summaryrefslogtreecommitdiffstatshomepage
path: root/src/osd/interface/inputseq.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/osd/interface/inputseq.cpp')
0 files changed, 0 insertions, 0 deletions
diffstat' width='100%'> -rw-r--r--src/devices/bus/a1bus/a1cffa.cpp68
-rw-r--r--src/devices/bus/a1bus/a1cffa.h39
-rw-r--r--src/devices/bus/a2bus/4play.cpp51
-rw-r--r--src/devices/bus/a2bus/4play.h27
-rw-r--r--src/devices/bus/a2bus/a2alfam2.cpp129
-rw-r--r--src/devices/bus/a2bus/a2alfam2.h55
-rw-r--r--src/devices/bus/a2bus/a2applicard.cpp94
-rw-r--r--src/devices/bus/a2bus/a2applicard.h47
-rw-r--r--src/devices/bus/a2bus/a2arcadebd.cpp45
-rw-r--r--src/devices/bus/a2bus/a2arcadebd.h36
-rw-r--r--src/devices/bus/a2bus/a2bus.cpp51
-rw-r--r--src/devices/bus/a2bus/a2bus.h56
-rw-r--r--src/devices/bus/a2bus/a2cffa.cpp126
-rw-r--r--src/devices/bus/a2bus/a2cffa.h67
-rw-r--r--src/devices/bus/a2bus/a2corvus.cpp6
-rw-r--r--src/devices/bus/a2bus/a2corvus.h14
-rw-r--r--src/devices/bus/a2bus/a2diskii.cpp174
-rw-r--r--src/devices/bus/a2bus/a2diskii.h84
-rw-r--r--src/devices/bus/a2bus/a2diskiing.cpp110
-rw-r--r--src/devices/bus/a2bus/a2diskiing.h74
-rw-r--r--src/devices/bus/a2bus/a2dx1.cpp53
-rw-r--r--src/devices/bus/a2bus/a2dx1.h32
-rw-r--r--src/devices/bus/a2bus/a2eauxslot.cpp63
-rw-r--r--src/devices/bus/a2bus/a2eauxslot.h41
-rw-r--r--src/devices/bus/a2bus/a2echoii.cpp55
-rw-r--r--src/devices/bus/a2bus/a2echoii.h41
-rw-r--r--src/devices/bus/a2bus/a2eext80col.cpp15
-rw-r--r--src/devices/bus/a2bus/a2eext80col.h23
-rw-r--r--src/devices/bus/a2bus/a2eramworks3.cpp57
-rw-r--r--src/devices/bus/a2bus/a2eramworks3.h42
-rw-r--r--src/devices/bus/a2bus/a2estd80col.cpp32
-rw-r--r--src/devices/bus/a2bus/a2estd80col.h17
-rw-r--r--src/devices/bus/a2bus/a2hsscsi.cpp97
-rw-r--r--src/devices/bus/a2bus/a2hsscsi.h19
-rw-r--r--src/devices/bus/a2bus/a2iwm.cpp141
-rw-r--r--src/devices/bus/a2bus/a2iwm.h73
-rw-r--r--src/devices/bus/a2bus/a2mcms.cpp48
-rw-r--r--src/devices/bus/a2bus/a2mcms.h25
-rw-r--r--src/devices/bus/a2bus/a2memexp.cpp75
-rw-r--r--src/devices/bus/a2bus/a2memexp.h53
-rw-r--r--src/devices/bus/a2bus/a2midi.cpp57
-rw-r--r--src/devices/bus/a2bus/a2midi.h37
-rw-r--r--src/devices/bus/a2bus/a2mockingboard.cpp509
-rw-r--r--src/devices/bus/a2bus/a2mockingboard.h93
-rw-r--r--src/devices/bus/a2bus/a2parprn.cpp325
-rw-r--r--src/devices/bus/a2bus/a2parprn.h64
-rw-r--r--src/devices/bus/a2bus/a2pic.cpp694
-rw-r--r--src/devices/bus/a2bus/a2pic.h108
-rw-r--r--src/devices/bus/a2bus/a2sam.cpp77
-rw-r--r--src/devices/bus/a2bus/a2sam.h31
-rw-r--r--src/devices/bus/a2bus/a2scsi.cpp26
-rw-r--r--src/devices/bus/a2bus/a2scsi.h16
-rw-r--r--src/devices/bus/a2bus/a2sd.cpp333
-rw-r--r--src/devices/bus/a2bus/a2sd.h20
-rw-r--r--src/devices/bus/a2bus/a2softcard.cpp4
-rw-r--r--src/devices/bus/a2bus/a2softcard.h12
-rw-r--r--src/devices/bus/a2bus/a2ssc.cpp350
-rw-r--r--src/devices/bus/a2bus/a2ssc.h43
-rw-r--r--src/devices/bus/a2bus/a2superdrive.cpp347
-rw-r--r--src/devices/bus/a2bus/a2superdrive.h22
-rw-r--r--src/devices/bus/a2bus/a2swyft.cpp55
-rw-r--r--src/devices/bus/a2bus/a2swyft.h35
-rw-r--r--src/devices/bus/a2bus/a2themill.cpp26
-rw-r--r--src/devices/bus/a2bus/a2themill.h15
-rw-r--r--src/devices/bus/a2bus/a2thunderclock.cpp65
-rw-r--r--src/devices/bus/a2bus/a2thunderclock.h38
-rw-r--r--src/devices/bus/a2bus/a2ultraterm.cpp99
-rw-r--r--src/devices/bus/a2bus/a2ultraterm.h61
-rw-r--r--src/devices/bus/a2bus/a2videoterm.cpp126
-rw-r--r--src/devices/bus/a2bus/a2videoterm.h99
-rw-r--r--src/devices/bus/a2bus/a2vulcan.cpp102
-rw-r--r--src/devices/bus/a2bus/a2vulcan.h78
-rw-r--r--src/devices/bus/a2bus/a2wico_trackball.cpp245
-rw-r--r--src/devices/bus/a2bus/a2wico_trackball.h20
-rw-r--r--src/devices/bus/a2bus/a2zipdrive.cpp92
-rw-r--r--src/devices/bus/a2bus/a2zipdrive.h60
-rw-r--r--src/devices/bus/a2bus/ace2x00.cpp160
-rw-r--r--src/devices/bus/a2bus/ace2x00.h78
-rw-r--r--src/devices/bus/a2bus/agat7langcard.h4
-rw-r--r--src/devices/bus/a2bus/agat7ports.cpp8
-rw-r--r--src/devices/bus/a2bus/agat7ports.h20
-rw-r--r--src/devices/bus/a2bus/agat7ram.h4
-rw-r--r--src/devices/bus/a2bus/agat840k_hle.cpp85
-rw-r--r--src/devices/bus/a2bus/agat840k_hle.h38
-rw-r--r--src/devices/bus/a2bus/agat_fdc.cpp56
-rw-r--r--src/devices/bus/a2bus/agat_fdc.h34
-rw-r--r--src/devices/bus/a2bus/booti.cpp215
-rw-r--r--src/devices/bus/a2bus/booti.h21
-rw-r--r--src/devices/bus/a2bus/byte8251.cpp149
-rw-r--r--src/devices/bus/a2bus/byte8251.h13
-rw-r--r--src/devices/bus/a2bus/cards.cpp330
-rw-r--r--src/devices/bus/a2bus/cards.h23
-rw-r--r--src/devices/bus/a2bus/ccs7710.cpp155
-rw-r--r--src/devices/bus/a2bus/ccs7710.h56
-rw-r--r--src/devices/bus/a2bus/cmsscsi.cpp245
-rw-r--r--src/devices/bus/a2bus/cmsscsi.h61
-rw-r--r--src/devices/bus/a2bus/computereyes2.cpp65
-rw-r--r--src/devices/bus/a2bus/computereyes2.h48
-rw-r--r--src/devices/bus/a2bus/corvfdc01.cpp16
-rw-r--r--src/devices/bus/a2bus/corvfdc01.h15
-rw-r--r--src/devices/bus/a2bus/corvfdc02.cpp17
-rw-r--r--src/devices/bus/a2bus/corvfdc02.h18
-rw-r--r--src/devices/bus/a2bus/excel9.cpp305
-rw-r--r--src/devices/bus/a2bus/excel9.h62
-rw-r--r--src/devices/bus/a2bus/ezcgi.cpp101
-rw-r--r--src/devices/bus/a2bus/ezcgi.h93
-rw-r--r--src/devices/bus/a2bus/grafex.cpp143
-rw-r--r--src/devices/bus/a2bus/grafex.h21
-rw-r--r--src/devices/bus/a2bus/grappler.cpp1252
-rw-r--r--src/devices/bus/a2bus/grappler.h63
-rw-r--r--src/devices/bus/a2bus/lancegs.cpp215
-rw-r--r--src/devices/bus/a2bus/lancegs.h19
-rw-r--r--src/devices/bus/a2bus/laser128.cpp40
-rw-r--r--src/devices/bus/a2bus/laser128.h26
-rw-r--r--src/devices/bus/a2bus/mouse.cpp156
-rw-r--r--src/devices/bus/a2bus/mouse.h64
-rw-r--r--src/devices/bus/a2bus/nippelclock.cpp13
-rw-r--r--src/devices/bus/a2bus/nippelclock.h14
-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.cpp193
-rw-r--r--src/devices/bus/a2bus/pc_xporter.h110
-rw-r--r--src/devices/bus/a2bus/prodosromdrive.cpp119
-rw-r--r--src/devices/bus/a2bus/prodosromdrive.h21
-rw-r--r--src/devices/bus/a2bus/q68.cpp247
-rw-r--r--src/devices/bus/a2bus/q68.h82
-rw-r--r--src/devices/bus/a2bus/ramcard128k.h4
-rw-r--r--src/devices/bus/a2bus/ramcard16k.h4
-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/sider.cpp296
-rw-r--r--src/devices/bus/a2bus/sider.h71
-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/softcard3.cpp226
-rw-r--r--src/devices/bus/a2bus/softcard3.h66
-rw-r--r--src/devices/bus/a2bus/ssbapple.cpp42
-rw-r--r--src/devices/bus/a2bus/ssbapple.h35
-rw-r--r--src/devices/bus/a2bus/ssprite.cpp46
-rw-r--r--src/devices/bus/a2bus/ssprite.h42
-rw-r--r--src/devices/bus/a2bus/suprterminal.cpp281
-rw-r--r--src/devices/bus/a2bus/suprterminal.h21
-rw-r--r--src/devices/bus/a2bus/timemasterho.cpp80
-rw-r--r--src/devices/bus/a2bus/timemasterho.h49
-rw-r--r--src/devices/bus/a2bus/titan3plus2.cpp334
-rw-r--r--src/devices/bus/a2bus/titan3plus2.h64
-rw-r--r--src/devices/bus/a2bus/transwarp.cpp157
-rw-r--r--src/devices/bus/a2bus/transwarp.h50
-rw-r--r--src/devices/bus/a2bus/uniprint.cpp250
-rw-r--r--src/devices/bus/a2bus/uniprint.h32
-rw-r--r--src/devices/bus/a2bus/uthernet.cpp67
-rw-r--r--src/devices/bus/a2bus/uthernet.h19
-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/brightpen.cpp140
-rw-r--r--src/devices/bus/a2gameio/brightpen.h18
-rw-r--r--src/devices/bus/a2gameio/computereyes.cpp79
-rw-r--r--src/devices/bus/a2gameio/computereyes.h39
-rw-r--r--src/devices/bus/a2gameio/gameio.cpp52
-rw-r--r--src/devices/bus/a2gameio/gameio.h70
-rw-r--r--src/devices/bus/a2gameio/gizmo.cpp106
-rw-r--r--src/devices/bus/a2gameio/gizmo.h20
-rw-r--r--src/devices/bus/a2gameio/joyport.cpp56
-rw-r--r--src/devices/bus/a2gameio/joyport.h28
-rw-r--r--src/devices/bus/a2gameio/joyport_paddles.cpp133
-rw-r--r--src/devices/bus/a2gameio/joyport_paddles.h19
-rw-r--r--src/devices/bus/a2gameio/joystick.cpp61
-rw-r--r--src/devices/bus/a2gameio/joystick.h32
-rw-r--r--src/devices/bus/a2gameio/paddles.cpp136
-rw-r--r--src/devices/bus/a2gameio/paddles.h19
-rw-r--r--src/devices/bus/a2gameio/wico_joystick.cpp128
-rw-r--r--src/devices/bus/a2gameio/wico_joystick.h20
-rw-r--r--src/devices/bus/a7800/a78_slot.cpp112
-rw-r--r--src/devices/bus/a7800/a78_slot.h90
-rw-r--r--src/devices/bus/a7800/cpuwiz.cpp8
-rw-r--r--src/devices/bus/a7800/cpuwiz.h16
-rw-r--r--src/devices/bus/a7800/hiscore.cpp24
-rw-r--r--src/devices/bus/a7800/hiscore.h16
-rw-r--r--src/devices/bus/a7800/rom.cpp87
-rw-r--r--src/devices/bus/a7800/rom.h78
-rw-r--r--src/devices/bus/a7800/xboard.cpp40
-rw-r--r--src/devices/bus/a7800/xboard.h32
-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.h60
-rw-r--r--src/devices/bus/a800/a800_slot.cpp561
-rw-r--r--src/devices/bus/a800/a800_slot.h200
-rw-r--r--src/devices/bus/a800/a8sio.cpp46
-rw-r--r--src/devices/bus/a800/a8sio.h39
-rw-r--r--src/devices/bus/a800/atari1050.cpp24
-rw-r--r--src/devices/bus/a800/atari1050.h27
-rw-r--r--src/devices/bus/a800/atari810.cpp22
-rw-r--r--src/devices/bus/a800/atari810.h27
-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.cpp42
-rw-r--r--src/devices/bus/a800/cassette.h11
-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.h87
-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.h207
-rw-r--r--src/devices/bus/a800/rtime8.cpp60
-rw-r--r--src/devices/bus/a800/rtime8.h32
-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.h53
-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/abc890.cpp20
-rw-r--r--src/devices/bus/abcbus/abc890.h16
-rw-r--r--src/devices/bus/abcbus/abcbus.cpp62
-rw-r--r--src/devices/bus/abcbus/abcbus.h134
-rw-r--r--src/devices/bus/abcbus/cadmouse.h12
-rw-r--r--src/devices/bus/abcbus/db4106.cpp (renamed from src/devices/bus/abcbus/db411223.cpp)64
-rw-r--r--src/devices/bus/abcbus/db4106.h (renamed from src/devices/bus/abcbus/db411223.h)34
-rw-r--r--src/devices/bus/abcbus/db4107.cpp240
-rw-r--r--src/devices/bus/abcbus/db4107.h65
-rw-r--r--src/devices/bus/abcbus/db4112.cpp215
-rw-r--r--src/devices/bus/abcbus/db4112.h63
-rw-r--r--src/devices/bus/abcbus/fd2.cpp31
-rw-r--r--src/devices/bus/abcbus/fd2.h28
-rw-r--r--src/devices/bus/abcbus/hdc.cpp143
-rw-r--r--src/devices/bus/abcbus/hdc.h57
-rw-r--r--src/devices/bus/abcbus/lux10828.cpp72
-rw-r--r--src/devices/bus/abcbus/lux10828.h53
-rw-r--r--src/devices/bus/abcbus/lux21046.cpp116
-rw-r--r--src/devices/bus/abcbus/lux21046.h72
-rw-r--r--src/devices/bus/abcbus/lux21056.cpp87
-rw-r--r--src/devices/bus/abcbus/lux21056.h63
-rw-r--r--src/devices/bus/abcbus/lux4105.cpp463
-rw-r--r--src/devices/bus/abcbus/lux4105.h60
-rw-r--r--src/devices/bus/abcbus/memcard.cpp44
-rw-r--r--src/devices/bus/abcbus/memcard.h16
-rw-r--r--src/devices/bus/abcbus/ram.cpp3
-rw-r--r--src/devices/bus/abcbus/ram.h6
-rw-r--r--src/devices/bus/abcbus/sio.h10
-rw-r--r--src/devices/bus/abcbus/slutprov.cpp2
-rw-r--r--src/devices/bus/abcbus/slutprov.h6
-rw-r--r--src/devices/bus/abcbus/ssa.cpp48
-rw-r--r--src/devices/bus/abcbus/ssa.h35
-rw-r--r--src/devices/bus/abcbus/uni800.cpp2
-rw-r--r--src/devices/bus/abcbus/uni800.h6
-rw-r--r--src/devices/bus/abcbus/unidisk.cpp38
-rw-r--r--src/devices/bus/abcbus/unidisk.h22
-rw-r--r--src/devices/bus/abckb/abc77.cpp146
-rw-r--r--src/devices/bus/abckb/abc77.h47
-rw-r--r--src/devices/bus/abckb/abc800kb.cpp41
-rw-r--r--src/devices/bus/abckb/abc800kb.h27
-rw-r--r--src/devices/bus/abckb/abc99.cpp362
-rw-r--r--src/devices/bus/abckb/abc99.h66
-rw-r--r--src/devices/bus/abckb/abckb.cpp50
-rw-r--r--src/devices/bus/abckb/abckb.h19
-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.cpp26
-rw-r--r--src/devices/bus/acorn/atom/discpack.h17
-rw-r--r--src/devices/bus/acorn/atom/econet.cpp8
-rw-r--r--src/devices/bus/acorn/atom/econet.h8
-rw-r--r--src/devices/bus/acorn/atom/sid.cpp2
-rw-r--r--src/devices/bus/acorn/atom/sid.h4
-rw-r--r--src/devices/bus/acorn/bus.cpp33
-rw-r--r--src/devices/bus/acorn/bus.h17
-rw-r--r--src/devices/bus/acorn/cms/4080term.cpp17
-rw-r--r--src/devices/bus/acorn/cms/4080term.h8
-rw-r--r--src/devices/bus/acorn/cms/fdc.cpp44
-rw-r--r--src/devices/bus/acorn/cms/fdc.h14
-rw-r--r--src/devices/bus/acorn/cms/hires.cpp6
-rw-r--r--src/devices/bus/acorn/cms/hires.h8
-rw-r--r--src/devices/bus/acorn/cms/ieee.cpp89
-rw-r--r--src/devices/bus/acorn/cms/ieee.h48
-rw-r--r--src/devices/bus/acorn/system/32k.cpp7
-rw-r--r--src/devices/bus/acorn/system/32k.h7
-rw-r--r--src/devices/bus/acorn/system/8k.cpp20
-rw-r--r--src/devices/bus/acorn/system/8k.h13
-rw-r--r--src/devices/bus/acorn/system/cass.cpp2
-rw-r--r--src/devices/bus/acorn/system/cass.h6
-rw-r--r--src/devices/bus/acorn/system/econet.cpp8
-rw-r--r--src/devices/bus/acorn/system/econet.h10
-rw-r--r--src/devices/bus/acorn/system/fdc.cpp19
-rw-r--r--src/devices/bus/acorn/system/fdc.h16
-rw-r--r--src/devices/bus/acorn/system/vdu40.cpp10
-rw-r--r--src/devices/bus/acorn/system/vdu40.h8
-rw-r--r--src/devices/bus/acorn/system/vdu80.cpp12
-rw-r--r--src/devices/bus/acorn/system/vdu80.h10
-rw-r--r--src/devices/bus/acorn/system/vib.cpp157
-rw-r--r--src/devices/bus/acorn/system/vib.h17
-rw-r--r--src/devices/bus/adam/adamlink.h2
-rw-r--r--src/devices/bus/adam/exp.cpp38
-rw-r--r--src/devices/bus/adam/exp.h44
-rw-r--r--src/devices/bus/adam/ide.cpp10
-rw-r--r--src/devices/bus/adam/ide.h8
-rw-r--r--src/devices/bus/adam/ram.cpp3
-rw-r--r--src/devices/bus/adam/ram.h4
-rw-r--r--src/devices/bus/adamnet/adamnet.cpp22
-rw-r--r--src/devices/bus/adamnet/adamnet.h37
-rw-r--r--src/devices/bus/adamnet/ddp.cpp109
-rw-r--r--src/devices/bus/adamnet/ddp.h23
-rw-r--r--src/devices/bus/adamnet/fdc.cpp26
-rw-r--r--src/devices/bus/adamnet/fdc.h23
-rw-r--r--src/devices/bus/adamnet/kb.cpp37
-rw-r--r--src/devices/bus/adamnet/kb.h24
-rw-r--r--src/devices/bus/adamnet/printer.cpp26
-rw-r--r--src/devices/bus/adamnet/printer.h20
-rw-r--r--src/devices/bus/adamnet/spi.cpp35
-rw-r--r--src/devices/bus/adamnet/spi.h14
-rw-r--r--src/devices/bus/adb/a9m0330.cpp268
-rw-r--r--src/devices/bus/adb/a9m0330.h48
-rw-r--r--src/devices/bus/adb/a9m0331.cpp125
-rw-r--r--src/devices/bus/adb/a9m0331.h42
-rw-r--r--src/devices/bus/adb/adb.cpp68
-rw-r--r--src/devices/bus/adb/adb.h74
-rw-r--r--src/devices/bus/adb/adbhle.cpp45
-rw-r--r--src/devices/bus/adb/adbhle.h33
-rw-r--r--src/devices/bus/amiga/cpuslot/a570.cpp194
-rw-r--r--src/devices/bus/amiga/cpuslot/a570.h66
-rw-r--r--src/devices/bus/amiga/cpuslot/a590.cpp274
-rw-r--r--src/devices/bus/amiga/cpuslot/a590.h65
-rw-r--r--src/devices/bus/amiga/cpuslot/action_replay.cpp293
-rw-r--r--src/devices/bus/amiga/cpuslot/action_replay.h106
-rw-r--r--src/devices/bus/amiga/cpuslot/cards.cpp37
-rw-r--r--src/devices/bus/amiga/cpuslot/cards.h22
-rw-r--r--src/devices/bus/amiga/cpuslot/cpuslot.cpp60
-rw-r--r--src/devices/bus/amiga/cpuslot/cpuslot.h154
-rw-r--r--src/devices/bus/amiga/cpuslot/megamix500.cpp150
-rw-r--r--src/devices/bus/amiga/cpuslot/megamix500.h51
-rw-r--r--src/devices/bus/amiga/keyboard/a1200.cpp41
-rw-r--r--src/devices/bus/amiga/keyboard/a1200.h28
-rw-r--r--src/devices/bus/amiga/keyboard/a2000.cpp737
-rw-r--r--src/devices/bus/amiga/keyboard/a2000.h109
-rw-r--r--src/devices/bus/amiga/keyboard/keyboard.cpp17
-rw-r--r--src/devices/bus/amiga/keyboard/keyboard.h28
-rw-r--r--src/devices/bus/amiga/keyboard/matrix.cpp761
-rw-r--r--src/devices/bus/amiga/keyboard/matrix.h4
-rw-r--r--src/devices/bus/amiga/keyboard/mitsumi.cpp108
-rw-r--r--src/devices/bus/amiga/zorro/a2052.cpp90
-rw-r--r--src/devices/bus/amiga/zorro/a2052.h24
-rw-r--r--src/devices/bus/amiga/zorro/a2058.cpp81
-rw-r--r--src/devices/bus/amiga/zorro/a2058.h21
-rw-r--r--src/devices/bus/amiga/zorro/a2065.cpp152
-rw-r--r--src/devices/bus/amiga/zorro/a2065.h32
-rw-r--r--src/devices/bus/amiga/zorro/a2091.cpp252
-rw-r--r--src/devices/bus/amiga/zorro/a2091.h63
-rw-r--r--src/devices/bus/amiga/zorro/a2232.cpp162
-rw-r--r--src/devices/bus/amiga/zorro/a2232.h88
-rw-r--r--src/devices/bus/amiga/zorro/a590.cpp373
-rw-r--r--src/devices/bus/amiga/zorro/a590.h136
-rw-r--r--src/devices/bus/amiga/zorro/action_replay.cpp149
-rw-r--r--src/devices/bus/amiga/zorro/action_replay.h80
-rw-r--r--src/devices/bus/amiga/zorro/buddha.cpp341
-rw-r--r--src/devices/bus/amiga/zorro/buddha.h62
-rw-r--r--src/devices/bus/amiga/zorro/cards.cpp63
-rw-r--r--src/devices/bus/amiga/zorro/cards.h28
-rw-r--r--src/devices/bus/amiga/zorro/merlin.cpp191
-rw-r--r--src/devices/bus/amiga/zorro/merlin.h56
-rw-r--r--src/devices/bus/amiga/zorro/oktagon2008.cpp268
-rw-r--r--src/devices/bus/amiga/zorro/oktagon2008.h14
-rw-r--r--src/devices/bus/amiga/zorro/picasso2.cpp213
-rw-r--r--src/devices/bus/amiga/zorro/picasso2.h63
-rw-r--r--src/devices/bus/amiga/zorro/rainbow2.cpp222
-rw-r--r--src/devices/bus/amiga/zorro/rainbow2.h68
-rw-r--r--src/devices/bus/amiga/zorro/ripple.cpp234
-rw-r--r--src/devices/bus/amiga/zorro/ripple.h74
-rw-r--r--src/devices/bus/amiga/zorro/toccata.cpp318
-rw-r--r--src/devices/bus/amiga/zorro/toccata.h72
-rw-r--r--src/devices/bus/amiga/zorro/zorro.cpp351
-rw-r--r--src/devices/bus/amiga/zorro/zorro.h372
-rw-r--r--src/devices/bus/apf/rom.cpp8
-rw-r--r--src/devices/bus/apf/rom.h8
-rw-r--r--src/devices/bus/apf/slot.cpp63
-rw-r--r--src/devices/bus/apf/slot.h65
-rw-r--r--src/devices/bus/apricot/expansion/expansion.cpp31
-rw-r--r--src/devices/bus/apricot/expansion/expansion.h40
-rw-r--r--src/devices/bus/apricot/expansion/ram.h24
-rw-r--r--src/devices/bus/apricot/expansion/winchester.cpp18
-rw-r--r--src/devices/bus/apricot/expansion/winchester.h26
-rw-r--r--src/devices/bus/apricot/keyboard/hle.cpp4
-rw-r--r--src/devices/bus/apricot/keyboard/hle.h8
-rw-r--r--src/devices/bus/apricot/keyboard/keyboard.cpp23
-rw-r--r--src/devices/bus/apricot/keyboard/keyboard.h11
-rw-r--r--src/devices/bus/apricot/video/cards.cpp16
-rw-r--r--src/devices/bus/apricot/video/cards.h16
-rw-r--r--src/devices/bus/apricot/video/mono.cpp278
-rw-r--r--src/devices/bus/apricot/video/mono.h65
-rw-r--r--src/devices/bus/apricot/video/video.cpp111
-rw-r--r--src/devices/bus/apricot/video/video.h89
-rw-r--r--src/devices/bus/aquarius/c1541.cpp92
-rw-r--r--src/devices/bus/aquarius/c1541.h53
-rw-r--r--src/devices/bus/aquarius/mini.cpp221
-rw-r--r--src/devices/bus/aquarius/mini.h59
-rw-r--r--src/devices/bus/aquarius/qdisk.cpp164
-rw-r--r--src/devices/bus/aquarius/qdisk.h59
-rw-r--r--src/devices/bus/aquarius/ram.cpp110
-rw-r--r--src/devices/bus/aquarius/ram.h102
-rw-r--r--src/devices/bus/aquarius/rom.cpp51
-rw-r--r--src/devices/bus/aquarius/rom.h44
-rw-r--r--src/devices/bus/aquarius/slot.cpp219
-rw-r--r--src/devices/bus/aquarius/slot.h116
-rw-r--r--src/devices/bus/aquarius/supercart.cpp101
-rw-r--r--src/devices/bus/aquarius/supercart.h50
-rw-r--r--src/devices/bus/arcadia/rom.cpp4
-rw-r--r--src/devices/bus/arcadia/rom.h4
-rw-r--r--src/devices/bus/arcadia/slot.cpp41
-rw-r--r--src/devices/bus/arcadia/slot.h47
-rw-r--r--src/devices/bus/archimedes/econet/econet.cpp77
-rw-r--r--src/devices/bus/archimedes/econet/econet.h55
-rw-r--r--src/devices/bus/archimedes/econet/midi.cpp100
-rw-r--r--src/devices/bus/archimedes/econet/midi.h73
-rw-r--r--src/devices/bus/archimedes/econet/rtfmjoy.cpp94
-rw-r--r--src/devices/bus/archimedes/econet/rtfmjoy.h50
-rw-r--r--src/devices/bus/archimedes/econet/slot.cpp102
-rw-r--r--src/devices/bus/archimedes/econet/slot.h102
-rw-r--r--src/devices/bus/archimedes/podule/a448.cpp159
-rw-r--r--src/devices/bus/archimedes/podule/a448.h20
-rw-r--r--src/devices/bus/archimedes/podule/acejoy.cpp122
-rw-r--r--src/devices/bus/archimedes/podule/acejoy.h19
-rw-r--r--src/devices/bus/archimedes/podule/armadeus.cpp111
-rw-r--r--src/devices/bus/archimedes/podule/armadeus.h19
-rw-r--r--src/devices/bus/archimedes/podule/eaglem2.cpp156
-rw-r--r--src/devices/bus/archimedes/podule/eaglem2.h19
-rw-r--r--src/devices/bus/archimedes/podule/ether1.cpp184
-rw-r--r--src/devices/bus/archimedes/podule/ether1.h19
-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/etherd.cpp126
-rw-r--r--src/devices/bus/archimedes/podule/etherd.h19
-rw-r--r--src/devices/bus/archimedes/podule/etherr.cpp126
-rw-r--r--src/devices/bus/archimedes/podule/etherr.h19
-rw-r--r--src/devices/bus/archimedes/podule/faxpack.cpp135
-rw-r--r--src/devices/bus/archimedes/podule/faxpack.h20
-rw-r--r--src/devices/bus/archimedes/podule/greyhawk.cpp131
-rw-r--r--src/devices/bus/archimedes/podule/greyhawk.h19
-rw-r--r--src/devices/bus/archimedes/podule/hdisc.cpp118
-rw-r--r--src/devices/bus/archimedes/podule/hdisc.h19
-rw-r--r--src/devices/bus/archimedes/podule/hdisc_cw.cpp125
-rw-r--r--src/devices/bus/archimedes/podule/hdisc_cw.h19
-rw-r--r--src/devices/bus/archimedes/podule/hdisc_morley.cpp117
-rw-r--r--src/devices/bus/archimedes/podule/hdisc_morley.h19
-rw-r--r--src/devices/bus/archimedes/podule/hdisc_we.cpp124
-rw-r--r--src/devices/bus/archimedes/podule/hdisc_we.h19
-rw-r--r--src/devices/bus/archimedes/podule/ide_be.cpp130
-rw-r--r--src/devices/bus/archimedes/podule/ide_be.h19
-rw-r--r--src/devices/bus/archimedes/podule/ide_rdev.cpp122
-rw-r--r--src/devices/bus/archimedes/podule/ide_rdev.h19
-rw-r--r--src/devices/bus/archimedes/podule/io.cpp446
-rw-r--r--src/devices/bus/archimedes/podule/io.h23
-rw-r--r--src/devices/bus/archimedes/podule/io_hccs.cpp143
-rw-r--r--src/devices/bus/archimedes/podule/io_hccs.h19
-rw-r--r--src/devices/bus/archimedes/podule/io_morley.cpp338
-rw-r--r--src/devices/bus/archimedes/podule/io_morley.h21
-rw-r--r--src/devices/bus/archimedes/podule/io_we.cpp190
-rw-r--r--src/devices/bus/archimedes/podule/io_we.h19
-rw-r--r--src/devices/bus/archimedes/podule/lark.cpp255
-rw-r--r--src/devices/bus/archimedes/podule/lark.h19
-rw-r--r--src/devices/bus/archimedes/podule/laserd.cpp173
-rw-r--r--src/devices/bus/archimedes/podule/laserd.h19
-rw-r--r--src/devices/bus/archimedes/podule/midi_emr.cpp208
-rw-r--r--src/devices/bus/archimedes/podule/midi_emr.h20
-rw-r--r--src/devices/bus/archimedes/podule/midimax.cpp175
-rw-r--r--src/devices/bus/archimedes/podule/midimax.h20
-rw-r--r--src/devices/bus/archimedes/podule/nexus.cpp127
-rw-r--r--src/devices/bus/archimedes/podule/nexus.h19
-rw-r--r--src/devices/bus/archimedes/podule/rom.cpp231
-rw-r--r--src/devices/bus/archimedes/podule/rom.h20
-rw-r--r--src/devices/bus/archimedes/podule/rs423.cpp136
-rw-r--r--src/devices/bus/archimedes/podule/rs423.h19
-rw-r--r--src/devices/bus/archimedes/podule/scan256.cpp126
-rw-r--r--src/devices/bus/archimedes/podule/scan256.h19
-rw-r--r--src/devices/bus/archimedes/podule/scanlight.cpp261
-rw-r--r--src/devices/bus/archimedes/podule/scanlight.h22
-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.cpp173
-rw-r--r--src/devices/bus/archimedes/podule/scsi_vti.h19
-rw-r--r--src/devices/bus/archimedes/podule/serial.cpp156
-rw-r--r--src/devices/bus/archimedes/podule/serial.h19
-rw-r--r--src/devices/bus/archimedes/podule/slot.cpp387
-rw-r--r--src/devices/bus/archimedes/podule/slot.h158
-rw-r--r--src/devices/bus/archimedes/podule/spectra.cpp126
-rw-r--r--src/devices/bus/archimedes/podule/spectra.h19
-rw-r--r--src/devices/bus/archimedes/podule/tube.cpp87
-rw-r--r--src/devices/bus/archimedes/podule/tube.h19
-rw-r--r--src/devices/bus/astrocde/accessory.cpp35
-rw-r--r--src/devices/bus/astrocde/accessory.h11
-rw-r--r--src/devices/bus/astrocde/cassette.h6
-rw-r--r--src/devices/bus/astrocde/ctrl.cpp50
-rw-r--r--src/devices/bus/astrocde/ctrl.h65
-rw-r--r--src/devices/bus/astrocde/exp.cpp26
-rw-r--r--src/devices/bus/astrocde/exp.h36
-rw-r--r--src/devices/bus/astrocde/joy.h2
-rw-r--r--src/devices/bus/astrocde/lightpen.cpp23
-rw-r--r--src/devices/bus/astrocde/lightpen.h11
-rw-r--r--src/devices/bus/astrocde/ram.cpp40
-rw-r--r--src/devices/bus/astrocde/ram.h44
-rw-r--r--src/devices/bus/astrocde/rom.cpp8
-rw-r--r--src/devices/bus/astrocde/rom.h24
-rw-r--r--src/devices/bus/astrocde/slot.cpp43
-rw-r--r--src/devices/bus/astrocde/slot.h52
-rw-r--r--src/devices/bus/ata/atadev.cpp84
-rw-r--r--src/devices/bus/ata/atadev.h85
-rw-r--r--src/devices/bus/ata/ataintf.cpp (renamed from src/devices/machine/ataintf.cpp)112
-rw-r--r--src/devices/bus/ata/ataintf.h (renamed from src/devices/machine/ataintf.h)74
-rw-r--r--src/devices/bus/ata/atapicdr.cpp191
-rw-r--r--src/devices/bus/ata/atapicdr.h82
-rw-r--r--src/devices/bus/ata/atapihle.cpp (renamed from src/devices/machine/atapihle.cpp)36
-rw-r--r--src/devices/bus/ata/atapihle.h (renamed from src/devices/machine/atapihle.h)21
-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.cpp (renamed from src/devices/machine/cr589.cpp)100
-rw-r--r--src/devices/bus/ata/cr589.h (renamed from src/devices/machine/cr589.h)16
-rw-r--r--src/devices/bus/ata/gdrom.cpp901
-rw-r--r--src/devices/bus/ata/gdrom.h59
-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/px320a.cpp99
-rw-r--r--src/devices/bus/ata/px320a.h42
-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.cpp115
-rw-r--r--src/devices/bus/bbc/1mhzbus/1mhzbus.h16
-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/autoprom.h10
-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/beebopl.cpp95
-rw-r--r--src/devices/bus/bbc/1mhzbus/beebopl.h52
-rw-r--r--src/devices/bus/bbc/1mhzbus/beebsid.h4
-rw-r--r--src/devices/bus/bbc/1mhzbus/cc500.cpp178
-rw-r--r--src/devices/bus/bbc/1mhzbus/cc500.h59
-rw-r--r--src/devices/bus/bbc/1mhzbus/cfa3000opt.h4
-rw-r--r--src/devices/bus/bbc/1mhzbus/cisco.cpp267
-rw-r--r--src/devices/bus/bbc/1mhzbus/cisco.h60
-rw-r--r--src/devices/bus/bbc/1mhzbus/datacentre.cpp335
-rw-r--r--src/devices/bus/bbc/1mhzbus/datacentre.h68
-rw-r--r--src/devices/bus/bbc/1mhzbus/emrmidi.cpp6
-rw-r--r--src/devices/bus/bbc/1mhzbus/emrmidi.h8
-rw-r--r--src/devices/bus/bbc/1mhzbus/ide.cpp224
-rw-r--r--src/devices/bus/bbc/1mhzbus/ide.h86
-rw-r--r--src/devices/bus/bbc/1mhzbus/ieee488.cpp2
-rw-r--r--src/devices/bus/bbc/1mhzbus/ieee488.h16
-rw-r--r--src/devices/bus/bbc/1mhzbus/m2000.cpp2
-rw-r--r--src/devices/bus/bbc/1mhzbus/m2000.h6
-rw-r--r--src/devices/bus/bbc/1mhzbus/m5000.cpp430
-rw-r--r--src/devices/bus/bbc/1mhzbus/m5000.h158
-rw-r--r--src/devices/bus/bbc/1mhzbus/multiform.cpp195
-rw-r--r--src/devices/bus/bbc/1mhzbus/multiform.h69
-rw-r--r--src/devices/bus/bbc/1mhzbus/opus3.cpp70
-rw-r--r--src/devices/bus/bbc/1mhzbus/opus3.h21
-rw-r--r--src/devices/bus/bbc/1mhzbus/pdram.cpp87
-rw-r--r--src/devices/bus/bbc/1mhzbus/pdram.h49
-rw-r--r--src/devices/bus/bbc/1mhzbus/pms64k.cpp99
-rw-r--r--src/devices/bus/bbc/1mhzbus/pms64k.h50
-rw-r--r--src/devices/bus/bbc/1mhzbus/ramdisc.cpp208
-rw-r--r--src/devices/bus/bbc/1mhzbus/ramdisc.h59
-rw-r--r--src/devices/bus/bbc/1mhzbus/sasi.cpp175
-rw-r--r--src/devices/bus/bbc/1mhzbus/sasi.h71
-rw-r--r--src/devices/bus/bbc/1mhzbus/scsi.cpp201
-rw-r--r--src/devices/bus/bbc/1mhzbus/scsi.h81
-rw-r--r--src/devices/bus/bbc/1mhzbus/sprite.h6
-rw-r--r--src/devices/bus/bbc/analogue/analogue.cpp37
-rw-r--r--src/devices/bus/bbc/analogue/analogue.h18
-rw-r--r--src/devices/bus/bbc/analogue/bitstik.cpp8
-rw-r--r--src/devices/bus/bbc/analogue/bitstik.h8
-rw-r--r--src/devices/bus/bbc/analogue/cfa3000a.cpp8
-rw-r--r--src/devices/bus/bbc/analogue/cfa3000a.h6
-rw-r--r--src/devices/bus/bbc/analogue/joystick.cpp16
-rw-r--r--src/devices/bus/bbc/analogue/joystick.h8
-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/click.cpp113
-rw-r--r--src/devices/bus/bbc/cart/click.h47
-rw-r--r--src/devices/bus/bbc/cart/mastersd.cpp309
-rw-r--r--src/devices/bus/bbc/cart/mastersd.h20
-rw-r--r--src/devices/bus/bbc/cart/mega256.cpp97
-rw-r--r--src/devices/bus/bbc/cart/mega256.h47
-rw-r--r--src/devices/bus/bbc/cart/mr8000.cpp102
-rw-r--r--src/devices/bus/bbc/cart/mr8000.h46
-rw-r--r--src/devices/bus/bbc/cart/msc.cpp104
-rw-r--r--src/devices/bus/bbc/cart/msc.h48
-rw-r--r--src/devices/bus/bbc/cart/slot.cpp82
-rw-r--r--src/devices/bus/bbc/cart/slot.h161
-rw-r--r--src/devices/bus/bbc/exp/autocue.cpp102
-rw-r--r--src/devices/bus/bbc/exp/autocue.h51
-rw-r--r--src/devices/bus/bbc/exp/exp.cpp44
-rw-r--r--src/devices/bus/bbc/exp/exp.h16
-rw-r--r--src/devices/bus/bbc/exp/mertec.cpp6
-rw-r--r--src/devices/bus/bbc/exp/mertec.h6
-rw-r--r--src/devices/bus/bbc/fdc/acorn.cpp62
-rw-r--r--src/devices/bus/bbc/fdc/acorn.h31
-rw-r--r--src/devices/bus/bbc/fdc/ams.cpp39
-rw-r--r--src/devices/bus/bbc/fdc/ams.h19
-rw-r--r--src/devices/bus/bbc/fdc/cumana.cpp49
-rw-r--r--src/devices/bus/bbc/fdc/cumana.h23
-rw-r--r--src/devices/bus/bbc/fdc/cv1797.cpp82
-rw-r--r--src/devices/bus/bbc/fdc/cv1797.h22
-rw-r--r--src/devices/bus/bbc/fdc/fdc.cpp51
-rw-r--r--src/devices/bus/bbc/fdc/fdc.h18
-rw-r--r--src/devices/bus/bbc/fdc/kenda.cpp169
-rw-r--r--src/devices/bus/bbc/fdc/kenda.h52
-rw-r--r--src/devices/bus/bbc/fdc/microware.cpp156
-rw-r--r--src/devices/bus/bbc/fdc/opus.cpp77
-rw-r--r--src/devices/bus/bbc/fdc/opus.h32
-rw-r--r--src/devices/bus/bbc/fdc/solidisk.cpp363
-rw-r--r--src/devices/bus/bbc/fdc/solidisk.h110
-rw-r--r--src/devices/bus/bbc/fdc/udm.cpp170
-rw-r--r--src/devices/bus/bbc/fdc/udm.h (renamed from src/devices/bus/bbc/fdc/microware.h)38
-rw-r--r--src/devices/bus/bbc/fdc/watford.cpp48
-rw-r--r--src/devices/bus/bbc/fdc/watford.h22
-rw-r--r--src/devices/bus/bbc/internal/aries.cpp337
-rw-r--r--src/devices/bus/bbc/internal/aries.h117
-rw-r--r--src/devices/bus/bbc/internal/atpl.cpp250
-rw-r--r--src/devices/bus/bbc/internal/atpl.h85
-rw-r--r--src/devices/bus/bbc/internal/cumana68k.cpp324
-rw-r--r--src/devices/bus/bbc/internal/cumana68k.h86
-rw-r--r--src/devices/bus/bbc/internal/integrab.cpp341
-rw-r--r--src/devices/bus/bbc/internal/integrab.h67
-rw-r--r--src/devices/bus/bbc/internal/internal.cpp218
-rw-r--r--src/devices/bus/bbc/internal/internal.h117
-rw-r--r--src/devices/bus/bbc/internal/memex.cpp109
-rw-r--r--src/devices/bus/bbc/internal/memex.h50
-rw-r--r--src/devices/bus/bbc/internal/morleyaa.cpp307
-rw-r--r--src/devices/bus/bbc/internal/morleyaa.h55
-rw-r--r--src/devices/bus/bbc/internal/overlay.cpp224
-rw-r--r--src/devices/bus/bbc/internal/overlay.h57
-rw-r--r--src/devices/bus/bbc/internal/peartree.cpp295
-rw-r--r--src/devices/bus/bbc/internal/peartree.h116
-rw-r--r--src/devices/bus/bbc/internal/ramamp.cpp155
-rw-r--r--src/devices/bus/bbc/internal/ramamp.h55
-rw-r--r--src/devices/bus/bbc/internal/raven20.cpp112
-rw-r--r--src/devices/bus/bbc/internal/raven20.h52
-rw-r--r--src/devices/bus/bbc/internal/romex.cpp134
-rw-r--r--src/devices/bus/bbc/internal/romex.h53
-rw-r--r--src/devices/bus/bbc/internal/stl2m128.cpp248
-rw-r--r--src/devices/bus/bbc/internal/stl2m128.h59
-rw-r--r--src/devices/bus/bbc/internal/stl4m32.cpp303
-rw-r--r--src/devices/bus/bbc/internal/stl4m32.h67
-rw-r--r--src/devices/bus/bbc/internal/stlswr.cpp192
-rw-r--r--src/devices/bus/bbc/internal/stlswr.h108
-rw-r--r--src/devices/bus/bbc/internal/we32kram.cpp146
-rw-r--r--src/devices/bus/bbc/internal/we32kram.h55
-rw-r--r--src/devices/bus/bbc/internal/werom.cpp260
-rw-r--r--src/devices/bus/bbc/internal/werom.h90
-rw-r--r--src/devices/bus/bbc/internal/weromram.cpp133
-rw-r--r--src/devices/bus/bbc/internal/weromram.h58
-rw-r--r--src/devices/bus/bbc/joyport/joyport.cpp67
-rw-r--r--src/devices/bus/bbc/joyport/joyport.h18
-rw-r--r--src/devices/bus/bbc/joyport/joystick.cpp13
-rw-r--r--src/devices/bus/bbc/joyport/joystick.h7
-rw-r--r--src/devices/bus/bbc/joyport/mouse.cpp178
-rw-r--r--src/devices/bus/bbc/joyport/mouse.h62
-rw-r--r--src/devices/bus/bbc/modem/meup.cpp77
-rw-r--r--src/devices/bus/bbc/modem/meup.h46
-rw-r--r--src/devices/bus/bbc/modem/modem.cpp101
-rw-r--r--src/devices/bus/bbc/modem/modem.h105
-rw-r--r--src/devices/bus/bbc/modem/scsiaiv.cpp142
-rw-r--r--src/devices/bus/bbc/modem/scsiaiv.h71
-rw-r--r--src/devices/bus/bbc/rom/datagem.cpp96
-rw-r--r--src/devices/bus/bbc/rom/datagem.h48
-rw-r--r--src/devices/bus/bbc/rom/dfs.cpp14
-rw-r--r--src/devices/bus/bbc/rom/dfs.h13
-rw-r--r--src/devices/bus/bbc/rom/genie.cpp159
-rw-r--r--src/devices/bus/bbc/rom/genie.h37
-rw-r--r--src/devices/bus/bbc/rom/nvram.cpp58
-rw-r--r--src/devices/bus/bbc/rom/nvram.h42
-rw-r--r--src/devices/bus/bbc/rom/pal.cpp26
-rw-r--r--src/devices/bus/bbc/rom/pal.h16
-rw-r--r--src/devices/bus/bbc/rom/ram.cpp1
-rw-r--r--src/devices/bus/bbc/rom/ram.h2
-rw-r--r--src/devices/bus/bbc/rom/rom.cpp4
-rw-r--r--src/devices/bus/bbc/rom/rom.h2
-rw-r--r--src/devices/bus/bbc/rom/rtc.cpp30
-rw-r--r--src/devices/bus/bbc/rom/rtc.h12
-rw-r--r--src/devices/bus/bbc/rom/slot.cpp37
-rw-r--r--src/devices/bus/bbc/rom/slot.h43
-rw-r--r--src/devices/bus/bbc/tube/tube.cpp114
-rw-r--r--src/devices/bus/bbc/tube/tube.h30
-rw-r--r--src/devices/bus/bbc/tube/tube_32016.cpp178
-rw-r--r--src/devices/bus/bbc/tube/tube_32016.h58
-rw-r--r--src/devices/bus/bbc/tube/tube_6502.cpp208
-rw-r--r--src/devices/bus/bbc/tube/tube_6502.h83
-rw-r--r--src/devices/bus/bbc/tube/tube_80186.cpp64
-rw-r--r--src/devices/bus/bbc/tube/tube_80186.h41
-rw-r--r--src/devices/bus/bbc/tube/tube_80286.cpp38
-rw-r--r--src/devices/bus/bbc/tube/tube_80286.h26
-rw-r--r--src/devices/bus/bbc/tube/tube_a500.cpp233
-rw-r--r--src/devices/bus/bbc/tube/tube_a500.h14
-rw-r--r--src/devices/bus/bbc/tube/tube_arm.cpp76
-rw-r--r--src/devices/bus/bbc/tube/tube_arm.h25
-rw-r--r--src/devices/bus/bbc/tube/tube_arm7.cpp303
-rw-r--r--src/devices/bus/bbc/tube/tube_arm7.h93
-rw-r--r--src/devices/bus/bbc/tube/tube_casper.cpp40
-rw-r--r--src/devices/bus/bbc/tube/tube_casper.h21
-rw-r--r--src/devices/bus/bbc/tube/tube_cms6809.cpp125
-rw-r--r--src/devices/bus/bbc/tube/tube_cms6809.h54
-rw-r--r--src/devices/bus/bbc/tube/tube_matchbox.cpp1019
-rw-r--r--src/devices/bus/bbc/tube/tube_matchbox.h13
-rw-r--r--src/devices/bus/bbc/tube/tube_rc6502.cpp20
-rw-r--r--src/devices/bus/bbc/tube/tube_rc6502.h32
-rw-r--r--src/devices/bus/bbc/tube/tube_x25.cpp186
-rw-r--r--src/devices/bus/bbc/tube/tube_x25.h67
-rw-r--r--src/devices/bus/bbc/tube/tube_z80.cpp73
-rw-r--r--src/devices/bus/bbc/tube/tube_z80.h45
-rw-r--r--src/devices/bus/bbc/tube/tube_zep100.cpp81
-rw-r--r--src/devices/bus/bbc/tube/tube_zep100.h54
-rw-r--r--src/devices/bus/bbc/userport/beebspch.cpp4
-rw-r--r--src/devices/bus/bbc/userport/beebspch.h10
-rw-r--r--src/devices/bus/bbc/userport/cfa3000kbd.h6
-rw-r--r--src/devices/bus/bbc/userport/lcd.cpp117
-rw-r--r--src/devices/bus/bbc/userport/lcd.h56
-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.cpp185
-rw-r--r--src/devices/bus/bbc/userport/m4000.h13
-rw-r--r--src/devices/bus/bbc/userport/palext.cpp140
-rw-r--r--src/devices/bus/bbc/userport/palext.h78
-rw-r--r--src/devices/bus/bbc/userport/pointer.cpp63
-rw-r--r--src/devices/bus/bbc/userport/pointer.h19
-rw-r--r--src/devices/bus/bbc/userport/sdcard.cpp215
-rw-r--r--src/devices/bus/bbc/userport/sdcard.h21
-rw-r--r--src/devices/bus/bbc/userport/userport.cpp75
-rw-r--r--src/devices/bus/bbc/userport/userport.h19
-rw-r--r--src/devices/bus/bbc/userport/usersplit.cpp21
-rw-r--r--src/devices/bus/bbc/userport/usersplit.h16
-rw-r--r--src/devices/bus/bbc/userport/voicebox.cpp80
-rw-r--r--src/devices/bus/bbc/userport/voicebox.h49
-rw-r--r--src/devices/bus/bml3/bml3bus.cpp86
-rw-r--r--src/devices/bus/bml3/bml3bus.h86
-rw-r--r--src/devices/bus/bml3/bml3mp1805.cpp168
-rw-r--r--src/devices/bus/bml3/kanji.cpp (renamed from src/devices/bus/bml3/bml3kanji.cpp)24
-rw-r--r--src/devices/bus/bml3/kanji.h (renamed from src/devices/bus/bml3/bml3kanji.h)22
-rw-r--r--src/devices/bus/bml3/mp1802.cpp (renamed from src/devices/bus/bml3/bml3mp1802.cpp)89
-rw-r--r--src/devices/bus/bml3/mp1802.h (renamed from src/devices/bus/bml3/bml3mp1802.h)34
-rw-r--r--src/devices/bus/bml3/mp1805.cpp163
-rw-r--r--src/devices/bus/bml3/mp1805.h (renamed from src/devices/bus/bml3/bml3mp1805.h)34
-rw-r--r--src/devices/bus/bml3/rtc.cpp109
-rw-r--r--src/devices/bus/bml3/rtc.h54
-rw-r--r--src/devices/bus/bw2/exp.cpp9
-rw-r--r--src/devices/bus/bw2/exp.h15
-rw-r--r--src/devices/bus/bw2/ramcard.cpp28
-rw-r--r--src/devices/bus/bw2/ramcard.h8
-rw-r--r--src/devices/bus/c64/16kb.h11
-rw-r--r--src/devices/bus/c64/4dxh.cpp20
-rw-r--r--src/devices/bus/c64/4dxh.h11
-rw-r--r--src/devices/bus/c64/4ksa.cpp20
-rw-r--r--src/devices/bus/c64/4ksa.h11
-rw-r--r--src/devices/bus/c64/4tba.cpp20
-rw-r--r--src/devices/bus/c64/4tba.h11
-rw-r--r--src/devices/bus/c64/bn1541.cpp6
-rw-r--r--src/devices/bus/c64/bn1541.h24
-rw-r--r--src/devices/bus/c64/buscard.cpp78
-rw-r--r--src/devices/bus/c64/buscard.h28
-rw-r--r--src/devices/bus/c64/buscard2.cpp96
-rw-r--r--src/devices/bus/c64/buscard2.h26
-rw-r--r--src/devices/bus/c64/c128_comal80.h4
-rw-r--r--src/devices/bus/c64/c128_partner.cpp16
-rw-r--r--src/devices/bus/c64/c128_partner.h13
-rw-r--r--src/devices/bus/c64/comal80.h4
-rw-r--r--src/devices/bus/c64/cpm.cpp12
-rw-r--r--src/devices/bus/c64/cpm.h16
-rw-r--r--src/devices/bus/c64/currah_speech.cpp2
-rw-r--r--src/devices/bus/c64/currah_speech.h8
-rw-r--r--src/devices/bus/c64/dela_ep256.cpp21
-rw-r--r--src/devices/bus/c64/dela_ep256.h8
-rw-r--r--src/devices/bus/c64/dela_ep64.h6
-rw-r--r--src/devices/bus/c64/dela_ep7x8.h6
-rw-r--r--src/devices/bus/c64/dinamic.h4
-rw-r--r--src/devices/bus/c64/dqbb.cpp22
-rw-r--r--src/devices/bus/c64/dqbb.h17
-rw-r--r--src/devices/bus/c64/easy_calc_result.h4
-rw-r--r--src/devices/bus/c64/easyflash.cpp7
-rw-r--r--src/devices/bus/c64/easyflash.h10
-rw-r--r--src/devices/bus/c64/epyx_fast_load.cpp6
-rw-r--r--src/devices/bus/c64/epyx_fast_load.h7
-rw-r--r--src/devices/bus/c64/exos.h2
-rw-r--r--src/devices/bus/c64/exp.cpp113
-rw-r--r--src/devices/bus/c64/exp.h64
-rw-r--r--src/devices/bus/c64/fcc.cpp28
-rw-r--r--src/devices/bus/c64/fcc.h40
-rw-r--r--src/devices/bus/c64/final.cpp4
-rw-r--r--src/devices/bus/c64/final.h6
-rw-r--r--src/devices/bus/c64/final3.cpp4
-rw-r--r--src/devices/bus/c64/final3.h12
-rw-r--r--src/devices/bus/c64/fun_play.h4
-rw-r--r--src/devices/bus/c64/geocable.h25
-rw-r--r--src/devices/bus/c64/georam.cpp5
-rw-r--r--src/devices/bus/c64/georam.h12
-rw-r--r--src/devices/bus/c64/ide64.cpp14
-rw-r--r--src/devices/bus/c64/ide64.h12
-rw-r--r--src/devices/bus/c64/ieee488.cpp10
-rw-r--r--src/devices/bus/c64/ieee488.h14
-rw-r--r--src/devices/bus/c64/kingsoft.h4
-rw-r--r--src/devices/bus/c64/mach5.cpp2
-rw-r--r--src/devices/bus/c64/mach5.h6
-rw-r--r--src/devices/bus/c64/magic_desk.h4
-rw-r--r--src/devices/bus/c64/magic_formel.cpp15
-rw-r--r--src/devices/bus/c64/magic_formel.h16
-rw-r--r--src/devices/bus/c64/magic_voice.cpp20
-rw-r--r--src/devices/bus/c64/magic_voice.h28
-rw-r--r--src/devices/bus/c64/midi_maplin.cpp4
-rw-r--r--src/devices/bus/c64/midi_maplin.h13
-rw-r--r--src/devices/bus/c64/midi_namesoft.cpp4
-rw-r--r--src/devices/bus/c64/midi_namesoft.h13
-rw-r--r--src/devices/bus/c64/midi_passport.cpp6
-rw-r--r--src/devices/bus/c64/midi_passport.h15
-rw-r--r--src/devices/bus/c64/midi_sci.cpp4
-rw-r--r--src/devices/bus/c64/midi_sci.h13
-rw-r--r--src/devices/bus/c64/midi_siel.cpp4
-rw-r--r--src/devices/bus/c64/midi_siel.h13
-rw-r--r--src/devices/bus/c64/mikro_assembler.h2
-rw-r--r--src/devices/bus/c64/multiscreen.cpp4
-rw-r--r--src/devices/bus/c64/multiscreen.h10
-rw-r--r--src/devices/bus/c64/music64.h8
-rw-r--r--src/devices/bus/c64/neoram.cpp21
-rw-r--r--src/devices/bus/c64/neoram.h16
-rw-r--r--src/devices/bus/c64/ocean.cpp8
-rw-r--r--src/devices/bus/c64/ocean.h4
-rw-r--r--src/devices/bus/c64/pagefox.cpp6
-rw-r--r--src/devices/bus/c64/pagefox.h6
-rw-r--r--src/devices/bus/c64/partner.cpp8
-rw-r--r--src/devices/bus/c64/partner.h10
-rw-r--r--src/devices/bus/c64/prophet64.h4
-rw-r--r--src/devices/bus/c64/ps64.h6
-rw-r--r--src/devices/bus/c64/reu.cpp11
-rw-r--r--src/devices/bus/c64/reu.h8
-rw-r--r--src/devices/bus/c64/rex.h4
-rw-r--r--src/devices/bus/c64/rex_ep256.cpp21
-rw-r--r--src/devices/bus/c64/rex_ep256.h10
-rw-r--r--src/devices/bus/c64/ross.cpp2
-rw-r--r--src/devices/bus/c64/ross.h4
-rw-r--r--src/devices/bus/c64/sfx_sound_expander.cpp2
-rw-r--r--src/devices/bus/c64/sfx_sound_expander.h12
-rw-r--r--src/devices/bus/c64/silverrock.h4
-rw-r--r--src/devices/bus/c64/simons_basic.h4
-rw-r--r--src/devices/bus/c64/speakeasy.cpp2
-rw-r--r--src/devices/bus/c64/speakeasy.h4
-rw-r--r--src/devices/bus/c64/stardos.cpp2
-rw-r--r--src/devices/bus/c64/stardos.h10
-rw-r--r--src/devices/bus/c64/std.cpp12
-rw-r--r--src/devices/bus/c64/std.h2
-rw-r--r--src/devices/bus/c64/structured_basic.h4
-rw-r--r--src/devices/bus/c64/super_explode.cpp6
-rw-r--r--src/devices/bus/c64/super_explode.h7
-rw-r--r--src/devices/bus/c64/super_games.h4
-rw-r--r--src/devices/bus/c64/supercpu.cpp2
-rw-r--r--src/devices/bus/c64/supercpu.h12
-rw-r--r--src/devices/bus/c64/sw8k.h6
-rw-r--r--src/devices/bus/c64/swiftlink.cpp2
-rw-r--r--src/devices/bus/c64/swiftlink.h10
-rw-r--r--src/devices/bus/c64/system3.h8
-rw-r--r--src/devices/bus/c64/tdos.h8
-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.h10
-rw-r--r--src/devices/bus/c64/user.cpp2
-rw-r--r--src/devices/bus/c64/vizastar.h2
-rw-r--r--src/devices/bus/c64/vw64.cpp7
-rw-r--r--src/devices/bus/c64/vw64.h7
-rw-r--r--src/devices/bus/c64/warp_speed.cpp2
-rw-r--r--src/devices/bus/c64/warp_speed.h6
-rw-r--r--src/devices/bus/c64/westermann.cpp8
-rw-r--r--src/devices/bus/c64/westermann.h4
-rw-r--r--src/devices/bus/c64/xl80.cpp57
-rw-r--r--src/devices/bus/c64/xl80.h13
-rw-r--r--src/devices/bus/c64/z80videopak.cpp213
-rw-r--r--src/devices/bus/c64/z80videopak.h61
-rw-r--r--src/devices/bus/c64/zaxxon.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/24k.cpp3
-rw-r--r--src/devices/bus/cbm2/24k.h4
-rw-r--r--src/devices/bus/cbm2/exp.cpp63
-rw-r--r--src/devices/bus/cbm2/exp.h49
-rw-r--r--src/devices/bus/cbm2/hrg.h14
-rw-r--r--src/devices/bus/cbm2/std.cpp12
-rw-r--r--src/devices/bus/cbm2/std.h2
-rw-r--r--src/devices/bus/cbm2/user.cpp15
-rw-r--r--src/devices/bus/cbm2/user.h29
-rw-r--r--src/devices/bus/cbmiec/c1526.cpp2
-rw-r--r--src/devices/bus/cbmiec/c1526.h24
-rw-r--r--src/devices/bus/cbmiec/c1541.cpp371
-rw-r--r--src/devices/bus/cbmiec/c1541.h273
-rw-r--r--src/devices/bus/cbmiec/c1571.cpp64
-rw-r--r--src/devices/bus/cbmiec/c1571.h72
-rw-r--r--src/devices/bus/cbmiec/c1581.cpp28
-rw-r--r--src/devices/bus/cbmiec/c1581.h30
-rw-r--r--src/devices/bus/cbmiec/c64_nl10.cpp24
-rw-r--r--src/devices/bus/cbmiec/c64_nl10.h12
-rw-r--r--src/devices/bus/cbmiec/cbmiec.cpp53
-rw-r--r--src/devices/bus/cbmiec/cbmiec.h51
-rw-r--r--src/devices/bus/cbmiec/cmdhd.cpp6
-rw-r--r--src/devices/bus/cbmiec/cmdhd.h20
-rw-r--r--src/devices/bus/cbmiec/diag264_lb_iec.h2
-rw-r--r--src/devices/bus/cbmiec/fd2000.cpp22
-rw-r--r--src/devices/bus/cbmiec/fd2000.h39
-rw-r--r--src/devices/bus/cbmiec/interpod.cpp44
-rw-r--r--src/devices/bus/cbmiec/interpod.h22
-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/serialbox.cpp28
-rw-r--r--src/devices/bus/cbmiec/serialbox.h32
-rw-r--r--src/devices/bus/cbmiec/vic1515.h14
-rw-r--r--src/devices/bus/cbmiec/vic1520.cpp129
-rw-r--r--src/devices/bus/cbmiec/vic1520.h24
-rw-r--r--src/devices/bus/cbus/amd98.cpp (renamed from src/devices/bus/cbus/pc9801_amd98.cpp)122
-rw-r--r--src/devices/bus/cbus/amd98.h (renamed from src/devices/bus/cbus/pc9801_amd98.h)40
-rw-r--r--src/devices/bus/cbus/mif201.cpp70
-rw-r--r--src/devices/bus/cbus/mif201.h46
-rw-r--r--src/devices/bus/cbus/mpu_pc98.cpp5
-rw-r--r--src/devices/bus/cbus/mpu_pc98.h18
-rw-r--r--src/devices/bus/cbus/pc9801_118.cpp186
-rw-r--r--src/devices/bus/cbus/pc9801_118.h31
-rw-r--r--src/devices/bus/cbus/pc9801_26.cpp205
-rw-r--r--src/devices/bus/cbus/pc9801_26.h33
-rw-r--r--src/devices/bus/cbus/pc9801_55.cpp253
-rw-r--r--src/devices/bus/cbus/pc9801_55.h80
-rw-r--r--src/devices/bus/cbus/pc9801_86.cpp670
-rw-r--r--src/devices/bus/cbus/pc9801_86.h109
-rw-r--r--src/devices/bus/cbus/pc9801_cbus.cpp82
-rw-r--r--src/devices/bus/cbus/pc9801_cbus.h21
-rw-r--r--src/devices/bus/cbus/pc9801_snd.cpp50
-rw-r--r--src/devices/bus/cbus/pc9801_snd.h31
-rw-r--r--src/devices/bus/cbus/sb16_ct2720.cpp121
-rw-r--r--src/devices/bus/cbus/sb16_ct2720.h52
-rw-r--r--src/devices/bus/centronics/adaptator.cpp91
-rw-r--r--src/devices/bus/centronics/adaptator.h44
-rw-r--r--src/devices/bus/centronics/chessmec.cpp8
-rw-r--r--src/devices/bus/centronics/chessmec.h8
-rw-r--r--src/devices/bus/centronics/comxpl80.cpp8
-rw-r--r--src/devices/bus/centronics/comxpl80.h36
-rw-r--r--src/devices/bus/centronics/covox.cpp20
-rw-r--r--src/devices/bus/centronics/covox.h46
-rw-r--r--src/devices/bus/centronics/ctronics.cpp80
-rw-r--r--src/devices/bus/centronics/ctronics.h114
-rw-r--r--src/devices/bus/centronics/digiblst.cpp12
-rw-r--r--src/devices/bus/centronics/digiblst.h24
-rw-r--r--src/devices/bus/centronics/dsjoy.h18
-rw-r--r--src/devices/bus/centronics/epson_ex800.cpp32
-rw-r--r--src/devices/bus/centronics/epson_ex800.h46
-rw-r--r--src/devices/bus/centronics/epson_fx80.cpp320
-rw-r--r--src/devices/bus/centronics/epson_fx80.h20
-rw-r--r--src/devices/bus/centronics/epson_lx800.cpp126
-rw-r--r--src/devices/bus/centronics/epson_lx800.h44
-rw-r--r--src/devices/bus/centronics/epson_lx810l.cpp366
-rw-r--r--src/devices/bus/centronics/epson_lx810l.h141
-rw-r--r--src/devices/bus/centronics/epson_rx80.cpp171
-rw-r--r--src/devices/bus/centronics/epson_rx80.h19
-rw-r--r--src/devices/bus/centronics/nec_p72.cpp2
-rw-r--r--src/devices/bus/centronics/nec_p72.h8
-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.cpp105
-rw-r--r--src/devices/bus/centronics/printer.h38
-rw-r--r--src/devices/bus/centronics/samdac.cpp91
-rw-r--r--src/devices/bus/centronics/samdac.h57
-rw-r--r--src/devices/bus/centronics/smartboard.cpp37
-rw-r--r--src/devices/bus/centronics/smartboard.h40
-rw-r--r--src/devices/bus/centronics/spjoy.cpp94
-rw-r--r--src/devices/bus/centronics/spjoy.h50
-rw-r--r--src/devices/bus/cgenie/expansion/expansion.cpp16
-rw-r--r--src/devices/bus/cgenie/expansion/expansion.h13
-rw-r--r--src/devices/bus/cgenie/expansion/floppy.cpp41
-rw-r--r--src/devices/bus/cgenie/expansion/floppy.h20
-rw-r--r--src/devices/bus/cgenie/parallel/joystick.h6
-rw-r--r--src/devices/bus/cgenie/parallel/parallel.cpp22
-rw-r--r--src/devices/bus/cgenie/parallel/parallel.h15
-rw-r--r--src/devices/bus/cgenie/parallel/printer.cpp8
-rw-r--r--src/devices/bus/cgenie/parallel/printer.h14
-rw-r--r--src/devices/bus/chanf/rom.cpp10
-rw-r--r--src/devices/bus/chanf/rom.h46
-rw-r--r--src/devices/bus/chanf/slot.cpp55
-rw-r--r--src/devices/bus/chanf/slot.h62
-rw-r--r--src/devices/bus/coco/coco_dcmodem.cpp20
-rw-r--r--src/devices/bus/coco/coco_dwsock.cpp73
-rw-r--r--src/devices/bus/coco/coco_dwsock.h18
-rw-r--r--src/devices/bus/coco/coco_fdc.cpp652
-rw-r--r--src/devices/bus/coco/coco_fdc.h33
-rw-r--r--src/devices/bus/coco/coco_gmc.cpp12
-rw-r--r--src/devices/bus/coco/coco_ide.cpp249
-rw-r--r--src/devices/bus/coco/coco_ide.h62
-rw-r--r--src/devices/bus/coco/coco_max.cpp170
-rw-r--r--src/devices/bus/coco/coco_max.h14
-rw-r--r--src/devices/bus/coco/coco_midi.cpp116
-rw-r--r--src/devices/bus/coco/coco_midi.h14
-rw-r--r--src/devices/bus/coco/coco_multi.cpp228
-rw-r--r--src/devices/bus/coco/coco_multi.h7
-rw-r--r--src/devices/bus/coco/coco_orch90.cpp60
-rw-r--r--src/devices/bus/coco/coco_pak.cpp24
-rw-r--r--src/devices/bus/coco/coco_pak.h40
-rw-r--r--src/devices/bus/coco/coco_psg.cpp270
-rw-r--r--src/devices/bus/coco/coco_psg.h58
-rw-r--r--src/devices/bus/coco/coco_ram.cpp196
-rw-r--r--src/devices/bus/coco/coco_ram.h14
-rw-r--r--src/devices/bus/coco/coco_rs232.cpp20
-rw-r--r--src/devices/bus/coco/coco_ssc.cpp258
-rw-r--r--src/devices/bus/coco/coco_ssc.h2
-rw-r--r--src/devices/bus/coco/coco_stecomp.cpp85
-rw-r--r--src/devices/bus/coco/coco_stecomp.h13
-rw-r--r--src/devices/bus/coco/coco_sym12.cpp179
-rw-r--r--src/devices/bus/coco/coco_sym12.h13
-rw-r--r--src/devices/bus/coco/coco_t4426.cpp74
-rw-r--r--src/devices/bus/coco/coco_wpk.cpp200
-rw-r--r--src/devices/bus/coco/coco_wpk.h93
-rw-r--r--src/devices/bus/coco/coco_wpk2p.cpp56
-rw-r--r--src/devices/bus/coco/coco_wpk2p.h41
-rw-r--r--src/devices/bus/coco/cococart.cpp415
-rw-r--r--src/devices/bus/coco/cococart.h90
-rw-r--r--src/devices/bus/coco/dragon_amtor.cpp8
-rw-r--r--src/devices/bus/coco/dragon_amtor.h14
-rw-r--r--src/devices/bus/coco/dragon_claw.cpp212
-rw-r--r--src/devices/bus/coco/dragon_claw.h59
-rw-r--r--src/devices/bus/coco/dragon_fdc.cpp113
-rw-r--r--src/devices/bus/coco/dragon_jcbsnd.cpp10
-rw-r--r--src/devices/bus/coco/dragon_jcbsnd.h16
-rw-r--r--src/devices/bus/coco/dragon_jcbspch.cpp20
-rw-r--r--src/devices/bus/coco/dragon_jcbspch.h22
-rw-r--r--src/devices/bus/coco/dragon_msx2.cpp191
-rw-r--r--src/devices/bus/coco/dragon_msx2.h53
-rw-r--r--src/devices/bus/coco/dragon_serial.cpp138
-rw-r--r--src/devices/bus/coco/dragon_serial.h13
-rw-r--r--src/devices/bus/coco/dragon_sprites.cpp10
-rw-r--r--src/devices/bus/coco/dragon_sprites.h14
-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.cpp51
-rw-r--r--src/devices/bus/coleco/cartridge/exp.h43
-rw-r--r--src/devices/bus/coleco/cartridge/megacart.cpp97
-rw-r--r--src/devices/bus/coleco/cartridge/megacart.h49
-rw-r--r--src/devices/bus/coleco/cartridge/std.cpp6
-rw-r--r--src/devices/bus/coleco/cartridge/std.h11
-rw-r--r--src/devices/bus/coleco/cartridge/xin1.cpp5
-rw-r--r--src/devices/bus/coleco/cartridge/xin1.h13
-rw-r--r--src/devices/bus/coleco/controller/ctrl.cpp8
-rw-r--r--src/devices/bus/coleco/controller/ctrl.h17
-rw-r--r--src/devices/bus/coleco/controller/hand.cpp4
-rw-r--r--src/devices/bus/coleco/controller/hand.h13
-rw-r--r--src/devices/bus/coleco/controller/sac.cpp6
-rw-r--r--src/devices/bus/coleco/controller/sac.h13
-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.cpp9
-rw-r--r--src/devices/bus/compis/graphics.h10
-rw-r--r--src/devices/bus/compis/hrg.cpp24
-rw-r--r--src/devices/bus/compis/hrg.h12
-rw-r--r--src/devices/bus/compucolor/floppy.cpp16
-rw-r--r--src/devices/bus/compucolor/floppy.h15
-rw-r--r--src/devices/bus/comx35/clm.cpp15
-rw-r--r--src/devices/bus/comx35/clm.h10
-rw-r--r--src/devices/bus/comx35/eprom.h6
-rw-r--r--src/devices/bus/comx35/exp.cpp19
-rw-r--r--src/devices/bus/comx35/exp.h19
-rw-r--r--src/devices/bus/comx35/expbox.h16
-rw-r--r--src/devices/bus/comx35/fdc.cpp10
-rw-r--r--src/devices/bus/comx35/fdc.h18
-rw-r--r--src/devices/bus/comx35/joycard.h6
-rw-r--r--src/devices/bus/comx35/printer.h8
-rw-r--r--src/devices/bus/comx35/ram.cpp3
-rw-r--r--src/devices/bus/comx35/ram.h6
-rw-r--r--src/devices/bus/comx35/thermal.h6
-rw-r--r--src/devices/bus/cpc/amdrum.cpp8
-rw-r--r--src/devices/bus/cpc/amdrum.h8
-rw-r--r--src/devices/bus/cpc/brunword4.cpp6
-rw-r--r--src/devices/bus/cpc/brunword4.h8
-rw-r--r--src/devices/bus/cpc/cpc_pds.cpp8
-rw-r--r--src/devices/bus/cpc/cpc_pds.h10
-rw-r--r--src/devices/bus/cpc/cpc_rom.cpp32
-rw-r--r--src/devices/bus/cpc/cpc_rom.h29
-rw-r--r--src/devices/bus/cpc/cpc_rs232.cpp20
-rw-r--r--src/devices/bus/cpc/cpc_rs232.h26
-rw-r--r--src/devices/bus/cpc/cpc_ssa1.cpp46
-rw-r--r--src/devices/bus/cpc/cpc_ssa1.h48
-rw-r--r--src/devices/bus/cpc/cpcexp.cpp37
-rw-r--r--src/devices/bus/cpc/cpcexp.h26
-rw-r--r--src/devices/bus/cpc/ddi1.cpp20
-rw-r--r--src/devices/bus/cpc/ddi1.h18
-rw-r--r--src/devices/bus/cpc/doubler.cpp6
-rw-r--r--src/devices/bus/cpc/doubler.h9
-rw-r--r--src/devices/bus/cpc/hd20.cpp12
-rw-r--r--src/devices/bus/cpc/hd20.h14
-rw-r--r--src/devices/bus/cpc/magicsound.cpp49
-rw-r--r--src/devices/bus/cpc/magicsound.h38
-rw-r--r--src/devices/bus/cpc/mface2.h10
-rw-r--r--src/devices/bus/cpc/musicmachine.cpp24
-rw-r--r--src/devices/bus/cpc/musicmachine.h16
-rw-r--r--src/devices/bus/cpc/playcity.cpp33
-rw-r--r--src/devices/bus/cpc/playcity.h28
-rw-r--r--src/devices/bus/cpc/smartwatch.cpp31
-rw-r--r--src/devices/bus/cpc/smartwatch.h15
-rw-r--r--src/devices/bus/cpc/symbfac2.cpp60
-rw-r--r--src/devices/bus/cpc/symbfac2.h26
-rw-r--r--src/devices/bus/cpc/transtape.cpp14
-rw-r--r--src/devices/bus/cpc/transtape.h14
-rw-r--r--src/devices/bus/crvision/rom.cpp20
-rw-r--r--src/devices/bus/crvision/rom.h27
-rw-r--r--src/devices/bus/crvision/slot.cpp54
-rw-r--r--src/devices/bus/crvision/slot.h51
-rw-r--r--src/devices/bus/dmv/dmvbus.cpp19
-rw-r--r--src/devices/bus/dmv/dmvbus.h136
-rw-r--r--src/devices/bus/dmv/k012.cpp116
-rw-r--r--src/devices/bus/dmv/k012.h64
-rw-r--r--src/devices/bus/dmv/k210.cpp42
-rw-r--r--src/devices/bus/dmv/k210.h39
-rw-r--r--src/devices/bus/dmv/k220.cpp24
-rw-r--r--src/devices/bus/dmv/k220.h22
-rw-r--r--src/devices/bus/dmv/k230.cpp38
-rw-r--r--src/devices/bus/dmv/k230.h50
-rw-r--r--src/devices/bus/dmv/k233.cpp5
-rw-r--r--src/devices/bus/dmv/k233.h5
-rw-r--r--src/devices/bus/dmv/k801.cpp67
-rw-r--r--src/devices/bus/dmv/k801.h31
-rw-r--r--src/devices/bus/dmv/k803.cpp16
-rw-r--r--src/devices/bus/dmv/k803.h12
-rw-r--r--src/devices/bus/dmv/k806.cpp29
-rw-r--r--src/devices/bus/dmv/k806.h18
-rw-r--r--src/devices/bus/dmv/ram.cpp4
-rw-r--r--src/devices/bus/dmv/ram.h3
-rw-r--r--src/devices/bus/ecbbus/ecbbus.cpp28
-rw-r--r--src/devices/bus/ecbbus/ecbbus.h62
-rw-r--r--src/devices/bus/ecbbus/grip.cpp130
-rw-r--r--src/devices/bus/ecbbus/grip.h57
-rw-r--r--src/devices/bus/econet/e01.cpp138
-rw-r--r--src/devices/bus/econet/e01.h76
-rw-r--r--src/devices/bus/econet/econet.cpp74
-rw-r--r--src/devices/bus/econet/econet.h46
-rw-r--r--src/devices/bus/einstein/pipe/pipe.cpp21
-rw-r--r--src/devices/bus/einstein/pipe/pipe.h15
-rw-r--r--src/devices/bus/einstein/pipe/silicon_disc.cpp12
-rw-r--r--src/devices/bus/einstein/pipe/silicon_disc.h22
-rw-r--r--src/devices/bus/einstein/pipe/speculator.cpp26
-rw-r--r--src/devices/bus/einstein/pipe/speculator.h18
-rw-r--r--src/devices/bus/einstein/pipe/tk02.cpp30
-rw-r--r--src/devices/bus/einstein/pipe/tk02.h26
-rw-r--r--src/devices/bus/einstein/userport/mouse.h4
-rw-r--r--src/devices/bus/einstein/userport/speech.h6
-rw-r--r--src/devices/bus/einstein/userport/userport.cpp23
-rw-r--r--src/devices/bus/einstein/userport/userport.h15
-rw-r--r--src/devices/bus/ekara/rom.cpp84
-rw-r--r--src/devices/bus/ekara/rom.h55
-rw-r--r--src/devices/bus/ekara/slot.cpp72
-rw-r--r--src/devices/bus/ekara/slot.h80
-rw-r--r--src/devices/bus/electron/cart/abr.cpp3
-rw-r--r--src/devices/bus/electron/cart/abr.h2
-rw-r--r--src/devices/bus/electron/cart/ap34.cpp41
-rw-r--r--src/devices/bus/electron/cart/ap34.h10
-rw-r--r--src/devices/bus/electron/cart/ap5.cpp33
-rw-r--r--src/devices/bus/electron/cart/ap5.h12
-rw-r--r--src/devices/bus/electron/cart/aqr.h2
-rw-r--r--src/devices/bus/electron/cart/click.cpp11
-rw-r--r--src/devices/bus/electron/cart/click.h8
-rw-r--r--src/devices/bus/electron/cart/cumana.cpp62
-rw-r--r--src/devices/bus/electron/cart/cumana.h12
-rw-r--r--src/devices/bus/electron/cart/elksdp1.cpp228
-rw-r--r--src/devices/bus/electron/cart/elksdp1.h19
-rw-r--r--src/devices/bus/electron/cart/mgc.h4
-rw-r--r--src/devices/bus/electron/cart/peg400.cpp29
-rw-r--r--src/devices/bus/electron/cart/peg400.h9
-rw-r--r--src/devices/bus/electron/cart/romp144.cpp30
-rw-r--r--src/devices/bus/electron/cart/romp144.h10
-rw-r--r--src/devices/bus/electron/cart/rs423.cpp97
-rw-r--r--src/devices/bus/electron/cart/rs423.h47
-rw-r--r--src/devices/bus/electron/cart/slot.cpp55
-rw-r--r--src/devices/bus/electron/cart/slot.h53
-rw-r--r--src/devices/bus/electron/cart/sndexp.cpp58
-rw-r--r--src/devices/bus/electron/cart/sndexp.h8
-rw-r--r--src/devices/bus/electron/cart/sndexp3.cpp4
-rw-r--r--src/devices/bus/electron/cart/sndexp3.h4
-rw-r--r--src/devices/bus/electron/cart/sp64.h4
-rw-r--r--src/devices/bus/electron/cart/std.h2
-rw-r--r--src/devices/bus/electron/cart/stlefs.cpp43
-rw-r--r--src/devices/bus/electron/cart/stlefs.h11
-rw-r--r--src/devices/bus/electron/cart/tube.h4
-rw-r--r--src/devices/bus/electron/elksd128.cpp333
-rw-r--r--src/devices/bus/electron/elksd128.h19
-rw-r--r--src/devices/bus/electron/elksd64.cpp201
-rw-r--r--src/devices/bus/electron/elksd64.h19
-rw-r--r--src/devices/bus/electron/exp.cpp41
-rw-r--r--src/devices/bus/electron/exp.h11
-rw-r--r--src/devices/bus/electron/fbjoy.cpp66
-rw-r--r--src/devices/bus/electron/fbjoy.h39
-rw-r--r--src/devices/bus/electron/fbprint.cpp90
-rw-r--r--src/devices/bus/electron/fbprint.h50
-rw-r--r--src/devices/bus/electron/m2105.cpp204
-rw-r--r--src/devices/bus/electron/m2105.h26
-rw-r--r--src/devices/bus/electron/mc68k.cpp246
-rw-r--r--src/devices/bus/electron/mc68k.h62
-rw-r--r--src/devices/bus/electron/mode7.cpp235
-rw-r--r--src/devices/bus/electron/mode7.h66
-rw-r--r--src/devices/bus/electron/plus1.cpp365
-rw-r--r--src/devices/bus/electron/plus1.h73
-rw-r--r--src/devices/bus/electron/plus2.cpp46
-rw-r--r--src/devices/bus/electron/plus2.h10
-rw-r--r--src/devices/bus/electron/plus3.cpp25
-rw-r--r--src/devices/bus/electron/plus3.h9
-rw-r--r--src/devices/bus/electron/pwrjoy.cpp90
-rw-r--r--src/devices/bus/electron/pwrjoy.h41
-rw-r--r--src/devices/bus/electron/rombox.cpp34
-rw-r--r--src/devices/bus/electron/rombox.h12
-rw-r--r--src/devices/bus/electron/romboxp.cpp153
-rw-r--r--src/devices/bus/electron/romboxp.h20
-rw-r--r--src/devices/bus/electron/sidewndr.cpp185
-rw-r--r--src/devices/bus/electron/sidewndr.h14
-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.cpp57
-rw-r--r--src/devices/bus/ep64/exdos.h22
-rw-r--r--src/devices/bus/ep64/exp.cpp35
-rw-r--r--src/devices/bus/ep64/exp.h14
-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/multifont.cpp289
-rw-r--r--src/devices/bus/epson_qx/multifont.h87
-rw-r--r--src/devices/bus/epson_qx/option.cpp204
-rw-r--r--src/devices/bus/epson_qx/option.h280
-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.cpp22
-rw-r--r--src/devices/bus/epson_sio/epson_sio.h20
-rw-r--r--src/devices/bus/epson_sio/pf10.cpp42
-rw-r--r--src/devices/bus/epson_sio/pf10.h35
-rw-r--r--src/devices/bus/epson_sio/tf20.cpp64
-rw-r--r--src/devices/bus/epson_sio/tf20.h35
-rw-r--r--src/devices/bus/fmt_scsi/fmt121.cpp150
-rw-r--r--src/devices/bus/fmt_scsi/fmt121.h50
-rw-r--r--src/devices/bus/fmt_scsi/fmt_scsi.cpp156
-rw-r--r--src/devices/bus/fmt_scsi/fmt_scsi.h98
-rw-r--r--src/devices/bus/fp1000/fp1000_exp.cpp114
-rw-r--r--src/devices/bus/fp1000/fp1000_exp.h101
-rw-r--r--src/devices/bus/fp1000/fp1020fd.cpp94
-rw-r--r--src/devices/bus/fp1000/fp1020fd.h42
-rw-r--r--src/devices/bus/fp1000/fp1030_rampack.cpp50
-rw-r--r--src/devices/bus/fp1000/fp1030_rampack.h34
-rw-r--r--src/devices/bus/fp1000/fp1060io.cpp95
-rw-r--r--src/devices/bus/fp1000/fp1060io.h38
-rw-r--r--src/devices/bus/fp1000/fp1060io_exp.cpp98
-rw-r--r--src/devices/bus/fp1000/fp1060io_exp.h86
-rw-r--r--src/devices/bus/gamate/gamate_protection.cpp4
-rw-r--r--src/devices/bus/gamate/gamate_protection.h15
-rw-r--r--src/devices/bus/gamate/rom.cpp20
-rw-r--r--src/devices/bus/gamate/rom.h26
-rw-r--r--src/devices/bus/gamate/slot.cpp59
-rw-r--r--src/devices/bus/gamate/slot.h52
-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.cpp834
-rw-r--r--src/devices/bus/gameboy/gb_slot.h215
-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.cpp2488
-rw-r--r--src/devices/bus/gameboy/mbc.h453
-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.cpp1312
-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.h110
-rw-r--r--src/devices/bus/gamegear/smsctrladp.h54
-rw-r--r--src/devices/bus/gba/gba_slot.cpp87
-rw-r--r--src/devices/bus/gba/gba_slot.h68
-rw-r--r--src/devices/bus/gba/rom.cpp52
-rw-r--r--src/devices/bus/gba/rom.h81
-rw-r--r--src/devices/bus/generic/ram.h4
-rw-r--r--src/devices/bus/generic/slot.cpp172
-rw-r--r--src/devices/bus/generic/slot.h293
-rw-r--r--src/devices/bus/gio64/gio64.cpp71
-rw-r--r--src/devices/bus/gio64/gio64.h86
-rw-r--r--src/devices/bus/gio64/newport.cpp216
-rw-r--r--src/devices/bus/gio64/newport.h53
-rw-r--r--src/devices/bus/heathzenith/h19/tlb.cpp2170
-rw-r--r--src/devices/bus/heathzenith/h19/tlb.h480
-rw-r--r--src/devices/bus/heathzenith/h89/cdr_fdc_880h.cpp399
-rw-r--r--src/devices/bus/heathzenith/h89/cdr_fdc_880h.h18
-rw-r--r--src/devices/bus/heathzenith/h89/h17_fdc.cpp375
-rw-r--r--src/devices/bus/heathzenith/h89/h17_fdc.h26
-rw-r--r--src/devices/bus/heathzenith/h89/h89bus.cpp383
-rw-r--r--src/devices/bus/heathzenith/h89/h89bus.h400
-rw-r--r--src/devices/bus/heathzenith/h89/h_88_3.cpp389
-rw-r--r--src/devices/bus/heathzenith/h89/h_88_3.h13
-rwxr-xr-xsrc/devices/bus/heathzenith/h89/h_88_5.cpp214
-rw-r--r--src/devices/bus/heathzenith/h89/h_88_5.h12
-rw-r--r--src/devices/bus/heathzenith/h89/mms77316_fdc.cpp334
-rw-r--r--src/devices/bus/heathzenith/h89/mms77316_fdc.h73
-rw-r--r--src/devices/bus/heathzenith/h89/sigmasoft_parallel_port.cpp206
-rw-r--r--src/devices/bus/heathzenith/h89/sigmasoft_parallel_port.h73
-rw-r--r--src/devices/bus/heathzenith/h89/sigmasoft_sound.cpp214
-rw-r--r--src/devices/bus/heathzenith/h89/sigmasoft_sound.h18
-rw-r--r--src/devices/bus/heathzenith/h89/we_pullup.cpp51
-rw-r--r--src/devices/bus/heathzenith/h89/we_pullup.h18
-rw-r--r--src/devices/bus/heathzenith/h89/z37_fdc.cpp249
-rw-r--r--src/devices/bus/heathzenith/h89/z37_fdc.h71
-rw-r--r--src/devices/bus/heathzenith/h89/z_89_11.cpp324
-rw-r--r--src/devices/bus/heathzenith/h89/z_89_11.h19
-rw-r--r--src/devices/bus/heathzenith/intr_cntrl/intr_cntrl.cpp278
-rw-r--r--src/devices/bus/heathzenith/intr_cntrl/intr_cntrl.h168
-rw-r--r--src/devices/bus/hexbus/hexbus.cpp129
-rw-r--r--src/devices/bus/hexbus/hexbus.h69
-rw-r--r--src/devices/bus/hexbus/hx5102.cpp309
-rw-r--r--src/devices/bus/hexbus/hx5102.h80
-rw-r--r--src/devices/bus/hexbus/tp0370.cpp35
-rw-r--r--src/devices/bus/hexbus/tp0370.h14
-rw-r--r--src/devices/bus/hp80_io/82900.cpp174
-rw-r--r--src/devices/bus/hp80_io/82900.h67
-rw-r--r--src/devices/bus/hp80_io/82937.cpp30
-rw-r--r--src/devices/bus/hp80_io/82937.h34
-rw-r--r--src/devices/bus/hp80_io/82939.cpp227
-rw-r--r--src/devices/bus/hp80_io/82939.h60
-rw-r--r--src/devices/bus/hp80_io/hp80_io.cpp57
-rw-r--r--src/devices/bus/hp80_io/hp80_io.h49
-rw-r--r--src/devices/bus/hp80_optroms/hp80_optrom.cpp117
-rw-r--r--src/devices/bus/hp80_optroms/hp80_optrom.h86
-rw-r--r--src/devices/bus/hp9845_io/98032.cpp87
-rw-r--r--src/devices/bus/hp9845_io/98032.h74
-rw-r--r--src/devices/bus/hp9845_io/98034.cpp115
-rw-r--r--src/devices/bus/hp9845_io/98034.h50
-rw-r--r--src/devices/bus/hp9845_io/98035.cpp124
-rw-r--r--src/devices/bus/hp9845_io/98035.h60
-rw-r--r--src/devices/bus/hp9845_io/98036.cpp505
-rw-r--r--src/devices/bus/hp9845_io/98036.h96
-rw-r--r--src/devices/bus/hp9845_io/98046.cpp175
-rw-r--r--src/devices/bus/hp9845_io/98046.h61
-rw-r--r--src/devices/bus/hp9845_io/hp9845_io.cpp87
-rw-r--r--src/devices/bus/hp9845_io/hp9845_io.h58
-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.cpp495
-rw-r--r--src/devices/bus/hp9845_io/hp9885.h29
-rw-r--r--src/devices/bus/hp_dio/hp98265a.cpp85
-rw-r--r--src/devices/bus/hp_dio/hp98265a.h67
-rw-r--r--src/devices/bus/hp_dio/hp98543.cpp124
-rw-r--r--src/devices/bus/hp_dio/hp98543.h69
-rw-r--r--src/devices/bus/hp_dio/hp98544.cpp96
-rw-r--r--src/devices/bus/hp_dio/hp98544.h63
-rw-r--r--src/devices/bus/hp_dio/hp98550.cpp111
-rw-r--r--src/devices/bus/hp_dio/hp98550.h73
-rw-r--r--src/devices/bus/hp_dio/hp98603a.cpp42
-rw-r--r--src/devices/bus/hp_dio/hp98603a.h39
-rw-r--r--src/devices/bus/hp_dio/hp98603b.cpp43
-rw-r--r--src/devices/bus/hp_dio/hp98603b.h39
-rw-r--r--src/devices/bus/hp_dio/hp98620.cpp258
-rw-r--r--src/devices/bus/hp_dio/hp98620.h127
-rw-r--r--src/devices/bus/hp_dio/hp98624.cpp340
-rw-r--r--src/devices/bus/hp_dio/hp98624.h13
-rw-r--r--src/devices/bus/hp_dio/hp98628_9.cpp1152
-rwxr-xr-xsrc/devices/bus/hp_dio/hp98628_9.h21
-rw-r--r--src/devices/bus/hp_dio/hp98643.cpp125
-rw-r--r--src/devices/bus/hp_dio/hp98643.h86
-rw-r--r--src/devices/bus/hp_dio/hp98644.cpp67
-rw-r--r--src/devices/bus/hp_dio/hp98644.h57
-rw-r--r--src/devices/bus/hp_dio/hp_dio.cpp58
-rw-r--r--src/devices/bus/hp_dio/hp_dio.h117
-rw-r--r--src/devices/bus/hp_dio/human_interface.cpp72
-rw-r--r--src/devices/bus/hp_dio/human_interface.h51
-rw-r--r--src/devices/bus/hp_hil/hlebase.cpp14
-rw-r--r--src/devices/bus/hp_hil/hlebase.h15
-rw-r--r--src/devices/bus/hp_hil/hlekbd.cpp65
-rw-r--r--src/devices/bus/hp_hil/hlekbd.h31
-rw-r--r--src/devices/bus/hp_hil/hlemouse.cpp25
-rw-r--r--src/devices/bus/hp_hil/hlemouse.h14
-rw-r--r--src/devices/bus/hp_hil/hp_hil.cpp37
-rw-r--r--src/devices/bus/hp_hil/hp_hil.h27
-rw-r--r--src/devices/bus/hp_ipc_io/82919.cpp251
-rw-r--r--src/devices/bus/hp_ipc_io/82919.h73
-rw-r--r--src/devices/bus/hp_ipc_io/hp_ipc_io.cpp85
-rw-r--r--src/devices/bus/hp_ipc_io/hp_ipc_io.h82
-rw-r--r--src/devices/bus/hp_optroms/hp_optrom.cpp131
-rw-r--r--src/devices/bus/hp_optroms/hp_optrom.h73
-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.cpp36
-rw-r--r--src/devices/bus/ieee488/c2031.h32
-rw-r--r--src/devices/bus/ieee488/c2040.cpp76
-rw-r--r--src/devices/bus/ieee488/c2040.h50
-rw-r--r--src/devices/bus/ieee488/c2040fdc.cpp31
-rw-r--r--src/devices/bus/ieee488/c2040fdc.h35
-rw-r--r--src/devices/bus/ieee488/c8050.cpp97
-rw-r--r--src/devices/bus/ieee488/c8050.h66
-rw-r--r--src/devices/bus/ieee488/c8050fdc.cpp79
-rw-r--r--src/devices/bus/ieee488/c8050fdc.h35
-rw-r--r--src/devices/bus/ieee488/c8280.cpp79
-rw-r--r--src/devices/bus/ieee488/c8280.h45
-rw-r--r--src/devices/bus/ieee488/d9060.cpp44
-rw-r--r--src/devices/bus/ieee488/d9060.h40
-rw-r--r--src/devices/bus/ieee488/grid2102.cpp315
-rw-r--r--src/devices/bus/ieee488/grid2102.h118
-rw-r--r--src/devices/bus/ieee488/hardbox.cpp18
-rw-r--r--src/devices/bus/ieee488/hardbox.h26
-rw-r--r--src/devices/bus/ieee488/hp9122c.cpp54
-rw-r--r--src/devices/bus/ieee488/hp9122c.h50
-rw-r--r--src/devices/bus/ieee488/hp9133.cpp879
-rw-r--r--src/devices/bus/ieee488/hp9133.h18
-rw-r--r--src/devices/bus/ieee488/hp9895.cpp404
-rw-r--r--src/devices/bus/ieee488/hp9895.h91
-rw-r--r--src/devices/bus/ieee488/ieee488.cpp31
-rw-r--r--src/devices/bus/ieee488/ieee488.h47
-rw-r--r--src/devices/bus/ieee488/remote488.cpp95
-rw-r--r--src/devices/bus/ieee488/remote488.h22
-rw-r--r--src/devices/bus/ieee488/shark.h12
-rw-r--r--src/devices/bus/ieee488/softbox.cpp19
-rw-r--r--src/devices/bus/ieee488/softbox.h26
-rw-r--r--src/devices/bus/imi7000/imi5000h.cpp30
-rw-r--r--src/devices/bus/imi7000/imi5000h.h52
-rw-r--r--src/devices/bus/imi7000/imi7000.cpp13
-rw-r--r--src/devices/bus/imi7000/imi7000.h61
-rw-r--r--src/devices/bus/intellec4/insdatastor.cpp221
-rw-r--r--src/devices/bus/intellec4/insdatastor.h189
-rw-r--r--src/devices/bus/intellec4/intellec4.cpp70
-rw-r--r--src/devices/bus/intellec4/intellec4.h59
-rw-r--r--src/devices/bus/intellec4/prommemory.cpp132
-rw-r--r--src/devices/bus/intellec4/prommemory.h116
-rw-r--r--src/devices/bus/intellec4/tapereader.cpp73
-rw-r--r--src/devices/bus/intellec4/tapereader.h53
-rw-r--r--src/devices/bus/interpro/keyboard/hle.cpp24
-rw-r--r--src/devices/bus/interpro/keyboard/hle.h23
-rw-r--r--src/devices/bus/interpro/keyboard/keyboard.cpp9
-rw-r--r--src/devices/bus/interpro/keyboard/keyboard.h12
-rw-r--r--src/devices/bus/interpro/keyboard/lle.cpp29
-rw-r--r--src/devices/bus/interpro/keyboard/lle.h38
-rw-r--r--src/devices/bus/interpro/mouse/mouse.cpp31
-rw-r--r--src/devices/bus/interpro/mouse/mouse.h18
-rw-r--r--src/devices/bus/interpro/sr/edge.cpp80
-rw-r--r--src/devices/bus/interpro/sr/edge.h124
-rw-r--r--src/devices/bus/interpro/sr/gt.cpp64
-rw-r--r--src/devices/bus/interpro/sr/gt.h162
-rw-r--r--src/devices/bus/interpro/sr/sr.cpp9
-rw-r--r--src/devices/bus/interpro/sr/sr.h59
-rw-r--r--src/devices/bus/intv/ecs.cpp10
-rw-r--r--src/devices/bus/intv/ecs.h8
-rw-r--r--src/devices/bus/intv/slot.cpp63
-rw-r--r--src/devices/bus/intv/slot.h40
-rw-r--r--src/devices/bus/intv/voice.cpp4
-rw-r--r--src/devices/bus/intv/voice.h17
-rw-r--r--src/devices/bus/intv_ctrl/ctrl.cpp17
-rw-r--r--src/devices/bus/intv_ctrl/ctrl.h12
-rw-r--r--src/devices/bus/intv_ctrl/ecs_ctrl.cpp36
-rw-r--r--src/devices/bus/intv_ctrl/ecs_ctrl.h34
-rw-r--r--src/devices/bus/intv_ctrl/handctrl.h6
-rw-r--r--src/devices/bus/iq151/disc2.cpp8
-rw-r--r--src/devices/bus/iq151/disc2.h10
-rw-r--r--src/devices/bus/iq151/grafik.cpp8
-rw-r--r--src/devices/bus/iq151/grafik.h12
-rw-r--r--src/devices/bus/iq151/iq151.cpp48
-rw-r--r--src/devices/bus/iq151/iq151.h35
-rw-r--r--src/devices/bus/iq151/minigraf.cpp3
-rw-r--r--src/devices/bus/iq151/minigraf.h6
-rw-r--r--src/devices/bus/iq151/ms151a.cpp3
-rw-r--r--src/devices/bus/iq151/ms151a.h6
-rw-r--r--src/devices/bus/iq151/rom.h4
-rw-r--r--src/devices/bus/iq151/staper.cpp24
-rw-r--r--src/devices/bus/iq151/staper.h14
-rw-r--r--src/devices/bus/iq151/video32.cpp2
-rw-r--r--src/devices/bus/iq151/video32.h6
-rw-r--r--src/devices/bus/iq151/video64.cpp2
-rw-r--r--src/devices/bus/iq151/video64.h6
-rw-r--r--src/devices/bus/isa/3c503.cpp52
-rw-r--r--src/devices/bus/isa/3c503.h16
-rw-r--r--src/devices/bus/isa/3c505.cpp81
-rw-r--r--src/devices/bus/isa/3c505.h20
-rw-r--r--src/devices/bus/isa/3xtwin.cpp95
-rw-r--r--src/devices/bus/isa/3xtwin.h40
-rw-r--r--src/devices/bus/isa/acb2072.cpp118
-rw-r--r--src/devices/bus/isa/acb2072.h38
-rw-r--r--src/devices/bus/isa/adlib.cpp12
-rw-r--r--src/devices/bus/isa/adlib.h12
-rw-r--r--src/devices/bus/isa/aga.cpp898
-rw-r--r--src/devices/bus/isa/aga.h76
-rw-r--r--src/devices/bus/isa/aha1542b.cpp98
-rw-r--r--src/devices/bus/isa/aha1542b.h41
-rw-r--r--src/devices/bus/isa/aha1542c.cpp29
-rw-r--r--src/devices/bus/isa/aha1542c.h33
-rw-r--r--src/devices/bus/isa/aha174x.h12
-rw-r--r--src/devices/bus/isa/asc88.cpp22
-rw-r--r--src/devices/bus/isa/asc88.h18
-rw-r--r--src/devices/bus/isa/bblue2.cpp253
-rw-r--r--src/devices/bus/isa/bblue2.h68
-rw-r--r--src/devices/bus/isa/bt54x.cpp2
-rw-r--r--src/devices/bus/isa/bt54x.h16
-rw-r--r--src/devices/bus/isa/cga.cpp848
-rw-r--r--src/devices/bus/isa/cga.h95
-rw-r--r--src/devices/bus/isa/chessmdr.cpp8
-rw-r--r--src/devices/bus/isa/chessmdr.h12
-rw-r--r--src/devices/bus/isa/chessmsr.cpp23
-rw-r--r--src/devices/bus/isa/chessmsr.h16
-rw-r--r--src/devices/bus/isa/cl_sh260.h16
-rw-r--r--src/devices/bus/isa/com.cpp8
-rw-r--r--src/devices/bus/isa/com.h12
-rw-r--r--src/devices/bus/isa/dcb.h10
-rw-r--r--src/devices/bus/isa/dectalk.cpp54
-rw-r--r--src/devices/bus/isa/dectalk.h56
-rw-r--r--src/devices/bus/isa/ega.cpp390
-rw-r--r--src/devices/bus/isa/ega.h47
-rw-r--r--src/devices/bus/isa/eis_hgb107x.cpp603
-rw-r--r--src/devices/bus/isa/eis_hgb107x.h112
-rw-r--r--src/devices/bus/isa/eis_sad8852.cpp12
-rw-r--r--src/devices/bus/isa/eis_sad8852.h18
-rw-r--r--src/devices/bus/isa/eis_twib.cpp259
-rw-r--r--src/devices/bus/isa/eis_twib.h52
-rw-r--r--src/devices/bus/isa/ex1280.cpp216
-rw-r--r--src/devices/bus/isa/ex1280.h62
-rw-r--r--src/devices/bus/isa/fdc.cpp253
-rw-r--r--src/devices/bus/isa/fdc.h81
-rw-r--r--src/devices/bus/isa/finalchs.cpp8
-rw-r--r--src/devices/bus/isa/finalchs.h20
-rw-r--r--src/devices/bus/isa/gblaster.cpp31
-rw-r--r--src/devices/bus/isa/gblaster.h16
-rw-r--r--src/devices/bus/isa/gus.cpp292
-rw-r--r--src/devices/bus/isa/gus.h116
-rw-r--r--src/devices/bus/isa/hdc.cpp690
-rw-r--r--src/devices/bus/isa/hdc.h115
-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.cpp45
-rw-r--r--src/devices/bus/isa/ibm_mfc.h36
-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.cpp8
-rw-r--r--src/devices/bus/isa/ide.h18
-rw-r--r--src/devices/bus/isa/isa.cpp254
-rw-r--r--src/devices/bus/isa/isa.h113
-rw-r--r--src/devices/bus/isa/isa_cards.cpp112
-rw-r--r--src/devices/bus/isa/lbaenhancer.cpp4
-rw-r--r--src/devices/bus/isa/lbaenhancer.h16
-rw-r--r--src/devices/bus/isa/lpt.cpp11
-rw-r--r--src/devices/bus/isa/lpt.h10
-rw-r--r--src/devices/bus/isa/lrk330.cpp130
-rw-r--r--src/devices/bus/isa/lrk330.h38
-rw-r--r--src/devices/bus/isa/mach32.h229
-rw-r--r--src/devices/bus/isa/mc1502_fdc.cpp83
-rw-r--r--src/devices/bus/isa/mc1502_fdc.h22
-rw-r--r--src/devices/bus/isa/mc1502_rom.cpp2
-rw-r--r--src/devices/bus/isa/mc1502_rom.h6
-rw-r--r--src/devices/bus/isa/mcd.cpp126
-rw-r--r--src/devices/bus/isa/mcd.h25
-rw-r--r--src/devices/bus/isa/mda.cpp438
-rw-r--r--src/devices/bus/isa/mda.h47
-rw-r--r--src/devices/bus/isa/mpu401.cpp4
-rw-r--r--src/devices/bus/isa/mpu401.h8
-rw-r--r--src/devices/bus/isa/mufdc.cpp20
-rw-r--r--src/devices/bus/isa/mufdc.h22
-rw-r--r--src/devices/bus/isa/myb3k_com.cpp32
-rw-r--r--src/devices/bus/isa/myb3k_com.h28
-rw-r--r--src/devices/bus/isa/myb3k_fdc.cpp58
-rw-r--r--src/devices/bus/isa/myb3k_fdc.h40
-rw-r--r--src/devices/bus/isa/ne1000.cpp37
-rw-r--r--src/devices/bus/isa/ne1000.h16
-rw-r--r--src/devices/bus/isa/ne2000.cpp41
-rw-r--r--src/devices/bus/isa/ne2000.h16
-rw-r--r--src/devices/bus/isa/np600.cpp33
-rw-r--r--src/devices/bus/isa/np600.h17
-rw-r--r--src/devices/bus/isa/num9rev.cpp48
-rw-r--r--src/devices/bus/isa/num9rev.h32
-rw-r--r--src/devices/bus/isa/omti8621.cpp573
-rw-r--r--src/devices/bus/isa/omti8621.h91
-rw-r--r--src/devices/bus/isa/opus100pm.cpp351
-rw-r--r--src/devices/bus/isa/opus100pm.h71
-rw-r--r--src/devices/bus/isa/p1_fdc.cpp38
-rw-r--r--src/devices/bus/isa/p1_fdc.h20
-rw-r--r--src/devices/bus/isa/p1_hdc.cpp13
-rw-r--r--src/devices/bus/isa/p1_hdc.h12
-rw-r--r--src/devices/bus/isa/p1_rom.cpp2
-rw-r--r--src/devices/bus/isa/p1_rom.h6
-rw-r--r--src/devices/bus/isa/p1_sound.cpp49
-rw-r--r--src/devices/bus/isa/p1_sound.h33
-rw-r--r--src/devices/bus/isa/pc1640_iga.cpp8
-rw-r--r--src/devices/bus/isa/pc1640_iga.h4
-rw-r--r--src/devices/bus/isa/pcmidi.cpp262
-rw-r--r--src/devices/bus/isa/pcmidi.h47
-rw-r--r--src/devices/bus/isa/pds.cpp8
-rw-r--r--src/devices/bus/isa/pds.h12
-rw-r--r--src/devices/bus/isa/pgc.cpp57
-rw-r--r--src/devices/bus/isa/pgc.h32
-rw-r--r--src/devices/bus/isa/prose4k1.cpp92
-rw-r--r--src/devices/bus/isa/prose4k1.h13
-rw-r--r--src/devices/bus/isa/s3virge.cpp993
-rw-r--r--src/devices/bus/isa/s3virge.h140
-rw-r--r--src/devices/bus/isa/sb16.cpp205
-rw-r--r--src/devices/bus/isa/sb16.h106
-rw-r--r--src/devices/bus/isa/sblaster.cpp178
-rw-r--r--src/devices/bus/isa/sblaster.h69
-rw-r--r--src/devices/bus/isa/sc499.cpp166
-rw-r--r--src/devices/bus/isa/sc499.h50
-rw-r--r--src/devices/bus/isa/side116.cpp28
-rw-r--r--src/devices/bus/isa/side116.h18
-rw-r--r--src/devices/bus/isa/ssi2001.cpp5
-rw-r--r--src/devices/bus/isa/ssi2001.h6
-rw-r--r--src/devices/bus/isa/stereo_fx.cpp83
-rw-r--r--src/devices/bus/isa/stereo_fx.h52
-rw-r--r--src/devices/bus/isa/svga_cirrus.cpp253
-rw-r--r--src/devices/bus/isa/svga_cirrus.h31
-rw-r--r--src/devices/bus/isa/svga_paradise.cpp649
-rw-r--r--src/devices/bus/isa/svga_paradise.h256
-rw-r--r--src/devices/bus/isa/svga_s3.cpp344
-rw-r--r--src/devices/bus/isa/svga_s3.h91
-rw-r--r--src/devices/bus/isa/svga_trident.cpp119
-rw-r--r--src/devices/bus/isa/svga_trident.h45
-rw-r--r--src/devices/bus/isa/svga_tseng.cpp190
-rw-r--r--src/devices/bus/isa/svga_tseng.h72
-rw-r--r--src/devices/bus/isa/tekram_dc820.cpp2
-rw-r--r--src/devices/bus/isa/tekram_dc820.h28
-rw-r--r--src/devices/bus/isa/ultra12f.cpp79
-rw-r--r--src/devices/bus/isa/ultra12f.h21
-rw-r--r--src/devices/bus/isa/ultra14f.cpp4
-rw-r--r--src/devices/bus/isa/ultra14f.h8
-rw-r--r--src/devices/bus/isa/ultra24f.cpp2
-rw-r--r--src/devices/bus/isa/ultra24f.h8
-rw-r--r--src/devices/bus/isa/vga.cpp26
-rw-r--r--src/devices/bus/isa/vga.h14
-rw-r--r--src/devices/bus/isa/vga_ati.cpp407
-rw-r--r--src/devices/bus/isa/vga_ati.h56
-rw-r--r--src/devices/bus/isa/wd1002a_wx1.h6
-rw-r--r--src/devices/bus/isa/wd1007a.h6
-rw-r--r--src/devices/bus/isa/wdxt_gen.cpp26
-rw-r--r--src/devices/bus/isa/wdxt_gen.h40
-rw-r--r--src/devices/bus/isa/xsu_cards.cpp8
-rw-r--r--src/devices/bus/isa/xtide.cpp29
-rw-r--r--src/devices/bus/isa/xtide.h18
-rw-r--r--src/devices/bus/isbx/compis_fdc.cpp32
-rw-r--r--src/devices/bus/isbx/compis_fdc.h16
-rw-r--r--src/devices/bus/isbx/isbc_218a.cpp18
-rw-r--r--src/devices/bus/isbx/isbc_218a.h13
-rw-r--r--src/devices/bus/isbx/isbx.cpp17
-rw-r--r--src/devices/bus/isbx/isbx.h36
-rw-r--r--src/devices/bus/jakks_gamekey/rom.cpp24
-rw-r--r--src/devices/bus/jakks_gamekey/rom.h20
-rw-r--r--src/devices/bus/jakks_gamekey/slot.cpp54
-rw-r--r--src/devices/bus/jakks_gamekey/slot.h52
-rw-r--r--src/devices/bus/jvs/cyberlead.cpp486
-rw-r--r--src/devices/bus/jvs/cyberlead.h95
-rw-r--r--src/devices/bus/jvs/jvs.cpp449
-rw-r--r--src/devices/bus/jvs/jvs.h157
-rw-r--r--src/devices/bus/jvs/jvshle.cpp868
-rw-r--r--src/devices/bus/jvs/jvshle.h175
-rw-r--r--src/devices/bus/jvs/namcoio.cpp1611
-rw-r--r--src/devices/bus/jvs/namcoio.h73
-rw-r--r--src/devices/bus/kc/d002.cpp56
-rw-r--r--src/devices/bus/kc/d002.h16
-rw-r--r--src/devices/bus/kc/d004.cpp41
-rw-r--r--src/devices/bus/kc/d004.h41
-rw-r--r--src/devices/bus/kc/kc.cpp52
-rw-r--r--src/devices/bus/kc/kc.h42
-rw-r--r--src/devices/bus/kc/ram.cpp2
-rw-r--r--src/devices/bus/kc/ram.h12
-rw-r--r--src/devices/bus/kc/rom.cpp2
-rw-r--r--src/devices/bus/kc/rom.h10
-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.h208
-rw-r--r--src/devices/bus/lpci/cirrus.cpp18
-rw-r--r--src/devices/bus/lpci/cirrus.h12
-rw-r--r--src/devices/bus/lpci/i82371ab.cpp34
-rw-r--r--src/devices/bus/lpci/i82371ab.h4
-rw-r--r--src/devices/bus/lpci/i82371sb.cpp16
-rw-r--r--src/devices/bus/lpci/i82371sb.h12
-rw-r--r--src/devices/bus/lpci/i82439tx.cpp16
-rw-r--r--src/devices/bus/lpci/i82439tx.h8
-rw-r--r--src/devices/bus/lpci/mpc105.cpp18
-rw-r--r--src/devices/bus/lpci/mpc105.h6
-rw-r--r--src/devices/bus/lpci/northbridge.cpp10
-rw-r--r--src/devices/bus/lpci/northbridge.h10
-rw-r--r--src/devices/bus/lpci/pci.cpp53
-rw-r--r--src/devices/bus/lpci/pci.h28
-rw-r--r--src/devices/bus/lpci/southbridge.cpp153
-rw-r--r--src/devices/bus/lpci/southbridge.h118
-rw-r--r--src/devices/bus/lpci/vt82c505.h4
-rw-r--r--src/devices/bus/m5/rom.cpp6
-rw-r--r--src/devices/bus/m5/rom.h6
-rw-r--r--src/devices/bus/m5/slot.cpp48
-rw-r--r--src/devices/bus/m5/slot.h51
-rw-r--r--src/devices/bus/mackbd/keyboard.cpp974
-rw-r--r--src/devices/bus/mackbd/keyboard.h24
-rw-r--r--src/devices/bus/mackbd/mackbd.cpp176
-rw-r--r--src/devices/bus/mackbd/mackbd.h90
-rw-r--r--src/devices/bus/mackbd/pluskbd.cpp508
-rw-r--r--src/devices/bus/mackbd/pluskbd.h19
-rw-r--r--src/devices/bus/macpds/hyperdrive.cpp10
-rw-r--r--src/devices/bus/macpds/hyperdrive.h22
-rw-r--r--src/devices/bus/macpds/macpds.cpp65
-rw-r--r--src/devices/bus/macpds/macpds.h54
-rw-r--r--src/devices/bus/macpds/pds_tpdfpd.cpp51
-rw-r--r--src/devices/bus/macpds/pds_tpdfpd.h25
-rw-r--r--src/devices/bus/mc10/mc10_cart.cpp232
-rw-r--r--src/devices/bus/mc10/mc10_cart.h110
-rw-r--r--src/devices/bus/mc10/mcx128.cpp339
-rw-r--r--src/devices/bus/mc10/mcx128.h14
-rw-r--r--src/devices/bus/mc10/multiports_ext.cpp141
-rw-r--r--src/devices/bus/mc10/multiports_ext.h11
-rw-r--r--src/devices/bus/mc10/pak.cpp94
-rw-r--r--src/devices/bus/mc10/pak.h12
-rw-r--r--src/devices/bus/mc10/ram.cpp78
-rw-r--r--src/devices/bus/mc10/ram.h14
-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/eeprom.cpp113
-rw-r--r--src/devices/bus/megadrive/eeprom.h66
-rw-r--r--src/devices/bus/megadrive/ggenie.cpp6
-rw-r--r--src/devices/bus/megadrive/ggenie.h10
-rw-r--r--src/devices/bus/megadrive/jcart.cpp148
-rw-r--r--src/devices/bus/megadrive/jcart.h46
-rw-r--r--src/devices/bus/megadrive/md_carts.cpp5
-rw-r--r--src/devices/bus/megadrive/md_slot.cpp92
-rw-r--r--src/devices/bus/megadrive/md_slot.h115
-rw-r--r--src/devices/bus/megadrive/rom.cpp234
-rw-r--r--src/devices/bus/megadrive/rom.h223
-rw-r--r--src/devices/bus/megadrive/sk.cpp64
-rw-r--r--src/devices/bus/megadrive/sk.h12
-rw-r--r--src/devices/bus/megadrive/stm95.cpp6
-rw-r--r--src/devices/bus/megadrive/stm95.h10
-rw-r--r--src/devices/bus/megadrive/svp.cpp80
-rw-r--r--src/devices/bus/megadrive/svp.h54
-rw-r--r--src/devices/bus/midi/midi.cpp15
-rw-r--r--src/devices/bus/midi/midi.h15
-rw-r--r--src/devices/bus/midi/midiinport.h4
-rw-r--r--src/devices/bus/midi/midioutport.h4
-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/mpf1/epb.cpp131
-rw-r--r--src/devices/bus/mpf1/epb.h14
-rw-r--r--src/devices/bus/mpf1/iom.cpp145
-rw-r--r--src/devices/bus/mpf1/iom.h13
-rw-r--r--src/devices/bus/mpf1/prt.cpp138
-rw-r--r--src/devices/bus/mpf1/prt.h14
-rw-r--r--src/devices/bus/mpf1/sgb.cpp73
-rw-r--r--src/devices/bus/mpf1/sgb.h13
-rw-r--r--src/devices/bus/mpf1/slot.cpp126
-rw-r--r--src/devices/bus/mpf1/slot.h122
-rw-r--r--src/devices/bus/mpf1/ssb.cpp92
-rw-r--r--src/devices/bus/mpf1/ssb.h13
-rw-r--r--src/devices/bus/mpf1/tva.cpp85
-rw-r--r--src/devices/bus/mpf1/tva.h13
-rw-r--r--src/devices/bus/mpf1/vid.cpp158
-rw-r--r--src/devices/bus/mpf1/vid.h13
-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.cpp247
-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/franky.cpp86
-rw-r--r--src/devices/bus/msx/cart/franky.h13
-rw-r--r--src/devices/bus/msx/cart/fs_sr021.cpp191
-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/ide.cpp199
-rw-r--r--src/devices/bus/msx/cart/ide.h12
-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.cpp122
-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)51
-rw-r--r--src/devices/bus/msx/cart/msx_audio_kb.h (renamed from src/devices/bus/msx_cart/msx_audio_kb.h)22
-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.cpp544
-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.cpp94
-rw-r--r--src/devices/bus/msx/cart/slotoptions.h98
-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/video80.cpp212
-rw-r--r--src/devices/bus/msx/cart/video80.h19
-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.cpp211
-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)36
-rw-r--r--src/devices/bus/msx/slot/bunsetsu.h (renamed from src/devices/bus/msx_slot/bunsetsu.h)17
-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.cpp1435
-rw-r--r--src/devices/bus/msx/slot/disk.h499
-rw-r--r--src/devices/bus/msx/slot/fs4600.cpp136
-rw-r--r--src/devices/bus/msx/slot/fs4600.h (renamed from src/devices/bus/msx_slot/fs4600.h)35
-rw-r--r--src/devices/bus/msx/slot/fsa1fm.cpp223
-rw-r--r--src/devices/bus/msx/slot/fsa1fm.h83
-rw-r--r--src/devices/bus/msx/slot/msx_rs232.cpp527
-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.h35
-rw-r--r--src/devices/bus/msx/slot/panasonic08.cpp133
-rw-r--r--src/devices/bus/msx/slot/panasonic08.h (renamed from src/devices/bus/msx_slot/panasonic08.h)33
-rw-r--r--src/devices/bus/msx/slot/panasonic08r.cpp166
-rw-r--r--src/devices/bus/msx/slot/panasonic08r.h52
-rw-r--r--src/devices/bus/msx/slot/ram.cpp31
-rw-r--r--src/devices/bus/msx/slot/ram.h (renamed from src/devices/bus/msx_slot/ram.h)13
-rw-r--r--src/devices/bus/msx/slot/ram_mm.cpp59
-rw-r--r--src/devices/bus/msx/slot/ram_mm.h38
-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)13
-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.cpp89
-rw-r--r--src/devices/bus/msx/slot/sony08.h (renamed from src/devices/bus/msx_slot/sony08.h)30
-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.cpp128
-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.cpp611
-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/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/konami.cpp948
-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.cpp120
-rw-r--r--src/devices/bus/msx_cart/majutsushi.h43
-rw-r--r--src/devices/bus/msx_cart/moonsound.cpp125
-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.cpp204
-rw-r--r--src/devices/bus/msx_cart/yamaha.h67
-rw-r--r--src/devices/bus/msx_slot/cartridge.cpp370
-rw-r--r--src/devices/bus/msx_slot/cartridge.h82
-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/music.h37
-rw-r--r--src/devices/bus/msx_slot/panasonic08.cpp164
-rw-r--r--src/devices/bus/msx_slot/ram.cpp36
-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.cpp152
-rw-r--r--src/devices/bus/mtx/cfx.h51
-rw-r--r--src/devices/bus/mtx/exp.cpp96
-rw-r--r--src/devices/bus/mtx/exp.h56
-rw-r--r--src/devices/bus/mtx/magrom.cpp103
-rw-r--r--src/devices/bus/mtx/magrom.h50
-rw-r--r--src/devices/bus/mtx/rompak.cpp51
-rw-r--r--src/devices/bus/mtx/rompak.h40
-rw-r--r--src/devices/bus/mtx/sdx.cpp88
-rw-r--r--src/devices/bus/mtx/sdx.h45
-rw-r--r--src/devices/bus/multibus/cpuap.cpp214
-rw-r--r--src/devices/bus/multibus/cpuap.h58
-rw-r--r--src/devices/bus/multibus/isbc202.cpp1164
-rw-r--r--src/devices/bus/multibus/isbc202.h163
-rw-r--r--src/devices/bus/multibus/isbc8024.cpp156
-rw-r--r--src/devices/bus/multibus/isbc8024.h57
-rw-r--r--src/devices/bus/multibus/labtam_3232.cpp123
-rw-r--r--src/devices/bus/multibus/labtam_3232.h51
-rw-r--r--src/devices/bus/multibus/labtam_vducom.cpp455
-rw-r--r--src/devices/bus/multibus/labtam_vducom.h109
-rw-r--r--src/devices/bus/multibus/labtam_z80sbc.cpp603
-rw-r--r--src/devices/bus/multibus/labtam_z80sbc.h97
-rw-r--r--src/devices/bus/multibus/multibus.cpp112
-rw-r--r--src/devices/bus/multibus/multibus.h175
-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/multibus/serad.cpp204
-rw-r--r--src/devices/bus/multibus/serad.h49
-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/avc.cpp22
-rw-r--r--src/devices/bus/nasbus/avc.h12
-rw-r--r--src/devices/bus/nasbus/floppy.cpp22
-rw-r--r--src/devices/bus/nasbus/floppy.h14
-rw-r--r--src/devices/bus/nasbus/nasbus.cpp39
-rw-r--r--src/devices/bus/nasbus/nasbus.h56
-rw-r--r--src/devices/bus/neogeo/boot_cthd.h8
-rw-r--r--src/devices/bus/neogeo/boot_kof10th.cpp6
-rw-r--r--src/devices/bus/neogeo/boot_kof10th.h12
-rw-r--r--src/devices/bus/neogeo/boot_kof2k2.h6
-rw-r--r--src/devices/bus/neogeo/boot_kof2k3.h22
-rw-r--r--src/devices/bus/neogeo/boot_misc.cpp21
-rw-r--r--src/devices/bus/neogeo/boot_misc.h32
-rw-r--r--src/devices/bus/neogeo/boot_svc.h12
-rw-r--r--src/devices/bus/neogeo/carts.cpp1
-rw-r--r--src/devices/bus/neogeo/cmc.h14
-rw-r--r--src/devices/bus/neogeo/fatfury2.h10
-rw-r--r--src/devices/bus/neogeo/kof2k2.h6
-rw-r--r--src/devices/bus/neogeo/kof98.h10
-rw-r--r--src/devices/bus/neogeo/mslugx.h10
-rw-r--r--src/devices/bus/neogeo/pcm2.h6
-rw-r--r--src/devices/bus/neogeo/prot_cmc.cpp39
-rw-r--r--src/devices/bus/neogeo/prot_cmc.h5
-rw-r--r--src/devices/bus/neogeo/prot_cthd.cpp2
-rw-r--r--src/devices/bus/neogeo/prot_cthd.h6
-rw-r--r--src/devices/bus/neogeo/prot_fatfury2.cpp100
-rw-r--r--src/devices/bus/neogeo/prot_fatfury2.h14
-rw-r--r--src/devices/bus/neogeo/prot_kof2k2.h4
-rw-r--r--src/devices/bus/neogeo/prot_kof2k3bl.cpp8
-rw-r--r--src/devices/bus/neogeo/prot_kof2k3bl.h12
-rw-r--r--src/devices/bus/neogeo/prot_kof98.cpp4
-rw-r--r--src/devices/bus/neogeo/prot_kof98.h8
-rw-r--r--src/devices/bus/neogeo/prot_misc.cpp32
-rw-r--r--src/devices/bus/neogeo/prot_misc.h13
-rw-r--r--src/devices/bus/neogeo/prot_mslugx.cpp6
-rw-r--r--src/devices/bus/neogeo/prot_mslugx.h10
-rw-r--r--src/devices/bus/neogeo/prot_pcm2.h4
-rw-r--r--src/devices/bus/neogeo/prot_pvc.cpp4
-rw-r--r--src/devices/bus/neogeo/prot_pvc.h8
-rw-r--r--src/devices/bus/neogeo/prot_sma.cpp126
-rw-r--r--src/devices/bus/neogeo/prot_sma.h18
-rw-r--r--src/devices/bus/neogeo/pvc.h10
-rw-r--r--src/devices/bus/neogeo/rom.cpp4
-rw-r--r--src/devices/bus/neogeo/rom.h16
-rw-r--r--src/devices/bus/neogeo/sbp.cpp27
-rw-r--r--src/devices/bus/neogeo/sbp.h8
-rw-r--r--src/devices/bus/neogeo/slot.cpp60
-rw-r--r--src/devices/bus/neogeo/slot.h66
-rw-r--r--src/devices/bus/neogeo/sma.h10
-rw-r--r--src/devices/bus/neogeo_ctrl/ctrl.cpp30
-rw-r--r--src/devices/bus/neogeo_ctrl/ctrl.h29
-rw-r--r--src/devices/bus/neogeo_ctrl/dial.cpp35
-rw-r--r--src/devices/bus/neogeo_ctrl/dial.h9
-rw-r--r--src/devices/bus/neogeo_ctrl/irrmaze.cpp12
-rw-r--r--src/devices/bus/neogeo_ctrl/irrmaze.h8
-rw-r--r--src/devices/bus/neogeo_ctrl/joystick.cpp28
-rw-r--r--src/devices/bus/neogeo_ctrl/joystick.h12
-rw-r--r--src/devices/bus/neogeo_ctrl/kizuna4p.cpp4
-rw-r--r--src/devices/bus/neogeo_ctrl/kizuna4p.h8
-rw-r--r--src/devices/bus/neogeo_ctrl/mahjong.h6
-rw-r--r--src/devices/bus/nes/2a03pur.cpp33
-rw-r--r--src/devices/bus/nes/2a03pur.h12
-rw-r--r--src/devices/bus/nes/act53.cpp86
-rw-r--r--src/devices/bus/nes/act53.h13
-rw-r--r--src/devices/bus/nes/aladdin.cpp65
-rw-r--r--src/devices/bus/nes/aladdin.h55
-rw-r--r--src/devices/bus/nes/ave.cpp113
-rw-r--r--src/devices/bus/nes/ave.h30
-rw-r--r--src/devices/bus/nes/bandai.cpp87
-rw-r--r--src/devices/bus/nes/bandai.h18
-rw-r--r--src/devices/bus/nes/batlab.cpp256
-rw-r--r--src/devices/bus/nes/batlab.h60
-rw-r--r--src/devices/bus/nes/benshieng.cpp57
-rw-r--r--src/devices/bus/nes/benshieng.h11
-rw-r--r--src/devices/bus/nes/bootleg.cpp1695
-rw-r--r--src/devices/bus/nes/bootleg.h517
-rw-r--r--src/devices/bus/nes/camerica.cpp126
-rw-r--r--src/devices/bus/nes/camerica.h39
-rw-r--r--src/devices/bus/nes/cne.cpp101
-rw-r--r--src/devices/bus/nes/cne.h30
-rw-r--r--src/devices/bus/nes/cony.cpp405
-rw-r--r--src/devices/bus/nes/cony.h64
-rw-r--r--src/devices/bus/nes/datach.cpp96
-rw-r--r--src/devices/bus/nes/datach.h60
-rw-r--r--src/devices/bus/nes/discrete.cpp83
-rw-r--r--src/devices/bus/nes/discrete.h38
-rw-r--r--src/devices/bus/nes/disksys.cpp132
-rw-r--r--src/devices/bus/nes/disksys.h22
-rw-r--r--src/devices/bus/nes/event.cpp246
-rw-r--r--src/devices/bus/nes/event.h61
-rw-r--r--src/devices/bus/nes/ggenie.cpp240
-rw-r--r--src/devices/bus/nes/ggenie.h52
-rw-r--r--src/devices/bus/nes/henggedianzi.cpp177
-rw-r--r--src/devices/bus/nes/henggedianzi.h42
-rw-r--r--src/devices/bus/nes/hes.cpp39
-rw-r--r--src/devices/bus/nes/hes.h10
-rw-r--r--src/devices/bus/nes/hosenkan.cpp159
-rw-r--r--src/devices/bus/nes/hosenkan.h39
-rw-r--r--src/devices/bus/nes/irem.cpp172
-rw-r--r--src/devices/bus/nes/irem.h58
-rw-r--r--src/devices/bus/nes/jaleco.cpp422
-rw-r--r--src/devices/bus/nes/jaleco.h161
-rw-r--r--src/devices/bus/nes/jncota.cpp108
-rw-r--r--src/devices/bus/nes/jncota.h35
-rw-r--r--src/devices/bus/nes/jy.cpp39
-rw-r--r--src/devices/bus/nes/jy.h10
-rw-r--r--src/devices/bus/nes/kaiser.cpp818
-rw-r--r--src/devices/bus/nes/kaiser.h260
-rw-r--r--src/devices/bus/nes/karastudio.cpp39
-rw-r--r--src/devices/bus/nes/karastudio.h49
-rw-r--r--src/devices/bus/nes/konami.cpp563
-rw-r--r--src/devices/bus/nes/konami.h92
-rw-r--r--src/devices/bus/nes/legacy.cpp57
-rw-r--r--src/devices/bus/nes/legacy.h14
-rw-r--r--src/devices/bus/nes/mmc1.cpp244
-rw-r--r--src/devices/bus/nes/mmc1.h67
-rw-r--r--src/devices/bus/nes/mmc1_clones.cpp432
-rw-r--r--src/devices/bus/nes/mmc1_clones.h185
-rw-r--r--src/devices/bus/nes/mmc2.cpp27
-rw-r--r--src/devices/bus/nes/mmc2.h3
-rw-r--r--src/devices/bus/nes/mmc3.cpp185
-rw-r--r--src/devices/bus/nes/mmc3.h35
-rw-r--r--src/devices/bus/nes/mmc3_clones.cpp3241
-rw-r--r--src/devices/bus/nes/mmc3_clones.h795
-rw-r--r--src/devices/bus/nes/mmc5.cpp127
-rw-r--r--src/devices/bus/nes/mmc5.h42
-rw-r--r--src/devices/bus/nes/multigame.cpp3196
-rw-r--r--src/devices/bus/nes/multigame.h950
-rw-r--r--src/devices/bus/nes/namcot.cpp103
-rw-r--r--src/devices/bus/nes/namcot.h19
-rw-r--r--src/devices/bus/nes/nanjing.cpp16
-rw-r--r--src/devices/bus/nes/nanjing.h4
-rw-r--r--src/devices/bus/nes/nes_carts.cpp210
-rw-r--r--src/devices/bus/nes/nes_ines.hxx629
-rw-r--r--src/devices/bus/nes/nes_pcb.hxx268
-rw-r--r--src/devices/bus/nes/nes_slot.cpp328
-rw-r--r--src/devices/bus/nes/nes_slot.h325
-rw-r--r--src/devices/bus/nes/nes_unif.hxx112
-rw-r--r--src/devices/bus/nes/ntdec.cpp139
-rw-r--r--src/devices/bus/nes/ntdec.h33
-rw-r--r--src/devices/bus/nes/nxrom.cpp172
-rw-r--r--src/devices/bus/nes/nxrom.h52
-rw-r--r--src/devices/bus/nes/pirate.cpp849
-rw-r--r--src/devices/bus/nes/pirate.h198
-rw-r--r--src/devices/bus/nes/pt554.cpp39
-rw-r--r--src/devices/bus/nes/pt554.h7
-rw-r--r--src/devices/bus/nes/racermate.cpp12
-rw-r--r--src/devices/bus/nes/racermate.h2
-rw-r--r--src/devices/bus/nes/rcm.cpp226
-rw-r--r--src/devices/bus/nes/rcm.h59
-rw-r--r--src/devices/bus/nes/rexsoft.cpp166
-rw-r--r--src/devices/bus/nes/rexsoft.h16
-rw-r--r--src/devices/bus/nes/sachen.cpp238
-rw-r--r--src/devices/bus/nes/sachen.h91
-rw-r--r--src/devices/bus/nes/sealie.cpp241
-rw-r--r--src/devices/bus/nes/sealie.h85
-rw-r--r--src/devices/bus/nes/somari.cpp325
-rw-r--r--src/devices/bus/nes/somari.h50
-rw-r--r--src/devices/bus/nes/subor.cpp29
-rw-r--r--src/devices/bus/nes/subor.h6
-rw-r--r--src/devices/bus/nes/sunsoft.cpp229
-rw-r--r--src/devices/bus/nes/sunsoft.h45
-rw-r--r--src/devices/bus/nes/sunsoft_dcs.cpp74
-rw-r--r--src/devices/bus/nes/sunsoft_dcs.h55
-rw-r--r--src/devices/bus/nes/taito.cpp322
-rw-r--r--src/devices/bus/nes/taito.h61
-rw-r--r--src/devices/bus/nes/tengen.cpp194
-rw-r--r--src/devices/bus/nes/tengen.h58
-rw-r--r--src/devices/bus/nes/txc.cpp104
-rw-r--r--src/devices/bus/nes/txc.h20
-rw-r--r--src/devices/bus/nes/vrc_clones.cpp861
-rw-r--r--src/devices/bus/nes/vrc_clones.h309
-rw-r--r--src/devices/bus/nes/waixing.cpp387
-rw-r--r--src/devices/bus/nes/waixing.h109
-rw-r--r--src/devices/bus/nes/zemina.cpp79
-rw-r--r--src/devices/bus/nes/zemina.h9
-rw-r--r--src/devices/bus/nes_ctrl/4score.h20
-rw-r--r--src/devices/bus/nes_ctrl/arkpaddle.cpp99
-rw-r--r--src/devices/bus/nes_ctrl/arkpaddle.h33
-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/bcbattle.cpp63
-rw-r--r--src/devices/bus/nes_ctrl/bcbattle.h14
-rw-r--r--src/devices/bus/nes_ctrl/ctrl.cpp88
-rw-r--r--src/devices/bus/nes_ctrl/ctrl.h40
-rw-r--r--src/devices/bus/nes_ctrl/dorepiano.cpp158
-rw-r--r--src/devices/bus/nes_ctrl/dorepiano.h50
-rw-r--r--src/devices/bus/nes_ctrl/fckeybrd.cpp221
-rw-r--r--src/devices/bus/nes_ctrl/fckeybrd.h28
-rw-r--r--src/devices/bus/nes_ctrl/fcmat.cpp177
-rw-r--r--src/devices/bus/nes_ctrl/fcmat.h77
-rw-r--r--src/devices/bus/nes_ctrl/ftrainer.cpp155
-rw-r--r--src/devices/bus/nes_ctrl/ftrainer.h50
-rw-r--r--src/devices/bus/nes_ctrl/hori.cpp165
-rw-r--r--src/devices/bus/nes_ctrl/hori.h40
-rw-r--r--src/devices/bus/nes_ctrl/joypad.cpp209
-rw-r--r--src/devices/bus/nes_ctrl/joypad.h100
-rw-r--r--src/devices/bus/nes_ctrl/konamibag.cpp88
-rw-r--r--src/devices/bus/nes_ctrl/konamibag.h50
-rw-r--r--src/devices/bus/nes_ctrl/konamihs.cpp52
-rw-r--r--src/devices/bus/nes_ctrl/konamihs.h19
-rw-r--r--src/devices/bus/nes_ctrl/miracle.cpp11
-rw-r--r--src/devices/bus/nes_ctrl/miracle.h15
-rw-r--r--src/devices/bus/nes_ctrl/mjpanel.cpp71
-rw-r--r--src/devices/bus/nes_ctrl/mjpanel.h20
-rw-r--r--src/devices/bus/nes_ctrl/pachinko.cpp71
-rw-r--r--src/devices/bus/nes_ctrl/pachinko.h21
-rw-r--r--src/devices/bus/nes_ctrl/partytap.cpp51
-rw-r--r--src/devices/bus/nes_ctrl/partytap.h19
-rw-r--r--src/devices/bus/nes_ctrl/powerpad.cpp108
-rw-r--r--src/devices/bus/nes_ctrl/powerpad.h17
-rw-r--r--src/devices/bus/nes_ctrl/rob.cpp139
-rw-r--r--src/devices/bus/nes_ctrl/rob.h54
-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/snesadapter.cpp72
-rw-r--r--src/devices/bus/nes_ctrl/snesadapter.h46
-rw-r--r--src/devices/bus/nes_ctrl/suborkey.h11
-rw-r--r--src/devices/bus/nes_ctrl/turbofile.cpp140
-rw-r--r--src/devices/bus/nes_ctrl/turbofile.h59
-rw-r--r--src/devices/bus/nes_ctrl/zapper.cpp95
-rw-r--r--src/devices/bus/nes_ctrl/zapper.h27
-rw-r--r--src/devices/bus/nes_ctrl/zapper_sensor.cpp72
-rw-r--r--src/devices/bus/nes_ctrl/zapper_sensor.h53
-rw-r--r--src/devices/bus/newbrain/eim.cpp16
-rw-r--r--src/devices/bus/newbrain/eim.h22
-rw-r--r--src/devices/bus/newbrain/exp.cpp7
-rw-r--r--src/devices/bus/newbrain/exp.h15
-rw-r--r--src/devices/bus/newbrain/fdc.cpp24
-rw-r--r--src/devices/bus/newbrain/fdc.h19
-rw-r--r--src/devices/bus/nscsi/applecd.cpp92
-rw-r--r--src/devices/bus/nscsi/applecd.h30
-rw-r--r--src/devices/bus/nscsi/cd.cpp1258
-rw-r--r--src/devices/bus/nscsi/cd.h60
-rw-r--r--src/devices/bus/nscsi/cdd2000.cpp20
-rw-r--r--src/devices/bus/nscsi/cdd2000.h10
-rw-r--r--src/devices/bus/nscsi/cdrn820s.cpp8
-rw-r--r--src/devices/bus/nscsi/cdrn820s.h8
-rw-r--r--src/devices/bus/nscsi/cdu415.cpp67
-rw-r--r--src/devices/bus/nscsi/cdu415.h37
-rw-r--r--src/devices/bus/nscsi/cdu561.cpp87
-rw-r--r--src/devices/bus/nscsi/cdu561.h29
-rw-r--r--src/devices/bus/nscsi/cdu75s.cpp78
-rw-r--r--src/devices/bus/nscsi/cdu75s.h37
-rw-r--r--src/devices/bus/nscsi/cfp1080s.cpp95
-rw-r--r--src/devices/bus/nscsi/cfp1080s.h40
-rw-r--r--src/devices/bus/nscsi/crd254sh.cpp63
-rw-r--r--src/devices/bus/nscsi/crd254sh.h35
-rw-r--r--src/devices/bus/nscsi/cw7501.cpp2
-rw-r--r--src/devices/bus/nscsi/cw7501.h16
-rw-r--r--src/devices/bus/nscsi/devices.cpp25
-rw-r--r--src/devices/bus/nscsi/devices.h1
-rw-r--r--src/devices/bus/nscsi/hd.cpp190
-rw-r--r--src/devices/bus/nscsi/hd.h7
-rw-r--r--src/devices/bus/nscsi/s1410.cpp106
-rw-r--r--src/devices/bus/nscsi/s1410.h18
-rw-r--r--src/devices/bus/nscsi/smoc501.cpp91
-rw-r--r--src/devices/bus/nscsi/smoc501.h30
-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/bootbug.cpp98
-rw-r--r--src/devices/bus/nubus/bootbug.h36
-rw-r--r--src/devices/bus/nubus/cards.cpp120
-rw-r--r--src/devices/bus/nubus/cards.h21
-rw-r--r--src/devices/bus/nubus/laserview.cpp273
-rw-r--r--src/devices/bus/nubus/laserview.h12
-rw-r--r--src/devices/bus/nubus/nubus.cpp428
-rw-r--r--src/devices/bus/nubus/nubus.h213
-rw-r--r--src/devices/bus/nubus/nubus_48gc.cpp1190
-rw-r--r--src/devices/bus/nubus/nubus_48gc.h60
-rw-r--r--src/devices/bus/nubus/nubus_asntmc3b.cpp217
-rw-r--r--src/devices/bus/nubus/nubus_asntmc3b.h58
-rw-r--r--src/devices/bus/nubus/nubus_cb264.cpp412
-rw-r--r--src/devices/bus/nubus/nubus_cb264.h42
-rw-r--r--src/devices/bus/nubus/nubus_image.cpp354
-rw-r--r--src/devices/bus/nubus/nubus_image.h73
-rw-r--r--src/devices/bus/nubus/nubus_m2hires.cpp574
-rw-r--r--src/devices/bus/nubus/nubus_m2hires.h47
-rw-r--r--src/devices/bus/nubus/nubus_m2video.cpp416
-rw-r--r--src/devices/bus/nubus/nubus_m2video.h45
-rw-r--r--src/devices/bus/nubus/nubus_radiustpd.cpp186
-rw-r--r--src/devices/bus/nubus/nubus_radiustpd.h45
-rw-r--r--src/devices/bus/nubus/nubus_spec8.cpp551
-rw-r--r--src/devices/bus/nubus/nubus_spec8.h54
-rw-r--r--src/devices/bus/nubus/nubus_specpdq.cpp812
-rw-r--r--src/devices/bus/nubus/nubus_specpdq.h54
-rw-r--r--src/devices/bus/nubus/nubus_vikbw.cpp165
-rw-r--r--src/devices/bus/nubus/nubus_vikbw.h46
-rw-r--r--src/devices/bus/nubus/nubus_wsportrait.cpp301
-rw-r--r--src/devices/bus/nubus/nubus_wsportrait.h56
-rw-r--r--src/devices/bus/nubus/pds30_30hr.cpp822
-rw-r--r--src/devices/bus/nubus/pds30_30hr.h48
-rw-r--r--src/devices/bus/nubus/pds30_cb264.cpp374
-rw-r--r--src/devices/bus/nubus/pds30_cb264.h46
-rw-r--r--src/devices/bus/nubus/pds30_mc30.cpp327
-rw-r--r--src/devices/bus/nubus/pds30_mc30.h56
-rw-r--r--src/devices/bus/nubus/pds30_procolor816.cpp422
-rw-r--r--src/devices/bus/nubus/pds30_procolor816.h47
-rw-r--r--src/devices/bus/nubus/pds30_sigmalview.cpp209
-rw-r--r--src/devices/bus/nubus/pds30_sigmalview.h47
-rw-r--r--src/devices/bus/nubus/quadralink.cpp97
-rw-r--r--src/devices/bus/nubus/quadralink.h36
-rw-r--r--src/devices/bus/nubus/supermac.cpp167
-rw-r--r--src/devices/bus/nubus/supermac.h70
-rw-r--r--src/devices/bus/nubus/thunder4gx.cpp905
-rw-r--r--src/devices/bus/nubus/thunder4gx.h13
-rw-r--r--src/devices/bus/odyssey2/4in1.cpp79
-rw-r--r--src/devices/bus/odyssey2/4in1.h18
-rw-r--r--src/devices/bus/odyssey2/chess.cpp120
-rw-r--r--src/devices/bus/odyssey2/chess.h33
-rw-r--r--src/devices/bus/odyssey2/homecomp.cpp253
-rw-r--r--src/devices/bus/odyssey2/homecomp.h18
-rw-r--r--src/devices/bus/odyssey2/ktaa.cpp88
-rw-r--r--src/devices/bus/odyssey2/ktaa.h18
-rw-r--r--src/devices/bus/odyssey2/rally.cpp142
-rw-r--r--src/devices/bus/odyssey2/rally.h19
-rw-r--r--src/devices/bus/odyssey2/rom.cpp101
-rw-r--r--src/devices/bus/odyssey2/rom.h66
-rw-r--r--src/devices/bus/odyssey2/slot.cpp279
-rw-r--r--src/devices/bus/odyssey2/slot.h147
-rw-r--r--src/devices/bus/odyssey2/test.cpp92
-rw-r--r--src/devices/bus/odyssey2/test.h18
-rw-r--r--src/devices/bus/odyssey2/voice.cpp156
-rw-r--r--src/devices/bus/odyssey2/voice.h49
-rw-r--r--src/devices/bus/oricext/jasmin.cpp127
-rw-r--r--src/devices/bus/oricext/jasmin.h29
-rw-r--r--src/devices/bus/oricext/microdisc.cpp131
-rw-r--r--src/devices/bus/oricext/microdisc.h46
-rw-r--r--src/devices/bus/oricext/oricext.cpp90
-rw-r--r--src/devices/bus/oricext/oricext.h43
-rw-r--r--src/devices/bus/pasopia/pac2.cpp159
-rw-r--r--src/devices/bus/pasopia/pac2.h83
-rw-r--r--src/devices/bus/pasopia/pac2exp.cpp92
-rw-r--r--src/devices/bus/pasopia/pac2exp.h44
-rw-r--r--src/devices/bus/pasopia/rampac2.cpp151
-rw-r--r--src/devices/bus/pasopia/rampac2.h76
-rw-r--r--src/devices/bus/pasopia/rompac2.cpp98
-rw-r--r--src/devices/bus/pasopia/rompac2.h44
-rw-r--r--src/devices/bus/pc1512/mouse.cpp20
-rw-r--r--src/devices/bus/pc1512/mouse.h17
-rw-r--r--src/devices/bus/pc8801/README.md39
-rw-r--r--src/devices/bus/pc8801/gsx8800.cpp54
-rw-r--r--src/devices/bus/pc8801/gsx8800.h30
-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.cpp58
-rw-r--r--src/devices/bus/pc8801/jmbx1.h31
-rw-r--r--src/devices/bus/pc8801/pc8801_23.cpp89
-rw-r--r--src/devices/bus/pc8801/pc8801_23.h42
-rw-r--r--src/devices/bus/pc8801/pc8801_31.cpp251
-rw-r--r--src/devices/bus/pc8801/pc8801_31.h66
-rw-r--r--src/devices/bus/pc8801/pc8801_exp.cpp94
-rw-r--r--src/devices/bus/pc8801/pc8801_exp.h94
-rw-r--r--src/devices/bus/pc8801/pcg8100.cpp109
-rw-r--r--src/devices/bus/pc8801/pcg8100.h44
-rw-r--r--src/devices/bus/pc_joy/pc_joy.cpp25
-rw-r--r--src/devices/bus/pc_joy/pc_joy.h15
-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_joy/pc_joy_sw.cpp4
-rw-r--r--src/devices/bus/pc_joy/pc_joy_sw.h9
-rw-r--r--src/devices/bus/pc_kbd/cherry_mx1500.cpp333
-rw-r--r--src/devices/bus/pc_kbd/cherry_mx1500.h44
-rw-r--r--src/devices/bus/pc_kbd/ec1841.cpp37
-rw-r--r--src/devices/bus/pc_kbd/ec1841.h24
-rw-r--r--src/devices/bus/pc_kbd/hle_mouse.cpp11
-rw-r--r--src/devices/bus/pc_kbd/hle_mouse.h12
-rw-r--r--src/devices/bus/pc_kbd/iskr1030.cpp21
-rw-r--r--src/devices/bus/pc_kbd/iskr1030.h28
-rw-r--r--src/devices/bus/pc_kbd/keyboards.cpp2
-rw-r--r--src/devices/bus/pc_kbd/keyboards.h1
-rw-r--r--src/devices/bus/pc_kbd/keytro.cpp20
-rw-r--r--src/devices/bus/pc_kbd/keytro.h36
-rw-r--r--src/devices/bus/pc_kbd/msnat.cpp16
-rw-r--r--src/devices/bus/pc_kbd/msnat.h32
-rw-r--r--src/devices/bus/pc_kbd/pc83.cpp8
-rw-r--r--src/devices/bus/pc_kbd/pc83.h22
-rw-r--r--src/devices/bus/pc_kbd/pc_kbdc.cpp59
-rw-r--r--src/devices/bus/pc_kbd/pc_kbdc.h52
-rw-r--r--src/devices/bus/pc_kbd/pcat101.cpp1
-rw-r--r--src/devices/bus/pc_kbd/pcat101.h10
-rw-r--r--src/devices/bus/pc_kbd/pcat84.cpp22
-rw-r--r--src/devices/bus/pc_kbd/pcat84.h32
-rw-r--r--src/devices/bus/pc_kbd/pcxt83.cpp26
-rw-r--r--src/devices/bus/pc_kbd/pcxt83.h26
-rw-r--r--src/devices/bus/pccard/ataflash.cpp (renamed from src/devices/machine/ataflash.cpp)108
-rw-r--r--src/devices/bus/pccard/ataflash.h (renamed from src/devices/machine/ataflash.h)69
-rw-r--r--src/devices/bus/pccard/k573npu.cpp101
-rw-r--r--src/devices/bus/pccard/k573npu.h29
-rw-r--r--src/devices/bus/pccard/konami_dual.cpp93
-rw-r--r--src/devices/bus/pccard/konami_dual.h30
-rw-r--r--src/devices/bus/pccard/linflash.cpp249
-rw-r--r--src/devices/bus/pccard/linflash.h124
-rw-r--r--src/devices/bus/pccard/pccard.cpp122
-rw-r--r--src/devices/bus/pccard/pccard.h87
-rw-r--r--src/devices/bus/pccard/sram.cpp413
-rw-r--r--src/devices/bus/pccard/sram.h165
-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.cpp153
-rw-r--r--src/devices/bus/pce/pce_rom.h56
-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.cpp91
-rw-r--r--src/devices/bus/pce/pce_slot.h61
-rw-r--r--src/devices/bus/pce_ctrl/joypad2.cpp318
-rw-r--r--src/devices/bus/pce_ctrl/joypad2.h19
-rw-r--r--src/devices/bus/pce_ctrl/joypad6.cpp388
-rw-r--r--src/devices/bus/pce_ctrl/joypad6.h19
-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/multitap.cpp123
-rw-r--r--src/devices/bus/pce_ctrl/multitap.h57
-rw-r--r--src/devices/bus/pce_ctrl/pachinko.cpp151
-rw-r--r--src/devices/bus/pce_ctrl/pachinko.h61
-rw-r--r--src/devices/bus/pce_ctrl/pcectrl.cpp200
-rw-r--r--src/devices/bus/pce_ctrl/pcectrl.h81
-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.cpp149
-rw-r--r--src/devices/bus/pci/aha2940au.h47
-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.h58
-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/ncr53c825.cpp95
-rw-r--r--src/devices/bus/pci/ncr53c825.h39
-rw-r--r--src/devices/bus/pci/neon250.cpp188
-rw-r--r--src/devices/bus/pci/neon250.h53
-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.h47
-rw-r--r--src/devices/bus/pci/pci_slot.cpp186
-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.h71
-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.h37
-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.cpp162
-rw-r--r--src/devices/bus/pci/sonicvibes.h44
-rw-r--r--src/devices/bus/pci/sw1000xg.cpp93
-rw-r--r--src/devices/bus/pci/sw1000xg.h35
-rw-r--r--src/devices/bus/pci/virge_pci.cpp347
-rw-r--r--src/devices/bus/pci/virge_pci.h (renamed from src/devices/video/virge_pci.h)69
-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.cpp779
-rw-r--r--src/devices/bus/pci/zr36057.h121
-rw-r--r--src/devices/bus/pet/2joysnd.cpp25
-rw-r--r--src/devices/bus/pet/2joysnd.h20
-rw-r--r--src/devices/bus/pet/64k.cpp5
-rw-r--r--src/devices/bus/pet/64k.h6
-rw-r--r--src/devices/bus/pet/c2n.cpp8
-rw-r--r--src/devices/bus/pet/c2n.h8
-rw-r--r--src/devices/bus/pet/cass.cpp19
-rw-r--r--src/devices/bus/pet/cass.h16
-rw-r--r--src/devices/bus/pet/cb2snd.cpp5
-rw-r--r--src/devices/bus/pet/cb2snd.h6
-rw-r--r--src/devices/bus/pet/diag.h28
-rw-r--r--src/devices/bus/pet/diag264_lb_tape.h2
-rw-r--r--src/devices/bus/pet/exp.cpp45
-rw-r--r--src/devices/bus/pet/exp.h23
-rw-r--r--src/devices/bus/pet/hsg.h14
-rw-r--r--src/devices/bus/pet/petuja.cpp20
-rw-r--r--src/devices/bus/pet/petuja.h16
-rw-r--r--src/devices/bus/pet/superpet.cpp15
-rw-r--r--src/devices/bus/pet/superpet.h20
-rw-r--r--src/devices/bus/pet/user.cpp60
-rw-r--r--src/devices/bus/pet/user.h121
-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.cpp93
-rw-r--r--src/devices/bus/plg1x0/plg150-ap.h15
-rw-r--r--src/devices/bus/plg1x0/plg1x0.cpp50
-rw-r--r--src/devices/bus/plg1x0/plg1x0.h81
-rw-r--r--src/devices/bus/plus4/c1551.cpp35
-rw-r--r--src/devices/bus/plus4/c1551.h17
-rw-r--r--src/devices/bus/plus4/diag264_lb_user.h36
-rw-r--r--src/devices/bus/plus4/exp.cpp75
-rw-r--r--src/devices/bus/plus4/exp.h66
-rw-r--r--src/devices/bus/plus4/sid.cpp2
-rw-r--r--src/devices/bus/plus4/sid.h8
-rw-r--r--src/devices/bus/plus4/std.cpp16
-rw-r--r--src/devices/bus/plus4/std.h2
-rw-r--r--src/devices/bus/pofo/ccm.cpp36
-rw-r--r--src/devices/bus/pofo/ccm.h35
-rw-r--r--src/devices/bus/pofo/exp.cpp17
-rw-r--r--src/devices/bus/pofo/exp.h35
-rw-r--r--src/devices/bus/pofo/hpc101.cpp6
-rw-r--r--src/devices/bus/pofo/hpc101.h6
-rw-r--r--src/devices/bus/pofo/hpc102.h6
-rw-r--r--src/devices/bus/pofo/hpc104.cpp27
-rw-r--r--src/devices/bus/pofo/hpc104.h29
-rw-r--r--src/devices/bus/pofo/ram.cpp23
-rw-r--r--src/devices/bus/pofo/ram.h17
-rw-r--r--src/devices/bus/pofo/rom.cpp2
-rw-r--r--src/devices/bus/pofo/rom.h2
-rw-r--r--src/devices/bus/psi_kbd/ergoline.h14
-rw-r--r--src/devices/bus/psi_kbd/hle.cpp36
-rw-r--r--src/devices/bus/psi_kbd/hle.h6
-rw-r--r--src/devices/bus/psi_kbd/psi_kbd.cpp14
-rw-r--r--src/devices/bus/psi_kbd/psi_kbd.h20
-rw-r--r--src/devices/bus/psion/honda/parallel.cpp67
-rw-r--r--src/devices/bus/psion/honda/parallel.h13
-rw-r--r--src/devices/bus/psion/honda/pclink.cpp50
-rw-r--r--src/devices/bus/psion/honda/pclink.h13
-rw-r--r--src/devices/bus/psion/honda/slot.cpp126
-rw-r--r--src/devices/bus/psion/honda/slot.h119
-rw-r--r--src/devices/bus/psion/honda/ssd.cpp59
-rw-r--r--src/devices/bus/psion/honda/ssd.h12
-rw-r--r--src/devices/bus/psion/module/serpar.cpp91
-rw-r--r--src/devices/bus/psion/module/serpar.h13
-rw-r--r--src/devices/bus/psion/module/slot.cpp114
-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.h81
-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/analogue.cpp10
-rw-r--r--src/devices/bus/psx/analogue.h4
-rw-r--r--src/devices/bus/psx/ctlrport.cpp41
-rw-r--r--src/devices/bus/psx/ctlrport.h46
-rw-r--r--src/devices/bus/psx/gamebooster.cpp134
-rw-r--r--src/devices/bus/psx/gamebooster.h35
-rw-r--r--src/devices/bus/psx/memcard.cpp42
-rw-r--r--src/devices/bus/psx/memcard.h24
-rw-r--r--src/devices/bus/psx/multitap.cpp8
-rw-r--r--src/devices/bus/psx/multitap.h4
-rw-r--r--src/devices/bus/psx/parallel.cpp24
-rw-r--r--src/devices/bus/psx/parallel.h23
-rw-r--r--src/devices/bus/qbus/bk_kmd.cpp132
-rw-r--r--src/devices/bus/qbus/bk_kmd.h20
-rw-r--r--src/devices/bus/qbus/dsd4432.cpp255
-rw-r--r--src/devices/bus/qbus/dsd4432.h46
-rw-r--r--src/devices/bus/qbus/dvk_kgd.cpp163
-rw-r--r--src/devices/bus/qbus/dvk_kgd.h65
-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.cpp232
-rw-r--r--src/devices/bus/qbus/pc11.h84
-rw-r--r--src/devices/bus/qbus/qbus.cpp197
-rw-r--r--src/devices/bus/qbus/qbus.h167
-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.cpp166
-rw-r--r--src/devices/bus/qbus/qtx.h54
-rw-r--r--src/devices/bus/qbus/tdl12.cpp137
-rw-r--r--src/devices/bus/qbus/tdl12.h42
-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.h14
-rw-r--r--src/devices/bus/ql/cst_qdisc.h4
-rw-r--r--src/devices/bus/ql/cumana_fdi.h4
-rw-r--r--src/devices/bus/ql/exp.cpp27
-rw-r--r--src/devices/bus/ql/exp.h19
-rw-r--r--src/devices/bus/ql/kempston_di.h10
-rw-r--r--src/devices/bus/ql/miracle_gold_card.h4
-rw-r--r--src/devices/bus/ql/miracle_hd.h10
-rw-r--r--src/devices/bus/ql/mp_fdi.h4
-rw-r--r--src/devices/bus/ql/opd_basic_master.h4
-rw-r--r--src/devices/bus/ql/pcml_qdisk.h4
-rw-r--r--src/devices/bus/ql/qubide.cpp14
-rw-r--r--src/devices/bus/ql/qubide.h12
-rw-r--r--src/devices/bus/ql/rom.cpp42
-rw-r--r--src/devices/bus/ql/rom.h44
-rw-r--r--src/devices/bus/ql/sandy_superdisk.cpp23
-rw-r--r--src/devices/bus/ql/sandy_superdisk.h16
-rw-r--r--src/devices/bus/ql/sandy_superqboard.cpp32
-rw-r--r--src/devices/bus/ql/sandy_superqboard.h22
-rw-r--r--src/devices/bus/ql/std.cpp4
-rw-r--r--src/devices/bus/ql/std.h2
-rw-r--r--src/devices/bus/ql/trumpcard.cpp25
-rw-r--r--src/devices/bus/ql/trumpcard.h16
-rw-r--r--src/devices/bus/rc2014/cf.cpp67
-rw-r--r--src/devices/bus/rc2014/cf.h18
-rw-r--r--src/devices/bus/rc2014/clock.cpp230
-rw-r--r--src/devices/bus/rc2014/clock.h20
-rw-r--r--src/devices/bus/rc2014/edge.cpp203
-rw-r--r--src/devices/bus/rc2014/edge.h23
-rw-r--r--src/devices/bus/rc2014/fdc.cpp232
-rw-r--r--src/devices/bus/rc2014/fdc.h19
-rw-r--r--src/devices/bus/rc2014/ide.cpp295
-rw-r--r--src/devices/bus/rc2014/ide.h19
-rw-r--r--src/devices/bus/rc2014/micro.cpp303
-rw-r--r--src/devices/bus/rc2014/micro.h19
-rw-r--r--src/devices/bus/rc2014/modules.cpp88
-rw-r--r--src/devices/bus/rc2014/modules.h22
-rw-r--r--src/devices/bus/rc2014/ram.cpp216
-rw-r--r--src/devices/bus/rc2014/ram.h20
-rw-r--r--src/devices/bus/rc2014/rc2014.cpp361
-rw-r--r--src/devices/bus/rc2014/rc2014.h330
-rw-r--r--src/devices/bus/rc2014/rom.cpp262
-rw-r--r--src/devices/bus/rc2014/rom.h19
-rw-r--r--src/devices/bus/rc2014/romram.cpp226
-rw-r--r--src/devices/bus/rc2014/romram.h19
-rw-r--r--src/devices/bus/rc2014/rtc.cpp107
-rw-r--r--src/devices/bus/rc2014/rtc.h18
-rw-r--r--src/devices/bus/rc2014/serial.cpp274
-rw-r--r--src/devices/bus/rc2014/serial.h20
-rw-r--r--src/devices/bus/rc2014/sound.cpp207
-rw-r--r--src/devices/bus/rc2014/sound.h19
-rw-r--r--src/devices/bus/rc2014/z180cpu.cpp135
-rw-r--r--src/devices/bus/rc2014/z180cpu.h18
-rw-r--r--src/devices/bus/rc2014/z80cpu.cpp135
-rw-r--r--src/devices/bus/rc2014/z80cpu.h19
-rw-r--r--src/devices/bus/rs232/exorterm.cpp86
-rw-r--r--src/devices/bus/rs232/exorterm.h40
-rw-r--r--src/devices/bus/rs232/hlemouse.cpp52
-rw-r--r--src/devices/bus/rs232/hlemouse.h32
-rw-r--r--src/devices/bus/rs232/ie15.cpp100
-rw-r--r--src/devices/bus/rs232/ie15.h32
-rw-r--r--src/devices/bus/rs232/keyboard.cpp10
-rw-r--r--src/devices/bus/rs232/keyboard.h11
-rw-r--r--src/devices/bus/rs232/loopback.cpp18
-rw-r--r--src/devices/bus/rs232/loopback.h18
-rw-r--r--src/devices/bus/rs232/mboardd.cpp144
-rw-r--r--src/devices/bus/rs232/mboardd.h12
-rw-r--r--src/devices/bus/rs232/nss_tvinterface.cpp251
-rw-r--r--src/devices/bus/rs232/nss_tvinterface.h18
-rw-r--r--src/devices/bus/rs232/null_modem.cpp92
-rw-r--r--src/devices/bus/rs232/null_modem.h25
-rw-r--r--src/devices/bus/rs232/patchbox.cpp214
-rw-r--r--src/devices/bus/rs232/patchbox.h13
-rw-r--r--src/devices/bus/rs232/printer.cpp37
-rw-r--r--src/devices/bus/rs232/printer.h24
-rw-r--r--src/devices/bus/rs232/pty.cpp96
-rw-r--r--src/devices/bus/rs232/pty.h22
-rw-r--r--src/devices/bus/rs232/rs232.cpp95
-rw-r--r--src/devices/bus/rs232/rs232.h127
-rw-r--r--src/devices/bus/rs232/rs232_sync_io.cpp201
-rw-r--r--src/devices/bus/rs232/rs232_sync_io.h62
-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.cpp86
-rw-r--r--src/devices/bus/rs232/sun_kbd.h22
-rw-r--r--src/devices/bus/rs232/swtpc8212.cpp87
-rw-r--r--src/devices/bus/rs232/swtpc8212.h40
-rw-r--r--src/devices/bus/rs232/teletex800.cpp161
-rw-r--r--src/devices/bus/rs232/teletex800.h13
-rw-r--r--src/devices/bus/rs232/terminal.cpp44
-rw-r--r--src/devices/bus/rs232/terminal.h34
-rw-r--r--src/devices/bus/rs232/xvd701.cpp253
-rw-r--r--src/devices/bus/rs232/xvd701.h45
-rw-r--r--src/devices/bus/rtpc/kbd.cpp466
-rw-r--r--src/devices/bus/rtpc/kbd.h47
-rw-r--r--src/devices/bus/rtpc/kbd_con.cpp121
-rw-r--r--src/devices/bus/rtpc/kbd_con.h79
-rw-r--r--src/devices/bus/s100/am310.cpp72
-rw-r--r--src/devices/bus/s100/ascsasi.cpp366
-rw-r--r--src/devices/bus/s100/ascsasi.h18
-rw-r--r--src/devices/bus/s100/dg640.cpp24
-rw-r--r--src/devices/bus/s100/dg640.h8
-rw-r--r--src/devices/bus/s100/dj2db.cpp38
-rw-r--r--src/devices/bus/s100/dj2db.h19
-rw-r--r--src/devices/bus/s100/djdma.h12
-rw-r--r--src/devices/bus/s100/mm65k16s.cpp3
-rw-r--r--src/devices/bus/s100/mm65k16s.h10
-rw-r--r--src/devices/bus/s100/nsmdsa.cpp2
-rw-r--r--src/devices/bus/s100/nsmdsa.h8
-rw-r--r--src/devices/bus/s100/nsmdsad.cpp2
-rw-r--r--src/devices/bus/s100/nsmdsad.h8
-rw-r--r--src/devices/bus/s100/poly16k.cpp4
-rw-r--r--src/devices/bus/s100/polyfdc.cpp67
-rw-r--r--src/devices/bus/s100/polyvti.cpp32
-rw-r--r--src/devices/bus/s100/s100.cpp82
-rw-r--r--src/devices/bus/s100/s100.h66
-rw-r--r--src/devices/bus/s100/seals8k.cpp18
-rw-r--r--src/devices/bus/s100/seals8k.h6
-rw-r--r--src/devices/bus/s100/vectordualmode.cpp358
-rw-r--r--src/devices/bus/s100/vectordualmode.h54
-rw-r--r--src/devices/bus/s100/wunderbus.cpp5
-rw-r--r--src/devices/bus/s100/wunderbus.h12
-rw-r--r--src/devices/bus/saitek_osa/expansion.cpp167
-rw-r--r--src/devices/bus/saitek_osa/expansion.h126
-rw-r--r--src/devices/bus/saitek_osa/maestro.cpp436
-rw-r--r--src/devices/bus/saitek_osa/maestro.h19
-rw-r--r--src/devices/bus/saitek_osa/maestroa.cpp230
-rw-r--r--src/devices/bus/saitek_osa/maestroa.h18
-rw-r--r--src/devices/bus/saitek_osa/sparc.cpp237
-rw-r--r--src/devices/bus/saitek_osa/sparc.h18
-rw-r--r--src/devices/bus/samcoupe/drive/atom.cpp120
-rw-r--r--src/devices/bus/samcoupe/drive/atom.h48
-rw-r--r--src/devices/bus/samcoupe/drive/drive.cpp94
-rw-r--r--src/devices/bus/samcoupe/drive/drive.h96
-rw-r--r--src/devices/bus/samcoupe/drive/floppy.cpp93
-rw-r--r--src/devices/bus/samcoupe/drive/floppy.h49
-rw-r--r--src/devices/bus/samcoupe/drive/modules.cpp19
-rw-r--r--src/devices/bus/samcoupe/drive/modules.h16
-rw-r--r--src/devices/bus/samcoupe/expansion/blue_sampler.cpp115
-rw-r--r--src/devices/bus/samcoupe/expansion/blue_sampler.h54
-rw-r--r--src/devices/bus/samcoupe/expansion/dallas.cpp85
-rw-r--r--src/devices/bus/samcoupe/expansion/dallas.h49
-rw-r--r--src/devices/bus/samcoupe/expansion/expansion.cpp121
-rw-r--r--src/devices/bus/samcoupe/expansion/expansion.h128
-rw-r--r--src/devices/bus/samcoupe/expansion/modules.cpp32
-rw-r--r--src/devices/bus/samcoupe/expansion/modules.h16
-rw-r--r--src/devices/bus/samcoupe/expansion/onemeg.cpp110
-rw-r--r--src/devices/bus/samcoupe/expansion/onemeg.h52
-rw-r--r--src/devices/bus/samcoupe/expansion/sambus.cpp116
-rw-r--r--src/devices/bus/samcoupe/expansion/sambus.h53
-rw-r--r--src/devices/bus/samcoupe/expansion/sdide.cpp116
-rw-r--r--src/devices/bus/samcoupe/expansion/sdide.h49
-rw-r--r--src/devices/bus/samcoupe/expansion/sid.cpp90
-rw-r--r--src/devices/bus/samcoupe/expansion/sid.h67
-rw-r--r--src/devices/bus/samcoupe/expansion/spi.cpp120
-rw-r--r--src/devices/bus/samcoupe/expansion/spi.h54
-rw-r--r--src/devices/bus/samcoupe/expansion/voicebox.cpp88
-rw-r--r--src/devices/bus/samcoupe/expansion/voicebox.h46
-rw-r--r--src/devices/bus/samcoupe/mouse/modules.cpp17
-rw-r--r--src/devices/bus/samcoupe/mouse/modules.h16
-rw-r--r--src/devices/bus/samcoupe/mouse/mouse.cpp137
-rw-r--r--src/devices/bus/samcoupe/mouse/mouse.h54
-rw-r--r--src/devices/bus/samcoupe/mouse/mouseport.cpp89
-rw-r--r--src/devices/bus/samcoupe/mouse/mouseport.h92
-rw-r--r--src/devices/bus/sat_ctrl/analog.h6
-rw-r--r--src/devices/bus/sat_ctrl/ctrl.cpp9
-rw-r--r--src/devices/bus/sat_ctrl/ctrl.h8
-rw-r--r--src/devices/bus/sat_ctrl/joy.h6
-rw-r--r--src/devices/bus/sat_ctrl/joy_md.h4
-rw-r--r--src/devices/bus/sat_ctrl/keybd.cpp262
-rw-r--r--src/devices/bus/sat_ctrl/keybd.h6
-rw-r--r--src/devices/bus/sat_ctrl/mouse.h6
-rw-r--r--src/devices/bus/sat_ctrl/multitap.cpp36
-rw-r--r--src/devices/bus/sat_ctrl/multitap.h13
-rw-r--r--src/devices/bus/sat_ctrl/pointer.h6
-rw-r--r--src/devices/bus/sat_ctrl/racing.h6
-rw-r--r--src/devices/bus/sat_ctrl/segatap.cpp35
-rw-r--r--src/devices/bus/sat_ctrl/segatap.h12
-rw-r--r--src/devices/bus/saturn/bram.cpp21
-rw-r--r--src/devices/bus/saturn/bram.h12
-rw-r--r--src/devices/bus/saturn/dram.cpp8
-rw-r--r--src/devices/bus/saturn/dram.h12
-rw-r--r--src/devices/bus/saturn/rom.cpp2
-rw-r--r--src/devices/bus/saturn/rom.h6
-rw-r--r--src/devices/bus/saturn/sat_slot.cpp61
-rw-r--r--src/devices/bus/saturn/sat_slot.h71
-rw-r--r--src/devices/bus/sbus/artecon.cpp6
-rw-r--r--src/devices/bus/sbus/artecon.h12
-rw-r--r--src/devices/bus/sbus/bwtwo.cpp19
-rw-r--r--src/devices/bus/sbus/bwtwo.h16
-rw-r--r--src/devices/bus/sbus/cgsix.cpp311
-rw-r--r--src/devices/bus/sbus/cgsix.h76
-rw-r--r--src/devices/bus/sbus/cgthree.cpp22
-rw-r--r--src/devices/bus/sbus/cgthree.h23
-rw-r--r--src/devices/bus/sbus/hme.cpp6
-rw-r--r--src/devices/bus/sbus/hme.h12
-rw-r--r--src/devices/bus/sbus/sbus.cpp43
-rw-r--r--src/devices/bus/sbus/sbus.h56
-rw-r--r--src/devices/bus/sbus/sunpc.cpp6
-rw-r--r--src/devices/bus/sbus/sunpc.h12
-rw-r--r--src/devices/bus/scsi/cdu76s.cpp14
-rw-r--r--src/devices/bus/scsi/cdu76s.h3
-rw-r--r--src/devices/bus/scsi/omti5100.cpp30
-rw-r--r--src/devices/bus/scsi/omti5100.h6
-rw-r--r--src/devices/bus/scsi/pc9801_sasi.cpp27
-rw-r--r--src/devices/bus/scsi/pc9801_sasi.h3
-rw-r--r--src/devices/bus/scsi/s1410.cpp12
-rw-r--r--src/devices/bus/scsi/s1410.h10
-rw-r--r--src/devices/bus/scsi/sa1403d.h6
-rw-r--r--src/devices/bus/scsi/scsi.cpp62
-rw-r--r--src/devices/bus/scsi/scsi.h115
-rw-r--r--src/devices/bus/scsi/scsicd.cpp14
-rw-r--r--src/devices/bus/scsi/scsicd.h7
-rw-r--r--src/devices/bus/scsi/scsicd512.cpp6
-rw-r--r--src/devices/bus/scsi/scsicd512.h14
-rw-r--r--src/devices/bus/scsi/scsihd.cpp5
-rw-r--r--src/devices/bus/scsi/scsihd.h6
-rw-r--r--src/devices/bus/scsi/scsihle.cpp51
-rw-r--r--src/devices/bus/scsi/scsihle.h35
-rw-r--r--src/devices/bus/scv/rom.cpp260
-rw-r--r--src/devices/bus/scv/rom.h149
-rw-r--r--src/devices/bus/scv/slot.cpp183
-rw-r--r--src/devices/bus/scv/slot.h124
-rw-r--r--src/devices/bus/sdk85/i8755.cpp65
-rw-r--r--src/devices/bus/sdk85/i8755.h40
-rw-r--r--src/devices/bus/sdk85/memexp.cpp94
-rw-r--r--src/devices/bus/sdk85/memexp.h76
-rw-r--r--src/devices/bus/sega8/ccatch.cpp6
-rw-r--r--src/devices/bus/sega8/ccatch.h8
-rw-r--r--src/devices/bus/sega8/mgear.cpp2
-rw-r--r--src/devices/bus/sega8/mgear.h12
-rw-r--r--src/devices/bus/sega8/rom.cpp304
-rw-r--r--src/devices/bus/sega8/rom.h221
-rw-r--r--src/devices/bus/sega8/sega8_slot.cpp155
-rw-r--r--src/devices/bus/sega8/sega8_slot.h135
-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.cpp319
-rw-r--r--src/devices/bus/segaai/soundbox.h14
-rw-r--r--src/devices/bus/sg1000_exp/fm_unit.cpp4
-rw-r--r--src/devices/bus/sg1000_exp/fm_unit.h12
-rw-r--r--src/devices/bus/sg1000_exp/kblink.cpp44
-rw-r--r--src/devices/bus/sg1000_exp/kblink.h26
-rw-r--r--src/devices/bus/sg1000_exp/sg1000exp.cpp17
-rw-r--r--src/devices/bus/sg1000_exp/sg1000exp.h14
-rw-r--r--src/devices/bus/sg1000_exp/sk1100.cpp274
-rw-r--r--src/devices/bus/sg1000_exp/sk1100.h32
-rw-r--r--src/devices/bus/sg1000_exp/sk1100prn.cpp22
-rw-r--r--src/devices/bus/sg1000_exp/sk1100prn.h33
-rw-r--r--src/devices/bus/sg1000_exp/sp400.cpp233
-rw-r--r--src/devices/bus/sg1000_exp/sp400.h13
-rw-r--r--src/devices/bus/sgikbd/hlekbd.cpp413
-rw-r--r--src/devices/bus/sgikbd/hlekbd.h117
-rw-r--r--src/devices/bus/sgikbd/sgikbd.cpp89
-rw-r--r--src/devices/bus/sgikbd/sgikbd.h82
-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.cpp255
-rw-r--r--src/devices/bus/sms_ctrl/lphaser.h51
-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.h42
-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.h159
-rw-r--r--src/devices/bus/sms_ctrl/sports.cpp271
-rw-r--r--src/devices/bus/sms_ctrl/sports.h53
-rw-r--r--src/devices/bus/sms_ctrl/sportsjp.cpp149
-rw-r--r--src/devices/bus/sms_ctrl/sportsjp.h54
-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/sms_exp/gender.cpp20
-rw-r--r--src/devices/bus/sms_exp/gender.h14
-rw-r--r--src/devices/bus/sms_exp/smsexp.cpp8
-rw-r--r--src/devices/bus/sms_exp/smsexp.h27
-rw-r--r--src/devices/bus/snes/bsx.h18
-rw-r--r--src/devices/bus/snes/event.cpp45
-rw-r--r--src/devices/bus/snes/event.h17
-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/rom.cpp26
-rw-r--r--src/devices/bus/snes/rom.h28
-rw-r--r--src/devices/bus/snes/rom21.cpp4
-rw-r--r--src/devices/bus/snes/rom21.h8
-rw-r--r--src/devices/bus/snes/sa1.cpp1152
-rw-r--r--src/devices/bus/snes/sa1.h176
-rw-r--r--src/devices/bus/snes/sdd1.cpp7
-rw-r--r--src/devices/bus/snes/sdd1.h4
-rw-r--r--src/devices/bus/snes/sfx.cpp34
-rw-r--r--src/devices/bus/snes/sfx.h38
-rw-r--r--src/devices/bus/snes/sgb.cpp96
-rw-r--r--src/devices/bus/snes/sgb.h32
-rw-r--r--src/devices/bus/snes/snes_carts.cpp17
-rw-r--r--src/devices/bus/snes/snes_slot.cpp151
-rw-r--r--src/devices/bus/snes/snes_slot.h84
-rw-r--r--src/devices/bus/snes/spc7110.h4
-rw-r--r--src/devices/bus/snes/st018.cpp161
-rw-r--r--src/devices/bus/snes/st018.h56
-rw-r--r--src/devices/bus/snes/sufami.h6
-rw-r--r--src/devices/bus/snes/upd.cpp86
-rw-r--r--src/devices/bus/snes/upd.h58
-rw-r--r--src/devices/bus/snes_ctrl/bcbattle.cpp67
-rw-r--r--src/devices/bus/snes_ctrl/bcbattle.h11
-rw-r--r--src/devices/bus/snes_ctrl/ctrl.cpp15
-rw-r--r--src/devices/bus/snes_ctrl/ctrl.h27
-rw-r--r--src/devices/bus/snes_ctrl/joypad.cpp16
-rw-r--r--src/devices/bus/snes_ctrl/joypad.h6
-rw-r--r--src/devices/bus/snes_ctrl/miracle.cpp11
-rw-r--r--src/devices/bus/snes_ctrl/miracle.h11
-rw-r--r--src/devices/bus/snes_ctrl/mouse.cpp4
-rw-r--r--src/devices/bus/snes_ctrl/mouse.h6
-rw-r--r--src/devices/bus/snes_ctrl/multitap.h8
-rw-r--r--src/devices/bus/snes_ctrl/pachinko.h6
-rw-r--r--src/devices/bus/snes_ctrl/sscope.h12
-rw-r--r--src/devices/bus/snes_ctrl/twintap.h6
-rw-r--r--src/devices/bus/spc1000/exp.cpp16
-rw-r--r--src/devices/bus/spc1000/exp.h14
-rw-r--r--src/devices/bus/spc1000/fdd.cpp74
-rw-r--r--src/devices/bus/spc1000/fdd.h33
-rw-r--r--src/devices/bus/spc1000/vdp.cpp6
-rw-r--r--src/devices/bus/spc1000/vdp.h12
-rw-r--r--src/devices/bus/spectrum/beta.cpp618
-rw-r--r--src/devices/bus/spectrum/beta.h107
-rw-r--r--src/devices/bus/spectrum/beta128.cpp147
-rw-r--r--src/devices/bus/spectrum/beta128.h29
-rw-r--r--src/devices/bus/spectrum/d40.cpp473
-rw-r--r--src/devices/bus/spectrum/d40.h130
-rw-r--r--src/devices/bus/spectrum/exp.cpp97
-rw-r--r--src/devices/bus/spectrum/exp.h95
-rw-r--r--src/devices/bus/spectrum/floppyone.cpp317
-rw-r--r--src/devices/bus/spectrum/floppyone.h81
-rw-r--r--src/devices/bus/spectrum/fuller.cpp31
-rw-r--r--src/devices/bus/spectrum/fuller.h19
-rw-r--r--src/devices/bus/spectrum/intf1.cpp12
-rw-r--r--src/devices/bus/spectrum/intf1.h18
-rw-r--r--src/devices/bus/spectrum/intf2.cpp16
-rw-r--r--src/devices/bus/spectrum/intf2.h10
-rw-r--r--src/devices/bus/spectrum/kempdisc.cpp282
-rw-r--r--src/devices/bus/spectrum/kempdisc.h83
-rw-r--r--src/devices/bus/spectrum/kempjoy.cpp4
-rw-r--r--src/devices/bus/spectrum/kempjoy.h4
-rw-r--r--src/devices/bus/spectrum/logitek.cpp216
-rw-r--r--src/devices/bus/spectrum/logitek.h73
-rw-r--r--src/devices/bus/spectrum/lprint.cpp522
-rw-r--r--src/devices/bus/spectrum/lprint.h185
-rw-r--r--src/devices/bus/spectrum/melodik.cpp33
-rw-r--r--src/devices/bus/spectrum/melodik.h17
-rw-r--r--src/devices/bus/spectrum/mface.cpp745
-rw-r--r--src/devices/bus/spectrum/mface.h190
-rw-r--r--src/devices/bus/spectrum/mgt.cpp725
-rw-r--r--src/devices/bus/spectrum/mgt.h111
-rw-r--r--src/devices/bus/spectrum/mikroplus.cpp6
-rw-r--r--src/devices/bus/spectrum/mikroplus.h8
-rw-r--r--src/devices/bus/spectrum/mpoker.cpp168
-rw-r--r--src/devices/bus/spectrum/mpoker.h49
-rw-r--r--src/devices/bus/spectrum/musicmachine.cpp149
-rw-r--r--src/devices/bus/spectrum/musicmachine.h20
-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.cpp512
-rw-r--r--src/devices/bus/spectrum/neogs.h14
-rw-r--r--src/devices/bus/spectrum/opus.cpp53
-rw-r--r--src/devices/bus/spectrum/opus.h36
-rw-r--r--src/devices/bus/spectrum/plus2test.cpp2
-rw-r--r--src/devices/bus/spectrum/plus2test.h6
-rw-r--r--src/devices/bus/spectrum/protek.cpp2
-rw-r--r--src/devices/bus/spectrum/protek.h4
-rw-r--r--src/devices/bus/spectrum/sdi.cpp159
-rw-r--r--src/devices/bus/spectrum/sdi.h61
-rw-r--r--src/devices/bus/spectrum/sixword.cpp604
-rw-r--r--src/devices/bus/spectrum/sixword.h114
-rw-r--r--src/devices/bus/spectrum/smuc.cpp141
-rw-r--r--src/devices/bus/spectrum/smuc.h14
-rw-r--r--src/devices/bus/spectrum/speccydos.cpp251
-rw-r--r--src/devices/bus/spectrum/speccydos.h70
-rw-r--r--src/devices/bus/spectrum/specdrum.cpp4
-rw-r--r--src/devices/bus/spectrum/specdrum.h4
-rw-r--r--src/devices/bus/spectrum/specmate.cpp190
-rw-r--r--src/devices/bus/spectrum/specmate.h59
-rw-r--r--src/devices/bus/spectrum/uslot.cpp24
-rw-r--r--src/devices/bus/spectrum/uslot.h11
-rw-r--r--src/devices/bus/spectrum/usource.cpp11
-rw-r--r--src/devices/bus/spectrum/usource.h10
-rw-r--r--src/devices/bus/spectrum/uspeech.cpp58
-rw-r--r--src/devices/bus/spectrum/uspeech.h12
-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.cpp12
-rw-r--r--src/devices/bus/spectrum/wafa.h18
-rw-r--r--src/devices/bus/spectrum/zxbus.cpp94
-rw-r--r--src/devices/bus/spectrum/zxbus.h133
-rw-r--r--src/devices/bus/ss50/dc5.cpp326
-rw-r--r--src/devices/bus/ss50/dc5.h6
-rw-r--r--src/devices/bus/ss50/interface.cpp41
-rw-r--r--src/devices/bus/ss50/interface.h42
-rw-r--r--src/devices/bus/ss50/mpc.cpp33
-rw-r--r--src/devices/bus/ss50/mpc.h6
-rw-r--r--src/devices/bus/ss50/mps.cpp92
-rw-r--r--src/devices/bus/ss50/mps.h6
-rw-r--r--src/devices/bus/ss50/mps2.cpp82
-rw-r--r--src/devices/bus/ss50/mps2.h6
-rw-r--r--src/devices/bus/ss50/mpt.cpp42
-rw-r--r--src/devices/bus/ss50/mpt.h6
-rw-r--r--src/devices/bus/ss50/piaide.cpp28
-rw-r--r--src/devices/bus/ss50/piaide.h6
-rw-r--r--src/devices/bus/st/replay.cpp100
-rw-r--r--src/devices/bus/st/replay.h15
-rw-r--r--src/devices/bus/st/stcart.cpp40
-rw-r--r--src/devices/bus/st/stcart.h50
-rw-r--r--src/devices/bus/sunkbd/hlekbd.cpp493
-rw-r--r--src/devices/bus/sunkbd/hlekbd.h131
-rw-r--r--src/devices/bus/sunkbd/sunkbd.cpp42
-rw-r--r--src/devices/bus/sunkbd/sunkbd.h16
-rw-r--r--src/devices/bus/sunmouse/hlemouse.cpp24
-rw-r--r--src/devices/bus/sunmouse/hlemouse.h16
-rw-r--r--src/devices/bus/sunmouse/sunmouse.cpp38
-rw-r--r--src/devices/bus/sunmouse/sunmouse.h17
-rw-r--r--src/devices/bus/supracan/rom.cpp96
-rw-r--r--src/devices/bus/supracan/rom.h46
-rw-r--r--src/devices/bus/supracan/slot.cpp116
-rw-r--r--src/devices/bus/supracan/slot.h90
-rw-r--r--src/devices/bus/svi3x8/expander/expander.cpp50
-rw-r--r--src/devices/bus/svi3x8/expander/expander.h44
-rw-r--r--src/devices/bus/svi3x8/expander/sv601.cpp20
-rw-r--r--src/devices/bus/svi3x8/expander/sv601.h10
-rw-r--r--src/devices/bus/svi3x8/expander/sv602.cpp8
-rw-r--r--src/devices/bus/svi3x8/expander/sv602.h10
-rw-r--r--src/devices/bus/svi3x8/expander/sv603.cpp31
-rw-r--r--src/devices/bus/svi3x8/expander/sv603.h14
-rw-r--r--src/devices/bus/svi3x8/slot/slot.cpp126
-rw-r--r--src/devices/bus/svi3x8/slot/slot.h66
-rw-r--r--src/devices/bus/svi3x8/slot/sv801.cpp14
-rw-r--r--src/devices/bus/svi3x8/slot/sv801.h12
-rw-r--r--src/devices/bus/svi3x8/slot/sv802.cpp2
-rw-r--r--src/devices/bus/svi3x8/slot/sv802.h6
-rw-r--r--src/devices/bus/svi3x8/slot/sv803.h4
-rw-r--r--src/devices/bus/svi3x8/slot/sv805.cpp2
-rw-r--r--src/devices/bus/svi3x8/slot/sv805.h6
-rw-r--r--src/devices/bus/svi3x8/slot/sv806.cpp20
-rw-r--r--src/devices/bus/svi3x8/slot/sv806.h6
-rw-r--r--src/devices/bus/svi3x8/slot/sv807.h6
-rw-r--r--src/devices/bus/tanbus/bullsnd.h4
-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.cpp20
-rw-r--r--src/devices/bus/tanbus/mpvdu.h8
-rw-r--r--src/devices/bus/tanbus/ra32k.cpp143
-rw-r--r--src/devices/bus/tanbus/ra32k.h61
-rw-r--r--src/devices/bus/tanbus/radisc.cpp94
-rw-r--r--src/devices/bus/tanbus/radisc.h28
-rw-r--r--src/devices/bus/tanbus/ravdu.cpp20
-rw-r--r--src/devices/bus/tanbus/ravdu.h10
-rw-r--r--src/devices/bus/tanbus/tanbus.cpp79
-rw-r--r--src/devices/bus/tanbus/tanbus.h37
-rw-r--r--src/devices/bus/tanbus/tandos.cpp60
-rw-r--r--src/devices/bus/tanbus/tandos.h32
-rw-r--r--src/devices/bus/tanbus/tanex.cpp26
-rw-r--r--src/devices/bus/tanbus/tanex.h32
-rw-r--r--src/devices/bus/tanbus/tanhrg.cpp21
-rw-r--r--src/devices/bus/tanbus/tanhrg.h12
-rw-r--r--src/devices/bus/tanbus/tanram.cpp20
-rw-r--r--src/devices/bus/tanbus/tanram.h2
-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/tug64k.h4
-rw-r--r--src/devices/bus/tanbus/tug8082.cpp18
-rw-r--r--src/devices/bus/tanbus/tug8082.h14
-rw-r--r--src/devices/bus/tanbus/tugcombo.cpp270
-rw-r--r--src/devices/bus/tanbus/tugcombo.h142
-rw-r--r--src/devices/bus/tanbus/tugpgm.h4
-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.cpp151
-rw-r--r--src/devices/bus/thomson/cd90_015.h49
-rw-r--r--src/devices/bus/thomson/cd90_351.cpp88
-rw-r--r--src/devices/bus/thomson/cd90_351.h42
-rw-r--r--src/devices/bus/thomson/cd90_640.cpp93
-rw-r--r--src/devices/bus/thomson/cd90_640.h46
-rw-r--r--src/devices/bus/thomson/cq90_028.cpp76
-rw-r--r--src/devices/bus/thomson/cq90_028.h42
-rw-r--r--src/devices/bus/thomson/extension.cpp54
-rw-r--r--src/devices/bus/thomson/extension.h55
-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.cpp204
-rw-r--r--src/devices/bus/thomson/nanoreseau.h67
-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.cpp66
-rw-r--r--src/devices/bus/ti8x/bitsocket.h44
-rw-r--r--src/devices/bus/ti8x/graphlinkhle.cpp45
-rw-r--r--src/devices/bus/ti8x/graphlinkhle.h45
-rw-r--r--src/devices/bus/ti8x/teeconn.cpp46
-rw-r--r--src/devices/bus/ti8x/teeconn.h40
-rw-r--r--src/devices/bus/ti8x/ti8x.cpp29
-rw-r--r--src/devices/bus/ti8x/ti8x.h32
-rw-r--r--src/devices/bus/ti8x/tispeaker.cpp149
-rw-r--r--src/devices/bus/ti8x/tispeaker.h51
-rw-r--r--src/devices/bus/ti99/colorbus/busmouse.cpp25
-rw-r--r--src/devices/bus/ti99/colorbus/busmouse.h9
-rw-r--r--src/devices/bus/ti99/colorbus/colorbus.cpp24
-rw-r--r--src/devices/bus/ti99/colorbus/colorbus.h18
-rw-r--r--src/devices/bus/ti99/gromport/cartridges.cpp722
-rw-r--r--src/devices/bus/ti99/gromport/cartridges.h202
-rw-r--r--src/devices/bus/ti99/gromport/gkracker.cpp101
-rw-r--r--src/devices/bus/ti99/gromport/gkracker.h31
-rw-r--r--src/devices/bus/ti99/gromport/gromport.cpp40
-rw-r--r--src/devices/bus/ti99/gromport/gromport.h47
-rw-r--r--src/devices/bus/ti99/gromport/multiconn.cpp147
-rw-r--r--src/devices/bus/ti99/gromport/multiconn.h29
-rw-r--r--src/devices/bus/ti99/gromport/singleconn.cpp30
-rw-r--r--src/devices/bus/ti99/gromport/singleconn.h21
-rw-r--r--src/devices/bus/ti99/internal/992board.cpp364
-rw-r--r--src/devices/bus/ti99/internal/992board.h122
-rw-r--r--src/devices/bus/ti99/internal/998board.cpp198
-rw-r--r--src/devices/bus/ti99/internal/998board.h378
-rw-r--r--src/devices/bus/ti99/internal/buffram.cpp60
-rw-r--r--src/devices/bus/ti99/internal/buffram.h49
-rw-r--r--src/devices/bus/ti99/internal/datamux.cpp99
-rw-r--r--src/devices/bus/ti99/internal/datamux.h34
-rw-r--r--src/devices/bus/ti99/internal/evpcconn.cpp16
-rw-r--r--src/devices/bus/ti99/internal/evpcconn.h10
-rw-r--r--src/devices/bus/ti99/internal/genboard.cpp1967
-rw-r--r--src/devices/bus/ti99/internal/genboard.h306
-rw-r--r--src/devices/bus/ti99/internal/genkbd.cpp127
-rw-r--r--src/devices/bus/ti99/internal/genkbd.h17
-rw-r--r--src/devices/bus/ti99/internal/ioport.cpp57
-rw-r--r--src/devices/bus/ti99/internal/ioport.h46
-rw-r--r--src/devices/bus/ti99/internal/splitter.cpp190
-rw-r--r--src/devices/bus/ti99/internal/splitter.h65
-rw-r--r--src/devices/bus/ti99/joyport/handset.cpp178
-rw-r--r--src/devices/bus/ti99/joyport/handset.h23
-rw-r--r--src/devices/bus/ti99/joyport/joyport.cpp22
-rw-r--r--src/devices/bus/ti99/joyport/joyport.h18
-rw-r--r--src/devices/bus/ti99/joyport/mecmouse.cpp41
-rw-r--r--src/devices/bus/ti99/joyport/mecmouse.h18
-rw-r--r--src/devices/bus/ti99/peb/bwg.cpp135
-rw-r--r--src/devices/bus/ti99/peb/bwg.h59
-rw-r--r--src/devices/bus/ti99/peb/cc_fdc.cpp809
-rw-r--r--src/devices/bus/ti99/peb/cc_fdc.h249
-rw-r--r--src/devices/bus/ti99/peb/evpc.cpp79
-rw-r--r--src/devices/bus/ti99/peb/evpc.h31
-rw-r--r--src/devices/bus/ti99/peb/forti.cpp133
-rw-r--r--src/devices/bus/ti99/peb/forti.h52
-rw-r--r--src/devices/bus/ti99/peb/hfdc.cpp173
-rw-r--r--src/devices/bus/ti99/peb/hfdc.h47
-rw-r--r--src/devices/bus/ti99/peb/horizon.cpp817
-rw-r--r--src/devices/bus/ti99/peb/horizon.h69
-rw-r--r--src/devices/bus/ti99/peb/hsgpl.cpp34
-rw-r--r--src/devices/bus/ti99/peb/hsgpl.h18
-rw-r--r--src/devices/bus/ti99/peb/memex.cpp39
-rw-r--r--src/devices/bus/ti99/peb/memex.h18
-rw-r--r--src/devices/bus/ti99/peb/myarcfdc.cpp515
-rw-r--r--src/devices/bus/ti99/peb/myarcfdc.h137
-rw-r--r--src/devices/bus/ti99/peb/myarcmem.cpp10
-rw-r--r--src/devices/bus/ti99/peb/myarcmem.h14
-rw-r--r--src/devices/bus/ti99/peb/pcode.cpp55
-rw-r--r--src/devices/bus/ti99/peb/pcode.h30
-rw-r--r--src/devices/bus/ti99/peb/peribox.cpp276
-rw-r--r--src/devices/bus/ti99/peb/peribox.h107
-rw-r--r--src/devices/bus/ti99/peb/pgram.cpp564
-rw-r--r--src/devices/bus/ti99/peb/pgram.h87
-rw-r--r--src/devices/bus/ti99/peb/samsmem.cpp20
-rw-r--r--src/devices/bus/ti99/peb/samsmem.h18
-rw-r--r--src/devices/bus/ti99/peb/scsicard.cpp699
-rw-r--r--src/devices/bus/ti99/peb/scsicard.h145
-rw-r--r--src/devices/bus/ti99/peb/sidmaster.cpp98
-rw-r--r--src/devices/bus/ti99/peb/sidmaster.h47
-rw-r--r--src/devices/bus/ti99/peb/spchsyn.cpp186
-rw-r--r--src/devices/bus/ti99/peb/spchsyn.h53
-rw-r--r--src/devices/bus/ti99/peb/speechadapter.cpp158
-rw-r--r--src/devices/bus/ti99/peb/speechadapter.h49
-rw-r--r--src/devices/bus/ti99/peb/ti_32kmem.cpp8
-rw-r--r--src/devices/bus/ti99/peb/ti_32kmem.h12
-rw-r--r--src/devices/bus/ti99/peb/ti_fdc.cpp119
-rw-r--r--src/devices/bus/ti99/peb/ti_fdc.h47
-rw-r--r--src/devices/bus/ti99/peb/ti_rs232.cpp104
-rw-r--r--src/devices/bus/ti99/peb/ti_rs232.h91
-rw-r--r--src/devices/bus/ti99/peb/tipi.cpp739
-rw-r--r--src/devices/bus/ti99/peb/tipi.h131
-rw-r--r--src/devices/bus/ti99/peb/tn_ide.cpp917
-rw-r--r--src/devices/bus/ti99/peb/tn_ide.h87
-rw-r--r--src/devices/bus/ti99/peb/tn_usbsm.cpp29
-rw-r--r--src/devices/bus/ti99/peb/tn_usbsm.h17
-rw-r--r--src/devices/bus/ti99/sidecar/arcturus.cpp93
-rw-r--r--src/devices/bus/ti99/sidecar/arcturus.h49
-rw-r--r--src/devices/bus/ti99/sidecar/speechsyn.cpp273
-rw-r--r--src/devices/bus/ti99/sidecar/speechsyn.h65
-rw-r--r--src/devices/bus/ti99/ti99defs.h67
-rw-r--r--src/devices/bus/ti99x/990_dk.cpp5
-rw-r--r--src/devices/bus/ti99x/990_dk.h8
-rw-r--r--src/devices/bus/ti99x/990_hd.cpp104
-rw-r--r--src/devices/bus/ti99x/990_hd.h15
-rw-r--r--src/devices/bus/ti99x/990_tap.cpp40
-rw-r--r--src/devices/bus/ti99x/990_tap.h10
-rw-r--r--src/devices/bus/tiki100/8088.cpp14
-rw-r--r--src/devices/bus/tiki100/8088.h16
-rw-r--r--src/devices/bus/tiki100/exp.cpp91
-rw-r--r--src/devices/bus/tiki100/exp.h57
-rw-r--r--src/devices/bus/tiki100/hdc.h6
-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/tmc600/euro.cpp28
-rw-r--r--src/devices/bus/tmc600/euro.h52
-rw-r--r--src/devices/bus/tvc/hbf.cpp18
-rw-r--r--src/devices/bus/tvc/hbf.h19
-rw-r--r--src/devices/bus/tvc/tvc.cpp26
-rw-r--r--src/devices/bus/tvc/tvc.h29
-rw-r--r--src/devices/bus/uts_kbd/400kbd.cpp14
-rw-r--r--src/devices/bus/uts_kbd/400kbd.h16
-rw-r--r--src/devices/bus/uts_kbd/extw.cpp8
-rw-r--r--src/devices/bus/uts_kbd/extw.h18
-rw-r--r--src/devices/bus/uts_kbd/uts_kbd.cpp11
-rw-r--r--src/devices/bus/uts_kbd/uts_kbd.h19
-rw-r--r--src/devices/bus/vboy/rom.cpp188
-rw-r--r--src/devices/bus/vboy/rom.h44
-rw-r--r--src/devices/bus/vboy/slot.cpp287
-rw-r--r--src/devices/bus/vboy/slot.h222
-rw-r--r--src/devices/bus/vc4000/slot.cpp38
-rw-r--r--src/devices/bus/vc4000/slot.h46
-rw-r--r--src/devices/bus/vcs/compumat.cpp18
-rw-r--r--src/devices/bus/vcs/compumat.h14
-rw-r--r--src/devices/bus/vcs/dpc.cpp74
-rw-r--r--src/devices/bus/vcs/dpc.h30
-rw-r--r--src/devices/bus/vcs/harmony_melody.cpp42
-rw-r--r--src/devices/bus/vcs/harmony_melody.h25
-rw-r--r--src/devices/bus/vcs/rom.cpp1171
-rw-r--r--src/devices/bus/vcs/rom.h289
-rw-r--r--src/devices/bus/vcs/scharger.cpp164
-rw-r--r--src/devices/bus/vcs/scharger.h33
-rw-r--r--src/devices/bus/vcs/vcs_slot.cpp155
-rw-r--r--src/devices/bus/vcs/vcs_slot.h149
-rw-r--r--src/devices/bus/vcs_ctrl/ctrl.cpp14
-rw-r--r--src/devices/bus/vcs_ctrl/ctrl.h38
-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.h10
-rw-r--r--src/devices/bus/vcs_ctrl/keypad.cpp63
-rw-r--r--src/devices/bus/vcs_ctrl/keypad.h26
-rw-r--r--src/devices/bus/vcs_ctrl/lightpen.cpp2
-rw-r--r--src/devices/bus/vcs_ctrl/lightpen.h10
-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/trakball.cpp150
-rw-r--r--src/devices/bus/vcs_ctrl/trakball.h53
-rw-r--r--src/devices/bus/vcs_ctrl/wheel.cpp4
-rw-r--r--src/devices/bus/vcs_ctrl/wheel.h10
-rw-r--r--src/devices/bus/vectrex/rom.cpp8
-rw-r--r--src/devices/bus/vectrex/rom.h12
-rw-r--r--src/devices/bus/vectrex/slot.cpp75
-rw-r--r--src/devices/bus/vectrex/slot.h59
-rw-r--r--src/devices/bus/vic10/exp.cpp102
-rw-r--r--src/devices/bus/vic10/exp.h66
-rw-r--r--src/devices/bus/vic10/multimax.h4
-rw-r--r--src/devices/bus/vic10/std.cpp16
-rw-r--r--src/devices/bus/vic10/std.h2
-rw-r--r--src/devices/bus/vic20/4cga.cpp22
-rw-r--r--src/devices/bus/vic20/4cga.h22
-rw-r--r--src/devices/bus/vic20/exp.cpp185
-rw-r--r--src/devices/bus/vic20/exp.h69
-rw-r--r--src/devices/bus/vic20/fe3.cpp4
-rw-r--r--src/devices/bus/vic20/fe3.h10
-rw-r--r--src/devices/bus/vic20/megacart.cpp22
-rw-r--r--src/devices/bus/vic20/megacart.h21
-rw-r--r--src/devices/bus/vic20/speakeasy.cpp2
-rw-r--r--src/devices/bus/vic20/speakeasy.h4
-rw-r--r--src/devices/bus/vic20/std.h2
-rw-r--r--src/devices/bus/vic20/vic1010.h6
-rw-r--r--src/devices/bus/vic20/vic1011.cpp2
-rw-r--r--src/devices/bus/vic20/vic1011.h14
-rw-r--r--src/devices/bus/vic20/vic1110.cpp4
-rw-r--r--src/devices/bus/vic20/vic1110.h6
-rw-r--r--src/devices/bus/vic20/vic1111.cpp4
-rw-r--r--src/devices/bus/vic20/vic1111.h4
-rw-r--r--src/devices/bus/vic20/vic1112.cpp12
-rw-r--r--src/devices/bus/vic20/vic1112.h14
-rw-r--r--src/devices/bus/vic20/vic1210.cpp4
-rw-r--r--src/devices/bus/vic20/vic1210.h4
-rw-r--r--src/devices/bus/vic20/videopak.cpp11
-rw-r--r--src/devices/bus/vic20/videopak.h12
-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.cpp79
-rw-r--r--src/devices/bus/vidbrain/exp.h54
-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.cpp17
-rw-r--r--src/devices/bus/vip/byteio.h17
-rw-r--r--src/devices/bus/vip/exp.cpp23
-rw-r--r--src/devices/bus/vip/exp.h32
-rw-r--r--src/devices/bus/vip/vp550.cpp103
-rw-r--r--src/devices/bus/vip/vp550.h10
-rw-r--r--src/devices/bus/vip/vp570.cpp3
-rw-r--r--src/devices/bus/vip/vp570.h6
-rw-r--r--src/devices/bus/vip/vp575.h38
-rw-r--r--src/devices/bus/vip/vp585.h4
-rw-r--r--src/devices/bus/vip/vp590.cpp11
-rw-r--r--src/devices/bus/vip/vp590.h14
-rw-r--r--src/devices/bus/vip/vp595.cpp2
-rw-r--r--src/devices/bus/vip/vp595.h4
-rw-r--r--src/devices/bus/vip/vp620.h4
-rw-r--r--src/devices/bus/vip/vp700.h4
-rw-r--r--src/devices/bus/vme/cp31.cpp315
-rw-r--r--src/devices/bus/vme/cp31.h72
-rw-r--r--src/devices/bus/vme/enp10.cpp416
-rw-r--r--src/devices/bus/vme/enp10.h71
-rw-r--r--src/devices/bus/vme/hcpu30.cpp594
-rw-r--r--src/devices/bus/vme/hcpu30.h94
-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.cpp469
-rw-r--r--src/devices/bus/vme/mvme120.h153
-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.cpp129
-rw-r--r--src/devices/bus/vme/mvme180.h52
-rw-r--r--src/devices/bus/vme/mvme181.cpp155
-rw-r--r--src/devices/bus/vme/mvme181.h52
-rw-r--r--src/devices/bus/vme/mvme187.cpp135
-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/mvme328.cpp291
-rw-r--r--src/devices/bus/vme/mvme328.h56
-rw-r--r--src/devices/bus/vme/mvme350.cpp (renamed from src/devices/bus/vme/vme_mvme350.cpp)39
-rw-r--r--src/devices/bus/vme/mvme350.h (renamed from src/devices/bus/vme/vme_mvme350.h)20
-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)104
-rw-r--r--src/devices/bus/vme/mzr8300.h (renamed from src/devices/bus/vme/vme_mzr8300.h)22
-rw-r--r--src/devices/bus/vme/smvme2000.cpp138
-rw-r--r--src/devices/bus/vme/smvme2000.h54
-rw-r--r--src/devices/bus/vme/sys68k_cpu1.cpp671
-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)284
-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)152
-rw-r--r--src/devices/bus/vme/sys68k_iscsi.h72
-rw-r--r--src/devices/bus/vme/sys68k_isio.cpp (renamed from src/devices/bus/vme/vme_fcisio.cpp)82
-rw-r--r--src/devices/bus/vme/sys68k_isio.h53
-rw-r--r--src/devices/bus/vme/tp880v.cpp168
-rw-r--r--src/devices/bus/vme/tp880v.h57
-rw-r--r--src/devices/bus/vme/tp881v.cpp346
-rw-r--r--src/devices/bus/vme/tp881v.h59
-rw-r--r--src/devices/bus/vme/vme.cpp572
-rw-r--r--src/devices/bus/vme/vme.h282
-rw-r--r--src/devices/bus/vme/vme_cards.cpp69
-rw-r--r--src/devices/bus/vme/vme_cards.h11
-rw-r--r--src/devices/bus/vme/vme_fccpu20.h190
-rw-r--r--src/devices/bus/vme/vme_fcisio.h54
-rw-r--r--src/devices/bus/vme/vme_fcscsi.h73
-rw-r--r--src/devices/bus/vme/vme_hcpu30.cpp195
-rw-r--r--src/devices/bus/vme/vme_hcpu30.h48
-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/keyboard.cpp566
-rw-r--r--src/devices/bus/vsmile/keyboard.h143
-rw-r--r--src/devices/bus/vsmile/mat.cpp198
-rw-r--r--src/devices/bus/vsmile/mat.h70
-rw-r--r--src/devices/bus/vsmile/pad.cpp61
-rw-r--r--src/devices/bus/vsmile/pad.h41
-rw-r--r--src/devices/bus/vsmile/rom.cpp8
-rw-r--r--src/devices/bus/vsmile/rom.h16
-rw-r--r--src/devices/bus/vsmile/vsmile_ctrl.cpp72
-rw-r--r--src/devices/bus/vsmile/vsmile_ctrl.h12
-rw-r--r--src/devices/bus/vsmile/vsmile_slot.cpp74
-rw-r--r--src/devices/bus/vsmile/vsmile_slot.h78
-rw-r--r--src/devices/bus/vtech/ioexp/ioexp.cpp86
-rw-r--r--src/devices/bus/vtech/ioexp/ioexp.h46
-rw-r--r--src/devices/bus/vtech/ioexp/joystick.cpp25
-rw-r--r--src/devices/bus/vtech/ioexp/joystick.h13
-rw-r--r--src/devices/bus/vtech/ioexp/lpen.cpp63
-rw-r--r--src/devices/bus/vtech/ioexp/lpen.h43
-rw-r--r--src/devices/bus/vtech/ioexp/printer.cpp36
-rw-r--r--src/devices/bus/vtech/ioexp/printer.h19
-rw-r--r--src/devices/bus/vtech/memexp/carts.cpp2
-rw-r--r--src/devices/bus/vtech/memexp/floppy.cpp141
-rw-r--r--src/devices/bus/vtech/memexp/floppy.h31
-rw-r--r--src/devices/bus/vtech/memexp/memexp.cpp135
-rw-r--r--src/devices/bus/vtech/memexp/memexp.h67
-rw-r--r--src/devices/bus/vtech/memexp/memory.cpp112
-rw-r--r--src/devices/bus/vtech/memexp/memory.h39
-rw-r--r--src/devices/bus/vtech/memexp/rs232.cpp50
-rw-r--r--src/devices/bus/vtech/memexp/rs232.h18
-rw-r--r--src/devices/bus/vtech/memexp/rtty.cpp38
-rw-r--r--src/devices/bus/vtech/memexp/rtty.h18
-rw-r--r--src/devices/bus/vtech/memexp/sdloader.cpp343
-rw-r--r--src/devices/bus/vtech/memexp/sdloader.h19
-rw-r--r--src/devices/bus/vtech/memexp/wordpro.cpp25
-rw-r--r--src/devices/bus/vtech/memexp/wordpro.h9
-rw-r--r--src/devices/bus/wangpc/emb.cpp5
-rw-r--r--src/devices/bus/wangpc/emb.h6
-rw-r--r--src/devices/bus/wangpc/lic.h8
-rw-r--r--src/devices/bus/wangpc/lvc.cpp19
-rw-r--r--src/devices/bus/wangpc/lvc.h10
-rw-r--r--src/devices/bus/wangpc/mcc.cpp2
-rw-r--r--src/devices/bus/wangpc/mcc.h10
-rw-r--r--src/devices/bus/wangpc/mvc.cpp37
-rw-r--r--src/devices/bus/wangpc/mvc.h14
-rw-r--r--src/devices/bus/wangpc/rtc.cpp32
-rw-r--r--src/devices/bus/wangpc/rtc.h21
-rw-r--r--src/devices/bus/wangpc/tig.h12
-rw-r--r--src/devices/bus/wangpc/wangpc.cpp114
-rw-r--r--src/devices/bus/wangpc/wangpc.h80
-rw-r--r--src/devices/bus/wangpc/wdc.cpp20
-rw-r--r--src/devices/bus/wangpc/wdc.h34
-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.cpp55
-rw-r--r--src/devices/bus/waveblaster/waveblaster.h59
-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/rom.cpp721
-rw-r--r--src/devices/bus/wswan/rom.h113
-rw-r--r--src/devices/bus/wswan/slot.cpp163
-rw-r--r--src/devices/bus/wswan/slot.h165
-rw-r--r--src/devices/bus/wysekbd/wysegakb.cpp1020
-rw-r--r--src/devices/bus/wysekbd/wysegakb.h163
-rw-r--r--src/devices/bus/wysekbd/wysekbd.cpp89
-rw-r--r--src/devices/bus/wysekbd/wysekbd.h94
-rw-r--r--src/devices/bus/x68k/x68k_midi.cpp10
-rw-r--r--src/devices/bus/x68k/x68k_midi.h10
-rw-r--r--src/devices/bus/x68k/x68k_neptunex.cpp43
-rw-r--r--src/devices/bus/x68k/x68k_neptunex.h14
-rw-r--r--src/devices/bus/x68k/x68k_scsiext.cpp95
-rw-r--r--src/devices/bus/x68k/x68k_scsiext.h24
-rw-r--r--src/devices/bus/x68k/x68kexp.cpp33
-rw-r--r--src/devices/bus/x68k/x68kexp.h32
-rw-r--r--src/devices/bus/z29_kbd/he191_3425.cpp239
-rw-r--r--src/devices/bus/z29_kbd/he191_3425.h58
-rw-r--r--src/devices/bus/z29_kbd/keyboard.cpp111
-rw-r--r--src/devices/bus/z29_kbd/keyboard.h103
-rw-r--r--src/devices/bus/z29_kbd/md_kbd.cpp277
-rw-r--r--src/devices/bus/z29_kbd/md_kbd.h61
-rw-r--r--src/devices/bus/z88/flash.cpp23
-rw-r--r--src/devices/bus/z88/flash.h12
-rw-r--r--src/devices/bus/z88/ram.cpp116
-rw-r--r--src/devices/bus/z88/ram.h79
-rw-r--r--src/devices/bus/z88/rom.cpp128
-rw-r--r--src/devices/bus/z88/rom.h63
-rw-r--r--src/devices/bus/z88/z88.cpp91
-rw-r--r--src/devices/bus/z88/z88.h51
-rw-r--r--src/devices/cpu/8x300/8x300.cpp140
-rw-r--r--src/devices/cpu/8x300/8x300.h43
-rw-r--r--src/devices/cpu/8x300/8x300dasm.cpp4
-rw-r--r--src/devices/cpu/adsp2100/2100dasm.cpp297
-rw-r--r--src/devices/cpu/adsp2100/2100dasm.h6
-rw-r--r--src/devices/cpu/adsp2100/2100ops.hxx1050
-rw-r--r--src/devices/cpu/adsp2100/adsp2100.cpp390
-rw-r--r--src/devices/cpu/adsp2100/adsp2100.h59
-rw-r--r--src/devices/cpu/alph8201/8201dasm.cpp404
-rw-r--r--src/devices/cpu/alph8201/8201dasm.h51
-rw-r--r--src/devices/cpu/alph8201/alph8201.cpp698
-rw-r--r--src/devices/cpu/alph8201/alph8201.h415
-rw-r--r--src/devices/cpu/alpha/alpha.cpp25
-rw-r--r--src/devices/cpu/alpha/alpha.h19
-rw-r--r--src/devices/cpu/alpha/alphad.cpp31
-rw-r--r--src/devices/cpu/alpha/alphad.h4
-rw-r--r--src/devices/cpu/alpha/common.h4
-rw-r--r--src/devices/cpu/alto2/a2curt.h6
-rw-r--r--src/devices/cpu/alto2/a2dht.h6
-rw-r--r--src/devices/cpu/alto2/a2disk.cpp28
-rw-r--r--src/devices/cpu/alto2/a2disk.h8
-rw-r--r--src/devices/cpu/alto2/a2disp.cpp14
-rw-r--r--src/devices/cpu/alto2/a2disp.h52
-rw-r--r--src/devices/cpu/alto2/a2dvt.h6
-rw-r--r--src/devices/cpu/alto2/a2dwt.h6
-rw-r--r--src/devices/cpu/alto2/a2emu.cpp14
-rw-r--r--src/devices/cpu/alto2/a2emu.h6
-rw-r--r--src/devices/cpu/alto2/a2ether.cpp16
-rw-r--r--src/devices/cpu/alto2/a2ether.h90
-rw-r--r--src/devices/cpu/alto2/a2hw.cpp80
-rw-r--r--src/devices/cpu/alto2/a2hw.h88
-rw-r--r--src/devices/cpu/alto2/a2jkff.h6
-rw-r--r--src/devices/cpu/alto2/a2kbd.cpp2
-rw-r--r--src/devices/cpu/alto2/a2kbd.h8
-rw-r--r--src/devices/cpu/alto2/a2ksec.h6
-rw-r--r--src/devices/cpu/alto2/a2kwd.h6
-rw-r--r--src/devices/cpu/alto2/a2mem.cpp32
-rw-r--r--src/devices/cpu/alto2/a2mem.h42
-rw-r--r--src/devices/cpu/alto2/a2mouse.cpp6
-rw-r--r--src/devices/cpu/alto2/a2mouse.h8
-rw-r--r--src/devices/cpu/alto2/a2mrt.h6
-rw-r--r--src/devices/cpu/alto2/a2part.h6
-rw-r--r--src/devices/cpu/alto2/a2ram.cpp22
-rw-r--r--src/devices/cpu/alto2/a2ram.h6
-rw-r--r--src/devices/cpu/alto2/a2roms.cpp97
-rw-r--r--src/devices/cpu/alto2/a2roms.h10
-rw-r--r--src/devices/cpu/alto2/alto2cpu.cpp114
-rw-r--r--src/devices/cpu/alto2/alto2cpu.h81
-rw-r--r--src/devices/cpu/am29000/am29000.cpp20
-rw-r--r--src/devices/cpu/am29000/am29000.h20
-rw-r--r--src/devices/cpu/am29000/am29dasm.cpp14
-rw-r--r--src/devices/cpu/am29000/am29ops.h53
-rw-r--r--src/devices/cpu/amis2000/amis2000.cpp69
-rw-r--r--src/devices/cpu/amis2000/amis2000.h46
-rw-r--r--src/devices/cpu/amis2000/amis2000d.cpp29
-rw-r--r--src/devices/cpu/amis2000/amis2000d.h13
-rw-r--r--src/devices/cpu/amis2000/amis2000op.cpp6
-rw-r--r--src/devices/cpu/apexc/apexc.cpp12
-rw-r--r--src/devices/cpu/apexc/apexc.h9
-rw-r--r--src/devices/cpu/apexc/apexcdsm.cpp2
-rw-r--r--src/devices/cpu/arc/arc.cpp8
-rw-r--r--src/devices/cpu/arc/arc.h9
-rw-r--r--src/devices/cpu/arcompact/arcompact.cpp2885
-rw-r--r--src/devices/cpu/arcompact/arcompact.h1350
-rw-r--r--src/devices/cpu/arcompact/arcompact_common.h109
-rw-r--r--src/devices/cpu/arcompact/arcompact_execute.cpp8170
-rw-r--r--src/devices/cpu/arcompact/arcompact_execute_ops_00to01.cpp200
-rw-r--r--src/devices/cpu/arcompact/arcompact_execute_ops_02to03.cpp123
-rw-r--r--src/devices/cpu/arcompact/arcompact_execute_ops_04.cpp888
-rw-r--r--src/devices/cpu/arcompact/arcompact_execute_ops_04_2f_3f_zop.cpp63
-rw-r--r--src/devices/cpu/arcompact/arcompact_execute_ops_04_2f_sop.cpp336
-rw-r--r--src/devices/cpu/arcompact/arcompact_execute_ops_04_3x.cpp41
-rw-r--r--src/devices/cpu/arcompact/arcompact_execute_ops_04_aux.cpp153
-rw-r--r--src/devices/cpu/arcompact/arcompact_execute_ops_04_jumps.cpp149
-rw-r--r--src/devices/cpu/arcompact/arcompact_execute_ops_04_loop.cpp53
-rw-r--r--src/devices/cpu/arcompact/arcompact_execute_ops_05.cpp351
-rw-r--r--src/devices/cpu/arcompact/arcompact_execute_ops_05_2f_sop.cpp177
-rw-r--r--src/devices/cpu/arcompact/arcompact_execute_ops_06to0b.cpp41
-rw-r--r--src/devices/cpu/arcompact/arcompact_execute_ops_0c_16bit.cpp61
-rw-r--r--src/devices/cpu/arcompact/arcompact_execute_ops_0d_16bit.cpp66
-rw-r--r--src/devices/cpu/arcompact/arcompact_execute_ops_0e_16bit.cpp66
-rw-r--r--src/devices/cpu/arcompact/arcompact_execute_ops_0f_00_07_16bit.cpp78
-rw-r--r--src/devices/cpu/arcompact/arcompact_execute_ops_0f_00_16bit.cpp73
-rw-r--r--src/devices/cpu/arcompact/arcompact_execute_ops_0f_16bit.cpp370
-rw-r--r--src/devices/cpu/arcompact/arcompact_execute_ops_12to16_16bit.cpp104
-rw-r--r--src/devices/cpu/arcompact/arcompact_execute_ops_17_16bit.cpp114
-rw-r--r--src/devices/cpu/arcompact/arcompact_execute_ops_18_16bit.cpp154
-rw-r--r--src/devices/cpu/arcompact/arcompact_execute_ops_19_16bit.cpp53
-rw-r--r--src/devices/cpu/arcompact/arcompact_execute_ops_1ato1c_16bit.cpp59
-rw-r--r--src/devices/cpu/arcompact/arcompact_execute_ops_1dto1f_16bit.cpp161
-rw-r--r--src/devices/cpu/arcompact/arcompact_helper.ipp371
-rw-r--r--src/devices/cpu/arcompact/arcompactdasm.cpp2621
-rw-r--r--src/devices/cpu/arcompact/arcompactdasm.h749
-rw-r--r--src/devices/cpu/arcompact/arcompactdasm_dispatch.cpp987
-rw-r--r--src/devices/cpu/arcompact/arcompactdasm_internal.h251
-rw-r--r--src/devices/cpu/arcompact/arcompactdasm_ops.cpp4582
-rw-r--r--src/devices/cpu/arcompact/arcompactdasm_ops_00to01.cpp227
-rw-r--r--src/devices/cpu/arcompact/arcompactdasm_ops_02to03.cpp110
-rw-r--r--src/devices/cpu/arcompact/arcompactdasm_ops_04.cpp469
-rw-r--r--src/devices/cpu/arcompact/arcompactdasm_ops_04_2f_3f_zop.cpp41
-rw-r--r--src/devices/cpu/arcompact/arcompactdasm_ops_04_2f_sop.cpp134
-rw-r--r--src/devices/cpu/arcompact/arcompactdasm_ops_04_3x.cpp101
-rw-r--r--src/devices/cpu/arcompact/arcompactdasm_ops_05.cpp73
-rw-r--r--src/devices/cpu/arcompact/arcompactdasm_ops_05_2f_sop.cpp104
-rw-r--r--src/devices/cpu/arcompact/arcompactdasm_ops_06to0b.cpp45
-rw-r--r--src/devices/cpu/arcompact/arcompactdasm_ops_16bit.cpp715
-rw-r--r--src/devices/cpu/arm/arm.cpp79
-rw-r--r--src/devices/cpu/arm/arm.h25
-rw-r--r--src/devices/cpu/arm/armdasm.cpp258
-rw-r--r--src/devices/cpu/arm7/ap2010cpu.cpp45
-rw-r--r--src/devices/cpu/arm7/ap2010cpu.h35
-rw-r--r--src/devices/cpu/arm7/arm7.cpp1274
-rw-r--r--src/devices/cpu/arm7/arm7.h282
-rw-r--r--src/devices/cpu/arm7/arm7core.h129
-rw-r--r--src/devices/cpu/arm7/arm7core.hxx14
-rw-r--r--src/devices/cpu/arm7/arm7dasm.cpp1728
-rw-r--r--src/devices/cpu/arm7/arm7dasm.h9
-rw-r--r--src/devices/cpu/arm7/arm7drc.hxx102
-rw-r--r--src/devices/cpu/arm7/arm7fe.hxx2
-rw-r--r--src/devices/cpu/arm7/arm7help.h11
-rw-r--r--src/devices/cpu/arm7/arm7ops.cpp309
-rw-r--r--src/devices/cpu/arm7/arm7thmb.cpp49
-rw-r--r--src/devices/cpu/arm7/cecalls.hxx1066
-rw-r--r--src/devices/cpu/arm7/lpc210x.cpp66
-rw-r--r--src/devices/cpu/arm7/lpc210x.h66
-rw-r--r--src/devices/cpu/arm7/upd800468.cpp249
-rw-r--r--src/devices/cpu/arm7/upd800468.h104
-rw-r--r--src/devices/cpu/asap/asap.cpp153
-rw-r--r--src/devices/cpu/asap/asap.h13
-rw-r--r--src/devices/cpu/asap/asapdasm.cpp8
-rw-r--r--src/devices/cpu/avr8/avr8.cpp5448
-rw-r--r--src/devices/cpu/avr8/avr8.h1645
-rw-r--r--src/devices/cpu/avr8/avr8dasm.cpp1043
-rw-r--r--src/devices/cpu/avr8/avr8ops.hxx1403
-rw-r--r--src/devices/cpu/axc51/axc51.cpp1575
-rw-r--r--src/devices/cpu/axc51/axc51.h544
-rw-r--r--src/devices/cpu/axc51/axc51dasm.cpp (renamed from src/devices/cpu/mcs51/axc51-core_dasm.cpp)1235
-rw-r--r--src/devices/cpu/axc51/axc51dasm.h93
-rw-r--r--src/devices/cpu/axc51/axc51extops.hxx694
-rw-r--r--src/devices/cpu/axc51/axc51ops.hxx1050
-rw-r--r--src/devices/cpu/bcp/bcpdasm.cpp16
-rw-r--r--src/devices/cpu/bcp/dp8344.cpp1201
-rw-r--r--src/devices/cpu/bcp/dp8344.h111
-rw-r--r--src/devices/cpu/c33/c33common.h29
-rw-r--r--src/devices/cpu/c33/c33dasm.cpp674
-rw-r--r--src/devices/cpu/c33/c33dasm.h37
-rw-r--r--src/devices/cpu/c33/c33helpers.ipp64
-rw-r--r--src/devices/cpu/c33/c33std.cpp117
-rw-r--r--src/devices/cpu/c33/c33std.h58
-rw-r--r--src/devices/cpu/c33/s1c33209.cpp331
-rw-r--r--src/devices/cpu/c33/s1c33209.h57
-rw-r--r--src/devices/cpu/capricorn/capricorn.cpp62
-rw-r--r--src/devices/cpu/capricorn/capricorn.h39
-rw-r--r--src/devices/cpu/capricorn/capricorn_dasm.cpp30
-rw-r--r--src/devices/cpu/ccpu/ccpu.cpp77
-rw-r--r--src/devices/cpu/ccpu/ccpu.h71
-rw-r--r--src/devices/cpu/ccpu/ccpudasm.cpp15
-rw-r--r--src/devices/cpu/cdc160/cdc160d.cpp379
-rw-r--r--src/devices/cpu/cdc160/cdc160d.h34
-rw-r--r--src/devices/cpu/cdc1700/cdc1700d.cpp535
-rw-r--r--src/devices/cpu/cdc1700/cdc1700d.h37
-rw-r--r--src/devices/cpu/clipper/clipper.cpp213
-rw-r--r--src/devices/cpu/clipper/clipper.h49
-rw-r--r--src/devices/cpu/clipper/clipperd.cpp24
-rw-r--r--src/devices/cpu/clipper/clipperd.h6
-rw-r--r--src/devices/cpu/cop400/cop400.cpp141
-rw-r--r--src/devices/cpu/cop400/cop400.h148
-rw-r--r--src/devices/cpu/cop400/cop400op.hxx2
-rw-r--r--src/devices/cpu/cop400/cop410ds.cpp25
-rw-r--r--src/devices/cpu/cop400/cop410ds.h10
-rw-r--r--src/devices/cpu/cop400/cop420ds.cpp27
-rw-r--r--src/devices/cpu/cop400/cop420ds.h10
-rw-r--r--src/devices/cpu/cop400/cop424ds.cpp27
-rw-r--r--src/devices/cpu/cop400/cop424ds.h10
-rw-r--r--src/devices/cpu/cop400/cop444ds.cpp27
-rw-r--r--src/devices/cpu/cop400/cop444ds.h10
-rw-r--r--src/devices/cpu/cops1/cops1base.cpp220
-rw-r--r--src/devices/cpu/cops1/cops1base.h148
-rw-r--r--src/devices/cpu/cops1/cops1d.cpp201
-rw-r--r--src/devices/cpu/cops1/cops1d.h53
-rw-r--r--src/devices/cpu/cops1/mm5799.cpp156
-rw-r--r--src/devices/cpu/cops1/mm5799.h115
-rw-r--r--src/devices/cpu/cops1/mm5799op.cpp378
-rw-r--r--src/devices/cpu/cosmac/cosdasm.cpp54
-rw-r--r--src/devices/cpu/cosmac/cosmac.cpp287
-rw-r--r--src/devices/cpu/cosmac/cosmac.h96
-rw-r--r--src/devices/cpu/cp1610/1610dasm.cpp36
-rw-r--r--src/devices/cpu/cp1610/1610dasm.h6
-rw-r--r--src/devices/cpu/cp1610/cp1610.cpp159
-rw-r--r--src/devices/cpu/cp1610/cp1610.h31
-rw-r--r--src/devices/cpu/cr16b/cr16b.cpp6
-rw-r--r--src/devices/cpu/cr16b/cr16b.h8
-rw-r--r--src/devices/cpu/cr16b/cr16bdasm.cpp73
-rw-r--r--src/devices/cpu/cr16b/cr16bdasm.h3
-rw-r--r--src/devices/cpu/cr16c/cr16cdasm.cpp1472
-rw-r--r--src/devices/cpu/cr16c/cr16cdasm.h50
-rw-r--r--src/devices/cpu/cubeqcpu/cubedasm.cpp2
-rw-r--r--src/devices/cpu/cubeqcpu/cubeqcpu.cpp115
-rw-r--r--src/devices/cpu/cubeqcpu/cubeqcpu.h41
-rw-r--r--src/devices/cpu/ddp516/ddp516d.cpp1651
-rw-r--r--src/devices/cpu/ddp516/ddp516d.h87
-rw-r--r--src/devices/cpu/diablo/diablo1300.cpp30
-rw-r--r--src/devices/cpu/diablo/diablo1300.h29
-rw-r--r--src/devices/cpu/diablo/diablo1300dasm.cpp4
-rw-r--r--src/devices/cpu/drcbearm64.cpp5071
-rw-r--r--src/devices/cpu/drcbearm64.h26
-rw-r--r--src/devices/cpu/drcbec.cpp998
-rw-r--r--src/devices/cpu/drcbec.h57
-rw-r--r--src/devices/cpu/drcbeut.cpp273
-rw-r--r--src/devices/cpu/drcbeut.h148
-rw-r--r--src/devices/cpu/drcbex64.cpp7074
-rw-r--r--src/devices/cpu/drcbex64.h343
-rw-r--r--src/devices/cpu/drcbex86.cpp6579
-rw-r--r--src/devices/cpu/drcbex86.h336
-rw-r--r--src/devices/cpu/drccache.cpp186
-rw-r--r--src/devices/cpu/drccache.h52
-rw-r--r--src/devices/cpu/drcfe.h2
-rw-r--r--src/devices/cpu/drcuml.cpp679
-rw-r--r--src/devices/cpu/drcuml.h13
-rw-r--r--src/devices/cpu/drcumlsh.h30
-rw-r--r--src/devices/cpu/dsp16/dsp16.cpp91
-rw-r--r--src/devices/cpu/dsp16/dsp16.h48
-rw-r--r--src/devices/cpu/dsp16/dsp16dis.cpp2
-rw-r--r--src/devices/cpu/dsp16/dsp16fe.cpp18
-rw-r--r--src/devices/cpu/dsp16/dsp16fe.h8
-rw-r--r--src/devices/cpu/dsp32/dsp32.cpp40
-rw-r--r--src/devices/cpu/dsp32/dsp32.h13
-rw-r--r--src/devices/cpu/dsp32/dsp32dis.cpp6
-rw-r--r--src/devices/cpu/dsp32/dsp32ops.hxx13
-rw-r--r--src/devices/cpu/dsp56000/dsp56000.cpp86
-rw-r--r--src/devices/cpu/dsp56000/dsp56000.h58
-rw-r--r--src/devices/cpu/dsp56000/dsp56000d.cpp744
-rw-r--r--src/devices/cpu/dsp56000/dsp56000d.h25
-rw-r--r--src/devices/cpu/dsp56156/dsp56156.cpp44
-rw-r--r--src/devices/cpu/dsp56156/dsp56156.h136
-rw-r--r--src/devices/cpu/dsp56156/dsp56def.h12
-rw-r--r--src/devices/cpu/dsp56156/dsp56dsm.h6
-rw-r--r--src/devices/cpu/dsp56156/dsp56mem.cpp93
-rw-r--r--src/devices/cpu/dsp56156/dsp56ops.hxx2135
-rw-r--r--src/devices/cpu/dsp56156/dsp56pcu.cpp16
-rw-r--r--src/devices/cpu/dsp56156/dsp56pcu.h19
-rw-r--r--src/devices/cpu/dsp56156/inst.cpp7
-rw-r--r--src/devices/cpu/dsp56156/inst.h845
-rw-r--r--src/devices/cpu/dsp56156/opcode.cpp37
-rw-r--r--src/devices/cpu/dsp56156/opcode.h15
-rw-r--r--src/devices/cpu/dsp56156/pmove.h70
-rw-r--r--src/devices/cpu/dsp56156/tables.cpp114
-rw-r--r--src/devices/cpu/dsp56156/tables.h19
-rw-r--r--src/devices/cpu/dspp/dspp.cpp185
-rw-r--r--src/devices/cpu/dspp/dspp.h64
-rw-r--r--src/devices/cpu/dspp/dsppdasm.h6
-rw-r--r--src/devices/cpu/dspp/dsppdrc.cpp22
-rw-r--r--src/devices/cpu/dspp/dsppfe.cpp5
-rw-r--r--src/devices/cpu/dspp/dsppfe.h9
-rw-r--r--src/devices/cpu/e0c6200/e0c6200.cpp41
-rw-r--r--src/devices/cpu/e0c6200/e0c6200.h10
-rw-r--r--src/devices/cpu/e0c6200/e0c6200d.cpp48
-rw-r--r--src/devices/cpu/e0c6200/e0c6200d.h28
-rw-r--r--src/devices/cpu/e0c6200/e0c6200op.cpp5
-rw-r--r--src/devices/cpu/e0c6200/e0c6s46.cpp348
-rw-r--r--src/devices/cpu/e0c6200/e0c6s46.h112
-rw-r--r--src/devices/cpu/e132xs/32xsdasm.cpp2036
-rw-r--r--src/devices/cpu/e132xs/32xsdasm.h27
-rw-r--r--src/devices/cpu/e132xs/32xsdefs.h179
-rw-r--r--src/devices/cpu/e132xs/e132xs.cpp1663
-rw-r--r--src/devices/cpu/e132xs/e132xs.h679
-rw-r--r--src/devices/cpu/e132xs/e132xsdrc.cpp1043
-rw-r--r--src/devices/cpu/e132xs/e132xsdrc_ops.hxx5648
-rw-r--r--src/devices/cpu/e132xs/e132xsfe.cpp359
-rw-r--r--src/devices/cpu/e132xs/e132xsfe.h20
-rw-r--r--src/devices/cpu/e132xs/e132xsop.hxx1290
-rw-r--r--src/devices/cpu/es5510/es5510.cpp364
-rw-r--r--src/devices/cpu/es5510/es5510.h20
-rw-r--r--src/devices/cpu/es5510/es5510d.h6
-rw-r--r--src/devices/cpu/esrip/esrip.cpp44
-rw-r--r--src/devices/cpu/esrip/esrip.h27
-rw-r--r--src/devices/cpu/evolution/evo.cpp52
-rw-r--r--src/devices/cpu/evolution/evo.h39
-rw-r--r--src/devices/cpu/evolution/evod.cpp345
-rw-r--r--src/devices/cpu/evolution/evod.h34
-rw-r--r--src/devices/cpu/f2mc16/f2mc16.cpp3895
-rw-r--r--src/devices/cpu/f2mc16/f2mc16.h304
-rw-r--r--src/devices/cpu/f2mc16/f2mc16_adc.cpp304
-rw-r--r--src/devices/cpu/f2mc16/f2mc16_adc.h72
-rw-r--r--src/devices/cpu/f2mc16/f2mc16_clock.cpp355
-rw-r--r--src/devices/cpu/f2mc16/f2mc16_clock.h74
-rw-r--r--src/devices/cpu/f2mc16/f2mc16_intc.cpp269
-rw-r--r--src/devices/cpu/f2mc16/f2mc16_intc.h64
-rw-r--r--src/devices/cpu/f2mc16/f2mc16_port.cpp127
-rw-r--r--src/devices/cpu/f2mc16/f2mc16_port.h57
-rw-r--r--src/devices/cpu/f2mc16/f2mc16_ppg.cpp348
-rw-r--r--src/devices/cpu/f2mc16/f2mc16_ppg.h70
-rw-r--r--src/devices/cpu/f2mc16/f2mc16_reload.cpp381
-rw-r--r--src/devices/cpu/f2mc16/f2mc16_reload.h75
-rw-r--r--src/devices/cpu/f2mc16/f2mc16_uart.cpp456
-rw-r--r--src/devices/cpu/f2mc16/f2mc16_uart.h98
-rw-r--r--src/devices/cpu/f2mc16/f2mc16d.cpp1641
-rw-r--r--src/devices/cpu/f2mc16/f2mc16d.h62
-rw-r--r--src/devices/cpu/f2mc16/f2mc16dasm.cpp1705
-rw-r--r--src/devices/cpu/f2mc16/f2mc16dasm.h28
-rw-r--r--src/devices/cpu/f2mc16/mb90570.cpp169
-rw-r--r--src/devices/cpu/f2mc16/mb90570.h55
-rw-r--r--src/devices/cpu/f2mc16/mb90610a.cpp138
-rw-r--r--src/devices/cpu/f2mc16/mb90610a.h59
-rw-r--r--src/devices/cpu/f2mc16/mb9061x.cpp422
-rw-r--r--src/devices/cpu/f2mc16/mb9061x.h103
-rw-r--r--src/devices/cpu/f2mc16/mb90640a.cpp134
-rw-r--r--src/devices/cpu/f2mc16/mb90640a.h52
-rw-r--r--src/devices/cpu/f8/f8.cpp267
-rw-r--r--src/devices/cpu/f8/f8.h46
-rw-r--r--src/devices/cpu/f8/f8dasm.cpp193
-rw-r--r--src/devices/cpu/fr/fr.cpp141
-rw-r--r--src/devices/cpu/fr/fr.h72
-rw-r--r--src/devices/cpu/fr/frdasm.cpp977
-rw-r--r--src/devices/cpu/fr/frdasm.h49
-rw-r--r--src/devices/cpu/g65816/g65816.cpp264
-rw-r--r--src/devices/cpu/g65816/g65816.h115
-rw-r--r--src/devices/cpu/g65816/g65816cm.h29
-rw-r--r--src/devices/cpu/g65816/g65816ds.cpp78
-rw-r--r--src/devices/cpu/g65816/g65816ds.h40
-rw-r--r--src/devices/cpu/g65816/g65816o0.cpp3
-rw-r--r--src/devices/cpu/g65816/g65816o1.cpp3
-rw-r--r--src/devices/cpu/g65816/g65816o2.cpp3
-rw-r--r--src/devices/cpu/g65816/g65816o3.cpp3
-rw-r--r--src/devices/cpu/g65816/g65816o4.cpp3
-rw-r--r--src/devices/cpu/g65816/g65816op.ipp (renamed from src/devices/cpu/g65816/g65816op.h)61
-rw-r--r--src/devices/cpu/gigatron/gigatron.cpp378
-rw-r--r--src/devices/cpu/gigatron/gigatron.h95
-rw-r--r--src/devices/cpu/gigatron/gigatrondasm.cpp161
-rw-r--r--src/devices/cpu/gigatron/gigatrondasm.h26
-rw-r--r--src/devices/cpu/h16/h16dasm.cpp1063
-rw-r--r--src/devices/cpu/h16/h16dasm.h55
-rw-r--r--src/devices/cpu/h16/hd641016.cpp235
-rw-r--r--src/devices/cpu/h16/hd641016.h142
-rw-r--r--src/devices/cpu/h6280/6280dasm.cpp2
-rw-r--r--src/devices/cpu/h6280/h6280.cpp96
-rw-r--r--src/devices/cpu/h6280/h6280.h41
-rw-r--r--src/devices/cpu/h8/c77.cpp216
-rw-r--r--src/devices/cpu/h8/c77.h95
-rw-r--r--src/devices/cpu/h8/gt913.cpp294
-rw-r--r--src/devices/cpu/h8/gt913.h114
-rw-r--r--src/devices/cpu/h8/gt913.lst282
-rw-r--r--src/devices/cpu/h8/gt913d.cpp17
-rw-r--r--src/devices/cpu/h8/gt913d.h28
-rw-r--r--src/devices/cpu/h8/h8.cpp1588
-rw-r--r--src/devices/cpu/h8/h8.h467
-rw-r--r--src/devices/cpu/h8/h8.lst3665
-rw-r--r--src/devices/cpu/h8/h83002.cpp379
-rw-r--r--src/devices/cpu/h8/h83002.h101
-rw-r--r--src/devices/cpu/h8/h83003.cpp422
-rw-r--r--src/devices/cpu/h8/h83003.h112
-rw-r--r--src/devices/cpu/h8/h83006.cpp357
-rw-r--r--src/devices/cpu/h8/h83006.h90
-rw-r--r--src/devices/cpu/h8/h83008.cpp319
-rw-r--r--src/devices/cpu/h8/h83008.h81
-rw-r--r--src/devices/cpu/h8/h83032.cpp265
-rw-r--r--src/devices/cpu/h8/h83032.h112
-rw-r--r--src/devices/cpu/h8/h83042.cpp301
-rw-r--r--src/devices/cpu/h8/h83042.h120
-rw-r--r--src/devices/cpu/h8/h83048.cpp377
-rw-r--r--src/devices/cpu/h8/h83048.h111
-rw-r--r--src/devices/cpu/h8/h83217.cpp282
-rw-r--r--src/devices/cpu/h8/h83217.h120
-rw-r--r--src/devices/cpu/h8/h8325.cpp252
-rw-r--r--src/devices/cpu/h8/h8325.h126
-rw-r--r--src/devices/cpu/h8/h83337.cpp313
-rw-r--r--src/devices/cpu/h8/h83337.h101
-rw-r--r--src/devices/cpu/h8/h8_adc.cpp445
-rw-r--r--src/devices/cpu/h8/h8_adc.h99
-rw-r--r--src/devices/cpu/h8/h8_dma.cpp884
-rw-r--r--src/devices/cpu/h8/h8_dma.h312
-rw-r--r--src/devices/cpu/h8/h8_dtc.cpp228
-rw-r--r--src/devices/cpu/h8/h8_dtc.h53
-rw-r--r--src/devices/cpu/h8/h8_intc.cpp421
-rw-r--r--src/devices/cpu/h8/h8_intc.h155
-rw-r--r--src/devices/cpu/h8/h8_port.cpp130
-rw-r--r--src/devices/cpu/h8/h8_port.h50
-rw-r--r--src/devices/cpu/h8/h8_sci.cpp1037
-rw-r--r--src/devices/cpu/h8/h8_sci.h114
-rw-r--r--src/devices/cpu/h8/h8_timer16.cpp768
-rw-r--r--src/devices/cpu/h8/h8_timer16.h281
-rw-r--r--src/devices/cpu/h8/h8_timer8.cpp427
-rw-r--r--src/devices/cpu/h8/h8_timer8.h92
-rw-r--r--src/devices/cpu/h8/h8_watchdog.cpp147
-rw-r--r--src/devices/cpu/h8/h8_watchdog.h74
-rw-r--r--src/devices/cpu/h8/h8d.cpp54
-rw-r--r--src/devices/cpu/h8/h8d.h22
-rw-r--r--src/devices/cpu/h8/h8h.cpp6
-rw-r--r--src/devices/cpu/h8/h8h.h51
-rw-r--r--src/devices/cpu/h8/h8hd.cpp2
-rw-r--r--src/devices/cpu/h8/h8make.py67
-rw-r--r--src/devices/cpu/h8/h8s2000.cpp4
-rw-r--r--src/devices/cpu/h8/h8s2000.h23
-rw-r--r--src/devices/cpu/h8/h8s2000d.cpp2
-rw-r--r--src/devices/cpu/h8/h8s2245.cpp496
-rw-r--r--src/devices/cpu/h8/h8s2245.h112
-rw-r--r--src/devices/cpu/h8/h8s2319.cpp473
-rw-r--r--src/devices/cpu/h8/h8s2319.h164
-rw-r--r--src/devices/cpu/h8/h8s2320.cpp457
-rw-r--r--src/devices/cpu/h8/h8s2320.h153
-rw-r--r--src/devices/cpu/h8/h8s2329.cpp179
-rw-r--r--src/devices/cpu/h8/h8s2329.h121
-rw-r--r--src/devices/cpu/h8/h8s2357.cpp603
-rw-r--r--src/devices/cpu/h8/h8s2357.h122
-rw-r--r--src/devices/cpu/h8/h8s2600.cpp18
-rw-r--r--src/devices/cpu/h8/h8s2600.h7
-rw-r--r--src/devices/cpu/h8/h8s2600d.cpp2
-rw-r--r--src/devices/cpu/h8/h8s2655.cpp647
-rw-r--r--src/devices/cpu/h8/h8s2655.h112
-rw-r--r--src/devices/cpu/h8/swx00.cpp565
-rw-r--r--src/devices/cpu/h8/swx00.h152
-rw-r--r--src/devices/cpu/h8500/h8500.cpp140
-rw-r--r--src/devices/cpu/h8500/h8500.h74
-rw-r--r--src/devices/cpu/h8500/h8500dasm.cpp578
-rw-r--r--src/devices/cpu/h8500/h8500dasm.h46
-rw-r--r--src/devices/cpu/h8500/h8510.cpp112
-rw-r--r--src/devices/cpu/h8500/h8510.h29
-rw-r--r--src/devices/cpu/h8500/h8520.cpp116
-rw-r--r--src/devices/cpu/h8500/h8520.h37
-rw-r--r--src/devices/cpu/h8500/h8532.cpp128
-rw-r--r--src/devices/cpu/h8500/h8532.h37
-rw-r--r--src/devices/cpu/h8500/h8534.cpp179
-rw-r--r--src/devices/cpu/h8500/h8534.h66
-rw-r--r--src/devices/cpu/hcd62121/hcd62121.cpp692
-rw-r--r--src/devices/cpu/hcd62121/hcd62121.h33
-rw-r--r--src/devices/cpu/hcd62121/hcd62121d.cpp48
-rw-r--r--src/devices/cpu/hcd62121/hcd62121d.h2
-rw-r--r--src/devices/cpu/hd61700/hd61700.cpp831
-rw-r--r--src/devices/cpu/hd61700/hd61700.h50
-rw-r--r--src/devices/cpu/hd61700/hd61700d.cpp16
-rw-r--r--src/devices/cpu/hmcs40/hmcs40.cpp893
-rw-r--r--src/devices/cpu/hmcs40/hmcs40.h223
-rw-r--r--src/devices/cpu/hmcs40/hmcs40d.cpp75
-rw-r--r--src/devices/cpu/hmcs40/hmcs40d.h24
-rw-r--r--src/devices/cpu/hmcs40/hmcs40op.cpp92
-rw-r--r--src/devices/cpu/hmcs400/hmcs400.cpp1024
-rw-r--r--src/devices/cpu/hmcs400/hmcs400.h557
-rw-r--r--src/devices/cpu/hmcs400/hmcs400d.cpp237
-rw-r--r--src/devices/cpu/hmcs400/hmcs400d.h31
-rw-r--r--src/devices/cpu/hmcs400/hmcs400op.cpp692
-rw-r--r--src/devices/cpu/hp2100/hp2100d.cpp656
-rw-r--r--src/devices/cpu/hp2100/hp2100d.h50
-rw-r--r--src/devices/cpu/hpc/hpc.h8
-rw-r--r--src/devices/cpu/hpc/hpcdasm.cpp48
-rw-r--r--src/devices/cpu/hphybrid/hphybrid.cpp71
-rw-r--r--src/devices/cpu/hphybrid/hphybrid.h55
-rw-r--r--src/devices/cpu/hphybrid/hphybrid_dasm.cpp64
-rw-r--r--src/devices/cpu/ht1130/ht1130.cpp1129
-rw-r--r--src/devices/cpu/ht1130/ht1130.h144
-rw-r--r--src/devices/cpu/ht1130/ht1130d.cpp667
-rw-r--r--src/devices/cpu/ht1130/ht1130d.h22
-rw-r--r--src/devices/cpu/i386/athlon.cpp129
-rw-r--r--src/devices/cpu/i386/athlon.h13
-rw-r--r--src/devices/cpu/i386/cpuidmsrs.hxx32
-rw-r--r--src/devices/cpu/i386/cycles.h8
-rw-r--r--src/devices/cpu/i386/i386.cpp342
-rw-r--r--src/devices/cpu/i386/i386.h152
-rw-r--r--src/devices/cpu/i386/i386dasm.cpp66
-rw-r--r--src/devices/cpu/i386/i386dasm.h8
-rw-r--r--src/devices/cpu/i386/i386op16.hxx24
-rw-r--r--src/devices/cpu/i386/i386op32.hxx26
-rw-r--r--src/devices/cpu/i386/i386ops.h6
-rw-r--r--src/devices/cpu/i386/i386ops.hxx28
-rw-r--r--src/devices/cpu/i386/i386priv.h16
-rw-r--r--src/devices/cpu/i386/i386segs.hxx569
-rw-r--r--src/devices/cpu/i386/i486ops.hxx36
-rw-r--r--src/devices/cpu/i386/pentops.hxx672
-rw-r--r--src/devices/cpu/i386/x87ops.hxx1001
-rw-r--r--src/devices/cpu/i386/x87priv.h11
-rw-r--r--src/devices/cpu/i8008/8008dasm.cpp10
-rw-r--r--src/devices/cpu/i8008/i8008.cpp31
-rw-r--r--src/devices/cpu/i8008/i8008.h14
-rw-r--r--src/devices/cpu/i8085/8085dasm.cpp66
-rw-r--r--src/devices/cpu/i8085/i8085.cpp526
-rw-r--r--src/devices/cpu/i8085/i8085.h114
-rw-r--r--src/devices/cpu/i8089/i8089.cpp16
-rw-r--r--src/devices/cpu/i8089/i8089.h22
-rw-r--r--src/devices/cpu/i8089/i8089_channel.cpp16
-rw-r--r--src/devices/cpu/i8089/i8089_channel.h14
-rw-r--r--src/devices/cpu/i8089/i8089_dasm.cpp49
-rw-r--r--src/devices/cpu/i8089/i8089_dasm.h36
-rw-r--r--src/devices/cpu/i86/i186.cpp1116
-rw-r--r--src/devices/cpu/i86/i186.h80
-rw-r--r--src/devices/cpu/i86/i286.cpp50
-rw-r--r--src/devices/cpu/i86/i286.h23
-rw-r--r--src/devices/cpu/i86/i86.cpp92
-rw-r--r--src/devices/cpu/i86/i86.h19
-rw-r--r--src/devices/cpu/i86/i86inline.h2
-rw-r--r--src/devices/cpu/i860/i860.cpp1
-rw-r--r--src/devices/cpu/i860/i860.h10
-rw-r--r--src/devices/cpu/i860/i860dec.hxx44
-rw-r--r--src/devices/cpu/i960/i960.cpp282
-rw-r--r--src/devices/cpu/i960/i960.h30
-rw-r--r--src/devices/cpu/i960/i960dis.cpp696
-rw-r--r--src/devices/cpu/i960/i960dis.h14
-rw-r--r--src/devices/cpu/ibm1800/ibm1800d.cpp258
-rw-r--r--src/devices/cpu/ibm1800/ibm1800d.h35
-rw-r--r--src/devices/cpu/ie15/ie15.cpp29
-rw-r--r--src/devices/cpu/ie15/ie15.h14
-rw-r--r--src/devices/cpu/interdata16/dasm16.cpp428
-rw-r--r--src/devices/cpu/interdata16/dasm16.h25
-rw-r--r--src/devices/cpu/jaguar/jagdasm.cpp2
-rw-r--r--src/devices/cpu/jaguar/jaguar.cpp591
-rw-r--r--src/devices/cpu/jaguar/jaguar.h141
-rw-r--r--src/devices/cpu/ks0164/ks0164.cpp771
-rw-r--r--src/devices/cpu/ks0164/ks0164.h73
-rw-r--r--src/devices/cpu/ks0164/ks0164d.cpp245
-rw-r--r--src/devices/cpu/ks0164/ks0164d.h35
-rw-r--r--src/devices/cpu/lc57/lc57d.cpp131
-rw-r--r--src/devices/cpu/lc57/lc57d.h30
-rw-r--r--src/devices/cpu/lc58/lc58d.cpp160
-rw-r--r--src/devices/cpu/lc58/lc58d.h30
-rw-r--r--src/devices/cpu/lc8670/lc8670.cpp306
-rw-r--r--src/devices/cpu/lc8670/lc8670.h56
-rw-r--r--src/devices/cpu/lc8670/lc8670dsm.cpp2
-rw-r--r--src/devices/cpu/lh5801/5801dasm.cpp12
-rw-r--r--src/devices/cpu/lh5801/5801tbl.hxx1752
-rw-r--r--src/devices/cpu/lh5801/lh5801.cpp41
-rw-r--r--src/devices/cpu/lh5801/lh5801.h28
-rw-r--r--src/devices/cpu/lr35902/lr35902.cpp10
-rw-r--r--src/devices/cpu/lr35902/lr35902.h10
-rw-r--r--src/devices/cpu/lr35902/lr35902d.cpp34
-rw-r--r--src/devices/cpu/lr35902/lr35902d.h6
-rw-r--r--src/devices/cpu/lr35902/opc_main.hxx1
-rw-r--r--src/devices/cpu/m16c/m16cdasm.cpp1225
-rw-r--r--src/devices/cpu/m16c/m16cdasm.h52
-rw-r--r--src/devices/cpu/m32c/m32cdasm.cpp1245
-rw-r--r--src/devices/cpu/m32c/m32cdasm.h57
-rw-r--r--src/devices/cpu/m37710/m37710.cpp557
-rw-r--r--src/devices/cpu/m37710/m37710.h108
-rw-r--r--src/devices/cpu/m37710/m37710cm.h137
-rw-r--r--src/devices/cpu/m37710/m37710il.h37
-rw-r--r--src/devices/cpu/m37710/m37710o0.cpp3
-rw-r--r--src/devices/cpu/m37710/m37710o1.cpp3
-rw-r--r--src/devices/cpu/m37710/m37710o2.cpp3
-rw-r--r--src/devices/cpu/m37710/m37710o3.cpp3
-rw-r--r--src/devices/cpu/m37710/m37710op.h180
-rw-r--r--src/devices/cpu/m37710/m7700ds.cpp18
-rw-r--r--src/devices/cpu/m37710/m7700ds.h10
-rw-r--r--src/devices/cpu/m6502/deco16.cpp7
-rw-r--r--src/devices/cpu/m6502/deco16.h2
-rw-r--r--src/devices/cpu/m6502/dm6502.lst2
-rw-r--r--src/devices/cpu/m6502/dm740.lst64
-rw-r--r--src/devices/cpu/m6502/dr65c19.lst20
-rw-r--r--src/devices/cpu/m6502/drp2a03.lst (renamed from src/devices/cpu/m6502/dn2a03.lst)2
-rw-r--r--src/devices/cpu/m6502/dw65c02.lst (renamed from src/devices/cpu/m6502/dm65c02.lst)2
-rw-r--r--src/devices/cpu/m6502/dw65c02s.lst20
-rw-r--r--src/devices/cpu/m6502/g65sc02.cpp46
-rw-r--r--src/devices/cpu/m6502/g65sc02.h54
-rw-r--r--src/devices/cpu/m6502/gew12.cpp229
-rw-r--r--src/devices/cpu/m6502/gew12.h78
-rw-r--r--src/devices/cpu/m6502/gew7.cpp216
-rw-r--r--src/devices/cpu/m6502/gew7.h74
-rw-r--r--src/devices/cpu/m6502/m3745x.cpp59
-rw-r--r--src/devices/cpu/m6502/m3745x.h39
-rw-r--r--src/devices/cpu/m6502/m37640.cpp31
-rw-r--r--src/devices/cpu/m6502/m37640.h38
-rw-r--r--src/devices/cpu/m6502/m4510.cpp118
-rw-r--r--src/devices/cpu/m6502/m4510.h39
-rw-r--r--src/devices/cpu/m6502/m50734.cpp473
-rw-r--r--src/devices/cpu/m6502/m50734.h160
-rw-r--r--src/devices/cpu/m6502/m5074x.cpp342
-rw-r--r--src/devices/cpu/m6502/m5074x.h106
-rw-r--r--src/devices/cpu/m6502/m6500_1.cpp98
-rw-r--r--src/devices/cpu/m6502/m6500_1.h59
-rw-r--r--src/devices/cpu/m6502/m6502.cpp192
-rw-r--r--src/devices/cpu/m6502/m6502.h94
-rw-r--r--src/devices/cpu/m6502/m6502.txt18
-rw-r--r--src/devices/cpu/m6502/m6502d.cpp22
-rw-r--r--src/devices/cpu/m6502/m6502d.h4
-rwxr-xr-xsrc/devices/cpu/m6502/m6502make.py157
-rw-r--r--src/devices/cpu/m6502/m6502mcu.h37
-rw-r--r--src/devices/cpu/m6502/m6502mcu.ipp75
-rw-r--r--src/devices/cpu/m6502/m6503.cpp25
-rw-r--r--src/devices/cpu/m6502/m6503.h28
-rw-r--r--src/devices/cpu/m6502/m6504.cpp48
-rw-r--r--src/devices/cpu/m6502/m6504.h23
-rw-r--r--src/devices/cpu/m6502/m6507.cpp48
-rw-r--r--src/devices/cpu/m6502/m6507.h23
-rw-r--r--src/devices/cpu/m6502/m6509.cpp59
-rw-r--r--src/devices/cpu/m6502/m6509.h18
-rw-r--r--src/devices/cpu/m6502/m6510.cpp118
-rw-r--r--src/devices/cpu/m6502/m6510.h35
-rw-r--r--src/devices/cpu/m6502/m6510t.cpp4
-rw-r--r--src/devices/cpu/m6502/m65c02.cpp33
-rw-r--r--src/devices/cpu/m6502/m65ce02.cpp15
-rw-r--r--src/devices/cpu/m6502/m65ce02.h8
-rw-r--r--src/devices/cpu/m6502/m65sc02.cpp19
-rw-r--r--src/devices/cpu/m6502/m65sc02.h29
-rw-r--r--src/devices/cpu/m6502/m740.cpp52
-rw-r--r--src/devices/cpu/m6502/m740.h66
-rw-r--r--src/devices/cpu/m6502/m7501.cpp4
-rw-r--r--src/devices/cpu/m6502/m8502.cpp4
-rw-r--r--src/devices/cpu/m6502/n2a03.cpp87
-rw-r--r--src/devices/cpu/m6502/n2a03.h74
-rw-r--r--src/devices/cpu/m6502/odeco16.lst28
-rw-r--r--src/devices/cpu/m6502/om6502.lst556
-rw-r--r--src/devices/cpu/m6502/om6509.lst2
-rw-r--r--src/devices/cpu/m6502/om6510.lst7
-rw-r--r--src/devices/cpu/m6502/om65ce02.lst451
-rw-r--r--src/devices/cpu/m6502/om740.lst1770
-rw-r--r--src/devices/cpu/m6502/or65c19.lst488
-rw-r--r--src/devices/cpu/m6502/orp2a03.lst (renamed from src/devices/cpu/m6502/on2a03.lst)100
-rw-r--r--src/devices/cpu/m6502/ow65c02.lst (renamed from src/devices/cpu/m6502/om65c02.lst)286
-rw-r--r--src/devices/cpu/m6502/ow65c02s.lst968
-rw-r--r--src/devices/cpu/m6502/oxavix.lst209
-rw-r--r--src/devices/cpu/m6502/oxavix2000.lst201
-rw-r--r--src/devices/cpu/m6502/r65c02.cpp22
-rw-r--r--src/devices/cpu/m6502/r65c02.h20
-rw-r--r--src/devices/cpu/m6502/r65c19.cpp290
-rw-r--r--src/devices/cpu/m6502/r65c19.h165
-rw-r--r--src/devices/cpu/m6502/r65c19d.cpp10
-rw-r--r--src/devices/cpu/m6502/r65c19d.h21
-rw-r--r--src/devices/cpu/m6502/rp2a03.cpp99
-rw-r--r--src/devices/cpu/m6502/rp2a03.h91
-rw-r--r--src/devices/cpu/m6502/rp2a03d.cpp (renamed from src/devices/cpu/m6502/n2a03d.cpp)8
-rw-r--r--src/devices/cpu/m6502/rp2a03d.h (renamed from src/devices/cpu/m6502/n2a03d.h)12
-rw-r--r--src/devices/cpu/m6502/st2204.cpp728
-rw-r--r--src/devices/cpu/m6502/st2204.h163
-rw-r--r--src/devices/cpu/m6502/st2205u.cpp1354
-rw-r--r--src/devices/cpu/m6502/st2205u.h318
-rw-r--r--src/devices/cpu/m6502/st2xxx.cpp914
-rw-r--r--src/devices/cpu/m6502/st2xxx.h299
-rw-r--r--src/devices/cpu/m6502/w65c02.cpp33
-rw-r--r--src/devices/cpu/m6502/w65c02.h (renamed from src/devices/cpu/m6502/m65c02.h)24
-rw-r--r--src/devices/cpu/m6502/w65c02d.cpp (renamed from src/devices/cpu/m6502/m65c02d.cpp)10
-rw-r--r--src/devices/cpu/m6502/w65c02d.h (renamed from src/devices/cpu/m6502/m65c02d.h)14
-rw-r--r--src/devices/cpu/m6502/w65c02s.cpp33
-rw-r--r--src/devices/cpu/m6502/w65c02s.h71
-rw-r--r--src/devices/cpu/m6502/xavix.cpp102
-rw-r--r--src/devices/cpu/m6502/xavix.h50
-rw-r--r--src/devices/cpu/m6502/xavix2000.cpp14
-rw-r--r--src/devices/cpu/m6502/xavix2000.h2
-rw-r--r--src/devices/cpu/m6800/6800dasm.cpp32
-rw-r--r--src/devices/cpu/m6800/6800dasm.h14
-rw-r--r--src/devices/cpu/m6800/6800ops.hxx386
-rw-r--r--src/devices/cpu/m6800/6800tbl.hxx95
-rw-r--r--src/devices/cpu/m6800/m6800.cpp366
-rw-r--r--src/devices/cpu/m6800/m6800.h117
-rw-r--r--src/devices/cpu/m6800/m6801.cpp2503
-rw-r--r--src/devices/cpu/m6800/m6801.h512
-rw-r--r--src/devices/cpu/m68000/fscpu32.cpp24
-rw-r--r--src/devices/cpu/m68000/fscpu32.h26
-rw-r--r--src/devices/cpu/m68000/m68000-decode.cpp1537
-rw-r--r--src/devices/cpu/m68000/m68000-head.h6144
-rw-r--r--src/devices/cpu/m68000/m68000-sdf.cpp185362
-rw-r--r--src/devices/cpu/m68000/m68000-sdp.cpp209705
-rw-r--r--src/devices/cpu/m68000/m68000-sif.cpp185362
-rw-r--r--src/devices/cpu/m68000/m68000-sip.cpp209705
-rw-r--r--src/devices/cpu/m68000/m68000.cpp488
-rw-r--r--src/devices/cpu/m68000/m68000.h1397
-rw-r--r--src/devices/cpu/m68000/m68000.lst1528
-rwxr-xr-xsrc/devices/cpu/m68000/m68000gen.py2569
-rw-r--r--src/devices/cpu/m68000/m68000mcu-head.h6144
-rw-r--r--src/devices/cpu/m68000/m68000mcu-sdfm.cpp185362
-rw-r--r--src/devices/cpu/m68000/m68000mcu-sdpm.cpp209705
-rw-r--r--src/devices/cpu/m68000/m68000mcu-sifm.cpp185362
-rw-r--r--src/devices/cpu/m68000/m68000mcu-sipm.cpp209705
-rw-r--r--src/devices/cpu/m68000/m68000mcu.cpp109
-rw-r--r--src/devices/cpu/m68000/m68000mcu.h36
-rw-r--r--src/devices/cpu/m68000/m68000musashi.cpp25
-rw-r--r--src/devices/cpu/m68000/m68000musashi.h27
-rw-r--r--src/devices/cpu/m68000/m68008-head.h6144
-rw-r--r--src/devices/cpu/m68000/m68008-sdf8.cpp239440
-rw-r--r--src/devices/cpu/m68000/m68008-sdp8.cpp274776
-rw-r--r--src/devices/cpu/m68000/m68008-sif8.cpp239440
-rw-r--r--src/devices/cpu/m68000/m68008-sip8.cpp274776
-rw-r--r--src/devices/cpu/m68000/m68008.cpp102
-rw-r--r--src/devices/cpu/m68000/m68008.h76
-rw-r--r--src/devices/cpu/m68000/m68010.cpp30
-rw-r--r--src/devices/cpu/m68000/m68010.h28
-rw-r--r--src/devices/cpu/m68000/m68020.cpp112
-rw-r--r--src/devices/cpu/m68000/m68020.h93
-rw-r--r--src/devices/cpu/m68000/m68030.cpp42
-rw-r--r--src/devices/cpu/m68000/m68030.h43
-rw-r--r--src/devices/cpu/m68000/m68040.cpp64
-rw-r--r--src/devices/cpu/m68000/m68040.h59
-rw-r--r--src/devices/cpu/m68000/m68k_in.lst1022
-rw-r--r--src/devices/cpu/m68000/m68kcommon.cpp19
-rw-r--r--src/devices/cpu/m68000/m68kcommon.h75
-rw-r--r--src/devices/cpu/m68000/m68kcpu.cpp1164
-rw-r--r--src/devices/cpu/m68000/m68kcpu.h104
-rw-r--r--src/devices/cpu/m68000/m68kdasm.cpp61
-rw-r--r--src/devices/cpu/m68000/m68kdasm.h15
-rw-r--r--src/devices/cpu/m68000/m68kfpu.cpp (renamed from src/devices/cpu/m68000/m68kfpu.hxx)1040
-rwxr-xr-xsrc/devices/cpu/m68000/m68kmake.py14
-rw-r--r--src/devices/cpu/m68000/m68kmmu.h19
-rw-r--r--src/devices/cpu/m68000/m68kmusashi.h385
-rw-r--r--src/devices/cpu/m68000/m68kops.cpp11990
-rw-r--r--src/devices/cpu/m68000/mcf5206e.cpp24
-rw-r--r--src/devices/cpu/m68000/mcf5206e.h28
-rw-r--r--src/devices/cpu/m68000/scc68070.cpp54
-rw-r--r--src/devices/cpu/m68000/scc68070.h30
-rw-r--r--src/devices/cpu/m68000/tmp68301.cpp1335
-rw-r--r--src/devices/cpu/m68000/tmp68301.h320
-rw-r--r--src/devices/cpu/m6805/6805dasm.cpp24
-rw-r--r--src/devices/cpu/m6805/6805ops.hxx66
-rw-r--r--src/devices/cpu/m6805/hd6305.cpp623
-rw-r--r--src/devices/cpu/m6805/hd6305.h229
-rw-r--r--src/devices/cpu/m6805/m6805.cpp450
-rw-r--r--src/devices/cpu/m6805/m6805.h296
-rw-r--r--src/devices/cpu/m6805/m6805defs.h54
-rw-r--r--src/devices/cpu/m6805/m68705.cpp194
-rw-r--r--src/devices/cpu/m6805/m68705.h136
-rw-r--r--src/devices/cpu/m6805/m68hc05.cpp269
-rw-r--r--src/devices/cpu/m6805/m68hc05.h124
-rw-r--r--src/devices/cpu/m6805/m68hc05e1.cpp294
-rw-r--r--src/devices/cpu/m6805/m68hc05e1.h99
-rw-r--r--src/devices/cpu/m6805/m68hc05pge.cpp926
-rw-r--r--src/devices/cpu/m6805/m68hc05pge.h150
-rw-r--r--src/devices/cpu/m6809/6x09dasm.cpp1706
-rw-r--r--src/devices/cpu/m6809/6x09dasm.h83
-rw-r--r--src/devices/cpu/m6809/base6x09.lst (renamed from src/devices/cpu/m6809/base6x09.ops)337
-rw-r--r--src/devices/cpu/m6809/hd6309.cpp90
-rw-r--r--src/devices/cpu/m6809/hd6309.h32
-rw-r--r--src/devices/cpu/m6809/hd6309.lst1088
-rw-r--r--src/devices/cpu/m6809/hd6309.ops1087
-rw-r--r--src/devices/cpu/m6809/konami.cpp130
-rw-r--r--src/devices/cpu/m6809/konami.h16
-rw-r--r--src/devices/cpu/m6809/konami.lst632
-rw-r--r--src/devices/cpu/m6809/konami.ops607
-rw-r--r--src/devices/cpu/m6809/m6809.cpp153
-rw-r--r--src/devices/cpu/m6809/m6809.h112
-rw-r--r--src/devices/cpu/m6809/m6809.lst758
-rw-r--r--src/devices/cpu/m6809/m6809.ops582
-rw-r--r--src/devices/cpu/m6809/m6809inl.h23
-rw-r--r--src/devices/cpu/m6809/m6809make.py15
-rw-r--r--src/devices/cpu/m68hc16/cpu16.cpp5451
-rw-r--r--src/devices/cpu/m68hc16/cpu16.h129
-rw-r--r--src/devices/cpu/m68hc16/cpu16dasm.cpp1404
-rw-r--r--src/devices/cpu/m68hc16/cpu16dasm.h59
-rw-r--r--src/devices/cpu/m68hc16/m68hc16z.cpp450
-rw-r--r--src/devices/cpu/m68hc16/m68hc16z.h105
-rw-r--r--src/devices/cpu/m88000/m88000.cpp1831
-rw-r--r--src/devices/cpu/m88000/m88000.h95
-rw-r--r--src/devices/cpu/m88000/m88000d.cpp1274
-rw-r--r--src/devices/cpu/m88000/m88000d.h106
-rw-r--r--src/devices/cpu/mb86233/mb86233.cpp213
-rw-r--r--src/devices/cpu/mb86233/mb86233.h34
-rw-r--r--src/devices/cpu/mb86233/mb86233d.cpp13
-rw-r--r--src/devices/cpu/mb86235/mb86235.cpp12
-rw-r--r--src/devices/cpu/mb86235/mb86235.h32
-rw-r--r--src/devices/cpu/mb86235/mb86235d.cpp32
-rw-r--r--src/devices/cpu/mb86235/mb86235d.h2
-rw-r--r--src/devices/cpu/mb86235/mb86235drc.cpp15
-rw-r--r--src/devices/cpu/mb86235/mb86235fe.cpp4
-rw-r--r--src/devices/cpu/mb86235/mb86235fe.h9
-rw-r--r--src/devices/cpu/mb86235/mb86235ops.cpp17
-rw-r--r--src/devices/cpu/mb88xx/mb88dasm.cpp321
-rw-r--r--src/devices/cpu/mb88xx/mb88dasm.h6
-rw-r--r--src/devices/cpu/mb88xx/mb88xx.cpp565
-rw-r--r--src/devices/cpu/mb88xx/mb88xx.h171
-rw-r--r--src/devices/cpu/mc68hc11/hc11dasm.cpp4
-rw-r--r--src/devices/cpu/mc68hc11/hc11ops.h4
-rw-r--r--src/devices/cpu/mc68hc11/hc11ops.hxx82
-rw-r--r--src/devices/cpu/mc68hc11/mc68hc11.cpp1052
-rw-r--r--src/devices/cpu/mc68hc11/mc68hc11.h168
-rw-r--r--src/devices/cpu/mcs40/mcs40.cpp95
-rw-r--r--src/devices/cpu/mcs40/mcs40.h27
-rw-r--r--src/devices/cpu/mcs40/mcs40dasm.cpp4
-rw-r--r--src/devices/cpu/mcs48/mcs48.cpp1398
-rw-r--r--src/devices/cpu/mcs48/mcs48.h815
-rw-r--r--src/devices/cpu/mcs48/mcs48dsm.cpp63
-rw-r--r--src/devices/cpu/mcs48/mcs48dsm.h9
-rw-r--r--src/devices/cpu/mcs51/axc51-core.cpp69
-rw-r--r--src/devices/cpu/mcs51/axc51-core.h46
-rw-r--r--src/devices/cpu/mcs51/axc51-core_dasm.h63
-rw-r--r--src/devices/cpu/mcs51/mcs51.cpp1569
-rw-r--r--src/devices/cpu/mcs51/mcs51.h313
-rw-r--r--src/devices/cpu/mcs51/mcs51dasm.cpp492
-rw-r--r--src/devices/cpu/mcs51/mcs51dasm.h68
-rw-r--r--src/devices/cpu/mcs51/mcs51ops.hxx512
-rw-r--r--src/devices/cpu/mcs96/i8x9x.cpp199
-rw-r--r--src/devices/cpu/mcs96/i8x9x.h68
-rw-r--r--src/devices/cpu/mcs96/i8xc196.cpp2
-rw-r--r--src/devices/cpu/mcs96/i8xc196.h2
-rw-r--r--src/devices/cpu/mcs96/mcs96.cpp58
-rw-r--r--src/devices/cpu/mcs96/mcs96.h17
-rw-r--r--src/devices/cpu/mcs96/mcs96d.cpp4
-rw-r--r--src/devices/cpu/mcs96/mcs96make.py9
-rw-r--r--src/devices/cpu/mcs96/mcs96ops.lst10
-rw-r--r--src/devices/cpu/melps4/m58846.cpp15
-rw-r--r--src/devices/cpu/melps4/m58846.h14
-rw-r--r--src/devices/cpu/melps4/melps4.cpp111
-rw-r--r--src/devices/cpu/melps4/melps4.h98
-rw-r--r--src/devices/cpu/melps4/melps4d.cpp118
-rw-r--r--src/devices/cpu/melps4/melps4d.h37
-rw-r--r--src/devices/cpu/melps4/melps4op.cpp30
-rw-r--r--src/devices/cpu/minx/minx.cpp5
-rw-r--r--src/devices/cpu/minx/minx.h9
-rw-r--r--src/devices/cpu/minx/minxd.cpp16
-rw-r--r--src/devices/cpu/minx/minxd.h6
-rw-r--r--src/devices/cpu/minx/minxopce.h4
-rw-r--r--src/devices/cpu/mips/mips1.cpp883
-rw-r--r--src/devices/cpu/mips/mips1.h294
-rw-r--r--src/devices/cpu/mips/mips1dsm.cpp161
-rw-r--r--src/devices/cpu/mips/mips3.cpp786
-rw-r--r--src/devices/cpu/mips/mips3.h161
-rw-r--r--src/devices/cpu/mips/mips3com.cpp18
-rw-r--r--src/devices/cpu/mips/mips3com.h4
-rw-r--r--src/devices/cpu/mips/mips3drc.cpp565
-rw-r--r--src/devices/cpu/mips/mips3dsm.cpp216
-rw-r--r--src/devices/cpu/mips/mips3fe.cpp8
-rw-r--r--src/devices/cpu/mips/o2dprintf.hxx32
-rw-r--r--src/devices/cpu/mips/ps2vif1.cpp12
-rw-r--r--src/devices/cpu/mips/ps2vif1.h12
-rw-r--r--src/devices/cpu/mips/ps2vu.cpp15
-rw-r--r--src/devices/cpu/mips/ps2vu.h35
-rw-r--r--src/devices/cpu/mips/r4000.cpp1416
-rw-r--r--src/devices/cpu/mips/r4000.h152
-rw-r--r--src/devices/cpu/mipsx/mipsx.cpp62
-rw-r--r--src/devices/cpu/mipsx/mipsx.h37
-rw-r--r--src/devices/cpu/mipsx/mipsxdasm.cpp635
-rw-r--r--src/devices/cpu/mipsx/mipsxdasm.h19
-rw-r--r--src/devices/cpu/mk1/mk1.cpp521
-rw-r--r--src/devices/cpu/mk1/mk1.h81
-rw-r--r--src/devices/cpu/mk1/mk1dasm.cpp151
-rw-r--r--src/devices/cpu/mk1/mk1dasm.h18
-rw-r--r--src/devices/cpu/mn10200/mn10200.cpp29
-rw-r--r--src/devices/cpu/mn10200/mn10200.h23
-rw-r--r--src/devices/cpu/mn10200/mn102dis.cpp374
-rw-r--r--src/devices/cpu/mn10300/mn103dasm.cpp929
-rw-r--r--src/devices/cpu/mn10300/mn103dasm.h42
-rw-r--r--src/devices/cpu/mn1400/mn1400.cpp141
-rw-r--r--src/devices/cpu/mn1400/mn1400.h147
-rw-r--r--src/devices/cpu/mn1400/mn1400base.cpp267
-rw-r--r--src/devices/cpu/mn1400/mn1400base.h132
-rw-r--r--src/devices/cpu/mn1400/mn1400d.cpp135
-rw-r--r--src/devices/cpu/mn1400/mn1400d.h33
-rw-r--r--src/devices/cpu/mn1400/mn1400op.cpp446
-rw-r--r--src/devices/cpu/mn1610/mn1610d.cpp348
-rw-r--r--src/devices/cpu/mn1610/mn1610d.h36
-rw-r--r--src/devices/cpu/mn1880/mn1880.cpp2508
-rw-r--r--src/devices/cpu/mn1880/mn1880.h244
-rw-r--r--src/devices/cpu/mn1880/mn1880d.cpp646
-rw-r--r--src/devices/cpu/mn1880/mn1880d.h66
-rw-r--r--src/devices/cpu/mpk1839/kl1839vm1.cpp1088
-rw-r--r--src/devices/cpu/mpk1839/kl1839vm1.h121
-rw-r--r--src/devices/cpu/mpk1839/kl1839vm1dasm.cpp445
-rw-r--r--src/devices/cpu/mpk1839/kl1839vm1dasm.h25
-rw-r--r--src/devices/cpu/msm65x2/msm65x2d.cpp105
-rw-r--r--src/devices/cpu/msm65x2/msm65x2d.h30
-rw-r--r--src/devices/cpu/nanoprocessor/nanoprocessor.cpp130
-rw-r--r--src/devices/cpu/nanoprocessor/nanoprocessor.h38
-rw-r--r--src/devices/cpu/nanoprocessor/nanoprocessor_dasm.cpp30
-rw-r--r--src/devices/cpu/nec/nec.cpp170
-rw-r--r--src/devices/cpu/nec/nec.h292
-rw-r--r--src/devices/cpu/nec/nec80inst.hxx260
-rw-r--r--src/devices/cpu/nec/necdasm.cpp328
-rw-r--r--src/devices/cpu/nec/necdasm.h10
-rw-r--r--src/devices/cpu/nec/necinstr.h260
-rw-r--r--src/devices/cpu/nec/necinstr.hxx100
-rw-r--r--src/devices/cpu/nec/necmacro.h16
-rw-r--r--src/devices/cpu/nec/necpriv.ipp (renamed from src/devices/cpu/nec/necpriv.h)19
-rw-r--r--src/devices/cpu/nec/v25.cpp362
-rw-r--r--src/devices/cpu/nec/v25.h90
-rw-r--r--src/devices/cpu/nec/v25priv.ipp (renamed from src/devices/cpu/nec/v25priv.h)6
-rw-r--r--src/devices/cpu/nec/v25sfr.cpp247
-rw-r--r--src/devices/cpu/nec/v5x.cpp813
-rw-r--r--src/devices/cpu/nec/v5x.h258
-rw-r--r--src/devices/cpu/nios2/nios2.cpp558
-rw-r--r--src/devices/cpu/nios2/nios2.h62
-rw-r--r--src/devices/cpu/nios2/nios2dasm.cpp472
-rw-r--r--src/devices/cpu/nios2/nios2dasm.h29
-rw-r--r--src/devices/cpu/nova/novadasm.cpp262
-rw-r--r--src/devices/cpu/nova/novadasm.h25
-rw-r--r--src/devices/cpu/ns32000/common.h127
-rw-r--r--src/devices/cpu/ns32000/ns32000.cpp4259
-rw-r--r--src/devices/cpu/ns32000/ns32000.h319
-rw-r--r--src/devices/cpu/ns32000/ns32000d.cpp643
-rw-r--r--src/devices/cpu/ns32000/ns32000d.h52
-rw-r--r--src/devices/cpu/ns32000/ns32000dasm.cpp835
-rw-r--r--src/devices/cpu/ns32000/ns32000dasm.h117
-rw-r--r--src/devices/cpu/nuon/nuon.cpp17
-rw-r--r--src/devices/cpu/nuon/nuon.h11
-rw-r--r--src/devices/cpu/olms66k/msm665xx.cpp3278
-rw-r--r--src/devices/cpu/olms66k/msm665xx.h198
-rw-r--r--src/devices/cpu/olms66k/nx8dasm.cpp1019
-rw-r--r--src/devices/cpu/olms66k/nx8dasm.h28
-rw-r--r--src/devices/cpu/pace/pace.cpp977
-rw-r--r--src/devices/cpu/pace/pace.h224
-rw-r--r--src/devices/cpu/pace/pacedasm.cpp321
-rw-r--r--src/devices/cpu/pace/pacedasm.h36
-rw-r--r--src/devices/cpu/palm/palm.cpp330
-rw-r--r--src/devices/cpu/palm/palm.h78
-rw-r--r--src/devices/cpu/palm/palmd.cpp179
-rw-r--r--src/devices/cpu/palm/palmd.h19
-rw-r--r--src/devices/cpu/patinhofeio/patinho_feio.cpp68
-rw-r--r--src/devices/cpu/patinhofeio/patinhofeio_cpu.h26
-rw-r--r--src/devices/cpu/pdp1/pdp1.cpp178
-rw-r--r--src/devices/cpu/pdp1/pdp1.h43
-rw-r--r--src/devices/cpu/pdp1/pdp1dasm.cpp4
-rw-r--r--src/devices/cpu/pdp1/tx0dasm.cpp133
-rw-r--r--src/devices/cpu/pdp8/hd6120.cpp1364
-rw-r--r--src/devices/cpu/pdp8/hd6120.h216
-rw-r--r--src/devices/cpu/pdp8/pdp8.cpp40
-rw-r--r--src/devices/cpu/pdp8/pdp8.h23
-rw-r--r--src/devices/cpu/pdp8/pdp8dasm.cpp1024
-rw-r--r--src/devices/cpu/pdp8/pdp8dasm.h38
-rw-r--r--src/devices/cpu/pic16/pic16d.cpp181
-rw-r--r--src/devices/cpu/pic16/pic16d.h40
-rw-r--r--src/devices/cpu/pic1670/pic1670d.cpp103
-rw-r--r--src/devices/cpu/pic1670/pic1670d.h34
-rw-r--r--src/devices/cpu/pic16c5x/16c5xdsm.cpp102
-rw-r--r--src/devices/cpu/pic16c5x/16c5xdsm.h40
-rw-r--r--src/devices/cpu/pic16c5x/pic16c5x.cpp1435
-rw-r--r--src/devices/cpu/pic16c5x/pic16c5x.h234
-rw-r--r--src/devices/cpu/pic16c62x/16c62xdsm.cpp11
-rw-r--r--src/devices/cpu/pic16c62x/16c62xdsm.h2
-rw-r--r--src/devices/cpu/pic16c62x/pic16c62x.cpp722
-rw-r--r--src/devices/cpu/pic16c62x/pic16c62x.h115
-rw-r--r--src/devices/cpu/pic16x8x/16x8xdsm.cpp258
-rw-r--r--src/devices/cpu/pic16x8x/16x8xdsm.h46
-rw-r--r--src/devices/cpu/pic16x8x/pic16x8x.cpp1413
-rw-r--r--src/devices/cpu/pic16x8x/pic16x8x.h318
-rw-r--r--src/devices/cpu/pic17/pic17.cpp1108
-rw-r--r--src/devices/cpu/pic17/pic17.h181
-rw-r--r--src/devices/cpu/pic17/pic17c4x.cpp531
-rw-r--r--src/devices/cpu/pic17/pic17c4x.h179
-rw-r--r--src/devices/cpu/pic17/pic17d.cpp244
-rw-r--r--src/devices/cpu/pic17/pic17d.h36
-rw-r--r--src/devices/cpu/powerpc/ppc.h121
-rw-r--r--src/devices/cpu/powerpc/ppc_dasm.cpp649
-rw-r--r--src/devices/cpu/powerpc/ppc_dasm.h35
-rw-r--r--src/devices/cpu/powerpc/ppccom.cpp249
-rw-r--r--src/devices/cpu/powerpc/ppccom.h12
-rw-r--r--src/devices/cpu/powerpc/ppcdrc.cpp271
-rw-r--r--src/devices/cpu/powerpc/ppcfe.cpp96
-rw-r--r--src/devices/cpu/pps4/pps4.cpp188
-rw-r--r--src/devices/cpu/pps4/pps4.h30
-rw-r--r--src/devices/cpu/pps4/pps4dasm.cpp94
-rw-r--r--src/devices/cpu/pps4/pps4dasm.h7
-rw-r--r--src/devices/cpu/pps41/mm75.cpp27
-rw-r--r--src/devices/cpu/pps41/mm75.h56
-rw-r--r--src/devices/cpu/pps41/mm75op.cpp40
-rw-r--r--src/devices/cpu/pps41/mm76.cpp182
-rw-r--r--src/devices/cpu/pps41/mm76.h165
-rw-r--r--src/devices/cpu/pps41/mm76op.cpp473
-rw-r--r--src/devices/cpu/pps41/mm78.cpp217
-rw-r--r--src/devices/cpu/pps41/mm78.h128
-rw-r--r--src/devices/cpu/pps41/mm78la.cpp113
-rw-r--r--src/devices/cpu/pps41/mm78la.h98
-rw-r--r--src/devices/cpu/pps41/mm78laop.cpp73
-rw-r--r--src/devices/cpu/pps41/mm78op.cpp202
-rw-r--r--src/devices/cpu/pps41/pps41base.cpp351
-rw-r--r--src/devices/cpu/pps41/pps41base.h154
-rw-r--r--src/devices/cpu/pps41/pps41d.cpp210
-rw-r--r--src/devices/cpu/pps41/pps41d.h66
-rw-r--r--src/devices/cpu/psx/dma.cpp386
-rw-r--r--src/devices/cpu/psx/dma.h12
-rw-r--r--src/devices/cpu/psx/gte.cpp6
-rw-r--r--src/devices/cpu/psx/gte.h2
-rw-r--r--src/devices/cpu/psx/irq.cpp68
-rw-r--r--src/devices/cpu/psx/irq.h32
-rw-r--r--src/devices/cpu/psx/mdec.cpp47
-rw-r--r--src/devices/cpu/psx/mdec.h8
-rw-r--r--src/devices/cpu/psx/psx.cpp133
-rw-r--r--src/devices/cpu/psx/psx.h63
-rw-r--r--src/devices/cpu/psx/psxdasm.cpp140
-rw-r--r--src/devices/cpu/psx/rcnt.cpp102
-rw-r--r--src/devices/cpu/psx/rcnt.h13
-rw-r--r--src/devices/cpu/psx/sio.cpp100
-rw-r--r--src/devices/cpu/psx/sio.h13
-rw-r--r--src/devices/cpu/rii/riidasm.cpp24
-rw-r--r--src/devices/cpu/rii/riscii.cpp426
-rw-r--r--src/devices/cpu/rii/riscii.h68
-rw-r--r--src/devices/cpu/romp/romp.cpp1206
-rw-r--r--src/devices/cpu/romp/romp.h306
-rw-r--r--src/devices/cpu/romp/rompdasm.cpp261
-rw-r--r--src/devices/cpu/romp/rompdasm.h19
-rw-r--r--src/devices/cpu/romp/rsc.h94
-rw-r--r--src/devices/cpu/rsp/clamp.h37
-rw-r--r--src/devices/cpu/rsp/rsp.cpp3052
-rw-r--r--src/devices/cpu/rsp/rsp.h199
-rw-r--r--src/devices/cpu/rsp/rsp_dasm.cpp40
-rw-r--r--src/devices/cpu/rsp/rspcp2.cpp4223
-rw-r--r--src/devices/cpu/rsp/rspcp2.h395
-rw-r--r--src/devices/cpu/rsp/rspcp2d.cpp3388
-rw-r--r--src/devices/cpu/rsp/rspcp2d.h179
-rw-r--r--src/devices/cpu/rsp/rspdrc.cpp1279
-rw-r--r--src/devices/cpu/rsp/rspfe.cpp307
-rw-r--r--src/devices/cpu/rsp/rspfe.h55
-rw-r--r--src/devices/cpu/rsp/vabs.h15
-rw-r--r--src/devices/cpu/rsp/vadd.h16
-rw-r--r--src/devices/cpu/rsp/vaddc.h13
-rw-r--r--src/devices/cpu/rsp/vand.h9
-rw-r--r--src/devices/cpu/rsp/vch.h57
-rw-r--r--src/devices/cpu/rsp/vcl.h65
-rw-r--r--src/devices/cpu/rsp/vcmp.h49
-rw-r--r--src/devices/cpu/rsp/vcr.h35
-rw-r--r--src/devices/cpu/rsp/vdivh.h12
-rw-r--r--src/devices/cpu/rsp/vldst.h69
-rw-r--r--src/devices/cpu/rsp/vmac.h57
-rw-r--r--src/devices/cpu/rsp/vmov.h9
-rw-r--r--src/devices/cpu/rsp/vmrg.h13
-rw-r--r--src/devices/cpu/rsp/vmudh.h10
-rw-r--r--src/devices/cpu/rsp/vmul.h39
-rw-r--r--src/devices/cpu/rsp/vmulh.h30
-rw-r--r--src/devices/cpu/rsp/vmull.h44
-rw-r--r--src/devices/cpu/rsp/vmulm.h56
-rw-r--r--src/devices/cpu/rsp/vmuln.h55
-rw-r--r--src/devices/cpu/rsp/vor.h10
-rw-r--r--src/devices/cpu/rsp/vrcpsq.h58
-rw-r--r--src/devices/cpu/rsp/vrsq.h66
-rw-r--r--src/devices/cpu/rsp/vsub.h17
-rw-r--r--src/devices/cpu/rsp/vsubc.h14
-rw-r--r--src/devices/cpu/rsp/vxor.h10
-rw-r--r--src/devices/cpu/rw5000/a5000.cpp86
-rw-r--r--src/devices/cpu/rw5000/a5000.h37
-rw-r--r--src/devices/cpu/rw5000/a5500.cpp78
-rw-r--r--src/devices/cpu/rw5000/a5500.h43
-rw-r--r--src/devices/cpu/rw5000/a5900.cpp42
-rw-r--r--src/devices/cpu/rw5000/a5900.h32
-rw-r--r--src/devices/cpu/rw5000/b5000.cpp165
-rw-r--r--src/devices/cpu/rw5000/b5000.h113
-rw-r--r--src/devices/cpu/rw5000/b5000op.cpp331
-rw-r--r--src/devices/cpu/rw5000/b5500.cpp48
-rw-r--r--src/devices/cpu/rw5000/b5500.h32
-rw-r--r--src/devices/cpu/rw5000/b6000.cpp116
-rw-r--r--src/devices/cpu/rw5000/b6000.h71
-rw-r--r--src/devices/cpu/rw5000/b6100.cpp112
-rw-r--r--src/devices/cpu/rw5000/b6100.h73
-rw-r--r--src/devices/cpu/rw5000/rw5000base.cpp222
-rw-r--r--src/devices/cpu/rw5000/rw5000base.h117
-rw-r--r--src/devices/cpu/rw5000/rw5000d.cpp342
-rw-r--r--src/devices/cpu/rw5000/rw5000d.h112
-rw-r--r--src/devices/cpu/rx01/rx01.cpp601
-rw-r--r--src/devices/cpu/rx01/rx01.h121
-rw-r--r--src/devices/cpu/rx01/rx01dasm.cpp186
-rw-r--r--src/devices/cpu/rx01/rx01dasm.h27
-rw-r--r--src/devices/cpu/s2650/2650dasm.cpp142
-rw-r--r--src/devices/cpu/s2650/2650dasm.h9
-rw-r--r--src/devices/cpu/s2650/s2650.cpp1127
-rw-r--r--src/devices/cpu/s2650/s2650.h42
-rw-r--r--src/devices/cpu/s2650/s2650cpu.h33
-rw-r--r--src/devices/cpu/saturn/satops.ipp (renamed from src/devices/cpu/saturn/satops.hxx)561
-rw-r--r--src/devices/cpu/saturn/sattable.ipp (renamed from src/devices/cpu/saturn/sattable.hxx)246
-rw-r--r--src/devices/cpu/saturn/saturn.cpp59
-rw-r--r--src/devices/cpu/saturn/saturn.h257
-rw-r--r--src/devices/cpu/sc61860/readpc.cpp2
-rw-r--r--src/devices/cpu/sc61860/sc61860.cpp28
-rw-r--r--src/devices/cpu/sc61860/sc61860.h16
-rw-r--r--src/devices/cpu/sc61860/scdasm.cpp19
-rw-r--r--src/devices/cpu/sc61860/scdasm.h2
-rw-r--r--src/devices/cpu/sc61860/scops.hxx27
-rw-r--r--src/devices/cpu/sc61860/sctable.hxx5
-rw-r--r--src/devices/cpu/scmp/scmp.cpp88
-rw-r--r--src/devices/cpu/scmp/scmp.h26
-rw-r--r--src/devices/cpu/scmp/scmpdasm.cpp318
-rw-r--r--src/devices/cpu/scmp/scmpdasm.h21
-rw-r--r--src/devices/cpu/score/score.cpp199
-rw-r--r--src/devices/cpu/score/score.h18
-rw-r--r--src/devices/cpu/score/scoredsm.cpp33
-rw-r--r--src/devices/cpu/score/scoredsm.h1
-rw-r--r--src/devices/cpu/scudsp/scudsp.cpp32
-rw-r--r--src/devices/cpu/scudsp/scudsp.h25
-rw-r--r--src/devices/cpu/se3208/se3208.cpp739
-rw-r--r--src/devices/cpu/se3208/se3208.h43
-rw-r--r--src/devices/cpu/se3208/se3208dis.cpp28
-rw-r--r--src/devices/cpu/sh/sh.cpp1540
-rw-r--r--src/devices/cpu/sh/sh.h34
-rw-r--r--src/devices/cpu/sh/sh2.cpp753
-rw-r--r--src/devices/cpu/sh/sh2.h389
-rw-r--r--src/devices/cpu/sh/sh2comn.cpp1204
-rw-r--r--src/devices/cpu/sh/sh2comn.h52
-rw-r--r--src/devices/cpu/sh/sh2fe.cpp3
-rw-r--r--src/devices/cpu/sh/sh3comn.cpp2403
-rw-r--r--src/devices/cpu/sh/sh3comn.h79
-rw-r--r--src/devices/cpu/sh/sh4.cpp2806
-rw-r--r--src/devices/cpu/sh/sh4.h1603
-rw-r--r--src/devices/cpu/sh/sh4comn.cpp2972
-rw-r--r--src/devices/cpu/sh/sh4comn.h33
-rw-r--r--src/devices/cpu/sh/sh4dmac.cpp511
-rw-r--r--src/devices/cpu/sh/sh4dmac.h35
-rw-r--r--src/devices/cpu/sh/sh4fe.cpp22
-rw-r--r--src/devices/cpu/sh/sh4regs.h165
-rw-r--r--src/devices/cpu/sh/sh4tmu.cpp269
-rw-r--r--src/devices/cpu/sh/sh7014.cpp201
-rw-r--r--src/devices/cpu/sh/sh7014.h83
-rw-r--r--src/devices/cpu/sh/sh7014_bsc.cpp148
-rw-r--r--src/devices/cpu/sh/sh7014_bsc.h62
-rw-r--r--src/devices/cpu/sh/sh7014_dmac.cpp400
-rw-r--r--src/devices/cpu/sh/sh7014_dmac.h173
-rw-r--r--src/devices/cpu/sh/sh7014_intc.cpp313
-rw-r--r--src/devices/cpu/sh/sh7014_intc.h147
-rw-r--r--src/devices/cpu/sh/sh7014_mtu.cpp571
-rw-r--r--src/devices/cpu/sh/sh7014_mtu.h211
-rw-r--r--src/devices/cpu/sh/sh7014_port.cpp243
-rw-r--r--src/devices/cpu/sh/sh7014_port.h98
-rw-r--r--src/devices/cpu/sh/sh7014_sci.cpp380
-rw-r--r--src/devices/cpu/sh/sh7014_sci.h135
-rw-r--r--src/devices/cpu/sh/sh7021.cpp2243
-rw-r--r--src/devices/cpu/sh/sh7021.h334
-rw-r--r--src/devices/cpu/sh/sh7032.cpp43
-rw-r--r--src/devices/cpu/sh/sh7032.h33
-rw-r--r--src/devices/cpu/sh/sh7042.cpp505
-rw-r--r--src/devices/cpu/sh/sh7042.h190
-rw-r--r--src/devices/cpu/sh/sh7604.cpp1540
-rw-r--r--src/devices/cpu/sh/sh7604.h264
-rw-r--r--src/devices/cpu/sh/sh7604_bus.cpp78
-rw-r--r--src/devices/cpu/sh/sh7604_bus.h46
-rw-r--r--src/devices/cpu/sh/sh7604_sci.cpp48
-rw-r--r--src/devices/cpu/sh/sh7604_sci.h41
-rw-r--r--src/devices/cpu/sh/sh7604_wdt.cpp20
-rw-r--r--src/devices/cpu/sh/sh7604_wdt.h17
-rw-r--r--src/devices/cpu/sh/sh_adc.cpp342
-rw-r--r--src/devices/cpu/sh/sh_adc.h124
-rw-r--r--src/devices/cpu/sh/sh_bsc.cpp139
-rw-r--r--src/devices/cpu/sh/sh_bsc.h47
-rw-r--r--src/devices/cpu/sh/sh_cmt.cpp202
-rw-r--r--src/devices/cpu/sh/sh_cmt.h75
-rw-r--r--src/devices/cpu/sh/sh_dasm.cpp73
-rw-r--r--src/devices/cpu/sh/sh_dasm.h6
-rw-r--r--src/devices/cpu/sh/sh_dmac.cpp115
-rw-r--r--src/devices/cpu/sh/sh_dmac.h79
-rw-r--r--src/devices/cpu/sh/sh_fe.cpp259
-rw-r--r--src/devices/cpu/sh/sh_intc.cpp151
-rw-r--r--src/devices/cpu/sh/sh_intc.h58
-rw-r--r--src/devices/cpu/sh/sh_mtu.cpp529
-rw-r--r--src/devices/cpu/sh/sh_mtu.h182
-rw-r--r--src/devices/cpu/sh/sh_port.cpp109
-rw-r--r--src/devices/cpu/sh/sh_port.h75
-rw-r--r--src/devices/cpu/sh/sh_sci.cpp765
-rw-r--r--src/devices/cpu/sh/sh_sci.h151
-rw-r--r--src/devices/cpu/sharc/compute.hxx14
-rw-r--r--src/devices/cpu/sharc/sharc.cpp191
-rw-r--r--src/devices/cpu/sharc/sharc.h42
-rw-r--r--src/devices/cpu/sharc/sharcdma.hxx136
-rw-r--r--src/devices/cpu/sharc/sharcdrc.cpp23
-rw-r--r--src/devices/cpu/sharc/sharcdsm.cpp30
-rw-r--r--src/devices/cpu/sharc/sharcfe.cpp12
-rw-r--r--src/devices/cpu/sharc/sharcops.hxx121
-rw-r--r--src/devices/cpu/sigma2/sigma2d.cpp393
-rw-r--r--src/devices/cpu/sigma2/sigma2d.h40
-rw-r--r--src/devices/cpu/sm510/sm500.cpp (renamed from src/devices/cpu/sm510/sm500core.cpp)38
-rw-r--r--src/devices/cpu/sm510/sm500.h93
-rw-r--r--src/devices/cpu/sm510/sm500op.cpp17
-rw-r--r--src/devices/cpu/sm510/sm510.cpp (renamed from src/devices/cpu/sm510/sm510core.cpp)29
-rw-r--r--src/devices/cpu/sm510/sm510.h348
-rw-r--r--src/devices/cpu/sm510/sm510base.cpp210
-rw-r--r--src/devices/cpu/sm510/sm510base.h250
-rw-r--r--src/devices/cpu/sm510/sm510d.cpp75
-rw-r--r--src/devices/cpu/sm510/sm510d.h36
-rw-r--r--src/devices/cpu/sm510/sm510op.cpp39
-rw-r--r--src/devices/cpu/sm510/sm511.cpp (renamed from src/devices/cpu/sm510/sm511core.cpp)45
-rw-r--r--src/devices/cpu/sm510/sm511.h63
-rw-r--r--src/devices/cpu/sm510/sm530.cpp (renamed from src/devices/cpu/sm510/sm530core.cpp)139
-rw-r--r--src/devices/cpu/sm510/sm530.h112
-rw-r--r--src/devices/cpu/sm510/sm530op.cpp81
-rw-r--r--src/devices/cpu/sm510/sm590.cpp182
-rw-r--r--src/devices/cpu/sm510/sm590.h134
-rw-r--r--src/devices/cpu/sm510/sm590core.cpp186
-rw-r--r--src/devices/cpu/sm510/sm590op.cpp157
-rw-r--r--src/devices/cpu/sm510/sm5a.cpp (renamed from src/devices/cpu/sm510/sm5acore.cpp)37
-rw-r--r--src/devices/cpu/sm510/sm5a.h90
-rw-r--r--src/devices/cpu/sm8500/sm8500.cpp9
-rw-r--r--src/devices/cpu/sm8500/sm8500.h9
-rw-r--r--src/devices/cpu/sm8500/sm8500d.cpp25
-rw-r--r--src/devices/cpu/sm8500/sm85ops.h69
-rw-r--r--src/devices/cpu/sparc/sparc.cpp (renamed from src/devices/cpu/sparc/mb86901.cpp)3281
-rw-r--r--src/devices/cpu/sparc/sparc.h245
-rw-r--r--src/devices/cpu/sparc/sparc_intf.h2
-rw-r--r--src/devices/cpu/sparc/sparcdasm.cpp126
-rw-r--r--src/devices/cpu/sparc/sparcdasm.h14
-rw-r--r--src/devices/cpu/sparc/sparcdefs.h129
-rw-r--r--src/devices/cpu/sparc/sparcv8ops.ipp293
-rw-r--r--src/devices/cpu/sparc/ss1fcode.ipp8
-rw-r--r--src/devices/cpu/spc700/spc700.cpp52
-rw-r--r--src/devices/cpu/spc700/spc700.h17
-rw-r--r--src/devices/cpu/spc700/spc700ds.cpp3
-rw-r--r--src/devices/cpu/spc700/spc700ds.h9
-rw-r--r--src/devices/cpu/ssem/ssem.cpp16
-rw-r--r--src/devices/cpu/ssem/ssem.h11
-rw-r--r--src/devices/cpu/ssem/ssemdasm.cpp2
-rw-r--r--src/devices/cpu/ssp1601/ssp1601.cpp16
-rw-r--r--src/devices/cpu/ssp1601/ssp1601.h15
-rw-r--r--src/devices/cpu/ssp1601/ssp1601d.cpp4
-rw-r--r--src/devices/cpu/ssp1601/ssp1601d.h6
-rw-r--r--src/devices/cpu/st62xx/st62xx.cpp468
-rw-r--r--src/devices/cpu/st62xx/st62xx.h155
-rw-r--r--src/devices/cpu/st62xx/st62xx_dasm.cpp12
-rw-r--r--src/devices/cpu/st62xx/st62xx_dasm.h6
-rw-r--r--src/devices/cpu/st9/st905x.cpp238
-rw-r--r--src/devices/cpu/st9/st905x.h95
-rw-r--r--src/devices/cpu/st9/st9dasm.cpp1373
-rw-r--r--src/devices/cpu/st9/st9dasm.h90
-rw-r--r--src/devices/cpu/superfx/sfx_dasm.cpp13
-rw-r--r--src/devices/cpu/superfx/superfx.cpp27
-rw-r--r--src/devices/cpu/superfx/superfx.h38
-rw-r--r--src/devices/cpu/t11/t11.cpp409
-rw-r--r--src/devices/cpu/t11/t11.h144
-rw-r--r--src/devices/cpu/t11/t11dasm.cpp634
-rw-r--r--src/devices/cpu/t11/t11dasm.h2
-rw-r--r--src/devices/cpu/t11/t11ops.hxx178
-rw-r--r--src/devices/cpu/t11/t11table.hxx20
-rw-r--r--src/devices/cpu/tlcs870/tlcs870.cpp208
-rw-r--r--src/devices/cpu/tlcs870/tlcs870.h186
-rw-r--r--src/devices/cpu/tlcs870/tlcs870_ops.cpp3
-rw-r--r--src/devices/cpu/tlcs870/tlcs870_ops_dst.cpp1
-rw-r--r--src/devices/cpu/tlcs870/tlcs870_ops_helper.cpp1
-rw-r--r--src/devices/cpu/tlcs870/tlcs870_ops_reg.cpp1
-rw-r--r--src/devices/cpu/tlcs870/tlcs870_ops_src.cpp1
-rw-r--r--src/devices/cpu/tlcs870/tlcs870d.cpp9
-rw-r--r--src/devices/cpu/tlcs90/tlcs90.cpp886
-rw-r--r--src/devices/cpu/tlcs90/tlcs90.h231
-rw-r--r--src/devices/cpu/tlcs90/tlcs90d.cpp148
-rw-r--r--src/devices/cpu/tlcs90/tlcs90d.h74
-rw-r--r--src/devices/cpu/tlcs900/900htbl.hxx1267
-rw-r--r--src/devices/cpu/tlcs900/900tbl.hxx3073
-rw-r--r--src/devices/cpu/tlcs900/dasm900.cpp23
-rw-r--r--src/devices/cpu/tlcs900/tlcs900.cpp2283
-rw-r--r--src/devices/cpu/tlcs900/tlcs900.h284
-rw-r--r--src/devices/cpu/tlcs900/tmp94c241.cpp1332
-rw-r--r--src/devices/cpu/tlcs900/tmp94c241.h279
-rw-r--r--src/devices/cpu/tlcs900/tmp95c061.cpp1355
-rw-r--r--src/devices/cpu/tlcs900/tmp95c061.h196
-rw-r--r--src/devices/cpu/tlcs900/tmp95c063.cpp1403
-rw-r--r--src/devices/cpu/tlcs900/tmp95c063.h224
-rw-r--r--src/devices/cpu/tlcs900/tmp96c141.cpp197
-rw-r--r--src/devices/cpu/tlcs900/tmp96c141.h98
-rw-r--r--src/devices/cpu/tms1000/smc1102.cpp363
-rw-r--r--src/devices/cpu/tms1000/smc1102.h120
-rw-r--r--src/devices/cpu/tms1000/tms0270.cpp63
-rw-r--r--src/devices/cpu/tms1000/tms0270.h10
-rw-r--r--src/devices/cpu/tms1000/tms0970.cpp79
-rw-r--r--src/devices/cpu/tms1000/tms0970.h10
-rw-r--r--src/devices/cpu/tms1000/tms0980.cpp204
-rw-r--r--src/devices/cpu/tms1000/tms0980.h48
-rw-r--r--src/devices/cpu/tms1000/tms1000.cpp171
-rw-r--r--src/devices/cpu/tms1000/tms1000.h96
-rw-r--r--src/devices/cpu/tms1000/tms1000c.cpp39
-rw-r--r--src/devices/cpu/tms1000/tms1000c.h8
-rw-r--r--src/devices/cpu/tms1000/tms1100.cpp81
-rw-r--r--src/devices/cpu/tms1000/tms1100.h54
-rw-r--r--src/devices/cpu/tms1000/tms1400.cpp93
-rw-r--r--src/devices/cpu/tms1000/tms1400.h53
-rw-r--r--src/devices/cpu/tms1000/tms1k_base.cpp358
-rw-r--r--src/devices/cpu/tms1000/tms1k_base.h326
-rw-r--r--src/devices/cpu/tms1000/tms1k_dasm.cpp451
-rw-r--r--src/devices/cpu/tms1000/tms1k_dasm.h71
-rw-r--r--src/devices/cpu/tms1000/tms2100.cpp353
-rw-r--r--src/devices/cpu/tms1000/tms2100.h157
-rw-r--r--src/devices/cpu/tms1000/tms2400.cpp80
-rw-r--r--src/devices/cpu/tms1000/tms2400.h61
-rw-r--r--src/devices/cpu/tms1000/tp0320.cpp82
-rw-r--r--src/devices/cpu/tms1000/tp0320.h12
-rw-r--r--src/devices/cpu/tms32010/32010dsm.cpp32
-rw-r--r--src/devices/cpu/tms32010/32010dsm.h6
-rw-r--r--src/devices/cpu/tms32010/dis32010.cpp4
-rw-r--r--src/devices/cpu/tms32010/tms32010.cpp510
-rw-r--r--src/devices/cpu/tms32010/tms32010.h92
-rw-r--r--src/devices/cpu/tms32025/32025dsm.cpp42
-rw-r--r--src/devices/cpu/tms32025/32025dsm.h2
-rw-r--r--src/devices/cpu/tms32025/tms32025.cpp980
-rw-r--r--src/devices/cpu/tms32025/tms32025.h160
-rw-r--r--src/devices/cpu/tms32031/32031ops.hxx116
-rw-r--r--src/devices/cpu/tms32031/dis32031.cpp14
-rw-r--r--src/devices/cpu/tms32031/dis32031.h4
-rw-r--r--src/devices/cpu/tms32031/tms32031.cpp234
-rw-r--r--src/devices/cpu/tms32031/tms32031.h75
-rw-r--r--src/devices/cpu/tms32051/32051ops.hxx2
-rw-r--r--src/devices/cpu/tms32051/dis32051.cpp29
-rw-r--r--src/devices/cpu/tms32051/dis32051.h2
-rw-r--r--src/devices/cpu/tms32051/tms32051.cpp124
-rw-r--r--src/devices/cpu/tms32051/tms32051.h31
-rw-r--r--src/devices/cpu/tms32082/dis_mp.cpp16
-rw-r--r--src/devices/cpu/tms32082/dis_pp.cpp1069
-rw-r--r--src/devices/cpu/tms32082/dis_pp.h19
-rw-r--r--src/devices/cpu/tms32082/mp_ops.cpp310
-rw-r--r--src/devices/cpu/tms32082/tms32082.cpp199
-rw-r--r--src/devices/cpu/tms32082/tms32082.h42
-rw-r--r--src/devices/cpu/tms34010/34010dsm.cpp10
-rw-r--r--src/devices/cpu/tms34010/34010fld.hxx66
-rw-r--r--src/devices/cpu/tms34010/34010gfx.hxx104
-rw-r--r--src/devices/cpu/tms34010/34010ops.h30
-rw-r--r--src/devices/cpu/tms34010/34010ops.hxx319
-rw-r--r--src/devices/cpu/tms34010/34010tbl.hxx2313
-rw-r--r--src/devices/cpu/tms34010/makefile6
-rw-r--r--src/devices/cpu/tms34010/tms34010.cpp255
-rw-r--r--src/devices/cpu/tms34010/tms34010.h292
-rw-r--r--src/devices/cpu/tms57002/57002dsm.cpp6
-rw-r--r--src/devices/cpu/tms57002/tms57002.cpp67
-rw-r--r--src/devices/cpu/tms57002/tms57002.h1684
-rw-r--r--src/devices/cpu/tms57002/tms57kdec.cpp1
-rwxr-xr-xsrc/devices/cpu/tms57002/tmsmake.py24
-rw-r--r--src/devices/cpu/tms7000/7000dasm.cpp68
-rw-r--r--src/devices/cpu/tms7000/tms7000.cpp112
-rw-r--r--src/devices/cpu/tms7000/tms7000.h112
-rw-r--r--src/devices/cpu/tms9900/9900dasm.cpp5
-rw-r--r--src/devices/cpu/tms9900/9900dasm.h6
-rw-r--r--src/devices/cpu/tms9900/ti990_10.cpp9
-rw-r--r--src/devices/cpu/tms9900/ti990_10.h6
-rw-r--r--src/devices/cpu/tms9900/tms9900.cpp101
-rw-r--r--src/devices/cpu/tms9900/tms9900.h112
-rw-r--r--src/devices/cpu/tms9900/tms9980a.cpp34
-rw-r--r--src/devices/cpu/tms9900/tms9980a.h14
-rw-r--r--src/devices/cpu/tms9900/tms9995.cpp132
-rw-r--r--src/devices/cpu/tms9900/tms9995.h27
-rw-r--r--src/devices/cpu/tms9900/tms99com.h9
-rw-r--r--src/devices/cpu/tx0/tx0.cpp (renamed from src/devices/cpu/pdp1/tx0.cpp)353
-rw-r--r--src/devices/cpu/tx0/tx0.h (renamed from src/devices/cpu/pdp1/tx0.h)37
-rw-r--r--src/devices/cpu/tx0/tx0dasm.cpp889
-rw-r--r--src/devices/cpu/tx0/tx0dasm.h (renamed from src/devices/cpu/pdp1/tx0dasm.h)17
-rw-r--r--src/devices/cpu/ucom4/ucom4.cpp141
-rw-r--r--src/devices/cpu/ucom4/ucom4.h25
-rw-r--r--src/devices/cpu/ucom4/ucom4d.cpp114
-rw-r--r--src/devices/cpu/ucom4/ucom4d.h28
-rw-r--r--src/devices/cpu/ucom4/ucom4op.cpp10
-rw-r--r--src/devices/cpu/uml.cpp1352
-rw-r--r--src/devices/cpu/uml.h136
-rw-r--r--src/devices/cpu/unsp/unsp.cpp173
-rw-r--r--src/devices/cpu/unsp/unsp.h97
-rw-r--r--src/devices/cpu/unsp/unsp_extended.cpp284
-rw-r--r--src/devices/cpu/unsp/unsp_exxx.cpp292
-rw-r--r--src/devices/cpu/unsp/unsp_fxxx.cpp271
-rw-r--r--src/devices/cpu/unsp/unsp_jumps.cpp24
-rw-r--r--src/devices/cpu/unsp/unsp_other.cpp69
-rw-r--r--src/devices/cpu/unsp/unspdasm.cpp44
-rw-r--r--src/devices/cpu/unsp/unspdasm.h2
-rw-r--r--src/devices/cpu/unsp/unspdasm_extended.cpp809
-rw-r--r--src/devices/cpu/unsp/unspdasm_exxx.cpp4
-rw-r--r--src/devices/cpu/unsp/unspdasm_fxxx.cpp14
-rw-r--r--src/devices/cpu/unsp/unspdasm_other.cpp10
-rw-r--r--src/devices/cpu/unsp/unspdrc.cpp135
-rw-r--r--src/devices/cpu/unsp/unspfe.cpp17
-rw-r--r--src/devices/cpu/upd177x/upd177x.cpp792
-rw-r--r--src/devices/cpu/upd177x/upd177x.h124
-rw-r--r--src/devices/cpu/upd177x/upd177xd.cpp299
-rw-r--r--src/devices/cpu/upd177x/upd177xd.h41
-rw-r--r--src/devices/cpu/upd7725/dasm7725.cpp76
-rw-r--r--src/devices/cpu/upd7725/upd7725.cpp120
-rw-r--r--src/devices/cpu/upd7725/upd7725.h50
-rw-r--r--src/devices/cpu/upd777/upd777.cpp1262
-rw-r--r--src/devices/cpu/upd777/upd777.h165
-rw-r--r--src/devices/cpu/upd777/upd777dasm.cpp504
-rw-r--r--src/devices/cpu/upd777/upd777dasm.h34
-rw-r--r--src/devices/cpu/upd7810/upd7810.cpp661
-rw-r--r--src/devices/cpu/upd7810/upd7810.h150
-rw-r--r--src/devices/cpu/upd7810/upd7810_dasm.h6
-rw-r--r--src/devices/cpu/upd7810/upd7810_macros.h13
-rw-r--r--src/devices/cpu/upd7810/upd7810_opcodes.cpp151
-rw-r--r--src/devices/cpu/upd7810/upd7810_table.cpp1603
-rw-r--r--src/devices/cpu/upd7810/upd7811.cpp37
-rw-r--r--src/devices/cpu/upd7810/upd7811.h20
-rw-r--r--src/devices/cpu/upd78k/upd78k0.cpp234
-rw-r--r--src/devices/cpu/upd78k/upd78k0.h107
-rw-r--r--src/devices/cpu/upd78k/upd78k0d.cpp1348
-rw-r--r--src/devices/cpu/upd78k/upd78k0d.h160
-rw-r--r--src/devices/cpu/upd78k/upd78k1d.cpp844
-rw-r--r--src/devices/cpu/upd78k/upd78k1d.h65
-rw-r--r--src/devices/cpu/upd78k/upd78k2.cpp247
-rw-r--r--src/devices/cpu/upd78k/upd78k2.h116
-rw-r--r--src/devices/cpu/upd78k/upd78k2d.cpp584
-rw-r--r--src/devices/cpu/upd78k/upd78k2d.h85
-rw-r--r--src/devices/cpu/upd78k/upd78k3.cpp367
-rw-r--r--src/devices/cpu/upd78k/upd78k3.h132
-rw-r--r--src/devices/cpu/upd78k/upd78k3d.cpp1659
-rw-r--r--src/devices/cpu/upd78k/upd78k3d.h164
-rw-r--r--src/devices/cpu/upd78k/upd78k4.cpp275
-rw-r--r--src/devices/cpu/upd78k/upd78k4.h110
-rw-r--r--src/devices/cpu/upd78k/upd78k4d.cpp1408
-rw-r--r--src/devices/cpu/upd78k/upd78k4d.h128
-rw-r--r--src/devices/cpu/upd78k/upd78kd.cpp199
-rw-r--r--src/devices/cpu/upd78k/upd78kd.h53
-rw-r--r--src/devices/cpu/v30mz/v30mz.cpp2871
-rw-r--r--src/devices/cpu/v30mz/v30mz.h219
-rw-r--r--src/devices/cpu/v60/am1.hxx13
-rw-r--r--src/devices/cpu/v60/am2.hxx14
-rw-r--r--src/devices/cpu/v60/am3.hxx9
-rw-r--r--src/devices/cpu/v60/op12.hxx95
-rw-r--r--src/devices/cpu/v60/op2.hxx22
-rw-r--r--src/devices/cpu/v60/op7a.hxx5
-rw-r--r--src/devices/cpu/v60/v60.cpp54
-rw-r--r--src/devices/cpu/v60/v60.h83
-rw-r--r--src/devices/cpu/v60/v60d.cpp158
-rw-r--r--src/devices/cpu/v620/v620dasm.cpp650
-rw-r--r--src/devices/cpu/v620/v620dasm.h54
-rw-r--r--src/devices/cpu/v810/v810.cpp506
-rw-r--r--src/devices/cpu/v810/v810.h44
-rw-r--r--src/devices/cpu/v810/v810dasm.cpp30
-rw-r--r--src/devices/cpu/v810/v810dasm.h2
-rw-r--r--src/devices/cpu/v850/v850dasm.cpp1028
-rw-r--r--src/devices/cpu/v850/v850dasm.h86
-rw-r--r--src/devices/cpu/vax/vax.cpp100
-rw-r--r--src/devices/cpu/vax/vax.h82
-rw-r--r--src/devices/cpu/vax/vaxdasm.cpp1115
-rw-r--r--src/devices/cpu/vax/vaxdasm.h50
-rw-r--r--src/devices/cpu/vt50/vt50.cpp802
-rw-r--r--src/devices/cpu/vt50/vt50.h170
-rw-r--r--src/devices/cpu/vt50/vt50dasm.cpp129
-rw-r--r--src/devices/cpu/vt50/vt50dasm.h55
-rw-r--r--src/devices/cpu/vt61/vt61.cpp645
-rw-r--r--src/devices/cpu/vt61/vt61.h99
-rw-r--r--src/devices/cpu/vt61/vt61dasm.cpp277
-rw-r--r--src/devices/cpu/vt61/vt61dasm.h34
-rw-r--r--src/devices/cpu/we32000/we32100.cpp111
-rw-r--r--src/devices/cpu/we32000/we32100.h59
-rw-r--r--src/devices/cpu/we32000/we32100d.cpp912
-rw-r--r--src/devices/cpu/we32000/we32100d.h36
-rw-r--r--src/devices/cpu/x86emit.h3197
-rw-r--r--src/devices/cpu/x86log.cpp4
-rw-r--r--src/devices/cpu/x86log.h39
-rw-r--r--src/devices/cpu/xa/xa.cpp2651
-rw-r--r--src/devices/cpu/xa/xa.h968
-rw-r--r--src/devices/cpu/xa/xa_ops.cpp1926
-rw-r--r--src/devices/cpu/xa/xadasm.cpp1908
-rw-r--r--src/devices/cpu/xa/xadasm.h121
-rw-r--r--src/devices/cpu/xavix2/xavix2.cpp397
-rw-r--r--src/devices/cpu/xavix2/xavix2.h263
-rw-r--r--src/devices/cpu/xavix2/xavix2d.cpp364
-rw-r--r--src/devices/cpu/xavix2/xavix2d.h53
-rw-r--r--src/devices/cpu/xtensa/xtensa.cpp2295
-rw-r--r--src/devices/cpu/xtensa/xtensa.h210
-rw-r--r--src/devices/cpu/xtensa/xtensa_helper.cpp190
-rw-r--r--src/devices/cpu/xtensa/xtensa_helper.h69
-rw-r--r--src/devices/cpu/xtensa/xtensad.cpp931
-rw-r--r--src/devices/cpu/xtensa/xtensad.h22
-rw-r--r--src/devices/cpu/z180/hd647180x.cpp296
-rw-r--r--src/devices/cpu/z180/hd647180x.h79
-rw-r--r--src/devices/cpu/z180/z180.cpp809
-rw-r--r--src/devices/cpu/z180/z180.h172
-rw-r--r--src/devices/cpu/z180/z180asci.cpp694
-rw-r--r--src/devices/cpu/z180/z180asci.h202
-rw-r--r--src/devices/cpu/z180/z180csio.cpp254
-rw-r--r--src/devices/cpu/z180/z180csio.h70
-rw-r--r--src/devices/cpu/z180/z180dasm.cpp24
-rw-r--r--src/devices/cpu/z180/z180dasm.h1
-rw-r--r--src/devices/cpu/z180/z180dd.hxx7
-rw-r--r--src/devices/cpu/z180/z180ed.hxx2
-rw-r--r--src/devices/cpu/z180/z180fd.hxx2
-rw-r--r--src/devices/cpu/z180/z180op.hxx4
-rw-r--r--src/devices/cpu/z180/z180ops.h35
-rw-r--r--src/devices/cpu/z8/z8.cpp104
-rw-r--r--src/devices/cpu/z8/z8.h55
-rw-r--r--src/devices/cpu/z8/z8dasm.cpp35
-rw-r--r--src/devices/cpu/z8/z8ops.hxx40
-rw-r--r--src/devices/cpu/z80/ez80.cpp39
-rw-r--r--src/devices/cpu/z80/ez80.h35
-rw-r--r--src/devices/cpu/z80/kc82.cpp245
-rw-r--r--src/devices/cpu/z80/kc82.h69
-rw-r--r--src/devices/cpu/z80/kl5c80a12.cpp306
-rw-r--r--src/devices/cpu/z80/kl5c80a12.h105
-rw-r--r--src/devices/cpu/z80/kl5c80a16.cpp196
-rw-r--r--src/devices/cpu/z80/kl5c80a16.h85
-rw-r--r--src/devices/cpu/z80/kp63.cpp463
-rw-r--r--src/devices/cpu/z80/kp63.h97
-rw-r--r--src/devices/cpu/z80/kp64.cpp554
-rw-r--r--src/devices/cpu/z80/kp64.h80
-rw-r--r--src/devices/cpu/z80/kp69.cpp464
-rw-r--r--src/devices/cpu/z80/kp69.h104
-rw-r--r--src/devices/cpu/z80/ky80.cpp56
-rw-r--r--src/devices/cpu/z80/ky80.h42
-rw-r--r--src/devices/cpu/z80/lz8420m.cpp47
-rw-r--r--src/devices/cpu/z80/lz8420m.h45
-rw-r--r--src/devices/cpu/z80/mc8123.cpp416
-rw-r--r--src/devices/cpu/z80/mc8123.h43
-rw-r--r--src/devices/cpu/z80/nsc800.cpp87
-rw-r--r--src/devices/cpu/z80/nsc800.h38
-rw-r--r--src/devices/cpu/z80/r800.cpp103
-rw-r--r--src/devices/cpu/z80/r800.h49
-rw-r--r--src/devices/cpu/z80/r800dasm.cpp607
-rw-r--r--src/devices/cpu/z80/r800dasm.h39
-rw-r--r--src/devices/cpu/z80/t6a84.cpp237
-rw-r--r--src/devices/cpu/z80/t6a84.h96
-rw-r--r--src/devices/cpu/z80/tmpz84c011.cpp37
-rw-r--r--src/devices/cpu/z80/tmpz84c011.h68
-rw-r--r--src/devices/cpu/z80/tmpz84c015.cpp128
-rw-r--r--src/devices/cpu/z80/tmpz84c015.h162
-rw-r--r--src/devices/cpu/z80/z80.cpp3543
-rw-r--r--src/devices/cpu/z80/z80.h368
-rw-r--r--src/devices/cpu/z80/z80.inc67
-rw-r--r--src/devices/cpu/z80/z80.lst8474
-rw-r--r--src/devices/cpu/z80/z80dasm.cpp67
-rw-r--r--src/devices/cpu/z80/z80dasm.h8
-rw-r--r--src/devices/cpu/z80/z80make.py351
-rw-r--r--src/devices/cpu/z80/z80n.cpp49
-rw-r--r--src/devices/cpu/z80/z80n.h45
-rw-r--r--src/devices/cpu/z80/z80ndasm.cpp77
-rw-r--r--src/devices/cpu/z80/z80ndasm.h23
-rw-r--r--src/devices/cpu/z80/z84c015.cpp133
-rw-r--r--src/devices/cpu/z80/z84c015.h69
-rw-r--r--src/devices/cpu/z8000/8000dasm.cpp134
-rw-r--r--src/devices/cpu/z8000/makedab.cpp2
-rw-r--r--src/devices/cpu/z8000/z8000.cpp288
-rw-r--r--src/devices/cpu/z8000/z8000.h111
-rw-r--r--src/devices/cpu/z8000/z8000cpu.h5
-rw-r--r--src/devices/cpu/z8000/z8000ops.hxx378
-rw-r--r--src/devices/imagedev/avivideo.cpp58
-rw-r--r--src/devices/imagedev/avivideo.h45
-rw-r--r--src/devices/imagedev/bitbngr.cpp41
-rw-r--r--src/devices/imagedev/bitbngr.h41
-rw-r--r--src/devices/imagedev/cartrom.cpp30
-rw-r--r--src/devices/imagedev/cartrom.h55
-rw-r--r--src/devices/imagedev/cassette.cpp345
-rw-r--r--src/devices/imagedev/cassette.h99
-rw-r--r--src/devices/imagedev/cdromimg.cpp283
-rw-r--r--src/devices/imagedev/cdromimg.h117
-rw-r--r--src/devices/imagedev/chd_cd.cpp130
-rw-r--r--src/devices/imagedev/chd_cd.h70
-rw-r--r--src/devices/imagedev/diablo.cpp144
-rw-r--r--src/devices/imagedev/diablo.h59
-rw-r--r--src/devices/imagedev/flopdrv.cpp441
-rw-r--r--src/devices/imagedev/flopdrv.h115
-rw-r--r--src/devices/imagedev/floppy.cpp2274
-rw-r--r--src/devices/imagedev/floppy.h413
-rw-r--r--src/devices/imagedev/harddriv.cpp280
-rw-r--r--src/devices/imagedev/harddriv.h92
-rw-r--r--src/devices/imagedev/magtape.cpp35
-rw-r--r--src/devices/imagedev/magtape.h56
-rw-r--r--src/devices/imagedev/memcard.cpp18
-rw-r--r--src/devices/imagedev/memcard.h39
-rw-r--r--src/devices/imagedev/mfmhd.cpp464
-rw-r--r--src/devices/imagedev/mfmhd.h52
-rw-r--r--src/devices/imagedev/microdrv.cpp32
-rw-r--r--src/devices/imagedev/microdrv.h52
-rw-r--r--src/devices/imagedev/midiin.cpp567
-rw-r--r--src/devices/imagedev/midiin.h156
-rw-r--r--src/devices/imagedev/midiout.cpp40
-rw-r--r--src/devices/imagedev/midiout.h40
-rw-r--r--src/devices/imagedev/papertape.cpp38
-rw-r--r--src/devices/imagedev/papertape.h71
-rw-r--r--src/devices/imagedev/picture.cpp49
-rw-r--r--src/devices/imagedev/picture.h32
-rw-r--r--src/devices/imagedev/printer.cpp19
-rw-r--r--src/devices/imagedev/printer.h33
-rw-r--r--src/devices/imagedev/simh_tape_image.cpp85
-rw-r--r--src/devices/imagedev/simh_tape_image.h52
-rw-r--r--src/devices/imagedev/snapquik.cpp61
-rw-r--r--src/devices/imagedev/snapquik.h56
-rw-r--r--src/devices/imagedev/wafadrive.cpp11
-rw-r--r--src/devices/imagedev/wafadrive.h35
-rw-r--r--src/devices/machine/1801vp128.cpp818
-rw-r--r--src/devices/machine/1801vp128.h213
-rw-r--r--src/devices/machine/1ma6.cpp18
-rw-r--r--src/devices/machine/1ma6.h22
-rw-r--r--src/devices/machine/1mb5.cpp84
-rw-r--r--src/devices/machine/1mb5.h28
-rw-r--r--src/devices/machine/2812fifo.cpp17
-rw-r--r--src/devices/machine/2812fifo.h21
-rw-r--r--src/devices/machine/28fxxx.cpp14
-rw-r--r--src/devices/machine/28fxxx.h12
-rw-r--r--src/devices/machine/40105.cpp40
-rw-r--r--src/devices/machine/40105.h13
-rw-r--r--src/devices/machine/53c7xx.cpp59
-rw-r--r--src/devices/machine/53c7xx.h13
-rw-r--r--src/devices/machine/53c810.cpp11
-rw-r--r--src/devices/machine/53c810.h16
-rw-r--r--src/devices/machine/64h156.cpp34
-rw-r--r--src/devices/machine/64h156.h72
-rw-r--r--src/devices/machine/6522via.cpp449
-rw-r--r--src/devices/machine/6522via.h103
-rw-r--r--src/devices/machine/6525tpi.cpp78
-rw-r--r--src/devices/machine/6525tpi.h34
-rw-r--r--src/devices/machine/6532riot.cpp515
-rw-r--r--src/devices/machine/6532riot.h123
-rw-r--r--src/devices/machine/68153bim.cpp28
-rw-r--r--src/devices/machine/68153bim.h26
-rw-r--r--src/devices/machine/6821pia.cpp399
-rw-r--r--src/devices/machine/6821pia.h74
-rw-r--r--src/devices/machine/68230pit.cpp290
-rw-r--r--src/devices/machine/68230pit.h82
-rw-r--r--src/devices/machine/68307.cpp89
-rw-r--r--src/devices/machine/68307.h57
-rw-r--r--src/devices/machine/68307bus.cpp28
-rw-r--r--src/devices/machine/68307bus.h6
-rw-r--r--src/devices/machine/68307sim.cpp24
-rw-r--r--src/devices/machine/68307tmu.cpp56
-rw-r--r--src/devices/machine/68340.cpp95
-rw-r--r--src/devices/machine/68340.h49
-rw-r--r--src/devices/machine/68340dma.cpp8
-rw-r--r--src/devices/machine/68340ser.cpp12
-rw-r--r--src/devices/machine/68340ser.h4
-rw-r--r--src/devices/machine/68340sim.cpp141
-rw-r--r--src/devices/machine/68340tmu.cpp30
-rw-r--r--src/devices/machine/68340tmu.h13
-rw-r--r--src/devices/machine/6840ptm.cpp649
-rw-r--r--src/devices/machine/6840ptm.h58
-rw-r--r--src/devices/machine/6850acia.cpp69
-rw-r--r--src/devices/machine/6850acia.h14
-rw-r--r--src/devices/machine/68561mpcc.cpp44
-rw-r--r--src/devices/machine/68561mpcc.h22
-rw-r--r--src/devices/machine/6883sam.cpp491
-rw-r--r--src/devices/machine/6883sam.h219
-rw-r--r--src/devices/machine/7200fifo.cpp55
-rw-r--r--src/devices/machine/7200fifo.h19
-rw-r--r--src/devices/machine/7400.cpp95
-rw-r--r--src/devices/machine/7400.h85
-rw-r--r--src/devices/machine/7404.cpp29
-rw-r--r--src/devices/machine/7404.h32
-rw-r--r--src/devices/machine/74123.cpp50
-rw-r--r--src/devices/machine/74123.h17
-rw-r--r--src/devices/machine/74145.cpp8
-rw-r--r--src/devices/machine/74145.h8
-rw-r--r--src/devices/machine/74148.cpp11
-rw-r--r--src/devices/machine/74148.h8
-rw-r--r--src/devices/machine/74153.cpp34
-rw-r--r--src/devices/machine/74153.h40
-rw-r--r--src/devices/machine/74157.cpp45
-rw-r--r--src/devices/machine/74157.h28
-rw-r--r--src/devices/machine/74161.cpp70
-rw-r--r--src/devices/machine/74161.h38
-rw-r--r--src/devices/machine/74165.cpp12
-rw-r--r--src/devices/machine/74165.h18
-rw-r--r--src/devices/machine/74166.cpp12
-rw-r--r--src/devices/machine/74166.h18
-rw-r--r--src/devices/machine/74175.cpp29
-rw-r--r--src/devices/machine/74175.h24
-rw-r--r--src/devices/machine/74181.cpp4
-rw-r--r--src/devices/machine/74181.h14
-rw-r--r--src/devices/machine/74259.cpp30
-rw-r--r--src/devices/machine/74259.h26
-rw-r--r--src/devices/machine/74381.cpp4
-rw-r--r--src/devices/machine/74381.h4
-rw-r--r--src/devices/machine/74543.cpp117
-rw-r--r--src/devices/machine/74543.h124
-rw-r--r--src/devices/machine/7474.cpp34
-rw-r--r--src/devices/machine/7474.h26
-rw-r--r--src/devices/machine/8042kbdc.cpp211
-rw-r--r--src/devices/machine/8042kbdc.h51
-rw-r--r--src/devices/machine/82s129.cpp38
-rw-r--r--src/devices/machine/82s129.h40
-rw-r--r--src/devices/machine/8364_paula.cpp295
-rw-r--r--src/devices/machine/8364_paula.h155
-rw-r--r--src/devices/machine/8530scc.cpp645
-rw-r--r--src/devices/machine/8530scc.h103
-rw-r--r--src/devices/machine/aakart.cpp209
-rw-r--r--src/devices/machine/aakart.h81
-rw-r--r--src/devices/machine/acorn_bmu.cpp267
-rw-r--r--src/devices/machine/acorn_bmu.h87
-rw-r--r--src/devices/machine/acorn_ioc.cpp400
-rw-r--r--src/devices/machine/acorn_ioc.h129
-rw-r--r--src/devices/machine/acorn_lc.cpp152
-rw-r--r--src/devices/machine/acorn_lc.h85
-rw-r--r--src/devices/machine/acorn_memc.cpp512
-rw-r--r--src/devices/machine/acorn_memc.h101
-rw-r--r--src/devices/machine/acorn_vidc.cpp526
-rw-r--r--src/devices/machine/acorn_vidc.h176
-rw-r--r--src/devices/machine/adc0804.cpp276
-rw-r--r--src/devices/machine/adc0804.h125
-rw-r--r--src/devices/machine/adc0808.cpp21
-rw-r--r--src/devices/machine/adc0808.h17
-rw-r--r--src/devices/machine/adc083x.cpp27
-rw-r--r--src/devices/machine/adc083x.h26
-rw-r--r--src/devices/machine/adc0844.cpp30
-rw-r--r--src/devices/machine/adc0844.h17
-rw-r--r--src/devices/machine/adc1038.cpp11
-rw-r--r--src/devices/machine/adc1038.h23
-rw-r--r--src/devices/machine/adc1213x.cpp3
-rw-r--r--src/devices/machine/adc1213x.h14
-rw-r--r--src/devices/machine/aic565.cpp15
-rw-r--r--src/devices/machine/aic565.h7
-rw-r--r--src/devices/machine/aic580.cpp364
-rw-r--r--src/devices/machine/aic580.h86
-rw-r--r--src/devices/machine/aic6250.cpp21
-rw-r--r--src/devices/machine/aic6250.h12
-rw-r--r--src/devices/machine/aicartc.cpp15
-rw-r--r--src/devices/machine/aicartc.h11
-rw-r--r--src/devices/machine/akiko.cpp913
-rw-r--r--src/devices/machine/akiko.h131
-rw-r--r--src/devices/machine/alpha_8921.cpp212
-rw-r--r--src/devices/machine/alpha_8921.h67
-rw-r--r--src/devices/machine/am25s55x.cpp2
-rw-r--r--src/devices/machine/am25s55x.h8
-rw-r--r--src/devices/machine/am2847.cpp18
-rw-r--r--src/devices/machine/am2847.h22
-rw-r--r--src/devices/machine/am2901b.cpp216
-rw-r--r--src/devices/machine/am2901b.h105
-rw-r--r--src/devices/machine/am2910.cpp31
-rw-r--r--src/devices/machine/am2910.h23
-rw-r--r--src/devices/machine/am53cf96.cpp194
-rw-r--r--src/devices/machine/am53cf96.h72
-rw-r--r--src/devices/machine/am79c30.cpp2040
-rw-r--r--src/devices/machine/am79c30.h213
-rw-r--r--src/devices/machine/am79c90.cpp98
-rw-r--r--src/devices/machine/am79c90.h16
-rw-r--r--src/devices/machine/am9513.cpp92
-rw-r--r--src/devices/machine/am9513.h44
-rw-r--r--src/devices/machine/am9516.cpp1027
-rw-r--r--src/devices/machine/am9516.h135
-rw-r--r--src/devices/machine/am9517a.cpp213
-rw-r--r--src/devices/machine/am9517a.h58
-rw-r--r--src/devices/machine/am9519.cpp135
-rw-r--r--src/devices/machine/am9519.h30
-rw-r--r--src/devices/machine/amigafdc.cpp661
-rw-r--r--src/devices/machine/amigafdc.h128
-rw-r--r--src/devices/machine/appldriv.cpp336
-rw-r--r--src/devices/machine/appldriv.h66
-rw-r--r--src/devices/machine/applefdc.cpp586
-rw-r--r--src/devices/machine/applefdc.h156
-rw-r--r--src/devices/machine/applefdintf.cpp87
-rw-r--r--src/devices/machine/applefdintf.h116
-rw-r--r--src/devices/machine/applepic.cpp506
-rw-r--r--src/devices/machine/applepic.h110
-rw-r--r--src/devices/machine/archimedes_keyb.cpp414
-rw-r--r--src/devices/machine/archimedes_keyb.h73
-rw-r--r--src/devices/machine/arm_iomd.cpp761
-rw-r--r--src/devices/machine/arm_iomd.h207
-rw-r--r--src/devices/machine/at.cpp427
-rw-r--r--src/devices/machine/at.h107
-rw-r--r--src/devices/machine/at28c16.cpp52
-rw-r--r--src/devices/machine/at28c16.h18
-rw-r--r--src/devices/machine/at28c64b.cpp271
-rw-r--r--src/devices/machine/at28c64b.h80
-rw-r--r--src/devices/machine/at29x.cpp36
-rw-r--r--src/devices/machine/at29x.h9
-rw-r--r--src/devices/machine/at45dbxx.cpp49
-rw-r--r--src/devices/machine/at45dbxx.h16
-rw-r--r--src/devices/machine/at_keybc.cpp60
-rw-r--r--src/devices/machine/at_keybc.h30
-rw-r--r--src/devices/machine/atadev.cpp23
-rw-r--r--src/devices/machine/atadev.h47
-rw-r--r--src/devices/machine/atahle.cpp764
-rw-r--r--src/devices/machine/atahle.h97
-rw-r--r--src/devices/machine/atapicdr.cpp151
-rw-r--r--src/devices/machine/atapicdr.h54
-rw-r--r--src/devices/machine/atastorage.cpp (renamed from src/devices/machine/idehd.cpp)358
-rw-r--r--src/devices/machine/atastorage.h (renamed from src/devices/machine/idehd.h)77
-rw-r--r--src/devices/machine/atmel_arm_aic.cpp10
-rw-r--r--src/devices/machine/atmel_arm_aic.h64
-rw-r--r--src/devices/machine/autoconfig.cpp4
-rw-r--r--src/devices/machine/autoconfig.h4
-rw-r--r--src/devices/machine/ay31015.cpp101
-rw-r--r--src/devices/machine/ay31015.h56
-rw-r--r--src/devices/machine/bacta_datalogger.cpp217
-rw-r--r--src/devices/machine/bacta_datalogger.h39
-rw-r--r--src/devices/machine/bankdev.h16
-rw-r--r--src/devices/machine/bcreader.h10
-rw-r--r--src/devices/machine/bitmap_printer.cpp484
-rw-r--r--src/devices/machine/bitmap_printer.h124
-rw-r--r--src/devices/machine/bl_handhelds_menucontrol.cpp214
-rw-r--r--src/devices/machine/bl_handhelds_menucontrol.h64
-rw-r--r--src/devices/machine/bq4847.cpp511
-rw-r--r--src/devices/machine/bq4847.h98
-rw-r--r--src/devices/machine/bq48x2.cpp558
-rw-r--r--src/devices/machine/bq48x2.h135
-rw-r--r--src/devices/machine/buffer.h27
-rw-r--r--src/devices/machine/busmouse.cpp19
-rw-r--r--src/devices/machine/busmouse.h19
-rw-r--r--src/devices/machine/cammu.cpp814
-rw-r--r--src/devices/machine/cammu.h665
-rw-r--r--src/devices/machine/cat702.cpp310
-rw-r--r--src/devices/machine/cat702.h63
-rw-r--r--src/devices/machine/cdp1852.cpp56
-rw-r--r--src/devices/machine/cdp1852.h12
-rw-r--r--src/devices/machine/cdp1871.cpp45
-rw-r--r--src/devices/machine/cdp1871.h17
-rw-r--r--src/devices/machine/cdp1879.cpp21
-rw-r--r--src/devices/machine/cdp1879.h11
-rw-r--r--src/devices/machine/ch376.cpp527
-rw-r--r--src/devices/machine/ch376.h81
-rw-r--r--src/devices/machine/chessmachine.cpp95
-rw-r--r--src/devices/machine/chessmachine.h27
-rw-r--r--src/devices/machine/clock.cpp125
-rw-r--r--src/devices/machine/clock.h39
-rw-r--r--src/devices/machine/com52c50.cpp157
-rw-r--r--src/devices/machine/com52c50.h88
-rw-r--r--src/devices/machine/com8116.cpp74
-rw-r--r--src/devices/machine/com8116.h18
-rw-r--r--src/devices/machine/cop452.cpp342
-rw-r--r--src/devices/machine/cop452.h97
-rw-r--r--src/devices/machine/corvushd.cpp231
-rw-r--r--src/devices/machine/corvushd.h26
-rw-r--r--src/devices/machine/cr511b.cpp766
-rw-r--r--src/devices/machine/cr511b.h146
-rw-r--r--src/devices/machine/cs4031.cpp135
-rw-r--r--src/devices/machine/cs4031.h110
-rw-r--r--src/devices/machine/cs8221.cpp10
-rw-r--r--src/devices/machine/cs8221.h12
-rw-r--r--src/devices/machine/cs8900a.cpp1512
-rw-r--r--src/devices/machine/cs8900a.h108
-rw-r--r--src/devices/machine/cxd1095.cpp20
-rw-r--r--src/devices/machine/cxd1095.h14
-rw-r--r--src/devices/machine/cxd1185.cpp924
-rw-r--r--src/devices/machine/cxd1185.h257
-rw-r--r--src/devices/machine/dc7085.cpp449
-rw-r--r--src/devices/machine/dc7085.h186
-rw-r--r--src/devices/machine/diablo_hd.cpp48
-rw-r--r--src/devices/machine/diablo_hd.h12
-rw-r--r--src/devices/machine/dimm_spd.cpp110
-rw-r--r--src/devices/machine/dimm_spd.h49
-rw-r--r--src/devices/machine/dl11.cpp464
-rw-r--r--src/devices/machine/dl11.h138
-rw-r--r--src/devices/machine/dmac.cpp656
-rw-r--r--src/devices/machine/dmac.h213
-rw-r--r--src/devices/machine/dp8390.cpp105
-rw-r--r--src/devices/machine/dp8390.h18
-rw-r--r--src/devices/machine/dp83932c.cpp630
-rw-r--r--src/devices/machine/dp83932c.h254
-rw-r--r--src/devices/machine/dp8573.cpp358
-rw-r--r--src/devices/machine/dp8573.h149
-rw-r--r--src/devices/machine/dp8573a.cpp486
-rw-r--r--src/devices/machine/dp8573a.h73
-rw-r--r--src/devices/machine/ds1204.cpp118
-rw-r--r--src/devices/machine/ds1204.h14
-rw-r--r--src/devices/machine/ds1205.cpp134
-rw-r--r--src/devices/machine/ds1205.h14
-rw-r--r--src/devices/machine/ds1207.cpp682
-rw-r--r--src/devices/machine/ds1207.h122
-rw-r--r--src/devices/machine/ds1215.cpp340
-rw-r--r--src/devices/machine/ds1215.h77
-rw-r--r--src/devices/machine/ds128x.cpp15
-rw-r--r--src/devices/machine/ds1302.cpp129
-rw-r--r--src/devices/machine/ds1302.h36
-rw-r--r--src/devices/machine/ds1315.cpp307
-rw-r--r--src/devices/machine/ds1315.h65
-rw-r--r--src/devices/machine/ds1386.cpp191
-rw-r--r--src/devices/machine/ds1386.h52
-rw-r--r--src/devices/machine/ds17x85.h2
-rw-r--r--src/devices/machine/ds1994.cpp601
-rw-r--r--src/devices/machine/ds1994.h37
-rw-r--r--src/devices/machine/ds2401.cpp133
-rw-r--r--src/devices/machine/ds2401.h17
-rw-r--r--src/devices/machine/ds2404.cpp178
-rw-r--r--src/devices/machine/ds2404.h50
-rw-r--r--src/devices/machine/ds2430a.cpp693
-rw-r--r--src/devices/machine/ds2430a.h145
-rw-r--r--src/devices/machine/ds6417.cpp174
-rw-r--r--src/devices/machine/ds6417.h63
-rw-r--r--src/devices/machine/ds75160a.cpp26
-rw-r--r--src/devices/machine/ds75160a.h10
-rw-r--r--src/devices/machine/ds75161a.cpp111
-rw-r--r--src/devices/machine/ds75161a.h42
-rw-r--r--src/devices/machine/e0516.cpp259
-rw-r--r--src/devices/machine/e0516.h45
-rw-r--r--src/devices/machine/e05a03.cpp39
-rw-r--r--src/devices/machine/e05a03.h22
-rw-r--r--src/devices/machine/e05a30.cpp66
-rw-r--r--src/devices/machine/e05a30.h36
-rw-r--r--src/devices/machine/edlc.cpp334
-rw-r--r--src/devices/machine/edlc.h138
-rw-r--r--src/devices/machine/eeprom.cpp56
-rw-r--r--src/devices/machine/eeprom.h18
-rw-r--r--src/devices/machine/eeprompar.cpp14
-rw-r--r--src/devices/machine/eeprompar.h20
-rw-r--r--src/devices/machine/eepromser.cpp169
-rw-r--r--src/devices/machine/eepromser.h32
-rw-r--r--src/devices/machine/em_reel.cpp125
-rw-r--r--src/devices/machine/em_reel.h89
-rw-r--r--src/devices/machine/er1400.cpp56
-rw-r--r--src/devices/machine/er1400.h21
-rw-r--r--src/devices/machine/er2055.cpp16
-rw-r--r--src/devices/machine/er2055.h8
-rw-r--r--src/devices/machine/exorterm.cpp890
-rw-r--r--src/devices/machine/exorterm.h150
-rw-r--r--src/devices/machine/f3853.cpp60
-rw-r--r--src/devices/machine/f3853.h38
-rw-r--r--src/devices/machine/f4702.cpp260
-rw-r--r--src/devices/machine/f4702.h75
-rw-r--r--src/devices/machine/fdc37c665gt.cpp457
-rw-r--r--src/devices/machine/fdc37c665gt.h127
-rw-r--r--src/devices/machine/fdc37c93x.cpp302
-rw-r--r--src/devices/machine/fdc37c93x.h152
-rw-r--r--src/devices/machine/fdc_pll.cpp15
-rw-r--r--src/devices/machine/fdc_pll.h6
-rw-r--r--src/devices/machine/fga002.cpp117
-rw-r--r--src/devices/machine/fga002.h32
-rw-r--r--src/devices/machine/fm_scsi.cpp440
-rw-r--r--src/devices/machine/fm_scsi.h73
-rw-r--r--src/devices/machine/gayle.cpp204
-rw-r--r--src/devices/machine/gayle.h75
-rw-r--r--src/devices/machine/gen_fifo.cpp78
-rw-r--r--src/devices/machine/gen_fifo.h10
-rw-r--r--src/devices/machine/gen_latch.cpp21
-rw-r--r--src/devices/machine/gen_latch.h24
-rw-r--r--src/devices/machine/generalplus_gpl16250soc.cpp1856
-rw-r--r--src/devices/machine/generalplus_gpl16250soc.h486
-rw-r--r--src/devices/machine/generalplus_gpl16250soc_video.cpp1168
-rw-r--r--src/devices/machine/generalplus_gpl16250soc_video.h262
-rw-r--r--src/devices/machine/generic_spi_flash.cpp199
-rw-r--r--src/devices/machine/generic_spi_flash.h83
-rw-r--r--src/devices/machine/genpc.cpp254
-rw-r--r--src/devices/machine/genpc.h164
-rw-r--r--src/devices/machine/gt64xxx.cpp392
-rw-r--r--src/devices/machine/gt64xxx.h56
-rw-r--r--src/devices/machine/gt913_io.cpp155
-rw-r--r--src/devices/machine/gt913_io.h73
-rw-r--r--src/devices/machine/gt913_kbd.cpp104
-rw-r--r--src/devices/machine/gt913_kbd.h56
-rw-r--r--src/devices/machine/gt913_snd.cpp384
-rw-r--r--src/devices/machine/gt913_snd.h88
-rw-r--r--src/devices/machine/hd63450.cpp212
-rw-r--r--src/devices/machine/hd63450.h47
-rw-r--r--src/devices/machine/hd64610.cpp66
-rw-r--r--src/devices/machine/hd64610.h17
-rw-r--r--src/devices/machine/hdc92x4.cpp354
-rw-r--r--src/devices/machine/hdc92x4.h37
-rw-r--r--src/devices/machine/hp_dc100_tape.cpp347
-rw-r--r--src/devices/machine/hp_dc100_tape.h37
-rw-r--r--src/devices/machine/hp_taco.cpp306
-rw-r--r--src/devices/machine/hp_taco.h35
-rw-r--r--src/devices/machine/i2chle.cpp276
-rw-r--r--src/devices/machine/i2chle.h46
-rw-r--r--src/devices/machine/i2cmem.cpp402
-rw-r--r--src/devices/machine/i2cmem.h83
-rw-r--r--src/devices/machine/i3001.cpp137
-rw-r--r--src/devices/machine/i3001.h106
-rw-r--r--src/devices/machine/i3002.cpp428
-rw-r--r--src/devices/machine/i3002.h130
-rw-r--r--src/devices/machine/i6300esb.cpp176
-rw-r--r--src/devices/machine/i6300esb.h186
-rw-r--r--src/devices/machine/i7220.cpp301
-rw-r--r--src/devices/machine/i7220.h69
-rw-r--r--src/devices/machine/i80130.cpp53
-rw-r--r--src/devices/machine/i80130.h40
-rw-r--r--src/devices/machine/i8087.cpp129
-rw-r--r--src/devices/machine/i8087.h23
-rw-r--r--src/devices/machine/i8155.cpp160
-rw-r--r--src/devices/machine/i8155.h15
-rw-r--r--src/devices/machine/i8212.cpp12
-rw-r--r--src/devices/machine/i8212.h6
-rw-r--r--src/devices/machine/i8214.cpp92
-rw-r--r--src/devices/machine/i8214.h16
-rw-r--r--src/devices/machine/i82355.cpp31
-rw-r--r--src/devices/machine/i82355.h7
-rw-r--r--src/devices/machine/i82357.cpp67
-rw-r--r--src/devices/machine/i82357.h18
-rw-r--r--src/devices/machine/i82371eb_acpi.cpp194
-rw-r--r--src/devices/machine/i82371eb_acpi.h63
-rw-r--r--src/devices/machine/i82371eb_ide.cpp37
-rw-r--r--src/devices/machine/i82371eb_ide.h26
-rw-r--r--src/devices/machine/i82371eb_isa.cpp49
-rw-r--r--src/devices/machine/i82371eb_isa.h29
-rw-r--r--src/devices/machine/i82371eb_usb.cpp96
-rw-r--r--src/devices/machine/i82371eb_usb.h37
-rw-r--r--src/devices/machine/i82371sb.cpp534
-rw-r--r--src/devices/machine/i82371sb.h337
-rw-r--r--src/devices/machine/i8243.cpp17
-rw-r--r--src/devices/machine/i8243.h12
-rw-r--r--src/devices/machine/i82439hx.cpp160
-rw-r--r--src/devices/machine/i82439hx.h75
-rw-r--r--src/devices/machine/i82439tx.cpp53
-rw-r--r--src/devices/machine/i82439tx.h56
-rw-r--r--src/devices/machine/i82443bx_host.cpp193
-rw-r--r--src/devices/machine/i82443bx_host.h105
-rw-r--r--src/devices/machine/i8251.cpp173
-rw-r--r--src/devices/machine/i8251.h61
-rw-r--r--src/devices/machine/i82541.h10
-rw-r--r--src/devices/machine/i8255.cpp46
-rw-r--r--src/devices/machine/i8255.h15
-rw-r--r--src/devices/machine/i8257.cpp139
-rw-r--r--src/devices/machine/i8257.h33
-rw-r--r--src/devices/machine/i82586.cpp357
-rw-r--r--src/devices/machine/i82586.h23
-rw-r--r--src/devices/machine/i8271.cpp189
-rw-r--r--src/devices/machine/i8271.h17
-rw-r--r--src/devices/machine/i8279.cpp362
-rw-r--r--src/devices/machine/i8279.h49
-rw-r--r--src/devices/machine/i82875p.cpp109
-rw-r--r--src/devices/machine/i82875p.h122
-rw-r--r--src/devices/machine/i8291a.cpp183
-rw-r--r--src/devices/machine/i8291a.h62
-rw-r--r--src/devices/machine/i8355.cpp34
-rw-r--r--src/devices/machine/i8355.h10
-rw-r--r--src/devices/machine/ibm21s850.cpp161
-rw-r--r--src/devices/machine/ibm21s850.h209
-rw-r--r--src/devices/machine/icd2061a.cpp323
-rw-r--r--src/devices/machine/icd2061a.h105
-rw-r--r--src/devices/machine/icm7170.cpp329
-rw-r--r--src/devices/machine/icm7170.h89
-rw-r--r--src/devices/machine/idectrl.cpp4
-rw-r--r--src/devices/machine/idectrl.h27
-rw-r--r--src/devices/machine/ie15.cpp281
-rw-r--r--src/devices/machine/ie15.h141
-rw-r--r--src/devices/machine/ie15_kbd.cpp192
-rw-r--r--src/devices/machine/ie15_kbd.h38
-rw-r--r--src/devices/machine/im6402.cpp53
-rw-r--r--src/devices/machine/im6402.h51
-rw-r--r--src/devices/machine/input_merger.cpp38
-rw-r--r--src/devices/machine/input_merger.h19
-rw-r--r--src/devices/machine/ins8154.cpp25
-rw-r--r--src/devices/machine/ins8154.h6
-rw-r--r--src/devices/machine/ins8250.cpp123
-rw-r--r--src/devices/machine/ins8250.h26
-rw-r--r--src/devices/machine/intelfsh.cpp788
-rw-r--r--src/devices/machine/intelfsh.h282
-rw-r--r--src/devices/machine/iopcdvd.cpp4
-rw-r--r--src/devices/machine/iopcdvd.h8
-rw-r--r--src/devices/machine/iopdma.cpp14
-rw-r--r--src/devices/machine/iopdma.h12
-rw-r--r--src/devices/machine/iopintc.cpp4
-rw-r--r--src/devices/machine/iopintc.h8
-rw-r--r--src/devices/machine/iopsio2.cpp6
-rw-r--r--src/devices/machine/iopsio2.h8
-rw-r--r--src/devices/machine/ioptimer.cpp17
-rw-r--r--src/devices/machine/ioptimer.h8
-rw-r--r--src/devices/machine/it8705f.cpp593
-rw-r--r--src/devices/machine/it8705f.h131
-rw-r--r--src/devices/machine/iwm.cpp536
-rw-r--r--src/devices/machine/iwm.h93
-rw-r--r--src/devices/machine/jvsdev.cpp10
-rw-r--r--src/devices/machine/jvsdev.h6
-rw-r--r--src/devices/machine/jvshost.cpp10
-rw-r--r--src/devices/machine/jvshost.h4
-rw-r--r--src/devices/machine/k033906.cpp12
-rw-r--r--src/devices/machine/k033906.h9
-rw-r--r--src/devices/machine/k053252.cpp56
-rw-r--r--src/devices/machine/k053252.h10
-rw-r--r--src/devices/machine/k054321.cpp38
-rw-r--r--src/devices/machine/k054321.h38
-rw-r--r--src/devices/machine/k056230.cpp230
-rw-r--r--src/devices/machine/k056230.h54
-rw-r--r--src/devices/machine/kb3600.cpp43
-rw-r--r--src/devices/machine/kb3600.h7
-rw-r--r--src/devices/machine/keyboard.cpp17
-rw-r--r--src/devices/machine/keyboard.h20
-rw-r--r--src/devices/machine/keyboard.ipp6
-rw-r--r--src/devices/machine/keytronic_l2207.cpp311
-rw-r--r--src/devices/machine/keytronic_l2207.h75
-rw-r--r--src/devices/machine/kr1601rr1.cpp154
-rw-r--r--src/devices/machine/kr1601rr1.h77
-rw-r--r--src/devices/machine/kr2376.cpp165
-rw-r--r--src/devices/machine/kr2376.h31
-rw-r--r--src/devices/machine/laserdsc.cpp369
-rw-r--r--src/devices/machine/laserdsc.h132
-rw-r--r--src/devices/machine/latch8.cpp76
-rw-r--r--src/devices/machine/latch8.h120
-rw-r--r--src/devices/machine/lc89510.h4
-rw-r--r--src/devices/machine/ldp1000.cpp10
-rw-r--r--src/devices/machine/ldp1000.h10
-rw-r--r--src/devices/machine/ldp1450.cpp2
-rw-r--r--src/devices/machine/ldp1450.h6
-rw-r--r--src/devices/machine/ldp1450hle.cpp944
-rw-r--r--src/devices/machine/ldp1450hle.h198
-rw-r--r--src/devices/machine/ldpr8210.cpp315
-rw-r--r--src/devices/machine/ldpr8210.h98
-rw-r--r--src/devices/machine/ldstub.cpp4
-rw-r--r--src/devices/machine/ldstub.h16
-rw-r--r--src/devices/machine/ldv1000.cpp205
-rw-r--r--src/devices/machine/ldv1000.h83
-rw-r--r--src/devices/machine/ldv1000hle.cpp1046
-rw-r--r--src/devices/machine/ldv1000hle.h201
-rw-r--r--src/devices/machine/ldv4200hle.cpp979
-rw-r--r--src/devices/machine/ldv4200hle.h212
-rw-r--r--src/devices/machine/ldvp931.cpp271
-rw-r--r--src/devices/machine/ldvp931.h78
-rw-r--r--src/devices/machine/legscsi.cpp8
-rw-r--r--src/devices/machine/legscsi.h2
-rw-r--r--src/devices/machine/lh5810.cpp16
-rw-r--r--src/devices/machine/lh5810.h8
-rw-r--r--src/devices/machine/linflash.cpp202
-rw-r--r--src/devices/machine/linflash.h80
-rw-r--r--src/devices/machine/locomo.cpp376
-rw-r--r--src/devices/machine/locomo.h34
-rw-r--r--src/devices/machine/lpc-acpi.cpp104
-rw-r--r--src/devices/machine/lpc-acpi.h110
-rw-r--r--src/devices/machine/lpc-pit.cpp6
-rw-r--r--src/devices/machine/lpc-pit.h12
-rw-r--r--src/devices/machine/lpc-rtc.cpp20
-rw-r--r--src/devices/machine/lpc-rtc.h24
-rw-r--r--src/devices/machine/lpci.cpp43
-rw-r--r--src/devices/machine/lpci.h37
-rw-r--r--src/devices/machine/m3002.cpp497
-rw-r--r--src/devices/machine/m3002.h114
-rw-r--r--src/devices/machine/m68sfdc.cpp848
-rw-r--r--src/devices/machine/m68sfdc.h150
-rw-r--r--src/devices/machine/m6m80011ap.cpp33
-rw-r--r--src/devices/machine/m6m80011ap.h18
-rw-r--r--src/devices/machine/m950x0.cpp207
-rw-r--r--src/devices/machine/m950x0.h97
-rw-r--r--src/devices/machine/mb14241.cpp14
-rw-r--r--src/devices/machine/mb14241.h17
-rw-r--r--src/devices/machine/mb3773.cpp8
-rw-r--r--src/devices/machine/mb3773.h8
-rw-r--r--src/devices/machine/mb8421.cpp216
-rw-r--r--src/devices/machine/mb8421.h213
-rw-r--r--src/devices/machine/mb87030.cpp380
-rw-r--r--src/devices/machine/mb87030.h116
-rw-r--r--src/devices/machine/mb87078.cpp4
-rw-r--r--src/devices/machine/mb87078.h4
-rw-r--r--src/devices/machine/mb8795.cpp72
-rw-r--r--src/devices/machine/mb8795.h44
-rw-r--r--src/devices/machine/mb89352.cpp671
-rw-r--r--src/devices/machine/mb89352.h73
-rw-r--r--src/devices/machine/mb89363b.cpp76
-rw-r--r--src/devices/machine/mb89363b.h34
-rw-r--r--src/devices/machine/mb89371.cpp22
-rw-r--r--src/devices/machine/mb89371.h6
-rw-r--r--src/devices/machine/mb89374.cpp30
-rw-r--r--src/devices/machine/mb89374.h28
-rw-r--r--src/devices/machine/mc14411.cpp115
-rw-r--r--src/devices/machine/mc14411.h74
-rw-r--r--src/devices/machine/mc146818.cpp356
-rw-r--r--src/devices/machine/mc146818.h72
-rw-r--r--src/devices/machine/mc2661.cpp507
-rw-r--r--src/devices/machine/mc2661.h101
-rw-r--r--src/devices/machine/mc68328.cpp6127
-rw-r--r--src/devices/machine/mc68328.h1411
-rw-r--r--src/devices/machine/mc6843.cpp1543
-rw-r--r--src/devices/machine/mc6843.h227
-rw-r--r--src/devices/machine/mc6844.cpp537
-rw-r--r--src/devices/machine/mc6844.h146
-rw-r--r--src/devices/machine/mc6846.cpp56
-rw-r--r--src/devices/machine/mc6846.h10
-rw-r--r--src/devices/machine/mc6852.cpp277
-rw-r--r--src/devices/machine/mc6852.h38
-rw-r--r--src/devices/machine/mc6854.cpp335
-rw-r--r--src/devices/machine/mc6854.h46
-rw-r--r--src/devices/machine/mc68681.cpp387
-rw-r--r--src/devices/machine/mc68681.h65
-rw-r--r--src/devices/machine/mc68901.cpp1055
-rw-r--r--src/devices/machine/mc68901.h167
-rw-r--r--src/devices/machine/mc88200.cpp993
-rw-r--r--src/devices/machine/mc88200.h141
-rw-r--r--src/devices/machine/mccs1850.cpp65
-rw-r--r--src/devices/machine/mccs1850.h35
-rw-r--r--src/devices/machine/mcf5206e.cpp202
-rw-r--r--src/devices/machine/mcf5206e.h202
-rw-r--r--src/devices/machine/mdcr.cpp326
-rw-r--r--src/devices/machine/mdcr.h181
-rw-r--r--src/devices/machine/mediagx_cs5530_bridge.cpp562
-rw-r--r--src/devices/machine/mediagx_cs5530_bridge.h149
-rw-r--r--src/devices/machine/mediagx_cs5530_ide.cpp142
-rw-r--r--src/devices/machine/mediagx_cs5530_ide.h66
-rw-r--r--src/devices/machine/mediagx_cs5530_video.cpp55
-rw-r--r--src/devices/machine/mediagx_cs5530_video.h29
-rw-r--r--src/devices/machine/mediagx_host.cpp375
-rw-r--r--src/devices/machine/mediagx_host.h83
-rw-r--r--src/devices/machine/meters.cpp90
-rw-r--r--src/devices/machine/meters.h40
-rw-r--r--src/devices/machine/micomxe1a.cpp372
-rw-r--r--src/devices/machine/micomxe1a.h50
-rw-r--r--src/devices/machine/microtch.cpp180
-rw-r--r--src/devices/machine/microtch.h36
-rw-r--r--src/devices/machine/mm5307.cpp15
-rw-r--r--src/devices/machine/mm5307.h7
-rw-r--r--src/devices/machine/mm5740.cpp89
-rw-r--r--src/devices/machine/mm5740.h58
-rw-r--r--src/devices/machine/mm58167.cpp41
-rw-r--r--src/devices/machine/mm58167.h7
-rw-r--r--src/devices/machine/mm58174.cpp304
-rw-r--r--src/devices/machine/mm58174.h65
-rw-r--r--src/devices/machine/mm58274c.cpp60
-rw-r--r--src/devices/machine/mm58274c.h12
-rw-r--r--src/devices/machine/mm74c922.cpp92
-rw-r--r--src/devices/machine/mm74c922.h54
-rw-r--r--src/devices/machine/mos6526.cpp114
-rw-r--r--src/devices/machine/mos6526.h53
-rw-r--r--src/devices/machine/mos6529.cpp13
-rw-r--r--src/devices/machine/mos6529.h26
-rw-r--r--src/devices/machine/mos6530.cpp729
-rw-r--r--src/devices/machine/mos6530.h194
-rw-r--r--src/devices/machine/mos6530n.cpp831
-rw-r--r--src/devices/machine/mos6530n.h241
-rw-r--r--src/devices/machine/mos6551.cpp67
-rw-r--r--src/devices/machine/mos6551.h28
-rw-r--r--src/devices/machine/mos6702.h2
-rw-r--r--src/devices/machine/mos8706.cpp4
-rw-r--r--src/devices/machine/mos8706.h8
-rw-r--r--src/devices/machine/mos8722.cpp14
-rw-r--r--src/devices/machine/mos8722.h6
-rw-r--r--src/devices/machine/mos8726.cpp2
-rw-r--r--src/devices/machine/mos8726.h6
-rw-r--r--src/devices/machine/mpc106.cpp384
-rw-r--r--src/devices/machine/mpc106.h99
-rw-r--r--src/devices/machine/mpu401.cpp74
-rw-r--r--src/devices/machine/mpu401.h37
-rw-r--r--src/devices/machine/msm5001n.cpp199
-rw-r--r--src/devices/machine/msm5001n.h63
-rw-r--r--src/devices/machine/msm5832.cpp31
-rw-r--r--src/devices/machine/msm5832.h23
-rw-r--r--src/devices/machine/msm58321.cpp124
-rw-r--r--src/devices/machine/msm58321.h37
-rw-r--r--src/devices/machine/msm6200.cpp115
-rw-r--r--src/devices/machine/msm6200.h46
-rw-r--r--src/devices/machine/msm6242.cpp112
-rw-r--r--src/devices/machine/msm6242.h53
-rw-r--r--src/devices/machine/msm6253.cpp25
-rw-r--r--src/devices/machine/msm6253.h22
-rw-r--r--src/devices/machine/mv6436x.cpp1230
-rw-r--r--src/devices/machine/mv6436x.h282
-rw-r--r--src/devices/machine/mv_sonora.cpp405
-rw-r--r--src/devices/machine/mv_sonora.h76
-rw-r--r--src/devices/machine/myb3k_kbd.cpp59
-rw-r--r--src/devices/machine/myb3k_kbd.h42
-rw-r--r--src/devices/machine/nandflash.cpp653
-rw-r--r--src/devices/machine/nandflash.h169
-rw-r--r--src/devices/machine/ncr5380.cpp925
-rw-r--r--src/devices/machine/ncr5380.h217
-rw-r--r--src/devices/machine/ncr5380n.cpp608
-rw-r--r--src/devices/machine/ncr5380n.h235
-rw-r--r--src/devices/machine/ncr5385.cpp899
-rw-r--r--src/devices/machine/ncr5385.h149
-rw-r--r--src/devices/machine/ncr539x.cpp775
-rw-r--r--src/devices/machine/ncr539x.h83
-rw-r--r--src/devices/machine/ncr53c90.cpp (renamed from src/devices/machine/ncr5390.cpp)486
-rw-r--r--src/devices/machine/ncr53c90.h (renamed from src/devices/machine/ncr5390.h)100
-rw-r--r--src/devices/machine/netlist.cpp1210
-rw-r--r--src/devices/machine/netlist.h331
-rw-r--r--src/devices/machine/nmc9306.cpp165
-rw-r--r--src/devices/machine/nmc9306.h30
-rw-r--r--src/devices/machine/nmk112.cpp103
-rw-r--r--src/devices/machine/nmk112.h53
-rw-r--r--src/devices/machine/ns32081.cpp839
-rw-r--r--src/devices/machine/ns32081.h126
-rw-r--r--src/devices/machine/ns32082.cpp497
-rw-r--r--src/devices/machine/ns32082.h69
-rw-r--r--src/devices/machine/ns32202.cpp975
-rw-r--r--src/devices/machine/ns32202.h141
-rw-r--r--src/devices/machine/ns32382.cpp429
-rw-r--r--src/devices/machine/ns32382.h66
-rw-r--r--src/devices/machine/nsc810.cpp245
-rw-r--r--src/devices/machine/nsc810.h39
-rw-r--r--src/devices/machine/nscsi_bus.cpp311
-rw-r--r--src/devices/machine/nscsi_bus.h475
-rw-r--r--src/devices/machine/nscsi_cb.cpp35
-rw-r--r--src/devices/machine/nscsi_cb.h43
-rw-r--r--src/devices/machine/nvram.cpp53
-rw-r--r--src/devices/machine/nvram.h28
-rw-r--r--src/devices/machine/output_latch.cpp11
-rw-r--r--src/devices/machine/output_latch.h6
-rw-r--r--src/devices/machine/pc87306.cpp491
-rw-r--r--src/devices/machine/pc87306.h123
-rw-r--r--src/devices/machine/pc97338.cpp387
-rw-r--r--src/devices/machine/pc97338.h124
-rw-r--r--src/devices/machine/pc_fdc.cpp57
-rw-r--r--src/devices/machine/pc_fdc.h40
-rw-r--r--src/devices/machine/pc_lpt.cpp30
-rw-r--r--src/devices/machine/pc_lpt.h24
-rw-r--r--src/devices/machine/pccard.cpp81
-rw-r--r--src/devices/machine/pccard.h50
-rw-r--r--src/devices/machine/pcf8573.cpp356
-rw-r--r--src/devices/machine/pcf8573.h127
-rw-r--r--src/devices/machine/pcf8583.cpp437
-rw-r--r--src/devices/machine/pcf8583.h79
-rw-r--r--src/devices/machine/pcf8584.cpp20
-rw-r--r--src/devices/machine/pcf8584.h7
-rw-r--r--src/devices/machine/pcf8593.cpp66
-rw-r--r--src/devices/machine/pcf8593.h19
-rw-r--r--src/devices/machine/pci-apic.h4
-rw-r--r--src/devices/machine/pci-ide.cpp53
-rw-r--r--src/devices/machine/pci-ide.h50
-rw-r--r--src/devices/machine/pci-sata.h16
-rw-r--r--src/devices/machine/pci-smbus.cpp70
-rw-r--r--src/devices/machine/pci-smbus.h77
-rw-r--r--src/devices/machine/pci-usb.h18
-rw-r--r--src/devices/machine/pci.cpp305
-rw-r--r--src/devices/machine/pci.h225
-rw-r--r--src/devices/machine/pci9050.cpp44
-rw-r--r--src/devices/machine/pci9050.h42
-rw-r--r--src/devices/machine/pckeybrd.cpp68
-rw-r--r--src/devices/machine/pckeybrd.h21
-rw-r--r--src/devices/machine/pdc.cpp64
-rw-r--r--src/devices/machine/pdc.h62
-rw-r--r--src/devices/machine/pdp11.h37
-rw-r--r--src/devices/machine/phi.cpp291
-rw-r--r--src/devices/machine/phi.h65
-rw-r--r--src/devices/machine/pic8259.cpp177
-rw-r--r--src/devices/machine/pic8259.h46
-rw-r--r--src/devices/machine/pit8253.cpp167
-rw-r--r--src/devices/machine/pit8253.h40
-rw-r--r--src/devices/machine/pla.cpp35
-rw-r--r--src/devices/machine/pla.h5
-rw-r--r--src/devices/machine/ps2dma.cpp14
-rw-r--r--src/devices/machine/ps2dma.h16
-rw-r--r--src/devices/machine/ps2intc.cpp4
-rw-r--r--src/devices/machine/ps2intc.h8
-rw-r--r--src/devices/machine/ps2mc.h4
-rw-r--r--src/devices/machine/ps2pad.h4
-rw-r--r--src/devices/machine/ps2sif.cpp8
-rw-r--r--src/devices/machine/ps2sif.h12
-rw-r--r--src/devices/machine/ps2timer.cpp8
-rw-r--r--src/devices/machine/ps2timer.h8
-rw-r--r--src/devices/machine/pseudovia.cpp325
-rw-r--r--src/devices/machine/pseudovia.h54
-rw-r--r--src/devices/machine/psion_asic1.cpp484
-rw-r--r--src/devices/machine/psion_asic1.h100
-rw-r--r--src/devices/machine/psion_asic2.cpp448
-rw-r--r--src/devices/machine/psion_asic2.h100
-rw-r--r--src/devices/machine/psion_asic3.cpp301
-rw-r--r--src/devices/machine/psion_asic3.h79
-rw-r--r--src/devices/machine/psion_asic4.cpp170
-rw-r--r--src/devices/machine/psion_asic4.h59
-rw-r--r--src/devices/machine/psion_asic5.cpp459
-rw-r--r--src/devices/machine/psion_asic5.h119
-rw-r--r--src/devices/machine/psion_asic9.cpp1239
-rw-r--r--src/devices/machine/psion_asic9.h185
-rw-r--r--src/devices/machine/psion_condor.cpp278
-rw-r--r--src/devices/machine/psion_condor.h75
-rw-r--r--src/devices/machine/psion_ssd.cpp284
-rw-r--r--src/devices/machine/psion_ssd.h82
-rw-r--r--src/devices/machine/pxa255.cpp2438
-rw-r--r--src/devices/machine/pxa255.h549
-rw-r--r--src/devices/machine/pxa255defs.h379
-rw-r--r--src/devices/machine/r10696.cpp11
-rw-r--r--src/devices/machine/r10696.h10
-rw-r--r--src/devices/machine/r10788.cpp53
-rw-r--r--src/devices/machine/r10788.h15
-rw-r--r--src/devices/machine/r65c52.cpp988
-rw-r--r--src/devices/machine/r65c52.h249
-rw-r--r--src/devices/machine/ra17xx.cpp15
-rw-r--r--src/devices/machine/ra17xx.h9
-rw-r--r--src/devices/machine/ram.cpp27
-rw-r--r--src/devices/machine/ram.h8
-rw-r--r--src/devices/machine/rescap.h55
-rw-r--r--src/devices/machine/rf5c296.cpp20
-rw-r--r--src/devices/machine/rf5c296.h16
-rw-r--r--src/devices/machine/ripple_counter.cpp64
-rw-r--r--src/devices/machine/ripple_counter.h26
-rw-r--r--src/devices/machine/roc10937.cpp76
-rw-r--r--src/devices/machine/roc10937.h14
-rw-r--r--src/devices/machine/rp5c01.cpp78
-rw-r--r--src/devices/machine/rp5c01.h37
-rw-r--r--src/devices/machine/rp5c15.cpp68
-rw-r--r--src/devices/machine/rp5c15.h18
-rw-r--r--src/devices/machine/rp5h01.cpp18
-rw-r--r--src/devices/machine/rp5h01.h18
-rw-r--r--src/devices/machine/rstbuf.cpp14
-rw-r--r--src/devices/machine/rstbuf.h17
-rw-r--r--src/devices/machine/rtc4543.cpp22
-rw-r--r--src/devices/machine/rtc4543.h17
-rw-r--r--src/devices/machine/rtc65271.cpp213
-rw-r--r--src/devices/machine/rtc65271.h29
-rw-r--r--src/devices/machine/rtc9701.cpp54
-rw-r--r--src/devices/machine/rtc9701.h26
-rw-r--r--src/devices/machine/s2350.cpp418
-rw-r--r--src/devices/machine/s2350.h120
-rw-r--r--src/devices/machine/s2636.cpp72
-rw-r--r--src/devices/machine/s2636.h22
-rw-r--r--src/devices/machine/s3520cf.cpp287
-rw-r--r--src/devices/machine/s3520cf.h68
-rw-r--r--src/devices/machine/s3c2400.cpp76
-rw-r--r--src/devices/machine/s3c2400.h124
-rw-r--r--src/devices/machine/s3c2410.cpp86
-rw-r--r--src/devices/machine/s3c2410.h142
-rw-r--r--src/devices/machine/s3c2440.cpp90
-rw-r--r--src/devices/machine/s3c2440.h153
-rw-r--r--src/devices/machine/s3c24xx.h1
-rw-r--r--src/devices/machine/s3c24xx.hxx1157
-rw-r--r--src/devices/machine/s3c44b0.cpp192
-rw-r--r--src/devices/machine/s3c44b0.h105
-rw-r--r--src/devices/machine/s_smp.cpp314
-rw-r--r--src/devices/machine/s_smp.h87
-rw-r--r--src/devices/machine/sa1110.cpp3012
-rw-r--r--src/devices/machine/sa1110.h908
-rw-r--r--src/devices/machine/sa1111.cpp2194
-rw-r--r--src/devices/machine/sa1111.h688
-rw-r--r--src/devices/machine/saa1043.cpp53
-rw-r--r--src/devices/machine/saa1043.h82
-rw-r--r--src/devices/machine/saa5070.cpp350
-rw-r--r--src/devices/machine/saa5070.h151
-rw-r--r--src/devices/machine/saa7191.cpp214
-rw-r--r--src/devices/machine/saa7191.h172
-rw-r--r--src/devices/machine/sc16is741.cpp1264
-rw-r--r--src/devices/machine/sc16is741.h132
-rw-r--r--src/devices/machine/scc2698b.cpp80
-rw-r--r--src/devices/machine/scc2698b.h48
-rw-r--r--src/devices/machine/scc66470.cpp890
-rw-r--r--src/devices/machine/scc66470.h115
-rw-r--r--src/devices/machine/scc68070.cpp945
-rw-r--r--src/devices/machine/scc68070.h179
-rw-r--r--src/devices/machine/sci4.cpp339
-rw-r--r--src/devices/machine/sci4.h74
-rw-r--r--src/devices/machine/scn_pci.cpp1555
-rw-r--r--src/devices/machine/scn_pci.h283
-rw-r--r--src/devices/machine/scnxx562.cpp318
-rw-r--r--src/devices/machine/scnxx562.h74
-rw-r--r--src/devices/machine/scoop.cpp176
-rw-r--r--src/devices/machine/scoop.h42
-rw-r--r--src/devices/machine/sda2006.cpp20
-rw-r--r--src/devices/machine/sda2006.h16
-rw-r--r--src/devices/machine/sdlc.cpp11
-rw-r--r--src/devices/machine/sdlc.h14
-rw-r--r--src/devices/machine/sega_scu.cpp110
-rw-r--r--src/devices/machine/sega_scu.h65
-rw-r--r--src/devices/machine/segacrp2_device.cpp452
-rw-r--r--src/devices/machine/segacrp2_device.h126
-rw-r--r--src/devices/machine/segacrpt_device.cpp1068
-rw-r--r--src/devices/machine/segacrpt_device.h293
-rw-r--r--src/devices/machine/sensorboard.cpp471
-rw-r--r--src/devices/machine/sensorboard.h67
-rw-r--r--src/devices/machine/serflash.cpp473
-rw-r--r--src/devices/machine/serflash.h91
-rw-r--r--src/devices/machine/sis5513_ide.cpp363
-rw-r--r--src/devices/machine/sis5513_ide.h90
-rw-r--r--src/devices/machine/sis630_gui.cpp327
-rw-r--r--src/devices/machine/sis630_gui.h97
-rw-r--r--src/devices/machine/sis630_host.cpp440
-rw-r--r--src/devices/machine/sis630_host.h98
-rw-r--r--src/devices/machine/sis7001_usb.cpp93
-rw-r--r--src/devices/machine/sis7001_usb.h50
-rw-r--r--src/devices/machine/sis7018_audio.cpp163
-rw-r--r--src/devices/machine/sis7018_audio.h54
-rw-r--r--src/devices/machine/sis85c496.cpp381
-rw-r--r--src/devices/machine/sis85c496.h196
-rw-r--r--src/devices/machine/sis900_eth.cpp161
-rw-r--r--src/devices/machine/sis900_eth.h53
-rw-r--r--src/devices/machine/sis950_lpc.cpp790
-rw-r--r--src/devices/machine/sis950_lpc.h189
-rw-r--r--src/devices/machine/sis950_smbus.cpp108
-rw-r--r--src/devices/machine/sis950_smbus.h32
-rw-r--r--src/devices/machine/smartboard.cpp336
-rw-r--r--src/devices/machine/smartboard.h63
-rw-r--r--src/devices/machine/smartmed.cpp598
-rw-r--r--src/devices/machine/smartmed.h218
-rw-r--r--src/devices/machine/smc91c9x.cpp108
-rw-r--r--src/devices/machine/smc91c9x.h46
-rw-r--r--src/devices/machine/smioc.cpp66
-rw-r--r--src/devices/machine/smioc.h30
-rw-r--r--src/devices/machine/smpc.cpp345
-rw-r--r--src/devices/machine/smpc.h88
-rw-r--r--src/devices/machine/sonydriv.cpp586
-rw-r--r--src/devices/machine/sonydriv.h61
-rw-r--r--src/devices/machine/spchrom.cpp139
-rw-r--r--src/devices/machine/spchrom.h43
-rw-r--r--src/devices/machine/spg110.cpp197
-rw-r--r--src/devices/machine/spg110.h42
-rw-r--r--src/devices/machine/spg110_video.cpp682
-rw-r--r--src/devices/machine/spg110_video.h127
-rw-r--r--src/devices/machine/spg290_cdservo.cpp415
-rw-r--r--src/devices/machine/spg290_cdservo.h76
-rw-r--r--src/devices/machine/spg290_i2c.cpp144
-rw-r--r--src/devices/machine/spg290_i2c.h46
-rw-r--r--src/devices/machine/spg290_ppu.cpp560
-rw-r--r--src/devices/machine/spg290_ppu.h85
-rw-r--r--src/devices/machine/spg290_timer.cpp156
-rw-r--r--src/devices/machine/spg290_timer.h43
-rw-r--r--src/devices/machine/spg2xx.cpp159
-rw-r--r--src/devices/machine/spg2xx.h108
-rw-r--r--src/devices/machine/spg2xx_audio.cpp348
-rw-r--r--src/devices/machine/spg2xx_audio.h60
-rw-r--r--src/devices/machine/spg2xx_io.cpp1271
-rw-r--r--src/devices/machine/spg2xx_io.h198
-rw-r--r--src/devices/machine/spg2xx_sysdma.cpp6
-rw-r--r--src/devices/machine/spg2xx_sysdma.h8
-rw-r--r--src/devices/machine/spg2xx_video.cpp691
-rw-r--r--src/devices/machine/spg2xx_video.h101
-rw-r--r--src/devices/machine/spg_renderer.cpp862
-rw-r--r--src/devices/machine/spg_renderer.h121
-rw-r--r--src/devices/machine/spi_psram.cpp427
-rw-r--r--src/devices/machine/spi_psram.h87
-rw-r--r--src/devices/machine/spi_sdcard.cpp734
-rw-r--r--src/devices/machine/spi_sdcard.h87
-rw-r--r--src/devices/machine/spifi3.cpp1878
-rw-r--r--src/devices/machine/spifi3.h304
-rw-r--r--src/devices/machine/steppers.cpp55
-rw-r--r--src/devices/machine/steppers.h13
-rw-r--r--src/devices/machine/strata.cpp14
-rw-r--r--src/devices/machine/strata.h6
-rw-r--r--src/devices/machine/stvcd.cpp2749
-rw-r--r--src/devices/machine/stvcd.h200
-rw-r--r--src/devices/machine/sun4c_mmu.cpp667
-rw-r--r--src/devices/machine/sun4c_mmu.h123
-rw-r--r--src/devices/machine/sunplus_gcm394.cpp534
-rw-r--r--src/devices/machine/sunplus_gcm394.h252
-rw-r--r--src/devices/machine/sunplus_gcm394_video.cpp873
-rw-r--r--src/devices/machine/sunplus_gcm394_video.h218
-rw-r--r--src/devices/machine/swim1.cpp1230
-rw-r--r--src/devices/machine/swim1.h145
-rw-r--r--src/devices/machine/swim2.cpp565
-rw-r--r--src/devices/machine/swim2.h78
-rw-r--r--src/devices/machine/swim3.cpp730
-rw-r--r--src/devices/machine/swim3.h124
-rw-r--r--src/devices/machine/swtpc8212.cpp565
-rw-r--r--src/devices/machine/swtpc8212.h96
-rw-r--r--src/devices/machine/t10mmc.cpp1239
-rw-r--r--src/devices/machine/t10mmc.h45
-rw-r--r--src/devices/machine/t10sbc.cpp80
-rw-r--r--src/devices/machine/t10sbc.h5
-rw-r--r--src/devices/machine/t10spc.cpp11
-rw-r--r--src/devices/machine/t10spc.h4
-rw-r--r--src/devices/machine/tc009xlvc.cpp355
-rw-r--r--src/devices/machine/tc009xlvc.h86
-rw-r--r--src/devices/machine/tc9223.cpp75
-rw-r--r--src/devices/machine/tc9223.h30
-rw-r--r--src/devices/machine/tdc1008.cpp39
-rw-r--r--src/devices/machine/tdc1008.h44
-rw-r--r--src/devices/machine/te7750.cpp33
-rw-r--r--src/devices/machine/te7750.h21
-rw-r--r--src/devices/machine/terminal.cpp22
-rw-r--r--src/devices/machine/terminal.h28
-rw-r--r--src/devices/machine/thmfc1.cpp440
-rw-r--r--src/devices/machine/thmfc1.h106
-rw-r--r--src/devices/machine/ticket.cpp77
-rw-r--r--src/devices/machine/ticket.h40
-rw-r--r--src/devices/machine/timehelp.h8
-rw-r--r--src/devices/machine/timekpr.cpp99
-rw-r--r--src/devices/machine/timekpr.h33
-rw-r--r--src/devices/machine/timer.cpp114
-rw-r--r--src/devices/machine/timer.h97
-rw-r--r--src/devices/machine/tmc0430.cpp21
-rw-r--r--src/devices/machine/tmc0430.h12
-rw-r--r--src/devices/machine/tmc0999.cpp97
-rw-r--r--src/devices/machine/tmc0999.h57
-rw-r--r--src/devices/machine/tmc208k.cpp4
-rw-r--r--src/devices/machine/tmc208k.h10
-rw-r--r--src/devices/machine/tmp68301.cpp380
-rw-r--r--src/devices/machine/tmp68301.h100
-rw-r--r--src/devices/machine/tms1024.cpp37
-rw-r--r--src/devices/machine/tms1024.h17
-rw-r--r--src/devices/machine/tms5501.cpp78
-rw-r--r--src/devices/machine/tms5501.h35
-rw-r--r--src/devices/machine/tms6100.cpp16
-rw-r--r--src/devices/machine/tms6100.h20
-rw-r--r--src/devices/machine/tms9901.cpp130
-rw-r--r--src/devices/machine/tms9901.h26
-rw-r--r--src/devices/machine/tms9902.cpp73
-rw-r--r--src/devices/machine/tms9902.h7
-rw-r--r--src/devices/machine/tms9914.cpp265
-rw-r--r--src/devices/machine/tms9914.h35
-rw-r--r--src/devices/machine/tsb12lv01a.cpp275
-rw-r--r--src/devices/machine/tsb12lv01a.h195
-rw-r--r--src/devices/machine/tube.cpp92
-rw-r--r--src/devices/machine/tube.h7
-rw-r--r--src/devices/machine/ucb1200.cpp370
-rw-r--r--src/devices/machine/ucb1200.h147
-rw-r--r--src/devices/machine/upc82c710.cpp411
-rw-r--r--src/devices/machine/upc82c710.h109
-rw-r--r--src/devices/machine/upc82c711.cpp466
-rw-r--r--src/devices/machine/upc82c711.h127
-rw-r--r--src/devices/machine/upd1990a.cpp110
-rw-r--r--src/devices/machine/upd1990a.h36
-rw-r--r--src/devices/machine/upd4701.cpp96
-rw-r--r--src/devices/machine/upd4701.h63
-rw-r--r--src/devices/machine/upd4991a.cpp135
-rw-r--r--src/devices/machine/upd4991a.h52
-rw-r--r--src/devices/machine/upd4992.cpp21
-rw-r--r--src/devices/machine/upd4992.h21
-rw-r--r--src/devices/machine/upd7001.cpp193
-rw-r--r--src/devices/machine/upd7001.h101
-rw-r--r--src/devices/machine/upd7002.cpp64
-rw-r--r--src/devices/machine/upd7002.h18
-rw-r--r--src/devices/machine/upd7004.cpp19
-rw-r--r--src/devices/machine/upd7004.h17
-rw-r--r--src/devices/machine/upd71071.cpp37
-rw-r--r--src/devices/machine/upd71071.h20
-rw-r--r--src/devices/machine/upd7261.cpp733
-rw-r--r--src/devices/machine/upd7261.h104
-rw-r--r--src/devices/machine/upd765.cpp925
-rw-r--r--src/devices/machine/upd765.h218
-rw-r--r--src/devices/machine/v3021.cpp360
-rw-r--r--src/devices/machine/v3021.h57
-rw-r--r--src/devices/machine/vic_pl192.cpp402
-rw-r--r--src/devices/machine/vic_pl192.h126
-rw-r--r--src/devices/machine/vr0uart.cpp14
-rw-r--r--src/devices/machine/vrc4373.cpp68
-rw-r--r--src/devices/machine/vrc4373.h44
-rw-r--r--src/devices/machine/vrc5074.cpp225
-rw-r--r--src/devices/machine/vrc5074.h52
-rw-r--r--src/devices/machine/vrender0.cpp176
-rw-r--r--src/devices/machine/vrender0.h164
-rw-r--r--src/devices/machine/vt8231_isa.cpp226
-rw-r--r--src/devices/machine/vt8231_isa.h84
-rw-r--r--src/devices/machine/vt82c496.cpp147
-rw-r--r--src/devices/machine/vt82c496.h31
-rw-r--r--src/devices/machine/vt83c461.cpp4
-rw-r--r--src/devices/machine/vt83c461.h9
-rw-r--r--src/devices/machine/w83787f.cpp345
-rw-r--r--src/devices/machine/w83787f.h95
-rw-r--r--src/devices/machine/w83977tf.cpp535
-rw-r--r--src/devices/machine/w83977tf.h120
-rw-r--r--src/devices/machine/watchdog.cpp90
-rw-r--r--src/devices/machine/watchdog.h15
-rw-r--r--src/devices/machine/wd1000.cpp157
-rw-r--r--src/devices/machine/wd1000.h30
-rw-r--r--src/devices/machine/wd1010.cpp341
-rw-r--r--src/devices/machine/wd1010.h50
-rw-r--r--src/devices/machine/wd11c00_17.cpp44
-rw-r--r--src/devices/machine/wd11c00_17.h28
-rw-r--r--src/devices/machine/wd2010.cpp204
-rw-r--r--src/devices/machine/wd2010.h19
-rw-r--r--src/devices/machine/wd33c9x.cpp76
-rw-r--r--src/devices/machine/wd33c9x.h9
-rw-r--r--src/devices/machine/wd7600.cpp114
-rw-r--r--src/devices/machine/wd7600.h82
-rw-r--r--src/devices/machine/wd_fdc.cpp807
-rw-r--r--src/devices/machine/wd_fdc.h60
-rw-r--r--src/devices/machine/wozfdc.cpp17
-rw-r--r--src/devices/machine/wozfdc.h19
-rw-r--r--src/devices/machine/wtl3132.cpp52
-rw-r--r--src/devices/machine/wtl3132.h4
-rw-r--r--src/devices/machine/x2201.cpp23
-rw-r--r--src/devices/machine/x2201.h12
-rw-r--r--src/devices/machine/x2212.cpp23
-rw-r--r--src/devices/machine/x2212.h14
-rw-r--r--src/devices/machine/x76f041.cpp370
-rw-r--r--src/devices/machine/x76f041.h72
-rw-r--r--src/devices/machine/x76f100.cpp201
-rw-r--r--src/devices/machine/x76f100.h35
-rw-r--r--src/devices/machine/xc1700e.cpp4
-rw-r--r--src/devices/machine/xc1700e.h2
-rw-r--r--src/devices/machine/ym2148.cpp13
-rw-r--r--src/devices/machine/ym2148.h9
-rw-r--r--src/devices/machine/ym3802.cpp36
-rw-r--r--src/devices/machine/ym3802.h28
-rw-r--r--src/devices/machine/z8038.cpp21
-rw-r--r--src/devices/machine/z8038.h14
-rw-r--r--src/devices/machine/z80ctc.cpp63
-rw-r--r--src/devices/machine/z80ctc.h41
-rw-r--r--src/devices/machine/z80daisy.cpp2
-rw-r--r--src/devices/machine/z80daisy_generic.cpp7
-rw-r--r--src/devices/machine/z80daisy_generic.h6
-rw-r--r--src/devices/machine/z80dart.cpp1317
-rw-r--r--src/devices/machine/z80dart.h608
-rw-r--r--src/devices/machine/z80dma.cpp665
-rw-r--r--src/devices/machine/z80dma.h114
-rw-r--r--src/devices/machine/z80pio.cpp40
-rw-r--r--src/devices/machine/z80pio.h60
-rw-r--r--src/devices/machine/z80scc.cpp676
-rw-r--r--src/devices/machine/z80scc.h110
-rw-r--r--src/devices/machine/z80sio.cpp986
-rw-r--r--src/devices/machine/z80sio.h320
-rw-r--r--src/devices/machine/z80sti.cpp82
-rw-r--r--src/devices/machine/z80sti.h31
-rw-r--r--src/devices/machine/z8536.cpp156
-rw-r--r--src/devices/machine/z8536.h125
-rw-r--r--src/devices/machine/zfmicro_usb.cpp100
-rw-r--r--src/devices/machine/zfmicro_usb.h39
-rw-r--r--src/devices/sound/2203intf.cpp173
-rw-r--r--src/devices/sound/2203intf.h72
-rw-r--r--src/devices/sound/2608intf.cpp205
-rw-r--r--src/devices/sound/2608intf.h67
-rw-r--r--src/devices/sound/2610intf.cpp205
-rw-r--r--src/devices/sound/2610intf.h85
-rw-r--r--src/devices/sound/2612intf.cpp167
-rw-r--r--src/devices/sound/2612intf.h65
-rw-r--r--src/devices/sound/262intf.cpp145
-rw-r--r--src/devices/sound/262intf.h50
-rw-r--r--src/devices/sound/315-5641.cpp61
-rw-r--r--src/devices/sound/315-5641.h15
-rw-r--r--src/devices/sound/3526intf.cpp160
-rw-r--r--src/devices/sound/3526intf.h57
-rw-r--r--src/devices/sound/3812intf.cpp161
-rw-r--r--src/devices/sound/3812intf.h62
-rw-r--r--src/devices/sound/8950intf.cpp173
-rw-r--r--src/devices/sound/8950intf.h80
-rw-r--r--src/devices/sound/ad1848.cpp52
-rw-r--r--src/devices/sound/ad1848.h17
-rw-r--r--src/devices/sound/adc.cpp66
-rw-r--r--src/devices/sound/adc.h42
-rw-r--r--src/devices/sound/aica.cpp160
-rw-r--r--src/devices/sound/aica.h19
-rw-r--r--src/devices/sound/aicadsp.cpp46
-rw-r--r--src/devices/sound/aicadsp.h10
-rw-r--r--src/devices/sound/ap2010pcm.cpp224
-rw-r--r--src/devices/sound/ap2010pcm.h65
-rw-r--r--src/devices/sound/asc.cpp155
-rw-r--r--src/devices/sound/asc.h15
-rw-r--r--src/devices/sound/astrocde.cpp65
-rw-r--r--src/devices/sound/astrocde.h19
-rw-r--r--src/devices/sound/awacs.cpp352
-rw-r--r--src/devices/sound/awacs.h47
-rw-r--r--src/devices/sound/ay8910.cpp882
-rw-r--r--src/devices/sound/ay8910.h89
-rw-r--r--src/devices/sound/bbd.cpp127
-rw-r--r--src/devices/sound/bbd.h97
-rw-r--r--src/devices/sound/beep.cpp84
-rw-r--r--src/devices/sound/beep.h32
-rw-r--r--src/devices/sound/bsmt2000.cpp105
-rw-r--r--src/devices/sound/bsmt2000.h73
-rw-r--r--src/devices/sound/c140.cpp789
-rw-r--r--src/devices/sound/c140.h110
-rw-r--r--src/devices/sound/c352.cpp379
-rw-r--r--src/devices/sound/c352.h65
-rw-r--r--src/devices/sound/c6280.cpp356
-rw-r--r--src/devices/sound/c6280.h41
-rw-r--r--src/devices/sound/cdda.cpp190
-rw-r--r--src/devices/sound/cdda.h31
-rw-r--r--src/devices/sound/cdp1863.cpp28
-rw-r--r--src/devices/sound/cdp1863.h11
-rw-r--r--src/devices/sound/cdp1864.cpp227
-rw-r--r--src/devices/sound/cdp1864.h40
-rw-r--r--src/devices/sound/cdp1869.cpp163
-rw-r--r--src/devices/sound/cdp1869.h111
-rw-r--r--src/devices/sound/cem3394.cpp539
-rw-r--r--src/devices/sound/cem3394.h54
-rw-r--r--src/devices/sound/cf61909.cpp161
-rw-r--r--src/devices/sound/cf61909.h63
-rw-r--r--src/devices/sound/ct1745.cpp324
-rw-r--r--src/devices/sound/ct1745.h69
-rw-r--r--src/devices/sound/dac.cpp119
-rw-r--r--src/devices/sound/dac.h369
-rw-r--r--src/devices/sound/dac3350a.cpp332
-rw-r--r--src/devices/sound/dac3350a.h46
-rw-r--r--src/devices/sound/dac76.cpp64
-rw-r--r--src/devices/sound/dac76.h91
-rw-r--r--src/devices/sound/dave.cpp625
-rw-r--r--src/devices/sound/dave.h123
-rw-r--r--src/devices/sound/digitalk.cpp27
-rw-r--r--src/devices/sound/digitalk.h6
-rw-r--r--src/devices/sound/disc_cls.h140
-rw-r--r--src/devices/sound/disc_dev.hxx16
-rw-r--r--src/devices/sound/disc_flt.h192
-rw-r--r--src/devices/sound/disc_flt.hxx97
-rw-r--r--src/devices/sound/disc_inp.hxx44
-rw-r--r--src/devices/sound/disc_mth.h178
-rw-r--r--src/devices/sound/disc_mth.hxx4
-rw-r--r--src/devices/sound/disc_sys.hxx15
-rw-r--r--src/devices/sound/disc_wav.h184
-rw-r--r--src/devices/sound/disc_wav.hxx2
-rw-r--r--src/devices/sound/discrete.cpp432
-rw-r--r--src/devices/sound/discrete.h219
-rw-r--r--src/devices/sound/dmadac.cpp76
-rw-r--r--src/devices/sound/dmadac.h40
-rw-r--r--src/devices/sound/dspv.cpp97
-rw-r--r--src/devices/sound/dspv.h46
-rw-r--r--src/devices/sound/dspvd.cpp6
-rw-r--r--src/devices/sound/dspvd.h6
-rw-r--r--src/devices/sound/es1373.cpp165
-rw-r--r--src/devices/sound/es1373.h24
-rw-r--r--src/devices/sound/es5503.cpp216
-rw-r--r--src/devices/sound/es5503.h19
-rw-r--r--src/devices/sound/es5506.cpp2246
-rw-r--r--src/devices/sound/es5506.h263
-rw-r--r--src/devices/sound/es8712.cpp66
-rw-r--r--src/devices/sound/es8712.h19
-rw-r--r--src/devices/sound/esqpump.cpp130
-rw-r--r--src/devices/sound/esqpump.h14
-rw-r--r--src/devices/sound/flt_biquad.cpp695
-rw-r--r--src/devices/sound/flt_biquad.h113
-rw-r--r--src/devices/sound/flt_rc.cpp53
-rw-r--r--src/devices/sound/flt_rc.h47
-rw-r--r--src/devices/sound/flt_vol.cpp33
-rw-r--r--src/devices/sound/flt_vol.h11
-rw-r--r--src/devices/sound/fm.cpp3917
-rw-r--r--src/devices/sound/fm.h188
-rw-r--r--src/devices/sound/fm2612.cpp2572
-rw-r--r--src/devices/sound/fmopl.cpp2572
-rw-r--r--src/devices/sound/fmopl.h112
-rw-r--r--src/devices/sound/gaelco.cpp130
-rw-r--r--src/devices/sound/gaelco.h24
-rw-r--r--src/devices/sound/gb.cpp1102
-rw-r--r--src/devices/sound/gb.h95
-rw-r--r--src/devices/sound/gew.cpp641
-rw-r--r--src/devices/sound/gew.h160
-rw-r--r--src/devices/sound/gew7.cpp206
-rw-r--r--src/devices/sound/gew7.h30
-rw-r--r--src/devices/sound/gt155.cpp407
-rw-r--r--src/devices/sound/gt155.h103
-rw-r--r--src/devices/sound/hc55516.cpp578
-rw-r--r--src/devices/sound/hc55516.h207
-rw-r--r--src/devices/sound/huc6230.cpp69
-rw-r--r--src/devices/sound/huc6230.h20
-rw-r--r--src/devices/sound/i5000.cpp15
-rw-r--r--src/devices/sound/i5000.h11
-rw-r--r--src/devices/sound/ics2115.cpp384
-rw-r--r--src/devices/sound/ics2115.h99
-rw-r--r--src/devices/sound/imaadpcm.cpp133
-rw-r--r--src/devices/sound/imaadpcm.h45
-rw-r--r--src/devices/sound/iopspu.cpp10
-rw-r--r--src/devices/sound/iopspu.h16
-rw-r--r--src/devices/sound/iremga20.cpp27
-rw-r--r--src/devices/sound/iremga20.h15
-rw-r--r--src/devices/sound/k005289.cpp155
-rw-r--r--src/devices/sound/k005289.h55
-rw-r--r--src/devices/sound/k007232.cpp519
-rw-r--r--src/devices/sound/k007232.h58
-rw-r--r--src/devices/sound/k051649.cpp178
-rw-r--r--src/devices/sound/k051649.h45
-rw-r--r--src/devices/sound/k053260.cpp143
-rw-r--r--src/devices/sound/k053260.h63
-rw-r--r--src/devices/sound/k054539.cpp71
-rw-r--r--src/devices/sound/k054539.h38
-rw-r--r--src/devices/sound/k056800.cpp14
-rw-r--r--src/devices/sound/k056800.h12
-rw-r--r--src/devices/sound/ks0164.cpp543
-rw-r--r--src/devices/sound/ks0164.h117
-rw-r--r--src/devices/sound/l7a1045_l6028_dsp_a.cpp138
-rw-r--r--src/devices/sound/l7a1045_l6028_dsp_a.h29
-rw-r--r--src/devices/sound/lc7535.cpp14
-rw-r--r--src/devices/sound/lc7535.h20
-rw-r--r--src/devices/sound/lc78836m.cpp206
-rw-r--r--src/devices/sound/lc78836m.h66
-rw-r--r--src/devices/sound/lc82310.cpp297
-rw-r--r--src/devices/sound/lc82310.h92
-rw-r--r--src/devices/sound/lmc1992.cpp10
-rw-r--r--src/devices/sound/lmc1992.h10
-rw-r--r--src/devices/sound/lynx.cpp526
-rw-r--r--src/devices/sound/lynx.h95
-rw-r--r--src/devices/sound/mas3507d.cpp354
-rw-r--r--src/devices/sound/mas3507d.h87
-rw-r--r--src/devices/sound/mea8000.cpp17
-rw-r--r--src/devices/sound/mea8000.h46
-rw-r--r--src/devices/sound/meg.cpp180
-rw-r--r--src/devices/sound/meg.h81
-rw-r--r--src/devices/sound/megd.cpp118
-rw-r--r--src/devices/sound/mixer.cpp30
-rw-r--r--src/devices/sound/mixer.h27
-rw-r--r--src/devices/sound/mm5837.cpp81
-rw-r--r--src/devices/sound/mm5837.h185
-rw-r--r--src/devices/sound/mmc5.cpp314
-rw-r--r--src/devices/sound/mmc5.h75
-rw-r--r--src/devices/sound/mos6560.cpp180
-rw-r--r--src/devices/sound/mos6560.h28
-rw-r--r--src/devices/sound/mos6581.cpp146
-rw-r--r--src/devices/sound/mos6581.h8
-rw-r--r--src/devices/sound/mos7360.cpp309
-rw-r--r--src/devices/sound/mos7360.h38
-rw-r--r--src/devices/sound/mp3_audio.cpp90
-rw-r--r--src/devices/sound/mp3_audio.h37
-rw-r--r--src/devices/sound/mpeg_audio.cpp18
-rw-r--r--src/devices/sound/mpeg_audio.h5
-rw-r--r--src/devices/sound/msm5205.cpp123
-rw-r--r--src/devices/sound/msm5205.h37
-rw-r--r--src/devices/sound/msm5232.cpp269
-rw-r--r--src/devices/sound/msm5232.h53
-rw-r--r--src/devices/sound/multipcm.cpp643
-rw-r--r--src/devices/sound/multipcm.h130
-rw-r--r--src/devices/sound/n63701x.cpp16
-rw-r--r--src/devices/sound/n63701x.h6
-rw-r--r--src/devices/sound/namco.cpp504
-rw-r--r--src/devices/sound/namco.h70
-rw-r--r--src/devices/sound/namco_163.cpp24
-rw-r--r--src/devices/sound/namco_163.h8
-rw-r--r--src/devices/sound/nes_apu.cpp527
-rw-r--r--src/devices/sound/nes_apu.h58
-rw-r--r--src/devices/sound/nes_apu_vt.cpp28
-rw-r--r--src/devices/sound/nes_apu_vt.h26
-rw-r--r--src/devices/sound/nes_defs.h173
-rw-r--r--src/devices/sound/nile.cpp232
-rw-r--r--src/devices/sound/nile.h48
-rw-r--r--src/devices/sound/nn71003f.cpp84
-rw-r--r--src/devices/sound/nn71003f.h42
-rw-r--r--src/devices/sound/okiadpcm.cpp79
-rw-r--r--src/devices/sound/okiadpcm.h12
-rw-r--r--src/devices/sound/okim6258.cpp92
-rw-r--r--src/devices/sound/okim6258.h22
-rw-r--r--src/devices/sound/okim6295.cpp88
-rw-r--r--src/devices/sound/okim6295.h29
-rw-r--r--src/devices/sound/okim6376.cpp132
-rw-r--r--src/devices/sound/okim6376.h27
-rw-r--r--src/devices/sound/okim6588.cpp232
-rw-r--r--src/devices/sound/okim6588.h88
-rw-r--r--src/devices/sound/okim9810.cpp270
-rw-r--r--src/devices/sound/okim9810.h52
-rw-r--r--src/devices/sound/pcd3311.cpp2
-rw-r--r--src/devices/sound/pcd3311.h12
-rw-r--r--src/devices/sound/pci-ac97.h12
-rw-r--r--src/devices/sound/pokey.cpp655
-rw-r--r--src/devices/sound/pokey.h96
-rw-r--r--src/devices/sound/qs1000.cpp129
-rw-r--r--src/devices/sound/qs1000.h48
-rw-r--r--src/devices/sound/qsound.cpp38
-rw-r--r--src/devices/sound/qsound.h32
-rw-r--r--src/devices/sound/qsoundhle.cpp129
-rw-r--r--src/devices/sound/qsoundhle.h15
-rw-r--r--src/devices/sound/rf5c400.cpp216
-rw-r--r--src/devices/sound/rf5c400.h20
-rw-r--r--src/devices/sound/rf5c68.cpp127
-rw-r--r--src/devices/sound/rf5c68.h54
-rw-r--r--src/devices/sound/roland_gp.cpp78
-rw-r--r--src/devices/sound/roland_gp.h86
-rw-r--r--src/devices/sound/roland_lp.cpp381
-rw-r--r--src/devices/sound/roland_lp.h69
-rw-r--r--src/devices/sound/roland_sa.cpp404
-rw-r--r--src/devices/sound/roland_sa.h59
-rw-r--r--src/devices/sound/rp2c33_snd.cpp361
-rw-r--r--src/devices/sound/rp2c33_snd.h98
-rw-r--r--src/devices/sound/s14001a.cpp335
-rw-r--r--src/devices/sound/s14001a.h95
-rw-r--r--src/devices/sound/s_dsp.cpp995
-rw-r--r--src/devices/sound/s_dsp.h116
-rw-r--r--src/devices/sound/saa1099.cpp182
-rw-r--r--src/devices/sound/saa1099.h58
-rw-r--r--src/devices/sound/samples.cpp133
-rw-r--r--src/devices/sound/samples.h72
-rw-r--r--src/devices/sound/sb0400.h6
-rw-r--r--src/devices/sound/scsp.cpp123
-rw-r--r--src/devices/sound/scsp.h28
-rw-r--r--src/devices/sound/scspdsp.cpp74
-rw-r--r--src/devices/sound/segapcm.cpp23
-rw-r--r--src/devices/sound/segapcm.h19
-rw-r--r--src/devices/sound/setapcm.cpp427
-rw-r--r--src/devices/sound/setapcm.h103
-rw-r--r--src/devices/sound/sid.cpp200
-rw-r--r--src/devices/sound/sid.h50
-rw-r--r--src/devices/sound/sidenvel.cpp78
-rw-r--r--src/devices/sound/sidvoice.cpp205
-rw-r--r--src/devices/sound/sidvoice.h96
-rw-r--r--src/devices/sound/sn76477.cpp141
-rw-r--r--src/devices/sound/sn76477.h56
-rw-r--r--src/devices/sound/sn76496.cpp76
-rw-r--r--src/devices/sound/sn76496.h43
-rw-r--r--src/devices/sound/snkwave.cpp46
-rw-r--r--src/devices/sound/snkwave.h6
-rw-r--r--src/devices/sound/sp0250.cpp251
-rw-r--r--src/devices/sound/sp0250.h70
-rw-r--r--src/devices/sound/sp0256.cpp126
-rw-r--r--src/devices/sound/sp0256.h49
-rw-r--r--src/devices/sound/spkrdev.cpp116
-rw-r--r--src/devices/sound/spkrdev.h20
-rw-r--r--src/devices/sound/spu.cpp252
-rw-r--r--src/devices/sound/spu.h76
-rw-r--r--src/devices/sound/spu_tables.cpp838
-rw-r--r--src/devices/sound/spureverb.cpp22
-rw-r--r--src/devices/sound/spureverb.h12
-rw-r--r--src/devices/sound/ssi263hle.cpp230
-rw-r--r--src/devices/sound/ssi263hle.h76
-rw-r--r--src/devices/sound/st0016.cpp251
-rw-r--r--src/devices/sound/st0016.h49
-rw-r--r--src/devices/sound/stt_sa1.cpp187
-rw-r--r--src/devices/sound/stt_sa1.h57
-rw-r--r--src/devices/sound/swp00.cpp1834
-rw-r--r--src/devices/sound/swp00.h234
-rw-r--r--src/devices/sound/swp20.cpp203
-rw-r--r--src/devices/sound/swp20.h63
-rw-r--r--src/devices/sound/swp30.cpp1527
-rw-r--r--src/devices/sound/swp30.h229
-rw-r--r--src/devices/sound/swp30d.cpp172
-rw-r--r--src/devices/sound/swp30d.h (renamed from src/devices/sound/megd.h)20
-rw-r--r--src/devices/sound/swx00.cpp721
-rw-r--r--src/devices/sound/swx00.h126
-rw-r--r--src/devices/sound/t6721a.cpp30
-rw-r--r--src/devices/sound/t6721a.h8
-rw-r--r--src/devices/sound/t6w28.cpp25
-rw-r--r--src/devices/sound/t6w28.h4
-rw-r--r--src/devices/sound/ta7630.cpp27
-rw-r--r--src/devices/sound/ta7630.h15
-rw-r--r--src/devices/sound/tc8830f.cpp19
-rw-r--r--src/devices/sound/tc8830f.h4
-rw-r--r--src/devices/sound/tiaintf.cpp6
-rw-r--r--src/devices/sound/tiaintf.h8
-rw-r--r--src/devices/sound/tiasound.cpp336
-rw-r--r--src/devices/sound/tiasound.h2
-rw-r--r--src/devices/sound/tms3615.cpp22
-rw-r--r--src/devices/sound/tms3615.h4
-rw-r--r--src/devices/sound/tms36xx.cpp13
-rw-r--r--src/devices/sound/tms36xx.h4
-rw-r--r--src/devices/sound/tms5110.cpp178
-rw-r--r--src/devices/sound/tms5110.h36
-rw-r--r--src/devices/sound/tms5220.cpp503
-rw-r--r--src/devices/sound/tms5220.h48
-rw-r--r--src/devices/sound/tt5665.cpp427
-rw-r--r--src/devices/sound/tt5665.h116
-rw-r--r--src/devices/sound/uda1344.cpp284
-rw-r--r--src/devices/sound/uda1344.h104
-rw-r--r--src/devices/sound/upd1771.cpp557
-rw-r--r--src/devices/sound/upd1771.h78
-rw-r--r--src/devices/sound/upd65043gfu01.cpp249
-rw-r--r--src/devices/sound/upd65043gfu01.h56
-rw-r--r--src/devices/sound/upd7752.cpp9
-rw-r--r--src/devices/sound/upd7752.h15
-rw-r--r--src/devices/sound/upd7759.cpp283
-rw-r--r--src/devices/sound/upd7759.h140
-rw-r--r--src/devices/sound/upd931.cpp599
-rw-r--r--src/devices/sound/upd931.h153
-rw-r--r--src/devices/sound/upd933.cpp636
-rw-r--r--src/devices/sound/upd933.h103
-rw-r--r--src/devices/sound/upd934g.cpp90
-rw-r--r--src/devices/sound/upd934g.h28
-rw-r--r--src/devices/sound/va_eg.cpp134
-rw-r--r--src/devices/sound/va_eg.h71
-rw-r--r--src/devices/sound/va_vca.cpp76
-rw-r--r--src/devices/sound/va_vca.h58
-rw-r--r--src/devices/sound/vgm_visualizer.cpp766
-rw-r--r--src/devices/sound/vgm_visualizer.h140
-rw-r--r--src/devices/sound/vlm5030.cpp295
-rw-r--r--src/devices/sound/vlm5030.h21
-rw-r--r--src/devices/sound/volt_reg.cpp41
-rw-r--r--src/devices/sound/volt_reg.h40
-rw-r--r--src/devices/sound/votrax.cpp116
-rw-r--r--src/devices/sound/votrax.h28
-rw-r--r--src/devices/sound/vrc6.cpp13
-rw-r--r--src/devices/sound/vrc6.h6
-rw-r--r--src/devices/sound/vrender0.cpp584
-rw-r--r--src/devices/sound/vrender0.h136
-rw-r--r--src/devices/sound/wave.cpp56
-rw-r--r--src/devices/sound/wave.h11
-rw-r--r--src/devices/sound/x1_010.cpp193
-rw-r--r--src/devices/sound/x1_010.h22
-rw-r--r--src/devices/sound/xt446.cpp97
-rw-r--r--src/devices/sound/xt446.h43
-rw-r--r--src/devices/sound/ym2151.cpp1892
-rw-r--r--src/devices/sound/ym2151.h271
-rw-r--r--src/devices/sound/ym2154.cpp307
-rw-r--r--src/devices/sound/ym2154.h100
-rw-r--r--src/devices/sound/ym2413.cpp1764
-rw-r--r--src/devices/sound/ym2413.h203
-rw-r--r--src/devices/sound/ymdeltat.cpp628
-rw-r--r--src/devices/sound/ymdeltat.h88
-rw-r--r--src/devices/sound/ymf262.cpp2803
-rw-r--r--src/devices/sound/ymf262.h41
-rw-r--r--src/devices/sound/ymf271.cpp249
-rw-r--r--src/devices/sound/ymf271.h15
-rw-r--r--src/devices/sound/ymf278b.cpp1062
-rw-r--r--src/devices/sound/ymf278b.h142
-rw-r--r--src/devices/sound/ymfm_mame.h314
-rw-r--r--src/devices/sound/ymopl.cpp373
-rw-r--r--src/devices/sound/ymopl.h208
-rw-r--r--src/devices/sound/ymopm.cpp81
-rw-r--r--src/devices/sound/ymopm.h56
-rw-r--r--src/devices/sound/ymopn.cpp300
-rw-r--r--src/devices/sound/ymopn.h196
-rw-r--r--src/devices/sound/ymopq.cpp38
-rw-r--r--src/devices/sound/ymopq.h36
-rw-r--r--src/devices/sound/ymopz.cpp22
-rw-r--r--src/devices/sound/ymopz.h29
-rw-r--r--src/devices/sound/ymz280b.cpp213
-rw-r--r--src/devices/sound/ymz280b.h116
-rw-r--r--src/devices/sound/ymz770.cpp114
-rw-r--r--src/devices/sound/ymz770.h24
-rw-r--r--src/devices/sound/zsg2.cpp219
-rw-r--r--src/devices/sound/zsg2.h15
-rw-r--r--src/devices/video/315_5124.cpp543
-rw-r--r--src/devices/video/315_5124.h67
-rw-r--r--src/devices/video/315_5313.cpp189
-rw-r--r--src/devices/video/315_5313.h20
-rw-r--r--src/devices/video/am8052.cpp2
-rw-r--r--src/devices/video/am8052.h2
-rw-r--r--src/devices/video/ati_mach32.cpp (renamed from src/devices/bus/isa/mach32.cpp)108
-rw-r--r--src/devices/video/ati_mach32.h243
-rw-r--r--src/devices/video/ati_mach8.cpp337
-rw-r--r--src/devices/video/ati_mach8.h85
-rw-r--r--src/devices/video/atirage.cpp609
-rw-r--r--src/devices/video/atirage.h117
-rw-r--r--src/devices/video/avgdvg.cpp1504
-rw-r--r--src/devices/video/avgdvg.h293
-rw-r--r--src/devices/video/bt431.cpp10
-rw-r--r--src/devices/video/bt431.h20
-rw-r--r--src/devices/video/bt450.cpp99
-rw-r--r--src/devices/video/bt450.h37
-rw-r--r--src/devices/video/bt459.cpp16
-rw-r--r--src/devices/video/bt459.h24
-rw-r--r--src/devices/video/bt45x.cpp79
-rw-r--r--src/devices/video/bt45x.h67
-rw-r--r--src/devices/video/bt47x.cpp193
-rw-r--r--src/devices/video/bt47x.h60
-rw-r--r--src/devices/video/bt48x.cpp513
-rw-r--r--src/devices/video/bt48x.h115
-rw-r--r--src/devices/video/bufsprite.cpp2
-rw-r--r--src/devices/video/bufsprite.h9
-rw-r--r--src/devices/video/catseye.cpp61
-rw-r--r--src/devices/video/catseye.h14
-rw-r--r--src/devices/video/cdp1861.cpp146
-rw-r--r--src/devices/video/cdp1861.h22
-rw-r--r--src/devices/video/cdp1862.cpp26
-rw-r--r--src/devices/video/cdp1862.h8
-rw-r--r--src/devices/video/cesblit.cpp49
-rw-r--r--src/devices/video/cesblit.h12
-rw-r--r--src/devices/video/cgapal.cpp2
-rw-r--r--src/devices/video/clgd542x.cpp1511
-rw-r--r--src/devices/video/clgd542x.h135
-rw-r--r--src/devices/video/crt9007.cpp186
-rw-r--r--src/devices/video/crt9007.h42
-rw-r--r--src/devices/video/crt9021.cpp7
-rw-r--r--src/devices/video/crt9021.h43
-rw-r--r--src/devices/video/crt9028.cpp22
-rw-r--r--src/devices/video/crt9028.h13
-rw-r--r--src/devices/video/crt9212.cpp11
-rw-r--r--src/devices/video/crt9212.h20
-rw-r--r--src/devices/video/crtc_ega.cpp251
-rw-r--r--src/devices/video/crtc_ega.h45
-rw-r--r--src/devices/video/decsfb.cpp175
-rw-r--r--src/devices/video/decsfb.h38
-rw-r--r--src/devices/video/dl1416.cpp72
-rw-r--r--src/devices/video/dl1416.h38
-rw-r--r--src/devices/video/dm9368.cpp55
-rw-r--r--src/devices/video/dm9368.h17
-rw-r--r--src/devices/video/dp8350.cpp44
-rw-r--r--src/devices/video/dp8350.h21
-rw-r--r--src/devices/video/dp8510.h16
-rw-r--r--src/devices/video/ds8874.cpp86
-rw-r--r--src/devices/video/ds8874.h61
-rw-r--r--src/devices/video/ef9340_1.cpp549
-rw-r--r--src/devices/video/ef9340_1.h106
-rw-r--r--src/devices/video/ef9345.cpp136
-rw-r--r--src/devices/video/ef9345.h17
-rw-r--r--src/devices/video/ef9364.cpp79
-rw-r--r--src/devices/video/ef9364.h14
-rw-r--r--src/devices/video/ef9365.cpp887
-rw-r--r--src/devices/video/ef9365.h88
-rw-r--r--src/devices/video/ef9369.cpp11
-rw-r--r--src/devices/video/ef9369.h26
-rw-r--r--src/devices/video/epic12.cpp968
-rw-r--r--src/devices/video/epic12.h857
-rw-r--r--src/devices/video/epic12_blit0.cpp558
-rw-r--r--src/devices/video/epic12_blit1.cpp558
-rw-r--r--src/devices/video/epic12_blit2.cpp558
-rw-r--r--src/devices/video/epic12_blit3.cpp558
-rw-r--r--src/devices/video/epic12_blit4.cpp558
-rw-r--r--src/devices/video/epic12_blit5.cpp558
-rw-r--r--src/devices/video/epic12_blit6.cpp558
-rw-r--r--src/devices/video/epic12_blit7.cpp558
-rw-r--r--src/devices/video/epic12_blit8.cpp42
-rw-r--r--src/devices/video/epic12in.hxx163
-rw-r--r--src/devices/video/epic12pixel.hxx193
-rw-r--r--src/devices/video/fixfreq.cpp580
-rw-r--r--src/devices/video/fixfreq.h330
-rw-r--r--src/devices/video/gb_lcd.cpp90
-rw-r--r--src/devices/video/gb_lcd.h33
-rw-r--r--src/devices/video/gba_lcd.cpp94
-rw-r--r--src/devices/video/gba_lcd.h27
-rw-r--r--src/devices/video/gf4500.cpp44
-rw-r--r--src/devices/video/gf4500.h8
-rw-r--r--src/devices/video/gf7600gs.cpp49
-rw-r--r--src/devices/video/gf7600gs.h24
-rw-r--r--src/devices/video/hd44102.cpp162
-rw-r--r--src/devices/video/hd44102.h55
-rw-r--r--src/devices/video/hd44352.cpp34
-rw-r--r--src/devices/video/hd44352.h8
-rw-r--r--src/devices/video/hd44780.cpp330
-rw-r--r--src/devices/video/hd44780.h118
-rw-r--r--src/devices/video/hd61202.cpp132
-rw-r--r--src/devices/video/hd61202.h62
-rw-r--r--src/devices/video/hd61603.cpp103
-rw-r--r--src/devices/video/hd61603.h65
-rw-r--r--src/devices/video/hd61830.cpp33
-rw-r--r--src/devices/video/hd61830.h21
-rw-r--r--src/devices/video/hd63484.cpp167
-rw-r--r--src/devices/video/hd63484.h25
-rw-r--r--src/devices/video/hd66421.cpp28
-rw-r--r--src/devices/video/hd66421.h14
-rw-r--r--src/devices/video/hlcd0438.cpp107
-rw-r--r--src/devices/video/hlcd0438.h84
-rw-r--r--src/devices/video/hlcd0488.cpp110
-rw-r--r--src/devices/video/hlcd0488.h79
-rw-r--r--src/devices/video/hlcd0515.cpp119
-rw-r--r--src/devices/video/hlcd0515.h25
-rw-r--r--src/devices/video/hlcd0538.cpp31
-rw-r--r--src/devices/video/hlcd0538.h18
-rw-r--r--src/devices/video/hp1ll3.cpp12
-rw-r--r--src/devices/video/hp1ll3.h8
-rw-r--r--src/devices/video/huc6202.cpp254
-rw-r--r--src/devices/video/huc6202.h28
-rw-r--r--src/devices/video/huc6260.cpp161
-rw-r--r--src/devices/video/huc6260.h22
-rw-r--r--src/devices/video/huc6261.cpp22
-rw-r--r--src/devices/video/huc6261.h11
-rw-r--r--src/devices/video/huc6270.cpp449
-rw-r--r--src/devices/video/huc6270.h32
-rw-r--r--src/devices/video/huc6271.h8
-rw-r--r--src/devices/video/huc6272.cpp806
-rw-r--r--src/devices/video/huc6272.h86
-rw-r--r--src/devices/video/i8244.cpp1180
-rw-r--r--src/devices/video/i8244.h195
-rw-r--r--src/devices/video/i82730.cpp618
-rw-r--r--src/devices/video/i82730.h153
-rw-r--r--src/devices/video/i8275.cpp554
-rw-r--r--src/devices/video/i8275.h98
-rw-r--r--src/devices/video/ibm8514a.cpp1664
-rw-r--r--src/devices/video/ibm8514a.h155
-rw-r--r--src/devices/video/imagetek_i4100.cpp439
-rw-r--r--src/devices/video/imagetek_i4100.h205
-rw-r--r--src/devices/video/ims_cvc.cpp216
-rw-r--r--src/devices/video/ims_cvc.h116
-rw-r--r--src/devices/video/jangou_blitter.cpp23
-rw-r--r--src/devices/video/jangou_blitter.h28
-rw-r--r--src/devices/video/k051316.cpp327
-rw-r--r--src/devices/video/k051316.h87
-rw-r--r--src/devices/video/k053936.cpp808
-rw-r--r--src/devices/video/k053936.h60
-rw-r--r--src/devices/video/lc7580.cpp159
-rw-r--r--src/devices/video/lc7580.h84
-rw-r--r--src/devices/video/lc7985.cpp302
-rw-r--r--src/devices/video/lc7985.h62
-rw-r--r--src/devices/video/m50458.cpp90
-rw-r--r--src/devices/video/m50458.h30
-rw-r--r--src/devices/video/mb86292.cpp1166
-rw-r--r--src/devices/video/mb86292.h162
-rw-r--r--src/devices/video/mb88303.cpp19
-rw-r--r--src/devices/video/mb88303.h16
-rw-r--r--src/devices/video/mb90082.cpp50
-rw-r--r--src/devices/video/mb90082.h18
-rw-r--r--src/devices/video/mb_vcu.cpp509
-rw-r--r--src/devices/video/mb_vcu.h59
-rw-r--r--src/devices/video/mc68328lcd.cpp149
-rw-r--r--src/devices/video/mc68328lcd.h53
-rw-r--r--src/devices/video/mc6845.cpp909
-rw-r--r--src/devices/video/mc6845.h200
-rw-r--r--src/devices/video/mc6847.cpp1303
-rw-r--r--src/devices/video/mc6847.h180
-rw-r--r--src/devices/video/md4330b.cpp12
-rw-r--r--src/devices/video/md4330b.h14
-rw-r--r--src/devices/video/mga2064w.cpp26
-rw-r--r--src/devices/video/mga2064w.h21
-rw-r--r--src/devices/video/mm5445.cpp7
-rw-r--r--src/devices/video/mm5445.h8
-rw-r--r--src/devices/video/mn1252.cpp103
-rw-r--r--src/devices/video/mn1252.h42
-rw-r--r--src/devices/video/mos6566.cpp136
-rw-r--r--src/devices/video/mos6566.h24
-rw-r--r--src/devices/video/mos8563.cpp501
-rw-r--r--src/devices/video/mos8563.h109
-rw-r--r--src/devices/video/msm6222b.h4
-rw-r--r--src/devices/video/msm6255.cpp16
-rw-r--r--src/devices/video/msm6255.h16
-rw-r--r--src/devices/video/nereid.cpp4
-rw-r--r--src/devices/video/nereid.h10
-rw-r--r--src/devices/video/nt7534.cpp46
-rw-r--r--src/devices/video/nt7534.h24
-rw-r--r--src/devices/video/pc_vga.cpp6510
-rw-r--r--src/devices/video/pc_vga.h594
-rw-r--r--src/devices/video/pc_vga_alliance.cpp89
-rw-r--r--src/devices/video/pc_vga_alliance.h40
-rw-r--r--src/devices/video/pc_vga_ati.cpp335
-rw-r--r--src/devices/video/pc_vga_ati.h53
-rw-r--r--src/devices/video/pc_vga_cirrus.cpp1563
-rw-r--r--src/devices/video/pc_vga_cirrus.h148
-rw-r--r--src/devices/video/pc_vga_matrox.cpp785
-rw-r--r--src/devices/video/pc_vga_matrox.h117
-rw-r--r--src/devices/video/pc_vga_mediagx.cpp57
-rw-r--r--src/devices/video/pc_vga_mediagx.h37
-rw-r--r--src/devices/video/pc_vga_nvidia.cpp322
-rw-r--r--src/devices/video/pc_vga_nvidia.h43
-rw-r--r--src/devices/video/pc_vga_oak.cpp480
-rw-r--r--src/devices/video/pc_vga_oak.h74
-rw-r--r--src/devices/video/pc_vga_paradise.cpp830
-rw-r--r--src/devices/video/pc_vga_paradise.h186
-rw-r--r--src/devices/video/pc_vga_s3.cpp1221
-rw-r--r--src/devices/video/pc_vga_s3.h134
-rw-r--r--src/devices/video/pc_vga_sis.cpp524
-rw-r--r--src/devices/video/pc_vga_sis.h65
-rw-r--r--src/devices/video/pc_vga_trident.cpp (renamed from src/devices/bus/isa/trident.cpp)1467
-rw-r--r--src/devices/video/pc_vga_trident.h (renamed from src/devices/bus/isa/trident.h)72
-rw-r--r--src/devices/video/pc_vga_tseng.cpp690
-rw-r--r--src/devices/video/pc_vga_tseng.h124
-rw-r--r--src/devices/video/pc_xga.cpp757
-rw-r--r--src/devices/video/pc_xga.h73
-rw-r--r--src/devices/video/pcd8544.cpp13
-rw-r--r--src/devices/video/pcd8544.h12
-rw-r--r--src/devices/video/pcf2100.cpp125
-rw-r--r--src/devices/video/pcf2100.h95
-rw-r--r--src/devices/video/poly.h1206
-rw-r--r--src/devices/video/polylgcy.cpp1365
-rw-r--r--src/devices/video/polylgcy.h155
-rw-r--r--src/devices/video/ppu2c0x.cpp1472
-rw-r--r--src/devices/video/ppu2c0x.h254
-rw-r--r--src/devices/video/ppu2c0x_sh6578.cpp310
-rw-r--r--src/devices/video/ppu2c0x_sh6578.h57
-rw-r--r--src/devices/video/ppu2c0x_vt.cpp642
-rw-r--r--src/devices/video/ppu2c0x_vt.h74
-rw-r--r--src/devices/video/ps2gif.cpp8
-rw-r--r--src/devices/video/ps2gif.h8
-rw-r--r--src/devices/video/ps2gs.cpp20
-rw-r--r--src/devices/video/ps2gs.h20
-rw-r--r--src/devices/video/psx.cpp346
-rw-r--r--src/devices/video/psx.h12
-rw-r--r--src/devices/video/pwm.cpp214
-rw-r--r--src/devices/video/pwm.h58
-rw-r--r--src/devices/video/ramdac.cpp39
-rw-r--r--src/devices/video/ramdac.h26
-rw-r--r--src/devices/video/s3virge.cpp1450
-rw-r--r--src/devices/video/s3virge.h243
-rw-r--r--src/devices/video/saa5050.cpp31
-rw-r--r--src/devices/video/saa5050.h31
-rw-r--r--src/devices/video/saa5240.cpp790
-rw-r--r--src/devices/video/saa5240.h220
-rw-r--r--src/devices/video/saa7110.cpp177
-rw-r--r--src/devices/video/saa7110.h46
-rw-r--r--src/devices/video/scn2674.cpp93
-rw-r--r--src/devices/video/scn2674.h32
-rw-r--r--src/devices/video/sda5708.cpp18
-rw-r--r--src/devices/video/sda5708.h12
-rw-r--r--src/devices/video/sed1200.cpp112
-rw-r--r--src/devices/video/sed1200.h21
-rw-r--r--src/devices/video/sed1330.cpp191
-rw-r--r--src/devices/video/sed1330.h19
-rw-r--r--src/devices/video/sed1356.cpp1839
-rw-r--r--src/devices/video/sed1356.h561
-rw-r--r--src/devices/video/sed1375.cpp549
-rw-r--r--src/devices/video/sed1375.h196
-rw-r--r--src/devices/video/sed1500.cpp116
-rw-r--r--src/devices/video/sed1500.h86
-rw-r--r--src/devices/video/sed1520.cpp433
-rw-r--r--src/devices/video/sed1520.h175
-rw-r--r--src/devices/video/sn74s262.cpp130
-rw-r--r--src/devices/video/sn74s262.h78
-rw-r--r--src/devices/video/snes_ppu.cpp2326
-rw-r--r--src/devices/video/snes_ppu.h179
-rw-r--r--src/devices/video/sprite.cpp70
-rw-r--r--src/devices/video/sprite.h82
-rw-r--r--src/devices/video/stvvdp1.cpp2216
-rw-r--r--src/devices/video/stvvdp1.h2
-rw-r--r--src/devices/video/stvvdp2.cpp7185
-rw-r--r--src/devices/video/stvvdp2.h2
-rw-r--r--src/devices/video/t6963c.cpp53
-rw-r--r--src/devices/video/t6963c.h15
-rw-r--r--src/devices/video/t6a04.cpp12
-rw-r--r--src/devices/video/t6a04.h12
-rw-r--r--src/devices/video/tea1002.cpp24
-rw-r--r--src/devices/video/tea1002.h15
-rw-r--r--src/devices/video/tlc34076.cpp7
-rw-r--r--src/devices/video/tlc34076.h6
-rw-r--r--src/devices/video/tmap038.cpp261
-rw-r--r--src/devices/video/tmap038.h114
-rw-r--r--src/devices/video/tms34061.cpp35
-rw-r--r--src/devices/video/tms34061.h10
-rw-r--r--src/devices/video/tms3556.cpp170
-rw-r--r--src/devices/video/tms3556.h19
-rw-r--r--src/devices/video/tms9927.cpp100
-rw-r--r--src/devices/video/tms9927.h24
-rw-r--r--src/devices/video/tms9928a.cpp35
-rw-r--r--src/devices/video/tms9928a.h31
-rw-r--r--src/devices/video/topcat.cpp13
-rw-r--r--src/devices/video/topcat.h84
-rw-r--r--src/devices/video/upd3301.cpp661
-rw-r--r--src/devices/video/upd3301.h77
-rw-r--r--src/devices/video/upd7220.cpp1298
-rw-r--r--src/devices/video/upd7220.h197
-rw-r--r--src/devices/video/upd7227.cpp10
-rw-r--r--src/devices/video/upd7227.h16
-rw-r--r--src/devices/video/v9938.cpp256
-rw-r--r--src/devices/video/v9938.h15
-rw-r--r--src/devices/video/vector.cpp21
-rw-r--r--src/devices/video/vector.h3
-rw-r--r--src/devices/video/vic4567.cpp2046
-rw-r--r--src/devices/video/vic4567.h239
-rw-r--r--src/devices/video/virge_pci.cpp309
-rw-r--r--src/devices/video/vooddefs.h3176
-rw-r--r--src/devices/video/voodoo.cpp7792
-rw-r--r--src/devices/video/voodoo.h2524
-rw-r--r--src/devices/video/voodoo_2.cpp1723
-rw-r--r--src/devices/video/voodoo_2.h249
-rw-r--r--src/devices/video/voodoo_banshee.cpp1929
-rw-r--r--src/devices/video/voodoo_banshee.h185
-rw-r--r--src/devices/video/voodoo_pci.cpp230
-rw-r--r--src/devices/video/voodoo_pci.h123
-rw-r--r--src/devices/video/voodoo_rast.hxx614
-rw-r--r--src/devices/video/voodoo_regs.h1440
-rw-r--r--src/devices/video/voodoo_render.cpp2897
-rw-r--r--src/devices/video/voodoo_render.h616
-rw-r--r--src/devices/video/vrender0.cpp94
-rw-r--r--src/devices/video/vrender0.h32
-rw-r--r--src/devices/video/wd90c26.cpp121
-rw-r--r--src/devices/video/wd90c26.h30
-rw-r--r--src/devices/video/x1_001.cpp478
-rw-r--r--src/devices/video/x1_001.h90
-rw-r--r--src/devices/video/zeus2.cpp51
-rw-r--r--src/devices/video/zeus2.h57
-rw-r--r--src/devices/video/zr36060.cpp677
-rw-r--r--src/devices/video/zr36060.h108
-rw-r--r--src/devices/video/zr36110.cpp412
-rw-r--r--src/devices/video/zr36110.h98
6892 files changed, 3451120 insertions, 360395 deletions
diff --git a/src/devices/bus/a1bus/a1bus.cpp b/src/devices/bus/a1bus/a1bus.cpp
index 1dee51c40b2..5386f185897 100644
--- a/src/devices/bus/a1bus/a1bus.cpp
+++ b/src/devices/bus/a1bus/a1bus.cpp
@@ -16,6 +16,10 @@
DEFINE_DEVICE_TYPE(A1BUS_SLOT, a1bus_slot_device, "a1bus_slot", "Apple I Slot")
+template class device_finder<device_a1bus_card_interface, false>;
+template class device_finder<device_a1bus_card_interface, true>;
+
+
//**************************************************************************
// LIVE DEVICE
//**************************************************************************
@@ -30,7 +34,7 @@ a1bus_slot_device::a1bus_slot_device(const machine_config &mconfig, const char *
a1bus_slot_device::a1bus_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)
+ , device_single_card_slot_interface<device_a1bus_card_interface>(mconfig, *this)
, m_a1bus(*this, finder_base::DUMMY_TAG)
{
}
@@ -39,13 +43,6 @@ a1bus_slot_device::a1bus_slot_device(const machine_config &mconfig, device_type
// device_start - device-specific startup
//-------------------------------------------------
-void a1bus_slot_device::device_validity_check(validity_checker &valid) const
-{
- device_t *const card(get_card_device());
- if (card && !dynamic_cast<device_a1bus_card_interface *>(card))
- osd_printf_error("Card device %s (%s) does not implement device_a1bus_card_interface\n", card->tag(), card->name());
-}
-
void a1bus_slot_device::device_resolve_objects()
{
device_a1bus_card_interface *const a1bus_card(dynamic_cast<device_a1bus_card_interface *>(get_card_device()));
@@ -55,9 +52,6 @@ void a1bus_slot_device::device_resolve_objects()
void a1bus_slot_device::device_start()
{
- device_t *const card(get_card_device());
- if (card && !dynamic_cast<device_a1bus_card_interface *>(card))
- throw emu_fatalerror("a1bus_slot_device: card device %s (%s) does not implement device_a1bus_card_interface\n", card->tag(), card->name());
}
@@ -93,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
@@ -134,21 +121,20 @@ void a1bus_device::set_nmi_line(int state)
m_out_nmi_cb(state);
}
-void a1bus_device::install_device(offs_t start, offs_t end, read8_delegate rhandler, write8_delegate whandler)
+void a1bus_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 a1bus_device::install_bank(offs_t start, offs_t end, const char *tag, uint8_t *data)
+void a1bus_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_readwrite_bank(start, end, tag);
- machine().root_device().membank(siblingtag(tag).c_str())->set_base(data);
+ m_space->install_ram(start, end, 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
@@ -164,9 +150,9 @@ 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_slot_card_interface(mconfig, 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)
{
}
@@ -187,8 +173,6 @@ void device_a1bus_card_interface::interface_validity_check(validity_checker &val
void device_a1bus_card_interface::interface_pre_start()
{
- device_slot_card_interface::interface_pre_start();
-
if (!m_a1bus)
{
m_a1bus = m_a1bus_finder;
@@ -202,12 +186,12 @@ void device_a1bus_card_interface::interface_pre_start()
m_a1bus->add_a1bus_card(this);
}
-void device_a1bus_card_interface::install_device(offs_t start, offs_t end, read8_delegate rhandler, write8_delegate whandler)
+void device_a1bus_card_interface::install_device(offs_t start, offs_t end, read8sm_delegate rhandler, write8sm_delegate whandler)
{
m_a1bus->install_device(start, end, rhandler, whandler);
}
-void device_a1bus_card_interface::install_bank(offs_t start, offs_t end, const char *tag, uint8_t *data)
+void device_a1bus_card_interface::install_bank(offs_t start, offs_t end, uint8_t *data)
{
- m_a1bus->install_bank(start, end, tag, data);
+ m_a1bus->install_bank(start, end, data);
}
diff --git a/src/devices/bus/a1bus/a1bus.h b/src/devices/bus/a1bus/a1bus.h
index 7970f150719..2af48e5eb6f 100644
--- a/src/devices/bus/a1bus/a1bus.h
+++ b/src/devices/bus/a1bus/a1bus.h
@@ -17,8 +17,9 @@
//**************************************************************************
class a1bus_device;
+class device_a1bus_card_interface;
-class a1bus_slot_device : public device_t, public device_slot_interface
+class a1bus_slot_device : public device_t, public device_single_card_slot_interface<device_a1bus_card_interface>
{
public:
// construction/destruction
@@ -37,10 +38,9 @@ public:
protected:
a1bus_slot_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock);
- // device-level overrides
- virtual void device_validity_check(validity_checker &valid) const override;
- virtual void device_resolve_objects() override;
- virtual void device_start() override;
+ // device_t implementation
+ virtual void device_resolve_objects() override ATTR_COLD;
+ virtual void device_start() override ATTR_COLD;
// configuration
required_device<a1bus_device> m_a1bus;
@@ -50,7 +50,6 @@ protected:
DECLARE_DEVICE_TYPE(A1BUS_SLOT, a1bus_slot_device)
-class device_a1bus_card_interface;
// ======================> a1bus_device
class a1bus_device : public device_t
{
@@ -69,19 +68,18 @@ public:
void set_irq_line(int state);
void set_nmi_line(int state);
- void install_device(offs_t start, offs_t end, read8_delegate rhandler, write8_delegate whandler);
- void install_bank(offs_t start, offs_t end, const char *tag, uint8_t *data);
+ 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;
- virtual void device_start() override;
- virtual void device_reset() override;
+ // device_t implementation
+ virtual void device_start() override ATTR_COLD;
+ virtual void device_reset() override ATTR_COLD;
// internal state
required_address_space m_space;
@@ -99,15 +97,13 @@ DECLARE_DEVICE_TYPE(A1BUS, a1bus_device)
// ======================> device_a1bus_card_interface
// class representing interface-specific live a1bus card
-class device_a1bus_card_interface : public device_slot_card_interface
+class device_a1bus_card_interface : public device_interface
{
friend class a1bus_device;
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(); }
@@ -118,8 +114,8 @@ protected:
void raise_slot_nmi() { m_a1bus->set_nmi_line(ASSERT_LINE); }
void lower_slot_nmi() { m_a1bus->set_nmi_line(CLEAR_LINE); }
- void install_device(offs_t start, offs_t end, read8_delegate rhandler, write8_delegate whandler);
- void install_bank(offs_t start, offs_t end, const char *tag, uint8_t *data);
+ 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_a1bus_card_interface(const machine_config &mconfig, device_t &device);
@@ -130,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/a1bus/a1cassette.cpp b/src/devices/bus/a1bus/a1cassette.cpp
index 13140382f48..5ceb89d8b8d 100644
--- a/src/devices/bus/a1bus/a1cassette.cpp
+++ b/src/devices/bus/a1bus/a1cassette.cpp
@@ -11,25 +11,60 @@
#include "emu.h"
#include "a1cassette.h"
+#include "imagedev/cassette.h"
+
+#include "speaker.h"
+
+
+namespace {
+
/***************************************************************************
PARAMETERS
***************************************************************************/
-//**************************************************************************
-// GLOBAL VARIABLES
-//**************************************************************************
-
#define CASSETTE_ROM_REGION "casrom"
-DEFINE_DEVICE_TYPE(A1BUS_CASSETTE, a1bus_cassette_device, "a1cass", "Apple I cassette board")
-
ROM_START( cassette )
- /* 256-byte cassette interface ROM, in two 82s129 or mmi6301 256x4 proms at locations 3 and 4 on the cassette interface daughtercard (they are labeled "MMI 6301-IJ // 7623L // APPLE-A3" and "MMI 6301-IJ // 7623L // APPLE-A4") */
+ // 256-byte cassette interface ROM, in two 82s129 or mmi6301 256x4 proms at locations 3 and 4 on the cassette interface daughtercard (they are labeled "MMI 6301-IJ // 7623L // APPLE-A3" and "MMI 6301-IJ // 7623L // APPLE-A4")
ROM_REGION(0x100, CASSETTE_ROM_REGION, 0)
ROM_LOAD_NIB_HIGH( "apple-a3.3", 0x0000, 0x0100, CRC(6eae8f52) SHA1(71906932727ef70952ef6afe6b08708df15cd67d) )
ROM_LOAD_NIB_LOW( "apple-a4.4", 0x0000, 0x0100, CRC(94efa977) SHA1(851f3bd6863859a1a6909179a5e5bf744b3d807e) )
ROM_END
+//**************************************************************************
+// TYPE DEFINITIONS
+//**************************************************************************
+
+class a1bus_cassette_device:
+ public device_t,
+ public device_a1bus_card_interface
+{
+public:
+ // construction/destruction
+ a1bus_cassette_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
+
+ uint8_t cassette_r(offs_t offset);
+ void cassette_w(offs_t offset, uint8_t data);
+
+protected:
+ a1bus_cassette_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock);
+
+ virtual void device_start() override ATTR_COLD;
+ virtual void device_reset() override ATTR_COLD;
+ // optional information overrides
+ virtual void device_add_mconfig(machine_config &config) override ATTR_COLD;
+ virtual const tiny_rom_entry *device_rom_region() const override ATTR_COLD;
+
+
+ void cassette_toggle_output();
+
+ optional_device<cassette_image_device> m_cassette;
+
+private:
+ required_region_ptr<uint8_t> m_rom;
+ int m_cassette_output_flipflop;
+};
+
//-------------------------------------------------
// device_add_mconfig - add device configuration
//-------------------------------------------------
@@ -38,9 +73,11 @@ ROM_END
void a1bus_cassette_device::device_add_mconfig(machine_config &config)
{
+ SPEAKER(config, "mono").front_center();
CASSETTE(config, m_cassette);
m_cassette->set_default_state(CASSETTE_STOPPED);
m_cassette->set_interface("apple1_cass");
+ m_cassette->add_route(ALL_OUTPUTS, "mono", 0.08);
}
const tiny_rom_entry *a1bus_cassette_device::device_rom_region() const
@@ -72,8 +109,8 @@ a1bus_cassette_device::a1bus_cassette_device(const machine_config &mconfig, devi
void a1bus_cassette_device::device_start()
{
- install_device(0xc000, 0xc0ff, read8_delegate(FUNC(a1bus_cassette_device::cassette_r), this), write8_delegate(FUNC(a1bus_cassette_device::cassette_w), this));
- install_bank(0xc100, 0xc1ff, "bank_a1cas", &m_rom[0]);
+ install_device(0xc000, 0xc0ff, read8sm_delegate(*this, FUNC(a1bus_cassette_device::cassette_r)), write8sm_delegate(*this, FUNC(a1bus_cassette_device::cassette_w)));
+ install_bank(0xc100, 0xc1ff, &m_rom[0]);
save_item(NAME(m_cassette_output_flipflop));
}
@@ -145,9 +182,10 @@ void a1bus_cassette_device::cassette_toggle_output()
m_cassette->output(m_cassette_output_flipflop ? 1.0 : -1.0);
}
-READ8_MEMBER(a1bus_cassette_device::cassette_r)
+uint8_t a1bus_cassette_device::cassette_r(offs_t offset)
{
- cassette_toggle_output();
+ if (!machine().side_effects_disabled())
+ cassette_toggle_output();
if (offset <= 0x7f)
{
@@ -180,7 +218,7 @@ READ8_MEMBER(a1bus_cassette_device::cassette_r)
}
}
-WRITE8_MEMBER(a1bus_cassette_device::cassette_w)
+void a1bus_cassette_device::cassette_w(offs_t offset, uint8_t data)
{
/* Writes toggle the output flip-flop in the same way that reads
do; other than that they have no effect. Any repeated accesses
@@ -191,3 +229,12 @@ WRITE8_MEMBER(a1bus_cassette_device::cassette_w)
cassette_toggle_output();
}
+
+} // anonymous namespace
+
+
+//**************************************************************************
+// GLOBAL VARIABLES
+//**************************************************************************
+
+DEFINE_DEVICE_TYPE_PRIVATE(A1BUS_CASSETTE, device_a1bus_card_interface, a1bus_cassette_device, "a1cass", "Apple I cassette board")
diff --git a/src/devices/bus/a1bus/a1cassette.h b/src/devices/bus/a1bus/a1cassette.h
index c1911f16390..fb0ca1b679b 100644
--- a/src/devices/bus/a1bus/a1cassette.h
+++ b/src/devices/bus/a1bus/a1cassette.h
@@ -14,43 +14,8 @@
#pragma once
#include "a1bus.h"
-#include "imagedev/cassette.h"
-//**************************************************************************
-// TYPE DEFINITIONS
-//**************************************************************************
-
-class a1bus_cassette_device:
- public device_t,
- public device_a1bus_card_interface
-{
-public:
- // construction/destruction
- a1bus_cassette_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
-
- DECLARE_READ8_MEMBER(cassette_r);
- DECLARE_WRITE8_MEMBER(cassette_w);
-
-protected:
- a1bus_cassette_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;
- virtual const tiny_rom_entry *device_rom_region() const override;
-
-
- void cassette_toggle_output();
-
- optional_device<cassette_image_device> m_cassette;
-
-private:
- required_region_ptr<uint8_t> m_rom;
- int m_cassette_output_flipflop;
-};
-
-// device type definition
-DECLARE_DEVICE_TYPE(A1BUS_CASSETTE, a1bus_cassette_device)
+// device type declaration
+DECLARE_DEVICE_TYPE(A1BUS_CASSETTE, device_a1bus_card_interface)
#endif // MAME_BUS_A1BUS_A1CASSETTE_H
diff --git a/src/devices/bus/a1bus/a1cffa.cpp b/src/devices/bus/a1bus/a1cffa.cpp
index 105abba1eff..d7400710247 100644
--- a/src/devices/bus/a1bus/a1cffa.cpp
+++ b/src/devices/bus/a1bus/a1cffa.cpp
@@ -11,24 +11,55 @@
#include "emu.h"
#include "a1cffa.h"
+#include "bus/ata/ataintf.h"
+
+
+namespace {
+
/***************************************************************************
PARAMETERS
***************************************************************************/
-//**************************************************************************
-// GLOBAL VARIABLES
-//**************************************************************************
-
#define CFFA_ROM_REGION "cffa_rom"
#define CFFA_ATA_TAG "cffa_ata"
-DEFINE_DEVICE_TYPE(A1BUS_CFFA, a1bus_cffa_device, "cffa1", "CFFA Compact Flash for Apple I")
-
ROM_START( cffa )
ROM_REGION(0x2000, CFFA_ROM_REGION, 0)
ROM_LOAD ("cffaromv1.1.bin", 0x0000, 0x1fe0, CRC(bf6b55ad) SHA1(6a290be18485a06f243a3561c4e01be5aafa4bfe) )
ROM_END
+//**************************************************************************
+// TYPE DEFINITIONS
+//**************************************************************************
+
+class a1bus_cffa_device:
+ public device_t,
+ public device_a1bus_card_interface
+{
+public:
+ // construction/destruction
+ a1bus_cffa_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
+
+ uint8_t cffa_r(offs_t offset);
+ void cffa_w(offs_t offset, uint8_t data);
+
+protected:
+ a1bus_cffa_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock);
+
+ virtual void device_start() override ATTR_COLD;
+ virtual void device_reset() override ATTR_COLD;
+ // optional information overrides
+ virtual void device_add_mconfig(machine_config &config) override ATTR_COLD;
+ virtual const tiny_rom_entry *device_rom_region() const override ATTR_COLD;
+
+ required_device<ata_interface_device> m_ata;
+
+private:
+ required_region_ptr<uint8_t> m_rom;
+ uint16_t m_lastdata;
+ bool m_writeprotect;
+};
+
//-------------------------------------------------
// device_add_mconfig - add device configuration
//-------------------------------------------------
@@ -68,8 +99,8 @@ a1bus_cffa_device::a1bus_cffa_device(const machine_config &mconfig, device_type
void a1bus_cffa_device::device_start()
{
- install_device(0xafe0, 0xafff, read8_delegate(FUNC(a1bus_cffa_device::cffa_r), this), write8_delegate(FUNC(a1bus_cffa_device::cffa_w), this));
- install_bank(0x9000, 0xafdf, "bank_cffa1", &m_rom[0]);
+ install_device(0xafe0, 0xafff, read8sm_delegate(*this, FUNC(a1bus_cffa_device::cffa_r)), write8sm_delegate(*this, FUNC(a1bus_cffa_device::cffa_w)));
+ install_bank(0x9000, 0xafdf, &m_rom[0]);
save_item(NAME(m_lastdata));
save_item(NAME(m_writeprotect));
@@ -81,7 +112,7 @@ void a1bus_cffa_device::device_reset()
m_lastdata = 0;
}
-READ8_MEMBER(a1bus_cffa_device::cffa_r)
+uint8_t a1bus_cffa_device::cffa_r(offs_t offset)
{
switch (offset & 0xf)
{
@@ -97,7 +128,7 @@ READ8_MEMBER(a1bus_cffa_device::cffa_r)
break;
case 0x8:
- m_lastdata = m_ata->read_cs0((offset & 0xf) - 8, 0xff);
+ m_lastdata = m_ata->cs0_r((offset & 0xf) - 8, 0xff);
return m_lastdata & 0x00ff;
case 0x9:
@@ -107,13 +138,13 @@ READ8_MEMBER(a1bus_cffa_device::cffa_r)
case 0xd:
case 0xe:
case 0xf:
- return m_ata->read_cs0((offset & 0xf) - 8, 0xff);
+ return m_ata->cs0_r((offset & 0xf) - 8, 0xff);
}
return 0xff;
}
-WRITE8_MEMBER(a1bus_cffa_device::cffa_w)
+void a1bus_cffa_device::cffa_w(offs_t offset, uint8_t data)
{
switch (offset & 0xf)
{
@@ -132,7 +163,7 @@ WRITE8_MEMBER(a1bus_cffa_device::cffa_w)
case 0x8:
- m_ata->write_cs0((offset & 0xf) - 8, data, 0xff);
+ m_ata->cs0_w((offset & 0xf) - 8, data, 0xff);
break;
case 0x9:
@@ -142,8 +173,17 @@ WRITE8_MEMBER(a1bus_cffa_device::cffa_w)
case 0xd:
case 0xe:
case 0xf:
- m_ata->write_cs0((offset & 0xf) - 8, data, 0xff);
+ m_ata->cs0_w((offset & 0xf) - 8, data, 0xff);
break;
}
}
+
+} // anonymous namespace
+
+
+//**************************************************************************
+// GLOBAL VARIABLES
+//**************************************************************************
+
+DEFINE_DEVICE_TYPE_PRIVATE(A1BUS_CFFA, device_a1bus_card_interface, a1bus_cffa_device, "cffa1", "CFFA Compact Flash for Apple I")
diff --git a/src/devices/bus/a1bus/a1cffa.h b/src/devices/bus/a1bus/a1cffa.h
index 6c68b8c8d17..f82a300e349 100644
--- a/src/devices/bus/a1bus/a1cffa.h
+++ b/src/devices/bus/a1bus/a1cffa.h
@@ -14,41 +14,8 @@
#pragma once
#include "a1bus.h"
-#include "machine/ataintf.h"
-
-//**************************************************************************
-// TYPE DEFINITIONS
-//**************************************************************************
-
-class a1bus_cffa_device:
- public device_t,
- public device_a1bus_card_interface
-{
-public:
- // construction/destruction
- a1bus_cffa_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
-
- DECLARE_READ8_MEMBER(cffa_r);
- DECLARE_WRITE8_MEMBER(cffa_w);
-
-protected:
- a1bus_cffa_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;
- virtual const tiny_rom_entry *device_rom_region() const override;
-
- required_device<ata_interface_device> m_ata;
-
-private:
- required_region_ptr<uint8_t> m_rom;
- uint16_t m_lastdata;
- bool m_writeprotect;
-};
-
-// device type definition
-DECLARE_DEVICE_TYPE(A1BUS_CFFA, a1bus_cffa_device)
+
+// device type declaration
+DECLARE_DEVICE_TYPE(A1BUS_CFFA, device_a1bus_card_interface)
#endif // MAME_BUS_A1BUS_A1CFFA_H
diff --git a/src/devices/bus/a2bus/4play.cpp b/src/devices/bus/a2bus/4play.cpp
index eab126e5a6d..39f77ddd62c 100644
--- a/src/devices/bus/a2bus/4play.cpp
+++ b/src/devices/bus/a2bus/4play.cpp
@@ -12,15 +12,31 @@
#include "emu.h"
#include "4play.h"
-/***************************************************************************
- PARAMETERS
-***************************************************************************/
+
+namespace {
//**************************************************************************
-// GLOBAL VARIABLES
+// TYPE DEFINITIONS
//**************************************************************************
-DEFINE_DEVICE_TYPE(A2BUS_4PLAY, a2bus_4play_device, "a24play", "4play Joystick Card (rev. B)")
+class a2bus_4play_device:
+ public device_t,
+ public device_a2bus_card_interface
+{
+public:
+ // construction/destruction
+ a2bus_4play_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
+
+protected:
+ a2bus_4play_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock);
+
+ virtual void device_start() override ATTR_COLD;
+ virtual ioport_constructor device_input_ports() const override ATTR_COLD;
+
+ virtual uint8_t read_c0nx(uint8_t offset) override;
+
+ required_ioport m_p1, m_p2, m_p3, m_p4;
+};
static INPUT_PORTS_START( a24play )
PORT_START("p1")
@@ -54,14 +70,14 @@ static INPUT_PORTS_START( a24play )
PORT_BIT( 0x80, IP_ACTIVE_HIGH, IPT_BUTTON1 ) PORT_PLAYER(3)
PORT_START("p4")
- PORT_BIT( 0x01, IP_ACTIVE_HIGH, IPT_JOYSTICK_UP ) PORT_PLAYER(3)
- PORT_BIT( 0x02, IP_ACTIVE_HIGH, IPT_JOYSTICK_DOWN ) PORT_PLAYER(3)
- PORT_BIT( 0x04, IP_ACTIVE_HIGH, IPT_JOYSTICK_LEFT ) PORT_PLAYER(3)
- PORT_BIT( 0x08, IP_ACTIVE_HIGH, IPT_JOYSTICK_RIGHT ) PORT_PLAYER(3)
- PORT_BIT( 0x10, IP_ACTIVE_HIGH, IPT_BUTTON3 ) PORT_PLAYER(3)
- PORT_BIT( 0x20, IP_ACTIVE_LOW, IPT_UNKNOWN ) PORT_PLAYER(3)
- PORT_BIT( 0x40, IP_ACTIVE_HIGH, IPT_BUTTON2 ) PORT_PLAYER(3)
- PORT_BIT( 0x80, IP_ACTIVE_HIGH, IPT_BUTTON1 ) PORT_PLAYER(3)
+ PORT_BIT( 0x01, IP_ACTIVE_HIGH, IPT_JOYSTICK_UP ) PORT_PLAYER(4)
+ PORT_BIT( 0x02, IP_ACTIVE_HIGH, IPT_JOYSTICK_DOWN ) PORT_PLAYER(4)
+ PORT_BIT( 0x04, IP_ACTIVE_HIGH, IPT_JOYSTICK_LEFT ) PORT_PLAYER(4)
+ PORT_BIT( 0x08, IP_ACTIVE_HIGH, IPT_JOYSTICK_RIGHT ) PORT_PLAYER(4)
+ PORT_BIT( 0x10, IP_ACTIVE_HIGH, IPT_BUTTON3 ) PORT_PLAYER(4)
+ PORT_BIT( 0x20, IP_ACTIVE_LOW, IPT_UNKNOWN ) PORT_PLAYER(4)
+ PORT_BIT( 0x40, IP_ACTIVE_HIGH, IPT_BUTTON2 ) PORT_PLAYER(4)
+ PORT_BIT( 0x80, IP_ACTIVE_HIGH, IPT_BUTTON1 ) PORT_PLAYER(4)
INPUT_PORTS_END
//-------------------------------------------------
@@ -123,3 +139,12 @@ uint8_t a2bus_4play_device::read_c0nx(uint8_t offset)
return 0;
}
+
+} // anonymous namespace
+
+
+//**************************************************************************
+// GLOBAL VARIABLES
+//**************************************************************************
+
+DEFINE_DEVICE_TYPE_PRIVATE(A2BUS_4PLAY, device_a2bus_card_interface, a2bus_4play_device, "a24play", "4play Joystick Card (rev. B)")
diff --git a/src/devices/bus/a2bus/4play.h b/src/devices/bus/a2bus/4play.h
index 96c407d315e..69a5a2b86a1 100644
--- a/src/devices/bus/a2bus/4play.h
+++ b/src/devices/bus/a2bus/4play.h
@@ -14,32 +14,7 @@
#include "a2bus.h"
-//**************************************************************************
-// TYPE DEFINITIONS
-//**************************************************************************
-
-class a2bus_4play_device:
- public device_t,
- public device_a2bus_card_interface
-{
-public:
- // construction/destruction
- a2bus_4play_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
-
-protected:
- a2bus_4play_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock);
-
- virtual void device_start() override;
- virtual ioport_constructor device_input_ports() const override;
-
- virtual uint8_t read_c0nx(uint8_t offset) override;
-
- required_ioport m_p1, m_p2, m_p3, m_p4;
-
-private:
-};
-
// device type definition
-DECLARE_DEVICE_TYPE(A2BUS_4PLAY, a2bus_4play_device)
+DECLARE_DEVICE_TYPE(A2BUS_4PLAY, device_a2bus_card_interface)
#endif // MAME_BUS_A2BUS_4PLAY_H
diff --git a/src/devices/bus/a2bus/a2alfam2.cpp b/src/devices/bus/a2bus/a2alfam2.cpp
index e97722708da..e220d1616c2 100644
--- a/src/devices/bus/a2bus/a2alfam2.cpp
+++ b/src/devices/bus/a2bus/a2alfam2.cpp
@@ -11,19 +11,67 @@
#include "emu.h"
#include "a2alfam2.h"
+
#include "sound/sn76496.h"
+
#include "speaker.h"
-/***************************************************************************
- PARAMETERS
-***************************************************************************/
+#include <algorithm>
+
+
+namespace {
//**************************************************************************
-// GLOBAL VARIABLES
+// TYPE DEFINITIONS
//**************************************************************************
-DEFINE_DEVICE_TYPE(A2BUS_ALFAM2, a2bus_alfam2_device, "a2alfam2", "ALF MC1 / Apple Music II")
-DEFINE_DEVICE_TYPE(A2BUS_AESMS, a2bus_aesms_device, "a2aesms", "Applied Engineering Super Music Synthesizer")
+class a2bus_alfam2_device:
+ public device_t,
+ public device_a2bus_card_interface
+{
+public:
+ a2bus_alfam2_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) :
+ a2bus_alfam2_device(mconfig, A2BUS_ALFAM2, tag, owner, clock)
+ {
+ }
+
+protected:
+ // construction/destruction
+ a2bus_alfam2_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock);
+
+ 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;
+
+ // 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 bool take_c800() override { return false; }
+
+ required_device<sn76489_device> m_sn1;
+ required_device<sn76489_device> m_sn2;
+ required_device<sn76489_device> m_sn3;
+ optional_device<sn76489_device> m_sn4;
+
+private:
+ uint8_t m_latch[4];
+};
+
+class a2bus_aesms_device : public a2bus_alfam2_device
+{
+public:
+ a2bus_aesms_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) :
+ a2bus_alfam2_device(mconfig, A2BUS_AESMS, tag, owner, clock)
+ {
+ }
+
+protected:
+ virtual void device_add_mconfig(machine_config &config) override ATTR_COLD;
+};
+
+/***************************************************************************
+ PARAMETERS
+***************************************************************************/
#define SN1_TAG "sn76489_1" // left
#define SN2_TAG "sn76489_2" // center
@@ -39,16 +87,18 @@ DEFINE_DEVICE_TYPE(A2BUS_AESMS, a2bus_aesms_device, "a2aesms", "Applied Engin
// device_add_mconfig - add device configuration
//-------------------------------------------------
-void a2bus_sn76489_device::device_add_mconfig(machine_config &config)
+void a2bus_alfam2_device::device_add_mconfig(machine_config &config)
{
SPEAKER(config, "alf_l").front_left();
SPEAKER(config, "alf_r").front_right();
SN76489(config, m_sn1, 1020484);
m_sn1->add_route(ALL_OUTPUTS, "alf_l", 0.50);
+
SN76489(config, m_sn2, 1020484);
m_sn2->add_route(ALL_OUTPUTS, "alf_l", 0.50);
m_sn2->add_route(ALL_OUTPUTS, "alf_r", 0.50);
+
SN76489(config, m_sn3, 1020484);
m_sn3->add_route(ALL_OUTPUTS, "alf_r", 0.50);
}
@@ -77,98 +127,81 @@ void a2bus_aesms_device::device_add_mconfig(machine_config &config)
// LIVE DEVICE
//**************************************************************************
-a2bus_sn76489_device::a2bus_sn76489_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock) :
+a2bus_alfam2_device::a2bus_alfam2_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_sn1(*this, SN1_TAG),
m_sn2(*this, SN2_TAG),
m_sn3(*this, SN3_TAG),
- m_sn4(*this, SN4_TAG), m_latch0(0), m_latch1(0), m_latch2(0), m_latch3(0), m_has4thsn(false)
+ m_sn4(*this, SN4_TAG),
+ m_latch{ 0, 0, 0, 0 }
{
}
-a2bus_alfam2_device::a2bus_alfam2_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) :
- a2bus_sn76489_device(mconfig, A2BUS_ALFAM2, tag, owner, clock)
-{
- m_has4thsn = false;
-}
-
-a2bus_aesms_device::a2bus_aesms_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) :
- a2bus_sn76489_device(mconfig, A2BUS_AESMS, tag, owner, clock)
-{
- m_has4thsn = true;
-}
-
//-------------------------------------------------
// device_start - device-specific startup
//-------------------------------------------------
-void a2bus_sn76489_device::device_start()
+void a2bus_alfam2_device::device_start()
{
- m_latch0 = m_latch1 = m_latch2 = m_latch3 = 0;
-
- save_item(NAME(m_latch0));
- save_item(NAME(m_latch1));
- save_item(NAME(m_latch2));
- save_item(NAME(m_latch3));
+ save_item(NAME(m_latch));
}
-void a2bus_sn76489_device::device_reset()
+void a2bus_alfam2_device::device_reset()
{
- m_latch0 = m_latch1 = m_latch2 = m_latch3 = 0;
+ std::fill(std::begin(m_latch), std::end(m_latch), 0);
}
-uint8_t a2bus_sn76489_device::read_c0nx(uint8_t offset)
+uint8_t a2bus_alfam2_device::read_c0nx(uint8_t offset)
{
// SN76489 can't be read, it appears from the schematics this is what happens
switch (offset)
{
case 0:
- return m_latch0;
-
case 1:
- return m_latch1;
-
case 2:
- return m_latch2;
-
case 3:
- return m_latch3;
+ return m_latch[offset];
}
return 0xff;
}
-void a2bus_sn76489_device::write_c0nx(uint8_t offset, uint8_t data)
+void a2bus_alfam2_device::write_c0nx(uint8_t offset, uint8_t data)
{
switch (offset)
{
case 0:
m_sn1->write(data);
- m_latch0 = data;
+ m_latch[0] = data;
break;
case 1:
m_sn2->write(data);
- m_latch1 = data;
+ m_latch[1] = data;
break;
case 2:
m_sn3->write(data);
- m_latch2 = data;
+ m_latch[2] = data;
break;
case 3:
- if (m_has4thsn)
+ if (m_sn4)
{
m_sn4->write(data);
- m_latch3 = data;
+ m_latch[3] = data;
}
break;
}
}
-bool a2bus_sn76489_device::take_c800()
-{
- return false;
-}
+} // anonymous namespace
+
+
+//**************************************************************************
+// GLOBAL VARIABLES
+//**************************************************************************
+
+DEFINE_DEVICE_TYPE_PRIVATE(A2BUS_ALFAM2, device_a2bus_card_interface, a2bus_alfam2_device, "a2alfam2", "ALF MC1 / Apple Music II")
+DEFINE_DEVICE_TYPE_PRIVATE(A2BUS_AESMS, device_a2bus_card_interface, a2bus_aesms_device, "a2aesms", "Applied Engineering Super Music Synthesizer")
diff --git a/src/devices/bus/a2bus/a2alfam2.h b/src/devices/bus/a2bus/a2alfam2.h
index 48088cdffd6..ee29faf6622 100644
--- a/src/devices/bus/a2bus/a2alfam2.h
+++ b/src/devices/bus/a2bus/a2alfam2.h
@@ -14,58 +14,9 @@
#pragma once
#include "a2bus.h"
-#include "sound/sn76496.h"
-//**************************************************************************
-// TYPE DEFINITIONS
-//**************************************************************************
-
-class a2bus_sn76489_device:
- public device_t,
- public device_a2bus_card_interface
-{
-protected:
- // construction/destruction
- a2bus_sn76489_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
- virtual uint8_t read_c0nx(uint8_t offset) override;
- virtual void write_c0nx(uint8_t offset, uint8_t data) override;
- virtual bool take_c800() override;
-
- required_device<sn76489_device> m_sn1;
- required_device<sn76489_device> m_sn2;
- required_device<sn76489_device> m_sn3;
- optional_device<sn76489_device> m_sn4;
-
-private:
- uint8_t m_latch0, m_latch1, m_latch2, m_latch3;
-
-protected:
- bool m_has4thsn;
-};
-
-class a2bus_alfam2_device : public a2bus_sn76489_device
-{
-public:
- a2bus_alfam2_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
-};
-
-class a2bus_aesms_device : public a2bus_sn76489_device
-{
-public:
- a2bus_aesms_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(A2BUS_ALFAM2, a2bus_alfam2_device)
-DECLARE_DEVICE_TYPE(A2BUS_AESMS, a2bus_aesms_device)
+// device type declaration
+DECLARE_DEVICE_TYPE(A2BUS_ALFAM2, device_a2bus_card_interface)
+DECLARE_DEVICE_TYPE(A2BUS_AESMS, device_a2bus_card_interface)
#endif // MAME_BUS_A2BUS_A2ALFAM2_H
diff --git a/src/devices/bus/a2bus/a2applicard.cpp b/src/devices/bus/a2bus/a2applicard.cpp
index 2b5aea0609a..3ccfb3838d9 100644
--- a/src/devices/bus/a2bus/a2applicard.cpp
+++ b/src/devices/bus/a2bus/a2applicard.cpp
@@ -16,18 +16,68 @@
#include "cpu/z80/z80.h"
#include "machine/z80ctc.h"
+
+namespace {
+
/***************************************************************************
PARAMETERS
***************************************************************************/
+#define Z80_TAG "z80"
+#define Z80_ROM_REGION "z80_rom"
+
+ROM_START( a2applicard )
+ ROM_REGION(0x800, Z80_ROM_REGION, 0)
+ ROM_LOAD( "applicard-v9.bin", 0x000000, 0x000800, CRC(1d461000) SHA1(71d633be864b6084362e85108a4e600cbe6e44fe) )
+ROM_END
+
//**************************************************************************
-// GLOBAL VARIABLES
+// TYPE DEFINITIONS
//**************************************************************************
-DEFINE_DEVICE_TYPE(A2BUS_APPLICARD, a2bus_applicard_device, "a2aplcrd", "PCPI Applicard")
+class a2bus_applicard_device:
+ public device_t,
+ public device_a2bus_card_interface
+{
+public:
+ // construction/destruction
+ a2bus_applicard_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
-#define Z80_TAG "z80"
-#define Z80_ROM_REGION "z80_rom"
+ uint8_t z80_io_r(offs_t offset);
+ void z80_io_w(offs_t offset, uint8_t data);
+
+protected:
+ a2bus_applicard_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock);
+
+ virtual void device_start() override ATTR_COLD;
+ virtual void device_reset() override ATTR_COLD;
+ virtual const tiny_rom_entry *device_rom_region() const override ATTR_COLD;
+ virtual void device_add_mconfig(machine_config &config) override ATTR_COLD;
+
+ // 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 bool take_c800() override { return false; }
+
+private:
+ required_device<cpu_device> m_z80;
+ required_region_ptr<uint8_t> m_z80rom;
+
+ bool m_bROMAtZ80Zero;
+ bool m_z80stat, m_6502stat;
+ uint8_t m_toz80, m_to6502;
+ uint8_t m_z80ram[64*1024];
+
+ uint8_t dma_r(offs_t offset);
+ void dma_w(offs_t offset, uint8_t data);
+
+ void z80_io(address_map &map) ATTR_COLD;
+ void z80_mem(address_map &map) ATTR_COLD;
+};
+
+/***************************************************************************
+ FUNCTION PROTOTYPES
+***************************************************************************/
void a2bus_applicard_device::z80_mem(address_map &map)
{
@@ -39,15 +89,6 @@ void a2bus_applicard_device::z80_io(address_map &map)
map(0x00, 0x60).mirror(0xff00).rw(FUNC(a2bus_applicard_device::z80_io_r), FUNC(a2bus_applicard_device::z80_io_w));
}
-ROM_START( a2applicard )
- ROM_REGION(0x800, Z80_ROM_REGION, 0)
- ROM_LOAD( "applicard-v9.bin", 0x000000, 0x000800, CRC(1d461000) SHA1(71d633be864b6084362e85108a4e600cbe6e44fe) )
-ROM_END
-
-/***************************************************************************
- FUNCTION PROTOTYPES
-***************************************************************************/
-
//-------------------------------------------------
// device_add_mconfig - add device configuration
//-------------------------------------------------
@@ -75,7 +116,9 @@ const tiny_rom_entry *a2bus_applicard_device::device_rom_region() const
a2bus_applicard_device::a2bus_applicard_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_z80(*this, Z80_TAG), m_bROMAtZ80Zero(false), m_z80stat(false), m_6502stat(false), m_toz80(0), m_to6502(0), m_z80rom(nullptr)
+ m_z80(*this, Z80_TAG),
+ m_z80rom(*this, Z80_ROM_REGION),
+ m_bROMAtZ80Zero(false), m_z80stat(false), m_6502stat(false), m_toz80(0), m_to6502(0)
{
}
@@ -90,9 +133,6 @@ a2bus_applicard_device::a2bus_applicard_device(const machine_config &mconfig, co
void a2bus_applicard_device::device_start()
{
- // locate Z80 ROM
- m_z80rom = device().machine().root_device().memregion(this->subtag(Z80_ROM_REGION).c_str())->base();
-
save_item(NAME(m_bROMAtZ80Zero));
save_item(NAME(m_z80stat));
save_item(NAME(m_6502stat));
@@ -174,7 +214,7 @@ void a2bus_applicard_device::write_c0nx(uint8_t offset, uint8_t data)
}
}
-READ8_MEMBER( a2bus_applicard_device::z80_io_r )
+uint8_t a2bus_applicard_device::z80_io_r(offs_t offset)
{
uint8_t tmp = 0;
@@ -204,7 +244,7 @@ READ8_MEMBER( a2bus_applicard_device::z80_io_r )
return 0xff;
}
-WRITE8_MEMBER( a2bus_applicard_device::z80_io_w )
+void a2bus_applicard_device::z80_io_w(offs_t offset, uint8_t data)
{
switch (offset)
{
@@ -230,7 +270,7 @@ WRITE8_MEMBER( a2bus_applicard_device::z80_io_w )
// dma_r -
//-------------------------------------------------
-READ8_MEMBER( a2bus_applicard_device::dma_r )
+uint8_t a2bus_applicard_device::dma_r(offs_t offset)
{
if (offset < 0x8000)
{
@@ -256,7 +296,7 @@ READ8_MEMBER( a2bus_applicard_device::dma_r )
// dma_w -
//-------------------------------------------------
-WRITE8_MEMBER( a2bus_applicard_device::dma_w )
+void a2bus_applicard_device::dma_w(offs_t offset, uint8_t data)
{
if (offset < 0x8000)
{
@@ -272,7 +312,11 @@ WRITE8_MEMBER( a2bus_applicard_device::dma_w )
}
}
-bool a2bus_applicard_device::take_c800()
-{
- return false;
-}
+} // anonymous namespace
+
+
+//**************************************************************************
+// GLOBAL VARIABLES
+//**************************************************************************
+
+DEFINE_DEVICE_TYPE_PRIVATE(A2BUS_APPLICARD, device_a2bus_card_interface, a2bus_applicard_device, "a2aplcrd", "PCPI Applicard")
diff --git a/src/devices/bus/a2bus/a2applicard.h b/src/devices/bus/a2bus/a2applicard.h
index 90bf01ddece..51f39bb3a11 100644
--- a/src/devices/bus/a2bus/a2applicard.h
+++ b/src/devices/bus/a2bus/a2applicard.h
@@ -15,50 +15,7 @@
#include "a2bus.h"
-//**************************************************************************
-// TYPE DEFINITIONS
-//**************************************************************************
-
-class a2bus_applicard_device:
- public device_t,
- public device_a2bus_card_interface
-{
-public:
- // construction/destruction
- a2bus_applicard_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
-
- DECLARE_READ8_MEMBER( z80_io_r );
- DECLARE_WRITE8_MEMBER( z80_io_w );
-
-protected:
- a2bus_applicard_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 const tiny_rom_entry *device_rom_region() const override;
- virtual void device_add_mconfig(machine_config &config) 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 bool take_c800() override;
-
-private:
- required_device<cpu_device> m_z80;
- bool m_bROMAtZ80Zero;
- bool m_z80stat, m_6502stat;
- uint8_t m_toz80, m_to6502;
- uint8_t m_z80ram[64*1024];
- uint8_t *m_z80rom;
-
- DECLARE_READ8_MEMBER( dma_r );
- DECLARE_WRITE8_MEMBER( dma_w );
-
- void z80_io(address_map &map);
- void z80_mem(address_map &map);
-};
-
-// device type definition
-DECLARE_DEVICE_TYPE(A2BUS_APPLICARD, a2bus_applicard_device)
+// device type declaration
+DECLARE_DEVICE_TYPE(A2BUS_APPLICARD, device_a2bus_card_interface)
#endif // MAME_BUS_A2BUS_A2APPLICARD_H
diff --git a/src/devices/bus/a2bus/a2arcadebd.cpp b/src/devices/bus/a2bus/a2arcadebd.cpp
index 169971ea3e5..219c67c4905 100644
--- a/src/devices/bus/a2bus/a2arcadebd.cpp
+++ b/src/devices/bus/a2bus/a2arcadebd.cpp
@@ -15,9 +15,15 @@
#include "emu.h"
#include "a2arcadebd.h"
+
+#include "video/tms9928a.h"
+#include "sound/ay8910.h"
+
#include "speaker.h"
+namespace {
+
/***************************************************************************
PARAMETERS
***************************************************************************/
@@ -27,10 +33,34 @@
#define SCREEN_TAG "screen"
//**************************************************************************
-// GLOBAL VARIABLES
+// TYPE DEFINITIONS
//**************************************************************************
-DEFINE_DEVICE_TYPE(A2BUS_ARCADEBOARD, a2bus_arcboard_device, "a2arcbd", "Third Millenium Engineering Arcade Board")
+class a2bus_arcboard_device:
+ public device_t,
+ public device_a2bus_card_interface
+{
+public:
+ // construction/destruction
+ a2bus_arcboard_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
+
+protected:
+ a2bus_arcboard_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock);
+
+ 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;
+
+ // 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;
+
+private:
+ void tms_irq_w(int state);
+
+ required_device<tms9918a_device> m_tms;
+ required_device<ay8910_device> m_ay;
+};
//-------------------------------------------------
// device_add_mconfig - add device configuration
@@ -127,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)
{
@@ -138,3 +168,12 @@ WRITE_LINE_MEMBER( a2bus_arcboard_device::tms_irq_w )
lower_slot_irq();
}
}
+
+} // anonymous namespace
+
+
+//**************************************************************************
+// GLOBAL VARIABLES
+//**************************************************************************
+
+DEFINE_DEVICE_TYPE_PRIVATE(A2BUS_ARCADEBOARD, device_a2bus_card_interface, a2bus_arcboard_device, "a2arcbd", "Third Millenium Engineering Arcade Board")
diff --git a/src/devices/bus/a2bus/a2arcadebd.h b/src/devices/bus/a2bus/a2arcadebd.h
index 9c0af1830fd..b9ebf88727f 100644
--- a/src/devices/bus/a2bus/a2arcadebd.h
+++ b/src/devices/bus/a2bus/a2arcadebd.h
@@ -14,40 +14,8 @@
#pragma once
#include "a2bus.h"
-#include "video/tms9928a.h"
-#include "sound/ay8910.h"
-//**************************************************************************
-// TYPE DEFINITIONS
-//**************************************************************************
-
-class a2bus_arcboard_device:
- public device_t,
- public device_a2bus_card_interface
-{
-public:
- // construction/destruction
- a2bus_arcboard_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
-
-protected:
- a2bus_arcboard_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
- virtual uint8_t read_c0nx(uint8_t offset) override;
- virtual void write_c0nx(uint8_t offset, uint8_t data) override;
-
-private:
- DECLARE_WRITE_LINE_MEMBER( tms_irq_w );
-
- required_device<tms9918a_device> m_tms;
- required_device<ay8910_device> m_ay;
-};
-
-// device type definition
-DECLARE_DEVICE_TYPE(A2BUS_ARCADEBOARD, a2bus_arcboard_device)
+// device type declaration
+DECLARE_DEVICE_TYPE(A2BUS_ARCADEBOARD, device_a2bus_card_interface)
#endif // MAME_BUS_A2BUS_A2ARCADEBD_H
diff --git a/src/devices/bus/a2bus/a2bus.cpp b/src/devices/bus/a2bus/a2bus.cpp
index 7adcaf368a7..d591accf73e 100644
--- a/src/devices/bus/a2bus/a2bus.cpp
+++ b/src/devices/bus/a2bus/a2bus.cpp
@@ -80,6 +80,10 @@
DEFINE_DEVICE_TYPE(A2BUS_SLOT, a2bus_slot_device, "a2bus_slot", "Apple II Slot")
+template class device_finder<device_a2bus_card_interface, false>;
+template class device_finder<device_a2bus_card_interface, true>;
+
+
//**************************************************************************
// LIVE DEVICE
//**************************************************************************
@@ -94,7 +98,7 @@ a2bus_slot_device::a2bus_slot_device(const machine_config &mconfig, const char *
a2bus_slot_device::a2bus_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)
+ , device_single_card_slot_interface<device_a2bus_card_interface>(mconfig, *this)
, m_a2bus(*this, finder_base::DUMMY_TAG)
{
}
@@ -103,25 +107,15 @@ a2bus_slot_device::a2bus_slot_device(const machine_config &mconfig, device_type
// device_start - device-specific startup
//-------------------------------------------------
-void a2bus_slot_device::device_validity_check(validity_checker &valid) const
-{
- device_t *const card(get_card_device());
- if (card && !dynamic_cast<device_a2bus_card_interface *>(card))
- osd_printf_error("Card device %s (%s) does not implement device_a2bus_card_interface\n", card->tag(), card->name());
-}
-
void a2bus_slot_device::device_resolve_objects()
{
- device_a2bus_card_interface *const a2bus_card(dynamic_cast<device_a2bus_card_interface *>(get_card_device()));
+ device_a2bus_card_interface *const a2bus_card = get_card_device();
if (a2bus_card)
a2bus_card->set_a2bus(m_a2bus, tag());
}
void a2bus_slot_device::device_start()
{
- device_t *const card(get_card_device());
- if (card && !dynamic_cast<device_a2bus_card_interface *>(card))
- throw emu_fatalerror("a2bus_slot_device: card device %s (%s) does not implement device_a2bus_card_interface\n", card->tag(), card->name());
}
//**************************************************************************
@@ -158,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
@@ -203,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;
@@ -215,8 +212,6 @@ uint8_t a2bus_device::get_a2bus_nmi_mask()
void a2bus_device::set_irq_line(int state, int slot)
{
- m_out_irq_cb(state);
-
if (state == CLEAR_LINE)
{
m_slot_irq_mask &= ~(1<<slot);
@@ -225,6 +220,8 @@ void a2bus_device::set_irq_line(int state, int slot)
{
m_slot_irq_mask |= (1<<slot);
}
+
+ m_out_irq_cb(state);
}
void a2bus_device::set_nmi_line(int state, int slot)
@@ -263,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
@@ -280,7 +277,7 @@ WRITE_LINE_MEMBER( a2bus_device::nmi_w ) { m_out_nmi_cb(state); }
//-------------------------------------------------
device_a2bus_card_interface::device_a2bus_card_interface(const machine_config &mconfig, device_t &device)
- : device_slot_card_interface(mconfig, device)
+ : device_interface(device, "a2bus")
, m_a2bus_finder(device, finder_base::DUMMY_TAG), m_a2bus(nullptr)
, m_a2bus_slottag(nullptr), m_slot(-1), m_next(nullptr)
{
@@ -303,8 +300,6 @@ void device_a2bus_card_interface::interface_validity_check(validity_checker &val
void device_a2bus_card_interface::interface_pre_start()
{
- device_slot_card_interface::interface_pre_start();
-
if (!m_a2bus)
{
m_a2bus = m_a2bus_finder;
diff --git a/src/devices/bus/a2bus/a2bus.h b/src/devices/bus/a2bus/a2bus.h
index 502ff72e854..037b4f2b175 100644
--- a/src/devices/bus/a2bus/a2bus.h
+++ b/src/devices/bus/a2bus/a2bus.h
@@ -17,33 +17,26 @@
// /INH special addresses
-#define INH_START_INVALID 0xffff
-#define INH_END_INVALID 0x0000
+static constexpr uint16_t INH_START_INVALID = 0xffff;
+static constexpr uint16_t INH_END_INVALID = 0x0000;
// /INH types
-#define INH_NONE 0x00
-#define INH_READ 0x01
-#define INH_WRITE 0x02
-
-// 7M = XTAL(14'318'181) / 2 or XTAL(28'636'363) / 4 (for IIgs)
-static constexpr uint32_t A2BUS_7M_CLOCK = 7159090;
+static constexpr int INH_NONE = 0x00;
+static constexpr int INH_READ = 0x01;
+static constexpr int INH_WRITE = 0x02;
//**************************************************************************
// TYPE DEFINITIONS
//**************************************************************************
class a2bus_device;
+class device_a2bus_card_interface;
-class a2bus_slot_device : public device_t, public device_slot_interface
+class a2bus_slot_device : public device_t, public device_single_card_slot_interface<device_a2bus_card_interface>
{
public:
// construction/destruction
template <typename T, typename U>
- a2bus_slot_device(const machine_config &mconfig, const char *tag, device_t *owner, T &&a2bus_tag, U &&opts, const char *dflt)
- : a2bus_slot_device(mconfig, tag, owner, A2BUS_7M_CLOCK, std::forward<T>(a2bus_tag), std::forward<U>(opts), dflt)
- {
- }
- template <typename T, typename U>
a2bus_slot_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock, T &&a2bus_tag, U &&opts, const char *dflt)
: a2bus_slot_device(mconfig, tag, owner, clock)
{
@@ -53,15 +46,14 @@ public:
set_fixed(false);
m_a2bus.set_tag(std::forward<T>(a2bus_tag));
}
- a2bus_slot_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock = A2BUS_7M_CLOCK);
+ a2bus_slot_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
protected:
a2bus_slot_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock);
- // device-level overrides
- virtual void device_validity_check(validity_checker &valid) const override;
- virtual void device_resolve_objects() override;
- virtual void device_start() override;
+ // device_t implementation
+ virtual void device_resolve_objects() override ATTR_COLD;
+ virtual void device_start() override ATTR_COLD;
// configuration
required_device<a2bus_device> m_a2bus;
@@ -71,8 +63,6 @@ protected:
DECLARE_DEVICE_TYPE(A2BUS_SLOT, a2bus_slot_device)
-class device_a2bus_card_interface;
-
// ======================> a2bus_device
class a2bus_device : public device_t
{
@@ -100,17 +90,17 @@ 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;
- virtual void device_start() override;
- virtual void device_reset() override;
+ // device_t implementation
+ virtual void device_start() override ATTR_COLD;
+ virtual void device_reset() override ATTR_COLD;
// internal state
required_address_space m_maincpu_space;
@@ -133,25 +123,27 @@ DECLARE_DEVICE_TYPE(A2BUS, a2bus_device)
// ======================> device_a2bus_card_interface
// class representing interface-specific live a2bus card
-class device_a2bus_card_interface : public device_slot_card_interface
+class device_a2bus_card_interface : public device_interface
{
friend class a2bus_device;
public:
// construction/destruction
virtual ~device_a2bus_card_interface();
- virtual uint8_t read_c0nx(uint8_t offset) { m_device.logerror("a2bus: unhandled read at C0n%x\n", offset); return 0; } // C0nX - /DEVSEL
- virtual void write_c0nx(uint8_t offset, uint8_t data) { m_device.logerror("a2bus: unhandled write %02x to C0n%x\n", data, offset); }
+ virtual uint8_t read_c0nx(uint8_t offset) { device().logerror("a2bus: unhandled read at C0n%x\n", offset); return 0; } // C0nX - /DEVSEL
+ virtual void write_c0nx(uint8_t offset, uint8_t data) { device().logerror("a2bus: unhandled write %02x to C0n%x\n", data, offset); }
virtual uint8_t read_cnxx(uint8_t offset) { return 0; } // CnXX - /IOSEL
- virtual void write_cnxx(uint8_t offset, uint8_t data) { m_device.logerror("a2bus: unhandled write %02x to Cn%02x\n", data, offset); }
+ virtual void write_cnxx(uint8_t offset, uint8_t data) { device().logerror("a2bus: unhandled write %02x to Cn%02x\n", data, offset); }
virtual uint8_t read_c800(uint16_t offset) { return 0; } // C800 - /IOSTB
- virtual void write_c800(uint16_t offset, uint8_t data) {m_device.logerror("a2bus: unhandled write %02x to %04x\n", data, offset + 0xc800); }
+ virtual void write_c800(uint16_t offset, uint8_t data) {device().logerror("a2bus: unhandled write %02x to %04x\n", data, offset + 0xc800); }
virtual bool take_c800() { return true; } // override and return false if your card doesn't take over the c800 space
virtual uint8_t read_inh_rom(uint16_t offset) { return 0; }
virtual void write_inh_rom(uint16_t offset, uint8_t data) { }
virtual uint16_t inh_start() { return INH_START_INVALID; }
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 41c5a1603f6..fe0288892ee 100644
--- a/src/devices/bus/a2bus/a2cffa.cpp
+++ b/src/devices/bus/a2bus/a2cffa.cpp
@@ -2,7 +2,7 @@
// copyright-holders:R. Belmont
/*********************************************************************
- a2cffa.c
+ a2cffa.cpp
Implementation of Rich Dreher's IDE/CompactFlash card
for the Apple II.
@@ -13,22 +13,14 @@
#include "emu.h"
#include "a2cffa.h"
-#include "machine/ataintf.h"
-#include "imagedev/harddriv.h"
-#include "softlist.h"
-/***************************************************************************
- PARAMETERS
-***************************************************************************/
+#include "imagedev/harddriv.h"
+#include "bus/ata/ataintf.h"
-#define LOG_A2CFFA 1
+#include "softlist_dev.h"
-//**************************************************************************
-// GLOBAL VARIABLES
-//**************************************************************************
-DEFINE_DEVICE_TYPE(A2BUS_CFFA2, a2bus_cffa2_device, "a2cffa2", "CFFA2000 Compact Flash (65C02 firmware, www.dreher.net)")
-DEFINE_DEVICE_TYPE(A2BUS_CFFA2_6502, a2bus_cffa2_6502_device, "a2cffa02", "CFFA2000 Compact Flash (6502 firmware, www.dreher.net)")
+namespace {
#define CFFA2_ROM_REGION "cffa2_rom"
#define CFFA2_ATA_TAG "cffa2_ata"
@@ -43,6 +35,66 @@ ROM_START( cffa2_6502 )
ROM_LOAD( "cffa20ee02.bin", 0x000000, 0x001000, CRC(3ecafce5) SHA1(d600692ed9626668233a22a48236af639410cb7b) )
ROM_END
+//**************************************************************************
+// TYPE DEFINITIONS
+//**************************************************************************
+
+class a2bus_cffa2000_device:
+ public device_t,
+ public device_a2bus_card_interface
+{
+protected:
+ // construction/destruction
+ a2bus_cffa2000_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock);
+
+ 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;
+ virtual const tiny_rom_entry *device_rom_region() const override ATTR_COLD;
+
+ // 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;
+ virtual uint8_t read_c800(uint16_t offset) override;
+ virtual void write_c800(uint16_t offset, uint8_t data) override;
+
+ required_device<ata_interface_device> m_ata;
+ required_region_ptr<uint8_t> m_rom;
+
+ uint8_t m_eeprom[0x1000];
+
+private:
+ uint16_t m_lastdata, m_lastreaddata;
+ bool m_writeprotect;
+ bool m_inwritecycle;
+};
+
+class a2bus_cffa2_device : public a2bus_cffa2000_device, public device_nvram_interface
+{
+public:
+ a2bus_cffa2_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
+
+protected:
+ // device_config_nvram_interface overrides
+ virtual void nvram_default() override;
+ virtual bool nvram_read(util::read_stream &file) override;
+ virtual bool nvram_write(util::write_stream &file) override;
+};
+
+class a2bus_cffa2_6502_device : public a2bus_cffa2000_device, public device_nvram_interface
+{
+public:
+ a2bus_cffa2_6502_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
+ virtual const tiny_rom_entry *device_rom_region() const override ATTR_COLD;
+
+protected:
+ // device_config_nvram_interface overrides
+ virtual void nvram_default() override;
+ virtual bool nvram_read(util::read_stream &file) override;
+ virtual bool nvram_write(util::write_stream &file) override;
+};
+
/***************************************************************************
FUNCTION PROTOTYPES
***************************************************************************/
@@ -53,7 +105,7 @@ ROM_END
void a2bus_cffa2000_device::device_add_mconfig(machine_config &config)
{
- ATA_INTERFACE(config, m_ata).options(ata_devices, "hdd", nullptr, false);
+ ATA_INTERFACE(config, m_ata).options(ata_devices, "hdd", "hdd", false);
// not yet, the core explodes
// SOFTWARE_LIST(config, "hdd_list").set_original("apple2gs_hdd");
@@ -81,7 +133,9 @@ const tiny_rom_entry *a2bus_cffa2_6502_device::device_rom_region() const
a2bus_cffa2000_device::a2bus_cffa2000_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_ata(*this, CFFA2_ATA_TAG), m_rom(nullptr), m_lastdata(0), m_lastreaddata(0), m_writeprotect(false), m_inwritecycle(false)
+ m_ata(*this, CFFA2_ATA_TAG),
+ m_rom(*this, CFFA2_ROM_REGION),
+ m_lastdata(0), m_lastreaddata(0), m_writeprotect(false), m_inwritecycle(false)
{
}
@@ -103,8 +157,6 @@ a2bus_cffa2_6502_device::a2bus_cffa2_6502_device(const machine_config &mconfig,
void a2bus_cffa2000_device::device_start()
{
- m_rom = device().machine().root_device().memregion(this->subtag(CFFA2_ROM_REGION).c_str())->base();
-
// patch default setting so slave device is enabled and up to 13 devices on both connectors
m_rom[0x800] = 13;
m_rom[0x801] = 13;
@@ -132,7 +184,7 @@ uint8_t a2bus_cffa2000_device::read_c0nx(uint8_t offset)
switch (offset)
{
case 0:
- return m_lastreaddata>>8;
+ return m_lastreaddata >> 8;
case 3:
m_writeprotect = false;
@@ -146,7 +198,7 @@ uint8_t a2bus_cffa2000_device::read_c0nx(uint8_t offset)
// Apple /// driver uses sta $c080,x when writing, which causes spurious reads of c088
if (!m_inwritecycle)
{
- m_lastreaddata = m_ata->read_cs0(offset - 8);
+ m_lastreaddata = m_ata->cs0_r(offset - 8);
}
return m_lastreaddata & 0xff;
@@ -157,7 +209,7 @@ uint8_t a2bus_cffa2000_device::read_c0nx(uint8_t offset)
case 0xd:
case 0xe:
case 0xf:
- return m_ata->read_cs0(offset-8, 0xff);
+ return m_ata->cs0_r(offset - 8, 0xff);
}
return 0xff;
@@ -193,7 +245,7 @@ void a2bus_cffa2000_device::write_c0nx(uint8_t offset, uint8_t data)
m_lastdata &= 0xff00;
m_lastdata |= data;
// printf("%02x to 8, m_lastdata = %x\n", data, m_lastdata);
- m_ata->write_cs0(offset-8, m_lastdata);
+ m_ata->cs0_w(offset-8, m_lastdata);
break;
case 9:
@@ -203,7 +255,7 @@ void a2bus_cffa2000_device::write_c0nx(uint8_t offset, uint8_t data)
case 0xd:
case 0xe:
case 0xf:
- m_ata->write_cs0(offset-8, data, 0xff);
+ m_ata->cs0_w(offset-8, data, 0xff);
break;
}
}
@@ -243,14 +295,16 @@ void a2bus_cffa2_device::nvram_default()
memcpy(m_eeprom, m_rom, 0x1000);
}
-void a2bus_cffa2_device::nvram_read(emu_file &file)
+bool a2bus_cffa2_device::nvram_read(util::read_stream &file)
{
- file.read(m_eeprom, 0x1000);
+ auto const [err, actual] = read(file, m_eeprom, 0x1000);
+ return !err && (actual == 0x1000);
}
-void a2bus_cffa2_device::nvram_write(emu_file &file)
+bool a2bus_cffa2_device::nvram_write(util::write_stream &file)
{
- file.write(m_eeprom, 0x1000);
+ auto const [err, actual] = write(file, m_eeprom, 0x1000);
+ return !err;
}
void a2bus_cffa2_6502_device::nvram_default()
@@ -258,12 +312,24 @@ void a2bus_cffa2_6502_device::nvram_default()
memcpy(m_eeprom, m_rom, 0x1000);
}
-void a2bus_cffa2_6502_device::nvram_read(emu_file &file)
+bool a2bus_cffa2_6502_device::nvram_read(util::read_stream &file)
{
- file.read(m_eeprom, 0x1000);
+ auto const [err, actual] = read(file, m_eeprom, 0x1000);
+ return !err && (actual == 0x1000);
}
-void a2bus_cffa2_6502_device::nvram_write(emu_file &file)
+bool a2bus_cffa2_6502_device::nvram_write(util::write_stream &file)
{
- file.write(m_eeprom, 0x1000);
+ auto const [err, actual] = write(file, m_eeprom, 0x1000);
+ return !err;
}
+
+} // anonymous namespace
+
+
+//**************************************************************************
+// GLOBAL VARIABLES
+//**************************************************************************
+
+DEFINE_DEVICE_TYPE_PRIVATE(A2BUS_CFFA2, device_a2bus_card_interface, a2bus_cffa2_device, "a2cffa2", "CFFA 2.0 Compact Flash (65C02 firmware, www.dreher.net)")
+DEFINE_DEVICE_TYPE_PRIVATE(A2BUS_CFFA2_6502, device_a2bus_card_interface, a2bus_cffa2_6502_device, "a2cffa02", "CFFA 2.0 Compact Flash (6502 firmware, www.dreher.net)")
diff --git a/src/devices/bus/a2bus/a2cffa.h b/src/devices/bus/a2bus/a2cffa.h
index 09fd4cd5d0d..f1b7111197f 100644
--- a/src/devices/bus/a2bus/a2cffa.h
+++ b/src/devices/bus/a2bus/a2cffa.h
@@ -15,70 +15,9 @@
#pragma once
#include "a2bus.h"
-#include "machine/ataintf.h"
-//**************************************************************************
-// TYPE DEFINITIONS
-//**************************************************************************
-
-class a2bus_cffa2000_device:
- public device_t,
- public device_a2bus_card_interface
-{
-protected:
- // construction/destruction
- a2bus_cffa2000_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;
- virtual uint8_t read_c800(uint16_t offset) override;
- virtual void write_c800(uint16_t offset, uint8_t data) override;
-
- required_device<ata_interface_device> m_ata;
-
- uint8_t *m_rom;
- uint8_t m_eeprom[0x1000];
-
-private:
- uint16_t m_lastdata, m_lastreaddata;
- bool m_writeprotect;
- bool m_inwritecycle;
-};
-
-class a2bus_cffa2_device : public a2bus_cffa2000_device, public device_nvram_interface
-{
-public:
- a2bus_cffa2_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
-
-protected:
- // device_config_nvram_interface overrides
- virtual void nvram_default() override;
- virtual void nvram_read(emu_file &file) override;
- virtual void nvram_write(emu_file &file) override;
-};
-
-class a2bus_cffa2_6502_device : public a2bus_cffa2000_device, public device_nvram_interface
-{
-public:
- a2bus_cffa2_6502_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
- virtual const tiny_rom_entry *device_rom_region() const override;
-
-protected:
- // device_config_nvram_interface overrides
- virtual void nvram_default() override;
- virtual void nvram_read(emu_file &file) override;
- virtual void nvram_write(emu_file &file) override;
-};
-
-// device type definition
-DECLARE_DEVICE_TYPE(A2BUS_CFFA2, a2bus_cffa2_device)
-DECLARE_DEVICE_TYPE(A2BUS_CFFA2_6502, a2bus_cffa2_6502_device)
+// device type declaration
+DECLARE_DEVICE_TYPE(A2BUS_CFFA2, device_a2bus_card_interface)
+DECLARE_DEVICE_TYPE(A2BUS_CFFA2_6502, device_a2bus_card_interface)
#endif // MAME_BUS_A2BUS_A2CFFA_H
diff --git a/src/devices/bus/a2bus/a2corvus.cpp b/src/devices/bus/a2bus/a2corvus.cpp
index 3b0af093659..b2e845f3d2c 100644
--- a/src/devices/bus/a2bus/a2corvus.cpp
+++ b/src/devices/bus/a2bus/a2corvus.cpp
@@ -128,10 +128,10 @@ uint8_t a2bus_corvus_device::read_c0nx(uint8_t offset)
switch (offset)
{
case 0:
- return m_corvushd->read(machine().dummy_space(), 0);
+ return m_corvushd->read();
case 1:
- return m_corvushd->status_r(machine().dummy_space(), 0);
+ return m_corvushd->status_r();
default:
logerror("Corvus: read unhandled c0n%x (%s)\n", offset, machine().describe_context());
@@ -150,7 +150,7 @@ void a2bus_corvus_device::write_c0nx(uint8_t offset, uint8_t data)
{
if (offset == 0)
{
- m_corvushd->write(machine().dummy_space(), 0, data);
+ m_corvushd->write(data);
}
}
diff --git a/src/devices/bus/a2bus/a2corvus.h b/src/devices/bus/a2bus/a2corvus.h
index a6d1a232eee..874b7dc019e 100644
--- a/src/devices/bus/a2bus/a2corvus.h
+++ b/src/devices/bus/a2bus/a2corvus.h
@@ -9,8 +9,8 @@
*********************************************************************/
-#ifndef MAME_A2BUS_A2CORVUS_H
-#define MAME_A2BUS_A2CORVUS_H
+#ifndef MAME_BUS_A2BUS_A2CORVUS_H
+#define MAME_BUS_A2BUS_A2CORVUS_H
#pragma once
@@ -32,10 +32,10 @@ public:
protected:
a2bus_corvus_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 device_start() override ATTR_COLD;
+ virtual void device_reset() override ATTR_COLD;
+ virtual void device_add_mconfig(machine_config &config) override ATTR_COLD;
+ virtual const tiny_rom_entry *device_rom_region() const override ATTR_COLD;
// overrides of standard a2bus slot functions
virtual uint8_t read_c0nx(uint8_t offset) override;
@@ -52,4 +52,4 @@ private:
// device type definition
DECLARE_DEVICE_TYPE(A2BUS_CORVUS, a2bus_corvus_device)
-#endif // MAME_A2BUS_A2CORVUS_H
+#endif // MAME_BUS_A2BUS_A2CORVUS_H
diff --git a/src/devices/bus/a2bus/a2diskii.cpp b/src/devices/bus/a2bus/a2diskii.cpp
deleted file mode 100644
index c67eb306837..00000000000
--- a/src/devices/bus/a2bus/a2diskii.cpp
+++ /dev/null
@@ -1,174 +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_IWM_FDC, a2bus_iwmflop_device, "a2iwm_flop", "Apple IWM floppy card")
-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)
-{
- APPLEFDC(config, m_fdc, &fdc_interface);
- FLOPPY_APPLE(config, FLOPPY_0, &floppy_interface, 15, 16);
- FLOPPY_APPLE(config, FLOPPY_1, &floppy_interface, 15, 16);
-}
-
-void a2bus_iwmflop_device::device_add_mconfig(machine_config &config)
-{
- IWM(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_iwmflop_device::a2bus_iwmflop_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) :
- a2bus_floppy_device(mconfig, A2BUS_IWM_FDC, 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 879744e8950..00000000000
--- a/src/devices/bus/a2bus/a2diskii.h
+++ /dev/null
@@ -1,84 +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_iwmflop_device: public a2bus_floppy_device
-{
-public:
- a2bus_iwmflop_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 a2bus_agat7flop_device: public a2bus_floppy_device
-{
-public:
- a2bus_agat7flop_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 a2bus_agat9flop_device: public a2bus_floppy_device
-{
-public:
- a2bus_agat9flop_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(A2BUS_DISKII, a2bus_diskii_device)
-DECLARE_DEVICE_TYPE(A2BUS_IWM_FDC, a2bus_iwmflop_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 1846b447a04..1d384bbec56 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
***************************************************************************/
@@ -23,6 +25,9 @@
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"
@@ -42,13 +47,41 @@ ROM_START( diskiing13 )
ROM_LOAD( "341-0009.bin", 0x000000, 0x000100, CRC(d34eb2ff) SHA1(afd060e6f35faf3bb0146fa889fc787adf56330a) )
ROM_END
-FLOPPY_FORMATS_MEMBER( diskiing_device::floppy_formats )
- FLOPPY_A216S_FORMAT, FLOPPY_RWTS18_FORMAT, FLOPPY_EDD_FORMAT, FLOPPY_WOZ_FORMAT
-FLOPPY_FORMATS_END
+ROM_START( applesurance )
+ ROM_REGION(0x1000, DISKII_ROM_REGION, 0)
+ 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_A213S_FORMAT);
+ fr.add(FLOPPY_A216S_DOS_FORMAT);
+ fr.add(FLOPPY_A216S_PRODOS_FORMAT);
+ fr.add(FLOPPY_RWTS18_FORMAT);
+ fr.add(FLOPPY_EDD_FORMAT);
+ fr.add(FLOPPY_WOZ_FORMAT);
+ fr.add(FLOPPY_NIB_FORMAT);
+
+ fr.add(fs::PRODOS);
+}
-FLOPPY_FORMATS_MEMBER( a2bus_diskiing13_device::floppy_formats )
- FLOPPY_EDD_FORMAT, FLOPPY_WOZ_FORMAT
-FLOPPY_FORMATS_END
+void a2bus_diskiing13_device::floppy_formats(format_registration &fr)
+{
+ fr.add(FLOPPY_A213S_FORMAT);
+ fr.add(FLOPPY_EDD_FORMAT);
+ fr.add(FLOPPY_WOZ_FORMAT);
+ fr.add(FLOPPY_NIB_FORMAT);
+}
//-------------------------------------------------
// device_add_mconfig - add device configuration
@@ -58,14 +91,14 @@ void diskiing_device::device_add_mconfig(machine_config &config)
{
DISKII_FDC(config, m_wozfdc, 1021800*2);
for (auto &floppy : m_floppy)
- FLOPPY_CONNECTOR(config, floppy, a2_floppies, "525", diskiing_device::floppy_formats);
+ FLOPPY_CONNECTOR(config, floppy, a2_floppies, "525", diskiing_device::floppy_formats).enable_sound(true);
}
void a2bus_diskiing13_device::device_add_mconfig(machine_config &config)
{
DISKII_FDC(config, m_wozfdc, 1021800*2);
for (auto &floppy : m_floppy)
- FLOPPY_CONNECTOR(config, floppy, a2_floppies, "525", a2bus_diskiing13_device::floppy_formats);
+ FLOPPY_CONNECTOR(config, floppy, a2_floppies, "525", a2bus_diskiing13_device::floppy_formats).enable_sound(true);
}
//-------------------------------------------------
@@ -82,6 +115,21 @@ const tiny_rom_entry *a2bus_diskiing13_device::device_rom_region() const
return ROM_NAME( diskiing13 );
}
+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
//**************************************************************************
@@ -105,6 +153,22 @@ a2bus_diskiing13_device::a2bus_diskiing13_device(const machine_config &mconfig,
{
}
+a2bus_applesurance_device::a2bus_applesurance_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) :
+ diskiing_device(mconfig, A2BUS_APPLESURANCE, tag, owner, clock),
+ m_c800_bank(1)
+{
+}
+
+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
//-------------------------------------------------
@@ -146,3 +210,29 @@ uint8_t diskiing_device::read_cnxx(uint8_t offset)
{
return m_rom[offset];
}
+
+uint8_t a2bus_applesurance_device::read_cnxx(uint8_t offset)
+{
+ return m_rom[offset+0x800];
+}
+
+uint8_t a2bus_applesurance_device::read_c800(uint16_t offset)
+{
+ if (offset == 0x7ff)
+ {
+ m_c800_bank = 1;
+ }
+
+ if (!m_c800_bank)
+ {
+ return m_rom[offset];
+ }
+
+ return m_rom[offset+0x800];
+}
+
+void a2bus_applesurance_device::device_reset()
+{
+ m_c800_bank = 1;
+ diskiing_device::device_reset();
+}
diff --git a/src/devices/bus/a2bus/a2diskiing.h b/src/devices/bus/a2bus/a2diskiing.h
index c30d49ebf0d..6568bfe3624 100644
--- a/src/devices/bus/a2bus/a2diskiing.h
+++ b/src/devices/bus/a2bus/a2diskiing.h
@@ -14,9 +14,10 @@
#pragma once
#include "a2bus.h"
-#include "imagedev/floppy.h"
-#include "formats/flopimg.h"
+
#include "machine/wozfdc.h"
+#include "imagedev/floppy.h"
+
//**************************************************************************
// TYPE DEFINITIONS
@@ -27,15 +28,14 @@ class diskiing_device:
public device_t,
public device_a2bus_card_interface
{
-public:
+protected:
// construction/destruction
diskiing_device(const machine_config &mconfig, device_type type, 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;
+ 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;
+ virtual const tiny_rom_entry *device_rom_region() const override ATTR_COLD;
// overrides of standard a2bus slot functions
virtual uint8_t read_c0nx(uint8_t offset) override;
@@ -45,10 +45,10 @@ protected:
required_device<diskii_fdc_device> m_wozfdc;
required_device_array<floppy_connector, 2> m_floppy;
-private:
const uint8_t *m_rom;
- DECLARE_FLOPPY_FORMATS( floppy_formats );
+private:
+ static void floppy_formats(format_registration &fr);
};
class a2bus_diskiing_device: public diskiing_device
@@ -63,15 +63,63 @@ public:
a2bus_diskiing13_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_add_mconfig(machine_config &config) override ATTR_COLD;
+ virtual const tiny_rom_entry *device_rom_region() const override ATTR_COLD;
+
+private:
+ static void floppy_formats(format_registration &fr);
+};
+
+class a2bus_applesurance_device: public diskiing_device
+{
+public:
+ a2bus_applesurance_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 ATTR_COLD;
+
+ virtual void device_reset() override ATTR_COLD;
+
+ virtual uint8_t read_cnxx(uint8_t offset) override;
+ virtual uint8_t read_c800(uint16_t offset) override;
+
+ virtual void write_c800(uint16_t offset, uint8_t data) override
+ {
+ if (offset == 0x7ff)
+ {
+ m_c800_bank = data & 1;
+ }
+ }
+
+ virtual bool take_c800() override { return true; }
private:
- DECLARE_FLOPPY_FORMATS( floppy_formats );
+ 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 ATTR_COLD;
+};
+
+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 ATTR_COLD;
};
// 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/a2dx1.cpp b/src/devices/bus/a2bus/a2dx1.cpp
index 9c1a0733405..6946bef8342 100644
--- a/src/devices/bus/a2bus/a2dx1.cpp
+++ b/src/devices/bus/a2bus/a2dx1.cpp
@@ -10,18 +10,40 @@
#include "emu.h"
#include "a2dx1.h"
-#include "sound/volt_reg.h"
+
+#include "sound/dac.h"
+
#include "speaker.h"
-/***************************************************************************
- PARAMETERS
-***************************************************************************/
+
+namespace {
//**************************************************************************
-// GLOBAL VARIABLES
+// TYPE DEFINITIONS
//**************************************************************************
-DEFINE_DEVICE_TYPE(A2BUS_DX1, a2bus_dx1_device, "a2dx1", "Decillonix DX-1")
+class a2bus_dx1_device:
+ public device_t,
+ public device_a2bus_card_interface
+{
+public:
+ // construction/destruction
+ a2bus_dx1_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
+
+protected:
+ a2bus_dx1_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock);
+
+ virtual void device_start() override ATTR_COLD;
+ virtual void device_add_mconfig(machine_config &config) override ATTR_COLD;
+
+ // 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 bool take_c800() override { return false; }
+
+ required_device<dac_byte_interface> m_dac;
+ required_device<dac_byte_interface> m_dacvol;
+};
/***************************************************************************
FUNCTION PROTOTYPES
@@ -35,9 +57,10 @@ void a2bus_dx1_device::device_add_mconfig(machine_config &config)
{
SPEAKER(config, "speaker").front_center();
DAC_8BIT_R2R(config, m_dac, 0).add_route(ALL_OUTPUTS, "speaker", 0.5); // unknown DAC
- DAC_8BIT_R2R(config, m_dacvol, 0).add_route(0, "dac", 1.0, DAC_VREF_POS_INPUT).add_route(0, "dac", -1.0, DAC_VREF_NEG_INPUT); // unknown DAC
- voltage_regulator_device &vref(VOLTAGE_REGULATOR(config, "vref"));
- vref.add_route(0, "dacvol", 1.0, DAC_VREF_POS_INPUT);
+ DAC_8BIT_R2R(config, m_dacvol, 0)
+ .set_output_range(0, 1)
+ .add_route(0, "dac", 1.0, DAC_INPUT_RANGE_HI)
+ .add_route(0, "dac", -1.0, DAC_INPUT_RANGE_LO); // unknown DAC
}
//**************************************************************************
@@ -96,7 +119,11 @@ void a2bus_dx1_device::write_c0nx(uint8_t offset, uint8_t data)
}
}
-bool a2bus_dx1_device::take_c800()
-{
- return false;
-}
+} // anonymous namespace
+
+
+//**************************************************************************
+// GLOBAL VARIABLES
+//**************************************************************************
+
+DEFINE_DEVICE_TYPE_PRIVATE(A2BUS_DX1, device_a2bus_card_interface, a2bus_dx1_device, "a2dx1", "Decillonix DX-1")
diff --git a/src/devices/bus/a2bus/a2dx1.h b/src/devices/bus/a2bus/a2dx1.h
index c4ea9f561e0..74557cf78d3 100644
--- a/src/devices/bus/a2bus/a2dx1.h
+++ b/src/devices/bus/a2bus/a2dx1.h
@@ -14,36 +14,8 @@
#pragma once
#include "a2bus.h"
-#include "sound/dac.h"
-//**************************************************************************
-// TYPE DEFINITIONS
-//**************************************************************************
-
-class a2bus_dx1_device:
- public device_t,
- public device_a2bus_card_interface
-{
-public:
- // construction/destruction
- a2bus_dx1_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
-
-protected:
- a2bus_dx1_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;
-
- // 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 bool take_c800() override;
-
- required_device<dac_byte_interface> m_dac;
- required_device<dac_byte_interface> m_dacvol;
-};
-
-// device type definition
-DECLARE_DEVICE_TYPE(A2BUS_DX1, a2bus_dx1_device)
+// device type declaration
+DECLARE_DEVICE_TYPE(A2BUS_DX1, device_a2bus_card_interface)
#endif // MAME_BUS_A2BUS_A2DX1_H
diff --git a/src/devices/bus/a2bus/a2eauxslot.cpp b/src/devices/bus/a2bus/a2eauxslot.cpp
index 5fab40ba9ae..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
***************************************************************************/
@@ -32,17 +31,16 @@ a2eauxslot_slot_device::a2eauxslot_slot_device(const machine_config &mconfig, co
a2eauxslot_slot_device::a2eauxslot_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)
+ , device_single_card_slot_interface<device_a2eauxslot_card_interface>(mconfig, *this)
, m_a2eauxslot(*this, finder_base::DUMMY_TAG)
{
}
void a2eauxslot_slot_device::device_resolve_objects()
{
- device_a2eauxslot_card_interface *dev = dynamic_cast<device_a2eauxslot_card_interface *>(get_card_device());
-
+ device_a2eauxslot_card_interface *const dev = get_card_device();
if (dev)
- dev->set_a2eauxslot_device(m_a2eauxslot.target());
+ dev->set_a2eauxslot(m_a2eauxslot.target(), tag());
}
//**************************************************************************
@@ -74,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
//-------------------------------------------------
@@ -115,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
@@ -132,12 +117,34 @@ WRITE_LINE_MEMBER( a2eauxslot_device::nmi_w ) { m_out_nmi_cb(state); }
//-------------------------------------------------
device_a2eauxslot_card_interface::device_a2eauxslot_card_interface(const machine_config &mconfig, device_t &device)
- : device_slot_card_interface(mconfig, device),
- m_a2eauxslot(nullptr),
- m_slot(0), m_next(nullptr)
+ : device_interface(device, "a2eaux"),
+ m_a2eauxslot_finder(device, finder_base::DUMMY_TAG), m_a2eauxslot(nullptr),
+ m_a2eauxslot_slottag(nullptr), m_slot(0), m_next(nullptr)
{
}
+void device_a2eauxslot_card_interface::interface_validity_check(validity_checker &valid) const
+{
+ if (m_a2eauxslot_finder && m_a2eauxslot && (m_a2eauxslot != m_a2eauxslot_finder))
+ osd_printf_error("Contradictory buses configured (%s and %s)\n", m_a2eauxslot_finder->tag(), m_a2eauxslot->tag());
+}
+
+void device_a2eauxslot_card_interface::interface_pre_start()
+{
+ if (!m_a2eauxslot)
+ {
+ m_a2eauxslot = m_a2eauxslot_finder;
+ if (!m_a2eauxslot)
+ fatalerror("Can't find Apple IIe Aux Slot device %s\n", m_a2eauxslot_finder.finder_tag());
+ }
+
+ if (!m_a2eauxslot->started())
+ {
+ throw device_missing_dependencies();
+ }
+
+ m_a2eauxslot->add_a2eauxslot_card(this);
+}
//-------------------------------------------------
// ~device_a2eauxslot_card_interface - destructor
@@ -146,9 +153,3 @@ device_a2eauxslot_card_interface::device_a2eauxslot_card_interface(const machine
device_a2eauxslot_card_interface::~device_a2eauxslot_card_interface()
{
}
-
-void device_a2eauxslot_card_interface::set_a2eauxslot_device(a2eauxslot_device *a2eauxslot)
-{
- m_a2eauxslot = a2eauxslot;
- m_a2eauxslot->add_a2eauxslot_card(this);
-}
diff --git a/src/devices/bus/a2bus/a2eauxslot.h b/src/devices/bus/a2bus/a2eauxslot.h
index 4351bc6112a..9d6ccfb7036 100644
--- a/src/devices/bus/a2bus/a2eauxslot.h
+++ b/src/devices/bus/a2bus/a2eauxslot.h
@@ -21,9 +21,11 @@
//**************************************************************************
class a2eauxslot_device;
+class device_a2eauxslot_card_interface;
+
class a2eauxslot_slot_device : public device_t,
- public device_slot_interface
+ public device_single_card_slot_interface<device_a2eauxslot_card_interface>
{
public:
// construction/destruction
@@ -40,8 +42,8 @@ public:
a2eauxslot_slot_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock = 0);
- // device-level overrides
- virtual void device_resolve_objects() override;
+ // device_t implementation
+ virtual void device_resolve_objects() override ATTR_COLD;
virtual void device_start() override { }
protected:
@@ -55,8 +57,6 @@ protected:
DECLARE_DEVICE_TYPE(A2EAUXSLOT_SLOT, a2eauxslot_slot_device)
-class device_a2eauxslot_card_interface;
-
// ======================> a2eauxslot_device
class a2eauxslot_device : public device_t
{
@@ -75,15 +75,14 @@ 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;
- virtual void device_start() override;
+ // device_t implementation
+ virtual void device_start() override ATTR_COLD;
// internal state
required_address_space m_space;
@@ -101,33 +100,41 @@ DECLARE_DEVICE_TYPE(A2EAUXSLOT, a2eauxslot_device)
// ======================> device_a2eauxslot_card_interface
// class representing interface-specific live a2eauxslot card
-class device_a2eauxslot_card_interface : public device_slot_card_interface
+class device_a2eauxslot_card_interface : public device_interface
{
friend class a2eauxslot_device;
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; }
- void set_a2eauxslot_device(a2eauxslot_device *a2eauxslot);
+ // inline configuration
+ void set_a2eauxslot(a2eauxslot_device *a2eauxslot, const char *slottag) { m_a2eauxslot = a2eauxslot; m_a2eauxslot_slottag = slottag; }
+ template <typename T> void set_onboard(T &&a2eauxslot) { m_a2eauxslot_finder.set_tag(std::forward<T>(a2eauxslot)); m_a2eauxslot_slottag = device().tag(); }
void raise_slot_irq() { m_a2eauxslot->set_irq_line(ASSERT_LINE); }
void lower_slot_irq() { m_a2eauxslot->set_irq_line(CLEAR_LINE); }
void raise_slot_nmi() { m_a2eauxslot->set_nmi_line(ASSERT_LINE); }
void lower_slot_nmi() { m_a2eauxslot->set_nmi_line(CLEAR_LINE); }
+ virtual void interface_validity_check(validity_checker &valid) const override;
+ virtual void interface_pre_start() override;
+
protected:
device_a2eauxslot_card_interface(const machine_config &mconfig, device_t &device);
+ optional_device<a2eauxslot_device> m_a2eauxslot_finder;
a2eauxslot_device *m_a2eauxslot;
+ const char *m_a2eauxslot_slottag;
int m_slot;
device_a2eauxslot_card_interface *m_next;
};
diff --git a/src/devices/bus/a2bus/a2echoii.cpp b/src/devices/bus/a2bus/a2echoii.cpp
index 4bc6c9ccfb2..6d73924d105 100644
--- a/src/devices/bus/a2bus/a2echoii.cpp
+++ b/src/devices/bus/a2bus/a2echoii.cpp
@@ -27,25 +27,55 @@
#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"
+namespace {
+
/***************************************************************************
PARAMETERS
***************************************************************************/
+#define TMS_TAG "tms5220"
+
//**************************************************************************
-// GLOBAL VARIABLES
+// TYPE DEFINITIONS
//**************************************************************************
-DEFINE_DEVICE_TYPE(A2BUS_ECHOII, a2bus_echoii_device, "a2echoii", "Street Electronics Echo II")
+class a2bus_echoii_device:
+ public device_t,
+ public device_a2bus_card_interface
+{
+public:
+ // construction/destruction
+ a2bus_echoii_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
-#define TMS_TAG "tms5220"
+ required_device<tms5220_device> m_tms;
+
+protected:
+ a2bus_echoii_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock);
+
+ 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;
+
+ // 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 bool take_c800() override;
+
+private:
+ //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
+};
/***************************************************************************
FUNCTION PROTOTYPES
@@ -110,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)
{
@@ -170,3 +200,12 @@ bool a2bus_echoii_device::take_c800()
{
return false;
}
+
+} // anonymous namespace
+
+
+//**************************************************************************
+// GLOBAL VARIABLES
+//**************************************************************************
+
+DEFINE_DEVICE_TYPE_PRIVATE(A2BUS_ECHOII, device_a2bus_card_interface, a2bus_echoii_device, "a2echoii", "Street Electronics Echo II")
diff --git a/src/devices/bus/a2bus/a2echoii.h b/src/devices/bus/a2bus/a2echoii.h
index 7cb1c401550..264f8e065d9 100644
--- a/src/devices/bus/a2bus/a2echoii.h
+++ b/src/devices/bus/a2bus/a2echoii.h
@@ -14,43 +14,8 @@
#pragma once
#include "a2bus.h"
-#include "sound/tms5220.h"
-
-//**************************************************************************
-// TYPE DEFINITIONS
-//**************************************************************************
-
-class a2bus_echoii_device:
- public device_t,
- public device_a2bus_card_interface
-{
-public:
- // construction/destruction
- a2bus_echoii_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
-
- required_device<tms5220_device> m_tms;
-
-protected:
- a2bus_echoii_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
- virtual uint8_t read_c0nx(uint8_t offset) override;
- virtual void write_c0nx(uint8_t offset, uint8_t data) override;
- virtual bool take_c800() override;
-
-private:
- //DECLARE_WRITE_LINE_MEMBER(tms_irq_callback);
- DECLARE_WRITE_LINE_MEMBER(tms_readyq_callback);
- uint8_t m_writelatch_data; // 74ls373 latch
- bool m_readlatch_flag; // 74c74 1st half
- bool m_writelatch_flag; // 74c74 2nd half
-};
-
-// device type definition
-DECLARE_DEVICE_TYPE(A2BUS_ECHOII, a2bus_echoii_device)
+
+// device type declaration
+DECLARE_DEVICE_TYPE(A2BUS_ECHOII, device_a2bus_card_interface)
#endif // MAME_BUS_A2BUS_A2ECHOII_H
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..9e79193e99d 100644
--- a/src/devices/bus/a2bus/a2eext80col.h
+++ b/src/devices/bus/a2bus/a2eext80col.h
@@ -2,14 +2,14 @@
// copyright-holders:R. Belmont
/*********************************************************************
- a2eext80col.c
+ a2eext80col.h
Apple IIe Extended 80 Column Card
*********************************************************************/
-#ifndef MAME_BUS_A2BUS_A2EEXT809COL_H
-#define MAME_BUS_A2BUS_A2EEXT809COL_H
+#ifndef MAME_BUS_A2BUS_A2EEXT80COL_H
+#define MAME_BUS_A2BUS_A2EEXT80COL_H
#pragma once
@@ -30,20 +30,21 @@ public:
protected:
a2eaux_ext80col_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_start() override ATTR_COLD;
+ virtual void device_reset() override ATTR_COLD;
- 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
DECLARE_DEVICE_TYPE(A2EAUX_EXT80COL, a2eaux_ext80col_device)
-#endif // MAME_BUS_A2BUS_A2EEXT809COL_H
+#endif // MAME_BUS_A2BUS_A2EEXT80COL_H
diff --git a/src/devices/bus/a2bus/a2eramworks3.cpp b/src/devices/bus/a2bus/a2eramworks3.cpp
index 46ada4066a1..11dcf3cae68 100644
--- a/src/devices/bus/a2bus/a2eramworks3.cpp
+++ b/src/devices/bus/a2bus/a2eramworks3.cpp
@@ -2,10 +2,11 @@
// copyright-holders:R. Belmont
/*********************************************************************
- a2eramworks3.c
+ a2eramworks3.cpp
Applied Engineering RamWorks III
+ The AE RamWorks patent is US 4601018.
*********************************************************************/
@@ -22,6 +23,8 @@
//**************************************************************************
DEFINE_DEVICE_TYPE(A2EAUX_RAMWORKS3, a2eaux_ramworks3_device, "a2erwks3", "Applied Engineering RamWorks III")
+DEFINE_DEVICE_TYPE(A2EAUX_FRANKLIN384, a2eaux_franklin384_device, "a2ef384", "Franklin ACE 500 expansion RAM")
+DEFINE_DEVICE_TYPE(A2EAUX_FRANKLIN512, a2eaux_franklin512_device, "a2ef512", "Franklin ACE 2x00 expansion RAM")
//**************************************************************************
// LIVE DEVICE
@@ -39,6 +42,16 @@ a2eaux_ramworks3_device::a2eaux_ramworks3_device(const machine_config &mconfig,
{
}
+a2eaux_franklin384_device::a2eaux_franklin384_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) :
+ a2eaux_ramworks3_device(mconfig, A2EAUX_FRANKLIN384, tag, owner, clock)
+{
+}
+
+a2eaux_franklin512_device::a2eaux_franklin512_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) :
+ a2eaux_ramworks3_device(mconfig, A2EAUX_FRANKLIN512, tag, owner, clock)
+{
+}
+
//-------------------------------------------------
// device_start - device-specific startup
//-------------------------------------------------
@@ -54,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.
@@ -87,11 +105,34 @@ 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 C073?
- if (offset == 3)
+ // write to C071/3/5/7?
+ if ((offset & 0x9) == 1)
{
m_bank = 0x10000 * (data & 0x7f);
}
}
+
+void a2eaux_franklin384_device::write_c07x(u8 offset, u8 data)
+{
+ if ((offset & 0x9) == 1)
+ {
+ // RamWorks/Z-RAM bank order is 0 3 4 7 8 11 12 15
+ // so cut off access above bank 11 to limit to 384K.
+ if (data > 11)
+ {
+ data = 0;
+ }
+ m_bank = 0x10000 * (data & 0xf);
+ }
+}
+
+void a2eaux_franklin512_device::write_c07x(u8 offset, u8 data)
+{
+ if ((offset & 0x9) == 1)
+ {
+ m_bank = 0x10000 * (data & 0x0f);
+ }
+}
+
diff --git a/src/devices/bus/a2bus/a2eramworks3.h b/src/devices/bus/a2bus/a2eramworks3.h
index d47d88c37d9..b837b0dac0d 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
@@ -28,22 +28,44 @@ public:
protected:
a2eaux_ramworks3_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_start() override ATTR_COLD;
+ virtual void device_reset() override ATTR_COLD;
- 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;
-private:
- uint8_t m_ram[8*1024*1024];
int m_bank;
+
+private:
+ u8 m_ram[8*1024*1024];
+};
+
+class a2eaux_franklin384_device: public a2eaux_ramworks3_device
+{
+public:
+ a2eaux_franklin384_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
+
+protected:
+ virtual void write_c07x(u8 offset, u8 data) override;
+};
+
+class a2eaux_franklin512_device: public a2eaux_ramworks3_device
+{
+public:
+ a2eaux_franklin512_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
+
+protected:
+ virtual void write_c07x(u8 offset, u8 data) override;
};
// device type definition
DECLARE_DEVICE_TYPE(A2EAUX_RAMWORKS3, a2eaux_ramworks3_device)
+DECLARE_DEVICE_TYPE(A2EAUX_FRANKLIN384, a2eaux_franklin384_device)
+DECLARE_DEVICE_TYPE(A2EAUX_FRANKLIN512, a2eaux_franklin512_device)
#endif // MAME_BUS_A2BUS_A2ERAMWORKS3_H
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..9d52676893f 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
@@ -30,17 +30,18 @@ public:
protected:
a2eaux_std80col_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_start() override ATTR_COLD;
+ virtual void device_reset() override ATTR_COLD;
- 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 98c612dae78..2d015cf5d36 100644
--- a/src/devices/bus/a2bus/a2hsscsi.cpp
+++ b/src/devices/bus/a2bus/a2hsscsi.cpp
@@ -2,7 +2,7 @@
// copyright-holders:R. Belmont
/*********************************************************************
- a2hsscsi.c
+ a2hsscsi.cpp
Implementation of the Apple II High Speed SCSI Card
@@ -101,7 +101,8 @@ a2bus_hsscsi_device::a2bus_hsscsi_device(const machine_config &mconfig, device_t
device_t(mconfig, type, tag, owner, clock),
device_a2bus_card_interface(mconfig, *this),
m_ncr5380(*this, SCSI_5380_TAG),
- m_scsibus(*this, SCSI_BUS_TAG), m_rom(nullptr), m_rambank(0), m_rombank(0), m_drq(0), m_bank(0), m_816block(false), m_c0ne(0), m_c0nf(0)
+ m_scsibus(*this, SCSI_BUS_TAG), m_rom(*this, SCSI_ROM_REGION), m_rambank(0), m_rombank(0), m_drq(0), m_bank(0), m_c0ne(0), m_c0nf(0),
+ m_dma_addr(0), m_dma_size(0)
{
}
@@ -116,8 +117,6 @@ a2bus_hsscsi_device::a2bus_hsscsi_device(const machine_config &mconfig, const ch
void a2bus_hsscsi_device::device_start()
{
- m_rom = machine().root_device().memregion(this->subtag(SCSI_ROM_REGION).c_str())->base();
-
memset(m_ram, 0, 8192);
save_item(NAME(m_ram));
@@ -125,15 +124,16 @@ void a2bus_hsscsi_device::device_start()
save_item(NAME(m_rombank));
save_item(NAME(m_bank));
save_item(NAME(m_drq));
- save_item(NAME(m_816block));
+ save_item(NAME(m_dma_addr));
+ save_item(NAME(m_dma_size));
}
void a2bus_hsscsi_device::device_reset()
{
m_rambank = 0;
m_rombank = 0;
+ m_dma_addr = m_dma_size = 0;
m_c0ne = m_c0nf = 0;
- m_816block = false;
}
@@ -151,13 +151,35 @@ uint8_t a2bus_hsscsi_device::read_c0nx(uint8_t offset)
case 3:
case 4:
case 5:
- case 6:
case 7:
// logerror("Read 5380 @ %x\n", offset);
return m_ncr5380->read(offset);
- case 0xc:
- return 0x00; // indicate watchdog?
+ case 6:
+ if (m_dma_control & 1) // pseudo-DMA?
+ {
+ return m_ncr5380->dma_r();
+ }
+ else
+ {
+ //printf("Read 5380 PIO data (%s)\n", machine().describe_context().c_str());
+ return m_ncr5380->read(offset);
+ }
+
+ case 8: // DMA address low
+ return m_dma_addr & 0xff;
+
+ case 9: // DMA address high
+ return (m_dma_addr >> 8) & 0xff;
+
+ case 0xa: // DMA size low
+ return m_dma_size & 0xff;
+
+ case 0xb: // DMA size high
+ return (m_dma_size >> 8) & 0xff;
+
+ case 0xc: // DMA control
+ return m_dma_control;
case 0xe: // code at cf32 wants to RMW this without killing the ROM bank
return m_c0ne;
@@ -166,7 +188,7 @@ uint8_t a2bus_hsscsi_device::read_c0nx(uint8_t offset)
return m_c0nf;
default:
- logerror("Read c0n%x (%s)\n", offset, machine().describe_context());
+ logerror("Read c0n%x (%s)\n", offset, machine().describe_context().c_str());
break;
}
@@ -182,7 +204,17 @@ void a2bus_hsscsi_device::write_c0nx(uint8_t offset, uint8_t data)
{
switch (offset)
{
- case 0:
+ case 0: // data out register; in PDMA mode, it's assumed this goes to DMA as reads do
+ if (m_dma_control & 1)
+ {
+ m_ncr5380->dma_w(data);
+ }
+ else
+ {
+ m_ncr5380->write(offset, data);
+ }
+ break;
+
case 1:
case 2:
case 3:
@@ -193,25 +225,39 @@ void a2bus_hsscsi_device::write_c0nx(uint8_t offset, uint8_t data)
// logerror("%02x to 5380 reg %x\n", data, offset);
m_ncr5380->write(offset, data);
break;
-#if 0
+
case 8: // DMA address low
+ //printf("%02x to DMA adr low\n", data);
+ m_dma_addr &= 0xff00;
+ m_dma_addr |= data;
break;
case 9: // DMA address high
+ //printf("%02x to DMA adr high\n", data);
+ m_dma_addr &= 0x00ff;
+ m_dma_addr |= (data << 8);
break;
case 0xa: // DMA count low
+ //printf("%02x to DMA count low\n", data);
+ m_dma_size &= 0xff00;
+ m_dma_size |= data;
break;
case 0xb: // DMA count high
+ //printf("%02x to DMA count high\n", data);
+ m_dma_size &= 0x00ff;
+ m_dma_size |= (data << 8);
break;
case 0xc: // DMA control
+ //printf("%02x to DMA control\n", data);
+ m_dma_control &= ~0x2b; // clear the read/write bits
+ m_dma_control |= (data & 0x2b);
break;
-#endif
case 0xd: // DMA enable / reset
- logerror("%02x to DMA enable/reset\n", data);
+ //printf("%02x to DMA enable/reset\n", data);
if (data & 0x2)
{
// logerror("Resetting SCSI: %02x at %s\n", data, machine().describe_context());
@@ -222,17 +268,17 @@ void a2bus_hsscsi_device::write_c0nx(uint8_t offset, uint8_t data)
case 0xe:
m_c0ne = data;
m_rombank = (data & 0x1f) * 0x400;
- logerror("c0ne to %x (ROM bank %x)\n", data & 0x1f, m_rombank);
+ //logerror("c0ne to %x (ROM bank %x)\n", data & 0x1f, m_rombank);
break;
case 0xf:
m_c0nf = data;
m_rambank = (data & 0x7) * 0x400;
- logerror("c0nf to %x (RAM bank %x)\n", data & 0x7, m_rambank);
+ //logerror("c0nf to %x (RAM bank %x)\n", data & 0x7, m_rambank);
break;
default:
- logerror("Write %02x to c0n%x (%s)\n", data, offset, machine().describe_context());
+ logerror("Write %02x to c0n%x (%s)\n", data, offset, machine().describe_context().c_str());
break;
}
}
@@ -263,11 +309,6 @@ uint8_t a2bus_hsscsi_device::read_c800(uint16_t offset)
if (offset < 0x400)
{
// logerror("Read RAM at %x = %02x\n", offset+m_rambank, m_ram[offset + m_rambank]);
- if (m_816block)
- {
- return m_ncr5380->dma_r();
- }
-
return m_ram[offset + m_rambank];
}
else
@@ -284,18 +325,12 @@ void a2bus_hsscsi_device::write_c800(uint16_t offset, uint8_t data)
if (offset < 0x400)
{
// logerror("%02x to RAM at %x\n", data, offset+m_rambank);
- if (m_816block)
- {
- m_ncr5380->dma_w(data);
- }
- else
- {
- m_ram[offset + m_rambank] = data;
- }
+ m_ram[offset + m_rambank] = 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 a660dac5e58..b3c17d9a1dd 100644
--- a/src/devices/bus/a2bus/a2hsscsi.h
+++ b/src/devices/bus/a2bus/a2hsscsi.h
@@ -14,7 +14,7 @@
#pragma once
#include "a2bus.h"
-#include "machine/ncr5380n.h"
+#include "machine/ncr5380.h"
//**************************************************************************
// TYPE DEFINITIONS
@@ -28,15 +28,17 @@ public:
// construction/destruction
a2bus_hsscsi_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
- DECLARE_WRITE_LINE_MEMBER( drq_w );
+ static constexpr feature_type unemulated_features() { return feature::DISK; }
+
+ 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);
- 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 device_start() override ATTR_COLD;
+ virtual void device_reset() override ATTR_COLD;
+ virtual void device_add_mconfig(machine_config &config) override ATTR_COLD;
+ virtual const tiny_rom_entry *device_rom_region() const override ATTR_COLD;
// overrides of standard a2bus slot functions
virtual uint8_t read_c0nx(uint8_t offset) override;
@@ -48,15 +50,16 @@ protected:
required_device<ncr53c80_device> m_ncr5380;
required_device<nscsi_bus_device> m_scsibus;
+ required_region_ptr<u8> m_rom;
private:
- uint8_t *m_rom;
uint8_t m_ram[8192]; // 8 banks of 1024 bytes
int m_rambank, m_rombank;
uint8_t m_drq;
uint8_t m_bank;
- bool m_816block;
+ uint8_t m_dma_control;
uint8_t m_c0ne, m_c0nf;
+ uint16_t m_dma_addr, m_dma_size;
};
// device type definition
diff --git a/src/devices/bus/a2bus/a2iwm.cpp b/src/devices/bus/a2bus/a2iwm.cpp
new file mode 100644
index 00000000000..74adc23ffa8
--- /dev/null
+++ b/src/devices/bus/a2bus/a2iwm.cpp
@@ -0,0 +1,141 @@
+// license:BSD-3-Clause
+// copyright-holders:R. Belmont, O. Galibert
+/*********************************************************************
+
+ a2iwm.c
+
+ Implementation of the Apple II IWM controller card
+
+ WANTED: there are no ROM dumps from this card in any form
+ (the IWM card, the UniDisk )
+
+*********************************************************************/
+
+#include "emu.h"
+#include "a2iwm.h"
+
+#include "machine/applefdintf.h"
+#include "formats/ap2_dsk.h"
+#include "formats/as_dsk.h"
+
+
+//**************************************************************************
+// GLOBAL VARIABLES
+//**************************************************************************
+
+DEFINE_DEVICE_TYPE(A2BUS_IWM, a2bus_iwm_int_device, "a2iwmint", "Apple IWM controller")
+DEFINE_DEVICE_TYPE(A2BUS_IWM_CARD, a2bus_iwm_card_device, "a2iwm", "Apple Disk II IWM controller")
+
+#define DISKII_ROM_REGION "diskii_rom"
+
+ROM_START( iwm )
+ ROM_REGION(0x100, DISKII_ROM_REGION, 0)
+ ROM_LOAD( "341-0027-a.p5", 0x000000, 0x000100, CRC(ce7144f6) SHA1(d4181c9f046aafc3fb326b381baac809d9e38d16) )
+ROM_END
+
+//-------------------------------------------------
+// device_add_mconfig - add device configuration
+//-------------------------------------------------
+
+void a2bus_iwm_device::device_add_mconfig(machine_config &config)
+{
+ IWM(config, m_iwm, clock(), 1021800*2);
+ m_iwm->phases_cb().set(FUNC(a2bus_iwm_device::phases_w));
+ m_iwm->devsel_cb().set(FUNC(a2bus_iwm_device::devsel_w));
+ applefdintf_device::add_525(config, m_floppy[0]);
+ applefdintf_device::add_525(config, m_floppy[1]);
+}
+
+//-------------------------------------------------
+// rom_region - device-specific ROM region
+//-------------------------------------------------
+
+const tiny_rom_entry *a2bus_iwm_card_device::device_rom_region() const
+{
+ return ROM_NAME( iwm );
+}
+
+//**************************************************************************
+// LIVE DEVICE
+//**************************************************************************
+
+a2bus_iwm_device::a2bus_iwm_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_iwm(*this, "iwm"),
+ m_floppy(*this, "%u", 0U)
+{
+}
+
+a2bus_iwm_int_device::a2bus_iwm_int_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) :
+ a2bus_iwm_device(mconfig, A2BUS_IWM, tag, owner, clock)
+{
+}
+
+a2bus_iwm_card_device::a2bus_iwm_card_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) :
+ a2bus_iwm_device(mconfig, A2BUS_IWM_CARD, tag, owner, clock)
+{
+}
+
+//-------------------------------------------------
+// device_start - device-specific startup
+//-------------------------------------------------
+
+void a2bus_iwm_device::device_start()
+{
+}
+
+void a2bus_iwm_card_device::device_start()
+{
+ a2bus_iwm_device::device_start();
+ m_rom = device().machine().root_device().memregion(this->subtag(DISKII_ROM_REGION).c_str())->base();
+}
+
+void a2bus_iwm_device::device_reset()
+{
+}
+
+/*-------------------------------------------------
+ read_c0nx - called for reads from this card's c0nx space
+-------------------------------------------------*/
+
+uint8_t a2bus_iwm_device::read_c0nx(u8 offset)
+{
+ return m_iwm->read(offset);
+}
+
+
+/*-------------------------------------------------
+ write_c0nx - called for writes to this card's c0nx space
+-------------------------------------------------*/
+
+void a2bus_iwm_device::write_c0nx(u8 offset, u8 data)
+{
+ m_iwm->write(offset, data);
+}
+
+/*-------------------------------------------------
+ read_cnxx - called for reads from this card's c0nx space
+-------------------------------------------------*/
+
+uint8_t a2bus_iwm_card_device::read_cnxx(uint8_t offset)
+{
+ return m_rom[offset];
+}
+
+void a2bus_iwm_device::devsel_w(u8 data)
+{
+ if(data & 1)
+ m_iwm->set_floppy(m_floppy[0]->get_device());
+ else if(data & 2)
+ m_iwm->set_floppy(m_floppy[1]->get_device());
+ else
+ m_iwm->set_floppy(nullptr);
+}
+
+void a2bus_iwm_device::phases_w(u8 data)
+{
+ auto flp = m_iwm->get_floppy();
+ if(flp)
+ flp->seek_phase_w(data);
+}
diff --git a/src/devices/bus/a2bus/a2iwm.h b/src/devices/bus/a2bus/a2iwm.h
new file mode 100644
index 00000000000..6c4f008b0ef
--- /dev/null
+++ b/src/devices/bus/a2bus/a2iwm.h
@@ -0,0 +1,73 @@
+// license:BSD-3-Clause
+// copyright-holders:R. Belmont, O. Galibert
+/*********************************************************************
+
+ a2iwm.h
+
+ Apple II IWM Controller Card, new floppy
+
+*********************************************************************/
+
+#ifndef MAME_BUS_A2BUS_A2IWM_H
+#define MAME_BUS_A2BUS_A2IWM_H
+
+#pragma once
+
+#include "a2bus.h"
+#include "imagedev/floppy.h"
+#include "machine/iwm.h"
+
+//**************************************************************************
+// TYPE DEFINITIONS
+//**************************************************************************
+
+
+class a2bus_iwm_device:
+ public device_t,
+ public device_a2bus_card_interface
+{
+protected:
+ // construction/destruction
+ a2bus_iwm_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock);
+
+ 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;
+
+ // overrides of standard a2bus slot functions
+ virtual uint8_t read_c0nx(u8 offset) override;
+ virtual void write_c0nx(u8 offset, u8 data) override;
+
+ required_device<iwm_device> m_iwm;
+ required_device_array<floppy_connector, 2> m_floppy;
+
+private:
+ void devsel_w(u8 data);
+ void phases_w(u8 data);
+};
+
+class a2bus_iwm_int_device: public a2bus_iwm_device
+{
+public:
+ a2bus_iwm_int_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
+};
+
+class a2bus_iwm_card_device: public a2bus_iwm_device
+{
+public:
+ a2bus_iwm_card_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
+
+ virtual void device_start() override ATTR_COLD;
+ virtual const tiny_rom_entry *device_rom_region() const override ATTR_COLD;
+
+ virtual uint8_t read_cnxx(uint8_t offset) override;
+
+private:
+ uint8_t *m_rom;
+};
+
+// device type definition
+DECLARE_DEVICE_TYPE(A2BUS_IWM, a2bus_iwm_int_device)
+DECLARE_DEVICE_TYPE(A2BUS_IWM_CARD, a2bus_iwm_card_device)
+
+#endif // MAME_BUS_A2BUS_A2IWM_H
diff --git a/src/devices/bus/a2bus/a2mcms.cpp b/src/devices/bus/a2bus/a2mcms.cpp
index 7e2cab57b6b..7ccf96376fa 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,10 +205,9 @@ mcms_device::mcms_device(const machine_config &mconfig, const char *tag, device_
void mcms_device::device_start()
{
- m_write_irq.resolve();
- m_stream = machine().sound().stream_alloc(*this, 0, 2, 31250);
- m_timer = timer_alloc(0, nullptr);
- m_clrtimer = timer_alloc(1, nullptr);
+ 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);
m_enabled = false;
memset(m_vols, 0, sizeof(m_vols));
memset(m_table, 0, sizeof(m_table));
@@ -238,34 +237,28 @@ void mcms_device::device_reset()
m_enabled = false;
}
-void mcms_device::device_timer(emu_timer &timer, device_timer_id tid, int param, void *ptr)
+TIMER_CALLBACK_MEMBER(mcms_device::set_irq_tick)
{
- if (tid == 0)
- {
- m_write_irq(ASSERT_LINE);
- // clear this IRQ in 10 cycles (?)
- m_clrtimer->adjust(attotime::from_usec(10), 0);
- }
- else if (tid == 1)
- {
- m_write_irq(CLEAR_LINE);
- }
+ m_write_irq(ASSERT_LINE);
+ // clear this IRQ in 10 cycles (?)
+ m_clrtimer->adjust(attotime::from_usec(10), 0);
+}
+
+TIMER_CALLBACK_MEMBER(mcms_device::clr_irq_tick)
+{
+ m_write_irq(CLEAR_LINE);
}
-void mcms_device::sound_stream_update(sound_stream &stream, stream_sample_t **inputs, stream_sample_t **outputs, int samples)
+void mcms_device::sound_stream_update(sound_stream &stream)
{
- stream_sample_t *outL, *outR;
int i, v;
uint16_t wptr;
int8_t sample;
int32_t mixL, mixR;
- outL = outputs[1];
- outR = outputs[0];
-
if (m_enabled)
{
- for (i = 0; i < samples; i++)
+ for (i = 0; i < stream.samples(); i++)
{
mixL = mixR = 0;
@@ -286,15 +279,8 @@ void mcms_device::sound_stream_update(sound_stream &stream, stream_sample_t **in
}
}
- outL[i] = (mixL * m_mastervol)>>9;
- outR[i] = (mixR * m_mastervol)>>9;
- }
- }
- else
- {
- for (i = 0; i < samples; i++)
- {
- outL[i] = outR[i] = 0;
+ stream.put_int(0, i, mixL * m_mastervol, 32768 << 9);
+ stream.put_int(1, i, mixR * m_mastervol, 32768 << 9);
}
}
}
diff --git a/src/devices/bus/a2bus/a2mcms.h b/src/devices/bus/a2bus/a2mcms.h
index 9a183a9313d..0f8cd2e72fb 100644
--- a/src/devices/bus/a2bus/a2mcms.h
+++ b/src/devices/bus/a2bus/a2mcms.h
@@ -38,15 +38,18 @@ public:
protected:
// device-level overrides
- virtual void device_start() override;
- virtual void device_reset() override;
- virtual void device_timer(emu_timer &timer, device_timer_id id, int param, void *ptr) override;
+ virtual void device_start() override ATTR_COLD;
+ virtual void device_reset() override ATTR_COLD;
- virtual void sound_stream_update(sound_stream &stream, stream_sample_t **inputs, stream_sample_t **outputs, int samples) override;
+ virtual void sound_stream_update(sound_stream &stream) override;
+
+ TIMER_CALLBACK_MEMBER(set_irq_tick);
+ TIMER_CALLBACK_MEMBER(clr_irq_tick);
private:
sound_stream *m_stream;
- emu_timer *m_timer, *m_clrtimer;
+ emu_timer *m_timer;
+ emu_timer *m_clrtimer;
a2bus_mcms1_device *m_pBusDevice;
bool m_enabled;
uint8_t m_vols[16];
@@ -74,9 +77,9 @@ public:
protected:
a2bus_mcms1_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 device_start() override ATTR_COLD;
+ virtual void device_reset() override ATTR_COLD;
+ virtual void device_add_mconfig(machine_config &config) override ATTR_COLD;
// overrides of standard a2bus slot functions
virtual uint8_t read_c0nx(uint8_t offset) override;
@@ -85,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
@@ -100,8 +103,8 @@ public:
protected:
a2bus_mcms2_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_start() override ATTR_COLD;
+ virtual void device_reset() override ATTR_COLD;
// overrides of standard a2bus slot functions
virtual uint8_t read_c0nx(uint8_t offset) override;
diff --git a/src/devices/bus/a2bus/a2memexp.cpp b/src/devices/bus/a2bus/a2memexp.cpp
index 6b088a1ea12..e0e79223d92 100644
--- a/src/devices/bus/a2bus/a2memexp.cpp
+++ b/src/devices/bus/a2bus/a2memexp.cpp
@@ -12,17 +12,12 @@
#include "a2memexp.h"
+namespace {
+
/***************************************************************************
PARAMETERS
***************************************************************************/
-//**************************************************************************
-// GLOBAL VARIABLES
-//**************************************************************************
-
-DEFINE_DEVICE_TYPE(A2BUS_MEMEXP, a2bus_memexpapple_device, "a2memexp", "Apple II Memory Expansion Card")
-DEFINE_DEVICE_TYPE(A2BUS_RAMFACTOR, a2bus_ramfactor_device, "a2ramfac", "Applied Engineering RamFactor")
-
#define MEMEXP_ROM_REGION "memexp_rom"
ROM_START( memexp )
@@ -38,6 +33,56 @@ ROM_START( ramfactor )
ROM_LOAD( "ae ramfactor rom v1.0.bin", 0x6000, 0x2000, CRC(39c2162a) SHA1(9286d35907939aadb1fffd3e1d75603fe3e846ad) )
ROM_END
+//**************************************************************************
+// TYPE DEFINITIONS
+//**************************************************************************
+
+class a2bus_memexp_device:
+ public device_t,
+ public device_a2bus_card_interface
+{
+public:
+ bool m_isramfactor;
+ uint8_t m_bankhior;
+ int m_addrmask;
+
+protected:
+ // construction/destruction
+ a2bus_memexp_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock);
+
+ 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;
+ virtual const tiny_rom_entry *device_rom_region() const override ATTR_COLD;
+
+ // 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;
+ virtual uint8_t read_c800(uint16_t offset) override;
+
+private:
+ required_region_ptr<uint8_t> m_rom;
+ uint8_t m_regs[0x10];
+ uint8_t m_ram[8*1024*1024];
+ int m_wptr, m_liveptr;
+};
+
+class a2bus_memexpapple_device : public a2bus_memexp_device
+{
+public:
+ a2bus_memexpapple_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
+};
+
+class a2bus_ramfactor_device : public a2bus_memexp_device
+{
+public:
+ a2bus_ramfactor_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 ATTR_COLD;
+};
+
/***************************************************************************
FUNCTION PROTOTYPES
***************************************************************************/
@@ -70,7 +115,9 @@ const tiny_rom_entry *a2bus_ramfactor_device::device_rom_region() const
a2bus_memexp_device::a2bus_memexp_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_isramfactor(false), m_bankhior(0), m_addrmask(0), m_rom(nullptr), m_wptr(0), m_liveptr(0)
+ device_a2bus_card_interface(mconfig, *this), m_isramfactor(false), m_bankhior(0), m_addrmask(0),
+ m_rom(*this, MEMEXP_ROM_REGION),
+ m_wptr(0), m_liveptr(0)
{
}
@@ -96,8 +143,6 @@ a2bus_ramfactor_device::a2bus_ramfactor_device(const machine_config &mconfig, co
void a2bus_memexp_device::device_start()
{
- m_rom = device().machine().root_device().memregion(this->subtag(MEMEXP_ROM_REGION).c_str())->base();
-
memset(m_ram, 0xff, 1024*1024*sizeof(uint8_t));
save_item(NAME(m_regs));
@@ -212,3 +257,13 @@ uint8_t a2bus_memexp_device::read_c800(uint16_t offset)
else
return m_rom[offset+0x800];
}
+
+} // anonymous namespace
+
+
+//**************************************************************************
+// GLOBAL VARIABLES
+//**************************************************************************
+
+DEFINE_DEVICE_TYPE_PRIVATE(A2BUS_MEMEXP, device_a2bus_card_interface, a2bus_memexpapple_device, "a2memexp", "Apple II Memory Expansion Card")
+DEFINE_DEVICE_TYPE_PRIVATE(A2BUS_RAMFACTOR, device_a2bus_card_interface, a2bus_ramfactor_device, "a2ramfac", "Applied Engineering RamFactor")
diff --git a/src/devices/bus/a2bus/a2memexp.h b/src/devices/bus/a2bus/a2memexp.h
index 2eeb3e157ae..0823ce27b9a 100644
--- a/src/devices/bus/a2bus/a2memexp.h
+++ b/src/devices/bus/a2bus/a2memexp.h
@@ -15,57 +15,8 @@
#include "a2bus.h"
-//**************************************************************************
-// TYPE DEFINITIONS
-//**************************************************************************
-
-class a2bus_memexp_device:
- public device_t,
- public device_a2bus_card_interface
-{
-public:
- bool m_isramfactor;
- uint8_t m_bankhior;
- int m_addrmask;
-
-protected:
- // construction/destruction
- a2bus_memexp_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;
- virtual uint8_t read_c800(uint16_t offset) override;
-
-private:
- uint8_t *m_rom;
- uint8_t m_regs[0x10];
- uint8_t m_ram[8*1024*1024];
- int m_wptr, m_liveptr;
-};
-
-class a2bus_memexpapple_device : public a2bus_memexp_device
-{
-public:
- a2bus_memexpapple_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
-};
-
-class a2bus_ramfactor_device : public a2bus_memexp_device
-{
-public:
- a2bus_ramfactor_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(A2BUS_MEMEXP, a2bus_memexpapple_device)
-DECLARE_DEVICE_TYPE(A2BUS_RAMFACTOR, a2bus_ramfactor_device)
+DECLARE_DEVICE_TYPE(A2BUS_MEMEXP, device_a2bus_card_interface)
+DECLARE_DEVICE_TYPE(A2BUS_RAMFACTOR, device_a2bus_card_interface)
#endif // MAME_BUS_A2BUS_A2MEMEXP_H
diff --git a/src/devices/bus/a2bus/a2midi.cpp b/src/devices/bus/a2bus/a2midi.cpp
index dfd6ce71694..ef19bd4e7e6 100644
--- a/src/devices/bus/a2bus/a2midi.cpp
+++ b/src/devices/bus/a2bus/a2midi.cpp
@@ -10,23 +10,55 @@
#include "emu.h"
#include "a2midi.h"
-#include "machine/clock.h"
+
#include "bus/midi/midi.h"
+#include "machine/6840ptm.h"
+#include "machine/6850acia.h"
+#include "machine/clock.h"
+namespace {
+
/***************************************************************************
PARAMETERS
***************************************************************************/
+#define MIDI_PTM_TAG "midi_ptm"
+#define MIDI_ACIA_TAG "midi_acia"
+
+
//**************************************************************************
-// GLOBAL VARIABLES
+// TYPE DEFINITIONS
//**************************************************************************
-DEFINE_DEVICE_TYPE(A2BUS_MIDI, a2bus_midi_device, "a2midi", "6850 MIDI card")
+class a2bus_midi_device:
+ public device_t,
+ public device_a2bus_card_interface
+{
+public:
+ // construction/destruction
+ a2bus_midi_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
-#define MIDI_PTM_TAG "midi_ptm"
-#define MIDI_ACIA_TAG "midi_acia"
+protected:
+ a2bus_midi_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock);
+ 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;
+
+ virtual uint8_t read_c0nx(uint8_t offset) override;
+ virtual void write_c0nx(uint8_t offset, uint8_t data) override;
+
+ required_device<ptm6840_device> m_ptm;
+ required_device<acia6850_device> m_acia;
+
+private:
+ 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;
+};
//-------------------------------------------------
// device_add_mconfig - add device configuration
@@ -117,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;
@@ -131,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;
@@ -145,8 +177,17 @@ 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);
}
+
+} // anonymous namespace
+
+
+//**************************************************************************
+// GLOBAL VARIABLES
+//**************************************************************************
+
+DEFINE_DEVICE_TYPE_PRIVATE(A2BUS_MIDI, device_a2bus_card_interface, a2bus_midi_device, "a2midi", "6850 MIDI card")
diff --git a/src/devices/bus/a2bus/a2midi.h b/src/devices/bus/a2bus/a2midi.h
index 67da46ee89f..c4f6b1462ee 100644
--- a/src/devices/bus/a2bus/a2midi.h
+++ b/src/devices/bus/a2bus/a2midi.h
@@ -14,43 +14,8 @@
#pragma once
#include "a2bus.h"
-#include "machine/6840ptm.h"
-#include "machine/6850acia.h"
-
-//**************************************************************************
-// TYPE DEFINITIONS
-//**************************************************************************
-
-class a2bus_midi_device:
- public device_t,
- public device_a2bus_card_interface
-{
-public:
- // construction/destruction
- a2bus_midi_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
-
-protected:
- a2bus_midi_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 uint8_t read_c0nx(uint8_t offset) override;
- virtual void write_c0nx(uint8_t offset, uint8_t data) override;
-
- required_device<ptm6840_device> m_ptm;
- 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 );
-
- bool m_acia_irq, m_ptm_irq;
-};
// device type definition
-DECLARE_DEVICE_TYPE(A2BUS_MIDI, a2bus_midi_device)
+DECLARE_DEVICE_TYPE(A2BUS_MIDI, device_a2bus_card_interface)
#endif // MAME_BUS_A2BUS_A2MIDI_H
diff --git a/src/devices/bus/a2bus/a2mockingboard.cpp b/src/devices/bus/a2bus/a2mockingboard.cpp
index c4c45b6975b..dbe2463a4a8 100644
--- a/src/devices/bus/a2bus/a2mockingboard.cpp
+++ b/src/devices/bus/a2bus/a2mockingboard.cpp
@@ -2,7 +2,7 @@
// copyright-holders:R. Belmont
/*********************************************************************
- a2mockingboard.c
+ a2mockingboard.cpp
Implementation of the Sweet Micro Systems Mockingboard card
and friends.
@@ -11,85 +11,208 @@
#include "emu.h"
#include "a2mockingboard.h"
-#include "speaker.h"
+#include "machine/6522via.h"
+#include "sound/ay8910.h"
+#include "sound/tms5220.h"
+#include "sound/votrax.h"
+
+#include "speaker.h"
-/***************************************************************************
- 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"
+namespace {
//**************************************************************************
-// GLOBAL VARIABLES
+// TYPE DEFINITIONS
//**************************************************************************
-DEFINE_DEVICE_TYPE(A2BUS_MOCKINGBOARD, a2bus_mockingboard_device, "a2mockbd", "Sweet Micro Systems Mockingboard")
-DEFINE_DEVICE_TYPE(A2BUS_PHASOR, a2bus_phasor_device, "a2phasor", "Applied Engineering Phasor")
-DEFINE_DEVICE_TYPE(A2BUS_ECHOPLUS, a2bus_echoplus_device, "a2echop", "Street Electronics Echo Plus")
+class a2bus_ayboard_device:
+ public device_t,
+ public device_a2bus_card_interface
+{
+protected:
+ // construction/destruction
+ 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;
+
+ 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;
+ required_device<ay8913_device> m_ay1;
+ required_device<ay8913_device> m_ay2;
+
+ u8 m_porta1;
+ u8 m_porta2;
+};
+
+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) ATTR_COLD;
+
+protected:
+ // 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:
+ void write_via1_cb2(int state);
+
+ u8 m_portb1;
+ int m_last_cb2_state;
+};
+
+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) ATTR_COLD;
+
+protected:
+ // 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;
+
+private:
+ void set_clocks();
+
+ bool m_native;
+};
+
+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) ATTR_COLD;
+
+protected:
+ // 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)
{
- VIA6522(config, m_via1, 1022727);
+ MOS6522(config, m_via1, 1022727);
+ m_via1->readpa_handler().set(FUNC(a2bus_ayboard_device::via1_in_a));
m_via1->writepa_handler().set(FUNC(a2bus_ayboard_device::via1_out_a));
m_via1->writepb_handler().set(FUNC(a2bus_ayboard_device::via1_out_b));
m_via1->irq_handler().set(FUNC(a2bus_ayboard_device::via1_irq_w));
- VIA6522(config, m_via2, 1022727);
- 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, "speaker", 2).front();
- SPEAKER(config, "lspeaker").front_left();
- SPEAKER(config, "rspeaker").front_right();
AY8913(config, m_ay1, 1022727);
- m_ay1->add_route(ALL_OUTPUTS, "lspeaker", 1.0);
+ m_ay1->add_route(ALL_OUTPUTS, "speaker", 0.5, 0);
+
+ AY8913(config, m_ay2, 1022727);
+ m_ay2->add_route(ALL_OUTPUTS, "speaker", 0.5, 1);
}
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", 1.0);
+ 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)
+{
+ 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));
+
+ VOTRAX_SC01A(config, m_sc01, 1022727);
+ m_sc01->ar_callback().set(m_via1, FUNC(via6522_device::write_cb1));
+ m_sc01->add_route(ALL_OUTPUTS, "speaker", 1.0, 0);
+ m_sc01->add_route(ALL_OUTPUTS, "speaker", 1.0, 1);
}
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);
+ SPEAKER(config, "speaker2", 2).front();
+
+ m_ay2->reset_routes().add_route(ALL_OUTPUTS, "speaker2", 0.5, 0);
+
AY8913(config, m_ay3, 1022727);
+ m_ay3->add_route(ALL_OUTPUTS, "speaker", 0.5, 1);
+
AY8913(config, m_ay4, 1022727);
- m_ay2->add_route(ALL_OUTPUTS, "lspeaker2", 1.0);
- m_ay3->add_route(ALL_OUTPUTS, "rspeaker", 1.0);
- m_ay4->add_route(ALL_OUTPUTS, "rspeaker2", 1.0);
+ m_ay4->add_route(ALL_OUTPUTS, "speaker2", 0.5, 1);
}
void a2bus_echoplus_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", 1.0);
+ 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);
}
@@ -101,31 +224,32 @@ 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)
{
}
a2bus_mockingboard_device::a2bus_mockingboard_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) :
- a2bus_ayboard_device(mconfig, A2BUS_MOCKINGBOARD, tag, owner, clock)
+ a2bus_ayboard_device(mconfig, A2BUS_MOCKINGBOARD, tag, owner, clock),
+ m_sc01(*this, "sc01")
{
}
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")
{
}
@@ -148,33 +272,49 @@ void a2bus_ayboard_device::device_reset()
read_cnxx - called for reads from this card's cnxx space
-------------------------------------------------*/
-uint8_t a2bus_ayboard_device::read_cnxx(uint8_t offset)
+u8 a2bus_ayboard_device::read_cnxx(u8 offset)
{
- if (offset <= 0x10)
+ if (offset <= 0x7f)
+ {
return m_via1->read(offset & 0xf);
- else if (offset >= 0x80 && offset <= 0x90)
+ }
+ else
+ {
return m_via2->read(offset & 0xf);
+ }
return 0;
}
-uint8_t a2bus_phasor_device::read_cnxx(uint8_t offset)
+u8 a2bus_echoplus_device::read_cnxx(u8 offset)
{
- uint8_t ret = 0;
+ return m_via1->read(offset & 0xf);
+}
+
+u8 a2bus_phasor_device::read_cnxx(u8 offset)
+{
+ u8 ret = 0;
int via_sel;
if (m_native)
+ {
via_sel = ((offset & 0x80) >> 6) | ((offset & 0x10) >> 4);
+ }
else
+ {
via_sel = (offset & 0x80) ? 2 : 1;
+ }
- if ((offset <= 0x20) || (offset >= 0x80 && offset <= 0xa0))
+ if ((offset < 0x20) || (offset >= 0x80 && offset < 0xa0))
{
if (BIT(via_sel, 0))
+ {
ret |= m_via1->read(offset & 0xf);
-
+ }
if (BIT(via_sel, 1))
+ {
ret |= m_via2->read(offset & 0xf);
+ }
}
return ret;
@@ -184,57 +324,103 @@ uint8_t a2bus_phasor_device::read_cnxx(uint8_t offset)
write_cnxx - called for writes to this card's c0nx space
-------------------------------------------------*/
-void a2bus_ayboard_device::write_cnxx(uint8_t offset, uint8_t data)
+void a2bus_ayboard_device::write_cnxx(u8 offset, u8 data)
{
- if (offset <= 0x10)
+ // When the SSI-263 is emulated, Cn40 will write to both the VIA and
+ // the first SSI-263, and Cn20 will write to both the VIA and the
+ // second SSI-263. Reads only select the VIA.
+ if (offset <= 0x7f)
+ {
m_via1->write(offset & 0xf, data);
- else if (offset >= 0x80 && offset <= 0x90)
- m_via2->write(offset & 0xf, data);
+ }
else
- logerror("Mockingboard(%d): unk write %02x to Cn%02X (%s)\n", slotno(), data, offset, machine().describe_context());
+ {
+ m_via2->write(offset & 0xf, data);
+ }
+}
+
+void a2bus_echoplus_device::write_cnxx(u8 offset, u8 data)
+{
+ m_via1->write(offset & 0xf, data);
}
-void a2bus_phasor_device::write_cnxx(uint8_t offset, uint8_t data)
+void a2bus_phasor_device::write_cnxx(u8 offset, u8 data)
{
- if ((offset <= 0x20) || (offset >= 0x80 && offset <= 0xa0))
+ if ((offset < 0x20) || (offset >= 0x80 && offset < 0xa0))
{
int via_sel;
if (m_native)
+ {
via_sel = ((offset & 0x80) >> 6) | ((offset & 0x10) >> 4);
+ }
else
+ {
via_sel = (offset & 0x80) ? 2 : 1;
+ }
if (BIT(via_sel, 0))
+ {
m_via1->write(offset & 0xf, data);
-
+ }
if (BIT(via_sel, 1))
+ {
m_via2->write(offset & 0xf, 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)
+ {
raise_slot_irq();
+ }
else
+ {
lower_slot_irq();
+ }
}
-WRITE_LINE_MEMBER( a2bus_ayboard_device::via2_irq_w )
+void a2bus_ayboard_device::via2_irq_w(int state)
{
if (state)
+ {
raise_slot_irq();
+ }
else
+ {
lower_slot_irq();
+ }
}
-WRITE8_MEMBER( a2bus_ayboard_device::via1_out_a )
+void a2bus_ayboard_device::via1_out_a(u8 data)
{
m_porta1 = data;
}
-WRITE8_MEMBER( a2bus_ayboard_device::via1_out_b )
+void a2bus_ayboard_device::via1_out_b(u8 data)
{
if (!BIT(data, 2))
{
@@ -242,27 +428,32 @@ WRITE8_MEMBER( a2bus_ayboard_device::via1_out_b )
}
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;
+ via_psg_ctrl(*m_ay1, m_porta1, data);
+ }
+}
- case 3: // BDIR=1, BC1=1 (latch)
- m_ay1->address_w(m_porta1);
- break;
+void a2bus_echoplus_device::via1_out_b(u8 data)
+{
+ if (!BIT(data, 2))
+ {
+ m_ay1->reset_w();
+ m_ay2->reset_w();
+ }
+ else
+ {
+ // TODO: reading with both PSGs selected should fight for the latch
+ if (BIT(data, 3)) // BC2_1=1 (PSG1 active)
+ {
+ via_psg_ctrl(*m_ay1, m_porta1, data);
+ }
+ if (BIT(data, 4)) // BC2_2_=1 (PSG2 active)
+ {
+ via_psg_ctrl(*m_ay2, m_porta1, data);
}
}
}
-WRITE8_MEMBER( a2bus_phasor_device::via1_out_b )
+void a2bus_phasor_device::via1_out_b(u8 data)
{
if (!(data & 4))
{
@@ -282,41 +473,20 @@ WRITE8_MEMBER( a2bus_phasor_device::via1_out_b )
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);
}
}
-WRITE8_MEMBER( a2bus_ayboard_device::via2_out_a )
+void a2bus_ayboard_device::via2_out_a(u8 data)
{
m_porta2 = data;
}
-WRITE8_MEMBER( a2bus_ayboard_device::via2_out_b )
+void a2bus_ayboard_device::via2_out_b(u8 data)
{
if (!BIT(data, 2))
{
@@ -324,27 +494,11 @@ WRITE8_MEMBER( a2bus_ayboard_device::via2_out_b )
}
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->data_w(m_porta2);
- break;
- }
+ via_psg_ctrl(*m_ay2, m_porta2, data);
}
}
-WRITE8_MEMBER( a2bus_phasor_device::via2_out_b )
+void a2bus_phasor_device::via2_out_b(u8 data)
{
if (!BIT(data, 2))
{
@@ -368,48 +522,46 @@ WRITE8_MEMBER( a2bus_phasor_device::via2_out_b )
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);
}
}
+void a2bus_phasor_device::set_clocks()
+{
+ if (m_native)
+ {
+ m_ay1->set_clock(1022727*2);
+ m_ay2->set_clock(1022727*2);
+ m_ay3->set_clock(1022727*2);
+ m_ay4->set_clock(1022727*2);
+ }
+ else
+ {
+ m_ay1->set_clock(1022727);
+ m_ay2->set_clock(1022727);
+ m_ay3->set_clock(1022727);
+ m_ay4->set_clock(1022727);
+ }
+}
-uint8_t a2bus_phasor_device::read_c0nx(uint8_t offset)
+u8 a2bus_phasor_device::read_c0nx(u8 offset)
{
m_native = BIT(offset, 0);
+ set_clocks();
return 0xff;
}
-void a2bus_phasor_device::write_c0nx(uint8_t offset, uint8_t data)
+void a2bus_phasor_device::write_c0nx(u8 offset, u8 data)
{
m_native = BIT(offset, 0);
+ set_clocks();
}
-uint8_t a2bus_echoplus_device::read_c0nx(uint8_t offset)
+u8 a2bus_echoplus_device::read_c0nx(u8 offset)
{
switch (offset)
{
@@ -420,7 +572,7 @@ uint8_t a2bus_echoplus_device::read_c0nx(uint8_t offset)
return 0;
}
-void a2bus_echoplus_device::write_c0nx(uint8_t offset, uint8_t data)
+void a2bus_echoplus_device::write_c0nx(u8 offset, u8 data)
{
switch (offset)
{
@@ -429,3 +581,44 @@ void a2bus_echoplus_device::write_c0nx(uint8_t offset, uint8_t data)
break;
}
}
+
+void a2bus_mockingboard_device::device_reset()
+{
+ m_porta1 = m_porta2 = m_portb1 = 0;
+ m_last_cb2_state = ASSERT_LINE;
+}
+
+void a2bus_mockingboard_device::write_via1_cb2(int state)
+{
+ if ((state == CLEAR_LINE) && (m_last_cb2_state == ASSERT_LINE))
+ {
+ m_sc01->write(m_portb1);
+ m_sc01->inflection_w(m_portb1 >> 6);
+ }
+ m_last_cb2_state = state;
+}
+
+void a2bus_mockingboard_device::via1_out_b(u8 data)
+{
+ m_portb1 = data;
+
+ if (!BIT(data, 2))
+ {
+ m_ay1->reset_w();
+ }
+ else
+ {
+ via_psg_ctrl(*m_ay1, m_porta1, data);
+ }
+}
+
+} // anonymous namespace
+
+
+//**************************************************************************
+// GLOBAL VARIABLES
+//**************************************************************************
+
+DEFINE_DEVICE_TYPE_PRIVATE(A2BUS_MOCKINGBOARD, device_a2bus_card_interface, a2bus_mockingboard_device, "a2mockbd", "Sweet Micro Systems Mockingboard Sound/Speech I")
+DEFINE_DEVICE_TYPE_PRIVATE(A2BUS_PHASOR, device_a2bus_card_interface, a2bus_phasor_device, "a2phasor", "Applied Engineering Phasor")
+DEFINE_DEVICE_TYPE_PRIVATE(A2BUS_ECHOPLUS, device_a2bus_card_interface, a2bus_echoplus_device, "a2echop", "Street Electronics Echo Plus")
diff --git a/src/devices/bus/a2bus/a2mockingboard.h b/src/devices/bus/a2bus/a2mockingboard.h
index b7d6b7f3b97..1b05a9b36fe 100644
--- a/src/devices/bus/a2bus/a2mockingboard.h
+++ b/src/devices/bus/a2bus/a2mockingboard.h
@@ -12,97 +12,10 @@
#define MAME_BUS_A2BUS_A2MOCKINGBOARD_H
#include "a2bus.h"
-#include "machine/6522via.h"
-#include "sound/ay8910.h"
-#include "sound/tms5220.h"
-
-//**************************************************************************
-// TYPE DEFINITIONS
-//**************************************************************************
-
-class a2bus_ayboard_device:
- public device_t,
- public device_a2bus_card_interface
-{
-public:
- DECLARE_WRITE_LINE_MEMBER( via1_irq_w );
- DECLARE_WRITE_LINE_MEMBER( via2_irq_w );
- DECLARE_WRITE8_MEMBER(via1_out_a);
- virtual DECLARE_WRITE8_MEMBER(via1_out_b);
- DECLARE_WRITE8_MEMBER(via2_out_a);
- virtual DECLARE_WRITE8_MEMBER(via2_out_b);
-
-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
- virtual uint8_t read_c0nx(uint8_t offset) override { return 0xff; }
- virtual void write_c0nx(uint8_t offset, uint8_t data) override { }
- virtual uint8_t read_cnxx(uint8_t offset) override;
- virtual void write_cnxx(uint8_t offset, uint8_t data) override;
-
- void add_common_devices(machine_config &config);
-
- required_device<via6522_device> m_via1;
- required_device<via6522_device> m_via2;
- required_device<ay8913_device> m_ay1;
- required_device<ay8913_device> m_ay2;
-
- uint8_t m_porta1;
- uint8_t m_porta2;
-};
-
-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);
-};
-
-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);
-
- DECLARE_WRITE8_MEMBER(via1_out_b) override;
- DECLARE_WRITE8_MEMBER(via2_out_b) override;
-
-protected:
- virtual void device_add_mconfig(machine_config &config) override;
-
- 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 void write_cnxx(uint8_t offset, uint8_t data) override;
-
- required_device<ay8913_device> m_ay3;
- required_device<ay8913_device> m_ay4;
-
-private:
- bool m_native;
-};
-
-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);
-
-protected:
- virtual void device_add_mconfig(machine_config &config) override;
-
- virtual uint8_t read_c0nx(uint8_t offset) override;
- virtual void write_c0nx(uint8_t offset, uint8_t data) override;
-
- required_device<tms5220_device> m_tms;
-};
// device type definition
-DECLARE_DEVICE_TYPE(A2BUS_MOCKINGBOARD, a2bus_mockingboard_device)
-DECLARE_DEVICE_TYPE(A2BUS_PHASOR, a2bus_phasor_device)
-DECLARE_DEVICE_TYPE(A2BUS_ECHOPLUS, a2bus_echoplus_device)
+DECLARE_DEVICE_TYPE(A2BUS_MOCKINGBOARD, device_a2bus_card_interface)
+DECLARE_DEVICE_TYPE(A2BUS_PHASOR, device_a2bus_card_interface)
+DECLARE_DEVICE_TYPE(A2BUS_ECHOPLUS, device_a2bus_card_interface)
#endif // MAME_BUS_A2BUS_A2MOCKINGBOARD_H
diff --git a/src/devices/bus/a2bus/a2parprn.cpp b/src/devices/bus/a2bus/a2parprn.cpp
new file mode 100644
index 00000000000..2377ea437e5
--- /dev/null
+++ b/src/devices/bus/a2bus/a2parprn.cpp
@@ -0,0 +1,325 @@
+// license:BSD-3-Clause
+// copyright-holders:Vas Crabb
+#include "emu.h"
+#include "a2parprn.h"
+
+#include "bus/centronics/ctronics.h"
+
+//#define VERBOSE 1
+//#define LOG_OUTPUT_FUNC osd_printf_info
+#include "logmacro.h"
+
+namespace {
+
+class a2bus_parprn_device : public device_t, public device_a2bus_card_interface
+{
+public:
+ a2bus_parprn_device(machine_config const &mconfig, char const *tag, device_t *owner, u32 clock);
+
+ // 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 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 ATTR_COLD;
+ virtual void device_add_mconfig(machine_config &config) override ATTR_COLD;
+ virtual ioport_constructor device_input_ports() const override ATTR_COLD;
+ virtual void device_start() override ATTR_COLD;
+ virtual void device_reset() override ATTR_COLD;
+
+private:
+ // printer status inputs
+ void ack_w(int state);
+
+ // timer handlers
+ TIMER_CALLBACK_MEMBER(update_strobe);
+
+ 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
+ u8 m_ack_latch; // B2 pin 6
+ u8 m_ack_in; // pin 2
+};
+
+
+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 ATTR_COLD;
+ virtual void device_start() override ATTR_COLD;
+};
+
+
+
+// FIXME: get proper PROM dumps.
+/*
+ There are most likely multiple revisions.
+ 6309 and 74471 PROMs were used.
+
+ Example silkscreen:
+
+ SINGAPORE
+ 341-0005-00
+ cAPPLE 78-02
+ SN74S471N
+
+ Example label:
+
+ APPLE
+ ©1978
+
+ PROM image here is from entering a listing and zero-filling unused areas.
+
+ ********************************
+ * *
+ * PRINTER CARD I FIRMWARE *
+ * *
+ * WOZ 11/1/77 *
+ * APPLE COMPUTER INC. *
+ * ALL RIGHTS RESERVED *
+ * *
+ ********************************
+*/
+ROM_START(parprn)
+ ROM_REGION(0x100, "prom", 0)
+ 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")
+ PORT_CONFNAME(0x01, 0x00, "Acknowledge latching edge")
+ PORT_CONFSETTING( 0x00, "Falling (/Y-B)")
+ PORT_CONFSETTING( 0x01, "Rising (Y-B)")
+ PORT_CONFNAME(0x06, 0x02, "Printer ready")
+ PORT_CONFSETTING( 0x00, "Always (S5-C-D)")
+ PORT_CONFSETTING( 0x02, "Acknowledge latch (Z-C-D)")
+ PORT_CONFSETTING( 0x04, "ACK (Y-C-D)")
+ PORT_CONFSETTING( 0x06, "/ACK (/Y-C-D)")
+ PORT_CONFNAME(0x08, 0x00, "Strobe polarity")
+ PORT_CONFSETTING( 0x00, "Negative (S5-A-/X, GND-X)")
+ PORT_CONFSETTING( 0x08, "Positive (S5-X, GND-A-/X)")
+ PORT_CONFNAME(0x10, 0x10, "Character width")
+ PORT_CONFSETTING( 0x00, "7-bit")
+ PORT_CONFSETTING( 0x10, "8-bit")
+INPUT_PORTS_END
+
+
+
+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"),
+ m_input_config(*this, "CFG"),
+ m_prom(*this, "prom"),
+ m_strobe_timer(nullptr),
+ m_next_strobe(0U),
+ m_ack_latch(0U),
+ m_ack_in(1U)
+{
+}
+
+
+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
+//----------------------------------------------
+
+u8 a2bus_parprn_device::read_c0nx(u8 offset)
+{
+ if (!machine().side_effects_disabled())
+ {
+ LOG("Read C0n%01X (effective open-bus write)\n", offset);
+
+ // R/W is ignored, so it has the same effect as a write
+ // the bus is open, but 74LS logic has low-impedance inputs so it's likely to latch 0xff
+ write_c0nx(offset, 0xffU);
+ }
+
+ return 0x00U;
+}
+
+
+void a2bus_parprn_device::write_c0nx(u8 offset, u8 data)
+{
+ LOG("Write C0n%01X=%02X\n", offset, data);
+ if (m_ack_latch)
+ LOG("Clearing acknowledge latch\n");
+ else
+ LOG("Previous data not acknowledged\n");
+
+ ioport_value const cfg(m_input_config->read());
+
+ 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;
+ m_strobe_timer->adjust(attotime::from_ticks(1, clock()));
+}
+
+
+u8 a2bus_parprn_device::read_cnxx(u8 offset)
+{
+ ioport_value const cfg(m_input_config->read());
+
+ if (BIT(cfg, 2))
+ {
+ if (!BIT(offset, 6) || (BIT(offset, 7) && (BIT(cfg, 1) != m_ack_in)))
+ offset |= 0x40U;
+ else
+ offset &= 0xbfU;
+ }
+ else if (BIT(cfg, 1))
+ {
+ if (!BIT(offset, 6) || (BIT(offset, 7) && !m_ack_latch))
+ offset |= 0x40U;
+ else
+ offset &= 0xbfU;
+ }
+ else
+ {
+ offset ^= 0x40U;
+ }
+
+ return m_prom[offset];
+}
+
+
+
+//----------------------------------------------
+// device_t implementation
+//----------------------------------------------
+
+tiny_rom_entry const *a2bus_parprn_device::device_rom_region() const
+{
+ return ROM_NAME(parprn);
+}
+
+
+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");
+ m_printer_conn->ack_handler().set(FUNC(a2bus_parprn_device::ack_w));
+
+ OUTPUT_LATCH(config, m_printer_out);
+ m_printer_conn->set_output_latch(*m_printer_out);
+}
+
+
+ioport_constructor a2bus_parprn_device::device_input_ports() const
+{
+ return INPUT_PORTS_NAME(parprn);
+}
+
+
+void a2bus_parprn_device::device_start()
+{
+ m_strobe_timer = timer_alloc(FUNC(a2bus_parprn_device::update_strobe), this);
+
+ save_item(NAME(m_next_strobe));
+ save_item(NAME(m_ack_latch));
+ save_item(NAME(m_ack_in));
+}
+
+
+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;
+}
+
+
+
+//----------------------------------------------
+// printer status inputs
+//----------------------------------------------
+
+void a2bus_parprn_device::ack_w(int state)
+{
+ if (bool(state) != bool(m_ack_in))
+ {
+ m_ack_in = state ? 1U : 0U;
+ LOG("ACK=%u\n", m_ack_in);
+ if (started() && (m_ack_in == BIT(m_input_config->read(), 0)))
+ {
+ LOG("Active ACK edge\n");
+ m_ack_latch = 1U;
+ }
+ }
+}
+
+
+
+//----------------------------------------------
+// timer handlers
+//----------------------------------------------
+
+TIMER_CALLBACK_MEMBER(a2bus_parprn_device::update_strobe)
+{
+ ioport_value const cfg(m_input_config->read());
+
+ LOG("Output /STROBE=%u\n", m_next_strobe);
+ m_printer_conn->write_strobe(m_next_strobe);
+ if (m_next_strobe == BIT(cfg, 3))
+ {
+ LOG("Start strobe timer\n");
+ m_next_strobe = BIT(~cfg, 3);
+ m_strobe_timer->adjust(attotime::from_ticks(1, clock()));
+ }
+}
+
+} // anonymous namespace
+
+
+
+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
new file mode 100644
index 00000000000..66681a3c395
--- /dev/null
+++ b/src/devices/bus/a2bus/a2parprn.h
@@ -0,0 +1,64 @@
+// license:BSD-3-Clause
+// copyright-holders:Vas Crabb
+/***********************************************************************
+
+ Apple II Parallel Printer Interface Card
+
+ 20-pin header:
+
+ GND 1 2 ACK
+ SP1* 3 4 F
+ SP2* 5 6 SP3*
+ SP4* 7 8 STR
+ SP5* 9 10 DP0
+ DP1 11 12 DP2
+ DP3 13 14 DP4
+ DP5 15 16 DP6
+ DP7 17 18 SP6*
+ SP7* 19 20 GND
+
+ *spare, SP1-SP5 brought out to pads for wire mods
+
+ DIP jumper B1:
+
+ no connection NC 1 16 B acknowledge latch clock
+ no connection NC 2 15 D printer ready 1
+ synchronised ACK Y 3 14 C printer ready 2
+ synchronised /ACK /Y 4 13 A idle strobe
+ acknowledge latch Q /Z 5 12 /X strobe on access
+ acknowlwdge latch /Q Z 6 11 S5 +5V via 12kΩ resistor
+ signal ground GND 7 10 X strobe after one cycle
+ header pin 4 F 8 9 NC no connection
+
+ In real life, the card only samples the ACK input on rising
+ edges of the phase 1 clock. Acknowledge pulses shorter than one
+ microsecond may be ignored. This limitation is not emulated.
+
+ The card completely ignores the R/W line. The PROM driver uses
+ an indexed write to access the C0nX region. This produces a
+ spurious read, causing data to be latched and triggering a
+ delayed strobe pulse. This is why the delay is important – the
+ write needs to happen on the cycle immediately following the
+ spurious read to prevent the open bus data from being printed.
+
+ The card was designed to allow user modifications. There are
+ locations at 5A (16-pin) and 5B (20-pin) for additional DIP
+ 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
+
+#pragma once
+
+#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 21c749eb50c..bd57b32413c 100644
--- a/src/devices/bus/a2bus/a2pic.cpp
+++ b/src/devices/bus/a2bus/a2pic.cpp
@@ -1,292 +1,604 @@
// license:BSD-3-Clause
-// copyright-holders:R. Belmont
-/*********************************************************************
+// copyright-holders:Vas Crabb
+#include "emu.h"
+#include "a2pic.h"
- a2pic.c
+#include "bus/centronics/ctronics.h"
- Apple II Parallel Interface Card (670-0021)
+//#define VERBOSE 1
+//#define LOG_OUTPUT_FUNC osd_printf_info
+#include "logmacro.h"
-*********************************************************************/
+namespace {
-#include "emu.h"
-#include "a2pic.h"
+class a2bus_pic_device : public device_t, public device_a2bus_card_interface
+{
+public:
+ a2bus_pic_device(machine_config const &mconfig, char const *tag, device_t *owner, u32 clock);
+
+ // DIP switch/jumper handlers
+ DECLARE_INPUT_CHANGED_MEMBER(sw1_strobe);
+ DECLARE_INPUT_CHANGED_MEMBER(sw1_ack);
+ DECLARE_INPUT_CHANGED_MEMBER(sw1_firmware);
+ DECLARE_INPUT_CHANGED_MEMBER(sw1_irq);
+ DECLARE_INPUT_CHANGED_MEMBER(x_data_out);
+ DECLARE_INPUT_CHANGED_MEMBER(x_char_width);
+
+ // 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;
+
+protected:
+ // device_t implementation
+ virtual tiny_rom_entry const *device_rom_region() const override ATTR_COLD;
+ virtual void device_add_mconfig(machine_config &config) override ATTR_COLD;
+ virtual ioport_constructor device_input_ports() const override ATTR_COLD;
+ virtual void device_start() override ATTR_COLD;
+ virtual void device_reset() override ATTR_COLD;
+
+private:
+ // printer status inputs
+ 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);
+
+ // synchronised inputs
+ void set_ack_in(s32 param);
+ void set_perror_in(s32 param);
+ void set_select_in(s32 param);
+ void set_fault_in(s32 param);
+ void data_write(s32 param);
+
+ // helpers
+ void reset_mode();
+ void set_ack_latch();
+ void clear_ack_latch();
+ void enable_irq();
+ void disable_irq();
+
+ required_device<centronics_device> m_printer_conn;
+ required_device<output_latch_device> m_printer_out;
+ required_ioport m_input_sw1;
+ required_ioport m_input_x;
+ required_region_ptr<u8> m_prom;
+ emu_timer * m_strobe_timer;
+
+ u16 m_firmware_base; // controlled by SW6
+ u8 m_data_latch; // 9B
+ u8 m_autostrobe_disable; // 2A pin 8
+ u8 m_ack_latch; // 2A pin 6
+ u8 m_irq_enable; // 2B pin 9
+ u8 m_ack_in;
+ u8 m_perror_in; // DI5
+ u8 m_select_in; // DI6
+ u8 m_fault_in; // DI3
+};
+
+
+
+ROM_START(pic)
+ ROM_REGION(0x0200, "prom", 0)
+ ROM_LOAD( "341-0057.7b", 0x0000, 0x0200, CRC(0a6b084b) SHA1(de8aa285dcac88b1cc80ec9128b092833f5174b6) )
+ROM_END
-/***************************************************************************
- PARAMETERS
-***************************************************************************/
-//**************************************************************************
-// GLOBAL VARIABLES
-//**************************************************************************
+INPUT_PORTS_START(pic)
+ PORT_START("SW1")
+ PORT_DIPNAME(0x07, 0x07, "Strobe Length") PORT_DIPLOCATION("SW1:1,2,3")
+ PORT_DIPSETTING( 0x07, "1 microsecond")
+ PORT_DIPSETTING( 0x06, "3 microseconds")
+ PORT_DIPSETTING( 0x05, "5 microseconds")
+ PORT_DIPSETTING( 0x04, "7 microseconds")
+ PORT_DIPSETTING( 0x03, "9 microseconds")
+ PORT_DIPSETTING( 0x02, "11 microseconds")
+ PORT_DIPSETTING( 0x01, "13 microseconds")
+ PORT_DIPSETTING( 0x00, "15 microseconds")
+ PORT_DIPNAME(0x08, 0x00, "Strobe Output Polarity") PORT_DIPLOCATION("SW1:4") PORT_CHANGED_MEMBER(DEVICE_SELF, FUNC(a2bus_pic_device::sw1_strobe), 0)
+ PORT_DIPSETTING( 0x08, "Positive")
+ PORT_DIPSETTING( 0x00, "Negative")
+ PORT_DIPNAME(0x10, 0x00, "Acknowledge Input Polarity") PORT_DIPLOCATION("SW1:5") PORT_CHANGED_MEMBER(DEVICE_SELF, FUNC(a2bus_pic_device::sw1_ack), 0)
+ PORT_DIPSETTING( 0x10, "Positive")
+ PORT_DIPSETTING( 0x00, "Negative")
+ PORT_DIPNAME(0x20, 0x20, "Firmware") PORT_DIPLOCATION("SW1:6") PORT_CHANGED_MEMBER(DEVICE_SELF, FUNC(a2bus_pic_device::sw1_firmware), 0)
+ PORT_DIPSETTING( 0x20, "Parallel Printer") // ROM #341-0005 - auto LF after CR
+ PORT_DIPSETTING( 0x00, "Centronics") // ROM #341-0019 - no auto LF after CR
+ PORT_DIPNAME(0x40, 0x40, "Interrupt") PORT_DIPLOCATION("SW1:7") PORT_CHANGED_MEMBER(DEVICE_SELF, FUNC(a2bus_pic_device::sw1_irq), 0)
+ PORT_DIPSETTING( 0x40, "Disabled")
+ PORT_DIPSETTING( 0x00, "Enabled")
+
+ PORT_START("X")
+ PORT_CONFNAME(0x01, 0x01, "PROM Addressing")
+ PORT_CONFSETTING( 0x00, "Flat (X1)")
+ PORT_CONFSETTING( 0x01, "Standard (X2)")
+ PORT_CONFNAME(0x02, 0x02, "Data Output") PORT_CHANGED_MEMBER(DEVICE_SELF, FUNC(a2bus_pic_device::x_data_out), 0)
+ PORT_CONFSETTING( 0x00, "Disabled (X3)")
+ PORT_CONFSETTING( 0x02, "Enabled (X4)")
+ PORT_CONFNAME(0x04, 0x04, "Character Width") PORT_CHANGED_MEMBER(DEVICE_SELF, FUNC(a2bus_pic_device::x_char_width), 0)
+ PORT_CONFSETTING( 0x00, "7-bit (X5)")
+ PORT_CONFSETTING( 0x04, "8-bit (X6)")
+INPUT_PORTS_END
-DEFINE_DEVICE_TYPE(A2BUS_PIC, a2bus_pic_device, "a2pic", "Apple Parallel Interface Card")
-#define PIC_ROM_REGION "pic_rom"
-#define PIC_CENTRONICS_TAG "pic_ctx"
-ROM_START( pic )
- ROM_REGION(0x000200, PIC_ROM_REGION, 0)
- ROM_LOAD( "341-0057.bin", 0x000000, 0x000200, CRC(0d2d84ee) SHA1(bfc5b863d37e59875a6159528eb0f2b6082063b5) )
-ROM_END
+a2bus_pic_device::a2bus_pic_device(machine_config const &mconfig, char const *tag, device_t *owner, u32 clock) :
+ device_t(mconfig, A2BUS_PIC, tag, owner, clock),
+ device_a2bus_card_interface(mconfig, *this),
+ m_printer_conn(*this, "prn"),
+ m_printer_out(*this, "prn_out"),
+ m_input_sw1(*this, "SW1"),
+ m_input_x(*this, "X"),
+ m_prom(*this, "prom"),
+ m_strobe_timer(nullptr),
+ m_firmware_base(0x0000U),
+ m_data_latch(0x00U),
+ m_autostrobe_disable(0U),
+ m_ack_latch(0U),
+ m_irq_enable(0U),
+ m_ack_in(1U),
+ m_perror_in(1U),
+ m_select_in(1U),
+ m_fault_in(1U)
+{
+}
-static INPUT_PORTS_START( pic )
- PORT_START("DSW1")
- PORT_DIPNAME( 0x07, 0x00, "Strobe length (SW1-3)" )
- PORT_DIPSETTING( 0x00, "1 microsecond" )
- PORT_DIPSETTING( 0x01, "3 microseconds" )
- PORT_DIPSETTING( 0x02, "5 microseconds" )
- PORT_DIPSETTING( 0x03, "7 microseconds" )
- PORT_DIPSETTING( 0x04, "9 microseconds" )
- PORT_DIPSETTING( 0x05, "11 microseconds" )
- PORT_DIPSETTING( 0x06, "13 microseconds" )
- PORT_DIPSETTING( 0x07, "15 microseconds" )
-
- PORT_DIPNAME( 0x08, 0x08, "Strobe polarity (SW4)" )
- PORT_DIPSETTING( 0x00, "Positive" )
- PORT_DIPSETTING( 0x08, "Negative" )
-
- PORT_DIPNAME( 0x10, 0x10, "Acknowledge polarity (SW5)" )
- PORT_DIPSETTING( 0x00, "Positive" )
- PORT_DIPSETTING( 0x10, "Negative" )
-
- PORT_DIPNAME( 0x20, 0x20, "Firmware (SW6)" )
- PORT_DIPSETTING( 0x00, "Parallel Printer (341-0005)" )
- PORT_DIPSETTING( 0x20, "Centronics (341-0019)" )
-
- PORT_DIPNAME( 0x40, 0x00, "Use interrupts (SW7)" )
- PORT_DIPSETTING( 0x00, "Off" )
- PORT_DIPSETTING( 0x40, "On" )
-INPUT_PORTS_END
-//-------------------------------------------------
-// input_ports - device-specific input ports
-//-------------------------------------------------
-ioport_constructor a2bus_pic_device::device_input_ports() const
+//----------------------------------------------
+// DIP switch/jumper handlers
+//----------------------------------------------
+
+INPUT_CHANGED_MEMBER(a2bus_pic_device::sw1_strobe)
{
- return INPUT_PORTS_NAME( pic );
+ m_printer_conn->write_strobe(BIT(m_input_sw1->read(), 3) ^ (m_strobe_timer->enabled() ? 0U : 1U));
}
-//-------------------------------------------------
-// device_add_mconfig - add device configuration
-//-------------------------------------------------
-void a2bus_pic_device::device_add_mconfig(machine_config &config)
+INPUT_CHANGED_MEMBER(a2bus_pic_device::sw1_ack)
{
- CENTRONICS(config, m_ctx, centronics_devices, "printer");
- m_ctx->set_data_input_buffer(m_ctx_data_in);
- m_ctx->ack_handler().set(FUNC(a2bus_pic_device::ack_w));
+ if (m_ack_in != BIT(m_input_sw1->read(), 4))
+ set_ack_latch();
+}
- INPUT_BUFFER(config, m_ctx_data_in);
- OUTPUT_LATCH(config, m_ctx_data_out);
- m_ctx->set_output_latch(*m_ctx_data_out);
+
+INPUT_CHANGED_MEMBER(a2bus_pic_device::sw1_firmware)
+{
+ m_firmware_base = BIT(m_input_sw1->read(), 5) << 8;
}
-//-------------------------------------------------
-// rom_region - device-specific ROM region
-//-------------------------------------------------
-const tiny_rom_entry *a2bus_pic_device::device_rom_region() const
+INPUT_CHANGED_MEMBER(a2bus_pic_device::sw1_irq)
{
- return ROM_NAME( pic );
+ if (m_ack_latch && m_irq_enable)
+ {
+ if (BIT(m_input_sw1->read(), 6))
+ lower_slot_irq();
+ else
+ raise_slot_irq();
+ }
}
-//**************************************************************************
-// LIVE DEVICE
-//**************************************************************************
-a2bus_pic_device::a2bus_pic_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) :
- a2bus_pic_device(mconfig, A2BUS_PIC, tag, owner, clock)
+INPUT_CHANGED_MEMBER(a2bus_pic_device::x_data_out)
{
+ if (m_data_latch && !BIT(m_input_x->read(), 1))
+ {
+ m_data_latch = 0x00U;
+ m_printer_out->write(0x00U);
+ }
}
-a2bus_pic_device::a2bus_pic_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_dsw1(*this, "DSW1"),
- m_ctx(*this, PIC_CENTRONICS_TAG),
- m_ctx_data_in(*this, "ctx_data_in"),
- m_ctx_data_out(*this, "ctx_data_out"), m_rom(nullptr),
- m_started(false), m_ack(0), m_irqenable(false), m_autostrobe(false), m_timer(nullptr)
+
+INPUT_CHANGED_MEMBER(a2bus_pic_device::x_char_width)
{
+ if (BIT(m_data_latch, 7))
+ m_printer_out->write(m_data_latch & (BIT(m_input_x->read(), 2) ? 0xffU : 0x7fU));
}
-//-------------------------------------------------
-// device_start - device-specific startup
-//-------------------------------------------------
-void a2bus_pic_device::device_start()
+
+//----------------------------------------------
+// device_a2bus_card_interface implementation
+//----------------------------------------------
+
+u8 a2bus_pic_device::read_c0nx(u8 offset)
{
- m_rom = device().machine().root_device().memregion(this->subtag(PIC_ROM_REGION).c_str())->base();
+ if (!machine().side_effects_disabled())
+ LOG("Read C0n%01X\n", offset);
+
+ switch (offset & 0x07U)
+ {
+ case 3U:
+ return 0x97U | (m_perror_in << 5) | (m_select_in << 6) | (m_fault_in << 3);
- m_timer = timer_alloc(0, nullptr);
- m_timer->adjust(attotime::never);
+ case 4U:
+ return (m_ack_latch << 7) | (m_ack_in ^ BIT(m_input_sw1->read(), 4));
- save_item(NAME(m_ack));
- save_item(NAME(m_irqenable));
- save_item(NAME(m_autostrobe));
+ case 5U:
+ logerror("500ns negative strobe not implemented\n");
+ break;
+
+ case 6U:
+ if (!machine().side_effects_disabled())
+ enable_irq();
+ break;
+
+ case 7U:
+ if (!machine().side_effects_disabled())
+ reset_mode();
+ break;
+ }
+
+ return 0x00U;
}
-void a2bus_pic_device::device_reset()
+void a2bus_pic_device::write_c0nx(u8 offset, u8 data)
{
- m_started = true;
- m_ack = 0;
- m_irqenable = false;
- m_autostrobe = false;
- lower_slot_irq();
- m_timer->adjust(attotime::never);
+ LOG("Write C0n%01X=%02X\n", offset, data);
- // set initial state of the strobe line depending on the dipswitch
- clear_strobe();
+ switch (offset & 0x07U)
+ {
+ case 0U:
+ if (BIT(m_input_x->read(), 1))
+ {
+ // latch output data and start strobe if autostrobe is enabled
+ LOG("Latch data %02X\n", data);
+ machine().scheduler().synchronize(
+ timer_expired_delegate(FUNC(a2bus_pic_device::data_write), this),
+ unsigned(data) | (1 << 8) | ((m_autostrobe_disable ? 0 : 1) << 9));
+ }
+ else
+ {
+ // just start strobe if autostrobe is enabled
+ LOG("Output disabled, not latching data\n");
+ if (!m_autostrobe_disable)
+ machine().scheduler().synchronize(timer_expired_delegate(FUNC(a2bus_pic_device::data_write), this), 1 << 9);
+ }
+ break;
+
+ case 2U:
+ machine().scheduler().synchronize(timer_expired_delegate(FUNC(a2bus_pic_device::data_write), this), 1 << 9);
+ break;
+
+ case 5U:
+ logerror("500ns negative strobe not implemented\n");
+ break;
+
+ case 6U:
+ enable_irq();
+ break;
+
+ case 7U:
+ reset_mode();
+ break;
+ }
}
-void a2bus_pic_device::device_timer(emu_timer &timer, device_timer_id tid, int param, void *ptr)
+
+u8 a2bus_pic_device::read_cnxx(u8 offset)
{
- clear_strobe();
+ if (BIT(m_input_x->read(), 0))
+ {
+ if (!BIT(offset, 6) || (BIT(offset, 7) && !m_ack_latch))
+ offset |= 0x40U;
+ else
+ offset &= 0xbfU;
+ }
- m_timer->adjust(attotime::never);
+ if (!machine().side_effects_disabled())
+ {
+ if (m_autostrobe_disable)
+ LOG("Enabling autostrobe\n");
+ m_autostrobe_disable = 0U;
+ }
+
+ return m_prom[m_firmware_base | offset];
+}
+
+
+void a2bus_pic_device::write_cnxx(u8 offset, u8 data)
+{
+ LOG("Write Cn%02X=%02X (bus conflict)\n", offset, data);
+
+ if (m_autostrobe_disable)
+ LOG("Enabling autostrobe\n");
+ m_autostrobe_disable = 0U;
}
-/*-------------------------------------------------
- read_cnxx - called for reads from this card's cnxx space
--------------------------------------------------*/
-uint8_t a2bus_pic_device::read_cnxx(uint8_t offset)
+
+//----------------------------------------------
+// device_t implementation
+//----------------------------------------------
+
+tiny_rom_entry const *a2bus_pic_device::device_rom_region() const
{
- m_autostrobe = true;
+ return ROM_NAME(pic);
+}
+
+
+void a2bus_pic_device::device_add_mconfig(machine_config &config)
+{
+ CENTRONICS(config, m_printer_conn, centronics_devices, "printer");
+ m_printer_conn->ack_handler().set(FUNC(a2bus_pic_device::ack_w));
+ m_printer_conn->perror_handler().set(FUNC(a2bus_pic_device::perror_w));
+ m_printer_conn->select_handler().set(FUNC(a2bus_pic_device::select_w));
+ m_printer_conn->fault_handler().set(FUNC(a2bus_pic_device::fault_w));
+
+ OUTPUT_LATCH(config, m_printer_out);
+ m_printer_conn->set_output_latch(*m_printer_out);
+}
+
+
+ioport_constructor a2bus_pic_device::device_input_ports() const
+{
+ return INPUT_PORTS_NAME(pic);
+}
+
+
+void a2bus_pic_device::device_start()
+{
+ m_strobe_timer = timer_alloc(FUNC(a2bus_pic_device::release_strobe), this);
+
+ m_firmware_base = 0x0100U;
+ m_data_latch = 0xffU;
+
+ save_item(NAME(m_data_latch));
+ save_item(NAME(m_autostrobe_disable));
+ save_item(NAME(m_ack_latch));
+ save_item(NAME(m_irq_enable));
+ save_item(NAME(m_ack_in));
+ save_item(NAME(m_perror_in));
+ save_item(NAME(m_select_in));
+ save_item(NAME(m_fault_in));
+}
+
+
+void a2bus_pic_device::device_reset()
+{
+ ioport_value const sw1(m_input_sw1->read());
+ ioport_value const x(m_input_x->read());
+
+ m_firmware_base = BIT(sw1, 5) << 8;
+ m_autostrobe_disable = 1U;
- if (m_dsw1->read() & 0x20)
+ if (!BIT(x, 1))
{
- return m_rom[(offset&0xff) | 0x100];
+ m_data_latch = 0x00U;
+ m_printer_out->write(0x00U);
}
- return m_rom[(offset&0xff)];
+ m_printer_conn->write_strobe(BIT(sw1, 3) ^ (m_strobe_timer->enabled() ? 0U : 1U));
+
+ reset_mode();
+}
+
+
+
+//----------------------------------------------
+// printer status inputs
+//----------------------------------------------
+
+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);
+}
+
+
+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);
}
-/*-------------------------------------------------
- read_c0nx - called for reads from this card's c0nx space
--------------------------------------------------*/
-uint8_t a2bus_pic_device::read_c0nx(uint8_t offset)
+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);
+}
+
+
+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);
+}
+
+
+
+//----------------------------------------------
+// timer handlers
+//----------------------------------------------
+
+TIMER_CALLBACK_MEMBER(a2bus_pic_device::release_strobe)
{
- uint8_t rv = 0;
+ int const state(BIT(~m_input_sw1->read(), 3));
+ LOG("Output /STROBE=%d\n", state);
+ m_printer_conn->write_strobe(state);
+}
+
+
- switch (offset)
+//----------------------------------------------
+// synchronised inputs
+//----------------------------------------------
+
+void a2bus_pic_device::set_ack_in(s32 param)
+{
+ if (u32(param) != m_ack_in)
{
- case 3:
- return m_ctx_data_in->read();
-
- case 4:
- rv = m_ack;
-
- // clear flip-flop
- if (m_dsw1->read() & 0x10) // negative polarity
- {
- m_ack |= 0x80;
- }
- else
- {
- m_ack &= ~0x80;
- }
-
- return rv;
-
- case 6: // does reading this really work?
- m_irqenable = true;
- break;
-
- case 7:
- m_irqenable = false;
- m_autostrobe = false;
- lower_slot_irq();
- break;
+ m_ack_in = u8(u32(param));
+ LOG("/ACK=%u\n", m_ack_in);
+ if (started() && (m_ack_in != BIT(m_input_sw1->read(), 4)))
+ {
+ LOG("Active /ACK edge\n");
+ set_ack_latch();
+ }
+ }
+}
+
+void a2bus_pic_device::set_perror_in(s32 param)
+{
+ if (u32(param) != m_perror_in)
+ {
+ m_perror_in = u8(u32(param));
+ LOG("PAPER EMPTY=%u\n", m_perror_in);
}
+}
- return 0;
+
+void a2bus_pic_device::set_select_in(s32 param)
+{
+ if (u32(param) != m_select_in)
+ {
+ m_select_in = u8(u32(param));
+ LOG("SELECT=%u\n", m_select_in);
+ }
}
-/*-------------------------------------------------
- write_c0nx - called for writes to this card's c0nx space
--------------------------------------------------*/
-void a2bus_pic_device::write_c0nx(uint8_t offset, uint8_t data)
+void a2bus_pic_device::set_fault_in(s32 param)
{
- switch (offset)
+ if (u32(param) != m_fault_in)
{
- case 0: // set data out and send a strobe
- m_ctx_data_out->write(data);
-
- if (m_autostrobe)
- {
- start_strobe();
- }
- break;
-
- case 2: // send a strobe
- start_strobe();
- break;
-
- case 6: // enable interrupt on ACK
- m_irqenable = true;
- break;
-
- case 7: // disable and acknowledge IRQ, reset ACK flip-flop, disable autostrobe
- m_irqenable = false;
- m_autostrobe = false;
- lower_slot_irq();
- break;
+ m_fault_in = u8(u32(param));
+ LOG("/FAULT=%u\n", m_fault_in);
}
}
-WRITE_LINE_MEMBER( a2bus_pic_device::ack_w )
+
+void a2bus_pic_device::data_write(s32 param)
{
- if (m_started)
+ // latch output data - remember MSB can be forced low by jumper
+ if (BIT(param, 8))
{
- uint8_t dsw1 = m_dsw1->read();
+ m_data_latch = u8(u32(param));
+ m_printer_out->write(m_data_latch & (BIT(m_input_x->read(), 2) ? 0xffU : 0x7fU));
+ }
- if (dsw1 & 0x10) // negative polarity
+ // start/extend strobe output
+ if (BIT(param, 9))
+ {
+ ioport_value const sw1(m_input_sw1->read());
+ unsigned const cycles(15U - ((sw1 & 0x07U) << 1));
+ int const state(BIT(sw1, 3));
+ if (!m_strobe_timer->enabled())
{
- m_ack = (state == ASSERT_LINE) ? 0x00 : 0x80;
+ LOG("Output /STROBE=%d for %u cycles\n", state, cycles);
+ clear_ack_latch();
+ m_printer_conn->write_strobe(state);
}
else
{
- m_ack = (state == ASSERT_LINE) ? 0x80 : 0x00;
+ LOG("Adjust /STROBE=%d remaining to %u cycles\n", state, cycles);
}
+ m_strobe_timer->adjust(attotime::from_ticks(cycles * 7, clock()));
+ }
+}
- m_ack |= 0x40; // set ACK flip-flop
- if ((dsw1 & 0x40) && (m_irqenable))
+
+//----------------------------------------------
+// helpers
+//----------------------------------------------
+
+void a2bus_pic_device::reset_mode()
+{
+ if (!m_autostrobe_disable)
+ LOG("Disabling autostrobe\n");
+ else
+ LOG("Autostrobe already disabled\n");
+ m_autostrobe_disable = 1U;
+ disable_irq();
+ set_ack_latch();
+}
+
+
+void a2bus_pic_device::set_ack_latch()
+{
+ if (m_strobe_timer->enabled())
+ {
+ LOG("Active strobe prevents acknowledge latch from being set\n");
+ }
+ else if (!m_ack_latch)
+ {
+ LOG("Setting acknowledge latch\n");
+ m_ack_latch = 1U;
+ if (m_irq_enable && !BIT(m_input_sw1->read(), 6))
{
+ LOG("Asserting slot IRQ\n");
raise_slot_irq();
}
}
+ else
+ {
+ LOG("Acknowledge latch already set\n");
+ }
}
-void a2bus_pic_device::start_strobe()
-{
- int usec = ((m_dsw1->read() & 7) * 2) + 1; // strobe length in microseconds
- if (m_dsw1->read() & 0x8) // negative polarity
+void a2bus_pic_device::clear_ack_latch()
+{
+ if (m_ack_latch)
{
- m_ctx->write_strobe(CLEAR_LINE);
+ LOG("Clearing acknowledge latch\n");
+ m_ack_latch = 0U;
+ if (m_irq_enable && !BIT(m_input_sw1->read(), 6))
+ {
+ LOG("Releasing slot IRQ\n");
+ lower_slot_irq();
+ }
}
else
{
- m_ctx->write_strobe(ASSERT_LINE);
+ LOG("Acknowledge latch already clear\n");
}
+}
+
- m_timer->adjust(attotime::from_usec(usec), 0, attotime::never);
+void a2bus_pic_device::enable_irq()
+{
+ if (!m_irq_enable)
+ {
+ LOG("Enabling IRQ\n");
+ m_irq_enable = 1U;
+ if (m_ack_latch && !BIT(m_input_sw1->read(), 6))
+ {
+ LOG("Asserting slot IRQ\n");
+ raise_slot_irq();
+ }
+ }
+ else
+ {
+ LOG("IRQ already enabled\n");
+ }
}
-void a2bus_pic_device::clear_strobe()
+
+void a2bus_pic_device::disable_irq()
{
- if (m_dsw1->read() & 0x8) // negative polarity
+ if (m_irq_enable)
{
- m_ctx->write_strobe(ASSERT_LINE);
+ LOG("Disabling IRQ\n");
+ m_irq_enable = 0U;
+ if (m_ack_latch && !BIT(m_input_sw1->read(), 6))
+ {
+ LOG("Releasing slot IRQ\n");
+ lower_slot_irq();
+ }
}
else
{
- m_ctx->write_strobe(CLEAR_LINE);
+ LOG("IRQ already disabled\n");
}
}
+
+} // anonymous namespace
+
+
+
+DEFINE_DEVICE_TYPE_PRIVATE(A2BUS_PIC, device_a2bus_card_interface, a2bus_pic_device, "a2pic", "Apple II Parallel Interface Card")
diff --git a/src/devices/bus/a2bus/a2pic.h b/src/devices/bus/a2bus/a2pic.h
index 755700ef0b0..5970cdcbc7c 100644
--- a/src/devices/bus/a2bus/a2pic.h
+++ b/src/devices/bus/a2bus/a2pic.h
@@ -1,68 +1,58 @@
// license:BSD-3-Clause
-// copyright-holders:R. Belmont
-/*********************************************************************
-
- a2pic.h
-
- Apple II Parallel Interface Card
-
-*********************************************************************/
-
+// copyright-holders:Vas Crabb
+/***********************************************************************
+
+ Apple II Parallel Interface Card (670-0021)
+
+ DB25 connector, with Centronics assignments:
+
+ Data In, Bit 0 1
+ Signal Ground 2 19 GND
+ Data In, Bit 2 3
+ Signal Ground 4
+ Data Out, Bit 0 5 2 D0
+ Data Out, Bit 1 6 3 D1
+ (blocked)* 7
+ Data Out, Bit 2 8 4 D2
+ -- 9
+ -- 10
+ Data Out, Bit 5 11 7 D5
+ Data Out, Bit 6 12 8 D6
+ Data Out, Bit 7 13 9 D7
+ Data In, Bit 4 14
+ Strobe Out 15 1 /STROBE
+ Acknowledge In 16 10 /ACK
+ Data In, Bit 1 17
+ Data In, Bit 7 18 18 +5V PULLUP
+ Data In, Bit 5 19 12 POUT
+ Signal Ground 20
+ Data In, Bit 6 21 13 SEL
+ Data Out, Bit 3 22 5 D3
+ Data Out, Bit 4 23 6 D4
+ Signal Ground 24 16 0V
+ Data In, Bit 3 25 32 /FAULT
+
+ *wired to 500ns strobe but connector hole is blocked
+
+ This card has significant flaws:
+ * The strobe pulse begins on the same rising edge of the phase 1
+ clock as the data is latched. The parallel load enable input
+ to the strobe time counter (6A) is delayed slightly, but the
+ load happens on the rising phase 1 clock edge. This could
+ glitch on a real printer. MAME always sets the data outputs
+ before starting the strobe pulse.
+ * Acknowledge is ignored while the strobe output is active. If
+ the printer acknowledges the data before the end of the strobe
+ pulse, the card will miss it and wait forever.
+
+***********************************************************************/
#ifndef MAME_BUS_A2BUS_A2PIC_H
#define MAME_BUS_A2BUS_A2PIC_H
#pragma once
#include "a2bus.h"
-#include "bus/centronics/ctronics.h"
-
-//**************************************************************************
-// TYPE DEFINITIONS
-//**************************************************************************
-
-class a2bus_pic_device:
- public device_t,
- public device_a2bus_card_interface
-{
-public:
- // construction/destruction
- a2bus_pic_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
-
-protected:
- a2bus_pic_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_timer(emu_timer &timer, device_timer_id id, int param, void *ptr) 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 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;
-
- void start_strobe();
- void clear_strobe();
-
- required_ioport m_dsw1;
-
- required_device<centronics_device> m_ctx;
- required_device<input_buffer_device> m_ctx_data_in;
- required_device<output_latch_device> m_ctx_data_out;
-
-private:
- DECLARE_WRITE_LINE_MEMBER( ack_w );
-
- uint8_t *m_rom;
- bool m_started;
- uint8_t m_ack;
- bool m_irqenable;
- bool m_autostrobe;
- emu_timer *m_timer;
-};
-// device type definition
-DECLARE_DEVICE_TYPE(A2BUS_PIC, a2bus_pic_device)
+DECLARE_DEVICE_TYPE(A2BUS_PIC, device_a2bus_card_interface)
-#endif // MAME_BUS_A2BUS_A2PIC_H
+#endif // MAME_BUS_A2BUS_A2PIC_H
diff --git a/src/devices/bus/a2bus/a2sam.cpp b/src/devices/bus/a2bus/a2sam.cpp
index 16b8b5affe8..3fad0c34fff 100644
--- a/src/devices/bus/a2bus/a2sam.cpp
+++ b/src/devices/bus/a2bus/a2sam.cpp
@@ -10,22 +10,42 @@
#include "emu.h"
#include "a2sam.h"
-#include "sound/volt_reg.h"
+
+#include "sound/dac.h"
+
#include "speaker.h"
-/***************************************************************************
- PARAMETERS
-***************************************************************************/
+
+namespace {
//**************************************************************************
-// GLOBAL VARIABLES
+// TYPE DEFINITIONS
//**************************************************************************
-DEFINE_DEVICE_TYPE(A2BUS_SAM, a2bus_sam_device, "a2sam", "Don't Ask Software S.A.M.")
-
-/***************************************************************************
- FUNCTION PROTOTYPES
-***************************************************************************/
+class a2bus_sam_device:
+ public device_t,
+ public device_a2bus_card_interface
+{
+public:
+ // construction/destruction
+ a2bus_sam_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) :
+ device_t(mconfig, A2BUS_SAM, tag, owner, clock),
+ device_a2bus_card_interface(mconfig, *this),
+ m_dac(*this, "dac")
+ {
+ }
+
+protected:
+ virtual void device_start() override { }
+ virtual void device_reset() override { }
+ virtual void device_add_mconfig(machine_config &config) override ATTR_COLD;
+
+ // overrides of standard a2bus slot functions
+ virtual void write_c0nx(uint8_t offset, uint8_t data) override { m_dac->write(data); }
+ virtual bool take_c800() override { return false; }
+
+ required_device<dac_byte_interface> m_dac;
+};
//-------------------------------------------------
// device_add_mconfig - add device configuration
@@ -35,40 +55,13 @@ void a2bus_sam_device::device_add_mconfig(machine_config &config)
{
SPEAKER(config, "speaker").front_center();
DAC_8BIT_R2R(config, m_dac, 0).add_route(ALL_OUTPUTS, "speaker", 0.5); // unknown DAC
- voltage_regulator_device &vref(VOLTAGE_REGULATOR(config, "vref"));
- vref.add_route(0, "dac", 1.0, DAC_VREF_POS_INPUT);
- vref.add_route(0, "dac", -1.0, DAC_VREF_NEG_INPUT);
}
-//**************************************************************************
-// LIVE DEVICE
-//**************************************************************************
-
-a2bus_sam_device::a2bus_sam_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) :
- device_t(mconfig, A2BUS_SAM, tag, owner, clock),
- device_a2bus_card_interface(mconfig, *this),
- m_dac(*this, "dac")
-{
-}
-
-//-------------------------------------------------
-// device_start - device-specific startup
-//-------------------------------------------------
-
-void a2bus_sam_device::device_start()
-{
-}
+} // anonymous namespace
-void a2bus_sam_device::device_reset()
-{
-}
-void a2bus_sam_device::write_c0nx(uint8_t offset, uint8_t data)
-{
- m_dac->write(data);
-}
+//**************************************************************************
+// GLOBAL VARIABLES
+//**************************************************************************
-bool a2bus_sam_device::take_c800()
-{
- return false;
-}
+DEFINE_DEVICE_TYPE_PRIVATE(A2BUS_SAM, device_a2bus_card_interface, a2bus_sam_device, "a2sam", "Don't Ask Software S.A.M.")
diff --git a/src/devices/bus/a2bus/a2sam.h b/src/devices/bus/a2bus/a2sam.h
index 20957e47e19..87066e6cd6e 100644
--- a/src/devices/bus/a2bus/a2sam.h
+++ b/src/devices/bus/a2bus/a2sam.h
@@ -14,33 +14,8 @@
#pragma once
#include "a2bus.h"
-#include "sound/dac.h"
-
-//**************************************************************************
-// TYPE DEFINITIONS
-//**************************************************************************
-
-class a2bus_sam_device:
- public device_t,
- public device_a2bus_card_interface
-{
-public:
- // construction/destruction
- a2bus_sam_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;
-
- // overrides of standard a2bus slot functions
- virtual void write_c0nx(uint8_t offset, uint8_t data) override;
- virtual bool take_c800() override;
-
- required_device<dac_byte_interface> m_dac;
-};
-
-// device type definition
-DECLARE_DEVICE_TYPE(A2BUS_SAM, a2bus_sam_device)
+
+// device type declaration
+DECLARE_DEVICE_TYPE(A2BUS_SAM, device_a2bus_card_interface)
#endif // MAME_BUS_A2BUS_A2SAM_H
diff --git a/src/devices/bus/a2bus/a2scsi.cpp b/src/devices/bus/a2bus/a2scsi.cpp
index 9c3e4bc6c85..53aff96effa 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,16 +66,25 @@ 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, "speaker", 2).front();
+
NSCSI_BUS(config, m_scsibus);
NSCSI_CONNECTOR(config, "scsibus:0", default_scsi_devices, nullptr, false);
- NSCSI_CONNECTOR(config, "scsibus:1", default_scsi_devices, "cdrom", 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, "^^speaker", 1.0, 0);
+ device->subdevice<cdda_device>("cdda")->add_route(1, "^^speaker", 1.0, 1);
+ });
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);
NSCSI_CONNECTOR(config, "scsibus:5", default_scsi_devices, nullptr, false);
NSCSI_CONNECTOR(config, "scsibus:6", default_scsi_devices, "harddisk", false);
- NSCSI_CONNECTOR(config, "scsibus:7").option_set("ncr5380", NCR5380N).machine_config([this](device_t *device) {
- downcast<ncr5380n_device &>(*device).drq_handler().set(*this, FUNC(a2bus_scsi_device::drq_w));
+ NSCSI_CONNECTOR(config, "scsibus:7").option_set("ncr5380", NCR5380).machine_config([this](device_t *device) {
+ downcast<ncr5380_device &>(*device).drq_handler().set(*this, FUNC(a2bus_scsi_device::drq_w));
});
}
@@ -94,7 +105,7 @@ a2bus_scsi_device::a2bus_scsi_device(const machine_config &mconfig, device_type
device_t(mconfig, type, tag, owner, clock),
device_a2bus_card_interface(mconfig, *this),
m_ncr5380(*this, SCSI_5380_TAG),
- m_scsibus(*this, SCSI_BUS_TAG), m_rom(nullptr), m_rambank(0), m_rombank(0), m_drq(0), m_bank(0), m_816block(false)
+ m_scsibus(*this, SCSI_BUS_TAG), m_rom(*this, SCSI_ROM_REGION), m_rambank(0), m_rombank(0), m_drq(0), m_bank(0), m_816block(false)
{
}
@@ -109,8 +120,6 @@ a2bus_scsi_device::a2bus_scsi_device(const machine_config &mconfig, const char *
void a2bus_scsi_device::device_start()
{
- m_rom = device().machine().root_device().memregion(this->subtag(SCSI_ROM_REGION).c_str())->base();
-
memset(m_ram, 0, 8192);
save_item(NAME(m_ram));
@@ -153,9 +162,6 @@ uint8_t a2bus_scsi_device::read_c0nx(uint8_t offset)
case 9: // our SCSI ID (normally 0x80 = 7)
return (1<<7);
- case 0xa: // RAM/ROM bank
- return m_bank;
-
case 0xe: // DRQ status in bit 7
return m_drq;
@@ -295,7 +301,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 f1a556eeab7..3beb78e5fce 100644
--- a/src/devices/bus/a2bus/a2scsi.h
+++ b/src/devices/bus/a2bus/a2scsi.h
@@ -14,7 +14,7 @@
#pragma once
#include "a2bus.h"
-#include "machine/ncr5380n.h"
+#include "machine/ncr5380.h"
//**************************************************************************
// TYPE DEFINITIONS
@@ -28,15 +28,15 @@ 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);
- 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 device_start() override ATTR_COLD;
+ virtual void device_reset() override ATTR_COLD;
+ virtual void device_add_mconfig(machine_config &config) override ATTR_COLD;
+ virtual const tiny_rom_entry *device_rom_region() const override ATTR_COLD;
// overrides of standard a2bus slot functions
virtual uint8_t read_c0nx(uint8_t offset) override;
@@ -46,11 +46,11 @@ protected:
virtual uint8_t read_c800(uint16_t offset) override;
virtual void write_c800(uint16_t offset, uint8_t data) override;
- required_device<ncr5380n_device> m_ncr5380;
+ required_device<ncr5380_device> m_ncr5380;
required_device<nscsi_bus_device> m_scsibus;
+ required_region_ptr<u8> m_rom;
private:
- uint8_t *m_rom;
uint8_t m_ram[8192]; // 8 banks of 1024 bytes
int m_rambank, m_rombank;
uint8_t m_drq;
diff --git a/src/devices/bus/a2bus/a2sd.cpp b/src/devices/bus/a2bus/a2sd.cpp
new file mode 100644
index 00000000000..14e6ad88c14
--- /dev/null
+++ b/src/devices/bus/a2bus/a2sd.cpp
@@ -0,0 +1,333 @@
+// license:BSD-3-Clause
+// copyright-holders:R. Belmont
+/*********************************************************************
+
+ a2sd.cpp
+
+ Implementation of the AppleIISD card by Florian Reitz
+ https://github.com/freitz85/AppleIISd
+
+ AppleIISD has a Xilinx FPGA which implements a minimally hardware
+ assisted SPI interface, and the SD card is thus driven in SPI
+ mode rather than SD.
+
+ The SPI controller is fixed to SPI Mode 3 only.
+ (shift on falling CLK edges, shift-then-latch).
+
+ Firmware is contained in an Atmel 28C64B parallel EEPROM, which
+ has a Flash-style command set.
+
+*********************************************************************/
+
+#include "emu.h"
+#include "a2sd.h"
+
+#include "machine/at28c64b.h"
+#include "machine/spi_sdcard.h"
+
+#define LOG_SPI (1U << 1)
+
+//#define VERBOSE (LOG_GENERAL)
+#define LOG_OUTPUT_FUNC osd_printf_info
+
+#include "logmacro.h"
+
+namespace {
+
+/***************************************************************************
+ PARAMETERS
+***************************************************************************/
+
+static constexpr u8 C0N1_ECE = 0x04; // external clock: toggles between 500 kHz internal clock and 1/2 of the 7M A2 bus clock
+static constexpr u8 C0N1_FRX = 0x10; // fast recieve: when enabled, both reads and writes of the SPI data register start a shift cycle
+[[maybe_unused]] static constexpr u8 C0N1_BSY = 0x20;
+static constexpr u8 C0N1_TC = 0x80; // SPI transfer complete
+
+static constexpr u8 C0N3_CD = 0x40; // card detect
+static constexpr u8 C0N3_BIT_SS = 7;
+
+ROM_START( a2sd )
+ ROM_REGION(0x2000, "flash", ROMREGION_ERASE00)
+ ROM_LOAD( "appleiisd.bin", 0x000000, 0x000800, CRC(e82eea8a) SHA1(7e0acef01e622eeed6f8e87893d07c701bbef016) )
+ROM_END
+
+//**************************************************************************
+// TYPE DEFINITIONS
+//**************************************************************************
+
+class a2bus_a2sd_device:
+ public device_t,
+ public device_a2bus_card_interface
+{
+public:
+ // construction/destruction
+ a2bus_a2sd_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
+
+protected:
+ a2bus_a2sd_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock);
+
+ 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;
+ virtual const tiny_rom_entry *device_rom_region() const override ATTR_COLD;
+
+ // overrides of standard a2bus slot functions
+ 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;
+ virtual u8 read_c800(uint16_t offset) override;
+ virtual void write_c800(uint16_t offset, u8 data) override;
+
+ // SPI 4-wire interface
+ void spi_miso_w(int state) { m_in_bit = state; }
+
+ TIMER_CALLBACK_MEMBER(shift_tick);
+
+private:
+ required_device<at28c64b_device> m_flash;
+ required_device<spi_sdcard_device> m_sdcard;
+
+ u8 m_datain, m_in_latch, m_out_latch;
+ u8 m_c0n1, m_c0n3;
+ int m_in_bit;
+
+ int m_shift_count;
+ emu_timer *m_shift_timer;
+};
+
+/***************************************************************************
+ FUNCTION PROTOTYPES
+***************************************************************************/
+
+//-------------------------------------------------
+// device_add_mconfig - add device configuration
+//-------------------------------------------------
+void a2bus_a2sd_device::device_add_mconfig(machine_config &config)
+{
+ AT28C64B(config, m_flash, 0);
+
+ SPI_SDCARD(config, m_sdcard, 0);
+ m_sdcard->set_prefer_sdhc();
+ m_sdcard->spi_miso_callback().set(FUNC(a2bus_a2sd_device::spi_miso_w));
+}
+
+//-------------------------------------------------
+// rom_region - device-specific ROM region
+//-------------------------------------------------
+
+const tiny_rom_entry *a2bus_a2sd_device::device_rom_region() const
+{
+ return ROM_NAME( a2sd );
+}
+
+//**************************************************************************
+// LIVE DEVICE
+//**************************************************************************
+
+a2bus_a2sd_device::a2bus_a2sd_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_flash(*this, "flash"),
+ m_sdcard(*this, "sdcard"),
+ m_datain(0), m_in_latch(0), m_out_latch(0), m_c0n1(0), m_c0n3(0x80), m_in_bit(0), m_shift_count(0)
+{
+}
+
+a2bus_a2sd_device::a2bus_a2sd_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) :
+ a2bus_a2sd_device(mconfig, A2BUS_A2SD, tag, owner, clock)
+{
+}
+
+//-------------------------------------------------
+// device_start - device-specific startup
+//-------------------------------------------------
+
+void a2bus_a2sd_device::device_start()
+{
+ m_shift_timer = timer_alloc(FUNC(a2bus_a2sd_device::shift_tick), this);
+
+ save_item(NAME(m_datain));
+ save_item(NAME(m_in_latch));
+ save_item(NAME(m_out_latch));
+ save_item(NAME(m_c0n1));
+ save_item(NAME(m_c0n3));
+ save_item(NAME(m_in_bit));
+ save_item(NAME(m_shift_count));
+}
+
+void a2bus_a2sd_device::device_reset()
+{
+ m_shift_timer->adjust(attotime::never);
+ m_shift_count = 0;
+ m_sdcard->spi_clock_w(CLEAR_LINE);
+}
+
+TIMER_CALLBACK_MEMBER(a2bus_a2sd_device::shift_tick)
+{
+ LOGMASKED(LOG_SPI, ">>>>>>> SHIFT %d (%c)\n", m_shift_count, (m_shift_count & 1) ? 'L' : 'S');
+ if (!(m_shift_count & 1))
+ {
+ if (m_shift_count < 16)
+ {
+ m_out_latch <<= 1;
+ }
+ m_in_latch <<= 1;
+ m_sdcard->spi_mosi_w(BIT(m_out_latch, 7));
+ m_sdcard->spi_clock_w(CLEAR_LINE);
+ }
+ else
+ {
+ m_in_latch &= ~0x01;
+ m_in_latch |= m_in_bit;
+ m_sdcard->spi_clock_w(ASSERT_LINE);
+
+ if (m_shift_count == 1)
+ {
+ m_datain = m_in_latch;
+ LOGMASKED(LOG_SPI, "SPI: got %02x (in latch %02x)\n", m_datain, m_in_latch);
+ }
+ }
+
+ m_shift_count--;
+ if (m_shift_count == 0)
+ {
+ m_shift_timer->adjust(attotime::never);
+ m_c0n1 |= C0N1_TC; // set TC
+ }
+}
+
+/*-------------------------------------------------
+ read_c0nx - called for reads from this card's c0nx space
+-------------------------------------------------*/
+
+u8 a2bus_a2sd_device::read_c0nx(u8 offset)
+{
+ switch (offset)
+ {
+ case 0:
+ m_c0n1 &= ~C0N1_TC; // clear TC
+ // if FRX is set, both reads and writes trigger a shift cycle
+ if (m_c0n1 & C0N1_FRX)
+ {
+ m_c0n1 &= ~C0N1_TC; // clear TC
+ m_shift_count = 16;
+ m_out_latch = 0xff;
+
+ if (m_c0n1 & C0N1_ECE)
+ {
+ m_shift_timer->adjust(attotime::from_hz(14.318181_MHz_XTAL / 4), 0, attotime::from_hz(14.318181_MHz_XTAL / 4));
+ }
+ else
+ {
+ m_shift_timer->adjust(attotime::from_hz(500_kHz_XTAL), 0, attotime::from_hz(500_kHz_XTAL));
+ }
+ }
+ return m_datain;
+
+ case 1:
+ return m_c0n1;
+
+ case 2:
+ return 0;
+
+ case 3:
+ m_c0n3 &= ~C0N3_CD;
+ m_c0n3 |= m_sdcard->get_card_present() ? 0 : C0N3_CD; // bit is set if no card is present
+ return m_c0n3;
+ }
+ return 0xff;
+}
+
+
+/*-------------------------------------------------
+ write_c0nx - called for writes to this card's c0nx space
+-------------------------------------------------*/
+
+void a2bus_a2sd_device::write_c0nx(u8 offset, u8 data)
+{
+ switch (offset)
+ {
+ case 0:
+ if (m_shift_count)
+ {
+ return;
+ }
+ LOGMASKED(LOG_SPI, "SPI sending %02x\n", data);
+ m_out_latch = data;
+ m_sdcard->spi_mosi_w(BIT(m_out_latch, 7));
+ m_c0n1 &= ~C0N1_TC; // clear TC
+ m_shift_count = 16;
+ // if ECE is set, clock is 3.58 MHz from the A2 bus, otherwise internally generated 500 kHz
+ if (m_c0n1 & C0N1_ECE)
+ {
+ m_shift_timer->adjust(attotime::from_hz(14.318181_MHz_XTAL / 4), 0, attotime::from_hz(14.318181_MHz_XTAL/4));
+ }
+ else
+ {
+ m_shift_timer->adjust(attotime::from_hz(500_kHz_XTAL), 0, attotime::from_hz(500_kHz_XTAL));
+ }
+ break;
+
+ case 1:
+ m_c0n1 &= 0xea;
+ m_c0n1 |= (data & 0x15);
+ break;
+
+ case 2:
+ break;
+
+ case 3:
+ m_c0n3 &= 0x9f;
+ m_c0n3 |= (data & 0x91);
+
+ m_sdcard->spi_ss_w(BIT(data, C0N3_BIT_SS));
+ LOG("/SS is %x\n", BIT(data, C0N3_BIT_SS));
+ break;
+
+ default:
+ logerror("a2sd: write %02x to c0n%x (%s)\n", data, offset, machine().describe_context().c_str());
+ break;
+ }
+}
+
+/*-------------------------------------------------
+ read_cnxx - called for reads from this card's cnxx space
+-------------------------------------------------*/
+
+u8 a2bus_a2sd_device::read_cnxx(u8 offset)
+{
+ // slot image at 0
+ return m_flash->read(offset);
+}
+
+void a2bus_a2sd_device::write_cnxx(u8 offset, u8 data)
+{
+ m_flash->write(offset, data);
+}
+
+/*-------------------------------------------------
+ read_c800 - called for reads from this card's c800 space
+-------------------------------------------------*/
+
+u8 a2bus_a2sd_device::read_c800(u16 offset)
+{
+ return m_flash->read(offset + 0x100);
+}
+
+/*-------------------------------------------------
+ write_c800 - called for writes to this card's c800 space
+-------------------------------------------------*/
+void a2bus_a2sd_device::write_c800(u16 offset, u8 data)
+{
+ m_flash->write(offset + 0x100, data);
+}
+
+} // anonymous namespace
+
+
+//**************************************************************************
+// GLOBAL VARIABLES
+//**************************************************************************
+
+DEFINE_DEVICE_TYPE_PRIVATE(A2BUS_A2SD, device_a2bus_card_interface, a2bus_a2sd_device, "a2sd", "Apple II SD Card")
diff --git a/src/devices/bus/a2bus/a2sd.h b/src/devices/bus/a2bus/a2sd.h
new file mode 100644
index 00000000000..6f8702fa903
--- /dev/null
+++ b/src/devices/bus/a2bus/a2sd.h
@@ -0,0 +1,20 @@
+// license:BSD-3-Clause
+// copyright-holders:R. Belmont
+/*********************************************************************
+
+ a2sd.h
+
+ Implementation of the AppleIISD card
+
+*********************************************************************/
+
+#ifndef MAME_BUS_A2BUS_A2SD_H
+#define MAME_BUS_A2BUS_A2SD_H
+
+#pragma once
+
+#include "a2bus.h"
+
+DECLARE_DEVICE_TYPE(A2BUS_A2SD, device_a2bus_card_interface)
+
+#endif // MAME_BUS_A2BUS_A2SD_H
diff --git a/src/devices/bus/a2bus/a2softcard.cpp b/src/devices/bus/a2bus/a2softcard.cpp
index d41c84b9425..bab2ea728f8 100644
--- a/src/devices/bus/a2bus/a2softcard.cpp
+++ b/src/devices/bus/a2bus/a2softcard.cpp
@@ -100,7 +100,7 @@ void a2bus_softcard_device::write_cnxx(uint8_t offset, uint8_t data)
}
}
-READ8_MEMBER( a2bus_softcard_device::dma_r )
+uint8_t a2bus_softcard_device::dma_r(offs_t offset)
{
if (m_bEnabled)
{
@@ -138,7 +138,7 @@ READ8_MEMBER( a2bus_softcard_device::dma_r )
// dma_w -
//-------------------------------------------------
-WRITE8_MEMBER( a2bus_softcard_device::dma_w )
+void a2bus_softcard_device::dma_w(offs_t offset, uint8_t data)
{
if (m_bEnabled)
{
diff --git a/src/devices/bus/a2bus/a2softcard.h b/src/devices/bus/a2bus/a2softcard.h
index e206cc805ae..c983e762cf6 100644
--- a/src/devices/bus/a2bus/a2softcard.h
+++ b/src/devices/bus/a2bus/a2softcard.h
@@ -28,9 +28,9 @@ public:
protected:
a2bus_softcard_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 device_start() override ATTR_COLD;
+ virtual void device_reset() override ATTR_COLD;
+ virtual void device_add_mconfig(machine_config &config) override ATTR_COLD;
// overrides of standard a2bus slot functions
virtual void write_cnxx(uint8_t offset, uint8_t data) override;
@@ -41,10 +41,10 @@ private:
bool m_bEnabled;
bool m_FirstZ80Boot;
- DECLARE_READ8_MEMBER( dma_r );
- DECLARE_WRITE8_MEMBER( dma_w );
+ uint8_t dma_r(offs_t offset);
+ void dma_w(offs_t offset, uint8_t data);
- void z80_mem(address_map &map);
+ void z80_mem(address_map &map) ATTR_COLD;
};
// device type definition
diff --git a/src/devices/bus/a2bus/a2ssc.cpp b/src/devices/bus/a2bus/a2ssc.cpp
index 773f4db246f..1e9a5fb1f8e 100644
--- a/src/devices/bus/a2bus/a2ssc.cpp
+++ b/src/devices/bus/a2bus/a2ssc.cpp
@@ -6,35 +6,96 @@
Apple II Super Serial Card
+ The Apricorn Super Serial Imager has separate "Modem" and
+ "Printer" pin headers, which carry different arrangements of the
+ same RS232 signals. Its GPI mode also features Videx VideoTerm
+ support when that card is installed in slot 3.
+
*********************************************************************/
#include "emu.h"
#include "a2ssc.h"
+
#include "bus/rs232/rs232.h"
+#include "machine/mos6551.h"
-/***************************************************************************
- PARAMETERS
-***************************************************************************/
+namespace {
//**************************************************************************
-// GLOBAL VARIABLES
+// TYPE DEFINITIONS
//**************************************************************************
-DEFINE_DEVICE_TYPE(A2BUS_SSC, a2bus_ssc_device, "a2ssc", "Apple Super Serial Card")
+class a2bus_ssc_device:
+ public device_t,
+ public device_a2bus_card_interface
+{
+public:
+ // construction/destruction
+ a2bus_ssc_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
+
+protected:
+ a2bus_ssc_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock);
+
+ 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;
+ virtual const tiny_rom_entry *device_rom_region() const override ATTR_COLD;
+ virtual ioport_constructor device_input_ports() const override ATTR_COLD;
+
+ 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;
+
+ required_ioport m_dsw1, m_dsw2;
+ required_ioport m_dswx;
-#define SSC_ROM_REGION "ssc_rom"
-#define SSC_ACIA_TAG "ssc_acia"
-#define SSC_RS232_TAG "ssc_rs232"
+ required_device<mos6551_device> m_acia;
+
+ required_region_ptr<uint8_t> m_rom;
+
+private:
+ void acia_irq_w(int state);
+};
+
+class apricorn_ssi_device : public a2bus_ssc_device
+{
+public:
+ // construction/destruction
+ apricorn_ssi_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
+
+protected:
+ virtual void device_start() override ATTR_COLD;
+ virtual const tiny_rom_entry *device_rom_region() const override ATTR_COLD;
+ virtual ioport_constructor device_input_ports() const override ATTR_COLD;
+
+ virtual void write_c0nx(uint8_t offset, uint8_t data) override;
+ virtual uint8_t read_cnxx(uint8_t offset) override;
+ virtual void write_cnxx(uint8_t offset, uint8_t data) override;
+ virtual uint8_t read_c800(uint16_t offset) override;
+
+private:
+ bool m_alt_bank;
+};
+
+/***************************************************************************
+ PARAMETERS
+***************************************************************************/
ROM_START( ssc )
- ROM_REGION(0x000800, SSC_ROM_REGION, 0)
+ ROM_REGION(0x800, "program", 0)
ROM_LOAD( "341-0065-a.bin", 0x000000, 0x000800, CRC(b7539d4c) SHA1(6dab633470c6bc4cb3e81d09fda46597caf8ee57) )
ROM_END
+ROM_START( ssi )
+ ROM_REGION(0x2000, "program", 0) // "SSI Version 1.1"
+ ROM_LOAD( "apricorn super serial imager - rom.bin", 0x0000, 0x2000, CRC(d251f7f1) SHA1(19f2bc1e60c3fd5e179c4a38f7ca4e3221553562) )
+ROM_END
+
static INPUT_PORTS_START( ssc )
PORT_START("DSW1")
- PORT_DIPNAME( 0xf0, 0xf0, "Baud rate" )
+ PORT_DIPNAME( 0xf0, 0xe0, "Baud Rate" ) PORT_DIPLOCATION("SW1:4,3,2,1")
PORT_DIPSETTING( 0x00, "Undefined/115200" )
PORT_DIPSETTING( 0x10, "50" )
PORT_DIPSETTING( 0x20, "75" )
@@ -51,36 +112,141 @@ static INPUT_PORTS_START( ssc )
PORT_DIPSETTING( 0xd0, "7200" )
PORT_DIPSETTING( 0xe0, "9600" )
PORT_DIPSETTING( 0xf0, "19200" )
-
- PORT_DIPNAME( 0x0c, 0x00, "Mode" )
+ PORT_BIT( 0x0c, IP_ACTIVE_LOW, IPT_UNUSED )
+ PORT_DIPNAME( 0x03, 0x00, "Mode" ) PORT_DIPLOCATION("SW1:6,5")
PORT_DIPSETTING( 0x00, "Communications Mode" )
- PORT_DIPSETTING( 0x04, "SIC P8 Emulation Mode" )
- PORT_DIPSETTING( 0x08, "Printer Mode" )
- PORT_DIPSETTING( 0x0c, "SIC P8A Emulation Mode" )
-
- PORT_DIPNAME( 0x01, 0x00, "Clear To Send" )
- PORT_DIPSETTING( 0x00, "Normal Clear To Send" )
- PORT_DIPSETTING( 0x01, "Secondary Clear To Send" )
+ PORT_DIPSETTING( 0x01, "SIC P8 Emulation Mode" )
+ PORT_DIPSETTING( 0x02, "Printer Mode" )
+ PORT_DIPSETTING( 0x03, "SIC P8A Emulation Mode" )
PORT_START("DSW2")
- PORT_DIPNAME( 0xc0, 0x00, "Format" )
- PORT_DIPSETTING( 0x00, "8 data, 1 stop")
- PORT_DIPSETTING( 0x40, "7 data, 1 stop")
- PORT_DIPSETTING( 0x80, "8 data, 2 stop")
- PORT_DIPSETTING( 0xc0, "7 data, 2 stop")
-
- PORT_DIPNAME( 0x30, 0x00, "Parity" )
- PORT_DIPSETTING( 0x00, "None")
- PORT_DIPSETTING( 0x10, "Odd")
- PORT_DIPSETTING( 0x30, "Even")
-
- PORT_DIPNAME( 0x08, 0x08, "End of Line" )
+ PORT_DIPNAME( 0x80, 0x00, "Stop Bits" ) PORT_DIPLOCATION("SW2:1")
+ PORT_DIPSETTING( 0x00, "1")
+ PORT_DIPSETTING( 0x80, "2")
+ PORT_DIPNAME( 0x20, 0x00, "Data Bits" ) PORT_DIPLOCATION("SW2:2") PORT_CONDITION("DSW1", 0x03, NOTEQUALS, 0x02)
+ PORT_DIPSETTING( 0x20, "7")
+ PORT_DIPSETTING( 0x00, "8")
+ PORT_DIPNAME( 0x20, 0x00, "Delay After CR" ) PORT_DIPLOCATION("SW2:2") PORT_CONDITION("DSW1", 0x03, EQUALS, 0x02)
+ PORT_DIPSETTING( 0x20, DEF_STR(None))
+ PORT_DIPSETTING( 0x00, "1/4 sec")
+ PORT_BIT( 0x50, IP_ACTIVE_LOW, IPT_UNUSED )
+ PORT_DIPNAME( 0x0c, 0x00, "Parity" ) PORT_DIPLOCATION("SW2:4,3") PORT_CONDITION("DSW1", 0x03, NOTEQUALS, 0x02)
+ PORT_DIPSETTING( 0x00, DEF_STR(None))
+ PORT_DIPSETTING( 0x08, "None (2)")
+ PORT_DIPSETTING( 0x04, "Odd")
+ PORT_DIPSETTING( 0x0c, "Even")
+ PORT_DIPNAME( 0x0c, 0x00, "Line Width" ) PORT_DIPLOCATION("SW2:4,3") PORT_CONDITION("DSW1", 0x03, EQUALS, 0x02)
+ PORT_DIPSETTING( 0x00, "40 Characters")
+ PORT_DIPSETTING( 0x04, "72 Characters")
+ PORT_DIPSETTING( 0x08, "80 Characters")
+ PORT_DIPSETTING( 0x0c, "132 Characters")
+ PORT_DIPNAME( 0x02, 0x02, "End of Line" ) PORT_DIPLOCATION("SW2:5")
PORT_DIPSETTING( 0x00, "Add LF after CR")
- PORT_DIPSETTING( 0x08, "Don't add LF after CR")
+ PORT_DIPSETTING( 0x02, "Don't add LF after CR")
+ PORT_BIT( 0x01, IP_ACTIVE_HIGH, IPT_CUSTOM ) PORT_READ_LINE_DEVICE_MEMBER("rs232", FUNC(rs232_port_device::cts_r))
+
+ PORT_START("DSWX") // Non-memory-mapped DIP switches
+ PORT_DIPNAME( 0x04, 0x04, "Interrupts" ) PORT_DIPLOCATION("SW2:6")
+ PORT_DIPSETTING( 0x04, DEF_STR(Off))
+ PORT_DIPSETTING( 0x00, DEF_STR(On))
+ PORT_DIPNAME( 0x02, 0x00, "DCD Connected" ) PORT_DIPLOCATION("SW1:7")
+ PORT_DIPSETTING( 0x00, DEF_STR(On))
+ PORT_DIPNAME( 0x01, 0x01, "Secondary CTS Connected" ) PORT_DIPLOCATION("SW2:7")
+ PORT_DIPSETTING( 0x01, DEF_STR(Off))
+INPUT_PORTS_END
+
+static INPUT_PORTS_START( ssi )
+ PORT_START("DSW1")
+ PORT_DIPNAME( 0x100, 0x100, "Emulation Mode" ) PORT_DIPLOCATION("SW1:8")
+ PORT_DIPSETTING( 0x100, "Off (GPI)" )
+ PORT_DIPSETTING( 0x000, "On (SSC)" )
+ PORT_DIPNAME( 0xf0, 0xe0, "Baud Rate" ) PORT_DIPLOCATION("SW1:4,3,2,1")
+ PORT_DIPSETTING( 0x00, "Undefined" )
+ PORT_DIPSETTING( 0x10, "50" )
+ PORT_DIPSETTING( 0x20, "75" )
+ PORT_DIPSETTING( 0x30, "110" )
+ PORT_DIPSETTING( 0x40, "135" )
+ PORT_DIPSETTING( 0x50, "150" )
+ PORT_DIPSETTING( 0x60, "300" )
+ PORT_DIPSETTING( 0x70, "600" )
+ PORT_DIPSETTING( 0x80, "1200" )
+ PORT_DIPSETTING( 0x90, "1800" )
+ PORT_DIPSETTING( 0xa0, "2400" )
+ PORT_DIPSETTING( 0xb0, "3600" )
+ PORT_DIPSETTING( 0xc0, "4800" )
+ PORT_DIPSETTING( 0xd0, "7200" )
+ PORT_DIPSETTING( 0xe0, "9600" )
+ PORT_DIPSETTING( 0xf0, "19200" )
+ PORT_BIT( 0x0c, IP_ACTIVE_LOW, IPT_UNUSED )
+ PORT_DIPNAME( 0x03, 0x02, "SSC Mode" ) PORT_DIPLOCATION("SW1:6,5") PORT_CONDITION("DSW1", 0x100, EQUALS, 0x000)
+ PORT_DIPSETTING( 0x00, "Communications" )
+ PORT_DIPSETTING( 0x02, "Printer" )
+ PORT_DIPNAME( 0x02, 0x02, "XON/XOFF Handshaking" ) PORT_DIPLOCATION("SW1:5") PORT_CONDITION("DSW1", 0x100, EQUALS, 0x100)
+ PORT_DIPSETTING( 0x02, DEF_STR(Off))
+ PORT_DIPSETTING( 0x00, DEF_STR(On))
+ PORT_DIPNAME( 0x01, 0x00, "LF After CR" ) PORT_DIPLOCATION("SW1:6") PORT_CONDITION("DSW1", 0x100, EQUALS, 0x100)
+ PORT_DIPSETTING( 0x01, DEF_STR(Off))
+ PORT_DIPSETTING( 0x00, DEF_STR(On))
- PORT_DIPNAME( 0x04, 0x04, "Interrupts" )
- PORT_DIPSETTING( 0x00, "On")
- PORT_DIPSETTING( 0x04, "Off")
+ PORT_START("DSW2")
+ PORT_DIPNAME( 0x80, 0x80, "Stop Bits" ) PORT_DIPLOCATION("SW2:1") PORT_CONDITION("DSW1", 0x100, EQUALS, 0x000)
+ PORT_DIPSETTING( 0x00, "1")
+ PORT_DIPSETTING( 0x80, "2")
+ PORT_DIPNAME( 0x40, 0x40, DEF_STR(Unused)) PORT_DIPLOCATION("SW2:7") PORT_CONDITION("DSW1", 0x100, EQUALS, 0x000)
+ PORT_DIPSETTING( 0x40, DEF_STR(Off))
+ PORT_DIPSETTING( 0x00, DEF_STR(On))
+ PORT_DIPNAME( 0x20, 0x00, "Data Bits" ) PORT_DIPLOCATION("SW2:2") PORT_CONDITION("DSW1", 0x103, EQUALS, 0x000)
+ PORT_DIPSETTING( 0x20, "7")
+ PORT_DIPSETTING( 0x00, "8")
+ PORT_DIPNAME( 0x20, 0x00, "CR Delay" ) PORT_DIPLOCATION("SW2:2") PORT_CONDITION("DSW1", 0x103, EQUALS, 0x002)
+ PORT_DIPSETTING( 0x20, DEF_STR(None))
+ PORT_DIPSETTING( 0x00, "32 ms")
+ PORT_DIPNAME( 0x10, 0x10, DEF_STR(Unused)) PORT_DIPLOCATION("SW2:8") PORT_CONDITION("DSW1", 0x100, EQUALS, 0x000)
+ PORT_DIPSETTING( 0x10, DEF_STR(Off))
+ PORT_DIPSETTING( 0x00, DEF_STR(On))
+ PORT_DIPNAME( 0x0c, 0x08, "Parity" ) PORT_DIPLOCATION("SW2:4,3") PORT_CONDITION("DSW1", 0x103, EQUALS, 0x000)
+ PORT_DIPSETTING( 0x00, DEF_STR(None))
+ PORT_DIPSETTING( 0x08, "None (2)")
+ PORT_DIPSETTING( 0x04, "Odd")
+ PORT_DIPSETTING( 0x0c, "Even")
+ PORT_DIPNAME( 0x0c, 0x00, "Line Width" ) PORT_DIPLOCATION("SW2:4,3") PORT_CONDITION("DSW1", 0x103, EQUALS, 0x002)
+ PORT_DIPSETTING( 0x00, "40 Characters (Echo On)")
+ PORT_DIPSETTING( 0x04, "72 Characters (Echo Off)")
+ PORT_DIPSETTING( 0x08, "80 Characters (Echo Off)")
+ PORT_DIPSETTING( 0x0c, "132 Characters (Echo Off)")
+ PORT_DIPNAME( 0x02, 0x00, "LF After CR" ) PORT_DIPLOCATION("SW2:5") PORT_CONDITION("DSW1", 0x100, EQUALS, 0x000)
+ PORT_DIPSETTING( 0x02, DEF_STR(Off))
+ PORT_DIPSETTING( 0x00, DEF_STR(On))
+ PORT_DIPNAME( 0xa8, 0x88, "Printer Type" ) PORT_DIPLOCATION("SW2:3,2,1") PORT_CONDITION("DSW1", 0x100, EQUALS, 0x100)
+ PORT_DIPSETTING( 0x08, "ImageWriter" )
+ PORT_DIPSETTING( 0x88, "Epson" )
+ PORT_DIPSETTING( 0x80, "Star Micronics" )
+ PORT_DIPSETTING( 0x20, "Okidata" )
+ PORT_DIPSETTING( 0x00, "C. Itoh" )
+ PORT_DIPSETTING( 0x28, "Unknown (1)" )
+ PORT_DIPSETTING( 0xa0, "Unknown (2)" )
+ PORT_DIPSETTING( 0xa8, "Unknown (3)" )
+ PORT_DIPNAME( 0x40, 0x40, "Video Echo" ) PORT_DIPLOCATION("SW2:7") PORT_CONDITION("DSW1", 0x100, EQUALS, 0x100)
+ PORT_DIPSETTING( 0x40, DEF_STR(Off))
+ PORT_DIPSETTING( 0x00, DEF_STR(On))
+ PORT_DIPNAME( 0x10, 0x10, "Transparent Mode" ) PORT_DIPLOCATION("SW2:8") PORT_CONDITION("DSW1", 0x100, EQUALS, 0x100)
+ PORT_DIPSETTING( 0x10, DEF_STR(Off))
+ PORT_DIPSETTING( 0x00, DEF_STR(On))
+ PORT_DIPNAME( 0x04, 0x04, DEF_STR(Unused)) PORT_DIPLOCATION("SW2:4") PORT_CONDITION("DSW1", 0x100, EQUALS, 0x100)
+ PORT_DIPSETTING( 0x04, DEF_STR(Off))
+ PORT_DIPSETTING( 0x00, DEF_STR(On))
+ PORT_DIPNAME( 0x02, 0x00, "MSB Output" ) PORT_DIPLOCATION("SW2:5") PORT_CONDITION("DSW1", 0x100, EQUALS, 0x100)
+ PORT_DIPSETTING( 0x02, "Clear 8th Bit" )
+ PORT_DIPSETTING( 0x00, "Pass 8th Bit" )
+ PORT_BIT( 0x01, IP_ACTIVE_HIGH, IPT_CUSTOM ) PORT_READ_LINE_DEVICE_MEMBER("rs232", FUNC(rs232_port_device::cts_r)) // TBD: implemented on SSI or not?
+
+ PORT_START("DSWX")
+ PORT_DIPNAME( 0x04, 0x04, "Interrupts" ) PORT_DIPLOCATION("SW2:6")
+ PORT_DIPSETTING( 0x04, DEF_STR(Off))
+ PORT_DIPSETTING( 0x00, DEF_STR(On))
+ PORT_DIPNAME( 0x02, 0x00, "DCD Connected" ) PORT_DIPLOCATION("SW1:7")
+ PORT_DIPSETTING( 0x00, DEF_STR(On))
+ PORT_BIT( 0x01, IP_ACTIVE_LOW, IPT_UNUSED )
INPUT_PORTS_END
//-------------------------------------------------
@@ -92,6 +258,11 @@ ioport_constructor a2bus_ssc_device::device_input_ports() const
return INPUT_PORTS_NAME( ssc );
}
+ioport_constructor apricorn_ssi_device::device_input_ports() const
+{
+ return INPUT_PORTS_NAME( ssi );
+}
+
//-------------------------------------------------
// device_add_mconfig - add device configuration
//-------------------------------------------------
@@ -101,9 +272,11 @@ void a2bus_ssc_device::device_add_mconfig(machine_config &config)
MOS6551(config, m_acia, 0);
m_acia->set_xtal(1.8432_MHz_XTAL);
m_acia->irq_handler().set(FUNC(a2bus_ssc_device::acia_irq_w));
- m_acia->txd_handler().set(SSC_RS232_TAG, FUNC(rs232_port_device::write_txd));
+ m_acia->txd_handler().set("rs232", FUNC(rs232_port_device::write_txd));
+ m_acia->rts_handler().set("rs232", FUNC(rs232_port_device::write_rts));
+ m_acia->dtr_handler().set("rs232", FUNC(rs232_port_device::write_dtr));
- rs232_port_device &rs232(RS232_PORT(config, SSC_RS232_TAG, default_rs232_devices, nullptr));
+ rs232_port_device &rs232(RS232_PORT(config, "rs232", default_rs232_devices, nullptr));
rs232.rxd_handler().set(m_acia, FUNC(mos6551_device::write_rxd));
rs232.dcd_handler().set(m_acia, FUNC(mos6551_device::write_dcd));
rs232.dsr_handler().set(m_acia, FUNC(mos6551_device::write_dsr));
@@ -119,6 +292,11 @@ const tiny_rom_entry *a2bus_ssc_device::device_rom_region() const
return ROM_NAME( ssc );
}
+const tiny_rom_entry *apricorn_ssi_device::device_rom_region() const
+{
+ return ROM_NAME( ssi );
+}
+
//**************************************************************************
// LIVE DEVICE
//**************************************************************************
@@ -133,8 +311,15 @@ a2bus_ssc_device::a2bus_ssc_device(const machine_config &mconfig, device_type ty
device_a2bus_card_interface(mconfig, *this),
m_dsw1(*this, "DSW1"),
m_dsw2(*this, "DSW2"),
- m_acia(*this, SSC_ACIA_TAG), m_rom(nullptr),
- m_started(false)
+ m_dswx(*this, "DSWX"),
+ m_acia(*this, "acia"),
+ m_rom(*this, "program")
+{
+}
+
+apricorn_ssi_device::apricorn_ssi_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) :
+ a2bus_ssc_device(mconfig, APRICORN_SSI, tag, owner, clock),
+ m_alt_bank(false)
{
}
@@ -144,12 +329,15 @@ a2bus_ssc_device::a2bus_ssc_device(const machine_config &mconfig, device_type ty
void a2bus_ssc_device::device_start()
{
- m_rom = machine().root_device().memregion(this->subtag(SSC_ROM_REGION).c_str())->base();
+}
+
+void apricorn_ssi_device::device_start()
+{
+ save_item(NAME(m_alt_bank));
}
void a2bus_ssc_device::device_reset()
{
- m_started = true;
}
/*-------------------------------------------------
@@ -161,6 +349,19 @@ uint8_t a2bus_ssc_device::read_cnxx(uint8_t offset)
return m_rom[(offset&0xff)+0x700];
}
+uint8_t apricorn_ssi_device::read_cnxx(uint8_t offset)
+{
+ if (!machine().side_effects_disabled())
+ m_alt_bank = false;
+ return m_rom[offset | (BIT(m_dsw1->read(), 8) ? 0x1700 : 0x0700)];
+}
+
+void apricorn_ssi_device::write_cnxx(uint8_t offset, uint8_t data)
+{
+ // TBD: behavior guessed
+ m_alt_bank = false;
+}
+
/*-------------------------------------------------
read_c800 - called for reads from this card's c800 space
-------------------------------------------------*/
@@ -170,6 +371,15 @@ uint8_t a2bus_ssc_device::read_c800(uint16_t offset)
return m_rom[offset];
}
+uint8_t apricorn_ssi_device::read_c800(uint16_t offset)
+{
+ if (BIT(m_dsw1->read(), 8))
+ offset |= 0x1000;
+ if (m_alt_bank)
+ offset |= 0x800;
+ return m_rom[offset];
+}
+
/*-------------------------------------------------
read_c0nx - called for reads from this card's c0nx space
-------------------------------------------------*/
@@ -178,22 +388,17 @@ uint8_t a2bus_ssc_device::read_c0nx(uint8_t offset)
{
// dips at C0n1/C0n2, ACIA at C0n8/9/A/B
- switch (offset)
+ if (BIT(offset, 3))
+ return m_acia->read(offset & 3);
+ else
{
- case 1:
- return m_dsw1->read();
- case 2:
- return m_dsw2->read();
-
- case 8:
- case 9:
- case 0xa:
- case 0xb:
- return m_acia->read(offset-8);
-
+ uint8_t buffer = 0xff;
+ if (!BIT(offset, 1))
+ buffer &= m_dsw1->read();
+ if (!BIT(offset, 0))
+ buffer &= m_dsw2->read();
+ return buffer;
}
-
- return 0;
}
/*-------------------------------------------------
@@ -202,22 +407,23 @@ uint8_t a2bus_ssc_device::read_c0nx(uint8_t offset)
void a2bus_ssc_device::write_c0nx(uint8_t offset, uint8_t data)
{
- switch (offset)
- {
- case 8:
- case 9:
- case 0xa:
- case 0xb:
- m_acia->write(offset-8, data);
- break;
- }
+ if (BIT(offset, 3))
+ m_acia->write(offset & 3, data);
}
-WRITE_LINE_MEMBER( a2bus_ssc_device::acia_irq_w )
+void apricorn_ssi_device::write_c0nx(uint8_t offset, uint8_t data)
{
- if (m_started)
+ if (BIT(offset, 3))
+ m_acia->write(offset & 3, data);
+ else
+ m_alt_bank = true;
+}
+
+void a2bus_ssc_device::acia_irq_w(int state)
+{
+ if (machine().ioport().safe_to_read())
{
- if (!(m_dsw2->read() & 4))
+ if (!(m_dswx->read() & 4))
{
if (state)
{
@@ -230,3 +436,13 @@ WRITE_LINE_MEMBER( a2bus_ssc_device::acia_irq_w )
}
}
}
+
+} // anonymous namespace
+
+
+//**************************************************************************
+// GLOBAL VARIABLES
+//**************************************************************************
+
+DEFINE_DEVICE_TYPE_PRIVATE(A2BUS_SSC, device_a2bus_card_interface, a2bus_ssc_device, "a2ssc", "Apple Super Serial Card")
+DEFINE_DEVICE_TYPE_PRIVATE(APRICORN_SSI, device_a2bus_card_interface, apricorn_ssi_device, "aprissi", "Apricorn Super Serial Imager")
diff --git a/src/devices/bus/a2bus/a2ssc.h b/src/devices/bus/a2bus/a2ssc.h
index 0e298bc7d96..9cc41e53970 100644
--- a/src/devices/bus/a2bus/a2ssc.h
+++ b/src/devices/bus/a2bus/a2ssc.h
@@ -12,46 +12,9 @@
#define MAME_BUS_A2BUS_A2SSC_H
#include "a2bus.h"
-#include "machine/mos6551.h"
-//**************************************************************************
-// TYPE DEFINITIONS
-//**************************************************************************
-
-class a2bus_ssc_device:
- public device_t,
- public device_a2bus_card_interface
-{
-public:
- // construction/destruction
- a2bus_ssc_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
-
-protected:
- a2bus_ssc_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 ioport_constructor device_input_ports() const override;
-
- 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;
-
- required_ioport m_dsw1, m_dsw2;
-
- required_device<mos6551_device> m_acia;
-
-private:
- DECLARE_WRITE_LINE_MEMBER( acia_irq_w );
-
- uint8_t *m_rom;
- bool m_started;
-};
-
-// device type definition
-DECLARE_DEVICE_TYPE(A2BUS_SSC, a2bus_ssc_device)
+// device type declarations
+DECLARE_DEVICE_TYPE(A2BUS_SSC, device_a2bus_card_interface)
+DECLARE_DEVICE_TYPE(APRICORN_SSI, device_a2bus_card_interface)
#endif // MAME_BUS_A2BUS_A2SSC_H
diff --git a/src/devices/bus/a2bus/a2superdrive.cpp b/src/devices/bus/a2bus/a2superdrive.cpp
new file mode 100644
index 00000000000..922c9bc0403
--- /dev/null
+++ b/src/devices/bus/a2bus/a2superdrive.cpp
@@ -0,0 +1,347 @@
+// license:BSD-3-Clause
+// copyright-holders:Kelvin Sherlock
+/*********************************************************************
+
+ a2superdrive.cpp
+
+ Apple II 3.5" Disk Controller Card (Apple, 1991)
+ aka SuperDrive Card, aka NuMustang (development codename)
+
+ 32k ram
+ 32k eprom
+ 15.6672Mhz crystal
+ SWIM 1 Chip (1987)
+ 65c02 processor (~2mhz)
+
+ uc:
+
+ $0000-$7fff is ram
+ $8000-$ffff is rom
+ $0a00-$0aff is i/o
+
+ apple 2 bus:
+
+ $c0n0-$c0nf - memory latch. selects a 1k window for $c800-$cbff
+ $cn00-$cnff - uc ram ($7b00-$7bff)
+ $c800-$cbff - uc ram ($0000-$3cff, based on memory latch)
+ $cc00-$cfff - uc ram ($7c00-$7fff)
+
+ spamming Control-D while booting will invoke the built-in
+ diagnostics. An alternative entry is Cx0DG from the monitor.
+
+*********************************************************************/
+
+
+#include "emu.h"
+#include "a2superdrive.h"
+#include "cpu/m6502/w65c02s.h"
+#include "machine/applefdintf.h"
+#include "machine/swim1.h"
+#include "imagedev/floppy.h"
+
+#define C16M (15.6672_MHz_XTAL)
+
+
+namespace {
+
+
+//**************************************************************************
+// TYPE DEFINITIONS
+//**************************************************************************
+
+class a2bus_superdrive_device:
+ public device_t,
+ public device_a2bus_card_interface
+{
+public:
+ // construction/destruction
+ a2bus_superdrive_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
+
+protected:
+ a2bus_superdrive_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock);
+
+ 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;
+ virtual const tiny_rom_entry *device_rom_region() const override ATTR_COLD;
+
+ // 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;
+ virtual void write_cnxx(uint8_t offset, uint8_t data) override;
+ virtual uint8_t read_c800(uint16_t offset) override;
+ virtual void write_c800(uint16_t offset, uint8_t data) override;
+
+private:
+ void w65c02_mem(address_map &map) ATTR_COLD;
+
+ void w65c02_w(offs_t offset, uint8_t value);
+ uint8_t w65c02_r(offs_t offset);
+
+ void phases_w(uint8_t phases);
+ void sel35_w(int sel35);
+ void devsel_w(uint8_t devsel);
+ void hdsel_w(int hdsel);
+
+
+ required_device<cpu_device> m_65c02;
+ required_region_ptr<u8> m_rom;
+ required_shared_ptr<u8> m_ram;
+
+ required_device<applefdintf_device> m_fdc;
+
+ uint8_t m_bank_select;
+ uint8_t m_side;
+};
+
+
+#define SUPERDRIVE_ROM_REGION "superdrive_rom"
+
+
+ROM_START( superdrive )
+ ROM_REGION(0x8000, SUPERDRIVE_ROM_REGION, 0)
+ ROM_LOAD( "341-0438-a.bin", 0x0000, 0x08000, CRC(c73ff25b) SHA1(440c3f84176c7b9f542da0b6ddf4fb13ec326c46) )
+ROM_END
+
+
+const tiny_rom_entry *a2bus_superdrive_device::device_rom_region() const
+{
+ return ROM_NAME( superdrive );
+}
+
+void a2bus_superdrive_device::w65c02_mem(address_map &map)
+{
+ map(0x0000, 0x7fff).ram().share(m_ram);
+ map(0x0a00, 0x0aff).rw(FUNC(a2bus_superdrive_device::w65c02_r), FUNC(a2bus_superdrive_device::w65c02_w));
+ map(0x8000, 0xffff).rom().region(SUPERDRIVE_ROM_REGION, 0x0000);
+}
+
+
+void a2bus_superdrive_device::device_add_mconfig(machine_config &config)
+{
+
+ W65C02S(config, m_65c02, DERIVED_CLOCK(2, 7)); /* ~ 2.046 MHz */
+ m_65c02->set_addrmap(AS_PROGRAM, &a2bus_superdrive_device::w65c02_mem);
+
+ SWIM1(config, m_fdc, C16M);
+
+ applefdintf_device::add_35_hd(config, "fdc:0");
+ applefdintf_device::add_35_hd(config, "fdc:1");
+
+ m_fdc->devsel_cb().set(FUNC(a2bus_superdrive_device::devsel_w));
+ m_fdc->hdsel_cb().set(FUNC(a2bus_superdrive_device::hdsel_w));
+ m_fdc->phases_cb().set(FUNC(a2bus_superdrive_device::phases_w));
+ m_fdc->sel35_cb().set(FUNC(a2bus_superdrive_device::sel35_w));
+}
+
+
+
+a2bus_superdrive_device::a2bus_superdrive_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_65c02(*this, "superdrive_65c02"),
+ m_rom(*this, SUPERDRIVE_ROM_REGION),
+ m_ram(*this, "superdrive_ram"),
+ m_fdc(*this, "fdc"),
+ m_bank_select(0),
+ m_side(0)
+{ }
+
+a2bus_superdrive_device::a2bus_superdrive_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock):
+ a2bus_superdrive_device(mconfig, A2BUS_SUPERDRIVE, tag, owner, clock)
+{ }
+
+void a2bus_superdrive_device::device_start()
+{
+ save_item(NAME(m_bank_select));
+ save_item(NAME(m_side));
+}
+
+
+void a2bus_superdrive_device::device_reset()
+{
+ m_bank_select = 0;
+ m_side = 0;
+}
+
+
+// overrides of standard a2bus slot functions
+uint8_t a2bus_superdrive_device::read_c0nx(uint8_t offset)
+{
+ if (machine().side_effects_disabled()) return 0;
+
+ m_bank_select = offset & 0x0f;
+ return 0;
+}
+
+void a2bus_superdrive_device::write_c0nx(uint8_t offset, uint8_t data)
+{
+ m_bank_select = offset & 0x0f;
+}
+
+uint8_t a2bus_superdrive_device::read_cnxx(uint8_t offset)
+{
+ return m_ram[0x7b00 + offset];
+}
+
+void a2bus_superdrive_device::write_cnxx(uint8_t offset, uint8_t data)
+{
+ //m_ram[0x7b00 + offset] = data;
+}
+
+/*
+ * $c800 - $cbff is uc RAM, controlled via c0nx
+ * $cc00 - $cfff is uc RAM, hardcoded to $7c00 - $7fff
+ */
+uint8_t a2bus_superdrive_device::read_c800(uint16_t offset)
+{
+ unsigned address;
+
+ if (offset < 0x400)
+ address = (m_bank_select << 10) + offset;
+ else
+ address = 0x7c00 + offset - 0x400;
+
+ return m_ram[address];
+}
+
+void a2bus_superdrive_device::write_c800(uint16_t offset, uint8_t data)
+{
+ unsigned address;
+
+ if (offset < 0x400)
+ address = (m_bank_select << 10) + offset;
+ else
+ address = 0x7c00 + offset - 0x400;
+
+ m_ram[address] = data;
+}
+
+
+/* uc 65c02 i/o at $0a00 */
+void a2bus_superdrive_device::w65c02_w(offs_t offset, uint8_t value)
+{
+ // $00-$0f = swim registers
+ // $40 = head sel low
+ // $41 = head sel high
+ // $80 = diagnostic led on
+ // $81 = diagnostic led off
+
+ floppy_image_device *floppy = nullptr;
+
+ if (offset < 16)
+ {
+ m_fdc->write(offset, value);
+ return;
+ }
+
+ switch (offset)
+ {
+ case 0x40:
+ m_side = 0;
+ floppy = m_fdc->get_floppy();
+ if (floppy) floppy->ss_w(m_side);
+ break;
+
+ case 0x41:
+ m_side = 1;
+ floppy = m_fdc->get_floppy();
+ if (floppy) floppy->ss_w(m_side);
+ break;
+
+ case 0x80:
+ logerror("LED on\n");
+ break;
+
+ case 0x81:
+ logerror("LED off\n");
+ break;
+
+ default:
+ logerror("write($0a%02x,%02x)\n", offset, value);
+ break;
+ }
+}
+
+uint8_t a2bus_superdrive_device::w65c02_r(offs_t offset)
+{
+ floppy_image_device *floppy = nullptr;
+
+ if (offset < 16)
+ return m_fdc->read(offset);
+
+ if (machine().side_effects_disabled()) return 0;
+
+ switch (offset)
+ {
+ case 0x40:
+ m_side = 0;
+ floppy = m_fdc->get_floppy();
+ if (floppy) floppy->ss_w(m_side);
+ break;
+
+ case 0x41:
+ m_side = 1;
+ floppy = m_fdc->get_floppy();
+ if (floppy) floppy->ss_w(m_side);
+ break;
+
+ case 0x80:
+ logerror("LED on\n");
+ break;
+
+ case 0x81:
+ logerror("LED off\n");
+ break;
+
+ default:
+ logerror("read($0a%02x)\n", offset);
+ break;
+ }
+ return 0;
+}
+
+
+void a2bus_superdrive_device::devsel_w(uint8_t devsel)
+{
+ floppy_image_device *floppy = nullptr;
+
+ switch (devsel)
+ {
+ case 1:
+ floppy = m_fdc->subdevice<floppy_connector>("0")->get_device();
+ break;
+ case 2:
+ floppy = m_fdc->subdevice<floppy_connector>("1")->get_device();
+ break;
+ }
+
+ m_fdc->set_floppy(floppy);
+}
+
+void a2bus_superdrive_device::phases_w(uint8_t phases)
+{
+ floppy_image_device *floppy = m_fdc->get_floppy();
+ if (floppy)
+ floppy->seek_phase_w(phases);
+}
+
+
+void a2bus_superdrive_device::sel35_w(int sel35)
+{
+}
+
+void a2bus_superdrive_device::hdsel_w(int hdsel)
+{
+ /* Q3/HDSEL pin (ISM MODE register bit 5) is used to control the clock speed */
+ /* MFM runs at 15.6672, GCR at 15.6672/2 */
+
+ m_fdc->set_clock_scale( hdsel ? 1.0 : 0.5);
+}
+
+} // anonymous namespace
+
+
+DEFINE_DEVICE_TYPE_PRIVATE(A2BUS_SUPERDRIVE, device_a2bus_card_interface, a2bus_superdrive_device, "a2superdrive", "Apple II 3.5\" Disk Controller Card")
+
diff --git a/src/devices/bus/a2bus/a2superdrive.h b/src/devices/bus/a2bus/a2superdrive.h
new file mode 100644
index 00000000000..f99a6272019
--- /dev/null
+++ b/src/devices/bus/a2bus/a2superdrive.h
@@ -0,0 +1,22 @@
+// license:BSD-3-Clause
+// copyright-holders:Kelvin Sherlock
+/*********************************************************************
+
+ a2superdrive.h
+
+ Implementation of the Apple II 3.5 Disk Controller Card
+
+*********************************************************************/
+
+#ifndef MAME_BUS_A2BUS_A2SUPERDRIVE_H
+#define MAME_BUS_A2BUS_A2SUPERDRIVE_H
+
+#pragma once
+
+#include "a2bus.h"
+
+
+// device type definition
+DECLARE_DEVICE_TYPE(A2BUS_SUPERDRIVE, device_a2bus_card_interface)
+
+#endif // MAME_BUS_A2BUS_A2SUPERDRIVE_H
diff --git a/src/devices/bus/a2bus/a2swyft.cpp b/src/devices/bus/a2bus/a2swyft.cpp
index ba4cb8ec46e..7b53ed48029 100644
--- a/src/devices/bus/a2bus/a2swyft.cpp
+++ b/src/devices/bus/a2bus/a2swyft.cpp
@@ -12,16 +12,12 @@
#include "a2swyft.h"
+namespace {
+
/***************************************************************************
PARAMETERS
***************************************************************************/
-//**************************************************************************
-// GLOBAL VARIABLES
-//**************************************************************************
-
-DEFINE_DEVICE_TYPE(A2BUS_SWYFT, a2bus_swyft_device, "a2swyft", "IAI SwyftCard")
-
#define SWYFT_ROM_REGION "swyft_rom"
ROM_START( swyft )
@@ -31,6 +27,39 @@ ROM_START( swyft )
ROM_LOAD( "swyft_pal16r4.jed", 0x0000, 0x08EF, CRC(462a6938) SHA1(38be885539cf91423a246378c411ac8b2f150ec6) ) // swyft3.pal derived by D. Elvey, works as a replacement pal (original is protected?)
ROM_END
+//**************************************************************************
+// TYPE DEFINITIONS
+//**************************************************************************
+
+class a2bus_swyft_device:
+ public device_t,
+ public device_a2bus_card_interface
+{
+public:
+ // construction/destruction
+ a2bus_swyft_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
+
+ virtual const tiny_rom_entry *device_rom_region() const override ATTR_COLD;
+
+protected:
+ a2bus_swyft_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock);
+
+ virtual void device_start() override ATTR_COLD;
+ virtual void device_reset() override ATTR_COLD;
+
+ 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 uint16_t inh_start() override { return 0xd000; }
+ virtual uint16_t inh_end() override { return 0xffff; }
+ virtual int inh_type() override;
+
+private:
+ required_region_ptr<uint8_t> m_rom;
+ int m_rombank = 0;
+ int m_inh_state = 0;
+};
+
//-------------------------------------------------
// rom_region - device-specific ROM region
//-------------------------------------------------
@@ -51,7 +80,8 @@ a2bus_swyft_device::a2bus_swyft_device(const machine_config &mconfig, const char
a2bus_swyft_device::a2bus_swyft_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_rombank(0), m_inh_state(0)
+ device_a2bus_card_interface(mconfig, *this),
+ m_rom(*this, SWYFT_ROM_REGION)
{
}
@@ -61,8 +91,6 @@ a2bus_swyft_device::a2bus_swyft_device(const machine_config &mconfig, device_typ
void a2bus_swyft_device::device_start()
{
- m_rom = device().machine().root_device().memregion(this->subtag(SWYFT_ROM_REGION).c_str())->base();
-
save_item(NAME(m_rombank));
}
@@ -142,3 +170,12 @@ int a2bus_swyft_device::inh_type()
{
return m_inh_state;
}
+
+} // anonymous namespace
+
+
+//**************************************************************************
+// GLOBAL VARIABLES
+//**************************************************************************
+
+DEFINE_DEVICE_TYPE_PRIVATE(A2BUS_SWYFT, device_a2bus_card_interface, a2bus_swyft_device, "a2swyft", "IAI SwyftCard")
diff --git a/src/devices/bus/a2bus/a2swyft.h b/src/devices/bus/a2bus/a2swyft.h
index d160fb77a4c..dbf3c02827a 100644
--- a/src/devices/bus/a2bus/a2swyft.h
+++ b/src/devices/bus/a2bus/a2swyft.h
@@ -15,40 +15,7 @@
#include "a2bus.h"
-//**************************************************************************
-// TYPE DEFINITIONS
-//**************************************************************************
-
-class a2bus_swyft_device:
- public device_t,
- public device_a2bus_card_interface
-{
-public:
- // construction/destruction
- a2bus_swyft_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
-
- virtual const tiny_rom_entry *device_rom_region() const override;
-
-protected:
- a2bus_swyft_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 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 uint16_t inh_start() override { return 0xd000; }
- virtual uint16_t inh_end() override { return 0xffff; }
- virtual int inh_type() override;
-
-private:
- uint8_t *m_rom;
- int m_rombank;
- int m_inh_state;
-};
-
// device type definition
-DECLARE_DEVICE_TYPE(A2BUS_SWYFT, a2bus_swyft_device)
+DECLARE_DEVICE_TYPE(A2BUS_SWYFT, device_a2bus_card_interface)
#endif // MAME_BUS_A2BUS_A2SWYFT_H
diff --git a/src/devices/bus/a2bus/a2themill.cpp b/src/devices/bus/a2bus/a2themill.cpp
index 14474662ef8..44925c4c68b 100644
--- a/src/devices/bus/a2bus/a2themill.cpp
+++ b/src/devices/bus/a2bus/a2themill.cpp
@@ -18,8 +18,6 @@
ProDOS "Stellation The Mill Disk.po" requires Mill in slot 2; boot
the disc and type "-DEMO1" and press Enter to launch the simple demo.
- TODO: Add DIP switch to select standard and OS-9 modes.
-
*********************************************************************/
#include "emu.h"
@@ -43,6 +41,23 @@ void a2bus_themill_device::m6809_mem(address_map &map)
map(0x0000, 0xffff).rw(FUNC(a2bus_themill_device::dma_r), FUNC(a2bus_themill_device::dma_w));
}
+static INPUT_PORTS_START( themill )
+ PORT_START("MILLCFG")
+ PORT_DIPNAME( 0x01, 0x01, "6809 Mapping" )
+ PORT_DIPSETTING( 0x00, "Original")
+ PORT_DIPSETTING( 0x01, "OS-9")
+INPUT_PORTS_END
+
+//-------------------------------------------------
+// input_ports - device-specific input ports
+//-------------------------------------------------
+
+ioport_constructor a2bus_themill_device::device_input_ports() const
+{
+ return INPUT_PORTS_NAME( themill );
+}
+
+
/***************************************************************************
FUNCTION PROTOTYPES
***************************************************************************/
@@ -65,6 +80,7 @@ a2bus_themill_device::a2bus_themill_device(const machine_config &mconfig, device
: device_t(mconfig, type, tag, owner, clock)
, device_a2bus_card_interface(mconfig, *this)
, m_6809(*this, "m6809")
+ , m_cfgsw(*this, "MILLCFG")
, m_bEnabled(false)
, m_flipAddrSpace(false)
, m_6809Mode(false)
@@ -93,7 +109,7 @@ void a2bus_themill_device::device_reset()
{
m_bEnabled = false;
m_flipAddrSpace = false;
- m_6809Mode = true;
+ m_6809Mode = (m_cfgsw->read() & 1) ? true : false;
m_status = 0xc0; // OS9 loader relies on this
m_6809->set_input_line(INPUT_LINE_HALT, ASSERT_LINE);
m_6809->set_input_line(INPUT_LINE_RESET, ASSERT_LINE);
@@ -226,7 +242,7 @@ void a2bus_themill_device::write_c0nx(uint8_t offset, uint8_t data)
}
}
-READ8_MEMBER( a2bus_themill_device::dma_r )
+uint8_t a2bus_themill_device::dma_r(offs_t offset)
{
// MAME startup ordering has the 6809 free-running at boot, which is undesirable
if (!m_bEnabled)
@@ -277,7 +293,7 @@ READ8_MEMBER( a2bus_themill_device::dma_r )
// dma_w -
//-------------------------------------------------
-WRITE8_MEMBER( a2bus_themill_device::dma_w )
+void a2bus_themill_device::dma_w(offs_t offset, uint8_t data)
{
if (m_6809Mode)
{
diff --git a/src/devices/bus/a2bus/a2themill.h b/src/devices/bus/a2bus/a2themill.h
index 113ccdbb9ec..c46ecdedab8 100644
--- a/src/devices/bus/a2bus/a2themill.h
+++ b/src/devices/bus/a2bus/a2themill.h
@@ -30,9 +30,10 @@ public:
protected:
a2bus_themill_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 device_start() override ATTR_COLD;
+ virtual void device_reset() override ATTR_COLD;
+ virtual void device_add_mconfig(machine_config &config) override ATTR_COLD;
+ virtual ioport_constructor device_input_ports() const override ATTR_COLD;
// overrides of standard a2bus slot functions
virtual uint8_t read_c0nx(uint8_t offset) override;
@@ -41,15 +42,17 @@ protected:
private:
required_device<cpu_device> m_6809;
+ required_ioport m_cfgsw;
+
bool m_bEnabled;
bool m_flipAddrSpace;
bool m_6809Mode;
uint8_t m_status;
- DECLARE_READ8_MEMBER( dma_r );
- DECLARE_WRITE8_MEMBER( dma_w );
+ uint8_t dma_r(offs_t offset);
+ void dma_w(offs_t offset, uint8_t data);
- void m6809_mem(address_map &map);
+ void m6809_mem(address_map &map) ATTR_COLD;
};
// device type definition
diff --git a/src/devices/bus/a2bus/a2thunderclock.cpp b/src/devices/bus/a2bus/a2thunderclock.cpp
index 69cc87a07ff..f671af3e2e1 100644
--- a/src/devices/bus/a2bus/a2thunderclock.cpp
+++ b/src/devices/bus/a2bus/a2thunderclock.cpp
@@ -28,16 +28,15 @@
#include "emu.h"
#include "a2thunderclock.h"
+#include "machine/upd1990a.h"
+
+
+namespace {
+
/***************************************************************************
PARAMETERS
***************************************************************************/
-//**************************************************************************
-// GLOBAL VARIABLES
-//**************************************************************************
-
-DEFINE_DEVICE_TYPE(A2BUS_THUNDERCLOCK, a2bus_thunderclock_device, "a2thunpl", "ThunderWare ThunderClock Plus")
-
#define THUNDERCLOCK_ROM_REGION "thunclk_rom"
#define THUNDERCLOCK_UPD1990_TAG "thunclk_upd"
@@ -46,6 +45,41 @@ ROM_START( thunderclock )
ROM_LOAD( "thunderclock plus rom.bin", 0x0000, 0x0800, CRC(1b99c4e3) SHA1(60f434f5325899d7ea257a6e56e6f53eae65146a) )
ROM_END
+//**************************************************************************
+// TYPE DEFINITIONS
+//**************************************************************************
+
+class a2bus_thunderclock_device:
+ public device_t,
+ public device_a2bus_card_interface
+{
+public:
+ // construction/destruction
+ a2bus_thunderclock_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
+
+protected:
+ a2bus_thunderclock_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock);
+
+ 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;
+ virtual const tiny_rom_entry *device_rom_region() const override ATTR_COLD;
+
+ // 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;
+ virtual uint8_t read_c800(uint16_t offset) override;
+
+ required_device<upd1990a_device> m_upd1990ac;
+ required_region_ptr<uint8_t> m_rom;
+
+private:
+ void upd_dataout_w(int state);
+
+ int m_dataout;
+};
+
/***************************************************************************
FUNCTION PROTOTYPES
***************************************************************************/
@@ -56,7 +90,7 @@ ROM_END
void a2bus_thunderclock_device::device_add_mconfig(machine_config &config)
{
- UPD1990A(config, m_upd1990ac, 1021800);
+ UPD1990A(config, m_upd1990ac, 32.768_kHz_XTAL);
m_upd1990ac->data_callback().set(FUNC(a2bus_thunderclock_device::upd_dataout_w));
}
@@ -76,7 +110,9 @@ const tiny_rom_entry *a2bus_thunderclock_device::device_rom_region() const
a2bus_thunderclock_device::a2bus_thunderclock_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_upd1990ac(*this, THUNDERCLOCK_UPD1990_TAG), m_rom(nullptr), m_dataout(0)
+ m_upd1990ac(*this, THUNDERCLOCK_UPD1990_TAG),
+ m_rom(*this, THUNDERCLOCK_ROM_REGION),
+ m_dataout(0)
{
}
@@ -91,8 +127,6 @@ a2bus_thunderclock_device::a2bus_thunderclock_device(const machine_config &mconf
void a2bus_thunderclock_device::device_start()
{
- m_rom = device().machine().root_device().memregion(this->subtag(THUNDERCLOCK_ROM_REGION).c_str())->base();
-
save_item(NAME(m_dataout));
}
@@ -158,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)
{
@@ -169,3 +203,12 @@ WRITE_LINE_MEMBER( a2bus_thunderclock_device::upd_dataout_w )
m_dataout = 0;
}
}
+
+} // anonymous namespace
+
+
+//**************************************************************************
+// GLOBAL VARIABLES
+//**************************************************************************
+
+DEFINE_DEVICE_TYPE_PRIVATE(A2BUS_THUNDERCLOCK, device_a2bus_card_interface, a2bus_thunderclock_device, "a2thunpl", "ThunderWare ThunderClock Plus")
diff --git a/src/devices/bus/a2bus/a2thunderclock.h b/src/devices/bus/a2bus/a2thunderclock.h
index 2f1e908a1cd..6c5025f0789 100644
--- a/src/devices/bus/a2bus/a2thunderclock.h
+++ b/src/devices/bus/a2bus/a2thunderclock.h
@@ -14,44 +14,8 @@
#pragma once
#include "a2bus.h"
-#include "machine/upd1990a.h"
-
-//**************************************************************************
-// TYPE DEFINITIONS
-//**************************************************************************
-
-class a2bus_thunderclock_device:
- public device_t,
- public device_a2bus_card_interface
-{
-public:
- // construction/destruction
- a2bus_thunderclock_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
-
-protected:
- a2bus_thunderclock_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;
- virtual uint8_t read_c800(uint16_t offset) override;
-
- required_device<upd1990a_device> m_upd1990ac;
-
-private:
- DECLARE_WRITE_LINE_MEMBER( upd_dataout_w );
-
- uint8_t *m_rom;
- int m_dataout;
-};
// device type definition
-DECLARE_DEVICE_TYPE(A2BUS_THUNDERCLOCK, a2bus_thunderclock_device)
+DECLARE_DEVICE_TYPE(A2BUS_THUNDERCLOCK, device_a2bus_card_interface)
#endif // MAME_BUS_A2BUS_A2THUNDERCLOCK_H
diff --git a/src/devices/bus/a2bus/a2ultraterm.cpp b/src/devices/bus/a2bus/a2ultraterm.cpp
index fd8fb2a895a..7ed7ca905f3 100644
--- a/src/devices/bus/a2bus/a2ultraterm.cpp
+++ b/src/devices/bus/a2bus/a2ultraterm.cpp
@@ -29,20 +29,18 @@
#include "emu.h"
#include "a2ultraterm.h"
+
+#include "video/mc6845.h"
+
#include "screen.h"
+namespace {
+
/***************************************************************************
PARAMETERS
***************************************************************************/
-//**************************************************************************
-// GLOBAL VARIABLES
-//**************************************************************************
-
-DEFINE_DEVICE_TYPE(A2BUS_ULTRATERM, a2bus_ultraterm_device, "a2ulttrm", "Videx UltraTerm (original)")
-DEFINE_DEVICE_TYPE(A2BUS_ULTRATERMENH, a2bus_ultratermenh_device, "a2ultrme", "Videx UltraTerm (enhanced //e)")
-
#define ULTRATERM_ROM_REGION "uterm_rom"
#define ULTRATERM_GFX_REGION "uterm_gfx"
#define ULTRATERM_SCREEN_NAME "uterm_screen"
@@ -65,7 +63,7 @@ DEFINE_DEVICE_TYPE(A2BUS_ULTRATERMENH, a2bus_ultratermenh_device, "a2ultrme", "V
#define CT2_HLBIT7L (0x01)
-static const rgb_t ultraterm_palette[4] =
+const rgb_t ultraterm_palette[4] =
{
rgb_t(0x00,0x00,0x00),
rgb_t(0x55,0x55,0x55),
@@ -96,6 +94,60 @@ ROM_START( a2ultratermenh )
ROM_LOAD( "ult_251c.jed", 0x000000, 0x000305, CRC(12fabb0d) SHA1(d4a36837cb98bb65f7ddef7455eb5a7f8e648a82) )
ROM_END
+//**************************************************************************
+// TYPE DEFINITIONS
+//**************************************************************************
+
+class a2bus_videx160_device:
+ public device_t,
+ public device_a2bus_card_interface
+{
+protected:
+ // construction/destruction
+ a2bus_videx160_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock);
+
+ 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;
+
+ // 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;
+ virtual void write_cnxx(uint8_t offset, uint8_t data) override;
+ virtual uint8_t read_c800(uint16_t offset) override;
+ virtual void write_c800(uint16_t offset, uint8_t data) override;
+
+ uint8_t m_ram[256*16];
+ int m_framecnt;
+ uint8_t m_ctrl1, m_ctrl2;
+
+ required_device<mc6845_device> m_crtc;
+ required_region_ptr<uint8_t> m_rom, m_chrrom;
+
+private:
+ void vsync_changed(int state);
+ MC6845_UPDATE_ROW(crtc_update_row);
+
+ int m_rambank;
+};
+
+class a2bus_ultraterm_device : public a2bus_videx160_device
+{
+public:
+ a2bus_ultraterm_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
+
+ virtual const tiny_rom_entry *device_rom_region() const override ATTR_COLD;
+};
+
+class a2bus_ultratermenh_device : public a2bus_videx160_device
+{
+public:
+ a2bus_ultratermenh_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
+
+ virtual const tiny_rom_entry *device_rom_region() const override ATTR_COLD;
+};
+
/***************************************************************************
FUNCTION PROTOTYPES
***************************************************************************/
@@ -114,7 +166,7 @@ void a2bus_videx160_device::device_add_mconfig(machine_config &config)
m_crtc->set_screen(ULTRATERM_SCREEN_NAME);
m_crtc->set_show_border_area(false);
m_crtc->set_char_width(8);
- m_crtc->set_update_row_callback(FUNC(a2bus_videx160_device::crtc_update_row), this);
+ m_crtc->set_update_row_callback(FUNC(a2bus_videx160_device::crtc_update_row));
m_crtc->out_vsync_callback().set(FUNC(a2bus_videx160_device::vsync_changed));
}
@@ -138,8 +190,12 @@ const tiny_rom_entry *a2bus_ultratermenh_device::device_rom_region() const
a2bus_videx160_device::a2bus_videx160_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_chrrom(nullptr), m_framecnt(0), m_ctrl1(0), m_ctrl2(0),
- m_crtc(*this, ULTRATERM_MC6845_NAME), m_rambank(0)
+ device_a2bus_card_interface(mconfig, *this),
+ m_framecnt(0), m_ctrl1(0), m_ctrl2(0),
+ m_crtc(*this, ULTRATERM_MC6845_NAME),
+ m_rom(*this, ULTRATERM_ROM_REGION),
+ m_chrrom(*this, ULTRATERM_GFX_REGION),
+ m_rambank(0)
{
}
@@ -159,10 +215,6 @@ a2bus_ultratermenh_device::a2bus_ultratermenh_device(const machine_config &mconf
void a2bus_videx160_device::device_start()
{
- m_rom = machine().root_device().memregion(this->subtag(ULTRATERM_ROM_REGION).c_str())->base();
-
- m_chrrom = machine().root_device().memregion(this->subtag(ULTRATERM_GFX_REGION).c_str())->base();
-
memset(m_ram, 0, 256*16);
save_item(NAME(m_ram));
@@ -304,11 +356,10 @@ void a2bus_videx160_device::write_c800(uint16_t offset, uint8_t data)
MC6845_UPDATE_ROW( a2bus_videx160_device::crtc_update_row )
{
- uint32_t *p = &bitmap.pix32(y);
+ uint32_t *p = &bitmap.pix(y);
uint16_t chr_base = ra;
- int i;
- for ( i = 0; i < x_count; i++ )
+ for ( int i = 0; i < x_count; i++ )
{
uint16_t offset = ( ma + i );
uint8_t chr = m_ram[ offset ];
@@ -385,10 +436,20 @@ 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 )
{
m_framecnt++;
}
}
+
+} // anonymous namespace
+
+
+//**************************************************************************
+// GLOBAL VARIABLES
+//**************************************************************************
+
+DEFINE_DEVICE_TYPE_PRIVATE(A2BUS_ULTRATERM, device_a2bus_card_interface, a2bus_ultraterm_device, "a2ulttrm", "Videx UltraTerm (original)")
+DEFINE_DEVICE_TYPE_PRIVATE(A2BUS_ULTRATERMENH, device_a2bus_card_interface, a2bus_ultratermenh_device, "a2ultrme", "Videx UltraTerm (enhanced //e)")
diff --git a/src/devices/bus/a2bus/a2ultraterm.h b/src/devices/bus/a2bus/a2ultraterm.h
index b7dd4c9d3f5..2197ea9f446 100644
--- a/src/devices/bus/a2bus/a2ultraterm.h
+++ b/src/devices/bus/a2bus/a2ultraterm.h
@@ -14,64 +14,9 @@
#pragma once
#include "a2bus.h"
-#include "video/mc6845.h"
-//**************************************************************************
-// TYPE DEFINITIONS
-//**************************************************************************
-
-class a2bus_videx160_device:
- public device_t,
- public device_a2bus_card_interface
-{
-protected:
- // construction/destruction
- a2bus_videx160_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
- 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 void write_cnxx(uint8_t offset, uint8_t data) override;
- virtual uint8_t read_c800(uint16_t offset) override;
- virtual void write_c800(uint16_t offset, uint8_t data) override;
-
- uint8_t *m_rom, *m_chrrom;
- uint8_t m_ram[256*16];
- int m_framecnt;
- uint8_t m_ctrl1, m_ctrl2;
-
- required_device<mc6845_device> m_crtc;
-
-private:
- DECLARE_WRITE_LINE_MEMBER(vsync_changed);
- MC6845_UPDATE_ROW(crtc_update_row);
-
- int m_rambank;
-};
-
-class a2bus_ultraterm_device : public a2bus_videx160_device
-{
-public:
- a2bus_ultraterm_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 a2bus_ultratermenh_device : public a2bus_videx160_device
-{
-public:
- a2bus_ultratermenh_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(A2BUS_ULTRATERM, a2bus_ultraterm_device)
-DECLARE_DEVICE_TYPE(A2BUS_ULTRATERMENH, a2bus_ultratermenh_device)
+// device type declaration
+DECLARE_DEVICE_TYPE(A2BUS_ULTRATERM, device_a2bus_card_interface)
+DECLARE_DEVICE_TYPE(A2BUS_ULTRATERMENH, device_a2bus_card_interface)
#endif // MAME_BUS_A2BUS_A2ULTRATERM_H
diff --git a/src/devices/bus/a2bus/a2videoterm.cpp b/src/devices/bus/a2bus/a2videoterm.cpp
index 64d614bc60c..6fa2ccad74b 100644
--- a/src/devices/bus/a2bus/a2videoterm.cpp
+++ b/src/devices/bus/a2bus/a2videoterm.cpp
@@ -24,23 +24,18 @@
#include "emu.h"
#include "a2videoterm.h"
+
+#include "video/mc6845.h"
+
#include "screen.h"
+namespace {
+
/***************************************************************************
PARAMETERS
***************************************************************************/
-//**************************************************************************
-// GLOBAL VARIABLES
-//**************************************************************************
-
-DEFINE_DEVICE_TYPE(A2BUS_VIDEOTERM, a2bus_videoterm_device, "a2vidtrm", "Videx Videoterm 80 Column Display")
-DEFINE_DEVICE_TYPE(A2BUS_IBSAP16, a2bus_ap16_device, "a2ap16", "IBS AP-16 80 column card")
-DEFINE_DEVICE_TYPE(A2BUS_IBSAP16ALT, a2bus_ap16alt_device, "a2ap16a", "IBS AP-16 80 column card (alt. version)")
-DEFINE_DEVICE_TYPE(A2BUS_VTC1, a2bus_vtc1_device, "a2vtc1", "unknown Videoterm clone")
-DEFINE_DEVICE_TYPE(A2BUS_AEVIEWMASTER80, a2bus_aevm80_device, "a2aevm80", "Applied Engineering Viewmaster 80")
-
#define VIDEOTERM_ROM_REGION "vterm_rom"
#define VIDEOTERM_GFX_REGION "vterm_gfx"
#define VIDEOTERM_SCREEN_NAME "vterm_screen"
@@ -101,6 +96,92 @@ ROM_START( a2aevm80 )
ROM_LOAD( "ae viewmaster 80 video rom.bin", 0x000000, 0x000800, CRC(4801ab90) SHA1(f90658ffee7740f3cb30ecef2e151f7dc6098833) )
ROM_END
+//**************************************************************************
+// TYPE DEFINITIONS
+//**************************************************************************
+
+class a2bus_videx80_device:
+ public device_t,
+ public device_a2bus_card_interface
+{
+protected:
+ // construction/destruction
+ a2bus_videx80_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock);
+
+ 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;
+
+ // 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;
+ virtual void write_cnxx(uint8_t offset, uint8_t data) override;
+ virtual uint8_t read_c800(uint16_t offset) override;
+ virtual void write_c800(uint16_t offset, uint8_t data) override;
+
+ uint8_t m_ram[512*4];
+
+ required_device<mc6845_device> m_crtc;
+ required_region_ptr<uint8_t> m_rom, m_chrrom;
+
+ MC6845_UPDATE_ROW(crtc_update_row);
+
+ int m_rambank;
+ uint8_t m_char_width;
+};
+
+class a2bus_videoterm_device : public a2bus_videx80_device
+{
+public:
+ a2bus_videoterm_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
+
+ virtual const tiny_rom_entry *device_rom_region() const override ATTR_COLD;
+};
+
+class a2bus_ap16_device : public a2bus_videx80_device
+{
+public:
+ a2bus_ap16_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
+
+ virtual void device_add_mconfig(machine_config &config) override ATTR_COLD;
+ virtual const tiny_rom_entry *device_rom_region() const override ATTR_COLD;
+
+protected:
+ virtual uint8_t read_cnxx(uint8_t offset) override;
+};
+
+
+class a2bus_ap16alt_device : public a2bus_videx80_device
+{
+public:
+ a2bus_ap16alt_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
+
+ virtual void device_add_mconfig(machine_config &config) override ATTR_COLD;
+ virtual const tiny_rom_entry *device_rom_region() const override ATTR_COLD;
+
+protected:
+ virtual uint8_t read_cnxx(uint8_t offset) override;
+};
+
+class a2bus_vtc1_device : public a2bus_videx80_device
+{
+public:
+ a2bus_vtc1_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
+
+ virtual void device_add_mconfig(machine_config &config) override ATTR_COLD;
+ virtual const tiny_rom_entry *device_rom_region() const override ATTR_COLD;
+};
+
+class a2bus_aevm80_device : public a2bus_videx80_device
+{
+public:
+ a2bus_aevm80_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
+
+ virtual void device_add_mconfig(machine_config &config) override ATTR_COLD;
+ virtual const tiny_rom_entry *device_rom_region() const override ATTR_COLD;
+};
+
/***************************************************************************
FUNCTION PROTOTYPES
***************************************************************************/
@@ -120,7 +201,7 @@ void a2bus_videx80_device::device_add_mconfig(machine_config &config)
m_crtc->set_screen(VIDEOTERM_SCREEN_NAME);
m_crtc->set_show_border_area(false);
m_crtc->set_char_width(9);
- m_crtc->set_update_row_callback(FUNC(a2bus_videx80_device::crtc_update_row), this);
+ m_crtc->set_update_row_callback(FUNC(a2bus_videx80_device::crtc_update_row));
}
void a2bus_ap16_device::device_add_mconfig(machine_config &config)
@@ -196,8 +277,10 @@ const tiny_rom_entry *a2bus_aevm80_device::device_rom_region() const
a2bus_videx80_device::a2bus_videx80_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_chrrom(nullptr),
+ device_a2bus_card_interface(mconfig, *this),
m_crtc(*this, VIDEOTERM_MC6845_NAME),
+ m_rom(*this, VIDEOTERM_ROM_REGION),
+ m_chrrom(*this, VIDEOTERM_GFX_REGION),
m_rambank(0),
m_char_width(9)
{
@@ -236,10 +319,6 @@ a2bus_aevm80_device::a2bus_aevm80_device(const machine_config &mconfig, const ch
void a2bus_videx80_device::device_start()
{
- m_rom = device().machine().root_device().memregion(this->subtag(VIDEOTERM_ROM_REGION).c_str())->base();
-
- m_chrrom = device().machine().root_device().memregion(this->subtag(VIDEOTERM_GFX_REGION).c_str())->base();
-
memset(m_ram, 0, 4*512);
save_item(NAME(m_ram));
@@ -347,7 +426,7 @@ void a2bus_videx80_device::write_c800(uint16_t offset, uint8_t data)
MC6845_UPDATE_ROW( a2bus_videx80_device::crtc_update_row )
{
- uint32_t *p = &bitmap.pix32(y);
+ uint32_t *p = &bitmap.pix(y);
uint16_t chr_base = ra; //( ra & 0x08 ) ? 0x800 | ( ra & 0x07 ) : ra;
for (int i = 0; i < x_count; i++)
@@ -368,3 +447,16 @@ MC6845_UPDATE_ROW( a2bus_videx80_device::crtc_update_row )
}
}
}
+
+} // anonymous namespace
+
+
+//**************************************************************************
+// GLOBAL VARIABLES
+//**************************************************************************
+
+DEFINE_DEVICE_TYPE_PRIVATE(A2BUS_VIDEOTERM, device_a2bus_card_interface, a2bus_videoterm_device, "a2vidtrm", "Videx Videoterm 80 Column Display")
+DEFINE_DEVICE_TYPE_PRIVATE(A2BUS_IBSAP16, device_a2bus_card_interface, a2bus_ap16_device, "a2ap16", "IBS AP-16 80 column card")
+DEFINE_DEVICE_TYPE_PRIVATE(A2BUS_IBSAP16ALT, device_a2bus_card_interface, a2bus_ap16alt_device, "a2ap16a", "IBS AP-16 80 column card (alt. version)")
+DEFINE_DEVICE_TYPE_PRIVATE(A2BUS_VTC1, device_a2bus_card_interface, a2bus_vtc1_device, "a2vtc1", "unknown Videoterm clone")
+DEFINE_DEVICE_TYPE_PRIVATE(A2BUS_AEVIEWMASTER80, device_a2bus_card_interface, a2bus_aevm80_device, "a2aevm80", "Applied Engineering Viewmaster 80")
diff --git a/src/devices/bus/a2bus/a2videoterm.h b/src/devices/bus/a2bus/a2videoterm.h
index 589a1331a40..17d6c550df0 100644
--- a/src/devices/bus/a2bus/a2videoterm.h
+++ b/src/devices/bus/a2bus/a2videoterm.h
@@ -14,99 +14,12 @@
#pragma once
#include "a2bus.h"
-#include "video/mc6845.h"
-//**************************************************************************
-// TYPE DEFINITIONS
-//**************************************************************************
-
-class a2bus_videx80_device:
- public device_t,
- public device_a2bus_card_interface
-{
-protected:
- // construction/destruction
- a2bus_videx80_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
- 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 void write_cnxx(uint8_t offset, uint8_t data) override;
- virtual uint8_t read_c800(uint16_t offset) override;
- virtual void write_c800(uint16_t offset, uint8_t data) override;
-
- uint8_t *m_rom, *m_chrrom;
- uint8_t m_ram[512*4];
-
- required_device<mc6845_device> m_crtc;
-
- MC6845_UPDATE_ROW(crtc_update_row);
-
- int m_rambank;
- uint8_t m_char_width;
-};
-
-class a2bus_videoterm_device : public a2bus_videx80_device
-{
-public:
- a2bus_videoterm_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 a2bus_ap16_device : public a2bus_videx80_device
-{
-public:
- a2bus_ap16_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;
-
-protected:
- virtual uint8_t read_cnxx(uint8_t offset) override;
-};
-
-
-class a2bus_ap16alt_device : public a2bus_videx80_device
-{
-public:
- a2bus_ap16alt_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;
-
-protected:
- virtual uint8_t read_cnxx(uint8_t offset) override;
-};
-
-class a2bus_vtc1_device : public a2bus_videx80_device
-{
-public:
- a2bus_vtc1_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;
-};
-
-class a2bus_aevm80_device : public a2bus_videx80_device
-{
-public:
- a2bus_aevm80_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;
-};
-
-// device type definition
-DECLARE_DEVICE_TYPE(A2BUS_VIDEOTERM, a2bus_videoterm_device)
-DECLARE_DEVICE_TYPE(A2BUS_IBSAP16, a2bus_ap16_device)
-DECLARE_DEVICE_TYPE(A2BUS_IBSAP16ALT, a2bus_ap16alt_device)
-DECLARE_DEVICE_TYPE(A2BUS_VTC1, a2bus_vtc1_device)
-DECLARE_DEVICE_TYPE(A2BUS_AEVIEWMASTER80, a2bus_aevm80_device)
+// device type declaration
+DECLARE_DEVICE_TYPE(A2BUS_VIDEOTERM, device_a2bus_card_interface)
+DECLARE_DEVICE_TYPE(A2BUS_IBSAP16, device_a2bus_card_interface)
+DECLARE_DEVICE_TYPE(A2BUS_IBSAP16ALT, device_a2bus_card_interface)
+DECLARE_DEVICE_TYPE(A2BUS_VTC1, device_a2bus_card_interface)
+DECLARE_DEVICE_TYPE(A2BUS_AEVIEWMASTER80, device_a2bus_card_interface)
#endif // MAME_BUS_A2BUS_A2VIDEOTERM_H
diff --git a/src/devices/bus/a2bus/a2vulcan.cpp b/src/devices/bus/a2bus/a2vulcan.cpp
index 292f80b219a..32827eba1f6 100644
--- a/src/devices/bus/a2bus/a2vulcan.cpp
+++ b/src/devices/bus/a2bus/a2vulcan.cpp
@@ -55,16 +55,12 @@
#include "emu.h"
#include "a2vulcan.h"
-#include "machine/ataintf.h"
+
+#include "bus/ata/ataintf.h"
#include "imagedev/harddriv.h"
-//**************************************************************************
-// GLOBAL VARIABLES
-//**************************************************************************
-DEFINE_DEVICE_TYPE(A2BUS_VULCAN, a2bus_vulcan_device, "a2vulcan", "Applied Engineering Vulcan IDE controller (IIgs version)")
-DEFINE_DEVICE_TYPE(A2BUS_VULCANIIE, a2bus_vulcaniie_device, "a2vuliie", "Applied Engineering Vulcan IDE controller (//e version)")
-DEFINE_DEVICE_TYPE(A2BUS_VULCANGOLD, a2bus_vulcangold_device, "a2vulgld", "Applied Engineering Vulcan Gold IDE controller (IIgs version)")
+namespace {
#define VULCAN_ROM_REGION "vulcan_rom"
#define VULCAN_ATA_TAG "vulcan_ata"
@@ -84,6 +80,69 @@ ROM_START( vulcangold )
ROM_LOAD( "ae vulcan gold rom v2.0.bin", 0x000000, 0x004000, CRC(19bc3958) SHA1(96a22c2540fa603648a4e638e176eee76523b4e1) )
ROM_END
+//**************************************************************************
+// TYPE DEFINITIONS
+//**************************************************************************
+
+class a2bus_vulcanbase_device:
+ public device_t,
+ public device_a2bus_card_interface
+{
+protected:
+ // construction/destruction
+ a2bus_vulcanbase_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock);
+
+ 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;
+
+ // 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;
+ virtual uint8_t read_c800(uint16_t offset) override;
+ virtual void write_c800(uint16_t offset, uint8_t data) override;
+
+ required_device<ata_interface_device> m_ata;
+ required_region_ptr<uint8_t> m_rom;
+
+ uint8_t m_ram[8*1024];
+
+private:
+ uint16_t m_lastdata;
+ int m_rombank, m_rambank;
+ bool m_last_read_was_0;
+};
+
+class a2bus_vulcan_device : public a2bus_vulcanbase_device
+{
+public:
+ a2bus_vulcan_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 ATTR_COLD;
+ virtual void device_start() override ATTR_COLD;
+};
+
+class a2bus_vulcaniie_device : public a2bus_vulcanbase_device
+{
+public:
+ a2bus_vulcaniie_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 ATTR_COLD;
+ virtual void device_start() override ATTR_COLD;
+};
+
+class a2bus_vulcangold_device : public a2bus_vulcanbase_device
+{
+public:
+ a2bus_vulcangold_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 ATTR_COLD;
+};
+
/***************************************************************************
FUNCTION PROTOTYPES
***************************************************************************/
@@ -123,7 +182,9 @@ const tiny_rom_entry *a2bus_vulcangold_device::device_rom_region() const
a2bus_vulcanbase_device::a2bus_vulcanbase_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_ata(*this, VULCAN_ATA_TAG), m_rom(nullptr), m_lastdata(0), m_rombank(0), m_rambank(0), m_last_read_was_0(false)
+ m_ata(*this, VULCAN_ATA_TAG),
+ m_rom(*this, VULCAN_ROM_REGION),
+ m_lastdata(0), m_rombank(0), m_rambank(0), m_last_read_was_0(false)
{
}
@@ -148,8 +209,6 @@ a2bus_vulcangold_device::a2bus_vulcangold_device(const machine_config &mconfig,
void a2bus_vulcanbase_device::device_start()
{
- m_rom = device().machine().root_device().memregion(this->subtag(VULCAN_ROM_REGION).c_str())->base();
-
save_item(NAME(m_lastdata));
save_item(NAME(m_ram));
save_item(NAME(m_rombank));
@@ -192,7 +251,7 @@ uint8_t a2bus_vulcanbase_device::read_c0nx(uint8_t offset)
switch (offset)
{
case 0:
- m_lastdata = m_ata->read_cs0(offset);
+ m_lastdata = m_ata->cs0_r(offset);
// printf("IDE: read %04x\n", m_lastdata);
m_last_read_was_0 = true;
return m_lastdata&0xff;
@@ -205,7 +264,7 @@ uint8_t a2bus_vulcanbase_device::read_c0nx(uint8_t offset)
}
else
{
- return m_ata->read_cs0(offset, 0xff);
+ return m_ata->cs0_r(offset, 0xff);
}
case 2:
@@ -214,7 +273,7 @@ uint8_t a2bus_vulcanbase_device::read_c0nx(uint8_t offset)
case 5:
case 6:
case 7:
- return m_ata->read_cs0(offset, 0xff);
+ return m_ata->cs0_r(offset, 0xff);
default:
logerror("a2vulcan: unknown read @ C0n%x\n", offset);
@@ -246,11 +305,11 @@ void a2bus_vulcanbase_device::write_c0nx(uint8_t offset, uint8_t data)
m_lastdata &= 0x00ff;
m_lastdata |= (data << 8);
// printf("IDE: write %04x\n", m_lastdata);
- m_ata->write_cs0(0, m_lastdata);
+ m_ata->cs0_w(0, m_lastdata);
}
else
{
- m_ata->write_cs0(offset, data, 0xff);
+ m_ata->cs0_w(offset, data, 0xff);
}
break;
@@ -261,7 +320,7 @@ void a2bus_vulcanbase_device::write_c0nx(uint8_t offset, uint8_t data)
case 6:
case 7:
// printf("%02x to IDE controller @ %x\n", data, offset);
- m_ata->write_cs0(offset, data, 0xff);
+ m_ata->cs0_w(offset, data, 0xff);
break;
case 9: // ROM bank
@@ -318,3 +377,14 @@ void a2bus_vulcanbase_device::write_c800(uint16_t offset, uint8_t data)
m_ram[offset + m_rambank] = data;
}
}
+
+} // anonymous namespace
+
+
+//**************************************************************************
+// GLOBAL VARIABLES
+//**************************************************************************
+
+DEFINE_DEVICE_TYPE_PRIVATE(A2BUS_VULCAN, device_a2bus_card_interface, a2bus_vulcan_device, "a2vulcan", "Applied Engineering Vulcan IDE controller (IIgs version)")
+DEFINE_DEVICE_TYPE_PRIVATE(A2BUS_VULCANIIE, device_a2bus_card_interface, a2bus_vulcaniie_device, "a2vuliie", "Applied Engineering Vulcan IDE controller (//e version)")
+DEFINE_DEVICE_TYPE_PRIVATE(A2BUS_VULCANGOLD, device_a2bus_card_interface, a2bus_vulcangold_device, "a2vulgld", "Applied Engineering Vulcan Gold IDE controller (IIgs version)")
diff --git a/src/devices/bus/a2bus/a2vulcan.h b/src/devices/bus/a2bus/a2vulcan.h
index a1f867196c4..50931b4166c 100644
--- a/src/devices/bus/a2bus/a2vulcan.h
+++ b/src/devices/bus/a2bus/a2vulcan.h
@@ -8,80 +8,16 @@
*********************************************************************/
-#ifndef MAME_BUS_A2BUS_VULCAN_H
-#define MAME_BUS_A2BUS_VULCAN_H
+#ifndef MAME_BUS_A2BUS_A2VULCAN_H
+#define MAME_BUS_A2BUS_A2VULCAN_H
#pragma once
#include "a2bus.h"
-#include "machine/ataintf.h"
-//**************************************************************************
-// TYPE DEFINITIONS
-//**************************************************************************
+// device type declaration
+DECLARE_DEVICE_TYPE(A2BUS_VULCAN, device_a2bus_card_interface)
+DECLARE_DEVICE_TYPE(A2BUS_VULCANIIE, device_a2bus_card_interface)
+DECLARE_DEVICE_TYPE(A2BUS_VULCANGOLD, device_a2bus_card_interface)
-class a2bus_vulcanbase_device:
- public device_t,
- public device_a2bus_card_interface
-{
-protected:
- // construction/destruction
- a2bus_vulcanbase_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
- 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;
- virtual void write_c800(uint16_t offset, uint8_t data) override;
-
- required_device<ata_interface_device> m_ata;
-
- uint8_t *m_rom;
- uint8_t m_ram[8*1024];
-
-private:
- uint16_t m_lastdata;
- int m_rombank, m_rambank;
- bool m_last_read_was_0;
-};
-
-class a2bus_vulcan_device : public a2bus_vulcanbase_device
-{
-public:
- a2bus_vulcan_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
- virtual const tiny_rom_entry *device_rom_region() const override;
-
-protected:
- virtual void device_start() override;
-
-protected:
-};
-
-class a2bus_vulcaniie_device : public a2bus_vulcanbase_device
-{
-public:
- a2bus_vulcaniie_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
- virtual const tiny_rom_entry *device_rom_region() const override;
-
-protected:
- virtual void device_start() override;
-};
-
-class a2bus_vulcangold_device : public a2bus_vulcanbase_device
-{
-public:
- a2bus_vulcangold_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(A2BUS_VULCAN, a2bus_vulcan_device)
-DECLARE_DEVICE_TYPE(A2BUS_VULCANIIE, a2bus_vulcaniie_device)
-DECLARE_DEVICE_TYPE(A2BUS_VULCANGOLD, a2bus_vulcangold_device)
-
-#endif // MAME_BUS_A2BUS_VULCAN_H
+#endif // MAME_BUS_A2BUS_A2VULCAN_H
diff --git a/src/devices/bus/a2bus/a2wico_trackball.cpp b/src/devices/bus/a2bus/a2wico_trackball.cpp
new file mode 100644
index 00000000000..12fb6e6275c
--- /dev/null
+++ b/src/devices/bus/a2bus/a2wico_trackball.cpp
@@ -0,0 +1,245 @@
+// license:BSD-3-Clause
+/*********************************************************************
+
+ a2wicotrackball.cpp
+
+ Implemention of the Wico Trackball
+
+ Wico Trackball Interface PCB
+ Wico 1983
+
+ This is a trackball interface for the Apple II
+
+ For API information, see:
+ Track Balls, Bill Morgan, Apple Assembly Line, Vol. 3, Iss. 9, June 1983
+
+*********************************************************************/
+
+#include "emu.h"
+#include "a2wico_trackball.h"
+
+namespace {
+
+//**************************************************************************
+// TYPE DEFINITIONS
+//**************************************************************************
+
+class a2bus_wicotrackball_device:
+ public device_t,
+ public device_a2bus_card_interface
+{
+public:
+ // construction/destruction
+ a2bus_wicotrackball_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 ATTR_COLD;
+
+protected:
+ a2bus_wicotrackball_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock);
+
+ virtual void device_start() override ATTR_COLD;
+ virtual void device_reset() override ATTR_COLD;
+
+ // 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;
+
+private:
+ uint8_t read_position(int axis);
+
+ required_ioport m_wicotrackballb;
+ required_ioport_array<2> m_wicotrackballxy;
+
+ bool m_speed[2];
+ uint8_t m_buttons;
+ bool m_wraparound;
+ uint8_t m_axis[2];
+ uint32_t m_last_pos[2];
+};
+
+/***************************************************************************
+ CONSTANTS
+***************************************************************************/
+
+#define WICOTRACKBALL_BUTTONS_TAG "a2wicotrackball_buttons"
+#define WICOTRACKBALL_XAXIS_TAG "a2wicotrackball_x"
+#define WICOTRACKBALL_YAXIS_TAG "a2wicotrackball_y"
+
+#define WICOTRACKBALL_POS_UNINIT 0xffffffff /* default out-of-range position */
+
+static INPUT_PORTS_START( wicotrackball )
+ PORT_START(WICOTRACKBALL_BUTTONS_TAG) /* Trackball - buttons */
+ PORT_BIT( 0x80, IP_ACTIVE_HIGH, IPT_BUTTON1) PORT_NAME("Trackball Button 1") PORT_CODE(MOUSECODE_BUTTON1)
+ PORT_BIT( 0x40, IP_ACTIVE_HIGH, IPT_BUTTON2) PORT_NAME("Trackball Button 2") PORT_CODE(MOUSECODE_BUTTON2)
+
+ PORT_START(WICOTRACKBALL_XAXIS_TAG) /* Trackball - X AXIS */
+ PORT_BIT( 0xff, 0x00, IPT_TRACKBALL_X) PORT_SENSITIVITY(40) PORT_KEYDELTA(0) PORT_PLAYER(1)
+
+ PORT_START(WICOTRACKBALL_YAXIS_TAG) /* Trackball - Y AXIS */
+ PORT_BIT( 0xff, 0x00, IPT_TRACKBALL_Y) PORT_SENSITIVITY(40) PORT_KEYDELTA(0) PORT_PLAYER(1)
+INPUT_PORTS_END
+
+
+/***************************************************************************
+ DEVICE CONFIGURATION
+***************************************************************************/
+
+/*-------------------------------------------------
+ input_ports - device-specific input ports
+-------------------------------------------------*/
+
+ioport_constructor a2bus_wicotrackball_device::device_input_ports() const
+{
+ return INPUT_PORTS_NAME(wicotrackball);
+}
+
+/***************************************************************************
+ LIVE DEVICE
+***************************************************************************/
+
+a2bus_wicotrackball_device::a2bus_wicotrackball_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_wicotrackballb(*this, WICOTRACKBALL_BUTTONS_TAG), m_wicotrackballxy(*this, { WICOTRACKBALL_XAXIS_TAG, WICOTRACKBALL_YAXIS_TAG }),
+ m_speed{ false, false }, m_buttons{ 0 }, m_wraparound{false}, m_axis{ 0, 0 },
+ m_last_pos{ WICOTRACKBALL_POS_UNINIT, WICOTRACKBALL_POS_UNINIT }
+{
+}
+
+a2bus_wicotrackball_device::a2bus_wicotrackball_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) :
+ a2bus_wicotrackball_device(mconfig, A2BUS_WICOTRACKBALL, tag, owner, clock)
+{
+}
+
+/*-------------------------------------------------
+ device_start - device-specific startup
+-------------------------------------------------*/
+
+void a2bus_wicotrackball_device::device_start()
+{
+ // register save state variables
+ save_item(NAME(m_speed));
+ save_item(NAME(m_wraparound));
+ save_item(NAME(m_buttons));
+ save_item(NAME(m_axis));
+ save_item(NAME(m_last_pos));
+}
+
+void a2bus_wicotrackball_device::device_reset()
+{
+ m_speed[0] = m_speed[1] = false;
+ m_wraparound = false;
+ m_buttons = 0;
+ m_axis[0] = m_axis[1] = 0;
+}
+
+uint8_t a2bus_wicotrackball_device::read_position(int axis)
+{
+ int const speed_scale = 1 << (m_speed[0] + m_speed[1] * 2);
+ int const cur_pos = m_wicotrackballxy[axis]->read();
+
+ uint8_t result = 0;
+ if (m_last_pos[axis] != WICOTRACKBALL_POS_UNINIT) {
+ int diff_pos = cur_pos - m_last_pos[axis];
+
+ // wrap-around the positoin
+ if (diff_pos > 0x7f) {
+ diff_pos -= 0x100;
+ } else if (diff_pos < -0x80) {
+ diff_pos += 0x100;
+ }
+
+ int const updated_axis = int(unsigned(m_axis[axis])) + diff_pos / speed_scale;;
+ if (m_wraparound) {
+ result = unsigned(updated_axis);
+ } else {
+ result = unsigned(std::clamp<int>(updated_axis, 0, 0xff));
+ }
+ if (!machine().side_effects_disabled()) {
+ m_axis[axis] = result;
+ }
+ }
+ if (!machine().side_effects_disabled()) {
+ m_last_pos[axis] = cur_pos;
+ }
+
+ return result;
+}
+
+/*-------------------------------------------------
+ read_c0nx - called for reads from this card's c0nx space
+-------------------------------------------------*/
+
+uint8_t a2bus_wicotrackball_device::read_c0nx(uint8_t offset)
+{
+ uint8_t data = 0;
+
+ switch (offset) {
+ case 0x0: /* read X-position */
+ data = read_position(0);
+ break;
+ case 0x1: /* read Y-position */
+ data = read_position(1);
+ break;
+ case 0x2: /* set Bounded/Wraparound Soft Switch to Bounded */
+ if (!machine().side_effects_disabled()) {
+ m_wraparound = false;
+ }
+ break;
+ case 0x3: /* set Bounded/Wraparound Soft Switch to Wraparound */
+ if (!machine().side_effects_disabled()) {
+ m_wraparound = true;
+ }
+ break;
+ case 0x6: /* read buttons */
+ data = m_buttons = m_wicotrackballb->read();
+ break;
+ }
+ return data;
+}
+
+/*-------------------------------------------------
+ write_c0nx - called for writes to this card's c0nx space
+-------------------------------------------------*/
+
+void a2bus_wicotrackball_device::write_c0nx(uint8_t offset, uint8_t data)
+{
+ switch (offset) {
+ case 0x0: /* set X-position */
+ m_last_pos[0] = m_wicotrackballxy[0]->read();
+ m_axis[0] = data;
+ break;
+ case 0x1: /* set Y-position */
+ m_last_pos[1] = m_wicotrackballxy[1]->read();
+ m_axis[1] = data;
+ break;
+ case 0x2: /* set Bounded/Wraparound Soft Switch to Bounded */
+ m_wraparound = false;
+ break;
+ case 0x3: /* set Bounded/Wraparound Soft Switch to Wraparound */
+ m_wraparound = true;
+ break;
+ case 0x4: /* set Speed 1/2 Soft Switch to Speed 1 */
+ m_speed[0] = false;
+ break;
+ case 0x5: /* set Speed 1/2 Soft Switch to Speed 2 */
+ m_speed[0] = true;
+ break;
+ case 0x6: /* set Speed 3/4 Soft Switch to Speed 3 */
+ m_speed[1] = false;
+ break;
+ case 0x7: /* set Speed 3/4 Soft Switch to Speed 4 */
+ m_speed[1] = true;
+ break;
+ }
+}
+
+} // anonymous namespace
+
+
+/***************************************************************************
+ GLOBAL VARIABLES
+***************************************************************************/
+
+DEFINE_DEVICE_TYPE_PRIVATE(A2BUS_WICOTRACKBALL, device_a2bus_card_interface, a2bus_wicotrackball_device, "a2wicotrackball", "Apple II Wico Trackball Card")
diff --git a/src/devices/bus/a2bus/a2wico_trackball.h b/src/devices/bus/a2bus/a2wico_trackball.h
new file mode 100644
index 00000000000..f18793d9cbb
--- /dev/null
+++ b/src/devices/bus/a2bus/a2wico_trackball.h
@@ -0,0 +1,20 @@
+// license:BSD-3-Clause
+/*********************************************************************
+
+ a2wicotrackball.h
+
+ Implemention of the Wico Apple II Trackball
+
+*********************************************************************/
+
+#ifndef MAME_BUS_A2BUS_A2WICO_TRACKBALL_H
+#define MAME_BUS_A2BUS_A2WICO_TRACKBALL_H
+
+#pragma once
+
+#include "a2bus.h"
+
+// device type definition
+DECLARE_DEVICE_TYPE(A2BUS_WICOTRACKBALL, device_a2bus_card_interface)
+
+#endif // MAME_BUS_A2BUS_A2WICO_TRACKBALL_H
diff --git a/src/devices/bus/a2bus/a2zipdrive.cpp b/src/devices/bus/a2bus/a2zipdrive.cpp
index 44fc6afc0ae..5d2a141ae86 100644
--- a/src/devices/bus/a2bus/a2zipdrive.cpp
+++ b/src/devices/bus/a2bus/a2zipdrive.cpp
@@ -68,15 +68,12 @@
#include "emu.h"
#include "a2zipdrive.h"
-#include "machine/ataintf.h"
+
+#include "bus/ata/ataintf.h"
#include "imagedev/harddriv.h"
-//**************************************************************************
-// GLOBAL VARIABLES
-//**************************************************************************
-DEFINE_DEVICE_TYPE(A2BUS_ZIPDRIVE, a2bus_zipdrive_device, "a2zipdrv", "Zip Technologies ZipDrive")
-DEFINE_DEVICE_TYPE(A2BUS_FOCUSDRIVE, a2bus_focusdrive_device, "a2focdrv", "Parsons Engineering Focus Drive")
+namespace {
#define ZIPDRIVE_ROM_REGION "zipdrive_rom"
#define ZIPDRIVE_ATA_TAG "zipdrive_ata"
@@ -91,6 +88,53 @@ ROM_START( focusdrive )
ROM_LOAD( "focusrom.bin", 0x001000, 0x001000, CRC(0fd0ba25) SHA1(acf414aa145fcfa1c12aca0269f1f7ada82f1c04) )
ROM_END
+//**************************************************************************
+// TYPE DEFINITIONS
+//**************************************************************************
+
+class a2bus_zipdrivebase_device:
+ public device_t,
+ public device_a2bus_card_interface
+{
+protected:
+ // construction/destruction
+ a2bus_zipdrivebase_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock);
+
+ 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;
+ virtual const tiny_rom_entry *device_rom_region() const override ATTR_COLD;
+
+ // 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;
+ virtual uint8_t read_c800(uint16_t offset) override;
+
+ required_device<ata_interface_device> m_ata;
+ required_region_ptr<uint8_t> m_rom;
+
+ uint16_t m_lastdata;
+};
+
+class a2bus_zipdrive_device : public a2bus_zipdrivebase_device
+{
+public:
+ a2bus_zipdrive_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
+};
+
+class a2bus_focusdrive_device : public a2bus_zipdrivebase_device
+{
+public:
+ a2bus_focusdrive_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
+
+protected:
+ virtual void device_reset() override ATTR_COLD;
+ virtual const tiny_rom_entry *device_rom_region() const override ATTR_COLD;
+ virtual uint8_t read_c0nx(uint8_t offset) override;
+ virtual void write_c0nx(uint8_t offset, uint8_t data) override;
+};
+
/***************************************************************************
FUNCTION PROTOTYPES
***************************************************************************/
@@ -125,7 +169,9 @@ const tiny_rom_entry *a2bus_focusdrive_device::device_rom_region() const
a2bus_zipdrivebase_device::a2bus_zipdrivebase_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_ata(*this, ZIPDRIVE_ATA_TAG), m_rom(nullptr), m_lastdata(0)
+ m_ata(*this, ZIPDRIVE_ATA_TAG),
+ m_rom(*this, ZIPDRIVE_ROM_REGION),
+ m_lastdata(0)
{
}
@@ -145,8 +191,6 @@ a2bus_focusdrive_device::a2bus_focusdrive_device(const machine_config &mconfig,
void a2bus_zipdrivebase_device::device_start()
{
- m_rom = device().machine().root_device().memregion(this->subtag(ZIPDRIVE_ROM_REGION).c_str())->base();
-
save_item(NAME(m_lastdata));
}
@@ -176,10 +220,10 @@ uint8_t a2bus_zipdrivebase_device::read_c0nx(uint8_t offset)
case 5:
case 6:
case 7:
- return m_ata->read_cs0(offset, 0xff);
+ return m_ata->cs0_r(offset, 0xff);
case 8: // data port
- m_lastdata = m_ata->read_cs0(0, 0xffff);
+ m_lastdata = m_ata->cs0_r(0, 0xffff);
// printf("%04x @ IDE data\n", m_lastdata);
return m_lastdata&0xff;
@@ -206,10 +250,10 @@ uint8_t a2bus_focusdrive_device::read_c0nx(uint8_t offset)
case 0xd:
case 0xe:
case 0xf:
- return m_ata->read_cs0(offset&7, 0xff);
+ return m_ata->cs0_r(offset&7, 0xff);
case 0: // data port
- m_lastdata = m_ata->read_cs0(0, 0xffff);
+ m_lastdata = m_ata->cs0_r(0, 0xffff);
//printf("%04x @ IDE data\n", m_lastdata);
return m_lastdata&0xff;
@@ -241,7 +285,7 @@ void a2bus_zipdrivebase_device::write_c0nx(uint8_t offset, uint8_t data)
case 6:
case 7:
// printf("%02x to IDE controller @ %x\n", data, offset);
- m_ata->write_cs0(offset, data, 0xff);
+ m_ata->cs0_w(offset, data, 0xff);
break;
case 8:
@@ -253,7 +297,7 @@ void a2bus_zipdrivebase_device::write_c0nx(uint8_t offset, uint8_t data)
// printf("%02x to IDE data hi\n", data);
m_lastdata &= 0x00ff;
m_lastdata |= (data << 8);
- m_ata->write_cs0(0, m_lastdata, 0xffff);
+ m_ata->cs0_w(0, m_lastdata, 0xffff);
break;
default:
@@ -276,14 +320,14 @@ void a2bus_focusdrive_device::write_c0nx(uint8_t offset, uint8_t data)
case 0xf:
// due to a bug in the 6502 firmware, eat data if DRQ is set
#if 0
- while (m_ata->read_cs0(7, 0xff) & 0x08)
+ while (m_ata->cs0_r(7, 0xff) & 0x08)
{
- m_ata->read_cs0(0, 0xffff);
+ m_ata->cs0_r(0, 0xffff);
printf("eating 2 bytes to clear DRQ\n");
}
#endif
// printf("%02x to IDE controller @ %x\n", data, offset);
- m_ata->write_cs0(offset & 7, data, 0xff);
+ m_ata->cs0_w(offset & 7, data, 0xff);
break;
case 0:
@@ -295,7 +339,7 @@ void a2bus_focusdrive_device::write_c0nx(uint8_t offset, uint8_t data)
// printf("%02x to IDE data hi\n", data);
m_lastdata &= 0x00ff;
m_lastdata |= (data << 8);
- m_ata->write_cs0(0, m_lastdata, 0xffff);
+ m_ata->cs0_w(0, m_lastdata, 0xffff);
break;
default:
@@ -326,3 +370,13 @@ uint8_t a2bus_zipdrivebase_device::read_c800(uint16_t offset)
return m_rom[offset+0x1800];
}
+
+} // anonymous namespace
+
+
+//**************************************************************************
+// GLOBAL VARIABLES
+//**************************************************************************
+
+DEFINE_DEVICE_TYPE_PRIVATE(A2BUS_ZIPDRIVE, device_a2bus_card_interface, a2bus_zipdrive_device, "a2zipdrv", "Zip Technologies ZipDrive")
+DEFINE_DEVICE_TYPE_PRIVATE(A2BUS_FOCUSDRIVE, device_a2bus_card_interface, a2bus_focusdrive_device, "a2focdrv", "Parsons Engineering Focus Drive")
diff --git a/src/devices/bus/a2bus/a2zipdrive.h b/src/devices/bus/a2bus/a2zipdrive.h
index 9e3e68e79f2..691c18457d0 100644
--- a/src/devices/bus/a2bus/a2zipdrive.h
+++ b/src/devices/bus/a2bus/a2zipdrive.h
@@ -11,63 +11,15 @@
*********************************************************************/
-#ifndef MAME_BUS_A2BUS_ZIPDRIVE_H
-#define MAME_BUS_A2BUS_ZIPDRIVE_H
+#ifndef MAME_BUS_A2BUS_A2ZIPDRIVE_H
+#define MAME_BUS_A2BUS_A2ZIPDRIVE_H
#pragma once
#include "a2bus.h"
-#include "machine/ataintf.h"
-//**************************************************************************
-// TYPE DEFINITIONS
-//**************************************************************************
+// device type declaration
+DECLARE_DEVICE_TYPE(A2BUS_ZIPDRIVE, device_a2bus_card_interface)
+DECLARE_DEVICE_TYPE(A2BUS_FOCUSDRIVE, device_a2bus_card_interface)
-class a2bus_zipdrivebase_device:
- public device_t,
- public device_a2bus_card_interface
-{
-protected:
- // construction/destruction
- a2bus_zipdrivebase_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;
- virtual uint8_t read_c800(uint16_t offset) override;
-
- required_device<ata_interface_device> m_ata;
-
- uint8_t *m_rom;
- uint16_t m_lastdata;
-};
-
-class a2bus_zipdrive_device : public a2bus_zipdrivebase_device
-{
-public:
- a2bus_zipdrive_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
-};
-
-class a2bus_focusdrive_device : public a2bus_zipdrivebase_device
-{
-public:
- a2bus_focusdrive_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
-
-protected:
- virtual void device_reset() override;
- virtual const tiny_rom_entry *device_rom_region() const override;
- virtual uint8_t read_c0nx(uint8_t offset) override;
- virtual void write_c0nx(uint8_t offset, uint8_t data) override;
-};
-
-// device type definition
-DECLARE_DEVICE_TYPE(A2BUS_ZIPDRIVE, a2bus_zipdrive_device)
-DECLARE_DEVICE_TYPE(A2BUS_FOCUSDRIVE, a2bus_focusdrive_device)
-
-#endif // MAME_BUS_A2BUS_ZIPDRIVE_H
+#endif // MAME_BUS_A2BUS_A2ZIPDRIVE_H
diff --git a/src/devices/bus/a2bus/ace2x00.cpp b/src/devices/bus/a2bus/ace2x00.cpp
new file mode 100644
index 00000000000..ccea01c4ecc
--- /dev/null
+++ b/src/devices/bus/a2bus/ace2x00.cpp
@@ -0,0 +1,160 @@
+// license:BSD-3-Clause
+// copyright-holders:R. Belmont
+/*********************************************************************
+
+ ace2x00.c
+
+ Helpers for the Franklin Ace 2x00's slot 1 and 6 internal peripherals
+
+*********************************************************************/
+
+#include "emu.h"
+#include "ace2x00.h"
+
+//#define VERBOSE 1
+#include "logmacro.h"
+
+/***************************************************************************
+ PARAMETERS
+***************************************************************************/
+
+//**************************************************************************
+// GLOBAL VARIABLES
+//**************************************************************************
+
+DEFINE_DEVICE_TYPE(A2BUS_ACE2X00_SLOT1, a2bus_ace2x00_slot1_device, "ace2x00s1", "Franklin Ace 2x00 Parallel Port")
+DEFINE_DEVICE_TYPE(A2BUS_ACE2X00_SLOT6, a2bus_ace2x00_slot6_device, "ace2x00s6", "Franklin Ace 2x00 Disk Port")
+
+/***************************************************************************
+ FUNCTION PROTOTYPES
+***************************************************************************/
+
+//-------------------------------------------------
+// device_add_mconfig - add device configuration
+//-------------------------------------------------
+
+void a2bus_ace2x00_device::device_add_mconfig(machine_config &config)
+{
+}
+
+//**************************************************************************
+// LIVE DEVICE
+//**************************************************************************
+
+a2bus_ace2x00_device::a2bus_ace2x00_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)
+{
+}
+
+a2bus_ace2x00_slot1_device::a2bus_ace2x00_slot1_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) :
+ a2bus_ace2x00_device(mconfig, A2BUS_ACE2X00_SLOT1, tag, owner, clock)
+{
+}
+
+a2bus_ace2x00_slot6_device::a2bus_ace2x00_slot6_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) :
+ a2bus_ace2x00_device(mconfig, A2BUS_ACE2X00_SLOT6, tag, owner, clock),
+ m_iwm(*this, "iwm"),
+ m_floppy(*this, "%u", 0U)
+{
+}
+
+//-------------------------------------------------
+// device_add_mconfig - add device configuration
+//-------------------------------------------------
+void a2bus_ace2x00_slot6_device::device_add_mconfig(machine_config &config)
+{
+ IWM(config, m_iwm, clock(), 1021800*2);
+ m_iwm->phases_cb().set(FUNC(a2bus_ace2x00_slot6_device::phases_w));
+ m_iwm->devsel_cb().set(FUNC(a2bus_ace2x00_slot6_device::devsel_w));
+ applefdintf_device::add_525(config, m_floppy[0]);
+ applefdintf_device::add_525(config, m_floppy[1]);
+}
+
+/*-------------------------------------------------
+ read_c0nx - called for reads from this card's c0nx space
+-------------------------------------------------*/
+
+uint8_t a2bus_ace2x00_slot6_device::read_c0nx(u8 offset)
+{
+ return m_iwm->read(offset);
+}
+
+/*-------------------------------------------------
+ write_c0nx - called for writes to this card's c0nx space
+-------------------------------------------------*/
+
+void a2bus_ace2x00_slot6_device::write_c0nx(u8 offset, u8 data)
+{
+ m_iwm->write(offset, data);
+}
+
+void a2bus_ace2x00_slot6_device::devsel_w(u8 data)
+{
+ if (data & 1)
+ m_iwm->set_floppy(m_floppy[0]->get_device());
+ else if (data & 2)
+ m_iwm->set_floppy(m_floppy[1]->get_device());
+ else
+ m_iwm->set_floppy(nullptr);
+}
+
+void a2bus_ace2x00_slot6_device::phases_w(u8 data)
+{
+ auto flp = m_iwm->get_floppy();
+ if (flp)
+ flp->seek_phase_w(data);
+}
+
+//-------------------------------------------------
+// device_start - device-specific startup
+//-------------------------------------------------
+
+void a2bus_ace2x00_device::device_start()
+{
+}
+
+void a2bus_ace2x00_device::device_reset()
+{
+ m_rom = device().machine().root_device().memregion("maincpu")->base();
+}
+
+uint8_t a2bus_ace2x00_device::read_cnxx(uint8_t offset)
+{
+ switch (slotno())
+ {
+ case 1:
+ return m_rom[offset];
+
+ case 6:
+ return m_rom[offset + 0x4600];
+ }
+
+ return 0xff;
+}
+
+uint8_t a2bus_ace2x00_device::read_c800(uint16_t offset)
+{
+ switch (slotno())
+ {
+ case 6:
+ return m_rom[(offset & 0x7ff) + 0x4800];
+ }
+
+ return 0xff;
+}
+
+void a2bus_ace2x00_device::write_c800(uint16_t offset, uint8_t data)
+{
+}
+
+bool a2bus_ace2x00_device::take_c800()
+{
+ switch (slotno())
+ {
+ case 6:
+ return true;
+ default:
+ return false;
+ }
+}
diff --git a/src/devices/bus/a2bus/ace2x00.h b/src/devices/bus/a2bus/ace2x00.h
new file mode 100644
index 00000000000..dba00760750
--- /dev/null
+++ b/src/devices/bus/a2bus/ace2x00.h
@@ -0,0 +1,78 @@
+// license:BSD-3-Clause
+// copyright-holders:R. Belmont
+/*********************************************************************
+
+ ace2x00.h
+
+ Helpers for the Franklin Ace 2x00's slot 1 and 6 internal peripherals
+
+*********************************************************************/
+
+#ifndef MAME_BUS_A2BUS_ACE2X00_H
+#define MAME_BUS_A2BUS_ACE2X00_H
+
+#pragma once
+
+#include "a2bus.h"
+#include "imagedev/floppy.h"
+#include "machine/iwm.h"
+
+//**************************************************************************
+// TYPE DEFINITIONS
+//**************************************************************************
+
+class a2bus_ace2x00_device:
+ public device_t,
+ public device_a2bus_card_interface
+{
+public:
+ // construction/destruction
+ a2bus_ace2x00_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock);
+
+protected:
+ 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;
+
+ // overrides of standard a2bus slot functions
+ virtual uint8_t read_cnxx(uint8_t offset) override;
+ virtual uint8_t read_c800(uint16_t offset) override;
+ virtual void write_c800(uint16_t offset, uint8_t data) override;
+ virtual bool take_c800() override;
+
+ uint8_t *m_rom;
+};
+
+class a2bus_ace2x00_slot1_device : public a2bus_ace2x00_device
+{
+public:
+ a2bus_ace2x00_slot1_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
+
+protected:
+};
+
+class a2bus_ace2x00_slot6_device : public a2bus_ace2x00_device
+{
+public:
+ a2bus_ace2x00_slot6_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
+
+protected:
+ virtual void device_add_mconfig(machine_config &config) override ATTR_COLD;
+
+ // overrides of standard a2bus slot functions
+ virtual uint8_t read_c0nx(u8 offset) override;
+ virtual void write_c0nx(u8 offset, u8 data) override;
+
+ required_device<iwm_device> m_iwm;
+ required_device_array<floppy_connector, 2> m_floppy;
+
+private:
+ void devsel_w(u8 data);
+ void phases_w(u8 data);
+};
+
+// device type definition
+DECLARE_DEVICE_TYPE(A2BUS_ACE2X00_SLOT1, a2bus_ace2x00_slot1_device)
+DECLARE_DEVICE_TYPE(A2BUS_ACE2X00_SLOT6, a2bus_ace2x00_slot6_device)
+
+#endif // MAME_BUS_A2BUS_ACE2X00_H
diff --git a/src/devices/bus/a2bus/agat7langcard.h b/src/devices/bus/a2bus/agat7langcard.h
index e7dae54ebfb..729b2252757 100644
--- a/src/devices/bus/a2bus/agat7langcard.h
+++ b/src/devices/bus/a2bus/agat7langcard.h
@@ -30,8 +30,8 @@ public:
protected:
a2bus_agat7langcard_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_start() override ATTR_COLD;
+ virtual void device_reset() override ATTR_COLD;
// overrides of standard a2bus slot functions
virtual uint8_t read_cnxx(uint8_t offset) override;
diff --git a/src/devices/bus/a2bus/agat7ports.cpp b/src/devices/bus/a2bus/agat7ports.cpp
index 5c24d8fac8f..417840b0164 100644
--- a/src/devices/bus/a2bus/agat7ports.cpp
+++ b/src/devices/bus/a2bus/agat7ports.cpp
@@ -54,7 +54,7 @@ INPUT_PORTS_END
void a2bus_agat7_ports_device::device_add_mconfig(machine_config &config)
{
I8255(config, m_d9);
- m_d9->out_pa_callback().set("cent_data_out", FUNC(output_latch_device::bus_w));
+ m_d9->out_pa_callback().set("cent_data_out", FUNC(output_latch_device::write));
m_d9->out_pb_callback().set(FUNC(a2bus_agat7_ports_device::write_portb));
m_d9->in_pc_callback().set(FUNC(a2bus_agat7_ports_device::read_portc));
@@ -158,7 +158,7 @@ void a2bus_agat7_ports_device::write_c0nx(uint8_t offset, uint8_t data)
* 6 /INIT
* 7 /STROBE
*/
-WRITE8_MEMBER(a2bus_agat7_ports_device::write_portb)
+void a2bus_agat7_ports_device::write_portb(uint8_t data)
{
m_centronics->write_strobe(BIT(data, 5));
m_centronics->write_init(BIT(data, 4));
@@ -173,12 +173,12 @@ WRITE8_MEMBER(a2bus_agat7_ports_device::write_portb)
* 6 dip ABRLEV (0: BUSY, /ACK. 1: READY, ACK)
* 7 ready signal from device
*/
-READ8_MEMBER(a2bus_agat7_ports_device::read_portc)
+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 6b96ee0d783..09ed302106b 100644
--- a/src/devices/bus/a2bus/agat7ports.h
+++ b/src/devices/bus/a2bus/agat7ports.h
@@ -8,8 +8,8 @@
*********************************************************************/
-#ifndef MAME_BUS_A2BUS_AGAT7_PORTS_H
-#define MAME_BUS_A2BUS_AGAT7_PORTS_H
+#ifndef MAME_BUS_A2BUS_AGAT7PORTS_H
+#define MAME_BUS_A2BUS_AGAT7PORTS_H
#pragma once
@@ -35,10 +35,10 @@ public:
protected:
a2bus_agat7_ports_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 ioport_constructor device_input_ports() const override;
+ 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;
+ virtual ioport_constructor device_input_ports() const override ATTR_COLD;
// overrides of standard a2bus slot functions
virtual uint8_t read_c0nx(uint8_t offset) override;
@@ -50,9 +50,9 @@ protected:
required_device<i8251_device> m_d10;
required_device<centronics_device> m_centronics;
- DECLARE_WRITE8_MEMBER(write_portb);
- DECLARE_READ8_MEMBER(read_portc);
- DECLARE_WRITE_LINE_MEMBER(write_centronics_busy);
+ void write_portb(uint8_t data);
+ uint8_t read_portc();
+ void write_centronics_busy(int state);
private:
bool m_centronics_busy;
@@ -61,4 +61,4 @@ private:
// device type definition
DECLARE_DEVICE_TYPE(A2BUS_AGAT7_PORTS, a2bus_agat7_ports_device)
-#endif // MAME_BUS_A2BUS_AGAT7_PORTS_H
+#endif // MAME_BUS_A2BUS_AGAT7PORTS_H
diff --git a/src/devices/bus/a2bus/agat7ram.h b/src/devices/bus/a2bus/agat7ram.h
index 6b8529fcb7b..20726672632 100644
--- a/src/devices/bus/a2bus/agat7ram.h
+++ b/src/devices/bus/a2bus/agat7ram.h
@@ -30,8 +30,8 @@ public:
protected:
a2bus_agat7ram_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_start() override ATTR_COLD;
+ virtual void device_reset() override ATTR_COLD;
// overrides of standard a2bus slot functions
virtual uint8_t read_cnxx(uint8_t offset) override;
diff --git a/src/devices/bus/a2bus/agat840k_hle.cpp b/src/devices/bus/a2bus/agat840k_hle.cpp
index 1d1923adfb1..0a0fd511a95 100644
--- a/src/devices/bus/a2bus/agat840k_hle.cpp
+++ b/src/devices/bus/a2bus/agat840k_hle.cpp
@@ -53,9 +53,9 @@ static const floppy_interface agat840k_hle_floppy_interface =
void a2bus_agat840k_hle_device::device_add_mconfig(machine_config &config)
{
- legacy_floppy_image_device &floppy0(LEGACY_FLOPPY(config, FLOPPY_0, 0, &agat840k_hle_floppy_interface));
+ legacy_floppy_image_device &floppy0(LEGACY_FLOPPY(config, m_floppy_image[0], 0, &agat840k_hle_floppy_interface));
floppy0.out_idx_cb().set(FUNC(a2bus_agat840k_hle_device::index_0_w));
- legacy_floppy_image_device &floppy1(LEGACY_FLOPPY(config, FLOPPY_1, 0, &agat840k_hle_floppy_interface));
+ legacy_floppy_image_device &floppy1(LEGACY_FLOPPY(config, m_floppy_image[1], 0, &agat840k_hle_floppy_interface));
floppy1.out_idx_cb().set(FUNC(a2bus_agat840k_hle_device::index_1_w));
I8255(config, m_d14);
@@ -86,8 +86,11 @@ const tiny_rom_entry *a2bus_agat840k_hle_device::device_rom_region() const
a2bus_agat840k_hle_device::a2bus_agat840k_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_a2bus_card_interface(mconfig, *this)
+ , m_floppy_image(*this, "floppy%u", 0U)
, m_d14(*this, "d14")
, m_d15(*this, "d15")
+ , m_timer_wait(nullptr)
+ , m_timer_seek(nullptr)
, m_rom(nullptr)
{
}
@@ -97,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);
}
@@ -136,8 +139,8 @@ void a2bus_agat840k_hle_device::device_start()
m_mxcs = MXCSR_SYNC;
- m_timer_wait = timer_alloc(TIMER_ID_WAIT);
- m_timer_seek = timer_alloc(TIMER_ID_SEEK);
+ m_timer_wait = timer_alloc(FUNC(a2bus_agat840k_hle_device::timer_wait_tick), this);
+ m_timer_seek = timer_alloc(FUNC(a2bus_agat840k_hle_device::timer_seek_tick), this);
m_seektime = 6000; // 6 ms, per es5323.txt
m_waittime = 32; // 16 bits x 2 us
@@ -147,17 +150,13 @@ void a2bus_agat840k_hle_device::device_reset()
{
u8 buf[256];
- for (int i = 0; i < 2; i++)
+ for (auto &img : m_floppy_image)
{
- legacy_floppy_image_device *img = floppy_image(i);
- if (img)
- {
- img->floppy_drive_set_ready_state(FLOPPY_DRIVE_READY, 0);
- img->floppy_drive_set_rpm(300.);
- img->floppy_drive_seek(-img->floppy_drive_get_current_track());
- }
+ img->floppy_drive_set_ready_state(FLOPPY_DRIVE_READY, 0);
+ img->floppy_drive_set_rpm(300.);
+ img->floppy_drive_seek(-img->floppy_drive_get_current_track());
}
- m_floppy = floppy_image(0);
+ m_floppy = m_floppy_image[0].target();
// generate track images in memory, using default volume ID and gap padding bytes
int t = 0;
@@ -229,29 +228,24 @@ void a2bus_agat840k_hle_device::device_reset()
m_mxcs &= ~MXCSR_TR;
}
-void a2bus_agat840k_hle_device::device_timer(emu_timer &timer, device_timer_id id, int param, void *ptr)
+TIMER_CALLBACK_MEMBER(a2bus_agat840k_hle_device::timer_wait_tick)
{
- switch (id)
- {
- case TIMER_ID_WAIT:
- {
- m_count_read++;
- m_count_read %= 6250;
- m_d15->pc4_w(0);
- m_d15->pc4_w(1);
- if (BIT(m_tracks[(2 * m_floppy->floppy_drive_get_current_track()) + m_side][m_count_read], 15))
- m_mxcs &= ~MXCSR_SYNC;
- }
- break;
+ m_count_read++;
+ m_count_read %= 6250;
+ m_d15->pc4_w(0);
+ m_d15->pc4_w(1);
+ if (BIT(m_tracks[(2 * m_floppy->floppy_drive_get_current_track()) + m_side][m_count_read], 15))
+ m_mxcs &= ~MXCSR_SYNC;
+}
- case TIMER_ID_SEEK:
- m_floppy->floppy_stp_w(1);
- m_floppy->floppy_stp_w(0);
- break;
- }
+TIMER_CALLBACK_MEMBER(a2bus_agat840k_hle_device::timer_seek_tick)
+{
+ m_floppy->floppy_stp_w(1);
+ m_floppy->floppy_stp_w(0);
}
+
/*-------------------------------------------------
read_c0nx - called for reads from this card's c0nx space
-------------------------------------------------*/
@@ -324,15 +318,6 @@ uint8_t a2bus_agat840k_hle_device::read_cnxx(uint8_t offset)
return m_rom[offset];
}
-legacy_floppy_image_device *a2bus_agat840k_hle_device::floppy_image(int drive)
-{
- switch(drive) {
- case 0 : return subdevice<legacy_floppy_image_device>(FLOPPY_0);
- case 1 : return subdevice<legacy_floppy_image_device>(FLOPPY_1);
- }
- return nullptr;
-}
-
/*
* all signals active low. write support not implemented; WPT is always active.
*
@@ -345,7 +330,7 @@ legacy_floppy_image_device *a2bus_agat840k_hle_device::floppy_image(int drive)
*
* C0x1
*/
-READ8_MEMBER(a2bus_agat840k_hle_device::d14_i_b)
+uint8_t a2bus_agat840k_hle_device::d14_i_b()
{
u8 data = 0x3;
@@ -375,14 +360,14 @@ READ8_MEMBER(a2bus_agat840k_hle_device::d14_i_b)
*
* C0x2
*/
-WRITE8_MEMBER(a2bus_agat840k_hle_device::d14_o_c)
+void a2bus_agat840k_hle_device::d14_o_c(uint8_t data)
{
m_unit = BIT(data, 3);
- m_floppy = floppy_image(m_unit);
+ m_floppy = m_floppy_image[m_unit].target();
if (m_unit)
- m_floppy->floppy_ds1_w(m_unit != 1);
+ m_floppy->floppy_ds_w(m_unit != 1);
else
- m_floppy->floppy_ds0_w(m_unit != 0);
+ m_floppy->floppy_ds_w(m_unit != 0);
m_floppy->floppy_drtn_w(!BIT(data, 2));
m_side = BIT(data, 4);
@@ -408,7 +393,7 @@ WRITE8_MEMBER(a2bus_agat840k_hle_device::d14_o_c)
// C0x4
//
// data are latched in by write to PC4
-READ8_MEMBER(a2bus_agat840k_hle_device::d15_i_a)
+uint8_t a2bus_agat840k_hle_device::d15_i_a()
{
const u16 data = m_tracks[(2 * m_floppy->floppy_drive_get_current_track()) + m_side][m_count_read];
LOG("sector data: %02x @ %4d (head %d track %2d)%s\n", data & 0xff, m_count_read,
@@ -422,7 +407,7 @@ READ8_MEMBER(a2bus_agat840k_hle_device::d15_i_a)
//
// b6 AL desync detected
// b7 AH read or write data ready
-READ8_MEMBER(a2bus_agat840k_hle_device::d15_i_c)
+uint8_t a2bus_agat840k_hle_device::d15_i_c()
{
LOG("status B: @ %4d %s %s (%s)\n", m_count_read,
BIT(m_mxcs, 7) ? "ready" : "READY", BIT(m_mxcs, 6) ? "SYNC" : "sync",
@@ -437,7 +422,7 @@ READ8_MEMBER(a2bus_agat840k_hle_device::d15_i_c)
// b2 AH b7 = ready for write data
// b3 -- connected to b7, set if m_intr[PORT_A]
// b4 AH b7 = read data ready
-WRITE8_MEMBER(a2bus_agat840k_hle_device::d15_o_c)
+void a2bus_agat840k_hle_device::d15_o_c(uint8_t data)
{
if (BIT(data, 0) || BIT(data, 3))
{
diff --git a/src/devices/bus/a2bus/agat840k_hle.h b/src/devices/bus/a2bus/agat840k_hle.h
index 98586f5072b..70d451398dd 100644
--- a/src/devices/bus/a2bus/agat840k_hle.h
+++ b/src/devices/bus/a2bus/agat840k_hle.h
@@ -37,15 +37,15 @@ public:
// construction/destruction
a2bus_agat840k_hle_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
- DECLARE_READ8_MEMBER(d14_i_b);
- DECLARE_READ8_MEMBER(d15_i_a);
- DECLARE_READ8_MEMBER(d15_i_c);
- DECLARE_WRITE8_MEMBER(d14_o_c);
- DECLARE_WRITE8_MEMBER(d15_o_b);
- DECLARE_WRITE8_MEMBER(d15_o_c);
+ uint8_t d14_i_b();
+ uint8_t d15_i_a();
+ uint8_t d15_i_c();
+ void d14_o_c(uint8_t data);
+ 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);
@@ -53,28 +53,24 @@ protected:
// construction/destruction
a2bus_agat840k_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;
- virtual void device_timer(emu_timer &timer, device_timer_id id, int param, void *ptr) override;
- virtual void device_add_mconfig(machine_config &config) override;
- virtual const tiny_rom_entry *device_rom_region() const override;
+ 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;
+ virtual const tiny_rom_entry *device_rom_region() const override ATTR_COLD;
// 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;
- enum
- {
- TIMER_ID_WAIT = 0,
- TIMER_ID_SEEK
- };
+ TIMER_CALLBACK_MEMBER(timer_wait_tick);
+ TIMER_CALLBACK_MEMBER(timer_seek_tick);
+ required_device_array<legacy_floppy_image_device, 2> m_floppy_image;
required_device<i8255_device> m_d14;
required_device<i8255_device> m_d15;
private:
- legacy_floppy_image_device *floppy_image(int drive);
legacy_floppy_image_device *m_floppy;
bool m_side;
@@ -91,8 +87,8 @@ private:
int m_seektime;
int m_waittime;
- emu_timer *m_timer_wait = nullptr;
- emu_timer *m_timer_seek = nullptr;
+ emu_timer *m_timer_wait;
+ emu_timer *m_timer_seek;
uint8_t *m_rom;
};
diff --git a/src/devices/bus/a2bus/agat_fdc.cpp b/src/devices/bus/a2bus/agat_fdc.cpp
index 4a9737aecbe..dc88c7ea39e 100644
--- a/src/devices/bus/a2bus/agat_fdc.cpp
+++ b/src/devices/bus/a2bus/agat_fdc.cpp
@@ -63,10 +63,11 @@ ROM_END
// device_add_mconfig - add device configuration
//-------------------------------------------------
-FLOPPY_FORMATS_MEMBER( a2bus_agat_fdc_device::floppy_formats )
- FLOPPY_DS9_FORMAT,
- FLOPPY_AIM_FORMAT
-FLOPPY_FORMATS_END
+void a2bus_agat_fdc_device::floppy_formats(format_registration &fr)
+{
+ fr.add(FLOPPY_DS9_FORMAT);
+ fr.add(FLOPPY_AIM_FORMAT);
+}
static void agat_floppies(device_slot_interface &device)
{
@@ -139,8 +140,8 @@ void a2bus_agat_fdc_device::device_start()
m_mxcs = MXCSR_SYNC;
- m_timer_lss = timer_alloc(TIMER_ID_LSS);
- m_timer_motor = timer_alloc(TIMER_ID_MOTOR);
+ m_timer_lss = timer_alloc(FUNC(a2bus_agat_fdc_device::lss_sync), this);
+ m_timer_motor = timer_alloc(FUNC(a2bus_agat_fdc_device::motor_off), this);
m_seektime = 6; // ms, per es5323.txt
m_waittime = 32; // us - 16 bits x 2 us
@@ -161,19 +162,10 @@ void a2bus_agat_fdc_device::device_reset()
m_timer_lss->adjust(attotime::from_msec(10), 0, attotime::from_msec(10));
}
-void a2bus_agat_fdc_device::device_timer(emu_timer &timer, device_timer_id id, int param, void *ptr)
+TIMER_CALLBACK_MEMBER(a2bus_agat_fdc_device::motor_off)
{
- switch (id)
- {
- case TIMER_ID_LSS:
- lss_sync();
- break;
-
- case TIMER_ID_MOTOR:
- active = 0;
- floppy->mon_w(1);
- break;
- }
+ active = 0;
+ floppy->mon_w(1);
}
uint64_t a2bus_agat_fdc_device::time_to_cycles(const attotime &tm)
@@ -198,7 +190,7 @@ void a2bus_agat_fdc_device::lss_start()
bits = 8;
}
-void a2bus_agat_fdc_device::lss_sync()
+TIMER_CALLBACK_MEMBER(a2bus_agat_fdc_device::lss_sync)
{
if(!active)
return;
@@ -300,7 +292,7 @@ uint8_t a2bus_agat_fdc_device::read_c0nx(uint8_t offset)
{
u8 data;
- lss_sync();
+ lss_sync(0);
switch (offset)
{
@@ -327,7 +319,7 @@ uint8_t a2bus_agat_fdc_device::read_c0nx(uint8_t offset)
void a2bus_agat_fdc_device::write_c0nx(uint8_t offset, uint8_t data)
{
- lss_sync();
+ lss_sync(0);
switch (offset)
{
@@ -382,9 +374,9 @@ uint8_t a2bus_agat_fdc_device::read_cnxx(uint8_t offset)
*
* C0x1
*/
-READ8_MEMBER(a2bus_agat_fdc_device::d14_i_b)
+uint8_t a2bus_agat_fdc_device::d14_i_b()
{
- u8 data = 0x3;
+ u8 data = 0x0;
// all signals active low
if (floppy)
@@ -417,10 +409,20 @@ READ8_MEMBER(a2bus_agat_fdc_device::d14_i_b)
*
* C0x2
*/
-WRITE8_MEMBER(a2bus_agat_fdc_device::d14_o_c)
+void a2bus_agat_fdc_device::d14_o_c(uint8_t data)
{
m_unit = BIT(data, 3);
+ switch (m_unit)
+ {
+ case 0:
+ floppy = floppy0 ? floppy0->get_device() : nullptr;
+ break;
+ case 1:
+ floppy = floppy1 ? floppy1->get_device() : nullptr;
+ break;
+ }
+
if (floppy)
{
floppy->dir_w(!BIT(data, 2));
@@ -451,7 +453,7 @@ WRITE8_MEMBER(a2bus_agat_fdc_device::d14_o_c)
}
// data are latched in by write to PC4
-READ8_MEMBER(a2bus_agat_fdc_device::d15_i_a)
+uint8_t a2bus_agat_fdc_device::d15_i_a()
{
return data_reg;
}
@@ -460,7 +462,7 @@ READ8_MEMBER(a2bus_agat_fdc_device::d15_i_a)
//
// b6 AL desync detected
// b7 AH read or write data ready
-READ8_MEMBER(a2bus_agat_fdc_device::d15_i_c)
+uint8_t a2bus_agat_fdc_device::d15_i_c()
{
LOG("status B: @ %4d %s %s\n", 0,
BIT(m_mxcs, 7) ? "ready" : "READY", BIT(m_mxcs, 6) ? "SYNC" : "sync");
@@ -474,7 +476,7 @@ READ8_MEMBER(a2bus_agat_fdc_device::d15_i_c)
// b2 AH b7 = ready for write data
// b3 -- connected to b7, set if m_intr[PORT_A]
// b4 AH b7 = read data ready
-WRITE8_MEMBER(a2bus_agat_fdc_device::d15_o_c)
+void a2bus_agat_fdc_device::d15_o_c(uint8_t data)
{
if (BIT(data, 0) || BIT(data, 3))
{
diff --git a/src/devices/bus/a2bus/agat_fdc.h b/src/devices/bus/a2bus/agat_fdc.h
index 7ba7d4c3752..fb02a02776f 100644
--- a/src/devices/bus/a2bus/agat_fdc.h
+++ b/src/devices/bus/a2bus/agat_fdc.h
@@ -34,37 +34,29 @@ public:
// construction/destruction
a2bus_agat_fdc_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
- DECLARE_READ8_MEMBER(d14_i_b);
- DECLARE_READ8_MEMBER(d15_i_a);
- DECLARE_READ8_MEMBER(d15_i_c);
- DECLARE_WRITE8_MEMBER(d14_o_c);
- DECLARE_WRITE8_MEMBER(d15_o_b);
- DECLARE_WRITE8_MEMBER(d15_o_c);
+ uint8_t d14_i_b();
+ uint8_t d15_i_a();
+ uint8_t d15_i_c();
+ void d14_o_c(uint8_t data);
+ void d15_o_b(uint8_t data);
+ void d15_o_c(uint8_t data);
- DECLARE_FLOPPY_FORMATS(floppy_formats);
+ static void floppy_formats(format_registration &fr);
protected:
// construction/destruction
a2bus_agat_fdc_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_timer(emu_timer &timer, device_timer_id id, int param, void *ptr) override;
- virtual void device_add_mconfig(machine_config &config) override;
- virtual const tiny_rom_entry *device_rom_region() const override;
+ 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;
+ virtual const tiny_rom_entry *device_rom_region() const override ATTR_COLD;
// 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;
- enum
- {
- TIMER_ID_LSS = 0,
- TIMER_ID_SEEK,
- TIMER_ID_MOTOR
- };
-
required_device<i8255_device> m_d14;
required_device<i8255_device> m_d15;
@@ -76,7 +68,9 @@ private:
attotime cycles_to_time(uint64_t cycles);
void lss_start();
- void lss_sync();
+ TIMER_CALLBACK_MEMBER(lss_sync);
+
+ TIMER_CALLBACK_MEMBER(motor_off);
floppy_image_device *floppy;
int active, bits;
diff --git a/src/devices/bus/a2bus/booti.cpp b/src/devices/bus/a2bus/booti.cpp
new file mode 100644
index 00000000000..de4b4cfdab2
--- /dev/null
+++ b/src/devices/bus/a2bus/booti.cpp
@@ -0,0 +1,215 @@
+// license:BSD-3-Clause
+// copyright-holders:R. Belmont
+/*********************************************************************
+
+ booti.cpp
+
+ Implementation of the BOOTI card
+
+ The BOOTI is an Apple II interface to the CH376 USB module.
+ The CH376 is intended for use with small microcontrollers (or,
+ you know, the 6502) to give them access to FAT-formatted
+ flash drives. See ch376.cpp for details.
+
+ C0n0: read/write data to CH376
+ C0n1: read status/write command to CH376
+ C0n4: $C800 ROM bank (0-3)
+
+*********************************************************************/
+
+#include "emu.h"
+#include "booti.h"
+
+#include "machine/at28c64b.h"
+#include "machine/ch376.h"
+
+
+namespace {
+
+/***************************************************************************
+ PARAMETERS
+***************************************************************************/
+
+ROM_START( booti )
+ ROM_REGION(0x2000, "flash", 0)
+ ROM_LOAD( "bootifw09l.bin", 0x000000, 0x002000, CRC(be3f21ff) SHA1(f505ad4685cd44e4cce5b8d6d27b9c4fea159f11) )
+ROM_END
+
+//**************************************************************************
+// TYPE DEFINITIONS
+//**************************************************************************
+
+class a2bus_booti_device:
+ public device_t,
+ public device_a2bus_card_interface
+{
+public:
+ // construction/destruction
+ a2bus_booti_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
+
+protected:
+ a2bus_booti_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock);
+
+ 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;
+ virtual const tiny_rom_entry *device_rom_region() const override ATTR_COLD;
+
+ // 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;
+ virtual void write_cnxx(uint8_t offset, uint8_t data) override;
+ virtual uint8_t read_c800(uint16_t offset) override;
+ virtual void write_c800(uint16_t offset, uint8_t data) override;
+
+private:
+ required_device<at28c64b_device> m_flash;
+ required_device<ch376_device> m_ch376;
+
+ int m_rombank;
+};
+
+/***************************************************************************
+ FUNCTION PROTOTYPES
+***************************************************************************/
+
+//-------------------------------------------------
+// device_add_mconfig - add device configuration
+//-------------------------------------------------
+
+void a2bus_booti_device::device_add_mconfig(machine_config &config)
+{
+ AT28C64B(config, "flash", 0);
+
+ CH376(config, "ch376");
+}
+
+//-------------------------------------------------
+// rom_region - device-specific ROM region
+//-------------------------------------------------
+
+const tiny_rom_entry *a2bus_booti_device::device_rom_region() const
+{
+ return ROM_NAME( booti );
+}
+
+//**************************************************************************
+// LIVE DEVICE
+//**************************************************************************
+
+a2bus_booti_device::a2bus_booti_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_flash(*this, "flash"),
+ m_ch376(*this, "ch376"),
+ m_rombank(0)
+{
+}
+
+a2bus_booti_device::a2bus_booti_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) :
+ a2bus_booti_device(mconfig, A2BUS_BOOTI, tag, owner, clock)
+{
+}
+
+//-------------------------------------------------
+// device_start - device-specific startup
+//-------------------------------------------------
+
+void a2bus_booti_device::device_start()
+{
+ save_item(NAME(m_rombank));
+}
+
+void a2bus_booti_device::device_reset()
+{
+ m_rombank = 0;
+}
+
+
+/*-------------------------------------------------
+ read_c0nx - called for reads from this card's c0nx space
+-------------------------------------------------*/
+
+uint8_t a2bus_booti_device::read_c0nx(uint8_t offset)
+{
+ switch (offset)
+ {
+ case 0:
+ case 1:
+ return m_ch376->read(offset);
+
+ case 4:
+ return m_rombank / 0x800;
+ }
+ return 0xff;
+}
+
+
+/*-------------------------------------------------
+ write_c0nx - called for writes to this card's c0nx space
+-------------------------------------------------*/
+
+void a2bus_booti_device::write_c0nx(uint8_t offset, uint8_t data)
+{
+ switch (offset)
+ {
+ case 0:
+ case 1:
+ m_ch376->write(offset, data);
+ break;
+
+ case 4:
+ m_rombank = 0x800 * (data & 3);
+ break;
+
+ default:
+ printf("Write %02x to c0n%x (%s)\n", data, offset, machine().describe_context().c_str());
+ break;
+ }
+}
+
+/*-------------------------------------------------
+ read_cnxx - called for reads from this card's cnxx space
+-------------------------------------------------*/
+
+uint8_t a2bus_booti_device::read_cnxx(uint8_t offset)
+{
+ // slot image at 0
+ return m_flash->read(offset);
+}
+
+void a2bus_booti_device::write_cnxx(uint8_t offset, uint8_t data)
+{
+}
+
+/*-------------------------------------------------
+ read_c800 - called for reads from this card's c800 space
+-------------------------------------------------*/
+
+uint8_t a2bus_booti_device::read_c800(uint16_t offset)
+{
+ return m_flash->read(offset + m_rombank);
+}
+
+/*-------------------------------------------------
+ write_c800 - called for writes to this card's c800 space
+-------------------------------------------------*/
+void a2bus_booti_device::write_c800(uint16_t offset, uint8_t data)
+{
+ // the card appears not to pass writes to $CFFF to the EEPROM,
+ // otherwise there's a false read of the next opcode after a $CFFF write and we crash.
+ if (offset < 0x7ff)
+ {
+ m_flash->write(offset + m_rombank, data);
+ }
+}
+
+} // anonymous namespace
+
+
+//**************************************************************************
+// GLOBAL VARIABLES
+//**************************************************************************
+
+DEFINE_DEVICE_TYPE_PRIVATE(A2BUS_BOOTI, device_a2bus_card_interface, a2bus_booti_device, "a2booti", "Booti Card")
diff --git a/src/devices/bus/a2bus/booti.h b/src/devices/bus/a2bus/booti.h
new file mode 100644
index 00000000000..324a08c7c14
--- /dev/null
+++ b/src/devices/bus/a2bus/booti.h
@@ -0,0 +1,21 @@
+// license:BSD-3-Clause
+// copyright-holders:R. Belmont
+/*********************************************************************
+
+ booti.h
+
+ Implementation of the Booti card
+
+*********************************************************************/
+
+#ifndef MAME_BUS_A2BUS_BOOTI_H
+#define MAME_BUS_A2BUS_BOOTI_H
+
+#pragma once
+
+#include "a2bus.h"
+
+// device type definition
+DECLARE_DEVICE_TYPE(A2BUS_BOOTI, device_a2bus_card_interface)
+
+#endif // MAME_BUS_A2BUS_BOOTI_H
diff --git a/src/devices/bus/a2bus/byte8251.cpp b/src/devices/bus/a2bus/byte8251.cpp
new file mode 100644
index 00000000000..fef5f19c0ac
--- /dev/null
+++ b/src/devices/bus/a2bus/byte8251.cpp
@@ -0,0 +1,149 @@
+// license:BSD-3-Clause
+// copyright-holders:AJR
+/**********************************************************************
+
+ This 8251-based RS232 compatible serial interface is described
+ in the article "Cross-Pollinating the Apple II" by Richard
+ Campbell, BYTE Volume 4 Number 4, April 1979, pages 20-25. It
+ works more as a proof of concept than a full-featured peripheral.
+
+ Rates are generated by the MM5307AA based on an 895 kHz division
+ of the bus clock, since no onboard oscillator is provided. The
+ resulting data rates are, as the author notes, “3 percent low,
+ but in practice this is close enough.”
+
+ Only TXD and RXD are connected to the 1488 driver and 1489
+ receiver, though, as the author admits, they have enough spare
+ pins that modem control signals could be easily added.
+
+***********************************************************************
+
+ List of integrated circuits (complete)
+
+ No. Type Function
+ --- ---- --------
+ IC1 74LS04 Invert read and reset signals from Apple bus
+ IC2 8251 Serial-to-parallel/parallel-to-serial conversion
+ IC3 74LS161 Divide 7 MHz Apple bus signal by 8
+ IC4 MM5307AA Data rate generation
+ IC5 LM1488 TTL to RS232 level conversion (TXD)
+ IC6 LM1489 RS232 to TTL level conversion (RXD)
+
+**********************************************************************/
+
+#include "emu.h"
+#include "byte8251.h"
+
+#include "bus/rs232/rs232.h"
+#include "machine/i8251.h"
+#include "machine/mm5307.h"
+
+
+namespace {
+
+class a2bus_byte8251_device : public device_t, public device_a2bus_card_interface
+{
+public:
+ // construction/destruction
+ a2bus_byte8251_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock);
+
+ DECLARE_INPUT_CHANGED_MEMBER(rate_changed);
+
+protected:
+ // device-level overrides
+ virtual void device_start() override ATTR_COLD;
+ virtual void device_reset() override ATTR_COLD;
+ virtual ioport_constructor device_input_ports() const override ATTR_COLD;
+ virtual void device_add_mconfig(machine_config &config) override ATTR_COLD;
+
+ // 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<i8251_device> m_usart;
+ required_device<mm5307_device> m_brg;
+ required_ioport m_switches;
+};
+
+a2bus_byte8251_device::a2bus_byte8251_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock)
+ : device_t(mconfig, A2BUS_BYTE8251, tag, owner, clock)
+ , device_a2bus_card_interface(mconfig, *this)
+ , m_usart(*this, "8251")
+ , m_brg(*this, "brg")
+ , m_switches(*this, "SWITCHES")
+{
+}
+
+void a2bus_byte8251_device::device_start()
+{
+ // CTS grounded
+ m_usart->write_cts(0);
+}
+
+void a2bus_byte8251_device::device_reset()
+{
+ // Update data rate
+ m_brg->control_w(m_switches->read());
+}
+
+INPUT_CHANGED_MEMBER(a2bus_byte8251_device::rate_changed)
+{
+ m_brg->control_w(newval);
+}
+
+u8 a2bus_byte8251_device::read_c0nx(u8 offset)
+{
+ return m_usart->read(offset & 1);
+}
+
+void a2bus_byte8251_device::write_c0nx(u8 offset, u8 data)
+{
+ m_usart->write(offset & 1, data);
+}
+
+static INPUT_PORTS_START(byte8251)
+ PORT_START("SWITCHES") // “A dual in line pin-type switch may be used”
+ PORT_DIPNAME(0xf, 0xf, "Data Rate") PORT_DIPLOCATION("S:1,2,3,4") PORT_CHANGED_MEMBER(DEVICE_SELF, FUNC(a2bus_byte8251_device::rate_changed), 0)
+ PORT_DIPSETTING(0x1, "50 bps")
+ PORT_DIPSETTING(0x2, "75 bps")
+ PORT_DIPSETTING(0x3, "110 bps")
+ PORT_DIPSETTING(0x4, "134.5 bps")
+ PORT_DIPSETTING(0x5, "150 bps")
+ PORT_DIPSETTING(0x6, "300 bps")
+ PORT_DIPSETTING(0x7, "600 bps")
+ PORT_DIPSETTING(0x8, "900 bps")
+ PORT_DIPSETTING(0x9, "1200 bps")
+ PORT_DIPSETTING(0xa, "1800 bps")
+ PORT_DIPSETTING(0xb, "2400 bps")
+ PORT_DIPSETTING(0xc, "3600 bps")
+ PORT_DIPSETTING(0xd, "4800 bps")
+ PORT_DIPSETTING(0xe, "7200 bps")
+ PORT_DIPSETTING(0xf, "9600 bps")
+INPUT_PORTS_END
+
+ioport_constructor a2bus_byte8251_device::device_input_ports() const
+{
+ return INPUT_PORTS_NAME(byte8251);
+}
+
+void a2bus_byte8251_device::device_add_mconfig(machine_config &config)
+{
+ I8251(config, m_usart, 1021800); // CLK tied to ϕ1 signal from bus pin 38
+ m_usart->txd_handler().set("rs232", FUNC(rs232_port_device::write_txd));
+
+ MM5307AA(config, m_brg, DERIVED_CLOCK(1, 8));
+ m_brg->output_cb().set(m_usart, FUNC(i8251_device::write_txc));
+ m_brg->output_cb().append(m_usart, FUNC(i8251_device::write_rxc));
+
+ rs232_port_device &rs232(RS232_PORT(config, "rs232", default_rs232_devices, nullptr));
+ rs232.rxd_handler().set(m_usart, FUNC(i8251_device::write_rxd));
+}
+
+} // anonymous namespace
+
+
+// device type definition
+DEFINE_DEVICE_TYPE_PRIVATE(A2BUS_BYTE8251, device_a2bus_card_interface, a2bus_byte8251_device, "a2bus_byte8251", "BYTE Serial Interface (8251 based)")
diff --git a/src/devices/bus/a2bus/byte8251.h b/src/devices/bus/a2bus/byte8251.h
new file mode 100644
index 00000000000..829bd968649
--- /dev/null
+++ b/src/devices/bus/a2bus/byte8251.h
@@ -0,0 +1,13 @@
+// license:BSD-3-Clause
+// copyright-holders:AJR
+#ifndef MAME_BUS_A2BUS_BYTE8251_H
+#define MAME_BUS_A2BUS_BYTE8251_H
+
+#pragma once
+
+#include "a2bus.h"
+
+// device type declaration
+DECLARE_DEVICE_TYPE(A2BUS_BYTE8251, device_a2bus_card_interface)
+
+#endif // MAME_BUS_A2BUS_BYTE8251_H
diff --git a/src/devices/bus/a2bus/cards.cpp b/src/devices/bus/a2bus/cards.cpp
new file mode 100644
index 00000000000..cc2380fd455
--- /dev/null
+++ b/src/devices/bus/a2bus/cards.cpp
@@ -0,0 +1,330 @@
+// license:BSD-3-Clause
+// copyright-holders:R. Belmont
+/***************************************************************************
+
+ Apple II bus slot cards
+
+ All of these cards are electrically compatible, but for compatibility
+ reasons we divide them by machine type.
+
+***************************************************************************/
+
+#include "emu.h"
+#include "cards.h"
+
+#include "4play.h"
+#include "a2alfam2.h"
+#include "a2applicard.h"
+#include "a2arcadebd.h"
+#include "a2cffa.h"
+#include "a2corvus.h"
+#include "a2diskiing.h"
+#include "a2dx1.h"
+#include "a2echoii.h"
+#include "a2hsscsi.h"
+#include "a2iwm.h"
+#include "a2mcms.h"
+#include "a2memexp.h"
+#include "a2midi.h"
+#include "a2mockingboard.h"
+#include "a2parprn.h"
+#include "a2pic.h"
+#include "a2sam.h"
+#include "a2scsi.h"
+#include "a2sd.h"
+#include "a2softcard.h"
+#include "a2ssc.h"
+#include "a2superdrive.h"
+#include "a2swyft.h"
+#include "a2themill.h"
+#include "a2thunderclock.h"
+#include "a2ultraterm.h"
+#include "a2videoterm.h"
+#include "a2vulcan.h"
+#include "a2wico_trackball.h"
+#include "a2zipdrive.h"
+#include "booti.h"
+#include "byte8251.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 "uthernet.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("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
+ device.option_add("mockingboard", A2BUS_MOCKINGBOARD); // Sweet Micro Systems Mockingboard
+ device.option_add("phasor", A2BUS_PHASOR); // Applied Engineering Phasor
+ device.option_add("cffa2", A2BUS_CFFA2); // CFFA2000 Compact Flash for Apple II (www.dreher.net), 65C02/65816 firmware
+ device.option_add("cffa202", A2BUS_CFFA2_6502); // CFFA2000 Compact Flash for Apple II (www.dreher.net), 6502 firmware
+ device.option_add("memexp", A2BUS_MEMEXP); // Apple II Memory Expansion Card
+ device.option_add("ramfactor", A2BUS_RAMFACTOR); // Applied Engineering RamFactor
+ device.option_add("thclock", A2BUS_THUNDERCLOCK); // ThunderWare ThunderClock Plus
+ device.option_add("softcard", A2BUS_SOFTCARD); // Microsoft SoftCard
+ device.option_add("videoterm", A2BUS_VIDEOTERM); // Videx VideoTerm
+ device.option_add("ssc", A2BUS_SSC); // Apple Super Serial Card
+ device.option_add("ssi", APRICORN_SSI); // Apricorn Super Serial Imager
+ device.option_add("swyft", A2BUS_SWYFT); // IAI SwyftCard
+ device.option_add("themill", A2BUS_THEMILL); // Stellation Two The Mill (6809 card)
+ device.option_add("sam", A2BUS_SAM); // SAM Software Automated Mouth (8-bit DAC + speaker)
+ device.option_add("alfam2", A2BUS_ALFAM2); // ALF Apple Music II
+ device.option_add("echoii", A2BUS_ECHOII); // Street Electronics Echo II
+ device.option_add("ap16", A2BUS_IBSAP16); // IBS AP16 (German VideoTerm clone)
+ device.option_add("ap16alt", A2BUS_IBSAP16ALT); // IBS AP16 (German VideoTerm clone), alternate revision
+ device.option_add("vtc1", A2BUS_VTC1); // Unknown VideoTerm clone
+ device.option_add("arcbd", A2BUS_ARCADEBOARD); // Third Millenium Engineering Arcade Board
+ device.option_add("midi", A2BUS_MIDI); // Generic 6840+6850 MIDI board
+ device.option_add("zipdrive", A2BUS_ZIPDRIVE); // ZIP Technologies IDE card
+ device.option_add("echoiiplus", A2BUS_ECHOPLUS); // Street Electronics Echo Plus (Echo II + Mockingboard clone)
+ device.option_add("scsi", A2BUS_SCSI); // Apple II SCSI Card
+ device.option_add("applicard", A2BUS_APPLICARD); // PCPI Applicard
+ device.option_add("aesms", A2BUS_AESMS); // Applied Engineering Super Music Synthesizer
+ device.option_add("ultraterm", A2BUS_ULTRATERM); // Videx UltraTerm (original)
+ 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
+ device.option_add("bufgrapplus", A2BUS_BUFGRAPPLERPLUS); // Orange Micro Buffered Grappler+ Printer Interface card
+ device.option_add("bufgrapplusa", A2BUS_BUFGRAPPLERPLUSA); // Orange Micro Buffered Grappler+ (rev A) Printer Interface card
+ device.option_add("corvus", A2BUS_CORVUS); // Corvus flat-cable HDD interface (see notes in a2corvus.c)
+ device.option_add("mcms1", A2BUS_MCMS1); // Mountain Computer Music System, card 1 of 2
+ device.option_add("mcms2", A2BUS_MCMS2); // Mountain Computer Music System, card 2 of 2. must be in card 1's slot + 1!
+ device.option_add("dx1", A2BUS_DX1); // Decillonix DX-1 sampler card
+ device.option_add("tm2ho", A2BUS_TIMEMASTERHO); // Applied Engineering TimeMaster II H.O.
+ device.option_add("mouse", A2BUS_MOUSE); // Apple II Mouse Card
+ device.option_add("ezcgi", A2BUS_EZCGI); // E-Z Color Graphics Interface
+ device.option_add("ezcgi9938", A2BUS_EZCGI_9938); // E-Z Color Graphics Interface (TMS9938)
+ device.option_add("ezcgi9958", A2BUS_EZCGI_9958); // E-Z Color Graphics Interface (TMS9958)
+ 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
+ device.option_add("booti", A2BUS_BOOTI); // Booti Card
+ device.option_add("q68", A2BUS_Q68); // Stellation Q68 68000 card
+ 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
+ device.option_add("wicotrackball", A2BUS_WICOTRACKBALL); // Wico Trackball
+}
+
+void apple2e_cards(device_slot_interface &device)
+{
+ 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
+ device.option_add("mockingboard", A2BUS_MOCKINGBOARD); // Sweet Micro Systems Mockingboard
+ device.option_add("phasor", A2BUS_PHASOR); // Applied Engineering Phasor
+ device.option_add("cffa2", A2BUS_CFFA2); // CFFA2000 Compact Flash for Apple II (www.dreher.net), 65C02/65816 firmware
+ device.option_add("cffa202", A2BUS_CFFA2_6502); // CFFA2000 Compact Flash for Apple II (www.dreher.net), 6502 firmware
+ device.option_add("memexp", A2BUS_MEMEXP); // Apple II Memory Expansion Card
+ device.option_add("ramfactor", A2BUS_RAMFACTOR); // Applied Engineering RamFactor
+ device.option_add("thclock", A2BUS_THUNDERCLOCK); // ThunderWare ThunderClock Plus
+ device.option_add("softcard", A2BUS_SOFTCARD); // Microsoft SoftCard
+ device.option_add("videoterm", A2BUS_VIDEOTERM); // Videx VideoTerm
+ device.option_add("ssc", A2BUS_SSC); // Apple Super Serial Card
+ device.option_add("ssi", APRICORN_SSI); // Apricorn Super Serial Imager
+ device.option_add("swyft", A2BUS_SWYFT); // IAI SwyftCard
+ device.option_add("themill", A2BUS_THEMILL); // Stellation Two The Mill (6809 card)
+ device.option_add("sam", A2BUS_SAM); // SAM Software Automated Mouth (8-bit DAC + speaker)
+ device.option_add("alfam2", A2BUS_ALFAM2); // ALF Apple Music II
+ device.option_add("echoii", A2BUS_ECHOII); // Street Electronics Echo II
+ device.option_add("ap16", A2BUS_IBSAP16); // IBS AP16 (German VideoTerm clone)
+ device.option_add("ap16alt", A2BUS_IBSAP16ALT); // IBS AP16 (German VideoTerm clone), alternate revision
+ device.option_add("vtc1", A2BUS_VTC1); // Unknown VideoTerm clone
+ device.option_add("arcbd", A2BUS_ARCADEBOARD); // Third Millenium Engineering Arcade Board
+ device.option_add("midi", A2BUS_MIDI); // Generic 6840+6850 MIDI board
+ device.option_add("zipdrive", A2BUS_ZIPDRIVE); // ZIP Technologies IDE card
+ device.option_add("focusdrive", A2BUS_FOCUSDRIVE); // Focus Drive IDE card
+ device.option_add("echoiiplus", A2BUS_ECHOPLUS); // Street Electronics Echo Plus (Echo II + Mockingboard clone)
+ device.option_add("scsi", A2BUS_SCSI); // Apple II SCSI Card
+ device.option_add("hsscsi", A2BUS_HSSCSI); // Apple II High-Speed SCSI Card
+ device.option_add("applicard", A2BUS_APPLICARD); // PCPI Applicard
+ device.option_add("aesms", A2BUS_AESMS); // Applied Engineering Super Music Synthesizer
+ device.option_add("ultraterm", A2BUS_ULTRATERM); // Videx UltraTerm (original)
+ 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
+ device.option_add("bufgrapplus", A2BUS_BUFGRAPPLERPLUS); // Orange Micro Buffered Grappler+ Printer Interface card
+ device.option_add("bufgrapplusa", A2BUS_BUFGRAPPLERPLUSA); // Orange Micro Buffered Grappler+ (rev A) Printer Interface card
+ device.option_add("corvus", A2BUS_CORVUS); // Corvus flat-cable HDD interface (see notes in a2corvus.c)
+ device.option_add("mcms1", A2BUS_MCMS1); // Mountain Computer Music System, card 1 of 2
+ device.option_add("mcms2", A2BUS_MCMS2); // Mountain Computer Music System, card 2 of 2. must be in card 1's slot + 1!
+ device.option_add("dx1", A2BUS_DX1); // Decillonix DX-1 sampler card
+ device.option_add("tm2ho", A2BUS_TIMEMASTERHO); // Applied Engineering TimeMaster II H.O.
+ device.option_add("mouse", A2BUS_MOUSE); // Apple II Mouse Card
+ device.option_add("ezcgi", A2BUS_EZCGI); // E-Z Color Graphics Interface
+ device.option_add("ezcgi9938", A2BUS_EZCGI_9938); // E-Z Color Graphics Interface (TMS9938)
+ device.option_add("ezcgi9958", A2BUS_EZCGI_9958); // E-Z Color Graphics Interface (TMS9958)
+// device.option_add("magicmusician", A2BUS_MAGICMUSICIAN); // Magic Musician Card
+ device.option_add("pcxport", A2BUS_PCXPORTER); // Applied Engineering PC Transporter
+ device.option_add("ssprite", A2BUS_SSPRITE); // Synetix SuperSprite Board
+ device.option_add("ssbapple", A2BUS_SSBAPPLE); // SSB Apple speech board
+ 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
+ device.option_add("sider1", A2BUS_SIDER1); // Advanced Tech Systems / First Class Peripherals Sider 1 SASI 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
+ device.option_add("booti", A2BUS_BOOTI); // Booti Card
+ device.option_add("lancegs", A2BUS_LANCEGS); // ///SHH SYSTEME LANceGS Card
+ device.option_add("q68", A2BUS_Q68); // Stellation Q68 68000 card
+ device.option_add("q68plus", A2BUS_Q68PLUS); // Stellation Q68 Plus 68000 card
+ device.option_add("a2sd", A2BUS_A2SD); // Florian Reitz AppleIISD
+ 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
+ device.option_add("wicotrackball", A2BUS_WICOTRACKBALL); // Wico Trackball
+}
+
+void apple2gs_cards(device_slot_interface &device)
+{
+ device.option_add("diskiing", A2BUS_DISKIING); // Disk II Controller Card, cycle-accurate version
+ device.option_add("mockingboard", A2BUS_MOCKINGBOARD); // Sweet Micro Systems Mockingboard
+ device.option_add("phasor", A2BUS_PHASOR); // Applied Engineering Phasor
+ device.option_add("cffa2", A2BUS_CFFA2); // CFFA2000 Compact Flash for Apple II (www.dreher.net), 65C02/65816 firmware
+ device.option_add("cffa202", A2BUS_CFFA2_6502); // CFFA2000 Compact Flash for Apple II (www.dreher.net), 6502 firmware
+ device.option_add("memexp", A2BUS_MEMEXP); // Apple II Memory Expansion Card
+ device.option_add("ramfactor", A2BUS_RAMFACTOR); // Applied Engineering RamFactor
+ device.option_add("thclock", A2BUS_THUNDERCLOCK); // ThunderWare ThunderClock Plus
+ device.option_add("softcard", A2BUS_SOFTCARD); // Microsoft SoftCard
+ device.option_add("videoterm", A2BUS_VIDEOTERM); // Videx VideoTerm
+ device.option_add("ssc", A2BUS_SSC); // Apple Super Serial Card
+ device.option_add("ssi", APRICORN_SSI); // Apricorn Super Serial Imager
+ device.option_add("swyft", A2BUS_SWYFT); // IAI SwyftCard
+ device.option_add("themill", A2BUS_THEMILL); // Stellation Two The Mill (6809 card)
+ device.option_add("sam", A2BUS_SAM); // SAM Software Automated Mouth (8-bit DAC + speaker)
+ device.option_add("alfam2", A2BUS_ALFAM2); // ALF Apple Music II
+ device.option_add("echoii", A2BUS_ECHOII); // Street Electronics Echo II
+ device.option_add("ap16", A2BUS_IBSAP16); // IBS AP16 (German VideoTerm clone)
+ device.option_add("ap16alt", A2BUS_IBSAP16ALT); // IBS AP16 (German VideoTerm clone), alternate revision
+ device.option_add("vtc1", A2BUS_VTC1); // Unknown VideoTerm clone
+ device.option_add("arcbd", A2BUS_ARCADEBOARD); // Third Millenium Engineering Arcade Board
+ device.option_add("midi", A2BUS_MIDI); // Generic 6840+6850 MIDI board
+ device.option_add("zipdrive", A2BUS_ZIPDRIVE); // ZIP Technologies IDE card
+ device.option_add("focusdrive", A2BUS_FOCUSDRIVE); // Focus Drive IDE card
+ device.option_add("echoiiplus", A2BUS_ECHOPLUS); // Street Electronics Echo Plus (Echo II + Mockingboard clone)
+ device.option_add("scsi", A2BUS_SCSI); // Apple II SCSI Card
+ device.option_add("hsscsi", A2BUS_HSSCSI); // Apple II High-Speed SCSI Card
+ device.option_add("applicard", A2BUS_APPLICARD); // PCPI Applicard
+ device.option_add("aesms", A2BUS_AESMS); // Applied Engineering Super Music Synthesizer
+ device.option_add("ultraterm", A2BUS_ULTRATERM); // Videx UltraTerm (original)
+ 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
+ device.option_add("bufgrapplus", A2BUS_BUFGRAPPLERPLUS); // Orange Micro Buffered Grappler+ Printer Interface card
+ device.option_add("bufgrapplusa", A2BUS_BUFGRAPPLERPLUSA); // Orange Micro Buffered Grappler+ (rev A) Printer Interface card
+ device.option_add("corvus", A2BUS_CORVUS); // Corvus flat-cable HDD interface (see notes in a2corvus.c)
+ device.option_add("mcms1", A2BUS_MCMS1); // Mountain Computer Music System, card 1 of 2
+ device.option_add("mcms2", A2BUS_MCMS2); // Mountain Computer Music System, card 2 of 2. must be in card 1's slot + 1!
+ device.option_add("dx1", A2BUS_DX1); // Decillonix DX-1 sampler card
+ device.option_add("tm2ho", A2BUS_TIMEMASTERHO); // Applied Engineering TimeMaster II H.O.
+ device.option_add("mouse", A2BUS_MOUSE); // Apple II Mouse Card
+ device.option_add("ezcgi", A2BUS_EZCGI); // E-Z Color Graphics Interface
+ device.option_add("ezcgi9938", A2BUS_EZCGI_9938); // E-Z Color Graphics Interface (TMS9938)
+ device.option_add("ezcgi9958", A2BUS_EZCGI_9958); // E-Z Color Graphics Interface (TMS9958)
+ 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
+ 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
+ device.option_add("sider1", A2BUS_SIDER1); // Advanced Tech Systems / First Class Peripherals Sider 1 SASI 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
+ device.option_add("booti", A2BUS_BOOTI); // Booti Card
+ device.option_add("lancegs", A2BUS_LANCEGS); // ///SHH SYSTEME LANceGS Card
+ device.option_add("q68", A2BUS_Q68); // Stellation Q68 68000 card
+ device.option_add("q68plus", A2BUS_Q68PLUS); // Stellation Q68 Plus 68000 card
+ 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("wicotrackball", A2BUS_WICOTRACKBALL); // Wico Trackball
+}
+
+void apple3_cards(device_slot_interface &device)
+{
+ device.option_add("cffa2", A2BUS_CFFA2_6502); // CFFA2.0 Compact Flash for Apple II (www.dreher.net), 6502 firmware
+ device.option_add("applicard", A2BUS_APPLICARD); // PCPI Applicard
+ device.option_add("thclock", A2BUS_THUNDERCLOCK); // ThunderWare ThunderClock Plus - driver assumes slot 2 by default
+ device.option_add("mouse", A2BUS_MOUSE); // Apple II Mouse Card
+ device.option_add("focusdrive", A2BUS_FOCUSDRIVE); // Focus Drive IDE card
+ device.option_add("cmsscsi", A2BUS_CMSSCSI); // CMS Apple II SCSI Card
+ device.option_add("titan3plus2", A2BUS_TITAN3PLUS2); // Titan /// Plus 2 card
+ device.option_add("mockingboard", A2BUS_MOCKINGBOARD); // Sweet Micro Systems Mockingboard (experimental on ///)
+ device.option_add("softcard3", A2BUS_SOFTCARD3); // Microsoft SoftCard ///
+ device.option_add("grafex", A2BUS_GRAFEX); // Grafex card (µPD7220 graphics)
+}
diff --git a/src/devices/bus/a2bus/cards.h b/src/devices/bus/a2bus/cards.h
new file mode 100644
index 00000000000..8bbdc71c33a
--- /dev/null
+++ b/src/devices/bus/a2bus/cards.h
@@ -0,0 +1,23 @@
+// license:BSD-3-Clause
+// copyright-holders:R. Belmont
+/***************************************************************************
+
+ Apple II bus slot cards
+
+ All of these cards are electrically compatible, but for compatibility
+ reasons we divide them by machine type.
+
+***************************************************************************/
+
+#ifndef MAME_BUS_A2BUS_CARDS_H
+#define MAME_BUS_A2BUS_CARDS_H
+
+#pragma once
+
+void apple2_slot0_cards(device_slot_interface &device) ATTR_COLD;
+void apple2_cards(device_slot_interface &device) ATTR_COLD;
+void apple2e_cards(device_slot_interface &device) ATTR_COLD;
+void apple2gs_cards(device_slot_interface &device) ATTR_COLD;
+void apple3_cards(device_slot_interface &device) ATTR_COLD;
+
+#endif // MAME_BUS_A2BUS_CARDS_H
diff --git a/src/devices/bus/a2bus/ccs7710.cpp b/src/devices/bus/a2bus/ccs7710.cpp
new file mode 100644
index 00000000000..3a6d1449fbb
--- /dev/null
+++ b/src/devices/bus/a2bus/ccs7710.cpp
@@ -0,0 +1,155 @@
+// license:BSD-3-Clause
+// copyright-holders:AJR
+/*********************************************************************
+
+ California Computer Systems, Inc. Model 7710
+ Asynchronous Serial Interface (ASI-1)
+
+ One unusual feature of this small RS-232-C communications card
+ which is not relevant for emulation is that the DP8304B bus
+ buffer and program ROMs are powered down when they are not being
+ accessed. Another unemulated feature is a suggested modification
+ to replace the two 256×4 program ROMs with like-sized 2112 RAMs
+ (the R/W bus signal is enabled to these with a jumper connection)
+ so that custom firmware can be uploaded instead.
+
+ The 7710-02 terminal firmware is incompatible with the Apple IIe
+ due to the use of a II+-specific monitor location. One recommended
+ way to work around this problem was to load the II+ monitor into
+ the IIe's language card. The incompatibility was corrected in
+ 7710-03, and the 7710-03 ROMs were the only ones delivered after
+ July 1983.
+
+**********************************************************************/
+
+#include "emu.h"
+#include "ccs7710.h"
+
+#include "bus/rs232/rs232.h"
+
+//**************************************************************************
+// GLOBAL VARIABLES
+//**************************************************************************
+
+// device type definition
+DEFINE_DEVICE_TYPE(A2BUS_CCS7710, ccs7710_device, "ccs7710", "CCS Model 7710 Asynchronous Serial Interface")
+
+//**************************************************************************
+// DEVICE IMPLEMENTATION
+//**************************************************************************
+
+ccs7710_device::ccs7710_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock)
+ : device_t(mconfig, A2BUS_CCS7710, tag, owner, clock)
+ , device_a2bus_card_interface(mconfig, *this)
+ , m_acia(*this, "acia")
+ , m_brg(*this, "brg")
+ , m_firmware(*this, "firmware")
+ , m_baud_select(*this, "BAUD")
+ , m_external_clock(false)
+{
+}
+
+void ccs7710_device::device_start()
+{
+ save_item(NAME(m_external_clock));
+}
+
+u8 ccs7710_device::read_c0nx(u8 offset)
+{
+ return m_acia->read(offset & 1);
+}
+
+void ccs7710_device::write_c0nx(u8 offset, u8 data)
+{
+ m_acia->write(offset & 1, data);
+}
+
+u8 ccs7710_device::read_cnxx(u8 offset)
+{
+ return m_firmware[offset];
+}
+
+void ccs7710_device::acia_irq_w(int state)
+{
+ if (state == ASSERT_LINE)
+ raise_slot_irq();
+ else
+ lower_slot_irq();
+}
+
+void ccs7710_device::external_clock_w(int state)
+{
+ m_external_clock = state;
+ if (!BIT(m_baud_select->read(), 0))
+ m_brg->im_w(state);
+}
+
+u8 ccs7710_device::baud_select_r(offs_t offset)
+{
+ u8 baud = m_baud_select->read();
+ m_brg->im_w(BIT(baud, 0) ? !BIT(offset, 2) : m_external_clock);
+ return baud;
+}
+
+static INPUT_PORTS_START(ccs7710)
+ PORT_START("BAUD")
+ PORT_DIPNAME(0xf, 0x8, "Baud Rate") PORT_DIPLOCATION("S1:1,2,3,4")
+ PORT_DIPSETTING(0x0, "External")
+ PORT_DIPSETTING(0x2, "50")
+ PORT_DIPSETTING(0x3, "75")
+ PORT_DIPSETTING(0xf, "110")
+ PORT_DIPSETTING(0x4, "134.5")
+ PORT_DIPSETTING(0xe, "150")
+ PORT_DIPSETTING(0x5, "200")
+ PORT_DIPSETTING(0xd, "300")
+ PORT_DIPSETTING(0x6, "600")
+ PORT_DIPSETTING(0xb, "1200")
+ PORT_DIPSETTING(0xa, "1800")
+ PORT_DIPSETTING(0x7, "2400")
+ PORT_DIPSETTING(0x9, "4800")
+ PORT_DIPSETTING(0x8, "9600")
+ PORT_DIPSETTING(0x1, "19200")
+INPUT_PORTS_END
+
+ioport_constructor ccs7710_device::device_input_ports() const
+{
+ return INPUT_PORTS_NAME(ccs7710);
+}
+
+void ccs7710_device::device_add_mconfig(machine_config &config)
+{
+ ACIA6850(config, m_acia);
+ m_acia->rts_handler().set("rs232", FUNC(rs232_port_device::write_rts));
+ m_acia->txd_handler().set("rs232", FUNC(rs232_port_device::write_txd));
+ m_acia->irq_handler().set(FUNC(ccs7710_device::acia_irq_w));
+
+ F4702(config, m_brg, 2.4576_MHz_XTAL);
+ m_brg->s_callback().set(FUNC(ccs7710_device::baud_select_r));
+ m_brg->z_callback().set(m_acia, FUNC(acia6850_device::write_rxc));
+ m_brg->z_callback().append(m_acia, FUNC(acia6850_device::write_txc));
+
+ rs232_port_device &rs232(RS232_PORT(config, "rs232", default_rs232_devices, nullptr));
+ 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.txc_handler().set(FUNC(ccs7710_device::external_clock_w));
+}
+
+ROM_START(ccs7710)
+ ROM_REGION(0x100, "firmware", 0)
+ ROM_DEFAULT_BIOS("7710-03")
+ ROM_SYSTEM_BIOS(0, "7710-01", "CCS 7710-01")
+ ROMX_LOAD("7710-01h.u5", 0x000, 0x100, CRC(4f4b1023) SHA1(4f96f9cbbad383c259d4a3f8762263d01532c735), ROM_BIOS(0) | ROM_NIBBLE | ROM_SHIFT_NIBBLE_HI)
+ ROMX_LOAD("7710-01l.u6", 0x000, 0x100, CRC(1dab7113) SHA1(c9c7b8b73db90fa008c8779b1d75ac265ec6ca2f), ROM_BIOS(0) | ROM_NIBBLE | ROM_SHIFT_NIBBLE_LO)
+ ROM_SYSTEM_BIOS(1, "7710-02", "CCS 7710-02")
+ ROMX_LOAD("7710-02h.u5", 0x000, 0x100, CRC(46ded0cc) SHA1(62a087e3a1790a9910561d84001acaa9ec804194), ROM_BIOS(1) | ROM_NIBBLE | ROM_SHIFT_NIBBLE_HI)
+ ROMX_LOAD("7710-02l.u6", 0x000, 0x100, CRC(d4922d69) SHA1(a651dbd3faba9476aff382952266188f3cb05f16), ROM_BIOS(1) | ROM_NIBBLE | ROM_SHIFT_NIBBLE_LO)
+ ROM_SYSTEM_BIOS(2, "7710-03", "CCS 7710-03")
+ ROMX_LOAD("7710-03h.u5", 0x000, 0x100, CRC(a2cdb6bd) SHA1(6ecfb6b145256d4787a943da8ef267303df562d6), ROM_BIOS(2) | ROM_NIBBLE | ROM_SHIFT_NIBBLE_HI)
+ ROMX_LOAD("7710-03l.u6", 0x000, 0x100, CRC(18e3983f) SHA1(d0df2aaf0134f8c1b929a4de0036fedc7e7164e2), ROM_BIOS(2) | ROM_NIBBLE | ROM_SHIFT_NIBBLE_LO)
+ROM_END
+
+const tiny_rom_entry *ccs7710_device::device_rom_region() const
+{
+ return ROM_NAME(ccs7710);
+}
diff --git a/src/devices/bus/a2bus/ccs7710.h b/src/devices/bus/a2bus/ccs7710.h
new file mode 100644
index 00000000000..4277b444d70
--- /dev/null
+++ b/src/devices/bus/a2bus/ccs7710.h
@@ -0,0 +1,56 @@
+// license:BSD-3-Clause
+// copyright-holders:AJR
+/*********************************************************************
+
+ CCS Model 7710 Asynchronous Serial Interface
+
+*********************************************************************/
+
+#ifndef MAME_BUS_A2BUS_CCS7710_H
+#define MAME_BUS_A2BUS_CCS7710_H
+
+#pragma once
+
+#include "a2bus.h"
+#include "machine/6850acia.h"
+#include "machine/f4702.h"
+
+class ccs7710_device : public device_t, public device_a2bus_card_interface
+{
+public:
+ // device type constructor
+ ccs7710_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock);
+
+protected:
+ // device-level overrides
+ virtual void device_start() override ATTR_COLD;
+ virtual ioport_constructor device_input_ports() const override ATTR_COLD;
+ virtual void device_add_mconfig(machine_config &config) override ATTR_COLD;
+ virtual const tiny_rom_entry *device_rom_region() const override ATTR_COLD;
+
+ // device_a2bus_card_interface overrides
+ 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; }
+
+private:
+ // miscellaneous handlers
+ void acia_irq_w(int state);
+ void external_clock_w(int state);
+ u8 baud_select_r(offs_t offset);
+
+ // object finders
+ required_device<acia6850_device> m_acia;
+ required_device<f4702_device> m_brg;
+ required_region_ptr<u8> m_firmware;
+ required_ioport m_baud_select;
+
+ // internal state
+ bool m_external_clock;
+};
+
+// device type declaration
+DECLARE_DEVICE_TYPE(A2BUS_CCS7710, ccs7710_device)
+
+#endif // MAME_BUS_A2BUS_CCS7710_H
diff --git a/src/devices/bus/a2bus/cmsscsi.cpp b/src/devices/bus/a2bus/cmsscsi.cpp
new file mode 100644
index 00000000000..77a7ade3e6f
--- /dev/null
+++ b/src/devices/bus/a2bus/cmsscsi.cpp
@@ -0,0 +1,245 @@
+// license:BSD-3-Clause
+// copyright-holders:R. Belmont
+/*********************************************************************
+
+ cmsscsi.cpp
+
+ Implementation of the CMS SCSI II Card
+
+ Details:
+ ROM is $2000 bytes. The last $800 bytes are 7 slot images at
+ offset (slot*$100). There is no slot 0 image, naturally, so $1800-$18FF
+ is blank.
+
+ The other $1800 bytes of the ROM are banked at $C800. The first $80
+ bytes at $C800 are the first $80 bytes of the 2K SRAM chip regardless
+ of the ROM bank setting. This also means the first $80 bytes of each
+ ROM bank are inaccessible. (Most of the SRAM is also inaccessible)
+
+ $C0(n+8)X space:
+ $0-$7: NCR5380 registers
+ $8: Appears to control SCSI delay time. 1 is shortest, 0 is longest ($FF is second longest, etc)
+ $9: ROM bank at $C800 in the low 2 bits.
+ $A: read/write to the DMA data register on the 5380
+ $B, $C, $D, $E: the jumpers on the card. Not sure yet which is which.
+ $F: Card will not boot if it doesn't return 0.
+
+*********************************************************************/
+
+#include "emu.h"
+#include "cmsscsi.h"
+#include "bus/nscsi/devices.h"
+
+/***************************************************************************
+ PARAMETERS
+***************************************************************************/
+
+//**************************************************************************
+// GLOBAL VARIABLES
+//**************************************************************************
+
+DEFINE_DEVICE_TYPE(A2BUS_CMSSCSI, a2bus_cmsscsi_device, "cmsscsi", "CMS SCSI II Card")
+
+#define SCSI_ROM_REGION "scsi_rom"
+#define SCSI_BUS_TAG "scsibus"
+#define SCSI_5380_TAG "scsibus:7:ncr5380"
+
+ROM_START( scsi )
+ ROM_REGION(0x4000, SCSI_ROM_REGION, 0)
+ ROM_DEFAULT_BIOS("cms3190")
+ ROM_SYSTEM_BIOS( 0, "cms3190", "CMS SCSI BIOS dated 3-1-90" )
+ ROMX_LOAD( "cms scsi ii interface card rom 3-1-90.bin", 0x000000, 0x002000, CRC(9452cc76) SHA1(b981ce644dde479c22d2ba270d472fe3b5d7f3e9), ROM_BIOS(0) )
+
+ ROM_SYSTEM_BIOS( 1, "cms871109", "CMS SCSI BIOS dated 1987-11-09" )
+ ROMX_LOAD( "cms 1987-11-09 scsi.bin", 0x000000, 0x002000, CRC(89d1d917) SHA1(f6028f6f2b16250950297e2ff5317ce463006796), ROM_BIOS(1) )
+ROM_END
+
+/***************************************************************************
+ FUNCTION PROTOTYPES
+***************************************************************************/
+
+//-------------------------------------------------
+// device_add_mconfig - add device configuration
+//-------------------------------------------------
+
+void a2bus_cmsscsi_device::device_add_mconfig(machine_config &config)
+{
+ NSCSI_BUS(config, m_scsibus);
+ NSCSI_CONNECTOR(config, "scsibus:0", default_scsi_devices, nullptr, false);
+ NSCSI_CONNECTOR(config, "scsibus:1", default_scsi_devices, nullptr, false);
+ 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);
+ NSCSI_CONNECTOR(config, "scsibus:5", default_scsi_devices, nullptr, false);
+ NSCSI_CONNECTOR(config, "scsibus:6", default_scsi_devices, "harddisk", false);
+ NSCSI_CONNECTOR(config, "scsibus:7").option_set("ncr5380", NCR5380);
+}
+
+//-------------------------------------------------
+// rom_region - device-specific ROM region
+//-------------------------------------------------
+
+const tiny_rom_entry *a2bus_cmsscsi_device::device_rom_region() const
+{
+ return ROM_NAME( scsi );
+}
+
+//**************************************************************************
+// LIVE DEVICE
+//**************************************************************************
+
+a2bus_cmsscsi_device::a2bus_cmsscsi_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_ncr5380(*this, SCSI_5380_TAG),
+ m_scsibus(*this, SCSI_BUS_TAG), m_rom(*this, SCSI_ROM_REGION), m_rombank(0)
+{
+}
+
+a2bus_cmsscsi_device::a2bus_cmsscsi_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) :
+ a2bus_cmsscsi_device(mconfig, A2BUS_CMSSCSI, tag, owner, clock)
+{
+}
+
+//-------------------------------------------------
+// device_start - device-specific startup
+//-------------------------------------------------
+
+void a2bus_cmsscsi_device::device_start()
+{
+ memset(m_ram, 0, 2048);
+
+ save_item(NAME(m_ram));
+ save_item(NAME(m_rombank));
+}
+
+void a2bus_cmsscsi_device::device_reset()
+{
+ m_rombank = 0;
+}
+
+
+/*-------------------------------------------------
+ read_c0nx - called for reads from this card's c0nx space
+-------------------------------------------------*/
+
+uint8_t a2bus_cmsscsi_device::read_c0nx(uint8_t offset)
+{
+ switch (offset)
+ {
+ case 0:
+ case 1:
+ case 2:
+ case 3:
+ case 4:
+ case 5:
+ case 6:
+ case 7:
+// logerror("Read 5380 @ %x\n", offset);
+ return m_ncr5380->read(offset);
+
+ case 8: // appears to be delay time
+ return 1;
+
+ case 0xa: // read and DACK
+ return m_ncr5380->dma_r();
+
+ case 0xb: //
+ return 0x1;
+
+ case 0xc: //
+ return 0x1;
+
+ case 0xd: //
+ return 0x1;
+
+ case 0xe: //
+ return 0x1;
+
+ case 0xf: // must be 0 to boot
+ return 0;
+
+ default:
+ logerror("Read c0n%x (%s)\n", offset, machine().describe_context().c_str());
+ break;
+ }
+
+ return 0xff;
+}
+
+
+/*-------------------------------------------------
+ write_c0nx - called for writes to this card's c0nx space
+-------------------------------------------------*/
+
+void a2bus_cmsscsi_device::write_c0nx(uint8_t offset, uint8_t data)
+{
+ switch (offset)
+ {
+ case 0:
+ case 1:
+ case 2:
+ case 3:
+ case 4:
+ case 5:
+ case 6:
+ case 7:
+// logerror("%02x to 5380 reg %x\n", data, offset);
+ m_ncr5380->write(offset, data);
+ break;
+
+ case 9:
+ m_rombank = (data & 3) * 0x800;
+ //printf("ROM bank to %x\n", m_rombank);
+ break;
+
+ case 0xa: // write and DACK
+ m_ncr5380->dma_w(data);
+ break;
+
+ default:
+ logerror("Write %02x to c0n%x (%s)\n", data, offset, machine().describe_context().c_str());
+ break;
+ }
+}
+
+/*-------------------------------------------------
+ read_cnxx - called for reads from this card's cnxx space
+-------------------------------------------------*/
+
+uint8_t a2bus_cmsscsi_device::read_cnxx(uint8_t offset)
+{
+ // slot images at $1800 + (slot * 100)
+ return m_rom[offset + (slotno() * 0x100) + 0x1800];
+}
+
+void a2bus_cmsscsi_device::write_cnxx(uint8_t offset, uint8_t data)
+{
+ // there are writes to cn0A, possibly misguided C0nA (bank select?) writes?
+// logerror("Write %02x to cn%02x (%s)\n", data, offset, machine().describe_context());
+}
+
+/*-------------------------------------------------
+ read_c800 - called for reads from this card's c800 space
+-------------------------------------------------*/
+
+uint8_t a2bus_cmsscsi_device::read_c800(uint16_t offset)
+{
+ if (offset < 0x80)
+ {
+ return m_ram[offset];
+ }
+
+ return m_rom[offset + m_rombank];
+}
+
+/*-------------------------------------------------
+ write_c800 - called for writes to this card's c800 space
+-------------------------------------------------*/
+void a2bus_cmsscsi_device::write_c800(uint16_t offset, uint8_t data)
+{
+ if (offset < 0x80)
+ {
+ m_ram[offset] = data;
+ }
+}
diff --git a/src/devices/bus/a2bus/cmsscsi.h b/src/devices/bus/a2bus/cmsscsi.h
new file mode 100644
index 00000000000..1dfa3a9834a
--- /dev/null
+++ b/src/devices/bus/a2bus/cmsscsi.h
@@ -0,0 +1,61 @@
+// license:BSD-3-Clause
+// copyright-holders:R. Belmont
+/*********************************************************************
+
+ cmsscsi.h
+
+ Implementation of the CMS SCSI II Card
+
+*********************************************************************/
+
+#ifndef MAME_BUS_A2BUS_CMSSCSI_H
+#define MAME_BUS_A2BUS_CMSSCSI_H
+
+#pragma once
+
+#include "a2bus.h"
+#include "machine/ncr5380.h"
+
+//**************************************************************************
+// TYPE DEFINITIONS
+//**************************************************************************
+
+class a2bus_cmsscsi_device:
+ public device_t,
+ public device_a2bus_card_interface
+{
+public:
+ // construction/destruction
+ a2bus_cmsscsi_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
+
+ 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);
+
+ 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;
+ virtual const tiny_rom_entry *device_rom_region() const override ATTR_COLD;
+
+ // 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;
+ virtual void write_cnxx(uint8_t offset, uint8_t data) override;
+ virtual uint8_t read_c800(uint16_t offset) override;
+ virtual void write_c800(uint16_t offset, uint8_t data) override;
+
+ required_device<ncr5380_device> m_ncr5380;
+ required_device<nscsi_bus_device> m_scsibus;
+ required_region_ptr<u8> m_rom;
+
+private:
+ uint8_t m_ram[2048]; // 2K SRAM chip on the card, only 128 bytes are used?
+ int m_rombank;
+};
+
+// device type definition
+DECLARE_DEVICE_TYPE(A2BUS_CMSSCSI, a2bus_cmsscsi_device)
+
+#endif // MAME_BUS_A2BUS_CMSSCSI_H
diff --git a/src/devices/bus/a2bus/computereyes2.cpp b/src/devices/bus/a2bus/computereyes2.cpp
index b8a80819023..89f6236cd4c 100644
--- a/src/devices/bus/a2bus/computereyes2.cpp
+++ b/src/devices/bus/a2bus/computereyes2.cpp
@@ -11,15 +11,43 @@
#include "emu.h"
#include "computereyes2.h"
-/***************************************************************************
- PARAMETERS
-***************************************************************************/
+#include "imagedev/picture.h"
+
+#include "bitmap.h"
+
+
+namespace {
//**************************************************************************
-// GLOBAL VARIABLES
+// TYPE DEFINITIONS
//**************************************************************************
-DEFINE_DEVICE_TYPE(A2BUS_COMPUTEREYES2, a2bus_computereyes2_device, "a2ceyes2", "Digital Vision ComputerEyes/2")
+class a2bus_computereyes2_device:
+ public device_t,
+ public device_a2bus_card_interface
+{
+public:
+ // construction/destruction
+ a2bus_computereyes2_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
+
+protected:
+ a2bus_computereyes2_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock);
+
+ 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;
+
+ // 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;
+
+private:
+ required_device<picture_image_device> m_picture;
+ int m_x, m_y, m_cer0, m_cer1, m_cer2;
+ u8 m_a2_bitmap[280*193];
+ u8 m_threshold;
+ bool m_bActive;
+};
/***************************************************************************
FUNCTION PROTOTYPES
@@ -196,22 +224,22 @@ void a2bus_computereyes2_device::write_c0nx(uint8_t offset, uint8_t data)
m_x = m_y = 0;
std::fill_n(m_a2_bitmap, 280*193, 0);
- m_bitmap = &m_picture->get_bitmap();
- if (m_bitmap)
+ const bitmap_argb32 &bitmap = m_picture->get_bitmap();
+ if (bitmap.valid())
{
// convert arbitrary sized ARGB32 image to a 188x193 image with 256 levels of grayscale
- double stepx = (double)m_bitmap->width() / 188.0;
- double stepy = (double)m_bitmap->height() / 193.0;
+ double stepx = (double)bitmap.width() / 188.0;
+ double stepy = (double)bitmap.height() / 193.0;
for (int y = 0; y < 193; y++)
{
for (int x = 0; x < 280; x++)
{
- u32 pixel = m_bitmap->pix((int)((double)y * stepy), (int)((double)x * stepx));
- double mono = ((0.2126 * (double)(((pixel>>16) & 0xff) / 255.0)) +
- (0.7152 * (double)(((pixel>>8) & 0xff) / 255.0)) +
- (0.0722 * (double)((pixel& 0xff) / 255.0)));
- m_a2_bitmap[(y*280)+x] = (u8)(mono * 255.0);
+ u32 pixel = bitmap.pix(int((double)y * stepy), int((double)x * stepx));
+ double mono = ((0.2126 * double(((pixel>>16) & 0xff) / 255.0)) +
+ (0.7152 * double(((pixel>>8) & 0xff) / 255.0)) +
+ (0.0722 * double((pixel& 0xff) / 255.0)));
+ m_a2_bitmap[(y*280)+x] = u8(mono * 255.0);
}
}
}
@@ -230,3 +258,12 @@ void a2bus_computereyes2_device::write_c0nx(uint8_t offset, uint8_t data)
break;
}
}
+
+} // anonymous namespace
+
+
+//**************************************************************************
+// GLOBAL VARIABLES
+//**************************************************************************
+
+DEFINE_DEVICE_TYPE_PRIVATE(A2BUS_COMPUTEREYES2, device_a2bus_card_interface, a2bus_computereyes2_device, "a2ceyes2", "Digital Vision ComputerEyes/2")
diff --git a/src/devices/bus/a2bus/computereyes2.h b/src/devices/bus/a2bus/computereyes2.h
index 31856f08813..aeaeab92384 100644
--- a/src/devices/bus/a2bus/computereyes2.h
+++ b/src/devices/bus/a2bus/computereyes2.h
@@ -8,48 +8,14 @@
*********************************************************************/
-#ifndef MAME_BUS_A2BUS_COMPEYES2_H
-#define MAME_BUS_A2BUS_COMPEYES2_H
+#ifndef MAME_BUS_A2BUS_COMPUTEREYES2_H
+#define MAME_BUS_A2BUS_COMPUTEREYES2_H
#pragma once
#include "a2bus.h"
-#include "bitmap.h"
-#include "imagedev/picture.h"
-
-//**************************************************************************
-// TYPE DEFINITIONS
-//**************************************************************************
-
-class a2bus_computereyes2_device:
- public device_t,
- public device_a2bus_card_interface
-{
-public:
- // construction/destruction
- a2bus_computereyes2_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
-
-protected:
- a2bus_computereyes2_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
- virtual uint8_t read_c0nx(uint8_t offset) override;
- virtual void write_c0nx(uint8_t offset, uint8_t data) override;
-
-private:
- required_device<picture_image_device> m_picture;
- int m_x, m_y, m_cer0, m_cer1, m_cer2;
- u8 m_a2_bitmap[280*193];
- u8 m_threshold;
- bool m_bActive;
- bitmap_argb32 *m_bitmap;
-};
-
-// device type definition
-DECLARE_DEVICE_TYPE(A2BUS_COMPUTEREYES2, a2bus_computereyes2_device)
-
-#endif // MAME_BUS_A2BUS_COMPEYES2_H
+
+// device type declaration
+DECLARE_DEVICE_TYPE(A2BUS_COMPUTEREYES2, device_a2bus_card_interface)
+
+#endif // MAME_BUS_A2BUS_COMPUTEREYES2_H
diff --git a/src/devices/bus/a2bus/corvfdc01.cpp b/src/devices/bus/a2bus/corvfdc01.cpp
index 2f1684c1da7..4511aa29a88 100644
--- a/src/devices/bus/a2bus/corvfdc01.cpp
+++ b/src/devices/bus/a2bus/corvfdc01.cpp
@@ -27,10 +27,6 @@ DEFINE_DEVICE_TYPE(A2BUS_CORVFDC01, a2bus_corvfdc01_device, "crvfdc01", "Corvus
#define FDC01_ROM_REGION "fdc01_rom"
#define FDC01_FDC_TAG "fdc01_fdc"
-FLOPPY_FORMATS_MEMBER( a2bus_corvfdc01_device::corv_floppy_formats )
- FLOPPY_IMD_FORMAT
-FLOPPY_FORMATS_END
-
static void corv_floppies(device_slot_interface &device)
{
device.option_add("8sssd", FLOPPY_8_SSSD);
@@ -88,10 +84,10 @@ void a2bus_corvfdc01_device::device_add_mconfig(machine_config &config)
FD1793(config, m_wdfdc, 16_MHz_XTAL / 8);
m_wdfdc->intrq_wr_callback().set(FUNC(a2bus_corvfdc01_device::intrq_w));
m_wdfdc->drq_wr_callback().set(FUNC(a2bus_corvfdc01_device::drq_w));
- FLOPPY_CONNECTOR(config, m_con1, corv_floppies, "8sssd", a2bus_corvfdc01_device::corv_floppy_formats);
- FLOPPY_CONNECTOR(config, m_con2, corv_floppies, "8sssd", a2bus_corvfdc01_device::corv_floppy_formats);
- FLOPPY_CONNECTOR(config, m_con3, corv_floppies, "8sssd", a2bus_corvfdc01_device::corv_floppy_formats);
- FLOPPY_CONNECTOR(config, m_con4, corv_floppies, "8sssd", a2bus_corvfdc01_device::corv_floppy_formats);
+ FLOPPY_CONNECTOR(config, m_con1, corv_floppies, "8sssd", floppy_image_device::default_fm_floppy_formats);
+ FLOPPY_CONNECTOR(config, m_con2, corv_floppies, "8sssd", floppy_image_device::default_fm_floppy_formats);
+ FLOPPY_CONNECTOR(config, m_con3, corv_floppies, "8sssd", floppy_image_device::default_fm_floppy_formats);
+ FLOPPY_CONNECTOR(config, m_con4, corv_floppies, "8sssd", floppy_image_device::default_fm_floppy_formats);
}
//-------------------------------------------------
@@ -253,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;
@@ -261,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 b08574ad19f..6db9b15d641 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"
//**************************************************************************
@@ -33,10 +32,10 @@ public:
protected:
a2bus_corvfdc01_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 device_start() override ATTR_COLD;
+ virtual void device_reset() override ATTR_COLD;
+ virtual void device_add_mconfig(machine_config &config) override ATTR_COLD;
+ virtual const tiny_rom_entry *device_rom_region() const override ATTR_COLD;
// overrides of standard a2bus slot functions
virtual uint8_t read_c0nx(uint8_t offset) override;
@@ -50,10 +49,8 @@ protected:
required_device<floppy_connector> m_con4;
private:
- DECLARE_WRITE_LINE_MEMBER(intrq_w);
- DECLARE_WRITE_LINE_MEMBER(drq_w);
-
- DECLARE_FLOPPY_FORMATS(corv_floppy_formats);
+ 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 e1c30bae9d0..3a1b4c433b5 100644
--- a/src/devices/bus/a2bus/corvfdc02.cpp
+++ b/src/devices/bus/a2bus/corvfdc02.cpp
@@ -29,10 +29,11 @@ DEFINE_DEVICE_TYPE(A2BUS_CORVFDC02, a2bus_corvfdc02_device, "crvfdc02", "Corvus
#define FDC02_ROM_REGION "fdc02_rom"
#define FDC02_FDC_TAG "fdc02_fdc"
-FLOPPY_FORMATS_MEMBER( a2bus_corvfdc02_device::corv_floppy_formats )
- FLOPPY_CONCEPT_525DSDD_FORMAT,
- FLOPPY_IMD_FORMAT
-FLOPPY_FORMATS_END
+void a2bus_corvfdc02_device::corv_floppy_formats(format_registration &fr)
+{
+ fr.add_mfm_containers();
+ fr.add(FLOPPY_CONCEPT_525DSDD_FORMAT);
+}
static void corv_floppies(device_slot_interface &device)
{
@@ -100,7 +101,7 @@ void a2bus_corvfdc02_device::device_start()
{
m_rom = device().machine().root_device().memregion(this->subtag(FDC02_ROM_REGION).c_str())->base();
- m_timer = timer_alloc(0);
+ m_timer = timer_alloc(FUNC(a2bus_corvfdc02_device::tc_tick), this);
save_item(NAME(m_fdc_local_status));
save_item(NAME(m_fdc_local_command));
@@ -117,7 +118,7 @@ void a2bus_corvfdc02_device::device_reset()
m_timer->adjust(attotime::never);
}
-void a2bus_corvfdc02_device::device_timer(emu_timer &timer, device_timer_id id, int param, void *ptr)
+TIMER_CALLBACK_MEMBER(a2bus_corvfdc02_device::tc_tick)
{
m_fdc->tc_w(true);
m_fdc->tc_w(false);
@@ -242,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)
{
@@ -259,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 1a54fe9caba..24c91bfaf6c 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
@@ -33,17 +32,18 @@ public:
protected:
a2bus_corvfdc02_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_timer(emu_timer &timer, device_timer_id id, int param, void *ptr) override;
- virtual void device_add_mconfig(machine_config &config) override;
- virtual const tiny_rom_entry *device_rom_region() const override;
+ 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;
+ virtual const tiny_rom_entry *device_rom_region() const override ATTR_COLD;
// 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;
+ TIMER_CALLBACK_MEMBER(tc_tick);
+
required_device<upd765a_device> m_fdc;
required_device<floppy_connector> m_con1;
required_device<floppy_connector> m_con2;
@@ -51,10 +51,10 @@ 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);
- DECLARE_FLOPPY_FORMATS(corv_floppy_formats);
+ static void corv_floppy_formats(format_registration &fr);
uint8_t *m_rom;
uint8_t m_fdc_local_status, m_fdc_local_command;
diff --git a/src/devices/bus/a2bus/excel9.cpp b/src/devices/bus/a2bus/excel9.cpp
new file mode 100644
index 00000000000..706cb3c4f63
--- /dev/null
+++ b/src/devices/bus/a2bus/excel9.cpp
@@ -0,0 +1,305 @@
+// license:BSD-3-Clause
+// copyright-holders:R. Belmont, Rob Justice
+/*********************************************************************
+
+ excel9.cpp
+ Implementation of the Seikou Excel-9 6809 card
+
+ Address mapping as follows:
+ 6809 0x0000-0x0fff -> 6502 0x9000-0x9fff
+ 6809 0x1000-0x8fff -> 6502 0x1000-0x8fff
+ 6809 0x9000-0x9fff -> 6502 0x0000-0x0fff
+ 6809 0xa000-0xbfff -> 6502 0xc000-0xdfff
+ 6809 0xc000-0xdfff -> 6502 0xa000-0xbfff
+ 6809 0xe000-0xffff -> 6502 0xe000-0xffff
+
+ Eproms/Proms and Schematic available here:
+ http://mirrors.apple2.org.za/Apple%20II%20Documentation%20Project/Interface%20Cards/CPU/Seikou%20Excel-9/
+
+ Todo:
+ Add timer support, board has a CD4536B timer onboard that can generate interrupts
+
+*********************************************************************/
+
+#include "emu.h"
+#include "excel9.h"
+#include "cpu/m6809/m6809.h"
+
+//**************************************************************************
+// GLOBAL VARIABLES
+//**************************************************************************
+
+DEFINE_DEVICE_TYPE(A2BUS_EXCEL9, a2bus_excel9_device, "a2excel9", "Seikou Excel-9")
+
+void a2bus_excel9_device::m6809_mem(address_map &map)
+{
+ map(0x0000, 0xffff).rw(FUNC(a2bus_excel9_device::dma_r), FUNC(a2bus_excel9_device::dma_w));
+}
+
+ROM_START( excel9 )
+ ROM_REGION(0x2000, "m6809_rom", 0)
+ ROM_LOAD( "e000.bin", 0x000000, 0x001000, CRC(f12f400d) SHA1(fde86ba8d1b9ffe08b13774a73b17a5f44990d7a) )
+ ROM_LOAD( "f000.bin", 0x001000, 0x001000, CRC(52484440) SHA1(d2960851ce8f70df12d23021dfbe031ec5a8988f) )
+ROM_END
+
+/***************************************************************************
+ FUNCTION PROTOTYPES
+***************************************************************************/
+
+//-------------------------------------------------
+// device_add_mconfig - add device configuration
+//-------------------------------------------------
+
+void a2bus_excel9_device::device_add_mconfig(machine_config &config)
+{
+ MC6809E(config, m_6809, 1021800); // 6809E runs at ~1 MHz
+ m_6809->set_addrmap(AS_PROGRAM, &a2bus_excel9_device::m6809_mem);
+}
+
+//-------------------------------------------------
+// device_rom_region - device-specific ROMs
+//-------------------------------------------------
+
+const tiny_rom_entry *a2bus_excel9_device::device_rom_region() const
+{
+ return ROM_NAME( excel9 );
+}
+
+//**************************************************************************
+// LIVE DEVICE
+//**************************************************************************
+
+a2bus_excel9_device::a2bus_excel9_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_6809(*this, "m6809")
+ , m_rom(*this, "m6809_rom")
+ , m_bEnabled(false)
+ , m_romenable(false)
+ , m_enable_flipflop(false)
+ , m_interrupttype_firq(false)
+ , m_powerup(false)
+ , m_status(0)
+{
+}
+
+a2bus_excel9_device::a2bus_excel9_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) :
+ a2bus_excel9_device(mconfig, A2BUS_EXCEL9, tag, owner, clock)
+{
+}
+
+//-------------------------------------------------
+// device_start - device-specific startup
+//-------------------------------------------------
+
+void a2bus_excel9_device::device_start()
+{
+ save_item(NAME(m_bEnabled));
+ save_item(NAME(m_romenable));
+ save_item(NAME(m_enable_flipflop));
+ save_item(NAME(m_status));
+ save_item(NAME(m_interrupttype_firq));
+ save_item(NAME(m_powerup));
+}
+
+void a2bus_excel9_device::device_reset()
+{
+ m_bEnabled = true;
+ m_romenable = true;
+ m_enable_flipflop = false;
+ m_status = 0;
+ m_interrupttype_firq = false;
+ m_powerup = true;
+ raise_slot_dma();
+ m_6809->reset();
+}
+
+uint8_t a2bus_excel9_device::read_c0nx(uint8_t offset)
+{
+ // Bit7 timer output, 1 = timer fired
+ // Bit6
+ // Bit5
+ // Bit4 BA
+ // Bit3 BS
+ // Bit2 rom enable 0=enable 1=disable
+ // Bit1 expansion connector pin34
+ // Bit0 interrupttype 0=6502 IRQ & 6809 IRQ, 1=6809 FIRQ
+
+ //Todo: add timer output, ba and bs
+ return m_status;
+}
+
+void a2bus_excel9_device::write_c0nx(uint8_t offset, uint8_t data)
+{
+ switch (offset)
+ {
+ case 0:
+ m_enable_flipflop = false;
+ break;
+
+ case 1:
+ m_enable_flipflop = true;
+ break;
+
+ case 2: // enable 6809
+ case 3:
+ raise_slot_dma();
+ m_6809->set_input_line(INPUT_LINE_HALT, CLEAR_LINE);
+ m_bEnabled = true;
+ break;
+
+ case 4: // disable 6809
+ case 5:
+ m_6809->set_input_line(INPUT_LINE_HALT, ASSERT_LINE);
+ lower_slot_dma();
+ m_bEnabled = false;
+ break;
+
+ case 6: // Set enable_flipflop state and trigger NMI
+ case 7:
+ if (m_enable_flipflop)
+ {
+ raise_slot_dma();
+ m_6809->set_input_line(INPUT_LINE_HALT, CLEAR_LINE);
+ m_6809->pulse_input_line(INPUT_LINE_NMI, attotime::zero);
+ m_bEnabled = true;
+ }
+ else
+ {
+ m_6809->set_input_line(INPUT_LINE_HALT, ASSERT_LINE);
+ lower_slot_dma();
+ if (m_powerup) // hack for initial 6502 RESET taking priority over the NMI
+ {
+ m_powerup = false;
+ }
+ else
+ {
+ raise_slot_nmi();
+ lower_slot_nmi();
+ }
+ m_bEnabled = false;
+ }
+ break;
+
+ case 8: // Timer control for CD4536B
+ case 9:
+ //to be added
+ break;
+
+ case 0xa: // status reg
+ case 0xb:
+ if (data & 0x04)
+ {
+ m_romenable=false;
+ m_status |= 0x04;
+ }
+ else
+ {
+ m_romenable=true;
+ m_status &= ~0x04;
+ }
+
+ if (data & 0x02) // this is an output to the expansion connector
+ {
+ m_status |= 0x02;
+ }
+ else
+ {
+ m_status &= ~0x02;
+ }
+
+ if (data & 0x01) // select interrupt type generated from timer
+ {
+ m_interrupttype_firq=true;
+ m_status |= 0x01;
+ }
+ else
+ {
+ m_interrupttype_firq=false;
+ m_status &= ~0x01;
+ }
+ break;
+
+ default:
+ logerror("Excel-9: %02x to unhandled c0n%x\n", data, offset);
+ break;
+ }
+}
+
+uint8_t a2bus_excel9_device::dma_r(offs_t offset)
+{
+ if (m_bEnabled)
+ {
+ if (offset <= 0x0fff)
+ {
+ return slot_dma_read(offset+0x9000);
+ }
+ else if (offset <= 0x8fff)
+ {
+ return slot_dma_read(offset);
+ }
+ else if (offset <= 0x9fff)
+ {
+ return slot_dma_read(offset&0xfff);
+ }
+ else if (offset <= 0xbfff)
+ {
+ return slot_dma_read(offset+0x2000);
+ }
+ else if (offset <= 0xdfff)
+ {
+ return slot_dma_read(offset-0x2000);
+ }
+ else
+ {
+ if (m_romenable)
+ {
+ return m_rom[offset & 0x1fff];
+ }
+ else
+ {
+ return slot_dma_read(offset);
+ }
+ }
+ }
+ return 0xff;
+}
+
+
+//-------------------------------------------------
+// dma_w -
+//-------------------------------------------------
+
+void a2bus_excel9_device::dma_w(offs_t offset, uint8_t data)
+{
+ if (m_bEnabled)
+ {
+ if (offset <= 0x0fff)
+ {
+ slot_dma_write(offset+0x9000, data);
+ }
+ else if (offset <= 0x8fff)
+ {
+ slot_dma_write(offset, data);
+ }
+ else if (offset <= 0x9fff)
+ {
+ slot_dma_write(offset&0xfff, data);
+ }
+ else if (offset <= 0xbfff)
+ {
+ slot_dma_write(offset+0x2000, data);
+ }
+ else if (offset <= 0xdfff)
+ {
+ slot_dma_write(offset-0x2000, data);
+ }
+ else
+ {
+ if (!m_romenable)
+ {
+ slot_dma_write(offset, data);
+ }
+ }
+ }
+}
diff --git a/src/devices/bus/a2bus/excel9.h b/src/devices/bus/a2bus/excel9.h
new file mode 100644
index 00000000000..4d8ceba9c09
--- /dev/null
+++ b/src/devices/bus/a2bus/excel9.h
@@ -0,0 +1,62 @@
+// license:BSD-3-Clause
+// copyright-holders:R. Belmont, Rob Justice
+/*********************************************************************
+
+ excel9.h
+
+ Implementation of the Seikou Excel-9 6809 card
+
+*********************************************************************/
+
+#ifndef MAME_BUS_A2BUS_EXCEL9_H
+#define MAME_BUS_A2BUS_EXCEL9_H
+
+#pragma once
+
+#include "a2bus.h"
+
+//**************************************************************************
+// TYPE DEFINITIONS
+//**************************************************************************
+
+class a2bus_excel9_device:
+ public device_t,
+ public device_a2bus_card_interface
+{
+public:
+ // construction/destruction
+ a2bus_excel9_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
+
+protected:
+ a2bus_excel9_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock);
+
+ 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;
+ virtual const tiny_rom_entry *device_rom_region() const override ATTR_COLD;
+
+ // 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;
+
+private:
+ required_device<cpu_device> m_6809;
+ required_region_ptr<u8> m_rom;
+
+ bool m_bEnabled;
+ bool m_romenable;
+ bool m_enable_flipflop;
+ bool m_interrupttype_firq;
+ bool m_powerup;
+ uint8_t m_status;
+
+ uint8_t dma_r(offs_t offset);
+ void dma_w(offs_t offset, uint8_t data);
+
+ void m6809_mem(address_map &map) ATTR_COLD;
+};
+
+// device type definition
+DECLARE_DEVICE_TYPE(A2BUS_EXCEL9, a2bus_excel9_device)
+
+#endif // MAME_BUS_A2BUS_EXCEL9_H
diff --git a/src/devices/bus/a2bus/ezcgi.cpp b/src/devices/bus/a2bus/ezcgi.cpp
index a9bc648f08e..51c48f61d20 100644
--- a/src/devices/bus/a2bus/ezcgi.cpp
+++ b/src/devices/bus/a2bus/ezcgi.cpp
@@ -13,6 +13,11 @@
#include "emu.h"
#include "ezcgi.h"
+#include "video/tms9928a.h"
+#include "video/v9938.h"
+
+
+namespace {
/***************************************************************************
PARAMETERS
@@ -22,12 +27,83 @@
#define SCREEN_TAG "screen"
//**************************************************************************
-// GLOBAL VARIABLES
+// TYPE DEFINITIONS
//**************************************************************************
-DEFINE_DEVICE_TYPE(A2BUS_EZCGI, a2bus_ezcgi_device, "a2ezcgi", "E-Z Color Graphics Interface")
-DEFINE_DEVICE_TYPE(A2BUS_EZCGI_9938, a2bus_ezcgi_9938_device, "a2ezcgi3", "E-Z Color Graphics Interface (TMS9938)")
-DEFINE_DEVICE_TYPE(A2BUS_EZCGI_9958, a2bus_ezcgi_9958_device, "a2ezcgi5", "E-Z Color Graphics Interface (TMS9958)")
+class a2bus_ezcgi_device:
+ public device_t,
+ public device_a2bus_card_interface
+{
+public:
+ // construction/destruction
+ a2bus_ezcgi_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
+
+protected:
+ a2bus_ezcgi_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock);
+
+ 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;
+
+ // 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;
+
+ required_device<tms9918a_device> m_tms;
+
+private:
+ void tms_irq_w(int state);
+};
+
+class a2bus_ezcgi_9938_device:
+ public device_t,
+ public device_a2bus_card_interface
+{
+public:
+ // construction/destruction
+ a2bus_ezcgi_9938_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
+
+protected:
+ a2bus_ezcgi_9938_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock);
+
+ 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;
+
+ // 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;
+
+ required_device<v9938_device> m_tms;
+
+private:
+ void tms_irq_w(int state);
+};
+
+class a2bus_ezcgi_9958_device:
+ public device_t,
+ public device_a2bus_card_interface
+{
+public:
+ // construction/destruction
+ a2bus_ezcgi_9958_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
+
+protected:
+ a2bus_ezcgi_9958_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock);
+
+ 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;
+
+ // 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;
+
+ required_device<v9958_device> m_tms;
+
+private:
+ void tms_irq_w(int state);
+};
#define MSX2_XBORDER_PIXELS 16
#define MSX2_YBORDER_PIXELS 28
@@ -252,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)
{
@@ -264,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)
{
@@ -276,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)
{
@@ -287,3 +363,14 @@ WRITE_LINE_MEMBER( a2bus_ezcgi_9958_device::tms_irq_w )
lower_slot_irq();
}
}
+
+} // anonymous namespace
+
+
+//**************************************************************************
+// GLOBAL VARIABLES
+//**************************************************************************
+
+DEFINE_DEVICE_TYPE_PRIVATE(A2BUS_EZCGI, device_a2bus_card_interface, a2bus_ezcgi_device, "a2ezcgi", "E-Z Color Graphics Interface")
+DEFINE_DEVICE_TYPE_PRIVATE(A2BUS_EZCGI_9938, device_a2bus_card_interface, a2bus_ezcgi_9938_device, "a2ezcgi3", "E-Z Color Graphics Interface (TMS9938)")
+DEFINE_DEVICE_TYPE_PRIVATE(A2BUS_EZCGI_9958, device_a2bus_card_interface, a2bus_ezcgi_9958_device, "a2ezcgi5", "E-Z Color Graphics Interface (TMS9958)")
diff --git a/src/devices/bus/a2bus/ezcgi.h b/src/devices/bus/a2bus/ezcgi.h
index b301bee332c..18b8e709ca9 100644
--- a/src/devices/bus/a2bus/ezcgi.h
+++ b/src/devices/bus/a2bus/ezcgi.h
@@ -10,97 +10,16 @@
*********************************************************************/
-#ifndef MAME_BUS_A2BUS_A2EZCGI_H
-#define MAME_BUS_A2BUS_A2EZCGI_H
+#ifndef MAME_BUS_A2BUS_EZCGI_H
+#define MAME_BUS_A2BUS_EZCGI_H
#pragma once
#include "a2bus.h"
-#include "video/tms9928a.h"
-#include "video/v9938.h"
-
-//**************************************************************************
-// TYPE DEFINITIONS
-//**************************************************************************
-
-class a2bus_ezcgi_device:
- public device_t,
- public device_a2bus_card_interface
-{
-public:
- // construction/destruction
- a2bus_ezcgi_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
-
-protected:
- a2bus_ezcgi_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
- virtual uint8_t read_c0nx(uint8_t offset) override;
- virtual void write_c0nx(uint8_t offset, uint8_t data) override;
-
- required_device<tms9918a_device> m_tms;
-
-private:
- DECLARE_WRITE_LINE_MEMBER( tms_irq_w );
-};
-
-class a2bus_ezcgi_9938_device:
- public device_t,
- public device_a2bus_card_interface
-{
-public:
- // construction/destruction
- a2bus_ezcgi_9938_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
-
-protected:
- a2bus_ezcgi_9938_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
- virtual uint8_t read_c0nx(uint8_t offset) override;
- virtual void write_c0nx(uint8_t offset, uint8_t data) override;
-
- required_device<v9938_device> m_tms;
-
-private:
- DECLARE_WRITE_LINE_MEMBER( tms_irq_w );
-};
-
-class a2bus_ezcgi_9958_device:
- public device_t,
- public device_a2bus_card_interface
-{
-public:
- // construction/destruction
- a2bus_ezcgi_9958_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
-
-protected:
- a2bus_ezcgi_9958_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
- virtual uint8_t read_c0nx(uint8_t offset) override;
- virtual void write_c0nx(uint8_t offset, uint8_t data) override;
-
- required_device<v9958_device> m_tms;
-
-private:
- DECLARE_WRITE_LINE_MEMBER( tms_irq_w );
-};
// device type definition
-DECLARE_DEVICE_TYPE(A2BUS_EZCGI, a2bus_ezcgi_device)
-DECLARE_DEVICE_TYPE(A2BUS_EZCGI_9938, a2bus_ezcgi_9938_device)
-DECLARE_DEVICE_TYPE(A2BUS_EZCGI_9958, a2bus_ezcgi_9958_device)
+DECLARE_DEVICE_TYPE(A2BUS_EZCGI, device_a2bus_card_interface)
+DECLARE_DEVICE_TYPE(A2BUS_EZCGI_9938, device_a2bus_card_interface)
+DECLARE_DEVICE_TYPE(A2BUS_EZCGI_9958, device_a2bus_card_interface)
-#endif // MAME_BUS_A2BUS_A2EZCGI_H
+#endif // MAME_BUS_A2BUS_EZCGI_H
diff --git a/src/devices/bus/a2bus/grafex.cpp b/src/devices/bus/a2bus/grafex.cpp
new file mode 100644
index 00000000000..cdb61572f73
--- /dev/null
+++ b/src/devices/bus/a2bus/grafex.cpp
@@ -0,0 +1,143 @@
+// license:BSD-3-Clause
+// copyright-holders:R. Belmont, Rob Justice
+/*********************************************************************
+
+ grafex.cpp
+
+ Implementation of the Grafex-32 card
+
+ This was a graphics board using the upd7220 for the Apple II by Ray Dahlby (RDE - Ray Dahlby Electronics)
+ Instructions on how to build this were described in Radio Electronics magazine in 1986
+ Febuary, March & April editions.
+ http://mirrors.apple2.org.za/ftp.apple.asimov.net/documentation/hardware/video/Grafex-32_from_Radio_Electronics_1986.pdf
+
+ This version has 128k ram emulated. The original had 32k with provision to accept 128k
+
+ A0 selects between the 7220 gdc registers
+ A1 switches AppleII video or Grafex video (not implemented)
+
+ Manual:
+ https://mirrors.apple2.org.za/Apple%20II%20Documentation%20Project/Interface%20Cards/Video/RDE%20Grafex/Manuals/RDE%20Grafex%20-%20Manual.pdf
+
+ The software described in the manual does not look like its available anywhere.
+
+ TODO:
+ Support for multiple cards, each card supported 1 bit of color. The article describes using
+ three cards to get 8 color RGB output. Each plane is driven directly by its dedicated 7220.
+
+*********************************************************************/
+
+#include "emu.h"
+#include "grafex.h"
+
+#include "video/upd7220.h"
+
+#include "screen.h"
+
+
+namespace {
+
+//**************************************************************************
+// TYPE DEFINITIONS
+//**************************************************************************
+
+class a2bus_grafex_device : public device_t,
+ public device_a2bus_card_interface
+{
+public:
+ // construction/destruction
+ a2bus_grafex_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
+
+protected:
+ a2bus_grafex_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock);
+
+ virtual void device_start() override ATTR_COLD;
+ virtual void device_add_mconfig(machine_config &config) override ATTR_COLD;
+
+ // 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;
+
+private:
+ required_device<upd7220_device> m_gdc;
+ required_shared_ptr<uint16_t> m_video_ram;
+
+ UPD7220_DISPLAY_PIXELS_MEMBER(hgdc_display_pixels);
+
+ void upd7220_map(address_map &map) ATTR_COLD;
+
+ rgb_t m_bg, m_fg;
+};
+
+//-------------------------------------------------
+// device_add_mconfig - add device configuration
+//-------------------------------------------------
+
+void a2bus_grafex_device::device_add_mconfig(machine_config &config)
+{
+ screen_device &screen(SCREEN(config, "screen", SCREEN_TYPE_RASTER));
+ screen.set_screen_update("upd7220", FUNC(upd7220_device::screen_update));
+ screen.set_raw(16_MHz_XTAL, 1024, 384, 640, 262, 62, 200);
+
+ UPD7220(config, m_gdc, 2_MHz_XTAL);
+ m_gdc->set_addrmap(0, &a2bus_grafex_device::upd7220_map);
+ m_gdc->set_display_pixels(FUNC(a2bus_grafex_device::hgdc_display_pixels));
+ m_gdc->set_screen("screen");
+}
+
+//**************************************************************************
+// LIVE DEVICE
+//**************************************************************************
+
+a2bus_grafex_device::a2bus_grafex_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) :
+ a2bus_grafex_device(mconfig, A2BUS_GRAFEX, tag, owner, clock)
+{
+}
+
+a2bus_grafex_device::a2bus_grafex_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_gdc(*this, "upd7220"),
+ m_video_ram(*this, "video_ram")
+{
+}
+
+void a2bus_grafex_device::device_start()
+{
+ m_bg = rgb_t::black();
+ m_fg = rgb_t::white();
+}
+
+uint8_t a2bus_grafex_device::read_c0nx(uint8_t offset)
+{
+ return m_gdc->read(offset & 0x01);
+}
+
+void a2bus_grafex_device::write_c0nx(uint8_t offset, uint8_t data)
+{
+ m_gdc->write(offset & 0x01, data);
+}
+
+void a2bus_grafex_device::upd7220_map(address_map &map)
+{
+ map(0x00000, 0x1ffff).ram().share("video_ram");
+}
+
+UPD7220_DISPLAY_PIXELS_MEMBER(a2bus_grafex_device::hgdc_display_pixels )
+{
+ uint16_t gfx = m_video_ram[(address & 0x1ffff)];
+
+ for (int i=0; i<16; i++)
+ {
+ bitmap.pix(y, x + i) = BIT(gfx, i) ? m_fg : m_bg;
+ }
+}
+
+} // anonymous namespace
+
+
+//**************************************************************************
+// GLOBAL VARIABLES
+//**************************************************************************
+
+DEFINE_DEVICE_TYPE_PRIVATE(A2BUS_GRAFEX, device_a2bus_card_interface, a2bus_grafex_device, "a2grafex", "Grafex-32")
diff --git a/src/devices/bus/a2bus/grafex.h b/src/devices/bus/a2bus/grafex.h
new file mode 100644
index 00000000000..78dda772f80
--- /dev/null
+++ b/src/devices/bus/a2bus/grafex.h
@@ -0,0 +1,21 @@
+// license:BSD-3-Clause
+// copyright-holders:R. Belmont, Rob Justice
+/*********************************************************************
+
+ grafex.h
+
+ Implementation of the Grafex-32 card
+
+*********************************************************************/
+
+#ifndef MAME_BUS_A2BUS_GRAFEX_H
+#define MAME_BUS_A2BUS_GRAFEX_H
+
+#pragma once
+
+#include "a2bus.h"
+
+// device type definition
+DECLARE_DEVICE_TYPE(A2BUS_GRAFEX, device_a2bus_card_interface)
+
+#endif // MAME_BUS_A2BUS_GRAFEX_H
diff --git a/src/devices/bus/a2bus/grappler.cpp b/src/devices/bus/a2bus/grappler.cpp
new file mode 100644
index 00000000000..2e6186fe954
--- /dev/null
+++ b/src/devices/bus/a2bus/grappler.cpp
@@ -0,0 +1,1252 @@
+// license:BSD-3-Clause
+// copyright-holders:Vas Crabb
+#include "emu.h"
+#include "grappler.h"
+
+#include "bus/centronics/ctronics.h"
+#include "cpu/mcs48/mcs48.h"
+
+//#define VERBOSE 1
+//#define LOG_OUTPUT_FUNC osd_printf_info
+#include "logmacro.h"
+
+namespace {
+
+ROM_START(grappler)
+ ROM_REGION(0x0800, "rom", 0)
+ ROM_LOAD( "eps-1_c1981.u6", 0x0000, 0x0800, CRC(862773cb) SHA1(791ebae64a7fad8f42bdfaec36b9e2d34f12ded8) )
+ROM_END
+
+
+ROM_START(grapplerplus)
+ // TODO: add other revisions - 3.3 is known to exist
+
+ ROM_DEFAULT_BIOS("v32")
+ ROM_SYSTEM_BIOS(0, "v30", "ROM 3.0")
+ ROM_SYSTEM_BIOS(1, "v32", "ROM 3.2")
+
+ ROM_REGION(0x1000, "rom", 0)
+ ROMX_LOAD( "3.0.u9", 0x0000, 0x1000, CRC(17cf5e02) SHA1(9b01a9b1cf7752987e03f9b0285eb9329d63b777), ROM_BIOS(0) )
+ ROMX_LOAD( "3.2.u9", 0x0000, 0x1000, CRC(6f88b70c) SHA1(433ae61a0553ee9c1628ea5b6376dac848c04cad), ROM_BIOS(1) )
+ROM_END
+
+
+ROM_START(bufgrapplerplus)
+ // TODO: confirm contents
+ // despite having the same version string, this differs from the Grapper+ 3.2.u9 ROM
+
+ // 9433B-0141
+ // 90ROM00002
+ // GI8603CEY
+ // TAIWAN
+ ROM_REGION(0x1000, "rom", 0)
+ ROM_LOAD( "90rom00002.u18", 0x0000, 0x1000, CRC(cd07c7ef) SHA1(6c2f1375b5df6bb65dfca1444c064661242fef1a) )
+
+ // S 8450
+ // SCN8048A
+ // C6N40 B
+ // 95ROM08048
+ ROM_REGION(0x0400, "mcu", 0)
+ ROM_LOAD( "95rom08048.u10", 0x0000, 0x0400, CRC(55990f67) SHA1(f0907cf02d8c5dbf1bfacb0d626f2231142f0ff7) )
+ROM_END
+
+
+
+//==============================================================
+// Grappler base
+//==============================================================
+
+class a2bus_grappler_device_base : public device_t, public device_a2bus_card_interface
+{
+public:
+ // device_a2bus_card_interface implementation
+ virtual u8 read_c800(u16 offset) override;
+
+protected:
+ a2bus_grappler_device_base(machine_config const &mconfig, device_type type, char const *tag, device_t *owner, u32 clock);
+
+ // signal state
+ u8 busy_in() const { return m_busy_in; }
+ u8 pe_in() const { return m_pe_in; }
+ u8 slct_in() const { return m_slct_in; }
+
+ required_device<centronics_device> m_printer_conn;
+ required_device<output_latch_device> m_printer_out;
+ required_region_ptr<u8> m_rom;
+
+protected:
+ // device_t implementation
+ virtual void device_add_mconfig(machine_config &config) override ATTR_COLD;
+ virtual void device_start() override ATTR_COLD;
+
+ // helpers
+ void set_rom_bank(u16 rom_bank);
+
+private:
+ // printer status inputs
+ 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);
+ void set_pe_in(s32 param);
+ void set_slct_in(s32 param);
+
+ u16 m_rom_bank; // U2D (pin 13)
+ u8 m_busy_in; // printer connector pin 21 (synchronised)
+ u8 m_pe_in; // printer connector pin 23 (synchronised)
+ u8 m_slct_in; // printer connector pin 25 (synchronised)
+};
+
+
+a2bus_grappler_device_base::a2bus_grappler_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_a2bus_card_interface(mconfig, *this),
+ m_printer_conn(*this, "prn"),
+ m_printer_out(*this, "prn_out"),
+ m_rom(*this, "rom"),
+ m_rom_bank(0x0000U),
+ m_busy_in(1U),
+ m_pe_in(1U),
+ m_slct_in(1U)
+{
+}
+
+
+
+//--------------------------------------------------
+// device_a2bus_card_interface implementation
+//--------------------------------------------------
+
+u8 a2bus_grappler_device_base::read_c800(u16 offset)
+{
+ return m_rom[(offset & 0x07ffU) | m_rom_bank];
+}
+
+
+
+//--------------------------------------------------
+// device_t implementation
+//--------------------------------------------------
+
+void a2bus_grappler_device_base::device_add_mconfig(machine_config &config)
+{
+ CENTRONICS(config, m_printer_conn, centronics_devices, "printer");
+ m_printer_conn->busy_handler().set(FUNC(a2bus_grappler_device_base::busy_w));
+ m_printer_conn->perror_handler().set(FUNC(a2bus_grappler_device_base::pe_w));
+ m_printer_conn->select_handler().set(FUNC(a2bus_grappler_device_base::slct_w));
+
+ OUTPUT_LATCH(config, m_printer_out);
+ m_printer_conn->set_output_latch(*m_printer_out);
+}
+
+
+void a2bus_grappler_device_base::device_start()
+{
+ save_item(NAME(m_rom_bank));
+ save_item(NAME(m_busy_in));
+ save_item(NAME(m_pe_in));
+ save_item(NAME(m_slct_in));
+}
+
+
+
+//--------------------------------------------------
+// printer status inputs
+//--------------------------------------------------
+
+void a2bus_grappler_device_base::set_rom_bank(u16 rom_bank)
+{
+ if (m_rom_bank != rom_bank)
+ LOG("Select ROM bank %04X\n", rom_bank);
+ m_rom_bank = rom_bank;
+}
+
+
+
+//--------------------------------------------------
+// printer status inputs
+//--------------------------------------------------
+
+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);
+}
+
+
+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);
+}
+
+
+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);
+}
+
+
+
+//--------------------------------------------------
+// synchronised printer status inputs
+//--------------------------------------------------
+
+void a2bus_grappler_device_base::set_busy_in(s32 param)
+{
+ if (u32(param) != m_busy_in)
+ {
+ LOG("BUSY=%d\n", param);
+ m_busy_in = u8(u32(param));
+ }
+}
+
+
+void a2bus_grappler_device_base::set_pe_in(s32 param)
+{
+ if (u32(param) != m_pe_in)
+ {
+ LOG("PAPER EMPTY=%d\n", param);
+ m_pe_in = u8(u32(param));
+ }
+}
+
+
+void a2bus_grappler_device_base::set_slct_in(s32 param)
+{
+ if (u32(param) != m_slct_in)
+ {
+ LOG("SELECT=%d\n", param);
+ m_slct_in = u8(u32(param));
+ }
+}
+
+
+
+//==============================================================
+// Grappler implementation
+//==============================================================
+
+class a2bus_grappler_device : public a2bus_grappler_device_base
+{
+public:
+ a2bus_grappler_device(machine_config const &mconfig, char const *tag, device_t *owner, u32 clock);
+
+ // 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;
+
+protected:
+ // device_t implementation
+ virtual tiny_rom_entry const *device_rom_region() const override { return ROM_NAME(grappler); }
+ 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:
+ // printer status inputs
+ void ack_w(int state);
+
+ // synchronised signals
+ void set_data(s32 param);
+ void set_strobe(s32 param);
+ void set_ack_in(s32 param);
+
+ u8 m_strobe; // U3 (pin 4)
+ u8 m_ack_latch; // U3 (pin 13)
+ u8 m_ack_in; // printer connector pin 19 (synchronised)
+};
+
+
+a2bus_grappler_device::a2bus_grappler_device(machine_config const &mconfig, char const *tag, device_t *owner, u32 clock) :
+ a2bus_grappler_device_base(mconfig, A2BUS_GRAPPLER, tag, owner, clock),
+ m_strobe(1U),
+ m_ack_latch(1U),
+ m_ack_in(1U)
+{
+}
+
+
+
+//--------------------------------------------------
+// device_a2bus_card_interface implementation
+//--------------------------------------------------
+
+u8 a2bus_grappler_device::read_c0nx(u8 offset)
+{
+ LOG("Read C0n%01X\n", offset);
+
+ if (!machine().side_effects_disabled())
+ {
+ if (BIT(offset, 1)) // A1 - assert strobe
+ machine().scheduler().synchronize(timer_expired_delegate(FUNC(a2bus_grappler_device::set_strobe), this), 0);
+ else if (BIT(offset, 2)) // A2 - release strobe
+ machine().scheduler().synchronize(timer_expired_delegate(FUNC(a2bus_grappler_device::set_strobe), this), 1);
+ }
+
+ if (BIT(offset, 0)) // A0 - printer status
+ {
+ return
+ 0xf0U | // TODO: actually open bus
+ (busy_in() << 3) |
+ (pe_in() << 2) |
+ (slct_in() << 1) |
+ m_ack_latch;
+ }
+ else
+ {
+ return 0xffU; // TODO: actually open bus
+ }
+}
+
+
+void a2bus_grappler_device::write_c0nx(u8 offset, u8 data)
+{
+ LOG("Write C0n%01X=%02X\n", offset, data);
+
+ if (BIT(offset, 0)) // A0 - write data
+ machine().scheduler().synchronize(timer_expired_delegate(FUNC(a2bus_grappler_device::set_data), this), int(unsigned(data)));
+
+ if (BIT(offset, 1)) // A1 - assert strobe
+ machine().scheduler().synchronize(timer_expired_delegate(FUNC(a2bus_grappler_device::set_strobe), this), 0);
+ else if (BIT(offset, 2)) // A2 - release strobe
+ machine().scheduler().synchronize(timer_expired_delegate(FUNC(a2bus_grappler_device::set_strobe), this), 1);
+}
+
+
+u8 a2bus_grappler_device::read_cnxx(u8 offset)
+{
+ return m_rom[offset | (slotno() << 8)];
+}
+
+
+void a2bus_grappler_device::write_cnxx(u8 offset, u8 data)
+{
+ LOG("Write Cn%02X=%02X (bus conflict)\n", offset, data);
+}
+
+
+
+//--------------------------------------------------
+// device_t implementation
+//--------------------------------------------------
+
+void a2bus_grappler_device::device_add_mconfig(machine_config &config)
+{
+ a2bus_grappler_device_base::device_add_mconfig(config);
+
+ m_printer_conn->ack_handler().set(FUNC(a2bus_grappler_device::ack_w));
+}
+
+
+void a2bus_grappler_device::device_start()
+{
+ a2bus_grappler_device_base::device_start();
+
+ save_item(NAME(m_strobe));
+ save_item(NAME(m_ack_latch));
+ save_item(NAME(m_ack_in));
+}
+
+
+void a2bus_grappler_device::device_reset()
+{
+ machine().scheduler().synchronize(timer_expired_delegate(FUNC(a2bus_grappler_device::set_strobe), this), 1);
+}
+
+
+
+//--------------------------------------------------
+// printer status inputs
+//--------------------------------------------------
+
+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);
+}
+
+
+
+//--------------------------------------------------
+// synchronised signals
+//--------------------------------------------------
+
+void a2bus_grappler_device::set_data(s32 param)
+{
+ LOG("Output data %02X\n", u8(u32(param)));
+ m_printer_out->write(u8(u32(param)));
+}
+
+
+void a2bus_grappler_device::set_strobe(s32 param)
+{
+ LOG("Output /STROBE=%d\n", param);
+ m_printer_conn->write_strobe(param);
+ if (m_strobe && !param)
+ {
+ if (m_ack_in)
+ {
+ if (!m_ack_latch)
+ LOG("Clearing acknowledge latch\n");
+ else
+ LOG("Previous data not acknowledged\n");
+ m_ack_latch = 1U;
+ }
+ else
+ {
+ LOG("/ACK asserted, not clearing acknowledge latch\n");
+ }
+ }
+ m_strobe = u8(u32(param));
+}
+
+
+void a2bus_grappler_device::set_ack_in(s32 param)
+{
+ if (u32(param) != m_ack_in)
+ {
+ LOG("/ACK=%d\n", param);
+ m_ack_in = u8(u32(param));
+ if (!param)
+ {
+ if (m_ack_latch)
+ LOG("Set acknowledge latch\n");
+ else
+ LOG("No data written since previous acknowledge\n");
+ m_ack_latch = 0U;
+ }
+ else if (!m_strobe)
+ {
+ LOG("Clearing acknowledge latch\n");
+ m_ack_latch = 1U;
+ }
+ }
+}
+
+
+
+//==============================================================
+// Grappler+ base
+//==============================================================
+
+class a2bus_grapplerplus_device_base : public a2bus_grappler_device_base
+{
+public:
+ // DIP switch handlers
+ virtual DECLARE_INPUT_CHANGED_MEMBER(sw_msb) { }
+
+ // device_a2bus_card_interface implementation
+ 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;
+
+protected:
+ a2bus_grapplerplus_device_base(machine_config const &mconfig, device_type type, char const *tag, device_t *owner, u32 clock);
+
+ // device_t implementation
+ virtual ioport_constructor device_input_ports() const override ATTR_COLD;
+ virtual void device_start() override ATTR_COLD;
+ virtual void device_reset() override ATTR_COLD;
+
+ // ACK latch set input
+ void ack_w(int state);
+
+ // signal state
+ u8 ack_latch() const { return m_ack_latch; }
+
+ required_ioport m_s1;
+
+private:
+ // synchronised printer status inputs
+ void set_ack_in(s32 param);
+
+ // for derived devices to implement
+ virtual void data_latched(u8 data) = 0;
+ virtual void ack_latch_set() { }
+ virtual void ack_latch_cleared() { }
+
+ u8 m_ack_latch; // U2C (pin 9)
+ u8 m_ack_in; // printer connector pin 19 (synchronised)
+};
+
+
+a2bus_grapplerplus_device_base::a2bus_grapplerplus_device_base(machine_config const &mconfig, device_type type, char const *tag, device_t *owner, u32 clock) :
+ a2bus_grappler_device_base(mconfig, type, tag, owner, clock),
+ m_s1(*this, "S1"),
+ m_ack_latch(1U),
+ m_ack_in(1U)
+{
+}
+
+
+
+//--------------------------------------------------
+// device_t implementation
+//--------------------------------------------------
+
+INPUT_PORTS_START(grapplerplus)
+ PORT_START("S1")
+ PORT_DIPNAME(0x07, 0x00, "Printer Type") PORT_DIPLOCATION("S1:4,3,2")
+ PORT_DIPSETTING( 0x00, "Epson Series")
+ PORT_DIPSETTING( 0x01, "NEC 8023/C. Itoh 8510/DMP 85")
+ PORT_DIPSETTING( 0x02, "Star Gemini")
+ PORT_DIPSETTING( 0x03, "Anadex Printers")
+ PORT_DIPSETTING( 0x04, "Okidata 82A, 83A, 92, 93, 84")
+ PORT_DIPSETTING( 0x06, "Okidata 84 w/o Step II Graphics")
+ PORT_DIPSETTING( 0x05, "Apple Dot Matrix")
+ PORT_DIPSETTING( 0x07, "invalid")
+ PORT_DIPNAME(0x08, 0x08, "Most Significant Bit") PORT_DIPLOCATION("S1:1") PORT_CHANGED_MEMBER(DEVICE_SELF, FUNC(a2bus_grapplerplus_device_base::sw_msb), 0)
+ PORT_DIPSETTING( 0x08, "Software Control")
+ PORT_DIPSETTING( 0x00, "Not Transmitted")
+INPUT_PORTS_END
+
+
+ioport_constructor a2bus_grapplerplus_device_base::device_input_ports() const
+{
+ return INPUT_PORTS_NAME(grapplerplus);
+}
+
+
+void a2bus_grapplerplus_device_base::device_start()
+{
+ a2bus_grappler_device_base::device_start();
+
+ save_item(NAME(m_ack_latch));
+ save_item(NAME(m_ack_in));
+}
+
+
+void a2bus_grapplerplus_device_base::device_reset()
+{
+ m_ack_latch = 1U;
+}
+
+
+
+//--------------------------------------------------
+// device_a2bus_card_interface implementation
+//--------------------------------------------------
+
+void a2bus_grapplerplus_device_base::write_c0nx(u8 offset, u8 data)
+{
+ LOG("Write C0n%01X=%02X\n", offset, data);
+
+ if (!(offset & 0x03U)) // !A0 && !A1 - write data
+ {
+ // latch output data
+ LOG("Latch data %02X\n", data);
+ data_latched(data);
+
+ // clearing the ACK latch will acknowledge an interrupt
+ if (m_ack_in)
+ {
+ if (m_ack_latch)
+ LOG("Clearing acknowledge latch\n");
+ else
+ LOG("Previous data not acknowledged\n");
+ m_ack_latch = 0U;
+ ack_latch_cleared();
+ }
+ else
+ {
+ LOG("/ACK asserted, not clearing acknowledge latch\n");
+ }
+ }
+
+ if (BIT(offset, 0)) // A0 - select high ROM bank
+ set_rom_bank(0x0800U);
+}
+
+
+u8 a2bus_grapplerplus_device_base::read_cnxx(u8 offset)
+{
+ if (!machine().side_effects_disabled())
+ set_rom_bank(0x0000U);
+ return m_rom[(!m_ack_latch && BIT(offset, 7)) ? (offset & 0xbfU) : offset];
+}
+
+
+void a2bus_grapplerplus_device_base::write_cnxx(u8 offset, u8 data)
+{
+ LOG("Write Cn%02X=%02X (bus conflict)\n", offset, data);
+
+ set_rom_bank(0x0000U);
+}
+
+
+
+//--------------------------------------------------
+// ACK latch set input
+//--------------------------------------------------
+
+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);
+}
+
+
+
+//--------------------------------------------------
+// synchronised printer status inputs
+//--------------------------------------------------
+
+void a2bus_grapplerplus_device_base::set_ack_in(s32 param)
+{
+ if (u32(param) != m_ack_in)
+ {
+ LOG("/ACK=%d\n", param);
+ m_ack_in = u8(u32(param));
+ if (!param)
+ {
+ if (!m_ack_latch)
+ LOG("Set acknowledge latch\n");
+ else
+ LOG("No data written since previous acknowledge\n");
+ m_ack_latch = 1U;
+ ack_latch_set();
+ }
+ }
+}
+
+
+
+//==============================================================
+// Grappler+ implementation
+//==============================================================
+
+class a2bus_grapplerplus_device : public a2bus_grapplerplus_device_base
+{
+public:
+ a2bus_grapplerplus_device(machine_config const &mconfig, char const *tag, device_t *owner, u32 clock);
+
+ // DIP switch handlers
+ virtual DECLARE_INPUT_CHANGED_MEMBER(sw_msb) override;
+
+ // device_a2bus_card_interface implementation
+ virtual u8 read_c0nx(u8 offset) override;
+ virtual void write_c0nx(u8 offset, u8 data) override;
+
+protected:
+ // device_t implementation
+ virtual tiny_rom_entry const *device_rom_region() const override { return ROM_NAME(grapplerplus); }
+ 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:
+ // a2bus_grapplerplus_device_base implementation
+ virtual void data_latched(u8 data) override;
+ virtual void ack_latch_set() override;
+ virtual void ack_latch_cleared() override;
+
+ // timer handlers
+ TIMER_CALLBACK_MEMBER(update_strobe);
+
+ emu_timer * m_strobe_timer;
+
+ u8 m_data_latch; // U10
+ u8 m_irq_disable; // U2A (pin 4)
+ u8 m_irq; // U3D (pin 13)
+ u8 m_next_strobe; // U5A (pin 5)
+};
+
+
+a2bus_grapplerplus_device::a2bus_grapplerplus_device(machine_config const &mconfig, char const *tag, device_t *owner, u32 clock) :
+ a2bus_grapplerplus_device_base(mconfig, A2BUS_GRAPPLERPLUS, tag, owner, clock),
+ m_strobe_timer(nullptr),
+ m_data_latch(0xffU),
+ m_irq_disable(1U),
+ m_irq(0x00U),
+ m_next_strobe(1U)
+{
+}
+
+
+
+//--------------------------------------------------
+// DIP switch handlers
+//--------------------------------------------------
+
+INPUT_CHANGED_MEMBER(a2bus_grapplerplus_device::sw_msb)
+{
+ if (BIT(m_data_latch, 7))
+ m_printer_out->write(m_data_latch & (BIT(m_s1->read(), 3) ? 0xffU : 0x7fU));
+}
+
+
+
+//--------------------------------------------------
+// device_a2bus_card_interface implementation
+//--------------------------------------------------
+
+u8 a2bus_grapplerplus_device::read_c0nx(u8 offset)
+{
+ return
+ m_irq |
+ ((m_s1->read() & 0x07U) << 4) |
+ (busy_in() << 3) |
+ (pe_in() << 2) |
+ (slct_in() << 1) |
+ ack_latch();
+}
+
+
+void a2bus_grapplerplus_device::write_c0nx(u8 offset, u8 data)
+{
+ a2bus_grapplerplus_device_base::write_c0nx(offset, data);
+
+ if (BIT(offset, 1)) // A1 - disable interrupt
+ {
+ if (!m_irq_disable)
+ LOG("Disable interrupt request\n");
+ else
+ LOG("Interrupt request already disabled\n");
+ m_irq_disable = 1U;
+ if (m_irq)
+ {
+ assert(ack_latch());
+ LOG("Releasing slot IRQ\n");
+ m_irq = 0x00U;
+ lower_slot_irq();
+ }
+ }
+ else if (BIT(offset, 2)) // A2 - enable interrupt
+ {
+ if (m_irq_disable)
+ LOG("Enable interrupt request\n");
+ else
+ LOG("Interrupt request already enabled\n");
+ m_irq_disable = 0U;
+ if (ack_latch() && !m_irq)
+ {
+ LOG("Asserting slot IRQ\n");
+ m_irq = 0x80U;
+ raise_slot_irq();
+ }
+ }
+}
+
+
+
+//--------------------------------------------------
+// device_t implementation
+//--------------------------------------------------
+
+void a2bus_grapplerplus_device::device_add_mconfig(machine_config &config)
+{
+ a2bus_grapplerplus_device_base::device_add_mconfig(config);
+
+ m_printer_conn->ack_handler().set(FUNC(a2bus_grapplerplus_device::ack_w));
+}
+
+
+void a2bus_grapplerplus_device::device_start()
+{
+ a2bus_grapplerplus_device_base::device_start();
+
+ m_strobe_timer = timer_alloc(FUNC(a2bus_grapplerplus_device::update_strobe), this);
+
+ m_next_strobe = 1U;
+
+ save_item(NAME(m_data_latch));
+ save_item(NAME(m_irq_disable));
+ save_item(NAME(m_irq));
+ save_item(NAME(m_next_strobe));
+
+ m_strobe_timer->adjust(attotime::from_ticks(7, clock()));
+}
+
+
+void a2bus_grapplerplus_device::device_reset()
+{
+ a2bus_grapplerplus_device_base::device_reset();
+
+ m_irq_disable = 1U;
+ if (m_irq)
+ {
+ m_irq = 0x00U;
+ lower_slot_irq();
+ }
+}
+
+
+
+//--------------------------------------------------
+// a2bus_grapplerplus_device_base implementation
+//--------------------------------------------------
+
+void a2bus_grapplerplus_device::data_latched(u8 data)
+{
+ // remember MSB can be forced low by DIP switch
+ m_data_latch = data;
+ m_printer_out->write(m_data_latch & (BIT(m_s1->read(), 3) ? 0xffU : 0x7fU));
+
+ // generate strobe pulse after one clock cycle
+ m_next_strobe = 0U;
+ if (!m_strobe_timer->enabled())
+ {
+ LOG("Start strobe timer\n");
+ m_strobe_timer->adjust(attotime::from_ticks(7, clock()));
+ }
+}
+
+
+void a2bus_grapplerplus_device::ack_latch_set()
+{
+ if (!m_irq_disable && !m_irq)
+ {
+ LOG("Asserting slot IRQ\n");
+ m_irq = 0x80U;
+ raise_slot_irq();
+ }
+}
+
+
+void a2bus_grapplerplus_device::ack_latch_cleared()
+{
+ if (m_irq)
+ {
+ assert(!m_irq_disable);
+ LOG("Releasing slot IRQ\n");
+ m_irq = 0x00U;
+ lower_slot_irq();
+ }
+}
+
+
+
+//--------------------------------------------------
+// timer handlers
+//--------------------------------------------------
+
+TIMER_CALLBACK_MEMBER(a2bus_grapplerplus_device::update_strobe)
+{
+ LOG("Output /STROBE=%u\n", m_next_strobe);
+ m_printer_conn->write_strobe(m_next_strobe);
+ if (!m_next_strobe)
+ {
+ LOG("Start strobe timer\n");
+ m_next_strobe = 1U;
+ m_strobe_timer->adjust(attotime::from_ticks(7, clock()));
+ }
+}
+
+
+
+//==============================================================
+// Buffered Grappler+ implementation
+//==============================================================
+
+class a2bus_buf_grapplerplus_device : public a2bus_grapplerplus_device_base
+{
+public:
+ a2bus_buf_grapplerplus_device(machine_config const &mconfig, char const *tag, device_t *owner, u32 clock) :
+ a2bus_buf_grapplerplus_device(mconfig, A2BUS_BUFGRAPPLERPLUS, tag, owner, clock)
+ {
+ }
+
+ // device_a2bus_card_interface implementation
+ virtual u8 read_c0nx(u8 offset) override;
+
+protected:
+ a2bus_buf_grapplerplus_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 { return ROM_NAME(bufgrapplerplus); }
+ virtual void device_add_mconfig(machine_config &config) override ATTR_COLD;
+ virtual ioport_constructor device_input_ports() const override ATTR_COLD;
+ virtual void device_start() override ATTR_COLD;
+ virtual void device_reset() override ATTR_COLD;
+
+ // helpers
+ template <typename T> void device_add_mconfig(machine_config &config, T &&mcu_clock);
+
+private:
+ // a2bus_grapplerplus_device_base implementation
+ virtual void data_latched(u8 data) override;
+
+ // printer status inputs
+ void buf_ack_w(int state);
+
+ // MCU I/O handlers
+ void mcu_io(address_map &map) ATTR_COLD;
+ void mcu_p2_w(u8 data);
+ u8 mcu_bus_r();
+ void mcu_bus_w(u8 data);
+
+ // synchronised signals
+ void set_buf_data(s32 param);
+ void set_buf_ack_in(s32 param);
+ void clear_ibusy(s32 param);
+
+ required_device<mcs48_cpu_device> m_mcu;
+ std::unique_ptr<u8 []> m_ram;
+
+ u16 m_ram_row; // U1-U8
+ u8 m_ram_mask; // mask out chips that are not installed
+ u8 m_mcu_p2; // U10
+ u8 m_data_latch; // U14 (synchronised)
+ u8 m_ibusy; // U12
+ u8 m_buf_ack_latch; // U12
+ u8 m_buf_ack_in; // printer connector pin 19 (synchronised)
+};
+
+
+
+a2bus_buf_grapplerplus_device::a2bus_buf_grapplerplus_device(machine_config const &mconfig, device_type type, char const *tag, device_t *owner, u32 clock) :
+ a2bus_grapplerplus_device_base(mconfig, type, tag, owner, clock),
+ m_mcu(*this, "mcu"),
+ m_ram(),
+ m_ram_row(0xff00),
+ m_ram_mask(0x00U),
+ m_mcu_p2(0xffU),
+ m_data_latch(0xffU),
+ m_ibusy(1U),
+ m_buf_ack_latch(1U),
+ m_buf_ack_in(1U)
+{
+}
+
+
+
+//--------------------------------------------------
+// device_a2bus_card_interface implementation
+//--------------------------------------------------
+
+u8 a2bus_buf_grapplerplus_device::read_c0nx(u8 offset)
+{
+ return
+ ((m_s1->read() & 0x0fU) << 4) |
+ (m_ibusy << 3) |
+ (pe_in() << 2) |
+ (slct_in() << 1) |
+ ack_latch();
+}
+
+
+
+//--------------------------------------------------
+// device_t implementation
+//--------------------------------------------------
+
+INPUT_PORTS_START(bufgrapplerplus)
+ PORT_INCLUDE(grapplerplus)
+
+ PORT_START("CNF")
+ PORT_CONFNAME(0xff, 0x00, "RAM Size")
+ PORT_CONFSETTING( 0xfc, "16K (2 chips)")
+ PORT_CONFSETTING( 0xf0, "32K (4 chips)")
+ PORT_CONFSETTING( 0x00, "64K (8 chips)")
+INPUT_PORTS_END
+
+
+void a2bus_buf_grapplerplus_device::device_add_mconfig(machine_config &config)
+{
+ // 1982 schematics show MCU driven by 7M clock
+ device_add_mconfig(config, DERIVED_CLOCK(1, 1));
+}
+
+
+ioport_constructor a2bus_buf_grapplerplus_device::device_input_ports() const
+{
+ return INPUT_PORTS_NAME(bufgrapplerplus);
+}
+
+
+void a2bus_buf_grapplerplus_device::device_start()
+{
+ a2bus_grapplerplus_device_base::device_start();
+
+ m_ram = std::make_unique<u8 []>(0x10000);
+
+ save_pointer(NAME(m_ram), 0x10000);
+ save_item(NAME(m_ram_row));
+ save_item(NAME(m_ram_mask));
+ save_item(NAME(m_mcu_p2));
+ save_item(NAME(m_data_latch));
+ save_item(NAME(m_ibusy));
+ save_item(NAME(m_buf_ack_latch));
+ save_item(NAME(m_buf_ack_in));
+}
+
+
+void a2bus_buf_grapplerplus_device::device_reset()
+{
+ // The MCU is not reset when /RST is asserted. Instead, /RST is
+ // connected to P27. Pressing the reset key(s) momentarily will not
+ // clear the print buffer - the host Apple II can be reset without
+ // interrupting a long print job. Holding the reset key(s) for two
+ // seconds clears the buffer. Holding the reset key(s) on initial
+ // boot enters the RAM test (results are printed). MAME doesn't
+ // currently cater for devices that don't reset their children on
+ // reset, and Apple II slots don't currently expose the /RST signal
+ // directly.
+
+ a2bus_grapplerplus_device_base::device_reset();
+
+ // should only do this on initial reset, but we get away with it here because the MCU is automatically reset even if it shouldn't be
+ m_ram_mask = ioport("CNF")->read();
+}
+
+
+
+//--------------------------------------------------
+// helpers
+//--------------------------------------------------
+
+template <typename T>
+void a2bus_buf_grapplerplus_device::device_add_mconfig(machine_config &config, T &&mcu_clock)
+{
+ a2bus_grapplerplus_device_base::device_add_mconfig(config);
+
+ m_printer_conn->ack_handler().set(FUNC(a2bus_buf_grapplerplus_device::buf_ack_w));
+
+ // P22 is tied high, pulling it low is used for some factory test mode
+ I8048(config, m_mcu, std::forward<T>(mcu_clock));
+ m_mcu->set_addrmap(AS_IO, &a2bus_buf_grapplerplus_device::mcu_io);
+ m_mcu->p2_out_cb().set(FUNC(a2bus_buf_grapplerplus_device::mcu_p2_w));
+ m_mcu->t0_in_cb().set([this] () { return busy_in(); });
+ m_mcu->t1_in_cb().set([this] () { return m_buf_ack_latch; });
+ m_mcu->bus_in_cb().set(FUNC(a2bus_buf_grapplerplus_device::mcu_bus_r));
+ m_mcu->bus_out_cb().set(FUNC(a2bus_buf_grapplerplus_device::mcu_bus_w));
+}
+
+
+
+//--------------------------------------------------
+// a2bus_grapplerplus_device_base implementation
+//--------------------------------------------------
+
+void a2bus_buf_grapplerplus_device::data_latched(u8 data)
+{
+ // IBUSY is exposed on C0nX
+ if (!m_ibusy)
+ LOG("Setting IBUSY\n");
+ else
+ LOG("IBUSY already set\n");
+ m_ibusy = 1U;
+
+ // these signals cross executable device domains
+ machine().scheduler().synchronize(timer_expired_delegate(FUNC(a2bus_buf_grapplerplus_device::set_buf_data), this), int(unsigned(data)));
+ m_mcu->set_input_line(MCS48_INPUT_IRQ, ASSERT_LINE);
+}
+
+
+
+//--------------------------------------------------
+// printer status inputs
+//--------------------------------------------------
+
+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);
+}
+
+
+
+//--------------------------------------------------
+// MCU I/O handlers
+//--------------------------------------------------
+
+void a2bus_buf_grapplerplus_device::mcu_io(address_map &map)
+{
+ map(0x00, 0xff).nopr(); // read to put the BUS lines in high-impedance state before a real read using INS
+}
+
+
+void a2bus_buf_grapplerplus_device::mcu_p2_w(u8 data)
+{
+ // check for changed bits
+ u8 const diff(data ^ m_mcu_p2);
+ m_mcu_p2 = data;
+
+ // P20 enables /CAS on /RD or /WR
+ if (BIT(diff, 0))
+ LOG("RAM EN=%u\n", BIT(data, 0));
+
+ // row address strobe
+ if (BIT(diff, 1))
+ {
+ if (!BIT(data, 1))
+ {
+ LOG("Row address %02X\n", m_mcu->p1_r());
+ m_ram_row = u16(m_mcu->p1_r()) << 8;
+ }
+ else
+ {
+ LOG("Released /RAS\n");
+ }
+ }
+
+ // P23 is the /IOEN signal
+ if (BIT(diff, 3))
+ LOG("/IOEN=%u\n", BIT(data, 3));
+
+ // P24 allows fast DRAM refresh using ALE for /RAS
+ if (BIT(diff, 4))
+ LOG(BIT(data, 4) ? "Start DRAM refresh\n" : "End DRAM refresh\n");
+
+ // P25 is the strobe output and clears the acknowledge latch
+ if (BIT(diff, 5))
+ {
+ if (BIT(data, 5))
+ {
+ if (m_buf_ack_in)
+ {
+ if (m_buf_ack_latch)
+ LOG("T1 already set\n");
+ else
+ LOG("Setting T1\n");
+ m_buf_ack_latch = 1U;
+ }
+ else
+ {
+ LOG("/ACK asserted, not setting T1\n");
+ }
+ }
+ LOG("Output /STROBE=%u\n", BIT(data, 5));
+ m_printer_conn->write_strobe(BIT(data, 5));
+ }
+}
+
+
+u8 a2bus_buf_grapplerplus_device::mcu_bus_r()
+{
+ u8 result(0xffU);
+
+ // RAM EN enables RAM
+ if (BIT(m_mcu_p2, 0))
+ {
+ if (!BIT(m_mcu_p2, 1))
+ {
+ u16 const addr(m_ram_row | u16(m_mcu->p1_r()));
+ LOG("Read RAM @%04X=%02X\n", addr, m_ram[addr]);
+ result &= m_ram[addr] | m_ram_mask;
+ }
+ else
+ {
+ LOG("/RD asserted /CAS while /RAS not asserted\n");
+ }
+ }
+
+ // /IOEN enables the data latch, pulses /IACK and clears IBUSY on /RD
+ if (!BIT(m_mcu_p2, 3))
+ {
+ LOG("Read data latch %02X\n", m_data_latch);
+ result &= m_data_latch;
+ machine().scheduler().synchronize(timer_expired_delegate(FUNC(a2bus_buf_grapplerplus_device::clear_ibusy), this));
+ m_mcu->set_input_line(MCS48_INPUT_IRQ, CLEAR_LINE);
+ ack_w(0);
+ ack_w(1);
+ }
+
+ return result;
+}
+
+
+void a2bus_buf_grapplerplus_device::mcu_bus_w(u8 data)
+{
+ // RAM EN enables RAM
+ if (BIT(m_mcu_p2, 0))
+ {
+ if (!BIT(m_mcu_p2, 1))
+ {
+ u16 const addr(m_ram_row | u16(m_mcu->p1_r()));
+ LOG("Wrote RAM @%04X=%02X\n", addr, data);
+ m_ram[addr] = data | m_ram_mask;
+ }
+ else
+ {
+ LOG("/WR asserted /CAS while /RAS not asserted\n");
+ }
+ }
+
+ // /IOEN enables output latch
+ if (!BIT(m_mcu_p2, 3))
+ {
+ LOG("Output data %02X\n", data);
+ m_printer_out->write(data);
+ }
+}
+
+
+
+//--------------------------------------------------
+// synchronised signals
+//--------------------------------------------------
+
+void a2bus_buf_grapplerplus_device::set_buf_data(s32 param)
+{
+ m_data_latch = u8(u32(param));
+}
+
+
+void a2bus_buf_grapplerplus_device::set_buf_ack_in(s32 param)
+{
+ if (u32(param) != m_buf_ack_in)
+ {
+ LOG("/ACK=%d\n", param);
+ m_buf_ack_in = u8(u32(param));
+ if (!param)
+ {
+ if (m_buf_ack_latch)
+ LOG("Clearing T1\n");
+ else
+ LOG("No data output since previous acknowledge\n");
+ m_buf_ack_latch = 0U;
+ }
+ }
+}
+
+
+void a2bus_buf_grapplerplus_device::clear_ibusy(s32 param)
+{
+ if (m_ibusy)
+ {
+ LOG("Clearing IBUSY\n");
+ m_ibusy = 0U;
+ }
+ else
+ {
+ LOG("IBUSY already clear\n");
+ }
+}
+
+
+
+//==============================================================
+// Buffered Grappler+ rev A implementation
+//==============================================================
+
+class a2bus_buf_grapplerplus_reva_device : public a2bus_buf_grapplerplus_device
+{
+public:
+ a2bus_buf_grapplerplus_reva_device(machine_config const &mconfig, char const *tag, device_t *owner, u32 clock) :
+ a2bus_buf_grapplerplus_device(mconfig, A2BUS_BUFGRAPPLERPLUSA, tag, owner, clock)
+ {
+ }
+
+ static auto parent_rom_device_type() { return &A2BUS_BUFGRAPPLERPLUS; }
+
+protected:
+ // device_t implementation
+ virtual void device_add_mconfig(machine_config &config) override
+ {
+ // boards with 6 MHz clock crystal for MCU have been seen with both UVEPROM and mask ROM parts
+ // ORANGE MICRO INC., 1983
+ // ASSY NO, 72 BGP 00001 REV A
+ // PART NO. 95PCB00003
+ a2bus_buf_grapplerplus_device::device_add_mconfig(config, 6_MHz_XTAL);
+ }
+};
+
+} // anonymous namespace
+
+
+
+DEFINE_DEVICE_TYPE_PRIVATE(A2BUS_GRAPPLER, device_a2bus_card_interface, a2bus_grappler_device, "a2grappler", "Orange Micro Grappler Printer Interface")
+DEFINE_DEVICE_TYPE_PRIVATE(A2BUS_GRAPPLERPLUS, device_a2bus_card_interface, a2bus_grapplerplus_device, "a2grapplerplus", "Orange Micro Grappler+ Printer Interface")
+DEFINE_DEVICE_TYPE_PRIVATE(A2BUS_BUFGRAPPLERPLUS, device_a2bus_card_interface, a2bus_buf_grapplerplus_device, "a2bufgrapplerplus", "Orange Micro Buffered Grappler+ Printer Interface")
+DEFINE_DEVICE_TYPE_PRIVATE(A2BUS_BUFGRAPPLERPLUSA, device_a2bus_card_interface, a2bus_buf_grapplerplus_reva_device, "a2bufgrapplerplusa", "Orange Micro Buffered Grappler+ (rev A) Printer Interface")
diff --git a/src/devices/bus/a2bus/grappler.h b/src/devices/bus/a2bus/grappler.h
new file mode 100644
index 00000000000..2e311ab03ef
--- /dev/null
+++ b/src/devices/bus/a2bus/grappler.h
@@ -0,0 +1,63 @@
+// license:BSD-3-Clause
+// copyright-holders:Vas Crabb
+/***********************************************************************
+
+ Orange Micro Grappler/Grappler+ Printer Interface
+
+ With references to schematics from The Grappler™ Interface
+ Operators Manual (Copyright 1982 Orance Micro, Inc.) and
+ Grappler™+ Printer Interface Series Operators Manual (© Orange
+ Micro, Inc. 1982). This uses the IC locations on the "long"
+ version of the Grappler+ card - the newer "short" version of the
+ card has slightly different circuitry and completely different IC
+ locations.
+
+ 26-pin two-row header to printer:
+
+ STB 1 2 GND
+ D0 3 4 GND
+ D1 5 6 GND
+ D2 7 8 GND
+ D3 9 10 GND
+ D4 11 12 GND
+ D5 23 14 GND
+ D6 15 16 GND
+ D7 17 18 GND
+ ACK 19 20 GND
+ BUSY 21 22 GND
+ P.E. 23 24 GND
+ SLCT 25 26 GND
+
+ Orange Micro Buffered Grappler+ Printer Interface
+
+ 26-pin two-row header to printer:
+
+ STB 1 2 GND
+ D0 3 4 GND
+ D1 5 6 GND
+ D2 7 8 GND
+ D3 9 10 GND
+ D4 11 12 GND
+ D5 23 14 GND
+ D6 15 16 GND
+ D7 17 18 GND
+ ACK 19 20 GND
+ BUSY 21 22 GND
+ P.E. 23 24 GND
+ SLCT 25 26 N/C
+
+***********************************************************************/
+#ifndef MAME_BUS_A2BUS_GRAPPLER_H
+#define MAME_BUS_A2BUS_GRAPPLER_H
+
+#pragma once
+
+#include "a2bus.h"
+
+
+DECLARE_DEVICE_TYPE(A2BUS_GRAPPLER, device_a2bus_card_interface)
+DECLARE_DEVICE_TYPE(A2BUS_GRAPPLERPLUS, device_a2bus_card_interface)
+DECLARE_DEVICE_TYPE(A2BUS_BUFGRAPPLERPLUS, device_a2bus_card_interface)
+DECLARE_DEVICE_TYPE(A2BUS_BUFGRAPPLERPLUSA, device_a2bus_card_interface)
+
+#endif // MAME_BUS_A2BUS_GRAPPLER_H
diff --git a/src/devices/bus/a2bus/lancegs.cpp b/src/devices/bus/a2bus/lancegs.cpp
new file mode 100644
index 00000000000..e2b249c03f2
--- /dev/null
+++ b/src/devices/bus/a2bus/lancegs.cpp
@@ -0,0 +1,215 @@
+// license:BSD-3-Clause
+// copyright-holders:Kelvin Sherlock
+/*********************************************************************
+
+ lancegs.cpp
+
+ Apple II LANceGS Card
+
+ Kelvin Sherlock with assistance from Geoff Weiss
+
+ SMSC LAN 91c96 and 24c04 EEPROM
+
+
+ Bit 1 of C0nF switches between EEPROM (1) and Ethernet (0, default).
+ This bit is write only.
+
+ In EEPROM Mode:
+
+ C0n4 - Clock Low
+ C0n5 - Clock High
+ C0n6 - Data Low
+ C0n7 - Data High
+ C0n8 - Read Data
+ C0nF - toggle EEPROM/Ethernet
+
+
+ Known EEPROM locations. All strings high ascii, 0-terminated.
+
+ 0x00: Identification string ("LANceGS Ethernet Card (c) 2000 Joachim Lange")
+ 0x30: Revision string
+ 0x40: Revision Code (1 byte)
+ 0x48: Production date, yy m d (4 bytes)
+ 0x4c: Service date, yy m d (4 bytes)
+ 0x50: Serial Number (2 bytes)
+ 0x60: MAC Address (6 bytes)
+ 0x66: Destination Mac Address (6 bytes) *
+ 0x80: IP Address (4 bytes) *
+ 0x84: Destination IP Address (4 bytes) *
+ 0x88: Netmask (4 bytes) *
+ 0x8c: Gateway (4 bytes) *
+
+ * configurable with included software.
+
+
+*********************************************************************/
+
+#include "emu.h"
+#include "lancegs.h"
+
+#include "machine/smc91c9x.h"
+#include "machine/i2cmem.h"
+
+
+namespace {
+
+//**************************************************************************
+// TYPE DEFINITIONS
+//**************************************************************************
+
+class a2bus_lancegs_device:
+ public device_t,
+ public device_a2bus_card_interface
+{
+public:
+ // construction/destruction
+ a2bus_lancegs_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
+
+protected:
+ a2bus_lancegs_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 ATTR_COLD;
+ virtual const tiny_rom_entry *device_rom_region() const override ATTR_COLD;
+
+ virtual void device_start() override ATTR_COLD;
+ virtual void device_reset() override ATTR_COLD;
+
+ virtual uint8_t read_c0nx(uint8_t offset) override;
+ virtual void write_c0nx(uint8_t offset, uint8_t data) override;
+
+private:
+ required_device<smc91c96_device> m_netinf;
+ required_device<i2c_24c04_device> m_i2cmem;
+ bool m_shadow;
+
+ void netinf_irq_w(int state);
+};
+
+
+//**************************************************************************
+// LIVE DEVICE
+//**************************************************************************
+
+a2bus_lancegs_device::a2bus_lancegs_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) :
+ a2bus_lancegs_device(mconfig, A2BUS_LANCEGS, tag, owner, clock)
+{
+}
+
+a2bus_lancegs_device::a2bus_lancegs_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_netinf(*this, "smc91c96"),
+ m_i2cmem(*this, "i2cmem"),
+ m_shadow(false)
+{
+}
+
+void a2bus_lancegs_device::device_add_mconfig(machine_config &config)
+{
+ SMC91C96(config, m_netinf, 20_MHz_XTAL); // Datasheet fig 12.26, pg 122.
+ I2C_24C04(config, m_i2cmem, 0).set_address(0x80).set_e0(1);
+
+ m_netinf->irq_handler().set(FUNC(a2bus_lancegs_device::netinf_irq_w));
+}
+
+//-------------------------------------------------
+// device_start - device-specific startup
+//-------------------------------------------------
+
+void a2bus_lancegs_device::device_start()
+{
+ save_item(NAME(m_shadow));
+}
+
+void a2bus_lancegs_device::device_reset()
+{
+ m_shadow = false;
+}
+
+/*-------------------------------------------------
+ read_c0nx - called for reads from this card's c0nx space
+-------------------------------------------------*/
+
+uint8_t a2bus_lancegs_device::read_c0nx(uint8_t offset)
+{
+ if (m_shadow) {
+ switch(offset) {
+ case 0x08: /* read data */
+ return 0xfe | m_i2cmem->read_sda();
+ break;
+ case 0x0f:
+ return 0x33;
+ break;
+ default:
+ return 0xff;
+ break;
+ }
+ } else {
+ const uint16_t mask = offset & 0x01 ? 0xff00: 0x00ff;
+ const uint16_t value = m_netinf->read(offset >> 1, mask);
+ return offset & 0x01 ? value >> 8 : value;
+ }
+}
+
+/*-------------------------------------------------
+ write_c0nx - called for writes to this card's c0nx space
+-------------------------------------------------*/
+
+void a2bus_lancegs_device::write_c0nx(uint8_t offset, uint8_t data)
+{
+ if (offset == 0x0f) {
+ m_shadow = data & 0x01;
+ return;
+ }
+
+ if (m_shadow) {
+ switch(offset) {
+ case 0x04: /* set clock low */
+ m_i2cmem->write_scl(0);
+ break;
+ case 0x05: /* set clock high */
+ m_i2cmem->write_scl(1);
+ break;
+ case 0x06: /* set data low */
+ m_i2cmem->write_sda(0);
+ break;
+ case 0x07: /* set data high */
+ m_i2cmem->write_sda(1);
+ break;
+ default:
+ break;
+ }
+ } else {
+ const uint16_t mask = offset & 0x01 ? 0xff00: 0x00ff;
+ const uint16_t value = offset & 0x01 ? data << 8 : data;
+ m_netinf->write(offset >> 1, value, mask);
+ }
+}
+
+void a2bus_lancegs_device::netinf_irq_w(int state)
+{
+ if (state) {
+ raise_slot_irq();
+ } else {
+ lower_slot_irq();
+ }
+}
+
+
+ROM_START(lancegs)
+ ROM_REGION(0x0200, "i2cmem", 0)
+ ROM_LOAD("lancegs.nv", 0x0000, 0x0200, NO_DUMP)
+ROM_END
+
+const tiny_rom_entry *a2bus_lancegs_device::device_rom_region() const
+{
+ return ROM_NAME(lancegs);
+}
+
+} // anonymous namespace
+
+
+//**************************************************************************
+// GLOBAL VARIABLES
+//**************************************************************************
+
+DEFINE_DEVICE_TYPE_PRIVATE(A2BUS_LANCEGS, device_a2bus_card_interface, a2bus_lancegs_device, "a2lancegs", "///SHH Systeme LANceGS")
diff --git a/src/devices/bus/a2bus/lancegs.h b/src/devices/bus/a2bus/lancegs.h
new file mode 100644
index 00000000000..1069d5e696d
--- /dev/null
+++ b/src/devices/bus/a2bus/lancegs.h
@@ -0,0 +1,19 @@
+// license:BSD-3-Clause
+// copyright-holders:Kelvin Sherlock
+/*********************************************************************
+
+ lancegs.h
+
+ Apple II LANceGS Card
+
+*********************************************************************/
+
+#ifndef MAME_BUS_A2BUS_LANCEGS_H
+#define MAME_BUS_A2BUS_LANCEGS_H
+
+#include "a2bus.h"
+
+// device type definition
+DECLARE_DEVICE_TYPE(A2BUS_LANCEGS, device_a2bus_card_interface)
+
+#endif // MAME_BUS_A2BUS_LANCEGS_H
diff --git a/src/devices/bus/a2bus/laser128.cpp b/src/devices/bus/a2bus/laser128.cpp
index e0c7626aa93..ecddbc66b14 100644
--- a/src/devices/bus/a2bus/laser128.cpp
+++ b/src/devices/bus/a2bus/laser128.cpp
@@ -23,6 +23,7 @@
//**************************************************************************
DEFINE_DEVICE_TYPE(A2BUS_LASER128, a2bus_laser128_device, "a2laser128", "VTech Laser 128 Internal Device")
+DEFINE_DEVICE_TYPE(A2BUS_LASER128_ORIG, a2bus_laser128_orig_device, "a2laser128o", "VTech Laser 128 Internal Device (original hardware)")
/***************************************************************************
FUNCTION PROTOTYPES
@@ -42,8 +43,7 @@ void a2bus_laser128_device::device_add_mconfig(machine_config &config)
a2bus_laser128_device::a2bus_laser128_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_slot7_bank(0), m_slot7_ram_bank(0)
-
+ device_a2bus_card_interface(mconfig, *this), m_rom(nullptr), m_slot7_bank(0), m_bParPrinter(false), m_slot7_ram_bank(0)
{
}
@@ -52,6 +52,11 @@ a2bus_laser128_device::a2bus_laser128_device(const machine_config &mconfig, cons
{
}
+a2bus_laser128_orig_device::a2bus_laser128_orig_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) :
+ a2bus_laser128_device(mconfig, A2BUS_LASER128_ORIG, tag, owner, clock)
+{
+}
+
//-------------------------------------------------
// device_start - device-specific startup
//-------------------------------------------------
@@ -80,6 +85,11 @@ void a2bus_laser128_device::write_c0nx(uint8_t offset, uint8_t data)
uint8_t a2bus_laser128_device::read_cnxx(uint8_t offset)
{
+ if ((!m_bParPrinter) && (slotno() == 1))
+ {
+ return m_rom[offset + 0x5100];
+ }
+
return m_rom[offset + (slotno() * 0x100) + 0x4000];
}
@@ -142,3 +152,29 @@ bool a2bus_laser128_device::take_c800()
return false;
}
}
+
+uint8_t a2bus_laser128_orig_device::read_c800(uint16_t offset)
+{
+ switch (slotno())
+ {
+ case 1:
+ return m_rom[(offset & 0x7ff) + 0x4800];
+
+ case 2:
+ return m_rom[(offset & 0x7ff) + 0x5800];
+
+ case 5:
+ return m_rom[(offset & 0x7ff) + 0x5000];
+
+ case 6:
+ return m_rom[(offset & 0x7ff) + 0x6800];
+
+ case 7:
+ if (offset < 0x400)
+ return m_slot7_ram[offset];
+ else
+ return m_rom[(offset & 0x3ff) + 0x6000 + m_slot7_bank];
+ }
+
+ return 0xff;
+}
diff --git a/src/devices/bus/a2bus/laser128.h b/src/devices/bus/a2bus/laser128.h
index a71f88e0c3d..6685318c1fe 100644
--- a/src/devices/bus/a2bus/laser128.h
+++ b/src/devices/bus/a2bus/laser128.h
@@ -27,12 +27,15 @@ public:
// construction/destruction
a2bus_laser128_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
+ // special config API
+ void set_parallel_printer(bool bPrinterIsParallel) { m_bParPrinter = bPrinterIsParallel; }
+
protected:
a2bus_laser128_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 device_start() override ATTR_COLD;
+ virtual void device_reset() override ATTR_COLD;
+ virtual void device_add_mconfig(machine_config &config) override ATTR_COLD;
// overrides of standard a2bus slot functions
virtual uint8_t read_c0nx(uint8_t offset) override;
@@ -42,13 +45,26 @@ protected:
virtual void write_c800(uint16_t offset, uint8_t data) override;
virtual bool take_c800() override;
-private:
uint8_t *m_rom;
uint8_t m_slot7_ram[0x800];
- int m_slot7_bank, m_slot7_ram_bank;
+ int m_slot7_bank;
+ bool m_bParPrinter;
+
+private:
+ int m_slot7_ram_bank;
+};
+
+class a2bus_laser128_orig_device: public a2bus_laser128_device
+{
+public:
+ a2bus_laser128_orig_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
+
+protected:
+ virtual uint8_t read_c800(uint16_t offset) override;
};
// device type definition
DECLARE_DEVICE_TYPE(A2BUS_LASER128, a2bus_laser128_device)
+DECLARE_DEVICE_TYPE(A2BUS_LASER128_ORIG, a2bus_laser128_orig_device)
#endif // MAME_BUS_A2BUS_LASER128_H
diff --git a/src/devices/bus/a2bus/mouse.cpp b/src/devices/bus/a2bus/mouse.cpp
index 817cbd1fd85..9d8d889386e 100644
--- a/src/devices/bus/a2bus/mouse.cpp
+++ b/src/devices/bus/a2bus/mouse.cpp
@@ -40,8 +40,8 @@
Hookup notes:
- PIA port A connects to 68705 port A in its entirety (bi-directional)
- PIA PB4-PB7 connects to 68705 PC0-3 (bi-directional)
+ PIA port A connects to 68705 port A in its entirety (bi-directional with internal pullups)
+ PIA PB4-PB7 connects to 68705 PC0-3 (bi-directional but should not be pulled up)
PIA PB0 is 'sync latch'
PIA PB1 is A8 on the EPROM
PIA PB2 is A9 on the EPROM
@@ -66,6 +66,12 @@
#include "emu.h"
#include "mouse.h"
+#include "machine/6821pia.h"
+#include "cpu/m6805/m68705.h"
+
+
+namespace {
+
/***************************************************************************
CONSTANTS
***************************************************************************/
@@ -79,11 +85,60 @@
#define MOUSE_YAXIS_TAG "a2mse_y"
-/***************************************************************************
- GLOBAL VARIABLES
-***************************************************************************/
+//**************************************************************************
+// TYPE DEFINITIONS
+//**************************************************************************
+
+class a2bus_mouse_device:
+ public device_t,
+ public device_a2bus_card_interface
+{
+public:
+ // construction/destruction
+ a2bus_mouse_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
+
+protected:
+ a2bus_mouse_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 ATTR_COLD;
+ virtual void device_add_mconfig(machine_config &config) override ATTR_COLD;
+ virtual ioport_constructor device_input_ports() const override ATTR_COLD;
+ virtual void device_start() override ATTR_COLD;
+
+ // 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;
+
+private:
+ void pia_out_a(uint8_t data);
+ void pia_out_b(uint8_t data);
+ void pia_irqa_w(int state);
+ void pia_irqb_w(int state);
+
+ uint8_t mcu_port_a_r();
+ uint8_t mcu_port_b_r();
+ void mcu_port_a_w(uint8_t data);
+ void mcu_port_b_w(uint8_t data);
+ void mcu_port_c_w(uint8_t data);
+
+ template <unsigned AXIS, u8 DIR, u8 CLK> void update_axis();
+ void set_port_a_out(int32_t param);
+ void set_port_a_in(int32_t param);
+ void set_port_c_in(int32_t param);
+
+ required_device<pia6821_device> m_pia;
+ required_device<m68705p_device> m_mcu;
+ required_ioport m_mouseb;
+ required_ioport_array<2> m_mousexy;
+
+ required_region_ptr<uint8_t> m_rom;
+
+ uint16_t m_rom_bank;
+ uint8_t m_port_a_in, m_port_b_in;
+ int16_t m_last[2], m_count[2];
+};
-DEFINE_DEVICE_TYPE(A2BUS_MOUSE, a2bus_mouse_device, "a2mouse", "Apple II Mouse Card")
ROM_START( mouse )
ROM_REGION(0x800, MOUSE_ROM_REGION, 0)
@@ -97,7 +152,7 @@ ROM_START( mouse )
ROM_LOAD( "mmi_pal16r4a,binary.2a", 0x000000, 0x000100, CRC(1da5c745) SHA1(ba267b69a2fda2a2348b140979ece562411bb37b) )
ROM_END
-static INPUT_PORTS_START( mouse )
+INPUT_PORTS_START( mouse )
PORT_START(MOUSE_BUTTON_TAG) /* Mouse - button */
PORT_BIT( 0x01, IP_ACTIVE_HIGH, IPT_BUTTON1) PORT_NAME("Mouse Button") PORT_CODE(MOUSECODE_BUTTON1)
@@ -139,6 +194,7 @@ void a2bus_mouse_device::device_add_mconfig(machine_config &config)
PIA6821(config, m_pia, 1021800);
m_pia->writepa_handler().set(FUNC(a2bus_mouse_device::pia_out_a));
m_pia->writepb_handler().set(FUNC(a2bus_mouse_device::pia_out_b));
+ m_pia->tspb_handler().set_constant(0x00);
m_pia->irqa_handler().set(FUNC(a2bus_mouse_device::pia_irqa_w));
m_pia->irqb_handler().set(FUNC(a2bus_mouse_device::pia_irqb_w));
}
@@ -181,20 +237,16 @@ a2bus_mouse_device::a2bus_mouse_device(const machine_config &mconfig, const char
void a2bus_mouse_device::device_start()
{
+ m_last[0] = m_last[1] = m_count[0] = m_count[1] = 0;
+
// register save state variables
+ save_item(NAME(m_rom_bank));
save_item(NAME(m_port_a_in));
save_item(NAME(m_port_b_in));
save_item(NAME(m_last));
save_item(NAME(m_count));
- m_port_b_in = 0x00;
-}
-
-void a2bus_mouse_device::device_reset()
-{
- m_rom_bank = 0;
- m_last[0] = m_last[1] = m_count[0] = m_count[1] = 0;
- m_port_a_in = 0x00;
+ m_pia->cb1_w(1); // tied high via 10k resistor
}
/*-------------------------------------------------
@@ -221,40 +273,46 @@ void a2bus_mouse_device::write_c0nx(uint8_t offset, uint8_t data)
uint8_t a2bus_mouse_device::read_cnxx(uint8_t offset)
{
- return m_rom[offset+m_rom_bank];
+ return m_rom[offset | m_rom_bank];
}
-WRITE8_MEMBER(a2bus_mouse_device::pia_out_a)
+void a2bus_mouse_device::pia_out_a(uint8_t data)
{
- m_port_a_in = data;
+ machine().scheduler().synchronize(
+ timer_expired_delegate(FUNC(a2bus_mouse_device::set_port_a_in), this),
+ int32_t(uint32_t(data)));
}
-WRITE8_MEMBER(a2bus_mouse_device::pia_out_b)
+void a2bus_mouse_device::pia_out_b(uint8_t data)
{
- m_mcu->pc_w(space, 0, 0xf0 | ((data >> 4) & 0x0f));
+ machine().scheduler().synchronize(
+ timer_expired_delegate(FUNC(a2bus_mouse_device::set_port_c_in), this),
+ int32_t(uint32_t(data >> 4)));
- m_rom_bank = (data & 0xe) << 7;
+ m_rom_bank = uint16_t(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)
{
}
-READ8_MEMBER(a2bus_mouse_device::mcu_port_a_r)
+uint8_t a2bus_mouse_device::mcu_port_a_r()
{
return m_port_a_in;
}
-WRITE8_MEMBER(a2bus_mouse_device::mcu_port_a_w)
+void a2bus_mouse_device::mcu_port_a_w(uint8_t data)
{
- m_pia->set_a_input(data);
+ machine().scheduler().synchronize(
+ timer_expired_delegate(FUNC(a2bus_mouse_device::set_port_a_out), this),
+ int32_t(uint32_t(data)));
}
-READ8_MEMBER(a2bus_mouse_device::mcu_port_b_r)
+uint8_t a2bus_mouse_device::mcu_port_b_r()
{
enum { XAXIS, YAXIS };
constexpr u8 BUTTON = 0x80;
@@ -280,7 +338,7 @@ READ8_MEMBER(a2bus_mouse_device::mcu_port_b_r)
return m_port_b_in;
}
-WRITE8_MEMBER(a2bus_mouse_device::mcu_port_b_w)
+void a2bus_mouse_device::mcu_port_b_w(uint8_t data)
{
if (!BIT(data, 6))
{
@@ -292,24 +350,23 @@ WRITE8_MEMBER(a2bus_mouse_device::mcu_port_b_w)
}
}
-WRITE8_MEMBER(a2bus_mouse_device::mcu_port_c_w)
+void a2bus_mouse_device::mcu_port_c_w(uint8_t data)
{
- m_pia->write_portb(data << 4);
+ m_pia->portb_w(data << 4);
}
-template <unsigned AXIS, u8 DIR, u8 CLK> void a2bus_mouse_device::update_axis()
+template <unsigned AXIS, u8 DIR, u8 CLK>
+void a2bus_mouse_device::update_axis()
{
- // read the axis
+ // read the axis and check for changes
const int new_m = m_mousexy[AXIS]->read();
-
- // did it change?
int diff = new_m - m_last[AXIS];
// check for wrap
if (diff > 0x80)
- diff = 0x100 - diff;
- if (diff < -0x80)
- diff = -0x100 - diff;
+ diff -= 0x100;
+ else if (diff < -0x80)
+ diff += 0x100;
m_count[AXIS] += diff;
m_last[AXIS] = new_m;
@@ -329,3 +386,28 @@ template <unsigned AXIS, u8 DIR, u8 CLK> void a2bus_mouse_device::update_axis()
}
}
}
+
+void a2bus_mouse_device::set_port_a_out(int32_t param)
+{
+ m_pia->set_a_input(uint8_t(uint32_t(param)));
+}
+
+void a2bus_mouse_device::set_port_a_in(int32_t param)
+{
+ m_port_a_in = uint8_t(uint32_t(param));
+}
+
+void a2bus_mouse_device::set_port_c_in(int32_t param)
+{
+ const uint8_t data = uint8_t(uint32_t(param));
+ m_mcu->pc_w(data);
+}
+
+} // anonymous namespace
+
+
+/***************************************************************************
+ GLOBAL VARIABLES
+***************************************************************************/
+
+DEFINE_DEVICE_TYPE_PRIVATE(A2BUS_MOUSE, device_a2bus_card_interface, a2bus_mouse_device, "a2mouse", "Apple II Mouse Card")
diff --git a/src/devices/bus/a2bus/mouse.h b/src/devices/bus/a2bus/mouse.h
index 1afca2d948f..1f9669409ce 100644
--- a/src/devices/bus/a2bus/mouse.h
+++ b/src/devices/bus/a2bus/mouse.h
@@ -8,69 +8,13 @@
*********************************************************************/
-#ifndef MAME_DEVICES_A2BUS_MOUSE_H
-#define MAME_DEVICES_A2BUS_MOUSE_H
+#ifndef MAME_BUS_A2BUS_MOUSE_H
+#define MAME_BUS_A2BUS_MOUSE_H
#pragma once
#include "a2bus.h"
-#include "machine/6821pia.h"
-#include "cpu/m6805/m68705.h"
-//**************************************************************************
-// TYPE DEFINITIONS
-//**************************************************************************
+DECLARE_DEVICE_TYPE(A2BUS_MOUSE, device_a2bus_card_interface)
-class a2bus_mouse_device:
- public device_t,
- public device_a2bus_card_interface
-{
-public:
- // construction/destruction
- a2bus_mouse_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 ioport_constructor device_input_ports() const override;
-
-protected:
- a2bus_mouse_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_start() override;
- virtual void device_reset() 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;
-
- DECLARE_WRITE8_MEMBER(pia_out_a);
- DECLARE_WRITE8_MEMBER(pia_out_b);
- DECLARE_WRITE_LINE_MEMBER(pia_irqa_w);
- DECLARE_WRITE_LINE_MEMBER(pia_irqb_w);
-
- DECLARE_READ8_MEMBER(mcu_port_a_r);
- DECLARE_READ8_MEMBER(mcu_port_b_r);
- DECLARE_WRITE8_MEMBER(mcu_port_a_w);
- DECLARE_WRITE8_MEMBER(mcu_port_b_w);
- DECLARE_WRITE8_MEMBER(mcu_port_c_w);
-
- required_device<pia6821_device> m_pia;
- required_device<m68705p_device> m_mcu;
- required_ioport m_mouseb;
- required_ioport_array<2> m_mousexy;
-
-private:
- template <unsigned AXIS, u8 DIR, u8 CLK> void update_axis();
-
- required_region_ptr<uint8_t> m_rom;
- int m_rom_bank;
- uint8_t m_port_a_in, m_port_b_in;
- int m_last[2], m_count[2];
-};
-
-// device type definition
-DECLARE_DEVICE_TYPE(A2BUS_MOUSE, a2bus_mouse_device)
-
-#endif // MAME_DEVICES_A2BUS_MOUSE_H
+#endif // MAME_BUS_A2BUS_MOUSE_H
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..cc96ca704ea 100644
--- a/src/devices/bus/a2bus/nippelclock.h
+++ b/src/devices/bus/a2bus/nippelclock.h
@@ -8,8 +8,8 @@
*********************************************************************/
-#ifndef MAME_BUS_A2BUS_A2NIPPELCLOCK_H
-#define MAME_BUS_A2BUS_A2NIPPELCLOCK_H
+#ifndef MAME_BUS_A2BUS_NIPPELCLOCK_H
+#define MAME_BUS_A2BUS_NIPPELCLOCK_H
#pragma once
@@ -31,9 +31,9 @@ public:
protected:
a2bus_nippelclock_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 device_start() override ATTR_COLD;
+ virtual void device_reset() override ATTR_COLD;
+ virtual void device_add_mconfig(machine_config &config) override ATTR_COLD;
// overrides of standard a2bus slot functions
virtual uint8_t read_c0nx(uint8_t offset) override;
@@ -42,10 +42,10 @@ protected:
required_device<mc146818_device> m_rtc;
private:
- DECLARE_WRITE_LINE_MEMBER(irq_w);
+ void irq_w(int state);
};
// device type definition
DECLARE_DEVICE_TYPE(A2BUS_NIPPELCLOCK, a2bus_nippelclock_device)
-#endif // MAME_BUS_A2BUS_A2NIPPELCLOCK_H
+#endif // MAME_BUS_A2BUS_NIPPELCLOCK_H
diff --git a/src/devices/bus/a2bus/noisemaker.cpp b/src/devices/bus/a2bus/noisemaker.cpp
new file mode 100644
index 00000000000..e185b389753
--- /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 ATTR_COLD;
+ virtual void device_add_mconfig(machine_config &config) override ATTR_COLD;
+
+ // 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 305da9aa868..7f6856ebd67 100644
--- a/src/devices/bus/a2bus/pc_xporter.cpp
+++ b/src/devices/bus/a2bus/pc_xporter.cpp
@@ -79,17 +79,119 @@
#include "emu.h"
#include "pc_xporter.h"
+
+#include "bus/isa/isa.h"
+#include "bus/isa/isa_cards.h"
+#include "bus/pc_kbd/keyboards.h"
+#include "bus/pc_kbd/pc_kbdc.h"
+#include "cpu/nec/nec.h"
+#include "machine/am9517a.h"
+#include "machine/i8255.h"
+#include "machine/ins8250.h"
+#include "machine/pic8259.h"
+#include "machine/pit8253.h"
+#include "sound/spkrdev.h"
+
#include "speaker.h"
-/***************************************************************************
- PARAMETERS
-***************************************************************************/
+
+namespace {
//**************************************************************************
-// GLOBAL VARIABLES
+// TYPE DEFINITIONS
//**************************************************************************
-DEFINE_DEVICE_TYPE(A2BUS_PCXPORTER, a2bus_pcxporter_device, "a2pcxport", "Applied Engineering PC Transporter")
+class a2bus_pcxporter_device:
+ public device_t,
+ public device_a2bus_card_interface
+{
+public:
+ // construction/destruction
+ a2bus_pcxporter_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
+
+ [[maybe_unused]] uint16_t pc_bios_r(offs_t offset); // TODO: hook up to something?
+
+protected:
+ a2bus_pcxporter_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock);
+
+ 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;
+ virtual void device_resolve_objects() override ATTR_COLD;
+
+ // 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;
+ virtual void write_cnxx(uint8_t offset, uint8_t data) override;
+ virtual uint8_t read_c800(uint16_t offset) override;
+ virtual void write_c800(uint16_t offset, uint8_t data) override;
+
+private:
+ required_device<v30_device> m_v30;
+ required_device<pic8259_device> m_pic8259;
+ required_device<am9517a_device> m_dma8237;
+ required_device<pit8253_device> m_pit8253;
+ required_device<speaker_sound_device> m_speaker;
+ required_device<isa8_device> m_isabus;
+ optional_device<pc_kbdc_device> m_pc_kbdc;
+
+ uint8_t m_u73_q2;
+ uint8_t m_out1;
+ int m_dma_channel;
+ uint8_t m_dma_offset[4];
+ uint8_t m_pc_spkrdata;
+ uint8_t m_pit_out2;
+ bool m_cur_eop;
+
+ uint8_t m_nmi_enabled;
+
+ uint8_t m_ram[768*1024];
+ uint8_t m_c800_ram[0x400];
+ uint8_t m_regs[0x400];
+ uint32_t m_offset;
+ address_space *m_pcmem_space, *m_pcio_space;
+ bool m_reset_during_halt;
+
+ uint8_t m_6845_reg;
+
+ // interface to the keyboard
+ void keyboard_clock_w(int state);
+ void keyboard_data_w(int state);
+
+ void pc_pit8253_out1_changed(int state);
+ void pc_pit8253_out2_changed(int state);
+
+ 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();
+ uint8_t pc_dma8237_2_dack_r();
+ uint8_t pc_dma8237_3_dack_r();
+ void pc_dma8237_1_dack_w(uint8_t data);
+ 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);
+ 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]] 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]] void iochck_w(int state); // TODO: hook up to something?
+
+ void pc_select_dma_channel(int channel, bool state);
+
+ void pc_io(address_map &map) ATTR_COLD;
+ void pc_map(address_map &map) ATTR_COLD;
+};
void a2bus_pcxporter_device::pc_map(address_map &map)
{
@@ -117,21 +219,18 @@ void a2bus_pcxporter_device::pc_io(address_map &map)
void a2bus_pcxporter_device::device_add_mconfig(machine_config &config)
{
- V30(config, m_v30, A2BUS_7M_CLOCK); // 7.16 MHz as per manual
+ V30(config, m_v30, DERIVED_CLOCK(1, 1)); // 7.16 MHz as per manual
m_v30->set_addrmap(AS_PROGRAM, &a2bus_pcxporter_device::pc_map);
m_v30->set_addrmap(AS_IO, &a2bus_pcxporter_device::pc_io);
m_v30->set_irq_acknowledge_callback("pic8259", FUNC(pic8259_device::inta_cb));
m_v30->set_disable();
PIT8253(config, m_pit8253);
- m_pit8253->set_clk<0>(A2BUS_7M_CLOCK / 6.0); // heartbeat IRQ
m_pit8253->out_handler<0>().set(m_pic8259, FUNC(pic8259_device::ir0_w));
- m_pit8253->set_clk<1>(A2BUS_7M_CLOCK / 6.0); // DRAM refresh
m_pit8253->out_handler<1>().set(FUNC(a2bus_pcxporter_device::pc_pit8253_out1_changed));
- m_pit8253->set_clk<2>(A2BUS_7M_CLOCK / 6.0); // PIO port C pin 4, and speaker polling enough
m_pit8253->out_handler<2>().set(FUNC(a2bus_pcxporter_device::pc_pit8253_out2_changed));
- PCXPORT_DMAC(config, m_dma8237, A2BUS_7M_CLOCK / 2);
+ PCXPORT_DMAC(config, m_dma8237, DERIVED_CLOCK(1, 2));
m_dma8237->out_hreq_callback().set(FUNC(a2bus_pcxporter_device::pc_dma_hrq_changed));
m_dma8237->out_eop_callback().set(FUNC(a2bus_pcxporter_device::pc_dma8237_out_eop));
m_dma8237->in_memr_callback().set(FUNC(a2bus_pcxporter_device::pc_dma_read_byte));
@@ -164,10 +263,9 @@ void a2bus_pcxporter_device::device_add_mconfig(machine_config &config)
m_isabus->drq2_callback().set(m_dma8237, FUNC(am9517a_device::dreq2_w));
m_isabus->drq3_callback().set(m_dma8237, FUNC(am9517a_device::dreq3_w));
- PC_KBDC(config, m_pc_kbdc, 0);
+ PC_KBDC(config, m_pc_kbdc, pc_xt_keyboards, STR_KBD_KEYTRONIC_PC3270);
m_pc_kbdc->out_clock_cb().set(FUNC(a2bus_pcxporter_device::keyboard_clock_w));
m_pc_kbdc->out_data_cb().set(FUNC(a2bus_pcxporter_device::keyboard_data_w));
- PC_KBDC_SLOT(config, "kbd", pc_xt_keyboards, STR_KBD_KEYTRONIC_PC3270).set_pc_kbdc_slot(m_pc_kbdc);
/* sound hardware */
SPEAKER(config, "mono").front_center();
@@ -177,6 +275,14 @@ void a2bus_pcxporter_device::device_add_mconfig(machine_config &config)
ISA8_SLOT(config, "isa2", 0, m_isabus, pc_isa8_cards, "fdc_xt", true);
}
+void a2bus_pcxporter_device::device_resolve_objects()
+{
+ // DERIVED_CLOCK doesn't work for this case, so do this here instead
+ m_pit8253->set_clk<0>(clock() / 6.0); // heartbeat IRQ
+ m_pit8253->set_clk<1>(clock() / 6.0); // DRAM refresh
+ m_pit8253->set_clk<2>(clock() / 6.0); // PIO port C pin 4, and speaker polling enough
+}
+
//**************************************************************************
// LIVE DEVICE
//**************************************************************************
@@ -190,7 +296,7 @@ a2bus_pcxporter_device::a2bus_pcxporter_device(const machine_config &mconfig, de
m_pit8253(*this, "pit8253"),
m_speaker(*this, "speaker"),
m_isabus(*this, "isa"),
- m_pc_kbdc(*this, "pc_kbdc")
+ m_pc_kbdc(*this, "kbd")
{
}
@@ -442,17 +548,17 @@ void a2bus_pcxporter_device::write_c800(uint16_t offset, uint8_t data)
}
}
-READ16_MEMBER(a2bus_pcxporter_device::pc_bios_r)
+uint16_t a2bus_pcxporter_device::pc_bios_r(offs_t offset)
{
return m_ram[offset+0xa0000] | (m_ram[offset+0xa0001]<<8);
}
-READ8_MEMBER( a2bus_pcxporter_device::kbd_6502_r )
+uint8_t a2bus_pcxporter_device::kbd_6502_r(offs_t offset)
{
return m_c800_ram[offset+0x60];
}
-WRITE8_MEMBER( a2bus_pcxporter_device::kbd_6502_w )
+void a2bus_pcxporter_device::kbd_6502_w(offs_t offset, uint8_t data)
{
m_c800_ram[offset+0x60] = data;
}
@@ -463,7 +569,7 @@ WRITE8_MEMBER( a2bus_pcxporter_device::kbd_6502_w )
*
*************************************************************************/
-WRITE8_MEMBER( a2bus_pcxporter_device::pc_page_w)
+void a2bus_pcxporter_device::pc_page_w(offs_t offset, uint8_t data)
{
switch(offset % 4)
{
@@ -480,7 +586,7 @@ WRITE8_MEMBER( a2bus_pcxporter_device::pc_page_w)
}
-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);
@@ -489,7 +595,7 @@ WRITE_LINE_MEMBER( a2bus_pcxporter_device::pc_dma_hrq_changed )
}
-READ8_MEMBER( a2bus_pcxporter_device::pc_dma_read_byte )
+uint8_t a2bus_pcxporter_device::pc_dma_read_byte(offs_t offset)
{
if(m_dma_channel == -1)
return 0xff;
@@ -499,7 +605,7 @@ READ8_MEMBER( a2bus_pcxporter_device::pc_dma_read_byte )
}
-WRITE8_MEMBER( a2bus_pcxporter_device::pc_dma_write_byte )
+void a2bus_pcxporter_device::pc_dma_write_byte(offs_t offset, uint8_t data)
{
if(m_dma_channel == -1)
return;
@@ -510,48 +616,48 @@ WRITE8_MEMBER( a2bus_pcxporter_device::pc_dma_write_byte )
}
-READ8_MEMBER( a2bus_pcxporter_device::pc_dma8237_1_dack_r )
+uint8_t a2bus_pcxporter_device::pc_dma8237_1_dack_r()
{
return m_isabus->dack_r(1);
}
-READ8_MEMBER( a2bus_pcxporter_device::pc_dma8237_2_dack_r )
+uint8_t a2bus_pcxporter_device::pc_dma8237_2_dack_r()
{
return m_isabus->dack_r(2);
}
-READ8_MEMBER( a2bus_pcxporter_device::pc_dma8237_3_dack_r )
+uint8_t a2bus_pcxporter_device::pc_dma8237_3_dack_r()
{
return m_isabus->dack_r(3);
}
-WRITE8_MEMBER( a2bus_pcxporter_device::pc_dma8237_1_dack_w )
+void a2bus_pcxporter_device::pc_dma8237_1_dack_w(uint8_t data)
{
m_isabus->dack_w(1,data);
}
-WRITE8_MEMBER( a2bus_pcxporter_device::pc_dma8237_2_dack_w )
+void a2bus_pcxporter_device::pc_dma8237_2_dack_w(uint8_t data)
{
m_isabus->dack_w(2,data);
}
-WRITE8_MEMBER( a2bus_pcxporter_device::pc_dma8237_3_dack_w )
+void a2bus_pcxporter_device::pc_dma8237_3_dack_w(uint8_t data)
{
m_isabus->dack_w(3,data);
}
-WRITE8_MEMBER( a2bus_pcxporter_device::pc_dma8237_0_dack_w )
+void a2bus_pcxporter_device::pc_dma8237_0_dack_w(uint8_t data)
{
m_u73_q2 = 0;
m_dma8237->dreq0_w( m_u73_q2 );
}
-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)
@@ -572,10 +678,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); }
/*************************************************************
*
@@ -583,7 +689,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);
@@ -596,7 +702,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 )
@@ -608,19 +714,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)
{
}
@@ -630,15 +736,24 @@ WRITE_LINE_MEMBER( a2bus_pcxporter_device::keyboard_data_w )
*
**********************************************************/
-WRITE8_MEMBER( a2bus_pcxporter_device::nmi_enable_w )
+void a2bus_pcxporter_device::nmi_enable_w(uint8_t data)
{
m_nmi_enabled = BIT(data,7);
if (!m_nmi_enabled)
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);
}
+
+} // anonymous namespace
+
+
+//**************************************************************************
+// GLOBAL VARIABLES
+//**************************************************************************
+
+DEFINE_DEVICE_TYPE_PRIVATE(A2BUS_PCXPORTER, device_a2bus_card_interface, a2bus_pcxporter_device, "a2pcxport", "Applied Engineering PC Transporter")
diff --git a/src/devices/bus/a2bus/pc_xporter.h b/src/devices/bus/a2bus/pc_xporter.h
index 2a449ed4019..d765c4d1bb2 100644
--- a/src/devices/bus/a2bus/pc_xporter.h
+++ b/src/devices/bus/a2bus/pc_xporter.h
@@ -14,114 +14,8 @@
#pragma once
#include "a2bus.h"
-#include "cpu/nec/nec.h"
-#include "bus/pc_kbd/keyboards.h"
-#include "machine/ins8250.h"
-#include "machine/i8255.h"
-#include "machine/am9517a.h"
-#include "bus/isa/isa.h"
-#include "bus/isa/isa_cards.h"
-#include "bus/pc_kbd/pc_kbdc.h"
-#include "machine/pic8259.h"
-#include "machine/pit8253.h"
-#include "sound/spkrdev.h"
-//**************************************************************************
-// TYPE DEFINITIONS
-//**************************************************************************
-
-class a2bus_pcxporter_device:
- public device_t,
- public device_a2bus_card_interface
-{
-public:
- // construction/destruction
- a2bus_pcxporter_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
-
- DECLARE_READ16_MEMBER(pc_bios_r);
-
-protected:
- a2bus_pcxporter_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
- 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 void write_cnxx(uint8_t offset, uint8_t data) override;
- virtual uint8_t read_c800(uint16_t offset) override;
- virtual void write_c800(uint16_t offset, uint8_t data) override;
-
-private:
- required_device<v30_device> m_v30;
- required_device<pic8259_device> m_pic8259;
- required_device<am9517a_device> m_dma8237;
- required_device<pit8253_device> m_pit8253;
- required_device<speaker_sound_device> m_speaker;
- required_device<isa8_device> m_isabus;
- optional_device<pc_kbdc_device> m_pc_kbdc;
-
- uint8_t m_u73_q2;
- uint8_t m_out1;
- int m_dma_channel;
- uint8_t m_dma_offset[4];
- uint8_t m_pc_spkrdata;
- uint8_t m_pit_out2;
- bool m_cur_eop;
-
- uint8_t m_nmi_enabled;
-
- uint8_t m_ram[768*1024];
- uint8_t m_c800_ram[0x400];
- uint8_t m_regs[0x400];
- uint32_t m_offset;
- address_space *m_pcmem_space, *m_pcio_space;
- bool m_reset_during_halt;
-
- uint8_t m_6845_reg;
-
- // interface to the keyboard
- DECLARE_WRITE_LINE_MEMBER( keyboard_clock_w );
- DECLARE_WRITE_LINE_MEMBER( keyboard_data_w );
-
- DECLARE_WRITE_LINE_MEMBER( pc_pit8253_out1_changed );
- DECLARE_WRITE_LINE_MEMBER( pc_pit8253_out2_changed );
-
- DECLARE_WRITE_LINE_MEMBER( pc_dma_hrq_changed );
- DECLARE_WRITE_LINE_MEMBER( pc_dma8237_out_eop );
- DECLARE_READ8_MEMBER( pc_dma_read_byte );
- DECLARE_WRITE8_MEMBER( pc_dma_write_byte );
- DECLARE_READ8_MEMBER( pc_dma8237_1_dack_r );
- DECLARE_READ8_MEMBER( pc_dma8237_2_dack_r );
- DECLARE_READ8_MEMBER( pc_dma8237_3_dack_r );
- DECLARE_WRITE8_MEMBER( pc_dma8237_1_dack_w );
- DECLARE_WRITE8_MEMBER( pc_dma8237_2_dack_w );
- DECLARE_WRITE8_MEMBER( pc_dma8237_3_dack_w );
- DECLARE_WRITE8_MEMBER( pc_dma8237_0_dack_w );
- 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_READ8_MEMBER( kbd_6502_r );
- DECLARE_WRITE8_MEMBER( kbd_6502_w );
-
- DECLARE_WRITE_LINE_MEMBER( pc_speaker_set_spkrdata );
-
- DECLARE_WRITE8_MEMBER(pc_page_w);
- DECLARE_WRITE8_MEMBER(nmi_enable_w);
- DECLARE_WRITE_LINE_MEMBER(iochck_w);
-
- void pc_select_dma_channel(int channel, bool state);
-
- void pc_io(address_map &map);
- void pc_map(address_map &map);
-};
-
-// device type definition
-DECLARE_DEVICE_TYPE(A2BUS_PCXPORTER, a2bus_pcxporter_device)
+// device type declaration
+DECLARE_DEVICE_TYPE(A2BUS_PCXPORTER, device_a2bus_card_interface)
#endif // MAME_BUS_A2BUS_PC_XPORTER_H
diff --git a/src/devices/bus/a2bus/prodosromdrive.cpp b/src/devices/bus/a2bus/prodosromdrive.cpp
new file mode 100644
index 00000000000..381397163ce
--- /dev/null
+++ b/src/devices/bus/a2bus/prodosromdrive.cpp
@@ -0,0 +1,119 @@
+// license:BSD-3-Clause
+// copyright-holders:R. Belmont
+/*********************************************************************
+
+ prodosromdrive.cpp
+
+ Implementation of the ProDOS ROM Drive card
+
+ This is a hobbyist board which provides a minimal SmartPort API
+ interface to boot from a 1 MiB disk image stored in a 27C080 or
+ compatible EPROM.
+
+ Board and firmware by Terence J. Boldt
+ http://apple2.ca/
+ https://github.com/tjboldt/ProDOS-ROM-Drive
+
+ The firmware requires a IIe or better, and some of the games
+ included require a 65C02 (enhanced IIe).
+
+*********************************************************************/
+
+#include "emu.h"
+#include "prodosromdrive.h"
+
+namespace {
+
+//**************************************************************************
+// TYPE DEFINITIONS
+//**************************************************************************
+
+class a2bus_pdromdrive_device : public device_t,
+ public device_a2bus_card_interface
+{
+public:
+ // construction/destruction
+ a2bus_pdromdrive_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
+
+protected:
+ a2bus_pdromdrive_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock);
+
+ virtual void device_start() override ATTR_COLD;
+ virtual const tiny_rom_entry *device_rom_region() const override ATTR_COLD;
+
+ // 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;
+
+private:
+ required_region_ptr<u8> m_rom;
+
+ u16 m_latch;
+};
+
+//**************************************************************************
+// LIVE DEVICE
+//**************************************************************************
+
+a2bus_pdromdrive_device::a2bus_pdromdrive_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) :
+ a2bus_pdromdrive_device(mconfig, A2BUS_PRODOSROMDRIVE, tag, owner, clock)
+{
+}
+
+a2bus_pdromdrive_device::a2bus_pdromdrive_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(*this, "romdrive")
+{
+}
+
+void a2bus_pdromdrive_device::device_start()
+{
+ save_item(NAME(m_latch));
+}
+
+ROM_START( pdromdrive )
+ ROM_REGION(0x100000, "romdrive", 0)
+ ROM_LOAD( "gameswithfirmware.bin", 0x000000, 0x100000, CRC(a1efd23b) SHA1(f0733b7a68126adc5247a1008de2ea4f65ad645a) )
+ROM_END
+
+const tiny_rom_entry *a2bus_pdromdrive_device::device_rom_region() const
+{
+ return ROM_NAME(pdromdrive);
+}
+
+uint8_t a2bus_pdromdrive_device::read_c0nx(uint8_t offset)
+{
+ return m_rom[(m_latch << 4) | (offset & 0xf)];
+}
+
+void a2bus_pdromdrive_device::write_c0nx(uint8_t offset, uint8_t data)
+{
+ switch (offset)
+ {
+ case 0:
+ m_latch &= 0xff00;
+ m_latch |= data;
+ break;
+
+ case 1:
+ m_latch &= 0x00ff;
+ m_latch |= (data << 8);
+ break;
+ }
+}
+
+uint8_t a2bus_pdromdrive_device::read_cnxx(uint8_t offset)
+{
+ return m_rom[offset + 0x300];
+}
+
+} // anonymous namespace
+
+
+//**************************************************************************
+// GLOBAL VARIABLES
+//**************************************************************************
+
+DEFINE_DEVICE_TYPE_PRIVATE(A2BUS_PRODOSROMDRIVE, device_a2bus_card_interface, a2bus_pdromdrive_device, "a2pdromdr", "ProDOS ROM Drive")
diff --git a/src/devices/bus/a2bus/prodosromdrive.h b/src/devices/bus/a2bus/prodosromdrive.h
new file mode 100644
index 00000000000..d283053a39d
--- /dev/null
+++ b/src/devices/bus/a2bus/prodosromdrive.h
@@ -0,0 +1,21 @@
+// license:BSD-3-Clause
+// copyright-holders:R. Belmont
+/*********************************************************************
+
+ prodosromdrive.h
+
+ Implementation of the ProDOS ROM Drive card
+
+*********************************************************************/
+
+#ifndef MAME_BUS_A2BUS_PRODOSROMDRIVE_H
+#define MAME_BUS_A2BUS_PRODOSROMDRIVE_H
+
+#pragma once
+
+#include "a2bus.h"
+
+// device type definition
+DECLARE_DEVICE_TYPE(A2BUS_PRODOSROMDRIVE, device_a2bus_card_interface)
+
+#endif // MAME_BUS_A2BUS_PRODOSROMDRIVE_H
diff --git a/src/devices/bus/a2bus/q68.cpp b/src/devices/bus/a2bus/q68.cpp
new file mode 100644
index 00000000000..4729f450e4a
--- /dev/null
+++ b/src/devices/bus/a2bus/q68.cpp
@@ -0,0 +1,247 @@
+// license:BSD-3-Clause
+// copyright-holders:Rob Justice, R. Belmont
+/*********************************************************************
+
+ q68.cpp
+
+ Implementation of the Stellation Q-68 68008 card
+
+ Memory Map
+ 68008 0x00000-0x0ffff -> Apple II memory
+ 68008 0x10000-0x17fff -> Onboard EPROM, 8k (expandable to 32k)
+ 68008 0x18000-0x1ffff -> Onboard RAM, 8K (expandable to 32k?)
+ 68008 0x20000-0xfffff -> Open, for options via expansion connector
+
+ Apple II Memory
+ 68008 0x00000-0x003ff -> 6502 0x0800-0x0bff
+ 68008 0x00400-0x007ff -> 6502 0x0400-0x07ff
+ 68008 0x00800-0x00bff -> 6502 0x0000-0x03ff
+ 68008 0x00c00-0x0ffff -> 6502 0x0c00-0xffff
+
+ 0xc0n1 - Turn card on
+ 0xc0n3 - Interrupt card
+ 0xc0n0 - Turn card off
+
+ Also includes the Q-68 plus version made by nanja.info
+ This has a full 1MB of ram on board and slight update to the memory map
+ Memory Map
+ 68008 0x00000-0x0ffff -> Apple II memory
+ 68008 0x10000-0x11fff -> Onboard EPROM, 8k
+ 68008 0x12000-0x1ffff -> Onboard RAM, ~1MB
+
+ Todo:
+ Implement Watchdog timer. Only relevant to Q-68 and bus errors for nonexistent memory access
+ Speed of 6502 should be slower when 68008 is enabled and accessing AppleII memory space
+ Speed of 68008 should be slower when access the Apple II memory space
+
+ (reference: http://mirrors.apple2.org.za/ftp.apple.asimov.net/unsorted/QPAK-68%20Users%20Guide.pdf )
+
+*********************************************************************/
+
+#include "emu.h"
+#include "q68.h"
+
+#include "cpu/m68000/m68008.h"
+
+
+/***************************************************************************
+ PARAMETERS
+***************************************************************************/
+
+//**************************************************************************
+// GLOBAL VARIABLES
+//**************************************************************************
+
+DEFINE_DEVICE_TYPE(A2BUS_Q68, a2bus_q68_device, "a2q68", "Stellation Two Q-68")
+DEFINE_DEVICE_TYPE(A2BUS_Q68PLUS, a2bus_q68plus_device, "a2q68plus", "Stellation Two Q-68 Plus")
+
+void a2bus_q68_device::m68008_mem(address_map &map)
+{
+ map(0x00000, 0x0ffff).rw(FUNC(a2bus_q68_device::dma_r), FUNC(a2bus_q68_device::dma_w));
+ map(0x10000, 0x11fff).mirror(0x6000).rom(); // 8k debug rom
+ map(0x18000, 0x19fff).mirror(0x6000).ram(); // 8k of ram
+}
+
+void a2bus_q68plus_device::m68008_mem(address_map &map)
+{
+ map(0x00000, 0x0ffff).rw(FUNC(a2bus_q68plus_device::dma_r), FUNC(a2bus_q68plus_device::dma_w));
+ map(0x10000, 0x11fff).rom(); // 8k debug rom
+ map(0x12000, 0xfffff).ram(); // 1 MB of RAM
+}
+
+ROM_START( q68 )
+ ROM_REGION(0x100000, "m68008", 0)
+ ROM_LOAD( "debug1.04-caf4.bin", 0x10000, 0x02000, CRC(6bead126) SHA1(e46d5e8256faece3723e9040f78fd1c8edb3ee0e) )
+ROM_END
+
+/***************************************************************************
+ FUNCTION PROTOTYPES
+***************************************************************************/
+
+//-------------------------------------------------
+// device_add_mconfig - add device configuration
+//-------------------------------------------------
+
+void a2bus_q68_device::device_add_mconfig(machine_config &config)
+{
+ M68008(config, m_m68008, 1021800*7); // M68008 runs at 7.16 MHz
+ m_m68008->set_addrmap(AS_PROGRAM, &a2bus_q68_device::m68008_mem);
+}
+
+void a2bus_q68plus_device::device_add_mconfig(machine_config &config)
+{
+ M68008(config, m_m68008, 1021800*7); // M68008 runs at 7.16 MHz
+ m_m68008->set_addrmap(AS_PROGRAM, &a2bus_q68plus_device::m68008_mem);
+}
+
+//-------------------------------------------------
+// device_rom_region - device-specific ROMs
+//-------------------------------------------------
+
+const tiny_rom_entry *a2bus_68k_device::device_rom_region() const
+{
+ return ROM_NAME( q68 );
+}
+
+//**************************************************************************
+// LIVE DEVICE
+//**************************************************************************
+
+a2bus_68k_device::a2bus_68k_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_m68008(*this, "m68008")
+ , m_bEnabled(false)
+{
+}
+
+a2bus_q68_device::a2bus_q68_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) :
+ a2bus_68k_device(mconfig, A2BUS_Q68, tag, owner, clock)
+{
+}
+
+a2bus_q68plus_device::a2bus_q68plus_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) :
+ a2bus_68k_device(mconfig, A2BUS_Q68PLUS, tag, owner, clock)
+{
+}
+
+//-------------------------------------------------
+// device_start - device-specific startup
+//-------------------------------------------------
+
+void a2bus_68k_device::device_start()
+{
+ save_item(NAME(m_bEnabled));
+}
+
+void a2bus_68k_device::device_reset()
+{
+ m_m68008->set_input_line(INPUT_LINE_RESET, ASSERT_LINE);
+ m_m68008->set_input_line(INPUT_LINE_HALT, ASSERT_LINE);
+ m_bEnabled=false;
+}
+
+uint8_t a2bus_68k_device::read_c0nx(uint8_t offset)
+{
+ switch (offset & 0x3)
+ {
+ case 0:
+ case 2:
+ m_m68008->set_input_line(INPUT_LINE_RESET, ASSERT_LINE);
+ m_m68008->set_input_line(INPUT_LINE_HALT, ASSERT_LINE);
+ m_bEnabled=false;
+ break;
+
+ case 1:
+ m_m68008->set_input_line(INPUT_LINE_RESET, CLEAR_LINE);
+ m_m68008->set_input_line(INPUT_LINE_HALT, CLEAR_LINE);
+ m_bEnabled=true;
+ break;
+
+ case 3:
+ m_m68008->set_input_line(INPUT_LINE_RESET, CLEAR_LINE);
+ m_m68008->set_input_line(INPUT_LINE_HALT, CLEAR_LINE);
+ m_bEnabled=true;
+ m_m68008->pulse_input_line(M68K_IRQ_7, attotime::zero); //work around, processor status lines + logic should clear nmi.
+ break;
+ }
+ return 0;
+}
+
+void a2bus_68k_device::write_c0nx(uint8_t offset, uint8_t data)
+{
+ switch (offset & 0x3)
+ {
+ case 0:
+ case 2:
+ m_m68008->set_input_line(INPUT_LINE_RESET, ASSERT_LINE);
+ m_m68008->set_input_line(INPUT_LINE_HALT, ASSERT_LINE);
+ m_bEnabled=false;
+ break;
+
+ case 1:
+ m_m68008->set_input_line(INPUT_LINE_RESET, CLEAR_LINE);
+ m_m68008->set_input_line(INPUT_LINE_HALT, CLEAR_LINE);
+ m_bEnabled=true;
+ break;
+
+ case 3:
+ m_m68008->set_input_line(INPUT_LINE_RESET, CLEAR_LINE);
+ m_m68008->set_input_line(INPUT_LINE_HALT, CLEAR_LINE);
+ m_bEnabled=true;
+ m_m68008->pulse_input_line(M68K_IRQ_7, attotime::zero); //work around, processor status lines should clear nmi.
+ break;
+ }
+}
+
+uint8_t a2bus_68k_device::dma_r(offs_t offset)
+{
+ if (m_bEnabled)
+ {
+ if (offset <= 0x03ff) //0x0000-0x03ff
+ {
+ return slot_dma_read(offset+0x800);
+ }
+ else if (offset <= 0x07ff) //0x0400-0x07ff
+ {
+ return slot_dma_read(offset);
+ }
+ else if (offset <= 0x0bff) //0x0800-0x0bff
+ {
+ return slot_dma_read(offset-0x800);
+ }
+ else if (offset <= 0xffff) //0x0c00-0xffff
+ {
+ return slot_dma_read(offset);
+ }
+ }
+ return 0xff;
+}
+
+
+//-------------------------------------------------
+// dma_w -
+//-------------------------------------------------
+
+void a2bus_68k_device::dma_w(offs_t offset, uint8_t data)
+{
+ if (m_bEnabled)
+ {
+ if (offset <= 0x03ff) //0x0000-0x03ff
+ {
+ return slot_dma_write(offset+0x800, data);
+ }
+ else if (offset <= 0x07ff) //0x0400-0x07ff
+ {
+ return slot_dma_write(offset, data);
+ }
+ else if (offset <= 0x0bff) //0x0800-0x0bff
+ {
+ return slot_dma_write(offset-0x800, data);
+ }
+ else if (offset <= 0xffff) //0x0c00-0xffff
+ {
+ return slot_dma_write(offset, data);
+ }
+ }
+}
diff --git a/src/devices/bus/a2bus/q68.h b/src/devices/bus/a2bus/q68.h
new file mode 100644
index 00000000000..652437b0491
--- /dev/null
+++ b/src/devices/bus/a2bus/q68.h
@@ -0,0 +1,82 @@
+// license:BSD-3-Clause
+// copyright-holders:Rob Justice, R. Belmont
+/*********************************************************************
+
+ q68.h
+
+ Implementation of the Stellation Q-68 68008 card
+
+*********************************************************************/
+
+#ifndef MAME_BUS_A2BUS_Q68_H
+#define MAME_BUS_A2BUS_Q68_H
+
+#pragma once
+
+#include "a2bus.h"
+
+
+//**************************************************************************
+// DEVICE TYPE DECLARATION
+//**************************************************************************
+
+DECLARE_DEVICE_TYPE(A2BUS_Q68, a2bus_q68_device)
+DECLARE_DEVICE_TYPE(A2BUS_Q68PLUS, a2bus_q68plus_device)
+
+
+//**************************************************************************
+// TYPE DEFINITIONS
+//**************************************************************************
+
+class a2bus_68k_device:
+ public device_t,
+ public device_a2bus_card_interface
+{
+protected:
+ a2bus_68k_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock);
+
+ virtual void device_start() override ATTR_COLD;
+ virtual void device_reset() override ATTR_COLD;
+ virtual const tiny_rom_entry *device_rom_region() const override ATTR_COLD;
+
+ // 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 bool take_c800() override { return false; }
+
+ uint8_t dma_r(offs_t offset);
+ void dma_w(offs_t offset, uint8_t data);
+
+ required_device<cpu_device> m_m68008;
+
+private:
+ bool m_bEnabled;
+};
+
+class a2bus_q68_device : public a2bus_68k_device
+{
+public:
+ a2bus_q68_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
+
+protected:
+ virtual void device_add_mconfig(machine_config &config) override ATTR_COLD;
+
+private:
+ void m68008_mem(address_map &map) ATTR_COLD;
+};
+
+class a2bus_q68plus_device : public a2bus_68k_device
+{
+public:
+ a2bus_q68plus_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
+
+ static auto parent_rom_device_type() { return &A2BUS_Q68; }
+
+protected:
+ virtual void device_add_mconfig(machine_config &config) override ATTR_COLD;
+
+private:
+ void m68008_mem(address_map &map) ATTR_COLD;
+};
+
+#endif // MAME_BUS_A2BUS_Q68_H
diff --git a/src/devices/bus/a2bus/ramcard128k.h b/src/devices/bus/a2bus/ramcard128k.h
index ee3ac683514..e85a0539613 100644
--- a/src/devices/bus/a2bus/ramcard128k.h
+++ b/src/devices/bus/a2bus/ramcard128k.h
@@ -30,8 +30,8 @@ public:
protected:
a2bus_ssramcard_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_start() override ATTR_COLD;
+ virtual void device_reset() override ATTR_COLD;
// overrides of standard a2bus slot functions
virtual uint8_t read_c0nx(uint8_t offset) override;
diff --git a/src/devices/bus/a2bus/ramcard16k.h b/src/devices/bus/a2bus/ramcard16k.h
index 21edcd7a7fd..6a759f2633a 100644
--- a/src/devices/bus/a2bus/ramcard16k.h
+++ b/src/devices/bus/a2bus/ramcard16k.h
@@ -30,8 +30,8 @@ public:
protected:
a2bus_ramcard_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_start() override ATTR_COLD;
+ virtual void device_reset() override ATTR_COLD;
// overrides of standard a2bus slot functions
virtual uint8_t read_c0nx(uint8_t offset) override;
diff --git a/src/devices/bus/a2bus/romcard.cpp b/src/devices/bus/a2bus/romcard.cpp
new file mode 100644
index 00000000000..db50f847357
--- /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 ATTR_COLD;
+ virtual void bus_reset() override;
+ virtual ioport_constructor device_input_ports() const override ATTR_COLD;
+
+ // 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 ATTR_COLD;
+
+protected:
+ virtual const tiny_rom_entry *device_rom_region() const override ATTR_COLD;
+};
+
+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 ATTR_COLD;
+
+protected:
+ virtual const tiny_rom_entry *device_rom_region() const override ATTR_COLD;
+};
+
+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/sider.cpp b/src/devices/bus/a2bus/sider.cpp
new file mode 100644
index 00000000000..d2722c8bb77
--- /dev/null
+++ b/src/devices/bus/a2bus/sider.cpp
@@ -0,0 +1,296 @@
+// license:BSD-3-Clause
+// copyright-holders:R. Belmont
+/*********************************************************************
+
+ sider.cpp
+
+ Implementation of the First Class Peripherals / Advanced Tech Services / Xebec Sider cards
+
+ Sider 1: based on Xebec SASI hardware, with Xebec firmware. Requires HDD with 256 byte sectors
+ and special formatting - not compatible with standard .po/.hdv type images.
+
+ Sider 2: Same hardware, new firmware that's fully ProDOS compliant including 512 byte sectors.
+ Sectors are interleaved: the first byte is the byte that would be at 0, the second byte is the byte that would be at $100,
+ the third is the byte at $1, the fourth at $101, and so on. So this is also not compatible with standard images.
+
+ This command-line program will convert a standard image to work with Sider 2. First parameter is the input filename,
+ second parameter is the output filename. No error checking is done, if the input file doesn't exist it'll probably crash.
+
+ #include <stdio.h>
+ #include <stdlib.h>
+ #include <string.h>
+
+ static char block[512];
+ static char blockout[512];
+
+ int main(int argc, char *argv[])
+ {
+ FILE *in, *out;
+
+ in = fopen(argv[1], "rb");
+ out = fopen(argv[2], "wb");
+
+ int len = 0;
+ fseek(in, 0, SEEK_END);
+ len = ftell(in);
+ fseek(in, 0, SEEK_SET);
+
+ for (int bnum = 0; bnum < (len / 512); bnum++)
+ {
+ fread(block, 512, 1, in);
+ for (int byte = 0; byte < 256; byte++)
+ {
+ blockout[byte*2] = block[byte];
+ blockout[(byte*2)+1] = block[byte+256];
+ }
+ fwrite(blockout, 512, 1, out);
+ printf("block %d\n", bnum);
+ }
+
+ fclose(out);
+ fclose(in);
+ return 0;
+ }
+
+ --------------------------------------
+
+ $C0(n+8)X space:
+ $0: read state / write latch
+ $1: read data / write control
+
+ State:
+ b3: /Busy
+ b4: /Message
+ b5: I/O
+ b6: C/D
+ b7: REQ
+
+ Control:
+ b4: drive contents of output latch onto the SASI bus (reverse logic; latch is driven when this bit is clear)
+ b5: reset bus
+ b6: /BSY
+ b7: /SEL
+
+*********************************************************************/
+
+#include "emu.h"
+#include "sider.h"
+#include "bus/scsi/scsihd.h"
+#include "bus/scsi/s1410.h"
+
+/***************************************************************************
+ PARAMETERS
+***************************************************************************/
+
+//**************************************************************************
+// GLOBAL VARIABLES
+//**************************************************************************
+
+DEFINE_DEVICE_TYPE(A2BUS_SIDER2, a2bus_sider2card_device, "a2sider2", "First Class Peripherals Sider 2 SASI Card")
+DEFINE_DEVICE_TYPE(A2BUS_SIDER1, a2bus_sider1card_device, "a2sider1", "First Class Peripherals Sider 1 SASI Card")
+
+#define SASI_ROM_REGION "sasi_rom"
+
+ROM_START( sider2 )
+ ROM_REGION(0x800, SASI_ROM_REGION, 0)
+ ROM_LOAD( "atsv22_a02a9baad2262a8a49ecea843f602124.bin", 0x000000, 0x000800, CRC(97773a0b) SHA1(8d0a5d6ce3b9a236771126033c4aba6c0cc5e704) )
+ROM_END
+
+ROM_START( sider1 )
+ ROM_REGION(0x800, SASI_ROM_REGION, 0)
+ ROM_LOAD( "xebec-103684c-1986.bin", 0x000000, 0x000800, CRC(9e62e15f) SHA1(7f50b5e00cac4960204f50448a6e2d623b1a41e2) )
+ROM_END
+
+/***************************************************************************
+ FUNCTION PROTOTYPES
+***************************************************************************/
+
+//-------------------------------------------------
+// device_add_mconfig - add device configuration
+//-------------------------------------------------
+
+void a2bus_sider_device::device_add_mconfig(machine_config &config)
+{
+ NSCSI_BUS(config, m_sasibus);
+ NSCSI_CONNECTOR(config, "sasibus:0", default_scsi_devices, "s1410", false);
+ NSCSI_CONNECTOR(config, "sasibus:1", default_scsi_devices, nullptr, false);
+ NSCSI_CONNECTOR(config, "sasibus:2", default_scsi_devices, nullptr, false);
+ NSCSI_CONNECTOR(config, "sasibus:3", default_scsi_devices, nullptr, false);
+ NSCSI_CONNECTOR(config, "sasibus:4", default_scsi_devices, nullptr, false);
+ NSCSI_CONNECTOR(config, "sasibus:5", default_scsi_devices, nullptr, false);
+ NSCSI_CONNECTOR(config, "sasibus:6", default_scsi_devices, nullptr, false);
+ NSCSI_CONNECTOR(config, "sasibus:7", default_scsi_devices, "scsicb", true).option_add_internal("scsicb", NSCSI_CB);
+}
+
+//-------------------------------------------------
+// rom_region - device-specific ROM region
+//-------------------------------------------------
+
+const tiny_rom_entry *a2bus_sider2card_device::device_rom_region() const
+{
+ return ROM_NAME( sider2 );
+}
+
+const tiny_rom_entry *a2bus_sider1card_device::device_rom_region() const
+{
+ return ROM_NAME( sider1 );
+}
+
+//**************************************************************************
+// LIVE DEVICE
+//**************************************************************************
+
+a2bus_sider_device::a2bus_sider_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_sasibus(*this, "sasibus"),
+ m_sasi(*this, "sasibus:7:scsicb"),
+ m_rom(*this, SASI_ROM_REGION),
+ m_latch(0xff),
+ m_control(0)
+{
+}
+
+a2bus_sider2card_device::a2bus_sider2card_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) :
+ a2bus_sider_device(mconfig, A2BUS_SIDER2, tag, owner, clock)
+{
+}
+
+a2bus_sider1card_device::a2bus_sider1card_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) :
+ a2bus_sider_device(mconfig, A2BUS_SIDER1, tag, owner, clock)
+{
+}
+
+//-------------------------------------------------
+// device_start - device-specific startup
+//-------------------------------------------------
+
+void a2bus_sider_device::device_start()
+{
+ save_item(NAME(m_latch));
+ save_item(NAME(m_control));
+}
+
+void a2bus_sider_device::device_reset()
+{
+ m_latch = 0xff;
+ m_control = 0;
+}
+
+/*-------------------------------------------------
+ read_c0nx - called for reads from this card's c0nx space
+-------------------------------------------------*/
+
+uint8_t a2bus_sider_device::read_c0nx(uint8_t offset)
+{
+ u8 rv = 0;
+
+ switch (offset)
+ {
+ case 0:
+ // b3: /Busy
+ // b4: /Message
+ // b5: I/O
+ // b6: C/D
+ // b7: REQ
+ rv |= m_sasi->req_r() ? 0x80 : 0;
+ rv |= m_sasi->cd_r() ? 0x40 : 0;
+ rv |= m_sasi->io_r() ? 0x20 : 0;
+ rv |= m_sasi->msg_r() ? 0x10 : 0;
+ rv |= m_sasi->bsy_r() ? 0x08 : 0;
+ return rv;
+
+ case 1:
+ rv = m_sasi->read();
+ if ((m_sasi->req_r()) && (m_sasi->io_r()))
+ {
+ m_sasi->ack_w(1);
+ m_sasi->ack_w(0);
+ }
+ return rv;
+
+ default:
+ logerror("Read c0n%x (%s)\n", offset, machine().describe_context().c_str());
+ break;
+ }
+
+ return 0xff;
+}
+
+
+/*-------------------------------------------------
+ write_c0nx - called for writes to this card's c0nx space
+-------------------------------------------------*/
+
+void a2bus_sider_device::write_c0nx(uint8_t offset, uint8_t data)
+{
+ switch (offset)
+ {
+ case 0:
+ m_latch = data;
+ if (!(m_control & 0x10))
+ {
+ m_sasi->write(m_latch);
+
+ if (m_sasi->req_r())
+ {
+ m_sasi->ack_w(1);
+ m_sasi->write(0); // stop driving the data lines
+ m_sasi->ack_w(0);
+ }
+ }
+ break;
+
+ case 1:
+// b4: drive contents of output latch onto the SASI bus
+// b5: reset bus
+// b6: /BSY
+// b7: /SEL (error in note on A2DP's schematic; BSY and SEL are the same polarity from the 6502's POV)
+ m_control = data;
+ m_sasi->sel_w((data & 0x80) ? 1 : 0);
+ m_sasi->bsy_w((data & 0x40) ? 1 : 0);
+ if (data & 0x20)
+ {
+ m_sasibus->reset();
+ }
+ else if (!(data & 0x10))
+ {
+ m_sasi->write(m_latch);
+ }
+ break;
+
+ default:
+ logerror("Write %02x to c0n%x (%s)\n", data, offset, machine().describe_context().c_str());
+ break;
+ }
+}
+
+/*-------------------------------------------------
+ read_cnxx - called for reads from this card's cnxx space
+-------------------------------------------------*/
+
+uint8_t a2bus_sider_device::read_cnxx(uint8_t offset)
+{
+ // slot images at $700
+ return m_rom[offset + 0x700];
+}
+
+void a2bus_sider_device::write_cnxx(uint8_t offset, uint8_t data)
+{
+}
+
+/*-------------------------------------------------
+ read_c800 - called for reads from this card's c800 space
+-------------------------------------------------*/
+
+uint8_t a2bus_sider_device::read_c800(uint16_t offset)
+{
+ return m_rom[offset];
+}
+
+/*-------------------------------------------------
+ write_c800 - called for writes to this card's c800 space
+-------------------------------------------------*/
+void a2bus_sider_device::write_c800(uint16_t offset, uint8_t data)
+{
+}
diff --git a/src/devices/bus/a2bus/sider.h b/src/devices/bus/a2bus/sider.h
new file mode 100644
index 00000000000..580cded17b2
--- /dev/null
+++ b/src/devices/bus/a2bus/sider.h
@@ -0,0 +1,71 @@
+// license:BSD-3-Clause
+// copyright-holders:R. Belmont
+/*********************************************************************
+
+ sider.h
+
+ Implementation of the First Class Peripherals / Advanced Tech Services / Xebec Sider SASI Card
+
+*********************************************************************/
+
+#ifndef MAME_BUS_A2BUS_SIDER_H
+#define MAME_BUS_A2BUS_SIDER_H
+
+#pragma once
+
+#include "a2bus.h"
+#include "bus/nscsi/devices.h"
+#include "machine/nscsi_bus.h"
+#include "machine/nscsi_cb.h"
+
+//**************************************************************************
+// TYPE DEFINITIONS
+//**************************************************************************
+
+class a2bus_sider_device:
+ public device_t,
+ public device_a2bus_card_interface
+{
+protected:
+ a2bus_sider_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock);
+
+ 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;
+
+ // 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;
+ virtual void write_cnxx(uint8_t offset, uint8_t data) override;
+ virtual uint8_t read_c800(uint16_t offset) override;
+ virtual void write_c800(uint16_t offset, uint8_t data) override;
+
+ required_device<nscsi_bus_device> m_sasibus;
+ required_device<nscsi_callback_device> m_sasi;
+ required_region_ptr<u8> m_rom;
+
+private:
+ u8 m_latch;
+ u8 m_control;
+};
+
+class a2bus_sider2card_device: public a2bus_sider_device
+{
+public:
+ a2bus_sider2card_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
+ virtual const tiny_rom_entry *device_rom_region() const override ATTR_COLD;
+};
+
+class a2bus_sider1card_device: public a2bus_sider_device
+{
+public:
+ a2bus_sider1card_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
+ virtual const tiny_rom_entry *device_rom_region() const override ATTR_COLD;
+};
+
+// device type definition
+DECLARE_DEVICE_TYPE(A2BUS_SIDER2, a2bus_sider2card_device)
+DECLARE_DEVICE_TYPE(A2BUS_SIDER1, a2bus_sider1card_device)
+
+#endif // MAME_BUS_A2BUS_SIDER_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/softcard3.cpp b/src/devices/bus/a2bus/softcard3.cpp
new file mode 100644
index 00000000000..fb3da1eb291
--- /dev/null
+++ b/src/devices/bus/a2bus/softcard3.cpp
@@ -0,0 +1,226 @@
+// license:BSD-3-Clause
+// copyright-holders:Rob Justice, R. Belmont
+/*********************************************************************
+
+ softcard3.cpp
+
+ Implementation of the Microsoft SoftCard /// Z-80 card
+
+ Best guess at the moment based on disassembly of the boot disk
+ and some manual checks with the real hardware
+
+*********************************************************************/
+
+#include "emu.h"
+#include "softcard3.h"
+#include "cpu/z80/z80.h"
+
+/***************************************************************************
+ PARAMETERS
+***************************************************************************/
+
+//**************************************************************************
+// GLOBAL VARIABLES
+//**************************************************************************
+
+DEFINE_DEVICE_TYPE(A2BUS_SOFTCARD3, a2bus_softcard3_device, "softcard3", "Microsoft SoftCard ///")
+
+void a2bus_softcard3_device::z80_mem(address_map &map)
+{
+ map(0x0000, 0xffff).rw(FUNC(a2bus_softcard3_device::dma_r), FUNC(a2bus_softcard3_device::dma_w));
+}
+
+ROM_START( softcard3 )
+ ROM_REGION(0x100, "mapping_prom", 0)
+ ROM_LOAD("softcard3.rom", 0x0000, 0x0100, CRC(9d4433b2) SHA1(aff45dd8850641b4616b61750c104e7ee45a99a4))
+ROM_END
+
+void a2bus_softcard3_device::z80_io(address_map &map)
+{
+ map(0x00, 0x00).w(FUNC(a2bus_softcard3_device::z80_io_w));
+}
+
+/***************************************************************************
+ FUNCTION PROTOTYPES
+***************************************************************************/
+
+//-------------------------------------------------
+// device_add_mconfig - add device configuration
+//-------------------------------------------------
+
+void a2bus_softcard3_device::device_add_mconfig(machine_config &config)
+{
+ Z80(config, m_z80, 1021800*2); // Z80 runs at 2M based on comment in the manual
+ m_z80->set_addrmap(AS_PROGRAM, &a2bus_softcard3_device::z80_mem);
+ m_z80->set_addrmap(AS_IO, &a2bus_softcard3_device::z80_io);
+ TIMER(config, "timer").configure_generic(FUNC(a2bus_softcard3_device::timercallback));
+}
+
+//**************************************************************************
+// LIVE DEVICE
+//**************************************************************************
+
+a2bus_softcard3_device::a2bus_softcard3_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_z80(*this, "z80"),
+ m_prom(*this, "mapping_prom"),
+ m_timer(*this, "timer"),
+ m_bEnabled(false),
+ m_reset(false),
+ m_enable_fffx(false)
+{
+}
+
+a2bus_softcard3_device::a2bus_softcard3_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) :
+ a2bus_softcard3_device(mconfig, A2BUS_SOFTCARD3, tag, owner, clock)
+{
+}
+
+const tiny_rom_entry *a2bus_softcard3_device::device_rom_region() const
+{
+ return ROM_NAME(softcard3);
+}
+
+//-------------------------------------------------
+// device_start - device-specific startup
+//-------------------------------------------------
+
+void a2bus_softcard3_device::device_start()
+{
+ save_item(NAME(m_bEnabled));
+ save_item(NAME(m_reset));
+ save_item(NAME(m_enable_fffx));
+}
+
+void a2bus_softcard3_device::device_reset()
+{
+ m_bEnabled = false;
+ m_reset = false;
+ m_enable_fffx = false;
+ m_z80->set_input_line(INPUT_LINE_HALT, ASSERT_LINE);
+ m_timer->adjust(attotime::never);
+}
+
+uint8_t a2bus_softcard3_device::read_c0nx(uint8_t offset)
+{
+ return 0x50; //software is looking for 0x50, needs to be checked if this can return other flags
+}
+
+void a2bus_softcard3_device::write_c0nx(uint8_t offset, uint8_t data)
+{
+ switch (data)
+ {
+ case 0x01: // reset
+ m_reset = true; // flag we need a reset when we enable the Z80
+ break;
+
+ case 0x10: // enable the card fffc & fffd memory mapped address to appear
+ m_enable_fffx = true;
+ break;
+
+ default:
+ //printf("Softcard3: %02x to unhandled c0n%x\n", data, offset);
+ break;
+ }
+}
+
+// read to fffc halts 6502 and enables z80
+uint8_t a2bus_softcard3_device::read_inh_rom(uint16_t offset)
+{
+ if (offset == 0xfffc)
+ {
+ m_bEnabled = true;
+ raise_slot_dma();
+ m_z80->set_input_line(INPUT_LINE_HALT, CLEAR_LINE);
+ if (m_reset)
+ {
+ m_z80->reset();
+ }
+ m_timer->adjust(attotime::from_hz(5.0)); //start supervision timer
+ //printf("timer start\n");
+ }
+
+ if (offset == 0xfffd)
+ {
+ m_timer->adjust(attotime::never); //disable supervision timer
+ //printf("disable timer\n");
+ }
+
+ return 0xff;
+}
+
+// returns if we want to /INH a read or write to a specific address
+bool a2bus_softcard3_device::inh_check(u16 offset, bool bIsWrite)
+{
+ if (!m_enable_fffx)
+ {
+ return false;
+ }
+
+ if (!(bIsWrite) && (offset == 0xfffc)) //only a read to fffc is mapped in
+ {
+ return true;
+ }
+
+ if (!(bIsWrite) && (offset == 0xfffd)) //only a read to fffd is mapped in
+ {
+ return true;
+ }
+
+ return false;
+}
+
+// this io write halts the z80 and returns to the 6502
+void a2bus_softcard3_device::z80_io_w(offs_t offset, uint8_t data)
+{
+ m_z80->set_input_line(INPUT_LINE_HALT, ASSERT_LINE);
+ lower_slot_dma();
+ m_bEnabled = false;
+ m_enable_fffx = false;
+ m_reset = false;
+ m_timer->adjust(attotime::never);
+ //printf("z80 io timer stop\n");
+}
+
+// fires if Z80 has not handed back to the 6502 in this timer period
+// this ensures 6502 can run and service console i/o
+// actual time to be checked on real hw
+TIMER_DEVICE_CALLBACK_MEMBER(a2bus_softcard3_device::timercallback)
+{
+ m_z80->set_input_line(INPUT_LINE_HALT, ASSERT_LINE);
+ lower_slot_dma();
+ m_bEnabled = false;
+ m_enable_fffx = false;
+ m_reset = false;
+ //printf("timer callback stop\n");
+}
+
+//memory mapping based on a dump of the mapping rom 256x8
+//maps the top 8 address lines
+uint8_t a2bus_softcard3_device::dma_r(offs_t offset)
+{
+ if (m_bEnabled)
+ {
+ return slot_dma_read((offset & 0xff) + (m_prom[offset >> 8] << 8));
+ }
+
+ return 0xff;
+}
+
+//-------------------------------------------------
+// dma_w -
+//-------------------------------------------------
+
+void a2bus_softcard3_device::dma_w(offs_t offset, uint8_t data)
+{
+ if (m_bEnabled)
+ {
+ slot_dma_write((offset & 0xff) + (m_prom[offset >> 8] << 8), data);
+ }
+}
+
+bool a2bus_softcard3_device::take_c800()
+{
+ return false;
+}
diff --git a/src/devices/bus/a2bus/softcard3.h b/src/devices/bus/a2bus/softcard3.h
new file mode 100644
index 00000000000..d6a3157355b
--- /dev/null
+++ b/src/devices/bus/a2bus/softcard3.h
@@ -0,0 +1,66 @@
+// license:BSD-3-Clause
+// copyright-holders:Rob Justice, R. Belmont
+/*********************************************************************
+
+ softcard3.h
+
+ Implementation of the Microsoft SoftCard /// Z-80 card
+
+*********************************************************************/
+
+#ifndef MAME_BUS_A2BUS_SOFTCARD3_H
+#define MAME_BUS_A2BUS_SOFTCARD3_H
+
+#include "a2bus.h"
+#include "machine/timer.h"
+
+//**************************************************************************
+// TYPE DEFINITIONS
+//**************************************************************************
+
+class a2bus_softcard3_device:
+ public device_t,
+ public device_a2bus_card_interface
+{
+public:
+
+ // construction/destruction
+ a2bus_softcard3_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
+
+ void z80_io_w(offs_t offset, uint8_t data);
+
+protected:
+ a2bus_softcard3_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock);
+
+ 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;
+ virtual const tiny_rom_entry *device_rom_region() const override ATTR_COLD;
+
+ // 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 bool take_c800() override;
+ virtual u8 read_inh_rom(u16 offset) override;
+ virtual bool inh_check(uint16_t offset, bool bIsWrite) override;
+ TIMER_DEVICE_CALLBACK_MEMBER(timercallback);
+
+private:
+ required_device<cpu_device> m_z80;
+ required_region_ptr<u8> m_prom;
+ required_device<timer_device> m_timer;
+ bool m_bEnabled;
+ bool m_reset;
+ bool m_enable_fffx;
+
+ uint8_t dma_r(offs_t offset);
+ void dma_w(offs_t offset, uint8_t data);
+
+ void z80_io(address_map &map) ATTR_COLD;
+ void z80_mem(address_map &map) ATTR_COLD;
+};
+
+// device type definition
+DECLARE_DEVICE_TYPE(A2BUS_SOFTCARD3, a2bus_softcard3_device)
+
+#endif // MAME_BUS_A2BUS_SOFTCARD3_H
diff --git a/src/devices/bus/a2bus/ssbapple.cpp b/src/devices/bus/a2bus/ssbapple.cpp
index 89165617867..513bcb07611 100644
--- a/src/devices/bus/a2bus/ssbapple.cpp
+++ b/src/devices/bus/a2bus/ssbapple.cpp
@@ -11,20 +11,47 @@
#include "emu.h"
#include "ssbapple.h"
+
#include "sound/tms5220.h"
+
#include "speaker.h"
+
+namespace {
+
/***************************************************************************
PARAMETERS
***************************************************************************/
+#define TMS_TAG "tms5220"
+
//**************************************************************************
-// GLOBAL VARIABLES
+// TYPE DEFINITIONS
//**************************************************************************
-DEFINE_DEVICE_TYPE(A2BUS_SSBAPPLE, a2bus_ssb_device, "a2ssbapl", "Multitech Industrial SSB Apple speech card")
+class a2bus_ssb_device:
+ public device_t,
+ public device_a2bus_card_interface
+{
+public:
+ // construction/destruction
+ a2bus_ssb_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
+ static constexpr feature_type imperfect_features() { return feature::SOUND; }
-#define TMS_TAG "tms5220"
+ required_device<tms5220_device> m_tms;
+
+protected:
+ a2bus_ssb_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock);
+
+ 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;
+
+ // overrides of standard a2bus slot functions
+ virtual uint8_t read_cnxx(uint8_t offset) override;
+ virtual void write_cnxx(uint8_t offset, uint8_t data) override;
+ virtual bool take_c800() override;
+};
/***************************************************************************
FUNCTION PROTOTYPES
@@ -85,3 +112,12 @@ void a2bus_ssb_device::write_cnxx(uint8_t offset, uint8_t data)
{
m_tms->data_w(data);
}
+
+} // anonymous namespace
+
+
+//**************************************************************************
+// GLOBAL VARIABLES
+//**************************************************************************
+
+DEFINE_DEVICE_TYPE_PRIVATE(A2BUS_SSBAPPLE, device_a2bus_card_interface, a2bus_ssb_device, "a2ssbapl", "Multitech Industrial SSB Apple speech card")
diff --git a/src/devices/bus/a2bus/ssbapple.h b/src/devices/bus/a2bus/ssbapple.h
index def0db3c9d4..82559a7e5dd 100644
--- a/src/devices/bus/a2bus/ssbapple.h
+++ b/src/devices/bus/a2bus/ssbapple.h
@@ -14,37 +14,8 @@
#pragma once
#include "a2bus.h"
-#include "sound/tms5220.h"
-
-//**************************************************************************
-// TYPE DEFINITIONS
-//**************************************************************************
-
-class a2bus_ssb_device:
- public device_t,
- public device_a2bus_card_interface
-{
-public:
- // construction/destruction
- a2bus_ssb_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
- static constexpr feature_type imperfect_features() { return feature::SOUND; }
-
- required_device<tms5220_device> m_tms;
-
-protected:
- a2bus_ssb_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
- virtual uint8_t read_cnxx(uint8_t offset) override;
- virtual void write_cnxx(uint8_t offset, uint8_t data) override;
- virtual bool take_c800() override;
-};
-
-// device type definition
-DECLARE_DEVICE_TYPE(A2BUS_SSBAPPLE, a2bus_ssb_device)
+
+// device type declaration
+DECLARE_DEVICE_TYPE(A2BUS_SSBAPPLE, device_a2bus_card_interface)
#endif // MAME_BUS_A2BUS_A2SSBAPPLE_H
diff --git a/src/devices/bus/a2bus/ssprite.cpp b/src/devices/bus/a2bus/ssprite.cpp
index 69e12dc98dd..ec34845acd8 100644
--- a/src/devices/bus/a2bus/ssprite.cpp
+++ b/src/devices/bus/a2bus/ssprite.cpp
@@ -10,10 +10,16 @@
#include "emu.h"
#include "ssprite.h"
+
+#include "sound/ay8910.h"
#include "sound/tms5220.h"
+#include "video/tms9928a.h"
+
#include "speaker.h"
+namespace {
+
/***************************************************************************
PARAMETERS
***************************************************************************/
@@ -24,10 +30,35 @@
#define SCREEN_TAG "screen"
//**************************************************************************
-// GLOBAL VARIABLES
+// TYPE DEFINITIONS
//**************************************************************************
-DEFINE_DEVICE_TYPE(A2BUS_SSPRITE, a2bus_ssprite_device, "a2ssprite", "Synetix SuperSprite")
+class a2bus_ssprite_device:
+ public device_t,
+ public device_a2bus_card_interface
+{
+public:
+ // construction/destruction
+ a2bus_ssprite_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
+
+protected:
+ a2bus_ssprite_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock);
+
+ 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;
+
+ // 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;
+
+private:
+ void tms_irq_w(int state);
+
+ required_device<tms9918a_device> m_tms;
+ required_device<ay8910_device> m_ay;
+ required_device<tms5220_device> m_tms5220;
+};
//-------------------------------------------------
// device_add_mconfig - add device configuration
@@ -134,10 +165,19 @@ 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();
else
lower_slot_irq();
}
+
+} // anonymous namespace
+
+
+//**************************************************************************
+// GLOBAL VARIABLES
+//**************************************************************************
+
+DEFINE_DEVICE_TYPE_PRIVATE(A2BUS_SSPRITE, device_a2bus_card_interface, a2bus_ssprite_device, "a2ssprite", "Synetix SuperSprite")
diff --git a/src/devices/bus/a2bus/ssprite.h b/src/devices/bus/a2bus/ssprite.h
index 590e172445c..cb6be184299 100644
--- a/src/devices/bus/a2bus/ssprite.h
+++ b/src/devices/bus/a2bus/ssprite.h
@@ -9,48 +9,14 @@
*********************************************************************/
-#ifndef MAME_BUS_A2BUS_A2SSPRITE_H
-#define MAME_BUS_A2BUS_A2SSPRITE_H
+#ifndef MAME_BUS_A2BUS_SSPRITE_H
+#define MAME_BUS_A2BUS_SSPRITE_H
#pragma once
#include "a2bus.h"
-#include "video/tms9928a.h"
-#include "sound/ay8910.h"
-#include "sound/tms5220.h"
-
-//**************************************************************************
-// TYPE DEFINITIONS
-//**************************************************************************
-
-class a2bus_ssprite_device:
- public device_t,
- public device_a2bus_card_interface
-{
-public:
- // construction/destruction
- a2bus_ssprite_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
-
-protected:
- a2bus_ssprite_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
- virtual uint8_t read_c0nx(uint8_t offset) override;
- virtual void write_c0nx(uint8_t offset, uint8_t data) override;
-
-private:
- DECLARE_WRITE_LINE_MEMBER( tms_irq_w );
-
- required_device<tms9918a_device> m_tms;
- required_device<ay8910_device> m_ay;
- required_device<tms5220_device> m_tms5220;
-};
// device type definition
-DECLARE_DEVICE_TYPE(A2BUS_SSPRITE, a2bus_ssprite_device)
+DECLARE_DEVICE_TYPE(A2BUS_SSPRITE, device_a2bus_card_interface)
-#endif // MAME_BUS_A2BUS_SSPRITE_H
+#endif // MAME_BUS_A2BUS_SSPRITE_H
diff --git a/src/devices/bus/a2bus/suprterminal.cpp b/src/devices/bus/a2bus/suprterminal.cpp
new file mode 100644
index 00000000000..7f29899d0ec
--- /dev/null
+++ b/src/devices/bus/a2bus/suprterminal.cpp
@@ -0,0 +1,281 @@
+// license:BSD-3-Clause
+// copyright-holders:R. Belmont
+/*********************************************************************
+
+ suprterminal.cpp
+ M&R Enterprises SUP'R'TERMINAL 80-column card.
+
+ This card only works in Slot 3. The firmware will crash in any other slot.
+ Emulation tested and works with DOS 3.3, ProDOS, and CP/M.
+
+ $C0B2: Select VRAM at $C800 and disable ROM at $C800
+ $C0B4: Select font RAM at $C800 and disable ROM at $C800
+ $C0B6: Select bank 2 of (VRAM? font RAM?). This is unused on this card,
+ and there are not enough DRAMs (or places for them!) to make it work.
+ $C0B8: 6845 address
+ $C0B9: 6845 data
+
+ The $C800 handling on this card is unusual.
+ Disabling the card's $C800 space by accessing $CFFF resets the card to ROM
+ at $C800. Enabling either VRAM or font RAM at $C800 disables ROM until
+ $CFFF is accessed.
+
+*********************************************************************/
+
+#include "emu.h"
+#include "suprterminal.h"
+
+#include "video/mc6845.h"
+
+#include "screen.h"
+
+
+namespace {
+
+ROM_START(a2suprterm)
+ ROM_REGION(0x800, "s3firmware", ROMREGION_ERASEFF)
+ ROM_LOAD("suprterminal.bin", 0x000000, 0x000800, CRC(4c49b0f5) SHA1(66a7411c46c04a8089a7ddfb5ffd9809dd08a21f))
+ROM_END
+
+//**************************************************************************
+// TYPE DEFINITIONS
+//**************************************************************************
+
+class a2bus_suprterminal_device:
+ public device_t,
+ public device_a2bus_card_interface
+{
+public:
+ // construction/destruction
+ a2bus_suprterminal_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock);
+
+protected:
+ a2bus_suprterminal_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, u32 clock);
+
+ 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;
+ virtual const tiny_rom_entry *device_rom_region() const override ATTR_COLD;
+
+ // overrides of standard a2bus slot functions
+ virtual u8 read_cnxx(u8 offset) override;
+ virtual u8 read_c0nx(u8 offset) override;
+ virtual void write_c0nx(u8 offset, u8 data) override;
+ virtual u8 read_c800(u16 offset) override;
+ virtual void write_c800(u16 offset, u8 data) override;
+ virtual bool take_c800() override { return true; }
+
+private:
+ required_device<mc6845_device> m_crtc;
+ required_region_ptr<u8> m_rom;
+
+ MC6845_UPDATE_ROW(crtc_update_row);
+
+ std::unique_ptr<u8[]> m_vram;
+ std::unique_ptr<u8[]> m_fontram;
+// u8 m_fontram[0x400];
+ bool m_bRasterRAM, m_bCharBank1, m_bC800IsRAM;
+
+ void access_c0nx(u8 offset);
+};
+
+//-------------------------------------------------
+// device_add_mconfig - add device configuration
+//-------------------------------------------------
+
+void a2bus_suprterminal_device::device_add_mconfig(machine_config &config)
+{
+ screen_device &screen(SCREEN(config, "screen", SCREEN_TYPE_RASTER));
+ screen.set_raw(17.43_MHz_XTAL, 1116, 0, 720, 260, 0, 216);
+ screen.set_screen_update("crtc", FUNC(mc6845_device::screen_update));
+
+ HD6845S(config, m_crtc, 17.43_MHz_XTAL / 9);
+ m_crtc->set_screen("screen");
+ m_crtc->set_show_border_area(false);
+ m_crtc->set_char_width(9);
+ m_crtc->set_update_row_callback(FUNC(a2bus_suprterminal_device::crtc_update_row));
+}
+
+const tiny_rom_entry *a2bus_suprterminal_device::device_rom_region() const
+{
+ return ROM_NAME(a2suprterm);
+}
+
+//**************************************************************************
+// LIVE DEVICE
+//**************************************************************************
+
+a2bus_suprterminal_device::a2bus_suprterminal_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock) :
+ a2bus_suprterminal_device(mconfig, A2BUS_SUPRTERMINAL, tag, owner, clock)
+{
+}
+
+a2bus_suprterminal_device::a2bus_suprterminal_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, u32 clock) :
+ device_t(mconfig, type, tag, owner, clock),
+ device_a2bus_card_interface(mconfig, *this),
+ m_crtc(*this, "crtc"),
+ m_rom(*this, "s3firmware")
+{
+}
+
+//-------------------------------------------------
+// device_start - device-specific startup
+//-------------------------------------------------
+
+void a2bus_suprterminal_device::device_start()
+{
+ m_vram = std::make_unique<u8[]>(0x800); // 4 2114 DRAMs
+ m_fontram = std::make_unique<u8[]>(0x400); // 2 2114 DRAMs
+
+ m_bC800IsRAM = false;
+ m_bRasterRAM = true;
+ m_bCharBank1 = false;
+
+ save_item(NAME(m_bRasterRAM));
+ save_item(NAME(m_bCharBank1));
+ save_item(NAME(m_bC800IsRAM));
+ save_pointer(NAME(m_vram), 0x800);
+ save_pointer(NAME(m_fontram), 0x400);
+}
+
+void a2bus_suprterminal_device::device_reset()
+{
+}
+
+u8 a2bus_suprterminal_device::read_cnxx(u8 offset)
+{
+ return m_rom[offset+0x300];
+}
+
+void a2bus_suprterminal_device::access_c0nx(u8 offset)
+{
+ switch (offset)
+ {
+ case 2:
+ m_bRasterRAM = true;
+ m_bC800IsRAM = true;
+ break;
+
+ case 4:
+ m_bRasterRAM = false;
+ m_bC800IsRAM = true;
+ break;
+
+ case 6:
+ m_bCharBank1 ^= 1;
+ break;
+ }
+}
+
+u8 a2bus_suprterminal_device::read_c0nx(u8 offset)
+{
+ if (offset < 8)
+ {
+ if (!machine().side_effects_disabled())
+ {
+ access_c0nx(offset);
+ }
+ }
+ else if (offset == 9)
+ {
+ return m_crtc->register_r();
+ }
+
+ return 0xff;
+}
+
+void a2bus_suprterminal_device::write_c0nx(u8 offset, u8 data)
+{
+ if (offset < 8)
+ {
+ access_c0nx(offset);
+ }
+ else if (offset == 8)
+ {
+ m_crtc->address_w(data);
+ }
+ else if (offset == 9)
+ {
+ m_crtc->register_w(data);
+ }
+}
+
+u8 a2bus_suprterminal_device::read_c800(u16 offset)
+{
+ if (!machine().side_effects_disabled())
+ {
+ if (offset == 0x7ff)
+ {
+ m_bC800IsRAM = false;
+ }
+ }
+
+ if (m_bC800IsRAM)
+ {
+ if (!m_bRasterRAM)
+ {
+ return m_vram[offset];
+ }
+ else
+ {
+ return m_fontram[offset&0x3ff];
+ }
+ }
+
+ return m_rom[offset];
+}
+
+/*-------------------------------------------------
+ write_c800 - called for writes to this card's c800 space
+-------------------------------------------------*/
+void a2bus_suprterminal_device::write_c800(u16 offset, u8 data)
+{
+ if (offset == 0x7ff)
+ {
+ m_bC800IsRAM = false;
+ }
+
+ if (!m_bRasterRAM)
+ {
+ m_vram[offset] = data;
+ }
+ else
+ {
+ m_fontram[offset&0x3ff] = data;
+ }
+}
+
+MC6845_UPDATE_ROW(a2bus_suprterminal_device::crtc_update_row)
+{
+ u32 *p = &bitmap.pix(y);
+ u16 chr_base = ra;
+
+ for (int i = 0; i < x_count; i++)
+ {
+ u16 offset = (ma + i) & 0x7ff;
+ u8 chr = m_vram[offset] & 0x7f;
+ u8 data = m_fontram[chr_base + chr * 8];
+ rgb_t fg = rgb_t::white();
+ rgb_t bg = rgb_t::black();
+
+ if (i == cursor_x)
+ {
+ std::swap(fg, bg);
+ }
+
+ for (int j = 9; j > 0; j--)
+ {
+ *p++ = BIT(data, 7) ? fg : bg;
+ data <<= 1;
+ }
+ }
+}
+
+} // anonymous namespace
+
+
+//**************************************************************************
+// GLOBAL VARIABLES
+//**************************************************************************
+
+DEFINE_DEVICE_TYPE_PRIVATE(A2BUS_SUPRTERMINAL, device_a2bus_card_interface, a2bus_suprterminal_device, "a2suprterm", "M&R Enterprises SUP'R'TERMINAL")
diff --git a/src/devices/bus/a2bus/suprterminal.h b/src/devices/bus/a2bus/suprterminal.h
new file mode 100644
index 00000000000..3bc754c5d24
--- /dev/null
+++ b/src/devices/bus/a2bus/suprterminal.h
@@ -0,0 +1,21 @@
+// license:BSD-3-Clause
+// copyright-holders:R. Belmont
+/*********************************************************************
+
+ suprterminal.h
+
+ M&R Enterprises SUP'R'TERMINAL 80-column card
+
+*********************************************************************/
+
+#ifndef MAME_BUS_A2BUS_SUPRTERMINAL_H
+#define MAME_BUS_A2BUS_SUPRTERMINAL_H
+
+#pragma once
+
+#include "a2bus.h"
+
+// device type declaration
+DECLARE_DEVICE_TYPE(A2BUS_SUPRTERMINAL, device_a2bus_card_interface)
+
+#endif // MAME_BUS_A2BUS_SUPRTERMINAL_H
diff --git a/src/devices/bus/a2bus/timemasterho.cpp b/src/devices/bus/a2bus/timemasterho.cpp
index 6b7f0b1f5eb..0bb341f143c 100644
--- a/src/devices/bus/a2bus/timemasterho.cpp
+++ b/src/devices/bus/a2bus/timemasterho.cpp
@@ -38,16 +38,16 @@
#include "emu.h"
#include "timemasterho.h"
+#include "machine/6821pia.h"
+#include "machine/msm5832.h"
+
+
+namespace {
+
/***************************************************************************
PARAMETERS
***************************************************************************/
-//**************************************************************************
-// GLOBAL VARIABLES
-//**************************************************************************
-
-DEFINE_DEVICE_TYPE(A2BUS_TIMEMASTERHO, a2bus_timemasterho_device, "a2tmstho", "Applied Engineering TimeMaster H.O.")
-
#define TIMEMASTER_ROM_REGION "timemst_rom"
#define TIMEMASTER_PIA_TAG "timemst_pia"
#define TIMEMASTER_M5832_TAG "timemst_msm"
@@ -76,6 +76,49 @@ static INPUT_PORTS_START( tmho )
PORT_DIPSETTING( 0x08, DEF_STR(On))
INPUT_PORTS_END
+//**************************************************************************
+// TYPE DEFINITIONS
+//**************************************************************************
+
+class a2bus_timemasterho_device:
+ public device_t,
+ public device_a2bus_card_interface
+{
+public:
+ // construction/destruction
+ a2bus_timemasterho_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
+
+protected:
+ a2bus_timemasterho_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock);
+
+ 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;
+ virtual const tiny_rom_entry *device_rom_region() const override ATTR_COLD;
+ virtual ioport_constructor device_input_ports() const override ATTR_COLD;
+
+ // 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;
+ virtual uint8_t read_c800(uint16_t offset) override;
+
+ required_device<pia6821_device> m_pia;
+ required_device<msm5832_device> m_msm5832;
+ required_region_ptr<uint8_t> m_rom;
+ required_ioport m_dsw1;
+
+private:
+ void update_irqs();
+ void pia_out_a(uint8_t data);
+ void pia_out_b(uint8_t data);
+ void pia_irqa_w(int state);
+ void pia_irqb_w(int state);
+
+ bool m_irqa = false, m_irqb = false;
+ bool m_started = false;
+};
+
/***************************************************************************
FUNCTION PROTOTYPES
***************************************************************************/
@@ -122,15 +165,14 @@ a2bus_timemasterho_device::a2bus_timemasterho_device(const machine_config &mconf
device_a2bus_card_interface(mconfig, *this),
m_pia(*this, TIMEMASTER_PIA_TAG),
m_msm5832(*this, TIMEMASTER_M5832_TAG),
- m_dsw1(*this, "DSW1"), m_rom(nullptr), m_irqa(false), m_irqb(false)
+ m_rom(*this, TIMEMASTER_ROM_REGION),
+ m_dsw1(*this, "DSW1")
{
- m_started = false;
}
a2bus_timemasterho_device::a2bus_timemasterho_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) :
a2bus_timemasterho_device(mconfig, A2BUS_TIMEMASTERHO, tag, owner, clock)
{
- m_started = false;
}
//-------------------------------------------------
@@ -139,7 +181,6 @@ a2bus_timemasterho_device::a2bus_timemasterho_device(const machine_config &mconf
void a2bus_timemasterho_device::device_start()
{
- m_rom = device().machine().root_device().memregion(this->subtag(TIMEMASTER_ROM_REGION).c_str())->base();
}
void a2bus_timemasterho_device::device_reset()
@@ -203,12 +244,12 @@ uint8_t a2bus_timemasterho_device::read_c800(uint16_t offset)
return m_rom[offset+0xc00];
}
-WRITE8_MEMBER(a2bus_timemasterho_device::pia_out_a)
+void a2bus_timemasterho_device::pia_out_a(uint8_t data)
{
// port A appears to be input only
}
-WRITE8_MEMBER(a2bus_timemasterho_device::pia_out_b)
+void a2bus_timemasterho_device::pia_out_b(uint8_t data)
{
m_msm5832->address_w(data & 0xf);
m_msm5832->hold_w((data>>4) & 1 ? ASSERT_LINE : CLEAR_LINE);
@@ -225,7 +266,7 @@ WRITE8_MEMBER(a2bus_timemasterho_device::pia_out_b)
// if it's a read, poke it into the PIA
if ((data>>5) & 1)
{
- m_pia->write_porta(m_msm5832->data_r(space, 0));
+ m_pia->porta_w(m_msm5832->data_r());
}
}
@@ -256,14 +297,23 @@ 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();
}
+
+} // anonymous namespace
+
+
+//**************************************************************************
+// GLOBAL VARIABLES
+//**************************************************************************
+
+DEFINE_DEVICE_TYPE_PRIVATE(A2BUS_TIMEMASTERHO, device_a2bus_card_interface, a2bus_timemasterho_device, "a2tmstho", "Applied Engineering TimeMaster H.O.")
diff --git a/src/devices/bus/a2bus/timemasterho.h b/src/devices/bus/a2bus/timemasterho.h
index fcc71d6194f..f7bda98ce43 100644
--- a/src/devices/bus/a2bus/timemasterho.h
+++ b/src/devices/bus/a2bus/timemasterho.h
@@ -14,53 +14,8 @@
#pragma once
#include "a2bus.h"
-#include "machine/6821pia.h"
-#include "machine/msm5832.h"
-//**************************************************************************
-// TYPE DEFINITIONS
-//**************************************************************************
-
-class a2bus_timemasterho_device:
- public device_t,
- public device_a2bus_card_interface
-{
-public:
- // construction/destruction
- a2bus_timemasterho_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
-
-protected:
- a2bus_timemasterho_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 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_cnxx(uint8_t offset) override;
- virtual uint8_t read_c800(uint16_t offset) override;
-
- required_device<pia6821_device> m_pia;
- required_device<msm5832_device> m_msm5832;
- required_ioport m_dsw1;
-
-private:
- void update_irqs();
- DECLARE_WRITE8_MEMBER(pia_out_a);
- DECLARE_WRITE8_MEMBER(pia_out_b);
- DECLARE_WRITE_LINE_MEMBER(pia_irqa_w);
- DECLARE_WRITE_LINE_MEMBER(pia_irqb_w);
-
- uint8_t *m_rom;
- bool m_irqa, m_irqb;
- bool m_started;
-};
-
-// device type definition
-DECLARE_DEVICE_TYPE(A2BUS_TIMEMASTERHO, a2bus_timemasterho_device)
+// device type declaration
+DECLARE_DEVICE_TYPE(A2BUS_TIMEMASTERHO, device_a2bus_card_interface)
#endif // MAME_BUS_A2BUS_TIMEMASTERHO_H
diff --git a/src/devices/bus/a2bus/titan3plus2.cpp b/src/devices/bus/a2bus/titan3plus2.cpp
new file mode 100644
index 00000000000..e04dc03448a
--- /dev/null
+++ b/src/devices/bus/a2bus/titan3plus2.cpp
@@ -0,0 +1,334 @@
+// license:BSD-3-Clause
+// copyright-holders:R. Belmont
+/*********************************************************************
+
+ titan3plus3.cpp
+
+ Implemention of the Titan "/// Plus //"" card.
+ By R. Belmont, based on reverse-engineering by Rob Justice.
+
+ This extends the Apple ///'s II emulation to include a 128K
+ extended language card and Apple II compatible game I/O.
+
+ The card enables itself if the /// is at 1 MHz and accesses the
+ card's $CNxx ROM space. If the /// goes back to 2 MHz mode at
+ any time, the card disables itself.
+
+ Address ranges this messes with:
+ $C05X - passed through to ///, but also used for annunciators on A2 gameio
+ $C06X - /// doesn't see when card enabled, A2 paddles
+ $C07X - passed through to ///, but also used for A2 paddle reset
+ $C08X - unused by /// (language card control)
+ $D000-$FFFF: usual (for A2) language card space. Not so usual for ///.
+
+*********************************************************************/
+
+#include "emu.h"
+#include "titan3plus2.h"
+
+/***************************************************************************
+ PARAMETERS
+***************************************************************************/
+
+//**************************************************************************
+// GLOBAL VARIABLES
+//**************************************************************************
+
+DEFINE_DEVICE_TYPE(A2BUS_TITAN3PLUS2, a2bus_titan3plus2_device, "titan3p2", "Titan /// Plus //")
+
+/***************************************************************************
+ FUNCTION PROTOTYPES
+***************************************************************************/
+
+//**************************************************************************
+// LIVE DEVICE
+//**************************************************************************
+
+void a2bus_titan3plus2_device::device_add_mconfig(machine_config &config)
+{
+ APPLE2_GAMEIO(config, m_gameio, apple2_gameio_device::default_options, nullptr);
+}
+
+a2bus_titan3plus2_device::a2bus_titan3plus2_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_gameio(*this, "gameio"),
+ m_inh_state(0), m_last_offset(0), m_dxxx_bank(0), m_main_bank(0), m_enabled(false)
+{
+}
+
+a2bus_titan3plus2_device::a2bus_titan3plus2_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) :
+ a2bus_titan3plus2_device(mconfig, A2BUS_TITAN3PLUS2, tag, owner, clock)
+{
+}
+
+//-------------------------------------------------
+// device_start - device-specific startup
+//-------------------------------------------------
+
+void a2bus_titan3plus2_device::device_start()
+{
+ memset(m_ram, 0, 128*1024);
+
+ save_item(NAME(m_inh_state));
+ save_item(NAME(m_ram));
+ save_item(NAME(m_dxxx_bank));
+ save_item(NAME(m_main_bank));
+ save_item(NAME(m_last_offset));
+ save_item(NAME(m_enabled));
+
+ m_x_calibration = m_y_calibration = attotime::from_nsec(10800).as_double();
+}
+
+void a2bus_titan3plus2_device::device_reset()
+{
+ m_inh_state = INH_NONE;
+ m_dxxx_bank = 0;
+ m_main_bank = 0;
+ m_last_offset = -1;
+}
+
+void a2bus_titan3plus2_device::do_io(int offset)
+{
+ int old_inh_state = m_inh_state;
+
+ switch (offset)
+ {
+ case 0x1: case 0x3: case 0x9: case 0xb:
+ if (offset != m_last_offset)
+ {
+ m_last_offset = offset;
+ return;
+ }
+ break;
+ }
+ m_last_offset = offset;
+
+ if (offset & 4)
+ {
+ switch (offset)
+ {
+ case 0x4: m_main_bank = 0x00000; break;
+ case 0x5: m_main_bank = 0x04000; break;
+ case 0x6: m_main_bank = 0x08000; break;
+ case 0x7: m_main_bank = 0x0c000; break;
+ case 0xc: m_main_bank = 0x10000; break;
+ case 0xd: m_main_bank = 0x14000; break;
+ case 0xe: m_main_bank = 0x18000; break;
+ case 0xf: m_main_bank = 0x1c000; break;
+ }
+ }
+ else
+ {
+ m_inh_state = INH_NONE;
+ m_dxxx_bank = 0;
+
+ if (offset & 0x1)
+ {
+ m_inh_state |= INH_WRITE;
+ }
+
+ switch(offset & 0x03)
+ {
+ case 0x00:
+ case 0x03:
+ m_inh_state |= INH_READ;
+ break;
+ }
+
+ if (!(offset & 8))
+ {
+ m_dxxx_bank = 0x1000;
+ }
+ }
+
+ if (m_inh_state != old_inh_state)
+ {
+ recalc_slot_inh();
+ }
+
+ #if 0
+ printf("LC: (ofs %x) new state %c%c dxxx=%04x main=%05x\n",
+ offset,
+ (m_inh_state & INH_READ) ? 'R' : 'x',
+ (m_inh_state & INH_WRITE) ? 'W' : 'x',
+ m_dxxx_bank, m_main_bank);
+ #endif
+}
+
+
+/*-------------------------------------------------
+ read_c08x - called for reads from the LC switches
+-------------------------------------------------*/
+
+uint8_t a2bus_titan3plus2_device::read_c08x(uint8_t offset)
+{
+ if (!machine().side_effects_disabled())
+ {
+ do_io(offset & 0xf);
+ }
+ return 0xff;
+}
+
+
+/*-------------------------------------------------
+ write_c0nx - called for writes to the LC switches
+-------------------------------------------------*/
+
+void a2bus_titan3plus2_device::write_c08x(uint8_t offset, uint8_t data)
+{
+ do_io(offset & 0xf);
+}
+
+uint8_t a2bus_titan3plus2_device::read_inh_rom(uint16_t offset)
+{
+ if (offset < 0xd000)
+ {
+ if ((offset >= 0xc080) && (offset <= 0xc08f))
+ {
+ return read_c08x(offset & 0xf);
+ }
+
+ if ((offset >= 0xc060) && (offset <= 0xc06f))
+ {
+ switch (offset & 0x7)
+ {
+ case 1: // button 0
+ return (m_gameio->sw0_r() ? 0x80 : 0);
+
+ case 2: // button 1
+ return (m_gameio->sw1_r() ? 0x80 : 0);
+
+ case 3: // button 2
+ return (m_gameio->sw2_r() ? 0x80 : 0);
+
+ case 4: // joy 1 X axis
+ if (!m_gameio->is_device_connected())
+ return 0x80;
+ return ((machine().time().as_double() < m_joystick_x1_time) ? 0x80 : 0);
+
+ case 5: // joy 1 Y axis
+ if (!m_gameio->is_device_connected())
+ return 0x80;
+ return ((machine().time().as_double() < m_joystick_y1_time) ? 0x80 : 0);
+
+ case 6: // joy 2 X axis
+ if (!m_gameio->is_device_connected())
+ return 0x80;
+ return ((machine().time().as_double() < m_joystick_x2_time) ? 0x80 : 0);
+
+ case 7: // joy 2 Y axis
+ if (!m_gameio->is_device_connected())
+ return 0x80;
+ return ((machine().time().as_double() < m_joystick_y2_time) ? 0x80 : 0);
+ }
+ }
+ }
+ else
+ {
+ if (offset < 0xe000)
+ {
+ return m_ram[(offset & 0xfff) + m_dxxx_bank + m_main_bank];
+ }
+
+ return m_ram[(offset & 0x1fff) + 0x2000 + m_main_bank];
+ }
+
+ return 0xff;
+}
+
+void a2bus_titan3plus2_device::write_inh_rom(uint16_t offset, uint8_t data)
+{
+ if (offset < 0xd000)
+ {
+ if ((offset >= 0xc080) && (offset <= 0xc08f))
+ {
+ write_c08x(offset & 0xf, data);
+ return;
+ }
+ }
+ else
+ {
+ if (offset < 0xe000)
+ {
+ m_ram[(offset & 0xfff) + m_dxxx_bank + m_main_bank] = data;
+ return;
+ }
+
+ m_ram[(offset & 0x1fff) + 0x2000 + m_main_bank] = data;
+ }
+}
+
+u8 a2bus_titan3plus2_device::read_cnxx(u8 offset)
+{
+ m_enabled = true;
+ return 0xff;
+}
+
+// returns if we want to /INH a read or write to a specific address
+bool a2bus_titan3plus2_device::inh_check(u16 offset, bool bIsWrite)
+{
+ if (!m_enabled)
+ {
+ return false;
+ }
+
+ // handle LC
+ if (offset >= 0xd000)
+ {
+ if ((bIsWrite) && (m_inh_state & INH_WRITE))
+ {
+ return true;
+ }
+
+ if (!(bIsWrite) && (m_inh_state & INH_READ))
+ {
+ return true;
+ }
+ }
+
+ if ((offset >= 0xc080) && (offset <= 0xc08f))
+ {
+ return true;
+ }
+
+ if ((offset >= 0xc070) && (offset <= 0xc07f))
+ {
+ m_joystick_x1_time = machine().time().as_double() + m_x_calibration * m_gameio->pdl0_r();
+ m_joystick_y1_time = machine().time().as_double() + m_y_calibration * m_gameio->pdl1_r();
+ m_joystick_x2_time = machine().time().as_double() + m_x_calibration * m_gameio->pdl2_r();
+ m_joystick_y2_time = machine().time().as_double() + m_y_calibration * m_gameio->pdl3_r();
+
+ return false; // Apple /// should still handle this
+ }
+
+ if ((offset >= 0xc060) && (offset <= 0xc06f))
+ {
+ return true;
+ }
+
+ if ((offset >= 0xc058) && (offset <= 0xc05f))
+ {
+ switch (offset & 0xf)
+ {
+ case 8:
+ case 9:
+ m_gameio->an0_w(offset & 1);
+ break;
+ case 0xa:
+ case 0xb:
+ m_gameio->an1_w(offset & 1);
+ break;
+ case 0xc:
+ case 0xd:
+ m_gameio->an2_w(offset & 1);
+ break;
+ case 0xe:
+ case 0xf:
+ m_gameio->an3_w(offset & 1);
+ break;
+ }
+ return false; // Apple /// should still see this
+ }
+
+ return false;
+}
diff --git a/src/devices/bus/a2bus/titan3plus2.h b/src/devices/bus/a2bus/titan3plus2.h
new file mode 100644
index 00000000000..1fd98d1cab7
--- /dev/null
+++ b/src/devices/bus/a2bus/titan3plus2.h
@@ -0,0 +1,64 @@
+// license:BSD-3-Clause
+// copyright-holders:R. Belmont
+/*********************************************************************
+
+ titan3plus2.h
+
+ Implemention of the Titan /// Plus II card
+
+*********************************************************************/
+
+#ifndef MAME_BUS_A2BUS_TITAN3PLUS2_H
+#define MAME_BUS_A2BUS_TITAN3PLUS2_H
+
+#pragma once
+
+#include "a2bus.h"
+#include "bus/a2gameio/gameio.h"
+
+//**************************************************************************
+// TYPE DEFINITIONS
+//**************************************************************************
+
+class a2bus_titan3plus2_device:
+ public device_t,
+ public device_a2bus_card_interface
+{
+public:
+ // construction/destruction
+ a2bus_titan3plus2_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
+
+protected:
+ a2bus_titan3plus2_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock);
+
+ 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;
+
+ // overrides of standard a2bus slot functions
+ virtual u8 read_inh_rom(u16 offset) override;
+ virtual void write_inh_rom(u16 offset, u8 data) override;
+ virtual bool inh_check(uint16_t offset, bool bIsWrite) override;
+
+private:
+ required_device<apple2_gameio_device> m_gameio;
+
+ u8 read_c08x(u8 offset);
+ void write_c08x(u8 offset, u8 data);
+ u8 read_cnxx(u8 offset) override;
+ void do_io(int offset);
+
+ int m_inh_state;
+ int m_last_offset;
+ int m_dxxx_bank;
+ int m_main_bank;
+ u8 m_ram[128*1024];
+ bool m_enabled;
+
+ double m_joystick_x1_time, m_joystick_y1_time, m_joystick_x2_time, m_joystick_y2_time, m_x_calibration, m_y_calibration;
+};
+
+// device type definition
+DECLARE_DEVICE_TYPE(A2BUS_TITAN3PLUS2, a2bus_titan3plus2_device)
+
+#endif // MAME_BUS_A2BUS_TITAN3PLUS2_H
diff --git a/src/devices/bus/a2bus/transwarp.cpp b/src/devices/bus/a2bus/transwarp.cpp
index 97e02eb8b4e..34b3a3305b9 100644
--- a/src/devices/bus/a2bus/transwarp.cpp
+++ b/src/devices/bus/a2bus/transwarp.cpp
@@ -8,30 +8,76 @@
TODO:
- needs built-in language card, it's advertised to work w/o one.
- - C074 speed control
- Doesn't work with Swyft but advertised to; how does h/w get
around the Fxxx ROM not checksumming right?
+ To control this from software:
+ - There's no way I can tell to detect it besides maybe measuring
+ how many cycles between vblanks or something.
+ - Write to $C074: 0 = fast speed, 1 = 1 MHz,
+ 3 = disables the TransWarp's CPU and restarts the Apple's 65(C)02.
+
*********************************************************************/
#include "emu.h"
#include "transwarp.h"
#include "cpu/m6502/m6502.h"
-#include "cpu/m6502/m65c02.h"
+#include "cpu/m6502/w65c02.h"
-/***************************************************************************
- PARAMETERS
-***************************************************************************/
//**************************************************************************
-// GLOBAL VARIABLES
+// TYPE DEFINITIONS
//**************************************************************************
-DEFINE_DEVICE_TYPE(A2BUS_TRANSWARP, a2bus_transwarp_device, "a2twarp", "Applied Engineering TransWarp")
+class a2bus_transwarp_device:
+ public device_t,
+ public device_a2bus_card_interface
+{
+public:
+ // construction/destruction
+ a2bus_transwarp_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
+
+protected:
+ a2bus_transwarp_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock);
+
+ // overrides of device_t functions
+ 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;
+ virtual ioport_constructor device_input_ports() const override ATTR_COLD;
+ virtual const tiny_rom_entry *device_rom_region() const override ATTR_COLD;
+
+ // overrides of standard a2bus slot functions
+ virtual bool take_c800() override;
+
+private:
+ bool m_bEnabled;
+ bool m_bReadA2ROM;
+ bool m_bIn1MHzMode;
+ emu_timer *m_timer;
+
+ required_device<cpu_device> m_ourcpu;
+ required_region_ptr<uint8_t> m_rom;
+ required_ioport m_dsw1, m_dsw2;
+
+ TIMER_CALLBACK_MEMBER(clock_adjust_tick);
+
+ uint8_t dma_r(offs_t offset);
+ void dma_w(offs_t offset, uint8_t data);
-#define CPU_TAG "tw65c02"
+ void w65c02_mem(address_map &map) ATTR_COLD;
-void a2bus_transwarp_device::m65c02_mem(address_map &map)
+ void hit_slot(int slot);
+ void hit_slot_joy();
+};
+
+//**************************************************************************
+// GLOBAL VARIABLES
+//**************************************************************************
+
+DEFINE_DEVICE_TYPE_PRIVATE(A2BUS_TRANSWARP, device_a2bus_card_interface, a2bus_transwarp_device, "a2twarp", "Applied Engineering TransWarp")
+
+void a2bus_transwarp_device::w65c02_mem(address_map &map)
{
map(0x0000, 0xffff).rw(FUNC(a2bus_transwarp_device::dma_r), FUNC(a2bus_transwarp_device::dma_w));
}
@@ -123,8 +169,8 @@ ioport_constructor a2bus_transwarp_device::device_input_ports() const
void a2bus_transwarp_device::device_add_mconfig(machine_config &config)
{
- M65C02(config, m_ourcpu, A2BUS_7M_CLOCK / 2);
- m_ourcpu->set_addrmap(AS_PROGRAM, &a2bus_transwarp_device::m65c02_mem);
+ W65C02(config, m_ourcpu, DERIVED_CLOCK(1, 2));
+ m_ourcpu->set_addrmap(AS_PROGRAM, &a2bus_transwarp_device::w65c02_mem);
}
//**************************************************************************
@@ -135,7 +181,7 @@ a2bus_transwarp_device::a2bus_transwarp_device(const machine_config &mconfig, de
device_t(mconfig, type, tag, owner, clock),
device_a2bus_card_interface(mconfig, *this),
m_bEnabled(false),
- m_ourcpu(*this, CPU_TAG),
+ m_ourcpu(*this, "tw65c02"),
m_rom(*this, "twrom"),
m_dsw1(*this, "DSW1"),
m_dsw2(*this, "DSW2")
@@ -153,9 +199,11 @@ a2bus_transwarp_device::a2bus_transwarp_device(const machine_config &mconfig, co
void a2bus_transwarp_device::device_start()
{
- m_timer = timer_alloc(0);
+ m_timer = timer_alloc(FUNC(a2bus_transwarp_device::clock_adjust_tick), this);
save_item(NAME(m_bEnabled));
+ save_item(NAME(m_bReadA2ROM));
+ save_item(NAME(m_bIn1MHzMode));
}
void a2bus_transwarp_device::device_reset()
@@ -166,9 +214,13 @@ void a2bus_transwarp_device::device_reset()
if (!(m_dsw2->read() & 0x80))
{
if (m_dsw1->read() & 0x80)
- m_ourcpu->set_unscaled_clock(A2BUS_7M_CLOCK / 4);
+ {
+ m_ourcpu->set_unscaled_clock(clock() / 4);
+ }
else
- m_ourcpu->set_unscaled_clock(A2BUS_7M_CLOCK / 2);
+ {
+ m_ourcpu->set_unscaled_clock(clock() / 2);
+ }
}
else
{
@@ -176,31 +228,44 @@ void a2bus_transwarp_device::device_reset()
}
}
-void a2bus_transwarp_device::device_timer(emu_timer &timer, device_timer_id id, int param, void *ptr)
+TIMER_CALLBACK_MEMBER(a2bus_transwarp_device::clock_adjust_tick)
{
- if (!(m_dsw2->read() & 0x80))
+ if (m_bIn1MHzMode)
{
- if (m_dsw1->read() & 0x80)
- m_ourcpu->set_unscaled_clock(A2BUS_7M_CLOCK / 4);
- else
- m_ourcpu->set_unscaled_clock(A2BUS_7M_CLOCK / 2);
+ m_ourcpu->set_unscaled_clock(1021800);
+ }
+ else
+ {
+ if (!(m_dsw2->read() & 0x80))
+ {
+ if (m_dsw1->read() & 0x80)
+ {
+ m_ourcpu->set_unscaled_clock(clock() / 4);
+ }
+ else
+ {
+ m_ourcpu->set_unscaled_clock(clock() / 2);
+ }
+ }
}
m_timer->adjust(attotime::never);
}
-READ8_MEMBER( a2bus_transwarp_device::dma_r )
+uint8_t a2bus_transwarp_device::dma_r(offs_t offset)
{
if (offset == 0xc070)
{
hit_slot_joy();
}
-
- if ((offset >= 0xc090) && (offset <= 0xc0ff))
+ else if ((offset >= 0xc090) && (offset <= 0xc0ff))
{
hit_slot(((offset >> 4) & 0xf) - 8);
}
-
- if ((offset >= 0xf000) && (!m_bReadA2ROM))
+ else if ((offset >= 0xc100) && (offset <= 0xc7ff))
+ {
+ hit_slot((offset >> 8) & 0x7);
+ }
+ else if ((offset >= 0xf000) && (!m_bReadA2ROM))
{
return m_rom[offset & 0xfff];
}
@@ -213,7 +278,7 @@ READ8_MEMBER( a2bus_transwarp_device::dma_r )
// dma_w -
//-------------------------------------------------
-WRITE8_MEMBER( a2bus_transwarp_device::dma_w )
+void a2bus_transwarp_device::dma_w(offs_t offset, uint8_t data)
{
//if ((offset >= 0xc070) && (offset <= 0xc07f)) printf("%02x to %04x\n", data, offset);
@@ -221,16 +286,46 @@ WRITE8_MEMBER( a2bus_transwarp_device::dma_w )
{
hit_slot_joy();
}
-
- if (offset == 0xc072)
+ else if (offset == 0xc072)
{
m_bReadA2ROM = true;
}
-
- if ((offset >= 0xc090) && (offset <= 0xc0ff))
+ else if (offset == 0xc074)
+ {
+ if (data == 0)
+ {
+ if (m_dsw1->read() & 0x80)
+ {
+ m_ourcpu->set_unscaled_clock(clock() / 4);
+ }
+ else
+ {
+ m_ourcpu->set_unscaled_clock(clock() / 2);
+ }
+ m_bIn1MHzMode = false;
+ }
+ else if (data == 1)
+ {
+ m_ourcpu->set_unscaled_clock(1021800);
+ m_bIn1MHzMode = true;
+ }
+ else if (data == 3)
+ {
+ // disable our CPU
+ m_ourcpu->set_input_line(INPUT_LINE_HALT, ASSERT_LINE);
+ // re-enable the Apple's
+ lower_slot_dma();
+ }
+ return;
+ }
+ else if ((offset >= 0xc090) && (offset <= 0xc0ff))
{
hit_slot(((offset >> 4) & 0xf) - 8);
}
+ else if ((offset >= 0xc100) && (offset <= 0xc7ff))
+ {
+ hit_slot((offset >> 8) & 0x7);
+ }
slot_dma_write(offset, data);
}
diff --git a/src/devices/bus/a2bus/transwarp.h b/src/devices/bus/a2bus/transwarp.h
index e687ae6d350..42e9bfbc7f3 100644
--- a/src/devices/bus/a2bus/transwarp.h
+++ b/src/devices/bus/a2bus/transwarp.h
@@ -8,56 +8,12 @@
*********************************************************************/
-#ifndef MAME_BUS_A2BUS_A2TRANSWARP_H
-#define MAME_BUS_A2BUS_A2TRANSWARP_H
+#ifndef MAME_BUS_A2BUS_TRANSWARP_H
+#define MAME_BUS_A2BUS_TRANSWARP_H
#include "a2bus.h"
-//**************************************************************************
-// TYPE DEFINITIONS
-//**************************************************************************
-
-class a2bus_transwarp_device:
- public device_t,
- public device_a2bus_card_interface
-{
-public:
- // construction/destruction
- a2bus_transwarp_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
-
-protected:
- a2bus_transwarp_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock);
-
- // overrides of device_t functions
- 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 device_timer(emu_timer &timer, device_timer_id id, int param, void *ptr) override;
- virtual const tiny_rom_entry *device_rom_region() const override;
-
- // overrides of standard a2bus slot functions
- virtual bool take_c800() override;
-
-private:
- bool m_bEnabled;
- bool m_bReadA2ROM;
- emu_timer *m_timer;
-
- required_device<cpu_device> m_ourcpu;
- required_region_ptr<uint8_t> m_rom;
- required_ioport m_dsw1, m_dsw2;
-
- DECLARE_READ8_MEMBER( dma_r );
- DECLARE_WRITE8_MEMBER( dma_w );
-
- void m65c02_mem(address_map &map);
-
- void hit_slot(int slot);
- void hit_slot_joy();
-};
-
// device type definition
-DECLARE_DEVICE_TYPE(A2BUS_TRANSWARP, a2bus_transwarp_device)
+DECLARE_DEVICE_TYPE(A2BUS_TRANSWARP, device_a2bus_card_interface)
#endif // MAME_BUS_A2BUS_TRANSWARP_H
diff --git a/src/devices/bus/a2bus/uniprint.cpp b/src/devices/bus/a2bus/uniprint.cpp
new file mode 100644
index 00000000000..167cfc97243
--- /dev/null
+++ b/src/devices/bus/a2bus/uniprint.cpp
@@ -0,0 +1,250 @@
+// license:BSD-3-Clause
+// copyright-holders:Vas Crabb, R. Belmont
+#include "emu.h"
+#include "uniprint.h"
+
+#include "bus/centronics/ctronics.h"
+
+//#define VERBOSE 1
+//#define LOG_OUTPUT_FUNC osd_printf_info
+#include "logmacro.h"
+
+
+namespace {
+
+class a2bus_uniprint_device : public device_t, public device_a2bus_card_interface
+{
+public:
+ a2bus_uniprint_device(machine_config const &mconfig, char const *tag, device_t *owner, u32 clock);
+
+ // 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 u8 read_c800(u16 offset) override;
+
+protected:
+ // device_t implementation
+ virtual tiny_rom_entry const *device_rom_region() const override ATTR_COLD;
+ virtual void device_add_mconfig(machine_config &config) override ATTR_COLD;
+ virtual ioport_constructor device_input_ports() const override ATTR_COLD;
+ virtual void device_start() override ATTR_COLD;
+ virtual void device_reset() override ATTR_COLD;
+
+ // timer handlers
+ TIMER_CALLBACK_MEMBER(update_strobe);
+
+private:
+ // printer status inputs
+ void ack_w(int state);
+
+ required_device<centronics_device> m_printer_conn;
+ required_device<output_latch_device> m_printer_out;
+ required_ioport m_s1, m_s2;
+ required_region_ptr<u8> m_rom;
+ emu_timer * m_strobe_timer;
+
+ u8 m_data_latch; // U6
+ u8 m_ack_latch; // U2 (pin 9)
+ u8 m_next_strobe; // U4 (pin 5)
+ u8 m_ack_in; // printer connector pin 10
+};
+
+
+ROM_START(uniprint)
+ ROM_REGION(0x1000, "rom", 0)
+ ROM_LOAD("videx_uniprint_2732a.bin", 0x000000, 0x001000, CRC(e8423ef6) SHA1(0a2789ec2cb28f10a2836a91feabc24ceca8f142))
+ROM_END
+
+INPUT_PORTS_START(uniprint)
+ PORT_START("S1")
+ PORT_DIPNAME(0x70, 0x00, "Printer Type") PORT_DIPLOCATION("S1:1,2,3")
+ PORT_DIPSETTING( 0x00, "Apple DMP/C. Itoh 8510/NEC 8023A/Leading Edge Prowriter")
+ PORT_DIPSETTING( 0x10, "Epson MX, FX, RX/Mannesman Tally 160L, Sprit-80")
+ PORT_DIPSETTING( 0x20, "Star Gemini 10, 15")
+ PORT_DIPSETTING( 0x30, "Data Products (IDS) 440, 460, Prism, uPrism/Okidata 82A, 83A, 93A")
+ PORT_DIPSETTING( 0x40, "Anadex 9000, 9000A, 9001, 9001A, 9500A, 9501, 9501A")
+ PORT_DIPSETTING( 0x50, "Leading Edge Gorilla Banana/Commodore VIC Printer/Radio Shack DMP-100/Sekiosha GP-100A")
+ PORT_DIPSETTING( 0x60, "Centronics 739-1")
+ PORT_DIPSETTING( 0x70, "Reserved")
+ PORT_DIPNAME(0x0c, 0x00, "Default Page Width") PORT_DIPLOCATION("S1:4,5")
+ PORT_DIPSETTING( 0x00, "No Width")
+ PORT_DIPSETTING( 0x04, "80 Columns")
+ PORT_DIPSETTING( 0x08, "96 Columns")
+ PORT_DIPSETTING( 0x0c, "132 Columns")
+ PORT_DIPNAME(0x03, 0x00, "Default Page Length") PORT_DIPLOCATION("S1:6,7")
+ PORT_DIPSETTING( 0x00, "No Length")
+ PORT_DIPSETTING( 0x01, "54 Lines")
+ PORT_DIPSETTING( 0x02, "57 Lines")
+ PORT_DIPSETTING( 0x03, "60 Lines")
+
+ PORT_START("S2")
+ PORT_DIPNAME(0x01, 0x01, "Strobe Polarity") PORT_DIPLOCATION("S1:8")
+ PORT_DIPSETTING( 0x00, "Positive")
+ PORT_DIPSETTING( 0x01, "Negative")
+ PORT_DIPNAME(0x02, 0x02, "Acknowledge Polarity") PORT_DIPLOCATION("S1:9")
+ PORT_DIPSETTING( 0x00, "Positive")
+ PORT_DIPSETTING( 0x02, "Negative")
+INPUT_PORTS_END
+
+
+a2bus_uniprint_device::a2bus_uniprint_device(machine_config const &mconfig, char const *tag, device_t *owner, u32 clock) :
+ device_t(mconfig, A2BUS_UNIPRINT, tag, owner, clock),
+ device_a2bus_card_interface(mconfig, *this),
+ m_printer_conn(*this, "prn"),
+ m_printer_out(*this, "prn_out"),
+ m_s1(*this, "S1"),
+ m_s2(*this, "S2"),
+ m_rom(*this, "rom"),
+ m_strobe_timer(nullptr),
+ m_data_latch(0xffU),
+ m_ack_latch(0x01U),
+ m_next_strobe(1U),
+ m_ack_in(1U)
+{
+}
+
+
+
+//----------------------------------------------
+// device_a2bus_card_interface implementation
+//----------------------------------------------
+
+// address lines are connected only to the EPROM, so all C0NX accesses are the same
+u8 a2bus_uniprint_device::read_c0nx(u8 offset)
+{
+ // inverted /ACK?
+ if (m_s2->read() & 0x02U)
+ {
+ return (m_s1->read() & 0x07FU) | ((m_ack_latch ^ 1) << 7);
+ }
+
+ return (m_s1->read() & 0x07FU) | (m_ack_latch << 7);
+}
+
+void a2bus_uniprint_device::write_c0nx(u8 offset, u8 data)
+{
+ m_data_latch = data;
+ m_printer_out->write(data);
+
+ // clearing the ACK latch will acknowledge an interrupt
+ if (m_ack_in)
+ {
+ m_ack_latch = 0x00U;
+ }
+ else
+ {
+ LOG("/ACK asserted, not clearing acknowledge latch\n");
+ }
+
+ // generate strobe pulse after one clock cycle
+ m_next_strobe = 0U;
+ if (!m_strobe_timer->enabled())
+ {
+ LOG("Start strobe timer\n");
+ m_strobe_timer->adjust(attotime::from_ticks(1, clock()));
+ }
+}
+
+u8 a2bus_uniprint_device::read_cnxx(u8 offset)
+{
+ return m_rom[offset + (slotno() * 0x100)];
+}
+
+u8 a2bus_uniprint_device::read_c800(u16 offset)
+{
+ return m_rom[offset + 0x800];
+}
+
+
+//----------------------------------------------
+// device_t implementation
+//----------------------------------------------
+
+tiny_rom_entry const *a2bus_uniprint_device::device_rom_region() const
+{
+ return ROM_NAME(uniprint);
+}
+
+
+void a2bus_uniprint_device::device_add_mconfig(machine_config &config)
+{
+ CENTRONICS(config, m_printer_conn, centronics_devices, "printer");
+ m_printer_conn->ack_handler().set(FUNC(a2bus_uniprint_device::ack_w));
+
+ OUTPUT_LATCH(config, m_printer_out);
+ m_printer_conn->set_output_latch(*m_printer_out);
+}
+
+
+ioport_constructor a2bus_uniprint_device::device_input_ports() const
+{
+ return INPUT_PORTS_NAME(uniprint);
+}
+
+
+void a2bus_uniprint_device::device_start()
+{
+ m_strobe_timer = timer_alloc(FUNC(a2bus_uniprint_device::update_strobe), this);
+
+ m_next_strobe = 1U;
+
+ save_item(NAME(m_data_latch));
+ save_item(NAME(m_ack_latch));
+ save_item(NAME(m_next_strobe));
+ save_item(NAME(m_ack_in));
+
+ m_strobe_timer->adjust(attotime::from_ticks(1, clock()));
+}
+
+
+void a2bus_uniprint_device::device_reset()
+{
+ m_ack_latch = 0x01U;
+}
+
+
+
+//----------------------------------------------
+// printer status inputs
+//----------------------------------------------
+
+void a2bus_uniprint_device::ack_w(int state)
+{
+ if (bool(state) != bool(m_ack_in))
+ {
+ LOG("/ACK=%d\n", state);
+ m_ack_in = state ? 1U : 0U;
+ if (!state)
+ {
+ if (!m_ack_latch)
+ LOG("Set acknowledge latch\n");
+ else
+ LOG("No data written since previous acknowledge\n");
+ m_ack_latch = 0x01U;
+ }
+ }
+}
+
+//----------------------------------------------
+// timer handlers
+//----------------------------------------------
+
+TIMER_CALLBACK_MEMBER(a2bus_uniprint_device::update_strobe)
+{
+ LOG("Output /STROBE=%u\n", m_next_strobe);
+ // invert strobe if DIP set to positive polarity
+ m_printer_conn->write_strobe(m_next_strobe ^ (m_s2->read() & 0x01) ? 0 : 1);
+ if (!m_next_strobe)
+ {
+ LOG("Start strobe timer\n");
+ m_next_strobe = 1U;
+ m_strobe_timer->adjust(attotime::from_ticks(1, clock()));
+ }
+}
+
+} // anonymous namespace
+
+
+
+DEFINE_DEVICE_TYPE_PRIVATE(A2BUS_UNIPRINT, device_a2bus_card_interface, a2bus_uniprint_device, "a2uniprint", "Videx Uniprint Printer Interface")
diff --git a/src/devices/bus/a2bus/uniprint.h b/src/devices/bus/a2bus/uniprint.h
new file mode 100644
index 00000000000..57d6999b01e
--- /dev/null
+++ b/src/devices/bus/a2bus/uniprint.h
@@ -0,0 +1,32 @@
+// license:BSD-3-Clause
+// copyright-holders:Vas Crabb, R. Belmont
+/***********************************************************************
+
+ Videx Uniprint Parallel Interface Card
+
+ Manual, including schematic and theory of operation:
+ https://www.apple.asimov.net/documentation/hardware/io/Videx%20UniPrint%20Manual.pdf
+
+ Connector P2 pinout (pins 1 and 11 are at the top of the card):
+ STB 1 11 GND
+ D0 2 12 GND
+ D1 3 13 GND
+ D2 4 14 GND
+ D3 5 15 GND
+ D4 6 16 GND
+ D5 7 17 GND
+ D6 8 18 GND
+ D7 9 19 GND
+ ACK 10 20 GND
+
+***********************************************************************/
+#ifndef MAME_BUS_A2BUS_UNIPRINT_H
+#define MAME_BUS_A2BUS_UNIPRINT_H
+
+#pragma once
+
+#include "a2bus.h"
+
+DECLARE_DEVICE_TYPE(A2BUS_UNIPRINT, device_a2bus_card_interface)
+
+#endif // MAME_BUS_A2BUS_UNIPRINT_H
diff --git a/src/devices/bus/a2bus/uthernet.cpp b/src/devices/bus/a2bus/uthernet.cpp
new file mode 100644
index 00000000000..6f3a8d21b47
--- /dev/null
+++ b/src/devices/bus/a2bus/uthernet.cpp
@@ -0,0 +1,67 @@
+// license:BSD-3-Clause
+// copyright-holders:R. Belmont
+/*********************************************************************
+
+ uthernet.cpp
+
+ Apple II Uthernet Card
+
+*********************************************************************/
+
+#include "emu.h"
+#include "uthernet.h"
+
+#include "machine/cs8900a.h"
+
+namespace {
+
+//**************************************************************************
+// TYPE DEFINITIONS
+//**************************************************************************
+
+class a2bus_uthernet_device:
+ public device_t,
+ public device_a2bus_card_interface
+{
+public:
+ // construction/destruction
+ a2bus_uthernet_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) :
+ a2bus_uthernet_device(mconfig, A2BUS_UTHERNET, tag, owner, clock)
+ {
+ }
+
+protected:
+ a2bus_uthernet_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_netinf(*this, "cs8900a")
+ {
+ }
+
+ virtual void device_add_mconfig(machine_config &config) override
+ {
+ CS8900A(config, m_netinf, 20_MHz_XTAL); // see CS8900A data sheet sec 3.13
+ }
+
+ virtual void device_start() override { }
+ virtual void device_reset() override { }
+
+ // read_c0nx - called for reads from this card's c0nx space
+ virtual uint8_t read_c0nx(uint8_t offset) override { return m_netinf->read(offset); }
+
+ // write_c0nx - called for writes to this card's c0nx space
+ virtual void write_c0nx(uint8_t offset, uint8_t data) override { m_netinf->write(offset,data); }
+
+private:
+ required_device<cs8900a_device> m_netinf;
+
+};
+
+} // anonymous namespace
+
+
+//**************************************************************************
+// GLOBAL VARIABLES
+//**************************************************************************
+
+DEFINE_DEVICE_TYPE_PRIVATE(A2BUS_UTHERNET, device_a2bus_card_interface, a2bus_uthernet_device, "a2uthernet", "a2RetroSystems Uthernet")
diff --git a/src/devices/bus/a2bus/uthernet.h b/src/devices/bus/a2bus/uthernet.h
new file mode 100644
index 00000000000..438ee5a9083
--- /dev/null
+++ b/src/devices/bus/a2bus/uthernet.h
@@ -0,0 +1,19 @@
+// license:BSD-3-Clause
+// copyright-holders:R. Belmont
+/*********************************************************************
+
+ uthernet.h
+
+ Apple II Uthernet Card
+
+*********************************************************************/
+
+#ifndef MAME_BUS_A2BUS_UTHERNET_H
+#define MAME_BUS_A2BUS_UTHERNET_H
+
+#include "a2bus.h"
+
+// device type declaration
+DECLARE_DEVICE_TYPE(A2BUS_UTHERNET, device_a2bus_card_interface)
+
+#endif // MAME_BUS_A2BUS_UTHERNET_H
diff --git a/src/devices/bus/a2bus/vistaa800.cpp b/src/devices/bus/a2bus/vistaa800.cpp
new file mode 100644
index 00000000000..282b32e3720
--- /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 ATTR_COLD;
+ virtual void device_reset() override ATTR_COLD;
+ virtual void device_add_mconfig(machine_config &config) override ATTR_COLD;
+ virtual const tiny_rom_entry *device_rom_region() const override ATTR_COLD;
+
+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/brightpen.cpp b/src/devices/bus/a2gameio/brightpen.cpp
new file mode 100644
index 00000000000..41d8ce3b512
--- /dev/null
+++ b/src/devices/bus/a2gameio/brightpen.cpp
@@ -0,0 +1,140 @@
+// license:BSD-3-Clause
+// copyright-holders:kmg
+/*********************************************************************
+
+ Apple II Softape Bright Pen interface for the Apple ][/][+
+
+*********************************************************************/
+
+#include "emu.h"
+#include "bus/a2gameio/brightpen.h"
+#include "screen.h"
+
+
+namespace {
+
+#define BRIGHTPEN_POINT "BRIGHTPEN_POINT"
+#define BRIGHTPEN_X "BRIGHTPEN_X"
+#define BRIGHTPEN_Y "BRIGHTPEN_Y"
+
+// ======================> apple2_brightpen_device
+
+class apple2_brightpen_device : public device_t, public device_a2gameio_interface
+{
+public:
+ // construction/destruction
+ apple2_brightpen_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock)
+ : device_t(mconfig, APPLE2_BRIGHTPEN, tag, owner, clock)
+ , device_a2gameio_interface(mconfig, *this)
+ , m_brightpen_point(*this, BRIGHTPEN_POINT)
+ , m_brightpen_x(*this, BRIGHTPEN_X)
+ , m_brightpen_y(*this, BRIGHTPEN_Y)
+ {
+ }
+
+protected:
+ // device_t implementation
+ virtual ioport_constructor device_input_ports() const override ATTR_COLD;
+ virtual void device_start() override ATTR_COLD;
+
+ // device_a2gameio_interface implementation
+ virtual int sw0_r() override;
+
+private:
+ // input ports
+ required_ioport m_brightpen_point;
+ required_ioport m_brightpen_x;
+ required_ioport m_brightpen_y;
+
+ // radius of circle picked up by the bright pen
+ static constexpr int PEN_X_RADIUS = 2;
+ static constexpr int PEN_Y_RADIUS = 1;
+ // brightness threshold
+ static constexpr int BRIGHTNESS_THRESHOLD = 0x20;
+ // # of CRT scanlines that sustain brightness
+ static constexpr int SUSTAIN = 22;
+};
+
+//**************************************************************************
+// INPUT PORTS
+//**************************************************************************
+
+static INPUT_PORTS_START( apple2_brightpen )
+ PORT_START(BRIGHTPEN_X)
+ PORT_BIT( 0x3ff, 0x80, IPT_LIGHTGUN_X ) PORT_CROSSHAIR(X, 1.0, 0.0, 0) PORT_SENSITIVITY(45) PORT_KEYDELTA(15) PORT_MINMAX(0, 559) PORT_NAME("Bright Pen X")
+ PORT_START(BRIGHTPEN_Y)
+ PORT_BIT( 0x3ff, 0x80, IPT_LIGHTGUN_Y ) PORT_CROSSHAIR(Y, 1.0, 0.0, 0) PORT_SENSITIVITY(45) PORT_KEYDELTA(15) PORT_MINMAX(0, 191) PORT_NAME("Bright Pen Y")
+ PORT_START(BRIGHTPEN_POINT)
+ PORT_BIT( 0x01, IP_ACTIVE_HIGH, IPT_BUTTON1 ) PORT_NAME("Bright Pen pointed at screen")
+ PORT_BIT( 0xfe, IP_ACTIVE_LOW, IPT_UNUSED )
+INPUT_PORTS_END
+
+ioport_constructor apple2_brightpen_device::device_input_ports() const
+{
+ return INPUT_PORTS_NAME(apple2_brightpen);
+}
+
+void apple2_brightpen_device::device_start()
+{
+}
+
+// light detection logic based on zapper_sensor.cpp nes_zapper_sensor_device::detect_light
+
+int apple2_brightpen_device::sw0_r()
+{
+ if (!BIT(m_brightpen_point->read(), 0)) return 0;
+
+ int pen_x_pos = m_brightpen_x->read();
+ int pen_y_pos = m_brightpen_y->read();
+ int beam_vpos = m_screen->vpos();
+ int beam_hpos = m_screen->hpos();
+
+ // update the screen if the beam position is within the radius of the pen
+ if (!machine().side_effects_disabled())
+ {
+ if (!m_screen->vblank())
+ {
+ if (beam_vpos > pen_y_pos - PEN_Y_RADIUS || (beam_vpos == pen_y_pos - PEN_Y_RADIUS && beam_hpos >= pen_x_pos - PEN_X_RADIUS))
+ {
+ m_screen->update_now();
+ }
+ }
+ }
+
+ int brightness_sum = 0;
+ int pixels_scanned = 0;
+
+ // sum brightness of pixels nearby the pen position
+ for (int i = pen_x_pos - PEN_X_RADIUS; i <= pen_x_pos + PEN_X_RADIUS; i++)
+ {
+ for (int j = pen_y_pos - PEN_Y_RADIUS; j <= pen_y_pos + PEN_Y_RADIUS; j++)
+ {
+ // look at pixels within circular sensor
+ if ((pen_x_pos - i) * (pen_x_pos - i) + (pen_y_pos - j) * (pen_y_pos - j) <= PEN_X_RADIUS * PEN_Y_RADIUS)
+ {
+ rgb_t pix = m_screen->pixel(i, j);
+
+ // only detect light if pen position is near, and behind,
+ // where the video generator is drawing on the CRT,
+ if (j <= beam_vpos && j > beam_vpos - SUSTAIN && (j != beam_vpos || i <= beam_hpos))
+ {
+ brightness_sum += pix.r() + pix.g() + pix.b();
+ }
+ pixels_scanned++;
+ }
+ }
+ }
+
+ // light detected if average brightness is above threshold
+ return brightness_sum >= BRIGHTNESS_THRESHOLD * pixels_scanned;
+}
+
+} // anonymous namespace
+
+
+//**************************************************************************
+// GLOBAL VARIABLES
+//**************************************************************************
+
+// device type definition
+DEFINE_DEVICE_TYPE_PRIVATE(APPLE2_BRIGHTPEN, device_a2gameio_interface, apple2_brightpen_device, "a2brightpen", "Softape Bright Pen")
diff --git a/src/devices/bus/a2gameio/brightpen.h b/src/devices/bus/a2gameio/brightpen.h
new file mode 100644
index 00000000000..9c47c3d47d4
--- /dev/null
+++ b/src/devices/bus/a2gameio/brightpen.h
@@ -0,0 +1,18 @@
+// license:BSD-3-Clause
+/*********************************************************************
+
+ Apple II Softape Bright Pen interface for a lightpen
+
+*********************************************************************/
+
+#ifndef MAME_BUS_A2GAMEIO_BRIGHTPEN_H
+#define MAME_BUS_A2GAMEIO_BRIGHTPEN_H
+
+#pragma once
+
+#include "bus/a2gameio/gameio.h"
+
+// device type declaration
+DECLARE_DEVICE_TYPE(APPLE2_BRIGHTPEN, device_a2gameio_interface)
+
+#endif // MAME_BUS_A2GAMEIO_BRIGHTPEN_H
diff --git a/src/devices/bus/a2gameio/computereyes.cpp b/src/devices/bus/a2gameio/computereyes.cpp
index 1c587f54254..03de502df9c 100644
--- a/src/devices/bus/a2gameio/computereyes.cpp
+++ b/src/devices/bus/a2gameio/computereyes.cpp
@@ -9,12 +9,40 @@
#include "emu.h"
#include "bus/a2gameio/computereyes.h"
-//**************************************************************************
-// GLOBAL VARIABLES
-//**************************************************************************
+#include "imagedev/picture.h"
-// device type definition
-DEFINE_DEVICE_TYPE(APPLE2_COMPUTEREYES, apple2_compeyes_device, "a2ceyes", "Digital Vision ComputerEyes")
+#include "bitmap.h"
+
+
+namespace {
+
+// ======================> apple2_compeyes_device
+
+class apple2_compeyes_device : public device_t, public device_a2gameio_interface
+{
+public:
+ // construction/destruction
+ apple2_compeyes_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock);
+
+protected:
+ // device-level overrides
+ 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;
+
+ // device_a2gameio_interface overrides
+ 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;
+ int m_x, m_y, m_an1, m_an2, m_an3, m_level;
+ u8 m_a2_bitmap[280*192];
+};
//**************************************************************************
// DEVICE IMPLEMENTATION
@@ -47,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.
@@ -76,48 +104,57 @@ 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;
std::fill_n(m_a2_bitmap, 280*192, 0);
- m_bitmap = &m_picture->get_bitmap();
- if (m_bitmap)
+ const bitmap_argb32 &bitmap = m_picture->get_bitmap();
+ if (bitmap.valid())
{
// convert arbitrary sized ARGB32 image to a 280x192 image with 256 levels of grayscale
- double stepx = (double)m_bitmap->width() / 280.0;
- double stepy = (double)m_bitmap->height() / 192.0;
-
+ double stepx = (double)bitmap.width() / 280.0;
+ double stepy = (double)bitmap.height() / 192.0;
for (int y = 0; y < 192; y++)
{
for (int x = 0; x < 280; x++)
{
- u32 pixel = m_bitmap->pix((int)((double)y * stepy), (int)((double)x * stepx));
- double mono = ((0.2126 * (double)(((pixel>>16) & 0xff) / 255.0)) +
- (0.7152 * (double)(((pixel>>8) & 0xff) / 255.0)) +
- (0.0722 * (double)((pixel& 0xff) / 255.0)));
- m_a2_bitmap[(y*280)+x] = (u8)(mono * 255.0);
+ u32 pixel = bitmap.pix(int((double)y * stepy), int((double)x * stepx));
+ double mono = ((0.2126 * double(((pixel>>16) & 0xff) / 255.0)) +
+ (0.7152 * double(((pixel>>8) & 0xff) / 255.0)) +
+ (0.0722 * double((pixel& 0xff) / 255.0)));
+ m_a2_bitmap[(y*280)+x] = u8(mono * 255.0);
}
}
}
}
-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);
}
+
+} // anonymous namespace
+
+
+//**************************************************************************
+// GLOBAL VARIABLES
+//**************************************************************************
+
+// device type definition
+DEFINE_DEVICE_TYPE_PRIVATE(APPLE2_COMPUTEREYES, device_a2gameio_interface, apple2_compeyes_device, "a2ceyes", "Digital Vision ComputerEyes")
diff --git a/src/devices/bus/a2gameio/computereyes.h b/src/devices/bus/a2gameio/computereyes.h
index 6aef78796a6..44023723676 100644
--- a/src/devices/bus/a2gameio/computereyes.h
+++ b/src/devices/bus/a2gameio/computereyes.h
@@ -6,45 +6,14 @@
*********************************************************************/
-#ifndef MAME_BUS_A2GAMEIO_COMPEYES_H
-#define MAME_BUS_A2GAMEIO_COMPEYES_H
+#ifndef MAME_BUS_A2GAMEIO_COMPUTEREYES_H
+#define MAME_BUS_A2GAMEIO_COMPUTEREYES_H
#pragma once
#include "bus/a2gameio/gameio.h"
-#include "bitmap.h"
-#include "imagedev/picture.h"
-
-// ======================> apple2_compeyes_device
-
-class apple2_compeyes_device : public device_t, public device_a2gameio_interface
-{
-public:
- // construction/destruction
- apple2_compeyes_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock);
-
-protected:
- // device-level overrides
- virtual void device_add_mconfig(machine_config &config) override;
- virtual void device_start() override;
- 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;
-
-private:
- required_device<picture_image_device> m_picture;
- int m_x, m_y, m_an1, m_an2, m_an3, m_level;
- u8 m_a2_bitmap[280*192];
- bitmap_argb32 *m_bitmap;
-};
// device type declaration
-DECLARE_DEVICE_TYPE(APPLE2_COMPUTEREYES, apple2_compeyes_device)
+DECLARE_DEVICE_TYPE(APPLE2_COMPUTEREYES, device_a2gameio_interface)
-#endif // MAME_BUS_A2GAMEIO_COMPEYES_H
+#endif // MAME_BUS_A2GAMEIO_COMPUTEREYES_H
diff --git a/src/devices/bus/a2gameio/gameio.cpp b/src/devices/bus/a2gameio/gameio.cpp
index 4f9b7bd9b58..fa1f1accf71 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.
**********************************************************************
____________
@@ -49,10 +50,14 @@
#include "emu.h"
#include "bus/a2gameio/gameio.h"
+#include "bus/a2gameio/brightpen.h"
#include "bus/a2gameio/joystick.h"
#include "bus/a2gameio/joyport.h"
+#include "bus/a2gameio/joyport_paddles.h"
#include "bus/a2gameio/computereyes.h"
-
+#include "bus/a2gameio/paddles.h"
+#include "bus/a2gameio/gizmo.h"
+#include "bus/a2gameio/wico_joystick.h"
//**************************************************************************
// CONNECTOR DEVICE IMPLEMENTATION
@@ -63,33 +68,50 @@ DEFINE_DEVICE_TYPE(APPLE2_GAMEIO, apple2_gameio_device, "a2gameio", "Apple II Ga
apple2_gameio_device::apple2_gameio_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock)
: device_t(mconfig, APPLE2_GAMEIO, tag, owner, clock)
- , device_slot_interface(mconfig, *this)
+ , device_single_card_slot_interface<device_a2gameio_interface>(mconfig, *this)
+ , m_screen(*this, finder_base::DUMMY_TAG)
, m_intf(nullptr)
+ , m_sw_pullups(false)
{
}
void apple2_gameio_device::iiandplus_options(device_slot_interface &slot)
{
slot.option_add("joy", APPLE2_JOYSTICK);
+ slot.option_add("paddles", APPLE2_PADDLES);
slot.option_add("joyport", APPLE2_JOYPORT);
+ slot.option_add("joyport_paddles", APPLE2_JOYPORT_PADDLES);
+ slot.option_add("gizmo", APPLE2_GIZMO);
slot.option_add("compeyes", APPLE2_COMPUTEREYES);
+ slot.option_add("wicojoy", APPLE2_WICO_JOYSTICK);
+ slot.option_add("brightpen", APPLE2_BRIGHTPEN);
}
void apple2_gameio_device::default_options(device_slot_interface &slot)
{
slot.option_add("joy", APPLE2_JOYSTICK);
+ slot.option_add("paddles", APPLE2_PADDLES);
+ slot.option_add("gizmo", APPLE2_GIZMO);
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 = dynamic_cast<device_a2gameio_interface *>(get_card_device());
+ m_intf = get_card_device();
}
void apple2_gameio_device::device_resolve_objects()
{
- if (m_intf != nullptr)
+ if (m_intf) {
m_intf->m_connector = this;
+ m_intf->set_screen(m_screen);
+ }
}
void apple2_gameio_device::device_start()
@@ -133,7 +155,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();
@@ -141,7 +163,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();
@@ -149,7 +171,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();
@@ -157,7 +179,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();
@@ -165,37 +187,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);
@@ -207,7 +229,7 @@ WRITE_LINE_MEMBER(apple2_gameio_device::strobe_w)
//**************************************************************************
device_a2gameio_interface::device_a2gameio_interface(const machine_config &mconfig, device_t &device)
- : device_slot_card_interface(mconfig, device)
+ : device_interface(device, "a2gameio")
, m_connector(nullptr)
{
}
diff --git a/src/devices/bus/a2gameio/gameio.h b/src/devices/bus/a2gameio/gameio.h
index e2bc7e512ea..7c2dcbd5925 100644
--- a/src/devices/bus/a2gameio/gameio.h
+++ b/src/devices/bus/a2gameio/gameio.h
@@ -11,6 +11,7 @@
#pragma once
+#include "screen.h"
//**************************************************************************
// TYPE DEFINITIONS
@@ -21,7 +22,7 @@ class device_a2gameio_interface;
// ======================> apple2_gameio_device
-class apple2_gameio_device : public device_t, public device_slot_interface
+class apple2_gameio_device : public device_t, public device_single_card_slot_interface<device_a2gameio_interface>
{
public:
// construction/destruction
@@ -37,6 +38,13 @@ public:
set_fixed(false);
}
+ template <typename T, typename U>
+ apple2_gameio_device(const machine_config &mconfig, const char *tag, device_t *owner, T &&screen_tag, U &&opts, const char *dflt)
+ : apple2_gameio_device(mconfig, tag, owner, opts, dflt)
+ {
+ m_screen.set_tag(std::forward<T>(screen_tag));
+ }
+
// configuration
void set_sw_pullups(bool enabled) { m_sw_pullups = enabled; }
bool has_sw_pullups() const { return m_sw_pullups; }
@@ -44,6 +52,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,26 +61,31 @@ 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); }
protected:
// device-level overrides
virtual void device_config_complete() override;
- virtual void device_resolve_objects() override;
- virtual void device_start() override;
+ virtual void device_resolve_objects() override ATTR_COLD;
+ virtual void device_start() override ATTR_COLD;
+
+ optional_device<screen_device> m_screen;
private:
// selected device
@@ -82,33 +96,37 @@ private:
// ======================> device_a2gameio_interface
-class device_a2gameio_interface : public device_slot_card_interface
+class device_a2gameio_interface : public device_interface
{
friend class apple2_gameio_device;
+public:
+ virtual ~device_a2gameio_interface();
+
protected:
// construction/destruction
device_a2gameio_interface(const machine_config &mconfig, device_t &device);
- virtual ~device_a2gameio_interface();
// optional input overrides
virtual u8 pdl0_r() { return 0; }
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) { }
+
+ void set_screen(screen_device *screen) { m_screen = screen; }
+ screen_device *m_screen;
private:
apple2_gameio_device *m_connector;
};
diff --git a/src/devices/bus/a2gameio/gizmo.cpp b/src/devices/bus/a2gameio/gizmo.cpp
new file mode 100644
index 00000000000..d1e1ee52eae
--- /dev/null
+++ b/src/devices/bus/a2gameio/gizmo.cpp
@@ -0,0 +1,106 @@
+// license:BSD-3-Clause
+// copyright-holders:R. Belmont
+/*********************************************************************
+
+ gizmo.cpp - HAL Labs Gizmo digital joystick adapter
+ Used by Vindicator and Super Taxman 2.
+
+*********************************************************************/
+
+#include "emu.h"
+#include "bus/a2gameio/gizmo.h"
+
+
+namespace {
+
+// ======================> apple2_gizmo_device
+
+class apple2_gizmo_device : public device_t, public device_a2gameio_interface
+{
+public:
+ // construction/destruction
+ apple2_gizmo_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock);
+
+protected:
+ // device-level overrides
+ virtual ioport_constructor device_input_ports() const override ATTR_COLD;
+ virtual void device_start() override ATTR_COLD;
+
+ // device_a2gameio_interface overrides
+ 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
+ required_ioport m_player1;
+ int m_an0, m_an1, m_an2;
+};
+
+//**************************************************************************
+// INPUT PORTS
+//**************************************************************************
+
+static INPUT_PORTS_START( apple2_gizmo )
+ PORT_START("joystick_p1")
+ PORT_BIT( 0x01, IP_ACTIVE_HIGH, IPT_JOYSTICK_UP )
+ PORT_BIT( 0x02, IP_ACTIVE_HIGH, IPT_JOYSTICK_RIGHT )
+ PORT_BIT( 0x04, IP_ACTIVE_HIGH, IPT_JOYSTICK_DOWN )
+ PORT_BIT( 0x08, IP_ACTIVE_HIGH, IPT_JOYSTICK_LEFT )
+ PORT_BIT( 0x10, IP_ACTIVE_HIGH, IPT_BUTTON1 )
+INPUT_PORTS_END
+
+//**************************************************************************
+// DEVICE IMPLEMENTATION
+//**************************************************************************
+
+apple2_gizmo_device::apple2_gizmo_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock)
+ : device_t(mconfig, APPLE2_GIZMO, tag, owner, clock)
+ , device_a2gameio_interface(mconfig, *this)
+ , m_player1(*this, "joystick_p1")
+{
+}
+
+ioport_constructor apple2_gizmo_device::device_input_ports() const
+{
+ return INPUT_PORTS_NAME(apple2_gizmo);
+}
+
+void apple2_gizmo_device::device_start()
+{
+ save_item(NAME(m_an0));
+ save_item(NAME(m_an1));
+ save_item(NAME(m_an2));
+}
+
+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)]);
+}
+
+void apple2_gizmo_device::an0_w(int state)
+{
+ m_an0 = state;
+}
+
+void apple2_gizmo_device::an1_w(int state)
+{
+ m_an1 = state;
+}
+
+void apple2_gizmo_device::an2_w(int state)
+{
+ m_an2 = state;
+}
+
+} // anonymous namespace
+
+
+//**************************************************************************
+// GLOBAL VARIABLES
+//**************************************************************************
+
+// device type definition
+DEFINE_DEVICE_TYPE_PRIVATE(APPLE2_GIZMO, device_a2gameio_interface, apple2_gizmo_device, "a2gizmo", "HAL Labs Gizmo")
diff --git a/src/devices/bus/a2gameio/gizmo.h b/src/devices/bus/a2gameio/gizmo.h
new file mode 100644
index 00000000000..c304b39a6e9
--- /dev/null
+++ b/src/devices/bus/a2gameio/gizmo.h
@@ -0,0 +1,20 @@
+// license:BSD-3-Clause
+// copyright-holders:R. Belmont
+/*********************************************************************
+
+ gizmo.h - HAL Labs Gizmo digital joystick adapter
+ Used by Vindicator and Super Taxman 2.
+
+*********************************************************************/
+
+#ifndef MAME_BUS_A2GAMEIO_GIZMO_H
+#define MAME_BUS_A2GAMEIO_GIZMO_H
+
+#pragma once
+
+#include "bus/a2gameio/gameio.h"
+
+// device type declaration
+DECLARE_DEVICE_TYPE(APPLE2_GIZMO, device_a2gameio_interface)
+
+#endif // MAME_BUS_A2GAMEIO_GIZMO_H
diff --git a/src/devices/bus/a2gameio/joyport.cpp b/src/devices/bus/a2gameio/joyport.cpp
index 9ed05796447..7ff0e7a9adc 100644
--- a/src/devices/bus/a2gameio/joyport.cpp
+++ b/src/devices/bus/a2gameio/joyport.cpp
@@ -16,20 +16,34 @@
#include "emu.h"
#include "bus/a2gameio/joyport.h"
-//**************************************************************************
-// GLOBAL VARIABLES
-//**************************************************************************
-// device type definition
-DEFINE_DEVICE_TYPE(APPLE2_JOYPORT, apple2_joyport_device, "a2joyprt", "Sirius JoyPort")
+namespace {
-//**************************************************************************
-// PARAMETERS
-//**************************************************************************
+// ======================> apple2_joyport_device
-#define JOYSTICK_DELTA 80
-#define JOYSTICK_SENSITIVITY 50
-#define JOYSTICK_AUTOCENTER 80
+class apple2_joyport_device : public device_t, public device_a2gameio_interface
+{
+public:
+ // construction/destruction
+ apple2_joyport_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock);
+
+protected:
+ // device-level overrides
+ virtual ioport_constructor device_input_ports() const override ATTR_COLD;
+ virtual void device_start() override ATTR_COLD;
+
+ // device_a2gameio_interface overrides
+ 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
+ required_ioport m_player1, m_player2;
+ int m_an0, m_an1;
+};
//**************************************************************************
// INPUT PORTS
@@ -74,33 +88,43 @@ 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;
}
+
+} // anonymous namespace
+
+
+//**************************************************************************
+// GLOBAL VARIABLES
+//**************************************************************************
+
+// device type definition
+DEFINE_DEVICE_TYPE_PRIVATE(APPLE2_JOYPORT, device_a2gameio_interface, apple2_joyport_device, "a2joyprt", "Sirius JoyPort with Atari joysticks")
diff --git a/src/devices/bus/a2gameio/joyport.h b/src/devices/bus/a2gameio/joyport.h
index 0e1b9e1a8dd..c6cb526c211 100644
--- a/src/devices/bus/a2gameio/joyport.h
+++ b/src/devices/bus/a2gameio/joyport.h
@@ -13,33 +13,7 @@
#include "bus/a2gameio/gameio.h"
-// ======================> apple2_joyport_device
-
-class apple2_joyport_device : public device_t, public device_a2gameio_interface
-{
-public:
- // construction/destruction
- apple2_joyport_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock);
-
-protected:
- // device-level overrides
- virtual ioport_constructor device_input_ports() const override;
- 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;
-
-private:
- // input ports
- required_ioport m_player1, m_player2;
- int m_an0, m_an1;
-};
-
// device type declaration
-DECLARE_DEVICE_TYPE(APPLE2_JOYPORT, apple2_joyport_device)
+DECLARE_DEVICE_TYPE(APPLE2_JOYPORT, device_a2gameio_interface)
#endif // MAME_BUS_A2GAMEIO_JOYPORT_H
diff --git a/src/devices/bus/a2gameio/joyport_paddles.cpp b/src/devices/bus/a2gameio/joyport_paddles.cpp
new file mode 100644
index 00000000000..d16a5d042d9
--- /dev/null
+++ b/src/devices/bus/a2gameio/joyport_paddles.cpp
@@ -0,0 +1,133 @@
+// license:BSD-3-Clause
+// copyright-holders:R. Belmont
+/*********************************************************************
+
+ Sirius JoyPort with 4 Apple II paddles connected
+
+*********************************************************************/
+
+#include "emu.h"
+#include "bus/a2gameio/joyport_paddles.h"
+
+
+namespace {
+
+// ======================> apple2_joyport_paddles_device
+
+class apple2_joyport_paddles_device : public device_t, public device_a2gameio_interface
+{
+public:
+ // construction/destruction
+ apple2_joyport_paddles_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock);
+
+protected:
+ // device_t implementation
+ virtual ioport_constructor device_input_ports() const override ATTR_COLD;
+ virtual void device_start() override ATTR_COLD;
+
+ // device_a2gameio_interface implementation
+ virtual u8 pdl0_r() override;
+ virtual u8 pdl1_r() override;
+ virtual u8 pdl2_r() override;
+ virtual u8 pdl3_r() override;
+ virtual int sw0_r() override;
+ virtual int sw1_r() override;
+ virtual void an0_w(int state) override;
+
+private:
+ // input ports
+ required_ioport_array<4> m_pdl;
+ required_ioport m_buttons;
+ int m_an0;
+};
+
+//**************************************************************************
+// INPUT PORTS
+//**************************************************************************
+
+static INPUT_PORTS_START( apple2_joyport_paddles )
+ PORT_START("paddle_1")
+ PORT_BIT( 0xff, 0x80, IPT_PADDLE) PORT_PLAYER(1) PORT_SENSITIVITY(30) PORT_KEYDELTA(20) PORT_MINMAX(0, 255)
+
+ PORT_START("paddle_2")
+ PORT_BIT( 0xff, 0x80, IPT_PADDLE) PORT_PLAYER(2) PORT_SENSITIVITY(30) PORT_KEYDELTA(20) PORT_MINMAX(0, 255)
+
+ PORT_START("paddle_3")
+ PORT_BIT( 0xff, 0x80, IPT_PADDLE) PORT_PLAYER(3) PORT_SENSITIVITY(30) PORT_KEYDELTA(20) PORT_MINMAX(0, 255)
+
+ PORT_START("paddle_4")
+ PORT_BIT( 0xff, 0x80, IPT_PADDLE) PORT_PLAYER(4) PORT_SENSITIVITY(30) PORT_KEYDELTA(20) PORT_MINMAX(0, 255)
+
+ PORT_START("paddle_buttons")
+ PORT_BIT( 0x10, IP_ACTIVE_HIGH, IPT_BUTTON1) PORT_PLAYER(1)
+ PORT_BIT( 0x20, IP_ACTIVE_HIGH, IPT_BUTTON1) PORT_PLAYER(2)
+ PORT_BIT( 0x40, IP_ACTIVE_HIGH, IPT_BUTTON1) PORT_PLAYER(3)
+ PORT_BIT( 0x80, IP_ACTIVE_HIGH, IPT_BUTTON1) PORT_PLAYER(4)
+INPUT_PORTS_END
+
+//**************************************************************************
+// DEVICE IMPLEMENTATION
+//**************************************************************************
+
+apple2_joyport_paddles_device::apple2_joyport_paddles_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock)
+ : device_t(mconfig, APPLE2_JOYPORT_PADDLES, tag, owner, clock)
+ , device_a2gameio_interface(mconfig, *this)
+ , m_pdl(*this, "paddle_%u", 1U)
+ , m_buttons(*this, "paddle_buttons")
+{
+}
+
+ioport_constructor apple2_joyport_paddles_device::device_input_ports() const
+{
+ return INPUT_PORTS_NAME(apple2_joyport_paddles);
+}
+
+void apple2_joyport_paddles_device::device_start()
+{
+ save_item(NAME(m_an0));
+}
+
+u8 apple2_joyport_paddles_device::pdl0_r()
+{
+ return m_pdl[0]->read();
+}
+
+u8 apple2_joyport_paddles_device::pdl1_r()
+{
+ return m_pdl[1]->read();
+}
+
+u8 apple2_joyport_paddles_device::pdl2_r()
+{
+ return m_pdl[2]->read();
+}
+
+u8 apple2_joyport_paddles_device::pdl3_r()
+{
+ return m_pdl[3]->read();
+}
+
+int apple2_joyport_paddles_device::sw0_r()
+{
+ return m_an0 ? BIT(m_buttons->read(), 6) : BIT(m_buttons->read(), 4);
+}
+
+int apple2_joyport_paddles_device::sw1_r()
+{
+ return m_an0 ? BIT(m_buttons->read(), 7) : BIT(m_buttons->read(), 5);
+}
+
+void apple2_joyport_paddles_device::an0_w(int state)
+{
+ m_an0 = state;
+}
+
+} // anonymous namespace
+
+
+//**************************************************************************
+// GLOBAL VARIABLES
+//**************************************************************************
+
+// device type definition
+DEFINE_DEVICE_TYPE_PRIVATE(APPLE2_JOYPORT_PADDLES, device_a2gameio_interface, apple2_joyport_paddles_device, "a2joyprtpdls", "Sirius JoyPort with Apple II paddles")
diff --git a/src/devices/bus/a2gameio/joyport_paddles.h b/src/devices/bus/a2gameio/joyport_paddles.h
new file mode 100644
index 00000000000..01380a6198c
--- /dev/null
+++ b/src/devices/bus/a2gameio/joyport_paddles.h
@@ -0,0 +1,19 @@
+// license:BSD-3-Clause
+// copyright-holders:R. Belmont
+/*********************************************************************
+
+ Sirius JoyPort with 4 Apple II paddles connected
+
+*********************************************************************/
+
+#ifndef MAME_BUS_A2GAMEIO_JOYPORT_PADDLES_H
+#define MAME_BUS_A2GAMEIO_JOYPORT_PADDLES_H
+
+#pragma once
+
+#include "bus/a2gameio/gameio.h"
+
+// device type declaration
+DECLARE_DEVICE_TYPE(APPLE2_JOYPORT_PADDLES, device_a2gameio_interface)
+
+#endif // MAME_BUS_A2GAMEIO_JOYPORT_PADDLES_H
diff --git a/src/devices/bus/a2gameio/joystick.cpp b/src/devices/bus/a2gameio/joystick.cpp
index 02f256c8303..59c2a71d302 100644
--- a/src/devices/bus/a2gameio/joystick.cpp
+++ b/src/devices/bus/a2gameio/joystick.cpp
@@ -9,12 +9,37 @@
#include "emu.h"
#include "bus/a2gameio/joystick.h"
-//**************************************************************************
-// GLOBAL VARIABLES
-//**************************************************************************
+namespace {
-// device type definition
-DEFINE_DEVICE_TYPE(APPLE2_JOYSTICK, apple2_joystick_device, "a2joy", "Apple II analog joysticks")
+// ======================> apple2_joystick_device
+
+class apple2_joystick_device : public device_t, public device_a2gameio_interface
+{
+public:
+ // construction/destruction
+ apple2_joystick_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock);
+
+protected:
+ // device-level overrides
+ virtual ioport_constructor device_input_ports() const override ATTR_COLD;
+ virtual void device_start() override ATTR_COLD;
+
+ // device_a2gameio_interface overrides
+ virtual u8 pdl0_r() override;
+ virtual u8 pdl1_r() override;
+ virtual u8 pdl2_r() override;
+ virtual u8 pdl3_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
+ required_ioport_array<2> m_joy_x;
+ required_ioport_array<2> m_joy_y;
+ required_ioport m_buttons;
+};
//**************************************************************************
// PARAMETERS
@@ -35,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")
@@ -44,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")
@@ -53,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")
@@ -61,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)
@@ -109,25 +128,35 @@ u8 apple2_joystick_device::pdl2_r()
u8 apple2_joystick_device::pdl3_r()
{
- return m_joy_x[1]->read();
+ 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);
}
+
+} // anonymous namespace
+
+
+//**************************************************************************
+// GLOBAL VARIABLES
+//**************************************************************************
+
+// device type definition
+DEFINE_DEVICE_TYPE_PRIVATE(APPLE2_JOYSTICK, device_a2gameio_interface, apple2_joystick_device, "a2joy", "Apple II analog joysticks")
diff --git a/src/devices/bus/a2gameio/joystick.h b/src/devices/bus/a2gameio/joystick.h
index 59969c0c1b3..b42a91318e7 100644
--- a/src/devices/bus/a2gameio/joystick.h
+++ b/src/devices/bus/a2gameio/joystick.h
@@ -13,37 +13,7 @@
#include "bus/a2gameio/gameio.h"
-// ======================> apple2_joystick_device
-
-class apple2_joystick_device : public device_t, public device_a2gameio_interface
-{
-public:
- // construction/destruction
- apple2_joystick_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock);
-
-protected:
- // device-level overrides
- virtual ioport_constructor device_input_ports() const override;
- virtual void device_start() override;
-
- // device_a2gameio_interface overrides
- virtual u8 pdl0_r() override;
- 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;
-
-private:
- // input ports
- required_ioport_array<2> m_joy_x;
- required_ioport_array<2> m_joy_y;
- required_ioport m_buttons;
-};
-
// device type declaration
-DECLARE_DEVICE_TYPE(APPLE2_JOYSTICK, apple2_joystick_device)
+DECLARE_DEVICE_TYPE(APPLE2_JOYSTICK, device_a2gameio_interface)
#endif // MAME_BUS_A2GAMEIO_JOYSTICK_H
diff --git a/src/devices/bus/a2gameio/paddles.cpp b/src/devices/bus/a2gameio/paddles.cpp
new file mode 100644
index 00000000000..095739fcb29
--- /dev/null
+++ b/src/devices/bus/a2gameio/paddles.cpp
@@ -0,0 +1,136 @@
+// license:BSD-3-Clause
+// copyright-holders:R. Belmont
+/*********************************************************************
+
+ Apple II paddles
+
+*********************************************************************/
+
+#include "emu.h"
+#include "bus/a2gameio/paddles.h"
+
+namespace {
+
+// ======================> apple2_paddles_device
+
+class apple2_paddles_device : public device_t, public device_a2gameio_interface
+{
+public:
+ // construction/destruction
+ apple2_paddles_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock);
+
+protected:
+ // device-level overrides
+ virtual ioport_constructor device_input_ports() const override ATTR_COLD;
+ virtual void device_start() override ATTR_COLD;
+
+ // device_a2gameio_interface overrides
+ virtual u8 pdl0_r() override;
+ virtual u8 pdl1_r() override;
+ virtual u8 pdl2_r() override;
+ virtual u8 pdl3_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
+ required_ioport_array<4> m_pdl;
+ required_ioport m_buttons;
+};
+
+//**************************************************************************
+// INPUT PORTS
+//**************************************************************************
+
+static INPUT_PORTS_START( apple2_paddles )
+ PORT_START("paddle_1")
+ PORT_BIT( 0xff, 0x80, IPT_PADDLE) PORT_PLAYER(1) PORT_SENSITIVITY(30) PORT_KEYDELTA(20) PORT_MINMAX(0, 255)
+
+ PORT_START("paddle_2")
+ PORT_BIT( 0xff, 0x80, IPT_PADDLE) PORT_PLAYER(2) PORT_SENSITIVITY(30) PORT_KEYDELTA(20) PORT_MINMAX(0, 255)
+
+ PORT_START("paddle_3")
+ PORT_BIT( 0xff, 0x80, IPT_PADDLE) PORT_PLAYER(3) PORT_SENSITIVITY(30) PORT_KEYDELTA(20) PORT_MINMAX(0, 255)
+
+ PORT_START("paddle_4")
+ PORT_BIT( 0xff, 0x80, IPT_PADDLE) PORT_PLAYER(4) PORT_SENSITIVITY(30) PORT_KEYDELTA(20) PORT_MINMAX(0, 255)
+
+ PORT_START("paddle_buttons")
+ PORT_BIT( 0x10, IP_ACTIVE_HIGH, IPT_BUTTON1) PORT_PLAYER(1)
+ PORT_BIT( 0x20, IP_ACTIVE_HIGH, IPT_BUTTON1) PORT_PLAYER(2)
+ PORT_BIT( 0x40, IP_ACTIVE_HIGH, IPT_BUTTON1) PORT_PLAYER(3)
+ PORT_BIT( 0x80, IP_ACTIVE_HIGH, IPT_BUTTON1) PORT_PLAYER(4)
+INPUT_PORTS_END
+
+//**************************************************************************
+// DEVICE IMPLEMENTATION
+//**************************************************************************
+
+apple2_paddles_device::apple2_paddles_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock)
+ : device_t(mconfig, APPLE2_PADDLES, tag, owner, clock)
+ , device_a2gameio_interface(mconfig, *this)
+ , m_pdl(*this, "paddle_%u", 1U)
+ , m_buttons(*this, "paddle_buttons")
+{
+}
+
+ioport_constructor apple2_paddles_device::device_input_ports() const
+{
+ return INPUT_PORTS_NAME(apple2_paddles);
+}
+
+void apple2_paddles_device::device_start()
+{
+}
+
+u8 apple2_paddles_device::pdl0_r()
+{
+ return m_pdl[0]->read();
+}
+
+u8 apple2_paddles_device::pdl1_r()
+{
+ return m_pdl[1]->read();
+}
+
+u8 apple2_paddles_device::pdl2_r()
+{
+ return m_pdl[2]->read();
+}
+
+u8 apple2_paddles_device::pdl3_r()
+{
+ return m_pdl[3]->read();
+}
+
+int apple2_paddles_device::sw0_r()
+{
+ return BIT(m_buttons->read(), 4);
+}
+
+int apple2_paddles_device::sw1_r()
+{
+ return BIT(m_buttons->read(), 5);
+}
+
+int apple2_paddles_device::sw2_r()
+{
+ return BIT(m_buttons->read(), 6);
+}
+
+int apple2_paddles_device::sw3_r()
+{
+ return BIT(m_buttons->read(), 7);
+}
+
+} // anonymous namespace
+
+
+//**************************************************************************
+// GLOBAL VARIABLES
+//**************************************************************************
+
+// device type definition
+DEFINE_DEVICE_TYPE_PRIVATE(APPLE2_PADDLES, device_a2gameio_interface, apple2_paddles_device, "a2pdls", "Apple II paddles")
diff --git a/src/devices/bus/a2gameio/paddles.h b/src/devices/bus/a2gameio/paddles.h
new file mode 100644
index 00000000000..b9d91918c91
--- /dev/null
+++ b/src/devices/bus/a2gameio/paddles.h
@@ -0,0 +1,19 @@
+// license:BSD-3-Clause
+// copyright-holders:R. Belmont
+/*********************************************************************
+
+ Apple II paddles
+
+*********************************************************************/
+
+#ifndef MAME_BUS_A2GAMEIO_PADDLES_H
+#define MAME_BUS_A2GAMEIO_PADDLES_H
+
+#pragma once
+
+#include "bus/a2gameio/gameio.h"
+
+// device type declaration
+DECLARE_DEVICE_TYPE(APPLE2_PADDLES, device_a2gameio_interface)
+
+#endif // MAME_BUS_A2GAMEIO_PADDLES_H
diff --git a/src/devices/bus/a2gameio/wico_joystick.cpp b/src/devices/bus/a2gameio/wico_joystick.cpp
new file mode 100644
index 00000000000..b756b229cb8
--- /dev/null
+++ b/src/devices/bus/a2gameio/wico_joystick.cpp
@@ -0,0 +1,128 @@
+// license:BSD-3-Clause
+// copyright-holders:R. Belmont
+/*********************************************************************
+
+ Apple II Wico Command Control Joystick Adapter for Atari-style
+ digital joysticks
+
+*********************************************************************/
+
+#include "emu.h"
+#include "bus/a2gameio/wico_joystick.h"
+
+namespace {
+
+// ======================> apple2_wico_joystick_device
+
+class apple2_wico_joystick_device : public device_t, public device_a2gameio_interface
+{
+public:
+ // construction/destruction
+ apple2_wico_joystick_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock);
+
+protected:
+ // device_t implementation
+ virtual ioport_constructor device_input_ports() const override ATTR_COLD;
+ virtual void device_start() override ATTR_COLD;
+
+ // device_a2gameio_interface implementation
+ virtual u8 pdl0_r() override;
+ virtual u8 pdl1_r() override;
+ virtual u8 pdl2_r() override;
+ virtual u8 pdl3_r() override;
+ virtual int sw0_r() override;
+ virtual int sw1_r() override;
+
+private:
+ // input ports
+ required_ioport m_player1, m_player2;
+};
+
+//**************************************************************************
+// PARAMETERS
+//**************************************************************************
+
+#define JOYSTICK_DELTA 80
+#define JOYSTICK_SENSITIVITY 50
+#define JOYSTICK_AUTOCENTER 80
+
+//**************************************************************************
+// INPUT PORTS
+//**************************************************************************
+
+static INPUT_PORTS_START( apple2_wico_joystick )
+ PORT_START("joystick_p1")
+ PORT_BIT( 0x01, IP_ACTIVE_LOW, IPT_JOYSTICK_UP )
+ PORT_BIT( 0x02, IP_ACTIVE_LOW, IPT_JOYSTICK_RIGHT )
+ PORT_BIT( 0x04, IP_ACTIVE_LOW, IPT_JOYSTICK_DOWN )
+ PORT_BIT( 0x08, IP_ACTIVE_LOW, IPT_JOYSTICK_LEFT )
+ PORT_BIT( 0x10, IP_ACTIVE_LOW, IPT_BUTTON1 )
+
+ PORT_START("joystick_p2")
+ PORT_BIT( 0x01, IP_ACTIVE_LOW, IPT_JOYSTICK_UP ) PORT_PLAYER(2)
+ PORT_BIT( 0x02, IP_ACTIVE_LOW, IPT_JOYSTICK_RIGHT ) PORT_PLAYER(2)
+ PORT_BIT( 0x04, IP_ACTIVE_LOW, IPT_JOYSTICK_DOWN ) PORT_PLAYER(2)
+ PORT_BIT( 0x08, IP_ACTIVE_LOW, IPT_JOYSTICK_LEFT ) PORT_PLAYER(2)
+ PORT_BIT( 0x10, IP_ACTIVE_LOW, IPT_BUTTON1 ) PORT_PLAYER(2)
+INPUT_PORTS_END
+
+//**************************************************************************
+// DEVICE IMPLEMENTATION
+//**************************************************************************
+
+apple2_wico_joystick_device::apple2_wico_joystick_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock)
+ : device_t(mconfig, APPLE2_WICO_JOYSTICK, tag, owner, clock)
+ , device_a2gameio_interface(mconfig, *this)
+ , m_player1(*this, "joystick_p1")
+ , m_player2(*this, "joystick_p2")
+{
+}
+
+ioport_constructor apple2_wico_joystick_device::device_input_ports() const
+{
+ return INPUT_PORTS_NAME(apple2_wico_joystick);
+}
+
+void apple2_wico_joystick_device::device_start()
+{
+}
+
+u8 apple2_wico_joystick_device::pdl0_r()
+{
+ return !BIT(m_player1->read(), 3) ? 0x00 : !BIT(m_player1->read(), 1) ? 0xff : 0x80;
+}
+
+u8 apple2_wico_joystick_device::pdl1_r()
+{
+ return !BIT(m_player1->read(), 0) ? 0x00 : !BIT(m_player1->read(), 2) ? 0xff : 0x80;
+}
+
+u8 apple2_wico_joystick_device::pdl2_r()
+{
+ return !BIT(m_player2->read(), 3) ? 0x00 : !BIT(m_player2->read(), 1) ? 0xff : 0x80;
+}
+
+u8 apple2_wico_joystick_device::pdl3_r()
+{
+ return !BIT(m_player2->read(), 0) ? 0x00 : !BIT(m_player2->read(), 2) ? 0xff : 0x80;
+}
+
+int apple2_wico_joystick_device::sw0_r()
+{
+ return !BIT(m_player1->read(), 4);
+}
+
+int apple2_wico_joystick_device::sw1_r()
+{
+ return !BIT(m_player2->read(), 4);
+}
+
+} // anonymous namespace
+
+
+//**************************************************************************
+// GLOBAL VARIABLES
+//**************************************************************************
+
+// device type definition
+DEFINE_DEVICE_TYPE_PRIVATE(APPLE2_WICO_JOYSTICK, device_a2gameio_interface, apple2_wico_joystick_device, "a2wicojoy", "Wico Command Control Joystick Adapter")
diff --git a/src/devices/bus/a2gameio/wico_joystick.h b/src/devices/bus/a2gameio/wico_joystick.h
new file mode 100644
index 00000000000..4c7203a3175
--- /dev/null
+++ b/src/devices/bus/a2gameio/wico_joystick.h
@@ -0,0 +1,20 @@
+// license:BSD-3-Clause
+// copyright-holders:R. Belmont
+/*********************************************************************
+
+ Apple II Wico Command Control Joystick Adapter for Atari-style
+ digital joysticks
+
+*********************************************************************/
+
+#ifndef MAME_BUS_A2GAMEIO_WICO_JOYSTICK_H
+#define MAME_BUS_A2GAMEIO_WICO_JOYSTICK_H
+
+#pragma once
+
+#include "bus/a2gameio/gameio.h"
+
+// device type declaration
+DECLARE_DEVICE_TYPE(APPLE2_WICO_JOYSTICK, device_a2gameio_interface)
+
+#endif // MAME_BUS_A2GAMEIO_WICO_JOYSTICK_H
diff --git a/src/devices/bus/a7800/a78_slot.cpp b/src/devices/bus/a7800/a78_slot.cpp
index e33048ec40c..2f407adb374 100644
--- a/src/devices/bus/a7800/a78_slot.cpp
+++ b/src/devices/bus/a7800/a78_slot.cpp
@@ -25,10 +25,11 @@
***********************************************************************************************************/
-
#include "emu.h"
#include "a78_slot.h"
+#include "multibyte.h"
+
//**************************************************************************
// GLOBAL VARIABLES
//**************************************************************************
@@ -41,11 +42,11 @@ DEFINE_DEVICE_TYPE(A78_CART_SLOT, a78_cart_slot_device, "a78_cart_slot", "Atari
//-------------------------------------------------
device_a78_cart_interface::device_a78_cart_interface (const machine_config &mconfig, device_t &device)
- : device_slot_card_interface(mconfig, device),
- m_rom(nullptr),
- m_rom_size(0),
- m_base_rom(0x8000),
- m_bank_mask(0)
+ : device_interface(device, "a78cart")
+ , m_rom(nullptr)
+ , m_rom_size(0)
+ , m_base_rom(0x8000)
+ , m_bank_mask(0)
{
}
@@ -62,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
@@ -114,7 +115,7 @@ void device_a78_cart_interface::nvram_alloc(uint32_t size)
//-------------------------------------------------
a78_cart_slot_device::a78_cart_slot_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
: device_t(mconfig, A78_CART_SLOT, tag, owner, clock)
- , device_image_interface(mconfig, *this)
+ , device_cartrom_image_interface(mconfig, *this)
, device_slot_interface(mconfig, *this)
, m_cart(nullptr)
, m_type(0)
@@ -315,7 +316,7 @@ static int a78_get_pcb_id(const char *slot)
{
for (auto & elem : slot_list)
{
- if (!core_stricmp(elem.slot_option, slot))
+ if (!strcmp(elem.slot_option, slot))
return elem.pcb_id;
}
@@ -333,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)
{
@@ -346,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)
@@ -366,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");
@@ -380,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)
{
@@ -444,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)
@@ -464,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());
}
@@ -485,18 +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");
- 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());
}
@@ -508,16 +507,17 @@ std::string a78_cart_slot_device::get_default_card_software(get_default_card_sof
{
if (hook.image_file())
{
- const char *slot_string;
- std::vector<uint8_t> head(128);
- int type = A78_TYPE0, mapper;
+ uint64_t len;
+ hook.image_file()->length(len); // FIXME: check error return
// Load and check the header
- hook.image_file()->read(&head[0], 128);
+ uint8_t head[128];
+ /*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
- 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)
{
case 0x0000:
@@ -534,7 +534,7 @@ std::string a78_cart_slot_device::get_default_card_software(get_default_card_sof
break;
case 0x0022:
case 0x0026:
- if (hook.image_file()->size() > 0x40000)
+ if (len > 0x40000)
type = A78_MEGACART;
else
type = A78_VERSABOARD;
@@ -560,7 +560,7 @@ std::string a78_cart_slot_device::get_default_card_software(get_default_card_sof
type = A78_TYPE8;
logerror("Cart type: %x\n", type);
- slot_string = a78_get_slot(type);
+ char const *const slot_string = a78_get_slot(type);
return std::string(slot_string);
}
@@ -573,34 +573,34 @@ std::string a78_cart_slot_device::get_default_card_software(get_default_card_sof
read
-------------------------------------------------*/
-READ8_MEMBER(a78_cart_slot_device::read_04xx)
+uint8_t a78_cart_slot_device::read_04xx(offs_t offset)
{
if (m_cart)
- return m_cart->read_04xx(space, offset, mem_mask);
+ return m_cart->read_04xx(offset);
else
return 0xff;
}
-READ8_MEMBER(a78_cart_slot_device::read_10xx)
+uint8_t a78_cart_slot_device::read_10xx(offs_t offset)
{
if (m_cart)
- return m_cart->read_10xx(space, offset, mem_mask);
+ return m_cart->read_10xx(offset);
else
return 0xff;
}
-READ8_MEMBER(a78_cart_slot_device::read_30xx)
+uint8_t a78_cart_slot_device::read_30xx(offs_t offset)
{
if (m_cart)
- return m_cart->read_30xx(space, offset, mem_mask);
+ return m_cart->read_30xx(offset);
else
return 0xff;
}
-READ8_MEMBER(a78_cart_slot_device::read_40xx)
+uint8_t a78_cart_slot_device::read_40xx(offs_t offset)
{
if (m_cart)
- return m_cart->read_40xx(space, offset, mem_mask);
+ return m_cart->read_40xx(offset);
else
return 0xff;
}
@@ -610,28 +610,28 @@ READ8_MEMBER(a78_cart_slot_device::read_40xx)
write
-------------------------------------------------*/
-WRITE8_MEMBER(a78_cart_slot_device::write_04xx)
+void a78_cart_slot_device::write_04xx(offs_t offset, uint8_t data)
{
if (m_cart)
- m_cart->write_04xx(space, offset, data, mem_mask);
+ m_cart->write_04xx(offset, data);
}
-WRITE8_MEMBER(a78_cart_slot_device::write_10xx)
+void a78_cart_slot_device::write_10xx(offs_t offset, uint8_t data)
{
if (m_cart)
- m_cart->write_10xx(space, offset, data, mem_mask);
+ m_cart->write_10xx(offset, data);
}
-WRITE8_MEMBER(a78_cart_slot_device::write_30xx)
+void a78_cart_slot_device::write_30xx(offs_t offset, uint8_t data)
{
if (m_cart)
- m_cart->write_30xx(space, offset, data, mem_mask);
+ m_cart->write_30xx(offset, data);
}
-WRITE8_MEMBER(a78_cart_slot_device::write_40xx)
+void a78_cart_slot_device::write_40xx(offs_t offset, uint8_t data)
{
if (m_cart)
- m_cart->write_40xx(space, offset, data, mem_mask);
+ m_cart->write_40xx(offset, data);
}
@@ -700,11 +700,11 @@ WRITE8_MEMBER(a78_cart_slot_device::write_40xx)
-------------------------------------------------*/
-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];
@@ -790,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");
@@ -807,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 4b091161bf1..c3f6c5c6833 100644
--- a/src/devices/bus/a7800/a78_slot.h
+++ b/src/devices/bus/a7800/a78_slot.h
@@ -5,15 +5,13 @@
#pragma once
-#include "softlist_dev.h"
+#include "imagedev/cartrom.h"
/***************************************************************************
TYPE DEFINITIONS
***************************************************************************/
-#define A78SLOT_ROM_REGION_TAG ":cart:rom"
-
/* PCB */
enum
{
@@ -42,23 +40,23 @@ enum
// ======================> device_a78_cart_interface
-class device_a78_cart_interface : public device_slot_card_interface
+class device_a78_cart_interface : public device_interface
{
public:
// construction/destruction
virtual ~device_a78_cart_interface();
// memory accessor
- virtual DECLARE_READ8_MEMBER(read_04xx) { return 0xff; }
- virtual DECLARE_READ8_MEMBER(read_10xx) { return 0xff; }
- virtual DECLARE_READ8_MEMBER(read_30xx) { return 0xff; }
- virtual DECLARE_READ8_MEMBER(read_40xx) { return 0xff; }
- virtual DECLARE_WRITE8_MEMBER(write_04xx) {}
- virtual DECLARE_WRITE8_MEMBER(write_10xx) {}
- virtual DECLARE_WRITE8_MEMBER(write_30xx) {}
- virtual DECLARE_WRITE8_MEMBER(write_40xx) {}
-
- void rom_alloc(uint32_t size, const char *tag);
+ virtual uint8_t read_04xx(offs_t offset) { return 0xff; }
+ virtual uint8_t read_10xx(offs_t offset) { return 0xff; }
+ virtual uint8_t read_30xx(offs_t offset) { return 0xff; }
+ virtual uint8_t read_40xx(offs_t offset) { return 0xff; }
+ virtual void write_04xx(offs_t offset, uint8_t data) {}
+ virtual void write_10xx(offs_t offset, uint8_t data) {}
+ 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);
void ram_alloc(uint32_t size);
void nvram_alloc(uint32_t size);
uint8_t* get_rom_base() { return m_rom; }
@@ -85,64 +83,58 @@ protected:
// ======================> a78_cart_slot_device
class a78_cart_slot_device : public device_t,
- public device_image_interface,
+ public device_cartrom_image_interface,
public device_slot_interface
{
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();
- // 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 void call_unload() override;
- virtual const software_list_loader &get_software_list_loader() const override { return rom_software_list_loader::instance(); }
- int get_cart_type() { return m_type; };
- bool has_cart() { return m_cart != nullptr; }
+ virtual bool is_reset_on_load() const noexcept override { return true; }
+ virtual const char *image_interface() const noexcept override { return "a7800_cart"; }
+ virtual const char *file_extensions() const noexcept override { return "a78"; }
+ virtual u32 unhashed_header_length() const noexcept override { return 128; }
- virtual iodevice_t image_type() const override { return IO_CARTSLOT; }
- virtual bool is_readable() const override { return 1; }
- virtual bool is_writeable() const override { return 0; }
- virtual bool is_creatable() const override { return 0; }
- virtual bool must_be_loaded() const override { return 0; }
- virtual bool is_reset_on_load() const override { return 1; }
- virtual const char *image_interface() const override { return "a7800_cart"; }
- virtual const char *file_extensions() const override { return "bin,a78"; }
- virtual u32 unhashed_header_length() const 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; }
+ bool has_cart() { return m_cart != nullptr; }
+
// reading and writing
- virtual DECLARE_READ8_MEMBER(read_04xx);
- virtual DECLARE_READ8_MEMBER(read_10xx);
- virtual DECLARE_READ8_MEMBER(read_30xx);
- virtual DECLARE_READ8_MEMBER(read_40xx);
- virtual DECLARE_WRITE8_MEMBER(write_04xx);
- virtual DECLARE_WRITE8_MEMBER(write_10xx);
- virtual DECLARE_WRITE8_MEMBER(write_30xx);
- virtual DECLARE_WRITE8_MEMBER(write_40xx);
+ uint8_t read_04xx(offs_t offset);
+ uint8_t read_10xx(offs_t offset);
+ uint8_t read_30xx(offs_t offset);
+ uint8_t read_40xx(offs_t offset);
+ void write_04xx(offs_t offset, uint8_t data);
+ void write_10xx(offs_t offset, uint8_t data);
+ void write_30xx(offs_t offset, uint8_t data);
+ void write_40xx(offs_t offset, uint8_t data);
private:
- device_a78_cart_interface* m_cart;
- int m_type;
+ // device_t implementation
+ virtual void device_start() override ATTR_COLD;
- 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 0b76f7b2233..44f3d05027e 100644
--- a/src/devices/bus/a7800/cpuwiz.cpp
+++ b/src/devices/bus/a7800/cpuwiz.cpp
@@ -80,7 +80,7 @@ void a78_versaboard_device::device_reset()
// VersaBoard
-READ8_MEMBER(a78_versaboard_device::read_40xx)
+uint8_t a78_versaboard_device::read_40xx(offs_t offset)
{
if (offset < 0x4000)
return m_ram[offset + (m_ram_bank * 0x4000)];
@@ -90,7 +90,7 @@ READ8_MEMBER(a78_versaboard_device::read_40xx)
return m_rom[(offset & 0x3fff) + (m_bank_mask * 0x4000)]; // last bank
}
-WRITE8_MEMBER(a78_versaboard_device::write_40xx)
+void a78_versaboard_device::write_40xx(offs_t offset, uint8_t data)
{
if (offset < 0x4000)
m_ram[offset + (m_ram_bank * 0x4000)] = data;
@@ -105,7 +105,7 @@ WRITE8_MEMBER(a78_versaboard_device::write_40xx)
// MegaCart+
-WRITE8_MEMBER(a78_megacart_device::write_40xx)
+void a78_megacart_device::write_40xx(offs_t offset, uint8_t data)
{
if (offset < 0x4000)
m_ram[offset + (m_ram_bank * 0x4000)] = data;
@@ -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/cpuwiz.h b/src/devices/bus/a7800/cpuwiz.h
index e9f52a24d4f..83370f91c39 100644
--- a/src/devices/bus/a7800/cpuwiz.h
+++ b/src/devices/bus/a7800/cpuwiz.h
@@ -18,12 +18,12 @@ public:
a78_versaboard_device(const machine_config &mconfig, 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_start() override ATTR_COLD;
+ virtual void device_reset() override ATTR_COLD;
// reading and writing
- virtual DECLARE_READ8_MEMBER(read_40xx) override;
- virtual DECLARE_WRITE8_MEMBER(write_40xx) override;
+ virtual uint8_t read_40xx(offs_t offset) override;
+ virtual void write_40xx(offs_t offset, uint8_t data) override;
protected:
a78_versaboard_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock);
@@ -41,7 +41,7 @@ public:
a78_megacart_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
// reading and writing
- virtual DECLARE_WRITE8_MEMBER(write_40xx) override;
+ virtual void write_40xx(offs_t offset, uint8_t data) override;
};
@@ -56,11 +56,11 @@ public:
a78_rom_p450_vb_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
// reading and writing
- virtual DECLARE_READ8_MEMBER(read_04xx) override { if (offset >= 0x50 && offset < 0x60) return m_pokey450->read(offset & 0x0f); else return 0xff; }
- virtual DECLARE_WRITE8_MEMBER(write_04xx) override { if (offset >= 0x50 && offset < 0x60) m_pokey450->write(offset & 0x0f, data); }
+ virtual uint8_t read_04xx(offs_t offset) override { if (offset >= 0x50 && offset < 0x60) return m_pokey450->read(offset & 0x0f); else return 0xff; }
+ virtual void write_04xx(offs_t offset, uint8_t data) override { if (offset >= 0x50 && offset < 0x60) m_pokey450->write(offset & 0x0f, data); }
protected:
- virtual void device_add_mconfig(machine_config &config) override;
+ virtual void device_add_mconfig(machine_config &config) override ATTR_COLD;
required_device<pokey_device> m_pokey450;
};
diff --git a/src/devices/bus/a7800/hiscore.cpp b/src/devices/bus/a7800/hiscore.cpp
index 62630842e5c..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);
}
@@ -37,37 +37,37 @@ void a78_hiscore_device::device_add_mconfig(machine_config &config)
mapper specific handlers
-------------------------------------------------*/
-READ8_MEMBER(a78_hiscore_device::read_10xx)
+uint8_t a78_hiscore_device::read_10xx(offs_t offset)
{
return m_nvram[offset];
}
-WRITE8_MEMBER(a78_hiscore_device::write_10xx)
+void a78_hiscore_device::write_10xx(offs_t offset, uint8_t data)
{
m_nvram[offset] = data;
}
-READ8_MEMBER(a78_hiscore_device::read_30xx)
+uint8_t a78_hiscore_device::read_30xx(offs_t offset)
{
return m_rom[offset];
}
-READ8_MEMBER(a78_hiscore_device::read_04xx)
+uint8_t a78_hiscore_device::read_04xx(offs_t offset)
{
- return m_hscslot->read_04xx(space, offset);
+ return m_hscslot->read_04xx(offset);
}
-WRITE8_MEMBER(a78_hiscore_device::write_04xx)
+void a78_hiscore_device::write_04xx(offs_t offset, uint8_t data)
{
- m_hscslot->write_04xx(space, offset, data);
+ m_hscslot->write_04xx(offset, data);
}
-READ8_MEMBER(a78_hiscore_device::read_40xx)
+uint8_t a78_hiscore_device::read_40xx(offs_t offset)
{
- return m_hscslot->read_40xx(space, offset);
+ return m_hscslot->read_40xx(offset);
}
-WRITE8_MEMBER(a78_hiscore_device::write_40xx)
+void a78_hiscore_device::write_40xx(offs_t offset, uint8_t data)
{
- m_hscslot->write_40xx(space, offset, data);
+ m_hscslot->write_40xx(offset, data);
}
diff --git a/src/devices/bus/a7800/hiscore.h b/src/devices/bus/a7800/hiscore.h
index b26bea473db..9fbce46a3a3 100644
--- a/src/devices/bus/a7800/hiscore.h
+++ b/src/devices/bus/a7800/hiscore.h
@@ -18,16 +18,16 @@ public:
a78_hiscore_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
// reading and writing
- virtual DECLARE_READ8_MEMBER(read_04xx) override;
- virtual DECLARE_WRITE8_MEMBER(write_04xx) override;
- virtual DECLARE_READ8_MEMBER(read_10xx) override;
- virtual DECLARE_WRITE8_MEMBER(write_10xx) override;
- virtual DECLARE_READ8_MEMBER(read_30xx) override;
- virtual DECLARE_READ8_MEMBER(read_40xx) override;
- virtual DECLARE_WRITE8_MEMBER(write_40xx) override;
+ virtual uint8_t read_04xx(offs_t offset) override;
+ virtual void write_04xx(offs_t offset, uint8_t data) override;
+ virtual uint8_t read_10xx(offs_t offset) override;
+ virtual void write_10xx(offs_t offset, uint8_t data) override;
+ virtual uint8_t read_30xx(offs_t offset) override;
+ virtual uint8_t read_40xx(offs_t offset) override;
+ virtual void write_40xx(offs_t offset, uint8_t data) override;
protected:
- virtual void device_add_mconfig(machine_config &config) override;
+ virtual void device_add_mconfig(machine_config &config) override ATTR_COLD;
required_device<a78_cart_slot_device> m_hscslot;
};
diff --git a/src/devices/bus/a7800/rom.cpp b/src/devices/bus/a7800/rom.cpp
index 362902dbe51..45293f4260f 100644
--- a/src/devices/bus/a7800/rom.cpp
+++ b/src/devices/bus/a7800/rom.cpp
@@ -208,7 +208,7 @@ void a78_rom_act_device::device_reset()
-------------------------------------------------*/
-READ8_MEMBER(a78_rom_device::read_40xx)
+uint8_t a78_rom_device::read_40xx(offs_t offset)
{
if (offset + 0x4000 < m_base_rom)
return 0xff;
@@ -226,7 +226,7 @@ READ8_MEMBER(a78_rom_device::read_40xx)
-------------------------------------------------*/
-READ8_MEMBER(a78_rom_pokey_device::read_40xx)
+uint8_t a78_rom_pokey_device::read_40xx(offs_t offset)
{
if (offset < 0x4000)
return m_pokey->read(offset & 0x0f);
@@ -237,18 +237,17 @@ READ8_MEMBER(a78_rom_pokey_device::read_40xx)
return m_rom[offset + 0x4000 - m_base_rom];
}
-WRITE8_MEMBER(a78_rom_pokey_device::write_40xx)
+void a78_rom_pokey_device::write_40xx(offs_t offset, uint8_t data)
{
if (offset < 0x4000)
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);
}
/*-------------------------------------------------
@@ -264,7 +263,7 @@ void a78_rom_pokey_device::device_add_mconfig(machine_config &config)
-------------------------------------------------*/
-READ8_MEMBER(a78_rom_mram_device::read_40xx)
+uint8_t a78_rom_mram_device::read_40xx(offs_t offset)
{
if (offset < 0x4000)
return m_ram[offset & 0xfeff];
@@ -274,7 +273,7 @@ READ8_MEMBER(a78_rom_mram_device::read_40xx)
return m_rom[offset + 0x4000 - m_base_rom];
}
-WRITE8_MEMBER(a78_rom_mram_device::write_40xx)
+void a78_rom_mram_device::write_40xx(offs_t offset, uint8_t data)
{
if (offset < 0x4000)
m_ram[offset&0xfeff] = data;
@@ -298,7 +297,7 @@ WRITE8_MEMBER(a78_rom_mram_device::write_40xx)
-------------------------------------------------*/
-READ8_MEMBER(a78_rom_sg_device::read_40xx)
+uint8_t a78_rom_sg_device::read_40xx(offs_t offset)
{
if (offset < 0x4000)
return m_rom[(offset & 0x3fff) + ((m_bank_mask - 1) * 0x4000)]; // second to last bank (is this always ok?!?)
@@ -308,7 +307,7 @@ READ8_MEMBER(a78_rom_sg_device::read_40xx)
return m_rom[(offset & 0x3fff) + (m_bank_mask * 0x4000)]; // last bank
}
-WRITE8_MEMBER(a78_rom_sg_device::write_40xx)
+void a78_rom_sg_device::write_40xx(offs_t offset, uint8_t data)
{
if (offset >= 0x4000 && offset < 0x8000)
m_bank = data & m_bank_mask;
@@ -324,7 +323,7 @@ WRITE8_MEMBER(a78_rom_sg_device::write_40xx)
-------------------------------------------------*/
-READ8_MEMBER(a78_rom_sg_pokey_device::read_40xx)
+uint8_t a78_rom_sg_pokey_device::read_40xx(offs_t offset)
{
if (offset < 0x4000)
return m_pokey->read(offset & 0x0f);
@@ -334,7 +333,7 @@ READ8_MEMBER(a78_rom_sg_pokey_device::read_40xx)
return m_rom[(offset & 0x3fff) + (m_bank_mask * 0x4000)]; // last bank
}
-WRITE8_MEMBER(a78_rom_sg_pokey_device::write_40xx)
+void a78_rom_sg_pokey_device::write_40xx(offs_t offset, uint8_t data)
{
if (offset < 0x4000)
m_pokey->write(offset & 0x0f, data);
@@ -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);
}
@@ -361,7 +360,7 @@ void a78_rom_sg_pokey_device::device_add_mconfig(machine_config &config)
-------------------------------------------------*/
-READ8_MEMBER(a78_rom_sg_ram_device::read_40xx)
+uint8_t a78_rom_sg_ram_device::read_40xx(offs_t offset)
{
if (offset < 0x4000)
return m_ram[offset];
@@ -371,7 +370,7 @@ READ8_MEMBER(a78_rom_sg_ram_device::read_40xx)
return m_rom[(offset & 0x3fff) + (m_bank_mask * 0x4000)]; // last bank
}
-WRITE8_MEMBER(a78_rom_sg_ram_device::write_40xx)
+void a78_rom_sg_ram_device::write_40xx(offs_t offset, uint8_t data)
{
if (offset < 0x4000)
m_ram[offset] = data;
@@ -392,7 +391,7 @@ WRITE8_MEMBER(a78_rom_sg_ram_device::write_40xx)
-------------------------------------------------*/
-READ8_MEMBER(a78_rom_sg9_device::read_40xx)
+uint8_t a78_rom_sg9_device::read_40xx(offs_t offset)
{
if (offset < 0x4000)
return m_rom[(offset & 0x3fff)];
@@ -402,7 +401,7 @@ READ8_MEMBER(a78_rom_sg9_device::read_40xx)
return m_rom[(offset & 0x3fff) + ((m_bank_mask + 1) * 0x4000)]; // last bank
}
-WRITE8_MEMBER(a78_rom_sg9_device::write_40xx)
+void a78_rom_sg9_device::write_40xx(offs_t offset, uint8_t data)
{
if (offset >= 0x4000 && offset < 0x8000)
m_bank = (data & m_bank_mask) + 1;
@@ -419,7 +418,7 @@ WRITE8_MEMBER(a78_rom_sg9_device::write_40xx)
-------------------------------------------------*/
-READ8_MEMBER(a78_rom_abs_device::read_40xx)
+uint8_t a78_rom_abs_device::read_40xx(offs_t offset)
{
if (offset < 0x4000)
return m_rom[(offset & 0x3fff) + (m_bank * 0x4000)];
@@ -430,7 +429,7 @@ READ8_MEMBER(a78_rom_abs_device::read_40xx)
}
}
-WRITE8_MEMBER(a78_rom_abs_device::write_40xx)
+void a78_rom_abs_device::write_40xx(offs_t offset, uint8_t data)
{
if (offset == 0x4000)
{
@@ -445,52 +444,38 @@ WRITE8_MEMBER(a78_rom_abs_device::write_40xx)
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.
-------------------------------------------------*/
-READ8_MEMBER(a78_rom_act_device::read_40xx)
+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;
}
-WRITE8_MEMBER(a78_rom_act_device::write_40xx)
+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/rom.h b/src/devices/bus/a7800/rom.h
index 1ad27663b6f..45c9608a4ea 100644
--- a/src/devices/bus/a7800/rom.h
+++ b/src/devices/bus/a7800/rom.h
@@ -19,14 +19,14 @@ public:
a78_rom_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
// reading and writing
- virtual DECLARE_READ8_MEMBER(read_40xx) override;
+ virtual uint8_t read_40xx(offs_t offset) override;
protected:
a78_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 void device_start() override ATTR_COLD;
+ virtual void device_reset() override ATTR_COLD;
};
@@ -39,13 +39,13 @@ public:
a78_rom_pokey_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
// reading and writing
- virtual DECLARE_READ8_MEMBER(read_40xx) override;
- virtual DECLARE_WRITE8_MEMBER(write_40xx) override;
+ virtual uint8_t read_40xx(offs_t offset) override;
+ virtual void write_40xx(offs_t offset, uint8_t data) override;
protected:
a78_rom_pokey_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_add_mconfig(machine_config &config) override ATTR_COLD;
required_device<pokey_device> m_pokey;
};
@@ -60,8 +60,8 @@ public:
a78_rom_mram_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
// reading and writing
- virtual DECLARE_READ8_MEMBER(read_40xx) override;
- virtual DECLARE_WRITE8_MEMBER(write_40xx) override;
+ virtual uint8_t read_40xx(offs_t offset) override;
+ virtual void write_40xx(offs_t offset, uint8_t data) override;
protected:
a78_rom_mram_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock);
@@ -77,15 +77,15 @@ public:
a78_rom_sg_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
// reading and writing
- virtual DECLARE_READ8_MEMBER(read_40xx) override;
- virtual DECLARE_WRITE8_MEMBER(write_40xx) override;
+ virtual uint8_t read_40xx(offs_t offset) override;
+ virtual void write_40xx(offs_t offset, uint8_t data) override;
protected:
a78_rom_sg_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_start() override ATTR_COLD;
+ virtual void device_reset() override ATTR_COLD;
int m_bank;
};
@@ -100,11 +100,11 @@ public:
a78_rom_sg_pokey_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
// reading and writing
- virtual DECLARE_READ8_MEMBER(read_40xx) override;
- virtual DECLARE_WRITE8_MEMBER(write_40xx) override;
+ virtual uint8_t read_40xx(offs_t offset) override;
+ virtual void write_40xx(offs_t offset, uint8_t data) override;
protected:
- virtual void device_add_mconfig(machine_config &config) override;
+ virtual void device_add_mconfig(machine_config &config) override ATTR_COLD;
required_device<pokey_device> m_pokey;
};
@@ -119,8 +119,8 @@ public:
a78_rom_sg_ram_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
// reading and writing
- virtual DECLARE_READ8_MEMBER(read_40xx) override;
- virtual DECLARE_WRITE8_MEMBER(write_40xx) override;
+ virtual uint8_t read_40xx(offs_t offset) override;
+ virtual void write_40xx(offs_t offset, uint8_t data) override;
protected:
a78_rom_sg_ram_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock);
@@ -136,8 +136,8 @@ public:
a78_rom_sg9_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
// reading and writing
- virtual DECLARE_READ8_MEMBER(read_40xx) override;
- virtual DECLARE_WRITE8_MEMBER(write_40xx) override;
+ virtual uint8_t read_40xx(offs_t offset) override;
+ virtual void write_40xx(offs_t offset, uint8_t data) override;
protected:
a78_rom_sg9_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock);
@@ -153,13 +153,13 @@ public:
a78_rom_abs_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
// reading and writing
- virtual DECLARE_READ8_MEMBER(read_40xx) override;
- virtual DECLARE_WRITE8_MEMBER(write_40xx) override;
+ virtual uint8_t read_40xx(offs_t offset) override;
+ virtual void write_40xx(offs_t offset, uint8_t data) override;
protected:
// device-level overrides
- virtual void device_start() override;
- virtual void device_reset() override;
+ virtual void device_start() override ATTR_COLD;
+ virtual void device_reset() override ATTR_COLD;
int m_bank;
};
@@ -174,13 +174,13 @@ public:
a78_rom_act_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
// reading and writing
- virtual DECLARE_READ8_MEMBER(read_40xx) override;
- virtual DECLARE_WRITE8_MEMBER(write_40xx) override;
+ virtual uint8_t read_40xx(offs_t offset) override;
+ virtual void write_40xx(offs_t offset, uint8_t data) override;
protected:
// device-level overrides
- virtual void device_start() override;
- virtual void device_reset() override;
+ virtual void device_start() override ATTR_COLD;
+ virtual void device_reset() override ATTR_COLD;
int m_bank;
};
@@ -197,11 +197,11 @@ public:
a78_rom_p450_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
// reading and writing
- virtual DECLARE_READ8_MEMBER(read_04xx) override { if (offset >= 0x50 && offset < 0x60) return m_pokey450->read(offset & 0x0f); else return 0xff; }
- virtual DECLARE_WRITE8_MEMBER(write_04xx) override { if (offset >= 0x50 && offset < 0x60) m_pokey450->write(offset & 0x0f, data); }
+ virtual uint8_t read_04xx(offs_t offset) override { if (offset >= 0x50 && offset < 0x60) return m_pokey450->read(offset & 0x0f); else return 0xff; }
+ virtual void write_04xx(offs_t offset, uint8_t data) override { if (offset >= 0x50 && offset < 0x60) m_pokey450->write(offset & 0x0f, data); }
protected:
- virtual void device_add_mconfig(machine_config &config) override;
+ virtual void device_add_mconfig(machine_config &config) override ATTR_COLD;
required_device<pokey_device> m_pokey450;
};
@@ -216,11 +216,11 @@ public:
a78_rom_p450_pokey_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
// reading and writing
- virtual DECLARE_READ8_MEMBER(read_04xx) override { if (offset >= 0x50 && offset < 0x60) return m_pokey450->read(offset & 0x0f); else return 0xff; }
- virtual DECLARE_WRITE8_MEMBER(write_04xx) override { if (offset >= 0x50 && offset < 0x60) m_pokey450->write(offset & 0x0f, data); }
+ virtual uint8_t read_04xx(offs_t offset) override { if (offset >= 0x50 && offset < 0x60) return m_pokey450->read(offset & 0x0f); else return 0xff; }
+ virtual void write_04xx(offs_t offset, uint8_t data) override { if (offset >= 0x50 && offset < 0x60) m_pokey450->write(offset & 0x0f, data); }
protected:
- virtual void device_add_mconfig(machine_config &config) override;
+ virtual void device_add_mconfig(machine_config &config) override ATTR_COLD;
required_device<pokey_device> m_pokey450;
};
@@ -235,11 +235,11 @@ public:
a78_rom_p450_sg_ram_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
// reading and writing
- virtual DECLARE_READ8_MEMBER(read_04xx) override { if (offset >= 0x50 && offset < 0x60) return m_pokey450->read(offset & 0x0f); else return 0xff; }
- virtual DECLARE_WRITE8_MEMBER(write_04xx) override { if (offset >= 0x50 && offset < 0x60) m_pokey450->write(offset & 0x0f, data); }
+ virtual uint8_t read_04xx(offs_t offset) override { if (offset >= 0x50 && offset < 0x60) return m_pokey450->read(offset & 0x0f); else return 0xff; }
+ virtual void write_04xx(offs_t offset, uint8_t data) override { if (offset >= 0x50 && offset < 0x60) m_pokey450->write(offset & 0x0f, data); }
protected:
- virtual void device_add_mconfig(machine_config &config) override;
+ virtual void device_add_mconfig(machine_config &config) override ATTR_COLD;
required_device<pokey_device> m_pokey450;
};
@@ -254,11 +254,11 @@ public:
a78_rom_p450_sg9_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
// reading and writing
- virtual DECLARE_READ8_MEMBER(read_04xx) override { if (offset >= 0x50 && offset < 0x60) return m_pokey450->read(offset & 0x0f); else return 0xff; }
- virtual DECLARE_WRITE8_MEMBER(write_04xx) override { if (offset >= 0x50 && offset < 0x60) m_pokey450->write(offset & 0x0f, data); }
+ virtual uint8_t read_04xx(offs_t offset) override { if (offset >= 0x50 && offset < 0x60) return m_pokey450->read(offset & 0x0f); else return 0xff; }
+ virtual void write_04xx(offs_t offset, uint8_t data) override { if (offset >= 0x50 && offset < 0x60) m_pokey450->write(offset & 0x0f, data); }
protected:
- virtual void device_add_mconfig(machine_config &config) override;
+ virtual void device_add_mconfig(machine_config &config) override ATTR_COLD;
required_device<pokey_device> m_pokey450;
};
diff --git a/src/devices/bus/a7800/xboard.cpp b/src/devices/bus/a7800/xboard.cpp
index 0005e595a88..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);
}
@@ -139,38 +139,38 @@ void a78_xm_device::device_add_mconfig(machine_config &config)
-------------------------------------------------*/
-READ8_MEMBER(a78_xboard_device::read_40xx)
+uint8_t a78_xboard_device::read_40xx(offs_t offset)
{
if (BIT(m_reg, 3) && offset < 0x4000)
return m_ram[offset + (m_ram_bank * 0x4000)];
else
- return m_xbslot->read_40xx(space, offset);
+ return m_xbslot->read_40xx(offset);
}
-WRITE8_MEMBER(a78_xboard_device::write_40xx)
+void a78_xboard_device::write_40xx(offs_t offset, uint8_t data)
{
if (BIT(m_reg, 3) && offset < 0x4000)
m_ram[offset + (m_ram_bank * 0x4000)] = data;
else
- m_xbslot->write_40xx(space, offset, data);
+ m_xbslot->write_40xx(offset, data);
}
-READ8_MEMBER(a78_xboard_device::read_04xx)
+uint8_t a78_xboard_device::read_04xx(offs_t offset)
{
if (BIT(m_reg, 4) && offset >= 0x50 && offset < 0x60)
return m_pokey->read(offset & 0x0f);
else if (BIT(m_reg, 4) && offset >= 0x60 && offset < 0x70)
- return m_xbslot->read_04xx(space, offset - 0x10); // access second POKEY
+ return m_xbslot->read_04xx(offset - 0x10); // access second POKEY
else
return 0xff;
}
-WRITE8_MEMBER(a78_xboard_device::write_04xx)
+void a78_xboard_device::write_04xx(offs_t offset, uint8_t data)
{
if (BIT(m_reg, 4) && offset >= 0x50 && offset < 0x60)
m_pokey->write(offset & 0x0f, data);
else if (BIT(m_reg, 4) && offset >= 0x60 && offset < 0x70)
- m_xbslot->write_04xx(space, offset - 0x10, data); // access second POKEY
+ m_xbslot->write_04xx(offset - 0x10, data); // access second POKEY
else if (offset >= 0x70 && offset < 0x80)
{
m_reg = data;
@@ -185,41 +185,41 @@ WRITE8_MEMBER(a78_xboard_device::write_04xx)
-------------------------------------------------*/
-READ8_MEMBER(a78_xm_device::read_10xx)
+uint8_t a78_xm_device::read_10xx(offs_t offset)
{
return m_nvram[offset];
}
-WRITE8_MEMBER(a78_xm_device::write_10xx)
+void a78_xm_device::write_10xx(offs_t offset, uint8_t data)
{
m_nvram[offset] = data;
}
-READ8_MEMBER(a78_xm_device::read_30xx)
+uint8_t a78_xm_device::read_30xx(offs_t offset)
{
return m_rom[offset];
}
-READ8_MEMBER(a78_xm_device::read_04xx)
+uint8_t a78_xm_device::read_04xx(offs_t offset)
{
if (BIT(m_reg, 4) && offset >= 0x50 && offset < 0x60)
return m_pokey->read(offset & 0x0f);
else if (m_ym_enabled && offset >= 0x60 && offset <= 0x61)
return m_ym->read(offset & 1);
else if (BIT(m_reg, 4) && offset >= 0x60 && offset < 0x70)
- return m_xbslot->read_04xx(space, offset - 0x10); // access second POKEY
+ return m_xbslot->read_04xx(offset - 0x10); // access second POKEY
else
return 0xff;
}
-WRITE8_MEMBER(a78_xm_device::write_04xx)
+void a78_xm_device::write_04xx(offs_t offset, uint8_t data)
{
if (BIT(m_reg, 4) && offset >= 0x50 && offset < 0x60)
m_pokey->write(offset & 0x0f, data);
else if (m_ym_enabled && offset >= 0x60 && offset <= 0x61)
m_ym->write(offset & 1, data);
else if (BIT(m_reg, 4) && offset >= 0x60 && offset < 0x70)
- m_xbslot->write_04xx(space, offset - 0x10, data); // access second POKEY
+ m_xbslot->write_04xx(offset - 0x10, data); // access second POKEY
else if (offset >= 0x70 && offset < 0x80)
{
//printf("regs 0x%X\n", data);
diff --git a/src/devices/bus/a7800/xboard.h b/src/devices/bus/a7800/xboard.h
index 476d9a18aba..9bc3f2a4726 100644
--- a/src/devices/bus/a7800/xboard.h
+++ b/src/devices/bus/a7800/xboard.h
@@ -8,7 +8,7 @@
#include "a78_slot.h"
#include "rom.h"
#include "sound/pokey.h"
-#include "sound/ym2151.h"
+#include "sound/ymopm.h"
// ======================> a78_xboard_device
@@ -20,17 +20,17 @@ public:
a78_xboard_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
// reading and writing
- virtual DECLARE_READ8_MEMBER(read_04xx) override;
- virtual DECLARE_WRITE8_MEMBER(write_04xx) override;
- virtual DECLARE_READ8_MEMBER(read_40xx) override;
- virtual DECLARE_WRITE8_MEMBER(write_40xx) override;
+ virtual uint8_t read_04xx(offs_t offset) override;
+ virtual void write_04xx(offs_t offset, uint8_t data) override;
+ virtual uint8_t read_40xx(offs_t offset) override;
+ virtual void write_40xx(offs_t offset, uint8_t data) override;
protected:
a78_xboard_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 device_start() override ATTR_COLD;
+ virtual void device_reset() override ATTR_COLD;
+ virtual void device_add_mconfig(machine_config &config) override ATTR_COLD;
required_device<a78_cart_slot_device> m_xbslot;
required_device<pokey_device> m_pokey;
@@ -47,16 +47,16 @@ public:
a78_xm_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
// reading and writing
- virtual DECLARE_READ8_MEMBER(read_04xx) override;
- virtual DECLARE_WRITE8_MEMBER(write_04xx) override;
- virtual DECLARE_READ8_MEMBER(read_10xx) override;
- virtual DECLARE_WRITE8_MEMBER(write_10xx) override;
- virtual DECLARE_READ8_MEMBER(read_30xx) override;
+ virtual uint8_t read_04xx(offs_t offset) override;
+ virtual void write_04xx(offs_t offset, uint8_t data) override;
+ virtual uint8_t read_10xx(offs_t offset) override;
+ virtual void write_10xx(offs_t offset, uint8_t data) override;
+ virtual uint8_t read_30xx(offs_t offset) override;
protected:
- virtual void device_start() override;
- virtual void device_reset() override;
- virtual void device_add_mconfig(machine_config &config) override;
+ 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;
required_device<ym2151_device> m_ym;
int m_ym_enabled;
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..56d038db471
--- /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_A800_A5200_SUPERCART_H
+#define MAME_BUS_A800_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 ATTR_COLD;
+
+protected:
+ virtual void device_start() override ATTR_COLD;
+ virtual void device_reset() override ATTR_COLD;
+
+ 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_A800_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 d4ce87f5b54..6bbe9691e8a 100644
--- a/src/devices/bus/a800/a800_carts.h
+++ b/src/devices/bus/a800/a800_carts.h
@@ -1,54 +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 "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_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 9307efaf209..8045f0152d0 100644
--- a/src/devices/bus/a800/a800_slot.cpp
+++ b/src/devices/bus/a800/a800_slot.cpp
@@ -1,49 +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
-
- 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!
-
- ***********************************************************************************************************/
+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
+**************************************************************************************************/
#include "emu.h"
-#include "hashfile.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_slot_card_interface(mconfig, device),
- m_rom(nullptr),
- m_rom_size(0),
- m_bank_mask(0)
+ : 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());
}
@@ -55,73 +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_image_interface(mconfig, *this),
- device_slot_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())
{
}
@@ -138,20 +188,22 @@ a5200_cart_slot_device::~a5200_cart_slot_device()
{
}
-xegs_cart_slot_device::~xegs_cart_slot_device()
-{
-}
-
//-------------------------------------------------
// device_start - device-specific startup
//-------------------------------------------------
void a800_cart_slot_device::device_start()
{
- m_cart = dynamic_cast<device_a800_cart_interface *>(get_card_device());
+ 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
@@ -177,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" }
};
@@ -204,7 +264,7 @@ static int a800_get_pcb_id(const char *slot)
{
for (auto & elem : slot_list)
{
- if (!core_stricmp(elem.slot_option, slot))
+ if (!strcmp(elem.slot_option, slot))
return elem.pcb_id;
}
@@ -222,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)
{
@@ -233,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)
@@ -269,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
@@ -298,11 +412,127 @@ 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 (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;
+ }
+
+ 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 ((header[4] << 24) + (header[5] << 16) + (header[6] << 8) + (header[7] << 0))
+ switch (get_u32be(&header[4]))
{
case 1:
type = A800_8K;
@@ -331,6 +561,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;
@@ -343,19 +576,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;
+ case 56:
+ type = SIC_512KB;
break;
- // Atari 5200 CART files
+ case 69:
+ type = A800_ADAWLIAH;
+ break;
+ // Atari 5200 CART files
case 4:
type = A5200_32K;
break;
@@ -375,7 +629,7 @@ 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;
}
@@ -388,36 +642,50 @@ 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())
{
- const char *slot_string;
- std::vector<uint8_t> head(0x10);
- uint32_t len = hook.image_file()->size();
- int type = A800_8K;
+ 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
if ((len % 0x1000) == 0x10)
{
- hook.image_file()->read(&head[0], 0x10);
+ uint8_t head[0x10];
+ /*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");
- slot_string = a800_get_slot(type);
+ char const *const slot_string = a800_get_slot(type);
return std::string(slot_string);
}
- else
- return software_get_default_slot("a800_8k");
+
+ return software_get_default_slot(is_xegs ? "xegs" : "a800_8k");
}
@@ -425,15 +693,15 @@ std::string a5200_cart_slot_device::get_default_card_software(get_default_card_s
{
if (hook.image_file())
{
- const char *slot_string;
- std::vector<uint8_t> head(0x10);
- uint32_t len = hook.image_file()->size();
- int type = A5200_8K;
+ 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 = A5200_8K;
if ((len % 0x1000) == 0x10)
{
- hook.image_file()->read(&head[0], 0x10);
+ uint8_t head[0x10];
+ /*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
@@ -445,45 +713,12 @@ std::string a5200_cart_slot_device::get_default_card_software(get_default_card_s
if (type < A5200_4K)
osd_printf_info("This game is not designed for A5200. You might want to run it in A800 or A800XL.\n");
- slot_string = a800_get_slot(type);
+ char const *const slot_string = a800_get_slot(type);
return std::string(slot_string);
}
- else
- return software_get_default_slot("a5200");
-}
-
-
-std::string xegs_cart_slot_device::get_default_card_software(get_default_card_software_hook &hook) const
-{
- if (hook.image_file())
- {
- const char *slot_string;
- std::vector<uint8_t> head(0x10);
- uint32_t len = hook.image_file()->size();
- int type = A800_8K;
-
- // check whether there is an header, to identify the cart type
- if ((len % 0x1000) == 0x10)
- {
- hook.image_file()->read(&head[0], 0x10);
- 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");
- }
-
- slot_string = a800_get_slot(type);
- return std::string(slot_string);
- }
- else
- return software_get_default_slot("xegs");
+ return software_get_default_slot("a5200_rom");
}
@@ -491,35 +726,53 @@ std::string xegs_cart_slot_device::get_default_card_software(get_default_card_so
read
-------------------------------------------------*/
-READ8_MEMBER(a800_cart_slot_device::read_80xx)
+device_memory_interface::space_config_vector a800_cart_slot_device::memory_space_config() const
{
- if (m_cart)
- return m_cart->read_80xx(space, offset, mem_mask);
- else
- return 0xff;
+ return space_config_vector{
+ std::make_pair(AS_PROGRAM, &m_space_mem_config),
+ std::make_pair(AS_IO, &m_space_io_config)
+ };
}
-READ8_MEMBER(a800_cart_slot_device::read_d5xx)
+template <unsigned Bank> uint8_t a800_cart_slot_device::read_cart(offs_t offset)
{
- if (m_cart)
- return m_cart->read_d5xx(space, offset, mem_mask);
- else
- return 0xff;
+ 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);
+}
-/*-------------------------------------------------
- write
- -------------------------------------------------*/
+// 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);
-WRITE8_MEMBER(a800_cart_slot_device::write_80xx)
+uint8_t a800_cart_slot_device::read_cctl(offs_t offset)
{
- if (m_cart)
- m_cart->write_80xx(space, offset, data, mem_mask);
+ return m_space_io->read_byte(offset);
}
-WRITE8_MEMBER(a800_cart_slot_device::write_d5xx)
+void a800_cart_slot_device::write_cctl(offs_t offset, uint8_t data)
{
- if (m_cart)
- m_cart->write_d5xx(space, offset, data, mem_mask);
+ 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)
+ };
+}
+
+uint8_t a5200_cart_slot_device::read_cart(offs_t offset)
+{
+ return m_space_mem->read_byte(offset);
+}
+
+void a5200_cart_slot_device::write_cart(offs_t offset, uint8_t 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 cb31b6eacc2..b2c736078f0 100644
--- a/src/devices/bus/a800/a800_slot.h
+++ b/src/devices/bus/a800/a800_slot.h
@@ -1,20 +1,19 @@
// 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
#pragma once
-#include "softlist_dev.h"
+#include "imagedev/cartrom.h"
/***************************************************************************
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,50 +52,57 @@ enum
A5200_BBSB
};
+class a800_cart_slot_device;
-// ======================> device_a800_cart_interface
-
-class device_a800_cart_interface : public device_slot_card_interface
+class device_a800_cart_interface : public device_interface
{
public:
// construction/destruction
virtual ~device_a800_cart_interface();
- // memory accessor
- virtual DECLARE_READ8_MEMBER(read_80xx) { return 0xff; }
- virtual DECLARE_READ8_MEMBER(read_d5xx) { return 0xff; }
- virtual DECLARE_WRITE8_MEMBER(write_80xx) {}
- virtual DECLARE_WRITE8_MEMBER(write_d5xx) {}
+ virtual void cart_map(address_map &map) ATTR_COLD;
+ virtual void cctl_map(address_map &map) ATTR_COLD;
- 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_image_interface,
- public device_slot_interface
+ 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,52 +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 const software_list_loader &get_software_list_loader() const override { return rom_software_list_loader::instance(); }
-
- int get_cart_type() { return m_type; };
- int identify_cart_type(const uint8_t *header) const;
- bool has_cart() { return m_cart != nullptr; }
-
- virtual iodevice_t image_type() const override { return IO_CARTSLOT; }
- virtual bool is_readable() const override { return 1; }
- virtual bool is_writeable() const override { return 0; }
- virtual bool is_creatable() const override { return 0; }
- virtual bool must_be_loaded() const override { return 0; }
- virtual bool is_reset_on_load() const override { return 1; }
- virtual const char *image_interface() const override { return "a8bit_cart"; }
- virtual const char *file_extensions() const override { return "bin,rom,car"; }
+ 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 identify_cart_type(const uint8_t *header) const;
+ virtual std::pair<std::error_condition, std::string> call_load() override;
+ virtual void call_unload() override;
- // reading and writing
- virtual DECLARE_READ8_MEMBER(read_80xx);
- virtual DECLARE_READ8_MEMBER(read_d5xx);
- virtual DECLARE_WRITE8_MEMBER(write_80xx);
- virtual DECLARE_WRITE8_MEMBER(write_d5xx);
+ 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; }
+
+ 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
- virtual void device_start() override;
+ // device_t implementation
+ virtual void device_start() override ATTR_COLD;
+ 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) ATTR_COLD;
+
+ // 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);
+
+ virtual void interface_pre_start() override;
+ virtual void interface_post_start() override;
+ a5200_cart_slot_device *m_slot;
-// 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.
+ // internal state
+ uint8_t *m_rom;
+ uint32_t m_rom_size;
+ // helpers
+ int m_bank_mask;
+};
-// ======================> a5200_cart_slot_device
-class a5200_cart_slot_device : public a800_cart_slot_device
+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>
@@ -163,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 const char *file_extensions() const override { return "bin,rom,car,a52"; }
+ 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 ATTR_COLD;
+ virtual space_config_vector memory_space_config() const override;
- virtual const char *file_extensions() const 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 45fdb47ba45..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
@@ -53,7 +53,7 @@ DEFINE_DEVICE_TYPE(A8SIO, a8sio_device, "a8sio", "Atari 8 bit SIO Slot")
a8sio_device::a8sio_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
: device_t(mconfig, A8SIO, tag, owner, clock)
- , device_slot_interface(mconfig, *this)
+ , device_single_card_slot_interface<device_a8sio_card_interface>(mconfig, *this)
, m_out_clock_in_cb(*this)
, m_out_data_in_cb(*this)
, m_out_proceed_cb(*this)
@@ -71,19 +71,9 @@ a8sio_device::a8sio_device(const machine_config &mconfig, const char *tag, devic
void a8sio_device::device_resolve_objects()
{
- m_device = dynamic_cast<device_a8sio_card_interface *>(get_card_device());
-
+ 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();
}
//-------------------------------------------------
@@ -107,51 +97,51 @@ 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);
}
-WRITE8_MEMBER( a8sio_device::audio_in_w )
+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);
}
@@ -166,7 +156,7 @@ WRITE_LINE_MEMBER( a8sio_device::interrupt_w )
//-------------------------------------------------
device_a8sio_card_interface::device_a8sio_card_interface(const machine_config &mconfig, device_t &device)
- : device_slot_card_interface(mconfig, device)
+ : device_interface(device, "a8sio")
, m_a8sio(nullptr)
{
}
@@ -185,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 842c26bf99d..dab1665c5e8 100644
--- a/src/devices/bus/a800/a8sio.h
+++ b/src/devices/bus/a800/a8sio.h
@@ -39,8 +39,7 @@ void a8sio_cards(device_slot_interface &device);
class device_a8sio_card_interface;
-class a8sio_device : public device_t,
- public device_slot_interface
+class a8sio_device : public device_t, public device_single_card_slot_interface<device_a8sio_card_interface>
{
public:
// construction/destruction
@@ -63,23 +62,23 @@ 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
- DECLARE_WRITE8_MEMBER( audio_in_w ); // 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);
// device-level overrides
- virtual void device_resolve_objects() override;
- virtual void device_start() override;
- virtual void device_reset() override;
+ virtual void device_resolve_objects() override ATTR_COLD;
+ virtual void device_start() override ATTR_COLD;
+ virtual void device_reset() override ATTR_COLD;
devcb_write_line m_out_clock_in_cb; // pin 1
devcb_write_line m_out_data_in_cb; // pin 3
@@ -94,7 +93,7 @@ protected:
DECLARE_DEVICE_TYPE(A8SIO, a8sio_device)
-class device_a8sio_card_interface : public device_slot_card_interface
+class device_a8sio_card_interface : public device_interface
{
friend class a8sio_device;
public:
@@ -103,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..0c86dfd8dd4 100644
--- a/src/devices/bus/a800/atari1050.h
+++ b/src/devices/bus/a800/atari1050.h
@@ -6,13 +6,13 @@
***************************************************************************/
-#ifndef MAME_BUS_A800_ATARI1050
-#define MAME_BUS_A800_ATARI1050 1
+#ifndef MAME_BUS_A800_ATARI1050_H
+#define MAME_BUS_A800_ATARI1050_H
#pragma once
#include "a8sio.h"
-#include "machine/mos6530n.h"
+#include "machine/mos6530.h"
#include "machine/wd_fdc.h"
@@ -24,25 +24,24 @@ public:
static constexpr feature_type unemulated_features() { return feature::DISK; }
protected:
- virtual void device_start() override;
- virtual ioport_constructor device_input_ports() const override;
- virtual void device_add_mconfig(machine_config &config) override;
- virtual const tiny_rom_entry *device_rom_region() const override;
+ virtual void device_start() override ATTR_COLD;
+ virtual ioport_constructor device_input_ports() const override ATTR_COLD;
+ virtual void device_add_mconfig(machine_config &config) override ATTR_COLD;
+ virtual const tiny_rom_entry *device_rom_region() const override ATTR_COLD;
- 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);
+ void mem_map(address_map &map) ATTR_COLD;
- 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
+#endif // MAME_BUS_A800_ATARI1050_H
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..cfc6c2bbb3e 100644
--- a/src/devices/bus/a800/atari810.h
+++ b/src/devices/bus/a800/atari810.h
@@ -6,13 +6,13 @@
***************************************************************************/
-#ifndef MAME_BUS_A800_ATARI810
-#define MAME_BUS_A800_ATARI810 1
+#ifndef MAME_BUS_A800_ATARI810_H
+#define MAME_BUS_A800_ATARI810_H
#pragma once
#include "a8sio.h"
-#include "machine/mos6530n.h"
+#include "machine/mos6530.h"
#include "machine/wd_fdc.h"
@@ -24,25 +24,24 @@ public:
static constexpr feature_type unemulated_features() { return feature::DISK; }
protected:
- virtual void device_start() override;
- virtual ioport_constructor device_input_ports() const override;
- virtual void device_add_mconfig(machine_config &config) override;
- virtual const tiny_rom_entry *device_rom_region() const override;
+ virtual void device_start() override ATTR_COLD;
+ virtual ioport_constructor device_input_ports() const override ATTR_COLD;
+ virtual void device_add_mconfig(machine_config &config) override ATTR_COLD;
+ virtual const tiny_rom_entry *device_rom_region() const override ATTR_COLD;
- 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);
+ void mem_map(address_map &map) ATTR_COLD;
- 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
+#endif // MAME_BUS_A800_ATARI810_H
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..aceeaddd49a
--- /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 ATTR_COLD;
+ virtual void cctl_map(address_map &map) override ATTR_COLD;
+ virtual std::tuple<int, int> get_initial_rd_state() override { return std::make_tuple(0, 1); }
+
+protected:
+ virtual void device_start() override ATTR_COLD;
+ virtual void device_reset() override ATTR_COLD;
+
+ 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..69aad4ecd04
--- /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 ATTR_COLD;
+ virtual std::tuple<int, int> get_initial_rd_state() override { return std::make_tuple(1, 1); }
+
+protected:
+ virtual void device_start() override ATTR_COLD;
+ virtual void device_reset() override ATTR_COLD;
+
+ 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 ATTR_COLD;
+
+protected:
+ virtual void device_start() override ATTR_COLD;
+ virtual void device_reset() override ATTR_COLD;
+
+ 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 6a409611bbb..50feed49c5c 100644
--- a/src/devices/bus/a800/cassette.cpp
+++ b/src/devices/bus/a800/cassette.cpp
@@ -25,8 +25,7 @@ TODO:
// GLOBAL VARIABLES
//**************************************************************************
-DEFINE_DEVICE_TYPE(A8SIO_CASSETTE, a8sio_cassette_device, "a8sio_cass", "Atari 8 bit cassette")
-const device_timer_id TIMER_CASSETTE_READ = 1;
+DEFINE_DEVICE_TYPE(A8SIO_CASSETTE, a8sio_cassette_device, "a8sio_cass", "Atari 8-bit cassette")
void a8sio_cassette_device::device_add_mconfig(machine_config &config)
{
@@ -60,14 +59,14 @@ void a8sio_cassette_device::device_start()
save_item(NAME(m_old_cass_signal));
save_item(NAME(m_signal_count));
- m_read_timer = timer_alloc(TIMER_CASSETTE_READ);
+ m_read_timer = timer_alloc(FUNC(a8sio_cassette_device::read_tick), this);
}
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)
@@ -82,27 +81,22 @@ WRITE_LINE_MEMBER( a8sio_cassette_device::motor_w )
}
}
-void a8sio_cassette_device::device_timer(emu_timer &timer, device_timer_id id, int param, void *ptr)
+TIMER_CALLBACK_MEMBER(a8sio_cassette_device::read_tick)
{
- switch (id)
+ uint8_t cass_signal = m_cassette->input() < 0 ? 0 : 1;
+
+ if (m_signal_count < 20)
+ {
+ m_signal_count++;
+ }
+
+ if (cass_signal != m_old_cass_signal)
{
- case TIMER_CASSETTE_READ:
- uint8_t cass_signal = m_cassette->input() < 0 ? 0 : 1;
-
- if (m_signal_count < 20)
- {
- m_signal_count++;
- }
-
- if (cass_signal != m_old_cass_signal)
- {
- //printf("cass_signal: %d, count: %d, data: %d\n", cass_signal, m_signal_count, m_signal_count < 5 ? 1 : 0);
- // ~4 kHz -> 0
- // ~5 kHz -> 1
- m_a8sio->data_in_w((m_signal_count < 5) ? 1 : 0);
- m_signal_count = 0;
- m_old_cass_signal = cass_signal;
- }
- break;
+ //printf("cass_signal: %d, count: %d, data: %d\n", cass_signal, m_signal_count, m_signal_count < 5 ? 1 : 0);
+ // ~4 kHz -> 0
+ // ~5 kHz -> 1
+ m_a8sio->data_in_w((m_signal_count < 5) ? 1 : 0);
+ m_signal_count = 0;
+ m_old_cass_signal = cass_signal;
}
}
diff --git a/src/devices/bus/a800/cassette.h b/src/devices/bus/a800/cassette.h
index 17c45a9880b..b09d4a1111f 100644
--- a/src/devices/bus/a800/cassette.h
+++ b/src/devices/bus/a800/cassette.h
@@ -29,15 +29,16 @@ 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);
- virtual void device_start() override;
- virtual void device_reset() override;
- virtual void device_timer(emu_timer &timer, device_timer_id id, int param, void *ptr) override;
- virtual void device_add_mconfig(machine_config &config) override;
+ 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;
+
+ TIMER_CALLBACK_MEMBER(read_tick);
required_device<cassette_image_device> m_cassette;
emu_timer *m_read_timer;
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..ec043cbbbff
--- /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 ATTR_COLD;
+ virtual void cctl_map(address_map &map) override ATTR_COLD;
+ virtual std::tuple<int, int> get_initial_rd_state() override { return std::make_tuple(1, 1); }
+
+protected:
+ 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;
+
+ 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 ATTR_COLD;
+
+ 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..b096e41b8b3
--- /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 ATTR_COLD;
+ virtual void cctl_map(address_map &map) override ATTR_COLD;
+ 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 ATTR_COLD;
+
+ virtual void device_start() override ATTR_COLD;
+ virtual void device_reset() override ATTR_COLD;
+
+ 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 ATTR_COLD;
+
+protected:
+ virtual void device_add_mconfig(machine_config &config) override ATTR_COLD;
+};
+
+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 70a9375ef28..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
-------------------------------------------------*/
-READ8_MEMBER(a800_rom_oss8k_device::read_80xx)
+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)];
}
-WRITE8_MEMBER(a800_rom_oss8k_device::write_d5xx)
+/*
+ * ---- 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
-------------------------------------------------*/
-READ8_MEMBER(a800_rom_oss34_device::read_80xx)
+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)];
}
-WRITE8_MEMBER(a800_rom_oss34_device::write_d5xx)
+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]; })
+ );
+}
-READ8_MEMBER(a800_rom_oss43_device::read_80xx)
+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]; })
+ );
}
-WRITE8_MEMBER(a800_rom_oss43_device::write_d5xx)
+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)
-------------------------------------------------*/
-READ8_MEMBER(a800_rom_oss91_device::read_80xx)
+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)];
}
-WRITE8_MEMBER(a800_rom_oss91_device::write_d5xx)
+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 367bd4f8f8d..0af143028b6 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 DECLARE_READ8_MEMBER(read_80xx) override;
- virtual DECLARE_WRITE8_MEMBER(write_d5xx) override;
+ virtual void cart_map(address_map &map) override ATTR_COLD;
+ virtual void cctl_map(address_map &map) override ATTR_COLD;
+ 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_start() override ATTR_COLD;
+ virtual void device_reset() override ATTR_COLD;
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 DECLARE_READ8_MEMBER(read_80xx) override;
- virtual DECLARE_WRITE8_MEMBER(write_d5xx) override;
+ virtual void cart_map(address_map &map) override ATTR_COLD;
+ virtual void cctl_map(address_map &map) override ATTR_COLD;
+ 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_start() override ATTR_COLD;
+ virtual void device_reset() override ATTR_COLD;
+ virtual void device_add_mconfig(machine_config &config) override ATTR_COLD;
- int m_bank;
-};
+ void bankdev_map(address_map &map) ATTR_COLD;
+ 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 DECLARE_READ8_MEMBER(read_80xx) override;
- virtual DECLARE_WRITE8_MEMBER(write_d5xx) 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;
+ virtual void device_start() override ATTR_COLD;
};
-// ======================> 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 DECLARE_READ8_MEMBER(read_80xx) override;
- virtual DECLARE_WRITE8_MEMBER(write_d5xx) 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..2ca00adddca
--- /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 ATTR_COLD;
+ virtual void cctl_map(address_map &map) override ATTR_COLD;
+ virtual std::tuple<int, int> get_initial_rd_state() override { return std::make_tuple(0, 1); }
+
+protected:
+ virtual void device_start() override ATTR_COLD;
+ virtual void device_reset() override ATTR_COLD;
+
+ 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 ATTR_COLD;
+ virtual std::tuple<int, int> get_initial_rd_state() override { return std::make_tuple(1, 1); }
+
+protected:
+ virtual void device_reset() override ATTR_COLD;
+
+ 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 ATTR_COLD;
+
+protected:
+ virtual void device_start() override ATTR_COLD;
+ virtual void device_reset() override ATTR_COLD;
+ virtual ioport_constructor device_input_ports() const override ATTR_COLD;
+
+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 f33c8776d52..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
-
- -------------------------------------------------*/
-
-READ8_MEMBER(a800_rom_device::read_80xx)
+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
-------------------------------------------------*/
-READ8_MEMBER(a800_rom_bbsb_device::read_80xx)
+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];
}
-WRITE8_MEMBER(a800_rom_bbsb_device::write_80xx)
+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
-
- -------------------------------------------------*/
-
-READ8_MEMBER(xegs_rom_device::read_80xx)
+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);
}
-WRITE8_MEMBER(xegs_rom_device::write_d5xx)
+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)
-------------------------------------------------*/
-READ8_MEMBER(a800_rom_williams_device::read_80xx)
+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)];
}
-WRITE8_MEMBER(a800_rom_williams_device::write_d5xx)
+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
-
- -------------------------------------------------*/
-
-READ8_MEMBER(a800_rom_express_device::read_80xx)
+void xegs_rom_device::device_reset()
{
- return m_rom[(offset & 0x1fff) + (m_bank * 0x2000)];
+ // TODO: random
+ m_bank = 0;
}
-WRITE8_MEMBER(a800_rom_express_device::write_d5xx)
+// 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
-
-
- -------------------------------------------------*/
-
-READ8_MEMBER(a800_rom_turbo_device::read_80xx)
+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; })
+ );
}
-WRITE8_MEMBER(a800_rom_turbo_device::write_d5xx)
-{
- m_bank = offset & m_bank_mask;
-}
+
+// Atari 5200
/*-------------------------------------------------
- Telelink II
+ Carts with no bankswitch (4K, 8K, 16K, 32K)
+ Same as base carts above
-------------------------------------------------*/
-READ8_MEMBER(a800_rom_telelink2_device::read_80xx)
-{
- if (offset >= 0x2000)
- return m_rom[offset & 0x1fff];
- if (offset >= 0x1000 && offset < 0x1100)
- return m_nvram[offset & 0xff];
-
- return 0xff;
-}
-
-WRITE8_MEMBER(a800_rom_telelink2_device::write_80xx)
-{
- m_nvram[offset & 0xff] = data | 0xf0; // low 4bits only
-}
-
-READ8_MEMBER(a800_rom_telelink2_device::read_d5xx)
+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;
}
-WRITE8_MEMBER(a800_rom_telelink2_device::write_d5xx)
+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
-
-
- -------------------------------------------------*/
-
-READ8_MEMBER(a800_rom_microcalc_device::read_80xx)
+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))]; })
+ );
}
-WRITE8_MEMBER(a800_rom_microcalc_device::write_d5xx)
+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 @@ WRITE8_MEMBER(a800_rom_microcalc_device::write_d5xx)
-------------------------------------------------*/
-READ8_MEMBER(a5200_rom_2chips_device::read_80xx)
-{
- 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
-
- -------------------------------------------------*/
-
-READ8_MEMBER(a5200_rom_bbsb_device::read_80xx)
+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;
}
-WRITE8_MEMBER(a5200_rom_bbsb_device::write_80xx)
+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 9ba329b3113..4de7735ac3e 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 DECLARE_READ8_MEMBER(read_80xx) override;
+ virtual void cart_map(address_map &map) override ATTR_COLD;
+ 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;
+ virtual void device_start() override ATTR_COLD;
+ virtual void device_reset() override ATTR_COLD;
};
-
-// ======================> 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 DECLARE_READ8_MEMBER(read_80xx) override;
- virtual DECLARE_WRITE8_MEMBER(write_80xx) override;
+ virtual void cart_map(address_map &map) override ATTR_COLD;
+ 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];
+ virtual void device_start() override ATTR_COLD;
+ virtual void device_reset() override ATTR_COLD;
};
-
-// ======================> 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 DECLARE_READ8_MEMBER(read_80xx) override;
- virtual DECLARE_WRITE8_MEMBER(write_d5xx) override;
+ virtual void cart_map(address_map &map) override ATTR_COLD;
+ 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;
+ virtual void device_start() override ATTR_COLD;
+ virtual void device_reset() override ATTR_COLD;
};
-// ======================> a800_rom_express_device
-
-class a800_rom_express_device : public a800_rom_device
+class xegs_rom_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);
+ xegs_rom_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
- virtual DECLARE_READ8_MEMBER(read_80xx) override;
- virtual DECLARE_WRITE8_MEMBER(write_d5xx) override;
+ virtual void cart_map(address_map &map) override ATTR_COLD;
+ virtual void cctl_map(address_map &map) override ATTR_COLD;
+ 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;
+ virtual void device_start() override ATTR_COLD;
+ virtual void device_reset() override ATTR_COLD;
int m_bank;
};
-
-// ======================> a800_rom_blizzard_device
-
-class a800_rom_blizzard_device : public a800_rom_device
+class a5200_rom_device : public device_t,
+ public device_a5200_cart_interface
{
public:
- // construction/destruction
- a800_rom_blizzard_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 DECLARE_READ8_MEMBER(read_80xx) override;
+ virtual void cart_map(address_map &map) override ATTR_COLD;
protected:
- // device-level overrides
- virtual void device_start() override;
- virtual void device_reset() override;
-};
-
+ a5200_rom_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock);
-// ======================> a800_rom_turbo_device
-
-class a800_rom_turbo_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);
-
- virtual DECLARE_READ8_MEMBER(read_80xx) override;
- virtual DECLARE_WRITE8_MEMBER(write_d5xx) override;
-
-protected:
- // device-level overrides
- virtual void device_start() override;
- virtual void device_reset() override;
-
- int m_bank;
+ virtual void device_start() override ATTR_COLD;
};
-
-// ======================> a800_rom_telelink2_device
-
-class a800_rom_telelink2_device : public a800_rom_device
+class a5200_rom_2chips_device : public a5200_rom_device
{
public:
- // construction/destruction
- a800_rom_telelink2_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
-
- virtual DECLARE_READ8_MEMBER(read_80xx) override;
- virtual DECLARE_WRITE8_MEMBER(write_80xx) override;
- virtual DECLARE_READ8_MEMBER(read_d5xx) override;
- virtual DECLARE_WRITE8_MEMBER(write_d5xx) override;
-};
-
-
-// ======================> a800_rom_microcalc_device
-
-class a800_rom_microcalc_device : public a800_rom_device
-{
-public:
- // construction/destruction
- a800_rom_microcalc_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
-
- virtual DECLARE_READ8_MEMBER(read_80xx) override;
- virtual DECLARE_WRITE8_MEMBER(write_d5xx) 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);
-
- // device-level overrides
- virtual void device_start() override;
- virtual void device_reset() override;
-
- virtual DECLARE_READ8_MEMBER(read_80xx) override;
- virtual DECLARE_WRITE8_MEMBER(write_d5xx) override;
-
-protected:
- int m_bank;
-};
-
-
-// ======================> a5200_rom_2chips_device
-
-class a5200_rom_2chips_device : public a800_rom_device
-{
-public:
- // construction/destruction
a5200_rom_2chips_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
- virtual DECLARE_READ8_MEMBER(read_80xx) override;
+ virtual void cart_map(address_map &map) override ATTR_COLD;
};
-
-// ======================> 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 DECLARE_READ8_MEMBER(read_80xx) override;
- virtual DECLARE_WRITE8_MEMBER(write_80xx) 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
new file mode 100644
index 00000000000..88f133941b6
--- /dev/null
+++ b/src/devices/bus/a800/rtime8.cpp
@@ -0,0 +1,60 @@
+// license:BSD-3-Clause
+// copyright-holders:AJR
+/***********************************************************************************************************
+
+ ICD R-Time 8 (Atari 800 cartridge)
+
+ 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; the cartridge can be placed in the passthrough slot of the SpartaDOS X cartridge.
+
+***********************************************************************************************************/
+
+#include "emu.h"
+#include "rtime8.h"
+
+// device type definition
+DEFINE_DEVICE_TYPE(A800_RTIME8, a800_rtime8_device, "a800_rtime8", "ICD R-Time 8")
+
+
+//-------------------------------------------------
+// a800_rtime8_device - constructor
+//-------------------------------------------------
+
+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)
+ , m_rtc(*this, "rtc")
+{
+}
+
+//-------------------------------------------------
+// device_add_mconfig - configure subdevices
+//-------------------------------------------------
+
+void a800_rtime8_device::device_add_mconfig(machine_config &config)
+{
+ M3002(config, m_rtc, 32.768_kHz_XTAL);
+}
+
+//-------------------------------------------------
+// device_start - device-specific startup
+//-------------------------------------------------
+
+void a800_rtime8_device::device_start()
+{
+}
+
+
+//-------------------------------------------------
+// read_d5xx - handle reads from $D500-$D5FF
+//-------------------------------------------------
+
+// TODO: 4-bit access, D7-D4 returns open bus
+void a800_rtime8_device::cctl_map(address_map &map)
+{
+ 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
new file mode 100644
index 00000000000..0fc60686329
--- /dev/null
+++ b/src/devices/bus/a800/rtime8.h
@@ -0,0 +1,32 @@
+// license:BSD-3-Clause
+// copyright-holders:AJR
+
+#ifndef MAME_BUS_A800_RTIME8_H
+#define MAME_BUS_A800_RTIME8_H
+
+#pragma once
+
+#include "a800_slot.h"
+#include "machine/m3002.h"
+
+
+// ======================> a800_rtime8_device
+
+class a800_rtime8_device : public device_t, public device_a800_cart_interface
+{
+public:
+ a800_rtime8_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock);
+
+ virtual void cctl_map(address_map &map) override ATTR_COLD;
+
+protected:
+ virtual void device_add_mconfig(machine_config &config) override ATTR_COLD;
+ virtual void device_start() override ATTR_COLD;
+
+private:
+ required_device<m3002_device> m_rtc;
+};
+
+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..815008f53f5
--- /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 ATTR_COLD;
+ virtual void cctl_map(address_map &map) override ATTR_COLD;
+ 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 ATTR_COLD;
+
+ virtual void device_start() override ATTR_COLD;
+ virtual void device_reset() override ATTR_COLD;
+
+ 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 ATTR_COLD;
+};
+
+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 ATTR_COLD;
+};
+
+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 30d76eecc38..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);
+}
-READ8_MEMBER(a800_rom_spartados_device::read_80xx)
+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);
}
-WRITE8_MEMBER(a800_rom_spartados_device::write_d5xx)
+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 614ce86571c..2538567ec60 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 DECLARE_READ8_MEMBER(read_80xx) override;
- virtual DECLARE_WRITE8_MEMBER(write_d5xx) override;
+ virtual void cart_map(address_map &map) override ATTR_COLD;
+ virtual void cctl_map(address_map &map) override ATTR_COLD;
+ 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_start() override ATTR_COLD;
+ virtual void device_reset() override ATTR_COLD;
+
+ virtual void device_add_mconfig(machine_config &config) override ATTR_COLD;
+
+ 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;
- int m_bank, m_subslot_enabled;
+ 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 ATTR_COLD;
+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..14951740543
--- /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 ATTR_COLD;
+
+protected:
+ virtual void device_start() override ATTR_COLD;
+ virtual void device_reset() override ATTR_COLD;
+
+ 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..d542d3562b4
--- /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 ATTR_COLD;
+ virtual void cctl_map(address_map &map) override ATTR_COLD;
+
+ // 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 ATTR_COLD;
+ virtual void device_reset() override ATTR_COLD;
+ virtual void device_add_mconfig(machine_config &config) override ATTR_COLD;
+
+ 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..cc8371d7775
--- /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 ATTR_COLD;
+ virtual void cctl_map(address_map &map) override ATTR_COLD;
+ virtual std::tuple<int, int> get_initial_rd_state() override { return std::make_tuple(0, 1); }
+
+protected:
+ virtual void device_start() override ATTR_COLD;
+ virtual void device_reset() override ATTR_COLD;
+
+ 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..0b39c85d8a0
--- /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 ATTR_COLD;
+ virtual void cctl_map(address_map &map) override ATTR_COLD;
+ virtual std::tuple<int, int> get_initial_rd_state() override { return std::make_tuple(0, 1); };
+
+protected:
+ virtual void device_start() override ATTR_COLD;
+ virtual void device_reset() override ATTR_COLD;
+
+ 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 ATTR_COLD;
+
+ 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 ATTR_COLD;
+};
+
+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 ATTR_COLD;
+};
+
+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/abc890.cpp b/src/devices/bus/abcbus/abc890.cpp
index 27530439929..9374096f38b 100644
--- a/src/devices/bus/abcbus/abc890.cpp
+++ b/src/devices/bus/abcbus/abc890.cpp
@@ -192,7 +192,7 @@ void abc890_device::device_reset()
void abc890_device::abcbus_cs(uint8_t data)
{
- for (abcbus_slot_device &slot : abcbus_slot_device_iterator(*this))
+ for (abcbus_slot_device &slot : abcbus_slot_device_enumerator(*this))
slot.write_cs(data);
}
@@ -205,7 +205,7 @@ uint8_t abc890_device::abcbus_inp()
{
uint8_t data = 0xff;
- for (abcbus_slot_device &slot : abcbus_slot_device_iterator(*this))
+ for (abcbus_slot_device &slot : abcbus_slot_device_enumerator(*this))
data &= slot.read_inp();
return data;
@@ -218,7 +218,7 @@ uint8_t abc890_device::abcbus_inp()
void abc890_device::abcbus_out(uint8_t data)
{
- for (abcbus_slot_device &slot : abcbus_slot_device_iterator(*this))
+ for (abcbus_slot_device &slot : abcbus_slot_device_enumerator(*this))
slot.write_out(data);
}
@@ -231,7 +231,7 @@ uint8_t abc890_device::abcbus_stat()
{
uint8_t data = 0xff;
- for (abcbus_slot_device &slot : abcbus_slot_device_iterator(*this))
+ for (abcbus_slot_device &slot : abcbus_slot_device_enumerator(*this))
data &= slot.read_stat();
return data;
@@ -244,7 +244,7 @@ uint8_t abc890_device::abcbus_stat()
void abc890_device::abcbus_c1(uint8_t data)
{
- for (abcbus_slot_device &slot : abcbus_slot_device_iterator(*this))
+ for (abcbus_slot_device &slot : abcbus_slot_device_enumerator(*this))
slot.write_c1(data);
}
@@ -255,7 +255,7 @@ void abc890_device::abcbus_c1(uint8_t data)
void abc890_device::abcbus_c2(uint8_t data)
{
- for (abcbus_slot_device &slot : abcbus_slot_device_iterator(*this))
+ for (abcbus_slot_device &slot : abcbus_slot_device_enumerator(*this))
slot.write_c2(data);
}
@@ -266,7 +266,7 @@ void abc890_device::abcbus_c2(uint8_t data)
void abc890_device::abcbus_c3(uint8_t data)
{
- for (abcbus_slot_device &slot : abcbus_slot_device_iterator(*this))
+ for (abcbus_slot_device &slot : abcbus_slot_device_enumerator(*this))
slot.write_c3(data);
}
@@ -277,7 +277,7 @@ void abc890_device::abcbus_c3(uint8_t data)
void abc890_device::abcbus_c4(uint8_t data)
{
- for (abcbus_slot_device &slot : abcbus_slot_device_iterator(*this))
+ for (abcbus_slot_device &slot : abcbus_slot_device_enumerator(*this))
slot.write_c4(data);
}
@@ -290,7 +290,7 @@ uint8_t abc890_device::abcbus_xmemfl(offs_t offset)
{
uint8_t data = 0xff;
- for (abcbus_slot_device &slot : abcbus_slot_device_iterator(*this))
+ for (abcbus_slot_device &slot : abcbus_slot_device_enumerator(*this))
{
data &= slot.xmemfl_r(offset);
}
@@ -305,7 +305,7 @@ uint8_t abc890_device::abcbus_xmemfl(offs_t offset)
void abc890_device::abcbus_xmemw(offs_t offset, uint8_t data)
{
- for (abcbus_slot_device &slot : abcbus_slot_device_iterator(*this))
+ for (abcbus_slot_device &slot : abcbus_slot_device_enumerator(*this))
{
slot.xmemw_w(offset, data);
}
diff --git a/src/devices/bus/abcbus/abc890.h b/src/devices/bus/abcbus/abc890.h
index 5a56b9804fe..f8d14f4ed81 100644
--- a/src/devices/bus/abcbus/abc890.h
+++ b/src/devices/bus/abcbus/abc890.h
@@ -32,11 +32,11 @@ protected:
abc890_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_start() override ATTR_COLD;
+ virtual void device_reset() override ATTR_COLD;
// optional information overrides
- virtual void device_add_mconfig(machine_config &config) override;
+ virtual void device_add_mconfig(machine_config &config) override ATTR_COLD;
// device_abcbus_interface overrides
virtual void abcbus_cs(uint8_t data) override;
@@ -62,7 +62,7 @@ public:
protected:
// optional information overrides
- virtual void device_add_mconfig(machine_config &config) override;
+ virtual void device_add_mconfig(machine_config &config) override ATTR_COLD;
};
@@ -76,7 +76,7 @@ public:
protected:
// optional information overrides
- virtual void device_add_mconfig(machine_config &config) override;
+ virtual void device_add_mconfig(machine_config &config) override ATTR_COLD;
};
@@ -90,7 +90,7 @@ public:
protected:
// optional information overrides
- virtual void device_add_mconfig(machine_config &config) override;
+ virtual void device_add_mconfig(machine_config &config) override ATTR_COLD;
};
@@ -104,7 +104,7 @@ public:
protected:
// optional information overrides
- virtual void device_add_mconfig(machine_config &config) override;
+ virtual void device_add_mconfig(machine_config &config) override ATTR_COLD;
};
@@ -118,7 +118,7 @@ public:
protected:
// optional information overrides
- virtual void device_add_mconfig(machine_config &config) override;
+ virtual void device_add_mconfig(machine_config &config) override ATTR_COLD;
};
diff --git a/src/devices/bus/abcbus/abcbus.cpp b/src/devices/bus/abcbus/abcbus.cpp
index e34f51ac729..d02042720b7 100644
--- a/src/devices/bus/abcbus/abcbus.cpp
+++ b/src/devices/bus/abcbus/abcbus.cpp
@@ -28,7 +28,7 @@ DEFINE_DEVICE_TYPE(ABCBUS_SLOT, abcbus_slot_device, "abcbus_slot", "ABCBUS slot"
//-------------------------------------------------
device_abcbus_card_interface::device_abcbus_card_interface(const machine_config &mconfig, device_t &device) :
- device_slot_card_interface(mconfig, device)
+ device_interface(device, "abcbus")
{
m_slot = dynamic_cast<abcbus_slot_device *>(device.owner());
}
@@ -40,7 +40,7 @@ device_abcbus_card_interface::device_abcbus_card_interface(const machine_config
abcbus_slot_device::abcbus_slot_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) :
device_t(mconfig, ABCBUS_SLOT, tag, owner, clock),
- device_slot_interface(mconfig, *this),
+ device_single_card_slot_interface<device_abcbus_card_interface>(mconfig, *this),
m_write_irq(*this),
m_write_nmi(*this),
m_write_rdy(*this),
@@ -50,8 +50,16 @@ abcbus_slot_device::abcbus_slot_device(const machine_config &mconfig, const char
m_write_xint2(*this),
m_write_xint3(*this),
m_write_xint4(*this),
- m_write_xint5(*this), m_card(nullptr), m_irq(0), m_nmi(0), m_pren(0),
- m_trrq(0), m_xint2(0), m_xint3(0), m_xint4(0), m_xint5(0)
+ m_write_xint5(*this),
+ m_card(nullptr),
+ m_irq(1),
+ m_nmi(1),
+ m_pren(1),
+ m_trrq(1),
+ m_xint2(1),
+ m_xint3(1),
+ m_xint4(1),
+ m_xint5(1)
{
}
@@ -62,28 +70,29 @@ abcbus_slot_device::abcbus_slot_device(const machine_config &mconfig, const char
void abcbus_slot_device::device_start()
{
- m_card = dynamic_cast<device_abcbus_card_interface *>(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();
+ m_card = get_card_device();
+}
+
+
+//-------------------------------------------------
+// device_reset - device-specific reset
+//-------------------------------------------------
+
+void abcbus_slot_device::device_reset()
+{
+ m_write_irq(1);
+ m_write_pren(1);
+ m_write_trrq(1);
}
// slot devices
#include "abc890.h"
#include "cadmouse.h"
-#include "db411223.h"
+#include "db4106.h"
+#include "db4107.h"
+#include "db4112.h"
#include "fd2.h"
-#include "hdc.h"
#include "lux10828.h"
#include "lux21046.h"
#include "lux21056.h"
@@ -108,12 +117,14 @@ void abc80_cards(device_slot_interface &device)
device.option_add("abc830", ABC830);
device.option_add("abcexp", ABC_EXPANSION_UNIT);
device.option_add("cadabc", ABC_CADMOUSE);
- device.option_add("db411223", DATABOARD_4112_23);
+ device.option_add("db4106", DATABOARD_4106);
+ device.option_add("db4107", DATABOARD_4107);
+ device.option_add("db4112", DATABOARD_4112);
device.option_add("fd2", ABC_FD2);
device.option_add("memcard", ABC_MEMORY_CARD);
device.option_add("slow", LUXOR_55_10828);
- device.option_add("ssa", SUPER_SMARTAID);
- device.option_add("unidisk", UNIDISK);
+ device.option_add("ssa", ABC_SUPER_SMARTAID);
+ device.option_add("unidisk", ABC_UNIDISK);
}
@@ -133,13 +144,14 @@ void abcbus_cards(device_slot_interface &device)
device.option_add("abc856", ABC856);
device.option_add("abc890", ABC890);
device.option_add("abc894", ABC894);
- device.option_add("db411223", DATABOARD_4112_23);
- device.option_add("hdc", ABC_HDC);
+ device.option_add("db4106", DATABOARD_4106);
+ device.option_add("db4107", DATABOARD_4107);
+ device.option_add("db4112", DATABOARD_4112);
device.option_add("sio", ABC_SIO);
device.option_add("slow", LUXOR_55_10828);
device.option_add("slutprov", ABC_SLUTPROV);
device.option_add("uni800", ABC_UNI800);
- device.option_add("unidisk", UNIDISK);
+ device.option_add("unidisk", ABC_UNIDISK);
device.option_add("xebec", LUXOR_55_21056);
}
diff --git a/src/devices/bus/abcbus/abcbus.h b/src/devices/bus/abcbus/abcbus.h
index 2388fbc73cf..ee36effa8b7 100644
--- a/src/devices/bus/abcbus/abcbus.h
+++ b/src/devices/bus/abcbus/abcbus.h
@@ -95,22 +95,14 @@
**********************************************************************/
-#ifndef MAME_DEVICES_ABCBUS_ABCBUS_H
-#define MAME_DEVICES_ABCBUS_ABCBUS_H
+#ifndef MAME_BUS_ABCBUS_ABCBUS_H
+#define MAME_BUS_ABCBUS_ABCBUS_H
#pragma once
//**************************************************************************
-// CONSTANTS
-//**************************************************************************
-
-#define ABCBUS_TAG "bus"
-
-
-
-//**************************************************************************
// TYPE DEFINITIONS
//**************************************************************************
@@ -118,35 +110,36 @@
class abcbus_slot_device;
-class device_abcbus_card_interface : public device_slot_card_interface
+class device_abcbus_card_interface : public device_interface
{
public:
// required operation overrides
virtual void abcbus_cs(uint8_t data) = 0;
// optional operation overrides
- virtual uint8_t abcbus_inp() { return 0xff; };
- virtual void abcbus_out(uint8_t data) { };
- virtual uint8_t abcbus_stat() { return 0xff; };
- virtual void abcbus_c1(uint8_t data) { };
- virtual void abcbus_c2(uint8_t data) { };
- virtual void abcbus_c3(uint8_t data) { };
- virtual void abcbus_c4(uint8_t data) { };
+ virtual uint8_t abcbus_inp() { return 0xff; }
+ virtual void abcbus_out(uint8_t data) { }
+ virtual uint8_t abcbus_stat() { return 0xff; }
+ virtual void abcbus_c1(uint8_t data) { }
+ virtual void abcbus_c2(uint8_t data) { }
+ virtual void abcbus_c3(uint8_t data) { }
+ virtual void abcbus_c4(uint8_t data) { }
// optional operation overrides for ABC 80
- virtual uint8_t abcbus_xmemfl(offs_t offset) { return 0xff; };
- virtual void abcbus_xmemw(offs_t offset, uint8_t data) { };
+ virtual uint8_t abcbus_xmemfl(offs_t offset) { return 0xff; }
+ virtual void abcbus_xmemw(offs_t offset, uint8_t data) { }
// optional operation overrides for ABC 1600
virtual int abcbus_csb() { return 1; }
- virtual uint8_t abcbus_ops() { return 0xff; };
- virtual void abcbus_tren(int state) { };
- virtual void abcbus_prac(int state) { };
- virtual uint8_t abcbus_exp() { return 0xff; };
- virtual int abcbus_xcsb2() { return 1; };
- virtual int abcbus_xcsb3() { return 1; };
- virtual int abcbus_xcsb4() { return 1; };
- virtual int abcbus_xcsb5() { return 1; };
+ virtual uint8_t abcbus_ops() { return 0xff; }
+ virtual uint8_t abcbus_tren() { return 0xff; }
+ virtual void abcbus_tren(uint8_t data) { }
+ virtual void abcbus_prac(int state) { }
+ virtual uint8_t abcbus_exp() { return 0xff; }
+ virtual int abcbus_xcsb2() { return 1; }
+ virtual int abcbus_xcsb3() { return 1; }
+ virtual int abcbus_xcsb4() { return 1; }
+ virtual int abcbus_xcsb5() { return 1; }
protected:
// construction/destruction
@@ -161,7 +154,7 @@ protected:
// ======================> abcbus_slot_device
class abcbus_slot_device : public device_t,
- public device_slot_interface
+ public device_single_card_slot_interface<device_abcbus_card_interface>
{
public:
// construction/destruction
@@ -199,53 +192,52 @@ 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; }
- DECLARE_WRITE_LINE_MEMBER( tren_w ) { if (m_card) m_card->abcbus_tren(state); }
- DECLARE_WRITE_LINE_MEMBER( prac_w ) { if (m_card) m_card->abcbus_prac(state); }
-
- DECLARE_WRITE8_MEMBER( cs_w ) { write_cs(data); }
- DECLARE_READ8_MEMBER( rst_r ) { return read_rst(); }
- DECLARE_READ8_MEMBER( inp_r ) { return read_inp(); }
- DECLARE_WRITE8_MEMBER( out_w ) { write_out(data); }
- DECLARE_READ8_MEMBER( stat_r ) { return read_stat(); }
- DECLARE_WRITE8_MEMBER( c1_w ) { write_c1(data); }
- DECLARE_WRITE8_MEMBER( c2_w ) { write_c2(data); }
- DECLARE_WRITE8_MEMBER( c3_w ) { write_c3(data); }
- DECLARE_WRITE8_MEMBER( c4_w ) { write_c4(data); }
- DECLARE_READ8_MEMBER( xmemfl_r ) { return xmemfl_r(offset); }
- DECLARE_WRITE8_MEMBER( xmemw_w ) { xmemw_w(offset, 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 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); }
+ 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(); }
+ uint8_t inp_r() { return read_inp(); }
+ void out_w(uint8_t data) { write_out(data); }
+ uint8_t stat_r() { return read_stat(); }
+ void c1_w(uint8_t data) { write_c1(data); }
+ void c2_w(uint8_t data) { write_c2(data); }
+ void c3_w(uint8_t data) { write_c3(data); }
+ void c4_w(uint8_t data) { write_c4(data); }
+
+ 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 ) { 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 ) { m_pren = state; m_write_pren(state); }
- DECLARE_WRITE_LINE_MEMBER( trrq_w ) { 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
- virtual void device_start() override;
- virtual void device_reset() override { if (m_card) get_card_device()->reset(); }
+ virtual void device_start() override ATTR_COLD;
+ virtual void device_reset() override ATTR_COLD;
devcb_write_line m_write_irq;
devcb_write_line m_write_nmi;
@@ -280,7 +272,7 @@ void abcbus_cards(device_slot_interface &device);
void abc1600bus_cards(device_slot_interface &device);
-typedef device_type_iterator<abcbus_slot_device> abcbus_slot_device_iterator;
+typedef device_type_enumerator<abcbus_slot_device> abcbus_slot_device_enumerator;
-#endif // MAME_DEVICES_ABCBUS_ABCBUS_H
+#endif // MAME_BUS_ABCBUS_ABCBUS_H
diff --git a/src/devices/bus/abcbus/cadmouse.h b/src/devices/bus/abcbus/cadmouse.h
index 317c67e97aa..363b5f628bc 100644
--- a/src/devices/bus/abcbus/cadmouse.h
+++ b/src/devices/bus/abcbus/cadmouse.h
@@ -23,16 +23,16 @@ public:
static constexpr feature_type unemulated_features() { return feature::MOUSE | feature::GRAPHICS; }
protected:
- void abc_cadmouse_mem(address_map &map);
- void abc_cadmouse_io(address_map &map);
+ void abc_cadmouse_mem(address_map &map) ATTR_COLD;
+ void abc_cadmouse_io(address_map &map) ATTR_COLD;
// device-level overrides
- virtual void device_start() override;
- virtual void device_reset() override;
+ virtual void device_start() override ATTR_COLD;
+ virtual void device_reset() override ATTR_COLD;
// optional information overrides
- virtual const tiny_rom_entry *device_rom_region() const override;
- virtual void device_add_mconfig(machine_config &config) override;
+ virtual const tiny_rom_entry *device_rom_region() const override ATTR_COLD;
+ virtual void device_add_mconfig(machine_config &config) override ATTR_COLD;
// device_abcbus_interface overrides
virtual void abcbus_cs(uint8_t data) override;
diff --git a/src/devices/bus/abcbus/db411223.cpp b/src/devices/bus/abcbus/db4106.cpp
index 86ba1f22ee9..edd604f610c 100644
--- a/src/devices/bus/abcbus/db411223.cpp
+++ b/src/devices/bus/abcbus/db4106.cpp
@@ -2,12 +2,12 @@
// copyright-holders:Curt Coder
/**********************************************************************
- Databoard 4112-23 floppy disk controller emulation
+ DataBoard 4106 Minifloppy interface emulation
*********************************************************************/
#include "emu.h"
-#include "db411223.h"
+#include "db4106.h"
@@ -22,16 +22,16 @@
// DEVICE DEFINITIONS
//**************************************************************************
-DEFINE_DEVICE_TYPE(DATABOARD_4112_23, databoard_4112_23_t, "db411223", "Databoard 4112-23")
+DEFINE_DEVICE_TYPE(DATABOARD_4106, databoard_4106_device, "abc_db4106", "DataBoard 4106 Minifloppy interface")
//-------------------------------------------------
-// ROM( databoard_4112_23 )
+// ROM( databoard_4106 )
//-------------------------------------------------
-ROM_START( databoard_4112_23 )
- ROM_REGION( 0x2000, Z80_TAG, 0 )
- ROM_LOAD("fpy_int_4112-23_teac_fd55.bin", 0x0000, 0x2000, CRC(9175ceb8) SHA1(95c150d3152df318abd9267915d5669d2ec33895))
+ROM_START( databoard_4106 )
+ ROM_REGION( 0x800, Z80_TAG, 0 )
+ ROM_LOAD("databoard-4106-a5.12-floppy-cont.bin", 0x000, 0x800, CRC(708f2a2f) SHA1(3f99ea2ef301d9e3415db152dad79171dc62cc2d) ) // single track controller
ROM_END
@@ -39,27 +39,27 @@ ROM_END
// rom_region - device-specific ROM region
//-------------------------------------------------
-const tiny_rom_entry *databoard_4112_23_t::device_rom_region() const
+const tiny_rom_entry *databoard_4106_device::device_rom_region() const
{
- return ROM_NAME( databoard_4112_23 );
+ return ROM_NAME( databoard_4106 );
}
//-------------------------------------------------
-// ADDRESS_MAP( databoard_4112_23_mem )
+// ADDRESS_MAP( databoard_4106_mem )
//-------------------------------------------------
-void databoard_4112_23_t::databoard_4112_23_mem(address_map &map)
+void databoard_4106_device::databoard_4106_mem(address_map &map)
{
- map(0x0000, 0x1fff).rom().region(Z80_TAG, 0);
+ map(0x0000, 0x07ff).rom().region(Z80_TAG, 0);
}
//-------------------------------------------------
-// ADDRESS_MAP( databoard_4112_23_io )
+// ADDRESS_MAP( databoard_4106_io )
//-------------------------------------------------
-void databoard_4112_23_t::databoard_4112_23_io(address_map &map)
+void databoard_4106_device::databoard_4106_io(address_map &map)
{
}
@@ -68,19 +68,19 @@ void databoard_4112_23_t::databoard_4112_23_io(address_map &map)
// device_add_mconfig - add device configuration
//-------------------------------------------------
-void databoard_4112_23_t::device_add_mconfig(machine_config &config)
+void databoard_4106_device::device_add_mconfig(machine_config &config)
{
Z80(config, m_maincpu, 4000000);
- m_maincpu->set_addrmap(AS_PROGRAM, &databoard_4112_23_t::databoard_4112_23_mem);
- m_maincpu->set_addrmap(AS_IO, &databoard_4112_23_t::databoard_4112_23_io);
+ m_maincpu->set_memory_map(&databoard_4106_device::databoard_4106_mem);
+ m_maincpu->set_io_map(&databoard_4106_device::databoard_4106_io);
}
//-------------------------------------------------
-// INPUT_PORTS( databoard_4112_23 )
+// INPUT_PORTS( databoard_4106 )
//-------------------------------------------------
-INPUT_PORTS_START( databoard_4112_23 )
+INPUT_PORTS_START( databoard_4106 )
INPUT_PORTS_END
@@ -88,9 +88,9 @@ INPUT_PORTS_END
// input_ports - device-specific input ports
//-------------------------------------------------
-ioport_constructor databoard_4112_23_t::device_input_ports() const
+ioport_constructor databoard_4106_device::device_input_ports() const
{
- return INPUT_PORTS_NAME( databoard_4112_23 );
+ return INPUT_PORTS_NAME( databoard_4106 );
}
@@ -100,11 +100,11 @@ ioport_constructor databoard_4112_23_t::device_input_ports() const
//**************************************************************************
//-------------------------------------------------
-// databoard_4112_23_t - constructor
+// databoard_4106_device - constructor
//-------------------------------------------------
-databoard_4112_23_t::databoard_4112_23_t(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) :
- device_t(mconfig, DATABOARD_4112_23, tag, owner, clock),
+databoard_4106_device::databoard_4106_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) :
+ device_t(mconfig, DATABOARD_4106, tag, owner, clock),
device_abcbus_card_interface(mconfig, *this),
m_maincpu(*this, Z80_TAG)
{
@@ -115,7 +115,7 @@ databoard_4112_23_t::databoard_4112_23_t(const machine_config &mconfig, const ch
// device_start - device-specific startup
//-------------------------------------------------
-void databoard_4112_23_t::device_start()
+void databoard_4106_device::device_start()
{
}
@@ -124,7 +124,7 @@ void databoard_4112_23_t::device_start()
// device_reset - device-specific reset
//-------------------------------------------------
-void databoard_4112_23_t::device_reset()
+void databoard_4106_device::device_reset()
{
m_cs = false;
}
@@ -139,7 +139,7 @@ void databoard_4112_23_t::device_reset()
// abcbus_cs -
//-------------------------------------------------
-void databoard_4112_23_t::abcbus_cs(uint8_t data)
+void databoard_4106_device::abcbus_cs(uint8_t data)
{
}
@@ -148,7 +148,7 @@ void databoard_4112_23_t::abcbus_cs(uint8_t data)
// abcbus_stat -
//-------------------------------------------------
-uint8_t databoard_4112_23_t::abcbus_stat()
+uint8_t databoard_4106_device::abcbus_stat()
{
uint8_t data = 0xff;
@@ -164,7 +164,7 @@ uint8_t databoard_4112_23_t::abcbus_stat()
// abcbus_inp -
//-------------------------------------------------
-uint8_t databoard_4112_23_t::abcbus_inp()
+uint8_t databoard_4106_device::abcbus_inp()
{
uint8_t data = 0xff;
@@ -180,7 +180,7 @@ uint8_t databoard_4112_23_t::abcbus_inp()
// abcbus_out -
//-------------------------------------------------
-void databoard_4112_23_t::abcbus_out(uint8_t data)
+void databoard_4106_device::abcbus_out(uint8_t data)
{
if (!m_cs) return;
}
@@ -190,7 +190,7 @@ void databoard_4112_23_t::abcbus_out(uint8_t data)
// abcbus_c1 -
//-------------------------------------------------
-void databoard_4112_23_t::abcbus_c1(uint8_t data)
+void databoard_4106_device::abcbus_c1(uint8_t data)
{
if (m_cs)
{
@@ -202,7 +202,7 @@ void databoard_4112_23_t::abcbus_c1(uint8_t data)
// abcbus_c3 -
//-------------------------------------------------
-void databoard_4112_23_t::abcbus_c3(uint8_t data)
+void databoard_4106_device::abcbus_c3(uint8_t data)
{
if (m_cs)
{
diff --git a/src/devices/bus/abcbus/db411223.h b/src/devices/bus/abcbus/db4106.h
index e126d9cfb18..51c9fa4d507 100644
--- a/src/devices/bus/abcbus/db411223.h
+++ b/src/devices/bus/abcbus/db4106.h
@@ -2,12 +2,12 @@
// copyright-holders:Curt Coder
/**********************************************************************
- Databoard 4112-23 floppy disk controller emulation
+ DataBoard 4106 Minifloppy interface emulation
*********************************************************************/
-#ifndef MAME_BUS_ABCBUS_DATABOARD_4112_23_H
-#define MAME_BUS_ABCBUS_DATABOARD_4112_23_H
+#ifndef MAME_BUS_ABCBUS_DB4106_H
+#define MAME_BUS_ABCBUS_DB4106_H
#pragma once
@@ -20,24 +20,24 @@
// TYPE DEFINITIONS
//**************************************************************************
-// ======================> databoard_4112_23_t
+// ======================> databoard_4106_device
-class databoard_4112_23_t : public device_t,
- public device_abcbus_card_interface
+class databoard_4106_device : public device_t,
+ public device_abcbus_card_interface
{
public:
// construction/destruction
- databoard_4112_23_t(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
+ databoard_4106_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_start() override ATTR_COLD;
+ virtual void device_reset() override ATTR_COLD;
// optional information 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 const tiny_rom_entry *device_rom_region() const override ATTR_COLD;
+ virtual void device_add_mconfig(machine_config &config) override ATTR_COLD;
+ virtual ioport_constructor device_input_ports() const override ATTR_COLD;
// device_abcbus_interface overrides
virtual void abcbus_cs(uint8_t data) override;
@@ -48,16 +48,16 @@ protected:
virtual void abcbus_c3(uint8_t data) override;
private:
- required_device<cpu_device> m_maincpu;
+ required_device<z80_device> m_maincpu;
bool m_cs;
- void databoard_4112_23_io(address_map &map);
- void databoard_4112_23_mem(address_map &map);
+ void databoard_4106_io(address_map &map) ATTR_COLD;
+ void databoard_4106_mem(address_map &map) ATTR_COLD;
};
// device type definition
-DECLARE_DEVICE_TYPE(DATABOARD_4112_23, databoard_4112_23_t)
+DECLARE_DEVICE_TYPE(DATABOARD_4106, databoard_4106_device)
-#endif // MAME_BUS_ABCBUS_DATABOARD_4112_23_H
+#endif // MAME_BUS_ABCBUS_DB4106_H
diff --git a/src/devices/bus/abcbus/db4107.cpp b/src/devices/bus/abcbus/db4107.cpp
new file mode 100644
index 00000000000..0b9ab0ed062
--- /dev/null
+++ b/src/devices/bus/abcbus/db4107.cpp
@@ -0,0 +1,240 @@
+// license:BSD-3-Clause
+// copyright-holders:Curt Coder
+/**********************************************************************
+
+ DataBoard 4107 Winchester interface emulation
+
+*********************************************************************/
+
+#include "emu.h"
+#include "db4107.h"
+
+
+
+//**************************************************************************
+// MACROS / CONSTANTS
+//**************************************************************************
+
+#define Z80_TAG "maincpu"
+#define Z80DMA_TAG "dma"
+
+
+//**************************************************************************
+// DEVICE DEFINITIONS
+//**************************************************************************
+
+DEFINE_DEVICE_TYPE(DATABOARD_4107, databoard_4107_device, "abc_db4107", "DataBoard 4107 Winchester interface")
+
+
+//-------------------------------------------------
+// ROM( databoard_4107 )
+//-------------------------------------------------
+
+ROM_START( databoard_4107 )
+ ROM_REGION( 0x2000, Z80_TAG, 0 )
+ ROM_SYSTEM_BIOS( 0, "w511", "Micropolis W511" )
+ ROMX_LOAD("micr.w511_6490398-2.bin", 0x000, 0x1000, CRC(cd8f16ff) SHA1(52966142bbed07459f6eb272213b677ec49864d3), ROM_BIOS(0) )
+ ROM_SYSTEM_BIOS( 1, "nec5126", "NEC 5126)" )
+ ROMX_LOAD("nec_1.2_6490396-1.bin", 0x000, 0x1000, CRC(88fa6ed2) SHA1(9faa144591c620c5d7dcc15feada350f6a14f02a), ROM_BIOS(1) )
+ ROM_SYSTEM_BIOS( 2, "nec6490", "NEC 6490" )
+ ROMX_LOAD("nec_6490.bin", 0x000, 0x1000, CRC(17c247e7) SHA1(7339738b87751655cb4d6414422593272fe72f5d), ROM_BIOS(2) )
+ ROM_SYSTEM_BIOS( 3, "ro202", "Rodime RO-202" )
+ ROMX_LOAD("ro202_1.00_6490320-01.bin", 0x000, 0x800, CRC(337b4dcf) SHA1(791ebeb4521ddc11fb9742114018e161e1849bdf), ROM_BIOS(3) )
+ ROM_SYSTEM_BIOS( 4, "st4038", "Seagate ST4038 (CHS: 733,5,17,512)" )
+ ROMX_LOAD("st4038.bin", 0x000, 0x800, CRC(4c803b87) SHA1(1141bb51ad9200fc32d92a749460843dc6af8953), ROM_BIOS(4) )
+ ROM_SYSTEM_BIOS( 5, "st406", "Seagate ST406" )
+ ROMX_LOAD("st406.bin", 0x000, 0x800, CRC(3cdd154f) SHA1(b1464163370e9037a8ce1d535935ee55fbf68ee1), ROM_BIOS(5) )
+ ROM_SYSTEM_BIOS( 6, "st514", "Seagate ST514" )
+ ROMX_LOAD("st514_15_5.bin", 0x000, 0x800, CRC(6e25c645) SHA1(8b3ca02decef5aafdb46dbfdf84371057d06799e), ROM_BIOS(6) )
+ ROM_SYSTEM_BIOS( 7, "w504", "W504" )
+ ROMX_LOAD("w504_10m.bin", 0x000, 0x800, CRC(277ee4a5) SHA1(a3bf6f2b9f75ef46fd3b1aca6e4a42191d702b82), ROM_BIOS(7) )
+ ROM_SYSTEM_BIOS( 8, "st412", "Seagate ST412" )
+ ROMX_LOAD("w507_st412.bin", 0x000, 0x800, CRC(0d3c92d2) SHA1(345c5f8154f0ec9d66ef19ce9793176aa257707d), ROM_BIOS(8) )
+ ROM_SYSTEM_BIOS( 9, "w514", "W514" )
+ ROMX_LOAD("w514.bin", 0x000, 0x800, CRC(8ec3f70e) SHA1(ca60a48d591e42526fcc301ce94e861bf8368aa4), ROM_BIOS(9) )
+ ROM_SYSTEM_BIOS( 10, "b6185b", "BASF 6185B" )
+ ROMX_LOAD("basf_6185b.bin", 0x000, 0x800, CRC(06f8fe2e) SHA1(e81f2a47c854e0dbb096bee3428d79e63591059d), ROM_BIOS(10) )
+ ROM_SYSTEM_BIOS( 11, "m1325", "Micropolis 1325" )
+ ROMX_LOAD("micr1325.bin", 0x000, 0x800, CRC(084af409) SHA1(342b8e214a8c4c2b014604e53c45ef1bd1c69ea3), ROM_BIOS(11) )
+ ROM_SYSTEM_BIOS( 12, "st225", "W515 (CHS: 615,4,17,512)" )
+ ROMX_LOAD("w515_st225.bin", 0x000, 0x800, CRC(c9f68f81) SHA1(7ff8b2a19f71fe0279ab3e5a0a5fffcb6030360c), ROM_BIOS(12) )
+ROM_END
+
+
+//-------------------------------------------------
+// rom_region - device-specific ROM region
+//-------------------------------------------------
+
+const tiny_rom_entry *databoard_4107_device::device_rom_region() const
+{
+ return ROM_NAME( databoard_4107 );
+}
+
+
+//-------------------------------------------------
+// ADDRESS_MAP( databoard_4107_mem )
+//-------------------------------------------------
+
+void databoard_4107_device::databoard_4107_mem(address_map &map)
+{
+ map(0x0000, 0x1fff).rom().region(Z80_TAG, 0);
+}
+
+
+//-------------------------------------------------
+// ADDRESS_MAP( databoard_4107_io )
+//-------------------------------------------------
+
+void databoard_4107_device::databoard_4107_io(address_map &map)
+{
+}
+
+
+//-------------------------------------------------
+// device_add_mconfig - add device configuration
+//-------------------------------------------------
+
+void databoard_4107_device::device_add_mconfig(machine_config &config)
+{
+ Z80(config, m_maincpu, 4000000);
+ m_maincpu->set_memory_map(&databoard_4107_device::databoard_4107_mem);
+ m_maincpu->set_io_map(&databoard_4107_device::databoard_4107_io);
+
+ Z80DMA(config, m_dma, 4000000);
+}
+
+
+//-------------------------------------------------
+// INPUT_PORTS( databoard_4107 )
+//-------------------------------------------------
+
+INPUT_PORTS_START( databoard_4107 )
+INPUT_PORTS_END
+
+
+//-------------------------------------------------
+// input_ports - device-specific input ports
+//-------------------------------------------------
+
+ioport_constructor databoard_4107_device::device_input_ports() const
+{
+ return INPUT_PORTS_NAME( databoard_4107 );
+}
+
+
+
+//**************************************************************************
+// LIVE DEVICE
+//**************************************************************************
+
+//-------------------------------------------------
+// databoard_4107_device - constructor
+//-------------------------------------------------
+
+databoard_4107_device::databoard_4107_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) :
+ device_t(mconfig, DATABOARD_4107, tag, owner, clock),
+ device_abcbus_card_interface(mconfig, *this),
+ m_maincpu(*this, Z80_TAG),
+ m_dma(*this, Z80DMA_TAG)
+{
+}
+
+
+//-------------------------------------------------
+// device_start - device-specific startup
+//-------------------------------------------------
+
+void databoard_4107_device::device_start()
+{
+}
+
+
+//-------------------------------------------------
+// device_reset - device-specific reset
+//-------------------------------------------------
+
+void databoard_4107_device::device_reset()
+{
+ m_cs = false;
+}
+
+
+
+//**************************************************************************
+// ABC BUS INTERFACE
+//**************************************************************************
+
+//-------------------------------------------------
+// abcbus_cs -
+//-------------------------------------------------
+
+void databoard_4107_device::abcbus_cs(uint8_t data)
+{
+}
+
+
+//-------------------------------------------------
+// abcbus_stat -
+//-------------------------------------------------
+
+uint8_t databoard_4107_device::abcbus_stat()
+{
+ uint8_t data = 0xff;
+
+ if (m_cs)
+ {
+ }
+
+ return data;
+}
+
+
+//-------------------------------------------------
+// abcbus_inp -
+//-------------------------------------------------
+
+uint8_t databoard_4107_device::abcbus_inp()
+{
+ uint8_t data = 0xff;
+
+ if (m_cs)
+ {
+ }
+
+ return data;
+}
+
+
+//-------------------------------------------------
+// abcbus_out -
+//-------------------------------------------------
+
+void databoard_4107_device::abcbus_out(uint8_t data)
+{
+ if (!m_cs) return;
+}
+
+
+//-------------------------------------------------
+// abcbus_c1 -
+//-------------------------------------------------
+
+void databoard_4107_device::abcbus_c1(uint8_t data)
+{
+ if (m_cs)
+ {
+ }
+}
+
+
+//-------------------------------------------------
+// abcbus_c3 -
+//-------------------------------------------------
+
+void databoard_4107_device::abcbus_c3(uint8_t data)
+{
+ if (m_cs)
+ {
+ m_maincpu->reset();
+ }
+}
diff --git a/src/devices/bus/abcbus/db4107.h b/src/devices/bus/abcbus/db4107.h
new file mode 100644
index 00000000000..afeb2b0ffb2
--- /dev/null
+++ b/src/devices/bus/abcbus/db4107.h
@@ -0,0 +1,65 @@
+// license:BSD-3-Clause
+// copyright-holders:Curt Coder
+/**********************************************************************
+
+ DataBoard 4107 Winchester interface emulation
+
+*********************************************************************/
+
+#ifndef MAME_BUS_ABCBUS_DB4107_H
+#define MAME_BUS_ABCBUS_DB4107_H
+
+#pragma once
+
+#include "abcbus.h"
+#include "cpu/z80/z80.h"
+#include "machine/z80dma.h"
+
+
+
+//**************************************************************************
+// TYPE DEFINITIONS
+//**************************************************************************
+
+// ======================> databoard_4107_device
+
+class databoard_4107_device : public device_t,
+ public device_abcbus_card_interface
+{
+public:
+ // construction/destruction
+ databoard_4107_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
+
+protected:
+ // device-level overrides
+ virtual void device_start() override ATTR_COLD;
+ virtual void device_reset() override ATTR_COLD;
+
+ // optional information overrides
+ virtual const tiny_rom_entry *device_rom_region() const override ATTR_COLD;
+ virtual void device_add_mconfig(machine_config &config) override ATTR_COLD;
+ virtual ioport_constructor device_input_ports() const override ATTR_COLD;
+
+ // device_abcbus_interface overrides
+ virtual void abcbus_cs(uint8_t data) override;
+ virtual uint8_t abcbus_inp() override;
+ virtual void abcbus_out(uint8_t data) override;
+ virtual uint8_t abcbus_stat() override;
+ virtual void abcbus_c1(uint8_t data) override;
+ virtual void abcbus_c3(uint8_t data) override;
+
+private:
+ required_device<z80_device> m_maincpu;
+ required_device<z80dma_device> m_dma;
+
+ bool m_cs;
+
+ void databoard_4107_io(address_map &map) ATTR_COLD;
+ void databoard_4107_mem(address_map &map) ATTR_COLD;
+};
+
+
+// device type definition
+DECLARE_DEVICE_TYPE(DATABOARD_4107, databoard_4107_device)
+
+#endif // MAME_BUS_ABCBUS_DB4107_H
diff --git a/src/devices/bus/abcbus/db4112.cpp b/src/devices/bus/abcbus/db4112.cpp
new file mode 100644
index 00000000000..a2631f0b244
--- /dev/null
+++ b/src/devices/bus/abcbus/db4112.cpp
@@ -0,0 +1,215 @@
+// license:BSD-3-Clause
+// copyright-holders:Curt Coder
+/**********************************************************************
+
+ DataBoard 4112-23 floppy disk controller emulation
+
+*********************************************************************/
+
+#include "emu.h"
+#include "db4112.h"
+
+
+
+//**************************************************************************
+// MACROS / CONSTANTS
+//**************************************************************************
+
+#define Z80_TAG "maincpu"
+
+
+//**************************************************************************
+// DEVICE DEFINITIONS
+//**************************************************************************
+
+DEFINE_DEVICE_TYPE(DATABOARD_4112, abc_databoard_4112_device, "abc_db4112", "DataBoard 4112")
+
+
+//-------------------------------------------------
+// ROM( databoard_4112 )
+//-------------------------------------------------
+
+ROM_START( databoard_4112 )
+ ROM_DEFAULT_BIOS( "fd55" )
+ ROM_REGION( 0x2000, Z80_TAG, 0 )
+ ROM_SYSTEM_BIOS( 0, "119", "CONT 4112 Ver 1.19 85-07-04" )
+ ROMX_LOAD("fpy_int_4112-23_4112_ver1.19.bin", 0x0000, 0x2000, CRC(74c355e5) SHA1(cc434af31897cf326cb2bb2a630f74a8d8174c3c), ROM_BIOS(0) )
+ ROM_SYSTEM_BIOS( 1, "fd55", "TEAC FD55 (860702)" )
+ ROMX_LOAD("fpy_int_4112-23_teac_fd55.bin", 0x0000, 0x2000, CRC(9175ceb8) SHA1(95c150d3152df318abd9267915d5669d2ec33895), ROM_BIOS(1) )
+ROM_END
+
+
+//-------------------------------------------------
+// rom_region - device-specific ROM region
+//-------------------------------------------------
+
+const tiny_rom_entry *abc_databoard_4112_device::device_rom_region() const
+{
+ return ROM_NAME( databoard_4112 );
+}
+
+
+//-------------------------------------------------
+// ADDRESS_MAP( databoard_4112_mem )
+//-------------------------------------------------
+
+void abc_databoard_4112_device::databoard_4112_mem(address_map &map)
+{
+ map(0x0000, 0x1fff).rom().region(Z80_TAG, 0);
+}
+
+
+//-------------------------------------------------
+// ADDRESS_MAP( databoard_4112_io )
+//-------------------------------------------------
+
+void abc_databoard_4112_device::databoard_4112_io(address_map &map)
+{
+}
+
+
+//-------------------------------------------------
+// device_add_mconfig - add device configuration
+//-------------------------------------------------
+
+void abc_databoard_4112_device::device_add_mconfig(machine_config &config)
+{
+ Z80(config, m_maincpu, 4000000);
+ m_maincpu->set_memory_map(&abc_databoard_4112_device::databoard_4112_mem);
+ m_maincpu->set_io_map(&abc_databoard_4112_device::databoard_4112_io);
+}
+
+
+//-------------------------------------------------
+// INPUT_PORTS( databoard_4112 )
+//-------------------------------------------------
+
+INPUT_PORTS_START( databoard_4112 )
+INPUT_PORTS_END
+
+
+//-------------------------------------------------
+// input_ports - device-specific input ports
+//-------------------------------------------------
+
+ioport_constructor abc_databoard_4112_device::device_input_ports() const
+{
+ return INPUT_PORTS_NAME( databoard_4112 );
+}
+
+
+
+//**************************************************************************
+// LIVE DEVICE
+//**************************************************************************
+
+//-------------------------------------------------
+// abc_databoard_4112_device - constructor
+//-------------------------------------------------
+
+abc_databoard_4112_device::abc_databoard_4112_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) :
+ device_t(mconfig, DATABOARD_4112, tag, owner, clock),
+ device_abcbus_card_interface(mconfig, *this),
+ m_maincpu(*this, Z80_TAG)
+{
+}
+
+
+//-------------------------------------------------
+// device_start - device-specific startup
+//-------------------------------------------------
+
+void abc_databoard_4112_device::device_start()
+{
+}
+
+
+//-------------------------------------------------
+// device_reset - device-specific reset
+//-------------------------------------------------
+
+void abc_databoard_4112_device::device_reset()
+{
+ m_cs = false;
+}
+
+
+
+//**************************************************************************
+// ABC BUS INTERFACE
+//**************************************************************************
+
+//-------------------------------------------------
+// abcbus_cs -
+//-------------------------------------------------
+
+void abc_databoard_4112_device::abcbus_cs(uint8_t data)
+{
+}
+
+
+//-------------------------------------------------
+// abcbus_stat -
+//-------------------------------------------------
+
+uint8_t abc_databoard_4112_device::abcbus_stat()
+{
+ uint8_t data = 0xff;
+
+ if (m_cs)
+ {
+ }
+
+ return data;
+}
+
+
+//-------------------------------------------------
+// abcbus_inp -
+//-------------------------------------------------
+
+uint8_t abc_databoard_4112_device::abcbus_inp()
+{
+ uint8_t data = 0xff;
+
+ if (m_cs)
+ {
+ }
+
+ return data;
+}
+
+
+//-------------------------------------------------
+// abcbus_out -
+//-------------------------------------------------
+
+void abc_databoard_4112_device::abcbus_out(uint8_t data)
+{
+ if (!m_cs) return;
+}
+
+
+//-------------------------------------------------
+// abcbus_c1 -
+//-------------------------------------------------
+
+void abc_databoard_4112_device::abcbus_c1(uint8_t data)
+{
+ if (m_cs)
+ {
+ }
+}
+
+
+//-------------------------------------------------
+// abcbus_c3 -
+//-------------------------------------------------
+
+void abc_databoard_4112_device::abcbus_c3(uint8_t data)
+{
+ if (m_cs)
+ {
+ m_maincpu->reset();
+ }
+}
diff --git a/src/devices/bus/abcbus/db4112.h b/src/devices/bus/abcbus/db4112.h
new file mode 100644
index 00000000000..5594d06015b
--- /dev/null
+++ b/src/devices/bus/abcbus/db4112.h
@@ -0,0 +1,63 @@
+// license:BSD-3-Clause
+// copyright-holders:Curt Coder
+/**********************************************************************
+
+ DataBoard 4112-23 floppy disk controller emulation
+
+*********************************************************************/
+
+#ifndef MAME_BUS_ABCBUS_DB4112_H
+#define MAME_BUS_ABCBUS_DB4112_H
+
+#pragma once
+
+#include "abcbus.h"
+#include "cpu/z80/z80.h"
+
+
+
+//**************************************************************************
+// TYPE DEFINITIONS
+//**************************************************************************
+
+// ======================> abc_databoard_4112_device
+
+class abc_databoard_4112_device : public device_t,
+ public device_abcbus_card_interface
+{
+public:
+ // construction/destruction
+ abc_databoard_4112_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
+
+protected:
+ // device-level overrides
+ virtual void device_start() override ATTR_COLD;
+ virtual void device_reset() override ATTR_COLD;
+
+ // optional information overrides
+ virtual const tiny_rom_entry *device_rom_region() const override ATTR_COLD;
+ virtual void device_add_mconfig(machine_config &config) override ATTR_COLD;
+ virtual ioport_constructor device_input_ports() const override ATTR_COLD;
+
+ // device_abcbus_interface overrides
+ virtual void abcbus_cs(uint8_t data) override;
+ virtual uint8_t abcbus_inp() override;
+ virtual void abcbus_out(uint8_t data) override;
+ virtual uint8_t abcbus_stat() override;
+ virtual void abcbus_c1(uint8_t data) override;
+ virtual void abcbus_c3(uint8_t data) override;
+
+private:
+ required_device<z80_device> m_maincpu;
+
+ bool m_cs;
+
+ void databoard_4112_io(address_map &map) ATTR_COLD;
+ void databoard_4112_mem(address_map &map) ATTR_COLD;
+};
+
+
+// device type definition
+DECLARE_DEVICE_TYPE(DATABOARD_4112, abc_databoard_4112_device)
+
+#endif // MAME_BUS_ABCBUS_DB4112_H
diff --git a/src/devices/bus/abcbus/fd2.cpp b/src/devices/bus/abcbus/fd2.cpp
index 12607f51699..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"
+
//**************************************************************************
@@ -86,7 +88,7 @@ const tiny_rom_entry *abc_fd2_device::device_rom_region() const
// status_w -
//-------------------------------------------------
-WRITE8_MEMBER( abc_fd2_device::status_w )
+void abc_fd2_device::status_w(uint8_t data)
{
/*
@@ -138,17 +140,17 @@ void abc_fd2_device::abc_fd2_io(address_map &map)
// Z80PIO
//-------------------------------------------------
-READ8_MEMBER( abc_fd2_device::pio_pa_r )
+uint8_t abc_fd2_device::pio_pa_r()
{
return m_data;
}
-WRITE8_MEMBER( abc_fd2_device::pio_pa_w )
+void abc_fd2_device::pio_pa_w(uint8_t data)
{
m_data = data;
}
-READ8_MEMBER( abc_fd2_device::pio_pb_r )
+uint8_t abc_fd2_device::pio_pb_r()
{
/*
@@ -174,7 +176,7 @@ READ8_MEMBER( abc_fd2_device::pio_pb_r )
return data;
}
-WRITE8_MEMBER( abc_fd2_device::pio_pb_w )
+void abc_fd2_device::pio_pb_w(uint8_t data)
{
/*
@@ -193,8 +195,8 @@ WRITE8_MEMBER( abc_fd2_device::pio_pb_w )
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);
@@ -228,9 +230,11 @@ static void abc_fd2_floppies(device_slot_interface &device)
device.option_add("525sssd", FLOPPY_525_SSSD);
}
-FLOPPY_FORMATS_MEMBER( abc_fd2_device::floppy_formats )
- FLOPPY_ABC_FD2_FORMAT
-FLOPPY_FORMATS_END
+void abc_fd2_device::floppy_formats(format_registration &fr)
+{
+ fr.add_fm_containers();
+ fr.add(FLOPPY_ABC_FD2_FORMAT);
+}
//-------------------------------------------------
@@ -256,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);
- FLOPPY_CONNECTOR(config, m_floppy1, abc_fd2_floppies, "525sssd", abc_fd2_device::floppy_formats);
+ 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);
}
@@ -275,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 ff635575472..555f90a1d8e 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"
@@ -36,12 +35,12 @@ public:
protected:
// device-level overrides
- virtual void device_start() override;
- virtual void device_reset() override;
+ virtual void device_start() override ATTR_COLD;
+ virtual void device_reset() override ATTR_COLD;
// optional information overrides
- virtual const tiny_rom_entry *device_rom_region() const override;
- virtual void device_add_mconfig(machine_config &config) override;
+ virtual const tiny_rom_entry *device_rom_region() const override ATTR_COLD;
+ virtual void device_add_mconfig(machine_config &config) override ATTR_COLD;
// device_abcbus_interface overrides
virtual void abcbus_cs(uint8_t data) override;
@@ -53,23 +52,22 @@ protected:
virtual uint8_t abcbus_xmemfl(offs_t offset) override;
private:
- DECLARE_READ8_MEMBER( pio_pa_r );
- DECLARE_WRITE8_MEMBER( pio_pa_w );
- DECLARE_READ8_MEMBER( pio_pb_r );
- DECLARE_WRITE8_MEMBER( pio_pb_w );
+ uint8_t pio_pa_r();
+ void pio_pa_w(uint8_t data);
+ uint8_t pio_pb_r();
+ void pio_pb_w(uint8_t data);
- DECLARE_WRITE8_MEMBER( status_w );
+ void status_w(uint8_t data);
- DECLARE_FLOPPY_FORMATS( floppy_formats );
+ static void floppy_formats(format_registration &fr);
- void abc_fd2_io(address_map &map);
- void abc_fd2_mem(address_map &map);
+ void abc_fd2_io(address_map &map) ATTR_COLD;
+ void abc_fd2_mem(address_map &map) ATTR_COLD;
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/hdc.cpp b/src/devices/bus/abcbus/hdc.cpp
deleted file mode 100644
index 2febc491d79..00000000000
--- a/src/devices/bus/abcbus/hdc.cpp
+++ /dev/null
@@ -1,143 +0,0 @@
-// license:BSD-3-Clause
-// copyright-holders:Curt Coder
-/**********************************************************************
-
- Luxor XEBEC Winchester controller card emulation
-
-*********************************************************************/
-
-#include "emu.h"
-#include "hdc.h"
-
-
-
-//**************************************************************************
-// MACROS / CONSTANTS
-//**************************************************************************
-
-#define Z80_TAG "z80"
-#define SASIBUS_TAG "sasi"
-
-
-
-//**************************************************************************
-// DEVICE DEFINITIONS
-//**************************************************************************
-
-DEFINE_DEVICE_TYPE(ABC_HDC, abc_hdc_device, "abc_hdc", "ABC HDC")
-
-
-//-------------------------------------------------
-// ROM( abc_hdc )
-//-------------------------------------------------
-
-ROM_START( abc_hdc )
- ROM_REGION( 0x800, Z80_TAG, 0 )
- ROM_SYSTEM_BIOS( 0, "st4038", "Seagate ST4038 (CHS: 733,5,17,512)" )
- ROMX_LOAD( "st4038.6c", 0x000, 0x800, CRC(4c803b87) SHA1(1141bb51ad9200fc32d92a749460843dc6af8953), ROM_BIOS(0) ) // Seagate ST4038 (http://stason.org/TULARC/pc/hard-drives-hdd/seagate/ST4038-1987-31MB-5-25-FH-MFM-ST412.html)
- ROM_SYSTEM_BIOS( 1, "st225", "Seagate ST225 (CHS: 615,4,17,512)" )
- ROMX_LOAD( "st225.6c", 0x000, 0x800, CRC(c9f68f81) SHA1(7ff8b2a19f71fe0279ab3e5a0a5fffcb6030360c), ROM_BIOS(1) ) // Seagate ST225 (http://stason.org/TULARC/pc/hard-drives-hdd/seagate/ST225-21MB-5-25-HH-MFM-ST412.html)
-ROM_END
-
-
-//-------------------------------------------------
-// rom_region - device-specific ROM region
-//-------------------------------------------------
-
-const tiny_rom_entry *abc_hdc_device::device_rom_region() const
-{
- return ROM_NAME( abc_hdc );
-}
-
-
-//-------------------------------------------------
-// ADDRESS_MAP( abc_hdc_mem )
-//-------------------------------------------------
-
-void abc_hdc_device::abc_hdc_mem(address_map &map)
-{
- map(0x0000, 0x0ff).rom().region(Z80_TAG, 0);
-}
-
-
-//-------------------------------------------------
-// ADDRESS_MAP( abc_hdc_io )
-//-------------------------------------------------
-
-void abc_hdc_device::abc_hdc_io(address_map &map)
-{
-}
-
-
-//-------------------------------------------------
-// z80_daisy_config daisy_chain
-//-------------------------------------------------
-
-static const z80_daisy_config daisy_chain[] =
-{
- { nullptr }
-};
-
-
-//-------------------------------------------------
-// device_add_mconfig - add device configuration
-//-------------------------------------------------
-
-void abc_hdc_device::device_add_mconfig(machine_config &config)
-{
- Z80(config, m_maincpu, 4000000);
- m_maincpu->set_memory_map(&abc_hdc_device::abc_hdc_mem);
- m_maincpu->set_io_map(&abc_hdc_device::abc_hdc_io);
- m_maincpu->set_daisy_config(daisy_chain);
-
- scsi_port_device &scsi(SCSI_PORT(config, SASIBUS_TAG));
- scsi.set_slot_device(1, "harddisk", SCSIHD, DEVICE_INPUT_DEFAULTS_NAME(SCSI_ID_0));
-}
-
-
-//**************************************************************************
-// LIVE DEVICE
-//**************************************************************************
-
-//-------------------------------------------------
-// abc_hdc_device - constructor
-//-------------------------------------------------
-
-abc_hdc_device::abc_hdc_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
- : device_t(mconfig, ABC_HDC, tag, owner, clock)
- , device_abcbus_card_interface(mconfig, *this)
- , m_maincpu(*this, Z80_TAG)
-{
-}
-
-
-//-------------------------------------------------
-// device_start - device-specific startup
-//-------------------------------------------------
-
-void abc_hdc_device::device_start()
-{
-}
-
-
-//-------------------------------------------------
-// device_reset - device-specific reset
-//-------------------------------------------------
-
-void abc_hdc_device::device_reset()
-{
-}
-
-
-
-//**************************************************************************
-// ABC BUS INTERFACE
-//**************************************************************************
-
-//-------------------------------------------------
-// abcbus_cs -
-//-------------------------------------------------
-
-void abc_hdc_device::abcbus_cs(uint8_t data)
-{
-}
diff --git a/src/devices/bus/abcbus/hdc.h b/src/devices/bus/abcbus/hdc.h
deleted file mode 100644
index 075caad3778..00000000000
--- a/src/devices/bus/abcbus/hdc.h
+++ /dev/null
@@ -1,57 +0,0 @@
-// license:BSD-3-Clause
-// copyright-holders:Curt Coder
-/**********************************************************************
-
- Luxor XEBEC Winchester controller card emulation
-
-*********************************************************************/
-
-#ifndef MAME_BUS_ABCBUS_HDC_H
-#define MAME_BUS_ABCBUS_HDC_H
-
-#pragma once
-
-#include "abcbus.h"
-#include "cpu/z80/z80.h"
-#include "machine/z80daisy.h"
-#include "bus/scsi/scsihd.h"
-
-
-
-//**************************************************************************
-// TYPE DEFINITIONS
-//**************************************************************************
-
-// ======================> abc_hdc_device
-
-class abc_hdc_device : public device_t,
- public device_abcbus_card_interface
-{
-public:
- // construction/destruction
- abc_hdc_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 void device_add_mconfig(machine_config &config) override;
-
- // device_abcbus_interface overrides
- virtual void abcbus_cs(uint8_t data) override;
-
-private:
- required_device<z80_device> m_maincpu;
-
- void abc_hdc_io(address_map &map);
- void abc_hdc_mem(address_map &map);
-};
-
-
-// device type definition
-DECLARE_DEVICE_TYPE(ABC_HDC, abc_hdc_device)
-
-#endif // MAME_BUS_ABCBUS_HDC_H
diff --git a/src/devices/bus/abcbus/lux10828.cpp b/src/devices/bus/abcbus/lux10828.cpp
index bc6f14082ed..2516229d941 100644
--- a/src/devices/bus/abcbus/lux10828.cpp
+++ b/src/devices/bus/abcbus/lux10828.cpp
@@ -106,11 +106,17 @@ Notes:
0704: rr a
0706: call $073F
+ There is an alternate format function in the controller firmware that allows to set a secret byte which is stored in the sector header.
+ Copy protected software checks the secret byte read from the sector header and refuses to start if the disk has not been appropriately formatted.
+
*/
#include "emu.h"
#include "lux10828.h"
+#include "formats/abc800_dsk.h"
+#include "formats/abc800i_dsk.h"
+
//**************************************************************************
@@ -197,17 +203,17 @@ void luxor_55_10828_device::luxor_55_10828_io(address_map &map)
// Z80PIO
//-------------------------------------------------
-READ8_MEMBER( luxor_55_10828_device::pio_pa_r )
+uint8_t luxor_55_10828_device::pio_pa_r()
{
return m_data;
}
-WRITE8_MEMBER( luxor_55_10828_device::pio_pa_w )
+void luxor_55_10828_device::pio_pa_w(uint8_t data)
{
m_data = data;
}
-READ8_MEMBER( luxor_55_10828_device::pio_pb_r )
+uint8_t luxor_55_10828_device::pio_pb_r()
{
/*
@@ -228,13 +234,13 @@ READ8_MEMBER( 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
@@ -252,7 +258,7 @@ READ8_MEMBER( luxor_55_10828_device::pio_pb_r )
return data;
}
-WRITE8_MEMBER( luxor_55_10828_device::pio_pb_w )
+void luxor_55_10828_device::pio_pb_w(uint8_t data)
{
/*
@@ -296,11 +302,14 @@ static void abc_floppies(device_slot_interface &device)
device.option_add("8dsdd", FLOPPY_8_DSDD);
}
-FLOPPY_FORMATS_MEMBER( luxor_55_10828_device::floppy_formats )
- FLOPPY_ABC800_FORMAT
-FLOPPY_FORMATS_END
+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);
@@ -308,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;
@@ -338,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);
- FLOPPY_CONNECTOR(config, m_floppy1, abc_floppies, "525ssdd", luxor_55_10828_device::floppy_formats);
+ 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);
}
@@ -367,12 +376,12 @@ INPUT_PORTS_START( luxor_55_10828 )
PORT_DIPSETTING( 0x00, "44 (ABC 832/834/850)" )
PORT_DIPSETTING( 0x01, "45 (ABC 830)" )
- PORT_START("S2,S3")
+ PORT_START("S2_S3")
PORT_DIPNAME( 0x01, 0x01, "Shift Clock" )
PORT_DIPSETTING( 0x00, "2 MHz" )
PORT_DIPSETTING( 0x01, "4 MHz" )
- PORT_START("S4,S5")
+ PORT_START("S4_S5")
PORT_DIPNAME( 0x01, 0x01, "Write Precompensation" )
PORT_DIPSETTING( 0x00, "Always On" )
PORT_DIPSETTING( 0x01, "Programmable" )
@@ -404,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),
@@ -414,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)
{
}
@@ -433,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();
@@ -455,8 +461,7 @@ void luxor_55_10828_device::device_reset()
{
m_cs = false;
- address_space &space = m_maincpu->space(AS_PROGRAM);
- ctrl_w(space, 0, 0);
+ ctrl_w(0);
m_data = 0;
}
@@ -574,7 +579,7 @@ void luxor_55_10828_device::abcbus_c3(uint8_t data)
// ctrl_w -
//-------------------------------------------------
-WRITE8_MEMBER( luxor_55_10828_device::ctrl_w )
+void luxor_55_10828_device::ctrl_w(uint8_t data)
{
/*
@@ -595,13 +600,12 @@ WRITE8_MEMBER( luxor_55_10828_device::ctrl_w )
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);
@@ -618,7 +622,7 @@ WRITE8_MEMBER( luxor_55_10828_device::ctrl_w )
m_wait_enable = BIT(data, 6);
// FDC master reset
- if (!BIT(data, 7)) m_fdc->soft_reset();
+ m_fdc->mr_w(BIT(data, 7));
}
@@ -626,7 +630,7 @@ WRITE8_MEMBER( luxor_55_10828_device::ctrl_w )
// status_w -
//-------------------------------------------------
-WRITE8_MEMBER( luxor_55_10828_device::status_w )
+void luxor_55_10828_device::status_w(uint8_t data)
{
/*
@@ -657,7 +661,7 @@ WRITE8_MEMBER( luxor_55_10828_device::status_w )
// fdc_r -
//-------------------------------------------------
-READ8_MEMBER( luxor_55_10828_device::fdc_r )
+uint8_t luxor_55_10828_device::fdc_r(offs_t offset)
{
if (machine().side_effects_disabled())
return 0xff;
@@ -685,7 +689,7 @@ READ8_MEMBER( luxor_55_10828_device::fdc_r )
// fdc_w -
//-------------------------------------------------
-WRITE8_MEMBER( luxor_55_10828_device::fdc_w )
+void luxor_55_10828_device::fdc_w(offs_t offset, uint8_t data)
{
if (machine().side_effects_disabled())
return;
diff --git a/src/devices/bus/abcbus/lux10828.h b/src/devices/bus/abcbus/lux10828.h
index 97ecb787880..9222ad4629e 100644
--- a/src/devices/bus/abcbus/lux10828.h
+++ b/src/devices/bus/abcbus/lux10828.h
@@ -6,15 +6,14 @@
*********************************************************************/
-#ifndef MAME_BUS_ABCBUS_LUXOR10828_H
-#define MAME_BUS_ABCBUS_LUXOR10828_H
+#ifndef MAME_BUS_ABCBUS_LUX10828_H
+#define MAME_BUS_ABCBUS_LUX10828_H
#pragma once
#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"
@@ -58,13 +57,13 @@ public:
protected:
// device-level overrides
- virtual void device_start() override;
- virtual void device_reset() override;
+ virtual void device_start() override ATTR_COLD;
+ virtual void device_reset() override ATTR_COLD;
// optional information 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 const tiny_rom_entry *device_rom_region() const override ATTR_COLD;
+ virtual void device_add_mconfig(machine_config &config) override ATTR_COLD;
+ virtual ioport_constructor device_input_ports() const override ATTR_COLD;
// device_abcbus_interface overrides
virtual void abcbus_cs(uint8_t data) override;
@@ -75,44 +74,42 @@ protected:
virtual void abcbus_c3(uint8_t data) override;
private:
- DECLARE_READ8_MEMBER( pio_pa_r );
- DECLARE_WRITE8_MEMBER( pio_pa_w );
- DECLARE_READ8_MEMBER( pio_pb_r );
- DECLARE_WRITE8_MEMBER( pio_pb_w );
+ uint8_t pio_pa_r();
+ void pio_pa_w(uint8_t data);
+ 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);
- DECLARE_WRITE8_MEMBER( ctrl_w );
- DECLARE_WRITE8_MEMBER( status_w );
- DECLARE_READ8_MEMBER( fdc_r );
- DECLARE_WRITE8_MEMBER( fdc_w );
+ void ctrl_w(uint8_t data);
+ void status_w(uint8_t data);
+ uint8_t fdc_r(offs_t offset);
+ void fdc_w(offs_t offset, uint8_t data);
- DECLARE_FLOPPY_FORMATS( floppy_formats );
+ static void floppy_formats(format_registration &fr);
- void luxor_55_10828_io(address_map &map);
- void luxor_55_10828_mem(address_map &map);
+ void luxor_55_10828_io(address_map &map) ATTR_COLD;
+ void luxor_55_10828_mem(address_map &map) ATTR_COLD;
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
};
// device type definition
DECLARE_DEVICE_TYPE(LUXOR_55_10828, luxor_55_10828_device)
-#endif // MAME_BUS_ABCBUS_LUXOR10828_H
+#endif // MAME_BUS_ABCBUS_LUX10828_H
diff --git a/src/devices/bus/abcbus/lux21046.cpp b/src/devices/bus/abcbus/lux21046.cpp
index 61e03cfa4eb..79a1a6cea55 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"
+
//**************************************************************************
@@ -111,12 +114,14 @@ ROM_START( luxor_55_21046 )
ROM_DEFAULT_BIOS( "v207" )
ROM_SYSTEM_BIOS( 0, "v105", "Luxor v1.05 (1984-10-04)" )
ROMX_LOAD( "cntr 105.6cd", 0x2000, 0x2000, CRC(44043025) SHA1(17487ca35b399bb49d4015bbeede0809db8e772f), ROM_BIOS(0) )
- ROM_SYSTEM_BIOS( 1, "v107", "Luxor v1.07 (1985-07-03)" )
- ROMX_LOAD( "cntr 1.07 6490318-07.6cd", 0x0000, 0x4000, CRC(db8c1c0e) SHA1(8bccd5bc72124984de529ee058df779f06d2c1d5), ROM_BIOS(1) )
- ROM_SYSTEM_BIOS( 2, "v108", "Luxor v1.08 (1986-03-12)" )
- ROMX_LOAD( "cntr 108.6cd", 0x2000, 0x2000, CRC(229764cb) SHA1(a2e2f6f49c31b827efc62f894de9a770b65d109d), ROM_BIOS(2) )
- ROM_SYSTEM_BIOS( 3, "v207", "DiAB v2.07 (1987-06-24)" )
- ROMX_LOAD( "diab 207.6cd", 0x2000, 0x2000, CRC(86622f52) SHA1(61ad271de53152c1640c0b364fce46d1b0b4c7e2), ROM_BIOS(3) )
+ ROM_SYSTEM_BIOS( 1, "v106", "Luxor v1.06 (1984-12-13)" )
+ ROMX_LOAD( "6490318-06.6cd", 0x2000, 0x2000, CRC(7f4726c9) SHA1(cf576456f135877537c5ee56b00a7259160d2c56), ROM_BIOS(1) )
+ ROM_SYSTEM_BIOS( 2, "v107", "Luxor v1.07 (1985-07-03)" )
+ ROMX_LOAD( "cntr 1.07 6490318-07.6cd", 0x0000, 0x4000, CRC(db8c1c0e) SHA1(8bccd5bc72124984de529ee058df779f06d2c1d5), ROM_BIOS(2) )
+ ROM_SYSTEM_BIOS( 3, "v108", "Luxor v1.08 (1986-03-12)" )
+ ROMX_LOAD( "cntr 108.6cd", 0x2000, 0x2000, CRC(229764cb) SHA1(a2e2f6f49c31b827efc62f894de9a770b65d109d), ROM_BIOS(3) )
+ ROM_SYSTEM_BIOS( 4, "v207", "DiAB v2.07 (1987-06-24)" )
+ ROMX_LOAD( "diab 207.6cd", 0x2000, 0x2000, CRC(86622f52) SHA1(61ad271de53152c1640c0b364fce46d1b0b4c7e2), ROM_BIOS(4) )
ROM_REGION( 0x104, "plds", 0 )
ROM_LOAD( "pal16r4.2a", 0x000, 0x104, NO_DUMP)
@@ -159,9 +164,9 @@ void luxor_55_21046_device::luxor_55_21046_io(address_map &map)
map(0x3c, 0x3c).mirror(0xff03).w(FUNC(luxor_55_21046_device::_9b_w));
map(0x4c, 0x4c).mirror(0xff03).w(FUNC(luxor_55_21046_device::_8a_w));
map(0x58, 0x58).mirror(0x0007).select(0xff00).r(FUNC(luxor_55_21046_device::_9a_r));
- map(0x68, 0x6b).mirror(0xff00).r(SAB1793_TAG, FUNC(fd1793_device::read));
- map(0x78, 0x7b).mirror(0xff00).w(SAB1793_TAG, FUNC(fd1793_device::write));
- map(0x80, 0x80).mirror(0xff77).rw(m_dma, FUNC(z80dma_device::bus_r), FUNC(z80dma_device::bus_w));
+ map(0x68, 0x6b).mirror(0xff00).r(m_fdc, FUNC(fd1793_device::read));
+ map(0x78, 0x7b).mirror(0xff00).w(m_fdc, FUNC(fd1793_device::write));
+ map(0x80, 0x80).mirror(0xff77).rw(m_dma, FUNC(z80dma_device::read), FUNC(z80dma_device::write));
}
@@ -224,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;
@@ -232,29 +237,32 @@ WRITE_LINE_MEMBER( luxor_55_21046_device::dma_int_w )
m_maincpu->set_input_line(INPUT_LINE_IRQ0, m_fdc_irq || m_dma_irq);
}
-READ8_MEMBER( luxor_55_21046_device::memory_read_byte )
+uint8_t luxor_55_21046_device::memory_read_byte(offs_t offset)
{
return m_maincpu->space(AS_PROGRAM).read_byte(offset);
}
-WRITE8_MEMBER( luxor_55_21046_device::memory_write_byte )
+void luxor_55_21046_device::memory_write_byte(offs_t offset, uint8_t data)
{
return m_maincpu->space(AS_PROGRAM).write_byte(offset, data);
}
-READ8_MEMBER( luxor_55_21046_device::io_read_byte )
+uint8_t luxor_55_21046_device::io_read_byte(offs_t offset)
{
return m_maincpu->space(AS_IO).read_byte(offset);
}
-WRITE8_MEMBER( luxor_55_21046_device::io_write_byte )
+void luxor_55_21046_device::io_write_byte(offs_t offset, uint8_t data)
{
return m_maincpu->space(AS_IO).write_byte(offset, data);
}
-FLOPPY_FORMATS_MEMBER( luxor_55_21046_device::floppy_formats )
- FLOPPY_ABC800_FORMAT
-FLOPPY_FORMATS_END
+void luxor_55_21046_device::floppy_formats(format_registration &fr)
+{
+ fr.add_mfm_containers();
+ fr.add(FLOPPY_ABC800I_FORMAT);
+ fr.add(FLOPPY_ABC800_FORMAT);
+}
static void abc_floppies(device_slot_interface &device)
{
@@ -266,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;
@@ -296,9 +304,10 @@ void luxor_55_21046_device::device_add_mconfig(machine_config & config)
m_maincpu->set_daisy_config(z80_daisy_chain);
m_maincpu->set_addrmap(AS_PROGRAM, &luxor_55_21046_device::luxor_55_21046_mem);
m_maincpu->set_addrmap(AS_IO, &luxor_55_21046_device::luxor_55_21046_io);
+ m_maincpu->busack_cb().set(m_dma, FUNC(z80dma_device::bai_w));
Z80DMA(config, m_dma, 16_MHz_XTAL / 4);
- m_dma->out_busreq_callback().set_inputline(m_maincpu, INPUT_LINE_HALT);
+ m_dma->out_busreq_callback().set_inputline(m_maincpu, Z80_INPUT_LINE_BUSRQ);
m_dma->out_int_callback().set(FUNC(luxor_55_21046_device::dma_int_w));
m_dma->in_mreq_callback().set(FUNC(luxor_55_21046_device::memory_read_byte));
m_dma->out_mreq_callback().set(FUNC(luxor_55_21046_device::memory_write_byte));
@@ -313,36 +322,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);
- FLOPPY_CONNECTOR(config, m_floppy1, abc_floppies, "525ssdd", luxor_55_21046_device::floppy_formats);
+ 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);
- FLOPPY_CONNECTOR(config, m_floppy1, abc_floppies, "525qd", luxor_55_21046_device::floppy_formats);
+ 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);
- FLOPPY_CONNECTOR(config, m_floppy1, abc_floppies, "525qd", luxor_55_21046_device::floppy_formats);
+ 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);
- FLOPPY_CONNECTOR(config, m_floppy1, abc_floppies, "8dsdd", luxor_55_21046_device::floppy_formats);
+ 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);
- FLOPPY_CONNECTOR(config, m_floppy1, abc_floppies, nullptr, luxor_55_21046_device::floppy_formats);
+ 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);
}
@@ -714,12 +723,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"),
@@ -789,10 +797,9 @@ void luxor_55_21046_device::device_reset()
m_maincpu->reset();
- address_space &space = m_maincpu->space(AS_PROGRAM);
- _4b_w(space, 0, 0);
- _9b_w(space, 0, 0);
- _8a_w(space, 0, 0);
+ _4b_w(0);
+ _9b_w(0);
+ _8a_w(0);
}
@@ -932,9 +939,9 @@ void luxor_55_21046_device::abcbus_c4(uint8_t data)
// 3d_r -
//-------------------------------------------------
-READ8_MEMBER( luxor_55_21046_device::out_r )
+uint8_t luxor_55_21046_device::out_r()
{
- if (m_busy)
+ if (m_busy && !machine().side_effects_disabled())
{
m_busy = 0;
}
@@ -947,7 +954,7 @@ READ8_MEMBER( luxor_55_21046_device::out_r )
// 4d_w -
//-------------------------------------------------
-WRITE8_MEMBER( luxor_55_21046_device::inp_w )
+void luxor_55_21046_device::inp_w(uint8_t data)
{
if (m_busy)
{
@@ -962,7 +969,7 @@ WRITE8_MEMBER( luxor_55_21046_device::inp_w )
// 4b_w -
//-------------------------------------------------
-WRITE8_MEMBER( luxor_55_21046_device::_4b_w )
+void luxor_55_21046_device::_4b_w(uint8_t data)
{
/*
@@ -993,7 +1000,7 @@ WRITE8_MEMBER( luxor_55_21046_device::_4b_w )
// 9b_w -
//-------------------------------------------------
-WRITE8_MEMBER( luxor_55_21046_device::_9b_w )
+void luxor_55_21046_device::_9b_w(uint8_t data)
{
/*
@@ -1011,20 +1018,23 @@ WRITE8_MEMBER( luxor_55_21046_device::_9b_w )
*/
// 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));
}
}
@@ -1033,7 +1043,7 @@ WRITE8_MEMBER( luxor_55_21046_device::_9b_w )
// 8a_w -
//-------------------------------------------------
-WRITE8_MEMBER( luxor_55_21046_device::_8a_w )
+void luxor_55_21046_device::_8a_w(uint8_t data)
{
/*
@@ -1053,7 +1063,7 @@ WRITE8_MEMBER( luxor_55_21046_device::_8a_w )
*/
// FDC master reset
- if (!BIT(data, 0)) m_fdc->soft_reset();
+ m_fdc->mr_w(BIT(data, 0));
// density select
m_fdc->dden_w(BIT(data, 1));
@@ -1066,7 +1076,7 @@ WRITE8_MEMBER( luxor_55_21046_device::_8a_w )
// 9a_r -
//-------------------------------------------------
-READ8_MEMBER( luxor_55_21046_device::_9a_r )
+uint8_t luxor_55_21046_device::_9a_r(offs_t offset)
{
/*
@@ -1089,8 +1099,8 @@ READ8_MEMBER( luxor_55_21046_device::_9a_r )
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 703c419e776..da4a05e2f2f 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"
@@ -59,13 +58,13 @@ protected:
luxor_55_21046_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_start() override ATTR_COLD;
+ virtual void device_reset() override ATTR_COLD;
// optional information 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 const tiny_rom_entry *device_rom_region() const override ATTR_COLD;
+ virtual void device_add_mconfig(machine_config &config) override ATTR_COLD;
+ virtual ioport_constructor device_input_ports() const override ATTR_COLD;
// device_abcbus_interface overrides
virtual void abcbus_cs(uint8_t data) override;
@@ -77,43 +76,42 @@ protected:
virtual void abcbus_c3(uint8_t data) override;
virtual void abcbus_c4(uint8_t data) override;
- DECLARE_FLOPPY_FORMATS( floppy_formats );
+ 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);
- DECLARE_READ8_MEMBER(memory_read_byte);
- DECLARE_WRITE8_MEMBER(memory_write_byte);
- DECLARE_READ8_MEMBER(io_read_byte);
- DECLARE_WRITE8_MEMBER(io_write_byte);
+ 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);
- DECLARE_READ8_MEMBER( out_r );
- DECLARE_WRITE8_MEMBER( inp_w );
- DECLARE_WRITE8_MEMBER( _4b_w );
- DECLARE_WRITE8_MEMBER( _9b_w );
- DECLARE_WRITE8_MEMBER( _8a_w );
- DECLARE_READ8_MEMBER( _9a_r );
+ uint8_t out_r();
+ void inp_w(uint8_t data);
+ void _4b_w(uint8_t data);
+ void _9b_w(uint8_t data);
+ void _8a_w(uint8_t data);
+ uint8_t _9a_r(offs_t offset);
- void luxor_55_21046_io(address_map &map);
- void luxor_55_21046_mem(address_map &map);
+ void luxor_55_21046_io(address_map &map) ATTR_COLD;
+ void luxor_55_21046_mem(address_map &map) ATTR_COLD;
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
@@ -131,8 +129,8 @@ public:
protected:
// optional information overrides
- virtual void device_add_mconfig(machine_config &config) override;
- virtual ioport_constructor device_input_ports() const override;
+ virtual void device_add_mconfig(machine_config &config) override ATTR_COLD;
+ virtual ioport_constructor device_input_ports() const override ATTR_COLD;
};
@@ -146,8 +144,8 @@ public:
protected:
// optional information overrides
- virtual void device_add_mconfig(machine_config &config) override;
- virtual ioport_constructor device_input_ports() const override;
+ virtual void device_add_mconfig(machine_config &config) override ATTR_COLD;
+ virtual ioport_constructor device_input_ports() const override ATTR_COLD;
};
@@ -161,8 +159,8 @@ public:
protected:
// optional information overrides
- virtual void device_add_mconfig(machine_config &config) override;
- virtual ioport_constructor device_input_ports() const override;
+ virtual void device_add_mconfig(machine_config &config) override ATTR_COLD;
+ virtual ioport_constructor device_input_ports() const override ATTR_COLD;
};
@@ -176,8 +174,8 @@ public:
protected:
// optional information overrides
- virtual void device_add_mconfig(machine_config &config) override;
- virtual ioport_constructor device_input_ports() const override;
+ virtual void device_add_mconfig(machine_config &config) override ATTR_COLD;
+ virtual ioport_constructor device_input_ports() const override ATTR_COLD;
};
@@ -191,8 +189,8 @@ public:
protected:
// optional information overrides
- virtual void device_add_mconfig(machine_config &config) override;
- virtual ioport_constructor device_input_ports() const override;
+ virtual void device_add_mconfig(machine_config &config) override ATTR_COLD;
+ virtual ioport_constructor device_input_ports() const override ATTR_COLD;
};
diff --git a/src/devices/bus/abcbus/lux21056.cpp b/src/devices/bus/abcbus/lux21056.cpp
index b8c67ceb99a..3e5d0a0619c 100644
--- a/src/devices/bus/abcbus/lux21056.cpp
+++ b/src/devices/bus/abcbus/lux21056.cpp
@@ -25,17 +25,17 @@
Start the abc800 emulator with the ABC 850 attached on the ABC bus,
with the new CHD and a UFD-DOS floppy mounted:
- $ mess abc800m -bus abc850 -flop1 ufd631 -hard ro202.chd
- $ mess abc800m -bus abc850 -bus:abc850:io2 xebec,bios=basf6186 -flop1 ufd631 -hard basf6186.chd
+ $ mame abc800m -bus abc850 -flop1 ufd631 -hard ro202.chd
+ $ mame abc800m -bus abc850 -bus:abc850:io2 xebec,bios=basf6186 -flop1 ufd631 -hard basf6186.chd
or with the ABC 852 attached:
- $ mess abc800m -bus abc852 -flop1 ufd631 -hard basf6185.chd
- $ mess abc800m -bus abc852 -bus:abc852:io2 xebec,bios=nec5126 -flop1 ufd631 -hard nec5126.chd
+ $ mame abc800m -bus abc852 -flop1 ufd631 -hard basf6185.chd
+ $ mame abc800m -bus abc852 -bus:abc852:io2 xebec,bios=nec5126 -flop1 ufd631 -hard nec5126.chd
or with the ABC 856 attached:
- $ mess abc800m -bus abc856 -flop1 ufd631 -hard micr1325.chd
+ $ mame abc800m -bus abc856 -flop1 ufd631 -hard micr1325.chd
Configure the floppy controller for use with an ABC 850:
@@ -65,9 +65,9 @@
Or skip all of the above and use the preformatted images in the software list:
- $ mess abc800m -bus abc850 -flop1 ufd631 -hard abc850
- $ mess abc800m -bus abc852 -flop1 ufd631 -hard abc852
- $ mess abc800m -bus abc856 -flop1 ufd631 -hard abc856
+ $ mame abc800m -bus abc850 -flop1 ufd631 -hard abc850
+ $ mame abc800m -bus abc852 -flop1 ufd631 -hard abc852
+ $ mame abc800m -bus abc856 -flop1 ufd631 -hard abc856
*/
@@ -150,7 +150,7 @@ void luxor_55_21056_device::luxor_55_21056_io(address_map &map)
{
map.unmap_value_high();
map.global_mask(0xf8);
- map(0x00, 0x00).mirror(0xf0).rw(Z80DMA_TAG, FUNC(z80dma_device::bus_r), FUNC(z80dma_device::bus_w));
+ map(0x00, 0x00).mirror(0xf0).rw(Z80DMA_TAG, FUNC(z80dma_device::read), FUNC(z80dma_device::write));
map(0x08, 0x08).r(FUNC(luxor_55_21056_device::sasi_status_r));
map(0x18, 0x18).w(FUNC(luxor_55_21056_device::stat_w));
map(0x28, 0x28).r(FUNC(luxor_55_21056_device::out_r));
@@ -177,38 +177,38 @@ static const z80_daisy_config daisy_chain[] =
// Z80DMA
//-------------------------------------------------
-READ8_MEMBER( luxor_55_21056_device::memory_read_byte )
+uint8_t luxor_55_21056_device::memory_read_byte(offs_t offset)
{
return m_maincpu->space(AS_PROGRAM).read_byte(offset);
}
-WRITE8_MEMBER( luxor_55_21056_device::memory_write_byte )
+void luxor_55_21056_device::memory_write_byte(offs_t offset, uint8_t data)
{
return m_maincpu->space(AS_PROGRAM).write_byte(offset, data);
}
-READ8_MEMBER( luxor_55_21056_device::io_read_byte )
+uint8_t luxor_55_21056_device::io_read_byte(offs_t offset)
{
return m_maincpu->space(AS_IO).read_byte(offset);
}
-WRITE8_MEMBER( luxor_55_21056_device::io_write_byte )
+void luxor_55_21056_device::io_write_byte(offs_t offset, uint8_t data)
{
return m_maincpu->space(AS_IO).write_byte(offset, 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;
if (m_sasi_bsy)
{
- m_sasibus->write_sel(!m_sasi_bsy);
+ m_sasibus->write_sel(0);
}
}
-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,22 +222,23 @@ 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;
if (m_sasi_req)
{
- m_sasibus->write_ack(!m_sasi_req);
+ m_req = 0;
+ m_sasibus->write_ack(!m_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;
}
@@ -253,9 +254,10 @@ void luxor_55_21056_device::device_add_mconfig(machine_config &config)
m_maincpu->set_memory_map(&luxor_55_21056_device::luxor_55_21056_mem);
m_maincpu->set_io_map(&luxor_55_21056_device::luxor_55_21056_io);
m_maincpu->set_daisy_config(daisy_chain);
+ m_maincpu->busack_cb().set(m_dma, FUNC(z80dma_device::bai_w));
Z80DMA(config, m_dma, XTAL(8'000'000)/2);
- m_dma->out_busreq_callback().set_inputline(m_maincpu, INPUT_LINE_HALT);
+ m_dma->out_busreq_callback().set_inputline(m_maincpu, Z80_INPUT_LINE_BUSRQ);
m_dma->out_int_callback().set_inputline(m_maincpu, INPUT_LINE_IRQ0);
m_dma->in_mreq_callback().set(FUNC(luxor_55_21056_device::memory_read_byte));
m_dma->out_mreq_callback().set(FUNC(luxor_55_21056_device::memory_write_byte));
@@ -490,7 +492,7 @@ void luxor_55_21056_device::abcbus_c3(uint8_t data)
// sasi_status_r -
//-------------------------------------------------
-READ8_MEMBER( luxor_55_21056_device::sasi_status_r )
+uint8_t luxor_55_21056_device::sasi_status_r()
{
/*
@@ -511,8 +513,8 @@ READ8_MEMBER( luxor_55_21056_device::sasi_status_r )
data |= m_rdy ^ STAT_DIR;
- data |= !m_sasi_req << 1;
- data |= !m_sasi_io << 2;
+ data |= (m_req || m_sasi_req) << 1;
+ data |= m_sasi_io << 2;
data |= !m_sasi_cd << 3;
data |= !m_sasi_msg << 4;
data |= !m_sasi_bsy << 5;
@@ -525,7 +527,7 @@ READ8_MEMBER( luxor_55_21056_device::sasi_status_r )
// stat_w -
//-------------------------------------------------
-WRITE8_MEMBER( luxor_55_21056_device::stat_w )
+void luxor_55_21056_device::stat_w(uint8_t data)
{
m_stat = data;
@@ -537,7 +539,7 @@ WRITE8_MEMBER( luxor_55_21056_device::stat_w )
// out_r -
//-------------------------------------------------
-READ8_MEMBER( luxor_55_21056_device::out_r )
+uint8_t luxor_55_21056_device::out_r()
{
uint8_t data = m_out;
@@ -551,7 +553,7 @@ READ8_MEMBER( luxor_55_21056_device::out_r )
// inp_w -
//-------------------------------------------------
-WRITE8_MEMBER( luxor_55_21056_device::inp_w )
+void luxor_55_21056_device::inp_w(uint8_t data)
{
m_inp = data;
@@ -563,11 +565,12 @@ WRITE8_MEMBER( luxor_55_21056_device::inp_w )
// sasi_data_r -
//-------------------------------------------------
-READ8_MEMBER( luxor_55_21056_device::sasi_data_r )
+uint8_t luxor_55_21056_device::sasi_data_r()
{
uint8_t data = m_sasi_data_in->read();
- m_sasibus->write_ack(!m_sasi_req);
+ m_req = !m_sasi_req;
+ m_sasibus->write_ack(!m_req);
return data;
}
@@ -577,7 +580,7 @@ READ8_MEMBER( luxor_55_21056_device::sasi_data_r )
// sasi_data_w -
//-------------------------------------------------
-WRITE8_MEMBER( luxor_55_21056_device::sasi_data_w )
+void luxor_55_21056_device::sasi_data_w(uint8_t data)
{
m_sasi_data = data;
@@ -586,7 +589,8 @@ WRITE8_MEMBER( luxor_55_21056_device::sasi_data_w )
m_sasi_data_out->write(m_sasi_data);
}
- m_sasibus->write_ack(!m_sasi_req);
+ m_req = !m_sasi_req;
+ m_sasibus->write_ack(!m_req);
}
@@ -594,9 +598,10 @@ WRITE8_MEMBER( luxor_55_21056_device::sasi_data_w )
// rdy_reset_r -
//-------------------------------------------------
-READ8_MEMBER( luxor_55_21056_device::rdy_reset_r )
+uint8_t luxor_55_21056_device::rdy_reset_r()
{
- rdy_reset_w(space, offset, 0xff);
+ if (!machine().side_effects_disabled())
+ rdy_reset_w(0xff);
return 0xff;
}
@@ -606,7 +611,7 @@ READ8_MEMBER( luxor_55_21056_device::rdy_reset_r )
// rdy_reset_w -
//-------------------------------------------------
-WRITE8_MEMBER( luxor_55_21056_device::rdy_reset_w )
+void luxor_55_21056_device::rdy_reset_w(uint8_t data)
{
set_rdy(0);
}
@@ -616,9 +621,10 @@ WRITE8_MEMBER( luxor_55_21056_device::rdy_reset_w )
// sasi_sel_r -
//-------------------------------------------------
-READ8_MEMBER( luxor_55_21056_device::sasi_sel_r )
+uint8_t luxor_55_21056_device::sasi_sel_r()
{
- sasi_sel_w(space, offset, 0xff);
+ if (!machine().side_effects_disabled())
+ sasi_sel_w(0xff);
return 0xff;
}
@@ -628,7 +634,7 @@ READ8_MEMBER( luxor_55_21056_device::sasi_sel_r )
// sasi_sel_w -
//-------------------------------------------------
-WRITE8_MEMBER( luxor_55_21056_device::sasi_sel_w )
+void luxor_55_21056_device::sasi_sel_w(uint8_t data)
{
m_sasibus->write_sel(!m_sasi_bsy);
}
@@ -638,9 +644,10 @@ WRITE8_MEMBER( luxor_55_21056_device::sasi_sel_w )
// sasi_rst_r -
//-------------------------------------------------
-READ8_MEMBER( luxor_55_21056_device::sasi_rst_r )
+uint8_t luxor_55_21056_device::sasi_rst_r()
{
- sasi_rst_w(space, offset, 0xff);
+ if (!machine().side_effects_disabled())
+ sasi_rst_w(0xff);
return 0xff;
}
@@ -650,7 +657,7 @@ READ8_MEMBER( luxor_55_21056_device::sasi_rst_r )
// sasi_rst_w -
//-------------------------------------------------
-WRITE8_MEMBER( luxor_55_21056_device::sasi_rst_w )
+void luxor_55_21056_device::sasi_rst_w(uint8_t data)
{
m_sasibus->write_rst(1);
m_sasibus->write_rst(0);
diff --git a/src/devices/bus/abcbus/lux21056.h b/src/devices/bus/abcbus/lux21056.h
index 7103fa5ba9c..9187871567e 100644
--- a/src/devices/bus/abcbus/lux21056.h
+++ b/src/devices/bus/abcbus/lux21056.h
@@ -34,13 +34,13 @@ public:
protected:
// device-level overrides
- virtual void device_start() override;
- virtual void device_reset() override;
+ virtual void device_start() override ATTR_COLD;
+ virtual void device_reset() override ATTR_COLD;
// optional information 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 const tiny_rom_entry *device_rom_region() const override ATTR_COLD;
+ virtual void device_add_mconfig(machine_config &config) override ATTR_COLD;
+ virtual ioport_constructor device_input_ports() const override ATTR_COLD;
// device_abcbus_interface overrides
virtual void abcbus_cs(uint8_t data) override;
@@ -53,32 +53,32 @@ protected:
private:
void set_rdy(int state);
- DECLARE_READ8_MEMBER( memory_read_byte );
- DECLARE_WRITE8_MEMBER( memory_write_byte );
- DECLARE_READ8_MEMBER( io_read_byte );
- DECLARE_WRITE8_MEMBER( io_write_byte );
-
- 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 );
-
- DECLARE_READ8_MEMBER( sasi_status_r );
- DECLARE_WRITE8_MEMBER( stat_w );
- DECLARE_READ8_MEMBER( out_r );
- DECLARE_WRITE8_MEMBER( inp_w );
- DECLARE_READ8_MEMBER( sasi_data_r );
- DECLARE_WRITE8_MEMBER( sasi_data_w );
- DECLARE_READ8_MEMBER( rdy_reset_r );
- DECLARE_WRITE8_MEMBER( rdy_reset_w );
- DECLARE_READ8_MEMBER( sasi_sel_r );
- DECLARE_WRITE8_MEMBER( sasi_sel_w );
- DECLARE_READ8_MEMBER( sasi_rst_r );
- DECLARE_WRITE8_MEMBER( sasi_rst_w );
-
- void luxor_55_21056_io(address_map &map);
- void luxor_55_21056_mem(address_map &map);
+ 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);
+
+ 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);
+ uint8_t out_r();
+ void inp_w(uint8_t data);
+ uint8_t sasi_data_r();
+ void sasi_data_w(uint8_t data);
+ uint8_t rdy_reset_r();
+ void rdy_reset_w(uint8_t data);
+ uint8_t sasi_sel_r();
+ void sasi_sel_w(uint8_t data);
+ uint8_t sasi_rst_r();
+ void sasi_rst_w(uint8_t data);
+
+ void luxor_55_21056_io(address_map &map) ATTR_COLD;
+ void luxor_55_21056_mem(address_map &map) ATTR_COLD;
required_device<z80_device> m_maincpu;
required_device<z80dma_device> m_dma;
@@ -89,6 +89,7 @@ private:
int m_cs;
int m_rdy;
+ int m_req;
int m_sasi_req;
int m_sasi_io;
int m_sasi_cd;
diff --git a/src/devices/bus/abcbus/lux4105.cpp b/src/devices/bus/abcbus/lux4105.cpp
index 1d00d071fc8..1db5d0d3869 100644
--- a/src/devices/bus/abcbus/lux4105.cpp
+++ b/src/devices/bus/abcbus/lux4105.cpp
@@ -6,6 +6,37 @@
*********************************************************************/
+/*
+
+PCB Layout
+----------
+
+DATABOARD 4105-10
+
+|-------------------------------------------|
+|- LS367 LS74 LS32 LS00 LS38 LED|
+|| -|
+|| LS367 LS06 LS38 LS14 ||
+|C C|
+|N ALS08 LS08 81LS96 N|
+|1 2|
+|| 81LS95 74S373 LS273 74S240 ||
+|| -|
+|- SW1 DM8131 LS175 SW2 |
+|-------------------------------------------|
+
+Notes:
+ All IC's shown.
+
+ DM8131 - National Semiconductor DM8131N 6-Bit Unified Bus Comparator
+ LED - Power LED
+ SW1 - Drive settings
+ SW2 - Card address
+ CN1 - 2x32 PCB header, ABC 1600 bus
+ CN2 - 2x25 PCB header, Xebec S1410
+
+*/
+
#include "emu.h"
#include "lux4105.h"
#include "bus/scsi/scsihd.h"
@@ -17,8 +48,12 @@
// MACROS / CONSTANTS
//**************************************************************************
-#define SASIBUS_TAG "sasi"
+#define LOG 0
+#define SASIBUS_TAG "sasi"
+#define DMA_O1 BIT(m_dma, 0)
+#define DMA_O2 BIT(m_dma, 1)
+#define DMA_O3 BIT(m_dma, 2)
//**************************************************************************
@@ -28,64 +63,23 @@
DEFINE_DEVICE_TYPE(LUXOR_4105, luxor_4105_device, "lux4105", "Luxor 4105")
-WRITE_LINE_MEMBER( luxor_4105_device::write_sasi_bsy )
-{
- m_sasi_bsy = state;
-
- if (m_sasi_bsy)
- {
- m_sasibus->write_sel(0);
- }
-}
-
-WRITE_LINE_MEMBER( luxor_4105_device::write_sasi_io )
-{
- m_sasi_io = state;
-
- if (!m_sasi_io)
- {
- m_sasi_data_out->write(m_data);
- }
-
- update_trrq_int();
-}
-
-WRITE_LINE_MEMBER( luxor_4105_device::write_sasi_req )
-{
- m_sasi_req = state;
-
- if (m_sasi_req)
- {
- m_sasibus->write_ack(0);
- }
-
- update_trrq_int();
-}
-
-WRITE_LINE_MEMBER( luxor_4105_device::write_sasi_cd )
-{
- m_sasi_cd = state;
-}
-
-
//-------------------------------------------------
// device_add_mconfig - add device configuration
//-------------------------------------------------
void luxor_4105_device::device_add_mconfig(machine_config &config)
{
- SCSI_PORT(config, m_sasibus);
- m_sasibus->set_data_input_buffer(m_sasi_data_in);
- m_sasibus->bsy_handler().set(FUNC(luxor_4105_device::write_sasi_bsy));
- m_sasibus->req_handler().set(FUNC(luxor_4105_device::write_sasi_req));
- m_sasibus->cd_handler().set(FUNC(luxor_4105_device::write_sasi_cd));
- m_sasibus->io_handler().set(FUNC(luxor_4105_device::write_sasi_io));
- m_sasibus->set_slot_device(1, "harddisk", S1410, DEVICE_INPUT_DEFAULTS_NAME(SCSI_ID_0));
-
- OUTPUT_LATCH(config, m_sasi_data_out);
- m_sasibus->set_output_latch(*m_sasi_data_out);
-
- INPUT_BUFFER(config, m_sasi_data_in);
+ NSCSI_BUS(config, "sasi");
+ NSCSI_CONNECTOR(config, "sasi:0", default_scsi_devices, "s1410");
+ NSCSI_CONNECTOR(config, "sasi:7", default_scsi_devices, "scsicb", true)
+ .option_add_internal("scsicb", NSCSI_CB)
+ .machine_config([this](device_t* device) {
+ downcast<nscsi_callback_device&>(*device).cd_callback().set(*this, FUNC(luxor_4105_device::write_sasi_cd));
+ downcast<nscsi_callback_device&>(*device).bsy_callback().set(*this, FUNC(luxor_4105_device::write_sasi_bsy));
+ downcast<nscsi_callback_device&>(*device).req_callback().set(*this, FUNC(luxor_4105_device::write_sasi_req));
+ downcast<nscsi_callback_device&>(*device).msg_callback().set(*this, FUNC(luxor_4105_device::write_sasi_msg));
+ downcast<nscsi_callback_device&>(*device).io_callback().set(*this, FUNC(luxor_4105_device::write_sasi_io));
+ });
}
@@ -95,26 +89,31 @@ void luxor_4105_device::device_add_mconfig(machine_config &config)
INPUT_PORTS_START( luxor_4105 )
PORT_START("1E")
- PORT_DIPNAME( 0x03, 0x00, "Stepping" ) PORT_DIPLOCATION("1E:1,2")
+ PORT_DIPNAME( 0x03, 0x03, "Stepping" ) PORT_DIPLOCATION("1E:1,2")
PORT_DIPSETTING( 0x00, DEF_STR( Normal ) )
PORT_DIPSETTING( 0x01, "Half (Seagate/Texas)" )
PORT_DIPSETTING( 0x02, "Half (Tandon)" )
PORT_DIPSETTING( 0x03, "Buffered" )
- PORT_DIPNAME( 0x0c, 0x00, "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" )
PORT_DIPSETTING( 0x0c, "8" )
- PORT_DIPNAME( 0xf0, 0x00, "Drive Type" ) PORT_DIPLOCATION("1E:5,6,7,8")
+ PORT_DIPNAME( 0xf0, 0x30, "Drive Type" ) PORT_DIPLOCATION("1E:5,6,7,8")
PORT_DIPSETTING( 0x00, "Seagate ST506" )
PORT_DIPSETTING( 0x10, "Rodime RO100" )
PORT_DIPSETTING( 0x20, "Shugart SA600" )
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" )
+
+ PORT_START("S1")
+ PORT_CONFNAME( 0x01, 0x01, "DMA Timing" )
+ PORT_CONFSETTING( 0x00, "1043/1044" ) // a. TREN connected via delay circuit to OUT latch enable
+ PORT_CONFSETTING( 0x01, "1045/1046" ) // b. TREN connected directly to OUT latch enable
INPUT_PORTS_END
@@ -128,36 +127,6 @@ ioport_constructor luxor_4105_device::device_input_ports() const
}
-//**************************************************************************
-// INLINE HELPERS
-//**************************************************************************
-
-inline void luxor_4105_device::update_trrq_int()
-{
- bool cd = !m_sasi_cd;
- bool req = !m_sasi_req;
- int trrq = (cd & !req) ? 0 : 1;
-
- if (BIT(m_dma, 5))
- {
- m_slot->irq_w(trrq ? CLEAR_LINE : ASSERT_LINE);
- }
- else
- {
- m_slot->irq_w(CLEAR_LINE);
- }
-
- if (BIT(m_dma, 6))
- {
- m_slot->trrq_w(trrq);
- }
- else
- {
- m_slot->trrq_w(1);
- }
-}
-
-
//**************************************************************************
// LIVE DEVICE
@@ -170,18 +139,14 @@ inline void luxor_4105_device::update_trrq_int()
luxor_4105_device::luxor_4105_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) :
device_t(mconfig, LUXOR_4105, tag, owner, clock),
device_abcbus_card_interface(mconfig, *this),
- m_sasibus(*this, SASIBUS_TAG),
- m_sasi_data_out(*this, "sasi_data_out"),
- m_sasi_data_in(*this, "sasi_data_in"),
+ m_sasi(*this, "sasi:7:scsicb"),
m_1e(*this, "1E"),
m_5e(*this, "5E"),
m_cs(false),
- m_data(0),
m_dma(0),
- m_sasi_bsy(false),
- m_sasi_req(false),
- m_sasi_cd(false),
- m_sasi_io(false)
+ m_pren(1),
+ m_prac(1),
+ m_trrq(1)
{
}
@@ -194,8 +159,12 @@ void luxor_4105_device::device_start()
{
// state saving
save_item(NAME(m_cs));
- save_item(NAME(m_data));
+ save_item(NAME(m_data_out));
save_item(NAME(m_dma));
+ save_item(NAME(m_req));
+ save_item(NAME(m_drq));
+ save_item(NAME(m_pren));
+ save_item(NAME(m_trrq));
}
@@ -206,13 +175,165 @@ void luxor_4105_device::device_start()
void luxor_4105_device::device_reset()
{
m_cs = false;
- m_data = 0;
- m_dma = 0;
- m_sasibus->write_rst(1);
- m_sasibus->write_rst(0);
+ internal_reset();
+}
+
+
+void luxor_4105_device::internal_reset()
+{
+ write_dma_register(0);
+
+ m_data_out = 0;
+
+ m_sasi->sel_w(0);
+
+ m_sasi->rst_w(1);
+ m_sasi->rst_w(0);
+}
+
+
+void luxor_4105_device::update_dma()
+{
+ // TRRQ
+ bool req = m_sasi->req_r() && !m_req;
+ bool cd = m_sasi->cd_r();
+ m_trrq = !(req && !cd);
+ if (DMA_O2)
+ {
+ if (m_prac && !m_trrq)
+ {
+ // set REQ FF
+ m_req = 1;
+
+ update_ack();
+
+ req = m_sasi->req_r() && !m_req;
+ m_trrq = !(req && !cd);
+ }
+ }
+ m_slot->trrq_w(DMA_O2 ? m_trrq : 1);
+
+ // DRQ
+ bool io = m_sasi->io_r();
+ m_drq = (!((!cd || !io) && !(!cd && !DMA_O2))) && req;
+
+ // IRQ
+ bool irq = 1;
+ if (DMA_O2)
+ {
+ if (DMA_O1 && m_drq)
+ {
+ irq = 0;
+ }
+ }
+ else if (DMA_O3)
+ {
+ irq = 0;
+ }
+ m_slot->irq_w(!irq);
+}
+
+
+void luxor_4105_device::update_ack()
+{
+ m_sasi->ack_w(m_sasi->req_r() && (m_sasi->msg_r() || m_req));
+}
+
+
+void luxor_4105_device::write_dma_register(uint8_t data)
+{
+ /*
+
+ bit description
+
+ 0
+ 1
+ 2
+ 3
+ 4
+ 5 byte interrupt enable?
+ 6 DMA/CPU mode (1=DMA, 0=CPU)?
+ 7 error interrupt enable?
+
+ */
- m_slot->trrq_w(1);
+ m_dma = BIT(data, 5) << 2 | BIT(data, 6) << 1 | BIT(data, 7);
+ if (LOG) logerror("%s DMA O1 %u O2 %u O3 %u\n", machine().describe_context(), DMA_O1, DMA_O2, DMA_O3);
+
+ // PREN
+ m_pren = !DMA_O2;
+ m_slot->pren_w(m_pren);
+
+ update_dma();
+}
+
+
+void luxor_4105_device::write_sasi_data(uint8_t data)
+{
+ m_data_out = data;
+
+ if (!m_sasi->io_r())
+ {
+ m_sasi->write(data);
+ }
+
+ // clock REQ FF
+ m_req = m_sasi->req_r();
+
+ update_ack();
+ update_dma();
+}
+
+
+void luxor_4105_device::write_sasi_bsy(int state)
+{
+ if (state)
+ {
+ m_sasi->sel_w(0);
+ }
+}
+
+
+void luxor_4105_device::write_sasi_cd(int state)
+{
+ update_dma();
+}
+
+
+void luxor_4105_device::write_sasi_req(int state)
+{
+ if (LOG) logerror("%s REQ %u\n", machine().describe_context(), state);
+
+ if (!state)
+ {
+ // reset REQ FF
+ m_req = 0;
+ }
+
+ update_ack();
+ update_dma();
+}
+
+
+void luxor_4105_device::write_sasi_msg(int state)
+{
+ update_ack();
+}
+
+
+void luxor_4105_device::write_sasi_io(int state)
+{
+ if (state)
+ {
+ m_sasi->write(0);
+ }
+ else
+ {
+ m_sasi->write(m_data_out);
+ }
+
+ update_dma();
}
@@ -250,21 +371,25 @@ uint8_t luxor_4105_device::abcbus_stat()
bit description
- 0 ?
- 1 ?
- 2 ?
- 3 ?
- 4
- 5
- 6 ? (tested at 014D9A, after command 08 sent and 1 byte read from SASI, should be 1)
- 7
+ 0 REQ
+ 1 C/D
+ 2 BSY
+ 3 I/O
+ 4 0
+ 5 DMA !O3
+ 6 PREN
+ 7 DMA request
*/
- data = m_sasi_bsy ? 0 : (1 << 0);
- data |= m_sasi_req ? 0 : (1 << 2);
- data |= m_sasi_cd ? 0 : (1 << 3);
- data |= m_sasi_io ? 0 : (1 << 6);
+ data = m_sasi->req_r() && !m_req;
+ data |= !m_sasi->cd_r() << 1;
+ data |= m_sasi->bsy_r() << 2;
+ data |= !m_sasi->io_r() << 3;
+
+ data |= !DMA_O3 << 5;
+ data |= !m_pren << 6;
+ data |= !m_drq << 7;
}
return data;
@@ -281,22 +406,22 @@ uint8_t luxor_4105_device::abcbus_inp()
if (m_cs)
{
- if (!m_sasi_bsy)
+ if (m_sasi->bsy_r())
{
- data = m_1e->read();
+ data = m_sasi->read();
}
else
{
- if (m_sasi_io)
- {
- data = m_sasi_data_in->read();
-
- if (m_sasi_req)
- {
- m_sasibus->write_ack(1);
- }
- }
+ data = m_1e->read();
}
+
+ // clock REQ FF
+ m_req = m_sasi->req_r();
+
+ update_ack();
+ update_dma();
+
+ if (LOG) logerror("%s INP %02x\n", machine().describe_context(), data);
}
return data;
@@ -311,17 +436,9 @@ void luxor_4105_device::abcbus_out(uint8_t data)
{
if (m_cs)
{
- m_data = data;
-
- if (!m_sasi_io)
- {
- m_sasi_data_out->write(m_data);
+ if (LOG) logerror("%s OUT %02x\n", machine().describe_context(), data);
- if (m_sasi_req)
- {
- m_sasibus->write_ack(1);
- }
- }
+ write_sasi_data(data);
}
}
@@ -334,7 +451,9 @@ void luxor_4105_device::abcbus_c1(uint8_t data)
{
if (m_cs)
{
- m_sasibus->write_sel(1);
+ if (LOG) logerror("%s SELECT\n", machine().describe_context());
+
+ m_sasi->sel_w(1);
}
}
@@ -347,11 +466,9 @@ void luxor_4105_device::abcbus_c3(uint8_t data)
{
if (m_cs)
{
- m_data = 0;
- m_dma = 0;
+ if (LOG) logerror("%s RESET\n", machine().describe_context());
- m_sasibus->write_rst(1);
- m_sasibus->write_rst(0);
+ internal_reset();
}
}
@@ -364,23 +481,65 @@ void luxor_4105_device::abcbus_c4(uint8_t data)
{
if (m_cs)
{
- /*
+ if (LOG) logerror("%s DMA %02x\n", machine().describe_context(), data);
- bit description
+ write_dma_register(data);
+ }
+}
- 0
- 1
- 2
- 3
- 4
- 5 byte interrupt enable?
- 6 DMA/CPU mode (1=DMA, 0=CPU)?
- 7 error interrupt enable?
- */
+//-------------------------------------------------
+// abcbus_tren -
+//-------------------------------------------------
+
+uint8_t luxor_4105_device::abcbus_tren()
+{
+ uint8_t data = 0xff;
+
+ if (DMA_O2)
+ {
+ if (m_sasi->bsy_r())
+ {
+ data = m_sasi->read();
+ }
- m_dma = data;
+ // clock REQ FF
+ m_req = m_sasi->req_r();
- update_trrq_int();
+ update_ack();
+ update_dma();
+
+ if (LOG) logerror("%s TREN R %02x\n", machine().describe_context(), data);
+ }
+
+ return data;
+}
+
+
+//-------------------------------------------------
+// abcbus_tren -
+//-------------------------------------------------
+
+void luxor_4105_device::abcbus_tren(uint8_t data)
+{
+ if (DMA_O2)
+ {
+ if (LOG) logerror("%s TREN W %02x\n", machine().describe_context(), data);
+
+ write_sasi_data(data);
}
}
+
+
+//-------------------------------------------------
+// abcbus_prac -
+//-------------------------------------------------
+
+void luxor_4105_device::abcbus_prac(int state)
+{
+ if (LOG) logerror("%s PRAC %u\n", machine().describe_context(), state);
+
+ m_prac = state;
+
+ update_dma();
+}
diff --git a/src/devices/bus/abcbus/lux4105.h b/src/devices/bus/abcbus/lux4105.h
index 80e817336d8..a8e991403f5 100644
--- a/src/devices/bus/abcbus/lux4105.h
+++ b/src/devices/bus/abcbus/lux4105.h
@@ -13,15 +13,9 @@
#include "abcbus.h"
-#include "bus/scsi/scsi.h"
-
-
-
-//**************************************************************************
-// MACROS / CONSTANTS
-//**************************************************************************
-
-#define LUXOR_4105_TAG "luxor_4105"
+#include "bus/nscsi/devices.h"
+#include "machine/nscsi_bus.h"
+#include "machine/nscsi_cb.h"
@@ -32,7 +26,7 @@
// ======================> luxor_4105_device
class luxor_4105_device : public device_t,
- public device_abcbus_card_interface
+ public device_abcbus_card_interface
{
public:
// construction/destruction
@@ -40,12 +34,12 @@ public:
protected:
// device-level overrides
- virtual void device_start() override;
- virtual void device_reset() override;
+ virtual void device_start() override ATTR_COLD;
+ virtual void device_reset() override ATTR_COLD;
// optional information overrides
- virtual void device_add_mconfig(machine_config &config) override;
- virtual ioport_constructor device_input_ports() const override;
+ virtual void device_add_mconfig(machine_config &config) override ATTR_COLD;
+ virtual ioport_constructor device_input_ports() const override ATTR_COLD;
// device_abcbus_interface overrides
virtual void abcbus_cs(uint8_t data) override;
@@ -56,29 +50,35 @@ protected:
virtual void abcbus_c1(uint8_t data) override;
virtual void abcbus_c3(uint8_t data) override;
virtual void abcbus_c4(uint8_t data) override;
+ virtual uint8_t abcbus_tren() override;
+ virtual void abcbus_tren(uint8_t data) override;
+ virtual void abcbus_prac(int state) override;
private:
- inline void update_trrq_int();
-
- DECLARE_WRITE_LINE_MEMBER( write_sasi_bsy );
- DECLARE_WRITE_LINE_MEMBER( write_sasi_req );
- DECLARE_WRITE_LINE_MEMBER( write_sasi_cd );
- DECLARE_WRITE_LINE_MEMBER( write_sasi_io );
-
- required_device<scsi_port_device> m_sasibus;
- required_device<output_latch_device> m_sasi_data_out;
- required_device<input_buffer_device> m_sasi_data_in;
+ void internal_reset();
+ void update_ack();
+ void update_dma();
+ void write_dma_register(uint8_t data);
+ void write_sasi_data(uint8_t data);
+
+ 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;
required_ioport m_5e;
bool m_cs;
- uint8_t m_data;
+ uint8_t m_data_out;
uint8_t m_dma;
-
- int m_sasi_bsy;
- bool m_sasi_req;
- bool m_sasi_cd;
- bool m_sasi_io;
+ bool m_req;
+ bool m_drq;
+ bool m_pren;
+ bool m_prac;
+ bool m_trrq;
};
diff --git a/src/devices/bus/abcbus/memcard.cpp b/src/devices/bus/abcbus/memcard.cpp
index 6238345b65f..8ace715f696 100644
--- a/src/devices/bus/abcbus/memcard.cpp
+++ b/src/devices/bus/abcbus/memcard.cpp
@@ -63,41 +63,19 @@ Notes:
// DEVICE DEFINITIONS
//**************************************************************************
-DEFINE_DEVICE_TYPE(ABC_MEMORY_CARD, abc_memory_card_device, "abc_mem", "ABC Memory Card")
+DEFINE_DEVICE_TYPE(ABC_MEMORY_CARD, abc_memory_card_device, "abc_memcard", "ABC Memory Card")
//-------------------------------------------------
-// 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 68ce2858cef..fe5d70bc51b 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,21 +30,21 @@ 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 ATTR_COLD;
protected:
// device-level overrides
- virtual void device_start() override;
+ virtual void device_start() override ATTR_COLD;
// device_abcbus_interface overrides
- virtual void abcbus_cs(uint8_t data) override { };
+ virtual void abcbus_cs(uint8_t data) override { }
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/ram.cpp b/src/devices/bus/abcbus/ram.cpp
index 4886f46defa..563964041c5 100644
--- a/src/devices/bus/abcbus/ram.cpp
+++ b/src/devices/bus/abcbus/ram.cpp
@@ -30,7 +30,7 @@ DEFINE_DEVICE_TYPE(ABC80_16KB_RAM_CARD, abc80_16kb_ram_card_device, "abc80_16kb"
abc80_16kb_ram_card_device::abc80_16kb_ram_card_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) :
device_t(mconfig, ABC80_16KB_RAM_CARD, tag, owner, clock),
device_abcbus_card_interface(mconfig, *this),
- m_ram(*this, "ram")
+ m_ram(*this, "ram", 0x4000, ENDIANNESS_LITTLE)
{
}
@@ -41,7 +41,6 @@ abc80_16kb_ram_card_device::abc80_16kb_ram_card_device(const machine_config &mco
void abc80_16kb_ram_card_device::device_start()
{
- m_ram.allocate(0x4000);
}
diff --git a/src/devices/bus/abcbus/ram.h b/src/devices/bus/abcbus/ram.h
index cddb07182c7..5fd1ec5243c 100644
--- a/src/devices/bus/abcbus/ram.h
+++ b/src/devices/bus/abcbus/ram.h
@@ -29,15 +29,15 @@ public:
protected:
// device-level overrides
- virtual void device_start() override;
+ virtual void device_start() override ATTR_COLD;
// device_abcbus_interface overrides
- virtual void abcbus_cs(uint8_t data) override { };
+ virtual void abcbus_cs(uint8_t data) override { }
virtual uint8_t abcbus_xmemfl(offs_t offset) override;
virtual void abcbus_xmemw(offs_t offset, uint8_t data) override;
private:
- optional_shared_ptr<uint8_t> m_ram;
+ memory_share_creator<uint8_t> m_ram;
};
diff --git a/src/devices/bus/abcbus/sio.h b/src/devices/bus/abcbus/sio.h
index 6cb86d9fc76..ca382f702d2 100644
--- a/src/devices/bus/abcbus/sio.h
+++ b/src/devices/bus/abcbus/sio.h
@@ -7,7 +7,7 @@
#include "abcbus.h"
#include "machine/z80ctc.h"
-#include "machine/z80dart.h"
+#include "machine/z80sio.h"
@@ -26,12 +26,12 @@ public:
protected:
// device-level overrides
- virtual void device_start() override;
- virtual void device_reset() override;
+ virtual void device_start() override ATTR_COLD;
+ virtual void device_reset() override ATTR_COLD;
// optional information overrides
- virtual const tiny_rom_entry *device_rom_region() const override;
- virtual void device_add_mconfig(machine_config &config) override;
+ virtual const tiny_rom_entry *device_rom_region() const override ATTR_COLD;
+ virtual void device_add_mconfig(machine_config &config) override ATTR_COLD;
// device_abcbus_interface overrides
virtual void abcbus_cs(uint8_t data) override;
diff --git a/src/devices/bus/abcbus/slutprov.cpp b/src/devices/bus/abcbus/slutprov.cpp
index 3e75dcd577c..8ca4bc5934e 100644
--- a/src/devices/bus/abcbus/slutprov.cpp
+++ b/src/devices/bus/abcbus/slutprov.cpp
@@ -9,7 +9,7 @@
// DEVICE DEFINITIONS
//**************************************************************************
-DEFINE_DEVICE_TYPE(ABC_SLUTPROV, abc_slutprov_device, "slutprov", "Slutprov")
+DEFINE_DEVICE_TYPE(ABC_SLUTPROV, abc_slutprov_device, "abc_slutprov", "Slutprov")
//-------------------------------------------------
diff --git a/src/devices/bus/abcbus/slutprov.h b/src/devices/bus/abcbus/slutprov.h
index 16f6b0e9f79..63d469a427b 100644
--- a/src/devices/bus/abcbus/slutprov.h
+++ b/src/devices/bus/abcbus/slutprov.h
@@ -23,12 +23,12 @@ public:
abc_slutprov_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 const tiny_rom_entry *device_rom_region() const override ATTR_COLD;
protected:
// device-level overrides
- virtual void device_start() override;
- virtual void device_reset() override;
+ virtual void device_start() override ATTR_COLD;
+ virtual void device_reset() override ATTR_COLD;
// device_abcbus_interface overrides
virtual void abcbus_cs(uint8_t data) override;
diff --git a/src/devices/bus/abcbus/ssa.cpp b/src/devices/bus/abcbus/ssa.cpp
index 27bbdc3927f..5a190fc0fbb 100644
--- a/src/devices/bus/abcbus/ssa.cpp
+++ b/src/devices/bus/abcbus/ssa.cpp
@@ -65,16 +65,16 @@ Notes:
// DEVICE DEFINITIONS
//**************************************************************************
-DEFINE_DEVICE_TYPE(SUPER_SMARTAID, super_smartaid_t, "ssa", "Super Smartaid")
+DEFINE_DEVICE_TYPE(ABC_SUPER_SMARTAID, abc_super_smartaid_device, "abc_ssa", "Super Smartaid")
//-------------------------------------------------
// device_add_mconfig - add device configuration
//-------------------------------------------------
-void super_smartaid_t::device_add_mconfig(machine_config &config)
+void abc_super_smartaid_device::device_add_mconfig(machine_config &config)
{
- ABCBUS_SLOT(config, ABCBUS_TAG, DERIVED_CLOCK(1, 1), abc80_cards, nullptr);
+ ABCBUS_SLOT(config, m_bus, DERIVED_CLOCK(1, 1), abc80_cards, nullptr);
}
@@ -98,7 +98,7 @@ ROM_END
// rom_region - device-specific ROM region
//-------------------------------------------------
-const tiny_rom_entry *super_smartaid_t::device_rom_region() const
+const tiny_rom_entry *abc_super_smartaid_device::device_rom_region() const
{
return ROM_NAME( super_smartaid );
}
@@ -110,18 +110,18 @@ const tiny_rom_entry *super_smartaid_t::device_rom_region() const
//**************************************************************************
//-------------------------------------------------
-// super_smartaid_t - constructor
+// abc_super_smartaid_device - constructor
//-------------------------------------------------
-super_smartaid_t::super_smartaid_t(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) :
- device_t(mconfig, SUPER_SMARTAID, tag, owner, clock),
+abc_super_smartaid_device::abc_super_smartaid_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) :
+ device_t(mconfig, ABC_SUPER_SMARTAID, tag, owner, clock),
device_abcbus_card_interface(mconfig, *this),
device_nvram_interface(mconfig, *this),
- m_bus(*this, ABCBUS_TAG),
+ m_bus(*this, "bus"),
m_rom_1(*this, "ssa1"),
m_rom_2(*this, "ssa2"),
m_prom(*this, "ssa3"),
- m_nvram(*this, "nvram"),
+ m_nvram(*this, "nvram", 0x800, ENDIANNESS_LITTLE),
m_rom_bank(0),
m_prom_bank(0)
{
@@ -132,7 +132,7 @@ super_smartaid_t::super_smartaid_t(const machine_config &mconfig, const char *ta
// device_start - device-specific startup
//-------------------------------------------------
-void super_smartaid_t::device_start()
+void abc_super_smartaid_device::device_start()
{
// descramble ROMs
for (offs_t i = 0; i < 0x800; i++)
@@ -144,9 +144,6 @@ void super_smartaid_t::device_start()
m_rom_2->base()[i] = bitswap<8>(m_rom_2->base()[i], 2, 6, 1, 4, 3, 5, 7, 0);
}
- // allocate memory
- m_nvram.allocate(0x800);
-
// state saving
save_item(NAME(m_rom_bank));
save_item(NAME(m_prom_bank));
@@ -157,13 +154,30 @@ void super_smartaid_t::device_start()
// device_reset - device-specific reset
//-------------------------------------------------
-void super_smartaid_t::device_reset()
+void abc_super_smartaid_device::device_reset()
{
m_rom_bank = 0;
m_prom_bank = 0;
}
+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
@@ -173,7 +187,7 @@ void super_smartaid_t::device_reset()
// abcbus_xmemfl -
//-------------------------------------------------
-uint8_t super_smartaid_t::abcbus_xmemfl(offs_t offset)
+uint8_t abc_super_smartaid_device::abcbus_xmemfl(offs_t offset)
{
uint8_t data = 0xff;
@@ -181,7 +195,7 @@ uint8_t super_smartaid_t::abcbus_xmemfl(offs_t offset)
{
case 0x08:
m_prom_bank = 1;
- // fallthru
+ [[fallthrough]];
case 0x0c: case 0x0f:
data = m_rom_2->base()[(m_rom_bank << 12) | (offset & 0xfff)];
break;
@@ -204,7 +218,7 @@ uint8_t super_smartaid_t::abcbus_xmemfl(offs_t offset)
// abcbus_xmemw -
//-------------------------------------------------
-void super_smartaid_t::abcbus_xmemw(offs_t offset, uint8_t data)
+void abc_super_smartaid_device::abcbus_xmemw(offs_t offset, uint8_t data)
{
if ((offset == 0x4040) || (offset == 0x4041))
{
diff --git a/src/devices/bus/abcbus/ssa.h b/src/devices/bus/abcbus/ssa.h
index 86d0afa21f0..2b3df94826b 100644
--- a/src/devices/bus/abcbus/ssa.h
+++ b/src/devices/bus/abcbus/ssa.h
@@ -12,7 +12,6 @@
#pragma once
#include "abcbus.h"
-#include "machine/nvram.h"
@@ -20,31 +19,31 @@
// TYPE DEFINITIONS
//**************************************************************************
-// ======================> super_smartaid_t
+// ======================> abc_super_smartaid_device
-class super_smartaid_t : public device_t,
+class abc_super_smartaid_device : public device_t,
public device_abcbus_card_interface,
public device_nvram_interface
{
public:
// construction/destruction
- super_smartaid_t(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
+ 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
- virtual void device_start() override;
- virtual void device_reset() override;
-
- // device_nvram_interface overrides
- virtual void nvram_default() override { }
- virtual void nvram_read(emu_file &file) override { if (m_nvram != nullptr) { file.read(m_nvram, m_nvram.bytes()); } }
- virtual void nvram_write(emu_file &file) override { if (m_nvram != nullptr) { file.write(m_nvram, m_nvram.bytes()); } }
-
- // device_abcbus_interface overrides
+ // device_t implementation
+ virtual void device_add_mconfig(machine_config &config) override ATTR_COLD;
+ virtual const tiny_rom_entry *device_rom_region() const override ATTR_COLD;
+ virtual void device_start() override ATTR_COLD;
+ virtual void device_reset() override ATTR_COLD;
+
+ // 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 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); }
@@ -61,13 +60,13 @@ private:
required_memory_region m_rom_1;
required_memory_region m_rom_2;
required_memory_region m_prom;
- optional_shared_ptr<uint8_t> m_nvram;
+ memory_share_creator<uint8_t> m_nvram;
uint8_t m_rom_bank;
uint8_t m_prom_bank;
};
// device type definition
-DECLARE_DEVICE_TYPE(SUPER_SMARTAID, super_smartaid_t)
+DECLARE_DEVICE_TYPE(ABC_SUPER_SMARTAID, abc_super_smartaid_device)
#endif // MAME_BUS_ABCBUS_SSA_H
diff --git a/src/devices/bus/abcbus/uni800.cpp b/src/devices/bus/abcbus/uni800.cpp
index 5e45d3fc30e..2b38faac748 100644
--- a/src/devices/bus/abcbus/uni800.cpp
+++ b/src/devices/bus/abcbus/uni800.cpp
@@ -40,7 +40,7 @@ Notes:
// DEVICE DEFINITIONS
//**************************************************************************
-DEFINE_DEVICE_TYPE(ABC_UNI800, abc_uni800_device, "uni800", "UNI-800")
+DEFINE_DEVICE_TYPE(ABC_UNI800, abc_uni800_device, "abc_uni800", "UNI-800")
//-------------------------------------------------
diff --git a/src/devices/bus/abcbus/uni800.h b/src/devices/bus/abcbus/uni800.h
index c6eb9400d40..a5880631c6e 100644
--- a/src/devices/bus/abcbus/uni800.h
+++ b/src/devices/bus/abcbus/uni800.h
@@ -23,12 +23,12 @@ public:
abc_uni800_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 const tiny_rom_entry *device_rom_region() const override ATTR_COLD;
protected:
// device-level overrides
- virtual void device_start() override;
- virtual void device_reset() override;
+ virtual void device_start() override ATTR_COLD;
+ virtual void device_reset() override ATTR_COLD;
// device_abcbus_interface overrides
virtual void abcbus_cs(uint8_t data) override;
diff --git a/src/devices/bus/abcbus/unidisk.cpp b/src/devices/bus/abcbus/unidisk.cpp
index 0b068000193..4661bc1fc03 100644
--- a/src/devices/bus/abcbus/unidisk.cpp
+++ b/src/devices/bus/abcbus/unidisk.cpp
@@ -22,7 +22,7 @@
// DEVICE DEFINITIONS
//**************************************************************************
-DEFINE_DEVICE_TYPE(UNIDISK, unidisk_t, "unidisk", "MyAB UNI DISK")
+DEFINE_DEVICE_TYPE(ABC_UNIDISK, abc_unidisk_device, "abc_unidisk", "MyAB UNI DISK")
//-------------------------------------------------
@@ -44,7 +44,7 @@ ROM_END
// rom_region - device-specific ROM region
//-------------------------------------------------
-const tiny_rom_entry *unidisk_t::device_rom_region() const
+const tiny_rom_entry *abc_unidisk_device::device_rom_region() const
{
return ROM_NAME( unidisk );
}
@@ -54,7 +54,7 @@ const tiny_rom_entry *unidisk_t::device_rom_region() const
// ADDRESS_MAP( unidisk_mem )
//-------------------------------------------------
-void unidisk_t::unidisk_mem(address_map &map)
+void abc_unidisk_device::unidisk_mem(address_map &map)
{
map(0x0000, 0x0fff).rom().region(TMS9995_TAG, 0);
}
@@ -64,7 +64,7 @@ void unidisk_t::unidisk_mem(address_map &map)
// ADDRESS_MAP( unidisk_io )
//-------------------------------------------------
-void unidisk_t::unidisk_io(address_map &map)
+void abc_unidisk_device::unidisk_io(address_map &map)
{
}
@@ -73,11 +73,11 @@ void unidisk_t::unidisk_io(address_map &map)
// device_add_mconfig - add device configuration
//-------------------------------------------------
-void unidisk_t::device_add_mconfig(machine_config &config)
+void abc_unidisk_device::device_add_mconfig(machine_config &config)
{
TMS9995(config, m_maincpu, 12000000);
- m_maincpu->set_addrmap(AS_PROGRAM, &unidisk_t::unidisk_mem);
- m_maincpu->set_addrmap(AS_IO, &unidisk_t::unidisk_io);
+ m_maincpu->set_addrmap(AS_PROGRAM, &abc_unidisk_device::unidisk_mem);
+ m_maincpu->set_addrmap(AS_IO, &abc_unidisk_device::unidisk_io);
}
@@ -93,7 +93,7 @@ INPUT_PORTS_END
// input_ports - device-specific input ports
//-------------------------------------------------
-ioport_constructor unidisk_t::device_input_ports() const
+ioport_constructor abc_unidisk_device::device_input_ports() const
{
return INPUT_PORTS_NAME( unidisk );
}
@@ -105,11 +105,11 @@ ioport_constructor unidisk_t::device_input_ports() const
//**************************************************************************
//-------------------------------------------------
-// unidisk_t - constructor
+// abc_unidisk_device - constructor
//-------------------------------------------------
-unidisk_t::unidisk_t(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) :
- device_t(mconfig, UNIDISK, tag, owner, clock),
+abc_unidisk_device::abc_unidisk_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) :
+ device_t(mconfig, ABC_UNIDISK, tag, owner, clock),
device_abcbus_card_interface(mconfig, *this),
m_maincpu(*this, TMS9995_TAG)
{
@@ -120,7 +120,7 @@ unidisk_t::unidisk_t(const machine_config &mconfig, const char *tag, device_t *o
// device_start - device-specific startup
//-------------------------------------------------
-void unidisk_t::device_start()
+void abc_unidisk_device::device_start()
{
}
@@ -129,7 +129,7 @@ void unidisk_t::device_start()
// device_reset - device-specific reset
//-------------------------------------------------
-void unidisk_t::device_reset()
+void abc_unidisk_device::device_reset()
{
m_cs = false;
}
@@ -144,7 +144,7 @@ void unidisk_t::device_reset()
// abcbus_cs -
//-------------------------------------------------
-void unidisk_t::abcbus_cs(uint8_t data)
+void abc_unidisk_device::abcbus_cs(uint8_t data)
{
}
@@ -153,7 +153,7 @@ void unidisk_t::abcbus_cs(uint8_t data)
// abcbus_stat -
//-------------------------------------------------
-uint8_t unidisk_t::abcbus_stat()
+uint8_t abc_unidisk_device::abcbus_stat()
{
uint8_t data = 0xff;
@@ -169,7 +169,7 @@ uint8_t unidisk_t::abcbus_stat()
// abcbus_inp -
//-------------------------------------------------
-uint8_t unidisk_t::abcbus_inp()
+uint8_t abc_unidisk_device::abcbus_inp()
{
uint8_t data = 0xff;
@@ -185,7 +185,7 @@ uint8_t unidisk_t::abcbus_inp()
// abcbus_out -
//-------------------------------------------------
-void unidisk_t::abcbus_out(uint8_t data)
+void abc_unidisk_device::abcbus_out(uint8_t data)
{
if (!m_cs) return;
}
@@ -195,7 +195,7 @@ void unidisk_t::abcbus_out(uint8_t data)
// abcbus_c1 -
//-------------------------------------------------
-void unidisk_t::abcbus_c1(uint8_t data)
+void abc_unidisk_device::abcbus_c1(uint8_t data)
{
if (m_cs)
{
@@ -207,7 +207,7 @@ void unidisk_t::abcbus_c1(uint8_t data)
// abcbus_c3 -
//-------------------------------------------------
-void unidisk_t::abcbus_c3(uint8_t data)
+void abc_unidisk_device::abcbus_c3(uint8_t data)
{
if (m_cs)
{
diff --git a/src/devices/bus/abcbus/unidisk.h b/src/devices/bus/abcbus/unidisk.h
index 27cd7db78f2..582bcddaf0f 100644
--- a/src/devices/bus/abcbus/unidisk.h
+++ b/src/devices/bus/abcbus/unidisk.h
@@ -20,24 +20,24 @@
// TYPE DEFINITIONS
//**************************************************************************
-// ======================> unidisk_t
+// ======================> abc_unidisk_device
-class unidisk_t : public device_t,
+class abc_unidisk_device : public device_t,
public device_abcbus_card_interface
{
public:
// construction/destruction
- unidisk_t(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
+ abc_unidisk_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_start() override ATTR_COLD;
+ virtual void device_reset() override ATTR_COLD;
// optional information 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 const tiny_rom_entry *device_rom_region() const override ATTR_COLD;
+ virtual void device_add_mconfig(machine_config &config) override ATTR_COLD;
+ virtual ioport_constructor device_input_ports() const override ATTR_COLD;
// device_abcbus_interface overrides
virtual void abcbus_cs(uint8_t data) override;
@@ -52,12 +52,12 @@ private:
bool m_cs;
- void unidisk_io(address_map &map);
- void unidisk_mem(address_map &map);
+ void unidisk_io(address_map &map) ATTR_COLD;
+ void unidisk_mem(address_map &map) ATTR_COLD;
};
// device type definition
-DECLARE_DEVICE_TYPE(UNIDISK, unidisk_t)
+DECLARE_DEVICE_TYPE(ABC_UNIDISK, abc_unidisk_device)
#endif // MAME_BUS_ABCBUS_UNIDISK_H
diff --git a/src/devices/bus/abckb/abc77.cpp b/src/devices/bus/abckb/abc77.cpp
index c2bdceceaa6..f5e4f13bafd 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"
@@ -102,7 +110,7 @@ void abc77_device::abc77_map(address_map &map)
void abc77_device::abc77_io(address_map &map)
{
map(0x00, 0x00).mirror(0xff).w(FUNC(abc77_device::j3_w));
- map(0x00, 0x00).mirror(0xff).portr("DSW");
+ map(0x00, 0x00).mirror(0xff).portr(m_dsw);
}
@@ -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')
@@ -305,7 +313,7 @@ INPUT_PORTS_START( abc55 )
PORT_BIT( 0xe0, IP_ACTIVE_LOW, IPT_UNUSED)
PORT_START("SW1")
- PORT_BIT( 0x01, IP_ACTIVE_LOW, IPT_OTHER ) PORT_NAME("Keyboard Reset") PORT_CHANGED_MEMBER(DEVICE_SELF, abc77_device, keyboard_reset, 0)
+ PORT_BIT( 0x01, IP_ACTIVE_LOW, IPT_OTHER ) PORT_NAME("Keyboard Reset") PORT_CHANGED_MEMBER(DEVICE_SELF, FUNC(abc77_device::keyboard_reset), 0)
INPUT_PORTS_END
@@ -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,25 +372,10 @@ 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 -
//-------------------------------------------------
-inline void abc77_device::serial_clock()
+TIMER_CALLBACK_MEMBER(abc77_device::serial_clock)
{
m_clock = !m_clock;
@@ -390,20 +383,6 @@ inline void 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)
{
}
@@ -442,10 +423,11 @@ abc77_device::abc77_device(const machine_config &mconfig, const char *tag, devic
void abc77_device::device_start()
{
// allocate timers
- m_serial_timer = timer_alloc(TIMER_SERIAL);
- m_serial_timer->adjust(attotime::from_hz(19200), 0, attotime::from_hz(19200)); // ALE/32
+ m_serial_timer = timer_alloc(FUNC(abc77_device::serial_clock), this);
+ 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(TIMER_RESET);
+ m_reset_timer = timer_alloc(FUNC(abc77_device::reset_tick), this);
}
@@ -469,21 +451,12 @@ void abc77_device::device_reset()
//-------------------------------------------------
-// device_timer - handler timer events
+// reset_tick - handle delayed reset
//-------------------------------------------------
-void abc77_device::device_timer(emu_timer &timer, device_timer_id id, int param, void *ptr)
+TIMER_CALLBACK_MEMBER(abc77_device::reset_tick)
{
- switch (id)
- {
- case TIMER_SERIAL:
- serial_clock();
- break;
-
- case TIMER_RESET:
- m_maincpu->set_input_line(INPUT_LINE_RESET, CLEAR_LINE);
- break;
- }
+ m_maincpu->set_input_line(INPUT_LINE_RESET, CLEAR_LINE);
}
@@ -498,10 +471,20 @@ void abc77_device::txd_w(int state)
//-------------------------------------------------
+// reset_w -
+//-------------------------------------------------
+
+void abc77_device::reset_w(int state)
+{
+ // connected to NE556 pin 8
+}
+
+
+//-------------------------------------------------
// p1_r -
//-------------------------------------------------
-READ8_MEMBER( abc77_device::p1_r )
+uint8_t abc77_device::p1_r()
{
/*
@@ -536,7 +519,7 @@ READ8_MEMBER( abc77_device::p1_r )
// p2_w -
//-------------------------------------------------
-WRITE8_MEMBER( abc77_device::p2_w )
+void abc77_device::p2_w(uint8_t data)
{
/*
@@ -567,41 +550,8 @@ WRITE8_MEMBER( abc77_device::p2_w )
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 -
-//-------------------------------------------------
-
-WRITE8_MEMBER( abc77_device::j3_w )
-{
- 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 b217a0fca47..537a77d0ca0 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
@@ -38,28 +39,21 @@ protected:
abc77_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_timer(emu_timer &timer, device_timer_id id, int param, void *ptr) override;
+ virtual void device_start() override ATTR_COLD;
+ virtual void device_reset() override ATTR_COLD;
// optional information 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 const tiny_rom_entry *device_rom_region() const override ATTR_COLD;
+ virtual void device_add_mconfig(machine_config &config) override ATTR_COLD;
+ virtual ioport_constructor device_input_ports() const override ATTR_COLD;
// abc_keyboard_interface overrides
virtual void txd_w(int state) override;
+ virtual void reset_w(int state) override;
private:
- enum
- {
- TIMER_SERIAL,
- TIMER_RESET
- };
-
- inline void serial_output(int state);
- inline void serial_clock();
- inline void key_down(int state);
+ TIMER_CALLBACK_MEMBER(serial_clock);
+ TIMER_CALLBACK_MEMBER(reset_tick);
required_device<i8035_device> m_maincpu;
required_device<watchdog_timer_device> m_watchdog;
@@ -67,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;
@@ -79,25 +70,25 @@ private:
emu_timer *m_serial_timer;
emu_timer *m_reset_timer;
- DECLARE_READ8_MEMBER( p1_r );
- DECLARE_WRITE8_MEMBER( p2_w );
- DECLARE_READ_LINE_MEMBER( t1_r );
- DECLARE_WRITE_LINE_MEMBER( prog_w );
- DECLARE_WRITE8_MEMBER( j3_w );
+ uint8_t p1_r();
+ void p2_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);
+ void abc77_io(address_map &map) ATTR_COLD;
+ void abc77_map(address_map &map) ATTR_COLD;
};
-class abc55_device : public abc77_device
+class abc55_device : public abc77_device
{
public:
// construction/destruction
abc55_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;
+ virtual ioport_constructor device_input_ports() const override ATTR_COLD;
};
diff --git a/src/devices/bus/abckb/abc800kb.cpp b/src/devices/bus/abckb/abc800kb.cpp
index fa20b40d317..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
@@ -268,7 +268,7 @@ ioport_constructor abc800_keyboard_device::device_input_ports() const
// serial_output -
//-------------------------------------------------
-inline void abc800_keyboard_device::serial_output(int state)
+void abc800_keyboard_device::serial_output(int state)
{
if (m_txd != state)
{
@@ -283,7 +283,7 @@ inline void abc800_keyboard_device::serial_output(int state)
// serial_clock -
//-------------------------------------------------
-inline void abc800_keyboard_device::serial_clock()
+TIMER_CALLBACK_MEMBER(abc800_keyboard_device::serial_clock)
{
m_clk = !m_clk;
@@ -295,7 +295,7 @@ inline void abc800_keyboard_device::serial_clock()
// keydown -
//-------------------------------------------------
-inline void abc800_keyboard_device::key_down(int state)
+void abc800_keyboard_device::key_down(int state)
{
if (m_keydown != state)
{
@@ -337,7 +337,7 @@ abc800_keyboard_device::abc800_keyboard_device(const machine_config &mconfig, co
void abc800_keyboard_device::device_start()
{
// allocate timers
- m_serial_timer = timer_alloc();
+ m_serial_timer = timer_alloc(FUNC(abc800_keyboard_device::serial_clock), this);
m_serial_timer->adjust(attotime::from_hz(XTAL(5'990'400)/(3*5)/20), 0, attotime::from_hz(XTAL(5'990'400)/(3*5)/20)); // ???
// state saving
@@ -358,15 +358,6 @@ void abc800_keyboard_device::device_reset()
}
-//-------------------------------------------------
-// device_timer - handler timer events
-//-------------------------------------------------
-
-void abc800_keyboard_device::device_timer(emu_timer &timer, device_timer_id id, int param, void *ptr)
-{
- serial_clock();
-}
-
//-------------------------------------------------
// txd_w -
@@ -382,7 +373,7 @@ void abc800_keyboard_device::txd_w(int state)
// kb_p1_r - keyboard column data read
//-------------------------------------------------
-READ8_MEMBER( abc800_keyboard_device::kb_p1_r )
+uint8_t abc800_keyboard_device::kb_p1_r()
{
uint8_t data = 0xff;
@@ -402,7 +393,7 @@ READ8_MEMBER( abc800_keyboard_device::kb_p1_r )
// kb_p1_w - keyboard row write
//-------------------------------------------------
-WRITE8_MEMBER( abc800_keyboard_device::kb_p1_w )
+void abc800_keyboard_device::kb_p1_w(uint8_t data)
{
/*
@@ -431,7 +422,7 @@ WRITE8_MEMBER( abc800_keyboard_device::kb_p1_w )
// kb_p2_w - keyboard control write
//-------------------------------------------------
-WRITE8_MEMBER( abc800_keyboard_device::kb_p2_w )
+void abc800_keyboard_device::kb_p2_w(uint8_t data)
{
/*
@@ -463,7 +454,7 @@ WRITE8_MEMBER( abc800_keyboard_device::kb_p2_w )
// 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 50fde4beac9..4d192d6042a 100644
--- a/src/devices/bus/abckb/abc800kb.h
+++ b/src/devices/bus/abckb/abc800kb.h
@@ -36,24 +36,23 @@ public:
protected:
// device-level overrides
- virtual void device_start() override;
- virtual void device_reset() override;
- virtual void device_timer(emu_timer &timer, device_timer_id id, int param, void *ptr) override;
+ virtual void device_start() override ATTR_COLD;
+ virtual void device_reset() override ATTR_COLD;
// optional information 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 const tiny_rom_entry *device_rom_region() const override ATTR_COLD;
+ virtual void device_add_mconfig(machine_config &config) override ATTR_COLD;
+ virtual ioport_constructor device_input_ports() const override ATTR_COLD;
private:
- inline void serial_output(int state);
- inline void serial_clock();
- inline void key_down(int state);
-
- DECLARE_READ8_MEMBER( kb_p1_r );
- DECLARE_WRITE8_MEMBER( kb_p1_w );
- DECLARE_WRITE8_MEMBER( kb_p2_w );
- DECLARE_READ_LINE_MEMBER( kb_t1_r );
+ void serial_output(int state);
+ TIMER_CALLBACK_MEMBER(serial_clock);
+ void key_down(int state);
+
+ uint8_t kb_p1_r();
+ void kb_p1_w(uint8_t data);
+ void kb_p2_w(uint8_t data);
+ 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 b784487062a..69219dcf584 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 )
+ioport_value 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;
+}
+
+ioport_value 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(FUNC(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(FUNC(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,31 +387,26 @@ 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)
+ PORT_BIT( 0x01, IP_ACTIVE_LOW, IPT_OTHER ) PORT_NAME("Keyboard Reset") PORT_CHANGED_MEMBER(DEVICE_SELF, FUNC(abc99_device::keyboard_reset), 0)
INPUT_PORTS_END
@@ -398,15 +421,11 @@ ioport_constructor abc99_device::device_input_ports() const
-//**************************************************************************
-// INLINE HELPERS
-//**************************************************************************
-
//-------------------------------------------------
// serial_input -
//-------------------------------------------------
-inline void abc99_device::serial_input()
+void abc99_device::serial_input()
{
m_maincpu->set_input_line(MCS48_INPUT_IRQ, (m_si || m_si_en) ? CLEAR_LINE : ASSERT_LINE);
m_mousecpu->set_input_line(MCS48_INPUT_IRQ, m_si ? CLEAR_LINE : ASSERT_LINE);
@@ -414,55 +433,16 @@ inline void abc99_device::serial_input()
//-------------------------------------------------
-// serial_output -
-//-------------------------------------------------
-
-inline void abc99_device::serial_output(int state)
-{
- if (m_txd != state)
- {
- m_txd = state;
-
- m_slot->write_rx(m_txd);
- }
-}
-
-
-//-------------------------------------------------
// serial_clock -
//-------------------------------------------------
-inline void abc99_device::serial_clock()
+TIMER_CALLBACK_MEMBER(abc99_device::serial_clock)
{
m_slot->trxc_w(1);
m_slot->trxc_w(0);
}
-//-------------------------------------------------
-// keydown -
-//-------------------------------------------------
-
-inline void abc99_device::key_down(int state)
-{
- if (m_keydown != state)
- {
- m_slot->keydown_w(state);
- m_keydown = state;
- }
-}
-
-
-//-------------------------------------------------
-// scan_mouse -
-//-------------------------------------------------
-
-inline void abc99_device::scan_mouse()
-{
-}
-
-
-
//**************************************************************************
// LIVE DEVICE
//**************************************************************************
@@ -473,23 +453,26 @@ inline void abc99_device::scan_mouse()
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)
{
}
@@ -501,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(TIMER_SERIAL);
- 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(TIMER_MOUSE);
+ // allocate timers
+ m_serial_timer = timer_alloc(FUNC(abc99_device::serial_clock), 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));
}
@@ -527,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);
@@ -536,43 +518,34 @@ void abc99_device::device_reset()
//-------------------------------------------------
-// device_timer - handler timer events
+// txd_w -
//-------------------------------------------------
-void abc99_device::device_timer(emu_timer &timer, device_timer_id id, int param, void *ptr)
+void abc99_device::txd_w(int state)
{
- switch (id)
+ if (m_si != state)
{
- case TIMER_SERIAL:
- serial_clock();
- break;
-
- case TIMER_MOUSE:
- scan_mouse();
- break;
+ m_si = state;
+ serial_input();
}
}
//-------------------------------------------------
-// txd_w -
+// reset_w -
//-------------------------------------------------
-void abc99_device::txd_w(int state)
+void abc99_device::reset_w(int state)
{
- if (m_si != state)
- {
- m_si = state;
- serial_input();
- }
+ m_mousecpu->set_input_line(INPUT_LINE_RESET, state);
}
//-------------------------------------------------
-// z2_bus_w -
+// key_x_w -
//-------------------------------------------------
-WRITE8_MEMBER( abc99_device::z2_led_w )
+void abc99_device::led_w(uint8_t data)
{
if (m_led_en) return;
@@ -588,10 +561,35 @@ WRITE8_MEMBER( abc99_device::z2_led_w )
//-------------------------------------------------
+// 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 -
//-------------------------------------------------
-WRITE8_MEMBER( abc99_device::z2_p1_w )
+void abc99_device::z2_p1_w(uint8_t data)
{
/*
@@ -610,18 +608,18 @@ WRITE8_MEMBER( abc99_device::z2_p1_w )
// 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));
@@ -635,7 +633,7 @@ WRITE8_MEMBER( abc99_device::z2_p1_w )
// z2_p2_r -
//-------------------------------------------------
-READ8_MEMBER( abc99_device::z2_p2_r )
+uint8_t abc99_device::z2_p2_r()
{
/*
@@ -659,30 +657,10 @@ READ8_MEMBER( 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 -
//-------------------------------------------------
-READ8_MEMBER( abc99_device::z5_p1_r )
+uint8_t abc99_device::z5_p1_r()
{
/*
@@ -701,8 +679,8 @@ READ8_MEMBER( 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;
@@ -715,7 +693,7 @@ READ8_MEMBER( abc99_device::z5_p1_r )
// z5_p2_w -
//-------------------------------------------------
-WRITE8_MEMBER( abc99_device::z5_p2_w )
+void abc99_device::z5_p2_w(uint8_t data)
{
/*
@@ -744,27 +722,17 @@ WRITE8_MEMBER( abc99_device::z5_p2_w )
// 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 -
-//-------------------------------------------------
-
-READ8_MEMBER( 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 cae72ac0675..bbbf3a6b760 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,37 +27,34 @@
// ======================> 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);
+ ioport_value cursor_x4_r();
+ ioport_value cursor_x6_r();
+
DECLARE_INPUT_CHANGED_MEMBER( keyboard_reset );
protected:
// device-level overrides
- virtual void device_start() override;
- virtual void device_reset() override;
- virtual void device_timer(emu_timer &timer, device_timer_id id, int param, void *ptr) override;
+ virtual void device_start() override ATTR_COLD;
+ virtual void device_reset() override ATTR_COLD;
// optional information 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 const tiny_rom_entry *device_rom_region() const override ATTR_COLD;
+ virtual void device_add_mconfig(machine_config &config) override ATTR_COLD;
+ virtual ioport_constructor device_input_ports() const override ATTR_COLD;
// abc_keyboard_interface overrides
virtual void txd_w(int state) override;
+ virtual void reset_w(int state) override;
private:
enum
{
- TIMER_SERIAL,
- TIMER_MOUSE
- };
-
- enum
- {
LED_1 = 0,
LED_2,
LED_3,
@@ -69,46 +68,45 @@ private:
LED_CAPS_LOCK
};
- inline void serial_input();
- inline void serial_output(int state);
- inline void serial_clock();
- inline void key_down(int state);
- inline void scan_mouse();
+ void serial_input();
+ TIMER_CALLBACK_MEMBER(serial_clock);
- DECLARE_WRITE8_MEMBER( z2_p1_w );
- DECLARE_READ8_MEMBER( z2_p2_r );
- DECLARE_READ_LINE_MEMBER( z2_t0_r );
- DECLARE_READ_LINE_MEMBER( z2_t1_r );
+ 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();
+ int z2_t1_r() { return m_t1_z2; }
- DECLARE_WRITE8_MEMBER( z2_led_w );
- DECLARE_READ8_MEMBER( z5_p1_r );
- DECLARE_WRITE8_MEMBER( z5_p2_w );
- DECLARE_READ8_MEMBER( z5_t1_r );
+ void led_w(uint8_t data);
+ uint8_t z5_p1_r();
+ void z5_p2_w(uint8_t data);
+ 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) ATTR_COLD;
+ void keyboard_mem(address_map &map) ATTR_COLD;
+ void mouse_mem(address_map &map) ATTR_COLD;
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 f851deeffb8..efe3ef757e3 100644
--- a/src/devices/bus/abckb/abckb.cpp
+++ b/src/devices/bus/abckb/abckb.cpp
@@ -29,7 +29,7 @@ DEFINE_DEVICE_TYPE(ABC_KEYBOARD_PORT, abc_keyboard_port_device, "abc_keyboard_po
//-------------------------------------------------
abc_keyboard_interface::abc_keyboard_interface(const machine_config &mconfig, device_t &device)
- : device_slot_card_interface(mconfig, device)
+ : device_interface(device, "abckb")
{
m_slot = dynamic_cast<abc_keyboard_port_device *>(device.owner());
}
@@ -45,41 +45,22 @@ abc_keyboard_interface::abc_keyboard_interface(const machine_config &mconfig, de
abc_keyboard_port_device::abc_keyboard_port_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) :
device_t(mconfig, ABC_KEYBOARD_PORT, tag, owner, clock),
- device_slot_interface(mconfig, *this),
+ 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)
{
}
//-------------------------------------------------
-// device_validity_check -
-//-------------------------------------------------
-
-void abc_keyboard_port_device::device_validity_check(validity_checker &valid) const
-{
- device_t *const carddev = get_card_device();
- if (carddev && !dynamic_cast<abc_keyboard_interface *>(carddev))
- osd_printf_error("Card device %s (%s) does not implement abc_keyboard_interface\n", carddev->tag(), carddev->name());
-}
-
-
-//-------------------------------------------------
// device_start - device-specific startup
//-------------------------------------------------
void abc_keyboard_port_device::device_start()
{
- device_t *const carddev = get_card_device();
- m_card = dynamic_cast<abc_keyboard_interface *>(carddev);
- if (carddev && !m_card)
- fatalerror("Card device %s (%s) does not implement abc_keyboard_interface\n", carddev->tag(), carddev->name());
-
- // resolve callbacks
- m_out_rx_handler.resolve_safe();
- m_out_trxc_handler.resolve_safe();
- m_out_keydown_handler.resolve_safe();
+ m_card = get_card_device();
}
@@ -89,6 +70,11 @@ void abc_keyboard_port_device::device_start()
void abc_keyboard_port_device::device_reset()
{
+ if (m_card)
+ {
+ m_card->reset_w(ASSERT_LINE);
+ m_card->reset_w(CLEAR_LINE);
+ }
}
@@ -96,7 +82,7 @@ void abc_keyboard_port_device::device_reset()
// 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);
}
@@ -106,9 +92,9 @@ 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 != nullptr)
+ if (m_card)
m_card->txd_w(state);
}
@@ -117,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);
}
@@ -127,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);
}
@@ -142,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 d7ab8b6162a..06e4f2a4cde 100644
--- a/src/devices/bus/abckb/abckb.h
+++ b/src/devices/bus/abckb/abckb.h
@@ -18,7 +18,7 @@
class abc_keyboard_interface;
-class abc_keyboard_port_device : public device_t, public device_slot_interface
+class abc_keyboard_port_device : public device_t, public device_single_card_slot_interface<abc_keyboard_interface>
{
public:
// construction/destruction
@@ -39,18 +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_validity_check(validity_checker &valid) const override;
- virtual void device_start() override;
- virtual void device_reset() override;
+ virtual void device_start() override ATTR_COLD;
+ virtual void device_reset() override ATTR_COLD;
devcb_write_line m_out_rx_handler;
devcb_write_line m_out_trxc_handler;
@@ -60,10 +59,11 @@ protected:
};
-class abc_keyboard_interface : public device_slot_card_interface
+class abc_keyboard_interface : public device_interface
{
public:
virtual void txd_w(int state) { }
+ virtual void reset_w(int state) { }
protected:
// construction/destruction
@@ -78,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..4df17377204
--- /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 ATTR_COLD;
+ virtual void device_reset() override ATTR_COLD;
+
+ // optional information overrides
+ virtual ioport_constructor device_input_ports() const override ATTR_COLD;
+
+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 fd33ec293a6..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
@@ -21,9 +22,11 @@ DEFINE_DEVICE_TYPE(ATOM_DISCPACK, atom_discpack_device, "atom_discpack", "Acorn
// MACHINE_DRIVER( discpack )
//-------------------------------------------------
-FLOPPY_FORMATS_MEMBER(atom_discpack_device::floppy_formats )
- FLOPPY_ACORN_SSD_FORMAT
-FLOPPY_FORMATS_END
+void atom_discpack_device::floppy_formats(format_registration &fr)
+{
+ fr.add_mfm_containers();
+ fr.add(FLOPPY_ACORN_SSD_FORMAT);
+}
static void atom_floppies(device_slot_interface &device)
{
@@ -84,11 +87,12 @@ void atom_discpack_device::device_start()
address_space &space = m_bus->memspace();
space.install_device(0x0a00, 0x0a03, *m_fdc, &i8271_device::map);
- space.install_readwrite_handler(0x0a04, 0x0a04, 0, 0x1f8, 0, read8smo_delegate(FUNC(i8271_device::data_r), m_fdc.target()), write8smo_delegate(FUNC(i8271_device::data_w), m_fdc.target()));
- space.install_ram(0x2000, 0x23ff);
- space.install_ram(0x2400, 0x27ff);
- space.install_ram(0x3c00, 0x3fff);
+ space.install_readwrite_handler(0x0a04, 0x0a04, 0, 0x1f8, 0, read8smo_delegate(*m_fdc, FUNC(i8271_device::data_r)), write8smo_delegate(*m_fdc, FUNC(i8271_device::data_w)));
+ space.install_ram(0x2000, 0x27ff, m_ram);
+ space.install_ram(0x3c00, 0x3fff, m_ram+0x800);
space.install_rom(0xe000, 0xefff, m_dos_rom->base());
+
+ save_item(NAME(m_ram));
}
@@ -96,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 3f06870f87c..c9fe66b1bb2 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
@@ -29,24 +28,26 @@ public:
// construction/destruction
atom_discpack_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
- DECLARE_FLOPPY_FORMATS(floppy_formats);
+ static void floppy_formats(format_registration &fr);
protected:
// device-level overrides
- virtual void device_start() override;
+ virtual void device_start() override ATTR_COLD;
// optional information overrides
- virtual void device_add_mconfig(machine_config &config) override;
- virtual const tiny_rom_entry *device_rom_region() const override;
+ virtual void device_add_mconfig(machine_config &config) override ATTR_COLD;
+ virtual const tiny_rom_entry *device_rom_region() const override ATTR_COLD;
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;
required_device_array<floppy_connector, 2> m_floppy;
+
+ u8 m_ram[0x800 + 0x400];
};
diff --git a/src/devices/bus/acorn/atom/econet.cpp b/src/devices/bus/acorn/atom/econet.cpp
index 5051fd0e8e7..206f3435e7e 100644
--- a/src/devices/bus/acorn/atom/econet.cpp
+++ b/src/devices/bus/acorn/atom/econet.cpp
@@ -63,20 +63,20 @@ void atom_econet_device::device_start()
{
address_space &space = m_bus->memspace();
- space.install_readwrite_handler(0xb400, 0xb403, read8sm_delegate(FUNC(mc6854_device::read), m_adlc.target()), write8sm_delegate(FUNC(mc6854_device::write), m_adlc.target()));
- space.install_read_handler(0xb404, 0xb404, read8_delegate(FUNC(atom_econet_device::statid_r), this));
+ space.install_readwrite_handler(0xb400, 0xb403, read8sm_delegate(*m_adlc, FUNC(mc6854_device::read)), write8sm_delegate(*m_adlc, FUNC(mc6854_device::write)));
+ space.install_read_handler(0xb404, 0xb404, read8smo_delegate(*this, FUNC(atom_econet_device::statid_r)));
}
//**************************************************************************
// IMPLEMENTATION
//**************************************************************************
-READ8_MEMBER(atom_econet_device::statid_r)
+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 8d5f5e8eb19..443d9939062 100644
--- a/src/devices/bus/acorn/atom/econet.h
+++ b/src/devices/bus/acorn/atom/econet.h
@@ -30,14 +30,14 @@ public:
protected:
// device-level overrides
- virtual void device_start() override;
+ virtual void device_start() override ATTR_COLD;
// optional information overrides
- virtual void device_add_mconfig(machine_config &config) override;
+ virtual void device_add_mconfig(machine_config &config) override ATTR_COLD;
private:
- DECLARE_READ8_MEMBER(statid_r);
- DECLARE_WRITE_LINE_MEMBER(bus_irq_w);
+ uint8_t statid_r();
+ 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/atom/sid.cpp b/src/devices/bus/acorn/atom/sid.cpp
index 8b5cd738cfe..4b0e1f7ff4d 100644
--- a/src/devices/bus/acorn/atom/sid.cpp
+++ b/src/devices/bus/acorn/atom/sid.cpp
@@ -55,5 +55,5 @@ void atom_sid_device::device_start()
{
address_space &space = m_bus->memspace();
- space.install_readwrite_handler(0xbdc0, 0xbddf, read8sm_delegate(FUNC(mos6581_device::read), m_sid.target()), write8sm_delegate(FUNC(mos6581_device::write), m_sid.target()));
+ space.install_readwrite_handler(0xbdc0, 0xbddf, read8sm_delegate(*m_sid, FUNC(mos6581_device::read)), write8sm_delegate(*m_sid, FUNC(mos6581_device::write)));
}
diff --git a/src/devices/bus/acorn/atom/sid.h b/src/devices/bus/acorn/atom/sid.h
index 8383bbdf9c8..7f8afe51cce 100644
--- a/src/devices/bus/acorn/atom/sid.h
+++ b/src/devices/bus/acorn/atom/sid.h
@@ -29,10 +29,10 @@ public:
protected:
// device-level overrides
- virtual void device_start() override;
+ virtual void device_start() override ATTR_COLD;
// optional information overrides
- virtual void device_add_mconfig(machine_config &config) override;
+ virtual void device_add_mconfig(machine_config &config) override ATTR_COLD;
private:
required_device<mos6581_device> m_sid;
diff --git a/src/devices/bus/acorn/bus.cpp b/src/devices/bus/acorn/bus.cpp
index 2ecb509c30f..8f3a5fcde07 100644
--- a/src/devices/bus/acorn/bus.cpp
+++ b/src/devices/bus/acorn/bus.cpp
@@ -28,36 +28,20 @@ DEFINE_DEVICE_TYPE(ACORN_BUS_SLOT, acorn_bus_slot_device, "acorn_bus_slot", "Aco
//-------------------------------------------------
acorn_bus_slot_device::acorn_bus_slot_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
: device_t(mconfig, ACORN_BUS_SLOT, tag, owner, clock)
- , device_slot_interface(mconfig, *this)
+ , device_single_card_slot_interface<device_acorn_bus_interface>(mconfig, *this)
, m_bus(*this, finder_base::DUMMY_TAG)
{
}
//-------------------------------------------------
-// device_validity_check - device-specific checks
-//-------------------------------------------------
-
-void acorn_bus_slot_device::device_validity_check(validity_checker &valid) const
-{
- device_t *const card(get_card_device());
- if (card && !dynamic_cast<device_acorn_bus_interface *>(card))
- osd_printf_error("acorn_bus_slot_device: card device %s (%s) does not implement device_acorn_bus_interface\n", card->tag(), card->name());
-}
-
-//-------------------------------------------------
// device_start - device-specific startup
//-------------------------------------------------
void acorn_bus_slot_device::device_start()
{
- device_t *const card(get_card_device());
- if (card)
- {
- device_acorn_bus_interface *const intf(dynamic_cast<device_acorn_bus_interface *>(card));
- if (!intf)
- throw emu_fatalerror("acorn_bus_slot_device: card device %s (%s) does not implement device_acorn_bus_interface\n", card->tag(), card->name());
+ device_acorn_bus_interface *const intf(get_card_device());
+ if (intf)
intf->set_acorn_bus(*m_bus);
- }
// tell acorn bus that there is one slot with the specified tag
m_bus->add_slot(*this);
@@ -99,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();
}
//-------------------------------------------------
@@ -113,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); }
@@ -132,7 +113,7 @@ WRITE_LINE_MEMBER(acorn_bus_device::nmi_w) { m_out_nmi_cb(state); }
//-------------------------------------------------
device_acorn_bus_interface::device_acorn_bus_interface(const machine_config &mconfig, device_t &device)
- : device_slot_card_interface(mconfig, device)
+ : device_interface(device, "acornbus")
, m_bus(nullptr)
{
}
@@ -175,6 +156,7 @@ void device_acorn_bus_interface::interface_pre_start()
#include "cms/4080term.h"
#include "cms/fdc.h"
#include "cms/hires.h"
+#include "cms/ieee.h"
void acorn_bus_devices(device_slot_interface &device)
{
@@ -203,4 +185,5 @@ void cms_bus_devices(device_slot_interface &device)
device.option_add("4080term", CMS_4080TERM); /* CMS 40/80 Video Terminal Card */
device.option_add("fdc", CMS_FDC); /* CMS Floppy Disc Controller */
device.option_add("hires", CMS_HIRES); /* CMS High Resolution Colour Graphics Card */
+ device.option_add("ieee", CMS_IEEE); /* CMS IEEE Interface */
}
diff --git a/src/devices/bus/acorn/bus.h b/src/devices/bus/acorn/bus.h
index 149da10d447..3a179ea2939 100644
--- a/src/devices/bus/acorn/bus.h
+++ b/src/devices/bus/acorn/bus.h
@@ -26,7 +26,7 @@ class device_acorn_bus_interface;
// TYPE DEFINITIONS
//**************************************************************************
-class acorn_bus_slot_device : public device_t, public device_slot_interface
+class acorn_bus_slot_device : public device_t, public device_single_card_slot_interface<device_acorn_bus_interface>
{
public:
// construction/destruction
@@ -44,8 +44,7 @@ public:
protected:
// device-level overrides
- virtual void device_validity_check(validity_checker &valid) const override;
- virtual void device_start() override;
+ virtual void device_start() override ATTR_COLD;
// configuration
required_device<acorn_bus_device> m_bus;
@@ -70,15 +69,15 @@ 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);
protected:
// device-level overrides
- virtual void device_start() override;
- virtual void device_reset() override;
+ virtual void device_start() override ATTR_COLD;
+ virtual void device_reset() override ATTR_COLD;
// internal state
required_address_space m_space;
@@ -96,7 +95,7 @@ DECLARE_DEVICE_TYPE(ACORN_BUS, acorn_bus_device)
// ======================> device_acorn_bus_interface
// class representing interface-specific live acorn bus card
-class device_acorn_bus_interface : public device_slot_card_interface
+class device_acorn_bus_interface : public device_interface
{
public:
friend class acorn_bus_device;
@@ -105,7 +104,7 @@ public:
virtual ~device_acorn_bus_interface();
// inline configuration
- void set_acorn_bus(acorn_bus_device &bus) { m_bus = &bus; }
+ void set_acorn_bus(acorn_bus_device &bus) { assert(!device().started()); m_bus = &bus; }
protected:
device_acorn_bus_interface(const machine_config &mconfig, device_t &device);
diff --git a/src/devices/bus/acorn/cms/4080term.cpp b/src/devices/bus/acorn/cms/4080term.cpp
index 629b4915fdd..8d9d2eae40f 100644
--- a/src/devices/bus/acorn/cms/4080term.cpp
+++ b/src/devices/bus/acorn/cms/4080term.cpp
@@ -58,7 +58,6 @@ ROM_END
static DEVICE_INPUT_DEFAULTS_START(keyboard)
DEVICE_INPUT_DEFAULTS("RS232_TXBAUD", 0xff, RS232_BAUD_1200)
- DEVICE_INPUT_DEFAULTS("RS232_STARTBITS", 0xff, RS232_STARTBITS_1)
DEVICE_INPUT_DEFAULTS("RS232_DATABITS", 0xff, RS232_DATABITS_8)
DEVICE_INPUT_DEFAULTS("RS232_PARITY", 0xff, RS232_PARITY_NONE)
DEVICE_INPUT_DEFAULTS("RS232_STOPBITS", 0xff, RS232_STOPBITS_2)
@@ -72,13 +71,11 @@ void cms_4080term_device::device_add_mconfig(machine_config &config)
{
/* video hardware */
SCREEN(config, m_screen, SCREEN_TYPE_RASTER);
- m_screen->set_refresh_hz(50);
- m_screen->set_size(768, 312);
- m_screen->set_visarea(0, 492 - 1, 0, 270 - 1);
+ m_screen->set_raw(12_MHz_XTAL, 768, 0, 492, 312, 0, 270);
m_screen->set_screen_update("ef9345", FUNC(ef9345_device::screen_update));
GFXDECODE(config, "gfxdecode", "palette", gfx_cms_4080term);
- PALETTE(config, "palette").set_entries(8);
+ PALETTE(config, "palette", palette_device::RGB_3BIT);
EF9345(config, m_ef9345, 0);
m_ef9345->set_screen("screen");
@@ -86,8 +83,8 @@ void cms_4080term_device::device_add_mconfig(machine_config &config)
TIMER(config, "scantimer").configure_scanline(FUNC(cms_4080term_device::update_scanline), "screen", 0, 10);
- VIA6522(config, m_via, 1_MHz_XTAL);
- m_via->writepa_handler().set("cent_data_out", FUNC(output_latch_device::bus_w));
+ MOS6522(config, m_via, 1_MHz_XTAL);
+ m_via->writepa_handler().set("cent_data_out", FUNC(output_latch_device::write));
m_via->ca2_handler().set(m_centronics, FUNC(centronics_device::write_strobe));
m_via->irq_handler().set(FUNC(cms_4080term_device::bus_irq_w));
@@ -147,9 +144,9 @@ void cms_4080term_device::device_start()
{
address_space &space = m_bus->memspace();
- space.install_readwrite_handler(0xfd20, 0xfd2f, read8sm_delegate(FUNC(ef9345_device::data_r), m_ef9345.target()), write8sm_delegate(FUNC(ef9345_device::data_w), m_ef9345.target()));
+ space.install_readwrite_handler(0xfd20, 0xfd2f, read8sm_delegate(*m_ef9345, FUNC(ef9345_device::data_r)), write8sm_delegate(*m_ef9345, FUNC(ef9345_device::data_w)));
space.install_device(0xfd30, 0xfd3f, *m_via, &via6522_device::map);
- space.install_readwrite_handler(0xfd40, 0xfd4f, read8sm_delegate(FUNC(mos6551_device::read), m_acia.target()), write8sm_delegate(FUNC(mos6551_device::write), m_acia.target()));
+ space.install_readwrite_handler(0xfd40, 0xfd4f, read8sm_delegate(*m_acia, FUNC(mos6551_device::read)), write8sm_delegate(*m_acia, FUNC(mos6551_device::write)));
uint8_t *FNT = memregion("ef9345")->base();
uint16_t dest = 0x2000;
@@ -172,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..70243153c05 100644
--- a/src/devices/bus/acorn/cms/4080term.h
+++ b/src/devices/bus/acorn/cms/4080term.h
@@ -36,14 +36,14 @@ public:
protected:
// device-level overrides
- virtual void device_start() override;
+ virtual void device_start() override ATTR_COLD;
// optional information overrides
- virtual void device_add_mconfig(machine_config &config) override;
- virtual const tiny_rom_entry *device_rom_region() const override;
+ virtual void device_add_mconfig(machine_config &config) override ATTR_COLD;
+ virtual const tiny_rom_entry *device_rom_region() const override ATTR_COLD;
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 833fa2b09a4..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
@@ -23,9 +24,12 @@ DEFINE_DEVICE_TYPE(CMS_FDC, cms_fdc_device, "cms_fdc", "CMS Floppy Disc Controll
// MACHINE_DRIVER( cms_fdc )
//-------------------------------------------------
-FLOPPY_FORMATS_MEMBER(cms_fdc_device::floppy_formats )
- FLOPPY_ACORN_SSD_FORMAT
-FLOPPY_FORMATS_END
+void cms_fdc_device::floppy_formats(format_registration &fr)
+{
+ fr.add_mfm_containers();
+ fr.add(FLOPPY_ACORN_SSD_FORMAT);
+ fr.add(FLOPPY_ACORN_DSD_FORMAT);
+}
static void cms_floppies(device_slot_interface &device)
{
@@ -39,14 +43,9 @@ static void cms_floppies(device_slot_interface &device)
void cms_fdc_device::device_add_mconfig(machine_config &config)
{
WD1770(config, m_fdc, 8_MHz_XTAL);
- //m_fdc->intrq_wr_callback().set(FUNC(cms_fdc_device::bus_irq_w));
- //m_fdc->drq_wr_callback().set(FUNC(cms_fdc_device::bus_nmi_w));
- FLOPPY_CONNECTOR(config, m_floppy[0], cms_floppies, "35dd", floppy_formats);
- m_floppy[0]->enable_sound(true);
- FLOPPY_CONNECTOR(config, m_floppy[1], cms_floppies, "35dd", floppy_formats);
- m_floppy[1]->enable_sound(true);
- FLOPPY_CONNECTOR(config, m_floppy[2], cms_floppies, nullptr, floppy_formats);
- m_floppy[2]->enable_sound(true);
+ FLOPPY_CONNECTOR(config, m_floppy[0], cms_floppies, "35dd", floppy_formats).enable_sound(true);
+ FLOPPY_CONNECTOR(config, m_floppy[1], cms_floppies, "35dd", floppy_formats).enable_sound(true);
+ FLOPPY_CONNECTOR(config, m_floppy[2], cms_floppies, nullptr, floppy_formats).enable_sound(true);
}
@@ -75,8 +74,8 @@ void cms_fdc_device::device_start()
{
address_space &space = m_bus->memspace();
- space.install_readwrite_handler(0xfc50, 0xfc5f, read8_delegate(FUNC(cms_fdc_device::wd1770_state_r), this), write8_delegate(FUNC(cms_fdc_device::wd1770_control_w), this));
- space.install_readwrite_handler(0xfc40, 0xfc4f, read8sm_delegate(FUNC(wd1770_device::read), m_fdc.target()), write8sm_delegate(FUNC(wd1770_device::write), m_fdc.target()));
+ space.install_readwrite_handler(0xfc50, 0xfc5f, read8smo_delegate(*this, FUNC(cms_fdc_device::wd1770_state_r)), write8smo_delegate(*this, FUNC(cms_fdc_device::wd1770_control_w)));
+ space.install_readwrite_handler(0xfc40, 0xfc4f, read8sm_delegate(*m_fdc, FUNC(wd1770_device::read)), write8sm_delegate(*m_fdc, FUNC(wd1770_device::write)));
}
@@ -84,20 +83,19 @@ void cms_fdc_device::device_start()
// IMPLEMENTATION
//**************************************************************************
-READ8_MEMBER(cms_fdc_device::wd1770_state_r)
+uint8_t cms_fdc_device::wd1770_state_r()
{
uint8_t data = 0x3f;
data |= m_fdc->intrq_r() << 6;
data |= m_fdc->drq_r() << 7;
- logerror("floppy state %02x\n", data);
+
return data;
}
-WRITE8_MEMBER(cms_fdc_device::wd1770_control_w)
+void cms_fdc_device::wd1770_control_w(uint8_t data)
{
floppy_image_device *floppy = nullptr;
- logerror("floppy control %02x\n", data);
// bit 0, 1, 2: drive select
if (BIT(data, 0)) floppy = m_floppy[0]->get_device();
@@ -112,13 +110,3 @@ WRITE8_MEMBER(cms_fdc_device::wd1770_control_w)
// bit 7: density ??
m_fdc->dden_w(BIT(data, 7));
}
-
-WRITE_LINE_MEMBER(cms_fdc_device::bus_nmi_w)
-{
- m_bus->nmi_w(state);
-}
-
-WRITE_LINE_MEMBER(cms_fdc_device::bus_irq_w)
-{
- m_bus->irq_w(state);
-}
diff --git a/src/devices/bus/acorn/cms/fdc.h b/src/devices/bus/acorn/cms/fdc.h
index 4795eaab18a..a07c2b4abd1 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
@@ -29,20 +27,18 @@ public:
// construction/destruction
cms_fdc_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
- DECLARE_FLOPPY_FORMATS(floppy_formats);
+ static void floppy_formats(format_registration &fr);
protected:
// device-level overrides
- virtual void device_start() override;
+ virtual void device_start() override ATTR_COLD;
// optional information overrides
- virtual void device_add_mconfig(machine_config &config) override;
+ virtual void device_add_mconfig(machine_config &config) override ATTR_COLD;
private:
- DECLARE_READ8_MEMBER(wd1770_state_r);
- DECLARE_WRITE8_MEMBER(wd1770_control_w);
- DECLARE_WRITE_LINE_MEMBER(bus_irq_w);
- DECLARE_WRITE_LINE_MEMBER(bus_nmi_w);
+ uint8_t wd1770_state_r();
+ void wd1770_control_w(uint8_t data);
required_device<wd_fdc_device_base> m_fdc;
required_device_array<floppy_connector, 3> m_floppy;
diff --git a/src/devices/bus/acorn/cms/hires.cpp b/src/devices/bus/acorn/cms/hires.cpp
index 9e6e169737b..de42be218cd 100644
--- a/src/devices/bus/acorn/cms/hires.cpp
+++ b/src/devices/bus/acorn/cms/hires.cpp
@@ -71,8 +71,8 @@ void cms_hires_device::device_start()
{
address_space &space = m_bus->memspace();
- space.install_readwrite_handler(0xfc10, 0xfc1f, read8sm_delegate(FUNC(ef9365_device::data_r), m_gdp.target()), write8sm_delegate(FUNC(ef9365_device::data_w), m_gdp.target()));
- space.install_write_handler(0xfc20, 0xfc2f, write8_delegate(FUNC(cms_hires_device::colour_reg_w), this));
+ space.install_readwrite_handler(0xfc10, 0xfc1f, read8sm_delegate(*m_gdp, FUNC(ef9365_device::data_r)), write8sm_delegate(*m_gdp, FUNC(ef9365_device::data_w)));
+ space.install_write_handler(0xfc20, 0xfc2f, write8smo_delegate(*this, FUNC(cms_hires_device::colour_reg_w)));
save_item(NAME(m_flash_state));
}
@@ -109,7 +109,7 @@ TIMER_DEVICE_CALLBACK_MEMBER(cms_hires_device::flash_rate)
}
}
-WRITE8_MEMBER(cms_hires_device::colour_reg_w)
+void cms_hires_device::colour_reg_w(uint8_t data)
{
m_gdp->set_color_filler(data & 0x0f);
}
diff --git a/src/devices/bus/acorn/cms/hires.h b/src/devices/bus/acorn/cms/hires.h
index 5f2f2a691c2..03361e2bb37 100644
--- a/src/devices/bus/acorn/cms/hires.h
+++ b/src/devices/bus/acorn/cms/hires.h
@@ -30,15 +30,15 @@ public:
protected:
// device-level overrides
- virtual void device_start() override;
- virtual void device_reset() override;
+ virtual void device_start() override ATTR_COLD;
+ virtual void device_reset() override ATTR_COLD;
// optional information overrides
- virtual void device_add_mconfig(machine_config &config) override;
+ virtual void device_add_mconfig(machine_config &config) override ATTR_COLD;
private:
TIMER_DEVICE_CALLBACK_MEMBER(flash_rate);
- DECLARE_WRITE8_MEMBER(colour_reg_w);
+ void colour_reg_w(uint8_t data);
required_device<screen_device> m_screen;
required_device<ef9365_device> m_gdp;
diff --git a/src/devices/bus/acorn/cms/ieee.cpp b/src/devices/bus/acorn/cms/ieee.cpp
new file mode 100644
index 00000000000..001424aeb41
--- /dev/null
+++ b/src/devices/bus/acorn/cms/ieee.cpp
@@ -0,0 +1,89 @@
+// license:BSD-3-Clause
+// copyright-holders:Nigel Barnes
+/**********************************************************************
+
+ CMS IEEE Controller Board
+
+**********************************************************************/
+
+
+#include "emu.h"
+#include "ieee.h"
+
+
+//**************************************************************************
+// DEVICE DEFINITIONS
+//**************************************************************************
+
+DEFINE_DEVICE_TYPE(CMS_IEEE, cms_ieee_device, "cms_ieee", "CMS IEEE Controller Board");
+
+
+//-------------------------------------------------
+// device_add_mconfig - add device configuration
+//-------------------------------------------------
+
+void cms_ieee_device::device_add_mconfig(machine_config &config)
+{
+ TMS9914(config, m_tms9914, 4_MHz_XTAL); // TODO: verify clock
+ m_tms9914->int_write_cb().set(FUNC(cms_ieee_device::bus_irq_w));
+ 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);
+}
+
+
+//**************************************************************************
+// LIVE DEVICE
+//**************************************************************************
+
+//-------------------------------------------------
+// cms_ieee_device - constructor
+//-------------------------------------------------
+
+cms_ieee_device::cms_ieee_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
+ : device_t(mconfig, CMS_IEEE, tag, owner, clock)
+ , device_acorn_bus_interface(mconfig, *this)
+ , m_ieee(*this, IEEE488_TAG)
+ , m_tms9914(*this, "hpib")
+{
+}
+
+
+//-------------------------------------------------
+// device_start - device-specific startup
+//-------------------------------------------------
+
+void cms_ieee_device::device_start()
+{
+ address_space &space = m_bus->memspace();
+
+ space.install_readwrite_handler(0xfc60, 0xfc6f, read8sm_delegate(*m_tms9914, FUNC(tms9914_device::read)), write8sm_delegate(*m_tms9914, FUNC(tms9914_device::write)));
+}
+
+
+//**************************************************************************
+// IMPLEMENTATION
+//**************************************************************************
+
+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
new file mode 100644
index 00000000000..65738e800b9
--- /dev/null
+++ b/src/devices/bus/acorn/cms/ieee.h
@@ -0,0 +1,48 @@
+// license:BSD-3-Clause
+// copyright-holders:Nigel Barnes
+/**********************************************************************
+
+ CMS IEEE Controller Board
+
+**********************************************************************/
+
+
+#ifndef MAME_BUS_ACORN_CMS_IEEE_H
+#define MAME_BUS_ACORN_CMS_IEEE_H
+
+#include "bus/acorn/bus.h"
+#include "bus/ieee488/ieee488.h"
+#include "machine/tms9914.h"
+
+//**************************************************************************
+// TYPE DEFINITIONS
+//**************************************************************************
+
+class cms_ieee_device:
+ public device_t,
+ public device_acorn_bus_interface
+{
+public:
+ // construction/destruction
+ cms_ieee_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
+
+protected:
+ // device-level overrides
+ virtual void device_start() override ATTR_COLD;
+
+ // optional information overrides
+ virtual void device_add_mconfig(machine_config &config) override ATTR_COLD;
+
+private:
+ void bus_irq_w(int state);
+
+ required_device<ieee488_device> m_ieee;
+ required_device<tms9914_device> m_tms9914;
+};
+
+
+// device type definition
+DECLARE_DEVICE_TYPE(CMS_IEEE, cms_ieee_device);
+
+
+#endif /* MAME_BUS_ACORN_CMS_IEEE_H */
diff --git a/src/devices/bus/acorn/system/32k.cpp b/src/devices/bus/acorn/system/32k.cpp
index c74d60cc863..00eb80050e9 100644
--- a/src/devices/bus/acorn/system/32k.cpp
+++ b/src/devices/bus/acorn/system/32k.cpp
@@ -73,6 +73,7 @@ acorn_32k_device::acorn_32k_device(const machine_config &mconfig, const char *ta
void acorn_32k_device::device_start()
{
+ save_item(NAME(m_ram));
}
//-------------------------------------------------
@@ -85,11 +86,11 @@ void acorn_32k_device::device_reset()
if (m_links->read())
{
- space.install_ram(0x8000, 0xbfff);
+ space.install_ram(0x8000, 0xbfff, m_ram);
}
else
{
- space.install_ram(0x2000, 0x7fff);
- space.install_ram(0xc000, 0xdfff);
+ space.install_ram(0x2000, 0x7fff, m_ram);
+ space.install_ram(0xc000, 0xdfff, m_ram + 0x6000);
}
}
diff --git a/src/devices/bus/acorn/system/32k.h b/src/devices/bus/acorn/system/32k.h
index 0ef4c10f3c3..f6459292aee 100644
--- a/src/devices/bus/acorn/system/32k.h
+++ b/src/devices/bus/acorn/system/32k.h
@@ -30,14 +30,15 @@ public:
protected:
// device-level overrides
- virtual void device_start() override;
- virtual void device_reset() override;
+ virtual void device_start() override ATTR_COLD;
+ virtual void device_reset() override ATTR_COLD;
// optional information overrides
- virtual ioport_constructor device_input_ports() const override;
+ virtual ioport_constructor device_input_ports() const override ATTR_COLD;
private:
required_ioport m_links;
+ u8 m_ram[32768];
};
diff --git a/src/devices/bus/acorn/system/8k.cpp b/src/devices/bus/acorn/system/8k.cpp
index b8635920aab..b83544d3c8f 100644
--- a/src/devices/bus/acorn/system/8k.cpp
+++ b/src/devices/bus/acorn/system/8k.cpp
@@ -70,8 +70,8 @@ ioport_constructor acorn_8k_device::device_input_ports() const
void acorn_8k_device::device_add_mconfig(machine_config &config)
{
/* rom sockets */
- GENERIC_SOCKET(config, "rom0", generic_plain_slot, "acrnsys_rom", "bin,rom").set_device_load(FUNC(acorn_8k_device::rom0_load), this); // IC17
- GENERIC_SOCKET(config, "rom1", generic_plain_slot, "acrnsys_rom", "bin,rom").set_device_load(FUNC(acorn_8k_device::rom1_load), this); // IC18
+ GENERIC_SOCKET(config, "rom0", generic_plain_slot, "acrnsys_rom", "bin,rom").set_device_load(FUNC(acorn_8k_device::rom0_load)); // IC17
+ GENERIC_SOCKET(config, "rom1", generic_plain_slot, "acrnsys_rom", "bin,rom").set_device_load(FUNC(acorn_8k_device::rom1_load)); // IC18
}
@@ -98,6 +98,7 @@ acorn_8k_device::acorn_8k_device(const machine_config &mconfig, const char *tag,
void acorn_8k_device::device_start()
{
+ save_item(NAME(m_ram));
}
//-------------------------------------------------
@@ -112,11 +113,11 @@ void acorn_8k_device::device_reset()
if (ram_addr == 0x0000) // BLK0
{
- space.install_ram(0x1000, 0x1fff);
+ space.install_ram(0x1000, 0x1fff, m_ram);
}
else
{
- space.install_ram(ram_addr, ram_addr + 0x1fff);
+ space.install_ram(ram_addr, ram_addr + 0x1fff, m_ram);
}
uint16_t rom_addr = (m_links->read() & 0xf0) << 9;
@@ -136,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_UNSPECIFIED, "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");
@@ -154,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 125b636cd5b..6837beb0a22 100644
--- a/src/devices/bus/acorn/system/8k.h
+++ b/src/devices/bus/acorn/system/8k.h
@@ -32,21 +32,22 @@ public:
acorn_8k_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_t implementation
+ virtual void device_start() override ATTR_COLD;
+ virtual void device_reset() override ATTR_COLD;
// optional information overrides
- virtual void device_add_mconfig(machine_config &config) override;
- virtual ioport_constructor device_input_ports() const override;
+ virtual void device_add_mconfig(machine_config &config) override ATTR_COLD;
+ virtual ioport_constructor device_input_ports() const override ATTR_COLD;
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]); }
required_device_array<generic_slot_device, 2> m_rom;
required_ioport m_links;
+ u8 m_ram[8192];
};
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..36df84e80c1 100644
--- a/src/devices/bus/acorn/system/cass.h
+++ b/src/devices/bus/acorn/system/cass.h
@@ -32,13 +32,13 @@ public:
protected:
// device-level overrides
- virtual void device_start() override;
+ virtual void device_start() override ATTR_COLD;
// optional information overrides
- virtual void device_add_mconfig(machine_config &config) override;
+ virtual void device_add_mconfig(machine_config &config) override ATTR_COLD;
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 261fb4261a1..55ffc5232cf 100644
--- a/src/devices/bus/acorn/system/econet.cpp
+++ b/src/devices/bus/acorn/system/econet.cpp
@@ -70,20 +70,20 @@ void acorn_econet_device::device_reset()
{
address_space &space = m_bus->memspace();
- space.install_readwrite_handler(0x1940, 0x1943, read8sm_delegate(FUNC(mc6854_device::read), m_adlc.target()), write8sm_delegate(FUNC(mc6854_device::write), m_adlc.target()));
- space.install_read_handler(0x1944, 0x1944, read8_delegate(FUNC(acorn_econet_device::statid_r), this));
+ space.install_readwrite_handler(0x1940, 0x1943, read8sm_delegate(*m_adlc, FUNC(mc6854_device::read)), write8sm_delegate(*m_adlc, FUNC(mc6854_device::write)));
+ space.install_read_handler(0x1944, 0x1944, read8smo_delegate(*this, FUNC(acorn_econet_device::statid_r)));
}
//**************************************************************************
// IMPLEMENTATION
//**************************************************************************
-READ8_MEMBER(acorn_econet_device::statid_r)
+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 4b876674ae4..9a649aaaf10 100644
--- a/src/devices/bus/acorn/system/econet.h
+++ b/src/devices/bus/acorn/system/econet.h
@@ -32,15 +32,15 @@ public:
protected:
// device-level overrides
- virtual void device_start() override;
- virtual void device_reset() override;
+ virtual void device_start() override ATTR_COLD;
+ virtual void device_reset() override ATTR_COLD;
// optional information overrides
- virtual void device_add_mconfig(machine_config &config) override;
+ virtual void device_add_mconfig(machine_config &config) override ATTR_COLD;
private:
- DECLARE_READ8_MEMBER(statid_r);
- DECLARE_WRITE_LINE_MEMBER(bus_irq_w);
+ uint8_t statid_r();
+ 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 179b914d3cf..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
@@ -25,9 +26,11 @@ DEFINE_DEVICE_TYPE(ACORN_FDC, acorn_fdc_device, "acorn_fdc", "Acorn Floppy Disc
// MACHINE_DRIVER( fdc )
//-------------------------------------------------
-FLOPPY_FORMATS_MEMBER(acorn_fdc_device::floppy_formats )
- FLOPPY_ACORN_SSD_FORMAT
-FLOPPY_FORMATS_END
+void acorn_fdc_device::floppy_formats(format_registration &fr)
+{
+ fr.add_mfm_containers();
+ fr.add(FLOPPY_ACORN_SSD_FORMAT);
+}
static void acorn_floppies(device_slot_interface &device)
{
@@ -85,7 +88,7 @@ void acorn_fdc_device::device_reset()
address_space &space = m_bus->memspace();
space.install_device(0x0a00, 0x0a03, *m_fdc, &i8271_device::map);
- space.install_readwrite_handler(0x0a04, 0x0a04, 0, 0x1f8, 0, read8smo_delegate(FUNC(i8271_device::data_r), m_fdc.target()), write8smo_delegate(FUNC(i8271_device::data_w), m_fdc.target()));
+ space.install_readwrite_handler(0x0a04, 0x0a04, 0, 0x1f8, 0, read8smo_delegate(*m_fdc, FUNC(i8271_device::data_r)), write8smo_delegate(*m_fdc, FUNC(i8271_device::data_w)));
}
@@ -93,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 d2c0286ad27..c4be0b71748 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
@@ -31,20 +29,20 @@ public:
// construction/destruction
acorn_fdc_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
- DECLARE_FLOPPY_FORMATS(floppy_formats);
+ static void floppy_formats(format_registration &fr);
protected:
// device-level overrides
- virtual void device_start() override;
- virtual void device_reset() override;
+ virtual void device_start() override ATTR_COLD;
+ virtual void device_reset() override ATTR_COLD;
// optional information overrides
- virtual void device_add_mconfig(machine_config &config) override;
+ virtual void device_add_mconfig(machine_config &config) override ATTR_COLD;
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 916d7309dc3..1916981dc73 100644
--- a/src/devices/bus/acorn/system/vdu40.cpp
+++ b/src/devices/bus/acorn/system/vdu40.cpp
@@ -38,7 +38,7 @@ void acorn_vdu40_device::device_add_mconfig(machine_config &config)
m_crtc->set_show_border_area(false);
m_crtc->set_char_width(12);
m_crtc->out_vsync_callback().set(FUNC(acorn_vdu40_device::vsync_changed));
- m_crtc->set_update_row_callback(FUNC(acorn_vdu40_device::crtc_update_row), this);
+ m_crtc->set_update_row_callback(FUNC(acorn_vdu40_device::crtc_update_row));
SAA5050(config, m_trom, 12_MHz_XTAL / 2);
m_trom->set_screen_size(40, 25, 40);
@@ -82,8 +82,8 @@ void acorn_vdu40_device::device_reset()
address_space &space = m_bus->memspace();
space.install_ram(0x0400, 0x07ff, m_videoram.get());
- space.install_readwrite_handler(0x0800, 0x0800, read8smo_delegate(FUNC(mc6845_device::status_r), m_crtc.target()), write8smo_delegate(FUNC(mc6845_device::address_w), m_crtc.target()));
- space.install_readwrite_handler(0x0801, 0x0801, read8smo_delegate(FUNC(mc6845_device::register_r), m_crtc.target()), write8smo_delegate(FUNC(mc6845_device::register_w), m_crtc.target()));
+ space.install_readwrite_handler(0x0800, 0x0800, read8smo_delegate(*m_crtc, FUNC(mc6845_device::status_r)), write8smo_delegate(*m_crtc, FUNC(mc6845_device::address_w)));
+ space.install_readwrite_handler(0x0801, 0x0801, read8smo_delegate(*m_crtc, FUNC(mc6845_device::register_r)), write8smo_delegate(*m_crtc, FUNC(mc6845_device::register_w)));
}
@@ -93,7 +93,7 @@ void acorn_vdu40_device::device_reset()
MC6845_UPDATE_ROW(acorn_vdu40_device::crtc_update_row)
{
- uint32_t *p = &bitmap.pix32(y);
+ uint32_t *p = &bitmap.pix(y);
m_trom->lose_w(1);
m_trom->lose_w(0);
@@ -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..994c617d986 100644
--- a/src/devices/bus/acorn/system/vdu40.h
+++ b/src/devices/bus/acorn/system/vdu40.h
@@ -34,15 +34,15 @@ public:
protected:
// device-level overrides
- virtual void device_start() override;
- virtual void device_reset() override;
+ virtual void device_start() override ATTR_COLD;
+ virtual void device_reset() override ATTR_COLD;
// optional information overrides
- virtual void device_add_mconfig(machine_config &config) override;
+ virtual void device_add_mconfig(machine_config &config) override ATTR_COLD;
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/vdu80.cpp b/src/devices/bus/acorn/system/vdu80.cpp
index 702041c3cf1..77bad0bf32c 100644
--- a/src/devices/bus/acorn/system/vdu80.cpp
+++ b/src/devices/bus/acorn/system/vdu80.cpp
@@ -101,7 +101,7 @@ void acorn_vdu80_device::device_add_mconfig(machine_config &config)
m_crtc->set_screen("screen");
m_crtc->set_show_border_area(false);
m_crtc->set_char_width(6);
- m_crtc->set_update_row_callback(FUNC(acorn_vdu80_device::crtc_update_row), this);
+ m_crtc->set_update_row_callback(FUNC(acorn_vdu80_device::crtc_update_row));
}
@@ -152,15 +152,15 @@ void acorn_vdu80_device::device_reset()
{
space.install_ram(0xf000, 0x0f7ff, m_videoram.get());
- space.install_readwrite_handler(0xe840, 0xe840, 0, 0x3f, 0, read8smo_delegate(FUNC(mc6845_device::status_r), m_crtc.target()), write8smo_delegate(FUNC(mc6845_device::address_w), m_crtc.target()));
- space.install_readwrite_handler(0xe841, 0xe841, 0, 0x3e, 0, read8smo_delegate(FUNC(mc6845_device::register_r), m_crtc.target()), write8smo_delegate(FUNC(mc6845_device::register_w), m_crtc.target()));
+ space.install_readwrite_handler(0xe840, 0xe840, 0, 0x3f, 0, read8smo_delegate(*m_crtc, FUNC(mc6845_device::status_r)), write8smo_delegate(*m_crtc, FUNC(mc6845_device::address_w)));
+ space.install_readwrite_handler(0xe841, 0xe841, 0, 0x3e, 0, read8smo_delegate(*m_crtc, FUNC(mc6845_device::register_r)), write8smo_delegate(*m_crtc, FUNC(mc6845_device::register_w)));
}
else
{
space.install_ram(0x1000, 0x017ff, m_videoram.get());
- space.install_readwrite_handler(0x1840, 0x1840, 0, 0x3f, 0, read8smo_delegate(FUNC(mc6845_device::status_r), m_crtc.target()), write8smo_delegate(FUNC(mc6845_device::address_w), m_crtc.target()));
- space.install_readwrite_handler(0x1841, 0x1841, 0, 0x3e, 0, read8smo_delegate(FUNC(mc6845_device::register_r), m_crtc.target()), write8smo_delegate(FUNC(mc6845_device::register_w), m_crtc.target()));
+ space.install_readwrite_handler(0x1840, 0x1840, 0, 0x3f, 0, read8smo_delegate(*m_crtc, FUNC(mc6845_device::status_r)), write8smo_delegate(*m_crtc, FUNC(mc6845_device::address_w)));
+ space.install_readwrite_handler(0x1841, 0x1841, 0, 0x3e, 0, read8smo_delegate(*m_crtc, FUNC(mc6845_device::register_r)), write8smo_delegate(*m_crtc, FUNC(mc6845_device::register_w)));
}
}
@@ -172,7 +172,7 @@ void acorn_vdu80_device::device_reset()
MC6845_UPDATE_ROW(acorn_vdu80_device::crtc_update_row)
{
uint8_t invert = BIT(m_links->read(), 1);
- uint32_t *p = &bitmap.pix32(y);
+ uint32_t *p = &bitmap.pix(y);
for (int column = 0; column < x_count; column++)
{
diff --git a/src/devices/bus/acorn/system/vdu80.h b/src/devices/bus/acorn/system/vdu80.h
index 8ebb7e0a327..3b84086fee3 100644
--- a/src/devices/bus/acorn/system/vdu80.h
+++ b/src/devices/bus/acorn/system/vdu80.h
@@ -33,13 +33,13 @@ public:
protected:
// device-level overrides
- virtual void device_start() override;
- virtual void device_reset() override;
+ virtual void device_start() override ATTR_COLD;
+ virtual void device_reset() override ATTR_COLD;
// 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 void device_add_mconfig(machine_config &config) override ATTR_COLD;
+ virtual const tiny_rom_entry *device_rom_region() const override ATTR_COLD;
+ virtual ioport_constructor device_input_ports() const override ATTR_COLD;
private:
MC6845_UPDATE_ROW(crtc_update_row);
diff --git a/src/devices/bus/acorn/system/vib.cpp b/src/devices/bus/acorn/system/vib.cpp
index 48e08bd4088..cb44e02ce79 100644
--- a/src/devices/bus/acorn/system/vib.cpp
+++ b/src/devices/bus/acorn/system/vib.cpp
@@ -21,42 +21,6 @@
DEFINE_DEVICE_TYPE(ACORN_VIB, acorn_vib_device, "acorn_vib", "Acorn Versatile Interface Board")
-
-//-------------------------------------------------
-// device_add_mconfig - add device configuration
-//-------------------------------------------------
-
-void acorn_vib_device::device_add_mconfig(machine_config &config)
-{
- INPUT_MERGER_ANY_HIGH(config, m_irqs).output_handler().set(FUNC(acorn_vib_device::irq_w));
-
- VIA6522(config, m_via6522, XTAL(1'000'000));
- m_via6522->writepa_handler().set("cent_data_out", FUNC(output_latch_device::bus_w));
- m_via6522->ca2_handler().set(m_centronics, FUNC(centronics_device::write_strobe));
- m_via6522->irq_handler().set(m_irqs, FUNC(input_merger_device::in_w<0>));
-
- CENTRONICS(config, m_centronics, centronics_devices, "printer");
- m_centronics->ack_handler().set(m_via6522, FUNC(via6522_device::write_ca1));
- m_centronics->busy_handler().set(m_via6522, FUNC(via6522_device::write_pa7));
- output_latch_device &cent_data_out(OUTPUT_LATCH(config, "cent_data_out"));
- m_centronics->set_output_latch(cent_data_out);
-
- I8255(config, m_ppi8255, 0);
-
- ACIA6850(config, m_acia, 0);
- 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(m_irqs, FUNC(input_merger_device::in_w<1>));
-
- 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));
- m_rs232->dcd_handler().set(m_acia, FUNC(acia6850_device::write_dcd));
-
- CLOCK(config, m_acia_clock, 1.8432_MHz_XTAL);
- m_acia_clock->signal_handler().set(FUNC(acorn_vib_device::write_acia_clock));
-}
-
//**************************************************************************
// LIVE DEVICE
//**************************************************************************
@@ -71,20 +35,72 @@ acorn_vib_device::acorn_vib_device(const machine_config &mconfig, const char *ta
, m_ppi8255(*this, "ppi8255")
, m_via6522(*this, "via6522")
, m_acia(*this, "acia6850")
- , m_acia_clock(*this, "acia_clock")
+ , m_mc14411(*this, "mc14411")
, m_centronics(*this, "centronics")
, m_rs232(*this, "rs232")
, m_irqs(*this, "irqs")
+ , m_txc(*this, "TXC")
+ , m_rxc(*this, "RXC")
{
}
+static INPUT_PORTS_START(acorn_vib)
+ PORT_START("TXC")
+ PORT_CONFNAME(0x0f, mc14411_device::TIMER_F1, "Transmit Rate")
+ PORT_CONFSETTING(mc14411_device::TIMER_F1, "9600")
+ PORT_CONFSETTING(mc14411_device::TIMER_F2, "7200")
+ PORT_CONFSETTING(mc14411_device::TIMER_F3, "4800")
+ PORT_CONFSETTING(mc14411_device::TIMER_F4, "3600")
+ PORT_CONFSETTING(mc14411_device::TIMER_F5, "2400")
+ PORT_CONFSETTING(mc14411_device::TIMER_F6, "1800")
+ PORT_CONFSETTING(mc14411_device::TIMER_F7, "1200")
+ PORT_CONFSETTING(mc14411_device::TIMER_F8, "600")
+ PORT_CONFSETTING(mc14411_device::TIMER_F9, "300")
+ PORT_CONFSETTING(mc14411_device::TIMER_F10, "200")
+ PORT_CONFSETTING(mc14411_device::TIMER_F11, "150")
+ PORT_CONFSETTING(mc14411_device::TIMER_F12, "134.5")
+ PORT_CONFSETTING(mc14411_device::TIMER_F13, "110")
+ PORT_CONFSETTING(mc14411_device::TIMER_F14, "75")
+
+ PORT_START("RXC")
+ PORT_CONFNAME(0x0f, mc14411_device::TIMER_F1, "Receive Rate")
+ PORT_CONFSETTING(mc14411_device::TIMER_F1, "9600")
+ PORT_CONFSETTING(mc14411_device::TIMER_F2, "7200")
+ PORT_CONFSETTING(mc14411_device::TIMER_F3, "4800")
+ PORT_CONFSETTING(mc14411_device::TIMER_F4, "3600")
+ PORT_CONFSETTING(mc14411_device::TIMER_F5, "2400")
+ PORT_CONFSETTING(mc14411_device::TIMER_F6, "1800")
+ PORT_CONFSETTING(mc14411_device::TIMER_F7, "1200")
+ PORT_CONFSETTING(mc14411_device::TIMER_F8, "600")
+ PORT_CONFSETTING(mc14411_device::TIMER_F9, "300")
+ PORT_CONFSETTING(mc14411_device::TIMER_F10, "200")
+ PORT_CONFSETTING(mc14411_device::TIMER_F11, "150")
+ PORT_CONFSETTING(mc14411_device::TIMER_F12, "134.5")
+ PORT_CONFSETTING(mc14411_device::TIMER_F13, "110")
+ PORT_CONFSETTING(mc14411_device::TIMER_F14, "75")
+INPUT_PORTS_END
+
+//-------------------------------------------------
+// input_ports - return a pointer to the implicit
+// input ports description for this device
+//-------------------------------------------------
+
+ioport_constructor acorn_vib_device::device_input_ports() const
+{
+ return INPUT_PORTS_NAME(acorn_vib);
+}
+
+
//-------------------------------------------------
// device_start - device-specific startup
//-------------------------------------------------
void acorn_vib_device::device_start()
{
+ m_acia->write_dcd(0);
+ m_mc14411->rsa_w(1);
+ m_mc14411->rsb_w(1);
}
//-------------------------------------------------
@@ -97,8 +113,12 @@ void acorn_vib_device::device_reset()
space.install_device(0x0c00, 0x0c0f, *m_via6522, &via6522_device::map);
space.install_device(0x0c10, 0x0c1f, *m_via6522, &via6522_device::map);
- space.install_readwrite_handler(0x0c20, 0x0c21, 0, 0x1e, 0, read8sm_delegate(FUNC(acia6850_device::read), m_acia.target()), write8sm_delegate(FUNC(acia6850_device::write), m_acia.target()));
- space.install_readwrite_handler(0x0c40, 0x0c43, 0, 0x1c, 0, read8sm_delegate(FUNC(i8255_device::read), m_ppi8255.target()), write8sm_delegate(FUNC(i8255_device::write), m_ppi8255.target()));
+ space.install_readwrite_handler(0x0c20, 0x0c21, 0, 0x1e, 0, read8sm_delegate(*m_acia, FUNC(acia6850_device::read)), write8sm_delegate(*m_acia, FUNC(acia6850_device::write)));
+ space.install_readwrite_handler(0x0c40, 0x0c43, 0, 0x1c, 0, read8sm_delegate(*m_ppi8255, FUNC(i8255_device::read)), write8sm_delegate(*m_ppi8255, FUNC(i8255_device::write)));
+
+ m_mc14411->timer_disable_all();
+ m_mc14411->timer_enable(mc14411_device::timer_id(m_txc->read()), true);
+ m_mc14411->timer_enable(mc14411_device::timer_id(m_rxc->read()), true);
}
@@ -106,13 +126,64 @@ void acorn_vib_device::device_reset()
// IMPLEMENTATION
//**************************************************************************
-WRITE_LINE_MEMBER(acorn_vib_device::write_acia_clock)
+template<mc14411_device::timer_id T>
+void acorn_vib_device::write_acia_clock(int state)
{
- m_acia->write_txc(state);
- m_acia->write_rxc(state);
+ if (T == m_txc->read())
+ m_acia->write_txc(state);
+ if (T == m_rxc->read())
+ 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);
}
+
+
+//-------------------------------------------------
+// device_add_mconfig - add device configuration
+//-------------------------------------------------
+
+void acorn_vib_device::device_add_mconfig(machine_config &config)
+{
+ INPUT_MERGER_ANY_HIGH(config, m_irqs).output_handler().set(FUNC(acorn_vib_device::irq_w));
+
+ MOS6522(config, m_via6522, 1'000'000); // TODO: derive clock from bus (pin 29 = ϕ2)
+ m_via6522->writepa_handler().set("cent_data_out", FUNC(output_latch_device::write));
+ m_via6522->ca2_handler().set(m_centronics, FUNC(centronics_device::write_strobe));
+ m_via6522->irq_handler().set(m_irqs, FUNC(input_merger_device::in_w<0>));
+
+ CENTRONICS(config, m_centronics, centronics_devices, "printer");
+ m_centronics->ack_handler().set(m_via6522, FUNC(via6522_device::write_ca1));
+ m_centronics->busy_handler().set(m_via6522, FUNC(via6522_device::write_pa7));
+ output_latch_device &cent_data_out(OUTPUT_LATCH(config, "cent_data_out"));
+ m_centronics->set_output_latch(cent_data_out);
+
+ I8255(config, m_ppi8255);
+
+ 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(m_irqs, FUNC(input_merger_device::in_w<1>));
+
+ 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));
+
+ MC14411(config, m_mc14411, 1.8432_MHz_XTAL);
+ m_mc14411->out_f<1>().set(FUNC(acorn_vib_device::write_acia_clock<mc14411_device::TIMER_F1>));
+ m_mc14411->out_f<2>().set(FUNC(acorn_vib_device::write_acia_clock<mc14411_device::TIMER_F2>));
+ m_mc14411->out_f<3>().set(FUNC(acorn_vib_device::write_acia_clock<mc14411_device::TIMER_F3>));
+ m_mc14411->out_f<4>().set(FUNC(acorn_vib_device::write_acia_clock<mc14411_device::TIMER_F4>));
+ m_mc14411->out_f<5>().set(FUNC(acorn_vib_device::write_acia_clock<mc14411_device::TIMER_F5>));
+ m_mc14411->out_f<6>().set(FUNC(acorn_vib_device::write_acia_clock<mc14411_device::TIMER_F6>));
+ m_mc14411->out_f<7>().set(FUNC(acorn_vib_device::write_acia_clock<mc14411_device::TIMER_F7>));
+ m_mc14411->out_f<8>().set(FUNC(acorn_vib_device::write_acia_clock<mc14411_device::TIMER_F8>));
+ m_mc14411->out_f<9>().set(FUNC(acorn_vib_device::write_acia_clock<mc14411_device::TIMER_F9>));
+ m_mc14411->out_f<10>().set(FUNC(acorn_vib_device::write_acia_clock<mc14411_device::TIMER_F10>));
+ m_mc14411->out_f<11>().set(FUNC(acorn_vib_device::write_acia_clock<mc14411_device::TIMER_F11>));
+ m_mc14411->out_f<12>().set(FUNC(acorn_vib_device::write_acia_clock<mc14411_device::TIMER_F12>));
+ m_mc14411->out_f<13>().set(FUNC(acorn_vib_device::write_acia_clock<mc14411_device::TIMER_F13>));
+ m_mc14411->out_f<14>().set(FUNC(acorn_vib_device::write_acia_clock<mc14411_device::TIMER_F14>));
+}
diff --git a/src/devices/bus/acorn/system/vib.h b/src/devices/bus/acorn/system/vib.h
index d4d710a3256..21d90f895d4 100644
--- a/src/devices/bus/acorn/system/vib.h
+++ b/src/devices/bus/acorn/system/vib.h
@@ -20,7 +20,7 @@
#include "machine/i8255.h"
#include "machine/6522via.h"
#include "machine/6850acia.h"
-#include "machine/clock.h"
+#include "machine/mc14411.h"
#include "machine/input_merger.h"
//**************************************************************************
@@ -37,23 +37,26 @@ public:
protected:
// device-level overrides
- virtual void device_start() override;
- virtual void device_reset() override;
+ virtual void device_start() override ATTR_COLD;
+ virtual void device_reset() override ATTR_COLD;
// optional information overrides
- virtual void device_add_mconfig(machine_config &config) override;
+ virtual ioport_constructor device_input_ports() const override ATTR_COLD;
+ virtual void device_add_mconfig(machine_config &config) override ATTR_COLD;
private:
- 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;
required_device<acia6850_device> m_acia;
- required_device<clock_device> m_acia_clock;
+ required_device<mc14411_device> m_mc14411;
required_device<centronics_device> m_centronics;
required_device<rs232_port_device> m_rs232;
required_device<input_merger_device> m_irqs;
+ required_ioport m_txc;
+ required_ioport m_rxc;
};
diff --git a/src/devices/bus/adam/adamlink.h b/src/devices/bus/adam/adamlink.h
index 6fb07f81c6f..5bacb5f6ee6 100644
--- a/src/devices/bus/adam/adamlink.h
+++ b/src/devices/bus/adam/adamlink.h
@@ -30,7 +30,7 @@ public:
protected:
// device-level overrides
- virtual void device_start() override;
+ virtual void device_start() override ATTR_COLD;
// device_adam_expansion_slot_card_interface overrides
virtual uint8_t adam_bd_r(offs_t offset, uint8_t data, int bmreq, int biorq, int aux_rom_cs, int cas1, int cas2) override;
diff --git a/src/devices/bus/adam/exp.cpp b/src/devices/bus/adam/exp.cpp
index 4555ed961eb..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>
+
//**************************************************************************
@@ -36,8 +38,7 @@ DEFINE_DEVICE_TYPE(ADAM_EXPANSION_SLOT, adam_expansion_slot_device, "adam_expans
//-------------------------------------------------
device_adam_expansion_slot_card_interface::device_adam_expansion_slot_card_interface(const machine_config &mconfig, device_t &device) :
- device_slot_card_interface(mconfig, device),
- m_rom(*this, "rom")
+ device_interface(device, "adamexp")
{
m_slot = dynamic_cast<adam_expansion_slot_device *>(device.owner());
}
@@ -54,8 +55,8 @@ device_adam_expansion_slot_card_interface::device_adam_expansion_slot_card_inter
adam_expansion_slot_device::adam_expansion_slot_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) :
device_t(mconfig, ADAM_EXPANSION_SLOT, tag, owner, clock),
- device_slot_interface(mconfig, *this),
- device_image_interface(mconfig, *this),
+ device_single_card_slot_interface<device_adam_expansion_slot_card_interface>(mconfig, *this),
+ device_cartrom_image_interface(mconfig, *this),
m_write_irq(*this), m_card(nullptr)
{
}
@@ -67,19 +68,7 @@ adam_expansion_slot_device::adam_expansion_slot_device(const machine_config &mco
void adam_expansion_slot_device::device_start()
{
- m_card = dynamic_cast<device_adam_expansion_slot_card_interface *>(get_card_device());
-
- // resolve callbacks
- m_write_irq.resolve_safe();
-}
-
-
-//-------------------------------------------------
-// device_reset - device-specific reset
-//-------------------------------------------------
-
-void adam_expansion_slot_device::device_reset()
-{
+ m_card = get_card_device();
}
@@ -87,17 +76,20 @@ void adam_expansion_slot_device::device_reset()
// 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
{
@@ -105,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 618bc3d365a..ae6b759fcf9 100644
--- a/src/devices/bus/adam/exp.h
+++ b/src/devices/bus/adam/exp.h
@@ -11,18 +11,10 @@
#pragma once
-#include "softlist_dev.h"
+#include "imagedev/cartrom.h"
//**************************************************************************
-// CONSTANTS
-//**************************************************************************
-
-#define ADAM_LEFT_EXPANSION_SLOT_TAG "slot1"
-#define ADAM_CENTER_EXPANSION_SLOT_TAG "slot2"
-#define ADAM_RIGHT_EXPANSION_SLOT_TAG "slot3"
-
-//**************************************************************************
// TYPE DEFINITIONS
//**************************************************************************
@@ -31,8 +23,8 @@
class device_adam_expansion_slot_card_interface;
class adam_expansion_slot_device : public device_t,
- public device_slot_interface,
- public device_image_interface
+ public device_single_card_slot_interface<device_adam_expansion_slot_card_interface>,
+ public device_cartrom_image_interface
{
public:
// construction/destruction
@@ -55,28 +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
- virtual void device_start() override;
- virtual void device_reset() override;
-
- // image-level overrides
- virtual image_init_result call_load() override;
- virtual const software_list_loader &get_software_list_loader() const override { return rom_software_list_loader::instance(); }
+ // device_t implementation
+ virtual void device_start() override ATTR_COLD;
- virtual iodevice_t image_type() const override { return IO_CARTSLOT; }
+ // device_image_interface implementation
+ virtual std::pair<std::error_condition, std::string> call_load() override;
- virtual bool is_readable() const override { return 1; }
- virtual bool is_writeable() const override { return 0; }
- virtual bool is_creatable() const override { return 0; }
- virtual bool must_be_loaded() const override { return 0; }
- virtual bool is_reset_on_load() const override { return 1; }
- virtual const char *image_interface() const override { return "adam_rom"; }
- virtual const char *file_extensions() const override { return "bin,rom"; }
+ 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;
@@ -87,7 +71,7 @@ protected:
// ======================> device_adam_expansion_slot_card_interface
-class device_adam_expansion_slot_card_interface : public device_slot_card_interface
+class device_adam_expansion_slot_card_interface : public device_interface
{
friend class adam_expansion_slot_device;
@@ -101,7 +85,7 @@ protected:
adam_expansion_slot_device *m_slot;
- optional_shared_ptr<uint8_t> m_rom;
+ std::unique_ptr<uint8_t[]> m_rom;
};
diff --git a/src/devices/bus/adam/ide.cpp b/src/devices/bus/adam/ide.cpp
index 98078003f4b..114e9eeb2e6 100644
--- a/src/devices/bus/adam/ide.cpp
+++ b/src/devices/bus/adam/ide.cpp
@@ -116,7 +116,7 @@ uint8_t powermate_ide_device::adam_bd_r(offs_t offset, uint8_t data, int bmreq,
case 0x05:
case 0x06:
case 0x07:
- data = m_ata->read_cs0(offset & 0x07, 0xff);
+ data = m_ata->cs0_r(offset & 0x07, 0xff);
break;
case 0x40: // Printer status
@@ -137,7 +137,7 @@ uint8_t powermate_ide_device::adam_bd_r(offs_t offset, uint8_t data, int bmreq,
break;
case 0x58:
- m_ata_data = m_ata->read_cs0(0);
+ m_ata_data = m_ata->cs0_r(0);
data = m_ata_data & 0xff;
break;
@@ -147,7 +147,7 @@ uint8_t powermate_ide_device::adam_bd_r(offs_t offset, uint8_t data, int bmreq,
break;
case 0x5a:
- data = m_ata->read_cs1(6, 0xff);
+ data = m_ata->cs1_r(6, 0xff);
break;
case 0x5b: // Digital Input Register
@@ -176,7 +176,7 @@ void powermate_ide_device::adam_bd_w(offs_t offset, uint8_t data, int bmreq, int
case 0x05:
case 0x06:
case 0x07:
- m_ata->write_cs0(offset & 0x07, data, 0xff);
+ m_ata->cs0_w(offset & 0x07, data, 0xff);
break;
case 0x40:
@@ -188,7 +188,7 @@ void powermate_ide_device::adam_bd_w(offs_t offset, uint8_t data, int bmreq, int
case 0x58:
m_ata_data |= data;
- m_ata->write_cs0(0, m_ata_data);
+ m_ata->cs0_w(0, m_ata_data);
break;
case 0x59:
diff --git a/src/devices/bus/adam/ide.h b/src/devices/bus/adam/ide.h
index bfce0f9851f..7d2527de31c 100644
--- a/src/devices/bus/adam/ide.h
+++ b/src/devices/bus/adam/ide.h
@@ -12,7 +12,7 @@
#pragma once
#include "exp.h"
-#include "machine/ataintf.h"
+#include "bus/ata/ataintf.h"
#include "machine/output_latch.h"
@@ -32,11 +32,11 @@ public:
protected:
// device-level overrides
- virtual void device_start() override;
+ virtual void device_start() override ATTR_COLD;
// optional information overrides
- virtual const tiny_rom_entry *device_rom_region() const override;
- virtual void device_add_mconfig(machine_config &config) override;
+ virtual const tiny_rom_entry *device_rom_region() const override ATTR_COLD;
+ virtual void device_add_mconfig(machine_config &config) override ATTR_COLD;
// device_adam_expansion_slot_card_interface overrides
virtual uint8_t adam_bd_r(offs_t offset, uint8_t data, int bmreq, int biorq, int aux_rom_cs, int cas1, int cas2) override;
diff --git a/src/devices/bus/adam/ram.cpp b/src/devices/bus/adam/ram.cpp
index a7e79719867..65dc13f2246 100644
--- a/src/devices/bus/adam/ram.cpp
+++ b/src/devices/bus/adam/ram.cpp
@@ -30,7 +30,7 @@ DEFINE_DEVICE_TYPE(ADAM_RAM, adam_ram_expansion_device, "adam_ram", "Adam 64KB R
adam_ram_expansion_device::adam_ram_expansion_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) :
device_t(mconfig, ADAM_RAM, tag, owner, clock),
device_adam_expansion_slot_card_interface(mconfig, *this),
- m_ram(*this, "ram")
+ m_ram(*this, "ram", 0x10000, ENDIANNESS_LITTLE)
{
}
@@ -41,7 +41,6 @@ adam_ram_expansion_device::adam_ram_expansion_device(const machine_config &mconf
void adam_ram_expansion_device::device_start()
{
- m_ram.allocate(0x10000);
}
diff --git a/src/devices/bus/adam/ram.h b/src/devices/bus/adam/ram.h
index 780d51be726..e61d5670a75 100644
--- a/src/devices/bus/adam/ram.h
+++ b/src/devices/bus/adam/ram.h
@@ -30,14 +30,14 @@ public:
protected:
// device-level overrides
- virtual void device_start() override;
+ virtual void device_start() override ATTR_COLD;
// device_adam_expansion_slot_card_interface overrides
virtual uint8_t adam_bd_r(offs_t offset, uint8_t data, int bmreq, int biorq, int aux_rom_cs, int cas1, int cas2) override;
virtual void adam_bd_w(offs_t offset, uint8_t data, int bmreq, int biorq, int aux_rom_cs, int cas1, int cas2) override;
private:
- optional_shared_ptr<uint8_t> m_ram;
+ memory_share_creator<uint8_t> m_ram;
};
diff --git a/src/devices/bus/adamnet/adamnet.cpp b/src/devices/bus/adamnet/adamnet.cpp
index 7e45a72adca..c2886c61248 100644
--- a/src/devices/bus/adamnet/adamnet.cpp
+++ b/src/devices/bus/adamnet/adamnet.cpp
@@ -28,8 +28,8 @@ DEFINE_DEVICE_TYPE(ADAMNET_SLOT, adamnet_slot_device, "adamnet_slot", "ADAMnet s
// device_adamnet_card_interface - constructor
//-------------------------------------------------
-device_adamnet_card_interface::device_adamnet_card_interface(const machine_config &mconfig, device_t &device)
- : device_slot_card_interface(mconfig, device),
+device_adamnet_card_interface::device_adamnet_card_interface(const machine_config &mconfig, device_t &device) :
+ device_interface(device, "adamnet"),
m_bus(nullptr)
{
}
@@ -54,7 +54,8 @@ device_adamnet_card_interface::~device_adamnet_card_interface()
//-------------------------------------------------
adamnet_slot_device::adamnet_slot_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) :
device_t(mconfig, ADAMNET_SLOT, tag, owner, clock),
- device_slot_interface(mconfig, *this), m_bus(nullptr)
+ device_single_card_slot_interface<device_adamnet_card_interface>(mconfig, *this),
+ m_bus(*this, finder_base::DUMMY_TAG)
{
}
@@ -65,9 +66,8 @@ adamnet_slot_device::adamnet_slot_device(const machine_config &mconfig, const ch
void adamnet_slot_device::device_start()
{
- m_bus = machine().device<adamnet_device>(ADAMNET_TAG);
- device_adamnet_card_interface *dev = dynamic_cast<device_adamnet_card_interface *>(get_card_device());
- if (dev) m_bus->add_device(get_card_device());
+ device_adamnet_card_interface *dev = get_card_device();
+ if (dev) m_bus->add_device(&dev->device());
}
@@ -113,7 +113,7 @@ void adamnet_device::device_stop()
void adamnet_device::add_device(device_t *target)
{
- auto entry = global_alloc(daisy_entry(target));
+ auto entry = new daisy_entry(target);
entry->m_interface->m_bus = this;
@@ -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 51fc46a38dd..a7410e7185f 100644
--- a/src/devices/bus/adamnet/adamnet.h
+++ b/src/devices/bus/adamnet/adamnet.h
@@ -15,13 +15,6 @@
//**************************************************************************
-// CONSTANTS
-//**************************************************************************
-
-#define ADAMNET_TAG "adamnet"
-
-
-//**************************************************************************
// TYPE DEFINITIONS
//**************************************************************************
@@ -37,18 +30,18 @@ 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
- virtual void device_start() override;
- virtual void device_stop() override;
+ virtual void device_start() override ATTR_COLD;
+ virtual void device_stop() override ATTR_COLD;
private:
class daisy_entry
@@ -74,14 +67,18 @@ private:
// ======================> adamnet_slot_device
class adamnet_slot_device : public device_t,
- public device_slot_interface
+ public device_single_card_slot_interface<device_adamnet_card_interface>
{
public:
+ // configuration
+ template <typename T> void set_bus(T &&tag) { m_bus.set_tag(std::forward<T>(tag)); }
+
// construction/destruction
- template <typename T>
- adamnet_slot_device(machine_config const &mconfig, char const *tag, device_t *owner, T &&opts, char const *dflt)
+ template <typename T, typename U>
+ adamnet_slot_device(machine_config const &mconfig, char const *tag, device_t *owner, T &&bus, U &&opts, char const *dflt)
: adamnet_slot_device(mconfig, tag, owner, (uint32_t)0)
{
+ set_bus(std::forward<T>(bus));
option_reset();
opts(*this);
set_default_option(dflt);
@@ -89,18 +86,18 @@ public:
}
adamnet_slot_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_start() override ATTR_COLD;
-protected:
// configuration
- adamnet_device *m_bus;
+ required_device<adamnet_device> m_bus;
};
// ======================> device_adamnet_card_interface
-class device_adamnet_card_interface : public device_slot_card_interface
+class device_adamnet_card_interface : public device_interface
{
friend class adamnet_device;
diff --git a/src/devices/bus/adamnet/ddp.cpp b/src/devices/bus/adamnet/ddp.cpp
index ede3719c910..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,13 +54,10 @@ 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).rw(M6801_TAG, FUNC(m6801_cpu_device::m6801_io_r), FUNC(m6801_cpu_device::m6801_io_w));
- map(0x0080, 0x00ff).ram();
map(0x0400, 0x07ff).ram();
- map(0xf800, 0xffff).rom().region(M6801_TAG, 0);
}
-static const struct CassetteOptions adam_cassette_options =
+static const cassette_image::Options adam_cassette_options =
{
2, /* channels */
16, /* bits per sample */
@@ -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));
}
@@ -140,7 +135,7 @@ void adam_digital_data_pack_device::adamnet_reset_w(int state)
// p1_w -
//-------------------------------------------------
-WRITE8_MEMBER( adam_digital_data_pack_device::p1_w )
+void adam_digital_data_pack_device::p1_w(uint8_t data)
{
/*
@@ -157,27 +152,21 @@ WRITE8_MEMBER( adam_digital_data_pack_device::p1_w )
*/
- 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);
}
@@ -185,7 +174,7 @@ WRITE8_MEMBER( adam_digital_data_pack_device::p1_w )
// p2_r -
//-------------------------------------------------
-READ8_MEMBER( adam_digital_data_pack_device::p2_r )
+uint8_t adam_digital_data_pack_device::p2_r()
{
/*
@@ -204,7 +193,7 @@ READ8_MEMBER( 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;
@@ -217,7 +206,7 @@ READ8_MEMBER( adam_digital_data_pack_device::p2_r )
// p2_w -
//-------------------------------------------------
-WRITE8_MEMBER( adam_digital_data_pack_device::p2_w )
+void adam_digital_data_pack_device::p2_w(uint8_t data)
{
/*
@@ -231,16 +220,14 @@ WRITE8_MEMBER( adam_digital_data_pack_device::p2_w )
*/
- 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
@@ -252,7 +239,7 @@ WRITE8_MEMBER( adam_digital_data_pack_device::p2_w )
// p4_r -
//-------------------------------------------------
-READ8_MEMBER( adam_digital_data_pack_device::p4_r )
+uint8_t adam_digital_data_pack_device::p4_r()
{
/*
@@ -271,19 +258,15 @@ READ8_MEMBER( 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 0232fad9d06..f7e3466de62 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"
@@ -33,30 +32,28 @@ public:
protected:
// device-level overrides
- virtual void device_start() override;
+ virtual void device_start() override ATTR_COLD;
// optional information overrides
- virtual const tiny_rom_entry *device_rom_region() const override;
- virtual void device_add_mconfig(machine_config &config) override;
+ virtual const tiny_rom_entry *device_rom_region() const override ATTR_COLD;
+ virtual void device_add_mconfig(machine_config &config) override ATTR_COLD;
// device_adamnet_card_interface overrides
virtual void adamnet_reset_w(int state) override;
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;
- DECLARE_WRITE8_MEMBER( p1_w );
- DECLARE_READ8_MEMBER( p2_r );
- DECLARE_WRITE8_MEMBER( p2_w );
- DECLARE_READ8_MEMBER( p4_r );
+ void p1_w(uint8_t data);
+ uint8_t p2_r();
+ void p2_w(uint8_t data);
+ uint8_t p4_r();
- void adam_ddp_mem(address_map &map);
+ void adam_ddp_mem(address_map &map) ATTR_COLD;
};
diff --git a/src/devices/bus/adamnet/fdc.cpp b/src/devices/bus/adamnet/fdc.cpp
index e1c94c705a5..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).rw(M6801_TAG, FUNC(m6801_cpu_device::m6801_io_r), FUNC(m6801_cpu_device::m6801_io_w));
- 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");
@@ -97,12 +97,14 @@ void adam_fdc_device::adam_fdc_mem(address_map &map)
//-------------------------------------------------
-// floppy_format_type floppy_formats
+// floppy_formats
//-------------------------------------------------
-FLOPPY_FORMATS_MEMBER( adam_fdc_device::floppy_formats )
- FLOPPY_ADAM_FORMAT
-FLOPPY_FORMATS_END
+void adam_fdc_device::floppy_formats(format_registration &fr)
+{
+ fr.add_mfm_containers();
+ fr.add(FLOPPY_ADAM_FORMAT);
+}
static void adam_fdc_floppies(device_slot_interface &device)
{
@@ -116,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));
@@ -199,7 +201,7 @@ void adam_fdc_device::adamnet_reset_w(int state)
// data_r -
//-------------------------------------------------
-READ8_MEMBER( adam_fdc_device::data_r )
+uint8_t adam_fdc_device::data_r(offs_t offset)
{
uint8_t data = m_fdc->data_r();
@@ -213,7 +215,7 @@ READ8_MEMBER( adam_fdc_device::data_r )
// p1_r -
//-------------------------------------------------
-READ8_MEMBER( adam_fdc_device::p1_r )
+uint8_t adam_fdc_device::p1_r()
{
/*
@@ -250,7 +252,7 @@ READ8_MEMBER( adam_fdc_device::p1_r )
// p1_w -
//-------------------------------------------------
-WRITE8_MEMBER( adam_fdc_device::p1_w )
+void adam_fdc_device::p1_w(uint8_t data)
{
/*
@@ -292,7 +294,7 @@ WRITE8_MEMBER( adam_fdc_device::p1_w )
// p2_r -
//-------------------------------------------------
-READ8_MEMBER( adam_fdc_device::p2_r )
+uint8_t adam_fdc_device::p2_r()
{
/*
@@ -319,7 +321,7 @@ READ8_MEMBER( adam_fdc_device::p2_r )
// p2_w -
//-------------------------------------------------
-WRITE8_MEMBER( adam_fdc_device::p2_w )
+void adam_fdc_device::p2_w(uint8_t data)
{
/*
diff --git a/src/devices/bus/adamnet/fdc.h b/src/devices/bus/adamnet/fdc.h
index 2ed2eb24ccb..3132db46ba6 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"
@@ -34,12 +33,12 @@ public:
protected:
// device-level overrides
- virtual void device_start() override;
+ virtual void device_start() override ATTR_COLD;
// optional information 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 const tiny_rom_entry *device_rom_region() const override ATTR_COLD;
+ virtual void device_add_mconfig(machine_config &config) override ATTR_COLD;
+ virtual ioport_constructor device_input_ports() const override ATTR_COLD;
// device_adamnet_card_interface overrides
virtual void adamnet_reset_w(int state) override;
@@ -52,15 +51,15 @@ private:
required_shared_ptr<uint8_t> m_ram;
required_ioport m_sw3;
- DECLARE_FLOPPY_FORMATS( floppy_formats );
+ static void floppy_formats(format_registration &fr);
- DECLARE_READ8_MEMBER( data_r );
- DECLARE_READ8_MEMBER( p1_r );
- DECLARE_WRITE8_MEMBER( p1_w );
- DECLARE_READ8_MEMBER( p2_r );
- DECLARE_WRITE8_MEMBER( p2_w );
+ uint8_t data_r(offs_t offset);
+ uint8_t p1_r();
+ void p1_w(uint8_t data);
+ uint8_t p2_r();
+ void p2_w(uint8_t data);
- void adam_fdc_mem(address_map &map);
+ void adam_fdc_mem(address_map &map) ATTR_COLD;
};
diff --git a/src/devices/bus/adamnet/kb.cpp b/src/devices/bus/adamnet/kb.cpp
index ea17493f5a9..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).rw(M6801_TAG, FUNC(m6801_cpu_device::m6801_io_r), FUNC(m6801_cpu_device::m6801_io_w));
- 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));
@@ -134,7 +121,7 @@ static INPUT_PORTS_START( adam_kb )
PORT_START("Y5")
PORT_BIT( 0x01, IP_ACTIVE_LOW, IPT_KEYBOARD ) PORT_CODE(KEYCODE_9) PORT_CHAR('9') PORT_CHAR('(')
PORT_BIT( 0x02, IP_ACTIVE_LOW, IPT_KEYBOARD ) PORT_CODE(KEYCODE_0) PORT_CHAR('0') PORT_CHAR(')')
- PORT_BIT( 0x04, IP_ACTIVE_LOW, IPT_KEYBOARD ) PORT_CODE(KEYCODE_MINUS) PORT_CHAR('-') PORT_CHAR('\'')
+ PORT_BIT( 0x04, IP_ACTIVE_LOW, IPT_KEYBOARD ) PORT_CODE(KEYCODE_MINUS) 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_TILDE) PORT_CHAR('^') PORT_CHAR('~')
PORT_BIT( 0x20, IP_ACTIVE_LOW, IPT_KEYBOARD ) PORT_CODE(KEYCODE_L) PORT_CHAR('l') PORT_CHAR('L')
@@ -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))
@@ -243,7 +230,7 @@ void adam_keyboard_device::adamnet_reset_w(int state)
// p1_r -
//-------------------------------------------------
-READ8_MEMBER( adam_keyboard_device::p1_r )
+uint8_t adam_keyboard_device::p1_r()
{
/*
@@ -275,7 +262,7 @@ READ8_MEMBER( adam_keyboard_device::p1_r )
// p2_r -
//-------------------------------------------------
-READ8_MEMBER( adam_keyboard_device::p2_r )
+uint8_t adam_keyboard_device::p2_r()
{
/*
@@ -302,7 +289,7 @@ READ8_MEMBER( adam_keyboard_device::p2_r )
// p2_w -
//-------------------------------------------------
-WRITE8_MEMBER( adam_keyboard_device::p2_w )
+void adam_keyboard_device::p2_w(uint8_t data)
{
/*
@@ -324,7 +311,7 @@ WRITE8_MEMBER( adam_keyboard_device::p2_w )
// p3_r -
//-------------------------------------------------
-READ8_MEMBER( adam_keyboard_device::p3_r )
+uint8_t adam_keyboard_device::p3_r()
{
return 0xff;
}
@@ -334,7 +321,7 @@ READ8_MEMBER( adam_keyboard_device::p3_r )
// p3_w -
//-------------------------------------------------
-WRITE8_MEMBER( adam_keyboard_device::p3_w )
+void adam_keyboard_device::p3_w(uint8_t data)
{
/*
@@ -359,7 +346,7 @@ WRITE8_MEMBER( adam_keyboard_device::p3_w )
// p4_r -
//-------------------------------------------------
-READ8_MEMBER( adam_keyboard_device::p4_r )
+uint8_t adam_keyboard_device::p4_r()
{
return 0xff;
}
@@ -369,7 +356,7 @@ READ8_MEMBER( adam_keyboard_device::p4_r )
// p4_w -
//-------------------------------------------------
-WRITE8_MEMBER( adam_keyboard_device::p4_w )
+void adam_keyboard_device::p4_w(uint8_t data)
{
/*
diff --git a/src/devices/bus/adamnet/kb.h b/src/devices/bus/adamnet/kb.h
index 2af2834e7e8..1be0dc4b585 100644
--- a/src/devices/bus/adamnet/kb.h
+++ b/src/devices/bus/adamnet/kb.h
@@ -31,12 +31,12 @@ public:
protected:
// device-level overrides
- virtual void device_start() override;
+ virtual void device_start() override ATTR_COLD;
// optional information 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 const tiny_rom_entry *device_rom_region() const override ATTR_COLD;
+ virtual void device_add_mconfig(machine_config &config) override ATTR_COLD;
+ virtual ioport_constructor device_input_ports() const override ATTR_COLD;
// device_adamnet_card_interface overrides
virtual void adamnet_reset_w(int state) override;
@@ -47,15 +47,13 @@ private:
uint16_t m_key_y;
- DECLARE_READ8_MEMBER( p1_r );
- DECLARE_READ8_MEMBER( p2_r );
- DECLARE_WRITE8_MEMBER( p2_w );
- DECLARE_READ8_MEMBER( p3_r );
- DECLARE_WRITE8_MEMBER( p3_w );
- DECLARE_READ8_MEMBER( p4_r );
- DECLARE_WRITE8_MEMBER( p4_w );
-
- void adam_kb_mem(address_map &map);
+ uint8_t p1_r();
+ uint8_t p2_r();
+ void p2_w(uint8_t data);
+ uint8_t p3_r();
+ void p3_w(uint8_t data);
+ uint8_t p4_r();
+ void p4_w(uint8_t data);
};
diff --git a/src/devices/bus/adamnet/printer.cpp b/src/devices/bus/adamnet/printer.cpp
index 637ce3a86e6..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).rw(M6801_TAG, FUNC(m6801_cpu_device::m6801_io_r), FUNC(m6801_cpu_device::m6801_io_w));
- 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
}
@@ -116,7 +102,7 @@ void adam_printer_device::adamnet_reset_w(int state)
// p1_w -
//-------------------------------------------------
-WRITE8_MEMBER( adam_printer_device::p1_w )
+void adam_printer_device::p1_w(uint8_t data)
{
/*
@@ -139,7 +125,7 @@ WRITE8_MEMBER( adam_printer_device::p1_w )
// p2_r -
//-------------------------------------------------
-READ8_MEMBER( adam_printer_device::p2_r )
+uint8_t adam_printer_device::p2_r()
{
/*
@@ -166,7 +152,7 @@ READ8_MEMBER( adam_printer_device::p2_r )
// p2_w -
//-------------------------------------------------
-WRITE8_MEMBER( adam_printer_device::p2_w )
+void adam_printer_device::p2_w(uint8_t data)
{
/*
@@ -188,7 +174,7 @@ WRITE8_MEMBER( adam_printer_device::p2_w )
// p3_r -
//-------------------------------------------------
-READ8_MEMBER( adam_printer_device::p3_r )
+uint8_t adam_printer_device::p3_r()
{
return 0xff;
}
@@ -198,7 +184,7 @@ READ8_MEMBER( adam_printer_device::p3_r )
// p4_r -
//-------------------------------------------------
-READ8_MEMBER( adam_printer_device::p4_r )
+uint8_t adam_printer_device::p4_r()
{
/*
@@ -223,7 +209,7 @@ READ8_MEMBER( adam_printer_device::p4_r )
// p4_w -
//-------------------------------------------------
-WRITE8_MEMBER( adam_printer_device::p4_w )
+void adam_printer_device::p4_w(uint8_t data)
{
/*
diff --git a/src/devices/bus/adamnet/printer.h b/src/devices/bus/adamnet/printer.h
index bbb2617405e..5a7f571eda6 100644
--- a/src/devices/bus/adamnet/printer.h
+++ b/src/devices/bus/adamnet/printer.h
@@ -31,11 +31,11 @@ public:
protected:
// device-level overrides
- virtual void device_start() override;
+ virtual void device_start() override ATTR_COLD;
// optional information overrides
- virtual const tiny_rom_entry *device_rom_region() const override;
- virtual void device_add_mconfig(machine_config &config) override;
+ virtual const tiny_rom_entry *device_rom_region() const override ATTR_COLD;
+ virtual void device_add_mconfig(machine_config &config) override ATTR_COLD;
// device_adamnet_card_interface overrides
virtual void adamnet_reset_w(int state) override;
@@ -43,14 +43,12 @@ protected:
private:
required_device<m6801_cpu_device> m_maincpu;
- DECLARE_WRITE8_MEMBER( p1_w );
- DECLARE_READ8_MEMBER( p2_r );
- DECLARE_WRITE8_MEMBER( p2_w );
- DECLARE_READ8_MEMBER( p3_r );
- DECLARE_READ8_MEMBER( p4_r );
- DECLARE_WRITE8_MEMBER( p4_w );
-
- void adam_prn_mem(address_map &map);
+ void p1_w(uint8_t data);
+ uint8_t p2_r();
+ void p2_w(uint8_t data);
+ uint8_t p3_r();
+ uint8_t p4_r();
+ void p4_w(uint8_t data);
};
diff --git a/src/devices/bus/adamnet/spi.cpp b/src/devices/bus/adamnet/spi.cpp
index 6ad84bbed7c..34cbcb7f5ab 100644
--- a/src/devices/bus/adamnet/spi.cpp
+++ b/src/devices/bus/adamnet/spi.cpp
@@ -12,16 +12,6 @@
//**************************************************************************
-// MACROS / CONSTANTS
-//**************************************************************************
-
-#define M6801_TAG "m6801"
-#define MC2661_TAG "mc2661"
-#define RS232_TAG "rs232"
-
-
-
-//**************************************************************************
// DEVICE DEFINITIONS
//**************************************************************************
@@ -33,7 +23,7 @@ DEFINE_DEVICE_TYPE(ADAM_SPI, adam_spi_device, "adam_spi", "Adam SPI")
//-------------------------------------------------
ROM_START( adam_spi )
- ROM_REGION( 0x800, M6801_TAG, 0 )
+ ROM_REGION( 0x800, "m6801", 0 )
ROM_LOAD( "spi.bin", 0x000, 0x800, CRC(4ba30352) SHA1(99fe5aebd505a208bea6beec5d7322b15426e9c1) )
ROM_END
@@ -54,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).rw(M6801_TAG, FUNC(m6801_cpu_device::m6801_io_r), FUNC(m6801_cpu_device::m6801_io_w));
- map(0x0080, 0x00ff).ram();
- map(0xf800, 0xffff).rom().region(M6801_TAG, 0);
+ map(0x0100, 0x0103).rw("epci", FUNC(scn2661a_device::read), FUNC(scn2661a_device::write));
+ map(0x0104, 0x01ff).ram();
}
@@ -70,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();
- MC2661(config, MC2661_TAG, 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_TAG, 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");
@@ -96,7 +91,7 @@ void adam_spi_device::device_add_mconfig(machine_config &config)
adam_spi_device::adam_spi_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
: device_t(mconfig, ADAM_SPI, tag, owner, clock)
, device_adamnet_card_interface(mconfig, *this)
- , m_maincpu(*this, M6801_TAG)
+ , m_maincpu(*this, "m6801")
{
}
@@ -124,7 +119,7 @@ void adam_spi_device::adamnet_reset_w(int state)
// p2_r -
//-------------------------------------------------
-READ8_MEMBER( adam_spi_device::p2_r )
+uint8_t adam_spi_device::p2_r()
{
/*
@@ -151,7 +146,7 @@ READ8_MEMBER( adam_spi_device::p2_r )
// p2_w -
//-------------------------------------------------
-WRITE8_MEMBER( adam_spi_device::p2_w )
+void adam_spi_device::p2_w(uint8_t data)
{
/*
diff --git a/src/devices/bus/adamnet/spi.h b/src/devices/bus/adamnet/spi.h
index 8dc75265c6b..55b158c2e9d 100644
--- a/src/devices/bus/adamnet/spi.h
+++ b/src/devices/bus/adamnet/spi.h
@@ -15,7 +15,7 @@
#include "bus/centronics/ctronics.h"
#include "bus/rs232/rs232.h"
#include "cpu/m6800/m6801.h"
-#include "machine/mc2661.h"
+#include "machine/scn_pci.h"
@@ -34,11 +34,11 @@ public:
protected:
// device-level overrides
- virtual void device_start() override;
+ virtual void device_start() override ATTR_COLD;
// optional information overrides
- virtual const tiny_rom_entry *device_rom_region() const override;
- virtual void device_add_mconfig(machine_config &config) override;
+ virtual const tiny_rom_entry *device_rom_region() const override ATTR_COLD;
+ virtual void device_add_mconfig(machine_config &config) override ATTR_COLD;
// device_adamnet_card_interface overrides
virtual void adamnet_reset_w(int state) override;
@@ -46,10 +46,10 @@ protected:
private:
required_device<m6801_cpu_device> m_maincpu;
- DECLARE_READ8_MEMBER( p2_r );
- DECLARE_WRITE8_MEMBER( p2_w );
+ uint8_t p2_r();
+ void p2_w(uint8_t data);
- void adam_spi_mem(address_map &map);
+ void adam_spi_mem(address_map &map) ATTR_COLD;
};
diff --git a/src/devices/bus/adb/a9m0330.cpp b/src/devices/bus/adb/a9m0330.cpp
new file mode 100644
index 00000000000..e4e96d45a90
--- /dev/null
+++ b/src/devices/bus/adb/a9m0330.cpp
@@ -0,0 +1,268 @@
+// license:BSD-3-Clause
+// copyright-holders: R. Belmont
+/*********************************************************************
+
+ a9m0330.cpp
+ Apple model A9M0330 ADB keyboard for the Apple IIgs
+ by R. Belmont, with hints from pluskbd.cpp by Vas Crabb
+
+ Port 1: Row selects 0-7
+ Port 2: Bit 0: row select bit 8
+ Bit 1: row select bit 9
+ Bit 2: Shift
+ Bit 3: Caps Lock
+ Bit 4: Option
+ Bit 5: Command
+ Bit 6: Reset/Power? Control?
+ Bit 7: ADB out
+ Bus: Matrix read input
+ T1: ADB in
+
+*********************************************************************/
+
+#include "emu.h"
+#include "a9m0330.h"
+
+DEFINE_DEVICE_TYPE(ADB_A9M0330, a9m0330_device, "a9m0330", "Apple IIgs ADB Keyboard (A9M0330)");
+
+ROM_START(a9m0330)
+ ROM_REGION(0x400, "mcu", 0)
+ // from early-production ROM 00 Woz Limited Edition IIgs. keyboard "Part Number 658-4081 825-1301-A"
+ // ROM is marked "NEC Japan 8626XD 341-0232A 543" so 26th week of 1986
+ ROM_LOAD("341-0232a.bin", 0x000000, 0x000400, CRC(6a158b9f) SHA1(e8744180075182849d431fd8023a52a062a6da76))
+ // from later non-Woz ROM 01. keyboard "Model A9M0330"
+ // ROM is marked "NEC Japan 8806HD 8048HC610 341-0124-A (c) APPLE 87" so 6th week of 1988
+ ROM_LOAD("341-0124a.bin", 0x000000, 0x000400, CRC(2a3576bf) SHA1(58fbf770d3801a02d0944039829f9241b5279013))
+ROM_END
+
+// matrix is believed to be the same as the Mac Plus keyboard at the moment
+static INPUT_PORTS_START(a9m0330)
+ PORT_START("ROW0")
+ PORT_BIT(0x01, IP_ACTIVE_LOW, IPT_UNUSED)
+ PORT_BIT(0x02, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_ASTERISK) PORT_CHAR(UCHAR_MAMEKEY(ASTERISK)) PORT_NAME("Keypad *")
+ PORT_BIT(0x04, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_8_PAD) PORT_CHAR(UCHAR_MAMEKEY(8_PAD)) PORT_NAME("Keypad 8")
+ 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_D) PORT_CHAR('d') PORT_CHAR('D')
+ PORT_BIT(0x20, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_W) PORT_CHAR('w') PORT_CHAR('W')
+ PORT_BIT(0x40, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_2) PORT_CHAR('2') PORT_CHAR('@')
+ PORT_BIT(0x80, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_V) PORT_CHAR('v') PORT_CHAR('V')
+
+ PORT_START("ROW1")
+ 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_CODE(KEYCODE_SLASH_PAD) PORT_CHAR(UCHAR_MAMEKEY(SLASH_PAD)) PORT_NAME("Keypad /")
+ PORT_BIT(0x04, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_9_PAD) PORT_CHAR(UCHAR_MAMEKEY(9_PAD)) PORT_NAME("Keypad 9")
+ PORT_BIT(0x08, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_OPENBRACE) PORT_CHAR('[') PORT_CHAR('{')
+ PORT_BIT(0x10, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_F) PORT_CHAR('f') PORT_CHAR('F')
+ PORT_BIT(0x20, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_E) PORT_CHAR('e') PORT_CHAR('E')
+ PORT_BIT(0x40, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_3) PORT_CHAR('3') PORT_CHAR('#')
+ PORT_BIT(0x80, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_B) PORT_CHAR('b') PORT_CHAR('B')
+
+ PORT_START("ROW2")
+ PORT_BIT(0x01, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_LEFT) PORT_CHAR(UCHAR_MAMEKEY(LEFT))
+ PORT_BIT(0x02, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_EQUALS_PAD) PORT_CHAR(UCHAR_MAMEKEY(EQUALS_PAD)) PORT_NAME("Keypad =")
+ PORT_BIT(0x04, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_MINUS_PAD) PORT_CHAR(UCHAR_MAMEKEY(MINUS_PAD)) PORT_NAME("Keypad -")
+ PORT_BIT(0x08, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_CLOSEBRACE) PORT_CHAR(']') PORT_CHAR('}')
+ PORT_BIT(0x10, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_G) PORT_CHAR('g') PORT_CHAR('G')
+ PORT_BIT(0x20, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_R) PORT_CHAR('r') PORT_CHAR('R')
+ PORT_BIT(0x40, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_4) PORT_CHAR('4') PORT_CHAR('$')
+ PORT_BIT(0x80, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_N) PORT_CHAR('n') PORT_CHAR('N')
+
+ PORT_START("ROW3")
+ PORT_BIT(0x01, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_RIGHT) PORT_CHAR(UCHAR_MAMEKEY(RIGHT))
+ PORT_BIT(0x02, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_NUMLOCK) PORT_CHAR(UCHAR_MAMEKEY(NUMLOCK)) PORT_NAME("Keypad Clear")
+ PORT_BIT(0x04, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_UP) PORT_CHAR(UCHAR_MAMEKEY(UP))
+ PORT_BIT(0x08, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_QUOTE) PORT_CHAR('\'') PORT_CHAR('"')
+ PORT_BIT(0x10, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_H) PORT_CHAR('h') PORT_CHAR('H')
+ PORT_BIT(0x20, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_T) PORT_CHAR('t') PORT_CHAR('T')
+ PORT_BIT(0x40, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_5) PORT_CHAR('5') PORT_CHAR('%')
+ PORT_BIT(0x80, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_M) PORT_CHAR('m') PORT_CHAR('M')
+
+ PORT_START("ROW4")
+ PORT_BIT(0x01, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_DOWN) PORT_CHAR(UCHAR_MAMEKEY(DOWN))
+ PORT_BIT(0x02, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_BACKSPACE) PORT_CHAR(0x08) PORT_NAME("Backspace")
+ PORT_BIT(0x04, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_1_PAD) PORT_CHAR(UCHAR_MAMEKEY(1_PAD)) PORT_NAME("Keypad 1")
+ PORT_BIT(0x08, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_ENTER) PORT_CHAR(0x0d) PORT_NAME("Return")
+ PORT_BIT(0x10, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_J) PORT_CHAR('j') PORT_CHAR('J')
+ PORT_BIT(0x20, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_Y) PORT_CHAR('y') PORT_CHAR('Y')
+ PORT_BIT(0x40, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_6) PORT_CHAR('6') PORT_CHAR('^')
+ PORT_BIT(0x80, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_COMMA) PORT_CHAR(',') PORT_CHAR('<')
+
+ PORT_START("ROW5")
+ PORT_BIT(0x01, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_0_PAD) PORT_CHAR(UCHAR_MAMEKEY(0_PAD)) PORT_NAME("Keypad 0")
+ PORT_BIT(0x02, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_EQUALS) PORT_CHAR('=') PORT_CHAR('+')
+ PORT_BIT(0x04, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_2_PAD) PORT_CHAR(UCHAR_MAMEKEY(2_PAD)) PORT_NAME("Keypad 2")
+ PORT_BIT(0x08, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_4_PAD) PORT_CHAR(UCHAR_MAMEKEY(4_PAD)) PORT_NAME("Keypad 4")
+ PORT_BIT(0x10, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_K) PORT_CHAR('k') PORT_CHAR('K')
+ PORT_BIT(0x20, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_U) PORT_CHAR('u') PORT_CHAR('U')
+ PORT_BIT(0x40, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_7) PORT_CHAR('7') PORT_CHAR('&')
+ PORT_BIT(0x80, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_STOP) PORT_CHAR('.') PORT_CHAR('>')
+
+ PORT_START("ROW6")
+ PORT_BIT(0x01, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_DEL_PAD) PORT_CHAR(UCHAR_MAMEKEY(DEL_PAD)) PORT_NAME("Keypad .")
+ 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_3_PAD) PORT_CHAR(UCHAR_MAMEKEY(3_PAD)) PORT_NAME("Keypad 3")
+ PORT_BIT(0x08, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_5_PAD) PORT_CHAR(UCHAR_MAMEKEY(5_PAD)) PORT_NAME("Keypad 5")
+ 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_I) PORT_CHAR('i') PORT_CHAR('I')
+ PORT_BIT(0x40, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_8) PORT_CHAR('8') PORT_CHAR('*')
+ PORT_BIT(0x80, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_SLASH) PORT_CHAR('/') PORT_CHAR('?')
+
+ PORT_START("ROW7")
+ PORT_BIT(0x01, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_ENTER_PAD) PORT_CHAR(UCHAR_MAMEKEY(ENTER_PAD)) PORT_NAME("Keypad Enter")
+ PORT_BIT(0x02, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_0) PORT_CHAR('0') PORT_CHAR(')')
+ PORT_BIT(0x04, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_PLUS_PAD) PORT_CHAR(UCHAR_MAMEKEY(PLUS_PAD)) PORT_NAME("Keypad +")
+ PORT_BIT(0x08, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_6_PAD) PORT_CHAR(UCHAR_MAMEKEY(6_PAD)) PORT_NAME("Keypad 6")
+ PORT_BIT(0x10, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_COLON) PORT_CHAR(';') PORT_CHAR(':')
+ PORT_BIT(0x20, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_O) PORT_CHAR('o') PORT_CHAR('O')
+ PORT_BIT(0x40, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_9) PORT_CHAR('9') PORT_CHAR('(')
+ PORT_BIT(0x80, IP_ACTIVE_LOW, IPT_UNUSED)
+
+ PORT_START("ROW8")
+ PORT_BIT(0x01, IP_ACTIVE_LOW, IPT_UNUSED)
+ PORT_BIT(0x02, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_Z) PORT_CHAR('z') PORT_CHAR('Z')
+ PORT_BIT(0x04, IP_ACTIVE_LOW, IPT_UNUSED)
+ PORT_BIT(0x08, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_SPACE) PORT_CHAR(' ')
+ PORT_BIT(0x10, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_A) PORT_CHAR('a') PORT_CHAR('A')
+ PORT_BIT(0x20, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_TAB) PORT_CHAR(0x09) PORT_NAME("Tab")
+ PORT_BIT(0x40, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_TILDE) PORT_CHAR('`') PORT_CHAR('~')
+ PORT_BIT(0x80, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_X) PORT_CHAR('x') PORT_CHAR('X')
+
+ PORT_START("ROW9")
+ PORT_BIT(0x03, IP_ACTIVE_LOW, IPT_UNUSED)
+ PORT_BIT(0x04, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_7_PAD) PORT_CHAR(UCHAR_MAMEKEY(7_PAD)) PORT_NAME("Keypad 7")
+ PORT_BIT(0x08, IP_ACTIVE_LOW, IPT_UNUSED)
+ PORT_BIT(0x10, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_S) PORT_CHAR('s') PORT_CHAR('S')
+ PORT_BIT(0x20, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_Q) PORT_CHAR('q') PORT_CHAR('Q')
+ PORT_BIT(0x40, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_1) PORT_CHAR('1') PORT_CHAR('!')
+ PORT_BIT(0x80, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_C) PORT_CHAR('c') PORT_CHAR('C')
+
+ PORT_START("P2")
+ PORT_BIT(0x43, IP_ACTIVE_LOW, IPT_UNUSED)
+ PORT_BIT(0x04, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_LSHIFT) PORT_CODE(KEYCODE_RSHIFT) PORT_CHAR(UCHAR_SHIFT_1) PORT_NAME("Shift")
+ PORT_BIT(0x08, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_CAPSLOCK) PORT_CHAR(UCHAR_MAMEKEY(CAPSLOCK)) PORT_NAME("Caps Lock") PORT_TOGGLE
+ PORT_BIT(0x10, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_LALT) PORT_CODE(KEYCODE_RALT) PORT_CHAR(UCHAR_SHIFT_2) PORT_NAME("Option")
+ PORT_BIT(0x20, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_LCONTROL) PORT_NAME("Command")
+ PORT_BIT(0x80, IP_ACTIVE_LOW, IPT_UNUSED)
+INPUT_PORTS_END
+
+/***************************************************************************
+ DEVICE CONFIGURATION
+***************************************************************************/
+
+/*-------------------------------------------------
+ input_ports - device-specific input ports
+-------------------------------------------------*/
+ioport_constructor a9m0330_device::device_input_ports() const
+{
+ return INPUT_PORTS_NAME(a9m0330);
+}
+
+/*-------------------------------------------------
+ device_add_mconfig - device-specific
+ machine configurations
+-------------------------------------------------*/
+void a9m0330_device::device_add_mconfig(machine_config &config)
+{
+ I8048(config, m_mcu, 6_MHz_XTAL);
+ m_mcu->set_addrmap(AS_PROGRAM, &a9m0330_device::program_map);
+ m_mcu->bus_in_cb().set(FUNC(a9m0330_device::bus_r));
+ m_mcu->p1_out_cb().set(FUNC(a9m0330_device::p1_w));
+ m_mcu->p2_in_cb().set_ioport("P2");
+ m_mcu->p2_out_cb().set(FUNC(a9m0330_device::p2_w));
+ m_mcu->t0_in_cb().set(FUNC(a9m0330_device::t0_r));
+ m_mcu->t1_in_cb().set(FUNC(a9m0330_device::t1_r));
+}
+
+/*-------------------------------------------------
+ rom_region - device-specific ROM region
+-------------------------------------------------*/
+const tiny_rom_entry *a9m0330_device::device_rom_region() const
+{
+ return ROM_NAME(a9m0330);
+}
+
+/***************************************************************************
+ DEVICE IMPLEMENTATION
+***************************************************************************/
+
+a9m0330_device::a9m0330_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock) :
+ adb_device(mconfig, ADB_A9M0330, tag, owner, clock),
+ adb_slot_card_interface(mconfig, *this, DEVICE_SELF)
+ , m_mcu(*this, "mcu")
+ , m_rows{ *this, "ROW%u", 0U }
+{
+}
+
+void a9m0330_device::device_start()
+{
+ adb_device::device_start();
+
+ save_item(NAME(m_adb_state));
+ save_item(NAME(m_kbd_row));
+ save_item(NAME(m_our_last_adb_state));
+}
+
+void a9m0330_device::device_reset()
+{
+ adb_device::device_reset();
+
+ m_our_last_adb_state = 1;
+ m_adb_state = 1;
+ m_kbd_row = 0x3ff;
+}
+
+void a9m0330_device::adb_w(int state)
+{
+ m_adb_state = state;
+}
+
+void a9m0330_device::program_map(address_map &map)
+{
+ map(0x0000, 0x03ff).rom().region("mcu", 0);
+}
+
+u8 a9m0330_device::bus_r()
+{
+ u8 result = 0xffU;
+
+ for (unsigned int i = 0U; m_rows.size() > i; i++)
+ {
+ if (!BIT(m_kbd_row, i))
+ {
+ result &= m_rows[i]->read();
+ }
+ }
+
+ return result;
+}
+
+void a9m0330_device::p1_w(u8 data)
+{
+ m_kbd_row &= 0x300;
+ m_kbd_row |= data;
+}
+
+void a9m0330_device::p2_w(u8 data)
+{
+ m_kbd_row &= 0xff;
+ m_kbd_row |= (data & 0x03) << 8;
+
+ // ADB drive is through an inverting transistor
+ int adb_state = (data>>7) ^ 1;
+ if (adb_state != m_our_last_adb_state)
+ {
+ m_adb_cb(adb_state);
+ m_our_last_adb_state = adb_state;
+ }
+}
+
+int a9m0330_device::t0_r()
+{
+ // appears to be a config jumper of some sort
+ return 0;
+}
+
+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
new file mode 100644
index 00000000000..2c81e6538f4
--- /dev/null
+++ b/src/devices/bus/adb/a9m0330.h
@@ -0,0 +1,48 @@
+// license:BSD-3-Clause
+// copyright-holders: R. Belmont
+
+// a9m0330.h - Apple IIgs ADB keyboard
+
+#ifndef MAME_BUS_ADB_A9M0330_H
+#define MAME_BUS_ADB_A9M0330_H
+
+#pragma once
+
+#include "adb.h"
+#include "cpu/mcs48/mcs48.h"
+
+class a9m0330_device : public adb_device, public adb_slot_card_interface
+{
+public:
+ a9m0330_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock);
+
+protected:
+ virtual void device_start() override ATTR_COLD;
+ virtual void device_reset() override ATTR_COLD;
+
+ virtual const tiny_rom_entry *device_rom_region() const override ATTR_COLD;
+ virtual ioport_constructor device_input_ports() const override ATTR_COLD;
+ virtual void device_add_mconfig(machine_config &config) override ATTR_COLD;
+
+ virtual void adb_w(int state) override;
+
+ required_device<i8048_device> m_mcu;
+ required_ioport_array<10> m_rows;
+
+ void program_map(address_map &map) ATTR_COLD;
+
+private:
+ u8 bus_r();
+ void p1_w(u8 data);
+ void p2_w(u8 data);
+ int t0_r();
+ int t1_r();
+
+ int m_adb_state;
+ int m_kbd_row;
+ int m_our_last_adb_state;
+};
+
+DECLARE_DEVICE_TYPE(ADB_A9M0330, a9m0330_device)
+
+#endif
diff --git a/src/devices/bus/adb/a9m0331.cpp b/src/devices/bus/adb/a9m0331.cpp
new file mode 100644
index 00000000000..f0178dc4386
--- /dev/null
+++ b/src/devices/bus/adb/a9m0331.cpp
@@ -0,0 +1,125 @@
+// license:BSD-3-Clause
+// copyright-holders: R. Belmont
+/*********************************************************************
+
+ a9m0331.cpp
+ Apple standard ADB mouse
+ Skeleton by R. Belmont
+
+ TODO: Everything.
+ What 6805 or 68705 sub-model is this?
+ Is the boot vector actually correct?
+
+*********************************************************************/
+
+#include "emu.h"
+#include "a9m0331.h"
+
+DEFINE_DEVICE_TYPE(ADB_A9M0331, a9m0331_device, "a9m0331", "Apple ADB Mouse (A9M0331)");
+
+ROM_START(a9m0331)
+ ROM_REGION(0x800, "mcu", 0)
+ ROM_LOAD( "lsc84488p_1986_3.0.bin", 0x000000, 0x000800, CRC(572a11e0) SHA1(caab6c60b18670e5ea597e35e526032e33b6e8c7) )
+ ROM_LOAD( "zc84506p_1987_ea_3.2_trim.bin", 0x000000, 0x000800, CRC(85f858d9) SHA1(61ebad9953f4f88b6fcabf498f3875918493d138) )
+ROM_END
+
+static INPUT_PORTS_START(a9m0331)
+ PORT_START("button")
+ PORT_BIT(0x01, IP_ACTIVE_HIGH, IPT_BUTTON1) PORT_NAME("Mouse Button") PORT_CODE(MOUSECODE_BUTTON1)
+
+ PORT_START("mousex")
+ PORT_BIT(0xff, 0x00, IPT_MOUSE_X) PORT_SENSITIVITY(40) PORT_KEYDELTA(0) PORT_PLAYER(1)
+
+ PORT_START("mousey")
+ PORT_BIT(0xff, 0x00, IPT_MOUSE_Y) PORT_SENSITIVITY(40) PORT_KEYDELTA(0) PORT_PLAYER(1)
+INPUT_PORTS_END
+
+/***************************************************************************
+ DEVICE CONFIGURATION
+***************************************************************************/
+
+/*-------------------------------------------------
+ input_ports - device-specific input ports
+-------------------------------------------------*/
+ioport_constructor a9m0331_device::device_input_ports() const
+{
+ return INPUT_PORTS_NAME(a9m0331);
+}
+
+/*-------------------------------------------------
+ device_add_mconfig - device-specific
+ machine configurations
+-------------------------------------------------*/
+void a9m0331_device::device_add_mconfig(machine_config &config)
+{
+ M68705P3(config, m_mcu, 2048000);
+ m_mcu->porta_r().set(FUNC(a9m0331_device::mcu_port_a_r));
+ m_mcu->portb_r().set(FUNC(a9m0331_device::mcu_port_b_r));
+ m_mcu->portc_r().set(FUNC(a9m0331_device::mcu_port_c_r));
+ m_mcu->porta_w().set(FUNC(a9m0331_device::mcu_port_a_w));
+ m_mcu->portb_w().set(FUNC(a9m0331_device::mcu_port_b_w));
+ m_mcu->portc_w().set(FUNC(a9m0331_device::mcu_port_c_w));
+}
+
+/*-------------------------------------------------
+ rom_region - device-specific ROM region
+-------------------------------------------------*/
+const tiny_rom_entry *a9m0331_device::device_rom_region() const
+{
+ return ROM_NAME(a9m0331);
+}
+
+/***************************************************************************
+ DEVICE IMPLEMENTATION
+***************************************************************************/
+
+a9m0331_device::a9m0331_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) :
+ adb_device(mconfig, ADB_A9M0331, tag, owner, clock),
+ adb_slot_card_interface(mconfig, *this, DEVICE_SELF),
+ m_mcu(*this, "mcu")
+{
+}
+
+void a9m0331_device::device_start()
+{
+ adb_device::device_start();
+}
+
+void a9m0331_device::device_reset()
+{
+ adb_device::device_reset();
+}
+
+void a9m0331_device::adb_w(int state)
+{
+}
+
+void a9m0331_device::mcu_port_a_w(u8 data)
+{
+ logerror("%02x to port A\n", data);
+}
+
+void a9m0331_device::mcu_port_b_w(u8 data)
+{
+ logerror("%02x to port B\n", data);
+}
+
+void a9m0331_device::mcu_port_c_w(u8 data)
+{
+ logerror("%02x to port C\n", data);
+}
+
+u8 a9m0331_device::mcu_port_a_r()
+{
+ return 0xff;
+}
+
+u8 a9m0331_device::mcu_port_b_r()
+{
+ return 0xff;
+}
+
+u8 a9m0331_device::mcu_port_c_r()
+{
+ return 0xff;
+}
diff --git a/src/devices/bus/adb/a9m0331.h b/src/devices/bus/adb/a9m0331.h
new file mode 100644
index 00000000000..d213c491ea2
--- /dev/null
+++ b/src/devices/bus/adb/a9m0331.h
@@ -0,0 +1,42 @@
+// license:BSD-3-Clause
+// copyright-holders: R. Belmont
+
+// a9m0331.h - Apple ADB mouse
+
+#ifndef MAME_BUS_ADB_A9M0331_H
+#define MAME_BUS_ADB_A9M0331_H
+
+#pragma once
+
+#include "adb.h"
+#include "cpu/m6805/m68705.h"
+
+class a9m0331_device : public adb_device, public adb_slot_card_interface
+{
+public:
+ a9m0331_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
+
+protected:
+ virtual void device_start() override ATTR_COLD;
+ virtual void device_reset() override ATTR_COLD;
+
+ virtual const tiny_rom_entry *device_rom_region() const override ATTR_COLD;
+ virtual ioport_constructor device_input_ports() const override ATTR_COLD;
+ virtual void device_add_mconfig(machine_config &config) override ATTR_COLD;
+
+ virtual void adb_w(int state) override;
+
+ required_device<m68705p_device> m_mcu;
+
+private:
+ void mcu_port_a_w(u8 data);
+ void mcu_port_b_w(u8 data);
+ void mcu_port_c_w(u8 data);
+ u8 mcu_port_a_r();
+ u8 mcu_port_b_r();
+ u8 mcu_port_c_r();
+};
+
+DECLARE_DEVICE_TYPE(ADB_A9M0331, a9m0331_device)
+
+#endif
diff --git a/src/devices/bus/adb/adb.cpp b/src/devices/bus/adb/adb.cpp
new file mode 100644
index 00000000000..28d836ec3ff
--- /dev/null
+++ b/src/devices/bus/adb/adb.cpp
@@ -0,0 +1,68 @@
+// license:BSD-3-Clause
+// copyright-holders: Olivier Galibert
+
+// ADB - Apple Desktop Bus
+//
+// The serial desktop device bus from before USB was cool.
+//
+// Single data wire + poweron line, open collector
+
+#include "emu.h"
+#include "adb.h"
+
+#include "adbhle.h"
+#include "a9m0330.h"
+#include "a9m0331.h"
+
+DEFINE_DEVICE_TYPE(ADB_CONNECTOR, adb_connector, "adbslot", "ADB connector")
+
+adb_connector::adb_connector(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) :
+ device_t(mconfig, ADB_CONNECTOR, tag, owner, clock),
+ device_single_card_slot_interface<adb_slot_card_interface>(mconfig, *this)
+{
+}
+
+void adb_connector::device_start()
+{
+}
+
+adb_device *adb_connector::get_device()
+{
+ adb_slot_card_interface *const connected = get_card_device();
+ if (connected)
+ return connected->device().subdevice<adb_device>(connected->m_adb.finder_tag());
+ else
+ return nullptr;
+}
+
+adb_slot_card_interface::adb_slot_card_interface(const machine_config &mconfig, device_t &device, const char *adb_tag) :
+ device_interface(device, "adb"),
+ m_adb(*this, adb_tag)
+{
+}
+
+
+
+adb_device::adb_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_adb_cb(*this),
+ m_poweron_cb(*this)
+{
+}
+
+void adb_device::device_start()
+{
+}
+
+void adb_device::device_reset()
+{
+ m_adb_istate = true;
+ m_adb_ostate = true;
+}
+
+void adb_device::default_devices(device_slot_interface &device)
+{
+ device.option_add("hle", ADB_HLE);
+ device.option_add("a9m0330", ADB_A9M0330);
+ device.option_add("a9m0331", ADB_A9M0331);
+}
diff --git a/src/devices/bus/adb/adb.h b/src/devices/bus/adb/adb.h
new file mode 100644
index 00000000000..6d75a5c853d
--- /dev/null
+++ b/src/devices/bus/adb/adb.h
@@ -0,0 +1,74 @@
+// license:BSD-3-Clause
+// copyright-holders: Olivier Galibert
+
+// ADB - Apple Desktop Bus
+//
+// The serial desktop device bus from before USB was cool.
+//
+// Single data wire + poweron line, open collector
+
+#ifndef MAME_BUS_ADB_ADB_H
+#define MAME_BUS_ADB_ADB_H
+
+#pragma once
+
+class adb_device;
+class adb_slot_card_interface;
+
+class adb_connector: public device_t, public device_single_card_slot_interface<adb_slot_card_interface>
+{
+public:
+ template <typename T>
+ adb_connector(const machine_config &mconfig, const char *tag, device_t *owner, T &&opts, const char *dflt, bool fixed = false)
+ : adb_connector(mconfig, tag, owner, 0)
+ {
+ option_reset();
+ opts(*this);
+ set_default_option(dflt);
+ set_fixed(fixed);
+ }
+
+ adb_connector(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock = 0);
+ virtual ~adb_connector() = default;
+
+ adb_device *get_device();
+
+protected:
+ virtual void device_start() override ATTR_COLD;
+};
+
+class adb_slot_card_interface : public device_interface
+{
+ friend class adb_connector;
+
+public:
+ adb_slot_card_interface(const machine_config &mconfig, device_t &device, const char *adb_tag);
+
+private:
+ required_device<adb_device> m_adb;
+};
+
+class adb_device: public device_t
+{
+public:
+ virtual void adb_w(int state) = 0;
+ auto adb_r() { return m_adb_cb.bind(); }
+ auto poweron_r() { return m_poweron_cb.bind(); }
+
+ static void default_devices(device_slot_interface &device);
+
+protected:
+ adb_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock);
+ virtual void device_start() override ATTR_COLD;
+ virtual void device_reset() override ATTR_COLD;
+
+ devcb_write_line m_adb_cb;
+
+private:
+ devcb_write_line m_poweron_cb;
+ bool m_adb_istate, m_adb_ostate;
+};
+
+DECLARE_DEVICE_TYPE(ADB_CONNECTOR, adb_connector)
+
+#endif
diff --git a/src/devices/bus/adb/adbhle.cpp b/src/devices/bus/adb/adbhle.cpp
new file mode 100644
index 00000000000..369595ef143
--- /dev/null
+++ b/src/devices/bus/adb/adbhle.cpp
@@ -0,0 +1,45 @@
+// license:BSD-3-Clause
+// copyright-holders: Olivier Galibert
+
+// ADB - Apple Desktop Bus
+//
+// Generic HLE
+
+#include "emu.h"
+#include "adbhle.h"
+
+DEFINE_DEVICE_TYPE(ADB_HLE, adb_hle_device, "adbhle", "ADB HLE")
+
+adb_hle_device::adb_hle_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) :
+ adb_device(mconfig, ADB_HLE, tag, owner, clock),
+ adb_slot_card_interface(mconfig, *this, DEVICE_SELF)
+{
+}
+
+void adb_hle_device::device_start()
+{
+ adb_device::device_start();
+
+ save_item(NAME(m_last_state));
+ save_item(NAME(m_last_state_time));
+}
+
+void adb_hle_device::device_reset()
+{
+ adb_device::device_reset();
+ m_last_state = true;
+ m_last_state_time = machine().time();
+}
+
+void adb_hle_device::adb_w(int state)
+{
+ if(m_last_state != state) {
+ attotime delta = machine().time() - m_last_state_time;
+ u32 dt = delta.as_ticks(1000000);
+
+ logerror("level %d duration %6d us\n", m_last_state, dt);
+
+ m_last_state = state;
+ m_last_state_time = machine().time();
+ }
+}
diff --git a/src/devices/bus/adb/adbhle.h b/src/devices/bus/adb/adbhle.h
new file mode 100644
index 00000000000..f0a4ece90cc
--- /dev/null
+++ b/src/devices/bus/adb/adbhle.h
@@ -0,0 +1,33 @@
+// license:BSD-3-Clause
+// copyright-holders: Olivier Galibert
+
+// ADB - Apple Desktop Bus
+//
+// Generic HLE
+
+#ifndef MAME_BUS_ADB_ADBHLE_H
+#define MAME_BUS_ADB_ADBHLE_H
+
+#pragma once
+
+#include "adb.h"
+
+class adb_hle_device : public adb_device, public adb_slot_card_interface
+{
+public:
+ adb_hle_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
+
+protected:
+ virtual void device_start() override ATTR_COLD;
+ virtual void device_reset() override ATTR_COLD;
+
+ virtual void adb_w(int state) override;
+
+private:
+ bool m_last_state;
+ attotime m_last_state_time;
+};
+
+DECLARE_DEVICE_TYPE(ADB_HLE, adb_hle_device)
+
+#endif
diff --git a/src/devices/bus/amiga/cpuslot/a570.cpp b/src/devices/bus/amiga/cpuslot/a570.cpp
new file mode 100644
index 00000000000..abd42370380
--- /dev/null
+++ b/src/devices/bus/amiga/cpuslot/a570.cpp
@@ -0,0 +1,194 @@
+// license: GPL-2.0+
+// copyright-holders: Dirk Best
+/***************************************************************************
+
+ Commodore A570
+
+ DMAC based CD-ROM controller for the A500
+
+ Notes:
+ - Essentially turns the A500 into a CDTV
+ - A prototype version is called A690
+ - ROM label for the A690: "391298-01 V1.0 Copyright ©1991 CBM C480"
+ - The ROM P/N 391298-01 seems to have been used for multiple versions
+ - There are expansion slots for a 2 MB RAM expansion and a SCSI module
+ - Uses the CR-512-B drive from MKE (Matsushita Kotobuki Electronics)
+ - An FPGA is used in place of many discrete logic chips of the CDTV
+
+ TODO:
+ - Volume control (LC7883M)
+
+***************************************************************************/
+
+#include "emu.h"
+#include "a570.h"
+#include "speaker.h"
+
+#define VERBOSE (LOG_GENERAL)
+
+#include "logmacro.h"
+
+
+//**************************************************************************
+// DEVICE DEFINITIONS
+//**************************************************************************
+
+DEFINE_DEVICE_TYPE(AMIGA_CPUSLOT_A570, bus::amiga::cpuslot::a570_device, "amiga_a570", "Commodore A570")
+
+namespace bus::amiga::cpuslot {
+
+a570_device::a570_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) :
+ device_t(mconfig, AMIGA_CPUSLOT_A570, tag, owner, clock),
+ device_amiga_cpuslot_interface(mconfig, *this),
+ m_irq(*this, "irq"),
+ m_dmac(*this, "dmac"),
+ m_tpi(*this, "tpi"),
+ m_drive(*this, "drive"),
+ m_config(*this, "config")
+{
+}
+
+
+//**************************************************************************
+// ADDRESS MAPS
+//**************************************************************************
+
+void a570_device::map(address_map &map)
+{
+ map(0xdc8000, 0xdc87ff).mirror(0x07800).rw("nvram0", FUNC(at28c16_device::read), FUNC(at28c16_device::write)).umask16(0x00ff);
+ map(0xdc8000, 0xdc87ff).mirror(0x07800).rw("nvram1", FUNC(at28c16_device::read), FUNC(at28c16_device::write)).umask16(0xff00);
+ map(0xf00000, 0xf3ffff).mirror(0x40000).rom().region("bootrom", 0);
+}
+
+
+//**************************************************************************
+// INPUT DEFINITIONS
+//**************************************************************************
+
+static INPUT_PORTS_START( a570 )
+ PORT_START("config")
+ PORT_CONFNAME(0x01, 0x00, "2 MB RAM Expansion")
+ PORT_CONFSETTING(0x00, "Disabled")
+ PORT_CONFSETTING(0x01, "Enabled")
+INPUT_PORTS_END
+
+ioport_constructor a570_device::device_input_ports() const
+{
+ return INPUT_PORTS_NAME( a570 );
+}
+
+
+//**************************************************************************
+// ROM DEFINITIONS
+//**************************************************************************
+
+ROM_START( firmware )
+ ROM_REGION16_BE(0x40000, "bootrom", 0)
+ // COMMODORE-AMIGA 391298-01 ©1992 V2.30
+ ROM_LOAD("391298-01_v230.u20", 0x00000, 0x40000, CRC(30b54232) SHA1(ed7e461d1fff3cda321631ae42b80e3cd4fa5ebb))
+ROM_END
+
+const tiny_rom_entry *a570_device::device_rom_region() const
+{
+ return ROM_NAME( firmware );
+}
+
+
+//**************************************************************************
+// MACHINE DEFINITIONS
+//**************************************************************************
+
+void a570_device::device_add_mconfig(machine_config &config)
+{
+ INPUT_MERGER_ANY_HIGH(config, m_irq);
+ m_irq->output_handler().set([this] (int state) { m_host->int2_w(state); });
+
+ AMIGA_DMAC_REV2(config, m_dmac, 28.37516_MHz_XTAL / 4); // 7M
+ m_dmac->cfgout_cb().set([this] (int state) { m_host->cfgout_w(state); });
+ m_dmac->int_cb().set(m_irq, FUNC(input_merger_any_high_device::in_w<0>));
+ m_dmac->csx0_read_cb().set(m_drive, FUNC(cr511b_device::read));
+ m_dmac->csx0_write_cb().set(m_drive, FUNC(cr511b_device::write));
+ m_dmac->csx0_a4_read_cb().set(m_tpi, FUNC(tpi6525_device::read));
+ m_dmac->csx0_a4_write_cb().set(m_tpi, FUNC(tpi6525_device::write));
+ m_dmac->xdack_read_cb().set(m_drive, FUNC(cr511b_device::read));
+
+ AT28C16(config, "nvram0", 0);
+ AT28C16(config, "nvram1", 0);
+
+ TPI6525(config, m_tpi, 0);
+ m_tpi->out_irq_cb().set(m_irq, FUNC(input_merger_any_high_device::in_w<1>));
+ m_tpi->out_pb_cb().set(FUNC(a570_device::tpi_portb_w));
+
+ CR511B(config, m_drive, 0);
+ m_drive->add_route(0, "speaker", 1.0, 0);
+ m_drive->add_route(1, "speaker", 1.0, 1);
+ m_drive->scor_cb().set(m_tpi, FUNC(tpi6525_device::i1_w)).invert();
+ m_drive->stch_cb().set(m_tpi, FUNC(tpi6525_device::i2_w)).invert();
+ m_drive->sten_cb().set(m_tpi, FUNC(tpi6525_device::i3_w));
+ m_drive->sten_cb().append(FUNC(a570_device::sten_w));
+ m_drive->drq_cb().set(m_tpi, FUNC(tpi6525_device::i4_w));
+ m_drive->drq_cb().append(FUNC(a570_device::drq_w));
+
+ SPEAKER(config, "speaker", 2).front();
+
+ // TODO: Add stereo input for Amiga sound
+}
+
+
+//**************************************************************************
+// MACHINE EMULATION
+//**************************************************************************
+
+void a570_device::device_start()
+{
+ m_ram = make_unique_clear<uint16_t[]>(0x200000/2);
+
+ m_dmac->set_address_space(&m_host->space());
+ m_dmac->set_ram(m_ram.get());
+
+ m_host->space().install_device(0x000000, 0xffffff, *this, &a570_device::map);
+
+ // register for save states
+ save_pointer(NAME(m_ram), 0x200000/2);
+ save_item(NAME(m_sten));
+}
+
+void a570_device::sten_w(int state)
+{
+ m_sten = bool(state);
+}
+
+void a570_device::drq_w(int state)
+{
+ if (m_sten)
+ m_dmac->xdreq_w(state);
+}
+
+void a570_device::tpi_portb_w(uint8_t data)
+{
+ // 7------- daclch (lc7883m)
+ // -6------ dacst (lc7883m)
+ // --5----- dacatt (lc7883m)
+ // ---4---- weprom
+ // ----3--- dten (drive)
+ // -----2-- xaen (drive)
+ // ------1- enable (drive)
+ // -------0 cmd (drive)
+
+ m_drive->enable_w(BIT(data, 1));
+ m_drive->cmd_w(BIT(data, 0));
+}
+
+// the dmac handles this
+void a570_device::cfgin_w(int state) { m_dmac->configin_w(state); }
+
+void a570_device::rst_w(int state)
+{
+ // call rst first as it will unmap memory
+ m_dmac->rst_w(state);
+
+ if (state == 0)
+ m_dmac->ramsz_w(m_config->read() ? 3 : 0);
+}
+
+} // namespace bus::amiga::cpuslot
diff --git a/src/devices/bus/amiga/cpuslot/a570.h b/src/devices/bus/amiga/cpuslot/a570.h
new file mode 100644
index 00000000000..63d97b7703f
--- /dev/null
+++ b/src/devices/bus/amiga/cpuslot/a570.h
@@ -0,0 +1,66 @@
+// license: GPL-2.0+
+// copyright-holders: Dirk Best
+/***************************************************************************
+
+ Commodore A570
+
+ DMAC based CD-ROM controller for the A500
+
+***************************************************************************/
+
+#ifndef MAME_BUS_AMIGA_CPUSLOT_A570_H
+#define MAME_BUS_AMIGA_CPUSLOT_A570_H
+
+#pragma once
+
+#include "cpuslot.h"
+#include "machine/6525tpi.h"
+#include "machine/at28c16.h"
+#include "machine/cr511b.h"
+#include "machine/dmac.h"
+#include "machine/input_merger.h"
+
+
+namespace bus::amiga::cpuslot {
+
+class a570_device : public device_t, public device_amiga_cpuslot_interface
+{
+public:
+ a570_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
+
+protected:
+ virtual ioport_constructor device_input_ports() const override ATTR_COLD;
+ virtual const tiny_rom_entry *device_rom_region() const override ATTR_COLD;
+ virtual void device_add_mconfig(machine_config &config) override ATTR_COLD;
+
+ virtual void device_start() override ATTR_COLD;
+
+ // device_cpuslot_interface overrides
+ virtual void cfgin_w(int state) override;
+ virtual void rst_w(int state) override;
+
+private:
+ void map(address_map &map) ATTR_COLD;
+
+ void sten_w(int state);
+ void drq_w(int state);
+
+ void tpi_portb_w(uint8_t data);
+
+ required_device<input_merger_any_high_device> m_irq;
+ required_device<amiga_dmac_rev2_device> m_dmac;
+ required_device<tpi6525_device> m_tpi;
+ required_device<cr511b_device> m_drive;
+ required_ioport m_config;
+
+ bool m_sten;
+
+ std::unique_ptr<uint16_t[]> m_ram;
+};
+
+} // namespace bus::amiga::cpuslot
+
+// device type declaration
+DECLARE_DEVICE_TYPE_NS(AMIGA_CPUSLOT_A570, bus::amiga::cpuslot, a570_device)
+
+#endif // MAME_BUS_AMIGA_CPUSLOT_A570_H
diff --git a/src/devices/bus/amiga/cpuslot/a590.cpp b/src/devices/bus/amiga/cpuslot/a590.cpp
new file mode 100644
index 00000000000..5cc2bd91b7e
--- /dev/null
+++ b/src/devices/bus/amiga/cpuslot/a590.cpp
@@ -0,0 +1,274 @@
+// license: GPL-2.0+
+// copyright-holders: Dirk Best
+/***************************************************************************
+
+ Commodore A590
+
+ DMAC based SCSI controller for the A500
+
+ Notes:
+ - Hardware is almost identical to the A2091 controller for the A2000
+ - Commodore supplied XT drives: Epson HMD-755 or WD WD93028-X-A
+
+ TODO:
+ - 20/40 MB jumper
+ - DIP switch order/polarity
+ - JP3/JP4 switches (not really needed)
+ - Bootrom disable
+ - SCSI drives (fatalerrors early if you enable a drive)
+ - The XT drive should be a slot option
+ - Only DMAC Rev. 1: Data corruption when installing wb31
+
+***************************************************************************/
+
+#include "emu.h"
+#include "a590.h"
+#include "machine/nscsi_bus.h"
+#include "bus/nscsi/devices.h"
+
+#define LOG_XT (1U << 1)
+
+#define VERBOSE (LOG_GENERAL)
+
+#include "logmacro.h"
+
+
+//**************************************************************************
+// DEVICE DEFINITIONS
+//**************************************************************************
+
+DEFINE_DEVICE_TYPE(AMIGA_CPUSLOT_A590, bus::amiga::cpuslot::a590_device, "amiga_a590", "Commodore A590")
+
+namespace bus::amiga::cpuslot {
+
+a590_device::a590_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) :
+ device_t(mconfig, AMIGA_CPUSLOT_A590, tag, owner, clock),
+ device_amiga_cpuslot_interface(mconfig, *this),
+ m_irq(*this, "irq"),
+ m_dmac(*this, "dmac"),
+ m_wdc(*this, "scsi:7:wdc"),
+ m_xt(*this, "xt"),
+ m_jp1(*this, "jp1"),
+ m_dip(*this, "dip"),
+ m_ram_size(0)
+{
+}
+
+
+//**************************************************************************
+// INPUT DEFINITIONS
+//**************************************************************************
+
+static INPUT_PORTS_START( a590 )
+ PORT_START("jp1")
+ PORT_CONFNAME(0x03, 0x03, "Installed RAM")
+ PORT_CONFSETTING(0x00, "None")
+ PORT_CONFSETTING(0x01, "512K")
+ PORT_CONFSETTING(0x02, "1MB")
+ PORT_CONFSETTING(0x03, "2MB")
+
+ // JP3 (Switch HDD LED between XT and SCSI)
+
+ // JP4 (Switch between generating INT2 or INT6)
+
+ PORT_START("dip")
+ PORT_DIPNAME(0x01, 0x01, "Autoboot ROMs")
+ PORT_DIPLOCATION("DIP:1")
+ PORT_DIPSETTING(0x00, "Disabled")
+ PORT_DIPSETTING(0x01, "Enabled")
+ PORT_DIPNAME(0x02, 0x02, "LUN")
+ PORT_DIPLOCATION("DIP:2")
+ PORT_DIPSETTING(0x00, "Disabled")
+ PORT_DIPSETTING(0x02, "Enabled")
+ PORT_DIPNAME(0x04, 0x04, "Time-out")
+ PORT_DIPLOCATION("DIP:3")
+ PORT_DIPSETTING(0x00, "Short")
+ PORT_DIPSETTING(0x04, "Long")
+ PORT_DIPNAME(0x08, 0x08, "Reserved")
+ PORT_DIPLOCATION("DIP:4")
+ PORT_DIPSETTING(0x00, "Disabled")
+ PORT_DIPSETTING(0x08, "Enabled")
+INPUT_PORTS_END
+
+ioport_constructor a590_device::device_input_ports() const
+{
+ return INPUT_PORTS_NAME( a590 );
+}
+
+
+//**************************************************************************
+// ROM DEFINITIONS
+//**************************************************************************
+
+ROM_START( firmware )
+ ROM_REGION16_BE(0x8000, "bootrom", 0)
+ ROM_DEFAULT_BIOS("v70")
+
+ ROM_SYSTEM_BIOS(0, "v44", "Version 4.4")
+ ROMX_LOAD("390389-01.u13", 0x0000, 0x2000, CRC(0dbc6d28) SHA1(79378b8693b334fe12ee8d393235e3b571bfb55b), ROM_SKIP(1) | ROM_BIOS(0))
+ ROMX_LOAD("390388-01.u12", 0x0001, 0x2000, CRC(4d1b9757) SHA1(43ff80f7c5770566012d87118552842bb01010f5), ROM_SKIP(1) | ROM_BIOS(0))
+ ROMX_LOAD("390389-01.u13", 0x4000, 0x2000, CRC(0dbc6d28) SHA1(79378b8693b334fe12ee8d393235e3b571bfb55b), ROM_SKIP(1) | ROM_BIOS(0))
+ ROMX_LOAD("390388-01.u12", 0x4001, 0x2000, CRC(4d1b9757) SHA1(43ff80f7c5770566012d87118552842bb01010f5), ROM_SKIP(1) | ROM_BIOS(0))
+
+ ROM_SYSTEM_BIOS(1, "v46", "Version 4.6")
+ // 390389-02 ©1989 CBM V4.6 0703
+ ROMX_LOAD("390389-02.u13", 0x0000, 0x2000, CRC(26013266) SHA1(60dedda8d406b2762ad1504a88a4d6e29c0fb10d), ROM_SKIP(1) | ROM_BIOS(1))
+ // 390388-02 ©1989 CBM V4.6 E7E4
+ ROMX_LOAD("390388-02.u12", 0x0001, 0x2000, CRC(6c9cb089) SHA1(bd8c6bb79ae91a4d1b9ee76fdd11aaf97ca4358b), ROM_SKIP(1) | ROM_BIOS(1))
+ ROMX_LOAD("390389-02.u13", 0x4000, 0x2000, CRC(26013266) SHA1(60dedda8d406b2762ad1504a88a4d6e29c0fb10d), ROM_SKIP(1) | ROM_BIOS(1))
+ ROMX_LOAD("390388-02.u12", 0x4001, 0x2000, CRC(6c9cb089) SHA1(bd8c6bb79ae91a4d1b9ee76fdd11aaf97ca4358b), ROM_SKIP(1) | ROM_BIOS(1))
+
+ ROM_SYSTEM_BIOS(2, "v60", "Version 6.0")
+ // COPYRIGHT ©1989 CBM ALL RIGHTS RESERVED 390389-03 V6.0 CBE8
+ ROMX_LOAD("390389-03.u13", 0x0000, 0x2000, CRC(2e77bbff) SHA1(8a098845068f32cfa4d34a278cd290f61d35a52c), ROM_SKIP(1) | ROM_BIOS(2))
+ // COPYRIGHT ©1989 CBM ALL RIGHTS RESERVED 390388-03 V6.0 DFA0
+ ROMX_LOAD("390388-03.u12", 0x0001, 0x2000, CRC(b0b8cf24) SHA1(fcf4017505f4d441814b45d559c19eab43816b30), ROM_SKIP(1) | ROM_BIOS(2))
+ ROMX_LOAD("390389-03.u13", 0x4000, 0x2000, CRC(2e77bbff) SHA1(8a098845068f32cfa4d34a278cd290f61d35a52c), ROM_SKIP(1) | ROM_BIOS(2))
+ ROMX_LOAD("390388-03.u12", 0x4001, 0x2000, CRC(b0b8cf24) SHA1(fcf4017505f4d441814b45d559c19eab43816b30), ROM_SKIP(1) | ROM_BIOS(2))
+
+ ROM_SYSTEM_BIOS(3, "v61", "Version 6.1")
+ // COPYRIGHT ©1990 CBM ALL RIGHTS RESERVED 390721-01 V6.1 F4B8
+ ROMX_LOAD("390721-01.u13", 0x0000, 0x2000, CRC(00dbf615) SHA1(503940d04fb3b49eaa61100fd3a487018b35e25a), ROM_SKIP(1) | ROM_BIOS(3))
+ // COPYRIGHT ©1990 CBM ALL RIGHTS RESERVED 390722-01 V6.1 088B
+ ROMX_LOAD("390722-01.u12", 0x0001, 0x2000, CRC(c460cfdb) SHA1(0de457daec3b84f75e8fb344defe24ce56cda3e0), ROM_SKIP(1) | ROM_BIOS(3))
+ ROMX_LOAD("390721-01.u13", 0x4000, 0x2000, CRC(00dbf615) SHA1(503940d04fb3b49eaa61100fd3a487018b35e25a), ROM_SKIP(1) | ROM_BIOS(3))
+ ROMX_LOAD("390722-01.u12", 0x4001, 0x2000, CRC(c460cfdb) SHA1(0de457daec3b84f75e8fb344defe24ce56cda3e0), ROM_SKIP(1) | ROM_BIOS(3))
+
+ ROM_SYSTEM_BIOS(4, "v66", "Version 6.6")
+ // COPYRIGHT ©1991 CBM ALL RIGHTS RESERVED 390721-02V6.6 D464
+ ROMX_LOAD("390721-02.u13", 0x0000, 0x2000, CRC(c0871d25) SHA1(e155f18abb90cf820589c15e70559d3b6b391af8), ROM_SKIP(1) | ROM_BIOS(4))
+ // COPYRIGHT ©1991 CBM ALL RIGHTS RESERVED 390722-02V6.6 F929
+ ROMX_LOAD("390722-02.u12", 0x0001, 0x2000, CRC(e536bbb2) SHA1(fd7f8a6da18c1b02d07eb990c2467a24183ede12), ROM_SKIP(1) | ROM_BIOS(4))
+ ROMX_LOAD("390721-02.u13", 0x4000, 0x2000, CRC(c0871d25) SHA1(e155f18abb90cf820589c15e70559d3b6b391af8), ROM_SKIP(1) | ROM_BIOS(4))
+ ROMX_LOAD("390722-02.u12", 0x4001, 0x2000, CRC(e536bbb2) SHA1(fd7f8a6da18c1b02d07eb990c2467a24183ede12), ROM_SKIP(1) | ROM_BIOS(4))
+
+ ROM_SYSTEM_BIOS(5, "v70", "Version 7.0") // also seen with -07
+ ROMX_LOAD("390721-04.u13", 0x0000, 0x2000, CRC(2942747a) SHA1(dbd7648e79c753337ff3e4f491de224bf05e6bb6), ROM_SKIP(1) | ROM_BIOS(5))
+ ROMX_LOAD("390722-04.u12", 0x0001, 0x2000, CRC(a9ccffed) SHA1(149f5bd52e2d29904e3de483b9ad772448e9278e), ROM_SKIP(1) | ROM_BIOS(5))
+ ROMX_LOAD("390721-04.u13", 0x4000, 0x2000, CRC(2942747a) SHA1(dbd7648e79c753337ff3e4f491de224bf05e6bb6), ROM_SKIP(1) | ROM_BIOS(5))
+ ROMX_LOAD("390722-04.u12", 0x4001, 0x2000, CRC(a9ccffed) SHA1(149f5bd52e2d29904e3de483b9ad772448e9278e), ROM_SKIP(1) | ROM_BIOS(5))
+
+ // third-party upgrade ROM, requires a small ROM adapter pcb
+ ROM_SYSTEM_BIOS(6, "g614", "Guru-ROM 6.14")
+ ROMX_LOAD("gururom_v614.bin", 0x0000, 0x8000, CRC(04e52f93) SHA1(6da21b6f5e8f8837d64507cd8a4d5cdcac4f426b), ROM_GROUPWORD | ROM_BIOS(6))
+
+ // pal16l8a
+ ROM_REGION(0x104, "ram_controller", 0)
+ ROM_LOAD("390333-03.u5", 0x000, 0x104, CRC(dc4a8d9b) SHA1(761a1318106e49057f95258699076ec1079967ad))
+ROM_END
+
+const tiny_rom_entry *a590_device::device_rom_region() const
+{
+ return ROM_NAME( firmware );
+}
+
+
+//**************************************************************************
+// MACHINE DEFINITIONS
+//**************************************************************************
+
+void a590_device::wd33c93_config(device_t *device)
+{
+ device->set_clock(28.37516_MHz_XTAL / 4); // 7M
+ downcast<wd33c93a_device *>(device)->irq_cb().set(m_irq, FUNC(input_merger_any_high_device::in_w<0>));
+ downcast<wd33c93a_device *>(device)->drq_cb().set(m_dmac, FUNC(amiga_dmac_device::sdreq_w));
+}
+
+void a590_device::device_add_mconfig(machine_config &config)
+{
+ AMIGA_DMAC_REV2(config, m_dmac, 28.37516_MHz_XTAL / 4); // 7M
+ m_dmac->set_rom("bootrom");
+ m_dmac->cfgout_cb().set([this] (int state) { m_host->cfgout_w(state); });
+ m_dmac->int_cb().set([this] (int state) { m_host->int2_w(state); });
+ m_dmac->css_read_cb().set(m_wdc, FUNC(wd33c93a_device::indir_r));
+ m_dmac->css_write_cb().set(m_wdc, FUNC(wd33c93a_device::indir_w));
+ m_dmac->csx0_read_cb().set(FUNC(a590_device::xt_r));
+ m_dmac->csx0_write_cb().set(FUNC(a590_device::xt_w));
+ m_dmac->csx1_read_cb().set(FUNC(a590_device::dip_r));
+ m_dmac->xdack_read_cb().set(m_xt, FUNC(xt_hdc_device::dack_r));
+ m_dmac->xdack_write_cb().set(m_xt, FUNC(xt_hdc_device::dack_w));
+
+ INPUT_MERGER_ANY_HIGH(config, m_irq);
+ m_irq->output_handler().set(m_dmac, FUNC(amiga_dmac_device::intx_w));
+
+ NSCSI_BUS(config, "scsi", 0);
+ NSCSI_CONNECTOR(config, "scsi:0", default_scsi_devices, nullptr, false);
+ NSCSI_CONNECTOR(config, "scsi:1", 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("wdc", WD33C93A).machine_config([this] (device_t *device) { wd33c93_config(device); });
+
+ XT_HDC(config, m_xt, 0);
+ m_xt->irq_handler().set(m_irq, FUNC(input_merger_any_high_device::in_w<1>));
+ m_xt->drq_handler().set(m_dmac, FUNC(amiga_dmac_device::xdreq_w));
+
+ HARDDISK(config, "xt:primary");
+}
+
+
+//**************************************************************************
+// MACHINE EMULATION
+//**************************************************************************
+
+void a590_device::device_start()
+{
+ // setup ram
+ m_ram = make_unique_clear<uint16_t[]>(0x200000/2);
+
+ // setup dmac
+ m_dmac->set_address_space(&m_host->space());
+ m_dmac->set_ram(m_ram.get());
+
+ // register for save states
+ save_pointer(NAME(m_ram), 0x200000/2);
+ save_item(NAME(m_ram_size));
+}
+
+// the dmac handles this
+void a590_device::cfgin_w(int state) { m_dmac->configin_w(state); }
+
+void a590_device::rst_w(int state)
+{
+ // call rst first as it will unmap memory
+ m_dmac->rst_w(state);
+
+ if (state == 0)
+ m_dmac->ramsz_w(m_jp1->read() & 0x03);
+}
+
+uint8_t a590_device::xt_r(offs_t offset)
+{
+ LOGMASKED(LOG_XT, "xt_r(%02x)\n", offset);
+
+ switch (offset)
+ {
+ case 0: return m_xt->data_r();
+ case 1: return m_xt->status_r();
+ case 2: return 0x02; // jumper: 20/40 MB
+ }
+
+ return 0xff;
+}
+
+void a590_device::xt_w(offs_t offset, uint8_t data)
+{
+ LOGMASKED(LOG_XT, "xt_w(%02x): %02x\n", offset, data);
+
+ switch (offset)
+ {
+ case 0: m_xt->data_w(data); break;
+ case 1: m_xt->reset_w(data); break;
+ case 2: m_xt->select_w(data); break;
+ case 3: m_xt->control_w(data); break;
+ }
+}
+
+uint8_t a590_device::dip_r(offs_t offset)
+{
+ // TODO: order to be verified
+ return m_dip->read() >> 1;
+}
+
+} // namespace bus::amiga::cpuslot
diff --git a/src/devices/bus/amiga/cpuslot/a590.h b/src/devices/bus/amiga/cpuslot/a590.h
new file mode 100644
index 00000000000..2a046c179ee
--- /dev/null
+++ b/src/devices/bus/amiga/cpuslot/a590.h
@@ -0,0 +1,65 @@
+// license: GPL-2.0+
+// copyright-holders: Dirk Best
+/***************************************************************************
+
+ Commodore A590
+
+ DMAC based SCSI controller for the A500
+
+***************************************************************************/
+
+#ifndef MAME_BUS_AMIGA_CPUSLOT_A590_H
+#define MAME_BUS_AMIGA_CPUSLOT_A590_H
+
+#pragma once
+
+#include "cpuslot.h"
+#include "bus/isa/hdc.h"
+#include "machine/autoconfig.h"
+#include "machine/dmac.h"
+#include "machine/input_merger.h"
+#include "machine/wd33c9x.h"
+
+
+namespace bus::amiga::cpuslot {
+
+class a590_device : public device_t, public device_amiga_cpuslot_interface
+{
+public:
+ a590_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
+
+protected:
+ virtual ioport_constructor device_input_ports() const override ATTR_COLD;
+ virtual const tiny_rom_entry *device_rom_region() const override ATTR_COLD;
+ virtual void device_add_mconfig(machine_config &config) override ATTR_COLD;
+
+ virtual void device_start() override ATTR_COLD;
+
+ // device_cpuslot_interface overrides
+ virtual void cfgin_w(int state) override;
+ virtual void rst_w(int state) override;
+
+private:
+ void wd33c93_config(device_t *device);
+
+ uint8_t xt_r(offs_t offset);
+ void xt_w(offs_t offset, uint8_t data);
+ uint8_t dip_r(offs_t offset);
+
+ required_device<input_merger_any_high_device> m_irq;
+ required_device<amiga_dmac_rev2_device> m_dmac;
+ required_device<wd33c93a_device> m_wdc;
+ required_device<xt_hdc_device> m_xt;
+ required_ioport m_jp1;
+ required_ioport m_dip;
+
+ std::unique_ptr<uint16_t[]> m_ram;
+ uint8_t m_ram_size;
+};
+
+} // namespace bus::amiga::cpuslot
+
+// device type declaration
+DECLARE_DEVICE_TYPE_NS(AMIGA_CPUSLOT_A590, bus::amiga::cpuslot, a590_device)
+
+#endif // MAME_BUS_AMIGA_CPUSLOT_A590_H
diff --git a/src/devices/bus/amiga/cpuslot/action_replay.cpp b/src/devices/bus/amiga/cpuslot/action_replay.cpp
new file mode 100644
index 00000000000..4fe7f18a0ef
--- /dev/null
+++ b/src/devices/bus/amiga/cpuslot/action_replay.cpp
@@ -0,0 +1,293 @@
+// license: GPL-2.0+
+// copyright-holders: Dirk Best
+/***************************************************************************
+
+ Datel Electronics Action Replay
+
+ Freezer cartridge for the A500 and A2000
+
+ Notes:
+ - The first four bytes cannot be read if you read the ROM using
+ the cartridge. This the reason for the BAD_DUMP flags.
+
+ TODO:
+ - MK1: Unimplemented (ROM: 0xf00000-0xf0ffff, RAM: 0x9fc000-0x9fffff)
+ - MK2: Partially works, but entering/exiting from cartridge isn't stable
+ - MK3: Not working (needs different reset handling)
+ - Unmapping ROM/RAM
+ - Reset behaviour: Real cartridge measures reset pulse length to
+ differentiate between keyboard reset and CPU RESET instruction
+ - Breakpoints
+ - A2000 version
+
+***************************************************************************/
+
+#include "emu.h"
+#include "action_replay.h"
+
+#define VERBOSE (LOG_GENERAL)
+
+#include "logmacro.h"
+
+
+//**************************************************************************
+// DEVICE DEFINITIONS
+//**************************************************************************
+
+DEFINE_DEVICE_TYPE(AMIGA_CPUSLOT_ACTION_REPLAY_MK1, bus::amiga::cpuslot::action_replay_mk1_device, "amiga_ar1", "Action Replay")
+DEFINE_DEVICE_TYPE(AMIGA_CPUSLOT_ACTION_REPLAY_MK2, bus::amiga::cpuslot::action_replay_mk2_device, "amiga_ar2", "Action Replay MK II")
+DEFINE_DEVICE_TYPE(AMIGA_CPUSLOT_ACTION_REPLAY_MK3, bus::amiga::cpuslot::action_replay_mk3_device, "amiga_ar3", "Action Replay MK III")
+
+namespace bus::amiga::cpuslot {
+
+action_replay_device_base::action_replay_device_base(const machine_config &mconfig, device_type type, size_t ram_size, const char *tag, device_t *owner, uint32_t clock) :
+ device_t(mconfig, type, tag, owner, clock),
+ device_amiga_cpuslot_interface(mconfig, *this),
+ m_rom(*this, "rom"),
+ m_ram(*this, "ram", ram_size, ENDIANNESS_BIG)
+{
+}
+
+action_replay_mk1_device::action_replay_mk1_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) :
+ action_replay_device_base(mconfig, AMIGA_CPUSLOT_ACTION_REPLAY_MK1, 0x4000, tag, owner, clock)
+{
+}
+
+action_replay_mk2_device::action_replay_mk2_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) :
+ action_replay_device_base(mconfig, AMIGA_CPUSLOT_ACTION_REPLAY_MK2, 0x10000, tag, owner, clock)
+{
+}
+
+action_replay_mk2_device::action_replay_mk2_device(const machine_config &mconfig, device_type type, size_t ram_size, const char *tag, device_t *owner, uint32_t clock) :
+ action_replay_device_base(mconfig, type, ram_size, tag, owner, clock)
+{
+}
+
+action_replay_mk3_device::action_replay_mk3_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) :
+ action_replay_mk2_device(mconfig, AMIGA_CPUSLOT_ACTION_REPLAY_MK3, 0x10000, tag, owner, clock)
+{
+}
+
+
+//**************************************************************************
+// ADDRESS MAPS
+//**************************************************************************
+
+void action_replay_mk2_device::regs_map(address_map &map)
+{
+ // base address 0x400000
+ map(0x000000, 0x03ffff).rom().region("rom", 0);
+ map(0x000000, 0x000001).w(FUNC(action_replay_mk2_device::mode_w));
+ map(0x000000, 0x000001).mirror(0x02).r(FUNC(action_replay_mk2_device::status_r));
+ map(0x000006, 0x000007).w(FUNC(action_replay_mk2_device::restore_w));
+ map(0x040000, 0x04ffff).mirror(0x30000).ram().share(m_ram);
+}
+
+
+//**************************************************************************
+// INPUT DEFINITIONS
+//**************************************************************************
+
+static INPUT_PORTS_START( action_replay )
+ PORT_START("button")
+ PORT_BIT(0x01, IP_ACTIVE_HIGH, IPT_OTHER ) PORT_NAME("Freeze") PORT_CODE(KEYCODE_F12) PORT_CHANGED_MEMBER(DEVICE_SELF, FUNC(action_replay_device_base::freeze), 0)
+INPUT_PORTS_END
+
+ioport_constructor action_replay_device_base::device_input_ports() const
+{
+ return INPUT_PORTS_NAME( action_replay );
+}
+
+
+//**************************************************************************
+// ROM DEFINITIONS
+//**************************************************************************
+
+ROM_START( rom_mk1 )
+ ROM_REGION(0x10000, "rom", 0)
+ ROM_DEFAULT_BIOS("v150")
+ ROM_SYSTEM_BIOS(0, "v100", "Version 1.00")
+ ROMX_LOAD("ar1_v100.bin", 0x0000, 0x10000, BAD_DUMP CRC(2d921771) SHA1(1ead9dda2dad29146441f5ef7218375022e01248), ROM_BIOS(0))
+ ROM_SYSTEM_BIOS(1, "v150", "Version 1.50")
+ ROMX_LOAD("ar1_v150.bin", 0x0000, 0x10000, BAD_DUMP CRC(f82c4258) SHA1(843b433b2c56640e045d5fdc854dc6b1a4964e7c), ROM_BIOS(1))
+ROM_END
+
+const tiny_rom_entry *action_replay_mk1_device::device_rom_region() const
+{
+ return ROM_NAME( rom_mk1 );
+}
+
+ROM_START( rom_mk2 )
+ ROM_REGION16_BE(0x40000, "rom", 0)
+ ROM_DEFAULT_BIOS("v214")
+ ROM_SYSTEM_BIOS(0, "v205", "Version 2.05")
+ ROMX_LOAD("ar2_v205.bin", 0x00000, 0x20000, BAD_DUMP CRC(4051eef8) SHA1(9df22b1d3285b522c223697c83d144d04e961a4a), ROM_BIOS(0))
+ ROM_RELOAD( 0x20000, 0x20000)
+ ROM_SYSTEM_BIOS(1, "v212", "Version 2.12")
+ ROMX_LOAD("ar2_v212.bin", 0x00000, 0x20000, BAD_DUMP CRC(d29bdd86) SHA1(76c2900457badf22b742f0af48b78937e8b67694), ROM_BIOS(1))
+ ROM_RELOAD( 0x20000, 0x20000)
+ ROM_SYSTEM_BIOS(2, "v214", "Version 2.14")
+ ROMX_LOAD("ar2_v214.bin", 0x00000, 0x20000, BAD_DUMP CRC(1bb3d0a8) SHA1(14b1f5a69efb6f4e2331970e6ca0f33c0f04ac91), ROM_BIOS(2))
+ ROM_RELOAD( 0x20000, 0x20000)
+ROM_END
+
+const tiny_rom_entry *action_replay_mk2_device::device_rom_region() const
+{
+ return ROM_NAME( rom_mk2 );
+}
+
+ROM_START( rom_mk3 )
+ ROM_REGION16_BE(0x40000, "rom", 0)
+ ROM_DEFAULT_BIOS("v317")
+ ROM_SYSTEM_BIOS(0, "v309", "Version 3.09")
+ ROMX_LOAD("ar3_v309.evn", 0x00000, 0x20000, CRC(2b84519f) SHA1(7841873bf009d8341dfa2794b3751bacf86adcc8), ROM_SKIP(1) | ROM_BIOS(0))
+ ROMX_LOAD("ar3_v309.odd", 0x00001, 0x20000, CRC(1d35bd56) SHA1(6464be1626b519499e76e4e3409e8016515d48b6), ROM_SKIP(1) | ROM_BIOS(0))
+ ROM_SYSTEM_BIOS(1, "v317", "Version 3.17")
+ ROMX_LOAD("ar3_v317.evn", 0x00000, 0x20000, CRC(5fb69a10) SHA1(2ce641d1e2e254769be7d1ba41aace079cb04e27), ROM_SKIP(1) | ROM_BIOS(1))
+ ROMX_LOAD("ar3_v317.odd", 0x00001, 0x20000, CRC(f767d072) SHA1(a7431d22bfdb746a8bb6073c9edf7a2b65c6d307), ROM_SKIP(1) | ROM_BIOS(1))
+ROM_END
+
+const tiny_rom_entry *action_replay_mk3_device::device_rom_region() const
+{
+ return ROM_NAME( rom_mk3 );
+}
+
+
+//**************************************************************************
+// MACHINE EMULATION
+//**************************************************************************
+
+void action_replay_mk1_device::device_start()
+{
+}
+
+void action_replay_mk1_device::freeze_w(int state)
+{
+ LOG("freeze_w: %d\n", state);
+}
+
+void action_replay_mk2_device::install_chipmem_taps()
+{
+ m_chipmem_read_tap = m_host->space().install_read_tap
+ (
+ 0x000000, 0x1fffff,
+ "chipmem_r",
+ [this] (offs_t offset, uint16_t &data, uint16_t mem_mask)
+ {
+ if (m_nmi_active)
+ {
+ // disable chip memory
+ m_host->ovr_w(0);
+
+ // map action replay
+ m_host->space().install_rom(0x000000, 0x03ffff, 0x040000, m_rom);
+ m_host->space().install_device(0x400000, 0x47ffff, *this, &action_replay_mk2_device::regs_map);
+
+ // the rom is mapped too late for this read, so adjust it with the data that would have been read
+ data = m_rom[offset >> 1];
+
+ m_nmi_active = false;
+ }
+ },
+ &m_chipmem_read_tap
+ );
+
+ m_chipmem_write_tap = m_host->space().install_write_tap
+ (
+ 0x000000, 0x1fffff,
+ "chipmem_w",
+ [this] (offs_t offset, uint16_t &data, uint16_t mem_mask)
+ {
+ if (m_reset)
+ {
+ // trigger nmi
+ LOG("trigger nmi\n");
+
+ m_nmi_active = true;
+ m_host->ipl7_w(1);
+ m_host->ipl7_w(0);
+
+ m_reset = false;
+ }
+ },
+ &m_chipmem_write_tap
+ );
+}
+
+void action_replay_mk2_device::device_start()
+{
+ m_status = STATUS_RESET;
+ m_reset = true;
+
+ install_chipmem_taps();
+
+ // custom chip writes (by the cpu) get mirrored to internal ram
+ // TODO: exact range (probably supports mirrors)
+ m_custom_chip_tap = m_host->space().install_write_tap
+ (
+ 0xdff000, 0xdff1ff,
+ "custom_chip_w",
+ [this] (offs_t offset, uint16_t &data, uint16_t mem_mask)
+ {
+ m_ram[(0xf000 | (offset & 0x1ff)) >> 1] = data;
+ },
+ &m_custom_chip_tap
+ );
+
+}
+
+void action_replay_mk2_device::freeze_w(int state)
+{
+ LOG("freeze_w: %d\n", state);
+
+ if (state)
+ {
+ m_status = STATUS_BUTTON;
+
+ m_nmi_active = true;
+ m_host->ipl7_w(1);
+ m_host->ipl7_w(0);
+ }
+}
+
+void action_replay_mk2_device::rst_w(int state)
+{
+ LOG("rst_w: %d\n", state);
+
+ if (state == 0)
+ {
+ m_status = STATUS_RESET;
+ m_reset = true;
+ }
+}
+
+uint16_t action_replay_mk2_device::status_r(offs_t offset, uint16_t mem_mask)
+{
+ if (!machine().side_effects_disabled())
+ LOG("status_r: %04x & %04x\n", m_status, mem_mask);
+
+ return m_status;
+}
+
+void action_replay_mk2_device::mode_w(offs_t offset, uint16_t data, uint16_t mem_mask)
+{
+ // 1- enable freeze on read of 0xbfe001
+ // -0 enable freeze on write of 0xbfd100
+
+ LOG("mode_w: %04x & %04x\n", data, mem_mask);
+
+ m_mode = data & 0x03;
+}
+
+void action_replay_mk2_device::restore_w(offs_t offset, uint16_t data, uint16_t mem_mask)
+{
+ LOG("restore_w: %04x & %04x\n", data, mem_mask);
+
+ // map chip memory again
+ m_host->ovr_w(1);
+
+ // remapping chip memory has wiped out our tap, reinstall it
+ install_chipmem_taps();
+}
+
+} // namespace bus::amiga::cpuslot
diff --git a/src/devices/bus/amiga/cpuslot/action_replay.h b/src/devices/bus/amiga/cpuslot/action_replay.h
new file mode 100644
index 00000000000..21be7d7af2e
--- /dev/null
+++ b/src/devices/bus/amiga/cpuslot/action_replay.h
@@ -0,0 +1,106 @@
+// license: GPL-2.0+
+// copyright-holders: Dirk Best
+/***************************************************************************
+
+ Datel Electronics Action Replay
+
+ Freezer cartridge for the A500 and A2000
+
+***************************************************************************/
+
+#ifndef MAME_BUS_AMIGA_CPUSLOT_ACTION_REPLAY_H
+#define MAME_BUS_AMIGA_CPUSLOT_ACTION_REPLAY_H
+
+#pragma once
+
+#include "cpuslot.h"
+
+
+namespace bus::amiga::cpuslot {
+
+class action_replay_device_base : public device_t, public device_amiga_cpuslot_interface
+{
+public:
+ DECLARE_INPUT_CHANGED_MEMBER( freeze ) { freeze_w(newval); };
+ virtual void freeze_w(int state) = 0;
+
+protected:
+ action_replay_device_base(const machine_config &mconfig, device_type type, size_t ram_size, const char *tag, device_t *owner, uint32_t clock);
+
+ virtual ioport_constructor device_input_ports() const override ATTR_COLD;
+
+ required_region_ptr<uint16_t> m_rom;
+ memory_share_creator<uint16_t> m_ram;
+};
+
+class action_replay_mk1_device : public action_replay_device_base
+{
+public:
+ action_replay_mk1_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 ATTR_COLD;
+ virtual void device_start() override ATTR_COLD;
+
+ // action_replay_device_base overrides
+ virtual void freeze_w(int state) override;
+};
+
+class action_replay_mk2_device : public action_replay_device_base
+{
+public:
+ action_replay_mk2_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
+
+protected:
+ action_replay_mk2_device(const machine_config &mconfig, device_type type, size_t ram_size, const char *tag, device_t *owner, uint32_t clock);
+
+ virtual const tiny_rom_entry *device_rom_region() const override ATTR_COLD;
+ virtual void device_start() override ATTR_COLD;
+
+ // device_cpuslot_interface overrides
+ virtual void rst_w(int state) override;
+
+ // action_replay_device_base overrides
+ virtual void freeze_w(int state) override;
+
+private:
+ void regs_map(address_map &map) ATTR_COLD;
+ void install_chipmem_taps();
+
+ uint16_t status_r(offs_t offset, uint16_t mem_mask);
+ void mode_w(offs_t offset, uint16_t data, uint16_t mem_mask);
+ void restore_w(offs_t offset, uint16_t data, uint16_t mem_mask);
+
+ static constexpr uint8_t STATUS_BUTTON = 0x00;
+ static constexpr uint8_t STATUS_READ = 0x01; // 0xbfe001
+ static constexpr uint8_t STATUS_WRITE = 0x02; // 0xbfd100
+ static constexpr uint8_t STATUS_RESET = 0x03;
+
+ memory_passthrough_handler m_custom_chip_tap;
+ memory_passthrough_handler m_chipmem_read_tap;
+ memory_passthrough_handler m_chipmem_write_tap;
+
+ uint8_t m_status;
+ uint8_t m_mode;
+
+ bool m_nmi_active;
+ bool m_reset;
+};
+
+class action_replay_mk3_device : public action_replay_mk2_device
+{
+public:
+ action_replay_mk3_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 ATTR_COLD;
+};
+
+} // namespace bus::amiga::cpuslot
+
+// device type declaration
+DECLARE_DEVICE_TYPE_NS(AMIGA_CPUSLOT_ACTION_REPLAY_MK1, bus::amiga::cpuslot, action_replay_mk1_device)
+DECLARE_DEVICE_TYPE_NS(AMIGA_CPUSLOT_ACTION_REPLAY_MK2, bus::amiga::cpuslot, action_replay_mk2_device)
+DECLARE_DEVICE_TYPE_NS(AMIGA_CPUSLOT_ACTION_REPLAY_MK3, bus::amiga::cpuslot, action_replay_mk3_device)
+
+#endif // MAME_BUS_AMIGA_CPUSLOT_ACTION_REPLAY_H
diff --git a/src/devices/bus/amiga/cpuslot/cards.cpp b/src/devices/bus/amiga/cpuslot/cards.cpp
new file mode 100644
index 00000000000..a2f48edd030
--- /dev/null
+++ b/src/devices/bus/amiga/cpuslot/cards.cpp
@@ -0,0 +1,37 @@
+// license: GPL-2.0+
+// copyright-holders: Dirk Best
+/***************************************************************************
+
+ 86-pin expansion slot (A500, A1000)
+ Coprocessor slot (A2000, B2000)
+
+ Card options
+
+***************************************************************************/
+
+#include "emu.h"
+#include "cards.h"
+
+#include "a570.h"
+#include "a590.h"
+#include "action_replay.h"
+#include "megamix500.h"
+
+
+void a1000_cpuslot_cards(device_slot_interface &device)
+{
+}
+
+void a500_cpuslot_cards(device_slot_interface &device)
+{
+ device.option_add("a570", AMIGA_CPUSLOT_A570);
+ device.option_add("a590", AMIGA_CPUSLOT_A590);
+ device.option_add("ar", AMIGA_CPUSLOT_ACTION_REPLAY_MK1);
+ device.option_add("ar2", AMIGA_CPUSLOT_ACTION_REPLAY_MK2);
+ device.option_add("ar3", AMIGA_CPUSLOT_ACTION_REPLAY_MK3);
+ device.option_add("megamix500", AMIGA_CPUSLOT_MEGAMIX500);
+}
+
+void a2000_cpuslot_cards(device_slot_interface &device)
+{
+}
diff --git a/src/devices/bus/amiga/cpuslot/cards.h b/src/devices/bus/amiga/cpuslot/cards.h
new file mode 100644
index 00000000000..e857f580697
--- /dev/null
+++ b/src/devices/bus/amiga/cpuslot/cards.h
@@ -0,0 +1,22 @@
+// license: GPL-2.0+
+// copyright-holders: Dirk Best
+/***************************************************************************
+
+ 86-pin expansion slot (A500, A1000)
+ Coprocessor slot (A2000, B2000)
+
+ Card options
+
+***************************************************************************/
+
+#ifndef MAME_BUS_AMIGA_CPUSLOT_CARDS_H
+#define MAME_BUS_AMIGA_CPUSLOT_CARDS_H
+
+#pragma once
+
+
+void a1000_cpuslot_cards(device_slot_interface &device) ATTR_COLD;
+void a500_cpuslot_cards(device_slot_interface &device) ATTR_COLD;
+void a2000_cpuslot_cards(device_slot_interface &device) ATTR_COLD;
+
+#endif // MAME_BUS_AMIGA_CPUSLOT_CARDS_H
diff --git a/src/devices/bus/amiga/cpuslot/cpuslot.cpp b/src/devices/bus/amiga/cpuslot/cpuslot.cpp
new file mode 100644
index 00000000000..d0731a9e751
--- /dev/null
+++ b/src/devices/bus/amiga/cpuslot/cpuslot.cpp
@@ -0,0 +1,60 @@
+// license: GPL-2.0+
+// copyright-holders: Dirk Best
+/***************************************************************************
+
+ 86-pin expansion slot (A500, A1000)
+ Coprocessor slot (A2000, B2000)
+
+***************************************************************************/
+
+#include "emu.h"
+#include "cpuslot.h"
+
+
+// type definitions
+DEFINE_DEVICE_TYPE(AMIGA_CPUSLOT, amiga_cpuslot_device, "amiga_cpuslot", "Amiga CPU Expansion Slot")
+
+
+//**************************************************************************
+// SLOT DEVICE
+//**************************************************************************
+
+amiga_cpuslot_device::amiga_cpuslot_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) :
+ device_t(mconfig, AMIGA_CPUSLOT, tag, owner, clock),
+ device_single_card_slot_interface<device_amiga_cpuslot_interface>(mconfig, *this),
+ m_space(*this, finder_base::DUMMY_TAG, -1),
+ m_cfgout_cb(*this),
+ m_ovr_cb(*this),
+ m_int2_cb(*this),
+ m_int6_cb(*this),
+ m_ipl7_cb(*this)
+{
+}
+
+void amiga_cpuslot_device::device_start()
+{
+ m_card = get_card_device();
+}
+
+void amiga_cpuslot_device::cfgin_w(int state)
+{
+ if (m_card)
+ m_card->cfgin_w(state);
+}
+
+void amiga_cpuslot_device::rst_w(int state)
+{
+ if (m_card)
+ m_card->rst_w(state);
+}
+
+
+//**************************************************************************
+// CARD INTERFACE
+//**************************************************************************
+
+device_amiga_cpuslot_interface::device_amiga_cpuslot_interface(const machine_config &mconfig, device_t &device) :
+ device_interface(device, "amiga_cpuslot")
+{
+ m_host = dynamic_cast<amiga_cpuslot_device *>(device.owner());
+}
diff --git a/src/devices/bus/amiga/cpuslot/cpuslot.h b/src/devices/bus/amiga/cpuslot/cpuslot.h
new file mode 100644
index 00000000000..f4184506fe9
--- /dev/null
+++ b/src/devices/bus/amiga/cpuslot/cpuslot.h
@@ -0,0 +1,154 @@
+// license: GPL-2.0+
+// copyright-holders: Dirk Best
+/***************************************************************************
+
+ 86-pin expansion slot (A500, A1000)
+ Coprocessor slot (A2000, B2000)
+
+ 2 Ground 1 Ground
+ 4 Ground 3 Ground
+ 6 +5VDC 5 +5VDC
+ 8 -5VDC 7 N/C
+ 10 +12VDC 9 N/C *1
+ 12 CFGIN 11 N/C *2
+ 14 /C3 Clock 13 Ground
+ 16 /C1 Clock 15 CDAC
+ 18 RDY 17 /OVR
+ 20 N/C *3 19 /INT2
+ 22 /INT6 21 A5
+ 24 A4 23 A6
+ 26 A3 25 Ground
+ 28 A7 27 A2
+ 30 A8 29 A1
+ 32 A9 31 FC0
+ 34 A10 33 FC1
+ 36 A11 35 FC2
+ 38 A12 37 Ground
+ 40 /IPL0 39 A13
+ 42 /IPL1 41 A14
+ 44 /IPL2 43 A15
+ 46 /BERR 45 A16
+ 48 /VPA 47 A17
+ 50 E Clock 49 Ground
+ 52 A18 51 /VMA
+ 54 A19 53 /RST
+ 56 A20 55 /HLT
+ 58 A21 57 A22
+ 60 /BR *4 59 A23
+ 62 /BGACK 61 Ground
+ 64 /BG *5 63 D15
+ 66 /DTACK 65 D14
+ 68 R/W 67 D13
+ 70 /LDS 69 D12
+ 72 /UDS 71 D11
+ 74 /AS 73 Ground
+ 76 D10 75 D0
+ 78 D9 77 D1
+ 80 D8 79 D2
+ 82 D7 81 D3
+ 84 D6 83 D4
+ 86 D5 85 Ground
+
+ *1 28 MHz Clock on A2000 and B2000
+ *2 /COPCFG on B2000
+ *3 /PALOPE on A1000, /BOSS on B2000
+ *4 /CBR on B2000
+ *5 /CBG on B2000
+
+***************************************************************************/
+
+#ifndef MAME_BUS_AMIGA_CPUSLOT_CPUSLOT_H
+#define MAME_BUS_AMIGA_CPUSLOT_CPUSLOT_H
+
+#pragma once
+
+
+// forward declaration
+class device_amiga_cpuslot_interface;
+
+
+//**************************************************************************
+// DEVICE
+//**************************************************************************
+
+class amiga_cpuslot_device : public device_t, public device_single_card_slot_interface<device_amiga_cpuslot_interface>
+{
+public:
+ template <typename T>
+ amiga_cpuslot_device(machine_config const &mconfig, char const *tag, device_t *owner, T &&opts, char const *dflt) :
+ amiga_cpuslot_device(mconfig, tag, owner, 0)
+ {
+ option_reset();
+ opts(*this);
+ set_default_option(dflt);
+ set_fixed(false);
+ }
+
+ amiga_cpuslot_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock = 0);
+
+ // configuration helpers
+ template <class T>
+ void set_space(T &&tag, int spacenum) { m_space.set_tag(std::forward<T>(tag), spacenum); }
+
+ auto cfgout_cb() { return m_cfgout_cb.bind(); }
+ auto ovr_cb() { return m_ovr_cb.bind(); }
+ auto int2_cb() { return m_int2_cb.bind(); }
+ auto int6_cb() { return m_int6_cb.bind(); }
+ auto ipl7_cb() { return m_ipl7_cb.bind(); }
+
+ // from host
+ void cfgin_w(int state);
+ void rst_w(int state);
+
+ // from slot device
+ void int2_w(int state) { m_int2_cb(state); }
+ void int6_w(int state) { m_int6_cb(state); }
+ void ovr_w(int state) { m_ovr_cb(state); }
+ void cfgout_w(int state) { m_cfgout_cb(state); }
+ void ipl7_w(int state) { m_ipl7_cb(state); }
+
+ address_space &space() const { return *m_space; }
+
+protected:
+ virtual void device_start() override ATTR_COLD;
+
+private:
+ device_amiga_cpuslot_interface *m_card;
+
+ required_address_space m_space;
+
+ devcb_write_line m_cfgout_cb;
+ devcb_write_line m_ovr_cb;
+ devcb_write_line m_int2_cb;
+ devcb_write_line m_int6_cb;
+ devcb_write_line m_ipl7_cb;
+};
+
+
+//**************************************************************************
+// INTERFACE
+//**************************************************************************
+
+class device_amiga_cpuslot_interface : public device_interface
+{
+public:
+ // interface (from host)
+ virtual void cfgin_w(int state) { }
+ virtual void rst_w(int state) { }
+
+protected:
+ device_amiga_cpuslot_interface(const machine_config &mconfig, device_t &device);
+
+ amiga_cpuslot_device *m_host;
+};
+
+
+// device type declarations
+DECLARE_DEVICE_TYPE(AMIGA_CPUSLOT, amiga_cpuslot_device)
+
+
+// include this here so that you don't need to include it into every driver that uses zorro slots
+#include "cards.h"
+
+
+#endif // MAME_BUS_AMIGA_CPUSLOT_CPUSLOT_H
diff --git a/src/devices/bus/amiga/cpuslot/megamix500.cpp b/src/devices/bus/amiga/cpuslot/megamix500.cpp
new file mode 100644
index 00000000000..57d6b6f0212
--- /dev/null
+++ b/src/devices/bus/amiga/cpuslot/megamix500.cpp
@@ -0,0 +1,150 @@
+// license: GPL-2.0+
+// copyright-holders: Dirk Best
+/***************************************************************************
+
+ 3-State MegaMix 500
+
+ External RAM expansion for the A500
+
+ TODO: Passthrough
+
+***************************************************************************/
+
+#include "emu.h"
+#include "megamix500.h"
+
+#define VERBOSE (LOG_GENERAL)
+
+#include "logmacro.h"
+
+
+//**************************************************************************
+// DEVICE DEFINITIONS
+//**************************************************************************
+
+DEFINE_DEVICE_TYPE(AMIGA_CPUSLOT_MEGAMIX500, bus::amiga::cpuslot::megamix500_device, "amiga_megamix500", "3-State MegaMix 500")
+
+namespace bus::amiga::cpuslot {
+
+megamix500_device::megamix500_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) :
+ device_t(mconfig, AMIGA_CPUSLOT_MEGAMIX500, tag, owner, clock),
+ device_amiga_cpuslot_interface(mconfig, *this),
+ m_config(*this, "config"),
+ m_ram_size(0)
+{
+}
+
+
+//**************************************************************************
+// INPUT DEFINITIONS
+//**************************************************************************
+
+static INPUT_PORTS_START( megamix500 )
+ PORT_START("config")
+ PORT_CONFNAME(0x03, 0x03, "Installed RAM")
+ PORT_CONFSETTING(0x00, "Disabled")
+ PORT_CONFSETTING(0x01, "2 MB")
+ PORT_CONFSETTING(0x02, "4 MB")
+ PORT_CONFSETTING(0x03, "8 MB")
+INPUT_PORTS_END
+
+ioport_constructor megamix500_device::device_input_ports() const
+{
+ return INPUT_PORTS_NAME( megamix500 );
+}
+
+
+//**************************************************************************
+// MACHINE EMULATION
+//**************************************************************************
+
+void megamix500_device::device_start()
+{
+ // setup ram
+ m_ram = make_unique_clear<uint16_t[]>(0x800000/2);
+
+ // register for save states
+ save_pointer(NAME(m_ram), 0x800000/2);
+ save_item(NAME(m_ram_size));
+ save_item(NAME(m_base_address));
+}
+
+void megamix500_device::rst_w(int state)
+{
+ if (state == 0)
+ {
+ // on reset, remove ram
+ if (m_ram_size > 0)
+ {
+ LOG("unmapping ram, base = %06x\n", m_base_address);
+ m_host->space().unmap_readwrite(m_base_address, m_base_address + (m_ram_size << 20) - 1);
+ }
+
+ m_ram_size = 0;
+ }
+}
+
+
+//**************************************************************************
+// AUTOCONFIG
+//**************************************************************************
+
+void megamix500_device::autoconfig_base_address(offs_t address)
+{
+ LOG("autoconfig_base_address received: 0x%06x\n", address);
+ LOG("-> installing megamix500\n");
+
+ m_base_address = address;
+
+ m_host->space().unmap_readwrite(0xe80000, 0xe8007f);
+ m_host->space().install_ram(address, address + (m_ram_size << 20) - 1, m_ram.get());
+
+ m_host->cfgout_w(0);
+}
+
+void megamix500_device::cfgin_w(int state)
+{
+ LOG("cfgin_w: %d\n", state);
+
+ uint8_t cfg = m_config->read();
+
+ if (state == 0 && cfg)
+ {
+ // setup autoconfig
+ autoconfig_board_type(BOARD_TYPE_ZORRO2);
+
+ // setup ram
+ switch (cfg)
+ {
+ case 1:
+ autoconfig_board_size(BOARD_SIZE_2M);
+ m_ram_size = 0x200000 >> 20;
+ break;
+ case 2:
+ autoconfig_board_size(BOARD_SIZE_4M);
+ m_ram_size = 0x400000 >> 20;
+ break;
+ case 3:
+ autoconfig_board_size(BOARD_SIZE_8M);
+ m_ram_size = 0x800000 >> 20;
+ break;
+ }
+
+ autoconfig_product(2);
+ autoconfig_manufacturer(512);
+ autoconfig_serial(0x00000000);
+
+ autoconfig_link_into_memory(true);
+ autoconfig_rom_vector_valid(false);
+ autoconfig_multi_device(false);
+ autoconfig_8meg_preferred(false);
+ autoconfig_can_shutup(true); // ?
+
+ // install autoconfig handler
+ m_host->space().install_readwrite_handler(0xe80000, 0xe8007f,
+ read16_delegate(*this, FUNC(amiga_autoconfig::autoconfig_read)),
+ write16_delegate(*this, FUNC(amiga_autoconfig::autoconfig_write)), 0xffff);
+ }
+}
+
+} // namespace bus::amiga::cpuslot
diff --git a/src/devices/bus/amiga/cpuslot/megamix500.h b/src/devices/bus/amiga/cpuslot/megamix500.h
new file mode 100644
index 00000000000..c54e2c83659
--- /dev/null
+++ b/src/devices/bus/amiga/cpuslot/megamix500.h
@@ -0,0 +1,51 @@
+// license: GPL-2.0+
+// copyright-holders: Dirk Best
+/***************************************************************************
+
+ 3-State MegaMix 500
+
+ External RAM expansion for the A500
+
+***************************************************************************/
+
+#ifndef MAME_BUS_AMIGA_CPUSLOT_MEGAMIX500_H
+#define MAME_BUS_AMIGA_CPUSLOT_MEGAMIX500_H
+
+#pragma once
+
+#include "cpuslot.h"
+#include "machine/autoconfig.h"
+
+
+namespace bus::amiga::cpuslot {
+
+class megamix500_device : public device_t, public device_amiga_cpuslot_interface, public amiga_autoconfig
+{
+public:
+ megamix500_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
+
+protected:
+ virtual ioport_constructor device_input_ports() const override ATTR_COLD;
+ virtual void device_start() override ATTR_COLD;
+
+ // device_cpuslot_interface overrides
+ virtual void cfgin_w(int state) override;
+ virtual void rst_w(int state) override;
+
+ // amiga_autoconfig overrides
+ virtual void autoconfig_base_address(offs_t address) override;
+
+private:
+ required_ioport m_config;
+
+ std::unique_ptr<uint16_t[]> m_ram;
+ uint8_t m_ram_size;
+ offs_t m_base_address;
+};
+
+} // namespace bus::amiga::cpuslot
+
+// device type declaration
+DECLARE_DEVICE_TYPE_NS(AMIGA_CPUSLOT_MEGAMIX500, bus::amiga::cpuslot, megamix500_device)
+
+#endif // MAME_BUS_AMIGA_CPUSLOT_MEGAMIX500_H
diff --git a/src/devices/bus/amiga/keyboard/a1200.cpp b/src/devices/bus/amiga/keyboard/a1200.cpp
index 5534e07c15d..70222635578 100644
--- a/src/devices/bus/amiga/keyboard/a1200.cpp
+++ b/src/devices/bus/amiga/keyboard/a1200.cpp
@@ -47,6 +47,8 @@
#include "a1200.h"
#include "matrix.h"
+#include "cpu/m6805/m68hc05.h"
+
//#define VERBOSE 1
#include "logmacro.h"
@@ -55,11 +57,11 @@
// GLOBAL VARIABLES
//**************************************************************************
-DEFINE_DEVICE_TYPE_NS(A1200_KBD, bus::amiga::keyboard, a1200_kbd_device, "a1200kbd_rb", "Amiga 1200 Keyboard Rev B")
+DEFINE_DEVICE_TYPE(A1200_KBD, bus::amiga::keyboard::a1200_kbd_device, "a1200kbd_rb", "Amiga 1200 Keyboard Rev B")
-namespace bus { namespace amiga { namespace keyboard {
+namespace bus::amiga::keyboard {
namespace {
@@ -81,7 +83,7 @@ INPUT_PORTS_START(a1200_us_keyboard)
// FIXME: split compact mode into a separate device without the numeric keypad
PORT_START("IRQ")
- PORT_CONFNAME(0x01, 0x01, "Layout") PORT_CHANGED_MEMBER(DEVICE_SELF, a1200_kbd_device, layout_changed, 0)
+ PORT_CONFNAME(0x01, 0x01, "Layout") PORT_CHANGED_MEMBER(DEVICE_SELF, FUNC(a1200_kbd_device::layout_changed), 0)
PORT_CONFSETTING(0x01, "Full Size")
PORT_CONFSETTING(0x00, "Compact")
INPUT_PORTS_END
@@ -105,13 +107,14 @@ a1200_kbd_device::a1200_kbd_device(machine_config const &mconfig, char const *ta
, device_amiga_keyboard_interface(mconfig, *this)
, m_rows(*this, "ROW%u", 0)
, m_mpu(*this, "mpu")
+ , m_led_kbd_caps(*this, "led_kbd_caps")
, m_row_drive(0xffff)
, m_host_kdat(true)
, m_mpu_kdat(true)
{
}
-WRITE_LINE_MEMBER(a1200_kbd_device::kdat_w)
+void a1200_kbd_device::kdat_w(int state)
{
if (bool(state) != m_host_kdat)
{
@@ -127,7 +130,7 @@ INPUT_CHANGED_MEMBER(a1200_kbd_device::layout_changed)
m_mpu->set_input_line(M68HC05_IRQ_LINE, newval ? CLEAR_LINE : ASSERT_LINE);
}
-READ8_MEMBER(a1200_kbd_device::mpu_portb_r)
+u8 a1200_kbd_device::mpu_portb_r()
{
u8 result(m_host_kdat ? 0xff : 0xfe);
for (unsigned row = 0; m_rows.size() > row; ++row)
@@ -138,12 +141,12 @@ READ8_MEMBER(a1200_kbd_device::mpu_portb_r)
return result;
}
-WRITE8_MEMBER(a1200_kbd_device::mpu_porta_w)
+void a1200_kbd_device::mpu_porta_w(offs_t offset, u8 data, u8 mem_mask)
{
m_row_drive = (m_row_drive & 0xff00) | u16(u8(data | ~mem_mask));
}
-WRITE8_MEMBER(a1200_kbd_device::mpu_portb_w)
+void a1200_kbd_device::mpu_portb_w(offs_t offset, u8 data, u8 mem_mask)
{
u8 const kdat(BIT(data, 0) | BIT(~mem_mask, 0));
m_host->kdat_w(kdat ? 1 : 0);
@@ -158,26 +161,26 @@ WRITE8_MEMBER(a1200_kbd_device::mpu_portb_w)
}
}
-WRITE8_MEMBER(a1200_kbd_device::mpu_portc_w)
+void a1200_kbd_device::mpu_portc_w(offs_t offset, u8 data, u8 mem_mask)
{
m_row_drive = (m_row_drive & 0x80ff) | (u16(u8(data | ~mem_mask) & 0x7f) << 8);
- machine().output().set_value("led_kbd_caps", BIT(~data, 7));
+ 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);
}
void a1200_kbd_device::device_add_mconfig(machine_config &config)
{
- M68HC705C8A(config, m_mpu, XTAL(3'000'000));
- m_mpu->port_r<1>().set(FUNC(a1200_kbd_device::mpu_portb_r));
- m_mpu->port_r<3>().set_ioport("MOD");
- m_mpu->port_w<0>().set(FUNC(a1200_kbd_device::mpu_porta_w));
- m_mpu->port_w<1>().set(FUNC(a1200_kbd_device::mpu_portb_w));
- m_mpu->port_w<2>().set(FUNC(a1200_kbd_device::mpu_portc_w));
- m_mpu->tcmp().set(FUNC(a1200_kbd_device::mpu_tcmp));
+ m68hc705c8a_device &mpu(M68HC705C8A(config, m_mpu, XTAL(3'000'000)));
+ mpu.portb_r().set(FUNC(a1200_kbd_device::mpu_portb_r));
+ mpu.portd_r().set_ioport("MOD");
+ mpu.porta_w().set(FUNC(a1200_kbd_device::mpu_porta_w));
+ mpu.portb_w().set(FUNC(a1200_kbd_device::mpu_portb_w));
+ mpu.portc_w().set(FUNC(a1200_kbd_device::mpu_portc_w));
+ mpu.tcmp().set(FUNC(a1200_kbd_device::mpu_tcmp));
}
tiny_rom_entry const *a1200_kbd_device::device_rom_region() const
@@ -192,6 +195,8 @@ ioport_constructor a1200_kbd_device::device_input_ports() const
void a1200_kbd_device::device_start()
{
+ m_led_kbd_caps.resolve();
+
save_item(NAME(m_row_drive));
save_item(NAME(m_host_kdat));
save_item(NAME(m_mpu_kdat));
@@ -206,4 +211,4 @@ void a1200_kbd_device::device_reset_after_children()
m_mpu->set_input_line(M68HC05_IRQ_LINE, BIT(ioport("IRQ")->read(), 0) ? CLEAR_LINE : ASSERT_LINE);
}
-} } } // namespace bus::amiga::keyboard
+} // namespace bus::amiga::keyboard
diff --git a/src/devices/bus/amiga/keyboard/a1200.h b/src/devices/bus/amiga/keyboard/a1200.h
index ece885835ae..6329edc7d99 100644
--- a/src/devices/bus/amiga/keyboard/a1200.h
+++ b/src/devices/bus/amiga/keyboard/a1200.h
@@ -11,11 +11,10 @@
#pragma once
-#include "cpu/m6805/m68hc05.h"
#include "keyboard.h"
-namespace bus { namespace amiga { namespace keyboard {
+namespace bus::amiga::keyboard {
//**************************************************************************
// TYPE DECLARATIONS
@@ -28,34 +27,35 @@ 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);
protected:
// MPU I/O
- DECLARE_READ8_MEMBER(mpu_portb_r);
- DECLARE_WRITE8_MEMBER(mpu_porta_w);
- DECLARE_WRITE8_MEMBER(mpu_portb_w);
- DECLARE_WRITE8_MEMBER(mpu_portc_w);
- DECLARE_WRITE_LINE_MEMBER(mpu_tcmp);
+ u8 mpu_portb_r();
+ 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);
+ void mpu_tcmp(int state);
- virtual tiny_rom_entry const *device_rom_region() const override;
- virtual void device_add_mconfig(machine_config &config) override;
- virtual ioport_constructor device_input_ports() const override;
+ virtual tiny_rom_entry const *device_rom_region() const override ATTR_COLD;
+ virtual void device_add_mconfig(machine_config &config) override ATTR_COLD;
+ virtual ioport_constructor device_input_ports() const override ATTR_COLD;
- virtual void device_start() override;
+ virtual void device_start() override ATTR_COLD;
virtual void device_reset_after_children() override;
private:
required_ioport_array<15> m_rows;
- required_device<m68hc705c8a_device> m_mpu;
+ required_device<cpu_device> m_mpu;
+ output_finder<> m_led_kbd_caps;
u16 m_row_drive;
bool m_host_kdat, m_mpu_kdat;
};
-} } } // namespace bus::amiga::keyboard
+} // namespace bus::amiga::keyboard
//**************************************************************************
diff --git a/src/devices/bus/amiga/keyboard/a2000.cpp b/src/devices/bus/amiga/keyboard/a2000.cpp
index 4cc9141947b..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)
@@ -70,21 +69,147 @@
#define LOGSCAN(...) LOGMASKED(LOG_SCAN, __VA_ARGS__)
+namespace {
+
//**************************************************************************
-// GLOBAL VARIABLES
+// ROM DEFINITIONS
//**************************************************************************
-DEFINE_DEVICE_TYPE_NS(A2000_KBD_G80_US, bus::amiga::keyboard, a2000_kbd_g80_us_device, "a2000kbd_g80_us", "Amiga 2000 Keyboard (Cherry - U.S./Canada)")
-DEFINE_DEVICE_TYPE_NS(A2000_KBD_G80_DE, bus::amiga::keyboard, a2000_kbd_g80_de_device, "a2000kbd_g80_de", "Amiga 2000 Keyboard (Cherry - Germany/Austria)")
-DEFINE_DEVICE_TYPE_NS(A2000_KBD_G80_SE, bus::amiga::keyboard, a2000_kbd_g80_se_device, "a2000kbd_g80_se", "Amiga 2000 Keyboard (Cherry - Sweden/Finland)")
-DEFINE_DEVICE_TYPE_NS(A2000_KBD_G80_DK, bus::amiga::keyboard, a2000_kbd_g80_dk_device, "a2000kbd_g80_dk", "Amiga 2000 Keyboard (Cherry - Denmark)")
-DEFINE_DEVICE_TYPE_NS(A2000_KBD_G80_GB, bus::amiga::keyboard, a2000_kbd_g80_gb_device, "a2000kbd_g80_gb", "Amiga 2000 Keyboard (Cherry - UK)")
+ROM_START(a2000kbd)
+ ROM_REGION(0x0800, "mcu", 0)
+ ROM_LOAD("467.u4", 0x0000, 0x0800, CRC(fb92a773) SHA1(e787dc05de227f30a47ac5b9ee7a355c2e9e693b))
+ROM_END
+//**************************************************************************
+// KEYBOARD BASE CLASSES
+//**************************************************************************
-namespace bus { namespace amiga { namespace keyboard {
+class a2000_kbd_g80_device : public device_t, public device_amiga_keyboard_interface
+{
+public:
+ // from host
+ virtual void kdat_w(int state) override
+ {
+ if (bool(state) != m_host_kdat)
+ {
+ LOGCOMM("host DATA %u -> %u\n", m_host_kdat ? 1 : 0, state ? 1 : 0);
+ m_host_kdat = bool(state);
+ if (m_mcu_kdat)
+ m_mcu->set_input_line(MCS48_INPUT_IRQ, state ? CLEAR_LINE : ASSERT_LINE);
+ }
+ }
-namespace {
+protected:
+ // construction/destruction
+ a2000_kbd_g80_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_amiga_keyboard_interface(mconfig, *this)
+ , m_rows(*this, "ROW%u", 0U)
+ , m_mcu(*this, "u1")
+ , m_led_kbd_caps(*this, "led_kbd_caps")
+ {
+ }
+
+ // MCU I/O
+ u8 mcu_bus_r(offs_t offset)
+ {
+ // when jumpered for external ROM, offset latched by U2 is 0x60 + (row << 1)
+ uint8_t result(0U);
+ for (unsigned i = 0U; m_rows.size() > i; ++i)
+ {
+ if (BIT(m_row_drive, i))
+ result |= uint8_t(m_rows[i]->read());
+ }
+ LOGSCAN("read bus: offset = %02X, row drive = %04X\n, result = %02X", offset, m_row_drive, result);
+ return result;
+ }
+
+ void mcu_p1_w(u8 data)
+ {
+ m_row_drive = (m_row_drive & 0x1f00U) | uint16_t(data);
+ }
+
+ void mcu_p2_w(u8 data)
+ {
+ m_row_drive = (m_row_drive & 0x00ffU) | (uint16_t(data & 0x1fU) << 8);
+
+ m_led_kbd_caps = BIT(~data, 5);
+
+ if (bool(BIT(data, 6) != m_mcu_kdat))
+ {
+ m_mcu_kdat = BIT(data, 6);
+ LOGCOMM("keyboard DATA %u -> %u\n", m_mcu_kdat ? 0U : 1U, m_mcu_kdat ? 1U : 0U);
+ m_host->kdat_w(m_mcu_kdat ? 1 : 0);
+ if (m_host_kdat)
+ m_mcu->set_input_line(MCS48_INPUT_IRQ, m_mcu_kdat ? CLEAR_LINE : ASSERT_LINE);
+ }
+
+ if (bool(BIT(data, 7) != m_mcu_kclk))
+ {
+ m_mcu_kclk = BIT(data, 7);
+ LOGCOMM("keyboard CLOCK %u -> %u\n", m_mcu_kclk ? 0U : 1U, m_mcu_kclk ? 1U : 0U);
+ m_host->kclk_w(m_mcu_kclk ? 1 : 0);
+ }
+ }
+
+ virtual const tiny_rom_entry *device_rom_region() const override
+ {
+ return ROM_NAME(a2000kbd);
+ }
+
+ virtual void device_add_mconfig(machine_config &config) override
+ {
+ auto &mcu(I8039(config, "u1", 6_MHz_XTAL));
+ mcu.set_addrmap(AS_PROGRAM, &a2000_kbd_g80_device::program_map);
+ mcu.set_addrmap(AS_IO, &a2000_kbd_g80_device::ext_map);
+ mcu.p1_out_cb().set(FUNC(a2000_kbd_g80_device::mcu_p1_w));
+ mcu.p2_out_cb().set(FUNC(a2000_kbd_g80_device::mcu_p2_w));
+ mcu.bus_in_cb().set(FUNC(a2000_kbd_g80_device::mcu_bus_r));
+ mcu.t0_in_cb().set_constant(1);
+ mcu.t1_in_cb().set([this] () { return m_mcu_kclk ? 1 : 0; });
+ }
+
+ virtual void device_start() override
+ {
+ m_led_kbd_caps.resolve();
+
+ save_item(NAME(m_row_drive));
+ save_item(NAME(m_host_kdat));
+ save_item(NAME(m_mcu_kdat));
+ save_item(NAME(m_mcu_kclk));
+
+ m_row_drive = 0U;
+ m_host_kdat = true;
+ m_mcu_kdat = true;
+ m_mcu_kclk = true;
+ }
+
+ void program_map(address_map &map)
+ {
+ map.global_mask(0x07ff);
+ map(0x0000, 0x07ff).rom().region("mcu", 0);
+ }
+
+ void ext_map(address_map &map)
+ {
+ map.global_mask(0x00ff);
+ map(0x0000, 0x00ff).r(FUNC(a2000_kbd_g80_device::mcu_bus_r));
+ }
+
+private:
+ required_ioport_array<13> m_rows;
+ required_device<cpu_device> m_mcu;
+ output_finder<> m_led_kbd_caps;
+
+ uint16_t m_row_drive = 0U;
+ bool m_host_kdat = true, m_mcu_kdat = true, m_mcu_kclk = true;
+};
+
+
+//**************************************************************************
+// COMMON PORT DEFINITIONS
+//**************************************************************************
INPUT_PORTS_START(a2000_common_keyboard)
PORT_START("ROW0")
@@ -169,41 +294,46 @@ INPUT_PORTS_START(a2000_common_keyboard)
PORT_BIT(0x80, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CODE(KEYCODE_DOWN) PORT_CHAR(UCHAR_MAMEKEY(DOWN))
INPUT_PORTS_END
+
+//**************************************************************************
+// SPECIFIC KEYBOARD PORT DEFINITIONS
+//**************************************************************************
+
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 (")
@@ -211,459 +341,372 @@ 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
-ROM_START(a2000kbd)
- ROM_REGION(0x0800, "mcu", 0)
- ROM_LOAD("467.u4", 0x0000, 0x0800, CRC(fb92a773) SHA1(e787dc05de227f30a47ac5b9ee7a355c2e9e693b))
-ROM_END
-
-} // anonymous namespace
-
-
-
//**************************************************************************
-// LIVE DEVICE
+// SPECIFIC KEYBOARD CLASSES
//**************************************************************************
-// ======================> a2000_kbd_g80_device
-
-a2000_kbd_g80_device::a2000_kbd_g80_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_amiga_keyboard_interface(mconfig, *this)
- , m_rows(*this, "ROW%u", 0U)
- , m_mcu(*this, "u1")
- , m_row_drive(0U)
- , m_host_kdat(true)
- , m_mcu_kdat(true)
- , m_mcu_kclk(true)
-{
-}
-
-WRITE_LINE_MEMBER(a2000_kbd_g80_device::kdat_w)
+class a2000_kbd_g80_us_device : public a2000_kbd_g80_device
{
- if (bool(state) != m_host_kdat)
+public:
+ a2000_kbd_g80_us_device(machine_config const &mconfig, char const *tag, device_t *owner, uint32_t clock)
+ : a2000_kbd_g80_device(mconfig, A2000_KBD_G80_US, tag, owner, clock)
{
- LOGCOMM("host DATA %u -> %u\n", m_host_kdat ? 1 : 0, state ? 1 : 0);
- m_host_kdat = bool(state);
- if (m_mcu_kdat)
- m_mcu->set_input_line(MCS48_INPUT_IRQ, state ? CLEAR_LINE : ASSERT_LINE);
}
-}
-READ8_MEMBER(a2000_kbd_g80_device::mcu_bus_r)
-{
- // when jumpered for external ROM, offset latched by U2 is 0x60 + (row << 1)
- uint8_t result(0U);
- for (unsigned i = 0U; m_rows.size() > i; ++i)
+protected:
+ virtual ioport_constructor device_input_ports() const override
{
- if (BIT(m_row_drive, i))
- result |= uint8_t(m_rows[i]->read());
+ return INPUT_PORTS_NAME(a2000_us_keyboard);
}
- LOGSCAN("read bus: offset = %02X, row drive = %04X\n, result = %02X", offset, m_row_drive, result);
- return result;
-}
+};
-WRITE8_MEMBER(a2000_kbd_g80_device::mcu_p1_w)
-{
- m_row_drive = (m_row_drive & 0x1f00U) | uint16_t(data);
-}
-WRITE8_MEMBER(a2000_kbd_g80_device::mcu_p2_w)
+class a2000_kbd_g80_de_device : public a2000_kbd_g80_device
{
- m_row_drive = (m_row_drive & 0x00ffU) | (uint16_t(data & 0x1fU) << 8);
-
- machine().output().set_value("led_kbd_caps", BIT(~data, 5));
-
- if (bool(BIT(data, 6) != m_mcu_kdat))
+public:
+ a2000_kbd_g80_de_device(machine_config const &mconfig, char const *tag, device_t *owner, uint32_t clock)
+ : a2000_kbd_g80_device(mconfig, A2000_KBD_G80_DE, tag, owner, clock)
{
- m_mcu_kdat = BIT(data, 6);
- LOGCOMM("keyboard DATA %u -> %u\n", m_mcu_kdat ? 0U : 1U, m_mcu_kdat ? 1U : 0U);
- m_host->kdat_w(m_mcu_kdat ? 1 : 0);
- if (m_host_kdat)
- m_mcu->set_input_line(MCS48_INPUT_IRQ, m_mcu_kdat ? CLEAR_LINE : ASSERT_LINE);
}
- if (bool(BIT(data, 7) != m_mcu_kclk))
+ static auto parent_rom_device_type() { return &A2000_KBD_G80_US; }
+
+protected:
+ virtual ioport_constructor device_input_ports() const override
{
- m_mcu_kclk = BIT(data, 7);
- LOGCOMM("keyboard CLOCK %u -> %u\n", m_mcu_kclk ? 0U : 1U, m_mcu_kclk ? 1U : 0U);
- m_host->kclk_w(m_mcu_kclk ? 1 : 0);
+ return INPUT_PORTS_NAME(a2000_de_keyboard);
}
-}
-
-tiny_rom_entry const *a2000_kbd_g80_device::device_rom_region() const
-{
- return ROM_NAME(a2000kbd);
-}
-
-void a2000_kbd_g80_device::device_add_mconfig(machine_config &config)
-{
- auto &mcu(I8039(config, "u1", 6_MHz_XTAL));
- mcu.set_addrmap(AS_PROGRAM, &a2000_kbd_g80_device::program_map);
- mcu.set_addrmap(AS_IO, &a2000_kbd_g80_device::ext_map);
- mcu.p1_out_cb().set(FUNC(a2000_kbd_g80_device::mcu_p1_w));
- mcu.p2_out_cb().set(FUNC(a2000_kbd_g80_device::mcu_p2_w));
- mcu.bus_in_cb().set(FUNC(a2000_kbd_g80_device::mcu_bus_r));
- mcu.t0_in_cb().set_constant(1);
- mcu.t1_in_cb().set([this] () { return m_mcu_kclk ? 1 : 0; });
-}
-
-void a2000_kbd_g80_device::device_start()
-{
- save_item(NAME(m_row_drive));
- save_item(NAME(m_host_kdat));
- save_item(NAME(m_mcu_kdat));
- save_item(NAME(m_mcu_kclk));
-
- m_row_drive = 0U;
- m_host_kdat = true;
- m_mcu_kdat = true;
- m_mcu_kclk = true;
-}
-
-void a2000_kbd_g80_device::device_reset()
-{
-}
-
-void a2000_kbd_g80_device::program_map(address_map &map)
-{
- map.global_mask(0x07ff);
- map(0x0000, 0x07ff).rom().region("mcu", 0);
-}
-
-void a2000_kbd_g80_device::ext_map(address_map &map)
-{
- map.global_mask(0x00ff);
- map(0x0000, 0x00ff).r(FUNC(a2000_kbd_g80_device::mcu_bus_r));
-}
-
+};
-// ======================> a2000_kbd_g80_us_device
-a2000_kbd_g80_us_device::a2000_kbd_g80_us_device(machine_config const &mconfig, char const *tag, device_t *owner, uint32_t clock)
- : a2000_kbd_g80_device(mconfig, A2000_KBD_G80_US, tag, owner, clock)
+class a2000_kbd_g80_se_device : public a2000_kbd_g80_device
{
-}
-
-ioport_constructor a2000_kbd_g80_us_device::device_input_ports() const
-{
- return INPUT_PORTS_NAME(a2000_us_keyboard);
-}
+public:
+ a2000_kbd_g80_se_device(machine_config const &mconfig, char const *tag, device_t *owner, uint32_t clock)
+ : a2000_kbd_g80_device(mconfig, A2000_KBD_G80_SE, tag, owner, clock)
+ {
+ }
+ static auto parent_rom_device_type() { return &A2000_KBD_G80_US; }
-// ======================> a2000_kbd_g80_de_device
+protected:
+ virtual ioport_constructor device_input_ports() const override
+ {
+ return INPUT_PORTS_NAME(a2000_se_keyboard);
+ }
+};
-a2000_kbd_g80_de_device::a2000_kbd_g80_de_device(machine_config const &mconfig, char const *tag, device_t *owner, uint32_t clock)
- : a2000_kbd_g80_device(mconfig, A2000_KBD_G80_DE, tag, owner, clock)
-{
-}
-ioport_constructor a2000_kbd_g80_de_device::device_input_ports() const
+class a2000_kbd_g80_dk_device : public a2000_kbd_g80_device
{
- return INPUT_PORTS_NAME(a2000_de_keyboard);
-}
+public:
+ a2000_kbd_g80_dk_device(machine_config const &mconfig, char const *tag, device_t *owner, uint32_t clock)
+ : a2000_kbd_g80_device(mconfig, A2000_KBD_G80_DK, tag, owner, clock)
+ {
+ }
+ static auto parent_rom_device_type() { return &A2000_KBD_G80_US; }
-// ======================> a2000_kbd_g80_se_device
+protected:
+ virtual ioport_constructor device_input_ports() const override
+ {
+ return INPUT_PORTS_NAME(a2000_dk_keyboard);
+ }
+};
-a2000_kbd_g80_se_device::a2000_kbd_g80_se_device(machine_config const &mconfig, char const *tag, device_t *owner, uint32_t clock)
- : a2000_kbd_g80_device(mconfig, A2000_KBD_G80_SE, tag, owner, clock)
-{
-}
-ioport_constructor a2000_kbd_g80_se_device::device_input_ports() const
+class a2000_kbd_g80_gb_device : public a2000_kbd_g80_device
{
- return INPUT_PORTS_NAME(a2000_se_keyboard);
-}
-
-
-// ======================> a2000_kbd_g80_dk_device
+public:
+ a2000_kbd_g80_gb_device(machine_config const &mconfig, char const *tag, device_t *owner, uint32_t clock)
+ : a2000_kbd_g80_device(mconfig, A2000_KBD_G80_GB, tag, owner, clock)
+ {
+ }
-a2000_kbd_g80_dk_device::a2000_kbd_g80_dk_device(machine_config const &mconfig, char const *tag, device_t *owner, uint32_t clock)
- : a2000_kbd_g80_device(mconfig, A2000_KBD_G80_DK, tag, owner, clock)
-{
-}
+ static auto parent_rom_device_type() { return &A2000_KBD_G80_US; }
-ioport_constructor a2000_kbd_g80_dk_device::device_input_ports() const
-{
- return INPUT_PORTS_NAME(a2000_dk_keyboard);
-}
+protected:
+ virtual ioport_constructor device_input_ports() const override
+ {
+ return INPUT_PORTS_NAME(a2000_gb_keyboard);
+ }
+};
+} // anonymous namespace
-// ======================> a2000_kbd_g80_gb_device
-a2000_kbd_g80_gb_device::a2000_kbd_g80_gb_device(machine_config const &mconfig, char const *tag, device_t *owner, uint32_t clock)
- : a2000_kbd_g80_device(mconfig, A2000_KBD_G80_GB, tag, owner, clock)
-{
-}
-ioport_constructor a2000_kbd_g80_gb_device::device_input_ports() const
-{
- return INPUT_PORTS_NAME(a2000_gb_keyboard);
-}
+//**************************************************************************
+// GLOBAL VARIABLES
+//**************************************************************************
-} } } // namespace bus::amiga::keyboard
+DEFINE_DEVICE_TYPE_PRIVATE(A2000_KBD_G80_US, device_amiga_keyboard_interface, a2000_kbd_g80_us_device, "a2000kbd_g80_us", "Amiga 2000 Keyboard (Cherry - U.S./Canada)")
+DEFINE_DEVICE_TYPE_PRIVATE(A2000_KBD_G80_DE, device_amiga_keyboard_interface, a2000_kbd_g80_de_device, "a2000kbd_g80_de", "Amiga 2000 Keyboard (Cherry - Germany/Austria)")
+DEFINE_DEVICE_TYPE_PRIVATE(A2000_KBD_G80_SE, device_amiga_keyboard_interface, a2000_kbd_g80_se_device, "a2000kbd_g80_se", "Amiga 2000 Keyboard (Cherry - Sweden/Finland)")
+DEFINE_DEVICE_TYPE_PRIVATE(A2000_KBD_G80_DK, device_amiga_keyboard_interface, a2000_kbd_g80_dk_device, "a2000kbd_g80_dk", "Amiga 2000 Keyboard (Cherry - Denmark)")
+DEFINE_DEVICE_TYPE_PRIVATE(A2000_KBD_G80_GB, device_amiga_keyboard_interface, a2000_kbd_g80_gb_device, "a2000kbd_g80_gb", "Amiga 2000 Keyboard (Cherry - UK)")
diff --git a/src/devices/bus/amiga/keyboard/a2000.h b/src/devices/bus/amiga/keyboard/a2000.h
index 900d47c5cc2..fa698853159 100644
--- a/src/devices/bus/amiga/keyboard/a2000.h
+++ b/src/devices/bus/amiga/keyboard/a2000.h
@@ -13,113 +13,14 @@
#include "keyboard.h"
-
-namespace bus { namespace amiga { namespace keyboard {
-
-//**************************************************************************
-// TYPE DECLARATIONS
-//**************************************************************************
-
-// ======================> a2000_kbd_g80_device
-
-class a2000_kbd_g80_device : public device_t, public device_amiga_keyboard_interface
-{
-public:
- // from host
- virtual DECLARE_WRITE_LINE_MEMBER(kdat_w) override;
-
-protected:
- // construction/destruction
- a2000_kbd_g80_device(machine_config const &mconfig, device_type type, char const *tag, device_t *owner, uint32_t clock);
-
- // MCU I/O
- DECLARE_READ8_MEMBER(mcu_bus_r);
- DECLARE_WRITE8_MEMBER(mcu_p1_w);
- DECLARE_WRITE8_MEMBER(mcu_p2_w);
-
- 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;
-
- void program_map(address_map &map);
- void ext_map(address_map &map);
-
-private:
- required_ioport_array<13> m_rows;
- required_device<cpu_device> m_mcu;
-
- uint16_t m_row_drive;
- bool m_host_kdat, m_mcu_kdat, m_mcu_kclk;
-};
-
-// ======================> a2000_kbd_g80_us_device
-
-class a2000_kbd_g80_us_device : public a2000_kbd_g80_device
-{
-public:
- a2000_kbd_g80_us_device(machine_config const &mconfig, char const *tag, device_t *owner, uint32_t clock);
-
-protected:
- virtual ioport_constructor device_input_ports() const override;
-};
-
-// ======================> a2000_kbd_g80_de_device
-
-class a2000_kbd_g80_de_device : public a2000_kbd_g80_device
-{
-public:
- a2000_kbd_g80_de_device(machine_config const &mconfig, char const *tag, device_t *owner, uint32_t clock);
-
-protected:
- virtual ioport_constructor device_input_ports() const override;
-};
-
-// ======================> a2000_kbd_g80_se_device
-
-class a2000_kbd_g80_se_device : public a2000_kbd_g80_device
-{
-public:
- a2000_kbd_g80_se_device(machine_config const &mconfig, char const *tag, device_t *owner, uint32_t clock);
-
-protected:
- virtual ioport_constructor device_input_ports() const override;
-};
-
-// ======================> a2000_kbd_g80_dk_device
-
-class a2000_kbd_g80_dk_device : public a2000_kbd_g80_device
-{
-public:
- a2000_kbd_g80_dk_device(machine_config const &mconfig, char const *tag, device_t *owner, uint32_t clock);
-
-protected:
- virtual ioport_constructor device_input_ports() const override;
-};
-
-// ======================> a2000_kbd_g80_gb_device
-
-class a2000_kbd_g80_gb_device : public a2000_kbd_g80_device
-{
-public:
- a2000_kbd_g80_gb_device(machine_config const &mconfig, char const *tag, device_t *owner, uint32_t clock);
-
-protected:
- virtual ioport_constructor device_input_ports() const override;
-};
-
-} } } // namespace bus::amiga::keyboard
-
-
//**************************************************************************
// GLOBAL VARIABLES
//**************************************************************************
-DECLARE_DEVICE_TYPE_NS(A2000_KBD_G80_US, bus::amiga::keyboard, a2000_kbd_g80_us_device)
-DECLARE_DEVICE_TYPE_NS(A2000_KBD_G80_DE, bus::amiga::keyboard, a2000_kbd_g80_de_device)
-DECLARE_DEVICE_TYPE_NS(A2000_KBD_G80_SE, bus::amiga::keyboard, a2000_kbd_g80_se_device)
-DECLARE_DEVICE_TYPE_NS(A2000_KBD_G80_DK, bus::amiga::keyboard, a2000_kbd_g80_dk_device)
-DECLARE_DEVICE_TYPE_NS(A2000_KBD_G80_GB, bus::amiga::keyboard, a2000_kbd_g80_gb_device)
+DECLARE_DEVICE_TYPE(A2000_KBD_G80_US, device_amiga_keyboard_interface)
+DECLARE_DEVICE_TYPE(A2000_KBD_G80_DE, device_amiga_keyboard_interface)
+DECLARE_DEVICE_TYPE(A2000_KBD_G80_SE, device_amiga_keyboard_interface)
+DECLARE_DEVICE_TYPE(A2000_KBD_G80_DK, device_amiga_keyboard_interface)
+DECLARE_DEVICE_TYPE(A2000_KBD_G80_GB, device_amiga_keyboard_interface)
#endif // MAME_BUS_AMIGA_KEYBOARD_A2000_H
diff --git a/src/devices/bus/amiga/keyboard/keyboard.cpp b/src/devices/bus/amiga/keyboard/keyboard.cpp
index d60ad3256a2..a7c52973239 100644
--- a/src/devices/bus/amiga/keyboard/keyboard.cpp
+++ b/src/devices/bus/amiga/keyboard/keyboard.cpp
@@ -1,5 +1,5 @@
-// license: GPL-2.0+
-// copyright-holders: Dirk Best
+// license:BSD-3-Clause
+// copyright-holders:Dirk Best
/***************************************************************************
Amiga Keyboard Interface
@@ -34,7 +34,7 @@ template class device_finder<device_amiga_keyboard_interface, true>;
amiga_keyboard_bus_device::amiga_keyboard_bus_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) :
device_t(mconfig, AMIGA_KEYBOARD_INTERFACE, tag, owner, clock),
- device_slot_interface(mconfig, *this),
+ device_single_card_slot_interface<device_amiga_keyboard_interface>(mconfig, *this),
m_kbd(nullptr),
m_kclk_handler(*this), m_kdat_handler(*this), m_krst_handler(*this)
{
@@ -55,12 +55,7 @@ amiga_keyboard_bus_device::~amiga_keyboard_bus_device()
void amiga_keyboard_bus_device::device_start()
{
// get connected keyboard
- m_kbd = dynamic_cast<device_amiga_keyboard_interface *>(get_card_device());
-
- // resolve callbacks
- m_kclk_handler.resolve_safe();
- m_kdat_handler.resolve_safe();
- m_krst_handler.resolve_safe();
+ m_kbd = get_card_device();
}
//-------------------------------------------------
@@ -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);
@@ -91,7 +86,7 @@ WRITE_LINE_MEMBER( amiga_keyboard_bus_device::kdat_in_w )
//-------------------------------------------------
device_amiga_keyboard_interface::device_amiga_keyboard_interface(const machine_config &mconfig, device_t &device) :
- device_slot_card_interface(mconfig, device)
+ device_interface(device, "amigakbd")
{
m_host = dynamic_cast<amiga_keyboard_bus_device *>(device.owner());
}
diff --git a/src/devices/bus/amiga/keyboard/keyboard.h b/src/devices/bus/amiga/keyboard/keyboard.h
index 3458ab56912..9eee49da5b2 100644
--- a/src/devices/bus/amiga/keyboard/keyboard.h
+++ b/src/devices/bus/amiga/keyboard/keyboard.h
@@ -1,5 +1,5 @@
-// license: GPL-2.0+
-// copyright-holders: Dirk Best
+// license:BSD-3-Clause
+// copyright-holders:Dirk Best
/***************************************************************************
Amiga Keyboard Interface
@@ -12,8 +12,8 @@
***************************************************************************/
-#ifndef MAME_BUS_AMIGA_KEYBOARD_H
-#define MAME_BUS_AMIGA_KEYBOARD_H
+#ifndef MAME_BUS_AMIGA_KEYBOARD_KEYBOARD_H
+#define MAME_BUS_AMIGA_KEYBOARD_KEYBOARD_H
#pragma once
@@ -27,7 +27,7 @@ class device_amiga_keyboard_interface;
// ======================> amiga_keyboard_bus_device
-class amiga_keyboard_bus_device : public device_t, public device_slot_interface
+class amiga_keyboard_bus_device : public device_t, public device_single_card_slot_interface<device_amiga_keyboard_interface>
{
public:
// construction/destruction
@@ -49,17 +49,17 @@ 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
- virtual void device_start() override;
- virtual void device_reset() override;
+ virtual void device_start() override ATTR_COLD;
+ virtual void device_reset() override ATTR_COLD;
private:
device_amiga_keyboard_interface *m_kbd;
@@ -71,13 +71,13 @@ private:
// ======================> device_amiga_keyboard_interface
-class device_amiga_keyboard_interface : public device_slot_card_interface
+class device_amiga_keyboard_interface : public device_interface
{
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);
@@ -93,4 +93,4 @@ void amiga_keyboard_devices(device_slot_interface &device);
void a500_keyboard_devices(device_slot_interface &device);
void a600_keyboard_devices(device_slot_interface &device);
-#endif // MAME_BUS_AMIGA_KEYBOARD_H
+#endif // MAME_BUS_AMIGA_KEYBOARD_KEYBOARD_H
diff --git a/src/devices/bus/amiga/keyboard/matrix.cpp b/src/devices/bus/amiga/keyboard/matrix.cpp
index 6ff33666fcb..f550fe1aedc 100644
--- a/src/devices/bus/amiga/keyboard/matrix.cpp
+++ b/src/devices/bus/amiga/keyboard/matrix.cpp
@@ -9,7 +9,7 @@
#include "emu.h"
#include "matrix.h"
-namespace bus { namespace amiga { namespace keyboard {
+namespace bus::amiga::keyboard {
namespace {
@@ -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,396 +272,395 @@ 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)
- // FIXME: natural keyboard doesn't play nicely with PORT_CONDITION, but it's an issue with natural keyboard itself
PORT_INCLUDE(matrix_common)
PORT_START("CFG")
@@ -670,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)
@@ -779,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")
@@ -853,4 +852,4 @@ INPUT_PORTS_START(remove_keypad)
PORT_BIT(0x80, IP_ACTIVE_LOW, IPT_UNUSED)
INPUT_PORTS_END
-} } } // namespace bus::amiga::keyboard
+} // namespace bus::amiga::keyboard
diff --git a/src/devices/bus/amiga/keyboard/matrix.h b/src/devices/bus/amiga/keyboard/matrix.h
index 01ab81b1dec..50060d01f22 100644
--- a/src/devices/bus/amiga/keyboard/matrix.h
+++ b/src/devices/bus/amiga/keyboard/matrix.h
@@ -11,7 +11,7 @@
#pragma once
-namespace bus { namespace amiga { namespace keyboard {
+namespace bus::amiga::keyboard {
INPUT_PORTS_EXTERN(matrix_us);
INPUT_PORTS_EXTERN(matrix_de);
@@ -27,6 +27,6 @@ INPUT_PORTS_EXTERN(matrix_gb);
INPUT_PORTS_EXTERN(a1000_keypad);
INPUT_PORTS_EXTERN(remove_keypad);
-} } } // namespace bus::amiga::keyboard
+} // namespace bus::amiga::keyboard
#endif // MAME_BUS_AMIGA_KEYBOARD_MATRIX_H
diff --git a/src/devices/bus/amiga/keyboard/mitsumi.cpp b/src/devices/bus/amiga/keyboard/mitsumi.cpp
index 36837410cc4..f35ca018736 100644
--- a/src/devices/bus/amiga/keyboard/mitsumi.cpp
+++ b/src/devices/bus/amiga/keyboard/mitsumi.cpp
@@ -106,18 +106,18 @@ 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(machine().dummy_space(), 0, m_meta->read());
+ m_mcu->pa_w(m_meta->read());
}
- READ_LINE_MEMBER(kdat_r)
+ int kdat_r()
{
return m_kdat_in ^ 0x01U;
}
- CUSTOM_INPUT_MEMBER(cols_r)
+ ioport_value cols_r()
{
ioport_value result(0xffU);
for (unsigned i = 0U; m_rows.size() > i; ++i)
@@ -128,7 +128,7 @@ public:
return (result >> 2) ^ 0x3fU;
}
- READ_LINE_MEMBER(reset_r)
+ int reset_r()
{
return m_ctrl_a_a;
}
@@ -209,8 +209,8 @@ protected:
{
mitsumi_keyboard_base::device_start();
- m_wd_timeout = machine().scheduler().timer_alloc(timer_expired_delegate(FUNC(mitsumi_watchdog_keyboard_base::wd_timeout), this));
- m_wd_pulse = machine().scheduler().timer_alloc(timer_expired_delegate(FUNC(mitsumi_watchdog_keyboard_base::wd_pulse), this));
+ m_wd_timeout = timer_alloc(FUNC(mitsumi_watchdog_keyboard_base::wd_timeout), this);
+ m_wd_pulse = timer_alloc(FUNC(mitsumi_watchdog_keyboard_base::wd_pulse), this);
m_pd7 = 0x01U;
@@ -230,7 +230,7 @@ protected:
}
private:
- WRITE_LINE_MEMBER(pd7_w)
+ void pd7_w(int state)
{
if (bool(state) != bool(m_pd7))
{
@@ -284,7 +284,7 @@ protected:
{
mitsumi_watchdog_keyboard_base::device_start();
- m_reset_pulse = machine().scheduler().timer_alloc(timer_expired_delegate(FUNC(a500_keyboard_base::reset_pulse), this));
+ m_reset_pulse = timer_alloc(FUNC(a500_keyboard_base::reset_pulse), this);
m_reset_active = 0U;
@@ -344,7 +344,7 @@ protected:
{
mitsumi_keyboard_base::device_start();
- m_reset_pulse = machine().scheduler().timer_alloc(timer_expired_delegate(FUNC(a600_keyboard_base::reset_pulse), this));
+ m_reset_pulse = timer_alloc(FUNC(a600_keyboard_base::reset_pulse), this);
m_reset_trigger = 0U;
m_reset_active = 0U;
@@ -366,7 +366,7 @@ protected:
}
private:
- WRITE_LINE_MEMBER(reset_trigger)
+ void reset_trigger(int state)
{
if (bool(state) != bool(m_reset_trigger))
{
@@ -414,27 +414,27 @@ protected:
INPUT_PORTS_START(fullsize_cols)
PORT_START("COLS")
- PORT_BIT(0xfc, IP_ACTIVE_LOW, IPT_CUSTOM) PORT_CUSTOM_MEMBER(mitsumi_keyboard_base, cols_r)
+ PORT_BIT(0xfc, IP_ACTIVE_LOW, IPT_CUSTOM) PORT_CUSTOM_MEMBER(FUNC(mitsumi_keyboard_base::cols_r))
PORT_BIT(0x02, IP_ACTIVE_LOW, IPT_UNUSED)
- PORT_BIT(0x01, IP_ACTIVE_LOW, IPT_CUSTOM) PORT_READ_LINE_MEMBER(mitsumi_keyboard_base, kdat_r)
+ PORT_BIT(0x01, IP_ACTIVE_LOW, IPT_CUSTOM) PORT_READ_LINE_MEMBER(FUNC(mitsumi_keyboard_base::kdat_r))
INPUT_PORTS_END
INPUT_PORTS_START(compact_cols)
PORT_START("COLS")
- PORT_BIT(0x80, IP_ACTIVE_LOW, IPT_CUSTOM) PORT_READ_LINE_MEMBER(mitsumi_keyboard_base, reset_r)
- PORT_BIT(0x7c, IP_ACTIVE_LOW, IPT_CUSTOM) PORT_CUSTOM_MEMBER(mitsumi_keyboard_base, cols_r)
+ PORT_BIT(0x80, IP_ACTIVE_LOW, IPT_CUSTOM) PORT_READ_LINE_MEMBER(FUNC(mitsumi_keyboard_base::reset_r))
+ PORT_BIT(0x7c, IP_ACTIVE_LOW, IPT_CUSTOM) PORT_CUSTOM_MEMBER(FUNC(mitsumi_keyboard_base::cols_r))
PORT_BIT(0x02, IP_ACTIVE_LOW, IPT_UNUSED)
- PORT_BIT(0x01, IP_ACTIVE_LOW, IPT_CUSTOM) PORT_READ_LINE_MEMBER(mitsumi_keyboard_base, kdat_r)
+ PORT_BIT(0x01, IP_ACTIVE_LOW, IPT_CUSTOM) PORT_READ_LINE_MEMBER(FUNC(mitsumi_keyboard_base::kdat_r))
INPUT_PORTS_END
INPUT_PORTS_START(mitsumi_meta)
PORT_START("META")
PORT_BIT(0x80, IP_ACTIVE_LOW, IPT_UNUSED)
- PORT_BIT(0x40, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_LWIN) PORT_CHAR(UCHAR_MAMEKEY(LWIN)) PORT_NAME("Left Amiga") PORT_CHANGED_MEMBER(DEVICE_SELF, mitsumi_keyboard_base, check_ctrl_a_a, 0)
+ PORT_BIT(0x40, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_LWIN) PORT_CHAR(UCHAR_MAMEKEY(LWIN)) PORT_NAME("Left Amiga") PORT_CHANGED_MEMBER(DEVICE_SELF, FUNC(mitsumi_keyboard_base::check_ctrl_a_a), 0)
PORT_BIT(0x20, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_LALT) PORT_CHAR(UCHAR_MAMEKEY(LALT)) PORT_NAME("Left Alt")
PORT_BIT(0x10, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_LSHIFT) PORT_CHAR(UCHAR_SHIFT_1) PORT_NAME("Left Shift")
- PORT_BIT(0x08, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_LCONTROL) PORT_CHAR(UCHAR_MAMEKEY(LCONTROL)) PORT_NAME("Ctrl") PORT_CHANGED_MEMBER(DEVICE_SELF, mitsumi_keyboard_base, check_ctrl_a_a, 0)
- PORT_BIT(0x04, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_RWIN) PORT_CHAR(UCHAR_MAMEKEY(RWIN)) PORT_NAME("Right Amiga") PORT_CHANGED_MEMBER(DEVICE_SELF, mitsumi_keyboard_base, check_ctrl_a_a, 0)
+ PORT_BIT(0x08, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_LCONTROL) PORT_CHAR(UCHAR_MAMEKEY(LCONTROL)) PORT_NAME("Ctrl") PORT_CHANGED_MEMBER(DEVICE_SELF, FUNC(mitsumi_keyboard_base::check_ctrl_a_a), 0)
+ PORT_BIT(0x04, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_RWIN) PORT_CHAR(UCHAR_MAMEKEY(RWIN)) PORT_NAME("Right Amiga") PORT_CHANGED_MEMBER(DEVICE_SELF, FUNC(mitsumi_keyboard_base::check_ctrl_a_a), 0)
PORT_BIT(0x02, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_RALT) PORT_CHAR(UCHAR_SHIFT_2) PORT_NAME("Right Alt")
PORT_BIT(0x01, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_RSHIFT) PORT_CHAR(UCHAR_MAMEKEY(RSHIFT)) PORT_NAME("Right Shift")
INPUT_PORTS_END
@@ -665,6 +665,8 @@ public:
: a500_keyboard_base(mconfig, A500_KBD_US, tag, owner, clock)
{ }
+ static auto parent_rom_device_type() { return &A2000_KBD_US; }
+
protected:
virtual ioport_constructor device_input_ports() const override { return INPUT_PORTS_NAME(fullsize_us); }
};
@@ -676,6 +678,8 @@ public:
: a500_keyboard_base(mconfig, A500_KBD_DE, tag, owner, clock)
{ }
+ static auto parent_rom_device_type() { return &A2000_KBD_US; }
+
protected:
virtual ioport_constructor device_input_ports() const override { return INPUT_PORTS_NAME(fullsize_de); }
};
@@ -687,6 +691,8 @@ public:
: a500_keyboard_base(mconfig, A500_KBD_FR, tag, owner, clock)
{ }
+ static auto parent_rom_device_type() { return &A2000_KBD_US; }
+
protected:
virtual ioport_constructor device_input_ports() const override { return INPUT_PORTS_NAME(fullsize_fr); }
};
@@ -698,6 +704,8 @@ public:
: a500_keyboard_base(mconfig, A500_KBD_IT, tag, owner, clock)
{ }
+ static auto parent_rom_device_type() { return &A2000_KBD_US; }
+
protected:
virtual ioport_constructor device_input_ports() const override { return INPUT_PORTS_NAME(fullsize_it); }
};
@@ -709,6 +717,8 @@ public:
: a500_keyboard_base(mconfig, A500_KBD_SE, tag, owner, clock)
{ }
+ static auto parent_rom_device_type() { return &A2000_KBD_US; }
+
protected:
virtual ioport_constructor device_input_ports() const override { return INPUT_PORTS_NAME(fullsize_se); }
};
@@ -720,6 +730,8 @@ public:
: a500_keyboard_base(mconfig, A500_KBD_ES, tag, owner, clock)
{ }
+ static auto parent_rom_device_type() { return &A2000_KBD_US; }
+
protected:
virtual ioport_constructor device_input_ports() const override { return INPUT_PORTS_NAME(fullsize_es); }
};
@@ -731,6 +743,8 @@ public:
: a500_keyboard_base(mconfig, A500_KBD_DK, tag, owner, clock)
{ }
+ static auto parent_rom_device_type() { return &A2000_KBD_US; }
+
protected:
virtual ioport_constructor device_input_ports() const override { return INPUT_PORTS_NAME(fullsize_dk); }
};
@@ -742,6 +756,8 @@ public:
: a500_keyboard_base(mconfig, A500_KBD_CH, tag, owner, clock)
{ }
+ static auto parent_rom_device_type() { return &A2000_KBD_US; }
+
protected:
virtual ioport_constructor device_input_ports() const override { return INPUT_PORTS_NAME(fullsize_ch); }
};
@@ -753,6 +769,8 @@ public:
: a500_keyboard_base(mconfig, A500_KBD_NO, tag, owner, clock)
{ }
+ static auto parent_rom_device_type() { return &A2000_KBD_US; }
+
protected:
virtual ioport_constructor device_input_ports() const override { return INPUT_PORTS_NAME(fullsize_no); }
};
@@ -764,6 +782,8 @@ public:
: a500_keyboard_base(mconfig, A500_KBD_GB, tag, owner, clock)
{ }
+ static auto parent_rom_device_type() { return &A2000_KBD_US; }
+
protected:
virtual ioport_constructor device_input_ports() const override { return INPUT_PORTS_NAME(fullsize_gb); }
};
@@ -780,6 +800,8 @@ public:
: a600_keyboard_base(mconfig, A600_KBD_US, tag, owner, clock)
{ }
+ static auto parent_rom_device_type() { return &A2000_KBD_US; }
+
protected:
virtual ioport_constructor device_input_ports() const override { return INPUT_PORTS_NAME(compact_us); }
};
@@ -791,6 +813,8 @@ public:
: a600_keyboard_base(mconfig, A600_KBD_DE, tag, owner, clock)
{ }
+ static auto parent_rom_device_type() { return &A2000_KBD_US; }
+
protected:
virtual ioport_constructor device_input_ports() const override { return INPUT_PORTS_NAME(compact_de); }
};
@@ -802,6 +826,8 @@ public:
: a600_keyboard_base(mconfig, A600_KBD_FR, tag, owner, clock)
{ }
+ static auto parent_rom_device_type() { return &A2000_KBD_US; }
+
protected:
virtual ioport_constructor device_input_ports() const override { return INPUT_PORTS_NAME(compact_fr); }
};
@@ -813,6 +839,8 @@ public:
: a600_keyboard_base(mconfig, A600_KBD_IT, tag, owner, clock)
{ }
+ static auto parent_rom_device_type() { return &A2000_KBD_US; }
+
protected:
virtual ioport_constructor device_input_ports() const override { return INPUT_PORTS_NAME(compact_it); }
};
@@ -824,6 +852,8 @@ public:
: a600_keyboard_base(mconfig, A600_KBD_SE, tag, owner, clock)
{ }
+ static auto parent_rom_device_type() { return &A2000_KBD_US; }
+
protected:
virtual ioport_constructor device_input_ports() const override { return INPUT_PORTS_NAME(compact_se); }
};
@@ -835,6 +865,8 @@ public:
: a600_keyboard_base(mconfig, A600_KBD_ES, tag, owner, clock)
{ }
+ static auto parent_rom_device_type() { return &A2000_KBD_US; }
+
protected:
virtual ioport_constructor device_input_ports() const override { return INPUT_PORTS_NAME(compact_es); }
};
@@ -846,6 +878,8 @@ public:
: a600_keyboard_base(mconfig, A600_KBD_DK, tag, owner, clock)
{ }
+ static auto parent_rom_device_type() { return &A2000_KBD_US; }
+
protected:
virtual ioport_constructor device_input_ports() const override { return INPUT_PORTS_NAME(compact_dk); }
};
@@ -857,6 +891,8 @@ public:
: a600_keyboard_base(mconfig, A600_KBD_CH, tag, owner, clock)
{ }
+ static auto parent_rom_device_type() { return &A2000_KBD_US; }
+
protected:
virtual ioport_constructor device_input_ports() const override { return INPUT_PORTS_NAME(compact_ch); }
};
@@ -868,6 +904,8 @@ public:
: a600_keyboard_base(mconfig, A600_KBD_NO, tag, owner, clock)
{ }
+ static auto parent_rom_device_type() { return &A2000_KBD_US; }
+
protected:
virtual ioport_constructor device_input_ports() const override { return INPUT_PORTS_NAME(compact_no); }
};
@@ -879,6 +917,8 @@ public:
: a600_keyboard_base(mconfig, A600_KBD_GB, tag, owner, clock)
{ }
+ static auto parent_rom_device_type() { return &A2000_KBD_US; }
+
protected:
virtual ioport_constructor device_input_ports() const override { return INPUT_PORTS_NAME(compact_gb); }
};
@@ -906,6 +946,8 @@ public:
: a1000_keyboard_base(mconfig, A1000_KBD_DE, tag, owner, clock)
{ }
+ static auto parent_rom_device_type() { return &A1000_KBD_US; }
+
protected:
virtual ioport_constructor device_input_ports() const override { return INPUT_PORTS_NAME(a1000_de); }
};
@@ -917,6 +959,8 @@ public:
: a1000_keyboard_base(mconfig, A1000_KBD_FR, tag, owner, clock)
{ }
+ static auto parent_rom_device_type() { return &A1000_KBD_US; }
+
protected:
virtual ioport_constructor device_input_ports() const override { return INPUT_PORTS_NAME(a1000_fr); }
};
@@ -928,6 +972,8 @@ public:
: a1000_keyboard_base(mconfig, A1000_KBD_IT, tag, owner, clock)
{ }
+ static auto parent_rom_device_type() { return &A1000_KBD_US; }
+
protected:
virtual ioport_constructor device_input_ports() const override { return INPUT_PORTS_NAME(a1000_it); }
};
@@ -939,6 +985,8 @@ public:
: a1000_keyboard_base(mconfig, A1000_KBD_SE, tag, owner, clock)
{ }
+ static auto parent_rom_device_type() { return &A1000_KBD_US; }
+
protected:
virtual ioport_constructor device_input_ports() const override { return INPUT_PORTS_NAME(a1000_se); }
};
@@ -950,6 +998,8 @@ public:
: a1000_keyboard_base(mconfig, A1000_KBD_DK, tag, owner, clock)
{ }
+ static auto parent_rom_device_type() { return &A1000_KBD_US; }
+
protected:
virtual ioport_constructor device_input_ports() const override { return INPUT_PORTS_NAME(a1000_dk); }
};
@@ -961,6 +1011,8 @@ public:
: a1000_keyboard_base(mconfig, A1000_KBD_GB, tag, owner, clock)
{ }
+ static auto parent_rom_device_type() { return &A1000_KBD_US; }
+
protected:
virtual ioport_constructor device_input_ports() const override { return INPUT_PORTS_NAME(a1000_gb); }
};
@@ -988,6 +1040,8 @@ public:
: mitsumi_watchdog_keyboard_base(mconfig, A2000_KBD_DE, tag, owner, clock)
{ }
+ static auto parent_rom_device_type() { return &A2000_KBD_US; }
+
protected:
virtual ioport_constructor device_input_ports() const override { return INPUT_PORTS_NAME(fullsize_de); }
};
@@ -999,6 +1053,8 @@ public:
: mitsumi_watchdog_keyboard_base(mconfig, A2000_KBD_FR, tag, owner, clock)
{ }
+ static auto parent_rom_device_type() { return &A2000_KBD_US; }
+
protected:
virtual ioport_constructor device_input_ports() const override { return INPUT_PORTS_NAME(fullsize_fr); }
};
@@ -1010,6 +1066,8 @@ public:
: mitsumi_watchdog_keyboard_base(mconfig, A2000_KBD_IT, tag, owner, clock)
{ }
+ static auto parent_rom_device_type() { return &A2000_KBD_US; }
+
protected:
virtual ioport_constructor device_input_ports() const override { return INPUT_PORTS_NAME(fullsize_it); }
};
@@ -1021,6 +1079,8 @@ public:
: mitsumi_watchdog_keyboard_base(mconfig, A2000_KBD_SE, tag, owner, clock)
{ }
+ static auto parent_rom_device_type() { return &A2000_KBD_US; }
+
protected:
virtual ioport_constructor device_input_ports() const override { return INPUT_PORTS_NAME(fullsize_se); }
};
@@ -1032,6 +1092,8 @@ public:
: mitsumi_watchdog_keyboard_base(mconfig, A2000_KBD_ES, tag, owner, clock)
{ }
+ static auto parent_rom_device_type() { return &A2000_KBD_US; }
+
protected:
virtual ioport_constructor device_input_ports() const override { return INPUT_PORTS_NAME(fullsize_es); }
};
@@ -1043,6 +1105,8 @@ public:
: mitsumi_watchdog_keyboard_base(mconfig, A2000_KBD_DK, tag, owner, clock)
{ }
+ static auto parent_rom_device_type() { return &A2000_KBD_US; }
+
protected:
virtual ioport_constructor device_input_ports() const override { return INPUT_PORTS_NAME(fullsize_dk); }
};
@@ -1054,6 +1118,8 @@ public:
: mitsumi_watchdog_keyboard_base(mconfig, A2000_KBD_CH, tag, owner, clock)
{ }
+ static auto parent_rom_device_type() { return &A2000_KBD_US; }
+
protected:
virtual ioport_constructor device_input_ports() const override { return INPUT_PORTS_NAME(fullsize_ch); }
};
@@ -1065,6 +1131,8 @@ public:
: mitsumi_watchdog_keyboard_base(mconfig, A2000_KBD_NO, tag, owner, clock)
{ }
+ static auto parent_rom_device_type() { return &A2000_KBD_US; }
+
protected:
virtual ioport_constructor device_input_ports() const override { return INPUT_PORTS_NAME(fullsize_no); }
};
@@ -1076,6 +1144,8 @@ public:
: mitsumi_watchdog_keyboard_base(mconfig, A2000_KBD_GB, tag, owner, clock)
{ }
+ static auto parent_rom_device_type() { return &A2000_KBD_US; }
+
protected:
virtual ioport_constructor device_input_ports() const override { return INPUT_PORTS_NAME(fullsize_gb); }
};
diff --git a/src/devices/bus/amiga/zorro/a2052.cpp b/src/devices/bus/amiga/zorro/a2052.cpp
index 515c568c019..2fd7f1a09ea 100644
--- a/src/devices/bus/amiga/zorro/a2052.cpp
+++ b/src/devices/bus/amiga/zorro/a2052.cpp
@@ -1,5 +1,5 @@
-// license:GPL-2.0+
-// copyright-holders:Dirk Best
+// license: GPL-2.0+
+// copyright-holders: Dirk Best
/***************************************************************************
Commodore A2052
@@ -11,23 +11,30 @@
#include "emu.h"
#include "a2052.h"
-
-//**************************************************************************
-// CONSTANTS / MACROS
-//**************************************************************************
-
#define VERBOSE 1
+#include "logmacro.h"
//**************************************************************************
// DEVICE DEFINITIONS
//**************************************************************************
-DEFINE_DEVICE_TYPE(A2052, a2052_device, "a2052", "CBM A2052 Fast Memory")
+DEFINE_DEVICE_TYPE(AMIGA_A2052, bus::amiga::zorro::a2052_device, "amiga_a2052", "Commodore A2052 RAM Expansion Card")
+
+namespace bus::amiga::zorro {
+
+a2052_device::a2052_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) :
+ device_t(mconfig, AMIGA_A2052, tag, owner, clock),
+ device_zorro2_card_interface(mconfig, *this),
+ m_config(*this, "config"),
+ m_ram_size(0)
+{
+}
-//-------------------------------------------------
-// input_ports - device-specific input ports
-//-------------------------------------------------
+
+//**************************************************************************
+// INPUT DEFINITIONS
+//**************************************************************************
static INPUT_PORTS_START( a2052 )
PORT_START("config")
@@ -44,56 +51,41 @@ ioport_constructor a2052_device::device_input_ports() const
//**************************************************************************
-// LIVE DEVICE
+// MACHINE EMULATION
//**************************************************************************
-//-------------------------------------------------
-// a2052_device - constructor
-//-------------------------------------------------
-
-a2052_device::a2052_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) :
- device_t(mconfig, A2052, tag, owner, clock),
- device_zorro2_card_interface(mconfig, *this),
- m_config(*this, "config")
-{
-}
-
-//-------------------------------------------------
-// device_start - device-specific startup
-//-------------------------------------------------
-
void a2052_device::device_start()
{
- set_zorro_device();
+ // setup ram
+ m_ram = make_unique_clear<uint16_t[]>(0x200000/2);
+
+ // register for save states
+ save_pointer(NAME(m_ram), 0x200000/2);
}
//**************************************************************************
-// IMPLEMENTATION
+// AUTOCONFIG
//**************************************************************************
void a2052_device::autoconfig_base_address(offs_t address)
{
- if (VERBOSE)
- logerror("%s('%s'): autoconfig_base_address received: 0x%06x\n", shortname(), basetag(), address);
-
- if (VERBOSE)
- logerror("-> installing a2052\n");
+ LOG("%s: autoconfig_base_address received: 0x%06x\n", shortname(), address);
+ LOG("-> installing a2052\n");
// stop responding to default autoconfig
- m_slot->space().unmap_readwrite(0xe80000, 0xe8007f);
+ m_zorro->space().unmap_readwrite(0xe80000, 0xe8007f);
// install access to the rom space
- m_slot->space().install_ram(address, address + m_ram.size()*2 - 1, &m_ram[0]);
+ m_zorro->space().install_ram(address, address + (m_ram_size << 20) - 1, m_ram.get());
// we're done
- m_slot->cfgout_w(0);
+ m_zorro->cfgout_w(0);
}
-WRITE_LINE_MEMBER( a2052_device::cfgin_w )
+void a2052_device::cfgin_w(int state)
{
- if (VERBOSE)
- logerror("%s('%s'): configin_w (%d)\n", shortname(), basetag(), state);
+ LOG("%s: cfgin_w (%d)\n", shortname(), state);
if (state == 0)
{
@@ -105,20 +97,20 @@ WRITE_LINE_MEMBER( a2052_device::cfgin_w )
{
case 0:
autoconfig_board_size(BOARD_SIZE_512K);
- m_ram.resize(0x080000/2);
+ m_ram_size = 0x080000 >> 20;
break;
case 1:
autoconfig_board_size(BOARD_SIZE_1M);
- m_ram.resize(0x100000/2);
+ m_ram_size = 0x100000 >> 20;
break;
case 2:
autoconfig_board_size(BOARD_SIZE_2M);
- m_ram.resize(0x200000/2);
+ m_ram_size = 0x200000 >> 20;
break;
}
- autoconfig_product(0x0a);
- autoconfig_manufacturer(0x0202);
+ autoconfig_product(10);
+ autoconfig_manufacturer(514);
autoconfig_serial(0x00000000);
autoconfig_link_into_memory(true);
@@ -128,8 +120,10 @@ WRITE_LINE_MEMBER( a2052_device::cfgin_w )
autoconfig_can_shutup(true); // ?
// install autoconfig handler
- m_slot->space().install_readwrite_handler(0xe80000, 0xe8007f,
- read16_delegate(FUNC(amiga_autoconfig::autoconfig_read), static_cast<amiga_autoconfig *>(this)),
- write16_delegate(FUNC(amiga_autoconfig::autoconfig_write), static_cast<amiga_autoconfig *>(this)), 0xffff);
+ m_zorro->space().install_readwrite_handler(0xe80000, 0xe8007f,
+ read16_delegate(*this, FUNC(amiga_autoconfig::autoconfig_read)),
+ write16_delegate(*this, FUNC(amiga_autoconfig::autoconfig_write)), 0xffff);
}
}
+
+} // namespace bus::amiga::zorro
diff --git a/src/devices/bus/amiga/zorro/a2052.h b/src/devices/bus/amiga/zorro/a2052.h
index 255b459767d..516babf079a 100644
--- a/src/devices/bus/amiga/zorro/a2052.h
+++ b/src/devices/bus/amiga/zorro/a2052.h
@@ -1,5 +1,5 @@
-// license:GPL-2.0+
-// copyright-holders:Dirk Best
+// license: GPL-2.0+
+// copyright-holders: Dirk Best
/***************************************************************************
Commodore A2052
@@ -17,34 +17,36 @@
#include "machine/autoconfig.h"
+namespace bus::amiga::zorro {
+
//**************************************************************************
// TYPE DEFINITIONS
//**************************************************************************
-// ======================> a2052_device
-
class a2052_device : public device_t, public device_zorro2_card_interface, public amiga_autoconfig
{
public:
- // construction/destruction
a2052_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 ioport_constructor device_input_ports() const override ATTR_COLD;
+ 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;
private:
required_ioport m_config;
- std::vector<uint16_t> m_ram;
+ std::unique_ptr<uint16_t[]> m_ram;
+ int m_ram_size;
};
-// device type definition
-DECLARE_DEVICE_TYPE(A2052, a2052_device)
+} // namespace bus::amiga::zorro
+
+// device type declaration
+DECLARE_DEVICE_TYPE_NS(AMIGA_A2052, bus::amiga::zorro, a2052_device)
#endif // MAME_BUS_AMIGA_ZORRO_A2052_H
diff --git a/src/devices/bus/amiga/zorro/a2058.cpp b/src/devices/bus/amiga/zorro/a2058.cpp
index e8d6e8c28fb..fffead2d2d2 100644
--- a/src/devices/bus/amiga/zorro/a2058.cpp
+++ b/src/devices/bus/amiga/zorro/a2058.cpp
@@ -1,5 +1,5 @@
-// license:GPL-2.0+
-// copyright-holders:Dirk Best
+// license: GPL-2.0+
+// copyright-holders: Dirk Best
/***************************************************************************
Commodore A2058
@@ -11,23 +11,30 @@
#include "emu.h"
#include "a2058.h"
-
-//**************************************************************************
-// CONSTANTS / MACROS
-//**************************************************************************
-
#define VERBOSE 1
+#include "logmacro.h"
//**************************************************************************
// DEVICE DEFINITIONS
//**************************************************************************
-DEFINE_DEVICE_TYPE(A2058, a2058_device, "a2058", "CBM A2058 Fast Memory")
+DEFINE_DEVICE_TYPE(AMIGA_A2058, bus::amiga::zorro::a2058_device, "amiga_a2058", "Commodore A2058 RAM Expansion Card")
+
+namespace bus::amiga::zorro {
+
+a2058_device::a2058_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) :
+ device_t(mconfig, AMIGA_A2058, tag, owner, clock),
+ device_zorro2_card_interface(mconfig, *this),
+ m_config(*this, "config"),
+ m_ram_size(0)
+{
+}
-//-------------------------------------------------
-// input_ports - device-specific input ports
-//-------------------------------------------------
+
+//**************************************************************************
+// INPUT DEFINITIONS
+//**************************************************************************
static INPUT_PORTS_START( a2058 )
PORT_START("config")
@@ -45,25 +52,9 @@ ioport_constructor a2058_device::device_input_ports() const
//**************************************************************************
-// LIVE DEVICE
+// MACHINE EMULATION
//**************************************************************************
-//-------------------------------------------------
-// a2058_device - constructor
-//-------------------------------------------------
-
-a2058_device::a2058_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) :
- device_t(mconfig, A2058, tag, owner, clock),
- device_zorro2_card_interface(mconfig, *this),
- m_config(*this, "config"),
- m_ram_size(0)
-{
-}
-
-//-------------------------------------------------
-// device_start - device-specific startup
-//-------------------------------------------------
-
void a2058_device::device_start()
{
// setup ram
@@ -71,37 +62,31 @@ void a2058_device::device_start()
// register for save states
save_pointer(NAME(m_ram), 0x800000/2);
-
- set_zorro_device();
}
//**************************************************************************
-// IMPLEMENTATION
+// AUTOCONFIG
//**************************************************************************
void a2058_device::autoconfig_base_address(offs_t address)
{
- if (VERBOSE)
- logerror("%s('%s'): autoconfig_base_address received: 0x%06x\n", shortname(), basetag(), address);
-
- if (VERBOSE)
- logerror("-> installing a2058\n");
+ LOG("%s: autoconfig_base_address received: 0x%06x\n", shortname(), address);
+ LOG("-> installing a2058\n");
// stop responding to default autoconfig
- m_slot->space().unmap_readwrite(0xe80000, 0xe8007f);
+ m_zorro->space().unmap_readwrite(0xe80000, 0xe8007f);
// install access to the rom space
- m_slot->space().install_ram(address, address + (m_ram_size << 20) - 1, m_ram.get());
+ m_zorro->space().install_ram(address, address + (m_ram_size << 20) - 1, m_ram.get());
// we're done
- m_slot->cfgout_w(0);
+ m_zorro->cfgout_w(0);
}
-WRITE_LINE_MEMBER( a2058_device::cfgin_w )
+void a2058_device::cfgin_w(int state)
{
- if (VERBOSE)
- logerror("%s('%s'): configin_w (%d)\n", shortname(), basetag(), state);
+ LOG("%s: cfgin_w (%d)\n", shortname(), state);
if (state == 0)
{
@@ -129,8 +114,8 @@ WRITE_LINE_MEMBER( a2058_device::cfgin_w )
return;
}
- autoconfig_product(0x0a);
- autoconfig_manufacturer(0x0202);
+ autoconfig_product(10);
+ autoconfig_manufacturer(514);
autoconfig_serial(0x00000000);
autoconfig_link_into_memory(true);
@@ -140,8 +125,10 @@ WRITE_LINE_MEMBER( a2058_device::cfgin_w )
autoconfig_can_shutup(true); // ?
// install autoconfig handler
- m_slot->space().install_readwrite_handler(0xe80000, 0xe8007f,
- read16_delegate(FUNC(amiga_autoconfig::autoconfig_read), static_cast<amiga_autoconfig *>(this)),
- write16_delegate(FUNC(amiga_autoconfig::autoconfig_write), static_cast<amiga_autoconfig *>(this)), 0xffff);
+ m_zorro->space().install_readwrite_handler(0xe80000, 0xe8007f,
+ read16_delegate(*this, FUNC(amiga_autoconfig::autoconfig_read)),
+ write16_delegate(*this, FUNC(amiga_autoconfig::autoconfig_write)), 0xffff);
}
}
+
+} // namespace bus::amiga::zorro
diff --git a/src/devices/bus/amiga/zorro/a2058.h b/src/devices/bus/amiga/zorro/a2058.h
index 0d3b6771c1f..f8ad5c2a33e 100644
--- a/src/devices/bus/amiga/zorro/a2058.h
+++ b/src/devices/bus/amiga/zorro/a2058.h
@@ -1,5 +1,5 @@
-// license:GPL-2.0+
-// copyright-holders:Dirk Best
+// license: GPL-2.0+
+// copyright-holders: Dirk Best
/***************************************************************************
Commodore A2058
@@ -17,24 +17,23 @@
#include "machine/autoconfig.h"
+namespace bus::amiga::zorro {
+
//**************************************************************************
// TYPE DEFINITIONS
//**************************************************************************
-// ======================> a2058_device
-
class a2058_device : public device_t, public device_zorro2_card_interface, public amiga_autoconfig
{
public:
- // construction/destruction
a2058_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 ioport_constructor device_input_ports() const override ATTR_COLD;
+ 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;
@@ -45,7 +44,9 @@ private:
int m_ram_size;
};
-// device type definition
-DECLARE_DEVICE_TYPE(A2058, a2058_device)
+} // namespace bus::amiga::zorro
+
+// device type declaration
+DECLARE_DEVICE_TYPE_NS(AMIGA_A2058, bus::amiga::zorro, a2058_device)
#endif // MAME_BUS_AMIGA_ZORRO_A2058_H
diff --git a/src/devices/bus/amiga/zorro/a2065.cpp b/src/devices/bus/amiga/zorro/a2065.cpp
index b1b747594cc..3fd1b2a5acf 100644
--- a/src/devices/bus/amiga/zorro/a2065.cpp
+++ b/src/devices/bus/amiga/zorro/a2065.cpp
@@ -1,5 +1,5 @@
-// license:GPL-2.0+
-// copyright-holders:Dirk Best
+// license: GPL-2.0+
+// copyright-holders: Dirk Best
/***************************************************************************
Commodore A2065
@@ -11,24 +11,29 @@
#include "emu.h"
#include "a2065.h"
-
-//**************************************************************************
-// CONSTANTS / MACROS
-//**************************************************************************
-
#define VERBOSE 1
#include "logmacro.h"
//**************************************************************************
-// DEVICE DEFINITIONS
+// TYPE DEFINITIONS
//**************************************************************************
-DEFINE_DEVICE_TYPE(A2065, a2065_device, "a2065", "CBM A2065 Ethernet Card")
+DEFINE_DEVICE_TYPE(AMIGA_A2065, bus::amiga::zorro::a2065_device, "amiga_a2065", "Commodore A2065 Ethernet Card")
+
+namespace bus::amiga::zorro {
+
+a2065_device::a2065_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) :
+ device_t(mconfig, AMIGA_A2065, tag, owner, clock),
+ device_zorro2_card_interface(mconfig, *this),
+ m_lance(*this, "lance")
+{
+}
+
-//-------------------------------------------------
-// device_add_mconfig - add device configuration
-//-------------------------------------------------
+//**************************************************************************
+// MACHINE DEFINITIONS
+//**************************************************************************
void a2065_device::device_add_mconfig(machine_config &config)
{
@@ -40,24 +45,9 @@ void a2065_device::device_add_mconfig(machine_config &config)
//**************************************************************************
-// LIVE DEVICE
+// MACHINE EMULATION
//**************************************************************************
-//-------------------------------------------------
-// a2065_device - constructor
-//-------------------------------------------------
-
-a2065_device::a2065_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) :
- device_t(mconfig, A2065, tag, owner, clock),
- device_zorro2_card_interface(mconfig, *this),
- m_lance(*this, "lance")
-{
-}
-
-//-------------------------------------------------
-// device_start - device-specific startup
-//-------------------------------------------------
-
void a2065_device::device_start()
{
// setup ram
@@ -66,45 +56,77 @@ void a2065_device::device_start()
// register for save states
save_pointer(NAME(m_ram), 0x4000);
+}
+
+uint16_t a2065_device::host_ram_r(offs_t offset)
+{
+ // logerror("host read offset %04x\n", offset);
+ return m_ram[offset & 0x3fff];
+}
+
+void a2065_device::host_ram_w(offs_t offset, uint16_t data, uint16_t mem_mask)
+{
+ // logerror("host write %04x = %04x\n", offset, data);
+ COMBINE_DATA(&m_ram[offset]);
+}
+
+uint16_t a2065_device::lance_ram_r(offs_t offset)
+{
+ offset = (offset >> 1) & 0x3fff;
+ // logerror("lance read offset %04x\n", offset);
+ return m_ram[offset];
+}
+
+void a2065_device::lance_ram_w(offs_t offset, uint16_t data, uint16_t mem_mask)
+{
+ offset = (offset >> 1) & 0x3fff;
+ // logerror("lance write %04x = %04x\n", offset, data);
+ COMBINE_DATA(&m_ram[offset]);
+}
- set_zorro_device();
+void a2065_device::lance_irq_w(int state)
+{
+ // default is irq 2, can be changed via jumper
+ m_zorro->int2_w(!state);
}
//**************************************************************************
-// IMPLEMENTATION
+// AUTOCONFIG
//**************************************************************************
void a2065_device::autoconfig_base_address(offs_t address)
{
- LOG("%s('%s'): autoconfig_base_address received: 0x%06x\n", shortname(), basetag(), address);
+ LOG("%s: autoconfig_base_address received: 0x%06x\n", shortname(), address);
LOG("-> installing a2065\n");
// stop responding to default autoconfig
- m_slot->space().unmap_readwrite(0xe80000, 0xe8007f);
+ m_zorro->space().unmap_readwrite(0xe80000, 0xe8007f);
// install autoconfig handler to new location
- m_slot->space().install_readwrite_handler(address, address + 0x7f,
- read16_delegate(FUNC(amiga_autoconfig::autoconfig_read), static_cast<amiga_autoconfig *>(this)),
- write16_delegate(FUNC(amiga_autoconfig::autoconfig_write), static_cast<amiga_autoconfig *>(this)), 0xffff);
+ m_zorro->space().install_readwrite_handler(address, address + 0x7f,
+ read16_delegate(*this, FUNC(amiga_autoconfig::autoconfig_read)),
+ write16_delegate(*this, FUNC(amiga_autoconfig::autoconfig_write)), 0xffff);
// install access to lance registers
- m_slot->space().install_readwrite_handler(address + 0x4000, address + 0x4003,
- read16_delegate(FUNC(am7990_device::regs_r), &(*m_lance)),
- write16_delegate(FUNC(am7990_device::regs_w), &(*m_lance)), 0xffff);
+ m_zorro->space().install_read_handler(address + 0x4000, address + 0x4003,
+ read16m_delegate(*m_lance, FUNC(am7990_device::regs_r)), 0xffff);
+ m_zorro->space().install_write_handler(address + 0x4000, address + 0x4003,
+ write16sm_delegate(*m_lance, FUNC(am7990_device::regs_w)), 0xffff);
// install access to onboard ram (32k)
- m_slot->space().install_readwrite_handler(address + 0x8000, address + 0x8000 + 0x7fff,
- read16_delegate(FUNC(a2065_device::host_ram_r), this),
- write16_delegate(FUNC(a2065_device::host_ram_w), this), 0xffff);
+ m_zorro->space().install_read_handler(address + 0x8000, address + 0x8000 + 0x7fff,
+ read16sm_delegate(*this, FUNC(a2065_device::host_ram_r)), 0xffff);
+ m_zorro->space().install_write_handler(address + 0x8000, address + 0x8000 + 0x7fff,
+ write16s_delegate(*this, FUNC(a2065_device::host_ram_w)), 0xffff);
// we're done
- m_slot->cfgout_w(0);
+ m_zorro->cfgout_w(0);
}
-WRITE_LINE_MEMBER( a2065_device::cfgin_w )
+void a2065_device::cfgin_w(int state)
{
- LOG("%s('%s'): configin_w (%d)\n", shortname(), basetag(), state);
+ LOG("%s: cfgin_w (%d)\n", shortname(), state);
if (state == 0)
{
@@ -112,8 +134,8 @@ WRITE_LINE_MEMBER( a2065_device::cfgin_w )
autoconfig_board_type(BOARD_TYPE_ZORRO2);
autoconfig_board_size(BOARD_SIZE_64K);
- autoconfig_product(0x70);
- autoconfig_manufacturer(0x0202);
+ autoconfig_product(112);
+ autoconfig_manufacturer(514);
autoconfig_serial(0x00123456); // last 3 bytes = last 3 bytes of mac address
autoconfig_link_into_memory(false);
@@ -123,40 +145,10 @@ WRITE_LINE_MEMBER( a2065_device::cfgin_w )
autoconfig_can_shutup(true); // ?
// install autoconfig handler
- m_slot->space().install_readwrite_handler(0xe80000, 0xe8007f,
- read16_delegate(FUNC(amiga_autoconfig::autoconfig_read), static_cast<amiga_autoconfig *>(this)),
- write16_delegate(FUNC(amiga_autoconfig::autoconfig_write), static_cast<amiga_autoconfig *>(this)), 0xffff);
+ m_zorro->space().install_readwrite_handler(0xe80000, 0xe8007f,
+ read16_delegate(*this, FUNC(amiga_autoconfig::autoconfig_read)),
+ write16_delegate(*this, FUNC(amiga_autoconfig::autoconfig_write)), 0xffff);
}
}
-READ16_MEMBER( a2065_device::host_ram_r )
-{
- // logerror("host read offset %04x\n", offset);
- return m_ram[offset & 0x3fff];
-}
-
-WRITE16_MEMBER( a2065_device::host_ram_w )
-{
- // logerror("host write %04x = %04x\n", offset, data);
- COMBINE_DATA(&m_ram[offset]);
-}
-
-READ16_MEMBER( a2065_device::lance_ram_r )
-{
- offset = (offset >> 1) & 0x3fff;
- // logerror("lance read offset %04x\n", offset);
- return m_ram[offset];
-}
-
-WRITE16_MEMBER( a2065_device::lance_ram_w )
-{
- offset = (offset >> 1) & 0x3fff;
- // logerror("lance write %04x = %04x\n", offset, data);
- COMBINE_DATA(&m_ram[offset]);
-}
-
-WRITE_LINE_MEMBER( a2065_device::lance_irq_w )
-{
- // default is irq 2, can be changed via jumper
- m_slot->int2_w(!state);
-}
+} // namespace bus::amiga::zorro
diff --git a/src/devices/bus/amiga/zorro/a2065.h b/src/devices/bus/amiga/zorro/a2065.h
index bdc0db72475..6a617db8fb1 100644
--- a/src/devices/bus/amiga/zorro/a2065.h
+++ b/src/devices/bus/amiga/zorro/a2065.h
@@ -1,5 +1,5 @@
-// license:GPL-2.0+
-// copyright-holders:Dirk Best
+// license: GPL-2.0+
+// copyright-holders: Dirk Best
/***************************************************************************
Commodore A2065
@@ -18,32 +18,30 @@
#include "machine/autoconfig.h"
+namespace bus::amiga::zorro {
+
//**************************************************************************
// TYPE DEFINITIONS
//**************************************************************************
-// ======================> a2065_device
-
class a2065_device : public device_t, public device_zorro2_card_interface, public amiga_autoconfig
{
public:
- // construction/destruction
a2065_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
- DECLARE_READ16_MEMBER( host_ram_r );
- DECLARE_WRITE16_MEMBER( host_ram_w );
+ uint16_t host_ram_r(offs_t offset);
+ void host_ram_w(offs_t offset, uint16_t data, uint16_t mem_mask = ~0);
- DECLARE_READ16_MEMBER( lance_ram_r );
- DECLARE_WRITE16_MEMBER( lance_ram_w );
- DECLARE_WRITE_LINE_MEMBER( lance_irq_w );
+ uint16_t lance_ram_r(offs_t offset);
+ void lance_ram_w(offs_t offset, uint16_t data, uint16_t mem_mask = ~0);
+ void lance_irq_w(int state);
protected:
- // device-level overrides
- virtual void device_add_mconfig(machine_config &config) override;
- virtual void device_start() override;
+ virtual void device_add_mconfig(machine_config &config) override ATTR_COLD;
+ 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;
@@ -54,7 +52,9 @@ private:
std::unique_ptr<uint16_t[]> m_ram;
};
-// device type definition
-DECLARE_DEVICE_TYPE(A2065, a2065_device)
+} // namespace bus::amiga::zorro
+
+// device type declaration
+DECLARE_DEVICE_TYPE_NS(AMIGA_A2065, bus::amiga::zorro, a2065_device)
#endif // MAME_BUS_AMIGA_ZORRO_A2065_H
diff --git a/src/devices/bus/amiga/zorro/a2091.cpp b/src/devices/bus/amiga/zorro/a2091.cpp
new file mode 100644
index 00000000000..31e758cdfd5
--- /dev/null
+++ b/src/devices/bus/amiga/zorro/a2091.cpp
@@ -0,0 +1,252 @@
+// license: GPL-2.0+
+// copyright-holders: Dirk Best
+/***************************************************************************
+
+ Commodore A2091
+
+ DMAC based SCSI controller for the A2000
+
+ Notes:
+ - Hardware is almost identical to the A590 controller for the A500
+ - Sold as "A2091-40" it was bundled with 40 MB Quantum ProDrive 40S
+ - A2000 + A2091-40 = A2000HD
+ - XT drives aren't usually supported, but a header to connect one
+ can be soldered to the board (unknown how well this really works)
+
+ TODO:
+ - JP5 switch order/polarity
+ - JP3/JP201 switches
+ - Bootrom disable
+ - SCSI drives (fatalerrors early if you enable a drive)
+ - The XT drive should be a slot option (or removed once SCSI works)
+
+***************************************************************************/
+
+#include "emu.h"
+#include "a2091.h"
+#include "machine/nscsi_bus.h"
+#include "bus/nscsi/devices.h"
+
+#define LOG_XT (1U << 1)
+
+#define VERBOSE (LOG_GENERAL)
+
+#include "logmacro.h"
+
+
+//**************************************************************************
+// DEVICE DEFINITIONS
+//**************************************************************************
+
+DEFINE_DEVICE_TYPE(AMIGA_A2091, bus::amiga::zorro::a2091_device, "amiga_a2091", "Commodore A2091 Hard Disk/SCSI Controller")
+
+namespace bus::amiga::zorro {
+
+a2091_device::a2091_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) :
+ device_t(mconfig, AMIGA_A2091, tag, owner, clock),
+ device_zorro2_card_interface(mconfig, *this),
+ m_irq(*this, "irq"),
+ m_dmac(*this, "dmac"),
+ m_wdc(*this, "scsi:7:wdc"),
+ m_xt(*this, "xt"),
+ m_jp1(*this, "jp1"),
+ m_ram_size(0)
+{
+}
+
+
+//**************************************************************************
+// INPUT DEFINITIONS
+//**************************************************************************
+
+static INPUT_PORTS_START( a2091 )
+ PORT_START("jp1")
+ PORT_CONFNAME(0x03, 0x03, "Installed RAM")
+ PORT_CONFSETTING(0x00, "None")
+ PORT_CONFSETTING(0x01, "512K")
+ PORT_CONFSETTING(0x02, "1MB")
+ PORT_CONFSETTING(0x03, "2MB")
+
+ PORT_START("jp2")
+ PORT_CONFNAME(0x01, 0x01, "Autoboot")
+ PORT_CONFSETTING(0x00, "Disabled")
+ PORT_CONFSETTING(0x01, "Enabled")
+
+ // JP3 (would switch between generating INT2 or INT6)
+
+ PORT_START("jp5")
+ PORT_CONFNAME(0x01, 0x01, "LUN")
+ PORT_CONFSETTING(0x00, "Disabled")
+ PORT_CONFSETTING(0x01, "Enabled")
+ PORT_CONFNAME(0x02, 0x02, "Time-out")
+ PORT_CONFSETTING(0x00, "Short")
+ PORT_CONFSETTING(0x02, "Long")
+ PORT_CONFNAME(0x04, 0x04, "Reserved")
+ PORT_CONFSETTING(0x00, "Disabled")
+ PORT_CONFSETTING(0x04, "Enabled")
+
+ // JP201
+INPUT_PORTS_END
+
+ioport_constructor a2091_device::device_input_ports() const
+{
+ return INPUT_PORTS_NAME( a2091 );
+}
+
+
+//**************************************************************************
+// ROM DEFINITIONS
+//**************************************************************************
+
+ROM_START( firmware )
+ ROM_REGION16_BE(0x8000, "bootrom", 0)
+ ROM_DEFAULT_BIOS("v70")
+
+ ROM_SYSTEM_BIOS(0, "v592", "Version 5.92")
+ ROMX_LOAD("390508-02.u13", 0x0000, 0x2000, CRC(f99e3934) SHA1(1aa7f789db48ad0b75f8bb6b3e5532fbf30f5766), ROM_SKIP(1) | ROM_BIOS(2))
+ ROMX_LOAD("390509-02.u12", 0x0001, 0x2000, CRC(8f9dd6f8) SHA1(3a8a4639a498bf9a95cb11c45c13687efa714942), ROM_SKIP(1) | ROM_BIOS(2))
+ ROMX_LOAD("390508-02.u13", 0x4000, 0x2000, CRC(f99e3934) SHA1(1aa7f789db48ad0b75f8bb6b3e5532fbf30f5766), ROM_SKIP(1) | ROM_BIOS(2))
+ ROMX_LOAD("390509-02.u12", 0x4001, 0x2000, CRC(8f9dd6f8) SHA1(3a8a4639a498bf9a95cb11c45c13687efa714942), ROM_SKIP(1) | ROM_BIOS(2))
+
+ ROM_SYSTEM_BIOS(1, "v61", "Version 6.1")
+ ROMX_LOAD("390721-01.u13", 0x0000, 0x2000, CRC(00dbf615) SHA1(503940d04fb3b49eaa61100fd3a487018b35e25a), ROM_SKIP(1) | ROM_BIOS(1))
+ ROMX_LOAD("390722-01.u12", 0x0001, 0x2000, CRC(c460cfdb) SHA1(0de457daec3b84f75e8fb344defe24ce56cda3e0), ROM_SKIP(1) | ROM_BIOS(1))
+ ROMX_LOAD("390721-01.u13", 0x4000, 0x2000, CRC(00dbf615) SHA1(503940d04fb3b49eaa61100fd3a487018b35e25a), ROM_SKIP(1) | ROM_BIOS(1))
+ ROMX_LOAD("390722-01.u12", 0x4001, 0x2000, CRC(c460cfdb) SHA1(0de457daec3b84f75e8fb344defe24ce56cda3e0), ROM_SKIP(1) | ROM_BIOS(1))
+
+ ROM_SYSTEM_BIOS(2, "v66", "Version 6.6")
+ // COPYRIGHT ©1991 CBM ALL RIGHTS RESERVED 390721-02V6.6 D464
+ ROMX_LOAD("390721-02.u13", 0x0000, 0x2000, CRC(c0871d25) SHA1(e155f18abb90cf820589c15e70559d3b6b391af8), ROM_SKIP(1) | ROM_BIOS(2))
+ // COPYRIGHT ©1991 CBM ALL RIGHTS RESERVED 390722-02V6.6 F929
+ ROMX_LOAD("390722-02.u12", 0x0001, 0x2000, CRC(e536bbb2) SHA1(fd7f8a6da18c1b02d07eb990c2467a24183ede12), ROM_SKIP(1) | ROM_BIOS(2))
+ ROMX_LOAD("390721-02.u13", 0x4000, 0x2000, CRC(c0871d25) SHA1(e155f18abb90cf820589c15e70559d3b6b391af8), ROM_SKIP(1) | ROM_BIOS(2))
+ ROMX_LOAD("390722-02.u12", 0x4001, 0x2000, CRC(e536bbb2) SHA1(fd7f8a6da18c1b02d07eb990c2467a24183ede12), ROM_SKIP(1) | ROM_BIOS(2))
+
+ ROM_SYSTEM_BIOS(3, "v70", "Version 7.0")
+ // 360721-07 ©1994 CBM V7.0 081C U13
+ // A590 / A2091 390721-4 V7.0 ROM - (U13) ©1993 CAI (different pn - same content?)
+ ROMX_LOAD("390721-07.u13", 0x0000, 0x2000, CRC(2942747a) SHA1(dbd7648e79c753337ff3e4f491de224bf05e6bb6), ROM_SKIP(1) | ROM_BIOS(3))
+ // 390722-07 ©1994 CBM V7.0 3EF2 U12
+ // A590 / A2091 390722-4 V7.0 ROM - (U12) ©1993 CAI (different pn - same content?)
+ ROMX_LOAD("390722-07.u12", 0x0001, 0x2000, CRC(a9ccffed) SHA1(149f5bd52e2d29904e3de483b9ad772448e9278e), ROM_SKIP(1) | ROM_BIOS(3))
+ ROMX_LOAD("390721-07.u13", 0x4000, 0x2000, CRC(2942747a) SHA1(dbd7648e79c753337ff3e4f491de224bf05e6bb6), ROM_SKIP(1) | ROM_BIOS(3))
+ ROMX_LOAD("390722-07.u12", 0x4001, 0x2000, CRC(a9ccffed) SHA1(149f5bd52e2d29904e3de483b9ad772448e9278e), ROM_SKIP(1) | ROM_BIOS(3))
+
+ // third-party upgrade ROM, requires a small ROM adapter pcb
+ ROM_SYSTEM_BIOS(4, "g614", "Guru-ROM 6.14")
+ ROMX_LOAD("gururom_v614.bin", 0x0000, 0x8000, CRC(04e52f93) SHA1(6da21b6f5e8f8837d64507cd8a4d5cdcac4f426b), ROM_GROUPWORD | ROM_BIOS(4))
+
+ // pal16l8a
+ ROM_REGION(0x104, "ram_controller", 0)
+ ROM_LOAD("390333-03.u5", 0x000, 0x104, CRC(dc4a8d9b) SHA1(761a1318106e49057f95258699076ec1079967ad))
+ROM_END
+
+const tiny_rom_entry *a2091_device::device_rom_region() const
+{
+ return ROM_NAME( firmware );
+}
+
+
+//**************************************************************************
+// MACHINE DEFINITIONS
+//**************************************************************************
+
+void a2091_device::wd33c93_config(device_t *device)
+{
+ device->set_clock(28.37516_MHz_XTAL / 4); // 7M
+ downcast<wd33c93a_device *>(device)->irq_cb().set(m_irq, FUNC(input_merger_any_high_device::in_w<0>));
+ downcast<wd33c93a_device *>(device)->drq_cb().set(m_dmac, FUNC(amiga_dmac_device::sdreq_w));
+}
+
+void a2091_device::device_add_mconfig(machine_config &config)
+{
+ AMIGA_DMAC_REV2(config, m_dmac, 28.37516_MHz_XTAL / 4); // 7M
+ m_dmac->set_rom("bootrom");
+ m_dmac->cfgout_cb().set([this] (int state) { m_zorro->cfgout_w(state); });
+ m_dmac->int_cb().set([this] (int state) { m_zorro->int2_w(state); });
+ m_dmac->css_read_cb().set(m_wdc, FUNC(wd33c93a_device::indir_r));
+ m_dmac->css_write_cb().set(m_wdc, FUNC(wd33c93a_device::indir_w));
+ m_dmac->csx0_read_cb().set(FUNC(a2091_device::xt_r));
+ m_dmac->csx0_write_cb().set(FUNC(a2091_device::xt_w));
+ m_dmac->csx1_read_cb().set_ioport("jp5");
+ m_dmac->xdack_read_cb().set(m_xt, FUNC(xt_hdc_device::dack_r));
+ m_dmac->xdack_write_cb().set(m_xt, FUNC(xt_hdc_device::dack_w));
+
+ INPUT_MERGER_ANY_HIGH(config, m_irq);
+ m_irq->output_handler().set(m_dmac, FUNC(amiga_dmac_device::intx_w));
+
+ NSCSI_BUS(config, "scsi", 0);
+ NSCSI_CONNECTOR(config, "scsi:0", default_scsi_devices, nullptr, false);
+ NSCSI_CONNECTOR(config, "scsi:1", 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("wdc", WD33C93A).machine_config([this] (device_t *device) { wd33c93_config(device); });
+
+ XT_HDC(config, m_xt, 0);
+ m_xt->irq_handler().set(m_irq, FUNC(input_merger_any_high_device::in_w<1>));
+ m_xt->drq_handler().set(m_dmac, FUNC(amiga_dmac_device::xdreq_w));
+
+ HARDDISK(config, "xt:primary");
+}
+
+
+//**************************************************************************
+// MACHINE EMULATION
+//**************************************************************************
+
+void a2091_device::device_start()
+{
+ // setup ram
+ m_ram = make_unique_clear<uint16_t[]>(0x200000/2);
+
+ // setup dmac
+ m_dmac->set_address_space(&m_zorro->space());
+ m_dmac->set_ram(m_ram.get());
+
+ // register for save states
+ save_pointer(NAME(m_ram), 0x200000/2);
+ save_item(NAME(m_ram_size));
+}
+
+// the dmac handles this
+void a2091_device::cfgin_w(int state) { m_dmac->configin_w(state); }
+
+void a2091_device::busrst_w(int state)
+{
+ // call rst first as it will unmap memory
+ m_dmac->rst_w(state);
+
+ if (state == 0)
+ m_dmac->ramsz_w(m_jp1->read() & 0x03);
+}
+
+uint8_t a2091_device::xt_r(offs_t offset)
+{
+ LOGMASKED(LOG_XT, "xt_r(%02x)\n", offset);
+
+ switch (offset)
+ {
+ case 0: return m_xt->data_r();
+ case 1: return m_xt->status_r();
+ case 2: return 0x02; // jumper: 20/40 MB
+ }
+
+ return 0xff;
+}
+
+void a2091_device::xt_w(offs_t offset, uint8_t data)
+{
+ LOGMASKED(LOG_XT, "xt_w(%02x): %02x\n", offset, data);
+
+ switch (offset)
+ {
+ case 0: m_xt->data_w(data); break;
+ case 1: m_xt->reset_w(data); break;
+ case 2: m_xt->select_w(data); break;
+ case 3: m_xt->control_w(data); break;
+ }
+}
+
+} // namespace bus::amiga::zorro
diff --git a/src/devices/bus/amiga/zorro/a2091.h b/src/devices/bus/amiga/zorro/a2091.h
new file mode 100644
index 00000000000..89a3559a05d
--- /dev/null
+++ b/src/devices/bus/amiga/zorro/a2091.h
@@ -0,0 +1,63 @@
+// license: GPL-2.0+
+// copyright-holders: Dirk Best
+/***************************************************************************
+
+ Commodore A2091
+
+ DMAC based SCSI controller for the A2000
+
+***************************************************************************/
+
+#ifndef MAME_BUS_AMIGA_ZORRO_A2091_H
+#define MAME_BUS_AMIGA_ZORRO_A2091_H
+
+#pragma once
+
+#include "zorro.h"
+#include "bus/isa/hdc.h"
+#include "machine/autoconfig.h"
+#include "machine/dmac.h"
+#include "machine/input_merger.h"
+#include "machine/wd33c9x.h"
+
+
+namespace bus::amiga::zorro {
+
+class a2091_device : public device_t, public device_zorro2_card_interface
+{
+public:
+ a2091_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
+
+protected:
+ virtual ioport_constructor device_input_ports() const override ATTR_COLD;
+ virtual const tiny_rom_entry *device_rom_region() const override ATTR_COLD;
+ virtual void device_add_mconfig(machine_config &config) override ATTR_COLD;
+
+ virtual void device_start() override ATTR_COLD;
+
+ // device_zorro2_card_interface overrides
+ virtual void cfgin_w(int state) override;
+ virtual void busrst_w(int state) override;
+
+private:
+ void wd33c93_config(device_t *device);
+
+ uint8_t xt_r(offs_t offset);
+ void xt_w(offs_t offset, uint8_t data);
+
+ required_device<input_merger_any_high_device> m_irq;
+ required_device<amiga_dmac_rev2_device> m_dmac;
+ required_device<wd33c93a_device> m_wdc;
+ required_device<xt_hdc_device> m_xt;
+ required_ioport m_jp1;
+
+ std::unique_ptr<uint16_t[]> m_ram;
+ uint8_t m_ram_size;
+};
+
+} // namespace bus::amiga::zorro
+
+// device type declaration
+DECLARE_DEVICE_TYPE_NS(AMIGA_A2091, bus::amiga::zorro, a2091_device)
+
+#endif // MAME_BUS_AMIGA_ZORRO_A2091_H
diff --git a/src/devices/bus/amiga/zorro/a2232.cpp b/src/devices/bus/amiga/zorro/a2232.cpp
index 24020d7a25d..0c573311176 100644
--- a/src/devices/bus/amiga/zorro/a2232.cpp
+++ b/src/devices/bus/amiga/zorro/a2232.cpp
@@ -11,20 +11,21 @@
#include "emu.h"
#include "a2232.h"
+#define LOG_DATA (1U << 1)
-//**************************************************************************
-// CONSTANTS / MACROS
-//**************************************************************************
+//#define VERBOSE (LOG_GENERAL | LOG_DATA)
-#define VERBOSE 0
-#define VERBOSE_DATA 0
+#include "logmacro.h"
//**************************************************************************
// DEVICE DEFINITIONS
//**************************************************************************
-DEFINE_DEVICE_TYPE(A2232, a2232_device, "a2232", "CBM A2232 Serial Card")
+DEFINE_DEVICE_TYPE(AMIGA_A2232, bus::amiga::zorro::a2232_device, "amiga_a2232", "Commodore A2232 Serial Card")
+
+
+namespace bus::amiga::zorro {
//-------------------------------------------------
// device_add_mconfig - add device configuration
@@ -118,7 +119,7 @@ void a2232_device::device_add_mconfig(machine_config &config)
//-------------------------------------------------
a2232_device::a2232_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) :
- device_t(mconfig, A2232, tag, owner, clock),
+ device_t(mconfig, AMIGA_A2232, tag, owner, clock),
device_zorro2_card_interface(mconfig, *this),
m_iocpu(*this, "iocpu"),
m_ioirq(*this, "ioirq"),
@@ -136,7 +137,6 @@ a2232_device::a2232_device(const machine_config &mconfig, const char *tag, devic
void a2232_device::device_start()
{
- set_zorro_device();
}
//-------------------------------------------------
@@ -158,18 +158,16 @@ void a2232_device::device_reset_after_children()
// IMPLEMENTATION
//**************************************************************************
-WRITE8_MEMBER( a2232_device::int2_w )
+void a2232_device::int2_w(uint8_t data)
{
- if (VERBOSE)
- logerror("%s('%s'): int2_w %04x\n", shortname(), basetag(), data);
+ LOG("%s: int2_w %04x\n", shortname(), data);
- m_slot->int2_w(1);
+ m_zorro->int2_w(1);
}
-WRITE8_MEMBER( a2232_device::irq_ack8_w )
+void a2232_device::irq_ack8_w(uint8_t data)
{
- if (VERBOSE)
- logerror("%s('%s'): irq_ack_w %04x\n", shortname(), basetag(), data);
+ LOG("%s: irq_ack_w %04x\n", shortname(), data);
m_ioirq->in_w<8>(CLEAR_LINE);
}
@@ -181,43 +179,39 @@ WRITE8_MEMBER( a2232_device::irq_ack8_w )
void a2232_device::autoconfig_base_address(offs_t address)
{
- if (VERBOSE)
- logerror("%s('%s'): autoconfig_base_address received: 0x%06x\n", shortname(), basetag(), address);
-
- if (VERBOSE)
- logerror("-> installing a2232\n");
+ LOG("%s: autoconfig_base_address received: 0x%06x\n", shortname(), address);
+ LOG("-> installing a2232\n");
// stop responding to default autoconfig
- m_slot->space().unmap_readwrite(0xe80000, 0xe8007f);
+ m_zorro->space().unmap_readwrite(0xe80000, 0xe8007f);
- m_slot->space().install_readwrite_handler(address, address + 0x3fff,
- read16_delegate(FUNC(a2232_device::shared_ram_r), this),
- write16_delegate(FUNC(a2232_device::shared_ram_w), this), 0xffff);
+ m_zorro->space().install_readwrite_handler(address, address + 0x3fff,
+ read16s_delegate(*this, FUNC(a2232_device::shared_ram_r)),
+ write16s_delegate(*this, FUNC(a2232_device::shared_ram_w)), 0xffff);
- m_slot->space().install_readwrite_handler(address + 0x4000, address + 0x4001,
- read16_delegate(FUNC(a2232_device::irq_ack_r), this),
- write16_delegate(FUNC(a2232_device::irq_ack_w), this), 0xffff);
+ m_zorro->space().install_readwrite_handler(address + 0x4000, address + 0x4001,
+ read16smo_delegate(*this, FUNC(a2232_device::irq_ack_r)),
+ write16smo_delegate(*this, FUNC(a2232_device::irq_ack_w)), 0xffff);
- m_slot->space().install_readwrite_handler(address + 0x8000, address + 0x8001,
- read16_delegate(FUNC(a2232_device::reset_low_r), this),
- write16_delegate(FUNC(a2232_device::reset_low_w), this), 0xffff);
+ m_zorro->space().install_readwrite_handler(address + 0x8000, address + 0x8001,
+ read16smo_delegate(*this, FUNC(a2232_device::reset_low_r)),
+ write16smo_delegate(*this, FUNC(a2232_device::reset_low_w)), 0xffff);
- m_slot->space().install_readwrite_handler(address + 0xa000, address + 0xa001,
- read16_delegate(FUNC(a2232_device::irq_r), this),
- write16_delegate(FUNC(a2232_device::irq_w), this), 0xffff);
+ m_zorro->space().install_readwrite_handler(address + 0xa000, address + 0xa001,
+ read16smo_delegate(*this, FUNC(a2232_device::irq_r)),
+ write16smo_delegate(*this, FUNC(a2232_device::irq_w)), 0xffff);
- m_slot->space().install_readwrite_handler(address + 0xc000, address + 0xc001,
- read16_delegate(FUNC(a2232_device::reset_high_r), this),
- write16_delegate(FUNC(a2232_device::reset_high_w), this), 0xffff);
+ m_zorro->space().install_readwrite_handler(address + 0xc000, address + 0xc001,
+ read16s_delegate(*this, FUNC(a2232_device::reset_high_r)),
+ write16s_delegate(*this, FUNC(a2232_device::reset_high_w)), 0xffff);
// we're done
- m_slot->cfgout_w(0);
+ m_zorro->cfgout_w(0);
}
-WRITE_LINE_MEMBER( a2232_device::cfgin_w )
+void a2232_device::cfgin_w(int state)
{
- if (VERBOSE)
- logerror("%s('%s'): configin_w (%d)\n", shortname(), basetag(), state);
+ LOG("%s: cfgin_w (%d)\n", shortname(), state);
if (state == 0)
{
@@ -236,9 +230,9 @@ WRITE_LINE_MEMBER( a2232_device::cfgin_w )
autoconfig_can_shutup(true); // ?
// install autoconfig handler
- m_slot->space().install_readwrite_handler(0xe80000, 0xe8007f,
- read16_delegate(FUNC(amiga_autoconfig::autoconfig_read), static_cast<amiga_autoconfig *>(this)),
- write16_delegate(FUNC(amiga_autoconfig::autoconfig_write), static_cast<amiga_autoconfig *>(this)), 0xffff);
+ m_zorro->space().install_readwrite_handler(0xe80000, 0xe8007f,
+ read16_delegate(*this, FUNC(amiga_autoconfig::autoconfig_read)),
+ write16_delegate(*this, FUNC(amiga_autoconfig::autoconfig_write)), 0xffff);
}
}
@@ -247,7 +241,7 @@ WRITE_LINE_MEMBER( a2232_device::cfgin_w )
// ZORRO
//**************************************************************************
-READ16_MEMBER( a2232_device::shared_ram_r )
+uint16_t a2232_device::shared_ram_r(offs_t offset, uint16_t mem_mask)
{
uint16_t data = 0;
@@ -261,16 +255,14 @@ READ16_MEMBER( a2232_device::shared_ram_r )
else
data |= 0xff00;
- if (VERBOSE_DATA)
- logerror("%s('%s'): shared_ram_r(%04x) %04x [mask = %04x]\n", shortname(), basetag(), offset << 1, data, mem_mask);
+ LOGMASKED(LOG_DATA, "%s: shared_ram_r(%04x) %04x [mask = %04x]\n", shortname(), offset << 1, data, mem_mask);
return data;
}
-WRITE16_MEMBER( a2232_device::shared_ram_w )
+void a2232_device::shared_ram_w(offs_t offset, uint16_t data, uint16_t mem_mask)
{
- if (VERBOSE_DATA)
- logerror("%s('%s'): shared_ram_w(%04x) %04x [mask = %04x]\n", shortname(), basetag(), offset << 1, data, mem_mask);
+ LOGMASKED(LOG_DATA, "%s: shared_ram_w(%04x) %04x [mask = %04x]\n", shortname(), offset << 1, data, mem_mask);
if (ACCESSING_BITS_0_7)
m_shared_ram[(offset << 1) + 1] = data & 0xff;
@@ -279,31 +271,31 @@ WRITE16_MEMBER( a2232_device::shared_ram_w )
m_shared_ram[offset << 1] = (data & 0xff00) >> 8;
}
-READ16_MEMBER( a2232_device::irq_ack_r )
+uint16_t a2232_device::irq_ack_r()
{
- m_slot->int2_w(0);
+ m_zorro->int2_w(0);
return 0xffff;
}
-WRITE16_MEMBER( a2232_device::irq_ack_w )
+void a2232_device::irq_ack_w(uint16_t data)
{
- m_slot->int2_w(0);
+ m_zorro->int2_w(0);
}
-READ16_MEMBER( a2232_device::reset_low_r )
+uint16_t a2232_device::reset_low_r()
{
m_iocpu->set_input_line(INPUT_LINE_RESET, ASSERT_LINE);
return 0xffff;
}
-WRITE16_MEMBER( a2232_device::reset_low_w )
+void a2232_device::reset_low_w(uint16_t data)
{
m_iocpu->set_input_line(INPUT_LINE_RESET, ASSERT_LINE);
}
-READ16_MEMBER( a2232_device::irq_r )
+uint16_t a2232_device::irq_r()
{
if (!machine().side_effects_disabled())
m_ioirq->in_w<8>(ASSERT_LINE);
@@ -311,27 +303,25 @@ READ16_MEMBER( a2232_device::irq_r )
return 0xffff;
}
-WRITE16_MEMBER( a2232_device::irq_w )
+void a2232_device::irq_w(uint16_t data)
{
m_ioirq->in_w<8>(ASSERT_LINE);
}
-READ16_MEMBER( a2232_device::reset_high_r )
+uint16_t a2232_device::reset_high_r(offs_t offset, uint16_t mem_mask)
{
uint16_t data = 0xffff;
- if (VERBOSE)
- logerror("%s('%s'): reset_high_r %04x [mask = %04x]\n", shortname(), basetag(), data, mem_mask);
+ LOG("%s: reset_high_r %04x [mask = %04x]\n", shortname(), data, mem_mask);
m_iocpu->set_input_line(INPUT_LINE_RESET, CLEAR_LINE);
return data;
}
-WRITE16_MEMBER( a2232_device::reset_high_w )
+void a2232_device::reset_high_w(offs_t offset, uint16_t data, uint16_t mem_mask)
{
- if (VERBOSE)
- logerror("%s('%s'): reset_high_w %04x [mask = %04x]\n", shortname(), basetag(), data, mem_mask);
+ LOG("%s: reset_high_w %04x [mask = %04x]\n", shortname(), data, mem_mask);
m_iocpu->set_input_line(INPUT_LINE_RESET, CLEAR_LINE);
}
@@ -342,13 +332,13 @@ WRITE16_MEMBER( a2232_device::reset_high_w )
//**************************************************************************
template<int N>
-READ8_MEMBER( a2232_device::acia_r )
+uint8_t a2232_device::acia_r(offs_t offset)
{
return m_acia[N]->read(offset >> 1);
}
template<int N>
-WRITE8_MEMBER( a2232_device::acia_w )
+void a2232_device::acia_w(offs_t offset, uint8_t data)
{
m_acia[N]->write(offset >> 1, data);
}
@@ -358,27 +348,27 @@ WRITE8_MEMBER( a2232_device::acia_w )
// CIA
//**************************************************************************
-READ8_MEMBER( a2232_device::cia_r )
+uint8_t a2232_device::cia_r(offs_t offset)
{
return m_cia->read(offset >> 1);
}
-WRITE8_MEMBER( a2232_device::cia_w )
+void a2232_device::cia_w(offs_t offset, uint8_t data)
{
m_cia->write(offset >> 1, data);
}
-READ8_MEMBER( a2232_device::cia_port_a_r )
+uint8_t a2232_device::cia_port_a_r()
{
return m_cia_port_a;
}
-READ8_MEMBER( a2232_device::cia_port_b_r )
+uint8_t a2232_device::cia_port_b_r()
{
return m_cia_port_b;
}
-WRITE8_MEMBER( a2232_device::cia_port_b_w )
+void a2232_device::cia_port_b_w(uint8_t data)
{
// tod clock connected to pb7
m_cia->tod_w(BIT(data, 7));
@@ -389,19 +379,19 @@ WRITE8_MEMBER( a2232_device::cia_port_b_w )
// 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;
@@ -409,73 +399,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;
@@ -498,3 +488,5 @@ void a2232_device::iocpu_map(address_map &map)
map(0x8000, 0x8000).w(FUNC(a2232_device::irq_ack8_w));
map(0xc000, 0xffff).ram().share("shared");
}
+
+} // namespace bus::amiga::zorro
diff --git a/src/devices/bus/amiga/zorro/a2232.h b/src/devices/bus/amiga/zorro/a2232.h
index 31a0c368071..13062db8ba6 100644
--- a/src/devices/bus/amiga/zorro/a2232.h
+++ b/src/devices/bus/amiga/zorro/a2232.h
@@ -24,12 +24,12 @@
#include "bus/rs232/rs232.h"
+namespace bus::amiga::zorro {
+
//**************************************************************************
// TYPE DEFINITIONS
//**************************************************************************
-// ======================> a2232_device
-
class a2232_device : public device_t, public device_zorro2_card_interface, public amiga_autoconfig
{
public:
@@ -37,62 +37,62 @@ public:
a2232_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
// zorro slot
- DECLARE_READ16_MEMBER( shared_ram_r );
- DECLARE_WRITE16_MEMBER( shared_ram_w );
- DECLARE_READ16_MEMBER( irq_ack_r );
- DECLARE_WRITE16_MEMBER( irq_ack_w );
- DECLARE_READ16_MEMBER( reset_low_r );
- DECLARE_WRITE16_MEMBER( reset_low_w );
- DECLARE_READ16_MEMBER( irq_r );
- DECLARE_WRITE16_MEMBER( irq_w );
- DECLARE_READ16_MEMBER( reset_high_r );
- DECLARE_WRITE16_MEMBER( reset_high_w );
-
- void iocpu_map(address_map &map);
+ uint16_t shared_ram_r(offs_t offset, uint16_t mem_mask = ~0);
+ void shared_ram_w(offs_t offset, uint16_t data, uint16_t mem_mask = ~0);
+ uint16_t irq_ack_r();
+ void irq_ack_w(uint16_t data);
+ uint16_t reset_low_r();
+ void reset_low_w(uint16_t data);
+ uint16_t irq_r();
+ void irq_w(uint16_t data);
+ uint16_t reset_high_r(offs_t offset, uint16_t mem_mask = ~0);
+ void reset_high_w(offs_t offset, uint16_t data, uint16_t mem_mask = ~0);
+
+ void iocpu_map(address_map &map) ATTR_COLD;
protected:
- virtual void device_add_mconfig(machine_config &config) override;
- virtual void device_start() override;
+ virtual void device_add_mconfig(machine_config &config) override ATTR_COLD;
+ virtual void device_start() override ATTR_COLD;
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;
private:
// cpu
- WRITE8_MEMBER( int2_w );
- WRITE8_MEMBER( irq_ack8_w );
+ void int2_w(uint8_t data);
+ void irq_ack8_w(uint8_t data);
// acia
- template<int N> DECLARE_READ8_MEMBER( acia_r );
- template<int N> DECLARE_WRITE8_MEMBER( acia_w );
+ template<int N> uint8_t acia_r(offs_t offset);
+ template<int N> void acia_w(offs_t offset, uint8_t data);
// cia
- DECLARE_READ8_MEMBER( cia_port_a_r );
- DECLARE_READ8_MEMBER( cia_port_b_r );
- DECLARE_WRITE8_MEMBER( cia_port_b_w );
- DECLARE_READ8_MEMBER( cia_r );
- DECLARE_WRITE8_MEMBER( cia_w );
+ uint8_t cia_port_a_r();
+ uint8_t cia_port_b_r();
+ void cia_port_b_w(uint8_t data);
+ uint8_t cia_r(offs_t offset);
+ 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;
@@ -104,7 +104,9 @@ private:
uint8_t m_cia_port_b;
};
-// device type definition
-DECLARE_DEVICE_TYPE(A2232, a2232_device)
+} // namespace bus::amiga::zorro
+
+// device type declaration
+DECLARE_DEVICE_TYPE_NS(AMIGA_A2232, bus::amiga::zorro, a2232_device)
#endif // MAME_BUS_AMIGA_ZORRO_A2232_H
diff --git a/src/devices/bus/amiga/zorro/a590.cpp b/src/devices/bus/amiga/zorro/a590.cpp
deleted file mode 100644
index 01975c4a6ad..00000000000
--- a/src/devices/bus/amiga/zorro/a590.cpp
+++ /dev/null
@@ -1,373 +0,0 @@
-// license:GPL-2.0+
-// copyright-holders:Dirk Best
-/***************************************************************************
-
- Commodore A590 / A2091
-
- DMAC based HD controller for the Amiga 500 and Zorro-II
-
-***************************************************************************/
-
-#include "emu.h"
-#include "a590.h"
-#include "machine/nscsi_bus.h"
-#include "bus/nscsi/devices.h"
-
-
-//**************************************************************************
-// DEVICE DEFINITIONS
-//**************************************************************************
-
-DEFINE_DEVICE_TYPE(A590, a590_device, "a590", "CBM A590 HD Controller")
-DEFINE_DEVICE_TYPE(A2091, a2091_device, "a2091", "CBM A2091 HD Controller")
-
-//-------------------------------------------------
-// input_ports - device-specific input ports
-//-------------------------------------------------
-
-static INPUT_PORTS_START( a590_pcb )
- PORT_START("dips")
- PORT_DIPNAME(0x01, 0x01, "A590 Auto-Boot")
- PORT_DIPLOCATION("DIP:1")
- PORT_DIPSETTING(0x00, "Enabled")
- PORT_DIPSETTING(0x01, "Disabled")
- PORT_DIPNAME(0x02, 0x00, "A590 LUN")
- PORT_DIPLOCATION("DIP:2")
- PORT_DIPSETTING(0x00, "Disabled")
- PORT_DIPSETTING(0x02, "Enabled")
- PORT_DIPNAME(0x04, 0x04, "A590 Wait period")
- PORT_DIPLOCATION("DIP:3")
- PORT_DIPSETTING(0x00, "Short")
- PORT_DIPSETTING(0x04, "Long")
- PORT_DIPNAME(0x08, 0x00, "A590 Reserved")
- PORT_DIPLOCATION("DIP:4")
- PORT_DIPSETTING(0x00, "Enabled")
- PORT_DIPSETTING(0x08, "Disabled")
- PORT_START("jp1")
- PORT_DIPNAME(0x0f, 0x01, "A590 Memory size")
- PORT_DIPLOCATION("JP1:1,2,3,4")
- PORT_DIPSETTING(0x01, "Amnesia")
- PORT_DIPSETTING(0x02, "512K")
- PORT_DIPSETTING(0x04, "1MB")
- PORT_DIPSETTING(0x08, "2MB")
- PORT_START("jp2")
- PORT_DIPNAME(0x01, 0x00, "A590 Drive LED")
- PORT_DIPLOCATION("JP2:1")
- PORT_DIPSETTING(0x00, "XT Drive")
- PORT_DIPSETTING(0x01, "SCSI Drive")
- PORT_START("jp4")
- PORT_DIPNAME(0x01, 0x00, "A590 Interrupt")
- PORT_DIPLOCATION("JP4:1")
- PORT_DIPSETTING(0x00, "INT 2")
- PORT_DIPSETTING(0x01, "INT 6")
-INPUT_PORTS_END
-
-ioport_constructor a590_device::device_input_ports() const
-{
- return INPUT_PORTS_NAME( a590_pcb );
-}
-
-static INPUT_PORTS_START( a2091_pcb )
- PORT_START("jp1")
- PORT_DIPNAME(0x0f, 0x01, "A2091 Memory size")
- PORT_DIPLOCATION("JP1:1,2,3,4")
- PORT_DIPSETTING(0x01, "0K")
- PORT_DIPSETTING(0x02, "512K")
- PORT_DIPSETTING(0x04, "1MB")
- PORT_DIPSETTING(0x08, "2MB")
- PORT_START("jp2")
- PORT_DIPNAME(0x01, 0x00, "A2091 Auto-Boot")
- PORT_DIPLOCATION("JP2:1")
- PORT_DIPSETTING(0x00, "Enabled")
- PORT_DIPSETTING(0x01, "Disabled")
- PORT_START("jp3")
- PORT_DIPNAME(0x01, 0x00, "A2091 Interrupt")
- PORT_DIPLOCATION("JP3:1")
- PORT_DIPSETTING(0x00, "INT 2")
- PORT_DIPSETTING(0x01, "INT 6")
- PORT_START("jp5")
- PORT_DIPNAME(0x01, 0x00, "A2091 LUN")
- PORT_DIPLOCATION("JP5:1")
- PORT_DIPSETTING(0x00, "Disabled")
- PORT_DIPSETTING(0x01, "Enabled")
- PORT_DIPNAME(0x02, 0x00, "A2091 Time-Out")
- PORT_DIPLOCATION("JP5:2")
- PORT_DIPSETTING(0x00, "Short")
- PORT_DIPSETTING(0x02, "Long")
- PORT_DIPNAME(0x04, 0x00, "A2091 Reserved")
- PORT_DIPLOCATION("JP5:3")
- PORT_DIPSETTING(0x00, "Disabled")
- PORT_DIPSETTING(0x02, "Enabled")
- PORT_START("jp201")
- PORT_DIPNAME(0x01, 0x00, "A2091 WD33C93 Clock")
- PORT_DIPLOCATION("JP201:1")
- PORT_DIPSETTING(0x00, "7 MHz")
- PORT_DIPSETTING(0x01, "14 MHz")
-INPUT_PORTS_END
-
-ioport_constructor a2091_device::device_input_ports() const
-{
- return INPUT_PORTS_NAME( a2091_pcb );
-}
-
-//-------------------------------------------------
-// device_add_mconfig - add device configuration
-//-------------------------------------------------
-
-void dmac_hdc_device::wd33c93(device_t *device)
-{
- device->set_clock(10000000);
- downcast<wd33c93a_device *>(device)->irq_cb().set(*this, FUNC(dmac_hdc_device::scsi_irq_w));
- downcast<wd33c93a_device *>(device)->drq_cb().set(*this, FUNC(dmac_hdc_device::scsi_drq_w));
-}
-
-void dmac_hdc_device::device_add_mconfig(machine_config &config)
-{
- amiga_dmac_device &dmac(AMIGA_DMAC(config, "dmac", 0));
- dmac.scsi_read_handler().set(FUNC(dmac_hdc_device::dmac_scsi_r));
- dmac.scsi_write_handler().set(FUNC(dmac_hdc_device::dmac_scsi_w));
- dmac.int_handler().set(FUNC(dmac_hdc_device::dmac_int_w));
- dmac.cfgout_handler().set(FUNC(dmac_hdc_device::dmac_cfgout_w));
-
- NSCSI_BUS(config, "scsi", 0);
- NSCSI_CONNECTOR(config, "scsi:0", default_scsi_devices, nullptr, false);
- NSCSI_CONNECTOR(config, "scsi:1", default_scsi_devices, "harddisk", 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", WD33C93A)
- .machine_config([this](device_t *device) { wd33c93(device); });
-}
-
-
-//-------------------------------------------------
-// rom_region - device-specific ROM region
-//-------------------------------------------------
-
-ROM_START( dmac_hdc )
- ROM_REGION16_BE(0x8000, "bootrom", 0)
- ROM_DEFAULT_BIOS("v70")
-
- ROM_SYSTEM_BIOS(0, "v46", "Version 4.6") // a590 only?
- ROMX_LOAD("390389-02.u13", 0x0000, 0x2000, NO_DUMP, ROM_SKIP(1) | ROM_BIOS(0)) // checksum-16: d703
- ROMX_LOAD("390388-02.u12", 0x0001, 0x2000, NO_DUMP, ROM_SKIP(1) | ROM_BIOS(0)) // checksum-16: e7e4
- ROMX_LOAD("390389-02.u13", 0x4000, 0x2000, NO_DUMP, ROM_SKIP(1) | ROM_BIOS(0))
- ROMX_LOAD("390388-02.u12", 0x4001, 0x2000, NO_DUMP, ROM_SKIP(1) | ROM_BIOS(0))
-
- ROM_SYSTEM_BIOS(1, "v592", "Version 5.92") // a2091 only?
- ROMX_LOAD("390508-02.u13", 0x0000, 0x2000, NO_DUMP, ROM_SKIP(1) | ROM_BIOS(1)) // checksum-16: ?
- ROMX_LOAD("390509-02.u12", 0x0001, 0x2000, NO_DUMP, ROM_SKIP(1) | ROM_BIOS(1)) // checksum-16: 288c
- ROMX_LOAD("390508-02.u13", 0x4000, 0x2000, NO_DUMP, ROM_SKIP(1) | ROM_BIOS(1))
- ROMX_LOAD("390509-02.u12", 0x4001, 0x2000, NO_DUMP, ROM_SKIP(1) | ROM_BIOS(1))
-
- ROM_SYSTEM_BIOS(2, "v60", "Version 6.0") // a590 only?
- ROMX_LOAD("390389-03.u13", 0x0000, 0x2000, CRC(2e77bbff) SHA1(8a098845068f32cfa4d34a278cd290f61d35a52c), ROM_SKIP(1) | ROM_BIOS(2)) // checksum-16: cbe8 (ok)
- ROMX_LOAD("390388-03.u12", 0x0001, 0x2000, CRC(b0b8cf24) SHA1(fcf4017505f4d441814b45d559c19eab43816b30), ROM_SKIP(1) | ROM_BIOS(2)) // checksum-16: dfa0 (ok)
- ROMX_LOAD("390389-03.u13", 0x4000, 0x2000, CRC(2e77bbff) SHA1(8a098845068f32cfa4d34a278cd290f61d35a52c), ROM_SKIP(1) | ROM_BIOS(2))
- ROMX_LOAD("390388-03.u12", 0x4001, 0x2000, CRC(b0b8cf24) SHA1(fcf4017505f4d441814b45d559c19eab43816b30), ROM_SKIP(1) | ROM_BIOS(2))
-
- // changelog v6.1: prevent accesses to location 0 by application programs
- ROM_SYSTEM_BIOS(3, "v61", "Version 6.1")
- ROMX_LOAD("390721-01.u13", 0x0000, 0x2000, CRC(00dbf615) SHA1(503940d04fb3b49eaa61100fd3a487018b35e25a), ROM_SKIP(1) | ROM_BIOS(3)) // checksum-16: f4b8 (ok)
- ROMX_LOAD("390722-01.u12", 0x0001, 0x2000, CRC(c460cfdb) SHA1(0de457daec3b84f75e8fb344defe24ce56cda3e0), ROM_SKIP(1) | ROM_BIOS(3)) // checksum-16: 088b (ok)
- ROMX_LOAD("390721-01.u13", 0x4000, 0x2000, CRC(00dbf615) SHA1(503940d04fb3b49eaa61100fd3a487018b35e25a), ROM_SKIP(1) | ROM_BIOS(3))
- ROMX_LOAD("390722-01.u12", 0x4001, 0x2000, CRC(c460cfdb) SHA1(0de457daec3b84f75e8fb344defe24ce56cda3e0), ROM_SKIP(1) | ROM_BIOS(3))
-
- // changelog v6.6: fixes dual SCSI problems with the wd33c93a controller
- ROM_SYSTEM_BIOS(4, "v66", "Version 6.6")
- ROMX_LOAD("390721-02.u13", 0x0000, 0x2000, CRC(c0871d25) SHA1(e155f18abb90cf820589c15e70559d3b6b391af8), ROM_SKIP(1) | ROM_BIOS(4)) // checksum-16: d464 (ok)
- ROMX_LOAD("390722-02.u12", 0x0001, 0x2000, CRC(e536bbb2) SHA1(fd7f8a6da18c1b02d07eb990c2467a24183ede12), ROM_SKIP(1) | ROM_BIOS(4)) // checksum-16: f929 (ok)
- ROMX_LOAD("390721-02.u13", 0x4000, 0x2000, CRC(c0871d25) SHA1(e155f18abb90cf820589c15e70559d3b6b391af8), ROM_SKIP(1) | ROM_BIOS(4))
- ROMX_LOAD("390722-02.u12", 0x4001, 0x2000, CRC(e536bbb2) SHA1(fd7f8a6da18c1b02d07eb990c2467a24183ede12), ROM_SKIP(1) | ROM_BIOS(4))
-
- // final Commodore released version
- ROM_SYSTEM_BIOS(5, "v70", "Version 7.0") // also seen with -07
- ROMX_LOAD("390721-04.u13", 0x0000, 0x2000, CRC(2942747a) SHA1(dbd7648e79c753337ff3e4f491de224bf05e6bb6), ROM_SKIP(1) | ROM_BIOS(5)) // checksum-16: 081c (ok)
- ROMX_LOAD("390722-04.u12", 0x0001, 0x2000, CRC(a9ccffed) SHA1(149f5bd52e2d29904e3de483b9ad772448e9278e), ROM_SKIP(1) | ROM_BIOS(5)) // checksum-16: 3ef2 (ok)
- ROMX_LOAD("390721-04.u13", 0x4000, 0x2000, CRC(2942747a) SHA1(dbd7648e79c753337ff3e4f491de224bf05e6bb6), ROM_SKIP(1) | ROM_BIOS(5))
- ROMX_LOAD("390722-04.u12", 0x4001, 0x2000, CRC(a9ccffed) SHA1(149f5bd52e2d29904e3de483b9ad772448e9278e), ROM_SKIP(1) | ROM_BIOS(5))
-
- // third-party upgrade ROM, requires a small ROM adapter pcb
- ROM_SYSTEM_BIOS(6, "g614", "Guru-ROM 6.14")
- ROMX_LOAD("gururom_v614.bin", 0x0000, 0x8000, CRC(04e52f93) SHA1(6da21b6f5e8f8837d64507cd8a4d5cdcac4f426b), ROM_GROUPWORD | ROM_BIOS(6))
-
- // pal16l8a
- ROM_REGION(0x104, "ram_controller", 0)
- ROM_LOAD("390333-03.u5", 0x000, 0x104, CRC(dc4a8d9b) SHA1(761a1318106e49057f95258699076ec1079967ad))
-ROM_END
-
-const tiny_rom_entry *dmac_hdc_device::device_rom_region() const
-{
- return ROM_NAME( dmac_hdc );
-}
-
-
-//**************************************************************************
-// LIVE DEVICE
-//**************************************************************************
-
-//-------------------------------------------------
-// dmac_hdc_device - constructor
-//-------------------------------------------------
-
-dmac_hdc_device::dmac_hdc_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_int6(false),
- m_dmac(*this, "dmac"),
- m_wdc(*this, "scsi:7:wd33c93")
-{
-}
-
-a590_device::a590_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) :
- dmac_hdc_device(mconfig, A590, tag, owner, clock),
- device_exp_card_interface(mconfig, *this),
- m_dips(*this, "dips"),
- m_jp1(*this, "jp1"),
- m_jp2(*this, "jp2"),
- m_jp4(*this, "jp4")
-{
-}
-
-a2091_device::a2091_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) :
- dmac_hdc_device(mconfig, A2091, tag, owner, clock),
- device_zorro2_card_interface(mconfig, *this),
- m_jp1(*this, "jp1"),
- m_jp2(*this, "jp2"),
- m_jp3(*this, "jp3"),
- m_jp5(*this, "jp5"),
- m_jp201(*this, "jp201")
-{
-}
-
-//-------------------------------------------------
-// device_start - device-specific startup
-//-------------------------------------------------
-
-void dmac_hdc_device::device_start()
-{
-}
-
-void a590_device::device_start()
-{
- set_zorro_device();
-
- // setup DMAC
- m_dmac->set_address_space(&m_slot->space());
- m_dmac->set_rom(memregion("bootrom")->base());
-}
-
-void a2091_device::device_start()
-{
- set_zorro_device();
-
- // setup DMAC
- m_dmac->set_address_space(&m_slot->space());
- m_dmac->set_rom(memregion("bootrom")->base());
-}
-
-//-------------------------------------------------
-// device_reset - device-specific reset
-//-------------------------------------------------
-
-void dmac_hdc_device::device_reset()
-{
-}
-
-void dmac_hdc_device::resize_ram(int config)
-{
- // allocate space for RAM
- switch (config & 0x0f)
- {
- case 0x01:
- m_ram.resize(0);
- m_dmac->ramsz_w(0);
- break;
- case 0x02:
- m_ram.resize(0x080000);
- m_dmac->ramsz_w(1);
- break;
- case 0x04:
- m_ram.resize(0x100000);
- m_dmac->ramsz_w(2);
- break;
- case 0x08:
- m_ram.resize(0x200000);
- m_dmac->ramsz_w(3);
- break;
- }
-
- m_dmac->set_ram(&m_ram[0]);
-}
-
-void a590_device::device_reset()
-{
-}
-
-void a2091_device::device_reset()
-{
-}
-
-
-//**************************************************************************
-// IMPLEMENTATION
-//**************************************************************************
-
-WRITE_LINE_MEMBER( a590_device::cfgin_w )
-{
- // make sure we configure ourselves first
- m_int6 = m_jp4->read() & 0x01;
- resize_ram(m_dips->read() & 0x0f);
-
- // then tell the DMAC to start configuring
- m_dmac->configin_w(state);
-}
-
-WRITE_LINE_MEMBER( a2091_device::cfgin_w )
-{
- // make sure we configure ourselves first
- m_int6 = m_jp3->read() & 0x01;
- resize_ram(m_jp1->read() & 0x0f);
-
- // then tell the DMAC to start configuring
- m_dmac->configin_w(state);
-}
-
-READ8_MEMBER( dmac_hdc_device::dmac_scsi_r )
-{
- switch (offset)
- {
- case 0x48: return m_wdc->indir_addr_r();
- case 0x49: return m_wdc->indir_reg_r();
- }
-
- return 0xff;
-}
-
-WRITE8_MEMBER( dmac_hdc_device::dmac_scsi_w )
-{
- switch (offset)
- {
- case 0x48: m_wdc->indir_addr_w(data); break;
- case 0x49: m_wdc->indir_reg_w(data); break;
- }
-}
-
-WRITE_LINE_MEMBER( dmac_hdc_device::dmac_int_w )
-{
- if (m_int6)
- int6_w(state);
- else
- int2_w(state);
-}
-
-WRITE_LINE_MEMBER( dmac_hdc_device::scsi_irq_w )
-{
- // should be or'ed with xt-ide IRQ
- m_dmac->intx_w(state);
-}
-
-WRITE_LINE_MEMBER( dmac_hdc_device::scsi_drq_w )
-{
- m_dmac->xdreq_w(state);
-}
diff --git a/src/devices/bus/amiga/zorro/a590.h b/src/devices/bus/amiga/zorro/a590.h
deleted file mode 100644
index 62ea3bd189f..00000000000
--- a/src/devices/bus/amiga/zorro/a590.h
+++ /dev/null
@@ -1,136 +0,0 @@
-// license:GPL-2.0+
-// copyright-holders:Dirk Best
-/***************************************************************************
-
- Commodore A590 / A2091
-
- DMAC based SCSI controller for the Amiga 500 and Zorro-II
-
-***************************************************************************/
-
-#ifndef MAME_BUS_AMIGA_ZORRO_A590_H
-#define MAME_BUS_AMIGA_ZORRO_A590_H
-
-#pragma once
-
-#include "zorro.h"
-#include "machine/dmac.h"
-#include "machine/wd33c9x.h"
-
-
-//**************************************************************************
-// TYPE DEFINITIONS
-//**************************************************************************
-
-// ======================> dmac_hdc_device
-
-class dmac_hdc_device : public device_t
-{
-protected:
- // construction/destruction
- dmac_hdc_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;
-
- // to slot
- virtual void cfgout_w(int state) = 0;
- virtual void int2_w(int state) = 0;
- virtual void int6_w(int state) = 0;
-
- // should be called when the ram size changes
- void resize_ram(int config);
-
- // amiga interrupt target, int 2 or 6
- bool m_int6;
-
- // sub-devices
- required_device<amiga_dmac_device> m_dmac;
- required_device<wd33c93a_device> m_wdc;
-
- std::vector<uint8_t> m_ram;
-
-private:
- DECLARE_READ8_MEMBER( dmac_scsi_r );
- DECLARE_WRITE8_MEMBER( dmac_scsi_w );
- 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 );
-
- static void scsi_devices(device_slot_interface &device);
- void wd33c93(device_t *device);
-};
-
-// ======================> a590_device
-
-class a590_device : public dmac_hdc_device, public device_exp_card_interface
-{
-public:
- // construction/destruction
- a590_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 ioport_constructor device_input_ports() const override;
-
- // output to slot
- virtual void cfgout_w(int state) override { m_slot->cfgout_w(state); }
- virtual void int2_w(int state) override { m_slot->int2_w(state); }
- virtual void int6_w(int state) override { m_slot->int6_w(state); }
-
- // input from slot
- virtual DECLARE_WRITE_LINE_MEMBER( cfgin_w ) override;
-
-private:
- required_ioport m_dips;
- required_ioport m_jp1;
- required_ioport m_jp2;
- required_ioport m_jp4;
-};
-
-// ======================> a2091_device
-
-class a2091_device : public dmac_hdc_device, public device_zorro2_card_interface
-{
-public:
- // construction/destruction
- a2091_device(const machine_config &mconfig, 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 ioport_constructor device_input_ports() const override;
-
- // output to slot
- virtual void cfgout_w(int state) override { m_slot->cfgout_w(state); }
- virtual void int2_w(int state) override { m_slot->int2_w(state); }
- virtual void int6_w(int state) override { m_slot->int6_w(state); }
-
- // input from slot
- virtual DECLARE_WRITE_LINE_MEMBER( cfgin_w ) override;
-
-private:
- required_ioport m_jp1;
- required_ioport m_jp2;
- required_ioport m_jp3;
- required_ioport m_jp5;
- required_ioport m_jp201;
-};
-
-// device type definition
-DECLARE_DEVICE_TYPE(A590, a590_device)
-DECLARE_DEVICE_TYPE(A2091, a2091_device)
-
-#endif // MAME_BUS_AMIGA_ZORRO_A590_H
diff --git a/src/devices/bus/amiga/zorro/action_replay.cpp b/src/devices/bus/amiga/zorro/action_replay.cpp
deleted file mode 100644
index 075948c4ec3..00000000000
--- a/src/devices/bus/amiga/zorro/action_replay.cpp
+++ /dev/null
@@ -1,149 +0,0 @@
-// license:GPL-2.0+
-// copyright-holders:Dirk Best
-/***************************************************************************
-
- Datel Action Replay
-
- Freezer cartridge for Amiga 500 and Amiga 2000
-
- Skeleton device, just loads the ROMs and generates the NMI
- for now.
-
- Hardware notes:
- - http://www.mways.co.uk/amiga/howtocode/text/actionreplay.php
-
-***************************************************************************/
-
-#include "emu.h"
-#include "action_replay.h"
-
-
-//**************************************************************************
-// DEVICE DEFINITIONS
-//**************************************************************************
-
-DEFINE_DEVICE_TYPE(ACTION_REPLAY_MK1, action_replay_mk1_device, "amiga_ar1", "Datel Action Replay MK-I")
-DEFINE_DEVICE_TYPE(ACTION_REPLAY_MK2, action_replay_mk2_device, "amiga_ar2", "Datel Action Replay MK-II")
-DEFINE_DEVICE_TYPE(ACTION_REPLAY_MK3, action_replay_mk3_device, "amiga_ar3", "Datel Action Replay MK-III")
-
-//-------------------------------------------------
-// input_ports - device-specific input ports
-//-------------------------------------------------
-
-static INPUT_PORTS_START( ar_button )
- PORT_START("freeze")
- PORT_BIT(0x01, IP_ACTIVE_HIGH, IPT_OTHER ) PORT_NAME("Freeze") PORT_CODE(KEYCODE_F12) PORT_CHANGED_MEMBER(DEVICE_SELF, action_replay_device, freeze, 0)
-INPUT_PORTS_END
-
-ioport_constructor action_replay_device::device_input_ports() const
-{
- return INPUT_PORTS_NAME( ar_button );
-}
-
-//-------------------------------------------------
-// rom_region - device-specific ROM region
-//-------------------------------------------------
-
-ROM_START( ar_mk1 )
- ROM_REGION(0x10000, "firmware", 0)
- ROM_DEFAULT_BIOS("v150")
- ROM_SYSTEM_BIOS(0, "v100", "Version 1.00")
- ROMX_LOAD("ar1_v100.bin", 0x0000, 0x10000, BAD_DUMP CRC(2d921771) SHA1(1ead9dda2dad29146441f5ef7218375022e01248), ROM_BIOS(0))
- ROM_SYSTEM_BIOS(1, "v150", "Version 1.50")
- ROMX_LOAD("ar1_v150.bin", 0x0000, 0x10000, BAD_DUMP CRC(f82c4258) SHA1(843b433b2c56640e045d5fdc854dc6b1a4964e7c), ROM_BIOS(1))
-ROM_END
-
-const tiny_rom_entry *action_replay_mk1_device::device_rom_region() const
-{
- return ROM_NAME( ar_mk1 );
-}
-
-ROM_START( ar_mk2 )
- ROM_REGION(0x20000, "firmware", 0)
- ROM_DEFAULT_BIOS("v214")
- ROM_SYSTEM_BIOS(0, "v205", "Version 2.05")
- ROMX_LOAD("ar2_v205.bin", 0x0000, 0x20000, BAD_DUMP CRC(4051eef8) SHA1(9df22b1d3285b522c223697c83d144d04e961a4a), ROM_BIOS(0))
- ROM_SYSTEM_BIOS(1, "v212", "Version 2.12")
- ROMX_LOAD("ar2_v212.bin", 0x0000, 0x20000, BAD_DUMP CRC(d29bdd86) SHA1(76c2900457badf22b742f0af48b78937e8b67694), ROM_BIOS(1))
- ROM_SYSTEM_BIOS(2, "v214", "Version 2.14")
- ROMX_LOAD("ar2_v214.bin", 0x0000, 0x20000, BAD_DUMP CRC(1bb3d0a8) SHA1(14b1f5a69efb6f4e2331970e6ca0f33c0f04ac91), ROM_BIOS(2))
-ROM_END
-
-const tiny_rom_entry *action_replay_mk2_device::device_rom_region() const
-{
- return ROM_NAME( ar_mk2 );
-}
-
-ROM_START( ar_mk3 )
- ROM_REGION(0x40000, "firmware", 0)
- ROM_DEFAULT_BIOS("v309")
- ROM_SYSTEM_BIOS(0, "v309", "Version 3.09")
- ROMX_LOAD("ar3_v309.evn", 0x00000, 0x20000, CRC(2b84519f) SHA1(7841873bf009d8341dfa2794b3751bacf86adcc8), ROM_SKIP(1) | ROM_BIOS(0))
- ROMX_LOAD("ar3_v309.odd", 0x00001, 0x20000, CRC(1d35bd56) SHA1(6464be1626b519499e76e4e3409e8016515d48b6), ROM_SKIP(1) | ROM_BIOS(0))
- ROM_SYSTEM_BIOS(1, "v317", "Version 3.17")
- ROMX_LOAD("ar3_v314.bin", 0x0000, 0x40000, BAD_DUMP CRC(009f7768) SHA1(0439d6ccc2a0e5c2e83fcf2389dc4d4a440a4c62), ROM_BIOS(1))
-ROM_END
-
-const tiny_rom_entry *action_replay_mk3_device::device_rom_region() const
-{
- return ROM_NAME( ar_mk3 );
-}
-
-
-//**************************************************************************
-// LIVE DEVICE
-//**************************************************************************
-
-//-------------------------------------------------
-// action_replay_device - constructor
-//-------------------------------------------------
-
-action_replay_device::action_replay_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_exp_card_interface(mconfig, *this),
- m_button(*this, "freeze")
-{
-}
-
-action_replay_mk1_device::action_replay_mk1_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) :
- action_replay_device(mconfig, ACTION_REPLAY_MK1, tag, owner, clock)
-{
-}
-
-action_replay_mk2_device::action_replay_mk2_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) :
- action_replay_device(mconfig, ACTION_REPLAY_MK2, tag, owner, clock)
-{
-}
-
-action_replay_mk3_device::action_replay_mk3_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) :
- action_replay_device(mconfig, ACTION_REPLAY_MK3, tag, owner, clock)
-{
-}
-
-//-------------------------------------------------
-// device_start - device-specific startup
-//-------------------------------------------------
-
-void action_replay_device::device_start()
-{
- set_zorro_device();
-}
-
-//-------------------------------------------------
-// device_reset - device-specific reset
-//-------------------------------------------------
-
-void action_replay_device::device_reset()
-{
-}
-
-
-//**************************************************************************
-// IMPLEMENTATION
-//**************************************************************************
-
-INPUT_CHANGED_MEMBER( action_replay_device::freeze )
-{
- // pushing the freeze button generates an nmi
- m_slot->ipl_w(newval == 1 ? 7 : 0);
-}
diff --git a/src/devices/bus/amiga/zorro/action_replay.h b/src/devices/bus/amiga/zorro/action_replay.h
deleted file mode 100644
index 5dd1e347049..00000000000
--- a/src/devices/bus/amiga/zorro/action_replay.h
+++ /dev/null
@@ -1,80 +0,0 @@
-// license:GPL-2.0+
-// copyright-holders:Dirk Best
-/***************************************************************************
-
- Datel Action Replay
-
- Freezer cartridge for Amiga 500 and Amiga 2000
-
-***************************************************************************/
-
-#ifndef MAME_BUS_AMIGA_ZORRO_ACTION_REPLAY_H
-#define MAME_BUS_AMIGA_ZORRO_ACTION_REPLAY_H
-
-#pragma once
-
-#include "zorro.h"
-
-
-//**************************************************************************
-// TYPE DEFINITIONS
-//**************************************************************************
-
-// ======================> action_replay_device
-
-class action_replay_device : public device_t, public device_exp_card_interface
-{
-public:
- // optional information overrides
- virtual ioport_constructor device_input_ports() const override;
-
- DECLARE_INPUT_CHANGED_MEMBER( freeze );
-
-protected:
- // construction/destruction
- action_replay_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:
- required_ioport m_button;
-};
-
-class action_replay_mk1_device : public action_replay_device
-{
-public:
- // construction/destruction
- action_replay_mk1_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;
-};
-
-class action_replay_mk2_device : public action_replay_device
-{
-public:
- // construction/destruction
- action_replay_mk2_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;
-};
-
-class action_replay_mk3_device : public action_replay_device
-{
-public:
- // construction/destruction
- action_replay_mk3_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;
-};
-
-// device type definition
-DECLARE_DEVICE_TYPE(ACTION_REPLAY_MK1, action_replay_mk1_device)
-DECLARE_DEVICE_TYPE(ACTION_REPLAY_MK2, action_replay_mk2_device)
-DECLARE_DEVICE_TYPE(ACTION_REPLAY_MK3, action_replay_mk3_device)
-
-#endif // MAME_BUS_AMIGA_ZORRO_ACTION_REPLAY_H
diff --git a/src/devices/bus/amiga/zorro/buddha.cpp b/src/devices/bus/amiga/zorro/buddha.cpp
index 376e2824660..e76d6a0640d 100644
--- a/src/devices/bus/amiga/zorro/buddha.cpp
+++ b/src/devices/bus/amiga/zorro/buddha.cpp
@@ -1,5 +1,5 @@
-// license:GPL-2.0+
-// copyright-holders:Dirk Best
+// license: GPL-2.0+
+// copyright-holders: Dirk Best
/***************************************************************************
Buddha
@@ -25,38 +25,52 @@
#include "emu.h"
#include "buddha.h"
-//**************************************************************************
-// CONSTANTS / MACROS
-//**************************************************************************
-
#define VERBOSE 1
+#include "logmacro.h"
//**************************************************************************
// DEVICE DEFINITIONS
//**************************************************************************
-DEFINE_DEVICE_TYPE(BUDDHA, buddha_device, "buddha", "Buddha IDE controller")
+DEFINE_DEVICE_TYPE(AMIGA_BUDDHA, bus::amiga::zorro::buddha_device, "amiga_buddha", "Buddha IDE controller")
+
+namespace bus::amiga::zorro {
+
+buddha_device::buddha_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) :
+ device_t(mconfig, AMIGA_BUDDHA, tag, owner, clock),
+ device_zorro2_card_interface(mconfig, *this),
+ m_ata_0(*this, "ata_0"),
+ m_ata_1(*this, "ata_1"),
+ m_bootrom(*this, "bootrom"),
+ m_ide_interrupts_enabled(false),
+ m_ide_0_interrupt(0),
+ m_ide_1_interrupt(0)
+{
+}
-//-------------------------------------------------
-// mmio_map - device-specific memory mapped I/O
-//-------------------------------------------------
+
+//**************************************************************************
+// ADDRESS MAPS
+//**************************************************************************
void buddha_device::mmio_map(address_map &map)
{
- map(0x7fe, 0x7ff).rw(FUNC(buddha_device::speed_r), FUNC(buddha_device::speed_w));
- map(0x800, 0x8ff).rw(FUNC(buddha_device::ide_0_cs0_r), FUNC(buddha_device::ide_0_cs0_w));
- map(0x900, 0x9ff).rw(FUNC(buddha_device::ide_0_cs1_r), FUNC(buddha_device::ide_0_cs1_w));
- map(0xa00, 0xaff).rw(FUNC(buddha_device::ide_1_cs0_r), FUNC(buddha_device::ide_1_cs0_w));
- map(0xb00, 0xbff).rw(FUNC(buddha_device::ide_1_cs1_r), FUNC(buddha_device::ide_1_cs1_w));
- map(0xf00, 0xf3f).r(FUNC(buddha_device::ide_0_interrupt_r));
- map(0xf40, 0xf7f).r(FUNC(buddha_device::ide_1_interrupt_r));
- map(0xfc0, 0xfff).w(FUNC(buddha_device::ide_interrupt_enable_w));
+ map(0x07fe, 0x07ff).rw(FUNC(buddha_device::speed_r), FUNC(buddha_device::speed_w));
+ map(0x0800, 0x08ff).rw(FUNC(buddha_device::ide_0_cs0_r), FUNC(buddha_device::ide_0_cs0_w));
+ map(0x0900, 0x09ff).rw(FUNC(buddha_device::ide_0_cs1_r), FUNC(buddha_device::ide_0_cs1_w));
+ map(0x0a00, 0x0aff).rw(FUNC(buddha_device::ide_1_cs0_r), FUNC(buddha_device::ide_1_cs0_w));
+ map(0x0b00, 0x0bff).rw(FUNC(buddha_device::ide_1_cs1_r), FUNC(buddha_device::ide_1_cs1_w));
+ map(0x0f00, 0x0f3f).r(FUNC(buddha_device::ide_0_interrupt_r));
+ map(0x0f40, 0x0f7f).r(FUNC(buddha_device::ide_1_interrupt_r));
+ map(0x0fc0, 0x0fff).w(FUNC(buddha_device::ide_interrupt_enable_w));
+ map(0x1000, 0xffff).r(FUNC(buddha_device::rom_r)).umask16(0xff00);
}
-//-------------------------------------------------
-// device_add_mconfig - add device configuration
-//-------------------------------------------------
+
+//**************************************************************************
+// MACHINE DEFINITIONS
+//**************************************************************************
void buddha_device::device_add_mconfig(machine_config &config)
{
@@ -67,17 +81,18 @@ void buddha_device::device_add_mconfig(machine_config &config)
m_ata_1->irq_handler().set(FUNC(buddha_device::ide_1_interrupt_w));
}
-//-------------------------------------------------
-// rom_region - device-specific ROM region
-//-------------------------------------------------
+
+//**************************************************************************
+// ROM DEFINITIONS
+//**************************************************************************
ROM_START( buddha )
- ROM_REGION16_BE(0x10000, "bootrom", ROMREGION_ERASEFF)
+ ROM_REGION(0x8000, "bootrom", 0)
ROM_DEFAULT_BIOS("v103-17")
ROM_SYSTEM_BIOS(0, "v103-8", "Version 103.8")
- ROMX_LOAD("buddha_103-8.rom", 0x0000, 0x8000, CRC(44f81426) SHA1(95555c6690b5c697e1cdca2726e47c1c6c194d7c), ROM_SKIP(1) | ROM_BIOS(0))
+ ROMX_LOAD("buddha_103-8.rom", 0x0000, 0x8000, CRC(44f81426) SHA1(95555c6690b5c697e1cdca2726e47c1c6c194d7c), ROM_BIOS(0))
ROM_SYSTEM_BIOS(1, "v103-17", "Version 103.17")
- ROMX_LOAD("buddha_103-17.rom", 0x0000, 0x8000, CRC(2b7b24e0) SHA1(ec17a58962c373a2892090ec9b1722d2c326d631), ROM_SKIP(1) | ROM_BIOS(1))
+ ROMX_LOAD("buddha_103-17.rom", 0x0000, 0x8000, CRC(2b7b24e0) SHA1(ec17a58962c373a2892090ec9b1722d2c326d631), ROM_BIOS(1))
ROM_END
const tiny_rom_entry *buddha_device::device_rom_region() const
@@ -87,261 +102,179 @@ const tiny_rom_entry *buddha_device::device_rom_region() const
//**************************************************************************
-// LIVE DEVICE
+// MACHINE EMULATION
//**************************************************************************
-//-------------------------------------------------
-// buddha_device - constructor
-//-------------------------------------------------
-
-buddha_device::buddha_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) :
- device_t(mconfig, BUDDHA, tag, owner, clock),
- device_zorro2_card_interface(mconfig, *this),
- m_ata_0(*this, "ata_0"),
- m_ata_1(*this, "ata_1"),
- m_ide_interrupts_enabled(false),
- m_ide_0_interrupt(0),
- m_ide_1_interrupt(0)
-{
-}
-
-//-------------------------------------------------
-// device_start - device-specific startup
-//-------------------------------------------------
-
void buddha_device::device_start()
{
- set_zorro_device();
-
save_item(NAME(m_ide_interrupts_enabled));
save_item(NAME(m_ide_0_interrupt));
save_item(NAME(m_ide_1_interrupt));
}
-//-------------------------------------------------
-// device_reset - device-specific reset
-//-------------------------------------------------
-
-void buddha_device::device_reset()
-{
- m_ide_interrupts_enabled = false;
- m_ide_0_interrupt = 0;
- m_ide_1_interrupt = 0;
-}
-
-
-//**************************************************************************
-// IMPLEMENTATION
-//**************************************************************************
-
-void buddha_device::autoconfig_base_address(offs_t address)
-{
- if (VERBOSE)
- logerror("autoconfig_base_address received: 0x%06x\n", address);
-
- if (VERBOSE)
- logerror("-> installing buddha\n");
-
- // stop responding to default autoconfig
- m_slot->space().unmap_readwrite(0xe80000, 0xe8007f);
-
- // buddha registers
- m_slot->space().install_device(address, address + 0xfff, *this, &buddha_device::mmio_map);
-
- // install autoconfig handler to new location
- m_slot->space().install_readwrite_handler(address, address + 0x7f,
- read16_delegate(FUNC(amiga_autoconfig::autoconfig_read), static_cast<amiga_autoconfig *>(this)),
- write16_delegate(FUNC(amiga_autoconfig::autoconfig_write), static_cast<amiga_autoconfig *>(this)), 0xffff);
-
- // install access to the rom space
- m_slot->space().install_rom(address + 0x1000, address + 0xffff, memregion("bootrom")->base() + 0x1000);
-
- // we're done
- m_slot->cfgout_w(0);
-}
-
-WRITE_LINE_MEMBER( buddha_device::cfgin_w )
+void buddha_device::busrst_w(int state)
{
- if (VERBOSE)
- logerror("configin_w (%d)\n", state);
-
if (state == 0)
{
- // setup autoconfig
- autoconfig_board_type(BOARD_TYPE_ZORRO2);
- autoconfig_board_size(BOARD_SIZE_64K);
- autoconfig_link_into_memory(false);
- autoconfig_rom_vector_valid(true);
- autoconfig_multi_device(false);
- autoconfig_8meg_preferred(false);
- autoconfig_can_shutup(true);
- autoconfig_product(0x00);
- autoconfig_manufacturer(0x1212);
- autoconfig_serial(0x00000000);
- autoconfig_rom_vector(0x1000);
-
- // install autoconfig handler
- m_slot->space().install_readwrite_handler(0xe80000, 0xe8007f,
- read16_delegate(FUNC(amiga_autoconfig::autoconfig_read), static_cast<amiga_autoconfig *>(this)),
- write16_delegate(FUNC(amiga_autoconfig::autoconfig_write), static_cast<amiga_autoconfig *>(this)), 0xffff);
+ m_ide_interrupts_enabled = false;
+ m_ide_0_interrupt = 0;
+ m_ide_1_interrupt = 0;
}
}
-READ16_MEMBER( buddha_device::speed_r )
+uint8_t buddha_device::rom_r(offs_t offset)
+{
+ // the first 0x800 bytes cannot be read
+ return m_bootrom[0x800 + offset];
+}
+
+uint16_t buddha_device::speed_r(offs_t offset, uint16_t mem_mask)
{
uint16_t data = 0xffff;
- if (VERBOSE)
- logerror("speed_r %04x [mask = %04x]\n", data, mem_mask);
+ if (!machine().side_effects_disabled())
+ LOG("speed_r %04x [mask = %04x]\n", data, mem_mask);
return data;
}
-WRITE16_MEMBER( buddha_device::speed_w )
+void buddha_device::speed_w(offs_t offset, uint16_t data, uint16_t mem_mask)
{
- if (VERBOSE)
- logerror("speed_w %04x [mask = %04x]\n", data, 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)
{
- if (VERBOSE)
- logerror("ide_0_interrupt_w (%d)\n", state);
+ LOG("ide_0_interrupt_w (%d)\n", state);
m_ide_0_interrupt = state;
if (m_ide_interrupts_enabled)
- m_slot->int2_w(state);
+ m_zorro->int2_w(state);
}
-WRITE_LINE_MEMBER( buddha_device::ide_1_interrupt_w)
+void buddha_device::ide_1_interrupt_w(int state)
{
- if (VERBOSE)
- logerror("ide_1_interrupt_w (%d)\n", state);
+ LOG("ide_1_interrupt_w (%d)\n", state);
m_ide_1_interrupt = state;
if (m_ide_interrupts_enabled)
- m_slot->int2_w(state);
+ m_zorro->int2_w(state);
}
-READ16_MEMBER( buddha_device::ide_0_interrupt_r )
+uint16_t buddha_device::ide_0_interrupt_r(offs_t offset, uint16_t mem_mask)
{
- uint16_t data;
-
- data = m_ide_0_interrupt << 15;
-
-// if (VERBOSE)
-// logerror("ide_0_interrupt_r %04x [mask = %04x]\n", data, mem_mask);
-
- return data;
+// LOG("ide_0_interrupt_r %04x [mask = %04x]\n", m_ide_0_interrupt << 15, mem_mask);
+ return m_ide_0_interrupt << 15;
}
-READ16_MEMBER( buddha_device::ide_1_interrupt_r )
+uint16_t buddha_device::ide_1_interrupt_r(offs_t offset, uint16_t mem_mask)
{
- uint16_t data;
-
- data = m_ide_1_interrupt << 15;
-
-// if (VERBOSE)
-// logerror("ide_1_interrupt_r %04x [mask = %04x]\n", data, mem_mask);
-
- return data;
+// LOG("ide_1_interrupt_r %04x [mask = %04x]\n", m_ide_1_interrupt << 15, mem_mask);
+ return m_ide_1_interrupt << 15;
}
-WRITE16_MEMBER( buddha_device::ide_interrupt_enable_w )
+void buddha_device::ide_interrupt_enable_w(offs_t offset, uint16_t data, uint16_t mem_mask)
{
- if (VERBOSE)
- logerror("ide_interrupt_enable_w %04x [mask = %04x]\n", data, mem_mask);
+ LOG("ide_interrupt_enable_w %04x [mask = %04x]\n", data, mem_mask);
// writing any value here enables ide interrupts to the zorro slot
m_ide_interrupts_enabled = true;
}
-READ16_MEMBER( buddha_device::ide_0_cs0_r )
+uint16_t buddha_device::ide_0_cs0_r(offs_t offset, uint16_t mem_mask)
{
- uint16_t data = m_ata_0->read_cs0((offset >> 1) & 0x07, (mem_mask << 8) | (mem_mask >> 8));
- data = (data << 8) | (data >> 8);
-
- if (VERBOSE)
- logerror("ide_0_cs0_r(%04x) %04x [mask = %04x]\n", offset, data, mem_mask);
-
- return data;
+ return m_ata_0->cs0_swap_r((offset >> 1) & 0x07, mem_mask);
}
-WRITE16_MEMBER( buddha_device::ide_0_cs0_w )
+void buddha_device::ide_0_cs0_w(offs_t offset, uint16_t data, uint16_t mem_mask)
{
- if (VERBOSE)
- logerror("ide_0_cs0_w(%04x) %04x [mask = %04x]\n", offset, data, mem_mask);
-
- mem_mask = (mem_mask << 8) | (mem_mask >> 8);
- data = (data << 8) | (data >> 8);
-
- m_ata_0->write_cs0((offset >> 1) & 0x07, data, mem_mask);
+ m_ata_0->cs0_swap_w((offset >> 1) & 0x07, data, mem_mask);
}
-READ16_MEMBER( buddha_device::ide_0_cs1_r )
+uint16_t buddha_device::ide_0_cs1_r(offs_t offset, uint16_t mem_mask)
{
- uint16_t data = m_ata_0->read_cs1((offset >> 1) & 0x07, (mem_mask << 8) | (mem_mask >> 8));
- data = (data << 8) | (data >> 8);
-
- if (VERBOSE)
- logerror("ide_0_cs1_r(%04x) %04x [mask = %04x]\n", offset, data, mem_mask);
-
- return data;
+ return m_ata_0->cs1_swap_r((offset >> 1) & 0x07, mem_mask);
}
-WRITE16_MEMBER( buddha_device::ide_0_cs1_w )
+void buddha_device::ide_0_cs1_w(offs_t offset, uint16_t data, uint16_t mem_mask)
{
- if (VERBOSE)
- logerror("ide_0_cs1_w(%04x) %04x [mask = %04x]\n", offset, data, mem_mask);
-
- mem_mask = (mem_mask << 8) | (mem_mask >> 8);
- data = (data << 8) | (data >> 8);
-
- m_ata_0->write_cs1((offset >> 1) & 0x07, data, mem_mask);
+ m_ata_0->cs1_swap_w((offset >> 1) & 0x07, data, mem_mask);
}
-READ16_MEMBER( buddha_device::ide_1_cs0_r )
+uint16_t buddha_device::ide_1_cs0_r(offs_t offset, uint16_t mem_mask)
{
- uint16_t data = m_ata_1->read_cs0((offset >> 1) & 0x07, (mem_mask << 8) | (mem_mask >> 8));
- data = (data << 8) | (data >> 8);
+ return m_ata_1->cs0_swap_r((offset >> 1) & 0x07, mem_mask);
+}
- if (VERBOSE)
- logerror("ide_1_cs0_r(%04x) %04x [mask = %04x]\n", offset, data, mem_mask);
+void buddha_device::ide_1_cs0_w(offs_t offset, uint16_t data, uint16_t mem_mask)
+{
+ m_ata_1->cs0_swap_w((offset >> 1) & 0x07, data, mem_mask);
+}
- return data;
+uint16_t buddha_device::ide_1_cs1_r(offs_t offset, uint16_t mem_mask)
+{
+ return m_ata_1->cs1_swap_r((offset >> 1) & 0x07, mem_mask);
}
-WRITE16_MEMBER( buddha_device::ide_1_cs0_w )
+void buddha_device::ide_1_cs1_w(offs_t offset, uint16_t data, uint16_t mem_mask)
{
- if (VERBOSE)
- logerror("ide_1_cs0_w(%04x) %04x [mask = %04x]\n", offset, data, mem_mask);
+ m_ata_1->cs1_swap_w((offset >> 1) & 0x07, data, mem_mask);
+}
- mem_mask = (mem_mask << 8) | (mem_mask >> 8);
- data = (data << 8) | (data >> 8);
- m_ata_1->write_cs0((offset >> 1) & 0x07, data, mem_mask);
-}
+//**************************************************************************
+// AUTOCONFIG
+//**************************************************************************
-READ16_MEMBER( buddha_device::ide_1_cs1_r )
+void buddha_device::autoconfig_base_address(offs_t address)
{
- uint16_t data = m_ata_1->read_cs1((offset >> 1) & 0x07, (mem_mask << 8) | (mem_mask >> 8));
- data = (data << 8) | (data >> 8);
+ LOG("autoconfig_base_address received: 0x%06x\n", address);
+ LOG("-> installing buddha\n");
- if (VERBOSE)
- logerror("ide_1_cs1_r(%04x) %04x [mask = %04x]\n", offset, data, mem_mask);
+ // stop responding to initial location
+ m_zorro->space().unmap_readwrite(0xe80000, 0xe8ffff);
- return data;
+ // install buddha memory access to final location
+ m_zorro->space().install_device(address, address + 0xffff, *this, &buddha_device::mmio_map);
+
+ // install autoconfig handler to new location
+ m_zorro->space().install_readwrite_handler(address, address + 0x7f,
+ read16_delegate(*this, FUNC(amiga_autoconfig::autoconfig_read)),
+ write16_delegate(*this, FUNC(amiga_autoconfig::autoconfig_write)), 0xffff);
+
+ // we're done
+ m_zorro->cfgout_w(0);
}
-WRITE16_MEMBER( buddha_device::ide_1_cs1_w )
+void buddha_device::cfgin_w(int state)
{
- if (VERBOSE)
- logerror("ide_1_cs1_w(%04x) %04x [mask = %04x]\n", offset, data, mem_mask);
+ LOG("cfgin_w (%d)\n", state);
+
+ if (state == 0)
+ {
+ // buddha memory is also active at this point
+ m_zorro->space().install_device(0xe80000, 0xe8ffff, *this, &buddha_device::mmio_map);
- mem_mask = (mem_mask << 8) | (mem_mask >> 8);
- data = (data << 8) | (data >> 8);
+ // setup autoconfig
+ autoconfig_board_type(BOARD_TYPE_ZORRO2);
+ autoconfig_board_size(BOARD_SIZE_64K);
+ autoconfig_link_into_memory(false);
+ autoconfig_rom_vector_valid(true);
+ autoconfig_multi_device(false);
+ autoconfig_8meg_preferred(false);
+ autoconfig_can_shutup(true);
+ autoconfig_product(0);
+ autoconfig_manufacturer(4626);
+ autoconfig_serial(0x00000000);
+ autoconfig_rom_vector(0x1000);
- m_ata_1->write_cs1((offset >> 1) & 0x07, data, mem_mask);
+ // install autoconfig handler
+ m_zorro->space().install_readwrite_handler(0xe80000, 0xe8007f,
+ read16_delegate(*this, FUNC(amiga_autoconfig::autoconfig_read)),
+ write16_delegate(*this, FUNC(amiga_autoconfig::autoconfig_write)), 0xffff);
+ }
}
+
+} // namespace bus::amiga::zorro
diff --git a/src/devices/bus/amiga/zorro/buddha.h b/src/devices/bus/amiga/zorro/buddha.h
index bf671902cc0..09b0a39b4f7 100644
--- a/src/devices/bus/amiga/zorro/buddha.h
+++ b/src/devices/bus/amiga/zorro/buddha.h
@@ -1,5 +1,5 @@
-// license:GPL-2.0+
-// copyright-holders:Dirk Best
+// license: GPL-2.0+
+// copyright-holders: Dirk Best
/***************************************************************************
Buddha
@@ -15,15 +15,15 @@
#include "zorro.h"
#include "machine/autoconfig.h"
-#include "machine/ataintf.h"
+#include "bus/ata/ataintf.h"
+namespace bus::amiga::zorro {
+
//**************************************************************************
// TYPE DEFINITIONS
//**************************************************************************
-// ======================> buddha_device
-
class buddha_device : public device_t, public device_zorro2_card_interface, public amiga_autoconfig
{
public:
@@ -31,52 +31,56 @@ public:
buddha_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
protected:
- // device-level overrides
- virtual void device_add_mconfig(machine_config &config) override;
- virtual const tiny_rom_entry *device_rom_region() const override;
+ virtual void device_add_mconfig(machine_config &config) override ATTR_COLD;
+ virtual const tiny_rom_entry *device_rom_region() const override ATTR_COLD;
- virtual void device_start() override;
- virtual void device_reset() override;
+ 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;
+ virtual void busrst_w(int state) override;
// amiga_autoconfig overrides
virtual void autoconfig_base_address(offs_t address) override;
private:
+ void mmio_map(address_map &map) ATTR_COLD;
+
// speed register
- DECLARE_READ16_MEMBER( speed_r );
- DECLARE_WRITE16_MEMBER( speed_w );
+ uint16_t speed_r(offs_t offset, uint16_t mem_mask = ~0);
+ void speed_w(offs_t offset, uint16_t data, uint16_t mem_mask = ~0);
// ide register
- DECLARE_READ16_MEMBER( ide_0_cs0_r );
- DECLARE_WRITE16_MEMBER( ide_0_cs0_w );
- DECLARE_READ16_MEMBER( ide_0_cs1_r );
- DECLARE_WRITE16_MEMBER( ide_0_cs1_w );
- DECLARE_READ16_MEMBER( ide_1_cs0_r );
- DECLARE_WRITE16_MEMBER( ide_1_cs0_w );
- DECLARE_READ16_MEMBER( ide_1_cs1_r );
- DECLARE_WRITE16_MEMBER( ide_1_cs1_w );
+ uint16_t ide_0_cs0_r(offs_t offset, uint16_t mem_mask = ~0);
+ void ide_0_cs0_w(offs_t offset, uint16_t data, uint16_t mem_mask = ~0);
+ uint16_t ide_0_cs1_r(offs_t offset, uint16_t mem_mask = ~0);
+ void ide_0_cs1_w(offs_t offset, uint16_t data, uint16_t mem_mask = ~0);
+ uint16_t ide_1_cs0_r(offs_t offset, uint16_t mem_mask = ~0);
+ void ide_1_cs0_w(offs_t offset, uint16_t data, uint16_t mem_mask = ~0);
+ uint16_t ide_1_cs1_r(offs_t offset, uint16_t mem_mask = ~0);
+ void ide_1_cs1_w(offs_t offset, uint16_t data, uint16_t mem_mask = ~0);
// interrupt register
- DECLARE_READ16_MEMBER( ide_0_interrupt_r );
- DECLARE_READ16_MEMBER( ide_1_interrupt_r );
- DECLARE_WRITE16_MEMBER( ide_interrupt_enable_w );
- DECLARE_WRITE_LINE_MEMBER( ide_0_interrupt_w );
- DECLARE_WRITE_LINE_MEMBER( ide_1_interrupt_w );
+ 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);
+ void ide_0_interrupt_w(int state);
+ void ide_1_interrupt_w(int state);
- void mmio_map(address_map &map);
+ uint8_t rom_r(offs_t offset);
required_device<ata_interface_device> m_ata_0;
required_device<ata_interface_device> m_ata_1;
+ required_region_ptr<uint8_t> m_bootrom;
bool m_ide_interrupts_enabled;
int m_ide_0_interrupt;
int m_ide_1_interrupt;
};
-// device type definition
-DECLARE_DEVICE_TYPE(BUDDHA, buddha_device)
+} // namespace bus::amiga::zorro
+
+// device type declaration
+DECLARE_DEVICE_TYPE_NS(AMIGA_BUDDHA, bus::amiga::zorro, buddha_device)
#endif // MAME_BUS_AMIGA_ZORRO_BUDDHA_H
diff --git a/src/devices/bus/amiga/zorro/cards.cpp b/src/devices/bus/amiga/zorro/cards.cpp
index 396069b537f..9ca8631e7cf 100644
--- a/src/devices/bus/amiga/zorro/cards.cpp
+++ b/src/devices/bus/amiga/zorro/cards.cpp
@@ -1,8 +1,8 @@
-// license:GPL-2.0+
-// copyright-holders:Dirk Best
+// license: GPL-2.0+
+// copyright-holders: Dirk Best
/***************************************************************************
- Amiga Zorro Cards
+ Amiga Zorro-II Cards
***************************************************************************/
@@ -12,47 +12,30 @@
#include "a2052.h"
#include "a2058.h"
#include "a2065.h"
+#include "a2091.h"
#include "a2232.h"
-#include "a590.h"
-#include "action_replay.h"
#include "buddha.h"
+#include "merlin.h"
+#include "oktagon2008.h"
+#include "picasso2.h"
+#include "rainbow2.h"
+#include "ripple.h"
+#include "toccata.h"
-void a1000_expansion_cards(device_slot_interface &device)
-{
-}
-
-void a500_expansion_cards(device_slot_interface &device)
-{
- device.option_add("ar1", ACTION_REPLAY_MK1);
- device.option_add("ar2", ACTION_REPLAY_MK2);
- device.option_add("ar3", ACTION_REPLAY_MK3);
- device.option_add("a590", A590);
-}
-
-void a2000_expansion_cards(device_slot_interface &device)
-{
- device.option_add("ar1", ACTION_REPLAY_MK1);
- device.option_add("ar2", ACTION_REPLAY_MK2);
- device.option_add("ar3", ACTION_REPLAY_MK3);
-}
-
void zorro2_cards(device_slot_interface &device)
{
- device.option_add("a2052", A2052);
- device.option_add("a2058", A2058);
- device.option_add("a2065", A2065);
- device.option_add("a2091", A2091);
- device.option_add("a2232", A2232);
- device.option_add("buddha", BUDDHA);
-}
-
-void zorro3_cards(device_slot_interface &device)
-{
- device.option_add("a2052", A2052);
- device.option_add("a2058", A2058);
- device.option_add("a2065", A2065);
- device.option_add("a2091", A2091);
- device.option_add("a2232", A2232);
- device.option_add("buddha", BUDDHA);
+ device.option_add("a2052", AMIGA_A2052);
+ device.option_add("a2058", AMIGA_A2058);
+ device.option_add("a2065", AMIGA_A2065);
+ device.option_add("a2091", AMIGA_A2091);
+ device.option_add("a2232", AMIGA_A2232);
+ device.option_add("buddha", AMIGA_BUDDHA);
+ device.option_add("merlin", AMIGA_MERLIN);
+ device.option_add("oktagon2008", AMIGA_OKTAGON2008);
+ device.option_add("picasso2p", AMIGA_PICASSO2P);
+ device.option_add("rainbow2", AMIGA_RAINBOW2);
+ device.option_add("framemaster", AMIGA_FRAMEMASTER);
+ device.option_add("ripple", AMIGA_RIPPLE);
+ device.option_add("toccata", AMIGA_TOCCATA);
}
diff --git a/src/devices/bus/amiga/zorro/cards.h b/src/devices/bus/amiga/zorro/cards.h
index 6daa99bf265..103c68dbd51 100644
--- a/src/devices/bus/amiga/zorro/cards.h
+++ b/src/devices/bus/amiga/zorro/cards.h
@@ -1,23 +1,8 @@
-// license:GPL-2.0+
-// copyright-holders:Dirk Best
+// license: GPL-2.0+
+// copyright-holders: Dirk Best
/***************************************************************************
- Amiga Zorro Cards
-
- There are different card types and layouts:
-
- * 86-pin expansion slot
- - A1000
- - A500 (rotated slot)
- - A2000/B2000 (internal slot)
- * Zorro-II
- - A2000
- - B2000
- * Zorro-III
- - A3000, A4000
-
- For details see zorro.h. Zorro-II cards can be inserted into
- Zorro-III slots.
+ Amiga Zorro-II Cards
***************************************************************************/
@@ -27,11 +12,6 @@
#pragma once
-void a1000_expansion_cards(device_slot_interface &device);
-void a500_expansion_cards(device_slot_interface &device);
-void a2000_expansion_cards(device_slot_interface &device);
-
-void zorro2_cards(device_slot_interface &device);
-void zorro3_cards(device_slot_interface &device);
+void zorro2_cards(device_slot_interface &device) ATTR_COLD;
#endif // MAME_BUS_AMIGA_ZORRO_CARDS_H
diff --git a/src/devices/bus/amiga/zorro/merlin.cpp b/src/devices/bus/amiga/zorro/merlin.cpp
new file mode 100644
index 00000000000..a55497ab23b
--- /dev/null
+++ b/src/devices/bus/amiga/zorro/merlin.cpp
@@ -0,0 +1,191 @@
+// license: GPL-2.0+
+// copyright-holders: Dirk Best
+/***************************************************************************
+
+ XPert/ProDev Merlin
+
+ RTG graphics card for Amiga 2000/3000/4000
+
+ Hardware:
+ - Tseng Labs ET4000W32
+ - 1, 2 (maximum in Zorro-II mode) or 4 MB RAM
+ - 33 MHz and 14.31818 MHz XTAL
+ - BT482KPJ85 RAMDAC
+ - Serial EEPROM with stored serial number (unknown type)
+ - DG894 (video switcher)
+ - Optional video module: X-Calibur (S-VHS/Composite input/output)
+
+ TODO:
+ - Skeleton
+
+***************************************************************************/
+
+#include "emu.h"
+#include "merlin.h"
+#include "screen.h"
+
+#define VERBOSE (LOG_GENERAL)
+
+#include "logmacro.h"
+
+
+//**************************************************************************
+// TYPE DEFINITIONS
+//**************************************************************************
+
+DEFINE_DEVICE_TYPE(AMIGA_MERLIN, bus::amiga::zorro::merlin_device, "amiga_merlin", "Merlin RTG")
+
+namespace bus::amiga::zorro {
+
+merlin_device::merlin_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) :
+ device_t(mconfig, AMIGA_MERLIN, tag, owner, clock),
+ device_zorro2_card_interface(mconfig, *this),
+ m_vga(*this, "vga"),
+ m_ramdac(*this, "ramdac"),
+ m_autoconfig_memory_done(false)
+{
+}
+
+
+//**************************************************************************
+// ADDRESS MAPS
+//**************************************************************************
+
+void merlin_device::mmio_map(address_map &map)
+{
+ map(0x0000, 0xffff).unmaprw();
+ map(0x0000, 0x001f).m(m_ramdac, FUNC(bt482_device::map)).umask32(0x00ff0000); // TODO: 16-bit
+ map(0x03b0, 0x03df).m(m_vga, FUNC(et4kw32i_vga_device::io_map));
+ //map(0x0401, 0x0401) monitor switch
+ map(0x210a, 0x210a).mirror(0x70).rw(m_vga, FUNC(et4kw32i_vga_device::acl_index_r), FUNC(et4kw32i_vga_device::acl_index_w));
+ map(0x210b, 0x210b).mirror(0x70).rw(m_vga, FUNC(et4kw32i_vga_device::acl_data_r), FUNC(et4kw32i_vga_device::acl_data_w));
+}
+
+
+//**************************************************************************
+// MACHINE DEFINITIONS
+//**************************************************************************
+
+void merlin_device::device_add_mconfig(machine_config &config)
+{
+ screen_device &screen(SCREEN(config, "screen", SCREEN_TYPE_RASTER));
+ screen.set_raw(33_MHz_XTAL, 900, 0, 640, 526, 0, 480); // TODO
+ screen.set_screen_update(FUNC(merlin_device::screen_update));
+
+ ET4KW32I_VGA(config, m_vga, 0); // should be ET4000W32
+ m_vga->set_screen("screen");
+ m_vga->set_vram_size(0x200000);
+ m_vga->vsync_cb().set([this](int state) { m_zorro->int6_w(state); });
+
+ BT482(config, m_ramdac, 0);
+}
+
+
+//**************************************************************************
+// MACHINE EMULATION
+//**************************************************************************
+
+void merlin_device::device_start()
+{
+}
+
+void merlin_device::busrst_w(int state)
+{
+ if (state == 0)
+ m_autoconfig_memory_done = false;
+}
+
+uint32_t merlin_device::screen_update(screen_device &screen, bitmap_rgb32 &bitmap, const rectangle &cliprect)
+{
+ m_vga->screen_update(screen, bitmap, cliprect);
+ m_ramdac->screen_update(screen, bitmap, cliprect);
+
+ return 0;
+}
+
+
+//**************************************************************************
+// AUTOCONFIG
+//**************************************************************************
+
+void merlin_device::autoconfig_base_address(offs_t address)
+{
+ LOG("autoconfig_base_address received: 0x%06x\n", address);
+
+ if (!m_autoconfig_memory_done)
+ {
+ LOG("-> installing merlin memory\n");
+
+ m_zorro->space().install_readwrite_handler(address, address + 0x1fffff,
+ emu::rw_delegate(m_vga, FUNC(et4kw32i_vga_device::mem_r)),
+ emu::rw_delegate(m_vga, FUNC(et4kw32i_vga_device::mem_w)), 0xffff);
+
+ m_autoconfig_memory_done = true;
+
+ // configure next
+ cfgin_w(0);
+ }
+ else
+ {
+ LOG("-> installing merlin registers\n");
+
+ // install merlin registers
+ m_zorro->space().install_device(address, address + 0x0ffff, *this, &merlin_device::mmio_map);
+
+ // stop responding to default autoconfig
+ m_zorro->space().unmap_readwrite(0xe80000, 0xe8007f);
+
+ // we're done
+ m_zorro->cfgout_w(0);
+ }
+}
+
+void merlin_device::cfgin_w(int state)
+{
+ LOG("cfgin_w (%d)\n", state);
+
+ if (state != 0)
+ return;
+
+ if (!m_autoconfig_memory_done)
+ {
+ LOG("autoconfig for memory\n");
+
+ // setup autoconfig for memory
+ autoconfig_board_type(BOARD_TYPE_ZORRO2);
+ autoconfig_board_size(BOARD_SIZE_2M);
+ autoconfig_link_into_memory(false);
+ autoconfig_rom_vector_valid(false);
+ autoconfig_multi_device(false); // ?
+ autoconfig_8meg_preferred(false);
+ autoconfig_can_shutup(true); // ?
+ autoconfig_product(3);
+ autoconfig_manufacturer(2117);
+ autoconfig_serial(0x00000000);
+ autoconfig_rom_vector(0x0000);
+
+ // install autoconfig handler
+ m_zorro->space().install_readwrite_handler(0xe80000, 0xe8007f,
+ read16_delegate(*this, FUNC(amiga_autoconfig::autoconfig_read)),
+ write16_delegate(*this, FUNC(amiga_autoconfig::autoconfig_write)), 0xffff);
+ }
+ else
+ {
+ LOG("autoconfig for registers\n");
+
+ // setup autoconfig for registers
+ autoconfig_board_type(BOARD_TYPE_ZORRO2);
+ autoconfig_board_size(BOARD_SIZE_64K);
+ autoconfig_link_into_memory(false);
+ autoconfig_rom_vector_valid(false);
+ autoconfig_multi_device(false); // ?
+ autoconfig_8meg_preferred(false);
+ autoconfig_can_shutup(true); // ?
+ autoconfig_product(4);
+ autoconfig_manufacturer(2117);
+ autoconfig_serial(0x00000000);
+ autoconfig_rom_vector(0x0000);
+ }
+}
+
+} // namespace bus::amiga::zorro
diff --git a/src/devices/bus/amiga/zorro/merlin.h b/src/devices/bus/amiga/zorro/merlin.h
new file mode 100644
index 00000000000..4a7a06bdcf8
--- /dev/null
+++ b/src/devices/bus/amiga/zorro/merlin.h
@@ -0,0 +1,56 @@
+// license: GPL-2.0+
+// copyright-holders: Dirk Best
+/***************************************************************************
+
+ XPert/ProDev Merlin
+
+ RTG graphics card for Amiga 2000/3000/4000
+
+***************************************************************************/
+
+#ifndef MAME_BUS_AMIGA_ZORRO_MERLIN_H
+#define MAME_BUS_AMIGA_ZORRO_MERLIN_H
+
+#pragma once
+
+#include "zorro.h"
+#include "machine/autoconfig.h"
+#include "video/bt48x.h"
+#include "video/pc_vga_tseng.h"
+
+
+namespace bus::amiga::zorro {
+
+class merlin_device : public device_t, public device_zorro2_card_interface, public amiga_autoconfig
+{
+public:
+ merlin_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
+
+protected:
+ virtual void device_add_mconfig(machine_config &config) override ATTR_COLD;
+
+ virtual void device_start() override ATTR_COLD;
+
+ // device_zorro2_card_interface overrides
+ virtual void cfgin_w(int state) override;
+ virtual void busrst_w(int state) override;
+
+ // amiga_autoconfig overrides
+ virtual void autoconfig_base_address(offs_t address) override;
+
+private:
+ void mmio_map(address_map &map) ATTR_COLD;
+ uint32_t screen_update(screen_device &screen, bitmap_rgb32 &bitmap, const rectangle &cliprect);
+
+ required_device<et4kw32i_vga_device> m_vga;
+ required_device<bt482_device> m_ramdac;
+
+ bool m_autoconfig_memory_done;
+};
+
+} // namespace bus::amiga::zorro
+
+// device type declaration
+DECLARE_DEVICE_TYPE_NS(AMIGA_MERLIN, bus::amiga::zorro, merlin_device)
+
+#endif // MAME_BUS_AMIGA_ZORRO_MERLIN_H
diff --git a/src/devices/bus/amiga/zorro/oktagon2008.cpp b/src/devices/bus/amiga/zorro/oktagon2008.cpp
new file mode 100644
index 00000000000..fc0dbfb2cfe
--- /dev/null
+++ b/src/devices/bus/amiga/zorro/oktagon2008.cpp
@@ -0,0 +1,268 @@
+// license:BSD-3-clause
+// copyright-holders:AJR
+/***************************************************************************
+
+ BSC / Alfa Data Oktagon 2008 SCSI controller (2092/5/8)
+
+***************************************************************************/
+
+#include "emu.h"
+#include "oktagon2008.h"
+
+#include "bus/nscsi/devices.h"
+#include "machine/autoconfig.h"
+#include "machine/i2cmem.h"
+#include "machine/ncr53c90.h"
+
+#define VERBOSE (0)
+#include "logmacro.h"
+
+
+namespace bus::amiga::zorro {
+
+class oktagon2008_device : public device_t, public device_zorro2_card_interface, public amiga_autoconfig
+{
+public:
+ oktagon2008_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
+
+protected:
+ // device_t overrides
+ virtual void device_start() override ATTR_COLD;
+ virtual ioport_constructor device_input_ports() const override ATTR_COLD;
+ virtual void device_add_mconfig(machine_config &config) override ATTR_COLD;
+ virtual const tiny_rom_entry *device_rom_region() const override ATTR_COLD;
+
+ // device_zorro2_card_interface overrides
+ virtual void busrst_w(int state) override;
+ virtual void cfgin_w(int state) override;
+
+ // amiga_autoconfig overrides
+ virtual void autoconfig_base_address(offs_t address) override;
+
+private:
+ u8 rom_r(offs_t offset);
+ u8 int_control_r();
+ void int_control_w(u8 data);
+ u8 i2c_sda_r();
+ void i2c_scl_w(u8 data);
+ void i2c_sda_w(u8 data);
+ void irq_w(int state);
+
+ required_device<ncr53c94_device> m_scsic;
+ required_device<i2cmem_device> m_eeprom;
+ required_region_ptr<u8> m_rom;
+ required_ioport m_jumpers;
+
+ std::unique_ptr<u16[]> m_ram;
+ bool m_ram_autoconfig_needed;
+ bool m_scsic_int;
+ bool m_scsic_int_enable;
+};
+
+
+oktagon2008_device::oktagon2008_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
+ : device_t(mconfig, AMIGA_OKTAGON2008, tag, owner, clock)
+ , device_zorro2_card_interface(mconfig, *this)
+ , m_scsic(*this, "scsi:7:scsic")
+ , m_eeprom(*this, "eeprom")
+ , m_rom(*this, "rom")
+ , m_jumpers(*this, "JUMPERS")
+ , m_ram_autoconfig_needed(false)
+ , m_scsic_int(false)
+ , m_scsic_int_enable(true)
+{
+}
+
+u8 oktagon2008_device::rom_r(offs_t offset)
+{
+ return m_rom[offset];
+}
+
+u8 oktagon2008_device::int_control_r()
+{
+ return m_scsic_int_enable ? 0x80 : 0;
+}
+
+void oktagon2008_device::int_control_w(u8 data)
+{
+ if (m_scsic_int_enable != BIT(data, 7))
+ {
+ LOG("%s: 53C94 interrupt %sabled\n", machine().describe_context(), BIT(data, 7) ? "en" : "dis");
+ m_scsic_int_enable = BIT(data, 7);
+ m_zorro->int2_w(m_scsic_int && m_scsic_int_enable);
+ }
+}
+
+u8 oktagon2008_device::i2c_sda_r()
+{
+ return m_eeprom->read_sda() << 7;
+}
+
+void oktagon2008_device::i2c_scl_w(u8 data)
+{
+ m_eeprom->write_scl(BIT(data, 7));
+}
+
+void oktagon2008_device::i2c_sda_w(u8 data)
+{
+ m_eeprom->write_sda(BIT(data, 7));
+}
+
+void oktagon2008_device::irq_w(int state)
+{
+ m_scsic_int = state;
+ if (m_scsic_int_enable)
+ m_zorro->int2_w(state);
+}
+
+void oktagon2008_device::device_start()
+{
+ m_ram = make_unique_clear<u16[]>(0x800000 / 2);
+
+ save_pointer(NAME(m_ram), 0x800000 / 2);
+ save_item(NAME(m_ram_autoconfig_needed));
+ save_item(NAME(m_scsic_int));
+}
+
+void oktagon2008_device::busrst_w(int state)
+{
+ if (!state)
+ {
+ int_control_w(0);
+ m_ram_autoconfig_needed = true;
+ }
+}
+
+void oktagon2008_device::autoconfig_base_address(offs_t address)
+{
+ LOG("Autoconfig base address (%s) = $%06X\n", m_ram_autoconfig_needed ? "RAM" : "controller", address);
+
+ if (m_ram_autoconfig_needed)
+ {
+ int memory_size = m_jumpers->read() & 0x03;
+ LOG("%u bytes of RAM installed\n", (memory_size + 1) * 0x200000);
+ m_zorro->space().install_ram(address, address + (memory_size + 1) * 0x200000 - 1, m_ram.get());
+
+ m_ram_autoconfig_needed = false;
+ cfgin_w(0);
+ }
+ else
+ {
+ // Diag init read from $Ex0001-$Ex0FFF; device drivers read from $Ex2001-$ExFFFF
+ m_zorro->space().install_read_handler(address + 0x0000, address + 0xffff,
+ read8sm_delegate(*this, FUNC(oktagon2008_device::rom_r)), 0x00ff);
+
+ m_zorro->space().install_readwrite_handler(address + 0x1000, address + 0x1fff,
+ read16smo_delegate(*m_scsic, FUNC(ncr53c94_device::dma16_swap_r)),
+ write16smo_delegate(*m_scsic, FUNC(ncr53c94_device::dma16_swap_w)), 0xffff);
+ m_zorro->space().install_device(address + 0x3000, address + 0x301f, *m_scsic, &ncr53c94_device::map, 0xff00);
+
+ m_zorro->space().install_readwrite_handler(address + 0x8000, address + 0x8001,
+ read8smo_delegate(*this, FUNC(oktagon2008_device::int_control_r)),
+ write8smo_delegate(*this, FUNC(oktagon2008_device::int_control_w)), 0xff00);
+ m_zorro->space().install_readwrite_handler(address + 0x8010, address + 0x8011,
+ read8smo_delegate(*this, FUNC(oktagon2008_device::i2c_sda_r)),
+ write8smo_delegate(*this, FUNC(oktagon2008_device::i2c_scl_w)), 0xff00);
+ m_zorro->space().install_readwrite_handler(address + 0x8018, address + 0x8019,
+ read8smo_delegate(*this, FUNC(oktagon2008_device::i2c_sda_r)),
+ write8smo_delegate(*this, FUNC(oktagon2008_device::i2c_sda_w)), 0xff00);
+
+ m_zorro->space().unmap_readwrite(0xe80000, 0xe8007f);
+ m_zorro->cfgout_w(0);
+ }
+}
+
+void oktagon2008_device::cfgin_w(int state)
+{
+ if (!state)
+ {
+ LOG("CFGIN received for %s\n", m_ram_autoconfig_needed ? "RAM" : "controller");
+
+ if (m_ram_autoconfig_needed)
+ {
+ int memory_size = m_jumpers->read() & 0x03;
+
+ autoconfig_board_type(BOARD_TYPE_ZORRO2);
+ if (memory_size == 0)
+ autoconfig_board_size(BOARD_SIZE_2M);
+ else if (memory_size == 1)
+ autoconfig_board_size(BOARD_SIZE_4M);
+ else
+ autoconfig_board_size(BOARD_SIZE_8M);
+ autoconfig_link_into_memory(false);
+ autoconfig_rom_vector_valid(false);
+ autoconfig_multi_device(false);
+ autoconfig_8meg_preferred(false);
+ autoconfig_can_shutup(true);
+ autoconfig_product(8);
+ autoconfig_manufacturer(2092);
+ autoconfig_serial(0x00000000);
+ autoconfig_rom_vector(0x0000);
+
+ m_zorro->space().install_readwrite_handler(0xe80000, 0xe8007f,
+ read16_delegate(*this, FUNC(amiga_autoconfig::autoconfig_read)),
+ write16_delegate(*this, FUNC(amiga_autoconfig::autoconfig_write)), 0xffff);
+ }
+ else
+ {
+ autoconfig_board_type(BOARD_TYPE_ZORRO2);
+ autoconfig_board_size(BOARD_SIZE_64K);
+ autoconfig_link_into_memory(false);
+ autoconfig_rom_vector_valid(true);
+ autoconfig_multi_device(false);
+ autoconfig_8meg_preferred(false);
+ autoconfig_can_shutup(true);
+ autoconfig_product(5);
+ autoconfig_manufacturer(2092);
+ autoconfig_serial(0x00000000);
+ autoconfig_rom_vector(0x0001);
+ }
+ }
+}
+
+static INPUT_PORTS_START(oktagon2008)
+ PORT_START("JUMPERS")
+ PORT_CONFNAME(0x03, 0x03, "Memory Size")
+ PORT_CONFSETTING(0x00, "2 MB")
+ PORT_CONFSETTING(0x01, "4 MB")
+ PORT_CONFSETTING(0x02, "6 MB")
+ PORT_CONFSETTING(0x03, "8 MB")
+INPUT_PORTS_END
+
+ioport_constructor oktagon2008_device::device_input_ports() const
+{
+ return INPUT_PORTS_NAME(oktagon2008);
+}
+
+void oktagon2008_device::device_add_mconfig(machine_config &config)
+{
+ NSCSI_BUS(config, "scsi");
+ NSCSI_CONNECTOR(config, "scsi:0", default_scsi_devices, "harddisk");
+ NSCSI_CONNECTOR(config, "scsi:1", default_scsi_devices, nullptr);
+ NSCSI_CONNECTOR(config, "scsi:2", default_scsi_devices, nullptr);
+ NSCSI_CONNECTOR(config, "scsi:3", default_scsi_devices, nullptr);
+ NSCSI_CONNECTOR(config, "scsi:4", default_scsi_devices, nullptr);
+ NSCSI_CONNECTOR(config, "scsi:5", default_scsi_devices, nullptr);
+ NSCSI_CONNECTOR(config, "scsi:6", default_scsi_devices, nullptr);
+ NSCSI_CONNECTOR(config, "scsi:7").option_set("scsic", NCR53C94).machine_config([this](device_t *device) {
+ device->set_clock(25_MHz_XTAL);
+ downcast<ncr53c94_device &>(*device).set_busmd(ncr53c94_device::BUSMD_1);
+ downcast<ncr53c94_device &>(*device).irq_handler_cb().set(*this, FUNC(oktagon2008_device::irq_w));
+ });
+
+ I2C_24C04(config, m_eeprom);
+}
+
+ROM_START(oktagon2008)
+ ROM_REGION(0x8000, "rom", 0)
+ ROM_LOAD("oktagon 2008 rev7 bs rl-v6.12.bin", 0x0000, 0x8000, CRC(bb0d2f6a) SHA1(56c441fa37d193393081b2e8ceae823bc7e97e49)) // Mitsubishi M5L27256K,54810C
+ROM_END
+
+const tiny_rom_entry *oktagon2008_device::device_rom_region() const
+{
+ return ROM_NAME(oktagon2008);
+}
+
+} // bus::amiga::zorro
+
+DEFINE_DEVICE_TYPE_PRIVATE(AMIGA_OKTAGON2008, device_zorro2_card_interface, bus::amiga::zorro::oktagon2008_device, "amiga_oktagon2008", "Oktagon 2008 SCSI controller")
diff --git a/src/devices/bus/amiga/zorro/oktagon2008.h b/src/devices/bus/amiga/zorro/oktagon2008.h
new file mode 100644
index 00000000000..66bb47529c8
--- /dev/null
+++ b/src/devices/bus/amiga/zorro/oktagon2008.h
@@ -0,0 +1,14 @@
+// license:BSD-3-clause
+// copyright-holders:AJR
+
+#ifndef MAME_BUS_AMIGA_ZORRO_OKTAGON2008_H
+#define MAME_BUS_AMIGA_ZORRO_OKTAGON2008_H
+
+#pragma once
+
+#include "zorro.h"
+
+// device type declaration
+DECLARE_DEVICE_TYPE(AMIGA_OKTAGON2008, device_zorro2_card_interface)
+
+#endif // MAME_BUS_AMIGA_ZORRO_OKTAGON2008_H
diff --git a/src/devices/bus/amiga/zorro/picasso2.cpp b/src/devices/bus/amiga/zorro/picasso2.cpp
new file mode 100644
index 00000000000..9c4f4baa47f
--- /dev/null
+++ b/src/devices/bus/amiga/zorro/picasso2.cpp
@@ -0,0 +1,213 @@
+// license: GPL-2.0+
+// copyright-holders: Dirk Best
+/***************************************************************************
+
+ Village Tronic Picasso II/Picasso II+
+
+ RTG graphics card for Amiga 2000/3000/4000
+
+ Hardware:
+ - Cirrus Logic CL-GD5426 or CL-GD5428
+ - 1 or 2 MB RAM
+ - 25 MHz (only II+) and 14.31818 MHz XTAL
+
+ TODO:
+ - Not working, VGA core needs work
+ - Interrupts?
+ - Segmented mode (jumper setting, autoconfig id 13)
+
+***************************************************************************/
+
+#include "emu.h"
+#include "picasso2.h"
+#include "screen.h"
+
+#define VERBOSE (LOG_GENERAL)
+
+#include "logmacro.h"
+
+
+//**************************************************************************
+// TYPE DEFINITIONS
+//**************************************************************************
+
+DEFINE_DEVICE_TYPE(AMIGA_PICASSO2P, bus::amiga::zorro::picasso2p_device, "amiga_picasso2p", "Picasso II+ RTG")
+
+namespace bus::amiga::zorro {
+
+picasso2p_device::picasso2p_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) :
+ device_t(mconfig, AMIGA_PICASSO2P, tag, owner, clock),
+ device_memory_interface(mconfig, *this),
+ device_zorro2_card_interface(mconfig, *this),
+ m_vga(*this, "vga"),
+ m_autoconfig_memory_done(false)
+{
+ m_vga_space_config = address_space_config("vga_regs", ENDIANNESS_BIG, 8, 12, 0, address_map_constructor(FUNC(picasso2p_device::vga_map), this));
+}
+
+
+//**************************************************************************
+// ADDRESS MAPS
+//**************************************************************************
+
+void picasso2p_device::mmio_map(address_map &map)
+{
+ map(0x0000, 0x0fff).rw(FUNC(picasso2p_device::vga0_r), FUNC(picasso2p_device::vga0_w)).umask16(0xffff);
+ map(0x1000, 0x1fff).rw(FUNC(picasso2p_device::vga1_r), FUNC(picasso2p_device::vga1_w)).umask16(0xffff);
+ map(0x46e8, 0x46e8).w(m_vga, FUNC(cirrus_gd5428_vga_device::mode_setup_w));
+}
+
+void picasso2p_device::vga_map(address_map &map)
+{
+ map(0x102, 0x102).unmaprw(); // TODO
+ map(0x3b0, 0x3df).m(m_vga, FUNC(cirrus_gd5428_vga_device::io_map));
+}
+
+
+//**************************************************************************
+// MACHINE DEFINITIONS
+//**************************************************************************
+
+void picasso2p_device::device_add_mconfig(machine_config &config)
+{
+ screen_device &screen(SCREEN(config, "screen", SCREEN_TYPE_RASTER));
+ screen.set_raw(25.1748_MHz_XTAL, 900, 0, 640, 526, 0, 480);
+ screen.set_screen_update(m_vga, FUNC(cirrus_gd5428_vga_device::screen_update));
+
+ CIRRUS_GD5428_VGA(config, m_vga, 0);
+ m_vga->set_screen("screen");
+ m_vga->set_vram_size(0x200000);
+}
+
+
+//**************************************************************************
+// MACHINE EMULATION
+//**************************************************************************
+
+void picasso2p_device::device_start()
+{
+}
+
+void picasso2p_device::busrst_w(int state)
+{
+ if (state == 0)
+ m_autoconfig_memory_done = false;
+}
+
+device_memory_interface::space_config_vector picasso2p_device::memory_space_config() const
+{
+ return space_config_vector {
+ std::make_pair(0, &m_vga_space_config)
+ };
+}
+
+uint8_t picasso2p_device::vga0_r(offs_t offset)
+{
+ LOG("vga0_r: %04x\n", offset);
+ return space(0).read_byte(offset);
+}
+
+void picasso2p_device::vga0_w(offs_t offset, uint8_t data)
+{
+ LOG("vga0_w: %04x = %02x\n", offset, data);
+ space(0).write_byte(offset, data);
+}
+
+uint8_t picasso2p_device::vga1_r(offs_t offset)
+{
+ LOG("vga1_r: %04x (%04x)\n", offset, offset | 1);
+ return space(0).read_byte(offset | 1);
+}
+
+void picasso2p_device::vga1_w(offs_t offset, uint8_t data)
+{
+ LOG("vga1_w: %04x (%04x) = %02x\n", offset, offset | 1, data);
+ space(0).write_byte(offset | 1, data);
+}
+
+
+//**************************************************************************
+// AUTOCONFIG
+//**************************************************************************
+
+void picasso2p_device::autoconfig_base_address(offs_t address)
+{
+ LOG("autoconfig_base_address received: 0x%06x\n", address);
+
+ if (!m_autoconfig_memory_done)
+ {
+ LOG("-> installing picasso2p memory\n");
+
+ m_zorro->space().install_readwrite_handler(address, address + 0x1fffff,
+ emu::rw_delegate(m_vga, FUNC(cirrus_gd5428_vga_device::mem_r)),
+ emu::rw_delegate(m_vga, FUNC(cirrus_gd5428_vga_device::mem_w)), 0xffff);
+
+ m_autoconfig_memory_done = true;
+
+ // configure next
+ cfgin_w(0);
+ }
+ else
+ {
+ LOG("-> installing picasso2p registers\n");
+
+ // install picasso registers
+ m_zorro->space().install_device(address, address + 0x0ffff, *this, &picasso2p_device::mmio_map);
+
+ // stop responding to default autoconfig
+ m_zorro->space().unmap_readwrite(0xe80000, 0xe8007f);
+
+ // we're done
+ m_zorro->cfgout_w(0);
+ }
+}
+
+void picasso2p_device::cfgin_w(int state)
+{
+ LOG("cfgin_w (%d)\n", state);
+
+ if (state != 0)
+ return;
+
+ if (!m_autoconfig_memory_done)
+ {
+ LOG("autoconfig for memory\n");
+
+ // setup autoconfig for memory
+ autoconfig_board_type(BOARD_TYPE_ZORRO2);
+ autoconfig_board_size(BOARD_SIZE_2M);
+ autoconfig_link_into_memory(false);
+ autoconfig_rom_vector_valid(false);
+ autoconfig_multi_device(false); // ?
+ autoconfig_8meg_preferred(false);
+ autoconfig_can_shutup(true); // ?
+ autoconfig_product(11);
+ autoconfig_manufacturer(2167);
+ autoconfig_serial(0x00000000);
+ autoconfig_rom_vector(0x0000);
+
+ // install autoconfig handler
+ m_zorro->space().install_readwrite_handler(0xe80000, 0xe8007f,
+ read16_delegate(*this, FUNC(amiga_autoconfig::autoconfig_read)),
+ write16_delegate(*this, FUNC(amiga_autoconfig::autoconfig_write)), 0xffff);
+ }
+ else
+ {
+ LOG("autoconfig for registers\n");
+
+ // setup autoconfig for registers
+ autoconfig_board_type(BOARD_TYPE_ZORRO2);
+ autoconfig_board_size(BOARD_SIZE_64K);
+ autoconfig_link_into_memory(false);
+ autoconfig_rom_vector_valid(false);
+ autoconfig_multi_device(false); // ?
+ autoconfig_8meg_preferred(false);
+ autoconfig_can_shutup(true); // ?
+ autoconfig_product(12);
+ autoconfig_manufacturer(2167);
+ autoconfig_serial(0x00000000);
+ autoconfig_rom_vector(0x0000);
+ }
+}
+
+} // namespace bus::amiga::zorro
diff --git a/src/devices/bus/amiga/zorro/picasso2.h b/src/devices/bus/amiga/zorro/picasso2.h
new file mode 100644
index 00000000000..1804c1a22eb
--- /dev/null
+++ b/src/devices/bus/amiga/zorro/picasso2.h
@@ -0,0 +1,63 @@
+// license: GPL-2.0+
+// copyright-holders: Dirk Best
+/***************************************************************************
+
+ Village Tronic Picasso II/Picasso II+
+
+ RTG graphics card for Amiga 2000/3000/4000
+
+***************************************************************************/
+
+#ifndef MAME_BUS_AMIGA_ZORRO_PICASSO2_H
+#define MAME_BUS_AMIGA_ZORRO_PICASSO2_H
+
+#pragma once
+
+#include "zorro.h"
+#include "machine/autoconfig.h"
+#include "video/pc_vga_cirrus.h"
+
+
+namespace bus::amiga::zorro {
+
+class picasso2p_device : public device_t, public device_memory_interface, public device_zorro2_card_interface, public amiga_autoconfig
+{
+public:
+ picasso2p_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
+
+protected:
+ virtual void device_add_mconfig(machine_config &config) override ATTR_COLD;
+
+ virtual void device_start() override ATTR_COLD;
+
+ // device_memory_interface
+ virtual space_config_vector memory_space_config() const override;
+
+ // device_zorro2_card_interface overrides
+ virtual void cfgin_w(int state) override;
+ virtual void busrst_w(int state) override;
+
+ // amiga_autoconfig overrides
+ virtual void autoconfig_base_address(offs_t address) override;
+
+private:
+ void mmio_map(address_map &map) ATTR_COLD;
+ void vga_map(address_map &map) ATTR_COLD;
+
+ uint8_t vga0_r(offs_t offset);
+ void vga0_w(offs_t offset, uint8_t data);
+ uint8_t vga1_r(offs_t offset);
+ void vga1_w(offs_t offset, uint8_t data);
+
+ required_device<cirrus_gd5428_vga_device> m_vga;
+ address_space_config m_vga_space_config;
+
+ bool m_autoconfig_memory_done;
+};
+
+} // namespace bus::amiga::zorro
+
+// device type declaration
+DECLARE_DEVICE_TYPE_NS(AMIGA_PICASSO2P, bus::amiga::zorro, picasso2p_device)
+
+#endif // MAME_BUS_AMIGA_ZORRO_PICASSO2_H
diff --git a/src/devices/bus/amiga/zorro/rainbow2.cpp b/src/devices/bus/amiga/zorro/rainbow2.cpp
new file mode 100644
index 00000000000..1cd8b38ac09
--- /dev/null
+++ b/src/devices/bus/amiga/zorro/rainbow2.cpp
@@ -0,0 +1,222 @@
+// license: GPL-2.0+
+// copyright-holders: Dirk Best
+/***************************************************************************
+
+ Omega Datentechnik Rainbow II (2145/32)
+ Ingenieurbuero Helfrich Rainbow II (2195/32)
+ BSC FrameMaster (2049/32, 2092/32)
+
+ 24-bit framebuffer for Amiga 2000/3000/4000
+
+ Hardware:
+ - ADV7120 RAMDAC
+ - 30 MHz XTAL
+ - 1.5 MB RAM with space for 0.5 more as alpha channel
+ - Fixed resolution 768x576 (PAL) and 768x480 (NTSC)
+ - 15.75 kHz or 31.5 kHz
+ - 24-bit color
+
+ TODO:
+ - ROM sockets are unsupported
+ - Rest of the jumpers
+ - Verify autoconfig IDs and include additional models
+ - Interlace (pending MAME support)
+
+***************************************************************************/
+
+#include "emu.h"
+#include "rainbow2.h"
+
+#define VERBOSE (LOG_GENERAL)
+
+#include "logmacro.h"
+
+
+//**************************************************************************
+// TYPE DEFINITIONS
+//**************************************************************************
+
+DEFINE_DEVICE_TYPE(AMIGA_RAINBOW2, bus::amiga::zorro::rainbow2_device, "amiga_rainbow2", "Rainbow II Framebuffer")
+DEFINE_DEVICE_TYPE(AMIGA_FRAMEMASTER, bus::amiga::zorro::framemaster_device, "amiga_framemaster", "FrameMaster Framebuffer")
+
+namespace bus::amiga::zorro {
+
+rainbow2_device::rainbow2_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock, device_type type, uint16_t manufacturer) :
+ device_t(mconfig, type, tag, owner, clock),
+ device_zorro2_card_interface(mconfig, *this),
+ m_screen(*this, "screen"),
+ m_jumper(*this, "jumper")
+{
+ m_manufacturer = manufacturer;
+}
+
+rainbow2_device::rainbow2_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) :
+ rainbow2_device(mconfig, tag, owner, clock, AMIGA_RAINBOW2, 2145)
+{
+}
+
+framemaster_device::framemaster_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) :
+ rainbow2_device(mconfig, tag, owner, clock, AMIGA_FRAMEMASTER, 2092)
+{
+}
+
+
+//**************************************************************************
+// INPUT DEFINITIONS
+//**************************************************************************
+
+static INPUT_PORTS_START( rainbow2 )
+ PORT_START("jumper")
+ PORT_CONFNAME(0x01, 0x01, "JP5")
+ PORT_CONFSETTING(0x00, "Test Signal")
+ PORT_CONFSETTING(0x01, DEF_STR(Normal))
+INPUT_PORTS_END
+
+ioport_constructor rainbow2_device::device_input_ports() const
+{
+ return INPUT_PORTS_NAME( rainbow2 );
+}
+
+
+//**************************************************************************
+// MACHINE DEFINITIONS
+//**************************************************************************
+
+void rainbow2_device::device_add_mconfig(machine_config &config)
+{
+ // default to PAL
+ SCREEN(config, m_screen, SCREEN_TYPE_RASTER);
+ m_screen->set_raw(30_MHz_XTAL, 960, 0, 768, 625, 0, 576); // exact values not known
+ m_screen->set_screen_update(FUNC(rainbow2_device::screen_update));
+}
+
+
+//**************************************************************************
+// MACHINE EMULATION
+//**************************************************************************
+
+void rainbow2_device::device_start()
+{
+ // setup ram
+ m_vram = make_unique_clear<uint16_t[]>(0x200000/2);
+
+ // register for save states
+ save_pointer(NAME(m_vram), 0x200000/2);
+ save_item(NAME(m_control));
+
+}
+
+void rainbow2_device::busrst_w(int state)
+{
+ if (state == 0)
+ m_control = 0;
+}
+
+void rainbow2_device::control_w(offs_t offset, uint8_t data)
+{
+ // 3--- enable ROM
+ // -2-- normal (PAL) or complement mode (NTSC)
+ // --1- video out enable
+ // ---0 interlace (0) or non-interlace (1)
+
+ LOG("control_w: %02x\n", data);
+
+ if (BIT(data, 2))
+ {
+ // NTSC
+ rectangle v(0, 768 - 1, 0, 480 - 1);
+ m_screen->configure(960, 525, v, attotime::from_ticks(960 * 525, 30_MHz_XTAL).as_attoseconds());
+ }
+ else
+ {
+ // PAL
+ rectangle v(0, 768 - 1, 0, 576 - 1);
+ m_screen->configure(960, 625, v, attotime::from_ticks(960 * 625, 30_MHz_XTAL).as_attoseconds());
+ }
+
+ m_control = data & 0x0f;
+}
+
+uint32_t rainbow2_device::screen_update(screen_device &screen, bitmap_rgb32 &bitmap, const rectangle &cliprect)
+{
+ if (BIT(m_jumper->read(), 0) == 0)
+ {
+ // test signal enabled
+ bitmap.fill(rgb_t::white(), cliprect);
+ }
+ else if (BIT(m_control, 1) == 0)
+ {
+ // video disabled
+ bitmap.fill(rgb_t::black(), cliprect);
+ }
+ else
+ {
+ for (unsigned y = cliprect.min_y; y <= cliprect.max_y; y++)
+ {
+ unsigned const i = y * 768 * 2; // line data start in memory
+ auto *const dst = &bitmap.pix(y);
+
+ for (unsigned x = cliprect.min_x; x <= cliprect.max_x; x++)
+ {
+ uint16_t const v1 = m_vram[(i + (x << 1)) | 0]; // green, blue
+ uint16_t const v2 = m_vram[(i + (x << 1)) | 1]; // alpha, red
+
+ dst[x] = (uint32_t(v2) << 16) | v1;
+ }
+ }
+ }
+
+ return 0;
+}
+
+
+//**************************************************************************
+// AUTOCONFIG
+//**************************************************************************
+
+void rainbow2_device::autoconfig_base_address(offs_t address)
+{
+ LOG("autoconfig_base_address received: 0x%06x\n", address);
+ LOG("-> installing rainbow2\n");
+
+ // stop responding to default autoconfig
+ m_zorro->space().unmap_readwrite(0xe80000, 0xe8007f);
+
+ // video memory
+ m_zorro->space().install_ram(address, address + 0x1fffff, m_vram.get());
+
+ // control register
+ m_zorro->space().install_write_handler(address + 0x1ffff8, address + 0x1ffff8,
+ emu::rw_delegate(*this, FUNC(rainbow2_device::control_w)));
+
+ // we're done
+ m_zorro->cfgout_w(0);
+}
+
+void rainbow2_device::cfgin_w(int state)
+{
+ LOG("cfgin_w (%d)\n", state);
+
+ if (state == 0)
+ {
+ // setup autoconfig
+ autoconfig_board_type(BOARD_TYPE_ZORRO2);
+ autoconfig_board_size(BOARD_SIZE_2M);
+ autoconfig_link_into_memory(false);
+ autoconfig_rom_vector_valid(false);
+ autoconfig_multi_device(false);
+ autoconfig_8meg_preferred(false);
+ autoconfig_can_shutup(true); // ?
+ autoconfig_product(32);
+ autoconfig_manufacturer(m_manufacturer);
+ autoconfig_serial(0x00000000);
+ autoconfig_rom_vector(0x0000);
+
+ // install autoconfig handler
+ m_zorro->space().install_readwrite_handler(0xe80000, 0xe8007f,
+ read16_delegate(*this, FUNC(amiga_autoconfig::autoconfig_read)),
+ write16_delegate(*this, FUNC(amiga_autoconfig::autoconfig_write)), 0xffff);
+ }
+}
+
+} // namespace bus::amiga::zorro
diff --git a/src/devices/bus/amiga/zorro/rainbow2.h b/src/devices/bus/amiga/zorro/rainbow2.h
new file mode 100644
index 00000000000..0905785b99b
--- /dev/null
+++ b/src/devices/bus/amiga/zorro/rainbow2.h
@@ -0,0 +1,68 @@
+// license: GPL-2.0+
+// copyright-holders: Dirk Best
+/***************************************************************************
+
+ Omega Datentechnik Rainbow II
+ Ingenieurbuero Helfrich Rainbow II
+ BSC FrameMaster
+
+ 24-bit framebuffer for Amiga 2000/3000/4000
+
+***************************************************************************/
+
+#ifndef MAME_BUS_AMIGA_ZORRO_RAINBOW2_H
+#define MAME_BUS_AMIGA_ZORRO_RAINBOW2_H
+
+#pragma once
+
+#include "zorro.h"
+#include "machine/autoconfig.h"
+#include "screen.h"
+
+
+namespace bus::amiga::zorro {
+
+class rainbow2_device : public device_t, public device_zorro2_card_interface, public amiga_autoconfig
+{
+public:
+ rainbow2_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
+
+protected:
+ rainbow2_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock, device_type type, uint16_t manufacturer);
+
+ virtual ioport_constructor device_input_ports() const override ATTR_COLD;
+ virtual void device_add_mconfig(machine_config &config) override ATTR_COLD;
+
+ virtual void device_start() override ATTR_COLD;
+
+ // device_zorro2_card_interface overrides
+ virtual void cfgin_w(int state) override;
+ virtual void busrst_w(int state) override;
+
+ // amiga_autoconfig overrides
+ virtual void autoconfig_base_address(offs_t address) override;
+
+private:
+ void control_w(offs_t offset, uint8_t data);
+ uint32_t screen_update(screen_device &screen, bitmap_rgb32 &bitmap, const rectangle &cliprect);
+
+ required_device<screen_device> m_screen;
+ std::unique_ptr<uint16_t[]> m_vram;
+ required_ioport m_jumper;
+ uint16_t m_manufacturer;
+ uint8_t m_control;
+};
+
+class framemaster_device : public rainbow2_device
+{
+public:
+ framemaster_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
+};
+
+} // namespace bus::amiga::zorro
+
+// device type declaration
+DECLARE_DEVICE_TYPE_NS(AMIGA_RAINBOW2, bus::amiga::zorro, rainbow2_device)
+DECLARE_DEVICE_TYPE_NS(AMIGA_FRAMEMASTER, bus::amiga::zorro, framemaster_device)
+
+#endif // MAME_BUS_AMIGA_ZORRO_RAINBOW2_H
diff --git a/src/devices/bus/amiga/zorro/ripple.cpp b/src/devices/bus/amiga/zorro/ripple.cpp
new file mode 100644
index 00000000000..f2d50da629b
--- /dev/null
+++ b/src/devices/bus/amiga/zorro/ripple.cpp
@@ -0,0 +1,234 @@
+// license: GPL-2.0+
+// copyright-holders: Dirk Best
+/***************************************************************************
+
+ RIPPLE IDE
+
+ Zorro-II IDE interface for Amiga 2000/3000/4000
+
+ Notes:
+ - See https://github.com/LIV2/RIPPLE-IDE
+ - To enable boot from CD-ROM you need CDFileSystem from OS 3.2.1 or
+ later, then you can issue the command "LoadModule L:CDFileSystem"
+ - If you have the correct version of CDFileSystem you can also flash
+ it to the controller with "lideflash -C L:CDFileSystem"
+
+ TODO:
+ - Verify cs1 access
+
+***************************************************************************/
+
+#include "emu.h"
+#include "ripple.h"
+
+#define VERBOSE 1
+#include "logmacro.h"
+
+
+//**************************************************************************
+// TYPE DEFINITIONS
+//**************************************************************************
+
+DEFINE_DEVICE_TYPE(AMIGA_RIPPLE, bus::amiga::zorro::ripple_ide_device, "amiga_ripple", "RIPPLE IDE Interface")
+
+namespace bus::amiga::zorro {
+
+ripple_ide_device::ripple_ide_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) :
+ device_t(mconfig, AMIGA_RIPPLE, tag, owner, clock),
+ device_zorro2_card_interface(mconfig, *this),
+ m_ata_0(*this, "ata_0"),
+ m_ata_1(*this, "ata_1"),
+ m_flash(*this, "flash")
+{
+}
+
+
+//**************************************************************************
+// ADDRESS MAPS
+//**************************************************************************
+
+void ripple_ide_device::mmio_map(address_map &map)
+{
+ map(0x01000, 0x01fff).rw(FUNC(ripple_ide_device::ide0_cs0_r), FUNC(ripple_ide_device::ide0_cs0_w));
+ map(0x02000, 0x02fff).rw(FUNC(ripple_ide_device::ide1_cs0_r), FUNC(ripple_ide_device::ide1_cs0_w));
+ map(0x05000, 0x05fff).rw(FUNC(ripple_ide_device::ide0_cs1_r), FUNC(ripple_ide_device::ide0_cs1_w));
+ map(0x06000, 0x06fff).rw(FUNC(ripple_ide_device::ide1_cs1_r), FUNC(ripple_ide_device::ide1_cs1_w));
+ map(0x08000, 0x08fff).w(FUNC(ripple_ide_device::bank_select_w));
+ map(0x10000, 0x1ffff).rw(FUNC(ripple_ide_device::banked_flash_r), FUNC(ripple_ide_device::banked_flash_w)).umask16(0xff00);
+}
+
+
+//**************************************************************************
+// MACHINE DEFINITIONS
+//**************************************************************************
+
+void ripple_ide_device::device_add_mconfig(machine_config &config)
+{
+ ATA_INTERFACE(config, m_ata_0).options(ata_devices, nullptr, nullptr, false);
+ ATA_INTERFACE(config, m_ata_1).options(ata_devices, nullptr, nullptr, false);
+
+ SST_39SF010(config, "flash");
+}
+
+
+//**************************************************************************
+// ROM DEFINITIONS
+//**************************************************************************
+
+ROM_START( lide )
+ ROM_REGION(0x20000, "flash", ROMREGION_ERASEFF)
+ ROM_DEFAULT_BIOS("40.8")
+ ROM_SYSTEM_BIOS(0, "40.8", "Release 40.8")
+ ROMX_LOAD("lide_40-8.rom", 0x0000, 0x8000, CRC(3f021472) SHA1(83762ef5a883e5c43ad321eaa03fde7454f70785), ROM_BIOS(0))
+ROM_END
+
+const tiny_rom_entry *ripple_ide_device::device_rom_region() const
+{
+ return ROM_NAME( lide );
+}
+
+
+//**************************************************************************
+// MACHINE EMULATION
+//**************************************************************************
+
+void ripple_ide_device::device_start()
+{
+ // register for save states
+ save_item(NAME(m_base_address));
+ save_item(NAME(m_flash_bank));
+}
+
+void ripple_ide_device::busrst_w(int state)
+{
+ if (state == 0)
+ m_flash_bank = 0;
+}
+
+void ripple_ide_device::bank_select_w(offs_t offset, uint16_t data, uint16_t mem_mask)
+{
+ if (ACCESSING_BITS_8_15)
+ m_flash_bank = data >> 14;
+}
+
+uint8_t ripple_ide_device::banked_flash_r(offs_t offset)
+{
+ return m_flash->read(m_flash_bank << 15 | offset);
+}
+
+void ripple_ide_device::banked_flash_w(offs_t offset, uint8_t data)
+{
+ m_flash->write(m_flash_bank << 15 | offset, data);
+}
+
+uint16_t ripple_ide_device::ide0_cs0_r(offs_t offset, uint16_t mem_mask)
+{
+ return m_ata_0->cs0_swap_r(offset >> 8, mem_mask);
+}
+
+void ripple_ide_device::ide0_cs0_w(offs_t offset, uint16_t data, uint16_t mem_mask)
+{
+ m_ata_0->cs0_swap_w(offset >> 8, data, mem_mask);
+}
+
+uint16_t ripple_ide_device::ide0_cs1_r(offs_t offset, uint16_t mem_mask)
+{
+ return m_ata_0->cs1_swap_r(offset >> 8, mem_mask);
+}
+
+void ripple_ide_device::ide0_cs1_w(offs_t offset, uint16_t data, uint16_t mem_mask)
+{
+ m_ata_0->cs1_swap_w(offset >> 8, data, mem_mask);
+}
+
+uint16_t ripple_ide_device::ide1_cs0_r(offs_t offset, uint16_t mem_mask)
+{
+ return m_ata_1->cs0_swap_r(offset >> 8, mem_mask);
+}
+
+void ripple_ide_device::ide1_cs0_w(offs_t offset, uint16_t data, uint16_t mem_mask)
+{
+ m_ata_1->cs0_swap_w(offset >> 8, data, mem_mask);
+}
+
+uint16_t ripple_ide_device::ide1_cs1_r(offs_t offset, uint16_t mem_mask)
+{
+ return m_ata_1->cs1_swap_r(offset >> 8, mem_mask);
+}
+
+void ripple_ide_device::ide1_cs1_w(offs_t offset, uint16_t data, uint16_t mem_mask)
+{
+ m_ata_1->cs1_swap_w(offset >> 8, data, mem_mask);
+}
+
+
+//**************************************************************************
+// AUTOCONFIG
+//**************************************************************************
+
+void ripple_ide_device::autoconfig_base_address(offs_t address)
+{
+ LOG("autoconfig_base_address received: 0x%06x\n", address);
+ LOG("-> installing ripple ide\n");
+
+ // save base address so that the tap can reconfigure our space
+ m_base_address = address;
+
+ // stop responding to default autoconfig
+ m_zorro->space().unmap_readwrite(0xe80000, 0xe8007f);
+
+ // flash occupies our space until the ide registers are switched in
+ m_zorro->space().install_readwrite_handler(address, address + 0x1ffff,
+ emu::rw_delegate(m_flash, FUNC(intelfsh8_device::read)),
+ emu::rw_delegate(m_flash, FUNC(intelfsh8_device::write)), 0xff00);
+
+ // install write tap to handle switching in ide registers
+ m_write_tap.remove();
+ m_write_tap = m_zorro->space().install_write_tap(
+ address, address + 0x1ffff,
+ "flash_disable_w",
+ [this] (offs_t offset, uint16_t &data, uint16_t mem_mask)
+ {
+ m_write_tap.remove();
+
+ // ripple registers are now available
+ m_zorro->space().install_device(m_base_address, m_base_address + 0x1ffff, *this, &ripple_ide_device::mmio_map);
+
+ // we need to repeat the write here as this tap won't hit it yet
+ // the initial write will instead hit the flash, but it's harmless
+ m_zorro->space().write_word(offset, data, mem_mask);
+ },
+ &m_write_tap
+ );
+
+ // we're done
+ m_zorro->cfgout_w(0);
+}
+
+void ripple_ide_device::cfgin_w(int state)
+{
+ LOG("cfgin_w (%d)\n", state);
+
+ if (state == 0)
+ {
+ // setup autoconfig
+ autoconfig_board_type(BOARD_TYPE_ZORRO2);
+ autoconfig_board_size(BOARD_SIZE_128K);
+ autoconfig_link_into_memory(false);
+ autoconfig_rom_vector_valid(true);
+ autoconfig_multi_device(false);
+ autoconfig_8meg_preferred(false);
+ autoconfig_can_shutup(true);
+ autoconfig_product(7);
+ autoconfig_manufacturer(5194);
+ autoconfig_serial(0x00000000);
+ autoconfig_rom_vector(0x0008);
+
+ // install autoconfig handler
+ m_zorro->space().install_readwrite_handler(0xe80000, 0xe8007f,
+ read16_delegate(*this, FUNC(amiga_autoconfig::autoconfig_read)),
+ write16_delegate(*this, FUNC(amiga_autoconfig::autoconfig_write)), 0xffff);
+ }
+}
+
+} // namespace bus::amiga::zorro
diff --git a/src/devices/bus/amiga/zorro/ripple.h b/src/devices/bus/amiga/zorro/ripple.h
new file mode 100644
index 00000000000..e8dae6fc36e
--- /dev/null
+++ b/src/devices/bus/amiga/zorro/ripple.h
@@ -0,0 +1,74 @@
+// license: GPL-2.0+
+// copyright-holders: Dirk Best
+/***************************************************************************
+
+ RIPPLE IDE
+
+ Zorro-II IDE interface for Amiga 2000/3000/4000
+
+***************************************************************************/
+
+#ifndef MAME_BUS_AMIGA_ZORRO_RIPPLE_H
+#define MAME_BUS_AMIGA_ZORRO_RIPPLE_H
+
+#pragma once
+
+#include "zorro.h"
+#include "machine/autoconfig.h"
+#include "machine/intelfsh.h"
+#include "bus/ata/ataintf.h"
+
+
+namespace bus::amiga::zorro {
+
+class ripple_ide_device : public device_t, public device_zorro2_card_interface, public amiga_autoconfig
+{
+public:
+ ripple_ide_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
+
+protected:
+ virtual void device_add_mconfig(machine_config &config) override ATTR_COLD;
+ virtual const tiny_rom_entry *device_rom_region() const override ATTR_COLD;
+
+ virtual void device_start() override ATTR_COLD;
+
+ // device_zorro2_card_interface overrides
+ virtual void cfgin_w(int state) override;
+ virtual void busrst_w(int state) override;
+
+ // amiga_autoconfig overrides
+ virtual void autoconfig_base_address(offs_t address) override;
+
+private:
+ void mmio_map(address_map &map) ATTR_COLD;
+
+ // flash
+ void bank_select_w(offs_t offset, uint16_t data, uint16_t mem_mask = ~0);
+ uint8_t banked_flash_r(offs_t offset);
+ void banked_flash_w(offs_t offset, uint8_t data);
+
+ // ide register
+ uint16_t ide0_cs0_r(offs_t offset, uint16_t mem_mask = ~0);
+ void ide0_cs0_w(offs_t offset, uint16_t data, uint16_t mem_mask = ~0);
+ uint16_t ide0_cs1_r(offs_t offset, uint16_t mem_mask = ~0);
+ void ide0_cs1_w(offs_t offset, uint16_t data, uint16_t mem_mask = ~0);
+ uint16_t ide1_cs0_r(offs_t offset, uint16_t mem_mask = ~0);
+ void ide1_cs0_w(offs_t offset, uint16_t data, uint16_t mem_mask = ~0);
+ uint16_t ide1_cs1_r(offs_t offset, uint16_t mem_mask = ~0);
+ void ide1_cs1_w(offs_t offset, uint16_t data, uint16_t mem_mask = ~0);
+
+ required_device<ata_interface_device> m_ata_0;
+ required_device<ata_interface_device> m_ata_1;
+ required_device<sst_39sf010_device> m_flash;
+ memory_passthrough_handler m_write_tap;
+
+ offs_t m_base_address = 0;
+ uint8_t m_flash_bank = 0;
+};
+
+} // namespace bus::amiga::zorro
+
+// device type declaration
+DECLARE_DEVICE_TYPE_NS(AMIGA_RIPPLE, bus::amiga::zorro, ripple_ide_device)
+
+#endif // MAME_BUS_AMIGA_ZORRO_RIPPLE_H
diff --git a/src/devices/bus/amiga/zorro/toccata.cpp b/src/devices/bus/amiga/zorro/toccata.cpp
new file mode 100644
index 00000000000..6aebd2defbc
--- /dev/null
+++ b/src/devices/bus/amiga/zorro/toccata.cpp
@@ -0,0 +1,318 @@
+// license: GPL-2.0+
+// copyright-holders: Dirk Best
+/***************************************************************************
+
+ MacroSystem Toccata
+
+ 16bit/48KHz Audio Digitizer
+
+ Hardware:
+ - AD1848KP SoundPort
+ - 2x 7202LA 1024x9 FIFO
+ - XTAL 24.576 MHz (also seen with 24.582) and 16.9344 MHz
+ - MC33078
+ - GALs for autoconfig and other logic
+ - 3 stereo inputs, 1 stereo output
+
+ Notes:
+ - Needs more testing
+
+ TODO:
+ - Verify data lanes
+ - Audio input
+
+***************************************************************************/
+
+#include "emu.h"
+#include "toccata.h"
+
+#define LOG_IRQ (1U << 1)
+#define LOG_FIFO (1U << 2)
+#define LOG_REG (1U << 3)
+#define LOG_AD1848 (1U << 4)
+
+#define VERBOSE (LOG_GENERAL)
+
+#include "logmacro.h"
+
+
+//**************************************************************************
+// TYPE DEFINITIONS
+//**************************************************************************
+
+DEFINE_DEVICE_TYPE(AMIGA_TOCCATA, bus::amiga::zorro::toccata_device, "amiga_toccata", "Toccata SoundCard")
+
+namespace bus::amiga::zorro {
+
+toccata_device::toccata_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) :
+ device_t(mconfig, AMIGA_TOCCATA, tag, owner, clock),
+ device_zorro2_card_interface(mconfig, *this),
+ m_ad1848(*this, "ad1848"),
+ m_fifo(*this, "fifo%u", 0U)
+{
+}
+
+
+//**************************************************************************
+// ADDRESS MAPS
+//**************************************************************************
+
+void toccata_device::mmio_map(address_map &map)
+{
+ map(0x0000, 0x0001).mirror(0x97fe).rw(FUNC(toccata_device::status_r), FUNC(toccata_device::control_w)).umask16(0xff00);
+ map(0x2000, 0x2001).mirror(0x97fe).rw(FUNC(toccata_device::fifo_r), FUNC(toccata_device::fifo_w));
+ map(0x6000, 0x6001).mirror(0x97fe).rw(FUNC(toccata_device::ad1848_idx_r), FUNC(toccata_device::ad1848_idx_w)).umask16(0x00ff);
+ map(0x6800, 0x6801).mirror(0x97fe).rw(FUNC(toccata_device::ad1848_data_r), FUNC(toccata_device::ad1848_data_w)).umask16(0x00ff);
+}
+
+
+//**************************************************************************
+// MACHINE DEFINITIONS
+//**************************************************************************
+
+void toccata_device::device_add_mconfig(machine_config &config)
+{
+ AD1848(config, m_ad1848, 0);
+ m_ad1848->drq().set(FUNC(toccata_device::drq_w));
+
+ IDT7202(config, m_fifo[0]);
+ m_fifo[0]->hf_handler().set(FUNC(toccata_device::playback_hf_w));
+
+ IDT7202(config, m_fifo[1]);
+ m_fifo[1]->hf_handler().set(FUNC(toccata_device::record_hf_w));
+}
+
+
+//**************************************************************************
+// MACHINE EMULATION
+//**************************************************************************
+
+void toccata_device::device_start()
+{
+ // register for save states
+ save_item(NAME(m_status));
+ save_item(NAME(m_control));
+}
+
+void toccata_device::update_interrupts()
+{
+ if ((BIT(m_control, 7) && BIT(m_status, 3)) || (BIT(m_control, 6) && BIT(m_status, 2)))
+ {
+ LOGMASKED(LOG_IRQ, "generating interrupt, control = %02x, status = %02x\n", m_control, m_status);
+
+ m_status &= ~(1 << 7);
+ m_zorro->int6_w(1);
+ }
+}
+
+void toccata_device::playback_hf_w(int state)
+{
+ LOGMASKED(LOG_IRQ, "playback_hf_w: %d, status %02x\n", state, m_status);
+
+ if (BIT(m_control, 7) && BIT(m_control, 4))
+ {
+ m_status &= ~(1 << 3);
+ m_status |= state << 3;
+
+ LOGMASKED(LOG_IRQ, "playback interrupts enabled, status now %02x\n", m_status);
+
+ update_interrupts();
+ }
+}
+
+void toccata_device::record_hf_w(int state)
+{
+ LOGMASKED(LOG_IRQ, "record_hf_w: %d, status %02x\n", state, m_status);
+
+ if (BIT(m_control, 7) && BIT(m_control, 3))
+ {
+ m_status &= ~(1 << 2);
+ m_status |= state << 2;
+
+ LOGMASKED(LOG_IRQ, "record interrupts enabled, status now %02x\n", m_status);
+
+ update_interrupts();
+ }
+}
+
+void toccata_device::drq_w(int state)
+{
+ if (BIT(m_control, 2) && BIT(m_control, 4) && state)
+ {
+ uint8_t tmp = 0;
+
+ // 16-bit stereo, bytes swapped
+ tmp = m_fifo[0]->data_byte_r();
+ m_ad1848->dack_w(m_fifo[0]->data_byte_r());
+ m_ad1848->dack_w(tmp);
+
+ tmp = m_fifo[0]->data_byte_r();
+ m_ad1848->dack_w(m_fifo[0]->data_byte_r());
+ m_ad1848->dack_w(tmp);
+ }
+}
+
+uint8_t toccata_device::status_r(offs_t offset)
+{
+ // 7------- interrupt pending (active low)
+ // -6------ unknown
+ // --5----- unknown
+ // ---4---- unknown
+ // ----3--- playback fifo half empty
+ // -----2-- record fifo half full
+ // ------1- unknown
+ // -------0 unknown
+
+ uint8_t data = m_status;
+
+ if (!machine().side_effects_disabled())
+ {
+ LOGMASKED(LOG_REG, "status_r: %02x\n", m_status);
+
+ // reading the status clears the interrupt
+ m_status = 0x80;
+ m_zorro->int6_w(0);
+ }
+
+ return data;
+}
+
+void toccata_device::control_w(offs_t offset, uint8_t data)
+{
+ // 7------- playback interrupt enable
+ // -6------ record interrupt enable
+ // --5----- unknown
+ // ---4---- fifo playback
+ // ----3--- fifo record
+ // -----2-- enable fifo
+ // ------1- card reset
+ // -------0 card active
+
+ LOGMASKED(LOG_REG, "control_w: %02x\n", data);
+
+ if (BIT(data, 1))
+ {
+ // reset card
+ LOG("card reset\n");
+
+ m_status = 0x80;
+ m_control = 0x00;
+
+ m_fifo[0]->reset();
+ m_fifo[1]->reset();
+ m_ad1848->reset();
+ }
+ else
+ {
+ // not sure
+ if (data == 0x01)
+ {
+ LOG("fifo reset\n");
+
+ m_status = 0x80;
+
+ m_fifo[0]->reset();
+ m_fifo[1]->reset();
+ }
+
+ m_control = data;
+
+ update_interrupts();
+ }
+}
+
+uint16_t toccata_device::fifo_r(offs_t offset, uint16_t mem_mask)
+{
+ uint16_t data = 0;
+
+ if (ACCESSING_BITS_0_7)
+ data |= m_fifo[1]->data_byte_r() << 0;
+
+ if (ACCESSING_BITS_8_15)
+ data |= m_fifo[1]->data_byte_r() << 8;
+
+ LOGMASKED(LOG_FIFO, "fifo_r: %04x & %04x\n", data, mem_mask);
+
+ return data;
+}
+
+void toccata_device::fifo_w(offs_t offset, uint16_t data, uint16_t mem_mask)
+{
+ LOGMASKED(LOG_FIFO, "fifo_w: %04x & %04x\n", data, mem_mask);
+
+ if (ACCESSING_BITS_0_7)
+ m_fifo[0]->data_byte_w(data >> 0);
+
+ if (ACCESSING_BITS_8_15)
+ m_fifo[0]->data_byte_w(data >> 8);
+}
+
+uint8_t toccata_device::ad1848_idx_r(offs_t offset)
+{
+ return m_ad1848->read(0);
+}
+
+void toccata_device::ad1848_idx_w(offs_t offset, uint8_t data)
+{
+ LOGMASKED(LOG_AD1848, "ad1848_idx_w: %02x\n", data);
+ m_ad1848->write(0, data);
+}
+
+uint8_t toccata_device::ad1848_data_r(offs_t offset)
+{
+ return m_ad1848->read(1);
+}
+
+void toccata_device::ad1848_data_w(offs_t offset, uint8_t data)
+{
+ LOGMASKED(LOG_AD1848, "ad1848_data_w: %02x\n", data);
+ m_ad1848->write(1, data);
+}
+
+
+//**************************************************************************
+// AUTOCONFIG
+//**************************************************************************
+
+void toccata_device::autoconfig_base_address(offs_t address)
+{
+ LOG("autoconfig_base_address received: 0x%06x\n", address);
+ LOG("-> installing toccata\n");
+
+ // stop responding to default autoconfig
+ m_zorro->space().unmap_readwrite(0xe80000, 0xe8007f);
+
+ // toccata registers
+ m_zorro->space().install_device(address, address + 0x0ffff, *this, &toccata_device::mmio_map);
+
+ // we're done
+ m_zorro->cfgout_w(0);
+}
+
+void toccata_device::cfgin_w(int state)
+{
+ LOG("cfgin_w (%d)\n", state);
+
+ if (state == 0)
+ {
+ // setup autoconfig
+ autoconfig_board_type(BOARD_TYPE_ZORRO2);
+ autoconfig_board_size(BOARD_SIZE_64K);
+ autoconfig_link_into_memory(false);
+ autoconfig_rom_vector_valid(false);
+ autoconfig_multi_device(false);
+ autoconfig_8meg_preferred(false);
+ autoconfig_can_shutup(true);
+ autoconfig_product(12);
+ autoconfig_manufacturer(18260);
+ autoconfig_serial(0x00000000);
+ autoconfig_rom_vector(0x0000);
+
+ // install autoconfig handler
+ m_zorro->space().install_readwrite_handler(0xe80000, 0xe8007f,
+ read16_delegate(*this, FUNC(amiga_autoconfig::autoconfig_read)),
+ write16_delegate(*this, FUNC(amiga_autoconfig::autoconfig_write)), 0xffff);
+ }
+}
+
+} // namespace bus::amiga::zorro
diff --git a/src/devices/bus/amiga/zorro/toccata.h b/src/devices/bus/amiga/zorro/toccata.h
new file mode 100644
index 00000000000..f065c2f8179
--- /dev/null
+++ b/src/devices/bus/amiga/zorro/toccata.h
@@ -0,0 +1,72 @@
+// license: GPL-2.0+
+// copyright-holders: Dirk Best
+/***************************************************************************
+
+ MacroSystem Toccata
+
+ 16bit/48KHz Audio Digitizer
+
+***************************************************************************/
+
+#ifndef MAME_BUS_AMIGA_ZORRO_TOCCATA_H
+#define MAME_BUS_AMIGA_ZORRO_TOCCATA_H
+
+#pragma once
+
+#include "zorro.h"
+#include "machine/7200fifo.h"
+#include "machine/autoconfig.h"
+#include "sound/ad1848.h"
+
+
+namespace bus::amiga::zorro {
+
+class toccata_device : public device_t, public device_zorro2_card_interface, public amiga_autoconfig
+{
+public:
+ toccata_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
+
+protected:
+ virtual void device_add_mconfig(machine_config &config) override ATTR_COLD;
+
+ virtual void device_start() override ATTR_COLD;
+
+ // device_zorro2_card_interface overrides
+ virtual void cfgin_w(int state) override;
+
+ // amiga_autoconfig overrides
+ virtual void autoconfig_base_address(offs_t address) override;
+
+private:
+ void mmio_map(address_map &map) ATTR_COLD;
+
+ void update_interrupts();
+
+ void playback_hf_w(int state);
+ void record_hf_w(int state);
+ void drq_w(int state);
+
+ uint8_t status_r(offs_t offset);
+ void control_w(offs_t offset, uint8_t data);
+
+ uint16_t fifo_r(offs_t offset, uint16_t mem_mask = ~0);
+ void fifo_w(offs_t offset, uint16_t data, uint16_t mem_mask = ~0);
+
+ uint8_t ad1848_idx_r(offs_t offset);
+ void ad1848_idx_w(offs_t offset, uint8_t data);
+ uint8_t ad1848_data_r(offs_t offset);
+ void ad1848_data_w(offs_t offset, uint8_t data);
+
+ required_device<ad1848_device> m_ad1848;
+ required_device_array<idt7202_device, 2> m_fifo;
+
+ uint8_t m_status = 0;
+ uint8_t m_control = 0;
+};
+
+} // namespace bus::amiga::zorro
+
+// device type declaration
+DECLARE_DEVICE_TYPE_NS(AMIGA_TOCCATA, bus::amiga::zorro, toccata_device)
+
+#endif // MAME_BUS_AMIGA_ZORRO_TOCCATA_H
diff --git a/src/devices/bus/amiga/zorro/zorro.cpp b/src/devices/bus/amiga/zorro/zorro.cpp
index b4f06507d55..14e13c76617 100644
--- a/src/devices/bus/amiga/zorro/zorro.cpp
+++ b/src/devices/bus/amiga/zorro/zorro.cpp
@@ -1,10 +1,8 @@
-// license:GPL-2.0+
-// copyright-holders:Dirk Best
+// license: GPL-2.0+
+// copyright-holders: Dirk Best
/***************************************************************************
- Amiga Zorro Slots
-
- 86-pin Expansion Slot (Zorro-I), Zorro-II, Zorro-III
+ Amiga Zorro-II Slot
***************************************************************************/
@@ -13,345 +11,166 @@
//**************************************************************************
-// ZORRO SLOT DEVICE
-//**************************************************************************
-
-DEFINE_DEVICE_TYPE(ZORRO_SLOT, zorro_slot_device, "zorro_slot", "Zorro slot")
-
-//-------------------------------------------------
-// zorro_slot_device - constructor
-//-------------------------------------------------
-
-zorro_slot_device::zorro_slot_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) :
- zorro_slot_device(mconfig, ZORRO_SLOT, tag, owner, clock)
-{
-}
-
-zorro_slot_device::zorro_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_zorro_bus(*this, finder_base::DUMMY_TAG)
-{
-}
-
-//-------------------------------------------------
-// device_start - device-specific startup
-//-------------------------------------------------
-
-void zorro_slot_device::device_start()
-{
- device_zorro_card_interface *dev = dynamic_cast<device_zorro_card_interface *>(get_card_device());
-
- if (dev)
- m_zorro_bus->add_card(dev);
-}
-
-
-//**************************************************************************
-// BASE ZORRO BUS DEVICE
+// BUS DEVICE
//**************************************************************************
-//-------------------------------------------------
-// exp_slot_device - constructor
-//-------------------------------------------------
+DEFINE_DEVICE_TYPE(ZORRO2_BUS, zorro2_bus_device, "zorro2", "Zorro-II Bus")
-zorro_device::zorro_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_ovr_handler(*this),
+zorro2_bus_device::zorro2_bus_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) :
+ device_t(mconfig, ZORRO2_BUS, tag, owner, clock),
+ device_memory_interface(mconfig, *this),
+ m_zorro_space_config("zorro", ENDIANNESS_BIG, 16, 24, 0, address_map_constructor()),
+ m_eint1_handler(*this),
+ m_eint4_handler(*this),
+ m_eint5_handler(*this),
+ m_eint7_handler(*this),
m_int2_handler(*this),
- m_int6_handler(*this)
-{
-}
-
-//-------------------------------------------------
-// device_resolve_objects - resolve objects that
-// may be needed for other devices to set
-// initial conditions at start time
-//-------------------------------------------------
-
-void zorro_device::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
-//-------------------------------------------------
-
-void zorro_device::device_start()
-{
-}
-
-// from slot device
-WRITE_LINE_MEMBER( zorro_device::ovr_w ) { m_ovr_handler(state); }
-WRITE_LINE_MEMBER( zorro_device::int2_w ) { m_int2_handler(state); }
-WRITE_LINE_MEMBER( zorro_device::int6_w ) { m_int6_handler(state); }
-
-
-//**************************************************************************
-// EXPANSION SLOT DEVICE
-//**************************************************************************
-
-DEFINE_DEVICE_TYPE(EXP_SLOT, exp_slot_device, "exp_slot", "86-pin expansion slot")
-
-//-------------------------------------------------
-// exp_slot_device - constructor
-//-------------------------------------------------
-
-exp_slot_device::exp_slot_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) :
- zorro_device(mconfig, EXP_SLOT, tag, owner, clock),
- m_ipl_handler(*this),
- m_dev(nullptr)
-{
-}
-
-exp_slot_device::exp_slot_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock) :
- zorro_device(mconfig, type, tag, owner, clock),
- m_ipl_handler(*this),
- m_dev(nullptr)
+ m_int6_handler(*this),
+ m_ovr_handler(*this),
+ m_autoconfig_device(0)
{
}
-//-------------------------------------------------
-// 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()
+void zorro2_bus_device::device_start()
{
- // resolve callbacks
- m_ipl_handler.resolve_safe();
-
- // call base device
- zorro_device::device_resolve_objects();
+ // register for save states
+ save_item(NAME(m_autoconfig_device));
}
-//-------------------------------------------------
-// device_reset - device-specific reset
-//-------------------------------------------------
-
-void exp_slot_device::device_reset()
+device_memory_interface::space_config_vector zorro2_bus_device::memory_space_config() const
{
- // if we have a device, start the autoconfig chain
- if (m_dev)
- m_dev->cfgin_w(0);
+ return space_config_vector{
+ std::make_pair(AS_PROGRAM, &m_zorro_space_config)
+ };
}
-//-------------------------------------------------
-// add_card - add new card to our bus
-//-------------------------------------------------
-
-void exp_slot_device::add_card(device_zorro_card_interface *card)
+void zorro2_bus_device::add_card(device_zorro2_card_interface &card)
{
- m_dev = downcast<device_exp_card_interface *>(card);
- card->set_zorro_bus(this);
+ card.set_bus(*this);
+ m_cards.emplace_back(card);
}
// from slot device
-void exp_slot_device::ipl_w(int interrupt) { m_ipl_handler(0, interrupt, 0xff); }
-
-// from host
-void exp_slot_device::fc_w(int code) { if (m_dev) m_dev->fc_w(code); }
-
-
-//**************************************************************************
-// ZORRO2 DEVICE
-//**************************************************************************
-
-DEFINE_DEVICE_TYPE(ZORRO2, zorro2_device, "zorro2", "Zorro-II bus")
-
-//-------------------------------------------------
-// zorro2_device - constructor
-//-------------------------------------------------
-
-zorro2_device::zorro2_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) :
- zorro2_device(mconfig, ZORRO2, tag, owner, clock)
-{
-}
-
-zorro2_device::zorro2_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock) :
- zorro_device(mconfig, type, tag, owner, clock),
- m_eint1_handler(*this),
- m_eint4_handler(*this),
- m_eint5_handler(*this),
- m_eint7_handler(*this),
- m_autoconfig_device(nullptr)
+void zorro2_bus_device::cfgout_w(int state)
{
+ // if there is still a device in the chain, tell it to configure itself
+ if (m_cards.size() > ++m_autoconfig_device)
+ m_cards[m_autoconfig_device].get().cfgin_w(0);
}
-//-------------------------------------------------
-// zorro2_device - destructor
-//-------------------------------------------------
+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); }
+void zorro2_bus_device::int2_w(int state) { m_int2_handler(state); }
+void zorro2_bus_device::int6_w(int state) { m_int6_handler(state); }
+void zorro2_bus_device::ovr_w(int state) { m_ovr_handler(state); }
-zorro2_device::~zorro2_device()
+// from host
+uint16_t zorro2_bus_device::mem_r(offs_t offset, uint16_t mem_mask)
{
- m_dev.detach_all();
+ return space().read_word(0x200000 + (offset << 1), mem_mask);
}
-//-------------------------------------------------
-// device_resolve_objects - resolve objects that
-// may be needed for other devices to set
-// initial conditions at start time
-//-------------------------------------------------
-
-void zorro2_device::device_resolve_objects()
+void zorro2_bus_device::mem_w(offs_t offset, uint16_t data, uint16_t mem_mask)
{
- // resolve callbacks
- m_eint1_handler.resolve_safe();
- m_eint4_handler.resolve_safe();
- m_eint5_handler.resolve_safe();
- m_eint7_handler.resolve_safe();
-
- // call base device
- zorro_device::device_resolve_objects();
+ space().write_word(0x200000 + (offset << 1), data, mem_mask);
}
-//-------------------------------------------------
-// device_reset - device-specific reset
-//-------------------------------------------------
-
-void zorro2_device::device_reset()
+uint16_t zorro2_bus_device::io_r(offs_t offset, uint16_t mem_mask)
{
- // initiate autoconfig
- m_autoconfig_device = m_dev.first();
-
- // if we have a device, start the autoconfig chain
- if (m_autoconfig_device)
- m_autoconfig_device->cfgin_w(0);
+ return space().read_word(0xe80000 + (offset << 1), mem_mask);
}
-//-------------------------------------------------
-// add_card - add new card to our bus
-//-------------------------------------------------
-
-void zorro2_device::add_card(device_zorro_card_interface *card)
+void zorro2_bus_device::io_w(offs_t offset, uint16_t data, uint16_t mem_mask)
{
- device_zorro2_card_interface *zorro2_card = downcast<device_zorro2_card_interface *>(card);
- card->set_zorro_bus(this);
- m_dev.append(*zorro2_card);
+ space().write_word(0xe80000 + (offset << 1), data, mem_mask);
}
-// from slot device
-WRITE_LINE_MEMBER( zorro2_device::eint1_w ) { m_eint1_handler(state); }
-WRITE_LINE_MEMBER( zorro2_device::eint4_w ) { m_eint4_handler(state); }
-WRITE_LINE_MEMBER( zorro2_device::eint5_w ) { m_eint5_handler(state); }
-WRITE_LINE_MEMBER( zorro2_device::eint7_w ) { m_eint7_handler(state); }
-
-WRITE_LINE_MEMBER( zorro2_device::cfgout_w )
+void zorro2_bus_device::fc_w(int code)
{
- 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);
+ for (device_zorro2_card_interface &entry : m_cards)
+ entry.fc_w(code);
}
-// from host
-void zorro2_device::fc_w(int code)
+void zorro2_bus_device::busrst_w(int state)
{
- device_zorro2_card_interface *entry = m_dev.first();
+ for (device_zorro2_card_interface &card : m_cards)
+ card.busrst_w(state);
- while (entry)
+ if (state == 0)
{
- entry->fc_w(code);
- entry = entry->next();
+ // initiate autoconfig
+ m_autoconfig_device = 0;
+
+ // if we have a device, start the autoconfig chain
+ if (m_cards.size() > m_autoconfig_device)
+ m_cards[m_autoconfig_device].get().cfgin_w(0);
}
}
//**************************************************************************
-// ZORRO INTERFACE
+// SLOT DEVICE
//**************************************************************************
-//-------------------------------------------------
-// device_zorro_card_interface - constructor
-//-------------------------------------------------
+DEFINE_DEVICE_TYPE(ZORRO2_SLOT, zorro2_slot_device, "zorro2_slot", "Zorro-II slot")
-device_zorro_card_interface::device_zorro_card_interface(const machine_config &mconfig, device_t &device) :
- device_slot_card_interface(mconfig, device),
- m_zorro(nullptr)
+zorro2_slot_device::zorro2_slot_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) :
+ zorro2_slot_device(mconfig, ZORRO2_SLOT, tag, owner, clock)
{
}
-//-------------------------------------------------
-// ~device_zorro_card_interface - destructor
-//-------------------------------------------------
-
-device_zorro_card_interface::~device_zorro_card_interface()
+zorro2_slot_device::zorro2_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(mconfig, *this)
{
}
-void device_zorro_card_interface::set_zorro_bus(zorro_device *device)
+void zorro2_slot_device::device_resolve_objects()
{
- m_zorro = device;
-}
+ device_zorro2_card_interface *dev = get_card_device();
-void device_zorro_card_interface::fc_w(int code)
-{
+ if (dev)
+ {
+ zorro2_bus_device *bus = downcast<zorro2_bus_device *>(m_owner);
+ bus->add_card(*dev);
+ }
}
-WRITE_LINE_MEMBER( device_zorro_card_interface::cfgin_w )
+void zorro2_slot_device::device_start()
{
}
//**************************************************************************
-// EXPANSION CARD INTERFACE
+// CARD INTERFACE
//**************************************************************************
-//-------------------------------------------------
-// device_exp_card_interface - constructor
-//-------------------------------------------------
-
-device_exp_card_interface::device_exp_card_interface(const machine_config &mconfig, device_t &device) :
- device_zorro_card_interface(mconfig, device),
- m_slot(nullptr)
+device_zorro2_card_interface::device_zorro2_card_interface(const machine_config &mconfig, device_t &device) :
+ device_interface(device, "zorro2"),
+ m_zorro(nullptr)
{
}
-//-------------------------------------------------
-// ~device_exp_card_interface - destructor
-//-------------------------------------------------
-
-device_exp_card_interface::~device_exp_card_interface()
+device_zorro2_card_interface::~device_zorro2_card_interface()
{
}
-void device_exp_card_interface::set_zorro_device()
+void device_zorro2_card_interface::set_bus(zorro2_bus_device &device)
{
- m_slot = dynamic_cast<exp_slot_device *>(m_zorro);
+ assert(!m_zorro);
+ m_zorro = &device;
}
-
-//**************************************************************************
-// ZORRO-II CARD INTERFACE
-//**************************************************************************
-
-//-------------------------------------------------
-// device_zorro2_interface - constructor
-//-------------------------------------------------
-
-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)
+void device_zorro2_card_interface::fc_w(int code)
{
}
-//-------------------------------------------------
-// ~device_zorro2_interface - destructor
-//-------------------------------------------------
-
-device_zorro2_card_interface::~device_zorro2_card_interface()
+void device_zorro2_card_interface::cfgin_w(int state)
{
}
-void device_zorro2_card_interface::set_zorro_device()
+void device_zorro2_card_interface::busrst_w(int state)
{
- m_slot = dynamic_cast<zorro2_device *>(m_zorro);
}
diff --git a/src/devices/bus/amiga/zorro/zorro.h b/src/devices/bus/amiga/zorro/zorro.h
index 4ad72da638b..2662a3e9356 100644
--- a/src/devices/bus/amiga/zorro/zorro.h
+++ b/src/devices/bus/amiga/zorro/zorro.h
@@ -1,23 +1,19 @@
-// license:GPL-2.0+
-// copyright-holders:Dirk Best
+// license: GPL-2.0+
+// copyright-holders: Dirk Best
/***************************************************************************
- Amiga Zorro Slots
-
- 86-pin Expansion Slot (Zorro-I), Zorro-II, Zorro-III
-
- 86-pin Expansion Slot
+ Amiga Zorro-II Slot
2 Ground 1 Ground
4 Ground 3 Ground
6 +5VDC 5 +5VDC
- 8 -5VDC 7 N/C
- 10 +12VDC 9 N/C *1
- 12 CFGIN 11 N/C *2
+ 8 -5VDC 7 /OWN
+ 10 +12VDC 9 /SLAVEn
+ 12 CFGINn 11 CFGOUTn
14 /C3 Clock 13 Ground
16 /C1 Clock 15 CDAC
18 XRDY 17 /OVR
- 20 N/C *3 19 /INT2
+ 20 -12V 19 /INT2
22 /INT6 21 A5
24 A4 23 A6
26 A3 25 Ground
@@ -27,21 +23,21 @@
34 A10 33 FC1
36 A11 35 FC2
38 A12 37 Ground
- 40 /IPL0 39 A13
- 42 /IPL1 41 A14
- 44 /IPL2 43 A15
- 46 /BEER 45 A16
+ 40 /EINT7 39 A13
+ 42 /EINT5 41 A14
+ 44 /EINT4 43 A15
+ 46 /BERR 45 A16
48 /VPA 47 A17
50 E Clock 49 Ground
52 A18 51 /VMA
54 A19 53 /RST
56 A20 55 /HLT
58 A21 57 A22
- 60 /BR *4 59 A23
+ 60 /BRn 59 A23
62 /BGACK 61 Ground
- 64 /BG *5 63 D15
+ 64 /BGn 63 D15
66 /DTACK 65 D14
- 68 R/W 67 D13
+ 68 READ 67 D13
70 /LDS 69 D12
72 /UDS 71 D11
74 /AS 73 Ground
@@ -51,91 +47,14 @@
82 D7 81 D3
84 D6 83 D4
86 D5 85 Ground
-
- *1 28 MHz Clock on A2000 and B2000
- *2 /COPCFG on B2000
- *3 /PALOPE on A1000, /BOSS on B2000
- *4 /CBR on B2000
- *5 /CBG on B2000
-
- Zorro-II (differences only)
-
- 7 /OWN
- 9 /SLAVEn
- 11 /CFGOUTn
- 12 /CFGINn
- 20 -12VDC
- 40 /EINT7
- 42 /EINT5
- 44 /EINT4
- 60 /BRn
- 64 /BGn
-
- 88 Ground 87 Ground
+ 87 Ground 88 Ground
90 Ground 89 Ground
- 92 7 MHz 91 Ground
- 94 /BURST 93 DOE
- 96 /EINT1 95 /BG *5
+ 92 7MHz 91 Ground
+ 94 /BUSRST 93 DOE
+ 96 /EINT1 95 /(C)BG
98 N/C 97 N/C
100 Ground 99 Ground
- *6 /GBG on B2000
-
- Zorro-III
-
- The Zorro-III is a multiplexed Zorro-II bus with address- and
- data phases. Signals changes as follows:
-
- 17 /CINH
- 18 /MTCR
- 29 /LOCK
- 30 AD8 (D0)
- 32 AD9 (D1)
- 34 AD10 (D2)
- 36 AD11 (D3)
- 38 AD12 (D4)
- 39 AD13 (D5)
- 40 Reserved
- 41 AD14 (D6)
- 42 Reserved
- 43 AD15 (D7)
- 44 Reserved
- 45 AD16 (D8)
- 47 AD17 (D9)
- 48 /MTACK
- 51 /DS0
- 52 AD18 (D10)
- 54 AD19 (D11)
- 56 AD20 (D12)
- 57 AD22 (D14)
- 58 AD21 (D13)
- 59 AD23 (D15)
- 63 AD31
- 65 AD30
- 67 AD29
- 69 AD28
- 70 /DS2
- 71 AD27
- 72 /DS3
- 74 /CCS
- 75 SD0 (D16)
- 76 AD26
- 77 SD1 (D17)
- 78 AD25
- 79 SD2 (D18)
- 80 AD24
- 81 SD3 (D19)
- 82 SD7 (D23)
- 83 SD4 (D20)
- 84 SD6 (D22)
- 86 SD5 (D21)
- 91 Sense Z3
- 94 /IORST
- 95 /BCLR
- 97 /FCS
- 98 /DS1
-
-
***************************************************************************/
#ifndef MAME_BUS_AMIGA_ZORRO_ZORRO_H
@@ -143,243 +62,140 @@
#pragma once
+#include <functional>
+#include <utility>
+#include <vector>
-//**************************************************************************
-// TYPE DEFINITIONS
-//**************************************************************************
// forward declaration of card interfaces
-class device_zorro_card_interface;
-class device_exp_card_interface;
class device_zorro2_card_interface;
-class zorro_device;
-// ======================> zorro slot device
-class zorro_slot_device : public device_t, public device_slot_interface
-{
-public:
- // construction/destruction
- zorro_slot_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
- template <typename T, typename O>
- zorro_slot_device(const machine_config &mconfig, const char *tag, device_t *owner, T &&zorrotag, O &&opts, const char *dflt)
- : zorro_slot_device(mconfig, tag, owner, 0)
- {
- set_zorro_slot(std::forward<T>(zorrotag));
- option_reset();
- opts(*this);
- set_default_option(dflt);
- set_fixed(false);
- }
-
- // device-level overrides
- virtual void device_start() override;
-
- // inline configuration
- template <class T> void set_zorro_slot(T &&zorro_tag) { m_zorro_bus.set_tag(zorro_tag); }
-
-protected:
- zorro_slot_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock);
-
- // configuration
- required_device<zorro_device> m_zorro_bus;
-};
-
-// device type definition
-DECLARE_DEVICE_TYPE(ZORRO_SLOT, zorro_slot_device)
-
-// ======================> base zorro bus device
+//**************************************************************************
+// BUS DEVICE
+//**************************************************************************
-class zorro_device : public device_t
+class zorro2_bus_device : public device_t, public device_memory_interface
{
public:
- // configuration helpers
- template <class T> void set_space(T &&tag, int spacenum) { m_space.set_tag(std::forward<T>(tag), spacenum); }
+ zorro2_bus_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
+ auto eint1_handler() { return m_eint1_handler.bind(); }
+ auto eint4_handler() { return m_eint4_handler.bind(); }
+ auto eint5_handler() { return m_eint5_handler.bind(); }
+ auto eint7_handler() { return m_eint7_handler.bind(); }
auto int2_handler() { return m_int2_handler.bind(); }
auto int6_handler() { return m_int6_handler.bind(); }
auto ovr_handler() { return m_ovr_handler.bind(); }
- virtual void add_card(device_zorro_card_interface *card) = 0;
+ // device_memory_interface
+ virtual space_config_vector memory_space_config() const override;
- // interface (from slot device)
- virtual DECLARE_WRITE_LINE_MEMBER( cfgout_w ) {};
+ virtual void add_card(device_zorro2_card_interface &card) ATTR_COLD;
- DECLARE_WRITE_LINE_MEMBER( int2_w );
- DECLARE_WRITE_LINE_MEMBER( int6_w );
- DECLARE_WRITE_LINE_MEMBER( ovr_w );
+ // interface (from slot device)
+ void cfgout_w(int state);
+ void eint1_w(int state);
+ void eint4_w(int state);
+ void eint5_w(int state);
+ void eint7_w(int state);
+ 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;
-
- // access to the host space
- address_space &space() const { return *m_space; }
-
-protected:
- // construction/destruction
- zorro_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock);
+ uint16_t mem_r(offs_t offset, uint16_t mem_mask);
+ void mem_w(offs_t offset, uint16_t data, uint16_t mem_mask);
+ uint16_t io_r(offs_t offset, uint16_t mem_mask);
+ void io_w(offs_t offset, uint16_t data, uint16_t mem_mask);
- // device-level overrides
- virtual void device_resolve_objects() override;
- virtual void device_start() override;
-
-private:
- required_address_space m_space;
-
- devcb_write_line m_ovr_handler;
- devcb_write_line m_int2_handler;
- devcb_write_line m_int6_handler;
-};
+ void fc_w(int code);
+ void busrst_w(int state);
-// ======================> expansion slot device
-
-class exp_slot_device : public zorro_device
-{
-public:
- // construction/destruction
- exp_slot_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
-
- auto ipl_handler() { return m_ipl_handler.bind(); }
-
- // the expansion slot can only have a single card
- virtual void add_card(device_zorro_card_interface *card) override;
-
- // interface (from slot device)
- void ipl_w(int interrupt);
-
- // interface (from host)
- virtual void fc_w(int code) override;
+ // access to the zorro2 space
+ address_space &space() const { return device_memory_interface::space(AS_PROGRAM); }
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;
- virtual void device_reset() override;
+ virtual void device_start() override ATTR_COLD;
private:
- devcb_write8 m_ipl_handler;
-
- device_exp_card_interface *m_dev;
-};
-
-// device type definition
-DECLARE_DEVICE_TYPE(EXP_SLOT, exp_slot_device)
+ using card_vector = std::vector<std::reference_wrapper<device_zorro2_card_interface>>;
+ card_vector m_cards;
-// ======================> zorro2 slot device
+ address_space_config m_zorro_space_config;
-class zorro2_device : public zorro_device
-{
-public:
- // construction/destruction
- zorro2_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
- ~zorro2_device();
-
- auto eint1_handler() { return m_eint1_handler.bind(); }
- auto eint4_handler() { return m_eint4_handler.bind(); }
- auto eint5_handler() { return m_eint5_handler.bind(); }
- auto eint7_handler() { return m_eint7_handler.bind(); }
-
- // the zorro2 bus supports multiple cards
- virtual void add_card(device_zorro_card_interface *card) override;
-
- // interface (from slot device)
- virtual DECLARE_WRITE_LINE_MEMBER( cfgout_w ) 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 );
-
- // interface (from host)
- virtual void fc_w(int code) override;
-
-protected:
- zorro2_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_reset() override;
-
-private:
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;
+ devcb_write_line m_int2_handler;
+ devcb_write_line m_int6_handler;
+ devcb_write_line m_ovr_handler;
// the device which is currently configuring
- device_zorro2_card_interface *m_autoconfig_device;
+ uint8_t m_autoconfig_device;
};
-// device type definition
-DECLARE_DEVICE_TYPE(ZORRO2, zorro2_device)
+// device type declaration
+DECLARE_DEVICE_TYPE(ZORRO2_BUS, zorro2_bus_device)
-// ======================> base zorro card interface
+//**************************************************************************
+// SLOT DEVICE
+//**************************************************************************
-class device_zorro_card_interface : public device_slot_card_interface
+class zorro2_slot_device : public device_t, public device_single_card_slot_interface<device_zorro2_card_interface>
{
public:
- // construction/destruction
- virtual ~device_zorro_card_interface();
-
- virtual void set_zorro_device() = 0;
-
- void set_zorro_bus(zorro_device *device);
-
- // interface (from device)
- void cfgout_w(int state) { m_zorro->cfgout_w(state); }
+ zorro2_slot_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
- // interface (from host)
- virtual void fc_w(int code);
- virtual DECLARE_WRITE_LINE_MEMBER( cfgin_w );
+ template <typename T>
+ zorro2_slot_device(const machine_config &mconfig, const char *tag, device_t *owner, T &&opts, const char *dflt) :
+ zorro2_slot_device(mconfig, tag, owner, 0)
+ {
+ option_reset();
+ opts(*this);
+ set_default_option(dflt);
+ set_fixed(false);
+ }
protected:
- device_zorro_card_interface(const machine_config &mconfig, device_t &device);
+ zorro2_slot_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock);
- zorro_device *m_zorro;
+ virtual void device_resolve_objects() override ATTR_COLD;
+ virtual void device_start() override ATTR_COLD;
};
-// ======================> expansion slot card interface
+// device type declaration
+DECLARE_DEVICE_TYPE(ZORRO2_SLOT, zorro2_slot_device)
-class device_exp_card_interface : public device_zorro_card_interface
-{
-public:
- // construction/destruction
- virtual ~device_exp_card_interface();
-
- virtual void set_zorro_device() override;
-protected:
- device_exp_card_interface(const machine_config &mconfig, device_t &device);
-
- exp_slot_device *m_slot;
-};
-
-// ======================> zorro2 card interface
+//**************************************************************************
+// INTERFACE
+//**************************************************************************
-class device_zorro2_card_interface : public device_zorro_card_interface
+class device_zorro2_card_interface : public device_interface
{
public:
- // construction/destruction
+ device_zorro2_card_interface(const machine_config &mconfig, device_t &device);
virtual ~device_zorro2_card_interface();
- virtual void set_zorro_device() override;
+ void set_bus(zorro2_bus_device &device) ATTR_COLD;
- device_zorro2_card_interface *next() const { return m_next; }
- device_zorro2_card_interface *m_next;
+ // interface (from device)
+ void cfgout_w(int state) { m_zorro->cfgout_w(state); }
-protected:
- device_zorro2_card_interface(const machine_config &mconfig, device_t &device);
+ // interface (from host)
+ virtual void fc_w(int code);
+ virtual void cfgin_w(int state);
+ virtual void busrst_w(int state);
- zorro2_device *m_slot;
+protected:
+ zorro2_bus_device *m_zorro;
};
-// include this here so that you don't need to include it into every
-// driver that uses zorro slots
+// include this here so that you don't need to include it into every driver that uses zorro slots
#include "cards.h"
diff --git a/src/devices/bus/apf/rom.cpp b/src/devices/bus/apf/rom.cpp
index 113e5bf5259..509aa30f458 100644
--- a/src/devices/bus/apf/rom.cpp
+++ b/src/devices/bus/apf/rom.cpp
@@ -47,7 +47,7 @@ apf_spacedst_device::apf_spacedst_device(const machine_config &mconfig, const ch
mapper specific handlers
-------------------------------------------------*/
-READ8_MEMBER(apf_rom_device::read_rom)
+uint8_t apf_rom_device::read_rom(offs_t offset)
{
if (offset < m_rom_size)
return m_rom[offset];
@@ -56,7 +56,7 @@ READ8_MEMBER(apf_rom_device::read_rom)
}
-READ8_MEMBER(apf_basic_device::extra_rom)
+uint8_t apf_basic_device::extra_rom(offs_t offset)
{
if (offset < (m_rom_size - 0x2000))
return m_rom[offset + 0x2000];
@@ -65,12 +65,12 @@ READ8_MEMBER(apf_basic_device::extra_rom)
}
-READ8_MEMBER(apf_spacedst_device::read_ram)
+uint8_t apf_spacedst_device::read_ram(offs_t offset)
{
return m_ram[offset];
}
-WRITE8_MEMBER(apf_spacedst_device::write_ram)
+void apf_spacedst_device::write_ram(offs_t offset, uint8_t data)
{
m_ram[offset] = data;
}
diff --git a/src/devices/bus/apf/rom.h b/src/devices/bus/apf/rom.h
index 89d82f51a99..ab129289493 100644
--- a/src/devices/bus/apf/rom.h
+++ b/src/devices/bus/apf/rom.h
@@ -16,7 +16,7 @@ public:
apf_rom_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
// reading and writing
- virtual DECLARE_READ8_MEMBER(read_rom) override;
+ virtual uint8_t read_rom(offs_t offset) override;
protected:
apf_rom_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock);
@@ -35,7 +35,7 @@ public:
apf_basic_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
// reading and writing
- virtual DECLARE_READ8_MEMBER(extra_rom) override;
+ virtual uint8_t extra_rom(offs_t offset) override;
};
// ======================> apf_spacedst_device
@@ -47,8 +47,8 @@ public:
apf_spacedst_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
// reading and writing
- virtual DECLARE_READ8_MEMBER(read_ram) override;
- virtual DECLARE_WRITE8_MEMBER(write_ram) override;
+ virtual uint8_t read_ram(offs_t offset) override;
+ virtual void write_ram(offs_t offset, uint8_t data) override;
};
diff --git a/src/devices/bus/apf/slot.cpp b/src/devices/bus/apf/slot.cpp
index 871c43e4655..2c5c3edb7f7 100644
--- a/src/devices/bus/apf/slot.cpp
+++ b/src/devices/bus/apf/slot.cpp
@@ -7,7 +7,6 @@
***********************************************************************************************************/
-
#include "emu.h"
#include "slot.h"
@@ -25,10 +24,10 @@ DEFINE_DEVICE_TYPE(APF_CART_SLOT, apf_cart_slot_device, "apf_cart_slot", "APF Ca
// device_apf_cart_interface - constructor
//-------------------------------------------------
-device_apf_cart_interface::device_apf_cart_interface(const machine_config &mconfig, device_t &device)
- : device_slot_card_interface(mconfig, device),
- m_rom(nullptr),
- m_rom_size(0)
+device_apf_cart_interface::device_apf_cart_interface(const machine_config &mconfig, device_t &device) :
+ device_interface(device, "apfcart"),
+ m_rom(nullptr),
+ m_rom_size(0)
{
}
@@ -45,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;
}
}
@@ -74,9 +73,10 @@ void device_apf_cart_interface::ram_alloc(uint32_t size)
//-------------------------------------------------
apf_cart_slot_device::apf_cart_slot_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) :
device_t(mconfig, APF_CART_SLOT, tag, owner, clock),
- device_image_interface(mconfig, *this),
- device_slot_interface(mconfig, *this),
- m_type(APF_STD), m_cart(nullptr)
+ device_cartrom_image_interface(mconfig, *this),
+ device_single_card_slot_interface<device_apf_cart_interface>(mconfig, *this),
+ m_type(APF_STD),
+ m_cart(nullptr)
{
}
@@ -95,7 +95,7 @@ apf_cart_slot_device::~apf_cart_slot_device()
void apf_cart_slot_device::device_start()
{
- m_cart = dynamic_cast<device_apf_cart_interface *>(get_card_device());
+ m_cart = get_card_device();
}
@@ -121,7 +121,7 @@ static int apf_get_pcb_id(const char *slot)
{
for (auto & elem : slot_list)
{
- if (!core_stricmp(elem.slot_option, slot))
+ if (!strcmp(elem.slot_option, slot))
return elem.pcb_id;
}
@@ -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_UNSPECIFIED, "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());
}
@@ -202,17 +197,17 @@ std::string apf_cart_slot_device::get_default_card_software(get_default_card_sof
{
if (hook.image_file())
{
- const char *slot_string;
- uint32_t size = hook.image_file()->size();
- int type = APF_STD;
+ uint64_t size;
+ hook.image_file()->length(size); // FIXME: check error return
// attempt to identify Space Destroyer, which needs 1K of additional RAM
+ int type = APF_STD;
if (size == 0x1800)
type = APF_SPACEDST;
if (size > 0x2000)
type = APF_BASIC;
- slot_string = apf_get_slot(type);
+ char const *const slot_string = apf_get_slot(type);
//printf("type: %s\n", slot_string);
@@ -226,10 +221,10 @@ std::string apf_cart_slot_device::get_default_card_software(get_default_card_sof
read
-------------------------------------------------*/
-READ8_MEMBER(apf_cart_slot_device::read_rom)
+uint8_t apf_cart_slot_device::read_rom(offs_t offset)
{
if (m_cart)
- return m_cart->read_rom(space, offset);
+ return m_cart->read_rom(offset);
else
return 0xff;
}
@@ -238,10 +233,10 @@ READ8_MEMBER(apf_cart_slot_device::read_rom)
read
-------------------------------------------------*/
-READ8_MEMBER(apf_cart_slot_device::extra_rom)
+uint8_t apf_cart_slot_device::extra_rom(offs_t offset)
{
if (m_cart)
- return m_cart->extra_rom(space, offset);
+ return m_cart->extra_rom(offset);
else
return 0xff;
}
@@ -250,10 +245,10 @@ READ8_MEMBER(apf_cart_slot_device::extra_rom)
read
-------------------------------------------------*/
-READ8_MEMBER(apf_cart_slot_device::read_ram)
+uint8_t apf_cart_slot_device::read_ram(offs_t offset)
{
if (m_cart)
- return m_cart->read_ram(space, offset);
+ return m_cart->read_ram(offset);
else
return 0xff;
}
@@ -262,8 +257,8 @@ READ8_MEMBER(apf_cart_slot_device::read_ram)
write
-------------------------------------------------*/
-WRITE8_MEMBER(apf_cart_slot_device::write_ram)
+void apf_cart_slot_device::write_ram(offs_t offset, uint8_t data)
{
if (m_cart)
- m_cart->write_ram(space, offset, data);
+ m_cart->write_ram(offset, data);
}
diff --git a/src/devices/bus/apf/slot.h b/src/devices/bus/apf/slot.h
index 3678124c3e9..71b831dbded 100644
--- a/src/devices/bus/apf/slot.h
+++ b/src/devices/bus/apf/slot.h
@@ -3,7 +3,7 @@
#ifndef MAME_BUS_APF_SLOT_H
#define MAME_BUS_APF_SLOT_H
-#include "softlist_dev.h"
+#include "imagedev/cartrom.h"
/***************************************************************************
TYPE DEFINITIONS
@@ -21,7 +21,7 @@ enum
// ======================> device_apf_cart_interface
-class device_apf_cart_interface : public device_slot_card_interface
+class device_apf_cart_interface : public device_interface
{
public:
// construction/destruction
@@ -29,12 +29,12 @@ public:
virtual ~device_apf_cart_interface();
// reading and writing
- virtual DECLARE_READ8_MEMBER(read_rom) { return 0xff; }
- virtual DECLARE_READ8_MEMBER(extra_rom) { return 0xff; }
- virtual DECLARE_READ8_MEMBER(read_ram) { return 0xff; }
- virtual DECLARE_WRITE8_MEMBER(write_ram) {}
+ virtual uint8_t read_rom(offs_t offset) { return 0xff; }
+ virtual uint8_t extra_rom(offs_t offset) { return 0xff; }
+ 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]; }
@@ -54,8 +54,8 @@ protected:
// ======================> apf_cart_slot_device
class apf_cart_slot_device : public device_t,
- public device_image_interface,
- public device_slot_interface
+ public device_cartrom_image_interface,
+ public device_single_card_slot_interface<device_apf_cart_interface>
{
public:
// construction/destruction
@@ -72,52 +72,37 @@ public:
apf_cart_slot_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock = 0);
virtual ~apf_cart_slot_device();
- // 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 void call_unload() override {}
- virtual const software_list_loader &get_software_list_loader() const override { return rom_software_list_loader::instance(); }
- int get_type() { return m_type; }
+ 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"; }
- void save_ram() { if (m_cart && m_cart->get_ram_size()) m_cart->save_ram(); }
+ // device_slot_interface implementation
+ virtual std::string get_default_card_software(get_default_card_software_hook &hook) const override;
- virtual iodevice_t image_type() const override { return IO_CARTSLOT; }
- virtual bool is_readable() const override { return 1; }
- virtual bool is_writeable() const override { return 0; }
- virtual bool is_creatable() const override { return 0; }
- virtual bool must_be_loaded() const override { return 0; }
- virtual bool is_reset_on_load() const override { return 1; }
- virtual const char *image_interface() const override { return "apfm1000_cart"; }
- virtual const char *file_extensions() const override { return "bin"; }
+ int get_type() { return m_type; }
- // slot interface overrides
- virtual std::string get_default_card_software(get_default_card_software_hook &hook) const override;
+ void save_ram() { if (m_cart && m_cart->get_ram_size()) m_cart->save_ram(); }
// reading and writing
- virtual DECLARE_READ8_MEMBER(read_rom);
- virtual DECLARE_READ8_MEMBER(extra_rom);
- virtual DECLARE_READ8_MEMBER(read_ram);
- virtual DECLARE_WRITE8_MEMBER(write_ram);
+ uint8_t read_rom(offs_t offset);
+ uint8_t extra_rom(offs_t offset);
+ uint8_t read_ram(offs_t offset);
+ void write_ram(offs_t offset, uint8_t data);
protected:
+ // device_t implementation
+ virtual void device_start() override ATTR_COLD;
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 5a89c9a8868..606e2b913fe 100644
--- a/src/devices/bus/apricot/expansion/expansion.cpp
+++ b/src/devices/bus/apricot/expansion/expansion.cpp
@@ -27,7 +27,7 @@ apricot_expansion_slot_device::apricot_expansion_slot_device(const machine_confi
apricot_expansion_slot_device::apricot_expansion_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)
+ device_single_card_slot_interface<device_apricot_expansion_card_interface>(mconfig, *this)
{
}
@@ -37,7 +37,7 @@ apricot_expansion_slot_device::apricot_expansion_slot_device(const machine_confi
void apricot_expansion_slot_device::device_start()
{
- device_apricot_expansion_card_interface *dev = dynamic_cast<device_apricot_expansion_card_interface *>(get_card_device());
+ device_apricot_expansion_card_interface *dev = get_card_device();
if (dev)
{
@@ -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
@@ -136,9 +128,8 @@ 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_slot_card_interface(mconfig, device),
- m_bus(nullptr),
- m_next(nullptr)
+ device_interface(device, "apricotexp"),
+ m_bus(nullptr)
{
}
diff --git a/src/devices/bus/apricot/expansion/expansion.h b/src/devices/bus/apricot/expansion/expansion.h
index 93c529f24e3..933f7d903f6 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
@@ -57,7 +60,7 @@ class device_apricot_expansion_card_interface;
// ======================> apricot_expansion_slot_device
-class apricot_expansion_slot_device : public device_t, public device_slot_interface
+class apricot_expansion_slot_device : public device_t, public device_single_card_slot_interface<device_apricot_expansion_card_interface>
{
public:
// construction/destruction
@@ -75,8 +78,8 @@ 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
- virtual void device_start() override;
+ // device_t implementation
+ virtual void device_start() override ATTR_COLD;
};
// device type definition
@@ -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
- virtual void device_start() override;
+ // device_t implementation
+ virtual void device_start() override ATTR_COLD;
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;
@@ -151,24 +157,18 @@ DECLARE_DEVICE_TYPE(APRICOT_EXPANSION_BUS, apricot_expansion_bus_device)
// ======================> device_apricot_expansion_card_interface
-class device_apricot_expansion_card_interface : public device_slot_card_interface
+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/ram.h b/src/devices/bus/apricot/expansion/ram.h
index d6692b49ba7..37325e58516 100644
--- a/src/devices/bus/apricot/expansion/ram.h
+++ b/src/devices/bus/apricot/expansion/ram.h
@@ -6,8 +6,8 @@
***************************************************************************/
-#ifndef MAME_BUS_APRICOT_RAM_H
-#define MAME_BUS_APRICOT_RAM_H
+#ifndef MAME_BUS_APRICOT_EXPANSION_RAM_H
+#define MAME_BUS_APRICOT_EXPANSION_RAM_H
#pragma once
@@ -28,9 +28,9 @@ public:
apricot_256k_ram_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 ioport_constructor device_input_ports() const override ATTR_COLD;
+ virtual void device_start() override ATTR_COLD;
+ virtual void device_reset() override ATTR_COLD;
private:
required_ioport m_sw;
@@ -48,9 +48,9 @@ public:
apricot_128k_ram_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 ioport_constructor device_input_ports() const override ATTR_COLD;
+ virtual void device_start() override ATTR_COLD;
+ virtual void device_reset() override ATTR_COLD;
private:
required_ioport m_strap;
@@ -68,9 +68,9 @@ public:
apricot_512k_ram_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 ioport_constructor device_input_ports() const override ATTR_COLD;
+ virtual void device_start() override ATTR_COLD;
+ virtual void device_reset() override ATTR_COLD;
private:
required_ioport m_strap;
@@ -85,4 +85,4 @@ DECLARE_DEVICE_TYPE(APRICOT_128K_RAM, apricot_128k_ram_device)
DECLARE_DEVICE_TYPE(APRICOT_512K_RAM, apricot_512k_ram_device)
-#endif // MAME_BUS_APRICOT_RAM_H
+#endif // MAME_BUS_APRICOT_EXPANSION_RAM_H
diff --git a/src/devices/bus/apricot/expansion/winchester.cpp b/src/devices/bus/apricot/expansion/winchester.cpp
index 5096cd7d4e0..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,14 +165,15 @@ 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);
+ m_hdc->head_w(m_head);
}
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);
@@ -201,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);
@@ -219,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..09cd450ff70 100644
--- a/src/devices/bus/apricot/expansion/winchester.h
+++ b/src/devices/bus/apricot/expansion/winchester.h
@@ -6,8 +6,8 @@
***************************************************************************/
-#ifndef MAME_BUS_APRICOT_WINCHESTER_H
-#define MAME_BUS_APRICOT_WINCHESTER_H
+#ifndef MAME_BUS_APRICOT_EXPANSION_WINCHESTER_H
+#define MAME_BUS_APRICOT_EXPANSION_WINCHESTER_H
#pragma once
@@ -29,24 +29,24 @@ public:
protected:
// device-level overrides
- virtual void device_add_mconfig(machine_config &config) override;
- virtual void device_start() override;
- virtual void device_reset() override;
+ 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:
- 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);
- void regs(address_map &map);
+ void regs(address_map &map) ATTR_COLD;
required_device<wd1010_device> m_hdc;
@@ -62,4 +62,4 @@ private:
// device type definition
DECLARE_DEVICE_TYPE(APRICOT_WINCHESTER, apricot_winchester_device)
-#endif // MAME_BUS_APRICOT_WINCHESTER_H
+#endif // MAME_BUS_APRICOT_EXPANSION_WINCHESTER_H
diff --git a/src/devices/bus/apricot/keyboard/hle.cpp b/src/devices/bus/apricot/keyboard/hle.cpp
index 28e98b9fb50..8a33c2952fa 100644
--- a/src/devices/bus/apricot/keyboard/hle.cpp
+++ b/src/devices/bus/apricot/keyboard/hle.cpp
@@ -290,7 +290,7 @@ void apricot_keyboard_hle_device::received_byte(uint8_t byte)
if (m_rtc_index >= 0)
{
m_rtc->address_w(m_rtc_index--);
- m_rtc->data_w(machine().dummy_space(), 0, byte);
+ m_rtc->data_w(byte);
m_rtc->write_w(1);
m_rtc->write_w(0);
}
@@ -316,7 +316,7 @@ void apricot_keyboard_hle_device::received_byte(uint8_t byte)
for (int i = 12; i >= 0; i--)
{
m_rtc->address_w(i);
- transmit_byte(0xf0 | m_rtc->data_r(machine().dummy_space(), 0));
+ transmit_byte(0xf0 | m_rtc->data_r());
}
break;
diff --git a/src/devices/bus/apricot/keyboard/hle.h b/src/devices/bus/apricot/keyboard/hle.h
index c9738598a57..cf149f77989 100644
--- a/src/devices/bus/apricot/keyboard/hle.h
+++ b/src/devices/bus/apricot/keyboard/hle.h
@@ -38,10 +38,10 @@ public:
protected:
// device_t overrides
- 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;
+ virtual ioport_constructor device_input_ports() const override ATTR_COLD;
+ 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;
// device_buffered_serial_interface overrides
virtual void tra_callback() override;
diff --git a/src/devices/bus/apricot/keyboard/keyboard.cpp b/src/devices/bus/apricot/keyboard/keyboard.cpp
index 6f502ae7c76..bb63a0e20c5 100644
--- a/src/devices/bus/apricot/keyboard/keyboard.cpp
+++ b/src/devices/bus/apricot/keyboard/keyboard.cpp
@@ -28,7 +28,7 @@ DEFINE_DEVICE_TYPE(APRICOT_KEYBOARD_INTERFACE, apricot_keyboard_bus_device, "apr
apricot_keyboard_bus_device::apricot_keyboard_bus_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) :
device_t(mconfig, APRICOT_KEYBOARD_INTERFACE, tag, owner, clock),
- device_slot_interface(mconfig, *this),
+ device_single_card_slot_interface<device_apricot_keyboard_interface>(mconfig, *this),
m_kbd(nullptr),
m_in_handler(*this)
{
@@ -49,28 +49,17 @@ apricot_keyboard_bus_device::~apricot_keyboard_bus_device()
void apricot_keyboard_bus_device::device_start()
{
// get connected keyboard
- m_kbd = dynamic_cast<device_apricot_keyboard_interface *>(get_card_device());
-
- // resolve callbacks
- m_in_handler.resolve_safe();
-}
-
-//-------------------------------------------------
-// device_reset - device-specific reset
-//-------------------------------------------------
-
-void apricot_keyboard_bus_device::device_reset()
-{
+ m_kbd = get_card_device();
}
//-------------------------------------------------
// 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);
+ if (m_kbd)
+ m_kbd->out_w(state);
}
@@ -83,7 +72,7 @@ WRITE_LINE_MEMBER( apricot_keyboard_bus_device::out_w )
//-------------------------------------------------
device_apricot_keyboard_interface::device_apricot_keyboard_interface(const machine_config &mconfig, device_t &device) :
- device_slot_card_interface(mconfig, device)
+ device_interface(device, "apricotkbd")
{
m_host = dynamic_cast<apricot_keyboard_bus_device *>(device.owner());
}
diff --git a/src/devices/bus/apricot/keyboard/keyboard.h b/src/devices/bus/apricot/keyboard/keyboard.h
index 9395dac4855..7f00dc7b0e6 100644
--- a/src/devices/bus/apricot/keyboard/keyboard.h
+++ b/src/devices/bus/apricot/keyboard/keyboard.h
@@ -42,7 +42,7 @@ class device_apricot_keyboard_interface;
// ======================> apricot_keyboard_bus_device
-class apricot_keyboard_bus_device : public device_t, public device_slot_interface
+class apricot_keyboard_bus_device : public device_t, public device_single_card_slot_interface<device_apricot_keyboard_interface>
{
public:
// construction/destruction
@@ -62,15 +62,14 @@ 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
- virtual void device_start() override;
- virtual void device_reset() override;
+ virtual void device_start() override ATTR_COLD;
private:
device_apricot_keyboard_interface *m_kbd;
@@ -80,7 +79,7 @@ private:
// ======================> device_apricot_keyboard_interface
-class device_apricot_keyboard_interface : public device_slot_card_interface
+class device_apricot_keyboard_interface : public device_interface
{
public:
// construction/destruction
diff --git a/src/devices/bus/apricot/video/cards.cpp b/src/devices/bus/apricot/video/cards.cpp
new file mode 100644
index 00000000000..7611be80abc
--- /dev/null
+++ b/src/devices/bus/apricot/video/cards.cpp
@@ -0,0 +1,16 @@
+// license: GPL-2.0+
+// copyright-holders: Dirk Best
+/***************************************************************************
+
+ ACT Apricot XEN Video Expansion Slot Devices
+
+***************************************************************************/
+
+#include "emu.h"
+#include "cards.h"
+#include "mono.h"
+
+void apricot_video_cards(device_slot_interface &device)
+{
+ device.option_add("mono", APRICOT_MONO_DISPLAY);
+}
diff --git a/src/devices/bus/apricot/video/cards.h b/src/devices/bus/apricot/video/cards.h
new file mode 100644
index 00000000000..61460b37064
--- /dev/null
+++ b/src/devices/bus/apricot/video/cards.h
@@ -0,0 +1,16 @@
+// license: GPL-2.0+
+// copyright-holders: Dirk Best
+/***************************************************************************
+
+ ACT Apricot XEN Video Expansion Slot Devices
+
+***************************************************************************/
+
+#ifndef MAME_BUS_APRICOT_VIDEO_CARDS_H
+#define MAME_BUS_APRICOT_VIDEO_CARDS_H
+
+#pragma once
+
+void apricot_video_cards(device_slot_interface &device);
+
+#endif // MAME_BUS_APRICOT_VIDEO_CARDS_H
diff --git a/src/devices/bus/apricot/video/mono.cpp b/src/devices/bus/apricot/video/mono.cpp
new file mode 100644
index 00000000000..424df94cea8
--- /dev/null
+++ b/src/devices/bus/apricot/video/mono.cpp
@@ -0,0 +1,278 @@
+// license: GPL-2.0+
+// copyright-holders: Dirk Best
+/***************************************************************************
+
+ ACT Apricot XEN Monochrome Display Option
+
+ TODO:
+ - Support monitor selection
+
+***************************************************************************/
+
+#include "emu.h"
+#include "mono.h"
+#include "screen.h"
+
+
+//**************************************************************************
+// DEVICE DEFINITIONS
+//**************************************************************************
+
+DEFINE_DEVICE_TYPE(APRICOT_MONO_DISPLAY, apricot_mono_display_device, "apricot_mono_display", "Apricot Monochrome Display")
+
+//-------------------------------------------------
+// character viewer
+//-------------------------------------------------
+
+static const gfx_layout apricot_charlayout =
+{
+ 10, 16,
+ 1792,
+ 1,
+ { 0 },
+ { 7, 6, 5, 4, 3, 2, 1, 0, 15, 14 },
+ { STEP16(0, 16) },
+ 16*16
+};
+
+static GFXDECODE_START( gfx )
+GFXDECODE_END
+
+//-------------------------------------------------
+// device_add_mconfig - add device configuration
+//-------------------------------------------------
+
+void apricot_mono_display_device::device_add_mconfig(machine_config &config)
+{
+ screen_device &screen(SCREEN(config, "screen", SCREEN_TYPE_RASTER));
+ screen.set_color(rgb_t::green());
+ screen.set_size(800, 400);
+ screen.set_visarea(0, 800-1, 0, 400-1);
+ screen.set_refresh_hz(72);
+ screen.set_screen_update(FUNC(apricot_mono_display_device::screen_update));
+
+ PALETTE(config, m_palette, palette_device::MONOCHROME_HIGHLIGHT);
+
+ HD6845S(config, m_crtc, 24_MHz_XTAL / 10); // actually MB89321B (15 MHz for white monitor, 24 MHz for green)
+ m_crtc->set_screen("screen");
+ m_crtc->set_show_border_area(false);
+ m_crtc->set_char_width(10);
+ m_crtc->set_update_row_callback(FUNC(apricot_mono_display_device::crtc_update_row));
+ m_crtc->out_de_callback().set(FUNC(apricot_mono_display_device::crtc_de_w));
+ m_crtc->out_vsync_callback().set(FUNC(apricot_mono_display_device::crtc_vsync_w));
+
+ GFXDECODE(config, m_gfxdecode, m_palette, gfx);
+}
+
+
+//**************************************************************************
+// LIVE DEVICE
+//**************************************************************************
+
+//-------------------------------------------------
+// apricot_mono_display_device - constructor
+//-------------------------------------------------
+
+apricot_mono_display_device::apricot_mono_display_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) :
+ device_t(mconfig, APRICOT_MONO_DISPLAY, tag, owner, clock),
+ device_apricot_video_interface(mconfig, *this),
+ m_crtc(*this, "crtc"),
+ m_palette(*this, "palette"),
+ m_gfxdecode(*this, "gfxdecode")
+{
+}
+
+//-------------------------------------------------
+// device_start - device-specific startup
+//-------------------------------------------------
+
+void apricot_mono_display_device::device_start()
+{
+ // allocate 64k vram
+ m_vram = std::make_unique<uint16_t[]>(0x8000);
+
+ // init gfxdecode
+ m_gfxdecode->set_gfx(0, std::make_unique<gfx_element>(m_palette, apricot_charlayout, reinterpret_cast<uint8_t *>(m_vram.get()), 0, 1, 0));
+
+ // register for save states
+ save_pointer(NAME(m_vram), 0x8000);
+ save_item(NAME(m_portb));
+ save_item(NAME(m_portc));
+ save_item(NAME(m_portx));
+}
+
+//-------------------------------------------------
+// device_reset - device-specific reset
+//-------------------------------------------------
+
+void apricot_mono_display_device::device_reset()
+{
+ // a reset forces all bits to a logic high
+ m_portb = 0xff;
+ m_portc = 0xff;
+ m_portx = 0xff;
+}
+
+
+//**************************************************************************
+// IMPLEMENTATION
+//**************************************************************************
+
+bool apricot_mono_display_device::mem_r(offs_t offset, uint16_t &data, uint16_t mem_mask)
+{
+ data = m_vram[offset];
+ return true;
+}
+
+bool apricot_mono_display_device::mem_w(offs_t offset, uint16_t data, uint16_t mem_mask)
+{
+ m_vram[offset] = data;
+ return true;
+}
+
+bool apricot_mono_display_device::io_r(offs_t offset, uint16_t &data, uint16_t mem_mask)
+{
+ offset <<= 1;
+
+ if (BIT(m_portx, 0) == 0)
+ {
+ // apricot pc/xi compatible
+ switch (offset)
+ {
+ case 0x4a: data = 0xff00 | m_portb; return true;
+ case 0x4c: data = 0xff00 | m_portc; return true;
+ case 0x6a: data = 0xff00 | m_crtc->register_r(); return true;
+ }
+ }
+ else
+ {
+ // xen mode
+ switch (offset)
+ {
+ case 0x80: data = 0xff00 | m_portb; return true;
+ case 0x82: data = 0xff00 | m_portc; return true;
+ case 0x8a: data = 0xff00 | m_crtc->register_r(); return true;
+ }
+ }
+
+ return false;
+}
+
+bool apricot_mono_display_device::io_w(offs_t offset, uint16_t data, uint16_t mem_mask)
+{
+ offset <<= 1;
+
+ // only 8-bit writes
+ if (mem_mask != 0x00ff)
+ return false;
+
+ if (BIT(m_portx, 0) == 0)
+ {
+ // apricot pc/xi compatible
+ switch (offset)
+ {
+ case 0x4a: portb_w(data); return true;
+ case 0x68: m_crtc->address_w(data); return true;
+ case 0x6a: m_crtc->register_w(data); return true;
+ case 0x6c: portx_w(data); return true;
+ }
+ }
+ else
+ {
+ // xen mode
+ switch (offset)
+ {
+ case 0x6c: portx_w(data); return true;
+ case 0x80: portb_w(data); return true;
+ case 0x88: m_crtc->address_w(data); return true;
+ case 0x8a: m_crtc->register_w(data); return true;
+ }
+ }
+
+ return false;
+}
+
+void apricot_mono_display_device::portb_w(uint8_t data)
+{
+ logerror("portb_w: %02x\n", data);
+
+ // 765----- not used
+ // ---4---- video mode (alphanumeric/graphics)
+ // ----3--- display on
+ // -----21- not used
+ // -------0 crtc reset
+
+ m_portb = data;
+
+ if (BIT(m_portb, 0) == 0)
+ m_crtc->reset();
+}
+
+void apricot_mono_display_device::portx_w(uint8_t data)
+{
+ logerror("portx_w: %02x\n", data);
+
+ // 765432-- not used
+ // ------1- reverse video
+ // -------0 mode (compatible or xen)
+
+ m_portx = data;
+
+ // forward mode to host
+ m_slot->apvid_w(BIT(m_portx, 0));
+}
+
+uint32_t apricot_mono_display_device::screen_update(screen_device &screen, bitmap_rgb32 &bitmap, const rectangle &cliprect)
+{
+ m_gfxdecode->gfx(0)->mark_all_dirty();
+ m_crtc->screen_update(screen, bitmap, cliprect);
+ return 0;
+}
+
+// see drivers/apricot.cpp
+MC6845_UPDATE_ROW( apricot_mono_display_device::crtc_update_row )
+{
+ const pen_t *pen = m_palette->pens();
+
+ for (int i = 0; i < x_count; i++)
+ {
+ uint16_t code = m_vram[(0xe000 >> 1) | (ma + i)];
+ uint16_t offset = ((code & 0x7ff) << 5) | (ra << 1);
+ uint16_t data = m_vram[offset >> 1];
+
+ if (BIT(m_portb, 4))
+ {
+ int fill = 0;
+
+ if (i == cursor_x) fill = 1; // cursor?
+ if (BIT(code, 12) && BIT(data, 14)) fill = 1; // strike-through?
+ if (BIT(code, 13) && BIT(data, 15)) fill = 1; // underline?
+
+ // draw 10 pixels of the character
+ for (int x = 0; x <= 10; x++)
+ {
+ int color = fill ? 1 : BIT(data, x);
+ color ^= BIT(code, 15); // reverse?
+ bitmap.pix(y, x + i*10) = pen[color ? 1 + BIT(code, 14) : 0];
+ }
+ }
+ else
+ {
+ // draw 16 pixels of the cell
+ for (int x = 0; x <= 16; x++)
+ bitmap.pix(y, x + i*16) = pen[BIT(data, x)];
+ }
+ }
+}
+
+void apricot_mono_display_device::crtc_de_w(int state)
+{
+ m_portc &= 0xf7;
+ m_portc |= (state << 3);
+}
+
+void apricot_mono_display_device::crtc_vsync_w(int state)
+{
+ m_portc &= 0x7f;
+ m_portc |= (state << 7);
+}
diff --git a/src/devices/bus/apricot/video/mono.h b/src/devices/bus/apricot/video/mono.h
new file mode 100644
index 00000000000..6ce27dd82c5
--- /dev/null
+++ b/src/devices/bus/apricot/video/mono.h
@@ -0,0 +1,65 @@
+// license: GPL-2.0+
+// copyright-holders: Dirk Best
+/***************************************************************************
+
+ ACT Apricot XEN Monochrome Display Option
+
+***************************************************************************/
+
+#ifndef MAME_BUS_APRICOT_VIDEO_MONO_H
+#define MAME_BUS_APRICOT_VIDEO_MONO_H
+
+#pragma once
+
+#include "video.h"
+#include "video/mc6845.h"
+#include "emupal.h"
+
+
+//**************************************************************************
+// TYPE DEFINITIONS
+//**************************************************************************
+
+// ======================> apricot_mono_display_device
+
+class apricot_mono_display_device : public device_t, public device_apricot_video_interface
+{
+public:
+ // construction/destruction
+ apricot_mono_display_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
+
+protected:
+ // device-level overrides
+ 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;
+
+ virtual bool mem_r(offs_t offset, uint16_t &data, uint16_t mem_mask) override;
+ virtual bool mem_w(offs_t offset, uint16_t data, uint16_t mem_mask) override;
+ virtual bool io_r(offs_t offset, uint16_t &data, uint16_t mem_mask) override;
+ virtual bool io_w(offs_t offset, uint16_t data, uint16_t mem_mask) override;
+
+private:
+ required_device<hd6845s_device> m_crtc;
+ required_device<palette_device> m_palette;
+ required_device<gfxdecode_device> m_gfxdecode;
+
+ void portb_w(uint8_t data);
+ void portx_w(uint8_t data);
+
+ uint32_t screen_update(screen_device &screen, bitmap_rgb32 &bitmap, const rectangle &cliprect);
+ MC6845_UPDATE_ROW(crtc_update_row);
+ void crtc_de_w(int state);
+ void crtc_vsync_w(int state);
+
+ std::unique_ptr<uint16_t[]> m_vram;
+
+ uint8_t m_portb;
+ uint8_t m_portc;
+ uint8_t m_portx;
+};
+
+// device type definition
+DECLARE_DEVICE_TYPE(APRICOT_MONO_DISPLAY, apricot_mono_display_device)
+
+#endif // MAME_BUS_APRICOT_VIDEO_MONO_H
diff --git a/src/devices/bus/apricot/video/video.cpp b/src/devices/bus/apricot/video/video.cpp
new file mode 100644
index 00000000000..8543ff4d571
--- /dev/null
+++ b/src/devices/bus/apricot/video/video.cpp
@@ -0,0 +1,111 @@
+// license: GPL-2.0+
+// copyright-holders: Dirk Best
+/***************************************************************************
+
+ ACT Apricot XEN Video Expansion Slot
+
+***************************************************************************/
+
+#include "emu.h"
+#include "video.h"
+
+
+//**************************************************************************
+// DEVICE DEFINITIONS
+//**************************************************************************
+
+DEFINE_DEVICE_TYPE(APRICOT_VIDEO_SLOT, apricot_video_slot_device, "apricot_video", "Apricot XEN Video Slot")
+
+
+//**************************************************************************
+// SLOT DEVICE
+//**************************************************************************
+
+//-------------------------------------------------
+// apricot_video_slot_device - constructor
+//-------------------------------------------------
+
+apricot_video_slot_device::apricot_video_slot_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) :
+ device_t(mconfig, APRICOT_VIDEO_SLOT, tag, owner, clock),
+ device_single_card_slot_interface<device_apricot_video_interface>(mconfig, *this),
+ m_apvid_handler(*this),
+ m_card(nullptr)
+{
+}
+
+//-------------------------------------------------
+// apricot_video_slot_device - destructor
+//-------------------------------------------------
+
+apricot_video_slot_device::~apricot_video_slot_device()
+{
+}
+
+//-------------------------------------------------
+// device_start - device-specific startup
+//-------------------------------------------------
+
+void apricot_video_slot_device::device_start()
+{
+ // get inserted module
+ m_card = get_card_device();
+}
+
+//-------------------------------------------------
+// host to module interface
+//-------------------------------------------------
+
+bool apricot_video_slot_device::mem_r(offs_t offset, uint16_t &data, uint16_t mem_mask)
+{
+ if (m_card)
+ return m_card->mem_r(offset, data, mem_mask);
+
+ return false;
+}
+
+bool apricot_video_slot_device::mem_w(offs_t offset, uint16_t data, uint16_t mem_mask)
+{
+ if (m_card)
+ return m_card->mem_w(offset, data, mem_mask);
+
+ return false;
+}
+
+bool apricot_video_slot_device::io_r(offs_t offset, uint16_t &data, uint16_t mem_mask)
+{
+ if (m_card)
+ return m_card->io_r(offset, data, mem_mask);
+
+ return false;
+}
+
+bool apricot_video_slot_device::io_w(offs_t offset, uint16_t data, uint16_t mem_mask)
+{
+ if (m_card)
+ return m_card->io_w(offset, data, mem_mask);
+
+ return false;
+}
+
+
+//**************************************************************************
+// MODULE INTERFACE
+//**************************************************************************
+
+//-------------------------------------------------
+// device_apricot_video_interface - constructor
+//-------------------------------------------------
+
+device_apricot_video_interface::device_apricot_video_interface(const machine_config &mconfig, device_t &device) :
+ device_interface(device, "apricotvid")
+{
+ m_slot = dynamic_cast<apricot_video_slot_device *>(device.owner());
+}
+
+//-------------------------------------------------
+// ~device_apricot_video_interface - destructor
+//-------------------------------------------------
+
+device_apricot_video_interface::~device_apricot_video_interface()
+{
+}
diff --git a/src/devices/bus/apricot/video/video.h b/src/devices/bus/apricot/video/video.h
new file mode 100644
index 00000000000..885bef8fc9a
--- /dev/null
+++ b/src/devices/bus/apricot/video/video.h
@@ -0,0 +1,89 @@
+// license: GPL-2.0+
+// copyright-holders: Dirk Best
+/***************************************************************************
+
+ ACT Apricot XEN Video Expansion Slot
+
+ Large identical to the standard Apricot PC/Xi expansion slot.
+
+***************************************************************************/
+
+#ifndef MAME_BUS_APRICOT_VIDEO_VIDEO_H
+#define MAME_BUS_APRICOT_VIDEO_VIDEO_H
+
+#pragma once
+
+
+//**************************************************************************
+// TYPE DEFINITIONS
+//**************************************************************************
+
+class device_apricot_video_interface;
+
+// ======================> apricot_video_slot_device
+
+class apricot_video_slot_device : public device_t, public device_single_card_slot_interface<device_apricot_video_interface>
+{
+public:
+ // construction/destruction
+ template <typename T>
+ apricot_video_slot_device(machine_config const &mconfig, char const *tag, device_t *owner, T &&opts, const char *dflt)
+ : apricot_video_slot_device(mconfig, tag, owner, uint32_t(0))
+ {
+ option_reset();
+ opts(*this);
+ set_default_option(dflt);
+ set_fixed(false);
+ }
+
+ apricot_video_slot_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
+ virtual ~apricot_video_slot_device();
+
+ // callbacks
+ auto apvid_handler() { return m_apvid_handler.bind(); }
+
+ // called from cart device
+ 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);
+ bool mem_w(offs_t offset, uint16_t data, uint16_t mem_mask);
+ bool io_r(offs_t offset, uint16_t &data, uint16_t mem_mask);
+ bool io_w(offs_t offset, uint16_t data, uint16_t mem_mask);
+
+protected:
+ // device-level overrides
+ virtual void device_start() override ATTR_COLD;
+
+private:
+ devcb_write_line m_apvid_handler;
+
+ device_apricot_video_interface *m_card;
+};
+
+// ======================> device_apricot_video_interface
+
+class device_apricot_video_interface : public device_interface
+{
+public:
+ // construction/destruction
+ virtual ~device_apricot_video_interface();
+
+ virtual bool mem_r(offs_t offset, uint16_t &data, uint16_t mem_mask) { return false; }
+ virtual bool mem_w(offs_t offset, uint16_t data, uint16_t mem_mask) { return false; }
+ virtual bool io_r(offs_t offset, uint16_t &data, uint16_t mem_mask) { return false; }
+ virtual bool io_w(offs_t offset, uint16_t data, uint16_t mem_mask) { return false; }
+
+protected:
+ device_apricot_video_interface(const machine_config &mconfig, device_t &device);
+
+ apricot_video_slot_device *m_slot;
+};
+
+// device type definition
+DECLARE_DEVICE_TYPE(APRICOT_VIDEO_SLOT, apricot_video_slot_device)
+
+// include here so drivers don't need to
+#include "cards.h"
+
+#endif // MAME_BUS_APRICOT_VIDEO_VIDEO_H
diff --git a/src/devices/bus/aquarius/c1541.cpp b/src/devices/bus/aquarius/c1541.cpp
new file mode 100644
index 00000000000..40ac2679422
--- /dev/null
+++ b/src/devices/bus/aquarius/c1541.cpp
@@ -0,0 +1,92 @@
+// license:BSD-3-Clause
+// copyright-holders:Nigel Barnes
+/**********************************************************************
+
+ Aquarius C1541 DOS Interface by Ron Koenig
+
+**********************************************************************/
+
+
+#include "emu.h"
+#include "c1541.h"
+
+
+//**************************************************************************
+// DEVICE DEFINITIONS
+//**************************************************************************
+
+DEFINE_DEVICE_TYPE(AQUARIUS_C1541, aquarius_c1541_device, "aquarius_c1541", "Aquarius C1541 DOS Interface")
+
+
+//-------------------------------------------------
+// device_add_mconfig - add device configuration
+//-------------------------------------------------
+
+void aquarius_c1541_device::device_add_mconfig(machine_config &config)
+{
+ cbm_iec_slot_device::add(config, m_iec, "c1541");
+}
+
+
+//**************************************************************************
+// LIVE DEVICE
+//**************************************************************************
+
+//-------------------------------------------------
+// aquarius_c1541_device - constructor
+//-------------------------------------------------
+
+aquarius_c1541_device::aquarius_c1541_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
+ : device_t(mconfig, AQUARIUS_C1541, tag, owner, clock)
+ , device_aquarius_cartridge_interface(mconfig, *this)
+ , m_iec(*this, "iec_bus")
+{
+}
+
+
+//-------------------------------------------------
+// device_start - device-specific startup
+//-------------------------------------------------
+
+void aquarius_c1541_device::device_start()
+{
+}
+
+
+//**************************************************************************
+// IMPLEMENTATION
+//**************************************************************************
+
+uint8_t aquarius_c1541_device::mreq_ce_r(offs_t offset)
+{
+ return get_rom_base()[offset & 0x3fff];
+}
+
+
+uint8_t aquarius_c1541_device::iorq_r(offs_t offset)
+{
+ uint8_t data = 0xff;
+
+ if (offset == 0x60)
+ {
+ // TODO: unknown connections
+ data = 0x00;
+ data |= m_iec->clk_r() << 7;
+ data |= m_iec->data_r() << 3;
+ logerror("iorq_r: %02x = %02x\n", offset, data);
+ }
+
+ return data;
+}
+
+void aquarius_c1541_device::iorq_w(offs_t offset, uint8_t data)
+{
+ if (offset == 0x60)
+ {
+ logerror("iorq_w: %02x = %02x\n", offset, data);
+ // TODO: unknown connections
+ m_iec->host_atn_w(BIT(data, 6));
+ m_iec->host_clk_w(BIT(data, 5));
+ m_iec->host_data_w(BIT(data, 4));
+ }
+}
diff --git a/src/devices/bus/aquarius/c1541.h b/src/devices/bus/aquarius/c1541.h
new file mode 100644
index 00000000000..0cfc58bd719
--- /dev/null
+++ b/src/devices/bus/aquarius/c1541.h
@@ -0,0 +1,53 @@
+// license:BSD-3-Clause
+// copyright-holders:Nigel Barnes
+/**********************************************************************
+
+ Aquarius C1541 DOS Interface by Ron Koenig
+
+**********************************************************************/
+
+#ifndef MAME_BUS_AQUARIUS_C1541_H
+#define MAME_BUS_AQUARIUS_C1541_H
+
+#pragma once
+
+#include "slot.h"
+#include "bus/cbmiec/cbmiec.h"
+
+
+//**************************************************************************
+// TYPE DEFINITIONS
+//**************************************************************************
+
+class aquarius_c1541_device :
+ public device_t,
+ public device_aquarius_cartridge_interface
+{
+public:
+ // construction/destruction
+ aquarius_c1541_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 ATTR_COLD;
+
+ // optional information overrides
+ virtual void device_add_mconfig(machine_config &config) override ATTR_COLD;
+
+ // device_aquarius_cartridge_interface overrides
+ virtual uint8_t mreq_ce_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;
+
+private:
+ required_device<cbm_iec_device> m_iec;
+};
+
+
+// device type definition
+DECLARE_DEVICE_TYPE(AQUARIUS_C1541, aquarius_c1541_device)
+
+
+#endif // MAME_BUS_AQUARIUS_C1541_H
diff --git a/src/devices/bus/aquarius/mini.cpp b/src/devices/bus/aquarius/mini.cpp
new file mode 100644
index 00000000000..7baff17fba2
--- /dev/null
+++ b/src/devices/bus/aquarius/mini.cpp
@@ -0,0 +1,221 @@
+// license:BSD-3-Clause
+// copyright-holders:Nigel Barnes
+/**********************************************************************
+
+ Aquarius Mini Expander
+
+**********************************************************************/
+
+
+#include "emu.h"
+#include "mini.h"
+#include "speaker.h"
+
+
+//**************************************************************************
+// DEVICE DEFINITIONS
+//**************************************************************************
+
+DEFINE_DEVICE_TYPE(AQUARIUS_MINI, aquarius_mini_device, "aquarius_mini", "Aquarius Mini Expander")
+
+
+//-------------------------------------------------
+// INPUT_PORTS( mini )
+//-------------------------------------------------
+
+static INPUT_PORTS_START(mini)
+ PORT_START("RIGHT")
+ PORT_BIT( 0x001000, IP_ACTIVE_HIGH, IPT_JOYSTICKRIGHT_UP ) PORT_PLAYER(1) PORT_NAME("P1 12:00 (Up)") PORT_16WAY PORT_CHANGED_MEMBER(DEVICE_SELF, FUNC(aquarius_mini_device::input_changed), 0x1fb)
+ PORT_BIT( 0x002000, IP_ACTIVE_HIGH, IPT_JOYSTICKRIGHT_UP ) PORT_PLAYER(1) PORT_NAME("P1 01:00") PORT_16WAY PORT_CHANGED_MEMBER(DEVICE_SELF, FUNC(aquarius_mini_device::input_changed), 0x1eb)
+ PORT_BIT( 0x004000, IP_ACTIVE_HIGH, IPT_JOYSTICKRIGHT_RIGHT ) PORT_PLAYER(1) PORT_NAME("P1 01:30") PORT_16WAY PORT_CHANGED_MEMBER(DEVICE_SELF, FUNC(aquarius_mini_device::input_changed), 0x1e9)
+ PORT_BIT( 0x008000, IP_ACTIVE_HIGH, IPT_JOYSTICKRIGHT_RIGHT ) PORT_PLAYER(1) PORT_NAME("P1 02:00") PORT_16WAY PORT_CHANGED_MEMBER(DEVICE_SELF, FUNC(aquarius_mini_device::input_changed), 0x1f9)
+ PORT_BIT( 0x000001, IP_ACTIVE_HIGH, IPT_JOYSTICKRIGHT_RIGHT ) PORT_PLAYER(1) PORT_NAME("P1 03:00 (Right)") PORT_16WAY PORT_CHANGED_MEMBER(DEVICE_SELF, FUNC(aquarius_mini_device::input_changed), 0x1fd)
+ PORT_BIT( 0x000002, IP_ACTIVE_HIGH, IPT_JOYSTICKRIGHT_RIGHT ) PORT_PLAYER(1) PORT_NAME("P1 04:00") PORT_16WAY PORT_CHANGED_MEMBER(DEVICE_SELF, FUNC(aquarius_mini_device::input_changed), 0x1ed)
+ PORT_BIT( 0x000004, IP_ACTIVE_HIGH, IPT_JOYSTICKRIGHT_DOWN ) PORT_PLAYER(1) PORT_NAME("P1 04:30") PORT_16WAY PORT_CHANGED_MEMBER(DEVICE_SELF, FUNC(aquarius_mini_device::input_changed), 0x1ec)
+ PORT_BIT( 0x000008, IP_ACTIVE_HIGH, IPT_JOYSTICKRIGHT_DOWN ) PORT_PLAYER(1) PORT_NAME("P1 05:00") PORT_16WAY PORT_CHANGED_MEMBER(DEVICE_SELF, FUNC(aquarius_mini_device::input_changed), 0x1fc)
+ PORT_BIT( 0x000010, IP_ACTIVE_HIGH, IPT_JOYSTICKRIGHT_DOWN ) PORT_PLAYER(1) PORT_NAME("P1 06:00 (Down)") PORT_16WAY PORT_CHANGED_MEMBER(DEVICE_SELF, FUNC(aquarius_mini_device::input_changed), 0x1fe)
+ PORT_BIT( 0x000020, IP_ACTIVE_HIGH, IPT_JOYSTICKRIGHT_DOWN ) PORT_PLAYER(1) PORT_NAME("P1 06:30") PORT_16WAY PORT_CHANGED_MEMBER(DEVICE_SELF, FUNC(aquarius_mini_device::input_changed), 0x1ee)
+ PORT_BIT( 0x000040, IP_ACTIVE_HIGH, IPT_JOYSTICKRIGHT_LEFT ) PORT_PLAYER(1) PORT_NAME("P1 07:00") PORT_16WAY PORT_CHANGED_MEMBER(DEVICE_SELF, FUNC(aquarius_mini_device::input_changed), 0x1e6)
+ PORT_BIT( 0x000080, IP_ACTIVE_HIGH, IPT_JOYSTICKRIGHT_LEFT ) PORT_PLAYER(1) PORT_NAME("P1 08:00") PORT_16WAY PORT_CHANGED_MEMBER(DEVICE_SELF, FUNC(aquarius_mini_device::input_changed), 0x1f6)
+ PORT_BIT( 0x000100, IP_ACTIVE_HIGH, IPT_JOYSTICKRIGHT_LEFT ) PORT_PLAYER(1) PORT_NAME("P1 09:00 (Left)") PORT_16WAY PORT_CHANGED_MEMBER(DEVICE_SELF, FUNC(aquarius_mini_device::input_changed), 0x1f7)
+ PORT_BIT( 0x000200, IP_ACTIVE_HIGH, IPT_JOYSTICKRIGHT_LEFT ) PORT_PLAYER(1) PORT_NAME("P1 09:30") PORT_16WAY PORT_CHANGED_MEMBER(DEVICE_SELF, FUNC(aquarius_mini_device::input_changed), 0x1e7)
+ PORT_BIT( 0x000400, IP_ACTIVE_HIGH, IPT_JOYSTICKRIGHT_UP ) PORT_PLAYER(1) PORT_NAME("P1 10:00") PORT_16WAY PORT_CHANGED_MEMBER(DEVICE_SELF, FUNC(aquarius_mini_device::input_changed), 0x1e3)
+ PORT_BIT( 0x000800, IP_ACTIVE_HIGH, IPT_JOYSTICKRIGHT_UP ) PORT_PLAYER(1) PORT_NAME("P1 11:00") PORT_16WAY PORT_CHANGED_MEMBER(DEVICE_SELF, FUNC(aquarius_mini_device::input_changed), 0x1f3)
+ PORT_BIT( 0x010000, IP_ACTIVE_HIGH, IPT_BUTTON1 ) PORT_PLAYER(1) PORT_CHANGED_MEMBER(DEVICE_SELF, FUNC(aquarius_mini_device::input_changed), 0x1bf)
+ PORT_BIT( 0x020000, IP_ACTIVE_HIGH, IPT_BUTTON2 ) PORT_PLAYER(1) PORT_CHANGED_MEMBER(DEVICE_SELF, FUNC(aquarius_mini_device::input_changed), 0x17b)
+ PORT_BIT( 0x040000, IP_ACTIVE_HIGH, IPT_BUTTON3 ) PORT_PLAYER(1) PORT_CHANGED_MEMBER(DEVICE_SELF, FUNC(aquarius_mini_device::input_changed), 0x15f)
+ PORT_BIT( 0x080000, IP_ACTIVE_HIGH, IPT_BUTTON4 ) PORT_PLAYER(1) PORT_CHANGED_MEMBER(DEVICE_SELF, FUNC(aquarius_mini_device::input_changed), 0x1df)
+ PORT_BIT( 0x100000, IP_ACTIVE_HIGH, IPT_BUTTON5 ) PORT_PLAYER(1) PORT_CHANGED_MEMBER(DEVICE_SELF, FUNC(aquarius_mini_device::input_changed), 0x17d)
+ PORT_BIT( 0x200000, IP_ACTIVE_HIGH, IPT_BUTTON6 ) PORT_PLAYER(1) PORT_CHANGED_MEMBER(DEVICE_SELF, FUNC(aquarius_mini_device::input_changed), 0x17e)
+
+ PORT_START("LEFT")
+ PORT_BIT( 0x001000, IP_ACTIVE_HIGH, IPT_JOYSTICKLEFT_UP ) PORT_PLAYER(2) PORT_NAME("P2 12:00 (Up)") PORT_16WAY PORT_CHANGED_MEMBER(DEVICE_SELF, FUNC(aquarius_mini_device::input_changed), 0x0fb)
+ PORT_BIT( 0x002000, IP_ACTIVE_HIGH, IPT_JOYSTICKLEFT_UP ) PORT_PLAYER(2) PORT_NAME("P2 01:00") PORT_16WAY PORT_CHANGED_MEMBER(DEVICE_SELF, FUNC(aquarius_mini_device::input_changed), 0x0eb)
+ PORT_BIT( 0x004000, IP_ACTIVE_HIGH, IPT_JOYSTICKLEFT_RIGHT ) PORT_PLAYER(2) PORT_NAME("P2 01:30") PORT_16WAY PORT_CHANGED_MEMBER(DEVICE_SELF, FUNC(aquarius_mini_device::input_changed), 0x0e9)
+ PORT_BIT( 0x008000, IP_ACTIVE_HIGH, IPT_JOYSTICKLEFT_RIGHT ) PORT_PLAYER(2) PORT_NAME("P2 02:00") PORT_16WAY PORT_CHANGED_MEMBER(DEVICE_SELF, FUNC(aquarius_mini_device::input_changed), 0x0f9)
+ PORT_BIT( 0x000001, IP_ACTIVE_HIGH, IPT_JOYSTICKLEFT_RIGHT ) PORT_PLAYER(2) PORT_NAME("P2 03:00 (Right)") PORT_16WAY PORT_CHANGED_MEMBER(DEVICE_SELF, FUNC(aquarius_mini_device::input_changed), 0x0fd)
+ PORT_BIT( 0x000002, IP_ACTIVE_HIGH, IPT_JOYSTICKLEFT_RIGHT ) PORT_PLAYER(2) PORT_NAME("P2 04:00") PORT_16WAY PORT_CHANGED_MEMBER(DEVICE_SELF, FUNC(aquarius_mini_device::input_changed), 0x0ed)
+ PORT_BIT( 0x000004, IP_ACTIVE_HIGH, IPT_JOYSTICKLEFT_DOWN ) PORT_PLAYER(2) PORT_NAME("P2 04:30") PORT_16WAY PORT_CHANGED_MEMBER(DEVICE_SELF, FUNC(aquarius_mini_device::input_changed), 0x0ec)
+ PORT_BIT( 0x000008, IP_ACTIVE_HIGH, IPT_JOYSTICKLEFT_DOWN ) PORT_PLAYER(2) PORT_NAME("P2 05:00") PORT_16WAY PORT_CHANGED_MEMBER(DEVICE_SELF, FUNC(aquarius_mini_device::input_changed), 0x0fc)
+ PORT_BIT( 0x000010, IP_ACTIVE_HIGH, IPT_JOYSTICKLEFT_DOWN ) PORT_PLAYER(2) PORT_NAME("P2 06:00 (Down)") PORT_16WAY PORT_CHANGED_MEMBER(DEVICE_SELF, FUNC(aquarius_mini_device::input_changed), 0x0fe)
+ PORT_BIT( 0x000020, IP_ACTIVE_HIGH, IPT_JOYSTICKLEFT_DOWN ) PORT_PLAYER(2) PORT_NAME("P2 06:30") PORT_16WAY PORT_CHANGED_MEMBER(DEVICE_SELF, FUNC(aquarius_mini_device::input_changed), 0x0ee)
+ PORT_BIT( 0x000040, IP_ACTIVE_HIGH, IPT_JOYSTICKLEFT_LEFT ) PORT_PLAYER(2) PORT_NAME("P2 07:00") PORT_16WAY PORT_CHANGED_MEMBER(DEVICE_SELF, FUNC(aquarius_mini_device::input_changed), 0x0e6)
+ PORT_BIT( 0x000080, IP_ACTIVE_HIGH, IPT_JOYSTICKLEFT_LEFT ) PORT_PLAYER(2) PORT_NAME("P2 08:00") PORT_16WAY PORT_CHANGED_MEMBER(DEVICE_SELF, FUNC(aquarius_mini_device::input_changed), 0x0f6)
+ PORT_BIT( 0x000100, IP_ACTIVE_HIGH, IPT_JOYSTICKLEFT_LEFT ) PORT_PLAYER(2) PORT_NAME("P2 09:00 (Left)") PORT_16WAY PORT_CHANGED_MEMBER(DEVICE_SELF, FUNC(aquarius_mini_device::input_changed), 0x0f7)
+ PORT_BIT( 0x000200, IP_ACTIVE_HIGH, IPT_JOYSTICKLEFT_LEFT ) PORT_PLAYER(2) PORT_NAME("P2 09:30") PORT_16WAY PORT_CHANGED_MEMBER(DEVICE_SELF, FUNC(aquarius_mini_device::input_changed), 0x0e7)
+ PORT_BIT( 0x000400, IP_ACTIVE_HIGH, IPT_JOYSTICKLEFT_UP ) PORT_PLAYER(2) PORT_NAME("P2 10:00") PORT_16WAY PORT_CHANGED_MEMBER(DEVICE_SELF, FUNC(aquarius_mini_device::input_changed), 0x0e3)
+ PORT_BIT( 0x000800, IP_ACTIVE_HIGH, IPT_JOYSTICKLEFT_UP ) PORT_PLAYER(2) PORT_NAME("P2 11:00") PORT_16WAY PORT_CHANGED_MEMBER(DEVICE_SELF, FUNC(aquarius_mini_device::input_changed), 0x0f3)
+ PORT_BIT( 0x010000, IP_ACTIVE_HIGH, IPT_BUTTON1 ) PORT_PLAYER(2) PORT_CHANGED_MEMBER(DEVICE_SELF, FUNC(aquarius_mini_device::input_changed), 0x0bf)
+ PORT_BIT( 0x020000, IP_ACTIVE_HIGH, IPT_BUTTON2 ) PORT_PLAYER(2) PORT_CHANGED_MEMBER(DEVICE_SELF, FUNC(aquarius_mini_device::input_changed), 0x07b)
+ PORT_BIT( 0x040000, IP_ACTIVE_HIGH, IPT_BUTTON3 ) PORT_PLAYER(2) PORT_CHANGED_MEMBER(DEVICE_SELF, FUNC(aquarius_mini_device::input_changed), 0x05f)
+ PORT_BIT( 0x080000, IP_ACTIVE_HIGH, IPT_BUTTON4 ) PORT_PLAYER(2) PORT_CHANGED_MEMBER(DEVICE_SELF, FUNC(aquarius_mini_device::input_changed), 0x0df)
+ PORT_BIT( 0x100000, IP_ACTIVE_HIGH, IPT_BUTTON5 ) PORT_PLAYER(2) PORT_CHANGED_MEMBER(DEVICE_SELF, FUNC(aquarius_mini_device::input_changed), 0x07d)
+ PORT_BIT( 0x200000, IP_ACTIVE_HIGH, IPT_BUTTON6 ) PORT_PLAYER(2) PORT_CHANGED_MEMBER(DEVICE_SELF, FUNC(aquarius_mini_device::input_changed), 0x07e)
+INPUT_PORTS_END
+
+//-------------------------------------------------
+// input_ports - device-specific input ports
+//-------------------------------------------------
+
+ioport_constructor aquarius_mini_device::device_input_ports() const
+{
+ return INPUT_PORTS_NAME(mini);
+}
+
+//-------------------------------------------------
+// device_add_mconfig - add device configuration
+//-------------------------------------------------
+
+void aquarius_mini_device::device_add_mconfig(machine_config &config)
+{
+ INPUT_MERGER_ANY_HIGH(config, m_irqs).output_handler().set(DEVICE_SELF_OWNER, FUNC(aquarius_cartridge_slot_device::irq_w));
+
+ /* sound hardware */
+ SPEAKER(config, "mono").front_center();
+
+ AY8910(config, m_ay, DERIVED_CLOCK(1, 2));
+ m_ay->port_a_read_callback().set([this] () { return m_ctrl_input[0]; });
+ m_ay->port_b_read_callback().set([this] () { return m_ctrl_input[1]; });
+ m_ay->add_route(ALL_OUTPUTS, "mono", 0.25);
+
+ /* cartridge */
+ AQUARIUS_CARTRIDGE_SLOT(config, m_exp[0], DERIVED_CLOCK(1,1), aquarius_cartridge_devices, nullptr);
+ m_exp[0]->irq_handler().set(m_irqs, FUNC(input_merger_device::in_w<0>));
+ m_exp[0]->nmi_handler().set(DEVICE_SELF_OWNER, FUNC(aquarius_cartridge_slot_device::nmi_w));
+
+ AQUARIUS_CARTRIDGE_SLOT(config, m_exp[1], DERIVED_CLOCK(1,1), aquarius_cartridge_devices, nullptr);
+ m_exp[1]->irq_handler().set(m_irqs, FUNC(input_merger_device::in_w<1>));
+ m_exp[1]->nmi_handler().set(DEVICE_SELF_OWNER, FUNC(aquarius_cartridge_slot_device::nmi_w));
+}
+
+
+//**************************************************************************
+// LIVE DEVICE
+//**************************************************************************
+
+//-------------------------------------------------
+// aquarius_mini_device - constructor
+//-------------------------------------------------
+
+aquarius_mini_device::aquarius_mini_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
+ : device_t(mconfig, AQUARIUS_MINI, tag, owner, clock)
+ , device_aquarius_cartridge_interface(mconfig, *this)
+ , m_irqs(*this, "irqs")
+ , m_exp(*this, "exp%u", 1U)
+ , m_ay(*this, "ay8910")
+{
+}
+
+//-------------------------------------------------
+// device_start - device-specific startup
+//-------------------------------------------------
+
+void aquarius_mini_device::device_start()
+{
+ m_ctrl_input[0] = 0xff;
+ m_ctrl_input[1] = 0xff;
+
+ save_item(NAME(m_ctrl_input));
+}
+
+
+//**************************************************************************
+// IMPLEMENTATION
+//**************************************************************************
+
+INPUT_CHANGED_MEMBER(aquarius_mini_device::input_changed)
+{
+ if (newval)
+ m_ctrl_input[BIT(param, 8)] &= param;
+ else
+ m_ctrl_input[BIT(param, 8)] |= ~param;
+}
+
+uint8_t aquarius_mini_device::mreq_r(offs_t offset)
+{
+ uint8_t data = 0xff;
+
+ data &= m_exp[0]->mreq_r(offset);
+ data &= m_exp[1]->mreq_r(offset);
+
+ return data;
+}
+
+void aquarius_mini_device::mreq_w(offs_t offset, uint8_t data)
+{
+ m_exp[0]->mreq_w(offset, data);
+ m_exp[1]->mreq_w(offset, data);
+}
+
+
+uint8_t aquarius_mini_device::mreq_ce_r(offs_t offset)
+{
+ uint8_t data = 0xff;
+
+ data &= m_exp[0]->mreq_ce_r(offset);
+ data &= m_exp[1]->mreq_ce_r(offset);
+
+ return data;
+}
+
+void aquarius_mini_device::mreq_ce_w(offs_t offset, uint8_t data)
+{
+ m_exp[0]->mreq_ce_w(offset, data);
+ m_exp[1]->mreq_ce_w(offset, data);
+}
+
+
+uint8_t aquarius_mini_device::iorq_r(offs_t offset)
+{
+ uint8_t data = 0xff;
+
+ switch (offset & 0xff)
+ {
+ case 0xf6:
+ data &= m_ay->data_r();
+ break;
+ case 0xf7:
+ break;
+ }
+
+ data &= m_exp[0]->iorq_r(offset);
+ data &= m_exp[1]->iorq_r(offset);
+
+ return data;
+}
+
+void aquarius_mini_device::iorq_w(offs_t offset, uint8_t data)
+{
+ switch (offset & 0xff)
+ {
+ case 0xf6:
+ m_ay->data_w(data);
+ break;
+ case 0xf7:
+ m_ay->address_w(data);
+ break;
+ }
+
+ m_exp[0]->iorq_w(offset, data);
+ m_exp[1]->iorq_w(offset, data);
+}
diff --git a/src/devices/bus/aquarius/mini.h b/src/devices/bus/aquarius/mini.h
new file mode 100644
index 00000000000..c2a533318fb
--- /dev/null
+++ b/src/devices/bus/aquarius/mini.h
@@ -0,0 +1,59 @@
+// license:BSD-3-Clause
+// copyright-holders:Nigel Barnes
+/**********************************************************************
+
+ Aquarius Mini Expander
+
+**********************************************************************/
+
+
+#ifndef MAME_BUS_AQUARIUS_MINI_H
+#define MAME_BUS_AQUARIUS_MINI_H
+
+#include "slot.h"
+#include "machine/input_merger.h"
+#include "sound/ay8910.h"
+
+//**************************************************************************
+// TYPE DEFINITIONS
+//**************************************************************************
+
+class aquarius_mini_device:
+ public device_t,
+ public device_aquarius_cartridge_interface
+{
+public:
+ // construction/destruction
+ aquarius_mini_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
+
+ DECLARE_INPUT_CHANGED_MEMBER(input_changed);
+
+protected:
+ virtual void device_start() override ATTR_COLD;
+
+ // optional information overrides
+ virtual void device_add_mconfig(machine_config &config) override ATTR_COLD;
+ virtual ioport_constructor device_input_ports() const override ATTR_COLD;
+
+ // device_aquarius_cartridge_interface overrides
+ virtual uint8_t mreq_r(offs_t offset) override;
+ virtual void mreq_w(offs_t offset, uint8_t data) override;
+ virtual uint8_t mreq_ce_r(offs_t offset) override;
+ virtual void mreq_ce_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;
+
+private:
+ required_device<input_merger_device> m_irqs;
+ required_device_array<aquarius_cartridge_slot_device, 2> m_exp;
+ required_device<ay8910_device> m_ay;
+
+ uint8_t m_ctrl_input[2];
+};
+
+
+// device type definition
+DECLARE_DEVICE_TYPE(AQUARIUS_MINI, aquarius_mini_device)
+
+
+#endif /* MAME_BUS_AQUARIUS_MINI_H */
diff --git a/src/devices/bus/aquarius/qdisk.cpp b/src/devices/bus/aquarius/qdisk.cpp
new file mode 100644
index 00000000000..ba06201f554
--- /dev/null
+++ b/src/devices/bus/aquarius/qdisk.cpp
@@ -0,0 +1,164 @@
+// license:BSD-3-Clause
+// copyright-holders:Nigel Barnes
+/**********************************************************************
+
+ Radofin Aquarius Quick Disk
+
+ Specifications:
+ Capacity 64K byte per side
+ Read/Write time 64K/8sec
+ Transmitting speed 101K [BPS]
+ Recording density 4410 [BPI]
+ Track density 59 [TPI]
+ Number of track 1 (spiral)
+ Recoding system MFM
+ Rotation speed 423 [RPM]
+ Disk 2.8"
+ Number of heads 1
+
+ TODO:
+
+ - floppy support (I/O 0xe6-0xe7 = drive 1, 0xea-0xeb = drive 2)
+
+**********************************************************************/
+
+
+#include "emu.h"
+#include "qdisk.h"
+
+
+//**************************************************************************
+// DEVICE DEFINITIONS
+//**************************************************************************
+
+DEFINE_DEVICE_TYPE(AQUARIUS_QDISK, aquarius_qdisk_device, "aquarius_qdisk", "Aquarius Quick Disk")
+
+
+//-------------------------------------------------
+// INPUT_PORTS( qdisk )
+//-------------------------------------------------
+
+static INPUT_PORTS_START(qdisk)
+ PORT_START("SW1")
+ PORT_DIPNAME(0x01, 0x00, "Drive Selection")
+ PORT_DIPSETTING(0x00, "1")
+ PORT_DIPSETTING(0x01, "2")
+INPUT_PORTS_END
+
+
+//-------------------------------------------------
+// input_ports - device-specific input ports
+//-------------------------------------------------
+
+ioport_constructor aquarius_qdisk_device::device_input_ports() const
+{
+ return INPUT_PORTS_NAME(qdisk);
+}
+
+
+//-------------------------------------------------
+// device_add_mconfig - add device configuration
+//-------------------------------------------------
+
+void aquarius_qdisk_device::device_add_mconfig(machine_config &config)
+{
+ MC6852(config, m_ssda, 6.5_MHz_XTAL);
+
+ AQUARIUS_CARTRIDGE_SLOT(config, m_exp, DERIVED_CLOCK(1,1), aquarius_cartridge_devices, nullptr);
+ m_exp->irq_handler().set(DEVICE_SELF_OWNER, FUNC(aquarius_cartridge_slot_device::irq_w));
+ m_exp->nmi_handler().set(DEVICE_SELF_OWNER, FUNC(aquarius_cartridge_slot_device::nmi_w));
+}
+
+
+//**************************************************************************
+// LIVE DEVICE
+//**************************************************************************
+
+//-------------------------------------------------
+// aquarius_qdisk_device - constructor
+//-------------------------------------------------
+
+aquarius_qdisk_device::aquarius_qdisk_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
+ : device_t(mconfig, AQUARIUS_QDISK, tag, owner, clock)
+ , device_aquarius_cartridge_interface(mconfig, *this)
+ , m_ssda(*this, "mc6852")
+ , m_exp(*this, "exp")
+ , m_sw1(*this, "SW1")
+{
+}
+
+
+//-------------------------------------------------
+// device_start - device-specific startup
+//-------------------------------------------------
+
+void aquarius_qdisk_device::device_start()
+{
+}
+
+
+//**************************************************************************
+// IMPLEMENTATION
+//**************************************************************************
+
+uint8_t aquarius_qdisk_device::mreq_r(offs_t offset)
+{
+ return m_exp->mreq_r(offset);
+}
+
+void aquarius_qdisk_device::mreq_w(offs_t offset, uint8_t data)
+{
+ m_exp->mreq_w(offset, data);
+}
+
+
+uint8_t aquarius_qdisk_device::mreq_ce_r(offs_t offset)
+{
+ uint8_t data = get_rom_base()[offset & 0x1fff];
+
+ data &= m_exp->mreq_ce_r(offset);
+
+ return data;
+}
+
+void aquarius_qdisk_device::mreq_ce_w(offs_t offset, uint8_t data)
+{
+ m_exp->mreq_ce_w(offset, data);
+}
+
+
+uint8_t aquarius_qdisk_device::iorq_r(offs_t offset)
+{
+ uint8_t data = m_exp->iorq_r(offset);
+
+ switch (offset & 0xfe)
+ {
+ case 0xe6: case 0xea:
+ if (BIT(offset, 3) == m_sw1->read())
+ {
+ data = m_ssda->read(offset & 0x01);
+ }
+ logerror("iorq_r: %02x = %02x\n", offset, data);
+ break;
+ }
+
+ data &= m_exp->iorq_r(offset);
+
+ return data;
+}
+
+void aquarius_qdisk_device::iorq_w(offs_t offset, uint8_t data)
+{
+ switch (offset & 0xfe)
+ {
+ case 0xe6: case 0xea:
+ if (BIT(offset, 3) == m_sw1->read())
+ {
+ m_ssda->write(offset & 0x01, data);
+ }
+ logerror("iorq_w: %02x = %02x\n", offset, data);
+ break;
+ }
+
+ m_exp->iorq_w(offset, data);
+}
diff --git a/src/devices/bus/aquarius/qdisk.h b/src/devices/bus/aquarius/qdisk.h
new file mode 100644
index 00000000000..813180d96bd
--- /dev/null
+++ b/src/devices/bus/aquarius/qdisk.h
@@ -0,0 +1,59 @@
+// license:BSD-3-Clause
+// copyright-holders:Nigel Barnes
+/**********************************************************************
+
+ Radofin Aquarius Quick Disk
+
+**********************************************************************/
+
+#ifndef MAME_BUS_AQUARIUS_QDISK_H
+#define MAME_BUS_AQUARIUS_QDISK_H
+
+#pragma once
+
+#include "slot.h"
+#include "machine/mc6852.h"
+
+
+//**************************************************************************
+// TYPE DEFINITIONS
+//**************************************************************************
+
+class aquarius_qdisk_device :
+ public device_t,
+ public device_aquarius_cartridge_interface
+{
+public:
+ // construction/destruction
+ aquarius_qdisk_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 ATTR_COLD;
+
+ // optional information overrides
+ virtual void device_add_mconfig(machine_config &config) override ATTR_COLD;
+ virtual ioport_constructor device_input_ports() const override ATTR_COLD;
+
+ // device_aquarius_cartridge_interface overrides
+ virtual uint8_t mreq_r(offs_t offset) override;
+ virtual void mreq_w(offs_t offset, uint8_t data) override;
+ virtual uint8_t mreq_ce_r(offs_t offset) override;
+ virtual void mreq_ce_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;
+
+private:
+ required_device<mc6852_device> m_ssda;
+ required_device<aquarius_cartridge_slot_device> m_exp;
+ required_ioport m_sw1;
+};
+
+
+// device type definition
+DECLARE_DEVICE_TYPE(AQUARIUS_QDISK, aquarius_qdisk_device)
+
+
+#endif // MAME_BUS_AQUARIUS_QDISK_H
diff --git a/src/devices/bus/aquarius/ram.cpp b/src/devices/bus/aquarius/ram.cpp
new file mode 100644
index 00000000000..753a1fbf3a3
--- /dev/null
+++ b/src/devices/bus/aquarius/ram.cpp
@@ -0,0 +1,110 @@
+// license:BSD-3-Clause
+// copyright-holders:Nigel Barnes
+/**********************************************************************
+
+ Aquarius Memory Cartridges
+
+**********************************************************************/
+
+#include "emu.h"
+#include "ram.h"
+
+
+//**************************************************************************
+// DEVICE DEFINITIONS
+//**************************************************************************
+
+DEFINE_DEVICE_TYPE(AQUARIUS_RAM4, aquarius_ram4_device, "aquarius_ram4", "Aquarius 4K Memory Cartridge")
+DEFINE_DEVICE_TYPE(AQUARIUS_RAM16, aquarius_ram16_device, "aquarius_ram16", "Aquarius 16K Memory Cartridge")
+DEFINE_DEVICE_TYPE(AQUARIUS_RAM32, aquarius_ram32_device, "aquarius_ram32", "Aquarius 32K Memory Cartridge")
+DEFINE_DEVICE_TYPE(AQUARIUS_RAM16P, aquarius_ram16p_device, "aquarius_ram16p", "Aquarius 16K+ Memory Cartridge")
+
+
+//**************************************************************************
+// LIVE DEVICE
+//**************************************************************************
+
+//-------------------------------------------------
+// aquarius_ram_device - constructor
+//-------------------------------------------------
+
+aquarius_ram_device::aquarius_ram_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock, uint16_t size)
+ : device_t(mconfig, type, tag, owner, clock)
+ , device_aquarius_cartridge_interface(mconfig, *this)
+ , m_ram_size(size)
+{
+}
+
+aquarius_ram4_device::aquarius_ram4_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
+ : aquarius_ram_device(mconfig, AQUARIUS_RAM4, tag, owner, clock, 0x1000)
+{
+}
+
+aquarius_ram16_device::aquarius_ram16_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
+ : aquarius_ram_device(mconfig, AQUARIUS_RAM16, tag, owner, clock, 0x4000)
+{
+}
+
+aquarius_ram32_device::aquarius_ram32_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
+ : aquarius_ram_device(mconfig, AQUARIUS_RAM32, tag, owner, clock, 0x8000)
+{
+}
+
+aquarius_ram16p_device::aquarius_ram16p_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
+ : device_t(mconfig, AQUARIUS_RAM16P, tag, owner, clock)
+ , device_aquarius_cartridge_interface(mconfig, *this)
+{
+}
+
+
+//-------------------------------------------------
+// device_start - device-specific startup
+//-------------------------------------------------
+
+void aquarius_ram_device::device_start()
+{
+ m_ram = make_unique_clear<uint8_t[]>(m_ram_size);
+
+ save_pointer(NAME(m_ram), m_ram_size);
+}
+
+void aquarius_ram16p_device::device_start()
+{
+ m_ram = make_unique_clear<uint8_t[]>(0x4000);
+
+ save_pointer(NAME(m_ram), 0x4000);
+}
+
+
+//**************************************************************************
+// IMPLEMENTATION
+//**************************************************************************
+
+uint8_t aquarius_ram_device::mreq_r(offs_t offset)
+{
+ if (offset < m_ram_size)
+ {
+ return m_ram[offset];
+ }
+
+ return 0xff;
+}
+
+void aquarius_ram_device::mreq_w(offs_t offset, uint8_t data)
+{
+ if (offset < m_ram_size)
+ {
+ m_ram[offset] = data;
+ }
+}
+
+
+uint8_t aquarius_ram16p_device::mreq_ce_r(offs_t offset)
+{
+ return m_ram[offset];
+}
+
+void aquarius_ram16p_device::mreq_ce_w(offs_t offset, uint8_t data)
+{
+ m_ram[offset] = data;
+}
diff --git a/src/devices/bus/aquarius/ram.h b/src/devices/bus/aquarius/ram.h
new file mode 100644
index 00000000000..71ee343f60e
--- /dev/null
+++ b/src/devices/bus/aquarius/ram.h
@@ -0,0 +1,102 @@
+// license:BSD-3-Clause
+// copyright-holders:Nigel Barnes
+/**********************************************************************
+
+ Aquarius Memory Cartridges
+
+**********************************************************************/
+
+#ifndef MAME_BUS_AQUARIUS_RAM_H
+#define MAME_BUS_AQUARIUS_RAM_H
+
+#pragma once
+
+#include "slot.h"
+
+
+//**************************************************************************
+// TYPE DEFINITIONS
+//**************************************************************************
+
+// ======================> aquarius_ram_device
+
+class aquarius_ram_device :
+ public device_t,
+ public device_aquarius_cartridge_interface
+{
+protected:
+ // construction/destruction
+ aquarius_ram_device(const machine_config& mconfig, device_type type, const char* tag, device_t* owner, uint32_t clock, uint16_t size);
+
+ // device-level overrides
+ virtual void device_start() override ATTR_COLD;
+
+ // device_aquarius_cartridge_interface overrides
+ virtual uint8_t mreq_r(offs_t offset) override;
+ virtual void mreq_w(offs_t offset, uint8_t data) override;
+
+private:
+ uint16_t m_ram_size;
+
+ std::unique_ptr<uint8_t[]> m_ram;
+};
+
+// ======================> aquarius_ram4_device
+
+class aquarius_ram4_device : public aquarius_ram_device
+{
+public:
+ // construction/destruction
+ aquarius_ram4_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
+};
+
+// ======================> aquarius_ram16_device
+
+class aquarius_ram16_device : public aquarius_ram_device
+{
+public:
+ // construction/destruction
+ aquarius_ram16_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
+};
+
+// ======================> aquarius_ram32_device
+
+class aquarius_ram32_device : public aquarius_ram_device
+{
+public:
+ // construction/destruction
+ aquarius_ram32_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
+};
+
+
+// ======================> aquarius_ram16p_device
+
+class aquarius_ram16p_device :
+ public device_t,
+ public device_aquarius_cartridge_interface
+{
+public:
+ // construction/destruction
+ aquarius_ram16p_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
+
+protected:
+ // device-level overrides
+ virtual void device_start() override ATTR_COLD;
+
+ // device_aquarius_cartridge_interface overrides
+ virtual uint8_t mreq_ce_r(offs_t offset) override;
+ virtual void mreq_ce_w(offs_t offset, uint8_t data) override;
+
+private:
+ std::unique_ptr<uint8_t[]> m_ram;
+};
+
+
+// device type definition
+DECLARE_DEVICE_TYPE(AQUARIUS_RAM4, aquarius_ram4_device)
+DECLARE_DEVICE_TYPE(AQUARIUS_RAM16, aquarius_ram16_device)
+DECLARE_DEVICE_TYPE(AQUARIUS_RAM32, aquarius_ram32_device)
+DECLARE_DEVICE_TYPE(AQUARIUS_RAM16P, aquarius_ram16p_device)
+
+
+#endif // MAME_BUS_AQUARIUS_RAM_H
diff --git a/src/devices/bus/aquarius/rom.cpp b/src/devices/bus/aquarius/rom.cpp
new file mode 100644
index 00000000000..87f7df97079
--- /dev/null
+++ b/src/devices/bus/aquarius/rom.cpp
@@ -0,0 +1,51 @@
+// license:BSD-3-Clause
+// copyright-holders:Nigel Barnes
+/***************************************************************************
+
+ Aquarius Software Cartridges
+
+***************************************************************************/
+
+#include "emu.h"
+#include "rom.h"
+
+
+//**************************************************************************
+// DEVICE DEFINITIONS
+//**************************************************************************
+
+DEFINE_DEVICE_TYPE(AQUARIUS_ROM, aquarius_rom_device, "aquarius_rom", "Aquarius ROM Cartridge")
+
+
+//**************************************************************************
+// LIVE DEVICE
+//**************************************************************************
+
+//-------------------------------------------------
+// aquarius_rom_device - constructor
+//-------------------------------------------------
+
+aquarius_rom_device::aquarius_rom_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
+ : device_t(mconfig, AQUARIUS_ROM, tag, owner, clock)
+ , device_aquarius_cartridge_interface(mconfig, *this)
+{
+}
+
+
+//-------------------------------------------------
+// device_start - device-specific startup
+//-------------------------------------------------
+
+void aquarius_rom_device::device_start()
+{
+}
+
+
+//**************************************************************************
+// IMPLEMENTATION
+//**************************************************************************
+
+uint8_t aquarius_rom_device::mreq_ce_r(offs_t offset)
+{
+ return get_rom_base()[offset & (get_rom_size() - 1)];
+}
diff --git a/src/devices/bus/aquarius/rom.h b/src/devices/bus/aquarius/rom.h
new file mode 100644
index 00000000000..f3790cdbf91
--- /dev/null
+++ b/src/devices/bus/aquarius/rom.h
@@ -0,0 +1,44 @@
+// license:BSD-3-Clause
+// copyright-holders:Nigel Barnes
+/***************************************************************************
+
+ Aquarius Software Cartridges
+
+***************************************************************************/
+
+#ifndef MAME_BUS_AQUARIUS_ROM_H
+#define MAME_BUS_AQUARIUS_ROM_H
+
+#pragma once
+
+#include "slot.h"
+
+
+//**************************************************************************
+// TYPE DEFINITIONS
+//**************************************************************************
+
+// ======================> aquarius_rom_device
+
+class aquarius_rom_device :
+ public device_t,
+ public device_aquarius_cartridge_interface
+{
+public:
+ // construction/destruction
+ aquarius_rom_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
+
+protected:
+ // device-level overrides
+ virtual void device_start() override ATTR_COLD;
+
+ // device_aquarius_cartridge_interface overrides
+ virtual uint8_t mreq_ce_r(offs_t offset) override;
+};
+
+
+// device type definition
+DECLARE_DEVICE_TYPE(AQUARIUS_ROM, aquarius_rom_device)
+
+
+#endif // MAME_BUS_AQUARIUS_ROM_H
diff --git a/src/devices/bus/aquarius/slot.cpp b/src/devices/bus/aquarius/slot.cpp
new file mode 100644
index 00000000000..aa3863963c6
--- /dev/null
+++ b/src/devices/bus/aquarius/slot.cpp
@@ -0,0 +1,219 @@
+// license:BSD-3-Clause
+// copyright-holders:Nigel Barnes
+/**********************************************************************
+
+ Aquarius Cartridge Port emulation
+
+**********************************************************************/
+
+#include "emu.h"
+#include "slot.h"
+
+
+//**************************************************************************
+// DEVICE DEFINITIONS
+//**************************************************************************
+
+DEFINE_DEVICE_TYPE(AQUARIUS_CARTRIDGE_SLOT, aquarius_cartridge_slot_device, "aquarius_cartridge_slot", "Aquarius Cartridge port")
+
+
+//**************************************************************************
+// DEVICE AQUARIUS_CARTRIDGE CARD INTERFACE
+//**************************************************************************
+
+//-------------------------------------------------
+// device_aquarius_cartridge_interface - constructor
+//-------------------------------------------------
+
+device_aquarius_cartridge_interface::device_aquarius_cartridge_interface(const machine_config &mconfig, device_t &device)
+ : device_interface(device, "aquariuscart")
+ , m_rom(nullptr)
+ , m_rom_size(0)
+{
+ m_slot = dynamic_cast<aquarius_cartridge_slot_device *>(device.owner());
+}
+
+
+//-------------------------------------------------
+// rom_alloc - alloc the space for the ROM
+//-------------------------------------------------
+
+void device_aquarius_cartridge_interface::rom_alloc(uint32_t size)
+{
+ if (m_rom == nullptr)
+ {
+ m_rom = device().machine().memory().region_alloc(device().subtag("^cart:rom"), size, 1, ENDIANNESS_LITTLE)->base();
+ m_rom_size = size;
+ }
+}
+
+//**************************************************************************
+// LIVE DEVICE
+//**************************************************************************
+
+//-------------------------------------------------
+// aquarius_cartridge_slot_device - constructor
+//-------------------------------------------------
+
+aquarius_cartridge_slot_device::aquarius_cartridge_slot_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
+ : device_t(mconfig, AQUARIUS_CARTRIDGE_SLOT, tag, owner, clock)
+ , device_cartrom_image_interface(mconfig, *this)
+ , device_single_card_slot_interface<device_aquarius_cartridge_interface>(mconfig, *this)
+ , m_cart(nullptr)
+ , m_irq_handler(*this)
+ , m_nmi_handler(*this)
+{
+}
+
+
+//-------------------------------------------------
+// device_start - device-specific startup
+//-------------------------------------------------
+
+void aquarius_cartridge_slot_device::device_start()
+{
+ m_cart = get_card_device();
+}
+
+//-------------------------------------------------
+// call_load
+//-------------------------------------------------
+
+std::pair<std::error_condition, std::string> aquarius_cartridge_slot_device::call_load()
+{
+ if (m_cart)
+ {
+ uint32_t const size = !loaded_through_softlist() ? length() : get_software_region_length("rom");
+
+ if (size % 0x1000)
+ return std::make_pair(image_error::INVALIDLENGTH, "Invalid ROM size (must be a multiple of 4K)");
+
+ m_cart->rom_alloc(size);
+
+ if (!loaded_through_softlist())
+ fread(m_cart->get_rom_base(), size);
+ else
+ memcpy(m_cart->get_rom_base(), get_software_region("rom"), size);
+ }
+
+ return std::make_pair(std::error_condition(), std::string());
+}
+
+//-------------------------------------------------
+// get_default_card_software
+//-------------------------------------------------
+
+std::string aquarius_cartridge_slot_device::get_default_card_software(get_default_card_software_hook &hook) const
+{
+ static const unsigned char SC08_HEADER[16] = { 0x53, 0x43, 0x30, 0x38, 0x4b, 0x9c, 0xb5, 0xb0, 0xa8, 0x6c, 0xac, 0x64, 0xcc, 0xa8, 0x06, 0x70 };
+ static const unsigned char SC16_HEADER[16] = { 0x53, 0x43, 0x31, 0x36, 0x4b, 0x9c, 0xb5, 0xb0, 0xa8, 0x6c, 0xac, 0x64, 0xcc, 0xa8, 0x08, 0x70 };
+
+ if (hook.image_file())
+ {
+ uint64_t len;
+ hook.image_file()->length(len); // FIXME: check error return
+
+ const char *slot_string = "rom";
+ if (len >= 0x10000)
+ {
+ uint8_t header[16];
+
+ hook.image_file()->seek(len - 0x2000, SEEK_SET); // FIXME: check error return
+ 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))
+ slot_string = "sc1";
+ }
+
+ return std::string(slot_string);
+ }
+ else
+ return software_get_default_slot("rom");
+}
+
+//-------------------------------------------------
+// iorq_r
+//-------------------------------------------------
+
+uint8_t aquarius_cartridge_slot_device::iorq_r(offs_t offset)
+{
+ if (m_cart)
+ return m_cart->iorq_r(offset);
+ else
+ return 0xff;
+}
+
+//-------------------------------------------------
+// iorq_w
+//-------------------------------------------------
+
+void aquarius_cartridge_slot_device::iorq_w(offs_t offset, uint8_t data)
+{
+ if (m_cart)
+ m_cart->iorq_w(offset, data);
+}
+
+//-------------------------------------------------
+// mreq_r
+//-------------------------------------------------
+
+uint8_t aquarius_cartridge_slot_device::mreq_r(offs_t offset)
+{
+ if (m_cart)
+ return m_cart->mreq_r(offset);
+ else
+ return 0xff;
+}
+
+uint8_t aquarius_cartridge_slot_device::mreq_ce_r(offs_t offset)
+{
+ if (m_cart)
+ return m_cart->mreq_ce_r(offset);
+ else
+ return 0xff;
+}
+
+//-------------------------------------------------
+// mreq_w
+//-------------------------------------------------
+
+void aquarius_cartridge_slot_device::mreq_w(offs_t offset, uint8_t data)
+{
+ if (m_cart)
+ m_cart->mreq_w(offset, data);
+}
+
+void aquarius_cartridge_slot_device::mreq_ce_w(offs_t offset, uint8_t data)
+{
+ if (m_cart)
+ m_cart->mreq_ce_w(offset, data);
+}
+
+
+//-------------------------------------------------
+// SLOT_INTERFACE( aquarius_cartridge_devices )
+//-------------------------------------------------
+
+
+// slot devices
+#include "c1541.h"
+#include "mini.h"
+#include "qdisk.h"
+#include "ram.h"
+#include "rom.h"
+#include "supercart.h"
+
+
+void aquarius_cartridge_devices(device_slot_interface &device)
+{
+ device.option_add("mini", AQUARIUS_MINI);
+ device.option_add("ram4", AQUARIUS_RAM4);
+ device.option_add("ram16", AQUARIUS_RAM16);
+ device.option_add("ram16p", AQUARIUS_RAM16P);
+ device.option_add("ram32", AQUARIUS_RAM32);
+ device.option_add_internal("c1541", AQUARIUS_C1541);
+ device.option_add_internal("qdisk", AQUARIUS_QDISK);
+ device.option_add_internal("rom", AQUARIUS_ROM);
+ device.option_add_internal("sc1", AQUARIUS_SC1);
+}
diff --git a/src/devices/bus/aquarius/slot.h b/src/devices/bus/aquarius/slot.h
new file mode 100644
index 00000000000..f30570bf24d
--- /dev/null
+++ b/src/devices/bus/aquarius/slot.h
@@ -0,0 +1,116 @@
+// license:BSD-3-Clause
+// copyright-holders:Nigel Barnes
+/**********************************************************************
+
+ Aquarius Cartridge Port emulation
+
+**********************************************************************/
+
+#ifndef MAME_BUS_AQUARIUS_SLOT_H
+#define MAME_BUS_AQUARIUS_SLOT_H
+
+#pragma once
+
+#include "imagedev/cartrom.h"
+
+
+//**************************************************************************
+// TYPE DEFINITIONS
+//**************************************************************************
+
+// ======================> aquarius_cartridge_slot_device
+
+class device_aquarius_cartridge_interface;
+
+class aquarius_cartridge_slot_device : public device_t,
+ public device_cartrom_image_interface,
+ public device_single_card_slot_interface<device_aquarius_cartridge_interface>
+{
+public:
+ // construction/destruction
+ template <typename T>
+ aquarius_cartridge_slot_device(machine_config const &mconfig, char const *tag, device_t *owner, uint32_t clock, T &&slot_options, const char *default_option)
+ : aquarius_cartridge_slot_device(mconfig, tag, owner, clock)
+ {
+ option_reset();
+ slot_options(*this);
+ set_default_option(default_option);
+ set_fixed(false);
+ }
+
+ aquarius_cartridge_slot_device(machine_config const &mconfig, char const *tag, device_t *owner, uint32_t clock);
+
+ // callbacks
+ auto irq_handler() { return m_irq_handler.bind(); }
+ auto nmi_handler() { return m_nmi_handler.bind(); }
+
+ // 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"; }
+
+ // device_slot_interface implementation
+ virtual std::string get_default_card_software(get_default_card_software_hook &hook) const override;
+
+ // reading and writing
+ uint8_t mreq_r(offs_t offset);
+ void mreq_w(offs_t offset, uint8_t data);
+ uint8_t mreq_ce_r(offs_t offset);
+ void mreq_ce_w(offs_t offset, uint8_t data);
+ uint8_t iorq_r(offs_t offset);
+ void iorq_w(offs_t offset, uint8_t data);
+
+ void irq_w(int state) { m_irq_handler(state); }
+ void nmi_w(int state) { m_nmi_handler(state); }
+
+protected:
+ // device_t implementation
+ virtual void device_start() override ATTR_COLD;
+
+ device_aquarius_cartridge_interface *m_cart;
+
+private:
+ devcb_write_line m_irq_handler;
+ devcb_write_line m_nmi_handler;
+};
+
+
+// ======================> device_aquarius_cartridge_interface
+
+class device_aquarius_cartridge_interface : public device_interface
+{
+public:
+ // reading and writing
+ virtual uint8_t mreq_r(offs_t offset) { return 0xff; }
+ virtual void mreq_w(offs_t offset, uint8_t data) { }
+ virtual uint8_t mreq_ce_r(offs_t offset) { return 0xff; }
+ virtual void mreq_ce_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) { }
+
+ void rom_alloc(uint32_t size);
+ uint8_t* get_rom_base() { return m_rom; }
+ uint32_t get_rom_size() { return m_rom_size; }
+
+protected:
+ // construction/destruction
+ device_aquarius_cartridge_interface(const machine_config &mconfig, device_t &device);
+
+ aquarius_cartridge_slot_device *m_slot;
+
+private:
+ // internal state
+ uint8_t *m_rom;
+ uint32_t m_rom_size;
+};
+
+
+// device type definition
+DECLARE_DEVICE_TYPE(AQUARIUS_CARTRIDGE_SLOT, aquarius_cartridge_slot_device)
+
+void aquarius_cartridge_devices(device_slot_interface &device);
+
+
+#endif // MAME_BUS_AQUARIUS_SLOT_H
diff --git a/src/devices/bus/aquarius/supercart.cpp b/src/devices/bus/aquarius/supercart.cpp
new file mode 100644
index 00000000000..2bc2ad82fd8
--- /dev/null
+++ b/src/devices/bus/aquarius/supercart.cpp
@@ -0,0 +1,101 @@
+// license:BSD-3-Clause
+// copyright-holders:Nigel Barnes
+/***************************************************************************
+
+ Aquarius SuperCart Cartridge
+
+***************************************************************************/
+
+#include "emu.h"
+#include "supercart.h"
+
+
+//**************************************************************************
+// DEVICE DEFINITIONS
+//**************************************************************************
+
+DEFINE_DEVICE_TYPE(AQUARIUS_SC1, aquarius_sc1_device, "aquarius_sc1", "Aquarius SuperCart I Cartridge")
+
+
+//**************************************************************************
+// LIVE DEVICE
+//**************************************************************************
+
+//-------------------------------------------------
+// aquarius_sc1_device - constructor
+//-------------------------------------------------
+
+aquarius_sc1_device::aquarius_sc1_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
+ : device_t(mconfig, AQUARIUS_SC1, tag, owner, clock)
+ , device_aquarius_cartridge_interface(mconfig, *this)
+ , m_bank(0)
+ , m_mode(0)
+{
+}
+
+
+//-------------------------------------------------
+// device_start - device-specific startup
+//-------------------------------------------------
+
+void aquarius_sc1_device::device_start()
+{
+ save_item(NAME(m_bank));
+ save_item(NAME(m_mode));
+}
+
+//-------------------------------------------------
+// device_reset - device-specific reset
+//-------------------------------------------------
+
+void aquarius_sc1_device::device_reset()
+{
+ static const unsigned char SC08_HEADER[16] = { 0x53, 0x43, 0x30, 0x38, 0x4b, 0x9c, 0xb5, 0xb0, 0xa8, 0x6c, 0xac, 0x64, 0xcc, 0xa8, 0x06, 0x70 };
+ static const unsigned char SC16_HEADER[16] = { 0x53, 0x43, 0x31, 0x36, 0x4b, 0x9c, 0xb5, 0xb0, 0xa8, 0x6c, 0xac, 0x64, 0xcc, 0xa8, 0x08, 0x70 };
+
+ uint8_t* header = get_rom_base() + get_rom_size() - 0x2000;
+
+ // select bank switching mode
+ if (!memcmp(header, SC08_HEADER, 16))
+ m_mode = 0;
+ else if (!memcmp(header, SC16_HEADER, 16))
+ m_mode = 1;
+ else
+ fatalerror("Invalid SuperCart mode header\n");
+}
+
+
+//**************************************************************************
+// IMPLEMENTATION
+//**************************************************************************
+
+uint8_t aquarius_sc1_device::mreq_ce_r(offs_t offset)
+{
+ switch (m_mode)
+ {
+ case 0: // 8K Mode
+ if (offset & 0x2000)
+ {
+ offset |= get_rom_size() - 0x2000;
+ }
+ else
+ {
+ offset |= m_bank << 13;
+ }
+ break;
+
+ case 1: // 16K Mode
+ offset |= (m_bank & 0x7e) << 13;
+ break;
+ }
+
+ return get_rom_base()[offset & (get_rom_size() - 1)];
+}
+
+void aquarius_sc1_device::mreq_ce_w(offs_t offset, uint8_t data)
+{
+ if (offset & 0x2000)
+ {
+ m_bank = data & 0x7f;
+ }
+}
diff --git a/src/devices/bus/aquarius/supercart.h b/src/devices/bus/aquarius/supercart.h
new file mode 100644
index 00000000000..e7460bb4464
--- /dev/null
+++ b/src/devices/bus/aquarius/supercart.h
@@ -0,0 +1,50 @@
+// license:BSD-3-Clause
+// copyright-holders:Nigel Barnes
+/***************************************************************************
+
+ Aquarius SuperCart Cartridge
+
+***************************************************************************/
+
+#ifndef MAME_BUS_AQUARIUS_SUPERCART_H
+#define MAME_BUS_AQUARIUS_SUPERCART_H
+
+#pragma once
+
+#include "slot.h"
+
+
+//**************************************************************************
+// TYPE DEFINITIONS
+//**************************************************************************
+
+// ======================> aquarius_sc1_device
+
+class aquarius_sc1_device :
+ public device_t,
+ public device_aquarius_cartridge_interface
+{
+public:
+ // construction/destruction
+ aquarius_sc1_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
+
+protected:
+ // device-level overrides
+ virtual void device_start() override ATTR_COLD;
+ virtual void device_reset() override ATTR_COLD;
+
+ // device_aquarius_cartridge_interface overrides
+ virtual uint8_t mreq_ce_r(offs_t offset) override;
+ virtual void mreq_ce_w(offs_t offset, uint8_t data) override;
+
+private:
+ uint8_t m_bank;
+ int m_mode;
+};
+
+
+// device type definition
+DECLARE_DEVICE_TYPE(AQUARIUS_SC1, aquarius_sc1_device)
+
+
+#endif // MAME_BUS_AQUARIUS_SUPERCART_H
diff --git a/src/devices/bus/arcadia/rom.cpp b/src/devices/bus/arcadia/rom.cpp
index 2221fed2f2c..60bc4b3a88e 100644
--- a/src/devices/bus/arcadia/rom.cpp
+++ b/src/devices/bus/arcadia/rom.cpp
@@ -42,7 +42,7 @@ arcadia_golf_device::arcadia_golf_device(const machine_config &mconfig, const ch
mapper specific handlers
-------------------------------------------------*/
-READ8_MEMBER(arcadia_rom_device::read_rom)
+uint8_t arcadia_rom_device::read_rom(offs_t offset)
{
if (offset < m_rom_size)
return m_rom[offset];
@@ -51,7 +51,7 @@ READ8_MEMBER(arcadia_rom_device::read_rom)
}
-READ8_MEMBER(arcadia_rom_device::extra_rom)
+uint8_t arcadia_rom_device::extra_rom(offs_t offset)
{
if (offset + 0x1000 < m_rom_size)
return m_rom[offset + 0x1000];
diff --git a/src/devices/bus/arcadia/rom.h b/src/devices/bus/arcadia/rom.h
index 31e71d833b5..b0ba196302e 100644
--- a/src/devices/bus/arcadia/rom.h
+++ b/src/devices/bus/arcadia/rom.h
@@ -18,8 +18,8 @@ public:
arcadia_rom_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
// reading and writing
- virtual DECLARE_READ8_MEMBER(read_rom) override;
- virtual DECLARE_READ8_MEMBER(extra_rom) override;
+ virtual uint8_t read_rom(offs_t offset) override;
+ virtual uint8_t extra_rom(offs_t offset) override;
public:
arcadia_rom_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock);
diff --git a/src/devices/bus/arcadia/slot.cpp b/src/devices/bus/arcadia/slot.cpp
index fed92bee9cd..5390ca91bf4 100644
--- a/src/devices/bus/arcadia/slot.cpp
+++ b/src/devices/bus/arcadia/slot.cpp
@@ -7,7 +7,6 @@
***********************************************************************************************************/
-
#include "emu.h"
#include "slot.h"
@@ -25,10 +24,10 @@ DEFINE_DEVICE_TYPE(EA2001_CART_SLOT, arcadia_cart_slot_device, "arcadia_cart_slo
// device_arcadia_cart_interface - constructor
//-------------------------------------------------
-device_arcadia_cart_interface::device_arcadia_cart_interface(const machine_config &mconfig, device_t &device)
- : device_slot_card_interface(mconfig, device),
- m_rom(nullptr),
- m_rom_size(0)
+device_arcadia_cart_interface::device_arcadia_cart_interface(const machine_config &mconfig, device_t &device) :
+ device_interface(device, "arcadiacart"),
+ m_rom(nullptr),
+ m_rom_size(0)
{
}
@@ -45,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;
}
}
@@ -64,8 +63,8 @@ void device_arcadia_cart_interface::rom_alloc(uint32_t size, const char *tag)
//-------------------------------------------------
arcadia_cart_slot_device::arcadia_cart_slot_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) :
device_t(mconfig, EA2001_CART_SLOT, tag, owner, clock),
- device_image_interface(mconfig, *this),
- device_slot_interface(mconfig, *this),
+ device_cartrom_image_interface(mconfig, *this),
+ device_single_card_slot_interface<device_arcadia_cart_interface>(mconfig, *this),
m_type(ARCADIA_STD), m_cart(nullptr)
{
}
@@ -85,7 +84,7 @@ arcadia_cart_slot_device::~arcadia_cart_slot_device()
void arcadia_cart_slot_device::device_start()
{
- m_cart = dynamic_cast<device_arcadia_cart_interface *>(get_card_device());
+ m_cart = get_card_device();
}
@@ -110,7 +109,7 @@ static int arcadia_get_pcb_id(const char *slot)
{
for (auto & elem : slot_list)
{
- if (!core_stricmp(elem.slot_option, slot))
+ if (!strcmp(elem.slot_option, slot))
return elem.pcb_id;
}
@@ -120,7 +119,7 @@ static int arcadia_get_pcb_id(const char *slot)
#if 0
static const char *arcadia_get_slot(int type)
{
- for (int i = 0; i < ARRAY_LENGTH(slot_list); i++)
+ for (int i = 0; i < std::size(slot_list); i++)
{
if (slot_list[i].pcb_id == type)
return slot_list[i].slot_option;
@@ -134,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);
@@ -194,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());
}
@@ -215,10 +212,10 @@ std::string arcadia_cart_slot_device::get_default_card_software(get_default_card
read
-------------------------------------------------*/
-READ8_MEMBER(arcadia_cart_slot_device::read_rom)
+uint8_t arcadia_cart_slot_device::read_rom(offs_t offset)
{
if (m_cart)
- return m_cart->read_rom(space, offset);
+ return m_cart->read_rom(offset);
else
return 0xff;
}
@@ -227,10 +224,10 @@ READ8_MEMBER(arcadia_cart_slot_device::read_rom)
write
-------------------------------------------------*/
-READ8_MEMBER(arcadia_cart_slot_device::extra_rom)
+uint8_t arcadia_cart_slot_device::extra_rom(offs_t offset)
{
if (m_cart)
- return m_cart->extra_rom(space, offset);
+ return m_cart->extra_rom(offset);
else
return 0xff;
}
diff --git a/src/devices/bus/arcadia/slot.h b/src/devices/bus/arcadia/slot.h
index 1269fe95e7e..eced97e405d 100644
--- a/src/devices/bus/arcadia/slot.h
+++ b/src/devices/bus/arcadia/slot.h
@@ -3,9 +3,8 @@
#ifndef MAME_BUS_ARCADIA_SLOT_H
#define MAME_BUS_ARCADIA_SLOT_H
-#include "softlist_dev.h"
+#include "imagedev/cartrom.h"
-#define EA2001SLOT_ROM_REGION_TAG ":cart:rom"
/***************************************************************************
TYPE DEFINITIONS
@@ -20,7 +19,7 @@ enum
// ======================> device_arcadia_cart_interface
-class device_arcadia_cart_interface : public device_slot_card_interface
+class device_arcadia_cart_interface : public device_interface
{
public:
// construction/destruction
@@ -28,10 +27,10 @@ public:
virtual ~device_arcadia_cart_interface();
// reading and writing
- virtual DECLARE_READ8_MEMBER(read_rom) { return 0xff; }
- virtual DECLARE_READ8_MEMBER(extra_rom) { return 0xff; }
+ 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; }
@@ -45,8 +44,8 @@ protected:
// ======================> arcadia_cart_slot_device
class arcadia_cart_slot_device : public device_t,
- public device_image_interface,
- public device_slot_interface
+ public device_cartrom_image_interface,
+ public device_single_card_slot_interface<device_arcadia_cart_interface>
{
public:
// construction/destruction
@@ -62,35 +61,29 @@ 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 const software_list_loader &get_software_list_loader() const override { return rom_software_list_loader::instance(); }
- int get_type() { return m_type; }
-
- virtual iodevice_t image_type() const override { return IO_CARTSLOT; }
- virtual bool is_readable() const override { return 1; }
- virtual bool is_writeable() const override { return 0; }
- virtual bool is_creatable() const override { return 0; }
- virtual bool must_be_loaded() const override { return 1; }
- virtual bool is_reset_on_load() const override { return 1; }
- virtual const char *image_interface() const override { return "arcadia_cart"; }
- virtual const char *file_extensions() const override { return "bin"; }
+ 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; }
+
// reading and writing
- virtual DECLARE_READ8_MEMBER(read_rom);
- virtual DECLARE_READ8_MEMBER(extra_rom);
+ uint8_t read_rom(offs_t offset);
+ uint8_t extra_rom(offs_t offset);
protected:
- // device-level overrides
- virtual void device_start() override;
+ // device_t implementation
+ virtual void device_start() override ATTR_COLD;
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/econet.cpp b/src/devices/bus/archimedes/econet/econet.cpp
new file mode 100644
index 00000000000..e469b9f581d
--- /dev/null
+++ b/src/devices/bus/archimedes/econet/econet.cpp
@@ -0,0 +1,77 @@
+// license:BSD-3-Clause
+// copyright-holders:Nigel Barnes
+/**********************************************************************
+
+ Acorn Archimedes Econet Module
+
+**********************************************************************/
+
+#include "emu.h"
+#include "econet.h"
+#include "bus/econet/econet.h"
+
+
+
+//**************************************************************************
+// DEVICE DEFINITIONS
+//**************************************************************************
+
+DEFINE_DEVICE_TYPE(ARC_ECONET, arc_econet_device, "arc_econet", "Acorn ADF10/AEH52 Econet Module");
+
+
+//-------------------------------------------------
+// device_add_mconfig - add device configuration
+//-------------------------------------------------
+
+void arc_econet_device::device_add_mconfig(machine_config &config)
+{
+ MC6854(config, m_adlc);
+ m_adlc->out_txd_cb().set("econet", FUNC(econet_device::host_data_w));
+ m_adlc->out_irq_cb().set(DEVICE_SELF_OWNER, FUNC(archimedes_econet_slot_device::efiq_w));
+
+ econet_device &econet(ECONET(config, "econet", 0));
+ econet.clk_wr_callback().set(m_adlc, FUNC(mc6854_device::txc_w));
+ econet.clk_wr_callback().append(m_adlc, FUNC(mc6854_device::rxc_w));
+ econet.data_wr_callback().set(m_adlc, FUNC(mc6854_device::set_rx));
+
+ ECONET_SLOT(config, "econet254", "econet", econet_devices);
+}
+
+
+//**************************************************************************
+// LIVE DEVICE
+//**************************************************************************
+
+//-------------------------------------------------
+// archimedes_econet_device - constructor
+//-------------------------------------------------
+
+arc_econet_device::arc_econet_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock)
+ : device_t(mconfig, ARC_ECONET, tag, owner, clock)
+ , device_archimedes_econet_interface(mconfig, *this)
+ , m_adlc(*this, "mc6854")
+{
+}
+
+
+//-------------------------------------------------
+// device_start - device-specific startup
+//-------------------------------------------------
+
+void arc_econet_device::device_start()
+{
+}
+
+//**************************************************************************
+// IMPLEMENTATION
+//**************************************************************************
+
+u8 arc_econet_device::read(offs_t offset)
+{
+ return m_adlc->read(offset);
+}
+
+void arc_econet_device::write(offs_t offset, u8 data)
+{
+ m_adlc->write(offset, data);
+}
diff --git a/src/devices/bus/archimedes/econet/econet.h b/src/devices/bus/archimedes/econet/econet.h
new file mode 100644
index 00000000000..a43967264ba
--- /dev/null
+++ b/src/devices/bus/archimedes/econet/econet.h
@@ -0,0 +1,55 @@
+// license:BSD-3-Clause
+// copyright-holders:Nigel Barnes
+/**********************************************************************
+
+ Acorn Archimedes Econet Module
+
+**********************************************************************/
+
+
+#ifndef MAME_BUS_ARCHIMEDES_ECONET_ECONET_H
+#define MAME_BUS_ARCHIMEDES_ECONET_ECONET_H
+
+#pragma once
+
+
+#include "slot.h"
+#include "machine/mc6854.h"
+
+
+
+//**************************************************************************
+// TYPE DEFINITIONS
+//**************************************************************************
+
+// ======================> arc_econet_adf10_device
+
+class arc_econet_device:
+ public device_t,
+ public device_archimedes_econet_interface
+{
+public:
+ // construction/destruction
+ arc_econet_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock);
+
+protected:
+ // device-level overrides
+ virtual void device_start() override ATTR_COLD;
+
+ // optional information overrides
+ virtual void device_add_mconfig(machine_config &config) override ATTR_COLD;
+
+ virtual u8 read(offs_t offset) override;
+ virtual void write(offs_t offset, u8 data) override;
+
+private:
+ required_device<mc6854_device> m_adlc;
+};
+
+
+
+// device type definition
+DECLARE_DEVICE_TYPE(ARC_ECONET, arc_econet_device);
+
+
+#endif /* MAME_BUS_ARCHIMEDES_ECONET_ECONET_H */
diff --git a/src/devices/bus/archimedes/econet/midi.cpp b/src/devices/bus/archimedes/econet/midi.cpp
new file mode 100644
index 00000000000..f6d3cc5c39b
--- /dev/null
+++ b/src/devices/bus/archimedes/econet/midi.cpp
@@ -0,0 +1,100 @@
+// license:BSD-3-Clause
+// copyright-holders:Nigel Barnes
+/**********************************************************************
+
+ The Serial Port MIDI Interface
+
+ http://chrisacorns.computinghistory.org.uk/32bit_UpgradesH2Z/TheSerialPort_MIDI.html
+
+ The Serial Port Sampler and MIDI Interface
+
+ http://chrisacorns.computinghistory.org.uk/32bit_UpgradesH2Z/TheSerialPort_SamplerMIDI.html
+
+ TODO:
+ - add sampler using ZN439E
+
+**********************************************************************/
+
+#include "emu.h"
+#include "midi.h"
+#include "bus/midi/midi.h"
+
+
+//**************************************************************************
+// DEVICE DEFINITIONS
+//**************************************************************************
+
+DEFINE_DEVICE_TYPE(ARC_SERIAL_MIDI, arc_serial_midi_device, "arc_serial_midi", "The Serial Port MIDI Interface");
+DEFINE_DEVICE_TYPE(ARC_SERIAL_SAMPLER, arc_serial_sampler_device, "arc_serial_sampler", "The Serial Port Sampler and MIDI Interface");
+
+
+//-------------------------------------------------
+// device_add_mconfig - add device configuration
+//-------------------------------------------------
+
+void arc_serial_midi_device::device_add_mconfig(machine_config &config)
+{
+ MC6854(config, m_adlc);
+ m_adlc->out_txd_cb().set("mdout", FUNC(midi_port_device::write_txd));
+ m_adlc->out_irq_cb().set(DEVICE_SELF_OWNER, FUNC(archimedes_econet_slot_device::efiq_w));
+
+ midi_port_device &mdin(MIDI_PORT(config, "mdin", midiin_slot, "midiin"));
+ mdin.rxd_handler().set(m_adlc, FUNC(mc6854_device::set_rx));
+ MIDI_PORT(config, "mdout", midiout_slot, "midiout");
+}
+
+void arc_serial_sampler_device::device_add_mconfig(machine_config &config)
+{
+ arc_serial_midi_device::device_add_mconfig(config);
+
+ // ZN439E
+}
+
+
+//**************************************************************************
+// LIVE DEVICE
+//**************************************************************************
+
+//-------------------------------------------------
+// arc_serial_midi_device - constructor
+//-------------------------------------------------
+
+arc_serial_midi_device::arc_serial_midi_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_econet_interface(mconfig, *this)
+ , m_adlc(*this, "mc6854")
+{
+}
+
+arc_serial_midi_device::arc_serial_midi_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock)
+ : arc_serial_midi_device(mconfig, ARC_SERIAL_MIDI, tag, owner, clock)
+{
+}
+
+arc_serial_sampler_device::arc_serial_sampler_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock)
+ : arc_serial_midi_device(mconfig, ARC_SERIAL_SAMPLER, tag, owner, clock)
+{
+}
+
+
+//-------------------------------------------------
+// device_start - device-specific startup
+//-------------------------------------------------
+
+void arc_serial_midi_device::device_start()
+{
+}
+
+//**************************************************************************
+// IMPLEMENTATION
+//**************************************************************************
+
+u8 arc_serial_midi_device::read(offs_t offset)
+{
+ return m_adlc->read(offset);
+}
+
+void arc_serial_midi_device::write(offs_t offset, u8 data)
+{
+ m_adlc->write(offset, data);
+}
diff --git a/src/devices/bus/archimedes/econet/midi.h b/src/devices/bus/archimedes/econet/midi.h
new file mode 100644
index 00000000000..da078f91d6a
--- /dev/null
+++ b/src/devices/bus/archimedes/econet/midi.h
@@ -0,0 +1,73 @@
+// license:BSD-3-Clause
+// copyright-holders:Nigel Barnes
+/**********************************************************************
+
+ The Serial Port MIDI Interface
+
+**********************************************************************/
+
+
+#ifndef MAME_BUS_ARCHIMEDES_ECONET_MIDI_H
+#define MAME_BUS_ARCHIMEDES_ECONET_MIDI_H
+
+#pragma once
+
+
+#include "slot.h"
+#include "machine/mc6854.h"
+
+
+//**************************************************************************
+// TYPE DEFINITIONS
+//**************************************************************************
+
+// ======================> arc_serial_midi_device
+
+class arc_serial_midi_device:
+ public device_t,
+ public device_archimedes_econet_interface
+{
+public:
+ // construction/destruction
+ arc_serial_midi_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock);
+
+protected:
+ arc_serial_midi_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, u32 clock);
+
+ // device-level overrides
+ virtual void device_start() override ATTR_COLD;
+
+ // optional information overrides
+ virtual void device_add_mconfig(machine_config &config) override ATTR_COLD;
+
+ virtual u8 read(offs_t offset) override;
+ virtual void write(offs_t offset, u8 data) override;
+
+private:
+ required_device<mc6854_device> m_adlc;
+};
+
+
+// ======================> arc_serial_sampler_device
+
+class arc_serial_sampler_device: public arc_serial_midi_device
+{
+public:
+ // construction/destruction
+ arc_serial_sampler_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock);
+
+ static constexpr feature_type unemulated_features() { return feature::CAPTURE; }
+
+protected:
+ // optional information overrides
+ virtual void device_add_mconfig(machine_config &config) override ATTR_COLD;
+};
+
+
+
+// device type definition
+DECLARE_DEVICE_TYPE(ARC_SERIAL_MIDI, arc_serial_midi_device);
+DECLARE_DEVICE_TYPE(ARC_SERIAL_SAMPLER, arc_serial_sampler_device);
+
+
+#endif /* MAME_BUS_ARCHIMEDES_ECONET_MIDI_H */
diff --git a/src/devices/bus/archimedes/econet/rtfmjoy.cpp b/src/devices/bus/archimedes/econet/rtfmjoy.cpp
new file mode 100644
index 00000000000..c53e7c155da
--- /dev/null
+++ b/src/devices/bus/archimedes/econet/rtfmjoy.cpp
@@ -0,0 +1,94 @@
+// license:BSD-3-Clause
+// copyright-holders:Nigel Barnes
+/**********************************************************************
+
+ Acorn Archimedes RTFM Joystick Interface
+
+**********************************************************************/
+
+#include "emu.h"
+#include "rtfmjoy.h"
+
+
+//**************************************************************************
+// DEVICE DEFINITIONS
+//**************************************************************************
+
+DEFINE_DEVICE_TYPE(ARC_RTFM_JOY, arc_rtfm_joystick_device, "arc_rtfmjoy", "Acorn Archimedes RTFM Joystick Interface");
+
+
+//-------------------------------------------------
+// INPUT_PORTS( rtfm_joystick )
+//-------------------------------------------------
+
+static INPUT_PORTS_START( rtfm_joystick )
+ PORT_START("JOY0")
+ PORT_BIT(0x01, IP_ACTIVE_LOW, IPT_JOYSTICK_RIGHT) PORT_8WAY PORT_PLAYER(1)
+ PORT_BIT(0x02, IP_ACTIVE_LOW, IPT_JOYSTICK_LEFT) PORT_8WAY PORT_PLAYER(1)
+ PORT_BIT(0x04, IP_ACTIVE_LOW, IPT_JOYSTICK_DOWN) PORT_8WAY PORT_PLAYER(1)
+ PORT_BIT(0x08, IP_ACTIVE_LOW, IPT_JOYSTICK_UP) PORT_8WAY PORT_PLAYER(1)
+ PORT_BIT(0x10, IP_ACTIVE_LOW, IPT_BUTTON1) PORT_NAME("Fire") PORT_PLAYER(1)
+
+ PORT_START("JOY1")
+ PORT_BIT(0x01, IP_ACTIVE_LOW, IPT_JOYSTICK_RIGHT) PORT_8WAY PORT_PLAYER(2)
+ PORT_BIT(0x02, IP_ACTIVE_LOW, IPT_JOYSTICK_LEFT) PORT_8WAY PORT_PLAYER(2)
+ PORT_BIT(0x04, IP_ACTIVE_LOW, IPT_JOYSTICK_DOWN) PORT_8WAY PORT_PLAYER(2)
+ PORT_BIT(0x08, IP_ACTIVE_LOW, IPT_JOYSTICK_UP) PORT_8WAY PORT_PLAYER(2)
+ PORT_BIT(0x10, IP_ACTIVE_LOW, IPT_BUTTON1) PORT_NAME("Fire") PORT_PLAYER(2)
+INPUT_PORTS_END
+
+
+//-------------------------------------------------
+// input_ports - device-specific input ports
+//-------------------------------------------------
+
+ioport_constructor arc_rtfm_joystick_device::device_input_ports() const
+{
+ return INPUT_PORTS_NAME( rtfm_joystick );
+}
+
+
+//**************************************************************************
+// LIVE DEVICE
+//**************************************************************************
+
+//-------------------------------------------------
+// archimedes_rtfm_joystick_device - constructor
+//-------------------------------------------------
+
+arc_rtfm_joystick_device::arc_rtfm_joystick_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock)
+ : device_t(mconfig, ARC_RTFM_JOY, tag, owner, clock)
+ , device_archimedes_econet_interface(mconfig, *this)
+ , m_joy(*this, "JOY%u", 0U)
+{
+}
+
+
+//-------------------------------------------------
+// device_start - device-specific startup
+//-------------------------------------------------
+
+void arc_rtfm_joystick_device::device_start()
+{
+}
+
+//**************************************************************************
+// IMPLEMENTATION
+//**************************************************************************
+
+u8 arc_rtfm_joystick_device::read(offs_t offset)
+{
+ u8 data = 0xff;
+
+ switch (offset & 0x03)
+ {
+ case 0x01:
+ data = ~m_joy[0]->read() & 0x1f;
+ break;
+ case 0x02:
+ data = ~m_joy[1]->read() & 0x1f;
+ break;
+ }
+
+ return data;
+}
diff --git a/src/devices/bus/archimedes/econet/rtfmjoy.h b/src/devices/bus/archimedes/econet/rtfmjoy.h
new file mode 100644
index 00000000000..63319512464
--- /dev/null
+++ b/src/devices/bus/archimedes/econet/rtfmjoy.h
@@ -0,0 +1,50 @@
+// license:BSD-3-Clause
+// copyright-holders:Nigel Barnes
+/**********************************************************************
+
+ Acorn Archimedes RTFM Joystick Interface
+
+**********************************************************************/
+
+
+#ifndef MAME_BUS_ARCHIMEDES_ECONET_RTFMJOY_H
+#define MAME_BUS_ARCHIMEDES_ECONET_RTFMJOY_H
+
+#pragma once
+
+
+#include "slot.h"
+
+
+
+//**************************************************************************
+// TYPE DEFINITIONS
+//**************************************************************************
+
+class arc_rtfm_joystick_device:
+ public device_t,
+ public device_archimedes_econet_interface
+{
+public:
+ // construction/destruction
+ arc_rtfm_joystick_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock);
+
+protected:
+ // device-level overrides
+ virtual void device_start() override ATTR_COLD;
+
+ // optional information overrides
+ virtual ioport_constructor device_input_ports() const override ATTR_COLD;
+
+ virtual u8 read(offs_t offset) override;
+
+private:
+ required_ioport_array<2> m_joy;
+};
+
+
+// device type definition
+DECLARE_DEVICE_TYPE(ARC_RTFM_JOY, arc_rtfm_joystick_device);
+
+
+#endif /* MAME_BUS_ARCHIMEDES_ECONET_RTFMJOY_H */
diff --git a/src/devices/bus/archimedes/econet/slot.cpp b/src/devices/bus/archimedes/econet/slot.cpp
new file mode 100644
index 00000000000..c6417eeb268
--- /dev/null
+++ b/src/devices/bus/archimedes/econet/slot.cpp
@@ -0,0 +1,102 @@
+// license:BSD-3-Clause
+// copyright-holders:Nigel Barnes
+/**********************************************************************
+
+ Acorn Archimedes Econet Module
+
+**********************************************************************/
+
+#include "emu.h"
+#include "slot.h"
+
+
+//**************************************************************************
+// DEVICE DEFINITIONS
+//**************************************************************************
+
+DEFINE_DEVICE_TYPE(ARCHIMEDES_ECONET_SLOT, archimedes_econet_slot_device, "archimedes_econet_slot", "Acorn Archimedes Econet Module slot")
+
+
+
+//**************************************************************************
+// DEVICE BBC_MODEM PORT INTERFACE
+//**************************************************************************
+
+//-------------------------------------------------
+// device_archimedes_econet_interface - constructor
+//-------------------------------------------------
+
+device_archimedes_econet_interface::device_archimedes_econet_interface(const machine_config &mconfig, device_t &device) :
+ device_interface(device, "arceconet")
+{
+ m_slot = dynamic_cast<archimedes_econet_slot_device *>(device.owner());
+}
+
+
+//**************************************************************************
+// LIVE DEVICE
+//**************************************************************************
+
+//-------------------------------------------------
+// archimedes_econet_slot_device - constructor
+//-------------------------------------------------
+
+archimedes_econet_slot_device::archimedes_econet_slot_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock)
+ : device_t(mconfig, ARCHIMEDES_ECONET_SLOT, tag, owner, clock)
+ , device_single_card_slot_interface<device_archimedes_econet_interface>(mconfig, *this)
+ , m_device(nullptr)
+ , m_efiq_handler(*this)
+{
+}
+
+
+//-------------------------------------------------
+// device_start - device-specific startup
+//-------------------------------------------------
+
+void archimedes_econet_slot_device::device_start()
+{
+ m_device = get_card_device();
+}
+
+
+//-------------------------------------------------
+// read
+//-------------------------------------------------
+
+u8 archimedes_econet_slot_device::read(offs_t offset)
+{
+ if (m_device)
+ return m_device->read(offset & 0x03);
+ else
+ return 0xff;
+}
+
+//-------------------------------------------------
+// write
+//-------------------------------------------------
+
+void archimedes_econet_slot_device::write(offs_t offset, u8 data)
+{
+ if (m_device)
+ m_device->write(offset & 0x03, data);
+}
+
+//-------------------------------------------------
+// SLOT_INTERFACE( archimedes_econet_devices )
+//-------------------------------------------------
+
+
+// slot devices
+#include "econet.h"
+#include "midi.h"
+#include "rtfmjoy.h"
+
+
+void archimedes_econet_devices(device_slot_interface &device)
+{
+ device.option_add("econet", ARC_ECONET);
+ device.option_add("midi", ARC_SERIAL_MIDI);
+ device.option_add("rtfmjoy", ARC_RTFM_JOY);
+ device.option_add("sampler", ARC_SERIAL_SAMPLER);
+}
diff --git a/src/devices/bus/archimedes/econet/slot.h b/src/devices/bus/archimedes/econet/slot.h
new file mode 100644
index 00000000000..bd6353f45e9
--- /dev/null
+++ b/src/devices/bus/archimedes/econet/slot.h
@@ -0,0 +1,102 @@
+// license:BSD-3-Clause
+// copyright-holders:Nigel Barnes
+/**********************************************************************
+
+ Acorn Archimedes Econet Module
+
+**********************************************************************
+
+ Pinout:
+
+ 1 NEFIQ
+ 2 NWBE
+ 3 NS2
+ 4 CLK2
+ 5 LA2
+ 6 LA3
+ 7 BD0
+ 8 BD1
+ 9 BD2
+ 10 BD3
+ 11 BD4
+ 12 BD5
+ 13 BD6
+ 14 BD7
+ 15 NRST
+ 16 0V
+ 17 +5V
+
+**********************************************************************/
+
+#ifndef MAME_BUS_ARCHIMEDES_ECONET_SLOT_H
+#define MAME_BUS_ARCHIMEDES_ECONET_SLOT_H
+
+#pragma once
+
+
+
+//**************************************************************************
+// TYPE DEFINITIONS
+//**************************************************************************
+
+// ======================> archimedes_econet_slot_device
+
+class device_archimedes_econet_interface;
+
+class archimedes_econet_slot_device : public device_t, public device_single_card_slot_interface<device_archimedes_econet_interface>
+{
+public:
+ // construction/destruction
+ template <typename T>
+ archimedes_econet_slot_device(machine_config const &mconfig, char const *tag, device_t *owner, T &&slot_options, const char *default_option)
+ : archimedes_econet_slot_device(mconfig, tag, owner)
+ {
+ option_reset();
+ slot_options(*this);
+ set_default_option(default_option);
+ set_fixed(false);
+ }
+
+ archimedes_econet_slot_device(machine_config const &mconfig, char const *tag, device_t *owner, u32 clock = 0);
+
+ // callbacks
+ auto efiq_handler() { return m_efiq_handler.bind(); }
+
+ virtual u8 read(offs_t offset);
+ virtual void write(offs_t offset, u8 data);
+
+ void efiq_w(int state) { m_efiq_handler(state); }
+
+protected:
+ // device-level overrides
+ virtual void device_start() override ATTR_COLD;
+
+ device_archimedes_econet_interface *m_device;
+
+private:
+ devcb_write_line m_efiq_handler;
+};
+
+
+// ======================> device_archimedes_econet_interface
+
+class device_archimedes_econet_interface : public device_interface
+{
+public:
+ virtual u8 read(offs_t offset) { return 0xff; }
+ virtual void write(offs_t offset, u8 data) { }
+
+protected:
+ device_archimedes_econet_interface(const machine_config &mconfig, device_t &device);
+
+ archimedes_econet_slot_device *m_slot;
+};
+
+
+// device type definition
+DECLARE_DEVICE_TYPE(ARCHIMEDES_ECONET_SLOT, archimedes_econet_slot_device)
+
+void archimedes_econet_devices(device_slot_interface &device);
+
+
+#endif // MAME_BUS_ARCHIMEDES_ECONET_SLOT_H
diff --git a/src/devices/bus/archimedes/podule/a448.cpp b/src/devices/bus/archimedes/podule/a448.cpp
new file mode 100644
index 00000000000..b4f3b99037d
--- /dev/null
+++ b/src/devices/bus/archimedes/podule/a448.cpp
@@ -0,0 +1,159 @@
+// license:BSD-3-Clause
+// copyright-holders:Nigel Barnes
+/**********************************************************************
+
+ Armadillo Systems A448 Sound Sampler
+
+ http://chrisacorns.computinghistory.org.uk/32bit_UpgradesA2G/Armadillo_A448.html
+
+ TODO:
+ - everything, requires driver software to determine how hardware is accessed.
+
+**********************************************************************/
+
+#include "emu.h"
+#include "a448.h"
+#include "bus/midi/midi.h"
+
+
+namespace {
+
+// ======================> arc_a448_device
+
+class arc_a448_device :
+ public device_t,
+ public device_archimedes_podule_interface
+{
+public:
+ static constexpr feature_type unemulated_features() { return feature::CAPTURE; }
+
+ // construction/destruction
+ arc_a448_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock);
+
+protected:
+ arc_a448_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, u32 clock);
+
+ // device-level overrides
+ virtual void device_start() override ATTR_COLD;
+
+ // optional information overrides
+ virtual void device_add_mconfig(machine_config &config) override ATTR_COLD;
+ virtual const tiny_rom_entry *device_rom_region() const override ATTR_COLD;
+
+ // device_archimedes_podule_interface overrides
+ virtual void ioc_map(address_map &map) override ATTR_COLD;
+
+private:
+ required_memory_region m_podule_rom;
+};
+
+
+// ======================> arc_a448b_device
+
+class arc_a448b_device : public arc_a448_device
+{
+public:
+ // construction/destruction
+ arc_a448b_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock);
+
+protected:
+ // optional information overrides
+ virtual void device_add_mconfig(machine_config &config) override ATTR_COLD;
+ virtual const tiny_rom_entry *device_rom_region() const override ATTR_COLD;
+};
+
+
+void arc_a448_device::ioc_map(address_map &map)
+{
+ map(0x0000, 0x1fff).lr8(NAME([this](offs_t offset) { return m_podule_rom->base()[offset]; })).umask32(0x000000ff);
+}
+
+
+//-------------------------------------------------
+// ROM( a448 )
+//-------------------------------------------------
+
+ROM_START( a448 )
+ ROM_REGION(0x1000, "podule_rom", 0)
+ ROM_LOAD("a448.rom", 0x0000, 0x1000, CRC(e1988e76) SHA1(8140e9cf82dc67324963766d33efd5c8ad6d53f8))
+ROM_END
+
+ROM_START( a448b )
+ ROM_REGION(0x4000, "podule_rom", 0)
+ ROM_LOAD("a448b_midi.rom", 0x0000, 0x4000, CRC(864f7967) SHA1(125b5a505498d91ca049f95fd05e693b2396bda6))
+ROM_END
+
+const tiny_rom_entry *arc_a448_device::device_rom_region() const
+{
+ return ROM_NAME( a448 );
+}
+
+const tiny_rom_entry *arc_a448b_device::device_rom_region() const
+{
+ return ROM_NAME( a448b );
+}
+
+
+//-------------------------------------------------
+// device_add_mconfig - add device configuration
+//-------------------------------------------------
+
+void arc_a448_device::device_add_mconfig(machine_config &config)
+{
+ //ZN448(config, "zn448", 0);
+}
+
+void arc_a448b_device::device_add_mconfig(machine_config &config)
+{
+ arc_a448_device::device_add_mconfig(config);
+
+ midi_port_device &mdin(MIDI_PORT(config, "mdin", midiin_slot, "midiin"));
+ mdin.rxd_handler().set("mdthru", FUNC(midi_port_device::write_txd));
+ midiout_slot(MIDI_PORT(config, "mdthru"));
+ midiout_slot(MIDI_PORT(config, "mdout"));
+}
+
+
+//**************************************************************************
+// LIVE DEVICE
+//**************************************************************************
+
+//-------------------------------------------------
+// arc_a448_device - constructor
+//-------------------------------------------------
+
+arc_a448_device::arc_a448_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")
+{
+}
+
+arc_a448_device::arc_a448_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock)
+ : arc_a448_device(mconfig, ARC_A448, tag, owner, clock)
+{
+}
+
+arc_a448b_device::arc_a448b_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock)
+ : arc_a448_device(mconfig, ARC_A448B, tag, owner, clock)
+{
+}
+
+
+//-------------------------------------------------
+// device_start - device-specific startup
+//-------------------------------------------------
+
+void arc_a448_device::device_start()
+{
+}
+
+} // anonymous namespace
+
+
+//**************************************************************************
+// DEVICE DEFINITIONS
+//**************************************************************************
+
+DEFINE_DEVICE_TYPE_PRIVATE(ARC_A448, device_archimedes_podule_interface, arc_a448_device, "arc_a448", "Armadillo Systems A448 Sound Sampler")
+DEFINE_DEVICE_TYPE_PRIVATE(ARC_A448B, device_archimedes_podule_interface, arc_a448b_device, "arc_a448b", "Armadillo Systems A448b Stereo MIDI Sound Sampler")
diff --git a/src/devices/bus/archimedes/podule/a448.h b/src/devices/bus/archimedes/podule/a448.h
new file mode 100644
index 00000000000..a207c2eafd3
--- /dev/null
+++ b/src/devices/bus/archimedes/podule/a448.h
@@ -0,0 +1,20 @@
+// license:BSD-3-Clause
+// copyright-holders:Nigel Barnes
+/**********************************************************************
+
+ Armadillo Systems A448 Sound Sampler
+
+**********************************************************************/
+
+#ifndef MAME_BUS_ARCHIMEDES_PODULE_A448_H
+#define MAME_BUS_ARCHIMEDES_PODULE_A448_H
+
+#pragma once
+
+#include "slot.h"
+
+// device type definition
+DECLARE_DEVICE_TYPE(ARC_A448, device_archimedes_podule_interface)
+DECLARE_DEVICE_TYPE(ARC_A448B, device_archimedes_podule_interface)
+
+#endif // MAME_BUS_ARCHIMEDES_PODULE_A448_H
diff --git a/src/devices/bus/archimedes/podule/acejoy.cpp b/src/devices/bus/archimedes/podule/acejoy.cpp
new file mode 100644
index 00000000000..e1b33462af0
--- /dev/null
+++ b/src/devices/bus/archimedes/podule/acejoy.cpp
@@ -0,0 +1,122 @@
+// license:BSD-3-Clause
+// copyright-holders:Nigel Barnes
+/**********************************************************************
+
+ Acorn Computer Enterprises Joy Connect
+
+ http://chrisacorns.computinghistory.org.uk/32bit_UpgradesA2G/ACE_JoyConnect.html
+
+**********************************************************************/
+
+#include "emu.h"
+#include "acejoy.h"
+
+
+namespace {
+
+class arc_acejoy_device :
+ public device_t,
+ public device_archimedes_podule_interface
+{
+public:
+ // construction/destruction
+ arc_acejoy_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock);
+
+protected:
+ // device-level overrides
+ virtual void device_start() override { }
+
+ // optional information overrides
+ virtual const tiny_rom_entry *device_rom_region() const override ATTR_COLD;
+ virtual ioport_constructor device_input_ports() const override ATTR_COLD;
+
+ // device_archimedes_podule_interface overrides
+ virtual void ioc_map(address_map &map) override
+ {
+ map(0x0000, 0x1fff).lr8(NAME([this](offs_t offset) { return m_podule_rom->base()[offset]; })).umask32(0x000000ff);
+ map(0x2008, 0x200b).portr(m_joy[0]);
+ map(0x200c, 0x200f).portr(m_joy[1]);
+ }
+
+private:
+ required_memory_region m_podule_rom;
+ required_ioport_array<2> m_joy;
+};
+
+
+//-------------------------------------------------
+// ROM( acejoy )
+//-------------------------------------------------
+
+ROM_START( acejoy )
+ ROM_REGION(0x1000, "podule_rom", 0)
+ ROM_LOAD("acejoy.bin", 0x0000, 0x1000, CRC(300c4aa8) SHA1(1addf507844c6590d111765051a43fe571491224))
+ROM_END
+
+const tiny_rom_entry *arc_acejoy_device::device_rom_region() const
+{
+ return ROM_NAME( acejoy );
+}
+
+
+//-------------------------------------------------
+// INPUT_PORTS( acejoy )
+//-------------------------------------------------
+
+static INPUT_PORTS_START( acejoy )
+ PORT_START("JOY0")
+ PORT_BIT(0x01, IP_ACTIVE_LOW, IPT_JOYSTICK_UP) PORT_8WAY PORT_PLAYER(1)
+ PORT_BIT(0x02, IP_ACTIVE_LOW, IPT_JOYSTICK_DOWN) PORT_8WAY PORT_PLAYER(1)
+ PORT_BIT(0x04, IP_ACTIVE_LOW, IPT_JOYSTICK_LEFT) PORT_8WAY PORT_PLAYER(1)
+ PORT_BIT(0x08, IP_ACTIVE_LOW, IPT_JOYSTICK_RIGHT) PORT_8WAY PORT_PLAYER(1)
+ PORT_BIT(0x10, IP_ACTIVE_LOW, IPT_BUTTON1) PORT_PLAYER(1)
+ PORT_BIT(0x20, IP_ACTIVE_LOW, IPT_BUTTON2) PORT_PLAYER(1)
+ PORT_BIT(0x40, IP_ACTIVE_LOW, IPT_BUTTON3) PORT_PLAYER(1)
+ PORT_BIT(0x80, IP_ACTIVE_HIGH, IPT_UNUSED )
+
+ PORT_START("JOY1")
+ PORT_BIT(0x01, IP_ACTIVE_LOW, IPT_JOYSTICK_UP) PORT_8WAY PORT_PLAYER(2)
+ PORT_BIT(0x02, IP_ACTIVE_LOW, IPT_JOYSTICK_DOWN) PORT_8WAY PORT_PLAYER(2)
+ PORT_BIT(0x04, IP_ACTIVE_LOW, IPT_JOYSTICK_LEFT) PORT_8WAY PORT_PLAYER(2)
+ PORT_BIT(0x08, IP_ACTIVE_LOW, IPT_JOYSTICK_RIGHT) PORT_8WAY PORT_PLAYER(2)
+ PORT_BIT(0x10, IP_ACTIVE_LOW, IPT_BUTTON1) PORT_PLAYER(2)
+ PORT_BIT(0x20, IP_ACTIVE_LOW, IPT_BUTTON2) PORT_PLAYER(2)
+ PORT_BIT(0x40, IP_ACTIVE_LOW, IPT_BUTTON3) PORT_PLAYER(2)
+ PORT_BIT(0x80, IP_ACTIVE_HIGH, IPT_UNUSED )
+INPUT_PORTS_END
+
+
+//-------------------------------------------------
+// input_ports - device-specific input ports
+//-------------------------------------------------
+
+ioport_constructor arc_acejoy_device::device_input_ports() const
+{
+ return INPUT_PORTS_NAME( acejoy );
+}
+
+
+//**************************************************************************
+// LIVE DEVICE
+//**************************************************************************
+
+//-------------------------------------------------
+// arc_acejoy_device - constructor
+//-------------------------------------------------
+
+arc_acejoy_device::arc_acejoy_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock)
+ : device_t(mconfig, ARC_ACEJOY, tag, owner, clock)
+ , device_archimedes_podule_interface(mconfig, *this)
+ , m_podule_rom(*this, "podule_rom")
+ , m_joy(*this, "JOY%u", 0U)
+{
+}
+
+} // anonymous namespace
+
+
+//**************************************************************************
+// DEVICE DEFINITIONS
+//**************************************************************************
+
+DEFINE_DEVICE_TYPE_PRIVATE(ARC_ACEJOY, device_archimedes_podule_interface, arc_acejoy_device, "arc_acejoy", "ACE Joy Connect")
diff --git a/src/devices/bus/archimedes/podule/acejoy.h b/src/devices/bus/archimedes/podule/acejoy.h
new file mode 100644
index 00000000000..1f822ed8803
--- /dev/null
+++ b/src/devices/bus/archimedes/podule/acejoy.h
@@ -0,0 +1,19 @@
+// license:BSD-3-Clause
+// copyright-holders:Nigel Barnes
+/**********************************************************************
+
+ Acorn Computer Enterprises Joy Connect
+
+**********************************************************************/
+
+#ifndef MAME_BUS_ARCHIMEDES_PODULE_ACEJOY_H
+#define MAME_BUS_ARCHIMEDES_PODULE_ACEJOY_H
+
+#pragma once
+
+#include "slot.h"
+
+// device type definition
+DECLARE_DEVICE_TYPE(ARC_ACEJOY, device_archimedes_podule_interface)
+
+#endif // MAME_BUS_ARCHIMEDES_PODULE_ACEJOY_H
diff --git a/src/devices/bus/archimedes/podule/armadeus.cpp b/src/devices/bus/archimedes/podule/armadeus.cpp
new file mode 100644
index 00000000000..462cc8a48e7
--- /dev/null
+++ b/src/devices/bus/archimedes/podule/armadeus.cpp
@@ -0,0 +1,111 @@
+// license:BSD-3-Clause
+// copyright-holders:Nigel Barnes
+/**********************************************************************
+
+ Clares Armadeus Sampler Board
+
+ http://chrisacorns.computinghistory.org.uk/32bit_UpgradesA2G/Clares_SoundSampler.html
+
+**********************************************************************/
+
+#include "emu.h"
+#include "armadeus.h"
+#include "sound/dac.h"
+#include "speaker.h"
+
+
+namespace {
+
+class arc_armadeus_device :
+ public device_t,
+ public device_archimedes_podule_interface
+{
+public:
+ static constexpr feature_type unemulated_features() { return feature::CAPTURE; }
+
+ // construction/destruction
+ arc_armadeus_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock);
+
+protected:
+ // device-level overrides
+ virtual void device_start() override ATTR_COLD;
+
+ // optional information overrides
+ virtual void device_add_mconfig(machine_config &config) override ATTR_COLD;
+ virtual const tiny_rom_entry *device_rom_region() const override ATTR_COLD;
+
+ // device_archimedes_podule_interface overrides
+ virtual void ioc_map(address_map &map) override ATTR_COLD;
+
+private:
+ required_memory_region m_podule_rom;
+};
+
+
+void arc_armadeus_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, 0x2000).w("dac", FUNC(zn428e_device::data_w));
+}
+
+
+//-------------------------------------------------
+// ROM( armadeus )
+//-------------------------------------------------
+
+ROM_START( armadeus )
+ ROM_REGION(0x0800, "podule_rom", 0)
+ ROM_LOAD("sound_sampler_issue_0.20.rom", 0x0000, 0x0800, CRC(dc41cfd9) SHA1(6129d91bcd21bdab75f1293f9daa7612feaffc4b))
+ROM_END
+
+const tiny_rom_entry *arc_armadeus_device::device_rom_region() const
+{
+ return ROM_NAME( armadeus );
+}
+
+
+//-------------------------------------------------
+// device_add_mconfig - add device configuration
+//-------------------------------------------------
+
+void arc_armadeus_device::device_add_mconfig(machine_config &config)
+{
+ SPEAKER(config, "speaker").front_center();
+ ZN428E(config, "dac", 0).add_route(ALL_OUTPUTS, "speaker", 0.5);
+
+ //ZN448(config, "zn448", 0);
+}
+
+
+//**************************************************************************
+// LIVE DEVICE
+//**************************************************************************
+
+//-------------------------------------------------
+// arc_armadeus_device - constructor
+//-------------------------------------------------
+
+arc_armadeus_device::arc_armadeus_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock)
+ : device_t(mconfig, ARC_ARMADEUS, tag, owner, clock)
+ , device_archimedes_podule_interface(mconfig, *this)
+ , m_podule_rom(*this, "podule_rom")
+{
+}
+
+
+//-------------------------------------------------
+// device_start - device-specific startup
+//-------------------------------------------------
+
+void arc_armadeus_device::device_start()
+{
+}
+
+} // anonymous namespace
+
+
+//**************************************************************************
+// DEVICE DEFINITIONS
+//**************************************************************************
+
+DEFINE_DEVICE_TYPE_PRIVATE(ARC_ARMADEUS, device_archimedes_podule_interface, arc_armadeus_device, "arc_armadeus", "Clares Armadeus Sampler Board")
diff --git a/src/devices/bus/archimedes/podule/armadeus.h b/src/devices/bus/archimedes/podule/armadeus.h
new file mode 100644
index 00000000000..2c45ae56e37
--- /dev/null
+++ b/src/devices/bus/archimedes/podule/armadeus.h
@@ -0,0 +1,19 @@
+// license:BSD-3-Clause
+// copyright-holders:Nigel Barnes
+/**********************************************************************
+
+ Clares Armadeus Sampler Board
+
+**********************************************************************/
+
+#ifndef MAME_BUS_ARCHIMEDES_PODULE_ARMADEUS_H
+#define MAME_BUS_ARCHIMEDES_PODULE_ARMADEUS_H
+
+#pragma once
+
+#include "slot.h"
+
+// device type definition
+DECLARE_DEVICE_TYPE(ARC_ARMADEUS, device_archimedes_podule_interface)
+
+#endif // MAME_BUS_ARCHIMEDES_PODULE_ARMADEUS_H
diff --git a/src/devices/bus/archimedes/podule/eaglem2.cpp b/src/devices/bus/archimedes/podule/eaglem2.cpp
new file mode 100644
index 00000000000..116dc20efd1
--- /dev/null
+++ b/src/devices/bus/archimedes/podule/eaglem2.cpp
@@ -0,0 +1,156 @@
+// license:BSD-3-Clause
+// copyright-holders:Nigel Barnes
+/**********************************************************************
+
+ Wild Vision/Computer Concepts Eagle M2
+
+ http://chrisacorns.computinghistory.org.uk/32bit_UpgradesA2G/CC_Eagle.html
+
+ Main components:
+ - Am7202A x 2 High Density First-In First-Out
+ - M514221B x 4
+ - SAA7191B Digital Multistandard ColourDecoder
+ - SAA7186 Digital video scaler
+ - SAA7197 Clock Generator Circuit
+ - TDA8708B Video analog input interface
+ - TDA8709A Video analog input interface
+ - YMZ263B Multimedia Audio & Game Interface Controller
+
+ TODO:
+ - everything, it's complex and not documented.
+
+**********************************************************************/
+
+#include "emu.h"
+#include "eaglem2.h"
+#include "machine/7200fifo.h"
+#include "machine/saa7191.h"
+#include "bus/midi/midi.h"
+#include "imagedev/avivideo.h"
+#include "speaker.h"
+
+
+namespace {
+
+class arc_eaglem2_device :
+ public device_t,
+ public device_archimedes_podule_interface
+{
+public:
+ // construction/destruction
+ arc_eaglem2_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock);
+
+ static constexpr feature_type unemulated_features() { return feature::CAPTURE | feature::SOUND; }
+
+protected:
+ // device-level overrides
+ virtual void device_start() override ATTR_COLD;
+ virtual void device_reset() override ATTR_COLD;
+
+ // optional information overrides
+ virtual void device_add_mconfig(machine_config &config) override ATTR_COLD;
+ virtual const tiny_rom_entry *device_rom_region() const override ATTR_COLD;
+
+ // device_archimedes_podule_interface overrides
+ virtual void ioc_map(address_map &map) override ATTR_COLD;
+
+private:
+ required_memory_region m_podule_rom;
+ required_device<saa7191_device> m_dmsd;
+ required_device<idt7202_device> m_fifo_in;
+ required_device<idt7202_device> m_fifo_out;
+ required_device<avivideo_image_device> m_avivideo;
+
+ u8 m_rom_page;
+};
+
+
+void arc_eaglem2_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) & 0x1f800)]; })).umask32(0x000000ff);
+ map(0x2000, 0x2000).lw8(NAME([this](u8 data) { m_rom_page = data; }));
+}
+
+
+//-------------------------------------------------
+// ROM( eagle )
+//-------------------------------------------------
+
+ROM_START( eagle )
+ ROM_REGION(0x20000, "podule_rom", 0)
+ ROM_LOAD("eagle.rom", 0x0000, 0x20000, CRC(9d9fa2e9) SHA1(b3633b8e1d58f59f5894d14a737c69b6d9d5d46d))
+ROM_END
+
+const tiny_rom_entry *arc_eaglem2_device::device_rom_region() const
+{
+ return ROM_NAME( eagle );
+}
+
+
+//-------------------------------------------------
+// device_add_mconfig - add device configuration
+//-------------------------------------------------
+
+void arc_eaglem2_device::device_add_mconfig(machine_config &config)
+{
+ SAA7191(config, m_dmsd);
+
+ IDT7202(config, m_fifo_in); // AM7202A
+ IDT7202(config, m_fifo_out); // AM7202A
+
+ IMAGE_AVIVIDEO(config, m_avivideo);
+
+ midi_port_device &mdin(MIDI_PORT(config, "mdin", midiin_slot, "midiin"));
+ mdin.rxd_handler().set("mdthru", FUNC(midi_port_device::write_txd));
+ midiout_slot(MIDI_PORT(config, "mdout"));
+ midiout_slot(MIDI_PORT(config, "mdthru"));
+}
+
+
+//**************************************************************************
+// LIVE DEVICE
+//**************************************************************************
+
+//-------------------------------------------------
+// arc_eaglem2_device - constructor
+//-------------------------------------------------
+
+arc_eaglem2_device::arc_eaglem2_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock)
+ : device_t(mconfig, ARC_EAGLEM2, tag, owner, clock)
+ , device_archimedes_podule_interface(mconfig, *this)
+ , m_podule_rom(*this, "podule_rom")
+ , m_dmsd(*this, "dmsd")
+ , m_fifo_in(*this, "fifo_in")
+ , m_fifo_out(*this, "fifo_out")
+ , m_avivideo(*this, "srcavi")
+ , m_rom_page(0)
+{
+}
+
+
+//-------------------------------------------------
+// device_start - device-specific startup
+//-------------------------------------------------
+
+void arc_eaglem2_device::device_start()
+{
+ save_item(NAME(m_rom_page));
+}
+
+//-------------------------------------------------
+// device_reset - device-specific reset
+//-------------------------------------------------
+
+void arc_eaglem2_device::device_reset()
+{
+ m_rom_page = 0x00;
+}
+
+} // anonymous namespace
+
+
+//**************************************************************************
+// DEVICE DEFINITIONS
+//**************************************************************************
+
+DEFINE_DEVICE_TYPE_PRIVATE(ARC_EAGLEM2, device_archimedes_podule_interface, arc_eaglem2_device, "arc_eaglem2", "Wild Vision/Computer Concepts Eagle M2")
diff --git a/src/devices/bus/archimedes/podule/eaglem2.h b/src/devices/bus/archimedes/podule/eaglem2.h
new file mode 100644
index 00000000000..829fb32f301
--- /dev/null
+++ b/src/devices/bus/archimedes/podule/eaglem2.h
@@ -0,0 +1,19 @@
+// license:BSD-3-Clause
+// copyright-holders:Nigel Barnes
+/**********************************************************************
+
+ Wild Vision/Computer Concepts Eagle M2
+
+**********************************************************************/
+
+#ifndef MAME_BUS_ARCHIMEDES_PODULE_EAGLEM2_H
+#define MAME_BUS_ARCHIMEDES_PODULE_EAGLEM2_H
+
+#pragma once
+
+#include "slot.h"
+
+// device type definition
+DECLARE_DEVICE_TYPE(ARC_EAGLEM2, device_archimedes_podule_interface)
+
+#endif // MAME_BUS_ARCHIMEDES_PODULE_EAGLEM2_H
diff --git a/src/devices/bus/archimedes/podule/ether1.cpp b/src/devices/bus/archimedes/podule/ether1.cpp
new file mode 100644
index 00000000000..20d96e89b28
--- /dev/null
+++ b/src/devices/bus/archimedes/podule/ether1.cpp
@@ -0,0 +1,184 @@
+// license:BSD-3-Clause
+// copyright-holders:Nigel Barnes
+/**********************************************************************
+
+ Acorn AKA25 Ethernet
+
+ http://chrisacorns.computinghistory.org.uk/32bit_UpgradesA2G/Acorn_AKA25_Ethernet.html
+
+**********************************************************************/
+
+#include "emu.h"
+#include "ether1.h"
+#include "machine/i82586.h"
+
+#include "multibyte.h"
+
+
+namespace {
+
+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_t overrides
+ virtual void device_start() override ATTR_COLD;
+ virtual void device_reset() override ATTR_COLD;
+
+ // optional information overrides
+ virtual void device_add_mconfig(machine_config &config) override ATTR_COLD;
+ virtual const tiny_rom_entry *device_rom_region() const override ATTR_COLD;
+
+ // device_archimedes_podule_interface overrides
+ virtual void ioc_map(address_map &map) override ATTR_COLD;
+
+private:
+ required_memory_region m_podule_rom;
+ required_shared_ptr<u16> m_ram;
+ required_device<i82586_device> m_lance;
+
+ void lan_map(address_map &map) ATTR_COLD;
+
+ void checksum();
+ void control_w(u8 data);
+
+ u8 m_rom_page;
+ u8 m_ram_page;
+};
+
+
+void arc_ether1_aka25_device::ioc_map(address_map &map)
+{
+ 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).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);
+}
+
+
+void arc_ether1_aka25_device::lan_map(address_map &map)
+{
+ map(0x000000, 0x00ffff).mirror(0xff0000).ram().share("ram");
+}
+
+
+//-------------------------------------------------
+// device_add_mconfig - add device configuration
+//-------------------------------------------------
+
+void arc_ether1_aka25_device::device_add_mconfig(machine_config &config)
+{
+ I82586(config, m_lance, 20_MHz_XTAL / 2);
+ m_lance->out_irq_cb().set([this](int state) { m_rom_page = state; set_pirq(state); });
+ m_lance->set_addrmap(0, &arc_ether1_aka25_device::lan_map);
+}
+
+
+//-------------------------------------------------
+// ROM( ether1_aka25 )
+//-------------------------------------------------
+
+ROM_START( ether1_aka25 )
+ ROM_REGION(0x20, "podule_rom", 0)
+ ROM_LOAD("27ls19.bin", 0x00, 0x20, CRC(e034ae68) SHA1(9a9404028d166d9cbb466513f514be5d3ea77956))
+ROM_END
+
+const tiny_rom_entry *arc_ether1_aka25_device::device_rom_region() const
+{
+ return ROM_NAME( ether1_aka25 );
+}
+
+
+//**************************************************************************
+// LIVE DEVICE
+//**************************************************************************
+
+//-------------------------------------------------
+// arc_ether1_aka25_device - constructor
+//-------------------------------------------------
+
+arc_ether1_aka25_device::arc_ether1_aka25_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock)
+ : device_t(mconfig, ARC_ETHER1_AKA25, tag, owner, clock)
+ , device_archimedes_podule_interface(mconfig, *this)
+ , m_podule_rom(*this, "podule_rom")
+ , m_ram(*this, "ram")
+ , m_lance(*this, "lance")
+ , m_rom_page(0)
+ , m_ram_page(0)
+{
+}
+
+
+//-------------------------------------------------
+// device_start - device-specific startup
+//-------------------------------------------------
+
+void arc_ether1_aka25_device::device_start()
+{
+ checksum();
+
+ save_item(NAME(m_rom_page));
+ save_item(NAME(m_ram_page));
+}
+
+//-------------------------------------------------
+// device_reset - device-specific reset
+//-------------------------------------------------
+
+void arc_ether1_aka25_device::device_reset()
+{
+ m_rom_page = 0x00;
+ m_ram_page = 0x00;
+}
+
+
+//**************************************************************************
+// IMPLEMENTATION
+//**************************************************************************
+
+void arc_ether1_aka25_device::checksum()
+{
+ // PROM CRC calculation (from A500/R200 Service Manual)
+ u32 chk = 0xffffffff;
+
+ for (int i = 0; i < 28; i++)
+ {
+ // CRC on bytes 0..28
+ u8 byte = m_podule_rom->base()[i];
+ for (int j = 0; j < 8; j++)
+ {
+ if (((byte & 1) ^ (chk >> 31)) != 0)
+ chk = (chk << 1) ^ (0x04c11db7);
+ else
+ chk = (chk << 1);
+
+ byte = byte >> 1;
+ }
+ }
+
+ // get CRC from PROM
+ 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");
+}
+
+void arc_ether1_aka25_device::control_w(u8 data)
+{
+ m_lance->reset_w(BIT(data, 0)); // b0 Reset
+ //m_sia->lpbk(BIT(data, 1)); // b1 Loop-Back
+ m_lance->ca(BIT(data, 2)); // b2 Channel Attention
+ if (BIT(data, 3)) set_pirq(0); // b3 Clear Interrupt
+}
+
+} // anonymous namespace
+
+
+//**************************************************************************
+// DEVICE DEFINITIONS
+//**************************************************************************
+
+DEFINE_DEVICE_TYPE_PRIVATE(ARC_ETHER1_AKA25, device_archimedes_podule_interface, arc_ether1_aka25_device, "arc_ether1_aka25", "Acorn AKA25 Ethernet")
diff --git a/src/devices/bus/archimedes/podule/ether1.h b/src/devices/bus/archimedes/podule/ether1.h
new file mode 100644
index 00000000000..05cd0a3fbb8
--- /dev/null
+++ b/src/devices/bus/archimedes/podule/ether1.h
@@ -0,0 +1,19 @@
+// license:BSD-3-Clause
+// copyright-holders:Nigel Barnes
+/**********************************************************************
+
+ Acorn AKA25 Ethernet
+
+**********************************************************************/
+
+#ifndef MAME_BUS_ARCHIMEDES_PODULE_ETHER1_H
+#define MAME_BUS_ARCHIMEDES_PODULE_ETHER1_H
+
+#pragma once
+
+#include "slot.h"
+
+// device type definition
+DECLARE_DEVICE_TYPE(ARC_ETHER1_AKA25, device_archimedes_podule_interface)
+
+#endif // MAME_BUS_ARCHIMEDES_PODULE_ETHER1_H
diff --git a/src/devices/bus/archimedes/podule/ether2.cpp b/src/devices/bus/archimedes/podule/ether2.cpp
new file mode 100644
index 00000000000..eee2eb19579
--- /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 ATTR_COLD;
+ virtual void device_reset() override ATTR_COLD;
+
+ // optional information overrides
+ virtual void device_add_mconfig(machine_config &config) override ATTR_COLD;
+ virtual const tiny_rom_entry *device_rom_region() const override ATTR_COLD;
+
+ // device_archimedes_podule_interface overrides
+ virtual void ioc_map(address_map &map) override ATTR_COLD;
+ virtual void memc_map(address_map &map) override ATTR_COLD;
+
+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..74f1e368769
--- /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 ATTR_COLD;
+ virtual void device_reset() override ATTR_COLD;
+
+ // optional information overrides
+ virtual void device_add_mconfig(machine_config &config) override ATTR_COLD;
+ virtual const tiny_rom_entry *device_rom_region() const override ATTR_COLD;
+
+ // device_archimedes_podule_interface overrides
+ virtual void ioc_map(address_map &map) override ATTR_COLD;
+
+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..a9f0d08d770
--- /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 ATTR_COLD;
+ virtual void device_reset() override ATTR_COLD;
+
+ // optional information overrides
+ virtual void device_add_mconfig(machine_config &config) override ATTR_COLD;
+ virtual const tiny_rom_entry *device_rom_region() const override ATTR_COLD;
+
+ // device_archimedes_podule_interface overrides
+ virtual void ioc_map(address_map &map) override ATTR_COLD;
+
+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/etherd.cpp b/src/devices/bus/archimedes/podule/etherd.cpp
new file mode 100644
index 00000000000..992545c5192
--- /dev/null
+++ b/src/devices/bus/archimedes/podule/etherd.cpp
@@ -0,0 +1,126 @@
+// license:BSD-3-Clause
+// copyright-holders:Nigel Barnes
+/**********************************************************************
+
+ Digital Services Ethernet Podule
+
+ TODO:
+ - everything, this is skeleton with ROM.
+
+**********************************************************************/
+
+#include "emu.h"
+#include "etherd.h"
+
+
+namespace {
+
+class arc_etherd_device :
+ public device_t,
+ public device_archimedes_podule_interface
+{
+public:
+ // construction/destruction
+ arc_etherd_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 ATTR_COLD;
+ virtual void device_reset() override ATTR_COLD;
+
+ // optional information overrides
+ virtual void device_add_mconfig(machine_config &config) override ATTR_COLD;
+ virtual const tiny_rom_entry *device_rom_region() const override ATTR_COLD;
+
+ // device_archimedes_podule_interface overrides
+ virtual void ioc_map(address_map &map) override ATTR_COLD;
+ virtual void memc_map(address_map &map) override ATTR_COLD;
+
+private:
+ required_memory_region m_podule_rom;
+
+ u8 m_rom_page;
+};
+
+
+void arc_etherd_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) & 0x1f800)]; })).umask32(0x000000ff);
+ map(0x0000, 0x0000).lw8(NAME([this](u8 data) { m_rom_page = data; }));
+}
+
+void arc_etherd_device::memc_map(address_map &map)
+{
+}
+
+
+//-------------------------------------------------
+// ROM( etherd )
+//-------------------------------------------------
+
+ROM_START( etherd )
+ ROM_REGION(0x20000, "podule_rom", 0)
+ ROM_LOAD("dsle3a-2.00.rom", 0x0000, 0x20000, CRC(123a04b9) SHA1(e972c1ab2ccfd20a6e5321549d555f8ae14e12f9))
+ROM_END
+
+const tiny_rom_entry *arc_etherd_device::device_rom_region() const
+{
+ return ROM_NAME( etherd );
+}
+
+
+//-------------------------------------------------
+// device_add_mconfig - add device configuration
+//-------------------------------------------------
+
+void arc_etherd_device::device_add_mconfig(machine_config &config)
+{
+ //SMC91C90(config, "lan", 20_MHz_XTAL);
+}
+
+
+//**************************************************************************
+// LIVE DEVICE
+//**************************************************************************
+
+//-------------------------------------------------
+// arc_etherd_device - constructor
+//-------------------------------------------------
+
+arc_etherd_device::arc_etherd_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock)
+ : device_t(mconfig, ARC_ETHERD, 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_etherd_device::device_start()
+{
+ save_item(NAME(m_rom_page));
+}
+
+//-------------------------------------------------
+// device_reset - device-specific reset
+//-------------------------------------------------
+
+void arc_etherd_device::device_reset()
+{
+ m_rom_page = 0x00;
+}
+
+} // anonymous namespace
+
+
+//**************************************************************************
+// DEVICE DEFINITIONS
+//**************************************************************************
+
+DEFINE_DEVICE_TYPE_PRIVATE(ARC_ETHERD, device_archimedes_podule_interface, arc_etherd_device, "arc_etherd", "Digital Services Ethernet Podule")
diff --git a/src/devices/bus/archimedes/podule/etherd.h b/src/devices/bus/archimedes/podule/etherd.h
new file mode 100644
index 00000000000..a7dcf88daaf
--- /dev/null
+++ b/src/devices/bus/archimedes/podule/etherd.h
@@ -0,0 +1,19 @@
+// license:BSD-3-Clause
+// copyright-holders:Nigel Barnes
+/**********************************************************************
+
+ Digital Services Ethernet Podule
+
+**********************************************************************/
+
+#ifndef MAME_BUS_ARCHIMEDES_PODULE_ETHERD_H
+#define MAME_BUS_ARCHIMEDES_PODULE_ETHERD_H
+
+#pragma once
+
+#include "slot.h"
+
+// device type definition
+DECLARE_DEVICE_TYPE(ARC_ETHERD, device_archimedes_podule_interface)
+
+#endif // MAME_BUS_ARCHIMEDES_PODULE_ETHERD_H
diff --git a/src/devices/bus/archimedes/podule/etherr.cpp b/src/devices/bus/archimedes/podule/etherr.cpp
new file mode 100644
index 00000000000..34ab9866149
--- /dev/null
+++ b/src/devices/bus/archimedes/podule/etherr.cpp
@@ -0,0 +1,126 @@
+// license:BSD-3-Clause
+// copyright-holders:Nigel Barnes
+/**********************************************************************
+
+ RISC Developments Ethernet Card
+
+ TODO:
+ - everything, this is skeleton with ROM.
+
+**********************************************************************/
+
+#include "emu.h"
+#include "etherr.h"
+
+
+namespace {
+
+class arc_etherr_device :
+ public device_t,
+ public device_archimedes_podule_interface
+{
+public:
+ // construction/destruction
+ arc_etherr_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 ATTR_COLD;
+ virtual void device_reset() override ATTR_COLD;
+
+ // optional information overrides
+ virtual void device_add_mconfig(machine_config &config) override ATTR_COLD;
+ virtual const tiny_rom_entry *device_rom_region() const override ATTR_COLD;
+
+ // device_archimedes_podule_interface overrides
+ virtual void ioc_map(address_map &map) override ATTR_COLD;
+ virtual void memc_map(address_map &map) override ATTR_COLD;
+
+private:
+ required_memory_region m_podule_rom;
+
+ u8 m_rom_page;
+};
+
+
+void arc_etherr_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) & 0x1f800)]; })).umask32(0x000000ff);
+ map(0x0000, 0x0000).lw8(NAME([this](u8 data) { m_rom_page = data; }));
+}
+
+void arc_etherr_device::memc_map(address_map &map)
+{
+}
+
+
+//-------------------------------------------------
+// ROM( etherr )
+//-------------------------------------------------
+
+ROM_START( etherr )
+ ROM_REGION(0x20000, "podule_rom", 0)
+ ROM_LOAD("etherr_1.06.rom", 0x0000, 0x20000, CRC(7b214fda) SHA1(a8045e3749fbf24e721e84e57acb68753fa46428))
+ROM_END
+
+const tiny_rom_entry *arc_etherr_device::device_rom_region() const
+{
+ return ROM_NAME( etherr );
+}
+
+
+//-------------------------------------------------
+// device_add_mconfig - add device configuration
+//-------------------------------------------------
+
+void arc_etherr_device::device_add_mconfig(machine_config &config)
+{
+ //NQ8005A(config, "edlc", 20_MHz_XTAL);
+}
+
+
+//**************************************************************************
+// LIVE DEVICE
+//**************************************************************************
+
+//-------------------------------------------------
+// arc_etherr_device - constructor
+//-------------------------------------------------
+
+arc_etherr_device::arc_etherr_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock)
+ : device_t(mconfig, ARC_ETHERR, 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_etherr_device::device_start()
+{
+ save_item(NAME(m_rom_page));
+}
+
+//-------------------------------------------------
+// device_reset - device-specific reset
+//-------------------------------------------------
+
+void arc_etherr_device::device_reset()
+{
+ m_rom_page = 0x00;
+}
+
+} // anonymous namespace
+
+
+//**************************************************************************
+// DEVICE DEFINITIONS
+//**************************************************************************
+
+DEFINE_DEVICE_TYPE_PRIVATE(ARC_ETHERR, device_archimedes_podule_interface, arc_etherr_device, "arc_etherr", "RISC Developments Ethernet Card")
diff --git a/src/devices/bus/archimedes/podule/etherr.h b/src/devices/bus/archimedes/podule/etherr.h
new file mode 100644
index 00000000000..dd653a2fada
--- /dev/null
+++ b/src/devices/bus/archimedes/podule/etherr.h
@@ -0,0 +1,19 @@
+// license:BSD-3-Clause
+// copyright-holders:Nigel Barnes
+/**********************************************************************
+
+ RISC Developments Ethernet Card
+
+**********************************************************************/
+
+#ifndef MAME_BUS_ARCHIMEDES_PODULE_ETHERR_H
+#define MAME_BUS_ARCHIMEDES_PODULE_ETHERR_H
+
+#pragma once
+
+#include "slot.h"
+
+// device type definition
+DECLARE_DEVICE_TYPE(ARC_ETHERR, device_archimedes_podule_interface)
+
+#endif // MAME_BUS_ARCHIMEDES_PODULE_ETHERR_H
diff --git a/src/devices/bus/archimedes/podule/faxpack.cpp b/src/devices/bus/archimedes/podule/faxpack.cpp
new file mode 100644
index 00000000000..bcbce02d706
--- /dev/null
+++ b/src/devices/bus/archimedes/podule/faxpack.cpp
@@ -0,0 +1,135 @@
+// license:BSD-3-Clause
+// copyright-holders:Nigel Barnes
+/**********************************************************************
+
+ Computer Concepts Fax-Pack
+
+ https://chrisacorns.computinghistory.org.uk/32bit_UpgradesA2G/CC_FaxPack.html
+
+ TODO:
+ - add R96DFX modem.
+
+**********************************************************************/
+
+#include "emu.h"
+#include "faxpack.h"
+#include "machine/mb8421.h"
+//#include "machine/r96dfx.h"
+
+
+namespace {
+
+class arc_faxpack_device :
+ public device_t,
+ public device_archimedes_podule_interface
+{
+public:
+ // construction/destruction
+ arc_faxpack_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock);
+
+ static constexpr feature_type unemulated_features() { return feature::CAPTURE; }
+
+protected:
+ // device-level overrides
+ virtual void device_start() override ATTR_COLD;
+
+ // optional information overrides
+ virtual void device_add_mconfig(machine_config &config) override ATTR_COLD;
+ virtual const tiny_rom_entry *device_rom_region() const override ATTR_COLD;
+
+ // device_archimedes_podule_interface overrides
+ virtual void ioc_map(address_map &map) override ATTR_COLD;
+
+private:
+ required_device<mcs51_cpu_device> m_mcu;
+ required_memory_region m_podule_rom;
+
+ void mem_map(address_map &map) ATTR_COLD;
+ void io_map(address_map &map) ATTR_COLD;
+};
+
+
+void arc_faxpack_device::ioc_map(address_map &map)
+{
+ map(0x0000, 0x0fff).rw("dpram", FUNC(idt7130_device::right_r), FUNC(idt7130_device::right_w)).umask32(0x000000ff);
+}
+
+
+void arc_faxpack_device::mem_map(address_map &map)
+{
+ map(0x0000, 0x7fff).rom().region("podule_rom", 0);
+}
+
+void arc_faxpack_device::io_map(address_map &map)
+{
+ //map(0x2000, 0x201f).rw("modem", FUNC(r96dfx_device::read), FUNC(r96dfx_device::write));
+ map(0x6000, 0x63ff).rw("dpram", FUNC(idt7130_device::left_r), FUNC(idt7130_device::left_w));
+}
+
+
+//-------------------------------------------------
+// ROM( faxpack )
+//-------------------------------------------------
+
+ROM_START( faxpack )
+ ROM_REGION(0x8000, "podule_rom", 0)
+ ROM_LOAD("faxpack_3873.rom", 0x0000, 0x8000, CRC(4bb7a925) SHA1(bbd1c4560c3bde1e61f81ae6505cd5d4658c6cb8))
+ROM_END
+
+const tiny_rom_entry *arc_faxpack_device::device_rom_region() const
+{
+ return ROM_NAME( faxpack );
+}
+
+
+//-------------------------------------------------
+// device_add_mconfig - add device configuration
+//-------------------------------------------------
+
+void arc_faxpack_device::device_add_mconfig(machine_config &config)
+{
+ I8031(config, m_mcu, 11.0592_MHz_XTAL);
+ m_mcu->set_addrmap(AS_PROGRAM, &arc_faxpack_device::mem_map);
+ m_mcu->set_addrmap(AS_IO, &arc_faxpack_device::io_map);
+
+ idt7130_device &dpram(IDT7130(config, "dpram"));
+ dpram.intl_callback().set_inputline(m_mcu, MCS51_INT0_LINE);
+ dpram.intr_callback().set([this](int state) { set_pirq(state); });
+
+ //R96DFX(config, "modem", 24.00014_MHz_XTAL);
+}
+
+
+//**************************************************************************
+// LIVE DEVICE
+//**************************************************************************
+
+//-------------------------------------------------
+// arc_faxpack_device - constructor
+//-------------------------------------------------
+
+arc_faxpack_device::arc_faxpack_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock)
+ : device_t(mconfig, ARC_FAXPACK, tag, owner, clock)
+ , device_archimedes_podule_interface(mconfig, *this)
+ , m_mcu(*this, "mcu")
+ , m_podule_rom(*this, "podule_rom")
+{
+}
+
+
+//-------------------------------------------------
+// device_start - device-specific startup
+//-------------------------------------------------
+
+void arc_faxpack_device::device_start()
+{
+}
+
+} // anonymous namespace
+
+
+//**************************************************************************
+// DEVICE DEFINITIONS
+//**************************************************************************
+
+DEFINE_DEVICE_TYPE_PRIVATE(ARC_FAXPACK, device_archimedes_podule_interface, arc_faxpack_device, "arc_faxpack", "Computer Concepts FaxPack Modem")
diff --git a/src/devices/bus/archimedes/podule/faxpack.h b/src/devices/bus/archimedes/podule/faxpack.h
new file mode 100644
index 00000000000..562af1ffdb8
--- /dev/null
+++ b/src/devices/bus/archimedes/podule/faxpack.h
@@ -0,0 +1,20 @@
+// license:BSD-3-Clause
+// copyright-holders:Nigel Barnes
+/**********************************************************************
+
+ Computer Concepts Fax-Pack
+
+**********************************************************************/
+
+#ifndef MAME_BUS_ARCHIMEDES_PODULE_FAXPACK_H
+#define MAME_BUS_ARCHIMEDES_PODULE_FAXPACK_H
+
+#pragma once
+
+#include "slot.h"
+#include "cpu/mcs51/mcs51.h"
+
+// device type definition
+DECLARE_DEVICE_TYPE(ARC_FAXPACK, device_archimedes_podule_interface)
+
+#endif // MAME_BUS_ARCHIMEDES_PODULE_FAXPACK_H
diff --git a/src/devices/bus/archimedes/podule/greyhawk.cpp b/src/devices/bus/archimedes/podule/greyhawk.cpp
new file mode 100644
index 00000000000..1eac6add450
--- /dev/null
+++ b/src/devices/bus/archimedes/podule/greyhawk.cpp
@@ -0,0 +1,131 @@
+// license:BSD-3-Clause
+// copyright-holders:Nigel Barnes
+/**********************************************************************
+
+ Computer Concepts GreyHawk Video Digitiser
+
+ http://chrisacorns.computinghistory.org.uk/32bit_UpgradesA2G/CC_GreyHawk.html
+
+ TODO:
+ - implement frame grabber from video source.
+
+**********************************************************************/
+
+#include "emu.h"
+#include "greyhawk.h"
+#include "imagedev/avivideo.h"
+
+
+namespace {
+
+class arc_greyhawk_device :
+ public device_t,
+ public device_archimedes_podule_interface
+{
+public:
+ // construction/destruction
+ arc_greyhawk_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock);
+
+ static constexpr feature_type unemulated_features() { return feature::CAPTURE; }
+
+protected:
+ // device-level overrides
+ virtual void device_start() override ATTR_COLD;
+ virtual void device_reset() override ATTR_COLD;
+
+ // optional information overrides
+ virtual void device_add_mconfig(machine_config &config) override ATTR_COLD;
+ virtual const tiny_rom_entry *device_rom_region() const override ATTR_COLD;
+
+ // device_archimedes_podule_interface overrides
+ virtual void ioc_map(address_map &map) override ATTR_COLD;
+ virtual void memc_map(address_map &map) override ATTR_COLD;
+
+private:
+ required_memory_region m_podule_rom;
+ required_device<avivideo_image_device> m_avivideo;
+
+ u8 m_rom_page;
+};
+
+
+void arc_greyhawk_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(0x2000, 0x2000).lw8(NAME([this](u8 data) { m_rom_page = data; }));
+}
+
+void arc_greyhawk_device::memc_map(address_map &map)
+{
+}
+
+
+//-------------------------------------------------
+// ROM( greyhawk )
+//-------------------------------------------------
+
+ROM_START( greyhawk )
+ ROM_REGION(0x10000, "podule_rom", 0)
+ ROM_LOAD("greyhawk.bin", 0x0000, 0x10000, CRC(1ecead90) SHA1(e8d5d271e2c10430ae858d2f4337fc73a0c63d82))
+ROM_END
+
+const tiny_rom_entry *arc_greyhawk_device::device_rom_region() const
+{
+ return ROM_NAME( greyhawk );
+}
+
+
+//-------------------------------------------------
+// device_add_mconfig - add device configuration
+//-------------------------------------------------
+
+void arc_greyhawk_device::device_add_mconfig(machine_config &config)
+{
+ IMAGE_AVIVIDEO(config, m_avivideo);
+}
+
+
+//**************************************************************************
+// LIVE DEVICE
+//**************************************************************************
+
+//-------------------------------------------------
+// arc_greyhawk_device - constructor
+//-------------------------------------------------
+
+arc_greyhawk_device::arc_greyhawk_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock)
+ : device_t(mconfig, ARC_GREYHAWK, tag, owner, clock)
+ , device_archimedes_podule_interface(mconfig, *this)
+ , m_podule_rom(*this, "podule_rom")
+ , m_avivideo(*this, "srcavi")
+ , m_rom_page(0)
+{
+}
+
+
+//-------------------------------------------------
+// device_start - device-specific startup
+//-------------------------------------------------
+
+void arc_greyhawk_device::device_start()
+{
+ save_item(NAME(m_rom_page));
+}
+
+//-------------------------------------------------
+// device_reset - device-specific reset
+//-------------------------------------------------
+
+void arc_greyhawk_device::device_reset()
+{
+ m_rom_page = 0x00;
+}
+
+} // anonymous namespace
+
+
+//**************************************************************************
+// DEVICE DEFINITIONS
+//**************************************************************************
+
+DEFINE_DEVICE_TYPE_PRIVATE(ARC_GREYHAWK, device_archimedes_podule_interface, arc_greyhawk_device, "arc_greyhawk", "Computer Concepts GreyHawk Video Digitiser")
diff --git a/src/devices/bus/archimedes/podule/greyhawk.h b/src/devices/bus/archimedes/podule/greyhawk.h
new file mode 100644
index 00000000000..ebff90e440c
--- /dev/null
+++ b/src/devices/bus/archimedes/podule/greyhawk.h
@@ -0,0 +1,19 @@
+// license:BSD-3-Clause
+// copyright-holders:Nigel Barnes
+/**********************************************************************
+
+ Computer Concepts GreyHawk Video Digitiser
+
+**********************************************************************/
+
+#ifndef MAME_BUS_ARCHIMEDES_PODULE_GREYHAWK_H
+#define MAME_BUS_ARCHIMEDES_PODULE_GREYHAWK_H
+
+#pragma once
+
+#include "slot.h"
+
+// device type definition
+DECLARE_DEVICE_TYPE(ARC_GREYHAWK, device_archimedes_podule_interface)
+
+#endif // MAME_BUS_ARCHIMEDES_PODULE_GREYHAWK_H
diff --git a/src/devices/bus/archimedes/podule/hdisc.cpp b/src/devices/bus/archimedes/podule/hdisc.cpp
new file mode 100644
index 00000000000..caf917c8a94
--- /dev/null
+++ b/src/devices/bus/archimedes/podule/hdisc.cpp
@@ -0,0 +1,118 @@
+// license:BSD-3-Clause
+// copyright-holders:Nigel Barnes
+/**********************************************************************
+
+ Acorn AKD52 Hard Disc Podule
+
+ http://chrisacorns.computinghistory.org.uk/32bit_UpgradesA2G/Acorn_AKD52_HDPodule.html
+
+ TODO:
+ - emulate HD63463 device.
+
+**********************************************************************/
+
+#include "emu.h"
+#include "hdisc.h"
+//#include "machine/hd63463.h"
+#include "imagedev/harddriv.h"
+
+
+namespace {
+
+// ======================> arc_hdisc_akd52_device
+
+class arc_hdisc_akd52_device :
+ public device_t,
+ public device_archimedes_podule_interface
+{
+public:
+ static constexpr feature_type unemulated_features() { return feature::DISK; }
+
+ // construction/destruction
+ arc_hdisc_akd52_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock);
+
+protected:
+ // device-level overrides
+ virtual void device_start() override ATTR_COLD;
+
+ // optional information overrides
+ virtual void device_add_mconfig(machine_config &config) override ATTR_COLD;
+ virtual const tiny_rom_entry *device_rom_region() const override ATTR_COLD;
+
+ // device_archimedes_podule_interface overrides
+ virtual void ioc_map(address_map &map) override ATTR_COLD;
+
+private:
+ required_memory_region m_podule_rom;
+};
+
+
+void arc_hdisc_akd52_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("hdc", FUNC(hd63463_device::read), FUNC(hd63463_device::write)).umask32(0x0000ffff);
+}
+
+
+//-------------------------------------------------
+// ROM( hdisc_akd52 )
+//-------------------------------------------------
+
+ROM_START( hdisc_akd52 )
+ ROM_REGION(0x0800, "podule_rom", 0)
+ ROM_LOAD("0276,242-01_hdisc_pod.rom", 0x0000, 0x0800, CRC(5e43bf28) SHA1(c8ebec931d6cef53b7b2965f526e8721c6cb3d28))
+ROM_END
+
+const tiny_rom_entry *arc_hdisc_akd52_device::device_rom_region() const
+{
+ return ROM_NAME( hdisc_akd52 );
+}
+
+
+//-------------------------------------------------
+// device_add_mconfig - add device configuration
+//-------------------------------------------------
+
+void arc_hdisc_akd52_device::device_add_mconfig(machine_config &config)
+{
+ //hd63463_device &hdc(HD63463(config, "hdc", 10_MHz_XTAL));
+ //hdc.irq_callback().set([this](int state) { set_pirq(state); });
+ //hdc.dreq_callback().set([this](int state) { set_pirq(state); });
+
+ //HARDDISK(config, "hdc:0", "st506_hdd");
+ //HARDDISK(config, "hdc:1", "st506_hdd");
+}
+
+
+//**************************************************************************
+// LIVE DEVICE
+//**************************************************************************
+
+//-------------------------------------------------
+// arc_hdisc_akd52_device - constructor
+//-------------------------------------------------
+
+arc_hdisc_akd52_device::arc_hdisc_akd52_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock)
+ : device_t(mconfig, ARC_HDISC_AKD52, tag, owner, clock)
+ , device_archimedes_podule_interface(mconfig, *this)
+ , m_podule_rom(*this, "podule_rom")
+{
+}
+
+
+//-------------------------------------------------
+// device_start - device-specific startup
+//-------------------------------------------------
+
+void arc_hdisc_akd52_device::device_start()
+{
+}
+
+} // anonymous namespace
+
+
+//**************************************************************************
+// DEVICE DEFINITIONS
+//**************************************************************************
+
+DEFINE_DEVICE_TYPE_PRIVATE(ARC_HDISC_AKD52, device_archimedes_podule_interface, arc_hdisc_akd52_device, "arc_hdisc_akd52", "Acorn AKD52 Hard Disc Podule")
diff --git a/src/devices/bus/archimedes/podule/hdisc.h b/src/devices/bus/archimedes/podule/hdisc.h
new file mode 100644
index 00000000000..b670e197023
--- /dev/null
+++ b/src/devices/bus/archimedes/podule/hdisc.h
@@ -0,0 +1,19 @@
+// license:BSD-3-Clause
+// copyright-holders:Nigel Barnes
+/**********************************************************************
+
+ Acorn AKD52 Hard Disc Podule
+
+**********************************************************************/
+
+#ifndef MAME_BUS_ARCHIMEDES_PODULE_HDISC_H
+#define MAME_BUS_ARCHIMEDES_PODULE_HDISC_H
+
+#pragma once
+
+#include "slot.h"
+
+// device type definition
+DECLARE_DEVICE_TYPE(ARC_HDISC_AKD52, device_archimedes_podule_interface)
+
+#endif // MAME_BUS_ARCHIMEDES_PODULE_HDISC_H
diff --git a/src/devices/bus/archimedes/podule/hdisc_cw.cpp b/src/devices/bus/archimedes/podule/hdisc_cw.cpp
new file mode 100644
index 00000000000..aa2c2080f0f
--- /dev/null
+++ b/src/devices/bus/archimedes/podule/hdisc_cw.cpp
@@ -0,0 +1,125 @@
+// license:BSD-3-Clause
+// copyright-holders:Nigel Barnes
+/**********************************************************************
+
+ Computerware Hard Disc Podule
+
+ TODO:
+ - emulate HD63463 device.
+
+**********************************************************************/
+
+#include "emu.h"
+#include "hdisc_cw.h"
+//#include "machine/hd63463.h"
+#include "imagedev/harddriv.h"
+
+
+namespace {
+
+// ======================> arc_hdisc_cw_device
+
+class arc_hdisc_cw_device :
+ public device_t,
+ public device_archimedes_podule_interface
+{
+public:
+ static constexpr feature_type unemulated_features() { return feature::DISK; }
+
+ // construction/destruction
+ arc_hdisc_cw_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock);
+
+protected:
+ // device-level overrides
+ virtual void device_start() override ATTR_COLD;
+
+ // optional information overrides
+ virtual void device_add_mconfig(machine_config &config) override ATTR_COLD;
+ virtual const tiny_rom_entry *device_rom_region() const override ATTR_COLD;
+
+ // device_archimedes_podule_interface overrides
+ virtual void ioc_map(address_map &map) override ATTR_COLD;
+
+private:
+ required_memory_region m_podule_rom;
+};
+
+
+void arc_hdisc_cw_device::ioc_map(address_map &map)
+{
+ map(0x0000, 0x0fff).lr8(NAME([this](offs_t offset) { return m_podule_rom->base()[offset]; })).umask32(0x000000ff);
+ //map(0x1000, 0x1007).rw("hdc", FUNC(hd63463_device::read), FUNC(hd63463_device::write)).umask32(0x0000ffff);
+}
+
+
+//-------------------------------------------------
+// ROM( hdisc_cw )
+//-------------------------------------------------
+
+ROM_START( hdisc_cw )
+ ROM_REGION(0x4000, "podule_rom", 0)
+ ROM_LOAD("hdisc_computerware.rom", 0x0000, 0x4000, CRC(adcef956) SHA1(da99cd0ee9d1eba237261f24b46e8399a2316086))
+ROM_END
+
+const tiny_rom_entry *arc_hdisc_cw_device::device_rom_region() const
+{
+ return ROM_NAME( hdisc_cw );
+}
+
+
+//-------------------------------------------------
+// device_add_mconfig - add device configuration
+//-------------------------------------------------
+
+void arc_hdisc_cw_device::device_add_mconfig(machine_config &config)
+{
+ //hd63463_device &hdc(HD63463(config, "hdc", 10_MHz_XTAL));
+ //hdc.irq_callback().set([this](int state) { set_pirq(state); });
+ //hdc.dreq_callback().set([this](int state) { set_pirq(state); });
+
+ //HARDDISK(config, "hdc:0", "st506_hdd");
+ //HARDDISK(config, "hdc:1", "st506_hdd");
+}
+
+
+//**************************************************************************
+// LIVE DEVICE
+//**************************************************************************
+
+//-------------------------------------------------
+// arc_hdisc_cw_device - constructor
+//-------------------------------------------------
+
+arc_hdisc_cw_device::arc_hdisc_cw_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock)
+ : device_t(mconfig, ARC_HDISC_CW, tag, owner, clock)
+ , device_archimedes_podule_interface(mconfig, *this)
+ , m_podule_rom(*this, "podule_rom")
+{
+}
+
+
+//-------------------------------------------------
+// device_start - device-specific startup
+//-------------------------------------------------
+
+void arc_hdisc_cw_device::device_start()
+{
+ u8 *rom = m_podule_rom->base();
+
+ u8 rom_copy[0x1000];
+ memcpy(rom_copy, &rom[0], 0x1000);
+
+ for (int i = 0x0000; i < 0x1000; i++)
+ {
+ rom[i] = rom_copy[bitswap<12>(i, 11, 10, 9, 8, 0, 1, 2, 3, 4, 5, 6, 7)];
+ }
+}
+
+} // anonymous namespace
+
+
+//**************************************************************************
+// DEVICE DEFINITIONS
+//**************************************************************************
+
+DEFINE_DEVICE_TYPE_PRIVATE(ARC_HDISC_CW, device_archimedes_podule_interface, arc_hdisc_cw_device, "arc_hdisc_cw", "Computerware Hard Disk Podule")
diff --git a/src/devices/bus/archimedes/podule/hdisc_cw.h b/src/devices/bus/archimedes/podule/hdisc_cw.h
new file mode 100644
index 00000000000..1167b292a62
--- /dev/null
+++ b/src/devices/bus/archimedes/podule/hdisc_cw.h
@@ -0,0 +1,19 @@
+// license:BSD-3-Clause
+// copyright-holders:Nigel Barnes
+/**********************************************************************
+
+ Computerware Hard Disc Podule
+
+**********************************************************************/
+
+#ifndef MAME_BUS_ARCHIMEDES_PODULE_HDISC_CW_H
+#define MAME_BUS_ARCHIMEDES_PODULE_HDISC_CW_H
+
+#pragma once
+
+#include "slot.h"
+
+// device type definition
+DECLARE_DEVICE_TYPE(ARC_HDISC_CW, device_archimedes_podule_interface)
+
+#endif // MAME_BUS_ARCHIMEDES_PODULE_HDISC_CW_H
diff --git a/src/devices/bus/archimedes/podule/hdisc_morley.cpp b/src/devices/bus/archimedes/podule/hdisc_morley.cpp
new file mode 100644
index 00000000000..b6df3aa25e3
--- /dev/null
+++ b/src/devices/bus/archimedes/podule/hdisc_morley.cpp
@@ -0,0 +1,117 @@
+// license:BSD-3-Clause
+// copyright-holders:Nigel Barnes
+/**********************************************************************
+
+ Morley Electronics ST506 Controller Card
+
+ http://chrisacorns.computinghistory.org.uk/32bit_UpgradesH2Z/Morley_ST506Card.html
+
+ TODO:
+ - emulate HD63463 device.
+
+**********************************************************************/
+
+#include "emu.h"
+#include "hdisc_morley.h"
+//#include "machine/hd63463.h"
+#include "imagedev/harddriv.h"
+
+
+namespace {
+
+// ======================> arc_hdisc_morley_device
+
+class arc_hdisc_morley_device :
+ public device_t,
+ public device_archimedes_podule_interface
+{
+public:
+ static constexpr feature_type unemulated_features() { return feature::DISK; }
+
+ // construction/destruction
+ arc_hdisc_morley_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock);
+
+protected:
+ // device-level overrides
+ virtual void device_start() override ATTR_COLD;
+
+ // optional information overrides
+ virtual void device_add_mconfig(machine_config &config) override ATTR_COLD;
+ virtual const tiny_rom_entry *device_rom_region() const override ATTR_COLD;
+
+ // device_archimedes_podule_interface overrides
+ virtual void ioc_map(address_map &map) override ATTR_COLD;
+
+private:
+ required_memory_region m_podule_rom;
+};
+
+
+void arc_hdisc_morley_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("hdc", FUNC(hd63463_device::read), FUNC(hd63463_device::write)).umask32(0x0000ffff);
+}
+
+
+//-------------------------------------------------
+// ROM( hdisc_morley )
+//-------------------------------------------------
+
+ROM_START( hdisc_morley )
+ ROM_REGION(0x4000, "podule_rom", 0)
+ ROM_LOAD("hdisc_v2.10.rom", 0x0000, 0x4000, CRC(df139312) SHA1(42947aef6b2bafb4b971e5bc61aa31ecb385afe0))
+ROM_END
+
+const tiny_rom_entry *arc_hdisc_morley_device::device_rom_region() const
+{
+ return ROM_NAME( hdisc_morley );
+}
+
+
+//-------------------------------------------------
+// device_add_mconfig - add device configuration
+//-------------------------------------------------
+
+void arc_hdisc_morley_device::device_add_mconfig(machine_config &config)
+{
+ //hd63463_device &hdc(HD63463(config, "hdc", 10_MHz_XTAL));
+ //hdc.irq_callback().set([this](int state) { set_pirq(state); });
+ //hdc.dreq_callback().set([this](int state) { set_pirq(state); });
+
+ //HARDDISK(config, "hdc:0", "st506_hdd");
+}
+
+
+//**************************************************************************
+// LIVE DEVICE
+//**************************************************************************
+
+//-------------------------------------------------
+// arc_hdisc_morley_device - constructor
+//-------------------------------------------------
+
+arc_hdisc_morley_device::arc_hdisc_morley_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock)
+ : device_t(mconfig, ARC_HDISC_MORLEY, tag, owner, clock)
+ , device_archimedes_podule_interface(mconfig, *this)
+ , m_podule_rom(*this, "podule_rom")
+{
+}
+
+
+//-------------------------------------------------
+// device_start - device-specific startup
+//-------------------------------------------------
+
+void arc_hdisc_morley_device::device_start()
+{
+}
+
+} // anonymous namespace
+
+
+//**************************************************************************
+// DEVICE DEFINITIONS
+//**************************************************************************
+
+DEFINE_DEVICE_TYPE_PRIVATE(ARC_HDISC_MORLEY, device_archimedes_podule_interface, arc_hdisc_morley_device, "arc_hdisc_morley", "Morley Electronics Hard Disc Podule")
diff --git a/src/devices/bus/archimedes/podule/hdisc_morley.h b/src/devices/bus/archimedes/podule/hdisc_morley.h
new file mode 100644
index 00000000000..d126a24b146
--- /dev/null
+++ b/src/devices/bus/archimedes/podule/hdisc_morley.h
@@ -0,0 +1,19 @@
+// license:BSD-3-Clause
+// copyright-holders:Nigel Barnes
+/**********************************************************************
+
+ Morley Electronics ST506 Controller Card
+
+**********************************************************************/
+
+#ifndef MAME_BUS_ARCHIMEDES_PODULE_HDISC_MORLEY_H
+#define MAME_BUS_ARCHIMEDES_PODULE_HDISC_MORLEY_H
+
+#pragma once
+
+#include "slot.h"
+
+// device type definition
+DECLARE_DEVICE_TYPE(ARC_HDISC_MORLEY, device_archimedes_podule_interface)
+
+#endif // MAME_BUS_ARCHIMEDES_PODULE_HDISC_MORLEY_H
diff --git a/src/devices/bus/archimedes/podule/hdisc_we.cpp b/src/devices/bus/archimedes/podule/hdisc_we.cpp
new file mode 100644
index 00000000000..350cea9c9c4
--- /dev/null
+++ b/src/devices/bus/archimedes/podule/hdisc_we.cpp
@@ -0,0 +1,124 @@
+// license:BSD-3-Clause
+// copyright-holders:Nigel Barnes
+/**********************************************************************
+
+ Watford Electronics Archimedes Hard Disk Podule
+
+ http://chrisacorns.computinghistory.org.uk/32bit_UpgradesH2Z/WE_ArchimedesHardDiskPodule.html
+
+ TODO:
+ - emulate HD63463 device.
+
+**********************************************************************/
+
+#include "emu.h"
+#include "hdisc_we.h"
+//#include "machine/hd63463.h"
+#include "imagedev/harddriv.h"
+
+
+namespace {
+
+// ======================> arc_hdisc_we_device
+
+class arc_hdisc_we_device :
+ public device_t,
+ public device_archimedes_podule_interface
+{
+public:
+ static constexpr feature_type unemulated_features() { return feature::DISK; }
+
+ // construction/destruction
+ arc_hdisc_we_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock);
+
+protected:
+ // device-level overrides
+ virtual void device_start() override ATTR_COLD;
+
+ // optional information overrides
+ virtual void device_add_mconfig(machine_config &config) override ATTR_COLD;
+ virtual const tiny_rom_entry *device_rom_region() const override ATTR_COLD;
+
+ // device_archimedes_podule_interface overrides
+ virtual void ioc_map(address_map &map) override ATTR_COLD;
+
+private:
+ required_memory_region m_podule_rom;
+};
+
+
+void arc_hdisc_we_device::ioc_map(address_map &map)
+{
+ map(0x0000, 0x1fff).lr8(NAME([this](offs_t offset) { return m_podule_rom->base()[offset]; })).umask32(0x000000ff);
+ //map(0x2f00, 0x2f07).w("hdc", FUNC(hd63463_device::write)).umask32(0x0000ffff);
+ //map(0x3f00, 0x3f07).r("hdc", FUNC(hd63463_device::read)).umask32(0x0000ffff);
+}
+
+
+//-------------------------------------------------
+// ROM( hdisc_we )
+//-------------------------------------------------
+
+ROM_START( hdisc_we )
+ ROM_REGION(0x4000, "podule_rom", 0)
+ ROM_LOAD("archwin_1.00.rom", 0x0000, 0x4000, CRC(962b02fd) SHA1(783d94839f47ee27032027d02e2e3f808659c540))
+ROM_END
+
+const tiny_rom_entry *arc_hdisc_we_device::device_rom_region() const
+{
+ return ROM_NAME( hdisc_we );
+}
+
+
+//-------------------------------------------------
+// device_add_mconfig - add device configuration
+//-------------------------------------------------
+
+void arc_hdisc_we_device::device_add_mconfig(machine_config &config)
+{
+ //hd63463_device &hdc(HD63463(config, "hdc", 10_MHz_XTAL));
+ //hdc.irq_callback().set([this](int state) { set_pirq(state); });
+ //hdc.dreq_callback().set([this](int state) { set_pirq(state); });
+
+ //HARDDISK(config, "hdc:0", "st506_hdd");
+}
+
+
+//**************************************************************************
+// LIVE DEVICE
+//**************************************************************************
+
+//-------------------------------------------------
+// arc_hdisc_we_device - constructor
+//-------------------------------------------------
+
+arc_hdisc_we_device::arc_hdisc_we_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock)
+ : device_t(mconfig, ARC_HDISC_WE, tag, owner, clock)
+ , device_archimedes_podule_interface(mconfig, *this)
+ , m_podule_rom(*this, "podule_rom")
+{
+}
+
+
+//-------------------------------------------------
+// device_start - device-specific startup
+//-------------------------------------------------
+
+void arc_hdisc_we_device::device_start()
+{
+ u8 *const rom = m_podule_rom->base();
+
+ for (int i = 0x0000; i < 0x8000; i++)
+ {
+ rom[i] = bitswap<8>(rom[i], 3, 2, 4, 1, 5, 0, 6, 7);
+ }
+}
+
+} // anonymous namespace
+
+
+//**************************************************************************
+// DEVICE DEFINITIONS
+//**************************************************************************
+
+DEFINE_DEVICE_TYPE_PRIVATE(ARC_HDISC_WE, device_archimedes_podule_interface, arc_hdisc_we_device, "arc_hdisc_we", "Watford Electronics Archimedes Hard Disk Podule")
diff --git a/src/devices/bus/archimedes/podule/hdisc_we.h b/src/devices/bus/archimedes/podule/hdisc_we.h
new file mode 100644
index 00000000000..9740bb670e3
--- /dev/null
+++ b/src/devices/bus/archimedes/podule/hdisc_we.h
@@ -0,0 +1,19 @@
+// license:BSD-3-Clause
+// copyright-holders:Nigel Barnes
+/**********************************************************************
+
+ Watford Electronics Archimedes Hard Disk Podule
+
+**********************************************************************/
+
+#ifndef MAME_BUS_ARCHIMEDES_PODULE_HDISC_WE_H
+#define MAME_BUS_ARCHIMEDES_PODULE_HDISC_WE_H
+
+#pragma once
+
+#include "slot.h"
+
+// device type definition
+DECLARE_DEVICE_TYPE(ARC_HDISC_WE, device_archimedes_podule_interface)
+
+#endif // MAME_BUS_ARCHIMEDES_PODULE_HDISC_WE_H
diff --git a/src/devices/bus/archimedes/podule/ide_be.cpp b/src/devices/bus/archimedes/podule/ide_be.cpp
new file mode 100644
index 00000000000..861f78c587b
--- /dev/null
+++ b/src/devices/bus/archimedes/podule/ide_be.cpp
@@ -0,0 +1,130 @@
+// license:BSD-3-Clause
+// copyright-holders:Nigel Barnes
+/**********************************************************************
+
+ Baildon Electronics IDE HD Interface
+
+ http://chrisacorns.computinghistory.org.uk/32bit_UpgradesA2G/BE_IDEHD.html
+
+**********************************************************************/
+
+#include "emu.h"
+#include "ide_be.h"
+#include "bus/ata/ataintf.h"
+
+
+namespace {
+
+// ======================> arc_ide_be_device
+
+class arc_ide_be_device :
+ public device_t,
+ public device_archimedes_podule_interface
+{
+public:
+ // construction/destruction
+ arc_ide_be_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock);
+
+protected:
+ // device-level overrides
+ virtual void device_start() override ATTR_COLD;
+ virtual void device_reset() override ATTR_COLD;
+
+ // optional information overrides
+ virtual void device_add_mconfig(machine_config &config) override ATTR_COLD;
+ virtual const tiny_rom_entry *device_rom_region() const override ATTR_COLD;
+
+ // device_archimedes_podule_interface overrides
+ virtual void ioc_map(address_map &map) override ATTR_COLD;
+
+private:
+ required_memory_region m_podule_rom;
+
+ u8 m_rom_page;
+};
+
+
+void arc_ide_be_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) & 0x1800)]; })).umask32(0x000000ff);
+ map(0x2000, 0x2000).lw8(NAME([this](u8 data) { m_rom_page = data; }));
+ map(0x3000, 0x301f).rw("ata", FUNC(ata_interface_device::cs0_r), FUNC(ata_interface_device::cs0_w)).umask32(0x0000ffff);
+}
+
+
+//-------------------------------------------------
+// ROM( ide_be )
+//-------------------------------------------------
+
+ROM_START( ide_be ) // if0
+ ROM_REGION(0x2000, "podule_rom", ROMREGION_ERASE00)
+ ROM_SYSTEM_BIOS(0, "be202", "BE IDEFS 2.02 (14 Jan 1991)")
+ ROMX_LOAD("ide1_be_2.02.rom", 0x0000, 0x2000, CRC(36d76e00) SHA1(25547b793d935ee44109ff9ac6ff4be010cdc33d), ROM_BIOS(0))
+ ROM_SYSTEM_BIOS(1, "sfps114", "SF & PS IDEFS 1.14 (23 Apr 1991)")
+ ROMX_LOAD("ide1_sfps_1.14.rom", 0x0000, 0x2000, CRC(26761c5d) SHA1(eb42f98ac7708b08faf1bba2840bef0ccdffbc20), ROM_BIOS(1))
+ ROM_SYSTEM_BIOS(2, "sfps113", "SF & PS IDEFS 1.13 (22 Oct 1990)")
+ ROMX_LOAD("ide1_sfps_1.13.rom", 0x0000, 0x2000, CRC(ef1dddff) SHA1(430432e6611b22da9c4fc1b03a986b08a120808b), ROM_BIOS(2))
+ ROM_SYSTEM_BIOS(3, "zidefs", "ZIDEFS 1.10 (13 May 2018)") // FIXME: not working ??
+ ROMX_LOAD("ide1_zidefs_1.10.rom", 0x0000, 0x1fe8, CRC(581fa41c) SHA1(f7d13fce76dbe7ac9a27fc7e4a859161bb98a9b5), ROM_BIOS(3))
+ROM_END
+
+const tiny_rom_entry *arc_ide_be_device::device_rom_region() const
+{
+ return ROM_NAME( ide_be );
+}
+
+
+//-------------------------------------------------
+// device_add_mconfig - add device configuration
+//-------------------------------------------------
+
+void arc_ide_be_device::device_add_mconfig(machine_config &config)
+{
+ ata_interface_device &ata(ATA_INTERFACE(config, "ata").options(ata_devices, "hdd", nullptr, false));
+ ata.irq_handler().set([this](int state) { set_pirq(state); });
+}
+
+
+//**************************************************************************
+// LIVE DEVICE
+//**************************************************************************
+
+//-------------------------------------------------
+// arc_ide_be_device - constructor
+//-------------------------------------------------
+
+arc_ide_be_device::arc_ide_be_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock)
+ : device_t(mconfig, ARC_IDE_BE, 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_ide_be_device::device_start()
+{
+ save_item(NAME(m_rom_page));
+}
+
+//-------------------------------------------------
+// device_reset - device-specific reset
+//-------------------------------------------------
+
+void arc_ide_be_device::device_reset()
+{
+ m_rom_page = 0x00;
+}
+
+} // anonymous namespace
+
+
+//**************************************************************************
+// DEVICE DEFINITIONS
+//**************************************************************************
+
+DEFINE_DEVICE_TYPE_PRIVATE(ARC_IDE_BE, device_archimedes_podule_interface, arc_ide_be_device, "arc_ide_be", "Baildon Electronics IDE HD Interface")
diff --git a/src/devices/bus/archimedes/podule/ide_be.h b/src/devices/bus/archimedes/podule/ide_be.h
new file mode 100644
index 00000000000..8c8fc70fd3e
--- /dev/null
+++ b/src/devices/bus/archimedes/podule/ide_be.h
@@ -0,0 +1,19 @@
+// license:BSD-3-Clause
+// copyright-holders:Nigel Barnes
+/**********************************************************************
+
+ Baildon Electronics IDE HD Interface
+
+**********************************************************************/
+
+#ifndef MAME_BUS_ARCHIMEDES_PODULE_IDE_BE_H
+#define MAME_BUS_ARCHIMEDES_PODULE_IDE_BE_H
+
+#pragma once
+
+#include "slot.h"
+
+// device type definition
+DECLARE_DEVICE_TYPE(ARC_IDE_BE, device_archimedes_podule_interface)
+
+#endif // MAME_BUS_ARCHIMEDES_PODULE_IDE_BE_H
diff --git a/src/devices/bus/archimedes/podule/ide_rdev.cpp b/src/devices/bus/archimedes/podule/ide_rdev.cpp
new file mode 100644
index 00000000000..3471e5e40a0
--- /dev/null
+++ b/src/devices/bus/archimedes/podule/ide_rdev.cpp
@@ -0,0 +1,122 @@
+// license:BSD-3-Clause
+// copyright-holders:Nigel Barnes
+/**********************************************************************
+
+ RISC Developments IDE Hard Disc System
+
+ http://chrisacorns.computinghistory.org.uk/32bit_UpgradesH2Z/RiscDev_IDE.html
+
+**********************************************************************/
+
+#include "emu.h"
+#include "ide_rdev.h"
+#include "bus/ata/ataintf.h"
+
+
+namespace {
+
+class arc_ide_rdev_device :
+ public device_t,
+ public device_archimedes_podule_interface
+{
+public:
+ // construction/destruction
+ arc_ide_rdev_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock);
+
+protected:
+ // device-level overrides
+ virtual void device_start() override ATTR_COLD;
+ virtual void device_reset() override ATTR_COLD;
+
+ // optional information overrides
+ virtual void device_add_mconfig(machine_config &config) override ATTR_COLD;
+ virtual const tiny_rom_entry *device_rom_region() const override ATTR_COLD;
+
+ // device_archimedes_podule_interface overrides
+ virtual void ioc_map(address_map &map) override ATTR_COLD;
+
+private:
+ required_memory_region m_podule_rom;
+
+ u8 m_rom_page;
+};
+
+
+void arc_ide_rdev_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) & 0x7800)]; })).umask32(0x000000ff);
+ map(0x2000, 0x2000).lw8(NAME([this](u8 data) { m_rom_page = data; }));
+ map(0x2400, 0x2403).nopw(); // TODO: interrupt enable?
+ map(0x2800, 0x281f).rw("ata", FUNC(ata_interface_device::cs0_r), FUNC(ata_interface_device::cs0_w)).umask32(0x0000ffff);
+}
+
+
+//-------------------------------------------------
+// ROM( ide_riscdev )
+//-------------------------------------------------
+
+ROM_START( ide_riscdev )
+ ROM_REGION(0x8000, "podule_rom", 0)
+ ROM_LOAD("ide_1.24_riscdev.bin", 0x0000, 0x8000, CRC(53bc8e72) SHA1(84e5d31d631b69401c47ef1ce91f11f1bb317597))
+ROM_END
+
+const tiny_rom_entry *arc_ide_rdev_device::device_rom_region() const
+{
+ return ROM_NAME( ide_riscdev );
+}
+
+
+//-------------------------------------------------
+// device_add_mconfig - add device configuration
+//-------------------------------------------------
+
+void arc_ide_rdev_device::device_add_mconfig(machine_config &config)
+{
+ ata_interface_device &ata(ATA_INTERFACE(config, "ata").options(ata_devices, "hdd", nullptr, false));
+ ata.irq_handler().set([this](int state) { set_pirq(state); });
+}
+
+
+//**************************************************************************
+// LIVE DEVICE
+//**************************************************************************
+
+//-------------------------------------------------
+// arc_ide_rdev_device - constructor
+//-------------------------------------------------
+
+arc_ide_rdev_device::arc_ide_rdev_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock)
+ : device_t(mconfig, ARC_IDE_RDEV, 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_ide_rdev_device::device_start()
+{
+ save_item(NAME(m_rom_page));
+}
+
+//-------------------------------------------------
+// device_reset - device-specific reset
+//-------------------------------------------------
+
+void arc_ide_rdev_device::device_reset()
+{
+ m_rom_page = 0x00;
+}
+
+} // anonymous namespace
+
+
+//**************************************************************************
+// DEVICE DEFINITIONS
+//**************************************************************************
+
+DEFINE_DEVICE_TYPE_PRIVATE(ARC_IDE_RDEV, device_archimedes_podule_interface, arc_ide_rdev_device, "arc_ide_rdev", "RISC Developments IDE Hard Disc System")
diff --git a/src/devices/bus/archimedes/podule/ide_rdev.h b/src/devices/bus/archimedes/podule/ide_rdev.h
new file mode 100644
index 00000000000..ad4ccb683a7
--- /dev/null
+++ b/src/devices/bus/archimedes/podule/ide_rdev.h
@@ -0,0 +1,19 @@
+// license:BSD-3-Clause
+// copyright-holders:Nigel Barnes
+/**********************************************************************
+
+ RISC Developments IDE Hard Disc System
+
+**********************************************************************/
+
+#ifndef MAME_BUS_ARCHIMEDES_PODULE_IDE_RDEV_H
+#define MAME_BUS_ARCHIMEDES_PODULE_IDE_RDEV_H
+
+#pragma once
+
+#include "slot.h"
+
+// device type definition
+DECLARE_DEVICE_TYPE(ARC_IDE_RDEV, device_archimedes_podule_interface)
+
+#endif // MAME_BUS_ARCHIMEDES_PODULE_IDE_RDEV_H
diff --git a/src/devices/bus/archimedes/podule/io.cpp b/src/devices/bus/archimedes/podule/io.cpp
new file mode 100644
index 00000000000..7e23b3ac57f
--- /dev/null
+++ b/src/devices/bus/archimedes/podule/io.cpp
@@ -0,0 +1,446 @@
+// license:BSD-3-Clause
+// copyright-holders:Nigel Barnes
+/**********************************************************************
+
+ Acorn AKA10 BBC I/O Podule
+ http://chrisacorns.computinghistory.org.uk/32bit_UpgradesA2G/Acorn_AKA10_IO.html
+
+ Acorn AKA12 User Port/Midi Upgrade
+ http://chrisacorns.computinghistory.org.uk/32bit_UpgradesA2G/Acorn_AKA12_MIDI.html
+
+ Acorn AKA15 Midi and BBC I/O Podule
+ http://chrisacorns.computinghistory.org.uk/32bit_UpgradesA2G/Acorn_AKA15_MIDI.html
+
+ Acorn AKA16 Midi Podule
+ http://chrisacorns.computinghistory.org.uk/32bit_UpgradesA2G/Acorn_AKA16_MIDI.html
+
+ TODO:
+ - interrupts are optional, and are enabled with links.
+
+**********************************************************************/
+
+#include "emu.h"
+#include "io.h"
+#include "machine/6522via.h"
+#include "machine/6850acia.h"
+#include "machine/clock.h"
+#include "machine/input_merger.h"
+#include "machine/mc68681.h"
+#include "machine/upd7002.h"
+#include "bus/bbc/1mhzbus/1mhzbus.h"
+#include "bus/bbc/analogue/analogue.h"
+#include "bus/bbc/userport/userport.h"
+#include "bus/midi/midi.h"
+
+
+namespace {
+
+// ======================> arc_io_aka_device
+
+class arc_io_aka_device :
+ public device_t,
+ public device_archimedes_podule_interface
+{
+protected:
+ arc_io_aka_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, u32 clock);
+
+ // device-level overrides
+ virtual void device_start() override ATTR_COLD;
+ virtual void device_reset() override ATTR_COLD;
+
+ void add_1mhzbus(machine_config &config);
+ void add_analogue(machine_config &config);
+ void add_midi_6850(machine_config &config);
+ void add_midi_2691(machine_config &config);
+ void add_userport(machine_config &config);
+
+ required_memory_region m_podule_rom;
+ required_device<input_merger_device> m_irqs;
+ optional_device<bbc_analogue_slot_device> m_analog;
+
+ u8 m_rom_page;
+
+ u8 pa_r();
+ int get_analogue_input(int channel_number);
+ void upd7002_eoc(int state);
+
+ int m_irq_en;
+};
+
+
+// ======================> arc_bbcio_aka10_device
+
+class arc_bbcio_aka10_device : public arc_io_aka_device
+{
+public:
+ // construction/destruction
+ arc_bbcio_aka10_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock);
+
+protected:
+ // optional information overrides
+ virtual void device_add_mconfig(machine_config &config) override ATTR_COLD;
+ virtual const tiny_rom_entry *device_rom_region() const override ATTR_COLD;
+
+ // device_archimedes_podule_interface overrides
+ virtual void ioc_map(address_map &map) override ATTR_COLD;
+ virtual void memc_map(address_map &map) override ATTR_COLD;
+};
+
+
+// ======================> arc_upmidi_aka12_device
+
+class arc_upmidi_aka12_device : public arc_io_aka_device
+{
+public:
+ // construction/destruction
+ arc_upmidi_aka12_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock);
+
+protected:
+ // optional information overrides
+ virtual void device_add_mconfig(machine_config &config) override ATTR_COLD;
+ virtual const tiny_rom_entry *device_rom_region() const override ATTR_COLD;
+
+ // device_archimedes_podule_interface overrides
+ virtual void ioc_map(address_map &map) override ATTR_COLD;
+};
+
+
+// ======================> arc_iomidi_aka15_device
+
+class arc_iomidi_aka15_device : public arc_io_aka_device
+{
+public:
+ // construction/destruction
+ arc_iomidi_aka15_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock);
+
+protected:
+ // optional information overrides
+ virtual void device_add_mconfig(machine_config &config) override ATTR_COLD;
+ virtual const tiny_rom_entry *device_rom_region() const override ATTR_COLD;
+
+ // device_archimedes_podule_interface overrides
+ virtual void ioc_map(address_map &map) override ATTR_COLD;
+ virtual void memc_map(address_map &map) override ATTR_COLD;
+};
+
+
+// ======================> arc_midi_aka16_device
+
+class arc_midi_aka16_device : public arc_io_aka_device
+{
+public:
+ // construction/destruction
+ arc_midi_aka16_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock);
+
+protected:
+ // optional information overrides
+ virtual void device_add_mconfig(machine_config &config) override ATTR_COLD;
+ virtual const tiny_rom_entry *device_rom_region() const override ATTR_COLD;
+
+ // device_archimedes_podule_interface overrides
+ virtual void ioc_map(address_map &map) override ATTR_COLD;
+};
+
+
+void arc_bbcio_aka10_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(0x2000, 0x203f).rw("via", FUNC(via6522_device::read), FUNC(via6522_device::write)).umask32(0x000000ff);
+}
+
+void arc_bbcio_aka10_device::memc_map(address_map &map)
+{
+ map(0x0000, 0x03ff).rw("1mhzbus", FUNC(bbc_1mhzbus_slot_device::fred_r), FUNC(bbc_1mhzbus_slot_device::fred_w)).umask32(0x000000ff);
+ map(0x0800, 0x0bff).rw("1mhzbus", FUNC(bbc_1mhzbus_slot_device::jim_r), FUNC(bbc_1mhzbus_slot_device::jim_w)).umask32(0x000000ff);
+ map(0x1000, 0x100f).rw("upd7002", FUNC(upd7002_device::read), FUNC(upd7002_device::write)).umask32(0x000000ff);
+}
+
+
+void arc_upmidi_aka12_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(0x2000, 0x203f).rw("via", FUNC(via6522_device::read), FUNC(via6522_device::write)).umask32(0x000000ff);
+ map(0x3000, 0x303f).rw("uart", FUNC(scn2681_device::read), FUNC(scn2681_device::write)).umask32(0x000000ff);
+}
+
+
+void arc_iomidi_aka15_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(0x2000, 0x203f).rw("via", FUNC(via6522_device::read), FUNC(via6522_device::write)).umask32(0x000000ff);
+}
+
+void arc_iomidi_aka15_device::memc_map(address_map &map)
+{
+ map(0x0000, 0x03ff).rw("1mhzbus", FUNC(bbc_1mhzbus_slot_device::fred_r), FUNC(bbc_1mhzbus_slot_device::fred_w)).umask32(0x000000ff);
+ map(0x0800, 0x0bff).rw("1mhzbus", FUNC(bbc_1mhzbus_slot_device::jim_r), FUNC(bbc_1mhzbus_slot_device::jim_w)).umask32(0x000000ff);
+ map(0x1000, 0x100f).rw("upd7002", FUNC(upd7002_device::read), FUNC(upd7002_device::write)).umask32(0x000000ff);
+ map(0x1800, 0x1807).rw("acia", FUNC(acia6850_device::read), FUNC(acia6850_device::write)).umask32(0x000000ff);
+}
+
+
+void arc_midi_aka16_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(0x2000, 0x203f).rw("uart", FUNC(scn2681_device::read), FUNC(scn2681_device::write)).umask32(0x000000ff);
+ map(0x3000, 0x3000).lw8(NAME([this](u8 data) { m_rom_page = data; }));
+}
+
+
+//-------------------------------------------------
+// ROM( aka10 )
+//-------------------------------------------------
+
+ROM_START( aka10 )
+ ROM_REGION(0x4000, "podule_rom", 0)
+ ROM_SYSTEM_BIOS(0, "3", "Third release 22-Sep-89")
+ ROMX_LOAD("0276,202-03_io.bin", 0x0000, 0x4000, CRC(f4df6587) SHA1(2c0402cd754ebeb1e1fe750dc8a88a2acc1ea06d), ROM_BIOS(0))
+ ROM_SYSTEM_BIOS(1, "2", "Second release 18-Dec-87")
+ ROMX_LOAD("0276,202-02_io.bin", 0x0000, 0x4000, CRC(d548b4dc) SHA1(22e1f1a0adf896f08b1e1d487aa24141296aa127), ROM_BIOS(1))
+ ROM_SYSTEM_BIOS(2, "1", "Release 1.04 07-Aug-87")
+ ROMX_LOAD("0276,202-01_io.bin", 0x0000, 0x4000, CRC(fc1d61d0) SHA1(4c3de606de594c8f6ed236ffa19374c76e307226), ROM_BIOS(2))
+ROM_END
+
+ROM_START( aka12 )
+ ROM_REGION(0x4000, "podule_rom", 0)
+ ROM_SYSTEM_BIOS(0, "2", "Second release 31-Aug-89")
+ ROMX_LOAD("0280,320-02_a3000_upm.bin", 0x0000, 0x4000, CRC(3f0f5794) SHA1(4e0e2cf2586c8f2fc1431458f677a45164749ab2), ROM_BIOS(0))
+ROM_END
+
+ROM_START( aka15 )
+ ROM_REGION(0x4000, "podule_rom", 0)
+ ROM_SYSTEM_BIOS(0, "1", "Initial release 18-Dec-87")
+ ROMX_LOAD("0276,211-01_iomidi.bin", 0x0000, 0x4000, CRC(e85a77c5) SHA1(32e990c435b439d4a169e85a009fc6a864121c3f), ROM_BIOS(0))
+ROM_END
+
+ROM_START( aka16 )
+ ROM_REGION(0x4000, "podule_rom", 0)
+ ROM_SYSTEM_BIOS(0, "2", "Second release 31-Aug-89")
+ ROMX_LOAD("0276,281-02_midi-pod_v3.03.rom", 0x0000, 0x4000, CRC(1833afdd) SHA1(beb86b74bf6a9c9caf10f57e326cc539ffe9624b), ROM_BIOS(0))
+ ROM_SYSTEM_BIOS(1, "1", "Test version 11-Jan-88")
+ ROMX_LOAD("0276,281-01_midi-pod.rom", 0x0000, 0x4000, CRC(c09ae053) SHA1(e0e63e0b44d3eba805aea9d2103ab35ea93e8c1c), ROM_BIOS(1))
+ ROM_SYSTEM_BIOS(2, "m", "Millipede Mod 8/1/98") // modified by Millipede to fix clash with their cards
+ ROMX_LOAD("millipede_mod_8-1-98.rom", 0x0000, 0x4000, CRC(729b9d61) SHA1(f6ad28d3cf9a14af3c103f9fae74795f539f24e8), ROM_BIOS(2))
+ROM_END
+
+const tiny_rom_entry *arc_bbcio_aka10_device::device_rom_region() const
+{
+ return ROM_NAME( aka10 );
+}
+
+const tiny_rom_entry *arc_upmidi_aka12_device::device_rom_region() const
+{
+ return ROM_NAME( aka12 );
+}
+
+const tiny_rom_entry *arc_iomidi_aka15_device::device_rom_region() const
+{
+ return ROM_NAME( aka15 );
+}
+
+const tiny_rom_entry *arc_midi_aka16_device::device_rom_region() const
+{
+ return ROM_NAME( aka16 );
+}
+
+
+//-------------------------------------------------
+// device_add_mconfig - add device configuration
+//-------------------------------------------------
+
+void arc_io_aka_device::add_userport(machine_config &config)
+{
+ via6522_device &via(MOS6522(config, "via", DERIVED_CLOCK(1, 4)));
+ via.irq_handler().set(m_irqs, FUNC(input_merger_device::in_w<0>));
+ via.readpa_handler().set(FUNC(arc_io_aka_device::pa_r));
+ via.writepa_handler().set([this](u8 data) { m_rom_page = data; });
+ via.readpb_handler().set("userport", FUNC(bbc_userport_slot_device::pb_r));
+ via.writepb_handler().set("userport", FUNC(bbc_userport_slot_device::pb_w));
+ via.ca2_handler().set([this](int state) { m_irq_en = !state; }); // AKA10/15 only
+ via.cb1_handler().set("userport", FUNC(bbc_userport_slot_device::write_cb1));
+ via.cb2_handler().set("userport", FUNC(bbc_userport_slot_device::write_cb2));
+
+ bbc_userport_slot_device &userport(BBC_USERPORT_SLOT(config, "userport", bbc_userport_devices, nullptr));
+ userport.cb1_handler().set("via", FUNC(via6522_device::write_cb1));
+ userport.cb2_handler().set("via", FUNC(via6522_device::write_cb2));
+}
+
+void arc_io_aka_device::add_analogue(machine_config &config)
+{
+ upd7002_device &upd7002(UPD7002(config, "upd7002", DERIVED_CLOCK(1, 4)));
+ upd7002.set_get_analogue_callback(FUNC(arc_io_aka_device::get_analogue_input));
+ upd7002.set_eoc_callback(FUNC(arc_io_aka_device::upd7002_eoc));
+
+ BBC_ANALOGUE_SLOT(config, m_analog, bbc_analogue_devices, nullptr);
+ m_analog->lpstb_handler().set("via", FUNC(via6522_device::write_ca1));
+}
+
+void arc_io_aka_device::add_1mhzbus(machine_config &config)
+{
+ bbc_1mhzbus_slot_device &bus(BBC_1MHZBUS_SLOT(config, "1mhzbus", DERIVED_CLOCK(1, 8), bbcm_1mhzbus_devices, nullptr));
+ bus.irq_handler().set(m_irqs, FUNC(input_merger_device::in_w<2>));
+ bus.nmi_handler().set([this](int state) { set_pfiq(state); });
+}
+
+void arc_io_aka_device::add_midi_6850(machine_config &config)
+{
+ acia6850_device &acia(ACIA6850(config, "acia", 0));
+ acia.irq_handler().set(m_irqs, FUNC(input_merger_device::in_w<3>));
+ acia.txd_handler().set("mdout", FUNC(midi_port_device::write_txd));
+
+ clock_device &acia_clock(CLOCK(config, "acia_clock", DERIVED_CLOCK(1, 4)));
+ acia_clock.signal_handler().set("acia", FUNC(acia6850_device::write_txc));
+ acia_clock.signal_handler().append("acia", FUNC(acia6850_device::write_rxc));
+
+ midiout_slot(MIDI_PORT(config, "mdout"));
+
+ auto &mdin(MIDI_PORT(config, "mdin"));
+ midiin_slot(mdin);
+ mdin.rxd_handler().set("acia", FUNC(acia6850_device::write_rxd));
+}
+
+void arc_io_aka_device::add_midi_2691(machine_config &config)
+{
+ scn2681_device &uart(SCN2681(config, "uart", DERIVED_CLOCK(1, 4))); // SCC2691
+ uart.irq_cb().set(m_irqs, FUNC(input_merger_device::in_w<3>));
+ uart.a_tx_cb().set("mdout", FUNC(midi_port_device::write_txd));
+ uart.a_tx_cb().append("mdthru", FUNC(midi_port_device::write_txd));
+
+ auto &mdin(MIDI_PORT(config, "mdin"));
+ midiin_slot(mdin);
+ mdin.rxd_handler().set("uart", FUNC(scn2681_device::rx_a_w));
+ mdin.rxd_handler().append("mdthru", FUNC(midi_port_device::write_txd));
+
+ midiout_slot(MIDI_PORT(config, "mdthru"));
+ midiout_slot(MIDI_PORT(config, "mdout"));
+}
+
+
+void arc_bbcio_aka10_device::device_add_mconfig(machine_config &config)
+{
+ INPUT_MERGER_ANY_HIGH(config, "irqs").output_handler().set([this](int state) { set_pirq(m_irq_en && state); });
+ add_userport(config);
+ add_1mhzbus(config);
+ add_analogue(config);
+}
+
+void arc_upmidi_aka12_device::device_add_mconfig(machine_config &config)
+{
+ INPUT_MERGER_ANY_HIGH(config, "irqs").output_handler().set([this](int state) { set_pirq(state); });
+ add_userport(config);
+ add_midi_2691(config);
+}
+
+void arc_iomidi_aka15_device::device_add_mconfig(machine_config &config)
+{
+ INPUT_MERGER_ANY_HIGH(config, "irqs").output_handler().set([this](int state) { set_pirq(m_irq_en && state); });
+ add_userport(config);
+ add_1mhzbus(config);
+ add_analogue(config);
+ add_midi_6850(config);
+}
+
+void arc_midi_aka16_device::device_add_mconfig(machine_config &config)
+{
+ INPUT_MERGER_ANY_HIGH(config, "irqs").output_handler().set([this](int state) { set_pirq(state); });
+ add_midi_2691(config);
+}
+
+
+//**************************************************************************
+// LIVE DEVICE
+//**************************************************************************
+
+//-------------------------------------------------
+// arc_io_aka_device - constructor
+//-------------------------------------------------
+
+arc_io_aka_device::arc_io_aka_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_irqs(*this, "irqs")
+ , m_analog(*this, "analogue")
+ , m_rom_page(0)
+ , m_irq_en(0)
+{
+}
+
+arc_bbcio_aka10_device::arc_bbcio_aka10_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock)
+ : arc_io_aka_device(mconfig, ARC_BBCIO_AKA10, tag, owner, clock)
+{
+}
+
+arc_upmidi_aka12_device::arc_upmidi_aka12_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock)
+ : arc_io_aka_device(mconfig, ARC_UPMIDI_AKA12, tag, owner, clock)
+{
+}
+
+arc_iomidi_aka15_device::arc_iomidi_aka15_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock)
+ : arc_io_aka_device(mconfig, ARC_IOMIDI_AKA15, tag, owner, clock)
+{
+}
+
+arc_midi_aka16_device::arc_midi_aka16_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock)
+ : arc_io_aka_device(mconfig, ARC_MIDI_AKA16, tag, owner, clock)
+{
+}
+
+
+//-------------------------------------------------
+// device_start - device-specific startup
+//-------------------------------------------------
+
+void arc_io_aka_device::device_start()
+{
+ save_item(NAME(m_rom_page));
+}
+
+
+//-------------------------------------------------
+// device_reset - device-specific reset
+//-------------------------------------------------
+
+void arc_io_aka_device::device_reset()
+{
+ m_rom_page = 0x00;
+}
+
+
+//**************************************************************************
+// IMPLEMENTATION
+//**************************************************************************
+
+u8 arc_io_aka_device::pa_r()
+{
+ u8 data = 0xff;
+
+ if (m_analog)
+ {
+ data = (m_analog->pb_r() << 2) | 0x3f;
+ }
+
+ return data;
+}
+
+int arc_io_aka_device::get_analogue_input(int channel_number)
+{
+ return m_analog->ch_r(channel_number) << 8;
+}
+
+void arc_io_aka_device::upd7002_eoc(int state)
+{
+ m_irqs->in_w<1>(!state);
+}
+
+} // anonymous namespace
+
+
+//**************************************************************************
+// DEVICE DEFINITIONS
+//**************************************************************************
+
+DEFINE_DEVICE_TYPE_PRIVATE(ARC_BBCIO_AKA10, device_archimedes_podule_interface, arc_bbcio_aka10_device, "arc_bbcio_aka10", "Acorn AKA10 BBC I/O Podule")
+DEFINE_DEVICE_TYPE_PRIVATE(ARC_UPMIDI_AKA12, device_archimedes_podule_interface, arc_upmidi_aka12_device, "arc_upmidi_aka12", "Acorn AKA12 User Port/MIDI Podule")
+DEFINE_DEVICE_TYPE_PRIVATE(ARC_IOMIDI_AKA15, device_archimedes_podule_interface, arc_iomidi_aka15_device, "arc_iomidi_aka15", "Acorn AKA15 MIDI and BBC I/O Podule")
+DEFINE_DEVICE_TYPE_PRIVATE(ARC_MIDI_AKA16, device_archimedes_podule_interface, arc_midi_aka16_device, "arc_midi_aka16", "Acorn AKA16 MIDI Podule")
diff --git a/src/devices/bus/archimedes/podule/io.h b/src/devices/bus/archimedes/podule/io.h
new file mode 100644
index 00000000000..56acab33bd6
--- /dev/null
+++ b/src/devices/bus/archimedes/podule/io.h
@@ -0,0 +1,23 @@
+// license:BSD-3-Clause
+// copyright-holders:Nigel Barnes
+/**********************************************************************
+
+ Acorn BBC I/O Podule
+
+**********************************************************************/
+
+#ifndef MAME_BUS_ARCHIMEDES_PODULE_IO_H
+#define MAME_BUS_ARCHIMEDES_PODULE_IO_H
+
+#pragma once
+
+#include "slot.h"
+
+// device type definition
+DECLARE_DEVICE_TYPE(ARC_BBCIO_AKA10, device_archimedes_podule_interface)
+DECLARE_DEVICE_TYPE(ARC_UPMIDI_AKA12, device_archimedes_podule_interface)
+DECLARE_DEVICE_TYPE(ARC_IOMIDI_AKA15, device_archimedes_podule_interface)
+DECLARE_DEVICE_TYPE(ARC_MIDI_AKA16, device_archimedes_podule_interface)
+DECLARE_DEVICE_TYPE(ARC_BBCIO_AGA30, device_archimedes_podule_interface)
+
+#endif // MAME_BUS_ARCHIMEDES_PODULE_IO_H
diff --git a/src/devices/bus/archimedes/podule/io_hccs.cpp b/src/devices/bus/archimedes/podule/io_hccs.cpp
new file mode 100644
index 00000000000..c815549d193
--- /dev/null
+++ b/src/devices/bus/archimedes/podule/io_hccs.cpp
@@ -0,0 +1,143 @@
+// license:BSD-3-Clause
+// copyright-holders:Nigel Barnes
+/**********************************************************************
+
+ HCCS User/Analogue Podule
+
+ http://chrisacorns.computinghistory.org.uk/32bit_UpgradesH2Z/HCCS_UserAnalogue.html
+
+**********************************************************************/
+
+#include "emu.h"
+#include "io_hccs.h"
+#include "machine/6522via.h"
+#include "machine/upd7002.h"
+#include "bus/bbc/analogue/analogue.h"
+#include "bus/bbc/userport/userport.h"
+
+
+namespace {
+
+// ======================> arc_upa_hccs_device
+
+class arc_upa_hccs_device :
+ public device_t,
+ public device_archimedes_podule_interface
+{
+public:
+ // construction/destruction
+ arc_upa_hccs_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock);
+
+protected:
+ // device-level overrides
+ virtual void device_start() override ATTR_COLD;
+
+ // optional information overrides
+ virtual void device_add_mconfig(machine_config &config) override ATTR_COLD;
+ virtual const tiny_rom_entry *device_rom_region() const override ATTR_COLD;
+
+ // device_archimedes_podule_interface overrides
+ virtual void ioc_map(address_map &map) override ATTR_COLD;
+
+private:
+ required_memory_region m_podule_rom;
+ required_device<bbc_analogue_slot_device> m_analog;
+
+ int get_analogue_input(int channel_number);
+};
+
+
+void arc_upa_hccs_device::ioc_map(address_map &map)
+{
+ map(0x0000, 0x1fff).lr8(NAME([this](offs_t offset) { return m_podule_rom->base()[offset | 0x4000]; })).umask32(0x000000ff);
+ map(0x2000, 0x203f).rw("via", FUNC(via6522_device::read), FUNC(via6522_device::write)).umask32(0x000000ff);
+ map(0x3000, 0x300f).rw("upd7002", FUNC(upd7002_device::read), FUNC(upd7002_device::write)).umask32(0x000000ff);
+}
+
+
+//-------------------------------------------------
+// ROM( upa_hccs )
+//-------------------------------------------------
+
+ROM_START( upa_hccs )
+ ROM_REGION(0x8000, "podule_rom", 0)
+ ROM_SYSTEM_BIOS(0, "7", "V7.00 (04 Jul 1991)")
+ ROMX_LOAD("upa_v7.00.bin", 0x0000, 0x8000, CRC(e4d5514e) SHA1(1a5d5c2571624df6fbeff91045c5b40effeda1d9), ROM_BIOS(0))
+ROM_END
+
+const tiny_rom_entry *arc_upa_hccs_device::device_rom_region() const
+{
+ return ROM_NAME( upa_hccs );
+}
+
+
+//-------------------------------------------------
+// device_add_mconfig - add device configuration
+//-------------------------------------------------
+
+void arc_upa_hccs_device::device_add_mconfig(machine_config &config)
+{
+ via6522_device &via(MOS6522(config, "via", DERIVED_CLOCK(1, 4)));
+ via.irq_handler().set([this](int state) { set_pirq(state); });
+ via.readpa_handler().set(m_analog, FUNC(bbc_analogue_slot_device::pb_r));
+ via.readpb_handler().set("userport", FUNC(bbc_userport_slot_device::pb_r));
+ via.writepb_handler().set("userport", FUNC(bbc_userport_slot_device::pb_w));
+ via.cb1_handler().set("userport", FUNC(bbc_userport_slot_device::write_cb1));
+ via.cb2_handler().set("userport", FUNC(bbc_userport_slot_device::write_cb2));
+
+ bbc_userport_slot_device &userport(BBC_USERPORT_SLOT(config, "userport", bbc_userport_devices, nullptr));
+ userport.cb1_handler().set("via", FUNC(via6522_device::write_cb1));
+ userport.cb2_handler().set("via", FUNC(via6522_device::write_cb2));
+
+ upd7002_device &upd7002(UPD7002(config, "upd7002", DERIVED_CLOCK(1, 4)));
+ upd7002.set_get_analogue_callback(FUNC(arc_upa_hccs_device::get_analogue_input));
+ upd7002.set_eoc_callback("via", FUNC(via6522_device::write_ca2));
+
+ BBC_ANALOGUE_SLOT(config, m_analog, bbc_analogue_devices, nullptr);
+ m_analog->lpstb_handler().set("via", FUNC(via6522_device::write_ca1));
+}
+
+
+//**************************************************************************
+// LIVE DEVICE
+//**************************************************************************
+
+//-------------------------------------------------
+// arc_upa_hccs_device - constructor
+//-------------------------------------------------
+
+arc_upa_hccs_device::arc_upa_hccs_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock)
+ : device_t(mconfig, ARC_UPA_HCCS, tag, owner, clock)
+ , device_archimedes_podule_interface(mconfig, *this)
+ , m_podule_rom(*this, "podule_rom")
+ , m_analog(*this, "analogue")
+{
+}
+
+
+//-------------------------------------------------
+// device_start - device-specific startup
+//-------------------------------------------------
+
+void arc_upa_hccs_device::device_start()
+{
+}
+
+
+//**************************************************************************
+// IMPLEMENTATION
+//**************************************************************************
+
+int arc_upa_hccs_device::get_analogue_input(int channel_number)
+{
+ return m_analog->ch_r(channel_number) << 8;
+}
+
+} // anonymous namespace
+
+
+//**************************************************************************
+// DEVICE DEFINITIONS
+//**************************************************************************
+
+DEFINE_DEVICE_TYPE_PRIVATE(ARC_UPA_HCCS, device_archimedes_podule_interface, arc_upa_hccs_device, "arc_upa_hccs", "HCCS User/Analogue Podule")
diff --git a/src/devices/bus/archimedes/podule/io_hccs.h b/src/devices/bus/archimedes/podule/io_hccs.h
new file mode 100644
index 00000000000..6287e5cedbf
--- /dev/null
+++ b/src/devices/bus/archimedes/podule/io_hccs.h
@@ -0,0 +1,19 @@
+// license:BSD-3-Clause
+// copyright-holders:Nigel Barnes
+/**********************************************************************
+
+ HCCS User/Analogue Podule
+
+**********************************************************************/
+
+#ifndef MAME_BUS_ARCHIMEDES_PODULE_IO_HCCS_H
+#define MAME_BUS_ARCHIMEDES_PODULE_IO_HCCS_H
+
+#pragma once
+
+#include "slot.h"
+
+// device type definition
+DECLARE_DEVICE_TYPE(ARC_UPA_HCCS, device_archimedes_podule_interface)
+
+#endif // MAME_BUS_ARCHIMEDES_PODULE_IO_HCCS_H
diff --git a/src/devices/bus/archimedes/podule/io_morley.cpp b/src/devices/bus/archimedes/podule/io_morley.cpp
new file mode 100644
index 00000000000..d030e3120f8
--- /dev/null
+++ b/src/devices/bus/archimedes/podule/io_morley.cpp
@@ -0,0 +1,338 @@
+// license:BSD-3-Clause
+// copyright-holders:Nigel Barnes
+/**********************************************************************
+
+ Acorn AGA30 BBC I/O Podule
+
+ http://chrisacorns.computinghistory.org.uk/32bit_UpgradesA2G/Acorn_AGA30_AnalogueUserP.html
+
+ Morley Electronics Analogue and User Interface
+
+ http://chrisacorns.computinghistory.org.uk/32bit_UpgradesH2Z/Morley_AnalogUIF.html
+
+ Morley Electronics User/MIDI/Analogue Interface
+
+ http://chrisacorns.computinghistory.org.uk/32bit_UpgradesH2Z/Morley_UserMIDIAnalogue.html
+
+**********************************************************************/
+
+#include "emu.h"
+#include "io_morley.h"
+#include "machine/6522via.h"
+#include "machine/input_merger.h"
+#include "machine/mc68681.h"
+#include "machine/upd7002.h"
+#include "bus/bbc/analogue/analogue.h"
+#include "bus/bbc/userport/userport.h"
+#include "bus/midi/midi.h"
+
+
+namespace {
+
+// ======================> arc_io_morley_device
+
+class arc_io_morley_device :
+ public device_t,
+ public device_archimedes_podule_interface
+{
+protected:
+ arc_io_morley_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, u32 clock);
+
+ // device-level overrides
+ virtual void device_start() override ATTR_COLD;
+ virtual void device_reset() override ATTR_COLD;
+
+ void add_userport(machine_config &config);
+ void add_analogue(machine_config &config);
+ void add_midi(machine_config &config);
+
+ required_memory_region m_podule_rom;
+ required_device<input_merger_device> m_irqs;
+ optional_device<bbc_analogue_slot_device> m_analog;
+
+ u8 m_rom_page;
+
+ int get_analogue_input(int channel_number);
+ void upd7002_eoc(int state);
+};
+
+
+// ======================> arc_bbcio_aga30_device
+
+class arc_bbcio_aga30_device : public arc_io_morley_device
+{
+public:
+ // construction/destruction
+ arc_bbcio_aga30_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock);
+
+protected:
+ // optional information overrides
+ virtual void device_add_mconfig(machine_config &config) override ATTR_COLD;
+ virtual const tiny_rom_entry *device_rom_region() const override ATTR_COLD;
+
+ // device_archimedes_podule_interface overrides
+ virtual void ioc_map(address_map &map) override ATTR_COLD;
+ virtual void memc_map(address_map &map) override ATTR_COLD;
+};
+
+
+// ======================> arc_ua_morley_device
+
+class arc_ua_morley_device : public arc_io_morley_device
+{
+public:
+ // construction/destruction
+ arc_ua_morley_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock);
+
+protected:
+ // optional information overrides
+ virtual void device_add_mconfig(machine_config &config) override ATTR_COLD;
+ virtual const tiny_rom_entry *device_rom_region() const override ATTR_COLD;
+
+ // device_archimedes_podule_interface overrides
+ virtual void ioc_map(address_map &map) override ATTR_COLD;
+ virtual void memc_map(address_map &map) override ATTR_COLD;
+};
+
+
+// ======================> arc_uma_morley_device
+
+class arc_uma_morley_device : public arc_io_morley_device
+{
+public:
+ // construction/destruction
+ arc_uma_morley_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock);
+
+protected:
+ // optional information overrides
+ virtual void device_add_mconfig(machine_config &config) override ATTR_COLD;
+ virtual const tiny_rom_entry *device_rom_region() const override ATTR_COLD;
+
+ // device_archimedes_podule_interface overrides
+ virtual void ioc_map(address_map &map) override ATTR_COLD;
+ virtual void memc_map(address_map &map) override ATTR_COLD;
+};
+
+
+void arc_bbcio_aga30_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(0x2000, 0x203f).rw("via", FUNC(via6522_device::read), FUNC(via6522_device::write)).umask32(0x000000ff);
+}
+
+void arc_bbcio_aga30_device::memc_map(address_map &map)
+{
+ map(0x1000, 0x100f).rw("upd7002", FUNC(upd7002_device::read), FUNC(upd7002_device::write)).umask32(0x000000ff);
+}
+
+
+void arc_ua_morley_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) & 0x7800)]; })).umask32(0x000000ff);
+ map(0x2000, 0x203f).rw("via", FUNC(via6522_device::read), FUNC(via6522_device::write)).umask32(0x000000ff);
+}
+
+void arc_ua_morley_device::memc_map(address_map &map)
+{
+ map(0x1000, 0x100f).rw("upd7002", FUNC(upd7002_device::read), FUNC(upd7002_device::write)).umask32(0x000000ff);
+}
+
+
+void arc_uma_morley_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) & 0x7800)]; })).umask32(0x000000ff);
+ map(0x2000, 0x203f).rw("via", FUNC(via6522_device::read), FUNC(via6522_device::write)).umask32(0x000000ff);
+ map(0x3000, 0x303f).rw("uart", FUNC(scn2681_device::read), FUNC(scn2681_device::write)).umask32(0x000000ff);
+}
+
+void arc_uma_morley_device::memc_map(address_map &map)
+{
+ map(0x1000, 0x100f).rw("upd7002", FUNC(upd7002_device::read), FUNC(upd7002_device::write)).umask32(0x000000ff);
+}
+
+
+//-------------------------------------------------
+// ROM( aga30 )
+//-------------------------------------------------
+
+ROM_START( aga30 )
+ ROM_REGION(0x4000, "podule_rom", 0)
+ ROM_SYSTEM_BIOS(0, "1", "First release 08-Mar-90")
+ ROMX_LOAD("morleyio_v2.01.bin", 0x0000, 0x4000, CRC(b149f631) SHA1(ed8d0caa478f030e11348b23e915897f27dcf153), ROM_BIOS(0))
+ROM_END
+
+ROM_START( ua )
+ ROM_REGION(0x8000, "podule_rom", 0)
+ ROM_SYSTEM_BIOS(0, "1", "First release 08-Mar-90")
+ ROMX_LOAD("morley_ua_16bit_v2.01.bin", 0x0000, 0x8000, CRC(736f8a07) SHA1(423208fb3132400d3582b29481b8f7b7e6cd0c70), ROM_BIOS(0))
+ROM_END
+
+ROM_START( uma )
+ ROM_REGION(0x8000, "podule_rom", 0)
+ ROM_SYSTEM_BIOS(0, "2", "Second release 03-Jun-93")
+ ROMX_LOAD("morley_uma_eprom_v1.00.bin", 0x0000, 0x8000, CRC(7474ec1a) SHA1(0db73540fc329b71a977a2be20c66ae2ae39df78), ROM_BIOS(0))
+ROM_END
+
+const tiny_rom_entry *arc_bbcio_aga30_device::device_rom_region() const
+{
+ return ROM_NAME( aga30 );
+}
+
+const tiny_rom_entry *arc_ua_morley_device::device_rom_region() const
+{
+ return ROM_NAME( ua );
+}
+
+const tiny_rom_entry *arc_uma_morley_device::device_rom_region() const
+{
+ return ROM_NAME( uma );
+}
+
+
+//-------------------------------------------------
+// device_add_mconfig - add device configuration
+//-------------------------------------------------
+
+void arc_io_morley_device::add_userport(machine_config &config)
+{
+ via6522_device &via(MOS6522(config, "via", DERIVED_CLOCK(1, 4)));
+ via.irq_handler().set(m_irqs, FUNC(input_merger_device::in_w<0>));
+ via.readpa_handler().set(m_analog, FUNC(bbc_analogue_slot_device::pb_r)).lshift(2);
+ via.writepa_handler().set([this](u8 data) { m_rom_page = data; });
+ via.readpb_handler().set("userport", FUNC(bbc_userport_slot_device::pb_r));
+ via.writepb_handler().set("userport", FUNC(bbc_userport_slot_device::pb_w));
+ via.cb1_handler().set("userport", FUNC(bbc_userport_slot_device::write_cb1));
+ via.cb2_handler().set("userport", FUNC(bbc_userport_slot_device::write_cb2));
+
+ bbc_userport_slot_device &userport(BBC_USERPORT_SLOT(config, "userport", bbc_userport_devices, nullptr));
+ userport.cb1_handler().set("via", FUNC(via6522_device::write_cb1));
+ userport.cb2_handler().set("via", FUNC(via6522_device::write_cb2));
+}
+
+void arc_io_morley_device::add_analogue(machine_config &config)
+{
+ upd7002_device &upd7002(UPD7002(config, "upd7002", DERIVED_CLOCK(1, 4)));
+ upd7002.set_get_analogue_callback(FUNC(arc_io_morley_device::get_analogue_input));
+ upd7002.set_eoc_callback(FUNC(arc_io_morley_device::upd7002_eoc));
+
+ BBC_ANALOGUE_SLOT(config, m_analog, bbc_analogue_devices, nullptr);
+ m_analog->lpstb_handler().set("via", FUNC(via6522_device::write_ca1));
+}
+
+void arc_io_morley_device::add_midi(machine_config &config)
+{
+ scn2681_device &uart(SCN2681(config, "uart", DERIVED_CLOCK(1, 4)));
+ uart.irq_cb().set(m_irqs, FUNC(input_merger_device::in_w<2>));
+ uart.a_tx_cb().set("mdout", FUNC(midi_port_device::write_txd));
+ uart.a_tx_cb().append("mdthru", FUNC(midi_port_device::write_txd));
+
+ auto &mdin(MIDI_PORT(config, "mdin"));
+ midiin_slot(mdin);
+ mdin.rxd_handler().set("uart", FUNC(scn2681_device::rx_a_w));
+ mdin.rxd_handler().append("mdthru", FUNC(midi_port_device::write_txd));
+
+ midiout_slot(MIDI_PORT(config, "mdthru"));
+ midiout_slot(MIDI_PORT(config, "mdout"));
+}
+
+
+void arc_bbcio_aga30_device::device_add_mconfig(machine_config &config)
+{
+ INPUT_MERGER_ANY_HIGH(config, "irqs").output_handler().set([this](int state) { set_pirq(state); });
+ add_userport(config);
+ add_analogue(config);
+}
+
+void arc_ua_morley_device::device_add_mconfig(machine_config &config)
+{
+ INPUT_MERGER_ANY_HIGH(config, "irqs").output_handler().set([this](int state) { set_pirq(state); });
+ add_userport(config);
+ add_analogue(config);
+}
+
+void arc_uma_morley_device::device_add_mconfig(machine_config &config)
+{
+ INPUT_MERGER_ANY_HIGH(config, "irqs").output_handler().set([this](int state) { set_pirq(state); });
+ add_userport(config);
+ add_analogue(config);
+ add_midi(config);
+}
+
+//**************************************************************************
+// LIVE DEVICE
+//**************************************************************************
+
+//-------------------------------------------------
+// arc_io_morley_device - constructor
+//-------------------------------------------------
+
+arc_io_morley_device::arc_io_morley_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_irqs(*this, "irqs")
+ , m_analog(*this, "analogue")
+ , m_rom_page(0)
+{
+}
+
+arc_bbcio_aga30_device::arc_bbcio_aga30_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock)
+ : arc_io_morley_device(mconfig, ARC_BBCIO_AGA30, tag, owner, clock)
+{
+}
+
+arc_ua_morley_device::arc_ua_morley_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock)
+ : arc_io_morley_device(mconfig, ARC_UA_MORLEY, tag, owner, clock)
+{
+}
+
+arc_uma_morley_device::arc_uma_morley_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock)
+ : arc_io_morley_device(mconfig, ARC_UMA_MORLEY, tag, owner, clock)
+{
+}
+
+
+//-------------------------------------------------
+// device_start - device-specific startup
+//-------------------------------------------------
+
+void arc_io_morley_device::device_start()
+{
+ save_item(NAME(m_rom_page));
+}
+
+
+//-------------------------------------------------
+// device_reset - device-specific reset
+//-------------------------------------------------
+
+void arc_io_morley_device::device_reset()
+{
+ m_rom_page = 0x00;
+}
+
+
+//**************************************************************************
+// IMPLEMENTATION
+//**************************************************************************
+
+int arc_io_morley_device::get_analogue_input(int channel_number)
+{
+ return m_analog->ch_r(channel_number) << 8;
+}
+
+void arc_io_morley_device::upd7002_eoc(int state)
+{
+ m_irqs->in_w<1>(!state);
+}
+
+} // anonymous namespace
+
+
+//**************************************************************************
+// DEVICE DEFINITIONS
+//**************************************************************************
+
+DEFINE_DEVICE_TYPE_PRIVATE(ARC_BBCIO_AGA30, device_archimedes_podule_interface, arc_bbcio_aga30_device, "arc_bbcio_aga30", "Acorn AGA30 BBC I/O Podule")
+DEFINE_DEVICE_TYPE_PRIVATE(ARC_UA_MORLEY, device_archimedes_podule_interface, arc_ua_morley_device, "arc_ua_morley", "Morley Electronics Analogue and User Interface")
+DEFINE_DEVICE_TYPE_PRIVATE(ARC_UMA_MORLEY, device_archimedes_podule_interface, arc_uma_morley_device, "arc_uma_morley", "Morley Electronics User/MIDI/Analogue Interface")
diff --git a/src/devices/bus/archimedes/podule/io_morley.h b/src/devices/bus/archimedes/podule/io_morley.h
new file mode 100644
index 00000000000..da04a36ac8f
--- /dev/null
+++ b/src/devices/bus/archimedes/podule/io_morley.h
@@ -0,0 +1,21 @@
+// license:BSD-3-Clause
+// copyright-holders:Nigel Barnes
+/**********************************************************************
+
+ Morley Electronics Analogue and User Interface
+
+**********************************************************************/
+
+#ifndef MAME_BUS_ARCHIMEDES_PODULE_IO_MORLEY_H
+#define MAME_BUS_ARCHIMEDES_PODULE_IO_MORLEY_H
+
+#pragma once
+
+#include "slot.h"
+
+// device type definition
+DECLARE_DEVICE_TYPE(ARC_BBCIO_AGA30, device_archimedes_podule_interface)
+DECLARE_DEVICE_TYPE(ARC_UA_MORLEY, device_archimedes_podule_interface)
+DECLARE_DEVICE_TYPE(ARC_UMA_MORLEY, device_archimedes_podule_interface)
+
+#endif // MAME_BUS_ARCHIMEDES_PODULE_IO_MORLEY_H
diff --git a/src/devices/bus/archimedes/podule/io_we.cpp b/src/devices/bus/archimedes/podule/io_we.cpp
new file mode 100644
index 00000000000..d05e646ec6c
--- /dev/null
+++ b/src/devices/bus/archimedes/podule/io_we.cpp
@@ -0,0 +1,190 @@
+// license:BSD-3-Clause
+// copyright-holders:Nigel Barnes
+/**********************************************************************
+
+ Watford Electronics A3000 BBC User I/O
+
+ http://chrisacorns.computinghistory.org.uk/32bit_UpgradesH2Z/WE_A3000_IICUserAnalog.html
+
+**********************************************************************/
+
+#include "emu.h"
+#include "io_we.h"
+#include "machine/6522via.h"
+#include "machine/input_merger.h"
+#include "machine/upd7002.h"
+#include "bus/bbc/analogue/analogue.h"
+#include "bus/bbc/userport/userport.h"
+
+
+namespace {
+
+// ======================> arc_bbcio_we_device
+
+class arc_bbcio_we_device :
+ public device_t,
+ public device_archimedes_podule_interface
+{
+public:
+ // construction/destruction
+ arc_bbcio_we_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock);
+
+protected:
+ // device-level overrides
+ virtual void device_start() override ATTR_COLD;
+ virtual void device_reset() override ATTR_COLD;
+
+ // optional information overrides
+ virtual void device_add_mconfig(machine_config &config) override ATTR_COLD;
+ virtual const tiny_rom_entry *device_rom_region() const override ATTR_COLD;
+
+ // device_archimedes_podule_interface overrides
+ virtual void ioc_map(address_map &map) override ATTR_COLD;
+ virtual void memc_map(address_map &map) override ATTR_COLD;
+
+private:
+ required_memory_region m_podule_rom;
+ required_device<input_merger_device> m_irqs;
+ required_device<bbc_analogue_slot_device> m_analog;
+ required_device<upd7002_device> m_upd7002;
+
+ u8 m_rom_page;
+
+ int get_analogue_input(int channel_number);
+ void upd7002_eoc(int state);
+
+ int m_adc_irq;
+ int m_via_irq;
+};
+
+
+void arc_bbcio_we_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(0x2000, 0x203f).rw("via", FUNC(via6522_device::read), FUNC(via6522_device::write)).umask32(0x000000ff);
+ map(0x3000, 0x3000).lr8(NAME([this]() { return (m_via_irq << 7); }));
+ map(0x3800, 0x3800).lr8(NAME([this]() { return (m_adc_irq << 7); }));
+}
+
+void arc_bbcio_we_device::memc_map(address_map &map)
+{
+ map(0x1000, 0x10ff).lr8(NAME([this](offs_t offset) { return m_upd7002->read(offset >> 4); })).umask32(0x000000ff);
+ map(0x1000, 0x10ff).lw8(NAME([this](offs_t offset, u8 data) { m_upd7002->write(offset >> 4, data); })).umask32(0x000000ff);
+}
+
+
+//-------------------------------------------------
+// ROM( bbcio_we )
+//-------------------------------------------------
+
+ROM_START( bbcio_we )
+ ROM_REGION(0x4000, "podule_rom", 0)
+ ROM_SYSTEM_BIOS(0, "100", "1.00 (16 Jan 1992)")
+ ROMX_LOAD("a3000_io-1.01.bin", 0x0000, 0x4000, CRC(a432bdcd) SHA1(05c79e38707e406eed23cec6b3d2730e8fe550e8), ROM_BIOS(0))
+ROM_END
+
+const tiny_rom_entry *arc_bbcio_we_device::device_rom_region() const
+{
+ return ROM_NAME( bbcio_we );
+}
+
+
+//-------------------------------------------------
+// device_add_mconfig - add device configuration
+//-------------------------------------------------
+
+void arc_bbcio_we_device::device_add_mconfig(machine_config &config)
+{
+ INPUT_MERGER_ANY_HIGH(config, "irqs").output_handler().set([this](int state) { set_pirq(state); });
+
+ via6522_device &via(MOS6522(config, "via", DERIVED_CLOCK(1, 4)));
+ via.irq_handler().set([this](int state) { m_via_irq = state; m_irqs->in_w<0>(state); });
+ via.readpa_handler().set(m_analog, FUNC(bbc_analogue_slot_device::pb_r)).lshift(2);
+ via.writepa_handler().set([this](u8 data) { m_rom_page = data; });
+ via.readpb_handler().set("userport", FUNC(bbc_userport_slot_device::pb_r));
+ via.writepb_handler().set("userport", FUNC(bbc_userport_slot_device::pb_w));
+ via.cb1_handler().set("userport", FUNC(bbc_userport_slot_device::write_cb1));
+ via.cb2_handler().set("userport", FUNC(bbc_userport_slot_device::write_cb2));
+
+ bbc_userport_slot_device &userport(BBC_USERPORT_SLOT(config, "userport", bbc_userport_devices, nullptr));
+ userport.cb1_handler().set("via", FUNC(via6522_device::write_cb1));
+ userport.cb2_handler().set("via", FUNC(via6522_device::write_cb2));
+
+ upd7002_device &upd7002(UPD7002(config, "upd7002", DERIVED_CLOCK(1, 4)));
+ upd7002.set_get_analogue_callback(FUNC(arc_bbcio_we_device::get_analogue_input));
+ upd7002.set_eoc_callback(FUNC(arc_bbcio_we_device::upd7002_eoc));
+
+ BBC_ANALOGUE_SLOT(config, m_analog, bbc_analogue_devices, nullptr);
+ m_analog->lpstb_handler().set("via", FUNC(via6522_device::write_ca1));
+
+ // TODO: internal A3000 version adds IIC port
+}
+
+
+//**************************************************************************
+// LIVE DEVICE
+//**************************************************************************
+
+//-------------------------------------------------
+// arc_bbcio_we_device - constructor
+//-------------------------------------------------
+
+arc_bbcio_we_device::arc_bbcio_we_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock)
+ : device_t(mconfig, ARC_BBCIO_WE, tag, owner, clock)
+ , device_archimedes_podule_interface(mconfig, *this)
+ , m_podule_rom(*this, "podule_rom")
+ , m_irqs(*this, "irqs")
+ , m_analog(*this, "analogue")
+ , m_upd7002(*this, "upd7002")
+ , m_rom_page(0)
+ , m_adc_irq(0)
+ , m_via_irq(0)
+{
+}
+
+
+//-------------------------------------------------
+// device_start - device-specific startup
+//-------------------------------------------------
+
+void arc_bbcio_we_device::device_start()
+{
+ save_item(NAME(m_rom_page));
+}
+
+
+//-------------------------------------------------
+// device_reset - device-specific reset
+//-------------------------------------------------
+
+void arc_bbcio_we_device::device_reset()
+{
+ m_rom_page = 0x00;
+}
+
+
+//**************************************************************************
+// IMPLEMENTATION
+//**************************************************************************
+
+int arc_bbcio_we_device::get_analogue_input(int channel_number)
+{
+ return m_analog->ch_r(channel_number) << 8;
+}
+
+void arc_bbcio_we_device::upd7002_eoc(int state)
+{
+ m_adc_irq = !state;
+
+ m_irqs->in_w<1>(!state);
+}
+
+
+} // anonymous namespace
+
+
+//**************************************************************************
+// DEVICE DEFINITIONS
+//**************************************************************************
+
+DEFINE_DEVICE_TYPE_PRIVATE(ARC_BBCIO_WE, device_archimedes_podule_interface, arc_bbcio_we_device, "arc_bbcio_we", "Watford Electronics BBC User I/O Card")
diff --git a/src/devices/bus/archimedes/podule/io_we.h b/src/devices/bus/archimedes/podule/io_we.h
new file mode 100644
index 00000000000..37a767eaee9
--- /dev/null
+++ b/src/devices/bus/archimedes/podule/io_we.h
@@ -0,0 +1,19 @@
+// license:BSD-3-Clause
+// copyright-holders:Nigel Barnes
+/**********************************************************************
+
+ Watford Electronics A3000 BBC User I/O
+
+**********************************************************************/
+
+#ifndef MAME_BUS_ARCHIMEDES_PODULE_IO_WE_H
+#define MAME_BUS_ARCHIMEDES_PODULE_IO_WE_H
+
+#pragma once
+
+#include "slot.h"
+
+// device type definition
+DECLARE_DEVICE_TYPE(ARC_BBCIO_WE, device_archimedes_podule_interface)
+
+#endif // MAME_BUS_ARCHIMEDES_PODULE_IO_WE_H
diff --git a/src/devices/bus/archimedes/podule/lark.cpp b/src/devices/bus/archimedes/podule/lark.cpp
new file mode 100644
index 00000000000..cfb1fe80333
--- /dev/null
+++ b/src/devices/bus/archimedes/podule/lark.cpp
@@ -0,0 +1,255 @@
+// license:BSD-3-Clause
+// copyright-holders:Nigel Barnes
+/**********************************************************************
+
+ Wild Vision/Computer Concepts Lark A16
+
+ http://chrisacorns.computinghistory.org.uk/32bit_UpgradesA2G/CC_Lark.html
+
+**********************************************************************/
+
+#include "emu.h"
+#include "lark.h"
+#include "machine/7200fifo.h"
+#include "machine/ins8250.h"
+#include "sound/ad1848.h"
+#include "bus/midi/midi.h"
+#include "speaker.h"
+
+
+namespace {
+
+class arc_lark_device :
+ public device_t,
+ public device_archimedes_podule_interface
+{
+public:
+ // construction/destruction
+ arc_lark_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock);
+
+ static constexpr feature_type unemulated_features() { return feature::CAPTURE; }
+
+protected:
+ // device-level overrides
+ virtual void device_start() override ATTR_COLD;
+ virtual void device_reset() override ATTR_COLD;
+
+ // optional information overrides
+ virtual void device_add_mconfig(machine_config &config) override ATTR_COLD;
+ virtual const tiny_rom_entry *device_rom_region() const override ATTR_COLD;
+
+ // device_archimedes_podule_interface overrides
+ virtual void ioc_map(address_map &map) override ATTR_COLD;
+ virtual void memc_map(address_map &map) override ATTR_COLD;
+
+private:
+ required_memory_region m_podule_rom;
+ required_device<ad1848_device> m_ad1848;
+ required_device<idt7202_device> m_fifo_in;
+ required_device<idt7202_device> m_fifo_out;
+
+ u8 status_r();
+ void control_w(u8 data);
+
+ void update_irqs();
+ void set_irq(u8 mask, int state);
+ void playback_drq(int state);
+
+ u8 m_rom_page;
+ u8 m_status;
+ u8 m_ctrl;
+
+ static constexpr u8 IRQ_MASTER = 1 << 0;
+ static constexpr u8 IRQ_AD1848 = 1 << 1;
+ static constexpr u8 IRQ_16550 = 1 << 2;
+ static constexpr u8 IRQ_FIFO_OUT = 1 << 6;
+ static constexpr u8 IRQ_FIFO_IN = 1 << 7;
+
+ static constexpr u8 CTRL_FIFO_OUT_ENA = 1 << 3;
+ static constexpr u8 CTRL_FIFO_IN_ENA = 1 << 4;
+ static constexpr u8 CTRL_RESET = 1 << 7;
+};
+
+
+void arc_lark_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) & 0x1f800)]; })).umask32(0x000000ff);
+ map(0x0000, 0x0000).lw8(NAME([](u8 data) { })); // XC3030 FPGA
+ map(0x2000, 0x2000).lw8(NAME([this](u8 data) { m_rom_page = data; }));
+ map(0x3000, 0x3000).rw(FUNC(arc_lark_device::status_r), FUNC(arc_lark_device::control_w));
+ map(0x3400, 0x341f).rw("uart", FUNC(ns16550_device::ins8250_r), FUNC(ns16550_device::ins8250_w)).umask32(0x000000ff);
+ map(0x3c00, 0x3c0f).rw(m_ad1848, FUNC(ad1848_device::read), FUNC(ad1848_device::write)).umask32(0x000000ff);
+}
+
+void arc_lark_device::memc_map(address_map &map)
+{
+ map(0x0000, 0x0003).mirror(0x1ffc)
+ .lr16(NAME([this]()
+ {
+ u16 data;
+ data = m_fifo_in->data_byte_r() << 8;
+ data |= m_fifo_in->data_byte_r();
+ return data;
+ }))
+ .lw16(NAME([this](u16 data)
+ {
+ m_fifo_out->data_byte_w(data >> 8);
+ m_fifo_out->data_byte_w(data & 0xff);
+
+ })).umask32(0x0000ffff);
+}
+
+
+//-------------------------------------------------
+// ROM( lark )
+//-------------------------------------------------
+
+ROM_START( lark )
+ ROM_REGION(0x20000, "podule_rom", 0)
+ ROM_SYSTEM_BIOS(0, "110", "Lark A16 V1.10 (12 Jul 1994)")
+ ROMX_LOAD("lark.rom", 0x0000, 0x20000, CRC(9bb6cb99) SHA1(f0b2ba52d0069dfe00a7ba66fba23e0eb2346d8c), ROM_BIOS(0))
+ROM_END
+
+const tiny_rom_entry *arc_lark_device::device_rom_region() const
+{
+ return ROM_NAME( lark );
+}
+
+
+//-------------------------------------------------
+// device_add_mconfig - add device configuration
+//-------------------------------------------------
+
+void arc_lark_device::device_add_mconfig(machine_config &config)
+{
+ AD1848(config, m_ad1848, 0);
+ //m_ad1848->irq().set([this](int state) { set_irq(IRQ_AD1848, state); }); // not used/connected?
+ m_ad1848->drq().set(FUNC(arc_lark_device::playback_drq));
+
+ IDT7202(config, m_fifo_out); // AM7202A
+ m_fifo_out->hf_handler().set([this](int state) { set_irq(IRQ_FIFO_OUT, state); });
+ IDT7202(config, m_fifo_in); // AM7202A
+ m_fifo_in->hf_handler().set([this](int state) { set_irq(IRQ_FIFO_IN, !state); });
+
+ ns16550_device &uart(NS16550(config, "uart", DERIVED_CLOCK(1, 4)));
+ uart.out_tx_callback().set("mdout", FUNC(midi_port_device::write_txd));
+ uart.out_tx_callback().append("mdthru", FUNC(midi_port_device::write_txd));
+ uart.out_int_callback().set([this](int state) { set_irq(IRQ_16550, state); });
+
+ midi_port_device &mdin(MIDI_PORT(config, "mdin", midiin_slot, "midiin"));
+ mdin.rxd_handler().set("uart", FUNC(ns16550_device::rx_w));
+ mdin.rxd_handler().append("mdthru", FUNC(midi_port_device::write_txd));
+ midiout_slot(MIDI_PORT(config, "mdout"));
+ midiout_slot(MIDI_PORT(config, "mdthru"));
+}
+
+
+//**************************************************************************
+// LIVE DEVICE
+//**************************************************************************
+
+//-------------------------------------------------
+// arc_lark_device - constructor
+//-------------------------------------------------
+
+arc_lark_device::arc_lark_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock)
+ : device_t(mconfig, ARC_LARK, tag, owner, clock)
+ , device_archimedes_podule_interface(mconfig, *this)
+ , m_podule_rom(*this, "podule_rom")
+ , m_ad1848(*this, "ad1848")
+ , m_fifo_in(*this, "fifo_in")
+ , m_fifo_out(*this, "fifo_out")
+ , m_rom_page(0)
+ , m_status(0)
+ , m_ctrl(0)
+{
+}
+
+
+//-------------------------------------------------
+// device_start - device-specific startup
+//-------------------------------------------------
+
+void arc_lark_device::device_start()
+{
+ save_item(NAME(m_rom_page));
+ save_item(NAME(m_status));
+ save_item(NAME(m_ctrl));
+}
+
+//-------------------------------------------------
+// device_reset - device-specific reset
+//-------------------------------------------------
+
+void arc_lark_device::device_reset()
+{
+ m_rom_page = 0x00;
+ m_status = 0x00;
+}
+
+
+//**************************************************************************
+// IMPLEMENTATION
+//**************************************************************************
+
+u8 arc_lark_device::status_r()
+{
+ if (m_status ^ IRQ_FIFO_IN)
+ return (m_status | IRQ_MASTER);
+ else
+ return m_status;
+}
+
+void arc_lark_device::control_w(u8 data)
+{
+ m_ctrl = data;
+
+ update_irqs();
+
+ if (m_ctrl & CTRL_RESET)
+ m_fifo_out->reset();
+}
+
+void arc_lark_device::update_irqs()
+{
+ u8 irq_status = m_status ^ 0x80;
+
+ if (!(m_ctrl & CTRL_FIFO_IN_ENA))
+ irq_status &= 0x7f;
+
+ set_pirq(irq_status ? ASSERT_LINE : CLEAR_LINE);
+}
+
+void arc_lark_device::set_irq(u8 mask, int state)
+{
+ if (state)
+ m_status |= mask;
+ else
+ m_status &= ~mask;
+
+ update_irqs();
+}
+
+void arc_lark_device::playback_drq(int state)
+{
+ if (state)
+ {
+ if (m_ctrl & CTRL_FIFO_OUT_ENA)
+ {
+ // 16-bit stereo data stream
+ m_ad1848->dack_w(m_fifo_out->data_byte_r());
+ m_ad1848->dack_w(m_fifo_out->data_byte_r());
+ m_ad1848->dack_w(m_fifo_out->data_byte_r());
+ m_ad1848->dack_w(m_fifo_out->data_byte_r());
+ }
+ }
+}
+
+} // anonymous namespace
+
+
+//**************************************************************************
+// DEVICE DEFINITIONS
+//**************************************************************************
+
+DEFINE_DEVICE_TYPE_PRIVATE(ARC_LARK, device_archimedes_podule_interface, arc_lark_device, "arc_lark", "Wild Vision/Computer Concepts Lark A16")
diff --git a/src/devices/bus/archimedes/podule/lark.h b/src/devices/bus/archimedes/podule/lark.h
new file mode 100644
index 00000000000..46202f82b2d
--- /dev/null
+++ b/src/devices/bus/archimedes/podule/lark.h
@@ -0,0 +1,19 @@
+// license:BSD-3-Clause
+// copyright-holders:Nigel Barnes
+/**********************************************************************
+
+ Wild Vision/Computer Concepts Lark A16
+
+**********************************************************************/
+
+#ifndef MAME_BUS_ARCHIMEDES_PODULE_LARK_H
+#define MAME_BUS_ARCHIMEDES_PODULE_LARK_H
+
+#pragma once
+
+#include "slot.h"
+
+// device type definition
+DECLARE_DEVICE_TYPE(ARC_LARK, device_archimedes_podule_interface)
+
+#endif // MAME_BUS_ARCHIMEDES_PODULE_LARK_H
diff --git a/src/devices/bus/archimedes/podule/laserd.cpp b/src/devices/bus/archimedes/podule/laserd.cpp
new file mode 100644
index 00000000000..e7d815dd6b5
--- /dev/null
+++ b/src/devices/bus/archimedes/podule/laserd.cpp
@@ -0,0 +1,173 @@
+// license:BSD-3-Clause
+// copyright-holders:Nigel Barnes
+/**********************************************************************
+
+ Computer Concepts LaserDirect
+
+ http://chrisacorns.computinghistory.org.uk/32bit_UpgradesA2G/CC_LaserDirect.html
+
+ TODO:
+ - everything, this is skeleton with ROM.
+
+**********************************************************************/
+
+#include "emu.h"
+#include "laserd.h"
+#include "machine/7200fifo.h"
+#include "bus/centronics/ctronics.h"
+
+
+namespace {
+
+class arc_laserd_device :
+ public device_t,
+ public device_archimedes_podule_interface
+{
+public:
+ static constexpr feature_type unemulated_features() { return feature::PRINTER; }
+
+protected:
+ arc_laserd_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, u32 clock);
+
+ // device-level overrides
+ virtual void device_start() override ATTR_COLD;
+ virtual void device_reset() override ATTR_COLD;
+
+ // optional information overrides
+ virtual void device_add_mconfig(machine_config &config) override ATTR_COLD;
+
+ // device_archimedes_podule_interface overrides
+ virtual void ioc_map(address_map &map) override ATTR_COLD;
+ virtual void memc_map(address_map &map) override ATTR_COLD;
+
+private:
+ required_memory_region m_podule_rom;
+
+ u8 m_rom_page;
+};
+
+
+// ======================> arc_lbp4_device
+
+class arc_lbp4_device : public arc_laserd_device
+{
+public:
+ // construction/destruction
+ arc_lbp4_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 ATTR_COLD;
+};
+
+
+void arc_laserd_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) & 0x7800)]; })).umask32(0x000000ff);
+ map(0x0000, 0x3fff).lw8(NAME([this](u8 data) { m_rom_page = data ^ 0xff; })).umask32(0x000000ff);
+}
+
+void arc_laserd_device::memc_map(address_map &map)
+{
+ //map(0x0000, 0x0003).r("fifo0", FUNC(fifo7200_device::data_word_r)).umask32(0x0000ffff);
+ //map(0x0000, 0x0003).w("cent_data_out", FUNC(output_latch_device::write)).umask32(0x000000ff);
+ map(0x0004, 0x0007).r("cent_status_in", FUNC(input_buffer_device::read)).umask32(0x000000ff);
+ map(0x0004, 0x0007).w("cent_ctrl_out", FUNC(output_latch_device::write)).umask32(0x000000ff);
+}
+
+
+//-------------------------------------------------
+// ROM( lbp4 )
+//-------------------------------------------------
+
+ROM_START( lbp4 )
+ ROM_REGION(0x8000, "podule_rom", 0)
+ ROM_SYSTEM_BIOS(0, "405", "4.50 (04 Mar 1992)")
+ ROMX_LOAD("lbp-4_4.50.rom", 0x0000, 0x8000, CRC(f21b8089) SHA1(07503fa6d29d34cc4ceb972296c9bd178085e412), ROM_BIOS(0))
+ ROM_SYSTEM_BIOS(1, "201", "2.01 (25 Sep 1990)")
+ ROMX_LOAD("lbp-4_2.01.rom", 0x0000, 0x4000, CRC(cf40565b) SHA1(b70afed20340e62279742996da9b0ccef51f08e2), ROM_BIOS(1))
+ ROM_RELOAD(0x4000, 0x4000)
+ROM_END
+
+const tiny_rom_entry *arc_lbp4_device::device_rom_region() const
+{
+ return ROM_NAME( lbp4 );
+}
+
+
+//-------------------------------------------------
+// device_add_mconfig - add device configuration
+//-------------------------------------------------
+
+void arc_laserd_device::device_add_mconfig(machine_config &config)
+{
+ IDT7201(config, "fifo0");
+ IDT7201(config, "fifo1");
+
+ centronics_device &centronics(CENTRONICS(config, "printer", centronics_devices, "printer"));
+ centronics.ack_handler().set("cent_status_in", FUNC(input_buffer_device::write_bit5));
+ centronics.busy_handler().set("cent_status_in", FUNC(input_buffer_device::write_bit1));
+ centronics.perror_handler().set("cent_status_in", FUNC(input_buffer_device::write_bit4));
+ centronics.select_handler().set("cent_status_in", FUNC(input_buffer_device::write_bit3));
+ centronics.fault_handler().set("cent_status_in", FUNC(input_buffer_device::write_bit6));
+
+ output_latch_device &cent_data_out(OUTPUT_LATCH(config, "cent_data_out"));
+ centronics.set_output_latch(cent_data_out);
+
+ INPUT_BUFFER(config, "cent_status_in");
+
+ 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));
+}
+
+
+//**************************************************************************
+// LIVE DEVICE
+//**************************************************************************
+
+//-------------------------------------------------
+// arc_laserd_device - constructor
+//-------------------------------------------------
+
+arc_laserd_device::arc_laserd_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_page(0)
+{
+}
+
+arc_lbp4_device::arc_lbp4_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock)
+ : arc_laserd_device(mconfig, ARC_LBP4, tag, owner, clock)
+{
+}
+
+
+//-------------------------------------------------
+// device_start - device-specific startup
+//-------------------------------------------------
+
+void arc_laserd_device::device_start()
+{
+ save_item(NAME(m_rom_page));
+}
+
+//-------------------------------------------------
+// device_reset - device-specific reset
+//-------------------------------------------------
+
+void arc_laserd_device::device_reset()
+{
+ m_rom_page = 0xff;
+}
+
+} // anonymous namespace
+
+
+//**************************************************************************
+// DEVICE DEFINITIONS
+//**************************************************************************
+
+DEFINE_DEVICE_TYPE_PRIVATE(ARC_LBP4, device_archimedes_podule_interface, arc_lbp4_device, "arc_lbp4", "Computer Concepts LaserDirect (Canon LBP-4)")
+//DEFINE_DEVICE_TYPE_PRIVATE(ARC_LBP8, device_archimedes_podule_interface, arc_lbp8_device, "arc_lbp8", "Computer Concepts LaserDirect (Canon LBP-8)")
+//DEFINE_DEVICE_TYPE_PRIVATE(ARC_QUME, device_archimedes_podule_interface, arc_qume_device, "arc_qume", "Computer Concepts LaserDirect (Qume)")
diff --git a/src/devices/bus/archimedes/podule/laserd.h b/src/devices/bus/archimedes/podule/laserd.h
new file mode 100644
index 00000000000..431e8809c68
--- /dev/null
+++ b/src/devices/bus/archimedes/podule/laserd.h
@@ -0,0 +1,19 @@
+// license:BSD-3-Clause
+// copyright-holders:Nigel Barnes
+/**********************************************************************
+
+ Computer Concepts LaserDirect
+
+**********************************************************************/
+
+#ifndef MAME_BUS_ARCHIMEDES_PODULE_LASERD_H
+#define MAME_BUS_ARCHIMEDES_PODULE_LASERD_H
+
+#pragma once
+
+#include "slot.h"
+
+// device type definition
+DECLARE_DEVICE_TYPE(ARC_LBP4, device_archimedes_podule_interface)
+
+#endif // MAME_BUS_ARCHIMEDES_PODULE_LASERD_H
diff --git a/src/devices/bus/archimedes/podule/midi_emr.cpp b/src/devices/bus/archimedes/podule/midi_emr.cpp
new file mode 100644
index 00000000000..59fb7e783f9
--- /dev/null
+++ b/src/devices/bus/archimedes/podule/midi_emr.cpp
@@ -0,0 +1,208 @@
+// license:BSD-3-Clause
+// copyright-holders:Nigel Barnes
+/**********************************************************************
+
+ EMR MIDI Interface
+
+ http://chrisacorns.computinghistory.org.uk/32bit_UpgradesA2G/EMR_MIDI4.html
+
+**********************************************************************/
+
+#include "emu.h"
+#include "midi_emr.h"
+#include "machine/input_merger.h"
+#include "machine/mc68681.h"
+#include "bus/midi/midi.h"
+
+
+namespace {
+
+// ======================> arc_midi2_emr_device
+
+class arc_midi2_emr_device :
+ public device_t,
+ public device_archimedes_podule_interface
+{
+public:
+ // construction/destruction
+ arc_midi2_emr_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock);
+
+protected:
+ // device-level overrides
+ virtual void device_start() override ATTR_COLD;
+ virtual void device_reset() override ATTR_COLD;
+
+ // optional information overrides
+ virtual void device_add_mconfig(machine_config &config) override ATTR_COLD;
+ virtual const tiny_rom_entry *device_rom_region() const override ATTR_COLD;
+
+ // device_archimedes_podule_interface overrides
+ virtual void ioc_map(address_map &map) override ATTR_COLD;
+
+private:
+ required_memory_region m_podule_rom;
+
+ u8 m_rom_page;
+};
+
+
+// ======================> arc_midi4_emr_device
+
+class arc_midi4_emr_device :
+ public device_t,
+ public device_archimedes_podule_interface
+{
+public:
+ // construction/destruction
+ arc_midi4_emr_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock);
+
+protected:
+ // device-level overrides
+ virtual void device_start() override ATTR_COLD;
+
+ // optional information overrides
+ virtual void device_add_mconfig(machine_config &config) override ATTR_COLD;
+
+ // device_archimedes_podule_interface overrides
+ virtual void ioc_map(address_map &map) override ATTR_COLD;
+};
+
+
+void arc_midi2_emr_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) & 0x7800) ^ 0x4000)]; })).umask32(0x000000ff);
+ map(0x1000, 0x1000).lw8(NAME([this](u8 data) { m_rom_page = data; }));
+ map(0x2000, 0x203f).rw("uart", FUNC(scn2681_device::read), FUNC(scn2681_device::write)).umask32(0x000000ff);
+}
+
+
+void arc_midi4_emr_device::ioc_map(address_map &map)
+{
+ map(0x2000, 0x203f).rw("uart1", FUNC(scn2681_device::read), FUNC(scn2681_device::write)).umask32(0x000000ff);
+ map(0x3000, 0x303f).rw("uart2", FUNC(scn2681_device::read), FUNC(scn2681_device::write)).umask32(0x000000ff);
+}
+
+
+//-------------------------------------------------
+// ROM( midi2 )
+//-------------------------------------------------
+
+ROM_START( midi2 )
+ ROM_REGION(0x8000, "podule_rom", 0)
+ ROM_SYSTEM_BIOS(0, "314", "V3.14/9/8/89")
+ ROMX_LOAD("emr_midi2_v3.14.bin", 0x0000, 0x8000, CRC(7de739fe) SHA1(d0440e4ef0fa7bbab2ea3d6f9f3f1d4513aec8c0), ROM_BIOS(0))
+ROM_END
+
+const tiny_rom_entry *arc_midi2_emr_device::device_rom_region() const
+{
+ return ROM_NAME( midi2 );
+}
+
+
+//-------------------------------------------------
+// device_add_mconfig - add device configuration
+//-------------------------------------------------
+
+void arc_midi2_emr_device::device_add_mconfig(machine_config &config)
+{
+ scn2681_device &uart(SCN2681(config, "uart", DERIVED_CLOCK(1, 4))); // TODO: confirm device
+ uart.irq_cb().set([this](int state) { set_pirq(state); });
+ uart.a_tx_cb().set("mdout_a", FUNC(midi_port_device::write_txd));
+ uart.b_tx_cb().set("mdout_b", FUNC(midi_port_device::write_txd));
+
+ midi_port_device &mdin1(MIDI_PORT(config, "mdin_a", midiin_slot, "midiin"));
+ mdin1.rxd_handler().set("uart", FUNC(scn2681_device::rx_a_w));
+ midi_port_device &mdin2(MIDI_PORT(config, "mdin_b", midiin_slot, "midiin"));
+ mdin2.rxd_handler().set("uart", FUNC(scn2681_device::rx_b_w));
+
+ MIDI_PORT(config, "mdout_a", midiout_slot, "midiout");
+ MIDI_PORT(config, "mdout_b", midiout_slot, "midiout");
+}
+
+void arc_midi4_emr_device::device_add_mconfig(machine_config &config)
+{
+ INPUT_MERGER_ANY_HIGH(config, "irqs").output_handler().set([this](int state) { set_pirq(state); });
+
+ scn2681_device &uart1(SCN2681(config, "uart1", 3.6864_MHz_XTAL));
+ uart1.irq_cb().set("irqs", FUNC(input_merger_device::in_w<0>));
+ uart1.a_tx_cb().set("mdout_a", FUNC(midi_port_device::write_txd));
+ uart1.b_tx_cb().set("mdout_b", FUNC(midi_port_device::write_txd));
+
+ midi_port_device &mdin1(MIDI_PORT(config, "mdin_a", midiin_slot, "midiin"));
+ mdin1.rxd_handler().set("uart1", FUNC(scn2681_device::rx_a_w));
+ midi_port_device &mdin2(MIDI_PORT(config, "mdin_b", midiin_slot, "midiin"));
+ mdin2.rxd_handler().set("uart1", FUNC(scn2681_device::rx_b_w));
+
+ MIDI_PORT(config, "mdout_a", midiout_slot, "midiout");
+ MIDI_PORT(config, "mdout_b", midiout_slot, "midiout");
+
+ scn2681_device &uart2(SCN2681(config, "uart2", 3.6864_MHz_XTAL));
+ uart2.irq_cb().set("irqs", FUNC(input_merger_device::in_w<1>));
+ uart2.a_tx_cb().set("mdout_c", FUNC(midi_port_device::write_txd));
+ uart2.b_tx_cb().set("mdout_d", FUNC(midi_port_device::write_txd));
+
+ midi_port_device &mdin3(MIDI_PORT(config, "mdin_c", midiin_slot, "midiin"));
+ mdin3.rxd_handler().set("uart2", FUNC(scn2681_device::rx_a_w));
+ midi_port_device &mdin4(MIDI_PORT(config, "mdin_d", midiin_slot, "midiin"));
+ mdin4.rxd_handler().set("uart2", FUNC(scn2681_device::rx_b_w));
+
+ MIDI_PORT(config, "mdout_c", midiout_slot, "midiout");
+ MIDI_PORT(config, "mdout_d", midiout_slot, "midiout");
+}
+
+
+//**************************************************************************
+// LIVE DEVICE
+//**************************************************************************
+
+//-------------------------------------------------
+// arc_midi_emr_device - constructor
+//-------------------------------------------------
+
+arc_midi2_emr_device::arc_midi2_emr_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock)
+ : device_t(mconfig, ARC_MIDI2_EMR, tag, owner, clock)
+ , device_archimedes_podule_interface(mconfig, *this)
+ , m_podule_rom(*this, "podule_rom")
+ , m_rom_page(0)
+{
+}
+
+arc_midi4_emr_device::arc_midi4_emr_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock)
+ : device_t(mconfig, ARC_MIDI4_EMR, tag, owner, clock)
+ , device_archimedes_podule_interface(mconfig, *this)
+{
+}
+
+
+//-------------------------------------------------
+// device_start - device-specific startup
+//-------------------------------------------------
+
+void arc_midi2_emr_device::device_start()
+{
+ save_item(NAME(m_rom_page));
+}
+
+void arc_midi4_emr_device::device_start()
+{
+}
+
+
+//-------------------------------------------------
+// device_reset - device-specific reset
+//-------------------------------------------------
+
+void arc_midi2_emr_device::device_reset()
+{
+ m_rom_page = 0x00;
+}
+
+} // anonymous namespace
+
+
+//**************************************************************************
+// DEVICE DEFINITIONS
+//**************************************************************************
+
+DEFINE_DEVICE_TYPE_PRIVATE(ARC_MIDI2_EMR, device_archimedes_podule_interface, arc_midi2_emr_device, "arc_midi2", "EMR MIDI 2 Interface")
+DEFINE_DEVICE_TYPE_PRIVATE(ARC_MIDI4_EMR, device_archimedes_podule_interface, arc_midi4_emr_device, "arc_midi4", "EMR MIDI 4 Interface")
diff --git a/src/devices/bus/archimedes/podule/midi_emr.h b/src/devices/bus/archimedes/podule/midi_emr.h
new file mode 100644
index 00000000000..268b1b0d78c
--- /dev/null
+++ b/src/devices/bus/archimedes/podule/midi_emr.h
@@ -0,0 +1,20 @@
+// license:BSD-3-Clause
+// copyright-holders:Nigel Barnes
+/**********************************************************************
+
+ EMR MIDI Interface
+
+**********************************************************************/
+
+#ifndef MAME_BUS_ARCHIMEDES_PODULE_MIDI_EMR_H
+#define MAME_BUS_ARCHIMEDES_PODULE_MIDI_EMR_H
+
+#pragma once
+
+#include "slot.h"
+
+// device type definition
+DECLARE_DEVICE_TYPE(ARC_MIDI2_EMR, device_archimedes_podule_interface)
+DECLARE_DEVICE_TYPE(ARC_MIDI4_EMR, device_archimedes_podule_interface)
+
+#endif // MAME_BUS_ARCHIMEDES_PODULE_MIDI_EMR_H
diff --git a/src/devices/bus/archimedes/podule/midimax.cpp b/src/devices/bus/archimedes/podule/midimax.cpp
new file mode 100644
index 00000000000..90ca5be2c81
--- /dev/null
+++ b/src/devices/bus/archimedes/podule/midimax.cpp
@@ -0,0 +1,175 @@
+// license:BSD-3-Clause
+// copyright-holders:Nigel Barnes
+/**********************************************************************
+
+ Wild Vision MidiMax
+
+ http://chrisacorns.computinghistory.org.uk/32bit_UpgradesH2Z/WildVision_MidiMax.html
+
+**********************************************************************/
+
+#include "emu.h"
+#include "midimax.h"
+#include "machine/ins8250.h"
+#include "bus/midi/midi.h"
+
+
+namespace {
+
+// ======================> arc_midimax_device
+
+class arc_midimax_device :
+ public device_t,
+ public device_archimedes_podule_interface
+{
+public:
+ // construction/destruction
+ arc_midimax_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock);
+
+protected:
+ arc_midimax_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, u32 clock);
+
+ // device-level overrides
+ virtual void device_start() override ATTR_COLD;
+ virtual void device_reset() override ATTR_COLD;
+
+ // optional information overrides
+ virtual void device_add_mconfig(machine_config &config) override ATTR_COLD;
+ virtual const tiny_rom_entry *device_rom_region() const override ATTR_COLD;
+
+ // device_archimedes_podule_interface overrides
+ virtual void ioc_map(address_map &map) override ATTR_COLD;
+
+private:
+ required_memory_region m_podule_rom;
+
+ u8 m_rom_page;
+};
+
+
+// ======================> arc_midimax2_device
+
+class arc_midimax2_device : public arc_midimax_device
+{
+public:
+ // construction/destruction
+ arc_midimax2_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 ATTR_COLD;
+};
+
+
+void arc_midimax_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(0x2000, 0x2000).lw8(NAME([this](u8 data) { m_rom_page = data; }));
+ map(0x3000, 0x301f).rw("uart", FUNC(ns16550_device::ins8250_r), FUNC(ns16550_device::ins8250_w)).umask32(0x000000ff);
+}
+
+
+//-------------------------------------------------
+// ROM( midimax )
+//-------------------------------------------------
+
+ROM_START( midimax )
+ ROM_REGION(0x10000, "podule_rom", 0)
+ ROM_SYSTEM_BIOS(0, "106", "1.06 (26 Mar 1995)")
+ ROMX_LOAD("midimax-1.06.rom", 0x0000, 0x10000, CRC(62d8a431) SHA1(8c291082d9e8a8533a4f3b59da857813aa357ecb), ROM_BIOS(0))
+ ROM_SYSTEM_BIOS(1, "105", "1.05 (26 Apr 1994)")
+ ROMX_LOAD("midimax-1.05.rom", 0x0000, 0x10000, CRC(2340a077) SHA1(8cba82ed214246b9fb55e24e87e4629231490465), ROM_BIOS(1))
+ROM_END
+
+ROM_START( midimax2 )
+ ROM_REGION(0x10000, "podule_rom", 0)
+ ROM_SYSTEM_BIOS(0, "201", "2.01 (10-Dec-97)")
+ ROMX_LOAD("midimax-2.01.rom", 0x0000, 0x10000, CRC(b112bdb2) SHA1(d713bf8661542009defadb08cc6096af94efce3e), ROM_BIOS(0))
+ROM_END
+
+const tiny_rom_entry *arc_midimax_device::device_rom_region() const
+{
+ return ROM_NAME( midimax );
+}
+
+const tiny_rom_entry *arc_midimax2_device::device_rom_region() const
+{
+ return ROM_NAME( midimax2 );
+}
+
+
+//-------------------------------------------------
+// device_add_mconfig - add device configuration
+//-------------------------------------------------
+
+void arc_midimax_device::device_add_mconfig(machine_config &config)
+{
+ ns16550_device &uart(NS16550(config, "uart", DERIVED_CLOCK(1, 4))); // TODO: verify clock
+ uart.out_tx_callback().set("mdout1", FUNC(midi_port_device::write_txd));
+ uart.out_tx_callback().append("mdout2", FUNC(midi_port_device::write_txd));
+ uart.out_tx_callback().append("mdthru", FUNC(midi_port_device::write_txd));
+ uart.out_int_callback().set([this](int state) { set_pirq(state); });
+
+ midiout_slot(MIDI_PORT(config, "mdthru"));
+ midiout_slot(MIDI_PORT(config, "mdout1"));
+ midiout_slot(MIDI_PORT(config, "mdout2"));
+ midi_port_device &mdin(MIDI_PORT(config, "mdin", midiin_slot, "midiin"));
+ mdin.rxd_handler().set("uart", FUNC(ns16550_device::rx_w));
+ mdin.rxd_handler().append("mdthru", FUNC(midi_port_device::write_txd));
+}
+
+
+//**************************************************************************
+// LIVE DEVICE
+//**************************************************************************
+
+//-------------------------------------------------
+// arc_midimax_device - constructor
+//-------------------------------------------------
+
+arc_midimax_device::arc_midimax_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_page(0)
+{
+}
+
+arc_midimax_device::arc_midimax_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock)
+ : arc_midimax_device(mconfig, ARC_MIDIMAX, tag, owner, clock)
+{
+}
+
+arc_midimax2_device::arc_midimax2_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock)
+ : arc_midimax_device(mconfig, ARC_MIDIMAX2, tag, owner, clock)
+{
+}
+
+
+//-------------------------------------------------
+// device_start - device-specific startup
+//-------------------------------------------------
+
+void arc_midimax_device::device_start()
+{
+ save_item(NAME(m_rom_page));
+}
+
+//-------------------------------------------------
+// device_reset - device-specific reset
+//-------------------------------------------------
+
+void arc_midimax_device::device_reset()
+{
+ m_rom_page = 0x00;
+}
+
+} // anonymous namespace
+
+
+//**************************************************************************
+// DEVICE DEFINITIONS
+//**************************************************************************
+
+DEFINE_DEVICE_TYPE_PRIVATE(ARC_MIDIMAX, device_archimedes_podule_interface, arc_midimax_device, "arc_midimax", "Wild Vision MidiMax")
+DEFINE_DEVICE_TYPE_PRIVATE(ARC_MIDIMAX2, device_archimedes_podule_interface, arc_midimax2_device, "arc_midimax2", "Wild Vision MidiMax II")
diff --git a/src/devices/bus/archimedes/podule/midimax.h b/src/devices/bus/archimedes/podule/midimax.h
new file mode 100644
index 00000000000..214fd46ee7c
--- /dev/null
+++ b/src/devices/bus/archimedes/podule/midimax.h
@@ -0,0 +1,20 @@
+// license:BSD-3-Clause
+// copyright-holders:Nigel Barnes
+/**********************************************************************
+
+ Wild Vision MidiMax
+
+**********************************************************************/
+
+#ifndef MAME_BUS_ARCHIMEDES_PODULE_MIDIMAX_H
+#define MAME_BUS_ARCHIMEDES_PODULE_MIDIMAX_H
+
+#pragma once
+
+#include "slot.h"
+
+// device type definition
+DECLARE_DEVICE_TYPE(ARC_MIDIMAX, device_archimedes_podule_interface)
+DECLARE_DEVICE_TYPE(ARC_MIDIMAX2, device_archimedes_podule_interface)
+
+#endif // MAME_BUS_ARCHIMEDES_PODULE_MIDIMAX_H
diff --git a/src/devices/bus/archimedes/podule/nexus.cpp b/src/devices/bus/archimedes/podule/nexus.cpp
new file mode 100644
index 00000000000..3963a4a9ea4
--- /dev/null
+++ b/src/devices/bus/archimedes/podule/nexus.cpp
@@ -0,0 +1,127 @@
+// license:BSD-3-Clause
+// copyright-holders:Nigel Barnes
+/**********************************************************************
+
+ SJ Research Nexus Interface
+
+ http://chrisacorns.computinghistory.org.uk/32bit_UpgradesH2Z/SJR_A300NexusI4.html
+
+**********************************************************************/
+
+#include "emu.h"
+#include "nexus.h"
+//#include "machine/imsc012.h"
+
+
+namespace {
+
+class arc_nexus_device :
+ public device_t,
+ public device_archimedes_podule_interface
+{
+public:
+ // construction/destruction
+ arc_nexus_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 ATTR_COLD;
+ virtual void device_reset() override ATTR_COLD;
+
+ // optional information overrides
+ virtual void device_add_mconfig(machine_config &config) override ATTR_COLD;
+ virtual const tiny_rom_entry *device_rom_region() const override ATTR_COLD;
+
+ // device_archimedes_podule_interface overrides
+ virtual void ioc_map(address_map &map) override ATTR_COLD;
+ virtual void memc_map(address_map &map) override ATTR_COLD;
+
+private:
+ required_memory_region m_podule_rom;
+
+ u8 m_rom_page;
+};
+
+
+void arc_nexus_device::ioc_map(address_map &map)
+{
+ map(0x0000, 0x03fff).lr8(NAME([this](offs_t offset) { return m_podule_rom->base()[offset | ((m_rom_page << 12) & 0x7000)]; })).umask32(0x000000ff);
+}
+
+void arc_nexus_device::memc_map(address_map &map)
+{
+ map(0x0040, 0x0040).lrw8(NAME([this]() { return m_rom_page; }), NAME([this](u8 data) { m_rom_page = data; }));
+ //map(0x0060, 0x006f).rw("c012", FUNC(imsc012_device::read), FUNC(imsc012_device::write)).umask32(0x000000ff);
+}
+
+
+//-------------------------------------------------
+// ROM( nexus )
+//-------------------------------------------------
+
+ROM_START( nexus )
+ ROM_REGION(0x8000, "podule_rom", 0)
+ ROM_LOAD("a500_2.24.bin", 0x0000, 0x8000, CRC(5d857330) SHA1(4d1c8cf82fddde1e0772c475da1b3283986aa7d3))
+ROM_END
+
+const tiny_rom_entry *arc_nexus_device::device_rom_region() const
+{
+ return ROM_NAME( nexus );
+}
+
+
+//-------------------------------------------------
+// device_add_mconfig - add device configuration
+//-------------------------------------------------
+
+void arc_nexus_device::device_add_mconfig(machine_config &config)
+{
+ //IMSC012(config, "c012", 5_MHz_XTAL); // INMOS IMSC012-P20S link adaptor
+}
+
+
+//**************************************************************************
+// LIVE DEVICE
+//**************************************************************************
+
+//-------------------------------------------------
+// arc_nexus_device - constructor
+//-------------------------------------------------
+
+arc_nexus_device::arc_nexus_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock)
+ : device_t(mconfig, ARC_NEXUS_A500, 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_nexus_device::device_start()
+{
+ save_item(NAME(m_rom_page));
+}
+
+//-------------------------------------------------
+// device_reset - device-specific reset
+//-------------------------------------------------
+
+void arc_nexus_device::device_reset()
+{
+ m_rom_page = 0xff;
+}
+
+} // anonymous namespace
+
+
+//**************************************************************************
+// DEVICE DEFINITIONS
+//**************************************************************************
+
+DEFINE_DEVICE_TYPE_PRIVATE(ARC_NEXUS_A500, device_archimedes_podule_interface, arc_nexus_device, "arc_nexus_a500", "SJ Research Nexus Interface (A500)")
diff --git a/src/devices/bus/archimedes/podule/nexus.h b/src/devices/bus/archimedes/podule/nexus.h
new file mode 100644
index 00000000000..e1d27e80b90
--- /dev/null
+++ b/src/devices/bus/archimedes/podule/nexus.h
@@ -0,0 +1,19 @@
+// license:BSD-3-Clause
+// copyright-holders:Nigel Barnes
+/**********************************************************************
+
+ SJ Research Nexus Interface
+
+**********************************************************************/
+
+#ifndef MAME_BUS_ARCHIMEDES_PODULE_NEXUS_H
+#define MAME_BUS_ARCHIMEDES_PODULE_NEXUS_H
+
+#pragma once
+
+#include "slot.h"
+
+// device type definition
+DECLARE_DEVICE_TYPE(ARC_NEXUS_A500, device_archimedes_podule_interface)
+
+#endif // MAME_BUS_ARCHIMEDES_PODULE_NEXUS_H
diff --git a/src/devices/bus/archimedes/podule/rom.cpp b/src/devices/bus/archimedes/podule/rom.cpp
new file mode 100644
index 00000000000..90f81eb359f
--- /dev/null
+++ b/src/devices/bus/archimedes/podule/rom.cpp
@@ -0,0 +1,231 @@
+// license:BSD-3-Clause
+// copyright-holders:Nigel Barnes
+/**********************************************************************
+
+ Acorn AKA05 ROM Podule
+
+ http://chrisacorns.computinghistory.org.uk/32bit_UpgradesA2G/Acorn_AKA05_ROMpodule.html
+
+**********************************************************************/
+
+#include "emu.h"
+#include "rom.h"
+#include "bus/generic/slot.h"
+#include "bus/generic/carts.h"
+#include "bus/generic/ram.h"
+#include "bus/generic/rom.h"
+#include "softlist_dev.h"
+
+
+namespace {
+
+class arc_rom_aka05_device :
+ public device_t,
+ public device_archimedes_podule_interface
+{
+public:
+ // construction/destruction
+ arc_rom_aka05_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock);
+
+ static constexpr feature_type unemulated_features() { return feature::ROM; }
+
+protected:
+ 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 ATTR_COLD;
+ virtual void device_reset() override ATTR_COLD;
+
+ // optional information overrides
+ virtual void device_add_mconfig(machine_config &config) override ATTR_COLD;
+ virtual const tiny_rom_entry *device_rom_region() const override ATTR_COLD;
+
+ // device_archimedes_podule_interface overrides
+ virtual void ioc_map(address_map &map) override ATTR_COLD;
+
+private:
+ required_memory_region m_podule_rom;
+ required_device_array<generic_slot_device, 8> m_rom;
+
+ u8 rom_r(offs_t offset);
+ void rom_w(offs_t offset, u8 data);
+
+ u8 m_rom_select;
+ 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 ATTR_COLD;
+};
+
+
+void arc_rom_aka05_device::ioc_map(address_map &map)
+{
+ map(0x0000, 0x1fff).rw(FUNC(arc_rom_aka05_device::rom_r), FUNC(arc_rom_aka05_device::rom_w)).umask32(0x000000ff);
+ map(0x2000, 0x2fff).lw8(NAME([this](u8 data) { m_rom_page = data & 0x3f; m_rom_select = (m_rom_select & 0x04) | ((data >> 6) & 0x03); })).umask32(0x000000ff);
+ map(0x3000, 0x37ff).lw8(NAME([this](u8 data) { m_rom_select &= ~0x04; })).umask32(0x000000ff);
+ map(0x3800, 0x3fff).lw8(NAME([this](u8 data) { m_rom_select |= 0x04; })).umask32(0x000000ff);
+}
+
+
+//-------------------------------------------------
+// ROM( rom )
+//-------------------------------------------------
+
+ROM_START( rom_aka05 )
+ ROM_REGION(0x20000, "podule_rom", ROMREGION_ERASEFF)
+ ROM_SYSTEM_BIOS(0, "2", "Second release 18-Dec-87")
+ 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)
+{
+ device.option_add("ram", GENERIC_RAM_32K_PLAIN);
+}
+
+//-------------------------------------------------
+// device_add_mconfig - add device configuration
+//-------------------------------------------------
+
+void arc_rom_aka05_device::device_add_mconfig(machine_config &config)
+{
+ // 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[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");
+}
+
+
+//**************************************************************************
+// LIVE DEVICE
+//**************************************************************************
+
+//-------------------------------------------------
+// arc_rom_aka05_device - constructor
+//-------------------------------------------------
+
+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)
+ , m_rom_select(0)
+ , m_rom_page(0)
+{
+}
+
+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
+//-------------------------------------------------
+
+void arc_rom_aka05_device::device_start()
+{
+ save_item(NAME(m_rom_select));
+ save_item(NAME(m_rom_page));
+}
+
+
+//-------------------------------------------------
+// device_reset - device-specific reset
+//-------------------------------------------------
+
+void arc_rom_aka05_device::device_reset()
+{
+ m_rom_select = 0x00;
+ m_rom_page = 0x00;
+}
+
+
+//**************************************************************************
+// IMPLEMENTATION
+//**************************************************************************
+
+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: 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]->read_ram(addr);
+ break;
+ }
+
+ return data;
+}
+
+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]->write_ram(addr, data);
+ break;
+ }
+}
+
+} // anonymous namespace
+
+
+//**************************************************************************
+// DEVICE DEFINITIONS
+//**************************************************************************
+
+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
new file mode 100644
index 00000000000..980e66eb9be
--- /dev/null
+++ b/src/devices/bus/archimedes/podule/rom.h
@@ -0,0 +1,20 @@
+// license:BSD-3-Clause
+// copyright-holders:Nigel Barnes
+/**********************************************************************
+
+ Acorn AKA05 ROM Podule
+
+**********************************************************************/
+
+#ifndef MAME_BUS_ARCHIMEDES_PODULE_ROM_H
+#define MAME_BUS_ARCHIMEDES_PODULE_ROM_H
+
+#pragma once
+
+#include "slot.h"
+
+// 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/rs423.cpp b/src/devices/bus/archimedes/podule/rs423.cpp
new file mode 100644
index 00000000000..1abc3a6d066
--- /dev/null
+++ b/src/devices/bus/archimedes/podule/rs423.cpp
@@ -0,0 +1,136 @@
+// license:BSD-3-Clause
+// copyright-holders:Nigel Barnes
+/**********************************************************************
+
+ Intelligent Interfaces Dual RS423 Serial Interface
+
+ TODO:
+ - everything, this is skeleton with ROM.
+
+**********************************************************************/
+
+#include "emu.h"
+#include "rs423.h"
+#include "machine/6522via.h"
+#include "machine/mc68681.h"
+#include "bus/rs232/rs232.h"
+
+
+namespace {
+
+// ======================> arc_rs423_device
+
+class arc_rs423_device :
+ public device_t,
+ public device_archimedes_podule_interface
+{
+public:
+ // construction/destruction
+ arc_rs423_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock);
+
+protected:
+ // device-level overrides
+ virtual void device_start() override ATTR_COLD;
+ virtual void device_reset() override ATTR_COLD;
+
+ // optional information overrides
+ virtual void device_add_mconfig(machine_config &config) override ATTR_COLD;
+ virtual const tiny_rom_entry *device_rom_region() const override ATTR_COLD;
+
+ // device_archimedes_podule_interface overrides
+ virtual void ioc_map(address_map &map) override ATTR_COLD;
+
+private:
+ required_memory_region m_podule_rom;
+
+ u8 m_rom_page;
+};
+
+
+void arc_rs423_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) & 0x7800)]; })).umask32(0x000000ff);
+ //map(0x2000, 0x203f).rw("via", FUNC(via6522_device::read), FUNC(via6522_device::write)).umask32(0x000000ff);
+ //map(0x3000, 0x303f).rw("duart", FUNC(scn2681_device::read), FUNC(scn2681_device::write)).umask32(0x000000ff);
+}
+
+
+//-------------------------------------------------
+// ROM( rs423 )
+//-------------------------------------------------
+
+ROM_START( rs423 )
+ ROM_REGION(0x8000, "podule_rom", 0)
+ ROM_LOAD("iidual_id.rom", 0x0000, 0x8000, CRC(ae113882) SHA1(eb97839cd66dce33598aed90ac2f0624de1aa60d))
+ROM_END
+
+const tiny_rom_entry *arc_rs423_device::device_rom_region() const
+{
+ return ROM_NAME( rs423 );
+}
+
+
+//-------------------------------------------------
+// device_add_mconfig - add device configuration
+//-------------------------------------------------
+
+void arc_rs423_device::device_add_mconfig(machine_config &config)
+{
+ via6522_device &via(R65C22(config, "via", DERIVED_CLOCK(1, 4)));
+ via.writepa_handler().set([this](u8 data) { m_rom_page = data; });
+ via.irq_handler().set([this](int state) { set_pirq(state); });
+
+ scn2681_device &duart(SCN2681(config, "duart", 3.6864_MHz_XTAL)); // SC26C92
+ duart.a_tx_cb().set("rs232a", FUNC(rs232_port_device::write_txd));
+ duart.b_tx_cb().set("rs232b", FUNC(rs232_port_device::write_txd));
+
+ rs232_port_device &rs232a(RS232_PORT(config, "rs232a", default_rs232_devices, nullptr));
+ rs232a.rxd_handler().set("duart", FUNC(scn2681_device::rx_a_w));
+ rs232_port_device &rs232b(RS232_PORT(config, "rs232b", default_rs232_devices, nullptr));
+ rs232b.rxd_handler().set("duart", FUNC(scn2681_device::rx_b_w));
+}
+
+
+//**************************************************************************
+// LIVE DEVICE
+//**************************************************************************
+
+//-------------------------------------------------
+// arc_rs423_device - constructor
+//-------------------------------------------------
+
+arc_rs423_device::arc_rs423_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock)
+ : device_t(mconfig, ARC_RS423, 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_rs423_device::device_start()
+{
+ save_item(NAME(m_rom_page));
+}
+
+//-------------------------------------------------
+// device_reset - device-specific reset
+//-------------------------------------------------
+
+void arc_rs423_device::device_reset()
+{
+ m_rom_page = 0x00;
+}
+
+} // anonymous namespace
+
+
+//**************************************************************************
+// DEVICE DEFINITIONS
+//**************************************************************************
+
+DEFINE_DEVICE_TYPE_PRIVATE(ARC_RS423, device_archimedes_podule_interface, arc_rs423_device, "arc_rs423", "Archimedes Dual RS423 Serial Interface")
diff --git a/src/devices/bus/archimedes/podule/rs423.h b/src/devices/bus/archimedes/podule/rs423.h
new file mode 100644
index 00000000000..f488d016599
--- /dev/null
+++ b/src/devices/bus/archimedes/podule/rs423.h
@@ -0,0 +1,19 @@
+// license:BSD-3-Clause
+// copyright-holders:Nigel Barnes
+/**********************************************************************
+
+ Intelligent Interfaces Dual RS423 Serial Interface
+
+**********************************************************************/
+
+#ifndef MAME_BUS_ARCHIMEDES_PODULE_RS423_H
+#define MAME_BUS_ARCHIMEDES_PODULE_RS423_H
+
+#pragma once
+
+#include "slot.h"
+
+// device type definition
+DECLARE_DEVICE_TYPE(ARC_RS423, device_archimedes_podule_interface)
+
+#endif // MAME_BUS_ARCHIMEDES_PODULE_RS423_H
diff --git a/src/devices/bus/archimedes/podule/scan256.cpp b/src/devices/bus/archimedes/podule/scan256.cpp
new file mode 100644
index 00000000000..4f219fc2012
--- /dev/null
+++ b/src/devices/bus/archimedes/podule/scan256.cpp
@@ -0,0 +1,126 @@
+// license:BSD-3-Clause
+// copyright-holders:Nigel Barnes
+/**********************************************************************
+
+ Watford Electronics 256 Grey-Scale Scanner
+
+ http://chrisacorns.computinghistory.org.uk/32bit_UpgradesH2Z/WE_Scanner.html
+
+ TODO:
+ - implement scanner.
+
+**********************************************************************/
+
+#include "emu.h"
+#include "scan256.h"
+#include "imagedev/picture.h"
+
+
+namespace {
+
+class arc_scan256_device :
+ public device_t,
+ public device_archimedes_podule_interface
+{
+public:
+ // construction/destruction
+ arc_scan256_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock);
+
+ static constexpr feature_type unemulated_features() { return feature::CAPTURE; }
+
+protected:
+ // device-level overrides
+ virtual void device_start() override ATTR_COLD;
+ virtual void device_reset() override ATTR_COLD;
+
+ // optional information overrides
+ virtual void device_add_mconfig(machine_config &config) override ATTR_COLD;
+ virtual const tiny_rom_entry *device_rom_region() const override ATTR_COLD;
+
+ // device_archimedes_podule_interface overrides
+ virtual void ioc_map(address_map &map) override ATTR_COLD;
+
+private:
+ required_memory_region m_podule_rom;
+ required_device<picture_image_device> m_picture;
+
+ u8 m_rom_page;
+};
+
+
+void arc_scan256_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(0x2000, 0x2000).lw8(NAME([this](u8 data) { m_rom_page = data; }));
+}
+
+
+//-------------------------------------------------
+// ROM( scan256 )
+//-------------------------------------------------
+
+ROM_START( scan256 )
+ ROM_REGION(0x20000, "podule_rom", 0)
+ ROM_LOAD("scan256_1.00.bin", 0x0000, 0x20000, CRC(3e5d5877) SHA1(9ea4bba1a752090b19a8ab9bf06414053fb8f7ff))
+ROM_END
+
+const tiny_rom_entry *arc_scan256_device::device_rom_region() const
+{
+ return ROM_NAME( scan256 );
+}
+
+
+//-------------------------------------------------
+// device_add_mconfig - add device configuration
+//-------------------------------------------------
+
+void arc_scan256_device::device_add_mconfig(machine_config &config)
+{
+ IMAGE_PICTURE(config, m_picture);
+}
+
+
+//**************************************************************************
+// LIVE DEVICE
+//**************************************************************************
+
+//-------------------------------------------------
+// arc_scan256_device - constructor
+//-------------------------------------------------
+
+arc_scan256_device::arc_scan256_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock)
+ : device_t(mconfig, ARC_SCAN256, tag, owner, clock)
+ , device_archimedes_podule_interface(mconfig, *this)
+ , m_podule_rom(*this, "podule_rom")
+ , m_picture(*this, "srcimg")
+ , m_rom_page(0)
+{
+}
+
+
+//-------------------------------------------------
+// device_start - device-specific startup
+//-------------------------------------------------
+
+void arc_scan256_device::device_start()
+{
+ save_item(NAME(m_rom_page));
+}
+
+//-------------------------------------------------
+// device_reset - device-specific reset
+//-------------------------------------------------
+
+void arc_scan256_device::device_reset()
+{
+ m_rom_page = 0x00;
+}
+
+} // anonymous namespace
+
+
+//**************************************************************************
+// DEVICE DEFINITIONS
+//**************************************************************************
+
+DEFINE_DEVICE_TYPE_PRIVATE(ARC_SCAN256, device_archimedes_podule_interface, arc_scan256_device, "arc_scan256", "Watford Electronics 256 Grey-Scale Scanner")
diff --git a/src/devices/bus/archimedes/podule/scan256.h b/src/devices/bus/archimedes/podule/scan256.h
new file mode 100644
index 00000000000..1ee134c8962
--- /dev/null
+++ b/src/devices/bus/archimedes/podule/scan256.h
@@ -0,0 +1,19 @@
+// license:BSD-3-Clause
+// copyright-holders:Nigel Barnes
+/**********************************************************************
+
+ Watford Electronics 256 Grey-Scale Scanner
+
+**********************************************************************/
+
+#ifndef MAME_BUS_ARCHIMEDES_PODULE_SCAN256_H
+#define MAME_BUS_ARCHIMEDES_PODULE_SCAN256_H
+
+#pragma once
+
+#include "slot.h"
+
+// device type definition
+DECLARE_DEVICE_TYPE(ARC_SCAN256, device_archimedes_podule_interface)
+
+#endif // MAME_BUS_ARCHIMEDES_PODULE_SCAN256_H
diff --git a/src/devices/bus/archimedes/podule/scanlight.cpp b/src/devices/bus/archimedes/podule/scanlight.cpp
new file mode 100644
index 00000000000..799a2004a3e
--- /dev/null
+++ b/src/devices/bus/archimedes/podule/scanlight.cpp
@@ -0,0 +1,261 @@
+// license:BSD-3-Clause
+// copyright-holders:Nigel Barnes
+/**********************************************************************
+
+ Computer Concepts Scanner Interface
+
+ http://chrisacorns.computinghistory.org.uk/32bit_UpgradesA2G/CC_Scannerif.html
+
+ Computer Concepts A3000 Scanner interface
+
+ http://chrisacorns.computinghistory.org.uk/32bit_UpgradesA2G/CC_scanner_minipodule.html
+
+ Computer Concepts ScanLight Video 256
+
+ http://chrisacorns.computinghistory.org.uk/32bit_UpgradesA2G/CC_ScanlightVideo256.html
+
+ TODO:
+ - implement scanner device
+ - implement frame grabber from video source.
+
+**********************************************************************/
+
+#include "emu.h"
+#include "scanlight.h"
+#include "imagedev/avivideo.h"
+#include "imagedev/picture.h"
+
+
+namespace {
+
+// ======================> arc_scanlight_device
+
+class arc_scanlight_device :
+ public device_t,
+ public device_archimedes_podule_interface
+{
+public:
+ // construction/destruction
+ arc_scanlight_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock);
+
+ static constexpr feature_type unemulated_features() { return feature::CAPTURE; }
+
+protected:
+ arc_scanlight_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, u32 clock);
+
+ // device-level overrides
+ virtual void device_start() override ATTR_COLD;
+ virtual void device_reset() override ATTR_COLD;
+
+ // optional information overrides
+ virtual void device_add_mconfig(machine_config &config) override ATTR_COLD;
+ virtual const tiny_rom_entry *device_rom_region() const override ATTR_COLD;
+
+ // device_archimedes_podule_interface overrides
+ virtual void ioc_map(address_map &map) override ATTR_COLD;
+
+//private:
+ required_memory_region m_podule_rom;
+ required_device<picture_image_device> m_picture;
+
+ u8 m_rom_page;
+};
+
+
+// ======================> arc_scanjunior_device
+
+class arc_scanjunior_device : public arc_scanlight_device
+{
+public:
+ // construction/destruction
+ arc_scanjunior_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 ATTR_COLD;
+};
+
+
+// ======================> arc_scanjunior3_device
+
+class arc_scanjunior3_device : public arc_scanlight_device
+{
+public:
+ // construction/destruction
+ arc_scanjunior3_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 ATTR_COLD;
+};
+
+
+// ======================> arc_scanvideo_device
+
+class arc_scanvideo_device : public arc_scanlight_device
+{
+public:
+ // construction/destruction
+ arc_scanvideo_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock);
+
+protected:
+ // optional information overrides
+ virtual void device_add_mconfig(machine_config &config) override ATTR_COLD;
+ virtual const tiny_rom_entry *device_rom_region() const override ATTR_COLD;
+
+ // device_archimedes_podule_interface overrides
+ virtual void ioc_map(address_map &map) override ATTR_COLD;
+
+private:
+ required_device<avivideo_image_device> m_avivideo;
+};
+
+
+void arc_scanlight_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) & 0x7800)]; })).umask32(0x000000ff);
+ map(0x2000, 0x2000).lw8(NAME([this](u8 data) { m_rom_page = data; }));
+}
+
+void arc_scanvideo_device::ioc_map(address_map &map)
+{
+ map(0x0000, 0x1fff).lr8(NAME([this](offs_t offset) { return m_podule_rom->base()[offset | (((m_rom_page ^ 0x10) << 11) & 0xf800)]; })).umask32(0x000000ff);
+ map(0x2000, 0x2000).lw8(NAME([this](u8 data) { m_rom_page = data; }));
+}
+
+
+//-------------------------------------------------
+// ROM( scanlight )
+//-------------------------------------------------
+
+ROM_START( scanlight )
+ ROM_REGION(0x8000, "podule_rom", 0)
+ ROM_SYSTEM_BIOS(0, "100", "1.00 (05 Sep 1990)") // also on A3000 Scanner mini-podule
+ ROMX_LOAD("scan-light_1.00.rom", 0x0000, 0x8000, CRC(6ba1764b) SHA1(fa69fb69e01553b27409b65a37d3d30a376e7380), ROM_BIOS(0))
+ROM_END
+
+ROM_START( scanjunior )
+ ROM_REGION(0x8000, "podule_rom", 0)
+ ROM_SYSTEM_BIOS(0, "100", "1.00 (05 Sep 1990)")
+ ROMX_LOAD("scan-light_jr_1.00.rom", 0x0000, 0x8000, CRC(bf1b8268) SHA1(3c63f8379d8fc222fc57838a9384ecec7c5d2484), ROM_BIOS(0))
+ROM_END
+
+ROM_START( scanjunior3 )
+ ROM_REGION(0x8000, "podule_rom", 0)
+ ROM_SYSTEM_BIOS(0, "200", "2.00 (02 Oct 1992)")
+ ROMX_LOAD("scan-light_jr_2.00.rom", 0x0000, 0x8000, CRC(bdc729bb) SHA1(382193f2b6cf8ba5ed04481d99050fe2f691ad0a), ROM_BIOS(0))
+ROM_END
+
+ROM_START( scanvideo )
+ ROM_REGION(0x10000, "podule_rom", 0)
+ ROM_SYSTEM_BIOS(0, "120", "1.20 (04 May 1994)")
+ ROMX_LOAD("video256_1.20.rom", 0x0000, 0x10000, CRC(3e9a44b8) SHA1(9fe739b42c5bf5dab69e3c1ffb1c3c5a5d8d7a50), ROM_BIOS(0))
+ROM_END
+
+
+const tiny_rom_entry *arc_scanlight_device::device_rom_region() const
+{
+ return ROM_NAME( scanlight );
+}
+
+const tiny_rom_entry *arc_scanjunior_device::device_rom_region() const
+{
+ return ROM_NAME( scanjunior );
+}
+
+const tiny_rom_entry *arc_scanjunior3_device::device_rom_region() const
+{
+ return ROM_NAME( scanjunior3 );
+}
+
+const tiny_rom_entry *arc_scanvideo_device::device_rom_region() const
+{
+ return ROM_NAME( scanvideo );
+}
+
+
+//-------------------------------------------------
+// device_add_mconfig - add device configuration
+//-------------------------------------------------
+
+void arc_scanlight_device::device_add_mconfig(machine_config &config)
+{
+ IMAGE_PICTURE(config, m_picture);
+}
+
+void arc_scanvideo_device::device_add_mconfig(machine_config &config)
+{
+ arc_scanlight_device::device_add_mconfig(config);
+
+ IMAGE_AVIVIDEO(config, m_avivideo);
+}
+
+
+//**************************************************************************
+// LIVE DEVICE
+//**************************************************************************
+
+//-------------------------------------------------
+// arc_scanlight_device - constructor
+//-------------------------------------------------
+
+arc_scanlight_device::arc_scanlight_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_picture(*this, "srcimg")
+ , m_rom_page(0)
+{
+}
+
+arc_scanlight_device::arc_scanlight_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock)
+ : arc_scanlight_device(mconfig, ARC_SCANLIGHT, tag, owner, clock)
+{
+}
+
+arc_scanjunior_device::arc_scanjunior_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock)
+ : arc_scanlight_device(mconfig, ARC_SCANJUNIOR, tag, owner, clock)
+{
+}
+
+arc_scanjunior3_device::arc_scanjunior3_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock)
+ : arc_scanlight_device(mconfig, ARC_SCANJUNIOR3, tag, owner, clock)
+{
+}
+
+arc_scanvideo_device::arc_scanvideo_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock)
+ : arc_scanlight_device(mconfig, ARC_SCANVIDEO, tag, owner, clock)
+ , m_avivideo(*this, "srcavi")
+{
+}
+
+
+//-------------------------------------------------
+// device_start - device-specific startup
+//-------------------------------------------------
+
+void arc_scanlight_device::device_start()
+{
+ save_item(NAME(m_rom_page));
+}
+
+//-------------------------------------------------
+// device_reset - device-specific reset
+//-------------------------------------------------
+
+void arc_scanlight_device::device_reset()
+{
+ m_rom_page = 0xff;
+}
+
+} // anonymous namespace
+
+
+//**************************************************************************
+// DEVICE DEFINITIONS
+//**************************************************************************
+
+DEFINE_DEVICE_TYPE_PRIVATE(ARC_SCANLIGHT, device_archimedes_podule_interface, arc_scanlight_device, "arc_scanlight", "Computer Concepts ScanLight")
+DEFINE_DEVICE_TYPE_PRIVATE(ARC_SCANJUNIOR, device_archimedes_podule_interface, arc_scanjunior_device, "arc_scanjunior", "Computer Concepts ScanLight Junior")
+DEFINE_DEVICE_TYPE_PRIVATE(ARC_SCANJUNIOR3, device_archimedes_podule_interface, arc_scanjunior3_device, "arc_scanjunior3", "Computer Concepts ScanLight Junior MkIII")
+DEFINE_DEVICE_TYPE_PRIVATE(ARC_SCANVIDEO, device_archimedes_podule_interface, arc_scanvideo_device, "arc_scanvideo", "Computer Concepts ScanLight Video 256")
diff --git a/src/devices/bus/archimedes/podule/scanlight.h b/src/devices/bus/archimedes/podule/scanlight.h
new file mode 100644
index 00000000000..d5b31006b98
--- /dev/null
+++ b/src/devices/bus/archimedes/podule/scanlight.h
@@ -0,0 +1,22 @@
+// license:BSD-3-Clause
+// copyright-holders:Nigel Barnes
+/**********************************************************************
+
+ Computer Concepts Scanner Interface
+
+**********************************************************************/
+
+#ifndef MAME_BUS_ARCHIMEDES_PODULE_SCANLIGHT_H
+#define MAME_BUS_ARCHIMEDES_PODULE_SCANLIGHT_H
+
+#pragma once
+
+#include "slot.h"
+
+// device type definition
+DECLARE_DEVICE_TYPE(ARC_SCANLIGHT, device_archimedes_podule_interface)
+DECLARE_DEVICE_TYPE(ARC_SCANJUNIOR, device_archimedes_podule_interface)
+DECLARE_DEVICE_TYPE(ARC_SCANJUNIOR3, device_archimedes_podule_interface)
+DECLARE_DEVICE_TYPE(ARC_SCANVIDEO, device_archimedes_podule_interface)
+
+#endif // MAME_BUS_ARCHIMEDES_PODULE_SCANLIGHT_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..d26e2784021
--- /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 ATTR_COLD;
+
+ // optional information overrides
+ virtual void device_add_mconfig(machine_config &config) override ATTR_COLD;
+ virtual const tiny_rom_entry *device_rom_region() const override ATTR_COLD;
+
+ // device_archimedes_podule_interface overrides
+ virtual void ioc_map(address_map &map) override ATTR_COLD;
+
+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..265a5ccd8a4
--- /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 ATTR_COLD;
+ virtual void device_reset() override ATTR_COLD;
+
+ // optional information overrides
+ virtual void device_add_mconfig(machine_config &config) override ATTR_COLD;
+ virtual const tiny_rom_entry *device_rom_region() const override ATTR_COLD;
+
+ // device_archimedes_podule_interface overrides
+ virtual void ioc_map(address_map &map) override ATTR_COLD;
+ virtual void memc_map(address_map &map) override ATTR_COLD;
+
+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 ATTR_COLD;
+};
+
+
+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..226ffe2bdfd
--- /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 ATTR_COLD;
+ virtual void device_reset() override ATTR_COLD;
+
+ // optional information overrides
+ virtual void device_add_mconfig(machine_config &config) override ATTR_COLD;
+ virtual const tiny_rom_entry *device_rom_region() const override ATTR_COLD;
+
+ // device_archimedes_podule_interface overrides
+ virtual void ioc_map(address_map &map) override ATTR_COLD;
+ virtual void memc_map(address_map &map) override ATTR_COLD;
+
+private:
+ required_device<dp8490_device> m_dp8490;
+ 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_dp8490, FUNC(dp8490_device::read), FUNC(dp8490_device::write)).umask32(0x000000ff);
+ map(0x2100, 0x211f).m(m_dp8490, FUNC(dp8490_device::map)).umask32(0x000000ff);
+ //map(0x2100, 0x2100).r(m_dp8490, FUNC(dp8490_device::dma_r));
+ //map(0x2100, 0x2100).w(m_dp8490, FUNC(dp8490_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("dp8490", DP8490) // DP8490N
+ .machine_config([this](device_t *device)
+ {
+ downcast<dp8490_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_dp8490(*this, "scsi:7:dp8490")
+ , 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..0f9425f61e4
--- /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 ATTR_COLD;
+ virtual void device_reset() override ATTR_COLD;
+
+ // optional information overrides
+ virtual void device_add_mconfig(machine_config &config) override ATTR_COLD;
+ virtual const tiny_rom_entry *device_rom_region() const override ATTR_COLD;
+
+ // device_archimedes_podule_interface overrides
+ virtual void ioc_map(address_map &map) override ATTR_COLD;
+ virtual void memc_map(address_map &map) override ATTR_COLD;
+
+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..fa749fbae40
--- /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 ATTR_COLD;
+ virtual void device_reset() override ATTR_COLD;
+
+ // optional information overrides
+ virtual void device_add_mconfig(machine_config &config) override ATTR_COLD;
+ virtual const tiny_rom_entry *device_rom_region() const override ATTR_COLD;
+
+ // device_archimedes_podule_interface overrides
+ virtual void ioc_map(address_map &map) override ATTR_COLD;
+ virtual void memc_map(address_map &map) override ATTR_COLD;
+
+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..4e414d8e995
--- /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 ATTR_COLD;
+ virtual void device_reset() override ATTR_COLD;
+
+ // optional information overrides
+ virtual void device_add_mconfig(machine_config &config) override ATTR_COLD;
+ virtual const tiny_rom_entry *device_rom_region() const override ATTR_COLD;
+
+ // device_archimedes_podule_interface overrides
+ virtual void ioc_map(address_map &map) override ATTR_COLD;
+ virtual void memc_map(address_map &map) override ATTR_COLD;
+
+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
new file mode 100644
index 00000000000..0ca3aa526bd
--- /dev/null
+++ b/src/devices/bus/archimedes/podule/scsi_vti.cpp
@@ -0,0 +1,173 @@
+// license:BSD-3-Clause
+// copyright-holders:Nigel Barnes
+/**********************************************************************
+
+ VTI User Port and SCSI Podule
+
+ http://chrisacorns.computinghistory.org.uk/32bit_UpgradesH2Z/VTI_userportSCSI.html
+
+ TODO:
+ - map the EEPROM
+ - fix User Port module
+
+**********************************************************************/
+
+#include "emu.h"
+#include "scsi_vti.h"
+#include "machine/6522via.h"
+#include "machine/eepromser.h"
+#include "machine/ncr53c90.h"
+#include "bus/bbc/userport/userport.h"
+#include "bus/nscsi/devices.h"
+
+
+namespace {
+
+class arc_scsi_vti_device :
+ public device_t,
+ public device_archimedes_podule_interface
+{
+public:
+ // construction/destruction
+ arc_scsi_vti_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock);
+
+ static constexpr feature_type imperfect_features() { return feature::DISK; }
+
+protected:
+ // device-level overrides
+ virtual void device_start() override ATTR_COLD;
+ virtual void device_reset() override ATTR_COLD;
+
+ // optional information overrides
+ virtual void device_add_mconfig(machine_config &config) override ATTR_COLD;
+ virtual const tiny_rom_entry *device_rom_region() const override ATTR_COLD;
+
+ // device_archimedes_podule_interface overrides
+ virtual void ioc_map(address_map &map) override ATTR_COLD;
+ virtual void memc_map(address_map &map) override ATTR_COLD;
+
+private:
+ required_device<ncr53c94_device> m_fas216;
+ required_device<eeprom_serial_93cxx_device> m_eeprom;
+ required_memory_region m_podule_rom;
+
+ u8 m_rom_page;
+ u8 m_drq_status;
+};
+
+
+void arc_scsi_vti_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(0x3d00, 0x3d3f).rw("via", FUNC(via6522_device::read), FUNC(via6522_device::write)).umask32(0x000000ff);
+}
+
+void arc_scsi_vti_device::memc_map(address_map &map)
+{
+ map(0x2000, 0x21ff).lr8(NAME([this](offs_t offset) { return m_fas216->read(offset >> 3); })).umask32(0x000000ff);
+ map(0x2000, 0x21ff).lw8(NAME([this](offs_t offset, u8 data) { m_fas216->write(offset >> 3, data); })).umask32(0x000000ff);
+ map(0x2200, 0x2203).rw(m_fas216, FUNC(ncr53c94_device::dma16_r), FUNC(ncr53c94_device::dma16_w)).umask32(0x0000ffff);
+ map(0x2600, 0x2600).lr8(NAME([this]() { return m_drq_status; }));
+}
+
+
+//-------------------------------------------------
+// ROM( scsi_vti )
+//-------------------------------------------------
+
+ROM_START( scsi_vti )
+ ROM_REGION(0x10000, "podule_rom", 0)
+ ROM_LOAD("vti_up_powerrom.bin", 0x0000, 0x10000, CRC(7ec5854c) SHA1(eb20b1369964cfaee156ba1fc3636997407cc7ba))
+ROM_END
+
+const tiny_rom_entry *arc_scsi_vti_device::device_rom_region() const
+{
+ return ROM_NAME( scsi_vti );
+}
+
+
+//-------------------------------------------------
+// device_add_mconfig - add device configuration
+//-------------------------------------------------
+
+void arc_scsi_vti_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("fas216", NCR53CF94).clock(24.576_MHz_XTAL) // FAS216
+ .machine_config([this](device_t *device)
+ {
+ ncr53c94_device &fas216(downcast<ncr53c94_device &>(*device));
+ fas216.set_busmd(ncr53c94_device::busmd_t::BUSMD_1);
+ fas216.irq_handler_cb().set([this](int state) { set_pirq(state); });
+ fas216.drq_handler_cb().set([this](int state) { m_drq_status = state; });
+ });
+
+ EEPROM_93C06_16BIT(config, m_eeprom); // 2600 b0
+
+ via6522_device &via(MOS6522(config, "via", DERIVED_CLOCK(1, 4)));
+ via.irq_handler().set([this](int state) { set_pirq(state); });
+ via.writepa_handler().set([this](u8 data) { m_rom_page = data; });
+ via.readpb_handler().set("userport", FUNC(bbc_userport_slot_device::pb_r));
+ via.writepb_handler().set("userport", FUNC(bbc_userport_slot_device::pb_w));
+ via.cb1_handler().set("userport", FUNC(bbc_userport_slot_device::write_cb1));
+ via.cb2_handler().set("userport", FUNC(bbc_userport_slot_device::write_cb2));
+
+ bbc_userport_slot_device &userport(BBC_USERPORT_SLOT(config, "userport", bbc_userport_devices, nullptr));
+ userport.cb1_handler().set("via", FUNC(via6522_device::write_cb1));
+ userport.cb2_handler().set("via", FUNC(via6522_device::write_cb2));
+}
+
+
+//**************************************************************************
+// LIVE DEVICE
+//**************************************************************************
+
+//-------------------------------------------------
+// arc_scsi_vti_device - constructor
+//-------------------------------------------------
+
+arc_scsi_vti_device::arc_scsi_vti_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock)
+ : device_t(mconfig, ARC_SCSI_VTI, tag, owner, clock)
+ , device_archimedes_podule_interface(mconfig, *this)
+ , m_fas216(*this, "scsi:7:fas216")
+ , m_eeprom(*this, "eeprom")
+ , m_podule_rom(*this, "podule_rom")
+ , m_rom_page(0)
+ , m_drq_status(0)
+{
+}
+
+
+//-------------------------------------------------
+// device_start - device-specific startup
+//-------------------------------------------------
+
+void arc_scsi_vti_device::device_start()
+{
+ save_item(NAME(m_rom_page));
+}
+
+//-------------------------------------------------
+// device_reset - device-specific reset
+//-------------------------------------------------
+
+void arc_scsi_vti_device::device_reset()
+{
+ m_rom_page = 0x00;
+}
+
+} // anonymous namespace
+
+
+//**************************************************************************
+// DEVICE DEFINITIONS
+//**************************************************************************
+
+DEFINE_DEVICE_TYPE_PRIVATE(ARC_SCSI_VTI, device_archimedes_podule_interface, arc_scsi_vti_device, "arc_scsi_vti", "VTI User Port and SCSI Podule")
diff --git a/src/devices/bus/archimedes/podule/scsi_vti.h b/src/devices/bus/archimedes/podule/scsi_vti.h
new file mode 100644
index 00000000000..8650c1fb26e
--- /dev/null
+++ b/src/devices/bus/archimedes/podule/scsi_vti.h
@@ -0,0 +1,19 @@
+// license:BSD-3-Clause
+// copyright-holders:Nigel Barnes
+/**********************************************************************
+
+ VTI User Port and SCSI Podule
+
+**********************************************************************/
+
+#ifndef MAME_BUS_ARCHIMEDES_PODULE_SCSI_VTI_H
+#define MAME_BUS_ARCHIMEDES_PODULE_SCSI_VTI_H
+
+#pragma once
+
+#include "slot.h"
+
+// device type definition
+DECLARE_DEVICE_TYPE(ARC_SCSI_VTI, device_archimedes_podule_interface)
+
+#endif // MAME_BUS_ARCHIMEDES_PODULE_SCSI_VTI_H
diff --git a/src/devices/bus/archimedes/podule/serial.cpp b/src/devices/bus/archimedes/podule/serial.cpp
new file mode 100644
index 00000000000..ba8f132043d
--- /dev/null
+++ b/src/devices/bus/archimedes/podule/serial.cpp
@@ -0,0 +1,156 @@
+// license:BSD-3-Clause
+// copyright-holders:Nigel Barnes
+/**********************************************************************
+
+ Atomwide Serial Expansion Card
+
+ http://chrisacorns.computinghistory.org.uk/32bit_UpgradesA2G/Atomwide_SerialExp.html
+
+**********************************************************************/
+
+#include "emu.h"
+#include "serial.h"
+#include "machine/ins8250.h"
+#include "bus/rs232/rs232.h"
+
+
+namespace {
+
+// ======================> arc_serial_device
+
+class arc_serial_device :
+ public device_t,
+ public device_archimedes_podule_interface
+{
+public:
+ // construction/destruction
+ arc_serial_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock);
+
+protected:
+ // device-level overrides
+ virtual void device_start() override ATTR_COLD;
+ virtual void device_reset() override ATTR_COLD;
+
+ // optional information overrides
+ virtual void device_add_mconfig(machine_config &config) override ATTR_COLD;
+ virtual const tiny_rom_entry *device_rom_region() const override ATTR_COLD;
+
+ // device_archimedes_podule_interface overrides
+ virtual void ioc_map(address_map &map) override ATTR_COLD;
+
+private:
+ required_memory_region m_podule_rom;
+
+ u8 m_rom_page;
+};
+
+
+void arc_serial_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(0x2000, 0x201f).rw("uart2", FUNC(ns16550_device::ins8250_r), FUNC(ns16550_device::ins8250_w)).umask32(0x000000ff);
+ map(0x2400, 0x241f).rw("uart1", FUNC(ns16550_device::ins8250_r), FUNC(ns16550_device::ins8250_w)).umask32(0x000000ff);
+ map(0x2800, 0x281f).rw("uart0", FUNC(ns16550_device::ins8250_r), FUNC(ns16550_device::ins8250_w)).umask32(0x000000ff);
+ map(0x3c00, 0x3c00).lw8(NAME([this](u8 data) { m_rom_page = data; }));
+}
+
+
+//-------------------------------------------------
+// ROM( serial )
+//-------------------------------------------------
+
+ROM_START( serial )
+ ROM_REGION(0x10000, "podule_rom", 0)
+ ROM_LOAD("atomwide_serial.rom", 0x0000, 0x10000, CRC(2dcf3b28) SHA1(c100cc4f5e3d87233e6db6a1da04ac7c19ac2357))
+ROM_END
+
+const tiny_rom_entry *arc_serial_device::device_rom_region() const
+{
+ return ROM_NAME( serial );
+}
+
+
+//-------------------------------------------------
+// device_add_mconfig - add device configuration
+//-------------------------------------------------
+
+void arc_serial_device::device_add_mconfig(machine_config &config)
+{
+ ns16550_device &uart0(NS16550(config, "uart0", 7.3728_MHz_XTAL));
+ uart0.out_tx_callback().set("serial0", FUNC(rs232_port_device::write_txd));
+ uart0.out_dtr_callback().set("serial0", FUNC(rs232_port_device::write_dtr));
+ uart0.out_rts_callback().set("serial0", FUNC(rs232_port_device::write_rts));
+
+ rs232_port_device &serial0(RS232_PORT(config, "serial0", default_rs232_devices, nullptr));
+ serial0.rxd_handler().set("uart0", FUNC(ns16550_device::rx_w));
+ serial0.dcd_handler().set("uart0", FUNC(ns16550_device::dcd_w));
+ serial0.dsr_handler().set("uart0", FUNC(ns16550_device::dsr_w));
+ serial0.cts_handler().set("uart0", FUNC(ns16550_device::cts_w));
+
+ ns16550_device &uart1(NS16550(config, "uart1", 7.3728_MHz_XTAL));
+ uart1.out_tx_callback().set("serial1", FUNC(rs232_port_device::write_txd));
+ uart1.out_dtr_callback().set("serial1", FUNC(rs232_port_device::write_dtr));
+ uart1.out_rts_callback().set("serial1", FUNC(rs232_port_device::write_rts));
+
+ rs232_port_device &serial1(RS232_PORT(config, "serial1", default_rs232_devices, nullptr));
+ serial1.rxd_handler().set("uart1", FUNC(ns16550_device::rx_w));
+ serial1.dcd_handler().set("uart1", FUNC(ns16550_device::dcd_w));
+ serial1.dsr_handler().set("uart1", FUNC(ns16550_device::dsr_w));
+ serial1.cts_handler().set("uart1", FUNC(ns16550_device::cts_w));
+
+ ns16550_device &uart2(NS16550(config, "uart2", 7.3728_MHz_XTAL));
+ uart2.out_tx_callback().set("serial2", FUNC(rs232_port_device::write_txd));
+ uart2.out_dtr_callback().set("serial2", FUNC(rs232_port_device::write_dtr));
+ uart2.out_rts_callback().set("serial2", FUNC(rs232_port_device::write_rts));
+
+ rs232_port_device &serial2(RS232_PORT(config, "serial2", default_rs232_devices, nullptr));
+ serial2.rxd_handler().set("uart2", FUNC(ns16550_device::rx_w));
+ serial2.dcd_handler().set("uart2", FUNC(ns16550_device::dcd_w));
+ serial2.dsr_handler().set("uart2", FUNC(ns16550_device::dsr_w));
+ serial2.cts_handler().set("uart2", FUNC(ns16550_device::cts_w));
+}
+
+
+//**************************************************************************
+// LIVE DEVICE
+//**************************************************************************
+
+//-------------------------------------------------
+// arc_serial_device - constructor
+//-------------------------------------------------
+
+arc_serial_device::arc_serial_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock)
+ : device_t(mconfig, ARC_SERIAL, 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_serial_device::device_start()
+{
+ save_item(NAME(m_rom_page));
+}
+
+//-------------------------------------------------
+// device_reset - device-specific reset
+//-------------------------------------------------
+
+void arc_serial_device::device_reset()
+{
+ m_rom_page = 0x00;
+}
+
+} // anonymous namespace
+
+
+//**************************************************************************
+// DEVICE DEFINITIONS
+//**************************************************************************
+
+DEFINE_DEVICE_TYPE_PRIVATE(ARC_SERIAL, device_archimedes_podule_interface, arc_serial_device, "arc_serial", "Atomwide Serial Expansion Card")
diff --git a/src/devices/bus/archimedes/podule/serial.h b/src/devices/bus/archimedes/podule/serial.h
new file mode 100644
index 00000000000..929bc914dc0
--- /dev/null
+++ b/src/devices/bus/archimedes/podule/serial.h
@@ -0,0 +1,19 @@
+// license:BSD-3-Clause
+// copyright-holders:Nigel Barnes
+/**********************************************************************
+
+ Atomwide Serial Expansion Card
+
+**********************************************************************/
+
+#ifndef MAME_BUS_ARCHIMEDES_PODULE_SERIAL_H
+#define MAME_BUS_ARCHIMEDES_PODULE_SERIAL_H
+
+#pragma once
+
+#include "slot.h"
+
+// device type definition
+DECLARE_DEVICE_TYPE(ARC_SERIAL, device_archimedes_podule_interface)
+
+#endif // MAME_BUS_ARCHIMEDES_PODULE_SERIAL_H
diff --git a/src/devices/bus/archimedes/podule/slot.cpp b/src/devices/bus/archimedes/podule/slot.cpp
new file mode 100644
index 00000000000..92544eb3433
--- /dev/null
+++ b/src/devices/bus/archimedes/podule/slot.cpp
@@ -0,0 +1,387 @@
+// license:BSD-3-Clause
+// copyright-holders:Nigel Barnes
+/**********************************************************************
+
+ Acorn Archimedes Expansion Bus emulation
+
+**********************************************************************/
+
+#include "emu.h"
+#include "slot.h"
+
+
+//**************************************************************************
+// DEVICE DEFINITIONS
+//**************************************************************************
+
+DEFINE_DEVICE_TYPE(ARCHIMEDES_PODULE_SLOT, archimedes_podule_slot_device, "archimedes_exp_slot", "Acorn Archimedes Podule slot")
+
+
+//**************************************************************************
+// LIVE DEVICE
+//**************************************************************************
+
+//-------------------------------------------------
+// archimedes_podule_slot_device - constructor
+//-------------------------------------------------
+archimedes_podule_slot_device::archimedes_podule_slot_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock)
+ : device_t(mconfig, ARCHIMEDES_PODULE_SLOT, tag, owner, clock)
+ , device_single_card_slot_interface<device_archimedes_podule_interface>(mconfig, *this)
+ , m_exp(*this, finder_base::DUMMY_TAG)
+{
+}
+
+
+//-------------------------------------------------
+// device_start - device-specific startup
+//-------------------------------------------------
+
+void archimedes_podule_slot_device::device_resolve_objects()
+{
+ device_archimedes_podule_interface *const intf(get_card_device());
+ if (intf)
+ intf->set_archimedes_exp(m_exp, tag());
+}
+
+void archimedes_podule_slot_device::device_start()
+{
+}
+
+
+//**************************************************************************
+// GLOBAL VARIABLES
+//**************************************************************************
+
+DEFINE_DEVICE_TYPE(ARCHIMEDES_EXPANSION_BUS, archimedes_exp_device, "archimedes_exp", "Acorn Archimedes Expansion Bus")
+
+
+//**************************************************************************
+// LIVE DEVICE
+//**************************************************************************
+
+//-------------------------------------------------
+// archimedes_exp_device - constructor
+//-------------------------------------------------
+
+archimedes_exp_device::archimedes_exp_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock)
+ : device_t(mconfig, ARCHIMEDES_EXPANSION_BUS, tag, owner, clock)
+ , device_memory_interface(mconfig, *this)
+ , m_ioc_config("podule_ioc", ENDIANNESS_LITTLE, 32, 16, 0, address_map_constructor(FUNC(archimedes_exp_device::ioc_map), this))
+ , m_memc_config("podule_memc", ENDIANNESS_LITTLE, 32, 16, 0, address_map_constructor(FUNC(archimedes_exp_device::memc_map), this))
+ , m_out_pirq_cb(*this)
+ , m_out_pfiq_cb(*this)
+{
+}
+
+device_memory_interface::space_config_vector archimedes_exp_device::memory_space_config() const
+{
+ return space_config_vector{
+ std::make_pair(AS_PROGRAM, &m_memc_config),
+ std::make_pair(AS_IO, &m_ioc_config)
+ };
+}
+
+void archimedes_exp_device::ioc_map(address_map &map)
+{
+ map.unmap_value_high();
+}
+
+void archimedes_exp_device::memc_map(address_map &map)
+{
+ map.unmap_value_high();
+}
+
+
+//-------------------------------------------------
+// device_start - device-specific startup
+//-------------------------------------------------
+
+void archimedes_exp_device::device_start()
+{
+ m_ioc = &space(AS_IO);
+ m_memc = &space(AS_PROGRAM);
+}
+
+//-------------------------------------------------
+// device_reset - device-specific reset
+//-------------------------------------------------
+
+void archimedes_exp_device::device_reset()
+{
+ m_pirq_state = 0x00;
+ m_pirq_mask = 0xff;
+}
+
+void archimedes_exp_device::pirq_w(int state, int slot)
+{
+ if (state == ASSERT_LINE)
+ {
+ m_pirq_state |= (1 << slot);
+ }
+ else
+ {
+ m_pirq_state &= ~(1 << slot);
+ }
+
+ m_out_pirq_cb(m_pirq_state & m_pirq_mask ? ASSERT_LINE : CLEAR_LINE);
+}
+
+
+//-------------------------------------------------
+// ps - simple podule select
+//-------------------------------------------------
+
+u16 archimedes_exp_device::ps4_r(offs_t offset, u16 mem_mask)
+{
+ return m_ioc->read_word(offset << 2, mem_mask);
+}
+
+void archimedes_exp_device::ps4_w(offs_t offset, u16 data, u16 mem_mask)
+{
+ m_ioc->write_word(offset << 2, data, mem_mask);
+}
+
+
+u16 archimedes_exp_device::ps6_r(offs_t offset, u16 mem_mask)
+{
+ switch ((offset << 2) & 0xfc)
+ {
+ case 0x00:
+ return m_pirq_state & m_pirq_mask;
+
+ case 0x04:
+ return m_pirq_mask;
+ }
+
+ return 0xffff;
+}
+
+void archimedes_exp_device::ps6_w(offs_t offset, u16 data, u16 mem_mask)
+{
+ switch ((offset << 2) & 0xfc)
+ {
+ case 0x00:
+ break;
+
+ case 0x04:
+ m_pirq_mask = data & 0xff;
+ m_out_pirq_cb(m_pirq_state & m_pirq_mask ? ASSERT_LINE : CLEAR_LINE);
+ break;
+ }
+}
+
+//-------------------------------------------------
+// ms - memc select
+//-------------------------------------------------
+
+u16 archimedes_exp_device::ms_r(offs_t offset, u16 mem_mask)
+{
+ return m_memc->read_word(offset << 2, mem_mask);
+}
+
+void archimedes_exp_device::ms_w(offs_t offset, u16 data, u16 mem_mask)
+{
+ m_memc->write_word(offset << 2, data, mem_mask);
+}
+
+
+//**************************************************************************
+// DEVICE ARCHIMEDES EXPANSION INTERFACE
+//**************************************************************************
+
+//-------------------------------------------------
+// device_archimedes_podule_interface - constructor
+//-------------------------------------------------
+
+device_archimedes_podule_interface::device_archimedes_podule_interface(const machine_config &mconfig, device_t &device)
+ : device_interface(device, "arcexp")
+ , m_exp(nullptr)
+ , m_exp_slottag(nullptr)
+ , m_slot(-1)
+{
+}
+
+
+//-------------------------------------------------
+// ~device_archimedes_podule_interface - destructor
+//-------------------------------------------------
+
+device_archimedes_podule_interface::~device_archimedes_podule_interface()
+{
+}
+
+
+void device_archimedes_podule_interface::interface_pre_start()
+{
+ if (!m_exp->started())
+ throw device_missing_dependencies();
+
+ // extract the slot number from the last digit of the slot tag
+ size_t const tlen = strlen(m_exp_slottag);
+
+ m_slot = (m_exp_slottag[tlen - 1] - '0');
+ if (m_slot < 0 || m_slot > 3)
+ fatalerror("Podule %d out of range for Archimedes expansion bus\n", m_slot);
+}
+
+void device_archimedes_podule_interface::interface_post_start()
+{
+ m_exp->install_ioc_map(m_slot, *this, &device_archimedes_podule_interface::ioc_map);
+ m_exp->install_memc_map(m_slot, *this, &device_archimedes_podule_interface::memc_map);
+}
+
+
+// slot devices
+#include "a448.h"
+#include "acejoy.h"
+//#include "archdigi.h"
+//#include "archscan.h"
+#include "armadeus.h"
+//#include "discbuffer.h"
+//#include "colourcard.h"
+#include "eaglem2.h"
+#include "ether1.h"
+#include "ether2.h"
+#include "ether3.h"
+//#include "ether5.h"
+#include "ethera.h"
+#include "etherd.h"
+#include "etherr.h"
+#include "faxpack.h"
+//#include "g8.h"
+#include "greyhawk.h"
+//#include "hdfc_rdev.h"
+#include "hdisc.h"
+#include "hdisc_cw.h"
+#include "hdisc_morley.h"
+#include "hdisc_we.h"
+#include "ide_be.h"
+//#include "ide_castle.h"
+//#include "ide_dt.h"
+//#include "ide_hccs.h"
+//#include "ide_ics.h"
+#include "ide_rdev.h"
+//#include "ide_we.h"
+#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"
+#include "midi_emr.h"
+#include "midimax.h"
+#include "nexus.h"
+//#include "prisma3.h"
+#include "rom.h"
+//#include "rom_cc.h"
+#include "rs423.h"
+#include "scan256.h"
+#include "scanlight.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"
+#include "tube.h"
+//#include "ultimate.h"
+//#include "ultimatecd.h"
+
+//-------------------------------------------------
+// archimedes_exp_devices (A3x0/A4x0/A5x0/A5000)
+//-------------------------------------------------
+
+void archimedes_exp_devices(device_slot_interface &device)
+{
+ device.option_add("a448", ARC_A448); // Armadillo Systems A448 Sound Sampler
+ device.option_add("a448b", ARC_A448B); // Armadillo Systems A448b Stereo MIDI Sound Sampler
+ device.option_add("acejoy", ARC_ACEJOY); // ACE Joy Connect
+ //device.option_add("archdigi", ARC_ARCHDIGI); // Watford Electronics Archimedes Video Digitiser
+ //device.option_add("archscan", ARC_ARCHSCAN); // Watford Electronics Archimedes Scanner
+ device.option_add("armadeus", ARC_ARMADEUS); // Clares Armadeus Sampler Board
+ device.option_add("bbcio_aka10", ARC_BBCIO_AKA10); // Acorn AKA10 BBC I/O Podule
+ device.option_add("bbcio_we", ARC_BBCIO_WE); // Watford BBC User I/O Card
+ //device.option_add("cc", ARC_CC); // Wild Vision/Computer Concepts Colour Card
+ //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("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
+ //device.option_add("g8", ARC_G8); // State Machine G8 Graphic Accelerator
+ //device.option_add("g16", ARC_G16); // State Machine G16 Graphic Accelerator
+ device.option_add("greyhawk", ARC_GREYHAWK); // Computer Concepts GreyHawk Video Digitiser
+ //device.option_add("hdfc_rdev", ARC_HDFC_RDEV); // RISC Developments High Density Floppy Controller
+ device.option_add("hdisc_akd52", ARC_HDISC_AKD52); // Acorn AKD52 Hard Disc Podule
+ device.option_add("hdisc_cw", ARC_HDISC_CW); // Computerware Hard Disk Podule
+ device.option_add("hdisc_morley", ARC_HDISC_MORLEY); // Morley Electronics Hard Disc Podule
+ device.option_add("hdisc_we", ARC_HDISC_WE); // Watford Electronics Archimedes Hard Disk Podule
+ device.option_add("ide_be", ARC_IDE_BE); // Baildon Electronics IDE HD Interface
+ //device.option_add("ide_dt", ARC_IDE_DT); // D.T. Software IDE Interface
+ //device.option_add("ide_hccs", ARC_IDE_HCCS); // HCCS IDE Interface
+ device.option_add("ide_rdev", ARC_IDE_RDEV); // RISC Developments IDE Hard Disc System
+ //device.option_add("ide1v4_ics", ARC_IDE1V4_ICS); // ICS ideA Hard Disc System
+ device.option_add("iomidi_aka15", ARC_IOMIDI_AKA15); // Acorn AKA15 MIDI and BBC I/O Podule
+ device.option_add("lark", ARC_LARK); // Wild Vision/Computer Concepts Lark A16
+ device.option_add("lbp4", ARC_LBP4); // Computer Concepts LaserDirect LBP-4
+ device.option_add("midi_aka16", ARC_MIDI_AKA16); // Acorn AKA16 MIDI Podule
+ device.option_add("midi2", ARC_MIDI2_EMR); // EMR MIDI 2 Interface
+ device.option_add("midi4", ARC_MIDI4_EMR); // EMR MIDI 4 Interface
+ device.option_add("midimax", ARC_MIDIMAX); // Wild Vision MidiMax
+ device.option_add("midimax2", ARC_MIDIMAX2); // Wild Vision MidiMax 2
+ device.option_add("nexus_a500", ARC_NEXUS_A500); // SJ Research Nexus Interface (A500)
+ //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
+ device.option_add("scanlight", ARC_SCANLIGHT); // Computer Concepts ScanLight
+ 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_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
+ device.option_add("tube", ARC_TUBE); // Acorn Tube Podule
+ device.option_add("ua_morley", ARC_UA_MORLEY); // Morley Electronics Analogue and User Interface
+ //device.option_add("ultcd", ARC_ULTCD); // HCCS Ultimate CD-ROM
+}
+
+//-------------------------------------------------
+// archimedes_mini_exp_devices (A30x0/A4000)
+//-------------------------------------------------
+
+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("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
+ //device.option_add("ide1v5_ics", ARC_IDE1V5_ICS); // ICS ideA Hard Disc System
+ //device.option_add("ide3v5_ics", ARC_IDE3V5_ICS); // ICS ideA Hard Disc System
+ //device.option_add("ide_we", ARC_IDE_WE); // Watford Electronics A3000 IDE Interface
+ device.option_add("scanlight", ARC_SCANLIGHT); // Computer Concepts A3000 ScanLight
+ //device.option_add("ult3010", ARC_ULT3010); // HCCS A3010 Ultimate Expansion System
+ device.option_add("uma_morley", ARC_UMA_MORLEY); // Morley Electronics User/MIDI/Analogue Interface
+ device.option_add("upa_hccs", ARC_UPA_HCCS); // HCCS User/Analogue Podule
+ device.option_add("upmidi_aka12", ARC_UPMIDI_AKA12); // Acorn AKA12 User Port/MIDI Upgrade
+}
diff --git a/src/devices/bus/archimedes/podule/slot.h b/src/devices/bus/archimedes/podule/slot.h
new file mode 100644
index 00000000000..849226f63b5
--- /dev/null
+++ b/src/devices/bus/archimedes/podule/slot.h
@@ -0,0 +1,158 @@
+// license:BSD-3-Clause
+// copyright-holders:Nigel Barnes
+/**********************************************************************
+
+ Acorn Archimedes Expansion Bus emulation
+
+**********************************************************************/
+
+#ifndef MAME_BUS_ARCHIMEDES_PODULE_SLOT_H
+#define MAME_BUS_ARCHIMEDES_PODULE_SLOT_H
+
+#pragma once
+
+
+//**************************************************************************
+// FORWARD DECLARATIONS
+//**************************************************************************
+
+class archimedes_exp_device;
+class device_archimedes_podule_interface;
+
+
+//**************************************************************************
+// TYPE DEFINITIONS
+//**************************************************************************
+
+// ======================> archimedes_podule_slot_device
+
+class archimedes_podule_slot_device : public device_t,
+ public device_single_card_slot_interface<device_archimedes_podule_interface>
+{
+public:
+ // construction/destruction
+ template <typename T, typename U>
+ archimedes_podule_slot_device(const machine_config &mconfig, const char *tag, device_t *owner, T &&bus_tag, U &&opts, const char *dflt)
+ : archimedes_podule_slot_device(mconfig, tag, owner, DERIVED_CLOCK(1, 1))
+ {
+ option_reset();
+ opts(*this);
+ set_default_option(dflt);
+ set_fixed(false);
+ m_exp.set_tag(std::forward<T>(bus_tag));
+ }
+ archimedes_podule_slot_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock);
+
+protected:
+ // device_t implementation
+ virtual void device_resolve_objects() override ATTR_COLD;
+ virtual void device_start() override ATTR_COLD;
+
+ required_device<archimedes_exp_device> m_exp;
+};
+
+// device type definition
+DECLARE_DEVICE_TYPE(ARCHIMEDES_PODULE_SLOT, archimedes_podule_slot_device)
+
+
+
+// ======================> archimedes_exp_device
+
+class archimedes_exp_device : public device_t,
+ public device_memory_interface
+{
+public:
+ // construction/destruction
+ archimedes_exp_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock);
+
+ // inline configuration
+ auto out_irq_callback() { return m_out_pirq_cb.bind(); }
+ auto out_fiq_callback() { return m_out_pfiq_cb.bind(); }
+
+ u16 ps4_r(offs_t offset, u16 mem_mask = ~0);
+ void ps4_w(offs_t offset, u16 data, u16 mem_mask = ~0);
+ u16 ps6_r(offs_t offset, u16 mem_mask = ~0);
+ void ps6_w(offs_t offset, u16 data, u16 mem_mask = ~0);
+ u16 ms_r(offs_t offset, u16 mem_mask = ~0);
+ void ms_w(offs_t offset, u16 data, u16 mem_mask = ~0);
+
+ template<typename T> void install_ioc_map(int slot, T &device, void (T::*map)(class address_map &map))
+ {
+ offs_t base = slot << 14;
+ m_ioc->install_device(base, base + 0x3fff, device, map);
+ }
+ template<typename T> void install_memc_map(int slot, T &device, void (T::*map)(class address_map &map))
+ {
+ offs_t base = slot << 14;
+ m_memc->install_device(base, base + 0x3fff, device, map);
+ }
+
+ void pirq_w(int state, int slot);
+ void pfiq_w(int state) { m_out_pfiq_cb(state); }
+
+protected:
+ // device_t implementation
+ virtual void device_start() override ATTR_COLD;
+ virtual void device_reset() override ATTR_COLD;
+
+ // device_memory_interface implementation
+ virtual space_config_vector memory_space_config() const override;
+
+private:
+ address_space_config m_ioc_config;
+ address_space_config m_memc_config;
+
+ devcb_write_line m_out_pirq_cb;
+ devcb_write_line m_out_pfiq_cb;
+
+ u8 m_pirq_state;
+ u8 m_pirq_mask;
+
+ address_space *m_ioc;
+ address_space *m_memc;
+
+ void ioc_map(address_map &map) ATTR_COLD;
+ void memc_map(address_map &map) ATTR_COLD;
+};
+
+
+// device type definition
+DECLARE_DEVICE_TYPE(ARCHIMEDES_EXPANSION_BUS, archimedes_exp_device)
+
+
+// ======================> device_archimedes_podule_interface
+
+class device_archimedes_podule_interface : public device_interface
+{
+ friend class archimedes_exp_device;
+
+public:
+ // construction/destruction
+ virtual ~device_archimedes_podule_interface();
+
+ // inline configuration
+ void set_archimedes_exp(archimedes_exp_device *exp, const char *slottag) { m_exp = exp; m_exp_slottag = slottag; }
+
+protected:
+ void set_pirq(int state) { m_exp->pirq_w(state, m_slot); }
+ void set_pfiq(int state) { m_exp->pfiq_w(state); }
+
+ device_archimedes_podule_interface(const machine_config &mconfig, device_t &device);
+
+ virtual void interface_pre_start() override;
+ virtual void interface_post_start() override;
+
+ virtual void ioc_map(address_map &map) { }
+ virtual void memc_map(address_map &map) { }
+
+ archimedes_exp_device *m_exp;
+ const char *m_exp_slottag;
+ int m_slot;
+};
+
+
+void archimedes_exp_devices(device_slot_interface &device);
+void archimedes_mini_exp_devices(device_slot_interface &device);
+
+
+#endif // MAME_BUS_ARCHIMEDES_PODULE_SLOT_H
diff --git a/src/devices/bus/archimedes/podule/spectra.cpp b/src/devices/bus/archimedes/podule/spectra.cpp
new file mode 100644
index 00000000000..7a9ada1839b
--- /dev/null
+++ b/src/devices/bus/archimedes/podule/spectra.cpp
@@ -0,0 +1,126 @@
+// license:BSD-3-Clause
+// copyright-holders:Nigel Barnes
+/**********************************************************************
+
+ Beebug Spectra Colour Scanner
+
+ http://chrisacorns.computinghistory.org.uk/32bit_UpgradesA2G/Beebug_ColourScanner.html
+
+ TODO:
+ - unknown scanner.
+
+**********************************************************************/
+
+#include "emu.h"
+#include "spectra.h"
+#include "imagedev/picture.h"
+
+
+namespace {
+
+class arc_spectra_device :
+ public device_t,
+ public device_archimedes_podule_interface
+{
+public:
+ // construction/destruction
+ arc_spectra_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock);
+
+ static constexpr feature_type unemulated_features() { return feature::CAPTURE; }
+
+protected:
+ // device-level overrides
+ virtual void device_start() override ATTR_COLD;
+ virtual void device_reset() override ATTR_COLD;
+
+ // optional information overrides
+ virtual void device_add_mconfig(machine_config &config) override ATTR_COLD;
+ virtual const tiny_rom_entry *device_rom_region() const override ATTR_COLD;
+
+ // device_archimedes_podule_interface overrides
+ virtual void ioc_map(address_map &map) override ATTR_COLD;
+
+private:
+ required_memory_region m_podule_rom;
+ required_device<picture_image_device> m_picture;
+
+ u8 m_rom_page;
+};
+
+
+void arc_spectra_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) & 0x7800)]; })).umask32(0x000000ff);
+ map(0x2000, 0x2000).lw8(NAME([this](u8 data) { m_rom_page = data; }));
+}
+
+
+//-------------------------------------------------
+// ROM( spectra )
+//-------------------------------------------------
+
+ROM_START( spectra )
+ ROM_REGION(0x8000, "podule_rom", 0)
+ ROM_LOAD("spectra_1.05.bin", 0x0000, 0x8000, CRC(51b858ae) SHA1(bac53e4cd1047606e6314992e2581acf09e1b658))
+ROM_END
+
+const tiny_rom_entry *arc_spectra_device::device_rom_region() const
+{
+ return ROM_NAME( spectra );
+}
+
+
+//-------------------------------------------------
+// device_add_mconfig - add device configuration
+//-------------------------------------------------
+
+void arc_spectra_device::device_add_mconfig(machine_config &config)
+{
+ IMAGE_PICTURE(config, m_picture);
+}
+
+
+//**************************************************************************
+// LIVE DEVICE
+//**************************************************************************
+
+//-------------------------------------------------
+// arc_spectra_device - constructor
+//-------------------------------------------------
+
+arc_spectra_device::arc_spectra_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock)
+ : device_t(mconfig, ARC_SPECTRA, tag, owner, clock)
+ , device_archimedes_podule_interface(mconfig, *this)
+ , m_podule_rom(*this, "podule_rom")
+ , m_picture(*this, "srcimg")
+ , m_rom_page(0)
+{
+}
+
+
+//-------------------------------------------------
+// device_start - device-specific startup
+//-------------------------------------------------
+
+void arc_spectra_device::device_start()
+{
+ save_item(NAME(m_rom_page));
+}
+
+//-------------------------------------------------
+// device_reset - device-specific reset
+//-------------------------------------------------
+
+void arc_spectra_device::device_reset()
+{
+ m_rom_page = 0x00;
+}
+
+} // anonymous namespace
+
+
+//**************************************************************************
+// DEVICE DEFINITIONS
+//**************************************************************************
+
+DEFINE_DEVICE_TYPE_PRIVATE(ARC_SPECTRA, device_archimedes_podule_interface, arc_spectra_device, "arc_spectra", "Beebug Spectra Colour Scanner")
diff --git a/src/devices/bus/archimedes/podule/spectra.h b/src/devices/bus/archimedes/podule/spectra.h
new file mode 100644
index 00000000000..af4dea15d8a
--- /dev/null
+++ b/src/devices/bus/archimedes/podule/spectra.h
@@ -0,0 +1,19 @@
+// license:BSD-3-Clause
+// copyright-holders:Nigel Barnes
+/**********************************************************************
+
+ Beebug Spectra Colour Scanner
+
+**********************************************************************/
+
+#ifndef MAME_BUS_ARCHIMEDES_PODULE_SPECTRA_H
+#define MAME_BUS_ARCHIMEDES_PODULE_SPECTRA_H
+
+#pragma once
+
+#include "slot.h"
+
+// device type definition
+DECLARE_DEVICE_TYPE(ARC_SPECTRA, device_archimedes_podule_interface)
+
+#endif // MAME_BUS_ARCHIMEDES_PODULE_SPECTRA_H
diff --git a/src/devices/bus/archimedes/podule/tube.cpp b/src/devices/bus/archimedes/podule/tube.cpp
new file mode 100644
index 00000000000..b9d5b724182
--- /dev/null
+++ b/src/devices/bus/archimedes/podule/tube.cpp
@@ -0,0 +1,87 @@
+// license:BSD-3-Clause
+// copyright-holders:Nigel Barnes
+/**********************************************************************
+
+ Acorn Tube Podule
+
+ TODO:
+ - attach BBC Micro as Tube Host.
+
+**********************************************************************/
+
+#include "emu.h"
+#include "tube.h"
+#include "machine/tube.h"
+
+
+namespace {
+
+class arc_tube_device :
+ public device_t,
+ public device_archimedes_podule_interface
+{
+public:
+ // construction/destruction
+ arc_tube_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock);
+
+protected:
+ // device-level overrides
+ virtual void device_start() override ATTR_COLD;
+
+ // optional information overrides
+ virtual void device_add_mconfig(machine_config &config) override ATTR_COLD;
+
+ // device_archimedes_podule_interface overrides
+ virtual void ioc_map(address_map &map) override ATTR_COLD;
+};
+
+
+void arc_tube_device::ioc_map(address_map &map)
+{
+ map(0x0000, 0x3fff).rw("tube", FUNC(tube_device::parasite_r), FUNC(tube_device::parasite_w)).umask32(0x000000ff);
+}
+
+
+//-------------------------------------------------
+// device_add_mconfig - add device configuration
+//-------------------------------------------------
+
+void arc_tube_device::device_add_mconfig(machine_config &config)
+{
+ tube_device &tube(TUBE(config, "tube"));
+ tube.pnmi_handler().set([this](int state) { set_pfiq(state); });
+ tube.pirq_handler().set([this](int state) { set_pirq(state); });
+}
+
+
+//**************************************************************************
+// LIVE DEVICE
+//**************************************************************************
+
+//-------------------------------------------------
+// arc_tube_device - constructor
+//-------------------------------------------------
+
+arc_tube_device::arc_tube_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock)
+ : device_t(mconfig, ARC_TUBE, tag, owner, clock)
+ , device_archimedes_podule_interface(mconfig, *this)
+{
+}
+
+
+//-------------------------------------------------
+// device_start - device-specific startup
+//-------------------------------------------------
+
+void arc_tube_device::device_start()
+{
+}
+
+} // anonymous namespace
+
+
+//**************************************************************************
+// DEVICE DEFINITIONS
+//**************************************************************************
+
+DEFINE_DEVICE_TYPE_PRIVATE(ARC_TUBE, device_archimedes_podule_interface, arc_tube_device, "arc_tube", "Acorn Tube Podule")
diff --git a/src/devices/bus/archimedes/podule/tube.h b/src/devices/bus/archimedes/podule/tube.h
new file mode 100644
index 00000000000..4c78a7404e4
--- /dev/null
+++ b/src/devices/bus/archimedes/podule/tube.h
@@ -0,0 +1,19 @@
+// license:BSD-3-Clause
+// copyright-holders:Nigel Barnes
+/**********************************************************************
+
+ Acorn Tube Podule
+
+**********************************************************************/
+
+#ifndef MAME_BUS_ARCHIMEDES_PODULE_TUBE_H
+#define MAME_BUS_ARCHIMEDES_PODULE_TUBE_H
+
+#pragma once
+
+#include "slot.h"
+
+// device type definition
+DECLARE_DEVICE_TYPE(ARC_TUBE, device_archimedes_podule_interface)
+
+#endif // MAME_BUS_ARCHIMEDES_PODULE_TUBE_H
diff --git a/src/devices/bus/astrocde/accessory.cpp b/src/devices/bus/astrocde/accessory.cpp
index fe7727b855d..b2e5fd6cf5c 100644
--- a/src/devices/bus/astrocde/accessory.cpp
+++ b/src/devices/bus/astrocde/accessory.cpp
@@ -19,7 +19,7 @@ DEFINE_DEVICE_TYPE(ASTROCADE_ACCESSORY_PORT, astrocade_accessory_port_device, "a
//**************************************************************************
device_astrocade_accessory_interface::device_astrocade_accessory_interface(const machine_config &mconfig, device_t &device)
- : device_slot_card_interface(mconfig, device)
+ : device_interface(device, "astrocadeacc")
, m_port(dynamic_cast<astrocade_accessory_port_device *>(device.owner()))
{
}
@@ -30,8 +30,6 @@ device_astrocade_accessory_interface::~device_astrocade_accessory_interface()
void device_astrocade_accessory_interface::interface_validity_check(validity_checker &valid) const
{
- device_slot_card_interface::interface_validity_check(valid);
-
if (device().owner() && !m_port)
{
osd_printf_error("Owner device %s (%s) is not an astrocade_accessory_port_device\n", device().owner()->tag(), device().owner()->name());
@@ -40,8 +38,6 @@ void device_astrocade_accessory_interface::interface_validity_check(validity_che
void device_astrocade_accessory_interface::interface_pre_start()
{
- device_slot_card_interface::interface_pre_start();
-
if (m_port && !m_port->started())
throw device_missing_dependencies();
}
@@ -53,7 +49,7 @@ void device_astrocade_accessory_interface::interface_pre_start()
astrocade_accessory_port_device::astrocade_accessory_port_device(machine_config const &mconfig, char const *tag, device_t *owner, uint32_t clock)
: device_t(mconfig, ASTROCADE_ACCESSORY_PORT, tag, owner, clock)
- , device_slot_interface(mconfig, *this)
+ , device_single_card_slot_interface<device_astrocade_accessory_interface>(mconfig, *this)
, m_ltpen(0)
, m_ltpen_handler(*this)
, m_screen(*this, finder_base::DUMMY_TAG)
@@ -65,38 +61,15 @@ astrocade_accessory_port_device::~astrocade_accessory_port_device()
{
}
-void astrocade_accessory_port_device::device_validity_check(validity_checker &valid) const
-{
- device_t *const card(get_card_device());
- if (card && !dynamic_cast<device_astrocade_accessory_interface *>(card))
- {
- osd_printf_error("Card device %s (%s) does not implement device_astrocade_accessory_interface\n", card->tag(), card->name());
- }
-}
-
void astrocade_accessory_port_device::device_resolve_objects()
{
- device_astrocade_accessory_interface *const card(dynamic_cast<device_astrocade_accessory_interface *>(get_card_device()));
- if (card)
- {
- m_device = card;
+ 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()
{
- device_t *const card(get_card_device());
- if (card)
- {
- if (!m_device)
- {
- throw emu_fatalerror("astrocade_accessory_port_device: card device %s (%s) does not implement device_astrocade_accessory_interface\n", card->tag(), card->name());
- }
- }
-
save_item(NAME(m_ltpen));
m_ltpen = 0;
diff --git a/src/devices/bus/astrocde/accessory.h b/src/devices/bus/astrocde/accessory.h
index d745e464cd2..00d4c55abd8 100644
--- a/src/devices/bus/astrocde/accessory.h
+++ b/src/devices/bus/astrocde/accessory.h
@@ -21,7 +21,7 @@ class device_astrocade_accessory_interface;
// ======================> astrocade_accessory_port_device
-class astrocade_accessory_port_device : public device_t, public device_slot_interface
+class astrocade_accessory_port_device : public device_t, public device_single_card_slot_interface<device_astrocade_accessory_interface>
{
public:
// construction/destruction
@@ -42,9 +42,8 @@ public:
protected:
// device_t implementation
- virtual void device_validity_check(validity_checker &valid) const override ATTR_COLD;
- virtual void device_resolve_objects() override;
- virtual void device_start() override;
+ virtual void device_resolve_objects() override ATTR_COLD;
+ virtual void device_start() override ATTR_COLD;
int m_ltpen;
devcb_write_line m_ltpen_handler;
@@ -59,12 +58,12 @@ private:
// ======================> device_astrocade_accessory_interface
-class device_astrocade_accessory_interface : public device_slot_card_interface
+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/cassette.h b/src/devices/bus/astrocde/cassette.h
index d36e8a1bfd7..01777a890f9 100644
--- a/src/devices/bus/astrocde/cassette.h
+++ b/src/devices/bus/astrocde/cassette.h
@@ -34,9 +34,9 @@ public:
protected:
// device_t implementation
- virtual void device_start() override;
- virtual void device_reset() override;
- virtual void device_add_mconfig(machine_config &config) override;
+ 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;
TIMER_DEVICE_CALLBACK_MEMBER(check_cassette_wave);
TIMER_DEVICE_CALLBACK_MEMBER(pulse_cassette_clock);
diff --git a/src/devices/bus/astrocde/ctrl.cpp b/src/devices/bus/astrocde/ctrl.cpp
index 89cd60ca6a5..07aa620aba6 100644
--- a/src/devices/bus/astrocde/ctrl.cpp
+++ b/src/devices/bus/astrocde/ctrl.cpp
@@ -19,7 +19,7 @@ DEFINE_DEVICE_TYPE(ASTROCADE_CTRL_PORT, astrocade_ctrl_port_device, "astrocade_c
//**************************************************************************
device_astrocade_ctrl_interface::device_astrocade_ctrl_interface(const machine_config &mconfig, device_t &device)
- : device_slot_card_interface(mconfig, device)
+ : device_interface(device, "astrocadectrl")
, m_port(dynamic_cast<astrocade_ctrl_port_device *>(device.owner()))
{
}
@@ -30,8 +30,6 @@ device_astrocade_ctrl_interface::~device_astrocade_ctrl_interface()
void device_astrocade_ctrl_interface::interface_validity_check(validity_checker &valid) const
{
- device_slot_card_interface::interface_validity_check(valid);
-
if (device().owner() && !m_port)
{
osd_printf_error("Owner device %s (%s) is not an astrocade_ctrl_port_device\n", device().owner()->tag(), device().owner()->name());
@@ -40,12 +38,19 @@ void device_astrocade_ctrl_interface::interface_validity_check(validity_checker
void device_astrocade_ctrl_interface::interface_pre_start()
{
- device_slot_card_interface::interface_pre_start();
-
if (m_port && !m_port->started())
throw device_missing_dependencies();
}
+void device_astrocade_ctrl_interface::write_ltpen(int state)
+{
+ if (m_port->m_ltpen != state)
+ {
+ m_port->m_ltpen = state;
+ m_port->m_ltpen_handler(state);
+ }
+}
+
//**************************************************************************
// Bally Astrocade controller port
@@ -53,7 +58,7 @@ void device_astrocade_ctrl_interface::interface_pre_start()
astrocade_ctrl_port_device::astrocade_ctrl_port_device(machine_config const &mconfig, char const *tag, device_t *owner, uint32_t clock)
: device_t(mconfig, ASTROCADE_CTRL_PORT, tag, owner, clock)
- , device_slot_interface(mconfig, *this)
+ , device_single_card_slot_interface<device_astrocade_ctrl_interface>(mconfig, *this)
, m_ltpen(0)
, m_ltpen_handler(*this)
, m_device(nullptr)
@@ -64,35 +69,13 @@ astrocade_ctrl_port_device::~astrocade_ctrl_port_device()
{
}
-void astrocade_ctrl_port_device::device_validity_check(validity_checker &valid) const
-{
- device_t *const card(get_card_device());
- if (card && !dynamic_cast<device_astrocade_ctrl_interface *>(card))
- {
- osd_printf_error("Card device %s (%s) does not implement device_astrocade_ctrl_interface\n", card->tag(), card->name());
- }
-}
-
void astrocade_ctrl_port_device::device_resolve_objects()
{
- device_astrocade_ctrl_interface *const card(dynamic_cast<device_astrocade_ctrl_interface *>(get_card_device()));
- if (card)
- m_device = card;
-
- m_ltpen_handler.resolve_safe();
+ m_device = get_card_device();
}
void astrocade_ctrl_port_device::device_start()
{
- device_t *const card(get_card_device());
- if (card)
- {
- if (!m_device)
- {
- throw emu_fatalerror("astrocade_ctrl_port_device: card device %s (%s) does not implement device_astrocade_ctrl_interface\n", card->tag(), card->name());
- }
- }
-
save_item(NAME(m_ltpen));
m_ltpen = 0;
@@ -100,15 +83,6 @@ void astrocade_ctrl_port_device::device_start()
m_ltpen_handler(0);
}
-uint8_t astrocade_ctrl_port_device::read_handle()
-{
- return m_device ? m_device->read_handle() : 0;
-}
-
-uint8_t astrocade_ctrl_port_device::read_knob()
-{
- return m_device ? m_device->read_knob() : 0;
-}
#include "joy.h"
#include "cassette.h"
diff --git a/src/devices/bus/astrocde/ctrl.h b/src/devices/bus/astrocde/ctrl.h
index 0cc34ea4dcc..871ae12b14d 100644
--- a/src/devices/bus/astrocde/ctrl.h
+++ b/src/devices/bus/astrocde/ctrl.h
@@ -10,16 +10,42 @@
FORWARD DECLARATIONS
***************************************************************************/
-class device_astrocade_ctrl_interface;
+class astrocade_ctrl_port_device;
/***************************************************************************
TYPE DEFINITIONS
***************************************************************************/
+// ======================> device_astrocade_ctrl_interface
+
+class device_astrocade_ctrl_interface : public device_interface
+{
+public:
+ virtual ~device_astrocade_ctrl_interface();
+
+ virtual uint8_t read_handle() { return 0; }
+ virtual uint8_t read_knob() { return 0; }
+
+protected:
+ device_astrocade_ctrl_interface(machine_config const &mconfig, device_t &device);
+
+ // device_interface implementation
+ virtual void interface_validity_check(validity_checker &valid) const override ATTR_COLD;
+ virtual void interface_pre_start() override;
+
+ void write_ltpen(int state);
+
+private:
+ astrocade_ctrl_port_device *const m_port;
+
+ friend class astrocade_ctrl_port_device;
+};
+
+
// ======================> astrocade_ctrl_port_device
-class astrocade_ctrl_port_device : public device_t, public device_slot_interface
+class astrocade_ctrl_port_device : public device_t, public device_single_card_slot_interface<device_astrocade_ctrl_interface>
{
public:
// construction/destruction
@@ -37,14 +63,13 @@ public:
auto ltpen_handler() { return m_ltpen_handler.bind(); }
- uint8_t read_handle();
- uint8_t read_knob();
+ uint8_t read_handle() { return m_device ? m_device->read_handle() : 0; }
+ uint8_t read_knob() { return m_device ? m_device->read_knob() : 0; }
protected:
// device_t implementation
- virtual void device_validity_check(validity_checker &valid) const override ATTR_COLD;
- virtual void device_resolve_objects() override;
- virtual void device_start() override;
+ virtual void device_resolve_objects() override ATTR_COLD;
+ virtual void device_start() override ATTR_COLD;
int m_ltpen;
devcb_write_line m_ltpen_handler;
@@ -56,32 +81,6 @@ private:
};
-// ======================> device_astrocade_ctrl_interface
-
-class device_astrocade_ctrl_interface : public device_slot_card_interface
-{
-public:
- virtual ~device_astrocade_ctrl_interface();
-
- virtual uint8_t read_handle() { return 0; }
- virtual uint8_t read_knob() { return 0; }
-
- DECLARE_WRITE_LINE_MEMBER( write_ltpen ) { m_port->m_ltpen = state; m_port->m_ltpen_handler(state); }
-
-protected:
- device_astrocade_ctrl_interface(machine_config const &mconfig, device_t &device);
-
- // device_interface implementation
- virtual void interface_validity_check(validity_checker &valid) const override ATTR_COLD;
- virtual void interface_pre_start() override;
-
-private:
- astrocade_ctrl_port_device *const m_port;
-
- friend class astrocade_ctrl_port_device;
-};
-
-
/***************************************************************************
FUNCTIONS
***************************************************************************/
diff --git a/src/devices/bus/astrocde/exp.cpp b/src/devices/bus/astrocde/exp.cpp
index 9fe3c9f3fda..a33259380f1 100644
--- a/src/devices/bus/astrocde/exp.cpp
+++ b/src/devices/bus/astrocde/exp.cpp
@@ -17,13 +17,13 @@
DEFINE_DEVICE_TYPE(ASTROCADE_EXP_SLOT, astrocade_exp_device, "astrocade_exp", "Bally Astrocade expansion")
-device_astrocade_card_interface::device_astrocade_card_interface(const machine_config &mconfig, device_t &device)
- : device_slot_card_interface(mconfig, device)
+device_astrocade_exp_interface::device_astrocade_exp_interface(const machine_config &mconfig, device_t &device) :
+ device_interface(device, "astrocadeexp")
{
}
-device_astrocade_card_interface::~device_astrocade_card_interface()
+device_astrocade_exp_interface::~device_astrocade_exp_interface()
{
}
@@ -37,7 +37,7 @@ device_astrocade_card_interface::~device_astrocade_card_interface()
//-------------------------------------------------
astrocade_exp_device::astrocade_exp_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) :
device_t(mconfig, ASTROCADE_EXP_SLOT, tag, owner, clock),
- device_slot_interface(mconfig, *this),
+ device_single_card_slot_interface<device_astrocade_exp_interface>(mconfig, *this),
m_card_mounted(false), m_card(nullptr)
{
}
@@ -57,7 +57,7 @@ astrocade_exp_device::~astrocade_exp_device()
void astrocade_exp_device::device_start()
{
- m_card = dynamic_cast<device_astrocade_card_interface *>(get_card_device());
+ m_card = get_card_device();
if (m_card)
m_card_mounted = true;
}
@@ -66,18 +66,18 @@ void astrocade_exp_device::device_start()
read
-------------------------------------------------*/
-READ8_MEMBER(astrocade_exp_device::read)
+uint8_t astrocade_exp_device::read(offs_t offset)
{
if (m_card)
- return m_card->read(space, offset);
+ return m_card->read(offset);
else
return 0xff;
}
-READ8_MEMBER(astrocade_exp_device::read_io)
+uint8_t astrocade_exp_device::read_io(offs_t offset)
{
if (m_card)
- return m_card->read_io(space, offset);
+ return m_card->read_io(offset);
else
return 0xff;
}
@@ -86,14 +86,14 @@ READ8_MEMBER(astrocade_exp_device::read_io)
write
-------------------------------------------------*/
-WRITE8_MEMBER(astrocade_exp_device::write)
+void astrocade_exp_device::write(offs_t offset, uint8_t data)
{
if (m_card)
- m_card->write(space, offset, data);
+ m_card->write(offset, data);
}
-WRITE8_MEMBER(astrocade_exp_device::write_io)
+void astrocade_exp_device::write_io(offs_t offset, uint8_t data)
{
if (m_card)
- m_card->write_io(space, offset, data);
+ m_card->write_io(offset, data);
}
diff --git a/src/devices/bus/astrocde/exp.h b/src/devices/bus/astrocde/exp.h
index a01db130974..4078147ebb7 100644
--- a/src/devices/bus/astrocde/exp.h
+++ b/src/devices/bus/astrocde/exp.h
@@ -1,30 +1,30 @@
// license:BSD-3-Clause
// copyright-holders:Fabio Priuli
-#ifndef MAME_BUS_ASTROCADE_EXP_H
-#define MAME_BUS_ASTROCADE_EXP_H
+#ifndef MAME_BUS_ASTROCDE_EXP_H
+#define MAME_BUS_ASTROCDE_EXP_H
-// ======================> device_astrocade_card_interface
+// ======================> device_astrocade_exp_interface
-class device_astrocade_card_interface : public device_slot_card_interface
+class device_astrocade_exp_interface : public device_interface
{
public:
// construction/destruction
- virtual ~device_astrocade_card_interface();
+ virtual ~device_astrocade_exp_interface();
// reading and writing
- virtual DECLARE_READ8_MEMBER(read) { return 0xff; }
- virtual DECLARE_WRITE8_MEMBER(write) { }
- virtual DECLARE_READ8_MEMBER(read_io) { return 0xff; }
- virtual DECLARE_WRITE8_MEMBER(write_io) { }
+ virtual uint8_t read(offs_t offset) { return 0xff; }
+ virtual void write(offs_t offset, uint8_t data) { }
+ virtual uint8_t read_io(offs_t offset) { return 0xff; }
+ virtual void write_io(offs_t offset, uint8_t data) { }
protected:
- device_astrocade_card_interface(const machine_config &mconfig, device_t &device);
+ device_astrocade_exp_interface(const machine_config &mconfig, device_t &device);
};
// ======================> astrocade_exp_device
-class astrocade_exp_device : public device_t, public device_slot_interface
+class astrocade_exp_device : public device_t, public device_single_card_slot_interface<device_astrocade_exp_interface>
{
public:
// construction/destruction
@@ -41,22 +41,22 @@ public:
virtual ~astrocade_exp_device();
// device-level overrides
- virtual void device_start() override;
+ virtual void device_start() override ATTR_COLD;
bool get_card_mounted() { return m_card_mounted; }
// reading and writing
- virtual DECLARE_READ8_MEMBER(read);
- virtual DECLARE_WRITE8_MEMBER(write);
- virtual DECLARE_READ8_MEMBER(read_io);
- virtual DECLARE_WRITE8_MEMBER(write_io);
+ uint8_t read(offs_t offset);
+ void write(offs_t offset, uint8_t data);
+ uint8_t read_io(offs_t offset);
+ void write_io(offs_t offset, uint8_t data);
protected:
bool m_card_mounted;
- device_astrocade_card_interface* m_card;
+ device_astrocade_exp_interface* m_card;
};
// device type definition
DECLARE_DEVICE_TYPE(ASTROCADE_EXP_SLOT, astrocade_exp_device)
-#endif // MAME_BUS_ASTROCADE_EXP_H
+#endif // MAME_BUS_ASTROCDE_EXP_H
diff --git a/src/devices/bus/astrocde/joy.h b/src/devices/bus/astrocde/joy.h
index bb8f755c845..88e641a3ddc 100644
--- a/src/devices/bus/astrocde/joy.h
+++ b/src/devices/bus/astrocde/joy.h
@@ -27,7 +27,7 @@ public:
protected:
// device_t implementation
- virtual ioport_constructor device_input_ports() const override;
+ virtual ioport_constructor device_input_ports() const override ATTR_COLD;
virtual void device_start() override { }
private:
diff --git a/src/devices/bus/astrocde/lightpen.cpp b/src/devices/bus/astrocde/lightpen.cpp
index 07c5c7480ee..7758b850c73 100644
--- a/src/devices/bus/astrocde/lightpen.cpp
+++ b/src/devices/bus/astrocde/lightpen.cpp
@@ -31,7 +31,7 @@ astrocade_lightpen_device::~astrocade_lightpen_device()
void astrocade_lightpen_device::device_start()
{
- m_pen_timer = timer_alloc(TIMER_TRIGGER);
+ m_pen_timer = timer_alloc(FUNC(astrocade_lightpen_device::trigger_tick), this);
save_item(NAME(m_retrigger));
}
@@ -42,20 +42,17 @@ void astrocade_lightpen_device::device_reset()
m_retrigger = false;
}
-void astrocade_lightpen_device::device_timer(emu_timer &timer, device_timer_id id, int param, void *ptr)
+TIMER_CALLBACK_MEMBER(astrocade_lightpen_device::trigger_tick)
{
- if (id == TIMER_TRIGGER)
- {
- write_ltpen(1);
- write_ltpen(0);
- if (m_retrigger)
- m_pen_timer->adjust(m_screen->time_until_pos(m_lighty->read(), m_lightx->read()));
- else
- m_pen_timer->adjust(attotime::never);
- }
+ write_ltpen(1);
+ write_ltpen(0);
+ if (m_retrigger)
+ m_pen_timer->adjust(m_screen->time_until_pos(m_lighty->read(), m_lightx->read()));
+ else
+ m_pen_timer->adjust(attotime::never);
}
-INPUT_CHANGED_MEMBER( astrocade_lightpen_device::trigger )
+INPUT_CHANGED_MEMBER(astrocade_lightpen_device::trigger)
{
if (newval)
{
@@ -71,7 +68,7 @@ INPUT_CHANGED_MEMBER( astrocade_lightpen_device::trigger )
static INPUT_PORTS_START( astrocade_lightpen )
PORT_START("TRIGGER")
- PORT_BIT( 0x01, IP_ACTIVE_HIGH, IPT_BUTTON1 ) PORT_CHANGED_MEMBER(DEVICE_SELF, astrocade_lightpen_device, trigger, 0)
+ PORT_BIT( 0x01, IP_ACTIVE_HIGH, IPT_BUTTON1 ) PORT_CHANGED_MEMBER(DEVICE_SELF, FUNC(astrocade_lightpen_device::trigger), 0)
PORT_BIT( 0xfe, IP_ACTIVE_HIGH, IPT_UNUSED )
PORT_START("LIGHTX")
diff --git a/src/devices/bus/astrocde/lightpen.h b/src/devices/bus/astrocde/lightpen.h
index a0863d5d3e8..9f6d03c3210 100644
--- a/src/devices/bus/astrocde/lightpen.h
+++ b/src/devices/bus/astrocde/lightpen.h
@@ -22,16 +22,15 @@ public:
astrocade_lightpen_device(machine_config const &mconfig, char const *tag, device_t *owner, uint32_t clock = 0U);
virtual ~astrocade_lightpen_device();
- DECLARE_INPUT_CHANGED_MEMBER( trigger );
+ DECLARE_INPUT_CHANGED_MEMBER(trigger);
protected:
// device_t implementation
- virtual void device_start() override;
- virtual void device_reset() override;
- virtual ioport_constructor device_input_ports() const override;
- virtual void device_timer(emu_timer &timer, device_timer_id id, int param, void *ptr) override;
+ virtual void device_start() override ATTR_COLD;
+ virtual void device_reset() override ATTR_COLD;
+ virtual ioport_constructor device_input_ports() const override ATTR_COLD;
- static const device_timer_id TIMER_TRIGGER = 0;
+ TIMER_CALLBACK_MEMBER(trigger_tick);
private:
required_ioport m_trigger;
diff --git a/src/devices/bus/astrocde/ram.cpp b/src/devices/bus/astrocde/ram.cpp
index 8f20b0256fa..39eb299d8f6 100644
--- a/src/devices/bus/astrocde/ram.cpp
+++ b/src/devices/bus/astrocde/ram.cpp
@@ -70,7 +70,7 @@ DEFINE_DEVICE_TYPE(ASTROCADE_RL64RAM, astrocade_rl64ram_device, "astroca
astrocade_blueram_4k_device::astrocade_blueram_4k_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_astrocade_card_interface(mconfig, *this)
+ , device_astrocade_exp_interface(mconfig, *this)
, m_write_prot(*this, "RAM_PROTECT")
, m_ramio(*this, "ramio")
, m_cassette(*this, "cassette")
@@ -93,23 +93,23 @@ astrocade_blueram_32k_device::astrocade_blueram_32k_device(const machine_config
}
astrocade_viper_sys1_device::astrocade_viper_sys1_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
- : device_t(mconfig, ASTROCADE_VIPER_SYS1, tag, owner, clock),
- device_astrocade_card_interface(mconfig, *this),
- m_write_prot(*this, "RAM_PROTECT")
+ : device_t(mconfig, ASTROCADE_VIPER_SYS1, tag, owner, clock)
+ , device_astrocade_exp_interface(mconfig, *this)
+ , m_write_prot(*this, "RAM_PROTECT")
{
}
astrocade_whiteram_device::astrocade_whiteram_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
- : device_t(mconfig, ASTROCADE_WHITERAM, tag, owner, clock),
- device_astrocade_card_interface(mconfig, *this),
- m_write_prot(*this, "RAM_PROTECT")
+ : device_t(mconfig, ASTROCADE_WHITERAM, tag, owner, clock)
+ , device_astrocade_exp_interface(mconfig, *this)
+ , m_write_prot(*this, "RAM_PROTECT")
{
}
astrocade_rl64ram_device::astrocade_rl64ram_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
- : device_t(mconfig, ASTROCADE_RL64RAM, tag, owner, clock),
- device_astrocade_card_interface(mconfig, *this),
- m_write_prot(*this, "RAM_PROTECT")
+ : device_t(mconfig, ASTROCADE_RL64RAM, tag, owner, clock)
+ , device_astrocade_exp_interface(mconfig, *this)
+ , m_write_prot(*this, "RAM_PROTECT")
{
}
@@ -151,7 +151,7 @@ ioport_constructor astrocade_rl64ram_device::device_input_ports() const
-------------------------------------------------*/
// Blue RAM expansions have RAM starting at 0x6000, up to the RAM size
-READ8_MEMBER(astrocade_blueram_4k_device::read)
+uint8_t astrocade_blueram_4k_device::read(offs_t offset)
{
if (offset >= 0x1000 && offset < 0x1000 + m_ram.size())
return m_ram[offset - 0x1000];
@@ -159,18 +159,18 @@ READ8_MEMBER(astrocade_blueram_4k_device::read)
return 0;
}
-WRITE8_MEMBER(astrocade_blueram_4k_device::write)
+void astrocade_blueram_4k_device::write(offs_t offset, uint8_t data)
{
if (offset >= 0x1000 && offset < 0x1000 + m_ram.size() && !m_write_prot->read())
m_ram[offset - 0x1000] = data;
}
-READ8_MEMBER(astrocade_blueram_4k_device::read_io)
+uint8_t astrocade_blueram_4k_device::read_io(offs_t offset)
{
return m_ramio->read_io(offset & 0x7f);
}
-WRITE8_MEMBER(astrocade_blueram_4k_device::write_io)
+void astrocade_blueram_4k_device::write_io(offs_t offset, uint8_t data)
{
logerror("write_io: %04x = %02x\n", offset, data);
m_ramio->write_io(offset & 0x7f, data);
@@ -196,7 +196,7 @@ void astrocade_blueram_4k_device::portb_w(uint8_t data)
}
// Viper System 1 expansion has RAM in 0x6000-0x9fff
-READ8_MEMBER(astrocade_viper_sys1_device::read)
+uint8_t astrocade_viper_sys1_device::read(offs_t offset)
{
if (offset >= 0x1000 && offset < 0xa000)
return m_ram[offset - 0x1000];
@@ -204,7 +204,7 @@ READ8_MEMBER(astrocade_viper_sys1_device::read)
return 0;
}
-WRITE8_MEMBER(astrocade_viper_sys1_device::write)
+void astrocade_viper_sys1_device::write(offs_t offset, uint8_t data)
{
if (offset >= 0x1000 && offset < 0xa000 && !m_write_prot->read())
m_ram[offset - 0x1000] = data;
@@ -213,12 +213,12 @@ WRITE8_MEMBER(astrocade_viper_sys1_device::write)
// Lil' WHITE RAM expansion has RAM in 0x5000-0xcfff + a mirror of the first 0x3000 bytes up to 0xffff
-READ8_MEMBER(astrocade_whiteram_device::read)
+uint8_t astrocade_whiteram_device::read(offs_t offset)
{
return m_ram[offset % 0x8000];
}
-WRITE8_MEMBER(astrocade_whiteram_device::write)
+void astrocade_whiteram_device::write(offs_t offset, uint8_t data)
{
if (!m_write_prot->read())
m_ram[offset % 0x8000] = data;
@@ -227,12 +227,12 @@ WRITE8_MEMBER(astrocade_whiteram_device::write)
// R&L 64K RAM Board (44KB installed) has RAM in 0x5000-0xffff
-READ8_MEMBER(astrocade_rl64ram_device::read)
+uint8_t astrocade_rl64ram_device::read(offs_t offset)
{
return m_ram[offset];
}
-WRITE8_MEMBER(astrocade_rl64ram_device::write)
+void astrocade_rl64ram_device::write(offs_t offset, uint8_t data)
{
if (!m_write_prot->read())
m_ram[offset] = data;
diff --git a/src/devices/bus/astrocde/ram.h b/src/devices/bus/astrocde/ram.h
index ee5ed884ef4..c163ff47e82 100644
--- a/src/devices/bus/astrocde/ram.h
+++ b/src/devices/bus/astrocde/ram.h
@@ -1,7 +1,7 @@
// license:BSD-3-Clause
// copyright-holders:Fabio Priuli
-#ifndef MAME_BUS_ASTROCADE_RAM_H
-#define MAME_BUS_ASTROCADE_RAM_H
+#ifndef MAME_BUS_ASTROCDE_RAM_H
+#define MAME_BUS_ASTROCDE_RAM_H
#pragma once
@@ -12,20 +12,20 @@
// ======================> astrocade_blueram_4k_device
-class astrocade_blueram_4k_device : public device_t, public device_astrocade_card_interface
+class astrocade_blueram_4k_device : public device_t, public device_astrocade_exp_interface
{
public:
// construction/destruction
astrocade_blueram_4k_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;
+ virtual ioport_constructor device_input_ports() const override ATTR_COLD;
// reading and writing
- virtual DECLARE_READ8_MEMBER(read) override;
- virtual DECLARE_WRITE8_MEMBER(write) override;
- virtual DECLARE_READ8_MEMBER(read_io) override;
- virtual DECLARE_WRITE8_MEMBER(write_io) override;
+ virtual uint8_t read(offs_t offset) override;
+ virtual void write(offs_t offset, uint8_t data) override;
+ virtual uint8_t read_io(offs_t offset) override;
+ virtual void write_io(offs_t offset, uint8_t data) override;
uint8_t porta_r();
uint8_t portb_r();
@@ -37,7 +37,7 @@ protected:
virtual void device_start() override { m_ram.resize(0x1000); save_item(NAME(m_ram)); }
virtual void device_reset() override { }
- virtual void device_add_mconfig(machine_config &config) override;
+ virtual void device_add_mconfig(machine_config &config) override ATTR_COLD;
std::vector<uint8_t> m_ram;
required_ioport m_write_prot;
@@ -69,18 +69,18 @@ public:
// ======================> astrocade_viper_sys1_device
-class astrocade_viper_sys1_device : public device_t, public device_astrocade_card_interface
+class astrocade_viper_sys1_device : public device_t, public device_astrocade_exp_interface
{
public:
// construction/destruction
astrocade_viper_sys1_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;
+ virtual ioport_constructor device_input_ports() const override ATTR_COLD;
// reading and writing
- virtual DECLARE_READ8_MEMBER(read) override;
- virtual DECLARE_WRITE8_MEMBER(write) override;
+ virtual uint8_t read(offs_t offset) override;
+ virtual void write(offs_t offset, uint8_t data) override;
protected:
virtual void device_start() override { m_ram.resize(0x4000); save_item(NAME(m_ram)); }
@@ -93,18 +93,18 @@ private:
// ======================> astrocade_whiteram_device
-class astrocade_whiteram_device : public device_t, public device_astrocade_card_interface
+class astrocade_whiteram_device : public device_t, public device_astrocade_exp_interface
{
public:
// construction/destruction
astrocade_whiteram_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;
+ virtual ioport_constructor device_input_ports() const override ATTR_COLD;
// reading and writing
- virtual DECLARE_READ8_MEMBER(read) override;
- virtual DECLARE_WRITE8_MEMBER(write) override;
+ virtual uint8_t read(offs_t offset) override;
+ virtual void write(offs_t offset, uint8_t data) override;
protected:
virtual void device_start() override { m_ram.resize(0x8000); save_item(NAME(m_ram)); }
@@ -117,18 +117,18 @@ private:
// ======================> astrocade_rl64ram_device
-class astrocade_rl64ram_device : public device_t, public device_astrocade_card_interface
+class astrocade_rl64ram_device : public device_t, public device_astrocade_exp_interface
{
public:
// construction/destruction
astrocade_rl64ram_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;
+ virtual ioport_constructor device_input_ports() const override ATTR_COLD;
// reading and writing
- virtual DECLARE_READ8_MEMBER(read) override;
- virtual DECLARE_WRITE8_MEMBER(write) override;
+ virtual uint8_t read(offs_t offset) override;
+ virtual void write(offs_t offset, uint8_t data) override;
protected:
virtual void device_start() override { m_ram.resize(0xb000); save_item(NAME(m_ram)); }
@@ -150,4 +150,4 @@ DECLARE_DEVICE_TYPE(ASTROCADE_WHITERAM, astrocade_whiteram_device)
DECLARE_DEVICE_TYPE(ASTROCADE_RL64RAM, astrocade_rl64ram_device)
-#endif // MAME_BUS_ASTROCADE_RAM_H
+#endif // MAME_BUS_ASTROCDE_RAM_H
diff --git a/src/devices/bus/astrocde/rom.cpp b/src/devices/bus/astrocde/rom.cpp
index bb5d6912fc2..e574c63ecd7 100644
--- a/src/devices/bus/astrocde/rom.cpp
+++ b/src/devices/bus/astrocde/rom.cpp
@@ -75,7 +75,7 @@ void astrocade_rom_512k_device::device_reset()
mapper specific handlers
-------------------------------------------------*/
-READ8_MEMBER(astrocade_rom_device::read_rom)
+uint8_t astrocade_rom_device::read_rom(offs_t offset)
{
if (offset < m_rom_size)
return m_rom[offset];
@@ -83,7 +83,7 @@ READ8_MEMBER(astrocade_rom_device::read_rom)
return 0xff;
}
-READ8_MEMBER(astrocade_rom_256k_device::read_rom)
+uint8_t astrocade_rom_256k_device::read_rom(offs_t offset)
{
if (offset < 0x1000) // 0x2000-0x2fff
return m_rom[offset + 0x1000 * 0x3f];
@@ -93,7 +93,7 @@ READ8_MEMBER(astrocade_rom_256k_device::read_rom)
return m_base_bank = offset & 0x3f;
}
-READ8_MEMBER(astrocade_rom_512k_device::read_rom)
+uint8_t astrocade_rom_512k_device::read_rom(offs_t offset)
{
if (offset < 0x1000) // 0x2000-0x2fff
return m_rom[offset + 0x1000 * 0x7f];
@@ -103,7 +103,7 @@ READ8_MEMBER(astrocade_rom_512k_device::read_rom)
return m_base_bank = offset & 0x7f;
}
-READ8_MEMBER(astrocade_rom_cass_device::read_rom)
+uint8_t astrocade_rom_cass_device::read_rom(offs_t offset)
{
if (offset < m_rom_size)
return m_rom[offset];
diff --git a/src/devices/bus/astrocde/rom.h b/src/devices/bus/astrocde/rom.h
index efd17b16ded..4e46ced63e6 100644
--- a/src/devices/bus/astrocde/rom.h
+++ b/src/devices/bus/astrocde/rom.h
@@ -1,7 +1,7 @@
// license:BSD-3-Clause
// copyright-holders:Fabio Priuli
-#ifndef MAME_BUS_ASTROCADE_ROM_H
-#define MAME_BUS_ASTROCADE_ROM_H
+#ifndef MAME_BUS_ASTROCDE_ROM_H
+#define MAME_BUS_ASTROCDE_ROM_H
#pragma once
@@ -19,7 +19,7 @@ public:
astrocade_rom_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
// reading and writing
- virtual DECLARE_READ8_MEMBER(read_rom) override;
+ virtual uint8_t read_rom(offs_t offset) override;
protected:
astrocade_rom_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock);
@@ -38,11 +38,11 @@ public:
astrocade_rom_256k_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
// reading and writing
- virtual DECLARE_READ8_MEMBER(read_rom) override;
+ virtual uint8_t read_rom(offs_t offset) override;
private:
- virtual void device_start() override;
- virtual void device_reset() override;
+ virtual void device_start() override ATTR_COLD;
+ virtual void device_reset() override ATTR_COLD;
uint8_t m_base_bank;
};
@@ -56,11 +56,11 @@ public:
astrocade_rom_512k_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
// reading and writing
- virtual DECLARE_READ8_MEMBER(read_rom) override;
+ virtual uint8_t read_rom(offs_t offset) override;
private:
- virtual void device_start() override;
- virtual void device_reset() override;
+ virtual void device_start() override ATTR_COLD;
+ virtual void device_reset() override ATTR_COLD;
uint8_t m_base_bank;
};
@@ -74,12 +74,12 @@ public:
astrocade_rom_cass_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
// reading and writing
- virtual DECLARE_READ8_MEMBER(read_rom) override;
+ virtual uint8_t read_rom(offs_t offset) override;
private:
virtual void device_start() override { }
virtual void device_reset() override { }
- virtual void device_add_mconfig(machine_config &config) override;
+ virtual void device_add_mconfig(machine_config &config) override ATTR_COLD;
required_device<cassette_image_device> m_cassette;
};
@@ -91,4 +91,4 @@ DECLARE_DEVICE_TYPE(ASTROCADE_ROM_256K, astrocade_rom_256k_device)
DECLARE_DEVICE_TYPE(ASTROCADE_ROM_512K, astrocade_rom_512k_device)
DECLARE_DEVICE_TYPE(ASTROCADE_ROM_CASS, astrocade_rom_cass_device)
-#endif // MAME_BUS_ASTROCADE_ROM_H
+#endif // MAME_BUS_ASTROCDE_ROM_H
diff --git a/src/devices/bus/astrocde/slot.cpp b/src/devices/bus/astrocde/slot.cpp
index 2aa78be98d9..3cc5ba6e8f5 100644
--- a/src/devices/bus/astrocde/slot.cpp
+++ b/src/devices/bus/astrocde/slot.cpp
@@ -7,7 +7,6 @@
***********************************************************************************************************/
-
#include "emu.h"
#include "slot.h"
@@ -25,10 +24,10 @@ DEFINE_DEVICE_TYPE(ASTROCADE_CART_SLOT, astrocade_cart_slot_device, "astrocade_c
// device_astrocade_cart_interface - constructor
//-------------------------------------------------
-device_astrocade_cart_interface::device_astrocade_cart_interface(const machine_config &mconfig, device_t &device)
- : device_slot_card_interface(mconfig, device),
- m_rom(nullptr),
- m_rom_size(0)
+device_astrocade_cart_interface::device_astrocade_cart_interface(const machine_config &mconfig, device_t &device) :
+ device_interface(device, "astrocadecart"),
+ m_rom(nullptr),
+ m_rom_size(0)
{
}
@@ -45,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;
}
}
@@ -64,8 +63,8 @@ void device_astrocade_cart_interface::rom_alloc(uint32_t size, const char *tag)
//-------------------------------------------------
astrocade_cart_slot_device::astrocade_cart_slot_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) :
device_t(mconfig, ASTROCADE_CART_SLOT, tag, owner, clock),
- device_image_interface(mconfig, *this),
- device_slot_interface(mconfig, *this),
+ device_cartrom_image_interface(mconfig, *this),
+ device_single_card_slot_interface<device_astrocade_cart_interface>(mconfig, *this),
m_type(ASTROCADE_STD), m_cart(nullptr)
{
}
@@ -85,7 +84,7 @@ astrocade_cart_slot_device::~astrocade_cart_slot_device()
void astrocade_cart_slot_device::device_start()
{
- m_cart = dynamic_cast<device_astrocade_cart_interface *>(get_card_device());
+ m_cart = get_card_device();
}
@@ -112,7 +111,7 @@ static int astrocade_get_pcb_id(const char *slot)
{
for (auto & elem : slot_list)
{
- if (!core_stricmp(elem.slot_option, slot))
+ if (!strcmp(elem.slot_option, slot))
return elem.pcb_id;
}
@@ -135,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);
@@ -164,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());
}
@@ -180,16 +177,16 @@ std::string astrocade_cart_slot_device::get_default_card_software(get_default_ca
{
if (hook.image_file())
{
- const char *slot_string;
- uint32_t size = hook.image_file()->size();
- int type = ASTROCADE_STD;
+ uint64_t size;
+ hook.image_file()->length(size); // FIXME: check error return
+ int type = ASTROCADE_STD;
if (size == 0x40000)
type = ASTROCADE_256K;
if (size == 0x80000)
type = ASTROCADE_512K;
- slot_string = astrocade_get_slot(type);
+ char const *const slot_string = astrocade_get_slot(type);
//printf("type: %s\n", slot_string);
@@ -203,10 +200,10 @@ std::string astrocade_cart_slot_device::get_default_card_software(get_default_ca
read
-------------------------------------------------*/
-READ8_MEMBER(astrocade_cart_slot_device::read_rom)
+uint8_t astrocade_cart_slot_device::read_rom(offs_t offset)
{
if (m_cart)
- return m_cart->read_rom(space, offset);
+ return m_cart->read_rom(offset);
else
return 0xff;
}
diff --git a/src/devices/bus/astrocde/slot.h b/src/devices/bus/astrocde/slot.h
index 419f4672985..a3eb711adf9 100644
--- a/src/devices/bus/astrocde/slot.h
+++ b/src/devices/bus/astrocde/slot.h
@@ -1,19 +1,17 @@
// license:BSD-3-Clause
// copyright-holders:Fabio Priuli
-#ifndef MAME_BUS_ASTROCADE_SLOT_H
-#define MAME_BUS_ASTROCADE_SLOT_H
+#ifndef MAME_BUS_ASTROCDE_SLOT_H
+#define MAME_BUS_ASTROCDE_SLOT_H
#pragma once
-#include "softlist_dev.h"
+#include "imagedev/cartrom.h"
/***************************************************************************
TYPE DEFINITIONS
***************************************************************************/
-#define ASTROCADESLOT_ROM_REGION_TAG ":cart:rom"
-
/* PCB */
enum
{
@@ -26,17 +24,17 @@ enum
// ======================> device_astrocade_cart_interface
-class device_astrocade_cart_interface : public device_slot_card_interface
+class device_astrocade_cart_interface : public device_interface
{
public:
// construction/destruction
virtual ~device_astrocade_cart_interface();
// reading and writing
- virtual DECLARE_READ8_MEMBER(read_rom) { return 0xff; }
+ 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:
@@ -51,8 +49,8 @@ protected:
// ======================> astrocade_cart_slot_device
class astrocade_cart_slot_device : public device_t,
- public device_image_interface,
- public device_slot_interface
+ public device_cartrom_image_interface,
+ public device_single_card_slot_interface<device_astrocade_cart_interface>
{
public:
// construction/destruction
@@ -68,37 +66,31 @@ 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 const software_list_loader &get_software_list_loader() const override { return rom_software_list_loader::instance(); }
-
- int get_type() { return m_type; }
- virtual iodevice_t image_type() const override { return IO_CARTSLOT; }
- virtual bool is_readable() const override { return 1; }
- virtual bool is_writeable() const override { return 0; }
- virtual bool is_creatable() const override { return 0; }
- virtual bool must_be_loaded() const override { return 0; }
- virtual bool is_reset_on_load() const override { return 1; }
- virtual const char *image_interface() const override { return "astrocde_cart"; }
- virtual const char *file_extensions() const override { return "bin"; }
+ 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; }
+
// reading and writing
- virtual DECLARE_READ8_MEMBER(read_rom);
+ uint8_t read_rom(offs_t offset);
protected:
- // device-level overrides
- virtual void device_start() override;
+ // device_t implementation
+ virtual void device_start() override ATTR_COLD;
int m_type;
- device_astrocade_cart_interface* m_cart;
+ device_astrocade_cart_interface *m_cart;
};
// device type definition
DECLARE_DEVICE_TYPE(ASTROCADE_CART_SLOT, astrocade_cart_slot_device)
-#endif // MAME_BUS_ASTROCADE_SLOT_H
+#endif // MAME_BUS_ASTROCDE_SLOT_H
diff --git a/src/devices/bus/ata/atadev.cpp b/src/devices/bus/ata/atadev.cpp
new file mode 100644
index 00000000000..2b1008eef33
--- /dev/null
+++ b/src/devices/bus/ata/atadev.cpp
@@ -0,0 +1,84 @@
+// license:BSD-3-Clause
+// copyright-holders:smf
+/***************************************************************************
+
+ ATA Device implementation.
+
+***************************************************************************/
+
+#include "emu.h"
+#include "atadev.h"
+
+#include "atapicdr.h"
+#include "cp2024.h"
+#include "cr589.h"
+#include "hdd.h"
+#include "px320a.h"
+#include "xm3301.h"
+#include "zip100.h"
+
+//-------------------------------------------------
+// device_ata_interface - constructor
+//-------------------------------------------------
+
+device_ata_interface::device_ata_interface(const machine_config &mconfig, device_t &device) :
+ device_interface(device, "ata"),
+ m_slot(dynamic_cast<ata_slot_device *>(device.owner()))
+{
+}
+
+
+//**************************************************************************
+// ATA SLOT DEVICE
+//**************************************************************************
+
+// device type definition
+DEFINE_DEVICE_TYPE(ATA_SLOT, ata_slot_device, "ata_slot", "ATA Connector")
+
+//-------------------------------------------------
+// ata_slot_device - constructor
+//-------------------------------------------------
+
+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)
+{
+}
+
+//-------------------------------------------------
+// device_config_complete - perform any
+// operations now that the configuration is
+// complete
+//-------------------------------------------------
+
+void ata_slot_device::device_config_complete()
+{
+ m_dev = get_card_device();
+}
+
+//-------------------------------------------------
+// device_start - device-specific startup
+//-------------------------------------------------
+
+void ata_slot_device::device_start()
+{
+}
+
+
+void ata_devices(device_slot_interface &device)
+{
+ device.option_add("hdd", IDE_HARDDISK);
+ device.option_add("cdrom", ATAPI_CDROM);
+
+ 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
new file mode 100644
index 00000000000..8f0ab682cde
--- /dev/null
+++ b/src/devices/bus/ata/atadev.h
@@ -0,0 +1,85 @@
+// license:BSD-3-Clause
+// copyright-holders:smf
+/***************************************************************************
+
+ atadev.h
+
+ ATA Device implementation.
+
+***************************************************************************/
+
+#ifndef MAME_BUS_ATA_ATADEV_H
+#define MAME_BUS_ATA_ATADEV_H
+
+#pragma once
+
+class device_ata_interface;
+
+
+class ata_slot_device :
+ public device_t,
+ public device_single_card_slot_interface<device_ata_interface>
+{
+public:
+ // construction/destruction
+ ata_slot_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock = 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(); }
+
+ device_ata_interface *dev() { return m_dev; }
+
+protected:
+ // device_t implementation
+ virtual void device_config_complete() override;
+ virtual void device_start() override ATTR_COLD;
+
+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;
+};
+
+
+class device_ata_interface : public device_interface
+{
+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;
+
+ 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_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:
+ ata_slot_device *const m_slot;
+};
+
+
+// device type declaration
+DECLARE_DEVICE_TYPE(ATA_SLOT, ata_slot_device)
+
+void ata_devices(device_slot_interface &device);
+
+#endif // MAME_BUS_ATA_ATADEV_H
diff --git a/src/devices/machine/ataintf.cpp b/src/devices/bus/ata/ataintf.cpp
index 5f658824c78..bd6753ee237 100644
--- a/src/devices/machine/ataintf.cpp
+++ b/src/devices/bus/ata/ataintf.cpp
@@ -11,22 +11,8 @@
#include "emu.h"
#include "ataintf.h"
-#include "atapicdr.h"
-#include "idehd.h"
-
#include "debugger.h"
-void abstract_ata_interface_device::set_default_ata_devices(const char* _master, const char* _slave)
-{
- for (size_t slot_index = 0; slot_index < SLOT_COUNT; slot_index++)
- {
- slot(slot_index).option_add("hdd", IDE_HARDDISK);
- slot(slot_index).option_add("cdrom", ATAPI_CDROM);
- }
- slot(SLOT_MASTER).set_default_option(_master);
- slot(SLOT_SLAVE).set_default_option(_slave);
-}
-
ata_slot_device &abstract_ata_interface_device::slot(int index)
{
assert(index < 2);
@@ -54,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)
{
@@ -64,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)
{
@@ -74,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)
{
@@ -84,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)
{
@@ -98,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)
{
@@ -108,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)
{
@@ -118,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)
{
@@ -211,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 );
@@ -220,12 +206,6 @@ WRITE_LINE_MEMBER( abstract_ata_interface_device::write_dmack )
elem->dev()->write_dmack(state);
}
-void ata_devices(device_slot_interface &device)
-{
- device.option_add("hdd", IDE_HARDDISK);
- device.option_add("cdrom", ATAPI_CDROM);
-}
-
abstract_ata_interface_device::abstract_ata_interface_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_slot(*this, "%u", 0U),
@@ -250,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;
@@ -261,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);
- }
}
}
@@ -291,44 +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 DEVICE
-//**************************************************************************
-
-// device type definition
-DEFINE_DEVICE_TYPE(ATA_SLOT, ata_slot_device, "ata_slot", "ATA Connector")
-
-//-------------------------------------------------
-// ata_slot_device - constructor
-//-------------------------------------------------
-
-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_slot_interface(mconfig, *this),
- m_dev(nullptr)
-{
-}
-
-//-------------------------------------------------
-// device_config_complete - perform any
-// operations now that the configuration is
-// complete
-//-------------------------------------------------
-
-void ata_slot_device::device_config_complete()
-{
- m_dev = dynamic_cast<device_ata_interface *>(get_card_device());
-}
-
-//-------------------------------------------------
-// device_start - device-specific startup
-//-------------------------------------------------
-
-void ata_slot_device::device_start()
-{
+ 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/machine/ataintf.h b/src/devices/bus/ata/ataintf.h
index 974645a24cb..691835fd267 100644
--- a/src/devices/machine/ataintf.h
+++ b/src/devices/bus/ata/ataintf.h
@@ -8,8 +8,8 @@
***************************************************************************/
-#ifndef MAME_MACHINE_ATAINTF_H
-#define MAME_MACHINE_ATAINTF_H
+#ifndef MAME_BUS_ATA_ATAINTF_H
+#define MAME_BUS_ATA_ATAINTF_H
#pragma once
@@ -19,35 +19,6 @@
TYPE DEFINITIONS
***************************************************************************/
-// ======================> ata_slot_device
-
-class ata_slot_device : public device_t,
- public device_slot_interface
-{
-public:
- // construction/destruction
- ata_slot_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock = 0);
-
- device_ata_interface *dev() { return m_dev; }
-
-protected:
- // device-level overrides
- virtual void device_start() override;
- virtual void device_config_complete() override;
-
-private:
- device_ata_interface *m_dev;
-};
-
-// device type definition
-DECLARE_DEVICE_TYPE(ATA_SLOT, ata_slot_device)
-
-void ata_devices(device_slot_interface &device);
-
-/***************************************************************************
- TYPE DEFINITIONS
-***************************************************************************/
-
/* ----- device interface ----- */
class abstract_ata_interface_device : public device_t
@@ -85,11 +56,10 @@ public:
}
ata_slot_device &slot(int index);
- virtual void set_default_ata_devices(const char* _master, const char* _slave);
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);
@@ -100,8 +70,8 @@ protected:
void internal_write_cs1(offs_t offset, uint16_t data, uint16_t mem_mask = 0xffff);
// device-level overrides
- virtual void device_start() override;
- virtual void device_add_mconfig(machine_config &config) override;
+ virtual void device_start() override ATTR_COLD;
+ virtual void device_add_mconfig(machine_config &config) override ATTR_COLD;
virtual void set_irq(int state);
virtual void set_dmarq(int state);
@@ -116,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];
@@ -163,17 +133,17 @@ public:
return *this;
}
- uint16_t read_cs0(offs_t offset, uint16_t mem_mask = 0xffff) { return internal_read_cs0(offset, mem_mask); }
- uint16_t read_cs1(offs_t offset, uint16_t mem_mask = 0xffff) { return internal_read_cs1(offset, mem_mask); }
- void write_cs0(offs_t offset, uint16_t data, uint16_t mem_mask = 0xffff) { internal_write_cs0(offset, data, mem_mask); }
- void write_cs1(offs_t offset, uint16_t data, uint16_t mem_mask = 0xffff) { internal_write_cs1(offset, data, mem_mask); }
+ uint16_t cs0_r(offs_t offset, uint16_t mem_mask = 0xffff) { return internal_read_cs0(offset, mem_mask); }
+ 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); }
- DECLARE_READ16_MEMBER(cs0_r) { return read_cs0(offset, mem_mask); }
- DECLARE_READ16_MEMBER(cs1_r) { return read_cs1(offset, mem_mask); }
- DECLARE_WRITE16_MEMBER(cs0_w) { write_cs0(offset, data, mem_mask); }
- DECLARE_WRITE16_MEMBER(cs1_w) { 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)
-#endif // MAME_MACHINE_ATAINTF_H
+#endif // MAME_BUS_ATA_ATAINTF_H
diff --git a/src/devices/bus/ata/atapicdr.cpp b/src/devices/bus/ata/atapicdr.cpp
new file mode 100644
index 00000000000..ec6dbcd5e59
--- /dev/null
+++ b/src/devices/bus/ata/atapicdr.cpp
@@ -0,0 +1,191 @@
+// license:BSD-3-Clause
+// 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_DVDROM, atapi_dvdrom_device, "dvdrom", "ATAPI 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)
+{
+}
+
+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),
+ device_ata_interface(mconfig, *this),
+ m_ultra_dma_mode(0)
+{
+}
+
+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)
+{
+}
+
+//-------------------------------------------------
+// device_add_mconfig - add device configuration
+//-------------------------------------------------
+
+void atapi_cdrom_device::device_add_mconfig(machine_config &config)
+{
+ if(type() == ATAPI_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()
+{
+ m_image = subdevice<cdrom_image_device>("image");
+ m_cdda = subdevice<cdda_device>("cdda");
+
+ 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] = m_ultra_dma_mode;
+
+ atapi_hle_device::device_start();
+}
+
+void atapi_cdrom_device::set_ultra_dma_mode(uint16_t 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_dvdrom_device::device_reset()
+{
+ atapi_hle_device::device_reset();
+ m_media_change = true;
+ m_sequence_counter = m_image->sequence_counter();
+}
+
+void atapi_cdrom_device::process_buffer()
+{
+ if( m_sequence_counter != m_image->sequence_counter() )
+ {
+ m_media_change = true;
+ m_sequence_counter = m_image->sequence_counter();
+ }
+ atapi_hle_device::process_buffer();
+}
+
+void atapi_cdrom_device::perform_diagnostic()
+{
+ m_error = IDE_ERROR_DIAGNOSTIC_PASSED;
+}
+
+void atapi_cdrom_device::identify_packet_device()
+{
+}
+
+void atapi_cdrom_device::ExecCommand()
+{
+ switch(command[0])
+ {
+ case T10SBC_CMD_READ_CAPACITY:
+ case T10SBC_CMD_READ_10:
+ case T10MMC_CMD_READ_SUB_CHANNEL:
+ case T10MMC_CMD_READ_TOC_PMA_ATIP:
+ case T10MMC_CMD_PLAY_AUDIO_10:
+ 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:
+ case T10SBC_CMD_SEEK_10:
+ if(!m_image->exists())
+ {
+ m_phase = SCSI_PHASE_STATUS;
+ m_sense_key = SCSI_SENSE_KEY_MEDIUM_ERROR;
+ m_sense_asc = SCSI_SENSE_ASC_MEDIUM_NOT_PRESENT;
+ m_status_code = SCSI_STATUS_CODE_CHECK_CONDITION;
+ m_transfer_length = 0;
+ return;
+ }
+ [[fallthrough]];
+ default:
+ if(m_media_change)
+ {
+ m_phase = SCSI_PHASE_STATUS;
+ m_sense_key = SCSI_SENSE_KEY_UNIT_ATTENTION;
+ m_sense_asc = SCSI_SENSE_ASC_NOT_READY_TO_READY_TRANSITION;
+ m_status_code = SCSI_STATUS_CODE_CHECK_CONDITION;
+ m_transfer_length = 0;
+
+ if (command[0] == T10SPC_CMD_TEST_UNIT_READY || // amiga(idefix97)/firebeat/namcos12/sprinter
+ command[0] == T10SPC_CMD_MODE_SENSE_10) // stingnet
+ m_media_change = false;
+ return;
+ }
+ break;
+ case T10SPC_CMD_INQUIRY:
+ m_media_change = false; // mtouchxl(mitsumi)
+ break;
+ case T10SPC_CMD_REQUEST_SENSE:
+ m_media_change = false;
+ break;
+ }
+ t10mmc::ExecCommand();
+
+ if (m_status_code == SCSI_STATUS_CODE_GOOD)
+ {
+ switch (command[0])
+ {
+ // Set the DSC (Drive Seek Complete) bit on commands that involve a drive seek.
+ // truckk is known to rely on this flag being set after T10SBC_CMD_SEEK_10.
+ case T10SBC_CMD_SEEK_10:
+ case T10MMC_CMD_PLAY_AUDIO_10:
+ case T10MMC_CMD_PLAY_AUDIO_12:
+ case T10MMC_CMD_PLAY_AUDIO_MSF:
+ case T10MMC_CMD_PLAY_AUDIO_TRACK_INDEX:
+ m_status |= IDE_STATUS_DSC;
+ break;
+ }
+ }
+}
diff --git a/src/devices/bus/ata/atapicdr.h b/src/devices/bus/ata/atapicdr.h
new file mode 100644
index 00000000000..00d17a350b5
--- /dev/null
+++ b/src/devices/bus/ata/atapicdr.h
@@ -0,0 +1,82 @@
+// license:BSD-3-Clause
+// copyright-holders:smf
+/***************************************************************************
+
+ atapicdr.h
+
+ ATAPI CDROM/DVDROM
+
+***************************************************************************/
+
+#ifndef MAME_BUS_ATA_ATAPICDR_H
+#define MAME_BUS_ATA_ATAPICDR_H
+
+#pragma once
+
+#include "atadev.h"
+#include "atapihle.h"
+
+#include "machine/t10mmc.h"
+
+
+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);
+
+ void set_ultra_dma_mode(uint16_t mode);
+
+ 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);
+
+ // device-level overrides
+ 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;
+
+ virtual void perform_diagnostic() override;
+ 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 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_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 ATTR_COLD;
+};
+
+// device type definition
+DECLARE_DEVICE_TYPE(ATAPI_CDROM, atapi_cdrom_device)
+DECLARE_DEVICE_TYPE(ATAPI_DVDROM, atapi_dvdrom_device)
+
+#endif // MAME_BUS_ATA_ATAPICDR_H
diff --git a/src/devices/machine/atapihle.cpp b/src/devices/bus/ata/atapihle.cpp
index 8bbc779ea23..0e327b8022b 100644
--- a/src/devices/machine/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()
@@ -38,7 +47,10 @@ void atapi_hle_device::process_buffer()
GetLength(&m_data_size);
if (m_status_code == SCSI_STATUS_CODE_CHECK_CONDITION)
+ {
m_status |= IDE_STATUS_ERR;
+ m_error |= (m_sense_key << 4);
+ }
m_buffer_size = (m_cylinder_high << 8) | m_cylinder_low;
if (m_buffer_size == 0xffff)
@@ -51,7 +63,8 @@ void atapi_hle_device::process_buffer()
if (m_feature & ATAPI_FEATURES_FLAG_OVL)
{
- printf( "ATAPI_FEATURES_FLAG_OVL not supported\n" );
+ // TODO: DC GD-ROM
+ logerror( "ATAPI_FEATURES_FLAG_OVL not supported\n" );
}
switch (m_phase)
@@ -96,7 +109,8 @@ void atapi_hle_device::fill_buffer()
case IDE_COMMAND_PACKET:
if (m_buffer_size >= m_data_size)
{
- m_buffer_size = m_data_size;
+ // MSCDEX/SHSUCDX PC drivers wants the clamp for CD audio playback (29 bytes).
+ m_buffer_size = m_data_size & 0xfffe;
}
else
{
@@ -226,8 +240,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;
@@ -256,7 +270,7 @@ void atapi_hle_device::process_command()
break;
default:
- ata_hle_device::process_command();
+ ata_hle_device_base::process_command();
break;
}
}
@@ -266,7 +280,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/machine/atapihle.h b/src/devices/bus/ata/atapihle.h
index d01447e5830..b0d7bbfc629 100644
--- a/src/devices/machine/atapihle.h
+++ b/src/devices/bus/ata/atapihle.h
@@ -8,15 +8,15 @@
***************************************************************************/
-#ifndef MAME_MACHINE_ATAPIHLE_H
-#define MAME_MACHINE_ATAPIHLE_H
+#ifndef MAME_BUS_ATA_ATAPIHLE_H
+#define MAME_BUS_ATA_ATAPIHLE_H
#pragma once
-#include "atahle.h"
-#include "t10spc.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,16 +46,18 @@ 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);
- virtual void device_start() override;
- virtual void device_reset() override;
+ virtual void device_start() override ATTR_COLD;
+ virtual void device_reset() override ATTR_COLD;
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,8 +72,9 @@ private:
int m_packet;
int m_data_size;
+ bool m_is_ready;
static constexpr int ATAPI_BUFFER_LENGTH = 0xf800;
};
-#endif // MAME_MACHINE_ATAPIHLE_H
+#endif // MAME_BUS_ATA_ATAPIHLE_H
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..dc33d3648bf
--- /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 ATTR_COLD;
+ virtual void device_add_mconfig(machine_config &config) override ATTR_COLD;
+ virtual const tiny_rom_entry *device_rom_region() const override ATTR_COLD;
+
+ 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) ATTR_COLD;
+};
+
+DECLARE_DEVICE_TYPE(CP2024, cp2024_device)
+
+#endif // MAME_BUS_ATA_CP2024_H
diff --git a/src/devices/machine/cr589.cpp b/src/devices/bus/ata/cr589.cpp
index 6142f75ee7a..15309f6e41e 100644
--- a/src/devices/machine/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);
}
@@ -25,9 +27,10 @@ void matsushita_cr589_device::nvram_default()
// .nv file
//-------------------------------------------------
-void matsushita_cr589_device::nvram_read(emu_file &file)
+bool matsushita_cr589_device::nvram_read(util::read_stream &file)
{
- file.read(buffer, sizeof(buffer));
+ auto const [err, actual] = read(file, buffer, sizeof(buffer));
+ return !err && (actual == sizeof(buffer));
}
@@ -37,36 +40,37 @@ void matsushita_cr589_device::nvram_read(emu_file &file)
// .nv file
//-------------------------------------------------
-void matsushita_cr589_device::nvram_write(emu_file &file)
+bool matsushita_cr589_device::nvram_write(util::write_stream &file)
{
- file.write(buffer, 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
@@ -83,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);
@@ -92,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;
@@ -113,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;
}
@@ -157,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/machine/cr589.h b/src/devices/bus/ata/cr589.h
index 8d94d5739b9..91a98bd1c23 100644
--- a/src/devices/machine/cr589.h
+++ b/src/devices/bus/ata/cr589.h
@@ -8,8 +8,8 @@
***************************************************************************/
-#ifndef MAME_MACHINE_CR589_H
-#define MAME_MACHINE_CR589_H
+#ifndef MAME_BUS_ATA_CR589_H
+#define MAME_BUS_ATA_CR589_H
#pragma once
@@ -29,21 +29,21 @@ public:
protected:
// device-level overrides
- virtual void device_start() override;
- virtual void device_reset() override;
+ virtual void device_start() override ATTR_COLD;
+ virtual void device_reset() override ATTR_COLD;
// device_nvram_interface overrides
virtual void nvram_default() override;
- virtual void nvram_read(emu_file &file) override;
- virtual void nvram_write(emu_file &file) override;
+ virtual bool nvram_read(util::read_stream &file) override;
+ virtual bool nvram_write(util::write_stream &file) override;
private:
int download;
- uint8_t buffer[ 65536 ];
+ uint8_t buffer[65536];
int bufferOffset;
};
// device type definition
DECLARE_DEVICE_TYPE(CR589, matsushita_cr589_device)
-#endif // MAME_MACHINE_CR589_H
+#endif // MAME_BUS_ATA_CR589_H
diff --git a/src/devices/bus/ata/gdrom.cpp b/src/devices/bus/ata/gdrom.cpp
new file mode 100644
index 00000000000..57ec03ba5c8
--- /dev/null
+++ b/src/devices/bus/ata/gdrom.cpp
@@ -0,0 +1,901 @@
+// license:BSD-3-Clause
+// copyright-holders:smf, Angelo Salese
+/***************************************************************************
+
+ gdrom.c - Implementation of the Sega GD-ROM device
+
+***************************************************************************/
+
+#include "emu.h"
+#include "gdrom.h"
+#include "coreutil.h"
+
+#include <iostream>
+
+#define LOG_WARN (1U << 1)
+#define LOG_CMD (1U << 2)
+#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_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
+#define GDROM_STANDBY_STATE 0x02
+#define GDROM_PLAY_STATE 0x03
+#define GDROM_SEEK_STATE 0x04
+#define GDROM_SCAN_STATE 0x05
+#define GDROM_OPEN_STATE 0x06
+#define GDROM_NODISC_STATE 0x07
+#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:
+
+ SYS_CHK_SECU (70h) Media security check
+ Parameters: 1byte - R0011111, R - "recheck" (it seems actual security check performed automatically at drive power on or when disc was inserted, so normally this and next command returns result of already performed check.
+ however, when MSB R bit is 1 will be forced media security recheck)
+ Result: none
+ SYS_REQ_SECU (71h) Request security data
+ Parameters: 1byte - always 0x1f
+ Result: a bit less than 1Kbyte chunk of data (length vary each time), contains real command reply obfuscated, which is extracted by such code:
+
+ u8 reply[], real_reply[];
+ for (u32 i = 0, offset = 0; i < length; i++)
+ {
+ offset++;
+ u32 skip = reply[offset] - 2; // normally skip value is < 0x10, might be used to identify real reply length
+ offset += skip;
+ real_reply[i] = reply[offset++];
+ }
+
+ Real reply is 43 byte:
+ struct sec_reply {
+ u8 check_result; // 0x1f - valid GD-ROM, 0x10 - valid Mil-CD (in this case following char[] fields is empty, 0x00-filled)
+ char key_id[10]; // presumable Disc ID (T-xxxxxx or HDR-xxxxx etc)
+ char key_maker_id[16]; // presumable "SEGA ENTERPRISES"
+ char hard_id[16]; // presumable "SEGA SEGAKATANA "
+ };
+
+ *_id fields names came from Dev.box "Checker BIOS" disassembly, contents meaning is guesswork because all the reply dumps we have now was dumped with Mil-CD disc inserted but not GD-ROM.
+ Presumable these data somehow encoded in GD-ROM disc HD area Lead-in (or Security Ring area ?), and compared with data in LD area IP.BIN by GD-drive firmware,
+ as described in Sega patent EP0935242A1 https://patents.google.com/patent/EP0935242A1
+
+ Dreamcast BIOS code verify only 1st result byte, if it's 5th bit (0x10) == 1.
+ Naomi DIMM firmware verify if result byte equal to 0x1f.
+
+ SYS_CHG_COMD (72h) ??? Authentication for next command ?
+ Parameters: 1byte, probably key/password, in retail Dreamcast - 5th byte of unit SN# (located in flash ROM at 1A05Ah), 0 in Dev.box checker BIOS.
+ Result: none
+
+ SYS_REQ_COMD (73h) Request command list
+ Parameters: none
+ Result: chunk of data where obfuscated real reply, see command 71.
+ real result: 14 bytes - codes of all regular (not security) packet commands supported by drive (00 10 11 12 13 14 15 16 20 21 22 30 31 40).
+
+ Dreamcast BIOS SysCalls contain commands 0x72/73 routine, but it seems not used at practice.
+*/
+
+static const uint8_t GDROM_Cmd71_Reply[] =
+{
+ 0x96, 0x0B, 0x45, 0xF0, 0x7E, 0xFF, 0x3D, 0x06, 0x4D, 0x7D, 0x10, 0xBF, 0x07, 0x00, 0x73, 0xCF,
+ 0x9C, 0x00, 0xBC, 0x0C, 0x1C, 0xAF, 0x1C, 0x30, 0xE7, 0xA7, 0x03, 0xA8, 0x98, 0x00, 0xBD, 0x0F,
+ 0xBD, 0x5B, 0xAA, 0x50, 0x23, 0x39, 0x31, 0x10, 0x0E, 0x69, 0x13, 0xE5, 0x00, 0xD2, 0x0D, 0x66,
+ 0x54, 0xBF, 0x5F, 0xFD, 0x37, 0x74, 0xF4, 0x5B, 0x22, 0x00, 0xC6, 0x09, 0x0F, 0xCA, 0x93, 0xE8,
+ 0xA4, 0xAB, 0x00, 0x61, 0x0E, 0x2E, 0xE1, 0x4B, 0x76, 0x8B, 0x6A, 0xA5, 0x9C, 0xE6, 0x23, 0xC4,
+ 0x00, 0x4B, 0x06, 0x1B, 0x91, 0x01, 0x00, 0xE2, 0x0D, 0xCF, 0xCA, 0x38, 0x3A, 0xB9, 0xE7, 0x91,
+ 0xE5, 0xEF, 0x4B, 0x00, 0xD6, 0x09, 0xD3, 0x68, 0x3E, 0xC4, 0xAF, 0x2D, 0x00, 0x2A, 0x0D, 0xF9,
+ 0xFC, 0x78, 0xED, 0xAE, 0x99, 0xB3, 0x32, 0x5A, 0xE7, 0x00, 0x4C, 0x0A, 0x22, 0x97, 0x5B, 0x82,
+ 0x06, 0x7A, 0x4C, 0x00, 0x42, 0x0E, 0x57, 0x78, 0x46, 0xF5, 0x20, 0xFC, 0x6B, 0xCB, 0x01, 0x5B,
+ 0x86, 0x00, 0xE4, 0x0E, 0xB2, 0x26, 0xCD, 0x71, 0xE3, 0xA5, 0x33, 0x06, 0x8E, 0x9A, 0x50, 0x00,
+ 0x07, 0x07, 0xF5, 0x34, 0xEF, 0xE6, 0x00, 0x32, 0x0F, 0x13, 0x41, 0x59, 0x56, 0x0F, 0x02, 0x38,
+ 0x2A, 0x64, 0x2A, 0x07, 0x3E, 0x00, 0x52, 0x11, 0x2A, 0x1D, 0x5F, 0x76, 0x66, 0xA0, 0xB2, 0x2F,
+ 0x97, 0xC7, 0x5E, 0x6E, 0x52, 0xE2, 0x00, 0x58, 0x09, 0xCA, 0x89, 0xA5, 0xDF, 0x0A, 0xDE, 0x00,
+ 0x50, 0x06, 0x49, 0xB8, 0xB4, 0x00, 0x77, 0x05, 0x24, 0xE8, 0x00, 0xBB, 0x0C, 0x91, 0x89, 0xA2,
+ 0x8B, 0x62, 0xDE, 0x6A, 0xC6, 0x60, 0x00, 0xE7, 0x0F, 0x0F, 0x11, 0x96, 0x55, 0xD2, 0xBF, 0xE6,
+ 0x48, 0x0B, 0x5C, 0xAB, 0xDC, 0x00, 0xBA, 0x0A, 0x30, 0xD7, 0x48, 0x0E, 0x78, 0x63, 0x0C, 0x00,
+ 0xD2, 0x0D, 0xFB, 0x8A, 0xA3, 0xFE, 0xF8, 0x3A, 0xDD, 0x88, 0xA9, 0x4B, 0x00, 0xA2, 0x0A, 0x75,
+ 0x5D, 0x0D, 0x37, 0x24, 0xC5, 0x9D, 0x00, 0xF7, 0x0B, 0x25, 0xEF, 0xDB, 0x41, 0xE0, 0x52, 0x3E,
+ 0x4E, 0x00, 0xB7, 0x03, 0x00, 0xE5, 0x11, 0xB9, 0xDE, 0x5A, 0x57, 0xCF, 0xB9, 0x1A, 0xFC, 0x7F,
+ 0x26, 0xEE, 0x7B, 0xCD, 0x2B, 0x00, 0x4B, 0x08, 0xB8, 0x09, 0x70, 0x6A, 0x9F, 0x00, 0x4B, 0x11,
+ 0x8C, 0x15, 0x87, 0xA3, 0x05, 0x4F, 0x37, 0x8E, 0x63, 0xDE, 0xEF, 0x39, 0xFC, 0x4B, 0x00, 0xAB,
+ 0x10, 0x0B, 0x91, 0xAA, 0x0F, 0xE1, 0xE9, 0xAE, 0x69, 0x3A, 0xF8, 0x03, 0x69, 0xD2, 0x00, 0xE2,
+ 0x07, 0xC1, 0x5C, 0x3D, 0x82, 0x00, 0xA9, 0x08, 0x68, 0xC4, 0xAD, 0x2E, 0xD1, 0x00, 0xF7, 0x0E,
+ 0xC6, 0x47, 0xC8, 0xCD, 0x8E, 0x7C, 0x00, 0x5C, 0x95, 0xB9, 0xF4, 0x00, 0xE3, 0x04, 0x5B, 0x00,
+ 0x74, 0x07, 0x65, 0xC7, 0x84, 0x8E, 0x00, 0xC6, 0x07, 0x61, 0x80, 0x44, 0x3F, 0x00, 0xC8, 0x0E,
+ 0x72, 0x78, 0x47, 0xD3, 0xC2, 0x4D, 0xAF, 0xC0, 0x54, 0x13, 0x31, 0x00, 0xF7, 0x0D, 0x48, 0xD8,
+ 0xE2, 0x92, 0x9F, 0x7F, 0x2F, 0x44, 0x68, 0x33, 0x00, 0x0D, 0x10, 0xAB, 0xFE, 0xEA, 0x8E, 0x19,
+ 0x81, 0xF8, 0x6F, 0x7C, 0xDE, 0xE1, 0xB3, 0x06, 0x00, 0x4D, 0x11, 0x66, 0xAE, 0x4C, 0xF9, 0xB7,
+ 0x2F, 0xEE, 0xB0, 0x8E, 0x7E, 0xE1, 0x8D, 0x95, 0x6F, 0x00, 0xF4, 0x0D, 0x88, 0x9D, 0xCA, 0xE3,
+ 0xC4, 0xB2, 0x47, 0xBB, 0xA0, 0x69, 0x00, 0xF3, 0x0B, 0x48, 0x17, 0x41, 0x64, 0xA0, 0x0E, 0x71,
+ 0x82, 0x00, 0x34, 0x1E, 0x18, 0x4D, 0x85, 0x80, 0x4C, 0xA9, 0x0B, 0x66, 0x9B, 0x75, 0x13, 0x61,
+ 0x70, 0x27, 0x81, 0x7A, 0x02, 0xCD, 0x57, 0xAB, 0xDF, 0x02, 0x93, 0x52, 0x83, 0xDF, 0x48, 0xA8,
+ 0xA6, 0x9E, 0x74, 0x6F, 0x89, 0x03, 0x28, 0x25, 0x52, 0x96, 0xFF, 0x67, 0x7A, 0xD8, 0x3C, 0xB1,
+ 0x2C, 0x46, 0x84, 0xEF, 0xE1, 0xC1, 0xC6, 0xC9, 0xDC, 0x96, 0xAA, 0xA9, 0xC4, 0x82, 0x58, 0x27,
+ 0x57, 0x75, 0x67, 0x34, 0xFB, 0x3B, 0x25, 0xBF, 0xFB, 0x3B, 0xF6, 0x13, 0xEC, 0x96, 0xE5, 0x16,
+ 0x26, 0xFD, 0xA8, 0xDA, 0x1B, 0xC6, 0x50, 0x7F, 0x47, 0xFF, 0x08, 0x55, 0x08, 0xED, 0x00, 0x93,
+ 0x9B, 0xC4, 0x71, 0x67, 0xEC, 0xA6, 0xCC, 0x16, 0x20, 0x87, 0x47, 0x07, 0xA6, 0x00, 0x79, 0x5D,
+ 0x4F, 0xAB, 0xA1, 0x6F, 0x7A, 0x6B, 0x27, 0xC4, 0xDA, 0xA3, 0xC3, 0x94, 0x4F, 0x7F, 0xF3, 0xE5,
+ 0x1B, 0x6F, 0xCC, 0xE5, 0xF0, 0xE5, 0x9D, 0xC9, 0xAE, 0xFD, 0x39, 0xAC, 0x4C, 0xE5, 0x58, 0x83,
+ 0x25, 0x65, 0x92, 0x74, 0x9E, 0x81, 0xA0, 0xB6, 0xA9, 0x02, 0x9B, 0x07, 0xB6, 0xE7, 0x79, 0x57,
+ 0xD9, 0x4A, 0xCE, 0xFA, 0xB4, 0x94, 0x05, 0xCC, 0x86, 0x3C, 0xDD, 0x06, 0xCD, 0xA6, 0x24, 0x24,
+ 0xFA, 0xC1, 0xF9, 0x48, 0xC9, 0x0C, 0x6C, 0xC4, 0x96, 0x82, 0x17, 0xF6, 0x31, 0x09, 0xC4, 0xE2,
+ 0x77, 0xFD, 0xCF, 0x46, 0x18, 0xB2, 0x5F, 0x01, 0x6B, 0xD1, 0x7B, 0x56, 0xB8, 0x94, 0x4A, 0xE5,
+ 0x6C, 0x19, 0xF0, 0xC0, 0xB6, 0x70, 0x93, 0xF7, 0xD3, 0xD1, 0x2B, 0x6E, 0x7C, 0x53, 0x6D, 0x85,
+ 0xD1, 0x0C, 0x8B, 0x77, 0xEE, 0x90, 0xDA, 0x15, 0x55, 0xE0, 0x58, 0x09, 0x56, 0xFC, 0x31, 0x9F,
+ 0xAF, 0x46, 0xCB, 0xC3, 0x8D, 0x71, 0x75, 0xF2, 0x2C, 0xC3, 0xBB, 0xA1, 0xC4, 0xCF, 0x27, 0x56,
+ 0x7C, 0x9B, 0xFE, 0xAF, 0x3E, 0x4E, 0xB4, 0xCD, 0x6A, 0xAA, 0xF5, 0xF3, 0xE3, 0x22, 0x82, 0xE1,
+ 0xA5, 0x68, 0xB3, 0xDB, 0x8F, 0x9E, 0x5E, 0x7B, 0x90, 0xF0, 0x79, 0x3F, 0x52, 0x8C, 0x61, 0x88,
+ 0x76, 0xAE, 0x14, 0x63, 0x19, 0x0F, 0x1D, 0xCE, 0xA1, 0x63, 0x10, 0xB2, 0xE2, 0xD7, 0x94, 0xB1,
+ 0x33, 0xCB, 0x28, 0x85, 0x7D, 0x9B, 0xF5, 0xF4, 0x25, 0x50, 0x9B, 0xDB, 0x35, 0xA5, 0xB0, 0x9C,
+ 0x09, 0x92, 0xE3, 0x31, 0x40, 0xAB, 0x4D, 0xF4, 0x35, 0xE8, 0xB3, 0x0A, 0x21, 0xC3, 0x86, 0x9C,
+ 0xCB, 0x29, 0xA4, 0x77, 0x57, 0xBC, 0xD8, 0xDA, 0xA5, 0x82, 0x80, 0xE8, 0xCF, 0x72, 0x81, 0xAD,
+ 0x2E, 0x28, 0xFF, 0xD8, 0xB6, 0xD1, 0x2B, 0x97, 0x00, 0xFF, 0xE1, 0x06, 0x44, 0x39, 0x1C, 0x4B,
+ 0xAB, 0x19, 0x5B, 0x4D, 0xD6, 0x3E, 0x1B, 0x5C, 0x64, 0xBB, 0x32, 0x68, 0xF5, 0x7C, 0xC9, 0x9E,
+ 0xE8, 0xB4, 0x29, 0x1B, 0x7F, 0x4D, 0x80, 0x80, 0x7E, 0x8B, 0x1C, 0x0A, 0xE6, 0x9A, 0xBF, 0x49,
+ 0x1E, 0xC5, 0xB6, 0x67, 0x7D, 0x05, 0xE4, 0x90, 0x40, 0x4B, 0xAF, 0x9B, 0x52, 0xDE, 0x17, 0x80,
+ 0x81, 0x56, 0xEA, 0x3A, 0x53, 0x82, 0x8C, 0x62, 0xFB, 0x96, 0x97, 0x6F, 0xC1, 0x16, 0x78, 0xD4,
+ 0x7B, 0xE7, 0xB9, 0x5A, 0x2A, 0xEB, 0x87, 0x68, 0x33, 0xD3, 0x31, 0x45, 0xFA, 0xFE, 0xF4, 0x1C,
+ 0x90, 0x86, 0x73, 0x77, 0xD9, 0xA9, 0xD1, 0x4A, 0x4A, 0xCF, 0xAE, 0x23, 0xDB, 0xF9, 0x09, 0xD8,
+ 0x18, 0xDC, 0x6A, 0x0D, 0xE4, 0x19, 0x8C, 0x65, 0xC6, 0x64, 0xC7, 0xDC, 0xA9, 0xE3, 0x91, 0xB1,
+ 0x4C, 0xC8, 0xC1, 0x9E, 0x3B, 0x7F, 0xCB, 0xA3, 0xCF, 0xDD, 0xF0, 0x1D, 0x07, 0x6E, 0xDC, 0xCE,
+ 0x0D, 0xCD, 0x7E, 0x1E, 0x55, 0x11, 0x8B, 0xDF, 0x3A, 0xAB, 0xB6, 0x3B, 0x6E, 0x52, 0x7F, 0xA7,
+ 0x00, 0xD1, 0x33, 0xBE, 0xF2, 0x9B, 0xFC, 0x4A, 0xCF, 0x9D, 0x8F, 0xC6, 0xC4, 0x7B, 0xDA, 0xE7,
+ 0x2A, 0x1C, 0x26, 0x6E
+};
+
+
+void gdrom_device::device_reset()
+{
+ static const uint8_t GDROM_Def_Cmd11_Reply[32] =
+ {
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0xB4, 0x19, 0x00, 0x00, 0x08, 0x53, 0x45, 0x20, 0x20, 0x20, 0x20,
+ 0x20, 0x20, 0x52, 0x65, 0x76, 0x20, 0x36, 0x2E, 0x34, 0x32, 0x39, 0x39, 0x30, 0x33, 0x31, 0x36
+ };
+
+ for(int i = 0;i<32;i++)
+ GDROM_Cmd11_Reply[i] = GDROM_Def_Cmd11_Reply[i];
+
+ atapi_cdrom_device::device_reset();
+}
+
+// scsicd_exec_command
+//
+// Execute a SCSI command.
+
+void gdrom_device::ExecCommand()
+{
+ LOGCMDRAW("%02x\n", command[0]);
+ switch ( command[0] )
+ {
+ 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;
+ 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] );
+ 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] );
+ 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)
+ {
+ m_transfer_length = 0;
+ throw emu_fatalerror("GDROM: MSF mode used for CD_READ, unsupported");
+ }
+ else
+ {
+ m_lba = (command[2]<<16 | command[3]<<8 | command[4]) - 150;
+ m_blocks = command[8]<<16 | command[9]<<8 | command[10];
+
+ read_type = (command[1] >> 1) & 7;
+ data_select = (command[1] >> 4) & 0xf;
+ //m_status |= IDE_STATUS_DSC;
+
+ // 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);
+ }
+
+ if (data_select != 2) // just sector data
+ {
+ throw emu_fatalerror("GDROM: Unhandled data_select %d", data_select);
+ }
+
+ // 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
+ );
+
+ if (m_num_subblocks > 1)
+ {
+ m_cur_subblock = m_lba % m_num_subblocks;
+ m_lba /= m_num_subblocks;
+ }
+ else
+ {
+ m_cur_subblock = 0;
+ }
+
+ 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;
+ m_status_code = SCSI_STATUS_CODE_GOOD;
+ m_transfer_length = m_blocks * m_sector_bytes;
+ }
+ break;
+
+ case 0x40:
+ {
+ m_transfer_length = SCSILengthFromUINT8( &command[4] );
+ //LOGCMD("CD_SCD 40h %02x %d\n", command[1] & 0xf, m_transfer_length);
+
+ switch(command[1] & 0xf)
+ {
+ 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;
+ }
+ break;
+ }
+
+ // 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;
+ break;
+
+ case 0x71:
+ m_phase = SCSI_PHASE_DATAIN;
+ m_status_code = SCSI_STATUS_CODE_GOOD;
+ m_transfer_length = sizeof(GDROM_Cmd71_Reply);
+ 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:
+ throw emu_fatalerror("GDROM: unhandled command %02x", command[0]);
+ }
+}
+
+// scsicd_read_data
+//
+// Read data from the device resulting from the execution of a command
+
+void gdrom_device::ReadData( uint8_t *data, int dataLength )
+{
+ int i;
+ uint8_t tmp_buffer[2048];
+
+ 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);
+ 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
+ LOGXFER("CD_READ read %x dataLength,\n", dataLength);
+ if ((m_image->exists()) && (m_blocks))
+ {
+ while (dataLength > 0)
+ {
+ 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);
+
+ memcpy(data, &tmp_buffer[m_cur_subblock * m_sector_bytes], m_sector_bytes);
+
+ m_cur_subblock++;
+ if (m_cur_subblock >= m_num_subblocks)
+ {
+ m_cur_subblock = 0;
+
+ m_lba++;
+ m_blocks--;
+ }
+
+ m_last_lba = m_lba;
+ dataLength -= m_sector_bytes;
+ data += m_sector_bytes;
+ }
+ }
+ break;
+
+ case 0x40: // Get Subchannel status
+ switch (command[2] & 0x0f)
+ {
+ case 0: // Subcode P-W
+ {
+ 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]))
+ {
+ // 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)
+ {
+ 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]
+ );
+ }
+
+ for (int i = 0; i < m_transfer_length - 4; i++)
+ data[i + 4] = BIT(subqbuf[i >> 3], 7 - (i & 7)) ? 0x40 : 0x00;
+ }
+
+ break;
+ }
+ 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;
+
+ case 0x71:
+ LOGCMD("SYS_REQ_SECU\n");
+ memcpy(data, &GDROM_Cmd71_Reply[0], sizeof(GDROM_Cmd71_Reply));
+ if (m_image->is_gd())
+ data[10] = 0x1f; // needed by dimm board firmware
+ break;
+
+ default:
+ t10mmc::ReadData( data, dataLength );
+ break;
+ }
+}
+
+// scsicd_write_data
+//
+// Write data to the CD-ROM device as part of the execution of a command
+
+void gdrom_device::WriteData( uint8_t *data, int dataLength )
+{
+ 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:
+ t10mmc::WriteData( data, dataLength );
+ break;
+ }
+}
+
+// device type definition
+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, ATAPI_GDROM, tag, owner, clock)
+{
+}
+
+void gdrom_device::device_start()
+{
+ save_item(NAME(read_type));
+ save_item(NAME(data_select));
+ save_item(NAME(transferOffset));
+
+ /// 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.
+ atapi_cdrom_device::device_start();
+
+ memset(m_identify_buffer, 0, sizeof(m_identify_buffer));
+
+ m_identify_buffer[0] = 0x8600; // ATAPI device, cmd set 6 compliant, DRQ within 3 ms of PACKET command
+
+ // 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
+
+ m_identify_buffer[63]=7; // multi word dma mode 0-2 supported
+ m_identify_buffer[64]=1; // PIO mode 3 supported
+}
+
+void gdrom_device::process_buffer()
+{
+ atapi_hle_device::process_buffer();
+ // HACK: find out when this should be updated
+ // 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();
+
+ // 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;
+
+ // naomi dimm board firmware needs the upper nibble to be 8 at the beginning
+ 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
new file mode 100644
index 00000000000..412a27d2e4a
--- /dev/null
+++ b/src/devices/bus/ata/gdrom.h
@@ -0,0 +1,59 @@
+// license:BSD-3-Clause
+// copyright-holders:smf, Angelo Salese
+/***************************************************************************
+
+ gdrom.h
+
+***************************************************************************/
+
+#ifndef MAME_BUS_ATA_GDROM_H
+#define MAME_BUS_ATA_GDROM_H
+
+#pragma once
+
+#include "atapicdr.h"
+
+class gdrom_device : public atapi_cdrom_device
+{
+public:
+ gdrom_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
+
+ // Sega GD-ROM handler
+
+ 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;
+
+ // device-level overrides
+ virtual void device_start() override ATTR_COLD;
+ virtual void device_reset() override ATTR_COLD;
+// 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]{};
+ uint32_t read_type = 0; // for command 0x30 only
+ uint32_t data_select = 0; // for command 0x30 only
+ uint32_t transferOffset = 0;
+
+ 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(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..c728fef6c7a
--- /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_HDD_H
+#define MAME_BUS_ATA_HDD_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_HDD_H
diff --git a/src/devices/bus/ata/px320a.cpp b/src/devices/bus/ata/px320a.cpp
new file mode 100644
index 00000000000..b7414df264a
--- /dev/null
+++ b/src/devices/bus/ata/px320a.cpp
@@ -0,0 +1,99 @@
+// license:BSD-3-Clause
+// copyright-holders:AJR
+/*******************************************************************************
+
+ Skeleton device for Plextor PleXCombo PX-320A IDE DVD/CD-RW drive.
+
+*******************************************************************************/
+
+#include "emu.h"
+#include "px320a.h"
+#include "cpu/fr/fr.h"
+
+DEFINE_DEVICE_TYPE(PX320A, px320a_device, "px320a", "PleXCombo PX-320A CD-RW/DVD-ROM Drive")
+
+px320a_device::px320a_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock)
+ : device_t(mconfig, PX320A, tag, owner, clock)
+ , device_ata_interface(mconfig, *this)
+ , m_frcpu(*this, "frcpu")
+{
+}
+
+void px320a_device::device_start()
+{
+}
+
+
+u16 px320a_device::read_dma()
+{
+ return 0;
+}
+
+u16 px320a_device::read_cs0(offs_t offset, u16 mem_mask)
+{
+ return 0;
+}
+
+u16 px320a_device::read_cs1(offs_t offset, u16 mem_mask)
+{
+ return 0;
+}
+
+void px320a_device::write_dma(u16 data)
+{
+}
+
+void px320a_device::write_cs0(offs_t offset, u16 data, u16 mem_mask)
+{
+}
+
+void px320a_device::write_cs1(offs_t offset, u16 data, u16 mem_mask)
+{
+}
+
+void px320a_device::write_dmack(int state)
+{
+}
+
+void px320a_device::write_csel(int state)
+{
+}
+
+void px320a_device::write_dasp(int state)
+{
+}
+
+void px320a_device::write_pdiag(int state)
+{
+}
+
+
+void px320a_device::frcpu_map(address_map &map)
+{
+ map(0x00080000, 0x000fffff).rom().region("firmware", 0);
+}
+
+void px320a_device::device_add_mconfig(machine_config &config)
+{
+ MB91F155A(config, m_frcpu, 16'000'000); // FR type guessed; clock unknown
+ m_frcpu->set_addrmap(AS_PROGRAM, &px320a_device::frcpu_map);
+}
+
+ROM_START(px320a)
+ ROM_REGION32_BE(0x80000, "firmware", 0)
+ ROM_SYSTEM_BIOS(0, "v106", "Firmware v1.06")
+ ROM_LOAD("sapp106.bin", 0x00000, 0x80000, CRC(2ba54c7a) SHA1(032cc5009fe84db902096ea2bb9dc2221601ab20))
+ ROM_SYSTEM_BIOS(1, "v105", "Firmware v1.05")
+ ROM_LOAD("sapp105.bin", 0x00000, 0x80000, CRC(3755a053) SHA1(fb966d506edb6e0a97ad64de3898ce9e75e22d7d))
+ ROM_SYSTEM_BIOS(2, "v104", "Firmware v1.04a")
+ ROM_LOAD("sapp104.bin", 0x00000, 0x80000, CRC(7197425f) SHA1(0b02508d668439a78ea8e3d97eddf5a3de6e2ba5))
+ ROM_SYSTEM_BIOS(3, "v103", "Firmware v1.03")
+ ROM_LOAD("sap1032.bin", 0x00000, 0x80000, CRC(9ff1c729) SHA1(6ed44bf8decaac2ee9127bdd66e0ff1fd52969c3))
+ ROM_SYSTEM_BIOS(4, "v102", "Firmware v1.02")
+ ROM_LOAD("sapp102.bin", 0x00000, 0x80000, CRC(9f96bea4) SHA1(5b70f32e83d8c19d2895d38d0f7e15f2eee326fd))
+ROM_END
+
+const tiny_rom_entry *px320a_device::device_rom_region() const
+{
+ return ROM_NAME(px320a);
+}
diff --git a/src/devices/bus/ata/px320a.h b/src/devices/bus/ata/px320a.h
new file mode 100644
index 00000000000..110bc1c0e6f
--- /dev/null
+++ b/src/devices/bus/ata/px320a.h
@@ -0,0 +1,42 @@
+// license:BSD-3-Clause
+// copyright-holders:AJR
+
+#ifndef MAME_BUS_ATA_PX320A_H
+#define MAME_BUS_ATA_PX320A_H
+
+#pragma once
+
+#include "atadev.h"
+
+class px320a_device : public device_t, public device_ata_interface
+{
+public:
+ px320a_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 ATTR_COLD;
+ virtual void device_add_mconfig(machine_config &config) override ATTR_COLD;
+ virtual const tiny_rom_entry *device_rom_region() const override ATTR_COLD;
+
+ 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 frcpu_map(address_map &map) ATTR_COLD;
+
+ required_device<cpu_device> m_frcpu;
+};
+
+DECLARE_DEVICE_TYPE(PX320A, px320a_device)
+
+#endif // MAME_BUS_ATA_PX320A_H
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..cd0610d5629
--- /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 ATTR_COLD;
+ virtual void device_reset() override ATTR_COLD;
+
+ 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..ca60dca4123
--- /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 ATTR_COLD;
+ virtual void device_add_mconfig(machine_config &config) override ATTR_COLD;
+ virtual const tiny_rom_entry *device_rom_region() const override ATTR_COLD;
+
+ 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) ATTR_COLD;
+ void ext_map(address_map &map) ATTR_COLD;
+};
+
+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 6b23371d580..502952bc185 100644
--- a/src/devices/bus/bbc/1mhzbus/1mhzbus.cpp
+++ b/src/devices/bus/bbc/1mhzbus/1mhzbus.cpp
@@ -27,9 +27,9 @@ DEFINE_DEVICE_TYPE(BBC_1MHZBUS_SLOT, bbc_1mhzbus_slot_device, "bbc_1mhzbus_slot"
//-------------------------------------------------
device_bbc_1mhzbus_interface::device_bbc_1mhzbus_interface(const machine_config &mconfig, device_t &device)
- : device_slot_card_interface(mconfig, 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());
}
@@ -43,7 +43,7 @@ device_bbc_1mhzbus_interface::device_bbc_1mhzbus_interface(const machine_config
bbc_1mhzbus_slot_device::bbc_1mhzbus_slot_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) :
device_t(mconfig, BBC_1MHZBUS_SLOT, tag, owner, clock),
- device_slot_interface(mconfig, *this),
+ device_single_card_slot_interface<device_bbc_1mhzbus_interface>(mconfig, *this),
m_card(nullptr),
m_irq_handler(*this),
m_nmi_handler(*this)
@@ -52,43 +52,16 @@ bbc_1mhzbus_slot_device::bbc_1mhzbus_slot_device(const machine_config &mconfig,
//-------------------------------------------------
-// device_validity_check -
-//-------------------------------------------------
-
-void bbc_1mhzbus_slot_device::device_validity_check(validity_checker &valid) const
-{
- device_t *const carddev = get_card_device();
- if (carddev && !dynamic_cast<device_bbc_1mhzbus_interface *>(carddev))
- osd_printf_error("Card device %s (%s) does not implement device_bbc_1mhzbus_interface\n", carddev->tag(), carddev->name());
-}
-
-
-//-------------------------------------------------
// device_start - device-specific startup
//-------------------------------------------------
void bbc_1mhzbus_slot_device::device_start()
{
- device_t *const carddev = get_card_device();
- m_card = dynamic_cast<device_bbc_1mhzbus_interface *>(carddev);
- if (carddev && !m_card)
- fatalerror("Card device %s (%s) does not implement device_bbc_1mhzbus_interface\n", carddev->tag(), carddev->name());
-
- // resolve callbacks
- m_irq_handler.resolve_safe();
- m_nmi_handler.resolve_safe();
+ m_card = get_card_device();
}
//-------------------------------------------------
-// device_reset - device-specific reset
-//-------------------------------------------------
-
-void bbc_1mhzbus_slot_device::device_reset()
-{
-}
-
-//-------------------------------------------------
// read
//-------------------------------------------------
@@ -130,19 +103,30 @@ 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"
//#include "teletext.h"
+#include "datacentre.h"
//#include "digitiser.h"
#include "emrmidi.h"
+#include "ide.h"
#include "ieee488.h"
#include "m2000.h"
-//#include "m5000.h"
-//#include "scsi.h"
-//#include "multiform.h"
+#include "m5000.h"
+#include "sasi.h"
+#include "scsi.h"
+#include "multiform.h"
#include "opus3.h"
-//#include "ramdisc.h"
+#include "pdram.h"
+#include "pms64k.h"
+#include "ramdisc.h"
//#include "graduate.h"
+#include "beebopl.h"
#include "beebsid.h"
//#include "prisma3.h"
#include "sprite.h"
@@ -153,45 +137,70 @@ void bbc_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("m500", BBC_M500); /* Acorn ANV02 Music 500 */
- //device.option_add("awdd", BBC_AWDD); /* Acorn Winchester 110/130 */
+ 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("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("twdd", BBC_TWDD); /* Technomatic Winchester (Akhter Host Adaptor + ABD4070 */
- //device.option_add("multiform", BBC_MULTIFORM); /* Technomatic Multiform Z80 */
+ device.option_add("m2000", BBC_M2000); /* Hybrid Music 2000 Interface */
+ device.option_add("m3000", BBC_M3000); /* Hybrid Music 3000 Expander */
+ device.option_add("m5000", BBC_M5000); /* Hybrid Music 5000 Synthesiser */
+ device.option_add("m87", BBC_M87); /* Peartree Music 87 Synthesiser */
+ device.option_add("multiform", BBC_MULTIFORM); /* PEDL Multiform Z80 */
device.option_add("opus3", BBC_OPUS3); /* Opus Challenger 3 */
- //device.option_add("ramdisc", BBC_RAMDISC); /* Morley Electronics RAM Disc */
- //device.option_add("graduate", BBC_GRADUATE); /* The Torch Graduate G400/G800 */
+ device.option_add("pdram", BBC_PDRAM); /* Micro User Pull Down RAM */
+ device.option_add("pms64k", BBC_PMS64K); /* PMS 64K Non-Volatile Ram Module */
+ device.option_add("ramdisc", BBC_RAMDISC); /* Morley Electronics RAM Disc */
+ device.option_add("torchhd", BBC_TORCHHD); /* Torch Hard Disc Pack */
+ device.option_add("dc", BBC_DATACENTRE); /* RetroClinic DataCentre */
+ //device.option_add("graduate", BBC_GRADUATE); /* Torch Graduate G400/G800 */
+ device.option_add("beebopl", BBC_BEEBOPL); /* BeebOPL */
device.option_add("beebsid", BBC_BEEBSID); /* BeebSID */
+ device.option_add("cc500", BBC_CC500); /* CTS Colour Card 500 */
//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)
{
//device.option_add("teletext", BBC_TELETEXT); /* Acorn ANE01 Teletext Adapter */
device.option_add("ieee488", BBC_IEEE488); /* Acorn ANK01 IEEE488 Interface */
- //device.option_add("m500", BBC_M500); /* Acorn ANV02 Music 500 */
- //device.option_add("awdd", BBC_AWDD); /* Acorn Winchester 110/130 */
+ 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("twdd", BBC_TWDD); /* Technomatic Winchester (Akhter Host Adaptor + ABD4070 */
device.option_add("m2000", BBC_M2000); /* Hybrid Music 2000 Interface */
- //device.option_add("m3000", BBC_M3000); /* Hybrid Music 3000 Expander */
- //device.option_add("m5000", BBC_M5000); /* Hybrid Music 5000 Synthesiser */
- //device.option_add("m87", BBC_M87); /* Peartree Music 87 Synthesiser */
- //device.option_add("multiform", BBC_MULTIFORM); /* Technomatic Multiform Z80 */
+ device.option_add("m3000", BBC_M3000); /* Hybrid Music 3000 Expander */
+ device.option_add("m5000", BBC_M5000); /* Hybrid Music 5000 Synthesiser */
+ device.option_add("m87", BBC_M87); /* Peartree Music 87 Synthesiser */
+ device.option_add("multiform", BBC_MULTIFORM); /* PEDL Multiform Z80 */
device.option_add("opusa", BBC_OPUSA); /* Opus Challenger ADFS */
- //device.option_add("ramdisc", BBC_RAMDISC); /* Morley Electronics RAM Disc */
- //device.option_add("graduate", BBC_GRADUATE); /* The Torch Graduate G400/G800 */
+ device.option_add("pdram", BBC_PDRAM); /* Micro User Pull Down RAM */
+ device.option_add("pms64k", BBC_PMS64K); /* PMS 64K Non-Volatile Ram Module */
+ device.option_add("ramdisc", BBC_RAMDISC); /* Morley Electronics RAM Disc */
+ device.option_add("torchhd", BBC_TORCHHD); /* Torch Hard Disc Pack */
+ device.option_add("dc", BBC_DATACENTRE); /* RetroClinic DataCentre */
+ //device.option_add("graduate", BBC_GRADUATE); /* Torch Graduate G400/G800 */
+ device.option_add("beebopl", BBC_BEEBOPL); /* BeebOPL */
device.option_add("beebsid", BBC_BEEBSID); /* BeebSID */
+ device.option_add("cc500", BBC_CC500); /* CTS Colour Card 500 */
//device.option_add("prisma3", BBC_PRISMA3); /* PRISMA-3 - Millipede 1989 */
device.option_add("sprite", BBC_SPRITE); /* Logotron Sprite Board */
- device.option_add("cfa3000opt", CFA3000_OPT); /* Henson CFA 3000 Option Board */
+ device.option_add_internal("cfa3000opt", CFA3000_OPT);/* Henson CFA 3000 Option Board */
}
diff --git a/src/devices/bus/bbc/1mhzbus/1mhzbus.h b/src/devices/bus/bbc/1mhzbus/1mhzbus.h
index 80e48425973..aa0fafda75c 100644
--- a/src/devices/bus/bbc/1mhzbus/1mhzbus.h
+++ b/src/devices/bus/bbc/1mhzbus/1mhzbus.h
@@ -87,7 +87,7 @@
class device_bbc_1mhzbus_interface;
-class bbc_1mhzbus_slot_device : public device_t, public device_slot_interface
+class bbc_1mhzbus_slot_device : public device_t, public device_single_card_slot_interface<device_bbc_1mhzbus_interface>
{
public:
// construction/destruction
@@ -112,14 +112,12 @@ 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
- virtual void device_validity_check(validity_checker &valid) const override;
- virtual void device_start() override;
- virtual void device_reset() override;
+ // device_t overrides
+ virtual void device_start() override ATTR_COLD;
device_bbc_1mhzbus_interface *m_card;
@@ -131,7 +129,7 @@ private:
// ======================> device_bbc_1mhzbus_interface
-class device_bbc_1mhzbus_interface : public device_slot_card_interface
+class device_bbc_1mhzbus_interface : public device_interface
{
public:
virtual uint8_t fred_r(offs_t offset) { return 0xff; }
@@ -142,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..4a1b4817bdf
--- /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 ATTR_COLD;
+
+ // optional information overrides
+ virtual void device_add_mconfig(machine_config &config) override ATTR_COLD;
+ 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..044f2ec074c
--- /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 ATTR_COLD;
+
+ // optional information overrides
+ virtual void device_add_mconfig(machine_config &config) override ATTR_COLD;
+ virtual const tiny_rom_entry* device_rom_region() const override;
+ virtual ioport_constructor device_input_ports() const override ATTR_COLD;
+
+ 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/autoprom.h b/src/devices/bus/bbc/1mhzbus/autoprom.h
index 358b5819f2b..3f3379cf431 100644
--- a/src/devices/bus/bbc/1mhzbus/autoprom.h
+++ b/src/devices/bus/bbc/1mhzbus/autoprom.h
@@ -27,13 +27,13 @@ public:
protected:
// device-level overrides
- virtual void device_start() override;
- virtual void device_reset() override;
+ virtual void device_start() override ATTR_COLD;
+ virtual void device_reset() override ATTR_COLD;
// 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 void device_add_mconfig(machine_config &config) override ATTR_COLD;
+ virtual const tiny_rom_entry *device_rom_region() const override ATTR_COLD;
+ virtual ioport_constructor device_input_ports() const override ATTR_COLD;
virtual uint8_t fred_r(offs_t offset) override;
virtual void fred_w(offs_t offset, uint8_t data) override;
diff --git a/src/devices/bus/bbc/1mhzbus/barrybox.cpp b/src/devices/bus/bbc/1mhzbus/barrybox.cpp
new file mode 100644
index 00000000000..bd47e6060e0
--- /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 ATTR_COLD;
+
+ // optional information overrides
+ virtual void device_add_mconfig(machine_config &config) override ATTR_COLD;
+
+ 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/beebopl.cpp b/src/devices/bus/bbc/1mhzbus/beebopl.cpp
new file mode 100644
index 00000000000..9c3db9ca6ff
--- /dev/null
+++ b/src/devices/bus/bbc/1mhzbus/beebopl.cpp
@@ -0,0 +1,95 @@
+// license:BSD-3-Clause
+// copyright-holders:Nigel Barnes
+/**********************************************************************
+
+ BeebOPL FM Synthesiser emulation
+
+ https://github.com/JudgeBeeb/BeebOPL
+
+**********************************************************************/
+
+
+#include "emu.h"
+#include "beebopl.h"
+#include "speaker.h"
+
+
+//**************************************************************************
+// DEVICE DEFINITIONS
+//**************************************************************************
+
+DEFINE_DEVICE_TYPE(BBC_BEEBOPL, bbc_beebopl_device, "beebopl", "BeebOPL FM Synthesiser")
+
+
+//-------------------------------------------------
+// device_add_mconfig - add device configuration
+//-------------------------------------------------
+
+void bbc_beebopl_device::device_add_mconfig(machine_config &config)
+{
+ SPEAKER(config, "speaker").front_center();
+
+ YM3812(config, m_ym3812, 3.579_MHz_XTAL);
+ m_ym3812->irq_handler().set(DEVICE_SELF_OWNER, FUNC(bbc_1mhzbus_slot_device::irq_w));
+ m_ym3812->add_route(ALL_OUTPUTS, "speaker", 1.0);
+
+ 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));
+}
+
+
+//**************************************************************************
+// LIVE DEVICE
+//**************************************************************************
+
+//-------------------------------------------------
+// bbc_beebopl_device - constructor
+//-------------------------------------------------
+
+bbc_beebopl_device::bbc_beebopl_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
+ : device_t(mconfig, BBC_BEEBOPL, tag, owner, clock)
+ , device_bbc_1mhzbus_interface(mconfig, *this)
+ , m_1mhzbus(*this, "1mhzbus")
+ , m_ym3812(*this, "ym3812")
+{
+}
+
+
+//**************************************************************************
+// IMPLEMENTATION
+//**************************************************************************
+
+uint8_t bbc_beebopl_device::fred_r(offs_t offset)
+{
+ uint8_t data = 0xff;
+
+ if ((offset & 0xfe) == 0x04)
+ {
+ data = m_ym3812->read(offset);
+ }
+
+ data &= m_1mhzbus->fred_r(offset);
+
+ return data;
+}
+
+void bbc_beebopl_device::fred_w(offs_t offset, uint8_t data)
+{
+ if ((offset & 0xfe) == 0x04)
+ {
+ m_ym3812->write(offset, data);
+ }
+
+ m_1mhzbus->fred_w(offset, data);
+}
+
+uint8_t bbc_beebopl_device::jim_r(offs_t offset)
+{
+ return m_1mhzbus->jim_r(offset);
+}
+
+void bbc_beebopl_device::jim_w(offs_t offset, uint8_t data)
+{
+ m_1mhzbus->jim_w(offset, data);
+}
diff --git a/src/devices/bus/bbc/1mhzbus/beebopl.h b/src/devices/bus/bbc/1mhzbus/beebopl.h
new file mode 100644
index 00000000000..c15face6561
--- /dev/null
+++ b/src/devices/bus/bbc/1mhzbus/beebopl.h
@@ -0,0 +1,52 @@
+// license:BSD-3-Clause
+// copyright-holders:Nigel Barnes
+/**********************************************************************
+
+ BeebOPL FM Synthesiser emulation
+
+**********************************************************************/
+
+#ifndef MAME_BUS_BBC_1MHZBUS_BEEBOPL_H
+#define MAME_BUS_BBC_1MHZBUS_BEEBOPL_H
+
+#include "1mhzbus.h"
+#include "sound/ymopl.h"
+
+
+//**************************************************************************
+// TYPE DEFINITIONS
+//**************************************************************************
+
+// ======================> bbc_beebopl_device
+
+class bbc_beebopl_device :
+ public device_t,
+ public device_bbc_1mhzbus_interface
+{
+public:
+ // construction/destruction
+ bbc_beebopl_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 ATTR_COLD;
+
+ 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;
+ required_device<ym3812_device> m_ym3812;
+};
+
+
+// device type definition
+DECLARE_DEVICE_TYPE(BBC_BEEBOPL, bbc_beebopl_device)
+
+
+#endif // MAME_BUS_BBC_1MHZBUS_BEEBOPL_H
diff --git a/src/devices/bus/bbc/1mhzbus/beebsid.h b/src/devices/bus/bbc/1mhzbus/beebsid.h
index 107e875abde..adfa0d072e3 100644
--- a/src/devices/bus/bbc/1mhzbus/beebsid.h
+++ b/src/devices/bus/bbc/1mhzbus/beebsid.h
@@ -29,10 +29,10 @@ public:
protected:
// device-level overrides
- virtual void device_start() override;
+ virtual void device_start() override ATTR_COLD;
// optional information overrides
- virtual void device_add_mconfig(machine_config &config) override;
+ virtual void device_add_mconfig(machine_config &config) override ATTR_COLD;
virtual uint8_t fred_r(offs_t offset) override;
virtual void fred_w(offs_t offset, uint8_t data) override;
diff --git a/src/devices/bus/bbc/1mhzbus/cc500.cpp b/src/devices/bus/bbc/1mhzbus/cc500.cpp
new file mode 100644
index 00000000000..6da7a1b995c
--- /dev/null
+++ b/src/devices/bus/bbc/1mhzbus/cc500.cpp
@@ -0,0 +1,178 @@
+// license:BSD-3-Clause
+// copyright-holders:Nigel Barnes
+/**********************************************************************
+
+ Colour Card 500 - CTS Recognition
+
+ The CTS Palette is a 1 MHz bus device and it can be used to convert the 8
+ colours available on the BBC into any 8 colours from a range of 4096.
+
+ Programming the hardware directly
+ ---------------------------------
+ The hardware consists of 3 banks of very fast RAM (for red, green and blue
+ levels) and a 6522 versatile interface adaptor.
+
+ The memory map is as follows:
+
+ 6522 VIA &FC90 to &FC9F
+
+ RED BANK &FCA0 to &FCA7
+ GREEN BANK &FCA8 to &FCAF
+ BLUE BANK &FCB0 to &FCB8
+
+ There are 8 bytes in each bank, one for each actual colour. The physical
+ colour for logical colour L is stored at &FCA0+L, &FCA8+L and &FCB0+L.
+
+ For example, to reprogram actual colour 1 to brown, 10 would be stored in
+ &FCA1, 6 in &FCA9 and 0 in &FCB1.
+
+ Port A of the 6522 VIA is available for use as an extra 'user port', and
+ Port B is used internally.
+
+ Note : Line (Horizontal) sync pulses are available on PB6
+ Field (Vertical) sync pulses are available on CB1
+
+**********************************************************************/
+
+
+#include "emu.h"
+#include "cc500.h"
+
+#include <algorithm>
+
+
+//**************************************************************************
+// DEVICE DEFINITIONS
+//**************************************************************************
+
+DEFINE_DEVICE_TYPE(BBC_CC500, bbc_cc500_device, "bbc_cc500", "CTS Colour Card 500")
+
+
+//-------------------------------------------------
+// ROM( cc500 )
+//-------------------------------------------------
+
+ROM_START(cc500)
+ ROM_REGION(0x4000, "exp_rom", 0)
+ ROM_LOAD("cts_palette_1.10.rom", 0x0000, 0x2000, CRC(93533144) SHA1(e645afdc5c7574a487ff484b79ea21a3b476f847))
+ROM_END
+
+//-------------------------------------------------
+// device_add_mconfig - add device configuration
+//-------------------------------------------------
+
+void bbc_cc500_device::device_add_mconfig(machine_config &config)
+{
+ MOS6522(config, m_via, DERIVED_CLOCK(1, 1));
+ m_via->readpa_handler().set(m_userport, FUNC(bbc_userport_slot_device::pb_r));
+ m_via->writepa_handler().set(m_userport, FUNC(bbc_userport_slot_device::pb_w));
+ m_via->irq_handler().set(DEVICE_SELF_OWNER, FUNC(bbc_1mhzbus_slot_device::irq_w));
+
+ BBC_USERPORT_SLOT(config, m_userport, bbc_userport_devices, nullptr);
+ m_userport->cb1_handler().set(m_via, FUNC(via6522_device::write_ca1));
+ m_userport->cb2_handler().set(m_via, FUNC(via6522_device::write_ca2));
+
+ 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_cc500_device::device_rom_region() const
+{
+ return ROM_NAME(cc500);
+}
+
+
+//**************************************************************************
+// LIVE DEVICE
+//**************************************************************************
+
+//-------------------------------------------------
+// bbc_cc500_device - constructor
+//-------------------------------------------------
+
+bbc_cc500_device::bbc_cc500_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
+ : device_t(mconfig, BBC_CC500, tag, owner, clock)
+ , device_bbc_1mhzbus_interface(mconfig, *this)
+ , m_palette(*this, ":palette")
+ , m_1mhzbus(*this, "1mhzbus")
+ , m_via(*this, "via")
+ , m_userport(*this, "userport")
+{
+}
+
+
+//-------------------------------------------------
+// device_start - device-specific startup
+//-------------------------------------------------
+
+void bbc_cc500_device::device_start()
+{
+ std::fill(std::begin(m_palette_ram), std::end(m_palette_ram), rgb_t(0));
+
+ // register for save states
+ save_item(NAME(m_palette_ram));
+}
+
+
+//**************************************************************************
+// IMPLEMENTATION
+//**************************************************************************
+
+uint8_t bbc_cc500_device::fred_r(offs_t offset)
+{
+ uint8_t data = 0xff;
+
+ switch (offset & 0xf0)
+ {
+ case 0x90:
+ data = m_via->read(offset & 0x0f);
+ break;
+ }
+
+ data &= m_1mhzbus->fred_r(offset);
+
+ return data;
+}
+
+void bbc_cc500_device::fred_w(offs_t offset, uint8_t data)
+{
+ switch (offset & 0xf0)
+ {
+ case 0x90:
+ m_via->write(offset & 0x0f, data);
+ break;
+
+ case 0xa0: case 0xb0:
+ switch (offset & 0x18)
+ {
+ case 0x00:
+ m_palette_ram[~offset & 0x07].set_r(pal4bit(data));
+ break;
+ case 0x08:
+ m_palette_ram[~offset & 0x07].set_g(pal4bit(data));
+ break;
+ case 0x10:
+ m_palette_ram[~offset & 0x07].set_b(pal4bit(data));
+ break;
+ }
+ m_palette->set_pen_colors(0, &m_palette_ram[0], 8);
+ break;
+ }
+
+ m_1mhzbus->fred_w(offset, data);
+}
+
+uint8_t bbc_cc500_device::jim_r(offs_t offset)
+{
+ return m_1mhzbus->jim_r(offset);
+}
+
+void bbc_cc500_device::jim_w(offs_t offset, uint8_t data)
+{
+ m_1mhzbus->jim_w(offset, data);
+}
diff --git a/src/devices/bus/bbc/1mhzbus/cc500.h b/src/devices/bus/bbc/1mhzbus/cc500.h
new file mode 100644
index 00000000000..29c748818e0
--- /dev/null
+++ b/src/devices/bus/bbc/1mhzbus/cc500.h
@@ -0,0 +1,59 @@
+// license:BSD-3-Clause
+// copyright-holders:Nigel Barnes
+/**********************************************************************
+
+ Colour Card 500 - CTS Recognition
+
+**********************************************************************/
+
+#ifndef MAME_BUS_BBC_1MHZBUS_CC500_H
+#define MAME_BUS_BBC_1MHZBUS_CC500_H
+
+#include "1mhzbus.h"
+#include "machine/6522via.h"
+#include "bus/bbc/userport/userport.h"
+#include "emupal.h"
+
+
+//**************************************************************************
+// TYPE DEFINITIONS
+//**************************************************************************
+
+// ======================> bbc_cc500_device
+
+class bbc_cc500_device :
+ public device_t,
+ public device_bbc_1mhzbus_interface
+{
+public:
+ // construction/destruction
+ bbc_cc500_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
+
+protected:
+ // device-level overrides
+ virtual void device_start() override ATTR_COLD;
+
+ // optional information overrides
+ virtual void device_add_mconfig(machine_config &config) override ATTR_COLD;
+ 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<palette_device> m_palette;
+ required_device<bbc_1mhzbus_slot_device> m_1mhzbus;
+ required_device<via6522_device> m_via;
+ required_device<bbc_userport_slot_device> m_userport;
+
+ rgb_t m_palette_ram[8];
+};
+
+
+// device type definition
+DECLARE_DEVICE_TYPE(BBC_CC500, bbc_cc500_device)
+
+
+#endif // MAME_BUS_BBC_1MHZBUS_CC500_H
diff --git a/src/devices/bus/bbc/1mhzbus/cfa3000opt.h b/src/devices/bus/bbc/1mhzbus/cfa3000opt.h
index 64913e95604..2acfcc87662 100644
--- a/src/devices/bus/bbc/1mhzbus/cfa3000opt.h
+++ b/src/devices/bus/bbc/1mhzbus/cfa3000opt.h
@@ -30,10 +30,10 @@ public:
protected:
// device-level overrides
- virtual void device_start() override;
+ virtual void device_start() override ATTR_COLD;
// optional information overrides
- virtual ioport_constructor device_input_ports() const override;
+ virtual ioport_constructor device_input_ports() const override ATTR_COLD;
virtual uint8_t fred_r(offs_t offset) override;
diff --git a/src/devices/bus/bbc/1mhzbus/cisco.cpp b/src/devices/bus/bbc/1mhzbus/cisco.cpp
new file mode 100644
index 00000000000..e12efa906d2
--- /dev/null
+++ b/src/devices/bus/bbc/1mhzbus/cisco.cpp
@@ -0,0 +1,267 @@
+// license:BSD-3-Clause
+// copyright-holders:Nigel Barnes
+/**********************************************************************
+
+ Cisco Terminal
+
+ This appears to be an information booth found in exhibitions and tourist
+ information sites. No information or photos of the actual hardware are
+ known. This romset was provided by the family of ex-Cisco developer
+ F.Verrelli.
+
+ This hardware is completely unknown, this device is derived from what the
+ software requires to run.
+
+ Notes:
+ - ROM containing frame data, 1K per page. This set has 64K but the system
+ could handle much more.
+ - RAM used for storing messages, maybe 32K but could be less, and is likely
+ battery-backed.
+ - RTC is unknown, and doesn't seem to match any of those currently emulated.
+ - Configuration data is unknown so has been derived, maybe stored in the RTC
+ device? It determines the mapping of ROM/RAM with their lo/hi addresses.
+ - A keyboard would be attached to the userport to limit the keys available
+ to the user. This is not emulated as we don't know which keys to include.
+
+ Special keys:
+ @ - word search
+ CTRL-C - customized frame, requires password ...
+
+
+**********************************************************************/
+
+
+#include "emu.h"
+#include "cisco.h"
+
+
+//**************************************************************************
+// DEVICE DEFINITIONS
+//**************************************************************************
+
+DEFINE_DEVICE_TYPE(BBC_CISCO, bbc_cisco_device, "bbc_cisco", "Cisco Terminal Data Board");
+
+
+//-------------------------------------------------
+// ROM( cisco )
+//-------------------------------------------------
+
+ROM_START(cisco)
+ ROM_REGION(0x10000, "rom", 0)
+ ROM_SYSTEM_BIOS(0, "confex", "Confex '88")
+ ROMX_LOAD("101.bin", 0x0000, 0x4000, CRC(36b42ed2) SHA1(bbbcef59e12da4cddc7a5cebf4c8597b0e76fbac), ROM_BIOS(0))
+ ROMX_LOAD("102.bin", 0x4000, 0x4000, CRC(e323e6b1) SHA1(d3344a964c0a37b4dfbdd0d01c8f16a1b796197b), ROM_BIOS(0))
+ ROMX_LOAD("103.bin", 0x8000, 0x4000, CRC(f8faaf74) SHA1(b11edeaa9eefd75bcfcb5e39bab01b74b7dbc45f), ROM_BIOS(0))
+ ROMX_LOAD("104.bin", 0xc000, 0x4000, CRC(c66ae87c) SHA1(500339258bd5cad363709c774c0cee36a17986cb), ROM_BIOS(0))
+ROM_END
+
+//-------------------------------------------------
+// rom_region - device-specific ROM region
+//-------------------------------------------------
+
+const tiny_rom_entry *bbc_cisco_device::device_rom_region() const
+{
+ return ROM_NAME(cisco);
+}
+
+
+//-------------------------------------------------
+// device_add_mconfig - add device configuration
+//-------------------------------------------------
+
+void bbc_cisco_device::device_add_mconfig(machine_config &config)
+{
+ // unknown RTC device
+}
+
+
+//**************************************************************************
+// LIVE DEVICE
+//**************************************************************************
+
+//-------------------------------------------------
+// bbc_cisco_device - constructor
+//-------------------------------------------------
+
+bbc_cisco_device::bbc_cisco_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
+ : device_t(mconfig, BBC_CISCO, tag, owner, clock)
+ , device_bbc_1mhzbus_interface(mconfig, *this)
+ , device_rtc_interface(mconfig , *this)
+ , m_rom(*this, "rom")
+ , m_rom_page(0)
+ , m_rtc_minute(0)
+ , m_rtc_hour(0)
+ , m_rtc_day(0)
+{
+}
+
+//-------------------------------------------------
+// device_start - device-specific startup
+//-------------------------------------------------
+
+void bbc_cisco_device::device_start()
+{
+ m_ram = make_unique_clear<uint8_t[]>(0x8000); // unknown RAM, likely non-volatile, 32K is a guess
+ m_cfg = make_unique_clear<uint8_t[]>(0x80); // unknown RAM, likely non-volatile, maybe with RTC
+
+ // default configuration data, unknown so has been derived from the software
+ static const uint8_t config[0x80] =
+ {
+ 0x00, 0x00, 0x01, // LOFRM frame ROM low address
+ 0xff, 0xff, 0x01, // HIFRM frame ROM high address
+ 0x00, 0x00, 0x00, // LOANSW
+ 0x00, 0x00, 0x00, // HIANSW
+ 0x00, 0x00, 0x00, // LODTBSE
+ 0x00, 0x00, 0x00, // HIDTBSE
+ 0x00, 0x00, 0x02, // message RAM low address
+ 0xff, 0x7f, 0x02, // message RAM high address
+ 0x00, 0x00, 0x00, // not used
+ 0x00, 0x00, 0x00, // not used
+ 0x00, 0x00, 0x00, // not used
+
+ 0x00, 0x08, // NORM page rotation delay
+ 0x00, 0x10, // SLOW page rotation delay
+
+ 0x1c, 0x00, // NFREE pages to rotate when free (32 max)
+ 0x01, 0x00, // FREE main index
+ 0x21, 0x00, // FREE cisco
+ 0x01, 0x00, // FREE
+ 0x26, 0x00, // FREE insurance services
+ 0x01, 0x00, // FREE
+ 0x27, 0x00, // FREE investment opportunities
+ 0x01, 0x00, // FREE
+ 0x28, 0x00, // FREE sport and leisure
+ 0x01, 0x00, // FREE
+ 0x29, 0x00, // FREE food and drink
+ 0x01, 0x00, // FREE
+ 0x2a, 0x00, // FREE marketing services
+ 0x01, 0x00, // FREE
+ 0x2b, 0x00, // FREE management services
+ 0x01, 0x00, // FREE
+ 0x2c, 0x00, // FREE office services
+ 0x01, 0x00, // FREE
+ 0x2d, 0x00, // FREE places to visit
+ 0x01, 0x00, // FREE
+ 0x2e, 0x00, // FREE publications
+ 0x01, 0x00, // FREE
+ 0x2f, 0x00, // FREE professional services
+ 0x01, 0x00, // FREE
+ 0x30, 0x00, // FREE professional bodies
+ 0x01, 0x00, // FREE
+ 0x31, 0x00, // FREE security
+ 0x01, 0x00, // FREE
+ 0x32, 0x00, // FREE travel
+ 0x00, 0x00, // FREE
+ 0x00, 0x00, // FREE
+ 0x00, 0x00, // FREE
+ 0x00, 0x00 // FREE
+ };
+ memcpy(m_cfg.get(), config, 0x80);
+
+ save_pointer(NAME(m_ram), 0x8000);
+ save_pointer(NAME(m_cfg), 0x80);
+ save_item(NAME(m_rom_page));
+}
+
+
+void bbc_cisco_device::rtc_clock_updated(int year, int month, int day, int day_of_week, int hour, int minute, int second)
+{
+ m_rtc_minute = convert_to_bcd(minute);
+ m_rtc_hour = convert_to_bcd(hour);
+ m_rtc_day = day;
+}
+
+
+//**************************************************************************
+// IMPLEMENTATION
+//**************************************************************************
+
+uint8_t bbc_cisco_device::fred_r(offs_t offset)
+{
+ uint8_t data = 0xff;
+
+ switch (offset)
+ {
+ case 0xe8: // unknown RTC
+ data = BIT(m_rtc_minute, 0, 4);
+ break;
+ case 0xe9:
+ data = BIT(m_rtc_minute, 4, 4);
+ break;
+ case 0xea:
+ data = BIT(m_rtc_hour, 0, 4);
+ break;
+ case 0xeb:
+ data = BIT(m_rtc_hour, 4, 4);
+ break;
+ case 0xfa:
+ data = m_rtc_day;
+ break;
+ case 0xfc: // expects 0x55
+ data = 0x55;
+ break;
+ default:
+ logerror("fred_r: unknown %02x = %02x\n", offset, data);
+ break;
+ }
+
+ return data;
+}
+
+void bbc_cisco_device::fred_w(offs_t offset, uint8_t data)
+{
+ switch (offset)
+ {
+ case 0xfc: // always writes 0x55
+ break;
+ case 0xfe: // JIM page MSB
+ m_rom_page = (m_rom_page & 0x00ff) | (data << 8);
+ break;
+ case 0xff: // JIM page LSB
+ m_rom_page = (m_rom_page & 0xff00) | (data << 0);
+ break;
+ default:
+ logerror("fred_w: unknown %02x = %02x\n", offset, data);
+ break;
+ }
+}
+
+
+uint8_t bbc_cisco_device::jim_r(offs_t offset)
+{
+ uint8_t data = 0xff;
+
+ switch (m_rom_page >> 8)
+ {
+ case 0:
+ data = m_cfg[offset & 0x7f];
+ break;
+ case 1:
+ data = m_rom[((m_rom_page << 8) & 0xff00) | offset];
+ break;
+ case 2:
+ data = m_ram[((m_rom_page << 8) & 0xff00) | offset];
+ break;
+ default:
+ logerror("jim_r: %d %06x = %02x\n", m_rom_page >> 8, (m_rom_page << 8) | offset, data);
+ break;
+ }
+
+ return data;
+}
+
+void bbc_cisco_device::jim_w(offs_t offset, uint8_t data)
+{
+ switch (m_rom_page >> 8)
+ {
+ case 0:
+ m_cfg[offset & 0x7f] = data;
+ break;
+ case 2:
+ m_ram[((m_rom_page << 8) & 0xff00) | offset] = data;
+ break;
+ default:
+ logerror("jim_w: %d %06x = %02x\n", m_rom_page >> 8, (m_rom_page << 8) | offset, data);
+ break;
+ }
+}
diff --git a/src/devices/bus/bbc/1mhzbus/cisco.h b/src/devices/bus/bbc/1mhzbus/cisco.h
new file mode 100644
index 00000000000..7bde215e020
--- /dev/null
+++ b/src/devices/bus/bbc/1mhzbus/cisco.h
@@ -0,0 +1,60 @@
+// license:BSD-3-Clause
+// copyright-holders:Nigel Barnes
+/**********************************************************************
+
+ Cisco Terminal
+
+**********************************************************************/
+
+
+#ifndef MAME_BUS_BBC_1MHZBUS_CISCO_H
+#define MAME_BUS_BBC_1MHZBUS_CISCO_H
+
+#include "1mhzbus.h"
+#include "dirtc.h"
+
+
+//**************************************************************************
+// TYPE DEFINITIONS
+//**************************************************************************
+
+class bbc_cisco_device
+ : public device_t
+ , public device_bbc_1mhzbus_interface
+ , public device_rtc_interface
+{
+public:
+ // construction/destruction
+ bbc_cisco_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
+
+protected:
+ // device-level overrides
+ virtual void device_start() 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;
+
+ // optional information overrides
+ virtual void device_add_mconfig(machine_config &config) override ATTR_COLD;
+ virtual const tiny_rom_entry *device_rom_region() const override ATTR_COLD;
+
+ 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_region_ptr<uint8_t> m_rom;
+ std::unique_ptr<uint8_t[]> m_ram;
+ std::unique_ptr<uint8_t[]> m_cfg;
+
+ uint16_t m_rom_page;
+ uint8_t m_rtc_minute;
+ uint8_t m_rtc_hour;
+ uint8_t m_rtc_day;
+};
+
+
+// device type definition
+DECLARE_DEVICE_TYPE(BBC_CISCO, bbc_cisco_device);
+
+
+#endif /* MAME_BUS_BBC_1MHZBUS_CISCO_H */
diff --git a/src/devices/bus/bbc/1mhzbus/datacentre.cpp b/src/devices/bus/bbc/1mhzbus/datacentre.cpp
new file mode 100644
index 00000000000..1c4cce0e492
--- /dev/null
+++ b/src/devices/bus/bbc/1mhzbus/datacentre.cpp
@@ -0,0 +1,335 @@
+// license:BSD-3-Clause
+// copyright-holders:Nigel Barnes
+/**********************************************************************
+
+ RetroClinic DataCentre - USB, IDE and RAMdisc for the BBC Model B, B+, and Master 128
+
+ http://www.retroclinic.com/acorn/datacentre/datacentre.htm
+
+ TODO:
+ - implement VNC2 USB controller
+
+**********************************************************************/
+
+
+#include "emu.h"
+#include "datacentre.h"
+
+
+//**************************************************************************
+// DEVICE DEFINITIONS
+//**************************************************************************
+
+DEFINE_DEVICE_TYPE(BBC_DATACENTRE, bbc_datacentre_device, "bbc_datacentre", "RetroClinic DataCentre");
+
+
+//-------------------------------------------------
+// INPUT_PORTS( datacentre )
+//-------------------------------------------------
+
+INPUT_PORTS_START(datacentre)
+ PORT_START("LINKS")
+ PORT_CONFNAME(0x01, 0x00, "JP1: IDE Power")
+ PORT_CONFSETTING(0x00, DEF_STR(No))
+ PORT_CONFSETTING(0x01, DEF_STR(Yes))
+ PORT_CONFNAME(0x02, 0x00, "JP2: IDE Interrupt Enable")
+ PORT_CONFSETTING(0x00, DEF_STR(No))
+ PORT_CONFSETTING(0x02, DEF_STR(Yes))
+ PORT_CONFNAME(0x04, 0x00, "JP3: NVRAM Write Protect")
+ PORT_CONFSETTING(0x00, DEF_STR(No))
+ PORT_CONFSETTING(0x04, DEF_STR(Yes))
+
+ PORT_START("NVREST")
+ PORT_CONFNAME(0x01, 0x00, "Import NVRAM Restore Utility") PORT_CHANGED_MEMBER(DEVICE_SELF, FUNC(bbc_datacentre_device::import_nvrest), 0)
+ PORT_CONFSETTING(0x00, DEF_STR(No))
+ PORT_CONFSETTING(0x01, DEF_STR(Yes))
+INPUT_PORTS_END
+
+
+//-------------------------------------------------
+// input_ports - device-specific input ports
+//-------------------------------------------------
+
+ioport_constructor bbc_datacentre_device::device_input_ports() const
+{
+ return INPUT_PORTS_NAME(datacentre);
+}
+
+//-------------------------------------------------
+// ROM( datacentre )
+//-------------------------------------------------
+
+ROM_START(datacentre)
+ ROM_REGION(0x4000, "exp_rom", 0)
+ ROM_LOAD("ramfs104.rom", 0x0000, 0x4000, CRC(2e52e331) SHA1(d3c501fb29d35c2d144b164fa3ceb5a3b65d2850))
+
+ /* initialised NVRAM */
+ ROM_REGION(0x10000, "nvram", 0)
+ ROM_LOAD("eeprom.bin", 0x0000, 0x10000, CRC(eb22a606) SHA1(7d791234216c63a32b7181ff09c2f5fbdfc7f1a0))
+
+ /* NVRAM restore utility */
+ ROM_REGION(0x32000, "nvrest", 0)
+ ROM_LOAD("nvrest_1.01.ssd", 0x00000, 0x32000, CRC(54b49e63) SHA1(524826112e436728ba54e73f3f6b25c7b43abd69))
+ROM_END
+
+//-------------------------------------------------
+// device_add_mconfig - add device configuration
+//-------------------------------------------------
+
+void bbc_datacentre_device::device_add_mconfig(machine_config &config)
+{
+ /* compact flash hard drive */
+ ATA_INTERFACE(config, m_ide).options(ata_devices, "hdd", "hdd", false);
+ m_ide->irq_handler().set(FUNC(bbc_datacentre_device::irq_w));
+
+ I2C_24C512(config, m_nvram); // 24LC512
+
+ /* import floppy images - delayed to allow RAMFS to initialise before import */
+ QUICKLOAD(config, "import0", "ssd,dsd,img", attotime::from_seconds(1)).set_load_callback(FUNC(bbc_datacentre_device::quickload_cb<0>));
+ QUICKLOAD(config, "import1", "ssd,dsd,img", attotime::from_seconds(1)).set_load_callback(FUNC(bbc_datacentre_device::quickload_cb<1>));
+ QUICKLOAD(config, "import2", "ssd,dsd,img", attotime::from_seconds(1)).set_load_callback(FUNC(bbc_datacentre_device::quickload_cb<2>));
+ QUICKLOAD(config, "import3", "ssd,dsd,img", attotime::from_seconds(1)).set_load_callback(FUNC(bbc_datacentre_device::quickload_cb<3>));
+}
+
+//-------------------------------------------------
+// rom_region - device-specific ROM region
+//-------------------------------------------------
+
+const tiny_rom_entry *bbc_datacentre_device::device_rom_region() const
+{
+ return ROM_NAME(datacentre);
+}
+
+//**************************************************************************
+// LIVE DEVICE
+//**************************************************************************
+
+//-------------------------------------------------
+// bbc_ide_device - constructor
+//-------------------------------------------------
+
+bbc_datacentre_device::bbc_datacentre_device(const machine_config& mconfig, const char* tag, device_t* owner, uint32_t clock)
+ : device_t(mconfig, BBC_DATACENTRE, tag, owner, clock)
+ , device_bbc_1mhzbus_interface(mconfig, *this)
+ , m_links(*this, "LINKS")
+ , m_ide(*this, "ide")
+ , m_nvram(*this, "nvram")
+ , m_nvrest(*this, "nvrest")
+ , m_page_ram(0)
+ , m_ide_data(0)
+{
+}
+
+//-------------------------------------------------
+// device_start - device-specific startup
+//-------------------------------------------------
+
+void bbc_datacentre_device::device_start()
+{
+ /* define 1mb ram */
+ m_ram = std::make_unique<uint8_t[]>(0x100000);
+
+ /* register for save states */
+ save_pointer(NAME(m_ram), 0x100000);
+ save_item(NAME(m_page_ram));
+ save_item(NAME(m_ide_data));
+}
+
+
+//**************************************************************************
+// IMPLEMENTATION
+//**************************************************************************
+
+uint8_t bbc_datacentre_device::fred_r(offs_t offset)
+{
+ uint8_t data = 0xff;
+
+ switch (offset & 0xf8)
+ {
+ case 0x40:
+ if (offset & 0x07)
+ {
+ data = m_ide->cs0_r(offset & 0x07, 0xff);
+ }
+ else
+ {
+ m_ide_data = m_ide->cs0_r(offset & 0x07);
+ data = m_ide_data & 0xff;
+ }
+ break;
+ case 0x48:
+ if (offset & 0x04)
+ {
+ data = m_ide->cs1_r(offset & 0x07, 0xff);
+ }
+ else
+ {
+ data = m_ide_data >> 8;
+ }
+ break;
+
+ case 0xf8:
+ switch (offset & 0x07)
+ {
+ case 0x00:
+ /* VNC Data Port */
+ logerror("fred_r: VNC Data Port not implemented\n");
+ break;
+ case 0x01:
+ /* VNC Control Port */
+ logerror("fred_r: VNC Control Port not implemented\n");
+ break;
+
+ case 0x02:
+ /* NVRAM Data Port */
+ data = m_nvram->read_sda();
+ break;
+
+ case 0x06:
+ /* PAGE RAM MSB - This register does not have feedback */
+ break;
+ case 0x07:
+ /* PAGE RAM LSB - LSB 8 bits of page ram register */
+ data = m_page_ram & 0xff;
+ break;
+ }
+ break;
+ }
+
+ return data;
+}
+
+void bbc_datacentre_device::fred_w(offs_t offset, uint8_t data)
+{
+ switch (offset & 0xf8)
+ {
+ case 0x40:
+ if (offset & 0x07)
+ {
+ m_ide->cs0_w(offset & 0x07, data, 0xff);
+ }
+ else
+ {
+ m_ide_data = (m_ide_data & 0xff00) | data;
+ m_ide->cs0_w(offset & 0x07, m_ide_data);
+ }
+ break;
+ case 0x48:
+ if (offset & 0x04)
+ {
+ m_ide->cs1_w(offset & 0x07, data, 0xff);
+ }
+ else
+ {
+ m_ide_data = data << 8;
+ }
+ break;
+
+ case 0xf8:
+ switch (offset & 0x07)
+ {
+ case 0x00:
+ /* VNC Data Port */
+ logerror("fred_w: VNC Data Port not implemented\n");
+ break;
+ case 0x01:
+ /* VNC Control Port */
+ logerror("fred_w: VNC Control Port not implemented\n");
+ break;
+
+ case 0x02:
+ /* NVRAM Data Port */
+ m_nvram->write_sda(BIT(data, 0));
+ break;
+ case 0x03:
+ /* NVRAM Data Direction Register */
+ break;
+ case 0x04:
+ /* NVRAM Clock */
+ m_nvram->write_scl(BIT(data, 0));
+ break;
+ case 0x05:
+ /* NVRAM Write Protect (Issue 1 boards only) */
+ logerror("fred_w: NVRAM Write Protect (Issue 1 boards only) not implemented\n");
+ break;
+
+ case 0x06:
+ /* PAGE RAM MSB - MSB 4 bits of page ram register */
+ m_page_ram = (m_page_ram & 0x00ff) | (data << 8);
+ break;
+ case 0x07:
+ /* PAGE RAM LSB - LSB 8 bits of page ram register */
+ m_page_ram = (m_page_ram & 0xff00) | data;
+ break;
+ }
+ break;
+ }
+}
+
+uint8_t bbc_datacentre_device::jim_r(offs_t offset)
+{
+ return m_ram[((m_page_ram & 0x0fff) << 8) | offset];
+}
+
+void bbc_datacentre_device::jim_w(offs_t offset, uint8_t data)
+{
+ m_ram[((m_page_ram & 0x0fff) << 8) | offset] = data;
+}
+
+void bbc_datacentre_device::irq_w(int state)
+{
+ if (BIT(m_links->read(), 1))
+ {
+ m_slot->irq_w(state);
+ }
+}
+
+
+INPUT_CHANGED_MEMBER(bbc_datacentre_device::import_nvrest)
+{
+ if (newval)
+ {
+ /* import NVRAM restore utility to RAM drive 0 */
+ memcpy(m_ram.get() + 0x1000, m_nvrest->base(), 0x32000);
+ }
+ else
+ {
+ /* clear RAM drive 0 */
+ memset(m_ram.get() + 0x1000, 0, 0x200);
+ m_ram[0x1106] = 0x03; // sector count MSB
+ m_ram[0x1107] = 0x20; // sector count LSB
+ }
+}
+
+
+//-------------------------------------------------
+// QUICKLOAD_LOAD_MEMBER( quickload_cb )
+//-------------------------------------------------
+
+template<int Drive>
+QUICKLOAD_LOAD_MEMBER(bbc_datacentre_device::quickload_cb)
+{
+ // simulate *IMPORT from USB to RAMFS
+ if (image.is_filetype("ssd") || image.is_filetype("img") || image.is_filetype("dsd"))
+ {
+ uint32_t const ram_addr = (Drive * 0x40000) | 0x1000;
+ offs_t offset = 0;
+
+ // import tracks
+ for (int i = 0; i < 80; i++)
+ {
+ image.fread(m_ram.get() + ram_addr + offset, 0xa00);
+ if (image.is_filetype("dsd"))
+ {
+ image.fread(m_ram.get() + ((ram_addr + offset) ^ 0x80000), 0xa00);
+ }
+ offset += 0xa00;
+ }
+ }
+ else
+ {
+ return std::make_pair(image_error::INVALIDIMAGE, "Unsupported file type, must be SSD, DSD, or IMG");
+ }
+
+ 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
new file mode 100644
index 00000000000..74cc90b3c0d
--- /dev/null
+++ b/src/devices/bus/bbc/1mhzbus/datacentre.h
@@ -0,0 +1,68 @@
+// license:BSD-3-Clause
+// copyright-holders:Nigel Barnes
+/**********************************************************************
+
+ RetroClinic DataCentre - USB, IDE and RAMdisc for the BBC Model B, B+, and Master 128
+
+ http://www.retroclinic.com/acorn/datacentre/datacentre.htm
+
+**********************************************************************/
+
+
+#ifndef MAME_BUS_BBC_1MHZBUS_DATACENTRE_H
+#define MAME_BUS_BBC_1MHZBUS_DATACENTRE_H
+
+#include "1mhzbus.h"
+#include "machine/i2cmem.h"
+#include "bus/ata/ataintf.h"
+#include "imagedev/snapquik.h"
+
+//**************************************************************************
+// TYPE DEFINITIONS
+//**************************************************************************
+
+class bbc_datacentre_device :
+ public device_t,
+ public device_bbc_1mhzbus_interface
+{
+public:
+ // construction/destruction
+ bbc_datacentre_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
+
+ DECLARE_INPUT_CHANGED_MEMBER(import_nvrest);
+ template<int Drive> DECLARE_QUICKLOAD_LOAD_MEMBER(quickload_cb);
+
+protected:
+ // device_t implementation
+ virtual void device_start() override ATTR_COLD;
+
+ // optional information overrides
+ virtual void device_add_mconfig(machine_config &config) override ATTR_COLD;
+ virtual ioport_constructor device_input_ports() const override ATTR_COLD;
+ virtual const tiny_rom_entry *device_rom_region() const override ATTR_COLD;
+
+ 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 irq_w(int state);
+
+ required_ioport m_links;
+ required_device<ata_interface_device> m_ide;
+ required_device<i2cmem_device> m_nvram;
+ required_memory_region m_nvrest;
+
+ std::unique_ptr<uint8_t[]> m_ram;
+ uint16_t m_page_ram;
+
+ uint16_t m_ide_data;
+};
+
+
+// device type definition
+DECLARE_DEVICE_TYPE(BBC_DATACENTRE, bbc_datacentre_device);
+
+
+#endif /* MAME_BUS_BBC_1MHZBUS_DATACENTRE_H */
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..f19379dc026 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
@@ -31,16 +31,16 @@ public:
protected:
// device-level overrides
- virtual void device_start() override;
+ virtual void device_start() override ATTR_COLD;
// optional information overrides
- virtual void device_add_mconfig(machine_config &config) override;
+ virtual void device_add_mconfig(machine_config &config) override ATTR_COLD;
virtual uint8_t fred_r(offs_t offset) override;
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
new file mode 100644
index 00000000000..1c6613f1282
--- /dev/null
+++ b/src/devices/bus/bbc/1mhzbus/ide.cpp
@@ -0,0 +1,224 @@
+// license:BSD-3-Clause
+// copyright-holders:Nigel Barnes
+/**********************************************************************
+
+ RetroClinic BBC 8-bit IDE Interface
+
+ http://www.retroclinic.com/acorn/bbcide/bbcide.htm
+ http://www.retroclinic.com/acorn/kitide1mhz/kitide1mhz.htm
+
+ Sprow BeebIDE 16-bit IDE Interface for the BBC series
+
+ http://www.sprow.co.uk/bbc/beebide.htm
+
+**********************************************************************/
+
+
+#include "emu.h"
+#include "ide.h"
+
+
+//**************************************************************************
+// DEVICE DEFINITIONS
+//**************************************************************************
+
+DEFINE_DEVICE_TYPE(BBC_IDE8, bbc_ide8_device, "bbc_ide8", "RetroClinic BBC 8-bit IDE Interface");
+DEFINE_DEVICE_TYPE(BBC_BEEBIDE, bbc_beebide_device, "bbc_beebide", "Sprow BeebIDE 16-bit IDE Interface");
+
+
+//-------------------------------------------------
+// INPUT_PORTS( beebide )
+//-------------------------------------------------
+
+INPUT_PORTS_START(beebide)
+ PORT_START("LINKS")
+ PORT_CONFNAME(0x01, 0x00, "Interrupt Enable")
+ PORT_CONFSETTING(0x00, DEF_STR(No))
+ PORT_CONFSETTING(0x01, DEF_STR(Yes))
+ PORT_CONFNAME(0x10, 0x00, "Address Selection")
+ PORT_CONFSETTING(0x00, "&FC40-&FC4F")
+ PORT_CONFSETTING(0x10, "&FC50-&FC5F")
+INPUT_PORTS_END
+
+
+//-------------------------------------------------
+// input_ports - device-specific input ports
+//-------------------------------------------------
+
+ioport_constructor bbc_beebide_device::device_input_ports() const
+{
+ return INPUT_PORTS_NAME(beebide);
+}
+
+//-------------------------------------------------
+// device_add_mconfig - add device configuration
+//-------------------------------------------------
+
+void bbc_ide8_device::device_add_mconfig(machine_config& config)
+{
+ ATA_INTERFACE(config, m_ide).options(ata_devices, "hdd", nullptr, false);
+}
+
+void bbc_beebide_device::device_add_mconfig(machine_config& config)
+{
+ ATA_INTERFACE(config, m_ide).options(ata_devices, "hdd", nullptr, false);
+ m_ide->irq_handler().set(FUNC(bbc_beebide_device::irq_w));
+
+ 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));
+}
+
+
+//**************************************************************************
+// LIVE DEVICE
+//**************************************************************************
+
+//-------------------------------------------------
+// bbc_ide_device - constructor
+//-------------------------------------------------
+
+bbc_ide8_device::bbc_ide8_device(const machine_config& mconfig, const char* tag, device_t* owner, uint32_t clock)
+ : device_t(mconfig, BBC_IDE8, tag, owner, clock)
+ , device_bbc_1mhzbus_interface(mconfig, *this)
+ , m_ide(*this, "ide")
+{
+}
+
+bbc_beebide_device::bbc_beebide_device(const machine_config& mconfig, const char* tag, device_t* owner, uint32_t clock)
+ : device_t(mconfig, BBC_BEEBIDE, tag, owner, clock)
+ , device_bbc_1mhzbus_interface(mconfig, *this)
+ , m_ide(*this, "ide")
+ , m_1mhzbus(*this, "1mhzbus")
+ , m_links(*this, "LINKS")
+ , m_ide_data(0)
+{
+}
+
+
+//-------------------------------------------------
+// device_start - device-specific startup
+//-------------------------------------------------
+
+void bbc_beebide_device::device_start()
+{
+ save_item(NAME(m_ide_data));
+}
+
+
+//**************************************************************************
+// IMPLEMENTATION
+//**************************************************************************
+
+uint8_t bbc_ide8_device::fred_r(offs_t offset)
+{
+ uint8_t data = 0xff;
+
+ switch (offset & 0xf8)
+ {
+ case 0x40:
+ data = m_ide->cs0_r(offset & 0x07, 0xff);
+ break;
+ }
+
+ return data;
+}
+
+void bbc_ide8_device::fred_w(offs_t offset, uint8_t data)
+{
+ switch (offset & 0xf8)
+ {
+ case 0x40:
+ m_ide->cs0_w(offset & 0x07, data, 0xff);
+ break;
+ }
+}
+
+
+uint8_t bbc_beebide_device::fred_r(offs_t offset)
+{
+ uint8_t data = 0xff;
+
+ if ((offset & 0x50) == ((m_links->read() & 0x10) | 0x40))
+ {
+ switch (offset & 0xe8)
+ {
+ case 0x40:
+ if (offset & 0x07)
+ {
+ data = m_ide->cs0_r(offset & 0x07, 0xff);
+ }
+ else
+ {
+ m_ide_data = m_ide->cs0_r(offset & 0x07);
+ data = m_ide_data & 0xff;
+ }
+ break;
+ case 0x48:
+ if (offset & 0x04)
+ {
+ data = m_ide->cs1_r(offset & 0x07, 0xff);
+ }
+ else
+ {
+ data = m_ide_data >> 8;
+ }
+ break;
+ }
+ }
+
+ data &= m_1mhzbus->fred_r(offset);
+
+ return data;
+}
+
+void bbc_beebide_device::fred_w(offs_t offset, uint8_t data)
+{
+ if ((offset & 0x50) == ((m_links->read() & 0x10) | 0x40))
+ {
+ switch (offset & 0xe8)
+ {
+ case 0x40:
+ if (offset & 0x07)
+ {
+ m_ide->cs0_w(offset & 0x07, data, 0xff);
+ }
+ else
+ {
+ m_ide_data = (m_ide_data & 0xff00) | data;
+ m_ide->cs0_w(offset & 0x07, m_ide_data);
+ }
+ break;
+ case 0x48:
+ if (offset & 0x04)
+ {
+ m_ide->cs1_w(offset & 0x07, data, 0xff);
+ }
+ else
+ {
+ m_ide_data = data << 8;
+ }
+ break;
+ }
+ }
+
+ m_1mhzbus->fred_w(offset, data);
+}
+
+uint8_t bbc_beebide_device::jim_r(offs_t offset)
+{
+ return m_1mhzbus->jim_r(offset);
+}
+
+void bbc_beebide_device::jim_w(offs_t offset, uint8_t data)
+{
+ m_1mhzbus->jim_w(offset, data);
+}
+
+void bbc_beebide_device::irq_w(int state)
+{
+ if (BIT(m_links->read(), 0))
+ {
+ m_slot->irq_w(state);
+ }
+}
diff --git a/src/devices/bus/bbc/1mhzbus/ide.h b/src/devices/bus/bbc/1mhzbus/ide.h
new file mode 100644
index 00000000000..f7cb2c15260
--- /dev/null
+++ b/src/devices/bus/bbc/1mhzbus/ide.h
@@ -0,0 +1,86 @@
+// license:BSD-3-Clause
+// copyright-holders:Nigel Barnes
+/**********************************************************************
+
+ RetroClinic BBC 8-bit IDE Interface
+
+ http://www.retroclinic.com/acorn/bbcide/bbcide.htm
+
+ Sprow BeebIDE 16-bit IDE Interface for the BBC series
+
+ http://www.sprow.co.uk/bbc/beebide.htm
+
+**********************************************************************/
+
+
+#ifndef MAME_BUS_BBC_1MHZBUS_IDE_H
+#define MAME_BUS_BBC_1MHZBUS_IDE_H
+
+#include "1mhzbus.h"
+#include "bus/ata/ataintf.h"
+
+//**************************************************************************
+// TYPE DEFINITIONS
+//**************************************************************************
+
+class bbc_ide8_device :
+ public device_t,
+ public device_bbc_1mhzbus_interface
+{
+public:
+ // construction/destruction
+ bbc_ide8_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 fred_r(offs_t offset) override;
+ virtual void fred_w(offs_t offset, uint8_t data) override;
+
+private:
+ required_device<ata_interface_device> m_ide;
+};
+
+
+class bbc_beebide_device :
+ public device_t,
+ public device_bbc_1mhzbus_interface
+{
+public:
+ // construction/destruction
+ bbc_beebide_device(const machine_config& mconfig, const char* tag, device_t* owner, uint32_t clock);
+
+protected:
+ // device-level overrides
+ virtual void device_start() override ATTR_COLD;
+
+ // optional information overrides
+ virtual void device_add_mconfig(machine_config& config) override;
+ virtual ioport_constructor device_input_ports() const override ATTR_COLD;
+
+ 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 irq_w(int state);
+
+ required_device<ata_interface_device> m_ide;
+ required_device<bbc_1mhzbus_slot_device> m_1mhzbus;
+ required_ioport m_links;
+
+ uint16_t m_ide_data;
+};
+
+
+// device type definition
+DECLARE_DEVICE_TYPE(BBC_IDE8, bbc_ide8_device);
+DECLARE_DEVICE_TYPE(BBC_BEEBIDE, bbc_beebide_device);
+
+
+#endif /* MAME_BUS_BBC_1MHZBUS_IDE_H */
diff --git a/src/devices/bus/bbc/1mhzbus/ieee488.cpp b/src/devices/bus/bbc/1mhzbus/ieee488.cpp
index 3aae6fe2f54..3ddb6a13dc1 100644
--- a/src/devices/bus/bbc/1mhzbus/ieee488.cpp
+++ b/src/devices/bus/bbc/1mhzbus/ieee488.cpp
@@ -39,6 +39,8 @@ ROM_START(ieee488)
ROMX_LOAD("ieeefs-0.5.rom", 0x0000, 0x2000, CRC(4c2e80ee) SHA1(0bf33f0378657cf35a49f4f74be40c26ebcb9de5), ROM_BIOS(0))
ROM_SYSTEM_BIOS(1, "ieee02", "IEEEFS 0.02")
ROMX_LOAD("ieeefs-0.2.rom", 0x0000, 0x2000, CRC(73a7960c) SHA1(86828db58e6d1d0a9aade9e73fb1fafd5b6aedff), ROM_BIOS(1))
+ ROM_SYSTEM_BIOS(2, "ieee01", "IEEEFS 0.01")
+ ROMX_LOAD("ieeefs-0.1.rom", 0x0000, 0x2000, CRC(69dfc98d) SHA1(0d3fcb79e70cfa42eff8cc78bf29c2493898d6eb), ROM_BIOS(2))
ROM_END
//ROM_START(procyon)
diff --git a/src/devices/bus/bbc/1mhzbus/ieee488.h b/src/devices/bus/bbc/1mhzbus/ieee488.h
index 9b810b4bf8d..a96521810b1 100644
--- a/src/devices/bus/bbc/1mhzbus/ieee488.h
+++ b/src/devices/bus/bbc/1mhzbus/ieee488.h
@@ -36,11 +36,11 @@ public:
protected:
// device-level overrides
- virtual void device_start() override;
+ virtual void device_start() override ATTR_COLD;
// optional information overrides
- virtual void device_add_mconfig(machine_config &config) override;
- virtual const tiny_rom_entry *device_rom_region() const override;
+ virtual void device_add_mconfig(machine_config &config) override ATTR_COLD;
+ virtual const tiny_rom_entry *device_rom_region() const override ATTR_COLD;
virtual uint8_t fred_r(offs_t offset) override;
virtual void fred_w(offs_t offset, uint8_t data) override;
@@ -64,10 +64,10 @@ public:
protected:
// device-level overrides
- virtual void device_start() override;
+ virtual void device_start() override ATTR_COLD;
// optional information overrides
- virtual void device_add_mconfig(machine_config &config) override;
+ virtual void device_add_mconfig(machine_config &config) override ATTR_COLD;
virtual uint8_t fred_r(offs_t offset) override;
virtual void fred_w(offs_t offset, uint8_t data) override;
@@ -88,11 +88,11 @@ private:
//
//protected:
// // device-level overrides
-// virtual void device_start() override;
+// virtual void device_start() override ATTR_COLD;
//
// // optional information overrides
-// virtual void device_add_mconfig(machine_config &config) override;
-// virtual const tiny_rom_entry *device_rom_region() const override;
+// virtual void device_add_mconfig(machine_config &config) override ATTR_COLD;
+// virtual const tiny_rom_entry *device_rom_region() const override ATTR_COLD;
//
// virtual uint8_t fred_r(offs_t offset) override;
// virtual void fred_w(offs_t offset, uint8_t data) override;
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..705bcf55fd8 100644
--- a/src/devices/bus/bbc/1mhzbus/m2000.h
+++ b/src/devices/bus/bbc/1mhzbus/m2000.h
@@ -33,10 +33,10 @@ public:
protected:
// device-level overrides
- virtual void device_start() override;
+ virtual void device_start() override ATTR_COLD;
// optional information overrides
- virtual void device_add_mconfig(machine_config &config) override;
+ virtual void device_add_mconfig(machine_config &config) override ATTR_COLD;
virtual uint8_t fred_r(offs_t offset) override;
virtual void fred_w(offs_t offset, uint8_t data) override;
@@ -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/m5000.cpp b/src/devices/bus/bbc/1mhzbus/m5000.cpp
new file mode 100644
index 00000000000..758e3311491
--- /dev/null
+++ b/src/devices/bus/bbc/1mhzbus/m5000.cpp
@@ -0,0 +1,430 @@
+// license:BSD-3-Clause
+// copyright-holders:Nigel Barnes
+// thanks-to:Darren Izzard
+/**********************************************************************
+
+ Acorn ANV02 Music 500
+
+ http://chrisacorns.computinghistory.org.uk/8bit_Upgrades/Acorn_ANV02_Music500.html
+
+ Hybrid Music 5000 Synthesiser
+
+ https://www.retro-kit.co.uk/page.cfm/content/Hybrid-Music-5000-Synthesiser/
+ http://chrisacorns.computinghistory.org.uk/8bit_Upgrades/Hybrid_Music5000.html
+
+ Hybrid Music 3000 Expander
+
+ https://www.retro-kit.co.uk/page.cfm/content/Hybrid-Music-3000-Expander/
+
+ Peartree Music 87 Synthesiser
+
+ http://www.computinghistory.org.uk/det/4535/Peartree-Computers-Music-87-Synthesizer-(M500)/
+
+ TODO:
+ - convert to use DAC76 device
+ - add suitably patched version of Ample ROM
+ - add ROMs for Music 87
+
+**********************************************************************/
+
+
+#include "emu.h"
+#include "m5000.h"
+#include "speaker.h"
+#include "softlist_dev.h"
+
+
+//**************************************************************************
+// DEVICE DEFINITIONS
+//**************************************************************************
+
+DEFINE_DEVICE_TYPE(HTMUSIC, htmusic_device, "htmusic", "Hybrid Technology Music System")
+
+DEFINE_DEVICE_TYPE(BBC_M500, bbc_m500_device, "bbc_m500", "Acorn Music 500");
+DEFINE_DEVICE_TYPE(BBC_M5000, bbc_m5000_device, "bbc_m5000", "Hybrid Music 5000 Synthesiser");
+DEFINE_DEVICE_TYPE(BBC_M3000, bbc_m3000_device, "bbc_m3000", "Hybrid Music 3000 Expander");
+DEFINE_DEVICE_TYPE(BBC_M87, bbc_m87_device, "bbc_m87", "Peartree Music 87 Synthesiser");
+
+
+//-------------------------------------------------
+// ROM( m5000 )
+//-------------------------------------------------
+
+//ROM_START( m5000 )
+ //ROM_REGION(0x4000, "exp_rom", 0)
+ // Each AMPLE Nucleus ROM has a unique identification code (ID)
+ //ROM_LOAD("ample_patch.rom", 0x0000, 0x4000, CRC(15bbd499) SHA1(ac90f403b3bde0cdaae68546799b94962bc00fcb))
+//ROM_END
+
+
+//-------------------------------------------------
+// device_add_mconfig - add device configuration
+//-------------------------------------------------
+
+void bbc_m500_device::add_common_devices(machine_config &config)
+{
+ SPEAKER(config, "speaker", 2).front();
+
+ HTMUSIC(config, m_hybrid, 12_MHz_XTAL / 2);
+ m_hybrid->add_route(0, "speaker", 1.0, 0);
+ m_hybrid->add_route(1, "speaker", 1.0, 1);
+
+ 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));
+}
+
+void bbc_m500_device::device_add_mconfig(machine_config &config)
+{
+ add_common_devices(config);
+
+ SOFTWARE_LIST(config, "flop_ls_hybrid").set_original("bbc_flop_hybrid").set_filter("M500");
+}
+
+void bbc_m5000_device::device_add_mconfig(machine_config &config)
+{
+ add_common_devices(config);
+
+ SOFTWARE_LIST(config, "flop_ls_hybrid").set_original("bbc_flop_hybrid").set_filter("M5000");
+}
+
+void bbc_m3000_device::device_add_mconfig(machine_config &config)
+{
+ add_common_devices(config);
+}
+
+void bbc_m87_device::device_add_mconfig(machine_config &config)
+{
+ add_common_devices(config);
+
+ SOFTWARE_LIST(config, "flop_ls_hybrid").set_original("bbc_flop_hybrid").set_filter("M87");
+}
+
+
+//-------------------------------------------------
+// rom_region - device-specific ROM region
+//-------------------------------------------------
+
+//const tiny_rom_entry *bbc_m5000_device::device_rom_region() const
+//{
+ //return ROM_NAME( m5000 );
+//}
+
+
+//**************************************************************************
+// LIVE DEVICE
+//**************************************************************************
+
+//-------------------------------------------------
+// bbc_hybrid_device - constructor
+//-------------------------------------------------
+
+bbc_m500_device::bbc_m500_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_1mhzbus_interface(mconfig, *this)
+ , m_1mhzbus(*this, "1mhzbus")
+ , m_hybrid(*this, "hybrid")
+ , m_page(0)
+{
+}
+
+bbc_m500_device::bbc_m500_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
+ : bbc_m500_device(mconfig, BBC_M500, tag, owner, clock)
+{
+}
+
+bbc_m5000_device::bbc_m5000_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
+ : bbc_m500_device(mconfig, BBC_M5000, tag, owner, clock)
+{
+}
+
+bbc_m3000_device::bbc_m3000_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
+ : bbc_m500_device(mconfig, BBC_M3000, tag, owner, clock)
+{
+}
+
+bbc_m87_device::bbc_m87_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
+ : bbc_m500_device(mconfig, BBC_M87, tag, owner, clock)
+{
+}
+
+
+//-------------------------------------------------
+// device_start - device-specific startup
+//-------------------------------------------------
+
+void bbc_m500_device::device_start()
+{
+ // register for save states
+ save_item(NAME(m_page));
+}
+
+
+//**************************************************************************
+// IMPLEMENTATION
+//**************************************************************************
+
+uint8_t bbc_m500_device::fred_r(offs_t offset)
+{
+ return m_1mhzbus->fred_r(offset);
+}
+
+void bbc_m500_device::fred_w(offs_t offset, uint8_t data)
+{
+ if (offset == 0xff)
+ {
+ m_page = data;
+ }
+
+ m_1mhzbus->fred_w(offset, data);
+}
+
+uint8_t bbc_m500_device::jim_r(offs_t offset)
+{
+ return m_1mhzbus->jim_r(offset);
+}
+
+void bbc_m500_device::jim_w(offs_t offset, uint8_t data)
+{
+ if ((m_page & 0xf0) == 0x30)
+ {
+ uint8_t page = (m_page >> 1) & 7;
+
+ m_hybrid->ram_w((page << 8) | offset, data);
+ }
+
+ m_1mhzbus->jim_w(offset, data);
+}
+
+
+void bbc_m3000_device::jim_w(offs_t offset, uint8_t data)
+{
+ if ((m_page & 0xf0) == 0x50)
+ {
+ uint8_t page = (m_page >> 1) & 7;
+
+ m_hybrid->ram_w((page << 8) | offset, data);
+ }
+
+ m_1mhzbus->jim_w(offset, data);
+}
+
+
+//**************************************************************************
+// HYBRID MUSIC IMPLEMENTATION
+//**************************************************************************
+
+//-------------------------------------------------
+// htmusic_device - constructor
+//-------------------------------------------------
+
+htmusic_device::htmusic_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
+ : device_t(mconfig, HTMUSIC, tag, owner, clock)
+ , device_sound_interface(mconfig, *this)
+ , m_counter(0)
+ , m_c4d(0)
+ , m_sign(0)
+ , m_sam(0)
+ , m_disable(false)
+ , m_modulate(false)
+ , m_dsp_timer(nullptr)
+ , m_stream(nullptr)
+{
+}
+
+//-------------------------------------------------
+// device_start - device-specific startup
+//-------------------------------------------------
+
+void htmusic_device::device_start()
+{
+ // 12-bit antilog as per Am6070 datasheet
+ for (int i = 0; i < 128; i++)
+ m_antilog[i] = (uint16_t)(2 * (pow(2.0, i >> 4) * ((i & 15) + 16.5) - 16.5));
+
+ // create the stream
+ m_stream = stream_alloc(0, 2, clock() / 128);
+
+ // allocate timer
+ m_dsp_timer = timer_alloc(FUNC(htmusic_device::dsp_tick), this);
+
+ // register for save states
+ save_item(NAME(m_wave_ram));
+ save_item(NAME(m_phase_ram));
+ save_item(NAME(m_counter));
+ save_item(NAME(m_c4d));
+ save_item(NAME(m_sign));
+ save_item(NAME(m_disable));
+ save_item(NAME(m_modulate));
+ save_item(NAME(m_sam));
+ save_item(NAME(m_sam_l));
+ save_item(NAME(m_sam_r));
+}
+
+//-------------------------------------------------
+// device_reset - device-specific reset
+//-------------------------------------------------
+
+void htmusic_device::device_reset()
+{
+ // clear ram
+ memset(m_wave_ram, 0, sizeof(m_wave_ram));
+ memset(m_phase_ram, 0, sizeof(m_phase_ram));
+
+ memset(m_sam_l, 0, sizeof(m_sam_l));
+ memset(m_sam_r, 0, sizeof(m_sam_r));
+
+ // reset counter
+ m_counter = 0;
+ m_disable = false;
+ m_modulate = false;
+
+ // start timer
+ m_dsp_timer->adjust(attotime::zero, 0, attotime::from_hz(clock()));
+}
+
+
+//-------------------------------------------------
+// digital signal processor
+//-------------------------------------------------
+
+#define I_CHAN(c) ((((c) & 0x1e) >> 1) + (((c) & 0x01) << 7) + 0x700)
+#define I_FREQ(c) (I_CHAN(c))
+#define I_WAVESEL(c) (I_CHAN(c) + 0x50)
+#define I_AMP(c) (I_CHAN(c) + 0x60)
+#define I_CTL(c) (I_CHAN(c) + 0x70)
+#define FREQ(c) ((m_wave_ram[I_FREQ(c) + 0x20] << 16) | (m_wave_ram[I_FREQ(c) + 0x10] << 8) | (m_wave_ram[I_FREQ(c)] & 0x7e))
+#define DISABLE(c) (BIT(m_wave_ram[I_FREQ(c)], 0))
+#define AMP(c) (m_wave_ram[I_AMP(c)])
+#define WAVESEL(c) (m_wave_ram[I_WAVESEL(c)] >> 4)
+#define CTL(c) (m_wave_ram[I_CTL(c)])
+#define MODULATE(c) (BIT(CTL(c), 5))
+#define INVERT(c) (BIT(CTL(c), 4))
+#define PAN(c) (CTL(c) & 0x0f)
+
+TIMER_CALLBACK_MEMBER(htmusic_device::dsp_tick)
+{
+ // 4-bit channel select
+ uint8_t channel = (m_counter >> 3) & 0x0f;
+ uint8_t c = (channel << 1) + (m_modulate ? 1 : 0);
+
+ // 3-bit program counter
+ switch (m_counter & 0x07)
+ {
+ case 0:
+ m_stream->update();
+
+ m_disable = DISABLE(c);
+ break;
+
+ case 1:
+ break;
+
+ case 2:
+ // In the real hardware the disable bit works by forcing the
+ // phase accumulator to zero.
+ if (m_disable)
+ {
+ m_phase_ram[channel] = 0;
+ m_c4d = 0;
+ }
+ else
+ {
+ uint32_t sum = m_phase_ram[channel] + FREQ(c);
+ m_phase_ram[channel] = sum & 0xffffff;
+ // c4d is used for "Synchronization" e.g. the "Wha" instrument
+ m_c4d = sum >> 24;
+ }
+ break;
+
+ case 3:
+ break;
+
+ case 4:
+ break;
+
+ case 5:
+ m_sam = m_wave_ram[(WAVESEL(c) << 7) + (m_phase_ram[channel] >> 17)];
+ break;
+
+ case 6:
+ // The amplitude operates in the log domain
+ // - m_sam holds the wave table output which is 1 bit sign and 7 bit magnitude
+ // - amp holds the amplitude which is 1 bit sign and 8 bit magnitude (0x00 being quite, 0x7f being loud)
+ // The real hardware combines these in a single 8 bit adder, as we do here.
+ //
+ // Consider a positive wav value (sign bit = 1)
+ // wav: (0x80 -> 0xFF) + amp: (0x00 -> 0x7F) => (0x80 -> 0x7E)
+ // values in the range 0x80...0xff are very small and clamped to zero
+ //
+ // Consider a negative wav value (sign bit = 0)
+ // wav: (0x00 -> 0x7F) + amp: (0x00 -> 0x7F) => (0x00 -> 0xFE)
+ // values in the range 0x00...0x7f are very small and clamped to zero
+ //
+ // In both cases:
+ // - zero clamping happens when the sign bit stays the same
+ // - the 7-bit result is in bits 0..6
+ //
+ m_sign = m_sam & 0x80;
+ m_sam += AMP(c);
+ if ((m_sign ^ m_sam) & 0x80)
+ m_sam &= 0x7f; // sign bits being different is the normal case
+ else
+ m_sam = 0x00; // sign bits being the same indicates underflow so clamp to zero
+ break;
+
+ case 7:
+ {
+ m_modulate = MODULATE(c) && (!!(m_sign) || !!(m_c4d));
+
+ // in the real hardware, inversion does not affect modulation
+ if (INVERT(c))
+ m_sign ^= 0x80;
+
+ // m_sam is an 8-bit log value
+ if (m_sign)
+ m_sam = m_antilog[m_sam]; // sign being 1 is positive
+ else
+ m_sam = -m_antilog[m_sam]; // sign being 0 is negative
+
+ // m_sam is a 12-bit linear sample
+ uint8_t pan;
+ switch (PAN(c))
+ {
+ case 8: case 9: case 10: pan = 6; break;
+ case 11: pan = 5; break;
+ case 12: pan = 4; break;
+ case 13: pan = 3; break;
+ case 14: pan = 2; break;
+ case 15: pan = 1; break;
+ default: pan = 0; break;
+ }
+
+ // Apply panning. In the real hardware, a disabled channel is not actually
+ // forced to zero, but this seems harmless so leave in for now.
+ m_sam_l[channel] = m_disable ? 0 : ((m_sam * pan) / 6);
+ m_sam_r[channel] = m_disable ? 0 : ((m_sam * (6 - pan)) / 6);
+ break;
+ }
+ }
+
+ m_counter++;
+}
+
+
+//-------------------------------------------------
+// sound_stream_update - handle a stream update
+//-------------------------------------------------
+
+void htmusic_device::sound_stream_update(sound_stream &stream)
+{
+ // iterate over channels and accumulate sample data
+ for (int channel = 0; channel < 16; channel++)
+ {
+ for (int sampindex = 0; sampindex < stream.samples(); sampindex++)
+ {
+ stream.add_int(0, sampindex, m_sam_l[channel], 8031 * 16);
+ stream.add_int(1, sampindex, m_sam_r[channel], 8031 * 16);
+ }
+ }
+}
diff --git a/src/devices/bus/bbc/1mhzbus/m5000.h b/src/devices/bus/bbc/1mhzbus/m5000.h
new file mode 100644
index 00000000000..44704a2b492
--- /dev/null
+++ b/src/devices/bus/bbc/1mhzbus/m5000.h
@@ -0,0 +1,158 @@
+// license:BSD-3-Clause
+// copyright-holders:Nigel Barnes
+/**********************************************************************
+
+ Acorn ANV02 Music 500
+
+ http://chrisacorns.computinghistory.org.uk/8bit_Upgrades/Acorn_ANV02_Music500.html
+
+ Hybrid Music 5000 Synthesiser
+
+ https://www.retro-kit.co.uk/page.cfm/content/Hybrid-Music-5000-Synthesiser/
+ http://chrisacorns.computinghistory.org.uk/8bit_Upgrades/Hybrid_Music5000.html
+
+ Hybrid Music 3000 Expander
+
+ https://www.retro-kit.co.uk/page.cfm/content/Hybrid-Music-3000-Expander/
+
+ Peartree Music 87 Synthesiser
+
+ http://www.computinghistory.org.uk/det/4535/Peartree-Computers-Music-87-Synthesizer-(M500)/
+
+**********************************************************************/
+
+
+#ifndef MAME_BUS_BBC_1MHZBUS_M5000_H
+#define MAME_BUS_BBC_1MHZBUS_M5000_H
+
+#include "1mhzbus.h"
+
+
+//**************************************************************************
+// TYPE DEFINITIONS
+//**************************************************************************
+
+// ======================> htmusic_device
+
+class htmusic_device : public device_t, public device_sound_interface
+{
+public:
+ htmusic_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
+
+ void ram_w(offs_t offset, uint8_t data) { m_wave_ram[offset & 0x7ff] = data; }
+
+protected:
+ // device-level overrides
+ virtual void device_start() override ATTR_COLD;
+ virtual void device_reset() override ATTR_COLD;
+
+ // sound stream update overrides
+ virtual void sound_stream_update(sound_stream &stream) override;
+
+ TIMER_CALLBACK_MEMBER(dsp_tick);
+
+private:
+ uint16_t m_antilog[128];
+ uint8_t m_wave_ram[0x800];
+ uint32_t m_phase_ram[0x200];
+
+ uint8_t m_counter;
+ uint8_t m_c4d;
+ uint8_t m_sign;
+ int16_t m_sam;
+ bool m_disable;
+ bool m_modulate;
+
+ int32_t m_sam_l[16];
+ int32_t m_sam_r[16];
+
+ emu_timer *m_dsp_timer;
+
+ sound_stream *m_stream;
+};
+
+
+// ======================> bbc_m500_device
+
+class bbc_m500_device : public device_t, public device_bbc_1mhzbus_interface
+{
+public:
+ // construction/destruction
+ bbc_m500_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
+
+protected:
+ bbc_m500_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 ATTR_COLD;
+
+ // optional information overrides
+ virtual void device_add_mconfig(machine_config &config) override ATTR_COLD;
+
+ void add_common_devices(machine_config &config);
+
+ 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;
+
+ required_device<bbc_1mhzbus_slot_device> m_1mhzbus;
+ required_device<htmusic_device> m_hybrid;
+
+ uint8_t m_page;
+};
+
+
+// ======================> bbc_m5000_device
+
+class bbc_m5000_device : public bbc_m500_device
+{
+public:
+ // construction/destruction
+ bbc_m5000_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 ATTR_COLD;
+ //virtual const tiny_rom_entry *device_rom_region() const override ATTR_COLD;
+};
+
+
+// ======================> bbc_m3000_device
+
+class bbc_m3000_device : public bbc_m500_device
+{
+public:
+ // construction/destruction
+ bbc_m3000_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 ATTR_COLD;
+
+ virtual void jim_w(offs_t offset, uint8_t data) override;
+};
+
+
+// ======================> bbc_m87_device
+
+class bbc_m87_device : public bbc_m500_device
+{
+public:
+ // construction/destruction
+ bbc_m87_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 ATTR_COLD;
+};
+
+
+// device type definition
+DECLARE_DEVICE_TYPE(BBC_M500, bbc_m500_device);
+DECLARE_DEVICE_TYPE(BBC_M5000, bbc_m5000_device);
+DECLARE_DEVICE_TYPE(BBC_M3000, bbc_m3000_device);
+DECLARE_DEVICE_TYPE(BBC_M87, bbc_m87_device);
+
+
+#endif /* MAME_BUS_BBC_1MHZBUS_M5000_H */
diff --git a/src/devices/bus/bbc/1mhzbus/multiform.cpp b/src/devices/bus/bbc/1mhzbus/multiform.cpp
new file mode 100644
index 00000000000..081c488107a
--- /dev/null
+++ b/src/devices/bus/bbc/1mhzbus/multiform.cpp
@@ -0,0 +1,195 @@
+// license:BSD-3-Clause
+// copyright-holders:Nigel Barnes
+/**********************************************************************
+
+ PEDL Multiform Z80 2nd processor
+
+ http://chrisacorns.computinghistory.org.uk/8bit_Upgrades/Technomatic_MultiformZ80.html
+
+ TODO:
+ - Find utility disc, library disc, and manual
+
+**********************************************************************/
+
+
+#include "emu.h"
+#include "multiform.h"
+#include "softlist_dev.h"
+
+
+//**************************************************************************
+// DEVICE DEFINITIONS
+//**************************************************************************
+
+DEFINE_DEVICE_TYPE(BBC_MULTIFORM, bbc_multiform_device, "bbc_multiform", "PEDL Multiform Z80")
+
+
+//-------------------------------------------------
+// ADDRESS_MAP( z80_mem )
+//-------------------------------------------------
+
+void bbc_multiform_device::z80_mem(address_map &map)
+{
+ map(0x0000, 0xffff).rw(FUNC(bbc_multiform_device::mem_r), FUNC(bbc_multiform_device::mem_w));
+}
+
+//-------------------------------------------------
+// ADDRESS_MAP( z80_io )
+//-------------------------------------------------
+
+void bbc_multiform_device::z80_io(address_map &map)
+{
+ map.global_mask(0xff);
+ map(0x00, 0x00).r(m_host_latch[0], FUNC(generic_latch_8_device::read)).w(m_parasite_latch[0], FUNC(generic_latch_8_device::write));
+ map(0x01, 0x01).r(m_host_latch[1], FUNC(generic_latch_8_device::read)).w(m_parasite_latch[1], FUNC(generic_latch_8_device::write));
+ map(0x80, 0x80).w(FUNC(bbc_multiform_device::rom_disable_w));
+}
+
+//-------------------------------------------------
+// ROM( multiform )
+//-------------------------------------------------
+
+ROM_START(multiform)
+ ROM_REGION(0x2000, "osm", 0)
+ ROM_LOAD("osmv200.rom", 0x0000, 0x2000, CRC(67ce1713) SHA1(314ee6211a7af6cab659640fbdd11f1078460f08))
+
+ ROM_REGION(0x4000, "exp_rom", 0)
+ ROM_LOAD("osmz80v137.rom", 0x0000, 0x4000, CRC(79a8de8f) SHA1(0bc06ce54ab9a2242294bbbe9ce8f07e464bb674))
+ROM_END
+
+//-------------------------------------------------
+// device_add_mconfig - add device configuration
+//-------------------------------------------------
+
+void bbc_multiform_device::device_add_mconfig(machine_config &config)
+{
+ Z80(config, m_z80, 8_MHz_XTAL / 2);
+ m_z80->set_addrmap(AS_PROGRAM, &bbc_multiform_device::z80_mem);
+ m_z80->set_addrmap(AS_IO, &bbc_multiform_device::z80_io);
+ m_z80->set_irq_acknowledge_callback(FUNC(bbc_multiform_device::irq_callback));
+
+ /* 74ls374 */
+ GENERIC_LATCH_8(config, m_host_latch[0]);
+ GENERIC_LATCH_8(config, m_host_latch[1]);
+ GENERIC_LATCH_8(config, m_parasite_latch[0]);
+ GENERIC_LATCH_8(config, m_parasite_latch[1]);
+
+ /* software lists */
+ SOFTWARE_LIST(config, "flop_ls_z80").set_original("bbc_flop_z80");
+}
+
+//-------------------------------------------------
+// rom_region - device-specific ROM region
+//-------------------------------------------------
+
+const tiny_rom_entry *bbc_multiform_device::device_rom_region() const
+{
+ return ROM_NAME( multiform );
+}
+
+//**************************************************************************
+// LIVE DEVICE
+//**************************************************************************
+
+//-------------------------------------------------
+// bbc_multiform_device - constructor
+//-------------------------------------------------
+
+bbc_multiform_device::bbc_multiform_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
+ : device_t(mconfig, BBC_MULTIFORM, tag, owner, clock)
+ , device_bbc_1mhzbus_interface(mconfig, *this)
+ , m_z80(*this, "z80")
+ , m_host_latch(*this, "host_latch%u", 0U)
+ , m_parasite_latch(*this, "parasite_latch%u", 0U)
+ , m_osm(*this, "osm")
+ , m_rom_enabled(true)
+{
+}
+
+//-------------------------------------------------
+// device_start - device-specific startup
+//-------------------------------------------------
+
+void bbc_multiform_device::device_start()
+{
+ m_ram = std::make_unique<uint8_t[]>(0x10000);
+
+ /* register for save states */
+ save_pointer(NAME(m_ram), 0x10000);
+ save_item(NAME(m_rom_enabled));
+}
+
+//-------------------------------------------------
+// device_reset - device-specific reset
+//-------------------------------------------------
+
+void bbc_multiform_device::device_reset()
+{
+ m_rom_enabled = true;
+}
+
+//**************************************************************************
+// IMPLEMENTATION
+//**************************************************************************
+
+uint8_t bbc_multiform_device::fred_r(offs_t offset)
+{
+ uint8_t data = 0xff;
+
+ switch (offset)
+ {
+ case 0x00:
+ data = m_parasite_latch[0]->read();
+ break;
+ case 0x01:
+ data = m_parasite_latch[1]->read();
+ break;
+ }
+
+ return data;
+}
+
+void bbc_multiform_device::fred_w(offs_t offset, uint8_t data)
+{
+ switch (offset)
+ {
+ case 0x00:
+ m_host_latch[0]->write(data);
+ break;
+ case 0x01:
+ m_host_latch[1]->write(data);
+ break;
+ }
+}
+
+uint8_t bbc_multiform_device::mem_r(offs_t offset)
+{
+ uint8_t data;
+
+ if (m_rom_enabled && offset < 0x2000)
+ data = m_osm->base()[offset & 0x1fff];
+ else
+ data = m_ram[offset];
+
+ return data;
+}
+
+void bbc_multiform_device::mem_w(offs_t offset, uint8_t data)
+{
+ m_ram[offset] = data;
+}
+
+void bbc_multiform_device::rom_disable_w(uint8_t data)
+{
+ if (!machine().side_effects_disabled())
+ m_rom_enabled = false;
+}
+
+//-------------------------------------------------
+// irq vector callback
+//-------------------------------------------------
+
+IRQ_CALLBACK_MEMBER(bbc_multiform_device::irq_callback)
+{
+ return 0xfe;
+}
diff --git a/src/devices/bus/bbc/1mhzbus/multiform.h b/src/devices/bus/bbc/1mhzbus/multiform.h
new file mode 100644
index 00000000000..d13dc83a19e
--- /dev/null
+++ b/src/devices/bus/bbc/1mhzbus/multiform.h
@@ -0,0 +1,69 @@
+// license:BSD-3-Clause
+// copyright-holders:Nigel Barnes
+/**********************************************************************
+
+ PEDL Multiform Z80 2nd processor
+
+ http://chrisacorns.computinghistory.org.uk/8bit_Upgrades/Technomatic_MultiformZ80.html
+
+**********************************************************************/
+
+
+#ifndef MAME_BUS_BBC_1MHZBUS_MULTIFORM_H
+#define MAME_BUS_BBC_1MHZBUS_MULTIFORM_H
+
+#include "1mhzbus.h"
+#include "cpu/z80/z80.h"
+#include "machine/gen_latch.h"
+
+//**************************************************************************
+// TYPE DEFINITIONS
+//**************************************************************************
+
+// ======================> bbc_multiform_device
+
+class bbc_multiform_device :
+ public device_t,
+ public device_bbc_1mhzbus_interface
+{
+public:
+ // construction/destruction
+ bbc_multiform_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
+
+ uint8_t mem_r(offs_t offset);
+ void mem_w(offs_t offset, uint8_t data);
+ void rom_disable_w(uint8_t data);
+
+protected:
+ // device-level overrides
+ virtual void device_start() override ATTR_COLD;
+ virtual void device_reset() override ATTR_COLD;
+
+ // optional information overrides
+ virtual void device_add_mconfig(machine_config &config) override ATTR_COLD;
+ virtual const tiny_rom_entry *device_rom_region() const override ATTR_COLD;
+
+ virtual uint8_t fred_r(offs_t offset) override;
+ virtual void fred_w(offs_t offset, uint8_t data) override;
+
+private:
+ IRQ_CALLBACK_MEMBER( irq_callback );
+
+ required_device<cpu_device> m_z80;
+ required_device_array<generic_latch_8_device, 2> m_host_latch;
+ required_device_array<generic_latch_8_device, 2> m_parasite_latch;
+ required_memory_region m_osm;
+
+ void z80_mem(address_map &map) ATTR_COLD;
+ void z80_io(address_map &map) ATTR_COLD;
+
+ std::unique_ptr<uint8_t[]> m_ram;
+ bool m_rom_enabled;
+};
+
+
+// device type definition
+DECLARE_DEVICE_TYPE(BBC_MULTIFORM, bbc_multiform_device)
+
+
+#endif /* MAME_BUS_BBC_1MHZBUS_MULTIFORM_H */
diff --git a/src/devices/bus/bbc/1mhzbus/opus3.cpp b/src/devices/bus/bbc/1mhzbus/opus3.cpp
index 77f21ac199a..bbf76509403 100644
--- a/src/devices/bus/bbc/1mhzbus/opus3.cpp
+++ b/src/devices/bus/bbc/1mhzbus/opus3.cpp
@@ -16,14 +16,14 @@
&FCFC 1770 drive control
Drive control register
- 0 Select side: 0=side 0, 1=side 1
- 1 Select drive 0
- 2 Select drive 1
- 3 ?Unused?
- 4 ?Always Set
- 5 Density select: 0=double, 1=single
- 6 ?Unused?
- 7 ?Unused?
+ 0 SS Select side: 0=side 0, 1=side 1
+ 1 DS0 Select drive 0
+ 2 DS1 Select drive 1
+ 3 DS2 Select drive 2
+ 4 MO Motor enable
+ 5 DDEN Density select: 0=double, 1=single
+ 6 NC
+ 7 NC
The RAM is accessible through JIM (page &FD). One page is visible in JIM at a time.
The selected page is controlled by the two paging registers:
@@ -40,6 +40,9 @@
#include "emu.h"
#include "opus3.h"
+#include "formats/acorn_dsk.h"
+#include "formats/fsd_dsk.h"
+
//**************************************************************************
// DEVICE DEFINITIONS
@@ -50,18 +53,20 @@ DEFINE_DEVICE_TYPE(BBC_OPUSA, bbc_opusa_device, "bbc_opusa", "Opus Challenger AD
//-------------------------------------------------
-// MACHINE_DRIVER( opus3 )
+// FLOPPY_FORMATS( floppy_formats )
//-------------------------------------------------
-FLOPPY_FORMATS_MEMBER(bbc_opus3_device::floppy_formats)
- FLOPPY_ACORN_SSD_FORMAT,
- FLOPPY_ACORN_DSD_FORMAT,
- FLOPPY_ACORN_ADFS_OLD_FORMAT,
- FLOPPY_ACORN_DOS_FORMAT,
- FLOPPY_FSD_FORMAT,
- FLOPPY_OPUS_DDOS_FORMAT,
- FLOPPY_OPUS_DDCPM_FORMAT
-FLOPPY_FORMATS_END0
+void bbc_opus3_device::floppy_formats(format_registration &fr)
+{
+ fr.add_mfm_containers();
+ fr.add(FLOPPY_ACORN_SSD_FORMAT);
+ fr.add(FLOPPY_ACORN_DSD_FORMAT);
+ fr.add(FLOPPY_ACORN_ADFS_OLD_FORMAT);
+ fr.add(FLOPPY_ACORN_DOS_FORMAT);
+ fr.add(FLOPPY_FSD_FORMAT);
+ fr.add(FLOPPY_OPUS_DDOS_FORMAT);
+ fr.add(FLOPPY_OPUS_DDCPM_FORMAT);
+}
void bbc_floppies(device_slot_interface &device)
{
@@ -69,6 +74,10 @@ void bbc_floppies(device_slot_interface &device)
}
+//-------------------------------------------------
+// ROM( opus3 )
+//-------------------------------------------------
+
ROM_START( opus3 )
ROM_REGION(0x4000, "exp_rom", 0)
ROM_DEFAULT_BIOS("ch103")
@@ -93,14 +102,12 @@ ROM_END
void bbc_opus3_device::device_add_mconfig(machine_config &config)
{
- /* fdc */
WD1770(config, m_fdc, 16_MHz_XTAL / 2);
- m_fdc->drq_wr_callback().set(FUNC(bbc_opus3_device::fdc_drq_w));
+ m_fdc->drq_wr_callback().set(DEVICE_SELF_OWNER, FUNC(bbc_1mhzbus_slot_device::nmi_w));
- FLOPPY_CONNECTOR(config, m_floppy0, bbc_floppies, "525qd", floppy_formats).enable_sound(true);
- FLOPPY_CONNECTOR(config, m_floppy1, bbc_floppies, nullptr, floppy_formats).enable_sound(true);
+ FLOPPY_CONNECTOR(config, m_floppy[0], bbc_floppies, "525qd", floppy_formats).enable_sound(true);
+ FLOPPY_CONNECTOR(config, m_floppy[1], bbc_floppies, nullptr, floppy_formats).enable_sound(true);
- /* ram disk */
RAM(config, m_ramdisk).set_default_size("512K").set_extra_options("256K").set_default_value(0);
}
@@ -127,8 +134,7 @@ bbc_opus3_device::bbc_opus3_device(const machine_config &mconfig, device_type ty
, device_bbc_1mhzbus_interface(mconfig, *this)
, m_ramdisk(*this, "ramdisk")
, m_fdc(*this, "wd1770")
- , m_floppy0(*this, "wd1770:0")
- , m_floppy1(*this, "wd1770:1")
+ , m_floppy(*this, "wd1770:%u", 0)
, m_ramdisk_page(0)
{
}
@@ -189,16 +195,15 @@ void bbc_opus3_device::fred_w(offs_t offset, uint8_t data)
break;
case 0xfc:
// 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
if (floppy)
floppy->ss_w(BIT(data, 0));
- // bit 4: interrupt enabled
- m_fdc_ie = BIT(data, 4);
+ // bit 4: motor enable (always set)
// bit 5: density
m_fdc->dden_w(BIT(data, 5));
@@ -212,13 +217,6 @@ void bbc_opus3_device::fred_w(offs_t offset, uint8_t data)
}
}
-WRITE_LINE_MEMBER(bbc_opus3_device::fdc_drq_w)
-{
- m_fdc_drq = state;
-
- m_slot->nmi_w((m_fdc_drq && m_fdc_ie) ? ASSERT_LINE : CLEAR_LINE);
-}
-
uint8_t bbc_opus3_device::jim_r(offs_t offset)
{
if ((m_ramdisk_page << 8) < m_ramdisk->size())
diff --git a/src/devices/bus/bbc/1mhzbus/opus3.h b/src/devices/bus/bbc/1mhzbus/opus3.h
index 7d287f1622c..fa6d56031d8 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
@@ -33,11 +31,11 @@ protected:
bbc_opus3_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_start() override ATTR_COLD;
// optional information overrides
- virtual void device_add_mconfig(machine_config &config) override;
- virtual const tiny_rom_entry *device_rom_region() const override;
+ virtual void device_add_mconfig(machine_config &config) override ATTR_COLD;
+ virtual const tiny_rom_entry *device_rom_region() const override ATTR_COLD;
virtual uint8_t fred_r(offs_t offset) override;
virtual void fred_w(offs_t offset, uint8_t data) override;
@@ -45,17 +43,12 @@ protected:
virtual void jim_w(offs_t offset, uint8_t data) override;
private:
- DECLARE_FLOPPY_FORMATS(floppy_formats);
-
- DECLARE_WRITE_LINE_MEMBER(fdc_drq_w);
+ static void floppy_formats(format_registration &fr);
required_device<ram_device> m_ramdisk;
required_device<wd1770_device> m_fdc;
- required_device<floppy_connector> m_floppy0;
- optional_device<floppy_connector> m_floppy1;
+ required_device_array<floppy_connector, 2> m_floppy;
- int m_fdc_ie;
- int m_fdc_drq;
uint16_t m_ramdisk_page;
};
@@ -68,10 +61,10 @@ public:
protected:
// device-level overrides
- virtual void device_start() override;
+ virtual void device_start() override ATTR_COLD;
// optional information overrides
- virtual const tiny_rom_entry *device_rom_region() const override;
+ virtual const tiny_rom_entry *device_rom_region() const override ATTR_COLD;
};
diff --git a/src/devices/bus/bbc/1mhzbus/pdram.cpp b/src/devices/bus/bbc/1mhzbus/pdram.cpp
new file mode 100644
index 00000000000..81106218fc4
--- /dev/null
+++ b/src/devices/bus/bbc/1mhzbus/pdram.cpp
@@ -0,0 +1,87 @@
+// license:BSD-3-Clause
+// copyright-holders:Nigel Barnes
+/**********************************************************************
+
+ Pull Down RAM - Micro User Jul/Aug 1990
+
+**********************************************************************/
+
+
+#include "emu.h"
+#include "pdram.h"
+
+
+//**************************************************************************
+// DEVICE DEFINITIONS
+//**************************************************************************
+
+DEFINE_DEVICE_TYPE(BBC_PDRAM, bbc_pdram_device, "bbc_pdram", "Micro User Pull Down RAM (DIY)");
+
+
+//-------------------------------------------------
+// ROM( pdram )
+//-------------------------------------------------
+
+ROM_START(pdram)
+ ROM_REGION(0x4000, "exp_rom", 0)
+ ROM_LOAD("ramdvr.rom", 0x0000, 0x2000, CRC(56f61728) SHA1(265359d1fb9c0adca53912aa6a42a995b8225a3e))
+ROM_END
+
+//-------------------------------------------------
+// rom_region - device-specific ROM region
+//-------------------------------------------------
+
+const tiny_rom_entry* bbc_pdram_device::device_rom_region() const
+{
+ return ROM_NAME(pdram);
+}
+
+//**************************************************************************
+// LIVE DEVICE
+//**************************************************************************
+
+//-------------------------------------------------
+// bbc_pdram_device - constructor
+//-------------------------------------------------
+
+bbc_pdram_device::bbc_pdram_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
+ : device_t(mconfig, BBC_PDRAM, tag, owner, clock)
+ , device_bbc_1mhzbus_interface(mconfig, *this)
+ , m_ram_page(0)
+{
+}
+
+//-------------------------------------------------
+// device_start - device-specific startup
+//-------------------------------------------------
+
+void bbc_pdram_device::device_start()
+{
+ m_ram = std::make_unique<uint8_t[]>(0x8000);
+
+ /* register for save states */
+ save_pointer(NAME(m_ram), 0x8000);
+}
+
+
+//**************************************************************************
+// IMPLEMENTATION
+//**************************************************************************
+
+void bbc_pdram_device::fred_w(offs_t offset, uint8_t data)
+{
+ if (offset == 0xff)
+ {
+ m_ram_page = data;
+ }
+}
+
+uint8_t bbc_pdram_device::jim_r(offs_t offset)
+{
+ return m_ram[(m_ram_page << 8) | offset];
+}
+
+void bbc_pdram_device::jim_w(offs_t offset, uint8_t data)
+{
+ m_ram[(m_ram_page << 8) | offset] = data;
+}
diff --git a/src/devices/bus/bbc/1mhzbus/pdram.h b/src/devices/bus/bbc/1mhzbus/pdram.h
new file mode 100644
index 00000000000..2ba46af358b
--- /dev/null
+++ b/src/devices/bus/bbc/1mhzbus/pdram.h
@@ -0,0 +1,49 @@
+// license:BSD-3-Clause
+// copyright-holders:Nigel Barnes
+/**********************************************************************
+
+ Pull Down RAM
+
+**********************************************************************/
+
+
+#ifndef MAME_BUS_BBC_1MHZBUS_PDRAM_H
+#define MAME_BUS_BBC_1MHZBUS_PDRAM_H
+
+#include "1mhzbus.h"
+
+//**************************************************************************
+// TYPE DEFINITIONS
+//**************************************************************************
+
+class bbc_pdram_device:
+ public device_t,
+ public device_bbc_1mhzbus_interface
+{
+public:
+ // construction/destruction
+ bbc_pdram_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
+
+protected:
+ // device-level overrides
+ virtual void device_start() override ATTR_COLD;
+
+ // optional information overrides
+ 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;
+ virtual void jim_w(offs_t offset, uint8_t data) override;
+
+private:
+ std::unique_ptr<uint8_t[]> m_ram;
+
+ uint8_t m_ram_page;
+};
+
+
+// device type definition
+DECLARE_DEVICE_TYPE(BBC_PDRAM, bbc_pdram_device);
+
+
+#endif /* MAME_BUS_BBC_1MHZBUS_PDRAM_H */
diff --git a/src/devices/bus/bbc/1mhzbus/pms64k.cpp b/src/devices/bus/bbc/1mhzbus/pms64k.cpp
new file mode 100644
index 00000000000..ef0205d1a4f
--- /dev/null
+++ b/src/devices/bus/bbc/1mhzbus/pms64k.cpp
@@ -0,0 +1,99 @@
+// license:BSD-3-Clause
+// copyright-holders:Nigel Barnes
+/**********************************************************************
+
+ PMS 64K Non-Volatile Ram Module
+
+**********************************************************************/
+
+
+#include "emu.h"
+#include "pms64k.h"
+
+
+//**************************************************************************
+// DEVICE DEFINITIONS
+//**************************************************************************
+
+DEFINE_DEVICE_TYPE(BBC_PMS64K, bbc_pms64k_device, "bbc_pms64k", "PMS 64K Non-Volatile Ram Module");
+
+
+//-------------------------------------------------
+// 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
+//-------------------------------------------------
+
+void bbc_pms64k_device::device_add_mconfig(machine_config &config)
+{
+ NVRAM(config, "nvram", nvram_device::DEFAULT_NONE);
+}
+
+//**************************************************************************
+// LIVE DEVICE
+//**************************************************************************
+
+//-------------------------------------------------
+// bbc_pms64k_device - constructor
+//-------------------------------------------------
+
+bbc_pms64k_device::bbc_pms64k_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
+ : device_t(mconfig, BBC_PMS64K, tag, owner, clock)
+ , device_bbc_1mhzbus_interface(mconfig, *this)
+ , m_nvram(*this, "nvram")
+ , m_ram_page(0)
+{
+}
+
+//-------------------------------------------------
+// device_start - device-specific startup
+//-------------------------------------------------
+
+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));
+}
+
+
+//**************************************************************************
+// IMPLEMENTATION
+//**************************************************************************
+
+void bbc_pms64k_device::fred_w(offs_t offset, uint8_t data)
+{
+ if (offset == 0xff)
+ {
+ m_ram_page = data;
+ }
+}
+
+uint8_t bbc_pms64k_device::jim_r(offs_t offset)
+{
+ return m_ram[(m_ram_page << 8) | offset];
+}
+
+void bbc_pms64k_device::jim_w(offs_t offset, uint8_t data)
+{
+ m_ram[(m_ram_page << 8) | offset] = data;
+}
diff --git a/src/devices/bus/bbc/1mhzbus/pms64k.h b/src/devices/bus/bbc/1mhzbus/pms64k.h
new file mode 100644
index 00000000000..95db1a8fc5a
--- /dev/null
+++ b/src/devices/bus/bbc/1mhzbus/pms64k.h
@@ -0,0 +1,50 @@
+// license:BSD-3-Clause
+// copyright-holders:Nigel Barnes
+/**********************************************************************
+
+ PMS 64K Non-Volatile Ram Module
+
+**********************************************************************/
+
+
+#ifndef MAME_BUS_BBC_1MHZBUS_PMS64K_H
+#define MAME_BUS_BBC_1MHZBUS_PMS64K_H
+
+#include "1mhzbus.h"
+#include "machine/nvram.h"
+
+//**************************************************************************
+// TYPE DEFINITIONS
+//**************************************************************************
+
+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_t overrides
+ virtual void device_start() override ATTR_COLD;
+
+ // optional information overrides
+ virtual void device_add_mconfig(machine_config &config) override ATTR_COLD;
+ virtual const tiny_rom_entry *device_rom_region() const override ATTR_COLD;
+
+ 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<nvram_device> m_nvram;
+ std::unique_ptr<uint8_t[]> m_ram;
+
+ uint8_t m_ram_page;
+};
+
+
+// device type definition
+DECLARE_DEVICE_TYPE(BBC_PMS64K, bbc_pms64k_device);
+
+
+#endif // MAME_BUS_BBC_1MHZBUS_PMS64K_H
diff --git a/src/devices/bus/bbc/1mhzbus/ramdisc.cpp b/src/devices/bus/bbc/1mhzbus/ramdisc.cpp
new file mode 100644
index 00000000000..f1ff589df26
--- /dev/null
+++ b/src/devices/bus/bbc/1mhzbus/ramdisc.cpp
@@ -0,0 +1,208 @@
+// license:BSD-3-Clause
+// copyright-holders:Nigel Barnes
+/**********************************************************************
+
+ Morley Electronics RAM Disc
+
+ Notes:
+ - 1MB model has 4096 sectors &0000 to &0fff
+ - 2MB model has 8192 sectors &0000 to &1fff
+
+**********************************************************************/
+
+
+#include "emu.h"
+#include "ramdisc.h"
+
+
+//**************************************************************************
+// DEVICE DEFINITIONS
+//**************************************************************************
+
+DEFINE_DEVICE_TYPE(BBC_RAMDISC, bbc_ramdisc_device, "bbc_ramdisc", "Morley Electronics RAM Disc");
+
+
+//-------------------------------------------------
+// INPUT_PORTS( ramdisc )
+//-------------------------------------------------
+
+static INPUT_PORTS_START(ramdisc)
+ PORT_START("POWER")
+ PORT_CONFNAME(0x01, 0x01, "Power") PORT_CHANGED_MEMBER(DEVICE_SELF, FUNC(bbc_ramdisc_device::power_changed), 0)
+ PORT_CONFSETTING(0x00, DEF_STR(Off))
+ PORT_CONFSETTING(0x01, DEF_STR(On))
+ PORT_START("SIZE")
+ PORT_CONFNAME(0x03, 0x02, "RAM Disk Capacity")
+ PORT_CONFSETTING(0x01, "1MB")
+ PORT_CONFSETTING(0x02, "2MB")
+INPUT_PORTS_END
+
+//-------------------------------------------------
+// input_ports - device-specific input ports
+//-------------------------------------------------
+
+ioport_constructor bbc_ramdisc_device::device_input_ports() const
+{
+ return INPUT_PORTS_NAME(ramdisc);
+}
+
+//-------------------------------------------------
+// ROM( ramdisc )
+//-------------------------------------------------
+
+ROM_START(ramdisc)
+ ROM_REGION(0x4000, "exp_rom", 0)
+ ROM_LOAD("ramdisc101.rom", 0x0000, 0x4000, CRC(627568c2) SHA1(17e727998756fe35ff451fd2ce1d4b5977be24fc))
+ROM_END
+
+//-------------------------------------------------
+// device_add_mconfig - add device configuration
+//-------------------------------------------------
+
+void bbc_ramdisc_device::device_add_mconfig(machine_config &config)
+{
+ /* ram disk */
+ NVRAM(config, "nvram", nvram_device::DEFAULT_NONE);
+
+ 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_ramdisc_device::device_rom_region() const
+{
+ return ROM_NAME(ramdisc);
+}
+
+//**************************************************************************
+// LIVE DEVICE
+//**************************************************************************
+
+//-------------------------------------------------
+// bbc_ramdisc_device - constructor
+//-------------------------------------------------
+
+bbc_ramdisc_device::bbc_ramdisc_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
+ : device_t(mconfig, BBC_RAMDISC, tag, owner, clock)
+ , device_bbc_1mhzbus_interface(mconfig, *this)
+ , m_1mhzbus(*this, "1mhzbus")
+ , m_nvram(*this, "nvram")
+ , m_ram_size(*this, "SIZE")
+ , m_power(*this, "POWER")
+ , m_sector(0)
+{
+}
+
+//-------------------------------------------------
+// device_start - device-specific startup
+//-------------------------------------------------
+
+void bbc_ramdisc_device::device_start()
+{
+ /* define 2mb ram */
+ m_ram = std::make_unique<uint8_t[]>(0x200000);
+ m_nvram->set_base(m_ram.get(), 0x200000);
+
+ /* register for save states */
+ save_pointer(NAME(m_ram), 0x200000);
+ save_item(NAME(m_sector));
+}
+
+
+//**************************************************************************
+// IMPLEMENTATION
+//**************************************************************************
+
+INPUT_CHANGED_MEMBER(bbc_ramdisc_device::power_changed)
+{
+ /* clear RAM on power off */
+ if (!newval)
+ {
+ memset(m_ram.get(), 0xff, 0x200000);
+ }
+}
+
+uint8_t bbc_ramdisc_device::fred_r(offs_t offset)
+{
+ uint8_t data = 0xff;
+
+ if (m_power->read())
+ {
+ switch (offset)
+ {
+ case 0xc0:
+ /* sector LSB */
+ data = m_sector & 0x00ff;
+ break;
+ case 0xc2:
+ /* sector MSB */
+ data = (m_sector & 0xff00) >> 8;
+ break;
+ case 0xc1:
+ case 0xc3:
+ /* TODO: unknown purpose, must return 0x3f or 0x5f */
+ data = 0x3f;
+ logerror("Read %04x -> %02x\n", offset | 0xfcc0, data);
+ break;
+ }
+ }
+
+ data &= m_1mhzbus->fred_r(offset);
+
+ return data;
+}
+
+void bbc_ramdisc_device::fred_w(offs_t offset, uint8_t data)
+{
+ if (m_power->read())
+ {
+ switch (offset)
+ {
+ case 0xc0:
+ /* sector LSB */
+ m_sector = (m_sector & 0xff00) | data;
+ break;
+ case 0xc2:
+ /* sector MSB */
+ m_sector = (m_sector & 0x00ff) | (data << 8);
+ break;
+ case 0xc1:
+ case 0xc3:
+ /* TODO: unknown purpose, always writes 0x00 or 0xff */
+ logerror("Write %04x <- %02x\n", offset | 0xfcc0, data);
+ break;
+ }
+ }
+
+ m_1mhzbus->fred_w(offset, data);
+}
+
+uint8_t bbc_ramdisc_device::jim_r(offs_t offset)
+{
+ uint8_t data = 0xff;
+
+ /* power on and sector < 2mb */
+ if (m_power->read() && m_sector < (m_ram_size->read() << 8))
+ {
+ data &= m_ram[(m_sector << 8) | offset];
+ }
+
+ data &= m_1mhzbus->jim_r(offset);
+
+ return data;
+}
+
+void bbc_ramdisc_device::jim_w(offs_t offset, uint8_t data)
+{
+ /* power on and sector < 2mb */
+ if (m_power->read() && m_sector < (m_ram_size->read() << 8))
+ {
+ m_ram[(m_sector << 8) | offset] = data;
+ }
+
+ m_1mhzbus->jim_w(offset, data);
+}
diff --git a/src/devices/bus/bbc/1mhzbus/ramdisc.h b/src/devices/bus/bbc/1mhzbus/ramdisc.h
new file mode 100644
index 00000000000..4a85921b78d
--- /dev/null
+++ b/src/devices/bus/bbc/1mhzbus/ramdisc.h
@@ -0,0 +1,59 @@
+// license:BSD-3-Clause
+// copyright-holders:Nigel Barnes
+/**********************************************************************
+
+ Morley Electronics RAM Disc
+
+**********************************************************************/
+
+
+#ifndef MAME_BUS_BBC_1MHZBUS_RAMDISC_H
+#define MAME_BUS_BBC_1MHZBUS_RAMDISC_H
+
+#include "1mhzbus.h"
+#include "machine/nvram.h"
+
+//**************************************************************************
+// TYPE DEFINITIONS
+//**************************************************************************
+
+class bbc_ramdisc_device:
+ public device_t,
+ public device_bbc_1mhzbus_interface
+{
+public:
+ // construction/destruction
+ bbc_ramdisc_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
+
+ DECLARE_INPUT_CHANGED_MEMBER(power_changed);
+
+protected:
+ // device-level overrides
+ virtual void device_start() override ATTR_COLD;
+
+ // optional information overrides
+ virtual void device_add_mconfig(machine_config &config) override ATTR_COLD;
+ virtual ioport_constructor device_input_ports() const override ATTR_COLD;
+ virtual const tiny_rom_entry *device_rom_region() const override ATTR_COLD;
+
+ 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;
+ required_device<nvram_device> m_nvram;
+ required_ioport m_ram_size;
+ required_ioport m_power;
+
+ std::unique_ptr<uint8_t[]> m_ram;
+ uint16_t m_sector;
+};
+
+
+// device type definition
+DECLARE_DEVICE_TYPE(BBC_RAMDISC, bbc_ramdisc_device);
+
+
+#endif /* MAME_BUS_BBC_1MHZBUS_RAMDISC_H */
diff --git a/src/devices/bus/bbc/1mhzbus/sasi.cpp b/src/devices/bus/bbc/1mhzbus/sasi.cpp
new file mode 100644
index 00000000000..4550a6791c6
--- /dev/null
+++ b/src/devices/bus/bbc/1mhzbus/sasi.cpp
@@ -0,0 +1,175 @@
+// license:BSD-3-Clause
+// copyright-holders:Nigel Barnes
+/**********************************************************************
+
+ Torch SCSI Host Adaptor
+
+ Circuit diagram: http://mdfs.net/Info/Comp/Torch/scsi1.gif
+
+ http://mdfs.net/Docs/Comp/BBC/Hardware/TorchSCSI
+
+ Supported by Hard Disc Utilities:
+ Mb ss i c h s
+ BASF 6188 11 256 9 360 4 32
+ BASF 6185 20 256 9 440 6 32
+ Mitsubishi MR522 19 256 9 612 4 32
+ NEC D5126 19 256 9 615 4 32
+ Rodime 200/10 10 256 9 320 4 32
+ Rodime 200/20 20 256 9 320 8 32
+ Rodime 202E 20 256 9 640 4 32
+ Rodime 204E 40 256 9 640 8 32
+ Vertex V130 23 256 9 987 5 32
+ Vertex V150 38 256 9 987 5 32
+ Vertex V170 53 256 9 987 7 32
+
+**********************************************************************/
+
+#include "emu.h"
+#include "sasi.h"
+#include "machine/nscsi_bus.h"
+#include "bus/nscsi/devices.h"
+
+
+//**************************************************************************
+// DEVICE DEFINITIONS
+//**************************************************************************
+
+DEFINE_DEVICE_TYPE(BBC_SASI, bbc_sasi_device, "bbc_sasi", "Torch SCSI Host Adaptor");
+DEFINE_DEVICE_TYPE(BBC_TORCHHD, bbc_torchhd_device, "bbc_torchhd", "Torch Hard Disc Pack");
+
+
+//-------------------------------------------------
+// device_add_mconfig - add device configuration
+//-------------------------------------------------
+
+void bbc_sasi_device::device_add_mconfig(machine_config& config)
+{
+ NSCSI_BUS(config, "sasi");
+ NSCSI_CONNECTOR(config, "sasi:0", default_scsi_devices, nullptr);
+ NSCSI_CONNECTOR(config, "sasi: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(bbc_sasi_device::req_w));
+ downcast<nscsi_callback_device&>(*device).sel_callback().set(*this, FUNC(bbc_sasi_device::sel_w));
+ });
+}
+
+void bbc_torchhd_device::device_add_mconfig(machine_config &config)
+{
+ bbc_sasi_device::device_add_mconfig(config);
+
+ /* Xebec S1410 */
+ subdevice<nscsi_connector>("sasi:0")->set_default_option("s1410");
+ subdevice<nscsi_connector>("sasi:0")->set_fixed(true);
+}
+
+
+//**************************************************************************
+// LIVE DEVICE
+//**************************************************************************
+
+//-------------------------------------------------
+// bbc_sasi_device - constructor
+//-------------------------------------------------
+
+bbc_sasi_device::bbc_sasi_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_1mhzbus_interface(mconfig, *this)
+ , m_sasi(*this, "sasi:7:scsicb")
+ , m_sel_state(0)
+{
+}
+
+bbc_sasi_device::bbc_sasi_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
+ : bbc_sasi_device(mconfig, BBC_SASI, tag, owner, clock)
+{
+}
+
+bbc_torchhd_device::bbc_torchhd_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
+ : bbc_sasi_device(mconfig, BBC_TORCHHD, tag, owner, clock)
+{
+}
+
+//-------------------------------------------------
+// device_start - device-specific startup
+//-------------------------------------------------
+
+void bbc_sasi_device::device_start()
+{
+ /* register for save states */
+ save_item(NAME(m_sel_state));
+}
+
+//-------------------------------------------------
+// device_reset - device-specific reset
+//-------------------------------------------------
+
+void bbc_sasi_device::device_reset()
+{
+ m_sasi->rst_w(1);
+ m_sasi->rst_w(0);
+}
+
+//**************************************************************************
+// IMPLEMENTATION
+//**************************************************************************
+
+uint8_t bbc_sasi_device::jim_r(offs_t offset)
+{
+ uint8_t data = 0xff;
+
+ switch (offset)
+ {
+ case 0xf0:
+ data = m_sasi->read();
+ m_sasi->ack_w(1);
+ break;
+ case 0xf1:
+ data = (m_sasi->req_r() << 0)
+ | (m_sasi->ack_r() << 1)
+ | (m_sasi->rst_r() << 2)
+ | (!m_sel_state << 3)
+ | (m_sasi->io_r() << 4)
+ | (m_sasi->cd_r() << 5)
+ | (m_sasi->msg_r() << 6)
+ | (m_sasi->bsy_r() << 7);
+ break;
+ case 0xf2:
+ m_sasi->ack_w(1);
+ break;
+ }
+ return data;
+}
+
+void bbc_sasi_device::jim_w(offs_t offset, uint8_t data)
+{
+ switch (offset)
+ {
+ case 0xf0:
+ m_sasi->write(data);
+ m_sasi->ack_w(1);
+ break;
+ case 0xf1:
+ m_sasi->rst_w(1);
+ m_sasi->rst_w(0);
+ break;
+ case 0xf2:
+ m_sasi->sel_w(1);
+ m_sel_state = 1;
+ break;
+ case 0xf3:
+ m_sasi->sel_w(0);
+ m_sel_state = 0;
+ break;
+ }
+}
+
+void bbc_sasi_device::req_w(int state)
+{
+ m_sasi->ack_w(0);
+}
+
+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
new file mode 100644
index 00000000000..5f73cfca98b
--- /dev/null
+++ b/src/devices/bus/bbc/1mhzbus/sasi.h
@@ -0,0 +1,71 @@
+// license:BSD-3-Clause
+// copyright-holders:Nigel Barnes
+/**********************************************************************
+
+ Torch SCSI Host Adaptor
+
+**********************************************************************/
+
+
+#ifndef MAME_BUS_BBC_1MHZBUS_SASI_H
+#define MAME_BUS_BBC_1MHZBUS_SASI_H
+
+#include "1mhzbus.h"
+#include "machine/nscsi_cb.h"
+
+
+//**************************************************************************
+// TYPE DEFINITIONS
+//**************************************************************************
+
+class bbc_sasi_device:
+ public device_t,
+ public device_bbc_1mhzbus_interface
+{
+public:
+ // construction/destruction
+ bbc_sasi_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
+
+ 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);
+
+ // device-level overrides
+ virtual void device_start() override ATTR_COLD;
+ virtual void device_reset() override ATTR_COLD;
+
+ // 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<nscsi_callback_device> m_sasi;
+
+ int m_sel_state;
+};
+
+
+// ======================> bbc_torchhd_device
+
+class bbc_torchhd_device : public bbc_sasi_device
+{
+public:
+ // construction/destruction
+ bbc_torchhd_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 ATTR_COLD;
+};
+
+
+// device type definition
+DECLARE_DEVICE_TYPE(BBC_SASI, bbc_sasi_device);
+DECLARE_DEVICE_TYPE(BBC_TORCHHD, bbc_torchhd_device);
+
+
+#endif /* MAME_BUS_BBC_1MHZBUS_SASI_H */
diff --git a/src/devices/bus/bbc/1mhzbus/scsi.cpp b/src/devices/bus/bbc/1mhzbus/scsi.cpp
new file mode 100644
index 00000000000..f565dd7eee9
--- /dev/null
+++ b/src/devices/bus/bbc/1mhzbus/scsi.cpp
@@ -0,0 +1,201 @@
+// license:BSD-3-Clause
+// copyright-holders:Nigel Barnes
+/**********************************************************************
+
+ Acorn SCSI Host Adaptor
+
+ Known SCSI controller boards used:
+ Adaptec ACB-4000A
+
+ Known SCSI devices using adaptor:
+ SCSI ID 0 - Acorn Winchester 110: Seagate ST412 + Adaptec ACB-4000A
+ Acorn Winchester 120: NEC D5126 + Adaptec ACB-4000A
+ Acorn Winchester 130: Rodime R0203E + Adaptec ACB-4000A
+ SCSI ID 1 - Digistore Tape Streamer: Archive 2060S
+
+ Compatible 3rd party Winchesters using Akhter Host Adaptor:
+ Technomatic 20MB: Seagate ST225 + Adaptec ACB-4070
+ Technomatic 30MB:
+ Technomatic 40MB:
+
+ Additional notes:
+ The Digistore used a modified Acorn Host Adaptor, it re-mapped
+ the device to &FC44-47, from &FC40-43. This allows both the
+ Digistore and Winchester to co-exist.
+
+ Useful CHD parameters:
+ 10MB -chs 306,4,33 -ss=256
+ 20MB -chs 612,4,33 -ss=256
+ 30MB -chs 640,6,33 -ss=256
+ 512MB -chs 3971,16,33 -ss 256
+
+ TODO:
+ - test formatting, may require specific ACB-4000A commands.
+
+**********************************************************************/
+
+#include "emu.h"
+#include "scsi.h"
+#include "machine/nscsi_bus.h"
+#include "bus/nscsi/devices.h"
+
+
+//**************************************************************************
+// DEVICE DEFINITIONS
+//**************************************************************************
+
+DEFINE_DEVICE_TYPE(BBC_SCSI, bbc_scsi_device, "bbc_scsi", "Acorn SCSI Host Adaptor");
+DEFINE_DEVICE_TYPE(BBC_AWHD, bbc_awhd_device, "bbc_awhd", "Acorn Winchester Disc");
+
+
+//-------------------------------------------------
+// device_add_mconfig - add device configuration
+//-------------------------------------------------
+
+void bbc_scsi_device::device_add_mconfig(machine_config& config)
+{
+ NSCSI_BUS(config, "scsi");
+ NSCSI_CONNECTOR(config, "scsi:0", default_scsi_devices, nullptr);
+ NSCSI_CONNECTOR(config, "scsi:1", default_scsi_devices, nullptr);
+ NSCSI_CONNECTOR(config, "scsi:7", default_scsi_devices, "scsicb", true)
+ .option_add_internal("scsicb", NSCSI_CB)
+ .machine_config([this](device_t* device) {
+ downcast<nscsi_callback_device&>(*device).bsy_callback().set(*this, FUNC(bbc_scsi_device::bsy_w));
+ downcast<nscsi_callback_device&>(*device).req_callback().set(*this, FUNC(bbc_scsi_device::req_w));
+ });
+}
+
+void bbc_awhd_device::device_add_mconfig(machine_config &config)
+{
+ bbc_scsi_device::device_add_mconfig(config);
+
+ /* Adaptec ACB-4000A */
+ subdevice<nscsi_connector>("scsi:0")->set_default_option("harddisk");
+ subdevice<nscsi_connector>("scsi:0")->set_fixed(true);
+
+ BBC_1MHZBUS_SLOT(config, m_1mhzbus, DERIVED_CLOCK(1, 1), bbc_1mhzbus_devices, nullptr);
+ m_1mhzbus->irq_handler().set(m_1mhzbus, FUNC(bbc_1mhzbus_slot_device::irq_w));
+ m_1mhzbus->nmi_handler().set(m_1mhzbus, FUNC(bbc_1mhzbus_slot_device::nmi_w));
+}
+
+
+//**************************************************************************
+// LIVE DEVICE
+//**************************************************************************
+
+//-------------------------------------------------
+// bbc_scsi_device - constructor
+//-------------------------------------------------
+
+bbc_scsi_device::bbc_scsi_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_1mhzbus_interface(mconfig, *this)
+ , m_scsi(*this, "scsi:7:scsicb")
+{
+}
+
+bbc_scsi_device::bbc_scsi_device(const machine_config& mconfig, const char* tag, device_t* owner, uint32_t clock)
+ : bbc_scsi_device(mconfig, BBC_SCSI, tag, owner, clock)
+{
+}
+
+bbc_awhd_device::bbc_awhd_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
+ : bbc_scsi_device(mconfig, BBC_AWHD, tag, owner, clock)
+ , m_1mhzbus(*this, "1mhzbus")
+{
+}
+
+//-------------------------------------------------
+// device_start - device-specific startup
+//-------------------------------------------------
+
+void bbc_scsi_device::device_start()
+{
+ /* register for save states */
+ save_item(NAME(m_irq_enable));
+ save_item(NAME(m_irq_state));
+}
+
+//**************************************************************************
+// IMPLEMENTATION
+//**************************************************************************
+
+uint8_t bbc_scsi_device::fred_r(offs_t offset)
+{
+ uint8_t data = 0xff;
+
+ switch (offset)
+ {
+ case 0x40:
+ data = m_scsi->read();
+ m_scsi->ack_w(1);
+ break;
+ case 0x41:
+ data = (m_scsi->msg_r() << 0)
+ | (m_scsi->bsy_r() << 1)
+ | (m_irq_state << 4)
+ | (m_scsi->req_r() << 5)
+ | (m_scsi->io_r() << 6)
+ | (m_scsi->cd_r() << 7);
+ break;
+ }
+
+ return data;
+}
+
+void bbc_scsi_device::fred_w(offs_t offset, uint8_t data)
+{
+ switch (offset)
+ {
+ case 0x40:
+ m_scsi->write(data);
+ m_scsi->ack_w(1);
+ break;
+ case 0x42:
+ m_scsi->sel_w(1);
+ break;
+ case 0x43:
+ m_irq_enable = BIT(data, 0);
+ break;
+ }
+}
+
+void bbc_scsi_device::bsy_w(int state)
+{
+ m_scsi->sel_w(0);
+}
+
+void bbc_scsi_device::req_w(int state)
+{
+ m_scsi->ack_w(0);
+
+ m_irq_state = (m_irq_enable && !state) ? 0 : 1;
+ m_slot->irq_w(m_irq_state ? CLEAR_LINE : ASSERT_LINE);
+}
+
+
+uint8_t bbc_awhd_device::fred_r(offs_t offset)
+{
+ uint8_t data = 0xff;
+
+ data &= bbc_scsi_device::fred_r(offset);
+ data &= m_1mhzbus->fred_r(offset);
+
+ return data;
+}
+
+void bbc_awhd_device::fred_w(offs_t offset, uint8_t data)
+{
+ bbc_scsi_device::fred_w(offset, data);
+ m_1mhzbus->fred_w(offset, data);
+}
+
+uint8_t bbc_awhd_device::jim_r(offs_t offset)
+{
+ return m_1mhzbus->jim_r(offset);
+}
+
+void bbc_awhd_device::jim_w(offs_t offset, uint8_t data)
+{
+ m_1mhzbus->jim_w(offset, data);
+}
diff --git a/src/devices/bus/bbc/1mhzbus/scsi.h b/src/devices/bus/bbc/1mhzbus/scsi.h
new file mode 100644
index 00000000000..c3fb0d9e361
--- /dev/null
+++ b/src/devices/bus/bbc/1mhzbus/scsi.h
@@ -0,0 +1,81 @@
+// license:BSD-3-Clause
+// copyright-holders:Nigel Barnes
+/**********************************************************************
+
+ Acorn SCSI Host Adaptor
+
+**********************************************************************/
+
+
+#ifndef MAME_BUS_BBC_1MHZBUS_SCSI_H
+#define MAME_BUS_BBC_1MHZBUS_SCSI_H
+
+#include "1mhzbus.h"
+#include "machine/nscsi_cb.h"
+
+
+//**************************************************************************
+// TYPE DEFINITIONS
+//**************************************************************************
+
+class bbc_scsi_device:
+ public device_t,
+ public device_bbc_1mhzbus_interface
+{
+public:
+ // construction/destruction
+ bbc_scsi_device(const machine_config& mconfig, const char* tag, device_t* owner, uint32_t clock);
+
+ 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);
+
+ // device-level overrides
+ virtual void device_start() override ATTR_COLD;
+
+ // optional information overrides
+ virtual void device_add_mconfig(machine_config& config) override;
+
+ virtual uint8_t fred_r(offs_t offset) override;
+ virtual void fred_w(offs_t offset, uint8_t data) override;
+
+private:
+ required_device<nscsi_callback_device> m_scsi;
+
+ int m_irq_enable;
+ int m_irq_state;
+};
+
+
+// ======================> bbc_awhd_device
+
+class bbc_awhd_device : public bbc_scsi_device
+{
+public:
+ static constexpr feature_type imperfect_features() { return feature::DISK; }
+
+ // construction/destruction
+ bbc_awhd_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 ATTR_COLD;
+
+ 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;
+};
+
+
+// device type definition
+DECLARE_DEVICE_TYPE(BBC_SCSI, bbc_scsi_device);
+DECLARE_DEVICE_TYPE(BBC_AWHD, bbc_awhd_device);
+
+
+#endif /* MAME_BUS_BBC_1MHZBUS_SCSI_H */
diff --git a/src/devices/bus/bbc/1mhzbus/sprite.h b/src/devices/bus/bbc/1mhzbus/sprite.h
index 02b0cff5dc2..914311841cd 100644
--- a/src/devices/bus/bbc/1mhzbus/sprite.h
+++ b/src/devices/bus/bbc/1mhzbus/sprite.h
@@ -28,11 +28,11 @@ public:
protected:
// device-level overrides
- virtual void device_start() override;
- virtual void device_reset() override;
+ virtual void device_start() override ATTR_COLD;
+ virtual void device_reset() override ATTR_COLD;
// optional information overrides
- virtual void device_add_mconfig(machine_config &config) override;
+ virtual void device_add_mconfig(machine_config &config) override ATTR_COLD;
virtual uint8_t fred_r(offs_t offset) override;
virtual void fred_w(offs_t offset, uint8_t data) override;
diff --git a/src/devices/bus/bbc/analogue/analogue.cpp b/src/devices/bus/bbc/analogue/analogue.cpp
index facc1a827bc..ab4da0b90e2 100644
--- a/src/devices/bus/bbc/analogue/analogue.cpp
+++ b/src/devices/bus/bbc/analogue/analogue.cpp
@@ -26,8 +26,8 @@ DEFINE_DEVICE_TYPE(BBC_ANALOGUE_SLOT, bbc_analogue_slot_device, "bbc_analogue_sl
// device_bbc_analogue_interface - constructor
//-------------------------------------------------
-device_bbc_analogue_interface::device_bbc_analogue_interface(const machine_config &mconfig, device_t &device)
- : device_slot_card_interface(mconfig, device)
+device_bbc_analogue_interface::device_bbc_analogue_interface(const machine_config &mconfig, device_t &device) :
+ device_interface(device, "bbcanalogue")
{
m_slot = dynamic_cast<bbc_analogue_slot_device *>(device.owner());
}
@@ -43,33 +43,20 @@ device_bbc_analogue_interface::device_bbc_analogue_interface(const machine_confi
bbc_analogue_slot_device::bbc_analogue_slot_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) :
device_t(mconfig, BBC_ANALOGUE_SLOT, tag, owner, clock),
- device_slot_interface(mconfig, *this),
+ device_single_card_slot_interface<device_bbc_analogue_interface>(mconfig, *this),
m_card(nullptr),
m_lpstb_handler(*this)
{
}
-void bbc_analogue_slot_device::device_validity_check(validity_checker &valid) const
-{
- device_t *const carddev = get_card_device();
- if (carddev && !dynamic_cast<device_bbc_analogue_interface *>(carddev))
- osd_printf_error("Card device %s (%s) does not implement device_bbc_analogue_interface\n", carddev->tag(), carddev->name());
-}
-
//-------------------------------------------------
// device_start - device-specific startup
//-------------------------------------------------
void bbc_analogue_slot_device::device_start()
{
- device_t *const carddev = get_card_device();
- m_card = dynamic_cast<device_bbc_analogue_interface *>(get_card_device());
- if (carddev && !m_card)
- osd_printf_error("Card device %s (%s) does not implement device_bbc_analogue_interface\n", carddev->tag(), carddev->name());
-
- // resolve callbacks
- m_lpstb_handler.resolve_safe();
+ m_card = get_card_device();
}
uint8_t bbc_analogue_slot_device::ch_r(int channel)
@@ -77,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()
@@ -88,12 +75,10 @@ uint8_t bbc_analogue_slot_device::pb_r()
return 0x30;
}
-//-------------------------------------------------
-// device_reset - device-specific reset
-//-------------------------------------------------
-
-void bbc_analogue_slot_device::device_reset()
+void bbc_analogue_slot_device::pb_w(uint8_t data)
{
+ if (m_card)
+ m_card->pb_w(data);
}
@@ -107,7 +92,7 @@ void bbc_analogue_slot_device::device_reset()
#include "bitstik.h"
//#include "lightpen.h"
//#include "micromike.h"
-//#include "quinkey.h"
+#include "quinkey.h"
#include "cfa3000a.h"
@@ -119,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("cfa3000a", CFA3000_ANLG); /* Hanson CFA 3000 Analogue */
+ 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 d8aec89e012..12ad0a4c608 100644
--- a/src/devices/bus/bbc/analogue/analogue.h
+++ b/src/devices/bus/bbc/analogue/analogue.h
@@ -41,7 +41,7 @@
class device_bbc_analogue_interface;
-class bbc_analogue_slot_device : public device_t, public device_slot_interface
+class bbc_analogue_slot_device : public device_t, public device_single_card_slot_interface<device_bbc_analogue_interface>
{
public:
// construction/destruction
@@ -60,16 +60,15 @@ 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
- virtual void device_validity_check(validity_checker &valid) const override;
- virtual void device_start() override;
- virtual void device_reset() override;
+ // device_t overrides
+ virtual void device_start() override ATTR_COLD;
device_bbc_analogue_interface *m_card;
@@ -80,11 +79,12 @@ private:
// ======================> device_bbc_analogue_interface
-class device_bbc_analogue_interface : public device_slot_card_interface
+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 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/bitstik.h b/src/devices/bus/bbc/analogue/bitstik.h
index 494be5dec69..c5986e39dd1 100644
--- a/src/devices/bus/bbc/analogue/bitstik.h
+++ b/src/devices/bus/bbc/analogue/bitstik.h
@@ -34,10 +34,10 @@ protected:
bbc_bitstik_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_start() override ATTR_COLD;
// optional information overrides
- virtual ioport_constructor device_input_ports() const override;
+ virtual ioport_constructor device_input_ports() const override ATTR_COLD;
virtual uint8_t ch_r(int channel) override;
virtual uint8_t pb_r() override;
@@ -53,7 +53,7 @@ public:
bbc_bitstik1_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;
+ virtual const tiny_rom_entry *device_rom_region() const override ATTR_COLD;
};
class bbc_bitstik2_device : public bbc_bitstik_device
@@ -62,7 +62,7 @@ public:
bbc_bitstik2_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;
+ virtual const tiny_rom_entry *device_rom_region() const override ATTR_COLD;
};
// device type definition
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/cfa3000a.h b/src/devices/bus/bbc/analogue/cfa3000a.h
index 8948ca586be..3e2ddb43ccc 100644
--- a/src/devices/bus/bbc/analogue/cfa3000a.h
+++ b/src/devices/bus/bbc/analogue/cfa3000a.h
@@ -30,11 +30,11 @@ public:
protected:
// device-level overrides
- virtual void device_start() override;
- virtual void device_reset() override;
+ virtual void device_start() override ATTR_COLD;
+ virtual void device_reset() override ATTR_COLD;
// optional information overrides
- virtual ioport_constructor device_input_ports() const override;
+ virtual ioport_constructor device_input_ports() const override ATTR_COLD;
virtual uint8_t ch_r(int channel) override;
virtual uint8_t pb_r() override;
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/joystick.h b/src/devices/bus/bbc/analogue/joystick.h
index 887e87c74d7..5f4572a7cf6 100644
--- a/src/devices/bus/bbc/analogue/joystick.h
+++ b/src/devices/bus/bbc/analogue/joystick.h
@@ -29,8 +29,8 @@ protected:
bbc_joystick_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_start() override ATTR_COLD;
+ virtual void device_reset() override ATTR_COLD;
virtual uint8_t ch_r(int channel) override;
virtual uint8_t pb_r() override;
@@ -45,7 +45,7 @@ class bbc_acornjoy_device : public bbc_joystick_device
public:
bbc_acornjoy_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
- virtual ioport_constructor device_input_ports() const override;
+ virtual ioport_constructor device_input_ports() const override ATTR_COLD;
};
class bbc_voltmace3b_device : public bbc_joystick_device
@@ -53,7 +53,7 @@ class bbc_voltmace3b_device : public bbc_joystick_device
public:
bbc_voltmace3b_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
- virtual ioport_constructor device_input_ports() const override;
+ virtual ioport_constructor device_input_ports() const override ATTR_COLD;
};
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..f88df64ec2c
--- /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 ATTR_COLD;
+
+ // optional information overrides
+ virtual void device_add_mconfig(machine_config &config) override ATTR_COLD;
+
+ 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 ATTR_COLD;
+
+ 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 ATTR_COLD;
+
+ // optional information overrides
+ virtual ioport_constructor device_input_ports() const override ATTR_COLD;
+
+ 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/click.cpp b/src/devices/bus/bbc/cart/click.cpp
new file mode 100644
index 00000000000..beaaf1f21b4
--- /dev/null
+++ b/src/devices/bus/bbc/cart/click.cpp
@@ -0,0 +1,113 @@
+// license:BSD-3-Clause
+// copyright-holders:Nigel Barnes
+/***************************************************************************
+
+ Slogger Click cartridge emulation
+
+ http://chrisacorns.computinghistory.org.uk/8bit_Upgrades/Slogger_Click.html
+
+ The Master version of the Click cartridge differs from the Electron
+ version:
+ Master 128 Electron
+ ROM 16K 32K
+ RAM (battery) 8K 32K
+
+ The data lines D1 and D2 are swapped between edge connector and ROM/RAM.
+
+***************************************************************************/
+
+#include "emu.h"
+#include "click.h"
+
+
+//**************************************************************************
+// DEVICE DEFINITIONS
+//**************************************************************************
+
+DEFINE_DEVICE_TYPE(BBC_CLICK, bbc_click_device, "bbc_click", "Slogger Click (Master 128) cartridge")
+
+
+//-------------------------------------------------
+// INPUT_PORTS( clickm )
+//-------------------------------------------------
+
+INPUT_PORTS_START(clickm)
+ PORT_START("BUTTON")
+ PORT_BIT(0x01, IP_ACTIVE_LOW, IPT_BUTTON1) PORT_NAME("Click") PORT_CODE(KEYCODE_HOME) PORT_CHANGED_MEMBER(DEVICE_SELF, FUNC(bbc_click_device::click_button), 0)
+INPUT_PORTS_END
+
+
+//-------------------------------------------------
+// input_ports - device-specific input ports
+//-------------------------------------------------
+
+ioport_constructor bbc_click_device::device_input_ports() const
+{
+ return INPUT_PORTS_NAME(clickm);
+}
+
+//**************************************************************************
+// LIVE DEVICE
+//**************************************************************************
+
+//-------------------------------------------------
+// bbc_click_device - constructor
+//-------------------------------------------------
+
+bbc_click_device::bbc_click_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
+ : device_t(mconfig, BBC_CLICK, tag, owner, clock)
+ , device_bbc_cart_interface(mconfig, *this)
+{
+}
+
+//-------------------------------------------------
+// device_start - device-specific startup
+//-------------------------------------------------
+
+void bbc_click_device::device_start()
+{
+}
+
+
+//-------------------------------------------------
+// read - cartridge data read
+//-------------------------------------------------
+
+uint8_t bbc_click_device::read(offs_t offset, int infc, int infd, int romqa, int oe, int oe2)
+{
+ uint8_t data = 0xff;
+
+ if (oe)
+ {
+ if (offset & 0x2000)
+ {
+ data = m_nvram[offset & 0x1fff];
+ }
+ else
+ {
+ data = m_rom[(offset & 0x1fff) | (romqa << 13)];
+ }
+ }
+
+ return bitswap<8>(data, 7, 6, 5, 4, 3, 1, 2, 0);
+}
+
+//-------------------------------------------------
+// write - cartridge data write
+//-------------------------------------------------
+
+void bbc_click_device::write(offs_t offset, uint8_t data, int infc, int infd, int romqa, int oe, int oe2)
+{
+ if (oe)
+ {
+ if (offset & 0x2000)
+ {
+ m_nvram[offset & 0x1fff] = bitswap<8>(data, 7, 6, 5, 4, 3, 1, 2, 0);
+ }
+ }
+}
+
+INPUT_CHANGED_MEMBER(bbc_click_device::click_button)
+{
+ m_slot->irq_w(!newval);
+}
diff --git a/src/devices/bus/bbc/cart/click.h b/src/devices/bus/bbc/cart/click.h
new file mode 100644
index 00000000000..d2102d90543
--- /dev/null
+++ b/src/devices/bus/bbc/cart/click.h
@@ -0,0 +1,47 @@
+// license:BSD-3-Clause
+// copyright-holders:Nigel Barnes
+/***************************************************************************
+
+ Slogger Click cartridge emulation
+
+ http://chrisacorns.computinghistory.org.uk/8bit_Upgrades/Slogger_Click.html
+
+***************************************************************************/
+
+#ifndef MAME_BUS_BBC_CART_CLICK_H
+#define MAME_BUS_BBC_CART_CLICK_H
+
+#pragma once
+
+#include "slot.h"
+
+
+//**************************************************************************
+// TYPE DEFINITIONS
+//**************************************************************************
+
+// ======================> bbc_click_device
+
+class bbc_click_device : public device_t, public device_bbc_cart_interface
+{
+public:
+ // construction/destruction
+ bbc_click_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
+
+ DECLARE_INPUT_CHANGED_MEMBER(click_button);
+
+protected:
+ // device-level overrides
+ virtual ioport_constructor device_input_ports() const override ATTR_COLD;
+
+ virtual void device_start() override ATTR_COLD;
+
+ // bbc_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_CLICK, bbc_click_device)
+
+#endif // MAME_BUS_BBC_CART_CLICK_H
diff --git a/src/devices/bus/bbc/cart/mastersd.cpp b/src/devices/bus/bbc/cart/mastersd.cpp
new file mode 100644
index 00000000000..94d5428386f
--- /dev/null
+++ b/src/devices/bus/bbc/cart/mastersd.cpp
@@ -0,0 +1,309 @@
+// license:BSD-3-Clause
+// copyright-holders:Nigel Barnes
+/**********************************************************************
+
+ MasterSD BBC Master SD Cartridge
+
+ http://ramtop-retro.uk/mastersd.html
+
+**********************************************************************/
+
+
+#include "emu.h"
+#include "mastersd.h"
+
+#include "machine/spi_sdcard.h"
+
+
+namespace {
+
+//**************************************************************************
+// TYPE DEFINITIONS
+//**************************************************************************
+
+// ======================> bbc_mastersd_device
+
+class bbc_mastersd_device : public device_t, public device_bbc_cart_interface
+{
+public:
+ // construction/destruction
+ 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_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_bbc_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;
+
+ TIMER_CALLBACK_MEMBER(spi_clock);
+
+ required_device<spi_sdcard_device> m_sdcard;
+
+ emu_timer *m_spi_clock;
+ bool m_spi_clock_state;
+ bool m_spi_clock_sysclk;
+ int m_spi_clock_cycles;
+ int m_in_bit;
+ uint8_t m_in_latch;
+ uint8_t m_out_latch;
+
+ std::unique_ptr<uint8_t[]> m_ram;
+};
+
+
+// ======================> 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:
+ // device_bbc_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;
+};
+
+
+//-------------------------------------------------
+// device_add_mconfig - add device configuration
+//-------------------------------------------------
+
+void bbc_mastersd_device::device_add_mconfig(machine_config &config)
+{
+ SPI_SDCARD(config, m_sdcard, 0);
+ m_sdcard->set_prefer_sdhc();
+ m_sdcard->spi_miso_callback().set([this](int state) { m_in_bit = state; });
+}
+
+//**************************************************************************
+// LIVE DEVICE
+//**************************************************************************
+
+//-------------------------------------------------
+// bbc_mastersd_device - constructor
+//-------------------------------------------------
+
+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)
+ , m_spi_clock_sysclk(false)
+ , m_spi_clock_cycles(0)
+{
+}
+
+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
+//-------------------------------------------------
+
+void bbc_mastersd_device::device_start()
+{
+ m_ram = make_unique_clear<uint8_t[]>(0x8000);
+
+ m_spi_clock = timer_alloc(FUNC(bbc_mastersd_device::spi_clock), this);
+
+ save_pointer(NAME(m_ram), 0x8000);
+ save_item(NAME(m_spi_clock_state));
+ save_item(NAME(m_spi_clock_sysclk));
+ save_item(NAME(m_spi_clock_cycles));
+ save_item(NAME(m_in_bit));
+ save_item(NAME(m_in_latch));
+ save_item(NAME(m_out_latch));
+}
+
+//-------------------------------------------------
+// device_reset - device-specific startup
+//-------------------------------------------------
+
+void bbc_mastersd_device::device_reset()
+{
+ m_spi_clock->adjust(attotime::never);
+ m_spi_clock_cycles = 0;
+ m_spi_clock_state = false;
+}
+
+
+//-------------------------------------------------
+// read - cartridge data read
+//-------------------------------------------------
+
+uint8_t bbc_mastersd_device::read(offs_t offset, int infc, int infd, int romqa, int oe, int oe2)
+{
+ uint8_t data = 0xff;
+
+ if (oe)
+ {
+ if (offset >= 0x3600 || romqa == 1)
+ {
+ data = m_ram[(offset & 0x3fff) | (romqa << 14)];
+ }
+ else if (offset == 0x35fe) // SPI controller data port
+ {
+ data = m_in_latch;
+ }
+ else if (offset == 0x35ff) // SPI controller status register
+ {
+ data = m_spi_clock_cycles > 0 ? 0x01 : 0x00;
+ }
+ else
+ {
+ data = m_rom[offset & 0x3fff];
+ }
+ }
+
+ 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
+//-------------------------------------------------
+
+void bbc_mastersd_device::write(offs_t offset, uint8_t data, int infc, int infd, int romqa, int oe, int oe2)
+{
+ if (oe)
+ {
+ if (offset >= 0x3600 || romqa == 1)
+ {
+ m_ram[(offset & 0x3fff) | (romqa << 14)] = data;
+ }
+ else if (offset == 0x35fe) // SPI controller data port
+ {
+ m_out_latch = data;
+ m_spi_clock_cycles = 8;
+
+ if (m_spi_clock_sysclk) // TODO: confirm fast/slow clock and 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));
+ }
+ else if (offset == 0x35ff) // SPI controller clock register
+ {
+ m_spi_clock_sysclk = bool(BIT(data, 0));
+ }
+ }
+}
+
+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)
+{
+ if (m_spi_clock_cycles > 0)
+ {
+ m_sdcard->spi_ss_w(1);
+
+ if (m_spi_clock_state)
+ {
+ m_in_latch <<= 1;
+ m_in_latch &= ~0x01;
+ m_in_latch |= m_in_bit;
+
+ m_sdcard->spi_clock_w(1);
+
+ m_spi_clock_cycles--;
+ }
+ else
+ {
+ m_sdcard->spi_mosi_w(BIT(m_out_latch, 7));
+ m_sdcard->spi_clock_w(0);
+
+ m_out_latch <<= 1;
+ }
+
+ m_spi_clock_state = !m_spi_clock_state;
+ }
+ else
+ {
+ m_spi_clock_state = false;
+ m_spi_clock->adjust(attotime::never);
+ }
+}
+
+} // anonymous namespace
+
+
+//**************************************************************************
+// DEVICE DEFINITIONS
+//**************************************************************************
+
+DEFINE_DEVICE_TYPE_PRIVATE(BBC_MASTERSD, device_bbc_cart_interface, bbc_mastersd_device, "bbc_mastersd", "MasterSD BBC Master SD Cartridge")
+DEFINE_DEVICE_TYPE_PRIVATE(BBC_MASTERSDR2, device_bbc_cart_interface, bbc_mastersdr2_device, "bbc_mastersdr2", "MasterSD R2 BBC Master SD Cartridge")
diff --git a/src/devices/bus/bbc/cart/mastersd.h b/src/devices/bus/bbc/cart/mastersd.h
new file mode 100644
index 00000000000..39a2a1ed7d7
--- /dev/null
+++ b/src/devices/bus/bbc/cart/mastersd.h
@@ -0,0 +1,20 @@
+// license:BSD-3-Clause
+// copyright-holders:Nigel Barnes
+/**********************************************************************
+
+ MasterSD BBC Master SD Cartridge
+
+**********************************************************************/
+
+#ifndef MAME_BUS_BBC_CART_MASTERSD_H
+#define MAME_BUS_BBC_CART_MASTERSD_H
+
+#pragma once
+
+#include "slot.h"
+
+
+DECLARE_DEVICE_TYPE(BBC_MASTERSD, device_bbc_cart_interface)
+DECLARE_DEVICE_TYPE(BBC_MASTERSDR2, device_bbc_cart_interface)
+
+#endif // MAME_BUS_BBC_CART_MASTERSD_H
diff --git a/src/devices/bus/bbc/cart/mega256.cpp b/src/devices/bus/bbc/cart/mega256.cpp
new file mode 100644
index 00000000000..f0348df2e74
--- /dev/null
+++ b/src/devices/bus/bbc/cart/mega256.cpp
@@ -0,0 +1,97 @@
+// license:BSD-3-Clause
+// copyright-holders:Nigel Barnes
+/***************************************************************************
+
+ Solidisk Mega 256 cartridge emulation
+
+ http://chrisacorns.computinghistory.org.uk/8bit_Upgrades/Solidisk_Mega256.html
+
+***************************************************************************/
+
+#include "emu.h"
+#include "mega256.h"
+
+
+//**************************************************************************
+// DEVICE DEFINITIONS
+//**************************************************************************
+
+DEFINE_DEVICE_TYPE(BBC_MEGA256, bbc_mega256_device, "bbc_mega256", "Solidisk Mega 256 cartridge")
+
+
+//**************************************************************************
+// LIVE DEVICE
+//**************************************************************************
+
+//-------------------------------------------------
+// bbc_mega256_device - constructor
+//-------------------------------------------------
+
+bbc_mega256_device::bbc_mega256_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
+ : device_t(mconfig, BBC_MEGA256, tag, owner, clock)
+ , device_bbc_cart_interface(mconfig, *this)
+ , m_page(0)
+{
+}
+
+//-------------------------------------------------
+// device_start - device-specific startup
+//-------------------------------------------------
+
+void bbc_mega256_device::device_start()
+{
+ // register for save states
+ save_item(NAME(m_page));
+}
+
+//-------------------------------------------------
+// device_reset - device-specific reset
+//-------------------------------------------------
+
+void bbc_mega256_device::device_reset()
+{
+ m_page = 0x00;
+}
+
+//-------------------------------------------------
+// read - cartridge data read
+//-------------------------------------------------
+
+uint8_t bbc_mega256_device::read(offs_t offset, int infc, int infd, int romqa, int oe, int oe2)
+{
+ uint8_t data = 0xff;
+
+ if (oe)
+ {
+ if (romqa)
+ {
+ data = m_rom[offset & 0x1fff];
+ }
+ else
+ {
+ data = m_ram[(offset & 0x3fff) | (m_page << 14)];
+ }
+ }
+
+ return data;
+}
+
+//-------------------------------------------------
+// write - cartridge data write
+//-------------------------------------------------
+
+void bbc_mega256_device::write(offs_t offset, uint8_t data, int infc, int infd, int romqa, int oe, int oe2)
+{
+ if (oe)
+ {
+ if (romqa)
+ {
+ // Not known whether this latch is fully decoded.
+ if (offset == 0x3fff) m_page = data & 0x0f;
+ }
+ else
+ {
+ m_ram[(offset & 0x3fff) | (m_page << 14)] = data;
+ }
+ }
+}
diff --git a/src/devices/bus/bbc/cart/mega256.h b/src/devices/bus/bbc/cart/mega256.h
new file mode 100644
index 00000000000..394c86f3e9e
--- /dev/null
+++ b/src/devices/bus/bbc/cart/mega256.h
@@ -0,0 +1,47 @@
+// license:BSD-3-Clause
+// copyright-holders:Nigel Barnes
+/***************************************************************************
+
+ Solidisk Mega 256 cartridge emulation
+
+ http://chrisacorns.computinghistory.org.uk/8bit_Upgrades/Solidisk_Mega256.html
+
+***************************************************************************/
+
+#ifndef MAME_BUS_BBC_CART_MEGA256_H
+#define MAME_BUS_BBC_CART_MEGA256_H
+
+#pragma once
+
+#include "slot.h"
+
+
+//**************************************************************************
+// TYPE DEFINITIONS
+//**************************************************************************
+
+// ======================> bbc_mega256_device
+
+class bbc_mega256_device : public device_t, public device_bbc_cart_interface
+{
+public:
+ // construction/destruction
+ bbc_mega256_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
+
+protected:
+ // device-level overrides
+ virtual void device_start() override ATTR_COLD;
+ virtual void device_reset() override ATTR_COLD;
+
+ // bbc_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;
+
+private:
+ uint8_t m_page;
+};
+
+// device type definition
+DECLARE_DEVICE_TYPE(BBC_MEGA256, bbc_mega256_device)
+
+#endif // MAME_BUS_BBC_CART_MEGA256_H
diff --git a/src/devices/bus/bbc/cart/mr8000.cpp b/src/devices/bus/bbc/cart/mr8000.cpp
new file mode 100644
index 00000000000..a039936f23a
--- /dev/null
+++ b/src/devices/bus/bbc/cart/mr8000.cpp
@@ -0,0 +1,102 @@
+// license:BSD-3-Clause
+// copyright-holders:Nigel Barnes
+/***************************************************************************
+
+ MR8000 Master RAM Cartridge emulation
+
+***************************************************************************/
+
+#include "emu.h"
+#include "mr8000.h"
+
+
+//**************************************************************************
+// DEVICE DEFINITIONS
+//**************************************************************************
+
+DEFINE_DEVICE_TYPE(BBC_MR8000, bbc_mr8000_device, "bbc_mr8000", "MR8000 Master RAM Cartridge")
+
+
+//-------------------------------------------------
+// INPUT_PORTS( mr8000 )
+//-------------------------------------------------
+
+INPUT_PORTS_START(mr8000)
+ PORT_START("SWITCH")
+ PORT_CONFNAME(0x03, 0x00, "ROM Choice")
+ PORT_CONFSETTING(0x00, "A (lower banks)")
+ PORT_CONFSETTING(0x01, "B (upper banks)")
+ PORT_CONFSETTING(0x02, "Off (disabled)")
+
+ PORT_CONFNAME(0x04, 0x00, "Write Protect")
+ PORT_CONFSETTING(0x00, "On (read only")
+ PORT_CONFSETTING(0x04, "Off (read and write)")
+INPUT_PORTS_END
+
+
+//-------------------------------------------------
+// input_ports - device-specific input ports
+//-------------------------------------------------
+
+ioport_constructor bbc_mr8000_device::device_input_ports() const
+{
+ return INPUT_PORTS_NAME(mr8000);
+}
+
+//**************************************************************************
+// LIVE DEVICE
+//**************************************************************************
+
+//-------------------------------------------------
+// bbc_mr8000_device - constructor
+//-------------------------------------------------
+
+bbc_mr8000_device::bbc_mr8000_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
+ : device_t(mconfig, BBC_MR8000, tag, owner, clock)
+ , device_bbc_cart_interface(mconfig, *this)
+ , m_switch(*this, "SWITCH")
+{
+}
+
+//-------------------------------------------------
+// device_start - device-specific startup
+//-------------------------------------------------
+
+void bbc_mr8000_device::device_start()
+{
+}
+
+
+//-------------------------------------------------
+// read - cartridge data read
+//-------------------------------------------------
+
+uint8_t bbc_mr8000_device::read(offs_t offset, int infc, int infd, int romqa, int oe, int oe2)
+{
+ uint8_t data = 0x00;
+ int bank = BIT(m_switch->read(), 0);
+
+ if (oe && !BIT(m_switch->read(), 1))
+ {
+ data = m_nvram[offset | (bank << 15) | (romqa << 14)];
+ }
+
+ return data;
+}
+
+//-------------------------------------------------
+// write - cartridge data write
+//-------------------------------------------------
+
+void bbc_mr8000_device::write(offs_t offset, uint8_t data, int infc, int infd, int romqa, int oe, int oe2)
+{
+ int bank = BIT(m_switch->read(), 0);
+
+ if (oe && !BIT(m_switch->read(), 1))
+ {
+ if (BIT(m_switch->read(), 2))
+ {
+ m_nvram[offset | (bank << 15) | (romqa << 14)] = data;
+ }
+ }
+}
diff --git a/src/devices/bus/bbc/cart/mr8000.h b/src/devices/bus/bbc/cart/mr8000.h
new file mode 100644
index 00000000000..4d581423b48
--- /dev/null
+++ b/src/devices/bus/bbc/cart/mr8000.h
@@ -0,0 +1,46 @@
+// license:BSD-3-Clause
+// copyright-holders:Nigel Barnes
+/***************************************************************************
+
+ MR8000 Master RAM Cartridge emulation
+
+***************************************************************************/
+
+#ifndef MAME_BUS_BBC_CART_MR8000_H
+#define MAME_BUS_BBC_CART_MR8000_H
+
+#pragma once
+
+#include "slot.h"
+
+
+//**************************************************************************
+// TYPE DEFINITIONS
+//**************************************************************************
+
+// ======================> bbc_mr8000_device
+
+class bbc_mr8000_device : public device_t, public device_bbc_cart_interface
+{
+public:
+ // construction/destruction
+ bbc_mr8000_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
+
+protected:
+ // device-level overrides
+ virtual ioport_constructor device_input_ports() const override ATTR_COLD;
+
+ virtual void device_start() override ATTR_COLD;
+
+ // bbc_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;
+
+private:
+ required_ioport m_switch;
+};
+
+// device type definition
+DECLARE_DEVICE_TYPE(BBC_MR8000, bbc_mr8000_device)
+
+#endif // MAME_BUS_BBC_CART_MR8000_H
diff --git a/src/devices/bus/bbc/cart/msc.cpp b/src/devices/bus/bbc/cart/msc.cpp
new file mode 100644
index 00000000000..c758afa6d30
--- /dev/null
+++ b/src/devices/bus/bbc/cart/msc.cpp
@@ -0,0 +1,104 @@
+// license:BSD-3-Clause
+// copyright-holders:Nigel Barnes
+/***************************************************************************
+
+ Master Smart Cartridge emulation
+
+***************************************************************************/
+
+#include "emu.h"
+#include "msc.h"
+
+
+//**************************************************************************
+// DEVICE DEFINITIONS
+//**************************************************************************
+
+DEFINE_DEVICE_TYPE(BBC_MSC, bbc_msc_device, "bbc_msc", "Master Smart Cartridge")
+
+
+//-------------------------------------------------
+// INPUT_PORTS( msc )
+//-------------------------------------------------
+
+INPUT_PORTS_START(msc)
+ PORT_START("BUTTON")
+ PORT_BIT(0x01, IP_ACTIVE_LOW, IPT_BUTTON1) PORT_NAME("Activate") PORT_CODE(KEYCODE_HOME) PORT_CHANGED_MEMBER(DEVICE_SELF, FUNC(bbc_msc_device::activate), 0)
+INPUT_PORTS_END
+
+
+//-------------------------------------------------
+// input_ports - device-specific input ports
+//-------------------------------------------------
+
+ioport_constructor bbc_msc_device::device_input_ports() const
+{
+ return INPUT_PORTS_NAME(msc);
+}
+
+//**************************************************************************
+// LIVE DEVICE
+//**************************************************************************
+
+//-------------------------------------------------
+// bbc_msc_device - constructor
+//-------------------------------------------------
+
+bbc_msc_device::bbc_msc_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
+ : device_t(mconfig, BBC_MSC, tag, owner, clock)
+ , device_bbc_cart_interface(mconfig, *this)
+ , m_button(*this, "BUTTON")
+{
+}
+
+//-------------------------------------------------
+// device_start - device-specific startup
+//-------------------------------------------------
+
+void bbc_msc_device::device_start()
+{
+}
+
+
+//-------------------------------------------------
+// read - cartridge data read
+//-------------------------------------------------
+
+uint8_t bbc_msc_device::read(offs_t offset, int infc, int infd, int romqa, int oe, int oe2)
+{
+ uint8_t data = 0xff;
+
+ if (oe & !romqa)
+ {
+ if (offset & 0x2000)
+ {
+ data = m_ram[offset & 0x7ff];
+ }
+ else
+ {
+ data = m_rom[(offset & 0x1fff) | (m_button->read() << 13)];
+ }
+ }
+
+ return data;
+}
+
+//-------------------------------------------------
+// write - cartridge data write
+//-------------------------------------------------
+
+void bbc_msc_device::write(offs_t offset, uint8_t data, int infc, int infd, int romqa, int oe, int oe2)
+{
+ if (oe & !romqa)
+ {
+ if (offset & 0x2000)
+ {
+ m_ram[offset & 0x7ff] = data;
+ }
+ }
+}
+
+INPUT_CHANGED_MEMBER(bbc_msc_device::activate)
+{
+ m_slot->irq_w(!newval);
+}
diff --git a/src/devices/bus/bbc/cart/msc.h b/src/devices/bus/bbc/cart/msc.h
new file mode 100644
index 00000000000..0f7cecb096e
--- /dev/null
+++ b/src/devices/bus/bbc/cart/msc.h
@@ -0,0 +1,48 @@
+// license:BSD-3-Clause
+// copyright-holders:Nigel Barnes
+/***************************************************************************
+
+ Master Smart Cartridge emulation
+
+***************************************************************************/
+
+#ifndef MAME_BUS_BBC_CART_MSC_H
+#define MAME_BUS_BBC_CART_MSC_H
+
+#pragma once
+
+#include "slot.h"
+
+
+//**************************************************************************
+// TYPE DEFINITIONS
+//**************************************************************************
+
+// ======================> bbc_msc_device
+
+class bbc_msc_device : public device_t, public device_bbc_cart_interface
+{
+public:
+ // construction/destruction
+ bbc_msc_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
+
+ DECLARE_INPUT_CHANGED_MEMBER(activate);
+
+protected:
+ // device-level overrides
+ virtual ioport_constructor device_input_ports() const override ATTR_COLD;
+
+ virtual void device_start() override ATTR_COLD;
+
+ // bbc_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;
+
+private:
+ required_ioport m_button;
+};
+
+// device type definition
+DECLARE_DEVICE_TYPE(BBC_MSC, bbc_msc_device)
+
+#endif // MAME_BUS_BBC_CART_MSC_H
diff --git a/src/devices/bus/bbc/cart/slot.cpp b/src/devices/bus/bbc/cart/slot.cpp
new file mode 100644
index 00000000000..91ab2779842
--- /dev/null
+++ b/src/devices/bus/bbc/cart/slot.cpp
@@ -0,0 +1,82 @@
+// license:BSD-3-Clause
+// copyright-holders:Nigel Barnes
+/***********************************************************************************************************
+
+ BBC Master Cartridge slot emulation
+
+ ***********************************************************************************************************/
+
+
+#include "emu.h"
+#include "slot.h"
+
+//**************************************************************************
+// GLOBAL VARIABLES
+//**************************************************************************
+
+DEFINE_DEVICE_TYPE(BBCM_CARTSLOT, bbc_cartslot_device, "bbc_cartslot", "BBC Master Cartridge Slot")
+
+
+//**************************************************************************
+// DEVICE ELECTRON_CARTSLOT CARD INTERFACE
+//**************************************************************************
+
+//-------------------------------------------------
+// device_bbc_cart_interface - constructor
+//-------------------------------------------------
+
+device_bbc_cart_interface::device_bbc_cart_interface(const machine_config &mconfig, device_t &device)
+ : device_electron_cart_interface(mconfig, device)
+{
+ m_slot = dynamic_cast<bbc_cartslot_device *>(device.owner());
+}
+
+
+//-------------------------------------------------
+// ~device_bbc_cart_interface - destructor
+//-------------------------------------------------
+
+device_bbc_cart_interface::~device_bbc_cart_interface()
+{
+}
+
+
+//**************************************************************************
+// LIVE DEVICE
+//**************************************************************************
+
+//-------------------------------------------------
+// bbc_cartslot_device - constructor
+//-------------------------------------------------
+bbc_cartslot_device::bbc_cartslot_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) :
+ electron_cartslot_device(mconfig, BBCM_CARTSLOT, tag, owner, clock)
+{
+}
+
+
+//-------------------------------------------------
+// SLOT_INTERFACE( bbcm_cart )
+//-------------------------------------------------
+
+#include "bus/electron/cart/std.h"
+#include "bus/electron/cart/abr.h"
+#include "bus/electron/cart/aqr.h"
+#include "click.h"
+#include "mastersd.h"
+#include "mega256.h"
+#include "mr8000.h"
+#include "msc.h"
+
+
+void bbcm_cart(device_slot_interface &device)
+{
+ device.option_add_internal("std", ELECTRON_STDCART);
+ device.option_add_internal("abr", ELECTRON_ABR);
+ 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/cart/slot.h b/src/devices/bus/bbc/cart/slot.h
new file mode 100644
index 00000000000..69e5b5f69a5
--- /dev/null
+++ b/src/devices/bus/bbc/cart/slot.h
@@ -0,0 +1,161 @@
+// license:BSD-3-Clause
+// copyright-holders:Nigel Barnes
+/**********************************************************************
+
+ BBC Master Cartridge slot emulation
+
+**********************************************************************
+
+ Pinout:
+ A B
+ +5V 1 1 +5
+ nOE 2 2 A10
+ nRST 3 3 D3
+ CSRW 4 4 A11
+ A8 5 5 A9
+ A13 6 6 D7
+ A12 7 7 D6
+ PHI2 8 8 D5
+ -5V 9 9 D4
+CSYNC/MADET 10 10 LPSTB
+ R/W 11 11 BA7
+ nNMI 12 12 BA6
+ nIRQ 13 13 BA5
+ nINFC 14 14 BA4
+ nINFD 15 15 BA3
+ ROMQA 16 16 BA2
+ Clock 17 17 BA1
+ nCRTCRST 18 18 BA0
+ ADOUT 19 19 D0
+ AGND 20 20 D2
+ NC 21 21 D1
+ 0V 22 22 0V
+
+ Signal Definitions:
+
+ SIDE 'A'
+ 1 +5V - Power supply. This is the system logic supply rail.
+ 2 n0E - Output Enable : Input with CMOS levels. This is an active low signal during the PH12
+ period of the system clock.
+ 3 nRST - System Reset : Input with CMOS levels. This signal is active low during system reset.
+ 4 CSRW - Changes function according to the memory region that the CPU is addressing.
+ During accesses to &FC00 through &FEFF it is equivalent to the CPU Read/Write line
+ during nPH12. For all other accesses it is an Active High chip select for memory devices.
+ 5 A8 - Address line 8 : Input with TTL levels
+ 6 A13 - Address line 13 : Input with TTL levels
+ 7 A12 - Address line 12 : Input with TTL levels
+ 8 PH12 - CPU clock : Input with CMOS levels
+ This input is the host computer PH12out.
+ 9 -5V - The negative supply voltage.
+ 10 MADET - There are two functions dependent upon link 12 in the computer:
+ E/nB - the default function. It enables cartridges to know which machine they are plugged
+ into. It is connected to 0V in the Master.
+ CSYNC - Composite Sync. Input from TTL levels.
+ System Vertical & Horizontal sync is made available for Genlock use.
+ 11 R/W - Data Direction Control. Input from TTL levels
+ 12 nNMI - Non maskable interrupt : Open collector output
+ This signal is connected to the system NMI line. It is active low.
+ 13 nIRQ - Interrupt request : Open collector output
+ This signal is connected to the system IRQ line. It is active low.
+ 14 nINFC - Internal Page &FC : When bit IFJ in the Master ACCON register (via &FE34) is set, all accesses to
+ &FC00 through &FCFF will cause this select to become active. : TTL active low
+ 15 nINFD - Internal page &FD : When bit IFJ in the Master ACCON register (via &FE34) is set, all accesses to
+ &FD00 through &FDFF will cause this select to become active. : TTL active low
+ 16 ROMQA - Memory paging select : Input with TTL levels
+ This is the least significant bit of the ROM select latch located at &FE30 in the Master.
+ 17 Clock - Links on the computer select one of two functions:
+ a) 16Mhz Output to computer (Link DB only).
+ b) 8 Mhz Input to cartridge (Link CD in addition to AB).
+ 18 nCRTCRST - nCRTCRST is an Active Low Output signal of the system CRTC reset input. It is
+ provided for Genlock use.
+ 19 ADOUT - System audio output
+ 20 AGND - Audio Ground
+ 21 ADIN - Cartridge audio output
+ 22 0V - Zero volts
+
+ SIDE 'B'
+ 1 +5V - Power supply. This is the system logic supply rail.
+ 2 A10 - Address line 10 : Input with TTL levels
+ 3 D3 - Data bus line 3 : Input/Output with TTL levels
+ 4 A11 - Address line 11 : Input with TTL levels
+ 5 A9 - Address line 9 : Input with TTL levels
+ 6 D7 - Most significant data bus line : Input/Output with TTL levels
+ 7 D6 - Data bus line 6 : Input/Output with TTL levels
+ 8 D5 - Data bus line 5 : Input/Output with TTL levels
+ 9 D4 - Data bus line 4 : Input/Output with TTL levels
+ 10 LPSTB - With link 21 removed in the computer, this pin provides a connection between the
+ two cartridges. With the link in place, the pin forms a connection to a pull-up resistor in the
+ computer to +5V. The connection is also made to the CRTC Light-Pen Strobe and interrupt
+ structure
+ 11 BA7 - Buffered address line 7 : Input with TTL levels
+ 12 BA6 - Buffered address line 6 : Input with TTL levels
+ 13 BA5 - Buffered address line 5 : Input with TTL levels
+ 14 BA4 - Buffered address line 4 : Input with TTL levels
+ 15 BA3 - Buffered address line 3 : Input with TTL levels
+ 16 BA2 - Buffered address line 2 : Input with TTL levels
+ 17 BA1 - Buffered address line 1 : Input with TTL levels
+ 18 BA0 - Buffered address line 0 : Input with TTL levels
+ 19 D0 - Data bus line 0 : Input/Output with TTL levels
+ 20 D2 - Data bus line 2 : Input/Output with TTL levels
+ 21 D1 - Data bus line 1 : Input/Output with TTL levels
+ 22 0V - Zero volts.
+
+**********************************************************************/
+#ifndef MAME_BUS_BBC_CART_SLOT_H
+#define MAME_BUS_BBC_CART_SLOT_H
+
+#pragma once
+
+#include "bus/electron/cart/slot.h"
+
+
+
+//**************************************************************************
+// TYPE DEFINITIONS
+//**************************************************************************
+
+// ======================> bbc_cartslot_device
+
+class device_bbc_cart_interface;
+
+class bbc_cartslot_device : public electron_cartslot_device
+{
+public:
+ // construction/destruction
+ template <typename T>
+ bbc_cartslot_device(machine_config const &mconfig, char const *tag, device_t *owner, uint32_t clock, T &&slot_options, const char *default_option)
+ : electron_cartslot_device(mconfig, tag, owner, clock)
+ {
+ option_reset();
+ slot_options(*this);
+ set_default_option(default_option);
+ set_fixed(false);
+ }
+
+ bbc_cartslot_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
+
+ virtual const char *image_interface() const noexcept override { return "bbcm_cart"; }
+ virtual const char *file_extensions() const noexcept override { return "rom,bin"; }
+};
+
+
+// ======================> device_bbc_cart_interface
+
+class device_bbc_cart_interface : public device_electron_cart_interface
+{
+public:
+ // construction/destruction
+ virtual ~device_bbc_cart_interface();
+
+protected:
+ device_bbc_cart_interface(const machine_config &mconfig, device_t &device);
+};
+
+
+// device type definition
+DECLARE_DEVICE_TYPE(BBCM_CARTSLOT, bbc_cartslot_device)
+
+void bbcm_cart(device_slot_interface &device);
+
+
+#endif // MAME_BUS_BBC_CART_SLOT_H
diff --git a/src/devices/bus/bbc/exp/autocue.cpp b/src/devices/bus/bbc/exp/autocue.cpp
new file mode 100644
index 00000000000..4c9fa193c3a
--- /dev/null
+++ b/src/devices/bus/bbc/exp/autocue.cpp
@@ -0,0 +1,102 @@
+// license:BSD-3-Clause
+// copyright-holders:Nigel Barnes
+/**********************************************************************
+
+ Autocue RAM Disc
+
+ The RAM is accessible through JIM (page &FD). One page is visible in JIM at a time.
+ The selected page is controlled by the two paging registers:
+
+ &FCFE Paging register MSB
+ &FCFF Paging register LSB
+
+ 256K board has 1024 pages &000 to &3FF
+ 512K board has 2048 pages &000 to &7FF
+
+**********************************************************************/
+
+
+#include "emu.h"
+#include "autocue.h"
+
+
+//**************************************************************************
+// DEVICE DEFINITIONS
+//**************************************************************************
+
+DEFINE_DEVICE_TYPE(BBC_AUTOCUE, bbc_autocue_device, "bbc_autocue", "Autocue RAM Disc");
+
+
+//-------------------------------------------------
+// device_add_mconfig - add device configuration
+//-------------------------------------------------
+
+void bbc_autocue_device::device_add_mconfig(machine_config &config)
+{
+ NVRAM(config, "nvram", nvram_device::DEFAULT_ALL_0);
+}
+
+//**************************************************************************
+// LIVE DEVICE
+//**************************************************************************
+
+//-------------------------------------------------
+// bbc_autocue_device - constructor
+//-------------------------------------------------
+
+bbc_autocue_device::bbc_autocue_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
+ : device_t(mconfig, BBC_AUTOCUE, tag, owner, clock)
+ , device_bbc_exp_interface(mconfig, *this)
+ , m_nvram(*this, "nvram")
+ , m_ram_page(0)
+{
+}
+
+//-------------------------------------------------
+// device_start - device-specific startup
+//-------------------------------------------------
+
+void bbc_autocue_device::device_start()
+{
+ /* ram disk - board with 8 x HM62256LFP-12 - 256K expandable to 512K */
+ m_ram = make_unique_clear<uint8_t[]>(0x40000);
+ m_nvram->set_base(m_ram.get(), 0x40000);
+
+ /* register for save states */
+ save_item(NAME(m_ram_page));
+ save_pointer(NAME(m_ram), 0x40000);
+}
+
+
+//**************************************************************************
+// IMPLEMENTATION
+//**************************************************************************
+
+void bbc_autocue_device::fred_w(offs_t offset, uint8_t data)
+{
+ switch (offset)
+ {
+ case 0xfe: m_ram_page = (m_ram_page & 0x00ff) | (data << 8); break;
+ case 0xff: m_ram_page = (m_ram_page & 0xff00) | (data << 0); break;
+ }
+}
+
+uint8_t bbc_autocue_device::jim_r(offs_t offset)
+{
+ uint8_t data = 0xff;
+
+ if (m_ram_page < 0x400)
+ {
+ data = m_ram[(m_ram_page << 8) | offset];
+ }
+
+ return data;
+}
+
+void bbc_autocue_device::jim_w(offs_t offset, uint8_t data)
+{
+ if (m_ram_page < 0x400)
+ {
+ m_ram[(m_ram_page << 8) | offset] = data;
+ }
+}
diff --git a/src/devices/bus/bbc/exp/autocue.h b/src/devices/bus/bbc/exp/autocue.h
new file mode 100644
index 00000000000..d406aa1b436
--- /dev/null
+++ b/src/devices/bus/bbc/exp/autocue.h
@@ -0,0 +1,51 @@
+// license:BSD-3-Clause
+// copyright-holders:Nigel Barnes
+/**********************************************************************
+
+ Autocue RAM Disc
+
+**********************************************************************/
+
+
+#ifndef MAME_BUS_BBC_EXP_AUTOCUE_H
+#define MAME_BUS_BBC_EXP_AUTOCUE_H
+
+#include "exp.h"
+#include "machine/nvram.h"
+
+//**************************************************************************
+// TYPE DEFINITIONS
+//**************************************************************************
+
+class bbc_autocue_device :
+ public device_t,
+ public device_bbc_exp_interface
+{
+public:
+ // construction/destruction
+ bbc_autocue_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
+
+protected:
+ // device-level overrides
+ virtual void device_start() override ATTR_COLD;
+
+ // optional information overrides
+ virtual void device_add_mconfig(machine_config &config) override ATTR_COLD;
+
+ 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<nvram_device> m_nvram;
+ std::unique_ptr<uint8_t[]> m_ram;
+
+ uint16_t m_ram_page;
+};
+
+
+// device type definition
+DECLARE_DEVICE_TYPE(BBC_AUTOCUE, bbc_autocue_device);
+
+
+#endif /* MAME_BUS_BBC_EXP_AUTOCUE_H */
diff --git a/src/devices/bus/bbc/exp/exp.cpp b/src/devices/bus/bbc/exp/exp.cpp
index 25f19746b72..8339197eccb 100644
--- a/src/devices/bus/bbc/exp/exp.cpp
+++ b/src/devices/bus/bbc/exp/exp.cpp
@@ -26,8 +26,8 @@ DEFINE_DEVICE_TYPE(BBC_EXP_SLOT, bbc_exp_slot_device, "bbc_exp_slot", "BBC Maste
// device_bbc_exp_interface - constructor
//-------------------------------------------------
-device_bbc_exp_interface::device_bbc_exp_interface(const machine_config &mconfig, device_t &device)
- : device_slot_card_interface(mconfig, device)
+device_bbc_exp_interface::device_bbc_exp_interface(const machine_config &mconfig, device_t &device) :
+ device_interface(device, "bbcexp")
{
m_slot = dynamic_cast<bbc_exp_slot_device *>(device.owner());
}
@@ -43,7 +43,7 @@ device_bbc_exp_interface::device_bbc_exp_interface(const machine_config &mconfig
bbc_exp_slot_device::bbc_exp_slot_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) :
device_t(mconfig, BBC_EXP_SLOT, tag, owner, clock),
- device_slot_interface(mconfig, *this),
+ device_single_card_slot_interface<device_bbc_exp_interface>(mconfig, *this),
m_card(nullptr),
m_irq_handler(*this),
m_nmi_handler(*this),
@@ -54,46 +54,16 @@ bbc_exp_slot_device::bbc_exp_slot_device(const machine_config &mconfig, const ch
//-------------------------------------------------
-// device_validity_check -
-//-------------------------------------------------
-
-void bbc_exp_slot_device::device_validity_check(validity_checker &valid) const
-{
- device_t *const carddev = get_card_device();
- if (carddev && !dynamic_cast<device_bbc_exp_interface *>(carddev))
- osd_printf_error("Card device %s (%s) does not implement device_bbc_exp_interface\n", carddev->tag(), carddev->name());
-}
-
-
-//-------------------------------------------------
// device_start - device-specific startup
//-------------------------------------------------
void bbc_exp_slot_device::device_start()
{
- device_t *const carddev = get_card_device();
- m_card = dynamic_cast<device_bbc_exp_interface *>(carddev);
- if (carddev && !m_card)
- fatalerror("Card device %s (%s) does not implement device_bbc_exp_interface\n", carddev->tag(), carddev->name());
-
- // resolve callbacks
- m_irq_handler.resolve_safe();
- m_nmi_handler.resolve_safe();
-
- m_cb1_handler.resolve_safe();
- m_cb2_handler.resolve_safe();
+ m_card = get_card_device();
}
//-------------------------------------------------
-// device_reset - device-specific reset
-//-------------------------------------------------
-
-void bbc_exp_slot_device::device_reset()
-{
-}
-
-//-------------------------------------------------
// read
//-------------------------------------------------
@@ -172,12 +142,12 @@ void bbc_exp_slot_device::pb_w(uint8_t data)
// slot devices
-//#include "autocue.h"
+#include "autocue.h"
#include "mertec.h"
void bbc_exp_devices(device_slot_interface &device)
{
- //device.option_add("autocue", BBC_AUTOCUE); /* Autocue RAM disk board */
- device.option_add("mertec", BBC_MERTEC); /* Mertec Compact Companion */
+ device.option_add_internal("autocue", BBC_AUTOCUE); /* Autocue RAM disk board */
+ device.option_add("mertec", BBC_MERTEC); /* Mertec Compact Companion */
}
diff --git a/src/devices/bus/bbc/exp/exp.h b/src/devices/bus/bbc/exp/exp.h
index ef1a0174b1a..7b1b3fec514 100644
--- a/src/devices/bus/bbc/exp/exp.h
+++ b/src/devices/bus/bbc/exp/exp.h
@@ -51,7 +51,7 @@
class device_bbc_exp_interface;
-class bbc_exp_slot_device : public device_t, public device_slot_interface
+class bbc_exp_slot_device : public device_t, public device_single_card_slot_interface<device_bbc_exp_interface>
{
public:
// construction/destruction
@@ -82,21 +82,19 @@ 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);
protected:
// device-level overrides
- virtual void device_validity_check(validity_checker &valid) const override;
- virtual void device_start() override;
- virtual void device_reset() override;
+ virtual void device_start() override ATTR_COLD;
device_bbc_exp_interface *m_card;
@@ -111,7 +109,7 @@ private:
// ======================> device_bbc_exp_interface
-class device_bbc_exp_interface : public device_slot_card_interface
+class device_bbc_exp_interface : public device_interface
{
public:
virtual uint8_t fred_r(offs_t offset) { return 0xff; }
diff --git a/src/devices/bus/bbc/exp/mertec.cpp b/src/devices/bus/bbc/exp/mertec.cpp
index ab9dc3c2f6e..c561f052460 100644
--- a/src/devices/bus/bbc/exp/mertec.cpp
+++ b/src/devices/bus/bbc/exp/mertec.cpp
@@ -53,8 +53,8 @@ void bbc_mertec_device::device_add_mconfig(machine_config &config)
/* adc */
UPD7002(config, m_upd7002, DERIVED_CLOCK(1, 8));
- m_upd7002->set_get_analogue_callback(FUNC(bbc_mertec_device::get_analogue_input), this);
- m_upd7002->set_eoc_callback(FUNC(bbc_mertec_device::upd7002_eoc), this);
+ m_upd7002->set_get_analogue_callback(FUNC(bbc_mertec_device::get_analogue_input));
+ m_upd7002->set_eoc_callback(FUNC(bbc_mertec_device::upd7002_eoc));
/* analogue port */
BBC_ANALOGUE_SLOT(config, m_analog, bbc_analogue_devices, nullptr);
@@ -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/exp/mertec.h b/src/devices/bus/bbc/exp/mertec.h
index 33d71ab2ce9..9f3847996c6 100644
--- a/src/devices/bus/bbc/exp/mertec.h
+++ b/src/devices/bus/bbc/exp/mertec.h
@@ -34,11 +34,11 @@ public:
protected:
// device-level overrides
- virtual void device_start() override;
+ virtual void device_start() override ATTR_COLD;
// optional information overrides
- virtual void device_add_mconfig(machine_config &config) override;
- virtual const tiny_rom_entry *device_rom_region() const override;
+ virtual void device_add_mconfig(machine_config &config) override ATTR_COLD;
+ virtual const tiny_rom_entry *device_rom_region() const override ATTR_COLD;
virtual uint8_t fred_r(offs_t offset) override;
virtual void fred_w(offs_t offset, uint8_t data) override;
diff --git a/src/devices/bus/bbc/fdc/acorn.cpp b/src/devices/bus/bbc/fdc/acorn.cpp
index e5042ae0411..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
@@ -20,17 +23,18 @@ DEFINE_DEVICE_TYPE(BBC_ACORN1770, bbc_acorn1770_device, "bbc_acorn1770", "Acorn
//-------------------------------------------------
-// MACHINE_DRIVER( acorn )
+// FLOPPY_FORMATS( floppy_formats )
//-------------------------------------------------
-FLOPPY_FORMATS_MEMBER( bbc_acorn8271_device::floppy_formats )
- FLOPPY_ACORN_SSD_FORMAT,
- FLOPPY_ACORN_DSD_FORMAT,
- FLOPPY_ACORN_ADFS_OLD_FORMAT,
- FLOPPY_ACORN_DOS_FORMAT,
- FLOPPY_FSD_FORMAT,
- FLOPPY_PC_FORMAT
-FLOPPY_FORMATS_END0
+void bbc_acorn8271_device::floppy_formats(format_registration &fr)
+{
+ fr.add_pc_formats();
+ fr.add(FLOPPY_ACORN_SSD_FORMAT);
+ fr.add(FLOPPY_ACORN_DSD_FORMAT);
+ fr.add(FLOPPY_ACORN_ADFS_OLD_FORMAT);
+ fr.add(FLOPPY_ACORN_DOS_FORMAT);
+ fr.add(FLOPPY_FSD_FORMAT);
+}
static void bbc_floppies_525(device_slot_interface &device)
{
@@ -41,6 +45,10 @@ static void bbc_floppies_525(device_slot_interface &device)
device.option_add("525qd", FLOPPY_525_QD);
}
+//-------------------------------------------------
+// ROM( acorn )
+//-------------------------------------------------
+
ROM_START( acorn8271 )
ROM_REGION(0x4000, "dfs_rom", 0)
ROM_DEFAULT_BIOS("dnfs120")
@@ -91,13 +99,13 @@ ROM_END
void bbc_acorn8271_device::device_add_mconfig(machine_config &config)
{
- I8271(config, m_fdc, DERIVED_CLOCK(1, 4));
+ I8271(config, m_fdc, DERIVED_CLOCK(1, 2));
m_fdc->intrq_wr_callback().set(DEVICE_SELF_OWNER, FUNC(bbc_fdc_slot_device::intrq_w));
m_fdc->hdl_wr_callback().set(FUNC(bbc_acorn8271_device::motor_w));
m_fdc->opt_wr_callback().set(FUNC(bbc_acorn8271_device::side_w));
- FLOPPY_CONNECTOR(config, m_floppy0, bbc_floppies_525, "525qd", bbc_acorn8271_device::floppy_formats).enable_sound(true);
- FLOPPY_CONNECTOR(config, m_floppy1, bbc_floppies_525, "525qd", bbc_acorn8271_device::floppy_formats).enable_sound(true);
+ FLOPPY_CONNECTOR(config, m_floppy[0], bbc_floppies_525, "525qd", bbc_acorn8271_device::floppy_formats).enable_sound(true);
+ FLOPPY_CONNECTOR(config, m_floppy[1], bbc_floppies_525, "525qd", bbc_acorn8271_device::floppy_formats).enable_sound(true);
}
void bbc_acorn1770_device::device_add_mconfig(machine_config &config)
@@ -107,8 +115,8 @@ void bbc_acorn1770_device::device_add_mconfig(machine_config &config)
m_fdc->intrq_wr_callback().set(FUNC(bbc_acorn1770_device::fdc_intrq_w));
m_fdc->drq_wr_callback().set(FUNC(bbc_acorn1770_device::fdc_drq_w));
- FLOPPY_CONNECTOR(config, m_floppy0, bbc_floppies_525, "525qd", bbc_acorn8271_device::floppy_formats).enable_sound(true);
- FLOPPY_CONNECTOR(config, m_floppy1, bbc_floppies_525, "525qd", bbc_acorn8271_device::floppy_formats).enable_sound(true);
+ FLOPPY_CONNECTOR(config, m_floppy[0], bbc_floppies_525, "525qd", bbc_acorn8271_device::floppy_formats).enable_sound(true);
+ FLOPPY_CONNECTOR(config, m_floppy[1], bbc_floppies_525, "525qd", bbc_acorn8271_device::floppy_formats).enable_sound(true);
}
@@ -134,8 +142,7 @@ bbc_acorn8271_device::bbc_acorn8271_device(const machine_config &mconfig, const
: device_t(mconfig, BBC_ACORN8271, tag, owner, clock)
, device_bbc_fdc_interface(mconfig, *this)
, m_fdc(*this, "i8271")
- , m_floppy0(*this, "i8271:0")
- , m_floppy1(*this, "i8271:1")
+ , m_floppy(*this, "i8271:%u", 0)
{
}
@@ -143,8 +150,7 @@ bbc_acorn1770_device::bbc_acorn1770_device(const machine_config &mconfig, const
: device_t(mconfig, BBC_ACORN1770, tag, owner, clock)
, device_bbc_fdc_interface(mconfig, *this)
, m_fdc(*this, "wd1770")
- , m_floppy0(*this, "wd1770:0")
- , m_floppy1(*this, "wd1770:1")
+ , m_floppy(*this, "wd1770:%u", 0)
{
}
@@ -193,17 +199,17 @@ 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_floppy0->get_device()) m_floppy0->get_device()->mon_w(!state);
- if (m_floppy1->get_device()) m_floppy1->get_device()->mon_w(!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_floppy0->get_device()) m_floppy0->get_device()->ss_w(state);
- if (m_floppy1->get_device()) m_floppy1->get_device()->ss_w(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);
}
@@ -233,8 +239,8 @@ void bbc_acorn1770_device::write(offs_t offset, uint8_t data)
floppy_image_device *floppy = nullptr;
// bit 0, 1: drive select
- 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);
// bit 2: side select
@@ -252,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 13b434b156b..4b7843da58d 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
@@ -32,26 +29,25 @@ public:
// construction/destruction
bbc_acorn8271_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
- DECLARE_FLOPPY_FORMATS(floppy_formats);
+ static void floppy_formats(format_registration &fr);
protected:
// device-level overrides
- virtual void device_start() override;
+ virtual void device_start() override ATTR_COLD;
// optional information overrides
- virtual void device_add_mconfig(machine_config &config) override;
- virtual const tiny_rom_entry *device_rom_region() const override;
+ virtual void device_add_mconfig(machine_config &config) override ATTR_COLD;
+ virtual const tiny_rom_entry *device_rom_region() const override ATTR_COLD;
virtual uint8_t read(offs_t offset) override;
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<floppy_connector> m_floppy0;
- optional_device<floppy_connector> m_floppy1;
+ required_device_array<floppy_connector, 2> m_floppy;
};
class bbc_acorn1770_device :
@@ -64,22 +60,21 @@ public:
protected:
// device-level overrides
- virtual void device_start() override;
+ virtual void device_start() override ATTR_COLD;
// optional information overrides
- virtual void device_add_mconfig(machine_config &config) override;
- virtual const tiny_rom_entry *device_rom_region() const override;
+ virtual void device_add_mconfig(machine_config &config) override ATTR_COLD;
+ virtual const tiny_rom_entry *device_rom_region() const override ATTR_COLD;
virtual uint8_t read(offs_t offset) override;
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<floppy_connector> m_floppy0;
- optional_device<floppy_connector> m_floppy1;
+ required_device_array<floppy_connector, 2> m_floppy;
int m_fdc_ie;
};
diff --git a/src/devices/bus/bbc/fdc/ams.cpp b/src/devices/bus/bbc/fdc/ams.cpp
index db9eb7e3012..cd3499c418d 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
@@ -19,12 +20,19 @@ DEFINE_DEVICE_TYPE(BBC_AMS3, bbc_ams3_device, "bbc_ams3", "AMS 3\" Microdrive Di
//-------------------------------------------------
-// MACHINE_DRIVER( ams3 )
+// FLOPPY_FORMATS( ams3 )
//-------------------------------------------------
-FLOPPY_FORMATS_MEMBER( bbc_ams3_device::floppy_formats )
- FLOPPY_ACORN_SSD_FORMAT
-FLOPPY_FORMATS_END
+void bbc_ams3_device::floppy_formats(format_registration &fr)
+{
+ fr.add_mfm_containers();
+ fr.add(FLOPPY_ACORN_SSD_FORMAT);
+}
+
+
+//-------------------------------------------------
+// ROM( ams3 )
+//-------------------------------------------------
ROM_START( ams3 )
ROM_REGION(0x8000, "dfs_rom", 0)
@@ -43,13 +51,13 @@ ROM_END
void bbc_ams3_device::device_add_mconfig(machine_config &config)
{
- I8271(config, m_fdc, DERIVED_CLOCK(1, 4));
+ I8271(config, m_fdc, DERIVED_CLOCK(1, 2));
m_fdc->intrq_wr_callback().set(DEVICE_SELF_OWNER, FUNC(bbc_fdc_slot_device::intrq_w));
m_fdc->hdl_wr_callback().set(FUNC(bbc_ams3_device::motor_w));
m_fdc->opt_wr_callback().set(FUNC(bbc_ams3_device::side_w));
// Hitachi HFD 305S
- FLOPPY_CONNECTOR(config, m_floppy0, "3dsdd", FLOPPY_3_DSDD, true, bbc_ams3_device::floppy_formats).enable_sound(true);
- FLOPPY_CONNECTOR(config, m_floppy1, "3dsdd", FLOPPY_3_DSDD, false, bbc_ams3_device::floppy_formats).enable_sound(true);
+ FLOPPY_CONNECTOR(config, m_floppy[0], "3dssd", FLOPPY_3_DSSD, true, bbc_ams3_device::floppy_formats).enable_sound(true);
+ FLOPPY_CONNECTOR(config, m_floppy[1], "3dssd", FLOPPY_3_DSSD, false, bbc_ams3_device::floppy_formats).enable_sound(true);
}
@@ -70,8 +78,7 @@ bbc_ams3_device::bbc_ams3_device(const machine_config &mconfig, const char *tag,
: device_t(mconfig, BBC_AMS3, tag, owner, clock)
, device_bbc_fdc_interface(mconfig, *this)
, m_fdc(*this, "i8271")
- , m_floppy0(*this, "i8271:0")
- , m_floppy1(*this, "i8271:1")
+ , m_floppy(*this, "i8271:%u", 0)
{
}
@@ -116,15 +123,15 @@ 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_floppy0->get_device()) m_floppy0->get_device()->mon_w(!state);
- if (m_floppy1->get_device()) m_floppy1->get_device()->mon_w(!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_floppy0->get_device()) m_floppy0->get_device()->ss_w(state);
- if (m_floppy1->get_device()) m_floppy1->get_device()->ss_w(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 304666b5392..879e7bd6eff 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
@@ -29,27 +27,26 @@ public:
// construction/destruction
bbc_ams3_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
- DECLARE_FLOPPY_FORMATS(floppy_formats);
+ static void floppy_formats(format_registration &fr);
protected:
// device-level overrides
- virtual void device_start() override;
+ virtual void device_start() override ATTR_COLD;
// optional information overrides
- virtual void device_add_mconfig(machine_config &config) override;
- virtual const tiny_rom_entry *device_rom_region() const override;
+ virtual void device_add_mconfig(machine_config &config) override ATTR_COLD;
+ virtual const tiny_rom_entry *device_rom_region() const override ATTR_COLD;
virtual uint8_t read(offs_t offset) override;
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<floppy_connector> m_floppy0;
- optional_device<floppy_connector> m_floppy1;
+ 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 f4490b1922d..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
@@ -22,14 +24,16 @@ DEFINE_DEVICE_TYPE(BBC_CUMANA2, bbc_cumana2_device, "bbc_cumana2", "Cumana QFS I
//-------------------------------------------------
-// MACHINE_DRIVER( cumana )
+// FLOPPY_FORMATS( floppy_formats )
//-------------------------------------------------
-FLOPPY_FORMATS_MEMBER( bbc_cumanafdc_device::floppy_formats )
- FLOPPY_ACORN_SSD_FORMAT,
- FLOPPY_ACORN_DSD_FORMAT,
- FLOPPY_FSD_FORMAT
-FLOPPY_FORMATS_END0
+void bbc_cumanafdc_device::floppy_formats(format_registration &fr)
+{
+ fr.add_mfm_containers();
+ fr.add(FLOPPY_ACORN_SSD_FORMAT);
+ fr.add(FLOPPY_ACORN_DSD_FORMAT);
+ fr.add(FLOPPY_FSD_FORMAT);
+}
static void bbc_floppies_525(device_slot_interface &device)
{
@@ -40,6 +44,10 @@ static void bbc_floppies_525(device_slot_interface &device)
device.option_add("525qd", FLOPPY_525_QD);
}
+//-------------------------------------------------
+// ROM( cumana )
+//-------------------------------------------------
+
ROM_START( cumana1 )
ROM_REGION(0x4000, "dfs_rom", 0)
ROM_DEFAULT_BIOS("qfs102")
@@ -66,8 +74,8 @@ void bbc_cumana1_device::device_add_mconfig(machine_config &config)
m_fdc->drq_wr_callback().set(FUNC(bbc_cumanafdc_device::fdc_drq_w));
m_fdc->hld_wr_callback().set(FUNC(bbc_cumanafdc_device::motor_w));
- FLOPPY_CONNECTOR(config, m_floppy0, bbc_floppies_525, "525qd", floppy_formats).enable_sound(true);
- FLOPPY_CONNECTOR(config, m_floppy1, bbc_floppies_525, "525qd", floppy_formats).enable_sound(true);
+ FLOPPY_CONNECTOR(config, m_floppy[0], bbc_floppies_525, "525qd", floppy_formats).enable_sound(true);
+ FLOPPY_CONNECTOR(config, m_floppy[1], bbc_floppies_525, "525qd", floppy_formats).enable_sound(true);
}
void bbc_cumana2_device::device_add_mconfig(machine_config &config)
@@ -77,8 +85,8 @@ void bbc_cumana2_device::device_add_mconfig(machine_config &config)
m_fdc->drq_wr_callback().set(FUNC(bbc_cumanafdc_device::fdc_drq_w));
m_fdc->hld_wr_callback().set(FUNC(bbc_cumanafdc_device::motor_w));
- FLOPPY_CONNECTOR(config, m_floppy0, bbc_floppies_525, "525qd", floppy_formats).enable_sound(true);
- FLOPPY_CONNECTOR(config, m_floppy1, bbc_floppies_525, "525qd", floppy_formats).enable_sound(true);
+ FLOPPY_CONNECTOR(config, m_floppy[0], bbc_floppies_525, "525qd", floppy_formats).enable_sound(true);
+ FLOPPY_CONNECTOR(config, m_floppy[1], bbc_floppies_525, "525qd", floppy_formats).enable_sound(true);
}
const tiny_rom_entry *bbc_cumana1_device::device_rom_region() const
@@ -104,8 +112,7 @@ bbc_cumanafdc_device::bbc_cumanafdc_device(const machine_config &mconfig, device
device_t(mconfig, type, tag, owner, clock),
device_bbc_fdc_interface(mconfig, *this),
m_fdc(*this, "mb8877a"),
- m_floppy0(*this, "mb8877a:0"),
- m_floppy1(*this, "mb8877a:1"),
+ m_floppy(*this, "mb8877a:%u", 0),
m_drive_control(0)
{
}
@@ -167,8 +174,8 @@ void bbc_cumanafdc_device::write(offs_t offset, uint8_t data)
// bit 0: drive select
switch (BIT(data, 0))
{
- case 0: floppy = m_floppy0->get_device(); break;
- case 1: floppy = m_floppy1->get_device(); break;
+ case 0: floppy = m_floppy[0]->get_device(); break;
+ case 1: floppy = m_floppy[1]->get_device(); break;
}
m_fdc->set_floppy(floppy);
@@ -192,27 +199,27 @@ void bbc_cumanafdc_device::write(offs_t offset, uint8_t data)
m_fdc->dden_w(BIT(data, 2));
}
// bit 3: reset
- if (BIT(data, 3)) m_fdc->soft_reset();
+ m_fdc->mr_w(!BIT(data, 3));
// bit 4: interrupt enable
m_fdc_ie = BIT(data, 4);
}
}
-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_floppy0->get_device()) m_floppy0->get_device()->mon_w(!state);
- if (m_floppy1->get_device()) m_floppy1->get_device()->mon_w(!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 6e1a4f25011..de544beb448 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
@@ -26,25 +24,24 @@ class bbc_cumanafdc_device :
public device_bbc_fdc_interface
{
public:
- DECLARE_FLOPPY_FORMATS(floppy_formats);
+ 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
bbc_cumanafdc_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_start() override ATTR_COLD;
virtual uint8_t read(offs_t offset) override;
virtual void write(offs_t offset, uint8_t data) override;
required_device<mb8877_device> m_fdc;
- required_device<floppy_connector> m_floppy0;
- optional_device<floppy_connector> m_floppy1;
+ required_device_array<floppy_connector, 2> m_floppy;
bool m_invert;
@@ -59,8 +56,8 @@ public:
bbc_cumana1_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_add_mconfig(machine_config &config) override ATTR_COLD;
+ virtual const tiny_rom_entry *device_rom_region() const override ATTR_COLD;
};
class bbc_cumana2_device : public bbc_cumanafdc_device
@@ -69,8 +66,8 @@ public:
bbc_cumana2_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_add_mconfig(machine_config &config) override ATTR_COLD;
+ virtual const tiny_rom_entry *device_rom_region() const override ATTR_COLD;
};
diff --git a/src/devices/bus/bbc/fdc/cv1797.cpp b/src/devices/bus/bbc/fdc/cv1797.cpp
index d14098a3fa3..8c51463bbf6 100644
--- a/src/devices/bus/bbc/fdc/cv1797.cpp
+++ b/src/devices/bus/bbc/fdc/cv1797.cpp
@@ -6,12 +6,18 @@
http://chrisacorns.computinghistory.org.uk/8bit_Upgrades/ComputerVillage_FDC.html
-**********************************************************************/
+ Notes:
+ Everything seems to work, but schematic required to confirm implementation
+ of side and motor control.
+**********************************************************************/
#include "emu.h"
#include "cv1797.h"
+#include "formats/acorn_dsk.h"
+#include "formats/fsd_dsk.h"
+
//**************************************************************************
// DEVICE DEFINITIONS
@@ -21,14 +27,16 @@ DEFINE_DEVICE_TYPE(BBC_CV1797, bbc_cv1797_device, "bbc_cv1797", "Computer Villa
//-------------------------------------------------
-// MACHINE_DRIVER( cv1797 )
+// FLOPPY_FORMATS( floppy_formats )
//-------------------------------------------------
-FLOPPY_FORMATS_MEMBER( bbc_cv1797_device::floppy_formats )
- FLOPPY_ACORN_SSD_FORMAT,
- FLOPPY_ACORN_DSD_FORMAT,
- FLOPPY_FSD_FORMAT
-FLOPPY_FORMATS_END0
+void bbc_cv1797_device::floppy_formats(format_registration &fr)
+{
+ fr.add_mfm_containers();
+ fr.add(FLOPPY_ACORN_SSD_FORMAT);
+ fr.add(FLOPPY_ACORN_DSD_FORMAT);
+ fr.add(FLOPPY_FSD_FORMAT);
+}
static void bbc_floppies_525(device_slot_interface &device)
{
@@ -39,6 +47,10 @@ static void bbc_floppies_525(device_slot_interface &device)
device.option_add("525qd", FLOPPY_525_QD);
}
+//-------------------------------------------------
+// ROM( cv1797 )
+//-------------------------------------------------
+
ROM_START( cv1797 )
ROM_REGION(0x4000, "dfs_rom", 0)
ROM_DEFAULT_BIOS("lvldos")
@@ -55,12 +67,12 @@ ROM_END
void bbc_cv1797_device::device_add_mconfig(machine_config &config)
{
FD1797(config, m_fdc, 8_MHz_XTAL / 8);
- m_fdc->intrq_wr_callback().set(DEVICE_SELF_OWNER, FUNC(bbc_fdc_slot_device::intrq_w));
m_fdc->drq_wr_callback().set(DEVICE_SELF_OWNER, FUNC(bbc_fdc_slot_device::drq_w));
- m_fdc->hld_wr_callback().set(FUNC(bbc_cv1797_device::motor_w));
+ m_fdc->sso_wr_callback().set(FUNC(bbc_cv1797_device::fdc_sso_w));
+ m_fdc->hld_wr_callback().set(FUNC(bbc_cv1797_device::fdc_hld_w));
- FLOPPY_CONNECTOR(config, m_floppy0, bbc_floppies_525, "525qd", floppy_formats).enable_sound(true);
- FLOPPY_CONNECTOR(config, m_floppy1, bbc_floppies_525, "525qd", floppy_formats).enable_sound(true);
+ FLOPPY_CONNECTOR(config, m_floppies[0], bbc_floppies_525, "525qd", floppy_formats).enable_sound(true);
+ FLOPPY_CONNECTOR(config, m_floppies[1], bbc_floppies_525, "525qd", floppy_formats).enable_sound(true);
}
const tiny_rom_entry *bbc_cv1797_device::device_rom_region() const
@@ -80,9 +92,8 @@ bbc_cv1797_device::bbc_cv1797_device(const machine_config &mconfig, const char *
: device_t(mconfig, BBC_CV1797, tag, owner, clock)
, device_bbc_fdc_interface(mconfig, *this)
, m_fdc(*this, "fd1797")
- , m_floppy0(*this, "fd1797:0")
- , m_floppy1(*this, "fd1797:1")
- , m_drive_control(0)
+ , m_floppies(*this, "fd1797:%u", 0)
+ , m_floppy(nullptr)
{
}
@@ -92,7 +103,6 @@ bbc_cv1797_device::bbc_cv1797_device(const machine_config &mconfig, const char *
void bbc_cv1797_device::device_start()
{
- save_item(NAME(m_drive_control));
}
@@ -106,11 +116,11 @@ uint8_t bbc_cv1797_device::read(offs_t offset)
if (offset & 0x04)
{
- data = m_fdc->read(offset & 0x03);
+ data = 0xfe;
}
else
{
- data = m_drive_control;
+ data = m_fdc->read(offset & 0x03);
}
return data;
}
@@ -119,36 +129,30 @@ void bbc_cv1797_device::write(offs_t offset, uint8_t data)
{
if (offset & 0x04)
{
- m_fdc->write(offset & 0x03, data);
- }
- else
- {
- floppy_image_device *floppy = nullptr;
-
- m_drive_control = data;
- logerror("fdc: Drive control %02x\n", data);
// bit 0: drive select
- switch (BIT(data, 0))
- {
- case 0: floppy = m_floppy0->get_device(); break;
- case 1: floppy = m_floppy1->get_device(); break;
- }
- m_fdc->set_floppy(floppy);
+ m_floppy = m_floppies[BIT(data, 0)]->get_device();
+ m_fdc->set_floppy(m_floppy);
// bit 1: side select
- if (floppy)
- floppy->ss_w(BIT(data, 1));
+ if (m_floppy)
+ m_floppy->ss_w(BIT(data, 1));
// bit 2: density
m_fdc->dden_w(!BIT(data, 2));
-
- // bit 6: reset
- //if (BIT(data, 6)) m_fdc->soft_reset();
}
+ else
+ {
+ m_fdc->write(offset & 0x03, data);
+ }
+}
+
+void bbc_cv1797_device::fdc_sso_w(int state)
+{
+ // TODO: schematic required to confirm usage.
}
-WRITE_LINE_MEMBER(bbc_cv1797_device::motor_w)
+void bbc_cv1797_device::fdc_hld_w(int state)
{
- if (m_floppy0->get_device()) m_floppy0->get_device()->mon_w(!state);
- if (m_floppy1->get_device()) m_floppy1->get_device()->mon_w(!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 86207c8fcd0..65dffe1b214 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
@@ -27,32 +24,29 @@ class bbc_cv1797_device :
public device_bbc_fdc_interface
{
public:
- static constexpr feature_type imperfect_features() { return feature::DISK; }
-
// construction/destruction
bbc_cv1797_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_start() override ATTR_COLD;
// optional information overrides
- virtual void device_add_mconfig(machine_config &config) override;
- virtual const tiny_rom_entry *device_rom_region() const override;
+ virtual void device_add_mconfig(machine_config &config) override ATTR_COLD;
+ virtual const tiny_rom_entry *device_rom_region() const override ATTR_COLD;
virtual uint8_t read(offs_t offset) override;
virtual void write(offs_t offset, uint8_t data) override;
private:
- DECLARE_FLOPPY_FORMATS(floppy_formats);
+ static void floppy_formats(format_registration &fr);
- DECLARE_WRITE_LINE_MEMBER(motor_w);
+ void fdc_sso_w(int state);
+ void fdc_hld_w(int state);
required_device<fd1797_device> m_fdc;
- required_device<floppy_connector> m_floppy0;
- optional_device<floppy_connector> m_floppy1;
-
- int m_drive_control;
+ required_device_array<floppy_connector, 2> m_floppies;
+ floppy_image_device* m_floppy;
};
diff --git a/src/devices/bus/bbc/fdc/fdc.cpp b/src/devices/bus/bbc/fdc/fdc.cpp
index 2269bb3370a..e13993d7b11 100644
--- a/src/devices/bus/bbc/fdc/fdc.cpp
+++ b/src/devices/bus/bbc/fdc/fdc.cpp
@@ -25,8 +25,8 @@ DEFINE_DEVICE_TYPE(BBC_FDC_SLOT, bbc_fdc_slot_device, "bbc_fdc_slot", "BBC Micro
// device_bbc_fdc_interface - constructor
//-------------------------------------------------
-device_bbc_fdc_interface::device_bbc_fdc_interface(const machine_config &mconfig, device_t &device)
- : device_slot_card_interface(mconfig, device)
+device_bbc_fdc_interface::device_bbc_fdc_interface(const machine_config &mconfig, device_t &device) :
+ device_interface(device, "bbcfdc")
{
m_slot = dynamic_cast<bbc_fdc_slot_device *>(device.owner());
}
@@ -42,47 +42,22 @@ device_bbc_fdc_interface::device_bbc_fdc_interface(const machine_config &mconfig
bbc_fdc_slot_device::bbc_fdc_slot_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) :
device_t(mconfig, BBC_FDC_SLOT, tag, owner, clock),
- device_slot_interface(mconfig, *this),
+ device_single_card_slot_interface<device_bbc_fdc_interface>(mconfig, *this),
m_card(nullptr),
m_intrq_cb(*this),
- m_drq_cb(*this)
+ m_drq_cb(*this),
+ m_insert_rom(true)
{
}
//-------------------------------------------------
-// device_validity_check -
-//-------------------------------------------------
-
-void bbc_fdc_slot_device::device_validity_check(validity_checker &valid) const
-{
- device_t *const carddev = get_card_device();
- if (carddev && !dynamic_cast<device_bbc_fdc_interface *>(carddev))
- osd_printf_error("Card device %s (%s) does not implement device_bbc_fdc_interface\n", carddev->tag(), carddev->name());
-}
-
-//-------------------------------------------------
// device_start - device-specific startup
//-------------------------------------------------
void bbc_fdc_slot_device::device_start()
{
- device_t *const carddev = get_card_device();
- m_card = dynamic_cast<device_bbc_fdc_interface *>(get_card_device());
- if (carddev && !m_card)
- osd_printf_error("Card device %s (%s) does not implement device_bbc_fdc_interface\n", carddev->tag(), carddev->name());
-
- // resolve callbacks
- m_intrq_cb.resolve_safe();
- m_drq_cb.resolve_safe();
-}
-
-//-------------------------------------------------
-// device_reset - device-specific reset
-//-------------------------------------------------
-
-void bbc_fdc_slot_device::device_reset()
-{
+ m_card = get_card_device();
}
//-------------------------------------------------
@@ -117,9 +92,10 @@ void bbc_fdc_slot_device::write(offs_t offset, uint8_t data)
#include "ams.h"
#include "cumana.h"
#include "cv1797.h"
-#include "microware.h"
+#include "kenda.h"
#include "opus.h"
-//#include "solidisk.h"
+#include "solidisk.h"
+#include "udm.h"
#include "watford.h"
@@ -131,14 +107,15 @@ void bbc_fdc_devices(device_slot_interface &device)
device.option_add("cumana1", BBC_CUMANA1);
device.option_add("cumana2", BBC_CUMANA2);
device.option_add("cv1797", BBC_CV1797);
- device.option_add("microware", BBC_MICROWARE);
+ device.option_add("kenda", BBC_KENDA);
device.option_add("opus8272", BBC_OPUS8272);
device.option_add("opus2791", BBC_OPUS2791);
device.option_add("opus2793", BBC_OPUS2793);
device.option_add("opus1770", BBC_OPUS1770);
- //device.option_add("stl8271", BBC_STL8271);
- //device.option_add("stl1770_1", BBC_STL1770_1);
- //device.option_add("stl1770_2", BBC_STL1770_2);
+ device.option_add("stl1770_1", BBC_STL1770_1);
+ device.option_add("stl1770_2", BBC_STL1770_2);
+ device.option_add("stldfdc_1", BBC_STLDFDC_1);
+ device.option_add("udm", BBC_UDM);
device.option_add("weddb2", BBC_WEDDB2);
device.option_add("weddb3", BBC_WEDDB3);
}
diff --git a/src/devices/bus/bbc/fdc/fdc.h b/src/devices/bus/bbc/fdc/fdc.h
index 3264172a25d..e8d20ebee94 100644
--- a/src/devices/bus/bbc/fdc/fdc.h
+++ b/src/devices/bus/bbc/fdc/fdc.h
@@ -21,7 +21,7 @@
class device_bbc_fdc_interface;
-class bbc_fdc_slot_device : public device_t, public device_slot_interface
+class bbc_fdc_slot_device : public device_t, public device_single_card_slot_interface<device_bbc_fdc_interface>
{
public:
// construction/destruction
@@ -33,10 +33,14 @@ public:
slot_options(*this);
set_default_option(default_option);
set_fixed(false);
+ set_insert_rom(true);
}
bbc_fdc_slot_device(machine_config const &mconfig, char const *tag, device_t *owner, uint32_t clock);
+ void set_insert_rom(bool insert_rom) { m_insert_rom = insert_rom; }
+ bool insert_rom() { return m_insert_rom; }
+
// callbacks
auto intrq_wr_callback() { return m_intrq_cb.bind(); }
auto drq_wr_callback() { return m_drq_cb.bind(); }
@@ -44,26 +48,26 @@ 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
- virtual void device_validity_check(validity_checker &valid) const override;
- virtual void device_start() override;
- virtual void device_reset() override;
+ virtual void device_start() override ATTR_COLD;
device_bbc_fdc_interface *m_card;
private:
devcb_write_line m_intrq_cb;
devcb_write_line m_drq_cb;
+
+ bool m_insert_rom;
};
// ======================> device_bbc_fdc_interface
-class device_bbc_fdc_interface : public device_slot_card_interface
+class device_bbc_fdc_interface : public device_interface
{
public:
virtual uint8_t read(offs_t offset) { return 0xff; }
diff --git a/src/devices/bus/bbc/fdc/kenda.cpp b/src/devices/bus/bbc/fdc/kenda.cpp
new file mode 100644
index 00000000000..fc71fa88cae
--- /dev/null
+++ b/src/devices/bus/bbc/fdc/kenda.cpp
@@ -0,0 +1,169 @@
+// license:BSD-3-Clause
+// copyright-holders:Nigel Barnes
+/**********************************************************************
+
+ Kenda Professional DMFS
+
+ The Kenda Professional is packaged with the board in an epoxy blob, and is
+ quite rare. The board contents are not known as no-one has attempted to
+ remove the epoxy.
+ What we do know is that it contains:
+ - 8K ROM
+ - 2K RAM
+ - FDC (definitely WD compatible, and likely a WD2793)
+
+ The board plugs into the usual 8271 socket and has a ribbon cable with 24 pin
+ header that plugs into a ROM socket.
+
+ The 8K ROM is mirrored to fill the 16K ROM space, and has the 2K RAM overlayed
+ from offset &3000, and also mirrored upto &4000.
+
+**********************************************************************/
+
+#include "emu.h"
+#include "kenda.h"
+
+#include "formats/acorn_dsk.h"
+
+
+//**************************************************************************
+// DEVICE DEFINITIONS
+//**************************************************************************
+
+DEFINE_DEVICE_TYPE(BBC_KENDA, bbc_kenda_device, "bbc_kenda", "Kenda Professional DMFS")
+
+
+//-------------------------------------------------
+// FLOPPY_FORMATS( floppy_formats )
+//-------------------------------------------------
+
+void bbc_kenda_device::floppy_formats(format_registration &fr)
+{
+ fr.add_mfm_containers();
+ fr.add(FLOPPY_ACORN_SSD_FORMAT);
+ fr.add(FLOPPY_ACORN_DSD_FORMAT);
+}
+
+//-------------------------------------------------
+// SLOT_INTERFACE( bbc_floppies_525 )
+//-------------------------------------------------
+
+static void bbc_floppies_525(device_slot_interface &device)
+{
+ device.option_add("525sssd", FLOPPY_525_SSSD);
+ device.option_add("525sd", FLOPPY_525_SD);
+ device.option_add("525ssdd", FLOPPY_525_SSDD);
+ device.option_add("525dd", FLOPPY_525_DD);
+ device.option_add("525qd", FLOPPY_525_QD);
+}
+
+//-------------------------------------------------
+// ROM( kenda )
+//-------------------------------------------------
+
+ROM_START( kenda )
+ ROM_REGION(0x4000, "dfs_rom", 0)
+ ROM_LOAD("kenda102.rom", 0x0000, 0x2000, CRC(430b911c) SHA1(594ae1d1aeaa20a1d5d1c64cd94d43926dda4029))
+ ROM_RELOAD( 0x2000, 0x2000)
+ROM_END
+
+
+//-------------------------------------------------
+// device_add_mconfig - add device configuration
+//-------------------------------------------------
+
+void bbc_kenda_device::device_add_mconfig(machine_config &config)
+{
+ WD2793(config, m_fdc, DERIVED_CLOCK(1, 8)); // TODO: unconfirmed FDC
+ m_fdc->intrq_wr_callback().set(DEVICE_SELF_OWNER, FUNC(bbc_fdc_slot_device::intrq_w));
+ m_fdc->drq_wr_callback().set(DEVICE_SELF_OWNER, FUNC(bbc_fdc_slot_device::drq_w));
+ m_fdc->hld_wr_callback().set(FUNC(bbc_kenda_device::motor_w));
+
+ FLOPPY_CONNECTOR(config, m_floppy[0], bbc_floppies_525, "525qd", floppy_formats).enable_sound(true);
+ FLOPPY_CONNECTOR(config, m_floppy[1], bbc_floppies_525, "525qd", floppy_formats).enable_sound(true);
+}
+
+//-------------------------------------------------
+// rom_region - device-specific ROM region
+//-------------------------------------------------
+
+const tiny_rom_entry *bbc_kenda_device::device_rom_region() const
+{
+ return ROM_NAME( kenda );
+}
+
+//**************************************************************************
+// LIVE DEVICE
+//**************************************************************************
+
+//-------------------------------------------------
+// bbc_kenda_device - constructor
+//-------------------------------------------------
+
+bbc_kenda_device::bbc_kenda_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
+ : device_t(mconfig, BBC_KENDA, tag, owner, clock)
+ , device_bbc_fdc_interface(mconfig, *this)
+ , m_fdc(*this, "fdc")
+ , m_floppy(*this, "fdc:%u", 0)
+{
+}
+
+//-------------------------------------------------
+// device_start - device-specific startup
+//-------------------------------------------------
+
+void bbc_kenda_device::device_start()
+{
+}
+
+
+//**************************************************************************
+// IMPLEMENTATION
+//**************************************************************************
+
+uint8_t bbc_kenda_device::read(offs_t offset)
+{
+ uint8_t data;
+
+ if (offset & 0x04)
+ {
+ data = 0xfe;
+ }
+ else
+ {
+ data = m_fdc->read(offset & 0x03);
+ }
+
+ return data;
+}
+
+void bbc_kenda_device::write(offs_t offset, uint8_t data)
+{
+ if (offset & 0x04)
+ {
+ floppy_image_device *floppy = nullptr;
+
+ // bit 0: drive select
+ floppy = m_floppy[BIT(data, 0)]->get_device();
+ m_fdc->set_floppy(floppy);
+
+ // bit 1: side select
+ if (floppy)
+ floppy->ss_w(BIT(data, 1));
+
+ // other bits unknown, or unused
+
+ // bit 7: density
+ m_fdc->dden_w(!BIT(data, 7));
+ }
+ else
+ {
+ m_fdc->write(offset & 0x03, data);
+ }
+}
+
+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
new file mode 100644
index 00000000000..97570b7ba3c
--- /dev/null
+++ b/src/devices/bus/bbc/fdc/kenda.h
@@ -0,0 +1,52 @@
+// license:BSD-3-Clause
+// copyright-holders:Nigel Barnes
+/**********************************************************************
+
+ Kenda Professional DMFS
+
+**********************************************************************/
+
+#ifndef MAME_BUS_BBC_FDC_KENDA_H
+#define MAME_BUS_BBC_FDC_KENDA_H
+
+#pragma once
+
+#include "fdc.h"
+#include "imagedev/floppy.h"
+#include "machine/wd_fdc.h"
+
+//**************************************************************************
+// TYPE DEFINITIONS
+//**************************************************************************
+
+class bbc_kenda_device : public device_t, public device_bbc_fdc_interface
+{
+public:
+ // construction/destruction
+ bbc_kenda_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
+
+protected:
+ // device-level overrides
+ virtual void device_start() override ATTR_COLD;
+
+ // optional information overrides
+ virtual void device_add_mconfig(machine_config &config) override ATTR_COLD;
+ virtual const tiny_rom_entry *device_rom_region() const override ATTR_COLD;
+
+ virtual uint8_t read(offs_t offset) override;
+ virtual void write(offs_t offset, uint8_t data) override;
+
+private:
+ static void floppy_formats(format_registration &fr);
+
+ void motor_w(int state);
+
+ required_device<wd2793_device> m_fdc;
+ required_device_array<floppy_connector, 2> m_floppy;
+};
+
+
+// device type definition
+DECLARE_DEVICE_TYPE(BBC_KENDA, bbc_kenda_device)
+
+#endif /* MAME_BUS_BBC_FDC_KENDA_H */
diff --git a/src/devices/bus/bbc/fdc/microware.cpp b/src/devices/bus/bbc/fdc/microware.cpp
deleted file mode 100644
index 477ac0f3f9e..00000000000
--- a/src/devices/bus/bbc/fdc/microware.cpp
+++ /dev/null
@@ -1,156 +0,0 @@
-// license:BSD-3-Clause
-// copyright-holders:Nigel Barnes
-/**********************************************************************
-
- United Disk Memories DDFS FDC
-
- Microware DDFS FDC
-
-**********************************************************************/
-
-
-#include "emu.h"
-#include "microware.h"
-
-
-//**************************************************************************
-// DEVICE DEFINITIONS
-//**************************************************************************
-
-DEFINE_DEVICE_TYPE(BBC_MICROWARE, bbc_microware_device, "bbc_microware", "Microware DDFS FDC")
-
-
-//-------------------------------------------------
-// MACHINE_DRIVER( microware )
-//-------------------------------------------------
-
-FLOPPY_FORMATS_MEMBER( bbc_microware_device::floppy_formats )
- FLOPPY_ACORN_SSD_FORMAT,
- FLOPPY_ACORN_DSD_FORMAT,
- FLOPPY_FSD_FORMAT
-FLOPPY_FORMATS_END
-
-static void bbc_floppies_525(device_slot_interface &device)
-{
- device.option_add("525sssd", FLOPPY_525_SSSD);
- device.option_add("525sd", FLOPPY_525_SD);
- device.option_add("525ssdd", FLOPPY_525_SSDD);
- device.option_add("525dd", FLOPPY_525_DD);
- device.option_add("525qd", FLOPPY_525_QD);
-}
-
-ROM_START( microware )
- ROM_REGION(0x4000, "dfs_rom", 0)
- ROM_DEFAULT_BIOS("udm200")
- ROM_SYSTEM_BIOS(0, "ddfs090", "Microware DDFS 0.90")
- ROMX_LOAD("microware_ddfs090.rom", 0x0000, 0x4000, CRC(700d50e5) SHA1(6834e46cb15354003d553e6c2bdb4ed76b47a465), ROM_BIOS(0))
- ROM_SYSTEM_BIOS(1, "udm200", "UDM DDFS 2.00")
- ROMX_LOAD("udm_ddfs200.rom", 0x0000, 0x4000, CRC(1b4708a2) SHA1(0f37bcc73a758657cfe58c19f0cc92be9107e767), ROM_BIOS(1))
-ROM_END
-
-
-//-------------------------------------------------
-// device_add_mconfig - add device configuration
-//-------------------------------------------------
-
-void bbc_microware_device::device_add_mconfig(machine_config &config)
-{
- WD2793(config, m_fdc, DERIVED_CLOCK(1, 8)); // Replay advert suggests Type R8272 UDM DFS
- m_fdc->intrq_wr_callback().set(DEVICE_SELF_OWNER, FUNC(bbc_fdc_slot_device::intrq_w));
- m_fdc->drq_wr_callback().set(DEVICE_SELF_OWNER, FUNC(bbc_fdc_slot_device::drq_w));
- m_fdc->hld_wr_callback().set(FUNC(bbc_microware_device::motor_w));
-
- FLOPPY_CONNECTOR(config, m_floppy0, bbc_floppies_525, "525qd", floppy_formats).enable_sound(true);
- FLOPPY_CONNECTOR(config, m_floppy1, bbc_floppies_525, "525qd", floppy_formats).enable_sound(true);
-}
-
-const tiny_rom_entry *bbc_microware_device::device_rom_region() const
-{
- return ROM_NAME( microware );
-}
-
-//**************************************************************************
-// LIVE DEVICE
-//**************************************************************************
-
-//-------------------------------------------------
-// bbc_microware_device - constructor
-//-------------------------------------------------
-
-bbc_microware_device::bbc_microware_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
- : device_t(mconfig, BBC_MICROWARE, tag, owner, clock)
- , device_bbc_fdc_interface(mconfig, *this)
- , m_fdc(*this, "wd2793")
- , m_floppy0(*this, "wd2793:0")
- , m_floppy1(*this, "wd2793:1")
- , m_drive_control(0)
-{
-}
-
-//-------------------------------------------------
-// device_start - device-specific startup
-//-------------------------------------------------
-
-void bbc_microware_device::device_start()
-{
- save_item(NAME(m_drive_control));
-}
-
-
-//**************************************************************************
-// IMPLEMENTATION
-//**************************************************************************
-
-uint8_t bbc_microware_device::read(offs_t offset)
-{
- uint8_t data;
-
- if (offset & 0x04)
- {
- data = m_fdc->read(offset & 0x03);
- }
- else
- {
- data = m_drive_control;
- }
- return data;
-}
-
-void bbc_microware_device::write(offs_t offset, uint8_t data)
-{
- if (offset & 0x04)
- {
- m_fdc->write(offset & 0x03, data);
- }
- else
- {
- floppy_image_device *floppy = nullptr;
-
- m_drive_control = data;
- logerror("fdc: Drive control %02x \n", data);
- // bit 0: drive select
- switch (BIT(data, 0))
- {
- case 0: floppy = m_floppy0->get_device(); break;
- case 1: floppy = m_floppy1->get_device(); break;
- }
- m_fdc->set_floppy(floppy);
-
- // bit 1: side select
- if (floppy)
- floppy->ss_w(BIT(data, 1));
-
- // bit 2: density
- m_fdc->dden_w(BIT(data, 2));
-
- // bit 3: always set ???
-
- // bit 4: ??? interrupt
- }
-}
-
-WRITE_LINE_MEMBER(bbc_microware_device::motor_w)
-{
- if (m_floppy0->get_device()) m_floppy0->get_device()->mon_w(!state);
- if (m_floppy1->get_device()) m_floppy1->get_device()->mon_w(!state);
-}
diff --git a/src/devices/bus/bbc/fdc/opus.cpp b/src/devices/bus/bbc/fdc/opus.cpp
index f6b07df6bcb..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
@@ -28,16 +30,18 @@ DEFINE_DEVICE_TYPE(BBC_OPUS1770, bbc_opus1770_device, "bbc_opus1770", "Opus D-DO
//-------------------------------------------------
-// MACHINE_DRIVER( opus2791 )
+// FLOPPY_FORMATS( floppy_formats )
//-------------------------------------------------
-FLOPPY_FORMATS_MEMBER( bbc_opusfdc_device::floppy_formats )
- FLOPPY_ACORN_SSD_FORMAT,
- FLOPPY_ACORN_DSD_FORMAT,
- FLOPPY_FSD_FORMAT,
- FLOPPY_OPUS_DDOS_FORMAT,
- FLOPPY_OPUS_DDCPM_FORMAT
-FLOPPY_FORMATS_END0
+void bbc_opusfdc_device::floppy_formats(format_registration &fr)
+{
+ fr.add_mfm_containers();
+ fr.add(FLOPPY_ACORN_SSD_FORMAT);
+ fr.add(FLOPPY_ACORN_DSD_FORMAT);
+ fr.add(FLOPPY_FSD_FORMAT);
+ fr.add(FLOPPY_OPUS_DDOS_FORMAT);
+ fr.add(FLOPPY_OPUS_DDCPM_FORMAT);
+}
static void bbc_floppies_525(device_slot_interface &device)
{
@@ -48,6 +52,10 @@ static void bbc_floppies_525(device_slot_interface &device)
device.option_add("525qd", FLOPPY_525_QD);
}
+//-------------------------------------------------
+// ROM( opus )
+//-------------------------------------------------
+
ROM_START( opus8272 )
ROM_REGION(0x4000, "dfs_rom", 0)
ROM_DEFAULT_BIOS("ddos305")
@@ -98,8 +106,8 @@ void bbc_opus8272_device::device_add_mconfig(machine_config &config)
I8272A(config, m_fdc, 20_MHz_XTAL / 5, true);
m_fdc->intrq_wr_callback().set(DEVICE_SELF_OWNER, FUNC(bbc_fdc_slot_device::intrq_w));
- FLOPPY_CONNECTOR(config, m_floppy0, bbc_floppies_525, "525qd", bbc_opusfdc_device::floppy_formats).enable_sound(true);
- FLOPPY_CONNECTOR(config, m_floppy1, bbc_floppies_525, "525qd", bbc_opusfdc_device::floppy_formats).enable_sound(true);
+ FLOPPY_CONNECTOR(config, m_floppy[0], bbc_floppies_525, "525qd", bbc_opusfdc_device::floppy_formats).enable_sound(true);
+ FLOPPY_CONNECTOR(config, m_floppy[1], bbc_floppies_525, "525qd", bbc_opusfdc_device::floppy_formats).enable_sound(true);
}
void bbc_opus2791_device::device_add_mconfig(machine_config &config)
@@ -108,8 +116,8 @@ void bbc_opus2791_device::device_add_mconfig(machine_config &config)
m_fdc->drq_wr_callback().set(DEVICE_SELF_OWNER, FUNC(bbc_fdc_slot_device::drq_w));
m_fdc->hld_wr_callback().set(FUNC(bbc_opusfdc_device::motor_w));
- FLOPPY_CONNECTOR(config, m_floppy0, bbc_floppies_525, "525qd", bbc_opusfdc_device::floppy_formats).enable_sound(true);
- FLOPPY_CONNECTOR(config, m_floppy1, bbc_floppies_525, "525qd", bbc_opusfdc_device::floppy_formats).enable_sound(true);
+ FLOPPY_CONNECTOR(config, m_floppy[0], bbc_floppies_525, "525qd", bbc_opusfdc_device::floppy_formats).enable_sound(true);
+ FLOPPY_CONNECTOR(config, m_floppy[1], bbc_floppies_525, "525qd", bbc_opusfdc_device::floppy_formats).enable_sound(true);
}
void bbc_opus2793_device::device_add_mconfig(machine_config &config)
@@ -118,8 +126,8 @@ void bbc_opus2793_device::device_add_mconfig(machine_config &config)
m_fdc->drq_wr_callback().set(DEVICE_SELF_OWNER, FUNC(bbc_fdc_slot_device::drq_w));
m_fdc->hld_wr_callback().set(FUNC(bbc_opusfdc_device::motor_w));
- FLOPPY_CONNECTOR(config, m_floppy0, bbc_floppies_525, "525qd", bbc_opusfdc_device::floppy_formats).enable_sound(true);
- FLOPPY_CONNECTOR(config, m_floppy1, bbc_floppies_525, "525qd", bbc_opusfdc_device::floppy_formats).enable_sound(true);
+ FLOPPY_CONNECTOR(config, m_floppy[0], bbc_floppies_525, "525qd", bbc_opusfdc_device::floppy_formats).enable_sound(true);
+ FLOPPY_CONNECTOR(config, m_floppy[1], bbc_floppies_525, "525qd", bbc_opusfdc_device::floppy_formats).enable_sound(true);
}
void bbc_opus1770_device::device_add_mconfig(machine_config &config)
@@ -127,8 +135,8 @@ void bbc_opus1770_device::device_add_mconfig(machine_config &config)
WD1770(config, m_fdc, DERIVED_CLOCK(1, 1));
m_fdc->drq_wr_callback().set(DEVICE_SELF_OWNER, FUNC(bbc_fdc_slot_device::drq_w));
- FLOPPY_CONNECTOR(config, m_floppy0, bbc_floppies_525, "525qd", bbc_opusfdc_device::floppy_formats).enable_sound(true);
- FLOPPY_CONNECTOR(config, m_floppy1, bbc_floppies_525, "525qd", bbc_opusfdc_device::floppy_formats).enable_sound(true);
+ FLOPPY_CONNECTOR(config, m_floppy[0], bbc_floppies_525, "525qd", bbc_opusfdc_device::floppy_formats).enable_sound(true);
+ FLOPPY_CONNECTOR(config, m_floppy[1], bbc_floppies_525, "525qd", bbc_opusfdc_device::floppy_formats).enable_sound(true);
}
const tiny_rom_entry *bbc_opus8272_device::device_rom_region() const
@@ -164,8 +172,7 @@ bbc_opus8272_device::bbc_opus8272_device(const machine_config &mconfig, const ch
device_t(mconfig, BBC_OPUS8272, tag, owner, clock),
device_bbc_fdc_interface(mconfig, *this),
m_fdc(*this, "i8272"),
- m_floppy0(*this, "i8272:0"),
- m_floppy1(*this, "i8272:1")
+ m_floppy(*this, "i8272:%u", 0)
{
}
@@ -173,8 +180,7 @@ bbc_opusfdc_device::bbc_opusfdc_device(const machine_config &mconfig, device_typ
device_t(mconfig, type, tag, owner, clock),
device_bbc_fdc_interface(mconfig, *this),
m_fdc(*this, "fdc"),
- m_floppy0(*this, "fdc:0"),
- m_floppy1(*this, "fdc:1"),
+ m_floppy(*this, "fdc:%u", 0),
m_drive_control(0)
{
}
@@ -224,15 +230,17 @@ uint8_t bbc_opus8272_device::read(offs_t offset)
break;
case 0x06:
- if (m_floppy0->get_device()) m_floppy0->get_device()->mon_w(1);
- if (m_floppy1->get_device()) m_floppy1->get_device()->mon_w(1);
+ if (m_floppy[0]->get_device()) m_floppy[0]->get_device()->mon_w(1);
+ if (m_floppy[1]->get_device()) m_floppy[1]->get_device()->mon_w(1);
+ [[fallthrough]];
case 0x04:
data = m_fdc->msr_r();
break;
case 0x05:
- 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);
+ [[fallthrough]];
case 0x07:
data = m_fdc->fifo_r();
break;
@@ -249,15 +257,16 @@ void bbc_opus8272_device::write(offs_t offset, uint8_t data)
case 0x01:
switch (data & 0x01)
{
- case 0: floppy = m_floppy1->get_device(); break;
- case 1: floppy = m_floppy0->get_device(); break;
+ case 0: floppy = m_floppy[1]->get_device(); break;
+ case 1: floppy = m_floppy[0]->get_device(); break;
}
m_fdc->set_floppy(floppy);
break;
case 0x05:
- 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);
+ [[fallthrough]];
case 0x07:
m_fdc->fifo_w(data);
break;
@@ -291,8 +300,8 @@ void bbc_opusfdc_device::write(offs_t offset, uint8_t data)
// bit 0: drive select
switch (BIT(data, 0))
{
- case 0: floppy = m_floppy0->get_device(); break;
- case 1: floppy = m_floppy1->get_device(); break;
+ case 0: floppy = m_floppy[0]->get_device(); break;
+ case 1: floppy = m_floppy[1]->get_device(); break;
}
m_fdc->set_floppy(floppy);
@@ -309,8 +318,8 @@ 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_floppy0->get_device()) m_floppy0->get_device()->mon_w(!state);
- if (m_floppy1->get_device()) m_floppy1->get_device()->mon_w(!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 033fccc02c4..d099308b6cb 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
@@ -30,19 +28,18 @@ public:
protected:
// device-level overrides
- virtual void device_start() override;
+ virtual void device_start() override ATTR_COLD;
// optional information overrides
- virtual void device_add_mconfig(machine_config &config) override;
- virtual const tiny_rom_entry *device_rom_region() const override;
+ virtual void device_add_mconfig(machine_config &config) override ATTR_COLD;
+ virtual const tiny_rom_entry *device_rom_region() const override ATTR_COLD;
virtual uint8_t read(offs_t offset) override;
virtual void write(offs_t offset, uint8_t data) override;
private:
required_device<i8272a_device> m_fdc;
- required_device<floppy_connector> m_floppy0;
- optional_device<floppy_connector> m_floppy1;
+ required_device_array<floppy_connector, 2> m_floppy;
};
@@ -51,23 +48,22 @@ class bbc_opusfdc_device :
public device_bbc_fdc_interface
{
public:
- DECLARE_FLOPPY_FORMATS(floppy_formats);
+ static void floppy_formats(format_registration &fr);
- DECLARE_WRITE_LINE_MEMBER(motor_w);
+ void motor_w(int state);
protected:
// construction/destruction
bbc_opusfdc_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_start() override ATTR_COLD;
virtual uint8_t read(offs_t offset) override;
virtual void write(offs_t offset, uint8_t data) override;
required_device<wd_fdc_device_base> m_fdc;
- required_device<floppy_connector> m_floppy0;
- optional_device<floppy_connector> m_floppy1;
+ required_device_array<floppy_connector, 2> m_floppy;
private:
int m_drive_control;
@@ -79,8 +75,8 @@ public:
bbc_opus2791_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_add_mconfig(machine_config &config) override ATTR_COLD;
+ virtual const tiny_rom_entry *device_rom_region() const override ATTR_COLD;
};
class bbc_opus2793_device : public bbc_opusfdc_device
@@ -89,8 +85,8 @@ public:
bbc_opus2793_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_add_mconfig(machine_config &config) override ATTR_COLD;
+ virtual const tiny_rom_entry *device_rom_region() const override ATTR_COLD;
};
class bbc_opus1770_device : public bbc_opusfdc_device
@@ -99,8 +95,8 @@ public:
bbc_opus1770_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_add_mconfig(machine_config &config) override ATTR_COLD;
+ virtual const tiny_rom_entry *device_rom_region() const override ATTR_COLD;
};
// device type definition
diff --git a/src/devices/bus/bbc/fdc/solidisk.cpp b/src/devices/bus/bbc/fdc/solidisk.cpp
new file mode 100644
index 00000000000..44fbd58f549
--- /dev/null
+++ b/src/devices/bus/bbc/fdc/solidisk.cpp
@@ -0,0 +1,363 @@
+// license:BSD-3-Clause
+// copyright-holders:Nigel Barnes
+/**********************************************************************
+
+ Solidisk 1770 Issue 2 FDC
+
+ http://chrisacorns.computinghistory.org.uk/8bit_Upgrades/Solidisk_1770DDFS.html
+
+ Solidisk Dual FDC
+ http://chrisacorns.computinghistory.org.uk/8bit_Upgrades/Solidisk_dfdc.html
+
+**********************************************************************/
+
+#include "emu.h"
+#include "solidisk.h"
+
+#include "formats/acorn_dsk.h"
+#include "formats/fsd_dsk.h"
+
+
+//**************************************************************************
+// DEVICE DEFINITIONS
+//**************************************************************************
+
+DEFINE_DEVICE_TYPE(BBC_STL1770_1, bbc_stl1770_1_device, "bbc_stl1770_1", "Solidisk 1770 DDFS Issue 1 FDC")
+DEFINE_DEVICE_TYPE(BBC_STL1770_2, bbc_stl1770_2_device, "bbc_stl1770_2", "Solidisk 1770 DDFS Issue 2 FDC")
+DEFINE_DEVICE_TYPE(BBC_STLDFDC_1, bbc_stldfdc_1_device, "bbc_stldfdc_1", "Solidisk 8271/1770 DFDC Issue 1 FDC")
+
+
+//-------------------------------------------------
+// FLOPPY_FORMATS( floppy_formats )
+//-------------------------------------------------
+
+void bbc_stlfdc_device::floppy_formats(format_registration &fr)
+{
+ fr.add_mfm_containers();
+ fr.add(FLOPPY_ACORN_SSD_FORMAT);
+ fr.add(FLOPPY_ACORN_DSD_FORMAT);
+ fr.add(FLOPPY_ACORN_ADFS_OLD_FORMAT);
+ fr.add(FLOPPY_FSD_FORMAT);
+}
+
+static void bbc_floppies_525(device_slot_interface &device)
+{
+ device.option_add("525sssd", FLOPPY_525_SSSD);
+ device.option_add("525sd", FLOPPY_525_SD);
+ device.option_add("525ssdd", FLOPPY_525_SSDD);
+ device.option_add("525dd", FLOPPY_525_DD);
+ device.option_add("525qd", FLOPPY_525_QD);
+}
+
+//-------------------------------------------------
+// INPUT_PORTS( stldfdc )
+//-------------------------------------------------
+
+INPUT_PORTS_START( stldfdc )
+ PORT_START("DFDC")
+ PORT_CONFNAME(0x01, 0x00, "Dual FDC Select") PORT_CHANGED_MEMBER(DEVICE_SELF, FUNC(bbc_stlfdc_device::fdc_changed), 0)
+ PORT_CONFSETTING(0x00, "8271")
+ PORT_CONFSETTING(0x01, "1770")
+INPUT_PORTS_END
+
+
+//-------------------------------------------------
+// input_ports - device-specific input ports
+//-------------------------------------------------
+
+ioport_constructor bbc_stldfdc_1_device::device_input_ports() const
+{
+ return INPUT_PORTS_NAME(stldfdc);
+}
+
+//-------------------------------------------------
+// ROM( solidisk )
+//-------------------------------------------------
+
+ROM_START( stl1770_1 )
+ ROM_REGION(0x4000, "dfs_rom", 0)
+ ROM_SYSTEM_BIOS(0, "dfs21j", "DFS 2.1J (1770)")
+ ROMX_LOAD("solidisk-dfs-2.1j.rom", 0x0000, 0x4000, CRC(b60296f1) SHA1(22e60d4dda37335f61c27a92ba76ccc3e2102c4e), ROM_BIOS(0))
+ROM_END
+
+ROM_START( stl1770_2 )
+ ROM_REGION(0x4000, "dfs_rom", 0)
+ ROM_SYSTEM_BIOS(0, "stl22m", "DFS 2.2M Issue 2")
+ ROMX_LOAD("solidisk-dfs-2.2m-iss2.rom", 0x0000, 0x4000, CRC(defe42ec) SHA1(78ee759c0f762bc2717d8454a88f117516d28325), ROM_BIOS(0))
+ROM_END
+
+ROM_START( stldfdc_1 )
+ ROM_REGION(0x4000, "dfs_rom", 0)
+ ROM_SYSTEM_BIOS(0, "dfs21", "DFS 2.1 (Mar 85)")
+ ROMX_LOAD("solidisk-dfs-8271-1770-2.1.rom", 0x0000, 0x4000, CRC(cc83d913) SHA1(c761102ac11be629676339e9e496fb78734e4399), ROM_BIOS(0))
+ROM_END
+
+//-------------------------------------------------
+// device_add_mconfig - add device configuration
+//-------------------------------------------------
+
+void bbc_stl1770_1_device::device_add_mconfig(machine_config &config)
+{
+ WD1770(config, m_wd1770, DERIVED_CLOCK(1, 1));
+ m_wd1770->drq_wr_callback().set(DEVICE_SELF_OWNER, FUNC(bbc_fdc_slot_device::drq_w));
+
+ FLOPPY_CONNECTOR(config, m_floppy[0], bbc_floppies_525, "525qd", bbc_stlfdc_device::floppy_formats).enable_sound(true);
+ FLOPPY_CONNECTOR(config, m_floppy[1], bbc_floppies_525, "525qd", bbc_stlfdc_device::floppy_formats).enable_sound(true);
+}
+
+void bbc_stl1770_2_device::device_add_mconfig(machine_config &config)
+{
+ WD1770(config, m_wd1770, DERIVED_CLOCK(1, 1));
+ m_wd1770->intrq_wr_callback().set(DEVICE_SELF_OWNER, FUNC(bbc_fdc_slot_device::intrq_w));
+ m_wd1770->drq_wr_callback().set(DEVICE_SELF_OWNER, FUNC(bbc_fdc_slot_device::drq_w));
+
+ FLOPPY_CONNECTOR(config, m_floppy[0], bbc_floppies_525, "525qd", bbc_stlfdc_device::floppy_formats).enable_sound(true);
+ FLOPPY_CONNECTOR(config, m_floppy[1], bbc_floppies_525, "525qd", bbc_stlfdc_device::floppy_formats).enable_sound(true);
+}
+
+void bbc_stldfdc_1_device::device_add_mconfig(machine_config& config)
+{
+ bbc_stl1770_1_device::device_add_mconfig(config);
+
+ I8271(config, m_i8271, DERIVED_CLOCK(1, 2));
+ m_i8271->intrq_wr_callback().set(DEVICE_SELF_OWNER, FUNC(bbc_fdc_slot_device::intrq_w));
+ m_i8271->hdl_wr_callback().set(FUNC(bbc_stldfdc_1_device::motor_w));
+ m_i8271->opt_wr_callback().set(FUNC(bbc_stldfdc_1_device::side_w));
+}
+
+
+const tiny_rom_entry *bbc_stl1770_1_device::device_rom_region() const
+{
+ return ROM_NAME( stl1770_1 );
+}
+
+const tiny_rom_entry *bbc_stl1770_2_device::device_rom_region() const
+{
+ return ROM_NAME( stl1770_2 );
+}
+
+const tiny_rom_entry *bbc_stldfdc_1_device::device_rom_region() const
+{
+ return ROM_NAME( stldfdc_1 );
+}
+
+//**************************************************************************
+// LIVE DEVICE
+//**************************************************************************
+
+//-------------------------------------------------
+// bbc_stlfdc_device - constructor
+//-------------------------------------------------
+
+bbc_stlfdc_device::bbc_stlfdc_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_fdc_interface(mconfig, *this)
+ , m_wd1770(*this, "wd1770")
+ , m_i8271(*this, "i8271")
+ , m_floppy(*this, "%u", 0)
+ , m_dfdc(*this, "DFDC")
+{
+}
+
+bbc_stl1770_1_device::bbc_stl1770_1_device(const machine_config& mconfig, device_type type, const char* tag, device_t* owner, uint32_t clock)
+ : bbc_stlfdc_device(mconfig, type, tag, owner, clock)
+{
+}
+
+bbc_stl1770_1_device::bbc_stl1770_1_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
+ : bbc_stlfdc_device(mconfig, BBC_STL1770_1, tag, owner, clock)
+{
+}
+
+bbc_stl1770_2_device::bbc_stl1770_2_device(const machine_config& mconfig, device_type type, const char* tag, device_t* owner, uint32_t clock)
+ : bbc_stlfdc_device(mconfig, type, tag, owner, clock)
+{
+}
+
+bbc_stl1770_2_device::bbc_stl1770_2_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
+ : bbc_stlfdc_device(mconfig, BBC_STL1770_2, tag, owner, clock)
+{
+}
+
+bbc_stldfdc_1_device::bbc_stldfdc_1_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
+ : bbc_stl1770_1_device(mconfig, BBC_STLDFDC_1, tag, owner, clock)
+{
+}
+
+//-------------------------------------------------
+// device_start - device-specific startup
+//-------------------------------------------------
+
+void bbc_stl1770_1_device::device_start()
+{
+}
+
+void bbc_stl1770_2_device::device_start()
+{
+}
+
+void bbc_stldfdc_1_device::device_start()
+{
+}
+
+//-------------------------------------------------
+// device_reset - device-specific reset
+//-------------------------------------------------
+
+void bbc_stldfdc_1_device::device_reset()
+{
+ switch (m_dfdc->read())
+ {
+ case 0:
+ m_i8271->set_floppies(m_floppy[0], m_floppy[1]);
+ break;
+
+ case 1:
+ m_wd1770->set_floppy(m_floppy[0]->get_device());
+ break;
+ }
+}
+
+
+//**************************************************************************
+// IMPLEMENTATION
+//**************************************************************************
+
+INPUT_CHANGED_MEMBER(bbc_stlfdc_device::fdc_changed)
+{
+ device_reset();
+}
+
+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);
+}
+
+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);
+}
+
+
+uint8_t bbc_stl1770_1_device::read(offs_t offset)
+{
+ return m_wd1770->read(offset & 0x03);
+}
+
+void bbc_stl1770_1_device::write(offs_t offset, uint8_t data)
+{
+ if (offset & 0x04)
+ {
+ floppy_image_device *floppy = nullptr;
+
+ // bit 0: drive select
+ switch (BIT(data, 0))
+ {
+ case 0: floppy = m_floppy[0]->get_device(); break;
+ case 1: floppy = m_floppy[1]->get_device(); break;
+ }
+ m_wd1770->set_floppy(floppy);
+
+ // bit 1: side select
+ if (floppy)
+ floppy->ss_w(BIT(data, 1));
+
+ // bit 2: density
+ m_wd1770->dden_w(BIT(data, 2));
+ }
+
+ m_wd1770->write(offset & 0x03, data);
+}
+
+
+uint8_t bbc_stl1770_2_device::read(offs_t offset)
+{
+ uint8_t data;
+
+ if (offset & 0x04)
+ {
+ data = m_wd1770->read(offset & 0x03);
+ }
+ else
+ {
+ data = 0xfe;
+ }
+ return data;
+}
+
+void bbc_stl1770_2_device::write(offs_t offset, uint8_t data)
+{
+ if (offset & 0x04)
+ {
+ m_wd1770->write(offset & 0x03, data);
+ }
+ else
+ {
+ floppy_image_device *floppy = nullptr;
+
+ // bit 0, 1: drive select
+ if (BIT(data, 0)) floppy = m_floppy[0]->get_device();
+ if (BIT(data, 1)) floppy = m_floppy[1]->get_device();
+ m_wd1770->set_floppy(floppy);
+
+ // bit 2: side select
+ if (floppy)
+ floppy->ss_w(BIT(data, 2));
+
+ // bit 3: density
+ m_wd1770->dden_w(BIT(data, 3));
+
+ // bit 5: reset
+ m_wd1770->mr_w(BIT(data, 5));
+ }
+}
+
+
+uint8_t bbc_stldfdc_1_device::read(offs_t offset)
+{
+ uint8_t data = 0xff;
+
+ switch (m_dfdc->read())
+ {
+ case 0:
+ if (offset & 0x04)
+ {
+ data = m_i8271->data_r();
+ }
+ else
+ {
+ data = m_i8271->read(offset & 0x03);
+ }
+ break;
+
+ case 1:
+ data = bbc_stl1770_1_device::read(offset);
+ break;
+ }
+
+ return data;
+}
+
+void bbc_stldfdc_1_device::write(offs_t offset, uint8_t data)
+{
+ switch (m_dfdc->read())
+ {
+ case 0:
+ if (offset & 0x04)
+ {
+ m_i8271->data_w(data);
+ }
+ else
+ {
+ m_i8271->write(offset & 0x03, data);
+ }
+ break;
+
+ case 1:
+ bbc_stl1770_1_device::write(offset, data);
+ break;
+ }
+}
diff --git a/src/devices/bus/bbc/fdc/solidisk.h b/src/devices/bus/bbc/fdc/solidisk.h
new file mode 100644
index 00000000000..bf5a089a94d
--- /dev/null
+++ b/src/devices/bus/bbc/fdc/solidisk.h
@@ -0,0 +1,110 @@
+// license:BSD-3-Clause
+// copyright-holders:Nigel Barnes
+/**********************************************************************
+
+ Solidisk 8271/1770 FDC
+
+**********************************************************************/
+
+#ifndef MAME_BUS_BBC_FDC_SOLIDISK_H
+#define MAME_BUS_BBC_FDC_SOLIDISK_H
+
+#pragma once
+
+#include "fdc.h"
+#include "machine/i8271.h"
+#include "imagedev/floppy.h"
+#include "machine/wd_fdc.h"
+
+//**************************************************************************
+// TYPE DEFINITIONS
+//**************************************************************************
+
+class bbc_stlfdc_device :
+ public device_t,
+ public device_bbc_fdc_interface
+{
+public:
+ static void floppy_formats(format_registration &fr);
+ DECLARE_INPUT_CHANGED_MEMBER(fdc_changed);
+
+protected:
+ // construction/destruction
+ bbc_stlfdc_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock);
+
+ void motor_w(int state);
+ void side_w(int state);
+
+ required_device<wd1770_device> m_wd1770;
+ optional_device<i8271_device> m_i8271;
+ required_device_array<floppy_connector, 2> m_floppy;
+ optional_ioport m_dfdc;
+};
+
+
+class bbc_stl1770_1_device : public bbc_stlfdc_device
+{
+public:
+ bbc_stl1770_1_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
+
+protected:
+ bbc_stl1770_1_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 ATTR_COLD;
+
+ virtual void device_add_mconfig(machine_config& config) override;
+ virtual const tiny_rom_entry* device_rom_region() const override;
+
+ virtual uint8_t read(offs_t offset) override;
+ virtual void write(offs_t offset, uint8_t data) override;
+};
+
+
+class bbc_stl1770_2_device : public bbc_stlfdc_device
+{
+public:
+ bbc_stl1770_2_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
+
+protected:
+ bbc_stl1770_2_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 ATTR_COLD;
+
+ virtual void device_add_mconfig(machine_config& config) override;
+ virtual const tiny_rom_entry* device_rom_region() const override;
+
+ virtual uint8_t read(offs_t offset) override;
+ virtual void write(offs_t offset, uint8_t data) override;
+};
+
+
+class bbc_stldfdc_1_device : public bbc_stl1770_1_device
+{
+public:
+ // construction/destruction
+ bbc_stldfdc_1_device(const machine_config& mconfig, const char* tag, device_t* owner, uint32_t clock);
+
+protected:
+ // device-level overrides
+ virtual void device_start() override ATTR_COLD;
+ virtual void device_reset() override ATTR_COLD;
+
+ // 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 ATTR_COLD;
+
+ virtual uint8_t read(offs_t offset) override;
+ virtual void write(offs_t offset, uint8_t data) override;
+};
+
+
+// device type definition
+DECLARE_DEVICE_TYPE(BBC_STL1770_1, bbc_stl1770_1_device)
+DECLARE_DEVICE_TYPE(BBC_STL1770_2, bbc_stl1770_2_device)
+DECLARE_DEVICE_TYPE(BBC_STLDFDC_1, bbc_stldfdc_1_device)
+
+
+#endif /* MAME_BUS_BBC_FDC_SOLIDISK_H */
diff --git a/src/devices/bus/bbc/fdc/udm.cpp b/src/devices/bus/bbc/fdc/udm.cpp
new file mode 100644
index 00000000000..3c913721909
--- /dev/null
+++ b/src/devices/bus/bbc/fdc/udm.cpp
@@ -0,0 +1,170 @@
+// license:BSD-3-Clause
+// copyright-holders:Nigel Barnes
+/**********************************************************************
+
+ Microware / United Disk Memories DDFS FDC
+
+**********************************************************************/
+
+#include "emu.h"
+#include "udm.h"
+
+#include "formats/acorn_dsk.h"
+#include "formats/fsd_dsk.h"
+
+
+//**************************************************************************
+// DEVICE DEFINITIONS
+//**************************************************************************
+
+DEFINE_DEVICE_TYPE(BBC_UDM, bbc_udm_device, "bbc_udm", "United Disk Memories DDFS FDC")
+
+
+//-------------------------------------------------
+// FLOPPY_FORMATS( udm )
+//-------------------------------------------------
+
+void bbc_udm_device::floppy_formats(format_registration &fr)
+{
+ fr.add_mfm_containers();
+ fr.add(FLOPPY_ACORN_SSD_FORMAT);
+ fr.add(FLOPPY_ACORN_DSD_FORMAT);
+ fr.add(FLOPPY_FSD_FORMAT);
+}
+
+static void bbc_floppies_525(device_slot_interface &device)
+{
+ device.option_add("525sssd", FLOPPY_525_SSSD);
+ device.option_add("525sd", FLOPPY_525_SD);
+ device.option_add("525ssdd", FLOPPY_525_SSDD);
+ device.option_add("525dd", FLOPPY_525_DD);
+ device.option_add("525qd", FLOPPY_525_QD);
+}
+
+
+//-------------------------------------------------
+// ROM( udm )
+//-------------------------------------------------
+
+ROM_START( udm )
+ ROM_REGION(0x4000, "dfs_rom", 0)
+ ROM_SYSTEM_BIOS(0, "ddfs310", "UDM DDFS 3.10")
+ ROMX_LOAD("udm_ddfs310.rom", 0x0000, 0x4000, CRC(55851c2d) SHA1(c5b6557fa4dbfa651c8ecc5b1da93b615c3aa905), ROM_BIOS(0))
+ ROM_SYSTEM_BIOS(1, "ddfs200", "UDM DDFS 2.00")
+ ROMX_LOAD("udm_ddfs200.rom", 0x0000, 0x4000, CRC(1b4708a2) SHA1(0f37bcc73a758657cfe58c19f0cc92be9107e767), ROM_BIOS(1))
+ ROM_SYSTEM_BIOS(2, "ddfs098", "UDM DDFS 0.98")
+ ROMX_LOAD("udm_ddfs098.rom", 0x0000, 0x4000, CRC(2119f9ad) SHA1(bfb9404b34de3b489db73d886300f37081db2482), ROM_BIOS(2))
+ ROM_SYSTEM_BIOS(3, "ddfs090", "Microware DDFS 0.90")
+ ROMX_LOAD("microware_ddfs090.rom", 0x0000, 0x4000, CRC(700d50e5) SHA1(6834e46cb15354003d553e6c2bdb4ed76b47a465), ROM_BIOS(3))
+ROM_END
+
+
+//-------------------------------------------------
+// device_add_mconfig - add device configuration
+//-------------------------------------------------
+
+void bbc_udm_device::device_add_mconfig(machine_config &config)
+{
+ WD2793(config, m_fdc, DERIVED_CLOCK(1, 8));
+ m_fdc->drq_wr_callback().set(FUNC(bbc_udm_device::drq_w));
+ m_fdc->intrq_wr_callback().set(FUNC(bbc_udm_device::intrq_w));
+ m_fdc->hld_wr_callback().set(FUNC(bbc_udm_device::motor_w));
+
+ FLOPPY_CONNECTOR(config, m_floppy[0], bbc_floppies_525, "525qd", floppy_formats).enable_sound(true);
+ FLOPPY_CONNECTOR(config, m_floppy[1], bbc_floppies_525, "525qd", floppy_formats).enable_sound(true);
+}
+
+const tiny_rom_entry *bbc_udm_device::device_rom_region() const
+{
+ return ROM_NAME( udm );
+}
+
+//**************************************************************************
+// LIVE DEVICE
+//**************************************************************************
+
+//-------------------------------------------------
+// bbc_udm_device - constructor
+//-------------------------------------------------
+
+bbc_udm_device::bbc_udm_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
+ : device_t(mconfig, BBC_UDM, tag, owner, clock)
+ , device_bbc_fdc_interface(mconfig, *this)
+ , m_fdc(*this, "wd2793")
+ , m_floppy(*this, "wd2793:%u", 0)
+ , m_fdc_ie(0)
+{
+}
+
+//-------------------------------------------------
+// device_start - device-specific startup
+//-------------------------------------------------
+
+void bbc_udm_device::device_start()
+{
+}
+
+
+//**************************************************************************
+// IMPLEMENTATION
+//**************************************************************************
+
+uint8_t bbc_udm_device::read(offs_t offset)
+{
+ uint8_t data;
+
+ if (offset & 0x04)
+ {
+ data = m_fdc->read(offset & 0x03);
+ }
+ else
+ {
+ data = 0xfe;
+ }
+ return data;
+}
+
+void bbc_udm_device::write(offs_t offset, uint8_t data)
+{
+ if (offset & 0x04)
+ {
+ m_fdc->write(offset & 0x03, data);
+ }
+ else
+ {
+ floppy_image_device *floppy = nullptr;
+
+ // bit 0: drive select
+ floppy = m_floppy[BIT(data, 0)]->get_device();
+ m_fdc->set_floppy(floppy);
+
+ // bit 1: side select
+ if (floppy)
+ floppy->ss_w(!BIT(data, 1));
+
+ // bit 2: density
+ m_fdc->dden_w(!BIT(data, 2));
+
+ // bit 3: master reset
+ m_fdc->mr_w(BIT(data, 3));
+
+ // bit 4: interrupt enable
+ m_fdc_ie = BIT(data, 4);
+ }
+}
+
+void bbc_udm_device::intrq_w(int state)
+{
+ m_slot->intrq_w((state && m_fdc_ie) ? ASSERT_LINE : CLEAR_LINE);
+}
+
+void bbc_udm_device::drq_w(int state)
+{
+ m_slot->drq_w((state && m_fdc_ie) ? ASSERT_LINE : CLEAR_LINE);
+}
+
+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/microware.h b/src/devices/bus/bbc/fdc/udm.h
index 61c0cb358cf..330d9eb736a 100644
--- a/src/devices/bus/bbc/fdc/microware.h
+++ b/src/devices/bus/bbc/fdc/udm.h
@@ -2,64 +2,58 @@
// copyright-holders:Nigel Barnes
/**********************************************************************
- United Disk Memories DDFS FDC
-
- Microware DDFS FDC
+ Microware / United Disk Memories DDFS FDC
**********************************************************************/
-
-#ifndef MAME_BUS_BBC_FDC_MICROWARE_H
-#define MAME_BUS_BBC_FDC_MICROWARE_H
+#ifndef MAME_BUS_BBC_FDC_UDM_H
+#define MAME_BUS_BBC_FDC_UDM_H
#pragma once
#include "fdc.h"
#include "imagedev/floppy.h"
#include "machine/wd_fdc.h"
-#include "formats/acorn_dsk.h"
-#include "formats/fsd_dsk.h"
//**************************************************************************
// TYPE DEFINITIONS
//**************************************************************************
-class bbc_microware_device :
+class bbc_udm_device :
public device_t,
public device_bbc_fdc_interface
{
public:
- static constexpr feature_type imperfect_features() { return feature::DISK; }
-
// construction/destruction
- bbc_microware_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
+ bbc_udm_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_start() override ATTR_COLD;
// optional information overrides
- virtual void device_add_mconfig(machine_config &config) override;
- virtual const tiny_rom_entry *device_rom_region() const override;
+ virtual void device_add_mconfig(machine_config &config) override ATTR_COLD;
+ virtual const tiny_rom_entry *device_rom_region() const override ATTR_COLD;
virtual uint8_t read(offs_t offset) override;
virtual void write(offs_t offset, uint8_t data) override;
private:
- DECLARE_FLOPPY_FORMATS(floppy_formats);
+ static void floppy_formats(format_registration &fr);
- 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<floppy_connector> m_floppy0;
- optional_device<floppy_connector> m_floppy1;
+ required_device_array<floppy_connector, 2> m_floppy;
- int m_drive_control;
+ int m_fdc_ie;
};
// device type definition
-DECLARE_DEVICE_TYPE(BBC_MICROWARE, bbc_microware_device);
+DECLARE_DEVICE_TYPE(BBC_UDM, bbc_udm_device);
-#endif /* MAME_BUS_BBC_FDC_MICROWARE_H */
+#endif /* MAME_BUS_BBC_FDC_UDM_H */
diff --git a/src/devices/bus/bbc/fdc/watford.cpp b/src/devices/bus/bbc/fdc/watford.cpp
index 4c3f31344ee..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
@@ -24,14 +26,16 @@ DEFINE_DEVICE_TYPE(BBC_WEDDB3, bbc_weddb3_device, "bbc_weddb3", "Watford Electro
//-------------------------------------------------
-// MACHINE_DRIVER( watford )
+// FLOPPY_FORMATS( floppy_formats )
//-------------------------------------------------
-FLOPPY_FORMATS_MEMBER( bbc_watfordfdc_device::floppy_formats )
- FLOPPY_ACORN_SSD_FORMAT,
- FLOPPY_ACORN_DSD_FORMAT,
- FLOPPY_FSD_FORMAT
-FLOPPY_FORMATS_END0
+void bbc_watfordfdc_device::floppy_formats(format_registration &fr)
+{
+ fr.add_mfm_containers();
+ fr.add(FLOPPY_ACORN_SSD_FORMAT);
+ fr.add(FLOPPY_ACORN_DSD_FORMAT);
+ fr.add(FLOPPY_FSD_FORMAT);
+}
static void bbc_floppies_525(device_slot_interface &device)
{
@@ -42,6 +46,10 @@ static void bbc_floppies_525(device_slot_interface &device)
device.option_add("525qd", FLOPPY_525_QD);
}
+//-------------------------------------------------
+// ROM( watford )
+//-------------------------------------------------
+
ROM_START( weddb2 )
ROM_REGION(0x4000, "dfs_rom", 0)
ROM_DEFAULT_BIOS("ddfs153")
@@ -71,8 +79,8 @@ void bbc_weddb2_device::device_add_mconfig(machine_config &config)
m_fdc->intrq_wr_callback().set(DEVICE_SELF_OWNER, FUNC(bbc_fdc_slot_device::intrq_w));
m_fdc->drq_wr_callback().set(DEVICE_SELF_OWNER, FUNC(bbc_fdc_slot_device::drq_w));
- FLOPPY_CONNECTOR(config, m_floppy0, bbc_floppies_525, "525qd", floppy_formats).enable_sound(true);
- FLOPPY_CONNECTOR(config, m_floppy1, bbc_floppies_525, "525qd", floppy_formats).enable_sound(true);
+ FLOPPY_CONNECTOR(config, m_floppy[0], bbc_floppies_525, "525qd", floppy_formats).enable_sound(true);
+ FLOPPY_CONNECTOR(config, m_floppy[1], bbc_floppies_525, "525qd", floppy_formats).enable_sound(true);
}
void bbc_weddb3_device::device_add_mconfig(machine_config &config)
@@ -81,8 +89,8 @@ void bbc_weddb3_device::device_add_mconfig(machine_config &config)
m_fdc->intrq_wr_callback().set(DEVICE_SELF_OWNER, FUNC(bbc_fdc_slot_device::intrq_w));
m_fdc->drq_wr_callback().set(DEVICE_SELF_OWNER, FUNC(bbc_fdc_slot_device::drq_w));
- FLOPPY_CONNECTOR(config, m_floppy0, bbc_floppies_525, "525qd", floppy_formats).enable_sound(true);
- FLOPPY_CONNECTOR(config, m_floppy1, bbc_floppies_525, "525qd", floppy_formats).enable_sound(true);
+ FLOPPY_CONNECTOR(config, m_floppy[0], bbc_floppies_525, "525qd", floppy_formats).enable_sound(true);
+ FLOPPY_CONNECTOR(config, m_floppy[1], bbc_floppies_525, "525qd", floppy_formats).enable_sound(true);
}
const tiny_rom_entry *bbc_weddb2_device::device_rom_region() const
@@ -113,8 +121,7 @@ bbc_watfordfdc_device::bbc_watfordfdc_device(const machine_config &mconfig, devi
bbc_weddb2_device::bbc_weddb2_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
: bbc_watfordfdc_device(mconfig, BBC_WEDDB2, tag, owner, clock)
, m_fdc(*this, "wd1772")
- , m_floppy0(*this, "wd1772:0")
- , m_floppy1(*this, "wd1772:1")
+ , m_floppy(*this, "wd1772:%u", 0)
, m_drive_control(0)
{
}
@@ -122,8 +129,7 @@ bbc_weddb2_device::bbc_weddb2_device(const machine_config &mconfig, const char *
bbc_weddb3_device::bbc_weddb3_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
: bbc_watfordfdc_device(mconfig, BBC_WEDDB3, tag, owner, clock)
, m_fdc(*this, "wd1770")
- , m_floppy0(*this, "wd1770:0")
- , m_floppy1(*this, "wd1770:1")
+ , m_floppy(*this, "wd1770:%u", 0)
, m_drive_control(0)
{
}
@@ -175,8 +181,8 @@ void bbc_weddb2_device::write(offs_t offset, uint8_t data)
m_drive_control = data;
// bit 2: drive select
- floppy_image_device *floppy0 = m_floppy0->get_device();
- floppy_image_device *floppy1 = m_floppy1->get_device();
+ floppy_image_device *floppy0 = m_floppy[0]->get_device();
+ floppy_image_device *floppy1 = m_floppy[1]->get_device();
floppy = (BIT(data, 2) ? floppy1 : floppy0);
m_fdc->set_floppy(floppy);
@@ -188,7 +194,7 @@ void bbc_weddb2_device::write(offs_t offset, uint8_t data)
floppy->ss_w(BIT(data, 1));
// bit 3: reset
- if (!BIT(data, 3)) m_fdc->soft_reset();
+ m_fdc->mr_w(BIT(data, 3));
}
}
@@ -220,8 +226,8 @@ void bbc_weddb3_device::write(offs_t offset, uint8_t data)
m_drive_control = data;
// bit 0, 1: drive select
- 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);
// bit 2: side select
@@ -232,6 +238,6 @@ void bbc_weddb3_device::write(offs_t offset, uint8_t data)
m_fdc->dden_w(BIT(data, 3));
// bit 5: reset
- if (!BIT(data, 5)) m_fdc->soft_reset();
+ m_fdc->mr_w(BIT(data, 5));
}
}
diff --git a/src/devices/bus/bbc/fdc/watford.h b/src/devices/bus/bbc/fdc/watford.h
index 2f1cfa65c64..e0b22879e37 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
@@ -26,7 +24,7 @@ class bbc_watfordfdc_device :
public device_bbc_fdc_interface
{
public:
- DECLARE_FLOPPY_FORMATS(floppy_formats);
+ static void floppy_formats(format_registration &fr);
protected:
// construction/destruction
@@ -40,18 +38,17 @@ public:
protected:
// device-level overrides
- virtual void device_start() override;
+ virtual void device_start() override ATTR_COLD;
- virtual void device_add_mconfig(machine_config &config) override;
- virtual const tiny_rom_entry *device_rom_region() const override;
+ virtual void device_add_mconfig(machine_config &config) override ATTR_COLD;
+ virtual const tiny_rom_entry *device_rom_region() const override ATTR_COLD;
virtual uint8_t read(offs_t offset) override;
virtual void write(offs_t offset, uint8_t data) override;
private:
required_device<wd_fdc_device_base> m_fdc;
- required_device<floppy_connector> m_floppy0;
- optional_device<floppy_connector> m_floppy1;
+ required_device_array<floppy_connector, 2> m_floppy;
int m_drive_control;
};
@@ -63,18 +60,17 @@ public:
protected:
// device-level overrides
- virtual void device_start() override;
+ virtual void device_start() override ATTR_COLD;
- virtual void device_add_mconfig(machine_config &config) override;
- virtual const tiny_rom_entry *device_rom_region() const override;
+ virtual void device_add_mconfig(machine_config &config) override ATTR_COLD;
+ virtual const tiny_rom_entry *device_rom_region() const override ATTR_COLD;
virtual uint8_t read(offs_t offset) override;
virtual void write(offs_t offset, uint8_t data) override;
private:
required_device<wd_fdc_device_base> m_fdc;
- required_device<floppy_connector> m_floppy0;
- optional_device<floppy_connector> m_floppy1;
+ required_device_array<floppy_connector, 2> m_floppy;
int m_drive_control;
};
diff --git a/src/devices/bus/bbc/internal/aries.cpp b/src/devices/bus/bbc/internal/aries.cpp
new file mode 100644
index 00000000000..1ee29009129
--- /dev/null
+++ b/src/devices/bus/bbc/internal/aries.cpp
@@ -0,0 +1,337 @@
+// license:BSD-3-Clause
+// copyright-holders:Nigel Barnes
+/**********************************************************************
+
+ Aries B12 Sideways ROM Expansion
+ http://chrisacorns.computinghistory.org.uk/8bit_Upgrades/Aries_B12.html
+
+ Aries B20 20K RAM expansion
+ http://chrisacorns.computinghistory.org.uk/8bit_Upgrades/Aries_B20.html
+
+ Aries-B32 32K RAM expansion
+ http://chrisacorns.computinghistory.org.uk/8bit_Upgrades/Aries_B32.html
+
+**********************************************************************/
+
+
+#include "emu.h"
+#include "aries.h"
+
+
+//**************************************************************************
+// DEVICE DEFINITIONS
+//**************************************************************************
+
+DEFINE_DEVICE_TYPE(BBC_ARIESB12, bbc_ariesb12_device, "bbc_ariesb12", "Aries-B12 ROM Expansion");
+DEFINE_DEVICE_TYPE(BBC_ARIESB20, bbc_ariesb20_device, "bbc_ariesb20", "Aries-B20 RAM expansion (w/ Aries-B12)");
+DEFINE_DEVICE_TYPE(BBC_ARIESB32, bbc_ariesb32_device, "bbc_ariesb32", "Aries-B32 RAM expansion (w/ Aries-B12)");
+
+
+//-------------------------------------------------
+// ROM( aries )
+//-------------------------------------------------
+
+ROM_START(ariesb20)
+ ROM_REGION(0x4000, "exp_rom", 0)
+ ROM_SYSTEM_BIOS(0, "24", "v2.4")
+ ROMX_LOAD("aries-b20_v2.4.rom", 0x0000, 0x2000, CRC(47a43a03) SHA1(2590596e0864b97b30050c33b21aa89bb8956204), ROM_BIOS(0))
+ ROM_SYSTEM_BIOS(1, "22", "v2.2")
+ ROMX_LOAD("aries-b20_v2.2.rom", 0x0000, 0x2000, CRC(c2f334a9) SHA1(d04bfd332d63f6f23dca2ef81a1d2074e3d88ee9), ROM_BIOS(1))
+ROM_END
+
+ROM_START(ariesb32)
+ ROM_REGION(0x4000, "aries_rom", 0)
+ ROM_SYSTEM_BIOS(0, "22", "v2.2")
+ ROMX_LOAD("aries-b32_v2.2.rom", 0x0000, 0x4000, CRC(2cb3443d) SHA1(466e3b68f1a8e0287ae095cb3c16dac6afc89dcb), ROM_BIOS(0))
+ROM_END
+
+
+//-------------------------------------------------
+// device_add_mconfig - add device configuration
+//-------------------------------------------------
+
+void bbc_ariesb12_device::device_add_mconfig(machine_config &config)
+{
+ /* TODO: romslot0-3 are unavailable when board is fitted, replaced by sockets on board */;
+ //config.device_remove(":romslot0");
+ //config.device_remove(":romslot1");
+ //config.device_remove(":romslot2");
+ //config.device_remove(":romslot3");
+
+ /* rom/ram sockets */
+ BBC_ROMSLOT16(config, m_rom[0], bbc_rom_devices, "ram").set_fixed_ram(true);
+ BBC_ROMSLOT16(config, m_rom[1], bbc_rom_devices, nullptr);
+ BBC_ROMSLOT16(config, m_rom[2], bbc_rom_devices, nullptr);
+ BBC_ROMSLOT16(config, m_rom[3], bbc_rom_devices, nullptr);
+ BBC_ROMSLOT16(config, m_rom[4], bbc_rom_devices, nullptr);
+ BBC_ROMSLOT16(config, m_rom[5], bbc_rom_devices, nullptr);
+ BBC_ROMSLOT16(config, m_rom[6], bbc_rom_devices, nullptr);
+ BBC_ROMSLOT16(config, m_rom[7], bbc_rom_devices, nullptr);
+ BBC_ROMSLOT16(config, m_rom[8], bbc_rom_devices, nullptr);
+ BBC_ROMSLOT16(config, m_rom[9], bbc_rom_devices, nullptr);
+ BBC_ROMSLOT16(config, m_rom[10], bbc_rom_devices, nullptr);
+ BBC_ROMSLOT16(config, m_rom[11], bbc_rom_devices, nullptr);
+ BBC_ROMSLOT16(config, m_rom[12], bbc_rom_devices, nullptr);
+}
+
+void bbc_ariesb32_device::device_add_mconfig(machine_config &config)
+{
+ bbc_ariesb12_device::device_add_mconfig(config);
+
+ BBC_ROMSLOT16(config, m_rom[15], bbc_rom_devices, nullptr);
+}
+
+//-------------------------------------------------
+// rom_region - device-specific ROM region
+//-------------------------------------------------
+
+const tiny_rom_entry *bbc_ariesb20_device::device_rom_region() const
+{
+ return ROM_NAME(ariesb20);
+}
+
+const tiny_rom_entry *bbc_ariesb32_device::device_rom_region() const
+{
+ return ROM_NAME(ariesb32);
+}
+
+//**************************************************************************
+// LIVE DEVICE
+//**************************************************************************
+
+//-------------------------------------------------
+// bbc_aries_device - constructor
+//-------------------------------------------------
+
+bbc_ariesb12_device::bbc_ariesb12_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_internal_interface(mconfig, *this)
+ , m_rom(*this, "romslot%u", 0U)
+{
+}
+
+bbc_ariesb12_device::bbc_ariesb12_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
+ : bbc_ariesb12_device(mconfig, BBC_ARIESB12, tag, owner, clock)
+{
+}
+
+bbc_ariesb20_device::bbc_ariesb20_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
+ : bbc_ariesb12_device(mconfig, BBC_ARIESB20, tag, owner, clock)
+{
+}
+
+bbc_ariesb32_device::bbc_ariesb32_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
+ : bbc_ariesb12_device(mconfig, BBC_ARIESB32, tag, owner, clock)
+ , m_aries_rom(*this, "aries_rom")
+{
+}
+
+//-------------------------------------------------
+// device_start - device-specific startup
+//-------------------------------------------------
+
+void bbc_ariesb12_device::device_start()
+{
+ /* move internal roms to board */
+ memmove(m_region_swr->base() + 0x24000, m_region_swr->base(), 0x10000);
+ memset(m_region_swr->base(), 0xff, 0x10000);
+
+ /* register for save states */
+ save_item(NAME(m_romsel));
+}
+
+void bbc_ariesb20_device::device_start()
+{
+ bbc_ariesb12_device::device_start();
+
+ m_shadow = false;
+ m_ram = std::make_unique<uint8_t[]>(0x5000);
+
+ /* register for save states */
+ save_item(NAME(m_shadow));
+ save_pointer(NAME(m_ram), 0x5000);
+}
+
+void bbc_ariesb32_device::device_start()
+{
+ bbc_ariesb12_device::device_start();
+
+ m_shadow = false;
+ m_ram = std::make_unique<uint8_t[]>(0x8000);
+
+ /* move internal roms to board */
+ memcpy(m_region_swr->base() + 0x3c000, m_aries_rom->base(), 0x4000);
+
+ /* register for save states */
+ save_item(NAME(m_ramsel));
+ save_item(NAME(m_shadow));
+ save_pointer(NAME(m_ram), 0x8000);
+}
+
+//-------------------------------------------------
+// device_reset - device-specific reset
+//-------------------------------------------------
+
+void bbc_ariesb20_device::device_reset()
+{
+ address_space &program = m_maincpu->space(AS_PROGRAM);
+
+ program.install_write_handler(0xfffe, 0xffff, write8sm_delegate(*this, FUNC(bbc_ariesb20_device::control_w)));
+}
+
+
+//**************************************************************************
+// IMPLEMENTATION
+//**************************************************************************
+
+uint8_t bbc_ariesb12_device::paged_r(offs_t offset)
+{
+ uint8_t data = 0xff;
+
+ if (m_rom[m_romsel] && m_rom[m_romsel]->present())
+ {
+ data = m_rom[m_romsel]->read(offset);
+ }
+ else
+ {
+ data = m_region_swr->base()[offset + (m_romsel << 14)];
+ }
+
+ return data;
+}
+
+void bbc_ariesb12_device::paged_w(offs_t offset, uint8_t data)
+{
+ if (m_rom[m_romsel] && m_rom[m_romsel]->present())
+ {
+ m_rom[m_romsel]->write(offset, data);
+ }
+
+ /* always write to sideways ram */
+ m_rom[0x00]->write(offset, data);
+}
+
+
+void bbc_ariesb20_device::control_w(offs_t offset, uint8_t data)
+{
+ switch (offset)
+ {
+ case 0:
+ /* &fffe - select BBC ram */
+ m_shadow = false;
+ break;
+ case 1:
+ /* &ffff - select Aries ram */
+ m_shadow = true;
+ break;
+ }
+}
+
+uint8_t bbc_ariesb20_device::ram_r(offs_t offset)
+{
+ uint8_t data = 0xff;
+
+ if (m_shadow && offset >= 0x3000)
+ data = m_ram[offset - 0x3000];
+ else
+ data = m_mb_ram->pointer()[offset];
+
+ return data;
+}
+
+void bbc_ariesb20_device::ram_w(offs_t offset, uint8_t data)
+{
+ if (m_shadow && offset >= 0x3000)
+ m_ram[offset - 0x3000] = data;
+ else
+ m_mb_ram->pointer()[offset] = data;
+}
+
+
+void bbc_ariesb32_device::romsel_w(offs_t offset, uint8_t data)
+{
+ //logerror("romsel_w: %04x = %02x\n", offset | 0xfe30, data);
+
+ switch (offset)
+ {
+ case 0x00:
+ m_romsel = data & 0x0f;
+ break;
+ case 0x02:
+ m_ramsel = data & 0x0f;
+ break;
+ case 0x04:
+ break;
+ case 0x06:
+ // switch
+ break;
+ case 0x08:
+ break;
+ case 0x0a:
+ // switch
+ break;
+ case 0x0e:
+ m_shadow = false;
+ break;
+ case 0x0f:
+ m_shadow = true;
+ break;
+ }
+}
+
+uint8_t bbc_ariesb32_device::ram_r(offs_t offset)
+{
+ uint8_t data = 0xff;
+
+ if (m_shadow && offset >= 0x3000)
+ data = m_ram[offset - 0x3000];
+ else
+ data = m_mb_ram->pointer()[offset];
+
+ return data;
+}
+
+void bbc_ariesb32_device::ram_w(offs_t offset, uint8_t data)
+{
+ //if ((offset & 0xff) == 0x00)
+ // logerror("ram_w: %04x = %02x\n", offset, data);
+ if (m_shadow && offset >= 0x3000)
+ m_ram[offset - 0x3000] = data;
+ else
+ m_mb_ram->pointer()[offset] = data;
+}
+
+uint8_t bbc_ariesb32_device::paged_r(offs_t offset)
+{
+ uint8_t data = 0xff;
+
+ if (m_rom[m_romsel] && m_rom[m_romsel]->present())
+ {
+ data = m_rom[m_romsel]->read(offset);
+ }
+ else if (m_romsel == 13 || m_romsel == 14)
+ {
+ data = m_ram[offset | (m_romsel & 0x02) << 13];
+ }
+ else
+ {
+ data = m_region_swr->base()[offset + (m_romsel << 14)];
+ }
+
+ return data;
+}
+
+void bbc_ariesb32_device::paged_w(offs_t offset, uint8_t data)
+{
+ //if ((offset & 0xff) == 0x00)
+ // logerror("paged_w: %04x = %02x\n", offset | 0x8000, data);
+ if (m_rom[m_romsel])
+ {
+ m_rom[m_romsel]->write(offset, data);
+ }
+
+ if (m_ramsel == 13 || m_ramsel == 14)
+ {
+ m_ram[offset | (m_ramsel & 0x02) << 13] = data;
+ }
+}
diff --git a/src/devices/bus/bbc/internal/aries.h b/src/devices/bus/bbc/internal/aries.h
new file mode 100644
index 00000000000..111cd5e6461
--- /dev/null
+++ b/src/devices/bus/bbc/internal/aries.h
@@ -0,0 +1,117 @@
+// license:BSD-3-Clause
+// copyright-holders:Nigel Barnes
+/**********************************************************************
+
+ Aries B12 Sideways ROM Expansion
+ http://chrisacorns.computinghistory.org.uk/8bit_Upgrades/Aries_B12.html
+
+ Aries B20 20K RAM expansion
+ http://chrisacorns.computinghistory.org.uk/8bit_Upgrades/Aries_B20.html
+
+ Aries-B32 32K RAM expansion
+ http://chrisacorns.computinghistory.org.uk/8bit_Upgrades/Aries_B32.html
+
+**********************************************************************/
+
+
+#ifndef MAME_BUS_BBC_INTERNAL_ARIES_H
+#define MAME_BUS_BBC_INTERNAL_ARIES_H
+
+#include "internal.h"
+
+
+//**************************************************************************
+// TYPE DEFINITIONS
+//**************************************************************************
+
+class bbc_ariesb12_device :
+ public device_t,
+ public device_bbc_internal_interface
+{
+public:
+ // construction/destruction
+ bbc_ariesb12_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
+
+protected:
+ bbc_ariesb12_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 ATTR_COLD;
+
+ // optional information overrides
+ virtual void device_add_mconfig(machine_config &config) override ATTR_COLD;
+
+ virtual bool overrides_rom() override { return true; }
+ virtual void romsel_w(offs_t offset, uint8_t data) override { m_romsel = data & 0x0f; }
+ virtual uint8_t paged_r(offs_t offset) override;
+ virtual void paged_w(offs_t offset, uint8_t data) override;
+
+ optional_device_array<bbc_romslot_device, 16> m_rom;
+
+ uint8_t m_romsel;
+};
+
+
+class bbc_ariesb20_device : public bbc_ariesb12_device
+{
+public:
+ // construction/destruction
+ bbc_ariesb20_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
+
+protected:
+ // device-level overrides
+ virtual void device_start() override ATTR_COLD;
+ virtual void device_reset() override ATTR_COLD;
+
+ // optional information overrides
+ virtual const tiny_rom_entry *device_rom_region() const override ATTR_COLD;
+
+ virtual bool overrides_ram() override { return true; }
+ virtual uint8_t ram_r(offs_t offset) override;
+ virtual void ram_w(offs_t offset, uint8_t data) override;
+
+private:
+ void control_w(offs_t offset, uint8_t data);
+
+ bool m_shadow;
+ std::unique_ptr<uint8_t[]> m_ram;
+};
+
+
+class bbc_ariesb32_device : public bbc_ariesb12_device
+{
+public:
+ // construction/destruction
+ bbc_ariesb32_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
+
+protected:
+ // device-level overrides
+ virtual void device_start() override ATTR_COLD;
+
+ // optional information overrides
+ virtual void device_add_mconfig(machine_config &config) override ATTR_COLD;
+ virtual const tiny_rom_entry *device_rom_region() const override ATTR_COLD;
+
+ virtual bool overrides_ram() override { return true; }
+ virtual uint8_t ram_r(offs_t offset) override;
+ virtual void ram_w(offs_t offset, uint8_t data) override;
+ virtual void romsel_w(offs_t offset, uint8_t data) override;
+ virtual uint8_t paged_r(offs_t offset) override;
+ virtual void paged_w(offs_t offset, uint8_t data) override;
+
+private:
+ required_memory_region m_aries_rom;
+
+ bool m_shadow;
+ std::unique_ptr<uint8_t[]> m_ram;
+ uint8_t m_ramsel;
+};
+
+
+// device type definition
+DECLARE_DEVICE_TYPE(BBC_ARIESB12, bbc_ariesb12_device);
+DECLARE_DEVICE_TYPE(BBC_ARIESB20, bbc_ariesb20_device);
+DECLARE_DEVICE_TYPE(BBC_ARIESB32, bbc_ariesb32_device);
+
+
+#endif /* MAME_BUS_BBC_INTERNAL_ARIES_H */
diff --git a/src/devices/bus/bbc/internal/atpl.cpp b/src/devices/bus/bbc/internal/atpl.cpp
new file mode 100644
index 00000000000..94c5f8459b0
--- /dev/null
+++ b/src/devices/bus/bbc/internal/atpl.cpp
@@ -0,0 +1,250 @@
+// license:BSD-3-Clause
+// copyright-holders:Nigel Barnes
+/**********************************************************************
+
+ ATPL Sidewise ROM/RAM Expansion board
+ https://www.retro-kit.co.uk/page.cfm/content/ATPL-Sidewise-Sideways-ROM-board/
+
+ ATPL Sidewise+
+ http://chrisacorns.computinghistory.org.uk/8bit_Upgrades/ATPL_Sidewise+.html
+
+**********************************************************************/
+
+
+#include "emu.h"
+#include "atpl.h"
+
+
+//**************************************************************************
+// DEVICE DEFINITIONS
+//**************************************************************************
+
+DEFINE_DEVICE_TYPE(BBC_ATPLSW, bbc_atplsw_device, "bbc_atplsw", "ATPL Sidewise ROM/RAM Expansion");
+DEFINE_DEVICE_TYPE(BBC_ATPLSWP, bbc_atplswp_device, "bbc_atplswp", "ATPL Sidewise+ ROM Expansion");
+
+
+//-------------------------------------------------
+// INPUT_PORTS( atplsw )
+//-------------------------------------------------
+
+static INPUT_PORTS_START(atplsw)
+ PORT_START("wp")
+ PORT_CONFNAME(0x01, 0x00, "Write Protect Sideways RAM")
+ PORT_CONFSETTING(0x00, DEF_STR(No))
+ PORT_CONFSETTING(0x01, DEF_STR(Yes))
+INPUT_PORTS_END
+
+//-------------------------------------------------
+// input_ports - device-specific input ports
+//-------------------------------------------------
+
+ioport_constructor bbc_atplsw_device::device_input_ports() const
+{
+ return INPUT_PORTS_NAME(atplsw);
+}
+
+//-------------------------------------------------
+// device_add_mconfig - add device configuration
+//-------------------------------------------------
+
+void bbc_atplsw_device::device_add_mconfig(machine_config &config)
+{
+ /* 12 rom sockets, 16K static ram (battery backed) */
+ BBC_ROMSLOT16(config, m_rom[4], bbc_rom_devices, nullptr);
+ BBC_ROMSLOT16(config, m_rom[5], bbc_rom_devices, nullptr);
+ BBC_ROMSLOT16(config, m_rom[6], bbc_rom_devices, nullptr);
+ BBC_ROMSLOT16(config, m_rom[7], bbc_rom_devices, nullptr);
+ BBC_ROMSLOT16(config, m_rom[8], bbc_rom_devices, nullptr);
+ BBC_ROMSLOT16(config, m_rom[9], bbc_rom_devices, nullptr);
+ BBC_ROMSLOT16(config, m_rom[10], bbc_rom_devices, nullptr);
+ BBC_ROMSLOT16(config, m_rom[11], bbc_rom_devices, nullptr);
+ BBC_ROMSLOT16(config, m_rom[12], bbc_rom_devices, nullptr);
+ BBC_ROMSLOT16(config, m_rom[13], bbc_rom_devices, nullptr);
+ BBC_ROMSLOT16(config, m_rom[14], bbc_rom_devices, nullptr);
+ BBC_ROMSLOT16(config, m_rom[15], bbc_rom_devices, "nvram").set_fixed_ram(true);
+}
+
+void bbc_atplswp_device::device_add_mconfig(machine_config &config)
+{
+ /* TODO: romslot2-10 are unavailable when board is fitted, replaced by sockets on board */
+ //config.device_remove(":romslot2");
+ //config.device_remove(":romslot4");
+ //config.device_remove(":romslot6");
+ //config.device_remove(":romslot8");
+ //config.device_remove(":romslot10");
+
+ /* 10 rom sockets */
+ BBC_ROMSLOT16(config, m_rom[2], bbc_rom_devices, nullptr);
+ BBC_ROMSLOT16(config, m_rom[3], bbc_rom_devices, nullptr);
+ BBC_ROMSLOT16(config, m_rom[4], bbc_rom_devices, nullptr);
+ BBC_ROMSLOT16(config, m_rom[5], bbc_rom_devices, nullptr);
+ BBC_ROMSLOT16(config, m_rom[6], bbc_rom_devices, nullptr);
+ BBC_ROMSLOT16(config, m_rom[7], bbc_rom_devices, nullptr);
+ BBC_ROMSLOT16(config, m_rom[8], bbc_rom_devices, nullptr);
+ BBC_ROMSLOT16(config, m_rom[9], bbc_rom_devices, nullptr);
+ BBC_ROMSLOT16(config, m_rom[10], bbc_rom_devices, nullptr);
+ BBC_ROMSLOT16(config, m_rom[11], bbc_rom_devices, nullptr);
+}
+
+//**************************************************************************
+// LIVE DEVICE
+//**************************************************************************
+
+//-------------------------------------------------
+// bbc_atplsw_device - constructor
+//-------------------------------------------------
+
+bbc_atplsw_device::bbc_atplsw_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
+ : device_t(mconfig, BBC_ATPLSW, tag, owner, clock)
+ , device_bbc_internal_interface(mconfig, *this)
+ , m_rom(*this, "romslot%u", 0U)
+ , m_wp(*this, "wp")
+{
+}
+
+bbc_atplswp_device::bbc_atplswp_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
+ : device_t(mconfig, BBC_ATPLSWP, tag, owner, clock)
+ , device_bbc_internal_interface(mconfig, *this)
+ , m_rom(*this, "romslot%u", 0U)
+{
+}
+
+//-------------------------------------------------
+// device_start - device-specific startup
+//-------------------------------------------------
+
+void bbc_atplsw_device::device_start()
+{
+ /* move internal roms to board */
+ memmove(m_region_swr->base() + 0x2c000, m_region_swr->base(), 0x10000);
+ memset(m_region_swr->base(), 0xff, 0x10000);
+
+ /* register for save states */
+ save_item(NAME(m_romsel));
+}
+
+void bbc_atplswp_device::device_start()
+{
+ /* register for save states */
+ save_item(NAME(m_romsel));
+}
+
+
+//**************************************************************************
+// IMPLEMENTATION
+//**************************************************************************
+
+uint8_t bbc_atplsw_device::paged_r(offs_t offset)
+{
+ uint8_t data = 0xff;
+
+ switch (m_romsel)
+ {
+ case 0: case 1: case 2: case 3:
+ /* motherboard rom sockets */
+ if (m_mb_rom[m_romsel] && m_mb_rom[m_romsel]->present())
+ {
+ data = m_mb_rom[m_romsel]->read(offset);
+ }
+ else
+ {
+ data = m_region_swr->base()[offset + (m_romsel << 14)];
+ }
+ break;
+ case 4: case 5: case 6: case 7: case 8: case 9: case 10: case 11: case 12: case 13: case 14: case 15:
+ /* expansion board sockets */
+ if (m_rom[m_romsel] && m_rom[m_romsel]->present())
+ {
+ data = m_rom[m_romsel]->read(offset);
+ }
+ else
+ {
+ data = m_region_swr->base()[offset + (m_romsel << 14)];
+ }
+ break;
+ }
+
+ return data;
+}
+
+void bbc_atplsw_device::paged_w(offs_t offset, uint8_t data)
+{
+ switch (m_romsel)
+ {
+ case 0: case 1: case 2: case 3:
+ /* motherboard rom sockets */
+ if (m_mb_rom[m_romsel])
+ {
+ m_mb_rom[m_romsel]->write(offset, data);
+ }
+ break;
+ case 4: case 5: case 6: case 7: case 8: case 9: case 10: case 11: case 12: case 13: case 14:
+ /* expansion board sockets */
+ if (m_rom[m_romsel])
+ {
+ m_rom[m_romsel]->write(offset, data);
+ }
+ break;
+ }
+
+ /* sideways ram (if not write protected) */
+ if (!m_wp->read())
+ {
+ m_rom[15]->write(offset, data);
+ }
+}
+
+
+uint8_t bbc_atplswp_device::paged_r(offs_t offset)
+{
+ uint8_t data = 0xff;
+
+ switch (m_romsel)
+ {
+ case 0: case 1: case 12: case 13:
+ /* motherboard ram sockets */
+ if (m_mb_rom[m_romsel & 0x0e] && m_mb_rom[m_romsel & 0x0e]->present())
+ {
+ data = m_mb_rom[m_romsel & 0x0e]->read(offset | (m_romsel & 0x01) << 14);
+ }
+ else
+ {
+ data = m_region_swr->base()[offset + (m_romsel << 14)];
+ }
+ break;
+ default:
+ /* expansion board sockets */
+ if (m_rom[m_romsel] && m_rom[m_romsel]->present())
+ {
+ data = m_rom[m_romsel]->read(offset);
+ }
+ else
+ {
+ data = m_region_swr->base()[offset + (m_romsel << 14)];
+ }
+ break;
+ }
+
+ return data;
+}
+
+void bbc_atplswp_device::paged_w(offs_t offset, uint8_t data)
+{
+ switch (m_romsel)
+ {
+ case 0: case 1: case 12: case 13:
+ /* motherboard rom sockets */
+ if (m_mb_rom[m_romsel & 0x0e])
+ {
+ m_mb_rom[m_romsel & 0x0e]->write(offset | (m_romsel & 0x01) << 14, data);
+ }
+ break;
+ default:
+ /* expansion board sockets */
+ if (m_rom[m_romsel])
+ {
+ m_rom[m_romsel]->write(offset, data);
+ }
+ break;
+ }
+}
diff --git a/src/devices/bus/bbc/internal/atpl.h b/src/devices/bus/bbc/internal/atpl.h
new file mode 100644
index 00000000000..2c26bdde184
--- /dev/null
+++ b/src/devices/bus/bbc/internal/atpl.h
@@ -0,0 +1,85 @@
+// license:BSD-3-Clause
+// copyright-holders:Nigel Barnes
+/**********************************************************************
+
+ ATPL Sidewise ROM/RAM Expansion board
+ https://www.retro-kit.co.uk/page.cfm/content/ATPL-Sidewise-Sideways-ROM-board/
+
+ ATPL Sidewise+
+ http://chrisacorns.computinghistory.org.uk/8bit_Upgrades/ATPL_Sidewise+.html
+
+**********************************************************************/
+
+
+#ifndef MAME_BUS_BBC_INTERNAL_ATPL_H
+#define MAME_BUS_BBC_INTERNAL_ATPL_H
+
+#include "internal.h"
+
+
+//**************************************************************************
+// TYPE DEFINITIONS
+//**************************************************************************
+
+class bbc_atplsw_device :
+ public device_t,
+ public device_bbc_internal_interface
+{
+public:
+ // construction/destruction
+ bbc_atplsw_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
+
+protected:
+ // device-level overrides
+ virtual void device_start() override ATTR_COLD;
+
+ // optional information overrides
+ virtual void device_add_mconfig(machine_config &config) override ATTR_COLD;
+ virtual ioport_constructor device_input_ports() const override ATTR_COLD;
+
+ virtual bool overrides_rom() override { return true; }
+ virtual void romsel_w(offs_t offset, uint8_t data) override { m_romsel = data & 0x0f; }
+ virtual uint8_t paged_r(offs_t offset) override;
+ virtual void paged_w(offs_t offset, uint8_t data) override;
+
+private:
+ optional_device_array<bbc_romslot_device, 16> m_rom;
+ required_ioport m_wp;
+
+ uint8_t m_romsel;
+};
+
+
+class bbc_atplswp_device :
+ public device_t,
+ public device_bbc_internal_interface
+{
+public:
+ // construction/destruction
+ bbc_atplswp_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
+
+protected:
+ // device-level overrides
+ virtual void device_start() override ATTR_COLD;
+
+ // optional information overrides
+ virtual void device_add_mconfig(machine_config &config) override ATTR_COLD;
+
+ virtual bool overrides_rom() override { return true; }
+ virtual void romsel_w(offs_t offset, uint8_t data) override { m_romsel = data & 0x0f; }
+ virtual uint8_t paged_r(offs_t offset) override;
+ virtual void paged_w(offs_t offset, uint8_t data) override;
+
+private:
+ optional_device_array<bbc_romslot_device, 16> m_rom;
+
+ uint8_t m_romsel;
+};
+
+
+// device type definition
+DECLARE_DEVICE_TYPE(BBC_ATPLSW, bbc_atplsw_device);
+DECLARE_DEVICE_TYPE(BBC_ATPLSWP, bbc_atplswp_device);
+
+
+#endif /* MAME_BUS_BBC_INTERNAL_ATPL_H */
diff --git a/src/devices/bus/bbc/internal/cumana68k.cpp b/src/devices/bus/bbc/internal/cumana68k.cpp
new file mode 100644
index 00000000000..4a2d7c71e2e
--- /dev/null
+++ b/src/devices/bus/bbc/internal/cumana68k.cpp
@@ -0,0 +1,324 @@
+// license:BSD-3-Clause
+// copyright-holders:Nigel Barnes
+/**********************************************************************
+
+ Cumana 68008 Upgrade Board
+
+ http://chrisacorns.computinghistory.org.uk/8bit_Upgrades/Cumana_680082ndProcessor.html
+
+ TODO:
+ - Test Winchester, when suitable image is available.
+ - RTC needs further work.
+ - Interrupt handling needs more testing.
+
+ Known Winchester:
+ - NEC D3126 -chs 615,4,17 -ss 256 (not yet imaged)
+
+**********************************************************************/
+
+#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
+//**************************************************************************
+
+DEFINE_DEVICE_TYPE(BBC_CUMANA68K, bbc_cumana68k_device, "bbc_cumana68k", "Cumana 68008 Upgrade Board")
+
+
+//-------------------------------------------------
+// ADDRESS_MAP( cumana68k_mem )
+//-------------------------------------------------
+
+void bbc_cumana68k_device::cumana68k_mem(address_map &map)
+{
+ map(0x00000, 0x7ffff).rw(FUNC(bbc_cumana68k_device::mem6502_r), FUNC(bbc_cumana68k_device::mem6502_w));
+ map(0x80000, 0xfffff).ram();
+}
+
+//-------------------------------------------------
+// FLOPPY_FORMATS( floppy_formats )
+//-------------------------------------------------
+
+void bbc_cumana68k_device::floppy_formats(format_registration &fr)
+{
+ fr.add_mfm_containers();
+ fr.add(FLOPPY_OS9_FORMAT);
+}
+
+//-------------------------------------------------
+// ROM( cumana68k )
+//-------------------------------------------------
+
+ROM_START(cumana68k)
+ ROM_REGION(0x4000, "exp_rom", 0)
+ ROM_LOAD("os9boot.rom", 0x0000, 0x4000, CRC(9b7d6754) SHA1(1cb54119bf13b39d598573d8d6a7e9f70d88b50d))
+ROM_END
+
+//-------------------------------------------------
+// device_add_mconfig - add device configuration
+//-------------------------------------------------
+
+void bbc_cumana68k_device::device_add_mconfig(machine_config &config)
+{
+ /* basic machine hardware */
+ M68008(config, m_m68008, 16_MHz_XTAL / 2);
+ m_m68008->set_addrmap(AS_PROGRAM, &bbc_cumana68k_device::cumana68k_mem);
+
+ /* fdc */
+ WD2797(config, m_fdc, 16_MHz_XTAL / 16);
+ m_fdc->intrq_wr_callback().set(m_pia_rtc, FUNC(pia6821_device::cb1_w));
+ m_fdc->drq_wr_callback().set(m_pia_sasi, FUNC(pia6821_device::pb6_w));
+ m_fdc->drq_wr_callback().append(DEVICE_SELF_OWNER, FUNC(bbc_internal_slot_device::nmi_w));
+ m_fdc->set_force_ready(true);
+
+ FLOPPY_CONNECTOR(config, m_floppy[0], "525qd", FLOPPY_525_QD, true, bbc_cumana68k_device::floppy_formats).enable_sound(true);
+ FLOPPY_CONNECTOR(config, m_floppy[1], "525qd", FLOPPY_525_QD, true, bbc_cumana68k_device::floppy_formats).enable_sound(true);
+ FLOPPY_CONNECTOR(config, m_floppy[2], "525qd", FLOPPY_525_QD, false, bbc_cumana68k_device::floppy_formats).enable_sound(true);
+ FLOPPY_CONNECTOR(config, m_floppy[3], "525qd", FLOPPY_525_QD, false, bbc_cumana68k_device::floppy_formats).enable_sound(true);
+
+ /* sasi */
+ NSCSI_BUS(config, "sasi");
+ NSCSI_CONNECTOR(config, "sasi:0", default_scsi_devices, "s1410");
+ NSCSI_CONNECTOR(config, "sasi:7", default_scsi_devices, "scsicb", true)
+ .option_add_internal("scsicb", NSCSI_CB)
+ .machine_config([this](device_t* device) {
+ downcast<nscsi_callback_device&>(*device).io_callback().set(m_pia_sasi, FUNC(pia6821_device::pb2_w));
+ downcast<nscsi_callback_device&>(*device).bsy_callback().set(m_pia_sasi, FUNC(pia6821_device::pb3_w));
+ downcast<nscsi_callback_device&>(*device).cd_callback().set(m_pia_sasi, FUNC(pia6821_device::pb4_w));
+ downcast<nscsi_callback_device&>(*device).msg_callback().set(m_pia_sasi, FUNC(pia6821_device::pb5_w));
+ downcast<nscsi_callback_device&>(*device).req_callback().set(m_pia_sasi, FUNC(pia6821_device::pb7_w));
+ downcast<nscsi_callback_device&>(*device).req_callback().append(m_pia_sasi, FUNC(pia6821_device::ca1_w));
+ });
+
+ 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));
+ m_pia_sasi->cb1_w(1); // tied to +5V
+ m_pia_sasi->ca2_handler().set(m_sasi, FUNC(nscsi_callback_device::ack_w));
+ m_pia_sasi->cb2_handler().set(m_sasi, FUNC(nscsi_callback_device::rst_w));
+ 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);
+ 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));
+ m_pia_rtc->ca2_handler().set(FUNC(bbc_cumana68k_device::rtc_ce_w));
+ m_pia_rtc->cb2_handler().set(FUNC(bbc_cumana68k_device::reset68008_w));
+ m_pia_rtc->irqa_handler().set(m_irqs, FUNC(input_merger_device::in_w<2>));
+ m_pia_rtc->irqb_handler().set(m_irqs, FUNC(input_merger_device::in_w<3>));
+
+ INPUT_MERGER_ANY_HIGH(config, m_irqs).output_handler().set(DEVICE_SELF_OWNER, FUNC(bbc_internal_slot_device::irq_w));
+
+ /* rtc */
+ MC146818(config, m_rtc, 32.768_kHz_XTAL);
+ m_rtc->irq().set(m_pia_rtc, FUNC(pia6821_device::ca1_w));
+
+ /* software lists */
+ SOFTWARE_LIST(config, "flop_ls_68008").set_original("bbc_flop_68000").set_filter("Cumana");
+}
+
+//-------------------------------------------------
+// rom_region - device-specific ROM region
+//-------------------------------------------------
+
+const tiny_rom_entry *bbc_cumana68k_device::device_rom_region() const
+{
+ return ROM_NAME( cumana68k );
+}
+
+//**************************************************************************
+// LIVE DEVICE
+//**************************************************************************
+
+//-------------------------------------------------
+// bbc_cumana68k_device - constructor
+//-------------------------------------------------
+
+bbc_cumana68k_device::bbc_cumana68k_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
+ : device_t(mconfig, BBC_CUMANA68K, tag, owner, clock)
+ , device_bbc_internal_interface(mconfig, *this)
+ , m_m68008(*this, "m68008")
+ , m_pia_sasi(*this, "pia_sasi")
+ , m_pia_rtc(*this, "pia_rtc")
+ , m_irqs(*this, "irqs")
+ , m_rtc(*this, "rtc")
+ , m_fdc(*this, "wd2797")
+ , m_floppy(*this, "wd2797:%u", 0)
+ , m_sasi(*this, "sasi:7:scsicb")
+ , m_masknmi(0)
+ , m_mc146818_data(0)
+ , m_mc146818_as(0)
+ , m_mc146818_ds(0)
+ , m_mc146818_rw(0)
+ , m_mc146818_ce(0)
+{
+}
+
+//-------------------------------------------------
+// device_start - device-specific startup
+//-------------------------------------------------
+
+void bbc_cumana68k_device::device_start()
+{
+ address_space &program = m_maincpu->space(AS_PROGRAM);
+
+ program.install_readwrite_handler(0xfc40, 0xfc43, read8sm_delegate(*m_pia_sasi, FUNC(pia6821_device::read)), write8sm_delegate(*m_pia_sasi, FUNC(pia6821_device::write)));
+ program.install_readwrite_handler(0xfc44, 0xfc47, read8sm_delegate(*m_pia_rtc, FUNC(pia6821_device::read)), write8sm_delegate(*m_pia_rtc, FUNC(pia6821_device::write)));
+ program.install_readwrite_handler(0xfc48, 0xfc4b, read8sm_delegate(*m_fdc, FUNC(wd2797_device::read)), write8sm_delegate(*m_fdc, FUNC(wd2797_device::write)));
+ program.install_write_handler(0xfc4c, 0xfc4f, write8sm_delegate(*this, FUNC(bbc_cumana68k_device::fsel_w)));
+
+ /* register for save states */
+ save_item(NAME(m_mc146818_as));
+ save_item(NAME(m_mc146818_ds));
+ save_item(NAME(m_mc146818_rw));
+ save_item(NAME(m_masknmi));
+}
+
+//-------------------------------------------------
+// device_reset_after_children - reset after child devices
+//-------------------------------------------------
+
+void bbc_cumana68k_device::device_reset_after_children()
+{
+ /* Pull up resistor R12 makes CB2 high when it's configured as an input, so set CB2 as output and high to compensate */
+ m_pia_rtc->write(0x03, 0x3c);
+}
+
+
+//**************************************************************************
+// IMPLEMENTATION
+//**************************************************************************
+
+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);
+}
+
+void bbc_cumana68k_device::irq6502_w(int state)
+{
+ m_m68008->set_input_line(M68K_IRQ_2, state);
+}
+
+void bbc_cumana68k_device::fsel_w(offs_t offset, uint8_t data)
+{
+ /* TODO: what does FSEL actually do? seems to affect the floppy FCLK */
+ //logerror("fsel_w %02x\n", data);
+}
+
+
+uint8_t bbc_cumana68k_device::mem6502_r(offs_t offset)
+{
+ uint8_t data = 0xff;
+
+ address_space &program = m_maincpu->space(AS_PROGRAM);
+
+ switch (offset & 0xf000)
+ {
+ case 0x0000:
+ data = program.read_byte(offset | 0x2000);
+ break;
+ case 0x2000:
+ data = program.read_byte(offset & 0x0fff);
+ break;
+ default:
+ data = program.read_byte(offset);
+ break;
+ }
+ return data;
+}
+
+void bbc_cumana68k_device::mem6502_w(offs_t offset, uint8_t data)
+{
+ address_space &program = m_maincpu->space(AS_PROGRAM);
+
+ switch (offset & 0xf000)
+ {
+ case 0x0000:
+ program.write_byte(offset | 0x2000, data);
+ break;
+ case 0x2000:
+ program.write_byte(offset & 0x0fff, data);
+ break;
+ default:
+ program.write_byte(offset, data);
+ break;
+ }
+}
+
+
+void bbc_cumana68k_device::rtc_ce_w(int state)
+{
+ m_mc146818_ce = !state;
+}
+
+void bbc_cumana68k_device::mc146818_set(int as, int ds, int rw)
+{
+ /* if chip enabled */
+ if (m_mc146818_ce)
+ {
+ /* if address select is set then set the address in the 146818 */
+ if (m_mc146818_as & !as)
+ {
+ m_rtc->address_w(m_mc146818_data);
+ //logerror("addr_w: %02x\n", m_mc146818_data);
+ }
+
+ /* if data select is set then access the data in the 146818 */
+ if (m_mc146818_ds & !ds)
+ {
+ if (m_mc146818_rw)
+ {
+ m_mc146818_data = m_rtc->data_r();
+ //logerror("data_r: %02x\n", m_mc146818_data);
+ }
+ else
+ {
+ m_rtc->data_w(m_mc146818_data);
+ //logerror("data_w: %02x\n", m_mc146818_data);
+ }
+ }
+ }
+ m_mc146818_as = as;
+ m_mc146818_ds = ds;
+ m_mc146818_rw = rw;
+}
+
+
+void bbc_cumana68k_device::pia_rtc_pb_w(uint8_t data)
+{
+ /* bit 0, 1: drive select */
+ floppy_image_device *floppy = m_floppy[data & 0x03]->get_device();
+
+ m_fdc->set_floppy(floppy);
+
+ /* bit 2: motor enable */
+ if (floppy)
+ floppy->mon_w(BIT(data, 2));
+
+ /* bit 3: density */
+ m_fdc->dden_w(BIT(data, 3));
+
+ /* bit 4: enable precomp */
+
+ /* bit 5, 6, 7: rtc */
+ //logerror("rtc: as=%d ds=%d rw=%d\n", BIT(data, 5), BIT(data, 6), BIT(data, 7));
+ mc146818_set(BIT(data, 5), BIT(data, 6), BIT(data, 7));
+}
+
+
+void bbc_cumana68k_device::pia_sasi_pb_w(uint8_t data)
+{
+ /* bit 0: masknmi */
+ m_masknmi = BIT(data, 0);
+ logerror("mask nmi %d\n", m_masknmi);
+}
diff --git a/src/devices/bus/bbc/internal/cumana68k.h b/src/devices/bus/bbc/internal/cumana68k.h
new file mode 100644
index 00000000000..4df7957f937
--- /dev/null
+++ b/src/devices/bus/bbc/internal/cumana68k.h
@@ -0,0 +1,86 @@
+// license:BSD-3-Clause
+// copyright-holders:Nigel Barnes
+/**********************************************************************
+
+ Cumana 68008 Upgrade Board
+
+ http://chrisacorns.computinghistory.org.uk/8bit_Upgrades/Cumana_680082ndProcessor.html
+
+**********************************************************************/
+
+#ifndef MAME_BUS_BBC_INTERNAL_CUMANA68K_H
+#define MAME_BUS_BBC_INTERNAL_CUMANA68K_H
+
+#include "internal.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"
+
+//**************************************************************************
+// TYPE DEFINITIONS
+//**************************************************************************
+
+class bbc_cumana68k_device :
+ public device_t,
+ public device_bbc_internal_interface
+{
+public:
+ // construction/destruction
+ bbc_cumana68k_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
+
+ void pia_rtc_pb_w(uint8_t data);
+ void pia_sasi_pb_w(uint8_t data);
+
+ uint8_t mem6502_r(offs_t offset);
+ void mem6502_w(offs_t offset, uint8_t data);
+
+ static void floppy_formats(format_registration &fr);
+
+protected:
+ // device-level overrides
+ virtual void device_start() override ATTR_COLD;
+ virtual void device_reset_after_children() override;
+
+ // optional information overrides
+ virtual void device_add_mconfig(machine_config &config) override ATTR_COLD;
+ virtual const tiny_rom_entry *device_rom_region() const override ATTR_COLD;
+
+ void irq6502_w(int state) override;
+
+private:
+ 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;
+ required_device<pia6821_device> m_pia_rtc;
+ required_device<input_merger_device> m_irqs;
+ required_device<mc146818_device> m_rtc;
+ required_device<wd2797_device> m_fdc;
+ required_device_array<floppy_connector, 4> m_floppy;
+ required_device<nscsi_callback_device> m_sasi;
+
+ void cumana68k_mem(address_map &map) ATTR_COLD;
+
+ void fsel_w(offs_t offset, uint8_t data);
+
+ int m_masknmi;
+
+ void mc146818_set(int as, int ds, int rw);
+ uint8_t m_mc146818_data;
+ int m_mc146818_as;
+ int m_mc146818_ds;
+ int m_mc146818_rw;
+ int m_mc146818_ce;
+};
+
+
+// device type definition
+DECLARE_DEVICE_TYPE(BBC_CUMANA68K, bbc_cumana68k_device)
+
+
+#endif // MAME_BUS_BBC_INTERNAL_CUMANA68K_H
diff --git a/src/devices/bus/bbc/internal/integrab.cpp b/src/devices/bus/bbc/internal/integrab.cpp
new file mode 100644
index 00000000000..1cb750b7022
--- /dev/null
+++ b/src/devices/bus/bbc/internal/integrab.cpp
@@ -0,0 +1,341 @@
+// license:BSD-3-Clause
+// copyright-holders:Nigel Barnes
+/**********************************************************************
+
+ Computech Integra-B expansion board
+
+ Usage:
+ To enable the computer to acknowledge the INTEGRA-β Expansion on the
+ first switch-on you must hold down the '@' key whilst switching on
+ the computer, or CTRL-@-BREAK to reset.
+
+ If default language has not been configured then reset the board and:
+ *CONFIGURE LANG 14
+
+**********************************************************************/
+
+
+#include "emu.h"
+#include "integrab.h"
+
+
+//**************************************************************************
+// DEVICE DEFINITIONS
+//**************************************************************************
+
+DEFINE_DEVICE_TYPE(BBC_INTEGRAB, bbc_integrab_device, "bbc_integrab", u8"Computech Integra-β")
+
+
+//-------------------------------------------------
+// INPUT_PORTS( integrab )
+//-------------------------------------------------
+
+static INPUT_PORTS_START(integrab)
+ PORT_START("wp")
+ PORT_CONFNAME(0x01, 0x00, "Write Protect Sideways RAM Banks 4/5")
+ PORT_CONFSETTING(0x00, DEF_STR(No))
+ PORT_CONFSETTING(0x01, DEF_STR(Yes))
+ PORT_CONFNAME(0x02, 0x00, "Write Protect Sideways RAM Bank 6/7")
+ PORT_CONFSETTING(0x00, DEF_STR(No))
+ PORT_CONFSETTING(0x02, DEF_STR(Yes))
+INPUT_PORTS_END
+
+//-------------------------------------------------
+// input_ports - device-specific input ports
+//-------------------------------------------------
+
+ioport_constructor bbc_integrab_device::device_input_ports() const
+{
+ return INPUT_PORTS_NAME(integrab);
+}
+
+//-------------------------------------------------
+// ROM( integrab )
+//-------------------------------------------------
+
+ROM_START(integrab)
+ ROM_REGION(0x4000, "ibos", 0)
+ ROM_SYSTEM_BIOS(0, "120p", "IBOS 1.20 (Y2K patched)")
+ ROMX_LOAD("ibos120p.rom", 0x0000, 0x4000, CRC(21e7a2c2) SHA1(d5ff79da2243aabd363ee26a1e7ad546657fdeb5), ROM_BIOS(0))
+ ROM_SYSTEM_BIOS(1, "120", "IBOS 1.20")
+ ROMX_LOAD("ibos120.rom", 0x0000, 0x4000, CRC(52b1b8c4) SHA1(0f5b2a5bee23808b34eab2f027f7c1e77395c782), ROM_BIOS(1))
+ ROM_SYSTEM_BIOS(2, "114", "IBOS 1.14")
+ ROMX_LOAD("ibos114.rom", 0x0000, 0x4000, CRC(d05ce376) SHA1(b2b7fc3258936296f83d720759caacba5378edec), ROM_BIOS(2))
+ROM_END
+
+//-------------------------------------------------
+// device_add_mconfig - add device configuration
+//-------------------------------------------------
+
+void bbc_integrab_device::device_add_mconfig(machine_config &config)
+{
+ /* rtc */
+ MC146818(config, m_rtc, 32.768_kHz_XTAL); // CDP6818
+ m_rtc->irq().set(DEVICE_SELF_OWNER, FUNC(bbc_internal_slot_device::irq_w));
+
+ /* rom/ram sockets */
+ BBC_ROMSLOT16(config, m_rom[4], bbc_rom_devices, "nvram").set_fixed_ram(true);
+ BBC_ROMSLOT16(config, m_rom[5], bbc_rom_devices, "nvram").set_fixed_ram(true);
+ BBC_ROMSLOT16(config, m_rom[6], bbc_rom_devices, "nvram").set_fixed_ram(true);
+ BBC_ROMSLOT16(config, m_rom[7], bbc_rom_devices, "nvram").set_fixed_ram(true);
+ BBC_ROMSLOT16(config, m_rom[8], bbc_rom_devices, nullptr);
+ BBC_ROMSLOT16(config, m_rom[9], bbc_rom_devices, nullptr);
+ BBC_ROMSLOT16(config, m_rom[10], bbc_rom_devices, nullptr);
+ BBC_ROMSLOT16(config, m_rom[11], bbc_rom_devices, nullptr);
+ BBC_ROMSLOT16(config, m_rom[12], bbc_rom_devices, nullptr);
+ BBC_ROMSLOT16(config, m_rom[13], bbc_rom_devices, nullptr);
+ BBC_ROMSLOT16(config, m_rom[14], bbc_rom_devices, nullptr);
+
+ /* battery-backed ram */
+ NVRAM(config, "nvram", nvram_device::DEFAULT_ALL_0);
+}
+
+//-------------------------------------------------
+// rom_region - device-specific ROM region
+//-------------------------------------------------
+
+const tiny_rom_entry *bbc_integrab_device::device_rom_region() const
+{
+ return ROM_NAME( integrab );
+}
+
+//**************************************************************************
+// LIVE DEVICE
+//**************************************************************************
+
+//-------------------------------------------------
+// bbc_integrab_device - constructor
+//-------------------------------------------------
+
+bbc_integrab_device::bbc_integrab_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
+ : device_t(mconfig, BBC_INTEGRAB, tag, owner, clock)
+ , device_bbc_internal_interface(mconfig, *this)
+ , m_ibos(*this, "ibos")
+ , m_rom(*this, "romslot%u", 0U)
+ , m_nvram(*this, "nvram")
+ , m_rtc(*this, "rtc")
+ , m_wp(*this, "wp")
+{
+}
+
+//-------------------------------------------------
+// device_start - device-specific startup
+//-------------------------------------------------
+
+void bbc_integrab_device::device_start()
+{
+ m_shadow = false;
+ m_ram = make_unique_clear<uint8_t[]>(0x8000);
+ m_nvram->set_base(m_ram.get(), 0x8000);
+
+ /* move internal roms to board */
+ memmove(m_region_swr->base() + 0x2c000, m_region_swr->base(), 0x10000);
+ memset(m_region_swr->base(), 0xff, 0x10000);
+ memcpy(m_region_swr->base() + 0x3c000, m_ibos->base(), 0x4000);
+
+ /* register for save states */
+ save_item(NAME(m_romsel));
+ save_item(NAME(m_ramsel));
+ save_item(NAME(m_shadow));
+ save_pointer(NAME(m_ram), 0x8000);
+}
+
+void bbc_integrab_device::device_reset()
+{
+ m_romsel = 0;
+ m_ramsel = 0;
+}
+
+
+//**************************************************************************
+// IMPLEMENTATION
+//**************************************************************************
+
+uint8_t bbc_integrab_device::romsel_r(offs_t offset)
+{
+ uint8_t data = 0xfe;
+
+ switch (offset & 0x0c)
+ {
+ case 0x0c:
+ data = m_rtc->data_r();
+ break;
+ }
+
+ return data;
+}
+
+void bbc_integrab_device::romsel_w(offs_t offset, uint8_t data)
+{
+ /*
+ ROMSEL & ROMID
+ Bits 0,3 ROMNUM Sideways ROM/RAM select bits
+ Bits 4,5 Not used
+ Bit 6 PRVEN Private RAM enable
+ Bit 7 MEMSEL Shadow/Main RAM toggle
+
+ RAMSEL & RAMID
+ Bits 0,1 AUX0,1 Not used but must be preserved
+ Bits 2,3 Not used
+ Bit 4 PRVS8 Private RAM 8K area select (&9000-&AFFF)
+ Bit 5 PRVS4 Private RAM 4K area select (&8000-&8FFF)
+ Bit 6 PRVS1 Private RAM 1K area select (&8000-&83FF)
+ Bit 7 SHEN Shadow RAM enable bit
+ */
+ switch (offset & 0x0c)
+ {
+ case 0x00:
+ m_romsel = data;
+ break;
+ case 0x04:
+ m_ramsel = data;
+ break;
+ case 0x08:
+ m_rtc->address_w(data);
+ break;
+ case 0x0c:
+ m_rtc->data_w(data);
+ break;
+ }
+
+ m_shadow = BIT(m_ramsel, 7) && !BIT(m_romsel, 7);
+}
+
+uint8_t bbc_integrab_device::ram_r(offs_t offset)
+{
+ uint8_t data = 0xff;
+
+ if (m_shadow && offset >= 0x3000)
+ data = m_ram[offset];
+ else
+ data = m_mb_ram->pointer()[offset];
+
+ return data;
+}
+
+void bbc_integrab_device::ram_w(offs_t offset, uint8_t data)
+{
+ if (m_shadow && offset >= 0x3000)
+ m_ram[offset] = data;
+ else
+ m_mb_ram->pointer()[offset] = data;
+}
+
+uint8_t bbc_integrab_device::paged_r(offs_t offset)
+{
+ uint8_t data = 0xff;
+ uint8_t romsel = m_romsel & 0x0f;
+
+ switch (romsel)
+ {
+ case 0: case 1: case 2: case 3:
+ /* motherboard rom sockets */
+ if (m_mb_rom[romsel] && m_mb_rom[romsel]->present())
+ {
+ data = m_mb_rom[romsel]->read(offset);
+ }
+ else
+ {
+ data = m_region_swr->base()[offset + (romsel << 14)];
+ }
+ break;
+ case 4: case 5: case 6: case 7: case 8: case 9: case 10: case 11: case 12: case 13: case 14: case 15:
+ /* expansion board sockets */
+ if (m_rom[romsel] && m_rom[romsel]->present())
+ {
+ data = m_rom[romsel]->read(offset);
+ }
+ else
+ {
+ data = m_region_swr->base()[offset + (romsel << 14)];
+ }
+ break;
+ }
+
+ /* private ram */
+ if (BIT(m_romsel, 6))
+ {
+ switch (offset & 0x3c00)
+ {
+ case 0x0000:
+ /* PRVS1 */
+ if (m_ramsel & 0x60)
+ data = m_ram[offset];
+ break;
+ case 0x0400: case 0x0800: case 0x0c00:
+ /* PRVS4 */
+ if (m_ramsel & 0x20)
+ data = m_ram[offset];
+ break;
+ case 0x1000: case 0x1400: case 0x1800: case 0x1c00: case 0x2000: case 0x2400: case 0x2800: case 0x2c00:
+ /* PRVS8 */
+ if (m_ramsel & 0x10)
+ data = m_ram[offset];
+ break;
+ }
+ }
+
+ return data;
+}
+
+void bbc_integrab_device::paged_w(offs_t offset, uint8_t data)
+{
+ uint8_t romsel = m_romsel & 0x0f;
+
+ /* private ram */
+ if (BIT(m_romsel, 6))
+ {
+ switch (offset & 0x3c00)
+ {
+ case 0x0000:
+ /* PRVS1 */
+ if (m_ramsel & 0x60)
+ m_ram[offset] = data;
+ break;
+ case 0x0400: case 0x0800: case 0x0c00:
+ /* PRVS4 */
+ if (m_ramsel & 0x20)
+ m_ram[offset] = data;
+ break;
+ case 0x1000: case 0x1400: case 0x1800: case 0x1c00: case 0x2000: case 0x2400: case 0x2800: case 0x2c00:
+ /* PRVS8 */
+ if (m_ramsel & 0x10)
+ m_ram[offset] = data;
+ break;
+ }
+ }
+ else
+ {
+ switch (romsel)
+ {
+ case 0: case 1: case 2: case 3:
+ /* motherboard rom sockets */
+ if (m_mb_rom[romsel])
+ {
+ m_mb_rom[romsel]->write(offset, data);
+ }
+ break;
+ case 4: case 5:
+ /* expansion board sockets */
+ if (m_rom[romsel] && !BIT(m_wp->read(), 0))
+ {
+ m_rom[romsel]->write(offset, data);
+ }
+ break;
+ case 6: case 7:
+ /* expansion board sockets */
+ if (m_rom[romsel] && !BIT(m_wp->read(), 1))
+ {
+ m_rom[romsel]->write(offset, data);
+ }
+ break;
+ case 8: case 9: case 10: case 11: case 12: case 13: case 14:
+ /* expansion board sockets */
+ if (m_rom[romsel])
+ {
+ m_rom[romsel]->write(offset, data);
+ }
+ break;
+ }
+ }
+}
diff --git a/src/devices/bus/bbc/internal/integrab.h b/src/devices/bus/bbc/internal/integrab.h
new file mode 100644
index 00000000000..51fba182a38
--- /dev/null
+++ b/src/devices/bus/bbc/internal/integrab.h
@@ -0,0 +1,67 @@
+// license:BSD-3-Clause
+// copyright-holders:Nigel Barnes
+/**********************************************************************
+
+ Computech Integra-B expansion board
+
+**********************************************************************/
+
+
+#ifndef MAME_BUS_BBC_INTERNAL_INTEGRAB_H
+#define MAME_BUS_BBC_INTERNAL_INTEGRAB_H
+
+#include "internal.h"
+#include "machine/mc146818.h"
+#include "machine/nvram.h"
+
+
+//**************************************************************************
+// TYPE DEFINITIONS
+//**************************************************************************
+
+class bbc_integrab_device :
+ public device_t,
+ public device_bbc_internal_interface
+{
+public:
+ // construction/destruction
+ bbc_integrab_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
+
+protected:
+ // device-level overrides
+ virtual void device_start() override ATTR_COLD;
+ virtual void device_reset() override ATTR_COLD;
+
+ // optional information overrides
+ virtual void device_add_mconfig(machine_config &config) override ATTR_COLD;
+ virtual const tiny_rom_entry *device_rom_region() const override ATTR_COLD;
+ virtual ioport_constructor device_input_ports() const override ATTR_COLD;
+
+ virtual bool overrides_rom() override { return true; }
+ virtual bool overrides_ram() override { return true; }
+ virtual uint8_t ram_r(offs_t offset) override;
+ virtual void ram_w(offs_t offset, uint8_t data) override;
+ virtual uint8_t romsel_r(offs_t offset) override;
+ virtual void romsel_w(offs_t offset, uint8_t data) override;
+ virtual uint8_t paged_r(offs_t offset) override;
+ virtual void paged_w(offs_t offset, uint8_t data) override;
+
+private:
+ required_memory_region m_ibos;
+ optional_device_array<bbc_romslot_device, 16> m_rom;
+ required_device<nvram_device> m_nvram;
+ required_device<mc146818_device> m_rtc;
+ required_ioport m_wp;
+
+ std::unique_ptr<uint8_t[]> m_ram;
+ bool m_shadow;
+ uint8_t m_romsel;
+ uint8_t m_ramsel;
+};
+
+
+// device type definition
+DECLARE_DEVICE_TYPE(BBC_INTEGRAB, bbc_integrab_device)
+
+
+#endif // MAME_BUS_BBC_INTERNAL_INTEGRAB_H
diff --git a/src/devices/bus/bbc/internal/internal.cpp b/src/devices/bus/bbc/internal/internal.cpp
new file mode 100644
index 00000000000..4adad689824
--- /dev/null
+++ b/src/devices/bus/bbc/internal/internal.cpp
@@ -0,0 +1,218 @@
+// license:BSD-3-Clause
+// copyright-holders:Nigel Barnes
+/**********************************************************************
+
+ BBC Micro internal expansion boards
+
+ These boards usually add shadow RAM and/or additional ROM sockets.
+ They don't have a fixed interface, some use the 6502 socket and move
+ the CPU to the board, others will move other IC's to the board and
+ flying leads will be connected to various points to pick up control
+ lines and writes to latches.
+
+**********************************************************************/
+
+#include "emu.h"
+#include "internal.h"
+
+
+//**************************************************************************
+// DEVICE DEFINITIONS
+//**************************************************************************
+
+DEFINE_DEVICE_TYPE(BBC_INTERNAL_SLOT, bbc_internal_slot_device, "bbc_internal_slot", "BBC Micro internal boards")
+
+
+
+//**************************************************************************
+// DEVICE BBC_INTERNAL PORT INTERFACE
+//**************************************************************************
+
+//-------------------------------------------------
+// device_bbc_internal_interface - constructor
+//-------------------------------------------------
+
+device_bbc_internal_interface::device_bbc_internal_interface(const machine_config &mconfig, device_t &device)
+ : device_interface(device, "bbcinternal")
+ , m_maincpu(*this, ":maincpu")
+ , m_mb_ram(*this, ":ram")
+ , m_mb_rom(*this, ":romslot%u", 0U)
+ , m_region_swr(*this, ":swr")
+ , m_region_mos(*this, ":mos")
+{
+ m_slot = dynamic_cast<bbc_internal_slot_device *>(device.owner());
+}
+
+
+//**************************************************************************
+// LIVE DEVICE
+//**************************************************************************
+
+//-------------------------------------------------
+// bbc_internal_slot_device - constructor
+//-------------------------------------------------
+
+bbc_internal_slot_device::bbc_internal_slot_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
+ : device_t(mconfig, BBC_INTERNAL_SLOT, tag, owner, clock)
+ , device_single_card_slot_interface<device_bbc_internal_interface>(mconfig, *this)
+ , m_irq_handler(*this)
+ , m_nmi_handler(*this)
+ , m_card(nullptr)
+{
+}
+
+
+//-------------------------------------------------
+// device_start - device-specific startup
+//-------------------------------------------------
+
+void bbc_internal_slot_device::device_start()
+{
+ m_card = get_card_device();
+}
+
+
+//-------------------------------------------------
+// read
+//-------------------------------------------------
+
+uint8_t bbc_internal_slot_device::ram_r(offs_t offset)
+{
+ if (m_card)
+ return m_card->ram_r(offset);
+ else
+ return 0xff;
+}
+
+uint8_t bbc_internal_slot_device::romsel_r(offs_t offset)
+{
+ if (m_card)
+ return m_card->romsel_r(offset);
+ else
+ return 0xfe;
+}
+
+uint8_t bbc_internal_slot_device::paged_r(offs_t offset)
+{
+ if (m_card)
+ return m_card->paged_r(offset);
+ else
+ return 0xff;
+}
+
+uint8_t bbc_internal_slot_device::mos_r(offs_t offset)
+{
+ if (m_card)
+ return m_card->mos_r(offset);
+ else
+ return 0xff;
+}
+
+//-------------------------------------------------
+// write
+//-------------------------------------------------
+
+void bbc_internal_slot_device::ram_w(offs_t offset, uint8_t data)
+{
+ if (m_card)
+ m_card->ram_w(offset, data);
+}
+
+void bbc_internal_slot_device::romsel_w(offs_t offset, uint8_t data)
+{
+ if (m_card)
+ m_card->romsel_w(offset, data);
+}
+
+void bbc_internal_slot_device::paged_w(offs_t offset, uint8_t data)
+{
+ if (m_card)
+ m_card->paged_w(offset, data);
+}
+
+void bbc_internal_slot_device::mos_w(offs_t offset, uint8_t data)
+{
+ if (m_card)
+ m_card->mos_w(offset, data);
+}
+
+void bbc_internal_slot_device::latch_fe60_w(uint8_t data)
+{
+ if (m_card)
+ m_card->latch_fe60_w(data);
+}
+
+void bbc_internal_slot_device::irq6502_w(int state)
+{
+ if (m_card)
+ m_card->irq6502_w(state);
+}
+
+//-------------------------------------------------
+// SLOT_INTERFACE( bbc_internal_devices )
+//-------------------------------------------------
+
+
+// slot devices
+#include "aries.h"
+#include "atpl.h"
+#include "cumana68k.h"
+#include "integrab.h"
+#include "memex.h"
+#include "morleyaa.h"
+#include "overlay.h"
+#include "peartree.h"
+#include "ramamp.h"
+#include "raven20.h"
+//#include "replaym.h"
+#include "romex.h"
+#include "stlswr.h"
+#include "stl2m128.h"
+#include "stl4m32.h"
+//#include "stl4m256.h"
+#include "werom.h"
+#include "weromram.h"
+#include "we32kram.h"
+
+
+void bbcb_internal_devices(device_slot_interface &device)
+{
+ device.option_add("ariesb12", BBC_ARIESB12); /* Aries-B12 ROM expansion */
+ device.option_add("ariesb20", BBC_ARIESB20); /* Aries-B20 RAM expansion */
+ device.option_add("ariesb32", BBC_ARIESB32); /* Aries-B32 RAM expansion */
+ device.option_add("atplsw", BBC_ATPLSW); /* ATPL Sidewise ROM/RAM expansion */
+ device.option_add("cumana68k", BBC_CUMANA68K); /* Cumana 68008 Upgrade Board */
+ device.option_add("integrab", BBC_INTEGRAB); /* Computech Integra-B */
+ device.option_add("memexb20", BBC_MEMEXB20); /* Memex-B20 RAM expansion */
+ device.option_add("mr3000", BBC_MR3000); /* Peartree MR3000 ROM board */
+ device.option_add("mr4200", BBC_MR4200); /* Peartree MR4200 RAM board */
+ device.option_add("mr4300", BBC_MR4300); /* Peartree MR4300 ROM/RAM board */
+ device.option_add("mr4800", BBC_MR4800); /* Peartree MR4800 RAM board */
+ device.option_add("ramamp", BBC_RAMAMP); /* Ramamp Sideways RAM/ROM board */
+ device.option_add("raven20", BBC_RAVEN20); /* Raven-20 RAM expansion */
+ device.option_add("romex13", BBC_ROMEX13); /* GCC Romex13 ROM expansion */
+ device.option_add("swr16", BBC_STLSWR16); /* Solidisk SWR16 */
+ device.option_add("swr32", BBC_STLSWR32); /* Solidisk SWR32 */
+ device.option_add("swr64", BBC_STLSWR64); /* Solidisk SWR64 */
+ device.option_add("swr128", BBC_STLSWR128); /* Solidisk SWR128 */
+ device.option_add("2m128", BBC_STL2M128); /* Solidisk Twomeg 128 */
+ device.option_add("4m32", BBC_STL4M32); /* Solidisk Fourmeg 32 */
+ //device.option_add("4m256", BBC_STL4M256); /* Solidisk Fourmeg 256 */
+ device.option_add("we12rom", BBC_WE12ROM); /* Watford Electronics 12 ROM board */
+ device.option_add("we13rom", BBC_WE13ROM); /* Watford Electronics 13 ROM board */
+ device.option_add("weromram", BBC_WEROMRAM); /* Watford Electronics RAM/ROM board */
+ device.option_add("we32kram", BBC_WE32KRAM); /* Watford Electronics 32K Shadow RAM */
+}
+
+void bbcbp_internal_devices(device_slot_interface &device)
+{
+ device.option_add("atplswp", BBC_ATPLSWP); /* ATPL Sidewise+ ROM expansion */
+ device.option_add("cumana68k", BBC_CUMANA68K); /* Cumana 68008 Upgrade Board */
+}
+
+void bbcm_internal_devices(device_slot_interface &device)
+{
+ device.option_add("morleyaa", BBC_MORLEYAA); /* Morley Master Board 'AA' */
+ device.option_add("overlay", BBC_OVERLAY); /* Vine Micros OS Overlay Board */
+ //device.option_add("replaym", BBC_REPLAYM); /* Vine Micros Master Replay */
+}
diff --git a/src/devices/bus/bbc/internal/internal.h b/src/devices/bus/bbc/internal/internal.h
new file mode 100644
index 00000000000..ca6f6b37e64
--- /dev/null
+++ b/src/devices/bus/bbc/internal/internal.h
@@ -0,0 +1,117 @@
+// license:BSD-3-Clause
+// copyright-holders:Nigel Barnes
+/**********************************************************************
+
+ BBC Micro internal expansion boards
+
+**********************************************************************/
+
+#ifndef MAME_BUS_BBC_INTERNAL_INTERNAL_H
+#define MAME_BUS_BBC_INTERNAL_INTERNAL_H
+
+#pragma once
+
+#include "machine/ram.h"
+#include "bus/bbc/rom/slot.h"
+
+
+//**************************************************************************
+// TYPE DEFINITIONS
+//**************************************************************************
+
+class bbc_internal_slot_device;
+
+// ======================> device_bbc_internal_interface
+
+class device_bbc_internal_interface : public device_interface
+{
+public:
+ virtual bool overrides_ram() { return false; }
+ virtual bool overrides_rom() { return false; }
+ virtual bool overrides_mos() { return false; }
+ virtual uint8_t ram_r(offs_t offset) { return 0xff; }
+ virtual void ram_w(offs_t offset, uint8_t data) { }
+ virtual uint8_t romsel_r(offs_t offset) { return 0xfe; }
+ virtual void romsel_w(offs_t offset, uint8_t data) { }
+ virtual uint8_t paged_r(offs_t offset) { return 0xff; }
+ virtual void paged_w(offs_t offset, uint8_t data) { }
+ virtual uint8_t mos_r(offs_t offset) { return 0xff; }
+ virtual void mos_w(offs_t offset, uint8_t data) { }
+ virtual void latch_fe60_w(uint8_t data) { }
+
+ virtual void irq6502_w(int state) { }
+
+protected:
+ device_bbc_internal_interface(const machine_config &mconfig, device_t &device);
+
+ required_device<cpu_device> m_maincpu;
+ required_device<ram_device> m_mb_ram;
+ optional_device_array<bbc_romslot_device, 16> m_mb_rom;
+ required_memory_region m_region_swr;
+ required_memory_region m_region_mos;
+
+ bbc_internal_slot_device *m_slot;
+};
+
+// ======================> bbc_internal_slot_device
+
+class bbc_internal_slot_device : public device_t, public device_single_card_slot_interface<device_bbc_internal_interface>
+{
+public:
+ // construction/destruction
+ template <typename T>
+ bbc_internal_slot_device(machine_config const &mconfig, char const *tag, device_t *owner, uint32_t clock, T &&slot_options, const char *default_option)
+ : bbc_internal_slot_device(mconfig, tag, owner, clock)
+ {
+ option_reset();
+ slot_options(*this);
+ set_default_option(default_option);
+ set_fixed(false);
+ }
+
+ bbc_internal_slot_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
+
+ // inline configuration
+ auto irq_handler() { return m_irq_handler.bind(); }
+ auto nmi_handler() { return m_nmi_handler.bind(); }
+
+ 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; }
+ virtual bool overrides_mos() { return m_card ? m_card->overrides_mos() : false; }
+ virtual uint8_t ram_r(offs_t offset);
+ virtual void ram_w(offs_t offset, uint8_t data);
+ virtual uint8_t romsel_r(offs_t offset);
+ virtual void romsel_w(offs_t offset, uint8_t data);
+ virtual uint8_t paged_r(offs_t offset);
+ virtual void paged_w(offs_t offset, uint8_t data);
+ virtual uint8_t mos_r(offs_t offset);
+ virtual void mos_w(offs_t offset, uint8_t data);
+ virtual void latch_fe60_w(uint8_t data);
+
+ virtual void irq6502_w(int state);
+
+protected:
+ // device-level overrides
+ virtual void device_start() override ATTR_COLD;
+
+ devcb_write_line m_irq_handler;
+ devcb_write_line m_nmi_handler;
+
+ uint8_t m_romsel_fe30;
+ uint8_t m_romsel_fe62;
+
+ device_bbc_internal_interface *m_card;
+};
+
+// device type definition
+DECLARE_DEVICE_TYPE(BBC_INTERNAL_SLOT, bbc_internal_slot_device)
+
+void bbcb_internal_devices(device_slot_interface &device);
+void bbcbp_internal_devices(device_slot_interface &device);
+void bbcm_internal_devices(device_slot_interface &device);
+
+
+#endif // MAME_BUS_BBC_INTERNAL_INTERNAL_H
diff --git a/src/devices/bus/bbc/internal/memex.cpp b/src/devices/bus/bbc/internal/memex.cpp
new file mode 100644
index 00000000000..809313e4c68
--- /dev/null
+++ b/src/devices/bus/bbc/internal/memex.cpp
@@ -0,0 +1,109 @@
+// license:BSD-3-Clause
+// copyright-holders:Nigel Barnes
+/**********************************************************************
+
+ Memex B20 20K RAM expansion
+
+ This is a DIY project from the May 1984 issue of Electronics and
+ Computing, with part two of the project in the August 1984 issue.
+
+**********************************************************************/
+
+
+#include "emu.h"
+#include "memex.h"
+
+
+//**************************************************************************
+// DEVICE DEFINITIONS
+//**************************************************************************
+
+DEFINE_DEVICE_TYPE(BBC_MEMEXB20, bbc_memexb20_device, "bbc_memexb20", "Memex-B20 RAM expansion");
+
+
+//-------------------------------------------------
+// ROM( memexb20 )
+//-------------------------------------------------
+
+ROM_START(memexb20)
+ ROM_REGION(0x2000, "exp_rom", 0)
+ ROM_LOAD("memex-b20_v2.2.rom", 0x0000, 0x2000, CRC(98ee8eb6) SHA1(aad311797e204b0b69450460f8b4605409c31ddd))
+ROM_END
+
+//-------------------------------------------------
+// rom_region - device-specific ROM region
+//-------------------------------------------------
+
+const tiny_rom_entry *bbc_memexb20_device::device_rom_region() const
+{
+ return ROM_NAME(memexb20);
+}
+
+
+//**************************************************************************
+// LIVE DEVICE
+//**************************************************************************
+
+//-------------------------------------------------
+// bbc_memexb20_device - constructor
+//-------------------------------------------------
+
+bbc_memexb20_device::bbc_memexb20_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
+ : device_t(mconfig, BBC_MEMEXB20, tag, owner, clock)
+ , device_bbc_internal_interface(mconfig, *this)
+ , m_shadow(false)
+{
+}
+
+//-------------------------------------------------
+// device_start - device-specific startup
+//-------------------------------------------------
+
+void bbc_memexb20_device::device_start()
+{
+ address_space &program = m_maincpu->space(AS_PROGRAM);
+
+ program.install_write_handler(0xd000, 0xd000, write8smo_delegate(*this, FUNC(bbc_memexb20_device::enable_w)));
+ program.install_write_handler(0xc000, 0xc000, write8smo_delegate(*this, FUNC(bbc_memexb20_device::disable_w)));
+
+ m_ram = make_unique_clear<uint8_t[]>(0x5000);
+
+ /* register for save states */
+ save_item(NAME(m_shadow));
+ save_pointer(NAME(m_ram), 0x5000);
+}
+
+
+//**************************************************************************
+// IMPLEMENTATION
+//**************************************************************************
+
+void bbc_memexb20_device::enable_w(uint8_t data)
+{
+ m_shadow = true;
+}
+
+void bbc_memexb20_device::disable_w(uint8_t data)
+{
+ m_shadow = false;
+}
+
+uint8_t bbc_memexb20_device::ram_r(offs_t offset)
+{
+ uint8_t data = 0xff;
+
+ if (m_shadow && offset >= 0x3000)
+ data = m_ram[offset - 0x3000];
+ else
+ data = m_mb_ram->pointer()[offset];
+
+ return data;
+}
+
+void bbc_memexb20_device::ram_w(offs_t offset, uint8_t data)
+{
+ if (m_shadow && offset >= 0x3000)
+ m_ram[offset - 0x3000] = data;
+ else
+ m_mb_ram->pointer()[offset] = data;
+}
diff --git a/src/devices/bus/bbc/internal/memex.h b/src/devices/bus/bbc/internal/memex.h
new file mode 100644
index 00000000000..bd471140b0d
--- /dev/null
+++ b/src/devices/bus/bbc/internal/memex.h
@@ -0,0 +1,50 @@
+// license:BSD-3-Clause
+// copyright-holders:Nigel Barnes
+/**********************************************************************
+
+ Memex B20 20K RAM expansion
+
+**********************************************************************/
+
+
+#ifndef MAME_BUS_BBC_INTERNAL_MEMEX_H
+#define MAME_BUS_BBC_INTERNAL_MEMEX_H
+
+#include "internal.h"
+
+
+//**************************************************************************
+// TYPE DEFINITIONS
+//**************************************************************************
+
+class bbc_memexb20_device : public device_t, public device_bbc_internal_interface
+{
+public:
+ // construction/destruction
+ bbc_memexb20_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
+
+protected:
+ // device-level overrides
+ virtual void device_start() override ATTR_COLD;
+
+ // optional information overrides
+ virtual const tiny_rom_entry *device_rom_region() const override ATTR_COLD;
+
+ virtual bool overrides_ram() override { return true; }
+ virtual uint8_t ram_r(offs_t offset) override;
+ virtual void ram_w(offs_t offset, uint8_t data) override;
+
+private:
+ void enable_w(uint8_t data);
+ void disable_w(uint8_t data);
+
+ bool m_shadow;
+ std::unique_ptr<uint8_t[]> m_ram;
+};
+
+
+// device type definition
+DECLARE_DEVICE_TYPE(BBC_MEMEXB20, bbc_memexb20_device);
+
+
+#endif /* MAME_BUS_BBC_INTERNAL_MEMEX_H */
diff --git a/src/devices/bus/bbc/internal/morleyaa.cpp b/src/devices/bus/bbc/internal/morleyaa.cpp
new file mode 100644
index 00000000000..e01336c3b5c
--- /dev/null
+++ b/src/devices/bus/bbc/internal/morleyaa.cpp
@@ -0,0 +1,307 @@
+// license:BSD-3-Clause
+// copyright-holders:Nigel Barnes
+/**********************************************************************
+
+ Morley Electronics 'AA' Master ROM Expansion Board
+
+**********************************************************************/
+
+
+#include "emu.h"
+#include "morleyaa.h"
+
+
+//**************************************************************************
+// DEVICE DEFINITIONS
+//**************************************************************************
+
+DEFINE_DEVICE_TYPE(BBC_MORLEYAA, bbc_morleyaa_device, "bbc_morleyaa", "Morley Electronics 'AA' Master ROM Expansion Board");
+
+
+//-------------------------------------------------
+// ROM( morleyaa )
+//-------------------------------------------------
+
+ROM_START(morleyaa)
+ ROM_REGION(0x4000, "aa_rom", 0)
+ ROM_LOAD("masterboard_200.rom", 0x0000, 0x4000, CRC(d93738ec) SHA1(c80f47e3f661b1636d21ff542c7a39a586008098))
+ROM_END
+
+//-------------------------------------------------
+// device_add_mconfig - add device configuration
+//-------------------------------------------------
+
+void bbc_morleyaa_device::device_add_mconfig(machine_config &config)
+{
+ /* TODO: romslot0-3 are unavailable when board is fitted, replaced by sockets on board */;
+ //config.device_remove(":romslot8");
+
+ /* 8 x 16K rom sockets */
+ BBC_ROMSLOT16(config, m_rom[0], bbc_rom_devices, nullptr);
+ BBC_ROMSLOT16(config, m_rom[1], bbc_rom_devices, nullptr);
+ BBC_ROMSLOT16(config, m_rom[2], bbc_rom_devices, nullptr);
+ BBC_ROMSLOT16(config, m_rom[3], bbc_rom_devices, nullptr);
+ BBC_ROMSLOT16(config, m_rom[4], bbc_rom_devices, nullptr);
+ BBC_ROMSLOT16(config, m_rom[5], bbc_rom_devices, nullptr);
+ BBC_ROMSLOT16(config, m_rom[6], bbc_rom_devices, nullptr);
+ BBC_ROMSLOT16(config, m_rom[7], bbc_rom_devices, nullptr);
+ /* 4 x 32K rom sockets */
+ BBC_ROMSLOT32(config, m_rom[8], bbc_rom_devices, nullptr);
+ BBC_ROMSLOT32(config, m_rom[9], bbc_rom_devices, nullptr);
+ BBC_ROMSLOT32(config, m_rom[10], bbc_rom_devices, nullptr);
+ BBC_ROMSLOT32(config, m_rom[11], bbc_rom_devices, nullptr);
+}
+
+
+//-------------------------------------------------
+// rom_region - device-specific ROM region
+//-------------------------------------------------
+
+const tiny_rom_entry *bbc_morleyaa_device::device_rom_region() const
+{
+ return ROM_NAME(morleyaa);
+}
+
+
+//**************************************************************************
+// LIVE DEVICE
+//**************************************************************************
+
+//-------------------------------------------------
+// bbc_morleyaa_device - constructor
+//-------------------------------------------------
+
+bbc_morleyaa_device::bbc_morleyaa_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
+ : device_t(mconfig, BBC_MORLEYAA, tag, owner, clock)
+ , device_bbc_internal_interface(mconfig, *this)
+ , m_aa_rom(*this, "aa_rom")
+ , m_rom(*this, "romslot%u", 0U)
+{
+}
+
+//-------------------------------------------------
+// device_start - device-specific startup
+//-------------------------------------------------
+
+void bbc_morleyaa_device::device_start()
+{
+ /* move internal roms to board */
+ memcpy(m_region_swr->base() + 0x20000, m_aa_rom->base(), 0x4000);
+
+ /* register for save states */
+ save_item(NAME(m_romsel));
+ save_item(NAME(m_banksel));
+}
+
+
+//**************************************************************************
+// IMPLEMENTATION
+//**************************************************************************
+
+uint8_t bbc_morleyaa_device::paged_r(offs_t offset)
+{
+ uint8_t data = 0xff;
+
+ switch (m_romsel)
+ {
+ case 8:
+ data = m_aa_rom->base()[offset];
+ break;
+ case 4:
+ if (m_banksel & 0x20)
+ {
+ /* motherboard ram selected */
+ data = m_mb_rom[m_romsel & 0x0e]->read(offset | (m_romsel & 0x01) << 14);
+ }
+ else
+ {
+ switch (m_banksel & 0x07)
+ {
+ case 2:
+ data = m_rom[0]->read(offset);
+ break;
+ case 4:
+ data = m_rom[2]->read(offset);
+ break;
+ case 0:
+ data = m_rom[4]->read(offset);
+ break;
+ case 6:
+ data = m_rom[6]->read(offset);
+ break;
+ case 7:
+ data = m_rom[8]->read(offset);
+ break;
+ case 3:
+ data = m_rom[9]->read(offset);
+ break;
+ case 5:
+ data = m_rom[10]->read(offset);
+ break;
+ case 1:
+ data = m_rom[11]->read(offset);
+ break;
+ }
+ }
+ break;
+ case 5:
+ if (m_banksel & 0x20)
+ {
+ /* motherboard ram selected */
+ data = m_mb_rom[m_romsel & 0x0e]->read(offset | (m_romsel & 0x01) << 14);
+ }
+ else
+ {
+ switch (m_banksel & 0x07)
+ {
+ case 2:
+ data = m_rom[1]->read(offset);
+ break;
+ case 4:
+ data = m_rom[3]->read(offset);
+ break;
+ case 0:
+ data = m_rom[5]->read(offset);
+ break;
+ case 6:
+ data = m_rom[7]->read(offset);
+ break;
+ case 7:
+ data = m_rom[8]->read(offset | 0x4000);
+ break;
+ case 3:
+ data = m_rom[9]->read(offset | 0x4000);
+ break;
+ case 5:
+ data = m_rom[10]->read(offset | 0x4000);
+ break;
+ case 1:
+ data = m_rom[11]->read(offset | 0x4000);
+ break;
+ }
+ }
+ break;
+ case 6:
+ if (m_banksel & 0x40)
+ {
+ /* motherboard ram selected */
+ data = m_mb_rom[m_romsel & 0x0e]->read(offset | (m_romsel & 0x01) << 14);
+ }
+ else
+ {
+ switch (bitswap<8>(m_banksel, 2, 6, 5, 0, 1, 7, 3, 4) & 0x07)
+ {
+ case 2:
+ data = m_rom[0]->read(offset);
+ break;
+ case 4:
+ data = m_rom[2]->read(offset);
+ break;
+ case 0:
+ data = m_rom[4]->read(offset);
+ break;
+ case 6:
+ data = m_rom[6]->read(offset);
+ break;
+ case 7:
+ data = m_rom[8]->read(offset);
+ break;
+ case 3:
+ data = m_rom[9]->read(offset);
+ break;
+ case 5:
+ data = m_rom[10]->read(offset);
+ break;
+ case 1:
+ data = m_rom[11]->read(offset);
+ break;
+ }
+ }
+ break;
+ case 7:
+ if (m_banksel & 0x40)
+ {
+ /* motherboard ram selected */
+ data = m_mb_rom[m_romsel & 0x0e]->read(offset | (m_romsel & 0x01) << 14);
+ }
+ else
+ {
+ switch (bitswap<8>(m_banksel, 2, 6, 5, 0, 1, 7, 3, 4) & 0x07)
+ {
+ case 2:
+ data = m_rom[1]->read(offset);
+ break;
+ case 4:
+ data = m_rom[3]->read(offset);
+ break;
+ case 0:
+ data = m_rom[5]->read(offset);
+ break;
+ case 6:
+ data = m_rom[7]->read(offset);
+ break;
+ case 7:
+ data = m_rom[8]->read(offset | 0x4000);
+ break;
+ case 3:
+ data = m_rom[9]->read(offset | 0x4000);
+ break;
+ case 5:
+ data = m_rom[10]->read(offset | 0x4000);
+ break;
+ case 1:
+ data = m_rom[11]->read(offset | 0x4000);
+ break;
+ }
+ }
+ break;
+ default:
+ /* motherboard rom sockets */
+ if (m_mb_rom[m_romsel] && m_mb_rom[m_romsel]->present())
+ {
+ data = m_mb_rom[m_romsel]->read(offset);
+ }
+ else
+ {
+ data = m_region_swr->base()[offset + (m_romsel << 14)];
+ }
+ break;
+ }
+
+ return data;
+}
+
+void bbc_morleyaa_device::paged_w(offs_t offset, uint8_t data)
+{
+ switch (m_romsel)
+ {
+ case 8:
+ if (offset == 0x3f00)
+ {
+ /* bank latch at &BF00 */
+ m_banksel = data;
+ }
+ break;
+ case 4: case 5:
+ if (m_banksel & 0x20)
+ {
+ /* motherboard ram selected */
+ m_mb_rom[m_romsel & 0x0e]->write(offset | (m_romsel & 0x01) << 14, data);
+ }
+ break;
+ case 6: case 7:
+ if (m_banksel & 0x40)
+ {
+ /* motherboard ram selected */
+ m_mb_rom[m_romsel & 0x0e]->write(offset | (m_romsel & 0x01) << 14, data);
+ }
+ break;
+ default:
+ /* motherboard rom sockets */
+ if (m_mb_rom[m_romsel])
+ {
+ m_mb_rom[m_romsel]->write(offset, data);
+ }
+ break;
+ }
+}
diff --git a/src/devices/bus/bbc/internal/morleyaa.h b/src/devices/bus/bbc/internal/morleyaa.h
new file mode 100644
index 00000000000..c565f4b5949
--- /dev/null
+++ b/src/devices/bus/bbc/internal/morleyaa.h
@@ -0,0 +1,55 @@
+// license:BSD-3-Clause
+// copyright-holders:Nigel Barnes
+/**********************************************************************
+
+ Morley Electronics 'AA' Master ROM Expansion Board
+
+**********************************************************************/
+
+#ifndef MAME_BUS_BBC_INTERNAL_MORLEYAA_H
+#define MAME_BUS_BBC_INTERNAL_MORLEYAA_H
+
+#pragma once
+
+#include "internal.h"
+
+
+//**************************************************************************
+// TYPE DEFINITIONS
+//**************************************************************************
+
+class bbc_morleyaa_device :
+ public device_t,
+ public device_bbc_internal_interface
+{
+public:
+ // construction/destruction
+ bbc_morleyaa_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
+
+protected:
+ // device-level overrides
+ virtual void device_start() override ATTR_COLD;
+
+ // optional information overrides
+ virtual void device_add_mconfig(machine_config &config) override ATTR_COLD;
+ virtual const tiny_rom_entry *device_rom_region() const override ATTR_COLD;
+
+ virtual bool overrides_rom() override { return true; }
+ virtual void romsel_w(offs_t offset, uint8_t data) override { m_romsel = data & 0x0f; }
+ virtual uint8_t paged_r(offs_t offset) override;
+ virtual void paged_w(offs_t offset, uint8_t data) override;
+
+private:
+ required_memory_region m_aa_rom;
+ required_device_array<bbc_romslot_device, 12> m_rom;
+
+ uint8_t m_romsel;
+ uint8_t m_banksel;
+};
+
+
+// device type definition
+DECLARE_DEVICE_TYPE(BBC_MORLEYAA, bbc_morleyaa_device);
+
+
+#endif // MAME_BUS_BBC_INTERNAL_MORLEYAA_H
diff --git a/src/devices/bus/bbc/internal/overlay.cpp b/src/devices/bus/bbc/internal/overlay.cpp
new file mode 100644
index 00000000000..c46a280a316
--- /dev/null
+++ b/src/devices/bus/bbc/internal/overlay.cpp
@@ -0,0 +1,224 @@
+// license:BSD-3-Clause
+// copyright-holders:Nigel Barnes
+/**********************************************************************
+
+ Vine Micros Romboard '3' (Master OS Overlay Board)
+
+ http://chrisacorns.computinghistory.org.uk/8bit_Upgrades/Vine_MasterOSoverlay.html
+
+**********************************************************************/
+
+
+#include "emu.h"
+#include "overlay.h"
+
+
+//**************************************************************************
+// DEVICE DEFINITIONS
+//**************************************************************************
+
+DEFINE_DEVICE_TYPE(BBC_OVERLAY, bbc_overlay_device, "bbc_overlay", "Vine Micros Romboard '3' (Master OS Overlay)");
+
+
+//-------------------------------------------------
+// INPUT_PORTS( overlay )
+//-------------------------------------------------
+
+static INPUT_PORTS_START(overlay)
+ PORT_START("link_rom1")
+ PORT_CONFNAME(0x1f, 0x0a, "ROM 1")
+ PORT_CONFSETTING(0x10, "Operating System (reserved)")
+ PORT_CONFSETTING(0x09, "1770 DFS")
+ PORT_CONFSETTING(0x0a, "Viewsheet")
+ PORT_CONFSETTING(0x0b, "Edit")
+ PORT_CONFSETTING(0x0c, "BASIC")
+ PORT_CONFSETTING(0x0d, "ADFS")
+ PORT_CONFSETTING(0x0e, "View (and some GXR)")
+ PORT_CONFSETTING(0x0f, "Terminal and Operating System (reserved)")
+ PORT_START("link_rom2")
+ PORT_CONFNAME(0x1f, 0x0b, "ROM 2")
+ PORT_CONFSETTING(0x10, "Operating System (reserved)")
+ PORT_CONFSETTING(0x09, "1770 DFS")
+ PORT_CONFSETTING(0x0a, "Viewsheet")
+ PORT_CONFSETTING(0x0b, "Edit")
+ PORT_CONFSETTING(0x0c, "BASIC")
+ PORT_CONFSETTING(0x0d, "ADFS")
+ PORT_CONFSETTING(0x0e, "View (and some GXR)")
+ PORT_CONFSETTING(0x0f, "Terminal and Operating System (reserved)")
+ PORT_START("link_rom3")
+ PORT_CONFNAME(0x1f, 0x0e, "ROM 3")
+ PORT_CONFSETTING(0x10, "Operating System (reserved)")
+ PORT_CONFSETTING(0x09, "1770 DFS")
+ PORT_CONFSETTING(0x0a, "Viewsheet")
+ PORT_CONFSETTING(0x0b, "Edit")
+ PORT_CONFSETTING(0x0c, "BASIC")
+ PORT_CONFSETTING(0x0d, "ADFS")
+ PORT_CONFSETTING(0x0e, "View (and some GXR)")
+ PORT_CONFSETTING(0x0f, "Terminal and Operating System (reserved)")
+INPUT_PORTS_END
+
+//-------------------------------------------------
+// input_ports - device-specific input ports
+//-------------------------------------------------
+
+ioport_constructor bbc_overlay_device::device_input_ports() const
+{
+ return INPUT_PORTS_NAME(overlay);
+}
+
+//-------------------------------------------------
+// device_add_mconfig - add device configuration
+//-------------------------------------------------
+
+void bbc_overlay_device::device_add_mconfig(machine_config &config)
+{
+ /* 3 x 16K rom sockets */
+ BBC_ROMSLOT16(config, m_rom[0], bbc_rom_devices, nullptr);
+ BBC_ROMSLOT16(config, m_rom[1], bbc_rom_devices, nullptr);
+ BBC_ROMSLOT16(config, m_rom[2], bbc_rom_devices, nullptr);
+}
+
+
+//**************************************************************************
+// LIVE DEVICE
+//**************************************************************************
+
+//-------------------------------------------------
+// bbc_overlay_device - constructor
+//-------------------------------------------------
+
+bbc_overlay_device::bbc_overlay_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
+ : device_t(mconfig, BBC_OVERLAY, tag, owner, clock)
+ , device_bbc_internal_interface(mconfig, *this)
+ , m_rom(*this, "romslot%u", 0U)
+ , m_link_rom(*this, "link_rom%u", 1U)
+{
+}
+
+//-------------------------------------------------
+// device_start - device-specific startup
+//-------------------------------------------------
+
+void bbc_overlay_device::device_start()
+{
+ /* register for save states */
+ save_item(NAME(m_romsel));
+}
+
+
+//**************************************************************************
+// IMPLEMENTATION
+//**************************************************************************
+
+uint8_t bbc_overlay_device::paged_r(offs_t offset)
+{
+ uint8_t data = 0xff;
+
+ switch (m_romsel)
+ {
+ case 9: case 10: case 11: case 12: case 13: case 14: case 15:
+ /* overlay banks */
+ if (m_link_rom[0]->read() == m_romsel && m_rom[0]->present())
+ {
+ data = m_rom[0]->read(offset);
+ }
+ else if (m_link_rom[1]->read() == m_romsel && m_rom[1]->present())
+ {
+ data = m_rom[1]->read(offset);
+ }
+ else if (m_link_rom[2]->read() == m_romsel && m_rom[2]->present())
+ {
+ data = m_rom[2]->read(offset);
+ }
+ else
+ {
+ data = m_region_swr->base()[offset + (m_romsel << 14)];
+ }
+ break;
+ case 4: case 5: case 6: case 7:
+ /* motherboard ram selected */
+ if (m_mb_rom[m_romsel & 0x0e] && m_mb_rom[m_romsel & 0x0e]->present())
+ {
+ data = m_mb_rom[m_romsel & 0x0e]->read(offset | (m_romsel & 0x01) << 14);
+ }
+ else
+ {
+ data = m_region_swr->base()[offset + (m_romsel << 14)];
+ }
+ break;
+ default:
+ /* motherboard rom sockets */
+ if (m_mb_rom[m_romsel] && m_mb_rom[m_romsel]->present())
+ {
+ data = m_mb_rom[m_romsel]->read(offset);
+ }
+ else
+ {
+ data = m_region_swr->base()[offset + (m_romsel << 14)];
+ }
+ break;
+ }
+
+ return data;
+}
+
+void bbc_overlay_device::paged_w(offs_t offset, uint8_t data)
+{
+ switch (m_romsel)
+ {
+ case 9: case 10: case 11: case 12: case 13: case 14: case 15:
+ /* overlay banks */
+ if (m_link_rom[0]->read() == m_romsel && m_rom[0]->present())
+ {
+ m_rom[0]->write(offset, data);
+ }
+ else if (m_link_rom[1]->read() == m_romsel && m_rom[1]->present())
+ {
+ m_rom[1]->write(offset, data);
+ }
+ else if (m_link_rom[2]->read() == m_romsel && m_rom[2]->present())
+ {
+ m_rom[2]->write(offset, data);
+ }
+ break;
+ case 4: case 5: case 6: case 7:
+ /* motherboard ram selected */
+ if (m_mb_rom[m_romsel & 0x0e])
+ {
+ m_mb_rom[m_romsel & 0x0e]->write(offset | (m_romsel & 0x01) << 14, data);
+ }
+ break;
+ default:
+ /* motherboard rom sockets */
+ if (m_mb_rom[m_romsel])
+ {
+ m_mb_rom[m_romsel]->write(offset, data);
+ }
+ break;
+ }
+}
+
+
+uint8_t bbc_overlay_device::mos_r(offs_t offset)
+{
+ uint8_t data = 0xff;
+
+ if (m_link_rom[0]->read() == 0x10 && m_rom[0]->present())
+ {
+ data = m_rom[0]->read(offset);
+ }
+ else if (m_link_rom[1]->read() == 0x10 && m_rom[1]->present())
+ {
+ data = m_rom[1]->read(offset);
+ }
+ else if (m_link_rom[2]->read() == 0x10 && m_rom[2]->present())
+ {
+ data = m_rom[2]->read(offset);
+ }
+ else
+ {
+ data = m_region_mos->base()[offset];
+ }
+
+ return data;
+}
diff --git a/src/devices/bus/bbc/internal/overlay.h b/src/devices/bus/bbc/internal/overlay.h
new file mode 100644
index 00000000000..1c11fe9cd18
--- /dev/null
+++ b/src/devices/bus/bbc/internal/overlay.h
@@ -0,0 +1,57 @@
+// license:BSD-3-Clause
+// copyright-holders:Nigel Barnes
+/**********************************************************************
+
+ Vine Micros Romboard '3' (Master OS Overlay Board)
+
+ http://chrisacorns.computinghistory.org.uk/8bit_Upgrades/Vine_MasterOSoverlay.html
+
+**********************************************************************/
+
+
+#ifndef MAME_BUS_BBC_INTERNAL_OVERLAY_H
+#define MAME_BUS_BBC_INTERNAL_OVERLAY_H
+
+#include "internal.h"
+
+
+//**************************************************************************
+// TYPE DEFINITIONS
+//**************************************************************************
+
+class bbc_overlay_device :
+ public device_t,
+ public device_bbc_internal_interface
+{
+public:
+ // construction/destruction
+ bbc_overlay_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
+
+protected:
+ // device-level overrides
+ virtual void device_start() override ATTR_COLD;
+
+ // optional information overrides
+ virtual void device_add_mconfig(machine_config &config) override ATTR_COLD;
+ virtual ioport_constructor device_input_ports() const override ATTR_COLD;
+
+ virtual bool overrides_rom() override { return true; }
+ virtual bool overrides_mos() override { return true; }
+ virtual void romsel_w(offs_t offset, uint8_t data) override { m_romsel = data & 0x0f; }
+ virtual uint8_t paged_r(offs_t offset) override;
+ virtual void paged_w(offs_t offset, uint8_t data) override;
+ virtual uint8_t mos_r(offs_t offset) override;
+
+private:
+ required_device_array<bbc_romslot_device, 3> m_rom;
+ required_ioport_array<3> m_link_rom;
+
+ uint8_t m_romsel;
+};
+
+
+// device type definition
+DECLARE_DEVICE_TYPE(BBC_OVERLAY, bbc_overlay_device);
+
+
+#endif /* MAME_BUS_BBC_INTERNAL_OVERLAY_H */
diff --git a/src/devices/bus/bbc/internal/peartree.cpp b/src/devices/bus/bbc/internal/peartree.cpp
new file mode 100644
index 00000000000..49281731097
--- /dev/null
+++ b/src/devices/bus/bbc/internal/peartree.cpp
@@ -0,0 +1,295 @@
+// license:BSD-3-Clause
+// copyright-holders:Nigel Barnes
+/**********************************************************************
+
+ Peartree MRxx00 ROM/RAM Boards
+
+ http://chrisacorns.computinghistory.org.uk/8bit_Upgrades/Peartree_ROMExpansion.html
+
+**********************************************************************/
+
+
+#include "emu.h"
+#include "peartree.h"
+
+
+//**************************************************************************
+// DEVICE DEFINITIONS
+//**************************************************************************
+
+DEFINE_DEVICE_TYPE(BBC_MR3000, bbc_mr3000_device, "bbc_mr3000", "Peartree MR3000 ROM Board");
+DEFINE_DEVICE_TYPE(BBC_MR4200, bbc_mr4200_device, "bbc_mr4200", "Peartree MR4200 RAM Board");
+DEFINE_DEVICE_TYPE(BBC_MR4300, bbc_mr4300_device, "bbc_mr4300", "Peartree MR4300 ROM/RAM Board");
+DEFINE_DEVICE_TYPE(BBC_MR4800, bbc_mr4800_device, "bbc_mr4800", "Peartree MR4800 RAM Board");
+
+
+//-------------------------------------------------
+// INPUT_PORTS( peartree )
+//-------------------------------------------------
+
+static INPUT_PORTS_START(peartree)
+ PORT_START("wp")
+ PORT_CONFNAME(0x01, 0x00, "Write Protect Sideways RAM")
+ PORT_CONFSETTING(0x00, DEF_STR(No))
+ PORT_CONFSETTING(0x01, DEF_STR(Yes))
+INPUT_PORTS_END
+
+//-------------------------------------------------
+// input_ports - device-specific input ports
+//-------------------------------------------------
+
+ioport_constructor bbc_mr4200_device::device_input_ports() const
+{
+ return INPUT_PORTS_NAME(peartree);
+}
+
+ioport_constructor bbc_mr4300_device::device_input_ports() const
+{
+ return INPUT_PORTS_NAME(peartree);
+}
+
+
+//-------------------------------------------------
+// device_add_mconfig - add device configuration
+//-------------------------------------------------
+
+void bbc_mr3000_device::device_add_mconfig(machine_config &config)
+{
+ /* 4 rom sockets */
+ BBC_ROMSLOT16(config, m_rom[12], bbc_rom_devices, nullptr);
+ BBC_ROMSLOT16(config, m_rom[13], bbc_rom_devices, nullptr);
+ BBC_ROMSLOT16(config, m_rom[14], bbc_rom_devices, nullptr);
+ BBC_ROMSLOT16(config, m_rom[15], bbc_rom_devices, nullptr);
+}
+
+void bbc_mr4200_device::device_add_mconfig(machine_config &config)
+{
+ /* 32K static ram */
+ BBC_ROMSLOT16(config, m_rom[13], bbc_rom_devices, "ram").set_fixed_ram(true);
+ BBC_ROMSLOT16(config, m_rom[15], bbc_rom_devices, "ram").set_fixed_ram(true);
+}
+
+void bbc_mr4300_device::device_add_mconfig(machine_config &config)
+{
+ /* 3 rom sockets, 32K static ram */
+ BBC_ROMSLOT16(config, m_rom[9], bbc_rom_devices, nullptr);
+ BBC_ROMSLOT16(config, m_rom[11], bbc_rom_devices, nullptr);
+ BBC_ROMSLOT16(config, m_rom[13], bbc_rom_devices, nullptr);
+ BBC_ROMSLOT16(config, m_rom[14], bbc_rom_devices, "ram").set_fixed_ram(true);
+ BBC_ROMSLOT16(config, m_rom[15], bbc_rom_devices, "ram").set_fixed_ram(true);
+}
+
+void bbc_mr4800_device::device_add_mconfig(machine_config &config)
+{
+ /* 128K static ram (battery backed) */
+ BBC_ROMSLOT16(config, m_rom[8], bbc_rom_devices, "nvram").set_fixed_ram(true);
+ BBC_ROMSLOT16(config, m_rom[9], bbc_rom_devices, "nvram").set_fixed_ram(true);
+ BBC_ROMSLOT16(config, m_rom[10], bbc_rom_devices, "nvram").set_fixed_ram(true);
+ BBC_ROMSLOT16(config, m_rom[11], bbc_rom_devices, "nvram").set_fixed_ram(true);
+ BBC_ROMSLOT16(config, m_rom[12], bbc_rom_devices, "nvram").set_fixed_ram(true);
+ BBC_ROMSLOT16(config, m_rom[13], bbc_rom_devices, "nvram").set_fixed_ram(true);
+ BBC_ROMSLOT16(config, m_rom[14], bbc_rom_devices, "nvram").set_fixed_ram(true);
+ BBC_ROMSLOT16(config, m_rom[15], bbc_rom_devices, "nvram").set_fixed_ram(true);
+}
+
+
+//**************************************************************************
+// LIVE DEVICE
+//**************************************************************************
+
+//-------------------------------------------------
+// bbc_mr3000_device - constructor
+//-------------------------------------------------
+
+bbc_mr3000_device::bbc_mr3000_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_internal_interface(mconfig, *this)
+ , m_rom(*this, "romslot%u", 0U)
+{
+}
+
+bbc_mr3000_device::bbc_mr3000_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
+ : bbc_mr3000_device(mconfig, BBC_MR3000, tag, owner, clock)
+{
+}
+
+bbc_mr4200_device::bbc_mr4200_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
+ : bbc_mr3000_device(mconfig, BBC_MR4200, tag, owner, clock)
+ , m_wp(*this, "wp")
+{
+}
+
+//-------------------------------------------------
+// bbc_mr4300_device - constructor
+//-------------------------------------------------
+
+bbc_mr4300_device::bbc_mr4300_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_internal_interface(mconfig, *this)
+ , m_rom(*this, "romslot%u", 0U)
+ , m_wp(*this, "wp")
+{
+}
+
+bbc_mr4300_device::bbc_mr4300_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
+ : bbc_mr4300_device(mconfig, BBC_MR4300, tag, owner, clock)
+{
+}
+
+bbc_mr4800_device::bbc_mr4800_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
+ : bbc_mr4300_device(mconfig, BBC_MR4800, tag, owner, clock)
+{
+}
+
+
+//-------------------------------------------------
+// device_start - device-specific startup
+//-------------------------------------------------
+
+void bbc_mr3000_device::device_start()
+{
+ /* register for save states */
+ save_item(NAME(m_romsel));
+}
+
+void bbc_mr4300_device::device_start()
+{
+ /* register for save states */
+ save_item(NAME(m_romsel));
+}
+
+
+//**************************************************************************
+// IMPLEMENTATION
+//**************************************************************************
+
+uint8_t bbc_mr3000_device::paged_r(offs_t offset)
+{
+ uint8_t data = 0xff;
+
+ switch (m_romsel)
+ {
+ case 8: case 9: case 10: case 11:
+ /* motherboard rom sockets 0-3 are re-assigned to 8-11 */
+ if (m_mb_rom[m_romsel & 0x03] && m_mb_rom[m_romsel & 0x03]->present())
+ {
+ data = m_mb_rom[m_romsel & 0x03]->read(offset);
+ }
+ else
+ {
+ data = m_region_swr->base()[offset + (m_romsel << 14) - 0x20000];
+ }
+ break;
+ case 12: case 13: case 14: case 15:
+ /* expansion board sockets */
+ if (m_rom[m_romsel] && m_rom[m_romsel]->present())
+ {
+ data = m_rom[m_romsel]->read(offset);
+ }
+ else
+ {
+ data = m_region_swr->base()[offset + (m_romsel << 14)];
+ }
+ break;
+ }
+
+ return data;
+}
+
+void bbc_mr3000_device::paged_w(offs_t offset, uint8_t data)
+{
+ switch (m_romsel)
+ {
+ case 8: case 9: case 10: case 11:
+ /* motherboard rom sockets 0-3 are re-assigned to 8-11 */
+ if (m_mb_rom[m_romsel & 0x03])
+ {
+ m_mb_rom[m_romsel & 0x03]->write(offset, data);
+ }
+ break;
+ case 12: case 13: case 14: case 15:
+ /* expansion board sockets */
+ if (m_rom[m_romsel])
+ {
+ m_rom[m_romsel]->write(offset, data);
+ }
+ break;
+ }
+}
+
+
+void bbc_mr4200_device::paged_w(offs_t offset, uint8_t data)
+{
+ switch (m_romsel)
+ {
+ case 8: case 9: case 10: case 11:
+ /* motherboard rom sockets 0-3 are re-assigned to 8-11 */
+ if (m_mb_rom[m_romsel & 0x03])
+ {
+ m_mb_rom[m_romsel & 0x03]->write(offset, data);
+ }
+ break;
+ case 12: case 13: case 14: case 15:
+ /* expansion board sockets (if not write protected) */
+ if (m_rom[m_romsel] && !m_wp->read())
+ {
+ m_rom[m_romsel]->write(offset, data);
+ }
+ break;
+ }
+}
+
+
+uint8_t bbc_mr4300_device::paged_r(offs_t offset)
+{
+ uint8_t data = 0xff;
+
+ switch (m_romsel)
+ {
+ case 4: case 5: case 6: case 7:
+ /* motherboard rom sockets 0-3 are re-assigned to 4-7 */
+ if (m_mb_rom[m_romsel & 0x03] && m_mb_rom[m_romsel & 0x03]->present())
+ {
+ data = m_mb_rom[m_romsel & 0x03]->read(offset);
+ }
+ else
+ {
+ data = m_region_swr->base()[offset + (m_romsel << 14) - 0x10000];
+ }
+ break;
+ case 8: case 9: case 10: case 11: case 12: case 13: case 14: case 15:
+ /* expansion board sockets */
+ if (m_rom[m_romsel] && m_rom[m_romsel]->present())
+ {
+ data = m_rom[m_romsel]->read(offset);
+ }
+ else
+ {
+ data = m_region_swr->base()[offset + (m_romsel << 14)];
+ }
+ break;
+ }
+
+ return data;
+}
+
+void bbc_mr4300_device::paged_w(offs_t offset, uint8_t data)
+{
+ switch (m_romsel)
+ {
+ case 4: case 5: case 6: case 7:
+ /* motherboard rom sockets 0-3 are re-assigned to 4-7 */
+ if (m_mb_rom[m_romsel & 0x03])
+ {
+ m_mb_rom[m_romsel & 0x03]->write(offset, data);
+ }
+ break;
+ case 8: case 9: case 10: case 11: case 12: case 13: case 14: case 15:
+ /* expansion board sockets (if not write protected) */
+ if (m_rom[m_romsel] && !m_wp->read())
+ {
+ m_rom[m_romsel]->write(offset, data);
+ }
+ break;
+ }
+}
diff --git a/src/devices/bus/bbc/internal/peartree.h b/src/devices/bus/bbc/internal/peartree.h
new file mode 100644
index 00000000000..e3bb2fa95c2
--- /dev/null
+++ b/src/devices/bus/bbc/internal/peartree.h
@@ -0,0 +1,116 @@
+// license:BSD-3-Clause
+// copyright-holders:Nigel Barnes
+/**********************************************************************
+
+ Peartree MRxx00 ROM/RAM Boards
+
+ http://chrisacorns.computinghistory.org.uk/8bit_Upgrades/Peartree_ROMExpansion.html
+
+**********************************************************************/
+
+
+#ifndef MAME_BUS_BBC_INTERNAL_PEARTREE_H
+#define MAME_BUS_BBC_INTERNAL_PEARTREE_H
+
+#include "internal.h"
+
+
+//**************************************************************************
+// TYPE DEFINITIONS
+//**************************************************************************
+
+class bbc_mr3000_device :
+ public device_t,
+ public device_bbc_internal_interface
+{
+public:
+ // construction/destruction
+ bbc_mr3000_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
+
+protected:
+ bbc_mr3000_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 ATTR_COLD;
+
+ // optional information overrides
+ virtual void device_add_mconfig(machine_config &config) override ATTR_COLD;
+
+ optional_device_array<bbc_romslot_device, 16> m_rom;
+
+ virtual bool overrides_rom() override { return true; }
+ virtual void romsel_w(offs_t offset, uint8_t data) override { m_romsel = data & 0x0f; }
+ virtual uint8_t paged_r(offs_t offset) override;
+ virtual void paged_w(offs_t offset, uint8_t data) override;
+
+ uint8_t m_romsel;
+};
+
+
+class bbc_mr4200_device : public bbc_mr3000_device
+{
+public:
+ // construction/destruction
+ bbc_mr4200_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 ATTR_COLD;
+ virtual ioport_constructor device_input_ports() const override ATTR_COLD;
+
+ required_ioport m_wp;
+
+ virtual void paged_w(offs_t offset, uint8_t data) override;
+};
+
+
+class bbc_mr4300_device :
+ public device_t,
+ public device_bbc_internal_interface
+{
+public:
+ // construction/destruction
+ bbc_mr4300_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
+
+protected:
+ bbc_mr4300_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 ATTR_COLD;
+
+ // optional information overrides
+ virtual void device_add_mconfig(machine_config &config) override ATTR_COLD;
+ virtual ioport_constructor device_input_ports() const override ATTR_COLD;
+
+ optional_device_array<bbc_romslot_device, 16> m_rom;
+ required_ioport m_wp;
+
+ virtual bool overrides_rom() override { return true; }
+ virtual void romsel_w(offs_t offset, uint8_t data) override { m_romsel = data & 0x0f; }
+ virtual uint8_t paged_r(offs_t offset) override;
+ virtual void paged_w(offs_t offset, uint8_t data) override;
+
+ uint8_t m_romsel;
+};
+
+
+class bbc_mr4800_device : public bbc_mr4300_device
+{
+public:
+ // construction/destruction
+ bbc_mr4800_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 ATTR_COLD;
+};
+
+
+// device type definition
+DECLARE_DEVICE_TYPE(BBC_MR3000, bbc_mr3000_device);
+DECLARE_DEVICE_TYPE(BBC_MR4200, bbc_mr4200_device);
+DECLARE_DEVICE_TYPE(BBC_MR4300, bbc_mr4300_device);
+DECLARE_DEVICE_TYPE(BBC_MR4800, bbc_mr4800_device);
+
+
+#endif /* MAME_BUS_BBC_INTERNAL_PEARTREE_H */
diff --git a/src/devices/bus/bbc/internal/ramamp.cpp b/src/devices/bus/bbc/internal/ramamp.cpp
new file mode 100644
index 00000000000..586159377aa
--- /dev/null
+++ b/src/devices/bus/bbc/internal/ramamp.cpp
@@ -0,0 +1,155 @@
+// license:BSD-3-Clause
+// copyright-holders:Nigel Barnes
+/**********************************************************************
+
+ Ramamp Computers Sideways RAM/ROM Board
+
+ http://chrisacorns.computinghistory.org.uk/8bit_Upgrades/RAMAMP_SidewaysRAMROM.html
+
+**********************************************************************/
+
+
+#include "emu.h"
+#include "ramamp.h"
+
+
+//**************************************************************************
+// DEVICE DEFINITIONS
+//**************************************************************************
+
+DEFINE_DEVICE_TYPE(BBC_RAMAMP, bbc_ramamp_device, "bbc_ramamp", "Ramamp Sideways RAM/ROM Board");
+
+
+//-------------------------------------------------
+// INPUT_PORTS( ramamp )
+//-------------------------------------------------
+
+static INPUT_PORTS_START(ramamp)
+ PORT_START("wp")
+ PORT_CONFNAME(0x01, 0x00, "Write Protect Sideways RAM")
+ PORT_CONFSETTING(0x00, DEF_STR(No))
+ PORT_CONFSETTING(0x01, DEF_STR(Yes))
+INPUT_PORTS_END
+
+//-------------------------------------------------
+// input_ports - device-specific input ports
+//-------------------------------------------------
+
+ioport_constructor bbc_ramamp_device::device_input_ports() const
+{
+ return INPUT_PORTS_NAME(ramamp);
+}
+
+//-------------------------------------------------
+// device_add_mconfig - add device configuration
+//-------------------------------------------------
+
+void bbc_ramamp_device::device_add_mconfig(machine_config &config)
+{
+ /* 6 rom sockets, 32K dynamic ram */
+ BBC_ROMSLOT16(config, m_rom[8], bbc_rom_devices, nullptr);
+ BBC_ROMSLOT16(config, m_rom[9], bbc_rom_devices, nullptr);
+ BBC_ROMSLOT16(config, m_rom[10], bbc_rom_devices, "ram").set_fixed_ram(true);
+ BBC_ROMSLOT16(config, m_rom[11], bbc_rom_devices, nullptr);
+ BBC_ROMSLOT16(config, m_rom[12], bbc_rom_devices, nullptr);
+ BBC_ROMSLOT16(config, m_rom[13], bbc_rom_devices, "ram").set_fixed_ram(true);
+ BBC_ROMSLOT16(config, m_rom[14], bbc_rom_devices, nullptr);
+ BBC_ROMSLOT16(config, m_rom[15], bbc_rom_devices, nullptr);
+}
+
+//**************************************************************************
+// LIVE DEVICE
+//**************************************************************************
+
+//-------------------------------------------------
+// bbc_ramamp_device - constructor
+//-------------------------------------------------
+
+bbc_ramamp_device::bbc_ramamp_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
+ : device_t(mconfig, BBC_RAMAMP, tag, owner, clock)
+ , device_bbc_internal_interface(mconfig, *this)
+ , m_rom(*this, "romslot%u", 0U)
+ , m_wp(*this, "wp")
+{
+}
+
+//-------------------------------------------------
+// device_start - device-specific startup
+//-------------------------------------------------
+
+void bbc_ramamp_device::device_start()
+{
+ /* move internal roms to board */
+ memmove(m_region_swr->base() + 0x2c000, m_region_swr->base(), 0x8000);
+ memmove(m_region_swr->base() + 0x38000, m_region_swr->base() + 0x8000, 0x8000);
+ memset(m_region_swr->base(), 0xff, 0x10000);
+
+ /* register for save states */
+ save_item(NAME(m_romsel));
+}
+
+
+//**************************************************************************
+// IMPLEMENTATION
+//**************************************************************************
+
+uint8_t bbc_ramamp_device::paged_r(offs_t offset)
+{
+ uint8_t data = 0xff;
+
+ switch (m_romsel)
+ {
+ case 0: case 1: case 2: case 3:
+ /* motherboard rom sockets */
+ if (m_mb_rom[m_romsel] && m_mb_rom[m_romsel]->present())
+ {
+ data = m_mb_rom[m_romsel]->read(offset);
+ }
+ else
+ {
+ data = m_region_swr->base()[offset + (m_romsel << 14)];
+ }
+ break;
+ default:
+ /* expansion board sockets */
+ if (m_rom[m_romsel] && m_rom[m_romsel]->present())
+ {
+ data = m_rom[m_romsel]->read(offset);
+ }
+ else
+ {
+ data = m_region_swr->base()[offset + (m_romsel << 14)];
+ }
+ break;
+ }
+
+ return data;
+}
+
+void bbc_ramamp_device::paged_w(offs_t offset, uint8_t data)
+{
+ switch (m_romsel)
+ {
+ case 0: case 1: case 2: case 3:
+ /* motherboard rom sockets */
+ if (m_mb_rom[m_romsel])
+ {
+ m_mb_rom[m_romsel]->write(offset, data);
+ }
+ break;
+ case 10: case 13:
+ /* expansion board sockets */
+ if (m_rom[m_romsel] && !m_wp->read())
+ {
+ m_rom[m_romsel]->write(offset, data);
+ }
+ break;
+ default:
+ /* expansion board sockets */
+ if (m_rom[m_romsel])
+ {
+ m_rom[m_romsel]->write(offset, data);
+ }
+ break;
+ }
+}
diff --git a/src/devices/bus/bbc/internal/ramamp.h b/src/devices/bus/bbc/internal/ramamp.h
new file mode 100644
index 00000000000..6adc421c389
--- /dev/null
+++ b/src/devices/bus/bbc/internal/ramamp.h
@@ -0,0 +1,55 @@
+// license:BSD-3-Clause
+// copyright-holders:Nigel Barnes
+/**********************************************************************
+
+ Ramamp Computers Sideways RAM/ROM Board
+
+ http://chrisacorns.computinghistory.org.uk/8bit_Upgrades/RAMAMP_SidewaysRAMROM.html
+
+**********************************************************************/
+
+
+#ifndef MAME_BUS_BBC_INTERNAL_RAMAMP_H
+#define MAME_BUS_BBC_INTERNAL_RAMAMP_H
+
+#include "internal.h"
+
+
+//**************************************************************************
+// TYPE DEFINITIONS
+//**************************************************************************
+
+class bbc_ramamp_device :
+ public device_t,
+ public device_bbc_internal_interface
+{
+public:
+ // construction/destruction
+ bbc_ramamp_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
+
+protected:
+ // device-level overrides
+ virtual void device_start() override ATTR_COLD;
+
+ // optional information overrides
+ virtual void device_add_mconfig(machine_config &config) override ATTR_COLD;
+ virtual ioport_constructor device_input_ports() const override ATTR_COLD;
+
+ virtual bool overrides_rom() override { return true; }
+ virtual void romsel_w(offs_t offset, uint8_t data) override { m_romsel = data & 0x0f; }
+ virtual uint8_t paged_r(offs_t offset) override;
+ virtual void paged_w(offs_t offset, uint8_t data) override;
+
+private:
+ optional_device_array<bbc_romslot_device, 16> m_rom;
+ required_ioport m_wp;
+
+ uint8_t m_romsel;
+};
+
+
+// device type definition
+DECLARE_DEVICE_TYPE(BBC_RAMAMP, bbc_ramamp_device);
+
+
+#endif /* MAME_BUS_BBC_INTERNAL_RAMAMP_H */
diff --git a/src/devices/bus/bbc/internal/raven20.cpp b/src/devices/bus/bbc/internal/raven20.cpp
new file mode 100644
index 00000000000..f6bb3efdb4b
--- /dev/null
+++ b/src/devices/bus/bbc/internal/raven20.cpp
@@ -0,0 +1,112 @@
+// license:BSD-3-Clause
+// copyright-holders:Nigel Barnes
+/**********************************************************************
+
+ Raven-20 RAM expansion board
+
+ TODO:
+ - Verify behaviour of RAVEN-20 1.00, seems buggy or incomplete emulation.
+ - FAST mode (*FRON) is not understood.
+
+**********************************************************************/
+
+
+#include "emu.h"
+#include "raven20.h"
+
+
+//**************************************************************************
+// DEVICE DEFINITIONS
+//**************************************************************************
+
+DEFINE_DEVICE_TYPE(BBC_RAVEN20, bbc_raven20_device, "bbc_raven20", "Raven-20 RAM expansion")
+
+
+//-------------------------------------------------
+// ROM( raven20 )
+//-------------------------------------------------
+
+ROM_START(raven20)
+ ROM_REGION(0x2000, "exp_rom", 0)
+ ROM_SYSTEM_BIOS(0, "106", "Raven-20 1.06")
+ ROMX_LOAD("raven20_1.06.rom", 0x0000, 0x2000, CRC(7efb0ab3) SHA1(d395199ef8f51579fe74e3d7d8dab1de6e0b30e2), ROM_BIOS(0))
+ ROM_SYSTEM_BIOS(1, "100", "Raven-20 1.00")
+ ROMX_LOAD("raven20_1.00.rom", 0x0000, 0x2000, CRC(e8c8f9d5) SHA1(e4f2acc07969e10c082355c82d8d1cbc1c08ee2e), ROM_BIOS(1))
+ROM_END
+
+//-------------------------------------------------
+// rom_region - device-specific ROM region
+//-------------------------------------------------
+
+const tiny_rom_entry *bbc_raven20_device::device_rom_region() const
+{
+ return ROM_NAME( raven20 );
+}
+
+//**************************************************************************
+// LIVE DEVICE
+//**************************************************************************
+
+//-------------------------------------------------
+// bbc_raven20_device - constructor
+//-------------------------------------------------
+
+bbc_raven20_device::bbc_raven20_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
+ : device_t(mconfig, BBC_RAVEN20, tag, owner, clock)
+ , device_bbc_internal_interface(mconfig, *this)
+{
+}
+
+//-------------------------------------------------
+// device_start - device-specific startup
+//-------------------------------------------------
+
+void bbc_raven20_device::device_start()
+{
+ address_space &program = m_maincpu->space(AS_PROGRAM);
+
+ program.install_write_handler(0xd000, 0xd000, write8sm_delegate(*this, FUNC(bbc_raven20_device::enable_w)));
+ program.install_write_handler(0xc000, 0xc000, write8sm_delegate(*this, FUNC(bbc_raven20_device::disable_w)));
+
+ m_shadow = false;
+ m_ram = std::make_unique<uint8_t[]>(0x5000);
+
+ /* register for save states */
+ save_item(NAME(m_shadow));
+ save_pointer(NAME(m_ram), 0x5000);
+}
+
+
+//**************************************************************************
+// IMPLEMENTATION
+//**************************************************************************
+
+void bbc_raven20_device::enable_w(offs_t offset, uint8_t data)
+{
+ m_shadow = true;
+}
+
+void bbc_raven20_device::disable_w(offs_t offset, uint8_t data)
+{
+ m_shadow = false;
+}
+
+uint8_t bbc_raven20_device::ram_r(offs_t offset)
+{
+ uint8_t data = 0xff;
+
+ if (m_shadow && offset >= 0x3000)
+ data = m_ram[offset - 0x3000];
+ else
+ data = m_mb_ram->pointer()[offset];
+
+ return data;
+}
+
+void bbc_raven20_device::ram_w(offs_t offset, uint8_t data)
+{
+ if (m_shadow && offset >= 0x3000)
+ m_ram[offset - 0x3000] = data;
+ else
+ m_mb_ram->pointer()[offset] = data;
+}
diff --git a/src/devices/bus/bbc/internal/raven20.h b/src/devices/bus/bbc/internal/raven20.h
new file mode 100644
index 00000000000..463d5aa5941
--- /dev/null
+++ b/src/devices/bus/bbc/internal/raven20.h
@@ -0,0 +1,52 @@
+// license:BSD-3-Clause
+// copyright-holders:Nigel Barnes
+/**********************************************************************
+
+ Raven-20 RAM expansion board
+
+**********************************************************************/
+
+
+#ifndef MAME_BUS_BBC_INTERNAL_RAVEN20_H
+#define MAME_BUS_BBC_INTERNAL_RAVEN20_H
+
+#include "internal.h"
+
+
+//**************************************************************************
+// TYPE DEFINITIONS
+//**************************************************************************
+
+class bbc_raven20_device :
+ public device_t,
+ public device_bbc_internal_interface
+{
+public:
+ // construction/destruction
+ bbc_raven20_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
+
+protected:
+ // device-level overrides
+ virtual void device_start() override ATTR_COLD;
+
+ // optional information overrides
+ virtual const tiny_rom_entry *device_rom_region() const override ATTR_COLD;
+
+ virtual bool overrides_ram() override { return true; }
+ virtual uint8_t ram_r(offs_t offset) override;
+ virtual void ram_w(offs_t offset, uint8_t data) override;
+
+private:
+ void enable_w(offs_t offset, uint8_t data);
+ void disable_w(offs_t offset, uint8_t data);
+
+ bool m_shadow;
+ std::unique_ptr<uint8_t[]> m_ram;
+};
+
+
+// device type definition
+DECLARE_DEVICE_TYPE(BBC_RAVEN20, bbc_raven20_device)
+
+
+#endif // MAME_BUS_BBC_INTERNAL_RAVEN20_H
diff --git a/src/devices/bus/bbc/internal/romex.cpp b/src/devices/bus/bbc/internal/romex.cpp
new file mode 100644
index 00000000000..9d7932db81f
--- /dev/null
+++ b/src/devices/bus/bbc/internal/romex.cpp
@@ -0,0 +1,134 @@
+// license:BSD-3-Clause
+// copyright-holders:Nigel Barnes
+/**********************************************************************
+
+ GCC (Cambridge) Romex 13
+
+ http://chrisacorns.computinghistory.org.uk/8bit_Upgrades/GCC_Romex13.html
+
+**********************************************************************/
+
+
+#include "emu.h"
+#include "romex.h"
+
+
+//**************************************************************************
+// DEVICE DEFINITIONS
+//**************************************************************************
+
+DEFINE_DEVICE_TYPE(BBC_ROMEX13, bbc_romex13_device, "bbc_romex13", "GCC Romex13 ROM Expansion");
+
+
+//-------------------------------------------------
+// device_add_mconfig - add device configuration
+//-------------------------------------------------
+
+void bbc_romex13_device::device_add_mconfig(machine_config &config)
+{
+ /* TODO: romslot2 is unavailable when board is fitted, replaced by socket on board */
+ //config.device_remove(":romslot2");
+
+ /* 13 rom sockets */
+ BBC_ROMSLOT16(config, m_rom[2], bbc_rom_devices, nullptr);
+ BBC_ROMSLOT16(config, m_rom[4], bbc_rom_devices, nullptr);
+ BBC_ROMSLOT16(config, m_rom[5], bbc_rom_devices, nullptr);
+ BBC_ROMSLOT16(config, m_rom[6], bbc_rom_devices, nullptr);
+ BBC_ROMSLOT16(config, m_rom[7], bbc_rom_devices, nullptr);
+ BBC_ROMSLOT16(config, m_rom[8], bbc_rom_devices, nullptr);
+ BBC_ROMSLOT16(config, m_rom[9], bbc_rom_devices, nullptr);
+ BBC_ROMSLOT16(config, m_rom[10], bbc_rom_devices, nullptr);
+ BBC_ROMSLOT16(config, m_rom[11], bbc_rom_devices, nullptr);
+ BBC_ROMSLOT16(config, m_rom[12], bbc_rom_devices, nullptr);
+ BBC_ROMSLOT16(config, m_rom[13], bbc_rom_devices, nullptr);
+ BBC_ROMSLOT16(config, m_rom[14], bbc_rom_devices, nullptr);
+ BBC_ROMSLOT16(config, m_rom[15], bbc_rom_devices, nullptr);
+}
+
+//**************************************************************************
+// LIVE DEVICE
+//**************************************************************************
+
+//-------------------------------------------------
+// bbc_romex13_device - constructor
+//-------------------------------------------------
+
+bbc_romex13_device::bbc_romex13_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
+ : device_t(mconfig, BBC_ROMEX13, tag, owner, clock)
+ , device_bbc_internal_interface(mconfig, *this)
+ , m_rom(*this, "romslot%u", 0U)
+{
+}
+
+//-------------------------------------------------
+// device_start - device-specific startup
+//-------------------------------------------------
+
+void bbc_romex13_device::device_start()
+{
+ /* move internal roms to board */
+ memmove(m_region_swr->base() + 0x30000, m_region_swr->base(), 0x10000);
+ memset(m_region_swr->base(), 0xff, 0x10000);
+
+ /* register for save states */
+ save_item(NAME(m_romsel));
+}
+
+
+//**************************************************************************
+// IMPLEMENTATION
+//**************************************************************************
+
+uint8_t bbc_romex13_device::paged_r(offs_t offset)
+{
+ uint8_t data = 0xff;
+
+ switch (m_romsel)
+ {
+ case 0: case 1: case 3:
+ /* motherboard rom sockets */
+ if (m_mb_rom[m_romsel] && m_mb_rom[m_romsel]->present())
+ {
+ data = m_mb_rom[m_romsel]->read(offset);
+ }
+ else
+ {
+ data = m_region_swr->base()[offset + (m_romsel << 14)];
+ }
+ break;
+ default:
+ /* expansion board sockets */
+ if (m_rom[m_romsel] && m_rom[m_romsel]->present())
+ {
+ data = m_rom[m_romsel]->read(offset);
+ }
+ else
+ {
+ data = m_region_swr->base()[offset + (m_romsel << 14)];
+ }
+ break;
+ }
+
+ return data;
+}
+
+void bbc_romex13_device::paged_w(offs_t offset, uint8_t data)
+{
+ switch (m_romsel)
+ {
+ case 0: case 1: case 3:
+ /* motherboard rom sockets */
+ if (m_mb_rom[m_romsel])
+ {
+ m_mb_rom[m_romsel]->write(offset, data);
+ }
+ break;
+ default:
+ /* expansion board sockets */
+ if (m_rom[m_romsel])
+ {
+ m_rom[m_romsel]->write(offset, data);
+ }
+ break;
+ }
+}
diff --git a/src/devices/bus/bbc/internal/romex.h b/src/devices/bus/bbc/internal/romex.h
new file mode 100644
index 00000000000..7d7bcc6d58f
--- /dev/null
+++ b/src/devices/bus/bbc/internal/romex.h
@@ -0,0 +1,53 @@
+// license:BSD-3-Clause
+// copyright-holders:Nigel Barnes
+/**********************************************************************
+
+ GCC (Cambridge) Romex 13
+
+ http://chrisacorns.computinghistory.org.uk/8bit_Upgrades/GCC_Romex13.html
+
+**********************************************************************/
+
+
+#ifndef MAME_BUS_BBC_INTERNAL_ROMEX_H
+#define MAME_BUS_BBC_INTERNAL_ROMEX_H
+
+#include "internal.h"
+
+
+//**************************************************************************
+// TYPE DEFINITIONS
+//**************************************************************************
+
+class bbc_romex13_device :
+ public device_t,
+ public device_bbc_internal_interface
+{
+public:
+ // construction/destruction
+ bbc_romex13_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
+
+protected:
+ // device-level overrides
+ virtual void device_start() override ATTR_COLD;
+
+ // optional information overrides
+ virtual void device_add_mconfig(machine_config &config) override ATTR_COLD;
+
+ virtual bool overrides_rom() override { return true; }
+ virtual void romsel_w(offs_t offset, uint8_t data) override { m_romsel = data & 0x0f; }
+ virtual uint8_t paged_r(offs_t offset) override;
+ virtual void paged_w(offs_t offset, uint8_t data) override;
+
+private:
+ optional_device_array<bbc_romslot_device, 16> m_rom;
+
+ uint8_t m_romsel;
+};
+
+
+// device type definition
+DECLARE_DEVICE_TYPE(BBC_ROMEX13, bbc_romex13_device);
+
+
+#endif /* MAME_BUS_BBC_INTERNAL_ROMEX_H */
diff --git a/src/devices/bus/bbc/internal/stl2m128.cpp b/src/devices/bus/bbc/internal/stl2m128.cpp
new file mode 100644
index 00000000000..46b595aedfa
--- /dev/null
+++ b/src/devices/bus/bbc/internal/stl2m128.cpp
@@ -0,0 +1,248 @@
+// license:BSD-3-Clause
+// copyright-holders:Nigel Barnes
+/**********************************************************************
+
+ Solidisk Twomeg 128K Shadow and Sideways ROM/RAM board
+
+**********************************************************************/
+
+
+#include "emu.h"
+#include "stl2m128.h"
+
+
+//**************************************************************************
+// DEVICE DEFINITIONS
+//**************************************************************************
+
+DEFINE_DEVICE_TYPE(BBC_STL2M128, bbc_stl2m128_device, "bbc_stl2m128", "Solidisk Twomeg 128K RAM/ROM Expansion");
+
+
+//-------------------------------------------------
+// INPUT_PORTS( stl2m128 )
+//-------------------------------------------------
+
+static INPUT_PORTS_START(stl2m128)
+ PORT_START("wp")
+ PORT_CONFNAME(0x01, 0x00, "Write Protect Sideways RAM")
+ PORT_CONFSETTING(0x00, DEF_STR(No))
+ PORT_CONFSETTING(0x01, DEF_STR(Yes))
+INPUT_PORTS_END
+
+//-------------------------------------------------
+// input_ports - device-specific input ports
+//-------------------------------------------------
+
+ioport_constructor bbc_stl2m128_device::device_input_ports() const
+{
+ return INPUT_PORTS_NAME(stl2m128);
+}
+
+//-------------------------------------------------
+// ROM( stl2m128 )
+//-------------------------------------------------
+
+ROM_START(stl2m128)
+ ROM_REGION(0x4000, "rom", ROMREGION_ERASEFF)
+ // ROM image usually distributed on floppy, to load into RAM
+ ROM_LOAD("manger128-1.00.rom", 0x0000, 0x102a, CRC(dbe84acb) SHA1(d170632b88d0ab276a919b0076dca305094a39b2))
+ROM_END
+
+
+//-------------------------------------------------
+// device_add_mconfig - add device configuration
+//-------------------------------------------------
+
+void bbc_stl2m128_device::device_add_mconfig(machine_config &config)
+{
+ BBC_ROMSLOT16(config, m_rom[4], bbc_rom_devices, "ram").set_fixed_ram(true);
+ BBC_ROMSLOT16(config, m_rom[5], bbc_rom_devices, "ram").set_fixed_ram(true);
+ BBC_ROMSLOT16(config, m_rom[6], bbc_rom_devices, "ram").set_fixed_ram(true);
+ BBC_ROMSLOT16(config, m_rom[7], bbc_rom_devices, "ram").set_fixed_ram(true);
+ BBC_ROMSLOT16(config, m_rom[8], bbc_rom_devices, nullptr);
+ BBC_ROMSLOT16(config, m_rom[9], bbc_rom_devices, nullptr);
+ BBC_ROMSLOT16(config, m_rom[10], bbc_rom_devices, nullptr);
+ BBC_ROMSLOT16(config, m_rom[11], bbc_rom_devices, nullptr);
+ BBC_ROMSLOT16(config, m_rom[12], bbc_rom_devices, "ram").set_fixed_ram(true);
+ BBC_ROMSLOT16(config, m_rom[13], bbc_rom_devices, "ram").set_fixed_ram(true);
+ BBC_ROMSLOT16(config, m_rom[14], bbc_rom_devices, "ram").set_fixed_ram(true);
+ BBC_ROMSLOT16(config, m_rom[15], bbc_rom_devices, "ram").set_fixed_ram(true);
+}
+
+//-------------------------------------------------
+// rom_region - device-specific ROM region
+//-------------------------------------------------
+
+const tiny_rom_entry *bbc_stl2m128_device::device_rom_region() const
+{
+ return ROM_NAME(stl2m128);
+}
+
+
+//**************************************************************************
+// LIVE DEVICE
+//**************************************************************************
+
+//-------------------------------------------------
+// bbc_stl2m128_device - constructor
+//-------------------------------------------------
+
+bbc_stl2m128_device::bbc_stl2m128_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
+ : device_t(mconfig, BBC_STL2M128, tag, owner, clock)
+ , device_bbc_internal_interface(mconfig, *this)
+ , m_rom(*this, "romslot%u", 0U)
+ , m_wp(*this, "wp")
+{
+}
+
+
+//-------------------------------------------------
+// device_start - device-specific startup
+//-------------------------------------------------
+
+void bbc_stl2m128_device::device_start()
+{
+ m_ram = std::make_unique<uint8_t[]>(0x20000);
+
+ /* copy rom image into ram bank c */
+ memcpy(&m_ram[0x10000], memregion("rom")->base(), 0x4000);
+
+ /* move internal roms to board */
+ memmove(m_region_swr->base() + 0x20000, m_region_swr->base(), 0x10000);
+ memset(m_region_swr->base(), 0xff, 0x10000);
+
+ /* register for save states */
+ save_pointer(NAME(m_ram), 0x20000);
+ save_item(NAME(m_romsel));
+ save_item(NAME(m_shadow));
+}
+
+
+//**************************************************************************
+// IMPLEMENTATION
+//**************************************************************************
+
+void bbc_stl2m128_device::romsel_w(offs_t offset, uint8_t data)
+{
+ switch (offset & 0x0c)
+ {
+ case 0x00:
+ m_romsel = data & 0x0f;
+ break;
+ case 0x04:
+ m_shadow = data;
+ break;
+ }
+}
+
+uint8_t bbc_stl2m128_device::ram_r(offs_t offset)
+{
+ uint8_t data = 0xff;
+
+ if (BIT(m_shadow, 7) && offset >= 0x2000)
+ {
+ if (BIT(m_shadow, 1))
+ {
+ /* banks E/F */
+ data = m_ram[offset | 0x18000];
+ }
+ else
+ {
+ /* banks C/D */
+ data = m_ram[offset | 0x10000];
+ }
+ }
+ else
+ {
+ data = m_mb_ram->pointer()[offset];
+ }
+
+ return data;
+}
+
+void bbc_stl2m128_device::ram_w(offs_t offset, uint8_t data)
+{
+ if (BIT(m_shadow, 7) && offset >= 0x2000)
+ {
+ if (BIT(m_shadow, 1))
+ {
+ /* banks E/F */
+ m_ram[offset | 0x18000] = data;
+ }
+ else
+ {
+ /* banks C/D */
+ m_ram[offset | 0x10000] = data;
+ }
+ }
+ else
+ {
+ m_mb_ram->pointer()[offset] = data;
+ }
+}
+
+uint8_t bbc_stl2m128_device::paged_r(offs_t offset)
+{
+ uint8_t data = 0xff;
+
+ switch (m_romsel)
+ {
+ case 0: case 1: case 2: case 3:
+ /* motherboard rom sockets */
+ if (m_mb_rom[m_romsel] && m_mb_rom[m_romsel]->present())
+ {
+ data = m_mb_rom[m_romsel]->read(offset);
+ }
+ else
+ {
+ data = m_region_swr->base()[offset + (m_romsel << 14)];
+ }
+ break;
+ case 8: case 9: case 10: case 11:
+ /* expansion board rom sockets */
+ if (m_rom[m_romsel] && m_rom[m_romsel]->present())
+ {
+ data = m_rom[m_romsel]->read(offset);
+ }
+ else
+ {
+ data = m_region_swr->base()[offset + (m_romsel << 14)];
+ }
+ break;
+ case 4: case 5: case 6: case 7: case 12: case 13: case 14: case 15:
+ /* expansion board ram sockets */
+ data = m_ram[offset | ((m_romsel & 0x03) << 14) | ((m_romsel & 0x08) << 13)];
+ break;
+ }
+
+
+ return data;
+}
+
+void bbc_stl2m128_device::paged_w(offs_t offset, uint8_t data)
+{
+ switch (m_romsel)
+ {
+ case 0: case 1: case 2: case 3:
+ /* motherboard rom sockets */
+ if (m_mb_rom[m_romsel])
+ {
+ m_mb_rom[m_romsel]->write(offset, data);
+ }
+ break;
+ case 8: case 9: case 10: case 11:
+ /* expansion board rom sockets */
+ if (m_rom[m_romsel])
+ {
+ m_rom[m_romsel]->write(offset, data);
+ }
+ break;
+ case 4: case 5: case 6: case 7: case 12: case 13: case 14: case 15:
+ /* expansion board ram sockets */
+ if (!m_wp->read())
+ {
+ m_ram[offset | ((m_romsel & 0x03) << 14) | ((m_romsel & 0x08) << 13)] = data;
+ }
+ break;
+ }
+}
diff --git a/src/devices/bus/bbc/internal/stl2m128.h b/src/devices/bus/bbc/internal/stl2m128.h
new file mode 100644
index 00000000000..48934a83c88
--- /dev/null
+++ b/src/devices/bus/bbc/internal/stl2m128.h
@@ -0,0 +1,59 @@
+// license:BSD-3-Clause
+// copyright-holders:Nigel Barnes
+/**********************************************************************
+
+ Solidisk Twomeg 128K Shadow and Sideways ROM/RAM board
+
+**********************************************************************/
+
+
+#ifndef MAME_BUS_BBC_INTERNAL_STL2M128_H
+#define MAME_BUS_BBC_INTERNAL_STL2M128_H
+
+#include "internal.h"
+
+
+//**************************************************************************
+// TYPE DEFINITIONS
+//**************************************************************************
+
+class bbc_stl2m128_device :
+ public device_t,
+ public device_bbc_internal_interface
+{
+public:
+ // construction/destruction
+ bbc_stl2m128_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
+
+protected:
+ // device-level overrides
+ virtual void device_start() override ATTR_COLD;
+
+ // optional information overrides
+ virtual void device_add_mconfig(machine_config &config) override ATTR_COLD;
+ virtual ioport_constructor device_input_ports() const override ATTR_COLD;
+ virtual const tiny_rom_entry *device_rom_region() const override ATTR_COLD;
+
+ virtual bool overrides_rom() override { return true; }
+ virtual bool overrides_ram() override { return true; }
+ virtual uint8_t ram_r(offs_t offset) override;
+ virtual void ram_w(offs_t offset, uint8_t data) override;
+ virtual void romsel_w(offs_t offset, uint8_t data) override;
+ virtual uint8_t paged_r(offs_t offset) override;
+ virtual void paged_w(offs_t offset, uint8_t data) override;
+
+ optional_device_array<bbc_romslot_device, 16> m_rom;
+ required_ioport m_wp;
+
+ std::unique_ptr<uint8_t[]> m_ram;
+
+ uint8_t m_romsel;
+ uint8_t m_shadow;
+};
+
+
+// device type definition
+DECLARE_DEVICE_TYPE(BBC_STL2M128, bbc_stl2m128_device);
+
+
+#endif /* MAME_BUS_BBC_INTERNAL_STL2M128_H */
diff --git a/src/devices/bus/bbc/internal/stl4m32.cpp b/src/devices/bus/bbc/internal/stl4m32.cpp
new file mode 100644
index 00000000000..c6d8903a91a
--- /dev/null
+++ b/src/devices/bus/bbc/internal/stl4m32.cpp
@@ -0,0 +1,303 @@
+// license:BSD-3-Clause
+// copyright-holders:Nigel Barnes
+/**********************************************************************
+
+ Solidisk Fourmeg RAM/ROM Expansions
+
+ http://chrisacorns.computinghistory.org.uk/8bit_Upgrades/Solidisk_4Meg.html
+
+**********************************************************************/
+
+
+#include "emu.h"
+#include "stl4m32.h"
+
+
+//**************************************************************************
+// DEVICE DEFINITIONS
+//**************************************************************************
+
+DEFINE_DEVICE_TYPE(BBC_STL4M32, bbc_stl4m32_device, "bbc_stl4m32", "Solidisk Fourmeg 32K RAM/ROM Expansion");
+
+
+//-------------------------------------------------
+// INPUT_PORTS( stl4m )
+//-------------------------------------------------
+
+INPUT_PORTS_START(stl4m32)
+ PORT_START("stl4m_clock")
+ PORT_CONFNAME(0x01, 0x01, "4MHz Clock") PORT_CHANGED_MEMBER(DEVICE_SELF, FUNC(bbc_stl4m32_device::clock_switch), 0)
+ PORT_CONFSETTING(0x00, "2MHz")
+ PORT_CONFSETTING(0x01, "4MHz")
+INPUT_PORTS_END
+
+
+//-------------------------------------------------
+// input_ports - device-specific input ports
+//-------------------------------------------------
+
+ioport_constructor bbc_stl4m32_device::device_input_ports() const
+{
+ return INPUT_PORTS_NAME(stl4m32);
+}
+
+
+//-------------------------------------------------
+// ROM( stl4m32 )
+//-------------------------------------------------
+
+ROM_START(stl4m32)
+ ROM_REGION(0x4000, "rom", 0)
+ ROM_SYSTEM_BIOS(0, "30", "Manager 3.00 (16.6.86)")
+ ROMX_LOAD("manager_4meg32k-16.6.86.rom", 0x0000, 0x4000, CRC(2024cd0d) SHA1(cf45217ac88480a6963cbf75e8cf684cd81c7b09), ROM_BIOS(0))
+ROM_END
+
+
+//-------------------------------------------------
+// device_add_mconfig - add device configuration
+//-------------------------------------------------
+
+void bbc_stl4m32_device::device_add_mconfig(machine_config &config)
+{
+ //G65SC02(config.replace(), m_maincpu, DERIVED_CLOCK(1, 4));
+
+ /* 5 x 32K rom sockets */
+ BBC_ROMSLOT32(config, m_rom[4], bbc_rom_devices, nullptr);
+ BBC_ROMSLOT32(config, m_rom[6], bbc_rom_devices, nullptr);
+ BBC_ROMSLOT32(config, m_rom[8], bbc_rom_devices, nullptr);
+ BBC_ROMSLOT32(config, m_rom[10], bbc_rom_devices, nullptr);
+ BBC_ROMSLOT32(config, m_rom[12], bbc_rom_devices, nullptr);
+ BBC_ROMSLOT16(config, m_rom[14], bbc_rom_devices, "ram").set_fixed_ram(true);
+ BBC_ROMSLOT16(config, m_rom[15], bbc_rom_devices, "ram").set_fixed_ram(true);
+}
+
+
+const tiny_rom_entry *bbc_stl4m32_device::device_rom_region() const
+{
+ return ROM_NAME(stl4m32);
+}
+
+
+//**************************************************************************
+// LIVE DEVICE
+//**************************************************************************
+
+//-------------------------------------------------
+// bbc_stl4m32_device - constructor
+//-------------------------------------------------
+
+bbc_stl4m32_device::bbc_stl4m32_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
+ : device_t(mconfig, BBC_STL4M32, tag, owner, clock)
+ , device_bbc_internal_interface(mconfig, *this)
+ , m_rom(*this, "romslot%u", 0U)
+{
+}
+
+
+//-------------------------------------------------
+// device_start - device-specific startup
+//-------------------------------------------------
+
+void bbc_stl4m32_device::device_start()
+{
+ m_ram = std::make_unique<uint8_t[]>(0x8000);
+
+ /* move internal roms to board */
+ memmove(m_region_swr->base() + 0x30000, m_region_swr->base() + 0xc000, 0x4000);
+ memcpy(m_region_swr->base() + 0x28000, memregion("rom")->base(), 0x4000);
+ memset(m_region_swr->base() + 0x0c000, 0xff, 0x4000);
+
+ /* register for save states */
+ save_pointer(NAME(m_ram), 0x8000);
+ save_item(NAME(m_romsel));
+ save_item(NAME(m_ramsel));
+ save_item(NAME(m_shadow));
+}
+
+
+//-------------------------------------------------
+// device_reset_after_children - reset after child devices
+//-------------------------------------------------
+
+void bbc_stl4m32_device::device_reset() //_after_children()
+{
+ /* set cpu clock to 4mhz */
+ //m_maincpu->set_clock(DERIVED_CLOCK(1, 4));
+}
+
+
+//**************************************************************************
+// IMPLEMENTATION
+//**************************************************************************
+
+INPUT_CHANGED_MEMBER(bbc_stl4m32_device::clock_switch)
+{
+ switch (newval)
+ {
+ case 0:
+ //m_maincpu->set_clock(DERIVED_CLOCK(1, 8));
+ break;
+ case 1:
+ //m_maincpu->set_clock(DERIVED_CLOCK(1, 4));
+ break;
+ }
+}
+
+void bbc_stl4m32_device::romsel_w(offs_t offset, uint8_t data)
+{
+ logerror("romsel_w: %04x = %02x\n", offset | 0xfe30, data);
+
+ switch (offset & 0x0e)
+ {
+ case 0x00:
+ m_romsel = data & 0x0f;
+ break;
+ case 0x02:
+ m_ramsel = data;
+ break;
+ case 0x04:
+ m_shadow = data;
+ break;
+ }
+}
+
+uint8_t bbc_stl4m32_device::ram_r(offs_t offset)
+{
+ uint8_t data = 0xff;
+
+ if (BIT(m_shadow, 7) && offset >= 0x2000)
+ {
+ data = m_ram[offset];
+ }
+ else
+ {
+ data = m_mb_ram->pointer()[offset];
+ }
+
+ return data;
+}
+
+void bbc_stl4m32_device::ram_w(offs_t offset, uint8_t data)
+{
+ if ((offset & 0xff) == 0x00)
+ logerror("ram_w: %04x = %02x\n", offset, data);
+
+ if (BIT(m_romsel, 7) && offset >= 0x2000)
+ {
+ m_ram[offset] = data;
+ }
+ else
+ {
+ m_mb_ram->pointer()[offset] = data;
+ }
+}
+
+
+uint8_t bbc_stl4m32_device::paged_r(offs_t offset)
+{
+ uint8_t data = 0xff;
+
+ if (BIT(m_romsel, 7) && offset < 0x2000)
+ {
+ data = m_ram[offset];
+ }
+ else
+ {
+ switch (m_romsel)
+ {
+ case 0: case 1: case 2: case 3:
+ /* motherboard rom sockets */
+ if (m_mb_rom[m_romsel] && m_mb_rom[m_romsel]->present())
+ {
+ data = m_mb_rom[m_romsel]->read(offset);
+ }
+ else
+ {
+ data = m_region_swr->base()[offset + (m_romsel << 14)];
+ }
+ break;
+ case 4: case 5: case 6: case 7: case 8: case 9: case 10: case 11: case 12: case 13:
+ /* expansion board rom sockets */
+ if (m_rom[m_romsel & 0x0e] && m_rom[m_romsel & 0x0e]->present())
+ {
+ data = m_rom[m_romsel & 0x0e]->read(offset | (m_romsel & 0x01) << 14);
+ }
+ else
+ {
+ data = m_region_swr->base()[offset + (m_romsel << 14)];
+ }
+ break;
+ case 14: case 15:
+ /* expansion board ram sockets */
+ data = m_ram[offset | ((m_romsel & 0x01) << 14)];
+ break;
+ }
+ }
+
+ return data;
+}
+
+void bbc_stl4m32_device::paged_w(offs_t offset, uint8_t data)
+{
+ if ((offset & 0xff) == 0x00)
+ logerror("paged_w: %04x = %02x\n", offset | 0x8000, data);
+
+ if (BIT(m_romsel, 7) && offset < 0x2000)
+ {
+ m_ram[offset] = data;
+ }
+ else
+ {
+ switch (m_romsel)
+ {
+ case 0: case 1: case 2: case 3:
+ /* motherboard rom sockets */
+ if (m_mb_rom[m_romsel])
+ {
+ m_mb_rom[m_romsel]->write(offset, data);
+ }
+ break;
+ case 4: case 5: case 6: case 7: case 8: case 9: case 10: case 11: case 12: case 13:
+ /* expansion board rom sockets */
+ if (m_rom[m_romsel & 0x0e])
+ {
+ m_rom[m_romsel & 0x0e]->write(offset | (m_romsel & 0x01) << 14, data);
+ }
+ break;
+ }
+
+ if (m_ramsel == 14 || m_ramsel == 15)
+ {
+ /* expansion board ram sockets */
+ m_ram[offset | ((m_ramsel & 0x01) << 14)] = data;
+ }
+ }
+}
+
+
+uint8_t bbc_stl4m32_device::mos_r(offs_t offset)
+{
+ uint8_t data = 0xff;
+
+ //if (BIT(m_shadow, 7) && offset >= 0x2000)
+ //{
+ // data = m_ram[offset];
+ //}
+ //else
+ //{
+ data = m_region_mos->base()[offset];
+ //}
+
+ return data;
+}
+
+void bbc_stl4m32_device::mos_w(offs_t offset, uint8_t data)
+{
+ if ((offset & 0xff) == 0x00)
+ logerror("mos_w: %04x = %02x\n", offset | 0xc000, data);
+
+ //if (BIT(m_romsel, 7) && offset >= 0x2000)
+ //{
+ // m_ram[offset] = data;
+ //}
+}
diff --git a/src/devices/bus/bbc/internal/stl4m32.h b/src/devices/bus/bbc/internal/stl4m32.h
new file mode 100644
index 00000000000..e919dbf35f3
--- /dev/null
+++ b/src/devices/bus/bbc/internal/stl4m32.h
@@ -0,0 +1,67 @@
+// license:BSD-3-Clause
+// copyright-holders:Nigel Barnes
+/**********************************************************************
+
+ Solidisk Fourmeg RAM/ROM Expansions
+
+ http://chrisacorns.computinghistory.org.uk/8bit_Upgrades/Solidisk_4Meg.html
+
+**********************************************************************/
+
+
+#ifndef MAME_BUS_BBC_INTERNAL_STL4M32_H
+#define MAME_BUS_BBC_INTERNAL_STL4M32_H
+
+#include "internal.h"
+
+
+//**************************************************************************
+// TYPE DEFINITIONS
+//**************************************************************************
+
+class bbc_stl4m32_device :
+ public device_t,
+ public device_bbc_internal_interface
+{
+public:
+ // construction/destruction
+ bbc_stl4m32_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
+
+ DECLARE_INPUT_CHANGED_MEMBER(clock_switch);
+
+protected:
+ // device-level overrides
+ virtual void device_start() override ATTR_COLD;
+ virtual void device_reset() override ATTR_COLD;
+
+ // optional information overrides
+ virtual void device_add_mconfig(machine_config &config) override ATTR_COLD;
+ virtual ioport_constructor device_input_ports() const override ATTR_COLD;
+ virtual const tiny_rom_entry *device_rom_region() const override ATTR_COLD;
+
+ virtual bool overrides_rom() override { return true; }
+ virtual bool overrides_ram() override { return true; }
+ virtual bool overrides_mos() override { return true; }
+ virtual uint8_t ram_r(offs_t offset) override;
+ virtual void ram_w(offs_t offset, uint8_t data) override;
+ virtual void romsel_w(offs_t offset, uint8_t data) override;
+ virtual uint8_t paged_r(offs_t offset) override;
+ virtual void paged_w(offs_t offset, uint8_t data) override;
+ virtual uint8_t mos_r(offs_t offset) override;
+ virtual void mos_w(offs_t offset, uint8_t data) override;
+
+ optional_device_array<bbc_romslot_device, 16> m_rom;
+
+ std::unique_ptr<uint8_t[]> m_ram;
+
+ uint8_t m_romsel;
+ uint8_t m_ramsel;
+ uint8_t m_shadow;
+};
+
+
+// device type definition
+DECLARE_DEVICE_TYPE(BBC_STL4M32, bbc_stl4m32_device);
+
+
+#endif /* MAME_BUS_BBC_INTERNAL_STL4M32_H */
diff --git a/src/devices/bus/bbc/internal/stlswr.cpp b/src/devices/bus/bbc/internal/stlswr.cpp
new file mode 100644
index 00000000000..f4992197453
--- /dev/null
+++ b/src/devices/bus/bbc/internal/stlswr.cpp
@@ -0,0 +1,192 @@
+// license:BSD-3-Clause
+// copyright-holders:Nigel Barnes
+/**********************************************************************
+
+ Solidisk Sideways RAM
+
+ http://chrisacorns.computinghistory.org.uk/8bit_Upgrades/Solidisk_128KSWE.html
+
+**********************************************************************/
+
+
+#include "emu.h"
+#include "stlswr.h"
+
+
+//**************************************************************************
+// DEVICE DEFINITIONS
+//**************************************************************************
+
+DEFINE_DEVICE_TYPE(BBC_STLSWR16, bbc_stlswr16_device, "bbc_stlswr16", "Solidisk SWR16 - 16K Sideways RAM");
+DEFINE_DEVICE_TYPE(BBC_STLSWR32, bbc_stlswr32_device, "bbc_stlswr32", "Solidisk SWR32 - 32K Sideways RAM");
+DEFINE_DEVICE_TYPE(BBC_STLSWR64, bbc_stlswr64_device, "bbc_stlswr64", "Solidisk SWR64 - 64K Sideways RAM");
+DEFINE_DEVICE_TYPE(BBC_STLSWR128, bbc_stlswr128_device, "bbc_stlswr128", "Solidisk SWR128 - 128K Sideways RAM");
+
+
+//-------------------------------------------------
+// ROM( stlswr )
+//-------------------------------------------------
+
+ROM_START(stlswr)
+ ROM_REGION(0x4000, "exp_rom", 0)
+ ROM_SYSTEM_BIOS(0, "13", "Toolkit 1.3 03/03/86")
+ ROMX_LOAD("toolkit-1.3-16k-128k-03-03-86.rom", 0x0000, 0x4000, CRC(a1745d10) SHA1(1821e74feca60b95766ead06df20f6db22e2b4bb), ROM_BIOS(0))
+ROM_END
+
+//-------------------------------------------------
+// device_add_mconfig - add device configuration
+//-------------------------------------------------
+
+void bbc_stlswr16_device::device_add_mconfig(machine_config &config)
+{
+ /* TODO: romslot3 is unavailable when board is fitted */
+ //config.device_remove(":romslot3");
+ BBC_ROMSLOT16(config, m_rom[15], bbc_rom_devices, "ram").set_fixed_ram(true);
+}
+
+void bbc_stlswr32_device::device_add_mconfig(machine_config &config)
+{
+ /* TODO: romslot3 is unavailable when board is fitted */
+ //config.device_remove(":romslot3");
+ BBC_ROMSLOT16(config, m_rom[14], bbc_rom_devices, "ram").set_fixed_ram(true);
+ BBC_ROMSLOT16(config, m_rom[15], bbc_rom_devices, "ram").set_fixed_ram(true);
+}
+
+void bbc_stlswr64_device::device_add_mconfig(machine_config &config)
+{
+ /* TODO: romslot3 is unavailable when board is fitted */
+ //config.device_remove(":romslot3");
+ BBC_ROMSLOT16(config, m_rom[12], bbc_rom_devices, "ram").set_fixed_ram(true);
+ BBC_ROMSLOT16(config, m_rom[13], bbc_rom_devices, "ram").set_fixed_ram(true);
+ BBC_ROMSLOT16(config, m_rom[14], bbc_rom_devices, "ram").set_fixed_ram(true);
+ BBC_ROMSLOT16(config, m_rom[15], bbc_rom_devices, "ram").set_fixed_ram(true);
+}
+
+void bbc_stlswr128_device::device_add_mconfig(machine_config &config)
+{
+ /* TODO: romslot3 is unavailable when board is fitted */
+ //config.device_remove(":romslot3");
+ BBC_ROMSLOT16(config, m_rom[8], bbc_rom_devices, "ram").set_fixed_ram(true);
+ BBC_ROMSLOT16(config, m_rom[9], bbc_rom_devices, "ram").set_fixed_ram(true);
+ BBC_ROMSLOT16(config, m_rom[10], bbc_rom_devices, "ram").set_fixed_ram(true);
+ BBC_ROMSLOT16(config, m_rom[11], bbc_rom_devices, "ram").set_fixed_ram(true);
+ BBC_ROMSLOT16(config, m_rom[12], bbc_rom_devices, "ram").set_fixed_ram(true);
+ BBC_ROMSLOT16(config, m_rom[13], bbc_rom_devices, "ram").set_fixed_ram(true);
+ BBC_ROMSLOT16(config, m_rom[14], bbc_rom_devices, "ram").set_fixed_ram(true);
+ BBC_ROMSLOT16(config, m_rom[15], bbc_rom_devices, "ram").set_fixed_ram(true);
+}
+
+//-------------------------------------------------
+// rom_region - device-specific ROM region
+//-------------------------------------------------
+
+const tiny_rom_entry *bbc_stlswr_device::device_rom_region() const
+{
+ return ROM_NAME(stlswr);
+}
+
+
+//**************************************************************************
+// LIVE DEVICE
+//**************************************************************************
+
+//-------------------------------------------------
+// bbc_stlswr_device - constructor
+//-------------------------------------------------
+
+bbc_stlswr_device::bbc_stlswr_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_internal_interface(mconfig, *this)
+ , m_rom(*this, "romslot%u", 0U)
+{
+}
+
+bbc_stlswr16_device::bbc_stlswr16_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
+ : bbc_stlswr_device(mconfig, BBC_STLSWR16, tag, owner, clock)
+{
+}
+
+bbc_stlswr32_device::bbc_stlswr32_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
+ : bbc_stlswr_device(mconfig, BBC_STLSWR32, tag, owner, clock)
+{
+}
+
+bbc_stlswr64_device::bbc_stlswr64_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
+ : bbc_stlswr_device(mconfig, BBC_STLSWR64, tag, owner, clock)
+{
+}
+
+bbc_stlswr128_device::bbc_stlswr128_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
+ : bbc_stlswr_device(mconfig, BBC_STLSWR128, tag, owner, clock)
+{
+}
+
+
+//-------------------------------------------------
+// device_start - device-specific startup
+//-------------------------------------------------
+
+void bbc_stlswr_device::device_start()
+{
+ /* register for save states */
+ save_item(NAME(m_romsel));
+ save_item(NAME(m_ramsel));
+}
+
+
+//**************************************************************************
+// IMPLEMENTATION
+//**************************************************************************
+
+uint8_t bbc_stlswr_device::paged_r(offs_t offset)
+{
+ uint8_t data = 0xff;
+
+ switch (m_romsel)
+ {
+ case 0: case 1: case 2: case 3:
+ /* motherboard rom sockets */
+ if (m_mb_rom[m_romsel] && m_mb_rom[m_romsel]->present())
+ {
+ data = m_mb_rom[m_romsel]->read(offset);
+ }
+ else
+ {
+ data = m_region_swr->base()[offset + (m_romsel << 14)];
+ }
+ break;
+ default:
+ /* expansion board sockets */
+ if (m_rom[m_romsel] && m_rom[m_romsel]->present())
+ {
+ data = m_rom[m_romsel]->read(offset);
+ }
+ else
+ {
+ data = m_region_swr->base()[offset + (m_romsel << 14)];
+ }
+ break;
+ }
+
+ return data;
+}
+
+void bbc_stlswr_device::paged_w(offs_t offset, uint8_t data)
+{
+ switch (m_romsel)
+ {
+ case 0: case 1: case 2: case 3:
+ /* motherboard rom sockets */
+ if (m_mb_rom[m_romsel])
+ {
+ m_mb_rom[m_romsel]->write(offset, data);
+ }
+ break;
+ }
+
+ /* expansion board sockets */
+ if (m_rom[m_ramsel])
+ {
+ m_rom[m_ramsel]->write(offset, data);
+ }
+}
diff --git a/src/devices/bus/bbc/internal/stlswr.h b/src/devices/bus/bbc/internal/stlswr.h
new file mode 100644
index 00000000000..d69b4f04f93
--- /dev/null
+++ b/src/devices/bus/bbc/internal/stlswr.h
@@ -0,0 +1,108 @@
+// license:BSD-3-Clause
+// copyright-holders:Nigel Barnes
+/**********************************************************************
+
+ Solidisk Sideways RAM
+
+ http://chrisacorns.computinghistory.org.uk/8bit_Upgrades/Solidisk_128KSWE.html
+
+**********************************************************************/
+
+
+#ifndef MAME_BUS_BBC_INTERNAL_STLSWR_H
+#define MAME_BUS_BBC_INTERNAL_STLSWR_H
+
+#include "internal.h"
+
+
+//**************************************************************************
+// TYPE DEFINITIONS
+//**************************************************************************
+
+class bbc_stlswr_device :
+ public device_t,
+ public device_bbc_internal_interface
+{
+public:
+ // construction/destruction
+ bbc_stlswr_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
+
+protected:
+ bbc_stlswr_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 ATTR_COLD;
+
+ // optional information overrides
+ virtual const tiny_rom_entry *device_rom_region() const override ATTR_COLD;
+
+ virtual bool overrides_rom() override { return true; }
+ virtual void romsel_w(offs_t offset, uint8_t data) override { m_romsel = data & 0x0f; }
+ virtual uint8_t paged_r(offs_t offset) override;
+ virtual void paged_w(offs_t offset, uint8_t data) override;
+ virtual void latch_fe60_w(uint8_t data) override { m_ramsel = (data & 0x07) | 0x08; }
+
+ optional_device_array<bbc_romslot_device, 16> m_rom;
+
+ uint8_t m_romsel;
+ uint8_t m_ramsel;
+};
+
+
+class bbc_stlswr16_device : public bbc_stlswr_device
+{
+public:
+ // construction/destruction
+ bbc_stlswr16_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 ATTR_COLD;
+};
+
+
+class bbc_stlswr32_device : public bbc_stlswr_device
+{
+public:
+ // construction/destruction
+ bbc_stlswr32_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 ATTR_COLD;
+};
+
+
+class bbc_stlswr64_device : public bbc_stlswr_device
+{
+public:
+ // construction/destruction
+ bbc_stlswr64_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 ATTR_COLD;
+};
+
+
+class bbc_stlswr128_device : public bbc_stlswr_device
+{
+public:
+ // construction/destruction
+ bbc_stlswr128_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 ATTR_COLD;
+};
+
+
+// device type definition
+DECLARE_DEVICE_TYPE(BBC_STLSWR16, bbc_stlswr16_device);
+DECLARE_DEVICE_TYPE(BBC_STLSWR32, bbc_stlswr32_device);
+DECLARE_DEVICE_TYPE(BBC_STLSWR64, bbc_stlswr64_device);
+DECLARE_DEVICE_TYPE(BBC_STLSWR128, bbc_stlswr128_device);
+
+
+
+#endif /* MAME_BUS_BBC_INTERNAL_STLSWR_H */
diff --git a/src/devices/bus/bbc/internal/we32kram.cpp b/src/devices/bus/bbc/internal/we32kram.cpp
new file mode 100644
index 00000000000..4e0e084e655
--- /dev/null
+++ b/src/devices/bus/bbc/internal/we32kram.cpp
@@ -0,0 +1,146 @@
+// license:BSD-3-Clause
+// copyright-holders:Nigel Barnes
+/**********************************************************************
+
+ Watford Electronics 32K RAM card
+
+ http://chrisacorns.computinghistory.org.uk/8bit_Upgrades/WE_32KRAMcard.html
+
+**********************************************************************/
+
+
+#include "emu.h"
+#include "we32kram.h"
+
+
+//**************************************************************************
+// DEVICE DEFINITIONS
+//**************************************************************************
+
+DEFINE_DEVICE_TYPE(BBC_WE32KRAM, bbc_we32kram_device, "bbc_we32kram", "Watford Electronics 32K Shadow RAM");
+
+
+//-------------------------------------------------
+// ROM( we32kram )
+//-------------------------------------------------
+
+ROM_START(we32kram)
+ ROM_REGION(0x4000, "exp_rom", 0)
+ ROM_SYSTEM_BIOS(0, "240", "v2.40")
+ ROMX_LOAD("we32kram_v2.40.rom", 0x0000, 0x2000, CRC(db9c3a1a) SHA1(0a5efb084eb1ae353b9c79c026e9e26cd7695293), ROM_BIOS(0))
+ ROM_SYSTEM_BIOS(1, "220", "v2.20")
+ ROMX_LOAD("we32kram_v2.20.rom", 0x0000, 0x2000, CRC(bc7124e0) SHA1(7f8536576de449916cd77488e94775ed438c5c6c), ROM_BIOS(1))
+ ROM_SYSTEM_BIOS(2, "200", "v2.00")
+ ROMX_LOAD("we32kram_v2.00.rom", 0x0000, 0x2000, CRC(1eff9b23) SHA1(98a3084b20c92427c2e9def58ade96f42659e20a), ROM_BIOS(2))
+ ROM_SYSTEM_BIOS(3, "106", "v1.06")
+ ROMX_LOAD("we32kram_v1.06.rom", 0x0000, 0x2000, CRC(b9749390) SHA1(210f6162d634fca8d75197d4f64d9b50abc01e1e), ROM_BIOS(3))
+ ROM_SYSTEM_BIOS(4, "100", "v1.00")
+ ROMX_LOAD("we32kram_v1.00.rom", 0x0000, 0x2000, CRC(7962b5db) SHA1(1b59a3354cfc704ad8aa60b0ed16e4cd2d815031), ROM_BIOS(4))
+ROM_END
+
+//-------------------------------------------------
+// rom_region - device-specific ROM region
+//-------------------------------------------------
+
+const tiny_rom_entry *bbc_we32kram_device::device_rom_region() const
+{
+ return ROM_NAME(we32kram);
+}
+
+
+//**************************************************************************
+// LIVE DEVICE
+//**************************************************************************
+
+//-------------------------------------------------
+// bbc_we32kram_device - constructor
+//-------------------------------------------------
+
+bbc_we32kram_device::bbc_we32kram_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
+ : device_t(mconfig, BBC_WE32KRAM, tag, owner, clock)
+ , device_bbc_internal_interface(mconfig, *this)
+{
+}
+
+
+//-------------------------------------------------
+// device_start - device-specific startup
+//-------------------------------------------------
+
+void bbc_we32kram_device::device_start()
+{
+ m_shadow = 2;
+ m_ram = std::make_unique<uint8_t[]>(0x8000);
+
+ /* register for save states */
+ save_item(NAME(m_shadow));
+ save_pointer(NAME(m_ram), 0x8000);
+}
+
+//-------------------------------------------------
+// device_reset - device-specific reset
+//-------------------------------------------------
+
+void bbc_we32kram_device::device_reset()
+{
+ address_space &program = m_maincpu->space(AS_PROGRAM);
+
+ program.install_write_handler(0xfffc, 0xffff, write8sm_delegate(*this, FUNC(bbc_we32kram_device::control_w)));
+}
+
+//**************************************************************************
+// IMPLEMENTATION
+//**************************************************************************
+
+void bbc_we32kram_device::control_w(offs_t offset, uint8_t data)
+{
+ m_shadow = offset;
+}
+
+uint8_t bbc_we32kram_device::ram_r(offs_t offset)
+{
+ uint8_t data = 0xff;
+
+ switch (m_shadow)
+ {
+ case 0:
+ /* &fffc - swap whole memory */
+ data = m_ram[offset];
+ break;
+ case 2:
+ /* &fffe - select BBC ram */
+ data = m_mb_ram->pointer()[offset];
+ break;
+ case 3:
+ /* &ffff - select Watford ram */
+ if (offset >= 0x3000)
+ data = m_ram[offset];
+ else
+ data = m_mb_ram->pointer()[offset];
+ break;
+ }
+
+ return data;
+}
+
+void bbc_we32kram_device::ram_w(offs_t offset, uint8_t data)
+{
+ switch (m_shadow)
+ {
+ case 0:
+ /* &fffc - swap whole memory */
+ m_ram[offset] = data;
+ break;
+ case 2:
+ /* &fffe - select BBC ram */
+ m_mb_ram->pointer()[offset] = data;
+ break;
+ case 3:
+ /* &ffff - select Watford ram */
+ if (offset >= 0x3000)
+ m_ram[offset] = data;
+ else
+ m_mb_ram->pointer()[offset] = data;
+ break;
+ }
+}
diff --git a/src/devices/bus/bbc/internal/we32kram.h b/src/devices/bus/bbc/internal/we32kram.h
new file mode 100644
index 00000000000..8dc28f1f37e
--- /dev/null
+++ b/src/devices/bus/bbc/internal/we32kram.h
@@ -0,0 +1,55 @@
+// license:BSD-3-Clause
+// copyright-holders:Nigel Barnes
+/**********************************************************************
+
+ Watford Electronics 32K RAM card
+
+ http://chrisacorns.computinghistory.org.uk/8bit_Upgrades/WE_32KRAMcard.html
+
+**********************************************************************/
+
+
+#ifndef MAME_BUS_BBC_INTERNAL_WE32KRAM_H
+#define MAME_BUS_BBC_INTERNAL_WE32KRAM_H
+
+#include "internal.h"
+
+
+//**************************************************************************
+// TYPE DEFINITIONS
+//**************************************************************************
+
+class bbc_we32kram_device :
+ public device_t,
+ public device_bbc_internal_interface
+{
+public:
+ // construction/destruction
+ bbc_we32kram_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
+
+protected:
+ // device-level overrides
+ virtual void device_start() override ATTR_COLD;
+ virtual void device_reset() override ATTR_COLD;
+
+ // optional information overrides
+ virtual const tiny_rom_entry *device_rom_region() const override ATTR_COLD;
+
+ virtual bool overrides_ram() override { return true; }
+ virtual uint8_t ram_r(offs_t offset) override;
+ virtual void ram_w(offs_t offset, uint8_t data) override;
+
+private:
+ void control_w(offs_t offset, uint8_t data);
+
+ uint8_t m_shadow;
+ std::unique_ptr<uint8_t[]> m_ram;
+};
+
+
+// device type definition
+DECLARE_DEVICE_TYPE(BBC_WE32KRAM, bbc_we32kram_device);
+
+
+
+#endif /* MAME_BUS_BBC_INTERNAL_WE32KRAM_H */
diff --git a/src/devices/bus/bbc/internal/werom.cpp b/src/devices/bus/bbc/internal/werom.cpp
new file mode 100644
index 00000000000..bc38500dee8
--- /dev/null
+++ b/src/devices/bus/bbc/internal/werom.cpp
@@ -0,0 +1,260 @@
+// license:BSD-3-Clause
+// copyright-holders:Nigel Barnes
+/**********************************************************************
+
+ Watford Electronics 12 ROM Board
+ http://chrisacorns.computinghistory.org.uk/8bit_Upgrades/WE_12ROMboard.html
+
+ Watford Electronics 13 ROM Board
+ http://chrisacorns.computinghistory.org.uk/8bit_Upgrades/WE_13ROMBoard.html
+
+**********************************************************************/
+
+
+#include "emu.h"
+#include "werom.h"
+
+
+//**************************************************************************
+// DEVICE DEFINITIONS
+//**************************************************************************
+
+DEFINE_DEVICE_TYPE(BBC_WE12ROM, bbc_we12rom_device, "bbc_we12rom", "Watford Electronics 12 ROM Board");
+DEFINE_DEVICE_TYPE(BBC_WE13ROM, bbc_we13rom_device, "bbc_we13rom", "Watford Electronics 13 ROM Board");
+
+
+//-------------------------------------------------
+// INPUT_PORTS( werom )
+//-------------------------------------------------
+
+static INPUT_PORTS_START(werom)
+ PORT_START("wp")
+ PORT_CONFNAME(0x01, 0x00, "Write Protect Sideways RAM")
+ PORT_CONFSETTING(0x00, DEF_STR(No))
+ PORT_CONFSETTING(0x01, DEF_STR(Yes))
+INPUT_PORTS_END
+
+//-------------------------------------------------
+// input_ports - device-specific input ports
+//-------------------------------------------------
+
+ioport_constructor bbc_we12rom_device::device_input_ports() const
+{
+ return INPUT_PORTS_NAME(werom);
+}
+
+//-------------------------------------------------
+// device_add_mconfig - add device configuration
+//-------------------------------------------------
+
+void bbc_we12rom_device::device_add_mconfig(machine_config &config)
+{
+ /* 12 rom sockets, 16K static ram (battery backed) */
+ BBC_ROMSLOT16(config, m_rom[4], bbc_rom_devices, nullptr);
+ BBC_ROMSLOT16(config, m_rom[5], bbc_rom_devices, nullptr);
+ BBC_ROMSLOT16(config, m_rom[6], bbc_rom_devices, nullptr);
+ BBC_ROMSLOT16(config, m_rom[7], bbc_rom_devices, nullptr);
+ BBC_ROMSLOT16(config, m_rom[8], bbc_rom_devices, nullptr);
+ BBC_ROMSLOT16(config, m_rom[9], bbc_rom_devices, nullptr);
+ BBC_ROMSLOT16(config, m_rom[10], bbc_rom_devices, nullptr);
+ BBC_ROMSLOT16(config, m_rom[11], bbc_rom_devices, nullptr);
+ BBC_ROMSLOT16(config, m_rom[12], bbc_rom_devices, nullptr);
+ BBC_ROMSLOT16(config, m_rom[13], bbc_rom_devices, nullptr);
+ BBC_ROMSLOT16(config, m_rom[14], bbc_rom_devices, "nvram").set_fixed_ram(true);
+ BBC_ROMSLOT16(config, m_rom[15], bbc_rom_devices, nullptr);
+}
+
+void bbc_we13rom_device::device_add_mconfig(machine_config &config)
+{
+ /* TODO: romslot2 is unavailable when board is fitted, replaced by socket on board */
+ //config.device_remove(":romslot2");
+
+ /* 13 rom sockets, 16K static ram (battery backed) */
+ BBC_ROMSLOT16(config, m_rom[2], bbc_rom_devices, nullptr);
+ BBC_ROMSLOT16(config, m_rom[4], bbc_rom_devices, nullptr);
+ BBC_ROMSLOT16(config, m_rom[5], bbc_rom_devices, nullptr);
+ BBC_ROMSLOT16(config, m_rom[6], bbc_rom_devices, nullptr);
+ BBC_ROMSLOT16(config, m_rom[7], bbc_rom_devices, nullptr);
+ BBC_ROMSLOT16(config, m_rom[8], bbc_rom_devices, nullptr);
+ BBC_ROMSLOT16(config, m_rom[9], bbc_rom_devices, nullptr);
+ BBC_ROMSLOT16(config, m_rom[10], bbc_rom_devices, nullptr);
+ BBC_ROMSLOT16(config, m_rom[11], bbc_rom_devices, nullptr);
+ BBC_ROMSLOT16(config, m_rom[12], bbc_rom_devices, nullptr);
+ BBC_ROMSLOT16(config, m_rom[13], bbc_rom_devices, nullptr);
+ BBC_ROMSLOT16(config, m_rom[14], bbc_rom_devices, nullptr);
+ BBC_ROMSLOT16(config, m_rom[15], bbc_rom_devices, "nvram").set_fixed_ram(true);
+}
+
+
+//**************************************************************************
+// LIVE DEVICE
+//**************************************************************************
+
+//-------------------------------------------------
+// bbc_werom_device - constructor
+//-------------------------------------------------
+
+bbc_werom_device::bbc_werom_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_internal_interface(mconfig, *this)
+ , m_rom(*this, "romslot%u", 0U)
+{
+}
+
+bbc_we12rom_device::bbc_we12rom_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
+ : bbc_werom_device(mconfig, BBC_WE12ROM, tag, owner, clock)
+ , m_wp(*this, "wp")
+{
+}
+
+bbc_we13rom_device::bbc_we13rom_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
+ : bbc_werom_device(mconfig, BBC_WE13ROM, tag, owner, clock)
+{
+}
+
+
+//-------------------------------------------------
+// device_start - device-specific startup
+//-------------------------------------------------
+
+void bbc_we12rom_device::device_start()
+{
+ /* move internal roms to board */
+ memmove(m_region_swr->base() + 0x2c000, m_region_swr->base(), 0xc000);
+ memmove(m_region_swr->base() + 0x3c000, m_region_swr->base() + 0xc000, 0x4000);
+ memset(m_region_swr->base(), 0xff, 0x10000);
+
+ /* register for save states */
+ save_item(NAME(m_romsel));
+}
+
+void bbc_we13rom_device::device_start()
+{
+ /* move internal roms to board */
+ memmove(m_region_swr->base() + 0x2c000, m_region_swr->base(), 0x10000);
+ memset(m_region_swr->base(), 0xff, 0x10000);
+
+ /* register for save states */
+ save_item(NAME(m_romsel));
+}
+
+
+//**************************************************************************
+// IMPLEMENTATION
+//**************************************************************************
+
+uint8_t bbc_we12rom_device::paged_r(offs_t offset)
+{
+ uint8_t data = 0xff;
+
+ switch (m_romsel)
+ {
+ case 0: case 1: case 2: case 3:
+ /* motherboard rom sockets */
+ if (m_mb_rom[m_romsel] && m_mb_rom[m_romsel]->present())
+ {
+ data = m_mb_rom[m_romsel]->read(offset);
+ }
+ else
+ {
+ data = m_region_swr->base()[offset + (m_romsel << 14)];
+ }
+ break;
+ default:
+ /* expansion board sockets */
+ if (m_rom[m_romsel] && m_rom[m_romsel]->present())
+ {
+ data = m_rom[m_romsel]->read(offset);
+ }
+ else
+ {
+ data = m_region_swr->base()[offset + (m_romsel << 14)];
+ }
+ break;
+ }
+
+ return data;
+}
+
+void bbc_we12rom_device::paged_w(offs_t offset, uint8_t data)
+{
+ switch (m_romsel)
+ {
+ case 0: case 1: case 2: case 3:
+ /* motherboard rom sockets */
+ if (m_mb_rom[m_romsel])
+ {
+ m_mb_rom[m_romsel]->write(offset, data);
+ }
+ break;
+ default:
+ /* expansion board sockets */
+ if (m_rom[m_romsel])
+ {
+ m_rom[m_romsel]->write(offset, data);
+ }
+ /* sideways ram (if not write protected) */
+ if (!m_wp->read())
+ {
+ m_rom[14]->write(offset, data);
+ }
+ break;
+ }
+}
+
+
+uint8_t bbc_we13rom_device::paged_r(offs_t offset)
+{
+ uint8_t data = 0xff;
+
+ switch (m_romsel)
+ {
+ case 0: case 1: case 3:
+ /* motherboard rom sockets */
+ if (m_mb_rom[m_romsel] && m_mb_rom[m_romsel]->present())
+ {
+ data = m_mb_rom[m_romsel]->read(offset);
+ }
+ else
+ {
+ data = m_region_swr->base()[offset + (m_romsel << 14)];
+ }
+ break;
+ default:
+ /* expansion board sockets */
+ if (m_rom[m_romsel] && m_rom[m_romsel]->present())
+ {
+ data = m_rom[m_romsel]->read(offset);
+ }
+ else
+ {
+ data = m_region_swr->base()[offset + (m_romsel << 14)];
+ }
+ break;
+ }
+
+ return data;
+}
+
+void bbc_we13rom_device::paged_w(offs_t offset, uint8_t data)
+{
+ switch (m_romsel)
+ {
+ case 0: case 1: case 3:
+ /* motherboard rom sockets */
+ if (m_mb_rom[m_romsel])
+ {
+ m_mb_rom[m_romsel]->write(offset, data);
+ }
+ break;
+ default:
+ /* expansion board sockets */
+ if (m_rom[m_romsel])
+ {
+ m_rom[m_romsel]->write(offset, data);
+ }
+ /* sideways ram */
+ m_rom[15]->write(offset, data);
+ break;
+ }
+}
diff --git a/src/devices/bus/bbc/internal/werom.h b/src/devices/bus/bbc/internal/werom.h
new file mode 100644
index 00000000000..9ce9ac06a45
--- /dev/null
+++ b/src/devices/bus/bbc/internal/werom.h
@@ -0,0 +1,90 @@
+// license:BSD-3-Clause
+// copyright-holders:Nigel Barnes
+/**********************************************************************
+
+ Watford Electronics 12 ROM Board
+ http://chrisacorns.computinghistory.org.uk/8bit_Upgrades/WE_12ROMboard.html
+
+ Watford Electronics 13 ROM Board
+ http://chrisacorns.computinghistory.org.uk/8bit_Upgrades/WE_13ROMBoard.html
+
+**********************************************************************/
+
+
+#ifndef MAME_BUS_BBC_INTERNAL_WEROM_H
+#define MAME_BUS_BBC_INTERNAL_WEROM_H
+
+#include "internal.h"
+
+
+//**************************************************************************
+// TYPE DEFINITIONS
+//**************************************************************************
+
+class bbc_werom_device :
+ public device_t,
+ public device_bbc_internal_interface
+{
+public:
+ // construction/destruction
+ bbc_werom_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
+
+protected:
+ bbc_werom_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock);
+
+ optional_device_array<bbc_romslot_device, 16> m_rom;
+
+ virtual bool overrides_rom() override { return true; }
+ virtual void romsel_w(offs_t offset, uint8_t data) override { m_romsel = data & 0x0f; }
+
+ uint8_t m_romsel;
+};
+
+
+class bbc_we12rom_device : public bbc_werom_device
+{
+public:
+ // construction/destruction
+ bbc_we12rom_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
+
+protected:
+ // device-level overrides
+ virtual void device_start() override ATTR_COLD;
+
+ // optional information overrides
+ virtual void device_add_mconfig(machine_config &config) override ATTR_COLD;
+ virtual ioport_constructor device_input_ports() const override ATTR_COLD;
+
+ virtual uint8_t paged_r(offs_t offset) override;
+ virtual void paged_w(offs_t offset, uint8_t data) override;
+
+private:
+ required_ioport m_wp;
+};
+
+
+class bbc_we13rom_device : public bbc_werom_device
+{
+public:
+ // construction/destruction
+ bbc_we13rom_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
+
+protected:
+ // device-level overrides
+ virtual void device_start() override ATTR_COLD;
+
+ // optional information overrides
+ virtual void device_add_mconfig(machine_config &config) override ATTR_COLD;
+
+ virtual uint8_t paged_r(offs_t offset) override;
+ virtual void paged_w(offs_t offset, uint8_t data) override;
+};
+
+
+// device type definition
+DECLARE_DEVICE_TYPE(BBC_WE12ROM, bbc_we12rom_device);
+DECLARE_DEVICE_TYPE(BBC_WE13ROM, bbc_we13rom_device);
+
+
+
+#endif /* MAME_BUS_BBC_INTERNAL_WEROM_H */
diff --git a/src/devices/bus/bbc/internal/weromram.cpp b/src/devices/bus/bbc/internal/weromram.cpp
new file mode 100644
index 00000000000..ceb8be3e270
--- /dev/null
+++ b/src/devices/bus/bbc/internal/weromram.cpp
@@ -0,0 +1,133 @@
+// license:BSD-3-Clause
+// copyright-holders:Nigel Barnes
+/**********************************************************************
+
+ Watford Electronics ROM/RAM Board
+
+ http://chrisacorns.computinghistory.org.uk/8bit_Upgrades/WE_RAMROMBoard.html
+
+**********************************************************************/
+
+
+#include "emu.h"
+#include "weromram.h"
+
+
+//**************************************************************************
+// DEVICE DEFINITIONS
+//**************************************************************************
+
+DEFINE_DEVICE_TYPE(BBC_WEROMRAM, bbc_weromram_device, "bbc_weromram", "Watford Electronics ROM/RAM Board");
+
+
+//-------------------------------------------------
+// device_add_mconfig - add device configuration
+//-------------------------------------------------
+
+void bbc_weromram_device::device_add_mconfig(machine_config &config)
+{
+ /* 3 rom sockets, 64K dynamic ram, 16K static ram (battery backed) */
+ BBC_ROMSLOT16(config, m_rom[0], bbc_rom_devices, "ram").set_fixed_ram(true);
+ BBC_ROMSLOT16(config, m_rom[1], bbc_rom_devices, "ram").set_fixed_ram(true);
+ BBC_ROMSLOT16(config, m_rom[2], bbc_rom_devices, "ram").set_fixed_ram(true);
+ BBC_ROMSLOT16(config, m_rom[3], bbc_rom_devices, "ram").set_fixed_ram(true);
+ BBC_ROMSLOT16(config, m_rom[4], bbc_rom_devices, "ram").set_fixed_ram(true);
+ BBC_ROMSLOT16(config, m_rom[5], bbc_rom_devices, "ram").set_fixed_ram(true);
+ BBC_ROMSLOT16(config, m_rom[6], bbc_rom_devices, "ram").set_fixed_ram(true);
+ BBC_ROMSLOT16(config, m_rom[7], bbc_rom_devices, "ram").set_fixed_ram(true);
+ BBC_ROMSLOT16(config, m_rom[12], bbc_rom_devices, nullptr);
+ BBC_ROMSLOT16(config, m_rom[13], bbc_rom_devices, nullptr);
+ BBC_ROMSLOT16(config, m_rom[14], bbc_rom_devices, "nvram").set_fixed_ram(true);
+ BBC_ROMSLOT16(config, m_rom[15], bbc_rom_devices, nullptr);
+}
+
+
+//**************************************************************************
+// LIVE DEVICE
+//**************************************************************************
+
+//-------------------------------------------------
+// bbc_weromram_device - constructor
+//-------------------------------------------------
+
+bbc_weromram_device::bbc_weromram_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
+ : device_t(mconfig, BBC_WEROMRAM, tag, owner, clock)
+ , device_bbc_internal_interface(mconfig, *this)
+ , m_rom(*this, "romslot%u", 0U)
+{
+}
+
+
+//-------------------------------------------------
+// device_start - device-specific startup
+//-------------------------------------------------
+
+void bbc_weromram_device::device_start()
+{
+ /* move internal roms to board */
+ memmove(m_region_swr->base() + 0x2c000, m_region_swr->base(), 0xc000);
+ memmove(m_region_swr->base() + 0x3c000, m_region_swr->base() + 0xc000, 0x4000);
+ memset(m_region_swr->base(), 0xff, 0x10000);
+
+ /* register for save states */
+ save_item(NAME(m_romsel));
+ save_item(NAME(m_ramsel));
+}
+
+
+//**************************************************************************
+// IMPLEMENTATION
+//**************************************************************************
+
+uint8_t bbc_weromram_device::paged_r(offs_t offset)
+{
+ uint8_t data = 0xff;
+
+ switch (m_romsel)
+ {
+ case 8: case 9: case 10: case 11:
+ /* motherboard rom sockets 0-3 are re-assigned to 8-11 */
+ if (m_mb_rom[m_romsel & 0x03] && m_mb_rom[m_romsel & 0x03]->present())
+ {
+ data = m_mb_rom[m_romsel & 0x03]->read(offset);
+ }
+ else
+ {
+ data = m_region_swr->base()[offset + (m_romsel << 14) - 0x20000];
+ }
+ break;
+ default:
+ /* expansion board sockets */
+ if (m_rom[m_romsel] && m_rom[m_romsel]->present())
+ {
+ data = m_rom[m_romsel]->read(offset);
+ }
+ else
+ {
+ data = m_region_swr->base()[offset + (m_romsel << 14)];
+ }
+ break;
+ }
+
+ return data;
+}
+
+void bbc_weromram_device::paged_w(offs_t offset, uint8_t data)
+{
+ switch (m_romsel)
+ {
+ case 8: case 9: case 10: case 11:
+ /* motherboard rom sockets 0-3 are re-assigned to 8-11 */
+ if (m_mb_rom[m_romsel & 0x03])
+ {
+ m_mb_rom[m_romsel & 0x03]->write(offset, data);
+ }
+ break;
+ }
+
+ /* expansion board sockets */
+ if (m_rom[m_ramsel])
+ {
+ m_rom[m_ramsel]->write(offset, data);
+ }
+}
diff --git a/src/devices/bus/bbc/internal/weromram.h b/src/devices/bus/bbc/internal/weromram.h
new file mode 100644
index 00000000000..4cd58cf4382
--- /dev/null
+++ b/src/devices/bus/bbc/internal/weromram.h
@@ -0,0 +1,58 @@
+// license:BSD-3-Clause
+// copyright-holders:Nigel Barnes
+/**********************************************************************
+
+ Watford Electronics ROM/RAM Board
+
+ http://chrisacorns.computinghistory.org.uk/8bit_Upgrades/WE_RAMROMBoard.html
+
+**********************************************************************/
+
+
+#ifndef MAME_BUS_BBC_INTERNAL_WEROMRAM_H
+#define MAME_BUS_BBC_INTERNAL_WEROMRAM_H
+
+#include "internal.h"
+
+
+//**************************************************************************
+// TYPE DEFINITIONS
+//**************************************************************************
+
+class bbc_weromram_device :
+ public device_t,
+ public device_bbc_internal_interface
+{
+public:
+ // construction/destruction
+ bbc_weromram_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
+
+protected:
+ // device-level overrides
+ virtual void device_start() override ATTR_COLD;
+
+ // optional information overrides
+ virtual void device_add_mconfig(machine_config &config) override ATTR_COLD;
+
+ virtual bool overrides_rom() override { return true; }
+ virtual void romsel_w(offs_t offset, uint8_t data) override { m_romsel = data & 0x0f; }
+ virtual uint8_t paged_r(offs_t offset) override;
+ virtual void paged_w(offs_t offset, uint8_t data) override;
+
+private:
+ optional_device_array<bbc_romslot_device, 16> m_rom;
+
+ void ramsel_w(offs_t offset, uint8_t data);
+
+ uint8_t m_romsel;
+ uint8_t m_ramsel;
+};
+
+
+
+// device type definition
+DECLARE_DEVICE_TYPE(BBC_WEROMRAM, bbc_weromram_device);
+
+
+
+#endif /* MAME_BUS_BBC_INTERNAL_WEROMRAM_H */
diff --git a/src/devices/bus/bbc/joyport/joyport.cpp b/src/devices/bus/bbc/joyport/joyport.cpp
index 0c1bae50ee2..44387a80deb 100644
--- a/src/devices/bus/bbc/joyport/joyport.cpp
+++ b/src/devices/bus/bbc/joyport/joyport.cpp
@@ -25,8 +25,8 @@ DEFINE_DEVICE_TYPE(BBC_JOYPORT_SLOT, bbc_joyport_slot_device, "bbc_joyport_slot"
// device_bbc_joyport_interface - constructor
//-------------------------------------------------
-device_bbc_joyport_interface::device_bbc_joyport_interface(const machine_config &mconfig, device_t &device)
- : device_slot_card_interface(mconfig, device)
+device_bbc_joyport_interface::device_bbc_joyport_interface(const machine_config &mconfig, device_t &device) :
+ device_interface(device, "bbcjoyport")
{
m_slot = dynamic_cast<bbc_joyport_slot_device *>(device.owner());
}
@@ -40,75 +40,69 @@ device_bbc_joyport_interface::device_bbc_joyport_interface(const machine_config
// bbcmc_joyport_slot_device - constructor
//-------------------------------------------------
-bbc_joyport_slot_device::bbc_joyport_slot_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) :
- device_t(mconfig, BBC_JOYPORT_SLOT, tag, owner, clock),
- device_slot_interface(mconfig, *this),
- m_device(nullptr),
- m_cb1_handler(*this),
- m_cb2_handler(*this)
+bbc_joyport_slot_device::bbc_joyport_slot_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
+ : device_t(mconfig, BBC_JOYPORT_SLOT, tag, owner, clock)
+ , device_single_card_slot_interface(mconfig, *this)
+ , m_device(nullptr)
+ , m_cb1_handler(*this)
+ , m_cb2_handler(*this)
{
}
//-------------------------------------------------
-// device_validity_check -
+// device_start - device-specific startup
//-------------------------------------------------
-void bbc_joyport_slot_device::device_validity_check(validity_checker &valid) const
+void bbc_joyport_slot_device::device_start()
{
- device_t *const carddev = get_card_device();
- if (carddev && !dynamic_cast<device_bbc_joyport_interface *>(carddev))
- osd_printf_error("Card device %s (%s) does not implement device_bbc_joyport_interface\n", carddev->tag(), carddev->name());
+ m_device = get_card_device();
}
+
//-------------------------------------------------
-// device_start - device-specific startup
+// pb_r
//-------------------------------------------------
-void bbc_joyport_slot_device::device_start()
+uint8_t bbc_joyport_slot_device::pb_r()
{
- device_t *const carddev = get_card_device();
- m_device = dynamic_cast<device_bbc_joyport_interface *>(carddev);
- if (carddev && !m_device)
- fatalerror("Card device %s (%s) does not implement device_bbc_joyport_interface\n", carddev->tag(), carddev->name());
-
- // resolve callbacks
- m_cb1_handler.resolve_safe();
- m_cb2_handler.resolve_safe();
+ if (m_device)
+ return 0xe0 | m_device->pb_r();
+ else
+ return 0xff;
}
//-------------------------------------------------
-// device_reset - device-specific reset
+// pb_w
//-------------------------------------------------
-void bbc_joyport_slot_device::device_reset()
+void bbc_joyport_slot_device::pb_w(uint8_t data)
{
+ if (m_device)
+ m_device->pb_w(data);
}
//-------------------------------------------------
-// pb_r
+// write_cb1
//-------------------------------------------------
-uint8_t bbc_joyport_slot_device::pb_r()
+void bbc_joyport_slot_device::write_cb1(int state)
{
- // TODO: Joyport connected to PB0-PB4 only. PB5-PB7 are expansion port.
if (m_device)
- return 0xe0 | m_device->pb_r();
- else
- return 0xff;
+ m_device->write_cb1(state);
}
//-------------------------------------------------
-// pb_w
+// write_cb2
//-------------------------------------------------
-void bbc_joyport_slot_device::pb_w(uint8_t data)
+void bbc_joyport_slot_device::write_cb2(int state)
{
if (m_device)
- m_device->pb_w(data);
+ m_device->write_cb2(state);
}
@@ -119,11 +113,12 @@ void bbc_joyport_slot_device::pb_w(uint8_t data)
// slot devices
#include "joystick.h"
-//#include "mouse.h"
+#include "mouse.h"
void bbc_joyport_devices(device_slot_interface &device)
{
device.option_add("joystick", BBCMC_JOYSTICK);
- //device.option_add("mouse", BBCMC_MOUSE);
+ device.option_add("mouse", BBCMC_MOUSE);
+ //device.option_add("sat", BBCMC_SAT); /* Solidisk Advanced Teletext */
}
diff --git a/src/devices/bus/bbc/joyport/joyport.h b/src/devices/bus/bbc/joyport/joyport.h
index 6abda62633d..8e23e4b8a9a 100644
--- a/src/devices/bus/bbc/joyport/joyport.h
+++ b/src/devices/bus/bbc/joyport/joyport.h
@@ -41,7 +41,7 @@
class device_bbc_joyport_interface;
-class bbc_joyport_slot_device : public device_t, public device_slot_interface
+class bbc_joyport_slot_device : public device_t, public device_single_card_slot_interface<device_bbc_joyport_interface>
{
public:
// construction/destruction
@@ -61,17 +61,19 @@ public:
auto cb1_handler() { return m_cb1_handler.bind(); }
auto cb2_handler() { return m_cb2_handler.bind(); }
- DECLARE_WRITE_LINE_MEMBER(cb1_w) { m_cb1_handler(state); }
- DECLARE_WRITE_LINE_MEMBER(cb2_w) { m_cb2_handler(state); }
+ // from slot
+ void cb1_w(int state) { m_cb1_handler(state); }
+ void cb2_w(int state) { m_cb2_handler(state); }
+ // from host
uint8_t pb_r();
void pb_w(uint8_t data);
+ void write_cb1(int state);
+ void write_cb2(int state);
protected:
// device-level overrides
- virtual void device_validity_check(validity_checker &valid) const override;
- virtual void device_start() override;
- virtual void device_reset() override;
+ virtual void device_start() override ATTR_COLD;
device_bbc_joyport_interface *m_device;
@@ -83,11 +85,13 @@ private:
// ======================> device_bbc_joyport_interface
-class device_bbc_joyport_interface : public device_slot_card_interface
+class device_bbc_joyport_interface : public device_interface
{
public:
virtual uint8_t pb_r() { return 0xff; }
virtual void pb_w(uint8_t data) { }
+ virtual void write_cb1(int state) { }
+ virtual void write_cb2(int state) { }
protected:
device_bbc_joyport_interface(const machine_config &mconfig, device_t &device);
diff --git a/src/devices/bus/bbc/joyport/joystick.cpp b/src/devices/bus/bbc/joyport/joystick.cpp
index d53186f118d..1f5a9f89c98 100644
--- a/src/devices/bus/bbc/joyport/joystick.cpp
+++ b/src/devices/bus/bbc/joyport/joystick.cpp
@@ -2,7 +2,7 @@
// copyright-holders:Nigel Barnes
/**********************************************************************
- Joystick
+ BBC Master Compact Joystick
**********************************************************************/
@@ -13,7 +13,7 @@
// DEVICE DEFINITIONS
//**************************************************************************
-DEFINE_DEVICE_TYPE(BBCMC_JOYSTICK, bbcmc_joystick_device, "bbcmc_joystick", "Master Compact Joystick")
+DEFINE_DEVICE_TYPE(BBCMC_JOYSTICK, bbcmc_joystick_device, "bbcmc_joystick", "BBC Master Compact Joystick")
//-------------------------------------------------
@@ -65,15 +65,6 @@ void bbcmc_joystick_device::device_start()
}
-//-------------------------------------------------
-// device_reset - device-specific reset
-//-------------------------------------------------
-
-void bbcmc_joystick_device::device_reset()
-{
-}
-
-
//**************************************************************************
// IMPLEMENTATION
//**************************************************************************
diff --git a/src/devices/bus/bbc/joyport/joystick.h b/src/devices/bus/bbc/joyport/joystick.h
index 8d0cc5a0458..2cfc3e3c2c2 100644
--- a/src/devices/bus/bbc/joyport/joystick.h
+++ b/src/devices/bus/bbc/joyport/joystick.h
@@ -2,7 +2,7 @@
// copyright-holders:Nigel Barnes
/**********************************************************************
- Joystick
+ BBC Master Compact Joystick
**********************************************************************/
@@ -29,12 +29,11 @@ public:
bbcmc_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;
+ virtual ioport_constructor device_input_ports() const override ATTR_COLD;
protected:
// device-level overrides
- virtual void device_start() override;
- virtual void device_reset() override;
+ virtual void device_start() override ATTR_COLD;
virtual uint8_t pb_r() override;
diff --git a/src/devices/bus/bbc/joyport/mouse.cpp b/src/devices/bus/bbc/joyport/mouse.cpp
new file mode 100644
index 00000000000..1cd91caeaa5
--- /dev/null
+++ b/src/devices/bus/bbc/joyport/mouse.cpp
@@ -0,0 +1,178 @@
+// license:BSD-3-Clause
+// copyright-holders:Nigel Barnes
+/**********************************************************************
+
+ BBC Master Compact Mouse
+
+ The New Advanced User Guide (page 371) states the Compact PB assignments are:
+ PB4 Joystick RIGHT / Mouse Y-axis
+ PB3 Joystick UP / Mouse X-axis
+ PB2 Joystick DOWN / Mouse right button
+ PB1 Joystick LEFT / Mouse middle button
+ PB0 Joystick FIRE / Mouse left button
+
+**********************************************************************/
+
+#include "emu.h"
+#include "mouse.h"
+
+//**************************************************************************
+// DEVICE DEFINITIONS
+//**************************************************************************
+
+DEFINE_DEVICE_TYPE(BBCMC_MOUSE, bbcmc_mouse_device, "bbcmc_mouse", "BBC Master Compact Mouse")
+
+
+//-------------------------------------------------
+// INPUT_PORTS( mouse )
+//-------------------------------------------------
+
+static INPUT_PORTS_START( mouse )
+ PORT_START("mouse_x")
+ PORT_BIT(0xff, 0x00, IPT_MOUSE_X) PORT_SENSITIVITY(100)
+
+ PORT_START("mouse_y")
+ PORT_BIT(0xff, 0x00, IPT_MOUSE_Y) PORT_SENSITIVITY(100)
+
+ PORT_START("buttons")
+ 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)
+INPUT_PORTS_END
+
+
+//-------------------------------------------------
+// input_ports - device-specific input ports
+//-------------------------------------------------
+
+ioport_constructor bbcmc_mouse_device::device_input_ports() const
+{
+ return INPUT_PORTS_NAME( mouse );
+}
+
+
+//**************************************************************************
+// LIVE DEVICE
+//**************************************************************************
+
+//-------------------------------------------------
+// bbcmc_mouse_device - constructor
+//-------------------------------------------------
+
+bbcmc_mouse_device::bbcmc_mouse_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
+ : device_t(mconfig, BBCMC_MOUSE, tag, owner, clock)
+ , device_bbc_joyport_interface(mconfig, *this)
+ , m_mouse_x(*this, "mouse_x")
+ , m_mouse_y(*this, "mouse_y")
+ , m_buttons(*this, "buttons")
+{
+}
+
+
+//-------------------------------------------------
+// device_start - device-specific startup
+//-------------------------------------------------
+
+void bbcmc_mouse_device::device_start()
+{
+ m_mouse_timer = timer_alloc(FUNC(bbcmc_mouse_device::update), this);
+}
+
+
+//-------------------------------------------------
+// device_reset - device-specific reset
+//-------------------------------------------------
+
+void bbcmc_mouse_device::device_reset()
+{
+ m_xdir = 0;
+ m_ydir = 0;
+ m_x = 0;
+ m_y = 0;
+ m_phase_x = 0;
+ m_phase_y = 0;
+
+ m_mouse_timer->adjust(attotime::zero, 0, attotime::from_hz(1400));
+}
+
+
+//**************************************************************************
+// IMPLEMENTATION
+//**************************************************************************
+
+TIMER_CALLBACK_MEMBER(bbcmc_mouse_device::update)
+{
+ int x = m_mouse_x->read();
+ int y = m_mouse_y->read();
+
+ int dx = x - m_x;
+ int dy = y - m_y;
+
+ // Process X output
+ if (dx)
+ {
+ // Set the output pins according to the current phase
+ switch (m_phase_x)
+ {
+ case 0:
+ m_slot->cb1_w(1); // Set X1 to 1
+ break;
+ case 1:
+ m_xdir = 1; // Set X2 to 1
+ break;
+ case 2:
+ m_slot->cb1_w(0); // Set X1 to 0
+ break;
+ case 3:
+ m_xdir = 0; // Set X2 to 0
+ break;
+ }
+
+ // Change phase
+ if (dx > 0)
+ m_phase_x++;
+ else
+ m_phase_x--;
+
+ // Range check the phase
+ m_phase_x &= 3;
+ }
+
+ // Process Y output
+ if (dy)
+ {
+ // Set the output pins according to the current phase
+ switch (m_phase_y)
+ {
+ case 3:
+ m_slot->cb2_w(0); // Set Y1 to 0
+ break;
+ case 2:
+ m_ydir = 0; // Set Y2 to 0
+ break;
+ case 1:
+ m_slot->cb2_w(1); // Set Y1 to 1
+ break;
+ case 0:
+ m_ydir = 1; // Set Y2 to 1
+ break;
+ }
+
+ // Change phase
+ if (dy > 0)
+ m_phase_y++;
+ else
+ m_phase_y--;
+
+ // Range check the phase
+ m_phase_y &= 3;
+ }
+
+ m_x = x;
+ m_y = y;
+}
+
+uint8_t bbcmc_mouse_device::pb_r()
+{
+ return (m_buttons->read() & 0x07) | (m_xdir << 3) | (m_ydir << 4) | 0xe0;
+}
diff --git a/src/devices/bus/bbc/joyport/mouse.h b/src/devices/bus/bbc/joyport/mouse.h
new file mode 100644
index 00000000000..dc0e68627dc
--- /dev/null
+++ b/src/devices/bus/bbc/joyport/mouse.h
@@ -0,0 +1,62 @@
+// license:BSD-3-Clause
+// copyright-holders:Nigel Barnes
+/**********************************************************************
+
+ BBC Master Compact Mouse
+
+**********************************************************************/
+
+#ifndef MAME_BUS_BBC_JOYPORT_MOUSE_H
+#define MAME_BUS_BBC_JOYPORT_MOUSE_H
+
+#pragma once
+
+#include "joyport.h"
+
+//**************************************************************************
+// TYPE DEFINITIONS
+//**************************************************************************
+
+// ======================> bbcmc_mouse_device
+
+class bbcmc_mouse_device :
+ public device_t,
+ public device_bbc_joyport_interface
+{
+public:
+ // construction/destruction
+ bbcmc_mouse_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
+
+protected:
+ // device-level overrides
+ virtual void device_start() override ATTR_COLD;
+ virtual void device_reset() override ATTR_COLD;
+
+ // optional information overrides
+ virtual ioport_constructor device_input_ports() const override ATTR_COLD;
+
+ virtual uint8_t pb_r() override;
+
+ TIMER_CALLBACK_MEMBER(update);
+
+private:
+ required_ioport m_mouse_x;
+ required_ioport m_mouse_y;
+ required_ioport m_buttons;
+
+ // quadrature output
+ int m_xdir, m_ydir;
+
+ // internal quadrature state
+ int m_x, m_y;
+ int m_phase_x, m_phase_y;
+
+ emu_timer *m_mouse_timer;
+};
+
+
+// device type definition
+DECLARE_DEVICE_TYPE(BBCMC_MOUSE, bbcmc_mouse_device)
+
+
+#endif // MAME_BUS_BBC_JOYPORT_MOUSE_H
diff --git a/src/devices/bus/bbc/modem/meup.cpp b/src/devices/bus/bbc/modem/meup.cpp
new file mode 100644
index 00000000000..128db2b0297
--- /dev/null
+++ b/src/devices/bus/bbc/modem/meup.cpp
@@ -0,0 +1,77 @@
+// license:BSD-3-Clause
+// copyright-holders:Nigel Barnes
+/**********************************************************************
+
+ Master Extra User Port
+
+**********************************************************************/
+
+#include "emu.h"
+#include "meup.h"
+#include "bus/bbc/userport/userport.h"
+
+
+//**************************************************************************
+// DEVICE DEFINITIONS
+//**************************************************************************
+
+DEFINE_DEVICE_TYPE(BBC_MEUP, bbc_meup_device, "bbc_meup", "Master Extra User Port");
+
+
+//-------------------------------------------------
+// device_add_mconfig - add device configuration
+//-------------------------------------------------
+
+void bbc_meup_device::device_add_mconfig(machine_config &config)
+{
+ MOS6522(config, m_via, DERIVED_CLOCK(1, 1));
+ m_via->readpb_handler().set("userport2", FUNC(bbc_userport_slot_device::pb_r));
+ m_via->writepb_handler().set("userport2", FUNC(bbc_userport_slot_device::pb_w));
+ m_via->cb1_handler().set("userport2", FUNC(bbc_userport_slot_device::write_cb1));
+ m_via->cb2_handler().set("userport2", FUNC(bbc_userport_slot_device::write_cb2));
+ m_via->irq_handler().set(DEVICE_SELF_OWNER, FUNC(bbc_modem_slot_device::irq_w));
+
+ bbc_userport_slot_device &userport2(BBC_USERPORT_SLOT(config, "userport2", bbc_userport_devices, nullptr));
+ userport2.cb1_handler().set(m_via, FUNC(via6522_device::write_cb1));
+ userport2.cb2_handler().set(m_via, FUNC(via6522_device::write_cb2));
+}
+
+
+//**************************************************************************
+// LIVE DEVICE
+//**************************************************************************
+
+//-------------------------------------------------
+// bbc_meup_device - constructor
+//-------------------------------------------------
+
+bbc_meup_device::bbc_meup_device(const machine_config &mconfig, const char* tag, device_t* owner, uint32_t clock)
+ : device_t(mconfig, BBC_MEUP, tag, owner, clock)
+ , device_bbc_modem_interface(mconfig, *this)
+ , m_via(*this, "via")
+{
+}
+
+
+//-------------------------------------------------
+// device_start - device-specific startup
+//-------------------------------------------------
+
+void bbc_meup_device::device_start()
+{
+}
+
+
+//**************************************************************************
+// IMPLEMENTATION
+//**************************************************************************
+
+uint8_t bbc_meup_device::read(offs_t offset)
+{
+ return m_via->read(offset);
+}
+
+void bbc_meup_device::write(offs_t offset, uint8_t data)
+{
+ m_via->write(offset, data);
+}
diff --git a/src/devices/bus/bbc/modem/meup.h b/src/devices/bus/bbc/modem/meup.h
new file mode 100644
index 00000000000..b102b55ebc9
--- /dev/null
+++ b/src/devices/bus/bbc/modem/meup.h
@@ -0,0 +1,46 @@
+// license:BSD-3-Clause
+// copyright-holders:Nigel Barnes
+/**********************************************************************
+
+ Master Extra User Port
+
+**********************************************************************/
+
+
+#ifndef MAME_BUS_BBC_MODEM_MEUP_H
+#define MAME_BUS_BBC_MODEM_MEUP_H
+
+#include "modem.h"
+#include "machine/6522via.h"
+
+
+//**************************************************************************
+// TYPE DEFINITIONS
+//**************************************************************************
+
+class bbc_meup_device: public device_t, public device_bbc_modem_interface
+{
+public:
+ // construction/destruction
+ bbc_meup_device(const machine_config &mconfig, const char* tag, device_t* owner, uint32_t clock);
+
+protected:
+ // device-level overrides
+ virtual void device_start() override ATTR_COLD;
+
+ // optional information overrides
+ virtual void device_add_mconfig(machine_config &config) override ATTR_COLD;
+
+ virtual uint8_t read(offs_t offset) override;
+ virtual void write(offs_t offset, uint8_t data) override;
+
+private:
+ required_device<via6522_device> m_via;
+};
+
+
+// device type definition
+DECLARE_DEVICE_TYPE(BBC_MEUP, bbc_meup_device);
+
+
+#endif /* MAME_BUS_BBC_MODEM_MEUP_H */
diff --git a/src/devices/bus/bbc/modem/modem.cpp b/src/devices/bus/bbc/modem/modem.cpp
new file mode 100644
index 00000000000..6dfcf4e47f1
--- /dev/null
+++ b/src/devices/bus/bbc/modem/modem.cpp
@@ -0,0 +1,101 @@
+// license:BSD-3-Clause
+// copyright-holders:Nigel Barnes
+/**********************************************************************
+
+ BBC Master Internal Modem port
+
+**********************************************************************/
+
+#include "emu.h"
+#include "modem.h"
+
+
+//**************************************************************************
+// DEVICE DEFINITIONS
+//**************************************************************************
+
+DEFINE_DEVICE_TYPE(BBC_MODEM_SLOT, bbc_modem_slot_device, "bbc_modem_slot", "BBC Master Internal Modem port")
+
+
+
+//**************************************************************************
+// DEVICE BBC_MODEM PORT INTERFACE
+//**************************************************************************
+
+//-------------------------------------------------
+// device_bbc_modem_interface - constructor
+//-------------------------------------------------
+
+device_bbc_modem_interface::device_bbc_modem_interface(const machine_config &mconfig, device_t &device) :
+ device_interface(device, "bbcmodem")
+{
+ m_slot = dynamic_cast<bbc_modem_slot_device *>(device.owner());
+}
+
+
+//**************************************************************************
+// LIVE DEVICE
+//**************************************************************************
+
+//-------------------------------------------------
+// bbc_modem_slot_device - constructor
+//-------------------------------------------------
+
+bbc_modem_slot_device::bbc_modem_slot_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
+ : device_t(mconfig, BBC_MODEM_SLOT, tag, owner, clock)
+ , device_single_card_slot_interface<device_bbc_modem_interface>(mconfig, *this)
+ , m_card(nullptr)
+ , m_irq_handler(*this)
+{
+}
+
+
+//-------------------------------------------------
+// device_start - device-specific startup
+//-------------------------------------------------
+
+void bbc_modem_slot_device::device_start()
+{
+ m_card = get_card_device();
+}
+
+
+//-------------------------------------------------
+// read
+//-------------------------------------------------
+
+uint8_t bbc_modem_slot_device::read(offs_t offset)
+{
+ if (m_card)
+ return m_card->read(offset & 0x0f);
+ else
+ return 0xfe;
+}
+
+//-------------------------------------------------
+// write
+//-------------------------------------------------
+
+void bbc_modem_slot_device::write(offs_t offset, uint8_t data)
+{
+ if (m_card)
+ m_card->write(offset & 0x0f, data);
+}
+
+//-------------------------------------------------
+// SLOT_INTERFACE( bbcm_modem_devices )
+//-------------------------------------------------
+
+
+// slot devices
+#include "meup.h"
+#include "scsiaiv.h"
+
+
+void bbcm_modem_devices(device_slot_interface &device)
+{
+ device.option_add("meup", BBC_MEUP); /* Master Extra User Ports */
+ //device.option_add("modem", BBC_MODEM); /* Beebug Master Modem */
+ device.option_add("scsiaiv", BBC_SCSIAIV); /* Acorn AIV SCSI Host Adaptor */
+ //device.option_add("vp415", BBC_VP415); /* Philips VP415 */
+}
diff --git a/src/devices/bus/bbc/modem/modem.h b/src/devices/bus/bbc/modem/modem.h
new file mode 100644
index 00000000000..aaff1b611ae
--- /dev/null
+++ b/src/devices/bus/bbc/modem/modem.h
@@ -0,0 +1,105 @@
+// license:BSD-3-Clause
+// copyright-holders:Nigel Barnes
+/**********************************************************************
+
+ BBC Master Internal Modem port
+
+**********************************************************************
+
+ Pinout:
+
+ 1 NIRQ
+ 2 NRST
+ 3 BD0
+ 4 BD1
+ 5 BD2
+ 6 BD3
+ 7 BD4
+ 8 BD5
+ 9 BD6
+ 10 BD7
+ 11 MODEM
+ 12 A0
+ 13 A1
+ 14 A2
+ 15 A3
+ 16 1MHzE
+ 17 R/W
+ 18 +5V
+ 19 -5V
+ 20 0V
+
+**********************************************************************/
+
+#ifndef MAME_BUS_BBC_MODEM_MODEM_H
+#define MAME_BUS_BBC_MODEM_MODEM_H
+
+#pragma once
+
+
+
+//**************************************************************************
+// TYPE DEFINITIONS
+//**************************************************************************
+
+// ======================> bbc_modem_slot_device
+
+class device_bbc_modem_interface;
+
+class bbc_modem_slot_device : public device_t, public device_single_card_slot_interface<device_bbc_modem_interface>
+{
+public:
+ // construction/destruction
+ template <typename T>
+ bbc_modem_slot_device(machine_config const &mconfig, char const *tag, device_t *owner, uint32_t clock, T &&slot_options, const char *default_option)
+ : bbc_modem_slot_device(mconfig, tag, owner, clock)
+ {
+ option_reset();
+ slot_options(*this);
+ set_default_option(default_option);
+ set_fixed(false);
+ }
+
+ bbc_modem_slot_device(machine_config const &mconfig, char const *tag, device_t *owner, uint32_t clock);
+
+ // callbacks
+ auto irq_handler() { return m_irq_handler.bind(); }
+
+ virtual uint8_t read(offs_t offset);
+ virtual void write(offs_t offset, uint8_t data);
+
+ void irq_w(int state) { m_irq_handler(state); }
+
+protected:
+ // device-level overrides
+ virtual void device_start() override ATTR_COLD;
+
+ device_bbc_modem_interface *m_card;
+
+private:
+ devcb_write_line m_irq_handler;
+};
+
+
+// ======================> device_bbc_modem_interface
+
+class device_bbc_modem_interface : public device_interface
+{
+public:
+ virtual uint8_t read(offs_t offset) { return 0xff; }
+ virtual void write(offs_t offset, uint8_t data) { }
+
+protected:
+ device_bbc_modem_interface(const machine_config &mconfig, device_t &device);
+
+ bbc_modem_slot_device *m_slot;
+};
+
+
+// device type definition
+DECLARE_DEVICE_TYPE(BBC_MODEM_SLOT, bbc_modem_slot_device)
+
+void bbcm_modem_devices(device_slot_interface &device);
+
+
+#endif // MAME_BUS_BBC_MODEM_MODEM_H
diff --git a/src/devices/bus/bbc/modem/scsiaiv.cpp b/src/devices/bus/bbc/modem/scsiaiv.cpp
new file mode 100644
index 00000000000..deb75196810
--- /dev/null
+++ b/src/devices/bus/bbc/modem/scsiaiv.cpp
@@ -0,0 +1,142 @@
+// license:BSD-3-Clause
+// copyright-holders:Nigel Barnes
+/**********************************************************************
+
+ Acorn AIV SCSI Host Adaptor
+
+**********************************************************************/
+
+#include "emu.h"
+#include "scsiaiv.h"
+#include "machine/nscsi_bus.h"
+#include "bus/nscsi/devices.h"
+
+
+//**************************************************************************
+// DEVICE DEFINITIONS
+//**************************************************************************
+
+DEFINE_DEVICE_TYPE(BBC_SCSIAIV, bbc_scsiaiv_device, "bbc_scsiaiv", "Acorn AIV SCSI Host Adaptor");
+//DEFINE_DEVICE_TYPE(BBC_VP415, bbc_vp415_device, "bbc_vp415", "BBC Philips VP415");
+
+
+//-------------------------------------------------
+// device_add_mconfig - add device configuration
+//-------------------------------------------------
+
+void bbc_scsiaiv_device::device_add_mconfig(machine_config &config)
+{
+ NSCSI_BUS(config, "scsi");
+ NSCSI_CONNECTOR(config, "scsi:0", default_scsi_devices, nullptr);
+ NSCSI_CONNECTOR(config, "scsi:7", default_scsi_devices, "scsicb", true)
+ .option_add_internal("scsicb", NSCSI_CB)
+ .machine_config([this](device_t* device) {
+ downcast<nscsi_callback_device&>(*device).bsy_callback().set(*this, FUNC(bbc_scsiaiv_device::bsy_w));
+ downcast<nscsi_callback_device&>(*device).req_callback().set(*this, FUNC(bbc_scsiaiv_device::req_w));
+ });
+}
+
+//void bbc_vp415_device::device_add_mconfig(machine_config &config)
+//{
+// bbc_scsiaiv_device::device_add_mconfig(config);
+//
+// /* Philips VP415 */
+// subdevice<nscsi_connector>("scsi:0")->set_default_option("vp415");
+// subdevice<nscsi_connector>("scsi:0")->set_fixed(true);
+//}
+
+
+//**************************************************************************
+// LIVE DEVICE
+//**************************************************************************
+
+//-------------------------------------------------
+// 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)
+ : 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(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_scsiaiv_device(mconfig, BBC_VP415, tag, owner, clock)
+//{
+//}
+
+
+//-------------------------------------------------
+// device_start - device-specific startup
+//-------------------------------------------------
+
+void bbc_scsiaiv_device::device_start()
+{
+ /* register for save states */
+ save_item(NAME(m_irq_enable));
+ save_item(NAME(m_irq_state));
+}
+
+//**************************************************************************
+// IMPLEMENTATION
+//**************************************************************************
+
+uint8_t bbc_scsiaiv_device::read(offs_t offset)
+{
+ uint8_t data = 0xff;
+
+ switch (offset & 0x07)
+ {
+ case 0x00:
+ data = m_scsi->read();
+ m_scsi->ack_w(1);
+ break;
+ case 0x01:
+ data = (m_scsi->msg_r() << 0)
+ | (m_scsi->bsy_r() << 1)
+ | (m_scsi->rst_r() << 2)
+ | (!m_irq_state << 4)
+ | (m_scsi->req_r() << 5)
+ | (m_scsi->io_r() << 6)
+ | (m_scsi->cd_r() << 7);
+ break;
+ }
+
+ return data;
+}
+
+void bbc_scsiaiv_device::write(offs_t offset, uint8_t data)
+{
+ switch (offset & 0x07)
+ {
+ case 0x00:
+ m_scsi->write(~data);
+ m_scsi->ack_w(1);
+ break;
+ case 0x02:
+ m_scsi->sel_w(1);
+ break;
+ case 0x03:
+ m_irq_enable = BIT(data, 0);
+ break;
+ }
+}
+
+void bbc_scsiaiv_device::bsy_w(int state)
+{
+ m_scsi->sel_w(0);
+}
+
+void bbc_scsiaiv_device::req_w(int state)
+{
+ m_scsi->ack_w(0);
+
+ m_irq_state = (m_irq_enable && !state) ? 0 : 1;
+ m_slot->irq_w(m_irq_state ? CLEAR_LINE : ASSERT_LINE);
+}
diff --git a/src/devices/bus/bbc/modem/scsiaiv.h b/src/devices/bus/bbc/modem/scsiaiv.h
new file mode 100644
index 00000000000..f4a59bf4bd8
--- /dev/null
+++ b/src/devices/bus/bbc/modem/scsiaiv.h
@@ -0,0 +1,71 @@
+// license:BSD-3-Clause
+// copyright-holders:Nigel Barnes
+/**********************************************************************
+
+ Acorn AIV SCSI Host Adaptor
+
+**********************************************************************/
+
+
+#ifndef MAME_BUS_BBC_MODEM_SCSIAIV_H
+#define MAME_BUS_BBC_MODEM_SCSIAIV_H
+
+#include "modem.h"
+#include "machine/nscsi_cb.h"
+
+
+//**************************************************************************
+// TYPE DEFINITIONS
+//**************************************************************************
+
+class bbc_scsiaiv_device:
+ public device_t,
+ public device_bbc_modem_interface
+{
+public:
+ // construction/destruction
+ bbc_scsiaiv_device(const machine_config &mconfig, const char* tag, device_t* owner, uint32_t clock);
+
+ 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);
+
+ // device-level overrides
+ virtual void device_start() override ATTR_COLD;
+
+ // optional information overrides
+ virtual void device_add_mconfig(machine_config &config) override ATTR_COLD;
+
+ virtual uint8_t read(offs_t offset) override;
+ virtual void write(offs_t offset, uint8_t data) override;
+
+private:
+ required_device<nscsi_callback_device> m_scsi;
+
+ int m_irq_enable;
+ int m_irq_state;
+};
+
+
+// ======================> bbc_vp415_device
+
+//class bbc_vp415_device : public bbc_scsiaiv_device
+//{
+//public:
+// // construction/destruction
+// 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 ATTR_COLD;
+//};
+
+
+// device type definition
+DECLARE_DEVICE_TYPE(BBC_SCSIAIV, bbc_scsiaiv_device);
+//DECLARE_DEVICE_TYPE(BBC_VP415, bbc_vp415_device);
+
+
+#endif /* MAME_BUS_BBC_MODEM_SCSIAIV_H */
diff --git a/src/devices/bus/bbc/rom/datagem.cpp b/src/devices/bus/bbc/rom/datagem.cpp
new file mode 100644
index 00000000000..11f2cfdb631
--- /dev/null
+++ b/src/devices/bus/bbc/rom/datagem.cpp
@@ -0,0 +1,96 @@
+// license:BSD-3-Clause
+// copyright-holders:Nigel Barnes
+/***************************************************************************
+
+ Gemini DataGem ROM Carrier
+
+***************************************************************************/
+
+#include "emu.h"
+#include "datagem.h"
+
+
+//**************************************************************************
+// DEVICE DEFINITIONS
+//**************************************************************************
+
+DEFINE_DEVICE_TYPE(BBC_DATAGEM, bbc_datagem_device, "bbc_datagem", "Gemini DataGem ROM Carrier")
+
+
+//**************************************************************************
+// LIVE DEVICE
+//**************************************************************************
+
+//-------------------------------------------------
+// bbc_datagem_device - constructor
+//-------------------------------------------------
+
+bbc_datagem_device::bbc_datagem_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
+ : device_t(mconfig, BBC_DATAGEM, tag, owner, clock)
+ , device_bbc_rom_interface(mconfig, *this)
+ , m_bank(0)
+{
+}
+
+
+//-------------------------------------------------
+// device_start - device-specific startup
+//-------------------------------------------------
+
+void bbc_datagem_device::device_start()
+{
+ /* register for save states */
+ save_item(NAME(m_bank));
+}
+
+//-------------------------------------------------
+// decrypt_rom
+//-------------------------------------------------
+
+void bbc_datagem_device::decrypt_rom()
+{
+ uint8_t *rom = get_rom_base();
+
+ for (int i = 0x0000; i < 0x6000; i++)
+ {
+ /* decrypt 16K and 8K ROM data lines */
+ switch (rom[i] & 0x07)
+ {
+ case 0x01: case 0x06: rom[i] = bitswap<8>(rom[i], 7, 6, 5, 4, 3, 0, 1, 2); break;
+ case 0x02: case 0x05: rom[i] = bitswap<8>(rom[i], 7, 6, 5, 4, 3, 2, 0, 1); break;
+ case 0x03: case 0x04: rom[i] = bitswap<8>(rom[i], 7, 6, 5, 4, 3, 1, 2, 0); break;
+ }
+
+ /* decrypt additional 8K ROM data lines */
+ if (i & 0x4000)
+ {
+ rom[i] = bitswap<8>(rom[i], 3, 6, 5, 4, 7, 2, 1, 0);
+ }
+ }
+}
+
+//-------------------------------------------------
+// read
+//-------------------------------------------------
+
+uint8_t bbc_datagem_device::read(offs_t offset)
+{
+ if (!machine().side_effects_disabled())
+ {
+ /* switching zones for DataGem */
+ switch (offset & 0x3fff)
+ {
+ case 0x1ffe: m_bank = 1; break;
+ case 0x1fff: m_bank = 0; break;
+ }
+ }
+
+ if (offset & 0x2000)
+ {
+ return get_rom_base()[(offset & 0x3fff) + (m_bank << 13)];
+ }
+ else
+ {
+ return get_rom_base()[offset & 0x3fff];
+ }
+}
diff --git a/src/devices/bus/bbc/rom/datagem.h b/src/devices/bus/bbc/rom/datagem.h
new file mode 100644
index 00000000000..ba12df0ff3f
--- /dev/null
+++ b/src/devices/bus/bbc/rom/datagem.h
@@ -0,0 +1,48 @@
+// license:BSD-3-Clause
+// copyright-holders:Nigel Barnes
+/***************************************************************************
+
+ Gemini DataGem ROM Carrier
+
+***************************************************************************/
+
+#ifndef MAME_BUS_BBC_ROM_DATAGEM_H
+#define MAME_BUS_BBC_ROM_DATAGEM_H
+
+#pragma once
+
+#include "slot.h"
+
+
+//**************************************************************************
+// TYPE DEFINITIONS
+//**************************************************************************
+
+// ======================> bbc_datagem_device
+
+class bbc_datagem_device : public device_t,
+ public device_bbc_rom_interface
+{
+public:
+ // construction/destruction
+ bbc_datagem_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
+
+protected:
+ // device-level overrides
+ virtual void device_start() override ATTR_COLD;
+
+ // device_bbc_rom_interface overrides
+ virtual uint32_t get_rom_size() override { return 0x4000; }
+ virtual uint8_t read(offs_t offset) override;
+ virtual void decrypt_rom() override;
+
+private:
+ uint8_t m_bank;
+};
+
+
+// device type definition
+DECLARE_DEVICE_TYPE(BBC_DATAGEM, bbc_datagem_device)
+
+
+#endif // MAME_BUS_BBC_ROM_DATAGEM_H
diff --git a/src/devices/bus/bbc/rom/dfs.cpp b/src/devices/bus/bbc/rom/dfs.cpp
index 8a3aac6d588..7395b31dae9 100644
--- a/src/devices/bus/bbc/rom/dfs.cpp
+++ b/src/devices/bus/bbc/rom/dfs.cpp
@@ -2,7 +2,7 @@
// copyright-holders:Nigel Barnes
/***************************************************************************
- BBC Micro MRM E00 DFS emulation
+ BBC Micro E00 DFS emulation
Comprises of 8K ROM and 2K/4K? RAM on a carrier board, with flying lead
to RW line to enable writing to RAM.
@@ -17,7 +17,7 @@
// DEVICE DEFINITIONS
//**************************************************************************
-DEFINE_DEVICE_TYPE(BBC_MRME00, bbc_mrme00_device, "bbc_mrme00", "BBC Micro MRM E00 DFS")
+DEFINE_DEVICE_TYPE(BBC_DFSE00, bbc_dfse00_device, "bbc_dfse00", "BBC Micro E00 DFS")
//**************************************************************************
// LIVE DEVICE
@@ -27,8 +27,8 @@ DEFINE_DEVICE_TYPE(BBC_MRME00, bbc_mrme00_device, "bbc_mrme00", "BBC Micro MRM E
// bbc_rom_device - constructor
//-------------------------------------------------
-bbc_mrme00_device::bbc_mrme00_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
- : device_t(mconfig, BBC_MRME00, tag, owner, clock)
+bbc_dfse00_device::bbc_dfse00_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
+ : device_t(mconfig, BBC_DFSE00, tag, owner, clock)
, device_bbc_rom_interface(mconfig, *this)
{
}
@@ -37,7 +37,7 @@ bbc_mrme00_device::bbc_mrme00_device(const machine_config &mconfig, const char *
// device_start - device-specific startup
//-------------------------------------------------
-void bbc_mrme00_device::device_start()
+void bbc_dfse00_device::device_start()
{
}
@@ -45,7 +45,7 @@ void bbc_mrme00_device::device_start()
// read
//-------------------------------------------------
-uint8_t bbc_mrme00_device::read(offs_t offset)
+uint8_t bbc_dfse00_device::read(offs_t offset)
{
if (offset < get_rom_size())
return get_rom_base()[offset & (get_rom_size() - 1)];
@@ -57,7 +57,7 @@ uint8_t bbc_mrme00_device::read(offs_t offset)
// write
//-------------------------------------------------
-void bbc_mrme00_device::write(offs_t offset, uint8_t data)
+void bbc_dfse00_device::write(offs_t offset, uint8_t data)
{
get_ram_base()[offset & (get_ram_size() - 1)] = data;
}
diff --git a/src/devices/bus/bbc/rom/dfs.h b/src/devices/bus/bbc/rom/dfs.h
index b76a7ab26ed..59ebb531423 100644
--- a/src/devices/bus/bbc/rom/dfs.h
+++ b/src/devices/bus/bbc/rom/dfs.h
@@ -2,7 +2,7 @@
// copyright-holders:Nigel Barnes
/***************************************************************************
- BBC Micro MRM E00 DFS emulation
+ BBC Micro E00 DFS emulation
***************************************************************************/
@@ -17,18 +17,17 @@
// TYPE DEFINITIONS
//**************************************************************************
-// ======================> bbc_mrme00_device
+// ======================> bbc_dfse00_device
-class bbc_mrme00_device : public device_t,
- public device_bbc_rom_interface
+class bbc_dfse00_device : public device_t, public device_bbc_rom_interface
{
public:
// construction/destruction
- bbc_mrme00_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
+ bbc_dfse00_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_start() override ATTR_COLD;
// device_bbc_rom_interface overrides
virtual uint8_t read(offs_t offset) override;
@@ -36,7 +35,7 @@ protected:
};
// device type definition
-DECLARE_DEVICE_TYPE(BBC_MRME00, bbc_mrme00_device)
+DECLARE_DEVICE_TYPE(BBC_DFSE00, bbc_dfse00_device)
#endif // MAME_BUS_BBC_ROM_DFS_H
diff --git a/src/devices/bus/bbc/rom/genie.cpp b/src/devices/bus/bbc/rom/genie.cpp
index 28b9b42644a..6515bfe4030 100644
--- a/src/devices/bus/bbc/rom/genie.cpp
+++ b/src/devices/bus/bbc/rom/genie.cpp
@@ -3,7 +3,7 @@
// thanks-to:Derek Mathieson (original author of Genie)
/***************************************************************************
- PMS Genie
+ PMS Genie ROM Board
***************************************************************************/
@@ -11,28 +11,45 @@
#include "genie.h"
-//**************************************************************************
-// DEVICE DEFINITIONS
-//**************************************************************************
+namespace {
-DEFINE_DEVICE_TYPE(BBC_PMSGENIE, bbc_pmsgenie_device, "bbc_pmsgenie", "PMS Genie ROM Board")
+class bbc_pmsgenie_device
+ : public device_t
+ , public device_bbc_rom_interface
+ , public device_nvram_interface
+{
+public:
+ bbc_pmsgenie_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
+ : device_t(mconfig, BBC_PMSGENIE, tag, owner, clock)
+ , device_bbc_rom_interface(mconfig, *this)
+ , device_nvram_interface(mconfig, *this)
+ , m_nvram(*this, "nvram", 0x8000, ENDIANNESS_LITTLE)
+ , m_ram(*this, "ram", 0x8000, ENDIANNESS_LITTLE)
+ , m_write_latch(0)
+ , m_bank_latch(0)
+ {
+ }
+protected:
+ // device_t overrides
+ virtual void device_start() override ATTR_COLD;
-//**************************************************************************
-// LIVE DEVICE
-//**************************************************************************
+ // device_nvram_interface overrides
+ virtual void nvram_default() override;
+ virtual bool nvram_read(util::read_stream &file) override;
+ virtual bool nvram_write(util::write_stream &file) override;
-//-------------------------------------------------
-// bbc_palprom_device - constructor
-//-------------------------------------------------
+ // device_bbc_rom_interface overrides
+ virtual uint8_t read(offs_t offset) override;
+ virtual uint32_t get_rom_size() override { return 0x4000; }
-bbc_pmsgenie_device::bbc_pmsgenie_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
- : device_t(mconfig, BBC_PMSGENIE, tag, owner, clock)
- , device_bbc_rom_interface(mconfig, *this)
- , m_write_latch(0)
- , m_bank_latch(0)
-{
-}
+private:
+ memory_share_creator<uint8_t> m_nvram;
+ memory_share_creator<uint8_t> m_ram;
+
+ uint8_t m_write_latch;
+ uint8_t m_bank_latch;
+};
//-------------------------------------------------
@@ -45,6 +62,65 @@ void bbc_pmsgenie_device::device_start()
save_item(NAME(m_bank_latch));
}
+
+//-------------------------------------------------
+// nvram_default - called to initialize NVRAM to
+// its default state
+//-------------------------------------------------
+
+void bbc_pmsgenie_device::nvram_default()
+{
+ // initial data from Genie formatter
+ static const uint8_t format[256] =
+ {
+ 0x37, 0x1b, 0x36, 0x1e, 0x1e, 0x35, 0x12, 0x10, 0x36, 0x34, 0x00, 0x00, 0x03, 0x01, 0x01, 0x01,
+ 0xff, 0x01, 0x01, 0x07, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0xf7, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x44, 0x65, 0x72, 0x65, 0x6b, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x01, 0x81, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x6e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+ };
+
+ // clear the Genie
+ memset(&m_nvram[0], 0x00, sizeof(m_nvram));
+
+ // set password to "GENIE", and initialise structures
+ memcpy(&m_nvram[0], format, sizeof(format));
+}
+
+//-------------------------------------------------
+// nvram_read - called to read NVRAM from the
+// specified file
+//-------------------------------------------------
+
+bool bbc_pmsgenie_device::nvram_read(util::read_stream &file)
+{
+ auto const [err, actual] = util::read(file, m_nvram, m_nvram.bytes());
+ return !err && (actual == m_nvram.bytes());
+}
+
+//-------------------------------------------------
+// nvram_write - called to write NVRAM to the
+// specified file
+//-------------------------------------------------
+
+bool bbc_pmsgenie_device::nvram_write(util::write_stream &file)
+{
+ auto const [err, actual] = util::write(file, m_nvram, m_nvram.bytes());
+ return !err;
+}
+
+
//-------------------------------------------------
// read
//-------------------------------------------------
@@ -58,17 +134,18 @@ uint8_t bbc_pmsgenie_device::read(offs_t offset)
switch (offset >> 8)
{
case 0x1e:
- /* &9E00-&9EFF - Write value latch */
+ // &9E00-&9EFF - Write value latch
m_write_latch = offset & 0xff;
break;
+
case 0x1f:
- /* &9F00-&9FFF - Bank select latch
- Bit
- 0-2: RAM bank select
- 3: Not used
- 4-5: ROM bank select
- 6: Not used
- 7: Read / NOT Write for internal RAM */
+ // &9F00-&9FFF - Bank select latch
+ // Bit
+ // 0-2: RAM bank select
+ // 3: Not used
+ // 4-5: ROM bank select
+ // 6: Not used
+ // 7: Read / NOT Write for internal RAM
m_bank_latch = offset & 0xff;
break;
}
@@ -77,35 +154,28 @@ uint8_t bbc_pmsgenie_device::read(offs_t offset)
switch (offset & 0x2000)
{
case 0x0000:
- /* &8000-&9FFF - 4 Pages of 8K ROM (32K in total) */
+ // &8000-&9FFF - 4 Pages of 8K ROM (32K in total)
data = get_rom_base()[(offset & 0x1fff) | (m_bank_latch & 0x30) << 9];
break;
case 0x2000:
- /* &A000-&BFFF - 8 Pages of 8K RAM (64K in total) */
+ // &A000-&BFFF - 8 Pages of 8K RAM (64K in total)
if (m_bank_latch & 0x80)
{
- /* RAM read */
+ // RAM read
if (m_bank_latch & 0x04)
- {
- data = get_nvram_base()[(offset & 0x1fff) | (m_bank_latch & 0x03) << 13];
- }
+ data = m_nvram[(offset & 0x1fff) | (m_bank_latch & 0x03) << 13];
else
- {
- data = get_ram_base()[(offset & 0x1fff) | (m_bank_latch & 0x03) << 13];
- }
+ data = m_ram[(offset & 0x1fff) | (m_bank_latch & 0x03) << 13];
}
else
{
- /* RAM write */
+ // RAM write
if (m_bank_latch & 0x04)
- {
- get_nvram_base()[(offset & 0x1fff) | (m_bank_latch & 0x03) << 13] = m_write_latch;
- }
+ m_nvram[(offset & 0x1fff) | (m_bank_latch & 0x03) << 13] = m_write_latch;
else
- {
- get_ram_base()[(offset & 0x1fff) | (m_bank_latch & 0x03) << 13] = m_write_latch;
- }
+ m_ram[(offset & 0x1fff) | (m_bank_latch & 0x03) << 13] = m_write_latch;
+
data = m_write_latch;
}
break;
@@ -113,3 +183,8 @@ uint8_t bbc_pmsgenie_device::read(offs_t offset)
return data;
}
+
+} // anonymous namespace
+
+
+DEFINE_DEVICE_TYPE_PRIVATE(BBC_PMSGENIE, device_bbc_rom_interface, bbc_pmsgenie_device, "bbc_pmsgenie", "PMS Genie ROM Board")
diff --git a/src/devices/bus/bbc/rom/genie.h b/src/devices/bus/bbc/rom/genie.h
index 82813b2b166..ec57e4a0492 100644
--- a/src/devices/bus/bbc/rom/genie.h
+++ b/src/devices/bus/bbc/rom/genie.h
@@ -1,11 +1,5 @@
// license:BSD-3-Clause
// copyright-holders:Nigel Barnes
-/***************************************************************************
-
- BBC Micro ROM carrier boards
-
-***************************************************************************/
-
#ifndef MAME_BUS_BBC_ROM_GENIE_H
#define MAME_BUS_BBC_ROM_GENIE_H
@@ -14,35 +8,6 @@
#include "slot.h"
-//**************************************************************************
-// TYPE DEFINITIONS
-//**************************************************************************
-
-// ======================> bbc_genie_device
-
-class bbc_pmsgenie_device : public device_t,
- public device_bbc_rom_interface
-{
-public:
- // construction/destruction
- bbc_pmsgenie_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
-
-protected:
- // device-level overrides
- virtual void device_start() override;
-
- // device_bbc_rom_interface overrides
- virtual uint8_t read(offs_t offset) override;
- virtual uint32_t get_rom_size() override { return 0x4000; }
-
-private:
- uint8_t m_write_latch;
- uint8_t m_bank_latch;
-};
-
-
-// device type definition
-DECLARE_DEVICE_TYPE(BBC_PMSGENIE, bbc_pmsgenie_device)
-
+DECLARE_DEVICE_TYPE(BBC_PMSGENIE, device_bbc_rom_interface)
#endif // MAME_BUS_BBC_ROM_GENIE_H
diff --git a/src/devices/bus/bbc/rom/nvram.cpp b/src/devices/bus/bbc/rom/nvram.cpp
new file mode 100644
index 00000000000..0d24f30c8bd
--- /dev/null
+++ b/src/devices/bus/bbc/rom/nvram.cpp
@@ -0,0 +1,58 @@
+// license:BSD-3-Clause
+// copyright-holders:Nigel Barnes
+/***************************************************************************
+
+ BBC Micro Sideways RAM (Battery Backup) emulation
+
+***************************************************************************/
+
+#include "emu.h"
+#include "nvram.h"
+
+
+//**************************************************************************
+// DEVICE DEFINITIONS
+//**************************************************************************
+
+DEFINE_DEVICE_TYPE(BBC_NVRAM, bbc_nvram_device, "bbc_nvram", "BBC Micro Sideways RAM (Battery Backup)")
+
+//**************************************************************************
+// LIVE DEVICE
+//**************************************************************************
+
+//-------------------------------------------------
+// bbc_nvram_device - constructor
+//-------------------------------------------------
+
+bbc_nvram_device::bbc_nvram_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
+ : device_t(mconfig, BBC_NVRAM, tag, owner, clock)
+ , device_bbc_rom_interface(mconfig, *this)
+{
+}
+
+//-------------------------------------------------
+// device_start - device-specific startup
+//-------------------------------------------------
+
+void bbc_nvram_device::device_start()
+{
+ nvram_alloc(0x4000);
+}
+
+//-------------------------------------------------
+// read
+//-------------------------------------------------
+
+uint8_t bbc_nvram_device::read(offs_t offset)
+{
+ return get_nvram_base()[offset & (get_nvram_size() - 1)];
+}
+
+//-------------------------------------------------
+// write
+//-------------------------------------------------
+
+void bbc_nvram_device::write(offs_t offset, uint8_t data)
+{
+ get_nvram_base()[offset & (get_nvram_size() - 1)] = data;
+}
diff --git a/src/devices/bus/bbc/rom/nvram.h b/src/devices/bus/bbc/rom/nvram.h
new file mode 100644
index 00000000000..25f7c58acd2
--- /dev/null
+++ b/src/devices/bus/bbc/rom/nvram.h
@@ -0,0 +1,42 @@
+// license:BSD-3-Clause
+// copyright-holders:Nigel Barnes
+/***************************************************************************
+
+ BBC Micro Sideways RAM (Battery Backup) emulation
+
+***************************************************************************/
+
+#ifndef MAME_BUS_BBC_ROM_NVRAM_H
+#define MAME_BUS_BBC_ROM_NVRAM_H
+
+#pragma once
+
+#include "slot.h"
+
+//**************************************************************************
+// TYPE DEFINITIONS
+//**************************************************************************
+
+// ======================> bbc_nvram_device
+
+class bbc_nvram_device : public device_t,
+ public device_bbc_rom_interface
+{
+public:
+ // construction/destruction
+ bbc_nvram_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
+
+protected:
+ // device-level overrides
+ virtual void device_start() override ATTR_COLD;
+
+ // device_bbc_rom_interface overrides
+ virtual uint8_t read(offs_t offset) override;
+ virtual void write(offs_t offset, uint8_t data) override;
+};
+
+
+// device type definition
+DECLARE_DEVICE_TYPE(BBC_NVRAM, bbc_nvram_device)
+
+#endif // MAME_BUS_BBC_ROM_NVRAM_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..faf14e73e54 100644
--- a/src/devices/bus/bbc/rom/pal.h
+++ b/src/devices/bus/bbc/rom/pal.h
@@ -28,7 +28,7 @@ protected:
bbc_pal_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_start() override ATTR_COLD;
// device_bbc_rom_interface overrides
virtual uint32_t get_rom_size() override { return 0x4000; }
@@ -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/ram.cpp b/src/devices/bus/bbc/rom/ram.cpp
index 0d626955812..bbe5d956006 100644
--- a/src/devices/bus/bbc/rom/ram.cpp
+++ b/src/devices/bus/bbc/rom/ram.cpp
@@ -36,6 +36,7 @@ bbc_ram_device::bbc_ram_device(const machine_config &mconfig, const char *tag, d
void bbc_ram_device::device_start()
{
+ ram_alloc(0x8000);
}
//-------------------------------------------------
diff --git a/src/devices/bus/bbc/rom/ram.h b/src/devices/bus/bbc/rom/ram.h
index 85267147a35..39a3e49a817 100644
--- a/src/devices/bus/bbc/rom/ram.h
+++ b/src/devices/bus/bbc/rom/ram.h
@@ -28,7 +28,7 @@ public:
protected:
// device-level overrides
- virtual void device_start() override;
+ virtual void device_start() override ATTR_COLD;
// device_bbc_rom_interface overrides
virtual uint8_t read(offs_t offset) override;
diff --git a/src/devices/bus/bbc/rom/rom.cpp b/src/devices/bus/bbc/rom/rom.cpp
index f798de11c6a..f419998510b 100644
--- a/src/devices/bus/bbc/rom/rom.cpp
+++ b/src/devices/bus/bbc/rom/rom.cpp
@@ -44,7 +44,5 @@ void bbc_rom_device::device_start()
uint8_t bbc_rom_device::read(offs_t offset)
{
- uint32_t size = std::min((int32_t)get_rom_size(), 0x4000);
-
- return get_rom_base()[offset & (size - 1)];
+ return get_rom_base()[offset & (get_rom_size() - 1)];
}
diff --git a/src/devices/bus/bbc/rom/rom.h b/src/devices/bus/bbc/rom/rom.h
index 282e5471781..0d1a7159278 100644
--- a/src/devices/bus/bbc/rom/rom.h
+++ b/src/devices/bus/bbc/rom/rom.h
@@ -28,7 +28,7 @@ public:
protected:
// device-level overrides
- virtual void device_start() override;
+ virtual void device_start() override ATTR_COLD;
// device_bbc_rom_interface overrides
virtual uint8_t read(offs_t offset) override;
diff --git a/src/devices/bus/bbc/rom/rtc.cpp b/src/devices/bus/bbc/rom/rtc.cpp
index 7d73c24b53e..e2c34beb20d 100644
--- a/src/devices/bus/bbc/rom/rtc.cpp
+++ b/src/devices/bus/bbc/rom/rtc.cpp
@@ -33,8 +33,8 @@ void bbc_stlrtc_device::device_add_mconfig(machine_config &config)
void bbc_pmsrtc_device::device_add_mconfig(machine_config &config)
{
- /* Dallas DS1216 SmartWatch RAM */
- DS1315(config, m_rtc, 0);
+ /* Dallas DS1216 SmartWatch ROM */
+ DS1216E(config, m_rtc);
}
//**************************************************************************
@@ -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;
@@ -107,18 +107,10 @@ uint8_t bbc_pmsrtc_device::read(offs_t offset)
{
uint8_t data = get_rom_base()[offset & 0x1fff];
- switch (offset)
- {
- case 0x00:
- data |= m_rtc->read_0();
- break;
- case 0x01:
- data |= m_rtc->read_1();
- break;
- case 0x04:
- if (m_rtc->chip_enable())
- data = m_rtc->read_data() & 0x01;
- break;
- }
+ if (m_rtc->ceo_r())
+ data = m_rtc->read(offset);
+ else
+ m_rtc->read(offset);
+
return data;
}
diff --git a/src/devices/bus/bbc/rom/rtc.h b/src/devices/bus/bbc/rom/rtc.h
index d37b2174b9b..d975fed41ce 100644
--- a/src/devices/bus/bbc/rom/rtc.h
+++ b/src/devices/bus/bbc/rom/rtc.h
@@ -15,7 +15,7 @@
#include "slot.h"
#include "machine/mc146818.h"
-#include "machine/ds1315.h"
+#include "machine/ds1215.h"
//**************************************************************************
// TYPE DEFINITIONS
@@ -32,9 +32,9 @@ public:
protected:
// device-level overrides
- virtual void device_add_mconfig(machine_config &config) override;
+ virtual void device_add_mconfig(machine_config &config) override ATTR_COLD;
- virtual void device_start() override;
+ virtual void device_start() override ATTR_COLD;
// device_bbc_rom_interface overrides
virtual uint8_t read(offs_t offset) override;
@@ -54,15 +54,15 @@ public:
protected:
// device-level overrides
- virtual void device_add_mconfig(machine_config &config) override;
+ virtual void device_add_mconfig(machine_config &config) override ATTR_COLD;
- virtual void device_start() override;
+ virtual void device_start() override ATTR_COLD;
// device_bbc_rom_interface overrides
virtual uint8_t read(offs_t offset) override;
private:
- required_device<ds1315_device> m_rtc;
+ required_device<ds1216e_device> m_rtc;
};
// device type definition
diff --git a/src/devices/bus/bbc/rom/slot.cpp b/src/devices/bus/bbc/rom/slot.cpp
index e421a1c520e..6ef0dddf180 100644
--- a/src/devices/bus/bbc/rom/slot.cpp
+++ b/src/devices/bus/bbc/rom/slot.cpp
@@ -27,7 +27,7 @@ DEFINE_DEVICE_TYPE(BBC_ROMSLOT32, bbc_romslot32_device, "bbc_romslot32", "BBC Mi
//-------------------------------------------------
device_bbc_rom_interface::device_bbc_rom_interface(const machine_config &mconfig, device_t &device)
- : device_slot_card_interface(mconfig, device)
+ : device_interface(device, "bbcrom")
, m_rom(nullptr)
, m_rom_size(0)
{
@@ -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;
}
}
@@ -72,6 +72,7 @@ void device_bbc_rom_interface::ram_alloc(uint32_t size)
void device_bbc_rom_interface::nvram_alloc(uint32_t size)
{
m_nvram.resize(size);
+ device().save_item(NAME(m_nvram));
}
//**************************************************************************
@@ -83,8 +84,8 @@ void device_bbc_rom_interface::nvram_alloc(uint32_t size)
//-------------------------------------------------
bbc_romslot_device::bbc_romslot_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_image_interface(mconfig, *this)
- , device_slot_interface(mconfig, *this)
+ , device_rom_image_interface(mconfig, *this)
+ , device_single_card_slot_interface<device_bbc_rom_interface>(mconfig, *this)
, m_cart(nullptr)
{
}
@@ -105,7 +106,7 @@ bbc_romslot32_device::bbc_romslot32_device(const machine_config &mconfig, const
void bbc_romslot_device::device_start()
{
- m_cart = dynamic_cast<device_bbc_rom_interface *>(get_card_device());
+ m_cart = get_card_device();
}
@@ -113,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());
@@ -132,6 +130,8 @@ image_init_result bbc_romslot_device::call_load()
else
memcpy(m_cart->get_rom_base(), get_software_region("rom"), size);
+ m_cart->decrypt_rom();
+
if (get_software_region("ram"))
m_cart->ram_alloc(get_software_region_length("ram"));
@@ -139,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());
}
//-------------------------------------------------
@@ -206,10 +206,13 @@ void bbc_romslot_device::write(offs_t offset, uint8_t data)
#include "rom.h"
#include "ram.h"
+#include "nvram.h"
+#include "datagem.h"
#include "dfs.h"
#include "genie.h"
+//#include "gommc.h"
#include "pal.h"
-//#include "replay.h"
+//#include "ramagic.h"
#include "rtc.h"
@@ -217,6 +220,7 @@ void bbc_rom_devices(device_slot_interface &device)
{
device.option_add_internal("rom", BBC_ROM);
device.option_add_internal("ram", BBC_RAM);
+ device.option_add_internal("nvram", BBC_NVRAM);
device.option_add_internal("cciword", BBC_CCIWORD);
device.option_add_internal("ccibase", BBC_CCIBASE);
device.option_add_internal("ccispell", BBC_CCISPELL);
@@ -226,9 +230,12 @@ void bbc_rom_devices(device_slot_interface &device)
device.option_add_internal("palabep", BBC_PALABEP);
device.option_add_internal("palabe", BBC_PALABE);
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("mrme00", BBC_MRME00);
- //device.option_add_internal("replay", BBC_REPLAY);
+ //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 40818d9e619..c36eb73fb28 100644
--- a/src/devices/bus/bbc/rom/slot.h
+++ b/src/devices/bus/bbc/rom/slot.h
@@ -11,7 +11,7 @@
#pragma once
-#include "softlist_dev.h"
+#include "imagedev/cartrom.h"
#define BBC_ROM_REGION_TAG ":cart:rom"
@@ -25,31 +25,29 @@
class device_bbc_rom_interface;
class bbc_romslot_device : public device_t,
- public device_image_interface,
- public device_slot_interface
+ public device_rom_image_interface,
+ 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 const software_list_loader &get_software_list_loader() const override { return rom_software_list_loader::instance(); }
-
- virtual iodevice_t image_type() const override { return IO_ROM; }
- virtual bool is_readable() const override { return 1; }
- virtual bool is_writeable() const override { return 0; }
- virtual bool is_creatable() const override { return 0; }
- virtual bool must_be_loaded() const override { return 0; }
- virtual bool is_reset_on_load() const override { return 1; }
- virtual const char *image_interface() const override { return "bbc_rom"; }
- virtual const char *file_extensions() const override { return "rom,bin"; }
-
- // slot interface overrides
+
+ 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"; }
+
+ // device_slot_interface implementation
virtual std::string get_default_card_software(get_default_card_software_hook &hook) const override;
// reading and writing
uint8_t read(offs_t offset);
void write(offs_t offset, uint8_t data);
+ void set_fixed_ram(bool fixed) { this->set_fixed(fixed); this->set_user_loadable(!fixed); }
+
+ virtual bool present() { return is_loaded() || loaded_through_softlist() || !user_loadable(); }
+
uint32_t get_rom_size();
uint32_t get_slot_size() const { return m_slot_size; }
@@ -57,8 +55,8 @@ 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
- virtual void device_start() override;
+ // device_t implementation
+ virtual void device_start() override ATTR_COLD;
uint32_t m_slot_size;
@@ -109,7 +107,7 @@ public:
// ======================> device_bbc_rom_interface
-class device_bbc_rom_interface : public device_slot_card_interface
+class device_bbc_rom_interface : public device_interface
{
public:
// construction/destruction
@@ -117,7 +115,7 @@ public:
// reading and writing
virtual uint8_t read(offs_t offset) { return 0xff; }
- virtual void write(offs_t offset, uint8_t data) { m_device.logerror("unhandled ROM write to %04X = %02X\n", offset | 0x8000, data); }
+ virtual void write(offs_t offset, uint8_t data) { device().logerror("unhandled ROM write to %04X = %02X\n", offset | 0x8000, data); }
void rom_alloc(uint32_t size, const char *tag);
void ram_alloc(uint32_t size);
@@ -132,6 +130,9 @@ public:
uint8_t* get_nvram_base() { return &m_nvram[0]; }
uint32_t get_nvram_size() { return m_nvram.size(); }
+ // decrypt data lines
+ virtual void decrypt_rom() { }
+
protected:
device_bbc_rom_interface(const machine_config &mconfig, device_t &device);
diff --git a/src/devices/bus/bbc/tube/tube.cpp b/src/devices/bus/bbc/tube/tube.cpp
index 602ea3c845a..574fb38ee2d 100644
--- a/src/devices/bus/bbc/tube/tube.cpp
+++ b/src/devices/bus/bbc/tube/tube.cpp
@@ -10,7 +10,6 @@
#include "tube.h"
-
//**************************************************************************
// DEVICE DEFINITIONS
//**************************************************************************
@@ -28,9 +27,9 @@ 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_slot_card_interface(mconfig, 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());
}
@@ -42,72 +41,68 @@ device_bbc_tube_interface::device_bbc_tube_interface(const machine_config &mconf
// bbc_tube_slot_device - constructor
//-------------------------------------------------
-bbc_tube_slot_device::bbc_tube_slot_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) :
- device_t(mconfig, BBC_TUBE_SLOT, tag, owner, clock),
- device_slot_interface(mconfig, *this),
- m_card(nullptr),
- m_irq_handler(*this)
+bbc_tube_slot_device::bbc_tube_slot_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
+ : device_t(mconfig, BBC_TUBE_SLOT, tag, owner, clock)
+ , device_single_card_slot_interface<device_bbc_tube_interface>(mconfig, *this)
+ , m_card(nullptr)
+ , m_irq_handler(*this)
+ , m_insert_rom(true)
{
}
//-------------------------------------------------
-// device_validity_check -
+// device_start - device-specific startup
//-------------------------------------------------
-void bbc_tube_slot_device::device_validity_check(validity_checker &valid) const
+void bbc_tube_slot_device::device_start()
{
- device_t *const carddev = get_card_device();
- if (carddev && !dynamic_cast<device_bbc_tube_interface *>(carddev))
- osd_printf_error("Card device %s (%s) does not implement device_bbc_tube_interface\n", carddev->tag(), carddev->name());
+ m_card = get_card_device();
}
//-------------------------------------------------
-// device_start - device-specific startup
+// host_r
//-------------------------------------------------
-void bbc_tube_slot_device::device_start()
+uint8_t bbc_tube_slot_device::host_r(offs_t offset)
{
- device_t *const carddev = get_card_device();
- m_card = dynamic_cast<device_bbc_tube_interface *>(carddev);
- if (carddev && !m_card)
- fatalerror("Card device %s (%s) does not implement device_bbc_tube_interface\n", carddev->tag(), carddev->name());
-
- // resolve callbacks
- m_irq_handler.resolve_safe();
+ if (m_card)
+ return m_card->host_r(offset);
+ else
+ return 0xfe;
}
-
//-------------------------------------------------
-// device_reset - device-specific reset
+// host_w
//-------------------------------------------------
-void bbc_tube_slot_device::device_reset()
+void bbc_tube_slot_device::host_w(offs_t offset, uint8_t data)
{
+ if (m_card)
+ m_card->host_w(offset, data);
}
-
//-------------------------------------------------
-// host_r
+// jim_r
//-------------------------------------------------
-uint8_t bbc_tube_slot_device::host_r(offs_t offset)
+uint8_t bbc_tube_slot_device::jim_r(offs_t offset)
{
if (m_card)
- return m_card->host_r(offset);
+ return m_card->jim_r(offset);
else
- return 0xfe;
+ return 0xff;
}
//-------------------------------------------------
-// host_w
+// jim_w
//-------------------------------------------------
-void bbc_tube_slot_device::host_w(offs_t offset, uint8_t data)
+void bbc_tube_slot_device::jim_w(offs_t offset, uint8_t data)
{
if (m_card)
- m_card->host_w(offset, data);
+ m_card->jim_w(offset, data);
}
@@ -116,12 +111,15 @@ void bbc_tube_slot_device::host_w(offs_t offset, uint8_t data)
#include "tube_6502.h"
#include "tube_80186.h"
#include "tube_80286.h"
-//#include "tube_a500.h"
+#include "tube_a500.h"
#include "tube_arm.h"
+#include "tube_arm7.h"
#include "tube_casper.h"
+#include "tube_cms6809.h"
+#include "tube_matchbox.h"
//#include "tube_pmsb2p.h"
#include "tube_rc6502.h"
-//#include "tube_x25.h"
+#include "tube_x25.h"
#include "tube_z80.h"
#include "tube_zep100.h"
@@ -133,21 +131,32 @@ void bbc_tube_slot_device::host_w(offs_t offset, uint8_t data)
void bbc_tube_devices(device_slot_interface &device)
{
device.option_add("6502", BBC_TUBE_6502); /* Acorn ANC01 6502 2nd processor */
+ device.option_add("6502p", BBC_TUBE_6502P); /* Acorn 6502 2nd processor (pre-production) */
+ device.option_add("6502e", BBC_TUBE_6502E); /* Acorn Extended 6502 2nd processor */
device.option_add("z80", BBC_TUBE_Z80); /* Acorn ANC04 Z80 2nd processor */
- device.option_add("32016", BBC_TUBE_32016); /* Acorn ANC05 32016 2nd processor */
+ device.option_add("z80w", BBC_TUBE_Z80W); /* Acorn ANC04 Z80 2nd processor (Winchester) */
+ device.option_add("16032", BBC_TUBE_16032); /* Acorn 16032 2nd processor */
+ device.option_add("32016", BBC_TUBE_32016); /* Acorn ANC05 32016 2nd processor */
+ device.option_add("32016l", BBC_TUBE_32016L); /* Acorn Large 32016 2nd processor */
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("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 */
+ device.option_add("matchbox", BBC_TUBE_MATCHBOX); /* Matchbox Co-Processor */
//device.option_add("pmsb2p", BBC_TUBE_PMSB2P); /* PMS B2P-6502 */
- //device.option_add("hdp68k", BBC_TUBE_HDP68K); /* Torch Unicorn (HDP68K) */
- //device.option_add("x25", BBC_TUBE_X25); /* Econet X25 Gateway */
+ device.option_add("pcplus", BBC_TUBE_PCPLUS); /* Solidisk PC-Plus co-processor */
+ device.option_add("x25", BBC_TUBE_X25); /* Econet X25 Gateway */
device.option_add("zep100", BBC_TUBE_ZEP100); /* Torch Z80 Communicator (ZEP100) (Torch) */
- //device.option_add("zep100l", BBC_TUBE_ZEP100L); /* Torch Z80 Communicator (ZEP100) (Model B) */
- //device.option_add("zep100w", BBC_TUBE_ZEP100W); /* Torch Z80 Communicator (ZEP100) (Model B+) */
+ device.option_add("zep100l", BBC_TUBE_ZEP100L); /* Torch Z80 Communicator (ZEP100) (Model B) */
+ device.option_add("zep100w", BBC_TUBE_ZEP100W); /* Torch Z80 Communicator (ZEP100) (Model B+) */
+
/* Acorn ANC21 Universal 2nd Processor Unit */
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("arm7", BBC_TUBE_ARM7); /* Sprow ARM7 co-processor */
device.option_add("rc6502", BBC_TUBE_RC6502); /* ReCo6502 (6502) */
device.option_add("rc65816", BBC_TUBE_RC65816); /* ReCo6502 (65816) */
}
@@ -160,16 +169,24 @@ void bbc_tube_devices(device_slot_interface &device)
void bbc_extube_devices(device_slot_interface &device)
{
device.option_add("6502", BBC_TUBE_6502); /* Acorn ANC01 6502 2nd processor */
+ device.option_add("6502e", BBC_TUBE_6502E); /* Acorn Extended 6502 2nd processor */
device.option_add("z80", BBC_TUBE_Z80); /* Acorn ANC04 Z80 2nd processor */
- device.option_add("32016", BBC_TUBE_32016); /* Acorn ANC05 32016 2nd processor */
+ device.option_add("z80w", BBC_TUBE_Z80W); /* Acorn ANC04 Z80 2nd processor (Winchester) */
+ device.option_add("32016", BBC_TUBE_32016); /* Acorn ANC05 32016 2nd processor */
+ device.option_add("32016l", BBC_TUBE_32016L); /* Acorn Large 32016 2nd processor */
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("matchbox", BBC_TUBE_MATCHBOX); /* Matchbox Co-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) */
+ device.option_add("zep100m", BBC_TUBE_ZEP100M); /* Torch Z80 Communicator (ZEP100) (Master) */
+
/* Acorn ANC21 Universal 2nd Processor Unit */
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("arm7", BBC_TUBE_ARM7); /* Sprow ARM7 co-processor */
device.option_add("rc6502", BBC_TUBE_RC6502); /* ReCo6502 (6502) */
device.option_add("rc65816", BBC_TUBE_RC65816); /* ReCo6502 (65816) */
}
@@ -183,7 +200,7 @@ void bbc_intube_devices(device_slot_interface &device)
{
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("arm7", BBC_TUBE_ARM7); /* Sprow ARM7 co-processor */
+ device.option_add("arm7", BBC_TUBE_ARM7); /* Sprow ARM7 co-processor */
device.option_add("rc6502", BBC_TUBE_RC6502); /* ReCo6502 (6502) */
device.option_add("rc65816", BBC_TUBE_RC65816); /* ReCo6502 (65816) */
}
@@ -196,11 +213,18 @@ void bbc_intube_devices(device_slot_interface &device)
void electron_tube_devices(device_slot_interface &device)
{
device.option_add("6502", BBC_TUBE_6502); /* Acorn ANC01 6502 2nd processor */
+ device.option_add("6502e", BBC_TUBE_6502E); /* Acorn Extended 6502 2nd processor */
device.option_add("z80", BBC_TUBE_Z80); /* Acorn ANC04 Z80 2nd processor */
device.option_add("32016", BBC_TUBE_32016); /* Acorn ANC05 32016 2nd processor */
+ device.option_add("32016l", BBC_TUBE_32016L); /* Acorn Large 32016 2nd processor */
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("matchbox", BBC_TUBE_MATCHBOX); /* Matchbox Co-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) */
device.option_add("rc65816", BBC_TUBE_RC65816); /* ReCo6502 (65816) */
}
diff --git a/src/devices/bus/bbc/tube/tube.h b/src/devices/bus/bbc/tube/tube.h
index e0d66907cb6..49f5025df4b 100644
--- a/src/devices/bus/bbc/tube/tube.h
+++ b/src/devices/bus/bbc/tube/tube.h
@@ -37,66 +37,74 @@
#pragma once
-
//**************************************************************************
// TYPE DEFINITIONS
//**************************************************************************
-
// ======================> bbc_tube_slot_device
class device_bbc_tube_interface;
-class bbc_tube_slot_device : public device_t, public device_slot_interface
+class bbc_tube_slot_device : public device_t, public device_single_card_slot_interface<device_bbc_tube_interface>
{
public:
// construction/destruction
template <typename T>
- bbc_tube_slot_device(machine_config const &mconfig, char const *tag, device_t *owner, T &&slot_options, const char *default_option)
+ bbc_tube_slot_device(machine_config const &mconfig, char const *tag, device_t *owner, T &&slot_options, char const *default_option)
: bbc_tube_slot_device(mconfig, tag, owner)
{
option_reset();
slot_options(*this);
set_default_option(default_option);
set_fixed(false);
+ set_insert_rom(true);
}
bbc_tube_slot_device(machine_config const &mconfig, char const *tag, device_t *owner, uint32_t clock = 0);
+ void set_insert_rom(bool insert_rom) { m_insert_rom = insert_rom; }
+ bool insert_rom() { return m_insert_rom; }
+
// callbacks
auto irq_handler() { return m_irq_handler.bind(); }
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); }
+ // JIM is not accessible on the Tube, but the PMS-B2P device connects to the Tube and also the NPGFD line of the 1MHz bus
+ uint8_t jim_r(offs_t offset);
+ void jim_w(offs_t offset, uint8_t data);
+
+ void irq_w(int state) { m_irq_handler(state); }
protected:
- // device-level overrides
- virtual void device_validity_check(validity_checker &valid) const override;
- virtual void device_start() override;
- virtual void device_reset() override;
+ // device_t overrides
+ virtual void device_start() override ATTR_COLD;
device_bbc_tube_interface *m_card;
private:
devcb_write_line m_irq_handler;
+
+ bool m_insert_rom;
};
// ======================> device_bbc_tube_interface
-class device_bbc_tube_interface : public device_slot_card_interface
+class device_bbc_tube_interface : public device_interface
{
public:
// reading and writing
virtual uint8_t host_r(offs_t offset) { return 0xfe; }
virtual void host_w(offs_t offset, uint8_t data) { }
+ virtual uint8_t jim_r(offs_t offset) { return 0xff; }
+ virtual void jim_w(offs_t offset, uint8_t data) { }
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 7b6ac355e42..01019302aec 100644
--- a/src/devices/bus/bbc/tube/tube_32016.cpp
+++ b/src/devices/bus/bbc/tube/tube_32016.cpp
@@ -21,6 +21,7 @@
#include "emu.h"
#include "tube_32016.h"
+
#include "softlist_dev.h"
@@ -29,6 +30,8 @@
//**************************************************************************
DEFINE_DEVICE_TYPE(BBC_TUBE_32016, bbc_tube_32016_device, "bbc_tube_32016", "Acorn 32016 2nd processor")
+DEFINE_DEVICE_TYPE(BBC_TUBE_16032, bbc_tube_16032_device, "bbc_tube_16032", "Acorn 16032 2nd processor (prototype)")
+DEFINE_DEVICE_TYPE(BBC_TUBE_32016L, bbc_tube_32016l_device, "bbc_tube_32016l", "Acorn Large 32016 2nd processor")
//-------------------------------------------------
@@ -37,9 +40,6 @@ DEFINE_DEVICE_TYPE(BBC_TUBE_32016, bbc_tube_32016_device, "bbc_tube_32016", "Aco
void bbc_tube_32016_device::tube_32016_mem(address_map &map)
{
- map(0x000000, 0xffffff).rw(FUNC(bbc_tube_32016_device::read), FUNC(bbc_tube_32016_device::write));
- map(0xf90000, 0xf90001).portr("CONFIG");
- map(0xfffff0, 0xffffff).rw("ula", FUNC(tube_device::parasite_r), FUNC(tube_device::parasite_w)).umask32(0x00ff);
}
//-------------------------------------------------
@@ -47,54 +47,77 @@ void bbc_tube_32016_device::tube_32016_mem(address_map &map)
//-------------------------------------------------
ROM_START(tube_32016)
- ROM_REGION(0x8000, "rom", 0)
- ROM_DEFAULT_BIOS("200")
+ ROM_REGION16_LE(0x8000, "rom", 0)
ROM_SYSTEM_BIOS(0, "200", "Pandora v2.00")
ROMX_LOAD("pan200lo.rom", 0x0000, 0x4000, CRC(b1980fd0) SHA1(8084f8896cd22953abefbd43c51e1a422b30e28d), ROM_SKIP(1) | ROM_BIOS(0)) // 0201-764-02 Pandora Lo
ROMX_LOAD("pan200hi.rom", 0x0001, 0x4000, CRC(cab98d6b) SHA1(dfad1f4180c50757a74fcfe3a0ee7d7b48eb1bee), ROM_SKIP(1) | ROM_BIOS(0)) // 0201-763-02 Pandora Hi
ROM_SYSTEM_BIOS(1, "100", "Pandora v1.00")
- ROMX_LOAD("pan100.rom", 0x0000, 0x8000, BAD_DUMP CRC(75333006) SHA1(996cd120103039390c9b979b16c327bb95da72e4), ROM_BIOS(1)) // 0201-763-01, 0201-764-01 Pandora
+ ROMX_LOAD("pan100lo.rom", 0x0000, 0x2000, CRC(101e8aca) SHA1(4998e64afe98b2f227df6daa7ae0af512ce8907a), ROM_SKIP(1) | ROM_BIOS(1)) // 0201-764-01 Pandora Lo
+ ROM_RELOAD( 0x4000, 0x2000)
+ ROMX_LOAD("pan100hi.rom", 0x0001, 0x2000, CRC(139de9ed) SHA1(1871e65c9ebd3eac835b0317b0ad8272ff207c4b), ROM_SKIP(1) | ROM_BIOS(1)) // 0201-763-01 Pandora Hi
+ ROM_RELOAD( 0x4001, 0x2000)
ROM_SYSTEM_BIOS(2, "061", "Pandora v0.61")
ROMX_LOAD("pan061lo.rom", 0x0000, 0x4000, CRC(6f801b35) SHA1(ce31f7c10603f3d15a06a8e32bde40df0639e446), ROM_SKIP(1) | ROM_BIOS(2))
ROMX_LOAD("pan061hi.rom", 0x0001, 0x4000, CRC(c00b1ab0) SHA1(e6a705232278c518340ddc69ea51af91965fa332), ROM_SKIP(1) | ROM_BIOS(2))
ROM_END
+ROM_START(tube_16032)
+ ROM_REGION16_LE(0x8000, "rom", 0)
+ ROM_SYSTEM_BIOS(0, "052", "Tiny Kernel v0.52")
+ ROMX_LOAD("tk052lo.rom", 0x0000, 0x2000, CRC(4daa7bfd) SHA1(c5f3dffc87f828e2420a036b6bc49ec07d712010), ROM_SKIP(1) | ROM_BIOS(0))
+ ROM_RELOAD( 0x4000, 0x2000)
+ ROMX_LOAD("tk052hi.rom", 0x0001, 0x2000, CRC(8611ff90) SHA1(bb1852fb2f3e7b3eb135ef52b8cbb6ebc521831a), ROM_SKIP(1) | ROM_BIOS(0))
+ ROM_RELOAD( 0x4001, 0x2000)
+ ROM_SYSTEM_BIOS(1, "060", "Pandora v0.60")
+ ROMX_LOAD("pan060lo.rom", 0x0000, 0x2000, CRC(76c9984e) SHA1(05346f9dbcba52ed12d8ce3a84cacc522ae07a67), ROM_SKIP(1) | ROM_BIOS(1))
+ ROM_RELOAD( 0x4000, 0x2000)
+ ROMX_LOAD("pan060hi.rom", 0x0001, 0x2000, CRC(2d49514c) SHA1(2ec67a74a81811d8c4ffaa3583e7a9c5fb2485ba), ROM_SKIP(1) | ROM_BIOS(1))
+ ROM_RELOAD( 0x4001, 0x2000)
+ROM_END
+
+ROM_START(tube_32016l)
+ ROM_REGION16_LE(0x8000, "rom", 0)
+ ROM_SYSTEM_BIOS(0, "200", "Pandora v2.00")
+ ROMX_LOAD("pan200lo.rom", 0x0000, 0x4000, CRC(b1980fd0) SHA1(8084f8896cd22953abefbd43c51e1a422b30e28d), ROM_SKIP(1) | ROM_BIOS(0)) // 0201-764-02 Pandora Lo
+ ROMX_LOAD("pan200hi.rom", 0x0001, 0x4000, CRC(cab98d6b) SHA1(dfad1f4180c50757a74fcfe3a0ee7d7b48eb1bee), ROM_SKIP(1) | ROM_BIOS(0)) // 0201-763-02 Pandora Hi
+ROM_END
+
//-------------------------------------------------
// INPUT_PORTS( tube_32016 )
//-------------------------------------------------
static INPUT_PORTS_START(tube_32016)
PORT_START("CONFIG")
- PORT_DIPNAME(0x80, 0x80, "H") PORT_DIPLOCATION("LKS:1")
- PORT_DIPSETTING(0x80, "FPU")
+ PORT_DIPNAME(0x01, 0x01, "H") PORT_DIPLOCATION("LKS:1")
+ PORT_DIPSETTING(0x01, "FPU")
PORT_DIPSETTING(0x00, "No FPU")
- PORT_DIPNAME(0x40, 0x00, "G") PORT_DIPLOCATION("LKS:2")
- PORT_DIPSETTING(0x40, "MMU")
+ PORT_DIPNAME(0x02, 0x00, "G") PORT_DIPLOCATION("LKS:2")
+ PORT_DIPSETTING(0x02, "MMU")
PORT_DIPSETTING(0x00, "No MMU")
- PORT_DIPNAME(0x20, 0x00, "F") PORT_DIPLOCATION("LKS:3")
- PORT_DIPSETTING(0x20, "Reserved")
+ PORT_DIPNAME(0x04, 0x00, "F") PORT_DIPLOCATION("LKS:3")
+ PORT_DIPSETTING(0x04, "Reserved")
PORT_DIPSETTING(0x00, "Reserved")
- PORT_DIPNAME(0x10, 0x00, "E") PORT_DIPLOCATION("LKS:4")
- PORT_DIPSETTING(0x10, "Reserved")
+ PORT_DIPNAME(0x08, 0x00, "E") PORT_DIPLOCATION("LKS:4")
+ PORT_DIPSETTING(0x08, "Reserved")
PORT_DIPSETTING(0x00, "Reserved")
- PORT_DIPNAME(0x08, 0x00, "D") PORT_DIPLOCATION("LKS:5")
- PORT_DIPSETTING(0x08, "Reserved")
+ PORT_DIPNAME(0x10, 0x00, "D") PORT_DIPLOCATION("LKS:5")
+ PORT_DIPSETTING(0x10, "Reserved")
PORT_DIPSETTING(0x00, "Reserved")
- PORT_DIPNAME(0x04, 0x00, "C") PORT_DIPLOCATION("LKS:6")
- PORT_DIPSETTING(0x04, "Reserved")
+ PORT_DIPNAME(0x20, 0x00, "C") PORT_DIPLOCATION("LKS:6")
+ PORT_DIPSETTING(0x20, "Reserved")
PORT_DIPSETTING(0x00, "Reserved")
- PORT_DIPNAME(0x02, 0x00, "B") PORT_DIPLOCATION("LKS:7")
- PORT_DIPSETTING(0x02, "Reserved")
+ PORT_DIPNAME(0x40, 0x00, "B") PORT_DIPLOCATION("LKS:7")
+ PORT_DIPSETTING(0x40, "Reserved")
PORT_DIPSETTING(0x00, "Reserved")
- PORT_DIPNAME(0x01, 0x00, "A") PORT_DIPLOCATION("LKS:8")
- PORT_DIPSETTING(0x01, "Reserved")
+ PORT_DIPNAME(0x80, 0x00, "A") PORT_DIPLOCATION("LKS:8")
+ PORT_DIPSETTING(0x80, "Reserved")
PORT_DIPSETTING(0x00, "Reserved")
INPUT_PORTS_END
@@ -106,18 +129,40 @@ void bbc_tube_32016_device::device_add_mconfig(machine_config &config)
{
NS32016(config, m_maincpu, 12_MHz_XTAL / 2);
m_maincpu->set_addrmap(AS_PROGRAM, &bbc_tube_32016_device::tube_32016_mem);
+ m_maincpu->set_fpu(m_ns32081);
+
+ NS32081(config, m_ns32081, 12_MHz_XTAL / 2);
TUBE(config, m_ula);
m_ula->pnmi_handler().set_inputline(m_maincpu, INPUT_LINE_NMI);
m_ula->pirq_handler().set_inputline(m_maincpu, INPUT_LINE_IRQ0);
+ m_ula->prst_handler().set(FUNC(bbc_tube_32016_device::prst_w));
- /* internal ram */
- RAM(config, m_ram).set_default_size("1M").set_default_value(0);
+ RAM(config, m_ram).set_default_size("1M").set_extra_options("256K").set_default_value(0);
- /* software lists */
SOFTWARE_LIST(config, "flop_ls_32016").set_original("bbc_flop_32016");
}
+
+void bbc_tube_16032_device::device_add_mconfig(machine_config &config)
+{
+ bbc_tube_32016_device::device_add_mconfig(config);
+
+ m_maincpu->set_clock(16_MHz_XTAL / 2); // also seen with a 8MHz crystal
+
+ m_ram->set_default_size("256K").set_extra_options("1M").set_default_value(0);
+}
+
+
+void bbc_tube_32016l_device::device_add_mconfig(machine_config &config)
+{
+ bbc_tube_32016_device::device_add_mconfig(config);
+
+ m_maincpu->set_clock(16_MHz_XTAL / 2);
+
+ m_ram->set_default_size("4M").set_extra_options("1M").set_default_value(0);
+}
+
//-------------------------------------------------
// rom_region - device-specific ROM region
//-------------------------------------------------
@@ -127,6 +172,16 @@ const tiny_rom_entry *bbc_tube_32016_device::device_rom_region() const
return ROM_NAME( tube_32016 );
}
+const tiny_rom_entry *bbc_tube_16032_device::device_rom_region() const
+{
+ return ROM_NAME( tube_16032 );
+}
+
+const tiny_rom_entry *bbc_tube_32016l_device::device_rom_region() const
+{
+ return ROM_NAME( tube_32016l );
+}
+
//-------------------------------------------------
// input_ports - device-specific input ports
//-------------------------------------------------
@@ -144,14 +199,29 @@ ioport_constructor bbc_tube_32016_device::device_input_ports() const
// bbc_tube_32016_device - constructor
//-------------------------------------------------
-bbc_tube_32016_device::bbc_tube_32016_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
- : device_t(mconfig, BBC_TUBE_32016, tag, owner, clock)
+bbc_tube_32016_device::bbc_tube_32016_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_ns32081(*this, "ns32081")
, m_ula(*this, "ula")
, m_ram(*this, "ram")
, m_rom(*this, "rom")
- , m_rom_enabled(true)
+{
+}
+
+bbc_tube_32016_device::bbc_tube_32016_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
+ : bbc_tube_32016_device(mconfig, BBC_TUBE_32016, tag, owner, clock)
+{
+}
+
+bbc_tube_16032_device::bbc_tube_16032_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
+ : bbc_tube_32016_device(mconfig, BBC_TUBE_16032, tag, owner, clock)
+{
+}
+
+bbc_tube_32016l_device::bbc_tube_32016l_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
+ : bbc_tube_32016_device(mconfig, BBC_TUBE_32016L, tag, owner, clock)
{
}
@@ -169,7 +239,28 @@ void bbc_tube_32016_device::device_start()
void bbc_tube_32016_device::device_reset()
{
- m_rom_enabled = true;
+ address_space &program = m_maincpu->space(AS_PROGRAM);
+
+ // address map during booting
+ program.install_rom(0x000000, 0x007fff, 0xff8000, m_rom->base());
+
+ m_rom_shadow_tap.remove();
+ m_rom_shadow_tap = program.install_write_tap(
+ 0x000000, 0xffffff,
+ "rom_shadow_w",
+ [this] (offs_t offset, u16 &data, u16 mem_mask)
+ {
+ // delete this tap
+ m_rom_shadow_tap.remove();
+
+ // address map after booting
+ m_maincpu->space(AS_PROGRAM).nop_readwrite(0x000000, 0xffffff);
+ m_maincpu->space(AS_PROGRAM).install_ram(0x000000, m_ram->mask(), 0x7fffff ^ m_ram->mask(), m_ram->pointer());
+ m_maincpu->space(AS_PROGRAM).install_rom(0xf00000, 0xf07fff, 0x038000, m_rom->base());
+ m_maincpu->space(AS_PROGRAM).install_read_port(0xf90000, 0xf90001, 0x00fffe, "CONFIG");
+ m_maincpu->space(AS_PROGRAM).install_readwrite_handler(0xfffff0, 0xffffff, read8sm_delegate(*m_ula, FUNC(tube_device::parasite_r)), write8sm_delegate(*m_ula, FUNC(tube_device::parasite_w)), 0xff);
+ },
+ &m_rom_shadow_tap);
}
@@ -177,34 +268,19 @@ void bbc_tube_32016_device::device_reset()
// IMPLEMENTATION
//**************************************************************************
-uint8_t bbc_tube_32016_device::host_r(offs_t offset)
+void bbc_tube_32016_device::prst_w(int state)
{
- return m_ula->host_r(offset);
-}
+ device_reset();
-void bbc_tube_32016_device::host_w(offs_t offset, uint8_t data)
-{
- m_ula->host_w(offset, data);
+ m_maincpu->set_input_line(INPUT_LINE_RESET, state);
}
-
-READ8_MEMBER(bbc_tube_32016_device::read)
+uint8_t bbc_tube_32016_device::host_r(offs_t offset)
{
- uint16_t data = 0xffff;
-
- if (m_rom_enabled)
- data = m_rom->base()[offset & 0x3fff];
- else if (offset < m_ram->size())
- data = m_ram->pointer()[offset];
-
- return data;
+ return m_ula->host_r(offset);
}
-WRITE8_MEMBER(bbc_tube_32016_device::write)
+void bbc_tube_32016_device::host_w(offs_t offset, uint8_t data)
{
- /* clear ROM select on first write */
- if (!machine().side_effects_disabled()) m_rom_enabled = false;
-
- if (offset < m_ram->size())
- m_ram->pointer()[offset] = data;
+ m_ula->host_w(offset, data);
}
diff --git a/src/devices/bus/bbc/tube/tube_32016.h b/src/devices/bus/bbc/tube/tube_32016.h
index 864b8173703..4d7fe4cb260 100644
--- a/src/devices/bus/bbc/tube/tube_32016.h
+++ b/src/devices/bus/bbc/tube/tube_32016.h
@@ -12,12 +12,14 @@
**********************************************************************/
+#ifndef MAME_BUS_BBC_TUBE_TUBE_32016_H
+#define MAME_BUS_BBC_TUBE_TUBE_32016_H
-#ifndef MAME_BUS_BBC_TUBE_32016_H
-#define MAME_BUS_BBC_TUBE_32016_H
+#pragma once
#include "tube.h"
#include "cpu/ns32000/ns32000.h"
+#include "machine/ns32081.h"
#include "machine/ram.h"
#include "machine/tube.h"
@@ -36,36 +38,62 @@ public:
bbc_tube_32016_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
protected:
+ bbc_tube_32016_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_start() override ATTR_COLD;
+ virtual void device_reset() override ATTR_COLD;
// 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 void device_add_mconfig(machine_config &config) override ATTR_COLD;
+ virtual const tiny_rom_entry *device_rom_region() const override ATTR_COLD;
+ virtual ioport_constructor device_input_ports() const override ATTR_COLD;
virtual uint8_t host_r(offs_t offset) override;
virtual void host_w(offs_t offset, uint8_t data) override;
-private:
- required_device<ns32016_cpu_device> m_maincpu;
+ required_device<ns32016_device> m_maincpu;
+ required_device<ns32081_device> m_ns32081;
required_device<tube_device> m_ula;
required_device<ram_device> m_ram;
required_memory_region m_rom;
- DECLARE_READ8_MEMBER(read);
- DECLARE_WRITE8_MEMBER(write);
+ memory_passthrough_handler m_rom_shadow_tap;
+
+ void tube_32016_mem(address_map &map) ATTR_COLD;
+
+ void prst_w(int state);
+};
+
+
+class bbc_tube_16032_device : public bbc_tube_32016_device
+{
+public:
+ bbc_tube_16032_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 ATTR_COLD;
+ virtual const tiny_rom_entry *device_rom_region() const override ATTR_COLD;
+};
- void tube_32016_mem(address_map &map);
- bool m_rom_enabled;
+class bbc_tube_32016l_device : public bbc_tube_32016_device
+{
+public:
+ bbc_tube_32016l_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 ATTR_COLD;
+ virtual const tiny_rom_entry *device_rom_region() const override ATTR_COLD;
};
// device type definition
DECLARE_DEVICE_TYPE(BBC_TUBE_32016, bbc_tube_32016_device)
+DECLARE_DEVICE_TYPE(BBC_TUBE_16032, bbc_tube_16032_device)
+DECLARE_DEVICE_TYPE(BBC_TUBE_32016L, bbc_tube_32016l_device)
-
-#endif /* MAME_BUS_BBC_TUBE_32016_H */
+#endif // MAME_BUS_BBC_TUBE_TUBE_32016_H
diff --git a/src/devices/bus/bbc/tube/tube_6502.cpp b/src/devices/bus/bbc/tube/tube_6502.cpp
index 99852ca8d90..360362634f7 100644
--- a/src/devices/bus/bbc/tube/tube_6502.cpp
+++ b/src/devices/bus/bbc/tube/tube_6502.cpp
@@ -6,6 +6,18 @@
http://chrisacorns.computinghistory.org.uk/8bit_Upgrades/Acorn_ANC01_65022ndproc.html
+ Acorn 6502 2nd Processor (pre-production)
+ Pre-production Iss.C and Iss.F boards have been seen running earlier versions
+ of the Tube OS. The boards are different in that they map the Tube ULA at
+ &FF78-&FF7F instead of the usual &FEF8-&FEFF. They also require an earlier
+ version of the Tube Host which can be found in NFS 3.34, the usual DNFS 1.20
+ will hang at the Tube startup banner.
+
+ Acorn Extended 6502 2nd Processor (non-commercial)
+ Used internally at Acorn, it extends the addressing of indexed indirect Y instructions
+ to address 256K RAM. Only two applications were created to make use of this, which
+ were turboMASM and turboBASIC.
+
Acorn ADC06 65C102 Co-processor
http://chrisacorns.computinghistory.org.uk/8bit_Upgrades/Acorn_ADC06_65C102CoPro.html
@@ -23,6 +35,8 @@
//**************************************************************************
DEFINE_DEVICE_TYPE(BBC_TUBE_6502, bbc_tube_6502_device, "bbc_tube_6502", "Acorn 6502 2nd Processor")
+DEFINE_DEVICE_TYPE(BBC_TUBE_6502P, bbc_tube_6502p_device, "bbc_tube_6502p", "Acorn 6502 2nd Processor (pre-production)")
+DEFINE_DEVICE_TYPE(BBC_TUBE_6502E, bbc_tube_6502e_device, "bbc_tube_6502e", "Acorn Extended 6502 2nd Processor")
DEFINE_DEVICE_TYPE(BBC_TUBE_65C102, bbc_tube_65c102_device, "bbc_tube_65c102", "Acorn 65C102 Co-Processor")
@@ -32,19 +46,38 @@ DEFINE_DEVICE_TYPE(BBC_TUBE_65C102, bbc_tube_65c102_device, "bbc_tube_65c102",
void bbc_tube_6502_device::tube_6502_mem(address_map &map)
{
- map(0x0000, 0xffff).m(m_bankdev, FUNC(address_map_bank_device::amap8));
- map(0xfef0, 0xfeff).rw(FUNC(bbc_tube_6502_device::tube_r), FUNC(bbc_tube_6502_device::tube_w));
+ map(0x0000, 0xffff).view(m_view);
+ // ROM enabled
+ m_view[0](0x0000, 0xffff).ram().share("ram");
+ m_view[0](0xf000, 0xffff).rom().region("rom", 0);
+ // ROM disabled
+ m_view[1](0x0000, 0xffff).ram().share("ram");
+ map(0xfef8, 0xfeff).rw(FUNC(bbc_tube_6502_device::tube_r), FUNC(bbc_tube_6502_device::tube_w));
+}
+
+void bbc_tube_6502p_device::tube_6502p_mem(address_map &map)
+{
+ map(0x0000, 0xffff).view(m_view);
+ // ROM enabled
+ m_view[0](0x0000, 0xffff).ram().share("ram");
+ m_view[0](0xf000, 0xffff).rom().region("rom", 0);
+ // ROM disabled
+ m_view[1](0x0000, 0xffff).ram().share("ram");
+ map(0xff78, 0xff7f).rw(FUNC(bbc_tube_6502p_device::tube_r), FUNC(bbc_tube_6502p_device::tube_w));
}
-void bbc_tube_6502_device::tube_6502_bank(address_map &map)
+void bbc_tube_6502e_device::tube_6502e_mem(address_map &map)
{
+ map(0x0000, 0xffff).view(m_view);
// ROM enabled
- map(0x00000, 0x0ffff).ram().share("ram");
- map(0x0f000, 0x0ffff).rom().region("rom", 0);
+ m_view[0](0x0000, 0xffff).rw(FUNC(bbc_tube_6502e_device::ram_r), FUNC(bbc_tube_6502e_device::ram_w));
+ m_view[0](0xf000, 0xffff).rom().region("rom", 0);
// ROM disabled
- map(0x10000, 0x1ffff).ram().share("ram");
+ m_view[1](0x0000, 0xffff).rw(FUNC(bbc_tube_6502e_device::ram_r), FUNC(bbc_tube_6502e_device::ram_w));
+ map(0xfef8, 0xfeff).rw(FUNC(bbc_tube_6502e_device::tube_r), FUNC(bbc_tube_6502e_device::tube_w));
}
+
//-------------------------------------------------
// ROM( tube_6502 )
//-------------------------------------------------
@@ -53,54 +86,87 @@ ROM_START( tube_6502 )
ROM_REGION(0x1000, "rom", 0)
ROM_DEFAULT_BIOS("110")
ROM_SYSTEM_BIOS(0, "110", "Tube 1.10")
- ROMX_LOAD("6502tube.rom", 0x0000, 0x1000, CRC(98b5fe42) SHA1(338269d03cf6bfa28e09d1651c273ea53394323b), ROM_BIOS(0))
- ROM_SYSTEM_BIOS(1, "121", "Tube 1.21 (ReCo6502)")
- ROMX_LOAD("reco6502tube.rom", 0x0000, 0x1000, CRC(75b2a466) SHA1(9ecef24de58a48c3fbe01b12888c3f6a5d24f57f), ROM_BIOS(1))
+ ROMX_LOAD("6502tube_110.rom", 0x0000, 0x1000, CRC(98b5fe42) SHA1(338269d03cf6bfa28e09d1651c273ea53394323b), ROM_BIOS(0))
+ ROM_SYSTEM_BIOS(1, "120", "Tube 1.20") // built from source, not an actual dump
+ ROMX_LOAD("6502tube_120.rom", 0x0000, 0x1000, CRC(50c36da5) SHA1(80e5f1c03a00cf728917242522befc17b264413f), ROM_BIOS(1))
+ ROM_SYSTEM_BIOS(2, "121", "Tube 1.21 (ReCo6502)")
+ ROMX_LOAD("reco6502tube.rom", 0x0000, 0x1000, CRC(75b2a466) SHA1(9ecef24de58a48c3fbe01b12888c3f6a5d24f57f), ROM_BIOS(2))
+ROM_END
+
+ROM_START( tube_6502p )
+ ROM_REGION(0x1000, "rom", 0)
+ 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 )
+ ROM_REGION(0x1000, "rom", 0)
+ ROM_DEFAULT_BIOS("120")
+ ROM_SYSTEM_BIOS(0, "120", "Tube 1.20") // built from source, not an actual dump
+ ROMX_LOAD("6502tube256_120.rom", 0x0000, 0x1000, BAD_DUMP CRC(967ee712) SHA1(ebca4bb471cd18608882668edda811ed88b4cee5), ROM_BIOS(0))
ROM_END
ROM_START( tube_65c102 )
ROM_REGION(0x1000, "rom", 0)
ROM_DEFAULT_BIOS("110")
ROM_SYSTEM_BIOS(0, "110", "Tube 1.10")
- ROMX_LOAD("65c102_boot_110.rom", 0x0000, 0x1000, CRC(ad5b70cc) SHA1(0ac9a1c70e55a79e2c81e102afae1d016af229fa), ROM_BIOS(0)) // 2201,243-02
- ROM_SYSTEM_BIOS(1, "121", "Tube 1.21 (ReCo6502)")
- ROMX_LOAD("reco6502tube.rom", 0x0000, 0x1000, CRC(75b2a466) SHA1(9ecef24de58a48c3fbe01b12888c3f6a5d24f57f), ROM_BIOS(1))
+ ROMX_LOAD("65c102_boot_110.rom", 0x0000, 0x1000, CRC(ad5b70cc) SHA1(0ac9a1c70e55a79e2c81e102afae1d016af229fa), ROM_BIOS(0)) // 2201,243-01
+ ROM_SYSTEM_BIOS(1, "120", "Tube 1.20")
+ ROMX_LOAD("65c102_boot_120.rom", 0x0000, 0x1000, CRC(1462f0f7) SHA1(7dc03d3c4862159baefebf1662de7e05987ddf7b), ROM_BIOS(1)) // 2201,243-02
+ ROM_SYSTEM_BIOS(2, "121", "Tube 1.21 (ReCo6502)")
+ ROMX_LOAD("reco6502tube.rom", 0x0000, 0x1000, CRC(75b2a466) SHA1(9ecef24de58a48c3fbe01b12888c3f6a5d24f57f), ROM_BIOS(2))
ROM_END
+
//-------------------------------------------------
// device_add_mconfig - add device configuration
//-------------------------------------------------
-void bbc_tube_6502_device::add_common_devices(machine_config &config)
+void bbc_tube_6502_device::device_add_mconfig(machine_config &config)
{
- ADDRESS_MAP_BANK(config, m_bankdev).set_map(&bbc_tube_6502_device::tube_6502_bank).set_options(ENDIANNESS_LITTLE, 8, 17, 0x10000);
+ G65SC02(config, m_maincpu, 12_MHz_XTAL / 4); // G65SC02
+ m_maincpu->set_addrmap(AS_PROGRAM, &bbc_tube_6502_device::tube_6502_mem);
TUBE(config, m_ula);
- m_ula->pnmi_handler().set_inputline(m_maincpu, M65C02_NMI_LINE);
- m_ula->pirq_handler().set_inputline(m_maincpu, M65C02_IRQ_LINE);
+ m_ula->pnmi_handler().set_inputline(m_maincpu, G65SC02_NMI_LINE);
+ m_ula->pirq_handler().set_inputline(m_maincpu, G65SC02_IRQ_LINE);
+ m_ula->prst_handler().set(FUNC(bbc_tube_6502_device::prst_w));
- /* internal ram */
RAM(config, m_ram).set_default_size("64K").set_default_value(0);
- /* software lists */
SOFTWARE_LIST(config, "flop_ls_6502").set_original("bbc_flop_6502");
- SOFTWARE_LIST(config, "flop_ls_65c102").set_original("bbc_flop_65c102");
}
-void bbc_tube_6502_device::device_add_mconfig(machine_config &config)
+void bbc_tube_6502p_device::device_add_mconfig(machine_config &config)
{
- M65C02(config, m_maincpu, 12_MHz_XTAL / 4);
- m_maincpu->set_addrmap(AS_PROGRAM, &bbc_tube_6502_device::tube_6502_mem);
+ bbc_tube_6502_device::device_add_mconfig(config);
+
+ M6502(config.replace(), m_maincpu, 12_MHz_XTAL / 4); // SY6502C
+ m_maincpu->set_addrmap(AS_PROGRAM, &bbc_tube_6502p_device::tube_6502p_mem);
+}
+
+void bbc_tube_6502e_device::device_add_mconfig(machine_config &config)
+{
+ bbc_tube_6502_device::device_add_mconfig(config);
+
+ G65SC02(config.replace(), m_maincpu, 12_MHz_XTAL / 4); // G65SC02
+ m_maincpu->set_addrmap(AS_PROGRAM, &bbc_tube_6502e_device::tube_6502e_mem);
- add_common_devices(config);
+ m_ram->set_default_size("256K").set_default_value(0);
}
void bbc_tube_65c102_device::device_add_mconfig(machine_config &config)
{
- M65C02(config, m_maincpu, 16_MHz_XTAL / 4);
- m_maincpu->set_addrmap(AS_PROGRAM, &bbc_tube_65c102_device::tube_6502_mem);
+ bbc_tube_6502_device::device_add_mconfig(config);
- add_common_devices(config);
+ R65C102(config.replace(), m_maincpu, 16_MHz_XTAL); // R65C102
+ m_maincpu->set_addrmap(AS_PROGRAM, &bbc_tube_65c102_device::tube_6502_mem);
}
//-------------------------------------------------
@@ -112,6 +178,16 @@ const tiny_rom_entry *bbc_tube_6502_device::device_rom_region() const
return ROM_NAME( tube_6502 );
}
+const tiny_rom_entry *bbc_tube_6502p_device::device_rom_region() const
+{
+ return ROM_NAME( tube_6502p );
+}
+
+const tiny_rom_entry *bbc_tube_6502e_device::device_rom_region() const
+{
+ return ROM_NAME( tube_6502e );
+}
+
const tiny_rom_entry *bbc_tube_65c102_device::device_rom_region() const
{
return ROM_NAME( tube_65c102 );
@@ -129,7 +205,7 @@ bbc_tube_6502_device::bbc_tube_6502_device(const machine_config &mconfig, device
: device_t(mconfig, type, tag, owner, clock)
, device_bbc_tube_interface(mconfig, *this)
, m_maincpu(*this, "maincpu")
- , m_bankdev(*this, "bankdev")
+ , m_view(*this, "view")
, m_ula(*this, "ula")
, m_ram(*this, "ram")
, m_rom(*this, "rom")
@@ -141,6 +217,19 @@ bbc_tube_6502_device::bbc_tube_6502_device(const machine_config &mconfig, const
{
}
+bbc_tube_6502p_device::bbc_tube_6502p_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
+ : bbc_tube_6502_device(mconfig, BBC_TUBE_6502P, tag, owner, clock)
+{
+}
+
+bbc_tube_6502e_device::bbc_tube_6502e_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
+ : bbc_tube_6502_device(mconfig, BBC_TUBE_6502E, tag, owner, clock)
+ , m_opcode_ind_y(false)
+ , m_page(0)
+ , m_cycles(0)
+{
+}
+
bbc_tube_65c102_device::bbc_tube_65c102_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
: bbc_tube_6502_device(mconfig, BBC_TUBE_65C102, tag, owner, clock)
{
@@ -154,13 +243,20 @@ void bbc_tube_6502_device::device_start()
{
}
+void bbc_tube_6502e_device::device_start()
+{
+ save_item(NAME(m_opcode_ind_y));
+ save_item(NAME(m_page));
+ save_item(NAME(m_cycles));
+}
+
//-------------------------------------------------
// device_reset - device-specific reset
//-------------------------------------------------
void bbc_tube_6502_device::device_reset()
{
- m_bankdev->set_bank(0);
+ m_view.select(0);
}
@@ -168,6 +264,13 @@ void bbc_tube_6502_device::device_reset()
// IMPLEMENTATION
//**************************************************************************
+void bbc_tube_6502_device::prst_w(int state)
+{
+ device_reset();
+
+ m_maincpu->set_input_line(INPUT_LINE_RESET, state);
+}
+
uint8_t bbc_tube_6502_device::host_r(offs_t offset)
{
return m_ula->host_r(offset);
@@ -183,7 +286,7 @@ uint8_t bbc_tube_6502_device::tube_r(offs_t offset)
{
// Disable ROM on first access
if (!machine().side_effects_disabled())
- m_bankdev->set_bank(1);
+ m_view.select(1);
return m_ula->parasite_r(offset);
}
@@ -192,3 +295,50 @@ void bbc_tube_6502_device::tube_w(offs_t offset, uint8_t data)
{
m_ula->parasite_w(offset, data);
}
+
+
+uint8_t bbc_tube_6502e_device::ram_r(offs_t offset)
+{
+ uint8_t data = m_ram->pointer()[offset];
+
+ if (!machine().side_effects_disabled())
+ {
+ /* opcode fetch */
+ if (m_maincpu->get_sync())
+ {
+ /* indexed indirect Y addressing */
+ m_opcode_ind_y = ((data & 0x1f) == 0x11 || (data & 0x1f) == 0x12) ? true : false;
+
+ m_cycles = m_maincpu->total_cycles();
+ }
+
+ if (m_opcode_ind_y)
+ {
+ if (m_maincpu->total_cycles() - m_cycles == 1)
+ {
+ /* fetch extra byte from &3xx where xx is low byte of ZP address */
+ m_page = m_ram->pointer()[0x301 + data] & 0x03;
+ }
+ else if (m_maincpu->total_cycles() - m_cycles > 3)
+ {
+ /* read data from extended address */
+ data = m_ram->pointer()[m_page << 16 | offset];
+ }
+ }
+ }
+
+ return data;
+}
+
+void bbc_tube_6502e_device::ram_w(offs_t offset, uint8_t data)
+{
+ if (m_opcode_ind_y)
+ {
+ /* write data to extended address */
+ m_ram->pointer()[m_page << 16 | offset] = data;
+ }
+ else
+ {
+ m_ram->pointer()[offset] = data;
+ }
+}
diff --git a/src/devices/bus/bbc/tube/tube_6502.h b/src/devices/bus/bbc/tube/tube_6502.h
index abb907ef3bd..367a6ed1623 100644
--- a/src/devices/bus/bbc/tube/tube_6502.h
+++ b/src/devices/bus/bbc/tube/tube_6502.h
@@ -12,13 +12,14 @@
**********************************************************************/
+#ifndef MAME_BUS_BBC_TUBE_TUBE_6502_H
+#define MAME_BUS_BBC_TUBE_TUBE_6502_H
-#ifndef MAME_BUS_BBC_TUBE_6502_H
-#define MAME_BUS_BBC_TUBE_6502_H
+#pragma once
#include "tube.h"
-#include "cpu/m6502/m65c02.h"
-#include "machine/bankdev.h"
+#include "cpu/m6502/g65sc02.h"
+#include "cpu/m6502/r65c02.h"
#include "machine/ram.h"
#include "machine/tube.h"
@@ -28,9 +29,9 @@
// ======================> bbc_tube_6502_device
-class bbc_tube_6502_device :
- public device_t,
- public device_bbc_tube_interface
+class bbc_tube_6502_device
+ : public device_t
+ , public device_bbc_tube_interface
{
public:
// construction/destruction
@@ -40,17 +41,14 @@ protected:
bbc_tube_6502_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_start() override ATTR_COLD;
+ virtual void device_reset() override ATTR_COLD;
// optional information overrides
- virtual void device_add_mconfig(machine_config &config) override;
- virtual const tiny_rom_entry *device_rom_region() const override;
+ virtual void device_add_mconfig(machine_config &config) override ATTR_COLD;
+ virtual const tiny_rom_entry *device_rom_region() const override ATTR_COLD;
- void tube_6502_bank(address_map &map);
- void tube_6502_mem(address_map &map);
-
- void add_common_devices(machine_config &config);
+ void tube_6502_mem(address_map &map) ATTR_COLD;
virtual uint8_t host_r(offs_t offset) override;
virtual void host_w(offs_t offset, uint8_t data) override;
@@ -58,11 +56,53 @@ protected:
virtual uint8_t tube_r(offs_t offset);
virtual void tube_w(offs_t offset, uint8_t data);
- required_device<cpu_device> m_maincpu;
- required_device<address_map_bank_device> m_bankdev;
+ required_device<m6502_device> m_maincpu;
+ memory_view m_view;
required_device<tube_device> m_ula;
required_device<ram_device> m_ram;
required_memory_region m_rom;
+
+ void prst_w(int state);
+};
+
+
+class bbc_tube_6502p_device : public bbc_tube_6502_device
+{
+public:
+ bbc_tube_6502p_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 ATTR_COLD;
+ virtual const tiny_rom_entry* device_rom_region() const override;
+
+private:
+ void tube_6502p_mem(address_map &map) ATTR_COLD;
+};
+
+
+class bbc_tube_6502e_device : public bbc_tube_6502_device
+{
+public:
+ bbc_tube_6502e_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
+
+protected:
+ // device-level overrides
+ virtual void device_start() override ATTR_COLD;
+
+ // optional information overrides
+ virtual void device_add_mconfig(machine_config &config) override ATTR_COLD;
+ virtual const tiny_rom_entry *device_rom_region() const override ATTR_COLD;
+
+private:
+ void tube_6502e_mem(address_map &map) ATTR_COLD;
+
+ uint8_t ram_r(offs_t offset);
+ void ram_w(offs_t offset, uint8_t data);
+
+ bool m_opcode_ind_y;
+ uint8_t m_page;
+ uint64_t m_cycles;
};
@@ -73,14 +113,15 @@ public:
protected:
// optional information overrides
- virtual void device_add_mconfig(machine_config &config) override;
- virtual const tiny_rom_entry *device_rom_region() const override;
+ virtual void device_add_mconfig(machine_config &config) override ATTR_COLD;
+ virtual const tiny_rom_entry *device_rom_region() const override ATTR_COLD;
};
// device type definition
DECLARE_DEVICE_TYPE(BBC_TUBE_6502, bbc_tube_6502_device)
+DECLARE_DEVICE_TYPE(BBC_TUBE_6502P, bbc_tube_6502p_device)
+DECLARE_DEVICE_TYPE(BBC_TUBE_6502E, bbc_tube_6502e_device)
DECLARE_DEVICE_TYPE(BBC_TUBE_65C102, bbc_tube_65c102_device)
-
-#endif /* MAME_BUS_BBC_TUBE_6502_H */
+#endif // MAME_BUS_BBC_TUBE_TUBE_6502_H
diff --git a/src/devices/bus/bbc/tube/tube_80186.cpp b/src/devices/bus/bbc/tube/tube_80186.cpp
index 85331ab1b2a..245cd3ff0e1 100644
--- a/src/devices/bus/bbc/tube/tube_80186.cpp
+++ b/src/devices/bus/bbc/tube/tube_80186.cpp
@@ -19,6 +19,7 @@
//**************************************************************************
DEFINE_DEVICE_TYPE(BBC_TUBE_80186, bbc_tube_80186_device, "bbc_tube_80186", "Acorn 80186 Co-Processor")
+DEFINE_DEVICE_TYPE(BBC_TUBE_PCPLUS, bbc_tube_pcplus_device, "bbc_tube_pcplus", "Solidisk PC-Plus Co-Processor")
//-------------------------------------------------
@@ -50,12 +51,22 @@ ROM_START( tube_80186 )
ROM_END
//-------------------------------------------------
+// ROM( tube_pcplus )
+//-------------------------------------------------
+
+ROM_START( tube_pcplus )
+ ROM_REGION(0x4000, "bootstrap", 0)
+ ROM_LOAD16_BYTE("pcplus_ic31.rom", 0x0000, 0x2000, CRC(5149417b) SHA1(a905c8570d70597bb2b2fca47a1a47783956af9c))
+ ROM_LOAD16_BYTE("pcplus_ic32.rom", 0x0001, 0x2000, CRC(e47f10b2) SHA1(45dc8d7e7936afbec6de423569d9005a1c350316))
+ROM_END
+
+//-------------------------------------------------
// device_add_mconfig - add device configuration
//-------------------------------------------------
void bbc_tube_80186_device::device_add_mconfig(machine_config &config)
{
- I80186(config, m_i80186, 20_MHz_XTAL / 2);
+ I80186(config, m_i80186, 20_MHz_XTAL);
m_i80186->set_addrmap(AS_PROGRAM, &bbc_tube_80186_device::tube_80186_mem);
m_i80186->set_addrmap(AS_IO, &bbc_tube_80186_device::tube_80186_io);
m_i80186->tmrout0_handler().set_inputline(m_i80186, INPUT_LINE_HALT).invert();
@@ -64,12 +75,22 @@ void bbc_tube_80186_device::device_add_mconfig(machine_config &config)
TUBE(config, m_ula, 0);
m_ula->pirq_handler().set(m_i80186, FUNC(i80186_cpu_device::int0_w));
m_ula->drq_handler().set(m_i80186, FUNC(i80186_cpu_device::drq0_w));
+ m_ula->prst_handler().set(FUNC(bbc_tube_80186_device::prst_w));
/* internal ram */
RAM(config, m_ram).set_default_size("512K");
/* software lists */
SOFTWARE_LIST(config, "flop_ls_80186").set_original("bbc_flop_80186");
+ SOFTWARE_LIST(config, "pc_disk_list").set_compatible("ibm5150");
+}
+
+void bbc_tube_pcplus_device::device_add_mconfig(machine_config &config)
+{
+ bbc_tube_80186_device::device_add_mconfig(config);
+
+ /* internal ram */
+ m_ram->set_default_size("1M");
}
//-------------------------------------------------
@@ -81,6 +102,11 @@ const tiny_rom_entry *bbc_tube_80186_device::device_rom_region() const
return ROM_NAME( tube_80186 );
}
+const tiny_rom_entry *bbc_tube_pcplus_device::device_rom_region() const
+{
+ return ROM_NAME( tube_pcplus );
+}
+
//**************************************************************************
// LIVE DEVICE
//**************************************************************************
@@ -89,13 +115,23 @@ const tiny_rom_entry *bbc_tube_80186_device::device_rom_region() const
// bbc_tube_80186_device - constructor
//-------------------------------------------------
+bbc_tube_80186_device::bbc_tube_80186_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_i80186(*this, "i80186")
+ , m_ula(*this, "ula")
+ , m_ram(*this, "ram")
+ , m_bootstrap(*this, "bootstrap")
+{
+}
+
bbc_tube_80186_device::bbc_tube_80186_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
- : device_t(mconfig, BBC_TUBE_80186, tag, owner, clock),
- device_bbc_tube_interface(mconfig, *this),
- m_i80186(*this, "i80186"),
- m_ula(*this, "ula"),
- m_ram(*this, "ram"),
- m_bootstrap(*this, "bootstrap")
+ : bbc_tube_80186_device(mconfig, BBC_TUBE_80186, tag, owner, clock)
+{
+}
+
+bbc_tube_pcplus_device::bbc_tube_pcplus_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
+ : bbc_tube_80186_device(mconfig, BBC_TUBE_PCPLUS, tag, owner, clock)
{
}
@@ -121,11 +157,25 @@ void bbc_tube_80186_device::device_reset()
program.install_rom(0xc0000, 0xc3fff, 0x3c000, m_bootstrap->base());
}
+void bbc_tube_pcplus_device::device_reset()
+{
+ address_space &program = m_i80186->space(AS_PROGRAM);
+
+ program.install_ram(0x00000, 0xfffff, m_ram->pointer());
+ program.install_rom(0xf0000, 0xf3fff, 0x0c000, m_bootstrap->base());
+}
//**************************************************************************
// IMPLEMENTATION
//**************************************************************************
+void bbc_tube_80186_device::prst_w(int state)
+{
+ device_reset();
+
+ m_i80186->set_input_line(INPUT_LINE_RESET, state);
+}
+
uint8_t bbc_tube_80186_device::host_r(offs_t offset)
{
return m_ula->host_r(offset);
diff --git a/src/devices/bus/bbc/tube/tube_80186.h b/src/devices/bus/bbc/tube/tube_80186.h
index 42f757e75e4..7c8f2b68931 100644
--- a/src/devices/bus/bbc/tube/tube_80186.h
+++ b/src/devices/bus/bbc/tube/tube_80186.h
@@ -8,9 +8,10 @@
**********************************************************************/
+#ifndef MAME_BUS_BBC_TUBE_TUBE_80186_H
+#define MAME_BUS_BBC_TUBE_TUBE_80186_H
-#ifndef MAME_BUS_BBC_TUBE_80186_H
-#define MAME_BUS_BBC_TUBE_80186_H
+#pragma once
#include "tube.h"
#include "cpu/i86/i186.h"
@@ -32,30 +33,48 @@ public:
bbc_tube_80186_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
protected:
+ bbc_tube_80186_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_start() override ATTR_COLD;
+ virtual void device_reset() override ATTR_COLD;
// optional information overrides
- virtual void device_add_mconfig(machine_config &config) override;
- virtual const tiny_rom_entry *device_rom_region() const override;
+ virtual void device_add_mconfig(machine_config &config) override ATTR_COLD;
+ virtual const tiny_rom_entry *device_rom_region() const override ATTR_COLD;
virtual uint8_t host_r(offs_t offset) override;
virtual void host_w(offs_t offset, uint8_t data) override;
-private:
required_device<i80186_cpu_device> m_i80186;
required_device<tube_device> m_ula;
required_device<ram_device> m_ram;
required_memory_region m_bootstrap;
- void tube_80186_io(address_map &map);
- void tube_80186_mem(address_map &map);
+ void tube_80186_io(address_map &map) ATTR_COLD;
+ void tube_80186_mem(address_map &map) ATTR_COLD;
+
+ void prst_w(int state);
+};
+
+
+class bbc_tube_pcplus_device : public bbc_tube_80186_device
+{
+public:
+ bbc_tube_pcplus_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
+
+protected:
+ // device-level overrides
+ virtual void device_reset() override ATTR_COLD;
+
+ // optional information overrides
+ virtual void device_add_mconfig(machine_config &config) override ATTR_COLD;
+ virtual const tiny_rom_entry *device_rom_region() const override ATTR_COLD;
};
// device type definition
DECLARE_DEVICE_TYPE(BBC_TUBE_80186, bbc_tube_80186_device)
+DECLARE_DEVICE_TYPE(BBC_TUBE_PCPLUS, bbc_tube_pcplus_device)
-
-#endif /* MAME_BUS_BBC_TUBE_80x86_H */
+#endif // MAME_BUS_BBC_TUBE_TUBE_80186_H
diff --git a/src/devices/bus/bbc/tube/tube_80286.cpp b/src/devices/bus/bbc/tube/tube_80286.cpp
index e8ff167d0fb..34917acf629 100644
--- a/src/devices/bus/bbc/tube/tube_80286.cpp
+++ b/src/devices/bus/bbc/tube/tube_80286.cpp
@@ -27,7 +27,7 @@ DEFINE_DEVICE_TYPE(BBC_TUBE_80286, bbc_tube_80286_device, "bbc_tube_80286", "Aco
void bbc_tube_80286_device::tube_80286_mem(address_map &map)
{
map.global_mask(0xfffff);
- map(0x00000, 0xbffff).ram().share("ram");
+ map(0x00000, 0xfffff).ram().share("ram");
map(0xc0000, 0xc3fff).rom().region("bootstrap", 0).mirror(0x3c000);
}
@@ -39,7 +39,7 @@ void bbc_tube_80286_device::tube_80286_io(address_map &map)
{
map.unmap_value_high();
map(0x50, 0x50).r(FUNC(bbc_tube_80286_device::disable_boot_rom));
- map(0x60, 0x60).w(FUNC(bbc_tube_80286_device::irq_latch_w));
+ map(0x60, 0x60).lw8(NAME([this](uint8_t data) { m_irq_latch = data; }));
map(0x80, 0x8f).rw("ula", FUNC(tube_device::parasite_r), FUNC(tube_device::parasite_w)).umask16(0x00ff);
}
@@ -48,7 +48,7 @@ void bbc_tube_80286_device::tube_80286_io(address_map &map)
//-------------------------------------------------
ROM_START(tube_80286)
- ROM_REGION(0x4000, "bootstrap", 0)
+ ROM_REGION16_LE(0x4000, "bootstrap", 0)
ROM_LOAD16_BYTE("m512_lo.ic31", 0x0000, 0x2000, CRC(c0df8707) SHA1(7f6d843d5aea6bdb36cbd4623ae942b16b96069d)) // 2201,287-02
ROM_LOAD16_BYTE("m512_hi.ic32", 0x0001, 0x2000, CRC(e47f10b2) SHA1(45dc8d7e7936afbec6de423569d9005a1c350316)) // 2201,288-02
ROM_END
@@ -62,17 +62,19 @@ void bbc_tube_80286_device::device_add_mconfig(machine_config &config)
I80286(config, m_i80286, 12_MHz_XTAL / 2);
m_i80286->set_addrmap(AS_PROGRAM, &bbc_tube_80286_device::tube_80286_mem);
m_i80286->set_addrmap(AS_IO, &bbc_tube_80286_device::tube_80286_io);
- m_i80286->set_irq_acknowledge_callback(device_irq_acknowledge_delegate(FUNC(bbc_tube_80286_device::irq_callback), this));
+ m_i80286->set_irq_acknowledge_callback(FUNC(bbc_tube_80286_device::irq_callback));
TUBE(config, m_ula);
m_ula->pnmi_handler().set_inputline(m_i80286, INPUT_LINE_NMI);
m_ula->pirq_handler().set_inputline(m_i80286, INPUT_LINE_INT0);
+ m_ula->prst_handler().set(FUNC(bbc_tube_80286_device::prst_w));
/* internal ram */
RAM(config, m_ram).set_default_size("1M");
/* software lists */
SOFTWARE_LIST(config, "flop_ls_80186").set_original("bbc_flop_80186");
+ SOFTWARE_LIST(config, "pc_disk_list").set_compatible("ibm5150");
}
//-------------------------------------------------
@@ -93,12 +95,13 @@ const tiny_rom_entry *bbc_tube_80286_device::device_rom_region() const
//-------------------------------------------------
bbc_tube_80286_device::bbc_tube_80286_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
- : device_t(mconfig, BBC_TUBE_80286, tag, owner, clock),
- device_bbc_tube_interface(mconfig, *this),
- m_i80286(*this, "i80286"),
- m_ula(*this, "ula"),
- m_ram(*this, "ram"),
- m_bootstrap(*this, "bootstrap")
+ : device_t(mconfig, BBC_TUBE_80286, tag, owner, clock)
+ , device_bbc_tube_interface(mconfig, *this)
+ , m_i80286(*this, "i80286")
+ , m_ula(*this, "ula")
+ , m_ram(*this, "ram")
+ , m_bootstrap(*this, "bootstrap")
+ , m_irq_latch(0)
{
}
@@ -108,7 +111,6 @@ bbc_tube_80286_device::bbc_tube_80286_device(const machine_config &mconfig, cons
void bbc_tube_80286_device::device_start()
{
- m_slot = dynamic_cast<bbc_tube_slot_device *>(owner());
}
//-------------------------------------------------
@@ -117,8 +119,6 @@ void bbc_tube_80286_device::device_start()
void bbc_tube_80286_device::device_reset()
{
- m_ula->reset();
-
address_space &program = m_i80286->space(AS_PROGRAM);
program.install_rom(0xc0000, 0xc3fff, 0x3c000, m_bootstrap->base());
@@ -129,6 +129,13 @@ void bbc_tube_80286_device::device_reset()
// IMPLEMENTATION
//**************************************************************************
+void bbc_tube_80286_device::prst_w(int state)
+{
+ device_reset();
+
+ m_i80286->set_input_line(INPUT_LINE_RESET, state);
+}
+
uint8_t bbc_tube_80286_device::host_r(offs_t offset)
{
return m_ula->host_r(offset);
@@ -147,11 +154,6 @@ uint8_t bbc_tube_80286_device::disable_boot_rom()
return 0xff;
}
-void bbc_tube_80286_device::irq_latch_w(uint8_t data)
-{
- m_irq_latch = data;
-}
-
//-------------------------------------------------
// irq vector callback
//-------------------------------------------------
diff --git a/src/devices/bus/bbc/tube/tube_80286.h b/src/devices/bus/bbc/tube/tube_80286.h
index a6e952d6bf2..6de4477ae0e 100644
--- a/src/devices/bus/bbc/tube/tube_80286.h
+++ b/src/devices/bus/bbc/tube/tube_80286.h
@@ -6,9 +6,10 @@
**********************************************************************/
+#ifndef MAME_BUS_BBC_TUBE_TUBE_80286_H
+#define MAME_BUS_BBC_TUBE_TUBE_80286_H
-#ifndef MAME_BUS_BBC_TUBE_80286_H
-#define MAME_BUS_BBC_TUBE_80286_H
+#pragma once
#include "tube.h"
#include "cpu/i86/i286.h"
@@ -31,19 +32,17 @@ public:
protected:
// device-level overrides
- virtual void device_start() override;
- virtual void device_reset() override;
+ virtual void device_start() override ATTR_COLD;
+ virtual void device_reset() override ATTR_COLD;
// optional information overrides
- virtual void device_add_mconfig(machine_config &config) override;
- virtual const tiny_rom_entry *device_rom_region() const override;
+ virtual void device_add_mconfig(machine_config &config) override ATTR_COLD;
+ virtual const tiny_rom_entry *device_rom_region() const override ATTR_COLD;
virtual uint8_t host_r(offs_t offset) override;
virtual void host_w(offs_t offset, uint8_t data) override;
private:
- uint8_t m_irq_latch;
-
IRQ_CALLBACK_MEMBER( irq_callback );
required_device<i80286_cpu_device> m_i80286;
@@ -51,16 +50,17 @@ private:
required_device<ram_device> m_ram;
required_memory_region m_bootstrap;
+ uint8_t m_irq_latch;
uint8_t disable_boot_rom();
- void irq_latch_w(uint8_t data);
- void tube_80286_io(address_map &map);
- void tube_80286_mem(address_map &map);
+ void tube_80286_io(address_map &map) ATTR_COLD;
+ void tube_80286_mem(address_map &map) ATTR_COLD;
+
+ void prst_w(int state);
};
// device type definition
DECLARE_DEVICE_TYPE(BBC_TUBE_80286, bbc_tube_80286_device)
-
-#endif /* MAME_BUS_BBC_TUBE_80286_H */
+#endif // MAME_BUS_BBC_TUBE_TUBE_80286_H
diff --git a/src/devices/bus/bbc/tube/tube_a500.cpp b/src/devices/bus/bbc/tube/tube_a500.cpp
new file mode 100644
index 00000000000..3c3e7a583e2
--- /dev/null
+++ b/src/devices/bus/bbc/tube/tube_a500.cpp
@@ -0,0 +1,233 @@
+// license:BSD-3-Clause
+// copyright-holders:Nigel Barnes
+/**********************************************************************
+
+ Acorn A500 2nd processor
+
+ 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"
+
+
+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);
+
+ // device_t overrides
+ virtual void device_start() override { }
+
+ // optional information overrides
+ virtual void device_add_mconfig(machine_config &config) override ATTR_COLD;
+ virtual const tiny_rom_entry *device_rom_region() const override ATTR_COLD;
+
+ 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) ATTR_COLD;
+ void a500_map(address_map &map) ATTR_COLD;
+
+ 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 ATTR_COLD;
+ virtual const tiny_rom_entry *device_rom_region() const override ATTR_COLD;
+
+private:
+ void a500d_map(address_map &map) ATTR_COLD;
+};
+
+
+//-------------------------------------------------
+// ADDRESS_MAP( a500_map )
+//-------------------------------------------------
+
+void bbc_tube_a500_device::arm_mem(address_map &map)
+{
+ map(0x00000000, 0x01ffffff).rw(m_memc, FUNC(acorn_memc_device::logical_r), FUNC(acorn_memc_device::logical_w));
+ map(0x02000000, 0x03ffffff).rw(m_memc, FUNC(acorn_memc_device::high_mem_r), FUNC(acorn_memc_device::high_mem_w));
+}
+
+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_region - device-specific ROM region
+//-------------------------------------------------
+
+ROM_START(tube_a500)
+ ROM_REGION(0x200000, "maincpu", 0)
+ 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
+//-------------------------------------------------
+
+void bbc_tube_a500_device::device_add_mconfig(machine_config &config)
+{
+ ARM(config, m_maincpu, 24_MHz_XTAL / 3);
+ m_maincpu->set_addrmap(AS_PROGRAM, &bbc_tube_a500_device::arm_mem);
+
+ INPUT_MERGER_ANY_HIGH(config, m_fiqs).output_handler().set_inputline(m_maincpu, ARM_FIRQ_LINE);
+ INPUT_MERGER_ANY_HIGH(config, m_irqs).output_handler().set_inputline(m_maincpu, ARM_IRQ_LINE);
+
+ TUBE(config, m_ula);
+ m_ula->pnmi_handler().set(m_fiqs, FUNC(input_merger_device::in_w<0>));
+ m_ula->pirq_handler().set(m_irqs, FUNC(input_merger_device::in_w<0>));
+ m_ula->prst_handler().set(FUNC(bbc_tube_a500_device::prst_w));
+
+ ACORN_MEMC(config, m_memc, 24_MHz_XTAL / 3, m_vidc);
+ m_memc->set_addrmap(0, &bbc_tube_a500_device::a500_map);
+ m_memc->sirq_w().set(m_ioc, FUNC(acorn_ioc_device::il1_w));
+
+ ACORN_IOC(config, m_ioc, 24_MHz_XTAL / 3);
+ 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<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));
+
+ screen_device &screen(SCREEN(config, "screen", SCREEN_TYPE_RASTER));
+ screen.screen_vblank().set(m_ioc, FUNC(acorn_ioc_device::ir_w));
+
+ ACORN_VIDC1(config, m_vidc, 24_MHz_XTAL);
+ m_vidc->set_screen("screen");
+ 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");
+}
+
+void bbc_tube_a500d_device::device_add_mconfig(machine_config &config)
+{
+ 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
+//**************************************************************************
+
+//-------------------------------------------------
+// bbc_tube_a500_device - constructor
+//-------------------------------------------------
+
+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")
+ , m_memc(*this, "memc")
+ , m_vidc(*this, "vidc")
+ , m_ula(*this, "ula")
+ , m_irqs(*this, "irqs")
+ , m_fiqs(*this, "fiqs")
+{
+}
+
+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)
+{
+}
+
+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)
+{
+}
+
+} // anonymous namespace
+
+
+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
new file mode 100644
index 00000000000..4e30ab3d9b0
--- /dev/null
+++ b/src/devices/bus/bbc/tube/tube_a500.h
@@ -0,0 +1,14 @@
+// license:BSD-3-Clause
+// copyright-holders:Nigel Barnes
+#ifndef MAME_BUS_BBC_TUBE_TUBE_A500_H
+#define MAME_BUS_BBC_TUBE_TUBE_A500_H
+
+#pragma once
+
+#include "tube.h"
+
+
+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_TUBE_A500_H
diff --git a/src/devices/bus/bbc/tube/tube_arm.cpp b/src/devices/bus/bbc/tube/tube_arm.cpp
index 463a82713be..f550a245e6e 100644
--- a/src/devices/bus/bbc/tube/tube_arm.cpp
+++ b/src/devices/bus/bbc/tube/tube_arm.cpp
@@ -26,9 +26,9 @@ DEFINE_DEVICE_TYPE(BBC_TUBE_ARM, bbc_tube_arm_device, "bbc_tube_arm", "ARM Evalu
void bbc_tube_arm_device::tube_arm_mem(address_map &map)
{
map.unmap_value_high();
- map(0x0000000, 0x03fffff).rw(FUNC(bbc_tube_arm_device::ram_r), FUNC(bbc_tube_arm_device::ram_w));
+ map(0x0000000, 0x03fffff).ram().share(RAM_TAG);
map(0x0400000, 0x0ffffff).noprw();
- map(0x1000000, 0x100001f).rw("ula", FUNC(tube_device::parasite_r), FUNC(tube_device::parasite_w)).umask32(0x000000ff);
+ map(0x1000000, 0x100001f).rw(m_ula, FUNC(tube_device::parasite_r), FUNC(tube_device::parasite_w)).umask32(0x000000ff);
map(0x3000000, 0x3003fff).rom().region("bootstrap", 0).mirror(0xc000);
}
@@ -37,7 +37,7 @@ void bbc_tube_arm_device::tube_arm_mem(address_map &map)
//-------------------------------------------------
ROM_START( tube_arm )
- ROM_REGION(0x4000, "bootstrap", 0)
+ ROM_REGION32_LE(0x4000, "bootstrap", 0)
ROM_DEFAULT_BIOS("101")
ROM_SYSTEM_BIOS(0, "101", "Executive v1.00 (14th August 1986)")
ROMX_LOAD("armeval_101.rom", 0x0000, 0x4000, CRC(cab85473) SHA1(f86bbc4894e62725b8ef22d44e7f44d37c98ac14), ROM_BIOS(0))
@@ -53,13 +53,13 @@ ROM_END
void bbc_tube_arm_device::device_add_mconfig(machine_config &config)
{
- ARM(config, m_arm, 20_MHz_XTAL / 3);
- m_arm->set_addrmap(AS_PROGRAM, &bbc_tube_arm_device::tube_arm_mem);
+ ARM(config, m_maincpu, 20_MHz_XTAL / 3);
+ m_maincpu->set_addrmap(AS_PROGRAM, &bbc_tube_arm_device::tube_arm_mem);
TUBE(config, m_ula);
- m_ula->hirq_handler().set(DEVICE_SELF_OWNER, FUNC(bbc_tube_slot_device::irq_w));
- m_ula->pnmi_handler().set_inputline(m_arm, ARM_FIRQ_LINE);
- m_ula->pirq_handler().set_inputline(m_arm, ARM_IRQ_LINE);
+ m_ula->pnmi_handler().set_inputline(m_maincpu, ARM_FIRQ_LINE);
+ m_ula->pirq_handler().set_inputline(m_maincpu, ARM_IRQ_LINE);
+ m_ula->prst_handler().set(FUNC(bbc_tube_arm_device::prst_w));
/* internal ram */
RAM(config, m_ram).set_default_size("4M").set_default_value(0);
@@ -86,13 +86,12 @@ const tiny_rom_entry *bbc_tube_arm_device::device_rom_region() const
//-------------------------------------------------
bbc_tube_arm_device::bbc_tube_arm_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
- : device_t(mconfig, BBC_TUBE_ARM, tag, owner, clock),
- device_bbc_tube_interface(mconfig, *this),
- m_arm(*this, "arm"),
- m_ula(*this, "ula"),
- m_ram(*this, "ram"),
- m_bootstrap(*this, "bootstrap"),
- m_rom_select(true)
+ : device_t(mconfig, BBC_TUBE_ARM, tag, owner, clock)
+ , device_bbc_tube_interface(mconfig, *this)
+ , m_maincpu(*this, "maincpu")
+ , m_ula(*this, "ula")
+ , m_ram(*this, "ram")
+ , m_bootstrap(*this, "bootstrap")
{
}
@@ -102,7 +101,6 @@ bbc_tube_arm_device::bbc_tube_arm_device(const machine_config &mconfig, const ch
void bbc_tube_arm_device::device_start()
{
- m_slot = dynamic_cast<bbc_tube_slot_device *>(owner());
}
//-------------------------------------------------
@@ -111,8 +109,24 @@ void bbc_tube_arm_device::device_start()
void bbc_tube_arm_device::device_reset()
{
+ address_space &program = m_maincpu->space(AS_PROGRAM);
+
/* enable the reset vector to be fetched from ROM */
- m_rom_select = true;
+ m_maincpu->space(AS_PROGRAM).install_rom(0x000000, 0x003fff, 0x3fc000, m_bootstrap->base());
+
+ m_rom_shadow_tap.remove();
+ m_rom_shadow_tap = program.install_write_tap(
+ 0x0000000, 0x03fffff,
+ "rom_shadow_w",
+ [this] (offs_t offset, u32 &data, u32 mem_mask)
+ {
+ /* delete this tap */
+ m_rom_shadow_tap.remove();
+
+ /* install ram */
+ m_maincpu->space(AS_PROGRAM).install_ram(0x0000000, 0x03fffff, m_ram->pointer());
+ },
+ &m_rom_shadow_tap);
}
@@ -120,33 +134,19 @@ void bbc_tube_arm_device::device_reset()
// IMPLEMENTATION
//**************************************************************************
-uint8_t bbc_tube_arm_device::host_r(offs_t offset)
+void bbc_tube_arm_device::prst_w(int state)
{
- return m_ula->host_r(offset);
-}
+ device_reset();
-void bbc_tube_arm_device::host_w(offs_t offset, uint8_t data)
-{
- m_ula->host_w(offset, data);
+ m_maincpu->set_input_line(INPUT_LINE_RESET, state);
}
-
-uint8_t bbc_tube_arm_device::ram_r(offs_t offset)
+uint8_t bbc_tube_arm_device::host_r(offs_t offset)
{
- uint8_t data;
-
- if (m_rom_select)
- data = m_bootstrap->base()[offset & 0x3fff];
- else
- data = m_ram->pointer()[offset];
-
- return data;
+ return m_ula->host_r(offset);
}
-void bbc_tube_arm_device::ram_w(offs_t offset, uint8_t data)
+void bbc_tube_arm_device::host_w(offs_t offset, uint8_t data)
{
- /* clear ROM select on first write */
- if (!machine().side_effects_disabled()) m_rom_select = false;
-
- m_ram->pointer()[offset] = data;
+ m_ula->host_w(offset, data);
}
diff --git a/src/devices/bus/bbc/tube/tube_arm.h b/src/devices/bus/bbc/tube/tube_arm.h
index 8470fec84ef..df243eeab35 100644
--- a/src/devices/bus/bbc/tube/tube_arm.h
+++ b/src/devices/bus/bbc/tube/tube_arm.h
@@ -6,9 +6,10 @@
**********************************************************************/
+#ifndef MAME_BUS_BBC_TUBE_TUBE_ARM_H
+#define MAME_BUS_BBC_TUBE_TUBE_ARM_H
-#ifndef MAME_BUS_BBC_TUBE_ARM_H
-#define MAME_BUS_BBC_TUBE_ARM_H
+#pragma once
#include "tube.h"
#include "cpu/arm/arm.h"
@@ -31,33 +32,31 @@ public:
protected:
// device-level overrides
- virtual void device_start() override;
- virtual void device_reset() override;
+ virtual void device_start() override ATTR_COLD;
+ virtual void device_reset() override ATTR_COLD;
// optional information overrides
- virtual void device_add_mconfig(machine_config &config) override;
- virtual const tiny_rom_entry *device_rom_region() const override;
+ virtual void device_add_mconfig(machine_config &config) override ATTR_COLD;
+ virtual const tiny_rom_entry *device_rom_region() const override ATTR_COLD;
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_arm;
+ required_device<arm_cpu_device> m_maincpu;
required_device<tube_device> m_ula;
required_device<ram_device> m_ram;
required_memory_region m_bootstrap;
- bool m_rom_select;
+ memory_passthrough_handler m_rom_shadow_tap;
- uint8_t ram_r(offs_t offset);
- void ram_w(offs_t offset, uint8_t data);
+ void tube_arm_mem(address_map &map) ATTR_COLD;
- void tube_arm_mem(address_map &map);
+ void prst_w(int state);
};
// device type definition
DECLARE_DEVICE_TYPE(BBC_TUBE_ARM, bbc_tube_arm_device)
-
-#endif /* MAME_BUS_BBC_TUBE_ARM_H */
+#endif // MAME_BUS_BBC_TUBE_TUBE_ARM_H
diff --git a/src/devices/bus/bbc/tube/tube_arm7.cpp b/src/devices/bus/bbc/tube/tube_arm7.cpp
new file mode 100644
index 00000000000..b7ec32aa78d
--- /dev/null
+++ b/src/devices/bus/bbc/tube/tube_arm7.cpp
@@ -0,0 +1,303 @@
+// license:BSD-3-Clause
+// copyright-holders:Nigel Barnes
+/**********************************************************************
+
+ Sprow ARM7TDMI Co-Processor (2005)
+
+ http://www.sprow.co.uk/bbc/armcopro.htm
+
+**********************************************************************/
+
+
+#include "emu.h"
+#include "tube_arm7.h"
+
+
+//**************************************************************************
+// DEVICE DEFINITIONS
+//**************************************************************************
+
+DEFINE_DEVICE_TYPE(BBC_TUBE_ARM7, bbc_tube_arm7_device, "bbc_tube_arm7", "Sprow ARM7TDMI Co-Processor")
+
+
+//-------------------------------------------------
+// ADDRESS_MAP( arm7_map )
+//-------------------------------------------------
+
+void bbc_tube_arm7_device::arm7_map(address_map &map)
+{
+ map(0x00000000, 0x07ffffff).view(m_bank0_view);
+ m_bank0_view[0](0x00000000, 0x0007ffff).rom().region("flash", 0).mirror(0x07f80000);
+ m_bank0_view[1](0x00000000, 0x07ffffff).rw(m_ram, FUNC(ram_device::read), FUNC(ram_device::write));
+ map(0x50000000, 0x50007fff).ram();
+ map(0x78000000, 0xbfffffff).rw(FUNC(bbc_tube_arm7_device::oki_reg_r), FUNC(bbc_tube_arm7_device::oki_reg_w));
+ map(0xc0000000, 0xc7ffffff).rw(m_ram, FUNC(ram_device::read), FUNC(ram_device::write));
+ map(0xc8000000, 0xc807ffff).rom().region("flash", 0).mirror(0x07f80000);
+ map(0xf0000000, 0xf000000f).rw(m_ula, FUNC(tube_device::parasite_r), FUNC(tube_device::parasite_w)).umask16(0x00ff);
+ map(0xf0000010, 0xf0000010).lrw8(NAME([this]() { return m_tube10; }), NAME([this](u8 data) { m_tube10 = data; }));
+}
+
+
+//-------------------------------------------------
+// ROM( tube_arm7 )
+//-------------------------------------------------
+
+ROM_START( tube_arm7 )
+ ROM_REGION32_LE(0x80000, "flash", 0)
+ ROM_SYSTEM_BIOS(0, "045", "ARM Tube OS 0.45")
+ ROMX_LOAD("atos045.rom", 0x00000, 0x80000, CRC(984c594e) SHA1(1909886361c2a143c02a3977f6ce1a529dfc8779), ROM_BIOS(0))
+ ROM_SYSTEM_BIOS(1, "040", "ARM Tube OS 0.40")
+ ROMX_LOAD("atos040.rom", 0x00000, 0x80000, CRC(b34b5011) SHA1(babfb5bdb8265cf3ac7feff254146cb2d2773da1), ROM_BIOS(1))
+ROM_END
+
+
+//-------------------------------------------------
+// device_add_mconfig - add device configuration
+//-------------------------------------------------
+
+void bbc_tube_arm7_device::device_add_mconfig(machine_config &config)
+{
+ ARM7(config, m_maincpu, 64_MHz_XTAL); // Oki ML67Q5003
+ m_maincpu->set_addrmap(AS_PROGRAM, &bbc_tube_arm7_device::arm7_map);
+
+ TUBE(config, m_ula);
+ m_ula->pnmi_handler().set(FUNC(bbc_tube_arm7_device::efiq_w));
+ m_ula->pirq_handler().set(FUNC(bbc_tube_arm7_device::exint3_w));
+ m_ula->prst_handler().set(FUNC(bbc_tube_arm7_device::prst_w));
+
+ RAM(config, m_ram).set_default_size("32M").set_extra_options("16M,64M");
+}
+
+
+//-------------------------------------------------
+// rom_region - device-specific ROM region
+//-------------------------------------------------
+
+const tiny_rom_entry *bbc_tube_arm7_device::device_rom_region() const
+{
+ return ROM_NAME( tube_arm7 );
+}
+
+
+//**************************************************************************
+// LIVE DEVICE
+//**************************************************************************
+
+//-------------------------------------------------
+// bbc_tube_arm7_device - constructor
+//-------------------------------------------------
+
+bbc_tube_arm7_device::bbc_tube_arm7_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
+ : device_t(mconfig, BBC_TUBE_ARM7, tag, owner, clock)
+ , device_bbc_tube_interface(mconfig, *this)
+ , m_maincpu(*this, "maincpu")
+ , m_flash(*this, "flash")
+ , m_ula(*this, "ula")
+ , m_ram(*this, "ram")
+ , m_bank0_view(*this, "bank0")
+ , m_tube10(0)
+{
+}
+
+//-------------------------------------------------
+// device_start - device-specific startup
+//-------------------------------------------------
+
+void bbc_tube_arm7_device::device_start()
+{
+ save_item(NAME(m_registers));
+}
+
+//-------------------------------------------------
+// device_reset - device-specific reset
+//-------------------------------------------------
+
+void bbc_tube_arm7_device::device_reset()
+{
+ // interrupt states
+ m_efiq_state = 0;
+ m_exint3_state = 0;
+
+ // reset registers
+ memset(m_registers, 0, sizeof(m_registers));
+ update_interrupts();
+
+ // enable rom
+ m_registers[CHIP_CONFIG][3] = 1; // ROMSEL
+ update_bank0();
+}
+
+
+//**************************************************************************
+// IMPLEMENTATION
+//**************************************************************************
+
+void bbc_tube_arm7_device::prst_w(int state)
+{
+ device_reset();
+
+ m_maincpu->set_input_line(INPUT_LINE_RESET, state);
+}
+
+uint8_t bbc_tube_arm7_device::host_r(offs_t offset)
+{
+ return m_ula->host_r(offset);
+}
+
+void bbc_tube_arm7_device::host_w(offs_t offset, uint8_t data)
+{
+ m_ula->host_w(offset, data);
+}
+
+
+void bbc_tube_arm7_device::update_interrupts()
+{
+ int firq = BIT(m_registers[INTERRUPT][4], 0) && m_efiq_state;
+ int irq = BIT(m_registers[EXP_INTERRUPT][6], 28, 4) && m_exint3_state;
+
+ m_maincpu->set_input_line(arm7_cpu_device::ARM7_FIRQ_LINE, firq ? ASSERT_LINE : CLEAR_LINE);
+ m_maincpu->set_input_line(arm7_cpu_device::ARM7_IRQ_LINE, irq ? ASSERT_LINE : CLEAR_LINE);
+}
+
+void bbc_tube_arm7_device::efiq_w(int state)
+{
+ m_efiq_state = state;
+ update_interrupts();
+}
+
+void bbc_tube_arm7_device::exint3_w(int state)
+{
+ m_exint3_state = state;
+ if (state)
+ {
+ m_registers[INTERRUPT][5] = 31; // IRN
+ }
+ update_interrupts();
+}
+
+
+void bbc_tube_arm7_device::update_bank0()
+{
+ if (BIT(m_registers[CHIP_CONFIG][3], 0) && !BIT(m_registers[SYSTEM][4], 3))
+ {
+ m_bank0_view.select(0);
+ }
+ else
+ {
+ m_bank0_view.select(1);
+ }
+}
+
+
+uint32_t bbc_tube_arm7_device::oki_reg_r(offs_t offset)
+{
+ uint32_t data = 0x00;
+ uint32_t reg_addr = 0x78000000 + (offset * 4);
+
+ switch (reg_addr >> 4)
+ {
+ case 0x7800000: case 0x7800001: case 0x7800002:
+ data = m_registers[INTERRUPT][offset & 0x0f];
+ if (reg_addr == 0x78000014) // IRN
+ {
+ m_registers[INTERRUPT][5] = 0; // IRN
+ m_registers[INTERRUPT][6] = 0; // CIL
+ }
+ update_interrupts();
+ break;
+
+ case 0x7810000:
+ data = m_registers[EXT_MEMORY][offset & 0x03];
+ break;
+
+ case 0x7820000: case 0x7820001:
+ data = m_registers[CACHE_MEMORY][offset & 0x07];
+ break;
+
+ case 0x7818000: case 0x7818001:
+ data = m_registers[DRAM_CONTROL][offset & 0x07];
+ break;
+
+ case 0x7bf0000: case 0x7bf0001:
+ data = m_registers[EXP_INTERRUPT][offset & 0x07];
+ break;
+
+ case 0xb700000:
+ data = m_registers[CHIP_CONFIG][offset & 0x03];
+ break;
+
+ case 0xb7a0100: case 0xb7a0101: case 0xb7a0102: case 0xb7a0103: case 0xb7a0104: case 0xb7a0105:
+ data = m_registers[PORT_CONTROL][offset & 0x1f];
+ break;
+
+ case 0xb800000: case 0xb800001:
+ data = m_registers[SYSTEM][offset & 0x07];
+ break;
+
+ case 0xb800100: case 0xb800101:
+ data = m_registers[SYSTEM_TIMER][offset & 0x07];
+ break;
+
+ default:
+ logerror("oki_reg_r: Unhandled register %08x\n", reg_addr);
+ break;
+ }
+
+ return data;
+}
+
+void bbc_tube_arm7_device::oki_reg_w(offs_t offset, uint32_t data)
+{
+ uint32_t reg_addr = 0x78000000 + (offset * 4);
+
+ switch (reg_addr >> 4)
+ {
+ case 0x7800000: case 0x7800001: case 0x7800002:
+ m_registers[INTERRUPT][offset & 0x0f] = data;
+ if (reg_addr == 0x78000028) // CILCL
+ {
+ m_registers[INTERRUPT][6] = 0; // CIL
+ }
+ update_interrupts();
+ break;
+
+ case 0x7810000:
+ m_registers[EXT_MEMORY][offset & 0x03] = data;
+ break;
+
+ case 0x7820000: case 0x7820001:
+ m_registers[CACHE_MEMORY][offset & 0x07] = data;
+ break;
+
+ case 0x7818000: case 0x7818001:
+ m_registers[DRAM_CONTROL][offset & 0x07] = data;
+ break;
+
+ case 0x7bf0000: case 0x7bf0001:
+ m_registers[EXP_INTERRUPT][offset & 0x07] = data;
+ update_interrupts();
+ break;
+
+ case 0xb700000:
+ m_registers[CHIP_CONFIG][offset & 0x03] = data;
+ update_bank0();
+ break;
+
+ case 0xb7a0100: case 0xb7a0101: case 0xb7a0102: case 0xb7a0103: case 0xb7a0104: case 0xb7a0105:
+ m_registers[PORT_CONTROL][offset & 0x1f] = data;
+ break;
+
+ case 0xb800000: case 0xb800001:
+ m_registers[SYSTEM][offset & 0x07] = data;
+ update_bank0();
+ break;
+
+ case 0xb800100: case 0xb800101:
+ m_registers[SYSTEM_TIMER][offset & 0x07] = data;
+ break;
+
+ default:
+ logerror("oki_reg_w: Unhandled register %08x = %04x\n", reg_addr, data);
+ break;
+ }
+}
diff --git a/src/devices/bus/bbc/tube/tube_arm7.h b/src/devices/bus/bbc/tube/tube_arm7.h
new file mode 100644
index 00000000000..bf4c6f157e8
--- /dev/null
+++ b/src/devices/bus/bbc/tube/tube_arm7.h
@@ -0,0 +1,93 @@
+// license:BSD-3-Clause
+// copyright-holders:Nigel Barnes
+/**********************************************************************
+
+ Sprow ARM7TDMI Co-Processor
+
+ http://www.sprow.co.uk/bbc/armcopro.htm
+
+**********************************************************************/
+
+#ifndef MAME_BUS_BBC_TUBE_TUBE_ARM7_H
+#define MAME_BUS_BBC_TUBE_TUBE_ARM7_H
+
+#pragma once
+
+#include "tube.h"
+#include "cpu/arm7/arm7.h"
+#include "machine/ram.h"
+#include "machine/tube.h"
+
+//**************************************************************************
+// TYPE DEFINITIONS
+//**************************************************************************
+
+// ======================> bbc_tube_arm7_device
+
+class bbc_tube_arm7_device :
+ public device_t,
+ public device_bbc_tube_interface
+{
+ enum
+ {
+ INTERRUPT = 0, // 7800_0000
+ EXT_MEMORY, // 7810_0000
+ DRAM_CONTROL, // 7818_0000
+ CACHE_MEMORY, // 7820_0000
+ EXP_INTERRUPT, // 7BF0_0000
+ CHIP_CONFIG, // B700_0000
+ PORT_CONTROL, // B7A0_1000
+ SYSTEM, // B800_0000
+ SYSTEM_TIMER, // B800_1000
+ NUM_REGS
+ };
+
+public:
+ // construction/destruction
+ bbc_tube_arm7_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
+
+protected:
+ // device-level overrides
+ virtual void device_start() override ATTR_COLD;
+ virtual void device_reset() override ATTR_COLD;
+
+ // optional information overrides
+ virtual void device_add_mconfig(machine_config &config) override ATTR_COLD;
+ virtual const tiny_rom_entry *device_rom_region() const override ATTR_COLD;
+
+ virtual uint8_t host_r(offs_t offset) override;
+ virtual void host_w(offs_t offset, uint8_t data) override;
+
+private:
+ required_device<cpu_device> m_maincpu;
+ required_memory_region m_flash;
+ required_device<tube_device> m_ula;
+ required_device<ram_device> m_ram;
+ memory_view m_bank0_view;
+
+ void arm7_map(address_map &map) ATTR_COLD;
+
+ void prst_w(int state);
+
+ uint32_t oki_reg_r(offs_t offset);
+ void oki_reg_w(offs_t offset, uint32_t data);
+
+ // registers
+ uint32_t m_registers[NUM_REGS][32];
+ uint8_t m_tube10;
+
+ void update_bank0();
+ void update_interrupts();
+
+ void efiq_w(int state);
+ void exint3_w(int state);
+
+ int m_efiq_state;
+ int m_exint3_state;
+};
+
+
+// device type definition
+DECLARE_DEVICE_TYPE(BBC_TUBE_ARM7, bbc_tube_arm7_device)
+
+#endif // MAME_BUS_BBC_TUBE_TUBE_ARM7_H
diff --git a/src/devices/bus/bbc/tube/tube_casper.cpp b/src/devices/bus/bbc/tube/tube_casper.cpp
index c01f80487e2..ea2734159f9 100644
--- a/src/devices/bus/bbc/tube/tube_casper.cpp
+++ b/src/devices/bus/bbc/tube/tube_casper.cpp
@@ -26,7 +26,7 @@ DEFINE_DEVICE_TYPE(BBC_TUBE_CASPER, bbc_tube_casper_device, "bbc_tube_casper", "
void bbc_tube_casper_device::tube_casper_mem(address_map &map)
{
map(0x00000, 0x03fff).rom().region("casper_rom", 0);
- map(0x10000, 0x1001f).m("via6522_1", FUNC(via6522_device::map)).umask16(0x00ff);
+ map(0x10000, 0x1001f).m(m_via[1], FUNC(via6522_device::map)).umask16(0x00ff);
map(0x20000, 0x3ffff).ram();
}
@@ -35,9 +35,9 @@ void bbc_tube_casper_device::tube_casper_mem(address_map &map)
//-------------------------------------------------
ROM_START( tube_casper )
- ROM_REGION(0x4000, "casper_rom", 0)
- ROM_LOAD16_BYTE("casper.ic9", 0x0000, 0x2000, CRC(4105cbf4) SHA1(a3efeb6fb144da55b47c718239967ed0af4fff72))
- ROM_LOAD16_BYTE("casper.ic10", 0x0001, 0x2000, CRC(f25bc320) SHA1(297db56283bb3164c31c21331837213cea426837))
+ ROM_REGION16_BE(0x4000, "casper_rom", 0)
+ ROM_LOAD16_BYTE("casper.ic9", 0x0001, 0x2000, CRC(4105cbf4) SHA1(a3efeb6fb144da55b47c718239967ed0af4fff72))
+ ROM_LOAD16_BYTE("casper.ic10", 0x0000, 0x2000, CRC(f25bc320) SHA1(297db56283bb3164c31c21331837213cea426837))
ROM_REGION(0x8000, "exp_rom", 0)
ROM_LOAD("rom1.rom", 0x0000, 0x4000, CRC(602b6a36) SHA1(7b24746dbcacb8772468532e92832d5c7f6648fd))
@@ -53,19 +53,18 @@ void bbc_tube_casper_device::device_add_mconfig(machine_config &config)
M68000(config, m_m68000, 4_MHz_XTAL);
m_m68000->set_addrmap(AS_PROGRAM, &bbc_tube_casper_device::tube_casper_mem);
- VIA6522(config, m_via6522_0, 4_MHz_XTAL / 2);
- m_via6522_0->writepb_handler().set(m_via6522_1, FUNC(via6522_device::write_pa));
- m_via6522_0->ca2_handler().set(m_via6522_1, FUNC(via6522_device::write_cb1));
- m_via6522_0->cb2_handler().set(m_via6522_1, FUNC(via6522_device::write_ca1));
- m_via6522_0->irq_handler().set(DEVICE_SELF_OWNER, FUNC(bbc_tube_slot_device::irq_w));
+ MOS6522(config, m_via[0], 4_MHz_XTAL / 2);
+ m_via[0]->writepb_handler().set(m_via[1], FUNC(via6522_device::write_pa));
+ m_via[0]->ca2_handler().set(m_via[1], FUNC(via6522_device::write_cb1));
+ m_via[0]->cb2_handler().set(m_via[1], FUNC(via6522_device::write_ca1));
+ m_via[0]->irq_handler().set(DEVICE_SELF_OWNER, FUNC(bbc_tube_slot_device::irq_w));
- VIA6522(config, m_via6522_1, 4_MHz_XTAL / 2);
- m_via6522_1->writepb_handler().set(m_via6522_0, FUNC(via6522_device::write_pa));
- m_via6522_1->ca2_handler().set(m_via6522_0, FUNC(via6522_device::write_cb1));
- m_via6522_1->cb2_handler().set(m_via6522_0, FUNC(via6522_device::write_ca1));
- m_via6522_1->irq_handler().set_inputline(m_m68000, M68K_IRQ_1);
+ MOS6522(config, m_via[1], 4_MHz_XTAL / 2);
+ m_via[1]->writepb_handler().set(m_via[0], FUNC(via6522_device::write_pa));
+ m_via[1]->ca2_handler().set(m_via[0], FUNC(via6522_device::write_cb1));
+ m_via[1]->cb2_handler().set(m_via[0], FUNC(via6522_device::write_ca1));
+ m_via[1]->irq_handler().set_inputline(m_m68000, M68K_IRQ_1);
- /* software lists */
SOFTWARE_LIST(config, "flop_ls_casper").set_original("bbc_flop_68000");
}
@@ -90,8 +89,7 @@ bbc_tube_casper_device::bbc_tube_casper_device(const machine_config &mconfig, co
: device_t(mconfig, BBC_TUBE_CASPER, tag, owner, clock),
device_bbc_tube_interface(mconfig, *this),
m_m68000(*this, "m68000"),
- m_via6522_0(*this, "via6522_0"),
- m_via6522_1(*this, "via6522_1"),
+ m_via(*this, "via%u", 0),
m_casper_rom(*this, "casper_rom")
{
}
@@ -111,10 +109,14 @@ void bbc_tube_casper_device::device_start()
uint8_t bbc_tube_casper_device::host_r(offs_t offset)
{
- return m_via6522_0->read(offset & 0xf);
+ if (offset & 0x10)
+ return m_via[0]->read(offset & 0xf);
+ else
+ return 0xfe;
}
void bbc_tube_casper_device::host_w(offs_t offset, uint8_t data)
{
- m_via6522_0->write(offset & 0xf, data);
+ if (offset & 0x10)
+ m_via[0]->write(offset & 0xf, data);
}
diff --git a/src/devices/bus/bbc/tube/tube_casper.h b/src/devices/bus/bbc/tube/tube_casper.h
index 965ac703355..9a6c278e900 100644
--- a/src/devices/bus/bbc/tube/tube_casper.h
+++ b/src/devices/bus/bbc/tube/tube_casper.h
@@ -6,9 +6,10 @@
**********************************************************************/
+#ifndef MAME_BUS_BBC_TUBE_TUBE_CASPER_H
+#define MAME_BUS_BBC_TUBE_TUBE_CASPER_H
-#ifndef MAME_BUS_BBC_TUBE_CASPER_H
-#define MAME_BUS_BBC_TUBE_CASPER_H
+#pragma once
#include "tube.h"
#include "cpu/m68000/m68000.h"
@@ -30,27 +31,25 @@ public:
protected:
// device-level overrides
- virtual void device_start() override;
+ virtual void device_start() override ATTR_COLD;
// optional information overrides
- virtual void device_add_mconfig(machine_config &config) override;
- virtual const tiny_rom_entry *device_rom_region() const override;
+ virtual void device_add_mconfig(machine_config &config) override ATTR_COLD;
+ virtual const tiny_rom_entry *device_rom_region() const override ATTR_COLD;
virtual uint8_t host_r(offs_t offset) override;
virtual void host_w(offs_t offset, uint8_t data) override;
private:
- required_device<cpu_device> m_m68000;
- required_device<via6522_device> m_via6522_0;
- required_device<via6522_device> m_via6522_1;
+ required_device<m68000_base_device> m_m68000;
+ required_device_array<via6522_device, 2> m_via;
required_memory_region m_casper_rom;
- void tube_casper_mem(address_map &map);
+ void tube_casper_mem(address_map &map) ATTR_COLD;
};
// device type definition
DECLARE_DEVICE_TYPE(BBC_TUBE_CASPER, bbc_tube_casper_device)
-
-#endif /* MAME_BUS_BBC_TUBE_CASPER_H */
+#endif // MAME_BUS_BBC_TUBE_TUBE_CASPER_H
diff --git a/src/devices/bus/bbc/tube/tube_cms6809.cpp b/src/devices/bus/bbc/tube/tube_cms6809.cpp
new file mode 100644
index 00000000000..43c86628f2a
--- /dev/null
+++ b/src/devices/bus/bbc/tube/tube_cms6809.cpp
@@ -0,0 +1,125 @@
+// license:BSD-3-Clause
+// copyright-holders:Nigel Barnes
+/**********************************************************************
+
+ CMS 6809 2nd Processor
+
+ Start with *FLEX:
+ f0 - OSCLI command
+ f1 - display help
+ CTRL+F - boot FLEX from ROM
+ U <drive> - boot from floppy drive
+
+**********************************************************************/
+
+
+#include "emu.h"
+#include "tube_cms6809.h"
+#include "softlist_dev.h"
+
+
+//**************************************************************************
+// DEVICE DEFINITIONS
+//**************************************************************************
+
+DEFINE_DEVICE_TYPE(BBC_TUBE_CMS6809, bbc_tube_cms6809_device, "bbc_tube_cms6809", "CMS 6809 2nd Processor")
+
+
+//-------------------------------------------------
+// ADDRESS_MAP( tube_cms6809_mem )
+//-------------------------------------------------
+
+void bbc_tube_cms6809_device::tube_cms6809_mem(address_map &map)
+{
+ map(0x0000, 0xffff).ram();
+ map(0xef00, 0xef0f).m(m_via[1], FUNC(via6522_device::map));
+ map(0xf000, 0xffff).rom().region("boot", 0);
+}
+
+//-------------------------------------------------
+// ROM( tube_cms6809 )
+//-------------------------------------------------
+
+ROM_START(tube_cms6809)
+ ROM_REGION(0x4000, "exp_rom", 0)
+ ROM_LOAD("cmsflex_v3.01.rom", 0x0000, 0x4000, CRC(87c7b09f) SHA1(7f2f8666298276713f6035f1dd12d1237cb8a81b))
+
+ ROM_REGION(0x1000, "boot", 0)
+ ROM_LOAD("cms6809_v6.rom", 0x0000, 0x1000, CRC(93e3b8f4) SHA1(f431f27941e13a92cdd0a9e2eda891c73d59d835))
+ROM_END
+
+//-------------------------------------------------
+// device_add_mconfig - add device configuration
+//-------------------------------------------------
+
+void bbc_tube_cms6809_device::device_add_mconfig(machine_config& config)
+{
+ MC6809(config, m_maincpu, 4_MHz_XTAL / 4);
+ m_maincpu->set_addrmap(AS_PROGRAM, &bbc_tube_cms6809_device::tube_cms6809_mem);
+
+ MOS6522(config, m_via[0], 4_MHz_XTAL / 4);
+ m_via[0]->writepb_handler().set(m_via[1], FUNC(via6522_device::write_pa));
+ m_via[0]->ca2_handler().set(m_via[1], FUNC(via6522_device::write_cb1));
+ m_via[0]->cb2_handler().set(m_via[1], FUNC(via6522_device::write_ca1));
+ m_via[0]->irq_handler().set(DEVICE_SELF_OWNER, FUNC(bbc_tube_slot_device::irq_w));
+
+ MOS6522(config, m_via[1], 4_MHz_XTAL / 4);
+ m_via[1]->writepb_handler().set(m_via[0], FUNC(via6522_device::write_pa));
+ m_via[1]->ca2_handler().set(m_via[0], FUNC(via6522_device::write_cb1));
+ m_via[1]->cb2_handler().set(m_via[0], FUNC(via6522_device::write_ca1));
+ m_via[1]->irq_handler().set_inputline(m_maincpu, M6809_IRQ_LINE);
+
+ //SOFTWARE_LIST(config, "flop_ls_6809").set_original("bbc_flop_6809").set_filter("CMS");
+}
+
+//-------------------------------------------------
+// rom_region - device-specific ROM region
+//-------------------------------------------------
+
+const tiny_rom_entry *bbc_tube_cms6809_device::device_rom_region() const
+{
+ return ROM_NAME( tube_cms6809 );
+}
+
+//**************************************************************************
+// LIVE DEVICE
+//**************************************************************************
+
+//-------------------------------------------------
+// bbc_tube_cms6809_device - constructor
+//-------------------------------------------------
+
+bbc_tube_cms6809_device::bbc_tube_cms6809_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
+ : device_t(mconfig, BBC_TUBE_CMS6809, tag, owner, clock)
+ , device_bbc_tube_interface(mconfig, *this)
+ , m_maincpu(*this, "maincpu")
+ , m_via(*this, "via%u", 0)
+{
+}
+
+//-------------------------------------------------
+// device_start - device-specific startup
+//-------------------------------------------------
+
+void bbc_tube_cms6809_device::device_start()
+{
+}
+
+
+//**************************************************************************
+// IMPLEMENTATION
+//**************************************************************************
+
+uint8_t bbc_tube_cms6809_device::host_r(offs_t offset)
+{
+ if (offset & 0x10)
+ return m_via[0]->read(offset & 0xf);
+ else
+ return 0xfe;
+}
+
+void bbc_tube_cms6809_device::host_w(offs_t offset, uint8_t data)
+{
+ if (offset & 0x10)
+ m_via[0]->write(offset & 0xf, data);
+}
diff --git a/src/devices/bus/bbc/tube/tube_cms6809.h b/src/devices/bus/bbc/tube/tube_cms6809.h
new file mode 100644
index 00000000000..2066de5d339
--- /dev/null
+++ b/src/devices/bus/bbc/tube/tube_cms6809.h
@@ -0,0 +1,54 @@
+// license:BSD-3-Clause
+// copyright-holders:Nigel Barnes
+/**********************************************************************
+
+ CMS 6809 2nd Processor
+
+**********************************************************************/
+
+#ifndef MAME_BUS_BBC_TUBE_TUBE_CMS6809_H
+#define MAME_BUS_BBC_TUBE_TUBE_CMS6809_H
+
+#pragma once
+
+#include "tube.h"
+#include "cpu/m6809/m6809.h"
+#include "machine/6522via.h"
+
+//**************************************************************************
+// TYPE DEFINITIONS
+//**************************************************************************
+
+// ======================> bbc_tube_cms6809_device
+
+class bbc_tube_cms6809_device :
+ public device_t,
+ public device_bbc_tube_interface
+{
+public:
+ // construction/destruction
+ bbc_tube_cms6809_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
+
+protected:
+ // device-level overrides
+ virtual void device_start() override ATTR_COLD;
+
+ // optional information overrides
+ virtual void device_add_mconfig(machine_config &config) override ATTR_COLD;
+ virtual const tiny_rom_entry *device_rom_region() const override ATTR_COLD;
+
+ virtual uint8_t host_r(offs_t offset) override;
+ virtual void host_w(offs_t offset, uint8_t data) override;
+
+private:
+ required_device<cpu_device> m_maincpu;
+ required_device_array<via6522_device, 2> m_via;
+
+ void tube_cms6809_mem(address_map &map) ATTR_COLD;
+};
+
+
+// device type definition
+DECLARE_DEVICE_TYPE(BBC_TUBE_CMS6809, bbc_tube_cms6809_device)
+
+#endif // MAME_BUS_BBC_TUBE_TUBE_CMS6809_H
diff --git a/src/devices/bus/bbc/tube/tube_matchbox.cpp b/src/devices/bus/bbc/tube/tube_matchbox.cpp
new file mode 100644
index 00000000000..7d8be65bd35
--- /dev/null
+++ b/src/devices/bus/bbc/tube/tube_matchbox.cpp
@@ -0,0 +1,1019 @@
+// license:BSD-3-Clause
+// copyright-holders:Nigel Barnes
+/**********************************************************************
+
+ Matchbox Co-Processor
+
+ Original firmware for the Matchbox co-processor can be found at:
+ https://github.com/hoglet67/CoPro6502/tree/master
+
+ Later developments of the client firmwares can be found at:
+ https://mdfs.net/Software/Tube/Matchbox/
+
+ TODO:
+ - fix PDP11 interrupt issues.
+
+**********************************************************************/
+
+#include "emu.h"
+#include "tube_matchbox.h"
+
+#include "cpu/arm/arm.h"
+#include "cpu/i86/i286.h"
+#include "cpu/m6502/r65c02.h"
+#include "cpu/m6809/m6809.h"
+#include "cpu/m68000/m68000.h"
+#include "cpu/ns32000/ns32000.h"
+#include "cpu/t11/t11.h"
+#include "cpu/z80/z80.h"
+#include "machine/ram.h"
+#include "machine/tube.h"
+
+#include "softlist_dev.h"
+
+
+namespace {
+
+class bbc_tube_matchbox_device : public device_t, public device_bbc_tube_interface
+{
+public:
+ bbc_tube_matchbox_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
+ : device_t(mconfig, BBC_TUBE_MATCHBOX, tag, owner, clock)
+ , device_bbc_tube_interface(mconfig, *this)
+ , m_ula(*this, "ula")
+ , m_ram(*this, "ram")
+ , m_soft_dip(0)
+ , m_prst(0)
+ , m_r65c102(*this, "r65c102")
+ , m_r65c102_rom(*this, "r65c102_rom")
+ , m_r65c102_view(*this, "r65c102_view")
+ , m_r65c102_bank(*this, "r65c102_bank%u", 0)
+ , m_z80(*this, "z80")
+ , m_z80_rom(*this, "z80_rom")
+ , m_z80_view(*this, "z80_view")
+ , m_i80286(*this, "i80286")
+ , m_i80286_rom(*this, "i80286_rom")
+ , m_irq_latch(0)
+ , m_m6809(*this, "m6809")
+ , m_m6809_rom(*this, "m6809_rom")
+ , m_m68000(*this, "m68000")
+ , m_m68000_rom(*this, "m68000_rom")
+ , m_m68000_view(*this, "m68000_view")
+ , m_pdp11(*this, "pdp11")
+ , m_pdp11_rom(*this, "pdp11_rom")
+ , m_irq_vector(0)
+ , m_arm2(*this, "arm2")
+ , m_arm2_rom(*this, "arm2_rom")
+ , m_ns32016(*this, "ns32016")
+ , m_ns32016_rom(*this, "ns32016_rom")
+ , m_ns32016_view(*this, "ns32016_view")
+ {
+ }
+
+ DECLARE_INPUT_CHANGED_MEMBER(dip_changed);
+
+protected:
+ // device_t overrides
+ virtual void device_start() override ATTR_COLD;
+ virtual void device_reset_after_children() override;
+
+ // optional information overrides
+ virtual void device_add_mconfig(machine_config &config) override ATTR_COLD;
+ virtual const tiny_rom_entry *device_rom_region() const override ATTR_COLD;
+ virtual ioport_constructor device_input_ports() const override ATTR_COLD;
+
+ virtual uint8_t host_r(offs_t offset) override;
+ virtual void host_w(offs_t offset, uint8_t data) override;
+
+private:
+ required_device<tube_device> m_ula;
+ required_device<ram_device> m_ram;
+
+ void pnmi_w(int state);
+ void pirq_w(int state);
+ void prst_w(int state);
+
+ uint8_t m_copro;
+ uint8_t m_soft_dip;
+ int m_prst;
+
+ // 65C102
+ required_device<r65c102_device> m_r65c102;
+ required_region_ptr<uint8_t> m_r65c102_rom;
+ memory_passthrough_handler m_r65c102_rom_shadow_tap;
+ memory_view m_r65c102_view;
+ required_memory_bank_array<8> m_r65c102_bank;
+
+ void r65c102_mem(address_map &map) ATTR_COLD;
+ void r65c102_reset(uint8_t dip);
+ void r65c102_bank_w(offs_t offset, uint8_t data);
+
+ // Z80
+ required_device<z80_device> m_z80;
+ required_region_ptr<uint8_t> m_z80_rom;
+ memory_view m_z80_view;
+
+ void z80_opcodes(address_map &map) ATTR_COLD;
+ void z80_io(address_map &map) ATTR_COLD;
+ void z80_mem(address_map &map) ATTR_COLD;
+ void z80_reset(uint8_t dip);
+ uint8_t z80_opcode_r(offs_t offset);
+
+ // 80286
+ required_device<i80286_cpu_device> m_i80286;
+ required_region_ptr<uint16_t> m_i80286_rom;
+
+ void i80286_io(address_map &map) ATTR_COLD;
+ void i80286_mem(address_map &map) ATTR_COLD;
+
+ uint8_t m_irq_latch;
+
+ // 6809
+ required_device<cpu_device> m_m6809;
+ required_region_ptr<uint8_t> m_m6809_rom;
+ memory_passthrough_handler m_m6809_rom_shadow_tap;
+
+ void m6809_mem(address_map &map) ATTR_COLD;
+ void m6809_reset();
+ uint8_t m6809_mem_r(offs_t offset);
+ bool m_m6809_rom_enabled;
+ int m_m6809_bs_hack_cnt;
+
+ // 68000
+ required_device<m68000_base_device> m_m68000;
+ required_region_ptr<uint16_t> m_m68000_rom;
+ memory_passthrough_handler m_m68000_rom_shadow_tap;
+ memory_view m_m68000_view;
+
+ void m68000_mem(address_map &map) ATTR_COLD;
+ void m68000_reset();
+
+ // PDP-11
+ required_device<t11_device> m_pdp11;
+ required_region_ptr<uint16_t> m_pdp11_rom;
+
+ void pdp11_mem(address_map &map) ATTR_COLD;
+ void pdp11_reset();
+ //uint8_t irq_callback(offs_t offset);
+ void pdp11_irq_encoder(int irq, int state);
+ uint16_t m_irqs;
+ uint16_t m_irq_vector;
+
+ // ARM2
+ required_device<arm_cpu_device> m_arm2;
+ required_region_ptr<uint32_t> m_arm2_rom;
+ memory_passthrough_handler m_arm2_rom_shadow_tap;
+
+ void arm2_mem(address_map &map) ATTR_COLD;
+ void arm2_reset();
+
+ // 32016
+ required_device<ns32016_device> m_ns32016;
+ required_region_ptr<uint16_t> m_ns32016_rom;
+ memory_passthrough_handler m_ns32016_rom_shadow_tap;
+ memory_view m_ns32016_view;
+
+ void ns32016_mem(address_map &map) ATTR_COLD;
+ void ns32016_reset();
+};
+
+
+//-------------------------------------------------
+// ADDRESS_MAP( r65c102_mem )
+//-------------------------------------------------
+
+void bbc_tube_matchbox_device::r65c102_mem(address_map &map)
+{
+ map(0x0000, 0xffff).view(m_r65c102_view);
+ m_r65c102_view[0](0x0000, 0xffff).rw(m_ram, FUNC(ram_device::read), FUNC(ram_device::write));
+ m_r65c102_view[0](0xf800, 0xffff).rom().region("r65c102_rom", 0);
+ m_r65c102_view[1](0x0000, 0x1fff).bankrw("r65c102_bank0");
+ m_r65c102_view[1](0x2000, 0x3fff).bankrw("r65c102_bank1");
+ m_r65c102_view[1](0x4000, 0x5fff).bankrw("r65c102_bank2");
+ m_r65c102_view[1](0x6000, 0x7fff).bankrw("r65c102_bank3");
+ m_r65c102_view[1](0x8000, 0x9fff).bankrw("r65c102_bank4");
+ m_r65c102_view[1](0xa000, 0xbfff).bankrw("r65c102_bank5");
+ m_r65c102_view[1](0xc000, 0xdfff).bankrw("r65c102_bank6");
+ m_r65c102_view[1](0xe000, 0xffff).bankrw("r65c102_bank7");
+ m_r65c102_view[1](0xfee0, 0xfee7).w(FUNC(bbc_tube_matchbox_device::r65c102_bank_w));
+ map(0xfef8, 0xfeff).rw("ula", FUNC(tube_device::parasite_r), FUNC(tube_device::parasite_w));
+}
+
+
+//-------------------------------------------------
+// ADDRESS_MAP( z80_mem )
+//-------------------------------------------------
+
+void bbc_tube_matchbox_device::z80_mem(address_map &map)
+{
+ map(0x0000, 0xffff).rw(m_ram, FUNC(ram_device::read), FUNC(ram_device::write));
+ map(0x0000, 0x0fff).view(m_z80_view);
+ m_z80_view[0](0x0000, 0x0fff).rom().region("z80_rom", 0);
+}
+
+void bbc_tube_matchbox_device::z80_opcodes(address_map &map)
+{
+ map(0x0000, 0xffff).r(FUNC(bbc_tube_matchbox_device::z80_opcode_r));
+}
+
+void bbc_tube_matchbox_device::z80_io(address_map &map)
+{
+ map.global_mask(0xff);
+ map(0x00, 0x07).rw("ula", FUNC(tube_device::parasite_r), FUNC(tube_device::parasite_w));
+}
+
+
+//-------------------------------------------------
+// ADDRESS_MAP( i286_mem )
+//-------------------------------------------------
+
+void bbc_tube_matchbox_device::i80286_mem(address_map &map)
+{
+ map.global_mask(0xfffff);
+ map(0x00000, 0xfffff).rw(m_ram, FUNC(ram_device::read), FUNC(ram_device::write));
+ map(0xf0000, 0xf3fff).rom().region("i80286_rom", 0).mirror(0xc000);
+}
+
+void bbc_tube_matchbox_device::i80286_io(address_map &map)
+{
+ map.unmap_value_high();
+ map(0x60, 0x60).lw8(NAME([this](uint8_t data) { m_irq_latch = data; }));
+ map(0x80, 0x8f).rw("ula", FUNC(tube_device::parasite_r), FUNC(tube_device::parasite_w)).umask16(0x00ff);
+}
+
+
+//-------------------------------------------------
+// ADDRESS_MAP( m6809_mem )
+//-------------------------------------------------
+
+void bbc_tube_matchbox_device::m6809_mem(address_map &map)
+{
+ map(0x0000, 0xffff).r(FUNC(bbc_tube_matchbox_device::m6809_mem_r)).w(m_ram, FUNC(ram_device::write));
+ map(0xfee0, 0xfeef).rw("ula", FUNC(tube_device::parasite_r), FUNC(tube_device::parasite_w));
+}
+
+
+//-------------------------------------------------
+// ADDRESS_MAP( m68000_mem )
+//-------------------------------------------------
+
+void bbc_tube_matchbox_device::m68000_mem(address_map &map)
+{
+ map.global_mask(0x3fffff);
+ map(0x000000, 0x3fffff).view(m_m68000_view);
+ m_m68000_view[0](0x000000, 0x007fff).mirror(0x3f8000).rom().region("m68000_rom", 0);
+ m_m68000_view[1](0x000000, 0x0fffff).mirror(0x300000).rw(m_ram, FUNC(ram_device::read), FUNC(ram_device::write));
+ map(0x3e0000, 0x3e000f).mirror(0x00fff0).rw("ula", FUNC(tube_device::parasite_r), FUNC(tube_device::parasite_w));
+ map(0x3f0000, 0x3f7fff).mirror(0x008000).rom().region("m68000_rom", 0);
+}
+
+
+//-------------------------------------------------
+// ADDRESS_MAP( pdp11_mem )
+//-------------------------------------------------
+
+void bbc_tube_matchbox_device::pdp11_mem(address_map &map)
+{
+ map(0x0000, 0xffff).rw(m_ram, FUNC(ram_device::read), FUNC(ram_device::write));
+ map(0xf800, 0xffff).rom().region("pdp11_rom", 0);
+ map(0xfff0, 0xffff).rw("ula", FUNC(tube_device::parasite_r), FUNC(tube_device::parasite_w)).umask16(0x00ff);
+}
+
+
+//-------------------------------------------------
+// ADDRESS_MAP( arm2_mem )
+//-------------------------------------------------
+
+void bbc_tube_matchbox_device::arm2_mem(address_map &map)
+{
+ map.unmap_value_high();
+ map(0x0000000, 0x0ffffff).noprw();
+ map(0x1000000, 0x100001f).rw(m_ula, FUNC(tube_device::parasite_r), FUNC(tube_device::parasite_w)).umask32(0x000000ff);
+ map(0x3000000, 0x3003fff).rom().region("arm2_rom", 0).mirror(0xc000);
+}
+
+
+//-------------------------------------------------
+// ADDRESS_MAP( ns32016_mem )
+//-------------------------------------------------
+
+void bbc_tube_matchbox_device::ns32016_mem(address_map &map)
+{
+ map(0x000000, 0xffffff).view(m_ns32016_view);
+ m_ns32016_view[0](0x000000, 0x007fff).mirror(0xff8000).rom().region("ns32016_rom", 0);
+ m_ns32016_view[1](0x000000, 0x1fffff).mirror(0x600000).rw(m_ram, FUNC(ram_device::read), FUNC(ram_device::write));
+ m_ns32016_view[1](0x800000, 0xffffff).noprw();
+ map(0xf00000, 0xf07fff).mirror(0x038000).rom().region("ns32016_rom", 0);
+ map(0xfffff0, 0xffffff).rw("ula", FUNC(tube_device::parasite_r), FUNC(tube_device::parasite_w)).umask16(0x00ff);
+}
+
+
+//-------------------------------------------------
+// INPUT_PORTS( matchbox )
+//-------------------------------------------------
+
+static INPUT_PORTS_START(matchbox)
+ PORT_START("DIPSW")
+ PORT_DIPNAME(0x0f, 0x00, "Co-Processor") PORT_CHANGED_MEMBER(DEVICE_SELF, FUNC(bbc_tube_matchbox_device::dip_changed), 0)
+ PORT_DIPSETTING(0x00, "65C102 3 MHz")
+ PORT_DIPSETTING(0x01, "65C102 4 MHz")
+ PORT_DIPSETTING(0x02, "65C102 16 MHz")
+ PORT_DIPSETTING(0x03, "65C102 64 MHz")
+ PORT_DIPSETTING(0x04, "Z80 8 MHz")
+ PORT_DIPSETTING(0x05, "Z80 32 MHz")
+ PORT_DIPSETTING(0x06, "Z80 56 MHz")
+ PORT_DIPSETTING(0x07, "Z80 112 MHz")
+ PORT_DIPSETTING(0x08, "80286 12 MHz")
+ PORT_DIPSETTING(0x09, "6809 4 MHz")
+ PORT_DIPSETTING(0x0a, "68000 16 MHz")
+ PORT_DIPSETTING(0x0b, "PDP-11 32 MHz")
+ PORT_DIPSETTING(0x0c, "ARM2 32 MHz")
+ PORT_DIPSETTING(0x0d, "32016 32 MHz")
+ PORT_DIPSETTING(0x0e, "Null / SPI")
+ PORT_DIPSETTING(0x0f, "BIST")
+INPUT_PORTS_END
+
+INPUT_CHANGED_MEMBER(bbc_tube_matchbox_device::dip_changed)
+{
+ m_soft_dip = newval;
+}
+
+//-------------------------------------------------
+// input_ports - device-specific input ports
+//-------------------------------------------------
+
+ioport_constructor bbc_tube_matchbox_device::device_input_ports() const
+{
+ return INPUT_PORTS_NAME( matchbox );
+}
+
+
+//-------------------------------------------------
+// ROM( matchbox )
+//-------------------------------------------------
+
+ROM_START( matchbox )
+ ROM_REGION(0x0800, "r65c102_rom", 0)
+ ROM_LOAD("client65v2.bin", 0x0000, 0x0800, CRC(866a5b7b) SHA1(40e2de0443e3447483fe6ee43fe66bac87fed1c4)) // latest from https://mdfs.net/Software/Tube/Matchbox/
+
+ ROM_REGION(0x1000, "z80_rom", 0)
+ ROM_LOAD("tuberom_z80.rom", 0x0000, 0x1000, CRC(229a764c) SHA1(9702f9a821e5beddd04f7f71c4a07ab660fcc962)) // from LX9CoProCombined_20171007_0719_dmb firmware
+
+ ROM_REGION16_LE(0x4000, "i80286_rom", 0)
+ ROM_LOAD("client86_101.bin", 0x0000, 0x4000, CRC(6da326ce) SHA1(8acaf42a4a6b5f62f6be5e62df5fcffbf48890dd)) // latest from https://mdfs.net/Software/Tube/Matchbox/
+
+ ROM_REGION(0x0800, "m6809_rom", 0)
+ ROM_LOAD("client09_106.bin", 0x0000, 0x0800, CRC(5f499c5b) SHA1(5c615d16f579b4b6fb42f8ff1188b1f3404425fa)) // latest from https://mdfs.net/Software/Tube/Matchbox/
+
+ ROM_REGION16_BE(0x8000, "m68000_rom", 0)
+ ROM_LOAD("tuberom_68000.bin", 0x0000, 0x8000, CRC(906d6733) SHA1(c376a6741e40d5b37a2e1fa7c2d766b9a575c57c)) // from LX9CoProCombined_20171007_0719_dmb firmware
+
+ ROM_REGION16_LE(0x0800, "pdp11_rom", 0)
+ ROM_LOAD("client11_040.bin", 0x0000, 0x0800, CRC(ab409e78) SHA1(3756c0b78f94c6a79d077c25c5c74c55cfacf65c)) // latest from https://mdfs.net/Software/Tube/Matchbox/
+
+ ROM_REGION32_LE(0x4000, "arm2_rom", 0)
+ ROM_LOAD("armeval_101.rom", 0x0000, 0x4000, CRC(cabd6a1b) SHA1(9f451f53a5cb6f649fa8a2946e22f1ee49199a93))
+
+ ROM_REGION16_LE(0x8000, "ns32016_rom", 0)
+ ROM_LOAD("tuberom_32016.bin", 0x0000, 0x8000, CRC(11dfca39) SHA1(80343cb198b03ea91c8790d765f7d3869ba9bb32)) // from LX9CoProCombined_20171007_0719_dmb firmware
+ROM_END
+
+//-------------------------------------------------
+// rom_region - device-specific ROM region
+//-------------------------------------------------
+
+const tiny_rom_entry *bbc_tube_matchbox_device::device_rom_region() const
+{
+ return ROM_NAME( matchbox );
+}
+
+
+//-------------------------------------------------
+// device_add_mconfig - add device configuration
+//-------------------------------------------------
+
+void bbc_tube_matchbox_device::device_add_mconfig(machine_config &config)
+{
+ TUBE(config, m_ula);
+ m_ula->pnmi_handler().set(FUNC(bbc_tube_matchbox_device::pnmi_w));
+ m_ula->pirq_handler().set(FUNC(bbc_tube_matchbox_device::pirq_w));
+ m_ula->prst_handler().set(FUNC(bbc_tube_matchbox_device::prst_w));
+
+ RAM(config, m_ram).set_default_size("2MB");
+
+ // 65C102
+ R65C102(config, m_r65c102, 32_MHz_XTAL);
+ m_r65c102->set_addrmap(AS_PROGRAM, &bbc_tube_matchbox_device::r65c102_mem);
+
+ SOFTWARE_LIST(config, "flop_ls_6502").set_original("bbc_flop_6502");
+
+ // Z80
+ Z80(config, m_z80, 32_MHz_XTAL);
+ m_z80->set_addrmap(AS_PROGRAM, &bbc_tube_matchbox_device::z80_mem);
+ m_z80->set_addrmap(AS_OPCODES, &bbc_tube_matchbox_device::z80_opcodes);
+ m_z80->set_addrmap(AS_IO, &bbc_tube_matchbox_device::z80_io);
+ m_z80->set_irq_acknowledge_callback(NAME([](device_t &, int) -> int { return 0xfe; }));
+
+ SOFTWARE_LIST(config, "flop_ls_z80").set_original("bbc_flop_z80");
+
+ // 80286
+ I80286(config, m_i80286, 32_MHz_XTAL * 6 / 16);
+ m_i80286->set_addrmap(AS_PROGRAM, &bbc_tube_matchbox_device::i80286_mem);
+ m_i80286->set_addrmap(AS_IO, &bbc_tube_matchbox_device::i80286_io);
+ m_i80286->set_irq_acknowledge_callback(NAME([this](device_t &, int) -> int { return m_irq_latch; }));
+
+ SOFTWARE_LIST(config, "flop_ls_80186").set_original("bbc_flop_80186");
+ SOFTWARE_LIST(config, "pc_disk_list").set_compatible("ibm5150");
+
+ // 6809
+ MC6809(config, m_m6809, 32_MHz_XTAL / 2);
+ m_m6809->set_addrmap(AS_PROGRAM, &bbc_tube_matchbox_device::m6809_mem);
+ m_m6809->set_irq_acknowledge_callback(NAME([this](device_t&, int) -> int { m_m6809_bs_hack_cnt = 3; return 0; }));
+
+ // 68000
+ M68000(config, m_m68000, 32_MHz_XTAL / 4);
+ m_m68000->set_addrmap(AS_PROGRAM, &bbc_tube_matchbox_device::m68000_mem);
+
+ SOFTWARE_LIST(config, "flop_ls_68000").set_original("bbc_flop_68000");
+
+ // PDP-11
+ T11(config, m_pdp11, 32_MHz_XTAL);
+ m_pdp11->set_initial_mode(6 << 13);
+ m_pdp11->set_addrmap(AS_PROGRAM, &bbc_tube_matchbox_device::pdp11_mem);
+ m_pdp11->in_iack().set([this](uint8_t addr) { return m_irq_vector; });
+
+ // ARM2
+ ARM(config, m_arm2, 32_MHz_XTAL);
+ m_arm2->set_addrmap(AS_PROGRAM, &bbc_tube_matchbox_device::arm2_mem);
+
+ SOFTWARE_LIST(config, "flop_ls_arm").set_original("bbc_flop_arm");
+
+ // 32016
+ NS32016(config, m_ns32016, 32_MHz_XTAL);
+ m_ns32016->set_addrmap(AS_PROGRAM, &bbc_tube_matchbox_device::ns32016_mem);
+
+ SOFTWARE_LIST(config, "flop_ls_32016").set_original("bbc_flop_32016");
+}
+
+
+//-------------------------------------------------
+// device_start - device-specific startup
+//-------------------------------------------------
+
+void bbc_tube_matchbox_device::device_start()
+{
+ m_prst = 0;
+}
+
+
+//-------------------------------------------------
+// device_reset_after_children - reset after child devices
+//-------------------------------------------------
+
+void bbc_tube_matchbox_device::device_reset_after_children()
+{
+ m_r65c102->set_input_line(INPUT_LINE_RESET, ASSERT_LINE);
+ m_z80->set_input_line(INPUT_LINE_RESET, ASSERT_LINE);
+ m_i80286->set_input_line(INPUT_LINE_RESET, ASSERT_LINE);
+ m_m6809->set_input_line(INPUT_LINE_RESET, ASSERT_LINE);
+ m_m68000->set_input_line(INPUT_LINE_RESET, ASSERT_LINE);
+ m_pdp11->set_input_line(INPUT_LINE_RESET, ASSERT_LINE);
+ m_arm2->set_input_line(INPUT_LINE_RESET, ASSERT_LINE);
+ m_ns32016->set_input_line(INPUT_LINE_RESET, ASSERT_LINE);
+
+ m_copro = m_soft_dip;
+
+ switch (m_copro)
+ {
+ case 0x00: case 0x01: case 0x02: case 0x03:
+ r65c102_reset(m_copro);
+ m_r65c102->set_input_line(INPUT_LINE_RESET, m_prst);
+ break;
+
+ case 0x04: case 0x05: case 0x06: case 0x07:
+ z80_reset(m_copro);
+ m_z80->set_input_line(INPUT_LINE_RESET, m_prst);
+ break;
+
+ case 0x08:
+ m_i80286->set_input_line(INPUT_LINE_RESET, m_prst);
+ break;
+
+ case 0x09:
+ m6809_reset();
+ m_m6809->set_input_line(INPUT_LINE_RESET, m_prst);
+ break;
+
+ case 0x0a:
+ m68000_reset();
+ m_m68000->set_input_line(INPUT_LINE_RESET, m_prst);
+ break;
+
+ case 0x0b:
+ pdp11_reset();
+ m_pdp11->set_input_line(INPUT_LINE_RESET, m_prst);
+ break;
+
+ case 0x0c:
+ arm2_reset();
+ m_arm2->set_input_line(INPUT_LINE_RESET, m_prst);
+ break;
+
+ case 0x0d:
+ ns32016_reset();
+ m_ns32016->set_input_line(INPUT_LINE_RESET, m_prst);
+ break;
+
+ default:
+ break;
+ }
+}
+
+
+//-------------------------------------------------
+// device_reset - device-specific reset
+//-------------------------------------------------
+
+void bbc_tube_matchbox_device::r65c102_reset(uint8_t copro)
+{
+ address_space &program = m_r65c102->space(AS_PROGRAM);
+
+ // address map during booting
+ m_r65c102_view.select(0);
+
+ m_r65c102_rom_shadow_tap.remove();
+ m_r65c102_rom_shadow_tap = program.install_read_tap(
+ 0x0fef8, 0xfeff,
+ "rom_shadow_r",
+ [this](offs_t offset, u8 &data, u8 mem_mask)
+ {
+ if (!machine().side_effects_disabled())
+ {
+ // delete this tap
+ m_r65c102_rom_shadow_tap.remove();
+
+ // address map after booting
+ m_r65c102_view.select(1);
+ }
+
+ // return the original data
+ return data;
+ },
+ &m_r65c102_rom_shadow_tap);
+
+ for (int i = 0; i < 8; i++)
+ {
+ m_r65c102_bank[i]->set_base(m_ram->pointer() + (i * 0x2000));
+ }
+
+ switch (copro & 3)
+ {
+ case 0: // 3MHz
+ m_r65c102->set_clock_scale(1.0 / 11);
+
+ // original startup banner
+ m_r65c102_rom[0x06f] = '6';
+ m_r65c102_rom[0x070] = '5';
+ m_r65c102_rom[0x071] = 'C';
+ m_r65c102_rom[0x072] = '1';
+ m_r65c102_rom[0x073] = '0';
+ m_r65c102_rom[0x074] = '2';
+ m_r65c102_rom[0x075] = ' ';
+ m_r65c102_rom[0x076] = 'C';
+ m_r65c102_rom[0x077] = 'o';
+ m_r65c102_rom[0x078] = '-';
+ m_r65c102_rom[0x079] = 'P';
+ m_r65c102_rom[0x07a] = 'r';
+ m_r65c102_rom[0x07b] = 'o';
+ m_r65c102_rom[0x07c] = 'c';
+ m_r65c102_rom[0x07d] = 'e';
+ m_r65c102_rom[0x07e] = 's';
+ m_r65c102_rom[0x07f] = 's';
+ m_r65c102_rom[0x080] = 'o';
+ m_r65c102_rom[0x081] = 'r';
+ break;
+ case 1: // 4MHz
+ m_r65c102->set_clock_scale(1.0 / 8);
+
+ // patch startup banner
+ m_r65c102_rom[0x06f] = '0';
+ m_r65c102_rom[0x070] = '4';
+ m_r65c102_rom[0x071] = 'M';
+ m_r65c102_rom[0x072] = 'H';
+ m_r65c102_rom[0x073] = 'z';
+ m_r65c102_rom[0x074] = ' ';
+ m_r65c102_rom[0x075] = '6';
+ m_r65c102_rom[0x076] = '5';
+ m_r65c102_rom[0x077] = 'C';
+ m_r65c102_rom[0x078] = '1';
+ m_r65c102_rom[0x079] = '0';
+ m_r65c102_rom[0x07a] = '2';
+ m_r65c102_rom[0x07b] = ' ';
+ m_r65c102_rom[0x07c] = 'C';
+ m_r65c102_rom[0x07d] = 'o';
+ m_r65c102_rom[0x07e] = '-';
+ m_r65c102_rom[0x07f] = 'P';
+ m_r65c102_rom[0x080] = 'r';
+ m_r65c102_rom[0x081] = 'o';
+ break;
+ case 2: // 16MHz
+ m_r65c102->set_clock_scale(1.0 / 2);
+
+ // patch startup banner
+ m_r65c102_rom[0x06f] = '1';
+ m_r65c102_rom[0x070] = '6';
+ m_r65c102_rom[0x071] = 'M';
+ m_r65c102_rom[0x072] = 'H';
+ m_r65c102_rom[0x073] = 'z';
+ m_r65c102_rom[0x074] = ' ';
+ m_r65c102_rom[0x075] = '6';
+ m_r65c102_rom[0x076] = '5';
+ m_r65c102_rom[0x077] = 'C';
+ m_r65c102_rom[0x078] = '1';
+ m_r65c102_rom[0x079] = '0';
+ m_r65c102_rom[0x07a] = '2';
+ m_r65c102_rom[0x07b] = ' ';
+ m_r65c102_rom[0x07c] = 'C';
+ m_r65c102_rom[0x07d] = 'o';
+ m_r65c102_rom[0x07e] = '-';
+ m_r65c102_rom[0x07f] = 'P';
+ m_r65c102_rom[0x080] = 'r';
+ m_r65c102_rom[0x081] = 'o';
+ break;
+ case 3: // 64MHz
+ m_r65c102->set_clock_scale(1.0 * 2);
+
+ // patch startup banner
+ m_r65c102_rom[0x06f] = '6';
+ m_r65c102_rom[0x070] = '4';
+ m_r65c102_rom[0x071] = 'M';
+ m_r65c102_rom[0x072] = 'H';
+ m_r65c102_rom[0x073] = 'z';
+ m_r65c102_rom[0x074] = ' ';
+ m_r65c102_rom[0x075] = '6';
+ m_r65c102_rom[0x076] = '5';
+ m_r65c102_rom[0x077] = 'C';
+ m_r65c102_rom[0x078] = '1';
+ m_r65c102_rom[0x079] = '0';
+ m_r65c102_rom[0x07a] = '2';
+ m_r65c102_rom[0x07b] = ' ';
+ m_r65c102_rom[0x07c] = 'C';
+ m_r65c102_rom[0x07d] = 'o';
+ m_r65c102_rom[0x07e] = '-';
+ m_r65c102_rom[0x07f] = 'P';
+ m_r65c102_rom[0x080] = 'r';
+ m_r65c102_rom[0x081] = 'o';
+ break;
+ }
+}
+
+
+void bbc_tube_matchbox_device::z80_reset(uint8_t copro)
+{
+ // address map during booting
+ m_z80_view.select(0);
+
+ switch (copro & 3)
+ {
+ case 0: // 8MHz
+ m_z80->set_clock_scale(1.0 / 4);
+
+ // original startup banner
+ m_z80_rom[0x2a2] = '6';
+ m_z80_rom[0x2a3] = '4';
+ m_z80_rom[0x2a4] = 'K';
+ m_z80_rom[0x2a5] = ' ';
+ m_z80_rom[0x2a6] = '1';
+ m_z80_rom[0x2a7] = '.';
+ m_z80_rom[0x2a8] = '2';
+ m_z80_rom[0x2a9] = '1';
+ break;
+ case 1: // 32MHz
+ m_z80->set_clock_scale(1.0);
+
+ // patch startup banner
+ m_z80_rom[0x2a2] = 0x06;
+ m_z80_rom[0x2a3] = '3';
+ m_z80_rom[0x2a4] = '2';
+ m_z80_rom[0x2a5] = ' ';
+ m_z80_rom[0x2a6] = 'M';
+ m_z80_rom[0x2a7] = 'H';
+ m_z80_rom[0x2a8] = 'z';
+ m_z80_rom[0x2a9] = ' ';
+ break;
+ case 2: // 56MHz
+ m_z80->set_clock_scale(1.0 * (7.0 / 4));
+
+ // patch startup banner
+ m_z80_rom[0x2a2] = 0x06;
+ m_z80_rom[0x2a3] = '5';
+ m_z80_rom[0x2a4] = '6';
+ m_z80_rom[0x2a5] = ' ';
+ m_z80_rom[0x2a6] = 'M';
+ m_z80_rom[0x2a7] = 'H';
+ m_z80_rom[0x2a8] = 'z';
+ m_z80_rom[0x2a9] = ' ';
+ break;
+ case 3: // 112MHz
+ m_z80->set_clock_scale(1.0 * (7.0 / 2));
+
+ // patch startup banner
+ m_z80_rom[0x2a2] = '1';
+ m_z80_rom[0x2a3] = '1';
+ m_z80_rom[0x2a4] = '2';
+ m_z80_rom[0x2a5] = ' ';
+ m_z80_rom[0x2a6] = 'M';
+ m_z80_rom[0x2a7] = 'H';
+ m_z80_rom[0x2a8] = 'z';
+ m_z80_rom[0x2a9] = ' ';
+ break;
+ }
+}
+
+
+void bbc_tube_matchbox_device::m6809_reset()
+{
+ m_m6809_bs_hack_cnt = 0;
+
+ address_space &program = m_m6809->space(AS_PROGRAM);
+
+ // enable rom
+ m_m6809_rom_enabled = true;
+
+ m_m6809_rom_shadow_tap.remove();
+ m_m6809_rom_shadow_tap = program.install_read_tap(
+ 0x0fee0, 0xfeef,
+ "rom_shadow_r",
+ [this](offs_t offset, u8 &data, u8 mem_mask)
+ {
+ if (!machine().side_effects_disabled())
+ {
+ // delete this tap
+ m_m6809_rom_shadow_tap.remove();
+
+ // disable rom
+ m_m6809_rom_enabled = false;
+ }
+
+ // return the original data
+ return data;
+ },
+ &m_m6809_rom_shadow_tap);
+}
+
+
+void bbc_tube_matchbox_device::m68000_reset()
+{
+ address_space &program = m_m68000->space(AS_PROGRAM);
+
+ // address map during booting
+ m_m68000_view.select(0);
+
+ m_m68000_rom_shadow_tap.remove();
+ m_m68000_rom_shadow_tap = program.install_read_tap(
+ 0x3f0000, 0x3fffff,
+ "rom_shadow_r",
+ [this](offs_t offset, u16 &data, u16 mem_mask)
+ {
+ if (!machine().side_effects_disabled())
+ {
+ // delete this tap
+ m_m68000_rom_shadow_tap.remove();
+
+ // address map after booting
+ m_m68000_view.select(1);
+ }
+
+ // return the original data
+ return data;
+ },
+ &m_m68000_rom_shadow_tap);
+}
+
+
+void bbc_tube_matchbox_device::pdp11_reset()
+{
+ m_irqs = 0;
+
+ m_pdp11->set_input_line(t11_device::VEC_LINE, ASSERT_LINE);
+ m_pdp11->set_state_int(T11_PC, 0xf800);
+}
+
+
+void bbc_tube_matchbox_device::arm2_reset()
+{
+ address_space &program = m_arm2->space(AS_PROGRAM);
+
+ // enable the reset vector to be fetched from ROM
+ m_arm2->space(AS_PROGRAM).install_rom(0x000000, 0x003fff, 0x3fc000, m_arm2_rom);
+
+ m_arm2_rom_shadow_tap.remove();
+ m_arm2_rom_shadow_tap = program.install_write_tap(
+ 0x0000000, 0x01fffff,
+ "rom_shadow_w",
+ [this] (offs_t offset, u32 &data, u32 mem_mask)
+ {
+ // delete this tap
+ m_arm2_rom_shadow_tap.remove();
+
+ // install ram
+ m_arm2->space(AS_PROGRAM).install_ram(0x0000000, 0x01fffff, m_ram->pointer());
+ },
+ &m_arm2_rom_shadow_tap);
+}
+
+
+void bbc_tube_matchbox_device::ns32016_reset()
+{
+ address_space &program = m_ns32016->space(AS_PROGRAM);
+
+ // address map during booting
+ m_ns32016_view.select(0);
+
+ m_ns32016_rom_shadow_tap.remove();
+ m_ns32016_rom_shadow_tap = program.install_write_tap(
+ 0x000000, 0xffffff,
+ "rom_shadow_w",
+ [this] (offs_t offset, u16 &data, u16 mem_mask)
+ {
+ // delete this tap
+ m_ns32016_rom_shadow_tap.remove();
+
+ // address map after booting
+ m_ns32016_view.select(1);
+ },
+ &m_ns32016_rom_shadow_tap);
+}
+
+
+//**************************************************************************
+// IMPLEMENTATION
+//**************************************************************************
+
+uint8_t bbc_tube_matchbox_device::host_r(offs_t offset)
+{
+ if (m_copro < 14)
+ return m_ula->host_r(offset);
+ else
+ return 0xfe;
+}
+
+void bbc_tube_matchbox_device::host_w(offs_t offset, uint8_t data)
+{
+ if (m_copro < 14)
+ m_ula->host_w(offset, data);
+
+ if (offset == 0x06)
+ m_soft_dip = data;
+}
+
+void bbc_tube_matchbox_device::pnmi_w(int state)
+{
+ switch (m_copro)
+ {
+ case 0x00: case 0x01: case 0x02: case 0x03:
+ m_r65c102->set_input_line(R65C02_NMI_LINE, state);
+ break;
+ case 0x04: case 0x05: case 0x06: case 0x07:
+ m_z80->set_input_line(INPUT_LINE_NMI, state);
+ break;
+ case 0x08:
+ m_i80286->set_input_line(INPUT_LINE_NMI, state);
+ break;
+ case 0x09:
+ m_m6809->set_input_line(M6809_IRQ_LINE, state);
+ break;
+ case 0x0a:
+ m_m68000->set_input_line(M68K_IRQ_5, state);
+ break;
+ case 0x0b:
+ m_irq_vector = 0x80;
+ pdp11_irq_encoder(7, state);
+ break;
+ case 0x0c:
+ m_arm2->set_input_line(ARM_FIRQ_LINE, state);
+ break;
+ case 0x0d:
+ m_ns32016->set_input_line(INPUT_LINE_NMI, state);
+ break;
+ }
+}
+
+void bbc_tube_matchbox_device::pirq_w(int state)
+{
+ switch (m_copro)
+ {
+ case 0x00: case 0x01: case 0x02: case 0x03:
+ m_r65c102->set_input_line(R65C02_IRQ_LINE, state);
+ break;
+ case 0x04: case 0x05: case 0x06: case 0x07:
+ m_z80->set_input_line(INPUT_LINE_IRQ0, state);
+ break;
+ case 0x08:
+ m_i80286->set_input_line(INPUT_LINE_INT0, state);
+ break;
+ case 0x09:
+ m_m6809->set_input_line(M6809_FIRQ_LINE, state);
+ break;
+ case 0x0a:
+ m_m68000->set_input_line(M68K_IRQ_2, state);
+ break;
+ case 0x0b:
+ m_irq_vector = 0x84;
+ pdp11_irq_encoder(6, state);
+ break;
+ case 0x0c:
+ m_arm2->set_input_line(ARM_IRQ_LINE, state);
+ break;
+ case 0x0d:
+ m_ns32016->set_input_line(INPUT_LINE_IRQ0, state);
+ break;
+ }
+}
+
+void bbc_tube_matchbox_device::prst_w(int state)
+{
+ m_prst = state;
+
+ device_reset_after_children();
+}
+
+
+//-------------------------------------------------
+// 65C102
+//-------------------------------------------------
+
+void bbc_tube_matchbox_device::r65c102_bank_w(offs_t offset, uint8_t data)
+{
+ if (BIT(data, 7))
+ m_r65c102_bank[offset & 7]->set_base(m_ram->pointer() + (data & 0x7f) * 0x2000 + 0x100000); // external RAM
+ else
+ m_r65c102_bank[offset & 7]->set_base(m_ram->pointer() + (data & 0x07) * 0x2000); // internal RAM
+}
+
+
+//-------------------------------------------------
+// Z80
+//-------------------------------------------------
+
+uint8_t bbc_tube_matchbox_device::z80_opcode_r(offs_t offset)
+{
+ if (!machine().side_effects_disabled())
+ {
+ if (offset == 0x0066 && m_z80->input_line_state(INPUT_LINE_NMI))
+ m_z80_view.select(0);
+ else if (offset & 0x8000)
+ m_z80_view.disable();
+ }
+ return m_z80->space(AS_PROGRAM).read_byte(offset);
+}
+
+
+//-------------------------------------------------
+// 6809
+//-------------------------------------------------
+
+uint8_t bbc_tube_matchbox_device::m6809_mem_r(offs_t offset)
+{
+ if (m_m6809_bs_hack_cnt > 0)
+ {
+ // BA/BS is decoded so that when vectors are fetched A8 is toggled so
+ // vectors are fetched from &FEFx instead of &FFFx
+ offset ^= 0x100;
+ m_m6809_bs_hack_cnt--;
+ }
+
+ if (m_m6809_rom_enabled && (offset >= 0xf800))
+ return m_m6809_rom[offset & 0x7ff];
+ else
+ return m_ram->pointer()[offset];
+}
+
+
+//-------------------------------------------------
+// PDP-11
+//-------------------------------------------------
+
+void bbc_tube_matchbox_device::pdp11_irq_encoder(int irq, int state)
+{
+ if (state == ASSERT_LINE)
+ m_irqs |= (1 << irq);
+ else
+ m_irqs &= ~(1 << irq);
+
+ int i;
+ for (i = 15; i > 0; i--)
+ {
+ if (m_irqs & (1 << i))
+ break;
+ }
+ m_pdp11->set_input_line(t11_device::CP3_LINE, (i & 8) ? ASSERT_LINE : CLEAR_LINE);
+ m_pdp11->set_input_line(t11_device::CP2_LINE, (i & 4) ? ASSERT_LINE : CLEAR_LINE);
+ m_pdp11->set_input_line(t11_device::CP1_LINE, (i & 2) ? ASSERT_LINE : CLEAR_LINE);
+ m_pdp11->set_input_line(t11_device::CP0_LINE, (i & 1) ? ASSERT_LINE : CLEAR_LINE);
+}
+
+} // anonymous namespace
+
+
+DEFINE_DEVICE_TYPE_PRIVATE(BBC_TUBE_MATCHBOX, device_bbc_tube_interface, bbc_tube_matchbox_device, "bbc_tube_matchbox", "Matchbox Co-Processor")
diff --git a/src/devices/bus/bbc/tube/tube_matchbox.h b/src/devices/bus/bbc/tube/tube_matchbox.h
new file mode 100644
index 00000000000..250f4bf4b48
--- /dev/null
+++ b/src/devices/bus/bbc/tube/tube_matchbox.h
@@ -0,0 +1,13 @@
+// license:BSD-3-Clause
+// copyright-holders:Nigel Barnes
+#ifndef MAME_BUS_BBC_TUBE_TUBE_MATCHBOX_H
+#define MAME_BUS_BBC_TUBE_TUBE_MATCHBOX_H
+
+#pragma once
+
+#include "tube.h"
+
+
+DECLARE_DEVICE_TYPE(BBC_TUBE_MATCHBOX, device_bbc_tube_interface)
+
+#endif // MAME_BUS_BBC_TUBE_TUBE_MATCHBOX_H
diff --git a/src/devices/bus/bbc/tube/tube_rc6502.cpp b/src/devices/bus/bbc/tube/tube_rc6502.cpp
index c567be6f98a..70a0d1ea2d1 100644
--- a/src/devices/bus/bbc/tube/tube_rc6502.cpp
+++ b/src/devices/bus/bbc/tube/tube_rc6502.cpp
@@ -61,13 +61,13 @@ ioport_constructor bbc_tube_rc6502_device::device_input_ports() const
void bbc_tube_rc6502_device::tube_rc6502_bank(address_map &map)
{
// Bank 0: ROM disabled with banked RAM (65C02)
- map(0x000000, 0x00ffff).ram().share("ram");
+ map(0x000000, 0x07ffff).ram().share("ram");
map(0x004000, 0x007fff).bankrw(m_bank1);
map(0x008000, 0x00bfff).bankrw(m_bank2);
// Bank 1: ROM disabled with linear RAM (65C816)
map(0x100000, 0x17ffff).ram().share("ram");
// Bank 2: ROM enabled with banked RAM (65C02)
- map(0x200000, 0x20ffff).ram().share("ram");
+ map(0x200000, 0x27ffff).ram().share("ram");
map(0x204000, 0x207fff).bankrw(m_bank1);
map(0x208000, 0x20bfff).bankrw(m_bank2);
map(0x208000, 0x20ffff).rom().region("maincpu", 0);
@@ -125,19 +125,19 @@ void bbc_tube_rc6502_device::add_common_devices(machine_config &config)
/* software lists */
SOFTWARE_LIST(config, "flop_ls_6502").set_original("bbc_flop_6502");
- SOFTWARE_LIST(config, "flop_ls_65c102").set_original("bbc_flop_65c102");
}
void bbc_tube_rc6502_device::device_add_mconfig(machine_config &config)
{
- M65C02(config, m_maincpu, 44.2368_MHz_XTAL);
+ W65C02S(config, m_maincpu, 44.2368_MHz_XTAL);
m_maincpu->set_addrmap(AS_PROGRAM, &bbc_tube_rc6502_device::tube_rc6502_mem);
add_common_devices(config);
TUBE(config, m_ula);
- m_ula->pnmi_handler().set_inputline(m_maincpu, M65C02_NMI_LINE);
- m_ula->pirq_handler().set_inputline(m_maincpu, M65C02_IRQ_LINE);
+ m_ula->pnmi_handler().set_inputline(m_maincpu, W65C02_NMI_LINE);
+ m_ula->pirq_handler().set_inputline(m_maincpu, W65C02_IRQ_LINE);
+ m_ula->prst_handler().set(FUNC(bbc_tube_rc6502_device::prst_w));
}
void bbc_tube_rc65816_device::device_add_mconfig(machine_config &config)
@@ -150,6 +150,7 @@ void bbc_tube_rc65816_device::device_add_mconfig(machine_config &config)
TUBE(config, m_ula);
m_ula->pnmi_handler().set_inputline(m_maincpu, G65816_LINE_NMI);
m_ula->pirq_handler().set_inputline(m_maincpu, G65816_LINE_IRQ);
+ m_ula->prst_handler().set(FUNC(bbc_tube_rc65816_device::prst_w));
}
//-------------------------------------------------
@@ -233,6 +234,13 @@ void bbc_tube_rc6502_device::device_reset()
// IMPLEMENTATION
//**************************************************************************
+void bbc_tube_rc6502_device::prst_w(int state)
+{
+ device_reset();
+
+ m_maincpu->set_input_line(INPUT_LINE_RESET, state);
+}
+
uint8_t bbc_tube_rc6502_device::host_r(offs_t offset)
{
return m_ula->host_r(offset);
diff --git a/src/devices/bus/bbc/tube/tube_rc6502.h b/src/devices/bus/bbc/tube/tube_rc6502.h
index eadb460cc96..016c1b3bd85 100644
--- a/src/devices/bus/bbc/tube/tube_rc6502.h
+++ b/src/devices/bus/bbc/tube/tube_rc6502.h
@@ -8,12 +8,13 @@
**********************************************************************/
+#ifndef MAME_BUS_BBC_TUBE_TUBE_RC6502_H
+#define MAME_BUS_BBC_TUBE_TUBE_RC6502_H
-#ifndef MAME_BUS_BBC_TUBE_RC6502_H
-#define MAME_BUS_BBC_TUBE_RC6502_H
+#pragma once
#include "tube.h"
-#include "cpu/m6502/m65c02.h"
+#include "cpu/m6502/w65c02s.h"
#include "cpu/g65816/g65816.h"
#include "machine/bankdev.h"
#include "machine/ram.h"
@@ -37,13 +38,13 @@ protected:
bbc_tube_rc6502_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_start() override ATTR_COLD;
+ virtual void device_reset() override ATTR_COLD;
// 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 void device_add_mconfig(machine_config &config) override ATTR_COLD;
+ virtual const tiny_rom_entry *device_rom_region() const override ATTR_COLD;
+ virtual ioport_constructor device_input_ports() const override ATTR_COLD;
void add_common_devices(machine_config &config);
@@ -53,7 +54,7 @@ protected:
uint8_t config_r();
void register_w(uint8_t data);
- void tube_rc6502_bank(address_map &map);
+ void tube_rc6502_bank(address_map &map) ATTR_COLD;
required_device<cpu_device> m_maincpu;
required_device<address_map_bank_device> m_bankdev;
@@ -63,8 +64,10 @@ protected:
required_device<ram_device> m_ram;
required_ioport m_config;
+ void prst_w(int state);
+
private:
- void tube_rc6502_mem(address_map &map);
+ void tube_rc6502_mem(address_map &map) ATTR_COLD;
uint8_t m_default;
uint8_t m_divider;
@@ -80,11 +83,11 @@ public:
protected:
// optional information overrides
- virtual void device_add_mconfig(machine_config &config) override;
- virtual const tiny_rom_entry *device_rom_region() const override;
+ virtual void device_add_mconfig(machine_config &config) override ATTR_COLD;
+ virtual const tiny_rom_entry *device_rom_region() const override ATTR_COLD;
private:
- void tube_rc65816_mem(address_map &map);
+ void tube_rc65816_mem(address_map &map) ATTR_COLD;
};
@@ -92,5 +95,4 @@ private:
DECLARE_DEVICE_TYPE(BBC_TUBE_RC6502, bbc_tube_rc6502_device)
DECLARE_DEVICE_TYPE(BBC_TUBE_RC65816, bbc_tube_rc65816_device)
-
-#endif /* MAME_BUS_BBC_TUBE_RC6502_H */
+#endif // MAME_BUS_BBC_TUBE_TUBE_RC6502_H
diff --git a/src/devices/bus/bbc/tube/tube_x25.cpp b/src/devices/bus/bbc/tube/tube_x25.cpp
new file mode 100644
index 00000000000..21e03217201
--- /dev/null
+++ b/src/devices/bus/bbc/tube/tube_x25.cpp
@@ -0,0 +1,186 @@
+// license:BSD-3-Clause
+// copyright-holders:Nigel Barnes
+/**********************************************************************
+
+ Acorn Econet X25 Gateway
+
+ http://chrisacorns.computinghistory.org.uk/32bit_UpgradesA2G/Acorn_EconetX25.html
+
+ TODO:
+ - everything to be verified when a schematic is found.
+
+**********************************************************************/
+
+
+#include "emu.h"
+#include "tube_x25.h"
+
+
+//**************************************************************************
+// DEVICE DEFINITIONS
+//**************************************************************************
+
+DEFINE_DEVICE_TYPE(BBC_TUBE_X25, bbc_tube_x25_device, "bbc_tube_x25", "Econet X25 Gateway Co-Processor")
+
+
+//-------------------------------------------------
+// ADDRESS_MAP( primary_mem )
+//-------------------------------------------------
+
+void bbc_tube_x25_device::primary_mem(address_map &map)
+{
+ map(0x0000, 0x7fff).bankrw("bank0");
+ map(0x0000, 0x0fff).rom().region("boot", 0);
+ map(0x8000, 0xffff).bankrw("bank1");
+}
+
+//-------------------------------------------------
+// ADDRESS_MAP( primary_io )
+//-------------------------------------------------
+
+void bbc_tube_x25_device::primary_io(address_map &map)
+{
+ map.global_mask(0xff);
+ map(0x00, 0x1f).rw(m_ula, FUNC(tube_device::parasite_r), FUNC(tube_device::parasite_w));
+}
+
+//-------------------------------------------------
+// ADDRESS_MAP( secondary_mem )
+//-------------------------------------------------
+
+void bbc_tube_x25_device::secondary_mem(address_map &map)
+{
+ map(0x0000, 0x7fff).rom().region("x25", 0);
+ map(0x8000, 0xffff).bankrw("bank1");
+}
+
+//-------------------------------------------------
+// ADDRESS_MAP( secondary_io )
+//-------------------------------------------------
+
+void bbc_tube_x25_device::secondary_io(address_map &map)
+{
+ map.global_mask(0xff);
+ map(0x00, 0x03).rw("ctc", FUNC(z80ctc_device::read), FUNC(z80ctc_device::write));
+ map(0x04, 0x07).rw("sio", FUNC(z80sio_device::ba_cd_r), FUNC(z80sio_device::ba_cd_w));
+}
+
+//-------------------------------------------------
+// ROM( tube_x25 )
+//-------------------------------------------------
+
+ROM_START(tube_x25)
+ ROM_REGION(0x1000, "boot", 0)
+ ROM_LOAD("0246,200_01-x25-boot.rom", 0x0000, 0x1000, CRC(8088edd9) SHA1(9692c77712d006596c89c18ae9cdf01d5be5b487))
+
+ ROM_REGION(0x8000, "x25", 0)
+ ROM_LOAD("0246,213_01-x25-lo-rom1.rom", 0x0000, 0x4000, CRC(43679e1d) SHA1(240a46f7fb9fb8eee834b36aa8526f1f3ff7e00c))
+ ROM_LOAD("0246,214_01-x25-hi-rom2.rom", 0x4000, 0x4000, CRC(e77ce291) SHA1(3d9e3f58f878d1f7c743b05e371845b3f7627129))
+ROM_END
+
+//-------------------------------------------------
+// device_add_mconfig - add device configuration
+//-------------------------------------------------
+
+static const z80_daisy_config daisy_chain[] =
+{
+ { "ctc" },
+ { "sio" },
+ { nullptr }
+};
+
+
+void bbc_tube_x25_device::device_add_mconfig(machine_config &config)
+{
+ Z80(config, m_z80[0], 12_MHz_XTAL / 2);
+ m_z80[0]->set_addrmap(AS_PROGRAM, &bbc_tube_x25_device::primary_mem);
+ m_z80[0]->set_addrmap(AS_IO, &bbc_tube_x25_device::primary_io);
+ m_z80[0]->set_irq_acknowledge_callback(FUNC(bbc_tube_x25_device::irq_callback));
+
+ TUBE(config, m_ula);
+ m_ula->pnmi_handler().set_inputline(m_z80[0], INPUT_LINE_NMI);
+ m_ula->pirq_handler().set_inputline(m_z80[0], INPUT_LINE_IRQ0);
+ m_ula->prst_handler().set_inputline(m_z80[0], INPUT_LINE_RESET);
+
+ Z80(config, m_z80[1], 12_MHz_XTAL / 4);
+ m_z80[1]->set_addrmap(AS_PROGRAM, &bbc_tube_x25_device::secondary_mem);
+ m_z80[1]->set_addrmap(AS_IO, &bbc_tube_x25_device::secondary_io);
+ m_z80[1]->set_daisy_config(daisy_chain);
+
+ z80sio_device& sio(Z80SIO(config, "sio", 12_MHz_XTAL / 4));
+ sio.out_int_callback().set_inputline(m_z80[1], INPUT_LINE_IRQ0);
+
+ z80ctc_device& ctc(Z80CTC(config, "ctc", 12_MHz_XTAL / 4));
+ ctc.zc_callback<0>().set("sio", FUNC(z80sio_device::rxca_w));
+ ctc.zc_callback<0>().append("sio", FUNC(z80sio_device::txca_w));
+ ctc.zc_callback<1>().set("sio", FUNC(z80sio_device::rxcb_w));
+ ctc.zc_callback<1>().append("sio", FUNC(z80sio_device::txcb_w));
+ ctc.intr_callback().set_inputline(m_z80[1], INPUT_LINE_IRQ0);
+}
+
+//-------------------------------------------------
+// rom_region - device-specific ROM region
+//-------------------------------------------------
+
+const tiny_rom_entry *bbc_tube_x25_device::device_rom_region() const
+{
+ return ROM_NAME( tube_x25 );
+}
+
+//**************************************************************************
+// LIVE DEVICE
+//**************************************************************************
+
+//-------------------------------------------------
+// bbc_tube_x25_device - constructor
+//-------------------------------------------------
+
+bbc_tube_x25_device::bbc_tube_x25_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
+ : device_t(mconfig, BBC_TUBE_X25, tag, owner, clock)
+ , device_bbc_tube_interface(mconfig, *this)
+ , m_z80(*this, "z80_%u", 0)
+ , m_ula(*this, "ula")
+ , m_bank(*this, "bank%u", 0)
+ , m_ram(nullptr)
+{
+}
+
+//-------------------------------------------------
+// device_start - device-specific startup
+//-------------------------------------------------
+
+void bbc_tube_x25_device::device_start()
+{
+ m_ram = make_unique_clear<uint8_t[]>(0x10000);
+
+ m_bank[0]->set_base(m_ram.get());
+ m_bank[1]->set_base(m_ram.get() + 0x8000);
+
+ /* register for save states */
+ save_pointer(NAME(m_ram), 0x10000);
+}
+
+
+//**************************************************************************
+// IMPLEMENTATION
+//**************************************************************************
+
+uint8_t bbc_tube_x25_device::host_r(offs_t offset)
+{
+ return m_ula->host_r(offset);
+}
+
+void bbc_tube_x25_device::host_w(offs_t offset, uint8_t data)
+{
+ m_ula->host_w(offset, data);
+}
+
+
+//-------------------------------------------------
+// irq vector callback
+//-------------------------------------------------
+
+IRQ_CALLBACK_MEMBER(bbc_tube_x25_device::irq_callback)
+{
+ return 0xfe;
+}
diff --git a/src/devices/bus/bbc/tube/tube_x25.h b/src/devices/bus/bbc/tube/tube_x25.h
new file mode 100644
index 00000000000..f0ac884d96b
--- /dev/null
+++ b/src/devices/bus/bbc/tube/tube_x25.h
@@ -0,0 +1,67 @@
+// license:BSD-3-Clause
+// copyright-holders:Nigel Barnes
+/**********************************************************************
+
+ Acorn Econet X25 Gateway
+
+ http://chrisacorns.computinghistory.org.uk/32bit_UpgradesA2G/Acorn_EconetX25.html
+
+**********************************************************************/
+
+#ifndef MAME_BUS_BBC_TUBE_TUBE_X25_H
+#define MAME_BUS_BBC_TUBE_TUBE_X25_H
+
+#pragma once
+
+#include "tube.h"
+#include "cpu/z80/z80.h"
+#include "machine/z80ctc.h"
+#include "machine/z80sio.h"
+#include "machine/tube.h"
+
+//**************************************************************************
+// TYPE DEFINITIONS
+//**************************************************************************
+
+// ======================> bbc_tube_x25_device
+
+class bbc_tube_x25_device :
+ public device_t,
+ public device_bbc_tube_interface
+{
+public:
+ // construction/destruction
+ bbc_tube_x25_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
+
+ static constexpr feature_type unemulated_features() { return feature::LAN; }
+
+protected:
+ // device-level overrides
+ virtual void device_start() override ATTR_COLD;
+
+ // optional information overrides
+ virtual void device_add_mconfig(machine_config &config) override ATTR_COLD;
+ virtual const tiny_rom_entry *device_rom_region() const override ATTR_COLD;
+
+ virtual uint8_t host_r(offs_t offset) override;
+ virtual void host_w(offs_t offset, uint8_t data) override;
+
+private:
+ IRQ_CALLBACK_MEMBER( irq_callback );
+
+ required_device_array<z80_device, 2> m_z80;
+ required_device<tube_device> m_ula;
+ required_memory_bank_array<2> m_bank;
+ std::unique_ptr<uint8_t[]> m_ram;
+
+ void primary_mem(address_map &map) ATTR_COLD;
+ void primary_io(address_map &map) ATTR_COLD;
+ void secondary_mem(address_map &map) ATTR_COLD;
+ void secondary_io(address_map &map) ATTR_COLD;
+};
+
+
+// device type definition
+DECLARE_DEVICE_TYPE(BBC_TUBE_X25, bbc_tube_x25_device)
+
+#endif // MAME_BUS_BBC_TUBE_TUBE_X25_H
diff --git a/src/devices/bus/bbc/tube/tube_z80.cpp b/src/devices/bus/bbc/tube/tube_z80.cpp
index 06e6931c7a3..f6b3fae93ca 100644
--- a/src/devices/bus/bbc/tube/tube_z80.cpp
+++ b/src/devices/bus/bbc/tube/tube_z80.cpp
@@ -19,6 +19,7 @@
//**************************************************************************
DEFINE_DEVICE_TYPE(BBC_TUBE_Z80, bbc_tube_z80_device, "bbc_tube_z80", "Acorn Z80 2nd Processor")
+DEFINE_DEVICE_TYPE(BBC_TUBE_Z80W, bbc_tube_z80w_device, "bbc_tube_z80w", "Acorn Z80 2nd Processor (Winchester)")
//-------------------------------------------------
@@ -54,7 +55,14 @@ void bbc_tube_z80_device::tube_z80_io(address_map &map)
ROM_START( tube_z80 )
ROM_REGION(0x1000, "rom", 0)
- ROM_LOAD("z80_120.rom", 0x0000, 0x1000, CRC(315bfc20) SHA1(069077df498599a9c880d4ec9f4bc53fcc602d82))
+ ROM_SYSTEM_BIOS(0, "120", "Z80 v1.20")
+ ROMX_LOAD("z80_120.rom", 0x0000, 0x1000, CRC(315bfc20) SHA1(069077df498599a9c880d4ec9f4bc53fcc602d82), ROM_BIOS(0))
+ROM_END
+
+ROM_START( tube_z80w )
+ ROM_REGION(0x1000, "rom", 0)
+ ROM_SYSTEM_BIOS(0, "200", "Z80 v2.00") /* supplied with Acorn Business Computer */
+ ROMX_LOAD("z80_200.rom", 0x0000, 0x1000, CRC(84672c3d) SHA1(47211cead3a1b0f9830dcdef8e54e29522c69bf8), ROM_BIOS(0))
ROM_END
//-------------------------------------------------
@@ -67,15 +75,12 @@ void bbc_tube_z80_device::device_add_mconfig(machine_config &config)
m_z80->set_addrmap(AS_PROGRAM, &bbc_tube_z80_device::tube_z80_mem);
m_z80->set_addrmap(AS_OPCODES, &bbc_tube_z80_device::tube_z80_fetch);
m_z80->set_addrmap(AS_IO, &bbc_tube_z80_device::tube_z80_io);
- m_z80->set_irq_acknowledge_callback(device_irq_acknowledge_delegate(FUNC(bbc_tube_z80_device::irq_callback), this));
+ m_z80->set_irq_acknowledge_callback(FUNC(bbc_tube_z80_device::irq_callback));
TUBE(config, m_ula);
- m_ula->hirq_handler().set(DEVICE_SELF_OWNER, FUNC(bbc_tube_slot_device::irq_w));
- m_ula->pnmi_handler().set(FUNC(bbc_tube_z80_device::nmi_w));
+ m_ula->pnmi_handler().set_inputline(m_z80, INPUT_LINE_NMI);
m_ula->pirq_handler().set_inputline(m_z80, INPUT_LINE_IRQ0);
-
- /* internal ram */
- RAM(config, m_ram).set_default_size("64K").set_default_value(0);
+ m_ula->prst_handler().set(FUNC(bbc_tube_z80_device::prst_w));
/* software lists */
SOFTWARE_LIST(config, "flop_ls_z80").set_original("bbc_flop_z80");
@@ -90,6 +95,11 @@ const tiny_rom_entry *bbc_tube_z80_device::device_rom_region() const
return ROM_NAME( tube_z80 );
}
+const tiny_rom_entry *bbc_tube_z80w_device::device_rom_region() const
+{
+ return ROM_NAME( tube_z80w );
+}
+
//**************************************************************************
// LIVE DEVICE
//**************************************************************************
@@ -98,14 +108,23 @@ const tiny_rom_entry *bbc_tube_z80_device::device_rom_region() const
// bbc_tube_z80_device - constructor
//-------------------------------------------------
+bbc_tube_z80_device::bbc_tube_z80_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_z80(*this, "z80")
+ , m_ula(*this, "ula")
+ , m_rom(*this, "rom")
+ , m_rom_enabled(true)
+{
+}
+
bbc_tube_z80_device::bbc_tube_z80_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
- : device_t(mconfig, BBC_TUBE_Z80, tag, owner, clock),
- device_bbc_tube_interface(mconfig, *this),
- m_z80(*this, "z80"),
- m_ula(*this, "ula"),
- m_ram(*this, "ram"),
- m_rom(*this, "rom"),
- m_rom_enabled(true)
+ : bbc_tube_z80_device(mconfig, BBC_TUBE_Z80, tag, owner, clock)
+{
+}
+
+bbc_tube_z80w_device::bbc_tube_z80w_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
+ : bbc_tube_z80_device(mconfig, BBC_TUBE_Z80W, tag, owner, clock)
{
}
@@ -115,7 +134,11 @@ bbc_tube_z80_device::bbc_tube_z80_device(const machine_config &mconfig, const ch
void bbc_tube_z80_device::device_start()
{
- m_slot = dynamic_cast<bbc_tube_slot_device *>(owner());
+ m_ram = std::make_unique<uint8_t[]>(0x10000);
+ memset(m_ram.get(), 0xff, 0x10000);
+
+ /* register for save states */
+ save_pointer(NAME(m_ram), 0x10000);
}
//-------------------------------------------------
@@ -124,8 +147,6 @@ void bbc_tube_z80_device::device_start()
void bbc_tube_z80_device::device_reset()
{
- m_ula->reset();
-
m_rom_enabled = true;
}
@@ -134,6 +155,13 @@ void bbc_tube_z80_device::device_reset()
// IMPLEMENTATION
//**************************************************************************
+void bbc_tube_z80_device::prst_w(int state)
+{
+ device_reset();
+
+ m_z80->set_input_line(INPUT_LINE_RESET, state);
+}
+
uint8_t bbc_tube_z80_device::host_r(offs_t offset)
{
return m_ula->host_r(offset);
@@ -149,7 +177,7 @@ uint8_t bbc_tube_z80_device::opcode_r(offs_t offset)
{
if (!machine().side_effects_disabled())
{
- if (offset == 0x0066 && m_z80->input_state(INPUT_LINE_NMI))
+ if (offset == 0x0066 && m_z80->input_line_state(INPUT_LINE_NMI))
m_rom_enabled = true;
else if (offset >= 0x8000)
m_rom_enabled = false;
@@ -165,19 +193,14 @@ uint8_t bbc_tube_z80_device::mem_r(offs_t offset)
if (m_rom_enabled && (offset < 0x1000))
data = m_rom->base()[offset & 0xfff];
else
- data = m_ram->pointer()[offset];
+ data = m_ram[offset];
return data;
}
void bbc_tube_z80_device::mem_w(offs_t offset, uint8_t data)
{
- m_ram->pointer()[offset] = data;
-}
-
-WRITE_LINE_MEMBER(bbc_tube_z80_device::nmi_w)
-{
- m_z80->set_input_line(INPUT_LINE_NMI, state);
+ m_ram[offset] = data;
}
diff --git a/src/devices/bus/bbc/tube/tube_z80.h b/src/devices/bus/bbc/tube/tube_z80.h
index 536e506d43d..981f1f8ac6b 100644
--- a/src/devices/bus/bbc/tube/tube_z80.h
+++ b/src/devices/bus/bbc/tube/tube_z80.h
@@ -8,13 +8,13 @@
**********************************************************************/
+#ifndef MAME_BUS_BBC_TUBE_TUBE_Z80_H
+#define MAME_BUS_BBC_TUBE_TUBE_Z80_H
-#ifndef MAME_BUS_BBC_TUBE_Z80_H
-#define MAME_BUS_BBC_TUBE_Z80_H
+#pragma once
#include "tube.h"
#include "cpu/z80/z80.h"
-#include "machine/ram.h"
#include "machine/tube.h"
//**************************************************************************
@@ -32,40 +32,55 @@ public:
bbc_tube_z80_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
protected:
+ bbc_tube_z80_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_start() override ATTR_COLD;
+ virtual void device_reset() override ATTR_COLD;
// optional information overrides
- virtual void device_add_mconfig(machine_config &config) override;
- virtual const tiny_rom_entry *device_rom_region() const override;
+ virtual void device_add_mconfig(machine_config &config) override ATTR_COLD;
+ virtual const tiny_rom_entry *device_rom_region() const override ATTR_COLD;
virtual uint8_t host_r(offs_t offset) override;
virtual void host_w(offs_t offset, uint8_t data) override;
private:
IRQ_CALLBACK_MEMBER( irq_callback );
- DECLARE_WRITE_LINE_MEMBER( nmi_w );
- required_device<cpu_device> m_z80;
+ required_device<z80_device> m_z80;
required_device<tube_device> m_ula;
- required_device<ram_device> m_ram;
required_memory_region m_rom;
+ std::unique_ptr<uint8_t[]> m_ram;
+
bool m_rom_enabled;
uint8_t mem_r(offs_t offset);
void mem_w(offs_t offset, uint8_t data);
uint8_t opcode_r(offs_t offset);
- void tube_z80_fetch(address_map &map);
- void tube_z80_io(address_map &map);
- void tube_z80_mem(address_map &map);
+ void tube_z80_fetch(address_map &map) ATTR_COLD;
+ void tube_z80_io(address_map &map) ATTR_COLD;
+ void tube_z80_mem(address_map &map) ATTR_COLD;
+
+ void prst_w(int state);
+};
+
+
+class bbc_tube_z80w_device : public bbc_tube_z80_device
+{
+public:
+ bbc_tube_z80w_device(const machine_config& mconfig, const char* tag, device_t* owner, uint32_t clock);
+
+protected:
+ // optional information overrides
+ virtual const tiny_rom_entry* device_rom_region() const override;
};
// device type definition
DECLARE_DEVICE_TYPE(BBC_TUBE_Z80, bbc_tube_z80_device)
+DECLARE_DEVICE_TYPE(BBC_TUBE_Z80W, bbc_tube_z80w_device)
-
-#endif /* MAME_BUS_BBC_TUBE_Z80_H */
+#endif // MAME_BUS_BBC_TUBE_TUBE_Z80_H
diff --git a/src/devices/bus/bbc/tube/tube_zep100.cpp b/src/devices/bus/bbc/tube/tube_zep100.cpp
index f11f0af6415..0d5b0d18948 100644
--- a/src/devices/bus/bbc/tube/tube_zep100.cpp
+++ b/src/devices/bus/bbc/tube/tube_zep100.cpp
@@ -19,6 +19,9 @@
//**************************************************************************
DEFINE_DEVICE_TYPE(BBC_TUBE_ZEP100, bbc_tube_zep100_device, "bbc_tube_zep100", "Torch Z80 Communicator")
+DEFINE_DEVICE_TYPE(BBC_TUBE_ZEP100L, bbc_tube_zep100l_device, "bbc_tube_zep100l", "Torch Z80 Communicator (Model B)")
+DEFINE_DEVICE_TYPE(BBC_TUBE_ZEP100W, bbc_tube_zep100w_device, "bbc_tube_zep100w", "Torch Z80 Communicator (Model B+)")
+DEFINE_DEVICE_TYPE(BBC_TUBE_ZEP100M, bbc_tube_zep100m_device, "bbc_tube_zep100m", "Torch Z80 Communicator (Master)")
//-------------------------------------------------
@@ -61,6 +64,37 @@ ROM_START( tube_zep100 )
ROMX_LOAD("cccp094.rom", 0x0000, 0x2000, CRC(49989bd4) SHA1(62b57c858a3baa4ff943c31f77d331c414772a61), ROM_BIOS(2))
ROM_END
+ROM_START( tube_zep100l )
+ ROM_REGION(0x4000, "exp_rom", 0)
+ ROM_SYSTEM_BIOS(0, "mcp121", "MCP v1.21 (ABL)") // 1985
+ ROMX_LOAD("mcp121abl.rom", 0x0000, 0x4000, CRC(216f1074) SHA1(ec3d285f757b1b35bd0cc65155048a55cc1146ed), ROM_BIOS(0))
+
+ ROM_REGION(0x2000, "rom", 0)
+ ROM_LOAD("cccp102.rom", 0x0000, 0x2000, CRC(2eb40a21) SHA1(e6ee738e5f2f8556002b79d18caa8ef21f14e08d))
+ROM_END
+
+ROM_START( tube_zep100w )
+ ROM_REGION(0x4000, "exp_rom", 0)
+ ROM_SYSTEM_BIOS(0, "mcp122", "MCP v1.22 (ABW)") // 1986
+ ROMX_LOAD("mcp122abw.rom", 0x0000, 0x4000, CRC(7124e9a6) SHA1(39cdd4367bfb2c8d6599b4a4420e6d311f8acaa9), ROM_BIOS(0))
+ ROM_SYSTEM_BIOS(1, "mcp121", "MCP v1.21 (ABW)") // 1985
+ ROMX_LOAD("mcp121abw.rom", 0x0000, 0x4000, CRC(5e4a4a56) SHA1(27172e29f1020147c7ae52111b4234ee4a22e627), ROM_BIOS(1))
+
+ ROM_REGION(0x2000, "rom", 0)
+ ROM_LOAD("cccp102.rom", 0x0000, 0x2000, CRC(2eb40a21) SHA1(e6ee738e5f2f8556002b79d18caa8ef21f14e08d))
+ROM_END
+
+ROM_START( tube_zep100m )
+ ROM_REGION(0x4000, "exp_rom", 0)
+ ROM_SYSTEM_BIOS(0, "mcp202", "MCP v2.02 (CBM)") // 1987
+ ROMX_LOAD("mcp202cbm.rom", 0x0000, 0x4000, CRC(237bd2d0) SHA1(064203ce44c764b189465fa93b71bcc6f0c66e3b), ROM_BIOS(0))
+ ROM_SYSTEM_BIOS(1, "mcp122", "MCP v1.22 (ABM)") // 1986
+ ROMX_LOAD("mcp122abm.rom", 0x0000, 0x4000, CRC(596be795) SHA1(35843ace281494ab40463a69a263244d0cb0ecd6), ROM_BIOS(1))
+
+ ROM_REGION(0x2000, "rom", 0)
+ ROM_LOAD("cccp102.rom", 0x0000, 0x2000, CRC(2eb40a21) SHA1(e6ee738e5f2f8556002b79d18caa8ef21f14e08d))
+ROM_END
+
//-------------------------------------------------
// device_add_mconfig - add device configuration
//-------------------------------------------------
@@ -71,7 +105,7 @@ void bbc_tube_zep100_device::device_add_mconfig(machine_config &config)
m_z80->set_addrmap(AS_PROGRAM, &bbc_tube_zep100_device::tube_zep100_mem);
m_z80->set_addrmap(AS_IO, &bbc_tube_zep100_device::tube_zep100_io);
- VIA6522(config, m_via, 4_MHz_XTAL / 2);
+ MOS6522(config, m_via, 4_MHz_XTAL / 2);
m_via->writepb_handler().set(FUNC(bbc_tube_zep100_device::via_pb_w));
m_via->cb2_handler().set(m_ppi, FUNC(i8255_device::pc2_w));
m_via->ca2_handler().set(m_ppi, FUNC(i8255_device::pc6_w));
@@ -82,11 +116,8 @@ void bbc_tube_zep100_device::device_add_mconfig(machine_config &config)
m_ppi->in_pb_callback().set(FUNC(bbc_tube_zep100_device::ppi_pb_r));
m_ppi->out_pc_callback().set(FUNC(bbc_tube_zep100_device::ppi_pc_w));
- /* internal ram */
- RAM(config, m_ram).set_default_size("64K").set_default_value(0x00);
-
/* software lists */
- SOFTWARE_LIST(config, "flop_ls_torch").set_type("bbc_flop_torch", SOFTWARE_LIST_ORIGINAL_SYSTEM).set_filter("Z80");
+ SOFTWARE_LIST(config, "flop_ls_torch").set_original("bbc_flop_torch").set_filter("Z80");
}
//-------------------------------------------------
@@ -98,6 +129,21 @@ const tiny_rom_entry *bbc_tube_zep100_device::device_rom_region() const
return ROM_NAME( tube_zep100 );
}
+const tiny_rom_entry *bbc_tube_zep100l_device::device_rom_region() const
+{
+ return ROM_NAME( tube_zep100l );
+}
+
+const tiny_rom_entry *bbc_tube_zep100w_device::device_rom_region() const
+{
+ return ROM_NAME( tube_zep100w );
+}
+
+const tiny_rom_entry *bbc_tube_zep100m_device::device_rom_region() const
+{
+ return ROM_NAME( tube_zep100m );
+}
+
//**************************************************************************
// LIVE DEVICE
//**************************************************************************
@@ -113,7 +159,6 @@ bbc_tube_zep100_device::bbc_tube_zep100_device(const machine_config &mconfig, de
, m_z80(*this, "z80")
, m_via(*this, "via")
, m_ppi(*this, "ppi")
- , m_ram(*this, "ram")
, m_rom(*this, "rom")
, m_port_b(0)
{
@@ -124,12 +169,32 @@ bbc_tube_zep100_device::bbc_tube_zep100_device(const machine_config &mconfig, co
{
}
+bbc_tube_zep100l_device::bbc_tube_zep100l_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
+ : bbc_tube_zep100_device(mconfig, BBC_TUBE_ZEP100L, tag, owner, clock)
+{
+}
+
+bbc_tube_zep100w_device::bbc_tube_zep100w_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
+ : bbc_tube_zep100_device(mconfig, BBC_TUBE_ZEP100W, tag, owner, clock)
+{
+}
+
+bbc_tube_zep100m_device::bbc_tube_zep100m_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
+ : bbc_tube_zep100_device(mconfig, BBC_TUBE_ZEP100M, tag, owner, clock)
+{
+}
+
//-------------------------------------------------
// device_start - device-specific startup
//-------------------------------------------------
void bbc_tube_zep100_device::device_start()
{
+ m_ram = std::make_unique<uint8_t[]>(0x10000);
+ memset(m_ram.get(), 0xff, 0x10000);
+
+ /* register for save states */
+ save_pointer(NAME(m_ram), 0x10000);
}
//-------------------------------------------------
@@ -167,14 +232,14 @@ uint8_t bbc_tube_zep100_device::mem_r(offs_t offset)
if (m_rom_enabled)
data = m_rom->base()[offset];
else
- data = m_ram->pointer()[offset];
+ data = m_ram[offset];
return data;
}
void bbc_tube_zep100_device::mem_w(offs_t offset, uint8_t data)
{
- m_ram->pointer()[offset] = data;
+ m_ram[offset] = data;
}
diff --git a/src/devices/bus/bbc/tube/tube_zep100.h b/src/devices/bus/bbc/tube/tube_zep100.h
index b7f881fcfac..e426e51c0db 100644
--- a/src/devices/bus/bbc/tube/tube_zep100.h
+++ b/src/devices/bus/bbc/tube/tube_zep100.h
@@ -8,15 +8,15 @@
**********************************************************************/
+#ifndef MAME_BUS_BBC_TUBE_TUBE_ZEP100_H
+#define MAME_BUS_BBC_TUBE_TUBE_ZEP100_H
-#ifndef MAME_BUS_BBC_TUBE_ZEP100_H
-#define MAME_BUS_BBC_TUBE_ZEP100_H
+#pragma once
#include "tube.h"
#include "cpu/z80/z80.h"
#include "machine/6522via.h"
#include "machine/i8255.h"
-#include "machine/ram.h"
//**************************************************************************
// TYPE DEFINITIONS
@@ -36,12 +36,12 @@ protected:
bbc_tube_zep100_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_start() override ATTR_COLD;
+ virtual void device_reset() override ATTR_COLD;
// optional information overrides
- virtual void device_add_mconfig(machine_config &config) override;
- virtual const tiny_rom_entry *device_rom_region() const override;
+ virtual void device_add_mconfig(machine_config &config) override ATTR_COLD;
+ virtual const tiny_rom_entry *device_rom_region() const override ATTR_COLD;
virtual uint8_t host_r(offs_t offset) override;
virtual void host_w(offs_t offset, uint8_t data) override;
@@ -52,9 +52,10 @@ private:
required_device<z80_device> m_z80;
required_device<via6522_device> m_via;
required_device<i8255_device> m_ppi;
- required_device<ram_device> m_ram;
required_memory_region m_rom;
+ std::unique_ptr<uint8_t[]> m_ram;
+
uint8_t m_port_b;
uint8_t mem_r(offs_t offset);
@@ -66,13 +67,42 @@ private:
uint8_t ppi_pb_r();
void ppi_pc_w(uint8_t data);
- void tube_zep100_io(address_map &map);
- void tube_zep100_mem(address_map &map);
+ void tube_zep100_io(address_map &map) ATTR_COLD;
+ void tube_zep100_mem(address_map &map) ATTR_COLD;
+};
+
+class bbc_tube_zep100l_device : public bbc_tube_zep100_device
+{
+public:
+ bbc_tube_zep100l_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 ATTR_COLD;
+};
+
+class bbc_tube_zep100w_device : public bbc_tube_zep100_device
+{
+public:
+ bbc_tube_zep100w_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 ATTR_COLD;
+};
+
+class bbc_tube_zep100m_device : public bbc_tube_zep100_device
+{
+public:
+ bbc_tube_zep100m_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 ATTR_COLD;
};
// device type definition
DECLARE_DEVICE_TYPE(BBC_TUBE_ZEP100, bbc_tube_zep100_device)
+DECLARE_DEVICE_TYPE(BBC_TUBE_ZEP100L, bbc_tube_zep100l_device)
+DECLARE_DEVICE_TYPE(BBC_TUBE_ZEP100W, bbc_tube_zep100w_device)
+DECLARE_DEVICE_TYPE(BBC_TUBE_ZEP100M, bbc_tube_zep100m_device)
-
-#endif /* MAME_BUS_BBC_TUBE_ZEP100_H */
+#endif // MAME_BUS_BBC_TUBE_TUBE_ZEP100_H
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..f7a1e59fa78 100644
--- a/src/devices/bus/bbc/userport/beebspch.h
+++ b/src/devices/bus/bbc/userport/beebspch.h
@@ -27,16 +27,16 @@ 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
- virtual void device_start() override;
+ virtual void device_start() override ATTR_COLD;
// optional information overrides
- virtual void device_add_mconfig(machine_config &config) override;
- virtual const tiny_rom_entry *device_rom_region() const override;
+ virtual void device_add_mconfig(machine_config &config) override ATTR_COLD;
+ virtual const tiny_rom_entry *device_rom_region() const override ATTR_COLD;
virtual void pb_w(uint8_t data) override;
diff --git a/src/devices/bus/bbc/userport/cfa3000kbd.h b/src/devices/bus/bbc/userport/cfa3000kbd.h
index ff9951399c8..a1544b3d240 100644
--- a/src/devices/bus/bbc/userport/cfa3000kbd.h
+++ b/src/devices/bus/bbc/userport/cfa3000kbd.h
@@ -30,11 +30,11 @@ public:
protected:
// device-level overrides
- virtual void device_start() override;
- virtual void device_reset() override;
+ virtual void device_start() override ATTR_COLD;
+ virtual void device_reset() override ATTR_COLD;
// optional information overrides
- virtual ioport_constructor device_input_ports() const override;
+ virtual ioport_constructor device_input_ports() const override ATTR_COLD;
virtual uint8_t pb_r() override;
diff --git a/src/devices/bus/bbc/userport/lcd.cpp b/src/devices/bus/bbc/userport/lcd.cpp
new file mode 100644
index 00000000000..2821187b56c
--- /dev/null
+++ b/src/devices/bus/bbc/userport/lcd.cpp
@@ -0,0 +1,117 @@
+// license:BSD-3-Clause
+// copyright-holders:Nigel Barnes
+/**********************************************************************
+
+ Sprow LCD Display
+
+ http://www.sprow.co.uk/bbc/buildit.htm#Lcddisplay
+
+**********************************************************************/
+
+
+#include "emu.h"
+#include "lcd.h"
+#include "screen.h"
+
+
+//**************************************************************************
+// DEVICE DEFINITIONS
+//**************************************************************************
+
+DEFINE_DEVICE_TYPE(BBC_LCD, bbc_lcd_device, "bbc_lcd", "Sprow LCD Display")
+
+
+//-------------------------------------------------
+// device_add_mconfig - add device configuration
+//-------------------------------------------------
+
+void bbc_lcd_device::device_add_mconfig(machine_config &config)
+{
+ auto &screen = SCREEN(config, "screen", SCREEN_TYPE_LCD);
+ screen.set_refresh_hz(50);
+ screen.set_vblank_time(ATTOSECONDS_IN_USEC(2500));
+ screen.set_size(120, 36);
+ screen.set_visarea_full();
+ screen.set_screen_update(m_lcdc, FUNC(hd44780_device::screen_update));
+ screen.set_palette("palette");
+
+ PALETTE(config, "palette", FUNC(bbc_lcd_device::lcd_palette), 3);
+
+ 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));
+}
+
+
+//**************************************************************************
+// LIVE DEVICE
+//**************************************************************************
+
+//-------------------------------------------------
+// bbc_lcd_device - constructor
+//-------------------------------------------------
+
+bbc_lcd_device::bbc_lcd_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
+ : device_t(mconfig, BBC_LCD, tag, owner, clock)
+ , device_bbc_userport_interface(mconfig, *this)
+ , m_lcdc(*this, "lcdc")
+{
+}
+
+
+//-------------------------------------------------
+// device_start - device-specific startup
+//-------------------------------------------------
+
+void bbc_lcd_device::device_start()
+{
+}
+
+
+//**************************************************************************
+// IMPLEMENTATION
+//**************************************************************************
+
+HD44780_PIXEL_UPDATE(bbc_lcd_device::lcd_pixel_update)
+{
+ // char size is 5x8
+ if (x > 4 || y > 7)
+ return;
+
+ if (pos < 40)
+ {
+ if (pos >= 20)
+ {
+ line += 2;
+ pos -= 20;
+ }
+
+ if (line < 4)
+ bitmap.pix(line * (8 + 1) + y, pos * 6 + x) = state ? 1 : 2;
+ }
+}
+
+void bbc_lcd_device::lcd_palette(palette_device &palette) const
+{
+ palette.set_pen_color(0, rgb_t(138, 146, 148)); // background
+ palette.set_pen_color(1, rgb_t( 92, 83, 88)); // lcd pixel on
+ palette.set_pen_color(2, rgb_t(131, 136, 139)); // lcd pixel off
+}
+
+uint8_t bbc_lcd_device::pb_r()
+{
+ return m_lcdc->db_r() >> 1;
+}
+
+void bbc_lcd_device::pb_w(uint8_t data)
+{
+ m_lcdc->rs_w(BIT(data, 0));
+ m_lcdc->rw_w(BIT(data, 1));
+ m_lcdc->e_w(BIT(data, 2));
+ m_lcdc->db_w(data << 1);
+}
diff --git a/src/devices/bus/bbc/userport/lcd.h b/src/devices/bus/bbc/userport/lcd.h
new file mode 100644
index 00000000000..14f8e701198
--- /dev/null
+++ b/src/devices/bus/bbc/userport/lcd.h
@@ -0,0 +1,56 @@
+// license:BSD-3-Clause
+// copyright-holders:Nigel Barnes
+/**********************************************************************
+
+ Sprow LCD Display
+
+**********************************************************************/
+
+#ifndef MAME_BUS_BBC_USERPORT_LCD_H
+#define MAME_BUS_BBC_USERPORT_LCD_H
+
+#pragma once
+
+#include "userport.h"
+#include "video/hd44780.h"
+#include "emupal.h"
+
+
+//**************************************************************************
+// TYPE DEFINITIONS
+//**************************************************************************
+
+// ======================> bbc_lcd_device
+
+class bbc_lcd_device :
+ public device_t,
+ public device_bbc_userport_interface
+{
+public:
+ // construction/destruction
+ bbc_lcd_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
+
+protected:
+ // device-level overrides
+ virtual void device_start() override ATTR_COLD;
+
+ // optional information overrides
+ virtual void device_add_mconfig(machine_config &config) override ATTR_COLD;
+
+ virtual uint8_t pb_r() override;
+ virtual void pb_w(uint8_t data) override;
+
+private:
+ required_device<hd44780_device> m_lcdc;
+
+ HD44780_PIXEL_UPDATE(lcd_pixel_update);
+
+ void lcd_palette(palette_device &palette) const;
+};
+
+
+// device type definition
+DECLARE_DEVICE_TYPE(BBC_LCD, bbc_lcd_device)
+
+
+#endif // MAME_BUS_BBC_USERPORT_LCD_H
diff --git a/src/devices/bus/bbc/userport/lvlecho.cpp b/src/devices/bus/bbc/userport/lvlecho.cpp
new file mode 100644
index 00000000000..296689af001
--- /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 ATTR_COLD;
+
+ // optional information overrides
+ virtual ioport_constructor device_input_ports() const override ATTR_COLD;
+
+ 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_GM_C2
+
+ PORT_START("KEY_1")
+ PORT_BIT(0x40, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_GM_CS2
+
+ PORT_START("KEY_2")
+ PORT_BIT(0x40, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_GM_D2
+
+ PORT_START("KEY_3")
+ PORT_BIT(0x40, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_GM_DS2
+
+ PORT_START("KEY_4")
+ PORT_BIT(0x40, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_GM_E2
+
+ PORT_START("KEY_5")
+ PORT_BIT(0x40, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_GM_F2
+
+ PORT_START("KEY_6")
+ PORT_BIT(0x40, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_GM_FS2
+
+ PORT_START("KEY_7")
+ PORT_BIT(0x40, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_GM_G2
+
+ PORT_START("KEY_8")
+ PORT_BIT(0x40, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_GM_GS2
+
+ PORT_START("KEY_9")
+ PORT_BIT(0x40, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_GM_A2
+
+ PORT_START("KEY_10")
+ PORT_BIT(0x40, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_GM_AS2
+
+ PORT_START("KEY_11")
+ PORT_BIT(0x40, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_GM_B2
+
+ PORT_START("KEY_12")
+ PORT_BIT(0x40, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_GM_C3 PORT_CODE(KEYCODE_TAB)
+
+ PORT_START("KEY_13")
+ PORT_BIT(0x40, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_GM_CS3 PORT_CODE(KEYCODE_1)
+
+ PORT_START("KEY_14")
+ PORT_BIT(0x40, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_GM_D3 PORT_CODE(KEYCODE_Q)
+
+ PORT_START("KEY_15")
+ PORT_BIT(0x40, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_GM_DS3 PORT_CODE(KEYCODE_2)
+
+ PORT_START("KEY_16")
+ PORT_BIT(0x40, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_GM_E3 PORT_CODE(KEYCODE_W)
+
+ PORT_START("KEY_17")
+ PORT_BIT(0x40, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_GM_F3 PORT_CODE(KEYCODE_E)
+
+ PORT_START("KEY_18")
+ PORT_BIT(0x40, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_GM_FS3 PORT_CODE(KEYCODE_4)
+
+ PORT_START("KEY_19")
+ PORT_BIT(0x40, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_GM_G3 PORT_CODE(KEYCODE_R)
+
+ PORT_START("KEY_20")
+ PORT_BIT(0x40, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_GM_GS3 PORT_CODE(KEYCODE_5)
+
+ PORT_START("KEY_21")
+ PORT_BIT(0x40, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_GM_A3 PORT_CODE(KEYCODE_T)
+
+ PORT_START("KEY_22")
+ PORT_BIT(0x40, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_GM_AS3 PORT_CODE(KEYCODE_6)
+
+ PORT_START("KEY_23")
+ PORT_BIT(0x40, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_GM_B3 PORT_CODE(KEYCODE_Y)
+
+ PORT_START("KEY_24")
+ PORT_BIT(0x40, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_GM_C4 PORT_CODE(KEYCODE_U)
+
+ PORT_START("KEY_25")
+ PORT_BIT(0x40, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_GM_CS4 PORT_CODE(KEYCODE_8)
+
+ PORT_START("KEY_26")
+ PORT_BIT(0x40, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_GM_D4 PORT_CODE(KEYCODE_I)
+
+ PORT_START("KEY_27")
+ PORT_BIT(0x40, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_GM_DS4 PORT_CODE(KEYCODE_9)
+
+ PORT_START("KEY_28")
+ PORT_BIT(0x40, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_GM_E4 PORT_CODE(KEYCODE_O)
+
+ PORT_START("KEY_29")
+ PORT_BIT(0x40, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_GM_F4 PORT_CODE(KEYCODE_P)
+
+ PORT_START("KEY_30")
+ PORT_BIT(0x40, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_GM_FS4 PORT_CODE(KEYCODE_A)
+
+ PORT_START("KEY_31")
+ PORT_BIT(0x40, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_GM_G4 PORT_CODE(KEYCODE_Z)
+
+ PORT_START("KEY_32")
+ PORT_BIT(0x40, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_GM_GS4 PORT_CODE(KEYCODE_S)
+
+ PORT_START("KEY_33")
+ PORT_BIT(0x40, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_GM_A4 PORT_CODE(KEYCODE_X)
+
+ PORT_START("KEY_34")
+ PORT_BIT(0x40, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_GM_AS4 PORT_CODE(KEYCODE_D)
+
+ PORT_START("KEY_35")
+ PORT_BIT(0x40, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_GM_B4 PORT_CODE(KEYCODE_C)
+
+ PORT_START("KEY_36")
+ PORT_BIT(0x40, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_GM_C5 PORT_CODE(KEYCODE_V)
+
+ PORT_START("KEY_37")
+ PORT_BIT(0x40, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_GM_CS5 PORT_CODE(KEYCODE_G)
+
+ PORT_START("KEY_38")
+ PORT_BIT(0x40, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_GM_D5 PORT_CODE(KEYCODE_B)
+
+ PORT_START("KEY_39")
+ PORT_BIT(0x40, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_GM_DS5 PORT_CODE(KEYCODE_H)
+
+ PORT_START("KEY_40")
+ PORT_BIT(0x40, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_GM_E5 PORT_CODE(KEYCODE_N)
+
+ PORT_START("KEY_41")
+ PORT_BIT(0x40, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_GM_F5 PORT_CODE(KEYCODE_M)
+
+ PORT_START("KEY_42")
+ PORT_BIT(0x40, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_GM_FS5 PORT_CODE(KEYCODE_K)
+
+ PORT_START("KEY_43")
+ PORT_BIT(0x40, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_GM_G5 PORT_CODE(KEYCODE_COMMA)
+
+ PORT_START("KEY_44")
+ PORT_BIT(0x40, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_GM_GS5 PORT_CODE(KEYCODE_L)
+
+ PORT_START("KEY_45")
+ PORT_BIT(0x40, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_GM_A5 PORT_CODE(KEYCODE_STOP)
+
+ PORT_START("KEY_46")
+ PORT_BIT(0x40, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_GM_AS5 PORT_CODE(KEYCODE_COLON)
+
+ PORT_START("KEY_47")
+ PORT_BIT(0x40, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_GM_B5 PORT_CODE(KEYCODE_SLASH)
+
+ PORT_START("KEY_48")
+ PORT_BIT(0x40, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_GM_C6 PORT_CODE(KEYCODE_RSHIFT)
+
+ PORT_START("KEY_49")
+ PORT_BIT(0x40, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_GM_CS6
+
+ PORT_START("KEY_50")
+ PORT_BIT(0x40, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_GM_D6
+
+ PORT_START("KEY_51")
+ PORT_BIT(0x40, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_GM_DS6
+
+ PORT_START("KEY_52")
+ PORT_BIT(0x40, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_GM_E6
+
+ PORT_START("KEY_53")
+ PORT_BIT(0x40, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_GM_F6
+
+ PORT_START("KEY_54")
+ PORT_BIT(0x40, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_GM_FS6
+
+ PORT_START("KEY_55")
+ PORT_BIT(0x40, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_GM_G6
+
+ PORT_START("KEY_56")
+ PORT_BIT(0x40, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_GM_GS6
+
+ PORT_START("KEY_57")
+ PORT_BIT(0x40, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_GM_A6
+
+ PORT_START("KEY_58")
+ PORT_BIT(0x40, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_GM_AS6
+
+ PORT_START("KEY_59")
+ PORT_BIT(0x40, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_GM_B6
+
+ PORT_START("KEY_60")
+ PORT_BIT(0x40, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_GM_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
new file mode 100644
index 00000000000..a8ae52e3a7d
--- /dev/null
+++ b/src/devices/bus/bbc/userport/m4000.cpp
@@ -0,0 +1,185 @@
+// license:BSD-3-Clause
+// copyright-holders:Nigel Barnes
+/**********************************************************************
+
+ Hybrid Music 4000 Keyboard (also known as ATPL Symphony)
+
+ https://www.retro-kit.co.uk/page.cfm/content/Hybrid-Music-4000-Keyboard/
+ http://chrisacorns.computinghistory.org.uk/8bit_Upgrades/Hybrid_Music4000.html
+
+**********************************************************************/
+
+#include "emu.h"
+#include "m4000.h"
+
+
+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 ATTR_COLD;
+
+ // optional information overrides
+ virtual ioport_constructor device_input_ports() const override ATTR_COLD;
+
+ 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;
+};
+
+
+//-------------------------------------------------
+// INPUT_PORTS( m4000 )
+//-------------------------------------------------
+
+static INPUT_PORTS_START( m4000 )
+ PORT_START("KBLOCK_1")
+ PORT_BIT(0x01, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_GM_C2 PORT_CODE(KEYCODE_TAB)
+ PORT_BIT(0x02, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_GM_CS2 PORT_CODE(KEYCODE_1)
+ PORT_BIT(0x04, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_GM_D2 PORT_CODE(KEYCODE_Q)
+ PORT_BIT(0x08, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_GM_DS2 PORT_CODE(KEYCODE_2)
+ PORT_BIT(0x10, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_GM_E2 PORT_CODE(KEYCODE_W)
+ PORT_BIT(0x20, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_GM_F2 PORT_CODE(KEYCODE_E)
+ PORT_BIT(0x40, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_GM_FS2 PORT_CODE(KEYCODE_4)
+ PORT_BIT(0x80, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_GM_G2 PORT_CODE(KEYCODE_R)
+
+ PORT_START("KBLOCK_2")
+ PORT_BIT(0x01, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_GM_GS2 PORT_CODE(KEYCODE_5)
+ PORT_BIT(0x02, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_GM_A2 PORT_CODE(KEYCODE_T)
+ PORT_BIT(0x04, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_GM_AS2 PORT_CODE(KEYCODE_6)
+ PORT_BIT(0x08, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_GM_B2 PORT_CODE(KEYCODE_Y)
+ PORT_BIT(0x10, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_GM_C3 PORT_CODE(KEYCODE_U)
+ PORT_BIT(0x20, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_GM_CS3 PORT_CODE(KEYCODE_8)
+ PORT_BIT(0x40, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_GM_D3 PORT_CODE(KEYCODE_I)
+ PORT_BIT(0x80, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_GM_DS3 PORT_CODE(KEYCODE_9)
+
+ PORT_START("KBLOCK_3")
+ PORT_BIT(0x01, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_GM_E3 PORT_CODE(KEYCODE_O)
+ PORT_BIT(0x02, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_GM_F3 PORT_CODE(KEYCODE_P)
+ PORT_BIT(0x04, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_GM_FS3 PORT_CODE(KEYCODE_A)
+ PORT_BIT(0x08, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_GM_G3 PORT_CODE(KEYCODE_Z)
+ PORT_BIT(0x10, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_GM_GS3 PORT_CODE(KEYCODE_S)
+ PORT_BIT(0x20, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_GM_A3 PORT_CODE(KEYCODE_X)
+ PORT_BIT(0x40, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_GM_AS3 PORT_CODE(KEYCODE_D)
+ PORT_BIT(0x80, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_GM_B3 PORT_CODE(KEYCODE_C)
+
+ PORT_START("KBLOCK_4")
+ PORT_BIT(0x01, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_GM_C4 PORT_CODE(KEYCODE_V)
+ PORT_BIT(0x02, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_GM_CS4 PORT_CODE(KEYCODE_G)
+ PORT_BIT(0x04, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_GM_D4 PORT_CODE(KEYCODE_B)
+ PORT_BIT(0x08, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_GM_DS4 PORT_CODE(KEYCODE_H)
+ PORT_BIT(0x10, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_GM_E4 PORT_CODE(KEYCODE_N)
+ PORT_BIT(0x20, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_GM_F4 PORT_CODE(KEYCODE_M)
+ PORT_BIT(0x40, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_GM_FS4 PORT_CODE(KEYCODE_K)
+ PORT_BIT(0x80, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_GM_G4 PORT_CODE(KEYCODE_COMMA)
+
+ PORT_START("KBLOCK_5")
+ PORT_BIT(0x01, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_GM_GS4 PORT_CODE(KEYCODE_L)
+ PORT_BIT(0x02, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_GM_A4 PORT_CODE(KEYCODE_STOP)
+ PORT_BIT(0x04, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_GM_AS4 PORT_CODE(KEYCODE_COLON)
+ PORT_BIT(0x08, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_GM_B4 PORT_CODE(KEYCODE_SLASH)
+ PORT_BIT(0x10, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_GM_C5 PORT_CODE(KEYCODE_RSHIFT)
+ PORT_BIT(0x20, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_GM_CS5
+ PORT_BIT(0x40, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_GM_D5
+ PORT_BIT(0x80, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_GM_DS5
+
+ PORT_START("KBLOCK_6")
+ PORT_BIT(0x01, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_GM_E5
+ PORT_BIT(0x02, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_GM_F5
+ PORT_BIT(0x04, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_GM_FS5
+ PORT_BIT(0x08, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_GM_G5
+ PORT_BIT(0x10, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_GM_GS5
+ PORT_BIT(0x20, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_GM_A5
+ PORT_BIT(0x40, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_GM_AS5
+ PORT_BIT(0x80, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_GM_B5
+
+ PORT_START("KBLOCK_7")
+ PORT_BIT(0x01, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_GM_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_KEYBOARD) PORT_NAME("Foot Switch")
+INPUT_PORTS_END
+
+
+//-------------------------------------------------
+// input_ports - device-specific input ports
+//-------------------------------------------------
+
+ioport_constructor bbc_m4000_device::device_input_ports() const
+{
+ return INPUT_PORTS_NAME( m4000 );
+}
+
+
+//-------------------------------------------------
+// device_start - device-specific startup
+//-------------------------------------------------
+
+void bbc_m4000_device::device_start()
+{
+ save_item(NAME(m_clk));
+ save_item(NAME(m_dsb));
+ save_item(NAME(m_out));
+}
+
+
+//**************************************************************************
+// IMPLEMENTATION
+//**************************************************************************
+
+void bbc_m4000_device::write_cb1(int state)
+{
+ // 74hc164
+ if (!m_clk && state)
+ {
+ m_out = (m_out << 1) | m_dsb;
+ }
+ m_clk = state;
+}
+
+void bbc_m4000_device::write_cb2(int state)
+{
+ // 74hc164
+ m_dsb = state;
+}
+
+uint8_t bbc_m4000_device::pb_r()
+{
+ uint8_t data = 0xff;
+
+ for (int block = 0; block < 8; block++)
+ {
+ if (!BIT(m_out, block))
+ data = m_kbd[block]->read();
+ }
+
+ 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
new file mode 100644
index 00000000000..75297243c27
--- /dev/null
+++ b/src/devices/bus/bbc/userport/m4000.h
@@ -0,0 +1,13 @@
+// license:BSD-3-Clause
+// copyright-holders:Nigel Barnes
+#ifndef MAME_BUS_BBC_USERPORT_M4000_H
+#define MAME_BUS_BBC_USERPORT_M4000_H
+
+#pragma once
+
+#include "userport.h"
+
+
+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
new file mode 100644
index 00000000000..090fae74593
--- /dev/null
+++ b/src/devices/bus/bbc/userport/palext.cpp
@@ -0,0 +1,140 @@
+// license:BSD-3-Clause
+// copyright-holders:Nigel Barnes
+/**********************************************************************
+
+ Clwyd Technics Colour Palette
+
+ Micro User Chameleon (DIY) - Micro User Jan/Feb 1990
+
+ TODO:
+ - the Chameleon should also implement a CB2 handler, as this is
+ pulsed whenever PB is written to. pb_w should only latch the
+ data, then a CB2 handler would update the palette.
+
+**********************************************************************/
+
+#include "emu.h"
+#include "palext.h"
+
+#include <algorithm>
+
+
+//**************************************************************************
+// DEVICE DEFINITIONS
+//**************************************************************************
+
+DEFINE_DEVICE_TYPE(BBC_CHAMELEON, bbc_chameleon_device, "bbc_chameleon", "Micro User Chameleon (DIY)")
+DEFINE_DEVICE_TYPE(BBC_CPALETTE, bbc_cpalette_device, "bbc_cpalette", "Clwyd Technics Colour Palette")
+
+
+//-------------------------------------------------
+// ROM( chameleon )
+//-------------------------------------------------
+
+ROM_START(chameleon)
+ ROM_REGION(0x2000, "exp_rom", 0)
+ ROM_LOAD("chameleon.rom", 0x0000, 0x2000, CRC(e0ea0252) SHA1(72cf334cdb866ba3dd2353fc7da0dfdb6abf63a7))
+ROM_END
+
+//-------------------------------------------------
+// rom_region - device-specific ROM region
+//-------------------------------------------------
+
+const tiny_rom_entry* bbc_chameleon_device::device_rom_region() const
+{
+ return ROM_NAME(chameleon);
+}
+
+
+//**************************************************************************
+// LIVE DEVICE
+//**************************************************************************
+
+//-------------------------------------------------
+// bbc_palext_device - constructor
+//-------------------------------------------------
+
+bbc_palext_device::bbc_palext_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_userport_interface(mconfig, *this)
+ , m_palette(*this, ":palette")
+ , m_colour(0)
+{
+}
+
+bbc_chameleon_device::bbc_chameleon_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
+ : bbc_palext_device(mconfig, BBC_CHAMELEON, tag, owner, clock)
+{
+}
+
+bbc_cpalette_device::bbc_cpalette_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
+ : bbc_palext_device(mconfig, BBC_CPALETTE, tag, owner, clock)
+{
+}
+
+
+//-------------------------------------------------
+// device_start - device-specific startup
+//-------------------------------------------------
+
+void bbc_palext_device::device_start()
+{
+ std::fill(std::begin(m_palette_ram), std::end(m_palette_ram), rgb_t(0));
+
+ // register for save states
+ save_item(NAME(m_colour));
+ save_item(NAME(m_palette_ram));
+}
+
+
+//**************************************************************************
+// IMPLEMENTATION
+//**************************************************************************
+
+void bbc_chameleon_device::pb_w(uint8_t data)
+{
+ data ^= 0x0f;
+
+ switch (data >> 6)
+ {
+ case 0x00:
+ m_palette_ram[m_colour].set_r(pal4bit(data));
+ break;
+ case 0x01:
+ m_palette_ram[m_colour].set_g(pal4bit(data));
+ break;
+ case 0x02:
+ m_palette_ram[m_colour].set_b(pal4bit(data));
+ break;
+ case 0x03:
+ m_colour = data & 0x0f;
+ m_palette->set_pen_colors(0, &m_palette_ram[BIT(data, 5) << 3], 8);
+ break;
+ }
+}
+
+void bbc_cpalette_device::pb_w(uint8_t data)
+{
+ if (BIT(data, 3))
+ {
+ switch (data & 0x07)
+ {
+ case 0x00:
+ m_colour = ~(data >> 4) & 0x07;
+ break;
+ case 0x01:
+ m_palette_ram[m_colour].set_r(pal4bit(data));
+ break;
+ case 0x02:
+ m_palette_ram[m_colour].set_g(pal4bit(data));
+ break;
+ case 0x03:
+ m_palette_ram[m_colour].set_b(pal4bit(data));
+ break;
+ }
+ }
+ else
+ {
+ m_palette->set_pen_colors(0, &m_palette_ram[0], 8);
+ }
+}
diff --git a/src/devices/bus/bbc/userport/palext.h b/src/devices/bus/bbc/userport/palext.h
new file mode 100644
index 00000000000..7597bcf44f7
--- /dev/null
+++ b/src/devices/bus/bbc/userport/palext.h
@@ -0,0 +1,78 @@
+// license:BSD-3-Clause
+// copyright-holders:Nigel Barnes
+/**********************************************************************
+
+ Clwyd Technics Colour Palette
+
+ Micro User Chameleon (DIY) - Micro User Jan/Feb 1990
+
+**********************************************************************/
+
+
+#ifndef MAME_BUS_BBC_USERPORT_PALEXT_H
+#define MAME_BUS_BBC_USERPORT_PALEXT_H
+
+#pragma once
+
+#include "userport.h"
+#include "emupal.h"
+
+//**************************************************************************
+// TYPE DEFINITIONS
+//**************************************************************************
+
+class bbc_palext_device :
+ public device_t,
+ public device_bbc_userport_interface
+{
+protected:
+ // construction/destruction
+ bbc_palext_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 ATTR_COLD;
+
+ required_device<palette_device> m_palette;
+
+ uint8_t m_colour;
+ rgb_t m_palette_ram[16];
+};
+
+
+// ======================> bbc_chameleon_device
+
+class bbc_chameleon_device : public bbc_palext_device
+{
+public:
+ // construction/destruction
+ bbc_chameleon_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
+
+protected:
+ // optional information overrides
+ virtual const tiny_rom_entry* device_rom_region() const override;
+
+ virtual void pb_w(uint8_t data) override;
+};
+
+
+// ======================> bbc_cpalette_device
+
+class bbc_cpalette_device : public bbc_palext_device
+{
+public:
+ static constexpr feature_type imperfect_features() { return feature::PALETTE; }
+
+ // construction/destruction
+ bbc_cpalette_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
+
+protected:
+ virtual void pb_w(uint8_t data) override;
+};
+
+
+// device type definition
+DECLARE_DEVICE_TYPE(BBC_CHAMELEON, bbc_chameleon_device)
+DECLARE_DEVICE_TYPE(BBC_CPALETTE, bbc_cpalette_device)
+
+
+#endif // MAME_BUS_BBC_USERPORT_PALEXT_H
diff --git a/src/devices/bus/bbc/userport/pointer.cpp b/src/devices/bus/bbc/userport/pointer.cpp
index d8272766d98..cff7c1570e2 100644
--- a/src/devices/bus/bbc/userport/pointer.cpp
+++ b/src/devices/bus/bbc/userport/pointer.cpp
@@ -47,10 +47,10 @@ DEFINE_DEVICE_TYPE(BBC_TRACKER, bbc_tracker_device, "bbc_tracker", "Marcon
static INPUT_PORTS_START( amxmouse )
PORT_START("POINTER_X")
- PORT_BIT(0xff, 0x00, IPT_MOUSE_X) PORT_SENSITIVITY(100) PORT_KEYDELTA(5) PORT_CHANGED_MEMBER(DEVICE_SELF, bbc_pointer_device, pointer_changed, 0) PORT_RESET
+ PORT_BIT(0xff, 0x00, IPT_MOUSE_X) PORT_SENSITIVITY(100)
PORT_START("POINTER_Y")
- PORT_BIT(0xff, 0x00, IPT_MOUSE_Y) PORT_SENSITIVITY(100) PORT_KEYDELTA(5) PORT_CHANGED_MEMBER(DEVICE_SELF, bbc_pointer_device, pointer_changed, 0) PORT_RESET
+ PORT_BIT(0xff, 0x00, IPT_MOUSE_Y) PORT_SENSITIVITY(100)
PORT_START("BUTTONS")
PORT_BIT(0x20, IP_ACTIVE_LOW, IPT_BUTTON1) PORT_NAME("Mouse Left Button (Execute)") PORT_CODE(MOUSECODE_BUTTON1)
@@ -65,10 +65,10 @@ INPUT_PORTS_END
static INPUT_PORTS_START( m512mouse )
PORT_START("POINTER_X")
- PORT_BIT(0xff, 0x00, IPT_MOUSE_X) PORT_SENSITIVITY(100) PORT_KEYDELTA(5) PORT_CHANGED_MEMBER(DEVICE_SELF, bbc_pointer_device, pointer_changed, 0) PORT_RESET
+ PORT_BIT(0xff, 0x00, IPT_MOUSE_X) PORT_SENSITIVITY(100)
PORT_START("POINTER_Y")
- PORT_BIT(0xff, 0x00, IPT_MOUSE_Y) PORT_SENSITIVITY(100) PORT_KEYDELTA(5) PORT_CHANGED_MEMBER(DEVICE_SELF, bbc_pointer_device, pointer_changed, 0) PORT_RESET
+ PORT_BIT(0xff, 0x00, IPT_MOUSE_Y) PORT_SENSITIVITY(100)
PORT_START("BUTTONS")
PORT_BIT(0x01, IP_ACTIVE_LOW, IPT_BUTTON1) PORT_NAME("Mouse Left Button") PORT_CODE(MOUSECODE_BUTTON1)
@@ -82,10 +82,10 @@ INPUT_PORTS_END
static INPUT_PORTS_START( tracker )
PORT_START("POINTER_X")
- PORT_BIT(0xff, 0x00, IPT_TRACKBALL_X) PORT_SENSITIVITY(100) PORT_KEYDELTA(5) PORT_CHANGED_MEMBER(DEVICE_SELF, bbc_pointer_device, pointer_changed, 0) PORT_RESET
+ PORT_BIT(0xff, 0x00, IPT_TRACKBALL_X) PORT_SENSITIVITY(100)
PORT_START("POINTER_Y")
- PORT_BIT(0xff, 0x00, IPT_TRACKBALL_Y) PORT_SENSITIVITY(100) PORT_KEYDELTA(5) PORT_CHANGED_MEMBER(DEVICE_SELF, bbc_pointer_device, pointer_changed, 0) PORT_RESET
+ PORT_BIT(0xff, 0x00, IPT_TRACKBALL_Y) PORT_SENSITIVITY(100)
PORT_START("BUTTONS")
PORT_BIT(0x01, IP_ACTIVE_LOW, IPT_BUTTON1) PORT_NAME("Left Button") PORT_CODE(MOUSECODE_BUTTON1)
@@ -151,8 +151,7 @@ bbc_tracker_device::bbc_tracker_device(const machine_config &mconfig, const char
void bbc_pointer_device::device_start()
{
- m_pointer_timer = machine().scheduler().timer_alloc(timer_expired_delegate(FUNC(bbc_pointer_device::pointer_poll), this));
- m_pointer_timer->adjust(attotime::zero, 0, attotime::from_hz(1400));
+ m_pointer_timer = timer_alloc(FUNC(bbc_pointer_device::update), this);
}
@@ -164,12 +163,12 @@ void bbc_pointer_device::device_reset()
{
m_xdir = 0;
m_ydir = 0;
- m_direction_x = 0;
- m_direction_y = 0;
- m_distance_x = 0;
- m_distance_y = 0;
+ m_x = 0;
+ m_y = 0;
m_phase_x = 0;
m_phase_y = 0;
+
+ m_pointer_timer->adjust(attotime::zero, 0, attotime::from_hz(1400));
}
@@ -177,25 +176,16 @@ void bbc_pointer_device::device_reset()
// IMPLEMENTATION
//**************************************************************************
-INPUT_CHANGED_MEMBER(bbc_pointer_device::pointer_changed)
+TIMER_CALLBACK_MEMBER(bbc_pointer_device::update)
{
int x = m_pointer_x->read();
int y = m_pointer_y->read();
- x -= (x & 0x80) ? 0x100 : 0;
- y -= (y & 0x80) ? 0x100 : 0;
- // Set the mouse movement direction and record the movement units
- m_direction_x = (x > 0) ? 1 : 0;
- m_distance_x = abs(x);
-
- m_direction_y = (y > 0) ? 1 : 0;
- m_distance_y = abs(y);
-}
+ int dx = x - m_x;
+ int dy = y - m_y;
-TIMER_CALLBACK_MEMBER(bbc_pointer_device::pointer_poll)
-{
// Process X output
- if (m_distance_x)
+ if (dx)
{
// Set the output pins according to the current phase
switch (m_phase_x)
@@ -215,20 +205,17 @@ TIMER_CALLBACK_MEMBER(bbc_pointer_device::pointer_poll)
}
// Change phase
- if (m_direction_x == 0)
- m_phase_x--;
- else
+ if (dx > 0)
m_phase_x++;
-
- // Decrement the distance left to move
- m_distance_x--;
+ else
+ m_phase_x--;
// Range check the phase
m_phase_x &= 3;
}
// Process Y output
- if (m_distance_y)
+ if (dy)
{
// Set the output pins according to the current phase
switch (m_phase_y)
@@ -248,17 +235,17 @@ TIMER_CALLBACK_MEMBER(bbc_pointer_device::pointer_poll)
}
// Change phase
- if (m_direction_y == 0)
- m_phase_y--;
- else
+ if (dy > 0)
m_phase_y++;
-
- // Decrement the distance left to move
- m_distance_y--;
+ else
+ m_phase_y--;
// Range check the phase
m_phase_y &= 3;
}
+
+ m_x = x;
+ m_y = y;
}
uint8_t bbc_amxmouse_device::pb_r()
diff --git a/src/devices/bus/bbc/userport/pointer.h b/src/devices/bus/bbc/userport/pointer.h
index a6e1bd0a629..eeff3ec449a 100644
--- a/src/devices/bus/bbc/userport/pointer.h
+++ b/src/devices/bus/bbc/userport/pointer.h
@@ -22,16 +22,15 @@ class bbc_pointer_device :
public device_t,
public device_bbc_userport_interface
{
-public:
- DECLARE_INPUT_CHANGED_MEMBER(pointer_changed);
-
protected:
// construction/destruction
bbc_pointer_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_start() override ATTR_COLD;
+ virtual void device_reset() override ATTR_COLD;
+
+ TIMER_CALLBACK_MEMBER(update);
required_ioport m_pointer_x;
required_ioport m_pointer_y;
@@ -41,11 +40,9 @@ protected:
int m_xdir, m_ydir;
// internal quadrature state
- int m_direction_x, m_direction_y;
- int m_distance_x, m_distance_y;
+ int m_x, m_y;
int m_phase_x, m_phase_y;
- TIMER_CALLBACK_MEMBER(pointer_poll);
emu_timer *m_pointer_timer;
};
@@ -61,7 +58,7 @@ public:
uint8_t pb_r() override;
// optional information overrides
- virtual ioport_constructor device_input_ports() const override;
+ virtual ioport_constructor device_input_ports() const override ATTR_COLD;
};
@@ -76,7 +73,7 @@ public:
uint8_t pb_r() override;
// optional information overrides
- virtual ioport_constructor device_input_ports() const override;
+ virtual ioport_constructor device_input_ports() const override ATTR_COLD;
};
@@ -91,7 +88,7 @@ public:
uint8_t pb_r() override;
// optional information overrides
- virtual ioport_constructor device_input_ports() const override;
+ virtual ioport_constructor device_input_ports() const override ATTR_COLD;
};
diff --git a/src/devices/bus/bbc/userport/sdcard.cpp b/src/devices/bus/bbc/userport/sdcard.cpp
new file mode 100644
index 00000000000..36f0bf2c1ac
--- /dev/null
+++ b/src/devices/bus/bbc/userport/sdcard.cpp
@@ -0,0 +1,215 @@
+// license:BSD-3-Clause
+// copyright-holders:Nigel Barnes
+/**********************************************************************
+
+ BBC Micro SD Card
+
+ Original Interface Hardware
+ ===========================
+
+ This is the original interface design, as conceived by Martin Mather
+ in 2006.
+
+ User Port SD Card
+ (Master) (Slave)
+ ========= =======
+ CB1/PB1 ==> S_CLK (Clock)
+ CB2 <== S_MISO (Dout)
+ PB0 ==> S_MOSI (Din)
+ 0V ==> S_SEL (Select)
+
+ TurboMMC Interface Hardware
+ ===========================
+
+ The TurboMMC hardware is a more complicated, as it uses PB[4:2] to
+ control three buffers, providing two different operating modes.
+
+ When PB[4:2] are 010, then the hardware is configured as above, and
+ the interface is compatible with the original hardware.
+
+ When PB[4:2] are 101, then the hardware is re-configured as:
+
+ User Port SD Card
+ (Master) (Slave)
+ ========= =======
+ CB1/PB1 ==> S_CLK (Clock)
+ n/c <== S_MISO (Dout)
+ CB2 ==> S_MOSI (Din)
+ 0V ==> S_SEL (Select)
+
+**********************************************************************/
+
+
+#include "emu.h"
+#include "sdcard.h"
+
+#include "machine/spi_sdcard.h"
+
+
+namespace {
+
+//**************************************************************************
+// TYPE DEFINITIONS
+//**************************************************************************
+
+// ======================> bbc_sdcard_device
+
+class bbc_sdcard_device : public device_t, public device_bbc_userport_interface
+{
+public:
+ // construction/destruction
+ bbc_sdcard_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
+
+protected:
+ bbc_sdcard_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 ATTR_COLD;
+ virtual void device_add_mconfig(machine_config &config) override ATTR_COLD;
+
+ // device_bbc_userport_interface implementation
+ virtual void pb_w(uint8_t data) override;
+ virtual void write_cb1(int state) override;
+
+ required_device<spi_sdcard_device> m_sdcard;
+};
+
+
+// ======================> bbc_sdcardt_device
+
+class bbc_sdcardt_device : public bbc_sdcard_device
+{
+public:
+ // construction/destruction
+ bbc_sdcardt_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
+
+protected:
+ // device_t implementation
+ virtual void device_start() override ATTR_COLD;
+ virtual void device_add_mconfig(machine_config &config) override ATTR_COLD;
+
+ // device_bbc_userport_interface implementation
+ virtual void pb_w(uint8_t data) override;
+ virtual void write_cb1(int state) override;
+ virtual void write_cb2(int state) override;
+
+private:
+ bool m_turbo;
+};
+
+
+//-------------------------------------------------
+// device_add_mconfig - add device configuration
+//-------------------------------------------------
+
+void bbc_sdcard_device::device_add_mconfig(machine_config &config)
+{
+ SPI_SDCARD(config, m_sdcard, 0);
+ m_sdcard->set_prefer_sdhc();
+ m_sdcard->spi_miso_callback().set([this](int state) { m_slot->cb2_w(state); });
+}
+
+void bbc_sdcardt_device::device_add_mconfig(machine_config &config)
+{
+ SPI_SDCARD(config, m_sdcard, 0);
+ m_sdcard->set_prefer_sdhc();
+ m_sdcard->spi_miso_callback().set([this](int state) { if (!m_turbo) m_slot->cb2_w(state); });
+}
+
+
+//**************************************************************************
+// LIVE DEVICE
+//**************************************************************************
+
+//-------------------------------------------------
+// bbc_sdcard_device - constructor
+//-------------------------------------------------
+
+bbc_sdcard_device::bbc_sdcard_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_userport_interface(mconfig, *this)
+ , m_sdcard(*this, "sdcard")
+{
+}
+
+bbc_sdcard_device::bbc_sdcard_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
+ : bbc_sdcard_device(mconfig, BBC_SDCARD, tag, owner, clock)
+{
+}
+
+bbc_sdcardt_device::bbc_sdcardt_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
+ : bbc_sdcard_device(mconfig, BBC_SDCARDT, tag, owner, clock)
+ , m_turbo(false)
+{
+}
+
+
+//-------------------------------------------------
+// device_start - device-specific startup
+//-------------------------------------------------
+
+void bbc_sdcard_device::device_start()
+{
+}
+
+void bbc_sdcardt_device::device_start()
+{
+ save_item(NAME(m_turbo));
+}
+
+
+//**************************************************************************
+// IMPLEMENTATION
+//**************************************************************************
+
+void bbc_sdcard_device::write_cb1(int state)
+{
+ m_sdcard->spi_ss_w(1);
+ m_sdcard->spi_clock_w(state);
+}
+
+void bbc_sdcard_device::pb_w(uint8_t data)
+{
+ m_sdcard->spi_ss_w(1);
+ m_sdcard->spi_mosi_w(BIT(data, 0));
+ m_sdcard->spi_clock_w(BIT(data, 1));
+
+ m_slot->cb1_w(BIT(data, 1));
+}
+
+
+void bbc_sdcardt_device::write_cb1(int state)
+{
+ m_sdcard->spi_ss_w(1);
+ m_sdcard->spi_clock_w(state);
+}
+
+void bbc_sdcardt_device::write_cb2(int state)
+{
+ if (m_turbo)
+ {
+ m_sdcard->spi_ss_w(1);
+ m_sdcard->spi_mosi_w(state);
+ }
+}
+
+void bbc_sdcardt_device::pb_w(uint8_t data)
+{
+ m_turbo = (data & 0x1c) == 0x14;
+
+ m_sdcard->spi_ss_w(1);
+ m_sdcard->spi_mosi_w(BIT(data, 0));
+ m_sdcard->spi_clock_w(BIT(data, 1));
+
+ m_slot->cb1_w(BIT(data, 1));
+}
+
+} // anonymous namespace
+
+
+//**************************************************************************
+// DEVICE DEFINITIONS
+//**************************************************************************
+
+DEFINE_DEVICE_TYPE_PRIVATE(BBC_SDCARD, device_bbc_userport_interface, bbc_sdcard_device, "bbc_sdcard", "BBC Micro SD Card")
+DEFINE_DEVICE_TYPE_PRIVATE(BBC_SDCARDT, device_bbc_userport_interface, bbc_sdcardt_device, "bbc_sdcardt", "BBC Micro Turbo SD Card")
diff --git a/src/devices/bus/bbc/userport/sdcard.h b/src/devices/bus/bbc/userport/sdcard.h
new file mode 100644
index 00000000000..30cae6748ee
--- /dev/null
+++ b/src/devices/bus/bbc/userport/sdcard.h
@@ -0,0 +1,21 @@
+// license:BSD-3-Clause
+// copyright-holders:Nigel Barnes
+/**********************************************************************
+
+ BBC Micro SD Card
+
+**********************************************************************/
+
+
+#ifndef MAME_BUS_BBC_USERPORT_SDCARD_H
+#define MAME_BUS_BBC_USERPORT_SDCARD_H
+
+#pragma once
+
+#include "userport.h"
+
+
+DECLARE_DEVICE_TYPE(BBC_SDCARD, device_bbc_userport_interface)
+DECLARE_DEVICE_TYPE(BBC_SDCARDT, device_bbc_userport_interface)
+
+#endif // MAME_BUS_BBC_USERPORT_SDCARD_H
diff --git a/src/devices/bus/bbc/userport/userport.cpp b/src/devices/bus/bbc/userport/userport.cpp
index 85a846544ed..d3b6467dd21 100644
--- a/src/devices/bus/bbc/userport/userport.cpp
+++ b/src/devices/bus/bbc/userport/userport.cpp
@@ -27,9 +27,9 @@ DEFINE_DEVICE_TYPE(BBC_USERPORT_SLOT, bbc_userport_slot_device, "bbc_userport_sl
//-------------------------------------------------
device_bbc_userport_interface::device_bbc_userport_interface(const machine_config &mconfig, device_t &device)
- : device_slot_card_interface(mconfig, 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());
}
@@ -51,12 +51,12 @@ device_bbc_userport_interface::~device_bbc_userport_interface()
// bbc_userport_slot_device - constructor
//-------------------------------------------------
-bbc_userport_slot_device::bbc_userport_slot_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) :
- device_t(mconfig, BBC_USERPORT_SLOT, tag, owner, clock),
- device_slot_interface(mconfig, *this),
- m_device(nullptr),
- m_cb1_handler(*this),
- m_cb2_handler(*this)
+bbc_userport_slot_device::bbc_userport_slot_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
+ : device_t(mconfig, BBC_USERPORT_SLOT, tag, owner, clock)
+ , device_single_card_slot_interface<device_bbc_userport_interface>(mconfig, *this)
+ , m_device(nullptr)
+ , m_cb1_handler(*this)
+ , m_cb2_handler(*this)
{
}
@@ -68,20 +68,7 @@ bbc_userport_slot_device::bbc_userport_slot_device(const machine_config &mconfig
void bbc_userport_slot_device::device_start()
{
- m_device = dynamic_cast<device_bbc_userport_interface *>(get_card_device());
-
- // resolve callbacks
- m_cb1_handler.resolve_safe();
- m_cb2_handler.resolve_safe();
-}
-
-
-//-------------------------------------------------
-// device_reset - device-specific reset
-//-------------------------------------------------
-
-void bbc_userport_slot_device::device_reset()
-{
+ m_device = get_card_device();
}
@@ -110,6 +97,28 @@ void bbc_userport_slot_device::pb_w(uint8_t data)
//-------------------------------------------------
+// write_cb1
+//-------------------------------------------------
+
+void bbc_userport_slot_device::write_cb1(int state)
+{
+ if (m_device)
+ m_device->write_cb1(state);
+}
+
+
+//-------------------------------------------------
+// write_cb2
+//-------------------------------------------------
+
+void bbc_userport_slot_device::write_cb2(int state)
+{
+ if (m_device)
+ m_device->write_cb2(state);
+}
+
+
+//-------------------------------------------------
// SLOT_INTERFACE( bbc_userport_devices )
//-------------------------------------------------
@@ -117,8 +126,16 @@ void bbc_userport_slot_device::pb_w(uint8_t data)
// slot devices
#include "beebspch.h"
//#include "digitiser.h"
+//#include "ev1.h"
+#include "lcd.h"
+#include "lvlecho.h"
+#include "m4000.h"
+#include "palext.h"
#include "pointer.h"
+#include "sdcard.h"
#include "usersplit.h"
+//#include "vci.h"
+#include "voicebox.h"
#include "cfa3000kbd.h"
@@ -128,9 +145,19 @@ void bbc_userport_devices(device_slot_interface &device)
//device.option_add("atr", BBC_ATR); /* Advanced Teletext Receiver (GIS) */
device.option_add("beebspch", BBC_BEEBSPCH); /* Beeb Speech Synthesiser (Watford Electronics) */
//device.option_add("beebvdig", BBC_BEEBVDIG); /* Beeb Video Digitiser (Watford Electronics) */
+ device.option_add("chameleon", BBC_CHAMELEON); /* Chameleon */
+ device.option_add("cpalette", BBC_CPALETTE); /* Clwyd Technics Colour Palette */
+ //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 */
+ device.option_add("sdcardt", BBC_SDCARDT); /* Turbo SD Card */
device.option_add("tracker", BBC_TRACKER); /* Marconi RB2 Tracker Ball / Acorn Tracker Ball */
device.option_add("usersplit", BBC_USERSPLIT); /*User Port Splitter (Watford Electronics) */
- //device.option_add("music4000", BBC_MUSIC4000); /* Hybrid Music 4000 Keyboard */
- device.option_add("cfa3000kbd", CFA3000_KBD); /* Henson CFA 3000 Keyboard */
+ //device.option_add("vci", BBC_VCI); /* Video Camera Interface (Data Harvest) */
+ device.option_add("voicebox", BBC_VOICEBOX); /* Robin Voice Box */
+ device.option_add_internal("cfa3000kbd", CFA3000_KBD);/* Henson CFA 3000 Keyboard */
}
diff --git a/src/devices/bus/bbc/userport/userport.h b/src/devices/bus/bbc/userport/userport.h
index e3040283a5a..c10fddee2dd 100644
--- a/src/devices/bus/bbc/userport/userport.h
+++ b/src/devices/bus/bbc/userport/userport.h
@@ -41,7 +41,7 @@
class device_bbc_userport_interface;
-class bbc_userport_slot_device : public device_t, public device_slot_interface
+class bbc_userport_slot_device : public device_t, public device_single_card_slot_interface<device_bbc_userport_interface>
{
public:
// construction/destruction
@@ -61,16 +61,19 @@ public:
auto cb1_handler() { return m_cb1_handler.bind(); }
auto cb2_handler() { return m_cb2_handler.bind(); }
- DECLARE_WRITE_LINE_MEMBER(cb1_w) { m_cb1_handler(state); }
- DECLARE_WRITE_LINE_MEMBER(cb2_w) { m_cb2_handler(state); }
+ // from slot
+ void cb1_w(int state) { m_cb1_handler(state); }
+ void cb2_w(int state) { m_cb2_handler(state); }
+ // from host
uint8_t pb_r();
void pb_w(uint8_t data);
+ void write_cb1(int state);
+ void write_cb2(int state);
protected:
// device-level overrides
- virtual void device_start() override;
- virtual void device_reset() override;
+ virtual void device_start() override ATTR_COLD;
device_bbc_userport_interface *m_device;
@@ -82,7 +85,7 @@ private:
// ======================> device_bbc_userport_interface
-class device_bbc_userport_interface : public device_slot_card_interface
+class device_bbc_userport_interface : public device_interface
{
public:
// construction/destruction
@@ -90,11 +93,13 @@ public:
virtual uint8_t pb_r() { return 0xff; }
virtual void pb_w(uint8_t data) { }
+ virtual void write_cb1(int state) { }
+ virtual void write_cb2(int state) { }
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 abe6ec155bf..48adaaddd89 100644
--- a/src/devices/bus/bbc/userport/usersplit.cpp
+++ b/src/devices/bus/bbc/userport/usersplit.cpp
@@ -23,7 +23,7 @@ DEFINE_DEVICE_TYPE(BBC_USERSPLIT, bbc_usersplit_device, "bbc_usersplit", "BBC Mi
static INPUT_PORTS_START( usersplit )
PORT_START("SELECT")
- PORT_CONFNAME(0x01, 0x00, "User Port") PORT_CHANGED_MEMBER(DEVICE_SELF, bbc_usersplit_device, userport_changed, 0)
+ PORT_CONFNAME(0x01, 0x00, "User Port") PORT_CHANGED_MEMBER(DEVICE_SELF, FUNC(bbc_usersplit_device::userport_changed), 0)
PORT_CONFSETTING(0x00, "A")
PORT_CONFSETTING(0x01, "B")
INPUT_PORTS_END
@@ -98,25 +98,36 @@ void bbc_usersplit_device::pb_w(uint8_t data)
m_userport[m_selected]->pb_w(data);
}
-WRITE_LINE_MEMBER(bbc_usersplit_device::cb1a_w)
+void bbc_usersplit_device::write_cb1(int state)
+{
+ m_userport[m_selected]->write_cb1(state);
+}
+
+void bbc_usersplit_device::write_cb2(int state)
+{
+ m_userport[m_selected]->write_cb2(state);
+}
+
+
+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 d10a31a3eb2..6094878990b 100644
--- a/src/devices/bus/bbc/userport/usersplit.h
+++ b/src/devices/bus/bbc/userport/usersplit.h
@@ -32,20 +32,22 @@ public:
protected:
// device-level overrides
- virtual void device_start() override;
+ virtual void device_start() override ATTR_COLD;
// optional information overrides
- virtual void device_add_mconfig(machine_config &config) override;
- virtual ioport_constructor device_input_ports() const override;
+ virtual void device_add_mconfig(machine_config &config) override ATTR_COLD;
+ virtual ioport_constructor device_input_ports() const override ATTR_COLD;
virtual uint8_t pb_r() override;
virtual void pb_w(uint8_t data) override;
+ virtual void write_cb1(int state) override;
+ 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/bbc/userport/voicebox.cpp b/src/devices/bus/bbc/userport/voicebox.cpp
new file mode 100644
index 00000000000..c42d71a2456
--- /dev/null
+++ b/src/devices/bus/bbc/userport/voicebox.cpp
@@ -0,0 +1,80 @@
+// license:BSD-3-Clause
+// copyright-holders:Nigel Barnes
+/**********************************************************************
+
+ Robin Voice Box - The Educational Software Company
+
+**********************************************************************/
+
+
+#include "emu.h"
+#include "voicebox.h"
+#include "speaker.h"
+
+
+//**************************************************************************
+// DEVICE DEFINITIONS
+//**************************************************************************
+
+DEFINE_DEVICE_TYPE(BBC_VOICEBOX, bbc_voicebox_device, "bbc_voicebox", "Robin Voice Box")
+
+
+ROM_START(voicebox)
+ 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 *bbc_voicebox_device::device_rom_region() const
+{
+ return ROM_NAME(voicebox);
+}
+
+//-------------------------------------------------
+// device_add_mconfig - add device configuration
+//-------------------------------------------------
+
+void bbc_voicebox_device::device_add_mconfig(machine_config &config)
+{
+ SPEAKER(config, "mono").front_center();
+ SP0256(config, m_nsp, 3120000); // TODO: unknown crystal
+ m_nsp->data_request_callback().set(DEVICE_SELF_OWNER, FUNC(bbc_userport_slot_device::cb1_w)).invert();
+ m_nsp->add_route(ALL_OUTPUTS, "mono", 1.0);
+}
+
+
+//**************************************************************************
+// LIVE DEVICE
+//**************************************************************************
+
+//-------------------------------------------------
+// bbc_voicebox_device - constructor
+//-------------------------------------------------
+
+bbc_voicebox_device::bbc_voicebox_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
+ : device_t(mconfig, BBC_VOICEBOX, tag, owner, clock)
+ , device_bbc_userport_interface(mconfig, *this)
+ , m_nsp(*this, "sp0256")
+{
+}
+
+
+//-------------------------------------------------
+// device_start - device-specific startup
+//-------------------------------------------------
+
+void bbc_voicebox_device::device_start()
+{
+}
+
+//**************************************************************************
+// IMPLEMENTATION
+//**************************************************************************
+
+void bbc_voicebox_device::pb_w(uint8_t data)
+{
+ m_nsp->ald_w(data & 0x3f);
+}
diff --git a/src/devices/bus/bbc/userport/voicebox.h b/src/devices/bus/bbc/userport/voicebox.h
new file mode 100644
index 00000000000..26c1e6680e3
--- /dev/null
+++ b/src/devices/bus/bbc/userport/voicebox.h
@@ -0,0 +1,49 @@
+// license:BSD-3-Clause
+// copyright-holders:Nigel Barnes
+/**********************************************************************
+
+ Robin Voice Box - The Educational Software Company
+
+**********************************************************************/
+
+#ifndef MAME_BUS_BBC_USERPORT_VOICEBOX_H
+#define MAME_BUS_BBC_USERPORT_VOICEBOX_H
+
+#include "userport.h"
+#include "sound/sp0256.h"
+
+
+//**************************************************************************
+// TYPE DEFINITIONS
+//**************************************************************************
+
+// ======================> bbc_voicebox_device
+
+class bbc_voicebox_device :
+ public device_t,
+ public device_bbc_userport_interface
+{
+public:
+ // construction/destruction
+ bbc_voicebox_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
+
+protected:
+ // device-level overrides
+ virtual void device_start() override ATTR_COLD;
+
+ // optional information overrides
+ virtual void device_add_mconfig(machine_config &config) override ATTR_COLD;
+ virtual const tiny_rom_entry *device_rom_region() const override ATTR_COLD;
+
+ virtual void pb_w(uint8_t data) override;
+
+private:
+ required_device<sp0256_device> m_nsp;
+};
+
+
+// device type definition
+DECLARE_DEVICE_TYPE(BBC_VOICEBOX, bbc_voicebox_device)
+
+
+#endif // MAME_BUS_BBC_USERPORT_VOICEBOX_H
diff --git a/src/devices/bus/bml3/bml3bus.cpp b/src/devices/bus/bml3/bml3bus.cpp
index 9acb1b9acb5..8c564cc2bb8 100644
--- a/src/devices/bus/bml3/bml3bus.cpp
+++ b/src/devices/bus/bml3/bml3bus.cpp
@@ -66,7 +66,9 @@ bml3bus_slot_device::bml3bus_slot_device(const machine_config &mconfig, const ch
bml3bus_slot_device::bml3bus_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_bml3bus_tag(nullptr), m_bml3bus_slottag(nullptr)
+ device_single_card_slot_interface<device_bml3bus_card_interface>(mconfig, *this),
+ m_bml3bus(*this, finder_base::DUMMY_TAG),
+ m_bml3bus_slottag(nullptr)
{
}
@@ -76,9 +78,9 @@ bml3bus_slot_device::bml3bus_slot_device(const machine_config &mconfig, device_t
void bml3bus_slot_device::device_start()
{
- device_bml3bus_card_interface *dev = dynamic_cast<device_bml3bus_card_interface *>(get_card_device());
-
- if (dev) dev->set_bml3bus_tag(m_bml3bus_tag, m_bml3bus_slottag);
+ device_bml3bus_card_interface *const dev = get_card_device();
+ if (dev)
+ dev->set_bml3bus(*m_bml3bus, m_bml3bus_slottag);
}
//**************************************************************************
@@ -102,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;
+ }
}
//-------------------------------------------------
@@ -115,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;
- }
}
//-------------------------------------------------
@@ -145,9 +141,27 @@ device_bml3bus_card_interface *bml3bus_device::get_bml3bus_card(int slot)
return m_device_list[slot];
}
-void bml3bus_device::add_bml3bus_card(int slot, device_bml3bus_card_interface *card)
+void bml3bus_device::add_bml3bus_card(int slot, device_bml3bus_card_interface &card)
{
- m_device_list[slot] = card;
+ 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)
@@ -166,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
@@ -183,10 +197,10 @@ WRITE_LINE_MEMBER( bml3bus_device::firq_w ) { m_out_firq_cb(state); }
// device_bml3bus_card_interface - constructor
//-------------------------------------------------
-device_bml3bus_card_interface::device_bml3bus_card_interface(const machine_config &mconfig, device_t &device)
- : device_slot_card_interface(mconfig, device),
- m_bml3bus(nullptr),
- m_bml3bus_tag(nullptr), m_bml3bus_slottag(nullptr), m_slot(0), m_next(nullptr)
+device_bml3bus_card_interface::device_bml3bus_card_interface(const machine_config &mconfig, device_t &device) :
+ device_interface(device, "bml3bus"),
+ m_bml3bus(nullptr),
+ m_slot(0)
{
}
@@ -199,18 +213,24 @@ device_bml3bus_card_interface::~device_bml3bus_card_interface()
{
}
-void device_bml3bus_card_interface::set_bml3bus_device()
+void device_bml3bus_card_interface::interface_pre_start()
{
- // extract the slot number from the last digit of the slot tag
- int tlen = strlen(m_bml3bus_slottag);
+ if (!m_bml3bus)
+ throw device_missing_dependencies();
+}
- m_slot = (m_bml3bus_slottag[tlen-1] - '1');
+void device_bml3bus_card_interface::set_bml3bus(bml3bus_device &bus, const char *slottag)
+{
+ assert(!m_bml3bus);
+ assert(!device().started());
+
+ // extract the slot number from the last digit of the slot tag
+ int tlen = strlen(slottag);
+ m_slot = (slottag[tlen - 1] - '1');
if (m_slot < 0 || m_slot >= BML3BUS_MAX_SLOTS)
- {
- fatalerror("Slot %x out of range for Hitachi MB-6890 Bus\n", m_slot);
- }
+ fatalerror("Slot %d out of range for Hitachi MB-6890 Bus\n", m_slot);
- m_bml3bus = dynamic_cast<bml3bus_device *>(device().machine().device(m_bml3bus_tag));
- m_bml3bus->add_bml3bus_card(m_slot, this);
+ m_bml3bus = &bus;
+ m_bml3bus->add_bml3bus_card(m_slot, *this);
}
diff --git a/src/devices/bus/bml3/bml3bus.h b/src/devices/bus/bml3/bml3bus.h
index 2132d376041..cdafbb3d33f 100644
--- a/src/devices/bus/bml3/bml3bus.h
+++ b/src/devices/bus/bml3/bml3bus.h
@@ -22,79 +22,86 @@
//**************************************************************************
class bml3bus_device;
+class device_bml3bus_card_interface;
+
class bml3bus_slot_device : public device_t,
- public device_slot_interface
+ public device_single_card_slot_interface<device_bml3bus_card_interface>
{
public:
// construction/destruction
- template <typename T>
- bml3bus_slot_device(machine_config const &mconfig, const char *tag, device_t *owner, const char *nbtag, T &&opts, const char *dflt)
+ template <typename T, typename U>
+ bml3bus_slot_device(machine_config const &mconfig, const char *tag, device_t *owner, T &&nbtag, U &&opts, const char *dflt)
: bml3bus_slot_device(mconfig, tag, owner, (uint32_t)0)
{
option_reset();
opts(*this);
set_default_option(dflt);
set_fixed(false);
- set_bml3bus_slot(nbtag, tag);
+ set_bml3bus_slot(std::forward<T>(nbtag), tag);
}
bml3bus_slot_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock = 0);
- // device-level overrides
- virtual void device_start() override;
-
// inline configuration
- void set_bml3bus_slot(const char *tag, const char *slottag) { m_bml3bus_tag = tag; m_bml3bus_slottag = slottag; }
+ template <typename T>
+ void set_bml3bus_slot(T &&tag, const char *slottag)
+ {
+ m_bml3bus.set_tag(std::forward<T>(tag));
+ m_bml3bus_slottag = slottag;
+ }
protected:
bml3bus_slot_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 ATTR_COLD;
+
// configuration
- const char *m_bml3bus_tag, *m_bml3bus_slottag;
+ required_device<bml3bus_device> m_bml3bus;
+ const char *m_bml3bus_slottag;
};
// device type definition
DECLARE_DEVICE_TYPE(BML3BUS_SLOT, bml3bus_slot_device)
-class device_bml3bus_card_interface;
// ======================> bml3bus_device
class bml3bus_device : public device_t
{
+ friend class device_bml3bus_card_interface;
public:
// construction/destruction
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(); }
- void add_bml3bus_card(int slot, device_bml3bus_card_interface *card);
device_bml3bus_card_interface *get_bml3bus_card(int slot);
- void set_nmi_line(int state);
- void set_irq_line(int state);
- void set_firq_line(int state);
-
- 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);
- address_space &space() const { return *m_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);
// device-level overrides
- virtual void device_start() override;
- virtual void device_reset() override;
+ virtual void device_start() override ATTR_COLD;
+ virtual void device_reset() override ATTR_COLD;
+
+ void add_bml3bus_card(int slot, device_bml3bus_card_interface &card);
- // internal state
- required_address_space m_space;
+ void set_nmi_line(int state);
+ void set_irq_line(int state);
+ void set_firq_line(int state);
+ // line callbacks
devcb_write_line m_out_nmi_cb;
devcb_write_line m_out_irq_cb;
devcb_write_line m_out_firq_cb;
@@ -109,34 +116,37 @@ DECLARE_DEVICE_TYPE(BML3BUS, bml3bus_device)
// ======================> device_bml3bus_card_interface
// class representing interface-specific live bml3bus card
-class device_bml3bus_card_interface : public device_slot_card_interface
+class device_bml3bus_card_interface : public device_interface
{
friend class bml3bus_device;
public:
// construction/destruction
virtual ~device_bml3bus_card_interface();
- device_bml3bus_card_interface *next() const { return m_next; }
+ // inline configuration
+ void set_bml3bus(bml3bus_device &bus, const char *slottag);
+
+protected:
+ virtual void interface_pre_start() override;
- void set_bml3bus_device();
+ 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); }
- void raise_slot_irq() { m_bml3bus->set_irq_line(ASSERT_LINE); }
- void lower_slot_irq() { m_bml3bus->set_irq_line(CLEAR_LINE); }
+ void raise_slot_nmi() { m_bml3bus->set_nmi_line(ASSERT_LINE); }
+ void lower_slot_nmi() { m_bml3bus->set_nmi_line(CLEAR_LINE); }
+ void raise_slot_irq() { m_bml3bus->set_irq_line(ASSERT_LINE); }
+ void lower_slot_irq() { m_bml3bus->set_irq_line(CLEAR_LINE); }
void raise_slot_firq() { m_bml3bus->set_firq_line(ASSERT_LINE); }
void lower_slot_firq() { m_bml3bus->set_firq_line(CLEAR_LINE); }
+ void nmi_w(int state) { m_bml3bus->set_nmi_line(state); }
+ void irq_w(int state) { m_bml3bus->set_irq_line(state); }
+ void firq_w(int state) { m_bml3bus->set_firq_line(state); }
- // inline configuration
- void set_bml3bus_tag(const char *tag, const char *slottag) { m_bml3bus_tag = tag; m_bml3bus_slottag = slottag; }
-
-protected:
device_bml3bus_card_interface(const machine_config &mconfig, device_t &device);
- bml3bus_device *m_bml3bus;
- const char *m_bml3bus_tag, *m_bml3bus_slottag;
+private:
+ bml3bus_device *m_bml3bus;
int m_slot;
- device_bml3bus_card_interface *m_next;
};
#endif // MAME_BUS_BML3_BML3BUS_H
diff --git a/src/devices/bus/bml3/bml3mp1805.cpp b/src/devices/bus/bml3/bml3mp1805.cpp
deleted file mode 100644
index 4ac4dc66df6..00000000000
--- a/src/devices/bus/bml3/bml3mp1805.cpp
+++ /dev/null
@@ -1,168 +0,0 @@
-// license:GPL-2.0+
-// copyright-holders:Jonathan Edwards
-/*********************************************************************
-
- bml3mp1805.c
-
- Hitachi MP-1805 floppy disk controller card for the MB-6890
- Floppy drive is attached
-
-*********************************************************************/
-
-#include "emu.h"
-#include "bml3mp1805.h"
-
-
-/***************************************************************************
- PARAMETERS
-***************************************************************************/
-
-//**************************************************************************
-// GLOBAL VARIABLES
-//**************************************************************************
-
-DEFINE_DEVICE_TYPE(BML3BUS_MP1805, bml3bus_mp1805_device, "bml3mp1805", "Hitachi MP-1805 Floppy Controller Card")
-
-static const floppy_interface bml3_mp1805_floppy_interface =
-{
- FLOPPY_STANDARD_3_SSDD,
- LEGACY_FLOPPY_OPTIONS_NAME(default),
- nullptr
-};
-
-WRITE_LINE_MEMBER( bml3bus_mp1805_device::bml3_mc6843_intrq_w )
-{
- if (state)
- {
- m_bml3bus->set_nmi_line(ASSERT_LINE);
- m_bml3bus->set_nmi_line(CLEAR_LINE);
- }
-}
-
-#define MP1805_ROM_REGION "mp1805_rom"
-
-ROM_START( mp1805 )
- ROM_REGION(0x10000, MP1805_ROM_REGION, 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_END
-
-
-/***************************************************************************
- FUNCTION PROTOTYPES
-***************************************************************************/
-
-//-------------------------------------------------
-// device_add_mconfig - add device configuration
-//-------------------------------------------------
-
-void bml3bus_mp1805_device::device_add_mconfig(machine_config &config)
-{
- MC6843(config, m_mc6843, 0);
- m_mc6843->irq().set(FUNC(bml3bus_mp1805_device::bml3_mc6843_intrq_w));
- legacy_floppy_image_device::add_4drives(config, &bml3_mp1805_floppy_interface);
-}
-
-//-------------------------------------------------
-// rom_region - device-specific ROM region
-//-------------------------------------------------
-
-const tiny_rom_entry *bml3bus_mp1805_device::device_rom_region() const
-{
- return ROM_NAME( mp1805 );
-}
-
-READ8_MEMBER( bml3bus_mp1805_device::bml3_mp1805_r)
-{
- // TODO: read supported or not?
- // return mc6843_drq_r(m_mc6843) ? 0x00 : 0x80;
- return -1;
-}
-
-WRITE8_MEMBER( bml3bus_mp1805_device::bml3_mp1805_w)
-{
- // b7 b6 b5 b4 b3 b2 b1 b0
- // MT ? ? ? D3 D2 D1 D0
- // MT: 0=motor off, 1=motor on
- // Dn: 1=select drive <n>
- int drive_select = data & 0x0f;
- int drive;
- // TODO: MESS UI for flipping disk? Note that D88 images are double-sided, but the physical drive is single-sided
- int side = 0;
- int motor = BIT(data, 7);
- const char *floppy_name = nullptr;
- switch (drive_select) {
- case 1:
- drive = 0;
- break;
- case 2:
- drive = 1;
- break;
- case 4:
- drive = 2;
- break;
- case 8:
- drive = 3;
- break;
- default:
- // TODO: what's the correct behaviour if more than one drive select bit is set? Or no bit set?
- drive = 0;
- break;
- }
- switch (drive) {
- case 0:
- floppy_name = FLOPPY_0;
- break;
- case 1:
- floppy_name = FLOPPY_1;
- break;
- case 2:
- floppy_name = FLOPPY_2;
- break;
- case 3:
- floppy_name = FLOPPY_3;
- break;
- }
- legacy_floppy_image_device *floppy = subdevice<legacy_floppy_image_device>(floppy_name);
- m_mc6843->set_drive(drive);
- floppy->floppy_mon_w(motor);
- floppy->floppy_drive_set_ready_state(ASSERT_LINE, 0);
- m_mc6843->set_side(side);
-}
-
-
-//**************************************************************************
-// LIVE DEVICE
-//**************************************************************************
-
-bml3bus_mp1805_device::bml3bus_mp1805_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) :
- device_t(mconfig, BML3BUS_MP1805, tag, owner, clock),
- device_bml3bus_card_interface(mconfig, *this),
- m_mc6843(*this, "mc6843"), m_rom(nullptr)
-{
-}
-
-
-//-------------------------------------------------
-// device_start - device-specific startup
-//-------------------------------------------------
-
-void bml3bus_mp1805_device::device_start()
-{
- // set_bml3bus_device makes m_slot valid
- set_bml3bus_device();
-
- m_rom = memregion(MP1805_ROM_REGION)->base();
-
- // install into memory
- address_space &space_prg = m_bml3bus->space();
- space_prg.install_readwrite_handler(0xff18, 0xff1f, read8_delegate( FUNC(mc6843_device::read), (mc6843_device*)m_mc6843), write8_delegate(FUNC(mc6843_device::write), (mc6843_device*)m_mc6843) );
- space_prg.install_readwrite_handler(0xff20, 0xff20, read8_delegate( FUNC(bml3bus_mp1805_device::bml3_mp1805_r), this), write8_delegate(FUNC(bml3bus_mp1805_device::bml3_mp1805_w), this) );
- // 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_mp1805_device::device_reset()
-{
-}
diff --git a/src/devices/bus/bml3/bml3kanji.cpp b/src/devices/bus/bml3/kanji.cpp
index 375dcd7becf..bfeef207720 100644
--- a/src/devices/bus/bml3/bml3kanji.cpp
+++ b/src/devices/bus/bml3/kanji.cpp
@@ -9,7 +9,7 @@
*********************************************************************/
#include "emu.h"
-#include "bml3kanji.h"
+#include "kanji.h"
/***************************************************************************
@@ -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
@@ -43,12 +41,12 @@ const tiny_rom_entry *bml3bus_kanji_device::device_rom_region() const
return ROM_NAME( kanji );
}
-READ8_MEMBER( bml3bus_kanji_device::bml3_kanji_r )
+uint8_t bml3bus_kanji_device::read(offs_t offset)
{
return m_rom[((uint32_t)m_kanji_addr << 1) + offset];
}
-WRITE8_MEMBER( bml3bus_kanji_device::bml3_kanji_w )
+void bml3bus_kanji_device::write(offs_t offset, uint8_t data)
{
m_kanji_addr &= (0xff << (offset*8));
m_kanji_addr |= (data << ((offset^1)*8));
@@ -61,7 +59,8 @@ WRITE8_MEMBER( bml3bus_kanji_device::bml3_kanji_w )
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,14 +71,13 @@ bml3bus_kanji_device::bml3bus_kanji_device(const machine_config &mconfig, const
void bml3bus_kanji_device::device_start()
{
- // set_bml3bus_device makes m_slot valid
- set_bml3bus_device();
-
- 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 = m_bml3bus->space();
- space_prg.install_readwrite_handler(0xff75, 0xff76, read8_delegate( FUNC(bml3bus_kanji_device::bml3_kanji_r), this), write8_delegate(FUNC(bml3bus_kanji_device::bml3_kanji_w), this) );
+ space.install_readwrite_handler(0xff75, 0xff76, read8sm_delegate(*this, FUNC(bml3bus_kanji_device::read)), write8sm_delegate(*this, FUNC(bml3bus_kanji_device::write)));
}
void bml3bus_kanji_device::device_reset()
diff --git a/src/devices/bus/bml3/bml3kanji.h b/src/devices/bus/bml3/kanji.h
index cee2b828c6f..3d559010a76 100644
--- a/src/devices/bus/bml3/bml3kanji.h
+++ b/src/devices/bus/bml3/kanji.h
@@ -2,14 +2,14 @@
// copyright-holders:Jonathan Edwards
/*********************************************************************
- bml3kanji.h
+ kanji.h
Hitachi MP-9740 (?) kanji character ROM for the MB-689x
*********************************************************************/
-#ifndef MAME_BUS_BML3_BML3KANJI_H
-#define MAME_BUS_BML3_BML3KANJI_H
+#ifndef MAME_BUS_BML3_KANJI_H
+#define MAME_BUS_BML3_KANJI_H
#pragma once
@@ -27,23 +27,25 @@ public:
// construction/destruction
bml3bus_kanji_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
- DECLARE_READ8_MEMBER(bml3_kanji_r);
- DECLARE_WRITE8_MEMBER(bml3_kanji_w);
+ uint8_t read(offs_t offset);
+ void write(offs_t offset, uint8_t data);
protected:
- virtual void device_start() override;
- virtual void device_reset() override;
+ virtual void device_start() override ATTR_COLD;
+ virtual void device_reset() override ATTR_COLD;
// optional information overrides
- virtual const tiny_rom_entry *device_rom_region() const override;
+ virtual const tiny_rom_entry *device_rom_region() const override ATTR_COLD;
+
+ 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
DECLARE_DEVICE_TYPE(BML3BUS_KANJI, bml3bus_kanji_device)
-#endif // MAME_BUS_BML3_BML3KANJI_H
+#endif // MAME_BUS_BML3_KANJI_H
diff --git a/src/devices/bus/bml3/bml3mp1802.cpp b/src/devices/bus/bml3/mp1802.cpp
index 85668d01f39..562a4711e6c 100644
--- a/src/devices/bus/bml3/bml3mp1802.cpp
+++ b/src/devices/bus/bml3/mp1802.cpp
@@ -10,7 +10,9 @@
*********************************************************************/
#include "emu.h"
-#include "bml3mp1802.h"
+#include "mp1802.h"
+
+#include "softlist_dev.h"
/***************************************************************************
@@ -21,28 +23,25 @@
// GLOBAL VARIABLES
//**************************************************************************
-DEFINE_DEVICE_TYPE(BML3BUS_MP1802, bml3bus_mp1802_device, "bml3mp1802", "Hitachi MP-1802 Floppy Controller Card")
+DEFINE_DEVICE_TYPE(BML3BUS_MP1802, bml3bus_mp1802_device, "bml3mp1802", "Hitachi MP-1802 5.25\" Floppy Controller Card")
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)
- {
- m_bml3bus->set_nmi_line(ASSERT_LINE);
- m_bml3bus->set_nmi_line(CLEAR_LINE);
- }
+ 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
@@ -56,13 +55,19 @@ ROM_END
void bml3bus_mp1802_device::device_add_mconfig(machine_config &config)
{
- MB8866(config, m_fdc, 1_MHz_XTAL);
- m_fdc->intrq_wr_callback().set(FUNC(bml3bus_mp1802_device::bml3_wd17xx_intrq_w));
+ 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(m_nmigate, FUNC(input_merger_device::in_w<0>));
- FLOPPY_CONNECTOR(config, m_floppy0, mp1802_floppies, "dd", floppy_image_device::default_floppy_formats);
- FLOPPY_CONNECTOR(config, m_floppy1, mp1802_floppies, "dd", floppy_image_device::default_floppy_formats);
- FLOPPY_CONNECTOR(config, m_floppy2, mp1802_floppies, "", floppy_image_device::default_floppy_formats);
- FLOPPY_CONNECTOR(config, m_floppy3, mp1802_floppies, "", floppy_image_device::default_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");
}
//-------------------------------------------------
@@ -74,30 +79,25 @@ const tiny_rom_entry *bml3bus_mp1802_device::device_rom_region() const
return ROM_NAME( mp1802 );
}
-READ8_MEMBER( bml3bus_mp1802_device::bml3_mp1802_r)
+uint8_t bml3bus_mp1802_device::read()
{
- return m_fdc->drq_r() ? 0x00 : 0x80;
+ return (m_fdc->drq_r() ? 0x00 : 0x80) | (m_fdc->intrq_r() ? 0x00 : 0x40);
}
-WRITE8_MEMBER( bml3bus_mp1802_device::bml3_mp1802_w)
+void bml3bus_mp1802_device::write(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));
}
@@ -109,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")
{
}
@@ -123,20 +122,22 @@ bml3bus_mp1802_device::bml3bus_mp1802_device(const machine_config &mconfig, cons
void bml3bus_mp1802_device::device_start()
{
- // set_bml3bus_device makes m_slot valid
- set_bml3bus_device();
+}
- m_rom = memregion(MP1802_ROM_REGION)->base();
+void bml3bus_mp1802_device::device_reset()
+{
+ write(0);
+}
- // install into memory
- address_space &space_prg = m_bml3bus->space();
- space_prg.install_readwrite_handler(0xff00, 0xff03, read8sm_delegate(FUNC(mb8866_device::read), m_fdc.target()), write8sm_delegate(FUNC(mb8866_device::write), m_fdc.target()));
- space_prg.install_readwrite_handler(0xff04, 0xff04, read8_delegate(FUNC(bml3bus_mp1802_device::bml3_mp1802_r), this), write8_delegate(FUNC(bml3bus_mp1802_device::bml3_mp1802_w), this));
- // 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::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::device_reset()
+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::read)), write8smo_delegate(*this, FUNC(bml3bus_mp1802_device::write)));
}
diff --git a/src/devices/bus/bml3/bml3mp1802.h b/src/devices/bus/bml3/mp1802.h
index 277d9ae89bd..908442a6bd7 100644
--- a/src/devices/bus/bml3/bml3mp1802.h
+++ b/src/devices/bus/bml3/mp1802.h
@@ -2,20 +2,21 @@
// copyright-holders:Jonathan Edwards
/*********************************************************************
- bml3mp1802.h
+ mp1802.h
Hitachi MP-1802 floppy disk controller card for the MB-6890
Hitachi MP-3550 floppy drive is attached
*********************************************************************/
-#ifndef MAME_BUS_BML3_BML3MP1802_H
-#define MAME_BUS_BML3_BML3MP1802_H
+#ifndef MAME_BUS_BML3_MP1802_H
+#define MAME_BUS_BML3_MP1802_H
#pragma once
#include "bml3bus.h"
#include "imagedev/floppy.h"
+#include "machine/input_merger.h"
#include "machine/wd_fdc.h"
@@ -31,30 +32,31 @@ public:
// construction/destruction
bml3bus_mp1802_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
- DECLARE_READ8_MEMBER(bml3_mp1802_r);
- DECLARE_WRITE8_MEMBER(bml3_mp1802_w);
+ uint8_t read();
+ void write(uint8_t data);
protected:
- virtual void device_start() override;
- virtual void device_reset() override;
+ virtual void device_start() override ATTR_COLD;
+ virtual void device_reset() override ATTR_COLD;
// optional information overrides
- virtual void device_add_mconfig(machine_config &config) override;
- virtual const tiny_rom_entry *device_rom_region() const override;
+ virtual void device_add_mconfig(machine_config &config) override ATTR_COLD;
+ virtual const tiny_rom_entry *device_rom_region() const override ATTR_COLD;
+
+ 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
DECLARE_DEVICE_TYPE(BML3BUS_MP1802, bml3bus_mp1802_device)
-#endif // MAME_BUS_BML3_BML3MP1802_H
+#endif // MAME_BUS_BML3_MP1802_H
diff --git a/src/devices/bus/bml3/mp1805.cpp b/src/devices/bus/bml3/mp1805.cpp
new file mode 100644
index 00000000000..b360d836044
--- /dev/null
+++ b/src/devices/bus/bml3/mp1805.cpp
@@ -0,0 +1,163 @@
+// license:GPL-2.0+
+// copyright-holders:Jonathan Edwards
+/*********************************************************************
+
+ bml3mp1805.c
+
+ Hitachi MP-1805 floppy disk controller card for the MB-6890
+ Floppy drive is attached (single-sided, single density)
+
+*********************************************************************/
+
+#include "emu.h"
+#include "mp1805.h"
+
+#include "softlist_dev.h"
+
+
+/***************************************************************************
+ PARAMETERS
+***************************************************************************/
+
+//**************************************************************************
+// GLOBAL VARIABLES
+//**************************************************************************
+
+DEFINE_DEVICE_TYPE(BML3BUS_MP1805, bml3bus_mp1805_device, "bml3mp1805", "Hitachi MP-1805 3\" Floppy Controller Card")
+
+ROM_START( mp1805 )
+ ROM_REGION(0x800, "mp1805_rom", 0)
+ // MP-1805 disk controller ROM, which replaces part of the system ROM
+ ROM_LOAD( "mp1805.rom", 0x000, 0x800, BAD_DUMP CRC(b532d8d9) SHA1(6f1160356d5bf64b5926b1fdb60db414edf65f22))
+ROM_END
+
+void bml3bus_mp1805_device::floppy_drives(device_slot_interface &device)
+{
+ device.option_add("mb_6890", FLOPPY_3_SSSD);
+}
+
+
+/***************************************************************************
+ FUNCTION PROTOTYPES
+***************************************************************************/
+
+//-------------------------------------------------
+// device_add_mconfig - add device configuration
+//-------------------------------------------------
+
+void bml3bus_mp1805_device::device_add_mconfig(machine_config &config)
+{
+ MC6843(config, m_mc6843, 500000);
+ 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);
+ FLOPPY_CONNECTOR(config, m_floppy[1], floppy_drives, nullptr, floppy_image_device::default_mfm_floppy_formats).enable_sound(true);
+ FLOPPY_CONNECTOR(config, m_floppy[2], floppy_drives, nullptr, floppy_image_device::default_mfm_floppy_formats).enable_sound(true);
+ FLOPPY_CONNECTOR(config, m_floppy[3], floppy_drives, nullptr, floppy_image_device::default_mfm_floppy_formats).enable_sound(true);
+ SOFTWARE_LIST(config, "flop_list").set_original("bml3_flop").set_filter("3");
+}
+
+//-------------------------------------------------
+// rom_region - device-specific ROM region
+//-------------------------------------------------
+
+const tiny_rom_entry *bml3bus_mp1805_device::device_rom_region() const
+{
+ return ROM_NAME( mp1805 );
+}
+
+uint8_t bml3bus_mp1805_device::read()
+{
+ // TODO: read supported or not?
+ // return mc6843_drq_r(m_mc6843) ? 0x00 : 0x80;
+ return -1;
+}
+
+void bml3bus_mp1805_device::write(uint8_t data)
+{
+ // b7 b6 b5 b4 b3 b2 b1 b0
+ // MT ? ? ? D3 D2 D1 D0
+ // MT: 0=motor off, 1=motor on
+ // Dn: 1=select drive <n>
+
+ logerror("control_w %02x\n", data);
+ u8 prev, next;
+ bool mon = BIT(data, 7);
+ floppy_image_device *fprev = nullptr, *fnext = nullptr;
+
+ if (!mon)
+ {
+ for(prev = 0; prev < 4; prev++)
+ if(BIT(m_control, prev))
+ break;
+
+ if (prev < 4)
+ {
+ fprev = m_floppy[prev]->get_device();
+ if (fprev)
+ {
+ logerror("Drive %d motor off\n",prev);
+ fprev->mon_w(1);
+ }
+ }
+ }
+ else
+ if (data & 15)
+ {
+ for(next = 0; next < 4; next++)
+ if(BIT(data, next))
+ break;
+
+ fnext = m_floppy[next]->get_device();
+ if (fnext)
+ {
+ logerror("Drive %d motor on\n",next);
+ fnext->mon_w(0);
+ }
+ }
+
+ m_control = data;
+ m_mc6843->set_floppy(fnext);
+}
+
+
+//**************************************************************************
+// LIVE DEVICE
+//**************************************************************************
+
+bml3bus_mp1805_device::bml3bus_mp1805_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) :
+ 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(*this, "mp1805_rom")
+{
+}
+
+
+//-------------------------------------------------
+// device_start - device-specific startup
+//-------------------------------------------------
+
+void bml3bus_mp1805_device::device_start()
+{
+ save_item(NAME(m_control));
+}
+
+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::read)), write8smo_delegate(*this, FUNC(bml3bus_mp1805_device::write)));
+}
diff --git a/src/devices/bus/bml3/bml3mp1805.h b/src/devices/bus/bml3/mp1805.h
index 7fd2c2f1621..c4f089eed83 100644
--- a/src/devices/bus/bml3/bml3mp1805.h
+++ b/src/devices/bus/bml3/mp1805.h
@@ -2,20 +2,20 @@
// copyright-holders:Jonathan Edwards
/*********************************************************************
- bml3mp1805.h
+ mp1805.h
Hitachi MP-1805 floppy disk controller card for the MB-6890
Floppy drive is attached
*********************************************************************/
-#ifndef MAME_BUS_BML3_BML3MP1805_H
-#define MAME_BUS_BML3_BML3MP1805_H
+#ifndef MAME_BUS_BML3_MP1805_H
+#define MAME_BUS_BML3_MP1805_H
#pragma once
#include "bml3bus.h"
-#include "imagedev/flopdrv.h"
+#include "imagedev/floppy.h"
#include "machine/mc6843.h"
//**************************************************************************
@@ -30,26 +30,32 @@ public:
// construction/destruction
bml3bus_mp1805_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
- DECLARE_READ8_MEMBER(bml3_mp1805_r);
- DECLARE_WRITE8_MEMBER(bml3_mp1805_w);
+ uint8_t read();
+ void write(uint8_t data);
protected:
- virtual void device_start() override;
- virtual void device_reset() override;
+ virtual void device_start() override ATTR_COLD;
+ virtual void device_reset() override ATTR_COLD;
// optional information overrides
- virtual void device_add_mconfig(machine_config &config) override;
- virtual const tiny_rom_entry *device_rom_region() const override;
+ virtual void device_add_mconfig(machine_config &config) override ATTR_COLD;
+ virtual const tiny_rom_entry *device_rom_region() const override ATTR_COLD;
- required_device<mc6843_device> m_mc6843;
+ virtual void map_exrom(address_space_installer &space) override;
+ virtual void map_io(address_space_installer &space) override;
private:
- DECLARE_WRITE_LINE_MEMBER( bml3_mc6843_intrq_w );
+ required_device_array<floppy_connector, 4> m_floppy;
+ required_device<mc6843_device> m_mc6843;
+
+ required_region_ptr<uint8_t> m_rom;
+
+ uint8_t m_control;
- uint8_t *m_rom;
+ static void floppy_drives(device_slot_interface &device);
};
// device type definition
DECLARE_DEVICE_TYPE(BML3BUS_MP1805, bml3bus_mp1805_device)
-#endif // MAME_BUS_BML3_BML3MP1805_H
+#endif // MAME_BUS_BML3_MP1805_H
diff --git a/src/devices/bus/bml3/rtc.cpp b/src/devices/bus/bml3/rtc.cpp
new file mode 100644
index 00000000000..eb672aaede0
--- /dev/null
+++ b/src/devices/bus/bml3/rtc.cpp
@@ -0,0 +1,109 @@
+// license:GPL-2.0+
+// copyright-holders:Russell Bull
+/*********************************************************************
+
+ bml3rtc.cpp
+
+ Hitachi RTC card for the MB-6890
+
+ I cannot find any reference to the original Hitachi board that
+ had this feature, but I was given a schematic back in the 1980's
+ and I designed a board that included the circuitry.
+ The standard ROM supported this battery-backed RTC and detects
+ it's presence on start up.
+
+*********************************************************************/
+
+#include "emu.h"
+#include "rtc.h"
+
+
+//**************************************************************************
+// DEVICE DEFINITIONS
+//**************************************************************************
+
+DEFINE_DEVICE_TYPE(BML3BUS_RTC, bml3bus_rtc_device, "bml3rtc", "Hitachi Real Time Clock Card")
+
+
+//-------------------------------------------------
+// device_add_mconfig - add device configuration
+//-------------------------------------------------
+
+void bml3bus_rtc_device::device_add_mconfig(machine_config &config)
+{
+ MSM5832(config, m_rtc, 32.768_kHz_XTAL);
+}
+
+
+uint8_t bml3bus_rtc_device::read(offs_t offset)
+{
+ uint8_t data = 0x00;
+
+ if (offset == 2) // read @ 0xff3a
+ {
+ if (BIT(m_addr_latch, 7)) //bit 7 is the !write buffer enable
+ {
+ data = m_rtc->data_r();
+ }
+ else
+ {
+ data = m_data_latch; //the Hitachi ROM code detects RTC presence by reading back what it wrote to the data latch
+ }
+ }
+ return data | 0xf0; // return low nibble only
+}
+
+void bml3bus_rtc_device::write(offs_t offset, uint8_t data)
+{
+ switch (offset)
+ {
+ case 0: // addr latch @ 0xff38
+ m_rtc->cs_w(1); //always selected
+ m_rtc->write_w(BIT(data, 6));
+ m_rtc->read_w(BIT(data, 7));
+ m_rtc->address_w(data & 0x0f);
+
+ m_addr_latch = data;
+ break;
+
+ case 1: // data latch @ 0xff39
+ m_rtc->hold_w(BIT(data, 6));
+
+ if (BIT(m_addr_latch, 6))
+ {
+ m_rtc->data_w(data & 0x0f);
+ }
+
+ m_data_latch = data;
+ break;
+ }
+}
+//**************************************************************************
+// LIVE DEVICE
+//**************************************************************************
+
+bml3bus_rtc_device::bml3bus_rtc_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
+ : device_t(mconfig, BML3BUS_RTC, tag, owner, clock)
+ , device_bml3bus_card_interface(mconfig, *this)
+ , m_rtc(*this, "rtc")
+{
+}
+
+//-------------------------------------------------
+// device_start - device-specific startup
+//-------------------------------------------------
+
+void bml3bus_rtc_device::device_start()
+{
+ 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::read)), write8sm_delegate(*this, FUNC(bml3bus_rtc_device::write)));
+}
diff --git a/src/devices/bus/bml3/rtc.h b/src/devices/bus/bml3/rtc.h
new file mode 100644
index 00000000000..cc29da7f920
--- /dev/null
+++ b/src/devices/bus/bml3/rtc.h
@@ -0,0 +1,54 @@
+// license:GPL-2.0+
+// copyright-holders:Russell Bull
+/*********************************************************************
+
+ rtc.h
+
+ Hitachi RTC card for the MB-6890
+
+*********************************************************************/
+
+#ifndef MAME_BUS_BML3_RTC_H
+#define MAME_BUS_BML3_RTC_H
+
+#pragma once
+
+#include "bml3bus.h"
+#include "machine/msm5832.h"
+
+
+//**************************************************************************
+// TYPE DEFINITIONS
+//**************************************************************************
+
+class bml3bus_rtc_device:
+ public device_t,
+ public device_bml3bus_card_interface
+{
+public:
+ // construction/destruction
+ bml3bus_rtc_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
+
+ uint8_t read(offs_t offset);
+ void write(offs_t offset, uint8_t data);
+
+protected:
+ // device-level overrides
+ virtual void device_start() override ATTR_COLD;
+
+ // optional information overrides
+ virtual void device_add_mconfig(machine_config &config) override ATTR_COLD;
+
+ virtual void map_io(address_space_installer &space) override;
+
+private:
+ required_device<msm5832_device> m_rtc;
+
+ uint8_t m_addr_latch;
+ uint8_t m_data_latch;
+};
+
+// device type definition
+DECLARE_DEVICE_TYPE(BML3BUS_RTC, bml3bus_rtc_device)
+
+#endif // MAME_BUS_BML3_RTC_H
diff --git a/src/devices/bus/bw2/exp.cpp b/src/devices/bus/bw2/exp.cpp
index 50f776b066e..030170d488c 100644
--- a/src/devices/bus/bw2/exp.cpp
+++ b/src/devices/bus/bw2/exp.cpp
@@ -27,8 +27,8 @@ DEFINE_DEVICE_TYPE(BW2_EXPANSION_SLOT, bw2_expansion_slot_device, "bw2_expansion
// device_bw2_expansion_slot_interface - constructor
//-------------------------------------------------
-device_bw2_expansion_slot_interface::device_bw2_expansion_slot_interface(const machine_config &mconfig, device_t &device)
- : device_slot_card_interface(mconfig,device)
+device_bw2_expansion_slot_interface::device_bw2_expansion_slot_interface(const machine_config &mconfig, device_t &device) :
+ device_interface(device, "bw2exp")
{
m_slot = dynamic_cast<bw2_expansion_slot_device *>(device.owner());
}
@@ -54,7 +54,8 @@ device_bw2_expansion_slot_interface::~device_bw2_expansion_slot_interface()
bw2_expansion_slot_device::bw2_expansion_slot_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) :
device_t(mconfig, BW2_EXPANSION_SLOT, tag, owner, clock),
- device_slot_interface(mconfig, *this), m_cart(nullptr)
+ device_single_card_slot_interface<device_bw2_expansion_slot_interface>(mconfig, *this),
+ m_cart(nullptr)
{
}
@@ -74,7 +75,7 @@ bw2_expansion_slot_device::~bw2_expansion_slot_device()
void bw2_expansion_slot_device::device_start()
{
- m_cart = dynamic_cast<device_bw2_expansion_slot_interface *>(get_card_device());
+ m_cart = get_card_device();
}
diff --git a/src/devices/bus/bw2/exp.h b/src/devices/bus/bw2/exp.h
index d37e5c66879..91799076ca3 100644
--- a/src/devices/bus/bw2/exp.h
+++ b/src/devices/bus/bw2/exp.h
@@ -43,13 +43,6 @@
//**************************************************************************
-// CONSTANTS
-//**************************************************************************
-
-#define BW2_EXPANSION_SLOT_TAG "exp"
-
-
-//**************************************************************************
// TYPE DEFINITIONS
//**************************************************************************
@@ -58,7 +51,7 @@
class device_bw2_expansion_slot_interface;
class bw2_expansion_slot_device : public device_t,
- public device_slot_interface
+ public device_single_card_slot_interface<device_bw2_expansion_slot_interface>
{
public:
// construction/destruction
@@ -87,8 +80,8 @@ public:
protected:
// device-level overrides
- virtual void device_start() override;
- virtual void device_reset() override;
+ virtual void device_start() override ATTR_COLD;
+ virtual void device_reset() override ATTR_COLD;
device_bw2_expansion_slot_interface *m_cart;
};
@@ -97,7 +90,7 @@ protected:
// ======================> device_bw2_expansion_slot_interface
// class representing interface-specific live bw2_expansion card
-class device_bw2_expansion_slot_interface : public device_slot_card_interface
+class device_bw2_expansion_slot_interface : public device_interface
{
public:
// construction/destruction
diff --git a/src/devices/bus/bw2/ramcard.cpp b/src/devices/bus/bw2/ramcard.cpp
index 48de6cffdec..33d1fc147d9 100644
--- a/src/devices/bus/bw2/ramcard.cpp
+++ b/src/devices/bus/bw2/ramcard.cpp
@@ -51,7 +51,7 @@ bw2_ramcard_device::bw2_ramcard_device(const machine_config &mconfig, const char
: device_t(mconfig, BW2_RAMCARD, tag, owner, clock),
device_bw2_expansion_slot_interface(mconfig, *this),
m_rom(*this, "ramcard"),
- m_ram(*this, "ram"),
+ m_ram(*this, "ram", 512*1024, ENDIANNESS_LITTLE),
m_en(0),
m_bank(0)
{
@@ -64,9 +64,6 @@ bw2_ramcard_device::bw2_ramcard_device(const machine_config &mconfig, const char
void bw2_ramcard_device::device_start()
{
- // allocate memory
- m_ram.allocate(512 * 1024);
-
// state saving
save_item(NAME(m_en));
save_item(NAME(m_bank));
@@ -90,15 +87,17 @@ void bw2_ramcard_device::device_reset()
uint8_t bw2_ramcard_device::bw2_cd_r(offs_t offset, uint8_t data, int ram2, int ram3, int ram4, int ram5, int ram6)
{
- if (!ram2)
- {
- data = m_rom->base()[offset & 0x3fff];
- }
- else if (m_en && !ram5)
+ if (offset < 0x8000)
{
- data = m_ram[(m_bank << 15) | offset];
+ if (!ram2)
+ {
+ data = m_rom->base()[offset & 0x3fff];
+ }
+ else if (m_en && !ram5)
+ {
+ data = m_ram[(m_bank << 15) | offset];
+ }
}
-
return data;
}
@@ -109,9 +108,12 @@ uint8_t bw2_ramcard_device::bw2_cd_r(offs_t offset, uint8_t data, int ram2, int
void bw2_ramcard_device::bw2_cd_w(offs_t offset, uint8_t data, int ram2, int ram3, int ram4, int ram5, int ram6)
{
- if (m_en && !ram5)
+ if (offset < 0x8000)
{
- m_ram[(m_bank << 15) | offset] = data;
+ if (m_en && !ram5)
+ {
+ m_ram[(m_bank << 15) | offset] = data;
+ }
}
}
diff --git a/src/devices/bus/bw2/ramcard.h b/src/devices/bus/bw2/ramcard.h
index 029d9b91feb..a67f79d9290 100644
--- a/src/devices/bus/bw2/ramcard.h
+++ b/src/devices/bus/bw2/ramcard.h
@@ -29,12 +29,12 @@ public:
bw2_ramcard_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 const tiny_rom_entry *device_rom_region() const override ATTR_COLD;
protected:
// device-level overrides
- virtual void device_start() override;
- virtual void device_reset() override;
+ virtual void device_start() override ATTR_COLD;
+ virtual void device_reset() override ATTR_COLD;
// device_bw2_expansion_slot_interface overrides
virtual uint8_t bw2_cd_r(offs_t offset, uint8_t data, int ram2, int ram3, int ram4, int ram5, int ram6) override;
@@ -43,7 +43,7 @@ protected:
private:
required_memory_region m_rom;
- optional_shared_ptr<uint8_t> m_ram;
+ memory_share_creator<uint8_t> m_ram;
int m_en;
uint8_t m_bank;
diff --git a/src/devices/bus/c64/16kb.h b/src/devices/bus/c64/16kb.h
index db7f294fda0..b869ab571d1 100644
--- a/src/devices/bus/c64/16kb.h
+++ b/src/devices/bus/c64/16kb.h
@@ -24,8 +24,7 @@
// ======================> c64_16kb_cartridge_device
-class c64_16kb_cartridge_device : public device_t,
- public device_c64_expansion_card_interface
+class c64_16kb_cartridge_device : public device_t, public device_c64_expansion_card_interface
{
public:
// construction/destruction
@@ -33,12 +32,12 @@ public:
protected:
// device-level overrides
- virtual void device_start() override;
- virtual void device_reset() override;
+ virtual void device_start() override ATTR_COLD;
+ virtual void device_reset() override ATTR_COLD;
// optional information overrides
- virtual void device_add_mconfig(machine_config &config) override;
- virtual ioport_constructor device_input_ports() const override;
+ virtual void device_add_mconfig(machine_config &config) override ATTR_COLD;
+ virtual ioport_constructor device_input_ports() const override ATTR_COLD;
// 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;
diff --git a/src/devices/bus/c64/4dxh.cpp b/src/devices/bus/c64/4dxh.cpp
index 4273388543b..621fb267f3e 100644
--- a/src/devices/bus/c64/4dxh.cpp
+++ b/src/devices/bus/c64/4dxh.cpp
@@ -26,20 +26,20 @@ DEFINE_DEVICE_TYPE(C64_4DXH, c64_4dxh_device, "c64_4dxh", "C64 DXH 4-Player Adap
static INPUT_PORTS_START( c64_4dxh )
PORT_START("SP2")
- PORT_BIT( 0x01, IP_ACTIVE_LOW, IPT_BUTTON1 ) PORT_PLAYER(2) PORT_WRITE_LINE_DEVICE_MEMBER(DEVICE_SELF, device_pet_user_port_interface, output_7)
+ PORT_BIT( 0x01, IP_ACTIVE_LOW, IPT_BUTTON1 ) PORT_PLAYER(2) PORT_WRITE_LINE_DEVICE_MEMBER(DEVICE_SELF, FUNC(device_pet_user_port_interface::output_7))
PORT_START("PB")
- PORT_BIT( 0x01, IP_ACTIVE_LOW, IPT_JOYSTICK_UP ) PORT_8WAY PORT_PLAYER(1) PORT_WRITE_LINE_DEVICE_MEMBER(DEVICE_SELF, device_pet_user_port_interface, output_c)
- PORT_BIT( 0x02, IP_ACTIVE_LOW, IPT_JOYSTICK_DOWN ) PORT_8WAY PORT_PLAYER(1) PORT_WRITE_LINE_DEVICE_MEMBER(DEVICE_SELF, device_pet_user_port_interface, output_d)
- PORT_BIT( 0x04, IP_ACTIVE_LOW, IPT_JOYSTICK_LEFT ) PORT_8WAY PORT_PLAYER(1) PORT_WRITE_LINE_DEVICE_MEMBER(DEVICE_SELF, device_pet_user_port_interface, output_e)
- PORT_BIT( 0x08, IP_ACTIVE_LOW, IPT_JOYSTICK_RIGHT ) PORT_8WAY PORT_PLAYER(1) PORT_WRITE_LINE_DEVICE_MEMBER(DEVICE_SELF, device_pet_user_port_interface, output_f)
- PORT_BIT( 0x10, IP_ACTIVE_LOW, IPT_JOYSTICK_UP ) PORT_8WAY PORT_PLAYER(2) PORT_WRITE_LINE_DEVICE_MEMBER(DEVICE_SELF, device_pet_user_port_interface, output_h)
- PORT_BIT( 0x20, IP_ACTIVE_LOW, IPT_JOYSTICK_DOWN ) PORT_8WAY PORT_PLAYER(2) PORT_WRITE_LINE_DEVICE_MEMBER(DEVICE_SELF, device_pet_user_port_interface, output_j)
- PORT_BIT( 0x40, IP_ACTIVE_LOW, IPT_JOYSTICK_LEFT ) PORT_8WAY PORT_PLAYER(2) PORT_WRITE_LINE_DEVICE_MEMBER(DEVICE_SELF, device_pet_user_port_interface, output_k)
- PORT_BIT( 0x80, IP_ACTIVE_LOW, IPT_JOYSTICK_RIGHT ) PORT_8WAY PORT_PLAYER(2) PORT_WRITE_LINE_DEVICE_MEMBER(DEVICE_SELF, device_pet_user_port_interface, output_l)
+ PORT_BIT( 0x01, IP_ACTIVE_LOW, IPT_JOYSTICK_UP ) PORT_8WAY PORT_PLAYER(1) PORT_WRITE_LINE_DEVICE_MEMBER(DEVICE_SELF, FUNC(device_pet_user_port_interface::output_c))
+ PORT_BIT( 0x02, IP_ACTIVE_LOW, IPT_JOYSTICK_DOWN ) PORT_8WAY PORT_PLAYER(1) PORT_WRITE_LINE_DEVICE_MEMBER(DEVICE_SELF, FUNC(device_pet_user_port_interface::output_d))
+ PORT_BIT( 0x04, IP_ACTIVE_LOW, IPT_JOYSTICK_LEFT ) PORT_8WAY PORT_PLAYER(1) PORT_WRITE_LINE_DEVICE_MEMBER(DEVICE_SELF, FUNC(device_pet_user_port_interface::output_e))
+ PORT_BIT( 0x08, IP_ACTIVE_LOW, IPT_JOYSTICK_RIGHT ) PORT_8WAY PORT_PLAYER(1) PORT_WRITE_LINE_DEVICE_MEMBER(DEVICE_SELF, FUNC(device_pet_user_port_interface::output_f))
+ PORT_BIT( 0x10, IP_ACTIVE_LOW, IPT_JOYSTICK_UP ) PORT_8WAY PORT_PLAYER(2) PORT_WRITE_LINE_DEVICE_MEMBER(DEVICE_SELF, FUNC(device_pet_user_port_interface::output_h))
+ PORT_BIT( 0x20, IP_ACTIVE_LOW, IPT_JOYSTICK_DOWN ) PORT_8WAY PORT_PLAYER(2) PORT_WRITE_LINE_DEVICE_MEMBER(DEVICE_SELF, FUNC(device_pet_user_port_interface::output_j))
+ PORT_BIT( 0x40, IP_ACTIVE_LOW, IPT_JOYSTICK_LEFT ) PORT_8WAY PORT_PLAYER(2) PORT_WRITE_LINE_DEVICE_MEMBER(DEVICE_SELF, FUNC(device_pet_user_port_interface::output_k))
+ PORT_BIT( 0x80, IP_ACTIVE_LOW, IPT_JOYSTICK_RIGHT ) PORT_8WAY PORT_PLAYER(2) PORT_WRITE_LINE_DEVICE_MEMBER(DEVICE_SELF, FUNC(device_pet_user_port_interface::output_l))
PORT_START("PA2")
- PORT_BIT( 0x10, IP_ACTIVE_LOW, IPT_BUTTON1 ) PORT_PLAYER(1) PORT_WRITE_LINE_DEVICE_MEMBER(DEVICE_SELF, device_pet_user_port_interface, output_m)
+ PORT_BIT( 0x10, IP_ACTIVE_LOW, IPT_BUTTON1 ) PORT_PLAYER(1) PORT_WRITE_LINE_DEVICE_MEMBER(DEVICE_SELF, FUNC(device_pet_user_port_interface::output_m))
INPUT_PORTS_END
diff --git a/src/devices/bus/c64/4dxh.h b/src/devices/bus/c64/4dxh.h
index 4f84231bf03..b9159758149 100644
--- a/src/devices/bus/c64/4dxh.h
+++ b/src/devices/bus/c64/4dxh.h
@@ -22,23 +22,22 @@
// ======================> c64_4dxh_device
-class c64_4dxh_device : public device_t,
- public device_pet_user_port_interface
+class c64_4dxh_device : public device_t, public device_pet_user_port_interface
{
public:
// construction/destruction
c64_4dxh_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;
+ virtual ioport_constructor device_input_ports() const override ATTR_COLD;
// 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
- virtual void device_start() override;
+ virtual void device_start() override ATTR_COLD;
};
diff --git a/src/devices/bus/c64/4ksa.cpp b/src/devices/bus/c64/4ksa.cpp
index 39a86b6b17c..80802e415f0 100644
--- a/src/devices/bus/c64/4ksa.cpp
+++ b/src/devices/bus/c64/4ksa.cpp
@@ -26,20 +26,20 @@ DEFINE_DEVICE_TYPE(C64_4KSA, c64_4ksa_device, "c64_4ksa", "C64 Kingsoft 4-Player
static INPUT_PORTS_START( c64_4ksa )
PORT_START("SP2")
- PORT_BIT( 0x01, IP_ACTIVE_LOW, IPT_BUTTON1 ) PORT_PLAYER(2) PORT_WRITE_LINE_DEVICE_MEMBER(DEVICE_SELF, device_pet_user_port_interface, output_7)
+ PORT_BIT( 0x01, IP_ACTIVE_LOW, IPT_BUTTON1 ) PORT_PLAYER(2) PORT_WRITE_LINE_DEVICE_MEMBER(DEVICE_SELF, FUNC(device_pet_user_port_interface::output_7))
PORT_START("PB")
- PORT_BIT( 0x01, IP_ACTIVE_LOW, IPT_JOYSTICK_RIGHT ) PORT_8WAY PORT_PLAYER(2) PORT_WRITE_LINE_DEVICE_MEMBER(DEVICE_SELF, device_pet_user_port_interface, output_c)
- PORT_BIT( 0x02, IP_ACTIVE_LOW, IPT_JOYSTICK_LEFT ) PORT_8WAY PORT_PLAYER(2) PORT_WRITE_LINE_DEVICE_MEMBER(DEVICE_SELF, device_pet_user_port_interface, output_d)
- PORT_BIT( 0x04, IP_ACTIVE_LOW, IPT_JOYSTICK_DOWN ) PORT_8WAY PORT_PLAYER(2) PORT_WRITE_LINE_DEVICE_MEMBER(DEVICE_SELF, device_pet_user_port_interface, output_e)
- PORT_BIT( 0x08, IP_ACTIVE_LOW, IPT_JOYSTICK_UP ) PORT_8WAY PORT_PLAYER(2) PORT_WRITE_LINE_DEVICE_MEMBER(DEVICE_SELF, device_pet_user_port_interface, output_f)
- PORT_BIT( 0x10, IP_ACTIVE_LOW, IPT_BUTTON1 ) PORT_PLAYER(1) PORT_WRITE_LINE_DEVICE_MEMBER(DEVICE_SELF, device_pet_user_port_interface, output_h)
- PORT_BIT( 0x20, IP_ACTIVE_LOW, IPT_JOYSTICK_RIGHT ) PORT_8WAY PORT_PLAYER(1) PORT_WRITE_LINE_DEVICE_MEMBER(DEVICE_SELF, device_pet_user_port_interface, output_j)
- PORT_BIT( 0x40, IP_ACTIVE_LOW, IPT_JOYSTICK_LEFT ) PORT_8WAY PORT_PLAYER(1) PORT_WRITE_LINE_DEVICE_MEMBER(DEVICE_SELF, device_pet_user_port_interface, output_k)
- PORT_BIT( 0x80, IP_ACTIVE_LOW, IPT_JOYSTICK_DOWN ) PORT_8WAY PORT_PLAYER(1) PORT_WRITE_LINE_DEVICE_MEMBER(DEVICE_SELF, device_pet_user_port_interface, output_l)
+ PORT_BIT( 0x01, IP_ACTIVE_LOW, IPT_JOYSTICK_RIGHT ) PORT_8WAY PORT_PLAYER(2) PORT_WRITE_LINE_DEVICE_MEMBER(DEVICE_SELF, FUNC(device_pet_user_port_interface::output_c))
+ PORT_BIT( 0x02, IP_ACTIVE_LOW, IPT_JOYSTICK_LEFT ) PORT_8WAY PORT_PLAYER(2) PORT_WRITE_LINE_DEVICE_MEMBER(DEVICE_SELF, FUNC(device_pet_user_port_interface::output_d))
+ PORT_BIT( 0x04, IP_ACTIVE_LOW, IPT_JOYSTICK_DOWN ) PORT_8WAY PORT_PLAYER(2) PORT_WRITE_LINE_DEVICE_MEMBER(DEVICE_SELF, FUNC(device_pet_user_port_interface::output_e))
+ PORT_BIT( 0x08, IP_ACTIVE_LOW, IPT_JOYSTICK_UP ) PORT_8WAY PORT_PLAYER(2) PORT_WRITE_LINE_DEVICE_MEMBER(DEVICE_SELF, FUNC(device_pet_user_port_interface::output_f))
+ PORT_BIT( 0x10, IP_ACTIVE_LOW, IPT_BUTTON1 ) PORT_PLAYER(1) PORT_WRITE_LINE_DEVICE_MEMBER(DEVICE_SELF, FUNC(device_pet_user_port_interface::output_h))
+ PORT_BIT( 0x20, IP_ACTIVE_LOW, IPT_JOYSTICK_RIGHT ) PORT_8WAY PORT_PLAYER(1) PORT_WRITE_LINE_DEVICE_MEMBER(DEVICE_SELF, FUNC(device_pet_user_port_interface::output_j))
+ PORT_BIT( 0x40, IP_ACTIVE_LOW, IPT_JOYSTICK_LEFT ) PORT_8WAY PORT_PLAYER(1) PORT_WRITE_LINE_DEVICE_MEMBER(DEVICE_SELF, FUNC(device_pet_user_port_interface::output_k))
+ PORT_BIT( 0x80, IP_ACTIVE_LOW, IPT_JOYSTICK_DOWN ) PORT_8WAY PORT_PLAYER(1) PORT_WRITE_LINE_DEVICE_MEMBER(DEVICE_SELF, FUNC(device_pet_user_port_interface::output_l))
PORT_START("PA2")
- PORT_BIT( 0x10, IP_ACTIVE_LOW, IPT_JOYSTICK_UP ) PORT_8WAY PORT_PLAYER(1) PORT_WRITE_LINE_DEVICE_MEMBER(DEVICE_SELF, device_pet_user_port_interface, output_m)
+ PORT_BIT( 0x10, IP_ACTIVE_LOW, IPT_JOYSTICK_UP ) PORT_8WAY PORT_PLAYER(1) PORT_WRITE_LINE_DEVICE_MEMBER(DEVICE_SELF, FUNC(device_pet_user_port_interface::output_m))
INPUT_PORTS_END
diff --git a/src/devices/bus/c64/4ksa.h b/src/devices/bus/c64/4ksa.h
index 7dc8676a6a8..610881c359d 100644
--- a/src/devices/bus/c64/4ksa.h
+++ b/src/devices/bus/c64/4ksa.h
@@ -22,23 +22,22 @@
// ======================> c64_4ksa_device
-class c64_4ksa_device : public device_t,
- public device_pet_user_port_interface
+class c64_4ksa_device : public device_t, public device_pet_user_port_interface
{
public:
// construction/destruction
c64_4ksa_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;
+ virtual ioport_constructor device_input_ports() const override ATTR_COLD;
// 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
- virtual void device_start() override;
+ virtual void device_start() override ATTR_COLD;
};
diff --git a/src/devices/bus/c64/4tba.cpp b/src/devices/bus/c64/4tba.cpp
index 4fc58cb0d49..8249a6c518a 100644
--- a/src/devices/bus/c64/4tba.cpp
+++ b/src/devices/bus/c64/4tba.cpp
@@ -26,20 +26,20 @@ DEFINE_DEVICE_TYPE(C64_4TBA, c64_4tba_device, "c64_4tba", "C64 Tie Break Adapter
static INPUT_PORTS_START( c64_4tba )
PORT_START("SP2")
- PORT_BIT( 0x01, IP_ACTIVE_LOW, IPT_BUTTON1 ) PORT_PLAYER(1) PORT_WRITE_LINE_DEVICE_MEMBER(DEVICE_SELF, device_pet_user_port_interface, output_7)
+ PORT_BIT( 0x01, IP_ACTIVE_LOW, IPT_BUTTON1 ) PORT_PLAYER(1) PORT_WRITE_LINE_DEVICE_MEMBER(DEVICE_SELF, FUNC(device_pet_user_port_interface::output_7))
PORT_START("PB")
- PORT_BIT( 0x01, IP_ACTIVE_LOW, IPT_JOYSTICK_DOWN ) PORT_8WAY PORT_PLAYER(1) PORT_WRITE_LINE_DEVICE_MEMBER(DEVICE_SELF, device_pet_user_port_interface, output_c)
- PORT_BIT( 0x02, IP_ACTIVE_LOW, IPT_JOYSTICK_RIGHT ) PORT_8WAY PORT_PLAYER(1) PORT_WRITE_LINE_DEVICE_MEMBER(DEVICE_SELF, device_pet_user_port_interface, output_d)
- PORT_BIT( 0x04, IP_ACTIVE_LOW, IPT_JOYSTICK_LEFT ) PORT_8WAY PORT_PLAYER(1) PORT_WRITE_LINE_DEVICE_MEMBER(DEVICE_SELF, device_pet_user_port_interface, output_e)
- PORT_BIT( 0x08, IP_ACTIVE_LOW, IPT_JOYSTICK_UP ) PORT_8WAY PORT_PLAYER(1) PORT_WRITE_LINE_DEVICE_MEMBER(DEVICE_SELF, device_pet_user_port_interface, output_f)
- PORT_BIT( 0x10, IP_ACTIVE_LOW, IPT_BUTTON1 ) PORT_PLAYER(2) PORT_WRITE_LINE_DEVICE_MEMBER(DEVICE_SELF, device_pet_user_port_interface, output_h)
- PORT_BIT( 0x20, IP_ACTIVE_LOW, IPT_JOYSTICK_DOWN ) PORT_8WAY PORT_PLAYER(2) PORT_WRITE_LINE_DEVICE_MEMBER(DEVICE_SELF, device_pet_user_port_interface, output_j)
- PORT_BIT( 0x40, IP_ACTIVE_LOW, IPT_JOYSTICK_RIGHT ) PORT_8WAY PORT_PLAYER(2) PORT_WRITE_LINE_DEVICE_MEMBER(DEVICE_SELF, device_pet_user_port_interface, output_k)
- PORT_BIT( 0x80, IP_ACTIVE_LOW, IPT_JOYSTICK_LEFT ) PORT_8WAY PORT_PLAYER(2) PORT_WRITE_LINE_DEVICE_MEMBER(DEVICE_SELF, device_pet_user_port_interface, output_l)
+ PORT_BIT( 0x01, IP_ACTIVE_LOW, IPT_JOYSTICK_DOWN ) PORT_8WAY PORT_PLAYER(1) PORT_WRITE_LINE_DEVICE_MEMBER(DEVICE_SELF, FUNC(device_pet_user_port_interface::output_c))
+ PORT_BIT( 0x02, IP_ACTIVE_LOW, IPT_JOYSTICK_RIGHT ) PORT_8WAY PORT_PLAYER(1) PORT_WRITE_LINE_DEVICE_MEMBER(DEVICE_SELF, FUNC(device_pet_user_port_interface::output_d))
+ PORT_BIT( 0x04, IP_ACTIVE_LOW, IPT_JOYSTICK_LEFT ) PORT_8WAY PORT_PLAYER(1) PORT_WRITE_LINE_DEVICE_MEMBER(DEVICE_SELF, FUNC(device_pet_user_port_interface::output_e))
+ PORT_BIT( 0x08, IP_ACTIVE_LOW, IPT_JOYSTICK_UP ) PORT_8WAY PORT_PLAYER(1) PORT_WRITE_LINE_DEVICE_MEMBER(DEVICE_SELF, FUNC(device_pet_user_port_interface::output_f))
+ PORT_BIT( 0x10, IP_ACTIVE_LOW, IPT_BUTTON1 ) PORT_PLAYER(2) PORT_WRITE_LINE_DEVICE_MEMBER(DEVICE_SELF, FUNC(device_pet_user_port_interface::output_h))
+ PORT_BIT( 0x20, IP_ACTIVE_LOW, IPT_JOYSTICK_DOWN ) PORT_8WAY PORT_PLAYER(2) PORT_WRITE_LINE_DEVICE_MEMBER(DEVICE_SELF, FUNC(device_pet_user_port_interface::output_j))
+ PORT_BIT( 0x40, IP_ACTIVE_LOW, IPT_JOYSTICK_RIGHT ) PORT_8WAY PORT_PLAYER(2) PORT_WRITE_LINE_DEVICE_MEMBER(DEVICE_SELF, FUNC(device_pet_user_port_interface::output_k))
+ PORT_BIT( 0x80, IP_ACTIVE_LOW, IPT_JOYSTICK_LEFT ) PORT_8WAY PORT_PLAYER(2) PORT_WRITE_LINE_DEVICE_MEMBER(DEVICE_SELF, FUNC(device_pet_user_port_interface::output_l))
PORT_START("PA2")
- PORT_BIT( 0x10, IP_ACTIVE_LOW, IPT_JOYSTICK_UP ) PORT_8WAY PORT_PLAYER(2) PORT_WRITE_LINE_DEVICE_MEMBER(DEVICE_SELF, device_pet_user_port_interface, output_m)
+ PORT_BIT( 0x10, IP_ACTIVE_LOW, IPT_JOYSTICK_UP ) PORT_8WAY PORT_PLAYER(2) PORT_WRITE_LINE_DEVICE_MEMBER(DEVICE_SELF, FUNC(device_pet_user_port_interface::output_m))
INPUT_PORTS_END
diff --git a/src/devices/bus/c64/4tba.h b/src/devices/bus/c64/4tba.h
index f96716c4839..fe5f6841b79 100644
--- a/src/devices/bus/c64/4tba.h
+++ b/src/devices/bus/c64/4tba.h
@@ -22,23 +22,22 @@
// ======================> c64_4tba_device
-class c64_4tba_device : public device_t,
- public device_pet_user_port_interface
+class c64_4tba_device : public device_t, public device_pet_user_port_interface
{
public:
// construction/destruction
c64_4tba_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;
+ virtual ioport_constructor device_input_ports() const override ATTR_COLD;
// 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
- virtual void device_start() override;
+ virtual void device_start() override ATTR_COLD;
};
diff --git a/src/devices/bus/c64/bn1541.cpp b/src/devices/bus/c64/bn1541.cpp
index dbb5fc4bb1a..ec89d07edb4 100644
--- a/src/devices/bus/c64/bn1541.cpp
+++ b/src/devices/bus/c64/bn1541.cpp
@@ -75,9 +75,9 @@ c64_bn1541_device::c64_bn1541_device(const machine_config &mconfig, const char *
void c64_bn1541_device::device_start()
{
- for (device_t &device : device_iterator(machine().root_device()))
+ for (device_t &device : device_enumerator(machine().root_device()))
{
- for (device_t &subdevice : device_iterator(device))
+ for (device_t &subdevice : device_enumerator(device))
{
if (subdevice.interface(m_other) && &subdevice != this)
{
@@ -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 1865adda460..2c1e1be4b42 100644
--- a/src/devices/bus/c64/bn1541.h
+++ b/src/devices/bus/c64/bn1541.h
@@ -42,8 +42,8 @@ protected:
// ======================> c64_bn1541_device
class c64_bn1541_device : public device_t,
- public device_pet_user_port_interface,
- public device_c64_floppy_parallel_interface
+ public device_pet_user_port_interface,
+ public device_c64_floppy_parallel_interface
{
public:
// construction/destruction
@@ -51,22 +51,22 @@ public:
protected:
// device-level overrides
- virtual void device_start() override;
+ virtual void device_start() override ATTR_COLD;
// device_c64_floppy_parallel_interface overrides
virtual void parallel_data_w(uint8_t data) override;
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 b325710a301..11402ad69ce 100644
--- a/src/devices/bus/c64/buscard.cpp
+++ b/src/devices/bus/c64/buscard.cpp
@@ -16,22 +16,10 @@
//**************************************************************************
-// MACROS/CONSTANTS
-//**************************************************************************
-
-#define I8255_TAG "u2"
-#define DS75160A_TAG "u3"
-#define DS75161A_TAG "u4"
-#define CENTRONICS_TAG "p4"
-#define EXPANSION_TAG "exp"
-
-
-
-//**************************************************************************
// DEVICE DEFINITIONS
//**************************************************************************
-DEFINE_DEVICE_TYPE(C64_BUSCARD, buscard_t, "c64_buscard", "C64 BusCard cartridge")
+DEFINE_DEVICE_TYPE(C64_BUSCARD, c64_buscard_device, "c64_buscard", "C64 BusCard cartridge")
//-------------------------------------------------
@@ -51,7 +39,7 @@ ROM_END
// rom_region - device-specific ROM region
//-------------------------------------------------
-const tiny_rom_entry *buscard_t::device_rom_region() const
+const tiny_rom_entry *c64_buscard_device::device_rom_region() const
{
return ROM_NAME( buscard );
}
@@ -93,7 +81,7 @@ INPUT_PORTS_END
// input_ports - device-specific input ports
//-------------------------------------------------
-ioport_constructor buscard_t::device_input_ports() const
+ioport_constructor c64_buscard_device::device_input_ports() const
{
return INPUT_PORTS_NAME( buscard );
}
@@ -103,13 +91,13 @@ ioport_constructor buscard_t::device_input_ports() const
// PPI interface
//-------------------------------------------------
-READ8_MEMBER( buscard_t::ppi_pa_r )
+uint8_t c64_buscard_device::ppi_pa_r()
{
uint8_t data = 0xff;
if (!m_te)
{
- data = m_ieee1->read(space, 0);
+ data = m_ieee1->read();
}
if (m_dipsw)
@@ -120,9 +108,9 @@ READ8_MEMBER( buscard_t::ppi_pa_r )
return data;
}
-WRITE8_MEMBER( buscard_t::ppi_pa_w )
+void c64_buscard_device::ppi_pa_w(uint8_t data)
{
- m_ieee1->write(space, 0, data);
+ m_ieee1->write(data);
m_centronics->write_data0(BIT(data, 0));
m_centronics->write_data1(BIT(data, 1));
@@ -134,7 +122,7 @@ WRITE8_MEMBER( buscard_t::ppi_pa_w )
m_centronics->write_data7(BIT(data, 7));
}
-WRITE8_MEMBER( buscard_t::ppi_pb_w )
+void c64_buscard_device::ppi_pb_w(uint8_t data)
{
/*
@@ -159,7 +147,7 @@ WRITE8_MEMBER( buscard_t::ppi_pb_w )
m_dipsw = BIT(data, 7);
}
-READ8_MEMBER( buscard_t::ppi_pc_r )
+uint8_t c64_buscard_device::ppi_pc_r()
{
/*
@@ -189,7 +177,7 @@ READ8_MEMBER( buscard_t::ppi_pc_r )
return data;
}
-WRITE8_MEMBER( buscard_t::ppi_pc_w )
+void c64_buscard_device::ppi_pc_w(uint8_t data)
{
/*
@@ -222,7 +210,7 @@ WRITE8_MEMBER( buscard_t::ppi_pc_w )
// Centronics interface
//-------------------------------------------------
-WRITE_LINE_MEMBER( buscard_t::busy_w )
+void c64_buscard_device::busy_w(int state)
{
m_busy = state;
}
@@ -232,15 +220,15 @@ WRITE_LINE_MEMBER( buscard_t::busy_w )
// device_add_mconfig - add device configuration
//-------------------------------------------------
-void buscard_t::device_add_mconfig(machine_config &config)
+void c64_buscard_device::device_add_mconfig(machine_config &config)
{
I8255A(config, m_ppi, 0);
- m_ppi->in_pa_callback().set(FUNC(buscard_t::ppi_pa_r));
- m_ppi->out_pa_callback().set(FUNC(buscard_t::ppi_pa_w));
+ m_ppi->in_pa_callback().set(FUNC(c64_buscard_device::ppi_pa_r));
+ m_ppi->out_pa_callback().set(FUNC(c64_buscard_device::ppi_pa_w));
m_ppi->in_pb_callback().set_constant(0xff);
- m_ppi->out_pb_callback().set(FUNC(buscard_t::ppi_pb_w));
- m_ppi->in_pc_callback().set(FUNC(buscard_t::ppi_pc_r));
- m_ppi->out_pc_callback().set(FUNC(buscard_t::ppi_pc_w));
+ m_ppi->out_pb_callback().set(FUNC(c64_buscard_device::ppi_pb_w));
+ m_ppi->in_pc_callback().set(FUNC(c64_buscard_device::ppi_pc_r));
+ m_ppi->out_pc_callback().set(FUNC(c64_buscard_device::ppi_pc_w));
DS75160A(config, m_ieee1, 0);
m_ieee1->read_callback().set(IEEE488_TAG, FUNC(ieee488_device::dio_r));
@@ -268,7 +256,7 @@ void buscard_t::device_add_mconfig(machine_config &config)
ieee488_slot_device::add_cbm_defaults(config, nullptr);
CENTRONICS(config, m_centronics, centronics_devices, nullptr);
- m_centronics->busy_handler().set(FUNC(buscard_t::busy_w));
+ m_centronics->busy_handler().set(FUNC(c64_buscard_device::busy_w));
C64_EXPANSION_SLOT(config, m_exp, DERIVED_CLOCK(1, 1), c64_expansion_cards, nullptr);
m_exp->set_passthrough();
@@ -281,18 +269,18 @@ void buscard_t::device_add_mconfig(machine_config &config)
//**************************************************************************
//-------------------------------------------------
-// buscard_t - constructor
+// c64_buscard_device - constructor
//-------------------------------------------------
-buscard_t::buscard_t(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) :
+c64_buscard_device::c64_buscard_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) :
device_t(mconfig, C64_BUSCARD, tag, owner, clock),
device_c64_expansion_card_interface(mconfig, *this),
- m_ppi(*this, I8255_TAG),
- m_ieee1(*this, DS75160A_TAG),
- m_ieee2(*this, DS75161A_TAG),
+ m_ppi(*this, "u2"),
+ m_ieee1(*this, "u3"),
+ m_ieee2(*this, "u4"),
m_bus(*this, IEEE488_TAG),
- m_centronics(*this, CENTRONICS_TAG),
- m_exp(*this, EXPANSION_TAG),
+ m_centronics(*this, "p4"),
+ m_exp(*this, "exp"),
m_s1(*this, "S1"),
m_rom(*this, "rom"),
m_te(1),
@@ -308,7 +296,7 @@ buscard_t::buscard_t(const machine_config &mconfig, const char *tag, device_t *o
// device_start - device-specific startup
//-------------------------------------------------
-void buscard_t::device_start()
+void c64_buscard_device::device_start()
{
m_ieee1->pe_w(0);
m_ieee2->dc_w(0);
@@ -326,7 +314,7 @@ void buscard_t::device_start()
// device_reset - device-specific reset
//-------------------------------------------------
-void buscard_t::device_reset()
+void c64_buscard_device::device_reset()
{
m_ppi->reset();
@@ -339,7 +327,7 @@ void buscard_t::device_reset()
// c64_cd_r - cartridge data read
//-------------------------------------------------
-uint8_t buscard_t::c64_cd_r(offs_t offset, uint8_t data, int sphi2, int ba, int roml, int romh, int io1, int io2)
+uint8_t c64_buscard_device::c64_cd_r(offs_t offset, uint8_t data, int sphi2, int ba, int roml, int romh, int io1, int io2)
{
int cs = BIT(offset, 6) && BIT(offset, 7);
@@ -376,7 +364,7 @@ uint8_t buscard_t::c64_cd_r(offs_t offset, uint8_t data, int sphi2, int ba, int
// c64_cd_w - cartridge data write
//-------------------------------------------------
-void buscard_t::c64_cd_w(offs_t offset, uint8_t data, int sphi2, int ba, int roml, int romh, int io1, int io2)
+void c64_buscard_device::c64_cd_w(offs_t offset, uint8_t data, int sphi2, int ba, int roml, int romh, int io1, int io2)
{
int cs = BIT(offset, 6) && BIT(offset, 7);
@@ -393,7 +381,7 @@ void buscard_t::c64_cd_w(offs_t offset, uint8_t data, int sphi2, int ba, int rom
// c64_game_r - cartridge GAME read
//-------------------------------------------------
-int buscard_t::c64_game_r(offs_t offset, int sphi2, int ba, int rw)
+int c64_buscard_device::c64_game_r(offs_t offset, int sphi2, int ba, int rw)
{
return pd_pgm1(offset, sphi2) & m_exp->game_r(offset, sphi2, ba, rw, m_slot->loram(), m_slot->hiram());
}
@@ -403,7 +391,7 @@ int buscard_t::c64_game_r(offs_t offset, int sphi2, int ba, int rw)
// c64_exrom_r - cartridge EXROM read
//-------------------------------------------------
-int buscard_t::c64_exrom_r(offs_t offset, int sphi2, int ba, int rw)
+int c64_buscard_device::c64_exrom_r(offs_t offset, int sphi2, int ba, int rw)
{
return (!pd_pgm1(offset, sphi2)) | m_exp->exrom_r(offset, sphi2, ba, rw, m_slot->loram(), m_slot->hiram());
}
@@ -413,7 +401,7 @@ int buscard_t::c64_exrom_r(offs_t offset, int sphi2, int ba, int rw)
// pd_pgm1 - ROM 1 enable
//-------------------------------------------------
-bool buscard_t::pd_pgm1(offs_t offset, int sphi2)
+bool c64_buscard_device::pd_pgm1(offs_t offset, int sphi2)
{
if (sphi2 && m_slot->hiram())
{
@@ -436,7 +424,7 @@ bool buscard_t::pd_pgm1(offs_t offset, int sphi2)
// pd_pgm234 - ROM 2/3/4 enable
//-------------------------------------------------
-bool buscard_t::pd_pgm234(offs_t offset, int sphi2, int bank)
+bool c64_buscard_device::pd_pgm234(offs_t offset, int sphi2, int bank)
{
return !(sphi2 && m_slot->hiram() && m_slot->loram() && offset >= 0xa000 && offset < 0xc000 && m_basic && (m_bank == bank));
}
diff --git a/src/devices/bus/c64/buscard.h b/src/devices/bus/c64/buscard.h
index 7c7324268d6..9ca22610572 100644
--- a/src/devices/bus/c64/buscard.h
+++ b/src/devices/bus/c64/buscard.h
@@ -27,22 +27,22 @@
// ======================> buscard_t
-class buscard_t : public device_t,
+class c64_buscard_device : public device_t,
public device_c64_expansion_card_interface
{
public:
// construction/destruction
- buscard_t(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
+ c64_buscard_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_start() override ATTR_COLD;
+ virtual void device_reset() override ATTR_COLD;
// optional information 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 const tiny_rom_entry *device_rom_region() const override ATTR_COLD;
+ virtual void device_add_mconfig(machine_config &config) override ATTR_COLD;
+ virtual ioport_constructor device_input_ports() const override ATTR_COLD;
// 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;
@@ -66,12 +66,12 @@ private:
bool m_dipsw;
bool m_busy;
- DECLARE_READ8_MEMBER( ppi_pa_r );
- DECLARE_WRITE8_MEMBER( ppi_pa_w );
- DECLARE_WRITE8_MEMBER( ppi_pb_w );
- DECLARE_READ8_MEMBER( ppi_pc_r );
- DECLARE_WRITE8_MEMBER( ppi_pc_w );
- DECLARE_WRITE_LINE_MEMBER( busy_w );
+ uint8_t ppi_pa_r();
+ void ppi_pa_w(uint8_t data);
+ void ppi_pb_w(uint8_t data);
+ uint8_t ppi_pc_r();
+ void ppi_pc_w(uint8_t data);
+ void busy_w(int state);
bool pd_pgm1(offs_t offset, int sphi2);
bool pd_pgm234(offs_t offset, int sphi2, int bank);
@@ -79,7 +79,7 @@ private:
// device type definition
-DECLARE_DEVICE_TYPE(C64_BUSCARD, buscard_t)
+DECLARE_DEVICE_TYPE(C64_BUSCARD, c64_buscard_device)
#endif // MAME_BUS_C64_BUSCARD_H
diff --git a/src/devices/bus/c64/buscard2.cpp b/src/devices/bus/c64/buscard2.cpp
index 20ccd254166..2546914cacc 100644
--- a/src/devices/bus/c64/buscard2.cpp
+++ b/src/devices/bus/c64/buscard2.cpp
@@ -10,27 +10,52 @@
**********************************************************************/
+/*
+
+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"
//**************************************************************************
-// MACROS/CONSTANTS
-//**************************************************************************
-
-#define R6532_TAG "riot"
-#define MC6821_TAG "pia"
-#define CENTRONICS_TAG "centronics"
-#define EXPANSION_TAG "exp"
-
-
-
-//**************************************************************************
// DEVICE DEFINITIONS
//**************************************************************************
-DEFINE_DEVICE_TYPE(C64_BUSCARD2, buscard2_t, "c64_buscard2", "C64 BusCard II cartridge")
+DEFINE_DEVICE_TYPE(C64_BUSCARD2, c64_buscard2_device, "c64_buscard2", "C64 BusCard II cartridge")
//-------------------------------------------------
@@ -41,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 )
@@ -52,7 +76,7 @@ ROM_END
// rom_region - device-specific ROM region
//-------------------------------------------------
-const tiny_rom_entry *buscard2_t::device_rom_region() const
+const tiny_rom_entry *c64_buscard2_device::device_rom_region() const
{
return ROM_NAME( buscard2 );
}
@@ -94,37 +118,27 @@ INPUT_PORTS_END
// input_ports - device-specific input ports
//-------------------------------------------------
-ioport_constructor buscard2_t::device_input_ports() const
+ioport_constructor c64_buscard2_device::device_input_ports() const
{
return INPUT_PORTS_NAME( buscard2 );
}
//-------------------------------------------------
-// Centronics interface
-//-------------------------------------------------
-
-WRITE_LINE_MEMBER( buscard2_t::busy_w )
-{
- m_busy = state;
-}
-
-
-//-------------------------------------------------
// device_add_mconfig - add device configuration
//-------------------------------------------------
-void buscard2_t::device_add_mconfig(machine_config &config)
+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);
CENTRONICS(config, m_centronics, centronics_devices, nullptr);
- m_centronics->busy_handler().set(FUNC(buscard2_t::busy_w));
+ m_centronics->busy_handler().set(FUNC(c64_buscard2_device::busy_w));
C64_EXPANSION_SLOT(config, m_exp, DERIVED_CLOCK(1, 1), c64_expansion_cards, nullptr);
m_exp->set_passthrough();
@@ -137,17 +151,17 @@ void buscard2_t::device_add_mconfig(machine_config &config)
//**************************************************************************
//-------------------------------------------------
-// buscard2_t - constructor
+// c64_buscard2_device - constructor
//-------------------------------------------------
-buscard2_t::buscard2_t(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) :
+c64_buscard2_device::c64_buscard2_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) :
device_t(mconfig, C64_BUSCARD2, tag, owner, clock),
device_c64_expansion_card_interface(mconfig, *this),
- m_riot(*this, R6532_TAG),
- m_pia(*this, MC6821_TAG),
+ m_riot(*this, "riot"),
+ m_pia(*this, "pia"),
m_bus(*this, IEEE488_TAG),
- m_centronics(*this, CENTRONICS_TAG),
- m_exp(*this, EXPANSION_TAG),
+ m_centronics(*this, "centronics"),
+ m_exp(*this, "exp"),
m_s1(*this, "S1"),
m_rom(*this, "rom"),
m_prom(*this, "prom"),
@@ -160,7 +174,7 @@ buscard2_t::buscard2_t(const machine_config &mconfig, const char *tag, device_t
// device_start - device-specific startup
//-------------------------------------------------
-void buscard2_t::device_start()
+void c64_buscard2_device::device_start()
{
// state saving
save_item(NAME(m_busy));
@@ -171,7 +185,7 @@ void buscard2_t::device_start()
// device_reset - device-specific reset
//-------------------------------------------------
-void buscard2_t::device_reset()
+void c64_buscard2_device::device_reset()
{
}
@@ -180,7 +194,7 @@ void buscard2_t::device_reset()
// c64_cd_r - cartridge data read
//-------------------------------------------------
-uint8_t buscard2_t::c64_cd_r(offs_t offset, uint8_t data, int sphi2, int ba, int roml, int romh, int io1, int io2)
+uint8_t c64_buscard2_device::c64_cd_r(offs_t offset, uint8_t data, int sphi2, int ba, int roml, int romh, int io1, int io2)
{
return m_exp->cd_r(offset, data, sphi2, ba, roml, romh, io1, io2);
}
@@ -190,7 +204,7 @@ uint8_t buscard2_t::c64_cd_r(offs_t offset, uint8_t data, int sphi2, int ba, int
// c64_cd_w - cartridge data write
//-------------------------------------------------
-void buscard2_t::c64_cd_w(offs_t offset, uint8_t data, int sphi2, int ba, int roml, int romh, int io1, int io2)
+void c64_buscard2_device::c64_cd_w(offs_t offset, uint8_t data, int sphi2, int ba, int roml, int romh, int io1, int io2)
{
m_exp->cd_w(offset, data, sphi2, ba, roml, romh, io1, io2);
}
@@ -200,7 +214,7 @@ void buscard2_t::c64_cd_w(offs_t offset, uint8_t data, int sphi2, int ba, int ro
// c64_game_r - cartridge GAME read
//-------------------------------------------------
-int buscard2_t::c64_game_r(offs_t offset, int sphi2, int ba, int rw)
+int c64_buscard2_device::c64_game_r(offs_t offset, int sphi2, int ba, int rw)
{
return m_exp->game_r(offset, sphi2, ba, rw, m_slot->loram(), m_slot->hiram());
}
@@ -210,7 +224,7 @@ int buscard2_t::c64_game_r(offs_t offset, int sphi2, int ba, int rw)
// c64_exrom_r - cartridge EXROM read
//-------------------------------------------------
-int buscard2_t::c64_exrom_r(offs_t offset, int sphi2, int ba, int rw)
+int c64_buscard2_device::c64_exrom_r(offs_t offset, int sphi2, int ba, int rw)
{
return m_exp->exrom_r(offset, sphi2, ba, rw, m_slot->loram(), m_slot->hiram());
}
diff --git a/src/devices/bus/c64/buscard2.h b/src/devices/bus/c64/buscard2.h
index 732fc299191..5506701bd00 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"
@@ -24,24 +24,24 @@
// TYPE DEFINITIONS
//**************************************************************************
-// ======================> buscard2_t
+// ======================> c64_buscard2_device
-class buscard2_t : public device_t,
- public device_c64_expansion_card_interface
+class c64_buscard2_device : public device_t,
+ public device_c64_expansion_card_interface
{
public:
// construction/destruction
- buscard2_t(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
+ c64_buscard2_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_start() override ATTR_COLD;
+ virtual void device_reset() override ATTR_COLD;
// optional information 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 const tiny_rom_entry *device_rom_region() const override ATTR_COLD;
+ virtual void device_add_mconfig(machine_config &config) override ATTR_COLD;
+ virtual ioport_constructor device_input_ports() const override ATTR_COLD;
// 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;
@@ -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,12 +61,12 @@ private:
bool m_busy;
- DECLARE_WRITE_LINE_MEMBER( busy_w );
+ void busy_w(int state) { m_busy = state; }
};
// device type definition
-DECLARE_DEVICE_TYPE(C64_BUSCARD2, buscard2_t)
+DECLARE_DEVICE_TYPE(C64_BUSCARD2, c64_buscard2_device)
#endif // MAME_BUS_C64_BUSCARD_H
diff --git a/src/devices/bus/c64/c128_comal80.h b/src/devices/bus/c64/c128_comal80.h
index fe413f9bef6..2112456f0bc 100644
--- a/src/devices/bus/c64/c128_comal80.h
+++ b/src/devices/bus/c64/c128_comal80.h
@@ -31,8 +31,8 @@ public:
protected:
// device-level overrides
- virtual void device_start() override;
- virtual void device_reset() override;
+ virtual void device_start() override ATTR_COLD;
+ virtual void device_reset() override ATTR_COLD;
// 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;
diff --git a/src/devices/bus/c64/c128_partner.cpp b/src/devices/bus/c64/c128_partner.cpp
index 91b7cf751ab..f27192a9bb5 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)
{
@@ -54,7 +54,7 @@ WRITE_LINE_MEMBER( c128_partner_cartridge_device::nmi_w )
static INPUT_PORTS_START( c128_partner )
PORT_START("NMI")
- PORT_BIT( 0x01, IP_ACTIVE_HIGH, IPT_OTHER ) PORT_NAME("Menu") PORT_CODE(KEYCODE_END) PORT_WRITE_LINE_DEVICE_MEMBER(DEVICE_SELF, c128_partner_cartridge_device, nmi_w)
+ PORT_BIT( 0x01, IP_ACTIVE_HIGH, IPT_OTHER ) PORT_NAME("Menu") PORT_CODE(KEYCODE_END) PORT_WRITE_LINE_DEVICE_MEMBER(DEVICE_SELF, FUNC(c128_partner_cartridge_device::nmi_w))
INPUT_PORTS_END
@@ -80,7 +80,8 @@ ioport_constructor c128_partner_cartridge_device::device_input_ports() const
c128_partner_cartridge_device::c128_partner_cartridge_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) :
device_t(mconfig, C128_PARTNER, tag, owner, clock),
device_c64_expansion_card_interface(mconfig, *this),
- m_ram(*this, "ram"), t_joyb2(nullptr),
+ m_ram(*this, "ram", 0x2000, ENDIANNESS_LITTLE),
+ t_joyb2(nullptr),
m_ram_a12_a7(0),
m_ls74_cd(0),
m_ls74_q1(0),
@@ -96,11 +97,8 @@ c128_partner_cartridge_device::c128_partner_cartridge_device(const machine_confi
void c128_partner_cartridge_device::device_start()
{
- // allocate memory
- m_ram.allocate(0x2000);
-
// simulate the 16.7ms pulse from CIA1 PB2 that would arrive thru the joystick port dongle
- t_joyb2 = timer_alloc();
+ t_joyb2 = timer_alloc(FUNC(c128_partner_cartridge_device::update_joyb2), this);
t_joyb2->adjust(attotime::from_msec(16), 0, attotime::from_msec(16));
// state saving
@@ -129,10 +127,10 @@ void c128_partner_cartridge_device::device_reset()
//-------------------------------------------------
-// device_timer -
+// update_joyb2 -
//-------------------------------------------------
-void c128_partner_cartridge_device::device_timer(emu_timer &timer, device_timer_id id, int param, void *ptr)
+TIMER_CALLBACK_MEMBER(c128_partner_cartridge_device::update_joyb2)
{
if (m_ls74_cd)
{
diff --git a/src/devices/bus/c64/c128_partner.h b/src/devices/bus/c64/c128_partner.h
index 1f4402d5b22..aaaba1a3b42 100644
--- a/src/devices/bus/c64/c128_partner.h
+++ b/src/devices/bus/c64/c128_partner.h
@@ -31,15 +31,14 @@ public:
c128_partner_cartridge_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;
+ virtual ioport_constructor device_input_ports() const override ATTR_COLD;
- DECLARE_WRITE_LINE_MEMBER( nmi_w );
+ void nmi_w(int state);
protected:
// device-level overrides
- virtual void device_start() override;
- virtual void device_reset() override;
- virtual void device_timer(emu_timer &timer, device_timer_id id, int param, void *ptr) override;
+ virtual void device_start() override ATTR_COLD;
+ virtual void device_reset() override ATTR_COLD;
// 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;
@@ -48,8 +47,10 @@ protected:
// device_vcs_control_port_interface overrides
virtual void vcs_joy_w(uint8_t data);
+ TIMER_CALLBACK_MEMBER(update_joyb2);
+
private:
- optional_shared_ptr<uint8_t> m_ram;
+ memory_share_creator<uint8_t> m_ram;
emu_timer *t_joyb2;
int m_ram_a12_a7;
diff --git a/src/devices/bus/c64/comal80.h b/src/devices/bus/c64/comal80.h
index af0958a8940..4b5e279dd18 100644
--- a/src/devices/bus/c64/comal80.h
+++ b/src/devices/bus/c64/comal80.h
@@ -31,8 +31,8 @@ public:
protected:
// device-level overrides
- virtual void device_start() override;
- virtual void device_reset() override;
+ virtual void device_start() override ATTR_COLD;
+ virtual void device_reset() override ATTR_COLD;
// 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;
diff --git a/src/devices/bus/c64/cpm.cpp b/src/devices/bus/c64/cpm.cpp
index 7a909f6e920..f60fe8bd506 100644
--- a/src/devices/bus/c64/cpm.cpp
+++ b/src/devices/bus/c64/cpm.cpp
@@ -122,8 +122,8 @@ inline void c64_cpm_cartridge_device::update_signals()
// c64_cpm_cartridge_device - constructor
//-------------------------------------------------
-c64_cpm_cartridge_device::c64_cpm_cartridge_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) :
- device_t(mconfig, C64_CPM, tag, owner, clock),
+c64_cpm_cartridge_device::c64_cpm_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_c64_expansion_card_interface(mconfig, *this),
m_maincpu(*this, Z80_TAG),
m_enabled(0),
@@ -131,6 +131,10 @@ c64_cpm_cartridge_device::c64_cpm_cartridge_device(const machine_config &mconfig
{
}
+c64_cpm_cartridge_device::c64_cpm_cartridge_device(const machine_config& mconfig, const char *tag, device_t *owner, uint32_t clock) :
+ c64_cpm_cartridge_device(mconfig, C64_CPM, tag, owner, clock)
+{
+}
//-------------------------------------------------
// device_start - device-specific startup
@@ -193,7 +197,7 @@ int c64_cpm_cartridge_device::c64_game_r(offs_t offset, int sphi2, int ba, int r
// dma_r -
//-------------------------------------------------
-READ8_MEMBER( c64_cpm_cartridge_device::dma_r )
+uint8_t c64_cpm_cartridge_device::dma_r(offs_t offset)
{
uint8_t data = 0xff;
@@ -212,7 +216,7 @@ READ8_MEMBER( c64_cpm_cartridge_device::dma_r )
// dma_w -
//-------------------------------------------------
-WRITE8_MEMBER( c64_cpm_cartridge_device::dma_w )
+void c64_cpm_cartridge_device::dma_w(offs_t offset, uint8_t data)
{
if (m_enabled)
{
diff --git a/src/devices/bus/c64/cpm.h b/src/devices/bus/c64/cpm.h
index 63d3a7123cd..efc7a2e2caf 100644
--- a/src/devices/bus/c64/cpm.h
+++ b/src/devices/bus/c64/cpm.h
@@ -30,12 +30,14 @@ public:
c64_cpm_cartridge_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
protected:
+ c64_cpm_cartridge_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_start() override ATTR_COLD;
+ virtual void device_reset() override ATTR_COLD;
// optional information overrides
- virtual void device_add_mconfig(machine_config &config) override;
+ virtual void device_add_mconfig(machine_config &config) override ATTR_COLD;
// device_c64_expansion_card_interface overrides
virtual void c64_cd_w(offs_t offset, uint8_t data, int sphi2, int ba, int roml, int romh, int io1, int io2) override;
@@ -51,11 +53,11 @@ private:
int m_reset;
- DECLARE_READ8_MEMBER( dma_r );
- DECLARE_WRITE8_MEMBER( dma_w );
+ uint8_t dma_r(offs_t offset);
+ void dma_w(offs_t offset, uint8_t data);
- void z80_io(address_map &map);
- void z80_mem(address_map &map);
+ void z80_io(address_map &map) ATTR_COLD;
+ void z80_mem(address_map &map) ATTR_COLD;
};
diff --git a/src/devices/bus/c64/currah_speech.cpp b/src/devices/bus/c64/currah_speech.cpp
index 2ce77f2ea04..0216e4c4ef5 100644
--- a/src/devices/bus/c64/currah_speech.cpp
+++ b/src/devices/bus/c64/currah_speech.cpp
@@ -76,7 +76,7 @@ Notes:
// DEVICE DEFINITIONS
//**************************************************************************
-DEFINE_DEVICE_TYPE(C64_CURRAH_SPEECH, c64_currah_speech_cartridge_device, "c64_cs", "C64 Currah Speech")
+DEFINE_DEVICE_TYPE(C64_CURRAH_SPEECH, c64_currah_speech_cartridge_device, "c64_cspeech", "C64 Currah Speech")
//-------------------------------------------------
diff --git a/src/devices/bus/c64/currah_speech.h b/src/devices/bus/c64/currah_speech.h
index f856833f659..8998f54aa87 100644
--- a/src/devices/bus/c64/currah_speech.h
+++ b/src/devices/bus/c64/currah_speech.h
@@ -32,12 +32,12 @@ public:
protected:
// device-level overrides
- virtual void device_start() override;
- virtual void device_reset() override;
+ virtual void device_start() override ATTR_COLD;
+ virtual void device_reset() override ATTR_COLD;
// optional information overrides
- virtual const tiny_rom_entry *device_rom_region() const override;
- virtual void device_add_mconfig(machine_config &config) override;
+ virtual const tiny_rom_entry *device_rom_region() const override ATTR_COLD;
+ virtual void device_add_mconfig(machine_config &config) override ATTR_COLD;
// 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;
diff --git a/src/devices/bus/c64/dela_ep256.cpp b/src/devices/bus/c64/dela_ep256.cpp
index 107f2828d21..d5052f914b2 100644
--- a/src/devices/bus/c64/dela_ep256.cpp
+++ b/src/devices/bus/c64/dela_ep256.cpp
@@ -15,7 +15,7 @@
// DEVICE DEFINITIONS
//**************************************************************************
-DEFINE_DEVICE_TYPE(C64_DELA_EP256, c64_dela_ep256_cartridge_device, "delep256", "C64 Dela 256KB EPROM cartridge")
+DEFINE_DEVICE_TYPE(C64_DELA_EP256, c64_dela_ep256_cartridge_device, "c64_dela_ep256", "C64 Dela 256KB EPROM cartridge")
//-------------------------------------------------
@@ -24,14 +24,8 @@ DEFINE_DEVICE_TYPE(C64_DELA_EP256, c64_dela_ep256_cartridge_device, "delep256",
void c64_dela_ep256_cartridge_device::device_add_mconfig(machine_config &config)
{
- GENERIC_SOCKET(config, "rom1", generic_linear_slot, nullptr, "bin,rom");
- GENERIC_SOCKET(config, "rom2", generic_linear_slot, nullptr, "bin,rom");
- GENERIC_SOCKET(config, "rom3", generic_linear_slot, nullptr, "bin,rom");
- GENERIC_SOCKET(config, "rom4", generic_linear_slot, nullptr, "bin,rom");
- GENERIC_SOCKET(config, "rom5", generic_linear_slot, nullptr, "bin,rom");
- GENERIC_SOCKET(config, "rom6", generic_linear_slot, nullptr, "bin,rom");
- GENERIC_SOCKET(config, "rom7", generic_linear_slot, nullptr, "bin,rom");
- GENERIC_SOCKET(config, "rom8", generic_linear_slot, nullptr, "bin,rom");
+ for (auto &rom : m_eproms)
+ GENERIC_SOCKET(config, rom, generic_linear_slot, nullptr, "bin,rom");
}
@@ -46,14 +40,9 @@ void c64_dela_ep256_cartridge_device::device_add_mconfig(machine_config &config)
c64_dela_ep256_cartridge_device::c64_dela_ep256_cartridge_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) :
device_t(mconfig, C64_DELA_EP256, tag, owner, clock),
- device_c64_expansion_card_interface(mconfig, *this)
+ device_c64_expansion_card_interface(mconfig, *this),
+ m_eproms(*this, "rom%u", 1U)
{
- for (int i = 0; i < 8; i++)
- {
- char str[6];
- sprintf(str, "rom%i", i + 1);
- m_eproms[i] = subdevice<generic_slot_device>(str);
- }
}
diff --git a/src/devices/bus/c64/dela_ep256.h b/src/devices/bus/c64/dela_ep256.h
index 61501df0790..ba0923325a3 100644
--- a/src/devices/bus/c64/dela_ep256.h
+++ b/src/devices/bus/c64/dela_ep256.h
@@ -33,18 +33,18 @@ public:
protected:
// device-level overrides
- virtual void device_start() override;
- virtual void device_reset() override;
+ virtual void device_start() override ATTR_COLD;
+ virtual void device_reset() override ATTR_COLD;
// optional information overrides
- virtual void device_add_mconfig(machine_config &config) override;
+ virtual void device_add_mconfig(machine_config &config) override ATTR_COLD;
// 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:
- generic_slot_device *m_eproms[8];
+ required_device_array<generic_slot_device, 8> m_eproms;
uint8_t m_bank, m_socket;
int m_reset;
diff --git a/src/devices/bus/c64/dela_ep64.h b/src/devices/bus/c64/dela_ep64.h
index 95ac3440871..b366faa736a 100644
--- a/src/devices/bus/c64/dela_ep64.h
+++ b/src/devices/bus/c64/dela_ep64.h
@@ -33,11 +33,11 @@ public:
protected:
// device-level overrides
- virtual void device_start() override;
- virtual void device_reset() override;
+ virtual void device_start() override ATTR_COLD;
+ virtual void device_reset() override ATTR_COLD;
// optional information overrides
- virtual void device_add_mconfig(machine_config &config) override;
+ virtual void device_add_mconfig(machine_config &config) override ATTR_COLD;
// 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;
diff --git a/src/devices/bus/c64/dela_ep7x8.h b/src/devices/bus/c64/dela_ep7x8.h
index 50e1b3af01e..6bbf1f5d77f 100644
--- a/src/devices/bus/c64/dela_ep7x8.h
+++ b/src/devices/bus/c64/dela_ep7x8.h
@@ -33,11 +33,11 @@ public:
protected:
// device-level overrides
- virtual void device_start() override;
- virtual void device_reset() override;
+ virtual void device_start() override ATTR_COLD;
+ virtual void device_reset() override ATTR_COLD;
// optional information overrides
- virtual void device_add_mconfig(machine_config &config) override;
+ virtual void device_add_mconfig(machine_config &config) override ATTR_COLD;
// 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;
diff --git a/src/devices/bus/c64/dinamic.h b/src/devices/bus/c64/dinamic.h
index e204964e4a1..dbee705afe5 100644
--- a/src/devices/bus/c64/dinamic.h
+++ b/src/devices/bus/c64/dinamic.h
@@ -31,8 +31,8 @@ public:
protected:
// device-level overrides
- virtual void device_start() override;
- virtual void device_reset() override;
+ virtual void device_start() override ATTR_COLD;
+ virtual void device_reset() override ATTR_COLD;
// 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;
diff --git a/src/devices/bus/c64/dqbb.cpp b/src/devices/bus/c64/dqbb.cpp
index 20adedd9057..e4d50057537 100644
--- a/src/devices/bus/c64/dqbb.cpp
+++ b/src/devices/bus/c64/dqbb.cpp
@@ -53,7 +53,8 @@ c64_dqbb_cartridge_device::c64_dqbb_cartridge_device(const machine_config &mconf
void c64_dqbb_cartridge_device::device_start()
{
// allocate memory
- m_nvram.allocate(0x4000);
+ m_nvram = std::make_unique<uint8_t[]>(0x4000);
+ save_pointer(NAME(m_nvram), 0x4000);
// state saving
save_item(NAME(m_cs));
@@ -74,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 aaa8c0e1bf4..15ed32f833e 100644
--- a/src/devices/bus/c64/dqbb.h
+++ b/src/devices/bus/c64/dqbb.h
@@ -13,7 +13,6 @@
#include "exp.h"
-#include "machine/nvram.h"
@@ -32,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
- virtual void device_start() override;
- virtual void device_reset() override;
+ // device_t implementation
+ virtual void device_start() override ATTR_COLD;
+ virtual void device_reset() override ATTR_COLD;
- // device_nvram_interface overrides
- virtual void nvram_default() override { }
- virtual void nvram_read(emu_file &file) override { if (m_nvram != nullptr) { file.read(m_nvram, m_nvram.bytes()); } }
- virtual void nvram_write(emu_file &file) override { if (m_nvram != nullptr) { file.write(m_nvram, 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_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/easy_calc_result.h b/src/devices/bus/c64/easy_calc_result.h
index 2d945b7dea2..9121a7750a7 100644
--- a/src/devices/bus/c64/easy_calc_result.h
+++ b/src/devices/bus/c64/easy_calc_result.h
@@ -31,8 +31,8 @@ public:
protected:
// device-level overrides
- virtual void device_start() override;
- virtual void device_reset() override;
+ virtual void device_start() override ATTR_COLD;
+ virtual void device_reset() override ATTR_COLD;
// 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;
diff --git a/src/devices/bus/c64/easyflash.cpp b/src/devices/bus/c64/easyflash.cpp
index 38cdf9739c6..b011b489d03 100644
--- a/src/devices/bus/c64/easyflash.cpp
+++ b/src/devices/bus/c64/easyflash.cpp
@@ -48,7 +48,7 @@ static INPUT_PORTS_START( c64_easyflash )
PORT_DIPSETTING( 0x01, "Boot" )
PORT_START("RESET")
- PORT_BIT( 0x01, IP_ACTIVE_HIGH, IPT_OTHER ) PORT_NAME("Reset") PORT_CODE(KEYCODE_F11) PORT_WRITE_LINE_DEVICE_MEMBER(DEVICE_SELF_OWNER, c64_expansion_slot_device, reset_w)
+ PORT_BIT( 0x01, IP_ACTIVE_HIGH, IPT_OTHER ) PORT_NAME("Reset") PORT_CODE(KEYCODE_F11) PORT_WRITE_LINE_DEVICE_MEMBER(DEVICE_SELF_OWNER, FUNC(c64_expansion_slot_device::reset_w))
INPUT_PORTS_END
@@ -77,7 +77,7 @@ c64_easyflash_cartridge_device::c64_easyflash_cartridge_device(const machine_con
m_flash_roml(*this, AM29F040_0_TAG),
m_flash_romh(*this, AM29F040_1_TAG),
m_jp1(*this, "JP1"),
- m_ram(*this, "ram"),
+ m_ram(*this, "ram", 0x100, ENDIANNESS_LITTLE),
m_bank(0),
m_mode(0)
{
@@ -90,9 +90,6 @@ c64_easyflash_cartridge_device::c64_easyflash_cartridge_device(const machine_con
void c64_easyflash_cartridge_device::device_start()
{
- // allocate memory
- m_ram.allocate(0x100);
-
// state saving
save_item(NAME(m_bank));
save_item(NAME(m_mode));
diff --git a/src/devices/bus/c64/easyflash.h b/src/devices/bus/c64/easyflash.h
index 377de25d50d..42f25076c85 100644
--- a/src/devices/bus/c64/easyflash.h
+++ b/src/devices/bus/c64/easyflash.h
@@ -32,12 +32,12 @@ public:
protected:
// device-level overrides
- virtual void device_start() override;
- virtual void device_reset() override;
+ virtual void device_start() override ATTR_COLD;
+ virtual void device_reset() override ATTR_COLD;
// optional information overrides
- virtual void device_add_mconfig(machine_config &config) override;
- virtual ioport_constructor device_input_ports() const override;
+ virtual void device_add_mconfig(machine_config &config) override ATTR_COLD;
+ virtual ioport_constructor device_input_ports() const override ATTR_COLD;
// 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;
@@ -49,7 +49,7 @@ private:
required_device<amd_29f040_device> m_flash_roml;
required_device<amd_29f040_device> m_flash_romh;
required_ioport m_jp1;
- optional_shared_ptr<uint8_t> m_ram;
+ memory_share_creator<uint8_t> m_ram;
uint8_t m_bank;
uint8_t m_mode;
diff --git a/src/devices/bus/c64/epyx_fast_load.cpp b/src/devices/bus/c64/epyx_fast_load.cpp
index 4dced91c76a..21352ddef63 100644
--- a/src/devices/bus/c64/epyx_fast_load.cpp
+++ b/src/devices/bus/c64/epyx_fast_load.cpp
@@ -51,7 +51,7 @@ c64_epyx_fast_load_cartridge_device::c64_epyx_fast_load_cartridge_device(const m
void c64_epyx_fast_load_cartridge_device::device_start()
{
// allocate timer
- m_exrom_timer = timer_alloc();
+ m_exrom_timer = timer_alloc(FUNC(c64_epyx_fast_load_cartridge_device::update_exrom), this);
}
@@ -67,10 +67,10 @@ void c64_epyx_fast_load_cartridge_device::device_reset()
//-------------------------------------------------
-// device_timer - handler timer events
+// update_exrom - update exrom flag
//-------------------------------------------------
-void c64_epyx_fast_load_cartridge_device::device_timer(emu_timer &timer, device_timer_id id, int param, void *ptr)
+TIMER_CALLBACK_MEMBER(c64_epyx_fast_load_cartridge_device::update_exrom)
{
m_exrom = 1;
}
diff --git a/src/devices/bus/c64/epyx_fast_load.h b/src/devices/bus/c64/epyx_fast_load.h
index 64d23f6febb..3719b8ae647 100644
--- a/src/devices/bus/c64/epyx_fast_load.h
+++ b/src/devices/bus/c64/epyx_fast_load.h
@@ -31,14 +31,15 @@ public:
protected:
// device-level overrides
- virtual void device_start() override;
- virtual void device_reset() override;
- virtual void device_timer(emu_timer &timer, device_timer_id id, int param, void *ptr) override;
+ virtual void device_start() override ATTR_COLD;
+ virtual void device_reset() override ATTR_COLD;
// 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;
+ TIMER_CALLBACK_MEMBER(update_exrom);
+
private:
emu_timer *m_exrom_timer;
};
diff --git a/src/devices/bus/c64/exos.h b/src/devices/bus/c64/exos.h
index 73b9b2699aa..1c79a333df4 100644
--- a/src/devices/bus/c64/exos.h
+++ b/src/devices/bus/c64/exos.h
@@ -31,7 +31,7 @@ public:
protected:
// device-level overrides
- virtual void device_start() override;
+ virtual void device_start() override ATTR_COLD;
// 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;
diff --git a/src/devices/bus/c64/exp.cpp b/src/devices/bus/c64/exp.cpp
index 2a996728adf..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>
+
//**************************************************************************
@@ -28,11 +32,9 @@ DEFINE_DEVICE_TYPE(C64_EXPANSION_SLOT, c64_expansion_slot_device, "c64_expansion
//-------------------------------------------------
device_c64_expansion_card_interface::device_c64_expansion_card_interface(const machine_config &mconfig, device_t &device) :
- device_slot_card_interface(mconfig, device),
- m_roml(*this, "roml"),
- m_romh(*this, "romh"),
- m_romx(*this, "romx"),
- m_nvram(*this, "nvram"),
+ device_interface(device, "c64exp"),
+ m_roml_size(0),
+ m_romh_size(0),
m_game(1),
m_exrom(1)
{
@@ -60,9 +62,9 @@ device_c64_expansion_card_interface::~device_c64_expansion_card_interface()
c64_expansion_slot_device::c64_expansion_slot_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) :
device_t(mconfig, C64_EXPANSION_SLOT, tag, owner, clock),
- device_slot_interface(mconfig, *this),
- device_image_interface(mconfig, *this),
- m_read_dma_cd(*this),
+ device_single_card_slot_interface<device_c64_expansion_card_interface>(mconfig, *this),
+ device_cartrom_image_interface(mconfig, *this),
+ m_read_dma_cd(*this, 0),
m_write_dma_cd(*this),
m_write_irq(*this),
m_write_nmi(*this),
@@ -73,35 +75,12 @@ c64_expansion_slot_device::c64_expansion_slot_device(const machine_config &mconf
//-------------------------------------------------
-// device_validity_check -
-//-------------------------------------------------
-
-void c64_expansion_slot_device::device_validity_check(validity_checker &valid) const
-{
- device_t *const carddev = get_card_device();
- if (carddev && !dynamic_cast<device_c64_expansion_card_interface *>(carddev))
- osd_printf_error("Card device %s (%s) does not implement device_c64_expansion_card_interface\n", carddev->tag(), carddev->name());
-}
-
-
-//-------------------------------------------------
// device_start - device-specific startup
//-------------------------------------------------
void c64_expansion_slot_device::device_start()
{
- device_t *const carddev = get_card_device();
- m_card = dynamic_cast<device_c64_expansion_card_interface *>(carddev);
- if (carddev && !m_card)
- fatalerror("Card device %s (%s) does not implement device_c64_expansion_card_interface\n", carddev->tag(), carddev->name());
-
- // 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();
+ m_card = get_card_device();
}
@@ -118,20 +97,33 @@ 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;
+ m_card->m_romh_size = 0;
+ m_card->m_exrom = 1;
+ m_card->m_game = 1;
+
size_t size;
if (!loaded_through_softlist())
{
+ util::core_file &file = image_core_file();
size = length();
if (is_filetype("80"))
{
- fread(m_card->m_roml, size);
- m_card->m_exrom = (0);
+ 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;
if (size == 0x4000)
{
@@ -140,40 +132,46 @@ 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;
m_card->m_game = 0;
}
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"))
{
- size_t roml_size = 0;
- size_t romh_size = 0;
- 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, &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;
- m_card->m_roml.allocate(roml_size);
- m_card->m_romh.allocate(romh_size);
+ m_card->m_roml = std::make_unique<uint8_t[]>(m_card->m_roml_size);
+ m_card->m_romh = std::make_unique<uint8_t[]>(m_card->m_romh_size);
- if (roml_size) roml = m_card->m_roml;
- if (romh_size) romh = m_card->m_roml;
+ 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);
}
-
- m_card->m_exrom = exrom;
- m_card->m_game = game;
+ }
+ else
+ {
+ err = image_error::INVALIDIMAGE;
}
}
else
@@ -185,6 +183,8 @@ image_init_result c64_expansion_slot_device::call_load()
// Ultimax (VIC-10) cartridge
load_software_region("lorom", m_card->m_roml);
load_software_region("uprom", m_card->m_romh);
+ m_card->m_roml_size = get_software_region_length("lorom");
+ m_card->m_romh_size = get_software_region_length("uprom");
m_card->m_exrom = 1;
m_card->m_game = 0;
@@ -196,14 +196,19 @@ image_init_result c64_expansion_slot_device::call_load()
load_software_region("romh", m_card->m_romh);
load_software_region("romx", m_card->m_romx);
load_software_region("nvram", m_card->m_nvram);
+ m_card->m_roml_size = get_software_region_length("roml");
+ m_card->m_romh_size = get_software_region_length("romh");
if (get_feature("exrom") != nullptr) m_card->m_exrom = atol(get_feature("exrom"));
if (get_feature("game") != nullptr) m_card->m_game = atol(get_feature("game"));
}
}
+
+ if ((m_card->m_roml_size & (m_card->m_roml_size - 1)) || (m_card->m_romh_size & (m_card->m_romh_size - 1)))
+ 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());
}
@@ -367,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"
@@ -375,6 +381,7 @@ void c64_expansion_slot_device::set_passthrough()
#include "westermann.h"
#include "xl80.h"
#include "zaxxon.h"
+#include "z80videopak.h"
void c64_expansion_cards(device_slot_interface &device)
{
@@ -398,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);
@@ -450,4 +458,5 @@ void c64_expansion_cards(device_slot_interface &device)
device.option_add_internal("westermann", C64_WESTERMANN);
device.option_add_internal("zaxxon", C64_ZAXXON);
device.option_add_internal("xl80", C64_XL80);
+ device.option_add_internal("z80videopak", C64_Z80VIDEOPAK);
}
diff --git a/src/devices/bus/c64/exp.h b/src/devices/bus/c64/exp.h
index 8a719688b4e..a775b9529d6 100644
--- a/src/devices/bus/c64/exp.h
+++ b/src/devices/bus/c64/exp.h
@@ -36,8 +36,7 @@
#pragma once
-#include "softlist_dev.h"
-#include "formats/cbm_crt.h"
+#include "imagedev/cartrom.h"
@@ -50,8 +49,8 @@
class device_c64_expansion_card_interface;
class c64_expansion_slot_device : public device_t,
- public device_slot_interface,
- public device_image_interface
+ public device_single_card_slot_interface<device_c64_expansion_card_interface>,
+ public device_cartrom_image_interface
{
public:
// construction/destruction
@@ -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,26 +94,18 @@ public:
void set_passthrough();
protected:
- // device-level overrides
- virtual void device_validity_check(validity_checker &valid) const override;
- virtual void device_start() override;
- virtual void device_reset() override;
-
- // image-level overrides
- virtual image_init_result call_load() override;
- virtual const software_list_loader &get_software_list_loader() const override { return rom_software_list_loader::instance(); }
-
- virtual iodevice_t image_type() const override { return IO_CARTSLOT; }
-
- virtual bool is_readable() const override { return 1; }
- virtual bool is_writeable() const override { return 0; }
- virtual bool is_creatable() const override { return 0; }
- virtual bool must_be_loaded() const override { return 0; }
- virtual bool is_reset_on_load() const override { return 1; }
- virtual const char *image_interface() const override { return "c64_cart,vic10_cart"; }
- virtual const char *file_extensions() const override { return "80,a0,e0,crt"; }
-
- // slot interface overrides
+ // device_t implementation
+ virtual void device_start() override ATTR_COLD;
+ virtual void device_reset() override ATTR_COLD;
+
+ // 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"; }
+
+ // 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;
@@ -133,7 +124,7 @@ protected:
// ======================> device_c64_expansion_card_interface
-class device_c64_expansion_card_interface : public device_slot_card_interface
+class device_c64_expansion_card_interface : public device_interface
{
friend class c64_expansion_slot_device;
@@ -141,18 +132,21 @@ public:
// construction/destruction
virtual ~device_c64_expansion_card_interface();
- virtual uint8_t c64_cd_r(offs_t offset, uint8_t data, int sphi2, int ba, int roml, int romh, int io1, int io2) { return data; };
- virtual void c64_cd_w(offs_t offset, uint8_t data, int sphi2, int ba, int roml, int romh, int io1, int io2) { };
+ virtual uint8_t c64_cd_r(offs_t offset, uint8_t data, int sphi2, int ba, int roml, int romh, int io1, int io2) { return data; }
+ virtual void c64_cd_w(offs_t offset, uint8_t data, int sphi2, int ba, int roml, int romh, int io1, int io2) { }
virtual int c64_game_r(offs_t offset, int sphi2, int ba, int rw) { return m_game; }
virtual int c64_exrom_r(offs_t offset, int sphi2, int ba, int rw) { return m_exrom; }
protected:
device_c64_expansion_card_interface(const machine_config &mconfig, device_t &device);
- optional_shared_ptr<uint8_t> m_roml;
- optional_shared_ptr<uint8_t> m_romh;
- optional_shared_ptr<uint8_t> m_romx;
- optional_shared_ptr<uint8_t> m_nvram;
+ std::unique_ptr<uint8_t[]> m_roml;
+ std::unique_ptr<uint8_t[]> m_romh;
+ std::unique_ptr<uint8_t[]> m_romx;
+ std::unique_ptr<uint8_t[]> m_nvram;
+
+ size_t m_roml_size;
+ size_t m_romh_size;
int m_game;
int m_exrom;
diff --git a/src/devices/bus/c64/fcc.cpp b/src/devices/bus/c64/fcc.cpp
index dc1668c0eab..96b0c172c12 100644
--- a/src/devices/bus/c64/fcc.cpp
+++ b/src/devices/bus/c64/fcc.cpp
@@ -42,11 +42,9 @@ void c64_final_chesscard_device::c64_fcc_map(address_map &map)
void c64_final_chesscard_device::device_add_mconfig(machine_config &config)
{
- M65SC02(config, m_maincpu, 5_MHz_XTAL);
+ G65SC02(config, m_maincpu, 5_MHz_XTAL);
m_maincpu->set_addrmap(AS_PROGRAM, &c64_final_chesscard_device::c64_fcc_map);
- config.m_perfect_cpu_quantum = subtag("maincpu");
-
GENERIC_LATCH_8(config, m_mainlatch).data_pending_callback().set(FUNC(c64_final_chesscard_device::mainlatch_int));
GENERIC_LATCH_8(config, m_sublatch).data_pending_callback().set_inputline(m_maincpu, INPUT_LINE_NMI);
}
@@ -58,7 +56,7 @@ void c64_final_chesscard_device::device_add_mconfig(machine_config &config)
static INPUT_PORTS_START( c64_fcc )
PORT_START("RESET")
- PORT_BIT( 0x01, IP_ACTIVE_LOW, IPT_OTHER ) PORT_NAME("Reset") PORT_CODE(KEYCODE_F11) PORT_WRITE_LINE_DEVICE_MEMBER(DEVICE_SELF_OWNER, c64_expansion_slot_device, reset_w)
+ PORT_BIT( 0x01, IP_ACTIVE_LOW, IPT_OTHER ) PORT_NAME("Reset") PORT_CODE(KEYCODE_F11) PORT_WRITE_LINE_DEVICE_MEMBER(DEVICE_SELF_OWNER, FUNC(c64_expansion_slot_device::reset_w))
INPUT_PORTS_END
@@ -99,7 +97,10 @@ c64_final_chesscard_device::c64_final_chesscard_device(const machine_config &mco
void c64_final_chesscard_device::device_start()
{
+ m_nvram = std::make_unique<uint8_t[]>(0x2000);
+
// state saving
+ save_pointer(NAME(m_nvram), 0x2000);
save_item(NAME(m_bank));
save_item(NAME(m_hidden));
}
@@ -122,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 3c3aa02881d..7123336d64a 100644
--- a/src/devices/bus/c64/fcc.h
+++ b/src/devices/bus/c64/fcc.h
@@ -12,7 +12,7 @@
#pragma once
#include "exp.h"
-#include "cpu/m6502/m65sc02.h"
+#include "cpu/m6502/g65sc02.h"
#include "machine/gen_latch.h"
@@ -32,37 +32,35 @@ 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
- virtual void device_add_mconfig(machine_config &config) override;
- virtual ioport_constructor device_input_ports() const override;
-
- // device_nvram_interface overrides
- virtual void nvram_default() override { }
- virtual void nvram_read(emu_file &file) override { if (m_nvram != nullptr) { file.read(m_nvram, m_nvram.bytes()); } }
- virtual void nvram_write(emu_file &file) override { if (m_nvram != nullptr) { file.write(m_nvram, m_nvram.bytes()); } }
-
- // device_c64_expansion_card_interface overrides
+ // device_t implementation
+ virtual void device_add_mconfig(machine_config &config) override ATTR_COLD;
+ virtual ioport_constructor device_input_ports() const override ATTR_COLD;
+ virtual void device_start() override ATTR_COLD;
+ virtual void device_reset() override ATTR_COLD;
+
+ // 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 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;
private:
- required_device<m65sc02_device> m_maincpu;
+ required_device<g65sc02_device> m_maincpu;
required_device<generic_latch_8_device> m_mainlatch;
required_device<generic_latch_8_device> m_sublatch;
uint8_t m_bank;
int m_hidden;
- DECLARE_WRITE_LINE_MEMBER(mainlatch_int) { m_slot->nmi_w(state); }
- DECLARE_READ8_MEMBER(rom_r) { return m_romx[offset]; } // cartridge cpu rom
- DECLARE_READ8_MEMBER(nvram_r) { return m_nvram[offset & m_nvram.mask()]; }
- DECLARE_WRITE8_MEMBER(nvram_w) { m_nvram[offset & m_nvram.mask()] = data; }
+ 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; }
- void c64_fcc_map(address_map &map);
+ void c64_fcc_map(address_map &map) ATTR_COLD;
};
diff --git a/src/devices/bus/c64/final.cpp b/src/devices/bus/c64/final.cpp
index b11267b1f01..000db193cee 100644
--- a/src/devices/bus/c64/final.cpp
+++ b/src/devices/bus/c64/final.cpp
@@ -39,8 +39,8 @@ INPUT_CHANGED_MEMBER( c64_final_cartridge_device::freeze )
static INPUT_PORTS_START( c64_final )
PORT_START("SW")
- PORT_BIT( 0x01, IP_ACTIVE_LOW, IPT_OTHER ) PORT_NAME("Reset") PORT_CODE(KEYCODE_F11) PORT_WRITE_LINE_DEVICE_MEMBER(DEVICE_SELF_OWNER, c64_expansion_slot_device, reset_w)
- PORT_BIT( 0x02, IP_ACTIVE_HIGH, IPT_OTHER ) PORT_NAME("Freeze") PORT_CODE(KEYCODE_F12) PORT_CHANGED_MEMBER(DEVICE_SELF, c64_final_cartridge_device, freeze, 0)
+ PORT_BIT( 0x01, IP_ACTIVE_LOW, IPT_OTHER ) PORT_NAME("Reset") PORT_CODE(KEYCODE_F11) PORT_WRITE_LINE_DEVICE_MEMBER(DEVICE_SELF_OWNER, FUNC(c64_expansion_slot_device::reset_w))
+ PORT_BIT( 0x02, IP_ACTIVE_HIGH, IPT_OTHER ) PORT_NAME("Freeze") PORT_CODE(KEYCODE_F12) PORT_CHANGED_MEMBER(DEVICE_SELF, FUNC(c64_final_cartridge_device::freeze), 0)
INPUT_PORTS_END
diff --git a/src/devices/bus/c64/final.h b/src/devices/bus/c64/final.h
index 6d59e737c02..7ef67e034f1 100644
--- a/src/devices/bus/c64/final.h
+++ b/src/devices/bus/c64/final.h
@@ -30,14 +30,14 @@ public:
c64_final_cartridge_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;
+ virtual ioport_constructor device_input_ports() const override ATTR_COLD;
DECLARE_INPUT_CHANGED_MEMBER( freeze );
protected:
// device-level overrides
- virtual void device_start() override;
- virtual void device_reset() override;
+ virtual void device_start() override ATTR_COLD;
+ virtual void device_reset() override ATTR_COLD;
// 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;
diff --git a/src/devices/bus/c64/final3.cpp b/src/devices/bus/c64/final3.cpp
index 7df9d03042e..08c70ec4077 100644
--- a/src/devices/bus/c64/final3.cpp
+++ b/src/devices/bus/c64/final3.cpp
@@ -40,8 +40,8 @@ INPUT_CHANGED_MEMBER( c64_final3_cartridge_device::freeze )
static INPUT_PORTS_START( c64_final3 )
PORT_START("SW")
- PORT_BIT( 0x01, IP_ACTIVE_LOW, IPT_OTHER ) PORT_NAME("Reset") PORT_CODE(KEYCODE_F11) PORT_WRITE_LINE_DEVICE_MEMBER(DEVICE_SELF_OWNER, c64_expansion_slot_device, reset_w)
- PORT_BIT( 0x02, IP_ACTIVE_HIGH, IPT_OTHER ) PORT_NAME("Freeze") PORT_CODE(KEYCODE_F12) PORT_CHANGED_MEMBER(DEVICE_SELF, c64_final3_cartridge_device, freeze, 0)
+ PORT_BIT( 0x01, IP_ACTIVE_LOW, IPT_OTHER ) PORT_NAME("Reset") PORT_CODE(KEYCODE_F11) PORT_WRITE_LINE_DEVICE_MEMBER(DEVICE_SELF_OWNER, FUNC(c64_expansion_slot_device::reset_w))
+ PORT_BIT( 0x02, IP_ACTIVE_HIGH, IPT_OTHER ) PORT_NAME("Freeze") PORT_CODE(KEYCODE_F12) PORT_CHANGED_MEMBER(DEVICE_SELF, FUNC(c64_final3_cartridge_device::freeze), 0)
INPUT_PORTS_END
diff --git a/src/devices/bus/c64/final3.h b/src/devices/bus/c64/final3.h
index 8b020482560..03b5c959c0c 100644
--- a/src/devices/bus/c64/final3.h
+++ b/src/devices/bus/c64/final3.h
@@ -6,8 +6,8 @@
**********************************************************************/
-#ifndef MAME_BUS_C4_FINAL3_H
-#define MAME_BUS_C4_FINAL3_H
+#ifndef MAME_BUS_C64_FINAL3_H
+#define MAME_BUS_C64_FINAL3_H
#pragma once
@@ -30,14 +30,14 @@ public:
c64_final3_cartridge_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;
+ virtual ioport_constructor device_input_ports() const override ATTR_COLD;
DECLARE_INPUT_CHANGED_MEMBER( freeze );
protected:
// device-level overrides
- virtual void device_start() override;
- virtual void device_reset() override;
+ virtual void device_start() override ATTR_COLD;
+ virtual void device_reset() override ATTR_COLD;
// 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;
@@ -53,4 +53,4 @@ private:
DECLARE_DEVICE_TYPE(C64_FINAL3, c64_final3_cartridge_device)
-#endif // MAME_BUS_C4_FINAL3_H
+#endif // MAME_BUS_C64_FINAL3_H
diff --git a/src/devices/bus/c64/fun_play.h b/src/devices/bus/c64/fun_play.h
index 6fc082164c6..a720d9c457a 100644
--- a/src/devices/bus/c64/fun_play.h
+++ b/src/devices/bus/c64/fun_play.h
@@ -31,8 +31,8 @@ public:
protected:
// device-level overrides
- virtual void device_start() override;
- virtual void device_reset() override;
+ virtual void device_start() override ATTR_COLD;
+ virtual void device_reset() override ATTR_COLD;
// 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;
diff --git a/src/devices/bus/c64/geocable.h b/src/devices/bus/c64/geocable.h
index 6a45edf4e94..a7f8a114679 100644
--- a/src/devices/bus/c64/geocable.h
+++ b/src/devices/bus/c64/geocable.h
@@ -23,8 +23,7 @@
// ======================> c64_geocable_device
-class c64_geocable_device : public device_t,
- public device_pet_user_port_interface
+class c64_geocable_device : public device_t, public device_pet_user_port_interface
{
public:
// construction/destruction
@@ -32,21 +31,21 @@ public:
protected:
// device-level overrides
- virtual void device_start() override;
+ virtual void device_start() override ATTR_COLD;
// optional information overrides
- virtual void device_add_mconfig(machine_config &config) override;
+ virtual void device_add_mconfig(machine_config &config) override ATTR_COLD;
// 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/georam.cpp b/src/devices/bus/c64/georam.cpp
index 6bf8a16a1d8..377bc10a391 100644
--- a/src/devices/bus/c64/georam.cpp
+++ b/src/devices/bus/c64/georam.cpp
@@ -30,7 +30,7 @@ DEFINE_DEVICE_TYPE(C64_GEORAM, c64_georam_cartridge_device, "c64_georam", "C64 G
c64_georam_cartridge_device::c64_georam_cartridge_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) :
device_t(mconfig, C64_GEORAM, tag, owner, clock),
device_c64_expansion_card_interface(mconfig, *this),
- m_ram(*this, "ram"),
+ m_ram(*this, "ram", 0x80000, ENDIANNESS_LITTLE),
m_bank(0)
{
}
@@ -42,9 +42,6 @@ c64_georam_cartridge_device::c64_georam_cartridge_device(const machine_config &m
void c64_georam_cartridge_device::device_start()
{
- // allocate memory
- m_ram.allocate(0x80000);
-
// state saving
save_item(NAME(m_bank));
}
diff --git a/src/devices/bus/c64/georam.h b/src/devices/bus/c64/georam.h
index 03967625c23..0f8c53f642a 100644
--- a/src/devices/bus/c64/georam.h
+++ b/src/devices/bus/c64/georam.h
@@ -6,8 +6,8 @@
**********************************************************************/
-#ifndef MAME_BUC_C64_GEORAM_H
-#define MAME_BUC_C64_GEORAM_H
+#ifndef MAME_BUS_C64_GEORAM_H
+#define MAME_BUS_C64_GEORAM_H
#pragma once
@@ -31,15 +31,15 @@ public:
protected:
// device-level overrides
- virtual void device_start() override;
- virtual void device_reset() override;
+ virtual void device_start() override ATTR_COLD;
+ virtual void device_reset() override ATTR_COLD;
// 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:
- optional_shared_ptr<uint8_t> m_ram;
+ memory_share_creator<uint8_t> m_ram;
uint16_t m_bank;
};
@@ -49,4 +49,4 @@ private:
DECLARE_DEVICE_TYPE(C64_GEORAM, c64_georam_cartridge_device)
-#endif // MAME_BUC_C64_GEORAM_H
+#endif // MAME_BUS_C64_GEORAM_H
diff --git a/src/devices/bus/c64/ide64.cpp b/src/devices/bus/c64/ide64.cpp
index 1942ce466b5..830f38c3993 100644
--- a/src/devices/bus/c64/ide64.cpp
+++ b/src/devices/bus/c64/ide64.cpp
@@ -93,7 +93,8 @@ c64_ide64_cartridge_device::c64_ide64_cartridge_device(const machine_config &mco
m_rtc(*this, DS1302_TAG),
m_ata(*this, ATA_TAG),
m_jp1(*this, "JP1"),
- m_ram(*this, "ram"), m_bank(0), m_ata_data(0), m_wp(0), m_enable(0)
+ m_ram(*this, "ram", 0x8000, ENDIANNESS_LITTLE),
+ m_bank(0), m_ata_data(0), m_wp(0), m_enable(0)
{
}
@@ -104,9 +105,6 @@ c64_ide64_cartridge_device::c64_ide64_cartridge_device(const machine_config &mco
void c64_ide64_cartridge_device::device_start()
{
- // allocate memory
- m_ram.allocate(0x8000);
-
// state saving
save_item(NAME(m_bank));
save_item(NAME(m_ata_data));
@@ -173,13 +171,13 @@ uint8_t c64_ide64_cartridge_device::c64_cd_r(offs_t offset, uint8_t data, int sp
if (io1_offset >= 0x20 && io1_offset < 0x28)
{
- m_ata_data = m_ata->read_cs0(offset & 0x07);
+ m_ata_data = m_ata->cs0_r(offset & 0x07);
data = m_ata_data & 0xff;
}
else if (io1_offset >= 0x28 && io1_offset < 0x30)
{
- m_ata_data = m_ata->read_cs1(offset & 0x07);
+ m_ata_data = m_ata->cs1_r(offset & 0x07);
data = m_ata_data & 0xff;
}
@@ -276,13 +274,13 @@ void c64_ide64_cartridge_device::c64_cd_w(offs_t offset, uint8_t data, int sphi2
{
m_ata_data = (m_ata_data & 0xff00) | data;
- m_ata->write_cs0(offset & 0x07, m_ata_data);
+ m_ata->cs0_w(offset & 0x07, m_ata_data);
}
else if (io1_offset >= 0x28 && io1_offset < 0x30)
{
m_ata_data = (m_ata_data & 0xff00) | data;
- m_ata->write_cs1(offset & 0x07, m_ata_data);
+ m_ata->cs1_w(offset & 0x07, m_ata_data);
}
else if (io1_offset == 0x31)
{
diff --git a/src/devices/bus/c64/ide64.h b/src/devices/bus/c64/ide64.h
index bfabad10c87..ca778dfda3c 100644
--- a/src/devices/bus/c64/ide64.h
+++ b/src/devices/bus/c64/ide64.h
@@ -13,8 +13,8 @@
#include "exp.h"
+#include "bus/ata/ataintf.h"
#include "machine/ds1302.h"
-#include "machine/ataintf.h"
#include "machine/intelfsh.h"
#include "imagedev/harddriv.h"
@@ -35,12 +35,12 @@ public:
protected:
// device-level overrides
- virtual void device_start() override;
- virtual void device_reset() override;
+ virtual void device_start() override ATTR_COLD;
+ virtual void device_reset() override ATTR_COLD;
// optional information overrides
- virtual void device_add_mconfig(machine_config &config) override;
- virtual ioport_constructor device_input_ports() const override;
+ virtual void device_add_mconfig(machine_config &config) override ATTR_COLD;
+ virtual ioport_constructor device_input_ports() const override ATTR_COLD;
// 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;
@@ -53,7 +53,7 @@ private:
required_device<ds1302_device> m_rtc;
required_device<ata_interface_device> m_ata;
required_ioport m_jp1;
- optional_shared_ptr<uint8_t> m_ram;
+ memory_share_creator<uint8_t> m_ram;
uint8_t m_bank;
uint16_t m_ata_data;
diff --git a/src/devices/bus/c64/ieee488.cpp b/src/devices/bus/c64/ieee488.cpp
index aed81dbc9d1..dc588dfc136 100644
--- a/src/devices/bus/c64/ieee488.cpp
+++ b/src/devices/bus/c64/ieee488.cpp
@@ -23,14 +23,14 @@
// DEVICE DEFINITIONS
//**************************************************************************
-DEFINE_DEVICE_TYPE(C64_IEEE488, c64_ieee488_device, "c64_ieee488_device", "C64 IEEE-488 cartridge")
+DEFINE_DEVICE_TYPE(C64_IEEE488, c64_ieee488_device, "c64_ieee488", "C64 IEEE-488 cartridge")
//-------------------------------------------------
// tpi6525_interface tpi_intf
//-------------------------------------------------
-READ8_MEMBER( c64_ieee488_device::tpi_pa_r )
+uint8_t c64_ieee488_device::tpi_pa_r()
{
/*
@@ -59,7 +59,7 @@ READ8_MEMBER( c64_ieee488_device::tpi_pa_r )
return data;
}
-WRITE8_MEMBER( c64_ieee488_device::tpi_pa_w )
+void c64_ieee488_device::tpi_pa_w(uint8_t data)
{
/*
@@ -84,7 +84,7 @@ WRITE8_MEMBER( c64_ieee488_device::tpi_pa_w )
m_bus->host_nrfd_w(BIT(data, 7));
}
-READ8_MEMBER( c64_ieee488_device::tpi_pc_r )
+uint8_t c64_ieee488_device::tpi_pc_r(offs_t offset)
{
/*
@@ -111,7 +111,7 @@ READ8_MEMBER( c64_ieee488_device::tpi_pc_r )
return data;
}
-WRITE8_MEMBER( c64_ieee488_device::tpi_pc_w )
+void c64_ieee488_device::tpi_pc_w(uint8_t data)
{
/*
diff --git a/src/devices/bus/c64/ieee488.h b/src/devices/bus/c64/ieee488.h
index ab3c7748b8d..98d0fac447d 100644
--- a/src/devices/bus/c64/ieee488.h
+++ b/src/devices/bus/c64/ieee488.h
@@ -32,11 +32,11 @@ public:
protected:
// device-level overrides
- virtual void device_start() override;
- virtual void device_reset() override;
+ virtual void device_start() override ATTR_COLD;
+ virtual void device_reset() override ATTR_COLD;
// optional information overrides
- virtual void device_add_mconfig(machine_config &config) override;
+ virtual void device_add_mconfig(machine_config &config) override ATTR_COLD;
// 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;
@@ -44,10 +44,10 @@ protected:
virtual int c64_game_r(offs_t offset, int sphi2, int ba, int rw) override;
private:
- DECLARE_READ8_MEMBER( tpi_pa_r );
- DECLARE_WRITE8_MEMBER( tpi_pa_w );
- DECLARE_READ8_MEMBER( tpi_pc_r );
- DECLARE_WRITE8_MEMBER( tpi_pc_w );
+ uint8_t tpi_pa_r();
+ void tpi_pa_w(uint8_t data);
+ uint8_t tpi_pc_r(offs_t offset);
+ void tpi_pc_w(uint8_t data);
required_device<tpi6525_device> m_tpi;
required_device<ieee488_device> m_bus;
diff --git a/src/devices/bus/c64/kingsoft.h b/src/devices/bus/c64/kingsoft.h
index 3a9fda45fef..7b4855f77e9 100644
--- a/src/devices/bus/c64/kingsoft.h
+++ b/src/devices/bus/c64/kingsoft.h
@@ -31,8 +31,8 @@ public:
protected:
// device-level overrides
- virtual void device_start() override;
- virtual void device_reset() override;
+ virtual void device_start() override ATTR_COLD;
+ virtual void device_reset() override ATTR_COLD;
// 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;
diff --git a/src/devices/bus/c64/mach5.cpp b/src/devices/bus/c64/mach5.cpp
index ddd44407d3e..d892f610a64 100644
--- a/src/devices/bus/c64/mach5.cpp
+++ b/src/devices/bus/c64/mach5.cpp
@@ -29,7 +29,7 @@ static INPUT_PORTS_START( c64_mach5 )
PORT_DIPSETTING( 0x01, "C128" )
PORT_START("S2")
- PORT_BIT( 0x01, IP_ACTIVE_LOW, IPT_OTHER ) PORT_NAME("Reset") PORT_CODE(KEYCODE_F11) PORT_WRITE_LINE_DEVICE_MEMBER(DEVICE_SELF_OWNER, c64_expansion_slot_device, reset_w)
+ PORT_BIT( 0x01, IP_ACTIVE_LOW, IPT_OTHER ) PORT_NAME("Reset") PORT_CODE(KEYCODE_F11) PORT_WRITE_LINE_DEVICE_MEMBER(DEVICE_SELF_OWNER, FUNC(c64_expansion_slot_device::reset_w))
INPUT_PORTS_END
diff --git a/src/devices/bus/c64/mach5.h b/src/devices/bus/c64/mach5.h
index a49e1bec347..12424a14193 100644
--- a/src/devices/bus/c64/mach5.h
+++ b/src/devices/bus/c64/mach5.h
@@ -29,12 +29,12 @@ public:
c64_mach5_cartridge_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;
+ virtual ioport_constructor device_input_ports() const override ATTR_COLD;
protected:
// device-level overrides
- virtual void device_start() override;
- virtual void device_reset() override;
+ virtual void device_start() override ATTR_COLD;
+ virtual void device_reset() override ATTR_COLD;
// 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;
diff --git a/src/devices/bus/c64/magic_desk.h b/src/devices/bus/c64/magic_desk.h
index 75f76dee732..dbbf839e1d3 100644
--- a/src/devices/bus/c64/magic_desk.h
+++ b/src/devices/bus/c64/magic_desk.h
@@ -31,8 +31,8 @@ public:
protected:
// device-level overrides
- virtual void device_start() override;
- virtual void device_reset() override;
+ virtual void device_start() override ATTR_COLD;
+ virtual void device_reset() override ATTR_COLD;
// 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;
diff --git a/src/devices/bus/c64/magic_formel.cpp b/src/devices/bus/c64/magic_formel.cpp
index e47795a9eb0..2435452cb2f 100644
--- a/src/devices/bus/c64/magic_formel.cpp
+++ b/src/devices/bus/c64/magic_formel.cpp
@@ -34,7 +34,7 @@
DEFINE_DEVICE_TYPE(C64_MAGIC_FORMEL, c64_magic_formel_cartridge_device, "c64_magic_formel", "C64 Magic Formel cartridge")
-WRITE8_MEMBER( c64_magic_formel_cartridge_device::pia_pa_w )
+void c64_magic_formel_cartridge_device::pia_pa_w(uint8_t data)
{
/*
@@ -56,7 +56,7 @@ WRITE8_MEMBER( c64_magic_formel_cartridge_device::pia_pa_w )
m_ram_oe = BIT(data, 4);
}
-WRITE8_MEMBER( c64_magic_formel_cartridge_device::pia_pb_w )
+void c64_magic_formel_cartridge_device::pia_pb_w(uint8_t data)
{
/*
@@ -83,7 +83,7 @@ WRITE8_MEMBER( c64_magic_formel_cartridge_device::pia_pb_w )
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));
@@ -130,7 +130,7 @@ INPUT_CHANGED_MEMBER( c64_magic_formel_cartridge_device::freeze )
static INPUT_PORTS_START( c64_magic_formel )
PORT_START("FREEZE")
- PORT_BIT( 0x01, IP_ACTIVE_HIGH, IPT_OTHER ) PORT_NAME("Freeze") PORT_CODE(KEYCODE_F12) PORT_CHANGED_MEMBER(DEVICE_SELF, c64_magic_formel_cartridge_device, freeze, 0)
+ PORT_BIT( 0x01, IP_ACTIVE_HIGH, IPT_OTHER ) PORT_NAME("Freeze") PORT_CODE(KEYCODE_F12) PORT_CHANGED_MEMBER(DEVICE_SELF, FUNC(c64_magic_formel_cartridge_device::freeze), 0)
INPUT_PORTS_END
@@ -157,7 +157,7 @@ c64_magic_formel_cartridge_device::c64_magic_formel_cartridge_device(const machi
device_t(mconfig, C64_MAGIC_FORMEL, tag, owner, clock),
device_c64_expansion_card_interface(mconfig, *this),
m_pia(*this, MC6821_TAG),
- m_ram(*this, "ram"),
+ m_ram(*this, "ram", 0x2000, ENDIANNESS_LITTLE),
m_rom_bank(0),
m_ram_bank(0),
m_ram_oe(0),
@@ -174,9 +174,6 @@ c64_magic_formel_cartridge_device::c64_magic_formel_cartridge_device(const machi
void c64_magic_formel_cartridge_device::device_start()
{
- // allocate memory
- m_ram.allocate(0x2000);
-
// state saving
save_item(NAME(m_rom_bank));
save_item(NAME(m_ram_bank));
diff --git a/src/devices/bus/c64/magic_formel.h b/src/devices/bus/c64/magic_formel.h
index 818342d3c3f..6a80cda9c1f 100644
--- a/src/devices/bus/c64/magic_formel.h
+++ b/src/devices/bus/c64/magic_formel.h
@@ -33,12 +33,12 @@ public:
protected:
// device-level overrides
- virtual void device_start() override;
- virtual void device_reset() override;
+ virtual void device_start() override ATTR_COLD;
+ virtual void device_reset() override ATTR_COLD;
// optional information overrides
- virtual void device_add_mconfig(machine_config &config) override;
- virtual ioport_constructor device_input_ports() const override;
+ virtual void device_add_mconfig(machine_config &config) override ATTR_COLD;
+ virtual ioport_constructor device_input_ports() const override ATTR_COLD;
// 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;
@@ -46,12 +46,12 @@ protected:
virtual int c64_game_r(offs_t offset, int sphi2, int ba, int rw) override;
private:
- DECLARE_WRITE8_MEMBER( pia_pa_w );
- DECLARE_WRITE8_MEMBER( pia_pb_w );
- DECLARE_WRITE_LINE_MEMBER( pia_cb2_w );
+ void pia_pa_w(uint8_t data);
+ void pia_pb_w(uint8_t data);
+ void pia_cb2_w(int state);
required_device<pia6821_device> m_pia;
- optional_shared_ptr<uint8_t> m_ram;
+ memory_share_creator<uint8_t> m_ram;
uint8_t m_rom_bank;
uint8_t m_ram_bank;
diff --git a/src/devices/bus/c64/magic_voice.cpp b/src/devices/bus/c64/magic_voice.cpp
index 3b6c0ebdb62..b9e0949ed3d 100644
--- a/src/devices/bus/c64/magic_voice.cpp
+++ b/src/devices/bus/c64/magic_voice.cpp
@@ -73,12 +73,12 @@ 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);
}
-READ8_MEMBER( c64_magic_voice_cartridge_device::tpi_pa_r )
+uint8_t c64_magic_voice_cartridge_device::tpi_pa_r()
{
/*
@@ -104,7 +104,7 @@ READ8_MEMBER( c64_magic_voice_cartridge_device::tpi_pa_r )
return data;
}
-WRITE8_MEMBER( c64_magic_voice_cartridge_device::tpi_pa_w )
+void c64_magic_voice_cartridge_device::tpi_pa_w(uint8_t data)
{
/*
@@ -125,7 +125,7 @@ WRITE8_MEMBER( c64_magic_voice_cartridge_device::tpi_pa_w )
m_fifo->si_w(BIT(data, 4));
}
-READ8_MEMBER( c64_magic_voice_cartridge_device::tpi_pb_r )
+uint8_t c64_magic_voice_cartridge_device::tpi_pb_r()
{
/*
@@ -149,7 +149,7 @@ READ8_MEMBER( c64_magic_voice_cartridge_device::tpi_pb_r )
return data;
}
-WRITE8_MEMBER( c64_magic_voice_cartridge_device::tpi_pb_w )
+void c64_magic_voice_cartridge_device::tpi_pb_w(uint8_t data)
{
/*
@@ -174,12 +174,12 @@ WRITE8_MEMBER( c64_magic_voice_cartridge_device::tpi_pb_w )
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 bf6f081fd67..cd9796413db 100644
--- a/src/devices/bus/c64/magic_voice.h
+++ b/src/devices/bus/c64/magic_voice.h
@@ -33,11 +33,11 @@ public:
protected:
// device-level overrides
- virtual void device_start() override;
- virtual void device_reset() override;
+ virtual void device_start() override ATTR_COLD;
+ virtual void device_reset() override ATTR_COLD;
// optional information overrides
- virtual void device_add_mconfig(machine_config &config) override;
+ virtual void device_add_mconfig(machine_config &config) override ATTR_COLD;
// 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;
@@ -47,17 +47,17 @@ protected:
private:
offs_t get_offset(offs_t offset);
- DECLARE_WRITE_LINE_MEMBER( tpi_irq_w );
- DECLARE_READ8_MEMBER( tpi_pa_r );
- DECLARE_WRITE8_MEMBER( tpi_pa_w );
- DECLARE_READ8_MEMBER( tpi_pb_r );
- DECLARE_WRITE8_MEMBER( tpi_pb_w );
- DECLARE_WRITE_LINE_MEMBER( tpi_ca_w );
- DECLARE_WRITE_LINE_MEMBER( tpi_cb_w );
-
- DECLARE_WRITE_LINE_MEMBER( phi2_w );
- DECLARE_WRITE_LINE_MEMBER( dtrd_w );
- DECLARE_WRITE_LINE_MEMBER( apd_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);
+ void tpi_ca_w(int state);
+ void tpi_cb_w(int state);
+
+ 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 eff1129802d..103b26e5670 100644
--- a/src/devices/bus/c64/midi_maplin.h
+++ b/src/devices/bus/c64/midi_maplin.h
@@ -22,8 +22,7 @@
// ======================> c64_maplin_midi_cartridge_device
-class c64_maplin_midi_cartridge_device : public device_t,
- public device_c64_expansion_card_interface
+class c64_maplin_midi_cartridge_device : public device_t, public device_c64_expansion_card_interface
{
public:
// construction/destruction
@@ -31,19 +30,19 @@ public:
protected:
// device-level overrides
- virtual void device_start() override;
- virtual void device_reset() override;
+ virtual void device_start() override ATTR_COLD;
+ virtual void device_reset() override ATTR_COLD;
// optional information overrides
- virtual void device_add_mconfig(machine_config &config) override;
+ virtual void device_add_mconfig(machine_config &config) override ATTR_COLD;
// 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:
- 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 ab5064486c0..11b7a3ce022 100644
--- a/src/devices/bus/c64/midi_namesoft.h
+++ b/src/devices/bus/c64/midi_namesoft.h
@@ -22,8 +22,7 @@
// ======================> c64_namesoft_midi_cartridge_device
-class c64_namesoft_midi_cartridge_device : public device_t,
- public device_c64_expansion_card_interface
+class c64_namesoft_midi_cartridge_device : public device_t, public device_c64_expansion_card_interface
{
public:
// construction/destruction
@@ -31,19 +30,19 @@ public:
protected:
// device-level overrides
- virtual void device_start() override;
- virtual void device_reset() override;
+ virtual void device_start() override ATTR_COLD;
+ virtual void device_reset() override ATTR_COLD;
// optional information overrides
- virtual void device_add_mconfig(machine_config &config) override;
+ virtual void device_add_mconfig(machine_config &config) override ATTR_COLD;
// 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:
- 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 a538d312912..8f99cf8f294 100644
--- a/src/devices/bus/c64/midi_passport.h
+++ b/src/devices/bus/c64/midi_passport.h
@@ -23,8 +23,7 @@
// ======================> c64_passport_midi_cartridge_device
-class c64_passport_midi_cartridge_device : public device_t,
- public device_c64_expansion_card_interface
+class c64_passport_midi_cartridge_device : public device_t, public device_c64_expansion_card_interface
{
public:
// construction/destruction
@@ -32,20 +31,20 @@ public:
protected:
// device-level overrides
- virtual void device_start() override;
- virtual void device_reset() override;
+ virtual void device_start() override ATTR_COLD;
+ virtual void device_reset() override ATTR_COLD;
// optional information overrides
- virtual void device_add_mconfig(machine_config &config) override;
+ virtual void device_add_mconfig(machine_config &config) override ATTR_COLD;
// 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:
- 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 b0d52a0f70d..d3146db7644 100644
--- a/src/devices/bus/c64/midi_sci.h
+++ b/src/devices/bus/c64/midi_sci.h
@@ -22,8 +22,7 @@
// ======================> c64_sequential_midi_cartridge_device
-class c64_sequential_midi_cartridge_device : public device_t,
- public device_c64_expansion_card_interface
+class c64_sequential_midi_cartridge_device : public device_t, public device_c64_expansion_card_interface
{
public:
// construction/destruction
@@ -31,19 +30,19 @@ public:
protected:
// device-level overrides
- virtual void device_start() override;
- virtual void device_reset() override;
+ virtual void device_start() override ATTR_COLD;
+ virtual void device_reset() override ATTR_COLD;
// optional information overrides
- virtual void device_add_mconfig(machine_config &config) override;
+ virtual void device_add_mconfig(machine_config &config) override ATTR_COLD;
// 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:
- 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 fe38834278e..0413ccd3d25 100644
--- a/src/devices/bus/c64/midi_siel.h
+++ b/src/devices/bus/c64/midi_siel.h
@@ -22,8 +22,7 @@
// ======================> c64_siel_midi_cartridge_device
-class c64_siel_midi_cartridge_device : public device_t,
- public device_c64_expansion_card_interface
+class c64_siel_midi_cartridge_device : public device_t, public device_c64_expansion_card_interface
{
public:
// construction/destruction
@@ -31,19 +30,19 @@ public:
protected:
// device-level overrides
- virtual void device_start() override;
- virtual void device_reset() override;
+ virtual void device_start() override ATTR_COLD;
+ virtual void device_reset() override ATTR_COLD;
// optional information overrides
- virtual void device_add_mconfig(machine_config &config) override;
+ virtual void device_add_mconfig(machine_config &config) override ATTR_COLD;
// 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:
- 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/mikro_assembler.h b/src/devices/bus/c64/mikro_assembler.h
index 754a91385d4..7a06c2fcc49 100644
--- a/src/devices/bus/c64/mikro_assembler.h
+++ b/src/devices/bus/c64/mikro_assembler.h
@@ -31,7 +31,7 @@ public:
protected:
// device-level overrides
- virtual void device_start() override;
+ virtual void device_start() override ATTR_COLD;
// 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;
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/multiscreen.h b/src/devices/bus/c64/multiscreen.h
index 619154d18c5..d4d18db1f7e 100644
--- a/src/devices/bus/c64/multiscreen.h
+++ b/src/devices/bus/c64/multiscreen.h
@@ -33,12 +33,12 @@ public:
protected:
// device-level overrides
- virtual void device_start() override;
- virtual void device_reset() override;
+ virtual void device_start() override ATTR_COLD;
+ virtual void device_reset() override ATTR_COLD;
// optional information overrides
- virtual const tiny_rom_entry *device_rom_region() const override;
- virtual void device_add_mconfig(machine_config &config) override;
+ virtual const tiny_rom_entry *device_rom_region() const override ATTR_COLD;
+ virtual void device_add_mconfig(machine_config &config) override ATTR_COLD;
// 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;
@@ -47,7 +47,7 @@ protected:
private:
uint8_t m_bank;
- void multiscreen_mem(address_map &map);
+ void multiscreen_mem(address_map &map) ATTR_COLD;
};
diff --git a/src/devices/bus/c64/music64.h b/src/devices/bus/c64/music64.h
index cf494c481b8..386ea98dbec 100644
--- a/src/devices/bus/c64/music64.h
+++ b/src/devices/bus/c64/music64.h
@@ -30,12 +30,12 @@ public:
protected:
// device-level overrides
- virtual void device_start() override;
- virtual void device_reset() override;
+ virtual void device_start() override ATTR_COLD;
+ virtual void device_reset() override ATTR_COLD;
// optional information overrides
- virtual void device_add_mconfig(machine_config &config) override;
- virtual ioport_constructor device_input_ports() const override;
+ virtual void device_add_mconfig(machine_config &config) override ATTR_COLD;
+ virtual ioport_constructor device_input_ports() const override ATTR_COLD;
// 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;
diff --git a/src/devices/bus/c64/neoram.cpp b/src/devices/bus/c64/neoram.cpp
index 4cb34cbbb57..e10ccac39b5 100644
--- a/src/devices/bus/c64/neoram.cpp
+++ b/src/devices/bus/c64/neoram.cpp
@@ -43,7 +43,7 @@ c64_neoram_cartridge_device::c64_neoram_cartridge_device(const machine_config &m
void c64_neoram_cartridge_device::device_start()
{
// allocate memory
- m_nvram.allocate(0x200000);
+ m_nvram = std::make_unique<uint8_t[]>(0x200000);
// state saving
save_item(NAME(m_bank));
@@ -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 d5058b878b7..b0b696a5c68 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
- virtual void device_start() override;
- virtual void device_reset() override;
+ // device_t implementation
+ virtual void device_start() override ATTR_COLD;
+ virtual void device_reset() override ATTR_COLD;
- // device_nvram_interface overrides
- virtual void nvram_default() override { }
- virtual void nvram_read(emu_file &file) override { if (m_nvram != nullptr) { file.read(m_nvram, m_nvram.bytes()); } }
- virtual void nvram_write(emu_file &file) override { if (m_nvram != nullptr) { file.write(m_nvram, 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_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/ocean.cpp b/src/devices/bus/c64/ocean.cpp
index 92b18de6a51..3e134d9449b 100644
--- a/src/devices/bus/c64/ocean.cpp
+++ b/src/devices/bus/c64/ocean.cpp
@@ -84,15 +84,15 @@ void c64_ocean_cartridge_device::device_reset()
uint8_t c64_ocean_cartridge_device::c64_cd_r(offs_t offset, uint8_t data, int sphi2, int ba, int roml, int romh, int io1, int io2)
{
- if (!roml && m_roml.bytes())
+ if (!roml && m_roml)
{
offs_t addr = (m_bank << 13) | (offset & 0x1fff);
- data = m_roml[addr & m_roml.mask()];
+ data = m_roml[addr & (m_roml_size - 1)];
}
- else if (!romh && m_romh.bytes())
+ else if (!romh && m_romh)
{
offs_t addr = (m_bank << 13) | (offset & 0x1fff);
- data = m_romh[addr & m_romh.mask()];
+ data = m_romh[addr & (m_romh_size - 1)];
}
else if (!io1)
{
diff --git a/src/devices/bus/c64/ocean.h b/src/devices/bus/c64/ocean.h
index 9a78f5e21f9..3412f4f1747 100644
--- a/src/devices/bus/c64/ocean.h
+++ b/src/devices/bus/c64/ocean.h
@@ -31,8 +31,8 @@ public:
protected:
// device-level overrides
- virtual void device_start() override;
- virtual void device_reset() override;
+ virtual void device_start() override ATTR_COLD;
+ virtual void device_reset() override ATTR_COLD;
// 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;
diff --git a/src/devices/bus/c64/pagefox.cpp b/src/devices/bus/c64/pagefox.cpp
index 80264aab13b..e33bb4d3d7b 100644
--- a/src/devices/bus/c64/pagefox.cpp
+++ b/src/devices/bus/c64/pagefox.cpp
@@ -52,7 +52,8 @@ DEFINE_DEVICE_TYPE(C64_PAGEFOX, c64_pagefox_cartridge_device, "c64_pagefox", "C6
c64_pagefox_cartridge_device::c64_pagefox_cartridge_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) :
device_t(mconfig, C64_PAGEFOX, tag, owner, clock),
device_c64_expansion_card_interface(mconfig, *this),
- m_ram(*this, "ram"), m_bank(0)
+ m_ram(*this, "ram", 0x8000, ENDIANNESS_LITTLE),
+ m_bank(0)
{
}
@@ -63,9 +64,6 @@ c64_pagefox_cartridge_device::c64_pagefox_cartridge_device(const machine_config
void c64_pagefox_cartridge_device::device_start()
{
- // allocate memory
- m_ram.allocate(0x8000);
-
// state saving
save_item(NAME(m_bank));
}
diff --git a/src/devices/bus/c64/pagefox.h b/src/devices/bus/c64/pagefox.h
index 74ed5a4edf0..b985939d7c5 100644
--- a/src/devices/bus/c64/pagefox.h
+++ b/src/devices/bus/c64/pagefox.h
@@ -31,15 +31,15 @@ public:
protected:
// device-level overrides
- virtual void device_start() override;
- virtual void device_reset() override;
+ virtual void device_start() override ATTR_COLD;
+ virtual void device_reset() override ATTR_COLD;
// 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:
- optional_shared_ptr<uint8_t> m_ram;
+ memory_share_creator<uint8_t> m_ram;
uint8_t m_bank;
};
diff --git a/src/devices/bus/c64/partner.cpp b/src/devices/bus/c64/partner.cpp
index 55e4d07f3e1..e13c99be49e 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)
{
@@ -54,7 +54,7 @@ WRITE_LINE_MEMBER( c64_partner_cartridge_device::nmi_w )
static INPUT_PORTS_START( c64_partner )
PORT_START("NMI")
- PORT_BIT( 0x01, IP_ACTIVE_HIGH, IPT_OTHER ) PORT_NAME("Menu") PORT_CODE(KEYCODE_F11) PORT_WRITE_LINE_DEVICE_MEMBER(DEVICE_SELF, c64_partner_cartridge_device, nmi_w)
+ PORT_BIT( 0x01, IP_ACTIVE_HIGH, IPT_OTHER ) PORT_NAME("Menu") PORT_CODE(KEYCODE_F11) PORT_WRITE_LINE_DEVICE_MEMBER(DEVICE_SELF, FUNC(c64_partner_cartridge_device::nmi_w))
INPUT_PORTS_END
@@ -80,7 +80,7 @@ ioport_constructor c64_partner_cartridge_device::device_input_ports() const
c64_partner_cartridge_device::c64_partner_cartridge_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) :
device_t(mconfig, C64_PARTNER, tag, owner, clock),
device_c64_expansion_card_interface(mconfig, *this),
- m_ram(*this, "ram"),
+ m_ram(*this, "ram", 0x2000, ENDIANNESS_LITTLE),
m_a0(1),
m_a6(1),
m_nmi(0)
@@ -94,8 +94,6 @@ c64_partner_cartridge_device::c64_partner_cartridge_device(const machine_config
void c64_partner_cartridge_device::device_start()
{
- // allocate memory
- m_ram.allocate(0x2000);
}
diff --git a/src/devices/bus/c64/partner.h b/src/devices/bus/c64/partner.h
index 6ecf4503a91..d7b1267ce60 100644
--- a/src/devices/bus/c64/partner.h
+++ b/src/devices/bus/c64/partner.h
@@ -29,14 +29,14 @@ public:
c64_partner_cartridge_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;
+ virtual ioport_constructor device_input_ports() const override ATTR_COLD;
- DECLARE_WRITE_LINE_MEMBER( nmi_w );
+ void nmi_w(int state);
protected:
// device-level overrides
- virtual void device_start() override;
- virtual void device_reset() override;
+ virtual void device_start() override ATTR_COLD;
+ virtual void device_reset() override ATTR_COLD;
// 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;
@@ -44,7 +44,7 @@ protected:
virtual int c64_game_r(offs_t offset, int sphi2, int ba, int rw) override;
private:
- optional_shared_ptr<uint8_t> m_ram;
+ memory_share_creator<uint8_t> m_ram;
int m_a0;
int m_a6;
diff --git a/src/devices/bus/c64/prophet64.h b/src/devices/bus/c64/prophet64.h
index f58ba30b7b7..1eb20ae50fd 100644
--- a/src/devices/bus/c64/prophet64.h
+++ b/src/devices/bus/c64/prophet64.h
@@ -30,8 +30,8 @@ public:
protected:
// device-level overrides
- virtual void device_start() override;
- virtual void device_reset() override;
+ virtual void device_start() override ATTR_COLD;
+ virtual void device_reset() override ATTR_COLD;
// 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;
diff --git a/src/devices/bus/c64/ps64.h b/src/devices/bus/c64/ps64.h
index 69a9c5b0110..c5ad9ead38b 100644
--- a/src/devices/bus/c64/ps64.h
+++ b/src/devices/bus/c64/ps64.h
@@ -32,11 +32,11 @@ public:
protected:
// device-level overrides
- virtual void device_start() override;
- virtual void device_reset() override;
+ virtual void device_start() override ATTR_COLD;
+ virtual void device_reset() override ATTR_COLD;
// optional information overrides
- virtual void device_add_mconfig(machine_config &config) override;
+ virtual void device_add_mconfig(machine_config &config) override ATTR_COLD;
// 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;
diff --git a/src/devices/bus/c64/reu.cpp b/src/devices/bus/c64/reu.cpp
index 332ac53f8a8..0d24a1967fa 100644
--- a/src/devices/bus/c64/reu.cpp
+++ b/src/devices/bus/c64/reu.cpp
@@ -22,9 +22,9 @@
// DEVICE DEFINITIONS
//**************************************************************************
-DEFINE_DEVICE_TYPE(C64_REU1700, c64_reu1700_cartridge_device, "c64_1700reu", "1700 REU")
-DEFINE_DEVICE_TYPE(C64_REU1750, c64_reu1750_cartridge_device, "c64_1750reu", "1750 REU")
-DEFINE_DEVICE_TYPE(C64_REU1764, c64_reu1764_cartridge_device, "c64_1764reu", "1764 REU")
+DEFINE_DEVICE_TYPE(C64_REU1700, c64_reu1700_cartridge_device, "c64_1700reu", "1700 RAM Expansion Unit")
+DEFINE_DEVICE_TYPE(C64_REU1750, c64_reu1750_cartridge_device, "c64_1750reu", "1750 RAM Expansion Unit")
+DEFINE_DEVICE_TYPE(C64_REU1764, c64_reu1764_cartridge_device, "c64_1764reu", "1764 RAM Expansion Unit")
//-------------------------------------------------
@@ -53,7 +53,7 @@ c64_reu_cartridge_device::c64_reu_cartridge_device(const machine_config &mconfig
device_c64_expansion_card_interface(mconfig, *this),
m_dmac(*this, MOS8726R1_TAG),
m_eprom(*this, "rom"),
- m_ram(*this, "ram"),
+ m_ram(*this, "ram", ram_size, ENDIANNESS_LITTLE),
m_variant(variant),
m_jp1(jp1),
m_ram_size(ram_size)
@@ -76,9 +76,6 @@ c64_reu1764_cartridge_device::c64_reu1764_cartridge_device(const machine_config
void c64_reu_cartridge_device::device_start()
{
- // allocate memory
- m_ram.allocate(m_ram_size);
-
// setup DMA controller
m_dmac->set_unscaled_clock(m_slot->phi2());
m_dmac->bs_w(m_jp1);
diff --git a/src/devices/bus/c64/reu.h b/src/devices/bus/c64/reu.h
index 0cbb67d9576..7c1e76e530a 100644
--- a/src/devices/bus/c64/reu.h
+++ b/src/devices/bus/c64/reu.h
@@ -40,11 +40,11 @@ protected:
c64_reu_cartridge_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock, uint32_t variant, int jp1, size_t ram_size);
// device-level overrides
- virtual void device_start() override;
- virtual void device_reset() override;
+ virtual void device_start() override ATTR_COLD;
+ virtual void device_reset() override ATTR_COLD;
// optional information overrides
- virtual void device_add_mconfig(machine_config &config) override;
+ virtual void device_add_mconfig(machine_config &config) override ATTR_COLD;
// 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;
@@ -52,7 +52,7 @@ protected:
required_device<mos8726_device> m_dmac;
required_device<generic_slot_device> m_eprom;
- optional_shared_ptr<uint8_t> m_ram;
+ memory_share_creator<uint8_t> m_ram;
int m_variant;
int m_jp1;
diff --git a/src/devices/bus/c64/rex.h b/src/devices/bus/c64/rex.h
index cc0cccb52da..04dc5fa975c 100644
--- a/src/devices/bus/c64/rex.h
+++ b/src/devices/bus/c64/rex.h
@@ -31,8 +31,8 @@ public:
protected:
// device-level overrides
- virtual void device_start() override;
- virtual void device_reset() override;
+ virtual void device_start() override ATTR_COLD;
+ virtual void device_reset() override ATTR_COLD;
// 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;
diff --git a/src/devices/bus/c64/rex_ep256.cpp b/src/devices/bus/c64/rex_ep256.cpp
index da1f7b601b7..c482e4b2589 100644
--- a/src/devices/bus/c64/rex_ep256.cpp
+++ b/src/devices/bus/c64/rex_ep256.cpp
@@ -15,7 +15,7 @@
// DEVICE DEFINITIONS
//**************************************************************************
-DEFINE_DEVICE_TYPE(C64_REX_EP256, c64_rex_ep256_cartridge_device, "rexexp256", "C64 Rex 256KB EPROM cartridge")
+DEFINE_DEVICE_TYPE(C64_REX_EP256, c64_rex_ep256_cartridge_device, "c64_rex_ep256", "C64 Rex 256KB EPROM cartridge")
//-------------------------------------------------
@@ -24,14 +24,8 @@ DEFINE_DEVICE_TYPE(C64_REX_EP256, c64_rex_ep256_cartridge_device, "rexexp256", "
void c64_rex_ep256_cartridge_device::device_add_mconfig(machine_config &config)
{
- GENERIC_SOCKET(config, "rom1", generic_linear_slot, nullptr, "bin,rom");
- GENERIC_SOCKET(config, "rom2", generic_linear_slot, nullptr, "bin,rom");
- GENERIC_SOCKET(config, "rom3", generic_linear_slot, nullptr, "bin,rom");
- GENERIC_SOCKET(config, "rom4", generic_linear_slot, nullptr, "bin,rom");
- GENERIC_SOCKET(config, "rom5", generic_linear_slot, nullptr, "bin,rom");
- GENERIC_SOCKET(config, "rom6", generic_linear_slot, nullptr, "bin,rom");
- GENERIC_SOCKET(config, "rom7", generic_linear_slot, nullptr, "bin,rom");
- GENERIC_SOCKET(config, "rom8", generic_linear_slot, nullptr, "bin,rom");
+ for (auto &eprom : m_eproms)
+ GENERIC_SOCKET(config, eprom, generic_linear_slot, nullptr, "bin,rom");
}
@@ -46,14 +40,9 @@ void c64_rex_ep256_cartridge_device::device_add_mconfig(machine_config &config)
c64_rex_ep256_cartridge_device::c64_rex_ep256_cartridge_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) :
device_t(mconfig, C64_REX_EP256, tag, owner, clock),
- device_c64_expansion_card_interface(mconfig, *this)
+ device_c64_expansion_card_interface(mconfig, *this),
+ m_eproms(*this, "rom%u", 1U)
{
- for (int i = 0; i < 8; i++)
- {
- char str[6];
- sprintf(str, "rom%i", i + 1);
- m_eproms[i] = subdevice<generic_slot_device>(str);
- }
}
diff --git a/src/devices/bus/c64/rex_ep256.h b/src/devices/bus/c64/rex_ep256.h
index 06f4a4325d5..b51fc1a1fd5 100644
--- a/src/devices/bus/c64/rex_ep256.h
+++ b/src/devices/bus/c64/rex_ep256.h
@@ -12,9 +12,9 @@
#pragma once
+#include "exp.h"
#include "bus/generic/slot.h"
#include "bus/generic/carts.h"
-#include "exp.h"
@@ -33,18 +33,18 @@ public:
protected:
// device-level overrides
- virtual void device_start() override;
- virtual void device_reset() override;
+ virtual void device_start() override ATTR_COLD;
+ virtual void device_reset() override ATTR_COLD;
// optional information overrides
- virtual void device_add_mconfig(machine_config &config) override;
+ virtual void device_add_mconfig(machine_config &config) override ATTR_COLD;
// 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:
- generic_slot_device *m_eproms[8];
+ required_device_array<generic_slot_device, 8> m_eproms;
uint8_t m_bank, m_socket;
int m_reset;
diff --git a/src/devices/bus/c64/ross.cpp b/src/devices/bus/c64/ross.cpp
index 25c1a996df8..e8703a33bcc 100644
--- a/src/devices/bus/c64/ross.cpp
+++ b/src/devices/bus/c64/ross.cpp
@@ -68,7 +68,7 @@ uint8_t c64_ross_cartridge_device::c64_cd_r(offs_t offset, uint8_t data, int sph
{
offs_t addr = (m_bank << 14) | (offset & 0x3fff);
- data = m_roml[addr & m_roml.mask()];
+ data = m_roml[addr];
}
return data;
diff --git a/src/devices/bus/c64/ross.h b/src/devices/bus/c64/ross.h
index 97f2698fb6c..bfd6693ebfe 100644
--- a/src/devices/bus/c64/ross.h
+++ b/src/devices/bus/c64/ross.h
@@ -31,8 +31,8 @@ public:
protected:
// device-level overrides
- virtual void device_start() override;
- virtual void device_reset() override;
+ virtual void device_start() override ATTR_COLD;
+ virtual void device_reset() override ATTR_COLD;
// 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;
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 9380e055c18..6d8959a20a2 100644
--- a/src/devices/bus/c64/sfx_sound_expander.h
+++ b/src/devices/bus/c64/sfx_sound_expander.h
@@ -12,7 +12,7 @@
#pragma once
#include "exp.h"
-#include "sound/3526intf.h"
+#include "sound/ymopl.h"
@@ -31,12 +31,12 @@ public:
protected:
// device-level overrides
- virtual void device_start() override;
- virtual void device_reset() override;
+ virtual void device_start() override ATTR_COLD;
+ virtual void device_reset() override ATTR_COLD;
// optional information overrides
- virtual void device_add_mconfig(machine_config &config) override;
- virtual ioport_constructor device_input_ports() const override;
+ virtual void device_add_mconfig(machine_config &config) override ATTR_COLD;
+ virtual ioport_constructor device_input_ports() const override ATTR_COLD;
// 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;
@@ -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/silverrock.h b/src/devices/bus/c64/silverrock.h
index 3d9c4e015f2..304b04af5a7 100644
--- a/src/devices/bus/c64/silverrock.h
+++ b/src/devices/bus/c64/silverrock.h
@@ -31,8 +31,8 @@ public:
protected:
// device-level overrides
- virtual void device_start() override;
- virtual void device_reset() override;
+ virtual void device_start() override ATTR_COLD;
+ virtual void device_reset() override ATTR_COLD;
// 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;
diff --git a/src/devices/bus/c64/simons_basic.h b/src/devices/bus/c64/simons_basic.h
index 63d2dfb5cb9..b71c6b3d553 100644
--- a/src/devices/bus/c64/simons_basic.h
+++ b/src/devices/bus/c64/simons_basic.h
@@ -31,8 +31,8 @@ public:
protected:
// device-level overrides
- virtual void device_start() override;
- virtual void device_reset() override;
+ virtual void device_start() override ATTR_COLD;
+ virtual void device_reset() override ATTR_COLD;
// 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;
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/speakeasy.h b/src/devices/bus/c64/speakeasy.h
index 0816e4caa2e..5ddf33fec13 100644
--- a/src/devices/bus/c64/speakeasy.h
+++ b/src/devices/bus/c64/speakeasy.h
@@ -30,10 +30,10 @@ public:
protected:
// device-level overrides
- virtual void device_start() override;
+ virtual void device_start() override ATTR_COLD;
// optional information overrides
- virtual void device_add_mconfig(machine_config &config) override;
+ virtual void device_add_mconfig(machine_config &config) override ATTR_COLD;
// 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;
diff --git a/src/devices/bus/c64/stardos.cpp b/src/devices/bus/c64/stardos.cpp
index 601ada2778c..609d6bd614a 100644
--- a/src/devices/bus/c64/stardos.cpp
+++ b/src/devices/bus/c64/stardos.cpp
@@ -53,7 +53,7 @@ DEFINE_DEVICE_TYPE(C64_STARDOS, c64_stardos_cartridge_device, "c64_stardos", "C6
static INPUT_PORTS_START( c64_stardos )
PORT_START("RESET")
- PORT_BIT( 0x01, IP_ACTIVE_LOW, IPT_OTHER ) PORT_NAME("Reset") PORT_CODE(KEYCODE_F11) PORT_WRITE_LINE_DEVICE_MEMBER(DEVICE_SELF_OWNER, c64_expansion_slot_device, reset_w)
+ PORT_BIT( 0x01, IP_ACTIVE_LOW, IPT_OTHER ) PORT_NAME("Reset") PORT_CODE(KEYCODE_F11) PORT_WRITE_LINE_DEVICE_MEMBER(DEVICE_SELF_OWNER, FUNC(c64_expansion_slot_device::reset_w))
INPUT_PORTS_END
diff --git a/src/devices/bus/c64/stardos.h b/src/devices/bus/c64/stardos.h
index 9be9f599957..ca6aea021d2 100644
--- a/src/devices/bus/c64/stardos.h
+++ b/src/devices/bus/c64/stardos.h
@@ -6,8 +6,8 @@
**********************************************************************/
-#ifndef MAME_BUS_C4_STARDOS_H
-#define MAME_BUS_C4_STARDOS_H
+#ifndef MAME_BUS_C64_STARDOS_H
+#define MAME_BUS_C64_STARDOS_H
#pragma once
@@ -31,11 +31,11 @@ public:
c64_stardos_cartridge_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;
+ virtual ioport_constructor device_input_ports() const override ATTR_COLD;
protected:
// device-level overrides
- virtual void device_start() override;
+ virtual void device_start() override ATTR_COLD;
// 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;
@@ -56,4 +56,4 @@ private:
DECLARE_DEVICE_TYPE(C64_STARDOS, c64_stardos_cartridge_device)
-#endif // MAME_BUS_C4_STARDOS_H
+#endif // MAME_BUS_C64_STARDOS_H
diff --git a/src/devices/bus/c64/std.cpp b/src/devices/bus/c64/std.cpp
index 08f4c1d65e0..127f0bf235c 100644
--- a/src/devices/bus/c64/std.cpp
+++ b/src/devices/bus/c64/std.cpp
@@ -49,19 +49,19 @@ void c64_standard_cartridge_device::device_start()
uint8_t c64_standard_cartridge_device::c64_cd_r(offs_t offset, uint8_t data, int sphi2, int ba, int roml, int romh, int io1, int io2)
{
- if (!roml && m_roml.bytes())
+ if (!roml && m_roml)
{
- data = m_roml[offset & m_roml.mask()];
+ data = m_roml[offset & (m_roml_size - 1)];
}
else if (!romh)
{
- if (m_romh.bytes())
+ if (m_romh)
{
- data = m_romh[offset & m_romh.mask()];
+ data = m_romh[offset & (m_romh_size - 1)];
}
- else if (m_roml.mask() == 0x3fff)
+ else if (m_roml)
{
- data = m_roml[offset & m_roml.mask()];
+ data = m_roml[offset & (m_roml_size - 1)];
}
}
diff --git a/src/devices/bus/c64/std.h b/src/devices/bus/c64/std.h
index 391e9ac973f..19ac1dde847 100644
--- a/src/devices/bus/c64/std.h
+++ b/src/devices/bus/c64/std.h
@@ -31,7 +31,7 @@ public:
protected:
// device-level overrides
- virtual void device_start() override;
+ virtual void device_start() override ATTR_COLD;
// 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;
diff --git a/src/devices/bus/c64/structured_basic.h b/src/devices/bus/c64/structured_basic.h
index 44d370cdb3f..231d231b7ae 100644
--- a/src/devices/bus/c64/structured_basic.h
+++ b/src/devices/bus/c64/structured_basic.h
@@ -31,8 +31,8 @@ public:
protected:
// device-level overrides
- virtual void device_start() override;
- virtual void device_reset() override;
+ virtual void device_start() override ATTR_COLD;
+ virtual void device_reset() override ATTR_COLD;
// 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;
diff --git a/src/devices/bus/c64/super_explode.cpp b/src/devices/bus/c64/super_explode.cpp
index 4ed2456bd2a..b01e2e25fba 100644
--- a/src/devices/bus/c64/super_explode.cpp
+++ b/src/devices/bus/c64/super_explode.cpp
@@ -51,7 +51,7 @@ c64_super_explode_cartridge_device::c64_super_explode_cartridge_device(const mac
void c64_super_explode_cartridge_device::device_start()
{
// allocate timer
- m_exrom_timer = timer_alloc();
+ m_exrom_timer = timer_alloc(FUNC(c64_super_explode_cartridge_device::update_exrom), this);
// state saving
save_item(NAME(m_bank));
@@ -72,10 +72,10 @@ void c64_super_explode_cartridge_device::device_reset()
//-------------------------------------------------
-// device_timer - handler timer events
+// update_exram - update exrom flag for banking
//-------------------------------------------------
-void c64_super_explode_cartridge_device::device_timer(emu_timer &timer, device_timer_id id, int param, void *ptr)
+TIMER_CALLBACK_MEMBER(c64_super_explode_cartridge_device::update_exrom)
{
m_exrom = 1;
}
diff --git a/src/devices/bus/c64/super_explode.h b/src/devices/bus/c64/super_explode.h
index ca3abdeebf5..9e7158f8e0f 100644
--- a/src/devices/bus/c64/super_explode.h
+++ b/src/devices/bus/c64/super_explode.h
@@ -31,14 +31,15 @@ public:
protected:
// device-level overrides
- virtual void device_start() override;
- virtual void device_reset() override;
- virtual void device_timer(emu_timer &timer, device_timer_id id, int param, void *ptr) override;
+ virtual void device_start() override ATTR_COLD;
+ virtual void device_reset() override ATTR_COLD;
// 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;
+ TIMER_CALLBACK_MEMBER(update_exrom);
+
private:
uint8_t m_bank;
diff --git a/src/devices/bus/c64/super_games.h b/src/devices/bus/c64/super_games.h
index 11e4b44046a..4856ce7e034 100644
--- a/src/devices/bus/c64/super_games.h
+++ b/src/devices/bus/c64/super_games.h
@@ -31,8 +31,8 @@ public:
protected:
// device-level overrides
- virtual void device_start() override;
- virtual void device_reset() override;
+ virtual void device_start() override ATTR_COLD;
+ virtual void device_reset() override ATTR_COLD;
// 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;
diff --git a/src/devices/bus/c64/supercpu.cpp b/src/devices/bus/c64/supercpu.cpp
index e0fe2e2a1ea..d7c3653e81f 100644
--- a/src/devices/bus/c64/supercpu.cpp
+++ b/src/devices/bus/c64/supercpu.cpp
@@ -88,7 +88,7 @@ static INPUT_PORTS_START( c64_supercpu )
PORT_DIPSETTING( 0x00, "Turbo" )
PORT_START("RESET")
- PORT_BIT( 0x01, IP_ACTIVE_LOW, IPT_OTHER ) PORT_NAME("Reset") PORT_CODE(KEYCODE_F11) PORT_WRITE_LINE_DEVICE_MEMBER(DEVICE_SELF_OWNER, c64_expansion_slot_device, reset_w)
+ PORT_BIT( 0x01, IP_ACTIVE_LOW, IPT_OTHER ) PORT_NAME("Reset") PORT_CODE(KEYCODE_F11) PORT_WRITE_LINE_DEVICE_MEMBER(DEVICE_SELF_OWNER, FUNC(c64_expansion_slot_device::reset_w))
INPUT_PORTS_END
diff --git a/src/devices/bus/c64/supercpu.h b/src/devices/bus/c64/supercpu.h
index 73982328c31..78bba5e6f68 100644
--- a/src/devices/bus/c64/supercpu.h
+++ b/src/devices/bus/c64/supercpu.h
@@ -31,13 +31,13 @@ public:
protected:
// device-level overrides
- virtual void device_start() override;
- virtual void device_reset() override;
+ virtual void device_start() override ATTR_COLD;
+ virtual void device_reset() override ATTR_COLD;
// optional information 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 const tiny_rom_entry *device_rom_region() const override ATTR_COLD;
+ virtual void device_add_mconfig(machine_config &config) override ATTR_COLD;
+ virtual ioport_constructor device_input_ports() const override ATTR_COLD;
// 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;
@@ -52,7 +52,7 @@ private:
required_shared_ptr<uint8_t> m_sram;
required_shared_ptr<uint8_t> m_dimm;
- void c64_supercpu_map(address_map &map);
+ void c64_supercpu_map(address_map &map) ATTR_COLD;
};
diff --git a/src/devices/bus/c64/sw8k.h b/src/devices/bus/c64/sw8k.h
index 186e96792d6..cb82fb1b9a5 100644
--- a/src/devices/bus/c64/sw8k.h
+++ b/src/devices/bus/c64/sw8k.h
@@ -30,12 +30,12 @@ public:
c64_switchable_8k_cartridge_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;
+ virtual ioport_constructor device_input_ports() const override ATTR_COLD;
protected:
// device-level overrides
- virtual void device_start() override;
- virtual void device_reset() override;
+ virtual void device_start() override ATTR_COLD;
+ virtual void device_reset() override ATTR_COLD;
// 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;
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..a5e741dd2c2 100644
--- a/src/devices/bus/c64/swiftlink.h
+++ b/src/devices/bus/c64/swiftlink.h
@@ -33,19 +33,19 @@ public:
protected:
// device-level overrides
- virtual void device_start() override;
- virtual void device_reset() override;
+ virtual void device_start() override ATTR_COLD;
+ virtual void device_reset() override ATTR_COLD;
// optional information overrides
- virtual void device_add_mconfig(machine_config &config) override;
- virtual ioport_constructor device_input_ports() const override;
+ virtual void device_add_mconfig(machine_config &config) override ATTR_COLD;
+ virtual ioport_constructor device_input_ports() const override ATTR_COLD;
// 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:
- 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/system3.h b/src/devices/bus/c64/system3.h
index 024798fc77e..fde76522a58 100644
--- a/src/devices/bus/c64/system3.h
+++ b/src/devices/bus/c64/system3.h
@@ -6,8 +6,8 @@
**********************************************************************/
-#ifndef MAME_BUS_BUS_SYSTEM3_H
-#define MAME_BUS_BUS_SYSTEM3_H
+#ifndef MAME_BUS_C64_SYSTEM3_H
+#define MAME_BUS_C64_SYSTEM3_H
#pragma once
@@ -31,8 +31,8 @@ public:
protected:
// device-level overrides
- virtual void device_start() override;
- virtual void device_reset() override;
+ virtual void device_start() override ATTR_COLD;
+ virtual void device_reset() override ATTR_COLD;
// 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;
diff --git a/src/devices/bus/c64/tdos.h b/src/devices/bus/c64/tdos.h
index 49c1b07651c..f59f8bf2f1b 100644
--- a/src/devices/bus/c64/tdos.h
+++ b/src/devices/bus/c64/tdos.h
@@ -31,12 +31,12 @@ public:
protected:
// device-level overrides
- virtual void device_start() override;
- virtual void device_reset() override;
+ virtual void device_start() override ATTR_COLD;
+ virtual void device_reset() override ATTR_COLD;
// optional information overrides
- virtual void device_add_mconfig(machine_config &config) override;
- virtual ioport_constructor device_input_ports() const override;
+ virtual void device_add_mconfig(machine_config &config) override ATTR_COLD;
+ virtual ioport_constructor device_input_ports() const override ATTR_COLD;
// 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;
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..21511806087
--- /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_TIBDD001_H
+#define MAME_BUS_C64_TIBDD001_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 ATTR_COLD;
+ virtual void device_reset() override ATTR_COLD;
+
+ // optional information overrides
+ virtual void device_add_mconfig(machine_config &config) override ATTR_COLD;
+
+ // 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_TIBDD001_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..bd5f1b05f4e 100644
--- a/src/devices/bus/c64/turbo232.h
+++ b/src/devices/bus/c64/turbo232.h
@@ -33,19 +33,19 @@ public:
protected:
// device-level overrides
- virtual void device_start() override;
- virtual void device_reset() override;
+ virtual void device_start() override ATTR_COLD;
+ virtual void device_reset() override ATTR_COLD;
// optional information overrides
- virtual void device_add_mconfig(machine_config &config) override;
- virtual ioport_constructor device_input_ports() const override;
+ virtual void device_add_mconfig(machine_config &config) override ATTR_COLD;
+ virtual ioport_constructor device_input_ports() const override ATTR_COLD;
// 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:
- 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/c64/user.cpp b/src/devices/bus/c64/user.cpp
index 1a5975ebbf8..e7c7138bd50 100644
--- a/src/devices/bus/c64/user.cpp
+++ b/src/devices/bus/c64/user.cpp
@@ -14,12 +14,12 @@
//-------------------------------------------------
// slot devices
-#include "bus/vic20/4cga.h"
#include "4dxh.h"
#include "4ksa.h"
#include "4tba.h"
#include "bn1541.h"
#include "geocable.h"
+#include "bus/vic20/4cga.h"
#include "bus/vic20/vic1011.h"
void c64_user_port_cards(device_slot_interface &device)
diff --git a/src/devices/bus/c64/vizastar.h b/src/devices/bus/c64/vizastar.h
index 26ec63cd46b..3866da432d8 100644
--- a/src/devices/bus/c64/vizastar.h
+++ b/src/devices/bus/c64/vizastar.h
@@ -31,7 +31,7 @@ public:
protected:
// device-level overrides
- virtual void device_start() override;
+ virtual void device_start() override ATTR_COLD;
// 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;
diff --git a/src/devices/bus/c64/vw64.cpp b/src/devices/bus/c64/vw64.cpp
index bf4d584d40d..81a56e478b8 100644
--- a/src/devices/bus/c64/vw64.cpp
+++ b/src/devices/bus/c64/vw64.cpp
@@ -81,7 +81,7 @@ c64_vizawrite_cartridge_device::c64_vizawrite_cartridge_device(const machine_con
void c64_vizawrite_cartridge_device::device_start()
{
// allocate timer
- m_game_timer = timer_alloc();
+ m_game_timer = timer_alloc(FUNC(c64_vizawrite_cartridge_device::update_game), this);
}
@@ -98,10 +98,11 @@ void c64_vizawrite_cartridge_device::device_reset()
//-------------------------------------------------
-// device_timer - handler timer events
+// update_game - update mapping flags for game
+// data
//-------------------------------------------------
-void c64_vizawrite_cartridge_device::device_timer(emu_timer &timer, device_timer_id id, int param, void *ptr)
+TIMER_CALLBACK_MEMBER(c64_vizawrite_cartridge_device::update_game)
{
m_game = 1;
}
diff --git a/src/devices/bus/c64/vw64.h b/src/devices/bus/c64/vw64.h
index 64287c0c785..dafcd2d58e8 100644
--- a/src/devices/bus/c64/vw64.h
+++ b/src/devices/bus/c64/vw64.h
@@ -31,14 +31,15 @@ public:
protected:
// device-level overrides
- virtual void device_start() override;
- virtual void device_reset() override;
- virtual void device_timer(emu_timer &timer, device_timer_id id, int param, void *ptr) override;
+ virtual void device_start() override ATTR_COLD;
+ virtual void device_reset() override ATTR_COLD;
// 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 int c64_exrom_r(offs_t offset, int sphi2, int ba, int rw) override { return 0; }
+ TIMER_CALLBACK_MEMBER(update_game);
+
private:
emu_timer *m_game_timer;
};
diff --git a/src/devices/bus/c64/warp_speed.cpp b/src/devices/bus/c64/warp_speed.cpp
index ff485c05277..ac5a436fc91 100644
--- a/src/devices/bus/c64/warp_speed.cpp
+++ b/src/devices/bus/c64/warp_speed.cpp
@@ -63,7 +63,7 @@ static INPUT_PORTS_START( c64_warp_speed )
PORT_DIPSETTING( 0x00, "C128" )
PORT_START("SW2")
- PORT_BIT( 0x01, IP_ACTIVE_LOW, IPT_OTHER ) PORT_NAME("Reset") PORT_CODE(KEYCODE_F11) PORT_WRITE_LINE_DEVICE_MEMBER(DEVICE_SELF_OWNER, c64_expansion_slot_device, reset_w)
+ PORT_BIT( 0x01, IP_ACTIVE_LOW, IPT_OTHER ) PORT_NAME("Reset") PORT_CODE(KEYCODE_F11) PORT_WRITE_LINE_DEVICE_MEMBER(DEVICE_SELF_OWNER, FUNC(c64_expansion_slot_device::reset_w))
INPUT_PORTS_END
diff --git a/src/devices/bus/c64/warp_speed.h b/src/devices/bus/c64/warp_speed.h
index d5c61f50f49..9677cf61691 100644
--- a/src/devices/bus/c64/warp_speed.h
+++ b/src/devices/bus/c64/warp_speed.h
@@ -30,12 +30,12 @@ public:
c64_warp_speed_cartridge_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;
+ virtual ioport_constructor device_input_ports() const override ATTR_COLD;
protected:
// device-level overrides
- virtual void device_start() override;
- virtual void device_reset() override;
+ virtual void device_start() override ATTR_COLD;
+ virtual void device_reset() override ATTR_COLD;
// 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;
diff --git a/src/devices/bus/c64/westermann.cpp b/src/devices/bus/c64/westermann.cpp
index ac254733f01..57a752c8fe2 100644
--- a/src/devices/bus/c64/westermann.cpp
+++ b/src/devices/bus/c64/westermann.cpp
@@ -61,17 +61,17 @@ uint8_t c64_westermann_cartridge_device::c64_cd_r(offs_t offset, uint8_t data, i
{
if (!roml)
{
- data = m_roml[offset & m_roml.mask()];
+ data = m_roml[offset & (m_roml_size - 1)];
}
else if (!romh)
{
- if (m_romh.bytes())
+ if (m_romh)
{
- data = m_romh[offset & m_romh.mask()];
+ data = m_romh[offset & (m_romh_size - 1)];
}
else
{
- data = m_roml[offset & m_roml.mask()];
+ data = m_roml[offset & (m_roml_size - 1)];
}
}
else if (!io2)
diff --git a/src/devices/bus/c64/westermann.h b/src/devices/bus/c64/westermann.h
index 4b7b2e4389f..36244f9b295 100644
--- a/src/devices/bus/c64/westermann.h
+++ b/src/devices/bus/c64/westermann.h
@@ -31,8 +31,8 @@ public:
protected:
// device-level overrides
- virtual void device_start() override;
- virtual void device_reset() override;
+ virtual void device_start() override ATTR_COLD;
+ virtual void device_reset() override ATTR_COLD;
// 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;
diff --git a/src/devices/bus/c64/xl80.cpp b/src/devices/bus/c64/xl80.cpp
index 19a2f768a2c..3f467c7ade3 100644
--- a/src/devices/bus/c64/xl80.cpp
+++ b/src/devices/bus/c64/xl80.cpp
@@ -85,12 +85,12 @@ const tiny_rom_entry *c64_xl80_device::device_rom_region() const
MC6845_UPDATE_ROW( c64_xl80_device::crtc_update_row )
{
- const pen_t *pen = m_palette->pens();
+ pen_t const *const pen = m_palette->pens();
for (int column = 0; column < x_count; column++)
{
- uint8_t code = m_ram[((ma + column) & 0x7ff)];
- uint16_t addr = (code << 3) | (ra & 0x07);
+ uint8_t const code = m_ram[((ma + column) & 0x7ff)];
+ uint16_t const addr = (m_case << 10) | ((code & 0x7f) << 3) | (ra & 0x07);
uint8_t data = m_char_rom->base()[addr & 0x7ff];
if (column == cursor_x)
@@ -100,10 +100,10 @@ MC6845_UPDATE_ROW( c64_xl80_device::crtc_update_row )
for (int bit = 0; bit < 8; bit++)
{
- int x = (column * 8) + bit;
- int color = BIT(data, 7) && de;
+ int const x = (column * 8) + bit;
+ int const color = BIT(data ^ code, 7) && de;
- bitmap.pix32(vbp + y, hbp + x) = pen[color];
+ bitmap.pix(vbp + y, hbp + x) = pen[color];
data <<= 1;
}
@@ -138,7 +138,7 @@ void c64_xl80_device::device_add_mconfig(machine_config &config)
m_crtc->set_screen(MC6845_SCREEN_TAG);
m_crtc->set_show_border_area(true);
m_crtc->set_char_width(8);
- m_crtc->set_update_row_callback(FUNC(c64_xl80_device::crtc_update_row), this);
+ m_crtc->set_update_row_callback(FUNC(c64_xl80_device::crtc_update_row));
}
@@ -157,7 +157,8 @@ c64_xl80_device::c64_xl80_device(const machine_config &mconfig, const char *tag,
m_crtc(*this, HD46505SP_TAG),
m_palette(*this, "palette"),
m_char_rom(*this, HD46505SP_TAG),
- m_ram(*this, "ram")
+ m_ram(*this, "ram", RAM_SIZE, ENDIANNESS_LITTLE),
+ m_case(0)
{
}
@@ -168,8 +169,8 @@ c64_xl80_device::c64_xl80_device(const machine_config &mconfig, const char *tag,
void c64_xl80_device::device_start()
{
- // allocate memory
- m_ram.allocate(RAM_SIZE);
+ // state saving
+ save_item(NAME(m_case));
}
@@ -188,20 +189,17 @@ void c64_xl80_device::device_reset()
uint8_t c64_xl80_device::c64_cd_r(offs_t offset, uint8_t data, int sphi2, int ba, int roml, int romh, int io1, int io2)
{
- if (!io2 && BIT(offset, 2))
+ if (!roml)
{
- if (offset & 0x01)
- {
- data = m_crtc->register_r();
- }
- }
- else if (offset >= 0x8000 && offset < 0x9000)
- {
- data = m_roml[offset & 0xfff];
+ if (BIT(offset, 12))
+ data = m_ram[offset & 0x7ff];
+ else
+ data = m_roml[offset & 0xfff];
}
- else if (offset >= 0x9800 && offset < 0xa000)
+ else if (!io2 && !BIT(offset, 1))
{
- data = m_ram[offset & 0x7ff];
+ if (BIT(offset, 0))
+ data = m_crtc->register_r();
}
return data;
@@ -218,15 +216,16 @@ void c64_xl80_device::c64_cd_w(offs_t offset, uint8_t data, int sphi2, int ba, i
{
m_ram[offset & 0x7ff] = data;
}
- else if (!io2 && BIT(offset, 2))
+ else if (!io2 && !BIT(offset, 1))
{
- if (offset & 0x01)
- {
- m_crtc->register_w(data);
- }
- else
- {
+ if (!BIT(offset, 0))
m_crtc->address_w(data);
- }
+ else
+ m_crtc->register_w(data);
+ }
+ else if (!io2)
+ {
+ m_case = BIT(data, 0);
+ // BIT(data, 2); // unknown
}
}
diff --git a/src/devices/bus/c64/xl80.h b/src/devices/bus/c64/xl80.h
index 70a9b1cba9d..8f9b7124e64 100644
--- a/src/devices/bus/c64/xl80.h
+++ b/src/devices/bus/c64/xl80.h
@@ -33,18 +33,16 @@ public:
protected:
// device-level overrides
- virtual void device_start() override;
- virtual void device_reset() override;
+ virtual void device_start() override ATTR_COLD;
+ virtual void device_reset() override ATTR_COLD;
// optional information overrides
- virtual const tiny_rom_entry *device_rom_region() const override;
- virtual void device_add_mconfig(machine_config &config) override;
+ virtual const tiny_rom_entry *device_rom_region() const override ATTR_COLD;
+ virtual void device_add_mconfig(machine_config &config) override ATTR_COLD;
// 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;
- virtual int c64_game_r(offs_t offset, int sphi2, int ba, int rw) override { return 1; }
- virtual int c64_exrom_r(offs_t offset, int sphi2, int ba, int rw) override { return 0; }
private:
MC6845_UPDATE_ROW( crtc_update_row );
@@ -52,7 +50,8 @@ private:
required_device<hd6845s_device> m_crtc;
required_device<palette_device> m_palette;
required_memory_region m_char_rom;
- optional_shared_ptr<uint8_t> m_ram;
+ memory_share_creator<uint8_t> m_ram;
+ int m_case;
};
diff --git a/src/devices/bus/c64/z80videopak.cpp b/src/devices/bus/c64/z80videopak.cpp
new file mode 100644
index 00000000000..fc6c3544b2c
--- /dev/null
+++ b/src/devices/bus/c64/z80videopak.cpp
@@ -0,0 +1,213 @@
+// license:BSD-3-Clause
+// copyright-holders:Curt Coder, smf
+/*
+
+Z80 Video Pak
+(c) 1983 Data 20 Corporation
+
+*/
+
+#include "emu.h"
+#include "z80videopak.h"
+#include "screen.h"
+
+
+
+//**************************************************************************
+// MACROS/CONSTANTS
+//**************************************************************************
+
+#define RAM_SIZE 0x800
+
+#define HD46505SP_TAG "mc6845"
+#define MC6845_SCREEN_TAG "screen80"
+
+
+
+//**************************************************************************
+// DEVICE DEFINITIONS
+//**************************************************************************
+
+DEFINE_DEVICE_TYPE(C64_Z80VIDEOPAK, c64_z80videopak_device, "c64_z80videopak", "Data20 Z80 Video Pak")
+
+
+//-------------------------------------------------
+// ROM( c64_z80videopak )
+//-------------------------------------------------
+
+ROM_START( c64_z80videopak )
+ ROM_REGION( 0x800, HD46505SP_TAG, 0 )
+ ROM_LOAD( "c68297 vid pak cg.u18", 0x000, 0x800, CRC(9edf5e58) SHA1(4b244e6d94a7653a2e52c351589f0b469119fb04) )
+ROM_END
+
+
+//-------------------------------------------------
+// rom_region - device-specific ROM region
+//-------------------------------------------------
+
+const tiny_rom_entry *c64_z80videopak_device::device_rom_region() const
+{
+ return ROM_NAME( c64_z80videopak );
+}
+
+//-------------------------------------------------
+// mc6845
+//-------------------------------------------------
+
+MC6845_UPDATE_ROW( c64_z80videopak_device::crtc_update_row )
+{
+ pen_t const *const pen = m_palette->pens();
+
+ for (int column = 0; column < x_count; column++)
+ {
+ uint8_t const code = m_ram[((ma + column) & 0x7ff)];
+ uint16_t const addr = (m_case << 10) | ((code & 0x7f) << 3) | (ra & 0x07);
+ uint8_t data = m_char_rom->base()[addr & 0x7ff];
+
+ if (column == cursor_x)
+ {
+ data = 0xff;
+ }
+
+ for (int bit = 0; bit < 8; bit++)
+ {
+ int const x = (column * 8) + bit;
+ int const color = BIT(data ^ code, 7) && de;
+
+ bitmap.pix(vbp + y, hbp + x) = pen[color];
+
+ data <<= 1;
+ }
+ }
+}
+
+//-------------------------------------------------
+// GFXDECODE( c64_videopak )
+//-------------------------------------------------
+
+static GFXDECODE_START( gfx_c64_z80videopak )
+ GFXDECODE_ENTRY(HD46505SP_TAG, 0x0000, gfx_8x8x1, 0, 1)
+GFXDECODE_END
+
+
+//-------------------------------------------------
+// device_add_mconfig - add device configuration
+//-------------------------------------------------
+
+void c64_z80videopak_device::device_add_mconfig(machine_config &config)
+{
+ c64_cpm_cartridge_device::device_add_mconfig(config);
+
+ screen_device &screen(SCREEN(config, MC6845_SCREEN_TAG, SCREEN_TYPE_RASTER, rgb_t::white()));
+ screen.set_screen_update(HD46505SP_TAG, FUNC(hd6845s_device::screen_update));
+ screen.set_size(80*8, 24*8);
+ screen.set_visarea(0, 80*8-1, 0, 24*8-1);
+ screen.set_refresh_hz(50);
+
+ GFXDECODE(config, "gfxdecode", m_palette, gfx_c64_z80videopak);
+ PALETTE(config, m_palette, palette_device::MONOCHROME);
+
+ HD6845S(config, m_crtc, XTAL(14'318'181) / 8);
+ m_crtc->set_screen(MC6845_SCREEN_TAG);
+ m_crtc->set_show_border_area(true);
+ m_crtc->set_char_width(8);
+ m_crtc->set_update_row_callback(FUNC(c64_z80videopak_device::crtc_update_row));
+}
+
+
+
+//**************************************************************************
+// LIVE DEVICE
+//**************************************************************************
+
+//-------------------------------------------------
+// c64_z80videopak_device - constructor
+//-------------------------------------------------
+
+c64_z80videopak_device::c64_z80videopak_device(const machine_config& mconfig, const char* tag, device_t* owner, uint32_t clock) :
+ c64_cpm_cartridge_device(mconfig, C64_Z80VIDEOPAK, tag, owner, clock),
+ m_crtc(*this, HD46505SP_TAG),
+ m_palette(*this, "palette"),
+ m_char_rom(*this, HD46505SP_TAG),
+ m_ram(*this, "ram", RAM_SIZE, ENDIANNESS_LITTLE)
+{
+}
+
+
+//-------------------------------------------------
+// device_start - device-specific startup
+//-------------------------------------------------
+
+void c64_z80videopak_device::device_start()
+{
+ // state saving
+ save_item(NAME(m_case));
+
+ c64_cpm_cartridge_device::device_start();
+}
+
+
+//-------------------------------------------------
+// device_reset - device-specific reset
+//-------------------------------------------------
+
+void c64_z80videopak_device::device_reset()
+{
+ m_case = 0;
+ m_exrom = 0;
+
+ c64_cpm_cartridge_device::device_reset();
+}
+
+
+//-------------------------------------------------
+// c64_cd_r - cartridge data read
+//-------------------------------------------------
+
+uint8_t c64_z80videopak_device::c64_cd_r(offs_t offset, uint8_t data, int sphi2, int ba, int roml, int romh, int io1, int io2)
+{
+ if (!roml)
+ {
+ if (BIT(offset, 11))
+ data = m_ram[offset & 0x7ff];
+ else
+ data = m_roml[offset & 0x7ff];
+ }
+ else if (!io2 && !BIT(offset, 1))
+ {
+ if (BIT(offset, 0))
+ data = m_crtc->register_r();
+ }
+
+ return data;
+}
+
+
+//-------------------------------------------------
+// c64_cd_w - cartridge data write
+//-------------------------------------------------
+
+void c64_z80videopak_device::c64_cd_w(offs_t offset, uint8_t data, int sphi2, int ba, int roml, int romh, int io1, int io2)
+{
+ c64_cpm_cartridge_device::c64_cd_w(offset, data, sphi2, ba, roml, romh, io1, io2);
+
+ if ((!m_exrom && offset >= 0x9800 && offset < 0xa000) ||
+ (m_exrom && offset >= 0xf800 && offset < 0x10000))
+ {
+ m_ram[offset & 0x7ff] = data;
+ }
+ else if (!io2 && !BIT(offset, 1))
+ {
+ if (!BIT(offset, 0))
+ m_crtc->address_w(data);
+ else
+ m_crtc->register_w(data);
+ }
+ else if (!io2)
+ {
+ m_case = BIT(data, 0);
+ // BIT(data, 1); // unknown
+ // BIT(data, 2); // unknown
+ m_exrom = BIT(data, 4);
+ }
+}
diff --git a/src/devices/bus/c64/z80videopak.h b/src/devices/bus/c64/z80videopak.h
new file mode 100644
index 00000000000..d35b298755c
--- /dev/null
+++ b/src/devices/bus/c64/z80videopak.h
@@ -0,0 +1,61 @@
+// license:BSD-3-Clause
+// copyright-holders:Curt Coder, smf
+/**********************************************************************
+
+ Z80 Video Pak cartridge emulation
+
+**********************************************************************/
+
+#ifndef MAME_BUS_C64_Z80VIDEOPAK_H
+#define MAME_BUS_C64_Z80VIDEOPAK_H
+
+#pragma once
+
+
+#include "cpm.h"
+#include "video/mc6845.h"
+#include "emupal.h"
+
+
+
+//**************************************************************************
+// TYPE DEFINITIONS
+//**************************************************************************
+
+// ======================> c64_z80videopak_device
+
+class c64_z80videopak_device : public c64_cpm_cartridge_device
+{
+public:
+ // construction/destruction
+ c64_z80videopak_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
+
+protected:
+ // device-level overrides
+ virtual void device_start() override ATTR_COLD;
+ virtual void device_reset() override ATTR_COLD;
+
+ // optional information overrides
+ virtual const tiny_rom_entry *device_rom_region() const override ATTR_COLD;
+ virtual void device_add_mconfig(machine_config &config) override ATTR_COLD;
+
+ // 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:
+ MC6845_UPDATE_ROW( crtc_update_row );
+
+ required_device<hd6845s_device> m_crtc;
+ required_device<palette_device> m_palette;
+ required_memory_region m_char_rom;
+ memory_share_creator<uint8_t> m_ram;
+ int m_case;
+};
+
+
+// device type definition
+DECLARE_DEVICE_TYPE(C64_Z80VIDEOPAK, c64_z80videopak_device)
+
+
+#endif // MAME_BUS_C64_Z80VIDEOPAK_H
diff --git a/src/devices/bus/c64/zaxxon.h b/src/devices/bus/c64/zaxxon.h
index 8e47d4caff7..e71135ee7c2 100644
--- a/src/devices/bus/c64/zaxxon.h
+++ b/src/devices/bus/c64/zaxxon.h
@@ -31,7 +31,7 @@ public:
protected:
// device-level overrides
- virtual void device_start() override;
+ virtual void device_start() override ATTR_COLD;
// 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;
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..5c6640ff43e
--- /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 ATTR_COLD;
+
+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 ATTR_COLD;
+};
+
+// 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..cce1effae96
--- /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 ATTR_COLD;
+
+ 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/24k.cpp b/src/devices/bus/cbm2/24k.cpp
index c212b2fef83..c56474c7be9 100644
--- a/src/devices/bus/cbm2/24k.cpp
+++ b/src/devices/bus/cbm2/24k.cpp
@@ -30,7 +30,7 @@ DEFINE_DEVICE_TYPE(CBM2_24K, cbm2_24k_cartridge_device, "cbm2_24k", "CBM-II 24K
cbm2_24k_cartridge_device::cbm2_24k_cartridge_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) :
device_t(mconfig, CBM2_24K, tag, owner, clock),
device_cbm2_expansion_card_interface(mconfig, *this),
- m_ram(*this, "ram")
+ m_ram(*this, "ram", 0x6000, ENDIANNESS_LITTLE)
{
}
@@ -41,7 +41,6 @@ cbm2_24k_cartridge_device::cbm2_24k_cartridge_device(const machine_config &mconf
void cbm2_24k_cartridge_device::device_start()
{
- m_ram.allocate(0x6000);
}
diff --git a/src/devices/bus/cbm2/24k.h b/src/devices/bus/cbm2/24k.h
index b1c029c5254..31f249528df 100644
--- a/src/devices/bus/cbm2/24k.h
+++ b/src/devices/bus/cbm2/24k.h
@@ -30,13 +30,13 @@ public:
protected:
// device-level overrides
- virtual void device_start() override;
+ virtual void device_start() override ATTR_COLD;
// device_cbm2_expansion_card_interface overrides
virtual uint8_t cbm2_bd_r(offs_t offset, uint8_t data, int csbank1, int csbank2, int csbank3) override;
virtual void cbm2_bd_w(offs_t offset, uint8_t data, int csbank1, int csbank2, int csbank3) override;
- optional_shared_ptr<uint8_t> m_ram;
+ memory_share_creator<uint8_t> m_ram;
};
diff --git a/src/devices/bus/cbm2/exp.cpp b/src/devices/bus/cbm2/exp.cpp
index bcc2a654060..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>
+
//**************************************************************************
@@ -35,11 +37,8 @@ DEFINE_DEVICE_TYPE(CBM2_EXPANSION_SLOT, cbm2_expansion_slot_device, "cbm2_expans
// device_cbm2_expansion_card_interface - constructor
//-------------------------------------------------
-device_cbm2_expansion_card_interface::device_cbm2_expansion_card_interface(const machine_config &mconfig, device_t &device)
- : device_slot_card_interface(mconfig, device),
- m_bank1(*this, "bank1"),
- m_bank2(*this, "bank2"),
- m_bank3(*this, "bank3")
+device_cbm2_expansion_card_interface::device_cbm2_expansion_card_interface(const machine_config &mconfig, device_t &device) :
+ device_interface(device, "cbm2exp")
{
m_slot = dynamic_cast<cbm2_expansion_slot_device *>(device.owner());
}
@@ -65,8 +64,8 @@ device_cbm2_expansion_card_interface::~device_cbm2_expansion_card_interface()
cbm2_expansion_slot_device::cbm2_expansion_slot_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) :
device_t(mconfig, CBM2_EXPANSION_SLOT, tag, owner, clock),
- device_slot_interface(mconfig, *this),
- device_image_interface(mconfig, *this),
+ device_single_card_slot_interface<device_cbm2_expansion_card_interface>(mconfig, *this),
+ device_cartrom_image_interface(mconfig, *this),
m_card(nullptr)
{
}
@@ -78,24 +77,7 @@ cbm2_expansion_slot_device::cbm2_expansion_slot_device(const machine_config &mco
void cbm2_expansion_slot_device::device_start()
{
- m_card = dynamic_cast<device_cbm2_expansion_card_interface *>(get_card_device());
-
- // inherit bus clock
- if (clock() == 0)
- {
- cbm2_expansion_slot_device *root = machine().device<cbm2_expansion_slot_device>(CBM2_EXPANSION_SLOT_TAG);
- assert(root);
- set_unscaled_clock(root->clock());
- }
-}
-
-
-//-------------------------------------------------
-// device_reset - device-specific reset
-//-------------------------------------------------
-
-void cbm2_expansion_slot_device::device_reset()
-{
+ m_card = get_card_device();
}
@@ -103,30 +85,41 @@ void cbm2_expansion_slot_device::device_reset()
// 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.allocate(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.allocate(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.allocate(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
@@ -137,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 4d905225299..fdf3c5a7305 100644
--- a/src/devices/bus/cbm2/exp.h
+++ b/src/devices/bus/cbm2/exp.h
@@ -29,18 +29,11 @@
#pragma once
-#include "softlist_dev.h"
+#include "imagedev/cartrom.h"
//**************************************************************************
-// CONSTANTS
-//**************************************************************************
-
-#define CBM2_EXPANSION_SLOT_TAG "exp"
-
-
-//**************************************************************************
// TYPE DEFINITIONS
//**************************************************************************
@@ -49,8 +42,8 @@
class device_cbm2_expansion_card_interface;
class cbm2_expansion_slot_device : public device_t,
- public device_slot_interface,
- public device_image_interface
+ public device_single_card_slot_interface<device_cbm2_expansion_card_interface>,
+ public device_cartrom_image_interface
{
public:
// construction/destruction
@@ -73,25 +66,17 @@ public:
int phi2() { return clock(); }
protected:
- // device-level overrides
- virtual void device_start() override;
- virtual void device_reset() override;
-
- // image-level overrides
- virtual image_init_result call_load() override;
- virtual const software_list_loader &get_software_list_loader() const override { return rom_software_list_loader::instance(); }
+ // device_t implementation
+ virtual void device_start() override ATTR_COLD;
- virtual iodevice_t image_type() const override { return IO_CARTSLOT; }
+ // device_image_interface implementation
+ virtual std::pair<std::error_condition, std::string> call_load() override;
- virtual bool is_readable() const override { return 1; }
- virtual bool is_writeable() const override { return 0; }
- virtual bool is_creatable() const override { return 0; }
- virtual bool must_be_loaded() const override { return 0; }
- virtual bool is_reset_on_load() const override { return 1; }
- virtual const char *image_interface() const override { return "cbm2_cart"; }
- virtual const char *file_extensions() const override { return "20,40,60"; }
+ 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;
@@ -100,7 +85,7 @@ protected:
// ======================> device_cbm2_expansion_card_interface
-class device_cbm2_expansion_card_interface : public device_slot_card_interface
+class device_cbm2_expansion_card_interface : public device_interface
{
friend class cbm2_expansion_slot_device;
@@ -108,15 +93,15 @@ public:
// construction/destruction
virtual ~device_cbm2_expansion_card_interface();
- virtual uint8_t cbm2_bd_r(offs_t offset, uint8_t data, int csbank1, int csbank2, int csbank3) { return data; };
- virtual void cbm2_bd_w(offs_t offset, uint8_t data, int csbank1, int csbank2, int csbank3) { };
+ virtual uint8_t cbm2_bd_r(offs_t offset, uint8_t data, int csbank1, int csbank2, int csbank3) { return data; }
+ virtual void cbm2_bd_w(offs_t offset, uint8_t data, int csbank1, int csbank2, int csbank3) { }
protected:
device_cbm2_expansion_card_interface(const machine_config &mconfig, device_t &device);
- optional_shared_ptr<uint8_t> m_bank1;
- optional_shared_ptr<uint8_t> m_bank2;
- optional_shared_ptr<uint8_t> m_bank3;
+ std::unique_ptr<uint8_t[]> m_bank1;
+ std::unique_ptr<uint8_t[]> m_bank2;
+ std::unique_ptr<uint8_t[]> m_bank3;
cbm2_expansion_slot_device *m_slot;
};
diff --git a/src/devices/bus/cbm2/hrg.h b/src/devices/bus/cbm2/hrg.h
index 3b6a20c94e8..51ce00aa648 100644
--- a/src/devices/bus/cbm2/hrg.h
+++ b/src/devices/bus/cbm2/hrg.h
@@ -27,15 +27,15 @@ class cbm2_hrg_device : public device_t,
{
public:
// optional information overrides
- virtual const tiny_rom_entry *device_rom_region() const override;
+ virtual const tiny_rom_entry *device_rom_region() const override ATTR_COLD;
protected:
// construction/destruction
cbm2_hrg_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_start() override ATTR_COLD;
+ virtual void device_reset() override ATTR_COLD;
// device_cbm2_expansion_card_interface overrides
virtual uint8_t cbm2_bd_r(offs_t offset, uint8_t data, int csbank1, int csbank2, int csbank3) override;
@@ -58,10 +58,10 @@ public:
protected:
// optional information overrides
- virtual void device_add_mconfig(machine_config &config) override;
+ virtual void device_add_mconfig(machine_config &config) override ATTR_COLD;
private:
- void hrg_a_map(address_map &map);
+ void hrg_a_map(address_map &map) ATTR_COLD;
};
@@ -75,10 +75,10 @@ public:
protected:
// optional information overrides
- virtual void device_add_mconfig(machine_config &config) override;
+ virtual void device_add_mconfig(machine_config &config) override ATTR_COLD;
private:
- void hrg_b_map(address_map &map);
+ void hrg_b_map(address_map &map) ATTR_COLD;
};
diff --git a/src/devices/bus/cbm2/std.cpp b/src/devices/bus/cbm2/std.cpp
index f56226028ee..51653c72755 100644
--- a/src/devices/bus/cbm2/std.cpp
+++ b/src/devices/bus/cbm2/std.cpp
@@ -49,17 +49,17 @@ void cbm2_standard_cartridge_device::device_start()
uint8_t cbm2_standard_cartridge_device::cbm2_bd_r(offs_t offset, uint8_t data, int csbank1, int csbank2, int csbank3)
{
- if (!csbank1 && m_bank1.bytes())
+ if (!csbank1 && m_bank1)
{
- data = m_bank1[offset & m_bank1.mask()];
+ data = m_bank1[offset];
}
- else if (!csbank2 && m_bank2.bytes())
+ else if (!csbank2 && m_bank2)
{
- data = m_bank2[offset & m_bank2.mask()];
+ data = m_bank2[offset];
}
- else if (!csbank3 && m_bank3.bytes())
+ else if (!csbank3 && m_bank3)
{
- data = m_bank3[offset & m_bank3.mask()];
+ data = m_bank3[offset];
}
return data;
diff --git a/src/devices/bus/cbm2/std.h b/src/devices/bus/cbm2/std.h
index ee941ca580a..cb16ee5511a 100644
--- a/src/devices/bus/cbm2/std.h
+++ b/src/devices/bus/cbm2/std.h
@@ -30,7 +30,7 @@ public:
protected:
// device-level overrides
- virtual void device_start() override;
+ virtual void device_start() override ATTR_COLD;
// device_cbm2_expansion_card_interface overrides
virtual uint8_t cbm2_bd_r(offs_t offset, uint8_t data, int csbank1, int csbank2, int csbank3) override;
diff --git a/src/devices/bus/cbm2/user.cpp b/src/devices/bus/cbm2/user.cpp
index eefb9c4d591..8aa9153e30e 100644
--- a/src/devices/bus/cbm2/user.cpp
+++ b/src/devices/bus/cbm2/user.cpp
@@ -28,7 +28,7 @@ DEFINE_DEVICE_TYPE(CBM2_USER_PORT, cbm2_user_port_device, "cbm2_user_port", "CBM
//-------------------------------------------------
device_cbm2_user_port_interface::device_cbm2_user_port_interface(const machine_config &mconfig, device_t &device) :
- device_slot_card_interface(mconfig,device)
+ device_interface(device, "cbm2user")
{
m_slot = dynamic_cast<cbm2_user_port_device *>(device.owner());
}
@@ -45,11 +45,12 @@ device_cbm2_user_port_interface::device_cbm2_user_port_interface(const machine_c
cbm2_user_port_device::cbm2_user_port_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) :
device_t(mconfig, CBM2_USER_PORT, tag, owner, clock),
- device_slot_interface(mconfig, *this),
+ device_single_card_slot_interface<device_cbm2_user_port_interface>(mconfig, *this),
m_write_irq(*this),
m_write_sp(*this),
m_write_cnt(*this),
- m_write_flag(*this), m_card(nullptr)
+ m_write_flag(*this),
+ m_card(nullptr)
{
}
@@ -60,13 +61,7 @@ cbm2_user_port_device::cbm2_user_port_device(const machine_config &mconfig, cons
void cbm2_user_port_device::device_start()
{
- m_card = dynamic_cast<device_cbm2_user_port_interface *>(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();
+ m_card = get_card_device();
}
diff --git a/src/devices/bus/cbm2/user.h b/src/devices/bus/cbm2/user.h
index 6bb6bba33c6..df31b854c51 100644
--- a/src/devices/bus/cbm2/user.h
+++ b/src/devices/bus/cbm2/user.h
@@ -39,7 +39,7 @@ class cbm2_user_port_device;
// ======================> device_cbm2_user_port_interface
// class representing interface-specific live cbm2_expansion card
-class device_cbm2_user_port_interface : public device_slot_card_interface
+class device_cbm2_user_port_interface : public device_interface
{
public:
virtual uint8_t cbm2_d1_r() { return 0xff; }
@@ -67,8 +67,7 @@ protected:
// ======================> cbm2_user_port_device
-class cbm2_user_port_device : public device_t,
- public device_slot_interface
+class cbm2_user_port_device : public device_t, public device_single_card_slot_interface<device_cbm2_user_port_interface>
{
public:
// construction/destruction
@@ -93,23 +92,23 @@ 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
- virtual void device_start() override;
+ virtual void device_start() override ATTR_COLD;
devcb_write_line m_write_irq;
devcb_write_line m_write_sp;
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/c1526.h b/src/devices/bus/cbmiec/c1526.h
index d5042f283f1..52b7f906a47 100644
--- a/src/devices/bus/cbmiec/c1526.h
+++ b/src/devices/bus/cbmiec/c1526.h
@@ -6,8 +6,8 @@
**********************************************************************/
-#ifndef MAME_BUS_CBMIEC_C1626_H
-#define MAME_BUS_CBMIEC_C1626_H
+#ifndef MAME_BUS_CBMIEC_C1526_H
+#define MAME_BUS_CBMIEC_C1526_H
#pragma once
@@ -30,9 +30,9 @@ protected:
c1526_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;
- virtual void device_reset() override;
- void c1526_mem(address_map &map);
+ virtual void device_start() override ATTR_COLD;
+ virtual void device_reset() override ATTR_COLD;
+ void c1526_mem(address_map &map) ATTR_COLD;
};
@@ -46,9 +46,9 @@ public:
protected:
// optional information 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;
+ virtual void device_add_mconfig(machine_config &config) override ATTR_COLD;
+ virtual ioport_constructor device_input_ports() const override ATTR_COLD;
+ virtual const tiny_rom_entry *device_rom_region() const override ATTR_COLD;
// device_cbm_iec_interface overrides
void cbm_iec_atn(int state) override;
@@ -67,9 +67,9 @@ public:
protected:
// optional information 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;
+ virtual void device_add_mconfig(machine_config &config) override ATTR_COLD;
+ virtual ioport_constructor device_input_ports() const override ATTR_COLD;
+ virtual const tiny_rom_entry *device_rom_region() const override ATTR_COLD;
// device_ieee488_interface overrides
virtual void ieee488_atn(int state) override;
@@ -82,4 +82,4 @@ DECLARE_DEVICE_TYPE(C1526, c1526_device)
DECLARE_DEVICE_TYPE(C4023, c4023_device)
-#endif // MAME_BUS_CBMIEC_C1626_H
+#endif // MAME_BUS_CBMIEC_C1526_H
diff --git a/src/devices/bus/cbmiec/c1541.cpp b/src/devices/bus/cbmiec/c1541.cpp
index 925014ac803..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
@@ -138,8 +136,13 @@
#include "emu.h"
#include "c1541.h"
+
#include "bus/centronics/ctronics.h"
+#include "formats/d64_dsk.h"
+#include "formats/g64_dsk.h"
+#include "formats/fs_cbmdos.h"
+
//**************************************************************************
@@ -161,25 +164,25 @@
// DEVICE DEFINITIONS
//**************************************************************************
-DEFINE_DEVICE_TYPE(C1540, c1540_t, "c1540", "Commodore 1540 Disk Drive")
-DEFINE_DEVICE_TYPE(C1541, c1541_t, "c1541", "Commodore 1541 Disk Drive")
-DEFINE_DEVICE_TYPE(C1541C, c1541c_t, "c1541c", "Commodore 1541C Disk Drive")
-DEFINE_DEVICE_TYPE(C1541II, c1541ii_t, "c1541ii", "Commodore 1541-II Disk Drive")
-DEFINE_DEVICE_TYPE(SX1541, sx1541_t, "sx1541", "SX1541 Disk Drive")
-DEFINE_DEVICE_TYPE(FSD1, fsd1_t, "fsd1", "FSD-1 Disk Drive")
-DEFINE_DEVICE_TYPE(FSD2, fsd2_t, "fsd2", "FSD-2 Disk Drive")
-DEFINE_DEVICE_TYPE(CSD1, csd1_t, "csd1", "CSD-1 Disk Drive")
-DEFINE_DEVICE_TYPE(C1541_DOLPHIN_DOS, c1541_dolphin_dos_t, "c1541dd", "Commodore 1541 Dolphin-DOS 2.0 Disk Drive")
-DEFINE_DEVICE_TYPE(C1541_PROFESSIONAL_DOS_V1, c1541_professional_dos_v1_t, "c1541pd", "Commodore 1541 Professional-DOS v1 Disk Drive")
-DEFINE_DEVICE_TYPE(C1541_PROLOGIC_DOS_CLASSIC, c1541_prologic_dos_classic_t, "c1541pdc", "Commodore 1541 ProLogic-DOS Classic Disk Drive")
-DEFINE_DEVICE_TYPE(INDUS_GT, indus_gt_t, "indusgt", "Indus GT Disk Drive")
-DEFINE_DEVICE_TYPE(TECHNICA, technica_t, "technica", "Westfalia Technica Disk Drive")
-DEFINE_DEVICE_TYPE(BLUE_CHIP, blue_chip_t, "bluechip", "Amtech Blue Chip Disk Drive")
-DEFINE_DEVICE_TYPE(COMMANDER_C2, commander_c2_t, "cmdrc2", "Commander C-II Disk Drive")
-DEFINE_DEVICE_TYPE(ENHANCER_2000, enhancer_2000_t, "enh2000", "Enhancer 2000 Disk Drive")
-DEFINE_DEVICE_TYPE(FD148, fd148_t, "fd148", "Rapid Access FD-148 Disk Drive")
-DEFINE_DEVICE_TYPE(MSD_SD1, msd_sd1_t, "msdsd1", "MSD SD-1 Disk Drive")
-DEFINE_DEVICE_TYPE(MSD_SD2, msd_sd2_t, "msdsd2", "MSD SD-2 Disk Drive")
+DEFINE_DEVICE_TYPE(C1540, c1540_device, "c1540", "Commodore 1540 Disk Drive")
+DEFINE_DEVICE_TYPE(C1541, c1541_device, "c1541", "Commodore 1541 Disk Drive")
+DEFINE_DEVICE_TYPE(C1541C, c1541c_device, "c1541c", "Commodore 1541C Disk Drive")
+DEFINE_DEVICE_TYPE(C1541II, c1541ii_device, "c1541ii", "Commodore 1541-II Disk Drive")
+DEFINE_DEVICE_TYPE(SX1541, sx1541_device, "sx1541", "SX1541 Disk Drive")
+DEFINE_DEVICE_TYPE(FSD1, fsd1_device, "fsd1", "FSD-1 Disk Drive")
+DEFINE_DEVICE_TYPE(FSD2, fsd2_device, "fsd2", "FSD-2 Disk Drive")
+DEFINE_DEVICE_TYPE(CSD1, csd1_device, "csd1", "CSD-1 Disk Drive")
+DEFINE_DEVICE_TYPE(C1541_DOLPHIN_DOS, c1541_dolphin_dos_device, "c1541dd", "Commodore 1541 Dolphin-DOS 2.0 Disk Drive")
+DEFINE_DEVICE_TYPE(C1541_PROFESSIONAL_DOS_V1, c1541_professional_dos_v1_device, "c1541pd", "Commodore 1541 Professional-DOS v1 Disk Drive")
+DEFINE_DEVICE_TYPE(C1541_PROLOGIC_DOS_CLASSIC, c1541_prologic_dos_classic_device, "c1541pdc", "Commodore 1541 ProLogic-DOS Classic Disk Drive")
+DEFINE_DEVICE_TYPE(INDUS_GT, indus_gt_device, "indusgt", "Indus GT Disk Drive")
+DEFINE_DEVICE_TYPE(TECHNICA, technica_device, "technica", "Westfalia Technica Disk Drive")
+DEFINE_DEVICE_TYPE(BLUE_CHIP, blue_chip_device, "bluechip", "Amtech Blue Chip Disk Drive")
+DEFINE_DEVICE_TYPE(COMMANDER_C2, commander_c2_device, "cmdrc2", "Commander C-II Disk Drive")
+DEFINE_DEVICE_TYPE(ENHANCER_2000, enhancer_2000_device, "enh2000", "Enhancer 2000 Disk Drive")
+DEFINE_DEVICE_TYPE(FD148, fd148_device, "fd148", "Rapid Access FD-148 Disk Drive")
+DEFINE_DEVICE_TYPE(MSD_SD1, msd_sd1_device, "msdsd1", "MSD SD-1 Disk Drive")
+DEFINE_DEVICE_TYPE(MSD_SD2, msd_sd2_device, "msdsd2", "MSD SD-2 Disk Drive")
//-------------------------------------------------
@@ -197,7 +200,7 @@ ROM_END
// rom_region - device-specific ROM region
//-------------------------------------------------
-const tiny_rom_entry *c1540_t::device_rom_region() const
+const tiny_rom_entry *c1540_device::device_rom_region() const
{
return ROM_NAME( c1540 );
}
@@ -241,7 +244,7 @@ ROM_END
// rom_region - device-specific ROM region
//-------------------------------------------------
-const tiny_rom_entry *c1541_t::device_rom_region() const
+const tiny_rom_entry *c1541_device::device_rom_region() const
{
return ROM_NAME( c1541 );
}
@@ -265,7 +268,7 @@ ROM_END
// rom_region - device-specific ROM region
//-------------------------------------------------
-const tiny_rom_entry *c1541c_t::device_rom_region() const
+const tiny_rom_entry *c1541c_device::device_rom_region() const
{
return ROM_NAME( c1541c );
}
@@ -291,7 +294,7 @@ ROM_END
// rom_region - device-specific ROM region
//-------------------------------------------------
-const tiny_rom_entry *c1541ii_t::device_rom_region() const
+const tiny_rom_entry *c1541ii_device::device_rom_region() const
{
return ROM_NAME( c1541ii );
}
@@ -319,7 +322,7 @@ ROM_END
// rom_region - device-specific ROM region
//-------------------------------------------------
-const tiny_rom_entry *sx1541_t::device_rom_region() const
+const tiny_rom_entry *sx1541_device::device_rom_region() const
{
return ROM_NAME( sx1541 );
}
@@ -339,7 +342,7 @@ ROM_END
// rom_region - device-specific ROM region
//-------------------------------------------------
-const tiny_rom_entry *fsd1_t::device_rom_region() const
+const tiny_rom_entry *fsd1_device::device_rom_region() const
{
return ROM_NAME( fsd1 );
}
@@ -367,7 +370,7 @@ ROM_END
// rom_region - device-specific ROM region
//-------------------------------------------------
-const tiny_rom_entry *fsd2_t::device_rom_region() const
+const tiny_rom_entry *fsd2_device::device_rom_region() const
{
return ROM_NAME( fsd2 );
}
@@ -388,7 +391,7 @@ ROM_END
// rom_region - device-specific ROM region
//-------------------------------------------------
-const tiny_rom_entry *csd1_t::device_rom_region() const
+const tiny_rom_entry *csd1_device::device_rom_region() const
{
return ROM_NAME( csd1 );
}
@@ -408,7 +411,7 @@ ROM_END
// rom_region - device-specific ROM region
//-------------------------------------------------
-const tiny_rom_entry *c1541_dolphin_dos_t::device_rom_region() const
+const tiny_rom_entry *c1541_dolphin_dos_device::device_rom_region() const
{
return ROM_NAME( c1541dd );
}
@@ -429,7 +432,7 @@ ROM_END
// rom_region - device-specific ROM region
//-------------------------------------------------
-const tiny_rom_entry *c1541_professional_dos_v1_t::device_rom_region() const
+const tiny_rom_entry *c1541_professional_dos_v1_device::device_rom_region() const
{
return ROM_NAME( c1541pd );
}
@@ -454,7 +457,7 @@ ROM_END
// rom_region - device-specific ROM region
//-------------------------------------------------
-const tiny_rom_entry *c1541_prologic_dos_classic_t::device_rom_region() const
+const tiny_rom_entry *c1541_prologic_dos_classic_device::device_rom_region() const
{
return ROM_NAME( c1541pdc );
}
@@ -478,7 +481,7 @@ ROM_END
// rom_region - device-specific ROM region
//-------------------------------------------------
-const tiny_rom_entry *indus_gt_t::device_rom_region() const
+const tiny_rom_entry *indus_gt_device::device_rom_region() const
{
return ROM_NAME( indusgt );
}
@@ -498,7 +501,7 @@ ROM_END
// rom_region - device-specific ROM region
//-------------------------------------------------
-const tiny_rom_entry *technica_t::device_rom_region() const
+const tiny_rom_entry *technica_device::device_rom_region() const
{
return ROM_NAME( technica );
}
@@ -521,7 +524,7 @@ ROM_END
// rom_region - device-specific ROM region
//-------------------------------------------------
-const tiny_rom_entry *blue_chip_t::device_rom_region() const
+const tiny_rom_entry *blue_chip_device::device_rom_region() const
{
return ROM_NAME( bluechip );
}
@@ -542,7 +545,7 @@ ROM_END
// rom_region - device-specific ROM region
//-------------------------------------------------
-const tiny_rom_entry *commander_c2_t::device_rom_region() const
+const tiny_rom_entry *commander_c2_device::device_rom_region() const
{
return ROM_NAME( cmdrc2 );
}
@@ -562,7 +565,7 @@ ROM_END
// rom_region - device-specific ROM region
//-------------------------------------------------
-const tiny_rom_entry *enhancer_2000_t::device_rom_region() const
+const tiny_rom_entry *enhancer_2000_device::device_rom_region() const
{
return ROM_NAME( enh2000 );
}
@@ -582,7 +585,7 @@ ROM_END
// rom_region - device-specific ROM region
//-------------------------------------------------
-const tiny_rom_entry *fd148_t::device_rom_region() const
+const tiny_rom_entry *fd148_device::device_rom_region() const
{
return ROM_NAME( fd148 );
}
@@ -603,7 +606,7 @@ ROM_END
// rom_region - device-specific ROM region
//-------------------------------------------------
-const tiny_rom_entry *msd_sd1_t::device_rom_region() const
+const tiny_rom_entry *msd_sd1_device::device_rom_region() const
{
return ROM_NAME( msdsd1 );
}
@@ -624,7 +627,7 @@ ROM_END
// rom_region - device-specific ROM region
//-------------------------------------------------
-const tiny_rom_entry *msd_sd2_t::device_rom_region() const
+const tiny_rom_entry *msd_sd2_device::device_rom_region() const
{
return ROM_NAME( msdsd2 );
}
@@ -634,7 +637,7 @@ const tiny_rom_entry *msd_sd2_t::device_rom_region() const
// read -
//-------------------------------------------------
-READ8_MEMBER( c1541_prologic_dos_classic_t::read )
+uint8_t c1541_prologic_dos_classic_device::read()
{
return 0;
}
@@ -644,7 +647,7 @@ READ8_MEMBER( c1541_prologic_dos_classic_t::read )
// write -
//-------------------------------------------------
-WRITE8_MEMBER( c1541_prologic_dos_classic_t::write )
+void c1541_prologic_dos_classic_device::write(uint8_t data)
{
}
@@ -653,7 +656,7 @@ WRITE8_MEMBER( c1541_prologic_dos_classic_t::write )
// ADDRESS_MAP( c1541_mem )
//-------------------------------------------------
-void c1541_base_t::c1541_mem(address_map &map)
+void c1541_device_base::c1541_mem(address_map &map)
{
map(0x0000, 0x07ff).mirror(0x6000).ram();
map(0x1800, 0x180f).mirror(0x63f0).m(M6522_0_TAG, FUNC(via6522_device::map));
@@ -666,7 +669,7 @@ void c1541_base_t::c1541_mem(address_map &map)
// ADDRESS_MAP( c1541dd_mem )
//-------------------------------------------------
-void c1541_base_t::c1541dd_mem(address_map &map)
+void c1541_device_base::c1541dd_mem(address_map &map)
{
map(0x0000, 0x07ff).mirror(0x6000).ram();
map(0x1800, 0x180f).mirror(0x63f0).m(M6522_0_TAG, FUNC(via6522_device::map));
@@ -680,7 +683,7 @@ void c1541_base_t::c1541dd_mem(address_map &map)
// ADDRESS_MAP( c1541pd_mem )
//-------------------------------------------------
-void c1541_base_t::c1541pd_mem(address_map &map)
+void c1541_device_base::c1541pd_mem(address_map &map)
{
map(0x0000, 0x07ff).mirror(0x6000).ram();
map(0x1800, 0x180f).mirror(0x63f0).m(M6522_0_TAG, FUNC(via6522_device::map));
@@ -695,34 +698,34 @@ void c1541_base_t::c1541pd_mem(address_map &map)
// ADDRESS_MAP( c1541pdc_mem )
//-------------------------------------------------
-void c1541_prologic_dos_classic_t::c1541pdc_mem(address_map &map)
+void c1541_prologic_dos_classic_device::c1541pdc_mem(address_map &map)
{
- map(0x0000, 0xffff).rw(FUNC(c1541_prologic_dos_classic_t::read), FUNC(c1541_prologic_dos_classic_t::write));
-/* AM_RANGE(0x0000, 0x07ff) AM_MIRROR(0x6000) AM_RAM AM_SHARE("share1")
- AM_RANGE(0x1800, 0x180f) AM_MIRROR(0x63f0) AM_DEVREADWRITE(M6522_0_TAG, via6522_device, read, write)
- AM_RANGE(0x1c00, 0x1c0f) AM_MIRROR(0x63f0) AM_DEVREADWRITE(M6522_1_TAG, via6522_device, read, write)
- AM_RANGE(0x8000, 0x87ff) AM_RAM AM_SHARE("share1")
- AM_RANGE(0x8800, 0x9fff) AM_RAM
- AM_RANGE(0xa000, 0xb7ff) AM_ROM AM_REGION(M6502_TAG, 0x0000)
- AM_RANGE(0xb800, 0xb80f) AM_READWRITE(pia_r, pia_w)
- AM_RANGE(0xf000, 0xffff) AM_ROM AM_REGION(M6502_TAG, 0x2000)*/
+ map(0x0000, 0xffff).rw(FUNC(c1541_prologic_dos_classic_device::read), FUNC(c1541_prologic_dos_classic_device::write));
+/* map(0x0000, 0x07ff).mirror(0x6000).ram().share("share1");
+ map(0x1800, 0x180f).mirror(0x63f0).rw(M6522_0_TAG, FUNC(via6522_device::read), FUNC(via6522_device::write));
+ map(0x1c00, 0x1c0f).mirror(0x63f0).rw(M6522_1_TAG, FUNC(via6522_device::read), FUNC(via6522_device::write));
+ map(0x8000, 0x87ff).ram().share("share1");
+ map(0x8800, 0x9fff).ram();
+ map(0xa000, 0xb7ff).rom().region(M6502_TAG, 0x0000);
+ map(0xb800, 0xb80f).rw(FUNC(c1541_prologic_dos_classic_device::pia_r), FUNC(c1541_prologic_dos_classic_device::pia_w));
+ map(0xf000, 0xffff).rom().region(M6502_TAG, 0x2000);*/
}
-WRITE_LINE_MEMBER( c1541_base_t::via0_irq_w )
+void c1541_device_base::via0_irq_w(int state)
{
m_via0_irq = state;
m_maincpu->set_input_line(INPUT_LINE_IRQ0, (m_via0_irq || m_via1_irq) ? ASSERT_LINE : CLEAR_LINE);
}
-READ8_MEMBER( c1541_base_t::via0_pa_r )
+uint8_t c1541_device_base::via0_pa_r()
{
// dummy read to acknowledge ATN IN interrupt
return m_parallel_data;
}
-WRITE8_MEMBER( c1541_base_t::via0_pa_w )
+void c1541_device_base::via0_pa_w(uint8_t data)
{
if (m_other != nullptr)
{
@@ -730,7 +733,7 @@ WRITE8_MEMBER( c1541_base_t::via0_pa_w )
}
}
-READ8_MEMBER( c1541_base_t::via0_pb_r )
+uint8_t c1541_device_base::via0_pb_r()
{
/*
@@ -747,7 +750,7 @@ READ8_MEMBER( c1541_base_t::via0_pb_r )
*/
- uint8_t data;
+ u8 data;
// data in
data = !m_bus->data_r() && !m_ga->atn_r();
@@ -764,7 +767,7 @@ READ8_MEMBER( c1541_base_t::via0_pb_r )
return data;
}
-WRITE8_MEMBER( c1541_base_t::via0_pb_w )
+void c1541_device_base::via0_pb_w(uint8_t data)
{
/*
@@ -791,7 +794,7 @@ WRITE8_MEMBER( c1541_base_t::via0_pb_w )
m_bus->clk_w(this, !BIT(data, 3));
}
-WRITE_LINE_MEMBER( c1541_base_t::via0_ca2_w )
+void c1541_device_base::via0_ca2_w(int state)
{
if (m_other != nullptr)
{
@@ -799,7 +802,7 @@ WRITE_LINE_MEMBER( c1541_base_t::via0_ca2_w )
}
}
-READ8_MEMBER( c1541c_t::via0_pa_r )
+uint8_t c1541c_device::via0_pa_r()
{
/*
@@ -820,14 +823,14 @@ READ8_MEMBER( c1541c_t::via0_pa_r )
}
-WRITE_LINE_MEMBER( c1541_base_t::via1_irq_w )
+void c1541_device_base::via1_irq_w(int state)
{
m_via1_irq = state;
m_maincpu->set_input_line(INPUT_LINE_IRQ0, (m_via0_irq || m_via1_irq) ? ASSERT_LINE : CLEAR_LINE);
}
-READ8_MEMBER( c1541_base_t::via1_pb_r )
+uint8_t c1541_device_base::via1_pb_r()
{
/*
@@ -844,7 +847,7 @@ READ8_MEMBER( c1541_base_t::via1_pb_r )
*/
- uint8_t data = 0;
+ u8 data = 0;
// write protect sense
data |= !m_floppy->wpt_r() << 4;
@@ -855,7 +858,7 @@ READ8_MEMBER( c1541_base_t::via1_pb_r )
return data;
}
-WRITE8_MEMBER( c1541_base_t::via1_pb_w )
+void c1541_device_base::via1_pb_w(uint8_t data)
{
/*
@@ -890,12 +893,12 @@ WRITE8_MEMBER( c1541_base_t::via1_pb_w )
// C64H156_INTERFACE( ga_intf )
//-------------------------------------------------
-WRITE_LINE_MEMBER( c1541_base_t::atn_w )
+void c1541_device_base::atn_w(int state)
{
set_iec_data();
}
-WRITE_LINE_MEMBER( c1541_base_t::byte_w )
+void c1541_device_base::byte_w(int state)
{
m_maincpu->set_input_line(M6502_SET_OVERFLOW, state);
@@ -907,23 +910,25 @@ WRITE_LINE_MEMBER( c1541_base_t::byte_w )
// FLOPPY_FORMATS( floppy_formats )
//-------------------------------------------------
-FLOPPY_FORMATS_MEMBER( c1541_base_t::floppy_formats )
- FLOPPY_D64_FORMAT,
- FLOPPY_G64_FORMAT
-FLOPPY_FORMATS_END
+void c1541_device_base::floppy_formats(format_registration &fr)
+{
+ fr.add(FLOPPY_D64_FORMAT);
+ fr.add(FLOPPY_G64_FORMAT);
+ fr.add(fs::CBMDOS);
+}
-READ8_MEMBER( c1541_prologic_dos_classic_t::pia_r )
+uint8_t c1541_prologic_dos_classic_device::pia_r(offs_t offset)
{
return m_pia->read((offset >> 2) & 0x03);
}
-WRITE8_MEMBER( c1541_prologic_dos_classic_t::pia_w )
+void c1541_prologic_dos_classic_device::pia_w(offs_t offset, uint8_t data)
{
m_pia->write((offset >> 2) & 0x03, data);
}
-WRITE8_MEMBER( c1541_prologic_dos_classic_t::pia_pa_w )
+void c1541_prologic_dos_classic_device::pia_pa_w(uint8_t data)
{
/*
@@ -941,12 +946,12 @@ WRITE8_MEMBER( c1541_prologic_dos_classic_t::pia_pa_w )
*/
}
-READ8_MEMBER( c1541_prologic_dos_classic_t::pia_pb_r )
+uint8_t c1541_prologic_dos_classic_device::pia_pb_r()
{
return m_parallel_data;
}
-WRITE8_MEMBER( c1541_prologic_dos_classic_t::pia_pb_w )
+void c1541_prologic_dos_classic_device::pia_pb_w(uint8_t data)
{
m_parallel_data = data;
@@ -958,71 +963,71 @@ WRITE8_MEMBER( c1541_prologic_dos_classic_t::pia_pb_w )
// device_add_mconfig - add device configuration
//-------------------------------------------------
-void c1541_base_t::device_add_mconfig(machine_config &config)
+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_base_t::c1541_mem);
- config.m_perfect_cpu_quantum = subtag(M6502_TAG);
-
- VIA6522(config, m_via0, XTAL(16'000'000)/16);
- m_via0->readpa_handler().set(FUNC(c1541_base_t::via0_pa_r));
- m_via0->readpb_handler().set(FUNC(c1541_base_t::via0_pb_r));
- m_via0->writepa_handler().set(FUNC(c1541_base_t::via0_pa_w));
- m_via0->writepb_handler().set(FUNC(c1541_base_t::via0_pb_w));
- m_via0->cb2_handler().set(FUNC(c1541_base_t::via0_ca2_w));
- m_via0->irq_handler().set(FUNC(c1541_base_t::via0_irq_w));
-
- VIA6522(config, m_via1, XTAL(16'000'000)/16);
+ m_maincpu->set_addrmap(AS_PROGRAM, &c1541_device_base::c1541_mem);
+
+ MOS6522(config, m_via0, XTAL(16'000'000)/16);
+ m_via0->readpa_handler().set(FUNC(c1541_device_base::via0_pa_r));
+ m_via0->readpb_handler().set(FUNC(c1541_device_base::via0_pb_r));
+ m_via0->writepa_handler().set(FUNC(c1541_device_base::via0_pa_w));
+ m_via0->writepb_handler().set(FUNC(c1541_device_base::via0_pb_w));
+ m_via0->cb2_handler().set(FUNC(c1541_device_base::via0_ca2_w));
+ m_via0->irq_handler().set(FUNC(c1541_device_base::via0_irq_w));
+
+ MOS6522(config, m_via1, XTAL(16'000'000)/16);
m_via1->readpa_handler().set(C64H156_TAG, FUNC(c64h156_device::yb_r));
- m_via1->readpb_handler().set(FUNC(c1541_base_t::via1_pb_r));
+ m_via1->readpb_handler().set(FUNC(c1541_device_base::via1_pb_r));
m_via1->writepa_handler().set(C64H156_TAG, FUNC(c64h156_device::yb_w));
- m_via1->writepb_handler().set(FUNC(c1541_base_t::via1_pb_w));
+ m_via1->writepb_handler().set(FUNC(c1541_device_base::via1_pb_w));
m_via1->ca2_handler().set(C64H156_TAG, FUNC(c64h156_device::soe_w));
m_via1->cb2_handler().set(C64H156_TAG, FUNC(c64h156_device::oe_w));
- m_via1->irq_handler().set(FUNC(c1541_base_t::via1_irq_w));
+ m_via1->irq_handler().set(FUNC(c1541_device_base::via1_irq_w));
C64H156(config, m_ga, XTAL(16'000'000));
- m_ga->atn_callback().set(FUNC(c1541_base_t::atn_w));
- m_ga->byte_callback().set(FUNC(c1541_base_t::byte_w));
+ m_ga->atn_callback().set(FUNC(c1541_device_base::atn_w));
+ m_ga->byte_callback().set(FUNC(c1541_device_base::byte_w));
floppy_connector &connector(FLOPPY_CONNECTOR(config, C64H156_TAG":0", 0));
connector.option_add("525ssqd", ALPS_3255190X);
connector.set_default_option("525ssqd");
connector.set_fixed(true);
- connector.set_formats(c1541_base_t::floppy_formats);
+ connector.set_formats(c1541_device_base::floppy_formats);
+ connector.enable_sound(true);
}
-void c1541c_t::device_add_mconfig(machine_config &config)
+void c1541c_device::device_add_mconfig(machine_config &config)
{
- c1541_base_t::device_add_mconfig(config);
+ c1541_device_base::device_add_mconfig(config);
}
-void c1541_dolphin_dos_t::device_add_mconfig(machine_config &config)
+void c1541_dolphin_dos_device::device_add_mconfig(machine_config &config)
{
- c1541_base_t::device_add_mconfig(config);
- m_maincpu->set_addrmap(AS_PROGRAM, &c1541_dolphin_dos_t::c1541dd_mem);
+ c1541_device_base::device_add_mconfig(config);
+ m_maincpu->set_addrmap(AS_PROGRAM, &c1541_dolphin_dos_device::c1541dd_mem);
}
-void c1541_professional_dos_v1_t::device_add_mconfig(machine_config &config)
+void c1541_professional_dos_v1_device::device_add_mconfig(machine_config &config)
{
- c1541_base_t::device_add_mconfig(config);
- m_maincpu->set_addrmap(AS_PROGRAM, &c1541_professional_dos_v1_t::c1541pd_mem);
+ c1541_device_base::device_add_mconfig(config);
+ m_maincpu->set_addrmap(AS_PROGRAM, &c1541_professional_dos_v1_device::c1541pd_mem);
}
-void c1541_prologic_dos_classic_t::device_add_mconfig(machine_config &config)
+void c1541_prologic_dos_classic_device::device_add_mconfig(machine_config &config)
{
- c1541_base_t::device_add_mconfig(config);
+ c1541_device_base::device_add_mconfig(config);
- m_maincpu->set_addrmap(AS_PROGRAM, &c1541_prologic_dos_classic_t::c1541pdc_mem);
+ m_maincpu->set_addrmap(AS_PROGRAM, &c1541_prologic_dos_classic_device::c1541pdc_mem);
- PIA6821(config, m_pia, 0);
- m_pia->readpb_handler().set(FUNC(c1541_prologic_dos_classic_t::pia_pb_r));
- m_pia->writepa_handler().set(FUNC(c1541_prologic_dos_classic_t::pia_pa_w));
- m_pia->writepb_handler().set(FUNC(c1541_prologic_dos_classic_t::pia_pb_w));
+ 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));
m_pia->ca2_handler().set(CENTRONICS_TAG, FUNC(centronics_device::write_strobe));
centronics_device &centronics(CENTRONICS(config, CENTRONICS_TAG, centronics_devices, "printer"));
@@ -1051,7 +1056,7 @@ INPUT_PORTS_END
// input_ports - device-specific input ports
//-------------------------------------------------
-ioport_constructor c1541_base_t::device_input_ports() const
+ioport_constructor c1541_device_base::device_input_ports() const
{
return INPUT_PORTS_NAME( c1541 );
}
@@ -1066,7 +1071,7 @@ ioport_constructor c1541_base_t::device_input_ports() const
// set_iec_data -
//-------------------------------------------------
-inline void c1541_base_t::set_iec_data()
+inline void c1541_device_base::set_iec_data()
{
int data = !m_data_out && !m_ga->atn_r();
@@ -1080,10 +1085,10 @@ inline void c1541_base_t::set_iec_data()
//**************************************************************************
//-------------------------------------------------
-// c1541_base_t - constructor
+// c1541_device_base - constructor
//-------------------------------------------------
-c1541_base_t::c1541_base_t(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock) :
+c1541_device_base::c1541_device_base(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, u32 clock) :
device_t(mconfig, type, tag, owner, clock),
device_cbm_iec_interface(mconfig, *this),
device_c64_floppy_parallel_interface(mconfig, *this),
@@ -1102,91 +1107,91 @@ c1541_base_t::c1541_base_t(const machine_config &mconfig, device_type type, cons
//-------------------------------------------------
-// c1540_t - constructor
+// c1540_device - constructor
//-------------------------------------------------
-c1540_t::c1540_t(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
- : c1541_base_t(mconfig, C1540, tag, owner, clock) { }
+c1540_device::c1540_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock)
+ : c1541_device_base(mconfig, C1540, tag, owner, clock) { }
//-------------------------------------------------
-// c1541_t - constructor
+// c1541_device - constructor
//-------------------------------------------------
-c1541_t::c1541_t(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
- : c1541_base_t(mconfig, C1541, tag, owner, clock) { }
+c1541_device::c1541_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock)
+ : c1541_device_base(mconfig, C1541, tag, owner, clock) { }
//-------------------------------------------------
-// c1541c_t - constructor
+// c1541c_device - constructor
//-------------------------------------------------
-c1541c_t::c1541c_t(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
- : c1541_base_t(mconfig, C1541C, tag, owner, clock) { }
+c1541c_device::c1541c_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock)
+ : c1541_device_base(mconfig, C1541C, tag, owner, clock) { }
//-------------------------------------------------
-// c1541ii_t - constructor
+// c1541ii_device - constructor
//-------------------------------------------------
-c1541ii_t::c1541ii_t(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
- : c1541_base_t(mconfig, C1541II, tag, owner, clock) { }
+c1541ii_device::c1541ii_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock)
+ : c1541_device_base(mconfig, C1541II, tag, owner, clock) { }
//-------------------------------------------------
-// sx1541_t - constructor
+// sx1541_device - constructor
//-------------------------------------------------
-sx1541_t::sx1541_t(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
- : c1541_base_t(mconfig, SX1541, tag, owner, clock) { }
+sx1541_device::sx1541_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock)
+ : c1541_device_base(mconfig, SX1541, tag, owner, clock) { }
//-------------------------------------------------
-// fsd1_t - constructor
+// fsd1_device - constructor
//-------------------------------------------------
-fsd1_t::fsd1_t(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
- : c1541_base_t(mconfig, FSD1, tag, owner, clock) { }
+fsd1_device::fsd1_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock)
+ : c1541_device_base(mconfig, FSD1, tag, owner, clock) { }
//-------------------------------------------------
-// fsd2_t - constructor
+// fsd2_device - constructor
//-------------------------------------------------
-fsd2_t::fsd2_t(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
- : c1541_base_t(mconfig, FSD2, tag, owner, clock) { }
+fsd2_device::fsd2_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock)
+ : c1541_device_base(mconfig, FSD2, tag, owner, clock) { }
//-------------------------------------------------
-// csd1_t - constructor
+// csd1_device - constructor
//-------------------------------------------------
-csd1_t::csd1_t(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
- : c1541_base_t(mconfig, CSD1, tag, owner, clock) { }
+csd1_device::csd1_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock)
+ : c1541_device_base(mconfig, CSD1, tag, owner, clock) { }
//-------------------------------------------------
-// c1541_dolphin_dos_t - constructor
+// c1541_dolphin_dos_device - constructor
//-------------------------------------------------
-c1541_dolphin_dos_t::c1541_dolphin_dos_t(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
- : c1541_base_t(mconfig, C1541_DOLPHIN_DOS, tag, owner, clock) { }
+c1541_dolphin_dos_device::c1541_dolphin_dos_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock)
+ : c1541_device_base(mconfig, C1541_DOLPHIN_DOS, tag, owner, clock) { }
//-------------------------------------------------
-// c1541_professional_dos_v1_t - constructor
+// c1541_professional_dos_v1_device - constructor
//-------------------------------------------------
-c1541_professional_dos_v1_t::c1541_professional_dos_v1_t(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
- : c1541_base_t(mconfig, C1541_PROFESSIONAL_DOS_V1, tag, owner, clock) { }
+c1541_professional_dos_v1_device::c1541_professional_dos_v1_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock)
+ : c1541_device_base(mconfig, C1541_PROFESSIONAL_DOS_V1, tag, owner, clock) { }
//-------------------------------------------------
-// c1541_prologic_dos_classic_t - constructor
+// c1541_prologic_dos_classic_device - constructor
//-------------------------------------------------
-c1541_prologic_dos_classic_t::c1541_prologic_dos_classic_t(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
- : c1541_base_t(mconfig, C1541_PROLOGIC_DOS_CLASSIC, tag, owner, clock),
+c1541_prologic_dos_classic_device::c1541_prologic_dos_classic_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock)
+ : c1541_device_base(mconfig, C1541_PROLOGIC_DOS_CLASSIC, tag, owner, clock),
m_pia(*this, MC6821_TAG),
m_cent_data_out(*this, "cent_data_out"),
m_mmu_rom(*this, "mmu")
@@ -1195,74 +1200,74 @@ c1541_prologic_dos_classic_t::c1541_prologic_dos_classic_t(const machine_config
//-------------------------------------------------
-// indus_gt_t - constructor
+// indus_gt_device - constructor
//-------------------------------------------------
-indus_gt_t::indus_gt_t(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
- : c1541_base_t(mconfig, INDUS_GT, tag, owner, clock) { }
+indus_gt_device::indus_gt_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock)
+ : c1541_device_base(mconfig, INDUS_GT, tag, owner, clock) { }
//-------------------------------------------------
-// technica_t - constructor
+// technica_device - constructor
//-------------------------------------------------
-technica_t::technica_t(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
- : c1541_base_t(mconfig, TECHNICA, tag, owner, clock) { }
+technica_device::technica_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock)
+ : c1541_device_base(mconfig, TECHNICA, tag, owner, clock) { }
//-------------------------------------------------
-// blue_chip_t - constructor
+// blue_chip_device - constructor
//-------------------------------------------------
-blue_chip_t::blue_chip_t(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
- : c1541_base_t(mconfig, BLUE_CHIP, tag, owner, clock) { }
+blue_chip_device::blue_chip_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock)
+ : c1541_device_base(mconfig, BLUE_CHIP, tag, owner, clock) { }
//-------------------------------------------------
-// commander_c2_t - constructor
+// commander_c2_device - constructor
//-------------------------------------------------
-commander_c2_t::commander_c2_t(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
- : c1541_base_t(mconfig, COMMANDER_C2, tag, owner, clock) { }
+commander_c2_device::commander_c2_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock)
+ : c1541_device_base(mconfig, COMMANDER_C2, tag, owner, clock) { }
//-------------------------------------------------
-// enhancer_2000_t - constructor
+// enhancer_2000_device - constructor
//-------------------------------------------------
-enhancer_2000_t::enhancer_2000_t(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
- : c1541_base_t(mconfig, ENHANCER_2000, tag, owner, clock) { }
+enhancer_2000_device::enhancer_2000_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock)
+ : c1541_device_base(mconfig, ENHANCER_2000, tag, owner, clock) { }
//-------------------------------------------------
-// fd148_t - constructor
+// fd148_device - constructor
//-------------------------------------------------
-fd148_t::fd148_t(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
- : c1541_base_t(mconfig, FD148, tag, owner, clock) { }
+fd148_device::fd148_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock)
+ : c1541_device_base(mconfig, FD148, tag, owner, clock) { }
//-------------------------------------------------
-// msd_sd1_t - constructor
+// msd_sd1_device - constructor
//-------------------------------------------------
-msd_sd1_t::msd_sd1_t(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
- : c1541_base_t(mconfig, MSD_SD1, tag, owner, clock) { }
+msd_sd1_device::msd_sd1_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock)
+ : c1541_device_base(mconfig, MSD_SD1, tag, owner, clock) { }
//-------------------------------------------------
-// msd_sd2_t - constructor
+// msd_sd2_device - constructor
//-------------------------------------------------
-msd_sd2_t::msd_sd2_t(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
- : c1541_base_t(mconfig, MSD_SD2, tag, owner, clock) { }
+msd_sd2_device::msd_sd2_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock)
+ : c1541_device_base(mconfig, MSD_SD2, tag, owner, clock) { }
//-------------------------------------------------
// device_start - device-specific startup
//-------------------------------------------------
-void c1541_base_t::device_start()
+void c1541_device_base::device_start()
{
m_leds.resolve();
@@ -1275,16 +1280,16 @@ void c1541_base_t::device_start()
save_item(NAME(m_via1_irq));
}
-void fsd2_t::device_start()
+void fsd2_device::device_start()
{
- c1541_base_t::device_start();
+ c1541_device_base::device_start();
// decrypt ROM
- uint8_t *rom = memregion(M6502_TAG)->base();
+ u8 *rom = memregion(M6502_TAG)->base();
for (offs_t offset = 0; offset < 0x4000; offset++)
{
- uint8_t data = bitswap<8>(rom[offset], 7, 6, 5, 3, 4, 2, 1, 0);
+ const u8 data = bitswap<8>(rom[offset], 7, 6, 5, 3, 4, 2, 1, 0);
rom[offset] = data;
}
@@ -1295,7 +1300,7 @@ void fsd2_t::device_start()
// device_reset - device-specific reset
//-------------------------------------------------
-void c1541_base_t::device_reset()
+void c1541_device_base::device_reset()
{
m_maincpu->reset();
@@ -1312,7 +1317,7 @@ void c1541_base_t::device_reset()
// iec_atn_w -
//-------------------------------------------------
-void c1541_base_t::cbm_iec_atn(int state)
+void c1541_device_base::cbm_iec_atn(int state)
{
m_via0->write_ca1(!state);
m_ga->atni_w(!state);
@@ -1325,7 +1330,7 @@ void c1541_base_t::cbm_iec_atn(int state)
// iec_reset_w -
//-------------------------------------------------
-void c1541_base_t::cbm_iec_reset(int state)
+void c1541_device_base::cbm_iec_reset(int state)
{
if (!state)
{
@@ -1338,7 +1343,7 @@ void c1541_base_t::cbm_iec_reset(int state)
// parallel_data_w -
//-------------------------------------------------
-void c1541_base_t::parallel_data_w(uint8_t data)
+void c1541_device_base::parallel_data_w(u8 data)
{
m_parallel_data = data;
}
@@ -1348,7 +1353,7 @@ void c1541_base_t::parallel_data_w(uint8_t data)
// parallel_strobe_w -
//-------------------------------------------------
-void c1541_base_t::parallel_strobe_w(int state)
+void c1541_device_base::parallel_strobe_w(int state)
{
m_via0->write_cb1(state);
}
diff --git a/src/devices/bus/cbmiec/c1541.h b/src/devices/bus/cbmiec/c1541.h
index 0382b62278e..216fd71debf 100644
--- a/src/devices/bus/cbmiec/c1541.h
+++ b/src/devices/bus/cbmiec/c1541.h
@@ -22,48 +22,40 @@
//**************************************************************************
-// MACROS / CONSTANTS
-//**************************************************************************
-
-#define C1541_TAG "c1541"
-
-
-
-//**************************************************************************
// TYPE DEFINITIONS
//**************************************************************************
-// ======================> c1541_base_t
+// ======================> c1541_device_base
-class c1541_base_t : public device_t,
+class c1541_device_base : public device_t,
public device_cbm_iec_interface,
public device_c64_floppy_parallel_interface
{
protected:
// construction/destruction
- c1541_base_t(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock);
+ c1541_device_base(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;
+ virtual void device_start() override ATTR_COLD;
+ virtual void device_reset() override ATTR_COLD;
// optional information overrides
- virtual void device_add_mconfig(machine_config &config) override;
- virtual ioport_constructor device_input_ports() const override;
+ virtual void device_add_mconfig(machine_config &config) override ATTR_COLD;
+ virtual ioport_constructor device_input_ports() const override ATTR_COLD;
// device_cbm_iec_interface overrides
virtual void cbm_iec_atn(int state) override;
virtual void cbm_iec_reset(int state) override;
// device_c64_floppy_parallel_interface overrides
- virtual void parallel_data_w(uint8_t data) override;
+ virtual void parallel_data_w(u8 data) override;
virtual void parallel_strobe_w(int state) override;
required_device<floppy_image_device> m_floppy;
- void c1541_mem(address_map &map);
- void c1541dd_mem(address_map &map);
- void c1541pd_mem(address_map &map);
+ void c1541_mem(address_map &map) ATTR_COLD;
+ void c1541dd_mem(address_map &map) ATTR_COLD;
+ void c1541pd_mem(address_map &map) ATTR_COLD;
required_device<m6502_device> m_maincpu;
@@ -76,19 +68,19 @@ private:
inline void set_iec_data();
- DECLARE_WRITE_LINE_MEMBER( via0_irq_w );
- virtual DECLARE_READ8_MEMBER( via0_pa_r );
- DECLARE_WRITE8_MEMBER( via0_pa_w );
- DECLARE_READ8_MEMBER( via0_pb_r );
- DECLARE_WRITE8_MEMBER( via0_pb_w );
- DECLARE_WRITE_LINE_MEMBER( via0_ca2_w );
- DECLARE_WRITE_LINE_MEMBER( via1_irq_w );
- DECLARE_READ8_MEMBER( via1_pb_r );
- DECLARE_WRITE8_MEMBER( via1_pb_w );
- DECLARE_WRITE_LINE_MEMBER( atn_w );
- DECLARE_WRITE_LINE_MEMBER( byte_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);
+ void via0_ca2_w(int state);
+ void via1_irq_w(int state);
+ uint8_t via1_pb_r();
+ void via1_pb_w(uint8_t data);
+ void atn_w(int state);
+ void byte_w(int state);
- DECLARE_FLOPPY_FORMATS( floppy_formats );
+ static void floppy_formats(format_registration &fr);
required_device<via6522_device> m_via0;
required_device<via6522_device> m_via1;
@@ -105,318 +97,317 @@ private:
};
-// ======================> c1540_t
+// ======================> c1540_device
-class c1540_t : public c1541_base_t
+class c1540_device : public c1541_device_base
{
public:
// construction/destruction
- c1540_t(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
+ c1540_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;
+ virtual const tiny_rom_entry *device_rom_region() const override ATTR_COLD;
};
-// ======================> c1541_t
+// ======================> c1541_device
-class c1541_t : public c1541_base_t
+class c1541_device : public c1541_device_base
{
public:
// construction/destruction
- c1541_t(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
+ c1541_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;
+ virtual const tiny_rom_entry *device_rom_region() const override ATTR_COLD;
};
-// ======================> c1541c_t
+// ======================> c1541c_device
-class c1541c_t : public c1541_base_t
+class c1541c_device : public c1541_device_base
{
public:
// construction/destruction
- c1541c_t(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
+ c1541c_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;
- virtual void device_add_mconfig(machine_config &config) override;
+ virtual const tiny_rom_entry *device_rom_region() const override ATTR_COLD;
+ virtual void device_add_mconfig(machine_config &config) override ATTR_COLD;
private:
- // not really public
- virtual DECLARE_READ8_MEMBER( via0_pa_r ) override;
+ virtual uint8_t via0_pa_r() override;
};
-// ======================> c1541ii_t
+// ======================> c1541ii_device
-class c1541ii_t : public c1541_base_t
+class c1541ii_device : public c1541_device_base
{
public:
// construction/destruction
- c1541ii_t(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
+ c1541ii_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;
+ virtual const tiny_rom_entry *device_rom_region() const override ATTR_COLD;
};
-// ======================> sx1541_t
+// ======================> sx1541_device
-class sx1541_t : public c1541_base_t
+class sx1541_device : public c1541_device_base
{
public:
// construction/destruction
- sx1541_t(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
+ sx1541_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;
+ virtual const tiny_rom_entry *device_rom_region() const override ATTR_COLD;
};
-// ======================> fsd1_t
+// ======================> fsd1_device
-class fsd1_t : public c1541_base_t
+class fsd1_device : public c1541_device_base
{
public:
// construction/destruction
- fsd1_t(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
+ fsd1_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;
+ virtual const tiny_rom_entry *device_rom_region() const override ATTR_COLD;
};
-// ======================> fsd2_t
+// ======================> fsd2_device
-class fsd2_t : public c1541_base_t
+class fsd2_device : public c1541_device_base
{
public:
// construction/destruction
- fsd2_t(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
+ fsd2_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;
+ virtual const tiny_rom_entry *device_rom_region() const override ATTR_COLD;
// device-level overrides
- virtual void device_start() override;
+ virtual void device_start() override ATTR_COLD;
};
-// ======================> csd1_t
+// ======================> csd1_device
-class csd1_t : public c1541_base_t
+class csd1_device : public c1541_device_base
{
public:
// construction/destruction
- csd1_t(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
+ csd1_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;
+ virtual const tiny_rom_entry *device_rom_region() const override ATTR_COLD;
};
-// ======================> c1541_dolphin_dos_t
+// ======================> c1541_dolphin_dos_device
-class c1541_dolphin_dos_t : public c1541_base_t
+class c1541_dolphin_dos_device : public c1541_device_base
{
public:
// construction/destruction
- c1541_dolphin_dos_t(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
+ c1541_dolphin_dos_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;
- virtual void device_add_mconfig(machine_config &config) override;
+ virtual const tiny_rom_entry *device_rom_region() const override ATTR_COLD;
+ virtual void device_add_mconfig(machine_config &config) override ATTR_COLD;
};
-// ======================> c1541_professional_dos_v1_t
+// ======================> c1541_professional_dos_v1_device
-class c1541_professional_dos_v1_t : public c1541_base_t
+class c1541_professional_dos_v1_device : public c1541_device_base
{
public:
// construction/destruction
- c1541_professional_dos_v1_t(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
+ c1541_professional_dos_v1_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;
- virtual void device_add_mconfig(machine_config &config) override;
+ virtual const tiny_rom_entry *device_rom_region() const override ATTR_COLD;
+ virtual void device_add_mconfig(machine_config &config) override ATTR_COLD;
};
-// ======================> c1541_prologic_dos_classic_t
+// ======================> c1541_prologic_dos_classic_device
-class c1541_prologic_dos_classic_t : public c1541_base_t
+class c1541_prologic_dos_classic_device : public c1541_device_base
{
public:
// construction/destruction
- c1541_prologic_dos_classic_t(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
+ c1541_prologic_dos_classic_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;
- virtual void device_add_mconfig(machine_config &config) override;
+ virtual const tiny_rom_entry *device_rom_region() const override ATTR_COLD;
+ virtual void device_add_mconfig(machine_config &config) override ATTR_COLD;
private:
required_device<pia6821_device> m_pia;
required_device<output_latch_device> m_cent_data_out;
required_memory_region m_mmu_rom;
- DECLARE_READ8_MEMBER( pia_r );
- DECLARE_WRITE8_MEMBER( pia_w );
- DECLARE_WRITE8_MEMBER( pia_pa_w );
- DECLARE_READ8_MEMBER( pia_pb_r );
- DECLARE_WRITE8_MEMBER( pia_pb_w );
- DECLARE_READ8_MEMBER( read );
- DECLARE_WRITE8_MEMBER( write );
+ uint8_t pia_r(offs_t offset);
+ void pia_w(offs_t offset, uint8_t data);
+ void pia_pa_w(uint8_t data);
+ uint8_t pia_pb_r();
+ void pia_pb_w(uint8_t data);
+ uint8_t read();
+ void write(uint8_t data);
- void c1541pdc_mem(address_map &map);
+ void c1541pdc_mem(address_map &map) ATTR_COLD;
};
-// ======================> indus_gt_t
+// ======================> indus_gt_device
-class indus_gt_t : public c1541_base_t
+class indus_gt_device : public c1541_device_base
{
public:
// construction/destruction
- indus_gt_t(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
+ indus_gt_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;
+ virtual const tiny_rom_entry *device_rom_region() const override ATTR_COLD;
};
-// ======================> technica_t
+// ======================> technica_device
-class technica_t : public c1541_base_t
+class technica_device : public c1541_device_base
{
public:
// construction/destruction
- technica_t(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
+ technica_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;
+ virtual const tiny_rom_entry *device_rom_region() const override ATTR_COLD;
};
-// ======================> blue_chip_t
+// ======================> blue_chip_device
-class blue_chip_t : public c1541_base_t
+class blue_chip_device : public c1541_device_base
{
public:
// construction/destruction
- blue_chip_t(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
+ blue_chip_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;
+ virtual const tiny_rom_entry *device_rom_region() const override ATTR_COLD;
};
-// ======================> commander_c2_t
+// ======================> commander_c2_device
-class commander_c2_t : public c1541_base_t
+class commander_c2_device : public c1541_device_base
{
public:
// construction/destruction
- commander_c2_t(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
+ commander_c2_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;
+ virtual const tiny_rom_entry *device_rom_region() const override ATTR_COLD;
};
-// ======================> enhancer_2000_t
+// ======================> enhancer_2000_device
-class enhancer_2000_t : public c1541_base_t
+class enhancer_2000_device : public c1541_device_base
{
public:
// construction/destruction
- enhancer_2000_t(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
+ enhancer_2000_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;
+ virtual const tiny_rom_entry *device_rom_region() const override ATTR_COLD;
};
-// ======================> fd148_t
+// ======================> fd148_device
-class fd148_t : public c1541_base_t
+class fd148_device : public c1541_device_base
{
public:
// construction/destruction
- fd148_t(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
+ fd148_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;
+ virtual const tiny_rom_entry *device_rom_region() const override ATTR_COLD;
};
-// ======================> msd_sd1_t
+// ======================> msd_sd1_device
-class msd_sd1_t : public c1541_base_t
+class msd_sd1_device : public c1541_device_base
{
public:
// construction/destruction
- msd_sd1_t(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
+ msd_sd1_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;
+ virtual const tiny_rom_entry *device_rom_region() const override ATTR_COLD;
};
-// ======================> msd_sd2_t
+// ======================> msd_sd2_device
-class msd_sd2_t : public c1541_base_t
+class msd_sd2_device : public c1541_device_base
{
public:
// construction/destruction
- msd_sd2_t(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
+ msd_sd2_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;
+ virtual const tiny_rom_entry *device_rom_region() const override ATTR_COLD;
};
// device type definition
-DECLARE_DEVICE_TYPE(C1540, c1540_t)
-DECLARE_DEVICE_TYPE(C1541, c1541_t)
-DECLARE_DEVICE_TYPE(C1541C, c1541c_t)
-DECLARE_DEVICE_TYPE(C1541II, c1541ii_t)
-DECLARE_DEVICE_TYPE(SX1541, sx1541_t)
-DECLARE_DEVICE_TYPE(FSD1, fsd1_t)
-DECLARE_DEVICE_TYPE(FSD2, fsd2_t)
-DECLARE_DEVICE_TYPE(CSD1, csd1_t)
-DECLARE_DEVICE_TYPE(C1541_DOLPHIN_DOS, c1541_dolphin_dos_t)
-DECLARE_DEVICE_TYPE(C1541_PROFESSIONAL_DOS_V1, c1541_professional_dos_v1_t)
-DECLARE_DEVICE_TYPE(C1541_PROLOGIC_DOS_CLASSIC, c1541_prologic_dos_classic_t)
-DECLARE_DEVICE_TYPE(INDUS_GT, indus_gt_t)
-DECLARE_DEVICE_TYPE(TECHNICA, technica_t)
-DECLARE_DEVICE_TYPE(BLUE_CHIP, blue_chip_t)
-DECLARE_DEVICE_TYPE(COMMANDER_C2, commander_c2_t)
-DECLARE_DEVICE_TYPE(ENHANCER_2000, enhancer_2000_t)
-DECLARE_DEVICE_TYPE(FD148, fd148_t)
-DECLARE_DEVICE_TYPE(MSD_SD1, msd_sd1_t)
-DECLARE_DEVICE_TYPE(MSD_SD2, msd_sd2_t)
+DECLARE_DEVICE_TYPE(C1540, c1540_device)
+DECLARE_DEVICE_TYPE(C1541, c1541_device)
+DECLARE_DEVICE_TYPE(C1541C, c1541c_device)
+DECLARE_DEVICE_TYPE(C1541II, c1541ii_device)
+DECLARE_DEVICE_TYPE(SX1541, sx1541_device)
+DECLARE_DEVICE_TYPE(FSD1, fsd1_device)
+DECLARE_DEVICE_TYPE(FSD2, fsd2_device)
+DECLARE_DEVICE_TYPE(CSD1, csd1_device)
+DECLARE_DEVICE_TYPE(C1541_DOLPHIN_DOS, c1541_dolphin_dos_device)
+DECLARE_DEVICE_TYPE(C1541_PROFESSIONAL_DOS_V1, c1541_professional_dos_v1_device)
+DECLARE_DEVICE_TYPE(C1541_PROLOGIC_DOS_CLASSIC, c1541_prologic_dos_classic_device)
+DECLARE_DEVICE_TYPE(INDUS_GT, indus_gt_device)
+DECLARE_DEVICE_TYPE(TECHNICA, technica_device)
+DECLARE_DEVICE_TYPE(BLUE_CHIP, blue_chip_device)
+DECLARE_DEVICE_TYPE(COMMANDER_C2, commander_c2_device)
+DECLARE_DEVICE_TYPE(ENHANCER_2000, enhancer_2000_device)
+DECLARE_DEVICE_TYPE(FD148, fd148_device)
+DECLARE_DEVICE_TYPE(MSD_SD1, msd_sd1_device)
+DECLARE_DEVICE_TYPE(MSD_SD2, msd_sd2_device)
#endif // MAME_BUS_CBMIEC_C1541_H
diff --git a/src/devices/bus/cbmiec/c1571.cpp b/src/devices/bus/cbmiec/c1571.cpp
index 0b4112ffd3e..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,14 +175,14 @@ 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;
m_maincpu->set_input_line(INPUT_LINE_IRQ0, (m_via0_irq || m_via1_irq || m_cia_irq) ? ASSERT_LINE : CLEAR_LINE);
}
-READ8_MEMBER( c1571_device::via0_pa_r )
+uint8_t c1571_device::via0_pa_r()
{
/*
@@ -207,7 +210,7 @@ READ8_MEMBER( c1571_device::via0_pa_r )
return data;
}
-WRITE8_MEMBER( c1571_device::via0_pa_w )
+void c1571_device::via0_pa_w(uint8_t data)
{
/*
@@ -252,7 +255,7 @@ WRITE8_MEMBER( c1571_device::via0_pa_w )
update_iec();
}
-WRITE8_MEMBER( c1571cr_device::via0_pa_w )
+void c1571cr_device::via0_pa_w(uint8_t data)
{
/*
@@ -289,7 +292,7 @@ WRITE8_MEMBER( c1571cr_device::via0_pa_w )
}
}
-READ8_MEMBER( c1571_device::via0_pb_r )
+uint8_t c1571_device::via0_pb_r()
{
/*
@@ -323,7 +326,7 @@ READ8_MEMBER( c1571_device::via0_pb_r )
return data;
}
-WRITE8_MEMBER( c1571_device::via0_pb_w )
+void c1571_device::via0_pb_w(uint8_t data)
{
/*
@@ -352,7 +355,7 @@ WRITE8_MEMBER( c1571_device::via0_pb_w )
update_iec();
}
-WRITE8_MEMBER( c1571cr_device::via0_pb_w )
+void c1571cr_device::via0_pb_w(uint8_t data)
{
/*
@@ -382,7 +385,7 @@ WRITE8_MEMBER( c1571cr_device::via0_pb_w )
}
-READ8_MEMBER( c1571_device::via1_r )
+uint8_t c1571_device::via1_r(offs_t offset)
{
uint8_t data = m_via1->read(offset);
@@ -392,7 +395,7 @@ READ8_MEMBER( c1571_device::via1_r )
return data;
}
-WRITE8_MEMBER( c1571_device::via1_w )
+void c1571_device::via1_w(offs_t offset, uint8_t data)
{
m_via1->write(offset, data);
@@ -400,14 +403,14 @@ WRITE8_MEMBER( c1571_device::via1_w )
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;
m_maincpu->set_input_line(INPUT_LINE_IRQ0, (m_via0_irq || m_via1_irq || m_cia_irq) ? ASSERT_LINE : CLEAR_LINE);
}
-READ8_MEMBER( c1571_device::via1_pb_r )
+uint8_t c1571_device::via1_pb_r()
{
/*
@@ -435,7 +438,7 @@ READ8_MEMBER( c1571_device::via1_pb_r )
return data;
}
-WRITE8_MEMBER( c1571_device::via1_pb_w )
+void c1571_device::via1_pb_w(uint8_t data)
{
/*
@@ -470,14 +473,14 @@ WRITE8_MEMBER( c1571_device::via1_pb_w )
// 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,26 +488,26 @@ 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;
update_iec();
}
-READ8_MEMBER( c1571_device::cia_pb_r )
+uint8_t c1571_device::cia_pb_r()
{
return m_parallel_data;
}
-WRITE8_MEMBER( c1571_device::cia_pb_w )
+void c1571_device::cia_pb_w(uint8_t data)
{
if (m_other != nullptr)
{
@@ -517,19 +520,19 @@ WRITE8_MEMBER( c1571_device::cia_pb_w )
// MOS6526_INTERFACE( mini_chief_cia_intf )
//-------------------------------------------------
-READ8_MEMBER( mini_chief_device::cia_pa_r )
+uint8_t mini_chief_device::cia_pa_r()
{
// TODO read from ISA bus @ 0x320 | A2 A1 A0
return 0;
}
-WRITE8_MEMBER( mini_chief_device::cia_pa_w )
+void mini_chief_device::cia_pa_w(uint8_t data)
{
// TODO write to ISA bus @ 0x320 | A2 A1 A0
}
-WRITE8_MEMBER( mini_chief_device::cia_pb_w )
+void mini_chief_device::cia_pb_w(uint8_t data)
{
/*
@@ -552,7 +555,7 @@ WRITE8_MEMBER( mini_chief_device::cia_pb_w )
// C64H156_INTERFACE( ga_intf )
//-------------------------------------------------
-WRITE_LINE_MEMBER( c1571_device::byte_w )
+void c1571_device::byte_w(int state)
{
m_via1->write_ca1(state);
@@ -574,11 +577,12 @@ void c1571_device::wpt_callback(floppy_image_device *floppy, int state)
// FLOPPY_FORMATS( floppy_formats )
//-------------------------------------------------
-FLOPPY_FORMATS_MEMBER( c1571_device::floppy_formats )
- FLOPPY_D64_FORMAT,
- FLOPPY_G64_FORMAT,
- FLOPPY_D71_FORMAT
-FLOPPY_FORMATS_END
+void c1571_device::floppy_formats(format_registration &fr)
+{
+ fr.add(FLOPPY_D64_FORMAT);
+ fr.add(FLOPPY_G64_FORMAT);
+ fr.add(FLOPPY_D71_FORMAT);
+}
//-------------------------------------------------
@@ -598,16 +602,15 @@ 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.m_perfect_cpu_quantum = subtag(M6502_TAG);
- VIA6522(config, m_via0, 16_MHz_XTAL / 16);
+ MOS6522(config, m_via0, 16_MHz_XTAL / 16);
m_via0->readpa_handler().set(FUNC(c1571_device::via0_pa_r));
m_via0->readpb_handler().set(FUNC(c1571_device::via0_pb_r));
m_via0->writepa_handler().set(FUNC(c1571_device::via0_pa_w));
m_via0->writepb_handler().set(FUNC(c1571_device::via0_pb_w));
m_via0->irq_handler().set(FUNC(c1571_device::via0_irq_w));
- VIA6522(config, m_via1, 16_MHz_XTAL / 16);
+ MOS6522(config, m_via1, 16_MHz_XTAL / 16);
m_via1->readpa_handler().set(C64H156_TAG, FUNC(c64h156_device::yb_r));
m_via1->readpb_handler().set(FUNC(c1571_device::via1_pb_r));
m_via1->writepa_handler().set(C64H156_TAG, FUNC(c64h156_device::yb_w));
@@ -626,6 +629,7 @@ void c1571_device::add_base_mconfig(machine_config &config)
connector.set_default_option("525qd");
connector.set_fixed(true);
connector.set_formats(c1571_device::floppy_formats);
+ connector.enable_sound(true);
}
void c1571_device::add_cia_mconfig(machine_config &config)
diff --git a/src/devices/bus/cbmiec/c1571.h b/src/devices/bus/cbmiec/c1571.h
index 467c959963e..d7067ab060a 100644
--- a/src/devices/bus/cbmiec/c1571.h
+++ b/src/devices/bus/cbmiec/c1571.h
@@ -43,43 +43,43 @@ 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 );
- DECLARE_READ8_MEMBER( via0_pa_r );
- DECLARE_WRITE8_MEMBER( via0_pa_w );
- DECLARE_READ8_MEMBER( via0_pb_r );
- DECLARE_WRITE8_MEMBER( via0_pb_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_READ8_MEMBER( via1_r );
- DECLARE_WRITE8_MEMBER( via1_w );
- DECLARE_WRITE_LINE_MEMBER( via1_irq_w );
- DECLARE_READ8_MEMBER( via1_pb_r );
- DECLARE_WRITE8_MEMBER( via1_pb_w );
+ uint8_t via1_r(offs_t offset);
+ void via1_w(offs_t offset, uint8_t data);
+ 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 );
- DECLARE_READ8_MEMBER( cia_pb_r );
- DECLARE_WRITE8_MEMBER( cia_pb_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);
- DECLARE_FLOPPY_FORMATS( floppy_formats );
+ static void floppy_formats(format_registration &fr);
void wpt_callback(floppy_image_device *floppy, int state);
- void c1571_mem(address_map &map);
+ void c1571_mem(address_map &map) ATTR_COLD;
protected:
c1571_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_start() override ATTR_COLD;
+ virtual void device_reset() override ATTR_COLD;
// optional information 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 const tiny_rom_entry *device_rom_region() const override ATTR_COLD;
+ virtual void device_add_mconfig(machine_config &config) override ATTR_COLD;
+ virtual ioport_constructor device_input_ports() const override ATTR_COLD;
// device_cbm_iec_interface overrides
virtual void cbm_iec_srq(int state) override;
@@ -138,8 +138,8 @@ public:
protected:
// optional information overrides
- virtual const tiny_rom_entry *device_rom_region() const override;
- virtual void device_add_mconfig(machine_config &config) override;
+ virtual const tiny_rom_entry *device_rom_region() const override ATTR_COLD;
+ virtual void device_add_mconfig(machine_config &config) override ATTR_COLD;
};
@@ -153,12 +153,12 @@ public:
protected:
// optional information overrides
- virtual const tiny_rom_entry *device_rom_region() const override;
- virtual void device_add_mconfig(machine_config &config) override;
+ virtual const tiny_rom_entry *device_rom_region() const override ATTR_COLD;
+ virtual void device_add_mconfig(machine_config &config) override ATTR_COLD;
private:
- DECLARE_WRITE8_MEMBER( via0_pa_w );
- DECLARE_WRITE8_MEMBER( via0_pb_w );
+ void via0_pa_w(uint8_t data);
+ void via0_pb_w(uint8_t data);
};
@@ -172,15 +172,15 @@ public:
protected:
// optional information overrides
- virtual const tiny_rom_entry *device_rom_region() const override;
- virtual void device_add_mconfig(machine_config &config) override;
+ virtual const tiny_rom_entry *device_rom_region() const override ATTR_COLD;
+ virtual void device_add_mconfig(machine_config &config) override ATTR_COLD;
private:
- DECLARE_READ8_MEMBER( cia_pa_r );
- DECLARE_WRITE8_MEMBER( cia_pa_w );
- DECLARE_WRITE8_MEMBER( cia_pb_w );
+ uint8_t cia_pa_r();
+ void cia_pa_w(uint8_t data);
+ void cia_pb_w(uint8_t data);
- void mini_chief_mem(address_map &map);
+ void mini_chief_mem(address_map &map) ATTR_COLD;
};
diff --git a/src/devices/bus/cbmiec/c1581.cpp b/src/devices/bus/cbmiec/c1581.cpp
index f589cb2f427..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"
+
//**************************************************************************
@@ -33,8 +36,8 @@
// DEVICE DEFINITIONS
//**************************************************************************
-DEFINE_DEVICE_TYPE(C1563, c1563_device, "c1563", "Commodore 1563 3.5 Disk Drive")
-DEFINE_DEVICE_TYPE(C1581, c1581_device, "c1581", "Commodore 1581 3.5 Disk Drive")
+DEFINE_DEVICE_TYPE(C1563, c1563_device, "c1563", "Commodore 1563 3.5\" Disk Drive")
+DEFINE_DEVICE_TYPE(C1581, c1581_device, "c1581", "Commodore 1581 3.5\" Disk Drive")
//-------------------------------------------------
@@ -102,21 +105,21 @@ 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;
update_iec();
}
-READ8_MEMBER( c1581_device::cia_pa_r )
+uint8_t c1581_device::cia_pa_r()
{
/*
@@ -147,7 +150,7 @@ READ8_MEMBER( c1581_device::cia_pa_r )
return data;
}
-WRITE8_MEMBER( c1581_device::cia_pa_w )
+void c1581_device::cia_pa_w(uint8_t data)
{
/*
@@ -177,7 +180,7 @@ WRITE8_MEMBER( c1581_device::cia_pa_w )
m_leds[LED_ACT] = BIT(data, 6);
}
-READ8_MEMBER( c1581_device::cia_pb_r )
+uint8_t c1581_device::cia_pb_r()
{
/*
@@ -211,7 +214,7 @@ READ8_MEMBER( c1581_device::cia_pb_r )
return data;
}
-WRITE8_MEMBER( c1581_device::cia_pb_w )
+void c1581_device::cia_pb_w(uint8_t data)
{
/*
@@ -258,9 +261,10 @@ static void c1581_floppies(device_slot_interface &device)
// FLOPPY_FORMATS( c1581_device::floppy_formats )
//-------------------------------------------------
-FLOPPY_FORMATS_MEMBER( c1581_device::floppy_formats )
- FLOPPY_D81_FORMAT
-FLOPPY_FORMATS_END
+void c1581_device::floppy_formats(format_registration &fr)
+{
+ fr.add(FLOPPY_D81_FORMAT);
+}
//-------------------------------------------------
@@ -282,7 +286,7 @@ void c1581_device::device_add_mconfig(machine_config &config)
m_cia->pb_wr_callback().set(FUNC(c1581_device::cia_pb_w));
WD1772(config, m_fdc, 16_MHz_XTAL / 2);
- FLOPPY_CONNECTOR(config, WD1772_TAG":0", c1581_floppies, "35dd", c1581_device::floppy_formats, true);
+ FLOPPY_CONNECTOR(config, WD1772_TAG":0", c1581_floppies, "35dd", c1581_device::floppy_formats, true).enable_sound(true);
}
diff --git a/src/devices/bus/cbmiec/c1581.h b/src/devices/bus/cbmiec/c1581.h
index 811375dbdaa..0bd747a4f12 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"
@@ -44,13 +42,13 @@ protected:
c1581_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_start() override ATTR_COLD;
+ virtual void device_reset() override ATTR_COLD;
// optional information 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 const tiny_rom_entry *device_rom_region() const override ATTR_COLD;
+ virtual void device_add_mconfig(machine_config &config) override ATTR_COLD;
+ virtual ioport_constructor device_input_ports() const override ATTR_COLD;
// device_cbm_iec_interface overrides
virtual void cbm_iec_srq(int state) override;
@@ -67,16 +65,16 @@ private:
void update_iec();
- DECLARE_WRITE_LINE_MEMBER( cnt_w );
- DECLARE_WRITE_LINE_MEMBER( sp_w );
- DECLARE_READ8_MEMBER( cia_pa_r );
- DECLARE_WRITE8_MEMBER( cia_pa_w );
- DECLARE_READ8_MEMBER( cia_pb_r );
- DECLARE_WRITE8_MEMBER( cia_pb_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();
+ void cia_pb_w(uint8_t data);
- void c1581_mem(address_map &map);
+ void c1581_mem(address_map &map) ATTR_COLD;
- DECLARE_FLOPPY_FORMATS( floppy_formats );
+ static void floppy_formats(format_registration &fr);
required_device<cpu_device> m_maincpu;
required_device<mos6526_device> m_cia;
@@ -102,7 +100,7 @@ public:
c1563_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 const tiny_rom_entry *device_rom_region() const override ATTR_COLD;
};
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..d183288421f 100644
--- a/src/devices/bus/cbmiec/c64_nl10.h
+++ b/src/devices/bus/cbmiec/c64_nl10.h
@@ -27,18 +27,20 @@ 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 void device_start() override;
- virtual void device_reset() override;
+ virtual const tiny_rom_entry *device_rom_region() const override ATTR_COLD;
+ 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;
// 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) ATTR_COLD;
};
diff --git a/src/devices/bus/cbmiec/cbmiec.cpp b/src/devices/bus/cbmiec/cbmiec.cpp
index c9a04f863e2..43faf6e17a3 100644
--- a/src/devices/bus/cbmiec/cbmiec.cpp
+++ b/src/devices/bus/cbmiec/cbmiec.cpp
@@ -222,8 +222,8 @@ DEFINE_DEVICE_TYPE(CBM_IEC_SLOT, cbm_iec_slot_device, "cbm_iec_slot", "CBM IEC s
// device_cbm_iec_interface - constructor
//-------------------------------------------------
-device_cbm_iec_interface::device_cbm_iec_interface(const machine_config &mconfig, device_t &device)
- : device_slot_card_interface(mconfig, device), m_next(nullptr), m_bus(nullptr), m_slot(nullptr)
+device_cbm_iec_interface::device_cbm_iec_interface(const machine_config &mconfig, device_t &device) :
+ device_interface(device, "cbmiec"), m_next(nullptr), m_bus(nullptr), m_slot(nullptr)
{
}
@@ -247,8 +247,8 @@ device_cbm_iec_interface::~device_cbm_iec_interface()
//-------------------------------------------------
cbm_iec_slot_device::cbm_iec_slot_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) :
- device_t(mconfig, CBM_IEC_SLOT, tag, owner, clock),
- device_slot_interface(mconfig, *this), m_address(0)
+ device_t(mconfig, CBM_IEC_SLOT, tag, owner, clock),
+ device_slot_interface(mconfig, *this), m_address(0)
{
}
@@ -273,14 +273,6 @@ void cbm_iec_slot_device::device_start()
if (dev) bus->add_device(this, get_card_device());
}
-void cbm_iec_slot_device::add_slot(machine_config &config, const char *_tag, int _address, const char *_def_slot)
-{
- cbm_iec_slot_device &slot(CBM_IEC_SLOT(config, _tag, 0));
- cbm_iec_devices(slot);
- slot.set_default_option(_def_slot);
- slot.set_address(_address);
-}
-
//**************************************************************************
// LIVE DEVICE
//**************************************************************************
@@ -289,13 +281,13 @@ void cbm_iec_slot_device::add_slot(machine_config &config, const char *_tag, int
// cbm_iec_device - constructor
//-------------------------------------------------
-cbm_iec_device::cbm_iec_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
- : device_t(mconfig, CBM_IEC, tag, owner, clock),
- m_write_srq(*this),
- m_write_atn(*this),
- m_write_clk(*this),
- m_write_data(*this),
- m_write_reset(*this)
+cbm_iec_device::cbm_iec_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) :
+ device_t(mconfig, CBM_IEC, tag, owner, clock),
+ m_write_srq(*this),
+ m_write_atn(*this),
+ m_write_clk(*this),
+ m_write_data(*this),
+ m_write_reset(*this)
{
for (auto & elem : m_line)
{
@@ -310,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();
}
@@ -346,7 +332,7 @@ void cbm_iec_device::device_stop()
void cbm_iec_device::add_device(cbm_iec_slot_device *slot, device_t *target)
{
- auto entry = global_alloc(daisy_entry(target));
+ auto entry = new daisy_entry(target);
entry->m_interface->m_slot = slot;
entry->m_interface->m_bus = this;
@@ -359,10 +345,10 @@ void cbm_iec_device::add_device(cbm_iec_slot_device *slot, device_t *target)
// daisy_entry - constructor
//-------------------------------------------------
-cbm_iec_device::daisy_entry::daisy_entry(device_t *device)
- : m_next(nullptr),
- m_device(device),
- m_interface(nullptr)
+cbm_iec_device::daisy_entry::daisy_entry(device_t *device) :
+ m_next(nullptr),
+ m_device(device),
+ m_interface(nullptr)
{
for (auto & elem : m_line)
{
@@ -502,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)
{
@@ -522,9 +509,9 @@ void cbm_iec_devices(device_slot_interface &device)
device.option_add("cmdhd", CMD_HD);
device.option_add("fd2000", FD2000);
device.option_add("fd4000", FD4000);
- device.option_add("interpod", INTERPOD);
+ device.option_add("interpod", CBM_INTERPOD);
device.option_add("minichief", MINI_CHIEF);
- device.option_add("serialbox", SERIAL_BOX);
+ device.option_add("serialbox", CBM_SERIAL_BOX);
device.option_add("diag264", DIAG264_SERIAL_LOOPBACK);
device.option_add("nl10", C64_NL10_INTERFACE);
device.option_add("vic1515", VIC1515);
@@ -537,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 ceb03d44948..fafea819abb 100644
--- a/src/devices/bus/cbmiec/cbmiec.h
+++ b/src/devices/bus/cbmiec/cbmiec.h
@@ -21,6 +21,9 @@
#define CBM_IEC_TAG "iec_bus"
+DECLARE_DEVICE_TYPE(CBM_IEC, cbm_iec_device)
+DECLARE_DEVICE_TYPE(CBM_IEC_SLOT, cbm_iec_slot_device)
+
void cbm_iec_devices(device_slot_interface &device);
//**************************************************************************
@@ -47,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); }
@@ -79,9 +82,9 @@ protected:
};
// device-level overrides
- virtual void device_start() override;
- virtual void device_reset() override;
- virtual void device_stop() override;
+ virtual void device_start() override ATTR_COLD;
+ virtual void device_reset() override ATTR_COLD;
+ virtual void device_stop() override ATTR_COLD;
class daisy_entry
{
@@ -111,8 +114,6 @@ private:
int m_line[SIGNAL_COUNT];
};
-DECLARE_DEVICE_TYPE(CBM_IEC, cbm_iec_device)
-
// ======================> cbm_iec_slot_device
@@ -122,24 +123,24 @@ class cbm_iec_slot_device : public device_t,
public:
// construction/destruction
template <typename T>
- cbm_iec_slot_device(machine_config const &mconfig, char const *tag, device_t *owner, T &&opts, char const *dflt)
+ cbm_iec_slot_device(machine_config const &mconfig, char const *tag, device_t *owner, int address, T &&opts, char const *dflt)
: cbm_iec_slot_device(mconfig, tag, owner, (uint32_t)0)
{
option_reset();
opts(*this);
set_default_option(dflt);
set_fixed(false);
+ set_address(address);
}
cbm_iec_slot_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
- static void add_slot(machine_config &config, const char *_tag, int _address, const char *_def_slot);
template <typename T> static void add(machine_config &config, T &&_bus_tag, const char *_default_drive)
{
- add_slot(config, "iec4", 4, nullptr);
- add_slot(config, "iec8", 8, _default_drive);
- add_slot(config, "iec9", 9, nullptr);
- add_slot(config, "iec10", 10, nullptr);
- add_slot(config, "iec11", 11, nullptr);
+ CBM_IEC_SLOT(config, "iec4", 4, cbm_iec_devices, nullptr);
+ CBM_IEC_SLOT(config, "iec8", 8, cbm_iec_devices, _default_drive);
+ CBM_IEC_SLOT(config, "iec9", 9, cbm_iec_devices, nullptr);
+ CBM_IEC_SLOT(config, "iec10", 10, cbm_iec_devices, nullptr);
+ CBM_IEC_SLOT(config, "iec11", 11, cbm_iec_devices, nullptr);
CBM_IEC(config, std::forward<T>(_bus_tag), 0);
}
@@ -148,7 +149,7 @@ public:
int get_address() { return m_address; }
// device-level overrides
- virtual void device_start() override;
+ virtual void device_start() override ATTR_COLD;
protected:
int m_address;
@@ -157,7 +158,7 @@ protected:
// ======================> device_cbm_iec_interface
-class device_cbm_iec_interface : public device_slot_card_interface
+class device_cbm_iec_interface : public device_interface
{
friend class cbm_iec_device;
@@ -182,6 +183,4 @@ protected:
cbm_iec_slot_device *m_slot;
};
-DECLARE_DEVICE_TYPE(CBM_IEC_SLOT, cbm_iec_slot_device)
-
#endif // MAME_BUS_CBMIEC_CBMIEC_H
diff --git a/src/devices/bus/cbmiec/cmdhd.cpp b/src/devices/bus/cbmiec/cmdhd.cpp
index 91d92bddc2a..104b0eb456e 100644
--- a/src/devices/bus/cbmiec/cmdhd.cpp
+++ b/src/devices/bus/cbmiec/cmdhd.cpp
@@ -78,8 +78,8 @@ void cmd_hd_device::device_add_mconfig(machine_config &config)
M6502(config, m_maincpu, 2000000);
m_maincpu->set_addrmap(AS_PROGRAM, &cmd_hd_device::mem_map);
- VIA6522(config, M6522_1_TAG, 2000000);
- VIA6522(config, M6522_2_TAG, 2000000);
+ MOS6522(config, M6522_1_TAG, 2000000);
+ MOS6522(config, M6522_2_TAG, 2000000);
I8255A(config, I8255A_TAG, 0);
RTC72421(config, RTC72421A_TAG, XTAL(32'768));
@@ -168,7 +168,7 @@ void cmd_hd_device::cbm_iec_reset(int state)
// led_w -
//-------------------------------------------------
-WRITE8_MEMBER( cmd_hd_device::led_w )
+void cmd_hd_device::led_w(uint8_t data)
{
/*
diff --git a/src/devices/bus/cbmiec/cmdhd.h b/src/devices/bus/cbmiec/cmdhd.h
index 2cdeada48df..bf4493d92e0 100644
--- a/src/devices/bus/cbmiec/cmdhd.h
+++ b/src/devices/bus/cbmiec/cmdhd.h
@@ -21,14 +21,6 @@
//**************************************************************************
-// MACROS / CONSTANTS
-//**************************************************************************
-
-#define CMD_HD_TAG "cmdhd"
-
-
-
-//**************************************************************************
// TYPE DEFINITIONS
//**************************************************************************
@@ -42,12 +34,12 @@ public:
protected:
// device-level overrides
- virtual void device_start() override;
- virtual void device_reset() override;
+ virtual void device_start() override ATTR_COLD;
+ virtual void device_reset() override ATTR_COLD;
// optional information overrides
- virtual const tiny_rom_entry *device_rom_region() const override;
- virtual void device_add_mconfig(machine_config &config) override;
+ virtual const tiny_rom_entry *device_rom_region() const override ATTR_COLD;
+ virtual void device_add_mconfig(machine_config &config) override ATTR_COLD;
// device_cbm_iec_interface overrides
void cbm_iec_srq(int state) override;
@@ -59,9 +51,9 @@ private:
required_device<m6502_device> m_maincpu;
required_device<scsi_port_device> m_scsibus;
- DECLARE_WRITE8_MEMBER( led_w );
+ void led_w(uint8_t data);
- void mem_map(address_map &map);
+ void mem_map(address_map &map) ATTR_COLD;
};
diff --git a/src/devices/bus/cbmiec/diag264_lb_iec.h b/src/devices/bus/cbmiec/diag264_lb_iec.h
index 6611fee413d..8d32d19d106 100644
--- a/src/devices/bus/cbmiec/diag264_lb_iec.h
+++ b/src/devices/bus/cbmiec/diag264_lb_iec.h
@@ -30,7 +30,7 @@ public:
protected:
// device-level overrides
- virtual void device_start() override;
+ virtual void device_start() override ATTR_COLD;
// device_cbm_iec_interface overrides
virtual void cbm_iec_atn(int state) override;
diff --git a/src/devices/bus/cbmiec/fd2000.cpp b/src/devices/bus/cbmiec/fd2000.cpp
index c4d1bd311c1..91b3cc9ae44 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"
+
//**************************************************************************
@@ -113,7 +115,7 @@ void fd4000_device::fd4000_mem(address_map &map)
}
-READ8_MEMBER( fd2000_device::via_pa_r )
+uint8_t fd2000_device::via_pa_r()
{
/*
@@ -133,7 +135,7 @@ READ8_MEMBER( fd2000_device::via_pa_r )
return 0;
}
-WRITE8_MEMBER( fd2000_device::via_pa_w )
+void fd2000_device::via_pa_w(uint8_t data)
{
/*
@@ -151,7 +153,7 @@ WRITE8_MEMBER( fd2000_device::via_pa_w )
*/
}
-READ8_MEMBER( fd2000_device::via_pb_r )
+uint8_t fd2000_device::via_pb_r()
{
/*
@@ -176,7 +178,7 @@ READ8_MEMBER( fd2000_device::via_pb_r )
return data;
}
-WRITE8_MEMBER( fd2000_device::via_pb_w )
+void fd2000_device::via_pb_w(uint8_t data)
{
/*
@@ -204,10 +206,10 @@ static void fd4000_floppies(device_slot_interface &device)
device.option_add("35ed", FLOPPY_35_ED); // TEAC FD-235J
}
/*
-FLOPPY_FORMATS_MEMBER( fd2000_device::floppy_formats )
+void fd2000_device::floppy_formats(format_registration &fr)
FLOPPY_D81_FORMAT
FLOPPY_D2M_FORMAT
-FLOPPY_FORMATS_END
+}
*/
@@ -217,9 +219,9 @@ FLOPPY_FORMATS_END
void fd2000_device::add_common_devices(machine_config &config)
{
- M65C02(config, m_maincpu, 24_MHz_XTAL / 12);
+ W65C02(config, m_maincpu, 24_MHz_XTAL / 12);
- via6522_device &via(VIA6522(config, G65SC22P2_TAG, 24_MHz_XTAL / 12));
+ via6522_device &via(R65C22(config, G65SC22P2_TAG, 24_MHz_XTAL / 12));
via.readpa_handler().set(FUNC(fd2000_device::via_pa_r));
via.readpb_handler().set(FUNC(fd2000_device::via_pb_r));
via.writepa_handler().set(FUNC(fd2000_device::via_pa_w));
@@ -231,7 +233,7 @@ void fd2000_device::device_add_mconfig(machine_config &config)
add_common_devices(config);
m_maincpu->set_addrmap(AS_PROGRAM, &fd2000_device::fd2000_mem);
DP8473(config, m_fdc, 24_MHz_XTAL);
- FLOPPY_CONNECTOR(config, DP8473V_TAG":0", fd2000_floppies, "35hd", floppy_image_device::default_floppy_formats, true);//fd2000_device::floppy_formats);
+ FLOPPY_CONNECTOR(config, DP8473V_TAG":0", fd2000_floppies, "35hd", floppy_image_device::default_mfm_floppy_formats, true);//fd2000_device::floppy_formats);
}
void fd4000_device::device_add_mconfig(machine_config &config)
@@ -239,7 +241,7 @@ void fd4000_device::device_add_mconfig(machine_config &config)
add_common_devices(config);
m_maincpu->set_addrmap(AS_PROGRAM, &fd4000_device::fd4000_mem);
PC8477A(config, m_fdc, 24_MHz_XTAL);
- FLOPPY_CONNECTOR(config, PC8477AV1_TAG":0", fd4000_floppies, "35ed", floppy_image_device::default_floppy_formats, true);//fd2000_device::floppy_formats);
+ FLOPPY_CONNECTOR(config, PC8477AV1_TAG":0", fd4000_floppies, "35ed", floppy_image_device::default_mfm_floppy_formats, true);//fd2000_device::floppy_formats);
}
diff --git a/src/devices/bus/cbmiec/fd2000.h b/src/devices/bus/cbmiec/fd2000.h
index f116f5f8cfb..d632e77c11f 100644
--- a/src/devices/bus/cbmiec/fd2000.h
+++ b/src/devices/bus/cbmiec/fd2000.h
@@ -12,8 +12,7 @@
#pragma once
#include "cbmiec.h"
-#include "cpu/m6502/m65c02.h"
-#include "formats/d81_dsk.h"
+#include "cpu/m6502/w65c02.h"
#include "imagedev/floppy.h"
#include "machine/6522via.h"
#include "machine/upd765.h"
@@ -21,14 +20,6 @@
//**************************************************************************
-// MACROS / CONSTANTS
-//**************************************************************************
-
-#define FD2000_TAG "fd2000"
-
-
-
-//**************************************************************************
// TYPE DEFINITIONS
//**************************************************************************
@@ -41,23 +32,23 @@ public:
// construction/destruction
fd2000_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
- DECLARE_READ8_MEMBER( via_pa_r );
- DECLARE_WRITE8_MEMBER( via_pa_w );
- DECLARE_READ8_MEMBER( via_pb_r );
- DECLARE_WRITE8_MEMBER( via_pb_w );
+ uint8_t via_pa_r();
+ void via_pa_w(uint8_t data);
+ uint8_t via_pb_r();
+ void via_pb_w(uint8_t data);
- //DECLARE_FLOPPY_FORMATS( floppy_formats );
+ //static void floppy_formats(format_registration &fr);
protected:
fd2000_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_start() override ATTR_COLD;
+ virtual void device_reset() override ATTR_COLD;
// optional information overrides
- virtual const tiny_rom_entry *device_rom_region() const override;
- virtual void device_add_mconfig(machine_config &config) override;
+ virtual const tiny_rom_entry *device_rom_region() const override ATTR_COLD;
+ virtual void device_add_mconfig(machine_config &config) override ATTR_COLD;
// device_cbm_iec_interface overrides
void cbm_iec_srq(int state) override;
@@ -67,12 +58,12 @@ protected:
void add_common_devices(machine_config &config);
- required_device<m65c02_device> m_maincpu;
+ required_device<w65c02_device> m_maincpu;
required_device<upd765_family_device> m_fdc;
required_device<floppy_connector> m_floppy0;
private:
- void fd2000_mem(address_map &map);
+ void fd2000_mem(address_map &map) ATTR_COLD;
};
@@ -85,11 +76,11 @@ public:
fd4000_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;
- virtual void device_add_mconfig(machine_config &config) override;
+ virtual const tiny_rom_entry *device_rom_region() const override ATTR_COLD;
+ virtual void device_add_mconfig(machine_config &config) override ATTR_COLD;
private:
- void fd4000_mem(address_map &map);
+ void fd4000_mem(address_map &map) ATTR_COLD;
};
diff --git a/src/devices/bus/cbmiec/interpod.cpp b/src/devices/bus/cbmiec/interpod.cpp
index aa70ca015cc..b256f42de19 100644
--- a/src/devices/bus/cbmiec/interpod.cpp
+++ b/src/devices/bus/cbmiec/interpod.cpp
@@ -67,17 +67,13 @@ Notes:
//**************************************************************************
#define R6502_TAG "u1"
-#define R6532_TAG "u3"
-#define R6522_TAG "u4"
-#define MC6850_TAG "u5"
-#define RS232_TAG "rs232"
//**************************************************************************
// DEVICE DEFINITIONS
//**************************************************************************
-DEFINE_DEVICE_TYPE(INTERPOD, interpod_t, "interpod", "Interpod")
+DEFINE_DEVICE_TYPE(CBM_INTERPOD, cbm_interpod_device, "cbm_interpod", "Oxford Computer Systems Interpod")
@@ -103,7 +99,7 @@ ROM_END
// rom_region - device-specific ROM region
//-------------------------------------------------
-const tiny_rom_entry *interpod_t::device_rom_region() const
+const tiny_rom_entry *cbm_interpod_device::device_rom_region() const
{
return ROM_NAME( interpod );
}
@@ -113,13 +109,13 @@ const tiny_rom_entry *interpod_t::device_rom_region() const
// ADDRESS_MAP( interpod_mem )
//-------------------------------------------------
-void interpod_t::interpod_mem(address_map &map)
+void cbm_interpod_device::interpod_mem(address_map &map)
{
- map(0x0000, 0x007f).mirror(0x3b80).m(R6532_TAG, FUNC(mos6532_new_device::ram_map));
- map(0x0400, 0x041f).mirror(0x3be0).m(R6532_TAG, FUNC(mos6532_new_device::io_map));
- map(0x2000, 0x2001).mirror(0x9ffe).rw(MC6850_TAG, FUNC(acia6850_device::read), FUNC(acia6850_device::write));
+ 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(R6522_TAG, FUNC(via6522_device::map));
+ map(0x8000, 0x800f).mirror(0x5ff0).m(m_via, FUNC(via6522_device::map));
}
@@ -127,14 +123,14 @@ void interpod_t::interpod_mem(address_map &map)
// device_add_mconfig - add device configuration
//-------------------------------------------------
-void interpod_t::device_add_mconfig(machine_config &config)
+void cbm_interpod_device::device_add_mconfig(machine_config &config)
{
M6502(config, m_maincpu, 1000000);
- m_maincpu->set_addrmap(AS_PROGRAM, &interpod_t::interpod_mem);
+ m_maincpu->set_addrmap(AS_PROGRAM, &cbm_interpod_device::interpod_mem);
- VIA6522(config, m_via, 1000000);
+ MOS6522(config, m_via, 1000000);
- MOS6532_NEW(config, m_riot, 1000000);
+ MOS6532(config, m_riot, 1000000);
ACIA6850(config, m_acia, 0);
@@ -150,18 +146,18 @@ void interpod_t::device_add_mconfig(machine_config &config)
//**************************************************************************
//-------------------------------------------------
-// interpod_t - constructor
+// cbm_interpod_device - constructor
//-------------------------------------------------
-interpod_t::interpod_t(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) :
- device_t(mconfig, INTERPOD, tag, owner, clock),
+cbm_interpod_device::cbm_interpod_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) :
+ device_t(mconfig, CBM_INTERPOD, tag, owner, clock),
device_cbm_iec_interface(mconfig, *this),
m_maincpu(*this, R6502_TAG),
- m_via(*this, R6522_TAG),
- m_riot(*this, R6532_TAG),
- m_acia(*this, MC6850_TAG),
+ m_via(*this, "u4"),
+ m_riot(*this, "u3"),
+ m_acia(*this, "u5"),
m_ieee(*this, IEEE488_TAG),
- m_rs232(*this, RS232_TAG)
+ m_rs232(*this, "rs232")
{
}
@@ -170,7 +166,7 @@ interpod_t::interpod_t(const machine_config &mconfig, const char *tag, device_t
// device_start - device-specific startup
//-------------------------------------------------
-void interpod_t::device_start()
+void cbm_interpod_device::device_start()
{
}
@@ -179,6 +175,6 @@ void interpod_t::device_start()
// device_reset - device-specific reset
//-------------------------------------------------
-void interpod_t::device_reset()
+void cbm_interpod_device::device_reset()
{
}
diff --git a/src/devices/bus/cbmiec/interpod.h b/src/devices/bus/cbmiec/interpod.h
index 60f0d728bf9..66d47dea6fd 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"
@@ -25,38 +25,38 @@
// TYPE DEFINITIONS
//**************************************************************************
-// ======================> interpod_t
+// ======================> cbm_interpod_device
-class interpod_t : public device_t,
+class cbm_interpod_device : public device_t,
public device_cbm_iec_interface
{
public:
// construction/destruction
- interpod_t(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
+ cbm_interpod_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_start() override ATTR_COLD;
+ virtual void device_reset() override ATTR_COLD;
// optional information overrides
- virtual const tiny_rom_entry *device_rom_region() const override;
- virtual void device_add_mconfig(machine_config &config) override;
+ virtual const tiny_rom_entry *device_rom_region() const override ATTR_COLD;
+ virtual void device_add_mconfig(machine_config &config) override ATTR_COLD;
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;
- void interpod_mem(address_map &map);
+ void interpod_mem(address_map &map) ATTR_COLD;
};
// device type definition
-DECLARE_DEVICE_TYPE(INTERPOD, interpod_t)
+DECLARE_DEVICE_TYPE(CBM_INTERPOD, cbm_interpod_device)
#endif // MAME_BUS_CBMIEC_INTERPOD_H
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..b9f017724e1
--- /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 ATTR_COLD;
+ virtual void device_add_mconfig(machine_config &config) override ATTR_COLD;
+ virtual ioport_constructor device_input_ports() const override ATTR_COLD;
+ virtual const tiny_rom_entry *device_rom_region() const override ATTR_COLD;
+
+ // 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) ATTR_COLD;
+ void data_map(address_map &map) ATTR_COLD;
+
+ 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 ATTR_COLD;
+ virtual const tiny_rom_entry *device_rom_region() const override ATTR_COLD;
+};
+
+
+// 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/serialbox.cpp b/src/devices/bus/cbmiec/serialbox.cpp
index ab8326528d0..950cf46b964 100644
--- a/src/devices/bus/cbmiec/serialbox.cpp
+++ b/src/devices/bus/cbmiec/serialbox.cpp
@@ -32,7 +32,7 @@ enum
// DEVICE DEFINITIONS
//**************************************************************************
-DEFINE_DEVICE_TYPE(SERIAL_BOX, serial_box_device, "serbox", "Serial Box")
+DEFINE_DEVICE_TYPE(CBM_SERIAL_BOX, cbm_serial_box_device, "cbm_serbox", "Serial Box")
//-------------------------------------------------
@@ -49,7 +49,7 @@ ROM_END
// rom_region - device-specific ROM region
//-------------------------------------------------
-const tiny_rom_entry *serial_box_device::device_rom_region() const
+const tiny_rom_entry *cbm_serial_box_device::device_rom_region() const
{
return ROM_NAME( serial_box );
}
@@ -59,7 +59,7 @@ const tiny_rom_entry *serial_box_device::device_rom_region() const
// ADDRESS_MAP( serial_box_mem )
//-------------------------------------------------
-void serial_box_device::serial_box_mem(address_map &map)
+void cbm_serial_box_device::serial_box_mem(address_map &map)
{
map(0xf000, 0xffff).rom().region(M6502_TAG, 0);
}
@@ -69,10 +69,10 @@ void serial_box_device::serial_box_mem(address_map &map)
// device_add_mconfig - add device configuration
//-------------------------------------------------
-void serial_box_device::device_add_mconfig(machine_config &config)
+void cbm_serial_box_device::device_add_mconfig(machine_config &config)
{
- M65C02(config, m_maincpu, XTAL(4'000'000)/4);
- m_maincpu->set_addrmap(AS_PROGRAM, &serial_box_device::serial_box_mem);
+ W65C02(config, m_maincpu, XTAL(4'000'000)/4);
+ m_maincpu->set_addrmap(AS_PROGRAM, &cbm_serial_box_device::serial_box_mem);
}
@@ -82,11 +82,11 @@ void serial_box_device::device_add_mconfig(machine_config &config)
//**************************************************************************
//-------------------------------------------------
-// serial_box_device - constructor
+// cbm_serial_box_device - constructor
//-------------------------------------------------
-serial_box_device::serial_box_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
- : device_t(mconfig, SERIAL_BOX, tag, owner, clock),
+cbm_serial_box_device::cbm_serial_box_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
+ : device_t(mconfig, CBM_SERIAL_BOX, tag, owner, clock),
device_cbm_iec_interface(mconfig, *this),
m_maincpu(*this, M6502_TAG)
{
@@ -97,7 +97,7 @@ serial_box_device::serial_box_device(const machine_config &mconfig, const char *
// device_start - device-specific startup
//-------------------------------------------------
-void serial_box_device::device_start()
+void cbm_serial_box_device::device_start()
{
}
@@ -106,7 +106,7 @@ void serial_box_device::device_start()
// device_reset - device-specific reset
//-------------------------------------------------
-void serial_box_device::device_reset()
+void cbm_serial_box_device::device_reset()
{
}
@@ -115,7 +115,7 @@ void serial_box_device::device_reset()
// cbm_iec_atn -
//-------------------------------------------------
-void serial_box_device::cbm_iec_atn(int state)
+void cbm_serial_box_device::cbm_iec_atn(int state)
{
}
@@ -124,7 +124,7 @@ void serial_box_device::cbm_iec_atn(int state)
// cbm_iec_data -
//-------------------------------------------------
-void serial_box_device::cbm_iec_data(int state)
+void cbm_serial_box_device::cbm_iec_data(int state)
{
}
@@ -133,7 +133,7 @@ void serial_box_device::cbm_iec_data(int state)
// cbm_iec_reset -
//-------------------------------------------------
-void serial_box_device::cbm_iec_reset(int state)
+void cbm_serial_box_device::cbm_iec_reset(int state)
{
if (!state)
{
diff --git a/src/devices/bus/cbmiec/serialbox.h b/src/devices/bus/cbmiec/serialbox.h
index 396f9a85927..268013ffb45 100644
--- a/src/devices/bus/cbmiec/serialbox.h
+++ b/src/devices/bus/cbmiec/serialbox.h
@@ -11,16 +11,8 @@
#pragma once
-#include "cpu/m6502/m65c02.h"
-#include "bus/cbmiec/cbmiec.h"
-
-
-
-//**************************************************************************
-// MACROS / CONSTANTS
-//**************************************************************************
-
-#define SERIAL_BOX_TAG "serialbox"
+#include "cbmiec.h"
+#include "cpu/m6502/w65c02.h"
@@ -28,22 +20,22 @@
// TYPE DEFINITIONS
//**************************************************************************
-// ======================> serial_box_device
+// ======================> cbm_serial_box_device
-class serial_box_device : public device_t, public device_cbm_iec_interface
+class cbm_serial_box_device : public device_t, public device_cbm_iec_interface
{
public:
// construction/destruction
- serial_box_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
+ cbm_serial_box_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_start() override ATTR_COLD;
+ virtual void device_reset() override ATTR_COLD;
// optional information overrides
- virtual const tiny_rom_entry *device_rom_region() const override;
- virtual void device_add_mconfig(machine_config &config) override;
+ virtual const tiny_rom_entry *device_rom_region() const override ATTR_COLD;
+ virtual void device_add_mconfig(machine_config &config) override ATTR_COLD;
// device_cbm_iec_interface overrides
void cbm_iec_atn(int state) override;
@@ -51,14 +43,14 @@ protected:
void cbm_iec_reset(int state) override;
private:
- required_device<m65c02_device> m_maincpu;
+ required_device<w65c02_device> m_maincpu;
- void serial_box_mem(address_map &map);
+ void serial_box_mem(address_map &map) ATTR_COLD;
};
// device type definition
-DECLARE_DEVICE_TYPE(SERIAL_BOX, serial_box_device)
+DECLARE_DEVICE_TYPE(CBM_SERIAL_BOX, cbm_serial_box_device)
#endif // MAME_BUS_CBMIEC_SERIALBOX_H
diff --git a/src/devices/bus/cbmiec/vic1515.h b/src/devices/bus/cbmiec/vic1515.h
index 1b84636e6d3..80c555d6936 100644
--- a/src/devices/bus/cbmiec/vic1515.h
+++ b/src/devices/bus/cbmiec/vic1515.h
@@ -30,13 +30,13 @@ public:
protected:
// device-level overrides
- virtual void device_start() override;
- virtual void device_reset() override;
+ virtual void device_start() override ATTR_COLD;
+ virtual void device_reset() override ATTR_COLD;
// optional information 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 const tiny_rom_entry *device_rom_region() const override ATTR_COLD;
+ virtual void device_add_mconfig(machine_config &config) override ATTR_COLD;
+ virtual ioport_constructor device_input_ports() const override ATTR_COLD;
// device_cbm_iec_interface overrides
void cbm_iec_atn(int state) override;
@@ -44,8 +44,8 @@ protected:
void cbm_iec_reset(int state) override;
private:
- void vic1515_io(address_map &map);
- void vic1515_mem(address_map &map);
+ void vic1515_io(address_map &map) ATTR_COLD;
+ void vic1515_mem(address_map &map) ATTR_COLD;
};
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..d379f512e38 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,25 +26,33 @@ 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;
+ virtual void device_start() override ATTR_COLD;
// optional information 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 const tiny_rom_entry *device_rom_region() const override ATTR_COLD;
+ virtual void device_add_mconfig(machine_config &config) override ATTR_COLD;
+ virtual ioport_constructor device_input_ports() const override ATTR_COLD;
// 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/pc9801_amd98.cpp b/src/devices/bus/cbus/amd98.cpp
index ca7b32e7b4e..8edfecafe60 100644
--- a/src/devices/bus/cbus/pc9801_amd98.cpp
+++ b/src/devices/bus/cbus/amd98.cpp
@@ -1,19 +1,19 @@
// license:BSD-3-Clause
// copyright-holders:Angelo Salese
-/***************************************************************************
+/**************************************************************************************************
- System Sacom AMD-98 (AmuseMent boarD)
+System Sacom AMD-98 (AmuseMent boarD)
- 3 PSG chips, one of the first sound boards released for PC98
- Superseded by later NEC in-house sound boards
+3 PSG chips, one of the first sound boards released for PC98
+Superseded by later NEC in-house sound boards
- TODO:
- - not sure if it's AY8910 or YM2203, from a PCB pic it looks with stock AY logos?
- - Third AY (uses port B from BOTH AYs);
- - PIT control;
- - PCM section;
+TODO:
+- not sure if it's AY8910 or YM2203, from a PCB pic it looks with stock AY logos?
+- f/f not completely understood;
+- PIT control;
+- PCM section;
-=============================================================================
+===================================================================================================
- Known games with AMD-98 support
Brown's Run (System Sacom)
@@ -25,41 +25,52 @@
Relics (Bothtec)
Thexder (Game Arts)
-***************************************************************************/
+**************************************************************************************************/
#include "emu.h"
-#include "bus/cbus/pc9801_amd98.h"
+#include "bus/cbus/amd98.h"
#include "speaker.h"
+#define LOG_LATCH (1U << 1) // Detailed AY3 latch setups
+
+
+#define VERBOSE (LOG_GENERAL)
+//#define LOG_OUTPUT_FUNC osd_printf_info
+#include "logmacro.h"
+
+#define LOGLATCH(...) LOGMASKED(LOG_LATCH, __VA_ARGS__)
+
//**************************************************************************
// GLOBAL VARIABLES
//**************************************************************************
// device type definition
-DEFINE_DEVICE_TYPE(PC9801_AMD98, pc9801_amd98_device, "pc9801_amd98", "pc9801_amd98")
+DEFINE_DEVICE_TYPE(AMD98, amd98_device, "amd98", "System Sacom AMD-98")
//-------------------------------------------------
// device_add_mconfig - add device configuration
//-------------------------------------------------
-void pc9801_amd98_device::device_add_mconfig(machine_config &config)
+void amd98_device::device_add_mconfig(machine_config &config)
{
- SPEAKER(config, "lspeaker").front_left();
- SPEAKER(config, "rspeaker").front_right();
+ // Assume mono, as per highway making engine noise from ay1 only
+ SPEAKER(config, "speaker").front_center();
AY8910(config, m_ay1, 1'996'800);
m_ay1->port_a_read_callback().set_ioport("OPN_PA1");
- m_ay1->port_b_write_callback().set(FUNC(pc9801_amd98_device::ay3_address_w));
- m_ay1->add_route(ALL_OUTPUTS, "lspeaker", 0.50);
+ m_ay1->port_b_write_callback().set(FUNC(amd98_device::ay3_address_w));
+ m_ay1->add_route(ALL_OUTPUTS, "speaker", 0.50);
AY8910(config, m_ay2, 1'996'800);
m_ay2->port_a_read_callback().set_ioport("OPN_PA2");
- m_ay2->port_b_write_callback().set(FUNC(pc9801_amd98_device::ay3_data_latch_w));
- m_ay2->add_route(ALL_OUTPUTS, "rspeaker", 0.50);
+ m_ay2->port_b_write_callback().set(FUNC(amd98_device::ay3_data_latch_w));
+ m_ay2->add_route(ALL_OUTPUTS, "speaker", 0.50);
AY8910(config, m_ay3, 1'996'800);
- m_ay3->add_route(ALL_OUTPUTS, "lspeaker", 0.25);
- m_ay3->add_route(ALL_OUTPUTS, "rspeaker", 0.25);
+ m_ay3->port_b_write_callback().set([this] (u8 data) {
+ LOG("AMD-98 DAC %02x\n", data);
+ });
+ m_ay3->add_route(ALL_OUTPUTS, "speaker", 0.25);
}
static INPUT_PORTS_START( pc9801_amd98 )
@@ -84,7 +95,7 @@ static INPUT_PORTS_START( pc9801_amd98 )
PORT_BIT( 0x80, IP_ACTIVE_LOW, IPT_UNUSED )
INPUT_PORTS_END
-ioport_constructor pc9801_amd98_device::device_input_ports() const
+ioport_constructor amd98_device::device_input_ports() const
{
return INPUT_PORTS_NAME( pc9801_amd98 );
}
@@ -97,15 +108,15 @@ ioport_constructor pc9801_amd98_device::device_input_ports() const
//**************************************************************************
//-------------------------------------------------
-// pc9801_amd98_device - constructor
+// amd98_device - constructor
//-------------------------------------------------
-pc9801_amd98_device::pc9801_amd98_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
- : device_t(mconfig, PC9801_AMD98, tag, owner, clock),
- m_bus(*this, DEVICE_SELF_OWNER),
- m_ay1(*this, "ay1"),
- m_ay2(*this, "ay2"),
- m_ay3(*this, "ay3")
+amd98_device::amd98_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
+ : device_t(mconfig, AMD98, tag, owner, clock)
+ , m_bus(*this, DEVICE_SELF_OWNER)
+ , m_ay1(*this, "ay1")
+ , m_ay2(*this, "ay2")
+ , m_ay3(*this, "ay3")
{
}
@@ -115,7 +126,7 @@ pc9801_amd98_device::pc9801_amd98_device(const machine_config &mconfig, const ch
// on this device
//-------------------------------------------------
-void pc9801_amd98_device::device_validity_check(validity_checker &valid) const
+void amd98_device::device_validity_check(validity_checker &valid) const
{
}
@@ -123,7 +134,7 @@ void pc9801_amd98_device::device_validity_check(validity_checker &valid) const
// device_start - device-specific startup
//-------------------------------------------------
-void pc9801_amd98_device::device_start()
+void amd98_device::device_start()
{
}
@@ -132,11 +143,11 @@ void pc9801_amd98_device::device_start()
// device_reset - device-specific reset
//-------------------------------------------------
-void pc9801_amd98_device::device_reset()
+void amd98_device::device_reset()
{
- m_bus->install_io(0x00d8, 0x00df, read8_delegate(FUNC(pc9801_amd98_device::read), this), write8_delegate(FUNC(pc9801_amd98_device::write), this) );
- // Thexder access with following
- m_bus->install_io(0x38d8, 0x38df, read8_delegate(FUNC(pc9801_amd98_device::read), this), write8_delegate(FUNC(pc9801_amd98_device::write), this) );
+ m_bus->install_io(0x00d8, 0x00df, read8sm_delegate(*this, FUNC(amd98_device::read)), write8sm_delegate(*this, FUNC(amd98_device::write)));
+ // thexder access with following
+ m_bus->install_io(0x38d8, 0x38df, read8sm_delegate(*this, FUNC(amd98_device::read)), write8sm_delegate(*this, FUNC(amd98_device::write)));
}
@@ -144,7 +155,7 @@ void pc9801_amd98_device::device_reset()
// READ/WRITE HANDLERS
//**************************************************************************
-READ8_MEMBER(pc9801_amd98_device::read)
+uint8_t amd98_device::read(offs_t offset)
{
switch(offset)
{
@@ -154,12 +165,12 @@ READ8_MEMBER(pc9801_amd98_device::read)
return m_ay2->data_r();
}
- printf("%02x\n",offset);
+ LOG("AMD-98: unhandled %02x read\n", offset + 0xd8);
return 0xff;
}
-WRITE8_MEMBER(pc9801_amd98_device::write)
+void amd98_device::write(offs_t offset, uint8_t data)
{
switch(offset)
{
@@ -176,27 +187,34 @@ WRITE8_MEMBER(pc9801_amd98_device::write)
m_ay2->data_w(data);
break;
default:
- printf("%02x %02x\n",offset,data);
+ LOG("AMD-98: unhandled %02x write %02x\n", offset + 0xd8, data);
}
}
-WRITE8_MEMBER(pc9801_amd98_device::ay3_address_w)
+void amd98_device::ay3_address_w(uint8_t data)
{
+ LOGLATCH("AMD-98 AY3 latch %02x\n", data);
m_ay3_latch = data;
}
-WRITE8_MEMBER(pc9801_amd98_device::ay3_data_latch_w)
+void amd98_device::ay3_data_latch_w(uint8_t data)
{
- // TODO: this actually uses a flip flop mechanism, not quite sure about how it works yet
- switch(data)
+ // TODO: actually goes 0 -> 1 -> 0
+ // TODO: thexder is the odd one: uses 0x00 -> 0x40 -> 0x47 (address) -> 0x40 -> 0x40 -> 0x43 (data) -> 0x40
+ if (!BIT(m_ay3_ff, 0) && BIT(data, 0))
{
- case 0x47:
- //printf("%02x addr\n",m_ay3_latch);
- m_ay3->address_w(m_ay3_latch);
- break;
- case 0x43:
- //printf("%02x data\n",m_ay3_latch);
- m_ay3->data_w(m_ay3_latch);
- break;
+ switch(data & 0xc2)
+ {
+ case 0x42:
+ LOG("AMD-98 AY3 write %02x address (f/f %02x)\n", m_ay3_latch, m_ay3_ff);
+ m_ay3->address_w(m_ay3_latch);
+ break;
+ case 0x40:
+ LOG("AMD-98 AY3 write %02x data (f/f %02x)\n", m_ay3_latch, m_ay3_ff);
+ m_ay3->data_w(m_ay3_latch);
+ break;
+ }
}
+ LOGLATCH("AMD-98 f/f %02x %02x\n", data, m_ay3_latch);
+ m_ay3_ff = data;
}
diff --git a/src/devices/bus/cbus/pc9801_amd98.h b/src/devices/bus/cbus/amd98.h
index 993cd6e9e4b..c97be6cb3b5 100644
--- a/src/devices/bus/cbus/pc9801_amd98.h
+++ b/src/devices/bus/cbus/amd98.h
@@ -2,50 +2,49 @@
// copyright-holders:Angelo Salese
/***************************************************************************
- NEC PC-9801-118
+ System Sacom AMD-98 (AmuseMent boarD)
***************************************************************************/
-#ifndef MAME_BUS_CBUS_PC9801_AMD98_H
-#define MAME_BUS_CBUS_PC9801_AMD98_H
+#ifndef MAME_BUS_CBUS_AMD98_H
+#define MAME_BUS_CBUS_AMD98_H
#pragma once
#include "bus/cbus/pc9801_cbus.h"
#include "sound/ay8910.h"
-
//**************************************************************************
// TYPE DEFINITIONS
//**************************************************************************
-// ======================> pc9801_118_device
+// ======================> amd98_device
-class pc9801_amd98_device : public device_t
+class amd98_device : public device_t
{
public:
// construction/destruction
- pc9801_amd98_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
+ amd98_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
static constexpr feature_type imperfect_features() { return feature::SOUND; }
- DECLARE_READ8_MEMBER(read);
- DECLARE_WRITE8_MEMBER(write);
+ uint8_t read(offs_t offset);
+ void write(offs_t offset, uint8_t data);
protected:
// device-level overrides
virtual void device_validity_check(validity_checker &valid) const override;
- virtual void device_start() override;
- virtual void device_reset() override;
+ virtual void device_start() override ATTR_COLD;
+ virtual void device_reset() override ATTR_COLD;
// optional information overrides
- virtual void device_add_mconfig(machine_config &config) override;
- virtual ioport_constructor device_input_ports() const override;
+ virtual void device_add_mconfig(machine_config &config) override ATTR_COLD;
+ virtual ioport_constructor device_input_ports() const override ATTR_COLD;
private:
- DECLARE_WRITE8_MEMBER(ay3_address_w);
- DECLARE_WRITE8_MEMBER(ay3_data_latch_w);
+ void ay3_address_w(uint8_t data);
+ void ay3_data_latch_w(uint8_t data);
- uint8_t m_ay3_latch;
+ uint8_t m_ay3_latch, m_ay3_ff;
required_device<pc9801_slot_device> m_bus;
required_device<ay8910_device> m_ay1;
@@ -54,12 +53,7 @@ private:
};
-
// device type definition
-DECLARE_DEVICE_TYPE(PC9801_AMD98, pc9801_amd98_device)
-
-
-
-
+DECLARE_DEVICE_TYPE(AMD98, amd98_device)
-#endif // MAME_BUS_CBUS_PC9801_118_H
+#endif // MAME_BUS_CBUS_AMD98_H
diff --git a/src/devices/bus/cbus/mif201.cpp b/src/devices/bus/cbus/mif201.cpp
new file mode 100644
index 00000000000..012928f5db4
--- /dev/null
+++ b/src/devices/bus/cbus/mif201.cpp
@@ -0,0 +1,70 @@
+// license:BSD-3-Clause
+// copyright-holders: Angelo Salese
+/**************************************************************************************************
+
+MIF-201 MIDI interface
+
+Bundled with Micro Musician VA
+
+References:
+- https://mamedev.emulab.it/kale/fast/files/micromusician_va.jpg
+
+TODO:
+- evasive, needs manual, dip-switch sheet and PCB pictures;
+
+**************************************************************************************************/
+
+#include "emu.h"
+#include "mif201.h"
+
+DEFINE_DEVICE_TYPE(MIF201, mif201_device, "mif201", "Micro Musician VA MIF-201 MIDI Interface")
+
+mif201_device::mif201_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
+ : device_t(mconfig, MIF201, tag, owner, clock)
+ , m_bus(*this, DEVICE_SELF_OWNER)
+ , m_uart(*this, "uart%u", 1U)
+ , m_pit(*this, "pit")
+{
+}
+
+//void mif201_device::irq_out(int state)
+//{
+// m_bus->int_w<2>(state);
+//}
+
+
+void mif201_device::device_add_mconfig(machine_config &config)
+{
+ // TODO: unknown clocks
+ I8251(config, m_uart[0], 1021800);
+
+ I8251(config, m_uart[1], 1021800);
+
+ PIT8253(config, m_pit, 1021800);
+}
+
+void mif201_device::device_start()
+{
+ // sheet claims i8251-1 having swapped ports compared to i8251-2 but micromus just uses
+ // $e2d2 for control, assume typo.
+ m_bus->install_io(0xe2d0, 0xe2d3,
+ read8sm_delegate(*this, [this](offs_t offset) { return m_uart[0]->read(offset); }, "uart1_r"),
+ write8sm_delegate(*this, [this](offs_t offset, u8 data) { m_uart[0]->write(offset, data); }, "uart1_w")
+ );
+ m_bus->install_io(0xe4d0, 0xe4d3,
+ read8sm_delegate(*this, [this](offs_t offset) { return m_uart[1]->read(offset); }, "uart2_r"),
+ write8sm_delegate(*this, [this](offs_t offset, u8 data) { m_uart[1]->write(offset, data); }, "uart2_w")
+ );
+ m_bus->install_io(0xe6d0, 0xe6d3,
+ read8sm_delegate(*this, [this](offs_t offset) { return m_pit->read(offset); }, "pit_low_r"),
+ write8sm_delegate(*this, [this](offs_t offset, u8 data) { m_pit->write(offset, data); }, "pit_low_w")
+ );
+ m_bus->install_io(0xe7d0, 0xe7d3,
+ read8sm_delegate(*this, [this](offs_t offset) { return m_pit->read(offset | 2); }, "pit_high_r"),
+ write8sm_delegate(*this, [this](offs_t offset, u8 data) { m_pit->write(offset | 2, data); }, "pit_high_w")
+ );
+}
+
+void mif201_device::device_reset()
+{
+}
diff --git a/src/devices/bus/cbus/mif201.h b/src/devices/bus/cbus/mif201.h
new file mode 100644
index 00000000000..1ef33e647d2
--- /dev/null
+++ b/src/devices/bus/cbus/mif201.h
@@ -0,0 +1,46 @@
+// license:BSD-3-Clause
+// copyright-holders: Angelo Salese
+#ifndef MAME_BUS_CBUS_MIF201_H
+#define MAME_BUS_CBUS_MIF201_H
+
+#pragma once
+
+#include "bus/cbus/pc9801_cbus.h"
+#include "machine/i8251.h"
+#include "machine/pit8253.h"
+
+//**************************************************************************
+// TYPE DEFINITIONS
+//**************************************************************************
+
+// ======================> mpu_pc98_device
+
+class mif201_device : public device_t
+{
+public:
+ // construction/destruction
+ mif201_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
+
+ static constexpr feature_type unemulated_features() { return feature::SOUND; }
+
+protected:
+ // device-level overrides
+ virtual void device_start() override ATTR_COLD;
+ virtual void device_reset() override ATTR_COLD;
+
+ // optional information overrides
+ virtual void device_add_mconfig(machine_config &config) override ATTR_COLD;
+
+private:
+ required_device<pc9801_slot_device> m_bus;
+ required_device_array<i8251_device, 2> m_uart;
+ required_device<pit8253_device> m_pit;
+
+// void map(address_map &map);
+};
+
+
+// device type definition
+DECLARE_DEVICE_TYPE(MIF201, mif201_device)
+
+#endif // MAME_BUS_CBUS_MIF201_H
diff --git a/src/devices/bus/cbus/mpu_pc98.cpp b/src/devices/bus/cbus/mpu_pc98.cpp
index 2230e966fda..757e90006a9 100644
--- a/src/devices/bus/cbus/mpu_pc98.cpp
+++ b/src/devices/bus/cbus/mpu_pc98.cpp
@@ -30,15 +30,16 @@ DIP-SWs
1 irq3
*/
-WRITE_LINE_MEMBER( mpu_pc98_device::mpu_irq_out )
+void mpu_pc98_device::mpu_irq_out(int state)
{
+ m_bus->int_w<2>(state);
}
//**************************************************************************
// GLOBAL VARIABLES
//**************************************************************************
-DEFINE_DEVICE_TYPE(MPU_PC98, mpu_pc98_device, "mpu_pc98", "Roland MPU-401 MIDI Interface (CBUS)")
+DEFINE_DEVICE_TYPE(MPU_PC98, mpu_pc98_device, "mpu_pc98", "Roland MPU-401 MIDI Interface (C-bus)")
//-------------------------------------------------
// device_add_mconfig - add device configuration
diff --git a/src/devices/bus/cbus/mpu_pc98.h b/src/devices/bus/cbus/mpu_pc98.h
index 798f8b8f11e..71c6d5c6f11 100644
--- a/src/devices/bus/cbus/mpu_pc98.h
+++ b/src/devices/bus/cbus/mpu_pc98.h
@@ -1,7 +1,7 @@
// license:BSD-3-Clause
// copyright-holders:R. Belmont,Kevin Horton
-#ifndef MAME_BUS_CBUS_MPU401_H
-#define MAME_BUS_CBUS_MPU401_H
+#ifndef MAME_BUS_CBUS_MPU_PC98_H
+#define MAME_BUS_CBUS_MPU_PC98_H
#pragma once
@@ -12,7 +12,7 @@
// TYPE DEFINITIONS
//**************************************************************************
-// ======================> isa8_mpu401_device
+// ======================> mpu_pc98_device
class mpu_pc98_device : public device_t
{
@@ -22,17 +22,17 @@ public:
protected:
// device-level overrides
- virtual void device_start() override;
- virtual void device_reset() override;
+ virtual void device_start() override ATTR_COLD;
+ virtual void device_reset() override ATTR_COLD;
// optional information overrides
- virtual void device_add_mconfig(machine_config &config) override;
+ virtual void device_add_mconfig(machine_config &config) override ATTR_COLD;
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);
+ void map(address_map &map) ATTR_COLD;
required_device<pc9801_slot_device> m_bus;
required_device<mpu401_device> m_mpu401;
@@ -42,4 +42,4 @@ private:
// device type definition
DECLARE_DEVICE_TYPE(MPU_PC98, mpu_pc98_device)
-#endif // MAME_BUS_CBUS_MPU401_H
+#endif // MAME_BUS_CBUS_MPU_PC98_H
diff --git a/src/devices/bus/cbus/pc9801_118.cpp b/src/devices/bus/cbus/pc9801_118.cpp
index a9271ecb0bf..7a64ddbad17 100644
--- a/src/devices/bus/cbus/pc9801_118.cpp
+++ b/src/devices/bus/cbus/pc9801_118.cpp
@@ -1,21 +1,32 @@
// license:BSD-3-Clause
// copyright-holders:Angelo Salese
-/***************************************************************************
+/**************************************************************************************************
- NEC PC-9801-118 sound card
+NEC PC-9801-118 sound card "CanBe Sound 2"
- YMF297 + some extra ports
+References:
+- https://sammargh.github.io/pc98/ext_card_doc/9801-118.txt
- TODO:
- - preliminary, presumably needs CS-4232 too, it's an extended clone of the already emulated AD1848 used on the Windows Sound System
- - verify sound irq;
+YMF297 + some extra ports, apparently derived from -86.
+Introduced around the same time as Windows 95 release, it has various compatibility issues
+under DOS (especially when PnP is enabled).
+Doesn't have a sound ROM, it also cannot be installed with an environment also sporting a -86.
-***************************************************************************/
+TODO:
+- Fix sound chip type (YMF297-F);
+- Add CS-4232 support, it's an extended clone of the already emulated AD1848 used on the
+ Windows Sound System;
+- Understand what the obfuscated NEC "ANCHOR" and "MAZE" chips really are;
+- PnP interface (missing BIOS);
+- verify sound irq;
+- test if driver can be installed under Windows 95;
+
+**************************************************************************************************/
#include "emu.h"
#include "bus/cbus/pc9801_118.h"
-#include "sound/2608intf.h"
+#include "sound/ymopn.h"
#include "speaker.h"
@@ -27,30 +38,25 @@
//**************************************************************************
// device type definition
-DEFINE_DEVICE_TYPE(PC9801_118, pc9801_118_device, "pc9801_118", "pc9801_118")
+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::device_add_mconfig(machine_config &config)
{
- /* TODO: seems to die very often */
- m_bus->int_w<5>(state);
-}
+ // TODO: "ANCHOR" & "MAZE" custom NEC chips
+ // sourced by 5D clock
-//-------------------------------------------------
-// device_add_mconfig - add device configuration
-//-------------------------------------------------
+ SPEAKER(config, "speaker", 2).front();
-void pc9801_118_device::device_add_mconfig(machine_config &config)
-{
- SPEAKER(config, "lspeaker").front_left();
- SPEAKER(config, "rspeaker").front_right();
- YM2608(config, m_opn3, XTAL_5B * 2 / 5); // actually YMF297-F, unknown clock / divider, more likely uses 5D clock
- m_opn3->irq_handler().set(FUNC(pc9801_118_device::sound_irq));
- m_opn3->port_a_read_callback().set(FUNC(pc9801_118_device::opn_porta_r));
- //m_opn3->port_b_read_callback().set(FUNC(pc8801_state::opn_portb_r));
- //m_opn3->port_a_write_callback().set(FUNC(pc8801_state::opn_porta_w));
- m_opn3->port_b_write_callback().set(FUNC(pc9801_118_device::opn_portb_w));
- m_opn3->add_route(ALL_OUTPUTS, "lspeaker", 1.00);
- m_opn3->add_route(ALL_OUTPUTS, "rspeaker", 1.00);
+ // actually YMF297-F (YMF288 + OPL3 compatible FM sources), unknown clock / divider
+ // 5B is near both CS-4232 and this
+ YM2608(config, m_opn3, XTAL_5B * 2 / 5);
+ m_opn3->irq_handler().set([this] (int state) { m_bus->int_w<5>(state); });
+// m_opn3->port_a_read_callback().set(FUNC(pc9801_118_device::opn_porta_r));
+// m_opn3->port_b_write_callback().set(FUNC(pc9801_118_device::opn_portb_w));
+ m_opn3->add_route(ALL_OUTPUTS, "speaker", 1.00, 0);
+ m_opn3->add_route(ALL_OUTPUTS, "speaker", 1.00, 1);
+
+ // TODO: DA-15 PC gameport labeled "MIDI / Joystick"
}
@@ -59,12 +65,48 @@ void pc9801_118_device::device_add_mconfig(machine_config &config)
//-------------------------------------------------
static INPUT_PORTS_START( pc9801_118 )
- PORT_INCLUDE( pc9801_joy_port )
-
- PORT_START("OPN3_DSW")
- PORT_CONFNAME( 0x01, 0x00, "PC-9801-118: Port Base" )
- PORT_CONFSETTING( 0x00, "0x088" )
- PORT_CONFSETTING( 0x01, "0x188" )
+ // 12 line Jumper settings @ 8F
+ // documented at https://sammargh.github.io/pc98/ext_card_doc/9801-118.txt
+ // TODO: understand how SW can read these
+ PORT_START("OPN3_JP_8F")
+ PORT_CONFNAME( 0x001, 0x000, "PC-9801-118: Enable Plug and Play" ) // [1]
+ PORT_CONFSETTING( 0x000, DEF_STR( No ) )
+ PORT_CONFSETTING( 0x001, DEF_STR( Yes ) )
+ // "group" is basically a obnoxious machine ID
+ // details are in the aforementioned link, in a nutshell should be:
+ // Group 1: later CanBe (Cb onward)
+ // Group 2: early CanBe (Ce, Ce2, Cs2), 9821 MATE A
+ // Group 4: several ValueStar models
+ // Group 5: 9821 MATE B, Notebooks, 9801 BX, some H98 models
+ // Group 3: anything not covered above (link also mentions BX4 here?)
+ // In practice this should really be tested on field ...
+ PORT_CONFNAME( 0x406, 0x000, "PC-9801-118: PCM Group select") // [2, 3, 11]
+ PORT_CONFSETTING( 0x000, "Groups 2, 3, 4, 5" ) // uses -118 PCM
+ PORT_CONFSETTING( 0x404, "Group 3" ) // uses PCM host
+ PORT_CONFSETTING( 0x002, "Group 1" ) // ?
+ // all other settings "prohibited"
+ PORT_CONFNAME( 0x008, 0x008, "PC-9801-118: unknown [4]" ) // [4] "prohibited", always ON
+ PORT_CONFSETTING( 0x000, DEF_STR( Off ) )
+ PORT_CONFSETTING( 0x008, DEF_STR( On ) )
+ PORT_CONFNAME( 0x030, 0x000, "PC-9801-118: FM Interrupt setting" ) // [5,6]
+ PORT_CONFSETTING( 0x000, "INT5 (IRQ12)" )
+ PORT_CONFSETTING( 0x010, "INT6 (IRQ13)" )
+ PORT_CONFSETTING( 0x020, "INT41 (IRQ10)" )
+ PORT_CONFSETTING( 0x030, "INT0 (IRQ3)")
+ PORT_CONFNAME( 0x040, 0x000, "PC-9801-118: DMA channel" ) // [7]
+ PORT_CONFSETTING( 0x000, "1" )
+ PORT_CONFSETTING( 0x040, "2" )
+ PORT_CONFNAME( 0x180, 0x000, "PC-9801-118: PCM Interrupt setting" ) // [8,9]
+ PORT_CONFSETTING( 0x000, "INT5 (IRQ12)" )
+ PORT_CONFSETTING( 0x080, "INT1 (IRQ5)" )
+ PORT_CONFSETTING( 0x100, "INT41 (IRQ10)" )
+ PORT_CONFSETTING( 0x180, "INT0 (IRQ3)" )
+ PORT_CONFNAME( 0x200, 0x000, "PC-9801-118: enable MIDI Interrupt" ) // [10]
+ PORT_CONFSETTING( 0x000, DEF_STR( No ) )
+ PORT_CONFSETTING( 0x200, DEF_STR( Yes ) ) // auto for PnP, INT41 for non-PnP
+ PORT_CONFNAME( 0x800, 0x000, "PC-9801-118: unknown [12]" ) // [12] "prohibited", always OFF
+ PORT_CONFSETTING( 0x000, DEF_STR( Off ) )
+ PORT_CONFSETTING( 0x800, DEF_STR( On ) )
INPUT_PORTS_END
ioport_constructor pc9801_118_device::device_input_ports() const
@@ -72,8 +114,14 @@ ioport_constructor pc9801_118_device::device_input_ports() const
return INPUT_PORTS_NAME( pc9801_118 );
}
-// RAM
ROM_START( pc9801_118 )
+ ROM_REGION( 0x20000, "pnp_bios", ROMREGION_ERASE00 )
+ // NB: either socket is exclusively populated, earlier models populates 1E while later populates 2E.
+ // Most likely contains same data or slight revision bump.
+ // μPD27c1024 socket
+ ROM_LOAD( "118 e316.1e", 0x00000, 0x20000, NO_DUMP )
+ // LH531024N socket at .2e (unreadable label)
+
ROM_REGION( 0x100000, "opn3", ROMREGION_ERASE00 )
ROM_END
@@ -91,45 +139,36 @@ const tiny_rom_entry *pc9801_118_device::device_rom_region() const
//-------------------------------------------------
pc9801_118_device::pc9801_118_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
- : pc9801_snd_device(mconfig, PC9801_118, tag, owner, clock),
+ : device_t(mconfig, PC9801_118, tag, owner, clock),
m_bus(*this, DEVICE_SELF_OWNER),
m_opn3(*this, "opn3")
{
}
-
-//-------------------------------------------------
-// device_validity_check - perform validity checks
-// on this device
-//-------------------------------------------------
-
-void pc9801_118_device::device_validity_check(validity_checker &valid) const
-{
-}
-
-//-------------------------------------------------
-// device_start - device-specific startup
-//-------------------------------------------------
-
-
void pc9801_118_device::device_start()
{
- m_bus->install_io(0xa460, 0xa463, read8_delegate(FUNC(pc9801_118_device::id_r), this), write8_delegate(FUNC(pc9801_118_device::ext_w), this) );
+ // hardwired on this board
+ const u16 m_io_base = 0x0188;
+ m_bus->install_io(0xa460, 0xa463, read8sm_delegate(*this, FUNC(pc9801_118_device::id_r)), write8sm_delegate(*this, FUNC(pc9801_118_device::ext_w)));
+
+ m_bus->install_io(
+ m_io_base,
+ m_io_base + 7,
+ read8sm_delegate(*this, FUNC(pc9801_118_device::opn3_r)),
+ write8sm_delegate(*this, FUNC(pc9801_118_device::opn3_w))
+ );
save_item(NAME(m_ext_reg));
}
-
-//-------------------------------------------------
-// device_reset - device-specific reset
-//-------------------------------------------------
-
void pc9801_118_device::device_reset()
{
- uint16_t port_base = (ioport("OPN3_DSW")->read() & 1) << 8;
- m_bus->io_space().unmap_readwrite(0x0088, 0x008b, 0x100);
- m_bus->install_io(port_base + 0x0088, port_base + 0x008f, read8_delegate(FUNC(pc9801_118_device::opn3_r), this), write8_delegate(FUNC(pc9801_118_device::opn3_w), this) );
- m_ext_reg = 1; // TODO: enabled or disabled?
+ // TODO: is this enabled or disabled at boot?
+ m_ext_reg = 1;
+}
+
+void pc9801_118_device::device_validity_check(validity_checker &valid) const
+{
}
@@ -138,9 +177,9 @@ void pc9801_118_device::device_reset()
//**************************************************************************
-READ8_MEMBER(pc9801_118_device::opn3_r)
+uint8_t pc9801_118_device::opn3_r(offs_t offset)
{
- if(((offset & 5) == 0) || m_ext_reg)
+ if(((offset & 5) == 0) || m_ext_reg )
return m_opn3->read(offset >> 1);
else // odd
{
@@ -150,36 +189,37 @@ READ8_MEMBER(pc9801_118_device::opn3_r)
}
-WRITE8_MEMBER(pc9801_118_device::opn3_w)
+void pc9801_118_device::opn3_w(offs_t offset, uint8_t data)
{
- if(((offset & 5) == 0) || m_ext_reg)
+ if( ((offset & 5) == 0) || m_ext_reg )
m_opn3->write(offset >> 1,data);
//else // odd
// printf("PC9801-118: Write to undefined port [%02x] %02x\n",offset+0x188,data);
}
-READ8_MEMBER( pc9801_118_device::id_r )
+uint8_t pc9801_118_device::id_r(offs_t offset)
{
if(offset == 0)
{
- printf("OPN3 EXT read ID [%02x]\n",offset);
+ logerror("OPN3 EXT read ID [%02x]\n",offset);
+ // TODO: confirm ID
+ // by assumption we make this same as later CanBe releases, may or may not be right
return 0x80 | (m_ext_reg & 1);
}
- printf("OPN3 EXT read unk [%02x]\n",offset);
+ logerror("OPN3 EXT read unk [%02x]\n", offset);
return 0xff;
}
-WRITE8_MEMBER( pc9801_118_device::ext_w )
+void pc9801_118_device::ext_w(offs_t offset, uint8_t data)
{
if(offset == 0)
{
m_ext_reg = data & 1;
- /* TODO: apparently writing a 1 doubles the available channels (and presumably enables CS-4231 too) */
- if(data)
- printf("PC-9801-118: extended register %02x write\n",data);
+ if(data & 2)
+ logerror("%s: extended register %02x write\n", machine().describe_context(), data);
return;
}
- printf("OPN3 EXT write unk %02x -> [%02x]\n",data,offset);
+ logerror("%s: EXT write unk %02x -> [%02x]\n", machine().describe_context(), data, offset);
}
diff --git a/src/devices/bus/cbus/pc9801_118.h b/src/devices/bus/cbus/pc9801_118.h
index 491179a478c..3e2dc05395a 100644
--- a/src/devices/bus/cbus/pc9801_118.h
+++ b/src/devices/bus/cbus/pc9801_118.h
@@ -11,10 +11,9 @@
#pragma once
-#include "bus/cbus/pc9801_cbus.h"
-#include "sound/2608intf.h"
-#include "pc9801_snd.h"
+#include "sound/ymopn.h"
+#include "pc9801_cbus.h"
//**************************************************************************
// TYPE DEFINITIONS
@@ -22,34 +21,36 @@
// ======================> pc9801_118_device
-class pc9801_118_device : public pc9801_snd_device
+class pc9801_118_device : public device_t
{
public:
// construction/destruction
pc9801_118_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
- DECLARE_READ8_MEMBER(opn3_r);
- DECLARE_WRITE8_MEMBER(opn3_w);
- DECLARE_READ8_MEMBER(id_r);
- DECLARE_WRITE8_MEMBER(ext_w);
+ static constexpr feature_type imperfect_features() { return feature::SOUND; }
+
+ uint8_t opn3_r(offs_t offset);
+ void opn3_w(offs_t offset, uint8_t data);
+ uint8_t id_r(offs_t offset);
+ void ext_w(offs_t offset, uint8_t data);
protected:
// device-level overrides
virtual void device_validity_check(validity_checker &valid) const override;
- virtual void device_start() override;
- virtual void device_reset() override;
+ virtual void device_start() override ATTR_COLD;
+ virtual void device_reset() override ATTR_COLD;
// optional information 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;
+ virtual void device_add_mconfig(machine_config &config) override ATTR_COLD;
+ virtual ioport_constructor device_input_ports() const override ATTR_COLD;
+ virtual const tiny_rom_entry *device_rom_region() const override ATTR_COLD;
private:
required_device<pc9801_slot_device> m_bus;
required_device<ym2608_device> m_opn3;
- uint8_t m_ext_reg;
+// u16 m_io_base, m_joy_sel;
- DECLARE_WRITE_LINE_MEMBER(sound_irq);
+ uint8_t m_ext_reg;
};
diff --git a/src/devices/bus/cbus/pc9801_26.cpp b/src/devices/bus/cbus/pc9801_26.cpp
index 603ea4a80b3..e86a276c619 100644
--- a/src/devices/bus/cbus/pc9801_26.cpp
+++ b/src/devices/bus/cbus/pc9801_26.cpp
@@ -1,20 +1,22 @@
// license:BSD-3-Clause
// copyright-holders:Angelo Salese
-/***************************************************************************
+/**************************************************************************************************
- NEC PC-9801-26 sound card
+NEC PC-9801-26 sound card
- Legacy sound card for PC-98xx family, composed by a single YM2203
+Legacy sound card for PC-98xx family, composed by a single YM2203
- TODO:
- - verify sound irq;
+TODO:
+- DE-9 output writes (cfr. page 419 of PC-9801 Bible, needs software testing the functionality)
+- understand if dips can be read by SW;
+- configurable irq level needs a binding flush in C-bus handling;
-***************************************************************************/
+**************************************************************************************************/
#include "emu.h"
#include "bus/cbus/pc9801_26.h"
-#include "sound/2203intf.h"
+#include "sound/ymopn.h"
#include "speaker.h"
@@ -23,29 +25,68 @@
//**************************************************************************
// device type definition
-DEFINE_DEVICE_TYPE(PC9801_26, pc9801_26_device, "pc9801_26", "pc9801_26")
+DEFINE_DEVICE_TYPE(PC9801_26, pc9801_26_device, "pc9801_26", "NEC PC-9801-26/K")
-WRITE_LINE_MEMBER(pc9801_26_device::sound_irq)
+pc9801_26_device::pc9801_26_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
+ : device_t(mconfig, PC9801_26, tag, owner, clock)
+ , m_bus(*this, DEVICE_SELF_OWNER)
+ , m_opn(*this, "opn")
+ , m_joy(*this, "joy_p%u", 1U)
+ , m_irq_jp(*this, "JP6A1_JP6A3")
{
- /* TODO: seems to die very often */
- m_bus->int_w<5>(state);
}
-
-//-------------------------------------------------
-// device_add_mconfig - add device configuration
-//-------------------------------------------------
-
void pc9801_26_device::device_add_mconfig(machine_config &config)
{
SPEAKER(config, "mono").front_center();
YM2203(config, m_opn, 15.9744_MHz_XTAL / 4); // divider not verified
- m_opn->irq_handler().set(FUNC(pc9801_26_device::sound_irq));
- m_opn->port_a_read_callback().set(FUNC(pc9801_26_device::opn_porta_r));
- //m_opn->port_b_read_callback().set(FUNC(pc8801_state::opn_portb_r));
- //m_opn->port_a_write_callback().set(FUNC(pc8801_state::opn_porta_w));
- m_opn->port_b_write_callback().set(FUNC(pc9801_26_device::opn_portb_w));
- m_opn->add_route(ALL_OUTPUTS, "mono", 1.00);
+ m_opn->irq_handler().set([this] (int state) {
+ switch(m_int_level & 3)
+ {
+ case 0: m_bus->int_w<0>(state); break;
+ case 1: m_bus->int_w<4>(state); break;
+ case 2: m_bus->int_w<6>(state); break;
+ case 3: m_bus->int_w<5>(state); break;
+ }
+ });
+ /*
+ * xx-- ---- IRSTx interrupt status 0/1
+ * --xx ---- TRIGx Trigger 1/2
+ * ---- xxxx <directions>
+ */
+ m_opn->port_a_read_callback().set([this] () {
+ u8 res = (BIT(m_joy_sel, 7)) ? m_joy[BIT(m_joy_sel, 6)]->read() : 0x3f;
+ res |= m_int_level << 6;
+ return (u8)res;
+ });
+ /*
+ * x--- ---- OUTE Output Enable (DDR?)
+ * -x-- ---- INSL Input Select
+ * --21 2211 OUTxy x = port / y (2-1) = number (1-3)
+ */
+ m_opn->port_b_write_callback().set([this] (u8 data) {
+ m_joy_sel = data;
+ // TODO: guesswork, verify
+ if (BIT(data, 7))
+ return;
+ m_joy[0]->pin_6_w(BIT(~data, 0));
+ m_joy[0]->pin_7_w(BIT(~data, 1));
+ m_joy[1]->pin_6_w(BIT(~data, 2));
+ m_joy[1]->pin_7_w(BIT(~data, 3));
+ m_joy[0]->pin_8_w(BIT(~data, 4));
+ m_joy[1]->pin_8_w(BIT(~data, 5));
+ });
+
+ // TODO: verify mixing on HW
+ // emerald stage 1 BGM uses ch. 3 for bassline, which sounds way more prominent
+ // than the others combined (0.25 1/4 ratio even?)
+ m_opn->add_route(0, "mono", 0.50);
+ m_opn->add_route(1, "mono", 0.50);
+ m_opn->add_route(2, "mono", 0.50);
+ m_opn->add_route(3, "mono", 1.00);
+
+ MSX_GENERAL_PURPOSE_PORT(config, m_joy[0], msx_general_purpose_port_devices, "joystick");
+ MSX_GENERAL_PURPOSE_PORT(config, m_joy[1], msx_general_purpose_port_devices, "joystick");
}
// to load a different bios for slots:
@@ -70,17 +111,27 @@ const tiny_rom_entry *pc9801_26_device::device_rom_region() const
return ROM_NAME( pc9801_26 );
}
-//-------------------------------------------------
-// input_ports - device-specific input ports
-//-------------------------------------------------
-
static INPUT_PORTS_START( pc9801_26 )
- PORT_INCLUDE( pc9801_joy_port )
-
- PORT_START("OPN_DSW")
+ // On-board jumpers
+ PORT_START("JP6A1_JP6A3")
+ PORT_CONFNAME( 0x03, 0x03, "PC-9801-26: Interrupt level")
+ PORT_CONFSETTING( 0x00, "INT0 (IRQ3)" ) // 2-3, 2-3
+ PORT_CONFSETTING( 0x02, "INT41 (IRQ10)" ) // 2-3, 1-2
+ PORT_CONFSETTING( 0x03, "INT5 (IRQ12)" ) // 1-2, 1-2
+ PORT_CONFSETTING( 0x01, "INT6 (IRQ13)" ) // 1-2, 2-3
+
+ PORT_START("JP6A2")
+ PORT_CONFNAME( 0x07, 0x01, "PC-9801-26: Sound ROM address")
+ PORT_CONFSETTING( 0x00, "0xc8000" ) // 1-10
+ PORT_CONFSETTING( 0x01, "0xcc000" ) // 2-9
+ PORT_CONFSETTING( 0x02, "0xd0000" ) // 3-8
+ PORT_CONFSETTING( 0x03, "0xd4000" ) // 4-7
+ PORT_CONFSETTING( 0x04, "Disable ROM") // 5-6
+
+ PORT_START("JP6A4")
PORT_CONFNAME( 0x01, 0x01, "PC-9801-26: Port Base" )
- PORT_CONFSETTING( 0x00, "0x088" )
- PORT_CONFSETTING( 0x01, "0x188" )
+ PORT_CONFSETTING( 0x00, "0x088" ) // 1-4
+ PORT_CONFSETTING( 0x01, "0x188" ) // 2-3
INPUT_PORTS_END
ioport_constructor pc9801_26_device::device_input_ports() const
@@ -88,52 +139,66 @@ ioport_constructor pc9801_26_device::device_input_ports() const
return INPUT_PORTS_NAME( pc9801_26 );
}
-//**************************************************************************
-// LIVE DEVICE
-//**************************************************************************
-
-//-------------------------------------------------
-// pc9801_26_device - constructor
-//-------------------------------------------------
-
-pc9801_26_device::pc9801_26_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
- : pc9801_snd_device(mconfig, PC9801_26, tag, owner, clock),
- m_bus(*this, DEVICE_SELF_OWNER),
- m_opn(*this, "opn")
+u16 pc9801_26_device::read_io_base()
{
+ return ((ioport("JP6A4")->read() & 1) << 8) + 0x0088;
}
-
-//-------------------------------------------------
-// device_validity_check - perform validity checks
-// on this device
-//-------------------------------------------------
-
-void pc9801_26_device::device_validity_check(validity_checker &valid) const
+void pc9801_26_device::device_start()
{
-}
-
-//-------------------------------------------------
-// device_start - device-specific startup
-//-------------------------------------------------
+ m_rom_base = 0;
+ m_io_base = 0;
+ save_item(NAME(m_joy_sel));
+}
-void pc9801_26_device::device_start()
+void pc9801_26_device::device_reset()
{
- m_bus->program_space().install_rom(0xcc000,0xcffff,memregion(this->subtag("sound_bios").c_str())->base());
-}
+ // install the ROM to the physical program space
+ u8 rom_setting = ioport("JP6A2")->read() & 7;
+ static const u32 rom_addresses[8] = { 0xc8000, 0xcc000, 0xd0000, 0xd4000, 0, 0, 0, 0 };
+ u32 current_rom = rom_addresses[rom_setting & 7];
+ memory_region *rom_region = memregion(this->subtag("sound_bios").c_str());
+ const u32 rom_size = rom_region->bytes() - 1;
+ if (m_rom_base == 0)
+ m_rom_base = current_rom;
-//-------------------------------------------------
-// device_reset - device-specific reset
-//-------------------------------------------------
+ if (m_rom_base != 0)
+ {
+ logerror("%s: uninstall ROM at %08x-%08x\n", machine().describe_context(), m_rom_base, m_rom_base + rom_size);
+ m_bus->program_space().unmap_readwrite(m_rom_base, m_rom_base + rom_size);
+ }
+ if (current_rom != 0)
+ {
+ logerror("%s: install ROM at %08x-%08x\n", machine().describe_context(), current_rom, current_rom + rom_size);
+ m_bus->program_space().unmap_readwrite(current_rom, current_rom + rom_size);
+ m_bus->program_space().install_rom(
+ current_rom,
+ current_rom + rom_size,
+ rom_region->base()
+ );
+ }
+ m_rom_base = current_rom;
+
+ // install I/O ports
+ u16 current_io = read_io_base();
+ m_bus->flush_install_io(
+ this->tag(),
+ m_io_base,
+ current_io,
+ 3,
+ read8sm_delegate(*this, FUNC(pc9801_26_device::opn_r)),
+ write8sm_delegate(*this, FUNC(pc9801_26_device::opn_w))
+ );
+ m_io_base = current_io;
+
+ // read INT line
+ m_int_level = m_irq_jp->read() & 3;
+}
-void pc9801_26_device::device_reset()
+void pc9801_26_device::device_validity_check(validity_checker &valid) const
{
- uint16_t port_base = (ioport("OPN_DSW")->read() & 1) << 8;
-
- m_bus->io_space().unmap_readwrite(0x0088, 0x008b, 0x100);
- m_bus->install_io(port_base + 0x0088, port_base + 0x008b, read8_delegate(FUNC(pc9801_26_device::opn_r), this), write8_delegate(FUNC(pc9801_26_device::opn_w), this) );
}
@@ -142,7 +207,7 @@ void pc9801_26_device::device_reset()
//**************************************************************************
// TODO: leftover mirrors? Doesn't match to what installs above
-READ8_MEMBER(pc9801_26_device::opn_r)
+uint8_t pc9801_26_device::opn_r(offs_t offset)
{
if((offset & 1) == 0)
{
@@ -150,16 +215,16 @@ READ8_MEMBER(pc9801_26_device::opn_r)
}
else // odd
{
- printf("Read to undefined port [%02x]\n",offset+0x188);
+ logerror("Read to undefined port [%02x]\n", offset+0x188);
return 0xff;
}
}
-WRITE8_MEMBER(pc9801_26_device::opn_w)
+void pc9801_26_device::opn_w(offs_t offset, uint8_t data)
{
if((offset & 5) == 0)
m_opn->write(offset >> 1, data);
else // odd
- printf("PC9801-26: Write to undefined port [%02x] %02x\n",offset+0x188,data);
+ logerror("PC9801-26: Write to undefined port [%02x] %02x\n", offset+0x188, data);
}
diff --git a/src/devices/bus/cbus/pc9801_26.h b/src/devices/bus/cbus/pc9801_26.h
index abda3181512..c3576e67286 100644
--- a/src/devices/bus/cbus/pc9801_26.h
+++ b/src/devices/bus/cbus/pc9801_26.h
@@ -2,7 +2,7 @@
// copyright-holders:Angelo Salese
/***************************************************************************
-Template for skeleton device
+ NEC PC-9801-26 sound card
***************************************************************************/
@@ -11,9 +11,10 @@ Template for skeleton device
#pragma once
-#include "bus/cbus/pc9801_cbus.h"
-#include "sound/2203intf.h"
-#include "pc9801_snd.h"
+#include "pc9801_cbus.h"
+
+#include "bus/msx/ctrl/ctrl.h"
+#include "sound/ymopn.h"
//**************************************************************************
// TYPE DEFINITIONS
@@ -21,30 +22,36 @@ Template for skeleton device
// ======================> pc9801_26_device
-class pc9801_26_device : public pc9801_snd_device
+class pc9801_26_device : public device_t
{
public:
// construction/destruction
pc9801_26_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
- DECLARE_READ8_MEMBER(opn_r);
- DECLARE_WRITE8_MEMBER(opn_w);
+ uint8_t opn_r(offs_t offset);
+ void opn_w(offs_t offset, uint8_t data);
protected:
// device-level overrides
virtual void device_validity_check(validity_checker &valid) const override;
- virtual void device_start() override;
- virtual void device_reset() override;
+ virtual void device_start() override ATTR_COLD;
+ virtual void device_reset() override ATTR_COLD;
// optional information 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;
+ virtual void device_add_mconfig(machine_config &config) override ATTR_COLD;
+ virtual ioport_constructor device_input_ports() const override ATTR_COLD;
+ virtual const tiny_rom_entry *device_rom_region() const override ATTR_COLD;
+ u16 read_io_base();
private:
required_device<pc9801_slot_device> m_bus;
required_device<ym2203_device> m_opn;
+ required_device_array<msx_general_purpose_port_device, 2U> m_joy;
+ required_ioport m_irq_jp;
- DECLARE_WRITE_LINE_MEMBER(sound_irq);
+ u32 m_rom_base;
+ u16 m_io_base;
+ u8 m_joy_sel;
+ u8 m_int_level;
};
diff --git a/src/devices/bus/cbus/pc9801_55.cpp b/src/devices/bus/cbus/pc9801_55.cpp
new file mode 100644
index 00000000000..f9cee085d2c
--- /dev/null
+++ b/src/devices/bus/cbus/pc9801_55.cpp
@@ -0,0 +1,253 @@
+// license:BSD-3-Clause
+// copyright-holders:Angelo Salese
+/**************************************************************************************************
+
+ NEC PC-9801-55/-55U/-55L
+
+ SCSI interface, running on WD33C93A
+
+ TODO:
+ - Is PC-9801-55 also running on this except with WD33C93 instead?
+ Will see once we obtain a dump of that;
+ - DIP is never taken (definitely lies at vector 0x2c -> PC=0xdc01e);
+ - DRQ
+ - All roms seems to be misdumped (too generous sizes), is it intentional?
+
+**************************************************************************************************/
+
+#include "emu.h"
+#include "bus/cbus/pc9801_55.h"
+
+//**************************************************************************
+// GLOBAL VARIABLES
+//**************************************************************************
+
+// device type definition
+DEFINE_DEVICE_TYPE(PC9801_55U, pc9801_55u_device, "pc9801_55u", "NEC PC-9801-55U")
+DEFINE_DEVICE_TYPE(PC9801_55L, pc9801_55l_device, "pc9801_55l", "NEC PC-9801-55L")
+
+ROM_START( pc9801_55u )
+ ROM_REGION16_LE( 0x10000, "scsi_bios", ROMREGION_ERASEFF )
+ // JNC2B_00.BIN BADADDR ---xxxxxxxxxxxx
+ // JNC3B_00.BIN BADADDR ---xxxxxxxxxxxx
+ ROM_LOAD16_BYTE( "jnc2b_00.bin", 0x000000, 0x008000, CRC(ddace1b7) SHA1(614569be28a90bd385cf8abc193e629e568125b7) )
+ ROM_LOAD16_BYTE( "jnc3b_00.bin", 0x000001, 0x008000, CRC(b8a8a49e) SHA1(7781dab492df889148e070a7da7ead207e18ed04) )
+ROM_END
+
+const tiny_rom_entry *pc9801_55u_device::device_rom_region() const
+{
+ return ROM_NAME( pc9801_55u );
+}
+
+ROM_START( pc9801_55l )
+ ROM_REGION16_LE( 0x10000, "scsi_bios", ROMREGION_ERASEFF )
+ // ETA1B_00.BIN BADADDR ---xxxxxxxxxxxx
+ // ETA3B_00.BIN BADADDR ---xxxxxxxxxxxx
+ ROM_LOAD16_BYTE( "eta1b_00.bin", 0x000000, 0x008000, CRC(300ff6c1) SHA1(6cdee535b77535fe6c4dda4427aeb803fcdea0b8) )
+ ROM_LOAD16_BYTE( "eta3b_00.bin", 0x000001, 0x008000, CRC(44477512) SHA1(182bb45ba0da7a4f9113e268e04ffca8403cf164) )
+ROM_END
+
+const tiny_rom_entry *pc9801_55l_device::device_rom_region() const
+{
+ return ROM_NAME( pc9801_55l );
+}
+
+//-------------------------------------------------
+// device_add_mconfig - add device configuration
+//-------------------------------------------------
+
+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);
+}
+
+void pc9801_55_device::device_add_mconfig(machine_config &config)
+{
+ NSCSI_BUS(config, m_scsi_bus);
+ // TODO: currently returning default_scsi_devices, checkout if true for PC-98
+ NSCSI_CONNECTOR(config, "scsi:0", default_scsi_devices, nullptr);
+ NSCSI_CONNECTOR(config, "scsi:1", default_scsi_devices, nullptr);
+ NSCSI_CONNECTOR(config, "scsi:2", default_scsi_devices, nullptr);
+ NSCSI_CONNECTOR(config, "scsi:3", default_scsi_devices, nullptr);
+ NSCSI_CONNECTOR(config, "scsi:4", default_scsi_devices, nullptr);
+ NSCSI_CONNECTOR(config, "scsi:5", default_scsi_devices, nullptr);
+ NSCSI_CONNECTOR(config, "scsi:6", default_scsi_devices, nullptr);
+ NSCSI_CONNECTOR(config, "scsi:7").option_set("wdc", WD33C93A).machine_config(
+ [this](device_t *device)
+ {
+ wd33c9x_base_device &adapter = downcast<wd33c9x_base_device &>(*device);
+
+ // TODO: unknown clock
+ adapter.set_clock(10'000'000);
+ adapter.irq_cb().set(*this, FUNC(pc9801_55_device::scsi_irq_w));
+ // TODO: DRQ on C-bus
+ //adapter.drq_cb().set(*this, FUNC(pc9801_55_device::scsi_drq));
+ }
+ );
+}
+
+static INPUT_PORTS_START( pc9801_55 )
+ PORT_START("SCSI_DSW1")
+ PORT_DIPNAME( 0x07, 0x07, "PC-9801-55: SCSI board ID") PORT_DIPLOCATION("SCSI_SW1:!1,!2,!3")
+ PORT_DIPSETTING( 0x00, "0" )
+ PORT_DIPSETTING( 0x01, "1" )
+ PORT_DIPSETTING( 0x02, "2" )
+ PORT_DIPSETTING( 0x03, "3" )
+ PORT_DIPSETTING( 0x04, "4" )
+ PORT_DIPSETTING( 0x05, "5" )
+ PORT_DIPSETTING( 0x06, "6" )
+ PORT_DIPSETTING( 0x07, "7" )
+ PORT_DIPNAME( 0x38, 0x18, "PC-9801-55: Interrupt level") PORT_DIPLOCATION("SCSI_SW1:!4,!5,!6")
+ PORT_DIPSETTING( 0x00, "INT0" )
+ PORT_DIPSETTING( 0x08, "INT1" )
+ PORT_DIPSETTING( 0x10, "INT2" )
+ PORT_DIPSETTING( 0x18, "INT3" )
+ PORT_DIPSETTING( 0x20, "INT5" )
+ PORT_DIPSETTING( 0x28, "INT6" )
+ PORT_DIPSETTING( 0x30, DEF_STR( Unknown ) )
+ PORT_DIPSETTING( 0x38, DEF_STR( Unknown ) )
+ PORT_DIPNAME( 0xc0, 0x00, "PC-9801-55: DMA channel") PORT_DIPLOCATION("SCSI_SW1:!7,!8")
+ PORT_DIPSETTING( 0x00, "0" )
+ PORT_DIPSETTING( 0x40, "1 (prohibited)" )
+ PORT_DIPSETTING( 0x80, "2" )
+ PORT_DIPSETTING( 0xc0, "3" )
+
+ PORT_START("SCSI_DSW2")
+ // TODO: understand all valid possible settings of this
+ PORT_DIPNAME( 0x7f, 0x66, "PC-9801-55: machine ID and ROM base address") PORT_DIPLOCATION("SCSI_SW2:!1,!2,!3,!4,!5,!6,!7")
+ PORT_DIPSETTING( 0x66, "i386, 0xdc000-0xddfff")
+ // ...
+ PORT_DIPNAME( 0x80, 0x80, "PC-9801-55: ROM accessibility at Power-On") PORT_DIPLOCATION("SCSI_SW2:!8")
+ PORT_DIPSETTING( 0x80, DEF_STR( Yes ))
+ PORT_DIPSETTING( 0x00, DEF_STR( No ))
+
+ PORT_START("SCSI_JP")
+ // SW3 and SW4 Jumper settings
+ PORT_CONFNAME( 0x03, 0x00, "PC-9801-55: I/O base address")
+ PORT_CONFSETTING( 0x00, "0xcc0") // 01-02 01 02
+ PORT_CONFSETTING( 0x01, "0xcd0")
+ PORT_CONFSETTING( 0x02, "0xce0")
+ PORT_CONFSETTING( 0x03, "0xcf0")
+INPUT_PORTS_END
+
+ioport_constructor pc9801_55_device::device_input_ports() const
+{
+ return INPUT_PORTS_NAME( pc9801_55 );
+}
+
+//**************************************************************************
+// LIVE DEVICE
+//**************************************************************************
+
+//-------------------------------------------------
+// pc9801_55u_device - constructor
+//-------------------------------------------------
+
+pc9801_55_device::pc9801_55_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_bus(*this, DEVICE_SELF_OWNER)
+ , m_scsi_bus(*this, "scsi")
+ , m_wdc(*this, "scsi:7:wdc")
+{
+}
+
+pc9801_55u_device::pc9801_55u_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
+ : pc9801_55_device(mconfig, PC9801_55U, tag, owner, clock)
+{
+
+}
+
+pc9801_55l_device::pc9801_55l_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
+ : pc9801_55_device(mconfig, PC9801_55L, tag, owner, clock)
+{
+
+}
+
+
+//-------------------------------------------------
+// device_validity_check - perform validity checks
+// on this device
+//-------------------------------------------------
+
+void pc9801_55_device::device_validity_check(validity_checker &valid) const
+{
+}
+
+//-------------------------------------------------
+// device_start - device-specific startup
+//-------------------------------------------------
+
+void pc9801_55_device::device_start()
+{
+ m_bus->program_space().install_rom(
+ 0xdc000,
+ 0xddfff,
+ memregion(this->subtag("scsi_bios").c_str())->base()
+ );
+
+ // TODO: docs hints that this has mirrors at 0xcd*, 0xce*, 0xcf*
+ m_bus->install_io(
+ 0xcc0,
+ 0xcc5,
+ read8sm_delegate(*this, FUNC(pc9801_55_device::comms_r)),
+ write8sm_delegate(*this, FUNC(pc9801_55_device::comms_w))
+ );
+
+}
+
+
+//-------------------------------------------------
+// device_reset - device-specific reset
+//-------------------------------------------------
+
+void pc9801_55_device::device_reset()
+{
+
+}
+
+
+//**************************************************************************
+// READ/WRITE HANDLERS
+//**************************************************************************
+
+u8 pc9801_55_device::comms_r(offs_t offset)
+{
+ if((offset & 1) == 0)
+ {
+ offs_t addr = offset >> 1;
+ if (addr & 2)
+ {
+ logerror("%s: Read to status port [%02x]\n", machine().describe_context(), offset + 0xcc0);
+
+ return 0;
+ }
+
+ return m_wdc->indir_r(addr);
+ }
+ // odd
+
+ logerror("%s: Read to undefined port [%02x]\n", machine().describe_context(), offset + 0xcc0);
+
+ return 0xff;
+}
+
+void pc9801_55_device::comms_w(offs_t offset, u8 data)
+{
+ if((offset & 1) == 0)
+ {
+ offs_t addr = offset >> 1;
+ if (addr & 2)
+ {
+ logerror("%s: Write to command port [%02x] %02x\n", machine().describe_context(), offset + 0xcc0, data);
+
+ return;
+ }
+
+ m_wdc->indir_w(addr, data);
+ return;
+ }
+
+ // odd
+ logerror("%s: Write to undefined port [%02x] %02x\n", machine().describe_context(), offset + 0xcc0, data);
+}
diff --git a/src/devices/bus/cbus/pc9801_55.h b/src/devices/bus/cbus/pc9801_55.h
new file mode 100644
index 00000000000..ee99051c124
--- /dev/null
+++ b/src/devices/bus/cbus/pc9801_55.h
@@ -0,0 +1,80 @@
+// license:BSD-3-Clause
+// copyright-holders:Angelo Salese
+/***************************************************************************
+
+ NEC PC-9801-55/-55U/-55L
+
+***************************************************************************/
+
+#ifndef MAME_BUS_CBUS_PC9801_55_H
+#define MAME_BUS_CBUS_PC9801_55_H
+
+#pragma once
+
+#include "bus/cbus/pc9801_cbus.h"
+#include "bus/nscsi/devices.h"
+#include "machine/nscsi_bus.h"
+#include "machine/wd33c9x.h"
+
+//**************************************************************************
+// TYPE DEFINITIONS
+//**************************************************************************
+
+// ======================> pc9801_118_device
+
+class pc9801_55_device : public device_t
+{
+public:
+ // construction/destruction
+ //pc9801_55_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
+ pc9801_55_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock);
+
+ static constexpr feature_type unemulated_features() { return feature::DISK; }
+
+ void scsi_irq_w(int state);
+
+protected:
+ // device-level overrides
+ virtual void device_validity_check(validity_checker &valid) const override;
+ virtual void device_start() override ATTR_COLD;
+ virtual void device_reset() override ATTR_COLD;
+ // optional information overrides
+// virtual const tiny_rom_entry *device_rom_region() const override ATTR_COLD;
+ virtual void device_add_mconfig(machine_config &config) override ATTR_COLD;
+ virtual ioport_constructor device_input_ports() const override ATTR_COLD;
+
+private:
+ required_device<pc9801_slot_device> m_bus;
+ required_device<nscsi_bus_device> m_scsi_bus;
+ required_device<wd33c9x_base_device> m_wdc;
+
+ u8 comms_r(offs_t offset);
+ void comms_w(offs_t offset, u8 data);
+};
+
+class pc9801_55u_device : public pc9801_55_device
+{
+public:
+ pc9801_55u_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
+
+private:
+ virtual const tiny_rom_entry *device_rom_region() const override ATTR_COLD;
+
+};
+
+class pc9801_55l_device : public pc9801_55_device
+{
+public:
+ pc9801_55l_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
+
+private:
+ virtual const tiny_rom_entry *device_rom_region() const override ATTR_COLD;
+
+};
+
+// device type definition
+//DECLARE_DEVICE_TYPE(PC9801_55, pc9801_55_device)
+DECLARE_DEVICE_TYPE(PC9801_55U, pc9801_55u_device)
+DECLARE_DEVICE_TYPE(PC9801_55L, pc9801_55l_device)
+
+#endif // MAME_BUS_CBUS_PC9801_55_H
diff --git a/src/devices/bus/cbus/pc9801_86.cpp b/src/devices/bus/cbus/pc9801_86.cpp
index d9d6150a9fa..16012f791ba 100644
--- a/src/devices/bus/cbus/pc9801_86.cpp
+++ b/src/devices/bus/cbus/pc9801_86.cpp
@@ -1,75 +1,115 @@
// license:BSD-3-Clause
// copyright-holders:Angelo Salese
-/***************************************************************************
-
- NEC PC-9801-86 sound card
- NEC PC-9801-SpeakBoard sound card
-
- Similar to PC-9801-26, this one has YM2608 instead of YM2203 and an
- additional DAC port
- SpeakBoard sound card seems to be derived design from -86, with an additional
- OPNA mapped at 0x58*
-
- TODO:
- - Test all pcm modes
- - Make volume work
- - Recording
- - SpeakBoard: no idea about software that uses this, also board shows a single YM2608B?
- "-86 only supports ADPCM instead of PCM, while SpeakBoard has OPNA + 256 Kbit RAM"
- Sounds like a sound core flaw since OPNA requires a rom region in any case;
- - verify sound irq;
-
-***************************************************************************/
+/**************************************************************************************************
+
+NEC PC-9801-86 sound card
+NEC PC-9801-SpeakBoard sound card
+Mad Factory Otomi-chan Kai sound card
+
+Similar to PC-9801-26, this one has YM2608 instead of YM2203 and an
+additional DAC port
+
+SpeakBoard sound card seems to be derived design from -86, with an additional
+OPNA mapped at 0x58*
+
+Otomi-chan Kai is a doujinshi sound card based off SpeakBoard design.
+It uses YM3438 OPL2C mapped at 0x78*, and anything that uses the nax.exe sound driver
+expects this to be installed as default (cfr. datsumj).
+To fallback to a regular -26/-86 board user needs to add parameter switches "-2" or "-3"
+respectively, cfr. "nax -?" for additional details.
+
+TODO:
+- Test all pcm modes;
+- Fix PCM overflow bug properly (CPUENB signal yield host CPU until DAC catches up?)
+- Make volume work;
+- Recording;
+- SpeakBoard: no idea about software that uses this, also board shows a single YM2608B?
+ "-86 only supports ADPCM instead of PCM, while SpeakBoard has OPNA + 256 Kbit RAM";
+- Otomi-chan Kai: find a manual (マニュアル), it's mentioned with nax usage.
+ Very low-res scan of the PCB sports a 4-bit dip-sw bank at very least;
+- Otomi-chan Kai: unknown ID port readback;
+- verify sound irq;
+
+**************************************************************************************************/
#include "emu.h"
#include "bus/cbus/pc9801_86.h"
-#include "sound/volt_reg.h"
#include "speaker.h"
#define QUEUE_SIZE 32768
-//**************************************************************************
-// GLOBAL VARIABLES
-//**************************************************************************
+#define LOG_DAC (1U << 1)
+
+#define VERBOSE (LOG_GENERAL)
+//#define LOG_OUTPUT_FUNC osd_printf_info
+#include "logmacro.h"
+
+#define LOGDAC(...) LOGMASKED(LOG_DAC, __VA_ARGS__)
+
-// device type definition
-DEFINE_DEVICE_TYPE(PC9801_86, pc9801_86_device, "pc9801_86", "pc9801_86")
+DEFINE_DEVICE_TYPE(PC9801_86, pc9801_86_device, "pc9801_86", "NEC PC-9801-86")
+DEFINE_DEVICE_TYPE(PC9801_SPEAKBOARD, pc9801_speakboard_device, "pc9801_spb", "NEC PC-9801 SpeakBoard")
+DEFINE_DEVICE_TYPE(OTOMICHAN_KAI, otomichan_kai_device, "pc98_otomichan_kai", "MAD Factory Otomi-chan Kai") // 音美(おとみ)ちゃん改
-WRITE_LINE_MEMBER(pc9801_86_device::sound_irq)
+pc9801_86_device::pc9801_86_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_bus(*this, DEVICE_SELF_OWNER)
+ , m_opna(*this, "opna")
+ , m_irqs(*this, "irqs")
+ , m_ldac(*this, "ldac")
+ , m_rdac(*this, "rdac")
+ , m_queue(QUEUE_SIZE)
+ , m_joy(*this, "joy_port")
{
- m_fmirq = state ? true : false;
- /* TODO: seems to die very often */
- m_bus->int_w<5>(state || (m_pcmirq ? ASSERT_LINE : CLEAR_LINE));
+}
+
+pc9801_86_device::pc9801_86_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
+ : pc9801_86_device(mconfig, PC9801_86, tag, owner, clock)
+{
+
}
-//-------------------------------------------------
-// device_add_mconfig - add device configuration
-//-------------------------------------------------
void pc9801_86_device::pc9801_86_config(machine_config &config)
{
- SPEAKER(config, "lspeaker").front_left();
- SPEAKER(config, "rspeaker").front_right();
- YM2608(config, m_opna, 7.987_MHz_XTAL);
- m_opna->irq_handler().set(FUNC(pc9801_86_device::sound_irq));
- m_opna->set_flags(AY8910_SINGLE_OUTPUT);
- m_opna->port_a_read_callback().set(FUNC(pc9801_86_device::opn_porta_r));
- //m_opna->port_b_read_callback().set(FUNC(pc8801_state::opn_portb_r));
- //m_opna->port_a_write_callback().set(FUNC(pc8801_state::opn_porta_w));
- m_opna->port_b_write_callback().set(FUNC(pc9801_86_device::opn_portb_w));
- m_opna->add_route(0, "lspeaker", 1.00);
- m_opna->add_route(0, "rspeaker", 1.00);
- m_opna->add_route(1, "lspeaker", 1.00);
- m_opna->add_route(2, "rspeaker", 1.00);
-
- DAC_16BIT_R2R_TWOS_COMPLEMENT(config, m_ldac, 0).add_route(ALL_OUTPUTS, "lspeaker", 1.0); // burr brown pcm61p
- DAC_16BIT_R2R_TWOS_COMPLEMENT(config, m_rdac, 0).add_route(ALL_OUTPUTS, "rspeaker", 1.0); // burr brown pcm61p
- voltage_regulator_device &vref(VOLTAGE_REGULATOR(config, "vref"));
- vref.add_route(0, "ldac", 1.0, DAC_VREF_POS_INPUT);
- vref.add_route(0, "ldac", -1.0, DAC_VREF_NEG_INPUT);
- vref.add_route(0, "rdac", 1.0, DAC_VREF_POS_INPUT);
- vref.add_route(0, "rdac", -1.0, DAC_VREF_NEG_INPUT);
+ // TODO: "SecondBus86" PCB contents differs from current hookup
+ // XTAL 15.9744 (X1)
+ // HD641180X0 MCU (U7) (!)
+ // YM2608B (U11)
+ // CS4231A (U15)
+ // OPL4 YMF278 + YRW801 (U21 + U22)
+ // TC55257CFL-10 (U15)
+ // unknown chip (most likely surface scratched) U3)
+
+ INPUT_MERGER_ANY_HIGH(config, m_irqs).output_handler().set([this](int state) { m_bus->int_w<5>(state); });
+
+ SPEAKER(config, "speaker", 2).front();
+ YM2608(config, m_opna, 7.987_MHz_XTAL); // actually YM2608B
+ // shouldn't have one
+// m_opna->set_addrmap(0, &pc9801_86_device::opna_map);
+ m_opna->irq_handler().set(m_irqs, FUNC(input_merger_device::in_w<0>));
+ m_opna->port_a_read_callback().set([this] () {
+ if((m_joy_sel & 0xc0) == 0x80)
+ return m_joy->read();
+
+ return (u8)0xff;
+ });
+ m_opna->port_b_write_callback().set([this] (u8 data) {
+ m_joy_sel = data;
+ });
+ // TODO: confirm mixing
+ m_opna->add_route(0, "speaker", 0.75, 0);
+ m_opna->add_route(0, "speaker", 0.75, 1);
+ m_opna->add_route(1, "speaker", 1.00, 0);
+ m_opna->add_route(2, "speaker", 1.00, 1);
+
+ // 2x burr brown pcm61p
+ DAC_16BIT_R2R_TWOS_COMPLEMENT(config, m_ldac, 0).add_route(ALL_OUTPUTS, "speaker", 1.0, 0);
+ DAC_16BIT_R2R_TWOS_COMPLEMENT(config, m_rdac, 0).add_route(ALL_OUTPUTS, "speaker", 1.0, 1);
+
+ // NOTE: 1x DE-9 port only
+ MSX_GENERAL_PURPOSE_PORT(config, m_joy, msx_general_purpose_port_devices, "joystick");
}
void pc9801_86_device::device_add_mconfig(machine_config &config)
@@ -77,6 +117,16 @@ void pc9801_86_device::device_add_mconfig(machine_config &config)
pc9801_86_config(config);
}
+// helper for derived devices to account for the different master OPNA sound mixing
+void pc9801_86_device::opna_reset_routes_config(machine_config &config)
+{
+ m_opna->reset_routes();
+ m_opna->add_route(0, "speaker", 0.125, 0);
+ m_opna->add_route(0, "speaker", 0.125, 1);
+ m_opna->add_route(1, "speaker", 0.50, 0);
+ m_opna->add_route(2, "speaker", 0.50, 1);
+}
+
// to load a different bios for slots:
// -cbusX pc9801_86,bios=N
ROM_START( pc9801_86 )
@@ -85,13 +135,12 @@ ROM_START( pc9801_86 )
// we currently mark bios names based off where they originally belonged to, lacking of a better info
// supposedly these are -86 roms according to eikanwa2 sound card detection,
// loading a -26 rom in a -86 environment causes an hang there.
+ // TODO: several later machines (i.e. CanBe) really has an internal -86 with sound BIOS data coming directly from the machine ROM
+ // it also sports different ID mapping at $a460
ROM_SYSTEM_BIOS( 0, "86rx", "nec86rx" )
ROMX_LOAD( "sound_rx.rom", 0x0000, 0x4000, BAD_DUMP CRC(fe9f57f2) SHA1(d5dbc4fea3b8367024d363f5351baecd6adcd8ef), ROM_BIOS(0) )
- ROM_SYSTEM_BIOS( 1, "86mu", "nec86mu" )
+ ROM_SYSTEM_BIOS( 1, "86mu", "epson86mu" )
ROMX_LOAD( "sound_486mu.rom", 0x0000, 0x4000, BAD_DUMP CRC(6cdfa793) SHA1(4b8250f9b9db66548b79f961d61010558d6d6e1c), ROM_BIOS(1) )
-
- // RAM
- ROM_REGION( 0x100000, "opna", ROMREGION_ERASE00 )
ROM_END
const tiny_rom_entry *pc9801_86_device::device_rom_region() const
@@ -105,12 +154,32 @@ const tiny_rom_entry *pc9801_86_device::device_rom_region() const
//-------------------------------------------------
static INPUT_PORTS_START( pc9801_86 )
- PORT_INCLUDE( pc9801_joy_port )
-
+ // Single 8-bit DSW bank
PORT_START("OPNA_DSW")
- PORT_CONFNAME( 0x01, 0x01, "PC-9801-86: Port Base" )
- PORT_CONFSETTING( 0x00, "0x088" )
- PORT_CONFSETTING( 0x01, "0x188" )
+ PORT_DIPNAME( 0x01, 0x00, "PC-9801-86: Port Base" ) PORT_DIPLOCATION("OPNA_SW:!1")
+ PORT_DIPSETTING( 0x00, "0x188" )
+ PORT_DIPSETTING( 0x01, "0x288" )
+ PORT_DIPNAME( 0x02, 0x00, "PC-9801-86: Enable sound ROM") PORT_DIPLOCATION("OPNA_SW:!2")
+ PORT_DIPSETTING( 0x00, DEF_STR( Yes ) ) // hardwired at 0xcc000
+ PORT_DIPSETTING( 0x02, DEF_STR( No ) )
+ PORT_DIPNAME( 0x0c, 0x00, "PC-9801-86: Interrupt level") PORT_DIPLOCATION("OPNA_SW:!3,!4")
+ PORT_DIPSETTING( 0x0c, "IRQ 0" )
+ PORT_DIPSETTING( 0x08, "IRQ 4" )
+ PORT_DIPSETTING( 0x00, "IRQ 5" )
+ PORT_DIPSETTING( 0x04, "IRQ 6" )
+ PORT_DIPNAME( 0x10, 0x00, "PC-9801-86: Interrupt enable") PORT_DIPLOCATION("OPNA_SW:!5")
+ PORT_DIPSETTING( 0x00, DEF_STR( Yes ) )
+ PORT_DIPSETTING( 0x10, DEF_STR( No ) )
+ // TODO: how HW really read this?
+ PORT_DIPNAME( 0xe0, 0x80, "PC-9801-86: ID number") PORT_DIPLOCATION("OPNA_SW:!6,!7,!8")
+ PORT_DIPSETTING( 0x00, "0" )
+ PORT_DIPSETTING( 0x20, "1" )
+ PORT_DIPSETTING( 0x40, "2" )
+ PORT_DIPSETTING( 0x60, "3" )
+ PORT_DIPSETTING( 0x80, "4" )
+ PORT_DIPSETTING( 0xa0, "5" )
+ PORT_DIPSETTING( 0xc0, "6" )
+ PORT_DIPSETTING( 0xe0, "7" )
INPUT_PORTS_END
ioport_constructor pc9801_86_device::device_input_ports() const
@@ -118,31 +187,14 @@ ioport_constructor pc9801_86_device::device_input_ports() const
return INPUT_PORTS_NAME( pc9801_86 );
}
-//**************************************************************************
-// LIVE DEVICE
-//**************************************************************************
-
-//-------------------------------------------------
-// pc9801_86_device - constructor
-//-------------------------------------------------
-
-pc9801_86_device::pc9801_86_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock)
- : pc9801_snd_device(mconfig, type, tag, owner, clock),
- m_bus(*this, DEVICE_SELF_OWNER),
- m_opna(*this, "opna"),
- m_ldac(*this, "ldac"),
- m_rdac(*this, "rdac"),
- m_queue(QUEUE_SIZE)
-{
-}
-
-pc9801_86_device::pc9801_86_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
- : pc9801_86_device(mconfig, PC9801_86, tag, owner, clock)
+// only for derived designs?
+void pc9801_86_device::opna_map(address_map &map)
{
-
+ // TODO: confirm it really is ROMless
+ // TODO: confirm size
+ map(0x000000, 0x1fffff).ram();
}
-
//-------------------------------------------------
// device_validity_check - perform validity checks
// on this device
@@ -152,42 +204,64 @@ void pc9801_86_device::device_validity_check(validity_checker &valid) const
{
}
-//-------------------------------------------------
-// device_start - device-specific startup
-//-------------------------------------------------
-
+u16 pc9801_86_device::read_io_base()
+{
+ return ((ioport("OPNA_DSW")->read() & 1) << 8) + 0x188;
+}
void pc9801_86_device::device_start()
{
- m_bus->program_space().install_rom(0xcc000,0xcffff,memregion(this->subtag("sound_bios").c_str())->base());
- m_bus->install_io(0xa460, 0xa463, read8_delegate(FUNC(pc9801_86_device::id_r), this), write8_delegate(FUNC(pc9801_86_device::mask_w), this));
- m_bus->install_io(0xa464, 0xa46f, read8_delegate(FUNC(pc9801_86_device::pcm_r), this), write8_delegate(FUNC(pc9801_86_device::pcm_w), this));
- m_bus->install_io(0xa66c, 0xa66f, read8_delegate([this](address_space &s, offs_t o, u8 mm){ return o == 2 ? m_pcm_mute : 0xff; }, "pc9801_86_mute_r"),
- write8_delegate([this](address_space &s, offs_t o, u8 d, u8 mm){ if(o == 2) m_pcm_mute = d; }, "pc9801_86_mute_w"));
-
- m_dac_timer = timer_alloc();
+ // TODO: uninstall option from dip
+ m_bus->program_space().install_rom(
+ 0xcc000,
+ 0xcffff,
+ memregion(this->subtag("sound_bios").c_str())->base()
+ );
+ // TODO: who wins if 2+ PC-9801-86 or mixed -73/-86 are mounted?
+ m_bus->install_device(0xa460, 0xa46f, *this, &pc9801_86_device::io_map);
+ m_bus->install_io(0xa66c, 0xa66f,
+ read8sm_delegate(*this, [this](offs_t o){ return o == 2 ? m_pcm_mute : 0xff; }, "pcm_mute_r"),
+ write8sm_delegate(*this, [this](offs_t o, u8 d){
+ if(o == 2)
+ {
+ m_pcm_mute = d;
+ m_ldac->set_output_gain(ALL_OUTPUTS, BIT(m_pcm_mute, 0) ? 0.0 : 1.0);
+ m_rdac->set_output_gain(ALL_OUTPUTS, BIT(m_pcm_mute, 0) ? 0.0 : 1.0);
+ }
+ }, "pcm_mute_w")
+ );
+
+ m_io_base = 0;
+
+ m_dac_timer = timer_alloc(FUNC(pc9801_86_device::dac_tick), this);
save_item(NAME(m_count));
save_item(NAME(m_queue));
save_item(NAME(m_irq_rate));
}
-
-//-------------------------------------------------
-// device_reset - device-specific reset
-//-------------------------------------------------
-
void pc9801_86_device::device_reset()
{
- uint16_t port_base = (ioport("OPNA_DSW")->read() & 1) << 8;
- m_bus->io_space().unmap_readwrite(0x0088, 0x008f, 0x100);
- m_bus->install_io(port_base + 0x0088, port_base + 0x008f, read8_delegate(FUNC(pc9801_86_device::opna_r), this), write8_delegate(FUNC(pc9801_86_device::opna_w), this) );
+ u16 current_io = read_io_base();
+ m_bus->flush_install_io(
+ this->tag(),
+ m_io_base,
+ current_io,
+ 7,
+ read8sm_delegate(*this, FUNC(pc9801_86_device::opna_r)),
+ write8sm_delegate(*this, FUNC(pc9801_86_device::opna_w))
+ );
+ m_io_base = current_io;
m_mask = 0;
m_head = m_tail = m_count = 0;
- m_fmirq = m_pcmirq = m_init = false;
+ m_pcmirq = m_init = false;
m_irq_rate = 0;
m_pcm_ctrl = m_pcm_mode = 0;
- m_pcm_mute = 0;
+ // Starts off with DACs muted (os2warp3 will burp a lot while initializing OS)
+ m_pcm_mute = 0x01;
+ m_ldac->set_output_gain(ALL_OUTPUTS, 0.0);
+ m_rdac->set_output_gain(ALL_OUTPUTS, 0.0);
+
m_pcm_clk = false;
memset(&m_queue[0], 0, QUEUE_SIZE);
}
@@ -198,100 +272,171 @@ void pc9801_86_device::device_reset()
//**************************************************************************
-READ8_MEMBER(pc9801_86_device::opna_r)
+u8 pc9801_86_device::opna_r(offs_t offset)
{
if((offset & 1) == 0)
return m_opna->read(offset >> 1);
else // odd
{
- logerror("PC9801-86: Read to undefined port [%02x]\n",offset+0x188);
+ logerror("%s: Read to undefined port [%02x]\n", machine().describe_context(), offset + m_io_base);
return 0xff;
}
}
-WRITE8_MEMBER(pc9801_86_device::opna_w)
+void pc9801_86_device::opna_w(offs_t offset, u8 data)
{
if((offset & 1) == 0)
m_opna->write(offset >> 1,data);
else // odd
- logerror("PC9801-86: Write to undefined port [%02x] %02x\n",offset+0x188,data);
+ logerror("%s: Write to undefined port [%02x] %02x\n", machine().describe_context(), offset + m_io_base, data);
}
-READ8_MEMBER(pc9801_86_device::id_r)
+u8 pc9801_86_device::pcm_control_r()
{
- return 0x40 | m_mask;
+ return m_pcm_ctrl | (m_pcmirq ? 0x10 : 0);
}
-WRITE8_MEMBER(pc9801_86_device::mask_w)
+void pc9801_86_device::pcm_control_w(u8 data)
{
- m_mask = data & 1;
-}
+ const u32 rate = (25.4_MHz_XTAL).value() / 16;
+ const int divs[8] = {36, 48, 72, 96, 144, 192, 288, 384};
-READ8_MEMBER(pc9801_86_device::pcm_r)
-{
- if((offset & 1) == 0)
+ LOGDAC("$a468 FIFO Control %02x\n", data);
+ if(((data & 7) != (m_pcm_ctrl & 7)) || !m_init)
{
- switch(offset >> 1)
+ LOGDAC("\tclk rate %01x (%d)\n", data, divs[data & 7]);
+ m_dac_timer->adjust(attotime::from_ticks(divs[data & 7], rate), 0, attotime::from_ticks(divs[data & 7], rate));
+ }
+ if(data & 8)
+ {
+ LOGDAC("\tFIFO reset\n");
+ m_head = m_tail = m_count = 0;
+ }
+ if(!(data & 0x10))
+ {
+ LOGDAC("\tIRQ clear\n");
+ //m_bus->int_w<5>(m_fmirq ? ASSERT_LINE : CLEAR_LINE);
+ if(!(queue_count() < m_irq_rate) || !(data & 0x80))
{
- case 1:
- return ((queue_count() == QUEUE_SIZE) ? 0x80 : 0) |
- (!queue_count() ? 0x40 : 0) | (m_pcm_clk ? 1 : 0);
- case 2:
- return m_pcm_ctrl | (m_pcmirq ? 0x10 : 0);
- case 3:
- return m_pcm_mode;
- case 4:
- return 0;
+ //TODO: this needs research
+ m_pcmirq = false;
+ m_irqs->in_w<1>(CLEAR_LINE);
}
}
- else // odd
- logerror("PC9801-86: Read to undefined port [%02x]\n",offset+0xa464);
- return 0xff;
+ m_init = true;
+ m_pcm_ctrl = data & ~0x10;
}
-WRITE8_MEMBER(pc9801_86_device::pcm_w)
+// $a460 base
+void pc9801_86_device::io_map(address_map &map)
{
- const u32 rate = (25.4_MHz_XTAL).value() / 16;
- const int divs[8] = {36, 48, 72, 96, 144, 192, 288, 384};
- if((offset & 1) == 0)
- {
- switch(offset >> 1)
- {
- case 1:
- m_vol[data >> 5] = data & 0x0f;
- break;
- case 2:
- if(((data & 7) != (m_pcm_ctrl & 7)) || !m_init)
- m_dac_timer->adjust(attotime::from_ticks(divs[data & 7], rate), 0, attotime::from_ticks(divs[data & 7], rate));
- if(data & 8)
- m_head = m_tail = m_count = 0;
- if(!(data & 0x10))
- {
- m_bus->int_w<5>(m_fmirq ? ASSERT_LINE : CLEAR_LINE);
- if(!(queue_count() < m_irq_rate) || !(data & 0x80))
- m_pcmirq = false; //TODO: this needs research
- }
- m_init = true;
- m_pcm_ctrl = data & ~0x10;
- break;
- case 3:
- if(m_pcm_ctrl & 0x20)
- m_irq_rate = (data + 1) * 128;
- else
- m_pcm_mode = data;
- break;
- case 4:
- if(queue_count() < QUEUE_SIZE)
- {
- m_queue[m_head++] = data;
- m_head %= QUEUE_SIZE;
- m_count++;
- }
- break;
- }
- }
- else // odd
- logerror("PC9801-86: Write to undefined port [%02x] %02x\n",offset+0xa464,data);
+ map.unmap_value_high();
+ map(0x00, 0x00).rw(FUNC(pc9801_86_device::id_r), FUNC(pc9801_86_device::mask_w));
+// map(0x02, 0x02) μPD6380 for PC9801-73 control
+// map(0x04, 0x04) μPD6380 for PC9801-73 data
+ map(0x06, 0x06).lrw8(
+ NAME([this] () {
+ u8 res = 0;
+ // FIFO full
+ res |= (queue_count() == QUEUE_SIZE) << 7;
+ // FIFO empty
+ res |= !queue_count() << 6;
+ // recording overflow
+ res |= 0 << 5;
+ // DAC clock
+ res |= m_pcm_clk << 0;
+ return res;
+ }),
+ NAME([this] (u8 data) {
+ const u8 line_select = data >> 5;
+ m_vol[line_select] = data & 0x0f;
+ logerror("$a466 volume control [%02x] %02x\n", line_select, data & 0xf);
+ })
+ );
+ map(0x08, 0x08).rw(FUNC(pc9801_86_device::pcm_control_r), FUNC(pc9801_86_device::pcm_control_w));
+ map(0x0a, 0x0a).lrw8(
+ NAME([this] () {
+ return m_pcm_mode;
+ }),
+ NAME([this] (u8 data) {
+ if(m_pcm_ctrl & 0x20)
+ {
+ // TODO: may fall over with the irq logic math
+ // queue_count() < (0xff + 1) << 7 = 0x8000 -> always true
+ if (data == 0xff)
+ popmessage("pc9801_86: $a46a irq_rate == 0xff");
+ m_irq_rate = (data + 1) * 128;
+ LOGDAC("$a468 irq_rate %d (%02x)\n", m_irq_rate, data);
+ }
+ else
+ {
+ m_pcm_mode = data;
+ LOGDAC("$a468 pcm_mode %02x\n", data);
+ LOGDAC("\tclock %d quantization %d-bit output %d mode %d\n"
+ , BIT(data, 7)
+ , BIT(data, 6) ? 16 : 8
+ // 3 = stereo, 2 Left only, 1 Right only, 0 = No PCM output
+ , (data >> 4) & 3
+ , data & 3
+ );
+ }
+ })
+ );
+ map(0x0c, 0x0c).lrw8(
+ NAME([this] () {
+ // TODO: recording mode
+ (void)this;
+ return 0;
+ }),
+ NAME([this] (u8 data) {
+ // HACK: on overflow make sure to single step the FIFO enough to claim some space back
+ // os2warp3 initializes the full buffer with 0x00 then quickly pretends
+ // that DAC already catched up by the time the actual startup/shutdown chimes are sent.
+ if (queue_count() == QUEUE_SIZE)
+ {
+ dac_transfer();
+ logerror("Warning: $a46c write with FIFO overflow %02x\n", m_pcm_mode);
+ }
+
+ if(queue_count() < QUEUE_SIZE)
+ {
+ m_queue[m_head++] = data;
+ m_head %= QUEUE_SIZE;
+ m_count++;
+ }
+ })
+ );
+}
+
+/*
+ * xxxx ---- ID
+ * 0000 ---- PC-90DO+ built-in
+ * 0001 ---- PC-98GS built-in
+ * 0010 ---- PC-9801-73/-76, I/O base $188
+ * 0011 ---- PC-9801-73/-76, I/O base $288
+ * 0100 ---- PC-9801-86, I/O base $188, PC-9821 Multi/A Mate/early CanBe (Ce/Cs2/Ce2)
+ * 0101 ---- PC-9801-86, I/O base $288
+ * 0110 ---- PC-9821Nf/Np built-in
+ * 0111 ---- PC-9821 X Mate (as PC-9821XE10-B?)
+ * 1000 ---- PC-9821 later CanBe/Na7/Nx built-in
+ * 1111 ---- <unsupported or PC-9801-26>
+ * ---- --x- (1) OPNA force volume to 0
+ * ---- ---x select OPN base
+ * ---- ---1 OPNA
+ * ---- ---0 OPN
+ */
+u8 pc9801_86_device::id_r()
+{
+ // either a -86 or 9821 MATE A uses this id (built-in)
+ const u8 id_port = ((ioport("OPNA_DSW")->read() & 1) << 4) | 0x40;
+ return id_port | m_mask;
+}
+
+void pc9801_86_device::mask_w(u8 data)
+{
+ m_mask = data & 3;
+ // TODO: bit 1 totally cuts off OPNA output
+ logerror("%s: OPNA mask setting %02x\n", machine().describe_context(), data);
}
int pc9801_86_device::queue_count()
@@ -299,22 +444,19 @@ int pc9801_86_device::queue_count()
return m_count;
}
-uint8_t pc9801_86_device::queue_pop()
+u8 pc9801_86_device::queue_pop()
{
- uint8_t ret = m_queue[m_tail++];
+ u8 ret = m_queue[m_tail++];
m_tail %= QUEUE_SIZE;
- m_count = (m_count - 1) % QUEUE_SIZE; // dangel resets the fifo after filling it completely so maybe it expects an underflow
+ // TODO: dangel resets the fifo after filling it completely so maybe it expects an underflow
+ // this breaks win95, that expects FIFO empty flags to stay consistant
+ //m_count = (m_count - 1) % QUEUE_SIZE;
+ m_count = std::max(m_count - 1, 0);
return ret;
}
-void pc9801_86_device::device_timer(emu_timer& timer, device_timer_id id, int param, void* ptr)
+void pc9801_86_device::dac_transfer()
{
- int16_t lsample, rsample;
-
- m_pcm_clk = !m_pcm_clk;
- if((m_pcm_ctrl & 0x40) || !(m_pcm_ctrl & 0x80))
- return;
-
switch(m_pcm_mode & 0x70)
{
case 0x70: // 8bit stereo
@@ -327,47 +469,59 @@ void pc9801_86_device::device_timer(emu_timer& timer, device_timer_id id, int pa
case 0x50: // 8bit right only
m_rdac->write(queue_pop() << 8);
break;
- case 0x30: // 16bit stereo
- lsample = queue_pop() << 8;
+ case 0x30: { // 16bit stereo
+ int16_t lsample = queue_pop() << 8;
lsample |= queue_pop();
- rsample = queue_pop() << 8;
+ int16_t rsample = queue_pop() << 8;
rsample |= queue_pop();
m_ldac->write(lsample);
m_rdac->write(rsample);
- break;
- case 0x20: // 16bit left only
- lsample = queue_pop() << 8;
+ } break;
+ case 0x20: { // 16bit left only
+ int16_t lsample = queue_pop() << 8;
lsample |= queue_pop();
m_ldac->write(lsample);
- break;
- case 0x10: // 16bit right only
- rsample = queue_pop() << 8;
+ } break;
+ case 0x10: { // 16bit right only
+ int16_t rsample = queue_pop() << 8;
rsample |= queue_pop();
m_rdac->write(rsample);
- break;
+ } break;
}
+}
+
+TIMER_CALLBACK_MEMBER(pc9801_86_device::dac_tick)
+{
+ m_pcm_clk = !m_pcm_clk;
+ if((m_pcm_ctrl & 0x40) || !(m_pcm_ctrl & 0x80))
+ return;
+
+ // TODO: verify underflow
+ // should leave the DACs in whatever state they are or ...?
+ if (!queue_count())
+ return;
+
+ dac_transfer();
if((queue_count() < m_irq_rate) && (m_pcm_ctrl & 0x20))
{
+ //LOGDAC("\tIRQ set\n");
m_pcmirq = true;
- m_bus->int_w<5>(ASSERT_LINE);
+ // win95 expects edge triggers
+ m_irqs->in_w<1>(CLEAR_LINE);
+ m_irqs->in_w<1>(ASSERT_LINE);
}
}
//**************************************************************************
+//
// SpeakBoard device section
+//
//**************************************************************************
-DEFINE_DEVICE_TYPE(PC9801_SPEAKBOARD, pc9801_speakboard_device, "pc9801_spb", "NEC PC9801 SpeakBoard")
-
ROM_START( pc9801_spb )
ROM_REGION( 0x4000, "sound_bios", ROMREGION_ERASEFF )
ROM_LOAD16_BYTE( "spb lh5764 ic21_pink.bin", 0x0001, 0x2000, CRC(5bcefa1f) SHA1(ae88e45d411bf5de1cb42689b12b6fca0146c586) )
ROM_LOAD16_BYTE( "spb lh5764 ic22_green.bin", 0x0000, 0x2000, CRC(a7925ced) SHA1(3def9ee386ab6c31436888261bded042cd64a0eb) )
-
- // RAM
- ROM_REGION( 0x100000, "opna", ROMREGION_ERASE00 )
-
- ROM_REGION( 0x100000, "opna_slave", ROMREGION_ERASE00 )
ROM_END
const tiny_rom_entry *pc9801_speakboard_device::device_rom_region() const
@@ -375,44 +529,32 @@ const tiny_rom_entry *pc9801_speakboard_device::device_rom_region() const
return ROM_NAME( pc9801_spb );
}
-
-//**************************************************************************
-// LIVE DEVICE
-//**************************************************************************
-
-//-------------------------------------------------
-// pc9801_speakboard_device - constructor
-//-------------------------------------------------
-
pc9801_speakboard_device::pc9801_speakboard_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
- : pc9801_86_device(mconfig, PC9801_SPEAKBOARD, tag, owner, clock),
- m_opna_slave(*this, "opna_slave")
+ : pc9801_86_device(mconfig, PC9801_SPEAKBOARD, tag, owner, clock)
+ , m_opna_slave(*this, "opna_slave")
{
}
void pc9801_speakboard_device::device_add_mconfig(machine_config &config)
{
pc9801_86_config(config);
-
- m_opna->reset_routes();
- m_opna->add_route(0, "lspeaker", 0.50);
- m_opna->add_route(0, "rspeaker", 0.50);
- m_opna->add_route(1, "lspeaker", 0.50);
- m_opna->add_route(2, "rspeaker", 0.50);
+ opna_reset_routes_config(config);
+ // TODO: confirm RAM mapping configuration (shared? not present on either chip? misc?)
+ m_opna->set_addrmap(0, &pc9801_speakboard_device::opna_map);
YM2608(config, m_opna_slave, 7.987_MHz_XTAL);
- m_opna_slave->set_flags(AY8910_SINGLE_OUTPUT);
- m_opna_slave->add_route(0, "lspeaker", 0.50);
- m_opna_slave->add_route(0, "rspeaker", 0.50);
- m_opna_slave->add_route(1, "lspeaker", 0.50);
- m_opna_slave->add_route(2, "rspeaker", 0.50);
+ m_opna_slave->set_addrmap(0, &pc9801_speakboard_device::opna_map);
+ m_opna_slave->add_route(0, "speaker", 0.50, 0);
+ m_opna_slave->add_route(0, "speaker", 0.50, 1);
+ m_opna_slave->add_route(1, "speaker", 0.50, 0);
+ m_opna_slave->add_route(2, "speaker", 0.50, 1);
}
void pc9801_speakboard_device::device_start()
{
pc9801_86_device::device_start();
- m_bus->install_io(0x0588, 0x058f, read8_delegate(FUNC(pc9801_speakboard_device::opna_slave_r), this), write8_delegate(FUNC(pc9801_speakboard_device::opna_slave_w), this) );
+ m_bus->install_io(0x0588, 0x058f, read8sm_delegate(*this, FUNC(pc9801_speakboard_device::opna_slave_r)), write8sm_delegate(*this, FUNC(pc9801_speakboard_device::opna_slave_w)));
}
void pc9801_speakboard_device::device_reset()
@@ -420,22 +562,94 @@ void pc9801_speakboard_device::device_reset()
pc9801_86_device::device_reset();
}
-READ8_MEMBER(pc9801_speakboard_device::opna_slave_r)
+u8 pc9801_speakboard_device::opna_slave_r(offs_t offset)
{
if((offset & 1) == 0)
return m_opna_slave->read(offset >> 1);
else // odd
{
- logerror("PC9801-SPB: Read to undefined port [%02x]\n",offset+0x588);
+ logerror("%s: Read to undefined port [%02x]\n", machine().describe_context(), offset + 0x588);
return 0xff;
}
}
-WRITE8_MEMBER(pc9801_speakboard_device::opna_slave_w)
+void pc9801_speakboard_device::opna_slave_w(offs_t offset, u8 data)
{
if((offset & 1) == 0)
m_opna_slave->write(offset >> 1,data);
else // odd
- logerror("PC9801-SPB: Write to undefined port [%02x] %02x\n",offset+0x588,data);
+ logerror("%s: Write to undefined port [%02x] %02x\n", machine().describe_context(), offset + 0x588, data);
+}
+
+//**************************************************************************
+//
+// Otomi-chan Kai device section
+//
+//**************************************************************************
+
+otomichan_kai_device::otomichan_kai_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
+ : pc9801_86_device(mconfig, OTOMICHAN_KAI, tag, owner, clock)
+ , m_opn2c(*this, "opn2c")
+{
}
+ROM_START( pc98_otomichan_kai )
+ ROM_REGION( 0x4000, "sound_bios", ROMREGION_ERASEFF )
+ // TODO: "compatible" with SpeakBoard, does it even uses a ROM altogether? low-res PCB pic doesn't help at all.
+ ROM_LOAD16_BYTE( "spb lh5764 ic21_pink.bin", 0x0001, 0x2000, BAD_DUMP CRC(5bcefa1f) SHA1(ae88e45d411bf5de1cb42689b12b6fca0146c586) )
+ ROM_LOAD16_BYTE( "spb lh5764 ic22_green.bin", 0x0000, 0x2000, BAD_DUMP CRC(a7925ced) SHA1(3def9ee386ab6c31436888261bded042cd64a0eb) )
+ROM_END
+
+const tiny_rom_entry *otomichan_kai_device::device_rom_region() const
+{
+ return ROM_NAME( pc98_otomichan_kai );
+}
+
+void otomichan_kai_device::device_add_mconfig(machine_config &config)
+{
+ pc9801_86_config(config);
+ opna_reset_routes_config(config);
+ // TODO: confirm if this has OPNA RAM
+ m_opna->set_addrmap(0, &otomichan_kai_device::opna_map);
+
+ YM3438(config, m_opn2c, 7.987_MHz_XTAL);
+ m_opn2c->add_route(0, "speaker", 0.50, 0);
+ m_opn2c->add_route(1, "speaker", 0.50, 1);
+}
+
+u8 otomichan_kai_device::id_r()
+{
+ // no ID, unconfirmed if it has mask
+ return 0xf0 | m_mask;
+}
+
+void otomichan_kai_device::device_start()
+{
+ pc9801_86_device::device_start();
+
+ m_bus->install_io(0x0788, 0x078f, read8sm_delegate(*this, FUNC(otomichan_kai_device::opn2c_r)), write8sm_delegate(*this, FUNC(otomichan_kai_device::opn2c_w)));
+}
+
+void otomichan_kai_device::device_reset()
+{
+ pc9801_86_device::device_reset();
+}
+
+u8 otomichan_kai_device::opn2c_r(offs_t offset)
+{
+ if((offset & 1) == 0)
+ return m_opn2c->read(offset >> 1);
+ else // odd
+ {
+ logerror("%s: Read to undefined port [%02x]\n", machine().describe_context(), offset + 0x788);
+ return 0xff;
+ }
+}
+
+void otomichan_kai_device::opn2c_w(offs_t offset, u8 data)
+{
+ if((offset & 1) == 0)
+ m_opn2c->write(offset >> 1, data);
+ else // odd
+ logerror("%s: Write to undefined port [%02x] %02x\n", machine().describe_context(), offset + 0x788, data);
+}
diff --git a/src/devices/bus/cbus/pc9801_86.h b/src/devices/bus/cbus/pc9801_86.h
index de3b9190aab..d79cf21b6de 100644
--- a/src/devices/bus/cbus/pc9801_86.h
+++ b/src/devices/bus/cbus/pc9801_86.h
@@ -11,10 +11,12 @@
#pragma once
-#include "bus/cbus/pc9801_cbus.h"
-#include "sound/2608intf.h"
+#include "pc9801_cbus.h"
+
+#include "bus/msx/ctrl/ctrl.h"
+#include "machine/input_merger.h"
#include "sound/dac.h"
-#include "pc9801_snd.h"
+#include "sound/ymopn.h"
//**************************************************************************
// TYPE DEFINITIONS
@@ -22,49 +24,66 @@
// ======================> pc9801_86_device
-class pc9801_86_device : public pc9801_snd_device
+class pc9801_86_device : public device_t
{
public:
// construction/destruction
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_READ8_MEMBER(opna_r);
- DECLARE_WRITE8_MEMBER(opna_w);
- DECLARE_READ8_MEMBER(id_r);
- DECLARE_WRITE8_MEMBER(mask_w);
- DECLARE_READ8_MEMBER(pcm_r);
- DECLARE_WRITE8_MEMBER(pcm_w);
-
- DECLARE_WRITE_LINE_MEMBER(sound_irq);
+ static constexpr feature_type unemulated_features() { return feature::MICROPHONE; }
+ static constexpr feature_type imperfect_features() { return feature::SOUND; }
protected:
+ void io_map(address_map &map) ATTR_COLD;
+ u8 pcm_control_r();
+ void pcm_control_w(u8 data);
+
// device-level overrides
virtual void device_validity_check(validity_checker &valid) const override;
- virtual void device_start() override;
- virtual void device_reset() override;
+ virtual void device_start() override ATTR_COLD;
+ virtual void device_reset() override ATTR_COLD;
// optional information 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;
- virtual void device_timer(emu_timer &timer, device_timer_id id, int param, void *ptr) override;
+ virtual void device_add_mconfig(machine_config &config) override ATTR_COLD;
+ void opna_reset_routes_config(machine_config &config);
+ virtual ioport_constructor device_input_ports() const override ATTR_COLD;
+ virtual const tiny_rom_entry *device_rom_region() const override ATTR_COLD;
void pc9801_86_config(machine_config &config);
+ u16 read_io_base();
+
+ TIMER_CALLBACK_MEMBER(dac_tick);
required_device<pc9801_slot_device> m_bus;
required_device<ym2608_device> m_opna;
+ required_device<input_merger_device> m_irqs;
+
+ void opna_map(address_map &map) ATTR_COLD;
+
+ u8 opna_r(offs_t offset);
+ void opna_w(offs_t offset, u8 data);
+ virtual u8 id_r();
+ void mask_w(u8 data);
+
+ u8 m_mask;
private:
int queue_count();
- uint8_t queue_pop();
+ u8 queue_pop();
-
- uint8_t m_mask, m_pcm_mode, m_vol[7], m_pcm_ctrl, m_pcm_mute;
+ u8 m_pcm_mode, m_vol[7], m_pcm_ctrl, m_pcm_mute;
uint16_t m_head, m_tail, m_count, m_irq_rate;
- bool m_pcmirq, m_fmirq, m_pcm_clk, m_init;
- required_device<dac_word_interface> m_ldac;
- required_device<dac_word_interface> m_rdac;
- std::vector<uint8_t> m_queue;
+ bool m_pcmirq, m_pcm_clk, m_init;
+ required_device<dac_16bit_r2r_twos_complement_device> m_ldac;
+ required_device<dac_16bit_r2r_twos_complement_device> m_rdac;
+ std::vector<u8> m_queue;
+ required_device<msx_general_purpose_port_device> m_joy;
+
emu_timer *m_dac_timer;
+
+ void dac_transfer();
+
+ u8 m_joy_sel;
+ u16 m_io_base;
};
class pc9801_speakboard_device : public pc9801_86_device
@@ -73,26 +92,48 @@ public:
// construction/destruction
pc9801_speakboard_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
- DECLARE_READ8_MEMBER(opna_slave_r);
- DECLARE_WRITE8_MEMBER(opna_slave_w);
+ static constexpr feature_type imperfect_features() { return feature::SOUND; }
+
+ u8 opna_slave_r(offs_t offset);
+ void opna_slave_w(offs_t offset, u8 data);
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;
+ 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;
+ virtual const tiny_rom_entry *device_rom_region() const override ATTR_COLD;
private:
required_device<ym2608_device> m_opna_slave;
};
+class otomichan_kai_device : public pc9801_86_device
+{
+public:
+ // construction/destruction
+ otomichan_kai_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
+
+ static constexpr feature_type imperfect_features() { return feature::SOUND; }
-// device type definition
-DECLARE_DEVICE_TYPE(PC9801_86, pc9801_86_device)
-DECLARE_DEVICE_TYPE(PC9801_SPEAKBOARD, pc9801_speakboard_device)
+ u8 opn2c_r(offs_t offset);
+ void opn2c_w(offs_t offset, u8 data);
+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;
+ virtual const tiny_rom_entry *device_rom_region() const override ATTR_COLD;
+private:
+ required_device<ym3438_device> m_opn2c;
+
+ virtual u8 id_r() override;
+};
+// device type definition
+DECLARE_DEVICE_TYPE(PC9801_86, pc9801_86_device)
+DECLARE_DEVICE_TYPE(PC9801_SPEAKBOARD, pc9801_speakboard_device)
+DECLARE_DEVICE_TYPE(OTOMICHAN_KAI, otomichan_kai_device)
#endif // MAME_BUS_CBUS_PC9801_86_H
diff --git a/src/devices/bus/cbus/pc9801_cbus.cpp b/src/devices/bus/cbus/pc9801_cbus.cpp
index 5a53eddcce7..33e1833d7e8 100644
--- a/src/devices/bus/cbus/pc9801_cbus.cpp
+++ b/src/devices/bus/cbus/pc9801_cbus.cpp
@@ -1,10 +1,27 @@
// license:BSD-3-Clause
// copyright-holders:Angelo Salese
-/**********************************************************************
+/**************************************************************************************************
- CCBUS Slot interface for PC-98xx family
+C-bus slot interface for PC-98xx family
-**********************************************************************/
+a.k.a. NEC version of the ISA bus.
+C-bus -> Compatible Bus
+
+References:
+- https://98epjunk.shakunage.net/sw/ext_card/ext_card.html
+- https://ja.wikipedia.org/wiki/C%E3%83%90%E3%82%B9
+- https://www.pc-9800.net/db2/db2_ga_index.htm
+- http://ookumaneko.s1005.xrea.com/pcibios.htm (PCI era mapping)
+
+TODO:
+- stub interface, checkout what actually belongs here
+- move pc9801_cbus_devices declaration from pc9801 driver in here;
+- 8-bit I/O smearing should be handled here;
+- INT# should be handled here too;
+- Best way to inform user when it tries to install incompatible boards?
+- Support for PCI bridging on later machines (cfr. pc9821cx3);
+
+**************************************************************************************************/
#include "emu.h"
#include "pc9801_cbus.h"
@@ -15,7 +32,7 @@
// GLOBAL VARIABLES
//**************************************************************************
-DEFINE_DEVICE_TYPE(PC9801CBUS_SLOT, pc9801_slot_device, "pc9801_slot", "PC-9801 sound cbus slot")
+DEFINE_DEVICE_TYPE(PC9801CBUS_SLOT, pc9801_slot_device, "pc9801_slot", "PC-9801 C-bus slot")
@@ -57,7 +74,7 @@ pc9801_slot_device::pc9801_slot_device(const machine_config &mconfig, const char
device_slot_interface(mconfig, *this),
m_memspace(*this, finder_base::DUMMY_TAG, -1),
m_iospace(*this, finder_base::DUMMY_TAG, -1),
- m_int_callback{{*this}, {*this}, {*this}, {*this}, {*this}, {*this}, {*this}}
+ m_int_callback(*this)
{
}
@@ -75,19 +92,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()
-{
- for (auto &cb : m_int_callback)
- cb.resolve_safe();
-}
-
-
-//-------------------------------------------------
// device_start - device-specific startup
//-------------------------------------------------
@@ -96,7 +100,7 @@ void pc9801_slot_device::device_start()
// m_card = dynamic_cast<device_pc9801_slot_card_interface *>(get_card_device());
}
-void pc9801_slot_device::install_io(offs_t start, offs_t end, read8_delegate rhandler, write8_delegate whandler)
+template<typename R, typename W> void pc9801_slot_device::install_io(offs_t start, offs_t end, R rhandler, W whandler)
{
int buswidth = m_iospace->data_width();
switch(buswidth)
@@ -111,6 +115,44 @@ void pc9801_slot_device::install_io(offs_t start, offs_t end, read8_delegate rha
m_iospace->install_readwrite_handler(start, end, rhandler, whandler, 0xffffffff);
break;
default:
- fatalerror("PC-9801-26: Bus width %d not supported\n", buswidth);
+ fatalerror("PC-9801 C-bus: Bus width %d not supported\n", buswidth);
}
}
+
+template void pc9801_slot_device::install_io<read8_delegate, write8_delegate >(offs_t start, offs_t end, read8_delegate rhandler, write8_delegate whandler);
+template void pc9801_slot_device::install_io<read8s_delegate, write8s_delegate >(offs_t start, offs_t end, read8s_delegate rhandler, write8s_delegate whandler);
+template void pc9801_slot_device::install_io<read8sm_delegate, write8sm_delegate >(offs_t start, offs_t end, read8sm_delegate rhandler, write8sm_delegate whandler);
+template void pc9801_slot_device::install_io<read8smo_delegate, write8smo_delegate>(offs_t start, offs_t end, read8smo_delegate rhandler, write8smo_delegate whandler);
+
+// boilerplate code for boards that has configurable I/O with either Jumpers or Dip-Switches
+// NB: client must have a mechanism to remember what port has been used before and after calling this,
+// in order to avoid "last instantiated wins" issues with overlapping board full configs.
+// TODO: refactor to actually be useful for PCI archs
+void pc9801_slot_device::flush_install_io(const char *client_tag, u16 old_io, u16 new_io, u16 size, read8sm_delegate rhandler, write8sm_delegate whandler)
+{
+ // initialize if client have this unmapped (such as first boot)
+ // device_start fns cannot read input ports ...
+ if (old_io == 0)
+ old_io = new_io;
+
+ logerror("%s: %s uninstall I/O at %04x-%04x\n",
+ this->tag(),
+ client_tag,
+ old_io,
+ old_io + size
+ );
+ this->io_space().unmap_readwrite(old_io, old_io + size);
+
+ logerror("%s: %s install I/O at %04x-%04x\n",
+ this->tag(),
+ client_tag,
+ new_io,
+ new_io + size
+ );
+ this->install_io(
+ new_io,
+ new_io + size,
+ rhandler,
+ whandler
+ );
+}
diff --git a/src/devices/bus/cbus/pc9801_cbus.h b/src/devices/bus/cbus/pc9801_cbus.h
index e094693f06c..14c1213e00b 100644
--- a/src/devices/bus/cbus/pc9801_cbus.h
+++ b/src/devices/bus/cbus/pc9801_cbus.h
@@ -58,8 +58,8 @@
<B> <A>
**********************************************************************/
-#ifndef MAME_MACHINE_PC9801_CBUS_H
-#define MAME_MACHINE_PC9801_CBUS_H
+#ifndef MAME_BUS_CBUS_PC9801_CBUS_H
+#define MAME_BUS_CBUS_PC9801_CBUS_H
#pragma once
@@ -111,23 +111,28 @@ public:
address_space &program_space() const { return *m_memspace; }
address_space &io_space() const { return *m_iospace; }
template<int I> void int_w(bool state) { m_int_callback[I](state); }
- void install_io(offs_t start, offs_t end, read8_delegate rhandler, write8_delegate whandler);
+ template<typename R, typename W> void install_io(offs_t start, offs_t end, R rhandler, W whandler);
+ template<typename T> void install_device(offs_t addrstart, offs_t addrend, T &device, void (T::*map)(class address_map &map), uint64_t unitmask = ~u64(0))
+ {
+ m_iospace->install_device(addrstart, addrend, device, map, unitmask);
+ }
+
+ 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
- virtual void device_start() override;
+ // device_t implementation
+ virtual void device_start() override ATTR_COLD;
virtual void device_config_complete() override;
- virtual void device_resolve_objects() override;
private:
// device_pc9801_slot_card_interface *m_card;
required_address_space m_memspace;
required_address_space m_iospace;
- devcb_write_line m_int_callback[7];
+ devcb_write_line::array<7> m_int_callback;
};
// device type definition
DECLARE_DEVICE_TYPE(PC9801CBUS_SLOT, pc9801_slot_device)
-#endif // MAME_MACHINE_PC9801_CBUS_H
+#endif // MAME_BUS_CBUS_PC9801_CBUS_H
diff --git a/src/devices/bus/cbus/pc9801_snd.cpp b/src/devices/bus/cbus/pc9801_snd.cpp
deleted file mode 100644
index 670e423e4d3..00000000000
--- a/src/devices/bus/cbus/pc9801_snd.cpp
+++ /dev/null
@@ -1,50 +0,0 @@
-// license:BSD-3-Clause
-// copyright-holders:Angelo Salese
-/***************************************************************************
-
- NEC PC-9801
- common functions for CBUS sound boards -26, -86, -118
-
-***************************************************************************/
-
-#include "emu.h"
-#include "pc9801_snd.h"
-
-//DEFINE_DEVICE_TYPE(PC9801_SND, pc9801_snd_device, "pc9801_snd", "PC9801 CBUS Sound")
-
-pc9801_snd_device::pc9801_snd_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock)
- : device_t(mconfig, type, tag, owner, clock)
-{
-}
-
-READ8_MEMBER(pc9801_snd_device::opn_porta_r)
-{
- if(m_joy_sel & 0x80)
- return ioport(m_joy_sel & 0x40 ? "PA2" : "PA1")->read();
-
- return 0xff;
-}
-
-WRITE8_MEMBER(pc9801_snd_device::opn_portb_w) { m_joy_sel = data; }
-
-INPUT_PORTS_START(pc9801_joy_port)
- PORT_START("PA1")
- PORT_BIT( 0x01, IP_ACTIVE_LOW, IPT_JOYSTICK_UP ) PORT_8WAY PORT_PLAYER(1) PORT_NAME("P1 Joystick Up")
- PORT_BIT( 0x02, IP_ACTIVE_LOW, IPT_JOYSTICK_DOWN ) PORT_8WAY PORT_PLAYER(1) PORT_NAME("P1 Joystick Down")
- PORT_BIT( 0x04, IP_ACTIVE_LOW, IPT_JOYSTICK_LEFT ) PORT_8WAY PORT_PLAYER(1) PORT_NAME("P1 Joystick Left")
- PORT_BIT( 0x08, IP_ACTIVE_LOW, IPT_JOYSTICK_RIGHT ) PORT_8WAY PORT_PLAYER(1) PORT_NAME("P1 Joystick Right")
- PORT_BIT( 0x10, IP_ACTIVE_LOW, IPT_BUTTON1 ) PORT_PLAYER(1) PORT_NAME("P1 Joystick Button 1")
- PORT_BIT( 0x20, IP_ACTIVE_LOW, IPT_BUTTON2 ) PORT_PLAYER(1) PORT_NAME("P1 Joystick Button 2")
- PORT_BIT( 0x40, IP_ACTIVE_LOW, IPT_UNUSED )
- PORT_BIT( 0x80, IP_ACTIVE_LOW, IPT_UNUSED )
-
- PORT_START("PA2")
- PORT_BIT( 0x01, IP_ACTIVE_LOW, IPT_JOYSTICK_UP ) PORT_8WAY PORT_PLAYER(2) PORT_NAME("P2 Joystick Up")
- PORT_BIT( 0x02, IP_ACTIVE_LOW, IPT_JOYSTICK_DOWN ) PORT_8WAY PORT_PLAYER(2) PORT_NAME("P2 Joystick Down")
- PORT_BIT( 0x04, IP_ACTIVE_LOW, IPT_JOYSTICK_LEFT ) PORT_8WAY PORT_PLAYER(2) PORT_NAME("P2 Joystick Left")
- PORT_BIT( 0x08, IP_ACTIVE_LOW, IPT_JOYSTICK_RIGHT ) PORT_8WAY PORT_PLAYER(2) PORT_NAME("P2 Joystick Right")
- PORT_BIT( 0x10, IP_ACTIVE_LOW, IPT_BUTTON1 ) PORT_PLAYER(2) PORT_NAME("P2 Joystick Button 1")
- PORT_BIT( 0x20, IP_ACTIVE_LOW, IPT_BUTTON2 ) PORT_PLAYER(2) PORT_NAME("P2 Joystick Button 2")
- PORT_BIT( 0x40, IP_ACTIVE_LOW, IPT_UNUSED )
- PORT_BIT( 0x80, IP_ACTIVE_LOW, IPT_UNUSED )
-INPUT_PORTS_END
diff --git a/src/devices/bus/cbus/pc9801_snd.h b/src/devices/bus/cbus/pc9801_snd.h
deleted file mode 100644
index 600e555b329..00000000000
--- a/src/devices/bus/cbus/pc9801_snd.h
+++ /dev/null
@@ -1,31 +0,0 @@
-// license:BSD-3-Clause
-// copyright-holders:Angelo Salese
-/***************************************************************************
-
- NEC PC-9801
- common functions for CBUS sound boards -26, -86, -118
-
-***************************************************************************/
-
-#ifndef MAME_BUS_CBUS_PC9801_SND_H
-#define MAME_BUS_CBUS_PC9801_SND_H
-
-#pragma once
-
-class pc9801_snd_device : public device_t
-{
-public:
- pc9801_snd_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock);
-
-protected:
- DECLARE_READ8_MEMBER(opn_porta_r);
- DECLARE_WRITE8_MEMBER(opn_portb_w);
-
-private:
- uint8_t m_joy_sel;
-};
-
-//DECLARE_DEVICE_TYPE(PC9801_SND, pc9801_snd_device)
-INPUT_PORTS_EXTERN(pc9801_joy_port);
-
-#endif
diff --git a/src/devices/bus/cbus/sb16_ct2720.cpp b/src/devices/bus/cbus/sb16_ct2720.cpp
new file mode 100644
index 00000000000..cbe417c9960
--- /dev/null
+++ b/src/devices/bus/cbus/sb16_ct2720.cpp
@@ -0,0 +1,121 @@
+// license:BSD-3-Clause
+// copyright-holders:Angelo Salese
+/**************************************************************************************************
+
+Creative Sound Blaster 16 for PC-9800 Series (board name: CT2720)
+
+References:
+- https://j02.nobody.jp/jto98/n_desk_sound/ct2720.htm
+- http://retropc.net/yasuma/V2/PC/SOUND/ct2720.html
+
+TODO:
+- Optional YM2203 (+ ROM socket), PC-9801-26K equivalent fallback;
+- Game port;
+- MIDI;
+- CT1741 (DSP);
+- CT1745 (Mixer);
+- CD-Rom interface/CD-In;
+- Mic-In/Line-In;
+- Configuration dips;
+
+**************************************************************************************************/
+
+#include "emu.h"
+#include "bus/cbus/sb16_ct2720.h"
+#include "speaker.h"
+
+
+DEFINE_DEVICE_TYPE(SB16_CT2720, sb16_ct2720_device, "sb16_ct2720", "Creative Sound Blaster 16 CT-2720")
+
+sb16_ct2720_device::sb16_ct2720_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
+ : device_t(mconfig, SB16_CT2720, tag, owner, clock)
+ , m_bus(*this, DEVICE_SELF_OWNER)
+ , m_opl3(*this, "opl3")
+ , m_mixer(*this, "mixer")
+ , m_ldac(*this, "ldac")
+ , m_rdac(*this, "rdac")
+{
+}
+
+void sb16_ct2720_device::device_add_mconfig(machine_config &config)
+{
+ SPEAKER(config, "speaker", 2).front();
+
+ CT1745(config, m_mixer);
+ m_mixer->set_fm_tag(m_opl3);
+ m_mixer->set_ldac_tag(m_ldac);
+ m_mixer->set_rdac_tag(m_rdac);
+ m_mixer->add_route(0, "speaker", 1.0, 0);
+ m_mixer->add_route(1, "speaker", 1.0, 1);
+ m_mixer->irq_status_cb().set([this] () {
+ (void)this;
+ return 0;
+ //return (m_irq8 << 0) | (m_irq16 << 1) | (m_irq_midi << 2) | (0x8 << 4);
+ });
+
+// 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");
+
+ DAC_16BIT_R2R(config, m_ldac, 0).add_route(ALL_OUTPUTS, m_mixer, 0.5, 0); // unknown DAC
+ DAC_16BIT_R2R(config, m_rdac, 0).add_route(ALL_OUTPUTS, m_mixer, 0.5, 1); // unknown DAC
+
+ YMF262(config, m_opl3, XTAL(14'318'181));
+ m_opl3->add_route(0, m_mixer, 1.00, 0);
+ m_opl3->add_route(1, m_mixer, 1.00, 1);
+ m_opl3->add_route(2, m_mixer, 1.00, 0);
+ m_opl3->add_route(3, m_mixer, 1.00, 1);
+}
+
+void sb16_ct2720_device::device_start()
+{
+ m_bus->install_device(0x0000, 0xffff, *this, &sb16_ct2720_device::io_map);
+}
+
+void sb16_ct2720_device::device_reset()
+{
+}
+
+void sb16_ct2720_device::io_map(address_map &map)
+{
+ const u16 base = 0xd2;
+// map(0x0400 | base, 0x0400 | base).select(0x300) PC Gameport
+ map(0x2000 | base, 0x2000 | base).select(0x300).lrw8(
+ NAME([this] (offs_t offset) {
+ return m_opl3->read(offset >> 8);
+ }),
+ NAME([this] (offs_t offset, u8 data) {
+ m_opl3->write(offset >> 8, data);
+ })
+ );
+ // ($224-$225 on AT)
+ map(0x2400 | base, 0x2400 | base).select(0x100).lrw8(
+ NAME([this] (offs_t offset) {
+ return m_mixer->read(offset >> 8);
+ }),
+ NAME([this] (offs_t offset, u8 data) {
+ m_mixer->write(offset >> 8, data);
+ })
+ );
+// map(0x2600 | base, 0x2600 | base) CT1741 DSP reset
+ map(0x2800 | base, 0x2800 | base).select(0x100).lrw8(
+ NAME([this] (offs_t offset) {
+ return m_opl3->read(offset >> 8);
+ }),
+ NAME([this] (offs_t offset, u8 data) {
+ m_opl3->write(offset >> 8, data);
+ })
+ );
+// map(0x2a00 | base, 0x2a00 | base) CT1741 DSP read data port
+// map(0x2c00 | base, 0x2c00 | base).select(0x300) CT1741 DSP ($22c-$22f on AT)
+// map(0x8000 | base, 0x8000 | base).select(0x100) MIDI port/Wave Blaster
+ map(0xc800 | base, 0xc800 | base).select(0x300).lrw8(
+ NAME([this] (offs_t offset) {
+ return m_opl3->read(offset >> 8);
+ }),
+ NAME([this] (offs_t offset, u8 data) {
+ m_opl3->write(offset >> 8, data);
+ })
+ );
+}
diff --git a/src/devices/bus/cbus/sb16_ct2720.h b/src/devices/bus/cbus/sb16_ct2720.h
new file mode 100644
index 00000000000..48178a9313a
--- /dev/null
+++ b/src/devices/bus/cbus/sb16_ct2720.h
@@ -0,0 +1,52 @@
+// license:BSD-3-Clause
+// copyright-holders:Angelo Salese
+
+#ifndef MAME_BUS_CBUS_SB16_CT2720_H
+#define MAME_BUS_CBUS_SB16_CT2720_H
+
+#pragma once
+
+#include "bus/cbus/pc9801_cbus.h"
+//#include "bus/midi/midi.h"
+//#include "bus/pc_joy/pc_joy.h"
+#include "sound/ct1745.h"
+#include "sound/dac.h"
+#include "sound/ymopl.h"
+//#include "diserial.h"
+
+
+//**************************************************************************
+// TYPE DEFINITIONS
+//**************************************************************************
+
+class sb16_ct2720_device : public device_t
+{
+public:
+ // construction/destruction
+ sb16_ct2720_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
+
+ static constexpr feature_type unemulated_features() { return feature::SOUND | feature::MICROPHONE; }
+
+protected:
+ // device-level overrides
+ virtual void device_start() override ATTR_COLD;
+ virtual void device_reset() override ATTR_COLD;
+
+ // optional information overrides
+ virtual void device_add_mconfig(machine_config &config) override ATTR_COLD;
+
+private:
+ void io_map(address_map &map) ATTR_COLD;
+
+ required_device<pc9801_slot_device> m_bus;
+ required_device<ymf262_device> m_opl3;
+ required_device<ct1745_mixer_device> m_mixer;
+ required_device<dac_16bit_r2r_device> m_ldac;
+ required_device<dac_16bit_r2r_device> m_rdac;
+};
+
+
+// device type definition
+DECLARE_DEVICE_TYPE(SB16_CT2720, sb16_ct2720_device)
+
+#endif // MAME_BUS_CBUS_SB16_CT2720_H
diff --git a/src/devices/bus/centronics/adaptator.cpp b/src/devices/bus/centronics/adaptator.cpp
new file mode 100644
index 00000000000..411992b6652
--- /dev/null
+++ b/src/devices/bus/centronics/adaptator.cpp
@@ -0,0 +1,91 @@
+// license:BSD-3-Clause
+// copyright-holders:Angelo Salese
+/**************************************************************************************************
+
+"The Adaptator" a.k.a. DIY parallel port to 2x DE-9 Multitap adapter
+
+Originally bundled with the Amiga/ST/DOS/C=64 versions of Dyna Blaster as a sort of mandatory
+dongle (i.e. game menus needs joy 3 in Amiga version at least).
+
+List of known supported games:
+amigaocs_flop
+- dynabls;
+- kickoff2;
+- gauntlt2;
+- protent2;
+- sskid;
+
+TODO:
+- DOS ct486 dynablst doesn't work, BIOS shenanigans?
+- atarist (cracked only, loose) Dyna Blaster doesn't work either, needs select and data in routing;
+- Untested on C=64;
+- gauntlt2 seemingly requires a slightly different pinout according to the Super Skidmarks
+ manual "connect pin 6 of joy 3 to pin 13 (?), pin 6 of joy 4 to pin 12";
+- Anything that isn't Atari/Commodore single button joystick is uncharted waters at current time
+ (read: no SW pretends to read a mouse or a MD pad with this);
+
+References:
+- https://www.aminet.net/package/util/misc/ControllerTest technical documentation;
+- https://www.aminet.net/package/util/misc/VATestprogram MouseJoy test;
+- Super Skidmarks manual, page 3;
+
+**************************************************************************************************/
+
+#include "emu.h"
+#include "adaptator.h"
+
+DEFINE_DEVICE_TYPE(ADAPTATOR_MULTITAP, adaptator_multitap_device, "adaptator_multitap", "The Adaptator 2x DE-9 Multitap")
+
+adaptator_multitap_device::adaptator_multitap_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) :
+ device_t(mconfig, ADAPTATOR_MULTITAP, tag, owner, clock),
+ device_centronics_peripheral_interface(mconfig, *this),
+ m_joy(*this, "joy_p%u", 1U)
+{ }
+
+
+void adaptator_multitap_device::device_add_mconfig(machine_config &config)
+{
+ VCS_CONTROL_PORT(config, m_joy[0], vcs_control_port_devices, "joy");
+ VCS_CONTROL_PORT(config, m_joy[1], vcs_control_port_devices, "joy");
+}
+
+void adaptator_multitap_device::device_start()
+{
+ save_item(NAME(m_ddr));
+}
+
+void adaptator_multitap_device::input_strobe(int state)
+{
+ // assume 1 -> 0, assume writing to the data port causes pullup
+ // i.e. ControllerTest just writes a 0xff, at init time. ct486 do the same at POST.
+ if (state)
+ return;
+
+ u8 p1_in = m_joy[0]->read_joy();
+ u8 p2_in = m_joy[1]->read_joy();
+
+ // route pin 13 -> joy port 3 pin 6
+ output_select(BIT(p1_in, 5));
+ // route pin 11 -> joy port 4 pin 6
+ output_busy(BIT(p2_in, 5));
+ // pins 18-22 -> pin 8 ground for both
+
+ // NOTE: 2nd button hooks are possible but ControllerTest warns that ACK
+ // "is not easily available to software without some fancy interrupt trickery"
+ // so it doesn't support it.
+ // route pin 12 (pout) -> joy port 3 pin 9
+ //output_perror(BIT(p1_in, ?));
+ // route pin 10 (ack) -> joy port 4 pin 9
+ //output_ack(BIT(p2_in, ?));
+
+ // route pins 2-5 -> joy port 3 pins 1-4
+ output_data0(BIT(p1_in, 0));
+ output_data1(BIT(p1_in, 1));
+ output_data2(BIT(p1_in, 2));
+ output_data3(BIT(p1_in, 3));
+ // route pins 6-9 -> joy port 4 pins 1-4
+ output_data4(BIT(p2_in, 0));
+ output_data5(BIT(p2_in, 1));
+ output_data6(BIT(p2_in, 2));
+ output_data7(BIT(p2_in, 3));
+}
diff --git a/src/devices/bus/centronics/adaptator.h b/src/devices/bus/centronics/adaptator.h
new file mode 100644
index 00000000000..b2c031475d9
--- /dev/null
+++ b/src/devices/bus/centronics/adaptator.h
@@ -0,0 +1,44 @@
+// license:BSD-3-Clause
+// copyright-holders:Angelo Salese
+
+#ifndef MAME_BUS_CENTRONICS_ADAPTATOR_H
+#define MAME_BUS_CENTRONICS_ADAPTATOR_H
+
+#pragma once
+
+#include "ctronics.h"
+#include "bus/vcs_ctrl/ctrl.h"
+
+class adaptator_multitap_device : public device_t,
+ public device_centronics_peripheral_interface
+{
+public:
+ // construction/destruction
+ adaptator_multitap_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
+
+ virtual void input_strobe(int state) override;
+ virtual void input_data0(int state) override { if (state) m_ddr |= 0x01; else m_ddr &= ~0x01; }
+ virtual void input_data1(int state) override { if (state) m_ddr |= 0x02; else m_ddr &= ~0x02; }
+ virtual void input_data2(int state) override { if (state) m_ddr |= 0x04; else m_ddr &= ~0x04; }
+ virtual void input_data3(int state) override { if (state) m_ddr |= 0x08; else m_ddr &= ~0x08; }
+ virtual void input_data4(int state) override { if (state) m_ddr |= 0x10; else m_ddr &= ~0x10; }
+ virtual void input_data5(int state) override { if (state) m_ddr |= 0x20; else m_ddr &= ~0x20; }
+ virtual void input_data6(int state) override { if (state) m_ddr |= 0x40; else m_ddr &= ~0x40; }
+ virtual void input_data7(int state) override { if (state) m_ddr |= 0x80; else m_ddr &= ~0x80; }
+
+protected:
+ // device-level overrides
+ virtual void device_start() override ATTR_COLD;
+ virtual void device_add_mconfig(machine_config &config) override ATTR_COLD;
+
+private:
+ required_device_array<vcs_control_port_device, 2> m_joy;
+
+ u8 m_ddr;
+};
+
+// device type definition
+DECLARE_DEVICE_TYPE(ADAPTATOR_MULTITAP, adaptator_multitap_device)
+
+
+#endif // MAME_BUS_CENTRONICS_ADAPTATOR_H
diff --git a/src/devices/bus/centronics/chessmec.cpp b/src/devices/bus/centronics/chessmec.cpp
index dc61831a42c..fb30a7253b7 100644
--- a/src/devices/bus/centronics/chessmec.cpp
+++ b/src/devices/bus/centronics/chessmec.cpp
@@ -2,7 +2,7 @@
// copyright-holders:hap
/*
-The ChessMachine EC by Tasc
+The ChessMachine EC by Tasc (LPT interface)
External module with ARM2 CPU, also sold under the Mephisto brand by H+G
see chessmachine_device for technical notes
@@ -13,7 +13,7 @@ see chessmachine_device for technical notes
#include "chessmec.h"
-DEFINE_DEVICE_TYPE(CENTRONICS_CHESSMEC, centronics_chessmec_device, "centronics_chessmec", "The ChessMachine EC")
+DEFINE_DEVICE_TYPE(CENTRONICS_CHESSMEC, centronics_chessmec_device, "centronics_chessmec", "Tasc ChessMachine EC Interface")
//-------------------------------------------------
// constructor
@@ -26,13 +26,11 @@ centronics_chessmec_device::centronics_chessmec_device(const machine_config &mco
{ }
-
//-------------------------------------------------
// device_add_mconfig - add device configuration
//-------------------------------------------------
void centronics_chessmec_device::device_add_mconfig(machine_config &config)
{
- CHESSMACHINE(config, m_chessm, 15'000'000);
- m_chessm->data_out().set(FUNC(centronics_chessmec_device::output_busy));
+ CHESSMACHINE(config, m_chessm, 15'000'000).data_out().set(FUNC(centronics_chessmec_device::output_busy));
}
diff --git a/src/devices/bus/centronics/chessmec.h b/src/devices/bus/centronics/chessmec.h
index 07bbd8970c3..5123ef3fa04 100644
--- a/src/devices/bus/centronics/chessmec.h
+++ b/src/devices/bus/centronics/chessmec.h
@@ -25,11 +25,11 @@ public:
protected:
// device-level overrides
virtual void device_start() override { }
- virtual void device_add_mconfig(machine_config &config) override;
+ virtual void device_add_mconfig(machine_config &config) override ATTR_COLD;
- 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.cpp b/src/devices/bus/centronics/comxpl80.cpp
index 3b0910389fa..65646f0d290 100644
--- a/src/devices/bus/centronics/comxpl80.cpp
+++ b/src/devices/bus/centronics/comxpl80.cpp
@@ -153,7 +153,7 @@ void comx_pl80_device::device_reset()
// pa_w -
//-------------------------------------------------
-WRITE8_MEMBER( comx_pl80_device::pa_w )
+void comx_pl80_device::pa_w(uint8_t data)
{
/*
@@ -205,7 +205,7 @@ WRITE8_MEMBER( comx_pl80_device::pa_w )
// pb_w -
//-------------------------------------------------
-WRITE8_MEMBER( comx_pl80_device::pb_w )
+void comx_pl80_device::pb_w(uint8_t data)
{
/*
@@ -232,7 +232,7 @@ WRITE8_MEMBER( comx_pl80_device::pb_w )
// pc_w -
//-------------------------------------------------
-WRITE8_MEMBER( comx_pl80_device::pc_w )
+void comx_pl80_device::pc_w(uint8_t data)
{
/*
@@ -262,7 +262,7 @@ WRITE8_MEMBER( comx_pl80_device::pc_w )
// pd_r -
//-------------------------------------------------
-READ8_MEMBER( comx_pl80_device::pd_r )
+uint8_t comx_pl80_device::pd_r()
{
/*
diff --git a/src/devices/bus/centronics/comxpl80.h b/src/devices/bus/centronics/comxpl80.h
index a6e77e730a2..06e7a90923b 100644
--- a/src/devices/bus/centronics/comxpl80.h
+++ b/src/devices/bus/centronics/comxpl80.h
@@ -30,22 +30,22 @@ public:
protected:
// device-level overrides
- virtual void device_start() override;
- virtual void device_reset() override;
+ virtual void device_start() override ATTR_COLD;
+ virtual void device_reset() override ATTR_COLD;
// optional information 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 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 const tiny_rom_entry *device_rom_region() const override ATTR_COLD;
+ virtual void device_add_mconfig(machine_config &config) override ATTR_COLD;
+ virtual ioport_constructor device_input_ports() const override ATTR_COLD;
+
+ 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;
@@ -63,10 +63,10 @@ private:
uint8_t m_data;
- DECLARE_WRITE8_MEMBER( pa_w );
- DECLARE_WRITE8_MEMBER( pb_w );
- DECLARE_WRITE8_MEMBER( pc_w );
- DECLARE_READ8_MEMBER( pd_r );
+ void pa_w(uint8_t data);
+ void pb_w(uint8_t data);
+ void pc_w(uint8_t data);
+ uint8_t pd_r();
};
diff --git a/src/devices/bus/centronics/covox.cpp b/src/devices/bus/centronics/covox.cpp
index 6cafe74cb42..9989308f593 100644
--- a/src/devices/bus/centronics/covox.cpp
+++ b/src/devices/bus/centronics/covox.cpp
@@ -4,11 +4,14 @@
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"
#include "covox.h"
-#include "sound/volt_reg.h"
#include "speaker.h"
//**************************************************************************
@@ -43,9 +46,6 @@ void centronics_covox_device::device_add_mconfig(machine_config &config)
/* sound hardware */
SPEAKER(config, "speaker").front_center();
DAC_8BIT_R2R(config, m_dac, 0).add_route(ALL_OUTPUTS, "speaker", 0.5); // unknown DAC
- voltage_regulator_device &vref(VOLTAGE_REGULATOR(config, "vref"));
- vref.add_route(0, "dac", 1.0, DAC_VREF_POS_INPUT);
- vref.add_route(0, "dac", -1.0, DAC_VREF_NEG_INPUT);
}
void centronics_covox_device::device_start()
@@ -92,15 +92,9 @@ centronics_covox_stereo_device::centronics_covox_stereo_device(const machine_con
void centronics_covox_stereo_device::device_add_mconfig(machine_config &config)
{
/* sound hardware */
- SPEAKER(config, "lspeaker").front_left();
- SPEAKER(config, "rspeaker").front_right();
- DAC_8BIT_R2R(config, m_ldac, 0).add_route(ALL_OUTPUTS, "lspeaker", 0.5); // unknown DAC
- DAC_8BIT_R2R(config, m_rdac, 0).add_route(ALL_OUTPUTS, "rspeaker", 0.5); // unknown DAC
- voltage_regulator_device &vref(VOLTAGE_REGULATOR(config, "vref"));
- vref.add_route(0, "ldac", 1.0, DAC_VREF_POS_INPUT);
- vref.add_route(0, "ldac", -1.0, DAC_VREF_NEG_INPUT);
- vref.add_route(0, "rdac", 1.0, DAC_VREF_POS_INPUT);
- vref.add_route(0, "rdac", -1.0, DAC_VREF_NEG_INPUT);
+ SPEAKER(config, "speaker", 2).front();
+ DAC_8BIT_R2R(config, m_ldac, 0).add_route(ALL_OUTPUTS, "speaker", 0.5, 0); // unknown DAC
+ DAC_8BIT_R2R(config, m_rdac, 0).add_route(ALL_OUTPUTS, "speaker", 0.5, 1); // unknown DAC
}
void centronics_covox_stereo_device::device_start()
diff --git a/src/devices/bus/centronics/covox.h b/src/devices/bus/centronics/covox.h
index da6ed1063aa..50ea2ec51f9 100644
--- a/src/devices/bus/centronics/covox.h
+++ b/src/devices/bus/centronics/covox.h
@@ -25,19 +25,19 @@ public:
protected:
// device-level overrides
- virtual void device_start() override;
+ virtual void device_start() override ATTR_COLD;
// optional information overrides
- virtual void device_add_mconfig(machine_config &config) override;
+ virtual void device_add_mconfig(machine_config &config) override ATTR_COLD;
- 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;
@@ -61,21 +61,21 @@ public:
protected:
// device-level overrides
- virtual void device_start() override;
+ virtual void device_start() override ATTR_COLD;
// 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 device_add_mconfig(machine_config &config) override ATTR_COLD;
+
+ 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 53d5ab7cb4a..3556cb0d756 100644
--- a/src/devices/bus/centronics/ctronics.cpp
+++ b/src/devices/bus/centronics/ctronics.cpp
@@ -13,8 +13,8 @@
DEFINE_DEVICE_TYPE(CENTRONICS, centronics_device, "centronics", "Centronics")
-centronics_device::centronics_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
- : device_t(mconfig, CENTRONICS, tag, owner, clock),
+centronics_device::centronics_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) :
+ device_t(mconfig, CENTRONICS, tag, owner, clock),
device_slot_interface(mconfig, *this),
m_strobe_handler(*this),
m_data0_handler(*this),
@@ -32,6 +32,7 @@ centronics_device::centronics_device(const machine_config &mconfig, const char *
m_autofd_handler(*this),
m_fault_handler(*this),
m_init_handler(*this),
+ m_sense_handler(*this),
m_select_in_handler(*this),
m_dev(nullptr)
{
@@ -42,25 +43,15 @@ void centronics_device::device_config_complete()
m_dev = dynamic_cast<device_centronics_peripheral_interface *>(get_card_device());
}
+void centronics_device::device_reset()
+{
+ if (m_dev && m_dev->supports_pin35_5v())
+ m_sense_handler(1);
+}
+
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_select_in_handler.resolve_safe();
+ m_sense_handler(0);
// pull up
m_strobe_handler(1);
@@ -94,29 +85,29 @@ 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
device_centronics_peripheral_interface::device_centronics_peripheral_interface(const machine_config &mconfig, device_t &device)
- : device_slot_card_interface(mconfig, device)
+ : device_interface(device, "centronics")
{
m_slot = dynamic_cast<centronics_device *>(device.owner());
}
@@ -126,25 +117,40 @@ device_centronics_peripheral_interface::~device_centronics_peripheral_interface(
}
+#include "adaptator.h"
#include "comxpl80.h"
#include "epson_ex800.h"
+#include "epson_fx80.h"
#include "epson_lx800.h"
#include "epson_lx810l.h"
+#include "epson_rx80.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)
{
+ device.option_add("adaptator", ADAPTATOR_MULTITAP);
device.option_add("pl80", COMX_PL80);
device.option_add("ex800", EPSON_EX800);
+ device.option_add("fx80", EPSON_FX80);
+ device.option_add("jx80", EPSON_JX80);
device.option_add("lx800", EPSON_LX800);
device.option_add("lx810l", EPSON_LX810L);
device.option_add("ap2000", EPSON_AP2000);
+ device.option_add("rx80", EPSON_RX80);
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 7189c465e98..cd3c9449705 100644
--- a/src/devices/bus/centronics/ctronics.h
+++ b/src/devices/bus/centronics/ctronics.h
@@ -18,8 +18,7 @@ DECLARE_DEVICE_TYPE(CENTRONICS, centronics_device)
class device_centronics_peripheral_interface;
-class centronics_device : public device_t,
- public device_slot_interface
+class centronics_device : public device_t, public device_slot_interface
{
friend class device_centronics_peripheral_interface;
@@ -44,6 +43,7 @@ public:
auto autofd_handler() { return m_autofd_handler.bind(); }
auto fault_handler() { return m_fault_handler.bind(); }
auto init_handler() { return m_init_handler.bind(); }
+ auto sense_handler() { return m_sense_handler.bind(); }
auto select_in_handler() { return m_select_in_handler.bind(); }
template <typename T> void set_data_input_buffer(T &&tag)
@@ -60,28 +60,29 @@ 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
virtual void device_config_complete() override;
- virtual void device_start() override;
+ virtual void device_reset() override ATTR_COLD;
+ virtual void device_start() override ATTR_COLD;
devcb_write_line m_strobe_handler;
devcb_write_line m_data0_handler;
@@ -99,6 +100,7 @@ protected:
devcb_write_line m_autofd_handler;
devcb_write_line m_fault_handler;
devcb_write_line m_init_handler;
+ devcb_write_line m_sense_handler;
devcb_write_line m_select_in_handler;
private:
@@ -106,51 +108,53 @@ private:
};
-class device_centronics_peripheral_interface : public device_slot_card_interface
+class device_centronics_peripheral_interface : public device_interface
{
friend class centronics_device;
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; }
centronics_device *m_slot;
};
diff --git a/src/devices/bus/centronics/digiblst.cpp b/src/devices/bus/centronics/digiblst.cpp
index 97a37054172..3b66d35b9df 100644
--- a/src/devices/bus/centronics/digiblst.cpp
+++ b/src/devices/bus/centronics/digiblst.cpp
@@ -1,29 +1,28 @@
// license:BSD-3-Clause
// copyright-holders:Barry Rodewald
/*
- * digiblst.c
+ * digiblst.cpp
*
* Created on: 23/08/2014
*/
#include "emu.h"
#include "digiblst.h"
-#include "sound/volt_reg.h"
#include "speaker.h"
//**************************************************************************
-// COVOX DEVICE
+// DIGIBLASTER DEVICE
//**************************************************************************
// 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)")
/***************************************************************************
IMPLEMENTATION
***************************************************************************/
//-------------------------------------------------
-// centronics_covox_device - constructor
+// centronics_digiblaster_device - constructor
//-------------------------------------------------
centronics_digiblaster_device::centronics_digiblaster_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
@@ -43,9 +42,6 @@ void centronics_digiblaster_device::device_add_mconfig(machine_config &config)
/* sound hardware */
SPEAKER(config, "speaker").front_center();
DAC_8BIT_R2R(config, m_dac, 0).add_route(ALL_OUTPUTS, "speaker", 0.5); // unknown DAC
- voltage_regulator_device &vref(VOLTAGE_REGULATOR(config, "vref"));
- vref.add_route(0, "dac", 1.0, DAC_VREF_POS_INPUT);
- vref.add_route(0, "dac", -1.0, DAC_VREF_NEG_INPUT);
}
void centronics_digiblaster_device::device_start()
diff --git a/src/devices/bus/centronics/digiblst.h b/src/devices/bus/centronics/digiblst.h
index d6c40cec78c..f779105e771 100644
--- a/src/devices/bus/centronics/digiblst.h
+++ b/src/devices/bus/centronics/digiblst.h
@@ -20,7 +20,7 @@
#include "ctronics.h"
#include "sound/dac.h"
-// ======================> centronics_covox_device
+// ======================> centronics_digiblaster_device
class centronics_digiblaster_device : public device_t,
public device_centronics_peripheral_interface
@@ -31,19 +31,19 @@ public:
protected:
// device-level overrides
- virtual void device_start() override;
+ virtual void device_start() override ATTR_COLD;
// 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 device_add_mconfig(machine_config &config) override ATTR_COLD;
+
+ 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..69724f1e0e0 100644
--- a/src/devices/bus/centronics/dsjoy.h
+++ b/src/devices/bus/centronics/dsjoy.h
@@ -22,15 +22,15 @@ public:
protected:
// device-level overrides
- 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 device_start() override ATTR_COLD;
+ virtual ioport_constructor device_input_ports() const override ATTR_COLD;
+
+ 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_ex800.cpp b/src/devices/bus/centronics/epson_ex800.cpp
index 5c978d49172..56d485859f8 100644
--- a/src/devices/bus/centronics/epson_ex800.cpp
+++ b/src/devices/bus/centronics/epson_ex800.cpp
@@ -1,4 +1,4 @@
-// license:GPL-2.0+
+// license:BSD-3-Clause
// copyright-holders:Dirk Best
/******************************************************************************
@@ -254,7 +254,7 @@ INPUT_CHANGED_MEMBER(epson_ex800_device::online_switch)
INPUT_PORTS_START( epson_ex800 )
PORT_START("ONLISW")
PORT_BIT(0xfe, IP_ACTIVE_HIGH, IPT_UNUSED)
- PORT_BIT(0x01, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_NAME("ON LINE") PORT_CODE(KEYCODE_F9) PORT_CHANGED_MEMBER(DEVICE_SELF, epson_ex800_device, online_switch, 0)
+ PORT_BIT(0x01, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_NAME("ON LINE") PORT_CODE(KEYCODE_F9) PORT_CHANGED_MEMBER(DEVICE_SELF, FUNC(epson_ex800_device::online_switch), 0)
PORT_START("FEED")
PORT_BIT(0xfc, IP_ACTIVE_LOW, IPT_UNUSED)
@@ -372,25 +372,25 @@ void epson_ex800_device::device_reset()
}
-READ8_MEMBER(epson_ex800_device::porta_r)
+uint8_t epson_ex800_device::porta_r()
{
logerror("PA R %s\n", machine().describe_context());
return machine().rand();
}
-READ8_MEMBER(epson_ex800_device::portb_r)
+uint8_t epson_ex800_device::portb_r()
{
logerror("PB R %s\n", machine().describe_context());
return machine().rand();
}
-READ8_MEMBER(epson_ex800_device::portc_r)
+uint8_t epson_ex800_device::portc_r()
{
logerror("PC R %s\n", machine().describe_context());
return machine().rand();
}
-WRITE8_MEMBER(epson_ex800_device::porta_w)
+void epson_ex800_device::porta_w(uint8_t data)
{
if (PA6) logerror("BNK0 selected.\n");
if (PA7) logerror("BNK1 selected.\n");
@@ -398,7 +398,7 @@ WRITE8_MEMBER(epson_ex800_device::porta_w)
logerror("PA W %x %s\n", data, machine().describe_context());
}
-WRITE8_MEMBER(epson_ex800_device::portb_w)
+void epson_ex800_device::portb_w(uint8_t data)
{
if (data & 3)
logerror("PB0/1 Line feed %s\n", machine().describe_context());
@@ -422,7 +422,7 @@ WRITE8_MEMBER(epson_ex800_device::portb_w)
// logerror("PB W %x %s\n", data, machine().describe_context());
}
-WRITE8_MEMBER(epson_ex800_device::portc_w)
+void epson_ex800_device::portc_w(uint8_t data)
{
if (data & 0x80)
m_beeper->set_state(0);
@@ -435,46 +435,46 @@ WRITE8_MEMBER(epson_ex800_device::portc_w)
/* Memory mapped I/O access */
-READ8_MEMBER(epson_ex800_device::devsel_r)
+uint8_t epson_ex800_device::devsel_r(offs_t offset)
{
logerror("DEVSEL R %s with offset %x\n", machine().describe_context(), offset);
return machine().rand();
}
-WRITE8_MEMBER(epson_ex800_device::devsel_w)
+void epson_ex800_device::devsel_w(offs_t offset, uint8_t data)
{
logerror("DEVSEL W %x %s with offset %x\n", data, machine().describe_context(), offset);
}
-READ8_MEMBER(epson_ex800_device::gate5a_r)
+uint8_t epson_ex800_device::gate5a_r(offs_t offset)
{
logerror("GATE5A R %s with offset %x\n", machine().describe_context(), offset);
return machine().rand();
}
-WRITE8_MEMBER(epson_ex800_device::gate5a_w)
+void epson_ex800_device::gate5a_w(offs_t offset, uint8_t data)
{
logerror("GATE5A W %x %s with offset %x\n", data, machine().describe_context(), offset);
}
-READ8_MEMBER(epson_ex800_device::iosel_r)
+uint8_t epson_ex800_device::iosel_r(offs_t offset)
{
logerror("IOSEL R %s with offset %x\n", machine().describe_context(), offset);
return machine().rand();
}
-WRITE8_MEMBER(epson_ex800_device::iosel_w)
+void epson_ex800_device::iosel_w(offs_t offset, uint8_t data)
{
logerror("IOSEL W %x %s with offset %x\n", data, machine().describe_context(), offset);
}
-READ8_MEMBER(epson_ex800_device::gate7a_r)
+uint8_t epson_ex800_device::gate7a_r(offs_t offset)
{
logerror("GATE7A R %s with offset %x\n", machine().describe_context(), offset);
return machine().rand();
}
-WRITE8_MEMBER(epson_ex800_device::gate7a_w)
+void epson_ex800_device::gate7a_w(offs_t offset, uint8_t data)
{
logerror("GATE7A W %x %s with offset %x\n", data, machine().describe_context(), offset);
}
diff --git a/src/devices/bus/centronics/epson_ex800.h b/src/devices/bus/centronics/epson_ex800.h
index 372f30eb660..703882b02a4 100644
--- a/src/devices/bus/centronics/epson_ex800.h
+++ b/src/devices/bus/centronics/epson_ex800.h
@@ -1,4 +1,4 @@
-// license:GPL-2.0+
+// license:BSD-3-Clause
// copyright-holders:Dirk Best
/**********************************************************************
@@ -33,31 +33,33 @@ public:
protected:
// device-level overrides
- virtual void device_start() override;
- virtual void device_reset() override;
+ virtual void device_start() override ATTR_COLD;
+ virtual void device_reset() override ATTR_COLD;
// optional information 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 const tiny_rom_entry *device_rom_region() const override ATTR_COLD;
+ virtual void device_add_mconfig(machine_config &config) override ATTR_COLD;
+ virtual ioport_constructor device_input_ports() const override ATTR_COLD;
+
+ virtual bool supports_pin35_5v() override { return true; }
private:
- DECLARE_READ8_MEMBER(porta_r);
- DECLARE_READ8_MEMBER(portb_r);
- DECLARE_READ8_MEMBER(portc_r);
- DECLARE_WRITE8_MEMBER(porta_w);
- DECLARE_WRITE8_MEMBER(portb_w);
- DECLARE_WRITE8_MEMBER(portc_w);
- DECLARE_READ8_MEMBER(devsel_r);
- DECLARE_WRITE8_MEMBER(devsel_w);
- DECLARE_READ8_MEMBER(gate5a_r);
- DECLARE_WRITE8_MEMBER(gate5a_w);
- DECLARE_READ8_MEMBER(iosel_r);
- DECLARE_WRITE8_MEMBER(iosel_w);
- DECLARE_READ8_MEMBER(gate7a_r);
- DECLARE_WRITE8_MEMBER(gate7a_w);
-
- void ex800_mem(address_map &map);
+ uint8_t porta_r();
+ uint8_t portb_r();
+ uint8_t portc_r();
+ void porta_w(uint8_t data);
+ void portb_w(uint8_t data);
+ void portc_w(uint8_t data);
+ uint8_t devsel_r(offs_t offset);
+ void devsel_w(offs_t offset, uint8_t data);
+ uint8_t gate5a_r(offs_t offset);
+ void gate5a_w(offs_t offset, uint8_t data);
+ uint8_t iosel_r(offs_t offset);
+ void iosel_w(offs_t offset, uint8_t data);
+ uint8_t gate7a_r(offs_t offset);
+ void gate7a_w(offs_t offset, uint8_t data);
+
+ void ex800_mem(address_map &map) ATTR_COLD;
required_device<cpu_device> m_maincpu;
required_device<beep_device> m_beeper;
diff --git a/src/devices/bus/centronics/epson_fx80.cpp b/src/devices/bus/centronics/epson_fx80.cpp
new file mode 100644
index 00000000000..7d64c2eb0c4
--- /dev/null
+++ b/src/devices/bus/centronics/epson_fx80.cpp
@@ -0,0 +1,320 @@
+// license:BSD-3-Clause
+// copyright-holders:Golden Child
+/***************************************************************************
+
+ Epson FX-80 Dot Matrix Printer (skeleton)
+
+ Main CPU is a UPD7810H6 running at 10 MHz.
+ Slave CPU is an 8042AH running at 11 Mhz.
+
+ Epson JX-80 Dot Matrix Printer (skeleton)
+
+ based on same hardware, adds an expansion board VX0B
+ that provides ram expansion and ribbon motor control
+
+*****************************************************************************/
+
+#include "emu.h"
+#include "epson_fx80.h"
+
+#include "cpu/mcs48/mcs48.h"
+#include "cpu/upd7810/upd7810.h"
+
+
+namespace {
+
+//**************************************************************************
+// TYPE DEFINITIONS
+//**************************************************************************
+
+class epson_fx80_device : public device_t, public device_centronics_peripheral_interface
+{
+public:
+ static constexpr feature_type unemulated_features() { return feature::PRINTER; }
+
+ // construction/destruction
+ epson_fx80_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
+
+ /* Centronics stuff */
+ virtual void input_init(int state) override;
+ virtual void input_strobe(int state) override;
+ virtual void input_data0(int state) override { if (state) m_centronics_data |= 0x01; else m_centronics_data &= ~0x01; }
+ virtual void input_data1(int state) override { if (state) m_centronics_data |= 0x02; else m_centronics_data &= ~0x02; }
+ virtual void input_data2(int state) override { if (state) m_centronics_data |= 0x04; else m_centronics_data &= ~0x04; }
+ virtual void input_data3(int state) override { if (state) m_centronics_data |= 0x08; else m_centronics_data &= ~0x08; }
+ virtual void input_data4(int state) override { if (state) m_centronics_data |= 0x10; else m_centronics_data &= ~0x10; }
+ virtual void input_data5(int state) override { if (state) m_centronics_data |= 0x20; else m_centronics_data &= ~0x20; }
+ virtual void input_data6(int state) override { if (state) m_centronics_data |= 0x40; else m_centronics_data &= ~0x40; }
+ virtual void input_data7(int state) override { if (state) m_centronics_data |= 0x80; else m_centronics_data &= ~0x80; }
+
+protected:
+ epson_fx80_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock);
+
+ virtual void device_start() override ATTR_COLD;
+ virtual void device_reset() override ATTR_COLD;
+
+ virtual const tiny_rom_entry *device_rom_region() const override ATTR_COLD;
+ virtual void device_add_mconfig(machine_config &config) override ATTR_COLD;
+ virtual ioport_constructor device_input_ports() const override ATTR_COLD;
+
+ virtual bool supports_pin35_5v() override { return true; }
+
+ void epson_fx80_mem(address_map &map) ATTR_COLD;
+
+ uint8_t slave_r(offs_t offset);
+ void slave_w(offs_t offset, uint8_t data);
+ uint8_t slave_p1_r();
+ void slave_p2_w(uint8_t data);
+ uint8_t centronics_data_r(offs_t offset);
+
+ TIMER_CALLBACK_MEMBER(slave_write_sync);
+
+ uint8_t pts_sensor() { return 0; }
+ uint8_t home_sensor() { return 0; }
+
+ required_device<upd7810_device> m_maincpu;
+ required_device<i8042ah_device> m_slavecpu;
+
+ uint8_t m_centronics_data;
+};
+
+
+class epson_jx80_device : public epson_fx80_device
+{
+public:
+ // construction/destruction
+ epson_jx80_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
+
+protected:
+ virtual void device_add_mconfig(machine_config &config) override ATTR_COLD;
+ virtual const tiny_rom_entry *device_rom_region() const override ATTR_COLD;
+
+ void epson_jx80_mem(address_map &map) ATTR_COLD;
+ uint8_t vxob_r(offs_t offset);
+ void vxob_w(offs_t offset, uint8_t data);
+};
+
+
+
+//-------------------------------------------------
+// ROM( epson_fx80 )
+//-------------------------------------------------
+
+ROM_START( epson_fx80 )
+ ROM_REGION(0x4000, "maincpu", 0) // 16K rom for upd7810 FX-80
+ // this is from an fx80+ (found with a M20214GA which according to the tech manual goes with an fx80+)
+ ROM_LOAD("epson_8426k9_m1206ba029_read_as_27c128.bin", 0x0000, 0x4000, CRC(ff5c2b1e) SHA1(e1e38c3e4864e60f701939e23331360b76603a24))
+
+ ROM_REGION(0x800, "slavecpu", 0) // 2K rom for 8042
+ ROM_LOAD("epson_fx_c42040kb_8042ah.bin", 0x0000, 0x800, CRC(3e9d08c1) SHA1(d5074f60497cc75d40996e6cef63231d3a3697f1))
+ROM_END
+
+ROM_START( epson_jx80 )
+ ROM_REGION(0x4000, "maincpu", 0) // JX-80 rom
+ ROM_LOAD("jx80_a4_fs5_27128.bin", 0x0000, 0x4000, CRC(2925a47b) SHA1(1864d3561491d7dca78ac2cd13a023460f551184))
+
+ ROM_REGION(0x800, "slavecpu", 0) // 2K rom for 8042
+ ROM_LOAD("epson_fx_c42040kb_8042ah.bin", 0x0000, 0x800, CRC(3e9d08c1) SHA1(d5074f60497cc75d40996e6cef63231d3a3697f1))
+ROM_END
+
+
+//-------------------------------------------------
+// rom_region - device-specific ROM region
+//-------------------------------------------------
+
+const tiny_rom_entry *epson_fx80_device::device_rom_region() const
+{
+ return ROM_NAME(epson_fx80);
+}
+
+const tiny_rom_entry *epson_jx80_device::device_rom_region() const
+{
+ return ROM_NAME(epson_jx80);
+}
+
+//-------------------------------------------------
+// ADDRESS_MAP( epson_fx80_mem )
+//-------------------------------------------------
+
+void epson_fx80_device::epson_fx80_mem(address_map &map)
+{
+ map(0x0000, 0x3fff).rom().region("maincpu", 0);
+ map(0x8000, 0x97ff).ram(); // external RAM 4K + 2K = 0x1800
+ map(0xd000, 0xd001).mirror(0x08fe).rw(FUNC(epson_fx80_device::slave_r), FUNC(epson_fx80_device::slave_w));
+ map(0xd800, 0xd800).r(FUNC(epson_fx80_device::centronics_data_r));
+}
+
+void epson_jx80_device::epson_jx80_mem(address_map &map)
+{
+ map(0x0000, 0x3fff).rom().region("maincpu", 0);
+ map(0x6000, 0x7fff).ram(); // external RAM VXOB board
+ map(0x8000, 0x97ff).ram(); // external RAM 4K + 2K = 0x1800
+ map(0xc800, 0xc801).rw(FUNC(epson_jx80_device::vxob_r), FUNC(epson_jx80_device::vxob_w));
+ map(0xd000, 0xd001).mirror(0x08fe).rw(FUNC(epson_jx80_device::slave_r), FUNC(epson_jx80_device::slave_w));
+ map(0xd800, 0xd800).r(FUNC(epson_jx80_device::centronics_data_r));
+}
+
+
+//-------------------------------------------------
+// device_add_mconfig - add device configuration
+//-------------------------------------------------
+
+void epson_fx80_device::device_add_mconfig(machine_config &config)
+{
+ /* basic machine hardware */
+ upd7810_device &upd(UPD7810(config, m_maincpu, 10000000)); // 10 Mhz
+ upd.set_addrmap(AS_PROGRAM, &epson_fx80_device::epson_fx80_mem);
+
+ /* upi41 i8042 slave cpu */
+ i8042ah_device &sla(I8042AH(config, m_slavecpu, 11000000)); // 11 Mhz
+ sla.p1_in_cb().set(FUNC(epson_fx80_device::slave_p1_r));
+ sla.p2_out_cb().set(FUNC(epson_fx80_device::slave_p2_w));
+ sla.t0_in_cb().set(FUNC(epson_fx80_device::home_sensor));
+ sla.t1_in_cb().set(FUNC(epson_fx80_device::pts_sensor));
+}
+
+void epson_jx80_device::device_add_mconfig(machine_config &config)
+{
+ epson_fx80_device::device_add_mconfig(config);
+ m_maincpu->set_addrmap(AS_PROGRAM, &epson_jx80_device::epson_jx80_mem);
+}
+
+
+//-------------------------------------------------
+// INPUT_PORTS( epson_fx80 )
+//-------------------------------------------------
+
+INPUT_PORTS_START( epson_fx80 )
+INPUT_PORTS_END
+
+//-------------------------------------------------
+// input_ports - device-specific input ports
+//-------------------------------------------------
+
+ioport_constructor epson_fx80_device::device_input_ports() const
+{
+ return INPUT_PORTS_NAME(epson_fx80);
+}
+
+//-------------------------------------------------
+// epson_fx80_device - constructor
+//-------------------------------------------------
+
+// constructor that passes device type
+epson_fx80_device::epson_fx80_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) :
+ epson_fx80_device(mconfig, EPSON_FX80, tag, owner, clock)
+{
+}
+
+// constructor to pass through the device type to device_t
+epson_fx80_device::epson_fx80_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_centronics_peripheral_interface(mconfig, *this),
+ m_maincpu(*this, "maincpu"),
+ m_slavecpu(*this, "slavecpu")
+{
+}
+
+// constructor that pass device type
+epson_jx80_device::epson_jx80_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) :
+ epson_fx80_device(mconfig, EPSON_JX80, tag, owner, clock)
+{
+}
+
+
+//-------------------------------------------------
+// device_start - device-specific startup
+//-------------------------------------------------
+
+void epson_fx80_device::device_start()
+{
+ save_item(NAME(m_centronics_data));
+}
+
+//-------------------------------------------------
+// device_reset - device-specific reset
+//-------------------------------------------------
+
+void epson_fx80_device::device_reset()
+{
+}
+
+//-------------------------------------------------
+// Slave CPU functions
+//-------------------------------------------------
+
+uint8_t epson_fx80_device::slave_r(offs_t offset)
+{
+ return m_slavecpu->upi41_master_r(offset);
+}
+
+void epson_fx80_device::slave_w(offs_t offset, uint8_t data)
+{
+ // pass offset and data packed into param
+ machine().scheduler().synchronize(
+ timer_expired_delegate(FUNC(epson_fx80_device::slave_write_sync), this),
+ (offset << 8) | data);
+}
+
+TIMER_CALLBACK_MEMBER(epson_fx80_device::slave_write_sync)
+{
+ m_slavecpu->upi41_master_w(u32(param) >> 8, u32(param) & 0xff);
+}
+
+uint8_t epson_fx80_device::slave_p1_r()
+{
+ // read DIPSW1
+ return 0;
+}
+
+void epson_fx80_device::slave_p2_w(uint8_t data)
+{
+ // p20 - p21 are cr_stepper
+ // p22, p24 stepper power
+ // p25 not err
+ // p26 online lamp
+ // p27 buzzer
+}
+
+
+//-------------------------------------------------
+// VX0B expansion board (for JX-80)
+//-------------------------------------------------
+
+uint8_t epson_jx80_device::vxob_r(offs_t offset)
+{
+ // read color ribbon home position status, MSB is high if in home position zone
+ return 0; // not hooked up
+}
+
+void epson_jx80_device::vxob_w(offs_t offset, uint8_t data)
+{
+ // bit 6 and 7 control the color ribbon stepper motor
+}
+
+//-------------------------------------------------
+// Centronics data read
+//-------------------------------------------------
+
+uint8_t epson_fx80_device::centronics_data_r(offs_t offset)
+{
+ return 0;
+}
+
+//-------------------------------------------------
+// Centronics device
+//-------------------------------------------------
+
+void epson_fx80_device::input_strobe(int state)
+{
+}
+
+void epson_fx80_device::input_init(int state)
+{
+}
+
+} // anonymous namespace
+
+// GLOBAL
+DEFINE_DEVICE_TYPE_PRIVATE(EPSON_FX80, device_centronics_peripheral_interface, epson_fx80_device, "epson_fx80", "Epson FX-80")
+DEFINE_DEVICE_TYPE_PRIVATE(EPSON_JX80, device_centronics_peripheral_interface, epson_jx80_device, "epson_jx80", "Epson JX-80")
diff --git a/src/devices/bus/centronics/epson_fx80.h b/src/devices/bus/centronics/epson_fx80.h
new file mode 100644
index 00000000000..0db6a1b62f1
--- /dev/null
+++ b/src/devices/bus/centronics/epson_fx80.h
@@ -0,0 +1,20 @@
+// license:BSD-3-Clause
+// copyright-holders:Golden Child
+/**********************************************************************
+
+ Epson FX-80 dot matrix printer emulation (skeleton)
+
+**********************************************************************/
+
+#ifndef MAME_BUS_CENTRONICS_EPSON_FX80_H
+#define MAME_BUS_CENTRONICS_EPSON_FX80_H
+
+#pragma once
+
+#include "ctronics.h"
+
+// device type declaration
+DECLARE_DEVICE_TYPE(EPSON_FX80, device_centronics_peripheral_interface)
+DECLARE_DEVICE_TYPE(EPSON_JX80, device_centronics_peripheral_interface)
+
+#endif // MAME_BUS_CENTRONICS_EPSON_FX80_H
diff --git a/src/devices/bus/centronics/epson_lx800.cpp b/src/devices/bus/centronics/epson_lx800.cpp
index f0b4dd4a968..9022f0befa4 100644
--- a/src/devices/bus/centronics/epson_lx800.cpp
+++ b/src/devices/bus/centronics/epson_lx800.cpp
@@ -1,4 +1,4 @@
-// license:GPL-2.0+
+// license:BSD-3-Clause
// copyright-holders:Dirk Best
/**********************************************************************
@@ -16,7 +16,9 @@
#include "emu.h"
#include "epson_lx800.h"
+
#include "speaker.h"
+
#include "lx800.lh"
@@ -92,7 +94,7 @@ void epson_lx800_device::device_add_mconfig(machine_config &config)
/* gate array */
e05a03_device &ic3b(E05A03(config, "ic3b", 0));
- ic3b.pe_lp_wr_callback().set(FUNC(epson_lx800_device::paperempty_led_w));
+ ic3b.pe_lp_wr_callback().set_output("paperout_led");
ic3b.reso_wr_callback().set(FUNC(epson_lx800_device::reset_w));
ic3b.pe_wr_callback().set(FUNC(epson_lx800_device::centronics_pe_w));
ic3b.data_rd_callback().set(FUNC(epson_lx800_device::centronics_data_r));
@@ -114,54 +116,44 @@ INPUT_PORTS_START( epson_lx800 )
PORT_BIT(0x01, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("Line Feed") PORT_CODE(KEYCODE_L)
PORT_START("DIPSW1")
- PORT_DIPNAME(0x01, 0x00, "Typeface")
- PORT_DIPLOCATION("DIP:8")
- PORT_DIPSETTING(0x01, "Condensed")
- PORT_DIPSETTING(0x00, DEF_STR(Normal))
- PORT_DIPNAME(0x02, 0x00, "ZERO font")
- PORT_DIPLOCATION("DIP:7")
- PORT_DIPSETTING(0x02, "0")
- PORT_DIPSETTING(0x00, "0")
- PORT_DIPNAME(0x04, 0x00, "Character Table")
- PORT_DIPLOCATION("DIP:6")
- PORT_DIPSETTING(0x04, "Graphic")
- PORT_DIPSETTING(0x00, "Italic")
- PORT_DIPNAME(0x08, 0x00, "Paper-out detection")
- PORT_DIPLOCATION("DIP:5")
- PORT_DIPSETTING(0x08, "Valid")
- PORT_DIPSETTING(0x00, "Invalid")
- PORT_DIPNAME(0x10, 0x00, "Printing quality")
- PORT_DIPLOCATION("DIP:4")
- PORT_DIPSETTING(0x10, "NLQ")
- PORT_DIPSETTING(0x00, "Draft")
- PORT_DIPNAME(0xe0, 0xe0, "International character set")
- PORT_DIPLOCATION("DIP:3,2,1")
- PORT_DIPSETTING(0xe0, "U.S.A.")
- PORT_DIPSETTING(0x60, "France")
- PORT_DIPSETTING(0xa0, "Germany")
- PORT_DIPSETTING(0x20, "U.K.")
- PORT_DIPSETTING(0xc0, "Denmark")
- PORT_DIPSETTING(0x40, "Sweden")
- PORT_DIPSETTING(0x80, "Italy")
- PORT_DIPSETTING(0x00, "Spain")
+ PORT_DIPNAME(0x01, 0x00, "Typeface") PORT_DIPLOCATION("SW 1:!1")
+ PORT_DIPSETTING( 0x00, "Normal")
+ PORT_DIPSETTING( 0x01, "Condensed")
+ PORT_DIPNAME(0x02, 0x00, "Shape of zero") PORT_DIPLOCATION("SW 1:!2")
+ PORT_DIPSETTING( 0x00, "Not slashed")
+ PORT_DIPSETTING( 0x02, "Slashed")
+ PORT_DIPNAME(0x04, 0x00, "Character table") PORT_DIPLOCATION("SW 1:!3")
+ PORT_DIPSETTING( 0x00, "Italics")
+ PORT_DIPSETTING( 0x04, "Graphics")
+ PORT_DIPNAME(0x08, 0x00, "Paper-out detection") PORT_DIPLOCATION("SW 1:!4")
+ PORT_DIPSETTING( 0x00, "Invalid")
+ PORT_DIPSETTING( 0x08, "Valid")
+ PORT_DIPNAME(0x10, 0x00, "Printing quality") PORT_DIPLOCATION("SW 1:!5")
+ PORT_DIPSETTING( 0x00, "Draft")
+ PORT_DIPSETTING( 0x10, "NLQ")
+ PORT_DIPNAME(0xe0, 0xe0, "International character set") PORT_DIPLOCATION("SW 1:!6,!7,!8")
+ PORT_DIPSETTING( 0xe0, "USA")
+ PORT_DIPSETTING( 0x60, "France")
+ PORT_DIPSETTING( 0xa0, "Germany")
+ PORT_DIPSETTING( 0x20, "UK")
+ PORT_DIPSETTING( 0xc0, "Denmark")
+ PORT_DIPSETTING( 0x40, "Sweden")
+ PORT_DIPSETTING( 0x80, "Italy")
+ PORT_DIPSETTING( 0x00, "Spain")
PORT_START("DIPSW2")
- PORT_DIPNAME(0x01, 0x00, "Page length")
- PORT_DIPLOCATION("DIP:4")
- PORT_DIPSETTING(0x01, "12\"")
- PORT_DIPSETTING(0x00, "11\"")
- PORT_DIPNAME(0x02, 0x00, "Cut sheet feeder mode")
- PORT_DIPLOCATION("DIP:3")
- PORT_DIPSETTING(0x02, "Valid")
- PORT_DIPSETTING(0x00, "Invalid")
- PORT_DIPNAME(0x04, 0x00, "1\" skip over perforation")
- PORT_DIPLOCATION("DIP:2")
- PORT_DIPSETTING(0x04, "Valid")
- PORT_DIPSETTING(0x00, "Invalid")
- PORT_DIPNAME(0x08, 0x00, "AUTO FEED XT control")
- PORT_DIPLOCATION("DIP:1")
- PORT_DIPSETTING(0x08, "Fix to LOW")
- PORT_DIPSETTING(0x00, "Depends on external signal")
+ PORT_DIPNAME(0x01, 0x00, "Page length") PORT_DIPLOCATION("SW 2:!1")
+ PORT_DIPSETTING( 0x00, "11\"")
+ PORT_DIPSETTING( 0x01, "12\"")
+ PORT_DIPNAME(0x02, 0x00, "Cut-sheet feeder mode") PORT_DIPLOCATION("SW 2:!2")
+ PORT_DIPSETTING( 0x00, DEF_STR(Off))
+ PORT_DIPSETTING( 0x02, DEF_STR(On))
+ PORT_DIPNAME(0x04, 0x00, "Skip over perforation") PORT_DIPLOCATION("SW 2:!3")
+ PORT_DIPSETTING( 0x00, DEF_STR(Off))
+ PORT_DIPSETTING( 0x04, "1\"")
+ PORT_DIPNAME(0x08, 0x00, "Auto line feed") PORT_DIPLOCATION("SW 2:!4")
+ PORT_DIPSETTING( 0x00, DEF_STR(Off)) // controlled by /AUTO FEED XT signal (Centronics pin 14)
+ PORT_DIPSETTING( 0x08, DEF_STR(On))
INPUT_PORTS_END
@@ -193,7 +185,8 @@ epson_lx800_device::epson_lx800_device(const machine_config &mconfig, device_typ
device_t(mconfig, type, tag, owner, clock),
device_centronics_peripheral_interface(mconfig, *this),
m_maincpu(*this, "maincpu"),
- m_beep(*this, "beeper")
+ m_beep(*this, "beeper"),
+ m_online_led(*this, "online_led")
{
}
@@ -204,6 +197,7 @@ epson_lx800_device::epson_lx800_device(const machine_config &mconfig, device_typ
void epson_lx800_device::device_start()
{
+ m_online_led.resolve();
}
@@ -230,7 +224,7 @@ void epson_lx800_device::device_reset()
* PA6 not used
* PA7 R P/S P/S signal from the optional interface
*/
-READ8_MEMBER( epson_lx800_device::porta_r )
+uint8_t epson_lx800_device::porta_r(offs_t offset)
{
uint8_t result = 0;
@@ -245,7 +239,7 @@ READ8_MEMBER( epson_lx800_device::porta_r )
return result;
}
-WRITE8_MEMBER( epson_lx800_device::porta_w )
+void epson_lx800_device::porta_w(offs_t offset, uint8_t data)
{
logerror("%s: lx800_porta_w(%02x): %02x\n", machine().describe_context(), offset, data);
logerror("--> carriage: %d, paper feed: %d\n", BIT(data, 0), BIT(data, 2));
@@ -260,7 +254,7 @@ WRITE8_MEMBER( epson_lx800_device::porta_w )
* PC6 W FIRE drive pulse width signal
* PC7 W BUZZER buzzer signal
*/
-READ8_MEMBER( epson_lx800_device::portc_r )
+uint8_t epson_lx800_device::portc_r(offs_t offset)
{
uint8_t result = 0;
@@ -271,41 +265,41 @@ READ8_MEMBER( epson_lx800_device::portc_r )
return result;
}
-WRITE8_MEMBER( epson_lx800_device::portc_w )
+void epson_lx800_device::portc_w(offs_t offset, uint8_t data)
{
logerror("%s: lx800_portc_w(%02x): %02x\n", machine().describe_context(), offset, data);
logerror("--> err: %d, ack: %d, fire: %d, buzzer: %d\n", BIT(data, 4), BIT(data, 5), BIT(data, 6), BIT(data, 7));
- machine().output().set_value("online_led", !BIT(data, 2));
+ m_online_led = !BIT(data, 2);
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,24 +309,18 @@ READ_LINE_MEMBER( epson_lx800_device::an5_r )
GATE ARRAY
***************************************************************************/
-READ8_MEMBER( epson_lx800_device::centronics_data_r )
+uint8_t epson_lx800_device::centronics_data_r()
{
logerror("centronics: data read\n");
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::paperempty_led_w )
-{
- logerror("setting paperout led: %d\n", state);
- machine().output().set_value("paperout_led", 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 6ee7a6af852..2d61afcc5ef 100644
--- a/src/devices/bus/centronics/epson_lx800.h
+++ b/src/devices/bus/centronics/epson_lx800.h
@@ -1,4 +1,4 @@
-// license:GPL-2.0+
+// license:BSD-3-Clause
// copyright-holders:Dirk Best
/**********************************************************************
@@ -34,36 +34,38 @@ protected:
epson_lx800_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_start() override ATTR_COLD;
+ virtual void device_reset() override ATTR_COLD;
// optional information 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 const tiny_rom_entry *device_rom_region() const override ATTR_COLD;
+ virtual void device_add_mconfig(machine_config &config) override ATTR_COLD;
+ virtual ioport_constructor device_input_ports() const override ATTR_COLD;
+
+ virtual bool supports_pin35_5v() override { return true; }
private:
- DECLARE_READ8_MEMBER(porta_r);
- DECLARE_WRITE8_MEMBER(porta_w);
- DECLARE_READ8_MEMBER(portc_r);
- DECLARE_WRITE8_MEMBER(portc_w);
+ uint8_t porta_r(offs_t offset);
+ void porta_w(offs_t offset, uint8_t data);
+ 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();
- DECLARE_READ8_MEMBER(centronics_data_r);
- DECLARE_WRITE_LINE_MEMBER(centronics_pe_w);
- DECLARE_WRITE_LINE_MEMBER(paperempty_led_w);
- DECLARE_WRITE_LINE_MEMBER(reset_w);
+ uint8_t centronics_data_r();
+ void centronics_pe_w(int state);
+ void reset_w(int state);
- void lx800_mem(address_map &map);
+ void lx800_mem(address_map &map) ATTR_COLD;
required_device<cpu_device> m_maincpu;
required_device<beep_device> m_beep;
+ output_finder<> m_online_led;
};
diff --git a/src/devices/bus/centronics/epson_lx810l.cpp b/src/devices/bus/centronics/epson_lx810l.cpp
index dd61c83baba..4670eeac49e 100644
--- a/src/devices/bus/centronics/epson_lx810l.cpp
+++ b/src/devices/bus/centronics/epson_lx810l.cpp
@@ -27,7 +27,6 @@
#include "emu.h"
#include "epson_lx810l.h"
-#include "sound/volt_reg.h"
#include "speaker.h"
//#define VERBOSE 1
@@ -36,11 +35,24 @@
//extern const char layout_lx800[]; /* use layout from lx800 */
+/* The printer starts printing at x offset 44 and stops printing at x
+ * offset 1009, giving a total of 965 printable pixels. Supposedly, the
+ * border at the far right would be at x offset 1053. I've chosen the
+ * width for the paper as 1024, since it's a nicer number than 1053, so
+ * an offset must be used to centralize the pixels.
+ */
+#define CR_OFFSET (-14)
+
+#define PAPER_WIDTH 1024 // 120 dpi * 8.5333 inches
+#define PAPER_HEIGHT (11*72) // 72 dpi * 11 inches
+
+
+
//**************************************************************************
// DEVICE DEFINITIONS
//**************************************************************************
-DEFINE_DEVICE_TYPE(EPSON_LX810L, epson_lx810l_device, "lx810l", "Espon LX-810L")
+DEFINE_DEVICE_TYPE(EPSON_LX810L, epson_lx810l_device, "lx810l", "Epson LX-810L")
DEFINE_DEVICE_TYPE(EPSON_AP2000, epson_ap2000_device, "ap2000", "Epson ActionPrinter 2000")
@@ -130,19 +142,9 @@ void epson_lx810l_device::device_add_mconfig(machine_config &config)
// config.set_default_layout(layout_lx800);
- /* video hardware (simulates paper) */
- screen_device &screen(SCREEN(config, m_screen, SCREEN_TYPE_RASTER));
- screen.set_refresh_hz(60);
- screen.set_vblank_time(ATTOSECONDS_IN_USEC(0));
- screen.set_size(PAPER_WIDTH, PAPER_HEIGHT);
- screen.set_visarea(0, PAPER_WIDTH-1, 0, PAPER_HEIGHT-1);
- screen.set_screen_update(FUNC(epson_lx810l_device::screen_update_lx810l));
-
/* audio hardware */
SPEAKER(config, "speaker").front_center();
DAC_1BIT(config, "dac", 0).add_route(ALL_OUTPUTS, "speaker", 0.25);
- voltage_regulator_device &vref(VOLTAGE_REGULATOR(config, "vref"));
- vref.add_route(0, "dac", 1.0, DAC_VREF_POS_INPUT);
/* gate array */
e05a30_device &e05a30(E05A30(config, m_e05a30, 0));
@@ -155,100 +157,106 @@ void epson_lx810l_device::device_add_mconfig(machine_config &config)
e05a30.centronics_perror().set(FUNC(epson_lx810l_device::e05a30_centronics_perror));
e05a30.centronics_fault().set(FUNC(epson_lx810l_device::e05a30_centronics_fault));
e05a30.centronics_select().set(FUNC(epson_lx810l_device::e05a30_centronics_select));
+ e05a30.cpu_reset().set(FUNC(epson_lx810l_device::e05a30_cpu_reset));
+ e05a30.ready_led().set(FUNC(epson_lx810l_device::e05a30_ready_led));
/* 256-bit eeprom */
EEPROM_93C06_16BIT(config, "eeprom");
- STEPPER(config, m_pf_stepper, (uint8_t)4);
- STEPPER(config, m_cr_stepper, (uint8_t)2);
+ BITMAP_PRINTER(config, m_bitmap_printer, PAPER_WIDTH, PAPER_HEIGHT, 120, 72); // do 72 dpi
+ m_bitmap_printer->set_pf_stepper_ratio(1,6); // pf stepper moves at 216 dpi so at 72dpi half steps
+ m_bitmap_printer->set_cr_stepper_ratio(1,1);
}
-
/***************************************************************************
INPUT PORTS
***************************************************************************/
-static INPUT_PORTS_START( epson_lx810l )
+static INPUT_PORTS_START( epson_lx810 )
/* Buttons on printer */
PORT_START("ONLINE")
- PORT_BIT(0x01, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("On Line") PORT_CODE(KEYCODE_O) PORT_CHANGED_MEMBER(DEVICE_SELF, epson_lx810l_device, online_sw, 0)
+ PORT_BIT(0x01, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("On Line") PORT_CODE(KEYCODE_0_PAD) PORT_CHANGED_MEMBER(DEVICE_SELF, FUNC(epson_lx810l_device::online_sw), 0)
PORT_START("FORMFEED")
- PORT_BIT(0x01, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("Form Feed") PORT_CODE(KEYCODE_F) PORT_TOGGLE
+ PORT_BIT(0x01, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("Form Feed") PORT_CODE(KEYCODE_7_PAD)
PORT_START("LINEFEED")
- PORT_BIT(0x01, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("Line Feed") PORT_CODE(KEYCODE_L) PORT_TOGGLE
+ PORT_BIT(0x01, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("Line Feed") PORT_CODE(KEYCODE_9_PAD)
PORT_START("LOADEJECT")
- PORT_BIT(0x01, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("Load/Eject") PORT_CODE(KEYCODE_E)
+ PORT_BIT(0x01, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("Load/Eject") PORT_CODE(KEYCODE_1_PAD)
+ PORT_START("PAPEREND")
+ PORT_BIT(0x01, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("Paper End Sensor") PORT_CODE(KEYCODE_6_PAD)
+ PORT_START("RESET")
+ PORT_BIT(0x01, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("Reset Printer") PORT_CODE(KEYCODE_2_PAD) PORT_CHANGED_MEMBER(DEVICE_SELF, FUNC(epson_lx810l_device::reset_printer), 0)
- /* DIPSW1 */
PORT_START("DIPSW1")
+ PORT_DIPNAME(0x01, 0x00, "Character spacing") PORT_DIPLOCATION("SW 1:!1")
+ PORT_DIPSETTING( 0x00, "10 cpi")
+ PORT_DIPSETTING( 0x01, "12 cpi")
+ PORT_DIPNAME(0x02, 0x00, "Shape of zero") PORT_DIPLOCATION("SW 1:!2")
+ PORT_DIPSETTING( 0x00, "Not slashed")
+ PORT_DIPSETTING( 0x02, "Slashed")
+ PORT_DIPNAME(0x04, 0x00, "Character table") PORT_DIPLOCATION("SW 1:!3")
+ PORT_DIPSETTING( 0x00, "Italics")
+ PORT_DIPSETTING( 0x04, "Graphics")
+ PORT_DIPNAME(0x08, 0x08, "Short tear-off") PORT_DIPLOCATION("SW 1:!4")
+ PORT_DIPSETTING( 0x08, DEF_STR(Off))
+ PORT_DIPSETTING( 0x00, DEF_STR(On))
+ PORT_DIPNAME(0x10, 0x00, "Draft printing speed") PORT_DIPLOCATION("SW 1:!6")
+ PORT_DIPSETTING( 0x10, DEF_STR(Normal))
+ PORT_DIPSETTING( 0x00, "High speed")
+ PORT_DIPNAME(0xe0, 0xe0, "International character set") PORT_DIPLOCATION("SW 1:!6,!7,!8")
+ PORT_DIPSETTING( 0xe0, "USA (PC 437)")
+ PORT_DIPSETTING( 0x60, "France (PC 850)")
+ PORT_DIPSETTING( 0xa0, "Germany (PC 860)")
+ PORT_DIPSETTING( 0x20, "UK (PC 863)")
+ PORT_DIPSETTING( 0xc0, "Denmark (PC 865)")
+ PORT_DIPSETTING( 0x40, "Sweden (PC 437)")
+ PORT_DIPSETTING( 0x80, "Italy (PC 437)")
+ PORT_DIPSETTING( 0x00, "Spain (PC 437)")
- PORT_DIPNAME(0x01, 0x01, "Character spacing")
- PORT_DIPLOCATION("DIP:1")
- PORT_DIPSETTING(0x01, "12 cpi") /* default */
- PORT_DIPSETTING(0x00, "10 cpi")
-
- PORT_DIPNAME(0x02, 0x00, "Shape of zero")
- PORT_DIPLOCATION("DIP:2")
- PORT_DIPSETTING(0x02, "Slashed")
- PORT_DIPSETTING(0x00, "Not slashed") /* default */
-
- PORT_DIPNAME(0x0c, 0x08, "Page length")
- PORT_DIPLOCATION("DIP:3,4")
- PORT_DIPSETTING(0x00, "11 inches")
- PORT_DIPSETTING(0x04, "12 inches")
- PORT_DIPSETTING(0x08, "8.5 inches") /* default */
- PORT_DIPSETTING(0x0c, "11.7 inches")
-
- PORT_DIPNAME(0x10, 0x10, "Character table")
- PORT_DIPLOCATION("DIP:5")
- PORT_DIPSETTING(0x10, "Graphics") /* default */
- PORT_DIPSETTING(0x00, "Italics")
-
- PORT_DIPNAME(0xe0, 0xe0, "International characters and PC selection")
- PORT_DIPLOCATION("DIP:6,7,8")
- PORT_DIPSETTING(0xe0, "United States") /* default */
- PORT_DIPSETTING(0x60, "France")
- PORT_DIPSETTING(0xa0, "Germany")
- PORT_DIPSETTING(0x20, "United Kingdom")
- PORT_DIPSETTING(0xc0, "Denmark")
- PORT_DIPSETTING(0x40, "Sweden")
- PORT_DIPSETTING(0x80, "Italy")
- PORT_DIPSETTING(0x00, "Spain")
-
- /* DIPSW2 */
PORT_START("DIPSW2")
+ PORT_DIPNAME(0x01, 0x00, "Page length") PORT_DIPLOCATION("SW 2:!1")
+ PORT_DIPSETTING( 0x00, "11\"")
+ PORT_DIPSETTING( 0x01, "12\"")
+ PORT_DIPNAME(0x02, 0x00, "Cut-sheet feeder mode") PORT_DIPLOCATION("SW 2:!2")
+ PORT_DIPSETTING( 0x00, DEF_STR(Off))
+ PORT_DIPSETTING( 0x02, DEF_STR(On))
+ PORT_DIPNAME(0x04, 0x00, "Skip over perforation") PORT_DIPLOCATION("SW 2:!3")
+ PORT_DIPSETTING( 0x00, DEF_STR(Off))
+ PORT_DIPSETTING( 0x04, "1\"")
+ PORT_DIPNAME(0x08, 0x00, "Auto line feed") PORT_DIPLOCATION("SW 2:!4")
+ PORT_DIPSETTING( 0x00, DEF_STR(Off))
+ PORT_DIPSETTING( 0x08, DEF_STR(On))
+INPUT_PORTS_END
- PORT_DIPNAME(0x01, 0x01, "Short tear-off")
- PORT_DIPLOCATION("DIP:1")
- PORT_DIPSETTING(0x01, "Invalid") /* default */
- PORT_DIPSETTING(0x00, "Valid")
-
- PORT_DIPNAME(0x02, 0x00, "Cut-sheet feeder mode")
- PORT_DIPLOCATION("DIP:2")
- PORT_DIPSETTING(0x02, "ON")
- PORT_DIPSETTING(0x00, "OFF") /* default */
-
- PORT_DIPNAME(0x04, 0x00, "Skip-over-perforation")
- PORT_DIPLOCATION("DIP:3")
- PORT_DIPSETTING(0x04, "ON")
- PORT_DIPSETTING(0x00, "OFF") /* default */
-
- PORT_DIPNAME(0x08, 0x00, "Auto line feed")
- PORT_DIPLOCATION("DIP:4")
- PORT_DIPSETTING(0x08, "ON")
- PORT_DIPSETTING(0x00, "OFF") /* default */
-
+static INPUT_PORTS_START( epson_lx810l )
+ PORT_INCLUDE(epson_lx810)
+
+ PORT_MODIFY("DIPSW1")
+ PORT_DIPNAME(0x0c, 0x00, "Page length") PORT_DIPLOCATION("SW 1:!3,!4")
+ PORT_DIPSETTING( 0x08, "8.5\"")
+ PORT_DIPSETTING( 0x00, "11\"")
+ PORT_DIPSETTING( 0x0c, "11.7\" (A4)")
+ PORT_DIPSETTING( 0x04, "12\"")
+ PORT_DIPNAME(0x10, 0x00, "Character table") PORT_DIPLOCATION("SW 1:!5")
+ PORT_DIPSETTING( 0x00, "Italics")
+ PORT_DIPSETTING( 0x10, "Graphics")
+
+ PORT_MODIFY("DIPSW2")
+ PORT_DIPNAME(0x01, 0x01, "Short tear-off") PORT_DIPLOCATION("SW 2:!1")
+ PORT_DIPSETTING( 0x01, "Invalid")
+ PORT_DIPSETTING( 0x00, "Valid")
INPUT_PORTS_END
+
//-------------------------------------------------
// input_ports - device-specific input ports
//-------------------------------------------------
ioport_constructor epson_lx810l_device::device_input_ports() const
{
- return INPUT_PORTS_NAME( epson_lx810l );
+ return INPUT_PORTS_NAME(epson_lx810l);
}
INPUT_CHANGED_MEMBER(epson_lx810l_device::online_sw)
@@ -256,6 +264,17 @@ INPUT_CHANGED_MEMBER(epson_lx810l_device::online_sw)
m_maincpu->set_input_line(UPD7810_INTF2, newval ? CLEAR_LINE : ASSERT_LINE);
}
+INPUT_CHANGED_MEMBER(epson_lx810l_device::reset_printer)
+{
+ if (newval)
+ {
+ m_maincpu->pulse_input_line(INPUT_LINE_RESET, attotime::zero); // reset cpu
+ m_e05a30->reset(); // this will generate an NMI interrupt when the e05a30 is ready (minimum 0.9 seconds after reset)
+ }
+}
+
+
+
//**************************************************************************
// LIVE DEVICE
@@ -274,19 +293,25 @@ epson_lx810l_device::epson_lx810l_device(const machine_config &mconfig, device_t
device_t(mconfig, type, tag, owner, clock),
device_centronics_peripheral_interface(mconfig, *this),
m_maincpu(*this, "maincpu"),
- m_pf_stepper(*this, "pf_stepper"),
- m_cr_stepper(*this, "cr_stepper"),
+ m_bitmap_printer(*this, "bitmap_printer"),
m_eeprom(*this, "eeprom"),
m_e05a30(*this, "e05a30"),
- m_screen(*this, "screen"),
+ m_online_led(*this, "online_led"),
+ m_ready_led(*this, "ready_led"),
+ m_online_ioport(*this, "ONLINE"),
+ m_formfeed_ioport(*this, "FORMFEED"),
+ m_linefeed_ioport(*this, "LINEFEED"),
+ m_loadeject_ioport(*this, "LOADEJECT"),
+ m_paperend_ioport(*this, "PAPEREND"),
+ m_dipsw1_ioport(*this, "DIPSW1"),
+ m_dipsw2_ioport(*this, "DIPSW2"),
m_93c06_clk(0),
m_93c06_cs(0),
m_printhead(0),
- m_pf_pos_abs(1),
- m_cr_pos_abs(1),
- m_real_cr_pos(1),
m_real_cr_steps(0),
- m_real_cr_dir(0), m_fakemem(0)
+ m_fakemem(0),
+ m_in_between_offset(0),
+ m_rightward_offset(-3)
{
}
@@ -299,15 +324,12 @@ epson_ap2000_device::epson_ap2000_device(const machine_config &mconfig, const ch
// device_start - device-specific startup
//-------------------------------------------------
-
-
-
void epson_lx810l_device::device_start()
{
- m_cr_timer = timer_alloc(TIMER_CR);
+ m_online_led.resolve();
+ m_ready_led.resolve();
- m_screen->register_screen_bitmap(m_bitmap);
- m_bitmap.fill(0xffffff); /* Start with a clean white piece of paper */
+ m_cr_timer = timer_alloc(FUNC(epson_lx810l_device::cr_tick), this);
}
@@ -317,29 +339,27 @@ void epson_lx810l_device::device_start()
void epson_lx810l_device::device_reset()
{
+ m_in_between_offset = 0;
}
//-------------------------------------------------
-// device_timer - device-specific timer
+// cr_tick - handle a carriage return
//-------------------------------------------------
-void epson_lx810l_device::device_timer(emu_timer &timer, device_timer_id id, int param, void *ptr)
+TIMER_CALLBACK_MEMBER(epson_lx810l_device::cr_tick)
{
- switch (id) {
- case TIMER_CR:
- /* The firmware issues two half-steps in sequence, one immediately
- * after the other. At full speed, the motor does two half-steps at
- * each 833 microseconds. A timer fires the printhead twice, with
- * the same period as each half-step (417 microseconds), but with
- * a 356 microseconds delay relative to the motor steps.
- */
- m_real_cr_pos += param;
- m_real_cr_steps--;
- if (m_real_cr_steps)
- m_cr_timer->adjust(attotime::from_usec(400), m_real_cr_dir);
- break;
- }
+ /* The firmware issues two half-steps in sequence, one immediately
+ * after the other. At full speed, the motor does two half-steps at
+ * each 833 microseconds. A timer fires the printhead twice, with
+ * the same period as each half-step (417 microseconds), but with
+ * a 356 microseconds delay relative to the motor steps.
+ */
+ m_in_between_offset += param;
+
+ m_real_cr_steps--;
+ if (m_real_cr_steps)
+ m_cr_timer->adjust(attotime::from_usec(400), m_bitmap_printer->m_cr_direction);
}
@@ -347,12 +367,12 @@ void epson_lx810l_device::device_timer(emu_timer &timer, device_timer_id id, int
FAKEMEM READ/WRITE
***************************************************************************/
-READ8_MEMBER(epson_lx810l_device::fakemem_r)
+uint8_t epson_lx810l_device::fakemem_r()
{
return m_fakemem;
}
-WRITE8_MEMBER(epson_lx810l_device::fakemem_w)
+void epson_lx810l_device::fakemem_w(uint8_t data)
{
m_fakemem = data;
}
@@ -372,23 +392,27 @@ WRITE8_MEMBER(epson_lx810l_device::fakemem_w)
* PA6 R Line Feed SWITCH
* PA7 R Form Feed SWITCH
*/
-READ8_MEMBER( epson_lx810l_device::porta_r )
+uint8_t epson_lx810l_device::porta_r(offs_t offset)
{
uint8_t result = 0;
- uint8_t hp_sensor = m_cr_pos_abs <= 0 ? 0 : 1;
- uint8_t pe_sensor = m_pf_pos_abs <= 0 ? 1 : 0;
+ uint8_t hp_sensor = (m_bitmap_printer->m_xpos <= 0) ? 0 : 1;
+
+ //uint8_t pe_sensor = m_pf_pos_abs <= 0 ? 1 : 0;
result |= hp_sensor; /* home position */
- result |= pe_sensor << 1; /* paper end */
- result |= ioport("LINEFEED")->read() << 6;
- result |= ioport("FORMFEED")->read() << 7;
+ //result |= pe_sensor << 1; /* paper end */
+ result |= m_paperend_ioport->read() << 1; // simulate a paper out error
+ result |= m_linefeed_ioport->read() << 6;
+ result |= m_formfeed_ioport->read() << 7;
LOG("%s: lx810l_PA_r(%02x): result %02x\n", machine().describe_context(), offset, result);
+ m_bitmap_printer->set_led_state(bitmap_printer_device::LED_ERROR, !m_paperend_ioport->read());
+
return result;
}
-WRITE8_MEMBER( epson_lx810l_device::porta_w )
+void epson_lx810l_device::porta_w(offs_t offset, uint8_t data)
{
LOG("%s: lx810l_PA_w(%02x): %02x: stepper vref %d\n", machine().describe_context(), offset, data, BIT(data, 3) | (BIT(data, 4)<<1) | (BIT(data, 5)<<2));
}
@@ -403,9 +427,9 @@ WRITE8_MEMBER( epson_lx810l_device::porta_w )
* PB6 R DIP1.6
* PB7 R DIP1.7
*/
-READ8_MEMBER( epson_lx810l_device::portb_r )
+uint8_t epson_lx810l_device::portb_r(offs_t offset)
{
- uint8_t result = ~ioport("DIPSW1")->read();
+ uint8_t result = ~m_dipsw1_ioport->read();
/* if 93C06 is selected */
if (m_93c06_cs) {
@@ -419,7 +443,7 @@ READ8_MEMBER( epson_lx810l_device::portb_r )
return result;
}
-WRITE8_MEMBER( epson_lx810l_device::portb_w )
+void epson_lx810l_device::portb_w(offs_t offset, uint8_t data)
{
uint8_t data_in = BIT(data, 1);
@@ -440,12 +464,12 @@ WRITE8_MEMBER( epson_lx810l_device::portb_w )
* PC6 W FIRE drive pulse width signal, also E05A30.57
* PC7 W BUZZER buzzer signal
*/
-READ8_MEMBER( epson_lx810l_device::portc_r )
+uint8_t epson_lx810l_device::portc_r(offs_t offset)
{
uint8_t result = 0;
/* result |= ioport("serial")->read() << 1; */
- result |= !ioport("ONLINE")->read() << 3;
+ result |= !m_online_ioport->read() << 3;
result |= m_93c06_clk << 4;
result |= m_93c06_cs << 5;
@@ -454,7 +478,7 @@ READ8_MEMBER( epson_lx810l_device::portc_r )
return result;
}
-WRITE8_MEMBER( epson_lx810l_device::portc_w )
+void epson_lx810l_device::portc_w(offs_t offset, uint8_t data)
{
/* ioport("serial")->write(BIT(data, 0)); */
@@ -466,7 +490,8 @@ WRITE8_MEMBER( epson_lx810l_device::portc_w )
m_eeprom->clk_write(m_93c06_clk ? ASSERT_LINE : CLEAR_LINE);
m_eeprom->cs_write (m_93c06_cs ? ASSERT_LINE : CLEAR_LINE);
- machine().output().set_value("online_led", !BIT(data, 2));
+ m_online_led = !BIT(data, 2);
+ m_bitmap_printer->set_led_state(bitmap_printer_device::LED_ONLINE, m_online_led);
}
@@ -474,66 +499,33 @@ WRITE8_MEMBER( epson_lx810l_device::portc_w )
GATE ARRAY
***************************************************************************/
-WRITE16_MEMBER( epson_lx810l_device::printhead )
+void epson_lx810l_device::printhead(uint16_t data)
{
m_printhead = data;
}
-WRITE8_MEMBER( epson_lx810l_device::pf_stepper )
+void epson_lx810l_device::pf_stepper(uint8_t data)
{
- int changed = m_pf_stepper->update(data);
- m_pf_pos_abs = -m_pf_stepper->get_absolute_position();
-
- /* clear last line of paper */
- if (changed > 0) {
- void *line = m_bitmap.raw_pixptr(bitmap_line(9), 0);
- memset(line, 0xff, m_bitmap.width() * 4);
- }
-
- LOG("%s: %s(%02x); abs %d\n", machine().describe_context(), __func__, data, m_pf_pos_abs);
+ m_bitmap_printer->update_pf_stepper(data);
}
-WRITE8_MEMBER( epson_lx810l_device::cr_stepper )
+void epson_lx810l_device::cr_stepper(uint8_t data)
{
- int m_cr_pos_abs_prev = m_cr_pos_abs;
+ m_bitmap_printer->update_cr_stepper(bitswap<4>(data, 0, 1, 2, 3)); // reverse bits
- m_cr_stepper->update(data);
- m_cr_pos_abs = -m_cr_stepper->get_absolute_position();
-
- if (m_cr_pos_abs > m_cr_pos_abs_prev) {
- /* going right */
- m_real_cr_dir = 1;
- } else {
- /* going left */
- m_real_cr_dir = -1;
- }
+ m_in_between_offset = 0;
if (!m_real_cr_steps)
- m_cr_timer->adjust(attotime::from_usec(400), m_real_cr_dir);
- m_real_cr_steps++;
-
- LOG("%s: %s(%02x); abs %d\n", machine().describe_context(), __func__, data, m_cr_pos_abs);
+ {
+ m_cr_timer->adjust(attotime::from_usec(400), m_bitmap_printer->m_cr_direction);
+ m_real_cr_steps++;
+ }
}
-WRITE_LINE_MEMBER( epson_lx810l_device::e05a30_ready )
+void epson_lx810l_device::e05a30_ready(int state)
{
- m_maincpu->pulse_input_line(INPUT_LINE_NMI, attotime::zero);
-}
-
-
-/***************************************************************************
- Video hardware (simulates paper)
-***************************************************************************/
-
-uint32_t epson_lx810l_device::screen_update_lx810l(screen_device &screen, bitmap_rgb32 &bitmap, const rectangle &cliprect)
-{
- int scrolly = -bitmap_line(9);
- copyscrollbitmap(bitmap, m_bitmap, 0, nullptr, 1, &scrolly, cliprect);
-
- /* draw "printhead" */
- bitmap.plot_box(m_real_cr_pos + CR_OFFSET - 10, PAPER_HEIGHT - 36, 20, 36, 0x888888);
-
- return 0;
+ // 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));
}
@@ -541,7 +533,7 @@ uint32_t epson_lx810l_device::screen_update_lx810l(screen_device &screen, bitmap
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) {
@@ -556,12 +548,12 @@ WRITE_LINE_MEMBER( epson_lx810l_device::co0_w )
* lines which are being printed in different directions is
* noticeably off in the 20+ years old printer used for testing =).
*/
- if (m_real_cr_pos < m_bitmap.width()) {
- for (int i = 0; i < 9; i++) {
- unsigned int y = bitmap_line(i);
- if ((m_printhead & (1<<(8-i))) != 0)
- m_bitmap.pix32(y, m_real_cr_pos + CR_OFFSET) = 0x000000;
- }
+ for (int i = 0; i < 9; i++)
+ {
+ if ((m_printhead & (1<<(8-i))) != 0)
+ m_bitmap_printer->pix(m_bitmap_printer->m_ypos + i * 1, // * 1 for no interleave at 72 vdpi
+ m_bitmap_printer->m_xpos + CR_OFFSET + m_in_between_offset +
+ (m_bitmap_printer->m_cr_direction > 0 ? m_rightward_offset : 0)) = 0x000000;
}
}
}
@@ -571,47 +563,47 @@ WRITE_LINE_MEMBER( epson_lx810l_device::co0_w )
ADC
***************************************************************************/
-READ8_MEMBER(epson_lx810l_device::an0_r)
+uint8_t epson_lx810l_device::an0_r()
{
- uint8_t res = !!(ioport("DIPSW2")->read() & 0x01);
+ uint8_t res = !!(m_dipsw2_ioport->read() & 0x01);
return res - 1; /* DIPSW2.1 */
}
-READ8_MEMBER(epson_lx810l_device::an1_r)
+uint8_t epson_lx810l_device::an1_r()
{
- uint8_t res = !!(ioport("DIPSW2")->read() & 0x02);
+ uint8_t res = !!(m_dipsw2_ioport->read() & 0x02);
return res - 1; /* DIPSW2.2 */
}
-READ8_MEMBER(epson_lx810l_device::an2_r)
+uint8_t epson_lx810l_device::an2_r()
{
- uint8_t res = !!(ioport("DIPSW2")->read() & 0x04);
+ uint8_t res = !!(m_dipsw2_ioport->read() & 0x04);
return res - 1; /* DIPSW2.3 */
}
-READ8_MEMBER(epson_lx810l_device::an3_r)
+uint8_t epson_lx810l_device::an3_r()
{
- uint8_t res = !!(ioport("DIPSW2")->read() & 0x08);
+ uint8_t res = !!(m_dipsw2_ioport->read() & 0x08);
return res - 1; /* DIPSW2.4 */
}
-READ8_MEMBER(epson_lx810l_device::an4_r)
+uint8_t epson_lx810l_device::an4_r()
{
return 0xff;
}
-READ8_MEMBER(epson_lx810l_device::an5_r)
+uint8_t epson_lx810l_device::an5_r()
{
return 0xCB; /* motor voltage, 0xcb = 24V */
}
-READ8_MEMBER(epson_lx810l_device::an6_r)
+uint8_t epson_lx810l_device::an6_r()
{
- uint8_t res = !ioport("LOADEJECT")->read();
+ uint8_t res = !m_loadeject_ioport->read();
return res - 1;
}
-READ8_MEMBER(epson_lx810l_device::an7_r)
+uint8_t epson_lx810l_device::an7_r()
{
return 0xff;
}
diff --git a/src/devices/bus/centronics/epson_lx810l.h b/src/devices/bus/centronics/epson_lx810l.h
index 82a493273d1..adf5f1af672 100644
--- a/src/devices/bus/centronics/epson_lx810l.h
+++ b/src/devices/bus/centronics/epson_lx810l.h
@@ -4,7 +4,6 @@
* Epson LX-810L dot matrix printer emulation
*
*/
-
#ifndef MAME_BUS_CENTRONICS_EPSON_LX810L_H
#define MAME_BUS_CENTRONICS_EPSON_LX810L_H
@@ -14,20 +13,13 @@
#include "cpu/upd7810/upd7810.h"
#include "machine/e05a30.h"
#include "machine/eepromser.h"
+#include "machine/bitmap_printer.h"
#include "machine/steppers.h"
#include "sound/dac.h"
#include "screen.h"
+#include <cstdlib>
-/* The printer starts printing at x offset 44 and stops printing at x
- * offset 1009, giving a total of 965 printable pixels. Supposedly, the
- * border at the far right would be at x offset 1053. I've chosen the
- * width for the paper as 1024, since it's a nicer number than 1053, so
- * an offset must be used to centralize the pixels.
- */
-#define CR_OFFSET (-14)
-#define PAPER_WIDTH 1024
-#define PAPER_HEIGHT 576
//**************************************************************************
// TYPE DEFINITIONS
@@ -42,95 +34,110 @@ 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 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);
+ /* Reset Printer (equivalent to turning power off and back on) */
+ DECLARE_INPUT_CHANGED_MEMBER(reset_printer);
+
protected:
epson_lx810l_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_timer(emu_timer &timer, device_timer_id id, int param, void *ptr) override;
+ virtual void device_start() override ATTR_COLD;
+ virtual void device_reset() override ATTR_COLD;
// optional information 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 const tiny_rom_entry *device_rom_region() const override ATTR_COLD;
+ virtual void device_add_mconfig(machine_config &config) override ATTR_COLD;
+ virtual ioport_constructor device_input_ports() const override ATTR_COLD;
+
+ virtual bool supports_pin35_5v() override { return true; }
private:
- DECLARE_READ8_MEMBER(porta_r);
- DECLARE_WRITE8_MEMBER(porta_w);
- DECLARE_READ8_MEMBER(portb_r);
- DECLARE_WRITE8_MEMBER(portb_w);
- DECLARE_READ8_MEMBER(portc_r);
- DECLARE_WRITE8_MEMBER(portc_w);
+ uint8_t porta_r(offs_t offset);
+ void porta_w(offs_t offset, uint8_t data);
+ uint8_t portb_r(offs_t offset);
+ void portb_w(offs_t offset, uint8_t data);
+ uint8_t portc_r(offs_t offset);
+ void portc_w(offs_t offset, uint8_t data);
+
+ TIMER_CALLBACK_MEMBER(cr_tick);
/* fake memory I/O to get past memory reset check */
- DECLARE_READ8_MEMBER(fakemem_r);
- DECLARE_WRITE8_MEMBER(fakemem_w);
+ uint8_t fakemem_r();
+ void fakemem_w(uint8_t data);
/* Extended Timer Output */
- DECLARE_WRITE_LINE_MEMBER(co0_w);
+ void co0_w(int state);
/* ADC */
- DECLARE_READ8_MEMBER(an0_r);
- DECLARE_READ8_MEMBER(an1_r);
- DECLARE_READ8_MEMBER(an2_r);
- DECLARE_READ8_MEMBER(an3_r);
- DECLARE_READ8_MEMBER(an4_r);
- DECLARE_READ8_MEMBER(an5_r);
- DECLARE_READ8_MEMBER(an6_r);
- DECLARE_READ8_MEMBER(an7_r);
+ uint8_t an0_r();
+ uint8_t an1_r();
+ uint8_t an2_r();
+ uint8_t an3_r();
+ uint8_t an4_r();
+ uint8_t an5_r();
+ uint8_t an6_r();
+ uint8_t an7_r();
/* GATE ARRAY */
- DECLARE_WRITE16_MEMBER(printhead);
- DECLARE_WRITE8_MEMBER(pf_stepper);
- DECLARE_WRITE8_MEMBER(cr_stepper);
- DECLARE_WRITE_LINE_MEMBER(e05a30_ready);
+ void printhead(uint16_t data);
+ void pf_stepper(uint8_t data);
+ void cr_stepper(uint8_t data);
+ 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); }
- void lx810l_mem(address_map &map);
+ void e05a30_cpu_reset(int state) { if (!state) m_maincpu->pulse_input_line(INPUT_LINE_RESET, attotime::zero); } // reset cpu
- /* Video hardware (simulates paper) */
- uint32_t screen_update_lx810l(screen_device &screen, bitmap_rgb32 &bitmap, const rectangle &cliprect);
+ void e05a30_ready_led(int state)
+ {
+ m_ready_led = state;
+ m_bitmap_printer->set_led_state(bitmap_printer_device::LED_READY, m_ready_led);
+ }
-#define uabs(x) ((x) > 0 ? (x) : -(x))
- unsigned int bitmap_line(int i) { return ((uabs(m_pf_pos_abs) / 6) + i) % m_bitmap.height(); }
+ void lx810l_mem(address_map &map) ATTR_COLD;
required_device<cpu_device> m_maincpu;
- required_device<stepper_device> m_pf_stepper;
- required_device<stepper_device> m_cr_stepper;
+ required_device<bitmap_printer_device> m_bitmap_printer;
required_device<eeprom_serial_93cxx_device> m_eeprom;
required_device<e05a30_device> m_e05a30;
- required_device<screen_device> m_screen;
+
+ output_finder<> m_online_led;
+ output_finder<> m_ready_led;
+
+ required_ioport m_online_ioport;
+ required_ioport m_formfeed_ioport;
+ required_ioport m_linefeed_ioport;
+ required_ioport m_loadeject_ioport;
+ required_ioport m_paperend_ioport;
+ required_ioport m_dipsw1_ioport;
+ required_ioport m_dipsw2_ioport;
int m_93c06_clk;
int m_93c06_cs;
uint16_t m_printhead;
- int m_pf_pos_abs;
- int m_cr_pos_abs;
- int m_real_cr_pos;
int m_real_cr_steps;
- int m_real_cr_dir; /* 1 is going right, -1 is going left */
uint8_t m_fakemem;
- bitmap_rgb32 m_bitmap;
+ int m_in_between_offset; // in between cr_stepper phases
+ int m_rightward_offset; // offset pixels when stepper moving rightward
enum {
TIMER_CR
@@ -145,11 +152,11 @@ class epson_ap2000_device : public epson_lx810l_device
{
public:
// construction/destruction
- epson_ap2000_device(const machine_config &mconfig, const char *tag,
- device_t *owner, uint32_t clock);
+ epson_ap2000_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
+protected:
// optional information overrides
- virtual const tiny_rom_entry *device_rom_region() const override;
+ virtual const tiny_rom_entry *device_rom_region() const override ATTR_COLD;
};
diff --git a/src/devices/bus/centronics/epson_rx80.cpp b/src/devices/bus/centronics/epson_rx80.cpp
new file mode 100644
index 00000000000..0dd75a00a04
--- /dev/null
+++ b/src/devices/bus/centronics/epson_rx80.cpp
@@ -0,0 +1,171 @@
+// license:BSD-3-Clause
+// copyright-holders:Golden Child
+/***************************************************************************
+
+ Epson RX-80 Dot Matrix printer (skeleton)
+
+ Main CPU is a UPD7810 running at 11 MHz.
+ 8K of mask ROM (marked EPSON M64200CA)
+ uses 256 bytes of ram inside upd7810, no external ram chips
+ has a limited line buffer of 137 bytes maximum from ff00 to ff88,
+ used for character buffer as well as during graphic print operation.
+ 137 bytes is approximate maximum line length during condensed print.
+
+*****************************************************************************/
+
+#include "emu.h"
+#include "epson_rx80.h"
+
+#include "cpu/upd7810/upd7810.h"
+
+
+namespace {
+
+//**************************************************************************
+// TYPE DEFINITIONS
+//**************************************************************************
+
+class epson_rx80_device : public device_t, public device_centronics_peripheral_interface
+{
+public:
+ // construction/destruction
+ epson_rx80_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
+
+ static constexpr feature_type unemulated_features() { return feature::PRINTER; }
+
+ /* Centronics stuff */
+ virtual void input_init(int state) override;
+ virtual void input_strobe(int state) override;
+ virtual void input_data0(int state) override { if (state) m_centronics_data |= 0x01; else m_centronics_data &= ~0x01; }
+ virtual void input_data1(int state) override { if (state) m_centronics_data |= 0x02; else m_centronics_data &= ~0x02; }
+ virtual void input_data2(int state) override { if (state) m_centronics_data |= 0x04; else m_centronics_data &= ~0x04; }
+ virtual void input_data3(int state) override { if (state) m_centronics_data |= 0x08; else m_centronics_data &= ~0x08; }
+ virtual void input_data4(int state) override { if (state) m_centronics_data |= 0x10; else m_centronics_data &= ~0x10; }
+ virtual void input_data5(int state) override { if (state) m_centronics_data |= 0x20; else m_centronics_data &= ~0x20; }
+ virtual void input_data6(int state) override { if (state) m_centronics_data |= 0x40; else m_centronics_data &= ~0x40; }
+ virtual void input_data7(int state) override { if (state) m_centronics_data |= 0x80; else m_centronics_data &= ~0x80; }
+
+protected:
+ virtual void device_start() override ATTR_COLD;
+ virtual void device_reset() override ATTR_COLD;
+
+ virtual const tiny_rom_entry *device_rom_region() const override ATTR_COLD;
+ virtual void device_add_mconfig(machine_config &config) override ATTR_COLD;
+ virtual ioport_constructor device_input_ports() const override ATTR_COLD;
+
+ virtual bool supports_pin35_5v() override { return true; }
+
+private:
+ uint8_t centronics_data_r(offs_t offset) { return m_centronics_data; };
+
+ void epson_rx80_mem(address_map &map) ATTR_COLD;
+
+ required_device<upd7810_device> m_maincpu;
+
+ uint8_t m_centronics_data;
+};
+
+//-------------------------------------------------
+// ROM( epson_rx80 )
+//-------------------------------------------------
+
+ROM_START( epson_rx80 )
+ ROM_REGION(0x2000, "maincpu", 0) // 8K rom for upd7810
+ ROM_LOAD("rx80_2764.bin", 0x0000, 0x2000, CRC(5206104a) SHA1(3e304f5331181aedb321d3db23a9387e3cfacf0c))
+ROM_END
+
+
+//-------------------------------------------------
+// rom_region - device-specific ROM region
+//-------------------------------------------------
+
+const tiny_rom_entry *epson_rx80_device::device_rom_region() const
+{
+ return ROM_NAME( epson_rx80 );
+}
+
+
+//-------------------------------------------------
+// ADDRESS_MAP( epson_rx80_mem )
+//-------------------------------------------------
+
+void epson_rx80_device::epson_rx80_mem(address_map &map)
+{
+ map(0x0000, 0x1fff).rom().region("maincpu", 0);
+ map(0xd800, 0xd800).r(FUNC(epson_rx80_device::centronics_data_r));
+}
+
+
+//-------------------------------------------------
+// device_add_mconfig - add device configuration
+//-------------------------------------------------
+
+void epson_rx80_device::device_add_mconfig(machine_config &config)
+{
+ upd7810_device &upd(UPD7810(config, m_maincpu, 11000000)); // 11 Mhz
+ upd.set_addrmap(AS_PROGRAM, &epson_rx80_device::epson_rx80_mem);
+
+}
+
+
+//-------------------------------------------------
+// INPUT_PORTS( epson_rx80 )
+//-------------------------------------------------
+
+INPUT_PORTS_START( epson_rx80 )
+INPUT_PORTS_END
+
+
+//-------------------------------------------------
+// input_ports - device-specific input ports
+//-------------------------------------------------
+
+ioport_constructor epson_rx80_device::device_input_ports() const
+{
+ return INPUT_PORTS_NAME( epson_rx80 );
+}
+
+
+//-------------------------------------------------
+// epson_rx80_device - constructor
+//-------------------------------------------------
+
+epson_rx80_device::epson_rx80_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) :
+ device_t(mconfig, EPSON_RX80, tag, owner, clock),
+ device_centronics_peripheral_interface(mconfig, *this),
+ m_maincpu(*this, "maincpu")
+{
+}
+
+//-------------------------------------------------
+// device_start - device-specific startup
+//-------------------------------------------------
+
+void epson_rx80_device::device_start()
+{
+}
+
+//-------------------------------------------------
+// device_reset - device-specific reset
+//-------------------------------------------------
+
+void epson_rx80_device::device_reset()
+{
+}
+
+/***************************************************************************
+ Centronics
+***************************************************************************/
+
+void epson_rx80_device::input_strobe(int state)
+{
+}
+
+void epson_rx80_device::input_init(int state)
+{
+}
+
+} // anonymous namespace
+
+// GLOBAL
+DEFINE_DEVICE_TYPE_PRIVATE(EPSON_RX80, device_centronics_peripheral_interface, epson_rx80_device, "epson_rx80", "Epson RX-80")
diff --git a/src/devices/bus/centronics/epson_rx80.h b/src/devices/bus/centronics/epson_rx80.h
new file mode 100644
index 00000000000..c47668a2934
--- /dev/null
+++ b/src/devices/bus/centronics/epson_rx80.h
@@ -0,0 +1,19 @@
+// license:BSD-3-Clause
+// copyright-holders:Golden Child
+/**********************************************************************
+
+ Epson RX-80 dot matrix printer emulation (skeleton)
+
+**********************************************************************/
+
+#ifndef MAME_BUS_CENTRONICS_EPSON_RX80_H
+#define MAME_BUS_CENTRONICS_EPSON_RX80_H
+
+#pragma once
+
+#include "ctronics.h"
+
+// device type declaration
+DECLARE_DEVICE_TYPE(EPSON_RX80, device_centronics_peripheral_interface)
+
+#endif // MAME_BUS_CENTRONICS_EPSON_RX80_H
diff --git a/src/devices/bus/centronics/nec_p72.cpp b/src/devices/bus/centronics/nec_p72.cpp
index c3a9ddd2ab2..fe03bb93d34 100644
--- a/src/devices/bus/centronics/nec_p72.cpp
+++ b/src/devices/bus/centronics/nec_p72.cpp
@@ -39,7 +39,7 @@ const tiny_rom_entry *nec_p72_device::device_rom_region() const
void nec_p72_device::p72_mem(address_map &map)
{
map(0x000000, 0x0fffff).rom(); /* 1Mbyte firmware */
- //AM_RANGE(0x100000, 0x1fffff) AM_RAM /* 1Mbyte external RAM */ /* TODO might be 2x1Mbit */
+ //map(0x100000, 0x1fffff).ram(); /* 1Mbyte external RAM */ /* TODO might be 2x1Mbit */
// [RH] 29 August 2016: Commented out because the NEC V33 only has 20 address lines, and
// the V40 has more, but we don't have an NEC V40 implemented yet.
}
diff --git a/src/devices/bus/centronics/nec_p72.h b/src/devices/bus/centronics/nec_p72.h
index f7ba6d59a73..7fe4aa23114 100644
--- a/src/devices/bus/centronics/nec_p72.h
+++ b/src/devices/bus/centronics/nec_p72.h
@@ -26,16 +26,16 @@ protected:
nec_p72_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_start() override ATTR_COLD;
// optional information overrides
- virtual const tiny_rom_entry *device_rom_region() const override;
- virtual void device_add_mconfig(machine_config &config) override;
+ virtual const tiny_rom_entry *device_rom_region() const override ATTR_COLD;
+ virtual void device_add_mconfig(machine_config &config) override ATTR_COLD;
private:
required_device<cpu_device> m_maincpu;
- void p72_mem(address_map &map);
+ void p72_mem(address_map &map) ATTR_COLD;
};
// device type definition
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..19d6e088e07
--- /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 ATTR_COLD;
+ virtual void device_add_mconfig(machine_config &config) override ATTR_COLD;
+ virtual ioport_constructor device_input_ports() const override ATTR_COLD;
+ virtual const tiny_rom_entry *device_rom_region() const override ATTR_COLD;
+
+ // 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) ATTR_COLD;
+
+ 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 484e718d074..25deb42cdd1 100644
--- a/src/devices/bus/centronics/printer.cpp
+++ b/src/devices/bus/centronics/printer.cpp
@@ -27,79 +27,88 @@ centronics_printer_device::centronics_printer_device(const machine_config &mconf
m_printer(*this, "printer")
{
}
+
//-------------------------------------------------
// device_add_mconfig - add device configuration
//-------------------------------------------------
-
void centronics_printer_device::device_add_mconfig(machine_config &config)
{
PRINTER(config, m_printer, 0);
m_printer->online_callback().set(FUNC(centronics_printer_device::printer_online));
}
+void centronics_printer_device::device_start()
+{
+ m_ack_timer = timer_alloc(FUNC(centronics_printer_device::ack_timer_tick), this);
+ m_busy_timer = timer_alloc(FUNC(centronics_printer_device::busy_timer_tick), this);
+
+ /* register for state saving */
+ save_item(NAME(m_strobe));
+ save_item(NAME(m_data));
+ save_item(NAME(m_busy));
+}
+
+void centronics_printer_device::device_reset()
+{
+ m_busy = false;
+ output_busy(m_busy);
+ output_fault(1);
+ output_ack(1);
+ output_select(1);
+}
+
+
+
/*-------------------------------------------------
printer_online - callback that
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);
}
-void centronics_printer_device::device_timer(emu_timer &timer, device_timer_id id, int param, void *ptr)
+/*-------------------------------------------------
+ ack_timer_tick - update the printer
+ acknowledge line after an appropriate delay
+-------------------------------------------------*/
+
+TIMER_CALLBACK_MEMBER(centronics_printer_device::ack_timer_tick)
{
- switch (id)
+ output_ack(param);
+
+ if (!param)
{
- case TIMER_ACK:
- output_ack(param);
-
- if (param == false)
- {
- /* data is now ready, output it */
- m_printer->output(m_data);
-
- /* ready to receive more data, return BUSY to low */
- m_busy_timer->adjust(attotime::from_usec(7), false);
- }
- break;
-
- case TIMER_BUSY:
- m_busy = param;
- output_busy(m_busy);
-
- if (param == true)
- {
- /* timer to turn ACK low to receive data */
- m_ack_timer->adjust(attotime::from_usec(10), false);
- }
- else
- {
- /* timer to return ACK to high state */
- m_ack_timer->adjust(attotime::from_usec(5), true);
- }
+ /* data is now ready, output it */
+ m_printer->output(m_data);
+
+ /* ready to receive more data, return BUSY to low */
+ m_busy_timer->adjust(attotime::from_usec(7), 0);
}
}
-void centronics_printer_device::device_start()
-{
- m_ack_timer = timer_alloc(TIMER_ACK);
- m_busy_timer = timer_alloc(TIMER_BUSY);
-
- /* register for state saving */
- save_item(NAME(m_strobe));
- save_item(NAME(m_data));
- save_item(NAME(m_busy));
-}
+/*-------------------------------------------------
+ busy_timer_tick - update the printer's
+ busy state
+-------------------------------------------------*/
-void centronics_printer_device::device_reset()
+TIMER_CALLBACK_MEMBER(centronics_printer_device::busy_timer_tick)
{
- m_busy = false;
+ m_busy = param;
output_busy(m_busy);
- output_fault(1);
- output_ack(1);
- output_select(1);
+
+ if (param)
+ {
+ /* timer to turn ACK low to receive data */
+ m_ack_timer->adjust(attotime::from_usec(10), 0);
+ }
+ else
+ {
+ /* timer to return ACK to high state */
+ m_ack_timer->adjust(attotime::from_usec(5), 1);
+ }
}
/*-------------------------------------------------
@@ -107,7 +116,7 @@ void centronics_printer_device::device_reset()
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)
@@ -125,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 8e564ff5df9..5a346fdc640 100644
--- a/src/devices/bus/centronics/printer.h
+++ b/src/devices/bus/centronics/printer.h
@@ -17,32 +17,30 @@ 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
- virtual void device_add_mconfig(machine_config &config) override;
- virtual void device_start() override;
- virtual void device_reset() override;
- virtual void device_timer(emu_timer &timer, device_timer_id id, int param, void *ptr) override;
+ 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;
+
+ virtual bool supports_pin35_5v() override { return true; }
private:
- DECLARE_WRITE_LINE_MEMBER( printer_online );
+ void printer_online(int state);
- enum
- {
- TIMER_ACK,
- TIMER_BUSY
- };
+ TIMER_CALLBACK_MEMBER(ack_timer_tick);
+ TIMER_CALLBACK_MEMBER(busy_timer_tick);
emu_timer *m_ack_timer;
emu_timer *m_busy_timer;
diff --git a/src/devices/bus/centronics/samdac.cpp b/src/devices/bus/centronics/samdac.cpp
new file mode 100644
index 00000000000..90afc8e8a7c
--- /dev/null
+++ b/src/devices/bus/centronics/samdac.cpp
@@ -0,0 +1,91 @@
+// license: BSD-3-Clause
+// copyright-holders: Dirk Best
+/***************************************************************************
+
+ SAMDAC Stereo DAC for SAM Coupe
+
+***************************************************************************/
+
+#include "emu.h"
+#include "samdac.h"
+#include "speaker.h"
+
+
+//**************************************************************************
+// DEVICE DEFINITIONS
+//**************************************************************************
+
+DEFINE_DEVICE_TYPE(CENTRONICS_SAMDAC, centronics_samdac_device, "centronics_samdac", "SAMDAC")
+
+//-------------------------------------------------
+// device_add_mconfig - add device configuration
+//-------------------------------------------------
+
+void centronics_samdac_device::device_add_mconfig(machine_config &config)
+{
+ SPEAKER(config, "speaker", 2).front();
+
+ DAC_8BIT_R2R(config, m_dac[0], 0).add_route(ALL_OUTPUTS, "speaker", 0.5, 0);
+ DAC_8BIT_R2R(config, m_dac[1], 0).add_route(ALL_OUTPUTS, "speaker", 0.5, 1);
+}
+
+
+//**************************************************************************
+// LIVE DEVICE
+//**************************************************************************
+
+//-------------------------------------------------
+// centronics_samdac_device - constructor
+//-------------------------------------------------
+
+centronics_samdac_device::centronics_samdac_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) :
+ device_t(mconfig, CENTRONICS_SAMDAC, tag, owner, clock),
+ device_centronics_peripheral_interface(mconfig, *this),
+ m_dac(*this, "dac%u", 0U),
+ m_strobe(0),
+ m_data{ 0x00, 0x00 }
+{
+}
+
+//-------------------------------------------------
+// device_start - device-specific startup
+//-------------------------------------------------
+
+void centronics_samdac_device::device_start()
+{
+ // register for savestates
+ save_item(NAME(m_strobe));
+ save_item(NAME(m_data), 2);
+}
+
+
+//**************************************************************************
+// IMPLEMENTATION
+//**************************************************************************
+
+void centronics_samdac_device::input_strobe(int state)
+{
+ // raising edge, write to left channel
+ if (m_strobe == 0 && state == 1)
+ m_dac[0]->data_w(m_data[0]);
+
+ // failing edge, write to right channel
+ if (m_strobe == 1 && state == 0)
+ m_dac[1]->data_w(m_data[1]);
+
+ m_strobe = state;
+}
+
+void centronics_samdac_device::update_data(int bit, int state)
+{
+ if (state)
+ {
+ m_data[0] |= (1 << bit);
+ m_data[1] |= (1 << bit);
+ }
+ else
+ {
+ m_data[0] &= ~(1 << bit);
+ m_data[1] &= ~(1 << bit);
+ }
+}
diff --git a/src/devices/bus/centronics/samdac.h b/src/devices/bus/centronics/samdac.h
new file mode 100644
index 00000000000..1f14fef9919
--- /dev/null
+++ b/src/devices/bus/centronics/samdac.h
@@ -0,0 +1,57 @@
+// license: BSD-3-Clause
+// copyright-holders: Dirk Best
+/***************************************************************************
+
+ SAMDAC Stereo DAC for SAM Coupe
+
+***************************************************************************/
+
+#ifndef MAME_BUS_CENTRONICS_SAMDAC_H
+#define MAME_BUS_CENTRONICS_SAMDAC_H
+
+#pragma once
+
+#include "ctronics.h"
+#include "sound/dac.h"
+
+
+//**************************************************************************
+// TYPE DEFINITIONS
+//**************************************************************************
+
+// ======================> centronics_samdac_device
+
+class centronics_samdac_device : public device_t, public device_centronics_peripheral_interface
+{
+public:
+ // construction/destruction
+ centronics_samdac_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
+
+ // from centronics port
+ 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 ATTR_COLD;
+ virtual void device_start() override ATTR_COLD;
+
+private:
+ void update_data(int bit, int state);
+
+ required_device_array<dac_byte_interface, 2> m_dac;
+
+ int m_strobe;
+ uint8_t m_data[2];
+};
+
+// device type definition
+DECLARE_DEVICE_TYPE(CENTRONICS_SAMDAC, centronics_samdac_device)
+
+#endif // MAME_BUS_CENTRONICS_SAMDAC_H
diff --git a/src/devices/bus/centronics/smartboard.cpp b/src/devices/bus/centronics/smartboard.cpp
new file mode 100644
index 00000000000..8afcfbf68f7
--- /dev/null
+++ b/src/devices/bus/centronics/smartboard.cpp
@@ -0,0 +1,37 @@
+// license:BSD-3-Clause
+// copyright-holders:hap
+/*
+
+Tasc SmartBoard SB30 (LPT interface)
+The actual chessboard controller device is in devices/machine/smartboard.*
+
+*/
+
+#include "emu.h"
+#include "smartboard.h"
+
+#include "smartboard.lh"
+
+
+DEFINE_DEVICE_TYPE(CENTRONICS_SMARTBOARD, centronics_smartboard_device, "centronics_smartboard", "Tasc SmartBoard SB30 Interface")
+
+//-------------------------------------------------
+// constructor
+//-------------------------------------------------
+
+centronics_smartboard_device::centronics_smartboard_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) :
+ device_t(mconfig, CENTRONICS_SMARTBOARD, tag, owner, clock),
+ device_centronics_peripheral_interface(mconfig, *this),
+ m_smartboard(*this, "smartboard")
+{ }
+
+
+//-------------------------------------------------
+// device_add_mconfig - add device configuration
+//-------------------------------------------------
+
+void centronics_smartboard_device::device_add_mconfig(machine_config &config)
+{
+ TASC_SB30(config, m_smartboard).data_out().set(FUNC(centronics_smartboard_device::output_busy));
+ config.set_default_layout(layout_smartboard);
+}
diff --git a/src/devices/bus/centronics/smartboard.h b/src/devices/bus/centronics/smartboard.h
new file mode 100644
index 00000000000..46251b68b22
--- /dev/null
+++ b/src/devices/bus/centronics/smartboard.h
@@ -0,0 +1,40 @@
+// license:BSD-3-Clause
+// copyright-holders:hap
+/*
+
+ Tasc SmartBoard SB30 (LPT interface)
+
+*/
+
+#ifndef MAME_BUS_CENTRONICS_SMARTBOARD_H
+#define MAME_BUS_CENTRONICS_SMARTBOARD_H
+
+#pragma once
+
+#include "ctronics.h"
+#include "machine/smartboard.h"
+
+
+class centronics_smartboard_device : public device_t,
+ public device_centronics_peripheral_interface
+{
+public:
+ // construction/destruction
+ centronics_smartboard_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 ATTR_COLD;
+
+ 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;
+};
+
+
+DECLARE_DEVICE_TYPE(CENTRONICS_SMARTBOARD, centronics_smartboard_device)
+
+#endif // MAME_BUS_CENTRONICS_SMARTBOARD_H
diff --git a/src/devices/bus/centronics/spjoy.cpp b/src/devices/bus/centronics/spjoy.cpp
new file mode 100644
index 00000000000..dc032c35031
--- /dev/null
+++ b/src/devices/bus/centronics/spjoy.cpp
@@ -0,0 +1,94 @@
+// license:BSD-3-Clause
+// copyright-holders:Nigel Barnes
+/***************************************************************************
+
+ The Serial Port / Vertical Twist Joystick Interface
+
+ Notes:
+ - Test cases for this joystick are Paradroid 2000 (paradr2k) and Blowpipe (blowpipe).
+
+***************************************************************************/
+
+#include "emu.h"
+#include "spjoy.h"
+
+DEFINE_DEVICE_TYPE(SERIAL_PORT_JOYSTICK, serial_port_joystick_device, "spjoy", "The Serial Port/Vertical Twist Joystick Interface")
+
+serial_port_joystick_device::serial_port_joystick_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
+ : device_t(mconfig, SERIAL_PORT_JOYSTICK, tag, owner, clock)
+ , device_centronics_peripheral_interface( mconfig, *this )
+ , m_joy(*this, "joy_p%u", 1U)
+ , m_data(0xff)
+ , m_busy(0)
+ , m_ack(0)
+{
+}
+
+void serial_port_joystick_device::device_start()
+{
+ save_item(NAME(m_data));
+ save_item(NAME(m_busy));
+ save_item(NAME(m_ack));
+}
+
+void serial_port_joystick_device::update_busy_ack()
+{
+ int busy = 0;
+ int ack = 0;
+
+ if (~m_data & 0x7f)
+ {
+ if ((~m_data & 0x5f) & (~m_joy[0]->read() & 0x5f))
+ {
+ busy = 1;
+ }
+ if ((~m_data & 0x5f) & (~m_joy[1]->read() & 0x5f))
+ {
+ ack = 1;
+ }
+ if (~m_data & 0x20)
+ {
+ busy = ack = 1;
+ }
+ }
+
+ if (m_busy != busy)
+ {
+ m_busy = busy;
+ output_busy(busy);
+ }
+
+ if (m_ack != ack)
+ {
+ m_ack = ack;
+ output_ack(!ack);
+ }
+}
+
+
+static INPUT_PORTS_START( serial_port_joystick )
+ PORT_START("joy_p1")
+ PORT_BIT( 0x01, IP_ACTIVE_LOW, IPT_JOYSTICK_UP ) PORT_PLAYER(1)
+ PORT_BIT( 0x02, IP_ACTIVE_LOW, IPT_JOYSTICK_DOWN ) PORT_PLAYER(1)
+ PORT_BIT( 0x04, IP_ACTIVE_LOW, IPT_JOYSTICK_LEFT ) PORT_PLAYER(1)
+ PORT_BIT( 0x08, IP_ACTIVE_LOW, IPT_JOYSTICK_RIGHT ) PORT_PLAYER(1)
+ PORT_BIT( 0x10, IP_ACTIVE_LOW, IPT_BUTTON1 ) PORT_PLAYER(1)
+ PORT_BIT( 0x20, IP_ACTIVE_LOW, IPT_UNUSED )
+ PORT_BIT( 0x40, IP_ACTIVE_LOW, IPT_BUTTON2 ) PORT_PLAYER(1)
+ PORT_BIT( 0x80, IP_ACTIVE_LOW, IPT_UNUSED )
+
+ PORT_START("joy_p2")
+ PORT_BIT( 0x01, IP_ACTIVE_LOW, IPT_JOYSTICK_UP ) PORT_PLAYER(2)
+ PORT_BIT( 0x02, IP_ACTIVE_LOW, IPT_JOYSTICK_DOWN ) PORT_PLAYER(2)
+ PORT_BIT( 0x04, IP_ACTIVE_LOW, IPT_JOYSTICK_LEFT ) PORT_PLAYER(2)
+ PORT_BIT( 0x08, IP_ACTIVE_LOW, IPT_JOYSTICK_RIGHT ) PORT_PLAYER(2)
+ PORT_BIT( 0x10, IP_ACTIVE_LOW, IPT_BUTTON1 ) PORT_PLAYER(2)
+ PORT_BIT( 0x20, IP_ACTIVE_LOW, IPT_UNUSED )
+ PORT_BIT( 0x40, IP_ACTIVE_LOW, IPT_BUTTON2 ) PORT_PLAYER(2)
+ PORT_BIT( 0x80, IP_ACTIVE_LOW, IPT_UNUSED )
+INPUT_PORTS_END
+
+ioport_constructor serial_port_joystick_device::device_input_ports() const
+{
+ return INPUT_PORTS_NAME( serial_port_joystick );
+}
diff --git a/src/devices/bus/centronics/spjoy.h b/src/devices/bus/centronics/spjoy.h
new file mode 100644
index 00000000000..d16d042cfd9
--- /dev/null
+++ b/src/devices/bus/centronics/spjoy.h
@@ -0,0 +1,50 @@
+// license:BSD-3-Clause
+// copyright-holders:Nigel Barnes
+/***************************************************************************
+
+ The Serial Port / Vertical Twist Joystick Interface
+
+***************************************************************************/
+
+#ifndef MAME_BUS_CENTRONICS_SPJOY_H
+#define MAME_BUS_CENTRONICS_SPJOY_H
+
+#pragma once
+
+#include "ctronics.h"
+
+class serial_port_joystick_device : public device_t,
+ public device_centronics_peripheral_interface
+{
+public:
+ // construction/destruction
+ serial_port_joystick_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
+
+protected:
+ // device-level overrides
+ virtual void device_start() override ATTR_COLD;
+ virtual ioport_constructor device_input_ports() const override ATTR_COLD;
+
+ 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;
+
+ void update_busy_ack();
+
+ uint8_t m_data;
+ int m_busy;
+ int m_ack;
+};
+
+// device type definition
+DECLARE_DEVICE_TYPE(SERIAL_PORT_JOYSTICK, serial_port_joystick_device)
+
+#endif // MAME_BUS_CENTRONICS_SPJOY_H
diff --git a/src/devices/bus/cgenie/expansion/expansion.cpp b/src/devices/bus/cgenie/expansion/expansion.cpp
index 3a7665f7c2b..577c8a4409b 100644
--- a/src/devices/bus/cgenie/expansion/expansion.cpp
+++ b/src/devices/bus/cgenie/expansion/expansion.cpp
@@ -29,7 +29,7 @@ DEFINE_DEVICE_TYPE(CG_EXP_SLOT, cg_exp_slot_device, "cg_exp_slot", "Colour Genie
cg_exp_slot_device::cg_exp_slot_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) :
device_t(mconfig, CG_EXP_SLOT, tag, owner, clock),
- device_slot_interface(mconfig, *this),
+ device_single_card_slot_interface<device_cg_exp_interface>(mconfig, *this),
m_program(*this, finder_base::DUMMY_TAG, -1),
m_io(*this, finder_base::DUMMY_TAG, -1),
m_cart(nullptr),
@@ -53,18 +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();
-}
-
-//-------------------------------------------------
-// device_reset - device-specific reset
-//-------------------------------------------------
-
-void cg_exp_slot_device::device_reset()
-{
}
@@ -77,7 +65,7 @@ void cg_exp_slot_device::device_reset()
//-------------------------------------------------
device_cg_exp_interface::device_cg_exp_interface(const machine_config &mconfig, device_t &device) :
- device_slot_card_interface(mconfig, device)
+ device_interface(device, "cgenieexp")
{
m_slot = dynamic_cast<cg_exp_slot_device *>(device.owner());
}
diff --git a/src/devices/bus/cgenie/expansion/expansion.h b/src/devices/bus/cgenie/expansion/expansion.h
index 3f61b275c19..bb8a57513d7 100644
--- a/src/devices/bus/cgenie/expansion/expansion.h
+++ b/src/devices/bus/cgenie/expansion/expansion.h
@@ -49,7 +49,7 @@
class device_cg_exp_interface;
-class cg_exp_slot_device : public device_t, public device_slot_interface
+class cg_exp_slot_device : public device_t, public device_single_card_slot_interface<device_cg_exp_interface>
{
public:
// construction/destruction
@@ -73,17 +73,16 @@ 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;
protected:
// device-level overrides
- virtual void device_start() override;
- virtual void device_reset() override;
+ virtual void device_start() override ATTR_COLD;
device_cg_exp_interface *m_cart;
@@ -94,7 +93,7 @@ private:
};
// class representing interface-specific live expansion device
-class device_cg_exp_interface : public device_slot_card_interface
+class device_cg_exp_interface : public device_interface
{
public:
// construction/destruction
diff --git a/src/devices/bus/cgenie/expansion/floppy.cpp b/src/devices/bus/cgenie/expansion/floppy.cpp
index a25e49c7019..a52b39a9ea5 100644
--- a/src/devices/bus/cgenie/expansion/floppy.cpp
+++ b/src/devices/bus/cgenie/expansion/floppy.cpp
@@ -14,7 +14,7 @@
#include "floppy.h"
#include "formats/cgenie_dsk.h"
#include "bus/generic/carts.h"
-#include "softlist.h"
+#include "softlist_dev.h"
//**************************************************************************
// CONSTANTS/MACROS
@@ -38,9 +38,11 @@ void cgenie_fdc_device::mmio(address_map &map)
map(0xef, 0xef).mirror(0x10).rw("wd2793", FUNC(wd2793_device::data_r), FUNC(wd2793_device::data_w));
}
-FLOPPY_FORMATS_MEMBER( cgenie_fdc_device::floppy_formats )
- FLOPPY_CGENIE_FORMAT
-FLOPPY_FORMATS_END
+void cgenie_fdc_device::floppy_formats(format_registration &fr)
+{
+ fr.add_mfm_containers();
+ fr.add(FLOPPY_CGENIE_FORMAT);
+}
static void cgenie_floppies(device_slot_interface &device)
{
@@ -97,7 +99,7 @@ void cgenie_fdc_device::device_add_mconfig(machine_config &config)
// SOFTWARE_LIST(config, "floppy_list").set_original("cgenie_flop");
- GENERIC_SOCKET(config, "socket", generic_plain_slot, "cgenie_flop_rom", "bin,rom").set_device_load(FUNC(cgenie_fdc_device::socket_load), this);
+ GENERIC_SOCKET(config, "socket", generic_plain_slot, "cgenie_flop_rom", "bin,rom").set_device_load(FUNC(cgenie_fdc_device::socket_load));
SOFTWARE_LIST(config, "rom_list").set_original("cgenie_flop_rom");
}
@@ -147,9 +149,7 @@ void cgenie_fdc_device::device_reset()
// map extra socket
if (m_socket->exists())
- {
- m_slot->m_program->install_read_handler(0xe000, 0xefff, read8sm_delegate(FUNC(generic_slot_device::read_rom), (generic_slot_device *) m_socket));
- }
+ m_slot->m_program->install_read_handler(0xe000, 0xefff, read8sm_delegate(*m_socket, FUNC(generic_slot_device::read_rom)));
}
@@ -157,13 +157,15 @@ void cgenie_fdc_device::device_reset()
// IMPLEMENTATION
//**************************************************************************
-READ8_MEMBER( cgenie_fdc_device::irq_r )
+uint8_t cgenie_fdc_device::irq_r()
{
uint8_t data = m_irq_status;
- m_irq_status &= ~IRQ_TIMER;
- m_slot->int_w(m_irq_status ? ASSERT_LINE : CLEAR_LINE);
-
+ if (!machine().side_effects_disabled())
+ {
+ m_irq_status &= ~IRQ_TIMER;
+ m_slot->int_w(m_irq_status ? ASSERT_LINE : CLEAR_LINE);
+ }
return data;
}
@@ -175,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_UNSPECIFIED, "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);
@@ -202,7 +201,7 @@ WRITE_LINE_MEMBER( cgenie_fdc_device::intrq_w )
m_slot->int_w(m_irq_status ? ASSERT_LINE : CLEAR_LINE);
}
-WRITE8_MEMBER( cgenie_fdc_device::select_w )
+void cgenie_fdc_device::select_w(uint8_t data)
{
if (VERBOSE)
logerror("cgenie_fdc_device::motor_w: 0x%02x\n", data);
@@ -223,7 +222,7 @@ WRITE8_MEMBER( cgenie_fdc_device::select_w )
}
}
-WRITE8_MEMBER( cgenie_fdc_device::command_w )
+void cgenie_fdc_device::command_w(uint8_t data)
{
// density select is encoded into this pseudo-command
if ((data & 0xfe) == 0xfe)
diff --git a/src/devices/bus/cgenie/expansion/floppy.h b/src/devices/bus/cgenie/expansion/floppy.h
index 1b6dbf5268b..f2595b22d52 100644
--- a/src/devices/bus/cgenie/expansion/floppy.h
+++ b/src/devices/bus/cgenie/expansion/floppy.h
@@ -31,25 +31,25 @@ public:
cgenie_fdc_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;
- 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 ATTR_COLD;
+ 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:
DECLARE_DEVICE_IMAGE_LOAD_MEMBER(socket_load);
- DECLARE_WRITE_LINE_MEMBER(intrq_w);
+ void intrq_w(int state);
TIMER_DEVICE_CALLBACK_MEMBER(timer_callback);
- DECLARE_READ8_MEMBER(irq_r);
- DECLARE_WRITE8_MEMBER(select_w);
- DECLARE_WRITE8_MEMBER(command_w);
+ uint8_t irq_r();
+ void select_w(uint8_t data);
+ void command_w(uint8_t data);
- void mmio(address_map &map);
+ void mmio(address_map &map) ATTR_COLD;
- DECLARE_FLOPPY_FORMATS(floppy_formats);
+ static void floppy_formats(format_registration &fr);
required_device<wd2793_device> m_fdc;
required_device<floppy_connector> m_floppy0;
diff --git a/src/devices/bus/cgenie/parallel/joystick.h b/src/devices/bus/cgenie/parallel/joystick.h
index 6a4025ada9f..0430adc5f7a 100644
--- a/src/devices/bus/cgenie/parallel/joystick.h
+++ b/src/devices/bus/cgenie/parallel/joystick.h
@@ -27,9 +27,9 @@ public:
cgenie_joystick_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 ioport_constructor device_input_ports() const override;
+ virtual void device_start() override ATTR_COLD;
+ virtual void device_reset() override ATTR_COLD;
+ virtual ioport_constructor device_input_ports() const override ATTR_COLD;
virtual void pa_w(uint8_t data) override;
virtual uint8_t pb_r() override;
diff --git a/src/devices/bus/cgenie/parallel/parallel.cpp b/src/devices/bus/cgenie/parallel/parallel.cpp
index a5072e094ee..2d08f27a1e5 100644
--- a/src/devices/bus/cgenie/parallel/parallel.cpp
+++ b/src/devices/bus/cgenie/parallel/parallel.cpp
@@ -29,7 +29,7 @@ DEFINE_DEVICE_TYPE(CG_PARALLEL_SLOT, cg_parallel_slot_device, "cg_parallel_slot"
cg_parallel_slot_device::cg_parallel_slot_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) :
device_t(mconfig, CG_PARALLEL_SLOT, tag, owner, clock),
- device_slot_interface(mconfig, *this),
+ device_single_card_slot_interface<device_cg_parallel_interface>(mconfig, *this),
m_cart(nullptr)
{
}
@@ -48,15 +48,7 @@ cg_parallel_slot_device::~cg_parallel_slot_device()
void cg_parallel_slot_device::device_start()
{
- m_cart = dynamic_cast<device_cg_parallel_interface *>(get_card_device());
-}
-
-//-------------------------------------------------
-// device_reset - device-specific reset
-//-------------------------------------------------
-
-void cg_parallel_slot_device::device_reset()
-{
+ m_cart = get_card_device();
}
@@ -64,7 +56,7 @@ void cg_parallel_slot_device::device_reset()
// I/O PORTS
//**************************************************************************
-READ8_MEMBER( cg_parallel_slot_device::pa_r )
+uint8_t cg_parallel_slot_device::pa_r()
{
if (m_cart)
return m_cart->pa_r();
@@ -72,13 +64,13 @@ READ8_MEMBER( cg_parallel_slot_device::pa_r )
return 0xff;
}
-WRITE8_MEMBER( cg_parallel_slot_device::pa_w )
+void cg_parallel_slot_device::pa_w(uint8_t data)
{
if (m_cart)
m_cart->pa_w(data);
}
-READ8_MEMBER( cg_parallel_slot_device::pb_r )
+uint8_t cg_parallel_slot_device::pb_r()
{
if (m_cart)
return m_cart->pb_r();
@@ -86,7 +78,7 @@ READ8_MEMBER( cg_parallel_slot_device::pb_r )
return 0xff;
}
-WRITE8_MEMBER( cg_parallel_slot_device::pb_w )
+void cg_parallel_slot_device::pb_w(uint8_t data)
{
if (m_cart)
m_cart->pb_w(data);
@@ -102,7 +94,7 @@ WRITE8_MEMBER( cg_parallel_slot_device::pb_w )
//-------------------------------------------------
device_cg_parallel_interface::device_cg_parallel_interface(const machine_config &mconfig, device_t &device) :
- device_slot_card_interface(mconfig, device)
+ device_interface(device, "cgeniepar")
{
m_slot = dynamic_cast<cg_parallel_slot_device *>(device.owner());
}
diff --git a/src/devices/bus/cgenie/parallel/parallel.h b/src/devices/bus/cgenie/parallel/parallel.h
index b31f8c749f4..9cf135ff068 100644
--- a/src/devices/bus/cgenie/parallel/parallel.h
+++ b/src/devices/bus/cgenie/parallel/parallel.h
@@ -33,7 +33,7 @@
class device_cg_parallel_interface;
-class cg_parallel_slot_device : public device_t, public device_slot_interface
+class cg_parallel_slot_device : public device_t, public device_single_card_slot_interface<device_cg_parallel_interface>
{
public:
// construction/destruction
@@ -49,23 +49,22 @@ public:
virtual ~cg_parallel_slot_device();
// IOA
- DECLARE_READ8_MEMBER(pa_r);
- DECLARE_WRITE8_MEMBER(pa_w);
+ uint8_t pa_r();
+ void pa_w(uint8_t data);
// IOB
- DECLARE_READ8_MEMBER(pb_r);
- DECLARE_WRITE8_MEMBER(pb_w);
+ uint8_t pb_r();
+ void pb_w(uint8_t data);
protected:
// device-level overrides
- virtual void device_start() override;
- virtual void device_reset() override;
+ virtual void device_start() override ATTR_COLD;
device_cg_parallel_interface *m_cart;
};
// class representing interface-specific live parallel device
-class device_cg_parallel_interface : public device_slot_card_interface
+class device_cg_parallel_interface : public device_interface
{
public:
// construction/destruction
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..e3f83b62a72 100644
--- a/src/devices/bus/cgenie/parallel/printer.h
+++ b/src/devices/bus/cgenie/parallel/printer.h
@@ -28,19 +28,19 @@ public:
cgenie_printer_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;
+ 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;
virtual void pa_w(uint8_t data) override;
virtual uint8_t pb_r() override;
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/rom.cpp b/src/devices/bus/chanf/rom.cpp
index a3a213ba7ed..ab4b1a83750 100644
--- a/src/devices/bus/chanf/rom.cpp
+++ b/src/devices/bus/chanf/rom.cpp
@@ -145,7 +145,7 @@ void chanf_multi_final_device::device_reset()
mapper specific handlers
-------------------------------------------------*/
-READ8_MEMBER(chanf_rom_device::read_rom)
+uint8_t chanf_rom_device::read_rom(offs_t offset)
{
if (offset < m_rom_size)
return m_rom[offset];
@@ -212,7 +212,7 @@ void chanf_rom_device::common_write_3853(uint32_t offset, uint8_t data)
m_ram[offset] = data;
}
-READ8_MEMBER(chanf_multi_old_device::read_rom)
+uint8_t chanf_multi_old_device::read_rom(offs_t offset)
{
if (offset < 0x2000)
return m_rom[offset + m_base_bank * 0x2000];
@@ -220,13 +220,13 @@ READ8_MEMBER(chanf_multi_old_device::read_rom)
return 0xff;
}
-WRITE8_MEMBER(chanf_multi_old_device::write_bank)
+void chanf_multi_old_device::write_bank(uint8_t data)
{
//printf("0x%x\n", data);
m_base_bank = data & 0x1f;
}
-READ8_MEMBER(chanf_multi_final_device::read_rom)
+uint8_t chanf_multi_final_device::read_rom(offs_t offset)
{
if (offset < 0x2000)
return m_rom[offset + (m_base_bank * 0x2000) + (m_half_bank * 0x1000)];
@@ -234,7 +234,7 @@ READ8_MEMBER(chanf_multi_final_device::read_rom)
return 0xff;
}
-WRITE8_MEMBER(chanf_multi_final_device::write_bank)
+void chanf_multi_final_device::write_bank(uint8_t data)
{
//printf("0x%x\n", data);
m_base_bank = data & 0x1f;
diff --git a/src/devices/bus/chanf/rom.h b/src/devices/bus/chanf/rom.h
index bd32f177ff8..bff8c87e711 100644
--- a/src/devices/bus/chanf/rom.h
+++ b/src/devices/bus/chanf/rom.h
@@ -25,7 +25,7 @@ public:
void common_write_3853(uint32_t offset, uint8_t data);
// reading and writing
- virtual DECLARE_READ8_MEMBER(read_rom) override;
+ virtual uint8_t read_rom(offs_t offset) override;
protected:
chanf_rom_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock);
@@ -45,12 +45,12 @@ public:
chanf_maze_device(const machine_config &mconfig, 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_start() override ATTR_COLD;
+ virtual void device_reset() override ATTR_COLD;
// reading and writing
- virtual DECLARE_READ8_MEMBER(read_ram) override { return common_read_2102(offset); }
- virtual DECLARE_WRITE8_MEMBER(write_ram) override { common_write_2102(offset, data); }
+ virtual uint8_t read_ram(offs_t offset) override { return common_read_2102(offset); }
+ virtual void write_ram(offs_t offset, uint8_t data) override { common_write_2102(offset, data); }
};
@@ -63,12 +63,12 @@ public:
chanf_hangman_device(const machine_config &mconfig, 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_start() override ATTR_COLD;
+ virtual void device_reset() override ATTR_COLD;
// reading and writing
- virtual DECLARE_READ8_MEMBER(read_ram) override { return common_read_2102(offset); }
- virtual DECLARE_WRITE8_MEMBER(write_ram) override { common_write_2102(offset, data); }
+ virtual uint8_t read_ram(offs_t offset) override { return common_read_2102(offset); }
+ virtual void write_ram(offs_t offset, uint8_t data) override { common_write_2102(offset, data); }
};
@@ -81,8 +81,8 @@ public:
chanf_chess_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
// reading and writing
- virtual DECLARE_READ8_MEMBER(read_ram) override { return common_read_3853(offset); }
- virtual DECLARE_WRITE8_MEMBER(write_ram) override { common_write_3853(offset, data); }
+ virtual uint8_t read_ram(offs_t offset) override { return common_read_3853(offset); }
+ virtual void write_ram(offs_t offset, uint8_t data) override { common_write_3853(offset, data); }
};
@@ -95,14 +95,14 @@ public:
chanf_multi_old_device(const machine_config &mconfig, 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_start() override ATTR_COLD;
+ virtual void device_reset() override ATTR_COLD;
// reading and writing
- virtual DECLARE_READ8_MEMBER(read_rom) override;
- virtual DECLARE_READ8_MEMBER(read_ram) override { return common_read_3853(offset); }
- virtual DECLARE_WRITE8_MEMBER(write_ram) override { common_write_3853(offset, data); }
- virtual DECLARE_WRITE8_MEMBER(write_bank) override;
+ virtual uint8_t read_rom(offs_t offset) override;
+ virtual uint8_t read_ram(offs_t offset) override { return common_read_3853(offset); }
+ virtual void write_ram(offs_t offset, uint8_t data) override { common_write_3853(offset, data); }
+ virtual void write_bank(uint8_t data) override;
private:
int m_base_bank;
@@ -118,14 +118,14 @@ public:
chanf_multi_final_device(const machine_config &mconfig, 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_start() override ATTR_COLD;
+ virtual void device_reset() override ATTR_COLD;
// reading and writing
- virtual DECLARE_READ8_MEMBER(read_rom) override;
- virtual DECLARE_READ8_MEMBER(read_ram) override { return common_read_3853(offset); }
- virtual DECLARE_WRITE8_MEMBER(write_ram) override { common_write_3853(offset, data); }
- virtual DECLARE_WRITE8_MEMBER(write_bank) override;
+ virtual uint8_t read_rom(offs_t offset) override;
+ virtual uint8_t read_ram(offs_t offset) override { return common_read_3853(offset); }
+ virtual void write_ram(offs_t offset, uint8_t data) override { common_write_3853(offset, data); }
+ virtual void write_bank(uint8_t data) override;
private:
int m_base_bank, m_half_bank;
diff --git a/src/devices/bus/chanf/slot.cpp b/src/devices/bus/chanf/slot.cpp
index d9e1a27d399..6092103eb1d 100644
--- a/src/devices/bus/chanf/slot.cpp
+++ b/src/devices/bus/chanf/slot.cpp
@@ -7,7 +7,6 @@
***********************************************************************************************************/
-
#include "emu.h"
#include "slot.h"
@@ -25,10 +24,10 @@ DEFINE_DEVICE_TYPE(CHANF_CART_SLOT, channelf_cart_slot_device, "chanf_cart_slot"
// device_channelf_cart_interface - constructor
//-------------------------------------------------
-device_channelf_cart_interface::device_channelf_cart_interface(const machine_config &mconfig, device_t &device)
- : device_slot_card_interface(mconfig, device),
- m_rom(nullptr),
- m_rom_size(0)
+device_channelf_cart_interface::device_channelf_cart_interface(const machine_config &mconfig, device_t &device) :
+ device_interface(device, "chanfcart"),
+ m_rom(nullptr),
+ m_rom_size(0)
{
}
@@ -45,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;
}
}
@@ -74,8 +73,8 @@ void device_channelf_cart_interface::ram_alloc(uint32_t size)
//-------------------------------------------------
channelf_cart_slot_device::channelf_cart_slot_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) :
device_t(mconfig, CHANF_CART_SLOT, tag, owner, clock),
- device_image_interface(mconfig, *this),
- device_slot_interface(mconfig, *this),
+ device_cartrom_image_interface(mconfig, *this),
+ device_single_card_slot_interface<device_channelf_cart_interface>(mconfig, *this),
m_type(CF_CHESS), m_cart(nullptr)
{
}
@@ -95,7 +94,7 @@ channelf_cart_slot_device::~channelf_cart_slot_device()
void channelf_cart_slot_device::device_start()
{
- m_cart = dynamic_cast<device_channelf_cart_interface *>(get_card_device());
+ m_cart = get_card_device();
}
@@ -124,7 +123,7 @@ static int chanf_get_pcb_id(const char *slot)
{
for (auto & elem : slot_list)
{
- if (!core_stricmp(elem.slot_option, slot))
+ if (!strcmp(elem.slot_option, slot))
return elem.pcb_id;
}
@@ -147,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);
@@ -181,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());
}
@@ -197,16 +194,16 @@ std::string channelf_cart_slot_device::get_default_card_software(get_default_car
{
if (hook.image_file())
{
- const char *slot_string;
- uint32_t len = hook.image_file()->size();
- int type;
+ uint64_t len;
+ hook.image_file()->length(len); // FIXME: check error return
+ int type;
if (len == 0x40000)
type = CF_MULTI;
else
type = CF_CHESS; // is there any way to detect the other carts from fullpath?
- slot_string = chanf_get_slot(type);
+ char const *const slot_string = chanf_get_slot(type);
//printf("type: %s\n", slot_string);
@@ -219,10 +216,10 @@ std::string channelf_cart_slot_device::get_default_card_software(get_default_car
read
-------------------------------------------------*/
-READ8_MEMBER(channelf_cart_slot_device::read_rom)
+uint8_t channelf_cart_slot_device::read_rom(offs_t offset)
{
if (m_cart)
- return m_cart->read_rom(space, offset);
+ return m_cart->read_rom(offset);
else
return 0xff;
}
@@ -231,10 +228,10 @@ READ8_MEMBER(channelf_cart_slot_device::read_rom)
read
-------------------------------------------------*/
-READ8_MEMBER(channelf_cart_slot_device::read_ram)
+uint8_t channelf_cart_slot_device::read_ram(offs_t offset)
{
if (m_cart)
- return m_cart->read_ram(space, offset);
+ return m_cart->read_ram(offset);
else
return 0xff;
}
@@ -243,18 +240,18 @@ READ8_MEMBER(channelf_cart_slot_device::read_ram)
write
-------------------------------------------------*/
-WRITE8_MEMBER(channelf_cart_slot_device::write_ram)
+void channelf_cart_slot_device::write_ram(offs_t offset, uint8_t data)
{
if (m_cart)
- m_cart->write_ram(space, offset, data);
+ m_cart->write_ram(offset, data);
}
/*-------------------------------------------------
write
-------------------------------------------------*/
-WRITE8_MEMBER(channelf_cart_slot_device::write_bank)
+void channelf_cart_slot_device::write_bank(uint8_t data)
{
if (m_cart)
- m_cart->write_bank(space, offset, data);
+ m_cart->write_bank(data);
}
diff --git a/src/devices/bus/chanf/slot.h b/src/devices/bus/chanf/slot.h
index d2f9654e8cd..01235a7595b 100644
--- a/src/devices/bus/chanf/slot.h
+++ b/src/devices/bus/chanf/slot.h
@@ -3,7 +3,7 @@
#ifndef MAME_BUS_CHANF_SLOT_H
#define MAME_BUS_CHANF_SLOT_H
-#include "softlist_dev.h"
+#include "imagedev/cartrom.h"
/***************************************************************************
@@ -25,19 +25,19 @@ enum
// ======================> device_channelf_cart_interface
-class device_channelf_cart_interface : public device_slot_card_interface
+class device_channelf_cart_interface : public device_interface
{
public:
// device_channelf_cart_interface/destruction
virtual ~device_channelf_cart_interface();
// reading and writing
- virtual DECLARE_READ8_MEMBER(read_rom) { return 0xff; }
- virtual DECLARE_READ8_MEMBER(read_ram) { return 0xff; }
- virtual DECLARE_WRITE8_MEMBER(write_ram) { }
- virtual DECLARE_WRITE8_MEMBER(write_bank) {}
+ virtual uint8_t read_rom(offs_t offset) { return 0xff; }
+ virtual uint8_t read_ram(offs_t offset) { return 0xff; }
+ 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]; }
@@ -59,8 +59,8 @@ protected:
// ======================> channelf_cart_slot_device
class channelf_cart_slot_device : public device_t,
- public device_image_interface,
- public device_slot_interface
+ public device_cartrom_image_interface,
+ public device_single_card_slot_interface<device_channelf_cart_interface>
{
public:
// construction/destruction
@@ -77,37 +77,30 @@ public:
channelf_cart_slot_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock = 0);
virtual ~channelf_cart_slot_device();
- // device-level overrides
- virtual void device_start() override;
+ // device_image_interface implementation
+ virtual std::pair<std::error_condition, std::string> call_load() override;
+ virtual void call_unload() override { }
- // image-level overrides
- virtual image_init_result call_load() override;
- virtual void call_unload() override {}
- virtual const software_list_loader &get_software_list_loader() const override { return rom_software_list_loader::instance(); }
+ 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"; }
+
+ // 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; }
void save_ram() { if (m_cart && m_cart->get_ram_size()) m_cart->save_ram(); }
- virtual iodevice_t image_type() const override { return IO_CARTSLOT; }
- virtual bool is_readable() const override { return 1; }
- virtual bool is_writeable() const override { return 0; }
- virtual bool is_creatable() const override { return 0; }
- virtual bool must_be_loaded() const override { return 0; }
- virtual bool is_reset_on_load() const override { return 1; }
- virtual const char *image_interface() const override { return "channelf_cart"; }
- virtual const char *file_extensions() const override { return "bin,chf"; }
-
- // slot interface overrides
- virtual std::string get_default_card_software(get_default_card_software_hook &hook) const override;
-
// reading and writing
- virtual DECLARE_READ8_MEMBER(read_rom);
- virtual DECLARE_READ8_MEMBER(read_ram);
- virtual DECLARE_WRITE8_MEMBER(write_ram);
- virtual DECLARE_WRITE8_MEMBER(write_bank);
+ uint8_t read_rom(offs_t offset);
+ uint8_t read_ram(offs_t offset);
+ void write_ram(offs_t offset, uint8_t data);
+ void write_bank(uint8_t data);
protected:
+ // device_t implementation
+ virtual void device_start() override ATTR_COLD;
int m_type;
device_channelf_cart_interface* m_cart;
@@ -118,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 ab6ba20a622..b3f7eba1b46 100644
--- a/src/devices/bus/coco/coco_dcmodem.cpp
+++ b/src/devices/bus/coco/coco_dcmodem.cpp
@@ -37,7 +37,7 @@ namespace
{
public:
// construction/destruction
- coco_dc_modem_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
+ coco_dc_modem_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock)
: device_t(mconfig, COCO_DCMODEM, tag, owner, clock)
, device_cococart_interface(mconfig, *this)
, m_uart(*this, UART_TAG)
@@ -46,10 +46,10 @@ namespace
}
// optional information overrides
- virtual void device_add_mconfig(machine_config &config) override;
+ virtual void device_add_mconfig(machine_config &config) override ATTR_COLD;
// callbacks
- WRITE_LINE_MEMBER(uart_irq_w)
+ void uart_irq_w(int state)
{
set_line_value(line::CART, state != 0);
}
@@ -59,24 +59,24 @@ namespace
virtual void device_start() override
{
install_readwrite_handler(0xFF6C, 0xFF6F,
- read8sm_delegate(FUNC(mos6551_device::read), (mos6551_device *)m_uart),
- write8sm_delegate(FUNC(mos6551_device::write), (mos6551_device *)m_uart));
+ read8sm_delegate(*m_uart, FUNC(mos6551_device::read)),
+ write8sm_delegate(*m_uart, FUNC(mos6551_device::write)));
}
- virtual const tiny_rom_entry *device_rom_region() const override;
+ virtual const tiny_rom_entry *device_rom_region() const override ATTR_COLD;
// CoCo cartridge level overrides
- virtual uint8_t *get_cart_base() override
+ virtual u8 *get_cart_base() override
{
return m_eprom->base();
}
- virtual memory_region* get_cart_memregion() override
+ virtual memory_region *get_cart_memregion() override
{
return m_eprom;
}
- virtual DECLARE_READ8_MEMBER(cts_read) override;
+ virtual u8 cts_read(offs_t offset) override;
private:
// internal state
@@ -126,7 +126,7 @@ const tiny_rom_entry *coco_dc_modem_device::device_rom_region() const
// cts_read
//-------------------------------------------------
-READ8_MEMBER(coco_dc_modem_device::cts_read)
+u8 coco_dc_modem_device::cts_read(offs_t offset)
{
return m_eprom->base()[offset & 0x1fff];
}
diff --git a/src/devices/bus/coco/coco_dwsock.cpp b/src/devices/bus/coco/coco_dwsock.cpp
index 049b3e658ca..b11172ec8a2 100644
--- a/src/devices/bus/coco/coco_dwsock.cpp
+++ b/src/devices/bus/coco/coco_dwsock.cpp
@@ -3,8 +3,8 @@
#include "emu.h"
#include "coco_dwsock.h"
-#include <stdio.h>
-#include <stdlib.h>
+#include <cstdio>
+#include <cstdlib>
#ifdef __GNUC__
#include <unistd.h>
#endif
@@ -24,7 +24,7 @@ DEFINE_DEVICE_TYPE(COCO_DWSOCK, beckerport_device, "coco_dwsock", "Virtual Becke
INPUT_PORTS_START( coco_drivewire )
PORT_START(DRIVEWIRE_PORT_TAG)
- PORT_CONFNAME( 0xffff, 65504, "Drivewire Server TCP Port") PORT_CHANGED_MEMBER(DEVICE_SELF, beckerport_device, drivewire_port_changed, 0)
+ PORT_CONFNAME( 0xffff, 65504, "Drivewire Server TCP Port") PORT_CHANGED_MEMBER(DEVICE_SELF, FUNC(beckerport_device::drivewire_port_changed), 0)
PORT_CONFSETTING( 65500, "65500" )
PORT_CONFSETTING( 65501, "65501" )
PORT_CONFSETTING( 65502, "65502" )
@@ -62,7 +62,7 @@ INPUT_CHANGED_MEMBER(beckerport_device::drivewire_port_changed)
// beckerport_device - constructor / destructor
//-------------------------------------------------
-beckerport_device::beckerport_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
+beckerport_device::beckerport_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock)
: device_t(mconfig, COCO_DWSOCK, tag, owner, clock)
, m_hostname(nullptr), m_dwconfigport(*this, DRIVEWIRE_PORT_TAG), m_dwtcpport(0)
{
@@ -80,35 +80,37 @@ beckerport_device::~beckerport_device()
device_start
-------------------------------------------------*/
-void beckerport_device::device_start(void)
+void beckerport_device::device_start()
{
- char chAddress[64];
+ osd_printf_verbose("%s: Connecting to Drivewire server on %s:%d... ", tag(), m_hostname, m_dwtcpport);
+ u64 filesize; // unused
/* format address string for opening the port */
- snprintf(chAddress, sizeof(chAddress), "socket.%s:%d", m_hostname, m_dwtcpport);
-
- osd_printf_verbose("Connecting to Drivewire server on %s:%d... ", m_hostname, m_dwtcpport);
-
- uint64_t filesize; // unused
- osd_file::error filerr = osd_file::open(chAddress, 0, m_pSocket, filesize);
- if (filerr != osd_file::error::NONE)
+ std::error_condition filerr = osd_file::open(util::string_format("socket.%s:%d", m_hostname, m_dwtcpport), 0, m_pSocket, filesize);
+ if (filerr)
{
- osd_printf_verbose("Error: osd_open returned error %i!\n", (int) filerr);
+ osd_printf_verbose("Error: osd_open returned error %s:%d %s!\n", filerr.category().name(), filerr.value(), filerr.message());
return;
}
osd_printf_verbose("Connected!\n");
+
+ // save state support
+ save_item(NAME(m_rx_pending));
+ save_item(NAME(m_head));
+ save_item(NAME(m_buf));
+
}
/*-------------------------------------------------
device_stop
-------------------------------------------------*/
-void beckerport_device::device_stop(void)
+void beckerport_device::device_stop()
{
if (m_pSocket)
{
- printf("Closing connection to Drivewire server\n");
+ printf("%s: Closing connection to Drivewire server\n", tag());
m_pSocket.reset();
}
}
@@ -117,7 +119,7 @@ void beckerport_device::device_stop(void)
device_config_complete
-------------------------------------------------*/
-void beckerport_device::device_config_complete(void)
+void beckerport_device::device_config_complete()
{
m_hostname = "127.0.0.1";
m_dwtcpport = 65504;
@@ -127,7 +129,7 @@ void beckerport_device::device_config_complete(void)
read
-------------------------------------------------*/
-READ8_MEMBER(beckerport_device::read)
+u8 beckerport_device::read(offs_t offset)
{
unsigned char data = 0x5a;
@@ -139,24 +141,25 @@ READ8_MEMBER(beckerport_device::read)
case DWS_STATUS:
if (!m_rx_pending)
{
- /* Try to read from dws */
- osd_file::error filerr = m_pSocket->read(m_buf, 0, sizeof(m_buf), m_rx_pending);
- if (filerr != osd_file::error::NONE && filerr != osd_file::error::FAILURE) // osd_file::error::FAILURE means no data available, so don't throw error message
- fprintf(stderr, "coco_dwsock.c: beckerport_device::read() socket read operation failed with osd_file::error %i\n", int(filerr));
+ // Try to read from dws
+ std::error_condition filerr = m_pSocket->read(m_buf, 0, sizeof(m_buf), m_rx_pending);
+ if (filerr && (std::errc::operation_would_block != filerr))
+ osd_printf_error("%s: coco_dwsock.c: beckerport_device::read() socket read operation failed with error %s:%d %s\n", tag(), filerr.category().name(), filerr.value(), filerr.message());
else
m_head = 0;
}
- //printf("beckerport_device: status read. %i bytes remaining.\n", m_rx_pending);
+ //logerror("beckerport_device: status read. %i bytes remaining.\n", m_rx_pending);
data = (m_rx_pending > 0) ? 2 : 0;
break;
case DWS_DATA:
- if (!m_rx_pending) {
- fprintf(stderr, "coco_dwsock.c: beckerport_device::read() buffer underrun\n");
+ if (!m_rx_pending)
+ {
+ osd_printf_error("%s: coco_dwsock.c: beckerport_device::read() buffer underrun\n", tag());
break;
}
data = m_buf[m_head++];
m_rx_pending--;
- //printf("beckerport_device: data read 1 byte (0x%02x). %i bytes remaining.\n", data&0xff, m_rx_pending);
+ //logerror("beckerport_device: data read 1 byte (0x%02x). %i bytes remaining.\n", data&0xff, m_rx_pending);
break;
default:
fprintf(stderr, "%s: read from bad offset %d\n", __FILE__, offset);
@@ -169,11 +172,11 @@ READ8_MEMBER(beckerport_device::read)
write
-------------------------------------------------*/
-WRITE8_MEMBER(beckerport_device::write)
+void beckerport_device::write(offs_t offset, u8 data)
{
char d = char(data);
- osd_file::error filerr;
- std::uint32_t written;
+ std::error_condition filerr;
+ u32 written;
if (!m_pSocket)
return;
@@ -181,13 +184,13 @@ WRITE8_MEMBER(beckerport_device::write)
switch (offset)
{
case DWS_STATUS:
- //printf("beckerport_write: error: write (0x%02x) to status register\n", d);
+ //logerror("beckerport_write: error: write (0x%02x) to status register\n", d);
break;
case DWS_DATA:
filerr = m_pSocket->write(&d, 0, 1, written);
- if (filerr != osd_file::error::NONE)
- fprintf(stderr, "coco_dwsock.c: beckerport_device::write() socket write operation failed with osd_file::error %i\n", int(filerr));
- //printf("beckerport_write: data write one byte (0x%02x)\n", d & 0xff);
+ if (filerr)
+ osd_printf_error("%s: coco_dwsock.c: beckerport_device::write() socket write operation failed with error %s:%d %s\n", tag(), filerr.category().name(), filerr.value(), filerr.message());
+ //logerror("beckerport_write: data write one byte (0x%02x)\n", d & 0xff);
break;
default:
fprintf(stderr, "%s: write to bad offset %d\n", __FILE__, offset);
@@ -198,9 +201,9 @@ WRITE8_MEMBER(beckerport_device::write)
update_port
-------------------------------------------------*/
-void beckerport_device::update_port(void)
+void beckerport_device::update_port()
{
device_stop();
- m_dwtcpport = m_dwconfigport.read_safe(65504);
+ m_dwtcpport = m_dwconfigport->read();
device_start();
}
diff --git a/src/devices/bus/coco/coco_dwsock.h b/src/devices/bus/coco/coco_dwsock.h
index a9ac21a18e4..9533b4ca15b 100644
--- a/src/devices/bus/coco/coco_dwsock.h
+++ b/src/devices/bus/coco/coco_dwsock.h
@@ -1,9 +1,9 @@
// license:BSD-3-Clause
// copyright-holders:Nathan Woods
-#ifndef MAME_BUS_COCO_COCO_DWSOCKH_H
-#define MAME_BUS_COCO_COCO_DWSOCKH_H
+#ifndef MAME_BUS_COCO_COCO_DWSOCK_H
+#define MAME_BUS_COCO_COCO_DWSOCK_H
-#include "osdcore.h"
+#include "osdfile.h"
//**************************************************************************
// MACROS / CONSTANTS
@@ -24,11 +24,11 @@
class beckerport_device : public device_t
{
public:
- beckerport_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
+ beckerport_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock);
virtual ~beckerport_device();
// optional information overrides
- virtual ioport_constructor device_input_ports() const override;
+ virtual ioport_constructor device_input_ports() const override ATTR_COLD;
virtual void device_start(void) override;
virtual void device_stop(void) override;
@@ -39,8 +39,8 @@ public:
// driver update handlers
DECLARE_INPUT_CHANGED_MEMBER(drivewire_port_changed);
- virtual DECLARE_READ8_MEMBER(read);
- virtual DECLARE_WRITE8_MEMBER(write);
+ u8 read(offs_t offset);
+ void write(offs_t offset, u8 data);
// types
enum dwsock_ports {
@@ -67,6 +67,6 @@ private:
DECLARE_DEVICE_TYPE(COCO_DWSOCK, beckerport_device)
// device iterator
-typedef device_type_iterator<beckerport_device> beckerport_device_iterator;
+typedef device_type_enumerator<beckerport_device> beckerport_device_enumerator;
-#endif // MAME_BUS_COCO_COCO_DWSOCKH_H
+#endif // MAME_BUS_COCO_COCO_DWSOCK_H
diff --git a/src/devices/bus/coco/coco_fdc.cpp b/src/devices/bus/coco/coco_fdc.cpp
index eded4ed4306..dfd68864f18 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
@@ -40,32 +39,77 @@
Reading from $FF48-$FF4F clears bit 7 of DSKREG ($FF40)
+ ---------------------------------------------------------------------------
+
+ Disto Super Controller II
+ Mini Expansion Bus
+ No Halt Extension. Implemented by using a read and write cache.
+
+ 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 & $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/input_merger.h"
#include "machine/msm6242.h"
-#include "machine/ds1315.h"
#include "machine/wd_fdc.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/sdf_dsk.h"
+#include "formats/vdk_dsk.h"
+
+#define LOG_WDFDC (1U << 1) // Shows register setup
+#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|LOG_WDSCII)
+#include "logmacro.h"
+
+#define LOGWDFDC(...) LOGMASKED(LOG_WDFDC, __VA_ARGS__)
+#define LOGWDIO(...) LOGMASKED(LOG_WDIO, __VA_ARGS__)
+#define LOGWDSCII(...) LOGMASKED(LOG_WDSCII, __VA_ARGS__)
/***************************************************************************
PARAMETERS
***************************************************************************/
-#define LOG_FDC 0
#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>;
@@ -79,54 +123,46 @@ class coco_fdc_device_base : public coco_family_fdc_device_base
{
protected:
// construction/destruction
- coco_fdc_device_base(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock);
-
- enum class rtc_type
- {
- DISTO = 0x00,
- CLOUD9 = 0x01,
- NONE = 0xFF
- };
+ coco_fdc_device_base(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, u32 clock);
// device-level overrides
- virtual DECLARE_READ8_MEMBER(cts_read) override;
- virtual DECLARE_READ8_MEMBER(scs_read) override;
- virtual DECLARE_WRITE8_MEMBER(scs_write) override;
- virtual void device_add_mconfig(machine_config &config) 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;
+ virtual void device_add_mconfig(machine_config &config) override ATTR_COLD;
// methods
virtual void update_lines() override;
- void dskreg_w(uint8_t data);
- rtc_type real_time_clock();
+ void dskreg_w(u8 data);
// 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;
};
-
/***************************************************************************
LOCAL VARIABLES
***************************************************************************/
-FLOPPY_FORMATS_MEMBER( coco_family_fdc_device_base::floppy_formats )
- FLOPPY_DMK_FORMAT,
- FLOPPY_JVC_FORMAT,
- FLOPPY_VDK_FORMAT,
- FLOPPY_SDF_FORMAT,
- FLOPPY_OS9_FORMAT
-FLOPPY_FORMATS_END
+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_OS9_FORMAT);
+ fr.add(fs::COCO_RSDOS);
+ fr.add(fs::COCO_OS9);
+}
static void coco_fdc_floppies(device_slot_interface &device)
{
- device.option_add("qd", FLOPPY_525_QD);
+ device.option_add("525qd", FLOPPY_525_QD);
+ device.option_add("525dd", FLOPPY_525_DD);
+ device.option_add("35dd", FLOPPY_35_DD);
}
void coco_fdc_device_base::device_add_mconfig(machine_config &config)
@@ -134,15 +170,13 @@ void coco_fdc_device_base::device_add_mconfig(machine_config &config)
WD1773(config, m_wd17xx, 8_MHz_XTAL);
m_wd17xx->intrq_wr_callback().set(FUNC(coco_fdc_device_base::fdc_intrq_w));
m_wd17xx->drq_wr_callback().set(FUNC(coco_fdc_device_base::fdc_drq_w));
+ m_wd17xx->set_disable_motor_control(true);
+ m_wd17xx->set_force_ready(true);
- FLOPPY_CONNECTOR(config, m_floppies[0], coco_fdc_floppies, "qd", coco_fdc_device_base::floppy_formats).enable_sound(true);
- FLOPPY_CONNECTOR(config, m_floppies[1], coco_fdc_floppies, "qd", coco_fdc_device_base::floppy_formats).enable_sound(true);
+ FLOPPY_CONNECTOR(config, m_floppies[0], coco_fdc_floppies, "525dd", coco_fdc_device_base::floppy_formats).enable_sound(true);
+ 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);
}
@@ -178,16 +212,17 @@ void coco_family_fdc_device_base::device_reset()
// coco_family_fdc_device_base::get_cart_base
//-------------------------------------------------
-uint8_t* coco_family_fdc_device_base::get_cart_base()
+u8 *coco_family_fdc_device_base::get_cart_base()
{
return memregion("eprom")->base();
}
+
//-------------------------------------------------
// coco_family_fdc_device_base::get_cart_memregion
//-------------------------------------------------
-memory_region* coco_family_fdc_device_base::get_cart_memregion()
+memory_region *coco_family_fdc_device_base::get_cart_memregion()
{
return memregion("eprom");
}
@@ -201,35 +236,13 @@ memory_region* coco_family_fdc_device_base::get_cart_memregion()
// coco_fdc_device_base - constructor
//-------------------------------------------------
-coco_fdc_device_base::coco_fdc_device_base(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock)
+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")
{
}
-//-------------------------------------------------
-// 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;
-}
-
//-------------------------------------------------
// update_lines - CoCo specific disk
@@ -239,7 +252,7 @@ coco_fdc_device_base::rtc_type coco_fdc_device_base::real_time_clock()
void coco_fdc_device_base::update_lines()
{
// clear HALT enable under certain circumstances
- if (intrq() && (dskreg() & 0x20))
+ if (intrq())
set_dskreg(dskreg() & ~0x80); // clear halt enable
// set the NMI line
@@ -254,28 +267,25 @@ void coco_fdc_device_base::update_lines()
// dskreg_w - function to write to CoCo dskreg
//-------------------------------------------------
-void coco_fdc_device_base::dskreg_w(uint8_t data)
+void coco_fdc_device_base::dskreg_w(u8 data)
{
- uint8_t drive = 0;
- uint8_t head;
-
- if (LOG_FDC)
- {
- logerror("fdc_coco_dskreg_w(): %c%c%c%c%c%c%c%c ($%02x)\n",
- data & 0x80 ? 'H' : 'h',
- data & 0x40 ? '3' : '.',
- data & 0x20 ? 'D' : 'S',
- data & 0x10 ? 'P' : 'p',
- data & 0x08 ? 'M' : 'm',
- data & 0x04 ? '2' : '.',
- data & 0x02 ? '1' : '.',
- data & 0x01 ? '0' : '.',
- data);
- }
+ u8 drive = 0;
+ u8 head;
+
+ LOG("fdc_coco_dskreg_w(): %c%c%c%c%c%c%c%c ($%02x)\n",
+ data & 0x80 ? 'H' : 'h',
+ data & 0x40 ? '3' : '.',
+ data & 0x20 ? 'D' : 'S',
+ data & 0x10 ? 'P' : 'p',
+ data & 0x08 ? 'M' : 'm',
+ data & 0x04 ? '2' : '.',
+ data & 0x02 ? '1' : '.',
+ data & 0x01 ? '0' : '.',
+ 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.
@@ -316,7 +326,7 @@ void coco_fdc_device_base::dskreg_w(uint8_t data)
// cts_read
//-------------------------------------------------
-READ8_MEMBER(coco_fdc_device_base::cts_read)
+u8 coco_fdc_device_base::cts_read(offs_t offset)
{
return memregion("eprom")->base()[offset];
}
@@ -326,49 +336,30 @@ READ8_MEMBER(coco_fdc_device_base::cts_read)
// scs_read
//-------------------------------------------------
-READ8_MEMBER(coco_fdc_device_base::scs_read)
+u8 coco_fdc_device_base::scs_read(offs_t offset)
{
- uint8_t result = 0;
+ u8 result = 0;
switch(offset & 0x1F)
{
case 8:
result = m_wd17xx->status_r();
+ LOGWDFDC("m_wd17xx->status_r: %02x\n", result );
break;
case 9:
result = m_wd17xx->track_r();
+ LOGWDFDC("m_wd17xx->track_r: %02x\n", result );
break;
case 10:
result = m_wd17xx->sector_r();
+ LOGWDFDC("m_wd17xx->sector_r: %02x\n", result );
break;
case 11:
result = m_wd17xx->data_r();
+ LOGWDIO("m_wd17xx->data_r: %02x\n", result );
break;
}
- /* other stuff for RTCs */
- switch (offset)
- {
- case 0x10: /* FF50 */
- if (real_time_clock() == rtc_type::DISTO)
- result = m_disto_msm6242->read(space, 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();
- break;
- }
return result;
}
@@ -377,7 +368,7 @@ READ8_MEMBER(coco_fdc_device_base::scs_read)
// scs_write
//-------------------------------------------------
-WRITE8_MEMBER(coco_fdc_device_base::scs_write)
+void coco_fdc_device_base::scs_write(offs_t offset, u8 data)
{
switch(offset & 0x1F)
{
@@ -386,171 +377,395 @@ WRITE8_MEMBER(coco_fdc_device_base::scs_write)
dskreg_w(data);
break;
case 8:
+ LOGWDFDC("m_wd17xx->cmd_w: %02x\n", data );
m_wd17xx->cmd_w(data);
break;
case 9:
+ LOGWDFDC("m_wd17xx->track_w: %02x\n", data );
m_wd17xx->track_w(data);
break;
case 10:
+ LOGWDFDC("m_wd17xx->sector_w: %02x\n", data );
m_wd17xx->sector_w(data);
break;
case 11:
+ 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(space,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("disk10.rom", 0x0000, 0x2000, CRC(b4f9968e) SHA1(04115be3f97952b9d9310b52f806d04f80b40d03))
+ 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("cd6809dsk.u16", 0x0000, 0x2000, CRC(3c35bda8) SHA1(9b2eec25188bed4326b84739a666435884e4ddf4))
+ROM_END
+
+
+//**************************************************************************
+// COCO Floppy Disk Controller
+//**************************************************************************
+
namespace
{
class coco_fdc_device : public coco_fdc_device_base
{
public:
// construction/destruction
- coco_fdc_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
+ coco_fdc_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock)
: coco_fdc_device_base(mconfig, COCO_FDC, tag, owner, clock)
{
}
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, uint32_t 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 ATTR_COLD;
+ virtual void device_reset() override ATTR_COLD;
+ 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 ATTR_COLD;
+
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, uint32_t 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);
}
+ }
- protected:
- // optional information overrides
- virtual const tiny_rom_entry *device_rom_region() const override
+
+//-------------------------------------------------
+// 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 */
{
- return ROM_NAME(coco3_hdb1);
+ // set the HALT line
+ set_line_value(line::HALT, !drq() && (dskreg() & 0x80));
+ }
+ else
+ {
+ set_line_value(line::HALT, CLEAR_LINE);
+
+ 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;
+ }
}
- };
-}
-DEFINE_DEVICE_TYPE_PRIVATE(COCO3_HDB1, coco_family_fdc_device_base, coco3_hdb1_device, "coco3_hdb1", "CoCo3 HDB-DOS")
+ if ((m_cache_controler & 0x08) == 0x08)
+ {
+ m_carts->in_w<0>(intrq());
+ }
+ else
+ {
+ m_carts->in_w<0>(CLEAR_LINE);
+ }
-//**************************************************************************
-// COCO-2 HDB-DOS
-//**************************************************************************
+ if ((m_cache_controler & 0x04) == 0x00)
+ {
+ set_line_value(line::NMI, intrq() && (dskreg() & 0x20));
+ }
+ else
+ {
+ set_line_value(line::NMI, CLEAR_LINE);
+ }
+ }
-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
-namespace
-{
- class coco2_hdb1_device : public coco_fdc_device_base
+//-------------------------------------------------
+// ff74_read - no halt registers
+//-------------------------------------------------
+
+ 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, uint32_t 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)
@@ -561,18 +776,11 @@ 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:
// construction/destruction
- cp450_fdc_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
+ cp450_fdc_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock)
: coco_fdc_device_base(mconfig, CP450_FDC, tag, owner, clock)
{
}
@@ -584,9 +792,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)
@@ -595,18 +801,11 @@ 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:
// construction/destruction
- cd6809_fdc_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
+ cd6809_fdc_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock)
: coco_fdc_device_base(mconfig, CD6809_FDC, tag, owner, clock)
{
}
@@ -618,6 +817,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 2568ed51bd0..4097b4b2e08 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,47 +27,45 @@ 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(); }
- DECLARE_FLOPPY_FORMATS(floppy_formats);
+ static void floppy_formats(format_registration &fr);
protected:
// construction/destruction
- coco_family_fdc_device_base(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock)
+ coco_family_fdc_device_base(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, u32 clock)
: device_t(mconfig, type, tag, owner, clock)
, device_cococart_interface(mconfig, *this)
{
};
// device-level overrides
- virtual void device_start() override;
- virtual void device_reset() override;
+ virtual void device_start() override ATTR_COLD;
+ virtual void device_reset() override ATTR_COLD;
// FDC overrides
virtual void update_lines() = 0;
- virtual uint8_t* get_cart_base() override;
- virtual memory_region* get_cart_memregion() override;
+ virtual u8 *get_cart_base() override;
+ virtual memory_region *get_cart_memregion() override;
// accessors
- uint8_t dskreg() const { return m_dskreg; }
+ u8 dskreg() const { return m_dskreg; }
bool intrq() const { return m_intrq; }
bool drq() const { return m_drq; }
- void set_dskreg(uint8_t data) { m_dskreg = data; }
+ void set_dskreg(u8 data) { m_dskreg = data; }
private:
// registers
- uint8_t m_dskreg;
+ u8 m_dskreg;
bool m_intrq;
bool m_drq;
};
// 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_gmc.cpp b/src/devices/bus/coco/coco_gmc.cpp
index 72c9edfdc80..bf7df5c24dc 100644
--- a/src/devices/bus/coco/coco_gmc.cpp
+++ b/src/devices/bus/coco/coco_gmc.cpp
@@ -38,12 +38,12 @@ namespace
{
public:
// construction/destruction
- coco_pak_gmc_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
- virtual void device_add_mconfig(machine_config &config) override;
+ coco_pak_gmc_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock);
+ virtual void device_add_mconfig(machine_config &config) override ATTR_COLD;
protected:
// device-level overrides
- virtual DECLARE_WRITE8_MEMBER(scs_write) override;
+ virtual void scs_write(offs_t offset, u8 data) override;
private:
required_device<sn76489a_device> m_psg;
@@ -68,7 +68,7 @@ DEFINE_DEVICE_TYPE_PRIVATE(COCO_PAK_GMC, device_cococart_interface, coco_pak_gmc
// coco_pak_device - constructor
//-------------------------------------------------
-coco_pak_gmc_device::coco_pak_gmc_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
+coco_pak_gmc_device::coco_pak_gmc_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock)
: coco_pak_banked_device(mconfig, COCO_PAK_GMC, tag, owner, clock)
, m_psg(*this, SN76489AN_TAG)
{
@@ -79,13 +79,13 @@ coco_pak_gmc_device::coco_pak_gmc_device(const machine_config &mconfig, const ch
// scs_write
//-------------------------------------------------
-WRITE8_MEMBER(coco_pak_gmc_device::scs_write)
+void coco_pak_gmc_device::scs_write(offs_t offset, u8 data)
{
switch(offset)
{
case 0:
/* set the bank */
- coco_pak_banked_device::scs_write(space, offset, data, mem_mask);
+ coco_pak_banked_device::scs_write(offset, data);
break;
case 1:
m_psg->write(data);
diff --git a/src/devices/bus/coco/coco_ide.cpp b/src/devices/bus/coco/coco_ide.cpp
new file mode 100644
index 00000000000..0d261e2be3b
--- /dev/null
+++ b/src/devices/bus/coco/coco_ide.cpp
@@ -0,0 +1,249 @@
+// license:BSD-3-Clause
+// copyright-holders:Nigel Barnes
+/***************************************************************************
+
+ Glenside IDE Adapter
+
+***************************************************************************/
+
+#include "emu.h"
+#include "coco_ide.h"
+
+
+//**************************************************************************
+// GLOBAL VARIABLES
+//**************************************************************************
+
+DEFINE_DEVICE_TYPE(COCO_IDE, coco_ide_device, "coco_ide", "Glenside IDE Adapter")
+
+
+//-------------------------------------------------
+// INPUT_PORTS( ide )
+//-------------------------------------------------
+
+INPUT_PORTS_START(ide)
+ PORT_START("JUMPERS")
+ PORT_CONFNAME(0x01, 0x00, "J2 Base Address")
+ PORT_CONFSETTING(0x00, "$FF5x")
+ PORT_CONFSETTING(0x01, "$FF7x")
+INPUT_PORTS_END
+
+
+//-------------------------------------------------
+// input_ports - device-specific input ports
+//-------------------------------------------------
+
+ioport_constructor coco_ide_device::device_input_ports() const
+{
+ return INPUT_PORTS_NAME(ide);
+}
+
+
+//**************************************************************************
+// LIVE DEVICE
+//**************************************************************************
+
+//-------------------------------------------------
+// coco_ide_device - constructor
+//-------------------------------------------------
+
+coco_ide_device::coco_ide_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock)
+ : device_t(mconfig, COCO_IDE, tag, owner, clock)
+ , device_cococart_interface(mconfig, *this )
+ , m_ata(*this, "ata")
+ , m_slot(*this, "slot")
+ , m_jumpers(*this, "JUMPERS")
+ , m_latch(0)
+{
+}
+
+//-------------------------------------------------
+// device_start - device-specific startup
+//-------------------------------------------------
+
+void coco_ide_device::device_start()
+{
+ save_item(NAME(m_latch));
+}
+
+//-------------------------------------------------
+// device_reset - device-specific reset
+//-------------------------------------------------
+
+void coco_ide_device::device_reset()
+{
+ if (m_jumpers->read() == 0x01)
+ install_readwrite_handler(0xff70, 0xff78, read8sm_delegate(*this, FUNC(coco_ide_device::ide_read)), write8sm_delegate(*this, FUNC(coco_ide_device::ide_write)));
+}
+
+
+//-------------------------------------------------
+// coco_cart
+//-------------------------------------------------
+
+static void coco_cart(device_slot_interface &device)
+{
+ coco_cart_add_basic_devices(device);
+ coco_cart_add_fdcs(device);
+}
+
+//-------------------------------------------------
+// device_add_mconfig - add device configuration
+//-------------------------------------------------
+
+void coco_ide_device::device_add_mconfig(machine_config &config)
+{
+ ATA_INTERFACE(config, m_ata).options(ata_devices, "hdd", nullptr, false);
+
+ COCOCART_SLOT(config, m_slot, DERIVED_CLOCK(1, 1), coco_cart, "pak");
+ m_slot->cart_callback().set([this](int state) { set_line_value(line::CART, state); });
+ m_slot->nmi_callback().set([this](int state) { set_line_value(line::NMI, state); });
+ m_slot->halt_callback().set([this](int state) { set_line_value(line::HALT, state); });
+}
+
+
+//-------------------------------------------------
+// ide_read
+//-------------------------------------------------
+
+u8 coco_ide_device::ide_read(offs_t offset)
+{
+ u8 result = 0x00;
+
+ switch (offset)
+ {
+ case 0:
+ {
+ u16 temp = m_ata->cs0_r(offset);
+ m_latch = temp >> 8;
+ result = temp & 0xff;
+ break;
+ }
+ case 1: case 2: case 3: case 4: case 5: case 6: case 7:
+ result = m_ata->cs0_r(offset, 0xff);
+ break;
+
+ case 8:
+ result = m_latch;
+ break;
+
+ default:
+ logerror("ide_read: %02x %04x\n", offset, result);
+ break;
+ }
+
+ return result;
+}
+
+
+//-------------------------------------------------
+// ide_write
+//-------------------------------------------------
+
+void coco_ide_device::ide_write(offs_t offset, u8 data)
+{
+ switch (offset)
+ {
+ case 0:
+ {
+ u16 temp = (m_latch << 8) | data;
+ m_ata->cs0_w(offset, temp);
+ break;
+ }
+ case 1: case 2: case 3: case 4: case 5: case 6: case 7:
+ m_ata->cs0_w(offset, data, 0xff);
+ break;
+
+ case 8:
+ m_latch = data;
+ break;
+
+ default:
+ logerror("ide_write: %02x %04x\n", offset, data);
+ break;
+ }
+}
+
+
+//-------------------------------------------------
+// set_sound_enable
+//-------------------------------------------------
+
+void coco_ide_device::set_sound_enable(bool sound_enable)
+{
+ m_slot->set_line_value(line::SOUND_ENABLE, sound_enable ? line_value::ASSERT : line_value::CLEAR);
+}
+
+
+//-------------------------------------------------
+// get_cart_base
+//-------------------------------------------------
+
+u8 *coco_ide_device::get_cart_base()
+{
+ return m_slot->get_cart_base();
+}
+
+
+//-------------------------------------------------
+// get_cart_size
+//-------------------------------------------------
+
+u32 coco_ide_device::get_cart_size()
+{
+ return m_slot->get_cart_size();
+}
+
+
+//-------------------------------------------------
+// cts_read
+//-------------------------------------------------
+
+u8 coco_ide_device::cts_read(offs_t offset)
+{
+ return m_slot->cts_read(offset);
+}
+
+//-------------------------------------------------
+// cts_write
+//-------------------------------------------------
+
+void coco_ide_device::cts_write(offs_t offset, u8 data)
+{
+ m_slot->cts_write(offset, data);
+}
+
+
+//-------------------------------------------------
+// scs_read
+//-------------------------------------------------
+
+u8 coco_ide_device::scs_read(offs_t offset)
+{
+ if (m_jumpers->read() == 0x00 && (offset & 0x10))
+ return ide_read(offset & 0x0f);
+ else
+ return m_slot->scs_read(offset);
+}
+
+//-------------------------------------------------
+// scs_write
+//-------------------------------------------------
+
+void coco_ide_device::scs_write(offs_t offset, u8 data)
+{
+ if (m_jumpers->read() == 0x00 && (offset & 0x10))
+ ide_write(offset & 0x0f, data);
+ else
+ m_slot->scs_write(offset, data);
+}
+
+
+//-------------------------------------------------
+// cartridge_space
+//-------------------------------------------------
+
+address_space &coco_ide_device::cartridge_space()
+{
+ return device_cococart_interface::cartridge_space();
+}
diff --git a/src/devices/bus/coco/coco_ide.h b/src/devices/bus/coco/coco_ide.h
new file mode 100644
index 00000000000..46ce852e78b
--- /dev/null
+++ b/src/devices/bus/coco/coco_ide.h
@@ -0,0 +1,62 @@
+// license:BSD-3-Clause
+// copyright-holders:Nigel Barnes
+#ifndef MAME_BUS_COCO_COCO_IDE_H
+#define MAME_BUS_COCO_COCO_IDE_H
+
+#pragma once
+
+#include "cococart.h"
+#include "bus/ata/ataintf.h"
+
+
+//**************************************************************************
+// TYPE DEFINITIONS
+//**************************************************************************
+
+// ======================> coco_ide_device
+
+class coco_ide_device :
+ public device_t,
+ public device_cococart_interface,
+ public device_cococart_host_interface
+{
+public:
+ // construction/destruction
+ coco_ide_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock);
+
+ // optional information overrides
+ virtual void device_add_mconfig(machine_config &config) override ATTR_COLD;
+ virtual ioport_constructor device_input_ports() const override ATTR_COLD;
+
+protected:
+ // device-level overrides
+ virtual void device_start() override ATTR_COLD;
+ virtual void device_reset() override ATTR_COLD;
+
+ virtual u8 cts_read(offs_t offset) override;
+ virtual void cts_write(offs_t offset, u8 data) override;
+ virtual u8 scs_read(offs_t offset) override;
+ virtual void scs_write(offs_t offset, u8 data) override;
+ virtual void set_sound_enable(bool sound_enable) override;
+
+ virtual u8 *get_cart_base() override;
+ virtual u32 get_cart_size() override;
+
+ virtual address_space &cartridge_space() override;
+
+private:
+ required_device<ata_interface_device> m_ata;
+ required_device<cococart_slot_device> m_slot;
+ required_ioport m_jumpers;
+
+ u8 ide_read(offs_t offset);
+ void ide_write(offs_t offset, u8 data);
+
+ u8 m_latch;
+};
+
+
+// device type definition
+DECLARE_DEVICE_TYPE(COCO_IDE, coco_ide_device)
+
+#endif // MAME_BUS_COCO_COCO_IDE_H
diff --git a/src/devices/bus/coco/coco_max.cpp b/src/devices/bus/coco/coco_max.cpp
new file mode 100644
index 00000000000..ebe9573cbc4
--- /dev/null
+++ b/src/devices/bus/coco/coco_max.cpp
@@ -0,0 +1,170 @@
+// license:BSD-3-Clause
+// copyright-holders:tim lindner
+/***************************************************************************
+
+ coco_max.cpp
+
+ Code for emulating CoCo Max Hi-Res Input Module
+
+***************************************************************************/
+
+#include "emu.h"
+#include "coco_max.h"
+
+#define MOUSE_SENSITIVITY 75
+#define COCOMAX_X_TAG "cocomax_x"
+#define COCOMAX_Y_TAG "cocomax_y"
+#define COCOMAX_BUTTONS "cocomax_buttons"
+
+// #define VERBOSE (LOG_GENERAL )
+#include "logmacro.h"
+
+//-------------------------------------------------
+// INPUT_PORTS( cocomax_mouse )
+//-------------------------------------------------
+
+INPUT_PORTS_START( cocomax_mouse )
+ PORT_START(COCOMAX_X_TAG)
+ PORT_BIT( 0xff, 0x80, IPT_AD_STICK_X) PORT_NAME("CoCo Max Mouse X") PORT_SENSITIVITY(MOUSE_SENSITIVITY) PORT_MINMAX(0x00,0xff) PORT_KEYDELTA(10) 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_PLAYER(1)
+ PORT_START(COCOMAX_Y_TAG)
+ PORT_BIT( 0xff, 0x80, IPT_AD_STICK_Y) PORT_NAME("CoCo Max Mouse Y") PORT_SENSITIVITY(MOUSE_SENSITIVITY) PORT_MINMAX(0x00,0xff) PORT_KEYDELTA(10) 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_PLAYER(1)
+ PORT_START(COCOMAX_BUTTONS)
+ PORT_BIT( 0x01, IP_ACTIVE_HIGH, IPT_BUTTON1) PORT_NAME("CoCo Max Left Button") PORT_CODE(KEYCODE_0_PAD) PORT_CODE(MOUSECODE_BUTTON1) PORT_PLAYER(1)
+ PORT_BIT( 0x02, IP_ACTIVE_HIGH, IPT_BUTTON2) PORT_NAME("CoCo Max Right Button") PORT_CODE(KEYCODE_DEL_PAD) PORT_CODE(MOUSECODE_BUTTON2) PORT_PLAYER(1)
+INPUT_PORTS_END
+
+//**************************************************************************
+// TYPE DECLARATIONS
+//**************************************************************************
+
+namespace
+{
+ // ======================> coco_pak_device
+
+ class coco_pak_max_device :
+ public device_t,
+ public device_cococart_interface
+ {
+ public:
+ // construction/destruction
+ coco_pak_max_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock);
+
+ protected:
+ // device-level overrides
+ virtual void device_start() override ATTR_COLD;
+ virtual void device_reset() override ATTR_COLD;
+ virtual ioport_constructor device_input_ports() const override ATTR_COLD;
+
+ u8 ff90_read(offs_t offset);
+
+ private:
+ required_ioport m_mouse_x;
+ required_ioport m_mouse_y;
+ required_ioport m_buttons;
+
+ uint8_t m_a2d_result;
+ };
+};
+
+
+
+//**************************************************************************
+// GLOBAL VARIABLES
+//**************************************************************************
+
+DEFINE_DEVICE_TYPE_PRIVATE(COCO_PAK_MAX, device_cococart_interface, coco_pak_max_device, "cocopakmax", "CoCo Max HI-RES input module")
+
+
+
+//-------------------------------------------------
+// coco_pak_device - constructor
+//-------------------------------------------------
+
+coco_pak_max_device::coco_pak_max_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock)
+ : device_t(mconfig, COCO_PAK_MAX, tag, owner, clock)
+ , device_cococart_interface(mconfig, *this)
+ , m_mouse_x(*this, COCOMAX_X_TAG)
+ , m_mouse_y(*this, COCOMAX_Y_TAG)
+ , m_buttons(*this, COCOMAX_BUTTONS)
+ , m_a2d_result(0)
+{
+}
+
+
+
+ioport_constructor coco_pak_max_device::device_input_ports() const
+{
+ return INPUT_PORTS_NAME(cocomax_mouse);
+}
+
+
+
+//-------------------------------------------------
+// device_start - device-specific startup
+//-------------------------------------------------
+
+void coco_pak_max_device::device_start()
+{
+ // initial state
+ m_a2d_result = 0;
+
+ // save state
+ save_item(NAME(m_a2d_result));
+
+ // install $ff90-$ff97 handler
+ install_read_handler(0xff90, 0xff97, read8sm_delegate(*this, FUNC(coco_pak_max_device::ff90_read)));
+}
+
+
+
+//-------------------------------------------------
+// device_reset - device-specific reset
+//-------------------------------------------------
+
+void coco_pak_max_device::device_reset()
+{
+ m_a2d_result = 0;
+}
+
+
+
+//-------------------------------------------------
+// ff90_read
+//-------------------------------------------------
+
+u8 coco_pak_max_device::ff90_read(offs_t offset)
+{
+ uint8_t result = m_a2d_result;
+
+ switch (offset & 0x07)
+ {
+ case 0:
+ m_a2d_result = m_mouse_y->read();
+ break;
+ case 1:
+ m_a2d_result = m_mouse_x->read();
+ break;
+ case 2:
+ m_a2d_result = BIT(m_buttons->read(), 0) ? 0 : 0xff;
+ break;
+ case 3:
+ m_a2d_result = BIT(m_buttons->read(), 1) ? 0 : 0xff;
+ break;
+ case 4:
+ /* not connected*/
+ break;
+ case 5:
+ /* not connected*/
+ break;
+ case 6:
+ /* not connected*/
+ break;
+ case 7:
+ /* not connected*/
+ break;
+ default:
+ break;
+ }
+
+ return result;
+}
diff --git a/src/devices/bus/coco/coco_max.h b/src/devices/bus/coco/coco_max.h
new file mode 100644
index 00000000000..22e592cff25
--- /dev/null
+++ b/src/devices/bus/coco/coco_max.h
@@ -0,0 +1,14 @@
+// license:BSD-3-Clause
+// copyright-holders:tim lindner
+#ifndef MAME_BUS_COCO_COCO_MAX_H
+#define MAME_BUS_COCO_COCO_MAX_H
+
+#pragma once
+
+#include "cococart.h"
+
+// device type definition
+DECLARE_DEVICE_TYPE(COCO_PAK_MAX, device_cococart_interface)
+
+#endif // MAME_BUS_COCO_COCO_MAX_H
+
diff --git a/src/devices/bus/coco/coco_midi.cpp b/src/devices/bus/coco/coco_midi.cpp
new file mode 100644
index 00000000000..118c8bcdb0d
--- /dev/null
+++ b/src/devices/bus/coco/coco_midi.cpp
@@ -0,0 +1,116 @@
+// license:BSD-3-Clause
+// copyright-holders:tim lindner
+/***************************************************************************
+
+ coco_midi.cpp
+
+ Emulation of Rutherford Research's Midi Pak and also compatible with
+ Go4Retro's MIDI Maestro.
+
+***************************************************************************/
+
+#include "emu.h"
+#include "coco_midi.h"
+
+#include "machine/6850acia.h"
+#include "machine/clock.h"
+#include "bus/midi/midi.h"
+
+namespace {
+
+// ======================> coco_midi_device
+
+class coco_midi_device :
+ public device_t,
+ public device_cococart_interface
+{
+ public:
+ // construction/destruction
+ coco_midi_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock);
+
+ protected:
+ coco_midi_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, u32 clock);
+ virtual void device_start() override ATTR_COLD;
+
+ // optional information overrides
+ virtual void device_add_mconfig(machine_config &config) override ATTR_COLD;
+ required_device<acia6850_device> m_acia;
+ void acia_irq_w(int state);
+
+ private:
+ required_device<midi_port_device> m_mdthru;
+};
+
+class dragon_midi_device : public coco_midi_device
+{
+ public:
+ // construction/destruction
+ dragon_midi_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock);
+
+ protected:
+ dragon_midi_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, u32 clock);
+ virtual void device_start() override ATTR_COLD;
+};
+
+coco_midi_device::coco_midi_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, u32 clock)
+ : device_t(mconfig, type, tag, owner, clock)
+ , device_cococart_interface(mconfig, *this )
+ , m_acia(*this, "mc6850")
+ , m_mdthru(*this, "mdthru")
+{
+}
+
+coco_midi_device::coco_midi_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock)
+ : coco_midi_device(mconfig, COCO_MIDI, tag, owner, clock)
+{
+}
+
+void coco_midi_device::device_add_mconfig(machine_config &config)
+{
+ ACIA6850(config, m_acia).txd_handler().set("mdout", FUNC(midi_port_device::write_txd));
+ m_acia->irq_handler().set(FUNC(coco_midi_device::acia_irq_w));
+
+ midi_port_device &mdin(MIDI_PORT(config, "mdin", midiin_slot, "midiin"));
+ mdin.rxd_handler().set(m_acia, FUNC(acia6850_device::write_rxd));
+ mdin.rxd_handler().append(m_mdthru, FUNC(midi_port_device::write_txd));
+ MIDI_PORT(config, m_mdthru, midiout_slot, "midiout");
+ MIDI_PORT(config, "mdout", midiout_slot, "midiout");
+
+ clock_device &acia_clock(CLOCK(config, "acia_clock", 31250*16));
+ acia_clock.signal_handler().set(m_acia, FUNC(acia6850_device::write_txc));
+ acia_clock.signal_handler().append(m_acia, FUNC(acia6850_device::write_rxc));
+}
+
+void coco_midi_device::device_start()
+{
+ install_readwrite_handler(0xff6e, 0xff6f,
+ read8sm_delegate(m_acia, FUNC(acia6850_device::read)),
+ write8sm_delegate(m_acia, FUNC(acia6850_device::write)));
+}
+
+void coco_midi_device::acia_irq_w(int state)
+{
+ set_line_value(line::CART, state == 0);
+}
+
+dragon_midi_device::dragon_midi_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, u32 clock)
+ : coco_midi_device(mconfig, type, tag, owner, clock)
+{
+}
+
+dragon_midi_device::dragon_midi_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock)
+ : dragon_midi_device(mconfig, DRAGON_MIDI, tag, owner, clock)
+{
+}
+
+void dragon_midi_device::device_start()
+{
+ install_readwrite_handler(0xff74, 0xff75,
+ read8sm_delegate(m_acia, FUNC(acia6850_device::read)),
+ write8sm_delegate(m_acia, FUNC(acia6850_device::write)));
+}
+
+} // anonymous namespace
+
+DEFINE_DEVICE_TYPE_PRIVATE(COCO_MIDI, device_cococart_interface, coco_midi_device, "coco_midi", "CoCo MIDI PAK")
+DEFINE_DEVICE_TYPE_PRIVATE(DRAGON_MIDI, device_cococart_interface, dragon_midi_device, "dragon_midi", "Dragon MIDI PAK")
diff --git a/src/devices/bus/coco/coco_midi.h b/src/devices/bus/coco/coco_midi.h
new file mode 100644
index 00000000000..77b0756ff20
--- /dev/null
+++ b/src/devices/bus/coco/coco_midi.h
@@ -0,0 +1,14 @@
+// license:BSD-3-Clause
+// copyright-holders:tim lindner
+#ifndef MAME_BUS_COCO_COCO_MIDI_H
+#define MAME_BUS_COCO_COCO_MIDI_H
+
+#pragma once
+
+#include "cococart.h"
+
+// device type definition
+DECLARE_DEVICE_TYPE(COCO_MIDI, device_cococart_interface)
+DECLARE_DEVICE_TYPE(DRAGON_MIDI, device_cococart_interface)
+
+#endif // MAME_BUS_COCO_COCO_MIDI_H
diff --git a/src/devices/bus/coco/coco_multi.cpp b/src/devices/bus/coco/coco_multi.cpp
index d6c5627ca11..312823b7a8f 100644
--- a/src/devices/bus/coco/coco_multi.cpp
+++ b/src/devices/bus/coco/coco_multi.cpp
@@ -57,13 +57,6 @@
#include "coco_multi.h"
#include "cococart.h"
-#include "coco_dcmodem.h"
-#include "coco_fdc.h"
-#include "coco_gmc.h"
-#include "coco_orch90.h"
-#include "coco_pak.h"
-#include "coco_rs232.h"
-#include "coco_ssc.h"
#define SLOT1_TAG "slot1"
#define SLOT2_TAG "slot2"
@@ -72,12 +65,20 @@
#define SWITCH_CONFIG_TAG "switch"
+#define LOG_CART (1U << 1) // shows cart line changes
+#define LOG_SWITCH (1U << 2) // shows switch changes
+//#define VERBOSE (LOG_CART|LOG_SWITCH)
+
+#include "logmacro.h"
+
+#define LOGCART(...) LOGMASKED(LOG_CART, __VA_ARGS__)
+#define LOGSWITCH(...) LOGMASKED(LOG_SWITCH, __VA_ARGS__)
//**************************************************************************
// MACROS / CONSTANTS
//**************************************************************************
-static constexpr uint8_t MULTI_SLOT_LOOKUP[] = {0xcc, 0xdd, 0xee, 0xff};
+static constexpr u8 MULTI_SLOT_LOOKUP[] = {0xcc, 0xdd, 0xee, 0xff};
//**************************************************************************
// TYPE DEFINITIONS
@@ -94,36 +95,40 @@ namespace
{
public:
// construction/destruction
- coco_multipak_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
+ coco_multipak_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock);
INPUT_CHANGED_MEMBER( switch_changed );
protected:
+ coco_multipak_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;
- virtual READ8_MEMBER(cts_read) override;
- virtual WRITE8_MEMBER(cts_write) override;
- virtual READ8_MEMBER(scs_read) override;
- virtual WRITE8_MEMBER(scs_write) override;
+ virtual void device_start() override ATTR_COLD;
+ virtual void device_reset() override ATTR_COLD;
+ virtual u8 cts_read(offs_t offset) override;
+ virtual void cts_write(offs_t offset, u8 data) override;
+ virtual u8 scs_read(offs_t offset) override;
+ virtual void scs_write(offs_t offset, u8 data) override;
virtual void set_sound_enable(bool sound_enable) override;
// optional information overrides
- virtual void device_add_mconfig(machine_config &config) override;
+ virtual void device_add_mconfig(machine_config &config) override ATTR_COLD;
- virtual uint8_t* get_cart_base() override;
- virtual uint32_t get_cart_size() override;
+ virtual u8 *get_cart_base() override;
+ virtual u32 get_cart_size() override;
virtual address_space &cartridge_space() override;
- virtual ioport_constructor device_input_ports() const override;
+ virtual ioport_constructor device_input_ports() const override ATTR_COLD;
- private:
// device references
required_device_array<cococart_slot_device, 4> m_slots;
+ void update_line(int slot_number, line ln);
+
+ private:
// internal state
- uint8_t m_select;
- uint8_t m_block;
+ u8 m_select;
+ u8 m_block;
// internal accessors
int active_scs_slot_number() const;
@@ -133,79 +138,99 @@ namespace
cococart_slot_device &active_cts_slot();
// methods
- void set_select(uint8_t new_select);
- DECLARE_READ8_MEMBER(ff7f_read);
- DECLARE_WRITE8_MEMBER(ff7f_write);
- void update_line(int slot_number, line ln);
-
- DECLARE_WRITE_LINE_MEMBER(multi_slot1_cart_w);
- DECLARE_WRITE_LINE_MEMBER(multi_slot1_nmi_w);
- DECLARE_WRITE_LINE_MEMBER(multi_slot1_halt_w);
- DECLARE_WRITE_LINE_MEMBER(multi_slot2_cart_w);
- DECLARE_WRITE_LINE_MEMBER(multi_slot2_nmi_w);
- DECLARE_WRITE_LINE_MEMBER(multi_slot2_halt_w);
- DECLARE_WRITE_LINE_MEMBER(multi_slot3_cart_w);
- DECLARE_WRITE_LINE_MEMBER(multi_slot3_nmi_w);
- DECLARE_WRITE_LINE_MEMBER(multi_slot3_halt_w);
- DECLARE_WRITE_LINE_MEMBER(multi_slot4_cart_w);
- DECLARE_WRITE_LINE_MEMBER(multi_slot4_nmi_w);
- DECLARE_WRITE_LINE_MEMBER(multi_slot4_halt_w);
+ void set_select(u8 new_select);
+ u8 ff7f_read();
+ void ff7f_write(u8 data);
};
};
+// ======================> dragon_multipak_device
+
+class dragon_multipak_device : public coco_multipak_device
+{
+public:
+ // construction/destruction
+ dragon_multipak_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock);
+
+protected:
+ // optional information overrides
+ virtual void device_add_mconfig(machine_config &config) override ATTR_COLD;
+};
+
+
/***************************************************************************
IMPLEMENTATION
***************************************************************************/
static void coco_cart_slot1_3(device_slot_interface &device)
{
- device.option_add("rs232", COCO_RS232);
- device.option_add("dcmodem", COCO_DCMODEM);
- device.option_add("orch90", COCO_ORCH90);
- device.option_add("ssc", COCO_SSC);
- device.option_add("games_master", COCO_PAK_GMC);
- device.option_add("banked_16k", COCO_PAK_BANKED);
- device.option_add("pak", COCO_PAK);
+ coco_cart_add_basic_devices(device);
}
+
static void coco_cart_slot4(device_slot_interface &device)
{
- device.option_add("cc2hdb1", COCO2_HDB1);
- device.option_add("cc3hdb1", COCO3_HDB1);
- device.option_add("fdcv11", COCO_FDC_V11);
- device.option_add("rs232", COCO_RS232);
- device.option_add("dcmodem", COCO_DCMODEM);
- device.option_add("orch90", COCO_ORCH90);
- device.option_add("ssc", COCO_SSC);
- device.option_add("games_master", COCO_PAK_GMC);
- device.option_add("banked_16k", COCO_PAK_BANKED);
- device.option_add("pak", COCO_PAK);
+ coco_cart_add_basic_devices(device);
+ coco_cart_add_fdcs(device);
}
void coco_multipak_device::device_add_mconfig(machine_config &config)
{
COCOCART_SLOT(config, m_slots[0], DERIVED_CLOCK(1, 1), coco_cart_slot1_3, nullptr);
- m_slots[0]->cart_callback().set(FUNC(coco_multipak_device::multi_slot1_cart_w));
- m_slots[0]->nmi_callback().set(FUNC(coco_multipak_device::multi_slot1_nmi_w));
- m_slots[0]->halt_callback().set(FUNC(coco_multipak_device::multi_slot1_halt_w));
+ m_slots[0]->cart_callback().set([this](int state) { update_line(1, line::CART); });
+ m_slots[0]->nmi_callback().set([this](int state) { update_line(1, line::NMI); });
+ m_slots[0]->halt_callback().set([this](int state) { update_line(1, line::HALT); });
COCOCART_SLOT(config, m_slots[1], DERIVED_CLOCK(1, 1), coco_cart_slot1_3, nullptr);
- m_slots[1]->cart_callback().set(FUNC(coco_multipak_device::multi_slot2_cart_w));
- m_slots[1]->nmi_callback().set(FUNC(coco_multipak_device::multi_slot2_nmi_w));
- m_slots[1]->halt_callback().set(FUNC(coco_multipak_device::multi_slot2_halt_w));
+ m_slots[1]->cart_callback().set([this](int state) { update_line(2, line::CART); });
+ m_slots[1]->nmi_callback().set([this](int state) { update_line(2, line::NMI); });
+ m_slots[1]->halt_callback().set([this](int state) { update_line(2, line::HALT); });
COCOCART_SLOT(config, m_slots[2], DERIVED_CLOCK(1, 1), coco_cart_slot1_3, nullptr);
- m_slots[2]->cart_callback().set(FUNC(coco_multipak_device::multi_slot3_cart_w));
- m_slots[2]->nmi_callback().set(FUNC(coco_multipak_device::multi_slot3_nmi_w));
- m_slots[2]->halt_callback().set(FUNC(coco_multipak_device::multi_slot3_halt_w));
- COCOCART_SLOT(config, m_slots[3], DERIVED_CLOCK(1, 1), coco_cart_slot4, "fdcv11");
- m_slots[3]->cart_callback().set(FUNC(coco_multipak_device::multi_slot4_cart_w));
- m_slots[3]->nmi_callback().set(FUNC(coco_multipak_device::multi_slot4_nmi_w));
- m_slots[3]->halt_callback().set(FUNC(coco_multipak_device::multi_slot4_halt_w));
+ 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, "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); });
+}
+
+
+static void dragon_cart_slot1_3(device_slot_interface &device)
+{
+ dragon_cart_add_basic_devices(device);
+}
+
+static void dragon_cart_slot4(device_slot_interface &device)
+{
+ dragon_cart_add_basic_devices(device);
+ dragon_cart_add_fdcs(device);
+}
+
+
+void dragon_multipak_device::device_add_mconfig(machine_config &config)
+{
+ COCOCART_SLOT(config, m_slots[0], DERIVED_CLOCK(1, 1), dragon_cart_slot1_3, nullptr);
+ m_slots[0]->cart_callback().set([this](int state) { update_line(1, line::CART); });
+ m_slots[0]->nmi_callback().set([this](int state) { update_line(1, line::NMI); });
+ m_slots[0]->halt_callback().set([this](int state) { update_line(1, line::HALT); });
+ COCOCART_SLOT(config, m_slots[1], DERIVED_CLOCK(1, 1), dragon_cart_slot1_3, nullptr);
+ m_slots[1]->cart_callback().set([this](int state) { update_line(2, line::CART); });
+ m_slots[1]->nmi_callback().set([this](int state) { update_line(2, line::NMI); });
+ m_slots[1]->halt_callback().set([this](int state) { update_line(2, line::HALT); });
+ COCOCART_SLOT(config, m_slots[2], DERIVED_CLOCK(1, 1), dragon_cart_slot1_3, nullptr);
+ 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), dragon_cart_slot4, "dragon_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); });
}
INPUT_PORTS_START( coco_multipack )
PORT_START( SWITCH_CONFIG_TAG )
- PORT_CONFNAME( 0x03, 0x03, "Multi-Pak Slot Switch" ) PORT_CHANGED_MEMBER(DEVICE_SELF, coco_multipak_device, switch_changed, 0)
+ PORT_CONFNAME( 0x03, 0x03, "Multi-Pak Slot Switch" ) PORT_CHANGED_MEMBER(DEVICE_SELF, FUNC(coco_multipak_device::switch_changed), 0)
PORT_CONFSETTING( 0x00, "Slot 1" )
PORT_CONFSETTING( 0x01, "Slot 2" )
PORT_CONFSETTING( 0x02, "Slot 3" )
@@ -217,6 +242,7 @@ INPUT_PORTS_END
//**************************************************************************
DEFINE_DEVICE_TYPE_PRIVATE(COCO_MULTIPAK, device_cococart_interface, coco_multipak_device, "coco_multipack", "CoCo Multi-Pak Interface")
+DEFINE_DEVICE_TYPE_PRIVATE(DRAGON_MULTIPAK, device_cococart_interface, dragon_multipak_device, "dragon_multipack", "Dragon Multi-Pak Interface")
@@ -237,13 +263,22 @@ ioport_constructor coco_multipak_device::device_input_ports() const
// coco_multipak_device - constructor
//-------------------------------------------------
-coco_multipak_device::coco_multipak_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
- : device_t(mconfig, COCO_MULTIPAK, tag, owner, clock)
+coco_multipak_device::coco_multipak_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, u32 clock)
+ : device_t(mconfig, type, tag, owner, clock)
, device_cococart_interface(mconfig, *this)
, m_slots(*this, "slot%u", 1), m_select(0), m_block(0)
{
}
+coco_multipak_device::coco_multipak_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock)
+ : coco_multipak_device(mconfig, COCO_MULTIPAK, tag, owner, clock)
+{
+}
+
+dragon_multipak_device::dragon_multipak_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock)
+ : coco_multipak_device(mconfig, DRAGON_MULTIPAK, tag, owner, clock)
+{
+}
//-------------------------------------------------
// device_start - device-specific startup
@@ -252,7 +287,7 @@ coco_multipak_device::coco_multipak_device(const machine_config &mconfig, const
void coco_multipak_device::device_start()
{
// install $FF7F handler
- install_readwrite_handler(0xFF7F, 0xFF7F, read8_delegate(FUNC(coco_multipak_device::ff7f_read), this),write8_delegate(FUNC(coco_multipak_device::ff7f_write), this));
+ install_readwrite_handler(0xFF7F, 0xFF7F, read8smo_delegate(*this, FUNC(coco_multipak_device::ff7f_read)), write8smo_delegate(*this, FUNC(coco_multipak_device::ff7f_write)));
// initial state
m_select = 0xFF;
@@ -351,8 +386,10 @@ cococart_slot_device &coco_multipak_device::active_cts_slot()
// set_select
//-------------------------------------------------
-void coco_multipak_device::set_select(uint8_t new_select)
+void coco_multipak_device::set_select(u8 new_select)
{
+ LOGSWITCH( "set_select: 0x%02X\n", new_select);
+
// identify old value for CART, in case this needs to change
cococart_slot_device::line_value old_cart = active_cts_slot().get_line_value(line::CART);
@@ -372,7 +409,7 @@ void coco_multipak_device::set_select(uint8_t new_select)
// ff7f_read
//-------------------------------------------------
-READ8_MEMBER(coco_multipak_device::ff7f_read)
+u8 coco_multipak_device::ff7f_read()
{
return m_select | 0xcc;
}
@@ -381,7 +418,7 @@ READ8_MEMBER(coco_multipak_device::ff7f_read)
// ff7f_write
//-------------------------------------------------
-WRITE8_MEMBER(coco_multipak_device::ff7f_write)
+void coco_multipak_device::ff7f_write(u8 data)
{
m_block = 0xff;
set_select(data);
@@ -402,6 +439,7 @@ void coco_multipak_device::update_line(int slot_number, line ln)
case line::CART:
// only propagate if this is coming from the slot specified
propagate = slot_number == active_cts_slot_number();
+ LOGCART( "update_line: slot: %d, line: CART, value: %s, propogate: %s\n", slot_number, owning_slot().line_value_string(slot(slot_number).get_line_value(ln)), propagate ? "yes" : "no" );
break;
case line::NMI:
@@ -437,7 +475,7 @@ void coco_multipak_device::set_sound_enable(bool sound_enable)
// get_cart_base
//-------------------------------------------------
-uint8_t* coco_multipak_device::get_cart_base()
+u8 *coco_multipak_device::get_cart_base()
{
return active_cts_slot().get_cart_base();
}
@@ -447,7 +485,7 @@ uint8_t* coco_multipak_device::get_cart_base()
// get_cart_size
//-------------------------------------------------
-uint32_t coco_multipak_device::get_cart_size()
+u32 coco_multipak_device::get_cart_size()
{
return active_cts_slot().get_cart_size();
}
@@ -457,9 +495,9 @@ uint32_t coco_multipak_device::get_cart_size()
// cts_read
//-------------------------------------------------
-READ8_MEMBER(coco_multipak_device::cts_read)
+u8 coco_multipak_device::cts_read(offs_t offset)
{
- return active_cts_slot().cts_read(space, offset);
+ return active_cts_slot().cts_read(offset);
}
@@ -467,9 +505,9 @@ READ8_MEMBER(coco_multipak_device::cts_read)
// cts_write
//-------------------------------------------------
-WRITE8_MEMBER(coco_multipak_device::cts_write)
+void coco_multipak_device::cts_write(offs_t offset, u8 data)
{
- active_cts_slot().cts_write(space, offset, data);
+ active_cts_slot().cts_write(offset, data);
}
@@ -477,9 +515,9 @@ WRITE8_MEMBER(coco_multipak_device::cts_write)
// scs_read
//-------------------------------------------------
-READ8_MEMBER(coco_multipak_device::scs_read)
+u8 coco_multipak_device::scs_read(offs_t offset)
{
- return active_scs_slot().scs_read(space, offset);
+ return active_scs_slot().scs_read(offset);
}
@@ -487,31 +525,13 @@ READ8_MEMBER(coco_multipak_device::scs_read)
// scs_write
//-------------------------------------------------
-WRITE8_MEMBER(coco_multipak_device::scs_write)
+void coco_multipak_device::scs_write(offs_t offset, u8 data)
{
- active_scs_slot().scs_write(space, offset, data);
+ active_scs_slot().scs_write(offset, data);
}
//-------------------------------------------------
-// multiX_slotX_[cart|nmi|halt] trampolines
-//-------------------------------------------------
-
-WRITE_LINE_MEMBER(coco_multipak_device::multi_slot1_cart_w) { update_line(1, line::CART); }
-WRITE_LINE_MEMBER(coco_multipak_device::multi_slot1_nmi_w) { update_line(1, line::NMI); }
-WRITE_LINE_MEMBER(coco_multipak_device::multi_slot1_halt_w) { update_line(1, line::HALT); }
-WRITE_LINE_MEMBER(coco_multipak_device::multi_slot2_cart_w) { update_line(2, line::CART); }
-WRITE_LINE_MEMBER(coco_multipak_device::multi_slot2_nmi_w) { update_line(2, line::NMI); }
-WRITE_LINE_MEMBER(coco_multipak_device::multi_slot2_halt_w) { update_line(2, line::HALT); }
-WRITE_LINE_MEMBER(coco_multipak_device::multi_slot3_cart_w) { update_line(3, line::CART); }
-WRITE_LINE_MEMBER(coco_multipak_device::multi_slot3_nmi_w) { update_line(3, line::NMI); }
-WRITE_LINE_MEMBER(coco_multipak_device::multi_slot3_halt_w) { update_line(3, line::HALT); }
-WRITE_LINE_MEMBER(coco_multipak_device::multi_slot4_cart_w) { update_line(4, line::CART); }
-WRITE_LINE_MEMBER(coco_multipak_device::multi_slot4_nmi_w) { update_line(4, line::NMI); }
-WRITE_LINE_MEMBER(coco_multipak_device::multi_slot4_halt_w) { update_line(4, line::HALT); }
-
-
-//-------------------------------------------------
// cartridge_space
//-------------------------------------------------
diff --git a/src/devices/bus/coco/coco_multi.h b/src/devices/bus/coco/coco_multi.h
index eb66aee9660..f4f3ea23db5 100644
--- a/src/devices/bus/coco/coco_multi.h
+++ b/src/devices/bus/coco/coco_multi.h
@@ -1,7 +1,7 @@
// license:BSD-3-Clause
// copyright-holders:Nathan Woods
-#ifndef MAME_BUS_COCO_COCO_MULTIPAK_H
-#define MAME_BUS_COCO_COCO_MULTIPAK_H
+#ifndef MAME_BUS_COCO_COCO_MULTI_H
+#define MAME_BUS_COCO_COCO_MULTI_H
#pragma once
@@ -9,5 +9,6 @@
// device type definition
DECLARE_DEVICE_TYPE(COCO_MULTIPAK, device_cococart_interface)
+DECLARE_DEVICE_TYPE(DRAGON_MULTIPAK, device_cococart_interface)
-#endif // MAME_BUS_COCO_COCO_MULTIPAK_H
+#endif // MAME_BUS_COCO_COCO_MULTI_H
diff --git a/src/devices/bus/coco/coco_orch90.cpp b/src/devices/bus/coco/coco_orch90.cpp
index e7506be7c2b..33151fb5d73 100644
--- a/src/devices/bus/coco/coco_orch90.cpp
+++ b/src/devices/bus/coco/coco_orch90.cpp
@@ -30,7 +30,6 @@
#include "cococart.h"
#include "sound/dac.h"
-#include "sound/volt_reg.h"
#include "speaker.h"
@@ -58,7 +57,7 @@ namespace
{
public:
// construction/destruction
- coco_orch90_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
+ coco_orch90_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock)
: device_t(mconfig, COCO_ORCH90, tag, owner, clock)
, device_cococart_interface(mconfig, *this)
, m_eprom(*this, "eprom")
@@ -67,16 +66,16 @@ namespace
{
}
+ protected:
// optional information overrides
- virtual void device_add_mconfig(machine_config &config) override;
+ virtual void device_add_mconfig(machine_config &config) override ATTR_COLD;
- protected:
// device-level overrides
virtual void device_start() override
{
// install handlers
- install_write_handler(0xFF7A, 0xFF7A, write8_delegate(FUNC(coco_orch90_device::write_left), this));
- install_write_handler(0xFF7B, 0xFF7B, write8_delegate(FUNC(coco_orch90_device::write_right), this));
+ install_write_handler(0xFF7A, 0xFF7A, write8smo_delegate(*this, FUNC(coco_orch90_device::write_left)));
+ install_write_handler(0xFF7B, 0xFF7B, write8smo_delegate(*this, FUNC(coco_orch90_device::write_right)));
// Orch-90 ties CART to Q
set_line_value(line::CART, line_value::Q);
@@ -88,55 +87,50 @@ namespace
}
// CoCo cartridge level overrides
- virtual uint8_t *get_cart_base() override
+ virtual u8 *get_cart_base() override
{
return m_eprom->base();
}
- virtual memory_region* get_cart_memregion() override
+ virtual memory_region *get_cart_memregion() override
{
return m_eprom;
}
- virtual DECLARE_READ8_MEMBER(cts_read) override;
+ virtual u8 cts_read(offs_t offset) override;
private:
- WRITE8_MEMBER(write_left) { m_ldac->write(data); }
- WRITE8_MEMBER(write_right) { m_rdac->write(data); }
+ void write_left(u8 data) { m_ldac->write(data); }
+ void write_right(u8 data) { m_rdac->write(data); }
// internal state
required_memory_region m_eprom;
required_device<dac_byte_interface> m_ldac;
required_device<dac_byte_interface> m_rdac;
};
-};
-
-//**************************************************************************
-// MACHINE AND ROM DECLARATIONS
-//**************************************************************************
-void coco_orch90_device::device_add_mconfig(machine_config &config)
-{
- SPEAKER(config, "lspeaker").front_left();
- SPEAKER(config, "rspeaker").front_right();
- DAC_8BIT_R2R(config, m_ldac, 0).add_route(ALL_OUTPUTS, "lspeaker", 0.5); // ls374.ic5 + r7 (8x20k) + r9 (8x10k)
- DAC_8BIT_R2R(config, m_rdac, 0).add_route(ALL_OUTPUTS, "rspeaker", 0.5); // ls374.ic4 + r6 (8x20k) + r8 (8x10k)
- voltage_regulator_device &vref(VOLTAGE_REGULATOR(config, "vref"));
- vref.add_route(0, "ldac", 1.0, DAC_VREF_POS_INPUT); vref.add_route(0, "ldac", -1.0, DAC_VREF_NEG_INPUT);
- vref.add_route(0, "rdac", 1.0, DAC_VREF_POS_INPUT); vref.add_route(0, "rdac", -1.0, DAC_VREF_NEG_INPUT);
-}
+ //**************************************************************************
+ // MACHINE AND ROM DECLARATIONS
+ //**************************************************************************
-//-------------------------------------------------
-// cts_read
-//-------------------------------------------------
+ void coco_orch90_device::device_add_mconfig(machine_config &config)
+ {
+ SPEAKER(config, "speaker", 2).front();
+ DAC_8BIT_R2R(config, m_ldac, 0).add_route(ALL_OUTPUTS, "speaker", 0.5, 0); // ls374.ic5 + r7 (8x20k) + r9 (8x10k)
+ DAC_8BIT_R2R(config, m_rdac, 0).add_route(ALL_OUTPUTS, "speaker", 0.5, 1); // ls374.ic4 + r6 (8x20k) + r8 (8x10k)
+ }
-READ8_MEMBER(coco_orch90_device::cts_read)
-{
- return m_eprom->base()[offset & 0x1fff];
-}
+ //-------------------------------------------------
+ // cts_read
+ //-------------------------------------------------
+ u8 coco_orch90_device::cts_read(offs_t offset)
+ {
+ return m_eprom->base()[offset & 0x1fff];
+ }
+}
//**************************************************************************
// DEVICE DECLARATION
//**************************************************************************
diff --git a/src/devices/bus/coco/coco_pak.cpp b/src/devices/bus/coco/coco_pak.cpp
index dea7632e7dc..b01698633eb 100644
--- a/src/devices/bus/coco/coco_pak.cpp
+++ b/src/devices/bus/coco/coco_pak.cpp
@@ -55,14 +55,14 @@ DEFINE_DEVICE_TYPE(COCO_PAK, coco_pak_device, "cocopak", "CoCo Program PAK")
//-------------------------------------------------
// coco_pak_device - constructor
//-------------------------------------------------
-coco_pak_device::coco_pak_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock)
+coco_pak_device::coco_pak_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, u32 clock)
: device_t(mconfig, type, tag, owner, clock)
, device_cococart_interface(mconfig, *this)
, m_cart(nullptr), m_eprom(*this, CARTSLOT_TAG), m_autostart(*this, CART_AUTOSTART_TAG)
{
}
-coco_pak_device::coco_pak_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
+coco_pak_device::coco_pak_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock)
: coco_pak_device(mconfig, COCO_PAK, tag, owner, clock)
{
}
@@ -99,7 +99,7 @@ const tiny_rom_entry *coco_pak_device::device_rom_region() const
// get_cart_size
//-------------------------------------------------
-uint32_t coco_pak_device::get_cart_size()
+u32 coco_pak_device::get_cart_size()
{
return 0x8000;
}
@@ -125,7 +125,7 @@ void coco_pak_device::device_reset()
get_cart_base
-------------------------------------------------*/
-uint8_t* coco_pak_device::get_cart_base()
+u8 *coco_pak_device::get_cart_base()
{
return m_eprom->base();
}
@@ -134,7 +134,7 @@ uint8_t* coco_pak_device::get_cart_base()
get_cart_memregion
-------------------------------------------------*/
-memory_region* coco_pak_device::get_cart_memregion()
+memory_region *coco_pak_device::get_cart_memregion()
{
return m_eprom;
}
@@ -143,7 +143,7 @@ memory_region* coco_pak_device::get_cart_memregion()
// cts_read
//-------------------------------------------------
-READ8_MEMBER(coco_pak_device::cts_read)
+u8 coco_pak_device::cts_read(offs_t offset)
{
if (offset < m_eprom->bytes())
return m_eprom->base()[offset];
@@ -171,12 +171,12 @@ DEFINE_DEVICE_TYPE(COCO_PAK_BANKED, coco_pak_banked_device, "cocopak_banked", "C
// coco_pak_device - constructor
//-------------------------------------------------
-coco_pak_banked_device::coco_pak_banked_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock)
+coco_pak_banked_device::coco_pak_banked_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, u32 clock)
: coco_pak_device(mconfig, type, tag, owner, clock)
, m_pos(0)
{
}
-coco_pak_banked_device::coco_pak_banked_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
+coco_pak_banked_device::coco_pak_banked_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock)
: coco_pak_banked_device(mconfig, COCO_PAK_BANKED, tag, owner, clock)
{
}
@@ -216,7 +216,7 @@ void coco_pak_banked_device::device_reset()
// get_cart_base
//-------------------------------------------------
-uint8_t *coco_pak_banked_device::get_cart_base()
+u8 *coco_pak_banked_device::get_cart_base()
{
return m_eprom->base() + (m_pos * 0x4000) % m_eprom->bytes();
}
@@ -225,7 +225,7 @@ uint8_t *coco_pak_banked_device::get_cart_base()
// get_cart_size
//-------------------------------------------------
-uint32_t coco_pak_banked_device::get_cart_size()
+u32 coco_pak_banked_device::get_cart_size()
{
return 0x4000;
}
@@ -234,7 +234,7 @@ uint32_t coco_pak_banked_device::get_cart_size()
// cts_read
//-------------------------------------------------
-READ8_MEMBER(coco_pak_banked_device::cts_read)
+u8 coco_pak_banked_device::cts_read(offs_t offset)
{
return m_eprom->base()[(m_pos * 0x4000) % m_eprom->bytes() | offset];
}
@@ -243,7 +243,7 @@ READ8_MEMBER(coco_pak_banked_device::cts_read)
// scs_write
//-------------------------------------------------
-WRITE8_MEMBER(coco_pak_banked_device::scs_write)
+void coco_pak_banked_device::scs_write(offs_t offset, u8 data)
{
switch(offset)
{
diff --git a/src/devices/bus/coco/coco_pak.h b/src/devices/bus/coco/coco_pak.h
index 105ca7d319b..b071ee1ee2f 100644
--- a/src/devices/bus/coco/coco_pak.h
+++ b/src/devices/bus/coco/coco_pak.h
@@ -19,23 +19,23 @@ class coco_pak_device :
{
public:
// construction/destruction
- coco_pak_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
+ coco_pak_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock);
// optional information overrides
- virtual const tiny_rom_entry *device_rom_region() const override;
- virtual ioport_constructor device_input_ports() const override;
+ virtual const tiny_rom_entry *device_rom_region() const override ATTR_COLD;
+ virtual ioport_constructor device_input_ports() const override ATTR_COLD;
- virtual uint8_t* get_cart_base() override;
- virtual uint32_t get_cart_size() override;
- virtual memory_region* get_cart_memregion() override;
+ virtual u8 *get_cart_base() override;
+ virtual u32 get_cart_size() override;
+ virtual memory_region *get_cart_memregion() override;
protected:
- coco_pak_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock);
+ coco_pak_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;
- virtual DECLARE_READ8_MEMBER(cts_read) override;
+ virtual void device_start() override ATTR_COLD;
+ virtual void device_reset() override ATTR_COLD;
+ virtual u8 cts_read(offs_t offset) override;
// internal state
device_image_interface *m_cart;
@@ -50,22 +50,22 @@ class coco_pak_banked_device : public coco_pak_device
{
public:
// construction/destruction
- coco_pak_banked_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
+ coco_pak_banked_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock);
protected:
- coco_pak_banked_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock);
+ coco_pak_banked_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, u32 clock);
// device-level overrides
- virtual const tiny_rom_entry *device_rom_region() const override;
- virtual void device_start() override;
- virtual void device_reset() override;
- virtual uint8_t *get_cart_base() override;
- virtual uint32_t get_cart_size() override;
- virtual DECLARE_READ8_MEMBER(cts_read) override;
- virtual DECLARE_WRITE8_MEMBER(scs_write) override;
+ virtual const tiny_rom_entry *device_rom_region() const override ATTR_COLD;
+ virtual void device_start() override ATTR_COLD;
+ virtual void device_reset() override ATTR_COLD;
+ virtual u8 *get_cart_base() override;
+ virtual u32 get_cart_size() override;
+ virtual u8 cts_read(offs_t offset) override;
+ virtual void scs_write(offs_t offset, u8 data) override;
private:
- uint8_t m_pos;
+ u8 m_pos;
};
diff --git a/src/devices/bus/coco/coco_psg.cpp b/src/devices/bus/coco/coco_psg.cpp
new file mode 100644
index 00000000000..5f3d84c98da
--- /dev/null
+++ b/src/devices/bus/coco/coco_psg.cpp
@@ -0,0 +1,270 @@
+// license:BSD-3-Clause
+// copyright-holders:Roberto Fernandez,Nigel Barnes
+// thanks-to:Ed Snider
+/***************************************************************************
+
+ coco_psg.cpp
+
+ Code for emulating the CoCo PSG. A banked switched ROM and RAM cartridge
+ with a YM2149 programmable sound generator and two digital Atari-compatible
+ joystick ports.
+
+ Cartridge by Ed Snider.
+
+ CoCo PSG site:
+ https://thezippsterzone.com/2018/05/08/coco-psg/
+
+ CoCo PSG manual:
+ https://thezippsterzone.com/wp-content/uploads/2018/05/coco-psg-users-manual.pdf
+
+***************************************************************************/
+
+#include "emu.h"
+#include "coco_psg.h"
+#include "speaker.h"
+
+
+//**************************************************************************
+// GLOBAL VARIABLES
+//**************************************************************************
+
+DEFINE_DEVICE_TYPE_PRIVATE(COCO_PSG, device_cococart_interface, coco_psg_device, "coco_psg", "CoCo PSG")
+
+
+//-------------------------------------------------
+// ROM( cocopsg )
+//-------------------------------------------------
+
+ROM_START(cocopsg)
+ ROM_REGION(0x80000, "flash", 0)
+ ROM_LOAD("psg_firmware_v1.bin", 0x0000, 0x80000, CRC(5de614f8) SHA1(9c7c8a5cc419ca1aca4d1c5e9f1195997c2bc95c))
+ROM_END
+
+//-------------------------------------------------
+// rom_region - device-specific ROM region
+//-------------------------------------------------
+
+const tiny_rom_entry *coco_psg_device::device_rom_region() const
+{
+ return ROM_NAME(cocopsg);
+}
+
+//-------------------------------------------------
+// INPUT_PORTS( cocopsg )
+//-------------------------------------------------
+
+static INPUT_PORTS_START(cocopsg)
+ PORT_START("GAMEPORT_A")
+ PORT_BIT(0x01, IP_ACTIVE_LOW, IPT_JOYSTICK_UP) PORT_8WAY PORT_PLAYER(1)
+ PORT_BIT(0x02, IP_ACTIVE_LOW, IPT_JOYSTICK_DOWN) PORT_8WAY PORT_PLAYER(1)
+ PORT_BIT(0x04, IP_ACTIVE_LOW, IPT_JOYSTICK_LEFT) PORT_8WAY PORT_PLAYER(1)
+ PORT_BIT(0x08, IP_ACTIVE_LOW, IPT_JOYSTICK_RIGHT) PORT_8WAY PORT_PLAYER(1)
+ PORT_BIT(0x10, IP_ACTIVE_LOW, IPT_BUTTON1) PORT_PLAYER(1)
+ PORT_BIT(0x20, IP_ACTIVE_LOW, IPT_BUTTON2) PORT_PLAYER(1)
+ PORT_BIT(0x40, IP_ACTIVE_LOW, IPT_UNUSED)
+ PORT_BIT(0x80, IP_ACTIVE_LOW, IPT_UNUSED)
+
+ PORT_START("GAMEPORT_B")
+ PORT_BIT(0x01, IP_ACTIVE_LOW, IPT_JOYSTICK_UP) PORT_8WAY PORT_PLAYER(2)
+ PORT_BIT(0x02, IP_ACTIVE_LOW, IPT_JOYSTICK_DOWN) PORT_8WAY PORT_PLAYER(2)
+ PORT_BIT(0x04, IP_ACTIVE_LOW, IPT_JOYSTICK_LEFT) PORT_8WAY PORT_PLAYER(2)
+ PORT_BIT(0x08, IP_ACTIVE_LOW, IPT_JOYSTICK_RIGHT) PORT_8WAY PORT_PLAYER(2)
+ PORT_BIT(0x10, IP_ACTIVE_LOW, IPT_BUTTON1) PORT_PLAYER(2)
+ PORT_BIT(0x20, IP_ACTIVE_LOW, IPT_BUTTON2) PORT_PLAYER(2)
+ PORT_BIT(0x40, IP_ACTIVE_LOW, IPT_UNUSED)
+ PORT_BIT(0x80, IP_ACTIVE_LOW, IPT_UNUSED)
+INPUT_PORTS_END
+
+//-------------------------------------------------
+// input_ports - device-specific input ports
+//-------------------------------------------------
+
+ioport_constructor coco_psg_device::device_input_ports() const
+{
+ return INPUT_PORTS_NAME(cocopsg);
+}
+
+//-------------------------------------------------
+// device_add_mconfig - add device configuration
+//-------------------------------------------------
+
+void coco_psg_device::device_add_mconfig(machine_config &config)
+{
+ SPEAKER(config, "speaker").front_center();
+ YM2149(config, m_psg, 1_MHz_XTAL);
+ m_psg->port_a_read_callback().set_ioport("GAMEPORT_A");
+ m_psg->port_b_read_callback().set_ioport("GAMEPORT_B");
+ m_psg->add_route(ALL_OUTPUTS, "speaker", 1.0);
+
+ SST_39SF040(config, "flash");
+}
+
+
+//-------------------------------------------------
+// coco_psg_device - constructor
+//-------------------------------------------------
+
+coco_psg_device::coco_psg_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock)
+ : device_t(mconfig, COCO_PSG, tag, owner, clock)
+ , device_cococart_interface(mconfig, *this)
+ , m_psg(*this, "psg")
+ , m_flash(*this, "flash")
+{
+}
+
+//-------------------------------------------------
+// device_start - device-specific startup
+//-------------------------------------------------
+
+void coco_psg_device::device_start()
+{
+ m_sram = std::make_unique<u8[]>(0x80000);
+
+ /* registers are set to a default of zero */
+ m_bank[0] = 0x00;
+ m_bank[1] = 0x00;
+ m_control = 0x00;
+
+ set_line_value(line::CART, line_value::Q);
+
+ /* register for save states */
+ save_item(NAME(m_bank));
+ save_item(NAME(m_control));
+ save_pointer(NAME(m_sram), 0x80000);
+}
+
+//-------------------------------------------------
+// device_reset - device-specific reset
+//-------------------------------------------------
+
+void coco_psg_device::device_reset()
+{
+ install_write_handler(0xb555, 0xb555, write8sm_delegate(*this, FUNC(coco_psg_device::flash5555_w)));
+ install_write_handler(0xbaaa, 0xbaaa, write8sm_delegate(*this, FUNC(coco_psg_device::flash2aaa_w)));
+}
+
+void coco_psg_device::flash2aaa_w(offs_t offset, u8 data)
+{
+ if (BIT(m_control, 5) && BIT(m_control, 3))
+ {
+ m_flash->write(0x2aaa, data);
+ }
+}
+
+void coco_psg_device::flash5555_w(offs_t offset, u8 data)
+{
+ if (BIT(m_control, 5) && BIT(m_control, 3))
+ {
+ m_flash->write(0x5555, data);
+ }
+}
+
+//-------------------------------------------------
+// scs_read
+//-------------------------------------------------
+
+u8 coco_psg_device::scs_read(offs_t offset)
+{
+ u8 data = 0x00;
+
+ switch (offset)
+ {
+ case 0x1a:
+ case 0x1b:
+ /* memory bank register */
+ data = m_bank[BIT(offset, 0)];
+ break;
+
+ case 0x1f:
+ /* ym data port */
+ data = m_psg->data_r();
+ break;
+ }
+
+ return data;
+}
+
+//-------------------------------------------------
+// scs_write
+//-------------------------------------------------
+
+void coco_psg_device::scs_write(offs_t offset, u8 data)
+{
+ switch (offset)
+ {
+ case 0x1a:
+ case 0x1b:
+ /* memory bank register */
+ m_bank[BIT(offset, 0)] = data;
+ break;
+
+ case 0x1d:
+ /* control register
+ BIT FUNCTION
+ 0 YM2149 MASTER CLOCK; 0=2MHz, 1=1MHz
+ 1 Gameport A SEL signal (pin 7 of controller port A)
+ 2 Gameport B SEL signal (pin 7 of controller port B)
+ 3 Write Enable (for FLASH/SRAM); 0=disabled, 1=enabled
+ 4 Autostart enable; 0=enabled, 1=disabled
+ 5 FLASH programming enable; 0=disabled, 1=enabled
+ 6 not used
+ 7 not used
+ */
+ m_control = data;
+
+ /* bit 0 - YM2149 MASTER CLOCK; 0=2MHz, 1=1MHz */
+ if (BIT(data, 0))
+ m_psg->set_pin26_low_w();
+ else
+ m_psg->set_pin26_high_w();
+
+ /* bit 4 - Autostart enable; 0=enabled, 1=disabled */
+ set_line_value(line::CART, BIT(data, 4) ? line_value::CLEAR : line_value::Q);
+ break;
+
+ case 0x1e:
+ /* ym register select port*/
+ m_psg->address_w(data & 0x0f);
+ break;
+ case 0x1f:
+ /* ym data port */
+ m_psg->data_w(data);
+ break;
+ }
+}
+
+
+//-------------------------------------------------
+// cts_read
+//-------------------------------------------------
+
+u8 coco_psg_device::cts_read(offs_t offset)
+{
+ u8 data = 0x00;
+
+ if (m_bank[BIT(offset, 13)] & 0x80)
+ {
+ data = m_sram[(offset & 0x1fff) | (m_bank[BIT(offset, 13)] & 0x3f) << 13];
+ }
+ else
+ {
+ data = m_flash->read_raw((offset & 0x1fff) | (m_bank[BIT(offset, 13)] & 0x3f) << 13);
+ }
+
+ return data;
+}
+
+//-------------------------------------------------
+// cts_write
+//-------------------------------------------------
+
+void coco_psg_device::cts_write(offs_t offset, u8 data)
+{
+ if (BIT(m_control, 3))
+ {
+ if (m_bank[BIT(offset, 13)] & 0x80)
+ {
+ m_sram[(offset & 0x1fff) | (m_bank[BIT(offset, 13)] & 0x3f) << 13] = data;
+ }
+ }
+}
diff --git a/src/devices/bus/coco/coco_psg.h b/src/devices/bus/coco/coco_psg.h
new file mode 100644
index 00000000000..7df3e1054fd
--- /dev/null
+++ b/src/devices/bus/coco/coco_psg.h
@@ -0,0 +1,58 @@
+// license:BSD-3-Clause
+// copyright-holders:Roberto Fernandez,Nigel Barnes
+#ifndef MAME_BUS_COCO_COCO_PSG_H
+#define MAME_BUS_COCO_COCO_PSG_H
+
+#pragma once
+
+#include "cococart.h"
+#include "machine/intelfsh.h"
+#include "sound/ay8910.h"
+
+
+//**************************************************************************
+// TYPE DEFINITIONS
+//**************************************************************************
+
+// ======================> coco_psg_device
+
+class coco_psg_device :
+ public device_t,
+ public device_cococart_interface
+{
+public:
+ // construction/destruction
+ coco_psg_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock);
+
+ // optional information overrides
+ virtual void device_add_mconfig(machine_config &config) override ATTR_COLD;
+ virtual const tiny_rom_entry *device_rom_region() const override ATTR_COLD;
+ virtual ioport_constructor device_input_ports() const override ATTR_COLD;
+
+protected:
+ // device-level overrides
+ virtual void device_start() override ATTR_COLD;
+ virtual void device_reset() override ATTR_COLD;
+
+ virtual u8 cts_read(offs_t offset) override;
+ virtual void cts_write(offs_t offset, u8 data) override;
+ virtual u8 scs_read(offs_t offset) override;
+ virtual void scs_write(offs_t offset, u8 data) override;
+
+private:
+ required_device<ay8910_device> m_psg;
+ required_device<sst_39sf040_device> m_flash;
+
+ void flash2aaa_w(offs_t offset, u8 data);
+ void flash5555_w(offs_t offset, u8 data);
+
+ std::unique_ptr<u8[]> m_sram;
+ u8 m_bank[2];
+ u8 m_control;
+};
+
+
+// device type definition
+DECLARE_DEVICE_TYPE(COCO_PSG, device_cococart_interface)
+
+#endif // MAME_BUS_COCO_COCO_PSG_H
diff --git a/src/devices/bus/coco/coco_ram.cpp b/src/devices/bus/coco/coco_ram.cpp
new file mode 100644
index 00000000000..c4dfe3500d9
--- /dev/null
+++ b/src/devices/bus/coco/coco_ram.cpp
@@ -0,0 +1,196 @@
+// license:BSD-3-Clause
+// copyright-holders:tim lindner
+/***************************************************************************
+
+ coco_ram.cpp
+
+ 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"
+
+//#define VERBOSE (LOG_GENERAL)
+#include "logmacro.h"
+
+#define RAM_SIZE 1024 * 1024
+#define MEB_TAG "meb"
+
+
+//**************************************************************************
+// TYPE DECLARATIONS
+//**************************************************************************
+
+namespace
+{
+ // ======================> coco_pak_ram_device
+
+ 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 ATTR_COLD;
+
+ protected:
+ // device-level overrides
+ virtual void device_start() override ATTR_COLD;
+ virtual void device_reset() override ATTR_COLD;
+ 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;
+ };
+};
+
+
+
+//**************************************************************************
+// GLOBAL VARIABLES
+//**************************************************************************
+
+DEFINE_DEVICE_TYPE_PRIVATE(COCO_PAK_RAM, device_cococart_interface, coco_pak_ram_device, "cocopakram", "Disto RAM Cartridge")
+
+
+
+//-------------------------------------------------
+// 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_slot(*this, MEB_TAG)
+{
+}
+
+
+
+//**************************************************************************
+// 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)
+{
+ 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); });
+}
+
+
+
+//-------------------------------------------------
+// device_start - device-specific startup
+//-------------------------------------------------
+
+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);
+}
+
+
+
+//-------------------------------------------------
+// device_reset - device-specific reset
+//-------------------------------------------------
+
+void coco_pak_ram_device::device_reset()
+{
+ m_offset = 0;
+}
+
+
+
+//-------------------------------------------------
+// scs_write
+//-------------------------------------------------
+
+void coco_pak_ram_device::scs_write(offs_t offset, u8 data)
+{
+ if (offset > 0x0f && offset < 0x18)
+ m_slot->meb_write(offset - 0x10, data);
+ else
+ {
+ 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);
+ }
+}
+
+
+
+//-------------------------------------------------
+// scs_read
+//-------------------------------------------------
+
+u8 coco_pak_ram_device::scs_read(offs_t offset)
+{
+ u8 data = 0x00;
+
+ if (offset > 0x0f && offset < 0x18)
+ {
+ data = m_slot->meb_read(offset - 0x10);
+ }
+ else
+ {
+ 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);
+ }
+
+ return data;
+}
diff --git a/src/devices/bus/coco/coco_ram.h b/src/devices/bus/coco/coco_ram.h
new file mode 100644
index 00000000000..a88874cc959
--- /dev/null
+++ b/src/devices/bus/coco/coco_ram.h
@@ -0,0 +1,14 @@
+// license:BSD-3-Clause
+// copyright-holders:tim lindner
+#ifndef MAME_BUS_COCO_COCO_RAM_H
+#define MAME_BUS_COCO_COCO_RAM_H
+
+#pragma once
+
+#include "cococart.h"
+
+// device type definition
+DECLARE_DEVICE_TYPE(COCO_PAK_RAM, device_cococart_interface)
+
+#endif // MAME_BUS_COCO_COCO_RAM_H
+
diff --git a/src/devices/bus/coco/coco_rs232.cpp b/src/devices/bus/coco/coco_rs232.cpp
index 5668034b80d..fbdea41fbf0 100644
--- a/src/devices/bus/coco/coco_rs232.cpp
+++ b/src/devices/bus/coco/coco_rs232.cpp
@@ -36,7 +36,7 @@ namespace
{
public:
// construction/destruction
- coco_rs232_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
+ coco_rs232_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock)
: device_t(mconfig, COCO_RS232, tag, owner, clock)
, device_cococart_interface(mconfig, *this)
, m_eprom(*this, "eprom")
@@ -45,9 +45,9 @@ namespace
}
// optional information overrides
- virtual void device_add_mconfig(machine_config &config) override;
+ virtual void device_add_mconfig(machine_config &config) override ATTR_COLD;
- WRITE_LINE_MEMBER(uart_irq_w)
+ void uart_irq_w(int state)
{
set_line_value(line::CART, state != 0);
}
@@ -57,24 +57,24 @@ namespace
virtual void device_start() override
{
install_readwrite_handler(0xFF68, 0xFF6B,
- read8sm_delegate(FUNC(mos6551_device::read), (mos6551_device *)m_uart),
- write8sm_delegate(FUNC(mos6551_device::write), (mos6551_device *)m_uart));
+ read8sm_delegate(*m_uart, FUNC(mos6551_device::read)),
+ write8sm_delegate(*m_uart, FUNC(mos6551_device::write)));
}
- virtual const tiny_rom_entry *device_rom_region() const override;
+ virtual const tiny_rom_entry *device_rom_region() const override ATTR_COLD;
// CoCo cartridge level overrides
- virtual uint8_t *get_cart_base() override
+ virtual u8 *get_cart_base() override
{
return m_eprom->base();
}
- virtual memory_region* get_cart_memregion() override
+ virtual memory_region *get_cart_memregion() override
{
return m_eprom;
}
- virtual DECLARE_READ8_MEMBER(cts_read) override;
+ virtual u8 cts_read(offs_t offset) override;
private:
// internal state
@@ -120,7 +120,7 @@ const tiny_rom_entry *coco_rs232_device::device_rom_region() const
// cts_read
//-------------------------------------------------
-READ8_MEMBER(coco_rs232_device::cts_read)
+u8 coco_rs232_device::cts_read(offs_t offset)
{
return m_eprom->base()[offset & 0x0fff];
}
diff --git a/src/devices/bus/coco/coco_ssc.cpp b/src/devices/bus/coco/coco_ssc.cpp
index 6dcd34a8f03..d6a0140d293 100644
--- a/src/devices/bus/coco/coco_ssc.cpp
+++ b/src/devices/bus/coco/coco_ssc.cpp
@@ -34,15 +34,23 @@
#include "coco_ssc.h"
#include "cpu/tms7000/tms7000.h"
-#include "machine/netlist.h"
#include "machine/ram.h"
-#include "netlist/devices/net_lib.h"
#include "sound/ay8910.h"
#include "sound/sp0256.h"
#include "speaker.h"
-#define LOG_SSC 0
+#define LOG_INTERFACE (1U << 1)
+#define LOG_INTERNAL (1U << 2)
+#define VERBOSE (0)
+// #define VERBOSE (LOG_INTERFACE)
+// #define VERBOSE (LOG_INTERFACE|LOG_INTERNAL)
+
+#include "logmacro.h"
+
+#define LOGINTERFACE(...) LOGMASKED(LOG_INTERFACE, __VA_ARGS__)
+#define LOGINTERNAL(...) LOGMASKED(LOG_INTERNAL, __VA_ARGS__)
+
#define PIC_TAG "pic7040"
#define AY_TAG "cocossc_ay"
#define SP0256_TAG "sp0256"
@@ -77,37 +85,34 @@ namespace
{
public:
// construction/destruction
- coco_ssc_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
+ coco_ssc_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 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 device_reset() override;
+ virtual const tiny_rom_entry *device_rom_region() const override ATTR_COLD;
+ virtual void device_add_mconfig(machine_config &config) override ATTR_COLD;
+ virtual void device_reset() override ATTR_COLD;
- DECLARE_READ8_MEMBER(ssc_port_a_r);
- DECLARE_WRITE8_MEMBER(ssc_port_b_w);
- DECLARE_READ8_MEMBER(ssc_port_c_r);
- DECLARE_WRITE8_MEMBER(ssc_port_c_w);
- DECLARE_READ8_MEMBER(ssc_port_d_r);
- DECLARE_WRITE8_MEMBER(ssc_port_d_w);
+ u8 ssc_port_a_r();
+ void ssc_port_b_w(u8 data);
+ u8 ssc_port_c_r();
+ void ssc_port_c_w(u8 data);
+ u8 ssc_port_d_r();
+ void ssc_port_d_w(u8 data);
protected:
// device-level overrides
- virtual void device_start() override;
- virtual void device_timer(emu_timer &timer, device_timer_id id, int param, void *ptr) override;
- virtual DECLARE_READ8_MEMBER(ff7d_read);
- virtual DECLARE_WRITE8_MEMBER(ff7d_write);
+ virtual void device_start() override ATTR_COLD;
+ u8 ff7d_read(offs_t offset);
+ void ff7d_write(offs_t offset, u8 data);
virtual void set_sound_enable(bool sound_enable) override;
- static constexpr device_timer_id BUSY_TIMER_ID = 0;
private:
- uint8_t m_reset_line;
+ u8 m_reset_line;
bool m_tms7000_busy;
- uint8_t m_tms7000_porta;
- uint8_t m_tms7000_portb;
- uint8_t m_tms7000_portc;
- uint8_t m_tms7000_portd;
- emu_timer *m_tms7000_busy_timer;
+ u8 m_tms7000_porta;
+ u8 m_tms7000_portb;
+ u8 m_tms7000_portc;
+ u8 m_tms7000_portd;
required_device<tms7040_device> m_tms7040;
required_device<ram_device> m_staticram;
required_device<ay8910_device> m_ay;
@@ -121,20 +126,22 @@ namespace
public device_sound_interface
{
public:
- cocossc_sac_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
+ cocossc_sac_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock);
~cocossc_sac_device() { }
bool sound_activity_circuit_output();
protected:
// device-level overrides
- virtual void device_start() override;
+ virtual void device_start() override ATTR_COLD;
// sound stream update overrides
- virtual void sound_stream_update(sound_stream &stream, stream_sample_t **inputs, stream_sample_t **outputs, int samples) override;
+ virtual void sound_stream_update(sound_stream &stream) override;
+ // Power of 2
+ static constexpr int BUFFER_SIZE = 4;
private:
sound_stream* m_stream;
- double m_rms[16];
+ float m_rms[BUFFER_SIZE];
int m_index;
};
};
@@ -193,7 +200,7 @@ ROM_END
// coco_ssc_device - constructor
//-------------------------------------------------
-coco_ssc_device::coco_ssc_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
+coco_ssc_device::coco_ssc_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock)
: device_t(mconfig, COCO_SSC, tag, owner, clock),
device_cococart_interface(mconfig, *this ),
m_tms7040(*this, PIC_TAG),
@@ -210,10 +217,10 @@ coco_ssc_device::coco_ssc_device(const machine_config &mconfig, const char *tag,
void coco_ssc_device::device_start()
{
- // install $FF7D-E handler
- write8_delegate wh = write8_delegate(FUNC(coco_ssc_device::ff7d_write), this);
- read8_delegate rh = read8_delegate(FUNC(coco_ssc_device::ff7d_read), this);
- install_readwrite_handler(0xFF7D, 0xFF7E, rh, wh);
+ // install $ff7d-e handler
+ install_readwrite_handler(0xff7d, 0xff7e,
+ read8sm_delegate(*this, FUNC(coco_ssc_device::ff7d_read)),
+ write8sm_delegate(*this, FUNC(coco_ssc_device::ff7d_write)));
save_item(NAME(m_reset_line));
save_item(NAME(m_tms7000_busy));
@@ -221,9 +228,6 @@ void coco_ssc_device::device_start()
save_item(NAME(m_tms7000_portb));
save_item(NAME(m_tms7000_portc));
save_item(NAME(m_tms7000_portd));
-
- m_tms7000_busy_timer = timer_alloc(BUSY_TIMER_ID);
-
}
@@ -233,32 +237,12 @@ void coco_ssc_device::device_start()
void coco_ssc_device::device_reset()
{
- m_reset_line = 0;
+ m_reset_line = 1;
m_tms7000_busy = false;
}
//-------------------------------------------------
-// device_timer - handle timer callbacks
-//-------------------------------------------------
-
-void coco_ssc_device::device_timer(emu_timer &timer, device_timer_id id, int param, void *ptr)
-{
- switch(id)
- {
- case BUSY_TIMER_ID:
- m_tms7000_busy = false;
- m_tms7000_busy_timer->adjust(attotime::never);
- break;
-
- default:
- break;
-
- }
-}
-
-
-//-------------------------------------------------
// rom_region - device-specific ROM region
//-------------------------------------------------
@@ -290,19 +274,15 @@ void coco_ssc_device::set_sound_enable(bool sound_enable)
// ff7d_read
//-------------------------------------------------
-READ8_MEMBER(coco_ssc_device::ff7d_read)
+u8 coco_ssc_device::ff7d_read(offs_t offset)
{
- uint8_t data = 0xff;
+ u8 data = 0xff;
switch(offset)
{
case 0x00:
data = 0xff;
-
- if (LOG_SSC)
- {
- logerror( "[%s] ff7d read: %02x\n", machine().describe_context(), data );
- }
+ LOGINTERFACE( "[%s] ff7d read: %02x\n", machine().describe_context(), data );
break;
case 0x01:
@@ -318,25 +298,22 @@ READ8_MEMBER(coco_ssc_device::ff7d_read)
data |= 0x40;
}
- if( ! m_sac->sound_activity_circuit_output() )
+ if( m_sac->sound_activity_circuit_output() )
{
data |= 0x20;
}
- if (LOG_SSC)
- {
- logerror( "[%s] ff7e read: %c%c%c%c %c%c%c%c (%02x)\n",
+ LOGINTERFACE( "[%s] ff7e read: %c%c%c%c %c%c%c%c (%02x)\n",
machine().describe_context(),
- data & 0x80 ? '.' : 'B',
- data & 0x40 ? '.' : 'S',
- data & 0x20 ? '.' : 'P',
- data & 0x10 ? '.' : '1',
- data & 0x08 ? '.' : '1',
- data & 0x04 ? '.' : '1',
- data & 0x02 ? '.' : '1',
- data & 0x01 ? '.' : '1',
+ data & 0x80 ? 'b' : 'B',
+ data & 0x40 ? 's' : 'S',
+ data & 0x20 ? 'p' : 'P',
+ data & 0x10 ? '1' : '0',
+ data & 0x08 ? '1' : '0',
+ data & 0x04 ? '1' : '0',
+ data & 0x02 ? '1' : '0',
+ data & 0x01 ? '1' : '0',
data );
- }
break;
}
@@ -348,37 +325,30 @@ READ8_MEMBER(coco_ssc_device::ff7d_read)
// ff7d_write
//-------------------------------------------------
-WRITE8_MEMBER(coco_ssc_device::ff7d_write)
+void coco_ssc_device::ff7d_write(offs_t offset, u8 data)
{
switch(offset)
{
case 0x00:
- if (LOG_SSC)
+ LOGINTERFACE( "[%s] ff7d write: %02x\n", machine().describe_context(), data );
+
+ if( (data & 1) == 1 )
{
- logerror( "[%s] ff7d write: %02x\n", machine().describe_context(), data );
+ m_spo->reset();
}
- if( (m_reset_line & 1) == 1 )
+ if( ((m_reset_line & 1) == 1) && ((data & 1) == 0) )
{
- if( (data & 1) == 0 )
- {
- m_tms7040->reset();
- m_ay->reset();
- m_spo->reset();
- m_tms7000_busy = false;
- }
+ m_tms7040->reset();
+ m_ay->reset();
+ m_tms7000_busy = false;
}
m_reset_line = data;
break;
case 0x01:
-
- if (LOG_SSC)
- {
- logerror( "[%s] ff7e write: %02x\n", machine().describe_context(), data );
- }
-
+ LOGINTERFACE( "[%s] ff7e write: %02x\n", machine().describe_context(), data );
m_tms7000_porta = data;
m_tms7000_busy = true;
m_tms7040->set_input_line(TMS7000_INT3_LINE, ASSERT_LINE);
@@ -391,43 +361,37 @@ WRITE8_MEMBER(coco_ssc_device::ff7d_write)
// Handlers for secondary CPU ports
//-------------------------------------------------
-READ8_MEMBER(coco_ssc_device::ssc_port_a_r)
+u8 coco_ssc_device::ssc_port_a_r()
{
- if (LOG_SSC)
+ LOGINTERNAL( "[%s] port a read: %02x\n", machine().describe_context(), m_tms7000_porta );
+
+ if( !machine().side_effects_disabled() )
{
- logerror( "[%s] port a read: %02x\n", machine().describe_context(), m_tms7000_porta );
+ m_tms7040->set_input_line(TMS7000_INT3_LINE, CLEAR_LINE);
}
- m_tms7040->set_input_line(TMS7000_INT3_LINE, CLEAR_LINE);
-
return m_tms7000_porta;
}
-WRITE8_MEMBER(coco_ssc_device::ssc_port_b_w)
+void coco_ssc_device::ssc_port_b_w(u8 data)
{
- if (LOG_SSC)
- {
- logerror( "[%s] port b write: %02x\n", machine().describe_context(), data );
- }
+ LOGINTERNAL( "[%s] port b write: %02x\n", machine().describe_context(), data );
m_tms7000_portb = data;
}
-READ8_MEMBER(coco_ssc_device::ssc_port_c_r)
+u8 coco_ssc_device::ssc_port_c_r()
{
- if (LOG_SSC)
- {
- logerror( "[%s] port c read: %02x\n", machine().describe_context(), m_tms7000_portc );
- }
+ LOGINTERNAL( "[%s] port c read: %02x\n", machine().describe_context(), m_tms7000_portc );
return m_tms7000_portc;
}
-WRITE8_MEMBER(coco_ssc_device::ssc_port_c_w)
+void coco_ssc_device::ssc_port_c_w(u8 data)
{
- if( (data & C_RCS) == 0 && (data & C_RRW) == 0) /* static RAM write */
+ if( (data & C_RCS) == 0 && (data & C_RRW) == 0 ) /* static RAM write */
{
- uint16_t address = (uint16_t)data << 8;
+ u16 address = u16(data) << 8;
address += m_tms7000_portb;
address &= 0x7ff;
@@ -447,19 +411,17 @@ WRITE8_MEMBER(coco_ssc_device::ssc_port_c_w)
}
}
- if( (data & C_ALD) == 0 )
+ if( ((m_tms7000_portc & C_ALD) == C_ALD) && ((data & C_ALD) == 0) && (m_tms7000_portd < 64) )
{
- m_spo->ald_w(m_tms7000_portd);
+ m_spo->ald_w(m_tms7000_portd); /* load allophone */
}
if( ((m_tms7000_portc & C_BSY) == 0) && ((data & C_BSY) == C_BSY) )
{
- m_tms7000_busy_timer->adjust(attotime::from_usec(1800));
+ m_tms7000_busy = false;
}
- if (LOG_SSC)
- {
- logerror( "[%s] port c write: %c%c%c%c %c%c%c%c (%02x)\n",
+ LOGINTERNAL( "[%s] port c write: %c%c%c%c %c%c%c%c (%02x)\n",
machine().describe_context(),
data & 0x80 ? '.' : 'B',
data & 0x40 ? '.' : 'P',
@@ -470,19 +432,18 @@ WRITE8_MEMBER(coco_ssc_device::ssc_port_c_w)
data & 0x02 ? '1' : '0',
data & 0x40 ? (data & 0x01 ? '1' : '0') : (data & 0x01 ? 'C' : '.'),
data );
- }
m_tms7000_portc = data;
}
-READ8_MEMBER(coco_ssc_device::ssc_port_d_r)
+u8 coco_ssc_device::ssc_port_d_r()
{
- if( ((m_tms7000_portc & C_RCS) == 0) && ((m_tms7000_portc & C_ACS) == 0))
+ if( ((m_tms7000_portc & C_RCS) == 0) && ((m_tms7000_portc & C_ACS) == 0) )
logerror( "[%s] Warning: Reading RAM and PSG at the same time!\n", machine().describe_context() );
if( ((m_tms7000_portc & C_RCS) == 0) && ((m_tms7000_portc & C_RRW) == C_RRW)) /* static ram chip select (low) and static ram chip read (high) */
{
- uint16_t address = (uint16_t)m_tms7000_portc << 8;
+ u16 address = u16(m_tms7000_portc) << 8;
address += m_tms7000_portb;
address &= 0x7ff;
@@ -497,20 +458,14 @@ READ8_MEMBER(coco_ssc_device::ssc_port_d_r)
}
}
- if (LOG_SSC)
- {
- logerror( "[%s] port d read: %02x\n", machine().describe_context(), m_tms7000_portd );
- }
+ LOGINTERNAL( "[%s] port d read: %02x\n", machine().describe_context(), m_tms7000_portd );
return m_tms7000_portd;
}
-WRITE8_MEMBER(coco_ssc_device::ssc_port_d_w)
+void coco_ssc_device::ssc_port_d_w(u8 data)
{
- if (LOG_SSC)
- {
- logerror( "[%s] port d write: %02x\n", machine().describe_context(), data );
- }
+ LOGINTERNAL( "[%s] port d write: %02x\n", machine().describe_context(), data );
m_tms7000_portd = data;
}
@@ -520,12 +475,13 @@ WRITE8_MEMBER(coco_ssc_device::ssc_port_d_w)
// cocossc_sac_device - constructor
//-------------------------------------------------
-cocossc_sac_device::cocossc_sac_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
+cocossc_sac_device::cocossc_sac_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock)
: device_t(mconfig, COCOSSC_SAC, tag, owner, clock),
device_sound_interface(mconfig, *this),
m_stream(nullptr),
m_index(0)
{
+ std::fill(std::begin(m_rms), std::end(m_rms), 0.0f);
}
@@ -543,24 +499,26 @@ void cocossc_sac_device::device_start()
// sound_stream_update - handle a stream update
//-------------------------------------------------
-void cocossc_sac_device::sound_stream_update(sound_stream &stream, stream_sample_t **inputs, stream_sample_t **outputs, int samples)
+void cocossc_sac_device::sound_stream_update(sound_stream &stream)
{
- stream_sample_t *src = inputs[0];
- stream_sample_t *dst = outputs[0];
-
- double n = samples;
+ int count = stream.samples();
+ m_rms[m_index] = 0;
- while (samples--)
+ if( count > 0 )
{
- m_rms[m_index] += ( (double)*src * (double)*src );
- *dst++ = (*src++);
- }
+ for( int sampindex = 0; sampindex < count; sampindex++ )
+ {
+ auto source_sample = stream.get(0, sampindex);
+ m_rms[m_index] += source_sample * source_sample;
+ stream.put(0, sampindex, source_sample);
+ }
- m_rms[m_index] = m_rms[m_index] / n;
- m_rms[m_index] = sqrt(m_rms[m_index]);
+ m_rms[m_index] = m_rms[m_index] / count;
+ m_rms[m_index] = sqrt(m_rms[m_index]);
+ }
m_index++;
- m_index &= 0x0f;
+ m_index &= (BUFFER_SIZE-1);
}
@@ -570,14 +528,8 @@ void cocossc_sac_device::sound_stream_update(sound_stream &stream, stream_sample
bool cocossc_sac_device::sound_activity_circuit_output()
{
- double average = m_rms[0] + m_rms[1] + m_rms[2] + m_rms[3] + m_rms[4] +
- m_rms[5] + m_rms[6] + m_rms[7] + m_rms[8] + m_rms[9] + m_rms[10] +
- m_rms[11] + m_rms[12] + m_rms[13] + m_rms[14] + m_rms[15];
-
- average /= 16.0;
-
- if( average > 10400.0 )
- return true;
+ float sum = std::accumulate(std::begin(m_rms), std::end(m_rms), 0.0f);
+ float average = (sum / BUFFER_SIZE);
- return false;
+ return average < 0.317f;
}
diff --git a/src/devices/bus/coco/coco_ssc.h b/src/devices/bus/coco/coco_ssc.h
index de672cd7771..4f4f9bce0a8 100644
--- a/src/devices/bus/coco/coco_ssc.h
+++ b/src/devices/bus/coco/coco_ssc.h
@@ -1,5 +1,5 @@
// license:BSD-3-Clause
-// copyright-holders:Nathan Woods
+// copyright-holders:tim lindner
#ifndef MAME_BUS_COCO_COCO_SSC_H
#define MAME_BUS_COCO_COCO_SSC_H
diff --git a/src/devices/bus/coco/coco_stecomp.cpp b/src/devices/bus/coco/coco_stecomp.cpp
new file mode 100644
index 00000000000..dc895555418
--- /dev/null
+++ b/src/devices/bus/coco/coco_stecomp.cpp
@@ -0,0 +1,85 @@
+// license:BSD-3-Clause
+// copyright-holders:tim lindner
+/***************************************************************************
+
+ coco_stecomp.cpp
+
+
+ Code for emulating The Stereo Composer by Speech Systems
+
+ This cartridge is a simple sound cartridge. It had two 8-bit DACs
+ connected thru a PIA. It contained no ROM.
+
+***************************************************************************/
+
+#include "emu.h"
+#include "coco_stecomp.h"
+#include "cococart.h"
+
+#include "sound/dac.h"
+#include "speaker.h"
+#include "machine/6821pia.h"
+
+
+//**************************************************************************
+// STEREO_COMPOSER DEVICE CLASS
+//**************************************************************************
+
+namespace
+{
+ // ======================> coco_stereo_composer_device
+
+ class coco_stereo_composer_device :
+ public device_t,
+ public device_cococart_interface
+ {
+ public:
+ // construction/destruction
+ coco_stereo_composer_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock)
+ : device_t(mconfig, COCO_STEREO_COMPOSER, tag, owner, clock)
+ , device_cococart_interface(mconfig, *this)
+ , m_pia(*this, "sc_pia")
+ , m_ldac(*this, "sc_ldac")
+ , m_rdac(*this, "sc_rdac")
+ {
+ }
+
+ protected:
+ // optional information overrides
+ virtual void device_add_mconfig(machine_config &config) override ATTR_COLD;
+
+ // device-level overrides
+ virtual void device_start() override
+ {
+ // install handlers
+ install_readwrite_handler( 0xFF70, 0xFF73, read8sm_delegate(*m_pia, FUNC(pia6821_device::read)), write8sm_delegate(*m_pia, FUNC(pia6821_device::write)));
+ }
+
+ private:
+ // internal state
+ required_device<pia6821_device> m_pia;
+ required_device<dac_byte_interface> m_ldac;
+ required_device<dac_byte_interface> m_rdac;
+ };
+
+ //**************************************************************************
+ // STEREO_COMPOSER MACHINE DECLARATIONS
+ //**************************************************************************
+
+ void coco_stereo_composer_device::device_add_mconfig(machine_config &config)
+ {
+ SPEAKER(config, "sc_speaker", 2).front();
+ DAC_8BIT_R2R(config, m_ldac).add_route(ALL_OUTPUTS, "sc_speaker", 0.5, 0);
+ DAC_8BIT_R2R(config, m_rdac).add_route(ALL_OUTPUTS, "sc_speaker", 0.5, 1);
+
+ 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));
+ }
+}
+
+//**************************************************************************
+// DEVICE DECLARATION
+//**************************************************************************
+
+DEFINE_DEVICE_TYPE_PRIVATE(COCO_STEREO_COMPOSER, device_cococart_interface, coco_stereo_composer_device, "coco_stereo_composer", "Speech Systems Stereo Composer")
diff --git a/src/devices/bus/coco/coco_stecomp.h b/src/devices/bus/coco/coco_stecomp.h
new file mode 100644
index 00000000000..a78c631b492
--- /dev/null
+++ b/src/devices/bus/coco/coco_stecomp.h
@@ -0,0 +1,13 @@
+// license:BSD-3-Clause
+// copyright-holders:tim lindner
+#ifndef MAME_BUS_COCO_COCO_STECOMP_H
+#define MAME_BUS_COCO_COCO_STECOMP_H
+
+#pragma once
+
+#include "cococart.h"
+
+// device type definition
+DECLARE_DEVICE_TYPE(COCO_STEREO_COMPOSER, device_cococart_interface)
+
+#endif // MAME_BUS_COCO_COCO_STECOMP_H
diff --git a/src/devices/bus/coco/coco_sym12.cpp b/src/devices/bus/coco/coco_sym12.cpp
new file mode 100644
index 00000000000..76b726b1bf5
--- /dev/null
+++ b/src/devices/bus/coco/coco_sym12.cpp
@@ -0,0 +1,179 @@
+// license:BSD-3-Clause
+// copyright-holders:tim lindner
+/***************************************************************************
+
+ coco_sym12.cpp
+
+
+ Code for emulating The Symphony 12
+
+ Made by Speech Systems, 1982.
+
+ This cartridge is a complex sound cartridge. It had 4 AY-3-8910 PSG
+ connected thru a PIA. It contained no ROM.
+
+***************************************************************************/
+
+#include "emu.h"
+#include "coco_sym12.h"
+#include "cococart.h"
+
+#include "speaker.h"
+#include "machine/6821pia.h"
+#include "sound/ay8910.h"
+
+//**************************************************************************
+// SYMPHONY_TWELVE DEVICE CLASS
+//**************************************************************************
+
+namespace
+{
+ // ======================> coco_symphony_twelve_device
+
+ class coco_symphony_twelve_device :
+ public device_t,
+ public device_cococart_interface
+ {
+ public:
+ // construction/destruction
+ coco_symphony_twelve_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock)
+ : device_t(mconfig, COCO_SYM12, tag, owner, clock)
+ , device_cococart_interface(mconfig, *this)
+ , m_pia(*this, "s12_pia")
+ , m_ay8910(*this, "s12_ay8910.%u", 1)
+ {
+ }
+
+ protected:
+ // optional information overrides
+ virtual void device_add_mconfig(machine_config &config) override ATTR_COLD;
+
+ // device-level overrides
+ virtual void device_start() override
+ {
+ // install handlers
+ install_readwrite_handler( 0xff60, 0xff63, read8sm_delegate(*m_pia, FUNC(pia6821_device::read)), write8sm_delegate(*m_pia, FUNC(pia6821_device::write)));
+ }
+
+ u8 read_porta();
+ void write_porta(u8 data);
+ void write_portb(u8 data);
+ void write_psg(u8 bus, u8 data);
+
+ private:
+ // internal state
+ required_device<pia6821_device> m_pia;
+ required_device_array<ay8910_device, 4> m_ay8910;
+ };
+
+ //**************************************************************************
+ // SYMPHONY_TWELVE MACHINE DECLARATIONS
+ //**************************************************************************
+
+ void coco_symphony_twelve_device::device_add_mconfig(machine_config &config)
+ {
+ 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));
+
+ SPEAKER(config, "s12_l").front_left();
+ SPEAKER(config, "s12_r").front_right();
+ AY8910(config, m_ay8910[0], DERIVED_CLOCK(1, 1));
+ m_ay8910[0]->set_flags(AY8910_SINGLE_OUTPUT);
+ m_ay8910[0]->add_route(ALL_OUTPUTS, "s12_l", 0.50);
+
+ AY8910(config, m_ay8910[1], DERIVED_CLOCK(1, 1));
+ m_ay8910[1]->set_flags(AY8910_SINGLE_OUTPUT);
+ m_ay8910[1]->add_route(ALL_OUTPUTS, "s12_l", 0.50);
+
+ AY8910(config, m_ay8910[2], DERIVED_CLOCK(1, 1));
+ m_ay8910[2]->set_flags(AY8910_SINGLE_OUTPUT);
+ m_ay8910[2]->add_route(ALL_OUTPUTS, "s12_r", 0.50);
+
+ AY8910(config, m_ay8910[3], DERIVED_CLOCK(1, 1));
+ m_ay8910[3]->set_flags(AY8910_SINGLE_OUTPUT);
+ m_ay8910[3]->add_route(ALL_OUTPUTS, "s12_r", 0.50);
+
+ }
+
+ //**************************************************************************
+ // SYMPHONY_TWELVE PSG I/O
+ //**************************************************************************
+
+ u8 coco_symphony_twelve_device::read_porta()
+ {
+ uint8_t b_output = m_pia->b_output();
+ u8 result = 0;
+
+ if ((b_output & 0x03) == 0x01) {
+ result |= m_ay8910[0]->data_r();
+ }
+
+ if ((b_output & 0x0c) == 0x04) {
+ result |= m_ay8910[1]->data_r();
+ }
+
+ if ((b_output & 0x30) == 0x10) {
+ result |= m_ay8910[2]->data_r();
+ }
+
+ if ((b_output & 0xc0) == 0x40) {
+ result |= m_ay8910[3]->data_r();
+ }
+
+ return result;
+ }
+
+ void coco_symphony_twelve_device::write_porta(u8 data)
+ {
+ write_psg(m_pia->b_output(), data);
+ }
+
+ void coco_symphony_twelve_device::write_portb(u8 data)
+ {
+ write_psg(data, m_pia->a_output());
+ }
+
+ void coco_symphony_twelve_device::write_psg(u8 bus, u8 data)
+ {
+ if ((bus & 0x03) == 0x03) {
+ m_ay8910[0]->address_w(data);
+ }
+
+ if ((bus & 0x03) == 0x02) {
+ m_ay8910[0]->data_w(data);
+ }
+
+ if ((bus & 0x0c) == 0x0c) {
+ m_ay8910[1]->address_w(data);
+ }
+
+ if ((bus & 0x0c) == 0x08) {
+ m_ay8910[1]->data_w(data);
+ }
+
+ if ((bus & 0x30) == 0x30) {
+ m_ay8910[2]->address_w(data);
+ }
+
+ if ((bus & 0x30) == 0x20) {
+ m_ay8910[2]->data_w(data);
+ }
+
+ if ((bus & 0xc0) == 0xc0) {
+ m_ay8910[3]->address_w(data);
+ }
+
+ if ((bus & 0xc0) == 0x80) {
+ m_ay8910[3]->data_w(data);
+ }
+ }
+}
+
+
+//**************************************************************************
+// DEVICE DECLARATION
+//**************************************************************************
+
+DEFINE_DEVICE_TYPE_PRIVATE(COCO_SYM12, device_cococart_interface, coco_symphony_twelve_device, "coco_symphony_twelve", "Speech Systems Symphony Twelve")
diff --git a/src/devices/bus/coco/coco_sym12.h b/src/devices/bus/coco/coco_sym12.h
new file mode 100644
index 00000000000..6c3dabc7517
--- /dev/null
+++ b/src/devices/bus/coco/coco_sym12.h
@@ -0,0 +1,13 @@
+// license:BSD-3-Clause
+// copyright-holders:tim lindner
+#ifndef MAME_BUS_COCO_COCO_SYM12_H
+#define MAME_BUS_COCO_COCO_SYM12_H
+
+#pragma once
+
+#include "cococart.h"
+
+// device type definition
+DECLARE_DEVICE_TYPE(COCO_SYM12, device_cococart_interface)
+
+#endif // MAME_BUS_COCO_COCO_SYM12_H
diff --git a/src/devices/bus/coco/coco_t4426.cpp b/src/devices/bus/coco/coco_t4426.cpp
index 4bb44e5949a..896769ed716 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
@@ -95,43 +94,43 @@ namespace
{
public:
// construction/destruction
- coco_t4426_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
+ coco_t4426_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock);
// 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 void device_add_mconfig(machine_config &config) override ATTR_COLD;
+ virtual const tiny_rom_entry *device_rom_region() const override ATTR_COLD;
+ virtual ioport_constructor device_input_ports() const override ATTR_COLD;
- virtual uint8_t* get_cart_base() override;
- DECLARE_WRITE8_MEMBER(pia_A_w);
+ virtual u8 *get_cart_base() override;
+ void pia_A_w(u8 data);
// 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, uint32_t clock);
+ coco_t4426_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;
+ virtual void device_start() override ATTR_COLD;
+ virtual void device_reset() override ATTR_COLD;
// internal state
device_image_interface *m_cart;
- uint8_t m_select;
+ u8 m_select;
optional_ioport m_autostart;
- virtual DECLARE_READ8_MEMBER(cts_read) override;
- virtual DECLARE_READ8_MEMBER(scs_read) override;
- virtual DECLARE_WRITE8_MEMBER(scs_write) 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:
// internal state
required_memory_region m_eprom;
@@ -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);
@@ -236,7 +235,7 @@ DEFINE_DEVICE_TYPE_PRIVATE(COCO_T4426, device_cococart_interface, coco_t4426_dev
// coco_t4426_device - constructor
//-------------------------------------------------
-coco_t4426_device::coco_t4426_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock)
+coco_t4426_device::coco_t4426_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, u32 clock)
: device_t(mconfig, type, tag, owner, clock)
, device_cococart_interface(mconfig, *this)
, m_cart(nullptr)
@@ -251,7 +250,7 @@ coco_t4426_device::coco_t4426_device(const machine_config &mconfig, device_type
{
}
-coco_t4426_device::coco_t4426_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
+coco_t4426_device::coco_t4426_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock)
: coco_t4426_device(mconfig, COCO_T4426, tag, owner, clock)
{
}
@@ -264,6 +263,9 @@ void coco_t4426_device::device_start()
{
LOG("%s()\n", FUNCNAME );
m_cart = dynamic_cast<device_image_interface *>(owner());
+
+ // save state support
+ save_item(NAME(m_select));
}
@@ -326,9 +328,9 @@ void coco_t4426_device::write_acia_clocks(int id, int state)
ACIA is located at ff48-ff4F with A1 = 1
-------------------------------------------------*/
-READ8_MEMBER(coco_t4426_device::scs_read)
+u8 coco_t4426_device::scs_read(offs_t offset)
{
- uint8_t result = 0x00;
+ u8 result = 0x00;
LOG("%s Offs:%d\n", FUNCNAME, offset);
@@ -358,7 +360,7 @@ READ8_MEMBER(coco_t4426_device::scs_read)
ACIA is located at ff48-ff4F with A1 = 1
-------------------------------------------------*/
-WRITE8_MEMBER(coco_t4426_device::scs_write)
+void coco_t4426_device::scs_write(offs_t offset, u8 data)
{
LOG("%s Offs:%d Data:%02x\n", FUNCNAME, offset, data);
LOGSETUP(" * Offs:%02x <- %02x\n", offset, data);
@@ -397,7 +399,7 @@ WRITE8_MEMBER(coco_t4426_device::scs_write)
#define ROM6 (~0x40 & 0xff)
#define ROM7 (~0x80 & 0xff)
-WRITE8_MEMBER( coco_t4426_device::pia_A_w )
+void coco_t4426_device::pia_A_w(u8 data)
{
LOGPIA("%s(%02x)\n", FUNCNAME, data);
m_select = data;
@@ -407,9 +409,9 @@ WRITE8_MEMBER( coco_t4426_device::pia_A_w )
cts_read
-------------------------------------------------*/
-READ8_MEMBER(coco_t4426_device::cts_read)
+u8 coco_t4426_device::cts_read(offs_t offset)
{
- uint8_t result = 0x00;
+ u8 result = 0x00;
switch (offset & 0x2000)
{
@@ -440,7 +442,7 @@ READ8_MEMBER(coco_t4426_device::cts_read)
get_cart_base
-------------------------------------------------*/
-uint8_t* coco_t4426_device::get_cart_base()
+u8 *coco_t4426_device::get_cart_base()
{
LOG("%s - m_select %02x -> %02x\n", FUNCNAME, m_select, ~m_select & 0xff );
return memregion(CARTSLOT_TAG)->base();
diff --git a/src/devices/bus/coco/coco_wpk.cpp b/src/devices/bus/coco/coco_wpk.cpp
new file mode 100644
index 00000000000..e2750428227
--- /dev/null
+++ b/src/devices/bus/coco/coco_wpk.cpp
@@ -0,0 +1,200 @@
+// license:BSD-3-Clause
+// copyright-holders:Nigel Barnes
+/***************************************************************************
+
+ PBJ Word-Pak/Word-Pak II - 80 Column Video Cartridge
+
+ TODO:
+ - the R6545 Transparent Mode used to update video RAM needs some attention.
+ - original PBJ WorkPak (not II or RS) had an optional Basic Driver ROM (undumped).
+ - does WordPak II use different character ROM?
+
+***************************************************************************/
+
+#include "emu.h"
+#include "coco_wpk.h"
+#include "render.h"
+#include "screen.h"
+
+
+//-------------------------------------------------
+// ROM( coco_wpk )
+//-------------------------------------------------
+
+ROM_START(coco_wpk)
+ ROM_REGION(0x0800, "chargen", 0)
+ ROM_LOAD("chr_gen_4.0.rom", 0x0000, 0x0800, CRC(6e9a671a) SHA1(0ff5fae512c7f1abe138504d51492404dd86be03)) // from PBJ WordPak RS
+ROM_END
+
+
+//**************************************************************************
+// GLOBAL VARIABLES
+//**************************************************************************
+
+DEFINE_DEVICE_TYPE(COCO_WPK, coco_wpk_device, "coco_wpk", "CoCo WordPak")
+DEFINE_DEVICE_TYPE(COCO_WPK2, coco_wpk2_device, "coco_wpk2", "CoCo WordPak II")
+DEFINE_DEVICE_TYPE(COCO_WPKRS, coco_wpkrs_device, "coco_wpkrs", "CoCo WordPak RS")
+
+
+//**************************************************************************
+// LIVE DEVICE
+//**************************************************************************
+
+//-------------------------------------------------
+// coco_wpk_device - constructor
+//-------------------------------------------------
+
+coco_wpk_device::coco_wpk_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, u32 clock)
+ : device_t(mconfig, type, tag, owner, clock)
+ , device_cococart_interface(mconfig, *this )
+ , m_crtc(*this, "crtc")
+ , m_palette(*this, "palette")
+ , m_chargen(*this, "chargen")
+ , m_video_addr(0)
+{
+}
+
+coco_wpk_device::coco_wpk_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock)
+ : coco_wpk_device(mconfig, COCO_WPK, tag, owner, clock)
+{
+}
+
+coco_wpk2_device::coco_wpk2_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock)
+ : coco_wpk_device(mconfig, COCO_WPK2, tag, owner, clock)
+{
+}
+
+coco_wpkrs_device::coco_wpkrs_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock)
+ : coco_wpk_device(mconfig, COCO_WPKRS, tag, owner, clock)
+{
+}
+
+
+//-------------------------------------------------
+// device_start - device-specific startup
+//-------------------------------------------------
+
+void coco_wpk_device::device_start()
+{
+ m_video_ram = std::make_unique<u8[]>(0x800);
+
+ save_pointer(NAME(m_video_ram), 0x800);
+ save_item(NAME(m_video_addr));
+}
+
+void coco_wpk2_device::device_start()
+{
+ coco_wpk_device::device_start();
+}
+
+void coco_wpkrs_device::device_start()
+{
+ coco_wpk_device::device_start();
+}
+
+
+//-------------------------------------------------
+// device_reset - device-specific reset
+//-------------------------------------------------
+
+void coco_wpk_device::device_reset()
+{
+ install_readwrite_handler(0xff98, 0xff98, read8smo_delegate(*m_crtc, FUNC(r6545_1_device::status_r)), write8smo_delegate(*m_crtc, FUNC(r6545_1_device::address_w)));
+ install_readwrite_handler(0xff99, 0xff99, read8smo_delegate(*m_crtc, FUNC(r6545_1_device::register_r)), write8smo_delegate(*m_crtc, FUNC(r6545_1_device::register_w)));
+ install_write_handler(0xff9b, 0xff9b, write8smo_delegate(*this, FUNC(coco_wpkrs_device::crtc_display_w)));
+}
+
+void coco_wpk2_device::device_reset()
+{
+ coco_wpk_device::device_reset();
+
+ install_write_handler(0xff9c, 0xff9c, write8smo_delegate(*this, FUNC(coco_wpk2_device::video_select_w)));
+
+ machine().render().first_target()->set_view(0);
+}
+
+void coco_wpkrs_device::device_reset()
+{
+ install_readwrite_handler(0xff76, 0xff76, read8smo_delegate(*m_crtc, FUNC(r6545_1_device::status_r)), write8smo_delegate(*m_crtc, FUNC(r6545_1_device::address_w)));
+ install_readwrite_handler(0xff77, 0xff77, read8smo_delegate(*m_crtc, FUNC(r6545_1_device::register_r)), write8smo_delegate(*m_crtc, FUNC(r6545_1_device::register_w)));
+ install_write_handler(0xff79, 0xff79, write8smo_delegate(*this, FUNC(coco_wpkrs_device::crtc_display_w)));
+}
+
+
+//-------------------------------------------------
+// device_add_mconfig - add device configuration
+//-------------------------------------------------
+
+void coco_wpk_device::device_add_mconfig(machine_config &config)
+{
+ screen_device &screen(SCREEN(config, "screen", SCREEN_TYPE_RASTER));
+ screen.set_raw(14.318181_MHz_XTAL, 896, 0, 640, 290, 0, 240);
+ screen.set_screen_update("crtc", FUNC(mc6845_device::screen_update));
+
+ PALETTE(config, m_palette, palette_device::MONOCHROME);
+
+ R6545_1(config, m_crtc, 14.318181_MHz_XTAL / 8);
+ m_crtc->set_screen("screen");
+ m_crtc->set_show_border_area(false);
+ m_crtc->set_char_width(8);
+ m_crtc->set_on_update_addr_change_callback(FUNC(coco_wpkrs_device::crtc_addr));
+ m_crtc->set_update_row_callback(FUNC(coco_wpkrs_device::crtc_update_row));
+}
+
+
+//-------------------------------------------------
+// rom_region - device-specific ROM region
+//-------------------------------------------------
+
+const tiny_rom_entry *coco_wpk_device::device_rom_region() const
+{
+ return ROM_NAME( coco_wpk );
+}
+
+
+void coco_wpk_device::crtc_display_w(u8 data)
+{
+ //logerror("crtc_display_w: %02x\n", data);
+ m_video_ram[m_video_addr] = data;
+
+ m_crtc->register_r();
+}
+
+
+MC6845_ON_UPDATE_ADDR_CHANGED(coco_wpk_device::crtc_addr)
+{
+ //logerror("crtc_addr: %04x %d\n", address, strobe);
+ m_video_addr = address;
+}
+
+
+MC6845_UPDATE_ROW(coco_wpk_device::crtc_update_row)
+{
+ u32 *p = &bitmap.pix(y);
+
+ for (int column = 0; column < x_count; column++)
+ {
+ u8 code = m_video_ram[(ma + column) & 0x7ff];
+ u16 addr = (code << 4) | (ra & 0x0f);
+ u8 data = m_chargen->base()[addr & 0x7ff];
+
+ if (column == cursor_x)
+ {
+ data = 0xff;
+ }
+
+ for (int bit = 0; bit < 8; bit++)
+ {
+ *p++ = m_palette->pen(BIT(data, 0) && de);
+
+ data >>= 1;
+ }
+ }
+}
+
+
+void coco_wpk2_device::video_select_w(u8 data)
+{
+ // software video switch (Word-Pak II only)
+ machine().render().first_target()->set_view(BIT(data, 6));
+}
diff --git a/src/devices/bus/coco/coco_wpk.h b/src/devices/bus/coco/coco_wpk.h
new file mode 100644
index 00000000000..c0e3e53ad8c
--- /dev/null
+++ b/src/devices/bus/coco/coco_wpk.h
@@ -0,0 +1,93 @@
+// license:BSD-3-Clause
+// copyright-holders:Nigel Barnes
+#ifndef MAME_BUS_COCO_COCO_WPK_H
+#define MAME_BUS_COCO_COCO_WPK_H
+
+#pragma once
+
+#include "cococart.h"
+#include "video/mc6845.h"
+#include "emupal.h"
+
+
+//**************************************************************************
+// TYPE DEFINITIONS
+//**************************************************************************
+
+// ======================> coco_wpk_device
+
+class coco_wpk_device :
+ public device_t,
+ public device_cococart_interface
+{
+public:
+ static constexpr feature_type imperfect_features() { return feature::GRAPHICS; }
+
+ // construction/destruction
+ coco_wpk_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock);
+
+protected:
+ // construction/destruction
+ coco_wpk_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, u32 clock);
+
+ // device-level overrides
+ virtual void device_start() override ATTR_COLD;
+ virtual void device_reset() override ATTR_COLD;
+
+ // optional information overrides
+ virtual void device_add_mconfig(machine_config &config) override ATTR_COLD;
+ virtual const tiny_rom_entry *device_rom_region() const override ATTR_COLD;
+
+ required_device<r6545_1_device> m_crtc;
+ required_device<palette_device> m_palette;
+ required_memory_region m_chargen;
+
+ u16 m_video_addr;
+
+ std::unique_ptr<u8[]> m_video_ram;
+
+ void crtc_display_w(u8 data);
+ MC6845_ON_UPDATE_ADDR_CHANGED(crtc_addr);
+ MC6845_UPDATE_ROW(crtc_update_row);
+};
+
+
+// ======================> coco_wpk2_device
+
+class coco_wpk2_device : public coco_wpk_device
+{
+public:
+ // construction/destruction
+ coco_wpk2_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
+
+protected:
+ // device-level overrides
+ virtual void device_start() override ATTR_COLD;
+ virtual void device_reset() override ATTR_COLD;
+
+private:
+ void video_select_w(u8 data);
+};
+
+
+// ======================> coco_wpkrs_device
+
+class coco_wpkrs_device : public coco_wpk_device
+{
+public:
+ // construction/destruction
+ coco_wpkrs_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
+
+protected:
+ // device-level overrides
+ virtual void device_start() override ATTR_COLD;
+ virtual void device_reset() override ATTR_COLD;
+};
+
+
+// device type definition
+DECLARE_DEVICE_TYPE(COCO_WPK, coco_wpk_device)
+DECLARE_DEVICE_TYPE(COCO_WPK2, coco_wpk2_device)
+DECLARE_DEVICE_TYPE(COCO_WPKRS, coco_wpkrs_device)
+
+#endif // MAME_BUS_COCO_COCO_WPK_H
diff --git a/src/devices/bus/coco/coco_wpk2p.cpp b/src/devices/bus/coco/coco_wpk2p.cpp
new file mode 100644
index 00000000000..62fb2504bf7
--- /dev/null
+++ b/src/devices/bus/coco/coco_wpk2p.cpp
@@ -0,0 +1,56 @@
+// license:BSD-3-Clause
+// copyright-holders:Nigel Barnes
+/***************************************************************************
+
+ CoCo WordPak 2+
+
+***************************************************************************/
+
+#include "emu.h"
+#include "coco_wpk2p.h"
+#include "screen.h"
+
+
+//**************************************************************************
+// GLOBAL VARIABLES
+//**************************************************************************
+
+DEFINE_DEVICE_TYPE(COCO_WPK2P, coco_wpk2p_device, "coco_wpk2p", "CoCo WordPak 2+")
+
+//**************************************************************************
+// LIVE DEVICE
+//**************************************************************************
+
+//-------------------------------------------------
+// coco_wpk2p_device - constructor
+//-------------------------------------------------
+
+coco_wpk2p_device::coco_wpk2p_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock)
+ : device_t(mconfig, COCO_WPK2P, tag, owner, clock)
+ , device_cococart_interface(mconfig, *this )
+ , m_v9958(*this, "v9958")
+{
+}
+
+//-------------------------------------------------
+// device_start - device-specific startup
+//-------------------------------------------------
+
+void coco_wpk2p_device::device_start()
+{
+ install_readwrite_handler(0xff78, 0xff7b, read8sm_delegate(*m_v9958, FUNC(v9958_device::read)), write8sm_delegate(*m_v9958, FUNC(v9958_device::write)));
+}
+
+//-------------------------------------------------
+// device_add_mconfig - add device configuration
+//-------------------------------------------------
+
+void coco_wpk2p_device::device_add_mconfig(machine_config &config)
+{
+ /* video hardware */
+ V9958(config, m_v9958, 21.477272_MHz_XTAL);
+ m_v9958->set_screen_ntsc("screen");
+ m_v9958->set_vram_size(0x20000);
+ m_v9958->int_cb().set([this](int state) { set_line_value(line::NMI, state); });
+ SCREEN(config, "screen", SCREEN_TYPE_RASTER);
+}
diff --git a/src/devices/bus/coco/coco_wpk2p.h b/src/devices/bus/coco/coco_wpk2p.h
new file mode 100644
index 00000000000..c44bb986286
--- /dev/null
+++ b/src/devices/bus/coco/coco_wpk2p.h
@@ -0,0 +1,41 @@
+// license:BSD-3-Clause
+// copyright-holders:Nigel Barnes
+#ifndef MAME_BUS_COCO_COCO_WPK2P_H
+#define MAME_BUS_COCO_COCO_WPK2P_H
+
+#pragma once
+
+#include "cococart.h"
+#include "video/v9938.h"
+
+
+//**************************************************************************
+// TYPE DEFINITIONS
+//**************************************************************************
+
+// ======================> coco_wpk2p_device
+
+class coco_wpk2p_device :
+ public device_t,
+ public device_cococart_interface
+{
+public:
+ // construction/destruction
+ coco_wpk2p_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock);
+
+protected:
+ // device-level overrides
+ virtual void device_start() override ATTR_COLD;
+
+ // optional information overrides
+ virtual void device_add_mconfig(machine_config &config) override ATTR_COLD;
+
+private:
+ required_device<v9958_device> m_v9958;
+};
+
+
+// device type definition
+DECLARE_DEVICE_TYPE(COCO_WPK2P, coco_wpk2p_device)
+
+#endif // MAME_BUS_COCO_COCO_WPK2P_H
diff --git a/src/devices/bus/coco/cococart.cpp b/src/devices/bus/coco/cococart.cpp
index 990cbde61c4..2c385890311 100644
--- a/src/devices/bus/coco/cococart.cpp
+++ b/src/devices/bus/coco/cococart.cpp
@@ -39,24 +39,70 @@
#include "emu.h"
#include "cococart.h"
+#include "formats/rpk.h"
+
+#include "coco_dcmodem.h"
+#include "coco_fdc.h"
+#include "coco_gmc.h"
+#include "coco_ide.h"
+#include "coco_max.h"
+#include "coco_midi.h"
+#include "coco_multi.h"
+#include "coco_orch90.h"
+#include "coco_pak.h"
+#include "coco_psg.h"
+#include "coco_ram.h"
+#include "coco_rs232.h"
+#include "coco_ssc.h"
+#include "coco_stecomp.h"
+#include "coco_sym12.h"
+#include "coco_wpk.h"
+#include "coco_wpk2p.h"
+
+#include "dragon_amtor.h"
+#include "dragon_claw.h"
+#include "dragon_fdc.h"
+#include "dragon_jcbsnd.h"
+#include "dragon_jcbspch.h"
+#include "dragon_msx2.h"
+#include "dragon_serial.h"
+#include "dragon_sprites.h"
/***************************************************************************
PARAMETERS
***************************************************************************/
-#define LOG_LINE 0
+#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
+// #define VERBOSE (LOG_CART)
+
+#include "logmacro.h"
+
+#define LOGCART(...) LOGMASKED(LOG_CART, __VA_ARGS__)
+#define LOGNMI(...) LOGMASKED(LOG_NMI, __VA_ARGS__)
+#define LOGHALT(...) LOGMASKED(LOG_HALT, __VA_ARGS__)
/***************************************************************************
CONSTANTS
***************************************************************************/
-enum
+// definitions of RPK PCBs in layout.xml
+static const char *coco_rpk_pcbdefs[] =
{
- TIMER_CART,
- TIMER_NMI,
- TIMER_HALT
+ "standard",
+ "paged16k",
+ nullptr
+};
+
+
+// ...and their mappings to "default card slots"
+static const char *coco_rpk_cardslottypes[] =
+{
+ "pak",
+ "banked_16k"
};
@@ -71,13 +117,15 @@ DEFINE_DEVICE_TYPE(COCOCART_SLOT, cococart_slot_device, "cococart_slot", "CoCo C
// LIVE DEVICE
//**************************************************************************
+ALLOW_SAVE_TYPE(cococart_slot_device::line_value);
+
//-------------------------------------------------
// cococart_slot_device - constructor
//-------------------------------------------------
-cococart_slot_device::cococart_slot_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) :
+cococart_slot_device::cococart_slot_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock) :
device_t(mconfig, COCOCART_SLOT, tag, owner, clock),
- device_slot_interface(mconfig, *this),
- device_image_interface(mconfig, *this),
+ device_single_card_slot_interface<device_cococart_interface>(mconfig, *this),
+ device_cartrom_image_interface(mconfig, *this),
m_cart_callback(*this),
m_nmi_callback(*this),
m_halt_callback(*this), m_cart(nullptr)
@@ -92,11 +140,11 @@ cococart_slot_device::cococart_slot_device(const machine_config &mconfig, const
void cococart_slot_device::device_start()
{
- for(int i=0; i<TIMER_POOL; i++ )
+ for(int i=0; i < TIMER_POOL; i++ )
{
- m_cart_line.timer[i] = timer_alloc(TIMER_CART);
- m_nmi_line.timer[i] = timer_alloc(TIMER_NMI);
- m_halt_line.timer[i] = timer_alloc(TIMER_HALT);
+ m_cart_line.timer[i] = timer_alloc(FUNC(cococart_slot_device::cart_line_timer_tick), this);
+ m_nmi_line.timer[i] = timer_alloc(FUNC(cococart_slot_device::nmi_line_timer_tick), this);
+ m_halt_line.timer[i] = timer_alloc(FUNC(cococart_slot_device::halt_line_timer_tick), this);
}
m_cart_line.timer_index = 0;
@@ -104,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;
@@ -112,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;
@@ -120,46 +166,72 @@ 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 = dynamic_cast<device_cococart_interface *>(get_card_device());
+ m_cart = get_card_device();
+
+ save_item(STRUCT_MEMBER(m_cart_line, timer_index));
+ save_item(STRUCT_MEMBER(m_cart_line, delay));
+ save_item(STRUCT_MEMBER(m_cart_line, value));
+ save_item(STRUCT_MEMBER(m_cart_line, line));
+ save_item(STRUCT_MEMBER(m_cart_line, q_count));
+
+ save_item(STRUCT_MEMBER(m_nmi_line, timer_index));
+ save_item(STRUCT_MEMBER(m_nmi_line, delay));
+ save_item(STRUCT_MEMBER(m_nmi_line, value));
+ save_item(STRUCT_MEMBER(m_nmi_line, line));
+ save_item(STRUCT_MEMBER(m_nmi_line, q_count));
+
+ save_item(STRUCT_MEMBER(m_halt_line, timer_index));
+ save_item(STRUCT_MEMBER(m_halt_line, delay));
+ save_item(STRUCT_MEMBER(m_halt_line, value));
+ save_item(STRUCT_MEMBER(m_halt_line, line));
+ save_item(STRUCT_MEMBER(m_halt_line, q_count));
}
//-------------------------------------------------
-// device_timer - handle timer callbacks
+// cart_line_timer_tick - update the output
+// value for the cart's line to PIA1 CB1
//-------------------------------------------------
-void cococart_slot_device::device_timer(emu_timer &timer, device_timer_id id, int param, void *ptr)
+TIMER_CALLBACK_MEMBER(cococart_slot_device::cart_line_timer_tick)
{
- switch(id)
- {
- case TIMER_CART:
- set_line("CART", m_cart_line, (line_value) param);
- break;
+ set_line(line::CART, m_cart_line, (line_value) param);
+}
- case TIMER_NMI:
- set_line("NMI", m_nmi_line, (line_value) param);
- break;
+//-------------------------------------------------
+// nmi_line_timer_tick - update the output
+// value sent to the CPU's NMI line
+//-------------------------------------------------
- case TIMER_HALT:
- set_line("HALT", m_halt_line, (line_value) param);
- break;
- }
+TIMER_CALLBACK_MEMBER(cococart_slot_device::nmi_line_timer_tick)
+{
+ set_line(line::NMI, m_nmi_line, (line_value) param);
}
+//-------------------------------------------------
+// halt_line_timer_tick - update the output
+// value sent to the CPU's HALT line
+//-------------------------------------------------
+
+TIMER_CALLBACK_MEMBER(cococart_slot_device::halt_line_timer_tick)
+{
+ set_line(line::HALT, m_halt_line, (line_value) param);
+}
+
+
//-------------------------------------------------
// cts_read
//-------------------------------------------------
-READ8_MEMBER(cococart_slot_device::cts_read)
+u8 cococart_slot_device::cts_read(offs_t offset)
{
- uint8_t result = 0x00;
+ u8 result = 0x00;
if (m_cart)
- result = m_cart->cts_read(space, offset);
+ result = m_cart->cts_read(offset);
return result;
}
@@ -168,10 +240,10 @@ READ8_MEMBER(cococart_slot_device::cts_read)
// cts_write
//-------------------------------------------------
-WRITE8_MEMBER(cococart_slot_device::cts_write)
+void cococart_slot_device::cts_write(offs_t offset, u8 data)
{
if (m_cart)
- m_cart->cts_write(space, offset, data);
+ m_cart->cts_write(offset, data);
}
@@ -179,11 +251,11 @@ WRITE8_MEMBER(cococart_slot_device::cts_write)
// scs_read
//-------------------------------------------------
-READ8_MEMBER(cococart_slot_device::scs_read)
+u8 cococart_slot_device::scs_read(offs_t offset)
{
- uint8_t result = 0x00;
+ u8 result = 0x00;
if (m_cart)
- result = m_cart->scs_read(space, offset);
+ result = m_cart->scs_read(offset);
return result;
}
@@ -192,10 +264,10 @@ READ8_MEMBER(cococart_slot_device::scs_read)
// scs_write
//-------------------------------------------------
-WRITE8_MEMBER(cococart_slot_device::scs_write)
+void cococart_slot_device::scs_write(offs_t offset, u8 data)
{
if (m_cart)
- m_cart->scs_write(space, offset, data);
+ m_cart->scs_write(offset, data);
}
@@ -229,14 +301,26 @@ const char *cococart_slot_device::line_value_string(line_value value)
// set_line
//-------------------------------------------------
-void cococart_slot_device::set_line(const char *line_name, coco_cartridge_line &line, cococart_slot_device::line_value value)
+void cococart_slot_device::set_line(line ln, coco_cartridge_line &line, cococart_slot_device::line_value value)
{
if ((line.value != value) || (value == line_value::Q))
{
line.value = value;
- if (LOG_LINE)
- logerror("[%s]: set_line(): %s <= %s\n", machine().describe_context(), line_name, line_value_string(value));
+ switch (ln)
+ {
+ case line::CART:
+ LOGCART( "set_line: CART, value: %s\n", line_value_string(value));
+ break;
+ case line::NMI:
+ LOGNMI( "set_line: NMI, value: %s\n", line_value_string(value));
+ break;
+ case line::HALT:
+ LOGHALT( "set_line: HALT, value: %s\n", line_value_string(value));
+ break;
+ case line::SOUND_ENABLE:
+ break;
+ }
// engage in a bit of gymnastics for this odious 'Q' value
switch(line.value)
@@ -258,9 +342,8 @@ void cococart_slot_device::set_line(const char *line_name, coco_cartridge_line &
break;
}
- /* invoke the callback, if present */
- if (!(*line.callback).isnull())
- (*line.callback)(line.line);
+ /* invoke the callback */
+ (*line.callback)(line.line);
}
}
@@ -273,8 +356,8 @@ void cococart_slot_device::set_line_timer(coco_cartridge_line &line, cococart_sl
{
// calculate delay; delay dependant on cycles per second
attotime delay = (line.delay != 0)
- ? clocks_to_attotime(line.delay)
- : attotime::zero;
+ ? clocks_to_attotime(line.delay)
+ : attotime::zero;
line.timer[line.timer_index]->adjust(delay, (int) value);
line.timer_index = (line.timer_index + 1) % TIMER_POOL;
@@ -395,7 +478,7 @@ cococart_slot_device::line_value cococart_slot_device::get_line_value(cococart_s
// get_cart_base
//-------------------------------------------------
-uint8_t* cococart_slot_device::get_cart_base()
+u8 *cococart_slot_device::get_cart_base()
{
if (m_cart != nullptr)
return m_cart->get_cart_base();
@@ -407,7 +490,7 @@ uint8_t* cococart_slot_device::get_cart_base()
// get_cart_size
//-------------------------------------------------
-uint32_t cococart_slot_device::get_cart_size()
+u32 cococart_slot_device::get_cart_size()
{
if (m_cart != nullptr)
return m_cart->get_cart_size();
@@ -427,35 +510,104 @@ void cococart_slot_device::set_cart_base_update(cococart_base_update_delegate up
//-------------------------------------------------
+// read_coco_rpk
+//-------------------------------------------------
+
+static std::error_condition read_coco_rpk(std::unique_ptr<util::random_read> &&stream, rpk_file::ptr &result)
+{
+ // sanity checks
+ static_assert(std::size(coco_rpk_pcbdefs) - 1 == std::size(coco_rpk_cardslottypes));
+
+ // set up the RPK reader
+ rpk_reader reader(coco_rpk_pcbdefs, false);
+
+ // and read the RPK file
+ return reader.read(std::move(stream), result);
+}
+
+
+//-------------------------------------------------
+// read_coco_rpk
+//-------------------------------------------------
+
+static std::error_condition read_coco_rpk(std::unique_ptr<util::random_read> &&stream, u8 *mem, offs_t cart_length, offs_t &actual_length)
+{
+ actual_length = 0;
+
+ // open the RPK
+ rpk_file::ptr file;
+ std::error_condition err = read_coco_rpk(std::move(stream), file);
+ if (err)
+ return err;
+
+ // for now, we are just going to load all sockets into the contiguous block of memory
+ // that cartridges use
+ offs_t pos = 0;
+ for (const rpk_socket &socket : file->sockets())
+ {
+ // only ROM supported for now; if we see anything else it should have been caught in the RPK code
+ assert(socket.type() == rpk_socket::socket_type::ROM);
+
+ // read all bytes
+ std::vector<uint8_t> contents;
+ err = socket.read_file(contents);
+ if (err)
+ return err;
+
+ // copy the bytes
+ offs_t size = (offs_t) std::min(contents.size(), (size_t)cart_length - pos);
+ memcpy(&mem[pos], &contents[0], size);
+ pos += size;
+ }
+
+ // we're done!
+ actual_length = pos;
+ return std::error_condition();
+}
+
+
+//-------------------------------------------------
// 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)
{
memory_region *cart_mem = m_cart->get_cart_memregion();
- uint8_t *base = cart_mem->base();
+ u8 *base = cart_mem->base();
offs_t read_length, cart_length = cart_mem->bytes();
- if (!loaded_through_softlist())
+ if (loaded_through_softlist())
{
- read_length = fread(base, cart_length);
+ // loaded through softlist
+ read_length = get_software_region_length("rom");
+ memcpy(base, get_software_region("rom"), read_length);
+ }
+ else if (is_filetype("rpk"))
+ {
+ // RPK file
+ util::core_file::ptr proxy;
+ std::error_condition err = util::core_file::open_proxy(image_core_file(), proxy);
+ if (!err)
+ err = read_coco_rpk(std::move(proxy), base, cart_length, read_length);
+ if (err)
+ return std::make_pair(err, std::string());
}
else
{
- read_length = get_software_region_length("rom");
- memcpy(base, get_software_region("rom"), read_length);
+ // conventional ROM image
+ read_length = fread(base, cart_length);
}
while (read_length < cart_length)
{
- offs_t len = std::min(read_length, m_cart->get_cart_size() - read_length);
+ offs_t len = std::min(read_length, cart_length - read_length);
memcpy(base + read_length, base, len);
read_length += len;
}
}
- return image_init_result::PASS;
+ return std::make_pair(std::error_condition(), std::string());
}
@@ -465,9 +617,25 @@ image_init_result cococart_slot_device::call_load()
std::string cococart_slot_device::get_default_card_software(get_default_card_software_hook &hook) const
{
- return software_get_default_slot("pak");
-}
+ // this is the default for anything not in an RPK file
+ int pcb_type = 0;
+ // is this an RPK?
+ if (hook.is_filetype("rpk"))
+ {
+ // RPK file
+ rpk_file::ptr file;
+ util::core_file::ptr proxy;
+ std::error_condition err = util::core_file::open_proxy(*hook.image_file(), proxy);
+ if (!err)
+ err = read_coco_rpk(std::move(proxy), file);
+ if (!err)
+ pcb_type = file->pcb_type();
+ }
+
+ // lookup the default slot
+ return software_get_default_slot(coco_rpk_cardslottypes[pcb_type]);
+}
//**************************************************************************
@@ -483,8 +651,8 @@ template class device_finder<device_cococart_interface, true>;
//-------------------------------------------------
device_cococart_interface::device_cococart_interface(const machine_config &mconfig, device_t &device)
- : device_slot_card_interface(mconfig, device)
- , m_owning_slot(nullptr)
+ : device_interface(device, "cococart")
+ , m_owning_slot(dynamic_cast<cococart_slot_device *>(device.owner()))
, m_host(nullptr)
{
}
@@ -505,10 +673,9 @@ 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;
+ ? dynamic_cast<device_cococart_host_interface *>(m_owning_slot->owner())
+ : nullptr;
}
@@ -530,7 +697,7 @@ void device_cococart_interface::interface_pre_start()
// on the cartridge slot was asserted ($C000-FFEF)
//-------------------------------------------------
-READ8_MEMBER(device_cococart_interface::cts_read)
+u8 device_cococart_interface::cts_read(offs_t offset)
{
return 0x00;
}
@@ -541,7 +708,7 @@ READ8_MEMBER(device_cococart_interface::cts_read)
// on the cartridge slot was asserted ($C000-FFEF)
//-------------------------------------------------
-WRITE8_MEMBER(device_cococart_interface::cts_write)
+void device_cococart_interface::cts_write(offs_t offset, u8 data)
{
}
@@ -551,7 +718,7 @@ WRITE8_MEMBER(device_cococart_interface::cts_write)
// on the cartridge slot was asserted ($FF40-5F)
//-------------------------------------------------
-READ8_MEMBER(device_cococart_interface::scs_read)
+u8 device_cococart_interface::scs_read(offs_t offset)
{
return 0x00;
}
@@ -562,7 +729,7 @@ READ8_MEMBER(device_cococart_interface::scs_read)
// on the cartridge slot was asserted ($FF40-5F)
//-------------------------------------------------
-WRITE8_MEMBER(device_cococart_interface::scs_write)
+void device_cococart_interface::scs_write(offs_t offset, u8 data)
{
}
@@ -580,7 +747,7 @@ void device_cococart_interface::set_sound_enable(bool sound_enable)
// get_cart_base
//-------------------------------------------------
-uint8_t* device_cococart_interface::get_cart_base()
+u8 *device_cococart_interface::get_cart_base()
{
return nullptr;
}
@@ -590,7 +757,7 @@ uint8_t* device_cococart_interface::get_cart_base()
// get_cart_size
//-------------------------------------------------
-uint32_t device_cococart_interface::get_cart_size()
+u32 device_cococart_interface::get_cart_size()
{
return 0x8000;
}
@@ -626,7 +793,7 @@ void device_cococart_interface::cart_base_changed(void)
get_cart_memregion
-------------------------------------------------*/
-memory_region* device_cococart_interface::get_cart_memregion()
+memory_region *device_cococart_interface::get_cart_memregion()
{
return 0;
}
@@ -649,3 +816,107 @@ void device_cococart_interface::set_line_value(cococart_slot_device::line line,
{
owning_slot().set_line_value(line, value);
}
+
+
+//-------------------------------------------------
+// coco_cart_add_basic_devices
+//-------------------------------------------------
+
+void coco_cart_add_basic_devices(device_slot_interface &device)
+{
+ // basic devices, on both the main slot and the Multi-Pak interface
+ device.option_add_internal("banked_16k", COCO_PAK_BANKED);
+ device.option_add_internal("pak", COCO_PAK);
+ device.option_add("ccpsg", COCO_PSG);
+ device.option_add("dcmodem", COCO_DCMODEM);
+ device.option_add("gmc", COCO_PAK_GMC);
+ device.option_add("ide", COCO_IDE);
+ device.option_add("max", COCO_PAK_MAX);
+ device.option_add("midi", COCO_MIDI);
+ device.option_add("orch90", COCO_ORCH90);
+ device.option_add("ram", COCO_PAK_RAM);
+ device.option_add("rs232", COCO_RS232);
+ device.option_add("ssc", COCO_SSC);
+ device.option_add("ssfm", DRAGON_MSX2);
+ device.option_add("stecomp", COCO_STEREO_COMPOSER);
+ device.option_add("sym12", COCO_SYM12);
+ device.option_add("wpk", COCO_WPK);
+ device.option_add("wpk2", COCO_WPK2);
+ device.option_add("wpkrs", COCO_WPKRS);
+ device.option_add("wpk2p", COCO_WPK2P);
+}
+
+
+//-------------------------------------------------
+// coco_cart_add_fdcs
+//-------------------------------------------------
+
+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("cd6809_fdc", CD6809_FDC);
+ device.option_add("cp450_fdc", CP450_FDC);
+ device.option_add("fdc", COCO_FDC);
+ device.option_add("scii", COCO_SCII);
+}
+
+
+//-------------------------------------------------
+// coco_cart_add_multi_pak
+//-------------------------------------------------
+
+void coco_cart_add_multi_pak(device_slot_interface &device)
+{
+ // and the Multi-Pak itself is optional because they cannot be daisy chained
+ device.option_add("multi", COCO_MULTIPAK);
+}
+
+
+//-------------------------------------------------
+// dragon_cart_add_basic_devices
+//-------------------------------------------------
+
+void dragon_cart_add_basic_devices(device_slot_interface &device)
+{
+ device.option_add_internal("amtor", DRAGON_AMTOR);
+ device.option_add("ccpsg", COCO_PSG);
+ device.option_add("claw", DRAGON_CLAW);
+ device.option_add("gmc", COCO_PAK_GMC);
+ device.option_add("jcbsnd", DRAGON_JCBSND);
+ device.option_add("jcbspch", DRAGON_JCBSPCH);
+ device.option_add("max", COCO_PAK_MAX);
+ device.option_add("midi", DRAGON_MIDI);
+ device.option_add("orch90", COCO_ORCH90);
+ device.option_add("pak", COCO_PAK);
+ device.option_add("serial", DRAGON_SERIAL);
+ device.option_add("ram", COCO_PAK_RAM);
+ device.option_add("sprites", DRAGON_SPRITES);
+ device.option_add("ssc", COCO_SSC);
+ device.option_add("ssfm", DRAGON_MSX2);
+ device.option_add("stecomp", COCO_STEREO_COMPOSER);
+ device.option_add("sym12", COCO_SYM12);
+ device.option_add("wpk2p", COCO_WPK2P);
+}
+
+
+//-------------------------------------------------
+// dragon_cart_add_fdcs
+//-------------------------------------------------
+
+void dragon_cart_add_fdcs(device_slot_interface &device)
+{
+ device.option_add("dragon_fdc", DRAGON_FDC);
+ device.option_add("premier_fdc", PREMIER_FDC);
+ device.option_add("sdtandy_fdc", SDTANDY_FDC);
+}
+
+
+//-------------------------------------------------
+// dragon_cart_add_multi_pak
+//-------------------------------------------------
+
+void dragon_cart_add_multi_pak(device_slot_interface &device)
+{
+ device.option_add("multi", DRAGON_MULTIPAK);
+}
diff --git a/src/devices/bus/coco/cococart.h b/src/devices/bus/coco/cococart.h
index bcee3d2990a..4916b9e6398 100644
--- a/src/devices/bus/coco/cococart.h
+++ b/src/devices/bus/coco/cococart.h
@@ -13,7 +13,7 @@
#pragma once
-#include "softlist_dev.h"
+#include "imagedev/cartrom.h"
/***************************************************************************
@@ -23,15 +23,15 @@
// ======================> cococart_base_update_delegate
// direct region update handler
-typedef delegate<void (uint8_t *)> cococart_base_update_delegate;
+typedef delegate<void (u8 *)> cococart_base_update_delegate;
// ======================> cococart_slot_device
class device_cococart_interface;
class cococart_slot_device final : public device_t,
- public device_slot_interface,
- public device_image_interface
+ public device_single_card_slot_interface<device_cococart_interface>,
+ public device_cartrom_image_interface
{
public:
// output lines on the CoCo cartridge slot
@@ -53,7 +53,7 @@ public:
// construction/destruction
template <typename T>
- cococart_slot_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock, T &&opts, const char *dflt)
+ cococart_slot_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock, T &&opts, const char *dflt)
: cococart_slot_device(mconfig, tag, owner, clock)
{
option_reset();
@@ -61,40 +61,32 @@ public:
set_default_option(dflt);
set_fixed(false);
}
- cococart_slot_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
+ cococart_slot_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock);
auto cart_callback() { return m_cart_callback.bind(); }
auto nmi_callback() { return m_nmi_callback.bind(); }
auto halt_callback() { return m_halt_callback.bind(); }
- // device-level overrides
- virtual void device_start() override;
- virtual void device_timer(emu_timer &timer, device_timer_id id, int param, void *ptr) override;
+ // device_t implementation
+ virtual void device_start() override ATTR_COLD;
- // image-level overrides
- virtual image_init_result call_load() override;
- virtual const software_list_loader &get_software_list_loader() const override { return rom_software_list_loader::instance(); }
+ // device_image_interface implementation
+ virtual std::pair<std::error_condition, std::string> call_load() override;
- virtual iodevice_t image_type() const override { return IO_CARTSLOT; }
+ 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"; }
- virtual bool is_readable() const override { return 1; }
- virtual bool is_writeable() const override { return 0; }
- virtual bool is_creatable() const override { return 0; }
- virtual bool must_be_loaded() const override { return 0; }
- virtual bool is_reset_on_load() const override { return 1; }
- virtual const char *image_interface() const override { return "coco_cart"; }
- virtual const char *file_extensions() const 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
- DECLARE_READ8_MEMBER(cts_read);
- DECLARE_WRITE8_MEMBER(cts_write);
+ u8 cts_read(offs_t offset);
+ void cts_write(offs_t offset, u8 data);
// reading and writing to $FF40-$FF5F
- DECLARE_READ8_MEMBER(scs_read);
- DECLARE_WRITE8_MEMBER(scs_write);
+ u8 scs_read(offs_t offset);
+ void scs_write(offs_t offset, u8 data);
// manipulation of cartridge lines
void set_line_value(line line, line_value value);
@@ -105,8 +97,8 @@ public:
void twiddle_q_lines();
// cart base
- uint8_t *get_cart_base();
- virtual uint32_t get_cart_size();
+ u8 *get_cart_base();
+ u32 get_cart_size();
void set_cart_base_update(cococart_base_update_delegate update);
private:
@@ -128,18 +120,26 @@ private:
coco_cartridge_line m_cart_line;
coco_cartridge_line m_nmi_line;
coco_cartridge_line m_halt_line;
+
public:
- devcb_write_line m_cart_callback;
+ devcb_write_line m_cart_callback;
devcb_write_line m_nmi_callback;
devcb_write_line m_halt_callback;
+
private:
// cartridge
device_cococart_interface *m_cart;
// methods
- void set_line(const char *line_name, coco_cartridge_line &line, line_value value);
+ void set_line(line ln, coco_cartridge_line &line, line_value value);
void set_line_timer(coco_cartridge_line &line, line_value value);
void twiddle_line_if_q(coco_cartridge_line &line);
+
+ TIMER_CALLBACK_MEMBER(cart_line_timer_tick);
+ TIMER_CALLBACK_MEMBER(nmi_line_timer_tick);
+ TIMER_CALLBACK_MEMBER(halt_line_timer_tick);
+
+public:
static const char *line_value_string(line_value value);
};
@@ -159,28 +159,27 @@ public:
// ======================> device_cococart_interface
-class device_cococart_interface : public device_slot_card_interface
+class device_cococart_interface : public device_interface
{
public:
// construction/destruction
virtual ~device_cococart_interface();
- virtual DECLARE_READ8_MEMBER(cts_read);
- virtual DECLARE_WRITE8_MEMBER(cts_write);
- virtual DECLARE_READ8_MEMBER(scs_read);
- virtual DECLARE_WRITE8_MEMBER(scs_write);
+ virtual u8 cts_read(offs_t offset);
+ virtual void cts_write(offs_t offset, u8 data);
+ virtual u8 scs_read(offs_t offset);
+ virtual void scs_write(offs_t offset, u8 data);
virtual void set_sound_enable(bool sound_enable);
- virtual uint8_t* get_cart_base();
- virtual uint32_t get_cart_size();
+ virtual u8 *get_cart_base();
+ virtual u32 get_cart_size();
void set_cart_base_update(cococart_base_update_delegate update);
- virtual memory_region* get_cart_memregion();
-
+ virtual memory_region *get_cart_memregion();
+protected:
virtual void interface_config_complete() override;
virtual void interface_pre_start() override;
-protected:
device_cococart_interface(const machine_config &mconfig, device_t &device);
void cart_base_changed(void);
@@ -222,8 +221,17 @@ 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;
};
+// methods for configuring CoCo slot devices (the expansion cart
+// itself, as well as slots on the Multi-Pak)
+void coco_cart_add_basic_devices(device_slot_interface &device);
+void coco_cart_add_fdcs(device_slot_interface &device);
+void coco_cart_add_multi_pak(device_slot_interface &device);
+void dragon_cart_add_basic_devices(device_slot_interface &device);
+void dragon_cart_add_fdcs(device_slot_interface &device);
+void dragon_cart_add_multi_pak(device_slot_interface &device);
+
#endif // MAME_BUS_COCO_COCOCART_H
diff --git a/src/devices/bus/coco/dragon_amtor.cpp b/src/devices/bus/coco/dragon_amtor.cpp
index 9805d408c1f..7ce51671153 100644
--- a/src/devices/bus/coco/dragon_amtor.cpp
+++ b/src/devices/bus/coco/dragon_amtor.cpp
@@ -53,7 +53,7 @@ INPUT_PORTS_END
// dragon_amtor_device - constructor
//-------------------------------------------------
-dragon_amtor_device::dragon_amtor_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
+dragon_amtor_device::dragon_amtor_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock)
: device_t(mconfig, DRAGON_AMTOR, tag, owner, clock)
, device_cococart_interface(mconfig, *this)
, m_eprom(*this, "eprom")
@@ -93,7 +93,7 @@ const tiny_rom_entry *dragon_amtor_device::device_rom_region() const
// dragon_amtor_device::get_cart_base
//-------------------------------------------------
-uint8_t* dragon_amtor_device::get_cart_base()
+u8 *dragon_amtor_device::get_cart_base()
{
return m_eprom->base();
}
@@ -102,7 +102,7 @@ uint8_t* dragon_amtor_device::get_cart_base()
// dragon_amtor_device::get_cart_memregion
//-------------------------------------------------
-memory_region* dragon_amtor_device::get_cart_memregion()
+memory_region *dragon_amtor_device::get_cart_memregion()
{
return m_eprom;
}
@@ -111,7 +111,7 @@ memory_region* dragon_amtor_device::get_cart_memregion()
// cts_read
//-------------------------------------------------
-READ8_MEMBER(dragon_amtor_device::cts_read)
+u8 dragon_amtor_device::cts_read(offs_t offset)
{
offset = bitswap<16>(offset, 15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 0, 1);
diff --git a/src/devices/bus/coco/dragon_amtor.h b/src/devices/bus/coco/dragon_amtor.h
index 34cea662110..d8f7cb7a568 100644
--- a/src/devices/bus/coco/dragon_amtor.h
+++ b/src/devices/bus/coco/dragon_amtor.h
@@ -19,19 +19,19 @@ class dragon_amtor_device :
{
public:
// construction/destruction
- dragon_amtor_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
+ dragon_amtor_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock);
// optional information overrides
- virtual const tiny_rom_entry *device_rom_region() const override;
- virtual ioport_constructor device_input_ports() const override;
+ virtual const tiny_rom_entry *device_rom_region() const override ATTR_COLD;
+ virtual ioport_constructor device_input_ports() const override ATTR_COLD;
protected:
// device-level overrides
- virtual void device_start() override;
- virtual uint8_t* get_cart_base() override;
- virtual memory_region* get_cart_memregion() override;
+ virtual void device_start() override ATTR_COLD;
+ virtual u8 *get_cart_base() override;
+ virtual memory_region *get_cart_memregion() override;
- virtual DECLARE_READ8_MEMBER(cts_read) override;
+ virtual u8 cts_read(offs_t offset) override;
private:
required_memory_region m_eprom;
diff --git a/src/devices/bus/coco/dragon_claw.cpp b/src/devices/bus/coco/dragon_claw.cpp
new file mode 100644
index 00000000000..54d99c6dc9a
--- /dev/null
+++ b/src/devices/bus/coco/dragon_claw.cpp
@@ -0,0 +1,212 @@
+// license:BSD-3-Clause
+// copyright-holders:Nigel Barnes
+/***************************************************************************
+
+ The Dragon's Claw from Lucidata
+
+ http://archive.worldofdragon.org/index.php?title=The_Dragon%27s_Claw
+
+ The Dragon's Claw is an extension cartridge for the Dragon by Lucidata.
+ It features two parallel I/O ports. One with the BBC User Port pinout,
+ and the second with a Centronics Printer Port pinout.
+
+***************************************************************************/
+
+#include "emu.h"
+#include "dragon_claw.h"
+#include "bus/bbc/userport/userport.h"
+#include "bus/centronics/ctronics.h"
+
+
+//**************************************************************************
+// GLOBAL VARIABLES
+//**************************************************************************
+
+DEFINE_DEVICE_TYPE_PRIVATE(DRAGON_CLAW, device_cococart_interface, dragon_claw_device, "dragon_claw", "The Dragon's Claw")
+
+//-------------------------------------------------
+// INPUT_PORTS( claw )
+//-------------------------------------------------
+
+INPUT_PORTS_START(claw)
+ PORT_START("LINKS")
+ PORT_CONFNAME(0x03, 0x00, "L1 Address Selection")
+ PORT_CONFSETTING(0x00, "$FF80")
+ PORT_CONFSETTING(0x01, "$FF90")
+ PORT_CONFSETTING(0x02, "$FFA0")
+ PORT_CONFSETTING(0x03, "$FFB0")
+ PORT_CONFNAME(0x04, 0x00, "L2 Interrupt Line")
+ PORT_CONFSETTING(0x00, "NMI")
+ PORT_CONFSETTING(0x04, "CART")
+INPUT_PORTS_END
+
+
+//-------------------------------------------------
+// input_ports - device-specific input ports
+//-------------------------------------------------
+
+ioport_constructor dragon_claw_device::device_input_ports() const
+{
+ return INPUT_PORTS_NAME(claw);
+}
+
+
+//**************************************************************************
+// LIVE DEVICE
+//**************************************************************************
+
+//-------------------------------------------------
+// dragon_claw_device - constructor
+//-------------------------------------------------
+
+dragon_claw_device::dragon_claw_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock)
+ : device_t(mconfig, DRAGON_CLAW, tag, owner, clock)
+ , device_cococart_interface(mconfig, *this )
+ , m_via(*this, "via")
+ , m_slot(*this, "slot")
+ , m_links(*this, "LINKS")
+{
+}
+
+//-------------------------------------------------
+// device_start - device-specific startup
+//-------------------------------------------------
+
+void dragon_claw_device::device_start()
+{
+}
+
+//-------------------------------------------------
+// device_reset - device-specific reset
+//-------------------------------------------------
+
+void dragon_claw_device::device_reset()
+{
+ uint8_t addr = (m_links->read() & 0x03) << 8;
+
+ install_readwrite_handler(0xff80 | addr, 0xff8f | addr, read8sm_delegate(*m_via, FUNC(via6522_device::read)), write8sm_delegate(*m_via, FUNC(via6522_device::write)));
+}
+
+static void dragon_cart(device_slot_interface &device)
+{
+ dragon_cart_add_basic_devices(device);
+ dragon_cart_add_fdcs(device);
+}
+
+//-------------------------------------------------
+// device_add_mconfig - add device configuration
+//-------------------------------------------------
+
+void dragon_claw_device::device_add_mconfig(machine_config &config)
+{
+ MOS6522(config, m_via, DERIVED_CLOCK(1, 1));
+ m_via->writepa_handler().set("cent_data_out", FUNC(output_latch_device::write));
+ m_via->readpb_handler().set("userport", FUNC(bbc_userport_slot_device::pb_r));
+ m_via->writepb_handler().set("userport", FUNC(bbc_userport_slot_device::pb_w));
+ m_via->ca2_handler().set("centronics", FUNC(centronics_device::write_strobe));
+ m_via->cb1_handler().set("userport", FUNC(bbc_userport_slot_device::write_cb1));
+ m_via->cb2_handler().set("userport", FUNC(bbc_userport_slot_device::write_cb2));
+ m_via->irq_handler().set(FUNC(dragon_claw_device::irq_w)); // link L2 selects either NMI or CART line
+
+ bbc_userport_slot_device &userport(BBC_USERPORT_SLOT(config, "userport", bbc_userport_devices, nullptr));
+ userport.cb1_handler().set(m_via, FUNC(via6522_device::write_cb1));
+ userport.cb2_handler().set(m_via, FUNC(via6522_device::write_cb2));
+
+ centronics_device &centronics(CENTRONICS(config, "centronics", centronics_devices, nullptr));
+ centronics.ack_handler().set(m_via, FUNC(via6522_device::write_ca1));
+ output_latch_device &latch(OUTPUT_LATCH(config, "cent_data_out"));
+ centronics.set_output_latch(latch);
+
+ COCOCART_SLOT(config, m_slot, DERIVED_CLOCK(1, 1), dragon_cart, nullptr);
+ m_slot->cart_callback().set([this](int state) { set_line_value(line::CART, state); });
+ m_slot->nmi_callback().set([this](int state) { set_line_value(line::NMI, state); });
+ m_slot->halt_callback().set([this](int state) { set_line_value(line::HALT, state); });
+}
+
+void dragon_claw_device::irq_w(int state)
+{
+ if (m_links->read() & 0x04)
+ set_line_value(line::CART, state);
+ else
+ set_line_value(line::NMI, state);
+}
+
+
+//-------------------------------------------------
+// set_sound_enable
+//-------------------------------------------------
+
+void dragon_claw_device::set_sound_enable(bool sound_enable)
+{
+ m_slot->set_line_value(line::SOUND_ENABLE, sound_enable ? line_value::ASSERT : line_value::CLEAR);
+}
+
+
+//-------------------------------------------------
+// get_cart_base
+//-------------------------------------------------
+
+u8 *dragon_claw_device::get_cart_base()
+{
+ return m_slot->get_cart_base();
+}
+
+
+//-------------------------------------------------
+// get_cart_size
+//-------------------------------------------------
+
+u32 dragon_claw_device::get_cart_size()
+{
+ return m_slot->get_cart_size();
+}
+
+
+//-------------------------------------------------
+// cts_read
+//-------------------------------------------------
+
+u8 dragon_claw_device::cts_read(offs_t offset)
+{
+ return m_slot->cts_read(offset);
+}
+
+
+//-------------------------------------------------
+// cts_write
+//-------------------------------------------------
+
+void dragon_claw_device::cts_write(offs_t offset, u8 data)
+{
+ m_slot->cts_write(offset, data);
+}
+
+
+//-------------------------------------------------
+// scs_read
+//-------------------------------------------------
+
+u8 dragon_claw_device::scs_read(offs_t offset)
+{
+ return m_slot->scs_read(offset);
+}
+
+
+//-------------------------------------------------
+// scs_write
+//-------------------------------------------------
+
+void dragon_claw_device::scs_write(offs_t offset, u8 data)
+{
+ m_slot->scs_write(offset, data);
+}
+
+
+//-------------------------------------------------
+// cartridge_space
+//-------------------------------------------------
+
+address_space &dragon_claw_device::cartridge_space()
+{
+ return device_cococart_interface::cartridge_space();
+}
diff --git a/src/devices/bus/coco/dragon_claw.h b/src/devices/bus/coco/dragon_claw.h
new file mode 100644
index 00000000000..ec82349d4e5
--- /dev/null
+++ b/src/devices/bus/coco/dragon_claw.h
@@ -0,0 +1,59 @@
+// license:BSD-3-Clause
+// copyright-holders:Nigel Barnes
+#ifndef MAME_BUS_COCO_DRAGON_CLAW_H
+#define MAME_BUS_COCO_DRAGON_CLAW_H
+
+#pragma once
+
+#include "cococart.h"
+#include "machine/6522via.h"
+
+
+//**************************************************************************
+// TYPE DEFINITIONS
+//**************************************************************************
+
+// ======================> dragon_claw_device
+
+class dragon_claw_device :
+ public device_t,
+ public device_cococart_interface,
+ public device_cococart_host_interface
+{
+public:
+ // construction/destruction
+ dragon_claw_device(const machine_config& mconfig, const char* tag, device_t* owner, u32 clock);
+
+protected:
+ // device-level overrides
+ virtual void device_start() override ATTR_COLD;
+ virtual void device_reset() override ATTR_COLD;
+
+ // optional information overrides
+ virtual void device_add_mconfig(machine_config& config) override;
+ virtual ioport_constructor device_input_ports() const override ATTR_COLD;
+
+ virtual u8 cts_read(offs_t offset) override;
+ virtual void cts_write(offs_t offset, u8 data) override;
+ virtual u8 scs_read(offs_t offset) override;
+ virtual void scs_write(offs_t offset, u8 data) override;
+ virtual void set_sound_enable(bool sound_enable) override;
+
+ virtual u8 *get_cart_base() override;
+ virtual u32 get_cart_size() override;
+
+ virtual address_space &cartridge_space() override;
+
+private:
+ void irq_w(int state);
+
+ required_device<via6522_device> m_via;
+ required_device<cococart_slot_device> m_slot;
+ required_ioport m_links;
+};
+
+
+// device type definition
+DECLARE_DEVICE_TYPE(DRAGON_CLAW, device_cococart_interface)
+
+#endif // MAME_BUS_COCO_DRAGON_CLAW_H
diff --git a/src/devices/bus/coco/dragon_fdc.cpp b/src/devices/bus/coco/dragon_fdc.cpp
index 48ab81501a5..7f6d9c41cd0 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"
/***************************************************************************
@@ -96,13 +97,13 @@ namespace
{
protected:
// construction/destruction
- dragon_fdc_device_base(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock);
+ dragon_fdc_device_base(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, u32 clock);
// device-level overrides
- virtual DECLARE_READ8_MEMBER(cts_read) override;
- virtual DECLARE_READ8_MEMBER(scs_read) override;
- virtual DECLARE_WRITE8_MEMBER(scs_write) override;
- virtual void device_add_mconfig(machine_config &config) 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;
+ virtual void device_add_mconfig(machine_config &config) override ATTR_COLD;
virtual void update_lines() override;
private:
@@ -111,20 +112,20 @@ namespace
required_device_array<floppy_connector, 4> m_floppies;
// methods
- void dskreg_w(uint8_t data);
+ void dskreg_w(u8 data);
};
class premier_fdc_device_base : public coco_family_fdc_device_base
{
protected:
// construction/destruction
- premier_fdc_device_base(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock);
+ premier_fdc_device_base(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, u32 clock);
// device-level overrides
- virtual DECLARE_READ8_MEMBER(cts_read) override;
- virtual DECLARE_READ8_MEMBER(scs_read) override;
- virtual DECLARE_WRITE8_MEMBER(scs_write) override;
- virtual void device_add_mconfig(machine_config &config) 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;
+ virtual void device_add_mconfig(machine_config &config) override ATTR_COLD;
virtual void update_lines() override;
private:
@@ -133,7 +134,7 @@ namespace
required_device_array<floppy_connector, 4> m_floppies;
// methods
- void dskreg_w(uint8_t data);
+ void dskreg_w(u8 data);
};
}
@@ -155,8 +156,8 @@ void dragon_fdc_device_base::device_add_mconfig(machine_config &config)
FLOPPY_CONNECTOR(config, m_floppies[0], dragon_fdc_drives, "qd", dragon_fdc_device_base::floppy_formats).enable_sound(true);
FLOPPY_CONNECTOR(config, m_floppies[1], dragon_fdc_drives, "qd", dragon_fdc_device_base::floppy_formats).enable_sound(true);
- FLOPPY_CONNECTOR(config, m_floppies[2], dragon_fdc_drives, "", dragon_fdc_device_base::floppy_formats).enable_sound(true);
- FLOPPY_CONNECTOR(config, m_floppies[3], dragon_fdc_drives, "", dragon_fdc_device_base::floppy_formats).enable_sound(true);
+ FLOPPY_CONNECTOR(config, m_floppies[2], dragon_fdc_drives, nullptr, dragon_fdc_device_base::floppy_formats).enable_sound(true);
+ FLOPPY_CONNECTOR(config, m_floppies[3], dragon_fdc_drives, nullptr, dragon_fdc_device_base::floppy_formats).enable_sound(true);
}
@@ -166,8 +167,8 @@ void premier_fdc_device_base::device_add_mconfig(machine_config &config)
FLOPPY_CONNECTOR(config, m_floppies[0], dragon_fdc_drives, "qd", dragon_fdc_device_base::floppy_formats).enable_sound(true);
FLOPPY_CONNECTOR(config, m_floppies[1], dragon_fdc_drives, "qd", dragon_fdc_device_base::floppy_formats).enable_sound(true);
- FLOPPY_CONNECTOR(config, m_floppies[2], dragon_fdc_drives, "", dragon_fdc_device_base::floppy_formats).enable_sound(true);
- FLOPPY_CONNECTOR(config, m_floppies[3], dragon_fdc_drives, "", dragon_fdc_device_base::floppy_formats).enable_sound(true);
+ FLOPPY_CONNECTOR(config, m_floppies[2], dragon_fdc_drives, nullptr, dragon_fdc_device_base::floppy_formats).enable_sound(true);
+ FLOPPY_CONNECTOR(config, m_floppies[3], dragon_fdc_drives, nullptr, dragon_fdc_device_base::floppy_formats).enable_sound(true);
}
@@ -178,7 +179,7 @@ void premier_fdc_device_base::device_add_mconfig(machine_config &config)
//-------------------------------------------------
// dragon_fdc_device_base - constructor
//-------------------------------------------------
-dragon_fdc_device_base::dragon_fdc_device_base(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock)
+dragon_fdc_device_base::dragon_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_wd2797(*this, "wd2797")
, m_floppies(*this, "wd2797:%u", 0)
@@ -186,7 +187,7 @@ dragon_fdc_device_base::dragon_fdc_device_base(const machine_config &mconfig, de
}
-premier_fdc_device_base::premier_fdc_device_base(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock)
+premier_fdc_device_base::premier_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_wd2791(*this, "wd2791")
, m_floppies(*this, "wd2791:%u", 0)
@@ -219,21 +220,18 @@ void premier_fdc_device_base::update_lines()
// Dragon dskreg
//-------------------------------------------------
-void dragon_fdc_device_base::dskreg_w(uint8_t data)
+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++)
@@ -251,21 +249,18 @@ void dragon_fdc_device_base::dskreg_w(uint8_t data)
}
-void premier_fdc_device_base::dskreg_w(uint8_t 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
@@ -293,13 +288,13 @@ void premier_fdc_device_base::dskreg_w(uint8_t data)
// cts_read
//-------------------------------------------------
-READ8_MEMBER(dragon_fdc_device_base::cts_read)
+u8 dragon_fdc_device_base::cts_read(offs_t offset)
{
return memregion("eprom")->base()[offset];
}
-READ8_MEMBER(premier_fdc_device_base::cts_read)
+u8 premier_fdc_device_base::cts_read(offs_t offset)
{
return memregion("eprom")->base()[offset];
}
@@ -309,9 +304,9 @@ READ8_MEMBER(premier_fdc_device_base::cts_read)
// scs_read
//-------------------------------------------------
-READ8_MEMBER(dragon_fdc_device_base::scs_read)
+u8 dragon_fdc_device_base::scs_read(offs_t offset)
{
- uint8_t result = 0;
+ u8 result = 0;
switch (offset & 0xef)
{
case 0:
@@ -325,9 +320,9 @@ READ8_MEMBER(dragon_fdc_device_base::scs_read)
}
-READ8_MEMBER(premier_fdc_device_base::scs_read)
+u8 premier_fdc_device_base::scs_read(offs_t offset)
{
- uint8_t result = 0;
+ u8 result = 0;
switch (offset)
{
case 0:
@@ -345,7 +340,7 @@ READ8_MEMBER(premier_fdc_device_base::scs_read)
// scs_write
//-------------------------------------------------
-WRITE8_MEMBER(dragon_fdc_device_base::scs_write)
+void dragon_fdc_device_base::scs_write(offs_t offset, u8 data)
{
switch (offset & 0xef)
{
@@ -363,7 +358,7 @@ WRITE8_MEMBER(dragon_fdc_device_base::scs_write)
}
-WRITE8_MEMBER(premier_fdc_device_base::scs_write)
+void premier_fdc_device_base::scs_write(offs_t offset, u8 data)
{
switch (offset)
{
@@ -395,7 +390,7 @@ namespace
{
public:
// construction/destruction
- dragon_fdc_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
+ dragon_fdc_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock)
: dragon_fdc_device_base(mconfig, DRAGON_FDC, tag, owner, clock)
{
}
@@ -427,7 +422,7 @@ namespace
{
public:
// construction/destruction
- premier_fdc_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
+ premier_fdc_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock)
: premier_fdc_device_base(mconfig, PREMIER_FDC, tag, owner, clock)
{
}
@@ -459,7 +454,7 @@ namespace
{
public:
// construction/destruction
- sdtandy_fdc_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
+ sdtandy_fdc_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock)
: dragon_fdc_device_base(mconfig, SDTANDY_FDC, tag, owner, clock)
{
}
diff --git a/src/devices/bus/coco/dragon_jcbsnd.cpp b/src/devices/bus/coco/dragon_jcbsnd.cpp
index c193e72eb80..fc5b8390f89 100644
--- a/src/devices/bus/coco/dragon_jcbsnd.cpp
+++ b/src/devices/bus/coco/dragon_jcbsnd.cpp
@@ -40,7 +40,7 @@ DEFINE_DEVICE_TYPE(DRAGON_JCBSND, dragon_jcbsnd_device, "dragon_jcbsnd", "Dragon
// dragon_jcbsnd_device - constructor
//-------------------------------------------------
-dragon_jcbsnd_device::dragon_jcbsnd_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
+dragon_jcbsnd_device::dragon_jcbsnd_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock)
: device_t(mconfig, DRAGON_JCBSND, tag, owner, clock)
, device_cococart_interface(mconfig, *this )
, m_eprom(*this, "eprom")
@@ -61,7 +61,7 @@ void dragon_jcbsnd_device::device_start()
// dragon_jcbsnd_device::get_cart_base
//-------------------------------------------------
-uint8_t* dragon_jcbsnd_device::get_cart_base()
+u8 *dragon_jcbsnd_device::get_cart_base()
{
return m_eprom->base();
}
@@ -70,7 +70,7 @@ uint8_t* dragon_jcbsnd_device::get_cart_base()
// dragon_jcbsnd_device::get_cart_memregion
//-------------------------------------------------
-memory_region* dragon_jcbsnd_device::get_cart_memregion()
+memory_region *dragon_jcbsnd_device::get_cart_memregion()
{
return m_eprom;
}
@@ -99,7 +99,7 @@ const tiny_rom_entry *dragon_jcbsnd_device::device_rom_region() const
// cts_read
//-------------------------------------------------
-READ8_MEMBER(dragon_jcbsnd_device::cts_read)
+u8 dragon_jcbsnd_device::cts_read(offs_t offset)
{
if (offset == 0x3eff)
return m_ay8910->data_r();
@@ -111,7 +111,7 @@ READ8_MEMBER(dragon_jcbsnd_device::cts_read)
// cts_write
//-------------------------------------------------
-WRITE8_MEMBER(dragon_jcbsnd_device::cts_write)
+void dragon_jcbsnd_device::cts_write(offs_t offset, u8 data)
{
if ((offset & ~1) == 0x3efe)
m_ay8910->address_data_w(offset & 1, data);
diff --git a/src/devices/bus/coco/dragon_jcbsnd.h b/src/devices/bus/coco/dragon_jcbsnd.h
index a22f6edd69b..9f6990ac7bf 100644
--- a/src/devices/bus/coco/dragon_jcbsnd.h
+++ b/src/devices/bus/coco/dragon_jcbsnd.h
@@ -20,19 +20,19 @@ class dragon_jcbsnd_device :
{
public:
// construction/destruction
- dragon_jcbsnd_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
+ dragon_jcbsnd_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock);
// optional information overrides
- virtual void device_add_mconfig(machine_config &config) override;
- virtual const tiny_rom_entry *device_rom_region() const override;
+ virtual void device_add_mconfig(machine_config &config) override ATTR_COLD;
+ virtual const tiny_rom_entry *device_rom_region() const override ATTR_COLD;
protected:
// device-level overrides
- virtual void device_start() override;
- virtual uint8_t* get_cart_base() override;
- virtual memory_region* get_cart_memregion() override;
+ virtual void device_start() override ATTR_COLD;
+ virtual u8 *get_cart_base() override;
+ virtual memory_region *get_cart_memregion() override;
- virtual DECLARE_READ8_MEMBER(cts_read) override;
- virtual DECLARE_WRITE8_MEMBER(cts_write) override;
+ virtual u8 cts_read(offs_t offset) override;
+ virtual void cts_write(offs_t offset, u8 data) override;
// internal state
device_image_interface *m_cart;
diff --git a/src/devices/bus/coco/dragon_jcbspch.cpp b/src/devices/bus/coco/dragon_jcbspch.cpp
index 9d774934066..71ba15ce267 100644
--- a/src/devices/bus/coco/dragon_jcbspch.cpp
+++ b/src/devices/bus/coco/dragon_jcbspch.cpp
@@ -41,7 +41,7 @@ DEFINE_DEVICE_TYPE(DRAGON_JCBSPCH, dragon_jcbspch_device, "dragon_jcbspch", "Dra
// dragon_jcbspch_device - constructor
//-------------------------------------------------
-dragon_jcbspch_device::dragon_jcbspch_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
+dragon_jcbspch_device::dragon_jcbspch_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock)
: device_t(mconfig, DRAGON_JCBSPCH, tag, owner, clock)
, device_cococart_interface(mconfig, *this )
, m_eprom(*this, "eprom")
@@ -63,7 +63,7 @@ void dragon_jcbspch_device::device_start()
// dragon_jcbspch_device::get_cart_base
//-------------------------------------------------
-uint8_t* dragon_jcbspch_device::get_cart_base()
+u8 *dragon_jcbspch_device::get_cart_base()
{
return m_eprom->base();
}
@@ -72,7 +72,7 @@ uint8_t* dragon_jcbspch_device::get_cart_base()
// dragon_jcbspch_device::get_cart_memregion
//-------------------------------------------------
-memory_region* dragon_jcbspch_device::get_cart_memregion()
+memory_region *dragon_jcbspch_device::get_cart_memregion()
{
return m_eprom;
}
@@ -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));
@@ -107,7 +107,7 @@ const tiny_rom_entry *dragon_jcbspch_device::device_rom_region() const
// cts_read
//-------------------------------------------------
-READ8_MEMBER(dragon_jcbspch_device::cts_read)
+u8 dragon_jcbspch_device::cts_read(offs_t offset)
{
return m_eprom->base()[offset & 0x0fff];
}
@@ -116,9 +116,9 @@ READ8_MEMBER(dragon_jcbspch_device::cts_read)
// scs_read
//-------------------------------------------------
-READ8_MEMBER(dragon_jcbspch_device::scs_read)
+u8 dragon_jcbspch_device::scs_read(offs_t offset)
{
- uint8_t result = 0x00;
+ u8 result = 0x00;
switch (offset)
{
@@ -133,7 +133,7 @@ READ8_MEMBER(dragon_jcbspch_device::scs_read)
// scs_write
//-------------------------------------------------
-WRITE8_MEMBER(dragon_jcbspch_device::scs_write)
+void dragon_jcbspch_device::scs_write(offs_t offset, u8 data)
{
switch (offset)
{
@@ -143,12 +143,12 @@ WRITE8_MEMBER(dragon_jcbspch_device::scs_write)
}
}
-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 af11762c04a..7706aae64e1 100644
--- a/src/devices/bus/coco/dragon_jcbspch.h
+++ b/src/devices/bus/coco/dragon_jcbspch.h
@@ -21,24 +21,24 @@ class dragon_jcbspch_device :
{
public:
// construction/destruction
- dragon_jcbspch_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
+ dragon_jcbspch_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock);
// optional information overrides
- virtual void device_add_mconfig(machine_config &config) override;
- virtual const tiny_rom_entry *device_rom_region() const override;
+ virtual void device_add_mconfig(machine_config &config) override ATTR_COLD;
+ virtual const tiny_rom_entry *device_rom_region() const override ATTR_COLD;
protected:
// device-level overrides
- virtual void device_start() override;
- virtual uint8_t* get_cart_base() override;
- virtual memory_region* get_cart_memregion() override;
+ virtual void device_start() override ATTR_COLD;
+ virtual u8 *get_cart_base() override;
+ virtual memory_region *get_cart_memregion() override;
- virtual DECLARE_READ8_MEMBER(cts_read) override;
- virtual DECLARE_READ8_MEMBER(scs_read) override;
- virtual DECLARE_WRITE8_MEMBER(scs_write) 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(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_msx2.cpp b/src/devices/bus/coco/dragon_msx2.cpp
new file mode 100644
index 00000000000..a8da5565991
--- /dev/null
+++ b/src/devices/bus/coco/dragon_msx2.cpp
@@ -0,0 +1,191 @@
+// license:BSD-3-Clause
+// copyright-holders:Nigel Barnes
+// thanks-to:John Whitworth
+/***************************************************************************
+
+ SuperSprite FM+ by DragonPlus Electronics (formerly Dragon MSX 2+)
+
+***************************************************************************/
+
+#include "emu.h"
+#include "dragon_msx2.h"
+#include "render.h"
+#include "screen.h"
+#include "speaker.h"
+
+
+//**************************************************************************
+// GLOBAL VARIABLES
+//**************************************************************************
+
+DEFINE_DEVICE_TYPE(DRAGON_MSX2, dragon_msx2_device, "dragon_msx2", "6x09 SuperSprite FM+")
+
+
+//-------------------------------------------------
+// INPUT_PORTS( dragon_msx2 )
+//-------------------------------------------------
+
+INPUT_PORTS_START( dragon_msx2 )
+ PORT_START("CONFIG")
+ PORT_CONFNAME(0x01, 0x00, "J1 PWR")
+ PORT_CONFSETTING(0x00, "Cart Port")
+ PORT_CONFSETTING(0x01, "External")
+ PORT_CONFNAME(0x02, 0x00, "J2 CART")
+ PORT_CONFSETTING(0x00, "N/C")
+ PORT_CONFSETTING(0x02, "HSYNC")
+ PORT_CONFNAME(0x04, 0x00, "J3 Port Select")
+ PORT_CONFSETTING(0x00, "FF7* (Native)")
+ PORT_CONFSETTING(0x04, "FF5* (MPI)")
+ PORT_CONFNAME(0x08, 0x08, "J4 Default Video")
+ PORT_CONFSETTING(0x00, "V9958")
+ PORT_CONFSETTING(0x08, "MC6847")
+ PORT_CONFNAME(0x10, 0x10, "J5 Video Lock")
+ PORT_CONFSETTING(0x00, "Locked")
+ PORT_CONFSETTING(0x10, "Unlocked")
+INPUT_PORTS_END
+
+
+//-------------------------------------------------
+// input_ports - device-specific input ports
+//-------------------------------------------------
+
+ioport_constructor dragon_msx2_device::device_input_ports() const
+{
+ return INPUT_PORTS_NAME( dragon_msx2 );
+}
+
+
+//**************************************************************************
+// LIVE DEVICE
+//**************************************************************************
+
+//-------------------------------------------------
+// dragon_msx2_device - constructor
+//-------------------------------------------------
+
+dragon_msx2_device::dragon_msx2_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock)
+ : device_t(mconfig, DRAGON_MSX2, tag, owner, clock)
+ , device_cococart_interface(mconfig, *this )
+ , m_ym2413(*this, "ym2413")
+ , m_v9958(*this, "v9958")
+ , m_ym2149(*this, "ym2149")
+ , m_config(*this, "CONFIG")
+{
+}
+
+//-------------------------------------------------
+// device_start - device-specific startup
+//-------------------------------------------------
+
+void dragon_msx2_device::device_start()
+{
+}
+
+//-------------------------------------------------
+// device_reset - device-specific reset
+//-------------------------------------------------
+
+void dragon_msx2_device::device_reset()
+{
+ // pin 26 is tied to GND
+ m_ym2149->set_pin26_low_w();
+
+ // Native mode
+ if (!BIT(m_config->read(), 2))
+ {
+ install_readwrite_handler(0xff76, 0xff77, read8sm_delegate(*m_ym2413, FUNC(ym2413_device::read)), write8sm_delegate(*m_ym2413, FUNC(ym2413_device::write)));
+ install_readwrite_handler(0xff78, 0xff7b, read8sm_delegate(*m_v9958, FUNC(v9958_device::read)), write8sm_delegate(*m_v9958, FUNC(v9958_device::write)));
+ install_write_handler(0xff7c, 0xff7c, write8smo_delegate(*m_ym2149, FUNC(ym2149_device::address_w)));
+ install_readwrite_handler(0xff7d, 0xff7d, read8smo_delegate(*m_ym2149, FUNC(ym2149_device::data_r)), write8smo_delegate(*m_ym2149, FUNC(ym2149_device::data_w)));
+ install_write_handler(0xff7e, 0xff7e, write8smo_delegate(*this, FUNC(dragon_msx2_device::video_select_w)));
+ }
+
+ // Default Video
+ machine().render().first_target()->set_view(!BIT(m_config->read(), 3));
+}
+
+//-------------------------------------------------
+// device_add_mconfig - add device configuration
+//-------------------------------------------------
+
+void dragon_msx2_device::device_add_mconfig(machine_config &config)
+{
+ V9958(config, m_v9958, 21.477272_MHz_XTAL);
+ m_v9958->set_screen_pal("screen");
+ m_v9958->set_vram_size(0x20000);
+ m_v9958->int_cb().set([this](int state) { set_line_value(line::NMI, state); });
+ SCREEN(config, "screen", SCREEN_TYPE_RASTER);
+
+ SPEAKER(config, "speaker").front_center();
+ YM2413(config, m_ym2413, 21.477272_MHz_XTAL / 6).add_route(ALL_OUTPUTS, "speaker", 1.0);
+ YM2149(config, m_ym2149, 21.477272_MHz_XTAL / 6).add_route(ALL_OUTPUTS, "speaker", 1.0);
+}
+
+
+//-------------------------------------------------
+// scs_read
+//-------------------------------------------------
+
+u8 dragon_msx2_device::scs_read(offs_t offset)
+{
+ u8 data = 0x00;
+
+ if (BIT(m_config->read(), 2)) // MPI mode
+ {
+ switch (offset)
+ {
+ case 0x16: case 0x17:
+ data = m_ym2413->read(offset & 1);
+ break;
+
+ case 0x18: case 0x19: case 0x1a: case 0x1b:
+ data = m_v9958->read(offset & 3);
+ break;
+
+ case 0x1d:
+ data = m_ym2149->data_r();
+ break;
+ }
+ }
+
+ return data;
+}
+
+//-------------------------------------------------
+// scs_write
+//-------------------------------------------------
+
+void dragon_msx2_device::scs_write(offs_t offset, u8 data)
+{
+ if (BIT(m_config->read(), 2)) // MPI mode
+ {
+ switch (offset)
+ {
+ case 0x16: case 0x17:
+ m_ym2413->write(offset & 1, data);
+ break;
+
+ case 0x18: case 0x19: case 0x1a: case 0x1b:
+ m_v9958->write(offset & 3, data);
+ break;
+
+ case 0x1c:
+ m_ym2149->address_w(data);
+ break;
+
+ case 0x1d:
+ m_ym2149->data_w(data);
+ break;
+
+ case 0x1e:
+ video_select_w(data);
+ break;
+ }
+ }
+}
+
+void dragon_msx2_device::video_select_w(u8 data)
+{
+ if (BIT(m_config->read(), 4)) // Unlocked
+ machine().render().first_target()->set_view(!BIT(data, 0));
+}
diff --git a/src/devices/bus/coco/dragon_msx2.h b/src/devices/bus/coco/dragon_msx2.h
new file mode 100644
index 00000000000..e4aaf3990f0
--- /dev/null
+++ b/src/devices/bus/coco/dragon_msx2.h
@@ -0,0 +1,53 @@
+// license:BSD-3-Clause
+// copyright-holders:Nigel Barnes
+#ifndef MAME_BUS_COCO_DRAGON_MSX2_H
+#define MAME_BUS_COCO_DRAGON_MSX2_H
+
+#pragma once
+
+#include "cococart.h"
+#include "sound/ay8910.h"
+#include "sound/ymopl.h"
+#include "video/v9938.h"
+
+
+//**************************************************************************
+// TYPE DEFINITIONS
+//**************************************************************************
+
+// ======================> dragon_msx2_device
+
+class dragon_msx2_device :
+ public device_t,
+ public device_cococart_interface
+{
+public:
+ // construction/destruction
+ dragon_msx2_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock);
+
+protected:
+ // device-level overrides
+ virtual void device_start() override ATTR_COLD;
+ virtual void device_reset() override ATTR_COLD;
+
+ // optional information overrides
+ virtual void device_add_mconfig(machine_config &config) override ATTR_COLD;
+ virtual ioport_constructor device_input_ports() const override ATTR_COLD;
+
+ virtual u8 scs_read(offs_t offset) override;
+ virtual void scs_write(offs_t offset, u8 data) override;
+
+private:
+ required_device<ym2413_device> m_ym2413;
+ required_device<v9958_device> m_v9958;
+ required_device<ym2149_device> m_ym2149;
+ required_ioport m_config;
+
+ void video_select_w(u8 data);
+};
+
+
+// device type definition
+DECLARE_DEVICE_TYPE(DRAGON_MSX2, dragon_msx2_device)
+
+#endif // MAME_BUS_COCO_DRAGON_MSX2_H
diff --git a/src/devices/bus/coco/dragon_serial.cpp b/src/devices/bus/coco/dragon_serial.cpp
new file mode 100644
index 00000000000..c2ecab858d8
--- /dev/null
+++ b/src/devices/bus/coco/dragon_serial.cpp
@@ -0,0 +1,138 @@
+// license:BSD-3-Clause
+// copyright-holders:Nigel Barnes
+/***************************************************************************
+
+ Peaksoft Prestel Module
+
+ Also known as the New Era Interface from Peaksoft/Harry Whitehouse, which
+ includes a through port for DOS cartridges.
+
+ TODO:
+ - 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"
+
+
+namespace {
+
+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")
+ {
+ }
+
+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; }
+
+ // optional information overrides
+ virtual void device_add_mconfig(machine_config &config) override ATTR_COLD;
+ virtual const tiny_rom_entry *device_rom_region() const override ATTR_COLD;
+
+ 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:
+ required_memory_region m_eprom;
+ required_device<acia6850_device> m_acia;
+};
+
+
+//-------------------------------------------------
+// ROM( dragon_serial )
+//-------------------------------------------------
+
+ROM_START(dragon_serial)
+ ROM_REGION(0x2000, "eprom", 0)
+ ROM_LOAD("comron_peaksoft.rom", 0x0000, 0x2000, CRC(9d18cf46) SHA1(14124dfb4bd78d1907e80d779cd7f3bae30564c9))
+ROM_END
+
+const tiny_rom_entry *dragon_serial_device::device_rom_region() const
+{
+ return ROM_NAME( dragon_serial );
+}
+
+
+//-------------------------------------------------
+// device_add_mconfig - add device configuration
+//-------------------------------------------------
+
+void dragon_serial_device::device_add_mconfig(machine_config &config)
+{
+ ACIA6850(config, m_acia, 0);
+ m_acia->txd_handler().set("rs232", FUNC(rs232_port_device::write_txd));
+ 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 &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)).invert();
+}
+
+
+//-------------------------------------------------
+// cts_read
+//-------------------------------------------------
+
+u8 dragon_serial_device::cts_read(offs_t offset)
+{
+ return m_eprom->base()[offset & 0x1fff];
+}
+
+//-------------------------------------------------
+// scs_read
+//-------------------------------------------------
+
+u8 dragon_serial_device::scs_read(offs_t offset)
+{
+ uint8_t result = 0x00;
+
+ switch (offset)
+ {
+ case 0x14: case 0x15:
+ result = m_acia->read(offset & 1);
+ break;
+ }
+
+ return result;
+}
+
+//-------------------------------------------------
+// scs_write
+//-------------------------------------------------
+
+void dragon_serial_device::scs_write(offs_t offset, u8 data)
+{
+ switch (offset)
+ {
+ case 0x14: case 0x15:
+ m_acia->write(offset & 1, data);
+ break;
+ }
+}
+
+} // 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
new file mode 100644
index 00000000000..5bd93f7e930
--- /dev/null
+++ b/src/devices/bus/coco/dragon_serial.h
@@ -0,0 +1,13 @@
+// license:BSD-3-Clause
+// copyright-holders:Nigel Barnes
+#ifndef MAME_BUS_COCO_DRAGON_SERIAL_H
+#define MAME_BUS_COCO_DRAGON_SERIAL_H
+
+#pragma once
+
+#include "cococart.h"
+
+
+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 b9021e5cdf9..c04167d8b03 100644
--- a/src/devices/bus/coco/dragon_sprites.cpp
+++ b/src/devices/bus/coco/dragon_sprites.cpp
@@ -30,7 +30,7 @@ DEFINE_DEVICE_TYPE(DRAGON_SPRITES, dragon_sprites_device, "dragon_sprites", "Dra
// dragon_sprites_device - constructor
//-------------------------------------------------
-dragon_sprites_device::dragon_sprites_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
+dragon_sprites_device::dragon_sprites_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock)
: device_t(mconfig, DRAGON_SPRITES, tag, owner, clock)
, device_cococart_interface(mconfig, *this )
, m_eprom(*this, "eprom")
@@ -74,9 +74,9 @@ const tiny_rom_entry *dragon_sprites_device::device_rom_region() const
// cts_read
//-------------------------------------------------
-READ8_MEMBER(dragon_sprites_device::cts_read)
+u8 dragon_sprites_device::cts_read(offs_t offset)
{
- uint8_t data = 0x00;
+ u8 data = 0x00;
switch (offset)
{
case 0x2000:
@@ -97,7 +97,7 @@ READ8_MEMBER(dragon_sprites_device::cts_read)
// cts_write
//-------------------------------------------------
-WRITE8_MEMBER(dragon_sprites_device::cts_write)
+void dragon_sprites_device::cts_write(offs_t offset, u8 data)
{
switch (offset)
{
@@ -111,7 +111,7 @@ WRITE8_MEMBER(dragon_sprites_device::cts_write)
}
-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 6ff1d20f8ab..c97e4b4fe08 100644
--- a/src/devices/bus/coco/dragon_sprites.h
+++ b/src/devices/bus/coco/dragon_sprites.h
@@ -21,24 +21,24 @@ class dragon_sprites_device :
{
public:
// construction/destruction
- dragon_sprites_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
+ dragon_sprites_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock);
// optional information overrides
- virtual void device_add_mconfig(machine_config &config) override;
- virtual const tiny_rom_entry *device_rom_region() const override;
+ virtual void device_add_mconfig(machine_config &config) override ATTR_COLD;
+ virtual const tiny_rom_entry *device_rom_region() const override ATTR_COLD;
protected:
// device-level overrides
- virtual void device_start() override;
+ virtual void device_start() override ATTR_COLD;
- virtual DECLARE_READ8_MEMBER(cts_read) override;
- virtual DECLARE_WRITE8_MEMBER(cts_write) override;
+ virtual u8 cts_read(offs_t offset) override;
+ virtual void cts_write(offs_t offset, u8 data) override;
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..d9919cb1e51
--- /dev/null
+++ b/src/devices/bus/coco/meb_intrf.h
@@ -0,0 +1,90 @@
+// license:BSD-3-Clause
+// copyright-holders:tim lindner
+/*********************************************************************
+
+ meb_intrf.h
+
+ CRC / Disto Mini Expansion Bus management
+
+*********************************************************************/
+
+#ifndef MAME_BUS_COCO_MEB_INTRF_H
+#define MAME_BUS_COCO_MEB_INTRF_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 ATTR_COLD;
+
+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_MEB_INTRF_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..140383759bb
--- /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 ATTR_COLD;
+ virtual void device_add_mconfig(machine_config &config) override ATTR_COLD;
+ 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..662153016a5
--- /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 ATTR_COLD;
+
+ // 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 ATTR_COLD;
+};
+
+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 ATTR_COLD;
+};
+
+// 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 eaf3f144322..21fcfd9708a 100644
--- a/src/devices/bus/coleco/cartridge/exp.cpp
+++ b/src/devices/bus/coleco/cartridge/exp.cpp
@@ -28,7 +28,7 @@ DEFINE_DEVICE_TYPE(COLECOVISION_CARTRIDGE_SLOT, colecovision_cartridge_slot_devi
//-------------------------------------------------
device_colecovision_cartridge_interface::device_colecovision_cartridge_interface(const machine_config &mconfig, device_t &device) :
- device_slot_card_interface(mconfig, device),
+ device_interface(device, "colecocart"),
m_rom(nullptr),
m_rom_size(0)
{
@@ -55,8 +55,8 @@ void device_colecovision_cartridge_interface::rom_alloc(size_t size)
colecovision_cartridge_slot_device::colecovision_cartridge_slot_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) :
device_t(mconfig, COLECOVISION_CARTRIDGE_SLOT, tag, owner, clock),
- device_slot_interface(mconfig, *this),
- device_image_interface(mconfig, *this),
+ device_single_card_slot_interface<device_colecovision_cartridge_interface>(mconfig, *this),
+ device_cartrom_image_interface(mconfig, *this),
m_card(nullptr)
{
}
@@ -68,7 +68,7 @@ colecovision_cartridge_slot_device::colecovision_cartridge_slot_device(const mac
void colecovision_cartridge_slot_device::device_start()
{
- m_card = dynamic_cast<device_colecovision_cartridge_interface *>(get_card_device());
+ m_card = get_card_device();
}
@@ -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());
}
@@ -106,39 +106,62 @@ std::string colecovision_cartridge_slot_device::get_default_card_software(get_de
{
if (hook.image_file())
{
- uint32_t length = hook.image_file()->size();
+ uint64_t length;
+ hook.image_file()->length(length); // FIXME: check error return
+
if (length == 0x100000 || length == 0x200000)
return software_get_default_slot("xin1");
+
+ if (length > 0x8000) // Assume roms longer than 32K are megacarts.
+ return software_get_default_slot("megacart");
}
+
return software_get_default_slot("standard");
}
//-------------------------------------------------
-// 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)
{
- if (m_card != nullptr)
- {
- data = m_card->bd_r(offset, data, _8000, _a000, _c000, _e000);
- }
+ uint8_t data = 0xff;
+
+ if (m_card)
+ 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"
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 4da9d2d1d00..59362fff11b 100644
--- a/src/devices/bus/coleco/cartridge/exp.h
+++ b/src/devices/bus/coleco/cartridge/exp.h
@@ -25,12 +25,12 @@
**********************************************************************/
-#ifndef MAME_BUS_COLECO_EXP_H
-#define MAME_BUS_COLECO_EXP_H
+#ifndef MAME_BUS_COLECO_CARTRIDGE_EXP_H
+#define MAME_BUS_COLECO_CARTRIDGE_EXP_H
#pragma once
-#include "softlist_dev.h"
+#include "imagedev/cartrom.h"
//**************************************************************************
@@ -48,8 +48,8 @@
class device_colecovision_cartridge_interface;
class colecovision_cartridge_slot_device : public device_t,
- public device_slot_interface,
- public device_image_interface
+ public device_single_card_slot_interface<device_colecovision_cartridge_interface>,
+ public device_cartrom_image_interface
{
public:
// construction/destruction
@@ -65,27 +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
- virtual void device_start() override;
+ // device_t implementation
+ virtual void device_start() override ATTR_COLD;
- // image-level overrides
- virtual image_init_result call_load() override;
- virtual const software_list_loader &get_software_list_loader() const override { return rom_software_list_loader::instance(); }
+ // device_image_interface implementation
+ virtual std::pair<std::error_condition, std::string> call_load() override;
- virtual iodevice_t image_type() const override { return IO_CARTSLOT; }
+ 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"; }
- virtual bool is_readable() const override { return 1; }
- virtual bool is_writeable() const override { return 0; }
- virtual bool is_creatable() const override { return 0; }
- virtual bool must_be_loaded() const override { return 0; }
- virtual bool is_reset_on_load() const override { return 1; }
- virtual const char *image_interface() const override { return "coleco_cart"; }
- virtual const char *file_extensions() const 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;
@@ -94,12 +88,13 @@ protected:
// ======================> device_colecovision_cartridge_interface
-class device_colecovision_cartridge_interface : public device_slot_card_interface
+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);
@@ -118,4 +113,4 @@ DECLARE_DEVICE_TYPE(COLECOVISION_CARTRIDGE_SLOT, colecovision_cartridge_slot_dev
void colecovision_cartridges(device_slot_interface &device);
-#endif // MAME_BUS_COLECO_EXP_H
+#endif // MAME_BUS_COLECO_CARTRIDGE_EXP_H
diff --git a/src/devices/bus/coleco/cartridge/megacart.cpp b/src/devices/bus/coleco/cartridge/megacart.cpp
new file mode 100644
index 00000000000..1cb6b471bb0
--- /dev/null
+++ b/src/devices/bus/coleco/cartridge/megacart.cpp
@@ -0,0 +1,97 @@
+// license:BSD-3-Clause
+// copyright-holders:Mark/Space Inc.
+/**********************************************************************
+
+ ColecoVision MegaCart emulation
+
+**********************************************************************/
+
+#include "emu.h"
+#include "megacart.h"
+
+
+
+//**************************************************************************
+// DEVICE DEFINITIONS
+//**************************************************************************
+
+DEFINE_DEVICE_TYPE(COLECOVISION_MEGACART, colecovision_megacart_cartridge_device, "colecovision_megacart", "ColecoVision MegaCart")
+
+
+
+//**************************************************************************
+// LIVE DEVICE
+//**************************************************************************
+
+//-------------------------------------------------
+// colecovision_megacart_cartridge_device - constructor
+//-------------------------------------------------
+
+colecovision_megacart_cartridge_device::colecovision_megacart_cartridge_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) :
+ device_t(mconfig, COLECOVISION_MEGACART, tag, owner, clock),
+ device_colecovision_cartridge_interface(mconfig, *this),
+ m_bankcount(0),
+ m_activebank(0)
+{
+}
+
+
+//-------------------------------------------------
+// device_start - device-specific startup
+//-------------------------------------------------
+
+void colecovision_megacart_cartridge_device::device_start()
+{
+ save_item(NAME(m_bankcount));
+ save_item(NAME(m_activebank));
+}
+
+
+//-------------------------------------------------
+// device_reset - device-specific reset
+//-------------------------------------------------
+
+void colecovision_megacart_cartridge_device::device_reset()
+{
+ m_bankcount = m_rom_size >> 14;
+ m_activebank = 0;
+}
+
+
+//-------------------------------------------------
+// read - cartridge data read
+//-------------------------------------------------
+
+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)
+ {
+ // Reads within the final 64 bytes select which megacart bank is active.
+ m_activebank = offset & (m_bankcount - 1);
+ }
+
+ if (offset >= 0x4000)
+ {
+ // The offset is within the active megacart bank.
+ offset = (m_activebank << 14) + (offset - 0x4000);
+ }
+ else
+ {
+ // The offset is within the last bank.
+ offset = (m_bankcount << 14) + (offset - 0x4000);
+ }
+ }
+
+ data = m_rom[offset];
+ }
+
+ return data;
+}
diff --git a/src/devices/bus/coleco/cartridge/megacart.h b/src/devices/bus/coleco/cartridge/megacart.h
new file mode 100644
index 00000000000..cc94c5932e6
--- /dev/null
+++ b/src/devices/bus/coleco/cartridge/megacart.h
@@ -0,0 +1,49 @@
+// license:BSD-3-Clause
+// copyright-holders:Mark/Space Inc.
+/**********************************************************************
+
+ ColecoVision MegaCart emulation
+
+**********************************************************************/
+
+#ifndef MAME_BUS_COLECO_CARTRIDGE_MEGACART_H
+#define MAME_BUS_COLECO_CARTRIDGE_MEGACART_H
+
+#pragma once
+
+#include "exp.h"
+
+
+
+//**************************************************************************
+// TYPE DEFINITIONS
+//**************************************************************************
+
+// ======================> colecovision_megacart_cartridge_device
+
+class colecovision_megacart_cartridge_device : public device_t,
+ public device_colecovision_cartridge_interface
+{
+public:
+ // construction/destruction
+ colecovision_megacart_cartridge_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
+
+protected:
+ // device_t overrides
+ virtual void device_start() override ATTR_COLD;
+ virtual void device_reset() override ATTR_COLD;
+
+ // device_colecovision_cartridge_interface overrides
+ virtual uint8_t read(offs_t offset, int _8000, int _a000, int _c000, int _e000) override;
+
+private:
+ uint32_t m_bankcount;
+ uint32_t m_activebank;
+};
+
+
+// device type definition
+DECLARE_DEVICE_TYPE(COLECOVISION_MEGACART, colecovision_megacart_cartridge_device)
+
+
+#endif // MAME_BUS_COLECO_CARTRIDGE_MEGACART_H
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..33c11cf050e 100644
--- a/src/devices/bus/coleco/cartridge/std.h
+++ b/src/devices/bus/coleco/cartridge/std.h
@@ -6,8 +6,8 @@
**********************************************************************/
-#ifndef MAME_BUS_COLECO_STD_H
-#define MAME_BUS_COLECO_STD_H
+#ifndef MAME_BUS_COLECO_CARTRIDGE_STD_H
+#define MAME_BUS_COLECO_CARTRIDGE_STD_H
#pragma once
@@ -30,15 +30,14 @@ public:
protected:
// device-level overrides
- virtual void device_start() override;
+ virtual void device_start() override ATTR_COLD;
// 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;
};
// device type definition
DECLARE_DEVICE_TYPE(COLECOVISION_STANDARD, colecovision_standard_cartridge_device)
-
-#endif // MAME_BUS_COLECO_STD_H
+#endif // MAME_BUS_COLECO_CARTRIDGE_STD_H
diff --git a/src/devices/bus/coleco/cartridge/xin1.cpp b/src/devices/bus/coleco/cartridge/xin1.cpp
index 140d2132ee4..6a3ba70d512 100644
--- a/src/devices/bus/coleco/cartridge/xin1.cpp
+++ b/src/devices/bus/coleco/cartridge/xin1.cpp
@@ -41,6 +41,7 @@ colecovision_xin1_cartridge_device::colecovision_xin1_cartridge_device(const mac
void colecovision_xin1_cartridge_device::device_start()
{
+ save_item(NAME(m_current_offset));
}
@@ -58,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..757095f705d 100644
--- a/src/devices/bus/coleco/cartridge/xin1.h
+++ b/src/devices/bus/coleco/cartridge/xin1.h
@@ -6,8 +6,8 @@
**********************************************************************/
-#ifndef MAME_BUS_COLECO_XIN1_H
-#define MAME_BUS_COLECO_XIN1_H
+#ifndef MAME_BUS_COLECO_CARTRIDGE_XIN1_H
+#define MAME_BUS_COLECO_CARTRIDGE_XIN1_H
#pragma once
@@ -30,11 +30,11 @@ public:
protected:
// device-level overrides
- virtual void device_start() override;
- virtual void device_reset() override;
+ virtual void device_start() override ATTR_COLD;
+ virtual void device_reset() override ATTR_COLD;
// 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;
@@ -44,5 +44,4 @@ private:
// device type definition
DECLARE_DEVICE_TYPE(COLECOVISION_XIN1, colecovision_xin1_cartridge_device)
-
-#endif // MAME_BUS_COLECO_XIN1_H
+#endif // MAME_BUS_COLECO_CARTRIDGE_XIN1_H
diff --git a/src/devices/bus/coleco/controller/ctrl.cpp b/src/devices/bus/coleco/controller/ctrl.cpp
index 330c7c71551..2a9cb9baadd 100644
--- a/src/devices/bus/coleco/controller/ctrl.cpp
+++ b/src/devices/bus/coleco/controller/ctrl.cpp
@@ -28,7 +28,7 @@ DEFINE_DEVICE_TYPE(COLECOVISION_CONTROL_PORT, colecovision_control_port_device,
//-------------------------------------------------
device_colecovision_control_port_interface::device_colecovision_control_port_interface(const machine_config &mconfig, device_t &device) :
- device_slot_card_interface(mconfig, device),
+ device_interface(device, "colecoctrl"),
m_common0(1),
m_common1(1)
{
@@ -47,7 +47,7 @@ device_colecovision_control_port_interface::device_colecovision_control_port_int
colecovision_control_port_device::colecovision_control_port_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) :
device_t(mconfig, COLECOVISION_CONTROL_PORT, tag, owner, clock),
- device_slot_interface(mconfig, *this),
+ device_single_card_slot_interface<device_colecovision_control_port_interface>(mconfig, *this),
m_device(nullptr),
m_write_irq(*this)
{
@@ -60,9 +60,7 @@ colecovision_control_port_device::colecovision_control_port_device(const machine
void colecovision_control_port_device::device_start()
{
- m_device = dynamic_cast<device_colecovision_control_port_interface *>(get_card_device());
-
- m_write_irq.resolve_safe();
+ m_device = get_card_device();
}
diff --git a/src/devices/bus/coleco/controller/ctrl.h b/src/devices/bus/coleco/controller/ctrl.h
index 3460dec0b7d..6862f4d1380 100644
--- a/src/devices/bus/coleco/controller/ctrl.h
+++ b/src/devices/bus/coleco/controller/ctrl.h
@@ -9,8 +9,8 @@
**********************************************************************/
-#ifndef MAME_BUS_COLECO_CTRL_H
-#define MAME_BUS_COLECO_CTRL_H
+#ifndef MAME_BUS_COLECO_CONTROLLER_CTRL_H
+#define MAME_BUS_COLECO_CONTROLLER_CTRL_H
#pragma once
@@ -23,7 +23,7 @@ class colecovision_control_port_device;
// ======================> device_colecovision_control_port_interface
-class device_colecovision_control_port_interface : public device_slot_card_interface
+class device_colecovision_control_port_interface : public device_interface
{
public:
virtual uint8_t joy_r() { return 0xff; }
@@ -44,7 +44,7 @@ protected:
// ======================> colecovision_control_port_device
class colecovision_control_port_device : public device_t,
- public device_slot_interface
+ public device_single_card_slot_interface<device_colecovision_control_port_interface>
{
public:
// construction/destruction
@@ -64,10 +64,9 @@ public:
// computer interface
uint8_t read() { uint8_t data = 0xff; if (exists()) data = m_device->joy_r(); return data; }
- DECLARE_READ8_MEMBER( read ) { return read(); }
- 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; }
@@ -75,7 +74,7 @@ public:
protected:
// device-level overrides
- virtual void device_start() override;
+ virtual void device_start() override ATTR_COLD;
device_colecovision_control_port_interface *m_device;
@@ -90,4 +89,4 @@ DECLARE_DEVICE_TYPE(COLECOVISION_CONTROL_PORT, colecovision_control_port_device)
void colecovision_control_port_devices(device_slot_interface &device);
-#endif // MAME_BUS_COLECO_CTRL_H
+#endif // MAME_BUS_COLECO_CONTROLLER_CTRL_H
diff --git a/src/devices/bus/coleco/controller/hand.cpp b/src/devices/bus/coleco/controller/hand.cpp
index d5e4d72b6bc..c2e945984f3 100644
--- a/src/devices/bus/coleco/controller/hand.cpp
+++ b/src/devices/bus/coleco/controller/hand.cpp
@@ -18,7 +18,7 @@
DEFINE_DEVICE_TYPE(COLECO_HAND_CONTROLLER, coleco_hand_controller_device, "coleco_hand", "ColecoVision Hand Controller")
-CUSTOM_INPUT_MEMBER( coleco_hand_controller_device::keypad_r )
+ioport_value coleco_hand_controller_device::keypad_r()
{
uint8_t data = 0xf;
uint16_t keypad = m_io_keypad->read();
@@ -50,7 +50,7 @@ static INPUT_PORTS_START( coleco_hand_controller )
PORT_BIT( 0x80, IP_ACTIVE_HIGH, IPT_CUSTOM )
PORT_START("COMMON1")
- PORT_BIT( 0x0f, IP_ACTIVE_HIGH, IPT_CUSTOM ) PORT_CUSTOM_MEMBER(coleco_hand_controller_device, keypad_r)
+ PORT_BIT( 0x0f, IP_ACTIVE_HIGH, IPT_CUSTOM ) PORT_CUSTOM_MEMBER(FUNC(coleco_hand_controller_device::keypad_r))
PORT_BIT( 0x30, IP_ACTIVE_LOW, IPT_UNUSED )
PORT_BIT( 0x40, IP_ACTIVE_LOW, IPT_BUTTON2 )
PORT_BIT( 0x80, IP_ACTIVE_HIGH, IPT_CUSTOM )
diff --git a/src/devices/bus/coleco/controller/hand.h b/src/devices/bus/coleco/controller/hand.h
index f65ad709106..9f6395be155 100644
--- a/src/devices/bus/coleco/controller/hand.h
+++ b/src/devices/bus/coleco/controller/hand.h
@@ -6,8 +6,8 @@
**********************************************************************/
-#ifndef MAME_BUS_COLECO_HAND_H
-#define MAME_BUS_COLECO_HAND_H
+#ifndef MAME_BUS_COLECO_CONTROLLER_HAND_H
+#define MAME_BUS_COLECO_CONTROLLER_HAND_H
#pragma once
@@ -29,13 +29,13 @@ public:
coleco_hand_controller_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;
+ virtual ioport_constructor device_input_ports() const override ATTR_COLD;
- DECLARE_CUSTOM_INPUT_MEMBER( keypad_r );
+ ioport_value keypad_r();
protected:
// device-level overrides
- virtual void device_start() override;
+ virtual void device_start() override ATTR_COLD;
// device_vcs_control_port_interface overrides
virtual uint8_t joy_r() override;
@@ -50,5 +50,4 @@ private:
// device type definition
DECLARE_DEVICE_TYPE(COLECO_HAND_CONTROLLER, coleco_hand_controller_device)
-
-#endif // MAME_BUS_COLECO_HAND_H
+#endif // MAME_BUS_COLECO_CONTROLLER_HAND_H
diff --git a/src/devices/bus/coleco/controller/sac.cpp b/src/devices/bus/coleco/controller/sac.cpp
index 7621897c78d..77390c84cbc 100644
--- a/src/devices/bus/coleco/controller/sac.cpp
+++ b/src/devices/bus/coleco/controller/sac.cpp
@@ -18,7 +18,7 @@
DEFINE_DEVICE_TYPE(COLECO_SUPER_ACTION_CONTROLLER, coleco_super_action_controller_device, "coleco_sac", "ColecoVision Super Action Controller")
-CUSTOM_INPUT_MEMBER( coleco_super_action_controller_device::keypad_r )
+ioport_value coleco_super_action_controller_device::keypad_r()
{
uint8_t data = 0xf;
uint16_t keypad = m_io_keypad->read();
@@ -57,7 +57,7 @@ static INPUT_PORTS_START( coleco_super_action_controller )
PORT_BIT( 0x80, IP_ACTIVE_HIGH, IPT_CUSTOM )
PORT_START("COMMON1")
- PORT_BIT( 0x0f, IP_ACTIVE_HIGH, IPT_CUSTOM ) PORT_CUSTOM_MEMBER(coleco_super_action_controller_device, keypad_r)
+ PORT_BIT( 0x0f, IP_ACTIVE_HIGH, IPT_CUSTOM ) PORT_CUSTOM_MEMBER(FUNC(coleco_super_action_controller_device::keypad_r))
PORT_BIT( 0x30, IP_ACTIVE_LOW, IPT_UNUSED )
PORT_BIT( 0x40, IP_ACTIVE_LOW, IPT_BUTTON2 )
PORT_BIT( 0x80, IP_ACTIVE_HIGH, IPT_CUSTOM )
@@ -79,7 +79,7 @@ static INPUT_PORTS_START( coleco_super_action_controller )
PORT_BIT( 0x2000, IP_ACTIVE_LOW, IPT_BUTTON4 )
PORT_START("SLIDER")
- PORT_BIT( 0xff, 0x00, IPT_DIAL ) PORT_SENSITIVITY(100) PORT_KEYDELTA(25) PORT_REVERSE PORT_RESET PORT_CHANGED_MEMBER(DEVICE_SELF, coleco_super_action_controller_device, slider_w, 0)
+ PORT_BIT( 0xff, 0x00, IPT_DIAL ) PORT_SENSITIVITY(100) PORT_KEYDELTA(25) PORT_REVERSE PORT_RESET PORT_CHANGED_MEMBER(DEVICE_SELF, FUNC(coleco_super_action_controller_device::slider_w), 0)
INPUT_PORTS_END
diff --git a/src/devices/bus/coleco/controller/sac.h b/src/devices/bus/coleco/controller/sac.h
index 20078e33ef7..ba7df71efd1 100644
--- a/src/devices/bus/coleco/controller/sac.h
+++ b/src/devices/bus/coleco/controller/sac.h
@@ -6,8 +6,8 @@
**********************************************************************/
-#ifndef MAME_BUS_COLECO_SAC_H
-#define MAME_BUS_COLECO_SAC_H
+#ifndef MAME_BUS_COLECO_CONTROLLER_SAC_H
+#define MAME_BUS_COLECO_CONTROLLER_SAC_H
#pragma once
@@ -29,14 +29,14 @@ public:
coleco_super_action_controller_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;
+ virtual ioport_constructor device_input_ports() const override ATTR_COLD;
- DECLARE_CUSTOM_INPUT_MEMBER( keypad_r );
+ ioport_value keypad_r();
DECLARE_INPUT_CHANGED_MEMBER( slider_w );
protected:
// device-level overrides
- virtual void device_start() override;
+ virtual void device_start() override ATTR_COLD;
// device_vcs_control_port_interface overrides
virtual uint8_t joy_r() override;
@@ -51,5 +51,4 @@ private:
// device type definition
DECLARE_DEVICE_TYPE(COLECO_SUPER_ACTION_CONTROLLER, coleco_super_action_controller_device)
-
-#endif // MAME_BUS_COLECO_SAC_H
+#endif // MAME_BUS_COLECO_CONTROLLER_SAC_H
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..6d724420df8
--- /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..0c38f42f514
--- /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 ATTR_COLD;
+
+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..aeb9ae7fe17
--- /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 ATTR_COLD;
+ virtual void device_start() override ATTR_COLD;
+ virtual void device_reset() override ATTR_COLD;
+
+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) ATTR_COLD;
+
+ 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 ec8db616003..059f19b6517 100644
--- a/src/devices/bus/compis/graphics.cpp
+++ b/src/devices/bus/compis/graphics.cpp
@@ -28,7 +28,7 @@ DEFINE_DEVICE_TYPE(COMPIS_GRAPHICS_SLOT, compis_graphics_slot_device, "compisgfx
//-------------------------------------------------
device_compis_graphics_card_interface::device_compis_graphics_card_interface(const machine_config &mconfig, device_t &device) :
- device_slot_card_interface(mconfig, device)
+ device_interface(device, "compisgfx")
{
m_slot = dynamic_cast<compis_graphics_slot_device *>(device.owner());
}
@@ -40,7 +40,7 @@ device_compis_graphics_card_interface::device_compis_graphics_card_interface(con
compis_graphics_slot_device::compis_graphics_slot_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) :
device_t(mconfig, COMPIS_GRAPHICS_SLOT, tag, owner, clock),
- device_slot_interface(mconfig, *this),
+ device_single_card_slot_interface<device_compis_graphics_card_interface>(mconfig, *this),
m_write_dma_request(*this),
m_card(nullptr)
{
@@ -53,10 +53,7 @@ compis_graphics_slot_device::compis_graphics_slot_device(const machine_config &m
void compis_graphics_slot_device::device_start()
{
- m_card = dynamic_cast<device_compis_graphics_card_interface *>(get_card_device());
-
- // resolve callbacks
- m_write_dma_request.resolve_safe();
+ m_card = get_card_device();
}
diff --git a/src/devices/bus/compis/graphics.h b/src/devices/bus/compis/graphics.h
index 0f3f2b104b1..4b176952f53 100644
--- a/src/devices/bus/compis/graphics.h
+++ b/src/devices/bus/compis/graphics.h
@@ -21,7 +21,7 @@
class compis_graphics_slot_device;
-class device_compis_graphics_card_interface : public device_slot_card_interface
+class device_compis_graphics_card_interface : public device_interface
{
public:
virtual uint8_t mcs0_r(offs_t offset) { return 0xff; }
@@ -45,8 +45,7 @@ protected:
// ======================> compis_graphics_slot_device
-class compis_graphics_slot_device : public device_t,
- public device_slot_interface
+class compis_graphics_slot_device : public device_t, public device_single_card_slot_interface<device_compis_graphics_card_interface>
{
public:
// construction/destruction
@@ -76,12 +75,11 @@ 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
- virtual void device_start() override;
- virtual void device_reset() override { if (m_card) get_card_device()->reset(); }
+ virtual void device_start() override ATTR_COLD;
devcb_write_line m_write_dma_request;
diff --git a/src/devices/bus/compis/hrg.cpp b/src/devices/bus/compis/hrg.cpp
index 7aa8aa72f7e..9fcd130bec0 100644
--- a/src/devices/bus/compis/hrg.cpp
+++ b/src/devices/bus/compis/hrg.cpp
@@ -34,14 +34,14 @@ DEFINE_DEVICE_TYPE(COMPIS_UHRG, compis_uhrg_device, "compis_uhrg", "Compis UHRG"
void compis_hrg_device::hrg_map(address_map &map)
{
- map.global_mask(0x7fff);
- map(0x00000, 0x7fff).ram().share("video_ram");
+ map.global_mask(0x3fff);
+ map(0x00000, 0x3fff).ram().share("video_ram");
}
void compis_uhrg_device::uhrg_map(address_map &map)
{
- map.global_mask(0x1ffff);
- map(0x00000, 0x1ffff).ram().share("video_ram");
+ map.global_mask(0xffff);
+ map(0x00000, 0xffff).ram().share("video_ram");
}
@@ -51,11 +51,11 @@ void compis_uhrg_device::uhrg_map(address_map &map)
UPD7220_DISPLAY_PIXELS_MEMBER( compis_hrg_device::display_pixels )
{
- uint16_t i,gfx = m_video_ram[(address & 0x7fff) >> 1];
- const pen_t *pen = m_palette->pens();
+ uint16_t const gfx = m_video_ram[(address & 0x3fff)];
+ pen_t const *const pen = m_palette->pens();
- for(i=0; i<16; i++)
- bitmap.pix32(y, x + i) = pen[BIT(gfx, i)];
+ for(uint16_t i=0; i<16; i++)
+ bitmap.pix(y, x + i) = pen[BIT(gfx, i)];
}
@@ -65,11 +65,11 @@ UPD7220_DISPLAY_PIXELS_MEMBER( compis_hrg_device::display_pixels )
UPD7220_DISPLAY_PIXELS_MEMBER( compis_uhrg_device::display_pixels )
{
- uint16_t i,gfx = m_video_ram[(address & 0x1ffff) >> 1];
- const pen_t *pen = m_palette->pens();
+ uint16_t const gfx = m_video_ram[(address & 0xffff)];
+ pen_t const *const pen = m_palette->pens();
- for(i=0; i<16; i++)
- bitmap.pix32(y, x + i) = pen[BIT(gfx, i)];
+ for(uint16_t i=0; i<16; i++)
+ bitmap.pix(y, x + i) = pen[BIT(gfx, i)];
}
diff --git a/src/devices/bus/compis/hrg.h b/src/devices/bus/compis/hrg.h
index 98ef784df14..63d36f57b48 100644
--- a/src/devices/bus/compis/hrg.h
+++ b/src/devices/bus/compis/hrg.h
@@ -34,11 +34,11 @@ protected:
compis_hrg_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_start() override ATTR_COLD;
+ virtual void device_reset() override ATTR_COLD;
// optional information overrides
- virtual void device_add_mconfig(machine_config &config) override;
+ virtual void device_add_mconfig(machine_config &config) override ATTR_COLD;
// device_compis_graphics_card_interface overrides
virtual uint8_t pcs6_6_r(offs_t offset) override;
@@ -53,7 +53,7 @@ protected:
private:
UPD7220_DISPLAY_PIXELS_MEMBER( display_pixels );
- void hrg_map(address_map &map);
+ void hrg_map(address_map &map) ATTR_COLD;
};
@@ -67,12 +67,12 @@ public:
protected:
// optional information overrides
- virtual void device_add_mconfig(machine_config &config) override;
+ virtual void device_add_mconfig(machine_config &config) override ATTR_COLD;
private:
UPD7220_DISPLAY_PIXELS_MEMBER( display_pixels );
- void uhrg_map(address_map &map);
+ void uhrg_map(address_map &map) ATTR_COLD;
};
diff --git a/src/devices/bus/compucolor/floppy.cpp b/src/devices/bus/compucolor/floppy.cpp
index fbe7912f6b6..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"
+
//**************************************************************************
@@ -33,9 +35,11 @@ void compucolor_floppy_port_devices(device_slot_interface &device)
// FLOPPY_FORMATS( floppy_formats )
//-------------------------------------------------
-FLOPPY_FORMATS_MEMBER( compucolor_floppy_device::floppy_formats )
- FLOPPY_CCVF_FORMAT
-FLOPPY_FORMATS_END
+void compucolor_floppy_device::floppy_formats(format_registration &fr)
+{
+ fr.add_fm_containers();
+ fr.add(FLOPPY_CCVF_FORMAT);
+}
//-------------------------------------------------
@@ -125,7 +129,7 @@ void compucolor_floppy_port_device::device_start()
void compucolor_floppy_device::device_start()
{
// allocate timer
- m_timer = timer_alloc();
+ m_timer = timer_alloc(FUNC(compucolor_floppy_device::rxd_tick), this);
m_timer->adjust(attotime::from_hz(9600*8), 0, attotime::from_hz(9600*8));
// state saving
@@ -136,10 +140,10 @@ void compucolor_floppy_device::device_start()
//-------------------------------------------------
-// device_timer - handle timer events
+// rxd_tick -
//-------------------------------------------------
-void compucolor_floppy_device::device_timer(emu_timer &timer, device_timer_id id, int param, void *ptr)
+TIMER_CALLBACK_MEMBER(compucolor_floppy_device::rxd_tick)
{
if (!m_sel && !m_rw)
{
diff --git a/src/devices/bus/compucolor/floppy.h b/src/devices/bus/compucolor/floppy.h
index a4e476eb152..fbf63da87ef 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,13 +49,13 @@ 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
- virtual void device_start() override;
+ virtual void device_start() override ATTR_COLD;
virtual void device_config_complete() override;
private:
@@ -74,11 +73,10 @@ public:
protected:
// device-level overrides
- virtual void device_start() override;
- virtual void device_timer(emu_timer &timer, device_timer_id id, int param, void *ptr) override;
+ virtual void device_start() override ATTR_COLD;
// optional information overrides
- virtual void device_add_mconfig(machine_config &config) override;
+ virtual void device_add_mconfig(machine_config &config) override ATTR_COLD;
// device_serial_port_interface overrides
virtual void tx(uint8_t state);
@@ -89,10 +87,11 @@ protected:
virtual void select_w(int state) override;
private:
- DECLARE_FLOPPY_FORMATS( floppy_formats );
+ static void floppy_formats(format_registration &fr);
required_device<floppy_connector> m_floppy;
+ TIMER_CALLBACK_MEMBER(rxd_tick);
bool read_bit();
void write_bit(bool bit);
diff --git a/src/devices/bus/comx35/clm.cpp b/src/devices/bus/comx35/clm.cpp
index 745606875f0..d32b4a694f8 100644
--- a/src/devices/bus/comx35/clm.cpp
+++ b/src/devices/bus/comx35/clm.cpp
@@ -104,8 +104,8 @@ MC6845_UPDATE_ROW( comx_clm_device::crtc_update_row )
{
for (int column = 0; column < x_count; column++)
{
- uint8_t code = m_video_ram[((ma + column) & 0x7ff)];
- uint16_t addr = (code << 3) | (ra & 0x07);
+ uint8_t const code = m_video_ram[((ma + column) & 0x7ff)];
+ uint16_t const addr = (code << 3) | (ra & 0x07);
uint8_t data = m_char_rom->base()[addr & 0x7ff];
if (BIT(ra, 3) && column == cursor_x)
@@ -115,9 +115,9 @@ MC6845_UPDATE_ROW( comx_clm_device::crtc_update_row )
for (int bit = 0; bit < 8; bit++)
{
- int x = (column * 8) + bit;
+ int const x = (column * 8) + bit;
- bitmap.pix32(vbp + y, hbp + x) = m_palette->pen(BIT(data, 7) && de);
+ bitmap.pix(vbp + y, hbp + x) = m_palette->pen(BIT(data, 7) && de);
data <<= 1;
}
@@ -153,7 +153,7 @@ void comx_clm_device::device_add_mconfig(machine_config &config)
m_crtc->set_screen(MC6845_SCREEN_TAG);
m_crtc->set_show_border_area(true);
m_crtc->set_char_width(8);
- m_crtc->set_update_row_callback(FUNC(comx_clm_device::crtc_update_row), this);
+ m_crtc->set_update_row_callback(FUNC(comx_clm_device::crtc_update_row));
}
@@ -173,7 +173,7 @@ comx_clm_device::comx_clm_device(const machine_config &mconfig, const char *tag,
m_palette(*this, "palette"),
m_rom(*this, "c000"),
m_char_rom(*this, MC6845_TAG),
- m_video_ram(*this, "video_ram")
+ m_video_ram(*this, "video_ram", VIDEORAM_SIZE, ENDIANNESS_LITTLE)
{
}
@@ -184,9 +184,6 @@ comx_clm_device::comx_clm_device(const machine_config &mconfig, const char *tag,
void comx_clm_device::device_start()
{
- // allocate memory
- m_video_ram.allocate(VIDEORAM_SIZE);
-
// state saving
save_item(NAME(m_ds));
}
diff --git a/src/devices/bus/comx35/clm.h b/src/devices/bus/comx35/clm.h
index 9c4845cbbe0..7743b8824ba 100644
--- a/src/devices/bus/comx35/clm.h
+++ b/src/devices/bus/comx35/clm.h
@@ -33,12 +33,12 @@ public:
protected:
// device-level overrides
- virtual void device_start() override;
- virtual void device_reset() override;
+ virtual void device_start() override ATTR_COLD;
+ virtual void device_reset() override ATTR_COLD;
// optional information overrides
- virtual const tiny_rom_entry *device_rom_region() const override;
- virtual void device_add_mconfig(machine_config &config) override;
+ virtual const tiny_rom_entry *device_rom_region() const override ATTR_COLD;
+ virtual void device_add_mconfig(machine_config &config) override ATTR_COLD;
// device_comx_expansion_card_interface overrides
virtual int comx_ef4_r() override;
@@ -52,7 +52,7 @@ private:
required_device<palette_device> m_palette;
required_memory_region m_rom;
required_memory_region m_char_rom;
- optional_shared_ptr<uint8_t> m_video_ram;
+ memory_share_creator<uint8_t> m_video_ram;
};
diff --git a/src/devices/bus/comx35/eprom.h b/src/devices/bus/comx35/eprom.h
index 90f57e52d3d..74adaa820da 100644
--- a/src/devices/bus/comx35/eprom.h
+++ b/src/devices/bus/comx35/eprom.h
@@ -29,12 +29,12 @@ public:
comx_epr_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 const tiny_rom_entry *device_rom_region() const override ATTR_COLD;
protected:
// device-level overrides
- virtual void device_start() override;
- virtual void device_reset() override;
+ virtual void device_start() override ATTR_COLD;
+ virtual void device_reset() override ATTR_COLD;
// device_comx_expansion_card_interface overrides
virtual uint8_t comx_mrd_r(offs_t offset, int *extrom) override;
diff --git a/src/devices/bus/comx35/exp.cpp b/src/devices/bus/comx35/exp.cpp
index 75036fb6ea8..6848ade4f92 100644
--- a/src/devices/bus/comx35/exp.cpp
+++ b/src/devices/bus/comx35/exp.cpp
@@ -27,7 +27,7 @@ DEFINE_DEVICE_TYPE(COMX_EXPANSION_SLOT, comx_expansion_slot_device, "comx_expans
//-------------------------------------------------
device_comx_expansion_card_interface::device_comx_expansion_card_interface(const machine_config &mconfig, device_t &device) :
- device_slot_card_interface(mconfig, device),
+ device_interface(device, "comxexp"),
m_ds(1)
{
m_slot = dynamic_cast<comx_expansion_slot_device *>(device.owner());
@@ -45,7 +45,7 @@ device_comx_expansion_card_interface::device_comx_expansion_card_interface(const
comx_expansion_slot_device::comx_expansion_slot_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) :
device_t(mconfig, COMX_EXPANSION_SLOT, tag, owner, clock),
- device_slot_interface(mconfig, *this),
+ device_single_card_slot_interface<device_comx_expansion_card_interface>(mconfig, *this),
m_write_irq(*this), m_card(nullptr)
{
}
@@ -57,10 +57,7 @@ comx_expansion_slot_device::comx_expansion_slot_device(const machine_config &mco
void comx_expansion_slot_device::device_start()
{
- m_card = dynamic_cast<device_comx_expansion_card_interface *>(get_card_device());
-
- // resolve callbacks
- m_write_irq.resolve_safe();
+ m_card = get_card_device();
}
@@ -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;
@@ -157,7 +154,7 @@ READ_LINE_MEMBER(comx_expansion_slot_device::ef4_r)
// sc_w - state code/N0-N2 write
//-------------------------------------------------
-WRITE8_MEMBER(comx_expansion_slot_device::sc_w)
+void comx_expansion_slot_device::sc_w(offs_t offset, uint8_t data)
{
if (m_card != nullptr)
m_card->comx_sc_w(offset, data);
@@ -168,7 +165,7 @@ WRITE8_MEMBER(comx_expansion_slot_device::sc_w)
// 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 1facb388037..108978e8800 100644
--- a/src/devices/bus/comx35/exp.h
+++ b/src/devices/bus/comx35/exp.h
@@ -42,8 +42,7 @@
class device_comx_expansion_card_interface;
-class comx_expansion_slot_device : public device_t,
- public device_slot_interface
+class comx_expansion_slot_device : public device_t, public device_single_card_slot_interface<device_comx_expansion_card_interface>
{
public:
// construction/destruction
@@ -67,19 +66,19 @@ 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); }
- DECLARE_WRITE8_MEMBER(sc_w);
- DECLARE_WRITE_LINE_MEMBER(tpb_w);
+ void sc_w(offs_t offset, uint8_t data);
+ void tpb_w(int state);
protected:
// device-level overrides
- virtual void device_start() override;
+ virtual void device_start() override ATTR_COLD;
devcb_write_line m_write_irq;
@@ -90,7 +89,7 @@ protected:
// ======================> device_comx_expansion_card_interface
// class representing interface-specific live comx_expansion card
-class device_comx_expansion_card_interface : public device_slot_card_interface
+class device_comx_expansion_card_interface : public device_interface
{
friend class comx_expansion_slot_device;
diff --git a/src/devices/bus/comx35/expbox.h b/src/devices/bus/comx35/expbox.h
index c4c89b4f2bc..106c29505b7 100644
--- a/src/devices/bus/comx35/expbox.h
+++ b/src/devices/bus/comx35/expbox.h
@@ -38,12 +38,12 @@ public:
protected:
// device-level overrides
- virtual void device_start() override;
- virtual void device_reset() override;
+ virtual void device_start() override ATTR_COLD;
+ virtual void device_reset() override ATTR_COLD;
// optional information overrides
- virtual const tiny_rom_entry *device_rom_region() const override;
- virtual void device_add_mconfig(machine_config &config) override;
+ virtual const tiny_rom_entry *device_rom_region() const override ATTR_COLD;
+ virtual void device_add_mconfig(machine_config &config) override ATTR_COLD;
// device_comx_expansion_card_interface overrides
virtual int comx_ef4_r() override;
@@ -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 da1b6dcc028..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"
+
//**************************************************************************
@@ -81,9 +83,11 @@ const tiny_rom_entry *comx_fd_device::device_rom_region() const
}
-FLOPPY_FORMATS_MEMBER( comx_fd_device::floppy_formats )
- FLOPPY_COMX35_FORMAT
-FLOPPY_FORMATS_END
+void comx_fd_device::floppy_formats(format_registration &fr)
+{
+ fr.add_mfm_containers();
+ fr.add(FLOPPY_COMX35_FORMAT);
+}
static void comx_fd_floppies(device_slot_interface &device)
{
diff --git a/src/devices/bus/comx35/fdc.h b/src/devices/bus/comx35/fdc.h
index 45617bb8580..2fd56f40f07 100644
--- a/src/devices/bus/comx35/fdc.h
+++ b/src/devices/bus/comx35/fdc.h
@@ -6,13 +6,12 @@
**********************************************************************/
-#ifndef MAME_BUS_COMX35_FD_H
-#define MAME_BUS_COMX35_FD_H
+#ifndef MAME_BUS_COMX35_FDC_H
+#define MAME_BUS_COMX35_FDC_H
#pragma once
#include "exp.h"
-#include "formats/comx35_dsk.h"
#include "imagedev/floppy.h"
#include "machine/wd_fdc.h"
@@ -33,12 +32,12 @@ public:
protected:
// device-level overrides
- virtual void device_start() override;
- virtual void device_reset() override;
+ virtual void device_start() override ATTR_COLD;
+ virtual void device_reset() override ATTR_COLD;
// optional information overrides
- virtual const tiny_rom_entry *device_rom_region() const override;
- virtual void device_add_mconfig(machine_config &config) override;
+ virtual const tiny_rom_entry *device_rom_region() const override ATTR_COLD;
+ virtual void device_add_mconfig(machine_config &config) override ATTR_COLD;
// device_comx_expansion_card_interface overrides
virtual int comx_ef4_r() override;
@@ -48,7 +47,7 @@ protected:
virtual void comx_io_w(offs_t offset, uint8_t data) override;
private:
- DECLARE_FLOPPY_FORMATS( floppy_formats );
+ static void floppy_formats(format_registration &fr);
// internal state
required_device<wd1770_device> m_fdc;
@@ -66,5 +65,4 @@ private:
// device type definition
DECLARE_DEVICE_TYPE(COMX_FD, comx_fd_device)
-
-#endif // MAME_BUS_COMX35_FD_H
+#endif // MAME_BUS_COMX35_FDC_H
diff --git a/src/devices/bus/comx35/joycard.h b/src/devices/bus/comx35/joycard.h
index 92c41431961..2530c6622aa 100644
--- a/src/devices/bus/comx35/joycard.h
+++ b/src/devices/bus/comx35/joycard.h
@@ -29,12 +29,12 @@ public:
comx_joy_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;
+ virtual ioport_constructor device_input_ports() const override ATTR_COLD;
protected:
// device-level overrides
- virtual void device_start() override;
- virtual void device_reset() override;
+ virtual void device_start() override ATTR_COLD;
+ virtual void device_reset() override ATTR_COLD;
// device_comx_expansion_card_interface overrides
virtual uint8_t comx_io_r(offs_t offset) override;
diff --git a/src/devices/bus/comx35/printer.h b/src/devices/bus/comx35/printer.h
index 1ffa3f66046..214008cb68f 100644
--- a/src/devices/bus/comx35/printer.h
+++ b/src/devices/bus/comx35/printer.h
@@ -31,12 +31,12 @@ public:
protected:
// device-level overrides
- virtual void device_start() override;
- virtual void device_reset() override;
+ virtual void device_start() override ATTR_COLD;
+ virtual void device_reset() override ATTR_COLD;
// optional information overrides
- virtual const tiny_rom_entry *device_rom_region() const override;
- virtual void device_add_mconfig(machine_config &config) override;
+ virtual const tiny_rom_entry *device_rom_region() const override ATTR_COLD;
+ virtual void device_add_mconfig(machine_config &config) override ATTR_COLD;
// device_comx_expansion_card_interface overrides
virtual uint8_t comx_mrd_r(offs_t offset, int *extrom) override;
diff --git a/src/devices/bus/comx35/ram.cpp b/src/devices/bus/comx35/ram.cpp
index b468b6366ff..0f11dfdb194 100644
--- a/src/devices/bus/comx35/ram.cpp
+++ b/src/devices/bus/comx35/ram.cpp
@@ -37,7 +37,7 @@ DEFINE_DEVICE_TYPE(COMX_RAM, comx_ram_device, "comx_ram", "COMX-35 RAM Card")
comx_ram_device::comx_ram_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) :
device_t(mconfig, COMX_RAM, tag, owner, clock),
device_comx_expansion_card_interface(mconfig, *this),
- m_ram(*this, "ram"),
+ m_ram(*this, "ram", RAM_SIZE, ENDIANNESS_LITTLE),
m_bank(0)
{
}
@@ -49,7 +49,6 @@ comx_ram_device::comx_ram_device(const machine_config &mconfig, const char *tag,
void comx_ram_device::device_start()
{
- m_ram.allocate(RAM_SIZE);
}
diff --git a/src/devices/bus/comx35/ram.h b/src/devices/bus/comx35/ram.h
index 3a75e208eb6..b936d91e226 100644
--- a/src/devices/bus/comx35/ram.h
+++ b/src/devices/bus/comx35/ram.h
@@ -30,8 +30,8 @@ public:
protected:
// device-level overrides
- virtual void device_start() override;
- virtual void device_reset() override;
+ virtual void device_start() override ATTR_COLD;
+ virtual void device_reset() override ATTR_COLD;
// device_comx_expansion_card_interface overrides
virtual uint8_t comx_mrd_r(offs_t offset, int *extrom) override;
@@ -39,7 +39,7 @@ protected:
virtual void comx_io_w(offs_t offset, uint8_t data) override;
private:
- optional_shared_ptr<uint8_t> m_ram;
+ memory_share_creator<uint8_t> m_ram;
int m_bank;
};
diff --git a/src/devices/bus/comx35/thermal.h b/src/devices/bus/comx35/thermal.h
index 645f6bf0213..4db4226fab7 100644
--- a/src/devices/bus/comx35/thermal.h
+++ b/src/devices/bus/comx35/thermal.h
@@ -29,12 +29,12 @@ public:
comx_thm_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 const tiny_rom_entry *device_rom_region() const override ATTR_COLD;
protected:
// device-level overrides
- virtual void device_start() override;
- virtual void device_reset() override;
+ virtual void device_start() override ATTR_COLD;
+ virtual void device_reset() override ATTR_COLD;
// device_comx_expansion_card_interface overrides
virtual uint8_t comx_mrd_r(offs_t offset, int *extrom) override;
diff --git a/src/devices/bus/cpc/amdrum.cpp b/src/devices/bus/cpc/amdrum.cpp
index 587577edf52..26345f48bc9 100644
--- a/src/devices/bus/cpc/amdrum.cpp
+++ b/src/devices/bus/cpc/amdrum.cpp
@@ -9,7 +9,6 @@
#include "emu.h"
#include "amdrum.h"
-#include "sound/volt_reg.h"
#include "speaker.h"
@@ -24,9 +23,6 @@ void cpc_amdrum_device::device_add_mconfig(machine_config &config)
{
SPEAKER(config, "speaker").front_center();
ZN428E(config, m_dac, 0).add_route(ALL_OUTPUTS, "speaker", 0.5);
- voltage_regulator_device &vref(VOLTAGE_REGULATOR(config, "vref"));
- vref.add_route(0, "dac", 1.0, DAC_VREF_POS_INPUT);
- vref.add_route(0, "dac", -1.0, DAC_VREF_NEG_INPUT);
// no pass-through
}
@@ -51,7 +47,7 @@ void cpc_amdrum_device::device_start()
{
m_slot = dynamic_cast<cpc_expansion_slot_device *>(owner());
address_space &space = m_slot->cpu().space(AS_IO);
- space.install_write_handler(0xff00,0xffff,write8_delegate(FUNC(cpc_amdrum_device::dac_w),this));
+ space.install_write_handler(0xff00,0xffff, write8smo_delegate(*this, FUNC(cpc_amdrum_device::dac_w)));
}
//-------------------------------------------------
@@ -63,7 +59,7 @@ void cpc_amdrum_device::device_reset()
// TODO
}
-WRITE8_MEMBER(cpc_amdrum_device::dac_w)
+void cpc_amdrum_device::dac_w(uint8_t data)
{
m_dac->write(data);
}
diff --git a/src/devices/bus/cpc/amdrum.h b/src/devices/bus/cpc/amdrum.h
index 360f1228c09..ecd8cf75c92 100644
--- a/src/devices/bus/cpc/amdrum.h
+++ b/src/devices/bus/cpc/amdrum.h
@@ -27,15 +27,15 @@ public:
// construction/destruction
cpc_amdrum_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
- DECLARE_WRITE8_MEMBER(dac_w);
+ void dac_w(uint8_t data);
protected:
// device-level overrides
- virtual void device_start() override;
- virtual void device_reset() override;
+ virtual void device_start() override ATTR_COLD;
+ virtual void device_reset() override ATTR_COLD;
// optional information overrides
- virtual void device_add_mconfig(machine_config &config) override;
+ virtual void device_add_mconfig(machine_config &config) override ATTR_COLD;
private:
cpc_expansion_slot_device *m_slot;
diff --git a/src/devices/bus/cpc/brunword4.cpp b/src/devices/bus/cpc/brunword4.cpp
index db5e8e1b57d..c28433b281a 100644
--- a/src/devices/bus/cpc/brunword4.cpp
+++ b/src/devices/bus/cpc/brunword4.cpp
@@ -74,7 +74,7 @@ void cpc_brunword4_device::device_start()
{
m_slot = dynamic_cast<cpc_expansion_slot_device *>(owner());
address_space &space = m_slot->cpu().space(AS_IO);
- space.install_write_handler(0xdf00,0xdfff,write8_delegate(FUNC(cpc_brunword4_device::rombank_w),this));
+ space.install_write_handler(0xdf00,0xdfff, write8smo_delegate(*this, FUNC(cpc_brunword4_device::rombank_w)));
}
void cpc_brunword4_device::device_reset()
@@ -82,7 +82,7 @@ void cpc_brunword4_device::device_reset()
m_rombank_active = false;
}
-WRITE8_MEMBER(cpc_brunword4_device::rombank_w)
+void cpc_brunword4_device::rombank_w(uint8_t data)
{
if((data & 0xc0) == 0xc0 && (data & 0x04) == 0)
{
@@ -95,7 +95,7 @@ WRITE8_MEMBER(cpc_brunword4_device::rombank_w)
m_rombank_active = false;
return;
}
- m_slot->rom_select(space,0,data & 0x3f); // repeats every 64 ROMs, this breaks upper cart ROM selection on the Plus
+ m_slot->rom_select(data & 0x3f); // repeats every 64 ROMs, this breaks upper cart ROM selection on the Plus
}
void cpc_brunword4_device::set_mapping(uint8_t type)
diff --git a/src/devices/bus/cpc/brunword4.h b/src/devices/bus/cpc/brunword4.h
index 66d5cdebab5..5af03c2ff98 100644
--- a/src/devices/bus/cpc/brunword4.h
+++ b/src/devices/bus/cpc/brunword4.h
@@ -20,15 +20,15 @@ public:
cpc_brunword4_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 const tiny_rom_entry *device_rom_region() const override ATTR_COLD;
- DECLARE_WRITE8_MEMBER(rombank_w);
+ void rombank_w(uint8_t data);
virtual void set_mapping(uint8_t type) override;
protected:
// device-level overrides
- virtual void device_start() override;
- virtual void device_reset() override;
+ virtual void device_start() override ATTR_COLD;
+ virtual void device_reset() override ATTR_COLD;
private:
cpc_expansion_slot_device *m_slot;
diff --git a/src/devices/bus/cpc/cpc_pds.cpp b/src/devices/bus/cpc/cpc_pds.cpp
index 0509ab866dc..411b0b6e575 100644
--- a/src/devices/bus/cpc/cpc_pds.cpp
+++ b/src/devices/bus/cpc/cpc_pds.cpp
@@ -33,7 +33,7 @@ cpc_pds_device::cpc_pds_device(const machine_config &mconfig, const char *tag, d
device_t(mconfig, CPC_PDS, tag, owner, clock),
device_cpc_expansion_card_interface(mconfig, *this),
m_slot(nullptr),
- m_pio(*this,"pio")
+ m_pio(*this, "pio")
{
}
@@ -46,7 +46,7 @@ void cpc_pds_device::device_start()
m_slot = dynamic_cast<cpc_expansion_slot_device *>(owner());
address_space &space = m_slot->cpu().space(AS_IO);
- space.install_readwrite_handler(0xfbec,0xfbef,read8_delegate(FUNC(cpc_pds_device::pio_r),this),write8_delegate(FUNC(cpc_pds_device::pio_w),this));
+ space.install_readwrite_handler(0xfbec,0xfbef, read8sm_delegate(*this, FUNC(cpc_pds_device::pio_r)), write8sm_delegate(*this, FUNC(cpc_pds_device::pio_w)));
}
//-------------------------------------------------
@@ -59,12 +59,12 @@ void cpc_pds_device::device_reset()
}
-READ8_MEMBER(cpc_pds_device::pio_r)
+uint8_t cpc_pds_device::pio_r(offs_t offset)
{
return m_pio->read(offset);
}
-WRITE8_MEMBER(cpc_pds_device::pio_w)
+void cpc_pds_device::pio_w(offs_t offset, uint8_t data)
{
m_pio->write(offset,data);
}
diff --git a/src/devices/bus/cpc/cpc_pds.h b/src/devices/bus/cpc/cpc_pds.h
index 5908a5a75c7..03572bb07e0 100644
--- a/src/devices/bus/cpc/cpc_pds.h
+++ b/src/devices/bus/cpc/cpc_pds.h
@@ -36,16 +36,16 @@ public:
// construction/destruction
cpc_pds_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
- DECLARE_READ8_MEMBER(pio_r);
- DECLARE_WRITE8_MEMBER(pio_w);
+ uint8_t pio_r(offs_t offset);
+ void pio_w(offs_t offset, uint8_t data);
protected:
// device-level overrides
- virtual void device_start() override;
- virtual void device_reset() override;
+ virtual void device_start() override ATTR_COLD;
+ virtual void device_reset() override ATTR_COLD;
// optional information overrides
- virtual void device_add_mconfig(machine_config &config) override;
+ virtual void device_add_mconfig(machine_config &config) override ATTR_COLD;
private:
cpc_expansion_slot_device *m_slot;
diff --git a/src/devices/bus/cpc/cpc_rom.cpp b/src/devices/bus/cpc/cpc_rom.cpp
index 69bd7f80035..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);
@@ -76,7 +79,7 @@ DEFINE_DEVICE_TYPE(CPC_ROMSLOT, cpc_rom_image_device, "cpc_rom_image", "CPC ROM
cpc_rom_image_device::cpc_rom_image_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
: device_t(mconfig, CPC_ROMSLOT, tag, owner, clock)
- , device_image_interface(mconfig, *this)
+ , device_rom_image_interface(mconfig, *this)
, m_base(nullptr)
{
}
@@ -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.get(),size);
- }
- else
- {
- image->fseek(size-16384,SEEK_SET);
- image->fread(m_base.get(),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 67e88cf6137..0e6faa0c11d 100644
--- a/src/devices/bus/cpc/cpc_rom.h
+++ b/src/devices/bus/cpc/cpc_rom.h
@@ -12,37 +12,32 @@
#pragma once
#include "cpcexp.h"
+#include "imagedev/cartrom.h"
/*** ROM image device ***/
// ======================> cpc_rom_image_device
-class cpc_rom_image_device : public device_t, public device_image_interface
+class cpc_rom_image_device : public device_t, public device_rom_image_interface
{
public:
// construction/destruction
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 iodevice_t image_type() const override { return IO_ROM; }
-
- virtual bool is_readable() const override { return 1; }
- virtual bool is_writeable() const override { return 0; }
- virtual bool is_creatable() const override { return 0; }
- virtual bool must_be_loaded() const override { return 0; }
- virtual bool is_reset_on_load() const override { return 1; }
- virtual const char *image_interface() const override { return "cpc_rom"; }
- virtual const char *file_extensions() const override { return "rom,bin"; }
+ virtual bool is_reset_on_load() const noexcept override { return true; }
+ virtual const char *image_interface() const noexcept override { return "cpc_rom"; }
+ virtual const char *file_extensions() const noexcept override { return "rom,bin"; }
uint8_t* base() { return m_base.get(); }
protected:
- // device-level overrides
- virtual void device_start() override;
+ // device_t implementation
+ virtual void device_start() override ATTR_COLD;
private:
std::unique_ptr<uint8_t[]> m_base;
@@ -66,11 +61,11 @@ public:
protected:
// device-level overrides
- virtual void device_start() override;
- virtual void device_reset() override;
+ virtual void device_start() override ATTR_COLD;
+ virtual void device_reset() override ATTR_COLD;
// optional information overrides
- virtual void device_add_mconfig(machine_config &config) override;
+ virtual void device_add_mconfig(machine_config &config) override ATTR_COLD;
private:
required_device_array<cpc_rom_image_device, 8> m_rom;
diff --git a/src/devices/bus/cpc/cpc_rs232.cpp b/src/devices/bus/cpc/cpc_rs232.cpp
index 40fc0853539..e3be3af93d3 100644
--- a/src/devices/bus/cpc/cpc_rs232.cpp
+++ b/src/devices/bus/cpc/cpc_rs232.cpp
@@ -52,7 +52,7 @@ void cpc_rs232_device::device_add_mconfig(machine_config &config)
m_rs232->rxd_handler().set(m_dart, FUNC(z80dart_device::rxa_w));
m_rs232->dcd_handler().set(m_dart, FUNC(z80dart_device::dcda_w));
m_rs232->cts_handler().set(m_dart, FUNC(z80dart_device::ctsa_w));
-// m_rs232->ri_handler().set(m_dart, FUNC(z80dart_device::ria_w));
+ m_rs232->ri_handler().set(m_dart, FUNC(z80dart_device::ria_w));
// pass-through
cpc_expansion_slot_device &exp(CPC_EXPANSION_SLOT(config, "exp", DERIVED_CLOCK(1, 1), cpc_exp_cards, nullptr));
@@ -106,8 +106,8 @@ void cpc_rs232_device::device_start()
m_slot = dynamic_cast<cpc_expansion_slot_device *>(owner());
address_space &space = m_slot->cpu().space(AS_IO);
- space.install_readwrite_handler(0xfadc,0xfadf,read8_delegate(FUNC(cpc_rs232_device::dart_r),this),write8_delegate(FUNC(cpc_rs232_device::dart_w),this));
- space.install_readwrite_handler(0xfbdc,0xfbdf,read8_delegate(FUNC(cpc_rs232_device::pit_r),this),write8_delegate(FUNC(cpc_rs232_device::pit_w),this));
+ space.install_readwrite_handler(0xfadc,0xfadf, read8sm_delegate(*this, FUNC(cpc_rs232_device::dart_r)), write8sm_delegate(*this, FUNC(cpc_rs232_device::dart_w)));
+ space.install_readwrite_handler(0xfbdc,0xfbdf, read8sm_delegate(*this, FUNC(cpc_rs232_device::pit_r)), write8sm_delegate(*this, FUNC(cpc_rs232_device::pit_w)));
}
//-------------------------------------------------
@@ -119,38 +119,38 @@ 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);
}
-READ8_MEMBER(cpc_rs232_device::dart_r)
+uint8_t cpc_rs232_device::dart_r(offs_t offset)
{
return m_dart->ba_cd_r(offset);
}
-WRITE8_MEMBER(cpc_rs232_device::dart_w)
+void cpc_rs232_device::dart_w(offs_t offset, uint8_t data)
{
m_dart->ba_cd_w(offset,data);
}
-READ8_MEMBER(cpc_rs232_device::pit_r)
+uint8_t cpc_rs232_device::pit_r(offs_t offset)
{
return m_pit->read(offset);
}
-WRITE8_MEMBER(cpc_rs232_device::pit_w)
+void cpc_rs232_device::pit_w(offs_t offset, uint8_t data)
{
m_pit->write(offset,data);
}
diff --git a/src/devices/bus/cpc/cpc_rs232.h b/src/devices/bus/cpc/cpc_rs232.h
index 56e7ccd8b4f..08d56074593 100644
--- a/src/devices/bus/cpc/cpc_rs232.h
+++ b/src/devices/bus/cpc/cpc_rs232.h
@@ -12,7 +12,7 @@
#pragma once
#include "cpcexp.h"
-#include "machine/z80dart.h"
+#include "machine/z80sio.h"
#include "machine/pit8253.h"
#include "bus/rs232/rs232.h"
@@ -22,30 +22,30 @@ public:
// construction/destruction
cpc_rs232_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
- DECLARE_READ8_MEMBER(dart_r);
- DECLARE_WRITE8_MEMBER(dart_w);
- DECLARE_READ8_MEMBER(pit_r);
- DECLARE_WRITE8_MEMBER(pit_w);
+ uint8_t dart_r(offs_t offset);
+ void dart_w(offs_t offset, uint8_t data);
+ uint8_t pit_r(offs_t offset);
+ void pit_w(offs_t offset, uint8_t data);
protected:
cpc_rs232_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 const tiny_rom_entry *device_rom_region() const override;
+ virtual void device_start() override ATTR_COLD;
+ virtual void device_reset() override ATTR_COLD;
+ virtual const tiny_rom_entry *device_rom_region() const override ATTR_COLD;
// optional information overrides
- virtual void device_add_mconfig(machine_config &config) override;
+ virtual void device_add_mconfig(machine_config &config) override ATTR_COLD;
required_device<pit8253_device> m_pit;
required_device<z80dart_device> m_dart;
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;
};
@@ -57,7 +57,7 @@ public:
cpc_ams_rs232_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;
+ virtual const tiny_rom_entry *device_rom_region() const override ATTR_COLD;
};
// device type definition
diff --git a/src/devices/bus/cpc/cpc_ssa1.cpp b/src/devices/bus/cpc/cpc_ssa1.cpp
index bdfedce16ed..eab90d6831d 100644
--- a/src/devices/bus/cpc/cpc_ssa1.cpp
+++ b/src/devices/bus/cpc/cpc_ssa1.cpp
@@ -26,61 +26,41 @@ DEFINE_DEVICE_TYPE(CPC_DKSPEECH, cpc_dkspeech_device, "cpc_dkspeech", "DK'Tronic
// device I/O handlers
//-------------------------------------------------
-READ8_MEMBER(cpc_ssa1_device::ssa1_r)
+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;
}
-WRITE8_MEMBER(cpc_ssa1_device::ssa1_w)
+void cpc_ssa1_device::ssa1_w(uint8_t data)
{
m_sp0256_device->ald_w(data);
}
-READ8_MEMBER(cpc_dkspeech_device::dkspeech_r)
+uint8_t cpc_dkspeech_device::dkspeech_r()
{
uint8_t ret = 0xff;
// SBY is not connected
- if(get_lrq() != 0)
+ if(m_sp0256_device->lrq_r())
ret &= ~0x80;
return ret;
}
-WRITE8_MEMBER(cpc_dkspeech_device::dkspeech_w)
+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")
{
}
@@ -177,8 +151,8 @@ void cpc_ssa1_device::device_start()
m_rom = memregion("sp0256")->base();
- space.install_readwrite_handler(0xfaee,0xfaee,read8_delegate(FUNC(cpc_ssa1_device::ssa1_r),this),write8_delegate(FUNC(cpc_ssa1_device::ssa1_w),this));
- space.install_readwrite_handler(0xfbee,0xfbee,read8_delegate(FUNC(cpc_ssa1_device::ssa1_r),this),write8_delegate(FUNC(cpc_ssa1_device::ssa1_w),this));
+ space.install_readwrite_handler(0xfaee,0xfaee, read8smo_delegate(*this, FUNC(cpc_ssa1_device::ssa1_r)), write8smo_delegate(*this, FUNC(cpc_ssa1_device::ssa1_w)));
+ space.install_readwrite_handler(0xfbee,0xfbee, read8smo_delegate(*this, FUNC(cpc_ssa1_device::ssa1_r)), write8smo_delegate(*this, FUNC(cpc_ssa1_device::ssa1_w)));
}
void cpc_dkspeech_device::device_start()
@@ -188,7 +162,7 @@ void cpc_dkspeech_device::device_start()
m_rom = memregion("sp0256")->base();
- space.install_readwrite_handler(0xfbfe,0xfbfe,read8_delegate(FUNC(cpc_dkspeech_device::dkspeech_r),this),write8_delegate(FUNC(cpc_dkspeech_device::dkspeech_w),this));
+ space.install_readwrite_handler(0xfbfe,0xfbfe, read8smo_delegate(*this, FUNC(cpc_dkspeech_device::dkspeech_r)), write8smo_delegate(*this, FUNC(cpc_dkspeech_device::dkspeech_w)));
}
//-------------------------------------------------
diff --git a/src/devices/bus/cpc/cpc_ssa1.h b/src/devices/bus/cpc/cpc_ssa1.h
index 0fb2c7a0e87..9ec7c2e1202 100644
--- a/src/devices/bus/cpc/cpc_ssa1.h
+++ b/src/devices/bus/cpc/cpc_ssa1.h
@@ -56,33 +56,21 @@ 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; }
-
- DECLARE_READ8_MEMBER(ssa1_r);
- DECLARE_WRITE8_MEMBER(ssa1_w);
+ uint8_t ssa1_r();
+ void ssa1_w(uint8_t data);
protected:
// device-level overrides
- virtual void device_start() override;
- virtual void device_reset() override;
+ virtual void device_start() override ATTR_COLD;
+ virtual void device_reset() override ATTR_COLD;
// optional information overrides
- virtual const tiny_rom_entry *device_rom_region() const override;
- virtual void device_add_mconfig(machine_config &config) override;
+ virtual const tiny_rom_entry *device_rom_region() const override ATTR_COLD;
+ virtual void device_add_mconfig(machine_config &config) override ATTR_COLD;
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,33 +81,21 @@ 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; }
-
- DECLARE_READ8_MEMBER(dkspeech_r);
- DECLARE_WRITE8_MEMBER(dkspeech_w);
+ uint8_t dkspeech_r();
+ void dkspeech_w(uint8_t data);
protected:
// device-level overrides
- virtual void device_start() override;
- virtual void device_reset() override;
+ virtual void device_start() override ATTR_COLD;
+ virtual void device_reset() override ATTR_COLD;
// optional information overrides
- virtual const tiny_rom_entry *device_rom_region() const override;
- virtual void device_add_mconfig(machine_config &config) override;
+ virtual const tiny_rom_entry *device_rom_region() const override ATTR_COLD;
+ virtual void device_add_mconfig(machine_config &config) override ATTR_COLD;
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 3f9f04e89ea..c625ed4689e 100644
--- a/src/devices/bus/cpc/cpcexp.cpp
+++ b/src/devices/bus/cpc/cpcexp.cpp
@@ -25,7 +25,7 @@ DEFINE_DEVICE_TYPE(CPC_EXPANSION_SLOT, cpc_expansion_slot_device, "cpc_expansion
device_cpc_expansion_card_interface::device_cpc_expansion_card_interface(const machine_config &mconfig, device_t &device)
- : device_slot_card_interface(mconfig,device)
+ : device_interface(device, "cpcexp")
, m_rom_sel(0)
{
}
@@ -43,7 +43,7 @@ device_cpc_expansion_card_interface::~device_cpc_expansion_card_interface()
cpc_expansion_slot_device::cpc_expansion_slot_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
: device_t(mconfig, CPC_EXPANSION_SLOT, tag, owner, clock)
- , device_slot_interface(mconfig, *this)
+ , device_single_card_slot_interface<device_cpc_expansion_card_interface>(mconfig, *this)
, m_cpu(*this, finder_base::DUMMY_TAG)
, m_out_irq_cb(*this)
, m_out_nmi_cb(*this)
@@ -64,14 +64,7 @@ cpc_expansion_slot_device::~cpc_expansion_slot_device()
void cpc_expansion_slot_device::device_start()
{
- m_card = dynamic_cast<device_cpc_expansion_card_interface *>(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();
+ m_card = get_card_device();
}
//-------------------------------------------------
@@ -83,25 +76,17 @@ void cpc_expansion_slot_device::device_start()
void cpc_expansion_slot_device::device_config_complete()
{
// for passthrough connectors, use the parent slot's CPU tag
- if ((m_cpu.finder_tag() == finder_base::DUMMY_TAG) && (dynamic_cast<device_cpc_expansion_card_interface *>(owner()) != nullptr))
+ if ((m_cpu.finder_tag() == finder_base::DUMMY_TAG) && dynamic_cast<device_cpc_expansion_card_interface *>(owner()))
{
- auto parent = dynamic_cast<cpc_expansion_slot_device *>(owner()->owner());
- if (parent != nullptr)
+ auto const parent = dynamic_cast<cpc_expansion_slot_device *>(owner()->owner());
+ if (parent)
m_cpu.set_tag(parent->m_cpu);
}
}
-//-------------------------------------------------
-// device_reset - device-specific reset
-//-------------------------------------------------
-
-void cpc_expansion_slot_device::device_reset()
-{
-}
-
-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); }
-WRITE8_MEMBER( cpc_expansion_slot_device::rom_select ) { m_out_rom_select(data); }
+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 51796dc7edd..7fed2af89e4 100644
--- a/src/devices/bus/cpc/cpcexp.h
+++ b/src/devices/bus/cpc/cpcexp.h
@@ -56,7 +56,7 @@
// ======================> device_cpc_expansion_card_interface
// class representing interface-specific live cpc_expansion card
-class device_cpc_expansion_card_interface : public device_slot_card_interface
+class device_cpc_expansion_card_interface : public device_interface
{
public:
enum
@@ -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; }
@@ -88,8 +88,7 @@ private:
// ======================> cpc_expansion_slot_device
-class cpc_expansion_slot_device : public device_t,
- public device_slot_interface
+class cpc_expansion_slot_device : public device_t, public device_single_card_slot_interface<device_cpc_expansion_card_interface>
{
public:
// construction/destruction
@@ -113,24 +112,23 @@ 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 );
- DECLARE_WRITE8_MEMBER( rom_select );
+ 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; }
protected:
// device-level overrides
virtual void device_config_complete() override;
- virtual void device_start() override;
- virtual void device_reset() override;
+ virtual void device_start() override ATTR_COLD;
required_device<cpu_device> m_cpu;
diff --git a/src/devices/bus/cpc/ddi1.cpp b/src/devices/bus/cpc/ddi1.cpp
index 76e09d36f34..7deaa49eabd 100644
--- a/src/devices/bus/cpc/ddi1.cpp
+++ b/src/devices/bus/cpc/ddi1.cpp
@@ -6,7 +6,7 @@
#include "emu.h"
#include "ddi1.h"
-#include "softlist.h"
+#include "softlist_dev.h"
void cpc_exp_cards(device_slot_interface &device);
@@ -43,7 +43,7 @@ const tiny_rom_entry *cpc_ddi1_device::device_rom_region() const
void cpc_ddi1_device::device_add_mconfig(machine_config &config)
{
UPD765A(config, m_fdc, DERIVED_CLOCK(1, 1), true, true); // pin 50 clock multiplied to 8 MHz, then divided back down through SMC FDC9229BT
- FLOPPY_CONNECTOR(config, m_connector, ddi1_floppies, "3ssdd", floppy_image_device::default_floppy_formats);
+ FLOPPY_CONNECTOR(config, m_connector, ddi1_floppies, "3ssdd", floppy_image_device::default_mfm_floppy_formats);
SOFTWARE_LIST(config, "flop_list").set_original("cpc_flop");
// pass-through
@@ -75,9 +75,9 @@ void cpc_ddi1_device::device_start()
m_slot = dynamic_cast<cpc_expansion_slot_device *>(owner());
address_space &space = m_slot->cpu().space(AS_IO);
- space.install_write_handler(0xfa7e,0xfa7f,write8_delegate(FUNC(cpc_ddi1_device::motor_w),this));
- space.install_readwrite_handler(0xfb7e,0xfb7f,read8_delegate(FUNC(cpc_ddi1_device::fdc_r),this),write8_delegate(FUNC(cpc_ddi1_device::fdc_w),this));
- space.install_write_handler(0xdf00,0xdfff,write8_delegate(FUNC(cpc_ddi1_device::rombank_w),this));
+ space.install_write_handler(0xfa7e,0xfa7f, write8sm_delegate(*this, FUNC(cpc_ddi1_device::motor_w)));
+ space.install_readwrite_handler(0xfb7e,0xfb7f, read8sm_delegate(*this, FUNC(cpc_ddi1_device::fdc_r)), write8sm_delegate(*this, FUNC(cpc_ddi1_device::fdc_w)));
+ space.install_write_handler(0xdf00,0xdfff, write8smo_delegate(*this, FUNC(cpc_ddi1_device::rombank_w)));
}
//-------------------------------------------------
@@ -89,7 +89,7 @@ void cpc_ddi1_device::device_reset()
m_rom_active = false;
}
-WRITE8_MEMBER(cpc_ddi1_device::motor_w)
+void cpc_ddi1_device::motor_w(offs_t offset, uint8_t data)
{
switch(offset)
{
@@ -111,7 +111,7 @@ WRITE8_MEMBER(cpc_ddi1_device::motor_w)
}
}
-WRITE8_MEMBER(cpc_ddi1_device::fdc_w)
+void cpc_ddi1_device::fdc_w(offs_t offset, uint8_t data)
{
switch(offset)
{
@@ -121,7 +121,7 @@ WRITE8_MEMBER(cpc_ddi1_device::fdc_w)
}
}
-READ8_MEMBER(cpc_ddi1_device::fdc_r)
+uint8_t cpc_ddi1_device::fdc_r(offs_t offset)
{
uint8_t data = 0xff;
@@ -137,13 +137,13 @@ READ8_MEMBER(cpc_ddi1_device::fdc_r)
return data;
}
-WRITE8_MEMBER(cpc_ddi1_device::rombank_w)
+void cpc_ddi1_device::rombank_w(uint8_t data)
{
if(data == 0x07)
m_rom_active = true;
else
m_rom_active = false;
- m_slot->rom_select(space,0,data);
+ m_slot->rom_select(data);
}
void cpc_ddi1_device::set_mapping(uint8_t type)
diff --git a/src/devices/bus/cpc/ddi1.h b/src/devices/bus/cpc/ddi1.h
index 6e07813c7a2..a61abce55cf 100644
--- a/src/devices/bus/cpc/ddi1.h
+++ b/src/devices/bus/cpc/ddi1.h
@@ -23,21 +23,21 @@ public:
// construction/destruction
cpc_ddi1_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
- DECLARE_WRITE8_MEMBER(motor_w);
- DECLARE_WRITE8_MEMBER(fdc_w);
- DECLARE_READ8_MEMBER(fdc_r);
- DECLARE_WRITE8_MEMBER(rombank_w);
+ void motor_w(offs_t offset, uint8_t data);
+ void fdc_w(offs_t offset, uint8_t data);
+ uint8_t fdc_r(offs_t offset);
+ void rombank_w(uint8_t data);
protected:
// device-level overrides
- virtual void device_start() override;
- virtual void device_reset() override;
+ virtual void device_start() override ATTR_COLD;
+ virtual void device_reset() override ATTR_COLD;
// optional information overrides
- virtual const tiny_rom_entry *device_rom_region() const override;
- virtual void device_add_mconfig(machine_config &config) override;
+ virtual const tiny_rom_entry *device_rom_region() const override ATTR_COLD;
+ virtual void device_add_mconfig(machine_config &config) override ATTR_COLD;
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 e9ed2e5b5f4..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
//**************************************************************************
@@ -46,7 +48,7 @@ void cpc_doubler_device::device_start()
{
m_slot = dynamic_cast<cpc_expansion_slot_device *>(owner());
address_space &space = m_slot->cpu().space(AS_IO);
- space.install_read_handler(0xf0e0,0xf0e0,read8_delegate(FUNC(cpc_doubler_device::ext_tape_r),this));
+ space.install_read_handler(0xf0e0,0xf0e0, read8smo_delegate(*this, FUNC(cpc_doubler_device::ext_tape_r)));
}
//-------------------------------------------------
@@ -58,7 +60,7 @@ void cpc_doubler_device::device_reset()
// TODO
}
-READ8_MEMBER(cpc_doubler_device::ext_tape_r)
+uint8_t cpc_doubler_device::ext_tape_r()
{
uint8_t data = 0;
if(m_tape->input() > 0.03)
diff --git a/src/devices/bus/cpc/doubler.h b/src/devices/bus/cpc/doubler.h
index 2cba51baaee..7fa696ae514 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
@@ -24,15 +23,15 @@ public:
// construction/destruction
cpc_doubler_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
- DECLARE_READ8_MEMBER(ext_tape_r);
+ uint8_t ext_tape_r();
protected:
// device-level overrides
- virtual void device_start() override;
- virtual void device_reset() override;
+ virtual void device_start() override ATTR_COLD;
+ virtual void device_reset() override ATTR_COLD;
// optional information overrides
- virtual void device_add_mconfig(machine_config &config) override;
+ virtual void device_add_mconfig(machine_config &config) override ATTR_COLD;
private:
cpc_expansion_slot_device *m_slot;
diff --git a/src/devices/bus/cpc/hd20.cpp b/src/devices/bus/cpc/hd20.cpp
index c13ffca6b4b..ae9751f3c51 100644
--- a/src/devices/bus/cpc/hd20.cpp
+++ b/src/devices/bus/cpc/hd20.cpp
@@ -46,7 +46,7 @@ const tiny_rom_entry *cpc_hd20_device::device_rom_region() const
cpc_hd20_device::cpc_hd20_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) :
device_t(mconfig, CPC_HD20, tag, owner, clock),
device_cpc_expansion_card_interface(mconfig, *this), m_slot(nullptr),
- m_hdc(*this,"hdc")
+ m_hdc(*this, "hdc")
{
}
@@ -58,8 +58,8 @@ void cpc_hd20_device::device_start()
{
m_slot = dynamic_cast<cpc_expansion_slot_device *>(owner());
address_space &space = m_slot->cpu().space(AS_IO);
- space.install_write_handler(0xfbe0,0xfbe4,write8_delegate(FUNC(cpc_hd20_device::hdc_w),this));
- space.install_read_handler(0xfbe0,0xfbe4,read8_delegate(FUNC(cpc_hd20_device::hdc_r),this));
+ space.install_write_handler(0xfbe0,0xfbe4, write8sm_delegate(*this, FUNC(cpc_hd20_device::hdc_w)));
+ space.install_read_handler(0xfbe0,0xfbe4, read8sm_delegate(*this, FUNC(cpc_hd20_device::hdc_r)));
}
//-------------------------------------------------
@@ -71,7 +71,7 @@ void cpc_hd20_device::device_reset()
// TODO
}
-READ8_MEMBER(cpc_hd20_device::hdc_r)
+uint8_t cpc_hd20_device::hdc_r(offs_t offset)
{
uint8_t ret = 0x00;
@@ -95,7 +95,7 @@ READ8_MEMBER(cpc_hd20_device::hdc_r)
return ret;
}
-WRITE8_MEMBER(cpc_hd20_device::hdc_w)
+void cpc_hd20_device::hdc_w(offs_t offset, uint8_t data)
{
switch(offset)
{
@@ -117,7 +117,7 @@ WRITE8_MEMBER(cpc_hd20_device::hdc_w)
}
}
-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 a0379dbd831..ac88d18875c 100644
--- a/src/devices/bus/cpc/hd20.h
+++ b/src/devices/bus/cpc/hd20.h
@@ -26,20 +26,20 @@ public:
// construction/destruction
cpc_hd20_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
- DECLARE_READ8_MEMBER(hdc_r);
- DECLARE_WRITE8_MEMBER(hdc_w);
+ uint8_t hdc_r(offs_t offset);
+ void hdc_w(offs_t offset, uint8_t data);
protected:
// device-level overrides
- virtual void device_start() override;
- virtual void device_reset() override;
+ virtual void device_start() override ATTR_COLD;
+ virtual void device_reset() override ATTR_COLD;
// optional information overrides
- virtual void device_add_mconfig(machine_config &config) override;
- virtual const tiny_rom_entry *device_rom_region() const override;
+ virtual void device_add_mconfig(machine_config &config) override ATTR_COLD;
+ virtual const tiny_rom_entry *device_rom_region() const override ATTR_COLD;
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 1a85915dca1..23828254aac 100644
--- a/src/devices/bus/cpc/magicsound.cpp
+++ b/src/devices/bus/cpc/magicsound.cpp
@@ -9,7 +9,6 @@
#include "emu.h"
#include "magicsound.h"
-#include "sound/volt_reg.h"
#include "speaker.h"
@@ -59,9 +58,6 @@ void al_magicsound_device::device_add_mconfig(machine_config &config)
SPEAKER(config, "speaker").front_center();
DAC_8BIT_R2R(config, m_dac, 0).add_route(ALL_OUTPUTS, "speaker", 0.5); // unknown DAC
- voltage_regulator_device &vref(VOLTAGE_REGULATOR(config, "vref"));
- vref.add_route(0, "dac", 1.0, DAC_VREF_POS_INPUT);
- vref.add_route(0, "dac", -1.0, DAC_VREF_NEG_INPUT);
// no pass-through(?)
}
@@ -89,17 +85,14 @@ void al_magicsound_device::device_start()
{
m_slot = dynamic_cast<cpc_expansion_slot_device *>(owner());
address_space &space = m_slot->cpu().space(AS_IO);
- space.install_readwrite_handler(0xf8d0,0xf8df,read8_delegate(FUNC(al_magicsound_device::dmac_r),this),write8_delegate(FUNC(al_magicsound_device::dmac_w),this));
- space.install_write_handler(0xf9d0,0xf9df,write8_delegate(FUNC(al_magicsound_device::timer_w),this));
- space.install_write_handler(0xfad0,0xfadf,write8_delegate(FUNC(al_magicsound_device::volume_w),this));
- space.install_write_handler(0xfbd0,0xfbdf,write8_delegate(FUNC(al_magicsound_device::mapper_w),this));
+ space.install_readwrite_handler(0xf8d0,0xf8df, read8sm_delegate(*this, FUNC(al_magicsound_device::dmac_r)), write8sm_delegate(*this, FUNC(al_magicsound_device::dmac_w)));
+ space.install_write_handler(0xf9d0,0xf9df, write8sm_delegate(*this, FUNC(al_magicsound_device::timer_w)));
+ space.install_write_handler(0xfad0,0xfadf, write8sm_delegate(*this, FUNC(al_magicsound_device::volume_w)));
+ space.install_write_handler(0xfbd0,0xfbdf, write8sm_delegate(*this, FUNC(al_magicsound_device::mapper_w)));
m_ramptr = machine().device<ram_device>(":" RAM_TAG);
- for(int x=0;x<4;x++)
- {
- save_item(NAME(m_output[x]),x);
- }
+ save_item(NAME(m_output));
}
//-------------------------------------------------
@@ -113,17 +106,17 @@ void al_magicsound_device::device_reset()
set_timer_gate(false);
}
-READ8_MEMBER(al_magicsound_device::dmac_r)
+uint8_t al_magicsound_device::dmac_r(offs_t offset)
{
return m_dmac->read(offset);
}
-WRITE8_MEMBER(al_magicsound_device::dmac_w)
+void al_magicsound_device::dmac_w(offs_t offset, uint8_t data)
{
m_dmac->write(offset,data);
}
-WRITE8_MEMBER(al_magicsound_device::timer_w)
+void al_magicsound_device::timer_w(offs_t offset, uint8_t data)
{
// can both PITs be selected at the same time?
if(offset & 0x08)
@@ -132,12 +125,12 @@ WRITE8_MEMBER(al_magicsound_device::timer_w)
m_timer2->write(offset & 0x03,data);
}
-WRITE8_MEMBER(al_magicsound_device::volume_w)
+void al_magicsound_device::volume_w(offs_t offset, uint8_t data)
{
m_volume[offset & 0x03] = data & 0x3f;
}
-WRITE8_MEMBER(al_magicsound_device::mapper_w)
+void al_magicsound_device::mapper_w(offs_t offset, uint8_t data)
{
uint8_t channel = (offset & 0x0c) >> 2;
uint8_t page = offset & 0x03;
@@ -145,24 +138,24 @@ WRITE8_MEMBER(al_magicsound_device::mapper_w)
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); }
-READ8_MEMBER(al_magicsound_device::dma_read_byte)
+uint8_t al_magicsound_device::dma_read_byte(offs_t offset)
{
uint8_t ret = 0xff;
uint8_t page = (offset & 0xc000) >> 14;
@@ -172,7 +165,7 @@ READ8_MEMBER(al_magicsound_device::dma_read_byte)
return ret;
}
-WRITE8_MEMBER(al_magicsound_device::dma_write_byte)
+void al_magicsound_device::dma_write_byte(uint8_t data)
{
m_output[m_current_channel] = data;
}
diff --git a/src/devices/bus/cpc/magicsound.h b/src/devices/bus/cpc/magicsound.h
index b90bbf4e897..162ef1f7c86 100644
--- a/src/devices/bus/cpc/magicsound.h
+++ b/src/devices/bus/cpc/magicsound.h
@@ -41,32 +41,32 @@ public:
// construction/destruction
al_magicsound_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
- DECLARE_READ8_MEMBER(dmac_r);
- DECLARE_WRITE8_MEMBER(dmac_w);
- DECLARE_WRITE8_MEMBER(timer_w);
- DECLARE_WRITE8_MEMBER(volume_w);
- DECLARE_WRITE8_MEMBER(mapper_w);
+ uint8_t dmac_r(offs_t offset);
+ void dmac_w(offs_t offset, uint8_t data);
+ void timer_w(offs_t offset, uint8_t data);
+ void volume_w(offs_t offset, uint8_t data);
+ void mapper_w(offs_t offset, uint8_t data);
protected:
// device-level overrides
- virtual void device_start() override;
- virtual void device_reset() override;
+ virtual void device_start() override ATTR_COLD;
+ virtual void device_reset() override ATTR_COLD;
// optional information overrides
- virtual void device_add_mconfig(machine_config &config) override;
+ virtual void device_add_mconfig(machine_config &config) override ATTR_COLD;
private:
- DECLARE_WRITE_LINE_MEMBER(da0_w);
- DECLARE_READ8_MEMBER(dma_read_byte);
- DECLARE_WRITE8_MEMBER(dma_write_byte);
- 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 da0_w(int state);
+ uint8_t dma_read_byte(offs_t offset);
+ void dma_write_byte(uint8_t data);
+ 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/mface2.h b/src/devices/bus/cpc/mface2.h
index ba230b917c6..0893d36634a 100644
--- a/src/devices/bus/cpc/mface2.h
+++ b/src/devices/bus/cpc/mface2.h
@@ -47,13 +47,13 @@ public:
protected:
// device-level overrides
- virtual void device_start() override;
- virtual void device_reset() override;
+ virtual void device_start() override ATTR_COLD;
+ virtual void device_reset() override ATTR_COLD;
// optional information overrides
- 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 const tiny_rom_entry *device_rom_region() const override ATTR_COLD;
+ virtual ioport_constructor device_input_ports() const override ATTR_COLD;
+ virtual void device_add_mconfig(machine_config &config) override ATTR_COLD;
private:
cpc_expansion_slot_device *m_slot;
diff --git a/src/devices/bus/cpc/musicmachine.cpp b/src/devices/bus/cpc/musicmachine.cpp
index 4d43f20c1fe..83c5bef8dfc 100644
--- a/src/devices/bus/cpc/musicmachine.cpp
+++ b/src/devices/bus/cpc/musicmachine.cpp
@@ -2,13 +2,12 @@
// copyright-holders:Barry Rodewald
/*
* The Music Machine - MIDI and sampling expansion
- * by Ram Electronics
+ * by Ram Electronics Ltd
*/
#include "emu.h"
#include "musicmachine.h"
-#include "sound/volt_reg.h"
#include "bus/midi/midi.h"
#include "machine/clock.h"
#include "speaker.h"
@@ -17,7 +16,7 @@
// DEVICE DEFINITIONS
//**************************************************************************
-DEFINE_DEVICE_TYPE(CPC_MUSICMACHINE, cpc_musicmachine_device, "cpcmusic", "The Music Machine")
+DEFINE_DEVICE_TYPE(CPC_MUSICMACHINE, cpc_musicmachine_device, "cpcmusic", "The Music Machine (CPC)")
void cpc_musicmachine_device::device_add_mconfig(machine_config &config)
@@ -31,9 +30,6 @@ void cpc_musicmachine_device::device_add_mconfig(machine_config &config)
SPEAKER(config, "speaker").front_center();
ZN429E(config, m_dac, 0).add_route(ALL_OUTPUTS, "speaker", 0.2);
- voltage_regulator_device &vref(VOLTAGE_REGULATOR(config, "vref"));
- vref.add_route(0, "dac", 1.0, DAC_VREF_POS_INPUT);
- vref.add_route(0, "dac", -1.0, DAC_VREF_NEG_INPUT);
// no pass-through
}
@@ -61,9 +57,9 @@ void cpc_musicmachine_device::device_start()
m_slot = dynamic_cast<cpc_expansion_slot_device *>(owner());
address_space &space = m_slot->cpu().space(AS_IO);
- space.install_write_handler(0xf8e8,0xf8e8,write8_delegate(FUNC(cpc_musicmachine_device::irqsel_w),this));
- space.install_readwrite_handler(0xf8ec,0xf8ef,read8_delegate(FUNC(cpc_musicmachine_device::acia_r), this),write8_delegate(FUNC(cpc_musicmachine_device::acia_w),this));
- space.install_write_handler(0xf8f0,0xf8f0,write8_delegate(FUNC(cpc_musicmachine_device::dac_w),this));
+ space.install_write_handler(0xf8e8,0xf8e8, write8smo_delegate(*this, FUNC(cpc_musicmachine_device::irqsel_w)));
+ space.install_readwrite_handler(0xf8ec,0xf8ef, read8sm_delegate(*this, FUNC(cpc_musicmachine_device::acia_r)), write8sm_delegate(*this, FUNC(cpc_musicmachine_device::acia_w)));
+ space.install_write_handler(0xf8f0,0xf8f0, write8smo_delegate(*this, FUNC(cpc_musicmachine_device::dac_w)));
// 0xf8f4 - ADC read8_delegate
// 0xf8f8 - ADC start
}
@@ -77,12 +73,12 @@ void cpc_musicmachine_device::device_reset()
// TODO
}
-WRITE8_MEMBER(cpc_musicmachine_device::dac_w)
+void cpc_musicmachine_device::dac_w(uint8_t data)
{
m_dac->write(data);
}
-READ8_MEMBER(cpc_musicmachine_device::acia_r)
+uint8_t cpc_musicmachine_device::acia_r(offs_t offset)
{
uint8_t ret = 0;
@@ -99,7 +95,7 @@ READ8_MEMBER(cpc_musicmachine_device::acia_r)
return ret;
}
-WRITE8_MEMBER(cpc_musicmachine_device::acia_w)
+void cpc_musicmachine_device::acia_w(offs_t offset, uint8_t data)
{
switch(offset)
{
@@ -112,7 +108,7 @@ WRITE8_MEMBER(cpc_musicmachine_device::acia_w)
}
}
-WRITE8_MEMBER(cpc_musicmachine_device::irqsel_w)
+void cpc_musicmachine_device::irqsel_w(uint8_t data)
{
if(data == 0x01)
m_irq_select = true;
@@ -120,7 +116,7 @@ WRITE8_MEMBER(cpc_musicmachine_device::irqsel_w)
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 511eb19aa02..aea3d6ab9d1 100644
--- a/src/devices/bus/cpc/musicmachine.h
+++ b/src/devices/bus/cpc/musicmachine.h
@@ -23,21 +23,21 @@ public:
// construction/destruction
cpc_musicmachine_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
- DECLARE_WRITE8_MEMBER(dac_w);
- DECLARE_READ8_MEMBER(acia_r);
- DECLARE_WRITE8_MEMBER(acia_w);
- DECLARE_WRITE8_MEMBER(irqsel_w);
- DECLARE_WRITE_LINE_MEMBER(irq_w);
+ void dac_w(uint8_t data);
+ uint8_t acia_r(offs_t offset);
+ void acia_w(offs_t offset, uint8_t data);
+ void irqsel_w(uint8_t data);
+ void irq_w(int state);
void write_acia_clock(u8 data) { m_acia->write_txc(data); m_acia->write_rxc(data); }
protected:
// device-level overrides
- virtual void device_start() override;
- virtual void device_reset() override;
+ virtual void device_start() override ATTR_COLD;
+ virtual void device_reset() override ATTR_COLD;
// optional information overrides
- virtual void device_add_mconfig(machine_config &config) override;
+ virtual void device_add_mconfig(machine_config &config) override ATTR_COLD;
private:
cpc_expansion_slot_device *m_slot;
diff --git a/src/devices/bus/cpc/playcity.cpp b/src/devices/bus/cpc/playcity.cpp
index 7d444abb03b..a2429242f43 100644
--- a/src/devices/bus/cpc/playcity.cpp
+++ b/src/devices/bus/cpc/playcity.cpp
@@ -31,12 +31,11 @@ void cpc_playcity_device::device_add_mconfig(machine_config &config)
m_ctc->zc_callback<2>().set(m_ctc, FUNC(z80ctc_device::trg3));
m_ctc->intr_callback().set(FUNC(cpc_playcity_device::ctc_intr_cb));
- SPEAKER(config, "lspeaker").front_left();
- SPEAKER(config, "rspeaker").front_right();
+ SPEAKER(config, "speaker", 2).front();
YMZ294(config, m_ymz1, DERIVED_CLOCK(1, 1)); // when timer is not set, operates at 4MHz (interally divided by 2, so equivalent to the ST)
- m_ymz1->add_route(ALL_OUTPUTS, "rspeaker", 0.30);
+ m_ymz1->add_route(ALL_OUTPUTS, "speaker", 0.30, 1);
YMZ294(config, m_ymz2, DERIVED_CLOCK(1, 1));
- m_ymz2->add_route(ALL_OUTPUTS, "lspeaker", 0.30);
+ m_ymz2->add_route(ALL_OUTPUTS, "speaker", 0.30, 0);
// pass-through
cpc_expansion_slot_device &exp(CPC_EXPANSION_SLOT(config, "exp", DERIVED_CLOCK(1, 1), cpc_exp_cards, nullptr));
@@ -69,11 +68,11 @@ void cpc_playcity_device::device_start()
m_slot = dynamic_cast<cpc_expansion_slot_device *>(owner());
address_space &space = m_slot->cpu().space(AS_IO);
- space.install_readwrite_handler(0xf880,0xf883,read8_delegate(FUNC(cpc_playcity_device::ctc_r),this),write8_delegate(FUNC(cpc_playcity_device::ctc_w),this));
- space.install_readwrite_handler(0xf884,0xf884,read8_delegate(FUNC(cpc_playcity_device::ymz1_data_r),this),write8_delegate(FUNC(cpc_playcity_device::ymz1_data_w),this));
- space.install_readwrite_handler(0xf888,0xf888,read8_delegate(FUNC(cpc_playcity_device::ymz2_data_r),this),write8_delegate(FUNC(cpc_playcity_device::ymz2_data_w),this));
- space.install_write_handler(0xf984,0xf984,write8_delegate(FUNC(cpc_playcity_device::ymz1_address_w),this));
- space.install_write_handler(0xf988,0xf988,write8_delegate(FUNC(cpc_playcity_device::ymz2_address_w),this));
+ space.install_readwrite_handler(0xf880,0xf883, read8sm_delegate(*this, FUNC(cpc_playcity_device::ctc_r)), write8sm_delegate(*this, FUNC(cpc_playcity_device::ctc_w)));
+ space.install_readwrite_handler(0xf884,0xf884, read8smo_delegate(*this, FUNC(cpc_playcity_device::ymz1_data_r)), write8smo_delegate(*this, FUNC(cpc_playcity_device::ymz1_data_w)));
+ space.install_readwrite_handler(0xf888,0xf888, read8smo_delegate(*this, FUNC(cpc_playcity_device::ymz2_data_r)), write8smo_delegate(*this, FUNC(cpc_playcity_device::ymz2_data_w)));
+ space.install_write_handler(0xf984,0xf984, write8smo_delegate(*this, FUNC(cpc_playcity_device::ymz1_address_w)));
+ space.install_write_handler(0xf988,0xf988, write8smo_delegate(*this, FUNC(cpc_playcity_device::ymz2_address_w)));
}
//-------------------------------------------------
@@ -85,44 +84,44 @@ void cpc_playcity_device::device_reset()
}
-READ8_MEMBER(cpc_playcity_device::ctc_r)
+uint8_t cpc_playcity_device::ctc_r(offs_t offset)
{
return m_ctc->read(offset);
}
-WRITE8_MEMBER(cpc_playcity_device::ctc_w)
+void cpc_playcity_device::ctc_w(offs_t offset, uint8_t data)
{
m_ctc->write(offset,data);
if(offset == 0)
update_ymz_clock();
}
-WRITE8_MEMBER(cpc_playcity_device::ymz1_address_w)
+void cpc_playcity_device::ymz1_address_w(uint8_t data)
{
m_ymz1->address_w(data);
}
-WRITE8_MEMBER(cpc_playcity_device::ymz2_address_w)
+void cpc_playcity_device::ymz2_address_w(uint8_t data)
{
m_ymz2->address_w(data);
}
-WRITE8_MEMBER(cpc_playcity_device::ymz1_data_w)
+void cpc_playcity_device::ymz1_data_w(uint8_t data)
{
m_ymz1->data_w(data);
}
-WRITE8_MEMBER(cpc_playcity_device::ymz2_data_w)
+void cpc_playcity_device::ymz2_data_w(uint8_t data)
{
m_ymz2->data_w(data);
}
-READ8_MEMBER(cpc_playcity_device::ymz1_data_r)
+uint8_t cpc_playcity_device::ymz1_data_r()
{
return m_ymz1->data_r();
}
-READ8_MEMBER(cpc_playcity_device::ymz2_data_r)
+uint8_t cpc_playcity_device::ymz2_data_r()
{
return m_ymz2->data_r();
}
diff --git a/src/devices/bus/cpc/playcity.h b/src/devices/bus/cpc/playcity.h
index e01c055aee5..0424220aadc 100644
--- a/src/devices/bus/cpc/playcity.h
+++ b/src/devices/bus/cpc/playcity.h
@@ -30,28 +30,28 @@ public:
// construction/destruction
cpc_playcity_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
- DECLARE_READ8_MEMBER(ctc_r);
- DECLARE_WRITE8_MEMBER(ctc_w);
- DECLARE_WRITE8_MEMBER(ymz1_address_w);
- DECLARE_WRITE8_MEMBER(ymz2_address_w);
- DECLARE_WRITE8_MEMBER(ymz1_data_w);
- DECLARE_WRITE8_MEMBER(ymz2_data_w);
- DECLARE_READ8_MEMBER(ymz1_data_r);
- DECLARE_READ8_MEMBER(ymz2_data_r);
+ uint8_t ctc_r(offs_t offset);
+ void ctc_w(offs_t offset, uint8_t data);
+ void ymz1_address_w(uint8_t data);
+ void ymz2_address_w(uint8_t data);
+ void ymz1_data_w(uint8_t data);
+ void ymz2_data_w(uint8_t data);
+ 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
- virtual void device_start() override;
- virtual void device_reset() override;
+ virtual void device_start() override ATTR_COLD;
+ virtual void device_reset() override ATTR_COLD;
// optional information overrides
- virtual void device_add_mconfig(machine_config &config) override;
+ virtual void device_add_mconfig(machine_config &config) override ATTR_COLD;
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/smartwatch.cpp b/src/devices/bus/cpc/smartwatch.cpp
index 272b7ca953e..4b2aa04cd10 100644
--- a/src/devices/bus/cpc/smartwatch.cpp
+++ b/src/devices/bus/cpc/smartwatch.cpp
@@ -4,9 +4,6 @@
Dobbertin Smartwatch
Created: 23/2/2015
-
- TODO: setting the time (requires the DS1315 core to be able to do this,
- at the moment it just reads the current time)
*/
#include "emu.h"
@@ -21,8 +18,7 @@ DEFINE_DEVICE_TYPE(CPC_SMARTWATCH, cpc_smartwatch_device, "cpc_smartwatch", "Dob
void cpc_smartwatch_device::device_add_mconfig(machine_config &config)
{
- DS1315(config, m_rtc, 0);
- // no pass-through (?)
+ DS1216E(config, m_rtc);
}
@@ -63,26 +59,17 @@ void cpc_smartwatch_device::device_start()
void cpc_smartwatch_device::device_reset()
{
address_space &space = m_slot->cpu().space(AS_PROGRAM);
- space.install_read_handler(0xc000,0xc001,read8_delegate(FUNC(cpc_smartwatch_device::rtc_w),this));
- space.install_read_handler(0xc004,0xc004,read8_delegate(FUNC(cpc_smartwatch_device::rtc_r),this));
+ // FIXME: should cover the whole ROM address decode range
+ space.install_read_handler(0xc000,0xc004, read8sm_delegate(*this, FUNC(cpc_smartwatch_device::rtc_r)));
m_bank = membank(":bank7");
}
-READ8_MEMBER(cpc_smartwatch_device::rtc_w)
-{
- uint8_t* bank = (uint8_t*)m_bank->base();
- if (!machine().side_effects_disabled())
- {
- if(offset & 1)
- m_rtc->read_1();
- else
- m_rtc->read_0();
- }
- return bank[offset & 1];
-}
-
-READ8_MEMBER(cpc_smartwatch_device::rtc_r)
+uint8_t cpc_smartwatch_device::rtc_r(offs_t offset)
{
uint8_t* bank = (uint8_t*)m_bank->base();
- return ((bank[(offset & 1)+4]) & 0xfe) | (m_rtc->read_data() & 0x01);
+ if (m_rtc->ceo_r())
+ return m_rtc->read(offset);
+ else
+ m_rtc->read(offset);
+ return bank[offset];
}
diff --git a/src/devices/bus/cpc/smartwatch.h b/src/devices/bus/cpc/smartwatch.h
index dbde5f58377..3c9959f6590 100644
--- a/src/devices/bus/cpc/smartwatch.h
+++ b/src/devices/bus/cpc/smartwatch.h
@@ -15,7 +15,7 @@
#pragma once
#include "cpcexp.h"
-#include "machine/ds1315.h"
+#include "machine/ds1215.h"
class cpc_smartwatch_device : public device_t, public device_cpc_expansion_card_interface
{
@@ -23,22 +23,21 @@ public:
// construction/destruction
cpc_smartwatch_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
- DECLARE_READ8_MEMBER(rtc_w);
- DECLARE_READ8_MEMBER(rtc_r);
+ uint8_t rtc_r(offs_t offset);
protected:
// device-level overrides
- virtual void device_start() override;
- virtual void device_reset() override;
+ virtual void device_start() override ATTR_COLD;
+ virtual void device_reset() override ATTR_COLD;
// optional information overrides
- virtual void device_add_mconfig(machine_config &config) override;
- virtual const tiny_rom_entry *device_rom_region() const override;
+ virtual void device_add_mconfig(machine_config &config) override ATTR_COLD;
+ virtual const tiny_rom_entry *device_rom_region() const override ATTR_COLD;
private:
cpc_expansion_slot_device *m_slot;
- required_device<ds1315_device> m_rtc;
+ required_device<ds1216e_device> m_rtc;
memory_bank* m_bank;
};
diff --git a/src/devices/bus/cpc/symbfac2.cpp b/src/devices/bus/cpc/symbfac2.cpp
index a59a73bf72e..f79fe5b029d 100644
--- a/src/devices/bus/cpc/symbfac2.cpp
+++ b/src/devices/bus/cpc/symbfac2.cpp
@@ -30,17 +30,17 @@ DEFINE_DEVICE_TYPE(CPC_SYMBIFACE2, cpc_symbiface2_device, "cpc_symf2", "SYMBiFAC
static INPUT_PORTS_START(cpc_symbiface2)
PORT_START("sf2_mouse_x")
- PORT_BIT(0x3f , 0x00, IPT_MOUSE_X) PORT_SENSITIVITY(50) PORT_KEYDELTA(0) PORT_REVERSE PORT_PLAYER(1) PORT_CODE(MOUSECODE_X) PORT_CHANGED_MEMBER(DEVICE_SELF,cpc_symbiface2_device,mouse_change_x,0)
+ PORT_BIT(0x3f , 0x00, IPT_MOUSE_X) PORT_SENSITIVITY(50) PORT_KEYDELTA(0) PORT_REVERSE PORT_PLAYER(1) PORT_CODE(MOUSECODE_X) PORT_CHANGED_MEMBER(DEVICE_SELF, FUNC(cpc_symbiface2_device::mouse_change_x), 0)
PORT_START("sf2_mouse_y")
- PORT_BIT(0x3f , 0x00, IPT_MOUSE_Y) PORT_SENSITIVITY(50) PORT_KEYDELTA(0) PORT_PLAYER(1) PORT_CODE(MOUSECODE_Y) PORT_CHANGED_MEMBER(DEVICE_SELF,cpc_symbiface2_device,mouse_change_x,0)
+ PORT_BIT(0x3f , 0x00, IPT_MOUSE_Y) PORT_SENSITIVITY(50) PORT_KEYDELTA(0) PORT_PLAYER(1) PORT_CODE(MOUSECODE_Y) PORT_CHANGED_MEMBER(DEVICE_SELF, FUNC(cpc_symbiface2_device::mouse_change_x), 0)
PORT_START("sf2_mouse_buttons")
- PORT_BIT(0x00000001, IP_ACTIVE_HIGH, IPT_OTHER) PORT_NAME("PS/2 Mouse left button") PORT_CODE(MOUSECODE_BUTTON1) PORT_CHANGED_MEMBER(DEVICE_SELF,cpc_symbiface2_device,mouse_change_x,0)
- PORT_BIT(0x00000002, IP_ACTIVE_HIGH, IPT_OTHER) PORT_NAME("PS/2 Mouse right button") PORT_CODE(MOUSECODE_BUTTON3) PORT_CHANGED_MEMBER(DEVICE_SELF,cpc_symbiface2_device,mouse_change_x,0)
- PORT_BIT(0x00000004, IP_ACTIVE_HIGH, IPT_OTHER) PORT_NAME("PS/2 Mouse middle button") PORT_CODE(MOUSECODE_BUTTON2) PORT_CHANGED_MEMBER(DEVICE_SELF,cpc_symbiface2_device,mouse_change_x,0)
- PORT_BIT(0x00000008, IP_ACTIVE_HIGH, IPT_OTHER) PORT_NAME("PS/2 Mouse back button") PORT_CODE(MOUSECODE_BUTTON4) PORT_CHANGED_MEMBER(DEVICE_SELF,cpc_symbiface2_device,mouse_change_x,0)
- PORT_BIT(0x00000010, IP_ACTIVE_HIGH, IPT_OTHER) PORT_NAME("PS/2 Mouse forward button") PORT_CODE(MOUSECODE_BUTTON5) PORT_CHANGED_MEMBER(DEVICE_SELF,cpc_symbiface2_device,mouse_change_x,0)
+ PORT_BIT(0x00000001, IP_ACTIVE_HIGH, IPT_OTHER) PORT_NAME("PS/2 Mouse left button") PORT_CODE(MOUSECODE_BUTTON1) PORT_CHANGED_MEMBER(DEVICE_SELF, FUNC(cpc_symbiface2_device::mouse_change_x), 0)
+ PORT_BIT(0x00000002, IP_ACTIVE_HIGH, IPT_OTHER) PORT_NAME("PS/2 Mouse right button") PORT_CODE(MOUSECODE_BUTTON3) PORT_CHANGED_MEMBER(DEVICE_SELF, FUNC(cpc_symbiface2_device::mouse_change_x), 0)
+ PORT_BIT(0x00000004, IP_ACTIVE_HIGH, IPT_OTHER) PORT_NAME("PS/2 Mouse middle button") PORT_CODE(MOUSECODE_BUTTON2) PORT_CHANGED_MEMBER(DEVICE_SELF, FUNC(cpc_symbiface2_device::mouse_change_x), 0)
+ PORT_BIT(0x00000008, IP_ACTIVE_HIGH, IPT_OTHER) PORT_NAME("PS/2 Mouse back button") PORT_CODE(MOUSECODE_BUTTON4) PORT_CHANGED_MEMBER(DEVICE_SELF, FUNC(cpc_symbiface2_device::mouse_change_x), 0)
+ PORT_BIT(0x00000010, IP_ACTIVE_HIGH, IPT_OTHER) PORT_NAME("PS/2 Mouse forward button") PORT_CODE(MOUSECODE_BUTTON5) PORT_CHANGED_MEMBER(DEVICE_SELF, FUNC(cpc_symbiface2_device::mouse_change_x), 0)
// TODO: mouse scroll wheel support
// PORT_START("sf2_mouse_scroll")
@@ -90,11 +90,12 @@ void cpc_symbiface2_device::device_start()
{
m_slot = dynamic_cast<cpc_expansion_slot_device *>(owner());
address_space &space = m_slot->cpu().space(AS_IO);
- space.install_readwrite_handler(0xfd00,0xfd07,read8_delegate(FUNC(cpc_symbiface2_device::ide_cs1_r),this),write8_delegate(FUNC(cpc_symbiface2_device::ide_cs1_w),this));
- space.install_readwrite_handler(0xfd08,0xfd0f,read8_delegate(FUNC(cpc_symbiface2_device::ide_cs0_r),this),write8_delegate(FUNC(cpc_symbiface2_device::ide_cs0_w),this));
- space.install_read_handler(0xfd10,0xfd10,read8_delegate(FUNC(cpc_symbiface2_device::mouse_r),this));
- space.install_readwrite_handler(0xfd14,0xfd15,read8_delegate(FUNC(cpc_symbiface2_device::rtc_r),this),write8_delegate(FUNC(cpc_symbiface2_device::rtc_w),this));
- space.install_readwrite_handler(0xfd17,0xfd17,read8_delegate(FUNC(cpc_symbiface2_device::rom_rewrite_r),this),write8_delegate(FUNC(cpc_symbiface2_device::rom_rewrite_w),this));
+ 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,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)
// 32 banks of 16kB (512kB)
@@ -120,7 +121,7 @@ void cpc_symbiface2_device::device_reset()
// IDE controller (custom)
// #FD00-07 - CS1
// #FD08-0F - CS0
-READ8_MEMBER(cpc_symbiface2_device::ide_cs0_r)
+uint8_t cpc_symbiface2_device::ide_cs0_r(offs_t offset)
{
// data is returned in words, so it must be buffered
if(offset == 0x00) // data register
@@ -133,41 +134,32 @@ READ8_MEMBER(cpc_symbiface2_device::ide_cs0_r)
else
{
m_iohigh = true;
- m_ide_data = m_ide->read_cs0(offset);
+ m_ide_data = m_ide->cs0_r(offset);
return m_ide_data & 0xff;
}
}
else
- return m_ide->read_cs0(offset);
+ return m_ide->cs0_r(offset);
}
-WRITE8_MEMBER(cpc_symbiface2_device::ide_cs0_w)
+void cpc_symbiface2_device::ide_cs0_w(offs_t offset, uint8_t data)
{
- m_ide->write_cs0(offset, data);
+ m_ide->cs0_w(offset, data);
}
-READ8_MEMBER(cpc_symbiface2_device::ide_cs1_r)
+uint8_t cpc_symbiface2_device::ide_cs1_r(offs_t offset)
{
- return m_ide->read_cs1(offset);
+ return m_ide->cs1_r(offset);
}
-WRITE8_MEMBER(cpc_symbiface2_device::ide_cs1_w)
+void cpc_symbiface2_device::ide_cs1_w(offs_t offset, uint8_t data)
{
- m_ide->write_cs1(offset, data);
+ m_ide->cs1_w(offset, data);
}
// RTC (Dallas DS1287A)
// #FD15 (write only) register select
// #FD14 (read/write) read from or write into selected register
-READ8_MEMBER(cpc_symbiface2_device::rtc_r)
-{
- return m_rtc->read(~offset & 0x01);
-}
-
-WRITE8_MEMBER(cpc_symbiface2_device::rtc_w)
-{
- m_rtc->write(~offset & 0x01, data);
-}
// PS/2 Mouse connector
// #FD10 (read only) read mouse status
@@ -193,7 +185,7 @@ WRITE8_MEMBER(cpc_symbiface2_device::rtc_w)
D[bit4] = backward button
D[bit5] = 1 -> D[bit0-4] = scroll wheel offset (signed)
*/
-READ8_MEMBER(cpc_symbiface2_device::mouse_r)
+uint8_t cpc_symbiface2_device::mouse_r()
{
uint8_t ret = 0;
int input;
@@ -247,11 +239,11 @@ INPUT_CHANGED_MEMBER(cpc_symbiface2_device::mouse_change_buttons)
}
// #FD17 (read) - map currently selected ROM to 0x4000 for read/write
-READ8_MEMBER(cpc_symbiface2_device::rom_rewrite_r)
+uint8_t cpc_symbiface2_device::rom_rewrite_r()
{
uint8_t bank = get_rom_bank();
- if(bank >= 32)
+ if(bank >= 32 || machine().side_effects_disabled())
return 0xff;
m_4xxx_ptr_r = (uint8_t*)machine().root_device().membank("bank3")->base();
@@ -267,7 +259,7 @@ READ8_MEMBER(cpc_symbiface2_device::rom_rewrite_r)
}
// #FD17 (write) - unmap selected ROM at 0x4000
-WRITE8_MEMBER(cpc_symbiface2_device::rom_rewrite_w)
+void cpc_symbiface2_device::rom_rewrite_w(uint8_t data)
{
machine().root_device().membank("bank3")->set_base(m_4xxx_ptr_r);
machine().root_device().membank("bank4")->set_base(m_6xxx_ptr_r);
diff --git a/src/devices/bus/cpc/symbfac2.h b/src/devices/bus/cpc/symbfac2.h
index df490907a90..941c2814542 100644
--- a/src/devices/bus/cpc/symbfac2.h
+++ b/src/devices/bus/cpc/symbfac2.h
@@ -12,7 +12,7 @@
#pragma once
#include "cpcexp.h"
-#include "machine/ataintf.h"
+#include "bus/ata/ataintf.h"
#include "machine/ds128x.h"
#include "machine/nvram.h"
@@ -23,15 +23,13 @@ public:
// construction/destruction
cpc_symbiface2_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
- DECLARE_READ8_MEMBER(ide_cs0_r);
- DECLARE_WRITE8_MEMBER(ide_cs0_w);
- DECLARE_READ8_MEMBER(ide_cs1_r);
- DECLARE_WRITE8_MEMBER(ide_cs1_w);
- DECLARE_READ8_MEMBER(rtc_r);
- DECLARE_WRITE8_MEMBER(rtc_w);
- DECLARE_READ8_MEMBER(mouse_r);
- DECLARE_READ8_MEMBER(rom_rewrite_r);
- DECLARE_WRITE8_MEMBER(rom_rewrite_w);
+ uint8_t ide_cs0_r(offs_t offset);
+ 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 mouse_r();
+ uint8_t rom_rewrite_r();
+ void rom_rewrite_w(uint8_t data);
DECLARE_INPUT_CHANGED_MEMBER(mouse_change_x);
DECLARE_INPUT_CHANGED_MEMBER(mouse_change_y);
DECLARE_INPUT_CHANGED_MEMBER(mouse_change_buttons);
@@ -47,12 +45,12 @@ public:
protected:
// device-level overrides
- virtual void device_start() override;
- virtual void device_reset() override;
+ virtual void device_start() override ATTR_COLD;
+ virtual void device_reset() override ATTR_COLD;
// optional information overrides
- virtual void device_add_mconfig(machine_config &config) override;
- virtual ioport_constructor device_input_ports() const override;
+ virtual void device_add_mconfig(machine_config &config) override ATTR_COLD;
+ virtual ioport_constructor device_input_ports() const override ATTR_COLD;
private:
cpc_expansion_slot_device *m_slot;
diff --git a/src/devices/bus/cpc/transtape.cpp b/src/devices/bus/cpc/transtape.cpp
index 78ec1f15c72..08c3ca84d71 100644
--- a/src/devices/bus/cpc/transtape.cpp
+++ b/src/devices/bus/cpc/transtape.cpp
@@ -29,8 +29,8 @@ const tiny_rom_entry *cpc_transtape_device::device_rom_region() const
static INPUT_PORTS_START(cpc_transtape)
PORT_START("transtape")
- PORT_BIT(0x01, IP_ACTIVE_HIGH, IPT_OTHER) PORT_NAME("Red Button") PORT_CODE(KEYCODE_F1) PORT_CHANGED_MEMBER(DEVICE_SELF,cpc_transtape_device,button_red_w,0)
- PORT_BIT(0x02, IP_ACTIVE_HIGH, IPT_OTHER) PORT_NAME("Black Button") PORT_CODE(KEYCODE_F2) PORT_CHANGED_MEMBER(DEVICE_SELF,cpc_transtape_device,button_black_w,0)
+ PORT_BIT(0x01, IP_ACTIVE_HIGH, IPT_OTHER) PORT_NAME("Red Button") PORT_CODE(KEYCODE_F1) PORT_CHANGED_MEMBER(DEVICE_SELF, FUNC(cpc_transtape_device::button_red_w), 0)
+ PORT_BIT(0x02, IP_ACTIVE_HIGH, IPT_OTHER) PORT_NAME("Black Button") PORT_CODE(KEYCODE_F2) PORT_CHANGED_MEMBER(DEVICE_SELF, FUNC(cpc_transtape_device::button_black_w), 0)
INPUT_PORTS_END
ioport_constructor cpc_transtape_device::device_input_ports() const
@@ -63,8 +63,8 @@ void cpc_transtape_device::device_start()
m_ram = make_unique_clear<uint8_t[]>(0x2000);
- m_space->install_write_handler(0xfbf0,0xfbf0,write8_delegate(FUNC(cpc_transtape_device::output_w),this));
- m_space->install_read_handler(0xfbff,0xfbff,read8_delegate(FUNC(cpc_transtape_device::input_r),this));
+ m_space->install_write_handler(0xfbf0,0xfbf0, write8smo_delegate(*this, FUNC(cpc_transtape_device::output_w)));
+ m_space->install_read_handler(0xfbff,0xfbff, read8smo_delegate(*this, FUNC(cpc_transtape_device::input_r)));
}
//-------------------------------------------------
@@ -117,17 +117,17 @@ INPUT_CHANGED_MEMBER(cpc_transtape_device::button_black_w)
}
}
-READ8_MEMBER(cpc_transtape_device::input_r)
+uint8_t cpc_transtape_device::input_r()
{
// TODO
return 0x80;
}
-WRITE8_MEMBER(cpc_transtape_device::output_w)
+void cpc_transtape_device::output_w(uint8_t data)
{
// TODO
m_output = data;
- m_slot->rom_select(space,0,get_rom_bank()); // trigger rethink
+ m_slot->rom_select(get_rom_bank()); // trigger rethink
}
void cpc_transtape_device::set_mapping(uint8_t type)
diff --git a/src/devices/bus/cpc/transtape.h b/src/devices/bus/cpc/transtape.h
index 6b7e4539023..aba5e1dfd38 100644
--- a/src/devices/bus/cpc/transtape.h
+++ b/src/devices/bus/cpc/transtape.h
@@ -22,21 +22,21 @@ public:
cpc_transtape_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 ioport_constructor device_input_ports() const override;
+ virtual const tiny_rom_entry *device_rom_region() const override ATTR_COLD;
+ virtual ioport_constructor device_input_ports() const override ATTR_COLD;
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; }
- DECLARE_READ8_MEMBER(input_r);
- DECLARE_WRITE8_MEMBER(output_w);
+ uint8_t input_r();
+ void output_w(uint8_t data);
DECLARE_INPUT_CHANGED_MEMBER(button_red_w);
DECLARE_INPUT_CHANGED_MEMBER(button_black_w);
protected:
// device-level overrides
- virtual void device_start() override;
- virtual void device_reset() override;
+ virtual void device_start() override ATTR_COLD;
+ virtual void device_reset() override ATTR_COLD;
private:
cpc_expansion_slot_device *m_slot;
diff --git a/src/devices/bus/crvision/rom.cpp b/src/devices/bus/crvision/rom.cpp
index fad177683b0..f4aac5393d8 100644
--- a/src/devices/bus/crvision/rom.cpp
+++ b/src/devices/bus/crvision/rom.cpp
@@ -72,7 +72,7 @@ crvision_rom18k_device::crvision_rom18k_device(const machine_config &mconfig, co
mapper specific handlers
-------------------------------------------------*/
-READ8_MEMBER(crvision_rom_device::read_rom80)
+uint8_t crvision_rom_device::read_rom80(offs_t offset)
{
offset &= 0x1fff;
if (offset < 0x1000)
@@ -82,7 +82,7 @@ READ8_MEMBER(crvision_rom_device::read_rom80)
}
-READ8_MEMBER(crvision_rom6k_device::read_rom80)
+uint8_t crvision_rom6k_device::read_rom80(offs_t offset)
{
offset &= 0x1fff;
if (offset < 0x1000)
@@ -92,48 +92,48 @@ READ8_MEMBER(crvision_rom6k_device::read_rom80)
}
-READ8_MEMBER(crvision_rom8k_device::read_rom80)
+uint8_t crvision_rom8k_device::read_rom80(offs_t offset)
{
return m_rom[offset & 0x1fff];
}
-READ8_MEMBER(crvision_rom10k_device::read_rom80)
+uint8_t crvision_rom10k_device::read_rom80(offs_t offset)
{
return m_rom[offset & 0x1fff];
}
-READ8_MEMBER(crvision_rom10k_device::read_rom40)
+uint8_t crvision_rom10k_device::read_rom40(offs_t offset)
{
return m_rom[0x2000 + (offset & 0x7ff)];
}
-READ8_MEMBER(crvision_rom12k_device::read_rom80)
+uint8_t crvision_rom12k_device::read_rom80(offs_t offset)
{
return m_rom[offset & 0x1fff];
}
-READ8_MEMBER(crvision_rom12k_device::read_rom40)
+uint8_t crvision_rom12k_device::read_rom40(offs_t offset)
{
return m_rom[0x2000 + (offset & 0xfff)];
}
-READ8_MEMBER(crvision_rom16k_device::read_rom80)
+uint8_t crvision_rom16k_device::read_rom80(offs_t offset)
{
// lower 8K in 0xa000-0xbfff, higher 8K in 0x8000-0x9fff
return m_rom[offset ^ 0x2000];
}
-READ8_MEMBER(crvision_rom18k_device::read_rom80)
+uint8_t crvision_rom18k_device::read_rom80(offs_t offset)
{
// lower 8K in 0xa000-0xbfff, higher 8K in 0x8000-0x9fff
return m_rom[offset ^ 0x2000];
}
-READ8_MEMBER(crvision_rom18k_device::read_rom40)
+uint8_t crvision_rom18k_device::read_rom40(offs_t offset)
{
return m_rom[0x4000 + (offset & 0x7ff)];
}
diff --git a/src/devices/bus/crvision/rom.h b/src/devices/bus/crvision/rom.h
index cf15b1e4e2a..c73e424a208 100644
--- a/src/devices/bus/crvision/rom.h
+++ b/src/devices/bus/crvision/rom.h
@@ -1,7 +1,7 @@
// license:BSD-3-Clause
// copyright-holders:Fabio Priuli
-#ifndef MAME_BUS_CPC_CRVISION_ROM_H
-#define MAME_BUS_CPC_CRVISION_ROM_H
+#ifndef MAME_BUS_CRVISION_ROM_H
+#define MAME_BUS_CRVISION_ROM_H
#pragma once
@@ -18,7 +18,7 @@ public:
crvision_rom_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
// reading and writing
- virtual DECLARE_READ8_MEMBER(read_rom80) override;
+ virtual uint8_t read_rom80(offs_t offset) override;
protected:
crvision_rom_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock);
@@ -37,7 +37,7 @@ public:
crvision_rom6k_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
// reading and writing
- virtual DECLARE_READ8_MEMBER(read_rom80) override;
+ virtual uint8_t read_rom80(offs_t offset) override;
};
// ======================> crvision_rom8k_device
@@ -49,7 +49,7 @@ public:
crvision_rom8k_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
// reading and writing
- virtual DECLARE_READ8_MEMBER(read_rom80) override;
+ virtual uint8_t read_rom80(offs_t offset) override;
};
// ======================> crvision_rom10k_device
@@ -61,8 +61,8 @@ public:
crvision_rom10k_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
// reading and writing
- virtual DECLARE_READ8_MEMBER(read_rom40) override;
- virtual DECLARE_READ8_MEMBER(read_rom80) override;
+ virtual uint8_t read_rom40(offs_t offset) override;
+ virtual uint8_t read_rom80(offs_t offset) override;
};
// ======================> crvision_rom12k_device
@@ -74,8 +74,8 @@ public:
crvision_rom12k_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
// reading and writing
- virtual DECLARE_READ8_MEMBER(read_rom40) override;
- virtual DECLARE_READ8_MEMBER(read_rom80) override;
+ virtual uint8_t read_rom40(offs_t offset) override;
+ virtual uint8_t read_rom80(offs_t offset) override;
};
// ======================> crvision_rom16k_device
@@ -87,7 +87,7 @@ public:
crvision_rom16k_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
// reading and writing
- virtual DECLARE_READ8_MEMBER(read_rom80) override;
+ virtual uint8_t read_rom80(offs_t offset) override;
};
// ======================> crvision_rom18k_device
@@ -99,8 +99,8 @@ public:
crvision_rom18k_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
// reading and writing
- virtual DECLARE_READ8_MEMBER(read_rom40) override;
- virtual DECLARE_READ8_MEMBER(read_rom80) override;
+ virtual uint8_t read_rom40(offs_t offset) override;
+ virtual uint8_t read_rom80(offs_t offset) override;
};
@@ -113,5 +113,4 @@ DECLARE_DEVICE_TYPE(CRVISION_ROM_12K, crvision_rom12k_device)
DECLARE_DEVICE_TYPE(CRVISION_ROM_16K, crvision_rom16k_device)
DECLARE_DEVICE_TYPE(CRVISION_ROM_18K, crvision_rom18k_device)
-
-#endif // MAME_BUS_CPC_CRVISION_ROM_H
+#endif // MAME_BUS_CRVISION_ROM_H
diff --git a/src/devices/bus/crvision/slot.cpp b/src/devices/bus/crvision/slot.cpp
index a0398840f00..0b28124eb5b 100644
--- a/src/devices/bus/crvision/slot.cpp
+++ b/src/devices/bus/crvision/slot.cpp
@@ -7,7 +7,6 @@
***********************************************************************************************************/
-
#include "emu.h"
#include "slot.h"
@@ -25,10 +24,10 @@ DEFINE_DEVICE_TYPE(CRVISION_CART_SLOT, crvision_cart_slot_device, "crvision_cart
// device_crvision_cart_interface - constructor
//-------------------------------------------------
-device_crvision_cart_interface::device_crvision_cart_interface(const machine_config &mconfig, device_t &device)
- : device_slot_card_interface(mconfig, device),
- m_rom(nullptr),
- m_rom_size(0)
+device_crvision_cart_interface::device_crvision_cart_interface(const machine_config &mconfig, device_t &device) :
+ device_interface(device, "crvisioncart"),
+ m_rom(nullptr),
+ m_rom_size(0)
{
}
@@ -45,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;
}
}
@@ -64,8 +63,8 @@ void device_crvision_cart_interface::rom_alloc(uint32_t size, const char *tag)
//-------------------------------------------------
crvision_cart_slot_device::crvision_cart_slot_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) :
device_t(mconfig, CRVISION_CART_SLOT, tag, owner, clock),
- device_image_interface(mconfig, *this),
- device_slot_interface(mconfig, *this),
+ device_cartrom_image_interface(mconfig, *this),
+ device_single_card_slot_interface<device_crvision_cart_interface>(mconfig, *this),
m_type(CRV_4K), m_cart(nullptr)
{
}
@@ -85,7 +84,7 @@ crvision_cart_slot_device::~crvision_cart_slot_device()
void crvision_cart_slot_device::device_start()
{
- m_cart = dynamic_cast<device_crvision_cart_interface *>(get_card_device());
+ m_cart = get_card_device();
}
@@ -115,7 +114,7 @@ static int crvision_get_pcb_id(const char *slot)
{
for (auto & elem : slot_list)
{
- if (!core_stricmp(elem.slot_option, slot))
+ if (!strcmp(elem.slot_option, slot))
return elem.pcb_id;
}
@@ -138,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_UNSPECIFIED, "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);
@@ -193,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());
}
@@ -210,10 +204,10 @@ std::string crvision_cart_slot_device::get_default_card_software(get_default_car
{
if (hook.image_file())
{
- const char *slot_string;
- uint32_t size = hook.image_file()->size();
- int type = CRV_4K;
+ uint64_t size;
+ hook.image_file()->length(size); // FIXME: check error return
+ int type = CRV_4K;
switch (size)
{
case 0x4800:
@@ -239,7 +233,7 @@ std::string crvision_cart_slot_device::get_default_card_software(get_default_car
break;
}
- slot_string = crvision_get_slot(type);
+ char const *const slot_string = crvision_get_slot(type);
//printf("type: %s\n", slot_string);
@@ -253,18 +247,18 @@ std::string crvision_cart_slot_device::get_default_card_software(get_default_car
read_rom
-------------------------------------------------*/
-READ8_MEMBER(crvision_cart_slot_device::read_rom40)
+uint8_t crvision_cart_slot_device::read_rom40(offs_t offset)
{
if (m_cart)
- return m_cart->read_rom40(space, offset);
+ return m_cart->read_rom40(offset);
else
return 0xff;
}
-READ8_MEMBER(crvision_cart_slot_device::read_rom80)
+uint8_t crvision_cart_slot_device::read_rom80(offs_t offset)
{
if (m_cart)
- return m_cart->read_rom80(space, offset);
+ return m_cart->read_rom80(offset);
else
return 0xff;
}
diff --git a/src/devices/bus/crvision/slot.h b/src/devices/bus/crvision/slot.h
index 0dff9f8636f..8d46aff5940 100644
--- a/src/devices/bus/crvision/slot.h
+++ b/src/devices/bus/crvision/slot.h
@@ -5,15 +5,13 @@
#pragma once
-#include "softlist_dev.h"
+#include "imagedev/cartrom.h"
/***************************************************************************
TYPE DEFINITIONS
***************************************************************************/
-#define CRVSLOT_ROM_REGION_TAG ":cart:rom"
-
/* PCB */
enum
{
@@ -29,17 +27,17 @@ enum
// ======================> device_crvision_cart_interface
-class device_crvision_cart_interface : public device_slot_card_interface
+class device_crvision_cart_interface : public device_interface
{
public:
// construction/destruction
virtual ~device_crvision_cart_interface();
// reading and writing
- virtual DECLARE_READ8_MEMBER(read_rom40) { return 0xff; }
- virtual DECLARE_READ8_MEMBER(read_rom80) { return 0xff; }
+ 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; }
@@ -55,8 +53,8 @@ protected:
// ======================> crvision_cart_slot_device
class crvision_cart_slot_device : public device_t,
- public device_image_interface,
- public device_slot_interface
+ public device_cartrom_image_interface,
+ public device_single_card_slot_interface<device_crvision_cart_interface>
{
public:
// construction/destruction
@@ -72,36 +70,29 @@ public:
crvision_cart_slot_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
virtual ~crvision_cart_slot_device();
- // device-level overrides
- virtual void device_start() override;
-
- // image-level overrides
- virtual image_init_result call_load() override;
- virtual void call_unload() override {}
- virtual const software_list_loader &get_software_list_loader() const override { return rom_software_list_loader::instance(); }
-
- int get_type() { return m_type; }
+ // device_image_interface implementation
+ virtual std::pair<std::error_condition, std::string> call_load() override;
+ virtual void call_unload() override { }
- virtual iodevice_t image_type() const override { return IO_CARTSLOT; }
- virtual bool is_readable() const override { return 1; }
- virtual bool is_writeable() const override { return 0; }
- virtual bool is_creatable() const override { return 0; }
- virtual bool must_be_loaded() const override { return 0; }
- virtual bool is_reset_on_load() const override { return 1; }
- virtual const char *image_interface() const override { return "crvision_cart"; }
- virtual const char *file_extensions() const override { return "bin,rom"; }
+ 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; }
+
// reading and writing
- virtual DECLARE_READ8_MEMBER(read_rom40);
- virtual DECLARE_READ8_MEMBER(read_rom80);
+ uint8_t read_rom40(offs_t offset);
+ uint8_t read_rom80(offs_t offset);
protected:
+ // device_t implementation
+ virtual void device_start() override ATTR_COLD;
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 7ad4ae3a2bb..a2a51092f81 100644
--- a/src/devices/bus/dmv/dmvbus.cpp
+++ b/src/devices/bus/dmv/dmvbus.cpp
@@ -1,5 +1,6 @@
// license:BSD-3-Clause
// copyright-holders:Sandro Ronco
+// thanks-to:rfka01
/*********************************************************************
NCR Decision mate slot bus and module emulation
@@ -172,8 +173,9 @@ DEFINE_DEVICE_TYPE(DMVCART_SLOT, dmvcart_slot_device, "dmvcart_slot", "Decision
// device_dmvslot_interface - constructor
//-------------------------------------------------
-device_dmvslot_interface::device_dmvslot_interface(const machine_config &mconfig, device_t &device)
- : device_slot_card_interface(mconfig, device)
+device_dmvslot_interface::device_dmvslot_interface(const machine_config &mconfig, device_t &device) :
+ device_interface(device, "dmvbus"),
+ m_bus(dynamic_cast<dmvcart_slot_device *>(device.owner()))
{
}
@@ -196,8 +198,8 @@ 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_slot_interface(mconfig, *this),
- m_prog_read_cb(*this),
+ device_single_card_slot_interface<device_dmvslot_interface>(mconfig, *this),
+ m_prog_read_cb(*this, 0),
m_prog_write_cb(*this),
m_out_int_cb(*this),
m_out_irq_cb(*this),
@@ -223,14 +225,7 @@ dmvcart_slot_device::~dmvcart_slot_device()
void dmvcart_slot_device::device_start()
{
- m_cart = dynamic_cast<device_dmvslot_interface *>(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();
+ m_cart = get_card_device();
}
/*-------------------------------------------------
diff --git a/src/devices/bus/dmv/dmvbus.h b/src/devices/bus/dmv/dmvbus.h
index 22c81767151..593925f4e12 100644
--- a/src/devices/bus/dmv/dmvbus.h
+++ b/src/devices/bus/dmv/dmvbus.h
@@ -1,5 +1,6 @@
// license:BSD-3-Clause
// copyright-holders:Sandro Ronco
+// thanks-to:rfka01
/*********************************************************************
Decision Mate V expansion slot
@@ -15,47 +16,13 @@
TYPE DEFINITIONS
***************************************************************************/
-// ======================> device_dmvslot_interface
-
-class device_dmvslot_interface : public device_slot_card_interface
-{
-public:
- // construction/destruction
- virtual ~device_dmvslot_interface();
-
- virtual bool read(offs_t offset, uint8_t &data) { return false; }
- virtual bool write(offs_t offset, uint8_t data) { return false; }
- virtual void io_read(int ifsel, offs_t offset, uint8_t &data) { }
- virtual void io_write(int ifsel, offs_t offset, uint8_t data) { }
-
- // slot 1
- virtual void ram_read(uint8_t cas, offs_t offset, uint8_t &data) { }
- virtual void ram_write(uint8_t cas, offs_t offset, uint8_t data) { }
-
- // slot 7 and 7A
- virtual bool av16bit() { return false; }
- virtual void hold_w(int state) { }
- virtual void switch16_w(int state) { }
- virtual void timint_w(int state) { }
- virtual void keyint_w(int state) { }
- virtual void busint_w(int state) { }
- virtual void flexint_w(int state) { }
- virtual void irq2_w(int state) { }
- virtual void irq2a_w(int state) { }
- virtual void irq3_w(int state) { }
- virtual void irq4_w(int state) { }
- virtual void irq5_w(int state) { }
- virtual void irq6_w(int state) { }
-
-protected:
- device_dmvslot_interface(const machine_config &mconfig, device_t &device);
-};
+class device_dmvslot_interface;
// ======================> dmvcart_slot_device
class dmvcart_slot_device : public device_t,
- public device_slot_interface
+ public device_single_card_slot_interface<device_dmvslot_interface>
{
public:
// construction/destruction
@@ -79,29 +46,30 @@ public:
template <typename T> void set_memspace(T &&tag, int spacenum) { m_memspace.set_tag(std::forward<T>(tag), spacenum); }
template <typename T> void set_iospace(T &&tag, int spacenum) { m_iospace.set_tag(std::forward<T>(tag), spacenum); }
- // device-level overrides
- virtual void device_start() override;
-
// reading and writing
- virtual bool read(offs_t offset, uint8_t &data);
- virtual bool write(offs_t offset, uint8_t data);
- virtual void ram_read(uint8_t cas, offs_t offset, uint8_t &data);
- virtual void ram_write(uint8_t cas, offs_t offset, uint8_t data);
- virtual void io_read(int ifsel, offs_t offset, uint8_t &data);
- virtual void io_write(int ifsel, offs_t offset, uint8_t data);
- virtual void hold_w(int state);
- virtual void switch16_w(int state);
- virtual void timint_w(int state);
- virtual void keyint_w(int state);
- virtual void busint_w(int state);
- virtual void flexint_w(int state);
- virtual void irq2_w(int state);
- virtual void irq2a_w(int state);
- virtual void irq3_w(int state);
- virtual void irq4_w(int state);
- virtual void irq5_w(int state);
- virtual void irq6_w(int state);
- virtual bool av16bit();
+ bool read(offs_t offset, uint8_t &data);
+ bool write(offs_t offset, uint8_t data);
+ void ram_read(uint8_t cas, offs_t offset, uint8_t &data);
+ void ram_write(uint8_t cas, offs_t offset, uint8_t data);
+ void io_read(int ifsel, offs_t offset, uint8_t &data);
+ void io_write(int ifsel, offs_t offset, uint8_t data);
+ void hold_w(int state);
+ void switch16_w(int state);
+ void timint_w(int state);
+ void keyint_w(int state);
+ void busint_w(int state);
+ void flexint_w(int state);
+ void irq2_w(int state);
+ void irq2a_w(int state);
+ void irq3_w(int state);
+ void irq4_w(int state);
+ void irq5_w(int state);
+ void irq6_w(int state);
+ bool av16bit();
+
+protected:
+ // device-level overrides
+ virtual void device_start() override ATTR_COLD;
// internal state
devcb_read8 m_prog_read_cb;
@@ -114,6 +82,58 @@ public:
required_address_space m_iospace;
device_dmvslot_interface* m_cart;
+
+ friend class device_dmvslot_interface;
+};
+
+
+// ======================> device_dmvslot_interface
+
+class device_dmvslot_interface : public device_interface
+{
+public:
+ // construction/destruction
+ virtual ~device_dmvslot_interface();
+
+ virtual bool read(offs_t offset, uint8_t &data) { return false; }
+ virtual bool write(offs_t offset, uint8_t data) { return false; }
+ virtual void io_read(int ifsel, offs_t offset, uint8_t &data) { }
+ virtual void io_write(int ifsel, offs_t offset, uint8_t data) { }
+
+ // slot 1
+ virtual void ram_read(uint8_t cas, offs_t offset, uint8_t &data) { }
+ virtual void ram_write(uint8_t cas, offs_t offset, uint8_t data) { }
+
+ // slot 7 and 7A
+ virtual bool av16bit() { return false; }
+ virtual void hold_w(int state) { }
+ virtual void switch16_w(int state) { }
+ virtual void timint_w(int state) { }
+ virtual void keyint_w(int state) { }
+ virtual void busint_w(int state) { }
+ virtual void flexint_w(int state) { }
+ virtual void irq2_w(int state) { }
+ virtual void irq2a_w(int state) { }
+ virtual void irq3_w(int state) { }
+ virtual void irq4_w(int state) { }
+ virtual void irq5_w(int state) { }
+ virtual void irq6_w(int state) { }
+
+protected:
+ device_dmvslot_interface(const machine_config &mconfig, device_t &device);
+
+ address_space &memspace() { return *m_bus->m_memspace; }
+ address_space &iospace() { return *m_bus->m_iospace; }
+
+ template <typename... T> uint8_t prog_read(T &&... args) { return m_bus->m_prog_read_cb(std::forward<T>(args)...); }
+ template <typename... T> void prog_write(T &&... args) { m_bus->m_prog_write_cb(std::forward<T>(args)...); }
+
+ void out_int(int state) { m_bus->m_out_int_cb(state); }
+ void out_irq(int state) { m_bus->m_out_irq_cb(state); }
+ void out_thold(int state) { m_bus->m_out_thold_cb(state); }
+
+private:
+ dmvcart_slot_device *m_bus;
};
diff --git a/src/devices/bus/dmv/k012.cpp b/src/devices/bus/dmv/k012.cpp
new file mode 100644
index 00000000000..21f5f4e5e8d
--- /dev/null
+++ b/src/devices/bus/dmv/k012.cpp
@@ -0,0 +1,116 @@
+// license:BSD-3-Clause
+// copyright-holders:Sandro Ronco
+// thanks-to:rfka01
+/***************************************************************************
+
+ K012 Internal HD Interface
+ C3282 External HD Interface
+
+***************************************************************************/
+
+#include "emu.h"
+#include "k012.h"
+
+/***************************************************************************
+ IMPLEMENTATION
+***************************************************************************/
+
+static INPUT_PORTS_START( dmv_k012 )
+ PORT_START("JUMPERS")
+ PORT_DIPNAME( 0x1f, 0x10, "IFSEL" ) PORT_DIPLOCATION("J:!1,J:!2,J:!3,J:!4,J:!5")
+ PORT_DIPSETTING( 0x01, "0A" )
+ PORT_DIPSETTING( 0x02, "1A" )
+ PORT_DIPSETTING( 0x04, "2A" )
+ PORT_DIPSETTING( 0x08, "3A" )
+ PORT_DIPSETTING( 0x10, "4A" ) // default
+INPUT_PORTS_END
+
+//**************************************************************************
+// GLOBAL VARIABLES
+//**************************************************************************
+
+DEFINE_DEVICE_TYPE(DMV_K012, dmv_k012_device, "dmv_k012", "K012 Internal HD Interface")
+DEFINE_DEVICE_TYPE(DMV_C3282, dmv_c3282_device, "dmv_c3282", "C3282 External HD Interface")
+
+//**************************************************************************
+// LIVE DEVICE
+//**************************************************************************
+
+//-------------------------------------------------
+// dmv_k012_device - constructor
+//-------------------------------------------------
+
+dmv_k012_device::dmv_k012_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
+ : dmv_k012_device(mconfig, DMV_K012, tag, owner, clock)
+{
+}
+
+dmv_k012_device::dmv_k012_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_dmvslot_interface( mconfig, *this )
+ , m_hdc(*this, "hdc")
+ , m_jumpers(*this, "JUMPERS")
+{
+}
+
+//-------------------------------------------------
+// dmv_c3282_device - constructor
+//-------------------------------------------------
+
+dmv_c3282_device::dmv_c3282_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
+ : dmv_k012_device(mconfig, DMV_C3282, tag, owner, clock)
+{
+}
+
+//-------------------------------------------------
+// device_start - device-specific startup
+//-------------------------------------------------
+
+void dmv_k012_device::device_start()
+{
+}
+
+//-------------------------------------------------
+// device_reset - device-specific reset
+//-------------------------------------------------
+
+void dmv_k012_device::device_reset()
+{
+}
+
+//-------------------------------------------------
+// input_ports - device-specific input ports
+//-------------------------------------------------
+
+ioport_constructor dmv_k012_device::device_input_ports() const
+{
+ return INPUT_PORTS_NAME( dmv_k012 );
+}
+
+//-------------------------------------------------
+// device_add_mconfig - add device configuration
+//-------------------------------------------------
+
+void dmv_k012_device::device_add_mconfig(machine_config &config)
+{
+ WD1000(config, m_hdc, 20_MHz_XTAL / 4); // WD1010
+ m_hdc->intrq_wr_callback().set(FUNC(dmv_k012_device::out_int));
+
+ // default drive is 10MB (306,4,17)
+ HARDDISK(config, "hdc:0", 0);
+ HARDDISK(config, "hdc:1", 0);
+ HARDDISK(config, "hdc:2", 0);
+ HARDDISK(config, "hdc:3", 0);
+}
+
+void dmv_k012_device::io_read(int ifsel, offs_t offset, uint8_t &data)
+{
+ if ((1 << ifsel) == m_jumpers->read() && !(offset & 0x08))
+ data = m_hdc->read(offset);
+}
+
+void dmv_k012_device::io_write(int ifsel, offs_t offset, uint8_t data)
+{
+ if ((1 << ifsel) == m_jumpers->read() && !(offset & 0x08))
+ m_hdc->write(offset, data);
+}
diff --git a/src/devices/bus/dmv/k012.h b/src/devices/bus/dmv/k012.h
new file mode 100644
index 00000000000..34126ad5b66
--- /dev/null
+++ b/src/devices/bus/dmv/k012.h
@@ -0,0 +1,64 @@
+// license:BSD-3-Clause
+// copyright-holders:Sandro Ronco
+// thanks-to:rfka01
+#ifndef MAME_BUS_DMV_K012_H
+#define MAME_BUS_DMV_K012_H
+
+#pragma once
+
+#include "dmvbus.h"
+#include "machine/wd1000.h"
+
+//**************************************************************************
+// TYPE DEFINITIONS
+//**************************************************************************
+
+// ======================> dmv_k012_device
+
+class dmv_k012_device :
+ public device_t,
+ public device_dmvslot_interface
+{
+public:
+ // construction/destruction
+ dmv_k012_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
+
+protected:
+ dmv_k012_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 ATTR_COLD;
+ virtual void device_reset() override ATTR_COLD;
+
+ // optional information overrides
+ virtual void device_add_mconfig(machine_config &config) override ATTR_COLD;
+ virtual ioport_constructor device_input_ports() const override ATTR_COLD;
+
+ // dmvcart_interface overrides
+ 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;
+
+ void hdc_intrq_w(int state);
+
+private:
+ required_device<wd1000_device> m_hdc;
+ required_ioport m_jumpers;
+};
+
+
+// ======================> dmv_c3282_device
+
+class dmv_c3282_device :
+ public dmv_k012_device
+{
+public:
+ // construction/destruction
+ dmv_c3282_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
+};
+
+
+// device type definition
+DECLARE_DEVICE_TYPE(DMV_K012, dmv_k012_device)
+DECLARE_DEVICE_TYPE(DMV_C3282, dmv_c3282_device)
+
+#endif // MAME_BUS_DMV_K012_H
diff --git a/src/devices/bus/dmv/k210.cpp b/src/devices/bus/dmv/k210.cpp
index d73f2dfb9a9..0f2371fedea 100644
--- a/src/devices/bus/dmv/k210.cpp
+++ b/src/devices/bus/dmv/k210.cpp
@@ -1,5 +1,6 @@
// license:BSD-3-Clause
// copyright-holders:Sandro Ronco
+// thanks-to:rfka01
/***************************************************************************
K210 Centronics module
@@ -35,7 +36,7 @@ dmv_k210_device::dmv_k210_device(const machine_config &mconfig, const char *tag,
, m_centronics(*this, "centronics")
, m_cent_data_in(*this, "cent_data_in")
, m_cent_data_out(*this, "cent_data_out")
- , m_bus(nullptr), m_clk1_timer(nullptr), m_portb(0), m_portc(0)
+ , m_clk1_timer(nullptr), m_portb(0), m_portc(0)
{
}
@@ -45,8 +46,11 @@ dmv_k210_device::dmv_k210_device(const machine_config &mconfig, const char *tag,
void dmv_k210_device::device_start()
{
- m_clk1_timer = timer_alloc(0, nullptr);
- m_bus = static_cast<dmvcart_slot_device*>(owner());
+ m_clk1_timer = timer_alloc(FUNC(dmv_k210_device::strobe_tick), this);
+
+ // register for state saving
+ save_item(NAME(m_portb));
+ save_item(NAME(m_portc));
}
//-------------------------------------------------
@@ -61,10 +65,10 @@ void dmv_k210_device::device_reset()
}
//-------------------------------------------------
-// device_timer - handler timer events
+// strobe_tick -
//-------------------------------------------------
-void dmv_k210_device::device_timer(emu_timer &timer, device_timer_id tid, int param, void *ptr)
+TIMER_CALLBACK_MEMBER(dmv_k210_device::strobe_tick)
{
m_centronics->write_strobe(CLEAR_LINE);
}
@@ -111,27 +115,27 @@ void dmv_k210_device::io_write(int ifsel, offs_t offset, uint8_t data)
m_ppi->write(offset & 0x03, data);
}
-READ8_MEMBER( dmv_k210_device::porta_r )
+uint8_t dmv_k210_device::porta_r()
{
return m_cent_data_in->read();
}
-READ8_MEMBER( dmv_k210_device::portb_r )
+uint8_t dmv_k210_device::portb_r()
{
return m_portb;
}
-READ8_MEMBER( dmv_k210_device::portc_r )
+uint8_t dmv_k210_device::portc_r()
{
return m_portc;
}
-WRITE8_MEMBER( dmv_k210_device::porta_w )
+void dmv_k210_device::porta_w(uint8_t data)
{
m_cent_data_out->write(data);
}
-WRITE8_MEMBER( dmv_k210_device::portb_w )
+void dmv_k210_device::portb_w(uint8_t data)
{
m_centronics->write_ack(BIT(data, 2));
m_centronics->write_select(BIT(data, 4));
@@ -140,7 +144,7 @@ WRITE8_MEMBER( dmv_k210_device::portb_w )
m_centronics->write_fault(BIT(data, 7));
}
-WRITE8_MEMBER( dmv_k210_device::portc_w )
+void dmv_k210_device::portc_w(uint8_t data)
{
if (!(data & 0x80))
{
@@ -151,14 +155,14 @@ WRITE8_MEMBER( dmv_k210_device::portc_w )
m_centronics->write_init(!BIT(data, 1));
m_centronics->write_autofd(!BIT(data, 2));
m_centronics->write_ack(BIT(data, 6));
- m_bus->m_out_irq_cb(BIT(data, 3));
+ 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; }
+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; }
-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_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 501178f6fcf..737b2fdb65a 100644
--- a/src/devices/bus/dmv/k210.h
+++ b/src/devices/bus/dmv/k210.h
@@ -1,5 +1,6 @@
// license:BSD-3-Clause
// copyright-holders:Sandro Ronco
+// thanks-to:rfka01
#ifndef MAME_BUS_DMV_K210_H
#define MAME_BUS_DMV_K210_H
@@ -25,38 +26,38 @@ public:
protected:
// device-level overrides
- virtual void device_start() override;
- virtual void device_reset() override;
- void device_timer(emu_timer &timer, device_timer_id tid, int param, void *ptr) override;
+ virtual void device_start() override ATTR_COLD;
+ virtual void device_reset() override ATTR_COLD;
// optional information overrides
- virtual void device_add_mconfig(machine_config &config) override;
+ virtual void device_add_mconfig(machine_config &config) override ATTR_COLD;
// dmvcart_interface overrides
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;
private:
- DECLARE_READ8_MEMBER(porta_r);
- DECLARE_READ8_MEMBER(portb_r);
- DECLARE_READ8_MEMBER(portc_r);
- DECLARE_WRITE8_MEMBER(porta_w);
- DECLARE_WRITE8_MEMBER(portb_w);
- DECLARE_WRITE8_MEMBER(portc_w);
-
- 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);
+ uint8_t porta_r();
+ uint8_t portb_r();
+ uint8_t portc_r();
+ void porta_w(uint8_t data);
+ void portb_w(uint8_t data);
+ void portc_w(uint8_t data);
+
+ 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);
required_device<i8255_device> m_ppi;
required_device<centronics_device> m_centronics;
required_device<input_buffer_device> m_cent_data_in;
required_device<output_latch_device> m_cent_data_out;
- dmvcart_slot_device * m_bus;
emu_timer * m_clk1_timer;
uint8_t m_portb;
diff --git a/src/devices/bus/dmv/k220.cpp b/src/devices/bus/dmv/k220.cpp
index 4ad0667f689..89f579ccf27 100644
--- a/src/devices/bus/dmv/k220.cpp
+++ b/src/devices/bus/dmv/k220.cpp
@@ -1,5 +1,6 @@
// license:BSD-3-Clause
// copyright-holders:Sandro Ronco
+// thanks-to:rfka01
/***************************************************************************
NCR DMV K220 Diagnostic module
@@ -122,7 +123,6 @@ DEFINE_DEVICE_TYPE(DMV_K220, dmv_k220_device, "dmv_k220", "K220 diagnostic")
dmv_k220_device::dmv_k220_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
: device_t(mconfig, DMV_K220, tag, owner, clock)
, device_dmvslot_interface(mconfig, *this)
- , m_bus(*this, DEVICE_SELF_OWNER)
, m_pit(*this, "pit8253")
, m_ppi(*this, "ppi8255")
, m_ram(*this, "ram")
@@ -138,11 +138,15 @@ dmv_k220_device::dmv_k220_device(const machine_config &mconfig, const char *tag,
void dmv_k220_device::device_start()
{
- address_space &space = *m_bus->m_iospace;
- space.install_readwrite_handler(0x08, 0x0b, read8sm_delegate(FUNC(pit8253_device::read), &(*m_pit)), write8sm_delegate(FUNC(pit8253_device::write), &(*m_pit)), 0);
- space.install_readwrite_handler(0x0c, 0x0f, read8sm_delegate(FUNC(i8255_device::read), &(*m_ppi)), write8sm_delegate(FUNC(i8255_device::write), &(*m_ppi)), 0);
+ address_space &space = iospace();
+ space.install_readwrite_handler(0x08, 0x0b, read8sm_delegate(*m_pit, FUNC(pit8253_device::read)), write8sm_delegate(*m_pit, FUNC(pit8253_device::write)), 0);
+ space.install_readwrite_handler(0x0c, 0x0f, read8sm_delegate(*m_ppi, FUNC(i8255_device::read)), write8sm_delegate(*m_ppi, FUNC(i8255_device::write)), 0);
m_digits.resolve();
+
+ // register for state saving
+ save_item(NAME(m_portc));
+ save_pointer(NAME(m_ram->base()), m_ram->bytes());
}
//-------------------------------------------------
@@ -152,6 +156,8 @@ void dmv_k220_device::device_start()
void dmv_k220_device::device_reset()
{
// active the correct layout
+ // FIXME: this is a very bad idea - you have no idea what view the user has loaded externally or from other devices,
+ // and it won't allow selected view to be saved/restored correctly
machine().render().first_target()->set_view(1);
}
@@ -231,7 +237,7 @@ bool dmv_k220_device::write(offs_t offset, uint8_t data)
return false;
}
-WRITE8_MEMBER( dmv_k220_device::porta_w )
+void dmv_k220_device::porta_w(uint8_t data)
{
// 74LS247 BCD-to-Seven-Segment Decoder
static uint8_t bcd2hex[] = { 0x3f, 0x06, 0x5b, 0x4f, 0x66, 0x6d, 0x7d, 0x07, 0x7f, 0x6f, 0x58, 0x4c, 0x62, 0x69, 0x78, 0x00 };
@@ -241,7 +247,7 @@ WRITE8_MEMBER( dmv_k220_device::porta_w )
}
-WRITE8_MEMBER( dmv_k220_device::portc_w )
+void dmv_k220_device::portc_w(uint8_t data)
{
/*
xxxx ---- not connected
@@ -258,18 +264,18 @@ WRITE8_MEMBER( dmv_k220_device::portc_w )
}
-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 60edad3b5f3..6fd740b7c0b 100644
--- a/src/devices/bus/dmv/k220.h
+++ b/src/devices/bus/dmv/k220.h
@@ -1,5 +1,6 @@
// license:BSD-3-Clause
// copyright-holders:Sandro Ronco
+// thanks-to:rfka01
#ifndef MAME_BUS_DMV_K220_H
#define MAME_BUS_DMV_K220_H
@@ -25,26 +26,25 @@ public:
protected:
// device-level overrides
- virtual void device_start() override;
- virtual void device_reset() override;
+ virtual void device_start() override ATTR_COLD;
+ virtual void device_reset() override ATTR_COLD;
// optional information 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 const tiny_rom_entry *device_rom_region() const override ATTR_COLD;
+ virtual void device_add_mconfig(machine_config &config) override ATTR_COLD;
+ virtual ioport_constructor device_input_ports() const override ATTR_COLD;
// dmvcart_interface overrides
virtual bool read(offs_t offset, uint8_t &data) override;
virtual bool write(offs_t offset, uint8_t data) override;
private:
- DECLARE_WRITE8_MEMBER(porta_w);
- DECLARE_WRITE8_MEMBER(portc_w);
- DECLARE_WRITE_LINE_MEMBER(write_out0);
- DECLARE_WRITE_LINE_MEMBER(write_out1);
- DECLARE_WRITE_LINE_MEMBER(write_out2);
+ void porta_w(uint8_t data);
+ void portc_w(uint8_t data);
+ void write_out0(int state);
+ void write_out1(int state);
+ void write_out2(int state);
- required_device<dmvcart_slot_device> m_bus;
required_device<pit8253_device> m_pit;
required_device<i8255_device> m_ppi;
required_memory_region m_ram;
diff --git a/src/devices/bus/dmv/k230.cpp b/src/devices/bus/dmv/k230.cpp
index b5454fa78db..82d6e24f7d2 100644
--- a/src/devices/bus/dmv/k230.cpp
+++ b/src/devices/bus/dmv/k230.cpp
@@ -1,5 +1,6 @@
// license:BSD-3-Clause
// copyright-holders:Sandro Ronco
+// thanks-to:rfka01
/***************************************************************************
K230 Internal 8088 module without interrupt controller
@@ -99,7 +100,6 @@ dmv_k230_device::dmv_k230_device(const machine_config &mconfig, device_type type
, device_dmvslot_interface(mconfig, *this)
, m_maincpu(*this, "maincpu")
, m_rom(*this, "rom")
- , m_bus(*this, DEVICE_SELF_OWNER)
, m_switch16(0)
, m_hold(0)
{
@@ -139,12 +139,18 @@ dmv_k235_device::dmv_k235_device(const machine_config &mconfig, const char *tag,
void dmv_k230_device::device_start()
{
+ // register for state saving
+ save_item(NAME(m_switch16));
+ save_item(NAME(m_hold));
}
void dmv_k234_device::device_start()
{
dmv_k230_device::device_start();
- m_bus->m_iospace->install_readwrite_handler(0xd8, 0xdf, read8_delegate(FUNC(dmv_k234_device::snr_r), this), write8_delegate(FUNC(dmv_k234_device::snr_w), this), 0);
+ iospace().install_readwrite_handler(0xd8, 0xdf, read8smo_delegate(*this, FUNC(dmv_k234_device::snr_r)), write8smo_delegate(*this, FUNC(dmv_k234_device::snr_w)), 0);
+
+ // register for state saving
+ save_item(NAME(m_snr));
}
//-------------------------------------------------
@@ -241,29 +247,29 @@ void dmv_k230_device::switch16_w(int state)
m_maincpu->set_input_line(INPUT_LINE_HALT, (m_hold || !m_switch16) ? ASSERT_LINE : CLEAR_LINE);
}
-READ8_MEMBER(dmv_k230_device::rom_r)
+uint8_t dmv_k230_device::rom_r(offs_t offset)
{
return m_rom->base()[offset & 0x0fff];
}
-READ8_MEMBER( dmv_k230_device::io_r )
+uint8_t dmv_k230_device::io_r(offs_t offset)
{
- return m_bus->m_iospace->read_byte(offset);
+ return iospace().read_byte(offset);
}
-WRITE8_MEMBER( dmv_k230_device::io_w )
+void dmv_k230_device::io_w(offs_t offset, uint8_t data)
{
- m_bus->m_iospace->write_byte(offset, data);
+ iospace().write_byte(offset, data);
}
-READ8_MEMBER( dmv_k230_device::program_r )
+uint8_t dmv_k230_device::program_r(offs_t offset)
{
- return m_bus->m_prog_read_cb(space, offset);
+ return prog_read(offset);
}
-WRITE8_MEMBER( dmv_k230_device::program_w )
+void dmv_k230_device::program_w(offs_t offset, uint8_t data)
{
- m_bus->m_prog_write_cb(space, offset, data);
+ prog_write(offset, data);
}
void dmv_k234_device::hold_w(int state)
@@ -278,25 +284,25 @@ void dmv_k234_device::switch16_w(int state)
{
m_snr = CLEAR_LINE;
m_maincpu->set_input_line(INPUT_LINE_HALT, ASSERT_LINE);
- m_bus->m_out_thold_cb(CLEAR_LINE);
+ out_thold(CLEAR_LINE);
m_switch16 = state;
}
}
-READ8_MEMBER( dmv_k234_device::snr_r )
+uint8_t dmv_k234_device::snr_r()
{
m_snr = ASSERT_LINE;
m_maincpu->set_input_line(INPUT_LINE_HALT, CLEAR_LINE);
m_maincpu->reset();
- m_bus->m_out_thold_cb(ASSERT_LINE);
+ out_thold(ASSERT_LINE);
return 0xff;
}
-WRITE8_MEMBER( dmv_k234_device::snr_w )
+void dmv_k234_device::snr_w(uint8_t data)
{
m_snr = ASSERT_LINE;
m_maincpu->set_input_line(INPUT_LINE_HALT, CLEAR_LINE);
m_maincpu->reset();
- m_bus->m_out_thold_cb(ASSERT_LINE);
+ out_thold(ASSERT_LINE);
}
diff --git a/src/devices/bus/dmv/k230.h b/src/devices/bus/dmv/k230.h
index e8e70fd878a..174fc29f3c8 100644
--- a/src/devices/bus/dmv/k230.h
+++ b/src/devices/bus/dmv/k230.h
@@ -1,5 +1,6 @@
// license:BSD-3-Clause
// copyright-holders:Sandro Ronco
+// thanks-to:rfka01
#ifndef MAME_BUS_DMV_K230_H
#define MAME_BUS_DMV_K230_H
@@ -9,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"
@@ -34,34 +35,33 @@ protected:
dmv_k230_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_start() override ATTR_COLD;
+ virtual void device_reset() override ATTR_COLD;
// optional information overrides
- virtual const tiny_rom_entry *device_rom_region() const override;
- virtual void device_add_mconfig(machine_config &config) override;
+ virtual const tiny_rom_entry *device_rom_region() const override ATTR_COLD;
+ virtual void device_add_mconfig(machine_config &config) override ATTR_COLD;
// dmvcart_interface overrides
virtual void hold_w(int state) override;
virtual void switch16_w(int state) override;
virtual bool av16bit() override;
- void k230_io(address_map &map);
- void k230_mem(address_map &map);
+ void k230_io(address_map &map) ATTR_COLD;
+ void k230_mem(address_map &map) ATTR_COLD;
required_device<cpu_device> m_maincpu;
optional_memory_region m_rom;
- required_device<dmvcart_slot_device> m_bus;
int m_switch16;
int m_hold;
- DECLARE_READ8_MEMBER(io_r);
- DECLARE_READ8_MEMBER(program_r);
- DECLARE_WRITE8_MEMBER(io_w);
- DECLARE_WRITE8_MEMBER(program_w);
+ uint8_t io_r(offs_t offset);
+ uint8_t program_r(offs_t offset);
+ void io_w(offs_t offset, uint8_t data);
+ void program_w(offs_t offset, uint8_t data);
private:
- DECLARE_READ8_MEMBER(rom_r);
+ uint8_t rom_r(offs_t offset);
};
@@ -75,7 +75,7 @@ public:
dmv_k231_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 const tiny_rom_entry *device_rom_region() const override ATTR_COLD;
};
@@ -90,12 +90,12 @@ public:
protected:
// optional information overrides
- virtual const tiny_rom_entry *device_rom_region() const override;
- virtual void device_add_mconfig(machine_config &config) override;
+ virtual const tiny_rom_entry *device_rom_region() const override ATTR_COLD;
+ virtual void device_add_mconfig(machine_config &config) override ATTR_COLD;
// device-level overrides
- virtual void device_start() override;
- virtual void device_reset() override;
+ virtual void device_start() override ATTR_COLD;
+ virtual void device_reset() override ATTR_COLD;
// dmvcart_interface overrides
virtual void hold_w(int state) override;
@@ -104,10 +104,10 @@ protected:
private:
int m_snr;
- DECLARE_READ8_MEMBER(snr_r);
- DECLARE_WRITE8_MEMBER(snr_w);
+ uint8_t snr_r();
+ void snr_w(uint8_t data);
- void k234_mem(address_map &map);
+ void k234_mem(address_map &map) ATTR_COLD;
};
@@ -122,9 +122,9 @@ public:
protected:
// optional information 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 const tiny_rom_entry *device_rom_region() const override ATTR_COLD;
+ virtual void device_add_mconfig(machine_config &config) override ATTR_COLD;
+ virtual ioport_constructor device_input_ports() const override ATTR_COLD;
void timint_w(int state) override { m_pic->ir0_w(state); }
void keyint_w(int state) override { m_pic->ir1_w(state); }
@@ -141,7 +141,7 @@ private:
required_device<pic8259_device> m_pic;
required_ioport m_dsw;
- void k235_io(address_map &map);
+ void k235_io(address_map &map) ATTR_COLD;
};
// device type definition
diff --git a/src/devices/bus/dmv/k233.cpp b/src/devices/bus/dmv/k233.cpp
index 2c8b13cff00..5873aec8d5c 100644
--- a/src/devices/bus/dmv/k233.cpp
+++ b/src/devices/bus/dmv/k233.cpp
@@ -1,5 +1,6 @@
// license:BSD-3-Clause
// copyright-holders:Sandro Ronco
+// thanks-to:rfka01
/***************************************************************************
K233 16K Shared RAM
@@ -43,6 +44,10 @@ dmv_k233_device::dmv_k233_device(const machine_config &mconfig, const char *tag,
void dmv_k233_device::device_start()
{
m_ram = machine().memory().region_alloc( "sharedram", 0x4000, 1, ENDIANNESS_LITTLE )->base();
+
+ // register for state saving
+ save_item(NAME(m_enabled));
+ save_pointer(NAME(m_ram), 0x4000);
}
//-------------------------------------------------
diff --git a/src/devices/bus/dmv/k233.h b/src/devices/bus/dmv/k233.h
index e73ae71a9df..9cb37de6daa 100644
--- a/src/devices/bus/dmv/k233.h
+++ b/src/devices/bus/dmv/k233.h
@@ -1,5 +1,6 @@
// license:BSD-3-Clause
// copyright-holders:Sandro Ronco
+// thanks-to:rfka01
#ifndef MAME_BUS_DMV_K233_H
#define MAME_BUS_DMV_K233_H
@@ -23,8 +24,8 @@ public:
protected:
// device-level overrides
- virtual void device_start() override;
- virtual void device_reset() override;
+ virtual void device_start() override ATTR_COLD;
+ virtual void device_reset() override ATTR_COLD;
// dmvcart_interface overrides
virtual void io_write(int ifsel, offs_t offset, uint8_t data) override;
diff --git a/src/devices/bus/dmv/k801.cpp b/src/devices/bus/dmv/k801.cpp
index 7c4892f4fb0..02bb59aa662 100644
--- a/src/devices/bus/dmv/k801.cpp
+++ b/src/devices/bus/dmv/k801.cpp
@@ -1,5 +1,6 @@
// license:BSD-3-Clause
// copyright-holders:Sandro Ronco
+// thanks-to:rfka01
/***************************************************************************
K801 RS-232 Switchable Interface
@@ -83,9 +84,9 @@ dmv_k801_device::dmv_k801_device(const machine_config &mconfig, const char *tag,
dmv_k801_device::dmv_k801_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_dmvslot_interface( mconfig, *this ),
- m_epci(*this, "epci"),
+ m_pci(*this, "pci"),
m_rs232(*this, "rs232"),
- m_dsw(*this, "DSW"), m_bus(nullptr)
+ m_dsw(*this, "DSW")
{
}
@@ -128,7 +129,6 @@ dmv_k213_device::dmv_k213_device(const machine_config &mconfig, const char *tag,
void dmv_k801_device::device_start()
{
- m_bus = static_cast<dmvcart_slot_device*>(owner());
}
//-------------------------------------------------
@@ -143,38 +143,43 @@ void dmv_k801_device::device_reset()
// device_add_mconfig - add device configuration
//-------------------------------------------------
-void dmv_k801_device::device_add_mconfig(machine_config &config)
+void dmv_k801_device::pci_mconfig(machine_config &config, bool epci, const char *default_option)
{
- MC2661(config, m_epci, XTAL(5'068'800));
- m_epci->txd_handler().set("rs232", FUNC(rs232_port_device::write_txd));
- m_epci->rts_handler().set("rs232", FUNC(rs232_port_device::write_rts));
- m_epci->dtr_handler().set("rs232", FUNC(rs232_port_device::write_dtr));
- m_epci->rxrdy_handler().set(FUNC(dmv_k801_device::epci_irq_w));
- m_epci->txrdy_handler().set(FUNC(dmv_k801_device::epci_irq_w));
+ if (epci)
+ SCN2661C(config, m_pci, XTAL(5'068'800));
+ else
+ SCN2651(config, m_pci, XTAL(5'068'800));
+ m_pci->txd_handler().set("rs232", FUNC(rs232_port_device::write_txd));
+ m_pci->rts_handler().set("rs232", FUNC(rs232_port_device::write_rts));
+ m_pci->dtr_handler().set("rs232", FUNC(rs232_port_device::write_dtr));
+ m_pci->rxrdy_handler().set(FUNC(dmv_k801_device::pci_irq_w));
+ m_pci->txrdy_handler().set(FUNC(dmv_k801_device::pci_irq_w));
+
+ RS232_PORT(config, m_rs232, default_rs232_devices, default_option);
+ m_rs232->rxd_handler().set(m_pci, FUNC(scn_pci_device::rxd_w));
+ m_rs232->dcd_handler().set(m_pci, FUNC(scn_pci_device::dcd_w));
+ m_rs232->dsr_handler().set(m_pci, FUNC(scn_pci_device::dsr_w));
+ m_rs232->cts_handler().set(m_pci, FUNC(scn_pci_device::cts_w));
+}
- RS232_PORT(config, m_rs232, default_rs232_devices, "printer");
- m_rs232->rxd_handler().set(m_epci, FUNC(mc2661_device::rx_w));
- m_rs232->dcd_handler().set(m_epci, FUNC(mc2661_device::dcd_w));
- m_rs232->dsr_handler().set(m_epci, FUNC(mc2661_device::dsr_w));
- m_rs232->cts_handler().set(m_epci, FUNC(mc2661_device::cts_w));
+void dmv_k801_device::device_add_mconfig(machine_config &config)
+{
+ pci_mconfig(config, true, "printer");
}
void dmv_k211_device::device_add_mconfig(machine_config &config)
{
- dmv_k801_device::device_add_mconfig(config);
- m_rs232->set_default_option("null_modem");
+ pci_mconfig(config, false, "null_modem");
}
void dmv_k212_device::device_add_mconfig(machine_config &config)
{
- dmv_k801_device::device_add_mconfig(config);
- m_rs232->set_default_option("printer");
+ pci_mconfig(config, false, "printer");
}
void dmv_k213_device::device_add_mconfig(machine_config &config)
{
- dmv_k801_device::device_add_mconfig(config);
- m_rs232->set_default_option(nullptr);
+ pci_mconfig(config, false, nullptr);
}
//-------------------------------------------------
@@ -201,9 +206,9 @@ ioport_constructor dmv_k213_device::device_input_ports() const
return INPUT_PORTS_NAME( dmv_k213 );
}
-WRITE_LINE_MEMBER(dmv_k801_device::epci_irq_w)
+void dmv_k801_device::pci_irq_w(int state)
{
- m_bus->m_out_irq_cb(state);
+ out_irq(state);
}
void dmv_k801_device::io_read(int ifsel, offs_t offset, uint8_t &data)
@@ -212,9 +217,9 @@ void dmv_k801_device::io_read(int ifsel, offs_t offset, uint8_t &data)
if ((dsw >> 1) == ifsel && BIT(offset, 3) == BIT(dsw, 0))
{
if (offset & 0x04)
- m_epci->write(offset & 0x03, data);
+ m_pci->write(offset & 0x03, data);
else
- data = m_epci->read(offset & 0x03);
+ data = m_pci->read(offset & 0x03);
}
}
@@ -224,9 +229,9 @@ void dmv_k801_device::io_write(int ifsel, offs_t offset, uint8_t data)
if ((dsw >> 1) == ifsel && BIT(offset, 3) == BIT(dsw, 0))
{
if (offset & 0x04)
- m_epci->write(offset & 0x03, data);
+ m_pci->write(offset & 0x03, data);
else
- data = m_epci->read(offset & 0x03);
+ data = m_pci->read(offset & 0x03);
}
}
@@ -236,9 +241,9 @@ void dmv_k211_device::io_read(int ifsel, offs_t offset, uint8_t &data)
if ((BIT(jumpers, 0) && ifsel == 0) || (BIT(jumpers, 1) && ifsel == 1))
{
if (offset & 0x04)
- m_epci->write(offset & 0x03, data);
+ m_pci->write(offset & 0x03, data);
else
- data = m_epci->read(offset & 0x03);
+ data = m_pci->read(offset & 0x03);
}
}
@@ -248,8 +253,8 @@ void dmv_k211_device::io_write(int ifsel, offs_t offset, uint8_t data)
if ((BIT(jumpers, 0) && ifsel == 0) || (BIT(jumpers, 1) && ifsel == 1))
{
if (offset & 0x04)
- m_epci->write(offset & 0x03, data);
+ m_pci->write(offset & 0x03, data);
else
- data = m_epci->read(offset & 0x03);
+ data = m_pci->read(offset & 0x03);
}
}
diff --git a/src/devices/bus/dmv/k801.h b/src/devices/bus/dmv/k801.h
index db4b557bbb1..1fca8cf2bf6 100644
--- a/src/devices/bus/dmv/k801.h
+++ b/src/devices/bus/dmv/k801.h
@@ -1,12 +1,13 @@
// license:BSD-3-Clause
// copyright-holders:Sandro Ronco
+// thanks-to:rfka01
#ifndef MAME_BUS_DMV_K801_H
#define MAME_BUS_DMV_K801_H
#pragma once
#include "dmvbus.h"
-#include "machine/mc2661.h"
+#include "machine/scn_pci.h"
#include "bus/rs232/rs232.h"
@@ -28,25 +29,25 @@ protected:
dmv_k801_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_start() override ATTR_COLD;
+ virtual void device_reset() override ATTR_COLD;
// optional information overrides
- virtual ioport_constructor device_input_ports() const override;
- virtual void device_add_mconfig(machine_config &config) override;
+ virtual ioport_constructor device_input_ports() const override ATTR_COLD;
+ virtual void device_add_mconfig(machine_config &config) override ATTR_COLD;
// dmvcart_interface overrides
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;
- required_device<mc2661_device> m_epci;
+ void pci_mconfig(machine_config &config, bool epci, const char *default_option);
+
+ required_device<scn_pci_device> m_pci;
required_device<rs232_port_device> m_rs232;
required_ioport m_dsw;
private:
- DECLARE_WRITE_LINE_MEMBER(epci_irq_w);
-
- dmvcart_slot_device * m_bus;
+ void pci_irq_w(int state);
};
@@ -63,8 +64,8 @@ protected:
dmv_k211_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;
- virtual void device_add_mconfig(machine_config &config) override;
+ virtual ioport_constructor device_input_ports() const override ATTR_COLD;
+ virtual void device_add_mconfig(machine_config &config) override ATTR_COLD;
// dmvcart_interface overrides
virtual void io_read(int ifsel, offs_t offset, uint8_t &data) override;
@@ -82,8 +83,8 @@ public:
protected:
// optional information overrides
- virtual ioport_constructor device_input_ports() const override;
- virtual void device_add_mconfig(machine_config &config) override;
+ virtual ioport_constructor device_input_ports() const override ATTR_COLD;
+ virtual void device_add_mconfig(machine_config &config) override ATTR_COLD;
};
// ======================> dmv_k213_device
@@ -97,8 +98,8 @@ public:
protected:
// optional information overrides
- virtual ioport_constructor device_input_ports() const override;
- virtual void device_add_mconfig(machine_config &config) override;
+ virtual ioport_constructor device_input_ports() const override ATTR_COLD;
+ virtual void device_add_mconfig(machine_config &config) override ATTR_COLD;
};
diff --git a/src/devices/bus/dmv/k803.cpp b/src/devices/bus/dmv/k803.cpp
index d0cf9cff336..87d7ef6bcbd 100644
--- a/src/devices/bus/dmv/k803.cpp
+++ b/src/devices/bus/dmv/k803.cpp
@@ -1,5 +1,6 @@
// license:BSD-3-Clause
// copyright-holders:Sandro Ronco
+// thanks-to:rfka01
/***************************************************************************
K803 RTC module
@@ -44,11 +45,12 @@ DEFINE_DEVICE_TYPE(DMV_K803, dmv_k803_device, "dmv_k803", "K803 RTC")
// dmv_k803_device - constructor
//-------------------------------------------------
-dmv_k803_device::dmv_k803_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
- : device_t(mconfig, DMV_K803, tag, owner, clock),
+dmv_k803_device::dmv_k803_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) :
+ device_t(mconfig, DMV_K803, tag, owner, clock),
device_dmvslot_interface( mconfig, *this ),
m_rtc(*this, "rtc"),
- m_dsw(*this, "DSW"), m_bus(nullptr), m_latch(0), m_rtc_int(0)
+ m_dsw(*this, "DSW"),
+ m_latch(0), m_rtc_int(0)
{
}
@@ -58,7 +60,9 @@ dmv_k803_device::dmv_k803_device(const machine_config &mconfig, const char *tag,
void dmv_k803_device::device_start()
{
- m_bus = static_cast<dmvcart_slot_device*>(owner());
+ // register for state saving
+ save_item(NAME(m_latch));
+ save_item(NAME(m_rtc_int));
}
//-------------------------------------------------
@@ -115,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();
@@ -124,5 +128,5 @@ WRITE_LINE_MEMBER(dmv_k803_device::rtc_irq_w)
void dmv_k803_device::update_int()
{
bool state = ((m_latch & 0x80) && m_rtc_int);
- m_bus->m_out_int_cb(state ? ASSERT_LINE : CLEAR_LINE);
+ out_int(state ? ASSERT_LINE : CLEAR_LINE);
}
diff --git a/src/devices/bus/dmv/k803.h b/src/devices/bus/dmv/k803.h
index e8455646d1e..68f8df1e896 100644
--- a/src/devices/bus/dmv/k803.h
+++ b/src/devices/bus/dmv/k803.h
@@ -1,5 +1,6 @@
// license:BSD-3-Clause
// copyright-holders:Sandro Ronco
+// thanks-to:rfka01
#ifndef MAME_BUS_DMV_K803_H
#define MAME_BUS_DMV_K803_H
@@ -24,12 +25,12 @@ public:
protected:
// device-level overrides
- virtual void device_start() override;
- virtual void device_reset() override;
+ virtual void device_start() override ATTR_COLD;
+ virtual void device_reset() override ATTR_COLD;
// optional information overrides
- virtual ioport_constructor device_input_ports() const override;
- virtual void device_add_mconfig(machine_config &config) override;
+ virtual ioport_constructor device_input_ports() const override ATTR_COLD;
+ virtual void device_add_mconfig(machine_config &config) override ATTR_COLD;
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;
@@ -37,11 +38,10 @@ 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;
- dmvcart_slot_device * m_bus;
uint8_t m_latch;
int m_rtc_int;
};
diff --git a/src/devices/bus/dmv/k806.cpp b/src/devices/bus/dmv/k806.cpp
index d7b3125771c..5f160dd6809 100644
--- a/src/devices/bus/dmv/k806.cpp
+++ b/src/devices/bus/dmv/k806.cpp
@@ -1,5 +1,6 @@
// license:BSD-3-Clause
// copyright-holders:Sandro Ronco
+// thanks-to:rfka01
/***************************************************************************
K806 Mouse module
@@ -70,7 +71,6 @@ dmv_k806_device::dmv_k806_device(const machine_config &mconfig, const char *tag,
, m_mouse_buttons(*this, "MOUSE")
, m_mouse_x(*this, "MOUSEX")
, m_mouse_y(*this, "MOUSEY")
- , m_bus(nullptr)
{
}
@@ -80,7 +80,16 @@ dmv_k806_device::dmv_k806_device(const machine_config &mconfig, const char *tag,
void dmv_k806_device::device_start()
{
- m_bus = static_cast<dmvcart_slot_device*>(owner());
+ // register for state saving
+ save_item(NAME(m_mouse.phase));
+ save_item(NAME(m_mouse.x));
+ save_item(NAME(m_mouse.y));
+ save_item(NAME(m_mouse.prev_x));
+ save_item(NAME(m_mouse.prev_y));
+ save_item(NAME(m_mouse.xa));
+ save_item(NAME(m_mouse.xb));
+ save_item(NAME(m_mouse.ya));
+ save_item(NAME(m_mouse.yb));
}
//-------------------------------------------------
@@ -107,7 +116,7 @@ void dmv_k806_device::device_add_mconfig(machine_config &config)
m_mcu->p2_out_cb().set(FUNC(dmv_k806_device::port2_w));
m_mcu->t1_in_cb().set(FUNC(dmv_k806_device::portt1_r));
- TIMER(config, "mouse_timer", 0).configure_periodic(timer_device::expired_delegate(FUNC(dmv_k806_device::mouse_timer), this), attotime::from_hz(1000));
+ TIMER(config, "mouse_timer", 0).configure_periodic(FUNC(dmv_k806_device::mouse_timer), attotime::from_hz(1000));
}
//-------------------------------------------------
@@ -132,7 +141,7 @@ void dmv_k806_device::io_read(int ifsel, offs_t offset, uint8_t &data)
{
uint8_t jumpers = m_jumpers->read();
if (BIT(jumpers, ifsel) && ((!BIT(offset, 3) && BIT(jumpers, 5)) || (BIT(offset, 3) && BIT(jumpers, 6))))
- data = m_mcu->upi41_master_r(machine().dummy_space(), offset & 1);
+ data = m_mcu->upi41_master_r(offset & 1);
}
void dmv_k806_device::io_write(int ifsel, offs_t offset, uint8_t data)
@@ -140,12 +149,12 @@ void dmv_k806_device::io_write(int ifsel, offs_t offset, uint8_t data)
uint8_t jumpers = m_jumpers->read();
if (BIT(jumpers, ifsel) && ((!BIT(offset, 3) && BIT(jumpers, 5)) || (BIT(offset, 3) && BIT(jumpers, 6))))
{
- m_mcu->upi41_master_w(machine().dummy_space(), offset & 1, data);
- m_bus->m_out_int_cb(CLEAR_LINE);
+ m_mcu->upi41_master_w(offset & 1, data);
+ out_int(CLEAR_LINE);
}
}
-READ8_MEMBER( dmv_k806_device::port1_r )
+uint8_t dmv_k806_device::port1_r()
{
// ---- ---x Left button
// ---- --x- Middle button
@@ -166,14 +175,14 @@ READ8_MEMBER( 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;
}
-WRITE8_MEMBER( dmv_k806_device::port2_w )
+void dmv_k806_device::port2_w(uint8_t data)
{
- m_bus->m_out_int_cb((data & 1) ? CLEAR_LINE : ASSERT_LINE);
+ out_int((data & 1) ? CLEAR_LINE : ASSERT_LINE);
}
/*-------------------------------------------------------------------
diff --git a/src/devices/bus/dmv/k806.h b/src/devices/bus/dmv/k806.h
index 082d56b11a6..acd00287e83 100644
--- a/src/devices/bus/dmv/k806.h
+++ b/src/devices/bus/dmv/k806.h
@@ -1,5 +1,6 @@
// license:BSD-3-Clause
// copyright-holders:Sandro Ronco
+// thanks-to:rfka01
#ifndef MAME_BUS_DMV_K806_H
#define MAME_BUS_DMV_K806_H
@@ -27,21 +28,21 @@ public:
protected:
// device-level overrides
- virtual void device_start() override;
- virtual void device_reset() override;
+ virtual void device_start() override ATTR_COLD;
+ virtual void device_reset() override ATTR_COLD;
// optional information overrides
- 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 const tiny_rom_entry *device_rom_region() const override ATTR_COLD;
+ virtual ioport_constructor device_input_ports() const override ATTR_COLD;
+ virtual void device_add_mconfig(machine_config &config) override ATTR_COLD;
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;
private:
- DECLARE_READ_LINE_MEMBER(portt1_r);
- DECLARE_READ8_MEMBER(port1_r);
- DECLARE_WRITE8_MEMBER(port2_w);
+ int portt1_r();
+ uint8_t port1_r();
+ void port2_w(uint8_t data);
TIMER_DEVICE_CALLBACK_MEMBER(mouse_timer);
@@ -50,7 +51,6 @@ private:
required_ioport m_mouse_buttons;
required_ioport m_mouse_x;
required_ioport m_mouse_y;
- dmvcart_slot_device * m_bus;
struct
{
diff --git a/src/devices/bus/dmv/ram.cpp b/src/devices/bus/dmv/ram.cpp
index 2e879fc9ce6..3538ba6ed41 100644
--- a/src/devices/bus/dmv/ram.cpp
+++ b/src/devices/bus/dmv/ram.cpp
@@ -1,5 +1,6 @@
// license:BSD-3-Clause
// copyright-holders:Sandro Ronco
+// thanks-to:rfka01
/***************************************************************************
K200 64K RAM expansion
@@ -74,6 +75,9 @@ dmv_k208_device::dmv_k208_device(const machine_config &mconfig, const char *tag,
void dmv_ram_device_base::device_start()
{
m_ram = machine().memory().region_alloc( "expram", m_size * 0x10000, 1, ENDIANNESS_LITTLE )->base();
+
+ // register for state saving
+ save_pointer(NAME(m_ram), m_size * 0x10000);
}
//-------------------------------------------------
diff --git a/src/devices/bus/dmv/ram.h b/src/devices/bus/dmv/ram.h
index 43e7820a9ca..038d342750b 100644
--- a/src/devices/bus/dmv/ram.h
+++ b/src/devices/bus/dmv/ram.h
@@ -1,5 +1,6 @@
// license:BSD-3-Clause
// copyright-holders:Sandro Ronco
+// thanks-to:rfka01
#ifndef MAME_BUS_DMV_RAM_H
#define MAME_BUS_DMV_RAM_H
@@ -22,7 +23,7 @@ protected:
dmv_ram_device_base(const machine_config &mconfig, device_type type, uint32_t size, const char *tag, device_t *owner, uint32_t clock);
// device-level overrides
- virtual void device_start() override;
+ virtual void device_start() override ATTR_COLD;
// dmvcart_interface overrides
virtual void ram_read(uint8_t cas, offs_t offset, uint8_t &data) override;
diff --git a/src/devices/bus/ecbbus/ecbbus.cpp b/src/devices/bus/ecbbus/ecbbus.cpp
index c5499f1fb6c..a59c0eede84 100644
--- a/src/devices/bus/ecbbus/ecbbus.cpp
+++ b/src/devices/bus/ecbbus/ecbbus.cpp
@@ -29,8 +29,9 @@ DEFINE_DEVICE_TYPE(ECBBUS_SLOT, ecbbus_slot_device, "ecbbus_slot", "ECB bus slot
ecbbus_slot_device::ecbbus_slot_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) :
device_t(mconfig, ECBBUS_SLOT, tag, owner, clock),
- device_slot_interface(mconfig, *this),
- m_bus_tag(nullptr), m_bus_num(0), m_bus(nullptr)
+ device_single_card_slot_interface<device_ecbbus_card_interface>(mconfig, *this),
+ m_bus(*this, finder_base::DUMMY_TAG),
+ m_bus_num(0)
{
}
@@ -41,9 +42,9 @@ ecbbus_slot_device::ecbbus_slot_device(const machine_config &mconfig, const char
void ecbbus_slot_device::device_start()
{
- m_bus = machine().device<ecbbus_device>(m_bus_tag);
- device_ecbbus_card_interface *dev = dynamic_cast<device_ecbbus_card_interface *>(get_card_device());
- if (dev) m_bus->add_card(dev, m_bus_num);
+ device_ecbbus_card_interface *const dev = get_card_device();
+ if (dev)
+ m_bus->add_card(*dev, m_bus_num);
}
@@ -65,7 +66,7 @@ DEFINE_DEVICE_TYPE(ECBBUS, ecbbus_device, "ecbbus", "ECB bus")
//-------------------------------------------------
device_ecbbus_card_interface::device_ecbbus_card_interface(const machine_config &mconfig, device_t &device) :
- device_slot_card_interface(mconfig, device)
+ device_interface(device, "ecbbus")
{
m_slot = dynamic_cast<ecbbus_slot_device *>(device.owner());
}
@@ -95,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();
}
@@ -105,9 +103,9 @@ void ecbbus_device::device_start()
// add_card - add ECB bus card
//-------------------------------------------------
-void ecbbus_device::add_card(device_ecbbus_card_interface *card, int pos)
+void ecbbus_device::add_card(device_ecbbus_card_interface &card, int pos)
{
- m_ecbbus_device[pos] = card;
+ m_ecbbus_device[pos] = &card;
}
@@ -115,7 +113,7 @@ void ecbbus_device::add_card(device_ecbbus_card_interface *card, int pos)
// mem_r -
//-------------------------------------------------
-READ8_MEMBER( ecbbus_device::mem_r )
+uint8_t ecbbus_device::mem_r(offs_t offset)
{
uint8_t data = 0;
@@ -135,7 +133,7 @@ READ8_MEMBER( ecbbus_device::mem_r )
// mem_w -
//-------------------------------------------------
-WRITE8_MEMBER( ecbbus_device::mem_w )
+void ecbbus_device::mem_w(offs_t offset, uint8_t data)
{
for (auto & elem : m_ecbbus_device)
{
@@ -151,7 +149,7 @@ WRITE8_MEMBER( ecbbus_device::mem_w )
// io_r -
//-------------------------------------------------
-READ8_MEMBER( ecbbus_device::io_r )
+uint8_t ecbbus_device::io_r(offs_t offset)
{
uint8_t data = 0;
@@ -171,7 +169,7 @@ READ8_MEMBER( ecbbus_device::io_r )
// io_w -
//-------------------------------------------------
-WRITE8_MEMBER( ecbbus_device::io_w )
+void ecbbus_device::io_w(offs_t offset, uint8_t data)
{
for (auto & elem : m_ecbbus_device)
{
diff --git a/src/devices/bus/ecbbus/ecbbus.h b/src/devices/bus/ecbbus/ecbbus.h
index c14f1c53de4..c3f9bad9fed 100644
--- a/src/devices/bus/ecbbus/ecbbus.h
+++ b/src/devices/bus/ecbbus/ecbbus.h
@@ -50,49 +50,46 @@
//**************************************************************************
-// CONSTANTS
+// TYPE DEFINITIONS
//**************************************************************************
-#define ECBBUS_TAG "ecbbus"
-
+class device_ecbbus_card_interface;
+class ecbbus_device;
-//**************************************************************************
-// TYPE DEFINITIONS
-//**************************************************************************
// ======================> ecbbus_slot_device
-class ecbbus_device;
-
-class ecbbus_slot_device : public device_t,
- public device_slot_interface
+class ecbbus_slot_device : public device_t, public device_single_card_slot_interface<device_ecbbus_card_interface>
{
public:
// construction/destruction
- template <typename T>
- ecbbus_slot_device(machine_config const &mconfig, char const *tag, device_t *owner, int num, T &&opts, char const *dflt)
+ template <typename T, typename U>
+ ecbbus_slot_device(machine_config const &mconfig, char const *tag, device_t *owner, T &&bustag, int num, U &&opts, char const *dflt)
: ecbbus_slot_device(mconfig, tag, owner, 0)
{
option_reset();
opts(*this);
set_default_option(dflt);
set_fixed(false);
- set_ecbbus_slot(ECBBUS_TAG, num);
+ set_ecbbus_slot(std::forward<T>(bustag), num);
}
ecbbus_slot_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
// device-level overrides
- virtual void device_start() override;
+ virtual void device_start() override ATTR_COLD;
// inline configuration
- void set_ecbbus_slot(const char *tag, int num) { m_bus_tag = tag; m_bus_num = num; }
+ template <typename T> void set_ecbbus_slot(T &&tag, int num)
+ {
+ m_bus.set_tag(std::forward<T>(tag));
+ m_bus_num = num;
+ }
private:
// configuration
- const char *m_bus_tag;
+ required_device<ecbbus_device> m_bus;
int m_bus_num;
- ecbbus_device *m_bus;
};
@@ -100,11 +97,6 @@ private:
DECLARE_DEVICE_TYPE(ECBBUS_SLOT, ecbbus_slot_device)
-// ======================> ecbbus_interface
-
-class device_ecbbus_card_interface;
-
-
// ======================> ecbbus_device
class ecbbus_device : public device_t
@@ -116,20 +108,20 @@ public:
auto irq_wr_callback() { return m_write_irq.bind(); }
auto nmi_wr_callback() { return m_write_nmi.bind(); }
- void add_card(device_ecbbus_card_interface *card, int pos);
+ void add_card(device_ecbbus_card_interface &card, int pos);
- DECLARE_READ8_MEMBER( mem_r );
- DECLARE_WRITE8_MEMBER( mem_w );
+ uint8_t mem_r(offs_t offset);
+ void mem_w(offs_t offset, uint8_t data);
- DECLARE_READ8_MEMBER( io_r );
- DECLARE_WRITE8_MEMBER( io_w );
+ 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
- virtual void device_start() override;
+ virtual void device_start() override ATTR_COLD;
private:
static constexpr unsigned MAX_ECBBUS_SLOTS = 16;
@@ -148,16 +140,16 @@ DECLARE_DEVICE_TYPE(ECBBUS, ecbbus_device)
// ======================> device_ecbbus_card_interface
// class representing interface-specific live ecbbus card
-class device_ecbbus_card_interface : public device_slot_card_interface
+class device_ecbbus_card_interface : public device_interface
{
friend class ecbbus_device;
public:
// optional operation overrides
- virtual uint8_t ecbbus_mem_r(offs_t offset) { return 0; };
- virtual void ecbbus_mem_w(offs_t offset, uint8_t data) { };
- virtual uint8_t ecbbus_io_r(offs_t offset) { return 0; };
- virtual void ecbbus_io_w(offs_t offset, uint8_t data) { };
+ virtual uint8_t ecbbus_mem_r(offs_t offset) { return 0; }
+ virtual void ecbbus_mem_w(offs_t offset, uint8_t data) { }
+ virtual uint8_t ecbbus_io_r(offs_t offset) { return 0; }
+ virtual void ecbbus_io_w(offs_t offset, uint8_t data) { }
protected:
// construction/destruction
diff --git a/src/devices/bus/ecbbus/grip.cpp b/src/devices/bus/ecbbus/grip.cpp
index 6312a32547f..d4f83e61edd 100644
--- a/src/devices/bus/ecbbus/grip.cpp
+++ b/src/devices/bus/ecbbus/grip.cpp
@@ -140,12 +140,12 @@ void ecb_grip21_device::grip_io(address_map &map)
{
map.global_mask(0xff);
map(0x00, 0x00).rw(FUNC(ecb_grip21_device::cxstb_r), FUNC(ecb_grip21_device::cxstb_w));
-// AM_RANGE(0x10, 0x10) AM_WRITE(ccon_w)
+// map(0x10, 0x10).w(FUNC(ecb_grip21_device::ccon_w));
map(0x11, 0x11).w(FUNC(ecb_grip21_device::vol0_w));
-// AM_RANGE(0x12, 0x12) AM_WRITE(rts_w)
+// map(0x12, 0x12).w(FUNC(ecb_grip21_device::rts_w));
map(0x13, 0x13).w(FUNC(ecb_grip21_device::page_w));
-// AM_RANGE(0x14, 0x14) AM_WRITE(cc1_w)
-// AM_RANGE(0x15, 0x15) AM_WRITE(cc2_w)
+// map(0x14, 0x14).w(FUNC(ecb_grip21_device::cc1_w));
+// map(0x15, 0x15).w(FUNC(ecb_grip21_device::cc2_w));
map(0x16, 0x16).w(FUNC(ecb_grip21_device::flash_w));
map(0x17, 0x17).w(FUNC(ecb_grip21_device::vol1_w));
map(0x20, 0x2f).rw(m_sti, FUNC(z80sti_device::read), FUNC(z80sti_device::write));
@@ -154,16 +154,16 @@ void ecb_grip21_device::grip_io(address_map &map)
map(0x50, 0x50).w(MC6845_TAG, FUNC(mc6845_device::address_w));
map(0x52, 0x52).w(MC6845_TAG, FUNC(mc6845_device::register_w));
map(0x53, 0x53).r(MC6845_TAG, FUNC(mc6845_device::register_r));
- map(0x60, 0x60).w("cent_data_out", FUNC(output_latch_device::bus_w));
+ map(0x60, 0x60).w("cent_data_out", FUNC(output_latch_device::write));
map(0x70, 0x73).rw(I8255A_TAG, FUNC(i8255_device::read), FUNC(i8255_device::write));
-// AM_RANGE(0x80, 0x80) AM_WRITE(bl2out_w)
-// AM_RANGE(0x90, 0x90) AM_WRITE(gr2out_w)
-// AM_RANGE(0xa0, 0xa0) AM_WRITE(rd2out_w)
-// AM_RANGE(0xb0, 0xb0) AM_WRITE(clrg2_w)
-// AM_RANGE(0xc0, 0xc0) AM_WRITE(bluout_w)
-// AM_RANGE(0xd0, 0xd0) AM_WRITE(grnout_w)
-// AM_RANGE(0xe0, 0xe0) AM_WRITE(redout_w)
-// AM_RANGE(0xf0, 0xf0) AM_WRITE(clrg1_w)
+// map(0x80, 0x80).w(FUNC(ecb_grip21_device::bl2out_w));
+// map(0x90, 0x90).w(FUNC(ecb_grip21_device::gr2out_w));
+// map(0xa0, 0xa0).w(FUNC(ecb_grip21_device::rd2out_w));
+// map(0xb0, 0xb0).w(FUNC(ecb_grip21_device::clrg2_w));
+// map(0xc0, 0xc0).w(FUNC(ecb_grip21_device::bluout_w));
+// map(0xd0, 0xd0).w(FUNC(ecb_grip21_device::grnout_w));
+// map(0xe0, 0xe0).w(FUNC(ecb_grip21_device::redout_w));
+// map(0xf0, 0xf0).w(FUNC(ecb_grip21_device::clrg1_w));
}
@@ -179,35 +179,33 @@ MC6845_UPDATE_ROW( ecb_grip21_device::crtc_update_row )
{
for (int column = 0; column < x_count; column++)
{
- uint16_t address = (m_page << 12) | (((ma + column) & 0xfff) << 3) | (ra & 0x07);
- uint8_t data = m_video_ram[address];
+ uint16_t const address = (m_page << 12) | (((ma + column) & 0xfff) << 3) | (ra & 0x07);
+ uint8_t const data = m_video_ram[address];
for (int bit = 0; bit < 8; bit++)
{
- int x = (column * 8) + bit;
- int color = (m_flash ? 0 : BIT(data, bit)) && de;
+ int const x = (column * 8) + bit;
+ int const color = (m_flash ? 0 : BIT(data, bit)) && de;
- bitmap.pix32(vbp + y, hbp + x) = m_palette->pen(color);
+ bitmap.pix(vbp + y, hbp + x) = m_palette->pen(color);
}
}
}
/*
MC6845_UPDATE_ROW( ecb_grip21_device::grip5_update_row )
{
- const rgb_t *palette = m_palette->palette()->entry_list_raw();
- int column, bit;
-
- for (column = 0; column < x_count; column++)
+ rgb_t const *const palette = m_palette->palette()->entry_list_raw();
+ for (int column = 0; column < x_count; column++)
{
- uint16_t address = (m_dpage << 12) | (((ma + column) & 0xfff) << 3) | (ra & 0x07);
- uint8_t data = m_video_ram[address];
+ uint16_t const address = (m_dpage << 12) | (((ma + column) & 0xfff) << 3) | (ra & 0x07);
+ uint8_t const data = m_video_ram[address];
- for (bit = 0; bit < 8; bit++)
+ for (int bit = 0; bit < 8; bit++)
{
- int x = (column * 8) + bit;
- int color = m_flash ? 0 : BIT(data, bit);
+ int const x = (column * 8) + bit;
+ int const color = m_flash ? 0 : BIT(data, bit);
- bitmap.pix32(y, x) = palette[color];
+ bitmap.pix(y, x) = palette[color];
}
}
}
@@ -217,13 +215,13 @@ MC6845_ON_UPDATE_ADDR_CHANGED( ecb_grip21_device::grip5_addr_changed )
}
*/
-static const int16_t speaker_levels[] = { -32768, 0, 32767, 0 };
+static const double speaker_levels[] = { -1.0, 0.0, 1.0, 0.0 };
//-------------------------------------------------
// I8255A interface
//-------------------------------------------------
-READ8_MEMBER( ecb_grip21_device::ppi_pa_r )
+uint8_t ecb_grip21_device::ppi_pa_r()
{
/*
@@ -243,7 +241,7 @@ READ8_MEMBER( ecb_grip21_device::ppi_pa_r )
return m_ppi_pa;
}
-WRITE8_MEMBER( ecb_grip21_device::ppi_pa_w )
+void ecb_grip21_device::ppi_pa_w(uint8_t data)
{
/*
@@ -263,7 +261,7 @@ WRITE8_MEMBER( ecb_grip21_device::ppi_pa_w )
m_ppi_pa = data;
}
-READ8_MEMBER( ecb_grip21_device::ppi_pb_r )
+uint8_t ecb_grip21_device::ppi_pb_r()
{
/*
@@ -283,7 +281,7 @@ READ8_MEMBER( ecb_grip21_device::ppi_pb_r )
return m_keydata;
}
-WRITE8_MEMBER( ecb_grip21_device::ppi_pc_w )
+void ecb_grip21_device::ppi_pc_w(uint8_t data)
{
/*
@@ -319,12 +317,12 @@ WRITE8_MEMBER( ecb_grip21_device::ppi_pc_w )
// 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;
}
-READ8_MEMBER( ecb_grip21_device::sti_gpio_r )
+uint8_t ecb_grip21_device::sti_gpio_r()
{
/*
@@ -361,7 +359,7 @@ READ8_MEMBER( 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);
@@ -435,7 +433,7 @@ void ecb_grip21_device::device_add_mconfig(machine_config &config)
m_crtc->set_screen(SCREEN_TAG);
m_crtc->set_show_border_area(true);
m_crtc->set_char_width(8);
- m_crtc->set_update_row_callback(FUNC(ecb_grip21_device::crtc_update_row), this);
+ m_crtc->set_update_row_callback(FUNC(ecb_grip21_device::crtc_update_row));
m_crtc->out_de_callback().set(m_sti, FUNC(z80sti_device::i1_w));
m_crtc->out_cur_callback().set(m_sti, FUNC(z80sti_device::i1_w));
@@ -569,11 +567,24 @@ ecb_grip21_device::ecb_grip21_device(const machine_config &mconfig, const char *
m_centronics(*this, CENTRONICS_TAG),
m_palette(*this, "palette"),
m_speaker(*this, "speaker"),
- m_video_ram(*this, "video_ram"),
+ m_video_ram(*this, "video_ram", VIDEORAM_SIZE, ENDIANNESS_LITTLE),
m_j3a(*this, "J3A"),
m_j3b(*this, "J3B"),
m_j7(*this, "J7"),
- m_centronics_busy(0), m_centronics_fault(0), m_vol0(0), m_vol1(0), m_ia(0), m_ib(0), m_keydata(0), m_kbf(0), m_lps(0), m_page(0), m_flash(0), m_base(0), m_ppi_pa(0), m_ppi_pc(0), m_kb_timer(nullptr)
+ m_centronics_busy(0),
+ m_centronics_fault(0),
+ m_vol0(0),
+ m_vol1(0),
+ m_ia(0),
+ m_ib(0),
+ m_keydata(0),
+ m_kbf(0),
+ m_lps(0),
+ m_page(0),
+ m_flash(0),
+ m_base(0),
+ m_ppi_pa(0),
+ m_ppi_pc(0)
{
}
@@ -583,17 +594,10 @@ ecb_grip21_device::ecb_grip21_device(const machine_config &mconfig, const char *
void ecb_grip21_device::device_start()
{
- // allocate video RAM
- m_video_ram.allocate(VIDEORAM_SIZE);
-
// setup GRIP memory banking
membank("videoram")->configure_entries(0, 2, m_video_ram, 0x8000);
membank("videoram")->set_entry(0);
- // allocate keyboard scan timer
- m_kb_timer = timer_alloc();
- m_kb_timer->adjust(attotime::zero, 0, attotime::from_hz(2500));
-
// register for state saving
save_item(NAME(m_vol0));
save_item(NAME(m_vol1));
@@ -634,7 +638,7 @@ void ecb_grip21_device::device_reset()
// vol0_w - volume 0
//-------------------------------------------------
-WRITE8_MEMBER( ecb_grip21_device::vol0_w )
+void ecb_grip21_device::vol0_w(uint8_t data)
{
m_vol0 = BIT(data, 7);
}
@@ -644,7 +648,7 @@ WRITE8_MEMBER( ecb_grip21_device::vol0_w )
// vol1_w - volume 1
//-------------------------------------------------
-WRITE8_MEMBER( ecb_grip21_device::vol1_w )
+void ecb_grip21_device::vol1_w(uint8_t data)
{
m_vol1 = BIT(data, 7);
}
@@ -654,7 +658,7 @@ WRITE8_MEMBER( ecb_grip21_device::vol1_w )
// flash_w -
//-------------------------------------------------
-WRITE8_MEMBER( ecb_grip21_device::flash_w )
+void ecb_grip21_device::flash_w(uint8_t data)
{
m_flash = BIT(data, 7);
}
@@ -664,7 +668,7 @@ WRITE8_MEMBER( ecb_grip21_device::flash_w )
// page_w - video page select
//-------------------------------------------------
-WRITE8_MEMBER( ecb_grip21_device::page_w )
+void ecb_grip21_device::page_w(uint8_t data)
{
m_page = BIT(data, 7);
@@ -676,12 +680,12 @@ WRITE8_MEMBER( ecb_grip21_device::page_w )
// stat_r -
//-------------------------------------------------
-WRITE_LINE_MEMBER(ecb_grip21_device::write_centronics_fault)
+void ecb_grip21_device::write_centronics_fault(int state)
{
m_centronics_fault = state;
}
-READ8_MEMBER( ecb_grip21_device::stat_r )
+uint8_t ecb_grip21_device::stat_r()
{
/*
@@ -739,9 +743,10 @@ READ8_MEMBER( ecb_grip21_device::stat_r )
// lrs_r -
//-------------------------------------------------
-READ8_MEMBER( ecb_grip21_device::lrs_r )
+uint8_t ecb_grip21_device::lrs_r()
{
- m_lps = 0;
+ if (!machine().side_effects_disabled())
+ m_lps = 0;
return 0;
}
@@ -751,7 +756,7 @@ READ8_MEMBER( ecb_grip21_device::lrs_r )
// lrs_w -
//-------------------------------------------------
-WRITE8_MEMBER( ecb_grip21_device::lrs_w )
+void ecb_grip21_device::lrs_w(uint8_t data)
{
m_lps = 0;
}
@@ -761,10 +766,13 @@ WRITE8_MEMBER( ecb_grip21_device::lrs_w )
// cxstb_r - centronics strobe
//-------------------------------------------------
-READ8_MEMBER( ecb_grip21_device::cxstb_r )
+uint8_t ecb_grip21_device::cxstb_r()
{
- m_centronics->write_strobe(0);
- m_centronics->write_strobe(1);
+ if (!machine().side_effects_disabled())
+ {
+ m_centronics->write_strobe(0);
+ m_centronics->write_strobe(1);
+ }
return 0;
}
@@ -774,7 +782,7 @@ READ8_MEMBER( ecb_grip21_device::cxstb_r )
// cxstb_w - centronics strobe
//-------------------------------------------------
-WRITE8_MEMBER( ecb_grip21_device::cxstb_w )
+void ecb_grip21_device::cxstb_w(uint8_t data)
{
m_centronics->write_strobe(0);
m_centronics->write_strobe(1);
@@ -785,7 +793,7 @@ WRITE8_MEMBER( ecb_grip21_device::cxstb_w )
// eprom_w - EPROM bank select
//-------------------------------------------------
-WRITE8_MEMBER( grip5_state::eprom_w )
+void grip5_state::eprom_w(uint8_t data)
{
membank("eprom")->set_entry(BIT(data, 0));
}
@@ -795,7 +803,7 @@ WRITE8_MEMBER( grip5_state::eprom_w )
// dpage_w - display page select
//-------------------------------------------------
-WRITE8_MEMBER( grip5_state::dpage_w )
+void grip5_state::dpage_w(uint8_t data)
{
m_dpage = BIT(data, 7);
}
diff --git a/src/devices/bus/ecbbus/grip.h b/src/devices/bus/ecbbus/grip.h
index d1e1456eb57..720c9d63e65 100644
--- a/src/devices/bus/ecbbus/grip.h
+++ b/src/devices/bus/ecbbus/grip.h
@@ -39,30 +39,30 @@ public:
protected:
// device-level overrides
- virtual void device_start() override;
- virtual void device_reset() override;
+ virtual void device_start() override ATTR_COLD;
+ virtual void device_reset() override ATTR_COLD;
// optional information 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 const tiny_rom_entry *device_rom_region() const override ATTR_COLD;
+ virtual void device_add_mconfig(machine_config &config) override ATTR_COLD;
+ virtual ioport_constructor device_input_ports() const override ATTR_COLD;
// device_ecbbus_card_interface overrides
virtual uint8_t ecbbus_io_r(offs_t offset) override;
virtual void ecbbus_io_w(offs_t offset, uint8_t data) override;
private:
- DECLARE_READ8_MEMBER( ppi_pa_r );
- DECLARE_WRITE8_MEMBER( ppi_pa_w );
- DECLARE_READ8_MEMBER( ppi_pb_r );
- DECLARE_WRITE8_MEMBER( ppi_pc_w );
- DECLARE_READ8_MEMBER( sti_gpio_r );
- DECLARE_WRITE_LINE_MEMBER( speaker_w );
+ uint8_t ppi_pa_r();
+ void ppi_pa_w(uint8_t data);
+ uint8_t ppi_pb_r();
+ void ppi_pc_w(uint8_t data);
+ uint8_t sti_gpio_r();
+ 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 );
@@ -72,7 +72,7 @@ private:
required_device<centronics_device> m_centronics;
required_device<palette_device> m_palette;
required_device<speaker_sound_device> m_speaker;
- optional_shared_ptr<uint8_t> m_video_ram;
+ memory_share_creator<uint8_t> m_video_ram;
required_ioport m_j3a;
required_ioport m_j3b;
required_ioport m_j7;
@@ -100,26 +100,23 @@ private:
uint8_t m_ppi_pa; // PPI port A data
uint8_t m_ppi_pc; // PPI port C data
- // timers
- emu_timer *m_kb_timer;
+ void vol0_w(uint8_t data);
+ void vol1_w(uint8_t data);
+ void flash_w(uint8_t data);
+ void page_w(uint8_t data);
+ uint8_t stat_r();
+ uint8_t lrs_r();
+ void lrs_w(uint8_t data);
+ uint8_t cxstb_r();
+ void cxstb_w(uint8_t data);
- DECLARE_WRITE8_MEMBER( vol0_w );
- DECLARE_WRITE8_MEMBER( vol1_w );
- DECLARE_WRITE8_MEMBER( flash_w );
- DECLARE_WRITE8_MEMBER( page_w );
- DECLARE_READ8_MEMBER( stat_r );
- DECLARE_READ8_MEMBER( lrs_r );
- DECLARE_WRITE8_MEMBER( lrs_w );
- DECLARE_READ8_MEMBER( cxstb_r );
- DECLARE_WRITE8_MEMBER( cxstb_w );
-
- void grip_io(address_map &map);
- void grip_mem(address_map &map);
+ void grip_io(address_map &map) ATTR_COLD;
+ void grip_mem(address_map &map) ATTR_COLD;
/*
required_device<hd6345_device> m_crtc;
- DECLARE_WRITE8_MEMBER( eprom_w );
- DECLARE_WRITE8_MEMBER( dpage_w );
+ void eprom_w(uint8_t data);
+ void dpage_w(uint8_t data);
// video state
int m_dpage; // displayed video page
diff --git a/src/devices/bus/econet/e01.cpp b/src/devices/bus/econet/e01.cpp
index ffb29dbe53e..e46ac49e379 100644
--- a/src/devices/bus/econet/e01.cpp
+++ b/src/devices/bus/econet/e01.cpp
@@ -30,7 +30,7 @@
2 x TMM27256D-20 white labelled EPROMs, TMSE01 MOS on left and E01 FS on the right
IC20 WD2793-APL-02 floppy disc controller
2 x NEC D41464C-12 64k x 4bit NMOS RAM ICs giving 64K memory
- IC21 Rockwell RC6522AP VIA behind to the right
+ IC21 Rockwell R65C22AP or CMD G65SC22P-2 VIA behind to the right
*/
@@ -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,49 +148,50 @@ 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;
}
-FLOPPY_FORMATS_MEMBER( econet_e01_device::floppy_formats_afs )
- FLOPPY_AFS_FORMAT
-FLOPPY_FORMATS_END0
+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);
@@ -197,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);
@@ -218,17 +222,17 @@ 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));
map(0xfc20, 0xfc23).mirror(0x00c0).rw(MC6854_TAG, FUNC(mc6854_device::read), FUNC(mc6854_device::write));
map(0xfc24, 0xfc24).mirror(0x00c3).rw(FUNC(econet_e01_device::network_irq_disable_r), FUNC(econet_e01_device::network_irq_disable_w));
map(0xfc28, 0xfc28).mirror(0x00c3).rw(FUNC(econet_e01_device::network_irq_enable_r), FUNC(econet_e01_device::network_irq_enable_w));
- map(0xfc2c, 0xfc2c).mirror(0x00c3).portr("FLAP");
+ map(0xfc2c, 0xfc2c).mirror(0x00c3).portr(m_flap);
map(0xfc30, 0xfc30).mirror(0x00c0).rw(FUNC(econet_e01_device::hdc_data_r), FUNC(econet_e01_device::hdc_data_w));
- map(0xfc31, 0xfc31).mirror(0x00c0).r("scsi_ctrl_in", FUNC(input_buffer_device::bus_r));
+ map(0xfc31, 0xfc31).mirror(0x00c0).r("scsi_ctrl_in", FUNC(input_buffer_device::read));
map(0xfc32, 0xfc32).mirror(0x00c0).w(FUNC(econet_e01_device::hdc_select_w));
map(0xfc33, 0xfc33).mirror(0x00c0).w(FUNC(econet_e01_device::hdc_irq_enable_w));
}
@@ -241,15 +245,15 @@ void econet_e01_device::e01_mem(address_map &map)
void econet_e01_device::device_add_mconfig(machine_config &config)
{
// basic machine hardware
- M65C02(config, m_maincpu, XTAL(8'000'000)/4); // Rockwell R65C102P3
+ R65C102(config, m_maincpu, XTAL(8'000'000)); // Rockwell R65C102P3
m_maincpu->set_addrmap(AS_PROGRAM, &econet_e01_device::e01_mem);
MC146818(config, m_rtc, 32.768_kHz_XTAL);
m_rtc->irq().set(FUNC(econet_e01_device::rtc_irq_w));
// devices
- via6522_device &via(VIA6522(config, R6522_TAG, 8_MHz_XTAL / 4));
- via.writepa_handler().set("cent_data_out", FUNC(output_latch_device::bus_w));
+ via6522_device &via(R65C22(config, R6522_TAG, 8_MHz_XTAL / 4));
+ via.writepa_handler().set("cent_data_out", FUNC(output_latch_device::write));
via.irq_handler().set(FUNC(econet_e01_device::via_irq_w));
MC6854(config, m_adlc, 0);
@@ -269,7 +273,7 @@ void econet_e01_device::device_add_mconfig(machine_config &config)
}
software_list_device &softlist(SOFTWARE_LIST(config, "flop_ls_e01"));
- softlist.set_type("e01_flop", SOFTWARE_LIST_ORIGINAL_SYSTEM);
+ softlist.set_original("e01_flop");
CENTRONICS(config, m_centronics, centronics_devices, "printer");
m_centronics->ack_handler().set(R6522_TAG, FUNC(via6522_device::write_ca1));
@@ -400,6 +404,8 @@ econet_e01_device::econet_e01_device(const machine_config &mconfig, device_type
, m_floppy(*this, WD2793_TAG":%u", 0U)
, m_rom(*this, R65C102_TAG)
, m_centronics(*this, CENTRONICS_TAG)
+ , m_flap(*this, "FLAP")
+ , m_led(*this, "led_0")
, m_adlc_ie(0)
, m_hdc_ie(0)
, m_rtc_irq(CLEAR_LINE)
@@ -421,8 +427,10 @@ econet_e01_device::econet_e01_device(const machine_config &mconfig, device_type
void econet_e01_device::device_start()
{
+ m_led.resolve();
+
// allocate timers
- m_clk_timer = timer_alloc();
+ m_clk_timer = timer_alloc(FUNC(econet_e01_device::clk_tick), this);
// register for state saving
save_item(NAME(m_adlc_ie));
@@ -447,10 +455,10 @@ void econet_e01_device::device_reset()
//-------------------------------------------------
-// device_timer - handler timer events
+// clk_tick - update our clock output
//-------------------------------------------------
-void econet_e01_device::device_timer(emu_timer &timer, device_timer_id id, int param, void *ptr)
+TIMER_CALLBACK_MEMBER(econet_e01_device::clk_tick)
{
if (m_clk_en)
{
@@ -464,7 +472,7 @@ void econet_e01_device::device_timer(emu_timer &timer, device_timer_id id, int p
// read -
//-------------------------------------------------
-READ8_MEMBER( econet_e01_device::read )
+uint8_t econet_e01_device::read(offs_t offset)
{
uint8_t data;
@@ -485,7 +493,7 @@ READ8_MEMBER( econet_e01_device::read )
// write -
//-------------------------------------------------
-WRITE8_MEMBER( econet_e01_device::write )
+void econet_e01_device::write(offs_t offset, uint8_t data)
{
m_ram->pointer()[offset] = data;
}
@@ -495,9 +503,10 @@ WRITE8_MEMBER( econet_e01_device::write )
// eprom_r - ROM/RAM select read
//-------------------------------------------------
-READ8_MEMBER( econet_e01_device::ram_select_r )
+uint8_t econet_e01_device::ram_select_r()
{
- m_ram_en = true;
+ if (!machine().side_effects_disabled())
+ m_ram_en = true;
return 0;
}
@@ -507,7 +516,7 @@ READ8_MEMBER( econet_e01_device::ram_select_r )
// floppy_w - floppy control write
//-------------------------------------------------
-WRITE8_MEMBER( econet_e01_device::floppy_w )
+void econet_e01_device::floppy_w(uint8_t data)
{
/*
@@ -542,12 +551,12 @@ WRITE8_MEMBER( econet_e01_device::floppy_w )
m_fdc->dden_w(BIT(data, 4));
// floppy master reset
- if (!BIT(data, 5)) m_fdc->soft_reset();
+ m_fdc->mr_w(BIT(data, 5));
// TODO floppy test
// mode LED
- machine().output().set_value("led_0", BIT(data, 7));
+ m_led = BIT(data, 7);
}
@@ -555,9 +564,10 @@ WRITE8_MEMBER( econet_e01_device::floppy_w )
// network_irq_disable_r -
//-------------------------------------------------
-READ8_MEMBER( econet_e01_device::network_irq_disable_r )
+uint8_t econet_e01_device::network_irq_disable_r()
{
- network_irq_enable(0);
+ if (!machine().side_effects_disabled())
+ network_irq_enable(0);
return 0;
}
@@ -567,7 +577,7 @@ READ8_MEMBER( econet_e01_device::network_irq_disable_r )
// network_irq_disable_w -
//-------------------------------------------------
-WRITE8_MEMBER( econet_e01_device::network_irq_disable_w )
+void econet_e01_device::network_irq_disable_w(uint8_t data)
{
network_irq_enable(0);
}
@@ -577,9 +587,10 @@ WRITE8_MEMBER( econet_e01_device::network_irq_disable_w )
// network_irq_enable_r -
//-------------------------------------------------
-READ8_MEMBER( econet_e01_device::network_irq_enable_r )
+uint8_t econet_e01_device::network_irq_enable_r()
{
- network_irq_enable(1);
+ if (!machine().side_effects_disabled())
+ network_irq_enable(1);
return 0;
}
@@ -589,7 +600,7 @@ READ8_MEMBER( econet_e01_device::network_irq_enable_r )
// network_irq_enable_w -
//-------------------------------------------------
-WRITE8_MEMBER( econet_e01_device::network_irq_enable_w )
+void econet_e01_device::network_irq_enable_w(uint8_t data)
{
network_irq_enable(1);
}
@@ -599,11 +610,12 @@ WRITE8_MEMBER( econet_e01_device::network_irq_enable_w )
// hdc_data_r -
//-------------------------------------------------
-READ8_MEMBER( econet_e01_device::hdc_data_r )
+uint8_t econet_e01_device::hdc_data_r()
{
uint8_t data = m_scsi_data_in->read();
- m_scsibus->write_ack(1);
+ if (!machine().side_effects_disabled())
+ m_scsibus->write_ack(1);
return data;
}
@@ -613,7 +625,7 @@ READ8_MEMBER( econet_e01_device::hdc_data_r )
// hdc_data_w -
//-------------------------------------------------
-WRITE8_MEMBER( econet_e01_device::hdc_data_w )
+void econet_e01_device::hdc_data_w(uint8_t data)
{
m_scsi_data_out->write(data);
@@ -625,7 +637,7 @@ WRITE8_MEMBER( econet_e01_device::hdc_data_w )
// hdc_select_w -
//-------------------------------------------------
-WRITE8_MEMBER( econet_e01_device::hdc_select_w )
+void econet_e01_device::hdc_select_w(uint8_t data)
{
m_scsibus->write_sel(1);
}
@@ -635,53 +647,13 @@ WRITE8_MEMBER( econet_e01_device::hdc_select_w )
// hdc_irq_enable_w -
//-------------------------------------------------
-WRITE8_MEMBER( econet_e01_device::hdc_irq_enable_w )
+void econet_e01_device::hdc_irq_enable_w(uint8_t data)
{
hdc_irq_enable(BIT(data, 0));
}
//-------------------------------------------------
-// rtc_address_r -
-//-------------------------------------------------
-
-READ8_MEMBER( econet_e01_device::rtc_address_r )
-{
- return m_rtc->read(0);
-}
-
-
-//-------------------------------------------------
-// rtc_address_w -
-//-------------------------------------------------
-
-WRITE8_MEMBER( econet_e01_device::rtc_address_w )
-{
- m_rtc->write(0, data);
-}
-
-
-//-------------------------------------------------
-// rtc_data_r -
-//-------------------------------------------------
-
-READ8_MEMBER( econet_e01_device::rtc_data_r )
-{
- return m_rtc->read(1);
-}
-
-
-//-------------------------------------------------
-// rtc_data_w -
-//-------------------------------------------------
-
-WRITE8_MEMBER( econet_e01_device::rtc_data_w )
-{
- 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 e78f88b2f90..10d556e7700 100644
--- a/src/devices/bus/econet/e01.h
+++ b/src/devices/bus/econet/e01.h
@@ -14,7 +14,7 @@
#include "econet.h"
#include "bus/centronics/ctronics.h"
#include "bus/scsi/scsi.h"
-#include "cpu/m6502/m65c02.h"
+#include "cpu/m6502/r65c02.h"
#include "imagedev/floppy.h"
#include "machine/6522via.h"
#include "machine/buffer.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
@@ -42,49 +41,47 @@ protected:
econet_e01_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock, int variant);
// device-level overrides
- virtual void device_start() override;
- virtual void device_reset() override;
- virtual void device_timer(emu_timer &timer, device_timer_id id, int param, void *ptr) override;
+ virtual void device_start() override ATTR_COLD;
+ virtual void device_reset() override ATTR_COLD;
// optional information 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 const tiny_rom_entry *device_rom_region() const override ATTR_COLD;
+ virtual void device_add_mconfig(machine_config &config) override ATTR_COLD;
+ virtual ioport_constructor device_input_ports() const override ATTR_COLD;
// device_econet_interface overrides
virtual void econet_data(int state) override;
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 );
- DECLARE_READ8_MEMBER( read );
- DECLARE_WRITE8_MEMBER( write );
- DECLARE_READ8_MEMBER( ram_select_r );
- DECLARE_WRITE8_MEMBER( floppy_w );
- DECLARE_READ8_MEMBER( network_irq_disable_r );
- DECLARE_WRITE8_MEMBER( network_irq_disable_w );
- DECLARE_READ8_MEMBER( network_irq_enable_r );
- DECLARE_WRITE8_MEMBER( network_irq_enable_w );
- DECLARE_READ8_MEMBER( hdc_data_r );
- DECLARE_WRITE8_MEMBER( hdc_data_w );
- DECLARE_WRITE8_MEMBER( hdc_select_w );
- DECLARE_WRITE8_MEMBER( hdc_irq_enable_w );
- DECLARE_READ8_MEMBER( rtc_address_r );
- DECLARE_WRITE8_MEMBER( rtc_address_w );
- DECLARE_READ8_MEMBER( rtc_data_r );
- DECLARE_WRITE8_MEMBER( rtc_data_w );
-
- DECLARE_FLOPPY_FORMATS(floppy_formats_afs);
-
- required_device<m65c02_device> m_maincpu;
+ 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);
+
+ uint8_t read(offs_t offset);
+ void write(offs_t offset, uint8_t data);
+ uint8_t ram_select_r();
+ void floppy_w(uint8_t data);
+ uint8_t network_irq_disable_r();
+ void network_irq_disable_w(uint8_t data);
+ uint8_t network_irq_enable_r();
+ void network_irq_enable_w(uint8_t data);
+ uint8_t hdc_data_r();
+ void hdc_data_w(uint8_t data);
+ void hdc_select_w(uint8_t data);
+ void hdc_irq_enable_w(uint8_t data);
+
+ static void floppy_formats_afs(format_registration &fr);
+
+ required_device<r65c102_device> m_maincpu;
required_device<wd2793_device> m_fdc;
required_device<mc6854_device> m_adlc;
required_device<mc146818_device> m_rtc;
@@ -96,12 +93,15 @@ private:
required_device_array<floppy_connector, 2> m_floppy;
required_memory_region m_rom;
required_device<centronics_device> m_centronics;
+ required_ioport m_flap;
+
+ output_finder<> m_led;
inline void update_interrupts();
inline void network_irq_enable(int enabled);
inline void hdc_irq_enable(int enabled);
- void e01_mem(address_map &map);
+ void e01_mem(address_map &map) ATTR_COLD;
// interrupt state
int m_adlc_ie;
diff --git a/src/devices/bus/econet/econet.cpp b/src/devices/bus/econet/econet.cpp
index c027614f317..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_slot_card_interface(mconfig, device), 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 = global_alloc(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 baecd8df67a..d04a14c2215 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 ATTR_COLD;
+ virtual void device_stop() override ATTR_COLD;
+
+ 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
@@ -97,7 +99,7 @@ public:
}
// device-level overrides
- virtual void device_start() override;
+ virtual void device_start() override ATTR_COLD;
// inline configuration
template <typename T> void set_econet_tag(T &&tag) { m_econet.set_tag(std::forward<T>(tag)); }
@@ -112,14 +114,11 @@ private:
// ======================> device_econet_interface
-class device_econet_interface : public device_slot_card_interface
+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 d521d146325..05196ac2d49 100644
--- a/src/devices/bus/einstein/pipe/pipe.cpp
+++ b/src/devices/bus/einstein/pipe/pipe.cpp
@@ -32,7 +32,7 @@ DEFINE_DEVICE_TYPE(TATUNG_PIPE, tatung_pipe_device, "tatung_pipe", "Tatung Pipe
tatung_pipe_device::tatung_pipe_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) :
device_t(mconfig, TATUNG_PIPE, tag, owner, clock),
- device_slot_interface(mconfig, *this),
+ device_single_card_slot_interface<device_tatung_pipe_interface>(mconfig, *this),
m_program(*this, finder_base::DUMMY_TAG, -1),
m_io(*this, finder_base::DUMMY_TAG, -1),
m_card(nullptr),
@@ -79,27 +79,14 @@ void tatung_pipe_device::device_config_complete()
void tatung_pipe_device::device_start()
{
// get inserted module
- m_card = dynamic_cast<device_tatung_pipe_interface *>(get_card_device());
-
- // resolve callbacks
- m_int_handler.resolve_safe();
- m_nmi_handler.resolve_safe();
- m_reset_handler.resolve_safe();
-}
-
-//-------------------------------------------------
-// device_reset - device-specific reset
-//-------------------------------------------------
-
-void tatung_pipe_device::device_reset()
-{
+ m_card = get_card_device();
}
//-------------------------------------------------
// 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);
@@ -115,7 +102,7 @@ WRITE_LINE_MEMBER( tatung_pipe_device::host_int_w )
//-------------------------------------------------
device_tatung_pipe_interface::device_tatung_pipe_interface(const machine_config &mconfig, device_t &device) :
- device_slot_card_interface(mconfig, device)
+ device_interface(device, "tatungpipe")
{
m_slot = dynamic_cast<tatung_pipe_device *>(device.owner());
}
diff --git a/src/devices/bus/einstein/pipe/pipe.h b/src/devices/bus/einstein/pipe/pipe.h
index f0c32bd0043..bbb96af1d6a 100644
--- a/src/devices/bus/einstein/pipe/pipe.h
+++ b/src/devices/bus/einstein/pipe/pipe.h
@@ -51,7 +51,7 @@
class device_tatung_pipe_interface;
-class tatung_pipe_device : public device_t, public device_slot_interface
+class tatung_pipe_device : public device_t, public device_single_card_slot_interface<device_tatung_pipe_interface>
{
friend class device_tatung_pipe_interface;
public:
@@ -77,18 +77,17 @@ 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
virtual void device_config_complete() override;
- virtual void device_start() override;
- virtual void device_reset() override;
+ virtual void device_start() override ATTR_COLD;
required_address_space m_program;
required_address_space m_io;
@@ -102,7 +101,7 @@ private:
};
// class representing interface-specific live pipe device
-class device_tatung_pipe_interface : public device_slot_card_interface
+class device_tatung_pipe_interface : public device_interface
{
public:
// construction/destruction
diff --git a/src/devices/bus/einstein/pipe/silicon_disc.cpp b/src/devices/bus/einstein/pipe/silicon_disc.cpp
index b9017cd6e56..c0a29f304bd 100644
--- a/src/devices/bus/einstein/pipe/silicon_disc.cpp
+++ b/src/devices/bus/einstein/pipe/silicon_disc.cpp
@@ -87,8 +87,8 @@ void einstein_silicon_disc_device::device_reset()
// install i/o ports
io_space().install_device(0xf0, 0xff, *this, &einstein_silicon_disc_device::map);
io_space().install_readwrite_handler(0xfa, 0xfa, 0, 0, 0xff00,
- read8_delegate(FUNC(einstein_silicon_disc_device::ram_r), this),
- write8_delegate(FUNC(einstein_silicon_disc_device::ram_w), this));
+ read8sm_delegate(*this, FUNC(einstein_silicon_disc_device::ram_r)),
+ write8sm_delegate(*this, FUNC(einstein_silicon_disc_device::ram_w)));
}
@@ -96,25 +96,25 @@ void einstein_silicon_disc_device::device_reset()
// IMPLEMENTATION
//**************************************************************************
-WRITE8_MEMBER( einstein_silicon_disc_device::sector_low_w )
+void einstein_silicon_disc_device::sector_low_w(uint8_t data)
{
m_sector &= 0xff00;
m_sector |= data;
}
-WRITE8_MEMBER( einstein_silicon_disc_device::sector_high_w )
+void einstein_silicon_disc_device::sector_high_w(uint8_t data)
{
m_sector &= 0x00ff;
m_sector |= ((data & 0x07) << 8);
}
// a8 to a14 are used to specify the byte in a 128-byte sector
-READ8_MEMBER( einstein_silicon_disc_device::ram_r )
+uint8_t einstein_silicon_disc_device::ram_r(offs_t offset)
{
return m_ram[(m_sector * 0x80) | ((offset >> 8) & 0x7f)];
}
-WRITE8_MEMBER( einstein_silicon_disc_device::ram_w )
+void einstein_silicon_disc_device::ram_w(offs_t offset, uint8_t data)
{
m_ram[(m_sector * 0x80) | ((offset >> 8) & 0x7f)] = data;
}
diff --git a/src/devices/bus/einstein/pipe/silicon_disc.h b/src/devices/bus/einstein/pipe/silicon_disc.h
index dad8ad7c940..132414c04b5 100644
--- a/src/devices/bus/einstein/pipe/silicon_disc.h
+++ b/src/devices/bus/einstein/pipe/silicon_disc.h
@@ -8,8 +8,8 @@
***************************************************************************/
-#ifndef MAME_BUS_EINSTEIN_SILICON_DISC_H
-#define MAME_BUS_EINSTEIN_SILICON_DISC_H
+#ifndef MAME_BUS_EINSTEIN_PIPE_SILICON_DISC_H
+#define MAME_BUS_EINSTEIN_PIPE_SILICON_DISC_H
#pragma once
@@ -29,12 +29,12 @@ public:
einstein_silicon_disc_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;
- virtual void device_start() override;
- virtual void device_reset() override;
+ virtual const tiny_rom_entry *device_rom_region() const override ATTR_COLD;
+ virtual void device_start() override ATTR_COLD;
+ virtual void device_reset() override ATTR_COLD;
private:
- void map(address_map &map);
+ void map(address_map &map) ATTR_COLD;
required_memory_region m_rom;
required_memory_region m_bios;
@@ -42,13 +42,13 @@ private:
std::unique_ptr<uint8_t[]> m_ram;
uint16_t m_sector;
- DECLARE_READ8_MEMBER(ram_r);
- DECLARE_WRITE8_MEMBER(ram_w);
- DECLARE_WRITE8_MEMBER(sector_low_w);
- DECLARE_WRITE8_MEMBER(sector_high_w);
+ uint8_t ram_r(offs_t offset);
+ void ram_w(offs_t offset, uint8_t data);
+ void sector_low_w(uint8_t data);
+ void sector_high_w(uint8_t data);
};
// device type definition
DECLARE_DEVICE_TYPE(EINSTEIN_SILICON_DISC, einstein_silicon_disc_device)
-#endif // MAME_BUS_EINSTEIN_SILICON_DISC_H
+#endif // MAME_BUS_EINSTEIN_PIPE_SILICON_DISC_H
diff --git a/src/devices/bus/einstein/pipe/speculator.cpp b/src/devices/bus/einstein/pipe/speculator.cpp
index ed35973ab12..ae73b030577 100644
--- a/src/devices/bus/einstein/pipe/speculator.cpp
+++ b/src/devices/bus/einstein/pipe/speculator.cpp
@@ -97,18 +97,18 @@ void einstein_speculator_device::device_reset()
{
// ram: range 0x1f, 0x3f, 0x5f, 0x7f, 0x9f, 0xbf, 0xdf, 0xff
io_space().install_readwrite_handler(0x1f, 0x1f, 0, 0, 0xffe0,
- read8_delegate(FUNC(einstein_speculator_device::ram_r), this),
- write8_delegate(FUNC(einstein_speculator_device::ram_w), this));
+ read8sm_delegate(*this, FUNC(einstein_speculator_device::ram_r)),
+ write8sm_delegate(*this, FUNC(einstein_speculator_device::ram_w)));
// ram: range 0x60 - 0xff
io_space().install_readwrite_handler(0x60, 0x60, 0, 0, 0xff9f,
- read8_delegate(FUNC(einstein_speculator_device::ram_r), this),
- write8_delegate(FUNC(einstein_speculator_device::ram_w), this));
+ read8sm_delegate(*this, FUNC(einstein_speculator_device::ram_r)),
+ write8sm_delegate(*this, FUNC(einstein_speculator_device::ram_w)));
// tape read/nmi write register: range 0xff
io_space().install_readwrite_handler(0xff, 0xff, 0, 0, 0xff00,
- read8_delegate(FUNC(einstein_speculator_device::tape_r), this),
- write8_delegate(FUNC(einstein_speculator_device::nmi_w), this));
+ read8smo_delegate(*this, FUNC(einstein_speculator_device::tape_r)),
+ write8smo_delegate(*this, FUNC(einstein_speculator_device::nmi_w)));
}
@@ -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)
{
@@ -167,19 +167,19 @@ offs_t einstein_speculator_device::address_translate(offs_t offset)
return (ra3 << 3) | (ra2 << 2) | (ra1 << 1) | (ra0 << 0);
}
-READ8_MEMBER( einstein_speculator_device::ram_r )
+uint8_t einstein_speculator_device::ram_r(offs_t offset)
{
offs_t addr = ((offset << 4) & 0x7f) | address_translate(offset);
return m_ram[addr];
}
-WRITE8_MEMBER( einstein_speculator_device::ram_w )
+void einstein_speculator_device::ram_w(offs_t offset, uint8_t data)
{
offs_t addr = ((offset << 4) & 0x7f) | address_translate(offset);
m_ram[addr] = data;
}
-READ8_MEMBER( einstein_speculator_device::tape_r )
+uint8_t einstein_speculator_device::tape_r()
{
// 7654321- unknown
// -------0 cassette input
@@ -187,9 +187,9 @@ READ8_MEMBER( einstein_speculator_device::tape_r )
return m_cassette->input() > 0.0038 ? 1 : 0;
}
-WRITE8_MEMBER( einstein_speculator_device::nmi_w )
+void einstein_speculator_device::nmi_w(uint8_t data)
{
- logerror("nmi_w offset %04x data %02x\n", offset, data);
+ logerror("nmi_w data %02x\n", data);
// 76543--- unknown
// -----2-- nmi enable?
diff --git a/src/devices/bus/einstein/pipe/speculator.h b/src/devices/bus/einstein/pipe/speculator.h
index bdbb4476e3e..c25933622ba 100644
--- a/src/devices/bus/einstein/pipe/speculator.h
+++ b/src/devices/bus/einstein/pipe/speculator.h
@@ -34,18 +34,18 @@ public:
virtual void int_w(int state) override;
- DECLARE_READ8_MEMBER(ram_r);
- DECLARE_WRITE8_MEMBER(ram_w);
- DECLARE_READ8_MEMBER(tape_r);
- DECLARE_WRITE8_MEMBER(nmi_w);
+ uint8_t ram_r(offs_t offset);
+ void ram_w(offs_t offset, uint8_t data);
+ 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;
- virtual void device_start() override;
- virtual void device_reset() override;
+ 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:
offs_t address_translate(offs_t offset);
diff --git a/src/devices/bus/einstein/pipe/tk02.cpp b/src/devices/bus/einstein/pipe/tk02.cpp
index 311c3099011..4b14e9b3391 100644
--- a/src/devices/bus/einstein/pipe/tk02.cpp
+++ b/src/devices/bus/einstein/pipe/tk02.cpp
@@ -23,7 +23,7 @@ DEFINE_DEVICE_TYPE(TK02_80COL, tk02_device, "tk02", "TK02 80 Column Monochrome U
void tk02_device::map(address_map &map)
{
-// AM_RANGE(0x00, 0x07) AM_SELECT(0xff00) AM_READWRITE(ram_r, ram_w) // no AM_SELECT (or AM_MASK) support here
+// map(0x00, 0x07).select(0xff00).rw(FUNC(tk02_device::ram_r), FUNC(tk02_device::ram_w)); // no select() (or mask()) support here
map(0x08, 0x08).mirror(0xff00).w(m_crtc, FUNC(mc6845_device::address_w));
map(0x09, 0x09).mirror(0xff00).w(m_crtc, FUNC(mc6845_device::register_w));
map(0x0c, 0x0c).mirror(0xff00).r(FUNC(tk02_device::status_r));
@@ -111,7 +111,7 @@ void tk02_device::device_add_mconfig(machine_config &config)
m_crtc->set_screen("mono");
m_crtc->set_show_border_area(false);
m_crtc->set_char_width(8);
- m_crtc->set_update_row_callback(FUNC(tk02_device::crtc_update_row), this);
+ m_crtc->set_update_row_callback(FUNC(tk02_device::crtc_update_row));
m_crtc->out_de_callback().set(FUNC(tk02_device::de_w));
TATUNG_PIPE(config, m_pipe, DERIVED_CLOCK(1, 1), tatung_pipe_cards, nullptr);
@@ -160,7 +160,7 @@ void tk02_device::device_start()
void tk02_device::device_reset()
{
io_space().install_device(0x40, 0x4f, *this, &tk02_device::map);
- io_space().install_readwrite_handler(0x40, 0x47, 0, 0, 0xff00, read8_delegate(FUNC(tk02_device::ram_r), this), write8_delegate(FUNC(tk02_device::ram_w), this));
+ io_space().install_readwrite_handler(0x40, 0x47, 0, 0, 0xff00, read8sm_delegate(*this, FUNC(tk02_device::ram_r)), write8sm_delegate(*this, FUNC(tk02_device::ram_w)));
}
@@ -185,35 +185,35 @@ MC6845_UPDATE_ROW( tk02_device::crtc_update_row )
if (i == cursor_x)
data ^= 0xff;
- bitmap.pix32(y, i * 8 + 0) = pen[BIT(data, 7)];
- bitmap.pix32(y, i * 8 + 1) = pen[BIT(data, 6)];
- bitmap.pix32(y, i * 8 + 2) = pen[BIT(data, 5)];
- bitmap.pix32(y, i * 8 + 3) = pen[BIT(data, 4)];
- bitmap.pix32(y, i * 8 + 4) = pen[BIT(data, 3)];
- bitmap.pix32(y, i * 8 + 5) = pen[BIT(data, 2)];
- bitmap.pix32(y, i * 8 + 6) = pen[BIT(data, 1)];
- bitmap.pix32(y, i * 8 + 7) = pen[BIT(data, 0)];
+ bitmap.pix(y, i * 8 + 0) = pen[BIT(data, 7)];
+ bitmap.pix(y, i * 8 + 1) = pen[BIT(data, 6)];
+ bitmap.pix(y, i * 8 + 2) = pen[BIT(data, 5)];
+ bitmap.pix(y, i * 8 + 3) = pen[BIT(data, 4)];
+ bitmap.pix(y, i * 8 + 4) = pen[BIT(data, 3)];
+ bitmap.pix(y, i * 8 + 5) = pen[BIT(data, 2)];
+ bitmap.pix(y, i * 8 + 6) = pen[BIT(data, 1)];
+ bitmap.pix(y, i * 8 + 7) = pen[BIT(data, 0)];
}
}
-WRITE_LINE_MEMBER( tk02_device::de_w )
+void tk02_device::de_w(int state)
{
m_de = state;
}
// lower 3 bits of address define a 256-byte "row"
// upper 8 bits define the offset in the row
-READ8_MEMBER( tk02_device::ram_r )
+uint8_t tk02_device::ram_r(offs_t offset)
{
return m_ram[((offset & 0x07) << 8) | ((offset >> 8) & 0xff)];
}
-WRITE8_MEMBER( tk02_device::ram_w )
+void tk02_device::ram_w(offs_t offset, uint8_t data)
{
m_ram[((offset & 0x07) << 8) | ((offset >> 8) & 0xff)] = data;
}
-READ8_MEMBER( tk02_device::status_r )
+uint8_t tk02_device::status_r()
{
// 7654---- unused
// ----3--- link M001
diff --git a/src/devices/bus/einstein/pipe/tk02.h b/src/devices/bus/einstein/pipe/tk02.h
index 8782def764c..5b4c05e4c18 100644
--- a/src/devices/bus/einstein/pipe/tk02.h
+++ b/src/devices/bus/einstein/pipe/tk02.h
@@ -6,8 +6,8 @@
***************************************************************************/
-#ifndef MAME_BUS_EINSTEIN_TK02_H
-#define MAME_BUS_EINSTEIN_TK02_H
+#ifndef MAME_BUS_EINSTEIN_PIPE_TK02_H
+#define MAME_BUS_EINSTEIN_PIPE_TK02_H
#pragma once
@@ -29,20 +29,20 @@ public:
tk02_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;
- 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;
+ virtual const tiny_rom_entry *device_rom_region() const override ATTR_COLD;
+ virtual void device_add_mconfig(machine_config &config) override ATTR_COLD;
+ virtual ioport_constructor device_input_ports() const override ATTR_COLD;
+ virtual void device_start() override ATTR_COLD;
+ virtual void device_reset() override ATTR_COLD;
private:
- void map(address_map &map);
+ void map(address_map &map) ATTR_COLD;
- DECLARE_WRITE_LINE_MEMBER(de_w);
+ void de_w(int state);
- DECLARE_READ8_MEMBER(ram_r);
- DECLARE_WRITE8_MEMBER(ram_w);
- DECLARE_READ8_MEMBER(status_r);
+ uint8_t ram_r(offs_t offset);
+ void ram_w(offs_t offset, uint8_t data);
+ uint8_t status_r();
MC6845_UPDATE_ROW(crtc_update_row);
@@ -59,4 +59,4 @@ private:
// device type definition
DECLARE_DEVICE_TYPE(TK02_80COL, tk02_device)
-#endif // MAME_BUS_EINSTEIN_TK02_H
+#endif // MAME_BUS_EINSTEIN_PIPE_TK02_H
diff --git a/src/devices/bus/einstein/userport/mouse.h b/src/devices/bus/einstein/userport/mouse.h
index dad8200d06b..61c57f2328f 100644
--- a/src/devices/bus/einstein/userport/mouse.h
+++ b/src/devices/bus/einstein/userport/mouse.h
@@ -27,8 +27,8 @@ public:
einstein_mouse_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 ioport_constructor device_input_ports() const override ATTR_COLD;
+ virtual void device_start() override ATTR_COLD;
virtual uint8_t read() override;
diff --git a/src/devices/bus/einstein/userport/speech.h b/src/devices/bus/einstein/userport/speech.h
index 4c62b24e842..92c498ac590 100644
--- a/src/devices/bus/einstein/userport/speech.h
+++ b/src/devices/bus/einstein/userport/speech.h
@@ -28,9 +28,9 @@ public:
einstein_speech_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;
- virtual void device_add_mconfig(machine_config &config) override;
- virtual void device_start() override;
+ virtual const tiny_rom_entry *device_rom_region() const override ATTR_COLD;
+ virtual void device_add_mconfig(machine_config &config) override ATTR_COLD;
+ virtual void device_start() override ATTR_COLD;
virtual uint8_t read() override;
virtual void write(uint8_t data) override;
diff --git a/src/devices/bus/einstein/userport/userport.cpp b/src/devices/bus/einstein/userport/userport.cpp
index 419c24d94d4..dac68cc1181 100644
--- a/src/devices/bus/einstein/userport/userport.cpp
+++ b/src/devices/bus/einstein/userport/userport.cpp
@@ -31,7 +31,7 @@ DEFINE_DEVICE_TYPE(EINSTEIN_USERPORT, einstein_userport_device, "einstein_userpo
einstein_userport_device::einstein_userport_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) :
device_t(mconfig, EINSTEIN_USERPORT, tag, owner, clock),
- device_slot_interface(mconfig, *this),
+ device_single_card_slot_interface<device_einstein_userport_interface>(mconfig, *this),
m_card(nullptr),
m_bstb_handler(*this)
{
@@ -51,18 +51,7 @@ einstein_userport_device::~einstein_userport_device()
void einstein_userport_device::device_start()
{
- // resolve callbacks
- m_bstb_handler.resolve_safe();
-
- m_card = dynamic_cast<device_einstein_userport_interface *>(get_card_device());
-}
-
-//-------------------------------------------------
-// device_reset - device-specific reset
-//-------------------------------------------------
-
-void einstein_userport_device::device_reset()
-{
+ m_card = get_card_device();
}
@@ -70,7 +59,7 @@ void einstein_userport_device::device_reset()
// I/O PORTS
//**************************************************************************
-READ8_MEMBER( einstein_userport_device::read )
+uint8_t einstein_userport_device::read()
{
if (m_card)
return m_card->read();
@@ -78,13 +67,13 @@ READ8_MEMBER( einstein_userport_device::read )
return 0xff;
}
-WRITE8_MEMBER( einstein_userport_device::write )
+void einstein_userport_device::write(uint8_t data)
{
if (m_card)
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);
@@ -100,7 +89,7 @@ WRITE_LINE_MEMBER( einstein_userport_device::brdy_w )
//-------------------------------------------------
device_einstein_userport_interface::device_einstein_userport_interface(const machine_config &mconfig, device_t &device) :
- device_slot_card_interface(mconfig, device)
+ device_interface(device, "einsteinuser")
{
m_slot = dynamic_cast<einstein_userport_device *>(device.owner());
}
diff --git a/src/devices/bus/einstein/userport/userport.h b/src/devices/bus/einstein/userport/userport.h
index f5bd8dcfeb3..85ca52311bd 100644
--- a/src/devices/bus/einstein/userport/userport.h
+++ b/src/devices/bus/einstein/userport/userport.h
@@ -32,7 +32,7 @@ class device_einstein_userport_interface;
// supported devices
void einstein_userport_cards(device_slot_interface &device);
-class einstein_userport_device : public device_t, public device_slot_interface
+class einstein_userport_device : public device_t, public device_single_card_slot_interface<device_einstein_userport_interface>
{
public:
// construction/destruction
@@ -52,16 +52,15 @@ 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); }
- DECLARE_READ8_MEMBER( read );
- DECLARE_WRITE8_MEMBER (write );
- DECLARE_WRITE_LINE_MEMBER( brdy_w );
+ uint8_t read();
+ void write(uint8_t data);
+ void brdy_w(int state);
protected:
// device-level overrides
- virtual void device_start() override;
- virtual void device_reset() override;
+ virtual void device_start() override ATTR_COLD;
device_einstein_userport_interface *m_card;
@@ -70,7 +69,7 @@ private:
};
// class representing interface-specific live userport device
-class device_einstein_userport_interface : public device_slot_card_interface
+class device_einstein_userport_interface : public device_interface
{
public:
// construction/destruction
diff --git a/src/devices/bus/ekara/rom.cpp b/src/devices/bus/ekara/rom.cpp
index f55fd325d2a..a6e5523e84c 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)
{
}
@@ -66,22 +77,22 @@ ekara_rom_i2c_24lc02_gc0010_device::ekara_rom_i2c_24lc02_gc0010_device(const mac
// plain
-READ8_MEMBER(ekara_rom_plain_device::read_cart)
+uint8_t ekara_rom_plain_device::read_cart(offs_t offset)
{
- return read_rom(space, offset, mem_mask);
+ return read_rom(offset);
}
-READ8_MEMBER(ekara_rom_plain_device::read_rom)
+uint8_t ekara_rom_plain_device::read_rom(offs_t offset)
{
return m_rom[offset & (m_rom_size-1)];
}
-WRITE8_MEMBER(ekara_rom_plain_device::write_cart)
+void ekara_rom_plain_device::write_cart(offs_t offset, uint8_t data)
{
- write_rom(space, offset, data, mem_mask);
+ write_rom(offset, data);
}
-WRITE8_MEMBER(ekara_rom_plain_device::write_rom)
+void ekara_rom_plain_device::write_rom(offs_t offset, uint8_t data)
{
logerror("ekara_rom_plain_device::write_rom %08x %02x\n", offset, data);
}
@@ -98,30 +109,50 @@ bool ekara_rom_i2c_base_device::is_write_access_not_rom(void)
return (m_buscontrol[0] & 0x08) ? true : false;
}
-WRITE8_MEMBER(ekara_rom_i2c_base_device::write_bus_control)
+void ekara_rom_i2c_base_device::write_bus_control(offs_t offset, uint8_t data)
{
logerror("ekara_rom_i2c_base_device::write_bus_control %08x %02x\n", offset, data);
m_buscontrol[offset] = data;
}
-WRITE8_MEMBER(ekara_rom_i2c_base_device::write_rom)
+void ekara_rom_i2c_base_device::write_rom(offs_t offset, uint8_t data)
{
- logerror("ekara_rom_i2c_base_device::write_rom %08x %02x\n", offset, data);
+ if (is_write_access_not_rom())
+ {
+ if (offset == 0x3fffff)
+ write_extra(offset,data);
+ else
+ logerror("ekara_rom_i2c_base_device::write_rom %08x %02x\n", offset, data);
+ }
+ else
+ {
+ logerror("ekara_rom_i2c_base_device::write_rom %08x %02x\n", offset, data);
+ }
}
-READ8_MEMBER(ekara_rom_i2c_base_device::read_rom)
+uint8_t ekara_rom_i2c_base_device::read_rom(offs_t offset)
{
- return m_rom[offset & (m_rom_size - 1)];
+ if (is_read_access_not_rom())
+ {
+ if (offset == 0x5fffff)
+ return read_extra(offset);
+ else
+ return m_rom[offset & (m_rom_size - 1)];
+ }
+ else
+ {
+ return m_rom[offset & (m_rom_size - 1)];
+ }
}
-READ8_MEMBER(ekara_rom_i2c_base_device::read_extra)
+uint8_t ekara_rom_i2c_base_device::read_extra(offs_t offset)
{
logerror("ekara_rom_i2c_base_device::read_extra %08x\n", offset);
return (m_i2cmem->read_sda() & 1) ? 0xff : 0x00;
}
-WRITE8_MEMBER(ekara_rom_i2c_base_device::write_extra)
+void ekara_rom_i2c_base_device::write_extra(offs_t offset, uint8_t data)
{
logerror("ekara_rom_i2c_base_device::write_extra %08x %02x\n", offset, data);
@@ -148,21 +179,21 @@ bool ekara_rom_i2c_24c08_epitch_device::is_write_access_not_rom(void)
void ekara_rom_i2c_24c08_epitch_device::device_add_mconfig(machine_config &config)
{
- I2CMEM(config, "i2cmem", 0).set_page_size(16).set_data_size(0x400); // 24C08
+ I2C_24C08(config, "i2cmem", 0);
}
// i2c 24lc04
void ekara_rom_i2c_24lc04_device::device_add_mconfig(machine_config &config)
{
- I2CMEM(config, "i2cmem", 0).set_page_size(16).set_data_size(0x200); // 24LC04
+ I2C_24C04(config, "i2cmem", 0); // 24LC04
}
// i2c 24lc02
void ekara_rom_i2c_24lc02_device::device_add_mconfig(machine_config &config)
{
- I2CMEM(config, "i2cmem", 0).set_page_size(16).set_data_size(0x100); // 24LC02
+ I2C_24C02(config, "i2cmem", 0); // 24LC02
}
// i2c 24lc02 with direct IO port access
@@ -177,27 +208,27 @@ bool ekara_rom_i2c_24lc02_gc0010_device::is_write_access_not_rom(void)
return false;
}
-READ8_MEMBER(ekara_rom_i2c_24lc02_gc0010_device::read_extra)
+uint8_t ekara_rom_i2c_24lc02_gc0010_device::read_extra(offs_t offset)
{
return 0;
}
-WRITE8_MEMBER(ekara_rom_i2c_24lc02_gc0010_device::write_extra)
+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();
}
@@ -206,10 +237,15 @@ READ_LINE_MEMBER(ekara_rom_i2c_24lc02_gc0010_device::read_sda )
void ekara_rom_i2c_24lc02_gc0010_device::device_add_mconfig(machine_config &config)
{
- I2CMEM(config, "i2cmem", 0)/*.set_page_size(16)*/.set_data_size(0x100); // 24LC02
+ I2C_24C02(config, "i2cmem", 0); // 24LC02
}
+void ekara_rom_i2c_24lc08_evio_device::device_add_mconfig(machine_config &config)
+{
+ I2C_24C08(config, "i2cmem", 0);
+}
+
/*-------------------------------------------------
slot interface
-------------------------------------------------*/
@@ -221,5 +257,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 76c5ed45e46..0c965fba7b7 100644
--- a/src/devices/bus/ekara/rom.h
+++ b/src/devices/bus/ekara/rom.h
@@ -18,14 +18,14 @@ public:
ekara_rom_plain_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
// reading and writing
- virtual DECLARE_READ8_MEMBER(read_cart) override;
- virtual DECLARE_WRITE8_MEMBER(write_cart) override;
+ virtual uint8_t read_cart(offs_t offset) override;
+ virtual void write_cart(offs_t offset, uint8_t data) override;
- virtual DECLARE_READ8_MEMBER(read_extra) override { return 0xff; };
- virtual DECLARE_WRITE8_MEMBER(write_extra) override { };
+ virtual uint8_t read_extra(offs_t offset) override { return 0xff; }
+ virtual void write_extra(offs_t offset, uint8_t data) override { }
- virtual READ8_MEMBER(read_rom);
- virtual WRITE8_MEMBER(write_rom);
+ virtual uint8_t read_rom(offs_t offset);
+ virtual void write_rom(offs_t offset, uint8_t data);
protected:
ekara_rom_plain_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock);
@@ -47,15 +47,15 @@ protected:
ekara_rom_i2c_base_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock);
// reading and writing
- virtual READ8_MEMBER(read_rom) override;
- virtual WRITE8_MEMBER(write_rom) override;
+ virtual uint8_t read_rom(offs_t offset) override;
+ virtual void write_rom(offs_t offset, uint8_t data) override;
optional_device<i2cmem_device> m_i2cmem;
- virtual DECLARE_READ8_MEMBER(read_extra) override;
- virtual DECLARE_WRITE8_MEMBER(write_extra) override;
+ virtual uint8_t read_extra(offs_t offset) override;
+ virtual void write_extra(offs_t offset, uint8_t data) override;
- virtual DECLARE_WRITE8_MEMBER(write_bus_control) override;
+ virtual void write_bus_control(offs_t offset, uint8_t data) override;
virtual bool is_read_access_not_rom(void) override;
virtual bool is_write_access_not_rom(void) override;
@@ -76,7 +76,7 @@ protected:
virtual bool is_read_access_not_rom(void) override;
virtual bool is_write_access_not_rom(void) override;
- virtual void device_add_mconfig(machine_config &config) override;
+ virtual void device_add_mconfig(machine_config &config) override ATTR_COLD;
};
@@ -89,7 +89,7 @@ public:
ekara_rom_i2c_24lc04_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_add_mconfig(machine_config &config) override ATTR_COLD;
};
// ======================> ekara_rom_i2c_24lc02_device
@@ -101,7 +101,7 @@ public:
ekara_rom_i2c_24lc02_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_add_mconfig(machine_config &config) override ATTR_COLD;
};
@@ -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:
- virtual void device_add_mconfig(machine_config &config) override;
+ 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 ATTR_COLD;
bool is_read_access_not_rom(void) override;
bool is_write_access_not_rom(void) override;
- DECLARE_READ8_MEMBER(read_extra) override;
- DECLARE_WRITE8_MEMBER(write_extra) override;
- DECLARE_WRITE_LINE_MEMBER(write_sda) override;
- DECLARE_WRITE_LINE_MEMBER(write_scl) override;
- DECLARE_READ_LINE_MEMBER(read_sda ) override;
+ uint8_t read_extra(offs_t offset) override;
+ void write_extra(offs_t offset, uint8_t data) 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 ATTR_COLD;
+
};
+
// 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 5140e3f28ab..33f4e087fa4 100644
--- a/src/devices/bus/ekara/slot.cpp
+++ b/src/devices/bus/ekara/slot.cpp
@@ -18,10 +18,10 @@ DEFINE_DEVICE_TYPE(EKARA_CART_SLOT, ekara_cart_slot_device, "ekara_cart_slot", "
// device_ekara_cart_interface - constructor
//-------------------------------------------------
-device_ekara_cart_interface::device_ekara_cart_interface(const machine_config &mconfig, device_t &device)
- : device_slot_card_interface(mconfig, device),
- m_rom(nullptr),
- m_rom_size(0)
+device_ekara_cart_interface::device_ekara_cart_interface(const machine_config &mconfig, device_t &device) :
+ device_interface(device, "ekaracart"),
+ m_rom(nullptr),
+ m_rom_size(0)
{
}
@@ -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;
}
}
@@ -56,8 +56,8 @@ void device_ekara_cart_interface::rom_alloc(uint32_t size, const char *tag)
//-------------------------------------------------
ekara_cart_slot_device::ekara_cart_slot_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) :
device_t(mconfig, EKARA_CART_SLOT, tag, owner, clock),
- device_image_interface(mconfig, *this),
- device_slot_interface(mconfig, *this),
+ device_cartrom_image_interface(mconfig, *this),
+ device_single_card_slot_interface<device_ekara_cart_interface>(mconfig, *this),
m_type(EKARA_PLAIN),
m_cart(nullptr)
{
@@ -77,7 +77,7 @@ ekara_cart_slot_device::~ekara_cart_slot_device()
void ekara_cart_slot_device::device_start()
{
- m_cart = dynamic_cast<device_ekara_cart_interface *>(get_card_device());
+ m_cart = get_card_device();
}
//-------------------------------------------------
@@ -104,7 +104,7 @@ static int ekara_get_pcb_id(const char *slot)
{
for (auto & elem : slot_list)
{
- if (!core_stricmp(elem.slot_option, slot))
+ if (!strcmp(elem.slot_option, slot))
return elem.pcb_id;
}
@@ -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());
}
@@ -184,17 +181,16 @@ std::string ekara_cart_slot_device::get_default_card_software(get_default_card_s
{
if (hook.image_file())
{
- const char *slot_string;
- uint32_t len = hook.image_file()->size();
+ uint64_t len;
+ hook.image_file()->length(len); // FIXME: check error return, guard against excessively large files
std::vector<uint8_t> rom(len);
- int type;
- hook.image_file()->read(&rom[0], len);
+ /*auto const [err, actual] =*/ read(*hook.image_file(), &rom[0], len); // FIXME: check error return or read returning short
- type = get_cart_type(&rom[0], len);
- slot_string = ekara_get_slot(type);
+ int const type = get_cart_type(&rom[0], len);
+ char const *const slot_string = ekara_get_slot(type);
- printf("type: %s\n", slot_string);
+ //printf("type: %s\n", slot_string);
return std::string(slot_string);
}
@@ -206,45 +202,45 @@ std::string ekara_cart_slot_device::get_default_card_software(get_default_card_s
read
-------------------------------------------------*/
-READ8_MEMBER(ekara_cart_slot_device::read_cart)
+uint8_t ekara_cart_slot_device::read_cart(offs_t offset)
{
- return m_cart->read_cart(space, offset);
+ return m_cart->read_cart(offset);
}
/*-------------------------------------------------
write
-------------------------------------------------*/
-WRITE8_MEMBER(ekara_cart_slot_device::write_cart)
+void ekara_cart_slot_device::write_cart(offs_t offset, uint8_t data)
{
- m_cart->write_cart(space, offset, data);
+ m_cart->write_cart(offset, data);
}
/*-------------------------------------------------
read extra
-------------------------------------------------*/
-READ8_MEMBER(ekara_cart_slot_device::read_extra)
+uint8_t ekara_cart_slot_device::read_extra(offs_t offset)
{
- return m_cart->read_extra(space, offset);
+ return m_cart->read_extra(offset);
}
/*-------------------------------------------------
write extra
-------------------------------------------------*/
-WRITE8_MEMBER(ekara_cart_slot_device::write_extra)
+void ekara_cart_slot_device::write_extra(offs_t offset, uint8_t data)
{
- m_cart->write_extra(space, offset, data);
+ m_cart->write_extra(offset, data);
}
/*-------------------------------------------------
write control
-------------------------------------------------*/
-WRITE8_MEMBER(ekara_cart_slot_device::write_bus_control)
+void ekara_cart_slot_device::write_bus_control(offs_t offset, uint8_t data)
{
- m_cart->write_bus_control(space, offset, data);
+ m_cart->write_bus_control(offset, data);
}
bool ekara_cart_slot_device::is_read_access_not_rom(void)
@@ -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 945a5175d4b..33db9fb8be4 100644
--- a/src/devices/bus/ekara/slot.h
+++ b/src/devices/bus/ekara/slot.h
@@ -5,7 +5,7 @@
#pragma once
-#include "softlist_dev.h"
+#include "imagedev/cartrom.h"
/***************************************************************************
TYPE DEFINITIONS
@@ -23,30 +23,30 @@ enum
// ======================> device_ekara_cart_interface
-class device_ekara_cart_interface : public device_slot_card_interface
+class device_ekara_cart_interface : public device_interface
{
public:
// construction/destruction
virtual ~device_ekara_cart_interface();
// reading and writing
- virtual DECLARE_READ8_MEMBER(read_cart) { return 0xff; }
- virtual DECLARE_WRITE8_MEMBER(write_cart) { }
+ virtual uint8_t read_cart(offs_t offset) { return 0xff; }
+ virtual void write_cart(offs_t offset, uint8_t data) { }
- virtual DECLARE_READ8_MEMBER(read_extra) { return 0xff; }
- virtual DECLARE_WRITE8_MEMBER(write_extra) { }
+ 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 DECLARE_WRITE8_MEMBER(write_bus_control) { }
+ 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; }
@@ -61,8 +61,8 @@ protected:
// ======================> ekara_cart_slot_device
class ekara_cart_slot_device : public device_t,
- public device_image_interface,
- public device_slot_interface
+ public device_cartrom_image_interface,
+ public device_single_card_slot_interface<device_ekara_cart_interface>
{
public:
// construction/destruction
@@ -80,48 +80,42 @@ 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 const software_list_loader &get_software_list_loader() const override { return rom_software_list_loader::instance(); }
- int get_type() { return m_type; }
- static int get_cart_type(const uint8_t *ROM, uint32_t len);
+ 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"; }
- virtual iodevice_t image_type() const override { return IO_CARTSLOT; }
- virtual bool is_readable() const override { return 1; }
- virtual bool is_writeable() const override { return 0; }
- virtual bool is_creatable() const override { return 0; }
- virtual bool must_be_loaded() const override { return 0; }
- virtual bool is_reset_on_load() const override { return 1; }
- virtual const char *image_interface() const override { return "ekara_cart"; }
- virtual const char *file_extensions() const 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; }
+ static int get_cart_type(const uint8_t *ROM, uint32_t len);
+
// reading and writing
- virtual DECLARE_READ8_MEMBER(read_cart);
- virtual DECLARE_WRITE8_MEMBER(write_cart);
+ uint8_t read_cart(offs_t offset);
+ void write_cart(offs_t offset, uint8_t data);
- virtual DECLARE_READ8_MEMBER(read_extra);
- virtual DECLARE_WRITE8_MEMBER(write_extra);
+ uint8_t read_extra(offs_t offset);
+ 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 );
+ void write_sda(int state);
+ void write_scl(int state);
+ //void write_wc(int state);
+ int read_sda();
- virtual DECLARE_WRITE8_MEMBER(write_bus_control);
+ void write_bus_control(offs_t offset, uint8_t data);
- virtual bool is_read_access_not_rom(void);
- virtual bool is_write_access_not_rom(void);
+ bool is_read_access_not_rom(void);
+ bool is_write_access_not_rom(void);
bool has_cart() { return m_cart ? true : false; }
protected:
- // device-level overrides
- virtual void device_start() override;
+ // device_t implementation
+ virtual void device_start() override ATTR_COLD;
int m_type;
device_ekara_cart_interface* m_cart;
@@ -134,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/abr.cpp b/src/devices/bus/electron/cart/abr.cpp
index 1d2455e56c1..0c82ca65782 100644
--- a/src/devices/bus/electron/cart/abr.cpp
+++ b/src/devices/bus/electron/cart/abr.cpp
@@ -39,6 +39,9 @@ void electron_abr_device::device_start()
{
m_bank_locked[0] = false;
m_bank_locked[1] = false;
+
+ // register for save states
+ save_item(NAME(m_bank_locked));
}
diff --git a/src/devices/bus/electron/cart/abr.h b/src/devices/bus/electron/cart/abr.h
index 3ef92c95a8d..bcb5fd9647b 100644
--- a/src/devices/bus/electron/cart/abr.h
+++ b/src/devices/bus/electron/cart/abr.h
@@ -29,7 +29,7 @@ public:
protected:
// device-level overrides
- virtual void device_start() override;
+ virtual void device_start() override ATTR_COLD;
// electron_cart_interface overrides
virtual uint8_t read(offs_t offset, int infc, int infd, int romqa, int oe, int oe2) override;
diff --git a/src/devices/bus/electron/cart/ap34.cpp b/src/devices/bus/electron/cart/ap34.cpp
index 694df390266..ac1188b8f54 100644
--- a/src/devices/bus/electron/cart/ap34.cpp
+++ b/src/devices/bus/electron/cart/ap34.cpp
@@ -7,15 +7,15 @@
http://chrisacorns.computinghistory.org.uk/8bit_Upgrades/PRES_AP3A.html
TODO:
- - AP4 (DFS) is unreliable, maybe WD1770 reset issue to be investigated
- add spare ROM slot in AP3 and AP4, not AP3/4
**********************************************************************/
-
#include "emu.h"
#include "ap34.h"
+#include "formats/acorn_dsk.h"
+
//**************************************************************************
// DEVICE DEFINITIONS
@@ -25,14 +25,16 @@ DEFINE_DEVICE_TYPE(ELECTRON_AP34, electron_ap34_device, "electron_ap34", "P.R.E.
//-------------------------------------------------
-// MACHINE_DRIVER( ap34 )
+// FLOPPY_FORMATS( ap34 )
//-------------------------------------------------
-FLOPPY_FORMATS_MEMBER(electron_ap34_device::floppy_formats)
- FLOPPY_ACORN_SSD_FORMAT,
- FLOPPY_ACORN_DSD_FORMAT,
- FLOPPY_ACORN_ADFS_OLD_FORMAT
-FLOPPY_FORMATS_END0
+void electron_ap34_device::floppy_formats(format_registration &fr)
+{
+ fr.add_mfm_containers();
+ fr.add(FLOPPY_ACORN_SSD_FORMAT);
+ fr.add(FLOPPY_ACORN_DSD_FORMAT);
+ fr.add(FLOPPY_ACORN_ADFS_OLD_FORMAT);
+}
void ap34_floppies(device_slot_interface &device)
{
@@ -48,8 +50,8 @@ void electron_ap34_device::device_add_mconfig(machine_config &config)
{
/* fdc */
WD1770(config, m_fdc, DERIVED_CLOCK(1, 2));
- FLOPPY_CONNECTOR(config, m_floppy0, ap34_floppies, "525qd", electron_ap34_device::floppy_formats).enable_sound(true);
- FLOPPY_CONNECTOR(config, m_floppy1, ap34_floppies, nullptr, electron_ap34_device::floppy_formats).enable_sound(true);
+ FLOPPY_CONNECTOR(config, m_floppy[0], ap34_floppies, "525qd", electron_ap34_device::floppy_formats).enable_sound(true);
+ FLOPPY_CONNECTOR(config, m_floppy[1], ap34_floppies, nullptr, electron_ap34_device::floppy_formats).enable_sound(true);
}
//**************************************************************************
@@ -64,8 +66,7 @@ electron_ap34_device::electron_ap34_device(const machine_config &mconfig, const
: device_t(mconfig, ELECTRON_AP34, 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)
{
}
@@ -87,12 +88,9 @@ uint8_t electron_ap34_device::read(offs_t offset, int infc, int infd, int romqa,
if (infc)
{
- switch (offset & 0xff)
+ switch (offset & 0xfc)
{
case 0xc4:
- case 0xc5:
- case 0xc6:
- case 0xc7:
data = m_fdc->read(offset & 0x03);
break;
}
@@ -120,15 +118,12 @@ void electron_ap34_device::write(offs_t offset, uint8_t data, int infc, int infd
{
if (infc)
{
- switch (offset & 0xff)
+ switch (offset & 0xfc)
{
case 0xc0:
wd1770_control_w(data);
break;
case 0xc4:
- case 0xc5:
- case 0xc6:
- case 0xc7:
m_fdc->write(offset & 0x03, data);
break;
}
@@ -152,8 +147,8 @@ void electron_ap34_device::wd1770_control_w(uint8_t data)
floppy_image_device *floppy = nullptr;
// bit 0, 1: drive select
- 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);
// bit 2: side select
@@ -167,5 +162,5 @@ void electron_ap34_device::wd1770_control_w(uint8_t data)
//m_slot->nmi_w(!BIT(data, 4));
// bit 5: reset
- if (!BIT(data, 5)) m_fdc->soft_reset();
+ m_fdc->mr_w(BIT(data, 5));
}
diff --git a/src/devices/bus/electron/cart/ap34.h b/src/devices/bus/electron/cart/ap34.h
index 69b47514487..b6e331673aa 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
@@ -30,10 +29,10 @@ public:
protected:
// device-level overrides
- virtual void device_start() override;
+ virtual void device_start() override ATTR_COLD;
// optional information overrides
- virtual void device_add_mconfig(machine_config &config) override;
+ virtual void device_add_mconfig(machine_config &config) override ATTR_COLD;
// electron_cart_interface overrides
virtual uint8_t read(offs_t offset, int infc, int infd, int romqa, int oe, int oe2) override;
@@ -41,11 +40,10 @@ protected:
private:
void wd1770_control_w(uint8_t data);
- DECLARE_FLOPPY_FORMATS(floppy_formats);
+ 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_array<floppy_connector, 2> m_floppy;
};
diff --git a/src/devices/bus/electron/cart/ap5.cpp b/src/devices/bus/electron/cart/ap5.cpp
index e72e9ac4e25..82d83bfe611 100644
--- a/src/devices/bus/electron/cart/ap5.cpp
+++ b/src/devices/bus/electron/cart/ap5.cpp
@@ -24,17 +24,21 @@ DEFINE_DEVICE_TYPE(ELECTRON_AP5, electron_ap5_device, "electron_ap5", "P.R.E.S.
void electron_ap5_device::device_add_mconfig(machine_config &config)
{
+ INPUT_MERGER_ANY_HIGH(config, m_irqs).output_handler().set(DEVICE_SELF_OWNER, FUNC(electron_cartslot_device::irq_w));
+
/* rom sockets */
GENERIC_SOCKET(config, m_romslot[0], generic_plain_slot, "electron_rom", "bin,rom"); // ROM SLOT 14
- m_romslot[0]->set_device_load(FUNC(electron_ap5_device::rom1_load), this);
+ m_romslot[0]->set_device_load(FUNC(electron_ap5_device::rom1_load));
GENERIC_SOCKET(config, m_romslot[1], generic_plain_slot, "electron_rom", "bin,rom"); // ROM SLOT 15
- m_romslot[1]->set_device_load(FUNC(electron_ap5_device::rom2_load), this);
+ m_romslot[1]->set_device_load(FUNC(electron_ap5_device::rom2_load));
/* via */
- VIA6522(config, m_via, DERIVED_CLOCK(1, 16));
+ MOS6522(config, m_via, DERIVED_CLOCK(1, 16));
m_via->readpb_handler().set(m_userport, FUNC(bbc_userport_slot_device::pb_r));
m_via->writepb_handler().set(m_userport, FUNC(bbc_userport_slot_device::pb_w));
- m_via->irq_handler().set(DEVICE_SELF_OWNER, FUNC(electron_cartslot_device::irq_w));
+ m_via->cb1_handler().set(m_userport, FUNC(bbc_userport_slot_device::write_cb1));
+ m_via->cb2_handler().set(m_userport, FUNC(bbc_userport_slot_device::write_cb2));
+ m_via->irq_handler().set(m_irqs, FUNC(input_merger_device::in_w<0>));
/* user port */
BBC_USERPORT_SLOT(config, m_userport, bbc_userport_devices, nullptr);
@@ -43,12 +47,12 @@ void electron_ap5_device::device_add_mconfig(machine_config &config)
/* 1mhz bus port */
BBC_1MHZBUS_SLOT(config, m_1mhzbus, DERIVED_CLOCK(1, 16), bbc_1mhzbus_devices, nullptr);
- m_1mhzbus->irq_handler().set(DEVICE_SELF_OWNER, FUNC(electron_cartslot_device::irq_w));
+ m_1mhzbus->irq_handler().set(m_irqs, FUNC(input_merger_device::in_w<1>));
m_1mhzbus->nmi_handler().set(DEVICE_SELF_OWNER, FUNC(electron_cartslot_device::nmi_w));
/* tube port */
BBC_TUBE_SLOT(config, m_tube, electron_tube_devices, nullptr);
- m_tube->irq_handler().set(DEVICE_SELF_OWNER, FUNC(electron_cartslot_device::irq_w));
+ m_tube->irq_handler().set(m_irqs, FUNC(input_merger_device::in_w<2>));
}
//**************************************************************************
@@ -62,6 +66,7 @@ void electron_ap5_device::device_add_mconfig(machine_config &config)
electron_ap5_device::electron_ap5_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
: device_t(mconfig, ELECTRON_AP5, tag, owner, clock)
, device_electron_cart_interface(mconfig, *this)
+ , m_irqs(*this, "irqs")
, m_via(*this, "via6522")
, m_tube(*this, "tube")
, m_1mhzbus(*this, "1mhzbus")
@@ -149,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_UNSPECIFIED, "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 846f3fbc649..786f077e521 100644
--- a/src/devices/bus/electron/cart/ap5.h
+++ b/src/devices/bus/electron/cart/ap5.h
@@ -11,6 +11,7 @@
#include "slot.h"
#include "machine/6522via.h"
+#include "machine/input_merger.h"
#include "bus/bbc/1mhzbus/1mhzbus.h"
#include "bus/bbc/tube/tube.h"
#include "bus/bbc/userport/userport.h"
@@ -30,21 +31,22 @@ public:
electron_ap5_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
protected:
- // device-level overrides
- virtual void device_start() override;
+ // device_t implementation
+ virtual void device_start() override ATTR_COLD;
// optional information overrides
- virtual void device_add_mconfig(machine_config &config) override;
+ virtual void device_add_mconfig(machine_config &config) override ATTR_COLD;
- // 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]); }
+ required_device<input_merger_device> m_irqs;
required_device<via6522_device> m_via;
required_device<bbc_tube_slot_device> m_tube;
required_device<bbc_1mhzbus_slot_device> m_1mhzbus;
diff --git a/src/devices/bus/electron/cart/aqr.h b/src/devices/bus/electron/cart/aqr.h
index 820f967b5cf..c8fbcd10437 100644
--- a/src/devices/bus/electron/cart/aqr.h
+++ b/src/devices/bus/electron/cart/aqr.h
@@ -29,7 +29,7 @@ public:
protected:
// device-level overrides
- virtual void device_start() override;
+ virtual void device_start() override ATTR_COLD;
// electron_cart_interface overrides
virtual uint8_t read(offs_t offset, int infc, int infd, int romqa, int oe, int oe2) override;
diff --git a/src/devices/bus/electron/cart/click.cpp b/src/devices/bus/electron/cart/click.cpp
index 709aac9d380..9c7a0962129 100644
--- a/src/devices/bus/electron/cart/click.cpp
+++ b/src/devices/bus/electron/cart/click.cpp
@@ -16,7 +16,7 @@
// DEVICE DEFINITIONS
//**************************************************************************
-DEFINE_DEVICE_TYPE(ELECTRON_CLICK, electron_click_device, "electron_click", "Slogger Click cartridge")
+DEFINE_DEVICE_TYPE(ELECTRON_CLICK, electron_click_device, "electron_click", "Slogger Click (Electron) cartridge")
//-------------------------------------------------
@@ -36,7 +36,7 @@ void electron_click_device::device_add_mconfig(machine_config &config)
INPUT_PORTS_START(click)
PORT_START("BUTTON")
- PORT_BIT(0x01, IP_ACTIVE_LOW, IPT_BUTTON1) PORT_NAME("Click") PORT_CODE(KEYCODE_HOME) PORT_CHANGED_MEMBER(DEVICE_SELF, electron_click_device, click_button, 0)
+ PORT_BIT(0x01, IP_ACTIVE_LOW, IPT_BUTTON1) PORT_NAME("Click") PORT_CODE(KEYCODE_HOME) PORT_CHANGED_MEMBER(DEVICE_SELF, FUNC(electron_click_device::click_button), 0)
INPUT_PORTS_END
@@ -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/click.h b/src/devices/bus/electron/cart/click.h
index cb7dd114687..c56897adeae 100644
--- a/src/devices/bus/electron/cart/click.h
+++ b/src/devices/bus/electron/cart/click.h
@@ -34,11 +34,11 @@ public:
protected:
// device-level overrides
- virtual void device_add_mconfig(machine_config &config) override;
- virtual ioport_constructor device_input_ports() const override;
+ virtual void device_add_mconfig(machine_config &config) override ATTR_COLD;
+ virtual ioport_constructor device_input_ports() const override ATTR_COLD;
- virtual void device_start() override;
- virtual void device_reset() override;
+ virtual void device_start() override ATTR_COLD;
+ virtual void device_reset() override ATTR_COLD;
// electron_cart_interface overrides
virtual uint8_t read(offs_t offset, int infc, int infd, int romqa, int oe, int oe2) override;
diff --git a/src/devices/bus/electron/cart/cumana.cpp b/src/devices/bus/electron/cart/cumana.cpp
index 8792395b503..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
@@ -26,14 +26,17 @@ DEFINE_DEVICE_TYPE(ELECTRON_CUMANA, electron_cumana_device, "electron_cumana", "
//-------------------------------------------------
-// MACHINE_DRIVER( cumana )
+// FLOPPY_FORMATS( cumana )
//-------------------------------------------------
-FLOPPY_FORMATS_MEMBER(electron_cumana_device::floppy_formats)
- FLOPPY_ACORN_SSD_FORMAT,
- FLOPPY_ACORN_DSD_FORMAT,
- FLOPPY_ACORN_ADFS_OLD_FORMAT
-FLOPPY_FORMATS_END0
+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);
+}
void cumana_floppies(device_slot_interface &device)
{
@@ -47,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));
}
@@ -69,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")
{
}
@@ -83,6 +83,7 @@ void electron_cumana_device::device_start()
{
}
+
//-------------------------------------------------
// read - cartridge data read
//-------------------------------------------------
@@ -93,17 +94,16 @@ uint8_t electron_cumana_device::read(offs_t offset, int infc, int infd, int romq
if (infc)
{
- switch (offset & 0xff)
+ switch (offset & 0xfc)
{
case 0x90:
- case 0x91:
- case 0x92:
- case 0x93:
data = m_fdc->read(offset & 0x03);
break;
+ case 0x94:
case 0x98:
+ break;
case 0x9c:
- data = m_rtc->read(BIT(offset, 2));
+ data = m_rtc->data_r();
break;
}
}
@@ -138,20 +138,19 @@ void electron_cumana_device::write(offs_t offset, uint8_t data, int infc, int in
{
if (infc)
{
- switch (offset & 0xff)
+ switch (offset & 0xfc)
{
case 0x90:
- case 0x91:
- case 0x92:
- case 0x93:
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;
}
}
@@ -169,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
@@ -189,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 9a3bc2ab834..7d446701a7e 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
@@ -31,22 +30,21 @@ public:
protected:
// device-level overrides
- virtual void device_start() override;
+ virtual void device_start() override ATTR_COLD;
// optional information overrides
- virtual void device_add_mconfig(machine_config &config) override;
+ virtual void device_add_mconfig(machine_config &config) override ATTR_COLD;
// 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;
private:
- void wd1793_control_w(uint8_t data);
- DECLARE_FLOPPY_FORMATS(floppy_formats);
+ 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/elksdp1.cpp b/src/devices/bus/electron/cart/elksdp1.cpp
new file mode 100644
index 00000000000..11b4d140fba
--- /dev/null
+++ b/src/devices/bus/electron/cart/elksdp1.cpp
@@ -0,0 +1,228 @@
+// license:BSD-3-Clause
+// copyright-holders:Nigel Barnes
+/**********************************************************************
+
+ ElkSD-Plus 1 Electron SD Cartridge
+
+ http://ramtop-retro.uk/elksdp1.html
+
+**********************************************************************/
+
+
+#include "emu.h"
+#include "elksdp1.h"
+
+#include "machine/spi_sdcard.h"
+
+
+namespace {
+
+//**************************************************************************
+// TYPE DEFINITIONS
+//**************************************************************************
+
+class electron_elksdp1_device : public device_t, public device_electron_cart_interface
+{
+public:
+ // construction/destruction
+ electron_elksdp1_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
+
+protected:
+ // 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_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:
+ TIMER_CALLBACK_MEMBER(spi_clock);
+
+ required_device<spi_sdcard_device> m_sdcard;
+
+ emu_timer *m_spi_clock;
+ bool m_spi_clock_state;
+ bool m_spi_clock_sysclk;
+ int m_spi_clock_cycles;
+ int m_in_bit;
+ uint8_t m_in_latch;
+ uint8_t m_out_latch;
+
+ std::unique_ptr<uint8_t[]> m_ram;
+};
+
+
+//-------------------------------------------------
+// device_add_mconfig - add device configuration
+//-------------------------------------------------
+
+void electron_elksdp1_device::device_add_mconfig(machine_config &config)
+{
+ SPI_SDCARD(config, m_sdcard, 0);
+ m_sdcard->set_prefer_sdhc();
+ m_sdcard->spi_miso_callback().set([this](int state) { m_in_bit = state; });
+}
+
+//**************************************************************************
+// LIVE DEVICE
+//**************************************************************************
+
+//-------------------------------------------------
+// electron_elksdp1_device - constructor
+//-------------------------------------------------
+
+electron_elksdp1_device::electron_elksdp1_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
+ : device_t(mconfig, ELECTRON_ELKSDP1, tag, owner, clock)
+ , device_electron_cart_interface(mconfig, *this)
+ , m_sdcard(*this, "sdcard")
+ , m_spi_clock_state(false)
+ , m_spi_clock_sysclk(false)
+ , m_spi_clock_cycles(0)
+{
+}
+
+//-------------------------------------------------
+// device_start - device-specific startup
+//-------------------------------------------------
+
+void electron_elksdp1_device::device_start()
+{
+ m_ram = make_unique_clear<uint8_t[]>(0x8000);
+
+ m_spi_clock = timer_alloc(FUNC(electron_elksdp1_device::spi_clock), this);
+
+ save_pointer(NAME(m_ram), 0x8000);
+ save_item(NAME(m_spi_clock_state));
+ save_item(NAME(m_spi_clock_sysclk));
+ save_item(NAME(m_spi_clock_cycles));
+ save_item(NAME(m_in_bit));
+ save_item(NAME(m_in_latch));
+ save_item(NAME(m_out_latch));
+}
+
+//-------------------------------------------------
+// device_reset - device-specific startup
+//-------------------------------------------------
+
+void electron_elksdp1_device::device_reset()
+{
+ m_spi_clock->adjust(attotime::never);
+ m_spi_clock_cycles = 0;
+ m_spi_clock_state = false;
+}
+
+
+//-------------------------------------------------
+// read - cartridge data read
+//-------------------------------------------------
+
+uint8_t electron_elksdp1_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
+//-------------------------------------------------
+
+void electron_elksdp1_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(electron_elksdp1_device::spi_clock)
+{
+ if (m_spi_clock_cycles > 0)
+ {
+ m_sdcard->spi_ss_w(1);
+
+ if (m_spi_clock_state)
+ {
+ m_in_latch <<= 1;
+ m_in_latch &= ~0x01;
+ m_in_latch |= m_in_bit;
+
+ m_sdcard->spi_clock_w(1);
+
+ m_spi_clock_cycles--;
+ }
+ else
+ {
+ m_sdcard->spi_mosi_w(BIT(m_out_latch, 7));
+ m_sdcard->spi_clock_w(0);
+
+ m_out_latch <<= 1;
+ }
+
+ m_spi_clock_state = !m_spi_clock_state;
+ }
+ else
+ {
+ m_spi_clock_state = false;
+ m_spi_clock->adjust(attotime::never);
+ }
+}
+
+} // anonymous namespace
+
+
+//**************************************************************************
+// DEVICE DEFINITIONS
+//**************************************************************************
+
+DEFINE_DEVICE_TYPE_PRIVATE(ELECTRON_ELKSDP1, device_electron_cart_interface, electron_elksdp1_device, "electron_elksdp1", "ElkSD-Plus 1 Electron SD Cartridge")
diff --git a/src/devices/bus/electron/cart/elksdp1.h b/src/devices/bus/electron/cart/elksdp1.h
new file mode 100644
index 00000000000..10f109bc7a2
--- /dev/null
+++ b/src/devices/bus/electron/cart/elksdp1.h
@@ -0,0 +1,19 @@
+// license:BSD-3-Clause
+// copyright-holders:Nigel Barnes
+/**********************************************************************
+
+ ElkSD-Plus 1 Electron SD Cartridge
+
+**********************************************************************/
+
+#ifndef MAME_BUS_ELECTRON_CART_ELKSDP1_H
+#define MAME_BUS_ELECTRON_CART_ELKSDP1_H
+
+#pragma once
+
+#include "slot.h"
+
+
+DECLARE_DEVICE_TYPE(ELECTRON_ELKSDP1, device_electron_cart_interface)
+
+#endif // MAME_BUS_ELECTRON_CART_ELKSDP1_H
diff --git a/src/devices/bus/electron/cart/mgc.h b/src/devices/bus/electron/cart/mgc.h
index bf23aa34391..9fcc23f5a57 100644
--- a/src/devices/bus/electron/cart/mgc.h
+++ b/src/devices/bus/electron/cart/mgc.h
@@ -29,8 +29,8 @@ public:
protected:
// device-level overrides
- virtual void device_start() override;
- virtual void device_reset() override;
+ virtual void device_start() override ATTR_COLD;
+ virtual void device_reset() override ATTR_COLD;
// electron_cart_interface overrides
virtual uint8_t read(offs_t offset, int infc, int infd, int romqa, int oe, int oe2) override;
diff --git a/src/devices/bus/electron/cart/peg400.cpp b/src/devices/bus/electron/cart/peg400.cpp
index abca703474a..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
@@ -22,14 +23,16 @@ DEFINE_DEVICE_TYPE(ELECTRON_PEG400, electron_peg400_device, "electron_peg400", "
//-------------------------------------------------
-// MACHINE_DRIVER( peg400 )
+// FLOPPY_FORMATS( peg400 )
//-------------------------------------------------
-FLOPPY_FORMATS_MEMBER(electron_peg400_device::floppy_formats)
- FLOPPY_ACORN_SSD_FORMAT,
- FLOPPY_ACORN_DSD_FORMAT,
- FLOPPY_ACORN_ADFS_OLD_FORMAT
-FLOPPY_FORMATS_END0
+void electron_peg400_device::floppy_formats(format_registration &fr)
+{
+ fr.add_mfm_containers();
+ fr.add(FLOPPY_ACORN_SSD_FORMAT);
+ fr.add(FLOPPY_ACORN_DSD_FORMAT);
+ fr.add(FLOPPY_ACORN_ADFS_OLD_FORMAT);
+}
void peg400_floppies(device_slot_interface &device)
{
@@ -85,12 +88,9 @@ uint8_t electron_peg400_device::read(offs_t offset, int infc, int infd, int romq
if (infc)
{
- switch (offset & 0xff)
+ switch (offset & 0xfc)
{
case 0xc4:
- case 0xc5:
- case 0xc6:
- case 0xc7:
data = m_fdc->read(offset & 0x03);
break;
}
@@ -126,15 +126,12 @@ void electron_peg400_device::write(offs_t offset, uint8_t data, int infc, int in
{
if (infc)
{
- switch (offset & 0xff)
+ switch (offset & 0xfc)
{
case 0xc0:
wd1770_control_w(data);
break;
case 0xc4:
- case 0xc5:
- case 0xc6:
- case 0xc7:
m_fdc->write(offset & 0x03, data);
break;
}
@@ -175,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 035947a1e59..4cbb2652fa1 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
@@ -28,10 +27,10 @@ public:
protected:
// device-level overrides
- virtual void device_start() override;
+ virtual void device_start() override ATTR_COLD;
// optional information overrides
- virtual void device_add_mconfig(machine_config &config) override;
+ virtual void device_add_mconfig(machine_config &config) override ATTR_COLD;
// electron_cart_interface overrides
virtual uint8_t read(offs_t offset, int infc, int infd, int romqa, int oe, int oe2) override;
@@ -39,8 +38,8 @@ protected:
private:
void wd1770_control_w(uint8_t data);
- DECLARE_FLOPPY_FORMATS(floppy_formats);
- DECLARE_WRITE_LINE_MEMBER(fdc_drq_w);
+ static void floppy_formats(format_registration &fr);
+ 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 14853d86949..e570074a7f2 100644
--- a/src/devices/bus/electron/cart/romp144.cpp
+++ b/src/devices/bus/electron/cart/romp144.cpp
@@ -26,19 +26,19 @@ void electron_romp144_device::device_add_mconfig(machine_config &config)
{
/* rom sockets */
GENERIC_SOCKET(config, m_romslot[0], generic_plain_slot, "electron_rom", "bin,rom");
- m_romslot[0]->set_device_load(FUNC(electron_romp144_device::rom0), this);
+ m_romslot[0]->set_device_load(FUNC(electron_romp144_device::rom0));
GENERIC_SOCKET(config, m_romslot[1], generic_plain_slot, "electron_rom", "bin,rom");
- m_romslot[1]->set_device_load(FUNC(electron_romp144_device::rom1), this);
+ m_romslot[1]->set_device_load(FUNC(electron_romp144_device::rom1));
GENERIC_SOCKET(config, m_romslot[2], generic_plain_slot, "electron_rom", "bin,rom");
- m_romslot[2]->set_device_load(FUNC(electron_romp144_device::rom2), this);
+ m_romslot[2]->set_device_load(FUNC(electron_romp144_device::rom2));
GENERIC_SOCKET(config, m_romslot[3], generic_plain_slot, "electron_rom", "bin,rom");
- m_romslot[3]->set_device_load(FUNC(electron_romp144_device::rom3), this);
+ m_romslot[3]->set_device_load(FUNC(electron_romp144_device::rom3));
GENERIC_SOCKET(config, m_romslot[4], generic_plain_slot, "electron_rom", "bin,rom");
- m_romslot[4]->set_device_load(FUNC(electron_romp144_device::rom4), this);
+ m_romslot[4]->set_device_load(FUNC(electron_romp144_device::rom4));
GENERIC_SOCKET(config, m_romslot[5], generic_plain_slot, "electron_rom", "bin,rom");
- m_romslot[5]->set_device_load(FUNC(electron_romp144_device::rom5), this);
+ m_romslot[5]->set_device_load(FUNC(electron_romp144_device::rom5));
GENERIC_SOCKET(config, m_romslot[6], generic_plain_slot, "electron_rom", "bin,rom");
- m_romslot[6]->set_device_load(FUNC(electron_romp144_device::rom6), this);
+ m_romslot[6]->set_device_load(FUNC(electron_romp144_device::rom6));
}
//**************************************************************************
@@ -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_UNSPECIFIED, "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..14faac8704d 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
- virtual void device_start() override;
+ // device_t implementation
+ virtual void device_start() override ATTR_COLD;
// optional information overrides
- virtual void device_add_mconfig(machine_config &config) override;
+ virtual void device_add_mconfig(machine_config &config) override ATTR_COLD;
- // 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/rs423.cpp b/src/devices/bus/electron/cart/rs423.cpp
new file mode 100644
index 00000000000..68838a4cae2
--- /dev/null
+++ b/src/devices/bus/electron/cart/rs423.cpp
@@ -0,0 +1,97 @@
+// license:BSD-3-Clause
+// copyright-holders:Nigel Barnes
+/**********************************************************************
+
+ Electron RS423 Communications cartridge (Pace Micro Technology)
+
+**********************************************************************/
+
+
+#include "emu.h"
+#include "rs423.h"
+#include "bus/rs232/rs232.h"
+
+
+//**************************************************************************
+// DEVICE DEFINITIONS
+//**************************************************************************
+
+DEFINE_DEVICE_TYPE(ELECTRON_RS423, electron_rs423_device, "electron_rs423", "Pace RS423 Communications cartridge")
+
+
+//-------------------------------------------------
+// device_add_mconfig - add device configuration
+//-------------------------------------------------
+
+void electron_rs423_device::device_add_mconfig(machine_config &config)
+{
+ SCN2681(config, m_duart, 3.6864_MHz_XTAL);
+ m_duart->irq_cb().set(DEVICE_SELF_OWNER, FUNC(electron_cartslot_device::irq_w));
+ m_duart->a_tx_cb().set("rs423", FUNC(rs232_port_device::write_txd));
+ m_duart->outport_cb().set("rs423", FUNC(rs232_port_device::write_rts)).bit(0);
+
+ rs232_port_device &rs232(RS232_PORT(config, "rs423", default_rs232_devices, "null_modem"));
+ rs232.rxd_handler().set(m_duart, FUNC(scn2681_device::rx_a_w));
+ rs232.cts_handler().set(m_duart, FUNC(scn2681_device::ip2_w));
+}
+
+//**************************************************************************
+// LIVE DEVICE
+//**************************************************************************
+
+//-------------------------------------------------
+// electron_rs423_device - constructor
+//-------------------------------------------------
+
+electron_rs423_device::electron_rs423_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
+ : device_t(mconfig, ELECTRON_RS423, tag, owner, clock)
+ , device_electron_cart_interface(mconfig, *this)
+ , m_duart(*this, "duart")
+{
+}
+
+//-------------------------------------------------
+// device_start - device-specific startup
+//-------------------------------------------------
+
+void electron_rs423_device::device_start()
+{
+}
+
+//-------------------------------------------------
+// read - cartridge data read
+//-------------------------------------------------
+
+uint8_t electron_rs423_device::read(offs_t offset, int infc, int infd, int romqa, int oe, int oe2)
+{
+ uint8_t data = 0xff;
+
+ if (infc)
+ {
+ if (offset >= 0x60 && offset < 0x70)
+ {
+ data = m_duart->read(offset & 0x0f);
+ }
+ }
+ else if (oe)
+ {
+ data = m_rom[offset & 0x3fff];
+ }
+
+ return data;
+}
+
+//-------------------------------------------------
+// write - cartridge data write
+//-------------------------------------------------
+
+void electron_rs423_device::write(offs_t offset, uint8_t data, int infc, int infd, int romqa, int oe, int oe2)
+{
+ if (infc)
+ {
+ if (offset >= 0x60 && offset < 0x70)
+ {
+ m_duart->write(offset & 0x0f, data);
+ }
+ }
+}
diff --git a/src/devices/bus/electron/cart/rs423.h b/src/devices/bus/electron/cart/rs423.h
new file mode 100644
index 00000000000..734ca70cd56
--- /dev/null
+++ b/src/devices/bus/electron/cart/rs423.h
@@ -0,0 +1,47 @@
+// license:BSD-3-Clause
+// copyright-holders:Nigel Barnes
+/**********************************************************************
+
+ Electron RS423 Communications cartridge (Pace Micro Technology)
+
+**********************************************************************/
+
+#ifndef MAME_BUS_ELECTRON_CART_RS423_H
+#define MAME_BUS_ELECTRON_CART_RS423_H
+
+#include "slot.h"
+#include "machine/mc68681.h"
+
+//**************************************************************************
+// TYPE DEFINITIONS
+//**************************************************************************
+
+class electron_rs423_device :
+ public device_t,
+ public device_electron_cart_interface
+{
+public:
+ // construction/destruction
+ electron_rs423_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
+
+protected:
+ // device-level overrides
+ virtual void device_start() override ATTR_COLD;
+
+ // optional information overrides
+ virtual void device_add_mconfig(machine_config &config) override ATTR_COLD;
+
+ // 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;
+
+private:
+ required_device<scn2681_device> m_duart;
+};
+
+
+// device type definition
+DECLARE_DEVICE_TYPE(ELECTRON_RS423, electron_rs423_device)
+
+
+#endif // MAME_BUS_ELECTRON_CART_RS423_H
diff --git a/src/devices/bus/electron/cart/slot.cpp b/src/devices/bus/electron/cart/slot.cpp
index f8682b9c654..76ea4a63cdc 100644
--- a/src/devices/bus/electron/cart/slot.cpp
+++ b/src/devices/bus/electron/cart/slot.cpp
@@ -26,7 +26,7 @@ DEFINE_DEVICE_TYPE(ELECTRON_CARTSLOT, electron_cartslot_device, "electron_cartsl
//-------------------------------------------------
device_electron_cart_interface::device_electron_cart_interface(const machine_config &mconfig, device_t &device)
- : device_slot_card_interface(mconfig, device),
+ : device_interface(device, "electroncart"),
m_rom(nullptr),
m_rom_size(0)
{
@@ -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;
}
}
@@ -89,35 +89,28 @@ void device_electron_cart_interface::nvram_alloc(uint32_t size)
//-------------------------------------------------
// electron_cartslot_device - constructor
//-------------------------------------------------
-electron_cartslot_device::electron_cartslot_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) :
- device_t(mconfig, ELECTRON_CARTSLOT, tag, owner, clock),
- device_image_interface(mconfig, *this),
- device_slot_interface(mconfig, *this),
+electron_cartslot_device::electron_cartslot_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_electron_cart_interface>(mconfig, *this),
m_cart(nullptr),
m_irq_handler(*this),
m_nmi_handler(*this)
{
}
-//-------------------------------------------------
-// device_start - device-specific startup
-//-------------------------------------------------
-
-void electron_cartslot_device::device_start()
+electron_cartslot_device::electron_cartslot_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) :
+ electron_cartslot_device(mconfig, ELECTRON_CARTSLOT, tag, owner, clock)
{
- m_cart = dynamic_cast<device_electron_cart_interface *>(get_card_device());
-
- // resolve callbacks
- m_irq_handler.resolve_safe();
- m_nmi_handler.resolve_safe();
}
//-------------------------------------------------
-// device_reset - device-specific reset
+// device_start - device-specific startup
//-------------------------------------------------
-void electron_cartslot_device::device_reset()
+void electron_cartslot_device::device_start()
{
+ m_cart = get_card_device();
}
@@ -125,19 +118,16 @@ void electron_cartslot_device::device_reset()
// 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_UNSPECIFIED, "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);
@@ -153,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_UNSPECIFIED, "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)
@@ -200,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());
}
@@ -264,11 +251,12 @@ void electron_cartslot_device::write(offs_t offset, uint8_t data, int infc, int
#include "aqr.h"
#include "click.h"
#include "cumana.h"
+#include "elksdp1.h"
#include "mgc.h"
#include "peg400.h"
//#include "pmse2p.h"
#include "romp144.h"
-//#include "rs423.h"
+#include "rs423.h"
#include "sndexp.h"
#include "sndexp3.h"
#include "sp64.h"
@@ -286,11 +274,12 @@ void electron_cart(device_slot_interface &device)
device.option_add_internal("aqr", ELECTRON_AQR);
device.option_add_internal("click", ELECTRON_CLICK);
device.option_add_internal("cumana", ELECTRON_CUMANA);
+ device.option_add_internal("elksdp1", ELECTRON_ELKSDP1);
device.option_add_internal("mgc", ELECTRON_MGC);
device.option_add_internal("peg400", ELECTRON_PEG400);
//device.option_add_internal("pmse2p", ELECTRON_PMSE2P);
device.option_add_internal("romp144", ELECTRON_ROMP144);
- //device.option_add_internal("rs423", ELECTRON_RS423);
+ device.option_add_internal("rs423", ELECTRON_RS423);
device.option_add_internal("sndexp", ELECTRON_SNDEXP);
device.option_add_internal("sndexp3", ELECTRON_SNDEXP3);
device.option_add_internal("sp64", ELECTRON_SP64);
diff --git a/src/devices/bus/electron/cart/slot.h b/src/devices/bus/electron/cart/slot.h
index d31bc16258c..a9f4ab1e12e 100644
--- a/src/devices/bus/electron/cart/slot.h
+++ b/src/devices/bus/electron/cart/slot.h
@@ -91,12 +91,12 @@
22 0V - Zero volts.
**********************************************************************/
-#ifndef MAME_BUS_ELECTRON_CARTSLOT_H
-#define MAME_BUS_ELECTRON_CARTSLOT_H
+#ifndef MAME_BUS_ELECTRON_CART_SLOT_H
+#define MAME_BUS_ELECTRON_CART_SLOT_H
#pragma once
-#include "softlist_dev.h"
+#include "imagedev/cartrom.h"
//**************************************************************************
@@ -115,8 +115,8 @@
class device_electron_cart_interface;
class electron_cartslot_device : public device_t,
- public device_image_interface,
- public device_slot_interface
+ public device_cartrom_image_interface,
+ public device_single_card_slot_interface<device_electron_cart_interface>
{
public:
// construction/destruction
@@ -136,35 +136,33 @@ public:
auto irq_handler() { return m_irq_handler.bind(); }
auto nmi_handler() { return m_nmi_handler.bind(); }
- // device-level overrides
- 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 void call_unload() override;
- virtual const software_list_loader &get_software_list_loader() const override { return rom_software_list_loader::instance(); }
-
- virtual iodevice_t image_type() const override { return IO_CARTSLOT; }
- virtual bool is_readable() const override { return true; }
- virtual bool is_writeable() const override { return true; }
- virtual bool is_creatable() const override { return false; }
- virtual bool must_be_loaded() const override { return false; }
- virtual bool is_reset_on_load() const override { return true; }
- virtual const char *image_interface() const override { return "electron_cart"; }
- virtual const char *file_extensions() const override { return "rom,bin"; }
-
- // slot interface overrides
+
+ virtual bool is_writeable() const noexcept override { return true; }
+ virtual bool is_reset_on_load() const noexcept override { return true; }
+ virtual const char *image_interface() const noexcept override { return "electron_cart"; }
+ virtual const char *file_extensions() const noexcept override { return "rom,bin"; }
+
+ // device_image_interface implementation
virtual std::string get_default_card_software(get_default_card_software_hook &hook) const override;
// reading and writing
virtual uint8_t read(offs_t offset, int infc, int infd, int romqa, int oe, int oe2);
virtual void write(offs_t offset, uint8_t data, int infc, int infd, int romqa, int oe, int oe2);
- DECLARE_WRITE_LINE_MEMBER(irq_w) { m_irq_handler(state); }
- DECLARE_WRITE_LINE_MEMBER(nmi_w) { m_nmi_handler(state); }
+ virtual bool present() { return is_loaded() || loaded_through_softlist(); }
+
+ 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_t implementation
+ virtual void device_start() override ATTR_COLD;
+
device_electron_cart_interface *m_cart;
private:
@@ -175,7 +173,7 @@ private:
// ======================> device_electron_cart_interface
-class device_electron_cart_interface : public device_slot_card_interface
+class device_electron_cart_interface : public device_interface
{
public:
// construction/destruction
@@ -213,5 +211,4 @@ DECLARE_DEVICE_TYPE(ELECTRON_CARTSLOT, electron_cartslot_device)
void electron_cart(device_slot_interface &device);
-
-#endif // MAME_BUS_ELECTRON_CARTSLOT_H
+#endif // MAME_BUS_ELECTRON_CART_SLOT_H
diff --git a/src/devices/bus/electron/cart/sndexp.cpp b/src/devices/bus/electron/cart/sndexp.cpp
index 4ba27cb4825..9ca096adbfd 100644
--- a/src/devices/bus/electron/cart/sndexp.cpp
+++ b/src/devices/bus/electron/cart/sndexp.cpp
@@ -4,10 +4,6 @@
Sound Expansion cartridge (Project Expansions)
- TODO:
- - compare with actual hardware, sounds awful compared to v3
- - implement jumper to configure 8K as sideways RAM
-
**********************************************************************/
@@ -40,11 +36,10 @@ void electron_sndexp_device::device_add_mconfig(machine_config &config)
//-------------------------------------------------
INPUT_PORTS_START(sndexp)
- // TODO: Not known how jumper affects RAM access
- PORT_START("JUMPER")
- PORT_DIPNAME(0x01, 0x00, "SOUND / RAM")
- PORT_DIPSETTING(0x00, "SOUND")
- PORT_DIPSETTING(0x01, "RAM")
+ PORT_START("LINK")
+ PORT_CONFNAME(0x01, 0x00, "SOUND / RAM")
+ PORT_CONFSETTING(0x00, "SOUND")
+ PORT_CONFSETTING(0x01, "RAM")
INPUT_PORTS_END
@@ -69,7 +64,7 @@ electron_sndexp_device::electron_sndexp_device(const machine_config &mconfig, co
: device_t(mconfig, ELECTRON_SNDEXP, tag, owner, clock)
, device_electron_cart_interface(mconfig, *this)
, m_sn(*this, "sn76489")
- , m_jumper(*this, "JUMPER")
+ , m_link(*this, "LINK")
, m_sound_latch(0)
, m_sound_enable(0)
{
@@ -93,28 +88,23 @@ uint8_t electron_sndexp_device::read(offs_t offset, int infc, int infd, int romq
{
uint8_t data = 0xff;
- if (oe)
+ if (oe2)
{
- if (m_jumper->read())
+ if (m_link->read())
{
- if (romqa == 0)
- {
- data = m_rom[offset & 0x1fff];
- }
- else
- {
- data = m_ram[offset & 0x1fff];
- }
+ data = m_ram[offset & 0x1fff];
}
else
{
- if (offset < 0x2000)
+ switch (offset & 0x2000)
{
+ case 0x0000:
data = m_rom[offset & 0x1fff];
- }
- else
- {
+ break;
+
+ case 0x2000:
data = m_ram[offset & 0x1fff];
+ break;
}
}
}
@@ -144,24 +134,22 @@ void electron_sndexp_device::write(offs_t offset, uint8_t data, int infc, int in
break;
}
}
- else if (oe)
+ else if (oe2)
{
- if (m_jumper->read())
+ if (m_link->read())
{
- if (romqa == 1)
- {
- m_ram[offset & 0x1fff] = data;
- }
+ m_ram[offset & 0x1fff] = data;
}
else
{
- if (offset < 0x2000)
- {
- m_ram[offset & 0x1fff] = data;
- }
- else
+ switch (offset & 0x2000)
{
+ case 0x0000:
+ break;
+
+ case 0x2000:
m_ram[offset & 0x1fff] = data;
+ break;
}
}
}
diff --git a/src/devices/bus/electron/cart/sndexp.h b/src/devices/bus/electron/cart/sndexp.h
index 5627c2ff734..ffec377ab28 100644
--- a/src/devices/bus/electron/cart/sndexp.h
+++ b/src/devices/bus/electron/cart/sndexp.h
@@ -26,11 +26,11 @@ public:
protected:
// device-level overrides
- virtual void device_start() override;
+ virtual void device_start() override ATTR_COLD;
// optional information overrides
- virtual void device_add_mconfig(machine_config &config) override;
- virtual ioport_constructor device_input_ports() const override;
+ virtual void device_add_mconfig(machine_config &config) override ATTR_COLD;
+ virtual ioport_constructor device_input_ports() const override ATTR_COLD;
// electron_cart_interface overrides
virtual uint8_t read(offs_t offset, int infc, int infd, int romqa, int oe, int oe2) override;
@@ -38,7 +38,7 @@ protected:
private:
required_device<sn76489_device> m_sn;
- required_ioport m_jumper;
+ required_ioport m_link;
uint8_t m_sound_latch;
uint8_t m_sound_enable;
diff --git a/src/devices/bus/electron/cart/sndexp3.cpp b/src/devices/bus/electron/cart/sndexp3.cpp
index afaf927e443..f39fb90c414 100644
--- a/src/devices/bus/electron/cart/sndexp3.cpp
+++ b/src/devices/bus/electron/cart/sndexp3.cpp
@@ -66,7 +66,7 @@ uint8_t electron_sndexp3_device::read(offs_t offset, int infc, int infd, int rom
{
uint8_t data = 0xff;
- if (oe && romqa)
+ if (oe2)
{
if (offset < 0x2000)
{
@@ -103,7 +103,7 @@ void electron_sndexp3_device::write(offs_t offset, uint8_t data, int infc, int i
break;
}
}
- else if (oe && romqa)
+ else if (oe2)
{
if (offset >= 0x2000)
{
diff --git a/src/devices/bus/electron/cart/sndexp3.h b/src/devices/bus/electron/cart/sndexp3.h
index 95d437b63e2..07dba7a35ad 100644
--- a/src/devices/bus/electron/cart/sndexp3.h
+++ b/src/devices/bus/electron/cart/sndexp3.h
@@ -26,10 +26,10 @@ public:
protected:
// device-level overrides
- virtual void device_start() override;
+ virtual void device_start() override ATTR_COLD;
// optional information overrides
- virtual void device_add_mconfig(machine_config &config) override;
+ virtual void device_add_mconfig(machine_config &config) override ATTR_COLD;
// electron_cart_interface overrides
virtual uint8_t read(offs_t offset, int infc, int infd, int romqa, int oe, int oe2) override;
diff --git a/src/devices/bus/electron/cart/sp64.h b/src/devices/bus/electron/cart/sp64.h
index 68954fc9d30..24151ff1785 100644
--- a/src/devices/bus/electron/cart/sp64.h
+++ b/src/devices/bus/electron/cart/sp64.h
@@ -29,8 +29,8 @@ public:
protected:
// device-level overrides
- virtual void device_start() override;
- virtual void device_reset() override;
+ virtual void device_start() override ATTR_COLD;
+ virtual void device_reset() override ATTR_COLD;
// electron_cart_interface overrides
virtual uint8_t read(offs_t offset, int infc, int infd, int romqa, int oe, int oe2) override;
diff --git a/src/devices/bus/electron/cart/std.h b/src/devices/bus/electron/cart/std.h
index 3fc9cefbcd9..a3fe9805102 100644
--- a/src/devices/bus/electron/cart/std.h
+++ b/src/devices/bus/electron/cart/std.h
@@ -28,7 +28,7 @@ public:
protected:
// device-level overrides
- virtual void device_start() override;
+ virtual void device_start() override ATTR_COLD;
// electron_cart_interface overrides
virtual uint8_t read(offs_t offset, int infc, int infd, int romqa, int oe, int oe2) override;
diff --git a/src/devices/bus/electron/cart/stlefs.cpp b/src/devices/bus/electron/cart/stlefs.cpp
index 47566871a9d..3aeb1ddac04 100644
--- a/src/devices/bus/electron/cart/stlefs.cpp
+++ b/src/devices/bus/electron/cart/stlefs.cpp
@@ -7,15 +7,15 @@
http://chrisacorns.computinghistory.org.uk/8bit_Upgrades/Solidisk_EFS.html
TODO:
- - add Winchester slot
- unknown how 16K RAM is paged as SWR (adverts claim it was unreliable)
**********************************************************************/
-
#include "emu.h"
#include "stlefs.h"
+#include "formats/acorn_dsk.h"
+
//**************************************************************************
// DEVICE DEFINITIONS
@@ -25,14 +25,16 @@ DEFINE_DEVICE_TYPE(ELECTRON_STLEFS, electron_stlefs_device, "electron_stlefs", "
//-------------------------------------------------
-// MACHINE_DRIVER( stlefs )
+// FLOPPY_FORMATS( stlefs )
//-------------------------------------------------
-FLOPPY_FORMATS_MEMBER(electron_stlefs_device::floppy_formats)
- FLOPPY_ACORN_SSD_FORMAT,
- FLOPPY_ACORN_DSD_FORMAT,
- FLOPPY_ACORN_ADFS_OLD_FORMAT
-FLOPPY_FORMATS_END
+void electron_stlefs_device::floppy_formats(format_registration &fr)
+{
+ fr.add_mfm_containers();
+ fr.add(FLOPPY_ACORN_SSD_FORMAT);
+ fr.add(FLOPPY_ACORN_DSD_FORMAT);
+ fr.add(FLOPPY_ACORN_ADFS_OLD_FORMAT);
+}
void stlefs_floppies(device_slot_interface &device)
{
@@ -46,12 +48,19 @@ void stlefs_floppies(device_slot_interface &device)
void electron_stlefs_device::device_add_mconfig(machine_config &config)
{
+ INPUT_MERGER_ANY_HIGH(config, m_irqs).output_handler().set(DEVICE_SELF_OWNER, FUNC(electron_cartslot_device::irq_w));
+
/* fdc */
WD1770(config, m_fdc, DERIVED_CLOCK(1, 2));
- m_fdc->intrq_wr_callback().set(DEVICE_SELF_OWNER, FUNC(electron_cartslot_device::irq_w));
+ m_fdc->intrq_wr_callback().set(m_irqs, FUNC(input_merger_device::in_w<0>));
m_fdc->drq_wr_callback().set(DEVICE_SELF_OWNER, FUNC(electron_cartslot_device::nmi_w));
FLOPPY_CONNECTOR(config, m_floppy0, stlefs_floppies, "525qd", electron_stlefs_device::floppy_formats).enable_sound(true);
FLOPPY_CONNECTOR(config, m_floppy1, stlefs_floppies, nullptr, electron_stlefs_device::floppy_formats).enable_sound(true);
+
+ /* winchester */
+ BBC_1MHZBUS_SLOT(config, m_1mhzbus, DERIVED_CLOCK(1, 16), bbc_1mhzbus_devices, nullptr);
+ m_1mhzbus->irq_handler().set(m_irqs, FUNC(input_merger_device::in_w<1>));
+ m_1mhzbus->nmi_handler().set(DEVICE_SELF_OWNER, FUNC(electron_cartslot_device::nmi_w));
}
//**************************************************************************
@@ -65,6 +74,8 @@ void electron_stlefs_device::device_add_mconfig(machine_config &config)
electron_stlefs_device::electron_stlefs_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
: device_t(mconfig, ELECTRON_STLEFS, tag, owner, clock)
, device_electron_cart_interface(mconfig, *this)
+ , m_irqs(*this, "irqs")
+ , m_1mhzbus(*this, "1mhzbus")
, m_fdc(*this, "fdc")
, m_floppy0(*this, "fdc:0")
, m_floppy1(*this, "fdc:1")
@@ -89,15 +100,13 @@ uint8_t electron_stlefs_device::read(offs_t offset, int infc, int infd, int romq
if (infc)
{
- switch (offset & 0xff)
+ switch (offset & 0xfc)
{
case 0xc4:
- case 0xc5:
- case 0xc6:
- case 0xc7:
data = m_fdc->read(offset & 0x03);
break;
}
+ data &= m_1mhzbus->fred_r(offset & 0xff);
}
else if (oe)
{
@@ -115,20 +124,18 @@ void electron_stlefs_device::write(offs_t offset, uint8_t data, int infc, int in
{
if (infc)
{
- switch (offset & 0xff)
+ switch (offset & 0xfc)
{
case 0xc0:
wd1770_control_w(data);
break;
case 0xc4:
- case 0xc5:
- case 0xc6:
- case 0xc7:
m_fdc->write(offset & 0x03, data);
break;
//case 0xcb:
//m_page_register = data;
}
+ m_1mhzbus->fred_w(offset & 0xff, data);
}
}
@@ -154,5 +161,5 @@ void electron_stlefs_device::wd1770_control_w(uint8_t data)
m_fdc->dden_w(BIT(data, 3));
// bit 5: reset
- if (!BIT(data, 5)) m_fdc->soft_reset();
+ m_fdc->mr_w(BIT(data, 5));
}
diff --git a/src/devices/bus/electron/cart/stlefs.h b/src/devices/bus/electron/cart/stlefs.h
index 421850943e2..2af9df1f946 100644
--- a/src/devices/bus/electron/cart/stlefs.h
+++ b/src/devices/bus/electron/cart/stlefs.h
@@ -12,9 +12,10 @@
#define MAME_BUS_ELECTRON_CART_STLEFS_H
#include "slot.h"
+#include "bus/bbc/1mhzbus/1mhzbus.h"
+#include "machine/input_merger.h"
#include "machine/wd_fdc.h"
#include "imagedev/floppy.h"
-#include "formats/acorn_dsk.h"
//**************************************************************************
// TYPE DEFINITIONS
@@ -30,10 +31,10 @@ public:
protected:
// device-level overrides
- virtual void device_start() override;
+ virtual void device_start() override ATTR_COLD;
// optional information overrides
- virtual void device_add_mconfig(machine_config &config) override;
+ virtual void device_add_mconfig(machine_config &config) override ATTR_COLD;
// electron_cart_interface overrides
virtual uint8_t read(offs_t offset, int infc, int infd, int romqa, int oe, int oe2) override;
@@ -41,8 +42,10 @@ protected:
private:
void wd1770_control_w(uint8_t data);
- DECLARE_FLOPPY_FORMATS(floppy_formats);
+ static void floppy_formats(format_registration &fr);
+ required_device<input_merger_device> m_irqs;
+ required_device<bbc_1mhzbus_slot_device> m_1mhzbus;
required_device<wd1770_device> m_fdc;
required_device<floppy_connector> m_floppy0;
required_device<floppy_connector> m_floppy1;
diff --git a/src/devices/bus/electron/cart/tube.h b/src/devices/bus/electron/cart/tube.h
index 1d239ef5215..25e0a7f2b6e 100644
--- a/src/devices/bus/electron/cart/tube.h
+++ b/src/devices/bus/electron/cart/tube.h
@@ -26,10 +26,10 @@ public:
protected:
// device-level overrides
- virtual void device_start() override;
+ virtual void device_start() override ATTR_COLD;
// optional information overrides
- virtual void device_add_mconfig(machine_config &config) override;
+ virtual void device_add_mconfig(machine_config &config) override ATTR_COLD;
// electron_cart_interface overrides
virtual uint8_t read(offs_t offset, int infc, int infd, int romqa, int oe, int oe2) override;
diff --git a/src/devices/bus/electron/elksd128.cpp b/src/devices/bus/electron/elksd128.cpp
new file mode 100644
index 00000000000..d82186318ce
--- /dev/null
+++ b/src/devices/bus/electron/elksd128.cpp
@@ -0,0 +1,333 @@
+// license:BSD-3-Clause
+// copyright-holders:Nigel Barnes
+/**********************************************************************
+
+ ElkSD128 Electron SD Interface
+
+ SD Card Interface, 128K Memory Expansion & Joystick Adapter
+
+ http://ramtop-retro.uk/elksd128.html
+
+**********************************************************************/
+
+#include "emu.h"
+#include "elksd128.h"
+
+#include "bus/vcs_ctrl/ctrl.h"
+#include "machine/spi_sdcard.h"
+
+
+namespace {
+
+class electron_elksd128_device
+ : public device_t
+ , public device_electron_expansion_interface
+{
+public:
+ electron_elksd128_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
+ : device_t(mconfig, ELECTRON_ELKSD128, tag, owner, clock)
+ , device_electron_expansion_interface(mconfig, *this)
+ , m_flash(*this, "flash")
+ , m_sdcard(*this, "sdcard")
+ , m_joy(*this, "joy")
+ , m_romsel(0)
+ , m_adc_channel(0)
+ , m_swr_lock(0)
+ , m_spi_clock_state(false)
+ , m_spi_clock_sysclk(false)
+ , m_spi_clock_cycles(0)
+ {
+ }
+
+protected:
+ // device_t overrides
+ virtual void device_start() override ATTR_COLD;
+ virtual void device_reset() override ATTR_COLD;
+
+ // optional information overrides
+ virtual void device_add_mconfig(machine_config &config) override ATTR_COLD;
+ virtual const tiny_rom_entry *device_rom_region() const override ATTR_COLD;
+
+ virtual uint8_t expbus_r(offs_t offset) override;
+ virtual void expbus_w(offs_t offset, uint8_t data) override;
+
+private:
+ required_memory_region m_flash;
+ required_device<spi_sdcard_device> m_sdcard;
+ required_device<vcs_control_port_device> m_joy;
+
+ uint8_t m_romsel;
+ uint8_t m_adc_channel;
+ uint8_t m_swr_lock;
+
+ TIMER_CALLBACK_MEMBER(spi_clock);
+
+ emu_timer *m_spi_clock;
+ bool m_spi_clock_state;
+ bool m_spi_clock_sysclk;
+ int m_spi_clock_cycles;
+ int m_in_bit;
+ uint8_t m_in_latch;
+ uint8_t m_out_latch;
+
+ std::unique_ptr<uint8_t[]> m_ram;
+};
+
+
+//-------------------------------------------------
+// rom_region - device-specific ROM region
+//-------------------------------------------------
+
+ROM_START( elksd128 )
+ ROM_REGION(0x80000, "flash", 0)
+ ROM_LOAD("esd12815.rom", 0x0000, 0x80000, CRC(3ecf23ce) SHA1(d552149fec6a1deec2b75c740092bd311d67046f))
+ROM_END
+
+const tiny_rom_entry *electron_elksd128_device::device_rom_region() const
+{
+ return ROM_NAME( elksd128 );
+}
+
+
+//-------------------------------------------------
+// device_add_mconfig - add device configuration
+//-------------------------------------------------
+
+void electron_elksd128_device::device_add_mconfig(machine_config &config)
+{
+ SPI_SDCARD(config, m_sdcard, 0);
+ m_sdcard->set_prefer_sdhc();
+ m_sdcard->spi_miso_callback().set([this](int state) { m_in_bit = state; });
+
+ VCS_CONTROL_PORT(config, m_joy, vcs_control_port_devices, "joy");
+}
+
+
+//-------------------------------------------------
+// device_start - device-specific startup
+//-------------------------------------------------
+
+void electron_elksd128_device::device_start()
+{
+ m_ram = make_unique_clear<uint8_t[]>(0x20000);
+
+ m_spi_clock = timer_alloc(FUNC(electron_elksd128_device::spi_clock), this);
+
+ save_item(NAME(m_romsel));
+ save_item(NAME(m_adc_channel));
+ save_item(NAME(m_swr_lock));
+ save_pointer(NAME(m_ram), 0x20000);
+ save_item(NAME(m_spi_clock_state));
+ save_item(NAME(m_spi_clock_sysclk));
+ save_item(NAME(m_spi_clock_cycles));
+ save_item(NAME(m_in_bit));
+ save_item(NAME(m_in_latch));
+ save_item(NAME(m_out_latch));
+}
+
+//-------------------------------------------------
+// device_reset - device-specific startup
+//-------------------------------------------------
+
+void electron_elksd128_device::device_reset()
+{
+ m_spi_clock->adjust(attotime::never);
+ m_spi_clock_cycles = 0;
+ m_spi_clock_state = false;
+}
+
+
+//-------------------------------------------------
+// expbus_r - expansion data read
+//-------------------------------------------------
+
+uint8_t electron_elksd128_device::expbus_r(offs_t offset)
+{
+ uint8_t data = 0xff;
+
+ switch (offset >> 12)
+ {
+ case 0x8: case 0x9: case 0xa: case 0xb:
+ switch (m_romsel)
+ {
+ case 0: case 1: case 2: case 3: case 4: case 5: case 6: case 7:
+ data = m_ram[(m_romsel) << 14 | (offset & 0x3fff)];
+ break;
+
+ case 12:
+ data = m_flash->base()[(m_romsel - 10) << 14 | (offset & 0x3fff)];
+ break;
+
+ case 14: case 15:
+ data = m_flash->base()[(m_romsel - 14) << 14 | (offset & 0x3fff)];
+ break;
+ }
+ break;
+
+ case 0xf:
+ switch (offset >> 8)
+ {
+ case 0xfc:
+ switch (offset)
+ {
+ case 0xfc70: // Plus 1 analogue/digital converter
+ switch (m_adc_channel)
+ {
+ case 0x04:
+ if (!BIT(m_joy->read_joy(), 3))
+ data = 0x00;
+ else if (!BIT(m_joy->read_joy(), 2))
+ data = 0xff;
+ else
+ data = 0x80;
+ break;
+ case 0x05:
+ if (!BIT(m_joy->read_joy(), 1))
+ data = 0x00;
+ else if (!BIT(m_joy->read_joy(), 0))
+ data = 0xff;
+ else
+ data = 0x80;
+ break;
+ case 0x06:
+ case 0x07:
+ data = 0x80;
+ break;
+ }
+ break;
+
+ case 0xfc72: // Plus 1 joystick and ADC status
+ data = 0xaf | (BIT(m_joy->read_joy(), 5) << 4);
+ break;
+
+ case 0xfc80: // SPI controller data port
+ data = m_in_latch;
+ break;
+
+ case 0xfc81: // SPI controller status register
+ data = m_spi_clock_cycles > 0 ? 0x01 : 0x00;
+ break;
+
+ case 0xfc83: // Device ID
+ data = 0x80; // ElkSD128 rev 1.0
+ break;
+
+ case 0xfcc0: // First Byte interface
+ data = bitswap<8>(m_joy->read_joy(), 7, 6, 4, 5, 3, 2, 1, 0);
+ break;
+
+ case 0xfcd0: // Slogger interface
+ data = bitswap<8>(m_joy->read_joy(), 7, 6, 4, 5, 3, 2, 1, 0);
+ break;
+ }
+ break;
+ }
+ }
+
+ return data;
+}
+
+
+//-------------------------------------------------
+// expbus_w - expansion data write
+//-------------------------------------------------
+
+void electron_elksd128_device::expbus_w(offs_t offset, uint8_t data)
+{
+ switch (offset >> 12)
+ {
+ case 0x8: case 0x9: case 0xa: case 0xb:
+ switch (m_romsel)
+ {
+ case 0: case 1: case 2: case 3: case 4: case 5:
+ m_ram[(m_romsel) << 14 | (offset & 0x3fff)] = data;
+ break;
+ case 6:
+ if (!BIT(m_swr_lock, 6) || (offset & 0x3fff) > 0x3600)
+ m_ram[(m_romsel) << 14 | (offset & 0x3fff)] = data;
+ break;
+ case 7:
+ if (BIT(m_swr_lock, 7) || (offset & 0x3fff) > 0x3600)
+ m_ram[(m_romsel) << 14 | (offset & 0x3fff)] = data;
+ break;
+ }
+ break;
+
+ case 0xf:
+ switch (offset >> 8)
+ {
+ case 0xfc:
+ switch (offset)
+ {
+ case 0xfc70: // Plus 1 analogue/digital converter
+ m_adc_channel = data;
+ break;
+
+ case 0xfc80: // 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 0xfc81: // SPI controller clock register
+ m_spi_clock_sysclk = bool(BIT(data, 0));
+ break;
+
+ case 0xfc82: // Sideways RAM lock
+ m_swr_lock = data;
+ break;
+ }
+ break;
+
+ case 0xfe:
+ if ((offset == 0xfe05) && !(data & 0xf0))
+ {
+ m_romsel = data & 0x0f;
+ }
+ break;
+ }
+ }
+}
+
+
+TIMER_CALLBACK_MEMBER(electron_elksd128_device::spi_clock)
+{
+ if (m_spi_clock_cycles > 0)
+ {
+ m_sdcard->spi_ss_w(1);
+
+ if (m_spi_clock_state)
+ {
+ m_in_latch <<= 1;
+ m_in_latch &= ~0x01;
+ m_in_latch |= m_in_bit;
+
+ m_sdcard->spi_clock_w(1);
+
+ m_spi_clock_cycles--;
+ }
+ else
+ {
+ m_sdcard->spi_mosi_w(BIT(m_out_latch, 7));
+ m_sdcard->spi_clock_w(0);
+
+ m_out_latch <<= 1;
+ }
+
+ m_spi_clock_state = !m_spi_clock_state;
+ }
+ else
+ {
+ m_spi_clock_state = false;
+ m_spi_clock->adjust(attotime::never);
+ }
+}
+
+} // anonymous namespace
+
+
+DEFINE_DEVICE_TYPE_PRIVATE(ELECTRON_ELKSD128, device_electron_expansion_interface, electron_elksd128_device, "electron_elksd128", "ElkSD128 Electron SD Interface")
diff --git a/src/devices/bus/electron/elksd128.h b/src/devices/bus/electron/elksd128.h
new file mode 100644
index 00000000000..b11b33f1cf6
--- /dev/null
+++ b/src/devices/bus/electron/elksd128.h
@@ -0,0 +1,19 @@
+// license:BSD-3-Clause
+// copyright-holders:Nigel Barnes
+/**********************************************************************
+
+ ElkSD128 Electron SD Interface
+
+**********************************************************************/
+
+#ifndef MAME_BUS_ELECTRON_ELKSD128_H
+#define MAME_BUS_ELECTRON_ELKSD128_H
+
+#pragma once
+
+#include "exp.h"
+
+
+DECLARE_DEVICE_TYPE(ELECTRON_ELKSD128, device_electron_expansion_interface)
+
+#endif // MAME_BUS_ELECTRON_ELKSD128_H
diff --git a/src/devices/bus/electron/elksd64.cpp b/src/devices/bus/electron/elksd64.cpp
new file mode 100644
index 00000000000..3a8a3216599
--- /dev/null
+++ b/src/devices/bus/electron/elksd64.cpp
@@ -0,0 +1,201 @@
+// license:BSD-3-Clause
+// copyright-holders:Nigel Barnes
+/**********************************************************************
+
+ ElkSD64 Electron SD Interface
+
+ SD Card Interface & 64K RAM Expansion
+
+ http://ramtop-retro.uk/elksd64.html
+
+**********************************************************************/
+
+
+#include "emu.h"
+#include "elksd64.h"
+
+#include "machine/spi_sdcard.h"
+
+
+namespace {
+
+//**************************************************************************
+// TYPE DEFINITIONS
+//**************************************************************************
+
+class electron_elksd64_device:
+ public device_t,
+ public device_electron_expansion_interface
+{
+public:
+ // construction/destruction
+ electron_elksd64_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
+
+protected:
+ // device_t implementation
+ virtual void device_start() override ATTR_COLD;
+ virtual void device_add_mconfig(machine_config &config) override ATTR_COLD;
+ virtual const tiny_rom_entry *device_rom_region() const override ATTR_COLD;
+
+ // device_electron_expansion_interface implementation
+ virtual uint8_t expbus_r(offs_t offset) override;
+ virtual void expbus_w(offs_t offset, uint8_t data) override;
+
+private:
+ required_memory_region m_flash;
+ required_device<spi_sdcard_device> m_sdcard;
+
+ uint8_t m_romsel;
+ uint8_t m_status;
+
+ std::unique_ptr<uint8_t[]> m_ram;
+};
+
+
+//-------------------------------------------------
+// ROM( elksd64 )
+//-------------------------------------------------
+
+ROM_START( elksd64 )
+ ROM_REGION(0x20000, "flash", ROMREGION_ERASE00) // SST39SF010
+ ROM_LOAD("zemmfs.bin", 0x0000, 0x4000, CRC(c3d38702) SHA1(8a1f0615ff93549815f4c8d21e35fb89535941dc))
+ ROM_LOAD("ap6rom.rom", 0x4000, 0x4000, CRC(364591eb) SHA1(316a25aeeda0266dae510eea52324b087875740f))
+ROM_END
+
+//-------------------------------------------------
+// device_add_mconfig - add device configuration
+//-------------------------------------------------
+
+void electron_elksd64_device::device_add_mconfig(machine_config &config)
+{
+ SPI_SDCARD(config, m_sdcard, 0);
+ m_sdcard->set_prefer_sdhc();
+ m_sdcard->spi_miso_callback().set([this](int state) { m_status = state << 7; });
+}
+
+//-------------------------------------------------
+// rom_region - device-specific ROM region
+//-------------------------------------------------
+
+const tiny_rom_entry *electron_elksd64_device::device_rom_region() const
+{
+ return ROM_NAME( elksd64 );
+}
+
+//**************************************************************************
+// LIVE DEVICE
+//**************************************************************************
+
+//-------------------------------------------------
+// electron_elksd64_device - constructor
+//-------------------------------------------------
+
+electron_elksd64_device::electron_elksd64_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
+ : device_t(mconfig, ELECTRON_ELKSD64, tag, owner, clock)
+ , device_electron_expansion_interface(mconfig, *this)
+ , m_flash(*this, "flash")
+ , m_sdcard(*this, "sdcard")
+ , m_romsel(0)
+ , m_status(0)
+{
+}
+
+//-------------------------------------------------
+// device_start - device-specific startup
+//-------------------------------------------------
+
+void electron_elksd64_device::device_start()
+{
+ m_ram = make_unique_clear<uint8_t[]>(0x8000);
+
+ save_item(NAME(m_romsel));
+ save_item(NAME(m_status));
+ save_pointer(NAME(m_ram), 0x8000);
+}
+
+//-------------------------------------------------
+// expbus_r - expansion data read
+//-------------------------------------------------
+
+uint8_t electron_elksd64_device::expbus_r(offs_t offset)
+{
+ uint8_t data = 0xff;
+
+ switch (offset >> 12)
+ {
+ case 0x8: case 0x9: case 0xa: case 0xb:
+ switch (m_romsel)
+ {
+ case 12: case 13:
+ data = m_ram[(m_romsel - 12) << 14 | (offset & 0x3fff)];
+ break;
+
+ case 14: case 15:
+ data = m_flash->base()[(m_romsel - 14) << 14 | (offset & 0x3fff)];
+ break;
+ }
+ break;
+
+ case 0xf:
+ switch (offset >> 8)
+ {
+ case 0xfc:
+ if (offset == 0xfc72)
+ {
+ data = m_status;
+ }
+ break;
+ }
+ }
+
+ return data;
+}
+
+
+//-------------------------------------------------
+// expbus_w - expansion data write
+//-------------------------------------------------
+
+void electron_elksd64_device::expbus_w(offs_t offset, uint8_t data)
+{
+ switch (offset >> 12)
+ {
+ case 0x8: case 0x9: case 0xa: case 0xb:
+ switch (m_romsel)
+ {
+ case 12: case 13:
+ m_ram[(m_romsel - 12) << 14 | (offset & 0x3fff)] = data;
+ break;
+ }
+ break;
+
+ case 0xf:
+ switch (offset >> 8)
+ {
+ case 0xfc:
+ if (offset == 0xfc71)
+ {
+ m_sdcard->spi_ss_w(1);
+ m_sdcard->spi_mosi_w(BIT(data, 0));
+ m_sdcard->spi_clock_w(BIT(data, 1));
+ }
+ break;
+
+ case 0xfe:
+ if ((offset == 0xfe05) && !(data & 0xf0))
+ {
+ m_romsel = data & 0x0f;
+ }
+ break;
+ }
+ }
+}
+
+} // anonymous namespace
+
+
+//**************************************************************************
+// DEVICE DEFINITIONS
+//**************************************************************************
+
+DEFINE_DEVICE_TYPE_PRIVATE(ELECTRON_ELKSD64, device_electron_expansion_interface, electron_elksd64_device, "electron_elksd64", "ElkSD64 Electron SD Interface")
diff --git a/src/devices/bus/electron/elksd64.h b/src/devices/bus/electron/elksd64.h
new file mode 100644
index 00000000000..11ab9536df8
--- /dev/null
+++ b/src/devices/bus/electron/elksd64.h
@@ -0,0 +1,19 @@
+// license:BSD-3-Clause
+// copyright-holders:Nigel Barnes
+/**********************************************************************
+
+ ElkSD64 Electron SD Interface
+
+**********************************************************************/
+
+#ifndef MAME_BUS_ELECTRON_ELKSD64_H
+#define MAME_BUS_ELECTRON_ELKSD64_H
+
+#pragma once
+
+#include "exp.h"
+
+
+DECLARE_DEVICE_TYPE(ELECTRON_ELKSD64, device_electron_expansion_interface)
+
+#endif // MAME_BUS_ELECTRON_ELKSD64_H
diff --git a/src/devices/bus/electron/exp.cpp b/src/devices/bus/electron/exp.cpp
index d2cd0abc824..794e2e0df96 100644
--- a/src/devices/bus/electron/exp.cpp
+++ b/src/devices/bus/electron/exp.cpp
@@ -26,7 +26,7 @@ DEFINE_DEVICE_TYPE(ELECTRON_EXPANSION_SLOT, electron_expansion_slot_device, "ele
//-------------------------------------------------
device_electron_expansion_interface::device_electron_expansion_interface(const machine_config &mconfig, device_t &device)
- : device_slot_card_interface(mconfig, device)
+ : device_interface(device, "electronexp")
{
m_slot = dynamic_cast<electron_expansion_slot_device *>(device.owner());
}
@@ -42,7 +42,7 @@ device_electron_expansion_interface::device_electron_expansion_interface(const m
electron_expansion_slot_device::electron_expansion_slot_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) :
device_t(mconfig, ELECTRON_EXPANSION_SLOT, tag, owner, clock),
- device_slot_interface(mconfig, *this),
+ device_single_card_slot_interface<device_electron_expansion_interface>(mconfig, *this),
m_card(nullptr),
m_irq_handler(*this),
m_nmi_handler(*this)
@@ -56,20 +56,9 @@ electron_expansion_slot_device::electron_expansion_slot_device(const machine_con
void electron_expansion_slot_device::device_start()
{
- m_card = dynamic_cast<device_electron_expansion_interface *>(get_card_device());
-
- // resolve callbacks
- m_irq_handler.resolve_safe();
- m_nmi_handler.resolve_safe();
+ m_card = get_card_device();
}
-//-------------------------------------------------
-// device_reset - device-specific reset
-//-------------------------------------------------
-
-void electron_expansion_slot_device::device_reset()
-{
-}
//-------------------------------------------------
// expbus_r - expansion data read
@@ -106,30 +95,42 @@ void electron_expansion_slot_device::expbus_w(offs_t offset, uint8_t data)
// slot devices
+#include "elksd64.h"
+#include "elksd128.h"
#include "fbjoy.h"
-//#include "fbprint.h"
-//#include "jafamode7.h"
+#include "fbprint.h"
+#include "mc68k.h"
+#include "mode7.h"
+//#include "lebox.h"
#include "plus1.h"
#include "plus2.h"
#include "plus3.h"
#include "pwrjoy.h"
#include "rombox.h"
#include "romboxp.h"
+#include "sidewndr.h"
#include "m2105.h"
-//#include "voxbox.h"
+#include "voxbox.h"
void electron_expansion_devices(device_slot_interface &device)
{
+ device.option_add("ap1", ELECTRON_AP1);
+ device.option_add("ap6", ELECTRON_AP6);
+ device.option_add("elksd64", ELECTRON_ELKSD64);
+ device.option_add("elksd128", ELECTRON_ELKSD128);
device.option_add("fbjoy", ELECTRON_FBJOY);
- //device.option_add("fbprint", ELECTRON_FBPRINT);
- //device.option_add("jafamode7", ELECTRON_JAFAMODE7);
+ device.option_add("fbprint", ELECTRON_FBPRINT);
+ device.option_add("mc68k", ELECTRON_MC68K);
+ device.option_add("mode7", ELECTRON_MODE7);
+ //device.option_add("lebox", ELECTRON_LEBOX);
device.option_add("plus1", ELECTRON_PLUS1);
device.option_add("plus2", ELECTRON_PLUS2);
device.option_add("plus3", ELECTRON_PLUS3);
device.option_add("pwrjoy", ELECTRON_PWRJOY);
device.option_add("rombox", ELECTRON_ROMBOX);
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 a3bfc045b3a..d36a9c75034 100644
--- a/src/devices/bus/electron/exp.h
+++ b/src/devices/bus/electron/exp.h
@@ -98,7 +98,7 @@ AC RETURNS (pins 3,4) - adaptor. A total of 6W may be drawn from these lines as
class device_electron_expansion_interface;
-class electron_expansion_slot_device : public device_t, public device_slot_interface
+class electron_expansion_slot_device : public device_t, public device_single_card_slot_interface<device_electron_expansion_interface>
{
public:
// construction/destruction
@@ -120,13 +120,12 @@ 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
- virtual void device_start() override;
- virtual void device_reset() override;
+ virtual void device_start() override ATTR_COLD;
device_electron_expansion_interface *m_card;
@@ -138,7 +137,7 @@ private:
// ======================> device_electron_expansion_interface
-class device_electron_expansion_interface : public device_slot_card_interface
+class device_electron_expansion_interface : public device_interface
{
public:
virtual uint8_t expbus_r(offs_t offset) { return 0xff; }
diff --git a/src/devices/bus/electron/fbjoy.cpp b/src/devices/bus/electron/fbjoy.cpp
index e5a4042cfeb..07c99d22bf6 100644
--- a/src/devices/bus/electron/fbjoy.cpp
+++ b/src/devices/bus/electron/fbjoy.cpp
@@ -11,55 +11,44 @@
#include "emu.h"
#include "fbjoy.h"
-//**************************************************************************
-// DEVICE DEFINITIONS
-//**************************************************************************
+#include "bus/vcs_ctrl/ctrl.h"
-DEFINE_DEVICE_TYPE(ELECTRON_FBJOY, electron_fbjoy_device, "electron_fbjoy", "First Byte Joystick Interface")
+namespace {
-static INPUT_PORTS_START( fbjoy )
- 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_NAME("Fire")
-INPUT_PORTS_END
-
-
-//-------------------------------------------------
-// input_ports - device-specific input ports
-//-------------------------------------------------
-
-ioport_constructor electron_fbjoy_device::device_input_ports() const
+class electron_fbjoy_device
+ : public device_t
+ , public device_electron_expansion_interface
{
- return INPUT_PORTS_NAME( fbjoy );
-}
+public:
+ electron_fbjoy_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
+ : device_t(mconfig, ELECTRON_FBJOY, tag, owner, clock)
+ , device_electron_expansion_interface(mconfig, *this)
+ , m_joy(*this, "joy")
+ {
+ }
+ virtual uint8_t expbus_r(offs_t offset) override;
-//**************************************************************************
-// LIVE DEVICE
-//**************************************************************************
+protected:
+ // device_t overrides
+ virtual void device_start() override ATTR_COLD { }
-//-------------------------------------------------
-// electron_fbjoy_device - constructor
-//-------------------------------------------------
+ // optional information overrides
+ virtual void device_add_mconfig(machine_config &config) override ATTR_COLD;
-electron_fbjoy_device::electron_fbjoy_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
- : device_t(mconfig, ELECTRON_FBJOY, tag, owner, clock)
- , device_electron_expansion_interface(mconfig, *this)
- , m_joy(*this, "JOY")
-{
-}
+private:
+ required_device<vcs_control_port_device> m_joy;
+};
//-------------------------------------------------
-// device_start - device-specific startup
+// device_add_mconfig - add device configuration
//-------------------------------------------------
-void electron_fbjoy_device::device_start()
+void electron_fbjoy_device::device_add_mconfig(machine_config &config)
{
+ VCS_CONTROL_PORT(config, m_joy, vcs_control_port_devices, "joy");
}
@@ -73,8 +62,13 @@ uint8_t electron_fbjoy_device::expbus_r(offs_t offset)
if (offset == 0xfcc0)
{
- data = m_joy->read() | 0xe0;
+ data = bitswap<8>(m_joy->read_joy(), 7, 6, 4, 5, 3, 2, 1, 0);
}
return data;
}
+
+} // anonymous namespace
+
+
+DEFINE_DEVICE_TYPE_PRIVATE(ELECTRON_FBJOY, device_electron_expansion_interface, electron_fbjoy_device, "electron_fbjoy", "First Byte Joystick Interface")
diff --git a/src/devices/bus/electron/fbjoy.h b/src/devices/bus/electron/fbjoy.h
index d9faaa6cd15..0d46202415b 100644
--- a/src/devices/bus/electron/fbjoy.h
+++ b/src/devices/bus/electron/fbjoy.h
@@ -1,51 +1,14 @@
// license:BSD-3-Clause
// copyright-holders:Nigel Barnes
-/**********************************************************************
-
- First Byte Switched Joystick Interface
-
- http://chrisacorns.computinghistory.org.uk/8bit_Upgrades/FirstByte_JoystickIF.html
-
-**********************************************************************/
-
#ifndef MAME_BUS_ELECTRON_FBJOY_H
#define MAME_BUS_ELECTRON_FBJOY_H
#pragma once
-
#include "exp.h"
-//**************************************************************************
-// TYPE DEFINITIONS
-//**************************************************************************
-
-// ======================> electron_fbjoy_device
-
-class electron_fbjoy_device :
- public device_t,
- public device_electron_expansion_interface
-{
-public:
- // construction/destruction
- electron_fbjoy_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;
-
- virtual uint8_t expbus_r(offs_t offset) override;
-
-protected:
- // device-level overrides
- virtual void device_start() override;
-
-private:
- required_ioport m_joy;
-};
-
// device type definition
-DECLARE_DEVICE_TYPE(ELECTRON_FBJOY, electron_fbjoy_device)
-
+DECLARE_DEVICE_TYPE(ELECTRON_FBJOY, device_electron_expansion_interface)
#endif // MAME_BUS_ELECTRON_FBJOY_H
diff --git a/src/devices/bus/electron/fbprint.cpp b/src/devices/bus/electron/fbprint.cpp
new file mode 100644
index 00000000000..00bb056db75
--- /dev/null
+++ b/src/devices/bus/electron/fbprint.cpp
@@ -0,0 +1,90 @@
+// license:BSD-3-Clause
+// copyright-holders:Nigel Barnes
+/**********************************************************************
+
+ First Byte Printer Interface
+
+**********************************************************************/
+
+
+#include "emu.h"
+#include "fbprint.h"
+
+
+//**************************************************************************
+// DEVICE DEFINITIONS
+//**************************************************************************
+
+DEFINE_DEVICE_TYPE(ELECTRON_FBPRINT, electron_fbprint_device, "electron_fbprint", "First Byte Printer Interface")
+
+
+//-------------------------------------------------
+// device_add_mconfig - add device configuration
+//-------------------------------------------------
+
+void electron_fbprint_device::device_add_mconfig(machine_config &config)
+{
+ /* printer */
+ CENTRONICS(config, m_centronics, centronics_devices, "printer");
+ m_centronics->busy_handler().set([this](int state) { m_centronics_busy = state; });
+ output_latch_device &latch(OUTPUT_LATCH(config, "cent_data_out"));
+ m_centronics->set_output_latch(latch);
+}
+
+//**************************************************************************
+// LIVE DEVICE
+//**************************************************************************
+
+//-------------------------------------------------
+// electron_fbprint_device - constructor
+//-------------------------------------------------
+
+electron_fbprint_device::electron_fbprint_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
+ : device_t(mconfig, ELECTRON_FBPRINT, tag, owner, clock)
+ , device_electron_expansion_interface(mconfig, *this)
+ , m_centronics(*this, "centronics")
+ , m_cent_data_out(*this, "cent_data_out")
+ , m_centronics_busy(0)
+{
+}
+
+
+//-------------------------------------------------
+// device_start - device-specific startup
+//-------------------------------------------------
+
+void electron_fbprint_device::device_start()
+{
+}
+
+
+//-------------------------------------------------
+// expbus_r - expansion data read
+//-------------------------------------------------
+
+uint8_t electron_fbprint_device::expbus_r(offs_t offset)
+{
+ uint8_t data = 0xff;
+
+ if (offset == 0xfc72)
+ {
+ data = (m_centronics_busy << 7) | 0x7f;
+ }
+
+ return data;
+}
+
+
+//-------------------------------------------------
+// expbus_w - expansion data write
+//-------------------------------------------------
+
+void electron_fbprint_device::expbus_w(offs_t offset, uint8_t data)
+{
+ if (offset == 0xfc71)
+ {
+ m_cent_data_out->write(data);
+ m_centronics->write_strobe(0);
+ m_centronics->write_strobe(1);
+ }
+}
diff --git a/src/devices/bus/electron/fbprint.h b/src/devices/bus/electron/fbprint.h
new file mode 100644
index 00000000000..041d88634fb
--- /dev/null
+++ b/src/devices/bus/electron/fbprint.h
@@ -0,0 +1,50 @@
+// license:BSD-3-Clause
+// copyright-holders:Nigel Barnes
+/**********************************************************************
+
+ First Byte Printer Interface
+
+**********************************************************************/
+
+
+#ifndef MAME_BUS_ELECTRON_FBPRINT_H
+#define MAME_BUS_ELECTRON_FBPRINT_H
+
+#include "exp.h"
+#include "bus/centronics/ctronics.h"
+
+
+//**************************************************************************
+// TYPE DEFINITIONS
+//**************************************************************************
+
+class electron_fbprint_device:
+ public device_t,
+ public device_electron_expansion_interface
+{
+public:
+ // construction/destruction
+ electron_fbprint_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
+
+protected:
+ // device-level overrides
+ virtual void device_start() override ATTR_COLD;
+
+ // optional information overrides
+ virtual void device_add_mconfig(machine_config &config) override ATTR_COLD;
+
+ virtual uint8_t expbus_r(offs_t offset) override;
+ virtual void expbus_w(offs_t offset, uint8_t data) override;
+
+ required_device<centronics_device> m_centronics;
+ required_device<output_latch_device> m_cent_data_out;
+
+ int m_centronics_busy;
+};
+
+
+// device type definition
+DECLARE_DEVICE_TYPE(ELECTRON_FBPRINT, electron_fbprint_device)
+
+
+#endif /* MAME_BUS_ELECTRON_FBPRINT_H */
diff --git a/src/devices/bus/electron/m2105.cpp b/src/devices/bus/electron/m2105.cpp
index a5edb8e3232..d2aa5da9f55 100644
--- a/src/devices/bus/electron/m2105.cpp
+++ b/src/devices/bus/electron/m2105.cpp
@@ -4,6 +4,10 @@
BT Merlin M2105
+ TODO:
+ - speech implementation is not verified
+ - modem
+
**********************************************************************/
@@ -25,28 +29,28 @@ DEFINE_DEVICE_TYPE(ELECTRON_M2105, electron_m2105_device, "electron_m2105", "Aco
ROM_START( m2105 )
ROM_REGION(0x10000, "exp_rom", 0)
- ROM_DEFAULT_BIOS("v350")
+ ROM_DEFAULT_BIOS("350")
- ROM_SYSTEM_BIOS(0, "v350", "V3.50 16/02/87")
+ ROM_SYSTEM_BIOS(0, "350", "V3.50 16/02/87")
ROMX_LOAD("ic22-sm-35l-1.ic22", 0x0000, 0x4000, CRC(e8f8a639) SHA1(eb7fa1e884be9c072ae0c1e598507b802422127f), ROM_BIOS(0))
ROMX_LOAD("ic23-sm-35l-1.ic23", 0x4000, 0x4000, CRC(b1bb1d83) SHA1(07ca3a93744519b8d03bbf1c3c3537c0a0a3c6fe), ROM_BIOS(0))
ROMX_LOAD("sk01-pc-35l-1.ic24", 0x8000, 0x4000, CRC(54fd4c09) SHA1(9588296306581580ba223cf6bce4be61476f14c4), ROM_BIOS(0))
ROMX_LOAD("sk02-pc-35l-1.ic24", 0xc000, 0x4000, CRC(c08de988) SHA1(86f2da5f8e9a5301ad40360e286f841f42e94a99), ROM_BIOS(0))
- ROM_SYSTEM_BIOS(1, "v341", "V3.41 26/11/85")
+ ROM_SYSTEM_BIOS(1, "341", "V3.41 26/11/85")
ROMX_LOAD("ic22-sm-34l-1.ic22", 0x0000, 0x4000, CRC(b514b15f) SHA1(a9c6c20b5a4f860b000511dde2f54497bcdd97b0), ROM_BIOS(1))
ROMX_LOAD("ic23-sm-34l-1.ic23", 0x4000, 0x4000, CRC(18875889) SHA1(d1a7dd87c4d99869a1961becec5e9d567d8fad53), ROM_BIOS(1))
ROMX_LOAD("sk01-pc-34l-1.ic24", 0x8000, 0x4000, CRC(a8796c9e) SHA1(29bc01b8f7617b252e4b243d13b1bbd3cd32cc3b), ROM_BIOS(1))
ROMX_LOAD("sk02-pc-34l-1.ic24", 0xc000, 0x4000, CRC(fa74063c) SHA1(cdc31c606e69e7a6d221b7340a310d475d487fc9), ROM_BIOS(1))
- ROM_SYSTEM_BIOS(2, "v207", "V2.07 14/03/85")
+ ROM_SYSTEM_BIOS(2, "207", "V2.07 14/03/85")
ROMX_LOAD("ic22-sm-207l-1.ic22", 0x0000, 0x4000, CRC(0c431547) SHA1(13d2eab49b9c79f507b7dd8436d1e56cf43be412), ROM_BIOS(2))
ROMX_LOAD("ic23-sm-207l-1.ic23", 0x4000, 0x4000, CRC(15044d49) SHA1(e75fe4321579a9027527a0e256050d1444b3fe82), ROM_BIOS(2))
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, "vsm", 0) /* system speech PHROM */
- 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
@@ -56,52 +60,75 @@ ROM_END
void electron_m2105_device::device_add_mconfig(machine_config &config)
{
- /* sound hardware */
- SPEAKER(config, "mono").front_center();
-
- INPUT_MERGER_ANY_HIGH(config, m_irqs).output_handler().set(DEVICE_SELF_OWNER, FUNC(electron_expansion_slot_device::irq_w));
-
- /* nvram */
- RAM(config, m_ram).set_default_size("64K");
-
- /* system via */
- VIA6522(config, m_via6522_0, DERIVED_CLOCK(1, 16));
- //m_via6522_0->readpa_handler().set(FUNC(electron_m2105_device::m2105_via_system_read_porta));
- m_via6522_0->readpb_handler().set(m_tms, FUNC(tms5220_device::status_r));
- //m_via6522_0->writepa_handler().set(FUNC(electron_m2105_device::m2105_via_system_write_porta));
- m_via6522_0->writepb_handler().set(m_tms, FUNC(tms5220_device::data_w));
- m_via6522_0->irq_handler().set(m_irqs, FUNC(input_merger_device::in_w<0>));
-
- /* user via */
- VIA6522(config, m_via6522_1, DERIVED_CLOCK(1, 16));
- m_via6522_1->writepb_handler().set("cent_data_out", FUNC(output_latch_device::bus_w));
- m_via6522_1->ca2_handler().set(m_centronics, FUNC(centronics_device::write_strobe));
- m_via6522_1->irq_handler().set(m_irqs, FUNC(input_merger_device::in_w<1>));
-
- /* duart */
- SCN2681(config, m_duart, XTAL(3'686'400)); // TODO: confirm clock
- m_duart->irq_cb().set(m_irqs, FUNC(input_merger_device::in_w<2>));
+ NVRAM(config, "nvram", nvram_device::DEFAULT_NONE);
+
+ 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("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));
+ m_via[0]->cb2_handler().set(m_via[1], FUNC(via6522_device::write_cb1));
+ m_via[0]->irq_handler().set("irqs", FUNC(input_merger_device::in_w<0>));
+
+ MOS6522(config, m_via[1], DERIVED_CLOCK(1, 16));
+ m_via[1]->writepa_handler().set("cent_data_out", FUNC(output_latch_device::write));
+ //m_via[1]->writepb_handler().set().bit(1); // DORELAY
+ m_via[1]->writepb_handler().append("modem", FUNC(rs232_port_device::write_dtr)).bit(2); // LSRELAY
+ //m_via[1]->readpb_handler().set().bit(3); // RA16
+ //m_via[1]->writepb_handler().set().bit(4); // DIALEN
+ //m_via[1]->writepb_handler().set().bit(5); // PULSE TRAIN
+ //m_via[1]->readpb_handler().set().bit(6); // RING
+ m_via[1]->ca2_handler().set("centronics", FUNC(centronics_device::write_strobe));
+ m_via[1]->irq_handler().set("irqs", FUNC(input_merger_device::in_w<1>));
+
+ SCN2681(config, m_duart, 3.6864_MHz_XTAL);
+ m_duart->irq_cb().set("irqs", FUNC(input_merger_device::in_w<2>));
m_duart->a_tx_cb().set("rs232", FUNC(rs232_port_device::write_txd));
- //m_duart->outport_cb().set(FUNC(electron_m2105_device::sio_out_w));
+ m_duart->b_tx_cb().set("modem", FUNC(rs232_port_device::write_txd));
+ m_duart->outport_cb().set("rs232", FUNC(rs232_port_device::write_rts)).bit(0);
+ m_duart->outport_cb().append("modem", FUNC(rs232_port_device::write_rts)).bit(1);
+ m_duart->outport_cb().append("rs232", FUNC(rs232_port_device::write_dtr)).bit(2);
+ m_duart->outport_cb().append("modem", FUNC(rs232_port_device::write_rts)).bit(5);
+
+ rs232_port_device &modem(RS232_PORT(config, "modem", default_rs232_devices, "null_modem")); // Am7910
+ modem.rxd_handler().set(m_duart, FUNC(scn2681_device::rx_b_w));
+ modem.cts_handler().set(m_duart, FUNC(scn2681_device::ip1_w));
+ modem.dcd_handler().set(m_duart, FUNC(scn2681_device::ip3_w));
rs232_port_device &rs232(RS232_PORT(config, "rs232", default_rs232_devices, nullptr));
rs232.rxd_handler().set(m_duart, FUNC(scn2681_device::rx_a_w));
+ rs232.cts_handler().set(m_duart, FUNC(scn2681_device::ip0_w));
+ rs232.dsr_handler().set(m_duart, FUNC(scn2681_device::ip5_w));
+ rs232.dcd_handler().set(m_duart, FUNC(scn2681_device::ip6_w));
- /* printer */
- CENTRONICS(config, m_centronics, centronics_devices, "printer");
- m_centronics->ack_handler().set(m_via6522_1, FUNC(via6522_device::write_ca1)).invert(); // ack seems to be inverted?
- output_latch_device &latch(OUTPUT_LATCH(config, "cent_data_out"));
- m_centronics->set_output_latch(latch);
+ centronics_device &centronics(CENTRONICS(config, "centronics", centronics_devices, "printer"));
+ centronics.ack_handler().set(m_via[1], FUNC(via6522_device::write_ca1));
+ centronics.busy_handler().set(m_via[1], FUNC(via6522_device::write_pb0));
+ centronics.select_handler().set(m_via[1], FUNC(via6522_device::write_pb7));
+ centronics.select_handler().append(m_via[1], FUNC(via6522_device::write_cb2));
- /* AM7910 modem */
+ output_latch_device &latch(OUTPUT_LATCH(config, "cent_data_out"));
+ centronics.set_output_latch(latch);
+
+ tms5220_device &tms(TMS5220(config, "vsp", 640000));
+ 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.add_route(ALL_OUTPUTS, "mono", 0.5);
+
+ TMS6100(config, "vsm", 0);
+ tms.m0_cb().set("vsm", FUNC(tms6100_device::m0_w));
+ tms.m1_cb().set("vsm", FUNC(tms6100_device::m1_w));
+ tms.addr_cb().set("vsm", FUNC(tms6100_device::add_w));
+ tms.data_cb().set("vsm", FUNC(tms6100_device::data_line_r));
+ tms.romclk_cb().set("vsm", FUNC(tms6100_device::clk_w));
- /* speech hardware */
- SPEECHROM(config, "vsm", 0);
- TMS5220(config, m_tms, 640000);
- m_tms->set_speechrom_tag("vsm");
- //m_tms->irq_handler().set(m_via6522_0, FUNC(via6522_device::write_cb1));
- //m_tms->readyq_handler().set(m_via6522_0, FUNC(via6522_device::write_cb2));
- m_tms->add_route(ALL_OUTPUTS, "mono", 1.0);
+ SPEAKER(config, "mono").front_center();
}
const tiny_rom_entry *electron_m2105_device::device_rom_region() const
@@ -121,13 +148,9 @@ electron_m2105_device::electron_m2105_device(const machine_config &mconfig, cons
: device_t(mconfig, ELECTRON_M2105, tag, owner, clock)
, device_electron_expansion_interface(mconfig, *this)
, m_exp_rom(*this, "exp_rom")
- , m_ram(*this, RAM_TAG)
- , m_via6522_0(*this, "via6522_0")
- , m_via6522_1(*this, "via6522_1")
+ , m_nvram(*this, "nvram")
+ , m_via(*this, "via%u", 0U)
, m_duart(*this, "duart")
- , m_tms(*this, "tms5220")
- , m_centronics(*this, "centronics")
- , m_irqs(*this, "irqs")
, m_ram_page(0)
, m_romsel(0)
{
@@ -139,15 +162,11 @@ electron_m2105_device::electron_m2105_device(const machine_config &mconfig, cons
void electron_m2105_device::device_start()
{
- save_item(NAME(m_ram_page));
-}
+ m_ram = std::make_unique<uint8_t[]>(0x10000);
+ m_nvram->set_base(m_ram.get(), 0x10000);
-//-------------------------------------------------
-// device_reset - device-specific reset
-//-------------------------------------------------
-
-void electron_m2105_device::device_reset()
-{
+ save_item(NAME(m_ram_page));
+ save_pointer(NAME(m_ram), 0x10000);
}
//-------------------------------------------------
@@ -166,18 +185,18 @@ uint8_t electron_m2105_device::expbus_r(offs_t offset)
case 0xb:
switch (m_romsel)
{
- case 0:
- data = m_exp_rom->base()[0x8000 | (offset & 0x3fff)];
- break;
- case 2:
- data = m_exp_rom->base()[0xc000 | (offset & 0x3fff)];
- break;
- case 12:
+ case 0: case 12:
data = m_exp_rom->base()[0x0000 | (offset & 0x3fff)];
break;
- case 13:
+ case 1: case 13:
data = m_exp_rom->base()[0x4000 | (offset & 0x3fff)];
break;
+ case 2: case 14:
+ data = m_exp_rom->base()[0x8000 | (offset & 0x3fff)];
+ break;
+ case 3: case 15:
+ data = m_exp_rom->base()[0xc000 | (offset & 0x3fff)];
+ break;
}
break;
@@ -185,24 +204,22 @@ uint8_t electron_m2105_device::expbus_r(offs_t offset)
switch (offset >> 8)
{
case 0xfc:
- logerror("read %04x\n", offset);
- if (offset >= 0xfc50 && offset < 0xfc60)
+ switch (offset & 0xf0)
{
+ case 0x50:
data = m_duart->read(offset & 0x0f);
- }
- else if (offset >= 0xfc60 && offset < 0xfc70)
- {
- data = m_via6522_1->read(offset & 0x0f);
- }
- else if (offset >= 0xfc70 && offset < 0xfc80)
- {
- data = m_via6522_0->read(offset & 0x0f);
+ break;
+ case 0x60:
+ data = m_via[0]->read(offset & 0x0f);
+ break;
+ case 0x70:
+ data = m_via[1]->read(offset & 0x0f);
+ break;
}
break;
case 0xfd:
- //if (m_ram_page < 0x80)
- data = m_ram->pointer()[(m_ram_page << 8) | (offset & 0xff)];
+ data = m_ram[(m_ram_page << 8) | (offset & 0xff)];
break;
}
}
@@ -222,32 +239,29 @@ void electron_m2105_device::expbus_w(offs_t offset, uint8_t data)
switch (offset >> 8)
{
case 0xfc:
- logerror("write %04x %02x\n", offset, data);
- if (offset >= 0xfc50 && offset < 0xfc60)
+ switch (offset & 0xf0)
{
+ case 0x50:
m_duart->write(offset & 0x0f, data);
- }
- else if (offset >= 0xfc60 && offset < 0xfc70)
- {
- m_via6522_1->write(offset & 0x0f, data);
- }
- else if (offset >= 0xfc70 && offset < 0xfc80)
- {
- m_via6522_0->write(offset & 0x0f, data);
- }
- else if (offset == 0xfcff)
- {
+ break;
+ case 0x60:
+ m_via[0]->write(offset & 0x0f, data);
+ break;
+ case 0x70:
+ m_via[1]->write(offset & 0x0f, data);
+ break;
+ case 0xf0:
m_ram_page = data;
+ break;
}
break;
case 0xfd:
- //if (m_ram_page < 0x80)
- m_ram->pointer()[(m_ram_page << 8) | (offset & 0xff)] = data;
+ m_ram[(m_ram_page << 8) | (offset & 0xff)] = data;
break;
case 0xfe:
- if (offset == 0xfe05)
+ if ((offset == 0xfe05) && !(data & 0xf0))
{
m_romsel = data & 0x0f;
}
diff --git a/src/devices/bus/electron/m2105.h b/src/devices/bus/electron/m2105.h
index c09f4722eab..152f229a96c 100644
--- a/src/devices/bus/electron/m2105.h
+++ b/src/devices/bus/electron/m2105.h
@@ -6,16 +6,17 @@
**********************************************************************/
-#ifndef MAME_BUS_ELECTRON_M2105_M
-#define MAME_BUS_ELECTRON_M2105_M
+#ifndef MAME_BUS_ELECTRON_M2105_H
+#define MAME_BUS_ELECTRON_M2105_H
#pragma once
#include "exp.h"
-#include "machine/ram.h"
#include "machine/6522via.h"
#include "machine/mc68681.h"
+#include "machine/nvram.h"
#include "machine/input_merger.h"
+#include "machine/tms6100.h"
#include "sound/tms5220.h"
#include "bus/centronics/ctronics.h"
#include "bus/rs232/rs232.h"
@@ -34,26 +35,22 @@ public:
electron_m2105_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_start() override ATTR_COLD;
// optional information overrides
- virtual void device_add_mconfig(machine_config &config) override;
- virtual const tiny_rom_entry *device_rom_region() const override;
+ virtual void device_add_mconfig(machine_config &config) override ATTR_COLD;
+ virtual const tiny_rom_entry *device_rom_region() const override ATTR_COLD;
virtual uint8_t expbus_r(offs_t offset) override;
virtual void expbus_w(offs_t offset, uint8_t data) override;
private:
required_memory_region m_exp_rom;
- required_device<ram_device> m_ram;
- required_device<via6522_device> m_via6522_0;
- required_device<via6522_device> m_via6522_1;
+ required_device<nvram_device> m_nvram;
+ required_device_array<via6522_device, 2> m_via;
required_device<scn2681_device> m_duart;
- required_device<tms5220_device> m_tms;
- required_device<centronics_device> m_centronics;
- required_device<input_merger_device> m_irqs;
+ std::unique_ptr<uint8_t[]> m_ram;
uint8_t m_ram_page;
uint8_t m_romsel;
};
@@ -62,5 +59,4 @@ private:
// device type definition
DECLARE_DEVICE_TYPE(ELECTRON_M2105, electron_m2105_device)
-
-#endif // MAME_BUS_ELECTRON_M2105_M
+#endif // MAME_BUS_ELECTRON_M2105_H
diff --git a/src/devices/bus/electron/mc68k.cpp b/src/devices/bus/electron/mc68k.cpp
new file mode 100644
index 00000000000..8963527c19b
--- /dev/null
+++ b/src/devices/bus/electron/mc68k.cpp
@@ -0,0 +1,246 @@
+// license:BSD-3-Clause
+// copyright-holders:Nigel Barnes
+/**********************************************************************
+
+ Electron 68000 Expansion
+
+ This is a homebrew 68000 second processor for the Electron from around 1990.
+
+ Commands:
+ *FX29 - sends a short stub to the 68000 which tells it to:
+ (a) start the 68000 OS in ROM now.
+ (b) start the 68000 OS on every reset from now on, until the next
+ CTRL+BREAK or power cycle.
+ *FX28 - tells sideways bank 12 to make itself the current language ROM on the
+ 6502, and the language entry point tells the 68000 to start the BASIC
+ interpreter in ROM, but the 68000 OS has to be currently running.
+
+ BREAK will restart the current language ROM, so will restart 68000 BASIC.
+ CTRL+BREAK will go back to 6502 BASIC as the language ROM.
+
+ Usage notes:
+ - to enter 68000 BASIC do *FX29, then *FX28, then BREAK.
+ - to start the word processor, do CALL&407000 from the 68000 BASIC prompt.
+ - to use the assembler, type your assembly code in as a BASIC program, with
+ instruction mnemonics in lower case. Set D% to where in RAM you want the
+ object code stored and P% to 2, then CALL&401C8C.
+
+**********************************************************************/
+
+
+#include "emu.h"
+#include "mc68k.h"
+
+#include "machine/6522via.h"
+#include "machine/6850acia.h"
+#include "machine/clock.h"
+#include "machine/input_merger.h"
+
+
+//**************************************************************************
+// DEVICE DEFINITIONS
+//**************************************************************************
+
+DEFINE_DEVICE_TYPE(ELECTRON_MC68K, electron_mc68k_device, "electron_mc68k", "Electron 68000 Expansion")
+
+
+
+//-------------------------------------------------
+// ADDRESS_MAP( mem_map )
+//-------------------------------------------------
+
+void electron_mc68k_device::mem_map(address_map &map)
+{
+ map(0x000000, 0x00ffff).ram();
+ map(0x400000, 0x40ffff).rom().region("main_rom", 0);
+ map(0x800000, 0x800fff).rom().region("boot_rom", 0);
+ map(0xff8000, 0xff801f).rw("via", FUNC(via6522_device::read), FUNC(via6522_device::write)).umask16(0xff00);
+ map(0xff8020, 0xff803f).rw(m_pia[0], FUNC(pia6821_device::read), FUNC(pia6821_device::write)).umask16(0xff00);
+ map(0xff8040, 0xff805f).rw("acia", FUNC(acia6850_device::read), FUNC(acia6850_device::write)).umask16(0xff00);
+}
+
+//-------------------------------------------------
+// ROM( mc68k )
+//-------------------------------------------------
+
+ROM_START( mc68k )
+ ROM_REGION(0x8000, "exp_rom", 0)
+ ROM_LOAD("elk68k_lower.bin", 0x0000, 0x4000, CRC(6e18f9fb) SHA1(31d228e4b6be18c51dd6a0c42c9e6e1e507decc6))
+ ROM_LOAD("elk68k_upper.bin", 0x4000, 0x4000, CRC(0c960571) SHA1(cf3a060fee7ac23128d9e4657790d218681e6e61))
+
+ ROM_REGION16_BE(0x1000, "boot_rom", ROMREGION_ERASE00)
+ ROM_LOAD("68kboot.bin", 0x0000, 0x0100, CRC(5855ef60) SHA1(76165ee0f34a24fd2a908987fd5f05e23ea75677))
+
+ ROM_REGION16_BE(0x10000, "main_rom", ROMREGION_ERASE00)
+ ROM_LOAD("68kmain.bin", 0x0000, 0x10000, CRC(4d7a9e4f) SHA1(90afb5910995511ae943ad62ea2967eff85e8ef7))
+ROM_END
+
+
+//-------------------------------------------------
+// device_add_mconfig - add device configuration
+//-------------------------------------------------
+
+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->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);
+ INPUT_MERGER_ANY_HIGH(config, "irq_exp").output_handler().set(DEVICE_SELF_OWNER, FUNC(electron_expansion_slot_device::irq_w));
+
+ RAM(config, m_ram).set_default_size("256K").set_extra_options("64K,128K,192K");
+
+ 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]);
+ 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));
+ m_pia[1]->irqa_handler().set("irq_exp", FUNC(input_merger_device::in_w<0>));
+ m_pia[1]->irqb_handler().set("irq_exp", FUNC(input_merger_device::in_w<1>));
+
+ via6522_device &via(MOS6522(config, "via", 10_MHz_XTAL / 10));
+ via.irq_handler().set("irq_ipl1", FUNC(input_merger_device::in_w<0>));
+
+ acia6850_device &acia(ACIA6850(config, "acia", 0));
+ acia.irq_handler().set("irq_ipl1", FUNC(input_merger_device::in_w<1>));
+
+ clock_device &acia_clock(CLOCK(config, "acia_clock", 3.6864_MHz_XTAL / 12));
+ acia_clock.signal_handler().set("acia", FUNC(acia6850_device::write_txc));
+ acia_clock.signal_handler().append("acia", FUNC(acia6850_device::write_rxc));
+}
+
+const tiny_rom_entry *electron_mc68k_device::device_rom_region() const
+{
+ return ROM_NAME( mc68k );
+}
+
+//**************************************************************************
+// LIVE DEVICE
+//**************************************************************************
+
+//-------------------------------------------------
+// electron_mc68k_device - constructor
+//-------------------------------------------------
+
+electron_mc68k_device::electron_mc68k_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock)
+ : device_t(mconfig, ELECTRON_MC68K, tag, owner, clock)
+ , device_electron_expansion_interface(mconfig, *this)
+ , m_maincpu(*this, "maincpu")
+ , m_ram(*this, RAM_TAG)
+ , m_pia(*this, "pia%u", 0U)
+ , m_boot_rom(*this, "boot_rom")
+ , m_exp_rom(*this, "exp_rom")
+ , m_romsel(0)
+{
+}
+
+//-------------------------------------------------
+// device_start - device-specific startup
+//-------------------------------------------------
+
+void electron_mc68k_device::device_start()
+{
+ save_item(NAME(m_romsel));
+}
+
+//-------------------------------------------------
+// device_reset - device-specific reset
+//-------------------------------------------------
+
+void electron_mc68k_device::device_reset()
+{
+ address_space &program = m_maincpu->space(AS_PROGRAM);
+
+ // address map during booting
+ program.install_rom(0x0000, 0x0fff, m_boot_rom->base());
+
+ m_rom_shadow_tap.remove();
+ m_rom_shadow_tap = program.install_read_tap(
+ 0x800000, 0xffffff,
+ "rom_shadow_r",
+ [this] (offs_t offset, u16 &data, u16 mem_mask)
+ {
+ if (!machine().side_effects_disabled())
+ {
+ // delete this tap
+ m_rom_shadow_tap.remove();
+
+ // address map after booting
+ m_maincpu->space(AS_PROGRAM).install_ram(0x000000, m_ram->mask(), m_ram->pointer());
+ }
+ },
+ &m_rom_shadow_tap);
+}
+
+//-------------------------------------------------
+// expbus_r - expansion data read
+//-------------------------------------------------
+
+u8 electron_mc68k_device::expbus_r(offs_t offset)
+{
+ u8 data = 0xff;
+
+ switch (offset >> 12)
+ {
+ case 0x8: case 0x9: case 0xa: case 0xb:
+ switch (m_romsel)
+ {
+ case 12:
+ data = m_exp_rom->base()[0x0000 | (offset & 0x3fff)];
+ break;
+ case 13:
+ data = m_exp_rom->base()[0x4000 | (offset & 0x3fff)];
+ break;
+ }
+ break;
+
+ case 0xf:
+ switch (offset >> 8)
+ {
+ case 0xfd:
+ switch (offset & 0xf8)
+ {
+ case 0x80:
+ data = m_pia[1]->read_alt(offset);
+ break;
+ }
+ break;
+ }
+ }
+
+ return data;
+}
+
+//-------------------------------------------------
+// expbus_w - expansion data write
+//-------------------------------------------------
+
+void electron_mc68k_device::expbus_w(offs_t offset, u8 data)
+{
+ switch (offset >> 8)
+ {
+ case 0xfd:
+ switch (offset & 0xf8)
+ {
+ case 0x80:
+ m_pia[1]->write_alt(offset, data);
+ break;
+ }
+ break;
+
+ case 0xfe:
+ if (offset == 0xfe05)
+ {
+ m_romsel = data & 0x0f;
+ }
+ break;
+ }
+}
diff --git a/src/devices/bus/electron/mc68k.h b/src/devices/bus/electron/mc68k.h
new file mode 100644
index 00000000000..67c23eba8a6
--- /dev/null
+++ b/src/devices/bus/electron/mc68k.h
@@ -0,0 +1,62 @@
+// license:BSD-3-Clause
+// copyright-holders:Nigel Barnes
+/**********************************************************************
+
+ Electron 68000 Expansion
+
+**********************************************************************/
+
+#ifndef MAME_BUS_ELECTRON_MC68K_H
+#define MAME_BUS_ELECTRON_MC68K_H
+
+#pragma once
+
+#include "exp.h"
+#include "cpu/m68000/m68000.h"
+#include "machine/6821pia.h"
+#include "machine/ram.h"
+
+
+//**************************************************************************
+// TYPE DEFINITIONS
+//**************************************************************************
+
+class electron_mc68k_device:
+ public device_t,
+ public device_electron_expansion_interface
+{
+public:
+ // construction/destruction
+ electron_mc68k_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
+
+protected:
+ // device-level overrides
+ virtual void device_start() override ATTR_COLD;
+ virtual void device_reset() override ATTR_COLD;
+
+ // optional information overrides
+ virtual void device_add_mconfig(machine_config &config) override ATTR_COLD;
+ virtual const tiny_rom_entry *device_rom_region() const override ATTR_COLD;
+
+ virtual u8 expbus_r(offs_t offset) override;
+ virtual void expbus_w(offs_t offset, u8 data) override;
+
+private:
+ required_device<m68000_base_device> m_maincpu;
+ required_device<ram_device> m_ram;
+ required_device_array<pia6821_device, 2> m_pia;
+ required_memory_region m_boot_rom;
+ required_memory_region m_exp_rom;
+
+ memory_passthrough_handler m_rom_shadow_tap;
+
+ void mem_map(address_map &map) ATTR_COLD;
+
+ u8 m_romsel;
+};
+
+
+// device type definition
+DECLARE_DEVICE_TYPE(ELECTRON_MC68K, electron_mc68k_device)
+
+#endif // MAME_BUS_ELECTRON_MC68K_H
diff --git a/src/devices/bus/electron/mode7.cpp b/src/devices/bus/electron/mode7.cpp
new file mode 100644
index 00000000000..e13ecc2aed5
--- /dev/null
+++ b/src/devices/bus/electron/mode7.cpp
@@ -0,0 +1,235 @@
+// license:BSD-3-Clause
+// copyright-holders:Nigel Barnes
+/**********************************************************************
+
+ JAFA Mode 7 Display Unit
+
+ TODO:
+ The SAA5050 output is currently being sent to a separate screen, it
+ should be output to the same screen as the Electron.
+ The Electron video output is 640x312 whereas the SAA5050 output is
+ 480x500 (doubled vertically to account for interlace). Only one
+ output is ever active at any time, which is selected by the MA13
+ line from the HD6845.
+
+**********************************************************************/
+
+
+#include "emu.h"
+#include "mode7.h"
+
+
+//**************************************************************************
+// DEVICE DEFINITIONS
+//**************************************************************************
+
+DEFINE_DEVICE_TYPE(ELECTRON_MODE7, electron_mode7_device, "electron_mode7", "JAFA Mode 7 Display Unit")
+
+
+//-------------------------------------------------
+// ROM( mode7 )
+//-------------------------------------------------
+
+ROM_START( mode7 )
+ ROM_REGION(0x2000, "exp_rom", 0)
+ ROM_SYSTEM_BIOS(0, "191", "Mode 7 OS v1.91")
+ ROMX_LOAD("mode7_1.91.rom", 0x0000, 0x2000, CRC(1863bfe6) SHA1(a18c12c8e4bcd5284aac5b0f0a33dc040176084a), ROM_BIOS(0))
+ ROM_SYSTEM_BIOS(1, "15", "Mode 7 OS v1.5")
+ ROMX_LOAD("mode7_1.5.rom", 0x0000, 0x2000, CRC(eeea69ee) SHA1(3689a6ca8693fa9a6e53a02cf34d613303cb34d7), ROM_BIOS(1))
+ROM_END
+
+//-------------------------------------------------
+// INPUT_PORTS( mode7 )
+//-------------------------------------------------
+
+static INPUT_PORTS_START( mode7 )
+ PORT_START("BUTTON")
+ PORT_BIT(0x01, IP_ACTIVE_LOW, IPT_BUTTON1) PORT_NAME("Mode 7 Break") PORT_CODE(KEYCODE_HOME) PORT_CHANGED_MEMBER(DEVICE_SELF, FUNC(electron_mode7_device::break_button), 0)
+INPUT_PORTS_END
+
+//-------------------------------------------------
+// input_ports - device-specific input ports
+//-------------------------------------------------
+
+ioport_constructor electron_mode7_device::device_input_ports() const
+{
+ return INPUT_PORTS_NAME( mode7 );
+}
+
+//-------------------------------------------------
+// device_add_mconfig - add device configuration
+//-------------------------------------------------
+
+void electron_mode7_device::device_add_mconfig(machine_config &config)
+{
+ /* video hardware */
+ SCREEN(config, m_screen, SCREEN_TYPE_RASTER);
+ m_screen->set_raw(16_MHz_XTAL, 768, 0, 480, 622, 0, 500);
+ m_screen->set_screen_update("hd6845", FUNC(hd6845s_device::screen_update));
+
+ HD6845S(config, m_hd6845, DERIVED_CLOCK(1, 8)); // FIXME: double clock until interlace is implemented
+ m_hd6845->set_screen("screen");
+ m_hd6845->set_show_border_area(false);
+ m_hd6845->set_char_width(12);
+ m_hd6845->set_update_row_callback(FUNC(electron_mode7_device::crtc_update_row));
+ m_hd6845->out_vsync_callback().set(FUNC(electron_mode7_device::vsync_changed));
+
+ SAA5050(config, m_trom, 6_MHz_XTAL);
+
+ /* pass-through */
+ ELECTRON_EXPANSION_SLOT(config, m_exp, DERIVED_CLOCK(1, 1), electron_expansion_devices, nullptr);
+ m_exp->irq_handler().set(DEVICE_SELF_OWNER, FUNC(electron_expansion_slot_device::irq_w));
+ m_exp->nmi_handler().set(DEVICE_SELF_OWNER, FUNC(electron_expansion_slot_device::nmi_w));
+}
+
+const tiny_rom_entry *electron_mode7_device::device_rom_region() const
+{
+ return ROM_NAME( mode7 );
+}
+
+//**************************************************************************
+// LIVE DEVICE
+//**************************************************************************
+
+//-------------------------------------------------
+// electron_mode7_device - constructor
+//-------------------------------------------------
+
+electron_mode7_device::electron_mode7_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
+ : device_t(mconfig, ELECTRON_MODE7, tag, owner, clock)
+ , device_electron_expansion_interface(mconfig, *this)
+ , m_screen(*this, "screen")
+ , m_hd6845(*this, "hd6845")
+ , m_trom(*this, "saa5050")
+ , m_exp(*this, "exp")
+ , m_exp_rom(*this, "exp_rom")
+ , m_romsel(0)
+{
+}
+
+//-------------------------------------------------
+// device_start - device-specific startup
+//-------------------------------------------------
+
+void electron_mode7_device::device_start()
+{
+ m_videoram = make_unique_clear<uint8_t[]>(0x800);
+
+ /* register for save states */
+ save_pointer(NAME(m_videoram), 0x800);
+ save_item(NAME(m_romsel));
+}
+
+//-------------------------------------------------
+// expbus_r - expansion data read
+//-------------------------------------------------
+
+uint8_t electron_mode7_device::expbus_r(offs_t offset)
+{
+ uint8_t data = 0xff;
+
+ if (offset >= 0x7c00 && offset < 0x8000)
+ {
+ data = m_videoram[offset & 0x3ff];
+ }
+ else if (offset >= 0x8000 && offset < 0xc000)
+ {
+ if (m_romsel == 15)
+ {
+ data = m_exp_rom->base()[offset & 0x1fff];
+ }
+ }
+ else
+ {
+ switch (offset)
+ {
+ case 0xfc1e:
+ data = m_hd6845->status_r();
+ break;
+ case 0xfc1f:
+ data = m_hd6845->register_r();
+ break;
+ }
+ }
+
+ data &= m_exp->expbus_r(offset);
+
+ return data;
+}
+
+//-------------------------------------------------
+// expbus_w - expansion data write
+//-------------------------------------------------
+
+void electron_mode7_device::expbus_w(offs_t offset, uint8_t data)
+{
+ if (offset >= 0x7c00 && offset < 0x8000)
+ {
+ m_videoram[offset & 0x3ff] = data & 0x7f;
+ }
+ else
+ {
+ switch (offset)
+ {
+ case 0xfc1c:
+ m_hd6845->address_w(data);
+ break;
+ case 0xfc1d:
+ m_hd6845->register_w(data);
+ break;
+
+ case 0xfe05:
+ if ((data & 0xf0) != 0xf0)
+ m_romsel = data & 0x0f;
+ break;
+ }
+ }
+
+ m_exp->expbus_w(offset, data);
+}
+
+
+//**************************************************************************
+// IMPLEMENTATION
+//**************************************************************************
+
+MC6845_UPDATE_ROW(electron_mode7_device::crtc_update_row)
+{
+ uint32_t* p = &bitmap.pix(y);
+
+ m_trom->lose_w(1);
+ m_trom->lose_w(0);
+
+ for (int column = 0; column < x_count; column++)
+ {
+ m_trom->write(m_videoram[(ma + column) & 0x3ff]);
+
+ m_trom->f1_w(1);
+ m_trom->f1_w(0);
+
+ for (int bit = 0; bit < 12; bit++)
+ {
+ m_trom->tr6_w(1);
+ m_trom->tr6_w(0);
+
+ int col = m_trom->get_rgb() ^ ((column == cursor_x) ? 7 : 0);
+
+ int r = BIT(col, 0) * 0xff;
+ int g = BIT(col, 1) * 0xff;
+ int b = BIT(col, 2) * 0xff;
+
+ *p++ = rgb_t(r, g, b);
+ }
+ }
+}
+
+void electron_mode7_device::vsync_changed(int state)
+{
+ m_trom->dew_w(state);
+}
+
+
+INPUT_CHANGED_MEMBER(electron_mode7_device::break_button)
+{
+ m_slot->nmi_w(!newval);
+}
diff --git a/src/devices/bus/electron/mode7.h b/src/devices/bus/electron/mode7.h
new file mode 100644
index 00000000000..8e0c02ec2f8
--- /dev/null
+++ b/src/devices/bus/electron/mode7.h
@@ -0,0 +1,66 @@
+// license:BSD-3-Clause
+// copyright-holders:Nigel Barnes
+/**********************************************************************
+
+ JAFA Mode 7 Display Unit
+
+**********************************************************************/
+
+#ifndef MAME_BUS_ELECTRON_MODE7_H
+#define MAME_BUS_ELECTRON_MODE7_H
+
+#include "exp.h"
+#include "video/mc6845.h"
+#include "video/saa5050.h"
+#include "screen.h"
+
+
+//**************************************************************************
+// TYPE DEFINITIONS
+//**************************************************************************
+
+class electron_mode7_device:
+ public device_t,
+ public device_electron_expansion_interface
+{
+public:
+ static constexpr feature_type imperfect_features() { return feature::GRAPHICS; }
+
+ // construction/destruction
+ electron_mode7_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
+
+ DECLARE_INPUT_CHANGED_MEMBER(break_button);
+
+protected:
+ // device-level overrides
+ virtual void device_start() override ATTR_COLD;
+
+ // optional information overrides
+ virtual void device_add_mconfig(machine_config &config) override ATTR_COLD;
+ virtual const tiny_rom_entry *device_rom_region() const override ATTR_COLD;
+ virtual ioport_constructor device_input_ports() const override ATTR_COLD;
+
+ virtual uint8_t expbus_r(offs_t offset) override;
+ virtual void expbus_w(offs_t offset, uint8_t data) override;
+
+private:
+ required_device<screen_device> m_screen;
+ required_device<mc6845_device> m_hd6845;
+ required_device<saa5050_device> m_trom;
+ required_device<electron_expansion_slot_device> m_exp;
+ required_memory_region m_exp_rom;
+
+ std::unique_ptr<uint8_t[]> m_videoram;
+
+ MC6845_UPDATE_ROW(crtc_update_row);
+ void vsync_changed(int state);
+
+ uint8_t m_romsel;
+};
+
+
+// device type definition
+DECLARE_DEVICE_TYPE(ELECTRON_MODE7, electron_mode7_device)
+
+
+#endif // MAME_BUS_ELECTRON_MODE7_H
diff --git a/src/devices/bus/electron/plus1.cpp b/src/devices/bus/electron/plus1.cpp
index a96ad20c656..349dcf9e5c7 100644
--- a/src/devices/bus/electron/plus1.cpp
+++ b/src/devices/bus/electron/plus1.cpp
@@ -23,6 +23,8 @@
//**************************************************************************
DEFINE_DEVICE_TYPE(ELECTRON_PLUS1, electron_plus1_device, "electron_plus1", "Acorn Plus 1 Expansion")
+DEFINE_DEVICE_TYPE(ELECTRON_AP1, electron_ap1_device, "electron_ap1", "P.R.E.S. Advanced Plus 1")
+DEFINE_DEVICE_TYPE(ELECTRON_AP6, electron_ap6_device, "electron_ap6", "P.R.E.S. Advanced Plus 6")
//-------------------------------------------------
@@ -36,54 +38,59 @@ ROM_START( plus1 )
ROM_SYSTEM_BIOS(0, "plus1", "Expansion 1.00")
ROMX_LOAD("plus1.rom", 0x0000, 0x1000, CRC(ac30b0ed) SHA1(2de04ab7c81414d6c9c967f965c53fc276392463), ROM_BIOS(0))
ROM_RELOAD( 0x1000, 0x1000)
+ROM_END
- ROM_SYSTEM_BIOS(1, "presap1", "PRES Expansion 1.1")
- ROMX_LOAD("presplus1.rom", 0x0000, 0x1000, CRC(8ef1e0e5) SHA1(080e1b788b3fe4fa272cd2cc792293eb7b874e82), ROM_BIOS(1))
+ROM_START( ap1 )
+ // Bank 12 Expansion module operating system
+ ROM_REGION( 0x2000, "exp_rom", 0 )
+ ROM_DEFAULT_BIOS("ap2")
+ ROM_SYSTEM_BIOS(0, "ap1", "PRES Expansion 1.1")
+ ROMX_LOAD("presplus1.rom", 0x0000, 0x1000, CRC(8ef1e0e5) SHA1(080e1b788b3fe4fa272cd2cc792293eb7b874e82), ROM_BIOS(0))
ROM_RELOAD( 0x1000, 0x1000)
- ROM_SYSTEM_BIOS(2, "presap2", "PRES AP2 Support 1.23")
- ROMX_LOAD("presap2_123.rom", 0x0000, 0x2000, CRC(f796689c) SHA1(bc40a79e6d2b4cb5e549d5d21f673c66a661850d), ROM_BIOS(2))
-
- ROM_SYSTEM_BIOS(3, "sl200", "Slogger Expansion 2.00")
- ROMX_LOAD("elkexp200.rom", 0x0000, 0x2000, CRC(dee02843) SHA1(5c9b940b4ddb46e9a223160310683a32266300c8), ROM_BIOS(3))
+ ROM_SYSTEM_BIOS(1, "ap2", "PRES AP2 Support 1.23")
+ ROMX_LOAD("presap2_123.rom", 0x0000, 0x2000, CRC(f796689c) SHA1(bc40a79e6d2b4cb5e549d5d21f673c66a661850d), ROM_BIOS(1))
- ROM_SYSTEM_BIOS(4, "sl201", "Slogger Expansion 2.01")
- ROMX_LOAD("elkexp201.rom", 0x0000, 0x2000, CRC(0e896892) SHA1(4e0794f1083fe529b01bd4fa100996a533ed8b10), ROM_BIOS(4))
+ ROM_SYSTEM_BIOS(2, "ap6", "RH Plus 1 1.33")
+ ROMX_LOAD("ap6v133.rom", 0x0000, 0x2000, CRC(566c7bfe) SHA1(f1053109ea236dd3e4b91ec64859480e8c2ed549), ROM_BIOS(2))
+ROM_END
- ROM_SYSTEM_BIOS(5, "sl202", "Slogger Expansion 2.02")
- ROMX_LOAD("elkexp202.rom", 0x0000, 0x2000, CRC(32b440be) SHA1(dbc73e8d919c5615d0241d99db60e06324e16c86), ROM_BIOS(5))
+ROM_START( ap6 )
+ // Bank 12 Expansion module operating system
+ ROM_REGION( 0x4000, "exp_rom", 0 )
+ ROM_DEFAULT_BIOS("ap6")
+ ROM_SYSTEM_BIOS(0, "ap2", "PRES AP2 Support 1.23")
+ ROMX_LOAD("presap2_123.rom", 0x0000, 0x2000, CRC(f796689c) SHA1(bc40a79e6d2b4cb5e549d5d21f673c66a661850d), ROM_BIOS(0))
+ ROM_RELOAD( 0x2000, 0x2000)
+
+ ROM_SYSTEM_BIOS(1, "ap6", "RH Plus 1 1.33")
+ ROMX_LOAD("ap6v133t.rom", 0x0000, 0x4000, CRC(364591eb) SHA1(316a25aeeda0266dae510eea52324b087875740f), ROM_BIOS(1))
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)
+static INPUT_PORTS_START( ap6 )
+ PORT_START("LINKS")
+ PORT_CONFNAME(0x01, 0x01, "J1 ROM 13")
+ PORT_CONFSETTING(0x00, "Disabled")
+ PORT_CONFSETTING(0x01, "Enabled")
+ PORT_CONFNAME(0x02, 0x02, "J2 ROM 4")
+ PORT_CONFSETTING(0x00, "Disabled")
+ PORT_CONFSETTING(0x02, "Enabled")
+ PORT_CONFNAME(0x04, 0x04, "J3 ROM 4,5,6,7")
+ PORT_CONFSETTING(0x00, "Disabled")
+ PORT_CONFSETTING(0x04, "Enabled")
INPUT_PORTS_END
//-------------------------------------------------
-// machine_config_additions - device-specific
-// machine configurations
+// input_ports - device-specific input ports
//-------------------------------------------------
-ioport_constructor electron_plus1_device::device_input_ports() const
+ioport_constructor electron_ap6_device::device_input_ports() const
{
- return INPUT_PORTS_NAME( plus1 );
+ return INPUT_PORTS_NAME( ap6 );
}
//-------------------------------------------------
@@ -92,29 +99,52 @@ ioport_constructor electron_plus1_device::device_input_ports() const
void electron_plus1_device::device_add_mconfig(machine_config &config)
{
+ INPUT_MERGER_ANY_HIGH(config, m_irqs).output_handler().set(DEVICE_SELF_OWNER, FUNC(electron_expansion_slot_device::irq_w));
+
/* printer */
CENTRONICS(config, m_centronics, centronics_devices, "printer");
- m_centronics->busy_handler().set(FUNC(electron_plus1_device::busy_w));
+ m_centronics->busy_handler().set([this](int state) { m_centronics_busy = state; });
output_latch_device &latch(OUTPUT_LATCH(config, "cent_data_out"));
m_centronics->set_output_latch(latch);
/* adc */
ADC0844(config, m_adc);
- m_adc->intr_callback().set(FUNC(electron_plus1_device::ready_w));
- 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->intr_callback().set([this](int state) { m_adc_ready = !state; });
+ 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);
- m_cart_sk1->irq_handler().set(DEVICE_SELF_OWNER, FUNC(electron_expansion_slot_device::irq_w));
+ m_cart_sk1->irq_handler().set(m_irqs, FUNC(input_merger_device::in_w<0>));
m_cart_sk1->nmi_handler().set(DEVICE_SELF_OWNER, FUNC(electron_expansion_slot_device::nmi_w));
ELECTRON_CARTSLOT(config, m_cart_sk2, DERIVED_CLOCK(1, 1), electron_cart, nullptr);
- m_cart_sk2->irq_handler().set(DEVICE_SELF_OWNER, FUNC(electron_expansion_slot_device::irq_w));
+ m_cart_sk2->irq_handler().set(m_irqs, FUNC(input_merger_device::in_w<1>));
m_cart_sk2->nmi_handler().set(DEVICE_SELF_OWNER, FUNC(electron_expansion_slot_device::nmi_w));
}
+void electron_ap6_device::device_add_mconfig(machine_config &config)
+{
+ electron_plus1_device::device_add_mconfig(config);
+
+ /* rom sockets */
+ GENERIC_SOCKET(config, m_rom[0], generic_plain_slot, "electron_rom", "bin,rom");
+ m_rom[0]->set_device_load(FUNC(electron_ap6_device::rom1_load));
+ GENERIC_SOCKET(config, m_rom[1], generic_plain_slot, "electron_rom", "bin,rom");
+ m_rom[1]->set_device_load(FUNC(electron_ap6_device::rom2_load));
+ GENERIC_SOCKET(config, m_rom[2], generic_plain_slot, "electron_rom", "bin,rom");
+ m_rom[2]->set_device_load(FUNC(electron_ap6_device::rom3_load));
+ GENERIC_SOCKET(config, m_rom[3], generic_plain_slot, "electron_rom", "bin,rom");
+ m_rom[3]->set_device_load(FUNC(electron_ap6_device::rom4_load));
+ GENERIC_SOCKET(config, m_rom[4], generic_plain_slot, "electron_rom", "bin,rom");
+ m_rom[4]->set_device_load(FUNC(electron_ap6_device::rom5_load));
+ GENERIC_SOCKET(config, m_rom[5], generic_plain_slot, "electron_rom", "bin,rom");
+ m_rom[5]->set_device_load(FUNC(electron_ap6_device::rom6_load));
+}
+
//-------------------------------------------------
// rom_region - device-specific ROM region
//-------------------------------------------------
@@ -124,6 +154,16 @@ const tiny_rom_entry *electron_plus1_device::device_rom_region() const
return ROM_NAME( plus1 );
}
+const tiny_rom_entry *electron_ap1_device::device_rom_region() const
+{
+ return ROM_NAME( ap1 );
+}
+
+const tiny_rom_entry *electron_ap6_device::device_rom_region() const
+{
+ return ROM_NAME( ap6 );
+}
+
//**************************************************************************
// LIVE DEVICE
//**************************************************************************
@@ -132,20 +172,37 @@ const tiny_rom_entry *electron_plus1_device::device_rom_region() const
// electron_plus1_device - constructor
//-------------------------------------------------
-electron_plus1_device::electron_plus1_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) :
- device_t(mconfig, ELECTRON_PLUS1, tag, owner, clock),
- device_electron_expansion_interface(mconfig, *this),
- m_exp_rom(*this, "exp_rom"),
- m_cart_sk1(*this, "cart_sk1"),
- m_cart_sk2(*this, "cart_sk2"),
- m_centronics(*this, "centronics"),
- m_cent_data_out(*this, "cent_data_out"),
- 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)
+electron_plus1_device::electron_plus1_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_electron_expansion_interface(mconfig, *this)
+ , m_irqs(*this, "irqs")
+ , m_exp_rom(*this, "exp_rom")
+ , m_cart_sk1(*this, "cart_sk1")
+ , 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_romsel(0)
+ , m_centronics_busy(0)
+ , m_adc_ready(0)
+{
+}
+
+electron_plus1_device::electron_plus1_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
+ : electron_plus1_device(mconfig, ELECTRON_PLUS1, tag, owner, clock)
+{
+}
+
+electron_ap1_device::electron_ap1_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
+ : electron_plus1_device(mconfig, ELECTRON_AP1, tag, owner, 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")
{
}
@@ -156,6 +213,23 @@ electron_plus1_device::electron_plus1_device(const machine_config &mconfig, cons
void electron_plus1_device::device_start()
{
+ /* register for save states */
+ save_item(NAME(m_romsel));
+}
+
+void electron_ap6_device::device_start()
+{
+ electron_plus1_device::device_start();
+
+ m_ram = make_unique_clear<uint8_t[]>(0x18000);
+ memset(m_ram.get(), 0xff, 0x18000);
+
+ m_bank_locked[0] = false;
+ m_bank_locked[1] = false;
+
+ /* register for save states */
+ save_pointer(NAME(m_ram), 0x18000);
+ save_item(NAME(m_bank_locked));
}
@@ -169,10 +243,7 @@ uint8_t electron_plus1_device::expbus_r(offs_t offset)
switch (offset >> 12)
{
- case 0x8:
- case 0x9:
- case 0xa:
- case 0xb:
+ case 0x8: case 0x9: case 0xa: case 0xb:
switch (m_romsel)
{
case 0:
@@ -206,7 +277,11 @@ uint8_t electron_plus1_device::expbus_r(offs_t offset)
}
else if (offset == 0xfc72)
{
- data &= status_r();
+ // Status: b7: printer Busy
+ // b6: ADC conversion end
+ // b5: Fire Button 1
+ // b4: Fire Button 2
+ data &= (m_centronics_busy << 7) | (m_adc_ready << 6) | m_analogue->pb_r() | 0x0f;
}
break;
@@ -221,6 +296,63 @@ uint8_t electron_plus1_device::expbus_r(offs_t offset)
}
+uint8_t electron_ap6_device::expbus_r(offs_t offset)
+{
+ uint8_t data = electron_plus1_device::expbus_r(offset);
+
+ switch (offset >> 12)
+ {
+ case 0x8: case 0x9: case 0xa: case 0xb:
+ switch (m_romsel)
+ {
+ case 4:
+ if (BIT(m_links->read(), 1) && BIT(m_links->read(), 2)) // ROM 4 enabled
+ {
+ if (m_rom[m_romsel - 4]->exists())
+ data = m_rom[m_romsel - 4]->read_rom(offset & 0x3fff);
+ else
+ data = m_ram[(m_romsel - 4) << 14 | (offset & 0x3fff)];
+ }
+ break;
+
+ case 5: case 6: case 7:
+ if (BIT(m_links->read(), 2)) // ROM 4,5,6,7 enabled
+ {
+ if (m_rom[m_romsel - 4]->exists())
+ data = m_rom[m_romsel - 4]->read_rom(offset & 0x3fff);
+ else
+ data = m_ram[(m_romsel - 4) << 14 | (offset & 0x3fff)];
+ }
+ break;
+
+ case 12:
+ data = m_exp_rom->base()[offset & 0x3fff];
+ break;
+
+ case 13:
+ if (BIT(m_links->read(), 0)) // ROM 13 enabled
+ {
+ if (m_rom[m_romsel - 9]->exists())
+ data &= m_rom[m_romsel - 9]->read_rom(offset & 0x3fff);
+ else
+ data &= m_ram[(m_romsel - 9) << 14 | (offset & 0x3fff)];
+ }
+ break;
+
+ case 14:
+ if (m_rom[m_romsel - 9]->exists())
+ data &= m_rom[m_romsel - 9]->read_rom(offset & 0x3fff);
+ else
+ data &= m_ram[(m_romsel - 9) << 14 | (offset & 0x3fff)];
+ break;
+ }
+ break;
+ }
+
+ return data;
+}
+
+
//-------------------------------------------------
// expbus_w - expansion data write
//-------------------------------------------------
@@ -229,10 +361,7 @@ void electron_plus1_device::expbus_w(offs_t offset, uint8_t data)
{
switch (offset >> 12)
{
- case 0x8:
- case 0x9:
- case 0xa:
- case 0xb:
+ case 0x8: case 0x9: case 0xa: case 0xb:
switch (m_romsel)
{
case 0:
@@ -243,6 +372,10 @@ void electron_plus1_device::expbus_w(offs_t offset, uint8_t data)
case 3:
m_cart_sk1->write(offset & 0x3fff, data, 0, 0, m_romsel & 0x01, 1, 0);
break;
+ case 13:
+ m_cart_sk1->write(offset & 0x3fff, data, 0, 0, m_romsel & 0x01, 0, 1);
+ m_cart_sk2->write(offset & 0x3fff, data, 0, 0, m_romsel & 0x01, 0, 1);
+ break;
}
break;
@@ -260,6 +393,8 @@ void electron_plus1_device::expbus_w(offs_t offset, uint8_t data)
else if (offset == 0xfc71)
{
m_cent_data_out->write(data);
+ m_centronics->write_strobe(0);
+ m_centronics->write_strobe(1);
}
break;
@@ -269,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;
}
@@ -279,30 +414,98 @@ void electron_plus1_device::expbus_w(offs_t offset, uint8_t data)
}
+void electron_ap6_device::expbus_w(offs_t offset, uint8_t data)
+{
+ electron_plus1_device::expbus_w(offset, data);
+
+ switch (offset >> 12)
+ {
+ case 0x8: case 0x9: case 0xa: case 0xb:
+ switch (m_romsel)
+ {
+ case 4:
+ if (BIT(m_links->read(), 1) && BIT(m_links->read(), 2)) // ROM 4 enabled
+ {
+ if (!m_rom[m_romsel - 4]->exists())
+ m_ram[(m_romsel - 4) << 14 | (offset & 0x3fff)] = data;
+ }
+ break;
+
+ case 7:
+ if (BIT(m_links->read(), 2)) // ROM 4,5,6,7 enabled
+ {
+ if (!m_rom[m_romsel - 4]->exists())
+ m_ram[(m_romsel - 4) << 14 | (offset & 0x3fff)] = data;
+ }
+ break;
+
+ case 5: case 6:
+ if (BIT(m_links->read(), 2)) // ROM 4,5,6,7 enabled
+ {
+ if (!m_rom[m_romsel - 4]->exists() && !m_bank_locked[0])
+ m_ram[(m_romsel - 4) << 14 | (offset & 0x3fff)] = data;
+ }
+ break;
+
+ case 13:
+ if (BIT(m_links->read(), 0)) // ROM 13 enabled
+ {
+ if (!m_rom[m_romsel - 9]->exists() && !m_bank_locked[1])
+ m_ram[(m_romsel - 9) << 14 | (offset & 0x3fff)] = data;
+ }
+ break;
+
+ case 14:
+ if (!m_rom[m_romsel - 9]->exists())
+ m_ram[(m_romsel - 9) << 14 | (offset & 0x3fff)] = data;
+ break;
+ }
+ break;
+
+ case 0xf:
+ switch (offset >> 8)
+ {
+ case 0xfc:
+ switch (offset & 0xff)
+ {
+ case 0xdc:
+ m_bank_locked[0] = false;
+ break;
+ case 0xdd:
+ m_bank_locked[0] = true;
+ break;
+ case 0xde:
+ m_bank_locked[1] = false;
+ break;
+ case 0xdf:
+ m_bank_locked[1] = true;
+ break;
+ }
+ break;
+ }
+ }
+}
+
+
//**************************************************************************
// IMPLEMENTATION
//**************************************************************************
-u8 electron_plus1_device::status_r()
+std::pair<std::error_condition, std::string> electron_ap6_device::load_rom(device_image_interface &image, generic_slot_device *slot)
{
- u8 data = 0x0f;
- // Status: b7: printer Busy
- // b6: ADC conversion end
- // b5: Fire Button 1
- // b4: Fire Button 2
- data |= (m_centronics_busy << 7);
- data |= (m_adc_ready << 6);
- data |= m_buttons->read();
+ uint32_t const size = slot->common_get_size("rom");
- return data;
-}
+ // socket accepts 8K and 16K ROM only
+ if (size != 0x2000 && size != 0x4000)
+ return std::make_pair(image_error::INVALIDLENGTH, "Invalid size: Only 8K/16K is supported");
-WRITE_LINE_MEMBER(electron_plus1_device::busy_w)
-{
- m_centronics_busy = !state;
-}
+ slot->rom_alloc(0x4000, GENERIC_ROM8_WIDTH, ENDIANNESS_LITTLE);
+ slot->common_load_rom(slot->get_rom_base(), size, "rom");
-WRITE_LINE_MEMBER(electron_plus1_device::ready_w)
-{
- m_adc_ready = !state;
+ // mirror 8K ROMs
+ uint8_t *const crt = slot->get_rom_base();
+ if (size <= 0x2000)
+ memcpy(crt + 0x2000, crt, 0x2000);
+
+ 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 e211594a2c6..a7e7507a36b 100644
--- a/src/devices/bus/electron/plus1.h
+++ b/src/devices/bus/electron/plus1.h
@@ -11,10 +11,13 @@
#define MAME_BUS_ELECTRON_PLUS1_H
#include "exp.h"
-#include "softlist.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"
+#include "bus/generic/carts.h"
//**************************************************************************
// TYPE DEFINITIONS
@@ -29,30 +32,26 @@ public:
electron_plus1_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
protected:
- // device-level overrides
- virtual void device_start() override;
+ electron_plus1_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 ATTR_COLD;
// 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 void device_add_mconfig(machine_config &config) override ATTR_COLD;
+ virtual const tiny_rom_entry *device_rom_region() const override ATTR_COLD;
virtual uint8_t expbus_r(offs_t offset) override;
virtual void expbus_w(offs_t offset, uint8_t data) override;
-private:
- u8 status_r();
- DECLARE_WRITE_LINE_MEMBER(busy_w);
- DECLARE_WRITE_LINE_MEMBER(ready_w);
-
+ required_device<input_merger_device> m_irqs;
required_memory_region m_exp_rom;
required_device<electron_cartslot_device> m_cart_sk1;
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;
@@ -60,8 +59,56 @@ private:
};
+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);
+
+protected:
+ // optional information overrides
+ virtual const tiny_rom_entry* device_rom_region() const override;
+};
+
+
+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);
+
+protected:
+ // device_t implementation
+ virtual void device_start() override ATTR_COLD;
+
+ // optional information overrides
+ virtual void device_add_mconfig(machine_config &config) override ATTR_COLD;
+ virtual const tiny_rom_entry* device_rom_region() const override;
+ virtual ioport_constructor device_input_ports() const override ATTR_COLD;
+
+ virtual uint8_t expbus_r(offs_t offset) override;
+ virtual void expbus_w(offs_t offset, uint8_t data) override;
+
+private:
+ 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]); }
+ DECLARE_DEVICE_IMAGE_LOAD_MEMBER(rom4_load) { return load_rom(image, m_rom[3]); }
+ DECLARE_DEVICE_IMAGE_LOAD_MEMBER(rom5_load) { return load_rom(image, m_rom[4]); }
+ DECLARE_DEVICE_IMAGE_LOAD_MEMBER(rom6_load) { return load_rom(image, m_rom[5]); }
+
+ required_device_array<generic_slot_device, 6> m_rom;
+ required_ioport m_links;
+
+ std::unique_ptr<uint8_t[]> m_ram;
+ bool m_bank_locked[2];
+};
+
+
+
// device type definition
DECLARE_DEVICE_TYPE(ELECTRON_PLUS1, electron_plus1_device)
+DECLARE_DEVICE_TYPE(ELECTRON_AP1, electron_ap1_device)
+DECLARE_DEVICE_TYPE(ELECTRON_AP6, electron_ap6_device)
#endif /* MAME_BUS_ELECTRON_PLUS1_H */
diff --git a/src/devices/bus/electron/plus2.cpp b/src/devices/bus/electron/plus2.cpp
index dd8be6e09eb..92a9599dfb0 100644
--- a/src/devices/bus/electron/plus2.cpp
+++ b/src/devices/bus/electron/plus2.cpp
@@ -4,7 +4,7 @@
Slogger Plus 2
- The Plus 2 interface from Slogger has been designed to compliment
+ The Plus 2 interface from Slogger has been designed to complement
the Slogger Rombox Plus and Acorn Plus 1 by offering further
expansion capabilities. This has been achieved by providing two
extra cartridge slots, three ROM sockets and connections for a
@@ -31,27 +31,31 @@ DEFINE_DEVICE_TYPE(ELECTRON_PLUS2, electron_plus2_device, "electron_plus2", "Slo
void electron_plus2_device::device_add_mconfig(machine_config &config)
{
+ INPUT_MERGER_ANY_HIGH(config, m_irqs).output_handler().set(DEVICE_SELF_OWNER, FUNC(electron_expansion_slot_device::irq_w));
+
/* rom sockets */
GENERIC_SOCKET(config, m_rom[0], generic_plain_slot, "electron_rom", "bin,rom"); // ROM SLOT 13
- m_rom[0]->set_device_load(FUNC(electron_plus2_device::rom1_load), this);
+ m_rom[0]->set_device_load(FUNC(electron_plus2_device::rom1_load));
GENERIC_SOCKET(config, m_rom[1], generic_plain_slot, "electron_rom", "bin,rom"); // ROM SLOT 14
- m_rom[1]->set_device_load(FUNC(electron_plus2_device::rom2_load), this);
+ m_rom[1]->set_device_load(FUNC(electron_plus2_device::rom2_load));
GENERIC_SOCKET(config, m_rom[2], generic_plain_slot, "electron_rom", "bin,rom"); // ROM SLOT 15
- m_rom[2]->set_device_load(FUNC(electron_plus2_device::rom3_load), this);
+ m_rom[2]->set_device_load(FUNC(electron_plus2_device::rom3_load));
/* cartridges */
ELECTRON_CARTSLOT(config, m_cart[0], DERIVED_CLOCK(1, 1), electron_cart, nullptr);
- m_cart[0]->irq_handler().set(DEVICE_SELF_OWNER, FUNC(electron_expansion_slot_device::irq_w));
+ m_cart[0]->irq_handler().set(m_irqs, FUNC(input_merger_device::in_w<0>));
m_cart[0]->nmi_handler().set(DEVICE_SELF_OWNER, FUNC(electron_expansion_slot_device::nmi_w));
ELECTRON_CARTSLOT(config, m_cart[1], DERIVED_CLOCK(1, 1), electron_cart, nullptr);
- m_cart[1]->irq_handler().set(DEVICE_SELF_OWNER, FUNC(electron_expansion_slot_device::irq_w));
+ m_cart[1]->irq_handler().set(m_irqs, FUNC(input_merger_device::in_w<1>));
m_cart[1]->nmi_handler().set(DEVICE_SELF_OWNER, FUNC(electron_expansion_slot_device::nmi_w));
/* via */
- VIA6522(config, m_via, DERIVED_CLOCK(1, 16));
+ MOS6522(config, m_via, DERIVED_CLOCK(1, 16));
m_via->readpb_handler().set(m_userport, FUNC(bbc_userport_slot_device::pb_r));
m_via->writepb_handler().set(m_userport, FUNC(bbc_userport_slot_device::pb_w));
- m_via->irq_handler().set(DEVICE_SELF_OWNER, FUNC(electron_expansion_slot_device::irq_w));
+ m_via->cb1_handler().set(m_userport, FUNC(bbc_userport_slot_device::write_cb1));
+ m_via->cb2_handler().set(m_userport, FUNC(bbc_userport_slot_device::write_cb2));
+ m_via->irq_handler().set(m_irqs, FUNC(input_merger_device::in_w<2>));
/* user port */
BBC_USERPORT_SLOT(config, m_userport, bbc_userport_devices, nullptr);
@@ -60,7 +64,7 @@ void electron_plus2_device::device_add_mconfig(machine_config &config)
/* pass-through */
ELECTRON_EXPANSION_SLOT(config, m_exp, DERIVED_CLOCK(1, 1), electron_expansion_devices, nullptr);
- m_exp->irq_handler().set(DEVICE_SELF_OWNER, FUNC(electron_expansion_slot_device::irq_w));
+ m_exp->irq_handler().set(m_irqs, FUNC(input_merger_device::in_w<3>));
m_exp->nmi_handler().set(DEVICE_SELF_OWNER, FUNC(electron_expansion_slot_device::nmi_w));
}
@@ -75,6 +79,7 @@ void electron_plus2_device::device_add_mconfig(machine_config &config)
electron_plus2_device::electron_plus2_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
: device_t(mconfig, ELECTRON_PLUS2, tag, owner, clock)
, device_electron_expansion_interface(mconfig, *this)
+ , m_irqs(*this, "irqs")
, m_exp(*this, "exp")
, m_via(*this, "via6522")
, m_rom(*this, "rom%u", 1)
@@ -121,6 +126,7 @@ uint8_t electron_plus2_device::expbus_r(offs_t offset)
case 13:
data &= m_cart[0]->read(offset & 0x3fff, 0, 0, m_romsel & 0x01, 0, 1);
data &= m_cart[1]->read(offset & 0x3fff, 0, 0, m_romsel & 0x01, 0, 1);
+ [[fallthrough]];
case 14:
case 15:
data &= m_rom[m_romsel - 13]->read_rom(offset & 0x3fff);
@@ -176,6 +182,10 @@ void electron_plus2_device::expbus_w(offs_t offset, uint8_t data)
case 7:
m_cart[0]->write(offset & 0x3fff, data, 0, 0, m_romsel & 0x01, 1, 0);
break;
+ case 13:
+ m_cart[0]->write(offset & 0x3fff, data, 0, 0, m_romsel & 0x01, 0, 1);
+ m_cart[1]->write(offset & 0x3fff, data, 0, 0, m_romsel & 0x01, 0, 1);
+ break;
}
break;
@@ -198,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;
}
@@ -214,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_UNSPECIFIED, "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 235ecd4f218..4908e8986a8 100644
--- a/src/devices/bus/electron/plus2.h
+++ b/src/devices/bus/electron/plus2.h
@@ -12,6 +12,7 @@
#include "exp.h"
#include "machine/6522via.h"
+#include "machine/input_merger.h"
#include "bus/electron/cart/slot.h"
#include "bus/bbc/userport/userport.h"
#include "bus/generic/slot.h"
@@ -30,21 +31,22 @@ public:
electron_plus2_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
protected:
- // device-level overrides
- virtual void device_start() override;
+ // device_t implementation
+ virtual void device_start() override ATTR_COLD;
// optional information overrides
- virtual void device_add_mconfig(machine_config &config) override;
+ virtual void device_add_mconfig(machine_config &config) override ATTR_COLD;
virtual uint8_t expbus_r(offs_t offset) override;
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]); }
+ required_device<input_merger_device> m_irqs;
required_device<electron_expansion_slot_device> m_exp;
required_device<via6522_device> m_via;
required_device_array<generic_slot_device, 3> m_rom;
diff --git a/src/devices/bus/electron/plus3.cpp b/src/devices/bus/electron/plus3.cpp
index 5996e357389..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
@@ -27,14 +28,16 @@ DEFINE_DEVICE_TYPE(ELECTRON_PLUS3, electron_plus3_device, "electron_plus3", "Aco
//-------------------------------------------------
-// MACHINE_DRIVER( plus3 )
+// FLOPPY_FORMATS( plus3 )
//-------------------------------------------------
-FLOPPY_FORMATS_MEMBER(electron_plus3_device::floppy_formats)
- FLOPPY_ACORN_SSD_FORMAT,
- FLOPPY_ACORN_DSD_FORMAT,
- FLOPPY_ACORN_ADFS_OLD_FORMAT
-FLOPPY_FORMATS_END0
+void electron_plus3_device::floppy_formats(format_registration &fr)
+{
+ fr.add_mfm_containers();
+ fr.add(FLOPPY_ACORN_SSD_FORMAT);
+ fr.add(FLOPPY_ACORN_DSD_FORMAT);
+ fr.add(FLOPPY_ACORN_ADFS_OLD_FORMAT);
+}
void electron_floppies(device_slot_interface &device)
{
@@ -43,6 +46,10 @@ void electron_floppies(device_slot_interface &device)
}
+//-------------------------------------------------
+// ROM( plus3 )
+//-------------------------------------------------
+
ROM_START( plus3 )
// Bank 4 Disc
ROM_REGION(0x4000, "exp_rom", 0)
@@ -158,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;
}
@@ -188,5 +195,5 @@ void electron_plus3_device::wd1770_status_w(uint8_t data)
m_fdc->dden_w(BIT(data, 3));
// bit 5: reset
- if (!BIT(data, 5)) m_fdc->soft_reset();
+ m_fdc->mr_w(BIT(data, 5));
}
diff --git a/src/devices/bus/electron/plus3.h b/src/devices/bus/electron/plus3.h
index 44de595a3db..136e31aa1c2 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
@@ -28,18 +27,18 @@ public:
protected:
// device-level overrides
- virtual void device_start() override;
+ virtual void device_start() override ATTR_COLD;
// optional information overrides
- virtual void device_add_mconfig(machine_config &config) override;
- virtual const tiny_rom_entry *device_rom_region() const override;
+ virtual void device_add_mconfig(machine_config &config) override ATTR_COLD;
+ virtual const tiny_rom_entry *device_rom_region() const override ATTR_COLD;
virtual uint8_t expbus_r(offs_t offset) override;
virtual void expbus_w(offs_t offset, uint8_t data) override;
private:
void wd1770_status_w(uint8_t data);
- DECLARE_FLOPPY_FORMATS(floppy_formats);
+ static void floppy_formats(format_registration &fr);
required_device<electron_expansion_slot_device> m_exp;
required_memory_region m_exp_rom;
diff --git a/src/devices/bus/electron/pwrjoy.cpp b/src/devices/bus/electron/pwrjoy.cpp
index 1ff7ab79566..cceac8df500 100644
--- a/src/devices/bus/electron/pwrjoy.cpp
+++ b/src/devices/bus/electron/pwrjoy.cpp
@@ -9,68 +9,67 @@
#include "emu.h"
#include "pwrjoy.h"
-//**************************************************************************
-// DEVICE DEFINITIONS
-//**************************************************************************
+#include "bus/vcs_ctrl/ctrl.h"
-DEFINE_DEVICE_TYPE(ELECTRON_PWRJOY, electron_pwrjoy_device, "electron_pwrjoy", "Power Software Joystick Interface")
+namespace {
-ROM_START( pwrjoy )
- // Bank 12 Expansion module operating system
- ROM_REGION(0x2000, "exp_rom", 0)
- ROM_LOAD("power_joystick.rom", 0x0000, 0x2000, CRC(44fb9360) SHA1(6d3aa85a436db952906e84839496e681ea115168))
-ROM_END
-
+class electron_pwrjoy_device
+ : public device_t
+ , public device_electron_expansion_interface
+{
+public:
+ electron_pwrjoy_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
+ : device_t(mconfig, ELECTRON_PWRJOY, tag, owner, clock)
+ , device_electron_expansion_interface(mconfig, *this)
+ , m_exp_rom(*this, "exp_rom")
+ , m_joy(*this, "joy")
+ , m_romsel(0)
+ {
+ }
-static INPUT_PORTS_START( pwrjoy )
- 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_NAME("Fire")
-INPUT_PORTS_END
+protected:
+ // device_t overrides
+ virtual void device_start() override ATTR_COLD { }
+ // optional information overrides
+ virtual void device_add_mconfig(machine_config &config) override ATTR_COLD;
+ virtual const tiny_rom_entry *device_rom_region() const override ATTR_COLD;
-//-------------------------------------------------
-// input_ports - device-specific input ports
-//-------------------------------------------------
+ virtual uint8_t expbus_r(offs_t offset) override;
+ virtual void expbus_w(offs_t offset, uint8_t data) override;
-ioport_constructor electron_pwrjoy_device::device_input_ports() const
-{
- return INPUT_PORTS_NAME( pwrjoy );
-}
+private:
+ required_memory_region m_exp_rom;
+ required_device<vcs_control_port_device> m_joy;
-const tiny_rom_entry *electron_pwrjoy_device::device_rom_region() const
-{
- return ROM_NAME( pwrjoy );
-}
+ uint8_t m_romsel;
+};
-//**************************************************************************
-// LIVE DEVICE
-//**************************************************************************
//-------------------------------------------------
-// electron_pwrjoy_device - constructor
+// device_add_mconfig - add device configuration
//-------------------------------------------------
-electron_pwrjoy_device::electron_pwrjoy_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
- : device_t(mconfig, ELECTRON_PWRJOY, tag, owner, clock)
- , device_electron_expansion_interface(mconfig, *this)
- , m_exp_rom(*this, "exp_rom")
- , m_joy(*this, "JOY")
- , m_romsel(0)
+void electron_pwrjoy_device::device_add_mconfig(machine_config &config)
{
+ VCS_CONTROL_PORT(config, m_joy, vcs_control_port_devices, "joy");
}
//-------------------------------------------------
-// device_start - device-specific startup
+// rom_region - device-specific ROM region
//-------------------------------------------------
-void electron_pwrjoy_device::device_start()
+ROM_START( pwrjoy )
+ // Bank 12 Expansion module operating system
+ ROM_REGION(0x2000, "exp_rom", 0)
+ ROM_LOAD("power_joystick.rom", 0x0000, 0x2000, CRC(44fb9360) SHA1(6d3aa85a436db952906e84839496e681ea115168))
+ROM_END
+
+const tiny_rom_entry *electron_pwrjoy_device::device_rom_region() const
{
+ return ROM_NAME( pwrjoy );
}
@@ -91,7 +90,7 @@ uint8_t electron_pwrjoy_device::expbus_r(offs_t offset)
}
else if (offset == 0xfcc0)
{
- data = m_joy->read() | 0xe0;
+ data = bitswap<8>(m_joy->read_joy(), 7, 6, 4, 5, 3, 2, 1, 0);
}
return data;
@@ -104,8 +103,13 @@ 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;
}
}
+
+} // anonymous namespace
+
+
+DEFINE_DEVICE_TYPE_PRIVATE(ELECTRON_PWRJOY, device_electron_expansion_interface, electron_pwrjoy_device, "electron_pwrjoy", "Power Software Joystick Interface")
diff --git a/src/devices/bus/electron/pwrjoy.h b/src/devices/bus/electron/pwrjoy.h
index abc91cf3e2b..0c46c38d18f 100644
--- a/src/devices/bus/electron/pwrjoy.h
+++ b/src/devices/bus/electron/pwrjoy.h
@@ -1,53 +1,14 @@
// license:BSD-3-Clause
// copyright-holders:Nigel Barnes
-/**********************************************************************
-
- Power Software Joystick Interface
-
-**********************************************************************/
-
#ifndef MAME_BUS_ELECTRON_PWRJOY_H
#define MAME_BUS_ELECTRON_PWRJOY_H
#pragma once
-
#include "exp.h"
-//**************************************************************************
-// TYPE DEFINITIONS
-//**************************************************************************
-
-// ======================> electron_pwrjoy_device
-
-class electron_pwrjoy_device :
- public device_t,
- public device_electron_expansion_interface
-{
-public:
- // construction/destruction
- electron_pwrjoy_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 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;
-
-protected:
- // device-level overrides
- virtual void device_start() override;
-
-private:
- required_memory_region m_exp_rom;
- required_ioport m_joy;
-
- uint8_t m_romsel;
-};
-
// device type definition
-DECLARE_DEVICE_TYPE(ELECTRON_PWRJOY, electron_pwrjoy_device)
+DECLARE_DEVICE_TYPE(ELECTRON_PWRJOY, device_electron_expansion_interface)
#endif // MAME_BUS_ELECTRON_PWRJOY_H
diff --git a/src/devices/bus/electron/rombox.cpp b/src/devices/bus/electron/rombox.cpp
index 05d0a7c9092..704a7eeb7e4 100644
--- a/src/devices/bus/electron/rombox.cpp
+++ b/src/devices/bus/electron/rombox.cpp
@@ -55,21 +55,21 @@ void electron_rombox_device::device_add_mconfig(machine_config &config)
{
/* rom sockets */
GENERIC_SOCKET(config, m_rom[0], generic_plain_slot, "electron_rom", "bin,rom");
- m_rom[0]->set_device_load(FUNC(electron_rombox_device::rom1_load), this);
+ m_rom[0]->set_device_load(FUNC(electron_rombox_device::rom1_load));
GENERIC_SOCKET(config, m_rom[1], generic_plain_slot, "electron_rom", "bin,rom");
- m_rom[1]->set_device_load(FUNC(electron_rombox_device::rom2_load), this);
+ m_rom[1]->set_device_load(FUNC(electron_rombox_device::rom2_load));
GENERIC_SOCKET(config, m_rom[2], generic_plain_slot, "electron_rom", "bin,rom");
- m_rom[2]->set_device_load(FUNC(electron_rombox_device::rom3_load), this);
+ m_rom[2]->set_device_load(FUNC(electron_rombox_device::rom3_load));
GENERIC_SOCKET(config, m_rom[3], generic_plain_slot, "electron_rom", "bin,rom");
- m_rom[3]->set_device_load(FUNC(electron_rombox_device::rom4_load), this);
+ m_rom[3]->set_device_load(FUNC(electron_rombox_device::rom4_load));
GENERIC_SOCKET(config, m_rom[4], generic_plain_slot, "electron_rom", "bin,rom");
- m_rom[4]->set_device_load(FUNC(electron_rombox_device::rom5_load), this);
+ m_rom[4]->set_device_load(FUNC(electron_rombox_device::rom5_load));
GENERIC_SOCKET(config, m_rom[5], generic_plain_slot, "electron_rom", "bin,rom");
- m_rom[5]->set_device_load(FUNC(electron_rombox_device::rom6_load), this);
+ m_rom[5]->set_device_load(FUNC(electron_rombox_device::rom6_load));
GENERIC_SOCKET(config, m_rom[6], generic_plain_slot, "electron_rom", "bin,rom");
- m_rom[6]->set_device_load(FUNC(electron_rombox_device::rom7_load), this);
+ m_rom[6]->set_device_load(FUNC(electron_rombox_device::rom7_load));
GENERIC_SOCKET(config, m_rom[7], generic_plain_slot, "electron_rom", "bin,rom");
- m_rom[7]->set_device_load(FUNC(electron_rombox_device::rom8_load), this);
+ m_rom[7]->set_device_load(FUNC(electron_rombox_device::rom8_load));
/* pass-through */
ELECTRON_EXPANSION_SLOT(config, m_exp, DERIVED_CLOCK(1, 1), electron_expansion_devices, nullptr);
@@ -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_UNSPECIFIED, "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..694902d9c82 100644
--- a/src/devices/bus/electron/rombox.h
+++ b/src/devices/bus/electron/rombox.h
@@ -27,19 +27,19 @@ public:
electron_rombox_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_t implementation
+ virtual void device_start() override ATTR_COLD;
+ virtual void device_reset() override ATTR_COLD;
// optional information overrides
- virtual void device_add_mconfig(machine_config &config) override;
- virtual ioport_constructor device_input_ports() const override;
+ virtual void device_add_mconfig(machine_config &config) override ATTR_COLD;
+ virtual ioport_constructor device_input_ports() const override ATTR_COLD;
virtual uint8_t expbus_r(offs_t offset) override;
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 7581cf5b2e1..e489849ec73 100644
--- a/src/devices/bus/electron/romboxp.cpp
+++ b/src/devices/bus/electron/romboxp.cpp
@@ -34,27 +34,24 @@ DEFINE_DEVICE_TYPE(ELECTRON_ROMBOXP, electron_romboxp_device, "electron_romboxp"
ROM_START( romboxp )
// Bank 12 Expansion module operating system
ROM_REGION(0x2000, "exp_rom", 0)
- ROM_DEFAULT_BIOS("exp100")
+ ROM_DEFAULT_BIOS("exp202")
ROM_SYSTEM_BIOS(0, "exp100", "ROMBOX+ Expansion 1.00")
ROMX_LOAD("romboxplus.rom", 0x0000, 0x2000, CRC(0520ab6d) SHA1(2f551bea279a64e09fd4d31024799f7459fb9938), ROM_BIOS(0))
- ROM_SYSTEM_BIOS(1, "presap2", "PRES AP2 Support 1.23")
- ROMX_LOAD("presap2rb_123.rom", 0x0000, 0x2000, CRC(04931d2c) SHA1(84a27fd30adea4e7f7c53e7875f63cf9e6928688), ROM_BIOS(1))
+ ROM_SYSTEM_BIOS(1, "exp101", "Slogger Expansion 1.01")
+ ROMX_LOAD("exprom101.rom", 0x0000, 0x2000, CRC(6f854419) SHA1(1f3e7e0c2843e1a364b4b3f96c890fe70ef03200), ROM_BIOS(1))
- ROM_SYSTEM_BIOS(2, "exp101", "Slogger Expansion 1.01")
- ROMX_LOAD("exprom101.rom", 0x0000, 0x2000, CRC(6f854419) SHA1(1f3e7e0c2843e1a364b4b3f96c890fe70ef03200), ROM_BIOS(2))
+ ROM_SYSTEM_BIOS(2, "exp200", "Slogger Expansion 2.00")
+ ROMX_LOAD("elkexp200.rom", 0x0000, 0x2000, CRC(dee02843) SHA1(5c9b940b4ddb46e9a223160310683a32266300c8), ROM_BIOS(2))
- ROM_SYSTEM_BIOS(3, "exp200", "Slogger Expansion 2.00")
- ROMX_LOAD("elkexp200.rom", 0x0000, 0x2000, CRC(dee02843) SHA1(5c9b940b4ddb46e9a223160310683a32266300c8), ROM_BIOS(3))
+ ROM_SYSTEM_BIOS(3, "exp201", "Slogger Expansion 2.01")
+ ROMX_LOAD("elkexp201.rom", 0x0000, 0x2000, CRC(0e896892) SHA1(4e0794f1083fe529b01bd4fa100996a533ed8b10), ROM_BIOS(3))
- ROM_SYSTEM_BIOS(4, "exp201", "Slogger Expansion 2.01")
- ROMX_LOAD("elkexp201.rom", 0x0000, 0x2000, CRC(0e896892) SHA1(4e0794f1083fe529b01bd4fa100996a533ed8b10), ROM_BIOS(4))
+ ROM_SYSTEM_BIOS(4, "exp202", "Slogger Expansion 2.02")
+ ROMX_LOAD("elkexp202.rom", 0x0000, 0x2000, CRC(32b440be) SHA1(dbc73e8d919c5615d0241d99db60e06324e16c86), ROM_BIOS(4))
- ROM_SYSTEM_BIOS(5, "exp202", "Slogger Expansion 2.02")
- ROMX_LOAD("elkexp202.rom", 0x0000, 0x2000, CRC(32b440be) SHA1(dbc73e8d919c5615d0241d99db60e06324e16c86), ROM_BIOS(5))
-
- ROM_SYSTEM_BIOS(6, "exp210", "Slogger Expansion 2.10 (dev)")
- ROMX_LOAD("elkexp210.rom", 0x0000, 0x2000, CRC(12442575) SHA1(eb8609991a9a8fb017b8100bfca4248d65faeea8), ROM_BIOS(6))
+ ROM_SYSTEM_BIOS(5, "exp210", "Slogger Expansion 2.10 (dev)")
+ ROMX_LOAD("elkexp210.rom", 0x0000, 0x2000, CRC(12442575) SHA1(eb8609991a9a8fb017b8100bfca4248d65faeea8), ROM_BIOS(5))
ROM_END
//-------------------------------------------------
@@ -63,12 +60,9 @@ ROM_END
static INPUT_PORTS_START( romboxp )
PORT_START("OPTION")
- PORT_CONFNAME(0x01, 0x01, "A1") // not implemented
- PORT_CONFSETTING(0x00, "RAM")
- PORT_CONFSETTING(0x01, "ROM")
- PORT_CONFNAME(0x02, 0x02, "A2")
- PORT_CONFSETTING(0x00, "ROM 12-15")
- PORT_CONFSETTING(0x02, "ROM 4-7")
+ PORT_CONFNAME(0x01, 0x01, "Sideways ROM Pages")
+ PORT_CONFSETTING(0x00, "12-15")
+ PORT_CONFSETTING(0x01, "4-7")
INPUT_PORTS_END
//-------------------------------------------------
@@ -86,28 +80,30 @@ ioport_constructor electron_romboxp_device::device_input_ports() const
void electron_romboxp_device::device_add_mconfig(machine_config &config)
{
+ INPUT_MERGER_ANY_HIGH(config, m_irqs).output_handler().set(DEVICE_SELF_OWNER, FUNC(electron_expansion_slot_device::irq_w));
+
/* printer */
CENTRONICS(config, m_centronics, centronics_devices, "printer");
- m_centronics->busy_handler().set(FUNC(electron_romboxp_device::busy_w));
+ m_centronics->busy_handler().set([this](int state) { m_centronics_busy = state; });
output_latch_device &latch(OUTPUT_LATCH(config, "cent_data_out"));
m_centronics->set_output_latch(latch);
/* rom sockets */
GENERIC_SOCKET(config, m_rom[0], generic_plain_slot, "electron_rom", "bin,rom"); // ROM SLOT 4/12
- m_rom[0]->set_device_load(FUNC(electron_romboxp_device::rom1_load), this);
+ m_rom[0]->set_device_load(FUNC(electron_romboxp_device::rom1_load));
GENERIC_SOCKET(config, m_rom[1], generic_plain_slot, "electron_rom", "bin,rom"); // ROM SLOT 5/13
- m_rom[1]->set_device_load(FUNC(electron_romboxp_device::rom2_load), this);
+ m_rom[1]->set_device_load(FUNC(electron_romboxp_device::rom2_load));
GENERIC_SOCKET(config, m_rom[2], generic_plain_slot, "electron_rom", "bin,rom"); // ROM SLOT 6/14 also ROM/RAM
- m_rom[2]->set_device_load(FUNC(electron_romboxp_device::rom3_load), this);
+ m_rom[2]->set_device_load(FUNC(electron_romboxp_device::rom3_load));
GENERIC_SOCKET(config, m_rom[3], generic_plain_slot, "electron_rom", "bin,rom"); // ROM SLOT 7/15
- m_rom[3]->set_device_load(FUNC(electron_romboxp_device::rom4_load), this);
+ m_rom[3]->set_device_load(FUNC(electron_romboxp_device::rom4_load));
/* cartridges */
ELECTRON_CARTSLOT(config, m_cart[0], DERIVED_CLOCK(1, 1), electron_cart, nullptr); // ROM SLOT 0/1
- m_cart[0]->irq_handler().set(DEVICE_SELF_OWNER, FUNC(electron_expansion_slot_device::irq_w));
+ m_cart[0]->irq_handler().set(m_irqs, FUNC(input_merger_device::in_w<0>));
m_cart[0]->nmi_handler().set(DEVICE_SELF_OWNER, FUNC(electron_expansion_slot_device::nmi_w));
ELECTRON_CARTSLOT(config, m_cart[1], DERIVED_CLOCK(1, 1), electron_cart, nullptr); // ROM SLOT 2/3
- m_cart[1]->irq_handler().set(DEVICE_SELF_OWNER, FUNC(electron_expansion_slot_device::irq_w));
+ m_cart[1]->irq_handler().set(m_irqs, FUNC(input_merger_device::in_w<1>));
m_cart[1]->nmi_handler().set(DEVICE_SELF_OWNER, FUNC(electron_expansion_slot_device::nmi_w));
}
@@ -124,18 +120,19 @@ const tiny_rom_entry *electron_romboxp_device::device_rom_region() const
// electron_romboxp_device - constructor
//-------------------------------------------------
-electron_romboxp_device::electron_romboxp_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) :
- device_t(mconfig, ELECTRON_ROMBOXP, tag, owner, clock),
- device_electron_expansion_interface(mconfig, *this),
- m_exp_rom(*this, "exp_rom"),
- m_rom(*this, "rom%u", 1),
- m_cart(*this, "cart%u", 1),
- m_centronics(*this, "centronics"),
- m_cent_data_out(*this, "cent_data_out"),
- m_option(*this, "OPTION"),
- m_romsel(0),
- m_rom_base(0),
- m_centronics_busy(0)
+electron_romboxp_device::electron_romboxp_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
+ : device_t(mconfig, ELECTRON_ROMBOXP, tag, owner, clock)
+ , device_electron_expansion_interface(mconfig, *this)
+ , m_irqs(*this, "irqs")
+ , m_exp_rom(*this, "exp_rom")
+ , m_rom(*this, "rom%u", 1)
+ , m_cart(*this, "cart%u", 1)
+ , m_centronics(*this, "centronics")
+ , m_cent_data_out(*this, "cent_data_out")
+ , m_option(*this, "OPTION")
+ , m_romsel(0)
+ , m_rom_base(0)
+ , m_centronics_busy(0)
{
}
@@ -145,6 +142,12 @@ electron_romboxp_device::electron_romboxp_device(const machine_config &mconfig,
void electron_romboxp_device::device_start()
{
+ m_ram = make_unique_clear<uint8_t[]>(0x10000);
+ memset(m_ram.get(), 0xff, 0x10000);
+
+ /* register for save states */
+ save_item(NAME(m_romsel));
+ save_pointer(NAME(m_ram), 0x10000);
}
//-------------------------------------------------
@@ -153,7 +156,7 @@ void electron_romboxp_device::device_start()
void electron_romboxp_device::device_reset()
{
- m_rom_base = (m_option->read() & 0x02) ? 4 : 12;
+ m_rom_base = m_option->read() ? 4 : 12;
}
//-------------------------------------------------
@@ -186,7 +189,10 @@ uint8_t electron_romboxp_device::expbus_r(offs_t offset)
case 7:
if (m_rom_base == 4)
{
- data = m_rom[m_romsel - 4]->read_rom(offset & 0x3fff);
+ if (m_rom[m_romsel - 4]->exists())
+ data = m_rom[m_romsel - 4]->read_rom(offset & 0x3fff);
+ else
+ data = m_ram[(m_romsel - 4) << 14 | (offset & 0x3fff)];
}
break;
case 12:
@@ -195,11 +201,15 @@ uint8_t electron_romboxp_device::expbus_r(offs_t offset)
case 13:
data &= m_cart[0]->read(offset & 0x3fff, 0, 0, m_romsel & 0x01, 0, 1);
data &= m_cart[1]->read(offset & 0x3fff, 0, 0, m_romsel & 0x01, 0, 1);
+ [[fallthrough]];
case 14:
case 15:
if (m_rom_base == 12)
{
- data = m_rom[m_romsel - 12]->read_rom(offset & 0x3fff);
+ if (m_rom[m_romsel - 12]->exists())
+ data = m_rom[m_romsel - 12]->read_rom(offset & 0x3fff);
+ else
+ data = m_ram[(m_romsel - 12) << 14 | (offset & 0x3fff)];
}
break;
}
@@ -214,7 +224,7 @@ uint8_t electron_romboxp_device::expbus_r(offs_t offset)
if (offset == 0xfc72)
{
- data &= status_r();
+ data &= (m_centronics_busy << 7) | 0x7f;
}
break;
@@ -250,6 +260,30 @@ void electron_romboxp_device::expbus_w(offs_t offset, uint8_t data)
case 3:
m_cart[0]->write(offset & 0x3fff, data, 0, 0, m_romsel & 0x01, 1, 0);
break;
+ case 4:
+ case 5:
+ case 6:
+ case 7:
+ if (m_rom_base == 4)
+ {
+ if (!m_rom[m_romsel - 4]->exists())
+ m_ram[(m_romsel - 4) << 14 | (offset & 0x3fff)] = data;
+ }
+ break;
+ case 12:
+ break;
+ case 13:
+ m_cart[0]->write(offset & 0x3fff, data, 0, 0, m_romsel & 0x01, 0, 1);
+ m_cart[1]->write(offset & 0x3fff, data, 0, 0, m_romsel & 0x01, 0, 1);
+ [[fallthrough]];
+ case 14:
+ case 15:
+ if (m_rom_base == 12)
+ {
+ if (!m_rom[m_romsel - 12]->exists())
+ m_ram[(m_romsel - 12) << 14 | (offset & 0x3fff)] = data;
+ }
+ break;
}
break;
@@ -263,6 +297,8 @@ void electron_romboxp_device::expbus_w(offs_t offset, uint8_t data)
if (offset == 0xfc71)
{
m_cent_data_out->write(data);
+ m_centronics->write_strobe(0);
+ m_centronics->write_strobe(1);
}
break;
@@ -272,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;
}
@@ -285,36 +321,21 @@ void electron_romboxp_device::expbus_w(offs_t offset, uint8_t data)
// IMPLEMENTATION
//**************************************************************************
-uint8_t electron_romboxp_device::status_r()
+std::pair<std::error_condition, std::string> electron_romboxp_device::load_rom(device_image_interface &image, generic_slot_device *slot)
{
- // Status: b7: printer Busy
- return (m_centronics_busy << 7) | 0x7f;
-}
-
-
-WRITE_LINE_MEMBER(electron_romboxp_device::busy_w)
-{
- m_centronics_busy = !state;
-}
-
-
-image_init_result 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_UNSPECIFIED, "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 f5905bc47bf..5f360df284f 100644
--- a/src/devices/bus/electron/romboxp.h
+++ b/src/devices/bus/electron/romboxp.h
@@ -13,6 +13,7 @@
#define MAME_BUS_ELECTRON_ROMBOXP_H
#include "exp.h"
+#include "machine/input_merger.h"
#include "bus/centronics/ctronics.h"
#include "bus/electron/cart/slot.h"
#include "bus/generic/slot.h"
@@ -31,28 +32,26 @@ public:
electron_romboxp_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_t implementation
+ virtual void device_start() override ATTR_COLD;
+ virtual void device_reset() override ATTR_COLD;
// 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 void device_add_mconfig(machine_config &config) override ATTR_COLD;
+ virtual const tiny_rom_entry *device_rom_region() const override ATTR_COLD;
+ virtual ioport_constructor device_input_ports() const override ATTR_COLD;
virtual uint8_t expbus_r(offs_t offset) override;
virtual void expbus_w(offs_t offset, uint8_t data) override;
private:
- uint8_t status_r();
- DECLARE_WRITE_LINE_MEMBER(busy_w);
-
- 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]); }
DECLARE_DEVICE_IMAGE_LOAD_MEMBER(rom4_load) { return load_rom(image, m_rom[3]); }
+ required_device<input_merger_device> m_irqs;
required_memory_region m_exp_rom;
required_device_array<generic_slot_device, 4> m_rom;
required_device_array<electron_cartslot_device, 2> m_cart;
@@ -60,6 +59,7 @@ private:
required_device<output_latch_device> m_cent_data_out;
required_ioport m_option;
+ std::unique_ptr<uint8_t[]> m_ram;
uint8_t m_romsel;
uint8_t m_rom_base;
int m_centronics_busy;
diff --git a/src/devices/bus/electron/sidewndr.cpp b/src/devices/bus/electron/sidewndr.cpp
new file mode 100644
index 00000000000..0298bbce8e5
--- /dev/null
+++ b/src/devices/bus/electron/sidewndr.cpp
@@ -0,0 +1,185 @@
+// license:BSD-3-Clause
+// copyright-holders:Nigel Barnes
+/**********************************************************************
+
+ Wizard Sidewinder Rom Expansion Board
+
+ TODO: Fire button doesn't seem to be recognised.
+
+**********************************************************************/
+
+#include "emu.h"
+#include "sidewndr.h"
+
+#include "bus/generic/slot.h"
+#include "bus/generic/carts.h"
+#include "bus/vcs_ctrl/ctrl.h"
+
+
+namespace {
+
+class electron_sidewndr_device
+ : public device_t
+ , public device_electron_expansion_interface
+{
+public:
+ electron_sidewndr_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
+ : device_t(mconfig, ELECTRON_SIDEWNDR, tag, owner, clock)
+ , device_electron_expansion_interface(mconfig, *this)
+ , m_exp(*this, "exp")
+ , m_exp_rom(*this, "exp_rom")
+ , m_rom(*this, "rom%u", 1)
+ , m_joy(*this, "joy")
+ , m_romsel(0)
+ {
+ }
+
+protected:
+ // device_t overrides
+ virtual void device_start() override ATTR_COLD { }
+
+ // optional information overrides
+ virtual void device_add_mconfig(machine_config &config) override ATTR_COLD;
+ virtual const tiny_rom_entry *device_rom_region() const override ATTR_COLD;
+
+ virtual uint8_t expbus_r(offs_t offset) override;
+ virtual void expbus_w(offs_t offset, uint8_t data) override;
+
+private:
+ 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]); }
+
+ required_device<electron_expansion_slot_device> m_exp;
+ required_memory_region m_exp_rom;
+ required_device_array<generic_slot_device, 3> m_rom;
+ required_device<vcs_control_port_device> m_joy;
+
+ uint8_t m_romsel;
+};
+
+
+//-------------------------------------------------
+// rom_region - device-specific ROM region
+//-------------------------------------------------
+
+ROM_START( sidewndr )
+ ROM_REGION(0x2000, "exp_rom", 0)
+ ROM_LOAD("joyrom.rom", 0x0000, 0x2000, CRC(a7320cda) SHA1(771664dbf23bb14febeb414a0272762cd6091ead))
+ROM_END
+
+const tiny_rom_entry *electron_sidewndr_device::device_rom_region() const
+{
+ return ROM_NAME( sidewndr );
+}
+
+
+//-------------------------------------------------
+// device_add_mconfig - add device configuration
+//-------------------------------------------------
+
+void electron_sidewndr_device::device_add_mconfig(machine_config &config)
+{
+ GENERIC_SOCKET(config, m_rom[0], generic_plain_slot, "electron_rom", "bin,rom"); // ROM SLOT 6
+ m_rom[0]->set_device_load(FUNC(electron_sidewndr_device::rom1_load));
+ GENERIC_SOCKET(config, m_rom[1], generic_plain_slot, "electron_rom", "bin,rom"); // ROM SLOT 7
+ m_rom[1]->set_device_load(FUNC(electron_sidewndr_device::rom2_load));
+ GENERIC_SOCKET(config, m_rom[2], generic_plain_slot, "electron_rom", "bin,rom"); // ROM SLOT 8
+ m_rom[2]->set_device_load(FUNC(electron_sidewndr_device::rom3_load));
+
+ VCS_CONTROL_PORT(config, m_joy, vcs_control_port_devices, "joy");
+
+ ELECTRON_EXPANSION_SLOT(config, m_exp, DERIVED_CLOCK(1, 1), electron_expansion_devices, nullptr);
+ m_exp->irq_handler().set(DEVICE_SELF_OWNER, FUNC(electron_expansion_slot_device::irq_w));
+ m_exp->nmi_handler().set(DEVICE_SELF_OWNER, FUNC(electron_expansion_slot_device::nmi_w));
+}
+
+
+//-------------------------------------------------
+// expbus_r - expansion data read
+//-------------------------------------------------
+
+uint8_t electron_sidewndr_device::expbus_r(offs_t offset)
+{
+ uint8_t data = 0xff;
+
+ switch (offset >> 12)
+ {
+ case 0x8: case 0x9: case 0xa: case 0xb:
+ switch (m_romsel)
+ {
+ case 5:
+ data = m_exp_rom->base()[offset & 0x0fff];
+ break;
+ case 6:
+ case 7:
+ case 8:
+ data = m_rom[m_romsel - 6]->read_rom(offset & 0x3fff);
+ break;
+ }
+ break;
+
+ case 0xf:
+ switch (offset >> 8)
+ {
+ case 0xfc:
+ if (offset == 0xfc05)
+ {
+ data = bitswap<8>(m_joy->read_joy(), 7, 6, 4, 5, 3, 2, 1, 0);
+ }
+ break;
+
+ case 0xfd:
+ data = m_exp_rom->base()[offset & 0x1dff];
+ break;
+ }
+ break;
+ }
+
+ data &= m_exp->expbus_r(offset);
+
+ return data;
+}
+
+//-------------------------------------------------
+// expbus_w - expansion data write
+//-------------------------------------------------
+
+void electron_sidewndr_device::expbus_w(offs_t offset, uint8_t data)
+{
+ m_exp->expbus_w(offset, data);
+
+ if ((offset == 0xfe05) && !(data & 0xf0))
+ {
+ m_romsel = data & 0x0f;
+ }
+}
+
+//**************************************************************************
+// IMPLEMENTATION
+//**************************************************************************
+
+std::pair<std::error_condition, std::string> electron_sidewndr_device::load_rom(device_image_interface &image, generic_slot_device *slot)
+{
+ uint32_t const size = slot->common_get_size("rom");
+
+ // socket accepts 8K and 16K ROM only
+ if (size != 0x2000 && size != 0x4000)
+ 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 *const crt = slot->get_rom_base();
+ if (size <= 0x2000)
+ memcpy(crt + 0x2000, crt, 0x2000);
+
+ return std::make_pair(std::error_condition(), std::string());
+}
+
+} // anonymous namespace
+
+
+DEFINE_DEVICE_TYPE_PRIVATE(ELECTRON_SIDEWNDR, device_electron_expansion_interface, electron_sidewndr_device, "electron_sidewndr", "Wizard Sidewinder Rom Expansion Board")
diff --git a/src/devices/bus/electron/sidewndr.h b/src/devices/bus/electron/sidewndr.h
new file mode 100644
index 00000000000..e27e5e97584
--- /dev/null
+++ b/src/devices/bus/electron/sidewndr.h
@@ -0,0 +1,14 @@
+// license:BSD-3-Clause
+// copyright-holders:Nigel Barnes
+#ifndef MAME_BUS_ELECTRON_SIDEWNDR_H
+#define MAME_BUS_ELECTRON_SIDEWNDR_H
+
+#pragma once
+
+#include "exp.h"
+
+
+// device type definition
+DECLARE_DEVICE_TYPE(ELECTRON_SIDEWNDR, device_electron_expansion_interface)
+
+#endif // MAME_BUS_ELECTRON_SIDEWNDR_H
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..71620ffe44a
--- /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 ATTR_COLD;
+ virtual void device_add_mconfig(machine_config &config) override ATTR_COLD;
+
+ virtual void expbus_w(offs_t offset, uint8_t data) override;
+
+protected:
+ // device-level overrides
+ virtual void device_start() override ATTR_COLD;
+
+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 a4487db6ba4..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"
+
//**************************************************************************
@@ -89,9 +91,11 @@ const tiny_rom_entry *ep64_exdos_device::device_rom_region() const
// SLOT_INTERFACE( ep64_exdos_floppies )
//-------------------------------------------------
-FLOPPY_FORMATS_MEMBER( ep64_exdos_device::floppy_formats )
- FLOPPY_EP64_FORMAT
-FLOPPY_FORMATS_END
+void ep64_exdos_device::floppy_formats(format_registration &fr)
+{
+ fr.add_mfm_containers();
+ fr.add(FLOPPY_EP64_FORMAT);
+}
static void ep64_exdos_floppies(device_slot_interface &device)
{
@@ -107,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");
}
@@ -126,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")
{
}
@@ -144,8 +144,8 @@ void ep64_exdos_device::device_start()
{
m_slot->program().install_rom(0x080000, 0x087fff, m_rom->base());
- m_slot->io().install_readwrite_handler(0x10, 0x13, 0, 0x04, 0, read8sm_delegate(FUNC(wd_fdc_device_base::read), m_fdc.target()), write8sm_delegate(FUNC(wd_fdc_device_base::write), m_fdc.target()));
- m_slot->io().install_readwrite_handler(0x18, 0x18, 0, 0x04, 0, READ8_DELEGATE(ep64_exdos_device, read), WRITE8_DELEGATE(ep64_exdos_device, write));
+ m_slot->io().install_readwrite_handler(0x10, 0x13, 0, 0x04, 0, read8sm_delegate(*m_fdc, FUNC(wd_fdc_device_base::read)), write8sm_delegate(*m_fdc, FUNC(wd_fdc_device_base::write)));
+ m_slot->io().install_readwrite_handler(0x18, 0x18, 0, 0x04, 0, read8smo_delegate(*this, FUNC(ep64_exdos_device::read)), write8smo_delegate(*this, FUNC(ep64_exdos_device::write)));
}
@@ -157,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);
}
@@ -167,7 +167,7 @@ void ep64_exdos_device::device_reset()
// read -
//-------------------------------------------------
-READ8_MEMBER( ep64_exdos_device::read )
+uint8_t ep64_exdos_device::read()
{
/*
@@ -189,7 +189,7 @@ READ8_MEMBER( 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;
}
@@ -199,7 +199,7 @@ READ8_MEMBER( ep64_exdos_device::read )
// write -
//-------------------------------------------------
-WRITE8_MEMBER( ep64_exdos_device::write )
+void ep64_exdos_device::write(uint8_t data)
{
/*
@@ -216,19 +216,18 @@ WRITE8_MEMBER( ep64_exdos_device::write )
*/
- 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_selected_floppy = nullptr;
- m_fdc->set_floppy(m_floppy);
-
- 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 b437c56eb50..e2288de89a9 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"
@@ -31,27 +30,24 @@ public:
// construction/destruction
ep64_exdos_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
- DECLARE_READ8_MEMBER( read );
- DECLARE_WRITE8_MEMBER( write );
+ uint8_t read();
+ void write(uint8_t data);
protected:
// device-level overrides
- virtual void device_start() override;
- virtual void device_reset() override;
+ virtual void device_start() override ATTR_COLD;
+ virtual void device_reset() override ATTR_COLD;
// optional information overrides
- virtual const tiny_rom_entry *device_rom_region() const override;
- virtual void device_add_mconfig(machine_config &config) override;
+ virtual const tiny_rom_entry *device_rom_region() const override ATTR_COLD;
+ virtual void device_add_mconfig(machine_config &config) override ATTR_COLD;
private:
- DECLARE_FLOPPY_FORMATS( floppy_formats );
+ 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 c241fb68c08..aff87fc77cc 100644
--- a/src/devices/bus/ep64/exp.cpp
+++ b/src/devices/bus/ep64/exp.cpp
@@ -28,7 +28,7 @@ DEFINE_DEVICE_TYPE(EP64_EXPANSION_BUS_SLOT, ep64_expansion_bus_slot_device, "ep6
//-------------------------------------------------
device_ep64_expansion_bus_card_interface::device_ep64_expansion_bus_card_interface(const machine_config &mconfig, device_t &device)
- : device_slot_card_interface(mconfig, device)
+ : device_interface(device, "ep64exp")
{
m_slot = dynamic_cast<ep64_expansion_bus_slot_device *>(device.owner());
}
@@ -45,7 +45,7 @@ device_ep64_expansion_bus_card_interface::device_ep64_expansion_bus_card_interfa
ep64_expansion_bus_slot_device::ep64_expansion_bus_slot_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
: device_t(mconfig, EP64_EXPANSION_BUS_SLOT, tag, owner, clock)
- , device_slot_interface(mconfig, *this)
+ , device_single_card_slot_interface<device_ep64_expansion_bus_card_interface>(mconfig, *this)
, m_write_irq(*this)
, m_write_nmi(*this)
, m_write_wait(*this)
@@ -57,41 +57,12 @@ ep64_expansion_bus_slot_device::ep64_expansion_bus_slot_device(const machine_con
//-------------------------------------------------
-// device_validity_check -
-//-------------------------------------------------
-
-void ep64_expansion_bus_slot_device::device_validity_check(validity_checker &valid) const
-{
- device_t *const carddev = get_card_device();
- if (carddev && !dynamic_cast<device_ep64_expansion_bus_card_interface *>(carddev))
- osd_printf_error("Card device %s (%s) does not implement device_ep64_expansion_bus_card_interface\n", carddev->tag(), carddev->name());
-}
-
-
-//-------------------------------------------------
// device_start - device-specific startup
//-------------------------------------------------
void ep64_expansion_bus_slot_device::device_start()
{
- device_t *const carddev = get_card_device();
- m_card = dynamic_cast<device_ep64_expansion_bus_card_interface *>(carddev);
- if (carddev && !m_card)
- fatalerror("Card device %s (%s) does not implement device_ep64_expansion_bus_card_interface\n", carddev->tag(), carddev->name());
-
- // resolve callbacks
- m_write_irq.resolve_safe();
- m_write_nmi.resolve_safe();
- m_write_wait.resolve_safe();
-}
-
-
-//-------------------------------------------------
-// device_reset - device-specific reset
-//-------------------------------------------------
-
-void ep64_expansion_bus_slot_device::device_reset()
-{
+ m_card = get_card_device();
}
diff --git a/src/devices/bus/ep64/exp.h b/src/devices/bus/ep64/exp.h
index 88d3b4e61b9..bb25803e6a5 100644
--- a/src/devices/bus/ep64/exp.h
+++ b/src/devices/bus/ep64/exp.h
@@ -59,7 +59,7 @@ void ep64_expansion_bus_cards(device_slot_interface &device);
class device_ep64_expansion_bus_card_interface;
class ep64_expansion_bus_slot_device : public device_t,
- public device_slot_interface
+ public device_single_card_slot_interface<device_ep64_expansion_bus_card_interface>
{
friend class device_ep64_expansion_bus_card_interface;
@@ -81,18 +81,16 @@ 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; }
protected:
// device-level overrides
- virtual void device_validity_check(validity_checker &valid) const override;
- virtual void device_start() override;
- virtual void device_reset() override;
+ virtual void device_start() override ATTR_COLD;
private:
devcb_write_line m_write_irq;
@@ -108,7 +106,7 @@ private:
// ======================> device_ep64_expansion_bus_card_interface
-class device_ep64_expansion_bus_card_interface : public device_slot_card_interface
+class device_ep64_expansion_bus_card_interface : public device_interface
{
protected:
// construction/destruction
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..25f5d537a1d
--- /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 ATTR_COLD;
+ virtual void device_reset() override ATTR_COLD;
+ virtual ioport_constructor device_input_ports() const override ATTR_COLD;
+ virtual space_config_vector memory_space_config() const override;
+
+private:
+ void write(offs_t offset, uint8_t data);
+
+ void io_map(address_map &map) ATTR_COLD;
+ void xmem_map(address_map &map) ATTR_COLD;
+
+ 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..b19ae7327da
--- /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 ATTR_COLD;
+ virtual void device_reset() override ATTR_COLD;
+
+ // optional information overrides
+ virtual void device_add_mconfig(machine_config &config) override ATTR_COLD;
+
+ void map(address_map &map) ATTR_COLD;
+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..d8ecfb0a1b1
--- /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 ATTR_COLD;
+ virtual void device_reset() override ATTR_COLD;
+ virtual ioport_constructor device_input_ports() const override ATTR_COLD;
+
+ uint8_t read(offs_t offset);
+ void write(offs_t offset, uint8_t data);
+
+ void map(address_map &map) ATTR_COLD;
+
+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..f260cd4849d
--- /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_KEYBOARD_H
+#define MAME_BUS_EPSON_QX_KEYBOARD_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 ATTR_COLD;
+ virtual void device_reset() override ATTR_COLD;
+
+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 ATTR_COLD;
+ virtual const tiny_rom_entry *device_rom_region() const override ATTR_COLD;
+ virtual void device_start() override ATTR_COLD;
+ 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 ATTR_COLD;
+ 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 ATTR_COLD;
+ 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 // MAME_BUS_EPSON_QX_KEYBOARD_KEYBOARD_H
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/multifont.cpp b/src/devices/bus/epson_qx/multifont.cpp
new file mode 100644
index 00000000000..27486cb5d4c
--- /dev/null
+++ b/src/devices/bus/epson_qx/multifont.cpp
@@ -0,0 +1,289 @@
+// license:BSD-3-Clause
+// copyright-holders:Brian Johnson
+/*******************************************************************
+ *
+ * Q10MF Multifont card
+ * Schematic: https://github.com/brijohn/qx10/raw/master/schematics/multifont/multifont.pdf
+ * Documentation: http://www.bitsavers.org/pdf/epson/QX-10/options/QX-10-multifont.pdf
+ *
+ * I/O Ports:
+ * 0xFC:
+ * Read:
+ * Reading from this will read a status byte followed by the character data for a requested character.
+ * Status byte:
+ * -------------------------------------------------
+ * | VALID | MODE | 0 0 | UP | RIGHT | LEFT | DOWN |
+ * -------------------------------------------------
+ * Valid: 1 = Character is valid, 0 = Character is invalid
+ * Mode: 1 = Pattern is for CRT, 0 = Pattern is for printer
+ * Up: Extends upwards 0 = No, 1 = Yes
+ * Right: Extends to the right 0 = No, 1 = Yes
+ * Left: Extends to the left 0 = No, 1 = Yes
+ * Down: Extends downwards 0 = No, 1 = Yes
+ * Write:
+ * Data written to this consists of a command byte followed by two bytes representing
+ * the character code being requested, least significant byte first. (0x0000-0x0DFF)
+ * Command byte:
+ * ------------------------------------------
+ * | 1 | MODE | 0 0 0 0 0 | BIT |
+ * ------------------------------------------
+ * Mode: 0 = Pattern for printer, 1 = Pattern for CRT
+ * Bit: 0 = Non-DMA Pattern for CRT, 1 = DMA pattern for CRT
+ * 0xFD:
+ * Read:
+ * This is the status register for the multifont card.
+ * ----------------------------------------------
+ * | IBF | X X X | X X | ERR | OBF |
+ * ----------------------------------------------
+ * IBF: 1 = Data available to read, 0 = Data not available
+ * ERR: 1 = Error occured, 0 = No error
+ * OBF: 1 = Not ready for data to be written , 0 = Ready for data
+ * Write:
+ * Writing any value will trigger an INTL interrupt. This used by cpm to determine
+ * which slot the card is installed in. To reset the interrupt simply read from the
+ * status port.
+ *
+ *******************************************************************/
+#include "emu.h"
+#include "multifont.h"
+
+
+//**************************************************************************
+// EPSON Q10MF MULTIFONT DEVICE
+//**************************************************************************
+
+DEFINE_DEVICE_TYPE(EPSON_QX_OPTION_MULTIFONT, bus::epson_qx::multifont_device, "epson_qx_option_multifont", "Epson Multifont Card")
+
+
+namespace bus::epson_qx {
+
+ROM_START(multifont)
+ /* This is the i8039 program ROM for the Q10MF Multifont card */
+ ROM_REGION( 0x0800, "i8039", 0 )
+ ROM_LOAD( "m12020a.3e", 0x0000, 0x0800, CRC(fa27f333) SHA1(73d27084ca7b002d5f370220d8da6623a6e82132))
+
+ ROM_REGION( 0x4000, "font0", 0 )
+ ROM_LOAD( "hn43128.1a", 0x0000, 0x4000, CRC(0ba54615) SHA1(d718e9b3b6cab29a17c2d4d72a7b397121d96ffd))
+ ROM_REGION( 0x4000, "font1", 0 )
+ ROM_LOAD( "hn43128.2a", 0x0000, 0x4000, CRC(968a8848) SHA1(e19ef2bd46c7471ed682a6d456be9cb1db5ce321))
+ ROM_REGION( 0x4000, "font2", 0 )
+ ROM_LOAD( "hn43128.1b", 0x0000, 0x4000, CRC(e4ed0fb1) SHA1(77e825061f9af77d3f1963aa9cbbb46f49e86f92))
+ ROM_REGION( 0x4000, "font3", 0 )
+ ROM_LOAD( "hn43128.2b", 0x0000, 0x4000, CRC(27e9c1da) SHA1(926985f0fec6b00960acd616bc73596bcb3d3884))
+ ROM_REGION( 0x4000, "font4", 0 )
+ ROM_LOAD( "hn43128.3a", 0x0000, 0x4000, CRC(3e5dd796) SHA1(ffa6eb775545833b8e7647c450595fab6d6aa341))
+ ROM_REGION( 0x4000, "font5", 0 )
+ ROM_LOAD( "hn43128.3b", 0x0000, 0x4000, CRC(adc569bf) SHA1(19246af07d6728ccd74a021265df827ecc6fe2b5))
+ /* Sockets 1c and 2c are empty */
+ ROM_REGION( 0x4000, "font6", 0 )
+ ROM_LOAD( "hn43128.1c", 0x0000, 0x4000, NO_DUMP)
+ ROM_REGION( 0x4000, "font7", 0 )
+ ROM_LOAD( "hn43128.2c", 0x0000, 0x4000, NO_DUMP)
+ROM_END
+
+INPUT_PORTS_START(multifont)
+ PORT_START("IOBASE")
+ PORT_CONFNAME(0x06, 0x04, "IO Base Address Selection")
+ PORT_CONFSETTING(0x00, "&F8")
+ PORT_CONFSETTING(0x02, "&FA")
+ PORT_CONFSETTING(0x04, "&FC")
+ PORT_CONFSETTING(0x06, "&FE")
+INPUT_PORTS_END
+
+//-------------------------------------------------
+// multifont_device - constructor
+//-------------------------------------------------
+multifont_device::multifont_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) :
+ device_t(mconfig, EPSON_QX_OPTION_MULTIFONT, tag, owner, clock),
+ device_option_expansion_interface(mconfig, *this),
+ m_mcu(*this, "mcu"),
+ m_i8243(*this, "i8243"),
+ m_fonts(*this, "font%u",0),
+ m_ioport(*this, "IOBASE")
+{
+}
+
+//-------------------------------------------------
+// device_input_ports - device-specific ports
+//-------------------------------------------------
+ioport_constructor multifont_device::device_input_ports() const
+{
+ return INPUT_PORTS_NAME(multifont);
+}
+
+//-------------------------------------------------
+// device_rom_region - device-specific roms
+//-------------------------------------------------
+const tiny_rom_entry *multifont_device::device_rom_region() const
+{
+ return ROM_NAME(multifont);
+}
+
+//-------------------------------------------------
+// device_add_mconfig - device-specific config
+//-------------------------------------------------
+void multifont_device::device_add_mconfig(machine_config &config)
+{
+ I8039(config, m_mcu, 9_MHz_XTAL);
+ m_mcu->set_addrmap(AS_PROGRAM, &multifont_device::rom_map);
+ m_mcu->prog_out_cb().set(m_i8243, FUNC(i8243_device::prog_w));
+ m_mcu->p1_out_cb().set(FUNC(multifont_device::p1_w));
+ m_mcu->p2_out_cb().set(FUNC(multifont_device::p2_w));
+ m_mcu->bus_out_cb().set(FUNC(multifont_device::write_bus));
+ m_mcu->bus_in_cb().set(FUNC(multifont_device::read_bus));
+ m_mcu->t1_in_cb().set(FUNC(multifont_device::t1_r));
+ m_mcu->t0_in_cb().set(FUNC(multifont_device::t0_r));
+ I8243(config, m_i8243);
+ m_i8243->p4_out_cb().set(FUNC(multifont_device::rom_addr_w<0>));
+ m_i8243->p5_out_cb().set(FUNC(multifont_device::rom_addr_w<4>));
+ m_i8243->p6_out_cb().set(FUNC(multifont_device::rom_addr_w<8>));
+ m_i8243->p7_out_cb().set(FUNC(multifont_device::rom_select_w));
+}
+
+//-------------------------------------------------
+// device_start - device-specific startup
+//-------------------------------------------------
+void multifont_device::device_start()
+{
+ m_hard_reset = true;
+
+ m_data_out = 0x00;
+ m_data_in = 0x00;
+ m_p1 = 0xff;
+ m_p2 = 0xff;
+
+ save_item(NAME(m_status));
+ save_item(NAME(m_data_out));
+ save_item(NAME(m_data_in));
+ save_item(NAME(m_p1));
+ save_item(NAME(m_p2));
+ save_item(NAME(m_rom_sel));
+ save_item(NAME(m_address));
+ save_item(NAME(m_rom_bank));
+ save_item(NAME(m_bus_reset));
+ save_item(NAME(m_hard_reset));
+}
+
+//-------------------------------------------------
+// device_reset - device-specific reset
+//-------------------------------------------------
+void multifont_device::device_reset()
+{
+ uint8_t iobase;
+
+ m_status = 0x00;
+
+ if (m_hard_reset) {
+ address_space &space = m_bus->iospace();
+ iobase = (m_ioport->read() & 0x06) + 0xf8;
+ space.install_device(iobase, iobase+1, *this, &multifont_device::map);
+ m_hard_reset = false;
+ }
+
+ m_bus_reset = true;
+}
+
+uint8_t multifont_device::t0_r()
+{
+ return BIT(m_status, 0);
+}
+
+uint8_t multifont_device::t1_r()
+{
+ return BIT(m_status, 7);
+}
+
+void multifont_device::write_bus(uint8_t data)
+{
+ if (!m_bus_reset) {
+ m_status = m_status | 0x80;
+ m_data_out = data;
+ } else {
+ m_bus_reset = false;
+ }
+}
+
+uint8_t multifont_device::read_bus()
+{
+ if (BIT(m_p1, 0)) {
+ m_status = (m_status & 0xfe);
+ return m_data_in;
+ } else if (BIT(m_p1, 1)) {
+ uint8_t *rom = m_fonts[m_rom_bank]->base();
+ return rom[m_address];
+ }
+ return 0xff;
+}
+
+void multifont_device::p1_w(uint8_t data)
+{
+ m_p1 = data;
+ if (BIT(m_p1, 7) == 0) {
+ get_slot()->intl_w(ASSERT_LINE);
+ }
+}
+
+void multifont_device::p2_w(uint8_t data)
+{
+ m_p2 = data;
+ m_i8243->p2_w(m_p2 & 0x0f);
+ update_bank_select();
+ m_status = (m_status & 0xfd) | ((m_p2 & 0x20) >> 4);
+}
+
+template<int Shift>
+void multifont_device::rom_addr_w(uint8_t data)
+{
+ m_address = (m_address & ~(0x00f << Shift)) | ((data & 0x0f) << Shift);
+}
+
+void multifont_device::rom_select_w(uint8_t data)
+{
+ m_rom_sel = (data & 0x0f) >> 2;
+ m_address = (m_address & 0xfff) | ((data & 0x03) << 12);
+ update_bank_select();
+}
+
+void multifont_device::update_bank_select()
+{
+ m_rom_bank = ((m_p2 & 0x80) >> 5) | (m_rom_sel & 0x03);
+}
+
+uint8_t multifont_device::read(offs_t offset)
+{
+ if (offset) {
+ if (!machine().side_effects_disabled()) {
+ if (BIT(m_p1, 7)) {
+ get_slot()->intl_w(CLEAR_LINE);
+ }
+ }
+ return m_status;
+ }
+ if (!machine().side_effects_disabled()) {
+ m_status = (m_status & 0x7f);
+ }
+ return m_data_out;
+}
+
+void multifont_device::write(offs_t offset, uint8_t data)
+{
+ if (offset) {
+ get_slot()->intl_w(ASSERT_LINE);
+ } else {
+ m_status = m_status | 0x01;
+ m_data_in = data;
+ }
+}
+
+void multifont_device::rom_map(address_map &map)
+{
+ map.global_mask(0x07ff);
+ map(0x0000, 0x07ff).rom().region("i8039", 0);
+}
+
+void multifont_device::map(address_map &map)
+{
+ map(0x00, 0x01).rw(FUNC(multifont_device::read), FUNC(multifont_device::write));
+}
+
+} // namespace bus::epson_qx
diff --git a/src/devices/bus/epson_qx/multifont.h b/src/devices/bus/epson_qx/multifont.h
new file mode 100644
index 00000000000..256e3c26bfb
--- /dev/null
+++ b/src/devices/bus/epson_qx/multifont.h
@@ -0,0 +1,87 @@
+// license:BSD-3-Clause
+// copyright-holders:Brian Johnson
+/*******************************************************************
+ *
+ * Q10MF Multifont card
+ *
+ *******************************************************************/
+
+#ifndef MAME_BUS_EPSON_QX_MULTIFONT_H
+#define MAME_BUS_EPSON_QX_MULTIFONT_H
+
+#pragma once
+
+#include "bus/epson_qx/option.h"
+#include "cpu/mcs48/mcs48.h"
+#include "machine/i8243.h"
+
+namespace bus::epson_qx {
+
+//**************************************************************************
+// TYPE DEFINITIONS
+//**************************************************************************
+
+/* Epson QX-10 Multifont Device */
+
+class multifont_device : public device_t, public bus::epson_qx::device_option_expansion_interface
+{
+public:
+ // construction/destruction
+ multifont_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
+
+protected:
+ // device-level overrides
+ virtual void device_start() override ATTR_COLD;
+ virtual void device_reset() override ATTR_COLD;
+
+ // optional information overrides
+ virtual const tiny_rom_entry *device_rom_region() const override ATTR_COLD;
+ virtual void device_add_mconfig(machine_config &config) override ATTR_COLD;
+ virtual ioport_constructor device_input_ports() const override ATTR_COLD;
+
+ uint8_t read(offs_t offset);
+ void write(offs_t offset, uint8_t data);
+
+ void rom_map(address_map &map) ATTR_COLD;
+ void map(address_map &map) ATTR_COLD;
+
+ void p1_w(uint8_t data);
+ void p2_w(uint8_t data);
+ template<int Shift> void rom_addr_w(uint8_t data);
+ void rom_select_w(uint8_t data);
+ uint8_t t0_r();
+ uint8_t t1_r();
+
+ void write_bus(uint8_t data);
+ uint8_t read_bus();
+private:
+ void update_bank_select();
+
+ required_device<i8039_device> m_mcu;
+ required_device<i8243_device> m_i8243;
+ required_memory_region_array<8> m_fonts;
+ required_ioport m_ioport;
+
+ uint8_t m_status;
+
+ uint8_t m_data_out;
+ uint8_t m_data_in;
+ uint8_t m_p1;
+ uint8_t m_p2;
+ uint8_t m_rom_sel;
+ uint16_t m_address;
+ uint8_t m_rom_bank;
+
+ bool m_bus_reset;
+ bool m_hard_reset;
+};
+
+} // namespace bus::epson_qx
+
+// device type definition
+DECLARE_DEVICE_TYPE_NS(EPSON_QX_OPTION_MULTIFONT, bus::epson_qx, multifont_device)
+
+
+#endif // MAME_BUS_EPSON_QX_MULTIFONT_H
+
+
diff --git a/src/devices/bus/epson_qx/option.cpp b/src/devices/bus/epson_qx/option.cpp
new file mode 100644
index 00000000000..a22a20236b3
--- /dev/null
+++ b/src/devices/bus/epson_qx/option.cpp
@@ -0,0 +1,204 @@
+// license:BSD-3-Clause
+// copyright-holders:Brian Johnson
+/*******************************************************************
+ *
+ * Epson QX-10 Expansion emulation
+ *
+ *******************************************************************/
+#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")
+
+namespace bus::epson_qx {
+//**************************************************************************
+// EPSON 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, EPSON_QX_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_dmas_w_cb(*this),
+ m_dmas_r_cb(*this, 0xff),
+ m_dmaf_w_cb(*this),
+ m_dmaf_r_cb(*this, 0),
+ m_eopf_cb(*this),
+ m_eops_cb(*this),
+ 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);
+}
+
+void option_slot_device::eopf(int state) { m_eopf_cb(state); }
+void option_slot_device::eops(int state) { m_eops_cb(state); }
+
+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); }
+
+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); }
+
+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
+//**************************************************************************
+
+//-------------------------------------------------
+// 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, EPSON_QX_OPTION_BUS, tag, owner, clock),
+ m_iospace(*this, finder_base::DUMMY_TAG, -1),
+ m_inth1_cb(*this),
+ m_inth2_cb(*this),
+ m_intl_cb(*this),
+ m_drqf_cb(*this),
+ m_drqs_cb(*this),
+ m_rdyf_cb(*this),
+ m_rdys_cb(*this),
+ m_inth1(0),
+ m_inth2(0),
+ m_drqf(0),
+ m_rdyf(0),
+ m_rdys(0)
+{
+}
+
+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()
+{
+ m_inth1 = 0;
+ m_inth2 = 0;
+ m_drqf = 0;
+ m_rdyf = 0;
+ m_rdys = 0;
+}
+
+void option_bus_device::dackf_w(uint8_t data)
+{
+ for (int i = 0; i < m_slot_list.size(); ++i) {
+ m_slot_list[i]->m_dmaf_w_cb(data);
+ }
+}
+
+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.isunset()) {
+ found = true;
+ value |= m_slot_list[i]->m_dmaf_r_cb();
+ }
+ }
+ return (found ? value : 0xff);
+}
+
+void option_bus_device::set_inth1_line(uint8_t state, uint8_t slot)
+{
+ m_inth1 = state ? (m_inth1 | (1 << (slot & 0x07))) : (m_inth1 & ~(1 << (slot & 0x07)));
+ m_inth1_cb(m_inth1 != 0);
+}
+
+void option_bus_device::set_inth2_line(uint8_t state, uint8_t slot)
+{
+ m_inth2 = state ? (m_inth2 | (1 << (slot & 0x07))) : (m_inth2 & ~(1 << (slot & 0x07)));
+ m_inth2_cb(m_inth2 != 0);
+}
+
+void option_bus_device::set_drqf_line(uint8_t state, uint8_t slot)
+{
+ m_drqf = !state ? (m_drqf | (1 << (slot & 0x07))) : (m_drqf & ~(1 << (slot & 0x07)));
+ m_drqf_cb(m_drqf == 0);
+}
+
+void option_bus_device::set_rdyf_line(uint8_t state, uint8_t slot)
+{
+ m_rdyf = !state ? (m_rdyf | (1 << (slot & 0x07))) : (m_rdyf & ~(1 << (slot & 0x07)));
+ m_rdyf_cb(m_rdyf == 0);
+}
+
+void option_bus_device::set_rdys_line(uint8_t state, uint8_t slot)
+{
+ m_rdys = !state ? (m_rdys | (1 << (slot & 0x07))) : (m_rdys & ~(1 << (slot & 0x07)));
+ m_rdys_cb(m_rdys == 0);
+}
+
+
+//**************************************************************************
+// EPSON 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, "qx_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("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
new file mode 100644
index 00000000000..0f39a194b51
--- /dev/null
+++ b/src/devices/bus/epson_qx/option.h
@@ -0,0 +1,280 @@
+// license:BSD-3-Clause
+// copyright-holders:Brian Johnson
+/*
+ QX-10 Option bus
+
+ 1 GND 2 GND
+ 3 DTB0 4 DTB1
+ 5 DTB2 6 DTB3
+ 7 DTB4 8 DTB5
+ 9 DTB6 10 DTB7
+ 11 -12V 12 -12V
+ 13 ADR0 14 ADR1
+ 15 ADR2 16 ADR3
+ 17 ADR4 18 ADR5
+ 19 ADR6 20 ADR7
+ 21 ADR8 22 ADR9
+ 23 ADR10 24 ADR11
+ 25 ADR12 26 ADR13
+ 27 ADR14 28 ADR15
+ 29 GND 30 GND
+ 31 CLK 32 GND
+ 33 /BSAK 34 /MEMX
+ 35 /IRD 36 /IWR
+ 37 /MRD 38 /MWR
+ 39 /RSIN 40 INTH1
+ 41 INTH2 42 INTL
+ 43 +5V 44 /RSET
+ 45 +5V 46 +5V
+ 47 /DRQF 48 /DRQS
+ 49 /RDYF 50 /RDYS
+ 51 /WAIT 52 /IWS
+ 53 /DAKF 54 /DAKS
+ 55 /EOPF 56 /EOPS
+ 57 +12V 58 +12V
+ 59 GND 60 GND
+
+ The INTH1 and INTH2 singals are the two hihg priority interrupts and are
+ global to the entire option bus. The INTL signal is the low priority interrupt
+ and is local to each of the 5 option slots.
+
+ 5 4 3 2 1
+ |---| |---| |---| |---| |---|
+ | | | | | | | | | |
+ | | | | | | | | | |
+ | | | | | | | | | |
+ | | | | | | | | | |
+ | *-|--|-*-|--|-*-|--|-*-|--|-*-|--------IRQH1 (Master IR2)
+ | | | | | | | | | |
+ | *-|--|-*-|--|-*-|--|-*-|--|-*-|--------IRQH2 (Master IR3)
+ | | | | | | | | | |
+ | | | | | | | | | |
+ | | | | | | | | | *-|--------IRQL (Slave IR1)
+ | | | | | | | | | |
+ | | | | | | | *-|--|---|--------IRQL (Slave IR3)
+ | | | | | | | | | |
+ | | | | | *-|--|---|--|---|--------IRQL (Slave IR4)
+ | | | | | | | | | |
+ | | | *-|--|---|--|---|--|---|--------IRQL (Slave IR6)
+ | | | | | | | | | |
+ | *-|--|---|--|---|--|---|--|---|--------IRQL (Slave IR7)
+ | | | | | | | | | |
+ | | | | | | | | | |
+ | | | | | | | | | |
+ | | | | | | | | | |
+ |---| |---| |---| |---| |---|
+
+ The DREQ/DACK(F) signals are the high priorty DMA signals and are shared between all option slots.
+ The DREQ/DACK(S) signals are the lower priority DMA signals and are local to each slot, with the
+ exception of slot 5 which does not provide low priority DMA signals. The RDY/EOP(S) signals are
+ also connected to all 5 options slots since the DREQ(S) signals are all connected to the same
+ DMA controller.
+
+ 5 4 3 2 1
+ |---| |---| |---| |---| |---|
+ | | | | | | | | | |
+ | *-|--|-*-|--|-*-|--|-*-|--|-*-|--------DREQF (Master CH3)
+ | *-|--|-*-|--|-*-|--|-*-|--|-*-|--------DACKF (Master Ch3)
+ | | | | | | | | | |
+ | *-|--|-*-|--|-*-|--|-*-|--|-*-|--------RDYF (Master RDY)
+ | *-|--|-*-|--|-*-|--|-*-|--|-*-|--------EOPF (Master EOP)
+ | | | | | | | | | |
+ | | | | | | | | | *-|--------DREQS (Slave CH0)
+ | | | | | | | | | *-|--------DACKS (Slave CH0)
+ | | | | | | | | | |
+ | | | | | | | *-|--|---|--------DREQS (Slave CH1)
+ | | | | | | | *-|--|---|--------DACKS (Slave CH1)
+ | | | | | | | | | |
+ | | | | | *-|--|---|--|---|--------DREQS (Slave CH2)
+ | | | | | *-|--|---|--|---|--------DACKS (Slave CH2)
+ | | | | | | | | | |
+ | | | *-|--|---|--|---|--|---|--------DREQS (Slave CH3)
+ | | | *-|--|---|--|---|--|---|--------DACKS (Slave CH3)
+ | | | | | | | | | |
+ | *-|--|-*-|--|-*-|--|-*-|--|-*-|--------RDYS (Slave RDY)
+ | *-|--|-*-|--|-*-|--|-*-|--|-*-|--------EOPS (Slave EOP)
+ | | | | | | | | | |
+ |---| |---| |---| |---| |---|
+
+*/
+#ifndef MAME_BUS_EPSON_QX_OPTION_H
+#define MAME_BUS_EPSON_QX_OPTION_H
+
+#pragma once
+
+#include <vector>
+
+namespace bus::epson_qx {
+
+//**************************************************************************
+// FORWARD DECLARATIONS
+//**************************************************************************
+
+class option_bus_device;
+class device_option_expansion_interface;
+
+
+//**************************************************************************
+// TYPE DEFINITIONS
+//**************************************************************************
+
+/* Epson Slot Device */
+
+class option_slot_device : public device_t, public device_single_card_slot_interface<device_option_expansion_interface>
+{
+public:
+ friend class option_bus_device;
+ // 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);
+
+ void inth1_w(int state);
+ void inth2_w(int state);
+ void intl_w(int state);
+
+ void drqf_w(int state);
+ void drqs_w(int state);
+
+ void rdyf_w(int state);
+ void rdys_w(int state);
+
+ 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(); }
+ auto dmaf_w_callback() { m_dmaf_w_cb.bind(); }
+ auto dmaf_r_callback() { m_dmaf_r_cb.bind(); }
+
+ auto in_eopf_callback() { return m_eopf_cb.bind(); }
+ auto in_eops_callback() { return m_eops_cb.bind(); }
+protected:
+ // device-level overrides
+ virtual void device_start() override ATTR_COLD;
+
+ // configuration
+ required_device<option_bus_device> m_bus;
+ devcb_write8 m_dmas_w_cb;
+ devcb_read8 m_dmas_r_cb;
+ devcb_write8 m_dmaf_w_cb;
+ devcb_read8 m_dmaf_r_cb;
+
+ devcb_write_line m_eopf_cb;
+ devcb_write_line m_eops_cb;
+
+ int m_slot;
+};
+
+
+/* Epson 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 <typename T> void set_iospace(T &&tag, int spacenum) { m_iospace.set_tag(std::forward<T>(tag), spacenum); }
+ void set_memview(memory_view::memory_view_entry &view) { m_view = &view; }
+
+ auto out_inth1_callback() { return m_inth1_cb.bind(); }
+ auto out_inth2_callback() { return m_inth2_cb.bind(); }
+ template <unsigned Slot> auto out_intl_callback() { return m_intl_cb[Slot].bind(); }
+
+ auto out_drqf_callback() { return m_drqf_cb.bind(); }
+ template <unsigned Slot> auto out_drqs_callback() { return m_drqs_cb[Slot].bind(); }
+
+ auto out_rdyf_callback() { return m_rdyf_cb.bind(); }
+ auto out_rdys_callback() { return m_rdys_cb.bind(); }
+
+ memory_view::memory_view_entry& memview() const { return *m_view; }
+ address_space &iospace() const { return *m_iospace; }
+
+ void dackf_w(uint8_t data);
+ uint8_t dackf_r();
+ template <unsigned Slot> void dacks_w(uint8_t data) { (*this)[Slot]->m_dmas_w_cb(data); }
+ template <unsigned Slot> uint8_t dacks_r() { return (*this)[Slot]->m_dmas_r_cb(); }
+
+ template <void (option_slot_device::*slot_callback)(int)> void slots_w(int state) {
+ for (option_slot_device *slot : m_slot_list) {
+ (slot->*slot_callback)(state);
+ }
+ }
+
+ void set_inth1_line(uint8_t state, uint8_t slot);
+ void set_inth2_line(uint8_t state, uint8_t slot);
+ void set_intl_line(uint8_t state, uint8_t slot) { m_intl_cb[slot](state); }
+ void set_drqf_line(uint8_t state, uint8_t slot);
+ void set_drqs_line(uint8_t state, uint8_t slot) { m_drqs_cb[slot](state); }
+ void set_rdyf_line(uint8_t state, uint8_t slot);
+ void set_rdys_line(uint8_t state, uint8_t slot);
+
+ 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 ATTR_COLD;
+ virtual void device_reset() override ATTR_COLD;
+
+ required_address_space m_iospace;
+ memory_view::memory_view_entry *m_view;
+
+ devcb_write_line m_inth1_cb;
+ devcb_write_line m_inth2_cb;
+ devcb_write_line::array<5> m_intl_cb;
+
+ devcb_write_line m_drqf_cb;
+ devcb_write_line::array<4> m_drqs_cb;
+
+ devcb_write_line m_rdyf_cb;
+ devcb_write_line m_rdys_cb;
+
+ std::vector<option_slot_device *> m_slot_list;
+
+ uint8_t m_inth1;
+ uint8_t m_inth2;
+
+ uint8_t m_drqf;
+
+ uint8_t m_rdyf;
+ uint8_t m_rdys;
+};
+
+
+/* Epson 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; }
+
+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::epson_qx
+
+
+// device type definition
+DECLARE_DEVICE_TYPE_NS(EPSON_QX_OPTION_BUS_SLOT, bus::epson_qx, option_slot_device)
+DECLARE_DEVICE_TYPE_NS(EPSON_QX_OPTION_BUS, bus::epson_qx, option_bus_device)
+
+#endif // MAME_BUS_EPSON_QX_OPTION_H
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..61d1a8a4ed1
--- /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_SOUND_CARD_H
+#define MAME_BUS_EPSON_QX_SOUND_CARD_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 ATTR_COLD;
+ virtual void device_reset() override ATTR_COLD;
+
+ // optional information overrides
+ virtual void device_add_mconfig(machine_config &config) override ATTR_COLD;
+ virtual ioport_constructor device_input_ports() const override ATTR_COLD;
+
+ void map(address_map &map) ATTR_COLD;
+
+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_SOUND_CARD_H
diff --git a/src/devices/bus/epson_sio/epson_sio.cpp b/src/devices/bus/epson_sio/epson_sio.cpp
index 32a572bb45d..926c1080ec2 100644
--- a/src/devices/bus/epson_sio/epson_sio.cpp
+++ b/src/devices/bus/epson_sio/epson_sio.cpp
@@ -30,7 +30,7 @@ DEFINE_DEVICE_TYPE(EPSON_SIO, epson_sio_device, "epson_sio", "EPSON SIO port")
//-------------------------------------------------
device_epson_sio_interface::device_epson_sio_interface(const machine_config &mconfig, device_t &device) :
- device_slot_card_interface(mconfig, device)
+ device_interface(device, "epsonsio")
{
m_slot = dynamic_cast<epson_sio_device *>(device.owner());
}
@@ -55,7 +55,7 @@ device_epson_sio_interface::~device_epson_sio_interface()
epson_sio_device::epson_sio_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) :
device_t(mconfig, EPSON_SIO, tag, owner, clock),
- device_slot_interface(mconfig, *this),
+ device_single_card_slot_interface<device_epson_sio_interface>(mconfig, *this),
m_cart(nullptr),
m_write_rx(*this),
m_write_pin(*this)
@@ -78,29 +78,17 @@ epson_sio_device::~epson_sio_device()
void epson_sio_device::device_start()
{
- m_cart = dynamic_cast<device_epson_sio_interface *>(get_card_device());
-
- m_write_rx.resolve_safe();
- m_write_pin.resolve_safe();
-}
-
-
-//-------------------------------------------------
-// device_reset - device-specific reset
-//-------------------------------------------------
-
-void epson_sio_device::device_reset()
-{
+ m_cart = get_card_device();
}
-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 5d93c42ba74..c8d9e9ba06a 100644
--- a/src/devices/bus/epson_sio/epson_sio.h
+++ b/src/devices/bus/epson_sio/epson_sio.h
@@ -21,8 +21,7 @@ class device_epson_sio_interface;
// supported devices
void epson_sio_devices(device_slot_interface &device);
-class epson_sio_device : public device_t,
- public device_slot_interface
+class epson_sio_device : public device_t, public device_single_card_slot_interface<device_epson_sio_interface>
{
public:
// construction/destruction
@@ -43,17 +42,16 @@ 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
- virtual void device_start() override;
- virtual void device_reset() override;
+ virtual void device_start() override ATTR_COLD;
device_epson_sio_interface *m_cart;
@@ -64,14 +62,14 @@ private:
// class representing interface-specific live sio device
-class device_epson_sio_interface : public device_slot_card_interface
+class device_epson_sio_interface : public device_interface
{
public:
// construction/destruction
virtual ~device_epson_sio_interface();
- virtual void tx_w(int state) { };
- virtual void pout_w(int state) { };
+ virtual void tx_w(int state) { }
+ virtual void pout_w(int state) { }
protected:
device_epson_sio_interface(const machine_config &mconfig, device_t &device);
diff --git a/src/devices/bus/epson_sio/pf10.cpp b/src/devices/bus/epson_sio/pf10.cpp
index f986bb5d4c2..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).rw("maincpu", FUNC(hd6303y_cpu_device::m6801_io_r), FUNC(hd6303y_cpu_device::m6801_io_w));
- 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));
@@ -71,7 +69,7 @@ void epson_pf10_device::device_add_mconfig(machine_config &config)
m_cpu->out_ser_tx_cb().set(FUNC(epson_pf10_device::hd6303_tx_w));
UPD765A(config, m_fdc, 4'000'000, false, true);
- FLOPPY_CONNECTOR(config, m_floppy, pf10_floppies, "smd165", floppy_image_device::default_floppy_formats);
+ FLOPPY_CONNECTOR(config, m_floppy, pf10_floppies, "smd165", floppy_image_device::default_mfm_floppy_formats);
EPSON_SIO(config, m_sio_output, nullptr);
m_sio_output->rx_callback().set(DEVICE_SELF, FUNC(epson_pf10_device::rxc_w));
@@ -109,7 +107,7 @@ epson_pf10_device::epson_pf10_device(const machine_config &mconfig, const char *
void epson_pf10_device::device_start()
{
- m_timer = timer_alloc(0, nullptr);
+ m_timer = timer_alloc(FUNC(epson_pf10_device::serial_clk_tick), this);
}
//-------------------------------------------------
@@ -118,21 +116,17 @@ void epson_pf10_device::device_start()
void epson_pf10_device::device_reset()
{
- m_timer->adjust(attotime::zero, 0, attotime::from_hz(38400 * 8));
+ m_timer->adjust(attotime::zero, 0, attotime::from_hz(38400 * 16));
}
//-------------------------------------------------
-// device_timer - handler timer events
+// serial_clk_tick - tick the CPU's external
+// serial clock
//-------------------------------------------------
-void epson_pf10_device::device_timer(emu_timer &timer, device_timer_id id, int param, void *ptr)
+TIMER_CALLBACK_MEMBER( epson_pf10_device::serial_clk_tick )
{
- switch (id)
- {
- case 0:
- m_cpu->m6801_clock_serial();
- break;
- }
+ m_cpu->clock_serial();
}
@@ -140,42 +134,42 @@ void epson_pf10_device::device_timer(emu_timer &timer, device_timer_id id, int p
// CPU
//**************************************************************************
-READ8_MEMBER( epson_pf10_device::port1_r )
+uint8_t epson_pf10_device::port1_r()
{
logerror("%s: port1_r(%02x)\n", tag(), m_port1);
return m_port1;
}
-WRITE8_MEMBER( epson_pf10_device::port1_w )
+void epson_pf10_device::port1_w(uint8_t data)
{
logerror("%s: port1_w(%02x)\n", tag(), data);
}
-READ8_MEMBER( epson_pf10_device::port2_r )
+uint8_t epson_pf10_device::port2_r()
{
logerror("%s: port2_r(%02x)\n", tag(), m_port2);
return m_port2;
}
-WRITE8_MEMBER( epson_pf10_device::port2_w )
+void epson_pf10_device::port2_w(uint8_t data)
{
if (m_floppy->get_device() != nullptr)
m_floppy->get_device()->mon_w(data & PORT2_MON);
logerror("%s: port2_w(%02x)\n", tag(), data);
}
-READ8_MEMBER( epson_pf10_device::fdc_r )
+uint8_t epson_pf10_device::fdc_r(offs_t offset)
{
logerror("%s: fdc_r @ %04x\n", tag(), offset);
return 0xff;
}
-WRITE8_MEMBER( epson_pf10_device::fdc_w )
+void epson_pf10_device::fdc_w(offs_t offset, uint8_t data)
{
logerror("%s: fdc_w @ %04x (%02x)\n", tag(), offset, data);
}
-WRITE8_MEMBER( epson_pf10_device::fdc_tc_w )
+void epson_pf10_device::fdc_tc_w(uint8_t data)
{
logerror("%s: fdc_tc_w(%02x)\n", tag(), data);
}
@@ -189,7 +183,7 @@ WRITE8_MEMBER( epson_pf10_device::fdc_tc_w )
// 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);
@@ -199,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);
@@ -209,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 7f305bed8c9..6cf8ec5eb1b 100644
--- a/src/devices/bus/epson_sio/pf10.h
+++ b/src/devices/bus/epson_sio/pf10.h
@@ -32,13 +32,12 @@ public:
protected:
// device-level overrides
- virtual void device_start() override;
- virtual void device_reset() override;
- virtual void device_timer(emu_timer &timer, device_timer_id id, int param, void *ptr) override;
+ virtual void device_start() override ATTR_COLD;
+ virtual void device_reset() override ATTR_COLD;
// optional information overrides
- virtual const tiny_rom_entry *device_rom_region() const override;
- virtual void device_add_mconfig(machine_config &config) override;
+ virtual const tiny_rom_entry *device_rom_region() const override ATTR_COLD;
+ virtual void device_add_mconfig(machine_config &config) override ATTR_COLD;
// device_epson_sio_interface overrides
virtual void tx_w(int level) override;
@@ -46,26 +45,28 @@ 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
- DECLARE_READ8_MEMBER( fdc_r );
- DECLARE_WRITE8_MEMBER( fdc_w );
- DECLARE_WRITE8_MEMBER( fdc_tc_w );
+ uint8_t fdc_r(offs_t offset);
+ void fdc_w(offs_t offset, uint8_t data);
+ void fdc_tc_w(uint8_t data);
// hd6303 i/o
- DECLARE_READ8_MEMBER( port1_r );
- DECLARE_WRITE8_MEMBER( port1_w );
- DECLARE_READ8_MEMBER( port2_r );
- DECLARE_WRITE8_MEMBER( port2_w );
+ uint8_t port1_r();
+ void port1_w(uint8_t data);
+ uint8_t port2_r();
+ void port2_w(uint8_t data);
- void cpu_mem(address_map &map);
+ TIMER_CALLBACK_MEMBER( serial_clk_tick );
- required_device<hd6303y_cpu_device> m_cpu;
+ void cpu_mem(address_map &map) ATTR_COLD;
+
+ 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 1fb12a66c0e..6b3f207561e 100644
--- a/src/devices/bus/epson_sio/tf20.cpp
+++ b/src/devices/bus/epson_sio/tf20.cpp
@@ -41,7 +41,7 @@ void epson_tf20_device::cpu_io(address_map &map)
map.global_mask(0xff);
map(0xf0, 0xf3).rw(m_mpsc, FUNC(upd7201_device::ba_cd_r), FUNC(upd7201_device::ba_cd_w));
map(0xf6, 0xf6).r(FUNC(epson_tf20_device::rom_disable_r));
- map(0xf7, 0xf7).portr("tf20_dip");
+ map(0xf7, 0xf7).portr(m_tf20_dip);
map(0xf8, 0xf8).rw(FUNC(epson_tf20_device::upd765_tc_r), FUNC(epson_tf20_device::fdc_control_w));
map(0xfa, 0xfb).m("5a", FUNC(upd765a_device::map));
}
@@ -107,7 +107,7 @@ void epson_tf20_device::device_add_mconfig(machine_config &config)
// floppy drives
for (auto &fd : m_fd)
- FLOPPY_CONNECTOR(config, fd, tf20_floppies, "sd320", floppy_image_device::default_floppy_formats);
+ FLOPPY_CONNECTOR(config, fd, tf20_floppies, "sd320", floppy_image_device::default_mfm_floppy_formats);
// serial interface to another device
EPSON_SIO(config, m_sio_output, nullptr);
@@ -133,6 +133,7 @@ epson_tf20_device::epson_tf20_device(const machine_config &mconfig, const char *
m_mpsc(*this, "3a"),
m_sio_output(*this, "sio"),
m_fd(*this, "5a:%u", 0U),
+ m_tf20_dip(*this, "tf20_dip"),
m_timer_serial(nullptr), m_timer_tc(nullptr),
m_rxc(1), m_txda(0), m_dtra(0), m_pinc(0)
{
@@ -149,8 +150,8 @@ void epson_tf20_device::device_start()
if (!m_ram->started())
throw device_missing_dependencies();
- m_timer_serial = timer_alloc(0, nullptr);
- m_timer_tc = timer_alloc(1, nullptr);
+ m_timer_serial = timer_alloc(FUNC(epson_tf20_device::serial_tick), this);
+ m_timer_tc = timer_alloc(FUNC(epson_tf20_device::tc_tick), this);
// enable second half of ram
m_cpu->space(AS_PROGRAM).install_ram(0x8000, 0xffff, m_ram->pointer() + 0x8000);
@@ -175,31 +176,32 @@ void epson_tf20_device::device_reset()
}
//-------------------------------------------------
-// device_timer - handler timer events
+// serial_tick - update serial clocks
//-------------------------------------------------
-void epson_tf20_device::device_timer(emu_timer &timer, device_timer_id id, int param, void *ptr)
+TIMER_CALLBACK_MEMBER( epson_tf20_device::serial_tick )
{
- switch (id)
- {
- case 0:
- m_mpsc->rxca_w(1);
- m_mpsc->rxca_w(0);
- m_mpsc->txca_w(1);
- m_mpsc->txca_w(0);
- m_mpsc->rxcb_w(1);
- m_mpsc->rxcb_w(0);
- m_mpsc->txcb_w(1);
- m_mpsc->txcb_w(0);
- break;
-
- case 1:
- logerror("%s: tc off\n", tag());
- m_fdc->tc_w(false);
- break;
- }
+ m_mpsc->rxca_w(1);
+ m_mpsc->rxca_w(0);
+ m_mpsc->txca_w(1);
+ m_mpsc->txca_w(0);
+ m_mpsc->rxcb_w(1);
+ m_mpsc->rxcb_w(0);
+ m_mpsc->txcb_w(1);
+ m_mpsc->txcb_w(0);
}
+//-------------------------------------------------
+// tc_tick - update the FDC terminal count flag
+//-------------------------------------------------
+
+TIMER_CALLBACK_MEMBER( epson_tf20_device::tc_tick )
+{
+ logerror("%s: tc off\n", tag());
+ m_fdc->tc_w(false);
+}
+
+
//**************************************************************************
// CPU & MEMORY
@@ -215,7 +217,7 @@ IRQ_CALLBACK_MEMBER( epson_tf20_device::irq_callback )
}
// a read from this location disables the rom
-READ8_MEMBER( epson_tf20_device::rom_disable_r )
+uint8_t epson_tf20_device::rom_disable_r()
{
// switch in ram
m_cpu->space(AS_PROGRAM).install_ram(0x0000, 0x7fff, m_ram->pointer());
@@ -231,7 +233,7 @@ READ8_MEMBER( epson_tf20_device::rom_disable_r )
// fdc interrupt
//-------------------------------------------------
-READ8_MEMBER( epson_tf20_device::upd765_tc_r )
+uint8_t epson_tf20_device::upd765_tc_r()
{
logerror("%s: upd765_tc_r\n", machine().describe_context());
@@ -242,7 +244,7 @@ READ8_MEMBER( epson_tf20_device::upd765_tc_r )
return 0xff;
}
-WRITE8_MEMBER( epson_tf20_device::fdc_control_w )
+void epson_tf20_device::fdc_control_w(uint8_t data)
{
logerror("%s: tf20_fdc_control_w(%02x)\n", machine().describe_context(), data);
@@ -261,7 +263,7 @@ WRITE8_MEMBER( epson_tf20_device::fdc_control_w )
// 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);
@@ -271,7 +273,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);
@@ -281,7 +283,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);
@@ -291,7 +293,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 236cd2e9059..407c0ac2d8c 100644
--- a/src/devices/bus/epson_sio/tf20.h
+++ b/src/devices/bus/epson_sio/tf20.h
@@ -18,7 +18,7 @@
#include "imagedev/floppy.h"
#include "machine/ram.h"
#include "machine/upd765.h"
-#include "machine/z80dart.h"
+#include "machine/z80sio.h"
//**************************************************************************
@@ -34,14 +34,13 @@ public:
protected:
// device-level overrides
- virtual void device_start() override;
- virtual void device_reset() override;
- virtual void device_timer(emu_timer &timer, device_timer_id id, int param, void *ptr) override;
+ virtual void device_start() override ATTR_COLD;
+ virtual void device_reset() override ATTR_COLD;
// optional information 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 const tiny_rom_entry *device_rom_region() const override ATTR_COLD;
+ virtual void device_add_mconfig(machine_config &config) override ATTR_COLD;
+ virtual ioport_constructor device_input_ports() const override ATTR_COLD;
// device_epson_sio_interface overrides
virtual void tx_w(int level) override;
@@ -49,19 +48,22 @@ 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);
- DECLARE_READ8_MEMBER( rom_disable_r );
- DECLARE_READ8_MEMBER( upd765_tc_r );
- DECLARE_WRITE8_MEMBER( fdc_control_w );
+ uint8_t rom_disable_r();
+ uint8_t upd765_tc_r();
+ void fdc_control_w(uint8_t data);
- void cpu_io(address_map &map);
- void cpu_mem(address_map &map);
+ TIMER_CALLBACK_MEMBER( serial_tick );
+ TIMER_CALLBACK_MEMBER( tc_tick );
+
+ void cpu_io(address_map &map) ATTR_COLD;
+ void cpu_mem(address_map &map) ATTR_COLD;
required_device<cpu_device> m_cpu;
required_device<ram_device> m_ram;
@@ -69,6 +71,7 @@ private:
required_device<upd7201_device> m_mpsc;
required_device<epson_sio_device> m_sio_output;
required_device_array<floppy_connector, 2> m_fd;
+ required_ioport m_tf20_dip;
emu_timer *m_timer_serial;
emu_timer *m_timer_tc;
diff --git a/src/devices/bus/fmt_scsi/fmt121.cpp b/src/devices/bus/fmt_scsi/fmt121.cpp
new file mode 100644
index 00000000000..34f784115a0
--- /dev/null
+++ b/src/devices/bus/fmt_scsi/fmt121.cpp
@@ -0,0 +1,150 @@
+// license:BSD-3-Clause
+// copyright-holders:r09
+/****************************************************************************
+
+ Fujitsu FMT-121 SCSI Card
+
+ An expansion card for the dedicated SCSI card slot on the FM Towns
+ Model 1 and 2 computers. It contains a Fujitsu MB673522U SCSI controller
+ and an external 50-pin Centronics connector.
+
+ |||||||||||||||||||||
++-------------------------| |-------------------------+
+| CN1 +-------------------+ |
+| |
+| 74LS04N |
+| 74LS14N 74LS240N SN74LS06N |
+| MB413 |
+| MB463 |
+| 74AS00N |
+| +-----------+ |
+| MB463 | | |
+| | MB673522U | MB412 |
+| +-----------+ |
+| MB463 74LS240N |
+| CN3 |
+| .......................................... |
+| . . |
+| .......................................... |
+| CN2 |
+| +----------------------------------------+ |
+| | | |
++--------------| |---------------+
+ ||||||||||||||||||||||||||||||||||||||||||
+
+ CN1: 30-pin MFC-30LFD DIP connector
+ CN2: 50-pin Centronics connector
+ CN3: solder pads for internal 50-pin connector (not present)
+
+****************************************************************************/
+
+#include "emu.h"
+#include "fmt121.h"
+
+#include "bus/scsi/scsi.h"
+#include "bus/scsi/scsihd.h"
+
+//**************************************************************************
+// GLOBAL VARIABLES
+//**************************************************************************
+
+// device type definition
+DEFINE_DEVICE_TYPE(FMT121, fmt121_device, "fmt121", "FMT-121 SCSI Card")
+
+//**************************************************************************
+// DEVICE DEFINITION
+//**************************************************************************
+
+//-------------------------------------------------
+// fmt121_device - construction
+//-------------------------------------------------
+
+fmt121_device::fmt121_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock)
+ : device_t(mconfig, FMT121, tag, owner, clock)
+ , fmt_scsi_card_interface(mconfig, *this)
+ , m_scsi_ctlr(*this, "fmscsi")
+{
+}
+
+
+//-------------------------------------------------
+// device_add_mconfig - add device-specific
+// machine configuration
+//-------------------------------------------------
+
+void fmt121_device::device_add_mconfig(machine_config &config)
+{
+ scsi_port_device &scsi(SCSI_PORT(config, "scsi", 0));
+ scsi.set_slot_device(1, "harddisk", SCSIHD, DEVICE_INPUT_DEFAULTS_NAME(SCSI_ID_0));
+ scsi.set_slot_device(2, "harddisk", SCSIHD, DEVICE_INPUT_DEFAULTS_NAME(SCSI_ID_1));
+ scsi.set_slot_device(3, "harddisk", SCSIHD, DEVICE_INPUT_DEFAULTS_NAME(SCSI_ID_2));
+ scsi.set_slot_device(4, "harddisk", SCSIHD, DEVICE_INPUT_DEFAULTS_NAME(SCSI_ID_3));
+ scsi.set_slot_device(5, "harddisk", SCSIHD, DEVICE_INPUT_DEFAULTS_NAME(SCSI_ID_4));
+
+ FMSCSI(config, m_scsi_ctlr, 0);
+ m_scsi_ctlr->set_scsi_port("scsi");
+ m_scsi_ctlr->irq_handler().set(FUNC(fmt121_device::irq_w));
+ m_scsi_ctlr->drq_handler().set(FUNC(fmt121_device::drq_w));
+}
+
+
+//-------------------------------------------------
+// device_start - device-specific startup
+//-------------------------------------------------
+
+void fmt121_device::device_start()
+{
+}
+
+//**************************************************************************
+// FMT121 INTERFACE
+//**************************************************************************
+
+//-------------------------------------------------
+// fmt_scsi_read - I/O read access
+//-------------------------------------------------
+
+u8 fmt121_device::fmt_scsi_read(offs_t offset)
+{
+ return m_scsi_ctlr->fmscsi_r(offset);
+}
+
+
+//-------------------------------------------------
+// fmt_scsi_write - I/O write access
+//-------------------------------------------------
+
+void fmt121_device::fmt_scsi_write(offs_t offset, u8 data)
+{
+ m_scsi_ctlr->fmscsi_w(offset, data);
+}
+
+//-------------------------------------------------
+// fmt_scsi_data_read - data read access
+//-------------------------------------------------
+
+u8 fmt121_device::fmt_scsi_data_read()
+{
+ return m_scsi_ctlr->fmscsi_data_r();
+}
+
+//-------------------------------------------------
+// fmt_scsi_data_write - data write access
+//-------------------------------------------------
+
+void fmt121_device::fmt_scsi_data_write(u8 data)
+{
+ m_scsi_ctlr->fmscsi_data_w(data);
+}
+
+
+void fmt121_device::irq_w(int state)
+{
+ m_slot->irq_w(state);
+}
+
+
+void fmt121_device::drq_w(int state)
+{
+ m_slot->drq_w(state);
+}
diff --git a/src/devices/bus/fmt_scsi/fmt121.h b/src/devices/bus/fmt_scsi/fmt121.h
new file mode 100644
index 00000000000..bf8ddd07876
--- /dev/null
+++ b/src/devices/bus/fmt_scsi/fmt121.h
@@ -0,0 +1,50 @@
+// license:BSD-3-Clause
+// copyright-holders:r09
+
+#ifndef MAME_BUS_FMT_SCSI_FMT121_H
+#define MAME_BUS_FMT_SCSI_FMT121_H
+
+#pragma once
+
+#include "fmt_scsi.h"
+
+#include "machine/fm_scsi.h"
+
+
+//**************************************************************************
+// TYPE DEFINITIONS
+//**************************************************************************
+
+// ======================> fmt121_device
+
+class fmt121_device : public device_t, public fmt_scsi_card_interface
+{
+public:
+ // device type constructor
+ fmt121_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock);
+
+protected:
+ // device-level overrides
+ virtual void device_add_mconfig(machine_config &config) override ATTR_COLD;
+ virtual void device_start() override ATTR_COLD;
+
+ // fmt_scsi_card_interface overrides
+ virtual u8 fmt_scsi_read(offs_t offset) override;
+ virtual void fmt_scsi_write(offs_t offset, u8 data) override;
+
+ virtual u8 fmt_scsi_data_read(void) override;
+ virtual void fmt_scsi_data_write(u8 data) override;
+
+private:
+
+ required_device<fmscsi_device> m_scsi_ctlr;
+
+ void irq_w(int state);
+ void drq_w(int state);
+
+};
+
+// device type declaration
+DECLARE_DEVICE_TYPE(FMT121, fmt121_device)
+
+#endif // MAME_BUS_FMT_SCSI_FMT121_H
diff --git a/src/devices/bus/fmt_scsi/fmt_scsi.cpp b/src/devices/bus/fmt_scsi/fmt_scsi.cpp
new file mode 100644
index 00000000000..ccdab14f57e
--- /dev/null
+++ b/src/devices/bus/fmt_scsi/fmt_scsi.cpp
@@ -0,0 +1,156 @@
+// license:BSD-3-Clause
+// copyright-holders:r09
+/****************************************************************************
+
+ Fujitsu FM Towns SCSI card slot
+
+ This is a dedicated 30-pin slot for the FMT-121 SCSI Card. It is only
+ present on the Model 1 and 2; all later models integrate the SCSI
+ controller directly on the motherboard.
+
+****************************************************************************/
+
+#include "emu.h"
+#include "fmt_scsi.h"
+
+#include "fmt121.h"
+
+//**************************************************************************
+// GLOBAL VARIABLES
+//**************************************************************************
+
+// device type definition
+DEFINE_DEVICE_TYPE(FMT_SCSI_SLOT, fmt_scsi_slot_device, "fmt_scsi_slot", "FM Towns SCSI card slot")
+
+//**************************************************************************
+// FMT_SCSI SLOT DEVICE
+//**************************************************************************
+
+//-------------------------------------------------
+// fmt_scsi_slot_device - construction
+//-------------------------------------------------
+
+fmt_scsi_slot_device::fmt_scsi_slot_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock)
+ : device_t(mconfig, FMT_SCSI_SLOT, tag, owner, clock)
+ , device_single_card_slot_interface<fmt_scsi_card_interface>(mconfig, *this)
+ , m_card(nullptr)
+ , m_irq_handler(*this)
+ , m_drq_handler(*this)
+{
+}
+
+
+//-------------------------------------------------
+// device_resolve_objects - resolve objects that
+// may be needed for other devices to set
+// initial conditions at start time
+//-------------------------------------------------
+
+void fmt_scsi_slot_device::device_resolve_objects()
+{
+ m_card = get_card_device();
+ if (m_card != nullptr)
+ m_card->m_slot = this;
+}
+
+
+//-------------------------------------------------
+// device_start - device-specific startup
+//-------------------------------------------------
+
+void fmt_scsi_slot_device::device_start()
+{
+}
+
+
+//-------------------------------------------------
+// read - I/O read access
+//-------------------------------------------------
+
+u8 fmt_scsi_slot_device::read(address_space &space, offs_t offset)
+{
+ if (m_card)
+ return m_card->fmt_scsi_read(offset);
+ else
+ return space.unmap();
+}
+
+
+//-------------------------------------------------
+// write - I/O write access
+//-------------------------------------------------
+
+void fmt_scsi_slot_device::write(offs_t offset, u8 data)
+{
+ if (m_card)
+ m_card->fmt_scsi_write(offset, data);
+}
+
+//-------------------------------------------------
+// data_read - data read access
+//-------------------------------------------------
+
+u8 fmt_scsi_slot_device::data_read()
+{
+ if (m_card)
+ return m_card->fmt_scsi_data_read();
+ else
+ return 0;
+}
+
+//-------------------------------------------------
+// data_write - data write access
+//-------------------------------------------------
+
+void fmt_scsi_slot_device::data_write(u8 data)
+{
+ if (m_card)
+ m_card->fmt_scsi_data_write(data);
+}
+
+void fmt_scsi_slot_device::irq_w(int state)
+{
+ m_irq_handler(state);
+}
+
+void fmt_scsi_slot_device::drq_w(int state)
+{
+ m_drq_handler(state);
+}
+
+//**************************************************************************
+// FMT_SCSI CARD INTERFACE
+//**************************************************************************
+
+//-------------------------------------------------
+// fmt_scsi_card_interface - construction
+//-------------------------------------------------
+
+fmt_scsi_card_interface::fmt_scsi_card_interface(const machine_config &mconfig, device_t &device)
+ : device_interface(device, "fmtscsicard")
+ , m_slot(nullptr)
+{
+}
+
+
+//-------------------------------------------------
+// interface_pre_start - called before the
+// device's own start function
+//-------------------------------------------------
+
+void fmt_scsi_card_interface::interface_pre_start()
+{
+ if (!m_slot)
+ throw device_missing_dependencies();
+}
+
+
+//-------------------------------------------------
+// fmt_scsi_default_devices - add standard options
+// for main slots
+//-------------------------------------------------
+
+void fmt_scsi_default_devices(device_slot_interface &device)
+{
+ device.option_add("fmt121", FMT121);
+}
diff --git a/src/devices/bus/fmt_scsi/fmt_scsi.h b/src/devices/bus/fmt_scsi/fmt_scsi.h
new file mode 100644
index 00000000000..80cbaa735e3
--- /dev/null
+++ b/src/devices/bus/fmt_scsi/fmt_scsi.h
@@ -0,0 +1,98 @@
+// license:BSD-3-Clause
+// copyright-holders:r09
+/**********************************************************************
+
+ Fujitsu FM Towns SCSI card slot
+
+**********************************************************************/
+
+#ifndef MAME_BUS_FMT_SCSI_FMT_SCSI_H
+#define MAME_BUS_FMT_SCSI_FMT_SCSI_H
+
+#pragma once
+
+
+//**************************************************************************
+// TYPE DEFINITIONS
+//**************************************************************************
+
+// forward declarations
+class fmt_scsi_card_interface;
+
+// ======================> fmt_scsi_slot_device
+
+class fmt_scsi_slot_device : public device_t, public device_single_card_slot_interface<fmt_scsi_card_interface>
+{
+ friend class fmt_scsi_card_interface;
+
+public:
+ // construction/destruction
+ template <typename T>
+ fmt_scsi_slot_device(machine_config const &mconfig, char const *tag, device_t *owner, T &&opts, char const *dflt)
+ : fmt_scsi_slot_device(mconfig, tag, owner, 0)
+ {
+ option_reset();
+ opts(*this);
+ set_default_option(dflt);
+ set_fixed(false);
+ }
+
+ fmt_scsi_slot_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock = 0);
+
+ auto irq_handler() { return m_irq_handler.bind(); }
+ auto drq_handler() { return m_drq_handler.bind(); }
+
+ u8 read(address_space &space, offs_t offset);
+ void write(offs_t offset, u8 data);
+
+ uint8_t data_read(void);
+ void data_write(uint8_t data);
+
+ void irq_w(int state);
+ void drq_w(int state);
+
+protected:
+ // device-specific overrides
+ virtual void device_resolve_objects() override ATTR_COLD;
+ virtual void device_start() override ATTR_COLD;
+
+private:
+ fmt_scsi_card_interface *m_card;
+
+ devcb_write_line m_irq_handler;
+ devcb_write_line m_drq_handler;
+
+};
+
+
+// ======================> fmt_scsi_card_interface
+
+class fmt_scsi_card_interface : public device_interface
+{
+ friend class fmt_scsi_slot_device;
+
+protected:
+ // construction/destruction
+ fmt_scsi_card_interface(const machine_config &mconfig, device_t &device);
+
+ // required overrides
+ virtual u8 fmt_scsi_read(offs_t offset) = 0;
+ virtual void fmt_scsi_write(offs_t offset, u8 data) = 0;
+
+ virtual u8 fmt_scsi_data_read(void) = 0;
+ virtual void fmt_scsi_data_write(u8 data) = 0;
+
+ fmt_scsi_slot_device *m_slot;
+
+private:
+ virtual void interface_pre_start() override;
+
+};
+
+
+// device type definition
+DECLARE_DEVICE_TYPE(FMT_SCSI_SLOT, fmt_scsi_slot_device)
+
+void fmt_scsi_default_devices(device_slot_interface &device);
+
+#endif // MAME_BUS_FMT_SCSI_FMT_SCSI_H
diff --git a/src/devices/bus/fp1000/fp1000_exp.cpp b/src/devices/bus/fp1000/fp1000_exp.cpp
new file mode 100644
index 00000000000..40233a9d215
--- /dev/null
+++ b/src/devices/bus/fp1000/fp1000_exp.cpp
@@ -0,0 +1,114 @@
+// license:BSD-3-Clause
+// copyright-holders:Angelo Salese
+
+#include "emu.h"
+#include "fp1000_exp.h"
+
+#define VERBOSE 1
+//#define LOG_OUTPUT_FUNC osd_printf_info
+#include "logmacro.h"
+
+DEFINE_DEVICE_TYPE(FP1000_EXP_SLOT, fp1000_exp_slot_device, "fp1000_exp_slot", "FP-1000/FP-1100 Expansion Slot")
+
+fp1000_exp_slot_device::fp1000_exp_slot_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
+ : device_t(mconfig, FP1000_EXP_SLOT, tag, owner, clock)
+ , device_single_card_slot_interface<device_fp1000_exp_interface>(mconfig, *this)
+ , m_iospace(*this, finder_base::DUMMY_TAG, -1)
+ , m_inta_cb(*this)
+ , m_intb_cb(*this)
+ , m_intc_cb(*this)
+ , m_intd_cb(*this)
+{
+}
+
+fp1000_exp_slot_device::~fp1000_exp_slot_device()
+{
+}
+
+void fp1000_exp_slot_device::device_start()
+{
+}
+
+void fp1000_exp_slot_device::device_config_complete()
+{
+ m_dev = get_card_device();
+}
+
+void fp1000_exp_slot_device::remap_cb()
+{
+ if (!m_main_enable || m_dev == nullptr)
+ {
+ LOG("%s: unmap\n", machine().describe_context());
+ m_iospace->unmap_readwrite(0x0000, 0xfeff);
+ m_iospace->unmap_readwrite(0xff00, 0xff7f);
+ }
+ else
+ {
+ LOG("%s: map\n", machine().describe_context());
+ m_iospace->install_readwrite_handler(0xff00, 0xff7f, read8sm_delegate(*m_dev, FUNC(device_fp1000_exp_interface::id_r)), write8sm_delegate(*this, FUNC(fp1000_exp_slot_device::main_cs_w)));
+ m_dev->remap_cb();
+ }
+}
+
+void fp1000_exp_slot_device::select_w(bool enable)
+{
+ m_main_enable = enable;
+ remap_cb();
+}
+
+void fp1000_exp_slot_device::main_cs_w(offs_t offset, u8 data)
+{
+ m_dev->cs_w(offset, data);
+ m_dev->remap_cb();
+}
+
+
+
+device_fp1000_exp_interface::device_fp1000_exp_interface(const machine_config &mconfig, device_t &device)
+ : device_interface(device, "fp1000exp")
+{
+ m_slot = dynamic_cast<fp1000_exp_slot_device *>(device.owner());
+}
+
+device_fp1000_exp_interface::~device_fp1000_exp_interface()
+{
+}
+
+void device_fp1000_exp_interface::interface_pre_start()
+{
+ if (!m_slot->started())
+ throw device_missing_dependencies();
+}
+
+void device_fp1000_exp_interface::interface_post_start()
+{
+ m_slot->select_w(false);
+}
+
+// generic passthroughs
+void device_fp1000_exp_interface::inta_w(int state) { m_slot->m_inta_cb(state); }
+void device_fp1000_exp_interface::intb_w(int state) { m_slot->m_intb_cb(state); }
+void device_fp1000_exp_interface::intc_w(int state) { m_slot->m_intc_cb(state); }
+void device_fp1000_exp_interface::intd_w(int state) { m_slot->m_intd_cb(state); }
+
+
+fp1000_exp_device::fp1000_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)
+ , device_fp1000_exp_interface(mconfig, *this)
+{
+}
+
+void fp1000_exp_device::device_start()
+{
+
+}
+
+
+// slot devices
+#include "fp1060io.h"
+
+void fp1000_exp_devices(device_slot_interface &device)
+{
+ device.option_add("fp1060io", FP1060IO);
+ // TODO: other options, if any
+}
diff --git a/src/devices/bus/fp1000/fp1000_exp.h b/src/devices/bus/fp1000/fp1000_exp.h
new file mode 100644
index 00000000000..4faca42d4f2
--- /dev/null
+++ b/src/devices/bus/fp1000/fp1000_exp.h
@@ -0,0 +1,101 @@
+// license:BSD-3-Clause
+// copyright-holders:Angelo Salese
+
+#ifndef MAME_BUS_FP1000_FP1000_EXP_H
+#define MAME_BUS_FP1000_FP1000_EXP_H
+
+#pragma once
+
+class device_fp1000_exp_interface;
+class fp1000_exp_device;
+
+class fp1000_exp_slot_device : public device_t, public device_single_card_slot_interface<device_fp1000_exp_interface>
+{
+ friend class device_fp1000_exp_interface;
+public:
+ // construction/destruction
+ template <typename T>
+ fp1000_exp_slot_device(machine_config const &mconfig, char const *tag, device_t *owner, T &&opts, char const *dflt)
+ : fp1000_exp_slot_device(mconfig, tag, owner, (uint32_t)0)
+ {
+ option_reset();
+ opts(*this);
+ set_default_option(dflt);
+ set_fixed(false);
+ }
+ fp1000_exp_slot_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
+ virtual ~fp1000_exp_slot_device();
+
+ template <typename T> void set_iospace(T &&tag, int spacenum) { m_iospace.set_tag(std::forward<T>(tag), spacenum); }
+
+ address_space &iospace() const { return *m_iospace; }
+
+ void select_w(bool enable);
+
+ auto inta_callback() { return m_inta_cb.bind(); }
+ auto intb_callback() { return m_intb_cb.bind(); }
+ auto intc_callback() { return m_intc_cb.bind(); }
+ auto intd_callback() { return m_intd_cb.bind(); }
+
+protected:
+ virtual void device_start() override ATTR_COLD;
+ virtual void device_config_complete() override;
+
+private:
+ required_address_space m_iospace;
+
+ void remap_cb();
+ void main_cs_w(offs_t offset, u8 data);
+
+ bool m_main_enable = false;
+ device_fp1000_exp_interface *m_dev;
+
+ devcb_write_line m_inta_cb;
+ devcb_write_line m_intb_cb;
+ devcb_write_line m_intc_cb;
+ devcb_write_line m_intd_cb;
+};
+
+class device_fp1000_exp_interface : public device_interface
+{
+public:
+ // construction/destruction
+ virtual ~device_fp1000_exp_interface();
+
+ virtual void cs_w(offs_t offset, u8 data) = 0;
+ virtual u8 id_r(offs_t offset) = 0;
+ virtual void remap_cb() = 0;
+
+
+protected:
+ device_fp1000_exp_interface(const machine_config &mconfig, device_t &device);
+
+ virtual void interface_pre_start() override;
+ virtual void interface_post_start() override;
+
+ fp1000_exp_slot_device *m_slot;
+
+ void inta_w(int state);
+ void intb_w(int state);
+ void intc_w(int state);
+ void intd_w(int state);
+};
+
+class fp1000_exp_device : public device_t, public device_fp1000_exp_interface
+{
+public:
+ // construction/destruction
+ fp1000_exp_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock);
+
+
+protected:
+// virtual void device_add_mconfig(machine_config &config) override ATTR_COLD;
+ virtual void device_start() override ATTR_COLD;
+};
+
+// device type definition
+DECLARE_DEVICE_TYPE(FP1000_EXP_SLOT, fp1000_exp_slot_device)
+
+void fp1000_exp_devices(device_slot_interface &device);
+
+#endif // MAME_BUS_FP1000_FP1000_EXP_H
diff --git a/src/devices/bus/fp1000/fp1020fd.cpp b/src/devices/bus/fp1000/fp1020fd.cpp
new file mode 100644
index 00000000000..1907de05a05
--- /dev/null
+++ b/src/devices/bus/fp1000/fp1020fd.cpp
@@ -0,0 +1,94 @@
+// license:BSD-3-Clause
+// copyright-holders:Angelo Salese
+
+#include "emu.h"
+#include "fp1020fd.h"
+
+#define VERBOSE 1
+//#define LOG_OUTPUT_FUNC osd_printf_info
+#include "logmacro.h"
+
+DEFINE_DEVICE_TYPE(FP1020FD, fp1020fd_device, "fp1020fd", "FP-1020FD FDCPACK")
+
+fp1020fd_device::fp1020fd_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
+ : fp1060io_exp_device(mconfig, FP1020FD, tag, owner, clock)
+ , m_fdc(*this, "fdc")
+ , m_floppy(*this, "fdc:%u", 0)
+{
+}
+
+void fp1020fd_device::io_map(address_map &map)
+{
+ map(0x0000, 0x0000).mirror(0xfef9).unmapr().lw8(
+ NAME([this](offs_t offset, u8 data) {
+ (void)data;
+ for (auto floppy : m_floppy)
+ {
+ floppy_image_device *fl = floppy->get_device();
+ fl->mon_w(0);
+ }
+
+ m_motor_timer->adjust(attotime::from_seconds(60));
+ })
+ );
+ map(0x0002, 0x0002).mirror(0xfef9).unmapr().lw8(
+ NAME([this](offs_t offset, u8 data) {
+ (void)data;
+ m_fdc->tc_w(true);
+ m_fdc->tc_w(false);
+ })
+ );
+ map(0x0004, 0x0004).mirror(0xfef8).r(m_fdc, FUNC(upd765a_device::msr_r));
+ map(0x0005, 0x0005).mirror(0xfef8).rw(m_fdc, FUNC(upd765a_device::fifo_r), FUNC(upd765a_device::fifo_w));
+ map(0x0006, 0x0006).mirror(0xfef8).rw(m_fdc, FUNC(upd765a_device::dma_r), FUNC(upd765a_device::dma_w));
+ map(0x0007, 0x0007).mirror(0xfef8).unmaprw();
+}
+
+
+
+static void fd1020fd_floppies(device_slot_interface &device)
+{
+ device.option_add("525dsdd", FLOPPY_525_DD);
+}
+
+void fp1020fd_device::intrq_w(int state)
+{
+// LOG("intrq_w %d\n",state);
+ fp1060io_exp_device::intb_w(state);
+}
+
+void fp1020fd_device::drq_w(int state)
+{
+// LOG("drq_w %d\n",state);
+ fp1060io_exp_device::inta_w(state);
+}
+
+void fp1020fd_device::device_add_mconfig(machine_config &config)
+{
+ // UPD765AC
+ // TODO: verify clock
+ // ready and select lines = true verified (pukes any floppy bootstrap if either is false)
+ UPD765A(config, m_fdc, 8'000'000, true, true);
+ m_fdc->intrq_wr_callback().set(FUNC(fp1020fd_device::intrq_w));
+ m_fdc->drq_wr_callback().set(FUNC(fp1020fd_device::drq_w));
+ FLOPPY_CONNECTOR(config, "fdc:0", fd1020fd_floppies, "525dsdd", floppy_image_device::default_mfm_floppy_formats).enable_sound(true);
+ FLOPPY_CONNECTOR(config, "fdc:1", fd1020fd_floppies, "525dsdd", floppy_image_device::default_mfm_floppy_formats).enable_sound(true);
+}
+
+void fp1020fd_device::device_start()
+{
+ m_motor_timer = timer_alloc(FUNC(fp1020fd_device::motor_timeout_cb), this);
+}
+
+void fp1020fd_device::device_reset()
+{
+}
+
+TIMER_CALLBACK_MEMBER(fp1020fd_device::motor_timeout_cb)
+{
+ for (auto floppy : m_floppy)
+ {
+ floppy_image_device *fl = floppy->get_device();
+ fl->mon_w(1);
+ }
+}
diff --git a/src/devices/bus/fp1000/fp1020fd.h b/src/devices/bus/fp1000/fp1020fd.h
new file mode 100644
index 00000000000..e19feef985b
--- /dev/null
+++ b/src/devices/bus/fp1000/fp1020fd.h
@@ -0,0 +1,42 @@
+// license:BSD-3-Clause
+// copyright-holders:Angelo Salese
+
+#ifndef MAME_BUS_FP1000_FP1020FD_H
+#define MAME_BUS_FP1000_FP1020FD_H
+
+#pragma once
+
+#include "fp1060io_exp.h"
+#include "imagedev/floppy.h"
+#include "machine/timer.h"
+#include "machine/upd765.h"
+
+class fp1020fd_device : public fp1060io_exp_device
+{
+public:
+ fp1020fd_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
+
+ virtual void io_map(address_map &map) override ATTR_COLD;
+ virtual u8 get_id() override { return 0x04; };
+
+
+protected:
+ virtual void device_start() override ATTR_COLD;
+ virtual void device_reset() override ATTR_COLD;
+
+private:
+ virtual void device_add_mconfig(machine_config &config) override ATTR_COLD;
+
+ required_device<upd765a_device> m_fdc;
+ required_device_array<floppy_connector, 2> m_floppy;
+
+ TIMER_CALLBACK_MEMBER(motor_timeout_cb);
+ emu_timer *m_motor_timer;
+
+ void intrq_w(int state);
+ void drq_w(int state);
+};
+
+DECLARE_DEVICE_TYPE(FP1020FD, fp1020fd_device)
+
+#endif // MAME_BUS_FP1000_FP1020FD_H
diff --git a/src/devices/bus/fp1000/fp1030_rampack.cpp b/src/devices/bus/fp1000/fp1030_rampack.cpp
new file mode 100644
index 00000000000..a0df5d048f2
--- /dev/null
+++ b/src/devices/bus/fp1000/fp1030_rampack.cpp
@@ -0,0 +1,50 @@
+// license:BSD-3-Clause
+// copyright-holders:Angelo Salese
+/**************************************************************************************************
+
+FP-1030 RAMPACK
+
+FILES"PACK<x>:" where <x> is the designated slot number 0-7
+LOAD"PACKx:<filename>"
+RUN
+FORMAT"PACK<x>:" to use it in BASIC as a writable buffer
+
+**************************************************************************************************/
+
+#include "emu.h"
+#include "fp1030_rampack.h"
+
+DEFINE_DEVICE_TYPE(FP1030_RAMPACK, fp1030_rampack_device, "fp1030_rampack", "FP-1030 RAMPACK")
+
+fp1030_rampack_device::fp1030_rampack_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
+ : fp1060io_exp_device(mconfig, FP1030_RAMPACK, tag, owner, clock)
+ , m_nvram(*this, "nvram")
+{
+}
+
+void fp1030_rampack_device::io_map(address_map &map)
+{
+ // TODO: verify mirror/unmap
+ map(0x0000, 0x3fff).lrw8(
+ NAME([this](offs_t offset) { return m_nvram_ptr[offset & 0x3fff]; }),
+ NAME([this](offs_t offset, uint8_t data) { m_nvram_ptr[offset & 0x3fff] = data; })
+ );
+}
+
+void fp1030_rampack_device::device_add_mconfig(machine_config &config)
+{
+ // C-16K CMOS, 8 banks with 0x800 length
+ NVRAM(config, "nvram", nvram_device::DEFAULT_ALL_0);
+}
+
+void fp1030_rampack_device::device_start()
+{
+ const u32 nvram_size = 0x4000;
+ 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 fp1030_rampack_device::device_reset()
+{
+}
diff --git a/src/devices/bus/fp1000/fp1030_rampack.h b/src/devices/bus/fp1000/fp1030_rampack.h
new file mode 100644
index 00000000000..05168afccc0
--- /dev/null
+++ b/src/devices/bus/fp1000/fp1030_rampack.h
@@ -0,0 +1,34 @@
+// license:BSD-3-Clause
+// copyright-holders:Angelo Salese
+
+#ifndef MAME_BUS_FP1000_FP1030_RAMPACK_H
+#define MAME_BUS_FP1000_FP1030_RAMPACK_H
+
+#pragma once
+
+#include "fp1060io_exp.h"
+#include "machine/nvram.h"
+
+class fp1030_rampack_device : public fp1060io_exp_device
+{
+public:
+ fp1030_rampack_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
+
+ virtual void io_map(address_map &map) override ATTR_COLD;
+ virtual u8 get_id() override { return 0x01; };
+
+protected:
+ virtual void device_start() override ATTR_COLD;
+ virtual void device_reset() override ATTR_COLD;
+
+private:
+ virtual void device_add_mconfig(machine_config &config) override ATTR_COLD;
+
+ required_device<nvram_device> m_nvram;
+ std::unique_ptr<uint8_t[]> m_nvram_ptr;
+};
+
+DECLARE_DEVICE_TYPE(FP1030_RAMPACK, fp1030_rampack_device)
+
+
+#endif // MAME_BUS_FP1000_FP1030_RAMPACK_H
diff --git a/src/devices/bus/fp1000/fp1060io.cpp b/src/devices/bus/fp1000/fp1060io.cpp
new file mode 100644
index 00000000000..b18b99aa0c0
--- /dev/null
+++ b/src/devices/bus/fp1000/fp1060io.cpp
@@ -0,0 +1,95 @@
+// license:BSD-3-Clause
+// copyright-holders:Angelo Salese
+
+#include "emu.h"
+#include "fp1060io.h"
+
+#define VERBOSE 1
+//#define LOG_OUTPUT_FUNC osd_printf_info
+#include "logmacro.h"
+
+DEFINE_DEVICE_TYPE(FP1060IO, fp1060io_device, "fp1060io", "FP-1060I/O Expansion Box")
+
+fp1060io_device::fp1060io_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
+ : fp1000_exp_device(mconfig, FP1060IO, tag, owner, clock)
+ , m_subslot(*this, "%u", 0U)
+ , m_irqs_int(*this, { "irqs_inta", "irqs_intb", "irqs_intc", "irqs_intd"})
+{
+}
+
+
+void fp1060io_device::device_add_mconfig(machine_config &config)
+{
+ INPUT_MERGER_ANY_HIGH(config, m_irqs_int[0]).output_handler().set(FUNC(fp1060io_device::inta_w));
+ INPUT_MERGER_ANY_HIGH(config, m_irqs_int[1]).output_handler().set(FUNC(fp1060io_device::intb_w));
+ INPUT_MERGER_ANY_HIGH(config, m_irqs_int[2]).output_handler().set(FUNC(fp1060io_device::intc_w));
+ INPUT_MERGER_ANY_HIGH(config, m_irqs_int[3]).output_handler().set(FUNC(fp1060io_device::intd_w));
+
+ // default is just for CLI usability, what a retail '1060 gives back on its own is unconfirmed.
+ FP1060IO_EXP_SLOT(config, m_subslot[0], fp1060io_slot_devices, "rampack");
+ m_subslot[0]->inta_callback().set(m_irqs_int[0], FUNC(input_merger_device::in_w<0>));
+ m_subslot[0]->intb_callback().set(m_irqs_int[1], FUNC(input_merger_device::in_w<0>));
+ m_subslot[0]->intc_callback().set(m_irqs_int[2], FUNC(input_merger_device::in_w<0>));
+ m_subslot[0]->intd_callback().set(m_irqs_int[3], FUNC(input_merger_device::in_w<0>));
+
+ FP1060IO_EXP_SLOT(config, m_subslot[1], fp1060io_slot_devices, "rampack");
+ m_subslot[1]->inta_callback().set(m_irqs_int[0], FUNC(input_merger_device::in_w<1>));
+ m_subslot[1]->intb_callback().set(m_irqs_int[1], FUNC(input_merger_device::in_w<1>));
+ m_subslot[1]->intc_callback().set(m_irqs_int[2], FUNC(input_merger_device::in_w<1>));
+ m_subslot[1]->intd_callback().set(m_irqs_int[3], FUNC(input_merger_device::in_w<1>));
+
+ FP1060IO_EXP_SLOT(config, m_subslot[2], fp1060io_slot_devices, "rampack");
+ m_subslot[2]->inta_callback().set(m_irqs_int[0], FUNC(input_merger_device::in_w<2>));
+ m_subslot[2]->intb_callback().set(m_irqs_int[1], FUNC(input_merger_device::in_w<2>));
+ m_subslot[2]->intc_callback().set(m_irqs_int[2], FUNC(input_merger_device::in_w<2>));
+ m_subslot[2]->intd_callback().set(m_irqs_int[3], FUNC(input_merger_device::in_w<2>));
+
+ FP1060IO_EXP_SLOT(config, m_subslot[3], fp1060io_slot_devices, "rampack");
+ m_subslot[3]->inta_callback().set(m_irqs_int[0], FUNC(input_merger_device::in_w<3>));
+ m_subslot[3]->intb_callback().set(m_irqs_int[1], FUNC(input_merger_device::in_w<3>));
+ m_subslot[3]->intc_callback().set(m_irqs_int[2], FUNC(input_merger_device::in_w<3>));
+ m_subslot[3]->intd_callback().set(m_irqs_int[3], FUNC(input_merger_device::in_w<3>));
+}
+
+void fp1060io_device::device_start()
+{
+}
+
+void fp1060io_device::device_reset()
+{
+}
+
+u8 fp1060io_device::id_r(offs_t offset)
+{
+ LOG("ID select %02x\n", m_slot_select);
+ if (m_slot_select & 0xc)
+ return 0xff;
+ const auto dev = m_subslot[m_slot_select]->m_dev;
+ //LOG("\texists: %d\n", dev != nullptr);
+
+ if (dev == nullptr)
+ return 0xff;
+
+ return dev->get_id();
+}
+
+void fp1060io_device::cs_w(offs_t offset, u8 data)
+{
+ m_slot_select = data & 0xf;
+}
+
+void fp1060io_device::remap_cb()
+{
+ LOG("remap_cb %02x\n", m_slot_select);
+ if (m_slot_select & 0xc)
+ m_slot->iospace().unmap_readwrite(0x0000, 0xfeff);
+ else
+ {
+ const auto dev = m_subslot[m_slot_select]->m_dev;
+ //LOG("\texists %d\n", dev != nullptr);
+ if (dev == nullptr)
+ m_slot->iospace().unmap_readwrite(0x0000, 0xfeff);
+ else
+ m_slot->iospace().install_device(0x0000, 0xfeff, *m_subslot[m_slot_select]->m_dev, &device_fp1060io_exp_interface::io_map);
+ }
+}
diff --git a/src/devices/bus/fp1000/fp1060io.h b/src/devices/bus/fp1000/fp1060io.h
new file mode 100644
index 00000000000..4f69eeddf1a
--- /dev/null
+++ b/src/devices/bus/fp1000/fp1060io.h
@@ -0,0 +1,38 @@
+// license:BSD-3-Clause
+// copyright-holders:Angelo Salese
+
+#ifndef MAME_BUS_FP1000_FP1060IO_H
+#define MAME_BUS_FP1000_FP1060IO_H
+
+#pragma once
+
+#include "fp1000_exp.h"
+#include "fp1060io_exp.h"
+#include "machine/input_merger.h"
+
+class fp1060io_device : public fp1000_exp_device
+//, public device_single_card_slot_interface<device_fp1060io_slot_interface>
+{
+public:
+ fp1060io_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
+
+ virtual void cs_w(offs_t offset, u8 data) override;
+ virtual u8 id_r(offs_t offset) override;
+ virtual void remap_cb() override;
+
+protected:
+ virtual void device_start() override ATTR_COLD;
+ virtual void device_reset() override ATTR_COLD;
+
+private:
+ virtual void device_add_mconfig(machine_config &config) override ATTR_COLD;
+ required_device_array<fp1060io_exp_slot_device, 4> m_subslot;
+ required_device_array<input_merger_device, 4> m_irqs_int;
+
+ u8 m_slot_select = 0;
+};
+
+
+DECLARE_DEVICE_TYPE(FP1060IO, fp1060io_device)
+
+#endif // MAME_BUS_FP1000_FP1060IO_H
diff --git a/src/devices/bus/fp1000/fp1060io_exp.cpp b/src/devices/bus/fp1000/fp1060io_exp.cpp
new file mode 100644
index 00000000000..3c4e7f85894
--- /dev/null
+++ b/src/devices/bus/fp1000/fp1060io_exp.cpp
@@ -0,0 +1,98 @@
+// license:BSD-3-Clause
+// copyright-holders:Angelo Salese
+/**************************************************************************************************
+
+FP-1060I/O Expansion Slot
+
+List of known devices:
+- FP-1020FD2 (FDC uPD765, 2x 5.25 floppy DSDD, id = 0x04)
+- FP-1021FD1 (FDC, 1x 5.25 floppy FP-200 compatible 70kb (?))
+- FP-1022FD1 (FDC, 1x 5.25)
+- FP-1023FD1 (Same as 1020 with 1x drive?)
+- FP-1024FD2 (FDC, 2x floppy 2HD)
+- FP-1030 (RAMPACK, id = 0x01)
+- FP-1031 (ROMPACK, id = 0x00)
+\- One of the ROMPACKs has undumped Test Mode (cfr. page 94 of service manual)
+- FP-1032K (Kanji ROM pack, unknown id)
+- FP-1035RS (RS-232C, id = 0x02)
+
+**************************************************************************************************/
+
+#include "emu.h"
+#include "fp1060io_exp.h"
+
+
+DEFINE_DEVICE_TYPE(FP1060IO_EXP_SLOT, fp1060io_exp_slot_device, "fp1060io_exp_slot", "FP-1060I/O Expansion Slot")
+
+fp1060io_exp_slot_device::fp1060io_exp_slot_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
+ : device_t(mconfig, FP1060IO_EXP_SLOT, tag, owner, clock)
+ , device_single_card_slot_interface<device_fp1060io_exp_interface>(mconfig, *this)
+ , m_inta_cb(*this)
+ , m_intb_cb(*this)
+ , m_intc_cb(*this)
+ , m_intd_cb(*this)
+{
+}
+
+fp1060io_exp_slot_device::~fp1060io_exp_slot_device()
+{
+}
+
+void fp1060io_exp_slot_device::device_start()
+{
+}
+
+void fp1060io_exp_slot_device::device_config_complete()
+{
+ m_dev = get_card_device();
+}
+
+
+device_fp1060io_exp_interface::device_fp1060io_exp_interface(const machine_config &mconfig, device_t &device)
+ : device_interface(device, "fp1060ioexp")
+{
+ m_slot = dynamic_cast<fp1060io_exp_slot_device *>(device.owner());
+}
+
+device_fp1060io_exp_interface::~device_fp1060io_exp_interface()
+{
+}
+
+void device_fp1060io_exp_interface::interface_pre_start()
+{
+ if (!m_slot->started())
+ throw device_missing_dependencies();
+}
+
+void device_fp1060io_exp_interface::interface_post_start()
+{
+ // Dynamic mapping, shouldn't need anything from here
+}
+
+void device_fp1060io_exp_interface::inta_w(int state) { m_slot->m_inta_cb(state); }
+void device_fp1060io_exp_interface::intb_w(int state) { m_slot->m_intb_cb(state); }
+void device_fp1060io_exp_interface::intc_w(int state) { m_slot->m_intc_cb(state); }
+void device_fp1060io_exp_interface::intd_w(int state) { m_slot->m_intd_cb(state); }
+
+
+fp1060io_exp_device::fp1060io_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)
+ , device_fp1060io_exp_interface(mconfig, *this)
+{
+}
+
+void fp1060io_exp_device::device_start()
+{
+
+}
+
+
+#include "fp1020fd.h"
+#include "fp1030_rampack.h"
+
+void fp1060io_slot_devices(device_slot_interface &device)
+{
+ device.option_add("fdcpack", FP1020FD);
+ device.option_add("rampack", FP1030_RAMPACK);
+}
+
diff --git a/src/devices/bus/fp1000/fp1060io_exp.h b/src/devices/bus/fp1000/fp1060io_exp.h
new file mode 100644
index 00000000000..59e176b6ff8
--- /dev/null
+++ b/src/devices/bus/fp1000/fp1060io_exp.h
@@ -0,0 +1,86 @@
+// license:BSD-3-Clause
+// copyright-holders:Angelo Salese
+
+#ifndef MAME_BUS_FP1000_FP1060IO_EXP_H
+#define MAME_BUS_FP1000_FP1060IO_EXP_H
+
+#pragma once
+
+class device_fp1060io_exp_interface;
+class fp1060io_exp_device;
+
+class fp1060io_exp_slot_device : public device_t, public device_single_card_slot_interface<device_fp1060io_exp_interface>
+{
+ friend class device_fp1060io_exp_interface;
+public:
+ // construction/destruction
+ template <typename T>
+ fp1060io_exp_slot_device(machine_config const &mconfig, char const *tag, device_t *owner, T &&opts, char const *dflt)
+ : fp1060io_exp_slot_device(mconfig, tag, owner, (uint32_t)0)
+ {
+ option_reset();
+ opts(*this);
+ set_default_option(dflt);
+ set_fixed(false);
+ }
+ fp1060io_exp_slot_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
+ virtual ~fp1060io_exp_slot_device();
+
+ device_fp1060io_exp_interface *m_dev;
+
+ auto inta_callback() { return m_inta_cb.bind(); }
+ auto intb_callback() { return m_intb_cb.bind(); }
+ auto intc_callback() { return m_intc_cb.bind(); }
+ auto intd_callback() { return m_intd_cb.bind(); }
+
+protected:
+ virtual void device_start() override ATTR_COLD;
+ virtual void device_config_complete() override;
+
+ devcb_write_line m_inta_cb;
+ devcb_write_line m_intb_cb;
+ devcb_write_line m_intc_cb;
+ devcb_write_line m_intd_cb;
+};
+
+
+class device_fp1060io_exp_interface : public device_interface
+{
+public:
+ // construction/destruction
+ virtual ~device_fp1060io_exp_interface();
+
+ virtual void io_map(address_map &map) = 0;
+ virtual u8 get_id() = 0;
+
+protected:
+ device_fp1060io_exp_interface(const machine_config &mconfig, device_t &device);
+
+ virtual void interface_pre_start() override;
+ virtual void interface_post_start() override;
+
+ fp1060io_exp_slot_device *m_slot;
+
+ void inta_w(int state);
+ void intb_w(int state);
+ void intc_w(int state);
+ void intd_w(int state);
+};
+
+class fp1060io_exp_device : public device_t, public device_fp1060io_exp_interface
+{
+public:
+ // construction/destruction
+ fp1060io_exp_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock);
+
+
+protected:
+// virtual void device_add_mconfig(machine_config &config) override ATTR_COLD;
+ virtual void device_start() override ATTR_COLD;
+};
+
+void fp1060io_slot_devices(device_slot_interface &device);
+
+DECLARE_DEVICE_TYPE(FP1060IO_EXP_SLOT, fp1060io_exp_slot_device)
+
+#endif // MAME_BUS_FP1000_FP1060IO_EXP_H
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..d0065693dbe 100644
--- a/src/devices/bus/gamate/gamate_protection.h
+++ b/src/devices/bus/gamate/gamate_protection.h
@@ -1,8 +1,8 @@
// license:BSD-3-Clause
// copyright-holders:David Haywood
-#ifndef MAME_BUS_GAMATE_PROTECTION_H
-#define MAME_BUS_GAMATE_PROTECTION_H
+#ifndef MAME_BUS_GAMATE_GAMATE_PROTECTION_H
+#define MAME_BUS_GAMATE_GAMATE_PROTECTION_H
#pragma once
@@ -16,12 +16,12 @@ 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;
- virtual void device_reset() override;
+ virtual void device_start() override ATTR_COLD;
+ virtual void device_reset() override ATTR_COLD;
private:
int m_is_protection_passed;
@@ -35,5 +35,4 @@ private:
const uint8_t m_prot_string[15] = { 0x42, 0x49, 0x54, 0x20, 0x43, 0x4F, 0x52, 0x50, 0x4F, 0x52, 0x41, 0x54, 0x49, 0x4F, 0x4E }; // "BIT CORPORATION"
};
-#endif // MAME_BUS_GAMATE_PROTECTION_H
-
+#endif // MAME_BUS_GAMATE_GAMATE_PROTECTION_H
diff --git a/src/devices/bus/gamate/rom.cpp b/src/devices/bus/gamate/rom.cpp
index 74af9e76160..7301b6bdfc7 100644
--- a/src/devices/bus/gamate/rom.cpp
+++ b/src/devices/bus/gamate/rom.cpp
@@ -77,11 +77,11 @@ void gamate_rom_4in1_device::device_reset()
-------------------------------------------------*/
-READ8_MEMBER(gamate_rom_plain_device::read_cart)
+uint8_t gamate_rom_plain_device::read_cart(offs_t offset)
{
if (m_protection->is_protection_passed())
{
- return read_rom(space, offset, mem_mask);
+ return read_rom(offset);
}
else
{
@@ -91,12 +91,12 @@ READ8_MEMBER(gamate_rom_plain_device::read_cart)
return 0xff;
}
-READ8_MEMBER(gamate_rom_plain_device::read_rom)
+uint8_t gamate_rom_plain_device::read_rom(offs_t offset)
{
return m_rom[offset & (m_rom_size-1)];
}
-READ8_MEMBER(gamate_rom_banked_device::read_rom)
+uint8_t gamate_rom_banked_device::read_rom(offs_t offset)
{
if (offset < 0x4000)
{
@@ -110,7 +110,7 @@ READ8_MEMBER(gamate_rom_banked_device::read_rom)
return 0xff;
}
-READ8_MEMBER(gamate_rom_4in1_device::read_rom)
+uint8_t gamate_rom_4in1_device::read_rom(offs_t offset)
{
if (offset < 0x4000)
{
@@ -122,11 +122,11 @@ READ8_MEMBER(gamate_rom_4in1_device::read_rom)
}
}
-WRITE8_MEMBER(gamate_rom_plain_device::write_cart)
+void gamate_rom_plain_device::write_cart(offs_t offset, uint8_t data)
{
if (m_protection->is_protection_passed())
{
- write_rom(space, offset, data, mem_mask);
+ write_rom(offset, data);
}
else
{
@@ -134,13 +134,13 @@ WRITE8_MEMBER(gamate_rom_plain_device::write_cart)
}
}
-WRITE8_MEMBER(gamate_rom_plain_device::write_rom)
+void gamate_rom_plain_device::write_rom(offs_t offset, uint8_t data)
{
// shouldn't be any write on an unbanked game
logerror("gamate_rom_plain_device::write_rom %04x %02x\n", offset, data);
}
-WRITE8_MEMBER(gamate_rom_banked_device::write_rom)
+void gamate_rom_banked_device::write_rom(offs_t offset, uint8_t data)
{
if (offset == 0x6000)
{
@@ -152,7 +152,7 @@ WRITE8_MEMBER(gamate_rom_banked_device::write_rom)
}
}
-WRITE8_MEMBER(gamate_rom_4in1_device::write_rom)
+void gamate_rom_4in1_device::write_rom(offs_t offset, uint8_t data)
{
if (offset == 0x2000)
{
diff --git a/src/devices/bus/gamate/rom.h b/src/devices/bus/gamate/rom.h
index 1d500082e36..f38302da17a 100644
--- a/src/devices/bus/gamate/rom.h
+++ b/src/devices/bus/gamate/rom.h
@@ -18,15 +18,15 @@ public:
gamate_rom_plain_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
// reading and writing
- virtual DECLARE_READ8_MEMBER(read_cart) override;
- virtual DECLARE_WRITE8_MEMBER(write_cart) override;
- virtual READ8_MEMBER(read_rom);
- virtual WRITE8_MEMBER(write_rom);
+ virtual uint8_t read_cart(offs_t offset) override;
+ virtual void write_cart(offs_t offset, uint8_t data) override;
+ virtual uint8_t read_rom(offs_t offset);
+ virtual void write_rom(offs_t offset, uint8_t data);
protected:
gamate_rom_plain_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_add_mconfig(machine_config &config) override ATTR_COLD;
// device-level overrides
virtual void device_start() override { }
@@ -47,12 +47,12 @@ protected:
gamate_rom_banked_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock);
// reading and writing
- virtual READ8_MEMBER(read_rom) override;
- virtual WRITE8_MEMBER(write_rom) override;
+ virtual uint8_t read_rom(offs_t offset) override;
+ virtual void write_rom(offs_t offset, uint8_t data) override;
protected:
- virtual void device_start() override;
- virtual void device_reset() override;
+ virtual void device_start() override ATTR_COLD;
+ virtual void device_reset() override ATTR_COLD;
int m_bank;
};
@@ -67,12 +67,12 @@ public:
gamate_rom_4in1_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
// reading and writing
- virtual READ8_MEMBER(read_rom) override;
- virtual WRITE8_MEMBER(write_rom) override;
+ virtual uint8_t read_rom(offs_t offset) override;
+ virtual void write_rom(offs_t offset, uint8_t data) override;
protected:
- virtual void device_start() override;
- virtual void device_reset() override;
+ virtual void device_start() override ATTR_COLD;
+ virtual void device_reset() override ATTR_COLD;
private:
int m_multibank;
diff --git a/src/devices/bus/gamate/slot.cpp b/src/devices/bus/gamate/slot.cpp
index 40a1c7fdfaa..b627aee6d3e 100644
--- a/src/devices/bus/gamate/slot.cpp
+++ b/src/devices/bus/gamate/slot.cpp
@@ -18,10 +18,10 @@ DEFINE_DEVICE_TYPE(GAMATE_CART_SLOT, gamate_cart_slot_device, "gamate_cart_slot"
// device_gamate_cart_interface - constructor
//-------------------------------------------------
-device_gamate_cart_interface::device_gamate_cart_interface(const machine_config &mconfig, device_t &device)
- : device_slot_card_interface(mconfig, device),
- m_rom(nullptr),
- m_rom_size(0)
+device_gamate_cart_interface::device_gamate_cart_interface(const machine_config &mconfig, device_t &device) :
+ device_interface(device, "gamatecart"),
+ m_rom(nullptr),
+ m_rom_size(0)
{
}
@@ -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;
}
}
@@ -56,8 +56,8 @@ void device_gamate_cart_interface::rom_alloc(uint32_t size, const char *tag)
//-------------------------------------------------
gamate_cart_slot_device::gamate_cart_slot_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) :
device_t(mconfig, GAMATE_CART_SLOT, tag, owner, clock),
- device_image_interface(mconfig, *this),
- device_slot_interface(mconfig, *this),
+ device_cartrom_image_interface(mconfig, *this),
+ device_single_card_slot_interface(mconfig, *this),
m_type(GAMATE_PLAIN),
m_cart(nullptr)
{
@@ -77,7 +77,7 @@ gamate_cart_slot_device::~gamate_cart_slot_device()
void gamate_cart_slot_device::device_start()
{
- m_cart = dynamic_cast<device_gamate_cart_interface *>(get_card_device());
+ m_cart = get_card_device();
}
//-------------------------------------------------
@@ -102,7 +102,7 @@ static int gamate_get_pcb_id(const char *slot)
{
for (auto & elem : slot_list)
{
- if (!core_stricmp(elem.slot_option, slot))
+ if (!strcmp(elem.slot_option, slot))
return elem.pcb_id;
}
@@ -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_UNSPECIFIED, "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());
}
@@ -203,15 +197,14 @@ std::string gamate_cart_slot_device::get_default_card_software(get_default_card_
{
if (hook.image_file())
{
- const char *slot_string;
- uint32_t len = hook.image_file()->size();
+ uint64_t len;
+ hook.image_file()->length(len); // FIXME: check error return, guard against excessively large files
std::vector<uint8_t> rom(len);
- int type;
- hook.image_file()->read(&rom[0], len);
+ /*auto const [err, actual] =*/ read(*hook.image_file(), &rom[0], len); // FIXME: check error return or read returning short
- type = get_cart_type(&rom[0], len);
- slot_string = gamate_get_slot(type);
+ int const type = get_cart_type(&rom[0], len);
+ char const *const slot_string = gamate_get_slot(type);
//printf("type: %s\n", slot_string);
@@ -225,11 +218,11 @@ std::string gamate_cart_slot_device::get_default_card_software(get_default_card_
read
-------------------------------------------------*/
-READ8_MEMBER(gamate_cart_slot_device::read_cart)
+uint8_t gamate_cart_slot_device::read_cart(offs_t offset)
{
if (m_cart)
{
- return m_cart->read_cart(space, offset);
+ return m_cart->read_cart(offset);
}
else
return 0xff;
@@ -239,10 +232,10 @@ READ8_MEMBER(gamate_cart_slot_device::read_cart)
write
-------------------------------------------------*/
-WRITE8_MEMBER(gamate_cart_slot_device::write_cart)
+void gamate_cart_slot_device::write_cart(offs_t offset, uint8_t data)
{
if (m_cart)
{
- m_cart->write_cart(space, offset, data);
+ m_cart->write_cart(offset, data);
}
}
diff --git a/src/devices/bus/gamate/slot.h b/src/devices/bus/gamate/slot.h
index 3606ac32c69..21381463667 100644
--- a/src/devices/bus/gamate/slot.h
+++ b/src/devices/bus/gamate/slot.h
@@ -5,7 +5,7 @@
#pragma once
-#include "softlist_dev.h"
+#include "imagedev/cartrom.h"
/***************************************************************************
TYPE DEFINITIONS
@@ -21,17 +21,17 @@ enum
// ======================> device_gamate_cart_interface
-class device_gamate_cart_interface : public device_slot_card_interface
+class device_gamate_cart_interface : public device_interface
{
public:
// construction/destruction
virtual ~device_gamate_cart_interface();
// reading and writing
- virtual DECLARE_READ8_MEMBER(read_cart) { return 0xff; }
- virtual DECLARE_WRITE8_MEMBER(write_cart) { }
+ 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; }
@@ -46,8 +46,8 @@ protected:
// ======================> gamate_cart_slot_device
class gamate_cart_slot_device : public device_t,
- public device_image_interface,
- public device_slot_interface
+ public device_cartrom_image_interface,
+ public device_single_card_slot_interface<device_gamate_cart_interface>
{
public:
// construction/destruction
@@ -64,36 +64,30 @@ 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;
- virtual void call_unload() override {}
- virtual const software_list_loader &get_software_list_loader() const override { return rom_software_list_loader::instance(); }
+ // device_image_interface implementation
+ virtual std::pair<std::error_condition, std::string> call_load() override;
+ virtual void call_unload() override { }
- int get_type() { return m_type; }
- static int get_cart_type(const uint8_t *ROM, uint32_t len);
+ 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"; }
- virtual iodevice_t image_type() const override { return IO_CARTSLOT; }
- virtual bool is_readable() const override { return 1; }
- virtual bool is_writeable() const override { return 0; }
- virtual bool is_creatable() const override { return 0; }
- virtual bool must_be_loaded() const override { return 0; }
- virtual bool is_reset_on_load() const override { return 1; }
- virtual const char *image_interface() const override { return "gamate_cart"; }
- virtual const char *file_extensions() const 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; }
+ static int get_cart_type(const uint8_t *ROM, uint32_t len);
+
// reading and writing
- virtual DECLARE_READ8_MEMBER(read_cart);
- virtual DECLARE_WRITE8_MEMBER(write_cart);
+ uint8_t read_cart(offs_t offset);
+ void write_cart(offs_t offset, uint8_t data);
protected:
- // device-level overrides
- virtual void device_start() override;
+ // device_t implementation
+ virtual void device_start() override ATTR_COLD;
int m_type;
- device_gamate_cart_interface* m_cart;
+ device_gamate_cart_interface *m_cart;
};
// device type definition
@@ -103,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 a72eedc24d5..00000000000
--- a/src/devices/bus/gameboy/gb_slot.cpp
+++ /dev/null
@@ -1,834 +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_slot_card_interface(mconfig, device),
- 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_image_interface(mconfig, *this),
- device_slot_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 = dynamic_cast<device_gb_cart_interface *>(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 (!core_stricmp(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_UNSPECIFIED, "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 (!core_stricmp(get_feature("rumble"), "yes"))
- m_cart->set_has_rumble(true);
- }
-
- if (get_feature("rtc"))
- {
- if (!core_stricmp(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);
-
- 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 = ARRAY_LENGTH(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())
- {
- const char *slot_string;
- uint32_t len = hook.image_file()->size(), offset = 0;
- std::vector<uint8_t> rom(len);
- int type;
-
- hook.image_file()->read(&rom[0], len);
-
- if ((len % 0x4000) == 512)
- offset = 512;
-
- if (get_mmm01_candidate(&rom[offset], len - offset))
- offset += (len - 0x8000);
-
- type = get_cart_type(&rom[offset], len - offset);
- 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 < ARRAY_LENGTH(companies); i++)
- if (tmp == companies[i].code)
- break;
- logerror("\tManufacturer ID: 0x%02X [%s]\n", tmp, (i < ARRAY_LENGTH(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 5f420c60823..00000000000
--- a/src/devices/bus/gameboy/gb_slot.h
+++ /dev/null
@@ -1,215 +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 "softlist_dev.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_slot_card_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_image_interface,
- public device_slot_interface
-{
-public:
- // construction/destruction
- virtual ~gb_cart_slot_device_base();
-
- // device-level overrides
- virtual void device_start() override;
-
- // image-level overrides
- virtual image_init_result call_load() override;
- virtual void call_unload() override;
- virtual const software_list_loader &get_software_list_loader() const override { return rom_software_list_loader::instance(); }
-
- 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(); }
-
- virtual iodevice_t image_type() const override { return IO_CARTSLOT; }
- virtual bool is_readable() const override { return 1; }
- virtual bool is_writeable() const override { return 0; }
- virtual bool is_creatable() const override { return 0; }
- virtual bool must_be_loaded() const override { return 0; }
- virtual bool is_reset_on_load() const override { return 1; }
- virtual const char *image_interface() const override { return "gameboy_cart"; }
- virtual const char *file_extensions() const override { return "bin,gb,gbc"; }
-
- // slot interface overrides
- virtual std::string get_default_card_software(get_default_card_software_hook &hook) const override;
-
- // 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);
-
- 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 override { return "megaduck_cart"; }
- virtual const char *file_extensions() const 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 bd57a4da23b..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,1428 +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)
-{
-}
+#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])
{
- machine().output().set_value("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 9658369d6fb..0da79f570d1 100644
--- a/src/devices/bus/gameboy/mbc.h
+++ b/src/devices/bus/gameboy/mbc.h
@@ -1,450 +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(); }
- virtual void device_reset() override { shared_reset(); }
-};
-
-// ======================> 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..a14ad8067f1
--- /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))
+ return 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 d3e90d73f51..c3c7ab0e347 100644
--- a/src/devices/bus/gameboy/rom.cpp
+++ b/src/devices/bus/gameboy/rom.cpp
@@ -1,362 +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;
+};
+
+
+//**************************************************************************
+// Mega Duck flat ROM (max 32 KiB)
+//**************************************************************************
-// these are identical to shared ones above, but megaduck cart class is not derived from gb cart class...
-void megaduck_rom_device::device_start()
+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;
+ }
+
+ // 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
+ {
+ }
+};
-void megaduck_rom_device::device_reset()
+
+
+//**************************************************************************
+// 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();
+ }
+
+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]);
+ }
+
+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];
+};
+
-/*-------------------------------------------------
- mapper specific handlers
- -------------------------------------------------*/
+//**************************************************************************
+// Game Boy flat ROM/RAM (max 32 KiB ROM, 8 KiB RAM)
+//**************************************************************************
-uint8_t gb_rom_device::read_rom(offs_t offset)
+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);
+ // 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();
+ }
+
+private:
+ void bank_rom_switch(offs_t offset, u8 data)
+ {
+ set_bank_rom(offset);
+ }
+};
-// Tamagotchi
-uint8_t gb_rom_tama5_device::read_rom(offs_t 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();
+
+ // 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);
+ }
+};
+
+
-uint8_t gb_rom_tama5_device::read_ram(offs_t offset)
+//**************************************************************************
+// 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();
+ }
+
+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);
+ }
+};
+
+
-void gb_rom_tama5_device::write_ram(offs_t offset, uint8_t 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;
- 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 99d464e87b7..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_slot_card_interface(mconfig,device)
-{
- 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_slot_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 = dynamic_cast<device_gg_ext_port_interface *>(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 f2145e694fd..00000000000
--- a/src/devices/bus/gamegear/ggext.h
+++ /dev/null
@@ -1,110 +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_slot_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_slot_card_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 0e926ff1d91..e36c7a2650d 100644
--- a/src/devices/bus/gba/gba_slot.cpp
+++ b/src/devices/bus/gba/gba_slot.cpp
@@ -478,10 +478,10 @@ DEFINE_DEVICE_TYPE(GBA_CART_SLOT, gba_cart_slot_device, "gba_cart_slot", "Game B
// device_gba_cart_interface - constructor
//-------------------------------------------------
-device_gba_cart_interface::device_gba_cart_interface(const machine_config &mconfig, device_t &device)
- : device_slot_card_interface(mconfig, device)
- , m_rom(nullptr)
- , m_rom_size(0)
+device_gba_cart_interface::device_gba_cart_interface(const machine_config &mconfig, device_t &device) :
+ device_interface(device, "gbacart"),
+ m_rom(nullptr),
+ m_rom_size(0)
{
}
@@ -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;
}
@@ -534,7 +534,7 @@ void device_gba_cart_interface::nvram_alloc(uint32_t size)
//-------------------------------------------------
gba_cart_slot_device::gba_cart_slot_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) :
device_t(mconfig, GBA_CART_SLOT, tag, owner, clock),
- device_image_interface(mconfig, *this),
+ device_cartrom_image_interface(mconfig, *this),
device_slot_interface(mconfig, *this),
m_type(GBA_STD),
m_cart(nullptr)
@@ -594,7 +594,7 @@ static int gba_get_pcb_id(const char *slot)
{
for (auto & elem : slot_list)
{
- if (!core_stricmp(elem.slot_option, slot))
+ if (!strcmp(elem.slot_option, slot))
return elem.pcb_id;
}
@@ -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_UNSPECIFIED, "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())
{
@@ -659,20 +655,20 @@ image_init_result gba_cart_slot_device::call_load()
{
case 2 * 1024 * 1024:
memcpy(ROM + 0x200000, ROM, 0x200000);
- // intentional fall-through
+ [[fallthrough]];
case 4 * 1024 * 1024:
memcpy(ROM + 0x400000, ROM, 0x400000);
- // intentional fall-through
+ [[fallthrough]];
case 8 * 1024 * 1024:
memcpy(ROM + 0x800000, ROM, 0x800000);
- // intentional fall-through
+ [[fallthrough]];
case 16 * 1024 * 1024:
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());
}
@@ -719,7 +713,11 @@ static inline std::string gba_chip_string( uint32_t chip )
if (chip & GBA_CHIP_FLASH_512) str += "FLASH_512 ";
if (chip & GBA_CHIP_SRAM) str += "SRAM ";
if (chip & GBA_CHIP_RTC) str += "RTC ";
- strtrimspace(str);
+ if (!str.empty())
+ {
+ assert(str.back() == ' ');
+ str = str.substr(0, str.length() - 1);
+ }
return str;
}
@@ -761,7 +759,7 @@ int gba_cart_slot_device::get_cart_type(const uint8_t *ROM, uint32_t len)
else if ((i<len-8) && !memcmp(&ROM[i], "SIIRTC_V", 8))
chip |= GBA_CHIP_RTC;
}
- osd_printf_info("GBA: Detected (ROM) %s\n", gba_chip_string(chip).c_str());
+ osd_printf_info("GBA: Detected (ROM) %s\n", gba_chip_string(chip));
// fix for games which return more than one kind of chip: either it is one of the known titles, or we default to no battery
if (gba_chip_has_conflict(chip))
@@ -829,7 +827,7 @@ int gba_cart_slot_device::get_cart_type(const uint8_t *ROM, uint32_t len)
has_rtc = true;
}
- osd_printf_info("GBA: Emulate %s\n", gba_chip_string(chip).c_str());
+ osd_printf_info("GBA: Emulate %s\n", gba_chip_string(chip));
switch (chip)
{
@@ -879,15 +877,14 @@ std::string gba_cart_slot_device::get_default_card_software(get_default_card_sof
{
if (hook.image_file())
{
- const char *slot_string;
- uint32_t len = hook.image_file()->size();
+ uint64_t len;
+ hook.image_file()->length(len); // FIXME: check error return, guard against excessively large files
std::vector<uint8_t> rom(len);
- int type;
- hook.image_file()->read(&rom[0], len);
+ read(*hook.image_file(), &rom[0], len); // FIXME: check error return or read returning short
- type = get_cart_type(&rom[0], len);
- slot_string = gba_get_slot(type);
+ int const type = get_cart_type(&rom[0], len);
+ char const *const slot_string = gba_get_slot(type);
//printf("type: %s\n", slot_string);
@@ -901,26 +898,26 @@ std::string gba_cart_slot_device::get_default_card_software(get_default_card_sof
read
-------------------------------------------------*/
-READ32_MEMBER(gba_cart_slot_device::read_rom)
+uint32_t gba_cart_slot_device::read_rom(offs_t offset)
{
if (m_cart)
- return m_cart->read_rom(space, offset, mem_mask);
+ return m_cart->read_rom(offset);
else
return 0xffffffff;
}
-READ32_MEMBER(gba_cart_slot_device::read_ram)
+uint32_t gba_cart_slot_device::read_ram(offs_t offset, uint32_t mem_mask)
{
if (m_cart)
- return m_cart->read_ram(space, offset, mem_mask);
+ return m_cart->read_ram(offset, mem_mask);
else
return 0xffffffff;
}
-READ32_MEMBER(gba_cart_slot_device::read_gpio)
+uint32_t gba_cart_slot_device::read_gpio(offs_t offset, uint32_t mem_mask)
{
if (m_cart)
- return m_cart->read_gpio(space, offset, mem_mask);
+ return m_cart->read_gpio(offset, mem_mask);
else
return 0xffffffff;
}
@@ -930,14 +927,14 @@ READ32_MEMBER(gba_cart_slot_device::read_gpio)
write
-------------------------------------------------*/
-WRITE32_MEMBER(gba_cart_slot_device::write_ram)
+void gba_cart_slot_device::write_ram(offs_t offset, uint32_t data, uint32_t mem_mask)
{
if (m_cart)
- m_cart->write_ram(space, offset, data, mem_mask);
+ m_cart->write_ram(offset, data, mem_mask);
}
-WRITE32_MEMBER(gba_cart_slot_device::write_gpio)
+void gba_cart_slot_device::write_gpio(offs_t offset, uint32_t data, uint32_t mem_mask)
{
if (m_cart)
- m_cart->write_gpio(space, offset, data, mem_mask);
+ m_cart->write_gpio(offset, data, mem_mask);
}
diff --git a/src/devices/bus/gba/gba_slot.h b/src/devices/bus/gba/gba_slot.h
index b26891c6589..4510993e872 100644
--- a/src/devices/bus/gba/gba_slot.h
+++ b/src/devices/bus/gba/gba_slot.h
@@ -5,7 +5,7 @@
#pragma once
-#include "softlist_dev.h"
+#include "imagedev/cartrom.h"
/***************************************************************************
@@ -36,21 +36,21 @@ enum
// ======================> device_gba_cart_interface
-class device_gba_cart_interface : public device_slot_card_interface
+class device_gba_cart_interface : public device_interface
{
public:
// construction/destruction
virtual ~device_gba_cart_interface();
// reading and writing
- virtual DECLARE_READ32_MEMBER(read_rom) { return 0xffffffff; }
- virtual DECLARE_READ32_MEMBER(read_ram) { return 0xffffffff; }
- virtual DECLARE_READ32_MEMBER(read_gpio) { return 0; }
- virtual DECLARE_READ32_MEMBER(read_tilt) { return 0xffffffff; }
- virtual DECLARE_WRITE32_MEMBER(write_ram) { }
- virtual DECLARE_WRITE32_MEMBER(write_gpio) { }
- virtual DECLARE_WRITE32_MEMBER(write_tilt) { }
- virtual DECLARE_WRITE32_MEMBER(write_mapper) { }
+ virtual uint32_t read_rom(offs_t offset) { return 0xffffffff; }
+ virtual uint32_t read_ram(offs_t offset, uint32_t mem_mask = ~0) { return 0xffffffff; }
+ virtual uint32_t read_gpio(offs_t offset, uint32_t mem_mask = ~0) { return 0; }
+ virtual uint32_t read_tilt(offs_t offset, uint32_t mem_mask = ~0) { return 0xffffffff; }
+ virtual void write_ram(offs_t offset, uint32_t data, uint32_t mem_mask = ~0) { }
+ virtual void write_gpio(offs_t offset, uint32_t data, uint32_t mem_mask = ~0) { }
+ virtual void write_tilt(offs_t offset, uint32_t data) { }
+ virtual void write_mapper(offs_t offset, uint32_t data) { }
void rom_alloc(uint32_t size, const char *tag);
void nvram_alloc(uint32_t size);
@@ -79,7 +79,7 @@ protected:
// ======================> gba_cart_slot_device
class gba_cart_slot_device : public device_t,
- public device_image_interface,
+ public device_cartrom_image_interface,
public device_slot_interface
{
public:
@@ -97,13 +97,16 @@ public:
gba_cart_slot_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock = 0);
virtual ~gba_cart_slot_device();
- // 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 void call_unload() override;
- virtual const software_list_loader &get_software_list_loader() const override { return rom_software_list_loader::instance(); }
+
+ 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"; }
+
+ // 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; }
static int get_cart_type(const uint8_t *ROM, uint32_t len);
@@ -111,30 +114,19 @@ public:
void save_nvram() { if (m_cart && m_cart->get_nvram_size()) m_cart->save_nvram(); }
uint32_t get_rom_size() { if (m_cart) return m_cart->get_rom_size(); return 0; }
- virtual iodevice_t image_type() const override { return IO_CARTSLOT; }
- virtual bool is_readable() const override { return 1; }
- virtual bool is_writeable() const override { return 0; }
- virtual bool is_creatable() const override { return 0; }
- virtual bool must_be_loaded() const override { return 0; }
- virtual bool is_reset_on_load() const override { return 1; }
- virtual const char *image_interface() const override { return "gba_cart"; }
- virtual const char *file_extensions() const override { return "gba,bin"; }
-
- // slot interface overrides
- virtual std::string get_default_card_software(get_default_card_software_hook &hook) const override;
-
// reading and writing
- virtual DECLARE_READ32_MEMBER(read_rom);
- virtual DECLARE_READ32_MEMBER(read_ram);
- virtual DECLARE_READ32_MEMBER(read_gpio);
- virtual DECLARE_READ32_MEMBER(read_tilt) { if (m_cart) return m_cart->read_tilt(space, offset, mem_mask); else return 0xffffffff; }
- virtual DECLARE_WRITE32_MEMBER(write_ram);
- virtual DECLARE_WRITE32_MEMBER(write_gpio);
- virtual DECLARE_WRITE32_MEMBER(write_tilt) { if (m_cart) m_cart->write_tilt(space, offset, data, mem_mask); }
- virtual DECLARE_WRITE32_MEMBER(write_mapper) { if (m_cart) m_cart->write_mapper(space, offset, data, mem_mask); }
-
+ virtual uint32_t read_rom(offs_t offset);
+ virtual uint32_t read_ram(offs_t offset, uint32_t mem_mask = ~0);
+ virtual uint32_t read_gpio(offs_t offset, uint32_t mem_mask = ~0);
+ virtual uint32_t read_tilt(offs_t offset, uint32_t mem_mask = ~0) { if (m_cart) return m_cart->read_tilt(offset); else return 0xffffffff; }
+ virtual void write_ram(offs_t offset, uint32_t data, uint32_t mem_mask = ~0);
+ virtual void write_gpio(offs_t offset, uint32_t data, uint32_t mem_mask = ~0);
+ virtual void write_tilt(offs_t offset, uint32_t data) { if (m_cart) m_cart->write_tilt(offset, data); }
+ virtual void write_mapper(offs_t offset, uint32_t data) { if (m_cart) m_cart->write_mapper(offset, data); }
protected:
+ // device_t implementation
+ virtual void device_start() override ATTR_COLD;
int m_type;
device_gba_cart_interface* m_cart;
diff --git a/src/devices/bus/gba/rom.cpp b/src/devices/bus/gba/rom.cpp
index e1c61ec0f49..643432b8433 100644
--- a/src/devices/bus/gba/rom.cpp
+++ b/src/devices/bus/gba/rom.cpp
@@ -59,11 +59,13 @@ gba_rom_sram_device::gba_rom_sram_device(const machine_config &mconfig, const ch
gba_rom_drilldoz_device::gba_rom_drilldoz_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
: gba_rom_sram_device(mconfig, GBA_ROM_DRILLDOZ, tag, owner, clock)
+ , m_rumble(*this, "Rumble")
{
}
gba_rom_wariotws_device::gba_rom_wariotws_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
: gba_rom_sram_device(mconfig, GBA_ROM_WARIOTWS, tag, owner, clock)
+ , m_rumble(*this, "Rumble")
, m_gyro_z(*this, "GYROZ")
{
}
@@ -162,8 +164,16 @@ void gba_rom_device::device_reset()
m_gpio_dirs = 0;
}
+void gba_rom_drilldoz_device::device_start()
+{
+ gba_rom_device::device_start();
+ m_rumble.resolve();
+}
+
void gba_rom_wariotws_device::device_start()
{
+ gba_rom_device::device_start();
+ m_rumble.resolve();
save_item(NAME(m_last_val));
save_item(NAME(m_counter));
}
@@ -187,6 +197,8 @@ void gba_rom_flash1m_device::device_reset()
void gba_rom_eeprom_device::device_start()
{
+ gba_rom_device::device_start();
+
// for the moment we use a custom eeprom implementation, so we alloc/save it as nvram
nvram_alloc(0x200);
m_eeprom = std::make_unique<gba_eeprom_device>(machine(), (uint8_t*)get_nvram_base(), get_nvram_size(), 6);
@@ -232,16 +244,19 @@ void gba_rom_boktai_device::device_reset()
void gba_rom_flash_rtc_device::device_start()
{
+ gba_rom_device::device_start();
m_rtc = std::make_unique<gba_s3511_device>(machine());
}
void gba_rom_flash1m_rtc_device::device_start()
{
+ gba_rom_device::device_start();
m_rtc = std::make_unique<gba_s3511_device>(machine());
}
void gba_rom_3dmatrix_device::device_start()
{
+ gba_rom_device::device_start();
save_item(NAME(m_src));
save_item(NAME(m_dst));
save_item(NAME(m_nblock));
@@ -271,7 +286,7 @@ void gba_rom_3dmatrix_device::device_reset()
cart types.
-------------------------------------------------*/
-READ32_MEMBER(gba_rom_device::read_gpio)
+uint32_t gba_rom_device::read_gpio(offs_t offset, uint32_t mem_mask)
{
if (!m_gpio_write_only)
{
@@ -286,6 +301,7 @@ READ32_MEMBER(gba_rom_device::read_gpio)
}
if (ACCESSING_BITS_16_31)
return m_gpio_regs[1] << 16;
+ [[fallthrough]];
case 1:
if (ACCESSING_BITS_0_15)
return m_gpio_regs[2];
@@ -298,7 +314,7 @@ READ32_MEMBER(gba_rom_device::read_gpio)
return m_rom[offset + 0xc4/4];
}
-WRITE32_MEMBER(gba_rom_device::write_gpio)
+void gba_rom_device::write_gpio(offs_t offset, uint32_t data, uint32_t mem_mask)
{
switch (offset)
{
@@ -331,7 +347,7 @@ WRITE32_MEMBER(gba_rom_device::write_gpio)
Carts with SRAM
-------------------------------------------------*/
-READ32_MEMBER(gba_rom_sram_device::read_ram)
+uint32_t gba_rom_sram_device::read_ram(offs_t offset, uint32_t mem_mask)
{
if (!m_nvram.empty() && offset < m_nvram.size())
return m_nvram[offset];
@@ -339,7 +355,7 @@ READ32_MEMBER(gba_rom_sram_device::read_ram)
return 0xffffffff;
}
-WRITE32_MEMBER(gba_rom_sram_device::write_ram)
+void gba_rom_sram_device::write_ram(offs_t offset, uint32_t data, uint32_t mem_mask)
{
if (!m_nvram.empty() && offset < m_nvram.size())
COMBINE_DATA(&m_nvram[offset]);
@@ -353,7 +369,7 @@ void gba_rom_drilldoz_device::gpio_dev_write(uint16_t data, int gpio_dirs)
if ((gpio_dirs & 0x08))
{
// send impulse to Rumble sensor
- machine().output().set_value("Rumble", BIT(data, 3));
+ m_rumble = BIT(data, 3);
}
}
@@ -383,7 +399,7 @@ void gba_rom_wariotws_device::gpio_dev_write(uint16_t data, int gpio_dirs)
if ((gpio_dirs & 0x08))
{
// send impulse to Rumble sensor
- machine().output().set_value("Rumble", BIT(data, 3));
+ m_rumble = BIT(data, 3);
}
if (gpio_dirs == 0x0b)
@@ -410,7 +426,7 @@ void gba_rom_flash_device::device_add_mconfig(machine_config &config)
}
-READ32_MEMBER(gba_rom_flash_device::read_ram)
+uint32_t gba_rom_flash_device::read_ram(offs_t offset, uint32_t mem_mask)
{
uint32_t rv = 0;
@@ -428,7 +444,7 @@ READ32_MEMBER(gba_rom_flash_device::read_ram)
return rv;
}
-WRITE32_MEMBER(gba_rom_flash_device::write_ram)
+void gba_rom_flash_device::write_ram(offs_t offset, uint32_t data, uint32_t mem_mask)
{
offset &= m_flash_mask;
@@ -457,7 +473,7 @@ void gba_rom_flash1m_device::device_add_mconfig(machine_config &config)
}
-READ32_MEMBER(gba_rom_flash1m_device::read_ram)
+uint32_t gba_rom_flash1m_device::read_ram(offs_t offset, uint32_t mem_mask)
{
uint32_t rv = 0;
@@ -475,7 +491,7 @@ READ32_MEMBER(gba_rom_flash1m_device::read_ram)
return rv;
}
-WRITE32_MEMBER(gba_rom_flash1m_device::write_ram)
+void gba_rom_flash1m_device::write_ram(offs_t offset, uint32_t data, uint32_t mem_mask)
{
offset &= m_flash_mask;
@@ -526,7 +542,7 @@ void gba_rom_flash1m_rtc_device::gpio_dev_write(uint16_t data, int gpio_dirs)
Carts with EEPROM
-------------------------------------------------*/
-READ32_MEMBER(gba_rom_eeprom_device::read_ram)
+uint32_t gba_rom_eeprom_device::read_ram(offs_t offset, uint32_t mem_mask)
{
// Larger games have smaller access to EERPOM content
if (m_rom_size > (16 * 1024 * 1024) && offset < 0xffff00/4)
@@ -535,7 +551,7 @@ READ32_MEMBER(gba_rom_eeprom_device::read_ram)
return m_eeprom->read();
}
-WRITE32_MEMBER(gba_rom_eeprom_device::write_ram)
+void gba_rom_eeprom_device::write_ram(offs_t offset, uint32_t data, uint32_t mem_mask)
{
// Larger games have smaller access to EEPROM content
if (m_rom_size > (16 * 1024 * 1024) && offset < 0xffff00/4)
@@ -547,7 +563,7 @@ WRITE32_MEMBER(gba_rom_eeprom_device::write_ram)
m_eeprom->write(data);
}
-READ32_MEMBER(gba_rom_eeprom64_device::read_ram)
+uint32_t gba_rom_eeprom64_device::read_ram(offs_t offset, uint32_t mem_mask)
{
// Larger games have smaller access to EERPOM content
if (m_rom_size > (16 * 1024 * 1024) && offset < 0xffff00/4)
@@ -556,7 +572,7 @@ READ32_MEMBER(gba_rom_eeprom64_device::read_ram)
return m_eeprom->read();
}
-WRITE32_MEMBER(gba_rom_eeprom64_device::write_ram)
+void gba_rom_eeprom64_device::write_ram(offs_t offset, uint32_t data, uint32_t mem_mask)
{
// Larger games have smaller access to EEPROM content
if (m_rom_size > (16 * 1024 * 1024) && offset < 0xffff00/4)
@@ -599,7 +615,7 @@ ioport_constructor gba_rom_yoshiug_device::device_input_ports() const
}
-READ32_MEMBER(gba_rom_yoshiug_device::read_tilt)
+uint32_t gba_rom_yoshiug_device::read_tilt(offs_t offset, uint32_t mem_mask)
{
switch (offset)
{
@@ -625,7 +641,7 @@ READ32_MEMBER(gba_rom_yoshiug_device::read_tilt)
return 0xffffffff;
}
-WRITE32_MEMBER(gba_rom_yoshiug_device::write_tilt)
+void gba_rom_yoshiug_device::write_tilt(offs_t offset, uint32_t data)
{
switch (offset)
{
@@ -728,7 +744,7 @@ void gba_rom_boktai_device::gpio_dev_write(uint16_t data, int gpio_dirs)
the cart "range" is accessible...)
-------------------------------------------------*/
-WRITE32_MEMBER(gba_rom_3dmatrix_device::write_mapper)
+void gba_rom_3dmatrix_device::write_mapper(offs_t offset, uint32_t data)
{
//printf("mapper write 0x%.8X - 0x%X\n", offset, data); fflush(stdout);
switch (offset & 3)
@@ -1060,7 +1076,7 @@ void gba_eeprom_device::write(uint32_t data)
if (m_bits == 0)
{
- osd_printf_verbose("%s: EEPROM: %02x to %x\n", machine().describe_context().c_str(), m_eep_data, m_addr);
+ osd_printf_verbose("%s: EEPROM: %02x to %x\n", machine().describe_context(), m_eep_data, m_addr);
if (m_addr >= m_data_size)
fatalerror("eeprom: invalid address (%x)\n", m_addr);
diff --git a/src/devices/bus/gba/rom.h b/src/devices/bus/gba/rom.h
index 7dc4c060f97..b9ffbef021e 100644
--- a/src/devices/bus/gba/rom.h
+++ b/src/devices/bus/gba/rom.h
@@ -91,10 +91,10 @@ public:
gba_rom_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
// reading and writing
- virtual DECLARE_READ32_MEMBER(read_rom) override { return m_rom[offset]; }
+ virtual uint32_t read_rom(offs_t offset) override { return m_rom[offset]; }
- virtual DECLARE_READ32_MEMBER(read_gpio) override;
- virtual DECLARE_WRITE32_MEMBER(write_gpio) override;
+ virtual uint32_t read_gpio(offs_t offset, uint32_t mem_mask = ~0) override;
+ virtual void write_gpio(offs_t offset, uint32_t data, uint32_t mem_mask = ~0) override;
virtual uint16_t gpio_dev_read(int gpio_dirs) { return 0; }
virtual void gpio_dev_write(uint16_t data, int gpio_dirs) { }
@@ -103,8 +103,8 @@ protected:
gba_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 void device_start() override ATTR_COLD;
+ virtual void device_reset() override ATTR_COLD;
private:
uint16_t m_gpio_regs[4];
@@ -121,8 +121,8 @@ public:
gba_rom_sram_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
// reading and writing
- virtual DECLARE_READ32_MEMBER(read_ram) override;
- virtual DECLARE_WRITE32_MEMBER(write_ram) override;
+ virtual uint32_t read_ram(offs_t offset, uint32_t mem_mask = ~0) override;
+ virtual void write_ram(offs_t offset, uint32_t data, uint32_t mem_mask = ~0) override;
protected:
gba_rom_sram_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock);
@@ -137,8 +137,13 @@ public:
// construction/destruction
gba_rom_drilldoz_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
+protected:
// device-level overrides
+ virtual void device_start() override ATTR_COLD;
virtual void gpio_dev_write(uint16_t data, int gpio_dirs) override;
+
+private:
+ output_finder<> m_rumble;
};
@@ -150,17 +155,19 @@ public:
// construction/destruction
gba_rom_wariotws_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
- virtual ioport_constructor device_input_ports() const override;
+ virtual ioport_constructor device_input_ports() const override ATTR_COLD;
virtual uint16_t gpio_dev_read(int gpio_dirs) override;
virtual void gpio_dev_write(uint16_t data, int gpio_dirs) override;
protected:
// device-level overrides
- virtual void device_start() override;
- virtual void device_reset() override;
+ virtual void device_start() override ATTR_COLD;
+ virtual void device_reset() override ATTR_COLD;
private:
+ output_finder<> m_rumble;
+
uint8_t m_last_val;
int m_counter;
required_ioport m_gyro_z;
@@ -176,16 +183,16 @@ public:
gba_rom_flash_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
// reading and writing
- virtual DECLARE_READ32_MEMBER(read_ram) override;
- virtual DECLARE_WRITE32_MEMBER(write_ram) override;
+ virtual uint32_t read_ram(offs_t offset, uint32_t mem_mask = ~0) override;
+ virtual void write_ram(offs_t offset, uint32_t data, uint32_t mem_mask = ~0) override;
protected:
gba_rom_flash_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock);
- virtual void device_reset() override;
+ virtual void device_reset() override ATTR_COLD;
// device-level overrides
- virtual void device_add_mconfig(machine_config &config) override;
+ virtual void device_add_mconfig(machine_config &config) override ATTR_COLD;
//uint32_t m_flash_size;
uint32_t m_flash_mask;
@@ -206,7 +213,7 @@ public:
virtual void gpio_dev_write(uint16_t data, int gpio_dirs) override;
protected:
- virtual void device_start() override;
+ virtual void device_start() override ATTR_COLD;
private:
std::unique_ptr<gba_s3511_device> m_rtc;
@@ -222,16 +229,16 @@ public:
gba_rom_flash1m_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
// reading and writing
- virtual DECLARE_READ32_MEMBER(read_ram) override;
- virtual DECLARE_WRITE32_MEMBER(write_ram) override;
+ virtual uint32_t read_ram(offs_t offset, uint32_t mem_mask = ~0) override;
+ virtual void write_ram(offs_t offset, uint32_t data, uint32_t mem_mask = ~0) override;
protected:
gba_rom_flash1m_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock);
- virtual void device_reset() override;
+ virtual void device_reset() override ATTR_COLD;
// device-level overrides
- virtual void device_add_mconfig(machine_config &config) override;
+ virtual void device_add_mconfig(machine_config &config) override ATTR_COLD;
//uint32_t m_flash_size;
uint32_t m_flash_mask;
@@ -252,7 +259,7 @@ public:
virtual void gpio_dev_write(uint16_t data, int gpio_dirs) override;
protected:
- virtual void device_start() override;
+ virtual void device_start() override ATTR_COLD;
private:
std::unique_ptr<gba_s3511_device> m_rtc;
@@ -268,14 +275,14 @@ public:
gba_rom_eeprom_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
// reading and writing
- virtual DECLARE_READ32_MEMBER(read_ram) override;
- virtual DECLARE_WRITE32_MEMBER(write_ram) override;
+ virtual uint32_t read_ram(offs_t offset, uint32_t mem_mask = ~0) override;
+ virtual void write_ram(offs_t offset, uint32_t data, uint32_t mem_mask = ~0) override;
protected:
gba_rom_eeprom_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_start() override ATTR_COLD;
private:
std::unique_ptr<gba_eeprom_device> m_eeprom;
@@ -291,15 +298,15 @@ public:
gba_rom_yoshiug_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;
+ virtual ioport_constructor device_input_ports() const override ATTR_COLD;
// reading and writing
- virtual DECLARE_READ32_MEMBER(read_tilt) override;
- virtual DECLARE_WRITE32_MEMBER(write_tilt) override;
+ virtual uint32_t read_tilt(offs_t offset, uint32_t mem_mask = ~0) override;
+ virtual void write_tilt(offs_t offset, uint32_t data) override;
protected:
- virtual void device_start() override;
- virtual void device_reset() override;
+ virtual void device_start() override ATTR_COLD;
+ virtual void device_reset() override ATTR_COLD;
private:
int m_tilt_ready;
@@ -318,14 +325,14 @@ public:
gba_rom_eeprom64_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
// reading and writing
- virtual DECLARE_READ32_MEMBER(read_ram) override;
- virtual DECLARE_WRITE32_MEMBER(write_ram) override;
+ virtual uint32_t read_ram(offs_t offset, uint32_t mem_mask = ~0) override;
+ virtual void write_ram(offs_t offset, uint32_t data, uint32_t mem_mask = ~0) override;
protected:
gba_rom_eeprom64_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_start() override ATTR_COLD;
std::unique_ptr<gba_eeprom_device> m_eeprom;
};
@@ -340,14 +347,14 @@ public:
gba_rom_boktai_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;
+ virtual ioport_constructor device_input_ports() const override ATTR_COLD;
virtual uint16_t gpio_dev_read(int gpio_dirs) override;
virtual void gpio_dev_write(uint16_t data, int gpio_dirs) override;
private:
- virtual void device_start() override;
- virtual void device_reset() override;
+ virtual void device_start() override ATTR_COLD;
+ virtual void device_reset() override ATTR_COLD;
std::unique_ptr<gba_s3511_device> m_rtc;
required_ioport m_sensor;
@@ -365,12 +372,12 @@ public:
gba_rom_3dmatrix_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
// reading and writing
- virtual DECLARE_WRITE32_MEMBER(write_mapper) override;
+ virtual void write_mapper(offs_t offset, uint32_t data) override;
protected:
// device-level overrides
- virtual void device_start() override;
- virtual void device_reset() override;
+ virtual void device_start() override ATTR_COLD;
+ virtual void device_reset() override ATTR_COLD;
private:
uint32_t m_src, m_dst, m_nblock;
diff --git a/src/devices/bus/generic/ram.h b/src/devices/bus/generic/ram.h
index 5cd8c8092b0..6da03757d5c 100644
--- a/src/devices/bus/generic/ram.h
+++ b/src/devices/bus/generic/ram.h
@@ -22,7 +22,7 @@ protected:
generic_ram_plain_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock, uint32_t size);
// device-level overrides
- virtual void device_start() override;
+ virtual void device_start() override ATTR_COLD;
private:
uint32_t m_size;
@@ -43,7 +43,7 @@ protected:
generic_ram_linear_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock, uint32_t size);
// device-level overrides
- virtual void device_start() override;
+ virtual void device_start() override ATTR_COLD;
private:
uint32_t m_size;
diff --git a/src/devices/bus/generic/slot.cpp b/src/devices/bus/generic/slot.cpp
index 557e1d8dcef..f2e86809a66 100644
--- a/src/devices/bus/generic/slot.cpp
+++ b/src/devices/bus/generic/slot.cpp
@@ -18,12 +18,20 @@
e.g. APF cart slot device for an example of a simple device with multiple
pcbs supported)
+ TODO:
+ - add support for hotswapping (ie. don't force a hard reset), it's doable for
+ generic rom cartridges, but then you still can't swap from empty slot
+
***********************************************************************************************************/
#include "emu.h"
#include "slot.h"
+#define VERBOSE 1
+#include "logmacro.h"
+
+
//**************************************************************************
// GLOBAL VARIABLES
//**************************************************************************
@@ -32,98 +40,127 @@ DEFINE_DEVICE_TYPE(GENERIC_SOCKET, generic_socket_device, "generic_socket", "Gen
DEFINE_DEVICE_TYPE(GENERIC_CARTSLOT, generic_cartslot_device, "generic_cartslot", "Generic Cartridge Slot")
-//-------------------------------------------------
-// device_generic_cart_interface - constructor
-//-------------------------------------------------
+//**************************************************************************
+// device_generic_cart_interface
+//**************************************************************************
-device_generic_cart_interface::device_generic_cart_interface(const machine_config &mconfig, device_t &device)
- : device_slot_card_interface(mconfig, device),
- m_rom(nullptr),
- m_rom_size(0),
- m_region(*this, DEVICE_SELF)
+device_generic_cart_interface::device_generic_cart_interface(machine_config const &mconfig, device_t &device) :
+ device_interface(device, "genslot"),
+ m_region(*this, DEVICE_SELF),
+ m_ram(),
+ m_rom(nullptr),
+ m_rom_size(0)
{
}
+device_generic_cart_interface::~device_generic_cart_interface()
+{
+}
-//-------------------------------------------------
-// ~device_generic_cart_interface - destructor
-//-------------------------------------------------
+u8 device_generic_cart_interface::read_rom(offs_t offset)
+{
+ return 0xff;
+}
-device_generic_cart_interface::~device_generic_cart_interface()
+u16 device_generic_cart_interface::read16_rom(offs_t offset, u16 mem_mask)
{
+ return 0xffff;
}
-//-------------------------------------------------
-// rom_alloc - alloc the space for the cart
-//-------------------------------------------------
+u32 device_generic_cart_interface::read32_rom(offs_t offset, u32 mem_mask)
+{
+ return 0xffffffff;
+}
-void device_generic_cart_interface::rom_alloc(size_t size, int width, endianness_t endian, const char *tag)
+u8 device_generic_cart_interface::read_ram(offs_t offset)
{
- if (m_rom == nullptr)
- {
- m_rom = device().machine().memory().region_alloc(std::string(tag).append(GENERIC_ROM_REGION_TAG).c_str(), size, width, endian)->base();
- m_rom_size = size;
- }
+ return 0xff;
}
+void device_generic_cart_interface::write_ram(offs_t offset, u8 data)
+{
+}
-//-------------------------------------------------
-// ram_alloc - alloc the space for the ram
-//-------------------------------------------------
+void device_generic_cart_interface::rom_alloc(u32 size, int width, endianness_t endian, char const *tag)
+{
+ if (m_rom)
+ {
+ throw emu_fatalerror(
+ "%s: Request to allocate ROM when already allocated (allocated size %u, requested size %u)\n",
+ device().tag(),
+ m_rom_size,
+ size);
+ }
-void device_generic_cart_interface::ram_alloc(uint32_t size)
+ 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, size, width, endian)->base();
+ m_rom_size = size;
+}
+
+void device_generic_cart_interface::ram_alloc(u32 size)
{
+ if (!m_ram.empty())
+ {
+ throw emu_fatalerror(
+ "%s: Request to allocate RAM when already allocated (allocated size %u, requested size %u)\n",
+ device().tag(),
+ m_ram.size(),
+ size);
+ }
+
+ device().logerror("Allocating %u bytes of RAM\n", size);
m_ram.resize(size);
}
-
//**************************************************************************
-// LIVE DEVICE
+// generic_slot_device
//**************************************************************************
-//-------------------------------------------------
-// generic_slot_device - constructor
-//-------------------------------------------------
-generic_slot_device::generic_slot_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock) :
+generic_slot_device::generic_slot_device(machine_config const &mconfig, device_type type, char const *tag, device_t *owner, u32 clock) :
device_t(mconfig, type, tag, owner, clock),
- device_image_interface(mconfig, *this),
- device_slot_interface(mconfig, *this),
+ device_rom_image_interface(mconfig, *this),
+ device_single_card_slot_interface<device_generic_cart_interface>(mconfig, *this),
m_interface(nullptr),
m_default_card("rom"),
m_extensions("bin"),
- m_must_be_loaded(false),
m_width(GENERIC_ROM8_WIDTH),
m_endianness(ENDIANNESS_LITTLE),
- m_cart(nullptr)
+ m_cart(nullptr),
+ m_device_image_load(*this),
+ m_device_image_unload(*this)
{
}
-generic_socket_device::generic_socket_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
- : generic_slot_device(mconfig, GENERIC_SOCKET, tag, owner, clock)
+generic_socket_device::generic_socket_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) :
+ generic_slot_device(mconfig, GENERIC_SOCKET, tag, owner, clock)
{
}
-generic_cartslot_device::generic_cartslot_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
- : generic_slot_device(mconfig, GENERIC_CARTSLOT, tag, owner, clock)
+generic_cartslot_device::generic_cartslot_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) :
+ generic_slot_device(mconfig, GENERIC_CARTSLOT, tag, owner, clock)
{
}
-//-------------------------------------------------
-// generic_slot_device - destructor
-//-------------------------------------------------
-
generic_slot_device::~generic_slot_device()
{
}
-//-------------------------------------------------
-// device_start - device-specific startup
-//-------------------------------------------------
+generic_socket_device::~generic_socket_device()
+{
+}
+
+generic_cartslot_device::~generic_cartslot_device()
+{
+}
void generic_slot_device::device_start()
{
- m_cart = dynamic_cast<device_generic_cart_interface *>(get_card_device());
+ m_cart = get_card_device();
+ m_device_image_load.resolve();
+ m_device_image_unload.resolve();
}
@@ -131,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)
+ {
+ return std::make_pair(std::error_condition(), std::string());
+ }
+ else if (!m_device_image_load.isnull())
{
- if (!m_device_image_load.isnull())
- return m_device_image_load(*this);
- else
- {
- uint32_t len = common_get_size("rom");
+ 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;
}
@@ -185,7 +223,7 @@ std::string generic_slot_device::get_default_card_software(get_default_card_soft
for fullpath and for softlist
-------------------------------------------------*/
-uint32_t generic_slot_device::common_get_size(const char *region)
+u32 generic_slot_device::common_get_size(char const *region)
{
// if we are loading from softlist, you have to specify a region
assert(!loaded_through_softlist() || (region != nullptr));
@@ -198,7 +236,7 @@ uint32_t generic_slot_device::common_get_size(const char *region)
for fullpath and for softlist
-------------------------------------------------*/
-void generic_slot_device::common_load_rom(uint8_t *ROM, uint32_t len, const char *region)
+void generic_slot_device::common_load_rom(u8 *ROM, u32 len, char const *region)
{
// basic sanity check
assert((ROM != nullptr) && (len > 0));
@@ -216,7 +254,7 @@ void generic_slot_device::common_load_rom(uint8_t *ROM, uint32_t len, const char
read_rom
-------------------------------------------------*/
-uint8_t generic_slot_device::read_rom(offs_t offset)
+u8 generic_slot_device::read_rom(offs_t offset)
{
if (m_cart)
return m_cart->read_rom(offset);
@@ -228,7 +266,7 @@ uint8_t generic_slot_device::read_rom(offs_t offset)
read16_rom
-------------------------------------------------*/
-uint16_t generic_slot_device::read16_rom(offs_t offset, uint16_t mem_mask)
+u16 generic_slot_device::read16_rom(offs_t offset, u16 mem_mask)
{
if (m_cart)
return m_cart->read16_rom(offset, mem_mask);
@@ -240,7 +278,7 @@ uint16_t generic_slot_device::read16_rom(offs_t offset, uint16_t mem_mask)
read32_rom
-------------------------------------------------*/
-uint32_t generic_slot_device::read32_rom(offs_t offset, uint32_t mem_mask)
+u32 generic_slot_device::read32_rom(offs_t offset, u32 mem_mask)
{
if (m_cart)
return m_cart->read32_rom(offset, mem_mask);
@@ -252,7 +290,7 @@ uint32_t generic_slot_device::read32_rom(offs_t offset, uint32_t mem_mask)
read_ram
-------------------------------------------------*/
-uint8_t generic_slot_device::read_ram(offs_t offset)
+u8 generic_slot_device::read_ram(offs_t offset)
{
if (m_cart)
return m_cart->read_ram(offset);
@@ -264,7 +302,7 @@ uint8_t generic_slot_device::read_ram(offs_t offset)
write_ram
-------------------------------------------------*/
-void generic_slot_device::write_ram(offs_t offset, uint8_t data)
+void generic_slot_device::write_ram(offs_t offset, u8 data)
{
if (m_cart)
m_cart->write_ram(offset, data);
diff --git a/src/devices/bus/generic/slot.h b/src/devices/bus/generic/slot.h
index a67fd25b9e5..06bab9424cc 100644
--- a/src/devices/bus/generic/slot.h
+++ b/src/devices/bus/generic/slot.h
@@ -5,54 +5,158 @@
#pragma once
-#include "softlist_dev.h"
+#include "imagedev/cartrom.h"
+#include <cassert>
-/***************************************************************************
- TYPE DEFINITIONS
- ***************************************************************************/
+//**************************************************************************
+// MACROS
+//**************************************************************************
-// ======================> device_generic_cart_interface
+#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)
-class device_generic_cart_interface : public device_slot_card_interface
+#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
{
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_mask,
+ offs_t decode_offset,
+ offs_t base,
+ T &&install)
+ {
+ assert(!(decode_limit & base));
+ for (offs_t remain = length, start = 0U; remain && (decode_limit >= start); )
+ {
+ unsigned const msb(31 - count_leading_zeros_32(u32(remain)));
+ offs_t const chunk(offs_t(1) << msb);
+ offs_t range((chunk - 1) & decode_limit);
+ offs_t mirror(decode_limit & ~decode_mask & ~range);
+
+ // TODO: deal with small offsets - probably requires breaking into smaller chunks with mirror set
+ if (decode_offset & range)
+ throw emu_fatalerror("Can't deal with offset/size combination\n");
+
+ range = (range << Shift) | ((offs_t(1) << Shift) - 1);
+ mirror <<= Shift;
+ offs_t const begin(start << Shift);
+ offs_t const end(begin | range);
+ offs_t const src(start | ((chunk - 1) & decode_offset));
+
+ install(base | begin, base | end, mirror, src);
+
+ remain ^= chunk;
+ start ^= chunk;
+ }
+ }
+
+ // 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();
// reading and writing
- virtual uint8_t read_rom(offs_t offset) { return 0xff; }
- virtual uint16_t read16_rom(offs_t offset, uint16_t mem_mask) { return 0xffff; }
- virtual uint32_t read32_rom(offs_t offset, uint32_t mem_mask) { return 0xffffffff; }
+ virtual u8 read_rom(offs_t offset);
+ virtual u16 read16_rom(offs_t offset, u16 mem_mask);
+ virtual u32 read32_rom(offs_t offset, u32 mem_mask);
- virtual uint8_t read_ram(offs_t offset) { return 0xff; }
- virtual void write_ram(offs_t offset, uint8_t data) {}
+ virtual u8 read_ram(offs_t offset);
+ virtual void write_ram(offs_t offset, u8 data);
- virtual void rom_alloc(size_t size, int width, endianness_t end, const char *tag);
- virtual void ram_alloc(uint32_t size);
+ virtual void rom_alloc(u32 size, int width, endianness_t end, char const *tag);
+ virtual void ram_alloc(u32 size);
- uint8_t* get_rom_base() { return m_rom; }
- uint32_t get_rom_size() { return m_rom_size; }
+ u8 *get_rom_base() { return m_rom; }
+ u32 get_rom_size() { return m_rom_size; }
- uint8_t* get_region_base() { if (m_region.found()) return m_region->base(); return nullptr; }
- uint32_t get_region_size() { if (m_region.found()) return m_region->bytes(); return 0; }
+ u8 *get_region_base() { return m_region.found() ? m_region->base() : nullptr; }
+ u32 get_region_size() { return m_region.found() ? m_region->bytes() : 0U; }
- uint8_t* get_ram_base() { return &m_ram[0]; }
- uint32_t get_ram_size() { return m_ram.size(); }
+ u8 *get_ram_base() { return &m_ram[0]; }
+ u32 get_ram_size() { return m_ram.size(); }
void save_ram() { device().save_item(NAME(m_ram)); }
protected:
- device_generic_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;
+ device_generic_cart_interface(machine_config const &mconfig, device_t &device);
// this replaces m_rom for non-user configurable carts!
optional_memory_region m_region;
+
+ // internal state
+ std::vector<u8> m_ram;
+ u8 *m_rom;
+ u32 m_rom_size;
};
@@ -67,96 +171,84 @@ enum
-// ======================> generic_slot_device
-
class generic_slot_device : public device_t,
- public device_image_interface,
- public device_slot_interface
+ public device_rom_image_interface,
+ public device_single_card_slot_interface<device_generic_cart_interface>
{
public:
- // construction/destruction
- generic_slot_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock);
+ 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 = load_delegate(std::forward<T>(args)...); }
- template <typename... T> void set_device_unload(T &&... args) { m_device_image_unload = unload_delegate(std::forward<T>(args)...); }
+ template <typename... T> void set_device_load(T &&... args) { m_device_image_load.set(std::forward<T>(args)...); }
+ template <typename... T> void set_device_unload(T &&... args) { m_device_image_unload.set(std::forward<T>(args)...); }
- void set_interface(const char * interface) { m_interface = interface; }
- void set_default_card(const char * def) { m_default_card = def; }
- void set_extensions(const char * exts) { m_extensions = exts; }
- void set_must_be_loaded(bool mandatory) { m_must_be_loaded = mandatory; }
+ void set_interface(char const *interface) { m_interface = interface; }
+ void set_default_card(char const *def) { m_default_card = def; }
+ void set_extensions(char const *exts) { m_extensions = exts; }
void set_width(int width) { m_width = width; }
void set_endian(endianness_t end) { m_endianness = end; }
- // 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 void call_unload() override;
- virtual const software_list_loader &get_software_list_loader() const override { return rom_software_list_loader::instance(); }
-
- uint32_t common_get_size(const char *region);
- void common_load_rom(uint8_t *ROM, uint32_t len, const char *region);
-
- virtual iodevice_t image_type() const override { return IO_CARTSLOT; }
- virtual bool is_readable() const override { return true; }
- virtual bool is_writeable() const override { return false; }
- virtual bool is_creatable() const override { return false; }
- virtual bool must_be_loaded() const override { return m_must_be_loaded; }
- virtual bool is_reset_on_load() const override { return true; }
- virtual const char *image_interface() const override { return m_interface; }
- virtual const char *file_extensions() const override { return m_extensions; }
+ virtual bool is_reset_on_load() const noexcept override { return true; }
+ virtual char const *image_interface() const noexcept override { return m_interface; }
+ virtual char const *file_extensions() const noexcept override { return m_extensions; }
// slot interface overrides
virtual std::string get_default_card_software(get_default_card_software_hook &hook) const override;
+ u32 common_get_size(char const *region);
+ void common_load_rom(u8 *ROM, u32 len, char const *region);
+
// reading and writing
- virtual uint8_t read_rom(offs_t offset);
- virtual uint16_t read16_rom(offs_t offset, uint16_t mem_mask = 0xffff);
- virtual uint32_t read32_rom(offs_t offset, uint32_t mem_mask = 0xffffffff);
+ virtual u8 read_rom(offs_t offset);
+ virtual u16 read16_rom(offs_t offset, u16 mem_mask = 0xffff);
+ virtual u32 read32_rom(offs_t offset, u32 mem_mask = 0xffffffff);
- virtual uint8_t read_ram(offs_t offset);
- virtual void write_ram(offs_t offset, uint8_t data);
+ virtual u8 read_ram(offs_t offset);
+ virtual void write_ram(offs_t offset, u8 data);
- virtual void rom_alloc(size_t size, int width, endianness_t end) { if (m_cart) m_cart->rom_alloc(size, width, end, tag()); }
- virtual void ram_alloc(uint32_t size) { if (m_cart) m_cart->ram_alloc(size); }
+ virtual void rom_alloc(u32 size, int width, endianness_t end) { if (m_cart) m_cart->rom_alloc(size, width, end, tag()); }
+ virtual void ram_alloc(u32 size) { if (m_cart) m_cart->ram_alloc(size); }
- uint8_t* get_rom_base()
+ u8* get_rom_base()
{
- if (m_cart)
- {
- if (!user_loadable())
- return m_cart->get_region_base();
- else
- return m_cart->get_rom_base();
- }
- return nullptr;
+ if (!m_cart)
+ return nullptr;
+ else if (!user_loadable())
+ return m_cart->get_region_base();
+ else
+ return m_cart->get_rom_base();
}
- uint32_t get_rom_size()
+ u32 get_rom_size()
{
- if (m_cart)
- {
- if (!user_loadable())
- return m_cart->get_region_size();
- else
- return m_cart->get_rom_size();
- }
- return 0;
+ if (!m_cart)
+ return 0U;
+ else if (!user_loadable())
+ return m_cart->get_region_size();
+ else
+ return m_cart->get_rom_size();
}
- uint8_t* get_ram_base() { if (m_cart) return m_cart->get_ram_base(); return nullptr; }
+ u8 *get_ram_base() { return m_cart ? m_cart->get_ram_base() : nullptr; }
void save_ram() { if (m_cart && m_cart->get_ram_size()) m_cart->save_ram(); }
protected:
- const char *m_interface;
- const char *m_default_card;
- const char *m_extensions;
- bool m_must_be_loaded;
- int m_width;
+ generic_slot_device(machine_config const &mconfig, device_type type, char const *tag, device_t *owner, u32 clock);
+
+ // device-level overrides
+ virtual void device_start() override ATTR_COLD;
+
+ char const *m_interface;
+ char const *m_default_card;
+ char const *m_extensions;
+ int m_width;
endianness_t m_endianness;
- device_generic_cart_interface *m_cart;
- load_delegate m_device_image_load;
+ device_generic_cart_interface *m_cart;
+ load_delegate m_device_image_load;
unload_delegate m_device_image_unload;
};
@@ -164,8 +256,8 @@ class generic_socket_device : public generic_slot_device
{
public:
template <typename T>
- generic_socket_device(const machine_config &mconfig, const char *tag, device_t *owner, T &&opts, const char *intf, const char *exts = nullptr)
- : generic_socket_device(mconfig, tag, owner, (uint32_t)0)
+ generic_socket_device(machine_config const &mconfig, char const *tag, device_t *owner, T &&opts, char const *intf, char const *exts = nullptr)
+ : generic_socket_device(mconfig, tag, owner, u32(0))
{
opts(*this);
set_fixed(false);
@@ -174,17 +266,19 @@ public:
set_extensions(exts);
}
- generic_socket_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock = 0);
+ generic_socket_device(machine_config const &mconfig, char const *tag, device_t *owner, u32 clock = 0);
+ virtual ~generic_socket_device();
- virtual iodevice_t image_type() const override { return IO_ROM; }
+ virtual const char *image_type_name() const noexcept override { return "romimage"; }
+ virtual const char *image_brief_type_name() const noexcept override { return "rom"; }
};
class generic_cartslot_device : public generic_slot_device
{
public:
template <typename T>
- generic_cartslot_device(const machine_config &mconfig, const char *tag, device_t *owner, T &&opts, const char *intf, const char *exts = nullptr)
- : generic_cartslot_device(mconfig, tag, owner, (uint32_t)0)
+ generic_cartslot_device(machine_config const &mconfig, char const *tag, device_t *owner, T &&opts, char const *intf, char const *exts = nullptr)
+ : generic_cartslot_device(mconfig, tag, owner, u32(0))
{
opts(*this);
set_fixed(false);
@@ -193,9 +287,11 @@ public:
set_extensions(exts);
}
- generic_cartslot_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock = 0);
+ generic_cartslot_device(machine_config const &mconfig, char const *tag, device_t *owner, u32 clock = 0);
+ virtual ~generic_cartslot_device();
- virtual iodevice_t image_type() const override { return IO_CARTSLOT; }
+ virtual const char *image_type_name() const noexcept override { return "cartridge"; }
+ virtual const char *image_brief_type_name() const noexcept override { return "cart"; }
};
@@ -203,9 +299,4 @@ public:
DECLARE_DEVICE_TYPE(GENERIC_SOCKET, generic_socket_device)
DECLARE_DEVICE_TYPE(GENERIC_CARTSLOT, generic_cartslot_device)
-
-/***************************************************************************
- DEVICE CONFIGURATION MACROS
- ***************************************************************************/
-
#endif // MAME_BUS_GENERIC_SLOT_H
diff --git a/src/devices/bus/gio64/gio64.cpp b/src/devices/bus/gio64/gio64.cpp
index 20caf53124b..ccd309251eb 100644
--- a/src/devices/bus/gio64/gio64.cpp
+++ b/src/devices/bus/gio64/gio64.cpp
@@ -21,24 +21,16 @@ void gio64_cards(device_slot_interface &device)
DEFINE_DEVICE_TYPE(GIO64_SLOT, gio64_slot_device, "gio64_slot", "SGI GIO64 Slot")
-gio64_slot_device::gio64_slot_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
- : gio64_slot_device(mconfig, GIO64_SLOT, tag, owner, clock)
-{
-}
-
-gio64_slot_device::gio64_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)
+gio64_slot_device::gio64_slot_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock, slot_type_t slot_type)
+ : device_t(mconfig, GIO64_SLOT, tag, owner, clock)
, device_slot_interface(mconfig, *this)
, m_gio64(*this, finder_base::DUMMY_TAG)
- , m_slot_type(GIO64_SLOT_COUNT)
+ , m_slot_type(slot_type)
{
}
void gio64_slot_device::device_validity_check(validity_checker &valid) const
{
- if (m_slot_type == GIO64_SLOT_COUNT)
- osd_printf_error("Slot type not defined\n");
-
device_t *const card(get_card_device());
if (card && !dynamic_cast<device_gio64_card_interface *>(card))
osd_printf_error("Card device %s (%s) does not implement device_gio64_card_interface\n", card->tag(), card->name());
@@ -76,43 +68,24 @@ gio64_device::gio64_device(const machine_config &mconfig, const char *tag, devic
gio64_device::gio64_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_space_config("GIO64 Space", ENDIANNESS_BIG, 64, 32, 0, address_map_constructor())
- , m_maincpu(*this, finder_base::DUMMY_TAG)
- , m_interrupt_cb{{*this}, {*this}, {*this}}
+ , m_space_config("gio64", ENDIANNESS_BIG, 64, 32, 0)
+ , m_interrupt_cb(*this)
{
}
-void gio64_device::device_resolve_objects()
-{
- for (auto &cb : m_interrupt_cb)
- cb.resolve_safe();
-}
-
void gio64_device::device_start()
{
std::fill(std::begin(m_device_list), std::end(m_device_list), nullptr);
-
- m_space = &space(0);
- m_space->install_readwrite_handler(0x00000000, 0x003fffff, read64_delegate(FUNC(gio64_device::no_gfx_r), this), write64_delegate(FUNC(gio64_device::no_gfx_w), this));
- m_space->install_readwrite_handler(0x00400000, 0x005fffff, read64_delegate(FUNC(gio64_device::no_exp0_r), this), write64_delegate(FUNC(gio64_device::no_exp0_w), this));
- m_space->install_readwrite_handler(0x00600000, 0x009fffff, read64_delegate(FUNC(gio64_device::no_exp1_r), this), write64_delegate(FUNC(gio64_device::no_exp1_w), this));
}
-READ64_MEMBER(gio64_device::no_gfx_r) { return ~0ULL; }
-READ64_MEMBER(gio64_device::no_exp0_r) { return ~0ULL; }
-READ64_MEMBER(gio64_device::no_exp1_r) { return ~0ULL; }
-WRITE64_MEMBER(gio64_device::no_gfx_w) { }
-WRITE64_MEMBER(gio64_device::no_exp0_w) { }
-WRITE64_MEMBER(gio64_device::no_exp1_w) { }
-
-READ64_MEMBER(gio64_device::read)
+u64 gio64_device::read(offs_t offset, u64 mem_mask)
{
- return m_space->read_qword(offset << 3, mem_mask);
+ return space(0).read_qword(offset << 3, mem_mask);
}
-WRITE64_MEMBER(gio64_device::write)
+void gio64_device::write(offs_t offset, u64 data, u64 mem_mask)
{
- m_space->write_qword(offset << 3, data, mem_mask);
+ space(0).write_qword(offset << 3, data, mem_mask);
}
device_gio64_card_interface *gio64_device::get_gio64_card(int slot)
@@ -130,20 +103,10 @@ device_gio64_card_interface *gio64_device::get_gio64_card(int slot)
return nullptr;
}
-void gio64_device::add_gio64_card(gio64_slot_device::slot_type_t slot_type, device_gio64_card_interface *card)
-{
- assert(slot_type >= 0 && slot_type < gio64_slot_device::GIO64_SLOT_COUNT);
- m_device_list[slot_type] = card;
- card->install_device();
-}
-
-
device_gio64_card_interface::device_gio64_card_interface(const machine_config &mconfig, device_t &device)
- : device_slot_card_interface(mconfig, device)
+ : device_interface(device, "sgigio64")
, m_gio64(nullptr)
- , m_gio64_slottag(nullptr)
- , m_slot_type(gio64_slot_device::GIO64_SLOT_COUNT)
{
}
@@ -151,14 +114,8 @@ device_gio64_card_interface::~device_gio64_card_interface()
{
}
-void device_gio64_card_interface::interface_validity_check(validity_checker &valid) const
-{
-}
-
void device_gio64_card_interface::interface_pre_start()
{
- device_slot_card_interface::interface_pre_start();
-
if (!m_gio64)
{
fatalerror("Can't find SGI GIO64 device\n");
@@ -168,13 +125,9 @@ void device_gio64_card_interface::interface_pre_start()
throw device_missing_dependencies();
}
-void device_gio64_card_interface::interface_post_start()
-{
- m_gio64->add_gio64_card(m_slot_type, this);
-}
-
void device_gio64_card_interface::set_gio64(gio64_device *gio64, gio64_slot_device::slot_type_t slot_type)
{
m_gio64 = gio64;
- m_slot_type = slot_type;
+
+ m_gio64->install_card(slot_type, *this, &device_gio64_card_interface::mem_map);
}
diff --git a/src/devices/bus/gio64/gio64.h b/src/devices/bus/gio64/gio64.h
index dd2c77aefc6..54642a66f2d 100644
--- a/src/devices/bus/gio64/gio64.h
+++ b/src/devices/bus/gio64/gio64.h
@@ -11,8 +11,6 @@
#pragma once
-#include "cpu/mips/r4000.h"
-
class gio64_device;
class gio64_slot_device : public device_t, public device_slot_interface
@@ -20,48 +18,40 @@ class gio64_slot_device : public device_t, public device_slot_interface
public:
enum slot_type_t : uint32_t
{
- GIO64_SLOT_GFX,
- GIO64_SLOT_EXP0,
- GIO64_SLOT_EXP1,
-
- GIO64_SLOT_COUNT
+ GIO64_SLOT_GFX = 0,
+ GIO64_SLOT_EXP0 = 1,
+ GIO64_SLOT_EXP1 = 2,
};
// construction/destruction
template <typename T, typename U>
gio64_slot_device(const machine_config &mconfig, const char *tag, device_t *owner, T &&gio64_tag, slot_type_t slot_type, U &&opts, const char *dflt)
- : gio64_slot_device(mconfig, tag, owner, (uint32_t)0)
+ : gio64_slot_device(mconfig, tag, owner, (uint32_t)0, slot_type)
{
option_reset();
opts(*this);
set_default_option(dflt);
set_fixed(false);
m_gio64.set_tag(std::forward<T>(gio64_tag));
- m_slot_type = slot_type;
}
- gio64_slot_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
+ 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:
- gio64_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;
+ virtual void device_resolve_objects() override ATTR_COLD;
+ virtual void device_start() override ATTR_COLD;
// configuration
required_device<gio64_device> m_gio64;
- slot_type_t m_slot_type;
-
- DECLARE_READ32_MEMBER(timeout_r);
- DECLARE_WRITE32_MEMBER(timeout_w);
+ slot_type_t const m_slot_type;
};
DECLARE_DEVICE_TYPE(GIO64_SLOT, gio64_slot_device)
// class representing interface-specific live GIO64 card
-class device_gio64_card_interface : public device_slot_card_interface
+class device_gio64_card_interface : public device_interface
{
friend class gio64_device;
public:
@@ -76,16 +66,9 @@ public:
protected:
device_gio64_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;
- virtual void interface_post_start() override;
- virtual void install_device() = 0;
-
- gio64_device &gio64() { assert(m_gio64); return *m_gio64; }
gio64_device *m_gio64;
- const char *m_gio64_slottag;
- gio64_slot_device::slot_type_t m_slot_type;
};
@@ -99,64 +82,47 @@ public:
gio64_device(const machine_config &mconfig, const char *tag, device_t *owner, T &&cpu_tag)
: gio64_device(mconfig, tag, owner, (uint32_t)0)
{
- set_cpu_tag(std::forward<T>(cpu_tag));
}
gio64_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
// inline configuration
- template <typename T> void set_cpu_tag(T &&tag) { m_maincpu.set_tag(std::forward<T>(tag)); }
template <int N> auto interrupt_cb() { return m_interrupt_cb[N].bind(); }
virtual space_config_vector memory_space_config() const override;
const address_space_config m_space_config;
- void add_gio64_card(gio64_slot_device::slot_type_t slot_type, device_gio64_card_interface *card);
device_gio64_card_interface *get_gio64_card(int slot);
- template<typename T> void install_graphics(T &device, void (T::*map)(class address_map &map), uint64_t unitmask = ~u64(0))
+ template<typename T> void install_card(gio64_slot_device::slot_type_t slot_type, T &device, void (T::*map)(class address_map &map))
{
- m_space->install_device(0x000000, 0x3fffff, device, map, unitmask);
+ m_device_list[slot_type] = &device;
+
+ switch (slot_type)
+ {
+ case gio64_slot_device::GIO64_SLOT_GFX: space(0).install_device(0x000000, 0x3fffff, device, map); break;
+ case gio64_slot_device::GIO64_SLOT_EXP0: space(0).install_device(0x400000, 0x5fffff, device, map); break;
+ case gio64_slot_device::GIO64_SLOT_EXP1: space(0).install_device(0x600000, 0x9fffff, device, map); break;
+ }
}
- template<typename T> void install_expansion(int index, T &device, void (T::*map)(class address_map &map), uint64_t unitmask = ~u64(0))
- {
- if (index == 0)
- m_space->install_device(0x400000, 0x5fffff, device, map, unitmask);
- else if (index == 1)
- m_space->install_device(0x600000, 0x9fffff, device, map, unitmask);
- else
- fatalerror("Invalid SGI GIO64 expansion slot index: %d\n", index);
- }
+ template <int N> void interrupt(int state) { m_interrupt_cb[N](state); }
- template <int N> DECLARE_WRITE_LINE_MEMBER(interrupt) { m_interrupt_cb[N](state); }
-
- DECLARE_READ64_MEMBER(read);
- DECLARE_WRITE64_MEMBER(write);
+ u64 read(offs_t offset, u64 mem_mask);
+ void write(offs_t offset, u64 data, u64 mem_mask);
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;
- virtual void device_start() override;
+ // device_t implementation
+ virtual void device_start() override ATTR_COLD;
// internal state
- required_device<r4000_base_device> m_maincpu;
- address_space *m_space;
-
device_gio64_card_interface *m_device_list[3];
private:
- devcb_write_line m_interrupt_cb[3];
-
- DECLARE_READ64_MEMBER(no_gfx_r);
- DECLARE_READ64_MEMBER(no_exp0_r);
- DECLARE_READ64_MEMBER(no_exp1_r);
- DECLARE_WRITE64_MEMBER(no_gfx_w);
- DECLARE_WRITE64_MEMBER(no_exp0_w);
- DECLARE_WRITE64_MEMBER(no_exp1_w);
+ devcb_write_line::array<3> m_interrupt_cb;
};
DECLARE_DEVICE_TYPE(GIO64, gio64_device)
@@ -164,4 +130,4 @@ DECLARE_DEVICE_TYPE(GIO64, gio64_device)
void gio64_cards(device_slot_interface &device);
-#endif // MAME_BUS_GIO_GIO_H
+#endif // MAME_BUS_GIO_GIO_H
diff --git a/src/devices/bus/gio64/newport.cpp b/src/devices/bus/gio64/newport.cpp
index 9d509a21560..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)
@@ -86,7 +86,7 @@ void xmap9_device::device_reset()
m_cursor_cmap = 0;
m_popup_cmap = 0;
m_mode_table_idx = 0;
- memset(m_mode_table, 0, sizeof(uint32_t) * ARRAY_LENGTH(m_mode_table));
+ std::fill(std::begin(m_mode_table), std::end(m_mode_table), 0);
}
void xmap9_device::serialize(FILE *file)
@@ -233,7 +233,7 @@ void cmap_device::device_reset()
{
m_status = 8;
m_palette_idx = 0;
- memset(m_palette, 0, sizeof(uint32_t) * ARRAY_LENGTH(m_palette));
+ std::fill(std::begin(m_palette), std::end(m_palette), 0);
}
void cmap_device::serialize(FILE *file)
@@ -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)
{
}
@@ -1111,7 +1109,7 @@ gio64_xl24_device::gio64_xl24_device(const machine_config &mconfig, const char *
void newport_base_device::device_start()
{
- m_dcb_timeout_timer = timer_alloc(DCB_TIMEOUT);
+ m_dcb_timeout_timer = timer_alloc(FUNC(newport_base_device::dcb_timeout_tick), this);
save_item(NAME(m_rex3.m_draw_mode0));
save_item(NAME(m_rex3.m_color_host));
@@ -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);
}
//-------------------------------------------------
@@ -1282,12 +1274,9 @@ void newport_base_device::stop_logging()
}
#endif
-void newport_base_device::device_timer(emu_timer &timer, device_timer_id id, int param, void *ptr)
+TIMER_CALLBACK_MEMBER(newport_base_device::dcb_timeout_tick)
{
- if (id == DCB_TIMEOUT)
- {
- m_rex3.m_status &= ~STATUS_BACKBUSY;
- }
+ m_rex3.m_status &= ~STATUS_BACKBUSY;
}
uint32_t newport_base_device::screen_update(screen_device &device, bitmap_rgb32 &bitmap, const rectangle &cliprect)
@@ -1302,7 +1291,7 @@ uint32_t newport_base_device::screen_update(screen_device &device, bitmap_rgb32
/* loop over rows and copy to the destination */
for (int y = cliprect.min_y, sy = y_start; y <= cliprect.max_y && sy < y_end; y++, sy++)
{
- uint32_t *dest = &bitmap.pix32(y, cliprect.min_x);
+ uint32_t *dest = &bitmap.pix(y, cliprect.min_x);
const uint32_t *src_rgbci = m_rb2->rgbci(y);
const uint32_t *src_cidaux = m_rb2->cidaux(y);
@@ -1708,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)
{
@@ -1718,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();
@@ -1729,7 +1718,7 @@ WRITE_LINE_MEMBER(newport_base_device::update_screen_size)
m_screen->set_visarea_full();
}
-READ64_MEMBER(newport_base_device::rex3_r)
+uint64_t newport_base_device::rex3_r(offs_t offset, uint64_t mem_mask)
{
uint64_t ret = 0;
switch (offset & ~(0x800/8))
@@ -2199,11 +2188,6 @@ READ64_MEMBER(newport_base_device::rex3_r)
return ret;
}
-uint32_t newport_base_device::do_endian_swap(uint32_t color)
-{
- return (color >> 24) | (color << 24) | ((color >> 8) & 0x0000ff00) | ((color << 8) & 0x00ff0000);
-}
-
uint32_t newport_base_device::get_host_color()
{
static const uint32_t s_color_masks[4] = { 0xf, 0xff, 0xfff, 0xffffffff };
@@ -2259,7 +2243,7 @@ uint32_t newport_base_device::get_host_color()
break;
}
if (BIT(m_rex3.m_draw_mode1, 11))
- color = do_endian_swap(color);
+ color = swapendian_int32(color);
return color;
}
@@ -2708,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;
@@ -2756,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;
@@ -2782,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;
@@ -2795,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;
@@ -2805,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;
@@ -2822,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;
@@ -2832,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;
}
@@ -2947,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;
@@ -3056,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;
@@ -3199,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
{
@@ -3305,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;
@@ -3318,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
@@ -3491,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;
@@ -3557,7 +3585,7 @@ void newport_base_device::write_y_end(int32_t val)
m_rex3.m_xy_end_i = (m_rex3.m_xy_end_i & 0xffff0000) | (uint16_t)m_rex3.m_y_end_i;
}
-WRITE64_MEMBER(newport_base_device::rex3_w)
+void newport_base_device::rex3_w(offs_t offset, uint64_t data, uint64_t mem_mask)
{
#if ENABLE_NEWVIEW_LOG
if (m_newview_log != nullptr)
@@ -3906,6 +3934,7 @@ WRITE64_MEMBER(newport_base_device::rex3_w)
{
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)
{
@@ -4436,11 +4465,6 @@ WRITE64_MEMBER(newport_base_device::rex3_w)
}
}
-void newport_base_device::install_device()
-{
- m_gio64->install_graphics(*this, &newport_base_device::mem_map);
-}
-
void newport_base_device::device_add_mconfig(machine_config &config)
{
VC2(config, m_vc2, 0);
diff --git a/src/devices/bus/gio64/newport.h b/src/devices/bus/gio64/newport.h
index 49e0af4e937..65a03476e35 100644
--- a/src/devices/bus/gio64/newport.h
+++ b/src/devices/bus/gio64/newport.h
@@ -8,8 +8,8 @@
*********************************************************************/
-#ifndef MAME_BUS_GIO_NEWPORT_H
-#define MAME_BUS_GIO_NEWPORT_H
+#ifndef MAME_BUS_GIO64_NEWPORT_H
+#define MAME_BUS_GIO64_NEWPORT_H
#pragma once
@@ -50,8 +50,8 @@ public:
private:
// device_t overrides
- virtual void device_start() override;
- virtual void device_reset() override;
+ virtual void device_start() override ATTR_COLD;
+ virtual void device_reset() override ATTR_COLD;
// Initializers
void set_revision(uint32_t revision) { m_revision = revision; }
@@ -98,11 +98,11 @@ public:
private:
// device_t overrides
- virtual void device_start() override;
- virtual void device_reset() override;
+ virtual void device_start() override ATTR_COLD;
+ virtual void device_reset() override ATTR_COLD;
// 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
@@ -149,8 +149,8 @@ public:
private:
// device_t overrides
- virtual void device_start() override;
- virtual void device_reset() override;
+ virtual void device_start() override ATTR_COLD;
+ virtual void device_reset() override ATTR_COLD;
enum
{
@@ -246,8 +246,8 @@ public:
private:
// device_t overrides
- virtual void device_start() override;
- virtual void device_reset() override;
+ virtual void device_start() override ATTR_COLD;
+ virtual void device_reset() override ATTR_COLD;
void logic_pixel(uint32_t src);
void store_pixel(uint32_t value);
@@ -292,16 +292,13 @@ class newport_base_device : public device_t
public:
newport_base_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock);
- // device_gio_slot_interface overrides
- virtual void install_device() override;
-
- DECLARE_READ64_MEMBER(rex3_r);
- DECLARE_WRITE64_MEMBER(rex3_w);
+ uint64_t rex3_r(offs_t offset, uint64_t mem_mask = ~0);
+ void rex3_w(offs_t offset, uint64_t data, uint64_t mem_mask = ~0);
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(); }
@@ -314,15 +311,14 @@ public:
protected:
// device_t overrides
- virtual void device_timer(emu_timer &timer, device_timer_id id, int param, void *ptr) override;
- virtual void device_add_mconfig(machine_config &config) override;
- virtual void device_start() override;
- virtual void device_reset() override;
+ 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;
void device_add_mconfig(machine_config &config, uint32_t xmap_revision, uint32_t cmap_revision, uint32_t global_mask);
void mem_map(address_map &map) override;
- static constexpr device_timer_id DCB_TIMEOUT = 0;
+ TIMER_CALLBACK_MEMBER(dcb_timeout_tick);
enum
{
@@ -479,8 +475,6 @@ protected:
uint32_t convert_8bpp_bgr_to_24bpp_rgb(uint8_t pix_in);
uint32_t convert_12bpp_bgr_to_24bpp_rgb(uint16_t pix_in);
- uint32_t do_endian_swap(uint32_t color);
-
struct bresenham_octant_info_t
{
int16_t incrx1;
@@ -490,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);
@@ -537,7 +532,7 @@ public:
gio64_xl8_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock = 0U);
protected:
- virtual void device_add_mconfig(machine_config &config) override;
+ virtual void device_add_mconfig(machine_config &config) override ATTR_COLD;
};
class gio64_xl24_device : public newport_base_device
@@ -546,10 +541,10 @@ public:
gio64_xl24_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock = 0U);
protected:
- virtual void device_add_mconfig(machine_config &config) override;
+ virtual void device_add_mconfig(machine_config &config) override ATTR_COLD;
};
DECLARE_DEVICE_TYPE(GIO64_XL8, gio64_xl8_device)
DECLARE_DEVICE_TYPE(GIO64_XL24, gio64_xl24_device)
-#endif // MAME_BUS_GIO_NEWPORT_H
+#endif // MAME_BUS_GIO64_NEWPORT_H
diff --git a/src/devices/bus/heathzenith/h19/tlb.cpp b/src/devices/bus/heathzenith/h19/tlb.cpp
new file mode 100644
index 00000000000..aefaeda33c4
--- /dev/null
+++ b/src/devices/bus/heathzenith/h19/tlb.cpp
@@ -0,0 +1,2170 @@
+// license:BSD-3-Clause
+// copyright-holders:Mark Garlanger
+/***************************************************************************
+
+ Heathkit Terminal Logic Board (TLB)
+
+ The board used in the H19 smart terminal designed and manufactured
+ by Heath Company. (and the identical Z19 sold by Zenith Data Systems)
+ This board is also used the Heath's H89 / H88, and ZDS's Z-89 and Z-90.
+
+ The keyboard consists of a 9x10 matrix connected to a MM5740AAC/N
+ mask-programmed keyboard controller. The output of this passes
+ through a rom.
+
+ Input can also come from the serial port.
+
+ Known Issues:
+ - With gp19
+ - 49/50 row mode only shows half the screen.
+ - In 49/50 row mode, character descenders are cut off.
+ - Screen saver does not disable the screen
+ - With Superset
+ - Screensaver freezes the screen instead of blanking the screen
+
+ Not Currently Implemented
+ - With Imaginator I-100
+ - Support for Tektronics Emulation (missing ROM image)
+ - With SigmaSoft IGC
+ - Interlace video support (with higher resolution)
+ - Joystick support
+ - Centronics support
+ - Lightpen support
+ - Alternate Font ROM support (missing ROM image)
+ - With Super19
+ - Interlace video
+ - Alternate Font19 alt 128 mode and extended 256 mode (missing ROM images)
+ - ANSI character set selection (missing ROM image)
+ - light pen support
+ - With UltraROM
+ - Interace mode
+
+****************************************************************************/
+/***************************************************************************
+
+ Memory Layout
+
+ The U435 three-to-eight line decoder uses A14 and A15 to generate
+ three memory address spaces:
+
+ Address Description
+ ----------------------------------------------------
+ 0x0000 Program ROM
+ 0x4000 Scratchpad RAM
+ 0xF800 (0xC000) Display Memory
+
+
+ Port Layout
+
+ Only address lines A5, A6, A7 are used by the U442 three-to-eight
+ line decoder
+
+ Address Description
+ ----------------------------------------------------
+ 0x00 Power-up configuration (primary - SW401)
+ 0x20 Power-up configuration (secondary - SW402)
+ 0x40 INS8250 ACE (communications)
+ 0x60 MC6845 CRT controller
+ 0x80 MM5740 Keyboard encoder
+ 0xA0 Keyboard status
+ 0xC0 Trigger key click
+ 0xE0 Trigger bell
+
+****************************************************************************/
+
+#include "emu.h"
+
+#include "tlb.h"
+
+#include <algorithm>
+
+#define LOG_REG (1U << 1) // Shows register setup
+
+//#define VERBOSE (LOG_REG)
+
+#include "logmacro.h"
+
+#define LOGREG(...) LOGMASKED(LOG_REG, __VA_ARGS__)
+
+#ifdef _MSC_VER
+#define FUNCNAME __func__
+#else
+#define FUNCNAME __PRETTY_FUNCTION__
+#endif
+
+// Clocks
+static constexpr XTAL MASTER_CLOCK = XTAL(12'288'000);
+
+// DOT clocks
+static constexpr XTAL BASE_DOT_CLOCK = MASTER_CLOCK;
+static constexpr XTAL GP19_DOT_CLOCK_1 = XTAL(20'282'000); // 132 columns
+static constexpr XTAL GP19_DOT_CLOCK_2 = XTAL(12'292'000); // 80 columns
+static constexpr XTAL GP19_DOT_CLOCK_3 = XTAL(10'644'000); // Graphics mode
+
+// Standard H19 used a 2.048 MHz clock for Z80
+static constexpr XTAL H19_CLOCK = MASTER_CLOCK / 6;
+static constexpr XTAL H19_3MHZ = MASTER_CLOCK / 4;
+static constexpr XTAL H19_4MHZ = MASTER_CLOCK / 3;
+static constexpr XTAL H19_6MHZ = MASTER_CLOCK / 2;
+
+static constexpr XTAL INS8250_CLOCK = MASTER_CLOCK / 4;
+
+// Beep Frequency is 1 KHz
+static constexpr XTAL H19_BEEP_FRQ = (H19_CLOCK / 2048);
+
+// Capacitor value in pF
+static constexpr u32 H19_KEY_DEBOUNCE_CAPACITOR = 5000;
+static const u32 MM5740_CLOCK = mm5740_device::calc_effective_clock_key_debounce(H19_KEY_DEBOUNCE_CAPACITOR);
+
+// Keyboard flag masks
+static constexpr u8 KB_STATUS_SHIFT_KEYS_MASK = 0x01;
+static constexpr u8 KB_STATUS_CONTROL_KEY_MASK = 0x10;
+static constexpr u8 KB_STATUS_KEYBOARD_STROBE_MASK = 0x80;
+
+DEFINE_DEVICE_TYPE(HEATH_TLB_CONNECTOR, heath_tlb_connector, "heath_tlb_connector", "Heath Terminal Logic board connector abstraction")
+
+DEFINE_DEVICE_TYPE(HEATH_TLB, heath_tlb_device, "heath_tlb", "Heath Terminal Logic Board")
+DEFINE_DEVICE_TYPE(HEATH_SUPER19, heath_super19_tlb_device, "heath_super19_tlb", "Heath Terminal Logic Board w/Super19 ROM")
+DEFINE_DEVICE_TYPE(HEATH_SUPERSET, heath_superset_tlb_device, "heath_superset_tlb", "Heath Terminal Logic Board w/Superset ROM")
+DEFINE_DEVICE_TYPE(HEATH_ULTRA, heath_ultra_tlb_device, "heath_ultra_tlb", "Heath Terminal Logic Board w/Ultra ROM")
+DEFINE_DEVICE_TYPE(HEATH_WATZ, heath_watz_tlb_device, "heath_watz_tlb", "Heath Terminal Logic Board w/Watzman ROM")
+DEFINE_DEVICE_TYPE(HEATH_GP19, heath_gp19_tlb_device, "heath_gp19_tlb", "Heath Terminal Logic Board plus Northwest Digital Systems GP-19")
+DEFINE_DEVICE_TYPE(HEATH_IMAGINATOR, heath_imaginator_tlb_device, "heath_imaginator_tlb", "Heath Terminal Logic Board plus Cleveland Codonics Imaginator I-100")
+
+// Devices for the terminal boards compatible with SigmaSoft IGC
+DEFINE_DEVICE_TYPE(HEATH_IGC, heath_igc_tlb_device, "heath_igc_tlb_device", "Heath Terminal Logic Board plus SigmaSoft Interactive Graphics Controller")
+DEFINE_DEVICE_TYPE(HEATH_IGC_SUPER19, heath_igc_super19_tlb_device, "heath_igc_super19_tlb_device", "Heath Terminal Logic Board w/ Super19 ROM plus SigmaSoft Interactive Graphics Controller")
+DEFINE_DEVICE_TYPE(HEATH_IGC_ULTRA, heath_igc_ultra_tlb_device, "heath_igc_ultra_tlb_device", "Heath Terminal Logic Board w/ Ultra ROM plus SigmaSoft Interactive Graphics Controller")
+DEFINE_DEVICE_TYPE(HEATH_IGC_WATZ, heath_igc_watz_tlb_device, "heath_igc_watz_tlb_device", "Heath Terminal Logic Board w/Watzman ROM plus SigmaSoft Interactive Graphics Controller")
+
+
+device_heath_tlb_card_interface::device_heath_tlb_card_interface(const machine_config &mconfig, device_t &device) :
+ device_interface(device, "heathtlbdevice"),
+ m_slot(dynamic_cast<heath_tlb_connector *>(device.owner()))
+{
+}
+
+
+/**
+ * original Heath H19 functionality
+ */
+heath_tlb_device::heath_tlb_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock) :
+ heath_tlb_device(mconfig, HEATH_TLB, tag, owner, clock)
+{
+}
+
+heath_tlb_device::heath_tlb_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, u32 clock) :
+ device_t(mconfig, type, tag, owner, clock),
+ device_heath_tlb_card_interface(mconfig, *this),
+ m_maincpu(*this, "maincpu"),
+ m_screen(*this, "screen"),
+ m_palette(*this, "palette"),
+ m_crtc(*this, "crtc"),
+ m_p_videoram(*this, "videoram"),
+ m_p_chargen(*this, "chargen"),
+ m_config(*this, "CONFIG"),
+ m_ace(*this, "ins8250"),
+ m_beep(*this, "beeper"),
+ m_mm5740(*this, "mm5740"),
+ m_kbdrom(*this, "keyboard"),
+ m_kbspecial(*this, "MODIFIERS"),
+ m_repeat_clock(*this, "repeatclock")
+{
+}
+
+void heath_tlb_device::check_beep_state()
+{
+ if (!m_key_click_active && !m_bell_active)
+ {
+ m_beep->set_state(0);
+ }
+}
+
+TIMER_CALLBACK_MEMBER(heath_tlb_device::key_click_off)
+{
+ m_key_click_active = false;
+
+ check_beep_state();
+}
+
+TIMER_CALLBACK_MEMBER(heath_tlb_device::bell_off)
+{
+ m_bell_active = false;
+
+ check_beep_state();
+}
+
+void heath_tlb_device::mem_map(address_map &map)
+{
+ map.unmap_value_high();
+
+ // H19 ROM
+ map(0x0000, 0x0fff).mirror(0x3000).rom();
+
+ // Scratchpad memory
+ map(0x4000, 0x40ff).mirror(0x3f00).ram();
+
+ // Video Memory
+ map(0xc000, 0xc7ff).mirror(0x3800).ram().share(m_p_videoram);
+}
+
+void heath_tlb_device::io_map(address_map &map)
+{
+ map.unmap_value_high();
+ map.global_mask(0xff);
+ map(0x00, 0x00).mirror(0x1f).portr("SW401");
+ map(0x20, 0x20).mirror(0x1f).portr("SW402");
+ map(0x40, 0x47).mirror(0x18).rw(m_ace, FUNC(ins8250_device::ins8250_r), FUNC(ins8250_device::ins8250_w));
+ map(0x60, 0x60).mirror(0x1a).select(0x04).w(FUNC(heath_tlb_device::crtc_addr_w));
+ map(0x61, 0x61).mirror(0x1a).select(0x04).rw(FUNC(heath_tlb_device::crtc_reg_r), FUNC(heath_tlb_device::crtc_reg_w));
+ map(0x80, 0x80).mirror(0x1f).r(FUNC(heath_tlb_device::kbd_key_r));
+ map(0xa0, 0xa0).mirror(0x1f).r(FUNC(heath_tlb_device::kbd_flags_r));
+ map(0xc0, 0xc0).mirror(0x1f).w(FUNC(heath_tlb_device::key_click_w));
+ map(0xe0, 0xe0).mirror(0x1f).w(FUNC(heath_tlb_device::bell_w));
+}
+
+void heath_tlb_device::device_start()
+{
+ save_item(NAME(m_transchar));
+ save_item(NAME(m_strobe));
+ save_item(NAME(m_key_click_active));
+ save_item(NAME(m_bell_active));
+ save_item(NAME(m_reset_pending));
+ save_item(NAME(m_right_shift));
+ save_item(NAME(m_reset_key));
+ save_item(NAME(m_keyboard_irq_raised));
+ save_item(NAME(m_serial_irq_raised));
+ save_item(NAME(m_break_key_irq_raised));
+ save_item(NAME(m_allow_vsync_nmi));
+
+ m_strobe = false;
+ m_key_click_active = false;
+ m_bell_active = false;
+ m_reset_pending = false;
+ m_right_shift = false;
+ m_reset_key = false;
+ m_keyboard_irq_raised = false;
+ m_serial_irq_raised = false;
+ m_break_key_irq_raised = false;
+ m_allow_vsync_nmi = false;
+
+ m_key_click_timer = timer_alloc(FUNC(heath_tlb_device::key_click_off), this);
+ m_bell_timer = timer_alloc(FUNC(heath_tlb_device::bell_off), this);
+
+ // Flip bits in font ROM to avoid having to flip them during scan out since some
+ // boards with graphics has the pixel graphic reversed from the font layout. Doing
+ // it for all devices for consistency.
+ for (size_t i = 0; i < m_p_chargen.length(); i++)
+ {
+ m_p_chargen[i] = bitswap<8>(m_p_chargen[i], 0, 1, 2, 3, 4, 5, 6, 7);
+ }
+}
+
+void heath_tlb_device::device_reset()
+{
+ m_strobe = false;
+ m_key_click_active = false;
+ m_bell_active = false;
+ m_allow_vsync_nmi = false;
+
+ ioport_value const cfg(m_config->read());
+
+ // CPU clock speed
+ switch (BIT(cfg, 0, 2))
+ {
+ case 0x01:
+ m_maincpu->set_clock(H19_3MHZ);
+ break;
+ case 0x02:
+ m_maincpu->set_clock(H19_4MHZ);
+ break;
+ case 0x03:
+ m_maincpu->set_clock(H19_6MHZ);
+ break;
+ case 0x00:
+ default:
+ // Standard Clock
+ m_maincpu->set_clock(H19_CLOCK);
+ break;
+ }
+
+ // Set screen color
+ switch (BIT(cfg, 2, 2))
+ {
+ case 0x01:
+ m_screen->set_color(rgb_t::white());
+ break;
+ case 0x02:
+ m_screen->set_color(rgb_t::amber());
+ break;
+ case 0x00:
+ default:
+ m_screen->set_color(rgb_t::green());
+ break;
+ }
+}
+
+void heath_tlb_device::key_click_w(u8 data)
+{
+ // Keyclick - 6 mSec
+ m_beep->set_state(1);
+ m_key_click_active = true;
+ m_key_click_timer->adjust(attotime::from_msec(6));
+}
+
+void heath_tlb_device::bell_w(u8 data)
+{
+ // Bell (^G) - 200 mSec
+ m_beep->set_state(1);
+ m_bell_active = true;
+ m_bell_timer->adjust(attotime::from_msec(200));
+}
+
+/**
+ * MM5740 B Mapping to the ROM address
+ */
+u16 heath_tlb_device::translate_mm5740_b(u16 b)
+{
+ return bitswap<9>(b, 7, 6, 8, 5, 4, 3, 2, 1, 0);
+}
+
+u8 heath_tlb_device::kbd_key_r()
+{
+ m_strobe = false;
+ m_keyboard_irq_raised = false;
+
+ set_irq_line();
+
+ // high bit is for control key pressed, this is handled in the ROM,
+ // no processing needed.
+ return m_transchar;
+}
+
+u8 heath_tlb_device::kbd_flags_r()
+{
+ u16 modifiers = m_kbspecial->read();
+ u8 rv = modifiers & 0x7e;
+
+ // check both shifts
+ if ((modifiers & 0x120) != 0x120)
+ {
+ rv |= KB_STATUS_SHIFT_KEYS_MASK;
+ }
+
+ if (!m_strobe)
+ {
+ rv |= KB_STATUS_KEYBOARD_STROBE_MASK;
+ }
+
+ return rv;
+}
+
+int heath_tlb_device::mm5740_shift_r()
+{
+ return ((m_kbspecial->read() & 0x120) != 0x120) ? 1 : 0;
+}
+
+int heath_tlb_device::mm5740_control_r()
+{
+ return (m_kbspecial->read() & KB_STATUS_CONTROL_KEY_MASK) ? 0 : 1;
+}
+
+void heath_tlb_device::mm5740_data_ready_w(int state)
+{
+ if (state)
+ {
+ u8 *decode = m_kbdrom->base();
+
+ m_transchar = decode[translate_mm5740_b(m_mm5740->b_r())];
+ m_strobe = true;
+ m_keyboard_irq_raised = true;
+
+ set_irq_line();
+ }
+}
+
+void heath_tlb_device::crtc_addr_w(offs_t reg, u8 val)
+{
+ m_allow_vsync_nmi = bool(BIT(reg, 2));
+
+ m_crtc->address_w(val);
+}
+
+u8 heath_tlb_device::crtc_reg_r(offs_t reg)
+{
+ if (!machine().side_effects_disabled())
+ {
+ m_allow_vsync_nmi = bool(BIT(reg, 2));
+ }
+
+ return m_crtc->register_r();
+}
+
+void heath_tlb_device::crtc_reg_w(offs_t reg, u8 val)
+{
+ m_allow_vsync_nmi = bool(BIT(reg, 2));
+
+ m_crtc->register_w(val);
+}
+
+void heath_tlb_device::crtc_vsync_w(int val)
+{
+ m_maincpu->set_input_line(INPUT_LINE_NMI, m_allow_vsync_nmi ? val : CLEAR_LINE);
+}
+
+void heath_tlb_device::serial_irq_w(int state)
+{
+ m_serial_irq_raised = bool(state);
+
+ set_irq_line();
+}
+
+void heath_tlb_device::set_irq_line()
+{
+ m_maincpu->set_input_line(INPUT_LINE_IRQ0,
+ (m_keyboard_irq_raised || m_serial_irq_raised || m_break_key_irq_raised) ?
+ ASSERT_LINE : CLEAR_LINE);
+}
+
+void heath_tlb_device::check_for_reset()
+{
+ if (m_reset_key && m_right_shift)
+ {
+ m_reset_pending = true;
+ m_slot->reset_out(1);
+ m_maincpu->set_input_line(INPUT_LINE_RESET, ASSERT_LINE);
+ }
+ else if (m_reset_pending)
+ {
+ m_reset_pending = false;
+ reset();
+ m_maincpu->set_input_line(INPUT_LINE_RESET, CLEAR_LINE);
+ m_slot->reset_out(0);
+ }
+}
+
+void heath_tlb_device::reset_key_w(int state)
+{
+ m_reset_key = (state == 0);
+
+ check_for_reset();
+}
+
+void heath_tlb_device::right_shift_w(int state)
+{
+ m_right_shift = (state == 0);
+
+ check_for_reset();
+}
+
+void heath_tlb_device::repeat_key_w(int state)
+{
+ // when repeat key pressed, set duty cycle to 50%, else 0%.
+ m_repeat_clock->set_duty_cycle(state == 0 ? 0.5 : 0);
+}
+
+void heath_tlb_device::break_key_w(int state)
+{
+ m_break_key_irq_raised = (state == 0);
+
+ set_irq_line();
+}
+
+MC6845_UPDATE_ROW(heath_tlb_device::crtc_update_row)
+{
+ rgb_t const *const palette = m_palette->palette()->entry_list_raw();
+ u32 *p = &bitmap.pix(y);
+
+ if (de)
+ {
+ for (int x = 0; x < x_count; x++)
+ {
+ u8 inv = (x == cursor_x) ? 0xff : 0;
+ u8 chr = m_p_videoram[(ma + x) & 0x7ff];
+
+ if (chr & 0x80)
+ {
+ inv ^= 0xff;
+ chr &= 0x7f;
+ }
+
+ // get pattern of pixels for that character scanline
+ u8 const gfx = m_p_chargen[(chr << 4) | ra] ^ inv;
+
+ // Display a scanline of a character (8 pixels)
+ for (int b = 0; 8 > b; ++b)
+ {
+ *p++ = palette[BIT(gfx, b)];
+ }
+ }
+ }
+ else
+ {
+ std::fill_n(p, x_count * 8, palette[0]);
+ }
+}
+
+
+// F4 Character Displayer
+static const gfx_layout h19_charlayout =
+{
+ 8, 10, // 8 x 10 characters
+ 128, // 128 characters
+ 1, // 1 bits per pixel
+ { 0 }, // no bitplanes
+ // x offsets
+ { 0, 1, 2, 3, 4, 5, 6, 7 },
+ // y offsets
+ { 0*8, 1*8, 2*8, 3*8, 4*8, 5*8, 6*8, 7*8, 8*8, 9*8 },
+ 8*16 // every char takes 16 bytes
+};
+
+static GFXDECODE_START( gfx_h19 )
+ GFXDECODE_ENTRY("chargen", 0x0000, h19_charlayout, 0, 1)
+GFXDECODE_END
+
+
+// Input ports
+static INPUT_PORTS_START( tlb )
+
+ PORT_START("MODIFIERS")
+ // bit 0 - 0x001 connects to B8 of MM5740 - low if either shift key is
+ PORT_BIT(0x002, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("CapsLock") PORT_CODE(KEYCODE_CAPSLOCK) PORT_TOGGLE
+ PORT_BIT(0x004, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("Break") PORT_CODE(KEYCODE_PAUSE) PORT_WRITE_LINE_MEMBER(FUNC(heath_tlb_device::break_key_w))
+ PORT_BIT(0x008, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("OffLine") PORT_CODE(KEYCODE_F12) PORT_TOGGLE
+ PORT_BIT(0x010, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("CTRL") PORT_CODE(KEYCODE_LCONTROL) PORT_CHAR(UCHAR_MAMEKEY(LCONTROL))
+ PORT_BIT(0x020, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("LeftShift") PORT_CODE(KEYCODE_LSHIFT) PORT_CHAR(UCHAR_SHIFT_1)
+ PORT_BIT(0x040, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("Repeat") PORT_CODE(KEYCODE_RALT) PORT_WRITE_LINE_MEMBER(FUNC(heath_tlb_device::repeat_key_w))
+ // bit 7 - 0x080 is low if any key is pressed
+ PORT_BIT(0x100, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("RightShift") PORT_CODE(KEYCODE_RSHIFT) PORT_WRITE_LINE_MEMBER(FUNC(heath_tlb_device::right_shift_w))
+ PORT_BIT(0x200, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("Reset") PORT_CODE(KEYCODE_F10) PORT_WRITE_LINE_MEMBER(FUNC(heath_tlb_device::reset_key_w))
+
+ PORT_START("X1")
+ PORT_BIT(0x001, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("/") PORT_CODE(KEYCODE_SLASH) PORT_CHAR('/') PORT_CHAR('?')
+ PORT_BIT(0x002, IP_ACTIVE_LOW, IPT_UNUSED)
+ PORT_BIT(0x004, IP_ACTIVE_LOW, IPT_UNUSED)
+ PORT_BIT(0x008, IP_ACTIVE_LOW, IPT_UNUSED)
+ PORT_BIT(0x010, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("k_X2")
+ PORT_BIT(0x020, IP_ACTIVE_LOW, IPT_UNUSED)
+ PORT_BIT(0x040, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("KP-0") PORT_CODE(KEYCODE_0_PAD) PORT_CHAR(UCHAR_MAMEKEY(0_PAD))
+ PORT_BIT(0x080, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("KP-.") PORT_CODE(KEYCODE_DEL_PAD) PORT_CHAR(UCHAR_MAMEKEY(DEL_PAD))
+ PORT_BIT(0x100, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("KP-Enter") PORT_CODE(KEYCODE_ENTER_PAD) PORT_CHAR(UCHAR_MAMEKEY(ENTER_PAD))
+ PORT_BIT(0x200, IP_ACTIVE_LOW, IPT_UNUSED)
+
+ PORT_START("X2")
+ PORT_BIT(0x001, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("; :") PORT_CODE(KEYCODE_COLON) PORT_CHAR(';') PORT_CHAR(':')
+ PORT_BIT(0x002, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("' \"") PORT_CODE(KEYCODE_QUOTE) PORT_CHAR('\'') PORT_CHAR('"')
+ PORT_BIT(0x004, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("{ }") PORT_CODE(KEYCODE_CLOSEBRACE) PORT_CHAR('{') PORT_CHAR('}')
+ PORT_BIT(0x008, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("Return") PORT_CODE(KEYCODE_ENTER) PORT_CHAR(13)
+ PORT_BIT(0x010, IP_ACTIVE_LOW, IPT_UNUSED)
+ PORT_BIT(0x020, IP_ACTIVE_LOW, IPT_UNUSED)
+ PORT_BIT(0x040, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("KP-1 IL") PORT_CODE(KEYCODE_1_PAD) PORT_CHAR(UCHAR_MAMEKEY(1_PAD))
+ PORT_BIT(0x080, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("KP-2 Down") PORT_CODE(KEYCODE_2_PAD) PORT_CHAR(UCHAR_MAMEKEY(2_PAD))
+ PORT_BIT(0x100, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("KP-3 DL") PORT_CODE(KEYCODE_3_PAD) PORT_CHAR(UCHAR_MAMEKEY(3_PAD))
+ PORT_BIT(0x200, IP_ACTIVE_LOW, IPT_UNUSED)
+
+ PORT_START("X3")
+ PORT_BIT(0x001, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("P") PORT_CODE(KEYCODE_P) PORT_CHAR('p') PORT_CHAR('P')
+ PORT_BIT(0x002, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("[ ]") PORT_CODE(KEYCODE_OPENBRACE) PORT_CHAR('[') PORT_CHAR(']')
+ PORT_BIT(0x004, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("\\ |") PORT_CODE(KEYCODE_BACKSLASH) PORT_CHAR('\\') PORT_CHAR('|')
+ PORT_BIT(0x008, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("Line Feed") PORT_CODE(KEYCODE_RWIN) PORT_CHAR(10)
+ PORT_BIT(0x010, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("DEL") PORT_CODE(KEYCODE_DEL) PORT_CHAR(127)
+ PORT_BIT(0x020, IP_ACTIVE_LOW, IPT_UNUSED)
+ PORT_BIT(0x040, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("KP-4 LEFT") PORT_CODE(KEYCODE_4_PAD) PORT_CHAR(UCHAR_MAMEKEY(4_PAD))
+ PORT_BIT(0x080, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("KP-5 HOME") PORT_CODE(KEYCODE_5_PAD) PORT_CHAR(UCHAR_MAMEKEY(5_PAD))
+ PORT_BIT(0x100, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("KP-6 RIGHT") PORT_CODE(KEYCODE_6_PAD) PORT_CHAR(UCHAR_MAMEKEY(6_PAD))
+ PORT_BIT(0x200, IP_ACTIVE_LOW, IPT_UNUSED)
+
+ PORT_START("X4")
+ PORT_BIT(0x001, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("0 )") PORT_CODE(KEYCODE_0) PORT_CHAR('0') PORT_CHAR(')')
+ PORT_BIT(0x002, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("- _") PORT_CODE(KEYCODE_MINUS) PORT_CHAR('-') PORT_CHAR('_')
+ PORT_BIT(0x004, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("= +") PORT_CODE(KEYCODE_EQUALS) PORT_CHAR('=') PORT_CHAR('+')
+ PORT_BIT(0x008, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("` ~") PORT_CODE(KEYCODE_TILDE) PORT_CHAR('`') PORT_CHAR('~')
+ PORT_BIT(0x010, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("Back Space") PORT_CODE(KEYCODE_BACKSPACE) PORT_CHAR(8)
+ PORT_BIT(0x020, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("k_X1")
+ PORT_BIT(0x040, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("KP-7 IC") PORT_CODE(KEYCODE_7_PAD) PORT_CHAR(UCHAR_MAMEKEY(7_PAD))
+ PORT_BIT(0x080, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("KP-8 UP") PORT_CODE(KEYCODE_8_PAD) PORT_CHAR(UCHAR_MAMEKEY(8_PAD))
+ PORT_BIT(0x100, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("KP-9 DC") PORT_CODE(KEYCODE_9_PAD) PORT_CHAR(UCHAR_MAMEKEY(9_PAD))
+ PORT_BIT(0x200, IP_ACTIVE_LOW, IPT_UNUSED)
+
+ PORT_START("X5")
+ PORT_BIT(0x001, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("F1") PORT_CODE(KEYCODE_F1) PORT_CHAR(UCHAR_MAMEKEY(F1))
+ PORT_BIT(0x002, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("F2") PORT_CODE(KEYCODE_F2) PORT_CHAR(UCHAR_MAMEKEY(F2))
+ PORT_BIT(0x004, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("F3") PORT_CODE(KEYCODE_F3) PORT_CHAR(UCHAR_MAMEKEY(F3))
+ PORT_BIT(0x008, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("F4") PORT_CODE(KEYCODE_F4) PORT_CHAR(UCHAR_MAMEKEY(F4))
+ PORT_BIT(0x010, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("F5") PORT_CODE(KEYCODE_F5) PORT_CHAR(UCHAR_MAMEKEY(F5))
+ PORT_BIT(0x020, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("Erase") PORT_CODE(KEYCODE_F6) PORT_CHAR(UCHAR_MAMEKEY(F6))
+ PORT_BIT(0x040, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("Blue") PORT_CODE(KEYCODE_F7) PORT_CHAR(UCHAR_MAMEKEY(F7))
+ PORT_BIT(0x080, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("Red") PORT_CODE(KEYCODE_F8) PORT_CHAR(UCHAR_MAMEKEY(F8))
+ PORT_BIT(0x100, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("Gray") PORT_CODE(KEYCODE_F9) PORT_CHAR(UCHAR_MAMEKEY(F9))
+ PORT_BIT(0x200, IP_ACTIVE_LOW, IPT_UNUSED)
+
+ PORT_START("X6")
+ PORT_BIT(0x001, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("Z") PORT_CODE(KEYCODE_Z) PORT_CHAR('z') PORT_CHAR('Z')
+ PORT_BIT(0x002, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("X") PORT_CODE(KEYCODE_X) PORT_CHAR('x') PORT_CHAR('X')
+ PORT_BIT(0x004, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("C") PORT_CODE(KEYCODE_C) PORT_CHAR('c') PORT_CHAR('C')
+ PORT_BIT(0x008, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("V") PORT_CODE(KEYCODE_V) PORT_CHAR('v') PORT_CHAR('V')
+ PORT_BIT(0x010, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("B") PORT_CODE(KEYCODE_B) PORT_CHAR('b') PORT_CHAR('B')
+ PORT_BIT(0x020, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("N") PORT_CODE(KEYCODE_N) PORT_CHAR('n') PORT_CHAR('N')
+ PORT_BIT(0x040, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("M") PORT_CODE(KEYCODE_M) PORT_CHAR('m') PORT_CHAR('M')
+ PORT_BIT(0x080, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME(", <") PORT_CODE(KEYCODE_COMMA) PORT_CHAR(',') PORT_CHAR('<')
+ PORT_BIT(0x100, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME(". >") PORT_CODE(KEYCODE_STOP) PORT_CHAR('.') PORT_CHAR('>')
+ PORT_BIT(0x200, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("Space") PORT_CODE(KEYCODE_SPACE) PORT_CHAR(' ')
+
+ PORT_START("X7")
+ PORT_BIT(0x001, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("A") PORT_CODE(KEYCODE_A) PORT_CHAR('a') PORT_CHAR('A')
+ PORT_BIT(0x002, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("S") PORT_CODE(KEYCODE_S) PORT_CHAR('s') PORT_CHAR('S')
+ PORT_BIT(0x004, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("D") PORT_CODE(KEYCODE_D) PORT_CHAR('d') PORT_CHAR('D')
+ PORT_BIT(0x008, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("F") PORT_CODE(KEYCODE_F) PORT_CHAR('f') PORT_CHAR('F')
+ PORT_BIT(0x010, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("G") PORT_CODE(KEYCODE_G) PORT_CHAR('g') PORT_CHAR('G')
+ PORT_BIT(0x020, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("H") PORT_CODE(KEYCODE_H) PORT_CHAR('h') PORT_CHAR('H')
+ PORT_BIT(0x040, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("J") PORT_CODE(KEYCODE_J) PORT_CHAR('j') PORT_CHAR('J')
+ PORT_BIT(0x080, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("K") PORT_CODE(KEYCODE_K) PORT_CHAR('k') PORT_CHAR('K')
+ PORT_BIT(0x100, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("L") PORT_CODE(KEYCODE_L) PORT_CHAR('l') PORT_CHAR('L')
+ PORT_BIT(0x200, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("Scroll") PORT_CODE(KEYCODE_F11)
+
+ PORT_START("X8")
+ PORT_BIT(0x001, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("Q") PORT_CODE(KEYCODE_Q) PORT_CHAR('q') PORT_CHAR('Q')
+ PORT_BIT(0x002, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("W") PORT_CODE(KEYCODE_W) PORT_CHAR('w') PORT_CHAR('W')
+ PORT_BIT(0x004, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("E") PORT_CODE(KEYCODE_E) PORT_CHAR('e') PORT_CHAR('E')
+ PORT_BIT(0x008, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("R") PORT_CODE(KEYCODE_R) PORT_CHAR('r') PORT_CHAR('R')
+ PORT_BIT(0x010, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("T") PORT_CODE(KEYCODE_T) PORT_CHAR('t') PORT_CHAR('T')
+ PORT_BIT(0x020, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("Y") PORT_CODE(KEYCODE_Y) PORT_CHAR('y') PORT_CHAR('Y')
+ PORT_BIT(0x040, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("U") PORT_CODE(KEYCODE_U) PORT_CHAR('u') PORT_CHAR('U')
+ PORT_BIT(0x080, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("I") PORT_CODE(KEYCODE_I) PORT_CHAR('i') PORT_CHAR('I')
+ PORT_BIT(0x100, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("O") PORT_CODE(KEYCODE_O) PORT_CHAR('o') PORT_CHAR('O')
+ PORT_BIT(0x200, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("Tab") PORT_CODE(KEYCODE_TAB) PORT_CHAR(9)
+
+ PORT_START("X9")
+ PORT_BIT(0x001, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("1 !") PORT_CODE(KEYCODE_1) PORT_CHAR('1') PORT_CHAR('!')
+ PORT_BIT(0x002, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("2 @") PORT_CODE(KEYCODE_2) PORT_CHAR('2') PORT_CHAR('@')
+ PORT_BIT(0x004, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("3 #") PORT_CODE(KEYCODE_3) PORT_CHAR('3') PORT_CHAR('#')
+ PORT_BIT(0x008, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("4 $") PORT_CODE(KEYCODE_4) PORT_CHAR('4') PORT_CHAR('$')
+ PORT_BIT(0x010, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("5 %") PORT_CODE(KEYCODE_5) PORT_CHAR('5') PORT_CHAR('%')
+ PORT_BIT(0x020, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("6 ^") PORT_CODE(KEYCODE_6) PORT_CHAR('6') PORT_CHAR('^')
+ PORT_BIT(0x040, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("7 &") PORT_CODE(KEYCODE_7) PORT_CHAR('7') PORT_CHAR('&')
+ PORT_BIT(0x080, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("8 *") PORT_CODE(KEYCODE_8) PORT_CHAR('8') PORT_CHAR('*')
+ PORT_BIT(0x100, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("9 (") PORT_CODE(KEYCODE_9) PORT_CHAR('9') PORT_CHAR('(')
+ PORT_BIT(0x200, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("Esc") PORT_CODE(KEYCODE_ESC) PORT_CHAR(27)
+
+ PORT_START("SW401")
+ PORT_DIPNAME( 0x0f, 0x0c, "Baud Rate") PORT_DIPLOCATION("SW401:1,2,3,4")
+ PORT_DIPSETTING( 0x01, "110")
+ PORT_DIPSETTING( 0x02, "150")
+ PORT_DIPSETTING( 0x03, "300")
+ PORT_DIPSETTING( 0x04, "600")
+ PORT_DIPSETTING( 0x05, "1200")
+ PORT_DIPSETTING( 0x06, "1800")
+ PORT_DIPSETTING( 0x07, "2000")
+ PORT_DIPSETTING( 0x08, "2400")
+ PORT_DIPSETTING( 0x09, "3600")
+ PORT_DIPSETTING( 0x0a, "4800")
+ PORT_DIPSETTING( 0x0b, "7200")
+ PORT_DIPSETTING( 0x0c, "9600")
+ PORT_DIPSETTING( 0x0d, "19200")
+ PORT_DIPNAME( 0x30, 0x00, "Parity") PORT_DIPLOCATION("SW401:5,6")
+ PORT_DIPSETTING( 0x00, DEF_STR( None ) )
+ PORT_DIPSETTING( 0x10, "Odd")
+ PORT_DIPSETTING( 0x20, DEF_STR( None ) )
+ PORT_DIPSETTING( 0x30, "Even")
+ PORT_DIPNAME( 0x40, 0x00, "Parity Type") PORT_DIPLOCATION("SW401:7")
+ PORT_DIPSETTING( 0x00, DEF_STR( Normal ) )
+ PORT_DIPSETTING( 0x40, "Stick")
+ PORT_DIPNAME( 0x80, 0x80, "Duplex") PORT_DIPLOCATION("SW401:8")
+ PORT_DIPSETTING( 0x00, "Half")
+ PORT_DIPSETTING( 0x80, "Full")
+
+ PORT_START("SW402")
+ PORT_DIPNAME( 0x01, 0x00, "Cursor") PORT_DIPLOCATION("SW402:1")
+ PORT_DIPSETTING( 0x00, "Underline")
+ PORT_DIPSETTING( 0x01, "Block")
+ PORT_DIPNAME( 0x02, 0x00, "Keyclick") PORT_DIPLOCATION("SW402:2")
+ PORT_DIPSETTING( 0x02, DEF_STR( No ) )
+ PORT_DIPSETTING( 0x00, DEF_STR( Yes ) )
+ PORT_DIPNAME( 0x04, 0x00, "Wrap at EOL") PORT_DIPLOCATION("SW402:3")
+ PORT_DIPSETTING( 0x00, DEF_STR( No ) )
+ PORT_DIPSETTING( 0x04, DEF_STR( Yes ) )
+ PORT_DIPNAME( 0x08, 0x00, "Auto LF on CR") PORT_DIPLOCATION("SW402:4")
+ PORT_DIPSETTING( 0x00, DEF_STR( No ) )
+ PORT_DIPSETTING( 0x08, DEF_STR( Yes ) )
+ PORT_DIPNAME( 0x10, 0x00, "Auto CR on LF") PORT_DIPLOCATION("SW402:5")
+ PORT_DIPSETTING( 0x00, DEF_STR( No ) )
+ PORT_DIPSETTING( 0x10, DEF_STR( Yes ) )
+ PORT_DIPNAME( 0x20, 0x00, "Mode") PORT_DIPLOCATION("SW402:6")
+ PORT_DIPSETTING( 0x00, "Heath/VT52")
+ PORT_DIPSETTING( 0x20, "ANSI")
+ PORT_DIPNAME( 0x40, 0x00, "Keypad Shifted") PORT_DIPLOCATION("SW402:7")
+ PORT_DIPSETTING( 0x00, DEF_STR( No ) )
+ PORT_DIPSETTING( 0x40, DEF_STR( Yes ) )
+ PORT_DIPNAME( 0x80, 0x00, "Refresh") PORT_DIPLOCATION("SW402:8")
+ PORT_DIPSETTING( 0x00, "60Hz")
+ PORT_DIPSETTING( 0x80, "50Hz")
+
+ PORT_START("CONFIG")
+ PORT_CONFNAME(0x03, 0x00, "CPU Clock")
+ PORT_CONFSETTING( 0x00, "2 MHz")
+ PORT_CONFSETTING( 0x01, "3 MHz")
+ PORT_CONFSETTING( 0x02, "4 MHz")
+ PORT_CONFSETTING( 0x03, "6 MHz")
+ PORT_CONFNAME(0x0C, 0x00, "CRT Color")
+ PORT_CONFSETTING( 0x00, "Green")
+ PORT_CONFSETTING( 0x04, "White")
+ PORT_CONFSETTING( 0x08, "Amber")
+INPUT_PORTS_END
+
+
+static INPUT_PORTS_START( super19 )
+ PORT_INCLUDE( tlb )
+
+ PORT_MODIFY("SW401")
+ PORT_DIPNAME( 0x0f, 0x0c, "Baud Rate") PORT_DIPLOCATION("SW401:1,2,3,4")
+ PORT_DIPSETTING( 0x01, "110")
+ PORT_DIPSETTING( 0x02, "150")
+ PORT_DIPSETTING( 0x03, "300")
+ PORT_DIPSETTING( 0x04, "600")
+ PORT_DIPSETTING( 0x05, "1200")
+ PORT_DIPSETTING( 0x06, "1800")
+ PORT_DIPSETTING( 0x07, "2000")
+ PORT_DIPSETTING( 0x08, "2400")
+ PORT_DIPSETTING( 0x09, "3600")
+ PORT_DIPSETTING( 0x0a, "4800")
+ PORT_DIPSETTING( 0x0b, "7200")
+ PORT_DIPSETTING( 0x0c, "9600")
+ PORT_DIPSETTING( 0x0d, "19200")
+ PORT_DIPSETTING( 0x0e, "38400")
+ PORT_DIPNAME( 0x70, 0x00, "8 bit mode") PORT_DIPLOCATION("SW401:5,6,7")
+ PORT_DIPSETTING( 0x00, "Mode A/0 - 8th bit ignored, sent as 0")
+ PORT_DIPSETTING( 0x10, "Mode B/1 - 8th bit ignored, sent as 1")
+ PORT_DIPSETTING( 0x20, "Mode C/2 - 8 bit escape mode")
+ PORT_DIPSETTING( 0x30, "Mode D/3 - 8 bit escape mode, invert 8th bit")
+ PORT_DIPSETTING( 0x40, "Mode E/4 - 8 bit data mode")
+ PORT_DIPSETTING( 0x50, "Mode F/5 - 8 bit data mode, invert 8th bit")
+ PORT_DIPSETTING( 0x60, "7 bit data with odd parity, 8th bit ignored on input")
+ PORT_DIPSETTING( 0x70, "7 bit data with even parity, 8th bit ignored on input")
+ PORT_DIPNAME( 0x80, 0x80, "Duplex") PORT_DIPLOCATION("SW401:8")
+ PORT_DIPSETTING( 0x00, "Half")
+ PORT_DIPSETTING( 0x80, "Full")
+
+ PORT_MODIFY("SW402")
+ PORT_DIPNAME( 0x02, 0x00, "Transmit mode") PORT_DIPLOCATION("SW402:2")
+ PORT_DIPSETTING( 0x00, DEF_STR( Normal ) )
+ PORT_DIPSETTING( 0x02, "Slow")
+ PORT_DIPNAME( 0x80, 0x00, "DEC Keypad Codes") PORT_DIPLOCATION("SW402:8")
+ PORT_DIPSETTING( 0x00, DEF_STR( Off ) )
+ PORT_DIPSETTING( 0x80, DEF_STR( On ) )
+INPUT_PORTS_END
+
+
+static INPUT_PORTS_START( superset )
+ PORT_INCLUDE( tlb )
+
+ PORT_MODIFY("SW401")
+ PORT_DIPNAME( 0x0f, 0x0c, "Baud Rate") PORT_DIPLOCATION("SW401:1,2,3,4")
+ PORT_DIPSETTING( 0x00, "75")
+ PORT_DIPSETTING( 0x01, "110")
+ PORT_DIPSETTING( 0x02, "150")
+ PORT_DIPSETTING( 0x03, "300")
+ PORT_DIPSETTING( 0x04, "600")
+ PORT_DIPSETTING( 0x05, "1200")
+ PORT_DIPSETTING( 0x06, "1800")
+ PORT_DIPSETTING( 0x07, "2000")
+ PORT_DIPSETTING( 0x08, "2400")
+ PORT_DIPSETTING( 0x09, "3600")
+ PORT_DIPSETTING( 0x0a, "4800")
+ PORT_DIPSETTING( 0x0b, "7200")
+ PORT_DIPSETTING( 0x0c, "9600")
+ PORT_DIPSETTING( 0x0d, "19200")
+ PORT_DIPSETTING( 0x0e, "38400")
+ PORT_DIPSETTING( 0x0f, "134.5")
+ PORT_DIPNAME( 0x10, 0x10, "Duplex") PORT_DIPLOCATION("SW401:5")
+ PORT_DIPSETTING( 0x00, "Half")
+ PORT_DIPSETTING( 0x80, "Full")
+ PORT_DIPNAME( 0x20, 0x00, "Word Length") PORT_DIPLOCATION("SW401:6")
+ PORT_DIPSETTING( 0x00, "8-bit" )
+ PORT_DIPSETTING( 0x20, "7-bit" )
+ PORT_DIPNAME( 0x40, 0x00, "Parity Type") PORT_DIPLOCATION("SW401:7")
+ PORT_DIPSETTING( 0x00, DEF_STR( None ) )
+ PORT_DIPSETTING( 0x40, "Even")
+ PORT_DIPNAME( 0x80, 0x80, "Parity") PORT_DIPLOCATION("SW401:8")
+ PORT_DIPSETTING( 0x00, "Disabled")
+ PORT_DIPSETTING( 0x80, "Enabled")
+INPUT_PORTS_END
+
+
+static INPUT_PORTS_START( ultra19 )
+ PORT_INCLUDE( tlb )
+
+ PORT_MODIFY("SW401")
+ PORT_DIPNAME( 0x07, 0x05, "Baud Rate") PORT_DIPLOCATION("SW401:1,2,3")
+ PORT_DIPSETTING( 0x00, "110")
+ PORT_DIPSETTING( 0x01, "300")
+ PORT_DIPSETTING( 0x02, "1200")
+ PORT_DIPSETTING( 0x03, "2400")
+ PORT_DIPSETTING( 0x04, "4800")
+ PORT_DIPSETTING( 0x05, "9600")
+ PORT_DIPSETTING( 0x06, "19200")
+ PORT_DIPSETTING( 0x07, "38400")
+ PORT_DIPNAME( 0x08, 0x00, "Parity") PORT_DIPLOCATION("SW401:4")
+ PORT_DIPSETTING( 0x00, "Disabled")
+ PORT_DIPSETTING( 0x08, "Enabled")
+ PORT_DIPNAME( 0x10, 0x00, "Parity Type") PORT_DIPLOCATION("SW401:5")
+ PORT_DIPSETTING( 0x00, "Odd")
+ PORT_DIPSETTING( 0x10, "Even")
+ PORT_DIPNAME( 0x20, 0x00, "Data Size") PORT_DIPLOCATION("SW401:6")
+ PORT_DIPSETTING( 0x00, "8-bit")
+ PORT_DIPSETTING( 0x20, "7-bit")
+ PORT_DIPNAME( 0x40, 0x40, "Duplex") PORT_DIPLOCATION("SW401:7")
+ PORT_DIPSETTING( 0x00, "Half")
+ PORT_DIPSETTING( 0x40, "Full")
+ PORT_DIPNAME( 0x80, 0x80, "Software Handshaking") PORT_DIPLOCATION("SW401:8")
+ PORT_DIPSETTING( 0x00, "Enabled")
+ PORT_DIPSETTING( 0x80, "Disabled")
+
+ PORT_MODIFY("SW402")
+ PORT_DIPNAME( 0x08, 0x00, "Keypad Shifted") PORT_DIPLOCATION("SW402:4")
+ PORT_DIPSETTING( 0x00, DEF_STR( No ) )
+ PORT_DIPSETTING( 0x08, DEF_STR( Yes ) )
+ PORT_DIPNAME( 0x10, 0x00, "Default Key Values") PORT_DIPLOCATION("SW402:5")
+ PORT_DIPSETTING( 0x00, "HDOS Values")
+ PORT_DIPSETTING( 0x10, "CP/M Values")
+ PORT_DIPNAME( 0x60, 0x60, "Cursor Blink") PORT_DIPLOCATION("SW402:6,7")
+ PORT_DIPSETTING( 0x00, "Steady")
+ PORT_DIPSETTING( 0x20, "Invisible")
+ PORT_DIPSETTING( 0x40, "Fast Blink")
+ PORT_DIPSETTING( 0x60, "Slow Blink")
+ PORT_DIPNAME( 0x80, 0x00, "Interlace Scan Mode") PORT_DIPLOCATION("SW402:8")
+ PORT_DIPSETTING( 0x00, DEF_STR( Off ) )
+ PORT_DIPSETTING( 0x80, DEF_STR( On ) )
+
+ PORT_MODIFY("CONFIG")
+ PORT_CONFNAME(0x10, 0x10, "Page 2 RAM present")
+ PORT_DIPSETTING( 0x00, DEF_STR( No ) )
+ PORT_DIPSETTING( 0x10, DEF_STR( Yes ) )
+
+INPUT_PORTS_END
+
+
+static INPUT_PORTS_START( watz19 )
+ PORT_INCLUDE( tlb )
+
+ PORT_MODIFY("SW401")
+ PORT_DIPNAME( 0x0f, 0x0c, "Baud Rate") PORT_DIPLOCATION("SW401:1,2,3,4")
+ PORT_DIPSETTING( 0x00, "75")
+ PORT_DIPSETTING( 0x01, "110")
+ PORT_DIPSETTING( 0x02, "150")
+ PORT_DIPSETTING( 0x03, "300")
+ PORT_DIPSETTING( 0x04, "600")
+ PORT_DIPSETTING( 0x05, "1200")
+ PORT_DIPSETTING( 0x06, "1800")
+ PORT_DIPSETTING( 0x07, "2000")
+ PORT_DIPSETTING( 0x08, "2400")
+ PORT_DIPSETTING( 0x09, "3600")
+ PORT_DIPSETTING( 0x0a, "4800")
+ PORT_DIPSETTING( 0x0b, "7200")
+ PORT_DIPSETTING( 0x0c, "9600")
+ PORT_DIPSETTING( 0x0d, "19200")
+ PORT_DIPSETTING( 0x0e, "38400")
+ PORT_DIPSETTING( 0x0f, "134.5")
+ PORT_DIPNAME( 0x40, 0x00, "Word Size") PORT_DIPLOCATION("SW401:7")
+ PORT_DIPSETTING( 0x00, "8-bit Word")
+ PORT_DIPSETTING( 0x40, "7-bit Word")
+ PORT_DIPNAME( 0x80, 0x80, "Duplex") PORT_DIPLOCATION("SW401:8")
+ PORT_DIPSETTING( 0x00, "Half")
+ PORT_DIPSETTING( 0x80, "Full")
+INPUT_PORTS_END
+
+
+static INPUT_PORTS_START( gp19 )
+ PORT_INCLUDE( tlb )
+
+ PORT_MODIFY("SW402")
+ PORT_DIPNAME( 0x80, 0x00, "Automatic Holdscreen") PORT_DIPLOCATION("SW402:8")
+ PORT_DIPSETTING( 0x00, "Disabled (VT100 mode)")
+ PORT_DIPSETTING( 0x80, "Enabled (Z19 mode)")
+
+ PORT_START("SW1")
+ PORT_DIPNAME( 0x03, 0x01, "Trailing Characters for Tektronix Message") PORT_DIPLOCATION("SW1:1,2")
+ PORT_DIPSETTING( 0x00, DEF_STR( None ) )
+ PORT_DIPSETTING( 0x01, "CR")
+ PORT_DIPSETTING( 0x02, DEF_STR( None ) )
+ PORT_DIPSETTING( 0x03, "CR,EOT")
+ PORT_DIPNAME( 0x04, 0x01, "Shift Key") PORT_DIPLOCATION("SW1:3")
+ PORT_DIPSETTING( 0x00, DEF_STR( Normal ) )
+ PORT_DIPSETTING( 0x04, "Shift key inverts CAPS LOCK")
+ PORT_DIPNAME( 0x08, 0x00, "Terminal Transmission Rate") PORT_DIPLOCATION("SW1:4")
+ PORT_DIPSETTING( 0x00, "Only limited by baud rate")
+ PORT_DIPSETTING( 0x08, "One character per 16.7 msec")
+ PORT_DIPNAME( 0x10, 0x10, "Character Set") PORT_DIPLOCATION("SW1:5")
+ PORT_DIPSETTING( 0x00, "VT100")
+ PORT_DIPSETTING( 0x10, "Zenith")
+ PORT_DIPNAME( 0x20, 0x00, "ANSI Mode") PORT_DIPLOCATION("SW1:6")
+ PORT_DIPSETTING( 0x00, "Zenith ANSI")
+ PORT_DIPSETTING( 0x20, "EDT compatible")
+ PORT_DIPNAME( 0x40, 0x00, "Tektronix Character Wrap") PORT_DIPLOCATION("SW1:7")
+ PORT_DIPSETTING( 0x00, "Column 74")
+ PORT_DIPSETTING( 0x40, "Column 73")
+ PORT_DIPNAME( 0x80, 0x00, "Blank Screen") PORT_DIPLOCATION("SW1:8")
+ PORT_DIPSETTING( 0x00, "After 10 mins")
+ PORT_DIPSETTING( 0x80, "Never")
+INPUT_PORTS_END
+
+static INPUT_PORTS_START( igc_common )
+ PORT_START("joystick_p1")
+ PORT_BIT( 0x01, IP_ACTIVE_HIGH, IPT_JOYSTICK_UP )
+ PORT_BIT( 0x02, IP_ACTIVE_HIGH, IPT_JOYSTICK_DOWN )
+ PORT_BIT( 0x04, IP_ACTIVE_HIGH, IPT_JOYSTICK_LEFT )
+ PORT_BIT( 0x08, IP_ACTIVE_HIGH, IPT_JOYSTICK_RIGHT )
+ PORT_BIT( 0x10, IP_ACTIVE_HIGH, IPT_BUTTON1 )
+
+ PORT_START("joystick_p2")
+ PORT_BIT( 0x01, IP_ACTIVE_HIGH, IPT_JOYSTICK_UP ) PORT_PLAYER(2)
+ PORT_BIT( 0x02, IP_ACTIVE_HIGH, IPT_JOYSTICK_DOWN ) PORT_PLAYER(2)
+ PORT_BIT( 0x04, IP_ACTIVE_HIGH, IPT_JOYSTICK_LEFT ) PORT_PLAYER(2)
+ PORT_BIT( 0x08, IP_ACTIVE_HIGH, IPT_JOYSTICK_RIGHT ) PORT_PLAYER(2)
+ PORT_BIT( 0x10, IP_ACTIVE_HIGH, IPT_BUTTON1 ) PORT_PLAYER(2)
+
+INPUT_PORTS_END
+
+static INPUT_PORTS_START( igc )
+ PORT_INCLUDE( tlb )
+
+ PORT_INCLUDE( igc_common )
+INPUT_PORTS_END
+
+static INPUT_PORTS_START( igc_super19 )
+ PORT_INCLUDE( super19 )
+
+ PORT_INCLUDE( igc_common )
+INPUT_PORTS_END
+
+static INPUT_PORTS_START( igc_ultra )
+ PORT_INCLUDE( ultra19 )
+
+ PORT_INCLUDE( igc_common )
+INPUT_PORTS_END
+
+static INPUT_PORTS_START( igc_watz )
+ PORT_INCLUDE( watz19 )
+
+ PORT_INCLUDE( igc_common )
+INPUT_PORTS_END
+
+
+
+
+ROM_START( h19 )
+ // Original terminal code
+ ROM_REGION( 0x1000, "maincpu", ROMREGION_ERASEFF )
+ ROM_LOAD( "2732_444-46_h19code.u437", 0x0000, 0x1000, CRC(f4447da0) SHA1(fb4093d5b763be21a9580a0defebed664b1f7a7b))
+
+ // Original font
+ ROM_REGION( 0x0800, "chargen", 0 )
+ ROM_LOAD( "2716_444-29_h19font.u420", 0x0000, 0x0800, CRC(d595ac1d) SHA1(130fb4ea8754106340c318592eec2d8a0deaf3d0))
+
+ // Original keyboard
+ ROM_REGION( 0x0800, "keyboard", 0 )
+ ROM_LOAD( "2716_444-37_h19keyb.u445", 0x0000, 0x0800, CRC(5c3e6972) SHA1(df49ce64ae48652346a91648c58178a34fb37d3c))
+ROM_END
+
+ROM_START( super19 )
+ // Super-19 ROM
+ ROM_REGION( 0x1000, "maincpu", ROMREGION_ERASEFF )
+ ROM_LOAD( "2732_super19_h447.u437", 0x0000, 0x1000, CRC(6c51aaa6) SHA1(5e368b39fe2f1af44a905dc474663198ab630117))
+
+ // Original font
+ ROM_REGION( 0x0800, "chargen", 0 )
+ ROM_LOAD( "2716_444-29_h19font.u420", 0x0000, 0x0800, CRC(d595ac1d) SHA1(130fb4ea8754106340c318592eec2d8a0deaf3d0))
+
+ // Original keyboard
+ ROM_REGION( 0x0800, "keyboard", 0 )
+ ROM_LOAD( "2716_444-37_h19keyb.u445", 0x0000, 0x0800, CRC(5c3e6972) SHA1(df49ce64ae48652346a91648c58178a34fb37d3c))
+ROM_END
+
+ROM_START( superset )
+ // SuperSet ROM
+ ROM_REGION( 0x4000, "maincpu", ROMREGION_ERASEFF )
+ ROM_LOAD( "27256_101-402_superset_code.u437", 0x0000, 0x2000, CRC(a6896076) SHA1(a4e2d25028dc75a665c3f5a830a4e8cdecbd481c))
+ // 1st 8k is unused, so overwrite it, with the next 16k (but only first 8k is valid)
+ ROM_CONTINUE(0x0000, 0x4000)
+ // overwrite at 8k starting address with the last 8k of the chip.
+ ROM_CONTINUE(0x2000, 0x2000)
+
+ // Superset SUPERFONT
+ ROM_REGION( 0x8000, "chargen", 0 )
+ ROM_LOAD( "27256_101-431_superset_font.u420", 0x0000, 0x8000, CRC(4c0688f6) SHA1(be6059913420ad66f5c839d619fdcb164ffae85a))
+
+ // Superset Keyboard
+ ROM_REGION( 0x0800, "keyboard", 0 )
+ ROM_LOAD( "2716_101-422_superset_kbd.u445", 0x0000, 0x0800, CRC(549d15b3) SHA1(981962e5e05bbdc5a66b0e86870853ce5596e877))
+ROM_END
+
+ROM_START( watz19 )
+ ROM_REGION( 0x1000, "maincpu", ROMREGION_ERASEFF )
+ ROM_DEFAULT_BIOS("watzman-a")
+
+ // Watzman ROM
+ ROM_SYSTEM_BIOS(0, "watzman", "Watzman")
+ ROMX_LOAD("watzman.u437", 0x0000, 0x1000, CRC(8168b6dc) SHA1(bfaebb9d766edbe545d24bc2b6630be4f3aa0ce9), ROM_BIOS(0))
+
+ ROM_SYSTEM_BIOS(1, "watzman-a", "Watzman w/clock persists after reset")
+ ROMX_LOAD("watzman-a.u437", 0x0000, 0x1000, CRC(1f7553e9) SHA1(ac6ddb12b4fb46c1a0ad08ee43978ad3153b51aa), ROM_BIOS(1))
+
+ // Original font
+ ROM_REGION( 0x0800, "chargen", 0 )
+ ROM_LOAD( "2716_444-29_h19font.u420", 0x0000, 0x0800, CRC(d595ac1d) SHA1(130fb4ea8754106340c318592eec2d8a0deaf3d0))
+
+ // Watzman keyboard
+ ROM_REGION( 0x0800, "keyboard", 0 )
+ ROM_LOAD( "keybd.u445", 0x0000, 0x0800, CRC(58dc8217) SHA1(1b23705290bdf9fc6342065c6a528c04bff67b13))
+ROM_END
+
+ROM_START( ultra19 )
+ // Ultra ROM
+ ROM_REGION( 0x1000, "maincpu", ROMREGION_ERASEFF )
+ ROM_LOAD( "2532_h19_ultra_firmware.u437", 0x0000, 0x1000, CRC(8ad4cdb4) SHA1(d6e1fc37a1f52abfce5e9adb1819e0030bed1df3))
+
+ // Original font
+ ROM_REGION( 0x0800, "chargen", 0 )
+ ROM_LOAD( "2716_444-29_h19font.u420", 0x0000, 0x0800, CRC(d595ac1d) SHA1(130fb4ea8754106340c318592eec2d8a0deaf3d0))
+
+ // Ultra keyboard
+ ROM_REGION( 0x0800, "keyboard", 0 )
+ ROM_LOAD( "2716_h19_ultra_keyboard.u445", 0x0000, 0x0800, CRC(76130c92) SHA1(ca39c602af48505139d2750a084b5f8f0e662ff7))
+ROM_END
+
+ROM_START( gp19 )
+ // GP-19 ROMs
+ ROM_REGION( 0x3000, "maincpu", ROMREGION_ERASEFF )
+ ROM_LOAD( "gp19_rom_1_ver_1_1.u26", 0x0000, 0x1000, CRC(7cbe8e0d) SHA1(977df895b067fa4e4646b4518cffb08d4e6bb6e0))
+ ROM_LOAD( "gp19_rom_2_ver_1_1.u25", 0x1000, 0x1000, CRC(a85e3bc4) SHA1(f64e851c5d3ef98a9a48e0fc482baa576773ff43))
+ ROM_LOAD( "gp19_rom_3_ver_1_1.u24", 0x2000, 0x1000, CRC(878f577c) SHA1(0756435914dcfb981de4e40d5f81af3e0f5bb1c5))
+
+ // GP-19 font
+ ROM_REGION( 0x1000, "chargen", 0 )
+ ROM_LOAD( "gp19_char_gen_cg_1.u21", 0x0000, 0x1000, CRC(49ec9242) SHA1(770a8c7b5b15bcfe465fd84326d0ae3dcaa85311))
+
+ // Original keyboard
+ ROM_REGION( 0x0800, "keyboard", 0 )
+ ROM_LOAD( "2716_444-37_h19keyb.u445", 0x0000, 0x0800, CRC(5c3e6972) SHA1(df49ce64ae48652346a91648c58178a34fb37d3c))
+ROM_END
+
+ROM_START( imaginator )
+ // Program code
+ ROM_REGION( 0x4000, "maincpu", ROMREGION_ERASEFF )
+ // Original terminal code
+ ROM_LOAD( "2732_444-46_h19code.u437", 0x0000, 0x1000, CRC(f4447da0) SHA1(fb4093d5b763be21a9580a0defebed664b1f7a7b))
+ // Imaginator ROMs
+ ROM_LOAD( "2732_imaginator_gpc_rev_1.2_pn_9000_0002.u9a", 0x2000, 0x1000, CRC(507bb13f) SHA1(5b210f8d77e22fdf063f611eb5c29636cdb01250))
+
+ // Original font
+ ROM_REGION( 0x0800, "chargen", 0 )
+ ROM_LOAD( "2716_444-29_h19font.u420", 0x0000, 0x0800, CRC(d595ac1d) SHA1(130fb4ea8754106340c318592eec2d8a0deaf3d0))
+
+ // Original keyboard
+ ROM_REGION( 0x0800, "keyboard", 0 )
+ ROM_LOAD( "2716_444-37_h19keyb.u445", 0x0000, 0x0800, CRC(5c3e6972) SHA1(df49ce64ae48652346a91648c58178a34fb37d3c))
+ROM_END
+
+
+ioport_constructor heath_tlb_device::device_input_ports() const
+{
+ return INPUT_PORTS_NAME(tlb);
+}
+
+const tiny_rom_entry *heath_tlb_device::device_rom_region() const
+{
+ return ROM_NAME(h19);
+}
+
+void heath_tlb_device::serial_out_b(int data)
+{
+ m_slot->serial_out_b(data);
+}
+
+void heath_tlb_device::dtr_out(int data)
+{
+ m_slot->dtr_out(data);
+}
+
+void heath_tlb_device::rts_out(int data)
+{
+ m_slot->rts_out(data);
+}
+
+void heath_tlb_device::serial_in_w(int state)
+{
+ m_ace->rx_w(state);
+}
+
+void heath_tlb_device::rlsd_in_w(int state)
+{
+ m_ace->dcd_w(state);
+}
+
+void heath_tlb_device::dsr_in_w(int state)
+{
+ m_ace->dsr_w(state);
+}
+
+void heath_tlb_device::cts_in_w(int state)
+{
+ m_ace->cts_w(state);
+}
+
+void heath_tlb_device::device_add_mconfig(machine_config &config)
+{
+ // basic machine hardware
+ Z80(config, m_maincpu, H19_CLOCK);
+ m_maincpu->set_addrmap(AS_PROGRAM, &heath_tlb_device::mem_map);
+ m_maincpu->set_addrmap(AS_IO, &heath_tlb_device::io_map);
+
+ // video hardware
+ SCREEN(config, m_screen, SCREEN_TYPE_RASTER, rgb_t::green());
+ // based on the H19 ROM code for 60 Hz
+ m_screen->set_raw(BASE_DOT_CLOCK, 768, 32, 672, 270, 0, 250);
+ m_screen->set_screen_update("crtc", FUNC(mc6845_device::screen_update));
+
+ GFXDECODE(config, "gfxdecode", m_palette, gfx_h19);
+ PALETTE(config, "palette", palette_device::MONOCHROME);
+
+ // MC 6845 uses a character clock, divide the DOT clock by 8.
+ MC6845(config, m_crtc, BASE_DOT_CLOCK / 8);
+ m_crtc->set_screen("screen");
+ m_crtc->set_show_border_area(false);
+ m_crtc->set_char_width(8);
+ m_crtc->set_update_row_callback(FUNC(heath_tlb_device::crtc_update_row));
+ // frame pulse
+ m_crtc->out_vsync_callback().set(FUNC(heath_tlb_device::crtc_vsync_w));
+
+ // serial port
+ INS8250(config, m_ace, INS8250_CLOCK);
+ m_ace->out_int_callback().set(FUNC(heath_tlb_device::serial_irq_w));
+ m_ace->out_tx_callback().set(FUNC(heath_tlb_device::serial_out_b));
+ m_ace->out_dtr_callback().set(FUNC(heath_tlb_device::dtr_out));
+ m_ace->out_rts_callback().set(FUNC(heath_tlb_device::rts_out));
+
+ // keyboard
+ MM5740(config, m_mm5740, MM5740_CLOCK);
+ m_mm5740->x_cb<1>().set_ioport("X1");
+ m_mm5740->x_cb<2>().set_ioport("X2");
+ m_mm5740->x_cb<3>().set_ioport("X3");
+ m_mm5740->x_cb<4>().set_ioport("X4");
+ m_mm5740->x_cb<5>().set_ioport("X5");
+ m_mm5740->x_cb<6>().set_ioport("X6");
+ m_mm5740->x_cb<7>().set_ioport("X7");
+ m_mm5740->x_cb<8>().set_ioport("X8");
+ m_mm5740->x_cb<9>().set_ioport("X9");
+ m_mm5740->shift_cb().set(FUNC(heath_tlb_device::mm5740_shift_r));
+ m_mm5740->control_cb().set(FUNC(heath_tlb_device::mm5740_control_r));
+ m_mm5740->data_ready_cb().set(FUNC(heath_tlb_device::mm5740_data_ready_w));
+
+ // sound hardware
+ SPEAKER(config, "mono").front_center();
+ BEEP(config, m_beep, H19_BEEP_FRQ).add_route(ALL_OUTPUTS, "mono", 0.05);
+
+ // clock for repeat key
+ CLOCK(config, m_repeat_clock, 40);
+ m_repeat_clock->set_duty_cycle(0);
+ m_repeat_clock->signal_handler().set(m_mm5740, FUNC(mm5740_device::repeat_line_w));
+}
+
+
+/**
+ * Super-19 ROM
+ *
+ * Developed by ATG Systems
+ */
+heath_super19_tlb_device::heath_super19_tlb_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock) :
+ heath_tlb_device(mconfig, HEATH_SUPER19, tag, owner, clock)
+{
+}
+
+const tiny_rom_entry *heath_super19_tlb_device::device_rom_region() const
+{
+ return ROM_NAME(super19);
+}
+
+ioport_constructor heath_super19_tlb_device::device_input_ports() const
+{
+ return INPUT_PORTS_NAME(super19);
+}
+
+
+/**
+ * Superset ROM
+ *
+ * Developed by TMSI
+ */
+heath_superset_tlb_device::heath_superset_tlb_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock) :
+ heath_tlb_device(mconfig, HEATH_SUPERSET, tag, owner, clock),
+ m_selected_char_set(0)
+{
+}
+
+void heath_superset_tlb_device::device_add_mconfig(machine_config &config)
+{
+ heath_tlb_device::device_add_mconfig(config);
+
+ // part of the Superset upgrade was to upgrade the CPU to 3 MHz.
+ m_maincpu->set_clock(H19_3MHZ);
+ m_maincpu->set_addrmap(AS_PROGRAM, &heath_superset_tlb_device::mem_map);
+ m_maincpu->set_addrmap(AS_IO, &heath_superset_tlb_device::io_map);
+
+ // per line updates are needed for onscreen menu to display properly
+ m_screen->set_video_attributes(VIDEO_UPDATE_SCANLINE);
+
+ m_crtc->set_update_row_callback(FUNC(heath_superset_tlb_device::crtc_update_row));
+
+ // link up the serial port outputs to font chip.
+ m_ace->out_dtr_callback().set(FUNC(heath_superset_tlb_device::dtr_internal));
+ m_ace->out_out1_callback().set(FUNC(heath_superset_tlb_device::out1_internal));
+ m_ace->out_out2_callback().set(FUNC(heath_superset_tlb_device::out2_internal));
+}
+
+void heath_superset_tlb_device::device_start()
+{
+ heath_tlb_device::device_start();
+
+ save_item(NAME(m_selected_char_set));
+
+ m_selected_char_set = 0;
+}
+
+void heath_superset_tlb_device::mem_map(address_map &map)
+{
+ heath_tlb_device::mem_map(map);
+
+ // update rom space for the 16k ROM.
+ map(0x0000, 0x3fff).rom();
+
+ // page 2 memory
+ map(0x8000, 0x87ff).ram();
+}
+
+void heath_superset_tlb_device::io_map(address_map &map)
+{
+ heath_tlb_device::io_map(map);
+
+ map(0x61, 0x61).mirror(0x12).select(0x0c).rw(FUNC(heath_superset_tlb_device::crtc_reg_r), FUNC(heath_superset_tlb_device::crtc_reg_w));
+}
+
+const tiny_rom_entry *heath_superset_tlb_device::device_rom_region() const
+{
+ return ROM_NAME(superset);
+}
+
+ioport_constructor heath_superset_tlb_device::device_input_ports() const
+{
+ return INPUT_PORTS_NAME(superset);
+}
+
+u8 heath_superset_tlb_device::crtc_reg_r(offs_t reg)
+{
+ if (!machine().side_effects_disabled())
+ {
+ m_reverse_video_disabled = bool(BIT(reg, 3));
+ }
+
+ return heath_tlb_device::crtc_reg_r(reg);
+}
+
+void heath_superset_tlb_device::crtc_reg_w(offs_t reg, u8 val)
+{
+ m_reverse_video_disabled = bool(BIT(reg, 3));
+
+ heath_tlb_device::crtc_reg_w(reg, val);
+}
+
+MC6845_UPDATE_ROW(heath_superset_tlb_device::crtc_update_row)
+{
+ rgb_t const *const palette = m_palette->palette()->entry_list_raw();
+ u32 *p = &bitmap.pix(y);
+
+ if (de)
+ {
+ for (int x = 0; x < x_count; x++)
+ {
+ u8 inv = (x == cursor_x) ? 0xff : 0;
+ u8 chr = m_p_videoram[(ma + x) & 0x7ff];
+ u16 char_set_base_offset = (m_selected_char_set << 11);
+
+ if (chr & 0x80)
+ {
+ if (m_reverse_video_disabled)
+ {
+ // set A13
+ char_set_base_offset |= 0x2000;
+ }
+ else
+ {
+ inv ^= 0xff;
+ }
+
+ chr &= 0x7f;
+ }
+
+ // get pattern of pixels for the character scanline
+ u8 const gfx = m_p_chargen[char_set_base_offset | (chr << 4) | ra] ^ inv;
+
+ // Display a scanline of a character (8 pixels)
+ for (int b = 0; 8 > b; ++b)
+ {
+ *p++ = palette[BIT(gfx, b)];
+ }
+ }
+ }
+ else
+ {
+ std::fill_n(p, bitmap.rowpixels(), palette[0]);
+ }
+}
+
+// DTR (pin 33) to A14 (pin 27) of 27256 ROM
+void heath_superset_tlb_device::dtr_internal(int data)
+{
+ m_selected_char_set = (m_selected_char_set & 0x03) | ((data & 0x01) << 3);
+}
+
+// OUT1 (pin 34) to A12 (pin 2) of 27256 ROM
+void heath_superset_tlb_device::out1_internal(int data)
+{
+ m_selected_char_set = (m_selected_char_set & 0x09) | ((data & 0x01) << 1);
+}
+
+// OUT2 (pin 31) to A11? on board
+void heath_superset_tlb_device::out2_internal(int data)
+{
+ m_selected_char_set = (m_selected_char_set & 0x0a) | (data & 0x01);
+}
+
+
+/**
+ * Watzman ROM
+ *
+ * Developed by Barry Watzman, sold by HUG (Heath Users Group)
+*/
+heath_watz_tlb_device::heath_watz_tlb_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock) :
+ heath_tlb_device(mconfig, HEATH_WATZ, tag, owner, clock)
+{
+}
+
+const tiny_rom_entry *heath_watz_tlb_device::device_rom_region() const
+{
+ return ROM_NAME(watz19);
+}
+
+ioport_constructor heath_watz_tlb_device::device_input_ports() const
+{
+ return INPUT_PORTS_NAME(watz19);
+}
+
+
+/**
+ * UltraROM
+ *
+ * Developed by William G. Parrott, III, sold by Software Wizardry, Inc.
+ */
+heath_ultra_tlb_device::heath_ultra_tlb_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock) :
+ heath_tlb_device(mconfig, HEATH_ULTRA, tag, owner, clock),
+ m_maincpu_region(*this, "maincpu"),
+ m_page_2_ram(*this, "page2ram"),
+ m_mem_view(*this, "mem")
+{
+}
+
+void heath_ultra_tlb_device::device_reset()
+{
+ heath_tlb_device::device_reset();
+
+ ioport_value const cfg(m_config->read());
+
+ // Page 2 memory
+ m_mem_view.select(BIT(cfg, 4));
+}
+
+void heath_ultra_tlb_device::device_add_mconfig(machine_config &config)
+{
+ heath_tlb_device::device_add_mconfig(config);
+
+ m_maincpu->set_addrmap(AS_PROGRAM, &heath_ultra_tlb_device::mem_map);
+}
+
+void heath_ultra_tlb_device::mem_map(address_map &map)
+{
+ heath_tlb_device::mem_map(map);
+
+ map(0x0000, 0x3fff).view(m_mem_view);
+
+ m_mem_view[0](0x0000, 0x0fff).mirror(0x3000).rom().region(m_maincpu_region, 0x0000).unmapw();
+ m_mem_view[1](0x0000, 0x0fff).mirror(0x2000).rom().region(m_maincpu_region, 0x0000).unmapw();
+ m_mem_view[1](0x1000, 0x1fff).mirror(0x2000).ram().share(m_page_2_ram);
+}
+
+const tiny_rom_entry *heath_ultra_tlb_device::device_rom_region() const
+{
+ return ROM_NAME(ultra19);
+}
+
+ioport_constructor heath_ultra_tlb_device::device_input_ports() const
+{
+ return INPUT_PORTS_NAME(ultra19);
+}
+
+
+/**
+ * Northwest Digital Systems GP-19 add-in board
+ */
+heath_gp19_tlb_device::heath_gp19_tlb_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock) :
+ heath_tlb_device(mconfig, HEATH_GP19, tag, owner, clock)
+{
+}
+
+void heath_gp19_tlb_device::device_add_mconfig(machine_config &config)
+{
+ heath_tlb_device::device_add_mconfig(config);
+
+ m_maincpu->set_addrmap(AS_PROGRAM, &heath_gp19_tlb_device::mem_map);
+ m_maincpu->set_addrmap(AS_IO, &heath_gp19_tlb_device::io_map);
+
+ m_crtc->set_update_row_callback(FUNC(heath_gp19_tlb_device::crtc_update_row));
+ m_crtc->set_clock(GP19_DOT_CLOCK_2 / 8);
+
+ m_screen->set_raw(GP19_DOT_CLOCK_2, 776, 32, 672, 264, 10, 250);
+}
+
+void heath_gp19_tlb_device::device_start()
+{
+ heath_tlb_device::device_start();
+
+ save_item(NAME(m_char_gen_a11));
+ save_item(NAME(m_graphic_mode));
+ save_item(NAME(m_col_132));
+ save_item(NAME(m_reverse_video));
+
+ m_char_gen_a11 = false;
+ m_graphic_mode = false;
+ m_col_132 = false;
+ m_reverse_video = false;
+}
+
+void heath_gp19_tlb_device::mem_map(address_map &map)
+{
+ // ROMs 1, 2, 3
+ map(0x0000, 0x02fff).rom();
+
+ // Optional external board - Program ROM 4(not aware if any ever existed), external I/O
+ // map(0x3000, 0x03fff).rom();
+
+ map(0x4000, 0x40ff).mirror(0x3f00).ram();
+ map(0x6000, 0x67ff).mirror(0x1800).ram();
+ map(0x8000, 0xbfff).mirror(0x4000).ram().share(m_p_videoram);
+}
+
+void heath_gp19_tlb_device::io_map(address_map &map)
+{
+ heath_tlb_device::io_map(map);
+
+ // Latch U5
+ map(0x68, 0x68).mirror(0x07).w(FUNC(heath_gp19_tlb_device::latch_u5_w));
+
+ // Switch on GP-19 board
+ map(0x70, 0x70).mirror(0x07).portr("SW1");
+
+ // Optional Auxiliary I/O connector(not aware if any ever existed)
+ // map(0x78, 0x78).mirror(0x07);
+}
+
+/**
+ * U5 Latch
+ *
+ * Q0 Graph/character H
+ * Q1 132/80 columns H
+ * Q2 Reverse Screen H
+ * Q3 Alt Character L
+ * Q4-Q7 LED indicators (debug LEDs on circuit board)
+ */
+void heath_gp19_tlb_device::latch_u5_w(u8 data)
+{
+ m_graphic_mode = bool(BIT(data, 0));
+ m_col_132 = bool(BIT(data, 1));
+ m_reverse_video = bool(BIT(data, 2));
+ m_char_gen_a11 = bool(BIT(data, 3));
+
+ // TODO handle LED indicators
+
+ if (m_graphic_mode)
+ {
+ m_crtc->set_clock(GP19_DOT_CLOCK_3 / 8);
+ }
+ else if (m_col_132)
+ {
+ m_crtc->set_clock(GP19_DOT_CLOCK_1 / 8);
+ }
+ else
+ {
+ m_crtc->set_clock(GP19_DOT_CLOCK_2 / 8);
+ }
+}
+
+MC6845_UPDATE_ROW(heath_gp19_tlb_device::crtc_update_row)
+{
+ rgb_t const *const palette = m_palette->palette()->entry_list_raw();
+ u32 *p = &bitmap.pix(y);
+
+ if (de)
+ {
+ u8 screen_inv = m_reverse_video ? 0xff : 0x00;
+
+ if (m_graphic_mode)
+ {
+ for (int x = 0; x < x_count; x++)
+ {
+ u8 const gfx = m_p_videoram[((ma << 1) + (ra * x_count) + x) & 0x3fff] ^ screen_inv;
+
+ for (int b = 0; 8 > b; ++b)
+ {
+ *p++ = palette[BIT(gfx, b)];
+ }
+ }
+ }
+ else
+ {
+ u16 const base = m_char_gen_a11 ? 0x800 : 0x0;
+
+ for (int x = 0; x < x_count; x++)
+ {
+ u8 inv = (x == cursor_x) ? 0xff : 0;
+ u8 chr = m_p_videoram[(ma + x) & 0x3fff];
+
+ if (chr & 0x80)
+ {
+ inv ^= 0xff;
+ chr &= 0x7f;
+ }
+
+ inv ^= screen_inv;
+
+ // select proper character set
+ u8 const gfx = m_p_chargen[base | (chr << 4) | ra] ^ inv;
+
+ // Display a scanline of a character (8 pixels)
+ for (int b = 0; 8 > b; ++b)
+ {
+ *p++ = palette[BIT(gfx, b)];
+ }
+ }
+ }
+ }
+ else
+ {
+ std::fill_n(p, x_count * 8, palette[0]);
+ }
+}
+
+const tiny_rom_entry *heath_gp19_tlb_device::device_rom_region() const
+{
+ return ROM_NAME(gp19);
+}
+
+ioport_constructor heath_gp19_tlb_device::device_input_ports() const
+{
+ return INPUT_PORTS_NAME(gp19);
+}
+
+
+/**
+ * Cleveland Codonics Imaginator-100 (I-100) add-in board
+ *
+ * Memory Range Description
+ * -----------------------------------------------------------------
+ * 0x0000-0x1fff Program ROM (Heath TLB board)
+ * 0x2000-0x3fff Graphics Command Processor(GCP) ROM (I-100)
+ * 0x4000-0x5fff Scratchpad RAM (Heath TLB board)
+ * 0x6000-0x7fff Graphics Scratchpad R/W RAM (I-100)
+ * 0x8000-0xbfff Graphics Display R/W RAM(I-100)
+ * 0xc000-0xdfff Optional Graphics Command Processor memory (I-100)
+ * 0xe000-0xffff Display Memory (Heath TLB board)
+ *
+ * New interrupt source
+ * - horizontal retrace interrupt
+ *
+ */
+heath_imaginator_tlb_device::heath_imaginator_tlb_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock) :
+ heath_tlb_device(mconfig, HEATH_IMAGINATOR, tag, owner, clock),
+ m_mem_bank(*this, "membank"),
+ m_p_graphic_ram(*this, "graphicram")
+{
+}
+
+void heath_imaginator_tlb_device::device_add_mconfig(machine_config &config)
+{
+ heath_tlb_device::device_add_mconfig(config);
+
+ m_maincpu->set_addrmap(AS_PROGRAM, &heath_imaginator_tlb_device::mem_map);
+ m_maincpu->set_addrmap(AS_IO, &heath_imaginator_tlb_device::io_map);
+ m_maincpu->set_irq_acknowledge_callback(FUNC(heath_imaginator_tlb_device::irq_ack_cb));
+
+ m_crtc->out_hsync_callback().set(FUNC(heath_imaginator_tlb_device::crtc_hsync_w));
+}
+
+void heath_imaginator_tlb_device::device_start()
+{
+ heath_tlb_device::device_start();
+
+ save_item(NAME(m_im2_val));
+ save_item(NAME(m_alphanumeric_mode_active));
+ save_item(NAME(m_graphics_mode_active));
+ save_item(NAME(m_allow_tlb_interrupts));
+ save_item(NAME(m_allow_imaginator_interrupts));
+ save_item(NAME(m_hsync_irq_raised));
+
+ m_mem_bank->configure_entries(0, 2, memregion("maincpu")->base(), 0x2000);
+
+ m_maincpu->space(AS_PROGRAM).install_readwrite_tap(0x8000, 0xbfff, "irq_update",
+ [this] (offs_t offset, u8 &data, u8 mem_mask) { if (!machine().side_effects_disabled()) { tap_8000h(); } },
+ [this] (offs_t offset, u8 &data, u8 mem_mask) { if (!machine().side_effects_disabled()) { tap_8000h(); } });
+}
+
+void heath_imaginator_tlb_device::device_reset()
+{
+ heath_tlb_device::device_reset();
+
+ m_mem_bank->set_entry(1);
+ m_tap_6000h.remove();
+ m_tap_6000h = m_maincpu->space(AS_PROGRAM).install_readwrite_tap(0x6000, 0x7fff, "mem_map_update",
+ [this] (offs_t offset, u8 &data, u8 mem_mask) { if (!machine().side_effects_disabled()) { tap_6000h(); } },
+ [this] (offs_t offset, u8 &data, u8 mem_mask) { if (!machine().side_effects_disabled()) { tap_6000h(); } });
+
+ m_alphanumeric_mode_active = true;
+ m_graphics_mode_active = false;
+
+ m_hsync_irq_raised = false;
+
+ allow_tlb_intr();
+}
+
+void heath_imaginator_tlb_device::mem_map(address_map &map)
+{
+ map.unmap_value_high();
+
+ map(0x0000, 0x1fff).bankr(m_mem_bank);
+
+ // Normal spot of the GCP ROM
+ map(0x2000, 0x3fff).rom();
+
+ // TLB Scratchpad
+ map(0x4000, 0x40ff).mirror(0x1f00).ram();
+
+ // GCP Scratchpad
+ map(0x6000, 0x607f).mirror(0x1f80).ram();
+
+ // Graphics RAM
+ map(0x8000, 0xbfff).ram().share(m_p_graphic_ram);
+
+ // optional Graphics Command Processor (GCP)
+ // map(0xc000, 0xdfff);
+
+ // Alphanumeric RAM
+ map(0xe000, 0xe7ff).mirror(0x1800).ram().share(m_p_videoram);
+}
+
+void heath_imaginator_tlb_device::tap_6000h()
+{
+ m_mem_bank->set_entry(0);
+ m_tap_6000h.remove();
+}
+
+void heath_imaginator_tlb_device::tap_8000h()
+{
+ if (!m_allow_tlb_interrupts)
+ {
+ allow_tlb_intr();
+
+ set_irq_line();
+ }
+}
+
+void heath_imaginator_tlb_device::allow_tlb_intr()
+{
+ m_allow_tlb_interrupts = true;
+ m_allow_imaginator_interrupts = false;
+ m_im2_val = 0x02;
+}
+
+void heath_imaginator_tlb_device::allow_hsync_intr()
+{
+ m_allow_tlb_interrupts = false;
+ m_allow_imaginator_interrupts = true;
+ m_im2_val = 0x00;
+}
+
+/**
+ * An input/output request (IORQ) is sent to the TERMINAL LOGIC board only when
+ * both IORQ (pin 20 of U7) AND A4 are low.
+ */
+void heath_imaginator_tlb_device::io_map(address_map &map)
+{
+ heath_tlb_device::io_map(map);
+
+ // interrupt routing
+ map(0x10, 0x10).select(0x08).mirror(0x07).w(FUNC(heath_imaginator_tlb_device::config_irq_w));
+
+ // display enabling (graphics or alphanumeric)
+ map(0x30, 0x30).select(0xc0).mirror(0x0f).w(FUNC(heath_imaginator_tlb_device::display_enable_w));
+
+ // Avoids writes to TLB when a4 is high on unused
+ map(0x50, 0x50).select(0x80).mirror(0x0f).w(FUNC(heath_imaginator_tlb_device::nop_w));
+}
+
+IRQ_CALLBACK_MEMBER(heath_imaginator_tlb_device::irq_ack_cb)
+{
+ return m_im2_val;
+}
+
+void heath_imaginator_tlb_device::config_irq_w(offs_t reg, u8 val)
+{
+ if (BIT(reg, 3))
+ {
+ allow_tlb_intr();
+ }
+ else
+ {
+ allow_hsync_intr();
+ }
+
+ set_irq_line();
+}
+
+void heath_imaginator_tlb_device::display_enable_w(offs_t reg, u8 val)
+{
+ m_alphanumeric_mode_active = bool(BIT(reg, 7));
+ m_graphics_mode_active = bool(BIT(reg, 6));
+}
+
+void heath_imaginator_tlb_device::nop_w(offs_t, u8)
+{
+}
+
+const tiny_rom_entry *heath_imaginator_tlb_device::device_rom_region() const
+{
+ return ROM_NAME(imaginator);
+}
+
+MC6845_UPDATE_ROW(heath_imaginator_tlb_device::crtc_update_row)
+{
+ rgb_t const *const palette = m_palette->palette()->entry_list_raw();
+ u32 *p = &bitmap.pix(y);
+
+ if (de)
+ {
+ for (int x = 0; x < x_count; x++)
+ {
+ u8 output = 0x00;
+
+ if (m_alphanumeric_mode_active)
+ {
+ u8 inv = (x == cursor_x) ? 0xff : 0;
+ u8 chr = m_p_videoram[(ma + x) & 0x7ff];
+
+ if (chr & 0x80)
+ {
+ inv ^= 0xff;
+ chr &= 0x7f;
+ }
+
+ output |= m_p_chargen[(chr << 4) | ra] ^ inv;
+ }
+
+ if (m_graphics_mode_active && (x > 7 ) && (x < 73))
+ {
+ output |= m_p_graphic_ram[((y * 64) + (x - 8)) & 0x3fff];
+ }
+
+ for (int b = 0; 8 > b; ++b)
+ {
+ *p++ = palette[BIT(output, b)];
+ }
+ }
+ }
+ else
+ {
+ std::fill_n(p, x_count * 8, palette[0]);
+ }
+}
+
+void heath_imaginator_tlb_device::crtc_hsync_w(int val)
+{
+ m_hsync_irq_raised = bool(val);
+
+ set_irq_line();
+}
+
+void heath_imaginator_tlb_device::set_irq_line()
+{
+ m_maincpu->set_input_line(INPUT_LINE_IRQ0,
+ (m_allow_imaginator_interrupts && m_hsync_irq_raised) ||
+ (m_allow_tlb_interrupts && (m_keyboard_irq_raised || m_serial_irq_raised || m_break_key_irq_raised)) ?
+ ASSERT_LINE : CLEAR_LINE);
+}
+
+
+/**
+ * SigmaSoft Interactive Graphics Controller (IGC)
+ *
+ *
+ */
+heath_igc_tlb_device::heath_igc_tlb_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock) :
+ heath_igc_tlb_device(mconfig, HEATH_IGC, tag, owner, clock)
+{
+}
+
+heath_igc_tlb_device::heath_igc_tlb_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, u32 clock) :
+ heath_tlb_device(mconfig, type, tag, owner, clock),
+ m_joystick1(*this, "joystick_p1"),
+ m_joystick2(*this, "joystick_p2")
+{
+}
+
+ioport_constructor heath_igc_tlb_device::device_input_ports() const
+{
+ return INPUT_PORTS_NAME(igc);
+}
+
+void heath_igc_tlb_device::device_add_mconfig(machine_config &config)
+{
+ heath_tlb_device::device_add_mconfig(config);
+
+ m_crtc->set_update_row_callback(FUNC(heath_igc_tlb_device::crtc_update_row));
+}
+
+void heath_igc_tlb_device::device_start()
+{
+ heath_tlb_device::device_start();
+
+ m_p_graphic_ram = make_unique_clear<u8[]>(0x3ffff);
+ save_pointer(NAME(m_p_graphic_ram), 0x3ffff);
+
+ save_item(NAME(m_data_reg));
+ save_item(NAME(m_pixel_video_enabled));
+ save_item(NAME(m_character_video_disabled));
+ save_item(NAME(m_video_invert_enabled));
+ save_item(NAME(m_alternate_character_set_enabled));
+ save_item(NAME(m_video_fill_enabled));
+ save_item(NAME(m_read_address_increment_disabled));
+ save_item(NAME(m_memory_bank_select));
+ save_item(NAME(m_io_address));
+ save_item(NAME(m_window_address));
+}
+
+void heath_igc_tlb_device::device_reset()
+{
+ heath_tlb_device::device_reset();
+
+ sigma_ctrl_w(0);
+ m_data_reg = 0x00;
+ m_io_address = 0x0000;
+ m_window_address = 0x0000;
+}
+
+void heath_igc_tlb_device::sigma_w(u8 offset, u8 data)
+{
+ switch (offset)
+ {
+ case 0:
+ sigma_video_mem_w(data);
+ break;
+ case 1:
+ sigma_io_lo_addr_w(data);
+ break;
+ case 2:
+ sigma_io_hi_addr_w(data);
+ break;
+ case 3:
+ sigma_window_lo_addr_w(data);
+ break;
+ case 4:
+ sigma_window_hi_addr_w(data);
+ break;
+ case 5:
+ sigma_ctrl_w(data);
+ break;
+ }
+}
+
+u8 heath_igc_tlb_device::sigma_r(u8 offset)
+{
+ u8 val = 0;
+
+ switch (offset)
+ {
+ case 0:
+ val = sigma_video_mem_r();
+ break;
+ case 1:
+ // TODO - Low pen address
+ break;
+ case 2:
+ // TODO - High pen address
+ break;
+ case 3:
+ // Left input device
+ val = m_joystick1->read();
+ break;
+ case 4:
+ // Right input device
+ val = m_joystick2->read();
+ break;
+ case 5:
+ val = sigma_ctrl_r();
+ break;
+ }
+
+ return val;
+}
+
+void heath_igc_tlb_device::sigma_ctrl_w(u8 data)
+{
+ LOGREG("%s: data: %02x\n", FUNCNAME, data);
+
+ m_pixel_video_enabled = bool(BIT(data, 0));
+ m_character_video_disabled = bool(BIT(data, 1));
+ m_video_invert_enabled = bool(BIT(data, 2));
+ m_alternate_character_set_enabled = bool(BIT(data, 3));
+ m_video_fill_enabled = bool(BIT(data, 4));
+ m_read_address_increment_disabled = bool(BIT(data, 5));
+
+ m_memory_bank_select = bitswap<2>(data, 6, 7);
+
+ if (m_video_fill_enabled)
+ {
+ std::fill_n(&m_p_graphic_ram[(m_memory_bank_select << 16) & 0x3ffff], 0x10000, m_data_reg);
+ }
+}
+
+u8 heath_igc_tlb_device::sigma_ctrl_r()
+{
+ u8 ret_val = 0x00;
+
+ ret_val |= m_pixel_video_enabled ? 0x01 : 0x00;
+ ret_val |= m_character_video_disabled ? 0x02 : 0x00;
+ ret_val |= m_video_invert_enabled ? 0x04 : 0x00;
+ ret_val |= m_alternate_character_set_enabled ? 0x08 : 0x00;
+ ret_val |= m_video_fill_enabled ? 0x10 : 0x00;
+ ret_val |= m_read_address_increment_disabled ? 0x20 : 0x00;
+
+ ret_val |= bitswap<2>(m_memory_bank_select, 0, 1) << 6;
+
+ LOGREG("%s: ret_val: %02x\n", FUNCNAME, ret_val);
+
+ return ret_val;
+}
+
+void heath_igc_tlb_device::sigma_video_mem_w(u8 data)
+{
+ LOGREG("%s: data: %02x\n", FUNCNAME, data);
+
+ m_data_reg = data;
+
+ m_p_graphic_ram[(m_memory_bank_select << 16) + m_io_address++] = data;
+}
+
+u8 heath_igc_tlb_device::sigma_video_mem_r()
+{
+ // control whether m_io_address is incremented during a read
+ u32 addr = (m_read_address_increment_disabled || machine().side_effects_disabled()) ?
+ ((m_memory_bank_select << 16) + m_io_address) :
+ ((m_memory_bank_select << 16) + m_io_address++);
+
+ return m_p_graphic_ram[addr];
+}
+
+void heath_igc_tlb_device::sigma_io_lo_addr_w(u8 data)
+{
+ LOGREG("%s: data: %02x\n", FUNCNAME, data);
+
+ m_io_address = (m_io_address & 0xff00) | data;
+}
+
+void heath_igc_tlb_device::sigma_io_hi_addr_w(u8 data)
+{
+ LOGREG("%s: data: %02x\n", FUNCNAME, data);
+
+ m_io_address = (data << 8) | (m_io_address & 0x00ff);
+}
+
+void heath_igc_tlb_device::sigma_window_lo_addr_w(u8 data)
+{
+ LOGREG("%s: data: %02x\n", FUNCNAME, data);
+
+ m_window_address = (m_window_address & 0xff00) | data;
+}
+
+void heath_igc_tlb_device::sigma_window_hi_addr_w(u8 data)
+{
+ LOGREG("%s: data: %02x\n", FUNCNAME, data);
+
+ m_window_address = (data << 8) | (m_window_address & 0x00ff);
+}
+
+MC6845_UPDATE_ROW(heath_igc_tlb_device::crtc_update_row)
+{
+ rgb_t const *const palette = m_palette->palette()->entry_list_raw();
+ u32 *p = &bitmap.pix(y);
+
+ if (de)
+ {
+ u8 video_invert = m_video_invert_enabled ? 0xff : 0;
+
+ for (int x = 0; x < x_count; x++)
+ {
+ u8 output = 0x00;
+
+ if (!m_character_video_disabled)
+ {
+ u8 inv = (x == cursor_x) ? 0xff : 0;
+ u8 chr = m_p_videoram[(ma + x) & 0x7ff];
+
+ if (chr & 0x80)
+ {
+ inv ^= 0xff;
+ chr &= 0x7f;
+ }
+
+ // TODO handle alt font
+ output |= m_p_chargen[(chr << 4) | ra] ^ inv;
+ }
+
+ if (m_pixel_video_enabled)
+ {
+ output |= m_p_graphic_ram[(((y * 80) + x) + m_window_address) & 0xffff];
+ }
+
+ output ^= video_invert;
+
+ for (int b = 0; 8 > b; ++b)
+ {
+ *p++ = palette[BIT(output, b)];
+ }
+ }
+ }
+ else
+ {
+ std::fill_n(p, x_count * 8, palette[0]);
+ }
+}
+
+
+/**
+ * SigmaSoft and Systems IGC plus TLB with Super-19 ROM
+ *
+ */
+heath_igc_super19_tlb_device::heath_igc_super19_tlb_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock) :
+ heath_igc_tlb_device(mconfig, HEATH_IGC_SUPER19, tag, owner, clock)
+{
+}
+
+const tiny_rom_entry *heath_igc_super19_tlb_device::device_rom_region() const
+{
+ return ROM_NAME(super19);
+}
+
+ioport_constructor heath_igc_super19_tlb_device::device_input_ports() const
+{
+ return INPUT_PORTS_NAME(igc_super19);
+}
+
+
+/**
+ * SigmaSoft and Systems IGC plus TLB with UltraROM
+ *
+ */
+heath_igc_ultra_tlb_device::heath_igc_ultra_tlb_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock) :
+ heath_igc_tlb_device(mconfig, HEATH_IGC_ULTRA, tag, owner, clock),
+ m_maincpu_region(*this, "maincpu"),
+ m_page_2_ram(*this, "page2ram"),
+ m_mem_view(*this, "mem")
+{
+}
+
+void heath_igc_ultra_tlb_device::device_reset()
+{
+ heath_igc_tlb_device::device_reset();
+
+ ioport_value const cfg(m_config->read());
+
+ // Page 2 memory
+ m_mem_view.select(BIT(cfg, 4));
+}
+
+void heath_igc_ultra_tlb_device::device_add_mconfig(machine_config &config)
+{
+ heath_igc_tlb_device::device_add_mconfig(config);
+
+ m_maincpu->set_addrmap(AS_PROGRAM, &heath_igc_ultra_tlb_device::mem_map);
+}
+
+void heath_igc_ultra_tlb_device::mem_map(address_map &map)
+{
+ heath_tlb_device::mem_map(map);
+
+ map(0x0000, 0x3fff).view(m_mem_view);
+
+ m_mem_view[0](0x0000, 0x0fff).mirror(0x3000).rom().region(m_maincpu_region, 0x0000).unmapw();
+ m_mem_view[1](0x0000, 0x0fff).mirror(0x2000).rom().region(m_maincpu_region, 0x0000).unmapw();
+ m_mem_view[1](0x1000, 0x1fff).mirror(0x2000).ram().share(m_page_2_ram);
+}
+
+const tiny_rom_entry *heath_igc_ultra_tlb_device::device_rom_region() const
+{
+ return ROM_NAME(ultra19);
+}
+
+ioport_constructor heath_igc_ultra_tlb_device::device_input_ports() const
+{
+ return INPUT_PORTS_NAME(igc_ultra);
+}
+
+
+/**
+ * SigmaSoft and Systems IGC plus TLB with Watzman ROM
+ *
+ */
+heath_igc_watz_tlb_device::heath_igc_watz_tlb_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock) :
+ heath_igc_tlb_device(mconfig, HEATH_IGC_WATZ, tag, owner, clock)
+{
+}
+
+const tiny_rom_entry *heath_igc_watz_tlb_device::device_rom_region() const
+{
+ return ROM_NAME(watz19);
+}
+
+ioport_constructor heath_igc_watz_tlb_device::device_input_ports() const
+{
+ return INPUT_PORTS_NAME(igc_watz);
+}
+
+
+/**
+ * Terminal Logic Board Connector
+ *
+ */
+heath_tlb_connector::heath_tlb_connector(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock) :
+ device_t(mconfig, HEATH_TLB_CONNECTOR, tag, owner, clock),
+ device_single_card_slot_interface(mconfig, *this),
+ m_write_sd(*this),
+ m_dtr_cb(*this),
+ m_rts_cb(*this),
+ m_reset(*this),
+ m_tlb(nullptr)
+{
+}
+
+heath_tlb_connector::~heath_tlb_connector()
+{
+}
+
+void heath_tlb_connector::device_start()
+{
+ m_tlb = get_card_device();
+}
diff --git a/src/devices/bus/heathzenith/h19/tlb.h b/src/devices/bus/heathzenith/h19/tlb.h
new file mode 100644
index 00000000000..216dc80f3b0
--- /dev/null
+++ b/src/devices/bus/heathzenith/h19/tlb.h
@@ -0,0 +1,480 @@
+// license:BSD-3-Clause
+// copyright-holders:Mark Garlanger
+/***************************************************************************
+
+ Heathkit Terminal Logic Board (TLB)
+
+****************************************************************************/
+
+#ifndef MAME_BUS_HEATHZENITH_H19_TLB_H
+#define MAME_BUS_HEATHZENITH_H19_TLB_H
+
+#pragma once
+
+#include "cpu/z80/z80.h"
+#include "machine/clock.h"
+#include "machine/ins8250.h"
+#include "machine/mm5740.h"
+#include "sound/beep.h"
+#include "video/mc6845.h"
+
+#include "emupal.h"
+#include "screen.h"
+#include "speaker.h"
+
+
+class heath_tlb_connector;
+
+class device_heath_tlb_card_interface : public device_interface
+{
+public:
+
+ // required operation
+ virtual void serial_in_w(int state) = 0;
+
+ // optional operations
+ virtual void rlsd_in_w(int state) {}
+ virtual void dsr_in_w(int state) {}
+ virtual void cts_in_w(int state) {}
+
+ // optional SigmaSet operations
+ virtual void sigma_w(u8 offset, u8 data) {}
+ virtual u8 sigma_r(u8 offset) { return 0x00; }
+
+protected:
+ device_heath_tlb_card_interface(const machine_config &mconfig, device_t &device);
+
+ heath_tlb_connector *const m_slot;
+};
+
+
+/**
+ * Standard Heath Terminal logic board
+ */
+class heath_tlb_device : public device_t,
+ public device_heath_tlb_card_interface
+{
+public:
+ heath_tlb_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock = 0);
+
+ // 8250 UART
+ virtual void serial_in_w(int state) override;
+ virtual void rlsd_in_w(int state) override;
+ virtual void dsr_in_w(int state) override;
+ virtual void cts_in_w(int state) override;
+ void serial_irq_w(int state);
+
+ // Keyboard
+ void reset_key_w(int state);
+ void right_shift_w(int state);
+ void repeat_key_w(int state);
+ void break_key_w(int state);
+
+protected:
+ heath_tlb_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, u32 clock = 0);
+
+ virtual ioport_constructor device_input_ports() const override ATTR_COLD;
+ virtual const tiny_rom_entry *device_rom_region() const override ATTR_COLD;
+ 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;
+
+ void mem_map(address_map &map) ATTR_COLD;
+ void io_map(address_map &map) ATTR_COLD;
+
+
+ // interrupt related
+ virtual void set_irq_line();
+
+ // reset
+ void check_for_reset();
+
+ // sound/speaker
+ void check_beep_state();
+ void key_click_w(u8 data);
+ void bell_w(u8 data);
+ TIMER_CALLBACK_MEMBER(key_click_off);
+ TIMER_CALLBACK_MEMBER(bell_off);
+
+ // keyboard
+ u8 kbd_key_r();
+ u8 kbd_flags_r();
+ u16 translate_mm5740_b(u16 b);
+ int mm5740_shift_r();
+ int mm5740_control_r();
+ void mm5740_data_ready_w(int state);
+
+ // serial port
+ void serial_out_b(int data);
+ void dtr_out(int data);
+ void rts_out(int data);
+
+ // crtc
+ void crtc_addr_w(offs_t reg, u8 val);
+ virtual u8 crtc_reg_r(offs_t reg);
+ virtual void crtc_reg_w(offs_t reg, u8 val);
+ void crtc_vsync_w(int val);
+ virtual MC6845_UPDATE_ROW(crtc_update_row);
+
+ required_device<cpu_device> m_maincpu;
+ required_device<screen_device> m_screen;
+ required_device<palette_device> m_palette;
+ required_device<mc6845_device> m_crtc;
+ required_shared_ptr<u8> m_p_videoram;
+ required_region_ptr<u8> m_p_chargen;
+ required_ioport m_config;
+ required_device<ins8250_device> m_ace;
+ required_device<beep_device> m_beep;
+ required_device<mm5740_device> m_mm5740;
+ required_memory_region m_kbdrom;
+ required_ioport m_kbspecial;
+ required_device<clock_device> m_repeat_clock;
+
+ emu_timer *m_key_click_timer;
+ emu_timer *m_bell_timer;
+
+ u8 m_transchar;
+ bool m_strobe;
+ bool m_key_click_active;
+ bool m_bell_active;
+ bool m_reset_pending;
+ bool m_right_shift;
+ bool m_reset_key;
+ bool m_keyboard_irq_raised;
+ bool m_serial_irq_raised;
+ bool m_break_key_irq_raised;
+ bool m_allow_vsync_nmi;
+};
+
+/**
+ * Heath TLB with Super19 ROM
+ */
+class heath_super19_tlb_device : public heath_tlb_device
+{
+public:
+ heath_super19_tlb_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock = 0);
+
+protected:
+ virtual const tiny_rom_entry *device_rom_region() const override ATTR_COLD;
+ virtual ioport_constructor device_input_ports() const override ATTR_COLD;
+};
+
+/**
+ * Heath TLB with Superset ROM
+ */
+class heath_superset_tlb_device : public heath_tlb_device
+{
+public:
+ heath_superset_tlb_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock = 0);
+
+protected:
+ virtual const tiny_rom_entry *device_rom_region() const override ATTR_COLD;
+ virtual ioport_constructor device_input_ports() const override ATTR_COLD;
+
+ virtual void device_start() override ATTR_COLD;
+ virtual void device_add_mconfig(machine_config &config) override ATTR_COLD;
+
+ void mem_map(address_map &map) ATTR_COLD;
+ void io_map(address_map &map) ATTR_COLD;
+
+ virtual MC6845_UPDATE_ROW(crtc_update_row) override;
+
+ void dtr_internal(int data);
+ void out1_internal(int data);
+ void out2_internal(int data);
+
+ virtual u8 crtc_reg_r(offs_t reg) override;
+ virtual void crtc_reg_w(offs_t reg, u8 val) override;
+
+ u8 m_selected_char_set;
+ bool m_reverse_video_disabled;
+};
+
+/**
+ * Heath TLB with Watzman (HUG) ROM
+ */
+class heath_watz_tlb_device : public heath_tlb_device
+{
+public:
+ heath_watz_tlb_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock = 0);
+
+protected:
+ virtual const tiny_rom_entry *device_rom_region() const override ATTR_COLD;
+ virtual ioport_constructor device_input_ports() const override ATTR_COLD;
+};
+
+/**
+ * Heath TLB with Ultra ROM
+ */
+class heath_ultra_tlb_device : public heath_tlb_device
+{
+public:
+ heath_ultra_tlb_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock = 0);
+
+protected:
+ virtual const tiny_rom_entry *device_rom_region() const override ATTR_COLD;
+ virtual ioport_constructor device_input_ports() const override ATTR_COLD;
+ virtual void device_reset() override ATTR_COLD;
+ virtual void device_add_mconfig(machine_config &config) override ATTR_COLD;
+
+ void mem_map(address_map &map) ATTR_COLD;
+
+ required_memory_region m_maincpu_region;
+ required_shared_ptr<u8> m_page_2_ram;
+ memory_view m_mem_view;
+};
+
+/**
+ * Heath TLB plus Northwest Digital Systems GP-19
+ */
+class heath_gp19_tlb_device : public heath_tlb_device
+{
+public:
+ heath_gp19_tlb_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock = 0);
+
+ static constexpr feature_type imperfect_features() { return feature::GRAPHICS; }
+
+protected:
+ virtual const tiny_rom_entry *device_rom_region() const override ATTR_COLD;
+ virtual ioport_constructor device_input_ports() const override ATTR_COLD;
+
+ virtual void device_start() override ATTR_COLD;
+ virtual void device_add_mconfig(machine_config &config) override ATTR_COLD;
+
+ void mem_map(address_map &map) ATTR_COLD;
+ void io_map(address_map &map) ATTR_COLD;
+
+ void latch_u5_w(u8 data);
+
+ virtual MC6845_UPDATE_ROW(crtc_update_row) override;
+
+ bool m_char_gen_a11;
+ bool m_graphic_mode;
+ bool m_col_132;
+ bool m_reverse_video;
+};
+
+/**
+ * Heath TLB plus Cleveland Codonics Imaginator-100
+ */
+class heath_imaginator_tlb_device : public heath_tlb_device
+{
+public:
+ heath_imaginator_tlb_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock = 0);
+
+protected:
+ virtual const tiny_rom_entry *device_rom_region() const override ATTR_COLD;
+
+ 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;
+
+ void mem_map(address_map &map) ATTR_COLD;
+ void io_map(address_map &map) ATTR_COLD;
+
+ virtual MC6845_UPDATE_ROW(crtc_update_row) override;
+ void crtc_hsync_w(int val);
+
+ IRQ_CALLBACK_MEMBER(irq_ack_cb);
+
+ void tap_6000h();
+ void tap_8000h();
+
+ void allow_tlb_intr();
+ void allow_hsync_intr();
+
+ void display_enable_w(offs_t reg, u8 val);
+ void config_irq_w(offs_t reg, u8 val);
+ void nop_w(offs_t reg, u8 val);
+ virtual void set_irq_line() override;
+
+ required_memory_bank m_mem_bank;
+ required_shared_ptr<u8> m_p_graphic_ram;
+ memory_passthrough_handler m_tap_6000h;
+
+ u8 m_im2_val;
+
+ bool m_alphanumeric_mode_active;
+ bool m_graphics_mode_active;
+
+ bool m_allow_tlb_interrupts;
+ bool m_allow_imaginator_interrupts;
+
+ bool m_hsync_irq_raised;
+};
+
+/**
+ * Heath TLB plus SigmaSoft Interactive Graphics Controller
+ */
+class heath_igc_tlb_device : public heath_tlb_device
+{
+public:
+ heath_igc_tlb_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock = 0);
+
+ virtual void sigma_w(u8 offset, u8 data) override;
+ virtual u8 sigma_r(u8 offset) override;
+
+protected:
+ heath_igc_tlb_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, u32 clock = 0);
+
+ virtual ioport_constructor device_input_ports() const override ATTR_COLD;
+ 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;
+
+ virtual MC6845_UPDATE_ROW(crtc_update_row) override;
+
+ virtual void sigma_ctrl_w(u8 data);
+ virtual u8 sigma_ctrl_r();
+
+ u8 sigma_video_mem_r();
+ void sigma_video_mem_w(u8 val);
+
+ void sigma_io_lo_addr_w(u8 val);
+ void sigma_io_hi_addr_w(u8 val);
+
+ void sigma_window_lo_addr_w(u8 val);
+ void sigma_window_hi_addr_w(u8 val);
+
+
+ std::unique_ptr<u8[]> m_p_graphic_ram;
+
+ // Control Register
+ bool m_pixel_video_enabled;
+ bool m_character_video_disabled;
+ bool m_video_invert_enabled;
+ bool m_alternate_character_set_enabled;
+ bool m_video_fill_enabled;
+ bool m_read_address_increment_disabled;
+ u8 m_memory_bank_select;
+
+ u8 m_data_reg;
+
+ u16 m_io_address;
+ u16 m_window_address;
+private:
+ required_ioport m_joystick1, m_joystick2;
+
+};
+
+/**
+ * Heath TLB with the super19 ROM plus SigmaSoft Interactive Graphics Controller
+ */
+class heath_igc_super19_tlb_device : public heath_igc_tlb_device
+{
+public:
+ heath_igc_super19_tlb_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock = 0);
+
+protected:
+ virtual const tiny_rom_entry *device_rom_region() const override ATTR_COLD;
+ virtual ioport_constructor device_input_ports() const override ATTR_COLD;
+};
+
+/**
+ * Heath TLB with the ultrarom plus SigmaSoft Interactive Graphics Controller
+ */
+class heath_igc_ultra_tlb_device : public heath_igc_tlb_device
+{
+public:
+ heath_igc_ultra_tlb_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock = 0);
+
+protected:
+ virtual const tiny_rom_entry *device_rom_region() const override ATTR_COLD;
+ virtual ioport_constructor device_input_ports() const override ATTR_COLD;
+ virtual void device_reset() override ATTR_COLD;
+ virtual void device_add_mconfig(machine_config &config) override ATTR_COLD;
+
+ void mem_map(address_map &map) ATTR_COLD;
+
+ required_memory_region m_maincpu_region;
+ required_shared_ptr<u8> m_page_2_ram;
+ memory_view m_mem_view;
+};
+
+/**
+ * Heath TLB with the watzman ROM plus SigmaSoft Interactive Graphics Controller
+ */
+class heath_igc_watz_tlb_device : public heath_igc_tlb_device
+{
+public:
+ heath_igc_watz_tlb_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock = 0);
+
+protected:
+ virtual const tiny_rom_entry *device_rom_region() const override ATTR_COLD;
+ virtual ioport_constructor device_input_ports() const override ATTR_COLD;
+};
+
+// Options for the standard H89 class of systems
+DECLARE_DEVICE_TYPE(HEATH_TLB, heath_tlb_device)
+DECLARE_DEVICE_TYPE(HEATH_GP19, heath_gp19_tlb_device)
+DECLARE_DEVICE_TYPE(HEATH_IMAGINATOR, heath_imaginator_tlb_device)
+DECLARE_DEVICE_TYPE(HEATH_SUPER19, heath_super19_tlb_device)
+DECLARE_DEVICE_TYPE(HEATH_SUPERSET, heath_superset_tlb_device)
+DECLARE_DEVICE_TYPE(HEATH_WATZ, heath_watz_tlb_device)
+DECLARE_DEVICE_TYPE(HEATH_ULTRA, heath_ultra_tlb_device)
+
+// Options for the H89 with the SigmaSoft IGC graphics installed
+DECLARE_DEVICE_TYPE(HEATH_IGC, heath_igc_tlb_device)
+DECLARE_DEVICE_TYPE(HEATH_IGC_SUPER19, heath_igc_super19_tlb_device)
+DECLARE_DEVICE_TYPE(HEATH_IGC_ULTRA, heath_igc_ultra_tlb_device)
+DECLARE_DEVICE_TYPE(HEATH_IGC_WATZ, heath_igc_watz_tlb_device)
+
+/**
+ * Connector for the Terminal Logic Board in an H-89 class computer
+ */
+class heath_tlb_connector : public device_t,
+ public device_single_card_slot_interface<device_heath_tlb_card_interface>
+{
+public:
+
+ template <typename T>
+ heath_tlb_connector(const machine_config &mconfig, const char *tag, device_t *owner, T &&opts, const char *dflt, bool fixed = false) :
+ heath_tlb_connector(mconfig, tag, owner, 0)
+ {
+ option_reset();
+ opts(*this);
+ set_default_option(dflt);
+ set_fixed(fixed);
+ }
+
+ heath_tlb_connector(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock = 0);
+ virtual ~heath_tlb_connector();
+
+ // computer interface
+ auto serial_data_callback() { return m_write_sd.bind(); }
+ auto dtr_callback() { return m_dtr_cb.bind(); }
+ auto rts_callback() { return m_rts_cb.bind(); }
+ auto reset_cb() { return m_reset.bind(); }
+
+ // card interface
+ void serial_in_w(int state) { if (m_tlb) m_tlb->serial_in_w(state); }
+ void rlsd_in_w(int state) { if (m_tlb) m_tlb->rlsd_in_w(state); }
+ void dsr_in_w(int state) { if (m_tlb) m_tlb->dsr_in_w(state); }
+ void cts_in_w(int state) { if (m_tlb) m_tlb->cts_in_w(state); }
+
+ // signals out from the tlb
+ void serial_out_b(int data) { m_write_sd(data); }
+ void dtr_out(int data) { m_dtr_cb(data); }
+ void rts_out(int data) { m_rts_cb(data); }
+ void reset_out(int data) { m_reset(data); }
+
+ // optional SigmaSet IGC operations
+ u8 sigma_r(u8 offset) { return (m_tlb) ? m_tlb->sigma_r(offset) : 0x00; }
+ void sigma_w(u8 offset, u8 data) { if (m_tlb) m_tlb->sigma_w(offset, data); }
+
+protected:
+ virtual void device_start() override ATTR_COLD;
+
+ devcb_write_line m_write_sd;
+ devcb_write_line m_dtr_cb;
+ devcb_write_line m_rts_cb;
+ devcb_write_line m_reset;
+
+ device_heath_tlb_card_interface *m_tlb;
+};
+
+
+// device type definition
+DECLARE_DEVICE_TYPE(HEATH_TLB_CONNECTOR, heath_tlb_connector)
+
+#endif // MAME_BUS_HEATHZENITH_H19_TLB_H
diff --git a/src/devices/bus/heathzenith/h89/cdr_fdc_880h.cpp b/src/devices/bus/heathzenith/h89/cdr_fdc_880h.cpp
new file mode 100644
index 00000000000..ed33daa4a88
--- /dev/null
+++ b/src/devices/bus/heathzenith/h89/cdr_fdc_880h.cpp
@@ -0,0 +1,399 @@
+// license:BSD-3-Clause
+// copyright-holders:Mark Garlanger
+/***************************************************************************
+
+ CDR FDC-880H soft-sectored floppy controller
+
+ Supports up to 4 floppy drives, both 5.25" and 8" drives.
+
+****************************************************************************/
+
+#include "emu.h"
+
+#include "cdr_fdc_880h.h"
+
+#include "imagedev/floppy.h"
+#include "machine/wd_fdc.h"
+
+#define LOG_REG (1U << 1) // Shows register setup
+#define LOG_LINES (1U << 2) // Show control lines
+#define LOG_DRIVE (1U << 3) // Show drive select
+#define LOG_FUNC (1U << 4) // Function calls
+#define LOG_ERR (1U << 5) // log errors
+#define LOG_WAIT (1U << 6) // wait mode
+#define LOG_DATA (1U << 7) // data read/writes
+
+#define VERBOSE (0xff)
+
+#include "logmacro.h"
+
+#define LOGREG(...) LOGMASKED(LOG_REG, __VA_ARGS__)
+#define LOGLINES(...) LOGMASKED(LOG_LINES, __VA_ARGS__)
+#define LOGDRIVE(...) LOGMASKED(LOG_DRIVE, __VA_ARGS__)
+#define LOGFUNC(...) LOGMASKED(LOG_FUNC, __VA_ARGS__)
+#define LOGERR(...) LOGMASKED(LOG_ERR, __VA_ARGS__)
+#define LOGWAIT(...) LOGMASKED(LOG_WAIT, __VA_ARGS__)
+#define LOGDATA(...) LOGMASKED(LOG_DATA, __VA_ARGS__)
+
+#ifdef _MSC_VER
+#define FUNCNAME __func__
+#else
+#define FUNCNAME __PRETTY_FUNCTION__
+#endif
+
+
+namespace {
+
+class cdr_fdc_880h_device : public device_t, public device_h89bus_right_card_interface
+{
+public:
+ cdr_fdc_880h_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock = 0);
+
+ virtual void write(u8 select_lines, u8 offset, u8 data) override;
+ virtual u8 read(u8 select_lines, u8 offset) override;
+
+ // The controller has two 16L8 PALs which are not dumped (z15 and z20 from schematics).
+ static constexpr feature_type unemulated_features() { return feature::DISK; }
+
+protected:
+
+ 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;
+
+ void cmd_w(u8 val);
+ void data_w(u8 val);
+ u8 data_r();
+ u8 status_r();
+
+ void set_irq(int state);
+ void set_drq(int state);
+
+private:
+ /// Bits set in cmd_ControlPort_c
+ static constexpr u8 ctrl_EnableIntReq_c = 7;
+ static constexpr u8 ctrl_SetMFMRecording_c = 6;
+ static constexpr u8 ctrl_DriveType_c = 5;
+ static constexpr u8 ctrl_Mode_c = 4;
+
+ static constexpr XTAL MASTER_CLOCK = XTAL(4'000'000);
+ static constexpr XTAL FIVE_IN_CLOCK = MASTER_CLOCK / 4;
+ static constexpr XTAL EIGHT_IN_CLOCK = MASTER_CLOCK / 2;
+
+ required_device<fd1797_device> m_fdc;
+ required_device_array<floppy_connector, 4> m_floppies;
+
+ bool m_irq_allowed;
+
+ bool m_irq;
+ bool m_drq;
+
+ bool m_double_density;
+ bool m_five_in_drive;
+ bool m_mode_operate;
+ s8 m_drive;
+};
+
+
+cdr_fdc_880h_device::cdr_fdc_880h_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock):
+ device_t(mconfig, H89BUS_CDR_FDC_880H, tag, owner, 0),
+ device_h89bus_right_card_interface(mconfig, *this),
+ m_fdc(*this, "cdr_fdc_880h"),
+ m_floppies(*this, "cdr_fdc_880h:%u", 0U)
+{
+}
+
+void cdr_fdc_880h_device::cmd_w(u8 val)
+{
+ LOGREG("%s: val: %d\n", FUNCNAME, val);
+
+ u8 drive = BIT(val, 0, 3);
+
+ if (drive & 0x01)
+ {
+ m_drive = 0;
+ }
+ else if (drive & 0x02)
+ {
+ m_drive = 1;
+ }
+ else if (drive & 0x04)
+ {
+ m_drive = 2;
+ }
+ else if (drive & 0x08)
+ {
+ m_drive = 3;
+ }
+ else
+ {
+ m_drive = -1;
+ }
+ m_mode_operate = bool(BIT(val, ctrl_Mode_c));
+ m_five_in_drive = bool(BIT(val, ctrl_DriveType_c));
+ m_double_density = !bool(BIT(val, ctrl_SetMFMRecording_c));
+ m_irq_allowed = bool(BIT(val, ctrl_EnableIntReq_c));
+
+ m_fdc->dden_w(!m_double_density);
+
+ LOGLINES("%s: intrq allowed: %d\n", FUNCNAME, m_irq_allowed);
+
+ set_slot_int5(m_irq_allowed ? m_irq : CLEAR_LINE);
+
+ LOGDRIVE("%s: floppydrive: %d, 5.25 in: %d\n", FUNCNAME, m_drive, m_five_in_drive);
+
+ if (m_drive >= 0)
+ {
+ m_fdc->set_floppy(m_floppies[m_drive]->get_device());
+ }
+
+ for (auto &elem : m_floppies)
+ {
+ floppy_image_device *floppy = elem->get_device();
+ if (floppy)
+ {
+ floppy->mon_w(m_drive == -1);
+ }
+ }
+
+ m_fdc->set_clock(m_five_in_drive ? FIVE_IN_CLOCK : EIGHT_IN_CLOCK);
+}
+
+void cdr_fdc_880h_device::data_w(u8 val)
+{
+ LOGDATA("%s: val: %d\n", FUNCNAME, val);
+
+ if (!m_drq && !m_irq)
+ {
+ LOGWAIT("%s: wait state\n", FUNCNAME);
+
+ set_slot_wait(ASSERT_LINE);
+ return;
+ }
+
+ m_fdc->data_w(val);
+}
+
+void cdr_fdc_880h_device::write(u8 select_lines, u8 offset, u8 data)
+{
+ if (!(select_lines & h89bus_device::H89_CASS))
+ {
+ return;
+ }
+
+ LOGREG("%s: reg: %d val: 0x%02x\n", FUNCNAME, offset, data);
+
+ switch (offset)
+ {
+ case 0:
+ case 1:
+ case 2:
+ // read not supported on these addresses
+ LOGERR("%s: Unexpected port read reg: %d\n", FUNCNAME, offset);
+ break;
+ case 3: // Select Port
+ cmd_w(data);
+ break;
+ case 4: // Command Port
+ m_fdc->cmd_w(data);
+ break;
+ case 5: // Track Port
+ m_fdc->track_w(data);
+ break;
+ case 6: // Sector Port
+ m_fdc->sector_w(data);
+ break;
+ case 7: // Data Port
+ data_w(data);
+ break;
+ }
+}
+
+u8 cdr_fdc_880h_device::status_r()
+{
+ u8 data = 0;
+
+ switch(m_drive)
+ {
+ case 0:
+ data |= 0x0e;
+ break;
+ case 1:
+ data |= 0x0d;
+ break;
+ case 2:
+ data |= 0x0b;
+ break;
+ case 3:
+ data |= 0x07;
+ break;
+ case -1:
+ default:
+ data |= 0x0f;
+ break;
+ }
+ data |= m_mode_operate ? 0x10 : 0;
+ data |= m_five_in_drive ? 0 : 0x20;
+ data |= m_double_density ? 0x40 : 0;
+ data |= m_irq ? 0 : 0x80;
+
+ return data;
+}
+
+u8 cdr_fdc_880h_device::data_r()
+{
+ u8 data = 0;
+
+ if (!m_drq && !m_irq)
+ {
+ LOGWAIT("%s: wait state\n", FUNCNAME);
+
+ if (!machine().side_effects_disabled())
+ {
+ set_slot_wait(ASSERT_LINE);
+ }
+ }
+ else
+ {
+ data = m_fdc->data_r();
+ }
+
+ LOGDATA("%s: data: %d\n", FUNCNAME, data);
+
+ return data;
+}
+
+u8 cdr_fdc_880h_device::read(u8 select_lines, u8 offset)
+{
+ if (!(select_lines & h89bus_device::H89_CASS))
+ {
+ return 0;
+ }
+
+ u8 value = 0;
+
+ switch (offset)
+ {
+ case 0:
+ case 1:
+ case 2:
+ // read not supported on these addresses
+ LOGERR("%s: Unexpected port read reg: %d\n", FUNCNAME, offset);
+ break;
+ case 3: // ??
+ value = status_r();
+ break;
+ case 4: // Drive Status Port
+ value = m_fdc->status_r();
+ break;
+ case 5: // Track Port
+ value = m_fdc->track_r();
+ break;
+ case 6: // Sector Port
+ value = m_fdc->sector_r();
+ break;
+ case 7: // Data Port
+ value = data_r();
+ break;
+ }
+
+ LOGREG("%s: reg: %d val: 0x%02x\n", FUNCNAME, offset, value);
+
+ return value;
+}
+
+void cdr_fdc_880h_device::device_start()
+{
+ save_item(NAME(m_irq_allowed));
+ save_item(NAME(m_irq));
+ save_item(NAME(m_drq));
+}
+
+void cdr_fdc_880h_device::device_reset()
+{
+ m_irq_allowed = false;
+ m_irq = false;
+
+ set_slot_int5(CLEAR_LINE);
+ set_slot_wait(CLEAR_LINE);
+
+ for (auto &elem : m_floppies)
+ {
+ if (elem)
+ {
+ floppy_image_device *const floppy = elem->get_device();
+ if (floppy)
+ {
+ // turn on motor of all installed 8" floppies
+ floppy->mon_w(0);
+ }
+ }
+ }
+}
+
+static void cdr_floppies(device_slot_interface &device)
+{
+ // 5.25" SS 48tpi
+ device.option_add("5_ss_dd", FLOPPY_525_SSDD);
+ // 5.25" SS 96tpi
+ device.option_add("5_ss_qd", FLOPPY_525_SSQD);
+ // 5.25" DS 48tpi
+ device.option_add("5_ds_dd", FLOPPY_525_DD);
+ // 5.25" DS 96tpi
+ device.option_add("5_ds_qd", FLOPPY_525_QD);
+
+ // 8" SSSD
+ device.option_add("8_ss_sd", FLOPPY_8_SSSD);
+ // 8" DSSD
+ device.option_add("8_ds_sd", FLOPPY_8_DSSD);
+ // 8" SSDD
+ device.option_add("8_ss_dd", FLOPPY_8_SSDD);
+ // 8" DSDD
+ device.option_add("8_ds_dd", FLOPPY_8_DSDD);
+}
+
+void cdr_fdc_880h_device::device_add_mconfig(machine_config &config)
+{
+ FD1797(config, m_fdc, EIGHT_IN_CLOCK);
+ m_fdc->intrq_wr_callback().set(FUNC(cdr_fdc_880h_device::set_irq));
+ m_fdc->drq_wr_callback().set(FUNC(cdr_fdc_880h_device::set_drq));
+
+ FLOPPY_CONNECTOR(config, m_floppies[0], cdr_floppies, "5_ds_qd", floppy_image_device::default_mfm_floppy_formats);
+ m_floppies[0]->enable_sound(true);
+ FLOPPY_CONNECTOR(config, m_floppies[1], cdr_floppies, "5_ds_qd", floppy_image_device::default_mfm_floppy_formats);
+ m_floppies[1]->enable_sound(true);
+ FLOPPY_CONNECTOR(config, m_floppies[2], cdr_floppies, "5_ds_qd", floppy_image_device::default_mfm_floppy_formats);
+ m_floppies[2]->enable_sound(true);
+ FLOPPY_CONNECTOR(config, m_floppies[3], cdr_floppies, "5_ds_qd", floppy_image_device::default_mfm_floppy_formats);
+ m_floppies[3]->enable_sound(true);
+}
+
+void cdr_fdc_880h_device::set_irq(int state)
+{
+ LOGLINES("set irq, allowed: %d state: %d\n", m_irq_allowed, state);
+
+ m_irq = state;
+
+ if (m_irq)
+ {
+ set_slot_wait(CLEAR_LINE);
+ }
+
+ set_slot_int5(m_irq_allowed ? m_irq : CLEAR_LINE);
+}
+
+void cdr_fdc_880h_device::set_drq(int state)
+{
+ LOGLINES("set drq state: %d\n", state);
+
+ m_drq = state;
+
+ if (m_drq)
+ {
+ set_slot_wait(CLEAR_LINE);
+ }
+
+}
+}
+
+DEFINE_DEVICE_TYPE_PRIVATE(H89BUS_CDR_FDC_880H, device_h89bus_right_card_interface, cdr_fdc_880h_device, "cdr_fdc_880h", "CDR FDC-880H Soft-sectored Controller");
diff --git a/src/devices/bus/heathzenith/h89/cdr_fdc_880h.h b/src/devices/bus/heathzenith/h89/cdr_fdc_880h.h
new file mode 100644
index 00000000000..f884da58405
--- /dev/null
+++ b/src/devices/bus/heathzenith/h89/cdr_fdc_880h.h
@@ -0,0 +1,18 @@
+// license:BSD-3-Clause
+// copyright-holders:Mark Garlanger
+/***************************************************************************
+
+ CDR FDC-880H soft-sectored floppy controller
+
+****************************************************************************/
+
+#ifndef MAME_BUS_HEATHZENITH_H89_CDR_FDC_880H_H
+#define MAME_BUS_HEATHZENITH_H89_CDR_FDC_880H_H
+
+#pragma once
+
+#include "h89bus.h"
+
+DECLARE_DEVICE_TYPE(H89BUS_CDR_FDC_880H, device_h89bus_right_card_interface)
+
+#endif // MAME_BUS_HEATHZENITH_H89_CDR_FDC_880H_H
diff --git a/src/devices/bus/heathzenith/h89/h17_fdc.cpp b/src/devices/bus/heathzenith/h89/h17_fdc.cpp
new file mode 100644
index 00000000000..ba43a379b8b
--- /dev/null
+++ b/src/devices/bus/heathzenith/h89/h17_fdc.cpp
@@ -0,0 +1,375 @@
+// license:BSD-3-Clause
+// copyright-holders:Mark Garlanger
+/***************************************************************************
+
+ Heathkit H-17 Floppy controller
+
+ This was an option for both the Heathkit H8 and H89 computer systems.
+
+ TODO
+ - define hard-sectored disk format
+ - incoming floppy data should drive receive clock of the ami 2350.
+
+****************************************************************************/
+
+#include "emu.h"
+#include "h17_fdc.h"
+
+#include "imagedev/floppy.h"
+#include "machine/s2350.h"
+
+#include "formats/h17disk.h"
+
+
+#define LOG_REG (1U << 1) // Register setup
+#define LOG_LINES (1U << 2) // Control lines
+#define LOG_DRIVE (1U << 3) // Drive select
+#define LOG_FUNC (1U << 4) // Function calls
+
+//#define VERBOSE (LOG_GENERAL | LOG_REG | LOG_LINES | LOG_DRIVE | LOG_FUNC)
+
+#include "logmacro.h"
+
+#define LOGREG(...) LOGMASKED(LOG_REG, __VA_ARGS__)
+#define LOGLINES(...) LOGMASKED(LOG_LINES, __VA_ARGS__)
+#define LOGDRIVE(...) LOGMASKED(LOG_DRIVE, __VA_ARGS__)
+#define LOGFUNC(...) LOGMASKED(LOG_FUNC, __VA_ARGS__)
+
+#ifdef _MSC_VER
+#define FUNCNAME __func__
+#else
+#define FUNCNAME __PRETTY_FUNCTION__
+#endif
+
+namespace {
+
+class heath_h17_fdc_device : public device_t, public device_h89bus_right_card_interface
+{
+public:
+ heath_h17_fdc_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock = 0);
+
+ auto floppy_ram_wp_cb() { return m_floppy_ram_wp.bind(); }
+
+ virtual void write(u8 select_lines, u8 offset, u8 data) override;
+ virtual u8 read(u8 select_lines, u8 offset) override;
+
+ [[maybe_unused]] void side_select_w(int state);
+
+protected:
+ static constexpr u8 MAX_FLOPPY_DRIVES = 3;
+
+ 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;
+
+ void ctrl_w(u8 val);
+ u8 floppy_status_r();
+
+ static void floppy_formats(format_registration &fr);
+ void set_floppy(floppy_image_device *floppy);
+ void step_w(int state);
+ void dir_w(int state);
+ void set_motor(bool motor_on);
+
+ void sync_character_received(int state);
+
+ TIMER_DEVICE_CALLBACK_MEMBER(tx_timer_cb);
+
+ devcb_write_line m_floppy_ram_wp;
+
+ required_device<s2350_device> m_s2350;
+ required_device_array<floppy_connector, MAX_FLOPPY_DRIVES> m_floppies;
+ required_device<timer_device> m_tx_timer;
+
+ bool m_motor_on;
+ bool m_write_gate;
+ bool m_sync_char_received;
+ u8 m_step_direction;
+ u8 m_side;
+
+ floppy_image_device *m_floppy;
+
+ /// write bit control port
+ static constexpr u8 CTRL_WRITE_GATE = 0;
+ static constexpr u8 CTRL_DRIVE_SELECT_0 = 1;
+ static constexpr u8 CTRL_DRIVE_SELECT_1 = 2;
+ static constexpr u8 CTRL_DRIVE_SELECT_2 = 3;
+ static constexpr u8 CTRL_MOTOR_ON = 4; // Controls all the drives
+ static constexpr u8 CTRL_DIRECTION = 5; // (0 = out)
+ static constexpr u8 CTRL_STEP_COMMAND = 6; // (Active high)
+ static constexpr u8 CTRL_WRITE_ENABLE_RAM = 7; // 0 - write protected
+
+ // USRT clock
+ static constexpr XTAL USRT_BASE_CLOCK = XTAL(12'288'000) / 6 / 16;
+ static constexpr u32 USRT_TX_CLOCK = USRT_BASE_CLOCK.value();
+};
+
+
+heath_h17_fdc_device::heath_h17_fdc_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock):
+ device_t(mconfig, H89BUS_H_17_FDC, tag, owner, 0),
+ device_h89bus_right_card_interface(mconfig, *this),
+ m_floppy_ram_wp(*this),
+ m_s2350(*this, "s2350"),
+ m_floppies(*this, "floppy%u", 0U),
+ m_tx_timer(*this, "tx_timer"),
+ m_floppy(nullptr)
+{
+}
+
+void heath_h17_fdc_device::write(u8 select_lines, u8 offset, u8 data)
+{
+ if (!(select_lines & h89bus_device::H89_FLPY))
+ {
+ return;
+ }
+
+ LOGFUNC("%s: reg: %d val: 0x%02x\n", FUNCNAME, offset, data);
+
+ switch (offset)
+ {
+ case 0: // data port
+ m_s2350->transmitter_holding_reg_w(data);
+ break;
+ case 1: // fill character
+ m_s2350->transmit_fill_reg_w(data);
+ break;
+ case 2: // sync port
+ m_s2350->receiver_sync_reg_w(data);
+ break;
+ case 3: // control port
+ ctrl_w(data);
+ break;
+ }
+}
+
+void heath_h17_fdc_device::set_floppy(floppy_image_device *floppy)
+{
+ if (m_floppy == floppy)
+ {
+ return;
+ }
+
+ LOGDRIVE("%s: selecting new drive\n", FUNCNAME);
+
+ m_floppy = floppy;
+
+ // set any latched signals
+ {
+ m_floppy->ss_w(m_side);
+ }
+}
+
+void heath_h17_fdc_device::side_select_w(int state)
+{
+ m_side = BIT(state, 0);
+
+ if (m_floppy)
+ {
+ m_floppy->ss_w(m_side);
+ }
+}
+
+void heath_h17_fdc_device::dir_w(int state)
+{
+ if (m_floppy)
+ {
+ LOGFUNC("%s: step dir: 0x%02x\n", FUNCNAME, state);
+
+ m_floppy->dir_w(state);
+ }
+}
+
+void heath_h17_fdc_device::step_w(int state)
+{
+ if (m_floppy)
+ {
+ LOGFUNC("%s: step dir: 0x%02x\n", FUNCNAME, state);
+
+ m_floppy->stp_w(state);
+ }
+}
+
+void heath_h17_fdc_device::set_motor(bool motor_on)
+{
+ if (m_motor_on == motor_on)
+ {
+ return;
+ }
+
+ m_motor_on = motor_on;
+
+ for (auto &elem : m_floppies)
+ {
+ floppy_image_device *floppy = elem->get_device();
+ if (floppy)
+ {
+ LOGFUNC("%s: motor: %d\n", FUNCNAME, motor_on);
+
+ floppy->mon_w(!motor_on);
+ }
+ }
+}
+
+void heath_h17_fdc_device::ctrl_w(u8 val)
+{
+ m_write_gate = bool(BIT(val, CTRL_WRITE_GATE));
+
+ set_motor(bool(BIT(val, CTRL_MOTOR_ON)));
+
+ if (BIT(val, CTRL_DRIVE_SELECT_0))
+ {
+ LOGFUNC("%s: set drive 0\n", FUNCNAME);
+
+ set_floppy(m_floppies[0]->get_device());
+ }
+ else if (BIT(val, CTRL_DRIVE_SELECT_1))
+ {
+ LOGFUNC("%s: set drive 1\n", FUNCNAME);
+
+ set_floppy(m_floppies[1]->get_device());
+ }
+ else if (BIT(val, CTRL_DRIVE_SELECT_2))
+ {
+ LOGFUNC("%s: set drive 2\n", FUNCNAME);
+
+ set_floppy(m_floppies[2]->get_device());
+ }
+ else
+ {
+ LOGFUNC("%s: set drive none\n", FUNCNAME);
+
+ set_floppy(nullptr);
+ }
+
+ dir_w(!BIT(val, CTRL_DIRECTION));
+
+ step_w(!BIT(val, CTRL_STEP_COMMAND));
+
+ m_floppy_ram_wp(BIT(val, CTRL_WRITE_ENABLE_RAM));
+}
+
+u8 heath_h17_fdc_device::read(u8 select_lines, u8 offset)
+{
+ if (!(select_lines & h89bus_device::H89_FLPY))
+ {
+ return 0;
+ }
+
+ u8 val = 0;
+
+ switch (offset)
+ {
+ case 0: // data port
+ val = m_s2350->receiver_output_reg_r();
+ break;
+ case 1: // status port
+ val = m_s2350->status_word_r();
+ break;
+ case 2: // sync port
+ val = m_s2350->receiver_sync_search();
+ break;
+ case 3: // floppy status port
+ val = floppy_status_r();
+ break;
+ }
+
+ LOGREG("%s: reg: %d val: 0x%02x\n", FUNCNAME, offset, val);
+
+ return val;
+}
+
+u8 heath_h17_fdc_device::floppy_status_r()
+{
+ u8 val = 0;
+
+ // statuses from the floppy drive
+ if (m_floppy)
+ {
+ // index/sector hole
+ val |= m_floppy->idx_r() ? 0x00 : 0x01;
+
+ // track 0
+ val |= m_floppy->trk00_r() ? 0x00 : 0x02;
+
+ // disk is write-protected
+ val |= m_floppy->wpt_r() ? 0x00 : 0x04;
+ }
+ else
+ {
+ LOGREG("%s: no drive selected\n", FUNCNAME);
+ }
+
+ // status from USRT
+ val |= m_sync_char_received ? 0x08 : 0x00;
+
+ LOGFUNC("%s: val: 0x%02x\n", FUNCNAME, val);
+
+ return val;
+}
+
+void heath_h17_fdc_device::device_start()
+{
+ save_item(NAME(m_motor_on));
+ save_item(NAME(m_write_gate));
+ save_item(NAME(m_sync_char_received));
+ save_item(NAME(m_step_direction));
+ save_item(NAME(m_side));
+}
+
+void heath_h17_fdc_device::device_reset()
+{
+ LOGFUNC("%s\n", FUNCNAME);
+
+ m_motor_on = false;
+ m_write_gate = false;
+ m_sync_char_received = false;
+
+ m_tx_timer->adjust(attotime::from_hz(USRT_TX_CLOCK), 0, attotime::from_hz(USRT_TX_CLOCK));
+}
+
+static void h17_floppies(device_slot_interface &device)
+{
+ // H-17-1
+ device.option_add("ssdd", FLOPPY_525_SSDD);
+
+ // Future plans - test and verify higher capacity drives with LLC's BIOS-80 for CP/M and an HUG's enhanced HDOS driver
+ // - FLOPPY_525_SSQD
+ // - FLOPPY_525_DD
+ // - FLOPPY_525_QD (H-17-4)
+}
+
+TIMER_DEVICE_CALLBACK_MEMBER(heath_h17_fdc_device::tx_timer_cb)
+{
+ m_s2350->tcp_w();
+}
+
+void heath_h17_fdc_device::floppy_formats(format_registration &fr)
+{
+ fr.add(FLOPPY_H17D_FORMAT);
+}
+
+void heath_h17_fdc_device::device_add_mconfig(machine_config &config)
+{
+ S2350(config, m_s2350, 0);
+ m_s2350->sync_character_received_cb().set(FUNC(heath_h17_fdc_device::sync_character_received));
+
+ for (int i = 0; i < MAX_FLOPPY_DRIVES; i++)
+ {
+ // TODO -> add (and define) heath hard-sectored floppy formats.
+ FLOPPY_CONNECTOR(config, m_floppies[i], h17_floppies, "ssdd", heath_h17_fdc_device::floppy_formats);
+ m_floppies[i]->enable_sound(true);
+ }
+
+ TIMER(config, m_tx_timer).configure_generic(FUNC(heath_h17_fdc_device::tx_timer_cb));
+}
+
+void heath_h17_fdc_device::sync_character_received(int state)
+{
+ LOGFUNC("%s: state: %d\n", FUNCNAME, state);
+
+ m_sync_char_received = bool(!BIT(state, 0));
+}
+
+} // anonymous namespace
+
+DEFINE_DEVICE_TYPE_PRIVATE(H89BUS_H_17_FDC, device_h89bus_right_card_interface, heath_h17_fdc_device, "h89_h17_fdc", "Heath H-17 Hard-sectored Controller (H-88-1)");
diff --git a/src/devices/bus/heathzenith/h89/h17_fdc.h b/src/devices/bus/heathzenith/h89/h17_fdc.h
new file mode 100644
index 00000000000..bf5c8a8a2c8
--- /dev/null
+++ b/src/devices/bus/heathzenith/h89/h17_fdc.h
@@ -0,0 +1,26 @@
+// license:BSD-3-Clause
+// copyright-holders:Mark Garlanger
+/***************************************************************************
+
+ Heathkit H-17 Floppy Disk Controller
+
+
+ Model number: H-88-1
+
+ TODO
+ - Mame core must support hard-sectored disk images.
+ - used floppy clock bits to clock USRT received clock.
+ - Add support for a heath hard-sectored disk support (h17disk).
+
+****************************************************************************/
+
+#ifndef MAME_BUS_HEATHZENITH_H89_H17_FDC_H
+#define MAME_BUS_HEATHZENITH_H89_H17_FDC_H
+
+#pragma once
+
+#include "h89bus.h"
+
+DECLARE_DEVICE_TYPE(H89BUS_H_17_FDC, device_h89bus_right_card_interface)
+
+#endif // MAME_BUS_HEATHZENITH_H89_H17_FDC_H
diff --git a/src/devices/bus/heathzenith/h89/h89bus.cpp b/src/devices/bus/heathzenith/h89/h89bus.cpp
new file mode 100644
index 00000000000..b9715af853f
--- /dev/null
+++ b/src/devices/bus/heathzenith/h89/h89bus.cpp
@@ -0,0 +1,383 @@
+// license:BSD-3-Clause
+// copyright-holders:R. Belmont, Mark Garlanger
+/***************************************************************************
+
+ h89bus.cpp - Heath/Zenith H-89/Z-90 bus
+
+ by R. Belmont
+
+ This system is weird. There are 3 left-hand slots. These are intended
+ for RAM expansion and map into the Z80's memory space. They get A0-A12
+ and some select signals decoded by a pair of PROMs at U516 and U517.
+ Notably, these slots don't get the Z80's /RD or /WR signals so actual
+ working boards for these slots always run a cable or jumper(s) to pick
+ signals from the motherboard. These slots also have no way to signal
+ an interrupt.
+
+ There are also 3 right-hand slots. These connect to the Z80's I/O address
+ space and are addressed by a 3-bit offset A0/A1/A2 plus select lines /SER0,
+ /SER1, /LP1 and /CASS (on P504/P510 and P505/P511), or /FLPY (on P506/P512).
+ P506/P512 replaces the /LP1 select line with the /FMWE signal which write-enables
+ the "floppy RAM" at 0x1400. These slots have 3 standard interrupt outputs
+ /INT3, /INT4, and /INT5.
+
+ Notable real-world use cases that we support:
+ - The Sigmasoft parallel card plugs into a left slot but picks the I/O space
+ select signal off the motherboard. This plus the left slots' nearly full
+ set of address lines let it decode the I/O space arbitrarily without
+ having to change the I/O decoder PROM.
+
+ - The MMS 77316 floppy controller has jumpers to replace U553 so that it can
+ intercept the GPP select line output by the PROM and further decode it.
+ This decode appears to check if A0/A1/A2 = b010. The partial schematic for
+ the card doesn't include that logic, but based on what signals it has access
+ to and the fact that the card doesn't respond to A0/A1/A2 = b010 that seems
+ to be a reasonable guess.
+
+***************************************************************************/
+
+#include "emu.h"
+#include "h89bus.h"
+
+#include <algorithm>
+#include <cctype>
+
+DEFINE_DEVICE_TYPE(H89BUS_LEFT_SLOT, h89bus_left_slot_device, "h89bus_lslot", "H-89 left (memory) slot")
+
+h89bus_left_slot_device::h89bus_left_slot_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) :
+ h89bus_left_slot_device(mconfig, H89BUS_LEFT_SLOT, tag, owner, clock)
+{
+}
+
+h89bus_left_slot_device::h89bus_left_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(mconfig, *this),
+ m_h89bus(*this, finder_base::DUMMY_TAG),
+ m_h89bus_slottag(nullptr)
+{
+}
+
+void h89bus_left_slot_device::device_start()
+{
+}
+
+void h89bus_left_slot_device::device_resolve_objects()
+{
+ device_h89bus_left_card_interface *dev = get_card_device();
+
+ if (dev)
+ {
+ dev->set_h89bus_tag(m_h89bus.target(), m_h89bus_slottag);
+ m_h89bus->add_h89bus_left_card(*dev);
+ }
+}
+
+DEFINE_DEVICE_TYPE(H89BUS_RIGHT_SLOT, h89bus_right_slot_device, "h89bus_rslot", "H-89 right (I/O) slot")
+
+h89bus_right_slot_device::h89bus_right_slot_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) :
+ h89bus_right_slot_device(mconfig, H89BUS_RIGHT_SLOT, tag, owner, clock)
+{
+}
+
+h89bus_right_slot_device::h89bus_right_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(mconfig, *this),
+ m_h89bus(*this, finder_base::DUMMY_TAG),
+ m_h89bus_slottag(nullptr),
+ m_p506_signals(false)
+{
+}
+
+void h89bus_right_slot_device::device_start()
+{
+}
+
+void h89bus_right_slot_device::device_resolve_objects()
+{
+ device_h89bus_right_card_interface *dev = get_card_device();
+
+ if (dev)
+ {
+ dev->set_h89bus_tag(m_h89bus.target(), m_h89bus_slottag);
+ dev->set_p506_signalling(m_p506_signals);
+ m_h89bus->add_h89bus_right_card(*dev);
+ }
+}
+
+//**************************************************************************
+// GLOBAL VARIABLES
+//**************************************************************************
+
+DEFINE_DEVICE_TYPE(H89BUS, h89bus_device, "h89bus", "H-89/Z-90 bus")
+
+ROM_START(h89bus)
+ ROM_REGION(0x100, "iodecode", 0)
+ // H88 I/O decoding
+ ROM_SYSTEM_BIOS(0, "444-43", "Heath/Zenith stock decoding (444-43)")
+ ROMX_LOAD("444-43.bin", 0x000000, 0x000100, CRC(3e0315f4) SHA1(11da9a9145de07f1f3bf1270a10e059dff30c693), ROM_BIOS(0))
+
+ // H89 I/O decoding
+ ROM_SYSTEM_BIOS(1, "444-61", "Z-37 decoding (444-61)")
+ ROMX_LOAD("444-61.bin", 0x000000, 0x000100, CRC(0b3c129f) SHA1(92da6484d1339160400d6bc75578a977c5e4d23e), ROM_BIOS(1))
+
+ // MMS (Magnolia Micro Systems) I/O decoding
+ ROM_SYSTEM_BIOS(2, "444-61c", "MMS decoding (444-61c)")
+ ROMX_LOAD( "444-61c.bin", 0x000000, 0x000100, CRC(e7122061) SHA1(33c124f44c0f9cb99c9b17ad15411b4bc6407eae), ROM_BIOS(2))
+
+ // CDR Systems
+ ROM_SYSTEM_BIOS(3, "cdr86", "CDR decoding (CDR86)")
+ ROMX_LOAD( "cdr86.bin", 0x000000, 0x000100, CRC(d35e4063) SHA1(879f9d265d77f8a74c70febd9a80d6896ab8ec7e), ROM_BIOS(3))
+ROM_END
+
+//**************************************************************************
+// LIVE DEVICE
+//**************************************************************************
+
+//-------------------------------------------------
+// h89bus_device - constructor
+//-------------------------------------------------
+
+h89bus_device::h89bus_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) :
+ h89bus_device(mconfig, H89BUS, tag, owner, clock)
+{
+}
+
+h89bus_device::h89bus_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_program_space(*this, finder_base::DUMMY_TAG, -1),
+ m_io_space(*this, finder_base::DUMMY_TAG, -1),
+ m_decode_prom(*this, "iodecode"),
+ m_out_int3_cb(*this),
+ m_out_int4_cb(*this),
+ m_out_int5_cb(*this),
+ m_out_fmwe_cb(*this),
+ m_out_wait_cb(*this),
+ m_in_tlb_cb(*this, 0),
+ m_in_nmi_cb(*this, 0),
+ m_in_gpp_cb(*this, 0),
+ m_out_tlb_cb(*this),
+ m_out_nmi_cb(*this),
+ m_out_gpp_cb(*this)
+{
+}
+
+h89bus_device::~h89bus_device()
+{
+}
+
+const tiny_rom_entry *h89bus_device::device_rom_region() const
+{
+ return ROM_NAME(h89bus);
+}
+
+//-------------------------------------------------
+// device_start - device-specific startup
+//-------------------------------------------------
+
+void h89bus_device::device_start()
+{
+ m_io_space->install_readwrite_handler(0x0000, 0x00ff, emu::rw_delegate(*this, FUNC(h89bus_device::io_dispatch_r)), emu::rw_delegate(*this, FUNC(h89bus_device::io_dispatch_w)));
+}
+
+void h89bus_device::add_h89bus_left_card(device_h89bus_left_card_interface &card)
+{
+ m_left_device_list.emplace_back(card);
+}
+
+void h89bus_device::add_h89bus_right_card(device_h89bus_right_card_interface &card)
+{
+ m_right_device_list.emplace_back(card);
+}
+
+void h89bus_device::set_io0(int state)
+{
+ m_io0 = state;
+}
+
+void h89bus_device::set_io1(int state)
+{
+ m_io1 = state;
+}
+
+void h89bus_device::set_mem0(int state)
+{
+ m_mem0 = state;
+}
+
+void h89bus_device::set_mem1(int state)
+{
+ m_mem1 = state;
+}
+
+int h89bus_device::get_io0()
+{
+ return m_io0;
+}
+
+int h89bus_device::get_io1()
+{
+ return m_io1;
+}
+
+int h89bus_device::get_mem0()
+{
+ return m_mem0;
+}
+
+int h89bus_device::get_mem1()
+{
+ return m_mem1;
+}
+
+u8 h89bus_device::read_gpp()
+{
+ return m_in_gpp_cb(0);
+}
+void h89bus_device::write_gpp(u8 data)
+{
+ m_out_gpp_cb(0, data);
+}
+
+u8 h89bus_device::io_dispatch_r(offs_t offset)
+{
+ u8 retval = 0;
+
+ u16 decode = m_decode_prom[offset] ^ 0xff;
+
+ if (decode)
+ {
+ if ((decode & H89_GPP) && ((offset & 7) == 2)) return m_in_gpp_cb(offset);
+ if (decode & H89_NMI) return m_in_nmi_cb(offset);
+ if (decode & H89_TERM) return m_in_tlb_cb(offset & 7);
+
+ for (device_h89bus_right_card_interface &entry : m_right_device_list)
+ {
+ if (entry.m_p506_signals)
+ {
+ // p506 does not have CASS or LP
+ retval |= entry.read(decode & ~(H89_CASS | H89_LP), offset & 7);
+ }
+ else
+ {
+ // p504/p505 does not have FLPY
+ retval |= entry.read(decode & ~H89_FLPY , offset & 7);
+ }
+ }
+ }
+
+ // service left-slot cards that have a motherboard connection to snoop the I/O space
+ for (device_h89bus_left_card_interface &entry : m_left_device_list)
+ {
+ retval |= entry.read(H89_IO, offset & 0x1fff);
+ }
+
+ return retval;
+}
+
+void h89bus_device::io_dispatch_w(offs_t offset, u8 data)
+{
+ u16 decode = m_decode_prom[offset] ^ 0xff;
+
+ if (decode)
+ {
+ if ((decode & H89_GPP) && ((offset & 7) == 2)) m_out_gpp_cb(offset, data);
+ if (decode & H89_NMI) { m_out_nmi_cb(offset, data); return; }
+ if (decode & H89_TERM) { m_out_tlb_cb(offset & 7, data); return; }
+
+ for (device_h89bus_right_card_interface &entry : m_right_device_list)
+ {
+ if (entry.m_p506_signals)
+ {
+ // p506 does not have CASS or LP
+ entry.write(decode & ~(H89_CASS | H89_LP), offset & 7, data);
+ }
+ else
+ {
+ // p504/p505 does not have FLPY
+ entry.write(decode & ~H89_FLPY, offset & 7, data);
+ }
+ }
+ }
+
+ // service left-slot cards that have a motherboard connection to snoop the I/O space
+ for (device_h89bus_left_card_interface &entry : m_left_device_list)
+ {
+ entry.write(H89_IO, offset, data);
+ }
+}
+
+void h89bus_device::set_int3_line(int state)
+{
+ m_out_int3_cb(state);
+}
+
+void h89bus_device::set_int4_line(int state)
+{
+ m_out_int4_cb(state);
+}
+
+void h89bus_device::set_int5_line(int state)
+{
+ m_out_int5_cb(state);
+}
+
+void h89bus_device::set_fmwe_line(int state)
+{
+ m_out_fmwe_cb(state);
+}
+
+void h89bus_device::set_wait_line(int state)
+{
+ m_out_wait_cb(state);
+}
+
+//**************************************************************************
+// DEVICE H89BUS CARD INTERFACE
+//**************************************************************************
+
+//-------------------------------------------------
+// device_h89bus_card_interface - constructor
+//-------------------------------------------------
+
+device_h89bus_card_interface::device_h89bus_card_interface(const machine_config &mconfig, device_t &device) :
+ device_interface(device, "h89bus"),
+ m_h89bus(nullptr)
+{
+}
+
+
+//-------------------------------------------------
+// ~device_h89bus_card_interface - destructor
+//-------------------------------------------------
+
+device_h89bus_card_interface::~device_h89bus_card_interface()
+{
+}
+
+void device_h89bus_card_interface::interface_pre_start()
+{
+ if (!m_h89bus)
+ {
+ fatalerror("Can't find H-89 bus device\n");
+ }
+}
+
+device_h89bus_left_card_interface::device_h89bus_left_card_interface(const machine_config &mconfig, device_t &device) :
+ device_h89bus_card_interface(mconfig, device)
+{
+}
+
+device_h89bus_left_card_interface::~device_h89bus_left_card_interface()
+{
+}
+
+device_h89bus_right_card_interface::device_h89bus_right_card_interface(const machine_config &mconfig, device_t &device) :
+ device_h89bus_card_interface(mconfig, device),
+ m_p506_signals(false)
+{
+}
+
+device_h89bus_right_card_interface::~device_h89bus_right_card_interface()
+{
+}
+
diff --git a/src/devices/bus/heathzenith/h89/h89bus.h b/src/devices/bus/heathzenith/h89/h89bus.h
new file mode 100644
index 00000000000..0cfe29da10a
--- /dev/null
+++ b/src/devices/bus/heathzenith/h89/h89bus.h
@@ -0,0 +1,400 @@
+// license:BSD-3-Clause
+// copyright-holders:R. Belmont
+/***************************************************************************
+
+ h89.h - Heath/Zenith H-89/Z-90 bus
+ by R. Belmont
+
+ Left-side slots of the H89 Right-side slots of the H89
+
+ pin P501 P502 P503 P504 P505 P506 pin
+
+ 1 GND----------GND----------GND-------------GND----------GND----------GND 1
+ 2 D0-----------D0-----------D0--------------D0-----------D0-----------D0 2
+ 3 D1-----------D1-----------D1--------------D1-----------D1-----------D1 3
+ 4 D2-----------D2-----------D2--------------D2-----------D2-----------D2 4
+ 5 D3-----------D3-----------D3--------------D3-----------D3-----------D3 5
+ 6 D4-----------D4-----------D4--------------D4-----------D4-----------D4 6
+ 7 D5-----------D5-----------D5--------------D5-----------D5-----------D5 7
+ 8 D6-----------D6-----------D6--------------D6-----------D6-----------D6 8
+ 9 D7-----------D7-----------D7--------------D7-----------D7-----------D7 9
+ 10 GND----------GND----------GND-------------GND----------GND----------GND 10
+
+ P507 P508 P509 P510 P511 P512
+
+ 1 VCC----------VCC----------VCC-------------VCC----------VCC----------VCC 1
+ 2 GND----------GND----------GND-------------GND----------GND----------GND 2
+ 3 A0-----------A0-----------A0--------------A0-----------A0-----------A0 3
+ 4 A1-----------A1-----------A1--------------A1-----------A1-----------A1 4
+ 5 A2-----------A2-----------A2--------------A2-----------A2-----------A2 5
+ 6 A3-----------A3-----------A3 /BRD---------/BRD---------/BRD 6
+ 7 A4-----------A4-----------A4 /BWR---------/BWR---------/BWR 7
+ 8 A5-----------A5-----------A5 /WAIT--------/WAIT--------/WAIT 8
+ 9 A6-----------A6-----------A6 /SER0--------/SER0--------/SER0 9
+ 10 A7-----------A7-----------A7 /SER1--------/SER1--------/SER1 10
+ 11 A8-----------A8-----------A8 /LP1---------/LP1 /FLPY 11
+ 12 A9-----------A9-----------A9 /CASS--------/CASS /FMWE 12
+ 13 A10----------A10----------A10 2MHz---------2MHz---------2MHz 13
+ 14 A11----------A11----------A11 1.8Mhz-------1.8MHz-------1.8MHz 14
+ 15 A12----------A12----------A12 /RST---------/RST---------/RST 15
+ 16 MEM 0--------MEM 0--------MEM 0 IO 0---------IO 0---------IO 0 16
+ 17 MEM 1--------MEM 1--------MEM 1 IO 1---------IO 1---------IO 1 17
+ 18 RD5----------RD5----------RD5 /INT3--------/INT3--------/INT3 18
+ 19 RD6----------RD6----------RD6 /INT4--------/INT4--------/INT4 19
+ 20 RD7----------RD7----------RD7 /INT5--------/INT5--------/INT5 20
+ 21 (+12V)-------(+12V)-------(+12V)-----------(+12V)-------(+12V)-------(+12V) 21
+ 22 (-12V)-------(-12V)-------(-12V)-----------(-12V)-------(-12V)-------(-12V) 22
+ 23 (-5V)--------(-5V)--------(-5V)------------(-5V)--------(-5V)--------(-5V) 23
+ 24 (+12V)-------(+12V)-------(+12V)-----------(+12V)-------(+12V)-------(+12V) 24
+ 25 GND----------GND----------GND--------------GND----------GND----------GND 25
+
+
+ Signal Description
+ ------------------------------------------
+ MEM 0 H Controlled by the GPP port
+ MEM 1 H Controlled by the GPP port
+ RD5 Tied to +5V when CPU jumpers configured as recommended by Heath's configuration
+ guide. Could be jumpered to RAS2 (bank select 2: address 32k-48k) (active low)
+ RD6 Selects the 16k Expansion memory (active low)
+ RD7 Reserved for future use, 444-66 PROM nevers sets this low. (active low)
+ BRD L Board Read (active low)
+ BWR L Board Write (active low)
+ WAIT L Wait state (active low)
+ SER0 L Select line for one of the serial ports on the HA-88-3 (active low)
+ SER1 L Select line for one of the serial ports on the HA-88-3 (active low)
+ LP 1 L Select line for one of the serial ports on the HA-88-3 (active low)
+ CASS L Select line originally for the Cassette Interface board, but when used with later PROM it
+ selected Floppy controllers/interfaces – Z-89-37, Z-89-47, Z-89-67 (active low)
+ 2 MHz CPU Clock, actual speed 2.048 MHz
+ 1.8 MHz Serial Port Clock, actual speed 1.8432 MHz
+ RST L Reset line (active low)
+ IO 0 H Controlled by the GPP port
+ IO 1 H Controlled by the GPP port
+ INT3 L Interrupt level 3 (active low)
+ INT4 L Interrupt level 4 (active low)
+ INT5 L Interrupt level 5 (active low)
+ FLPY L Select line originally for the H-88-1 hard-sectored controller, but also used for the later
+ Z-89-47 and Z-89-67 when installed in slot P506/P512 (active low)
+ FMWE H Floppy Memory Write Enable
+
+***************************************************************************/
+
+#ifndef MAME_BUS_HEATHZENITH_H89_H89BUS_H
+#define MAME_BUS_HEATHZENITH_H89_H89BUS_H
+
+#pragma once
+#include "emu.h"
+#include <functional>
+#include <utility>
+#include <vector>
+#include <string.h>
+
+//**************************************************************************
+// TYPE DEFINITIONS
+//**************************************************************************
+
+class h89bus_device;
+
+// ======================> device_h89bus_card_interface
+
+// class representing interface-specific live H-89/Z-89 bus card
+class device_h89bus_card_interface : public device_interface
+{
+ friend class h89bus_device;
+public:
+ // construction/destruction
+ virtual ~device_h89bus_card_interface();
+
+ // inline configuration
+ void set_h89bus_tag(h89bus_device *h89bus, const char *slottag) { m_h89bus = h89bus; m_h89bus_slottag = slottag; }
+
+protected:
+ device_h89bus_card_interface(const machine_config &mconfig, device_t &device);
+ virtual void interface_pre_start() override;
+
+ h89bus_device &h89bus() { assert(m_h89bus); return *m_h89bus; }
+
+ const char *m_h89bus_slottag;
+
+private:
+ h89bus_device *m_h89bus;
+};
+
+class device_h89bus_left_card_interface : public device_h89bus_card_interface
+{
+public:
+ // construction/destruction
+ virtual ~device_h89bus_left_card_interface();
+
+ int get_mem0();
+ int get_mem1();
+
+ virtual u8 read(u8 select_lines, u16 offset) { return 0; };
+ virtual void write(u8 select_lines, u16 offset, u8 data) {};
+
+protected:
+ device_h89bus_left_card_interface(const machine_config &mconfig, device_t &device);
+
+private:
+};
+
+class device_h89bus_right_card_interface : public device_h89bus_card_interface
+{
+ friend class h89bus_device;
+
+public:
+ // construction/destruction
+ virtual ~device_h89bus_right_card_interface();
+
+ void set_slot_int3(int state);
+ void set_slot_int4(int state);
+ void set_slot_int5(int state);
+ void set_slot_fmwe(int state);
+ void set_slot_wait(int state);
+ int get_io0();
+ int get_io1();
+
+ virtual u8 read(u8 select_lines, u8 offset) { return 0; };
+ virtual void write(u8 select_lines, u8 offset, u8 data) {};
+
+ void set_p506_signalling(bool val)
+ {
+ m_p506_signals = val;
+ }
+
+protected:
+ device_h89bus_right_card_interface(const machine_config &mconfig, device_t &device);
+ bool m_p506_signals;
+
+private:
+};
+
+class h89bus_left_slot_device : public device_t, public device_single_card_slot_interface<device_h89bus_left_card_interface>
+{
+public:
+ // construction/destruction
+ template <typename T, typename U>
+ h89bus_left_slot_device(const machine_config &mconfig, T &&tag, device_t *owner, const char *sltag, U &&opts, const char *dflt)
+ : h89bus_left_slot_device(mconfig, tag, owner, (uint32_t)0)
+ {
+ option_reset();
+ opts(*this);
+ set_default_option(dflt);
+ set_h89bus_slot(std::forward<T>(sltag), tag);
+ }
+
+ h89bus_left_slot_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
+
+ // inline configuration
+ template <typename T>
+ void set_h89bus_slot(T &&tag, const char *slottag)
+ {
+ m_h89bus.set_tag(std::forward<T>(tag));
+ m_h89bus_slottag = slottag;
+ }
+
+protected:
+ h89bus_left_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 ATTR_COLD;
+ virtual void device_start() override ATTR_COLD;
+
+ // configuration
+ required_device<h89bus_device> m_h89bus;
+ const char *m_h89bus_slottag;
+};
+
+// device type definition
+DECLARE_DEVICE_TYPE(H89BUS_LEFT_SLOT, h89bus_left_slot_device)
+
+class h89bus_right_slot_device : public device_t, public device_single_card_slot_interface<device_h89bus_right_card_interface>
+{
+public:
+ // construction/destruction
+ template <typename T, typename U>
+ h89bus_right_slot_device(const machine_config &mconfig, T &&tag, device_t *owner, const char *sltag, U &&opts, const char *dflt)
+ : h89bus_right_slot_device(mconfig, tag, owner, (uint32_t)0)
+ {
+ option_reset();
+ opts(*this);
+ set_default_option(dflt);
+ set_h89bus_slot(std::forward<T>(sltag), tag);
+ }
+
+ h89bus_right_slot_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
+
+ // inline configuration
+ template <typename T>
+ void set_h89bus_slot(T &&tag, const char *slottag)
+ {
+ m_h89bus.set_tag(std::forward<T>(tag));
+ m_h89bus_slottag = slottag;
+ }
+
+ void set_p506_signalling(bool val)
+ {
+ m_p506_signals = val;
+ }
+
+protected:
+ h89bus_right_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 ATTR_COLD;
+ virtual void device_start() override ATTR_COLD;
+
+ // configuration
+ required_device<h89bus_device> m_h89bus;
+ const char *m_h89bus_slottag;
+ bool m_p506_signals;
+};
+
+// device type definition
+DECLARE_DEVICE_TYPE(H89BUS_RIGHT_SLOT, h89bus_right_slot_device)
+
+// ======================> h89bus_device
+class h89bus_device : public device_t
+{
+ friend class h89bus_left_slot_device;
+ friend class h89bus_right_slot_device;
+ friend class device_h89bus_left_card_interface;
+ friend class device_h89bus_right_card_interface;
+
+public:
+ // left card select lines
+ static constexpr u8 H89_RD5 = 0x01;
+ static constexpr u8 H89_RD6 = 0x02;
+ static constexpr u8 H89_RD7 = 0x04;
+ // The Sigmasoft parallel card plugs into the left slot and has a jumper to
+ // get the memory / I/O select signal from the motherboard. This plus the left
+ // slots' A0-A13 lines means it can claim arbitrary I/O ranges that the PROM doesn't
+ // select anything at.
+ static constexpr u8 H89_IO = 0x80;
+
+ // right card and on-board I/O space select lines
+ static constexpr u8 H89_GPP = 0x01;
+ static constexpr u8 H89_NMI = 0x02;
+ static constexpr u8 H89_TERM = 0x04;
+ static constexpr u8 H89_SER1 = 0x08;
+ static constexpr u8 H89_SER0 = 0x10;
+ static constexpr u8 H89_LP = 0x20;
+ static constexpr u8 H89_CASS = 0x40;
+ static constexpr u8 H89_FLPY = 0x80;
+
+ // construction/destruction
+ h89bus_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
+ ~h89bus_device();
+
+ void set_io0(int state);
+ void set_io1(int state);
+ void set_mem0(int state);
+ void set_mem1(int state);
+ int get_io0();
+ int get_io1();
+ int get_mem0();
+ int get_mem1();
+
+ // inline configuration
+ template <typename T> void set_program_space(T &&tag, int spacenum) { m_program_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); }
+ auto out_int3_callback() { return m_out_int3_cb.bind(); }
+ auto out_int4_callback() { return m_out_int4_cb.bind(); }
+ auto out_int5_callback() { return m_out_int5_cb.bind(); }
+ auto out_fmwe_callback() { return m_out_fmwe_cb.bind(); }
+ auto out_wait_callback() { return m_out_wait_cb.bind(); }
+ auto in_tlb_callback() { return m_in_tlb_cb.bind(); }
+ auto in_nmi_callback() { return m_in_nmi_cb.bind(); }
+ auto in_gpp_callback() { return m_in_gpp_cb.bind(); }
+ auto out_tlb_callback() { return m_out_tlb_cb.bind(); }
+ auto out_nmi_callback() { return m_out_nmi_cb.bind(); }
+ auto out_gpp_callback() { return m_out_gpp_cb.bind(); }
+
+protected:
+ h89bus_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 ATTR_COLD;
+ virtual const tiny_rom_entry *device_rom_region() const override ATTR_COLD;
+
+ // bus-internal handlers
+ void add_h89bus_left_card(device_h89bus_left_card_interface &card);
+ void add_h89bus_right_card(device_h89bus_right_card_interface &card);
+ void set_int3_line(int state);
+ void set_int4_line(int state);
+ void set_int5_line(int state);
+ void set_fmwe_line(int state);
+ void set_wait_line(int state);
+ u8 read_gpp();
+ void write_gpp(u8 data);
+
+ // internal state
+ required_address_space m_program_space, m_io_space;
+ required_region_ptr<uint8_t> m_decode_prom;
+ int m_io0, m_io1, m_mem0, m_mem1;
+
+private:
+ devcb_write_line m_out_int3_cb, m_out_int4_cb, m_out_int5_cb;
+ devcb_write_line m_out_fmwe_cb, m_out_wait_cb;
+ devcb_read8 m_in_tlb_cb, m_in_nmi_cb, m_in_gpp_cb;
+ devcb_write8 m_out_tlb_cb, m_out_nmi_cb, m_out_gpp_cb;
+
+ std::vector<std::reference_wrapper<device_h89bus_left_card_interface>> m_left_device_list;
+ std::vector<std::reference_wrapper<device_h89bus_right_card_interface>> m_right_device_list;
+
+ u8 io_dispatch_r(offs_t offset);
+ void io_dispatch_w(offs_t offset, u8 data);
+};
+
+inline int device_h89bus_left_card_interface::get_mem0()
+{
+ return h89bus().get_mem0();
+}
+
+inline int device_h89bus_left_card_interface::get_mem1()
+{
+ return h89bus().get_mem1();
+}
+
+inline int device_h89bus_right_card_interface::get_io0()
+{
+ return h89bus().get_io0();
+}
+
+inline int device_h89bus_right_card_interface::get_io1()
+{
+ return h89bus().get_io1();
+}
+
+inline void device_h89bus_right_card_interface::set_slot_int3(int state)
+{
+ h89bus().set_int3_line(state);
+}
+
+inline void device_h89bus_right_card_interface::set_slot_int4(int state)
+{
+ h89bus().set_int4_line(state);
+}
+
+inline void device_h89bus_right_card_interface::set_slot_int5(int state)
+{
+ h89bus().set_int5_line(state);
+}
+
+inline void device_h89bus_right_card_interface::set_slot_fmwe(int state)
+{
+ if (m_p506_signals)
+ {
+ h89bus().set_fmwe_line(state);
+ }
+}
+
+inline void device_h89bus_right_card_interface::set_slot_wait(int state)
+{
+ h89bus().set_wait_line(state);
+}
+
+// device type definition
+DECLARE_DEVICE_TYPE(H89BUS, h89bus_device)
+
+#endif // MAME_BUS_HEATHZENITH_H89_H89BUS_H
diff --git a/src/devices/bus/heathzenith/h89/h_88_3.cpp b/src/devices/bus/heathzenith/h89/h_88_3.cpp
new file mode 100644
index 00000000000..224bbd93a9d
--- /dev/null
+++ b/src/devices/bus/heathzenith/h89/h_88_3.cpp
@@ -0,0 +1,389 @@
+// license:BSD-3-Clause
+// copyright-holders:Mark Garlanger, R. Belmont
+/***************************************************************************
+
+ Heath H-88-3 3-port serial port card
+ Came with 2 serial ports and space to add an additional serial port.
+
+ Heath HA-88-3 3-port serial port card
+ Came standard with 3 serial ports.
+
+****************************************************************************/
+
+#include "emu.h"
+
+#include "h_88_3.h"
+
+#include "bus/rs232/rs232.h"
+#include "machine/ins8250.h"
+
+namespace {
+
+class h_88_3_device : public device_t, public device_h89bus_right_card_interface
+{
+public:
+ h_88_3_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock = XTAL(1'843'200).value());
+
+ virtual void write(u8 select_lines, u8 offset, u8 data) override;
+ virtual u8 read(u8 select_lines, u8 offset) override;
+
+protected:
+ h_88_3_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, u32 clock);
+
+ 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;
+ virtual ioport_constructor device_input_ports() const override ATTR_COLD;
+
+ devcb_write_line::array<4> m_int_cb;
+
+ required_device<ins8250_device> m_lp;
+ required_device<ins8250_device> m_aux;
+ required_device<ins8250_device> m_modem;
+ required_ioport m_cfg_lp;
+ required_ioport m_cfg_aux;
+ required_ioport m_cfg_modem;
+
+ bool m_lp_enabled;
+ bool m_aux_enabled;
+ bool m_modem_enabled;
+
+ u8 m_lp_int_idx;
+ u8 m_aux_int_idx;
+ u8 m_modem_int_idx;
+
+ int m_lp_intr;
+ int m_aux_intr;
+ int m_modem_intr;
+
+private:
+ void lp_w(offs_t reg, u8 val);
+ u8 lp_r(offs_t reg);
+
+ void aux_w(offs_t reg, u8 val);
+ u8 aux_r(offs_t reg);
+
+ void modem_w(offs_t reg, u8 val);
+ u8 modem_r(offs_t reg);
+
+ void update_intr(u8 level);
+
+ void lp_int(int data);
+ void aux_int(int data);
+ void modem_int(int data);
+};
+
+class ha_88_3_device : public h_88_3_device
+{
+public:
+ ha_88_3_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock = XTAL(1'843'200).value());
+
+protected:
+ virtual ioport_constructor device_input_ports() const override;
+};
+
+h_88_3_device::h_88_3_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock) :
+ h_88_3_device(mconfig, H89BUS_H_88_3, tag, owner, clock)
+{
+}
+
+h_88_3_device::h_88_3_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, u32 clock):
+ device_t(mconfig, type, tag, owner, clock),
+ device_h89bus_right_card_interface(mconfig, *this),
+ m_int_cb(*this),
+ m_lp(*this, "lp"),
+ m_aux(*this, "aux"),
+ m_modem(*this, "modem"),
+ m_cfg_lp(*this, "CFG_LP"),
+ m_cfg_aux(*this, "CFG_AUX"),
+ m_cfg_modem(*this, "CFG_MODEM"),
+ m_lp_intr(0),
+ m_aux_intr(0),
+ m_modem_intr(0)
+{
+}
+
+u8 h_88_3_device::read(u8 select_lines, u8 offset)
+{
+ if ((select_lines & h89bus_device::H89_SER0) && (m_aux_enabled))
+ {
+ return aux_r(offset);
+ }
+
+ if ((select_lines & h89bus_device::H89_SER1) && (m_modem_enabled))
+ {
+ return modem_r(offset);
+ }
+
+ if ((select_lines & h89bus_device::H89_LP) && (m_lp_enabled))
+ {
+ return lp_r(offset);
+ }
+
+ return 0;
+}
+
+void h_88_3_device::write(u8 select_lines, u8 offset, u8 data)
+{
+ if ((select_lines & h89bus_device::H89_SER0) && (m_aux_enabled))
+ {
+ aux_w(offset, data);
+ return;
+ }
+
+ if ((select_lines & h89bus_device::H89_SER1) && (m_modem_enabled))
+ {
+ modem_w(offset, data);
+ return;
+ }
+
+ if ((select_lines & h89bus_device::H89_LP) && (m_lp_enabled))
+ {
+ lp_w(offset, data);
+ return;
+ }
+}
+
+u8 h_88_3_device::lp_r(offs_t reg)
+{
+ return m_lp->ins8250_r(reg);
+}
+
+void h_88_3_device::lp_w(offs_t reg, u8 val)
+{
+ m_lp->ins8250_w(reg, val);
+}
+
+u8 h_88_3_device::aux_r(offs_t reg)
+{
+ return m_aux->ins8250_r(reg);
+}
+
+void h_88_3_device::aux_w(offs_t reg, u8 val)
+{
+ m_aux->ins8250_w(reg, val);
+}
+
+u8 h_88_3_device::modem_r(offs_t reg)
+{
+ return m_modem->ins8250_r(reg);
+}
+
+void h_88_3_device::modem_w(offs_t reg, u8 val)
+{
+ m_modem->ins8250_w(reg, val);
+}
+
+void h_88_3_device::device_start()
+{
+ save_item(NAME(m_lp_intr));
+ save_item(NAME(m_aux_intr));
+ save_item(NAME(m_modem_intr));
+}
+
+void h_88_3_device::device_reset()
+{
+ ioport_value const cfg_lp(m_cfg_lp->read());
+ ioport_value const cfg_aux(m_cfg_aux->read());
+ ioport_value const cfg_modem(m_cfg_modem->read());
+
+ m_lp_enabled = bool(BIT(cfg_lp, 0));
+ m_aux_enabled = bool(BIT(cfg_aux, 0));
+ m_modem_enabled = bool(BIT(cfg_modem, 0));
+
+ // LP Interrupt level
+ m_lp_int_idx = BIT(cfg_lp, 1, 2);
+
+ // AUX Interrupt level
+ m_aux_int_idx = BIT(cfg_aux, 1, 2);
+
+ // MODEM Interrupt level
+ m_modem_int_idx = BIT(cfg_modem, 1, 2);
+}
+
+void h_88_3_device::update_intr(u8 level)
+{
+ // check for interrupt disabled
+ if (level == 0)
+ {
+ return;
+ }
+
+ // Handle multiple ports set to the same interrupt. If any are set, interrupt should be triggered
+ int data = 0;
+
+ if (m_lp_enabled && (m_lp_int_idx == level))
+ {
+ data |= m_lp_intr;
+ }
+ if (m_aux_enabled && (m_aux_int_idx == level))
+ {
+ data |= m_aux_intr;
+ }
+ if (m_modem_enabled && (m_modem_int_idx == level))
+ {
+ data |= m_modem_intr;
+ }
+
+ switch(level)
+ {
+ case 1:
+ set_slot_int3(data);
+ break;
+ case 2:
+ set_slot_int4(data);
+ break;
+ case 3:
+ set_slot_int5(data);
+ break;
+ }
+}
+
+void h_88_3_device::lp_int(int data)
+{
+ if (!m_lp_enabled)
+ {
+ return;
+ }
+
+ m_lp_intr = data;
+
+ update_intr(m_lp_int_idx);
+}
+
+void h_88_3_device::aux_int(int data)
+{
+ if (!m_aux_enabled)
+ {
+ return;
+ }
+
+ m_aux_intr = data;
+
+ update_intr(m_aux_int_idx);
+}
+
+void h_88_3_device::modem_int(int data)
+{
+ if (!m_modem_enabled)
+ {
+ return;
+ }
+
+ m_modem_intr = data;
+
+ update_intr(m_modem_int_idx);
+}
+
+void h_88_3_device::device_add_mconfig(machine_config &config)
+{
+ // LP DCE 0xE0-0xE7 (340 - 347 octal)
+ INS8250(config, m_lp, m_clock);
+ m_lp->out_tx_callback().set("dce1", FUNC(rs232_port_device::write_txd));
+ m_lp->out_dtr_callback().set("dce1", FUNC(rs232_port_device::write_dtr));
+ m_lp->out_rts_callback().set("dce1", FUNC(rs232_port_device::write_rts));
+ m_lp->out_int_callback().set(FUNC(h_88_3_device::lp_int));
+
+ rs232_port_device &dce1(RS232_PORT(config, "dce1", default_rs232_devices, "printer"));
+ dce1.rxd_handler().set(m_lp, FUNC(ins8250_device::rx_w));
+ dce1.dcd_handler().set(m_lp, FUNC(ins8250_device::dcd_w));
+ dce1.dsr_handler().set(m_lp, FUNC(ins8250_device::dsr_w));
+ dce1.cts_handler().set(m_lp, FUNC(ins8250_device::cts_w));
+ dce1.ri_handler().set(m_lp, FUNC(ins8250_device::ri_w));
+
+
+ // AUX DCE 0xD0-0xD7 (320 - 327 octal)
+ INS8250(config, m_aux, m_clock);
+ m_aux->out_tx_callback().set("dce2", FUNC(rs232_port_device::write_txd));
+ m_aux->out_dtr_callback().set("dce2", FUNC(rs232_port_device::write_dtr));
+ m_aux->out_rts_callback().set("dce2", FUNC(rs232_port_device::write_rts));
+ m_aux->out_int_callback().set(FUNC(h_88_3_device::aux_int));
+
+ rs232_port_device &dce2(RS232_PORT(config, "dce2", default_rs232_devices, "loopback"));
+ dce2.rxd_handler().set(m_aux, FUNC(ins8250_device::rx_w));
+ dce2.dcd_handler().set(m_aux, FUNC(ins8250_device::dcd_w));
+ dce2.dsr_handler().set(m_aux, FUNC(ins8250_device::dsr_w));
+ dce2.cts_handler().set(m_aux, FUNC(ins8250_device::cts_w));
+ dce2.ri_handler().set(m_aux, FUNC(ins8250_device::ri_w));
+
+
+ // Modem DTE 0xD7-0xDF (330 - 337 octal)
+ INS8250(config, m_modem, m_clock);
+ m_modem->out_tx_callback().set("dte", FUNC(rs232_port_device::write_txd));
+ m_modem->out_dtr_callback().set("dte", FUNC(rs232_port_device::write_dtr));
+ m_modem->out_rts_callback().set("dte", FUNC(rs232_port_device::write_rts));
+ m_modem->out_int_callback().set(FUNC(h_88_3_device::modem_int));
+
+ rs232_port_device &dte(RS232_PORT(config, "dte", default_rs232_devices, "loopback"));
+ dte.rxd_handler().set(m_modem, FUNC(ins8250_device::rx_w));
+ dte.dcd_handler().set(m_modem, FUNC(ins8250_device::dcd_w));
+ dte.dsr_handler().set(m_modem, FUNC(ins8250_device::dsr_w));
+ dte.cts_handler().set(m_modem, FUNC(ins8250_device::cts_w));
+ dte.ri_handler().set(m_modem, FUNC(ins8250_device::ri_w));
+}
+
+
+static INPUT_PORTS_START( h_88_3_device )
+
+ PORT_START("CFG_LP")
+ PORT_CONFNAME(0x01, 0x01, "LP - DCE (340 octal) Enabled" )
+ PORT_CONFSETTING( 0x00, DEF_STR( No ))
+ PORT_CONFSETTING( 0x01, DEF_STR( Yes ))
+ PORT_CONFNAME(0x06, 0x00, "LP - DCE (340 octal) Interrupt level")
+ PORT_CONFSETTING( 0x00, DEF_STR( None ))
+ PORT_CONFSETTING( 0x02, "3")
+ PORT_CONFSETTING( 0x04, "4")
+ PORT_CONFSETTING( 0x06, "5")
+
+ PORT_START("CFG_AUX")
+ PORT_CONFNAME(0x01, 0x00, "AUX - DCE (320 octal) Enabled" )
+ PORT_CONFSETTING( 0x00, DEF_STR( No ))
+ PORT_CONFSETTING( 0x01, DEF_STR( Yes ))
+ PORT_CONFNAME(0x06, 0x00, "AUX - DCE (320 octal) Interrupt level")
+ PORT_CONFSETTING( 0x00, DEF_STR( None ))
+ PORT_CONFSETTING( 0x02, "3")
+ PORT_CONFSETTING( 0x04, "4")
+ PORT_CONFSETTING( 0x06, "5")
+
+ PORT_START("CFG_MODEM")
+ PORT_CONFNAME(0x01, 0x01, "MODEM - DTE (330 octal) Enabled" )
+ PORT_CONFSETTING( 0x00, DEF_STR( No ))
+ PORT_CONFSETTING( 0x01, DEF_STR( Yes ))
+ PORT_CONFNAME(0x06, 0x00, "MODEM - DTE (330 octal) Interrupt level")
+ PORT_CONFSETTING( 0x00, DEF_STR( None ))
+ PORT_CONFSETTING( 0x02, "3")
+ PORT_CONFSETTING( 0x04, "4")
+ PORT_CONFSETTING( 0x06, "5")
+
+INPUT_PORTS_END
+
+static INPUT_PORTS_START( ha_88_3_device )
+ PORT_INCLUDE( h_88_3_device )
+
+ PORT_MODIFY("CFG_AUX")
+ PORT_CONFNAME(0x01, 0x01, "AUX - DCE (320 octal) Enabled" )
+ PORT_CONFSETTING( 0x00, DEF_STR( No ))
+ PORT_CONFSETTING( 0x01, DEF_STR( Yes ))
+
+INPUT_PORTS_END
+
+
+ioport_constructor h_88_3_device::device_input_ports() const
+{
+ return INPUT_PORTS_NAME(h_88_3_device);
+}
+
+ioport_constructor ha_88_3_device::device_input_ports() const
+{
+ return INPUT_PORTS_NAME(ha_88_3_device);
+}
+
+ha_88_3_device::ha_88_3_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock) :
+ h_88_3_device(mconfig, H89BUS_HA_88_3, tag, owner, clock)
+{
+}
+
+} // anonymous namespace
+
+DEFINE_DEVICE_TYPE_PRIVATE(H89BUS_H_88_3, device_h89bus_right_card_interface, h_88_3_device, "h89h_88_3", "Heath H-88-3 3-port Serial Board");
+DEFINE_DEVICE_TYPE_PRIVATE(H89BUS_HA_88_3, device_h89bus_right_card_interface, ha_88_3_device, "h89ha_88_3", "Heath HA-88-3 3-port Serial Board");
diff --git a/src/devices/bus/heathzenith/h89/h_88_3.h b/src/devices/bus/heathzenith/h89/h_88_3.h
new file mode 100644
index 00000000000..dbaaf7c2cd4
--- /dev/null
+++ b/src/devices/bus/heathzenith/h89/h_88_3.h
@@ -0,0 +1,13 @@
+// license:BSD-3-Clause
+// copyright-holders:R. Belmont
+#ifndef MAME_BUS_HEATHZENITH_H89_H_88_3_H
+#define MAME_BUS_HEATHZENITH_H89_H_88_3_H
+
+#pragma once
+
+#include "h89bus.h"
+
+DECLARE_DEVICE_TYPE(H89BUS_H_88_3, device_h89bus_right_card_interface)
+DECLARE_DEVICE_TYPE(H89BUS_HA_88_3, device_h89bus_right_card_interface)
+
+#endif // MAME_BUS_HEATHZENITH_H89_H_88_3_H
diff --git a/src/devices/bus/heathzenith/h89/h_88_5.cpp b/src/devices/bus/heathzenith/h89/h_88_5.cpp
new file mode 100755
index 00000000000..2300bef13ff
--- /dev/null
+++ b/src/devices/bus/heathzenith/h89/h_88_5.cpp
@@ -0,0 +1,214 @@
+// license:BSD-3-Clause
+// copyright-holders:Mark Garlanger
+/***************************************************************************
+
+ Heathkit H-88-5 Cassette Interface Card
+
+ Came standard on the H88 computer and was on option for other H89 class
+ systems.
+
+****************************************************************************/
+
+#include "emu.h"
+
+#include "h_88_5.h"
+
+#include "formats/h8_cas.h"
+#include "imagedev/cassette.h"
+#include "machine/clock.h"
+#include "machine/i8251.h"
+#include "machine/timer.h"
+
+#include "softlist_dev.h"
+#include "speaker.h"
+
+#define LOG_REG (1U << 1)
+#define LOG_LINES (1U << 2)
+#define LOG_CASS (1U << 3)
+#define LOG_FUNC (1U << 4)
+#define VERBOSE (0)
+
+#include "logmacro.h"
+
+#define LOGREG(...) LOGMASKED(LOG_REG, __VA_ARGS__)
+#define LOGLINES(...) LOGMASKED(LOG_LINES, __VA_ARGS__)
+#define LOGCASS(...) LOGMASKED(LOG_CASS, __VA_ARGS__)
+#define LOGFUNC(...) LOGMASKED(LOG_FUNC, __VA_ARGS__)
+
+#ifdef _MSC_VER
+#define FUNCNAME __func__
+#else
+#define FUNCNAME __PRETTY_FUNCTION__
+#endif
+
+namespace {
+
+class h_88_5_device : public device_t, public device_h89bus_right_card_interface
+{
+public:
+ h_88_5_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock = 0);
+
+ virtual void write(u8 select_lines, u8 offset, u8 data) override;
+ virtual u8 read(u8 select_lines, u8 offset) override;
+
+protected:
+ 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;
+
+ void uart_rts(u8 data);
+ void uart_tx_empty(u8 data);
+
+ TIMER_DEVICE_CALLBACK_MEMBER(kansas_r);
+ TIMER_DEVICE_CALLBACK_MEMBER(kansas_w);
+
+ required_device<i8251_device> m_uart;
+ required_device<cassette_image_device> m_cass_player;
+ required_device<cassette_image_device> m_cass_recorder;
+
+ u8 m_cass_data[4];
+ bool m_cassbit;
+ bool m_cassold;
+};
+
+h_88_5_device::h_88_5_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock):
+ device_t(mconfig, H89BUS_H_88_5, tag, owner, 0),
+ device_h89bus_right_card_interface(mconfig, *this),
+ m_uart(*this, "uart"),
+ m_cass_player(*this, "cassette_player"),
+ m_cass_recorder(*this, "cassette_recorder")
+{
+}
+
+void h_88_5_device::write(u8 select_lines, u8 reg, u8 val)
+{
+ if (select_lines & h89bus_device::H89_CASS)
+ {
+ LOGREG("%s: reg: %d val: 0x%02x\n", FUNCNAME, reg, val);
+
+ m_uart->write(reg, val);
+ }
+}
+
+u8 h_88_5_device::read(u8 select_lines, u8 reg)
+{
+ if (select_lines & h89bus_device::H89_CASS)
+ {
+ u8 val = m_uart->read(reg);
+
+ LOGREG("%s: reg: %d val: 0x%02x\n", FUNCNAME, reg, val);
+
+ return val;
+ }
+
+ return 0;
+}
+
+TIMER_DEVICE_CALLBACK_MEMBER(h_88_5_device::kansas_w)
+{
+ m_cass_data[3]++;
+
+ if (m_cassbit != m_cassold)
+ {
+ LOGCASS("%s: m_cassbit changed : %d\n", FUNCNAME, m_cassbit);
+ m_cass_data[3] = 0;
+ m_cassold = m_cassbit;
+ }
+
+ LOGCASS("%s: m_cassbit: %d\n", FUNCNAME, m_cassbit);
+ // 2400Hz -> 0
+ // 1200Hz -> 1
+ const int bit_pos = m_cassbit ? 0 : 1;
+
+ m_cass_recorder->output(BIT(m_cass_data[3], bit_pos) ? -1.0 : +1.0);
+}
+
+TIMER_DEVICE_CALLBACK_MEMBER(h_88_5_device::kansas_r)
+{
+ // cassette - turn 1200/2400Hz to a bit
+ m_cass_data[1]++;
+ u8 cass_ws = (m_cass_player->input() > +0.03) ? 1 : 0;
+
+ LOGCASS("%s: cass_ws: %d\n", FUNCNAME, cass_ws);
+
+ if (cass_ws != m_cass_data[0])
+ {
+ LOGCASS("%s: cass_ws has changed value\n", FUNCNAME);
+ m_cass_data[0] = cass_ws;
+ m_uart->write_rxd((m_cass_data[1] < 12) ? 1 : 0);
+ m_cass_data[1] = 0;
+ }
+}
+
+void h_88_5_device::uart_rts(u8 data)
+{
+ LOGLINES("%s: data: %d\n", FUNCNAME, data);
+
+ m_cass_player->change_state(bool(data) ? CASSETTE_STOPPED : CASSETTE_PLAY, CASSETTE_MASK_UISTATE);
+}
+
+void h_88_5_device::uart_tx_empty(u8 data)
+{
+ LOGLINES("%s: data: %d\n", FUNCNAME, data);
+
+ m_cass_recorder->change_state(bool(data) ? CASSETTE_STOPPED : CASSETTE_RECORD, CASSETTE_MASK_UISTATE);
+}
+
+void h_88_5_device::device_start()
+{
+ save_item(NAME(m_cass_data));
+ save_item(NAME(m_cassbit));
+ save_item(NAME(m_cassold));
+}
+
+void h_88_5_device::device_reset()
+{
+ LOGFUNC("%s\n", FUNCNAME);
+
+ // cassette
+ m_cassbit = 1;
+ m_cassold = 0;
+ m_cass_data[0] = 0;
+ m_cass_data[1] = 0;
+ m_cass_data[2] = 0;
+ m_cass_data[3] = 0;
+
+ m_uart->write_cts(0);
+ m_uart->write_dsr(0);
+ m_uart->write_rxd(0);
+}
+
+void h_88_5_device::device_add_mconfig(machine_config &config)
+{
+ I8251(config, m_uart, 0);
+ m_uart->txd_handler().set([this] (bool state) { m_cassbit = state; });
+ m_uart->rts_handler().set(FUNC(h_88_5_device::uart_rts));
+ m_uart->txempty_handler().set(FUNC(h_88_5_device::uart_tx_empty));
+
+ clock_device &cassette_clock(CLOCK(config, "cassette_clock", 4800));
+ cassette_clock.signal_handler().set(m_uart, FUNC(i8251_device::write_txc));
+ cassette_clock.signal_handler().append(m_uart, FUNC(i8251_device::write_rxc));
+
+ SPEAKER(config, "mono").front_right();
+
+ CASSETTE(config, m_cass_player);
+ m_cass_player->set_formats(h8_cassette_formats);
+ m_cass_player->set_default_state(CASSETTE_STOPPED | CASSETTE_MOTOR_ENABLED | CASSETTE_SPEAKER_ENABLED);
+ m_cass_player->add_route(ALL_OUTPUTS, "mono", 0.15);
+ m_cass_player->set_interface("h88_cass_player");
+
+ CASSETTE(config, m_cass_recorder);
+ m_cass_recorder->set_formats(h8_cassette_formats);
+ m_cass_recorder->set_default_state(CASSETTE_STOPPED | CASSETTE_MOTOR_ENABLED | CASSETTE_SPEAKER_ENABLED);
+ m_cass_recorder->add_route(ALL_OUTPUTS, "mono", 0.15);
+ m_cass_recorder->set_interface("h88_cass_recorder");
+
+ SOFTWARE_LIST(config, "cass_list").set_original("h88_cass");
+
+ TIMER(config, "kansas_w").configure_periodic(FUNC(h_88_5_device::kansas_w), attotime::from_hz(4800));
+ TIMER(config, "kansas_r").configure_periodic(FUNC(h_88_5_device::kansas_r), attotime::from_hz(40000));
+}
+
+}
+
+DEFINE_DEVICE_TYPE_PRIVATE(H89BUS_H_88_5, device_h89bus_right_card_interface, h_88_5_device, "h89h_88_5", "Heath H-88-5 Cassette Interface Board");
diff --git a/src/devices/bus/heathzenith/h89/h_88_5.h b/src/devices/bus/heathzenith/h89/h_88_5.h
new file mode 100644
index 00000000000..a210e7d0579
--- /dev/null
+++ b/src/devices/bus/heathzenith/h89/h_88_5.h
@@ -0,0 +1,12 @@
+// license:BSD-3-Clause
+// copyright-holders:R. Belmont
+#ifndef MAME_BUS_HEATHZENITH_H89_H_88_5_H
+#define MAME_BUS_HEATHZENITH_H89_H_88_5_H
+
+#pragma once
+
+#include "h89bus.h"
+
+DECLARE_DEVICE_TYPE(H89BUS_H_88_5, device_h89bus_right_card_interface)
+
+#endif // MAME_BUS_HEATHZENITH_H89_H_88_5_H
diff --git a/src/devices/bus/heathzenith/h89/mms77316_fdc.cpp b/src/devices/bus/heathzenith/h89/mms77316_fdc.cpp
new file mode 100644
index 00000000000..87a1599d8a2
--- /dev/null
+++ b/src/devices/bus/heathzenith/h89/mms77316_fdc.cpp
@@ -0,0 +1,334 @@
+// license:BSD-3-Clause
+// copyright-holders:Mark Garlanger
+/***************************************************************************
+
+ Magnolia Microsystems 77316 DD soft-sectored floppy controller
+
+ Supported upto 8 floppy drives
+ - 4 8" drives
+ - 4 5.25" drives
+
+****************************************************************************/
+
+#include "emu.h"
+
+#include "mms77316_fdc.h"
+
+#define LOG_REG (1U << 1) // Shows register setup
+#define LOG_LINES (1U << 2) // Show control lines
+#define LOG_DRIVE (1U << 3) // Show drive select
+#define LOG_FUNC (1U << 4) // Function calls
+#define LOG_ERR (1U << 5) // log errors
+#define LOG_BURST (1U << 6) // burst mode
+#define LOG_DATA (1U << 7) // data read/writes
+
+#define VERBOSE (0)
+
+#include "logmacro.h"
+
+#define LOGREG(...) LOGMASKED(LOG_REG, __VA_ARGS__)
+#define LOGLINES(...) LOGMASKED(LOG_LINES, __VA_ARGS__)
+#define LOGDRIVE(...) LOGMASKED(LOG_DRIVE, __VA_ARGS__)
+#define LOGFUNC(...) LOGMASKED(LOG_FUNC, __VA_ARGS__)
+#define LOGERR(...) LOGMASKED(LOG_ERR, __VA_ARGS__)
+#define LOGBURST(...) LOGMASKED(LOG_BURST, __VA_ARGS__)
+#define LOGDATA(...) LOGMASKED(LOG_DATA, __VA_ARGS__)
+
+#ifdef _MSC_VER
+#define FUNCNAME __func__
+#else
+#define FUNCNAME __PRETTY_FUNCTION__
+#endif
+
+
+mms77316_fdc_device::mms77316_fdc_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock):
+ device_t(mconfig, H89BUS_MMS77316, tag, owner, 0),
+ device_h89bus_right_card_interface(mconfig, *this),
+ m_fdc(*this, "mms_fdc"),
+ m_floppies(*this, "mms_fdc:%u", 0U),
+ m_intr_cntrl(*this, finder_base::DUMMY_TAG)
+{
+}
+
+void mms77316_fdc_device::ctrl_w(u8 val)
+{
+ LOGREG("%s: val: %d\n", FUNCNAME, val);
+
+ u8 floppy_drive = BIT(val, 0, 3);
+ u8 five_in_drv = bool(BIT(val, ctrl_525DriveSel_c));
+
+ m_drq_count = 0;
+ m_irq_allowed = bool(BIT(val, ctrl_EnableIntReq_c));
+ m_drq_allowed = m_irq_allowed && bool(BIT(val, ctrl_EnableDrqInt_c));
+
+ m_fdc->dden_w(BIT(val, ctrl_SetMFMRecording_c));
+
+ LOGLINES("%s: intrq allowed: %d, drq allowed: %d\n", FUNCNAME, m_irq_allowed, m_drq_allowed);
+
+ if (m_irq_allowed)
+ {
+ m_intr_cntrl->set_irq(m_irq);
+ m_intr_cntrl->set_drq(m_drq);
+ }
+ else
+ {
+ m_intr_cntrl->set_irq(CLEAR_LINE);
+ m_intr_cntrl->set_drq(CLEAR_LINE);
+ }
+
+ LOGDRIVE("%s: floppydrive: %d, 5.25 in: %d\n", FUNCNAME, floppy_drive, five_in_drv);
+
+ m_fdc->set_floppy(m_floppies[floppy_drive]->get_device());
+
+ m_fdc->set_clock(five_in_drv ? FIVE_IN_CLOCK : EIGHT_IN_CLOCK);
+
+ for (int i = 4; i < 8; i++)
+ {
+ auto elem = m_floppies[i];
+ if (elem)
+ {
+ floppy_image_device *floppy = elem->get_device();
+ if (floppy)
+ {
+ // set motor for installed 5" drives
+ floppy->mon_w(!five_in_drv);
+ }
+ }
+ }
+}
+
+void mms77316_fdc_device::data_w(u8 val)
+{
+ LOGDATA("%s: val: %d\n", FUNCNAME, val);
+
+ if (burst_mode_r() && !m_drq && !m_irq)
+ {
+ LOGBURST("%s: burst_mode_r\n", FUNCNAME);
+
+ set_slot_wait(ASSERT_LINE);
+ return;
+ }
+
+ m_fdc->data_w(val);
+}
+
+void mms77316_fdc_device::write(u8 select_lines, u8 reg, u8 val)
+{
+ if (!(select_lines & h89bus_device::H89_GPP))
+ {
+ return;
+ }
+
+ if (reg != 2) LOGREG("%s: reg: %d val: 0x%02x\n", FUNCNAME, reg, val);
+
+ switch (reg)
+ {
+ case 0:
+ ctrl_w(val);
+ break;
+ case 1:
+ case 2:
+ case 3:
+ LOGERR("%s: Unexpected port write reg: %d val: 0x%02x\n", FUNCNAME, reg, val);
+ break;
+ case 4:
+ m_fdc->cmd_w(val);
+ break;
+ case 5:
+ m_fdc->track_w(val);
+ break;
+ case 6:
+ m_fdc->sector_w(val);
+ break;
+ case 7:
+ data_w(val);
+ break;
+ }
+}
+
+u8 mms77316_fdc_device::data_r()
+{
+ u8 data = 0;
+
+ if (burst_mode_r() && !m_drq && !m_irq)
+ {
+ LOGBURST("%s: burst_mode setting wait state\n", FUNCNAME);
+
+ if (!machine().side_effects_disabled())
+ {
+ set_slot_wait(ASSERT_LINE);
+ }
+ }
+ else
+ {
+ data = m_fdc->data_r();
+ }
+
+ LOGDATA("%s: data: %d\n", FUNCNAME, data);
+
+ return data;
+}
+
+u8 mms77316_fdc_device::read(u8 select_lines, u8 reg)
+{
+ if (!(select_lines & h89bus_device::H89_GPP))
+ {
+ return 0;
+ }
+
+ // default return for the h89
+ u8 value = 0xff;
+
+ switch (reg)
+ {
+ case 0:
+ case 1:
+ case 2:
+ case 3:
+ // read not supported on these addresses
+ LOGERR("%s: Unexpected port read reg: %d\n", FUNCNAME, reg);
+ break;
+ case 4:
+ value = m_fdc->status_r();
+ break;
+ case 5:
+ value = m_fdc->track_r();
+ break;
+ case 6:
+ value = m_fdc->sector_r();
+ break;
+ case 7:
+ value = data_r();
+ break;
+ }
+
+ LOGREG("%s: reg: %d val: 0x%02x\n", FUNCNAME, reg, value);
+
+ return value;
+}
+
+void mms77316_fdc_device::device_start()
+{
+ save_item(NAME(m_irq_allowed));
+ save_item(NAME(m_drq_allowed));
+ save_item(NAME(m_irq));
+ save_item(NAME(m_drq));
+ save_item(NAME(m_drq_count));
+}
+
+void mms77316_fdc_device::device_reset()
+{
+ m_irq_allowed = false;
+ m_drq_allowed = false;
+ m_irq = false;
+ m_drq_count = 0;
+
+ m_intr_cntrl->set_irq(CLEAR_LINE);
+ m_intr_cntrl->set_drq(CLEAR_LINE);
+ set_slot_wait(CLEAR_LINE);
+
+ for (int i = 0; i < 4; i++)
+ {
+ auto elem = m_floppies[i];
+ if (elem)
+ {
+ floppy_image_device *floppy = elem->get_device();
+ if (floppy)
+ {
+ // turn on motor of all installed 8" floppies
+ floppy->mon_w(0);
+ }
+ }
+ }
+}
+
+static void mms_5_in_floppies(device_slot_interface &device)
+{
+ // H-17-1 -- SS 48tpi
+ device.option_add("5_ss_dd", FLOPPY_525_SSDD);
+ // SS 96tpi
+ device.option_add("5_ss_qd", FLOPPY_525_SSQD);
+ // DS 48tpi
+ device.option_add("5_ds_dd", FLOPPY_525_DD);
+ // H-17-4 / H-17-5 -- DS 96tpi
+ device.option_add("5_ds_qd", FLOPPY_525_QD);
+}
+
+static void mms_8_in_floppies(device_slot_interface &device)
+{
+ // 8" DSDD
+ device.option_add("8_ss_sd", FLOPPY_8_SSSD);
+ // 8" SSDD
+ device.option_add("8_ds_sd", FLOPPY_8_DSSD);
+ // 8" DSDD
+ device.option_add("8_ss_dd", FLOPPY_8_SSDD);
+ // 8" SSDD
+ device.option_add("8_ds_dd", FLOPPY_8_DSDD);
+}
+
+void mms77316_fdc_device::device_add_mconfig(machine_config &config)
+{
+ FD1797(config, m_fdc, EIGHT_IN_CLOCK);
+ m_fdc->intrq_wr_callback().set(FUNC(mms77316_fdc_device::set_irq));
+ m_fdc->drq_wr_callback().set(FUNC(mms77316_fdc_device::set_drq));
+
+ // 8" Floppy drives
+ FLOPPY_CONNECTOR(config, m_floppies[0], mms_8_in_floppies, "8_ds_dd", floppy_image_device::default_mfm_floppy_formats);
+ m_floppies[0]->enable_sound(true);
+ FLOPPY_CONNECTOR(config, m_floppies[1], mms_8_in_floppies, "8_ds_dd", floppy_image_device::default_mfm_floppy_formats);
+ m_floppies[1]->enable_sound(true);
+ FLOPPY_CONNECTOR(config, m_floppies[2], mms_8_in_floppies, "8_ds_dd", floppy_image_device::default_mfm_floppy_formats);
+ m_floppies[2]->enable_sound(true);
+ FLOPPY_CONNECTOR(config, m_floppies[3], mms_8_in_floppies, "8_ds_dd", floppy_image_device::default_mfm_floppy_formats);
+ m_floppies[3]->enable_sound(true);
+
+ // 5" Floppy drives
+ FLOPPY_CONNECTOR(config, m_floppies[4], mms_5_in_floppies, "5_ds_qd", floppy_image_device::default_mfm_floppy_formats);
+ m_floppies[4]->enable_sound(true);
+ FLOPPY_CONNECTOR(config, m_floppies[5], mms_5_in_floppies, "5_ds_qd", floppy_image_device::default_mfm_floppy_formats);
+ m_floppies[5]->enable_sound(true);
+ FLOPPY_CONNECTOR(config, m_floppies[6], mms_5_in_floppies, "5_ds_qd", floppy_image_device::default_mfm_floppy_formats);
+ m_floppies[6]->enable_sound(true);
+ FLOPPY_CONNECTOR(config, m_floppies[7], mms_5_in_floppies, "5_ds_qd", floppy_image_device::default_mfm_floppy_formats);
+ m_floppies[7]->enable_sound(true);
+}
+
+void mms77316_fdc_device::set_irq(int state)
+{
+ LOGLINES("set irq, allowed: %d state: %d\n", m_irq_allowed, state);
+
+ m_irq = state;
+
+ if (m_irq)
+ {
+ set_slot_wait(CLEAR_LINE);
+ m_drq_count = 0;
+ }
+
+ m_intr_cntrl->set_irq(m_irq_allowed ? m_irq : CLEAR_LINE);
+}
+
+void mms77316_fdc_device::set_drq(int state)
+{
+ LOGLINES("set drq, allowed: %d state: %d\n", m_drq_allowed, state);
+
+ m_drq = state;
+
+ if (burst_mode_r())
+ {
+ LOGBURST("%s: in burst mode drq: %d, m_drq_count: %d\n", FUNCNAME, m_drq, m_drq_count);
+
+ if (m_drq)
+ {
+ set_slot_wait(CLEAR_LINE);
+ }
+
+ m_intr_cntrl->set_drq(m_drq_count == 0 ? m_drq : CLEAR_LINE);
+ }
+ else
+ {
+ m_intr_cntrl->set_drq(m_drq_allowed ? m_drq : CLEAR_LINE);
+ }
+}
+
+DEFINE_DEVICE_TYPE_PRIVATE(H89BUS_MMS77316, device_h89bus_right_card_interface, mms77316_fdc_device, "mms77316_fdc", "Magnolia MicroSystems 77316 Soft-sectored Controller");
diff --git a/src/devices/bus/heathzenith/h89/mms77316_fdc.h b/src/devices/bus/heathzenith/h89/mms77316_fdc.h
new file mode 100644
index 00000000000..52d75b357a7
--- /dev/null
+++ b/src/devices/bus/heathzenith/h89/mms77316_fdc.h
@@ -0,0 +1,73 @@
+// license:BSD-3-Clause
+// copyright-holders:Mark Garlanger
+/***************************************************************************
+
+ Magnolia Microsystems 77316 soft-sectored floppy controller
+
+****************************************************************************/
+
+#ifndef MAME_BUS_HEATHZENITH_H89_MMS77316_FDC_H
+#define MAME_BUS_HEATHZENITH_H89_MMS77316_FDC_H
+
+#pragma once
+
+#include "h89bus.h"
+
+#include "imagedev/floppy.h"
+#include "machine/wd_fdc.h"
+
+#include "bus/heathzenith/intr_cntrl/intr_cntrl.h"
+
+class mms77316_fdc_device : public device_t, public device_h89bus_right_card_interface
+{
+public:
+ mms77316_fdc_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock = 0);
+
+ virtual void write(u8 select_lines, u8 offset, u8 data) override;
+ virtual u8 read(u8 select_lines, u8 offset) override;
+
+ template <typename T> void set_intr_cntrl(T &&tag) { m_intr_cntrl.set_tag(std::forward<T>(tag)); }
+
+protected:
+ 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;
+
+ void ctrl_w(u8 val);
+ void data_w(u8 val);
+ u8 data_r();
+
+ void set_irq(int state);
+ void set_drq(int state);
+
+ // Burst mode was required for a 2 MHz Z80 to handle 8" DD data rates.
+ // The typical irq/drq was too slow, this utilizes wait states to read the
+ // WD1797 data port once the drq line is high.
+ inline bool burst_mode_r() { return !m_drq_allowed; }
+
+private:
+ required_device<fd1797_device> m_fdc;
+ required_device_array<floppy_connector, 8> m_floppies;
+ required_device<heath_intr_socket> m_intr_cntrl;
+
+ bool m_irq_allowed;
+ bool m_drq_allowed;
+
+ bool m_irq;
+ bool m_drq;
+ u32 m_drq_count;
+
+ /// Bits set in cmd_ControlPort_c
+ static constexpr u8 ctrl_525DriveSel_c = 2;
+ static constexpr u8 ctrl_EnableIntReq_c = 3;
+ static constexpr u8 ctrl_EnableDrqInt_c = 5;
+ static constexpr u8 ctrl_SetMFMRecording_c = 6;
+
+ static constexpr XTAL MASTER_CLOCK = XTAL(8'000'000);
+ static constexpr XTAL FIVE_IN_CLOCK = MASTER_CLOCK / 8;
+ static constexpr XTAL EIGHT_IN_CLOCK = MASTER_CLOCK / 4;
+};
+
+DECLARE_DEVICE_TYPE(H89BUS_MMS77316, device_h89bus_right_card_interface)
+
+#endif // MAME_BUS_HEATHZENITH_H89_MMS77316_FDC_H
diff --git a/src/devices/bus/heathzenith/h89/sigmasoft_parallel_port.cpp b/src/devices/bus/heathzenith/h89/sigmasoft_parallel_port.cpp
new file mode 100644
index 00000000000..b25ae70669b
--- /dev/null
+++ b/src/devices/bus/heathzenith/h89/sigmasoft_parallel_port.cpp
@@ -0,0 +1,206 @@
+// license:BSD-3-Clause
+// copyright-holders:Mark Garlanger
+/***************************************************************************
+
+ SigmaSoft Universal Parallel Interface Board
+
+
+****************************************************************************/
+
+#include "emu.h"
+
+#include "bus/heathzenith/h19/tlb.h"
+
+#include "sigmasoft_parallel_port.h"
+
+//
+// Logging defines
+//
+#define LOG_REG (1U << 1) // Shows register setup
+#define LOG_FUNC (1U << 2) // Function calls
+
+#define VERBOSE (0)
+
+#include "logmacro.h"
+
+#define LOGREG(...) LOGMASKED(LOG_REG, __VA_ARGS__)
+#define LOGFUNC(...) LOGMASKED(LOG_FUNC, __VA_ARGS__)
+
+#ifdef _MSC_VER
+#define FUNCNAME __func__
+#else
+#define FUNCNAME __PRETTY_FUNCTION__
+#endif
+
+
+static constexpr u16 SELECT_ADDR_MASK = 0xF8;
+
+/**
+ * The SigmaSoft Parallel Port
+ */
+sigmasoft_parallel_port::sigmasoft_parallel_port(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock):
+ sigmasoft_parallel_port(mconfig, H89BUS_SIGMASOFT_PARALLEL, tag, owner, clock)
+{
+}
+
+sigmasoft_parallel_port::sigmasoft_parallel_port(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, u32 clock):
+ device_t(mconfig, type, tag, owner, clock),
+ device_h89bus_left_card_interface(mconfig, *this),
+ m_jumpers(*this, "JUMPERS")
+{
+}
+
+inline bool sigmasoft_parallel_port::card_selected(u8 select_lines, u16 offset)
+{
+ return m_enabled &&
+ (select_lines & h89bus_device::H89_IO) &&
+ ((offset & SELECT_ADDR_MASK) == m_base_addr);
+}
+
+void sigmasoft_parallel_port::igc_w(u8 offset, u8 val)
+{
+}
+
+void sigmasoft_parallel_port::write(u8 select_lines, u16 offset, u8 data)
+{
+ if (!card_selected(select_lines, offset))
+ {
+ return;
+ }
+
+ LOGFUNC("%s: reg: %d val: %d\n", FUNCNAME, offset, data);
+
+ offset &= 0x07;
+
+ switch (offset)
+ {
+ case 0:
+ case 1:
+ case 2:
+ case 3:
+ case 4:
+ case 5:
+ igc_w(offset, data);
+ break;
+ case 6:
+ // TODO - Centronics interface
+ break;
+ case 7:
+ // TODO - Centronics interface
+ break;
+ }
+}
+
+u8 sigmasoft_parallel_port::igc_r(u8 offset)
+{
+ return 0;
+}
+
+u8 sigmasoft_parallel_port::read(u8 select_lines, u16 offset)
+{
+ u8 value = 0;
+
+ if (!card_selected(select_lines, offset))
+ {
+ return value;
+ }
+
+ offset &= 0x07;
+
+ switch (offset)
+ {
+ case 0:
+ case 1:
+ case 2:
+ case 3:
+ case 4:
+ case 5:
+ value = igc_r(offset);
+ break;
+ case 6:
+ // TODO - Centronics interface
+ break;
+ case 7:
+ // TODO - Centronics interface
+ break;
+ }
+
+ LOGFUNC("%s: reg: %d val: %d\n", FUNCNAME, offset, value);
+
+ return value;
+}
+
+void sigmasoft_parallel_port::device_start()
+{
+}
+
+void sigmasoft_parallel_port::device_reset()
+{
+ ioport_value const jumpers(m_jumpers->read());
+
+ m_enabled = bool(jumpers & 0x20);
+
+ m_base_addr = (jumpers & 0x1f) << 3;
+}
+
+static INPUT_PORTS_START( sigmasoft_parallel_port_device )
+ PORT_START("JUMPERS")
+ PORT_CONFNAME(0x01, 0x01, "Port Address Selection a3" )
+ PORT_CONFSETTING( 0x00, "0")
+ PORT_CONFSETTING( 0x01, "1")
+ PORT_CONFNAME(0x02, 0x00, "Port Address Selection a4" )
+ PORT_CONFSETTING( 0x00, "0")
+ PORT_CONFSETTING( 0x02, "1")
+ PORT_CONFNAME(0x04, 0x00, "Port Address Selection a5" )
+ PORT_CONFSETTING( 0x00, "0")
+ PORT_CONFSETTING( 0x04, "1")
+ PORT_CONFNAME(0x08, 0x00, "Port Address Selection a6" )
+ PORT_CONFSETTING( 0x00, "0")
+ PORT_CONFSETTING( 0x08, "1")
+ PORT_CONFNAME(0x10, 0x00, "Port Address Selection a7" )
+ PORT_CONFSETTING( 0x00, "0")
+ PORT_CONFSETTING( 0x10, "1")
+
+ PORT_CONFNAME(0x20, 0x20, "Enabled" )
+ PORT_CONFSETTING( 0x00, DEF_STR( No ))
+ PORT_CONFSETTING( 0x20, DEF_STR( Yes ))
+INPUT_PORTS_END
+
+ioport_constructor sigmasoft_parallel_port::device_input_ports() const
+{
+ return INPUT_PORTS_NAME(sigmasoft_parallel_port_device);
+}
+
+
+/**
+ * The SigmaSoft Parallel Port connected to a SigmaSoft IGC board
+ */
+sigmasoft_parallel_port_igc::sigmasoft_parallel_port_igc(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock):
+ sigmasoft_parallel_port(mconfig, H89BUS_SIGMASOFT_PARALLEL_IGC, tag, owner, clock),
+ m_tlbc(*this, finder_base::DUMMY_TAG)
+{
+}
+
+void sigmasoft_parallel_port_igc::igc_w(u8 offset, u8 val)
+{
+ m_tlbc->sigma_w(offset, val);
+}
+
+u8 sigmasoft_parallel_port_igc::igc_r(u8 offset)
+{
+ return m_tlbc->sigma_r(offset);
+}
+
+void sigmasoft_parallel_port_igc::device_start()
+{
+ sigmasoft_parallel_port::device_start();
+}
+
+void sigmasoft_parallel_port_igc::device_reset()
+{
+ sigmasoft_parallel_port::device_reset();
+}
+
+
+DEFINE_DEVICE_TYPE_PRIVATE(H89BUS_SIGMASOFT_PARALLEL, device_h89bus_left_card_interface, sigmasoft_parallel_port, "sigmasoft_parallel_port", "SigmaSoft Universal Parallel Board");
+DEFINE_DEVICE_TYPE_PRIVATE(H89BUS_SIGMASOFT_PARALLEL_IGC, device_h89bus_left_card_interface, sigmasoft_parallel_port_igc, "sigmasoft_parallel_port_igc", "SigmaSoft Universal Parallel Board connected to SigmaSoft IGC");
diff --git a/src/devices/bus/heathzenith/h89/sigmasoft_parallel_port.h b/src/devices/bus/heathzenith/h89/sigmasoft_parallel_port.h
new file mode 100644
index 00000000000..66ead7076f9
--- /dev/null
+++ b/src/devices/bus/heathzenith/h89/sigmasoft_parallel_port.h
@@ -0,0 +1,73 @@
+// license:BSD-3-Clause
+// copyright-holders:Mark Garlanger
+/***************************************************************************
+
+ SigmaSoft Universal Parallel Interface Board
+
+****************************************************************************/
+
+#ifndef MAME_BUS_HEATHZENITH_H89_SIGMASOFT_PARALLEL_PORT_H
+#define MAME_BUS_HEATHZENITH_H89_SIGMASOFT_PARALLEL_PORT_H
+
+#pragma once
+
+#include "h89bus.h"
+
+#include "bus/heathzenith/h19/tlb.h"
+
+class sigmasoft_parallel_port : public device_t, public device_h89bus_left_card_interface
+{
+public:
+ sigmasoft_parallel_port(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock = 0);
+
+ virtual u8 read(u8 select_lines, u16 offset) override;
+ virtual void write(u8 select_lines, u16 offset, u8 data) override;
+
+protected:
+ sigmasoft_parallel_port(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, u32 clock);
+
+ virtual void device_start() override ATTR_COLD;
+ virtual void device_reset() override ATTR_COLD;
+ virtual ioport_constructor device_input_ports() const override ATTR_COLD;
+
+ inline bool card_selected(u8 select_lines, u16 offset);
+
+ virtual void igc_w(u8 offset, u8 val);
+ virtual u8 igc_r(u8 offset);
+
+private:
+
+ required_ioport m_jumpers;
+
+ // physical jumper on the board to enable/disable entire board
+ bool m_enabled;
+
+ // base address of board configured by jumpers.
+ u16 m_base_addr;
+};
+
+class sigmasoft_parallel_port_igc : public sigmasoft_parallel_port
+{
+public:
+ sigmasoft_parallel_port_igc(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock = 0);
+
+ template <typename T> void set_tlbc(T &&tag) { m_tlbc.set_tag(std::forward<T>(tag)); }
+
+protected:
+
+ virtual void device_start() override ATTR_COLD;
+ virtual void device_reset() override ATTR_COLD;
+
+ virtual void igc_w(u8 offset, u8 val) override;
+ virtual u8 igc_r(u8 offset) override;
+
+private:
+
+ required_device<heath_tlb_connector> m_tlbc;
+
+};
+
+DECLARE_DEVICE_TYPE(H89BUS_SIGMASOFT_PARALLEL, device_h89bus_left_card_interface)
+DECLARE_DEVICE_TYPE(H89BUS_SIGMASOFT_PARALLEL_IGC, device_h89bus_left_card_interface)
+
+#endif // MAME_BUS_HEATHZENITH_H89_SIGMASOFT_PARALLEL_PORT_H
diff --git a/src/devices/bus/heathzenith/h89/sigmasoft_sound.cpp b/src/devices/bus/heathzenith/h89/sigmasoft_sound.cpp
new file mode 100644
index 00000000000..16ee969ee6a
--- /dev/null
+++ b/src/devices/bus/heathzenith/h89/sigmasoft_sound.cpp
@@ -0,0 +1,214 @@
+// license:BSD-3-Clause
+// copyright-holders:Mark Garlanger
+/***************************************************************************
+
+ SigmaSoft Sound Effects Board
+
+****************************************************************************/
+
+#include "emu.h"
+
+#include "sound/ay8910.h"
+#include "speaker.h"
+
+#include "sigmasoft_sound.h"
+
+//
+// Logging defines
+//
+#define LOG_REG (1U << 1) // Shows register setup
+#define LOG_FUNC (1U << 2) // Function calls
+#define LOG_ERR (1U << 3)
+
+#define VERBOSE (0)
+
+#include "logmacro.h"
+
+#define LOGREG(...) LOGMASKED(LOG_REG, __VA_ARGS__)
+#define LOGFUNC(...) LOGMASKED(LOG_FUNC, __VA_ARGS__)
+#define LOGERR(...) LOGMASKED(LOG_ERR, __VA_ARGS__)
+
+#ifdef _MSC_VER
+#define FUNCNAME __func__
+#else
+#define FUNCNAME __PRETTY_FUNCTION__
+#endif
+
+namespace {
+
+class h89bus_sigmasoft_snd_device : public device_t, public device_h89bus_right_card_interface
+{
+public:
+ h89bus_sigmasoft_snd_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock = 0);
+
+ virtual u8 read(u8 select_lines, u8 reg) override;
+ virtual void write(u8 select_lines, u8 reg, u8 val) override;
+
+protected:
+ 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;
+ virtual ioport_constructor device_input_ports() const override ATTR_COLD;
+
+ u8 read_joystick();
+
+ u8 transform_joystick_input(u8 raw_value);
+
+private:
+ required_device<ay8910_device> m_ay8910;
+ required_ioport m_joystick1, m_joystick2;
+ required_ioport m_config;
+
+ u8 m_port_selection;
+};
+
+//**************************************************************************
+// INPUT PORTS
+//**************************************************************************
+static INPUT_PORTS_START( sigma_sound )
+ PORT_START("joystick_p1")
+ PORT_BIT( 0x01, IP_ACTIVE_HIGH, IPT_JOYSTICK_UP )
+ PORT_BIT( 0x02, IP_ACTIVE_HIGH, IPT_JOYSTICK_RIGHT )
+ PORT_BIT( 0x04, IP_ACTIVE_HIGH, IPT_JOYSTICK_DOWN )
+ PORT_BIT( 0x08, IP_ACTIVE_HIGH, IPT_JOYSTICK_LEFT )
+ PORT_BIT( 0x10, IP_ACTIVE_HIGH, IPT_BUTTON1 )
+
+ PORT_START("joystick_p2")
+ PORT_BIT( 0x01, IP_ACTIVE_HIGH, IPT_JOYSTICK_UP ) PORT_PLAYER(2)
+ PORT_BIT( 0x02, IP_ACTIVE_HIGH, IPT_JOYSTICK_RIGHT ) PORT_PLAYER(2)
+ PORT_BIT( 0x04, IP_ACTIVE_HIGH, IPT_JOYSTICK_DOWN ) PORT_PLAYER(2)
+ PORT_BIT( 0x08, IP_ACTIVE_HIGH, IPT_JOYSTICK_LEFT ) PORT_PLAYER(2)
+ PORT_BIT( 0x10, IP_ACTIVE_HIGH, IPT_BUTTON1 ) PORT_PLAYER(2)
+
+ PORT_START("CONFIG")
+ PORT_CONFNAME( 0x03, 0x01, "Port selection" )
+ PORT_CONFSETTING( 0x00, "Disabled" )
+ PORT_CONFSETTING( 0x01, "AUX - 320 Octal (0xD0)" )
+ PORT_CONFSETTING( 0x02, "MODEM - 330 Octal (0xD8)" )
+ PORT_CONFSETTING( 0x03, "LP - 340 Octal (0xE0)" )
+INPUT_PORTS_END
+
+
+h89bus_sigmasoft_snd_device::h89bus_sigmasoft_snd_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock):
+ device_t(mconfig, H89BUS_SIGMASOFT_SND, tag, owner, clock),
+ device_h89bus_right_card_interface(mconfig, *this),
+ m_ay8910(*this, "ay8910"),
+ m_joystick1(*this, "joystick_p1"),
+ m_joystick2(*this, "joystick_p2"),
+ m_config(*this, "CONFIG")
+{
+}
+
+void h89bus_sigmasoft_snd_device::write(u8 select_lines, u8 reg, u8 val)
+{
+ if (!(select_lines & m_port_selection))
+ {
+ return;
+ }
+
+ LOGFUNC("%s: reg: %d val: %d\n", FUNCNAME, reg, val);
+
+ switch (reg)
+ {
+ case 0:
+ m_ay8910->data_w(val);
+ break;
+ case 1:
+ m_ay8910->address_w(val);
+ break;
+ default:
+ LOGERR("%s: unexpected port write: %d - 0x%02x\n", FUNCNAME, reg, val);
+ }
+}
+
+u8 h89bus_sigmasoft_snd_device::read(u8 select_lines, u8 reg)
+{
+ if (!(select_lines & m_port_selection))
+ {
+ return 0;
+ }
+
+ u8 value = 0x00;
+
+ switch (reg)
+ {
+ case 0:
+ value = m_ay8910->data_r();
+ break;
+ case 1:
+ value = this->read_joystick();
+ break;
+ default:
+ LOGERR("%s: unexpected port read: %d\n", FUNCNAME, reg);
+ }
+
+ LOGFUNC("%s: reg: %d val: %d\n", FUNCNAME, reg, value);
+
+ return value;
+}
+
+u8 h89bus_sigmasoft_snd_device::transform_joystick_input(u8 raw_value)
+{
+ // when button on joystick is pressed, return 0xf
+ if (raw_value & 0x10)
+ {
+ return 0xf;
+ }
+
+ return raw_value & 0xf;
+}
+
+// high nibble is for left joystick, low nibble is for right joystick
+// when the button is pressed nibble will be set to 0xf
+//
+// note: 2 bits may be set if the direction of the joystick is diagonal, such as 0x9 for left & up.
+//
+u8 h89bus_sigmasoft_snd_device::read_joystick()
+{
+ u8 joy1 = m_joystick1->read();
+ u8 joy2 = m_joystick2->read();
+
+ return (this->transform_joystick_input(joy1) << 4) | this->transform_joystick_input(joy2);
+}
+
+void h89bus_sigmasoft_snd_device::device_start()
+{
+}
+
+void h89bus_sigmasoft_snd_device::device_reset()
+{
+ ioport_value const config(m_config->read());
+
+ switch (config & 0x03)
+ {
+ case 0x00:
+ m_port_selection = 0;
+ break;
+ case 0x01:
+ m_port_selection = h89bus_device::H89_SER0;
+ break;
+ case 0x02:
+ m_port_selection = h89bus_device::H89_SER1;
+ break;
+ case 0x03:
+ m_port_selection = h89bus_device::H89_LP;
+ break;
+ }
+}
+
+ioport_constructor h89bus_sigmasoft_snd_device::device_input_ports() const
+{
+ return INPUT_PORTS_NAME( sigma_sound );
+}
+
+void h89bus_sigmasoft_snd_device::device_add_mconfig(machine_config &config)
+{
+ SPEAKER(config, "mono").front_center();
+
+ AY8910(config, m_ay8910, XTAL(8'000'000)/4); /* ??? 2.000 MHz */
+ m_ay8910->add_route(ALL_OUTPUTS, "mono", 0.25);
+}
+
+} // anonymous namespace
+
+DEFINE_DEVICE_TYPE_PRIVATE(H89BUS_SIGMASOFT_SND, device_h89bus_right_card_interface, h89bus_sigmasoft_snd_device, "h89_sigma_snd", "SigmaSoft Sound Effects Board");
diff --git a/src/devices/bus/heathzenith/h89/sigmasoft_sound.h b/src/devices/bus/heathzenith/h89/sigmasoft_sound.h
new file mode 100644
index 00000000000..b432bc6ef10
--- /dev/null
+++ b/src/devices/bus/heathzenith/h89/sigmasoft_sound.h
@@ -0,0 +1,18 @@
+// license:BSD-3-Clause
+// copyright-holders:Mark Garlanger
+/***************************************************************************
+
+ SigmaSoft Sound Effects Board
+
+****************************************************************************/
+
+#ifndef MAME_BUS_HEATHZENITH_H89_SIGMASOFT_SOUND_H
+#define MAME_BUS_HEATHZENITH_H89_SIGMASOFT_SOUND_H
+
+#pragma once
+
+#include "h89bus.h"
+
+DECLARE_DEVICE_TYPE(H89BUS_SIGMASOFT_SND, device_h89bus_right_card_interface)
+
+#endif // MAME_BUS_HEATHZENITH_H89_SIGMASOFT_SOUND_H
diff --git a/src/devices/bus/heathzenith/h89/we_pullup.cpp b/src/devices/bus/heathzenith/h89/we_pullup.cpp
new file mode 100644
index 00000000000..84e8eb7d416
--- /dev/null
+++ b/src/devices/bus/heathzenith/h89/we_pullup.cpp
@@ -0,0 +1,51 @@
+// license:BSD-3-Clause
+// copyright-holders:Mark Garlanger
+/***************************************************************************
+
+ Heathkit Write Enable pull up resistor
+
+ The H89 has a 1k floppy RAM which can be write protected. With the original
+ equipment, the hard-sector controller card (H-88-1) could control the memory.
+ In later systems, Heath/Zenith wanted to provide a system with only the soft-
+ sectored controller (Z-89-37), but needed to allow writing to the floppy RAM.
+ Heath provided a pullup resistor with the new controller, which allowed the
+ memory to always be write enabled, this was installed on slot P506. Without
+ this, HDOS is not bootable on Z-89-37 soft-sectored controller.
+
+****************************************************************************/
+
+#include "emu.h"
+
+#include "we_pullup.h"
+
+
+namespace {
+
+class h89bus_we_pullup_device : public device_t, public device_h89bus_right_card_interface
+{
+public:
+ h89bus_we_pullup_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock = 0);
+
+protected:
+ virtual void device_start() override ATTR_COLD;
+ virtual void device_reset() override ATTR_COLD;
+};
+
+h89bus_we_pullup_device::h89bus_we_pullup_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock):
+ device_t(mconfig, H89BUS_WE_PULLUP, tag, owner, 0),
+ device_h89bus_right_card_interface(mconfig, *this)
+{
+}
+
+void h89bus_we_pullup_device::device_start()
+{
+}
+
+void h89bus_we_pullup_device::device_reset()
+{
+ set_slot_fmwe(ASSERT_LINE);
+}
+
+} // anonymous namespace
+
+DEFINE_DEVICE_TYPE_PRIVATE(H89BUS_WE_PULLUP, device_h89bus_right_card_interface, h89bus_we_pullup_device, "h89_we_pullup", "Pullup resistor needed when P506 slot is empty");
diff --git a/src/devices/bus/heathzenith/h89/we_pullup.h b/src/devices/bus/heathzenith/h89/we_pullup.h
new file mode 100644
index 00000000000..501d78c278e
--- /dev/null
+++ b/src/devices/bus/heathzenith/h89/we_pullup.h
@@ -0,0 +1,18 @@
+// license:BSD-3-Clause
+// copyright-holders:Mark Garlanger
+/***************************************************************************
+
+ Heathkit Write Enable Pullup
+
+****************************************************************************/
+
+#ifndef MAME_BUS_HEATHZENITH_H89_WE_PULLUP_H
+#define MAME_BUS_HEATHZENITH_H89_WE_PULLUP_H
+
+#pragma once
+
+#include "h89bus.h"
+
+DECLARE_DEVICE_TYPE(H89BUS_WE_PULLUP, device_h89bus_right_card_interface)
+
+#endif // MAME_BUS_HEATHZENITH_H89_WE_PULLUP_H
diff --git a/src/devices/bus/heathzenith/h89/z37_fdc.cpp b/src/devices/bus/heathzenith/h89/z37_fdc.cpp
new file mode 100644
index 00000000000..af0c4d9ae79
--- /dev/null
+++ b/src/devices/bus/heathzenith/h89/z37_fdc.cpp
@@ -0,0 +1,249 @@
+// license:BSD-3-Clause
+// copyright-holders:Mark Garlanger
+/***************************************************************************
+
+ Heathkit Z-37 Floppy controller
+
+ This was an option for both the Heathkit H8 and H89 computer systems.
+
+****************************************************************************/
+
+#include "emu.h"
+
+#include "imagedev/floppy.h"
+#include "machine/wd_fdc.h"
+
+#include "z37_fdc.h"
+
+#define LOG_REG (1U << 1) // Shows register setup
+#define LOG_LINES (1U << 2) // Show control lines
+#define LOG_DRIVE (1U << 3) // Show drive select
+#define LOG_FUNC (1U << 4) // Function calls
+
+#define VERBOSE (0)
+
+#include "logmacro.h"
+
+#define LOGREG(...) LOGMASKED(LOG_REG, __VA_ARGS__)
+#define LOGLINES(...) LOGMASKED(LOG_LINES, __VA_ARGS__)
+#define LOGDRIVE(...) LOGMASKED(LOG_DRIVE, __VA_ARGS__)
+#define LOGFUNC(...) LOGMASKED(LOG_FUNC, __VA_ARGS__)
+
+#ifdef _MSC_VER
+#define FUNCNAME __func__
+#else
+#define FUNCNAME __PRETTY_FUNCTION__
+#endif
+
+
+h89bus_z37_device::h89bus_z37_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock):
+ device_t(mconfig, H89BUS_Z37, tag, owner, 0),
+ device_h89bus_right_card_interface(mconfig, *this),
+ m_fdc(*this, "z37_fdc"),
+ m_floppies(*this, "z37_fdc:%u", 0U),
+ m_intr_cntrl(*this, finder_base::DUMMY_TAG)
+{
+}
+
+void h89bus_z37_device::ctrl_w(u8 val)
+{
+ bool motor_on = bool(BIT(val, ctrl_MotorsOn_c));
+
+ m_irq_allowed = bool(BIT(val, ctrl_EnableIntReq_c));
+ m_drq_allowed = bool(BIT(val, ctrl_EnableDrqInt_c));
+ m_fdc->dden_w(BIT(~val, ctrl_SetMFMRecording_c));
+
+ LOGREG("%s: motor on: %d, intrq allowed: %d, drq allowed: %d\n",
+ FUNCNAME, motor_on, m_irq_allowed, m_drq_allowed);
+
+ if (m_drq_allowed)
+ {
+ m_intr_cntrl->block_interrupts(1);
+ }
+ else
+ {
+ m_intr_cntrl->block_interrupts(0);
+ m_intr_cntrl->set_drq(0);
+ }
+
+ if (BIT(val, ctrl_Drive_0_c))
+ {
+ m_fdc->set_floppy(m_floppies[0]->get_device());
+ LOGDRIVE("Drive selected: 0\n");
+ }
+ else if (BIT(val, ctrl_Drive_1_c))
+ {
+ m_fdc->set_floppy(m_floppies[1]->get_device());
+ LOGDRIVE("Drive selected: 1\n");
+ }
+ else if (BIT(val, ctrl_Drive_2_c))
+ {
+ m_fdc->set_floppy(m_floppies[2]->get_device());
+ LOGDRIVE("Drive selected: 2\n");
+ }
+ else if (BIT(val, ctrl_Drive_3_c))
+ {
+ m_fdc->set_floppy(m_floppies[3]->get_device());
+ LOGDRIVE("Drive selected: 3\n");
+ }
+ else
+ {
+ m_fdc->set_floppy(nullptr);
+ LOGDRIVE("Drive selected: none\n");
+ }
+
+ for (auto &elem : m_floppies)
+ {
+ floppy_image_device *floppy = elem->get_device();
+ if (floppy)
+ {
+ floppy->mon_w(!motor_on);
+ }
+ }
+}
+
+void h89bus_z37_device::intf_w(u8 val)
+{
+ m_access_track_sector = bool(BIT(val, if_SelectSectorTrack_c));
+
+ LOGREG("access track/sector: %d\n", m_access_track_sector);
+}
+
+void h89bus_z37_device::cmd_w(u8 val)
+{
+ m_access_track_sector ? m_fdc->sector_w(val) : m_fdc->cmd_w(val);
+}
+
+u8 h89bus_z37_device::stat_r()
+{
+ return m_access_track_sector ? m_fdc->sector_r() : m_fdc->status_r();
+}
+
+void h89bus_z37_device::data_w(u8 val)
+{
+ m_access_track_sector ? m_fdc->track_w(val) : m_fdc->data_w(val);
+}
+
+u8 h89bus_z37_device::data_r()
+{
+ return m_access_track_sector ? m_fdc->track_r() : m_fdc->data_r();
+}
+
+void h89bus_z37_device::write(u8 select_lines, u8 offset, u8 data)
+{
+ if (!(select_lines & h89bus_device::H89_CASS))
+ {
+ return;
+ }
+
+ LOGFUNC("%s: reg: %d val: 0x%02x\n", FUNCNAME, offset, data);
+
+ switch (offset)
+ {
+ case 0:
+ ctrl_w(data);
+ break;
+ case 1:
+ intf_w(data);
+ break;
+ case 2:
+ cmd_w(data);
+ break;
+ case 3:
+ data_w(data);
+ break;
+ }
+}
+
+u8 h89bus_z37_device::read(u8 select_lines, u8 offset)
+{
+ if (!(select_lines & h89bus_device::H89_CASS))
+ {
+ return 0;
+ }
+
+ // default return for the h89
+ u8 value = 0xff;
+
+ switch (offset)
+ {
+ case 0:
+ case 1:
+ // read not supported on these addresses
+ break;
+ case 2:
+ value = stat_r();
+ break;
+ case 3:
+ value = data_r();
+ break;
+ }
+
+ LOGFUNC("%s: reg: %d val: 0x%02x\n", FUNCNAME, offset, value);
+
+ return value;
+}
+
+void h89bus_z37_device::device_start()
+{
+ save_item(NAME(m_irq_allowed));
+ save_item(NAME(m_drq_allowed));
+ save_item(NAME(m_access_track_sector));
+}
+
+void h89bus_z37_device::device_reset()
+{
+ m_irq_allowed = false;
+ m_drq_allowed = false;
+ m_access_track_sector = false;
+
+ m_intr_cntrl->set_irq(0);
+ m_intr_cntrl->set_drq(0);
+ m_intr_cntrl->block_interrupts(0);
+}
+
+static void z37_floppies(device_slot_interface &device)
+{
+ // H-17-1 -- SS 48tpi
+ device.option_add("ssdd", FLOPPY_525_SSDD);
+ // SS 96tpi
+ device.option_add("ssqd", FLOPPY_525_SSQD);
+ // DS 48tpi
+ device.option_add("dd", FLOPPY_525_DD);
+ // H-17-4 / H-17-5 -- DS 96tpi
+ device.option_add("qd", FLOPPY_525_QD);
+}
+
+void h89bus_z37_device::device_add_mconfig(machine_config &config)
+{
+ FD1797(config, m_fdc, 16_MHz_XTAL / 16);
+ m_fdc->intrq_wr_callback().set(FUNC(h89bus_z37_device::set_irq));
+ m_fdc->drq_wr_callback().set(FUNC(h89bus_z37_device::set_drq));
+ // Z-89-37 schematics show the ready line tied high.
+ m_fdc->set_force_ready(true);
+
+ FLOPPY_CONNECTOR(config, m_floppies[0], z37_floppies, "qd", floppy_image_device::default_mfm_floppy_formats);
+ m_floppies[0]->enable_sound(true);
+ FLOPPY_CONNECTOR(config, m_floppies[1], z37_floppies, "qd", floppy_image_device::default_mfm_floppy_formats);
+ m_floppies[1]->enable_sound(true);
+ FLOPPY_CONNECTOR(config, m_floppies[2], z37_floppies, "qd", floppy_image_device::default_mfm_floppy_formats);
+ m_floppies[2]->enable_sound(true);
+ FLOPPY_CONNECTOR(config, m_floppies[3], z37_floppies, nullptr, floppy_image_device::default_mfm_floppy_formats);
+ m_floppies[3]->enable_sound(true);
+}
+
+void h89bus_z37_device::set_irq(int state)
+{
+ LOGLINES("set irq, allowed: %d state: %d\n", m_irq_allowed, state);
+
+ m_intr_cntrl->set_irq(m_irq_allowed ? state : CLEAR_LINE);
+}
+
+void h89bus_z37_device::set_drq(int state)
+{
+ LOGLINES("set drq, allowed: %d state: %d\n", m_drq_allowed, state);
+
+ m_intr_cntrl->set_drq(m_drq_allowed ? state : CLEAR_LINE);
+}
+
+DEFINE_DEVICE_TYPE_PRIVATE(H89BUS_Z37, device_h89bus_right_card_interface, h89bus_z37_device, "h89_z37", "Heathkit Z-37 Floppy Disk Controller");
diff --git a/src/devices/bus/heathzenith/h89/z37_fdc.h b/src/devices/bus/heathzenith/h89/z37_fdc.h
new file mode 100644
index 00000000000..0c8b4d02983
--- /dev/null
+++ b/src/devices/bus/heathzenith/h89/z37_fdc.h
@@ -0,0 +1,71 @@
+// license:BSD-3-Clause
+// copyright-holders:Mark Garlanger
+/***************************************************************************
+
+ Heathkit Z-37 Floppy Disk Controller
+
+****************************************************************************/
+
+#ifndef MAME_BUS_HEATHZENITH_H89_Z37_FDC_H
+#define MAME_BUS_HEATHZENITH_H89_Z37_FDC_H
+
+#pragma once
+
+#include "h89bus.h"
+
+#include "bus/heathzenith/intr_cntrl/intr_cntrl.h"
+
+class h89bus_z37_device : public device_t, public device_h89bus_right_card_interface
+{
+public:
+ h89bus_z37_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock = 0);
+
+ virtual void write(u8 select_lines, u8 offset, u8 data) override;
+ virtual u8 read(u8 select_lines, u8 offset) override;
+
+ template <typename T> void set_intr_cntrl(T &&tag) { m_intr_cntrl.set_tag(std::forward<T>(tag)); }
+
+protected:
+ 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;
+
+ void ctrl_w(u8 val);
+
+ void intf_w(u8 val);
+
+ void cmd_w(u8 val);
+ u8 stat_r();
+
+ void data_w(u8 val);
+ u8 data_r();
+
+ void set_irq(int state);
+ void set_drq(int state);
+
+private:
+ required_device<fd1797_device> m_fdc;
+ required_device_array<floppy_connector, 4> m_floppies;
+ required_device<heath_intr_socket> m_intr_cntrl;
+
+ bool m_irq_allowed;
+ bool m_drq_allowed;
+ bool m_access_track_sector;
+
+ /// Bits set in cmd_ControlPort_c - DK.CON
+ static constexpr u8 ctrl_EnableIntReq_c = 0;
+ static constexpr u8 ctrl_EnableDrqInt_c = 1;
+ static constexpr u8 ctrl_SetMFMRecording_c = 2;
+ static constexpr u8 ctrl_MotorsOn_c = 3;
+ static constexpr u8 ctrl_Drive_0_c = 4;
+ static constexpr u8 ctrl_Drive_1_c = 5;
+ static constexpr u8 ctrl_Drive_2_c = 6;
+ static constexpr u8 ctrl_Drive_3_c = 7;
+
+ /// Bits to set alternate registers on InterfaceControl_c - DK.INT
+ static constexpr u8 if_SelectSectorTrack_c = 0;
+};
+
+DECLARE_DEVICE_TYPE(H89BUS_Z37, device_h89bus_right_card_interface)
+
+#endif // MAME_BUS_HEATHZENITH_H89_Z37_FDC_H
diff --git a/src/devices/bus/heathzenith/h89/z_89_11.cpp b/src/devices/bus/heathzenith/h89/z_89_11.cpp
new file mode 100644
index 00000000000..32c7b9007f9
--- /dev/null
+++ b/src/devices/bus/heathzenith/h89/z_89_11.cpp
@@ -0,0 +1,324 @@
+// license:BSD-3-Clause
+// copyright-holders:Mark Garlanger
+/***************************************************************************
+
+ Heath/Zenith Z-89-11 Multi-Mode Interface Card
+
+****************************************************************************/
+
+#include "emu.h"
+
+#include "z_89_11.h"
+
+#include "bus/rs232/rs232.h"
+#include "machine/i8255.h"
+#include "machine/ins8250.h"
+#include "machine/scn_pci.h"
+
+namespace {
+
+class z_89_11_device : public device_t, public device_h89bus_right_card_interface
+{
+public:
+
+ z_89_11_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock = XTAL(1'843'200).value());
+
+ virtual void write(u8 select_lines, u8 offset, u8 data) override;
+ virtual u8 read(u8 select_lines, u8 offset) override;
+
+protected:
+
+ 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;
+ virtual ioport_constructor device_input_ports() const override ATTR_COLD;
+
+ void lp_w(offs_t reg, u8 val);
+ u8 lp_r(offs_t reg);
+
+ void aux_w(offs_t reg, u8 val);
+ u8 aux_r(offs_t reg);
+
+ void modem_w(offs_t reg, u8 val);
+ u8 modem_r(offs_t reg);
+
+ void update_intr(u8 level);
+
+ void aux_int(int data);
+
+ required_device<i8255_device> m_lp;
+ required_device<ins8250_device> m_aux;
+ required_device<scn2661c_device> m_modem;
+ required_ioport m_cfg_lp;
+ required_ioport m_cfg_aux;
+ required_ioport m_cfg_modem;
+
+
+ bool m_lp_enabled;
+ bool m_aux_enabled;
+ bool m_modem_enabled;
+
+ u8 m_lp_int_idx;
+ u8 m_aux_int_idx;
+ u8 m_modem_int_idx;
+
+ int m_lp_intr;
+ int m_aux_intr;
+ int m_modem_intr;
+
+};
+
+
+z_89_11_device::z_89_11_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock):
+ device_t(mconfig, H89BUS_Z_89_11, tag, owner, clock),
+ device_h89bus_right_card_interface(mconfig, *this),
+ m_lp(*this, "lp"),
+ m_aux(*this, "aux"),
+ m_modem(*this, "modem"),
+ m_cfg_lp(*this, "CFG_LP"),
+ m_cfg_aux(*this, "CFG_AUX"),
+ m_cfg_modem(*this, "CFG_MODEM"),
+ m_lp_intr(0),
+ m_aux_intr(0),
+ m_modem_intr(0)
+{
+}
+
+u8 z_89_11_device::read(u8 select_lines, u8 offset)
+{
+ if ((select_lines & h89bus_device::H89_SER0) && (m_aux_enabled))
+ {
+ return aux_r(offset);
+ }
+
+ if ((select_lines & h89bus_device::H89_SER1) && (m_modem_enabled))
+ {
+ return modem_r(offset);
+ }
+
+ if ((select_lines & h89bus_device::H89_LP) && (m_lp_enabled))
+ {
+ return lp_r(offset);
+ }
+
+ return 0;
+}
+
+void z_89_11_device::write(u8 select_lines, u8 offset, u8 data)
+{
+ if ((select_lines & h89bus_device::H89_SER0) && (m_aux_enabled))
+ {
+ aux_w(offset, data);
+ return;
+ }
+
+ if ((select_lines & h89bus_device::H89_SER1) && (m_modem_enabled))
+ {
+ modem_w(offset, data);
+ return;
+ }
+
+ if ((select_lines & h89bus_device::H89_LP) && (m_lp_enabled))
+ {
+ lp_w(offset, data);
+ return;
+ }
+}
+
+u8 z_89_11_device::lp_r(offs_t reg)
+{
+ return m_lp->read(reg);
+}
+
+void z_89_11_device::lp_w(offs_t reg, u8 val)
+{
+ m_lp->write(reg, val);
+}
+
+u8 z_89_11_device::aux_r(offs_t reg)
+{
+ return m_aux->ins8250_r(reg);
+}
+
+void z_89_11_device::aux_w(offs_t reg, u8 val)
+{
+ m_aux->ins8250_w(reg, val);
+}
+
+u8 z_89_11_device::modem_r(offs_t reg)
+{
+ return m_modem->read(reg);
+}
+
+void z_89_11_device::modem_w(offs_t reg, u8 val)
+{
+ m_modem->write(reg, val);
+}
+
+void z_89_11_device::update_intr(u8 level)
+{
+ // check for interrupt disabled
+ if (level == 0)
+ {
+ return;
+ }
+
+ // Handle multiple ports set to the same interrupt. If any are set, interrupt should be triggered
+ int data = 0;
+
+ if (m_lp_enabled && (m_lp_int_idx == level))
+ {
+ data |= m_lp_intr;
+ }
+ if (m_aux_enabled && (m_aux_int_idx == level))
+ {
+ data |= m_aux_intr;
+ }
+ if (m_modem_enabled && (m_modem_int_idx == level))
+ {
+ data |= m_modem_intr;
+ }
+
+ switch(level)
+ {
+ case 1:
+ set_slot_int3(data);
+ break;
+ case 2:
+ set_slot_int4(data);
+ break;
+ case 3:
+ set_slot_int5(data);
+ break;
+ }
+}
+
+void z_89_11_device::aux_int(int data)
+{
+ if (!m_aux_enabled)
+ {
+ return;
+ }
+
+ m_aux_intr = data;
+
+ update_intr(m_aux_int_idx);
+}
+
+void z_89_11_device::device_start()
+{
+ save_item(NAME(m_lp_intr));
+ save_item(NAME(m_aux_intr));
+ save_item(NAME(m_modem_intr));
+}
+
+void z_89_11_device::device_reset()
+{
+ ioport_value const cfg_lp(m_cfg_lp->read());
+ ioport_value const cfg_aux(m_cfg_aux->read());
+ ioport_value const cfg_modem(m_cfg_modem->read());
+
+ m_lp_enabled = bool(BIT(cfg_lp, 0));
+ m_aux_enabled = bool(BIT(cfg_aux, 0));
+ m_modem_enabled = bool(BIT(cfg_modem, 0));
+
+ // LP Interrupt level
+ m_lp_int_idx = BIT(cfg_lp, 1, 2);
+
+ // AUX Interrupt level
+ m_aux_int_idx = BIT(cfg_aux, 1, 2);
+
+ // MODEM Interrupt level
+ m_modem_int_idx = BIT(cfg_modem, 1, 2);
+}
+
+void z_89_11_device::device_add_mconfig(machine_config &config)
+{
+ // Parallel 0xD0-0xD7 (320 - 327 octal)
+ I8255(config, m_lp, m_clock);
+
+ // AUX DCE 0xE0-0xE7 (340 - 347 octal)
+ //
+ INS8250(config, m_aux, XTAL(1'843'200));
+ m_aux->out_tx_callback().set("dce2", FUNC(rs232_port_device::write_txd));
+ m_aux->out_dtr_callback().set("dce2", FUNC(rs232_port_device::write_dtr));
+ m_aux->out_rts_callback().set("dce2", FUNC(rs232_port_device::write_rts));
+ m_aux->out_int_callback().set(FUNC(z_89_11_device::aux_int));
+
+ rs232_port_device &dce2(RS232_PORT(config, "dce2", default_rs232_devices, "loopback"));
+ dce2.rxd_handler().set(m_aux, FUNC(ins8250_device::rx_w));
+ dce2.dcd_handler().set(m_aux, FUNC(ins8250_device::dcd_w));
+ dce2.dsr_handler().set(m_aux, FUNC(ins8250_device::dsr_w));
+ dce2.cts_handler().set(m_aux, FUNC(ins8250_device::cts_w));
+ dce2.ri_handler().set(m_aux, FUNC(ins8250_device::ri_w));
+
+ // Modem DTE 0xD7-0xDF (330 - 337 octal)
+ SCN2661C(config, m_modem, XTAL(5'068'800));
+ m_modem->txd_handler().set("dte", FUNC(rs232_port_device::write_txd));
+ m_modem->dtr_handler().set("dte", FUNC(rs232_port_device::write_dtr));
+ m_modem->rts_handler().set("dte", FUNC(rs232_port_device::write_rts));
+
+
+ rs232_port_device &dte(RS232_PORT(config, "dte", default_rs232_devices, "loopback"));
+ dte.rxd_handler().set(m_modem, FUNC(scn2661c_device::rxd_w));
+ dte.dcd_handler().set(m_modem, FUNC(scn2661c_device::dcd_w));
+ dte.dsr_handler().set(m_modem, FUNC(scn2661c_device::dsr_w));
+ dte.cts_handler().set(m_modem, FUNC(scn2661c_device::cts_w));
+}
+
+
+static INPUT_PORTS_START( z_89_11_device )
+
+ // INS8250
+ PORT_START("CFG_LP")
+ PORT_CONFNAME(0x01, 0x01, "LP - DCE (340 octal) Enabled" )
+ PORT_CONFSETTING( 0x00, DEF_STR( No ))
+ PORT_CONFSETTING( 0x01, DEF_STR( Yes ))
+ PORT_CONFNAME(0x06, 0x00, "LP - DCE (340 octal) Interrupt level")
+ PORT_CONFSETTING( 0x00, DEF_STR( None ))
+ PORT_CONFSETTING( 0x02, "3")
+ PORT_CONFSETTING( 0x04, "4")
+ PORT_CONFSETTING( 0x06, "5")
+
+ // 8255 chip
+ PORT_START("CFG_AUX")
+ PORT_CONFNAME(0x01, 0x01, "AUX - DCE (320 octal) Enabled" )
+ PORT_CONFSETTING( 0x00, DEF_STR( No ))
+ PORT_CONFSETTING( 0x01, DEF_STR( Yes ))
+ PORT_CONFNAME(0x06, 0x00, "AUX - DCE (320 octal) Interrupt level")
+ PORT_CONFSETTING( 0x00, DEF_STR( None ))
+ PORT_CONFSETTING( 0x02, "3")
+ PORT_CONFSETTING( 0x04, "4")
+ PORT_CONFSETTING( 0x06, "5")
+
+ // 2661
+ PORT_START("CFG_MODEM")
+ PORT_CONFNAME(0x01, 0x01, "MODEM - DTE (330 octal) Enabled" )
+ PORT_CONFSETTING( 0x00, DEF_STR( No ))
+ PORT_CONFSETTING( 0x01, DEF_STR( Yes ))
+ PORT_CONFNAME(0x06, 0x00, "MODEM - DTE (330 octal) Interrupt level")
+ PORT_CONFSETTING( 0x00, DEF_STR( None ))
+ PORT_CONFSETTING( 0x02, "3")
+ PORT_CONFSETTING( 0x04, "4")
+ PORT_CONFSETTING( 0x06, "5")
+ PORT_CONFNAME(0x08, 0x00, "Interrupt on Rx Ready Enabled")
+ PORT_CONFSETTING( 0x00, DEF_STR( No ))
+ PORT_CONFSETTING( 0x08, DEF_STR( Yes ))
+ PORT_CONFNAME(0x10, 0x00, "Interrupt on Tx Ready Enabled")
+ PORT_CONFSETTING( 0x00, DEF_STR( No ))
+ PORT_CONFSETTING( 0x10, DEF_STR( Yes ))
+ PORT_CONFNAME(0x20, 0x00, "Interrupt on Tx Empty Enabled")
+ PORT_CONFSETTING( 0x00, DEF_STR( No ))
+ PORT_CONFSETTING( 0x20, DEF_STR( Yes ))
+
+INPUT_PORTS_END
+
+
+ioport_constructor z_89_11_device::device_input_ports() const
+{
+ return INPUT_PORTS_NAME(z_89_11_device);
+}
+
+} // anonymous namespace
+
+DEFINE_DEVICE_TYPE_PRIVATE(H89BUS_Z_89_11, device_h89bus_right_card_interface, z_89_11_device, "z_89_11", "Heath/Zenith Z-89-11 Multi-Function I/O Card");
diff --git a/src/devices/bus/heathzenith/h89/z_89_11.h b/src/devices/bus/heathzenith/h89/z_89_11.h
new file mode 100644
index 00000000000..76c6d7b230b
--- /dev/null
+++ b/src/devices/bus/heathzenith/h89/z_89_11.h
@@ -0,0 +1,19 @@
+// license:BSD-3-Clause
+// copyright-holders:Mark Garlanger
+/***************************************************************************
+
+ Heath/Zenith Z-89-1 Multi-Function I/O card
+
+****************************************************************************/
+
+
+#ifndef MAME_BUS_HEATHZENITH_H89_Z_89_11_H
+#define MAME_BUS_HEATHZENITH_H89_Z_89_11_H
+
+#pragma once
+
+#include "h89bus.h"
+
+DECLARE_DEVICE_TYPE(H89BUS_Z_89_11, device_h89bus_right_card_interface)
+
+#endif // MAME_BUS_HEATHZENITH_H89_Z_89_11_H
diff --git a/src/devices/bus/heathzenith/intr_cntrl/intr_cntrl.cpp b/src/devices/bus/heathzenith/intr_cntrl/intr_cntrl.cpp
new file mode 100644
index 00000000000..961d2662bb1
--- /dev/null
+++ b/src/devices/bus/heathzenith/intr_cntrl/intr_cntrl.cpp
@@ -0,0 +1,278 @@
+// license:BSD-3-Clause
+// copyright-holders:Mark Garlanger
+/***************************************************************************
+
+ Heathkit Interrupt controller for H89
+
+****************************************************************************/
+
+#include "emu.h"
+
+#include "intr_cntrl.h"
+
+DEFINE_DEVICE_TYPE(HEATH_INTR_CNTRL, heath_intr_cntrl, "heath_intr_cntrl", "Heath H/Z-89 Interrupt Controller");
+DEFINE_DEVICE_TYPE(HEATH_Z37_INTR_CNTRL, z37_intr_cntrl, "heath_z37_intr_cntrl", "Heath H/Z-89 with Z-37 Interrupt Controller");
+DEFINE_DEVICE_TYPE(HEATH_MMS_INTR_CNTRL, mms_intr_cntrl, "heath_mms_intr_cntrl", "Heath H/Z-89 with MMS Interrupt Controller");
+
+DEFINE_DEVICE_TYPE(HEATH_INTR_SOCKET, heath_intr_socket, "heath_intr_socket", "Heath Interrupt Socket");
+
+/**
+ * Heath interrupt interface
+ */
+device_heath_intr_interface::device_heath_intr_interface(const machine_config &mconfig, device_t &device) :
+ device_interface(device, "heathintrdevice"),
+ m_socket(dynamic_cast<heath_intr_socket *>(device.owner()))
+{
+}
+
+/**
+ * Original Heath interrrupt controller
+ *
+ */
+heath_intr_cntrl::heath_intr_cntrl(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock):
+ heath_intr_cntrl(mconfig, HEATH_INTR_CNTRL, tag, owner, clock)
+{
+}
+
+heath_intr_cntrl::heath_intr_cntrl(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, u32 clock):
+ device_t(mconfig, type, tag, owner, 0),
+ device_heath_intr_interface(mconfig, *this)
+{
+}
+
+void heath_intr_cntrl::device_start()
+{
+ save_item(NAME(m_intr_lines));
+
+ m_intr_lines = 0;
+}
+
+void heath_intr_cntrl::update_intr_line()
+{
+ if (m_socket)
+ {
+ m_socket->raise_irq((m_intr_lines == 0) ? 0 : 1);
+ }
+}
+
+void heath_intr_cntrl::set_irq_level(u8 level, int data)
+{
+ // only 0 to 7 is valid
+ level &= 0x7;
+
+ if (data == 0)
+ {
+ m_intr_lines &= ~(1 << level);
+ }
+ else
+ {
+ m_intr_lines |= 1 << level;
+ }
+
+ update_intr_line();
+}
+
+u8 heath_intr_cntrl::get_instruction()
+{
+
+ // determine top priority instruction
+ if (!m_intr_lines)
+ {
+ // should not occur.
+ // NO-OP ?
+ logerror("get instruct: bad m_intr_lines\n");
+
+ return 0x00;
+ }
+
+ // ideally this would be handled with a function like ffs()
+ u8 level = 0;
+ u8 mask = 0x01;
+
+ while (mask)
+ {
+ if (m_intr_lines & mask)
+ {
+ break;
+ }
+ level++;
+ mask <<= 1;
+ }
+
+ if (level > 7)
+ {
+ logerror("bad level: %d\n", level);
+ }
+
+ // return RST based on level
+ return 0xc7 | ((level & 0x7) << 3);
+}
+
+
+/**
+ * Base interrupt controller for soft-sectored controller.
+ *
+ */
+ss_intr_cntrl::ss_intr_cntrl(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, u32 clock):
+ heath_intr_cntrl(mconfig, type, tag, owner, clock)
+{
+}
+
+void ss_intr_cntrl::set_drq(int state)
+{
+ m_drq_raised = bool(state);
+
+ update_intr_line();
+}
+
+
+void ss_intr_cntrl::set_irq(int state)
+{
+ m_irq_raised = bool(state);
+
+ update_intr_line();
+}
+
+void ss_intr_cntrl::device_start()
+{
+ heath_intr_cntrl::device_start();
+
+ save_item(NAME(m_drq_raised));
+ save_item(NAME(m_irq_raised));
+
+ m_drq_raised = false;
+ m_irq_raised = false;
+}
+
+
+/**
+ * Interrupt controller for the Z37 soft-sectored controller.
+ *
+ * It will take control of the interrupt system and block all other
+ * interrupts while it is waiting for Z37 events.
+ */
+z37_intr_cntrl::z37_intr_cntrl(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock):
+ ss_intr_cntrl(mconfig, HEATH_Z37_INTR_CNTRL, tag, owner, clock)
+{
+}
+
+void z37_intr_cntrl::update_intr_line()
+{
+ m_socket->raise_irq(
+ (m_irq_raised || m_drq_raised ||
+ (!m_intr_blocked && (m_intr_lines != 0))) ? 1 : 0);
+}
+
+u8 z37_intr_cntrl::get_instruction()
+{
+
+ if (m_drq_raised)
+ {
+ // EI
+ return 0xfb;
+ }
+
+ if (m_irq_raised)
+ {
+ // RST 20H (Interrupt 4)
+ return 0xe7;
+ }
+
+ if (!m_intr_blocked)
+ {
+ return heath_intr_cntrl::get_instruction();
+ }
+
+ // shouldn't get here - NO-OP?
+ logerror("Warning: z37 intr get_instruction: fd: %d dr: %d ib: %d\n", m_irq_raised, m_drq_raised, m_intr_blocked);
+ return 0x00;
+}
+
+void z37_intr_cntrl::device_start()
+{
+ ss_intr_cntrl::device_start();
+
+ save_item(NAME(m_intr_blocked));
+
+ m_intr_blocked = false;
+}
+
+void z37_intr_cntrl::block_interrupts(u8 data)
+{
+ m_intr_blocked = bool(data);
+
+ update_intr_line();
+}
+
+
+/**
+ * Interrupt controller for the mms 77316 soft-sectored controller.
+ *
+ */
+mms_intr_cntrl::mms_intr_cntrl(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock):
+ ss_intr_cntrl(mconfig, HEATH_MMS_INTR_CNTRL, tag, owner, clock)
+{
+}
+
+void mms_intr_cntrl::update_intr_line()
+{
+ m_socket->raise_irq((m_irq_raised || m_drq_raised || (m_intr_lines != 0)) ? 1 : 0);
+}
+
+u8 mms_intr_cntrl::get_instruction()
+{
+ if (m_irq_raised)
+ {
+ // RST 30H (Interrupt 6)
+ return 0xf7;
+ }
+
+ if (m_drq_raised)
+ {
+ // EI
+ return 0xfb;
+ }
+
+ return heath_intr_cntrl::get_instruction();
+}
+
+void mms_intr_cntrl::device_start()
+{
+ ss_intr_cntrl::device_start();
+}
+
+
+/**
+ * Heath Interrupt socket
+ *
+ * Allows choice of interrupt controllers for Heath 8-bit computers.
+ */
+heath_intr_socket::heath_intr_socket(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock) :
+ device_t(mconfig, HEATH_INTR_SOCKET, tag, owner, clock),
+ device_single_card_slot_interface(mconfig, *this),
+ m_irq_line(*this),
+ m_cntrl(nullptr)
+{
+}
+
+heath_intr_socket::~heath_intr_socket()
+{
+}
+
+void heath_intr_socket::device_start()
+{
+ m_cntrl = get_card_device();
+}
+
+IRQ_CALLBACK_MEMBER(heath_intr_socket::irq_callback)
+{
+ // assume NO-OP
+ u8 instr = 0x00;
+
+ if (m_cntrl)
+ {
+ instr = m_cntrl->get_instruction();
+ }
+
+ return instr;
+}
diff --git a/src/devices/bus/heathzenith/intr_cntrl/intr_cntrl.h b/src/devices/bus/heathzenith/intr_cntrl/intr_cntrl.h
new file mode 100644
index 00000000000..0eee01945a3
--- /dev/null
+++ b/src/devices/bus/heathzenith/intr_cntrl/intr_cntrl.h
@@ -0,0 +1,168 @@
+// license:BSD-3-Clause
+// copyright-holders:Mark Garlanger
+/***************************************************************************
+
+ Heathkit Interrupt Controllers
+
+ Interrupt controllers for the Heath H89.
+
+****************************************************************************/
+
+#ifndef MAME_BUS_HEATHZENITH_INTR_CNTRL_INTR_CNTRL_H
+#define MAME_BUS_HEATHZENITH_INTR_CNTRL_INTR_CNTRL_H
+
+#pragma once
+
+class heath_intr_socket;
+
+class device_heath_intr_interface : public device_interface
+{
+public:
+ virtual void set_irq_level(u8 level, int state) = 0;
+
+ virtual void set_drq(int state) {}
+ virtual void set_irq(int state) {}
+ virtual void block_interrupts(u8 data) {}
+
+protected:
+ device_heath_intr_interface(const machine_config &mconfig, device_t &device);
+
+ virtual u8 get_instruction() = 0;
+
+ heath_intr_socket *const m_socket;
+
+ friend heath_intr_socket;
+};
+
+
+/**
+ * Heath original interrupt controller
+ *
+ */
+class heath_intr_cntrl : public device_t,
+ public device_heath_intr_interface
+{
+public:
+ heath_intr_cntrl(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock = 0);
+
+ virtual void set_irq_level(u8 level, int state) override;
+
+protected:
+ heath_intr_cntrl(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, u32 clock = 0);
+
+ virtual u8 get_instruction() override;
+ virtual void update_intr_line();
+
+ virtual void device_start() override ATTR_COLD;
+
+ u8 m_intr_lines;
+};
+
+
+/**
+ * Base interrupt controller for multiple soft-sectored controllers.
+ *
+ */
+class ss_intr_cntrl : public heath_intr_cntrl
+{
+public:
+ virtual void set_drq(int state) override;
+ virtual void set_irq(int state) override;
+
+protected:
+ ss_intr_cntrl(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, u32 clock = 0);
+
+ virtual void device_start() override ATTR_COLD;
+
+ bool m_drq_raised;
+ bool m_irq_raised;
+};
+
+
+/**
+ * Interrupt controller when the Z37 soft-sectored controller is installed.
+ *
+ */
+class z37_intr_cntrl : public ss_intr_cntrl
+{
+public:
+ z37_intr_cntrl(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock = 0);
+
+ virtual void block_interrupts(u8 data) override;
+
+protected:
+ virtual u8 get_instruction() override;
+ virtual void update_intr_line() override;
+
+ virtual void device_start() override ATTR_COLD;
+
+ bool m_intr_blocked;
+};
+
+
+/**
+ * Interrupt controller when the mms soft-sectored controller is installed.
+ *
+ */
+class mms_intr_cntrl : public ss_intr_cntrl
+{
+public:
+ mms_intr_cntrl(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock = 0);
+
+protected:
+ virtual u8 get_instruction() override;
+ virtual void update_intr_line() override;
+
+ virtual void device_start() override ATTR_COLD;
+};
+
+
+DECLARE_DEVICE_TYPE(HEATH_INTR_CNTRL, heath_intr_cntrl)
+DECLARE_DEVICE_TYPE(HEATH_Z37_INTR_CNTRL, z37_intr_cntrl)
+DECLARE_DEVICE_TYPE(HEATH_MMS_INTR_CNTRL, mms_intr_cntrl);
+
+
+class heath_intr_socket : public device_t,
+ public device_single_card_slot_interface<device_heath_intr_interface>
+{
+public:
+
+ template <typename T>
+ heath_intr_socket(const machine_config &mconfig, const char *tag, device_t *owner, T &&opts, const char *dflt, bool fixed = false) :
+ heath_intr_socket(mconfig, tag, owner, 0)
+ {
+ option_reset();
+ opts(*this);
+ set_default_option(dflt);
+ set_fixed(fixed);
+ }
+
+ heath_intr_socket(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock = 0);
+ virtual ~heath_intr_socket();
+
+ auto irq_line_cb() { return m_irq_line.bind(); }
+
+ // required operation
+ void set_irq_level(u8 level, int state) { if (m_cntrl) { m_cntrl->set_irq_level(level, state); }}
+
+ IRQ_CALLBACK_MEMBER(irq_callback);
+
+ void raise_irq(int state) { m_irq_line(state); }
+
+ void set_irq(int state) { if (m_cntrl) { m_cntrl->set_irq(state); } }
+ void set_drq(int state) { if (m_cntrl) { m_cntrl->set_drq(state); } }
+ void block_interrupts(u8 data) { if (m_cntrl) { m_cntrl->block_interrupts(data); } }
+
+protected:
+
+ virtual void device_start() override ATTR_COLD;
+
+ devcb_write8 m_irq_line;
+
+ device_heath_intr_interface *m_cntrl;
+};
+
+
+DECLARE_DEVICE_TYPE(HEATH_INTR_SOCKET, heath_intr_socket)
+
+#endif // MAME_BUS_HEATHZENITH_INTR_CNTRL_INTR_CNTRL_H
diff --git a/src/devices/bus/hexbus/hexbus.cpp b/src/devices/bus/hexbus/hexbus.cpp
index 6b6f19b7d98..110739b5fcf 100644
--- a/src/devices/bus/hexbus/hexbus.cpp
+++ b/src/devices/bus/hexbus/hexbus.cpp
@@ -150,27 +150,35 @@
// Devices
#include "hx5102.h"
-#define LOG_WRITE (1U<<1) // Write operation
+#define LOG_LINES (1U << 1) // Line changes
+#define LOG_ENABLED (1U << 2) // Enabled
-#define VERBOSE ( LOG_GENERAL )
+#define VERBOSE (LOG_GENERAL)
#include "logmacro.h"
// Hexbus instance
-DEFINE_DEVICE_TYPE_NS(HEXBUS, bus::hexbus, hexbus_device, "hexbus", "Hexbus connector")
+DEFINE_DEVICE_TYPE(HEXBUS, bus::hexbus::hexbus_device, "hexbus", "Hexbus connector")
+
+namespace bus::hexbus {
+
+device_hexbus_interface::device_hexbus_interface(const machine_config &mconfig, device_t &device) :
+ device_interface(device, "hexbus")
+{
+}
-namespace bus { namespace hexbus {
hexbus_device::hexbus_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) :
device_t(mconfig, HEXBUS, tag, owner, clock),
- device_slot_interface(mconfig, *this),
- m_next_dev(nullptr)
+ device_single_card_slot_interface<device_hexbus_interface>(mconfig, *this),
+ m_next_dev(nullptr),
+ m_chain_element(nullptr)
{
}
void hexbus_device::device_start()
{
- m_next_dev = dynamic_cast<device_hexbus_interface *>(get_card_device());
+ m_next_dev = get_card_device();
}
/*
@@ -215,18 +223,21 @@ uint8_t hexbus_device::read(int dir)
hexbus_chained_device::hexbus_chained_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_hexbus_interface(mconfig, *this)
+ device_hexbus_interface(mconfig, *this),
+ m_hexbus_outbound(nullptr),
+ m_enabled(false),
+ m_myvalue(0xff)
{
m_hexbus_inbound = dynamic_cast<hexbus_device *>(owner);
- m_myvalue = 0xff;
}
-void hexbus_chained_device::device_start()
+void hexbus_chained_device::device_resolve_objects()
{
- m_hexbus_outbound = static_cast<hexbus_device*>(subdevice("hexbus"));
+ m_hexbus_outbound = dynamic_cast<hexbus_device *>(subdevice("hexbus"));
// Establish callback for inbound propagations
- m_hexbus_outbound->set_chain_element(this);
+ if (m_hexbus_outbound != nullptr)
+ m_hexbus_outbound->set_chain_element(this);
}
/*
@@ -235,21 +246,31 @@ void hexbus_chained_device::device_start()
*/
void hexbus_chained_device::hexbus_write(uint8_t data)
{
+ uint8_t oldvalue = m_myvalue;
m_myvalue = data;
+ set_communication_enabled(true);
uint8_t otherval = hexbus_get_levels();
- // LOGMASKED(LOG_WRITE, ".. otherval=%02x\n", otherval);
-
// What is the new bus level?
// The data lines are not supposed to be set by multiple devices
// We assume that sending data overrides all data line levels.
// This is emulated by pulling the data lines to ones.
uint8_t newvalue = (otherval | 0xc3) & m_myvalue;
+ if (hsk_line(oldvalue)==ASSERT_LINE && own_hsk_level()==CLEAR_LINE)
+ LOGMASKED(LOG_LINES, "Release HSK*\n");
+
+ bool hsk_changed = (hsk_line(newvalue) != hsk_line(m_current_bus_value));
+ bool bav_changed = (bav_line(newvalue) != bav_line(m_current_bus_value));
+
// If it changed (with respect to HSK* or BAV*), propagate to both directions.
- if ((newvalue & (HEXBUS_LINE_HSK | HEXBUS_LINE_BAV)) != (m_current_bus_value & (HEXBUS_LINE_HSK | HEXBUS_LINE_BAV)))
+ if (hsk_changed || bav_changed)
{
- LOGMASKED(LOG_WRITE, "Trying to write %02x, actually: %02x (current=%02x)\n", data, newvalue, m_current_bus_value);
+ if (hsk_changed && own_hsk_level()==ASSERT_LINE)
+ LOGMASKED(LOG_LINES, "Pull down HSK*, send data=%x\n", data_lines(m_myvalue));
+
+ if (bav_changed)
+ LOGMASKED(LOG_LINES, "%s BAV*\n", (own_bav_level()==ASSERT_LINE)? "Pull down" : "Release");
m_current_bus_value = newvalue;
@@ -258,9 +279,38 @@ void hexbus_chained_device::hexbus_write(uint8_t data)
if (m_hexbus_outbound != nullptr)
m_hexbus_outbound->write(OUTBOUND, m_current_bus_value);
-
}
- else LOGMASKED(LOG_WRITE, "No change on hexbus\n");
+}
+
+/*
+ Assert or release the HSK* line.
+*/
+void hexbus_chained_device::set_hsk_line(line_state level)
+{
+ if (level==ASSERT_LINE)
+ hexbus_write(m_myvalue & ~HEXBUS_LINE_HSK);
+ else
+ hexbus_write(m_myvalue | HEXBUS_LINE_HSK);
+}
+
+/*
+ Assert or release the BAV* line.
+*/
+void hexbus_chained_device::set_bav_line(line_state level)
+{
+ if (level==ASSERT_LINE)
+ hexbus_write(m_myvalue & ~HEXBUS_LINE_BAV);
+ else
+ hexbus_write(m_myvalue | HEXBUS_LINE_BAV);
+}
+
+void hexbus_chained_device::set_data_latch(int value, int pos)
+{
+ const uint8_t hexbval[4] = { 0x01, 0x02, 0x40, 0x80 };
+ if (value==0)
+ m_myvalue &= ~hexbval[pos];
+ else
+ m_myvalue |= hexbval[pos];
}
/*
@@ -318,17 +368,45 @@ void hexbus_chained_device::bus_write(int dir, uint8_t data)
uint8_t oldvalue = m_current_bus_value;
m_current_bus_value = data;
+ // When disabled, just propagate, and then return
+ if (!m_enabled) return;
+
+ bool hsk_changed = (hsk_line(data) != hsk_line(oldvalue));
+
// Notify device
// Caution: Calling hexbus_value_changed may cause further activities that change the bus again
// Data changes alone shall not trigger the callback
- if ((data & (HEXBUS_LINE_HSK | HEXBUS_LINE_BAV)) != (oldvalue & (HEXBUS_LINE_HSK | HEXBUS_LINE_BAV)))
+ if (hsk_changed || (bav_line(data) != bav_line(oldvalue)))
{
- LOGMASKED(LOG_WRITE, "Hexbus value changed: %02x -> %02x\n", oldvalue, data);
+ if (hsk_changed)
+ {
+ if (hsk_line(data)==ASSERT_LINE) LOGMASKED(LOG_LINES, "Sense HSK*=0, got data=%x\n", data_lines(data));
+ else
+ {
+ LOGMASKED(LOG_LINES, "Sense HSK*=1\n");
+ // According to [1], HSK* going high writes ones into the data latch
+ m_myvalue |= 0xc3;
+ }
+ }
+ else LOGMASKED(LOG_LINES, "Sense BAV*=%d\n", bav_line(data)==CLEAR_LINE? 1:0);
+
hexbus_value_changed(data);
}
}
/*
+ Enable or disable this component.
+*/
+void hexbus_chained_device::set_communication_enabled(bool set)
+{
+ if (m_enabled != set)
+ LOGMASKED(LOG_ENABLED, "Hexbus listen %s\n", set? "enabled" : "disabled");
+ m_enabled = set;
+
+ if (!m_enabled) m_myvalue = 0xff;
+}
+
+/*
Convenience function to calculate the bus value. Used by subclasses.
*/
uint8_t hexbus_chained_device::to_line_state(uint8_t data, bool bav, bool hsk)
@@ -339,9 +417,18 @@ uint8_t hexbus_chained_device::to_line_state(uint8_t data, bool bav, bool hsk)
return lines;
}
+/*
+ Convenience function to get a data bit.
+*/
+int hexbus_chained_device::data_bit(int n)
+{
+ const uint8_t testbit[4] = { 0x01, 0x02, 0x40, 0x80 };
+ return (m_current_bus_value & testbit[n&3])? 1:0;
+}
+
// ------------------------------------------------------------------------
-} } // end namespace bus::hexbus
+} // end namespace bus::hexbus
void hexbus_options(device_slot_interface &device)
{
diff --git a/src/devices/bus/hexbus/hexbus.h b/src/devices/bus/hexbus/hexbus.h
index ca961a39d17..3260ed9ae16 100644
--- a/src/devices/bus/hexbus/hexbus.h
+++ b/src/devices/bus/hexbus/hexbus.h
@@ -15,7 +15,7 @@
#pragma once
-namespace bus { namespace hexbus {
+namespace bus::hexbus {
enum
{
@@ -27,9 +27,7 @@ enum
enum
{
HEXBUS_LINE_HSK = 0x10,
- HEXBUS_LINE_BAV = 0x04,
- HEXBUS_LINE_BIT32 = 0xc0,
- HEXBUS_LINE_BIT10 = 0x03
+ HEXBUS_LINE_BAV = 0x04
};
class hexbus_device;
@@ -39,15 +37,14 @@ class hexbus_chained_device;
Interface for a device that connects to the Hexbus
********************************************************************/
-class device_hexbus_interface : public device_slot_card_interface
+class device_hexbus_interface : public device_interface
{
public:
- virtual uint8_t bus_read(int dir) =0;
- virtual void bus_write(int dir, uint8_t data) =0;
+ virtual uint8_t bus_read(int dir) = 0;
+ virtual void bus_write(int dir, uint8_t data) = 0;
protected:
- device_hexbus_interface(const machine_config &mconfig, device_t &device) :
- device_slot_card_interface(mconfig, device) { }
+ device_hexbus_interface(const machine_config &mconfig, device_t &device);
};
/********************************************************************
@@ -58,13 +55,13 @@ class hexbus_chained_device : public device_t, public device_hexbus_interface
{
friend class hexbus_device;
-public:
+protected:
hexbus_chained_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock);
- virtual void device_start() override;
-protected:
void set_outbound_hexbus(hexbus_device *outbound) { m_hexbus_outbound = outbound; }
+ virtual void device_resolve_objects() override ATTR_COLD;
+
// Link to the inbound Hexbus (if not null, see Oso chip)
hexbus_device *m_hexbus_inbound;
@@ -90,13 +87,49 @@ protected:
uint8_t hexbus_read();
// Callback for changes on the hexbus
- virtual void hexbus_value_changed(uint8_t data) { };
+ virtual void hexbus_value_changed(uint8_t data) { }
+
+ // Enable or disable the Hexbus component
+ bool m_enabled;
+ void set_communication_enabled(bool set);
// Levels of the lines at this device. 0 means pull down, 1 means release.
uint8_t m_myvalue;
- // Utility method to create a Hexbus line state
- uint8_t to_line_state(uint8_t data, bool bav, bool hsk);
+ // Set or release the HSK* and BAV* lines
+ void set_hsk_line(line_state level);
+ void set_bav_line(line_state level);
+
+ // Set the data latch for upcoming transmission
+ void set_data_latch(int value, int pos);
+
+ // Convenience method to create a Hexbus line state
+ static uint8_t to_line_state(uint8_t data, bool bav, bool hsk);
+
+ // Latch HSK*=0
+ void latch_hsk() { m_myvalue &= ~HEXBUS_LINE_HSK; }
+
+ // Convenience function to check HSK/BAV lines on given values
+ static line_state hsk_line(uint8_t lines) { return (lines & HEXBUS_LINE_HSK)? CLEAR_LINE : ASSERT_LINE; }
+ static line_state bav_line(uint8_t lines) { return (lines & HEXBUS_LINE_BAV)? CLEAR_LINE : ASSERT_LINE; }
+
+ // Return the HSK* level on the bus
+ line_state bus_hsk_level() { return hsk_line(m_current_bus_value); }
+
+ // Return the BAV* level on the bus
+ line_state bus_bav_level() { return bav_line(m_current_bus_value); }
+
+ // Return the HSK* level from this device
+ line_state own_hsk_level() { return hsk_line(m_myvalue); }
+
+ // Return the BAV* level from this device
+ line_state own_bav_level() { return bav_line(m_myvalue); }
+
+ // Data lines
+ static int data_lines(uint8_t lines) { return (((lines & 0xc0) >> 4) | (lines & 0x03)); }
+
+ // Return the selected data bit (0-3)
+ int data_bit(int n);
};
// ------------------------------------------------------------------------
@@ -105,7 +138,7 @@ protected:
Connector to the Hexbus, offers a slot for Hexbus-chained devices
********************************************************************/
-class hexbus_device : public device_t, public device_slot_interface
+class hexbus_device : public device_t, public device_single_card_slot_interface<device_hexbus_interface>
{
public:
template <typename U>
@@ -128,7 +161,7 @@ public:
void write(int dir, uint8_t data);
protected:
- void device_start() override;
+ virtual void device_start() override ATTR_COLD;
device_hexbus_interface *m_next_dev;
private:
@@ -138,7 +171,7 @@ private:
hexbus_chained_device* m_chain_element;
};
-} } // end namespace bus::hexbus
+} // end namespace bus::hexbus
DECLARE_DEVICE_TYPE_NS(HEXBUS, bus::hexbus, hexbus_device)
diff --git a/src/devices/bus/hexbus/hx5102.cpp b/src/devices/bus/hexbus/hx5102.cpp
index 0cfd70c7dac..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,12 +105,15 @@
#define ROM1_TAG "u25_rom"
#define ROM2_TAG "u29_rom"
+#define FLOP0 "d0"
+#define FLOP1 "d1"
+
#define MOTOR_TIMER 1
#define UNDEF -1
-DEFINE_DEVICE_TYPE_NS(HX5102, bus::hexbus, hx5102_device, "ti_hx5102", "TI Hexbus Floppy Drive")
+DEFINE_DEVICE_TYPE(HX5102, bus::hexbus::hx5102_device, "ti_hx5102", "TI Hexbus Floppy Drive")
-namespace bus { namespace hexbus {
+namespace bus::hexbus {
void hx5102_device::memmap(address_map &map)
{
@@ -121,7 +125,9 @@ void hx5102_device::memmap(address_map &map)
*/
void hx5102_device::crumap(address_map &map)
{
- map(0x17e0, 0x17ff).rw(FUNC(hx5102_device::cruread), FUNC(hx5102_device::cruwrite));
+ map(0x17e0, 0x17ff).r(FUNC(hx5102_device::cruread));
+ map(0x17e0, 0x17ef).w(m_crulatch[0], FUNC(ls259_device::write_d0));
+ map(0x17f0, 0x17ff).w(m_crulatch[1], FUNC(ls259_device::write_d0));
}
hx5102_device::hx5102_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock):
@@ -131,15 +137,19 @@ 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),
m_hexbus_ctrl(*this, IBC_TAG),
m_floppy_ctrl(*this, FDC_TAG),
+ m_crulatch(*this, "crulatch%u", 0U),
m_motormf(*this, MTRD_TAG),
m_speedmf(*this, MTSPD_TAG),
m_readyff(*this, READYFF_TAG),
@@ -148,7 +158,7 @@ hx5102_device::hx5102_device(const machine_config &mconfig, const char *tag, dev
{
}
-WRITE8_MEMBER( hx5102_device::external_operation )
+void hx5102_device::external_operation(offs_t offset, uint8_t data)
{
static char const *const extop[8] = { "inv1", "inv2", "IDLE", "RSET", "inv3", "CKON", "CKOF", "LREX" };
if (offset != IDLE_OP) LOGMASKED(LOG_WARN, "External operation %s not implemented on HX5102 board\n", extop[offset]);
@@ -182,7 +192,7 @@ WRITE8_MEMBER( hx5102_device::external_operation )
/*
Reading from the address space of the drive.
*/
-READ8_MEMBER( hx5102_device::read )
+uint8_t hx5102_device::read(offs_t offset)
{
bool ramen1 = ((offset & 0xf800)==0xe000);
bool ramen2 = ((offset & 0xf800)==0xe800);
@@ -220,11 +230,11 @@ READ8_MEMBER( hx5102_device::read )
// Floppy drive controller
if (m_dcs)
- return fdc_read(space, offset&0x000f);
+ return fdc_read(offset&0x000f);
// Hexbus controller
if (hcs)
- return ibc_read(space, offset&0x000f);
+ return ibc_read(offset&0x000f);
// DMA
if (m_dack)
@@ -243,7 +253,7 @@ READ8_MEMBER( hx5102_device::read )
/*
Writing into the address space of the drive.
*/
-WRITE8_MEMBER( hx5102_device::write )
+void hx5102_device::write(offs_t offset, uint8_t data)
{
bool ramen1 = ((offset & 0xf800)==0xe000);
bool ramen2 = ((offset & 0xf800)==0xe800);
@@ -270,14 +280,14 @@ WRITE8_MEMBER( hx5102_device::write )
// Floppy drive controller
if (m_dcs)
{
- fdc_write(space, offset&0x000f, data);
+ fdc_write(offset&0x000f, data);
return;
}
// Hexbus controller
if (hcs)
{
- ibc_write(space, offset&0x000f, data);
+ ibc_write(offset&0x000f, data);
return;
}
@@ -296,7 +306,7 @@ WRITE8_MEMBER( hx5102_device::write )
/*
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);
}
@@ -313,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)
{
@@ -327,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);
@@ -342,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");
@@ -356,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");
@@ -366,7 +376,7 @@ WRITE_LINE_MEMBER( hx5102_device::mspeed_w )
/*
Read access to the floppy controller
*/
-READ8_MEMBER(hx5102_device::fdc_read)
+uint8_t hx5102_device::fdc_read(offs_t offset)
{
uint8_t val = 0;
switch (offset)
@@ -388,7 +398,7 @@ READ8_MEMBER(hx5102_device::fdc_read)
/*
Write access to the floppy controller
*/
-WRITE8_MEMBER(hx5102_device::fdc_write)
+void hx5102_device::fdc_write(offs_t offset, uint8_t data)
{
m_dcs = ((offset & 0x0003)==0);
@@ -416,23 +426,23 @@ void hx5102_device::update_readyff_input()
/*
Access to the Hexbus controller
*/
-READ8_MEMBER(hx5102_device::ibc_read)
+uint8_t hx5102_device::ibc_read(offs_t offset)
{
if ((offset & 1)==0)
- return m_hexbus_ctrl->read(space, (offset>>1)&1);
+ return m_hexbus_ctrl->read((offset>>1)&1);
else
return 0;
}
-WRITE8_MEMBER(hx5102_device::ibc_write)
+void hx5102_device::ibc_write(offs_t offset, uint8_t data)
{
if ((offset & 1)==0)
- m_hexbus_ctrl->write(space, (offset>>1)&1, data);
+ m_hexbus_ctrl->write((offset>>1)&1, data);
}
-WRITE8_MEMBER(hx5102_device::hexbus_out)
+void hx5102_device::hexbus_out(uint8_t data)
{
- LOGMASKED(LOG_HEXBUS, "hexbus out: %02x\n", data);
+ LOGMASKED(LOG_HEXBUS, "Write to hexbus: BAV*=%d, HSK*=%d, data=%x\n", bav_line(data)==ASSERT_LINE? 0:1, hsk_line(data)==ASSERT_LINE? 0:1, data_lines(data));
// Get the other levels and set our own states
uint8_t newlevel = hexbus_get_levels() & data;
@@ -445,7 +455,7 @@ WRITE8_MEMBER(hx5102_device::hexbus_out)
/*
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;
@@ -464,7 +474,7 @@ WRITE_LINE_MEMBER(hx5102_device::hsklatch_out)
MON = Motor on
INT = Interrupt from i8272A
*/
-READ8_MEMBER(hx5102_device::cruread)
+uint8_t hx5102_device::cruread(offs_t offset)
{
uint8_t crubits = 0;
// LOGMASKED(LOG_CRU, "Reading CRU addresses %04x-%04x\n", 0x17e0 + (offset<<4), 0x17ee + (offset<<4));
@@ -480,92 +490,81 @@ READ8_MEMBER(hx5102_device::cruread)
/*
CRU write access.
*/
-WRITE8_MEMBER(hx5102_device::cruwrite)
+void hx5102_device::nocomp_w(int state)
{
- // LOG("Writing CRU address %04x: %x\n", 0x17e0 + (offset<<1), data);
- switch (offset)
- {
- case 0:
- // unused right now
- LOGMASKED(LOG_CRU, "Set precompensation = %d\n", data);
- break;
- case 1:
- if (data==1)
- {
- LOGMASKED(LOG_CRU, "Trigger motor monoflop\n");
- }
- m_motormf->b_w(data);
- break;
- case 2:
- LOGMASKED(LOG_CRU, "Set undefined CRU bit 2 to %d\n", data);
- break;
- case 3:
- LOGMASKED(LOG_CRU, "Set step direction = %d\n", data);
- if (m_current_floppy != nullptr) m_current_floppy->dir_w((data==0)? 1 : 0);
- break;
- case 4:
- if (data==1)
- {
- LOGMASKED(LOG_CRU, "Assert DACK*\n");
- m_dacken = (data != 0);
- }
- break;
- case 5:
- if (data==1)
- {
- LOGMASKED(LOG_CRU, "Step pulse\n");
- }
- if (m_current_floppy != nullptr) m_current_floppy->stp_w((data==0)? 1 : 0);
- break;
- case 6:
- if (data==1)
- {
- LOGMASKED(LOG_CRU, "Start watchdog\n");
- }
- m_speedmf->b_w(data);
- break;
- case 7:
- if (data==0)
- {
- LOGMASKED(LOG_CRU, "Reset i8272A controller\n");
- m_floppy_ctrl->soft_reset();
- }
- break;
- case 8:
- LOGMASKED(LOG_CRU, "Set drive select 0 to %d\n", data);
- if (data == 1) m_floppy_select |= 1;
- else m_floppy_select &= ~1;
- break;
- case 9:
- LOGMASKED(LOG_CRU, "Set drive select 1 to %d\n", data);
- if (data == 1) m_floppy_select |= 2;
- else m_floppy_select &= ~2;
- break;
- case 10:
- // External drive; not implemented
- LOGMASKED(LOG_CRU, "Set drive select 2 to %d\n", data);
- break;
- case 11:
- // External drive; not implemented
- LOGMASKED(LOG_CRU, "Set drive select 3 to %d\n", data);
- break;
- case 12:
- // External drive; not implemented
- LOGMASKED(LOG_CRU, "Set auxiliary motor line to %d\n", data);
- break;
- case 13:
- LOGMASKED(LOG_CRU, "Set CRU bit 13 to %d (unused)\n", data);
- break;
- case 14:
- m_wait = (data!=0);
- LOGMASKED(LOG_CRU, "READY circuit %s\n", m_wait? "active" : "inactive" );
- update_readyff_input();
- break;
- case 15:
- LOGMASKED(LOG_CRU, "Set CRU bit 15 to %d (unused)\n", data);
- break;
- }
+ // unused right now
+ LOGMASKED(LOG_CRU, "Set precompensation = %d\n", state);
+}
+
+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);
+}
+void hx5102_device::dacken_w(int state)
+{
+ if (state==1)
+ LOGMASKED(LOG_CRU, "Assert DACK*\n");
+ m_dacken = (state != 0);
+}
+
+void hx5102_device::stepen_w(int state)
+{
+ if (state==1)
+ LOGMASKED(LOG_CRU, "Step pulse\n");
+ if (m_current_floppy != nullptr)
+ m_current_floppy->stp_w((state==0)? 1 : 0);
+}
+
+void hx5102_device::ds1_w(int state)
+{
+ LOGMASKED(LOG_CRU, "Set drive select 0 to %d\n", state);
+ if (state == 1)
+ m_floppy_select |= 1;
+ else
+ m_floppy_select &= ~1;
+ update_drive_select();
+}
+
+void hx5102_device::ds2_w(int state)
+{
+ LOGMASKED(LOG_CRU, "Set drive select 1 to %d\n", state);
+ if (state == 1)
+ m_floppy_select |= 2;
+ else
+ m_floppy_select &= ~2;
+ update_drive_select();
+}
+
+void hx5102_device::ds3_w(int state)
+{
+ // External drive; not implemented
+ LOGMASKED(LOG_CRU, "Set drive select 2 to %d\n", state);
+}
+
+void hx5102_device::ds4_w(int state)
+{
+ // External drive; not implemented
+ LOGMASKED(LOG_CRU, "Set drive select 3 to %d\n", state);
+}
+
+void hx5102_device::aux_motor_w(int state)
+{
+ // External drive; not implemented
+ LOGMASKED(LOG_CRU, "Set auxiliary motor line to %d\n", state);
+}
+
+void hx5102_device::wait_w(int state)
+{
+ m_wait = (state!=0);
+ LOGMASKED(LOG_CRU, "READY circuit %s\n", m_wait? "active" : "inactive" );
+ update_readyff_input();
+}
+
+void hx5102_device::update_drive_select()
+{
if (m_floppy_select != m_floppy_select_last)
{
if (m_floppy_select == 1)
@@ -588,13 +587,21 @@ WRITE8_MEMBER(hx5102_device::cruwrite)
*/
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");
}
/*
@@ -610,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);
@@ -622,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);
@@ -633,10 +640,12 @@ WRITE_LINE_MEMBER( hx5102_device::fdc_drq_w )
/*
Define the floppy formats.
*/
-FLOPPY_FORMATS_MEMBER(hx5102_device::floppy_formats)
- FLOPPY_TI99_SDF_FORMAT,
- FLOPPY_TI99_TDF_FORMAT
-FLOPPY_FORMATS_END
+void hx5102_device::floppy_formats(format_registration &fr)
+{
+ fr.add_mfm_containers();
+ fr.add(FLOPPY_TI99_SDF_FORMAT);
+ fr.add(FLOPPY_TI99_TDF_FORMAT);
+}
/*
Only one fixed floppy drive in the device.
@@ -677,7 +686,7 @@ void hx5102_device::device_add_mconfig(machine_config& config)
HEXBUS(config, "hexbus", 0, hexbus_options, nullptr);
// TMS9995 CPU @ 12.0 MHz
- TMS9995(config, m_flopcpu, XTAL(12'000'000));
+ TMS9995(config, m_flopcpu, 12_MHz_XTAL);
m_flopcpu->set_addrmap(AS_PROGRAM, &hx5102_device::memmap);
m_flopcpu->set_addrmap(AS_IO, &hx5102_device::crumap);
m_flopcpu->extop_cb().set(FUNC(hx5102_device::external_operation));
@@ -687,27 +696,41 @@ void hx5102_device::device_add_mconfig(machine_config& config)
// Not connected: Select lines (DS0, DS1), Head load (HDL), VCO
// Tied to 1: READY
// Tied to 0: TC
- I8272A(config, m_floppy_ctrl, 8'000'000, false);
+ I8272A(config, m_floppy_ctrl, 8_MHz_XTAL / 2, false);
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
+ m_crulatch[0]->q_out_cb<0>().set(FUNC(hx5102_device::nocomp_w));
+ m_crulatch[0]->q_out_cb<1>().set(m_motormf, FUNC(ttl74123_device::b_w));
+ m_crulatch[0]->q_out_cb<3>().set(FUNC(hx5102_device::diren_w));
+ m_crulatch[0]->q_out_cb<4>().set(FUNC(hx5102_device::dacken_w));
+ m_crulatch[0]->q_out_cb<5>().set(FUNC(hx5102_device::stepen_w));
+ m_crulatch[0]->q_out_cb<6>().set(m_speedmf, FUNC(ttl74123_device::b_w));
+ m_crulatch[0]->q_out_cb<7>().set(m_floppy_ctrl, FUNC(i8272a_device::reset_w)).invert();
+
+ LS259(config, m_crulatch[1]); // U10
+ m_crulatch[1]->q_out_cb<0>().set(FUNC(hx5102_device::ds1_w));
+ m_crulatch[1]->q_out_cb<1>().set(FUNC(hx5102_device::ds2_w));
+ m_crulatch[1]->q_out_cb<2>().set(FUNC(hx5102_device::ds3_w));
+ m_crulatch[1]->q_out_cb<3>().set(FUNC(hx5102_device::ds4_w));
+ m_crulatch[1]->q_out_cb<4>().set(FUNC(hx5102_device::aux_motor_w));
+ m_crulatch[1]->q_out_cb<6>().set(FUNC(hx5102_device::wait_w));
// Monoflops
- TTL74123(config, m_motormf, 0);
+ TTL74123(config, m_motormf, RES_K(200), CAP_U(47));
m_motormf->set_connection_type(TTL74123_GROUNDED);
- m_motormf->set_resistor_value(RES_K(200));
- m_motormf->set_capacitor_value(CAP_U(47));
m_motormf->set_a_pin_value(0);
m_motormf->set_b_pin_value(1);
m_motormf->set_clear_pin_value(1);
m_motormf->out_cb().set(FUNC(hx5102_device::motor_w));
- TTL74123(config, m_speedmf, 0);
+ TTL74123(config, m_speedmf, RES_K(200), CAP_U(10));
m_speedmf->set_connection_type(TTL74123_GROUNDED);
- m_speedmf->set_resistor_value(RES_K(200));
- m_speedmf->set_capacitor_value(CAP_U(10));
m_speedmf->set_a_pin_value(0);
m_speedmf->set_b_pin_value(1);
m_speedmf->set_clear_pin_value(1);
@@ -738,5 +761,5 @@ ioport_constructor hx5102_device::device_input_ports() const
return INPUT_PORTS_NAME( hx5102 );
}
-} } // end namespace bus::hexbus
+} // end namespace bus::hexbus
diff --git a/src/devices/bus/hexbus/hx5102.h b/src/devices/bus/hexbus/hx5102.h
index 73dea3bf2f1..3cafdff9940 100644
--- a/src/devices/bus/hexbus/hx5102.h
+++ b/src/devices/bus/hexbus/hx5102.h
@@ -22,12 +22,13 @@
#include "machine/upd765.h"
#include "machine/7474.h"
#include "machine/74123.h"
+#include "machine/74259.h"
#include "machine/rescap.h"
#include "machine/ram.h"
#include "imagedev/floppy.h"
#include "tp0370.h"
-namespace bus { namespace hexbus {
+namespace bus::hexbus {
class hx5102_device : public hexbus_chained_device
{
@@ -35,43 +36,53 @@ public:
hx5102_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;
- virtual void device_add_mconfig(machine_config &config) override;
- ioport_constructor device_input_ports() const override;
-
- void crumap(address_map &map);
- void memmap(address_map &map);
- DECLARE_WRITE8_MEMBER(external_operation);
- DECLARE_WRITE_LINE_MEMBER( clock_out );
- DECLARE_WRITE_LINE_MEMBER( board_ready );
- DECLARE_WRITE_LINE_MEMBER( board_reset );
- DECLARE_FLOPPY_FORMATS( floppy_formats );
-
- void device_start() override;
- void device_reset() override;
+ virtual const tiny_rom_entry *device_rom_region() const override ATTR_COLD;
+ virtual void device_add_mconfig(machine_config &config) override ATTR_COLD;
+ virtual ioport_constructor device_input_ports() const override ATTR_COLD;
+
+ void crumap(address_map &map) ATTR_COLD;
+ void memmap(address_map &map) ATTR_COLD;
+ void external_operation(offs_t offset, uint8_t data);
+ void clock_out(int state);
+ void board_ready(int state);
+ void board_reset(int state);
+ static void floppy_formats(format_registration &fr);
+
+ virtual void device_start() override ATTR_COLD;
+ virtual void device_reset() override ATTR_COLD;
virtual void hexbus_value_changed(uint8_t data) override;
private:
required_device<tms9995_device> m_flopcpu;
line_state m_ready_old;
- DECLARE_READ8_MEMBER(read);
- DECLARE_WRITE8_MEMBER(write);
-
- 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);
-
- DECLARE_READ8_MEMBER(fdc_read);
- DECLARE_WRITE8_MEMBER(fdc_write);
- DECLARE_READ8_MEMBER(ibc_read);
- DECLARE_WRITE8_MEMBER(ibc_write);
- DECLARE_WRITE8_MEMBER(hexbus_out);
- DECLARE_WRITE_LINE_MEMBER(hsklatch_out);
-
- DECLARE_READ8_MEMBER(cruread);
- DECLARE_WRITE8_MEMBER(cruwrite);
+ uint8_t read(offs_t offset);
+ void write(offs_t offset, uint8_t data);
+
+ 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);
+ void hsklatch_out(int state);
+
+ uint8_t cruread(offs_t offset);
+ 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
bool m_motor_on;
@@ -90,12 +101,15 @@ 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;
required_device<ibc_device> m_hexbus_ctrl;
required_device<i8272a_device> m_floppy_ctrl;
+ required_device_array<ls259_device, 2> m_crulatch;
required_device<ttl74123_device> m_motormf;
required_device<ttl74123_device> m_speedmf;
required_device<ttl7474_device> m_readyff;
@@ -109,7 +123,7 @@ private:
uint8_t* m_rom2;
};
-} } // end namespace bus::hexbus
+} // end namespace bus::hexbus
DECLARE_DEVICE_TYPE_NS(HX5102, bus::hexbus, hx5102_device)
diff --git a/src/devices/bus/hexbus/tp0370.cpp b/src/devices/bus/hexbus/tp0370.cpp
index 5c620a47bd3..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
{
@@ -128,9 +128,9 @@ enum
#include "logmacro.h"
// Hexbus instance
-DEFINE_DEVICE_TYPE_NS(IBC, bus::hexbus, ibc_device, "ibc", "Intelligent Peripheral Bus Controller")
+DEFINE_DEVICE_TYPE(IBC, bus::hexbus::ibc_device, "hexbus_ibc", "Intelligent Peripheral Bus Controller")
-namespace bus { namespace hexbus {
+namespace bus::hexbus {
ibc_device::ibc_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) :
device_t(mconfig, IBC, tag, owner, clock),
@@ -153,7 +153,7 @@ ibc_device::ibc_device(const machine_config &mconfig, const char *tag, device_t
/*
Reading from host
*/
-READ8_MEMBER( ibc_device::read )
+uint8_t ibc_device::read(offs_t offset)
{
uint8_t status = 0;
switch (offset)
@@ -177,7 +177,11 @@ READ8_MEMBER( ibc_device::read )
if (m_bav) status |= 0x20;
if (m_hsk) status |= 0x10;
- LOGMASKED(LOG_STATUS, "Status -> %02x\n", status);
+ if (status != m_last_status)
+ {
+ LOGMASKED(LOG_STATUS, "Status -> %02x\n", status);
+ m_last_status = status;
+ }
// Reset flag
m_message_started = false;
@@ -193,7 +197,7 @@ READ8_MEMBER( ibc_device::read )
/*
Writing from host
*/
-WRITE8_MEMBER( ibc_device::write )
+void ibc_device::write(offs_t offset, uint8_t data)
{
switch (offset)
{
@@ -246,7 +250,7 @@ void ibc_device::set_lines(bool bav, bool hsk)
uint8_t val = (m_transmit & 0xc0)|((m_transmit & 0x30)>>4);
if (!bav) val |= 0x04;
if (!hsk) val |= 0x10;
- if (m_transmit != 0xff) LOGMASKED(LOG_LINES, "Data = %01x\n", m_transmit>>4);
+ if (hsk) LOGMASKED(LOG_LINES, "Data = %01x\n", m_transmit>>4);
m_hexout(val);
}
@@ -343,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()
@@ -354,5 +355,5 @@ void ibc_device::device_reset()
m_disable = true;
}
-} }
+} // namespace bus::hexbus
diff --git a/src/devices/bus/hexbus/tp0370.h b/src/devices/bus/hexbus/tp0370.h
index 385059c7fa3..8a45efde193 100644
--- a/src/devices/bus/hexbus/tp0370.h
+++ b/src/devices/bus/hexbus/tp0370.h
@@ -16,17 +16,17 @@
#pragma once
-namespace bus { namespace hexbus {
+namespace bus::hexbus {
class ibc_device : public device_t
{
public:
ibc_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
- void device_start() override;
- void device_reset() override;
+ void device_start() override ATTR_COLD;
+ void device_reset() override ATTR_COLD;
- DECLARE_READ8_MEMBER( read );
- DECLARE_WRITE8_MEMBER( write );
+ uint8_t read(offs_t offset);
+ void write(offs_t offset, uint8_t data);
// Callbacks
auto int_cb() { return m_int.bind(); }
@@ -63,11 +63,13 @@ private:
uint8_t m_data;
uint8_t m_transmit;
+ uint8_t m_last_status;
+
void set_disable_inhibit(bool dis, bool inh);
void set_lines(bool bav, bool hsk);
};
-} }
+} // namespace bus::hexbus
DECLARE_DEVICE_TYPE_NS(IBC, bus::hexbus, ibc_device)
#endif
diff --git a/src/devices/bus/hp80_io/82900.cpp b/src/devices/bus/hp80_io/82900.cpp
new file mode 100644
index 00000000000..b910e36b1c6
--- /dev/null
+++ b/src/devices/bus/hp80_io/82900.cpp
@@ -0,0 +1,174 @@
+// license:BSD-3-Clause
+// copyright-holders: F. Ulivi
+/*********************************************************************
+
+ 82900.cpp
+
+ 82900 module (CP/M auxiliary processor)
+
+*********************************************************************/
+
+#include "emu.h"
+#include "82900.h"
+
+// Debugging
+#define VERBOSE 0
+#include "logmacro.h"
+
+// Bit manipulation
+namespace {
+ template<typename T> constexpr T BIT_MASK(unsigned n)
+ {
+ return (T)1U << n;
+ }
+
+ template<typename T> void BIT_SET(T& w , unsigned n)
+ {
+ w |= BIT_MASK<T>(n);
+ }
+}
+
+hp82900_io_card_device::hp82900_io_card_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
+ : device_t(mconfig , HP82900_IO_CARD , tag , owner , clock),
+ device_hp80_io_interface(mconfig, *this),
+ m_cpu(*this , "cpu"),
+ m_translator(*this , "xlator"),
+ m_rom(*this , "rom")
+{
+}
+
+hp82900_io_card_device::~hp82900_io_card_device()
+{
+}
+
+void hp82900_io_card_device::install_read_write_handlers(address_space& space , uint16_t base_addr)
+{
+ space.install_readwrite_handler(base_addr, base_addr + 1, read8sm_delegate(*m_translator, FUNC(hp_1mb5_device::cpu_r)), write8sm_delegate(*m_translator, FUNC(hp_1mb5_device::cpu_w)));
+}
+
+void hp82900_io_card_device::inten()
+{
+ m_translator->inten();
+}
+
+void hp82900_io_card_device::clear_service()
+{
+ m_translator->clear_service();
+}
+
+static INPUT_PORTS_START(hp82900_port)
+ PORT_START("SC")
+ PORT_CONFNAME(0xf , 3 , "Select Code")
+INPUT_PORTS_END
+
+ioport_constructor hp82900_io_card_device::device_input_ports() const
+{
+ return INPUT_PORTS_NAME(hp82900_port);
+}
+
+void hp82900_io_card_device::device_start()
+{
+ m_ram = std::make_unique<uint8_t[]>(65536);
+
+ save_pointer(NAME(m_ram) , 65536);
+ save_item(NAME(m_rom_enabled));
+ save_item(NAME(m_addr_latch));
+}
+
+void hp82900_io_card_device::device_reset()
+{
+ m_rom_enabled = true;
+}
+
+ROM_START(hp82900)
+ ROM_REGION(0x800 , "rom" , 0)
+ ROM_LOAD("82900-60002.bin" , 0 , 0x800 , CRC(48745bbb) SHA1(fb4427f729eedba5ac01809718b841c7bdd85e1f))
+ROM_END
+
+void hp82900_io_card_device::reset_w(int state)
+{
+ LOG("reset_w %d\n" , state);
+ m_cpu->set_input_line(INPUT_LINE_RESET , state);
+ if (state) {
+ // When reset is asserted, clear state
+ device_reset();
+ }
+}
+
+uint8_t hp82900_io_card_device::cpu_mem_r(offs_t offset)
+{
+ if (m_rom_enabled) {
+ return m_rom[ offset & 0x7ff ];
+ } else {
+ return m_ram[ offset ];
+ }
+}
+
+void hp82900_io_card_device::cpu_mem_w(offs_t offset, uint8_t data)
+{
+ m_ram[ offset ] = data;
+}
+
+uint8_t hp82900_io_card_device::cpu_io_r(offs_t offset)
+{
+ m_rom_enabled = false;
+
+ uint8_t res;
+ if (BIT(offset , 6) && (m_addr_latch & 0x82) == 0) {
+ res = m_translator->uc_r(m_addr_latch & 1);
+ } else {
+ res = ~0;
+ }
+ return res;
+}
+
+void hp82900_io_card_device::cpu_io_w(offs_t offset, uint8_t data)
+{
+ m_rom_enabled = false;
+ if (BIT(offset , 6) && (m_addr_latch & 0x82) == 0) {
+ m_translator->uc_w(m_addr_latch & 1 , data);
+ } else if (BIT(offset , 7)) {
+ m_addr_latch = data;
+ }
+}
+
+void hp82900_io_card_device::cpu_mem_map(address_map &map)
+{
+ map.unmap_value_high();
+ map(0x0000 , 0xffff).rw(FUNC(hp82900_io_card_device::cpu_mem_r) , FUNC(hp82900_io_card_device::cpu_mem_w));
+}
+
+void hp82900_io_card_device::cpu_io_map(address_map &map)
+{
+ map.unmap_value_high();
+ map.global_mask(0xff);
+ map(0x00 , 0xff).rw(FUNC(hp82900_io_card_device::cpu_io_r) , FUNC(hp82900_io_card_device::cpu_io_w));
+}
+
+void hp82900_io_card_device::z80_m1_w(uint8_t data)
+{
+ // 1 wait state on each M1 cycle
+ m_cpu->adjust_icount(-1);
+}
+
+const tiny_rom_entry *hp82900_io_card_device::device_rom_region() const
+{
+ return ROM_NAME(hp82900);
+}
+
+void hp82900_io_card_device::device_add_mconfig(machine_config &config)
+{
+ Z80(config , m_cpu , XTAL(8'000'000) / 2);
+ m_cpu->set_addrmap(AS_PROGRAM , &hp82900_io_card_device::cpu_mem_map);
+ m_cpu->set_addrmap(AS_IO , &hp82900_io_card_device::cpu_io_map);
+ m_cpu->refresh_cb().set(FUNC(hp82900_io_card_device::z80_m1_w));
+
+ HP_1MB5(config, m_translator, 0);
+ m_translator->irl_handler().set(FUNC(hp82900_io_card_device::irl_w));
+ m_translator->halt_handler().set(FUNC(hp82900_io_card_device::halt_w));
+ m_translator->reset_handler().set(FUNC(hp82900_io_card_device::reset_w));
+ m_translator->int_handler().set([this](int state) { m_cpu->set_input_line(INPUT_LINE_IRQ0 , !state); });
+}
+
+// device type definition
+DEFINE_DEVICE_TYPE(HP82900_IO_CARD, hp82900_io_card_device, "hp82900", "HP82900 card")
diff --git a/src/devices/bus/hp80_io/82900.h b/src/devices/bus/hp80_io/82900.h
new file mode 100644
index 00000000000..35270eef2e8
--- /dev/null
+++ b/src/devices/bus/hp80_io/82900.h
@@ -0,0 +1,67 @@
+// license:BSD-3-Clause
+// copyright-holders: F. Ulivi
+/*********************************************************************
+
+ 82900.h
+
+ 82900 module (CP/M auxiliary processor)
+
+*********************************************************************/
+
+#ifndef MAME_BUS_HP80_IO_82900_H
+#define MAME_BUS_HP80_IO_82900_H
+
+#pragma once
+
+#include "hp80_io.h"
+#include "cpu/z80/z80.h"
+#include "machine/1mb5.h"
+
+class hp82900_io_card_device : public device_t, public device_hp80_io_interface
+{
+public:
+ // construction/destruction
+ hp82900_io_card_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
+ virtual ~hp82900_io_card_device();
+
+protected:
+ virtual void device_start() override ATTR_COLD;
+ virtual void device_reset() override ATTR_COLD;
+
+ // device-level overrides
+ virtual ioport_constructor device_input_ports() const override ATTR_COLD;
+ virtual const tiny_rom_entry *device_rom_region() const override ATTR_COLD;
+ virtual void device_add_mconfig(machine_config &config) override ATTR_COLD;
+
+ virtual void install_read_write_handlers(address_space& space , uint16_t base_addr) override;
+
+ virtual void inten() override;
+ virtual void clear_service() override;
+
+private:
+ required_device<z80_device> m_cpu;
+ required_device<hp_1mb5_device> m_translator;
+
+ // Boot ROM
+ required_region_ptr<uint8_t> m_rom;
+
+ // RAM
+ std::unique_ptr<uint8_t []> m_ram;
+
+ bool m_rom_enabled;
+ uint8_t m_addr_latch;
+
+ 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);
+ void cpu_io_w(offs_t offset, uint8_t data);
+ void cpu_mem_map(address_map &map) ATTR_COLD;
+ void cpu_io_map(address_map &map) ATTR_COLD;
+ void z80_m1_w(uint8_t data);
+};
+
+// device type definition
+DECLARE_DEVICE_TYPE(HP82900_IO_CARD, hp82900_io_card_device)
+
+#endif // MAME_BUS_HP80_IO_82900_H
diff --git a/src/devices/bus/hp80_io/82937.cpp b/src/devices/bus/hp80_io/82937.cpp
index 171d4a62204..31fe00e8272 100644
--- a/src/devices/bus/hp80_io/82937.cpp
+++ b/src/devices/bus/hp80_io/82937.cpp
@@ -18,7 +18,6 @@
#include "emu.h"
#include "82937.h"
-#include "coreutil.h"
// Debugging
#define VERBOSE 0
@@ -56,7 +55,8 @@ constexpr unsigned P1_NDAC_BIT = 1;
constexpr unsigned P1_NRFD_BIT = 0;
hp82937_io_card_device::hp82937_io_card_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
- : hp80_io_card_device(mconfig , HP82937_IO_CARD , tag , owner , clock),
+ : device_t(mconfig , HP82937_IO_CARD , tag , owner , clock),
+ device_hp80_io_interface(mconfig, *this),
m_cpu(*this , "cpu"),
m_translator(*this , "xlator"),
m_sw1(*this , "sw1"),
@@ -70,7 +70,7 @@ hp82937_io_card_device::~hp82937_io_card_device()
void hp82937_io_card_device::install_read_write_handlers(address_space& space , uint16_t base_addr)
{
- space.install_readwrite_handler(base_addr , base_addr + 1 , READ8_DEVICE_DELEGATE(m_translator , hp_1mb5_device , cpu_r) , WRITE8_DEVICE_DELEGATE(m_translator , hp_1mb5_device , cpu_w));
+ space.install_readwrite_handler(base_addr, base_addr + 1, read8sm_delegate(*m_translator, FUNC(hp_1mb5_device::cpu_r)), write8sm_delegate(*m_translator, FUNC(hp_1mb5_device::cpu_w)));
}
void hp82937_io_card_device::inten()
@@ -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,12 +92,12 @@ 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;
}
-READ8_MEMBER(hp82937_io_card_device::p1_r)
+uint8_t hp82937_io_card_device::p1_r()
{
uint8_t res = 0;
@@ -146,32 +146,32 @@ READ8_MEMBER(hp82937_io_card_device::p1_r)
return res;
}
-WRITE8_MEMBER(hp82937_io_card_device::p1_w)
+void hp82937_io_card_device::p1_w(uint8_t data)
{
update_signals();
update_data_out();
}
-READ8_MEMBER(hp82937_io_card_device::dio_r)
+uint8_t hp82937_io_card_device::dio_r()
{
if (m_dio_out) {
return 0xff;
} else {
- return m_ieee488->read_dio();
+ return m_ieee488->dio_r();
}
}
-WRITE8_MEMBER(hp82937_io_card_device::dio_w)
+void hp82937_io_card_device::dio_w(uint8_t data)
{
update_data_out();
}
-READ8_MEMBER(hp82937_io_card_device::switch_r)
+uint8_t hp82937_io_card_device::switch_r()
{
return m_sw1->read() | 0xc0;
}
-WRITE8_MEMBER(hp82937_io_card_device::latch_w)
+void hp82937_io_card_device::latch_w(uint8_t data)
{
LOG("latch=%02x\n" , data);
m_latch = data;
@@ -179,7 +179,7 @@ WRITE8_MEMBER(hp82937_io_card_device::latch_w)
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();
@@ -243,8 +243,6 @@ void hp82937_io_card_device::device_start()
void hp82937_io_card_device::device_reset()
{
- hp80_io_card_device::device_reset();
-
m_latch = 0;
m_updating = false;
update_signals();
@@ -253,7 +251,7 @@ void hp82937_io_card_device::device_reset()
void hp82937_io_card_device::update_data_out()
{
- m_ieee488->write_dio(m_dio_out ? m_cpu->p2_r() : 0xff);
+ m_ieee488->host_dio_w(m_dio_out ? m_cpu->p2_r() : 0xff);
}
void hp82937_io_card_device::update_signals()
diff --git a/src/devices/bus/hp80_io/82937.h b/src/devices/bus/hp80_io/82937.h
index dabafa22f6e..e685f9ccb15 100644
--- a/src/devices/bus/hp80_io/82937.h
+++ b/src/devices/bus/hp80_io/82937.h
@@ -18,7 +18,7 @@
#include "bus/ieee488/ieee488.h"
#include "machine/1mb5.h"
-class hp82937_io_card_device : public hp80_io_card_device
+class hp82937_io_card_device : public device_t, public device_hp80_io_interface
{
public:
// construction/destruction
@@ -26,13 +26,13 @@ public:
virtual ~hp82937_io_card_device();
protected:
- virtual void device_start() override;
- virtual void device_reset() override;
+ virtual void device_start() override ATTR_COLD;
+ virtual void device_reset() override ATTR_COLD;
// device-level overrides
- 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 ioport_constructor device_input_ports() const override ATTR_COLD;
+ virtual const tiny_rom_entry *device_rom_region() const override ATTR_COLD;
+ virtual void device_add_mconfig(machine_config &config) override ATTR_COLD;
virtual void install_read_write_handlers(address_space& space , uint16_t base_addr) override;
@@ -51,17 +51,17 @@ private:
uint8_t m_latch; // U3
bool m_updating;
- DECLARE_WRITE_LINE_MEMBER(reset_w);
- DECLARE_READ_LINE_MEMBER(t0_r);
- DECLARE_READ8_MEMBER(p1_r);
- DECLARE_WRITE8_MEMBER(p1_w);
- DECLARE_READ8_MEMBER(dio_r);
- DECLARE_WRITE8_MEMBER(dio_w);
- DECLARE_WRITE_LINE_MEMBER(ieee488_ctrl_w);
- DECLARE_READ8_MEMBER(switch_r);
- DECLARE_WRITE8_MEMBER(latch_w);
-
- void cpu_io_map(address_map &map);
+ 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);
+ void ieee488_ctrl_w(int state);
+ uint8_t switch_r();
+ void latch_w(uint8_t data);
+
+ void cpu_io_map(address_map &map) ATTR_COLD;
void update_data_out();
void update_signals();
diff --git a/src/devices/bus/hp80_io/82939.cpp b/src/devices/bus/hp80_io/82939.cpp
new file mode 100644
index 00000000000..4649758f753
--- /dev/null
+++ b/src/devices/bus/hp80_io/82939.cpp
@@ -0,0 +1,227 @@
+// license:BSD-3-Clause
+// copyright-holders: F. Ulivi
+/*********************************************************************
+
+ 82939.cpp
+
+ 82939 module (RS232 interface)
+
+ Thanks to Tim Nye & Everett Kaser for dumping the 8049 ROM
+
+ Main reference for this module is:
+ HP 82939-90001, jun 81, HP82939A Serial Interface - Installation
+ and Theory of operation manual
+
+*********************************************************************/
+
+#include "emu.h"
+#include "82939.h"
+
+// Debugging
+#define VERBOSE 0
+#include "logmacro.h"
+
+// Bit manipulation
+namespace {
+ template<typename T> constexpr T BIT_MASK(unsigned n)
+ {
+ return (T)1U << n;
+ }
+
+ template<typename T> void BIT_SET(T& w , unsigned n)
+ {
+ w |= BIT_MASK<T>(n);
+ }
+}
+
+hp82939_io_card_device::hp82939_io_card_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
+ : device_t(mconfig , HP82939_IO_CARD , tag , owner , clock),
+ device_hp80_io_interface(mconfig, *this),
+ m_cpu(*this , "cpu"),
+ m_translator(*this , "xlator"),
+ m_rs232(*this , "rs232"),
+ m_uart(*this , "uart"),
+ m_sw12(*this , "sw12")
+{
+}
+
+hp82939_io_card_device::~hp82939_io_card_device()
+{
+}
+
+void hp82939_io_card_device::install_read_write_handlers(address_space& space , uint16_t base_addr)
+{
+ space.install_readwrite_handler(base_addr, base_addr + 1, read8sm_delegate(*m_translator, FUNC(hp_1mb5_device::cpu_r)), write8sm_delegate(*m_translator, FUNC(hp_1mb5_device::cpu_w)));
+}
+
+void hp82939_io_card_device::inten()
+{
+ m_translator->inten();
+}
+
+void hp82939_io_card_device::clear_service()
+{
+ m_translator->clear_service();
+}
+
+static INPUT_PORTS_START(hp82939_port)
+ PORT_HP80_IO_SC(10)
+ PORT_START("sw12")
+ PORT_DIPNAME(0x40 , 0 , "Auto Handshake")
+ PORT_DIPLOCATION("S1:1")
+ PORT_DIPSETTING(0x00 , "Ignore")
+ PORT_DIPSETTING(0x40 , DEF_STR(On))
+ PORT_DIPNAME(0x20 , 0 , "Parity tx")
+ PORT_DIPLOCATION("S2:1")
+ PORT_DIPSETTING(0x00 , DEF_STR(Off))
+ PORT_DIPSETTING(0x20 , DEF_STR(On))
+ PORT_DIPNAME(0x10 , 0 , "Parity")
+ PORT_DIPLOCATION("S2:2")
+ PORT_DIPSETTING(0x00 , "Odd")
+ PORT_DIPSETTING(0x10 , "Even")
+ PORT_DIPNAME(0x08 , 0x08 , "Parity enable")
+ PORT_DIPLOCATION("S2:3")
+ PORT_DIPSETTING(0x00 , DEF_STR(Off))
+ PORT_DIPSETTING(0x08 , DEF_STR(On))
+ PORT_DIPNAME(0x04 , 0 , "Stop bits")
+ PORT_DIPLOCATION("S2:4")
+ PORT_DIPSETTING(0x00 , "1")
+ PORT_DIPSETTING(0x04 , "2")
+ PORT_DIPNAME(0x03 , 0x02 , "Character size")
+ PORT_DIPLOCATION("S2:5,6")
+ PORT_DIPSETTING(0x00 , "5")
+ PORT_DIPSETTING(0x01 , "6")
+ PORT_DIPSETTING(0x02 , "7")
+ PORT_DIPSETTING(0x03 , "8")
+ PORT_DIPNAME(0x780 , 0x300 , "Baud rate")
+ PORT_DIPLOCATION("S2:7,8,9,10")
+ PORT_DIPSETTING(0x000 , "50")
+ PORT_DIPSETTING(0x080 , "75")
+ PORT_DIPSETTING(0x100 , "110")
+ PORT_DIPSETTING(0x180 , "134.5")
+ PORT_DIPSETTING(0x200 , "150")
+ PORT_DIPSETTING(0x280 , "200")
+ PORT_DIPSETTING(0x300 , "300")
+ PORT_DIPSETTING(0x380 , "600")
+ PORT_DIPSETTING(0x400 , "1200")
+ PORT_DIPSETTING(0x480 , "1800")
+ PORT_DIPSETTING(0x500 , "2000")
+ PORT_DIPSETTING(0x580 , "2400")
+ PORT_DIPSETTING(0x600 , "3600")
+ PORT_DIPSETTING(0x680 , "4800")
+ PORT_DIPSETTING(0x700 , "7200")
+ PORT_DIPSETTING(0x780 , "9600")
+INPUT_PORTS_END
+
+ioport_constructor hp82939_io_card_device::device_input_ports() const
+{
+ return INPUT_PORTS_NAME(hp82939_port);
+}
+
+void hp82939_io_card_device::device_start()
+{
+}
+
+ROM_START(hp82939)
+ ROM_REGION(0x800 , "cpu" , 0)
+ ROM_LOAD("1820-2438.bin" , 0 , 0x800 , CRC(3a2f42a2) SHA1(0f6a70eb8981a8a87c7514ce8226ff1af3ac1668))
+ROM_END
+
+uint8_t hp82939_io_card_device::p1_r()
+{
+ uint8_t res = uint8_t(m_sw12->read() & 0x7f);
+
+ BIT_SET(res , 7);
+
+ return res;
+}
+
+void hp82939_io_card_device::p1_w(uint8_t data)
+{
+ if (BIT(data , 7)) {
+ m_uart->reset();
+ }
+}
+
+uint8_t hp82939_io_card_device::p2_r()
+{
+ uint8_t res = uint8_t((m_sw12->read() >> 7) & 0xf);
+
+ if (m_rs232->cts_r()) {
+ BIT_SET(res , 4);
+ }
+ if (m_rs232->dsr_r()) {
+ BIT_SET(res , 5);
+ }
+ // RI always reads 1
+ BIT_SET(res , 6);
+ if (m_rs232->dcd_r()) {
+ BIT_SET(res , 7);
+ }
+
+ return res;
+}
+
+uint8_t hp82939_io_card_device::cpu_r(offs_t offset)
+{
+ if ((offset & 0x82) == 0x00) {
+ return m_translator->uc_r(offset & 1);
+ } else if ((offset & 0x83) == 0x82) {
+ return m_uart->ins8250_r((offset >> 2) & 7);
+ } else {
+ return 0xff;
+ }
+}
+
+void hp82939_io_card_device::cpu_w(offs_t offset, uint8_t data)
+{
+ if ((offset & 0x82) == 0x00) {
+ m_translator->uc_w(offset & 1 , data);
+ } else if ((offset & 0x83) == 0x82) {
+ m_uart->ins8250_w((offset >> 2) & 7 , data);
+ }
+}
+
+void hp82939_io_card_device::cpu_io_map(address_map &map)
+{
+ map.unmap_value_high();
+ map(0x00 , 0xff).rw(FUNC(hp82939_io_card_device::cpu_r) , FUNC(hp82939_io_card_device::cpu_w));
+}
+
+const tiny_rom_entry *hp82939_io_card_device::device_rom_region() const
+{
+ return ROM_NAME(hp82939);
+}
+
+void hp82939_io_card_device::device_add_mconfig(machine_config &config)
+{
+ I8049(config, m_cpu, XTAL(5'529'600));
+ m_cpu->set_addrmap(AS_IO, &hp82939_io_card_device::cpu_io_map);
+ m_cpu->t1_in_cb().set("xlator", FUNC(hp_1mb5_device::int_r));
+ m_cpu->set_t0_clk_cb("uart" , FUNC(device_t::set_unscaled_clock_int));
+ m_cpu->p1_in_cb().set(FUNC(hp82939_io_card_device::p1_r));
+ m_cpu->p1_out_cb().set(FUNC(hp82939_io_card_device::p1_w));
+ m_cpu->p2_in_cb().set(FUNC(hp82939_io_card_device::p2_r));
+
+ HP_1MB5(config, m_translator, 0);
+ m_translator->irl_handler().set(FUNC(hp82939_io_card_device::irl_w));
+ m_translator->halt_handler().set(FUNC(hp82939_io_card_device::halt_w));
+ m_translator->reset_handler().set_inputline(m_cpu , INPUT_LINE_RESET);
+
+ RS232_PORT(config, m_rs232, default_rs232_devices, nullptr);
+
+ INS8250(config , m_uart , 0);
+ m_uart->out_int_callback().set_inputline(m_cpu , MCS48_INPUT_IRQ);
+ m_uart->out_tx_callback().set(m_rs232 , FUNC(rs232_port_device::write_txd));
+ m_uart->out_dtr_callback().set(m_rs232 , FUNC(rs232_port_device::write_dtr));
+ m_uart->out_rts_callback().set(m_rs232 , FUNC(rs232_port_device::write_rts));
+ m_uart->out_out1_callback().set(m_rs232 , FUNC(rs232_port_device::write_spds));
+
+ m_rs232->rxd_handler().set(m_uart , FUNC(ins8250_device::rx_w));
+ m_rs232->dcd_handler().set(m_uart , FUNC(ins8250_device::dcd_w));
+ m_rs232->dsr_handler().set(m_uart , FUNC(ins8250_device::dsr_w));
+ m_rs232->cts_handler().set(m_uart , FUNC(ins8250_device::cts_w));
+}
+
+// device type definition
+DEFINE_DEVICE_TYPE(HP82939_IO_CARD, hp82939_io_card_device, "hp82939", "HP82939 card")
diff --git a/src/devices/bus/hp80_io/82939.h b/src/devices/bus/hp80_io/82939.h
new file mode 100644
index 00000000000..c91c8f98b69
--- /dev/null
+++ b/src/devices/bus/hp80_io/82939.h
@@ -0,0 +1,60 @@
+// license:BSD-3-Clause
+// copyright-holders: F. Ulivi
+/*********************************************************************
+
+ 82939.h
+
+ 82939 module (RS232 interface)
+
+*********************************************************************/
+
+#ifndef MAME_BUS_HP80_IO_82939_H
+#define MAME_BUS_HP80_IO_82939_H
+
+#pragma once
+
+#include "hp80_io.h"
+#include "cpu/mcs48/mcs48.h"
+#include "machine/1mb5.h"
+#include "machine/ins8250.h"
+#include "bus/rs232/rs232.h"
+
+class hp82939_io_card_device : public device_t, public device_hp80_io_interface
+{
+public:
+ // construction/destruction
+ hp82939_io_card_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
+ virtual ~hp82939_io_card_device();
+
+protected:
+ virtual void device_start() override ATTR_COLD;
+
+ // device-level overrides
+ virtual ioport_constructor device_input_ports() const override ATTR_COLD;
+ virtual const tiny_rom_entry *device_rom_region() const override ATTR_COLD;
+ virtual void device_add_mconfig(machine_config &config) override ATTR_COLD;
+
+ virtual void install_read_write_handlers(address_space& space , uint16_t base_addr) override;
+
+ virtual void inten() override;
+ virtual void clear_service() override;
+
+private:
+ required_device<i8049_device> m_cpu;
+ required_device<hp_1mb5_device> m_translator;
+ required_device<rs232_port_device> m_rs232;
+ required_device<ins8250_device> m_uart;
+ required_ioport m_sw12;
+
+ uint8_t p1_r();
+ void p1_w(uint8_t data);
+ uint8_t p2_r();
+ uint8_t cpu_r(offs_t offset);
+ void cpu_w(offs_t offset, uint8_t data);
+ void cpu_io_map(address_map &map) ATTR_COLD;
+};
+
+// device type definition
+DECLARE_DEVICE_TYPE(HP82939_IO_CARD, hp82939_io_card_device)
+
+#endif // MAME_BUS_HP80_IO_82939_H
diff --git a/src/devices/bus/hp80_io/hp80_io.cpp b/src/devices/bus/hp80_io/hp80_io.cpp
index 8004ce06bd4..5ca970060bf 100644
--- a/src/devices/bus/hp80_io/hp80_io.cpp
+++ b/src/devices/bus/hp80_io/hp80_io.cpp
@@ -23,7 +23,7 @@ DEFINE_DEVICE_TYPE(HP80_IO_SLOT, hp80_io_slot_device, "hp80_io_slot", "HP80 I/O
// +-------------------+
hp80_io_slot_device::hp80_io_slot_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) :
device_t(mconfig, HP80_IO_SLOT, tag, owner, clock),
- device_slot_interface(mconfig, *this),
+ device_single_card_slot_interface<device_hp80_io_interface>(mconfig, *this),
m_irl_cb_func(*this),
m_halt_cb_func(*this),
m_slot_no(0)
@@ -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);
@@ -54,7 +52,7 @@ WRITE_LINE_MEMBER(hp80_io_slot_device::halt_w)
void hp80_io_slot_device::inten()
{
- hp80_io_card_device *card = downcast<hp80_io_card_device*>(get_card_device());
+ device_hp80_io_interface *card = get_card_device();
if (card != nullptr) {
card->inten();
@@ -63,7 +61,7 @@ void hp80_io_slot_device::inten()
void hp80_io_slot_device::clear_service()
{
- hp80_io_card_device *card = downcast<hp80_io_card_device*>(get_card_device());
+ device_hp80_io_interface *card = get_card_device();
if (card != nullptr) {
card->clear_service();
@@ -72,7 +70,7 @@ void hp80_io_slot_device::clear_service()
void hp80_io_slot_device::install_read_write_handlers(address_space& space)
{
- hp80_io_card_device *card = downcast<hp80_io_card_device*>(get_card_device());
+ device_hp80_io_interface *card = get_card_device();
if (card != nullptr) {
card->install_read_write_handlers(space , get_base_addr());
@@ -81,7 +79,7 @@ void hp80_io_slot_device::install_read_write_handlers(address_space& space)
uint8_t hp80_io_slot_device::get_sc() const
{
- const hp80_io_card_device *card = downcast<hp80_io_card_device*>(get_card_device());
+ const device_hp80_io_interface *card = get_card_device();
if (card != nullptr) {
return card->get_sc();
@@ -92,60 +90,63 @@ uint8_t hp80_io_slot_device::get_sc() const
uint16_t hp80_io_slot_device::get_base_addr() const
{
- const hp80_io_card_device *card = downcast<hp80_io_card_device*>(get_card_device());
+ const device_hp80_io_interface *card = get_card_device();
if (card != nullptr) {
- uint16_t addr = ((uint16_t)(card->get_sc() - HP80_IO_FIRST_SC) << 1) | 0xff50;
+ uint16_t addr = ((uint16_t)(card->get_sc()) << 1) | 0xff40;
return addr;
} else {
return 0;
}
}
-// +-------------------+
-// |hp80_io_card_device|
-// +-------------------+
-uint8_t hp80_io_card_device::get_sc() const
+// +------------------------+
+// |device_hp80_io_interface|
+// +------------------------+
+uint8_t device_hp80_io_interface::get_sc() const
{
- return m_select_code_port->read() + HP80_IO_FIRST_SC;
+ return m_select_code_port->read();
}
-void hp80_io_card_device::inten()
+void device_hp80_io_interface::inten()
{
}
-void hp80_io_card_device::clear_service()
+void device_hp80_io_interface::clear_service()
{
}
-hp80_io_card_device::hp80_io_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_slot_card_interface(mconfig, *this),
+device_hp80_io_interface::device_hp80_io_interface(const machine_config &mconfig, device_t &device) :
+ device_interface(device, "hp80io"),
m_select_code_port(*this , "SC")
{
}
-hp80_io_card_device::~hp80_io_card_device()
+device_hp80_io_interface::~device_hp80_io_interface()
{
}
-WRITE_LINE_MEMBER(hp80_io_card_device::irl_w)
+void device_hp80_io_interface::irl_w(int state)
{
- LOG("irl_w card=%d\n" , state);
- hp80_io_slot_device *slot = downcast<hp80_io_slot_device *>(owner());
+ 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(hp80_io_card_device::halt_w)
+void device_hp80_io_interface::halt_w(int state)
{
- LOG("halt_w card=%d\n" , state);
- hp80_io_slot_device *slot = downcast<hp80_io_slot_device *>(owner());
+ if (VERBOSE & LOG_GENERAL) device().logerror("halt_w card=%d\n" , state);
+ hp80_io_slot_device *slot = downcast<hp80_io_slot_device *>(device().owner());
slot->halt_w(state);
}
+#include "82900.h"
#include "82937.h"
+#include "82939.h"
void hp80_io_slot_devices(device_slot_interface &device)
{
+ device.option_add("82900_cpm" , HP82900_IO_CARD);
device.option_add("82937_hpib" , HP82937_IO_CARD);
+ device.option_add("82939_serial" , HP82939_IO_CARD);
}
diff --git a/src/devices/bus/hp80_io/hp80_io.h b/src/devices/bus/hp80_io/hp80_io.h
index 1e51bf9b8b8..90f9912d222 100644
--- a/src/devices/bus/hp80_io/hp80_io.h
+++ b/src/devices/bus/hp80_io/hp80_io.h
@@ -13,25 +13,26 @@
#pragma once
-
-#define HP80_IO_FIRST_SC 3 // Lowest SC used by I/O cards
+#define HP80_IO_SC_OFFSET 5
#define PORT_HP80_IO_SC(_default_sc) \
PORT_START("SC") \
- PORT_CONFNAME(0xf , (_default_sc) - HP80_IO_FIRST_SC , "Select Code") \
- PORT_CONFSETTING(0 , "3")\
- PORT_CONFSETTING(1 , "4")\
- PORT_CONFSETTING(2 , "5")\
- PORT_CONFSETTING(3 , "6")\
- PORT_CONFSETTING(4 , "7")\
- PORT_CONFSETTING(5 , "8")\
- PORT_CONFSETTING(6 , "9")\
- PORT_CONFSETTING(7 , "10")
+ PORT_CONFNAME(0xf , (_default_sc) + HP80_IO_SC_OFFSET , "Select Code") \
+ PORT_CONFSETTING(8 , "3")\
+ PORT_CONFSETTING(9 , "4")\
+ PORT_CONFSETTING(10 , "5")\
+ PORT_CONFSETTING(11 , "6")\
+ PORT_CONFSETTING(12 , "7")\
+ PORT_CONFSETTING(13 , "8")\
+ PORT_CONFSETTING(14 , "9")\
+ PORT_CONFSETTING(15 , "10")
void hp80_io_slot_devices(device_slot_interface &device);
+class device_hp80_io_interface;
+
class hp80_io_slot_device : public device_t,
- public device_slot_interface
+ public device_single_card_slot_interface<device_hp80_io_interface>
{
public:
// construction/destruction
@@ -50,9 +51,6 @@ public:
// configuration helpers
void set_slot_no(unsigned slot_no) { m_slot_no = slot_no; }
- // device-level overrides
- virtual void device_start() override;
-
// Callback setups
auto irl_cb() { return m_irl_cb_func.bind(); }
auto halt_cb() { return m_halt_cb_func.bind(); }
@@ -64,22 +62,27 @@ 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();
+protected:
+ // device-level overrides
+ virtual void device_start() override ATTR_COLD;
+
private:
devcb_write8 m_irl_cb_func;
devcb_write8 m_halt_cb_func;
unsigned m_slot_no;
};
-class hp80_io_card_device : public device_t,
- public device_slot_card_interface
+class device_hp80_io_interface : public device_interface
{
public:
+ virtual ~device_hp80_io_interface();
+
// SC getter
uint8_t get_sc() const;
@@ -89,15 +92,13 @@ public:
virtual void clear_service();
protected:
- // construction/destruction
- hp80_io_card_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock);
- virtual ~hp80_io_card_device();
+ device_hp80_io_interface(const machine_config &mconfig, device_t &device);
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/hp80_optroms/hp80_optrom.cpp b/src/devices/bus/hp80_optroms/hp80_optrom.cpp
deleted file mode 100644
index 1816f0c0244..00000000000
--- a/src/devices/bus/hp80_optroms/hp80_optrom.cpp
+++ /dev/null
@@ -1,117 +0,0 @@
-// license:BSD-3-Clause
-// copyright-holders: F. Ulivi
-/*********************************************************************
-
- hp80_optrom.cpp
-
- Optional ROMs for HP80 systems
-
-*********************************************************************/
-
-#include "emu.h"
-#include "hp80_optrom.h"
-#include "softlist.h"
-
-// Debugging
-#define VERBOSE 1
-#include "logmacro.h"
-
-DEFINE_DEVICE_TYPE(HP80_OPTROM_CART, hp80_optrom_cart_device, "hp80_optrom_cart", "HP80 optional ROM cartridge")
-DEFINE_DEVICE_TYPE(HP80_OPTROM_SLOT, hp80_optrom_slot_device, "hp80_optrom_slot", "HP80 optional ROM slot")
-
-// +-----------------------+
-// |hp80_optrom_cart_device|
-// +-----------------------+
-hp80_optrom_cart_device::hp80_optrom_cart_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_card_interface(mconfig, *this)
-{
-}
-
-hp80_optrom_cart_device::hp80_optrom_cart_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) :
- hp80_optrom_cart_device(mconfig, HP80_OPTROM_CART, tag, owner, clock)
-{
-}
-
-// +-----------------------+
-// |hp80_optrom_slot_device|
-// +-----------------------+
-hp80_optrom_slot_device::hp80_optrom_slot_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) :
- device_t(mconfig, HP80_OPTROM_SLOT, tag, owner, clock),
- device_image_interface(mconfig, *this),
- device_slot_interface(mconfig, *this),
- m_cart(nullptr),
- m_select_code(0)
-{
-}
-
-hp80_optrom_slot_device::~hp80_optrom_slot_device()
-{
-}
-
-void hp80_optrom_slot_device::install_read_handler(address_space& space)
-{
- if (loaded_through_softlist()) {
- offs_t start = (offs_t)m_select_code * HP80_OPTROM_SIZE;
- space.install_rom(start , start + HP80_OPTROM_SIZE - 1 , get_software_region("rom"));
- }
-}
-
-void hp80_optrom_slot_device::device_start()
-{
- m_cart = dynamic_cast<hp80_optrom_cart_device *>(get_card_device());
-}
-
-image_init_result hp80_optrom_slot_device::call_load()
-{
- LOG("hp80_optrom: call_load\n");
- if (m_cart == nullptr || !loaded_through_softlist()) {
- LOG("hp80_optrom: must be loaded from sw list\n");
- return image_init_result::FAIL;
- }
-
- const char *sc_feature = get_feature("sc");
- if (sc_feature == nullptr) {
- LOG("hp80_optrom: no 'sc' feature\n");
- return image_init_result::FAIL;
- }
-
- unsigned sc;
- if (sc_feature[ 0 ] != '0' || sc_feature[ 1 ] != 'x' || sscanf(&sc_feature[ 2 ] , "%x" , &sc) != 1) {
- LOG("hp80_optrom: can't parse 'sc' feature\n");
- return image_init_result::FAIL;
- }
-
- // Valid SC values: 0x01..0xff
- if (sc < 1 || sc > 0xff) {
- LOG("hp80_optrom: illegal select code (%x)\n" , sc);
- return image_init_result::FAIL;
- }
-
- auto length = get_software_region_length("rom");
-
- if (length != HP80_OPTROM_SIZE) {
- LOG("hp80_optrom: illegal region length (%x)\n" , length);
- return image_init_result::FAIL;
- }
-
- LOG("hp80_optrom: loaded SC=0x%02x\n" , sc);
- m_select_code = sc;
- return image_init_result::PASS;
-}
-
-void hp80_optrom_slot_device::call_unload()
-{
- LOG("hp80_optrom: call_unload\n");
- machine().schedule_soft_reset();
-}
-
-std::string hp80_optrom_slot_device::get_default_card_software(get_default_card_software_hook &hook) const
-{
- return software_get_default_slot("rom");
-}
-
-void hp80_optrom_slot_devices(device_slot_interface &device)
-{
- device.option_add_internal("rom", HP80_OPTROM_CART);
-}
diff --git a/src/devices/bus/hp80_optroms/hp80_optrom.h b/src/devices/bus/hp80_optroms/hp80_optrom.h
deleted file mode 100644
index 33bd800027c..00000000000
--- a/src/devices/bus/hp80_optroms/hp80_optrom.h
+++ /dev/null
@@ -1,86 +0,0 @@
-// license:BSD-3-Clause
-// copyright-holders: F. Ulivi
-/*********************************************************************
-
- hp80_optrom.h
-
- Optional ROMs for HP80 systems
-
-*********************************************************************/
-
-#ifndef MAME_BUS_HP80_OPTROMS_HP80_OPTROM_H
-#define MAME_BUS_HP80_OPTROMS_HP80_OPTROM_H
-
-#pragma once
-
-#include "softlist_dev.h"
-
-// Size of optional ROMs (8k)
-static constexpr offs_t HP80_OPTROM_SIZE = 0x2000;
-
-void hp80_optrom_slot_devices(device_slot_interface &device);
-
-class hp80_optrom_cart_device : public device_t,
- public device_slot_card_interface
-{
-public:
- // construction/destruction
- hp80_optrom_cart_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
-
-protected:
- hp80_optrom_cart_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 { }
-};
-
-class hp80_optrom_slot_device : public device_t,
- public device_image_interface,
- public device_slot_interface
-{
-public:
- // construction/destruction
- hp80_optrom_slot_device(machine_config const &mconfig, char const *tag, device_t *owner)
- : hp80_optrom_slot_device(mconfig, tag, owner, (uint32_t)0)
- {
- option_reset();
- hp80_optrom_slot_devices(*this);
- set_default_option(nullptr);
- set_fixed(false);
- }
-
- hp80_optrom_slot_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
- virtual ~hp80_optrom_slot_device();
-
- void install_read_handler(address_space& space);
-
-protected:
- // device-level overrides
- virtual void device_start() override;
-
- // image-level overrides
- virtual image_init_result call_load() override;
- virtual void call_unload() override;
- virtual const software_list_loader &get_software_list_loader() const override { return rom_software_list_loader::instance(); }
-
- virtual iodevice_t image_type() const override { return IO_ROM; }
- virtual bool is_readable() const override { return true; }
- virtual bool is_writeable() const override { return false; }
- virtual bool is_creatable() const override { return false; }
- virtual bool must_be_loaded() const override { return false; }
- virtual bool is_reset_on_load() const override { return true; }
- virtual const char *image_interface() const override { return "hp80_rom"; }
- virtual const char *file_extensions() const override { return "bin"; }
-
- // slot interface overrides
- virtual std::string get_default_card_software(get_default_card_software_hook &hook) const override;
-
- hp80_optrom_cart_device *m_cart;
- uint8_t m_select_code;
-};
-
-// device type definition
-DECLARE_DEVICE_TYPE(HP80_OPTROM_SLOT, hp80_optrom_slot_device)
-DECLARE_DEVICE_TYPE(HP80_OPTROM_CART, hp80_optrom_cart_device)
-
-#endif // MAME_BUS_HP80_OPTROMS_HP80_OPTROM_H
diff --git a/src/devices/bus/hp9845_io/98032.cpp b/src/devices/bus/hp9845_io/98032.cpp
index 221d4e9e176..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"
@@ -47,8 +50,9 @@ DEFINE_DEVICE_TYPE(HP98032_GPIO_LOOPBACK , hp98032_gpio_loopback_device , "hp980
// +----------------------+
hp98032_io_card_device::hp98032_io_card_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
- : hp9845_io_card_device(mconfig , HP98032_IO_CARD , tag , owner , clock)
- , m_gpio(*this , "gpio")
+ : device_t(mconfig, HP98032_IO_CARD, tag, owner, clock)
+ , device_hp9845_io_interface(mconfig, *this)
+ , m_gpio(*this, "gpio")
{
}
@@ -93,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();
@@ -101,7 +106,7 @@ void hp98032_io_card_device::device_reset()
m_gpio->preset_w(0);
}
-READ16_MEMBER(hp98032_io_card_device::reg_r)
+uint16_t hp98032_io_card_device::reg_r(address_space &space, offs_t offset)
{
uint16_t res = 0;
@@ -172,7 +177,7 @@ READ16_MEMBER(hp98032_io_card_device::reg_r)
return res;
}
-WRITE16_MEMBER(hp98032_io_card_device::reg_w)
+void hp98032_io_card_device::reg_w(address_space &space, offs_t offset, uint16_t data)
{
LOG("wr R%u=%04x\n" , offset + 4 , data);
@@ -235,7 +240,7 @@ WRITE16_MEMBER(hp98032_io_card_device::reg_w)
}
}
-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;
@@ -260,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)) {
@@ -270,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);
@@ -348,13 +353,14 @@ void hp98032_io_card_device::latch_input_LSB()
hp98032_gpio_slot_device::hp98032_gpio_slot_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
: device_t(mconfig , HP98032_GPIO_SLOT , tag , owner , clock)
- , device_slot_interface(mconfig , *this)
+ , device_single_card_slot_interface<device_hp98032_gpio_interface>(mconfig , *this)
, m_pflg_handler(*this)
, m_psts_handler(*this)
, m_eir_handler(*this)
{
option_reset();
option_add("loopback" , HP98032_GPIO_LOOPBACK);
+ option_add("hp9871" , HP9871);
option_add("hp9885" , HP9885);
set_default_option(nullptr);
set_fixed(false);
@@ -366,7 +372,7 @@ hp98032_gpio_slot_device::~hp98032_gpio_slot_device()
uint16_t hp98032_gpio_slot_device::get_jumpers() const
{
- hp98032_gpio_card_device *card = downcast<hp98032_gpio_card_device*>(get_card_device());
+ device_hp98032_gpio_interface *card = get_card_device();
if (card != nullptr) {
return card->get_jumpers();
} else {
@@ -376,7 +382,7 @@ uint16_t hp98032_gpio_slot_device::get_jumpers() const
uint16_t hp98032_gpio_slot_device::input_r() const
{
- hp98032_gpio_card_device *card = downcast<hp98032_gpio_card_device*>(get_card_device());
+ device_hp98032_gpio_interface *card = get_card_device();
if (card != nullptr) {
return card->input_r();
} else {
@@ -386,7 +392,7 @@ uint16_t hp98032_gpio_slot_device::input_r() const
uint8_t hp98032_gpio_slot_device::ext_status_r() const
{
- hp98032_gpio_card_device *card = downcast<hp98032_gpio_card_device*>(get_card_device());
+ device_hp98032_gpio_interface *card = get_card_device();
if (card != nullptr) {
return card->ext_status_r();
} else {
@@ -396,7 +402,7 @@ uint8_t hp98032_gpio_slot_device::ext_status_r() const
void hp98032_gpio_slot_device::output_w(uint16_t data)
{
- hp98032_gpio_card_device *card = downcast<hp98032_gpio_card_device*>(get_card_device());
+ device_hp98032_gpio_interface *card = get_card_device();
if (card != nullptr) {
card->output_w(data);
}
@@ -404,46 +410,46 @@ void hp98032_gpio_slot_device::output_w(uint16_t data)
void hp98032_gpio_slot_device::ext_control_w(uint8_t data)
{
- hp98032_gpio_card_device *card = downcast<hp98032_gpio_card_device*>(get_card_device());
+ device_hp98032_gpio_interface *card = get_card_device();
if (card != nullptr) {
card->ext_control_w(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)
{
- hp98032_gpio_card_device *card = downcast<hp98032_gpio_card_device*>(get_card_device());
+ device_hp98032_gpio_interface *card = get_card_device();
if (card != nullptr) {
card->pctl_w(state);
}
}
-WRITE_LINE_MEMBER(hp98032_gpio_slot_device::io_w)
+void hp98032_gpio_slot_device::io_w(int state)
{
- hp98032_gpio_card_device *card = downcast<hp98032_gpio_card_device*>(get_card_device());
+ device_hp98032_gpio_interface *card = get_card_device();
if (card != nullptr) {
card->io_w(state);
}
}
-WRITE_LINE_MEMBER(hp98032_gpio_slot_device::preset_w)
+void hp98032_gpio_slot_device::preset_w(int state)
{
- hp98032_gpio_card_device *card = downcast<hp98032_gpio_card_device*>(get_card_device());
+ device_hp98032_gpio_interface *card = get_card_device();
if (card != nullptr) {
card->preset_w(state);
}
@@ -451,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()
@@ -466,35 +469,34 @@ void hp98032_gpio_slot_device::device_reset()
}
}
-// +------------------------+
-// |hp98032_gpio_card_device|
-// +------------------------+
+// +-----------------------------+
+// |device_hp98032_gpio_interface|
+// +-----------------------------+
-hp98032_gpio_card_device::hp98032_gpio_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_slot_card_interface(mconfig , *this)
+device_hp98032_gpio_interface::device_hp98032_gpio_interface(const machine_config &mconfig, device_t &device)
+ : device_interface(device, "hp98032gpio")
{
}
-hp98032_gpio_card_device::~hp98032_gpio_card_device()
+device_hp98032_gpio_interface::~device_hp98032_gpio_interface()
{
}
-WRITE_LINE_MEMBER(hp98032_gpio_card_device::pflg_w)
+void device_hp98032_gpio_interface::pflg_w(int state)
{
- hp98032_gpio_slot_device *slot = downcast<hp98032_gpio_slot_device*>(owner());
+ hp98032_gpio_slot_device *slot = downcast<hp98032_gpio_slot_device*>(device().owner());
slot->pflg_w(state);
}
-WRITE_LINE_MEMBER(hp98032_gpio_card_device::psts_w)
+void device_hp98032_gpio_interface::psts_w(int state)
{
- hp98032_gpio_slot_device *slot = downcast<hp98032_gpio_slot_device*>(owner());
+ hp98032_gpio_slot_device *slot = downcast<hp98032_gpio_slot_device*>(device().owner());
slot->psts_w(state);
}
-WRITE_LINE_MEMBER(hp98032_gpio_card_device::eir_w)
+void device_hp98032_gpio_interface::eir_w(int state)
{
- hp98032_gpio_slot_device *slot = downcast<hp98032_gpio_slot_device*>(owner());
+ hp98032_gpio_slot_device *slot = downcast<hp98032_gpio_slot_device*>(device().owner());
slot->eir_w(state);
}
@@ -503,7 +505,8 @@ WRITE_LINE_MEMBER(hp98032_gpio_card_device::eir_w)
// +----------------------------+
hp98032_gpio_loopback_device::hp98032_gpio_loopback_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
- : hp98032_gpio_card_device(mconfig, HP98032_GPIO_LOOPBACK, tag, owner, clock)
+ : device_t(mconfig, HP98032_GPIO_LOOPBACK, tag, owner, clock)
+ , device_hp98032_gpio_interface(mconfig, *this)
{
}
@@ -547,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 94013ca589f..0c0c742214c 100644
--- a/src/devices/bus/hp9845_io/98032.h
+++ b/src/devices/bus/hp9845_io/98032.h
@@ -14,9 +14,11 @@
#pragma once
#include "hp9845_io.h"
+
+class device_hp98032_gpio_interface;
class hp98032_gpio_slot_device;
-class hp98032_io_card_device : public hp9845_io_card_device
+class hp98032_io_card_device : public device_t, public device_hp9845_io_interface
{
public:
// construction/destruction
@@ -25,13 +27,13 @@ public:
protected:
// device-level overrides
- 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;
+ virtual void device_add_mconfig(machine_config &config) override ATTR_COLD;
+ virtual ioport_constructor device_input_ports() const override ATTR_COLD;
+ virtual void device_start() override ATTR_COLD;
+ virtual void device_reset() override ATTR_COLD;
- virtual DECLARE_READ16_MEMBER(reg_r) override;
- virtual DECLARE_WRITE16_MEMBER(reg_w) override;
+ virtual uint16_t reg_r(address_space &space, offs_t offset) override;
+ virtual void reg_w(address_space &space, offs_t offset, uint16_t data) override;
private:
required_device<hp98032_gpio_slot_device> m_gpio;
@@ -46,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);
@@ -61,7 +63,7 @@ private:
// The GPIO interface of HP98032 cards
class hp98032_gpio_slot_device : public device_t,
- public device_slot_interface
+ public device_single_card_slot_interface<device_hp98032_gpio_interface>
{
public:
// construction/destruction
@@ -112,19 +114,19 @@ 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
- virtual void device_start() override;
- virtual void device_reset() override;
+ virtual void device_start() override ATTR_COLD;
+ virtual void device_reset() override ATTR_COLD;
private:
devcb_write_line m_pflg_handler;
@@ -134,31 +136,30 @@ private:
};
// A device connected to GPIO port of HP98032
-class hp98032_gpio_card_device : public device_t,
- public device_slot_card_interface
+class device_hp98032_gpio_interface : public device_interface
{
public:
+ virtual ~device_hp98032_gpio_interface();
+
virtual uint16_t get_jumpers() const = 0;
virtual uint16_t input_r() const = 0;
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:
- // construction/destruction
- hp98032_gpio_card_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock);
- virtual ~hp98032_gpio_card_device();
+ 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
-class hp98032_gpio_loopback_device : public hp98032_gpio_card_device
+class hp98032_gpio_loopback_device : public device_t, public device_hp98032_gpio_interface
{
public:
// construction/destruction
@@ -170,14 +171,15 @@ 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
- virtual void device_start() override;
- virtual void device_reset() override;
+ virtual void device_start() override ATTR_COLD;
+ virtual void device_reset() override ATTR_COLD;
+
private:
uint16_t m_output;
uint8_t m_ext_control;
diff --git a/src/devices/bus/hp9845_io/98034.cpp b/src/devices/bus/hp9845_io/98034.cpp
index 9f016eaa3d8..61658c1ecf1 100644
--- a/src/devices/bus/hp9845_io/98034.cpp
+++ b/src/devices/bus/hp9845_io/98034.cpp
@@ -15,7 +15,6 @@
#include "emu.h"
#include "98034.h"
-#include "coreutil.h"
// Debugging
//#define VERBOSE 1
@@ -29,7 +28,8 @@
#define BIT_SET(w , n) ((w) |= BIT_MASK(n))
hp98034_io_card_device::hp98034_io_card_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
- : hp9845_io_card_device(mconfig , HP98034_IO_CARD , tag , owner , clock),
+ : device_t(mconfig , HP98034_IO_CARD , tag , owner , clock),
+ device_hp9845_io_interface(mconfig, *this),
m_cpu(*this , "np"),
m_sw1(*this , "sw1"),
m_ieee488(*this , IEEE488_TAG)
@@ -102,11 +102,10 @@ void hp98034_io_card_device::device_start()
void hp98034_io_card_device::device_reset()
{
- hp9845_io_card_device::device_reset();
-
m_idr = 0;
m_odr = 0;
m_force_flg = false;
+ m_flg = true;
m_mode_reg = 0xff;
m_clr_hpib = false;
m_ctrl_out = 0;
@@ -114,7 +113,7 @@ void hp98034_io_card_device::device_reset()
update_dc();
}
-READ16_MEMBER(hp98034_io_card_device::reg_r)
+uint16_t hp98034_io_card_device::reg_r(address_space &space, offs_t offset)
{
uint16_t res = m_odr;
@@ -133,18 +132,28 @@ READ16_MEMBER(hp98034_io_card_device::reg_r)
m_force_flg = true;
update_flg();
- // PPU pauses for an instant to let NP see FLG=0 immediately
- // There's a bug in Mass Memory opt. ROM because the PPU
- // doesn't wait for FLG from 98034 in a few (common) cases.
- // A magic combination of relative speeds between PPU and
- // NP always hides this bug in the real hw.
- space.device().execute().spin_until_time(attotime::from_usec(5));
-
- LOG("read R%u=%04x\n" , offset + 4 , res);
+
+ // This and the following scheduler acrobatics are meant
+ // to work around a lot of race conditions between hybrid
+ // CPU and Nanoprocessor. Apparently HP people cut a few
+ // cornerns for the sake of transfer speed (such as avoiding
+ // to wait for FLG in selected places) but didn't fully
+ // realize how tight the speed margins were.
+ // The goals of the scheduler manipulation are:
+ // - Quick propagation between processors of FLG setting &
+ // clearing
+ // - Delay the scheduling of hybrid CPU when FLG is set by NP.
+ // 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().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());
return res;
}
-WRITE16_MEMBER(hp98034_io_card_device::reg_w)
+void hp98034_io_card_device::reg_w(address_space &space, offs_t offset, uint16_t data)
{
m_idr = (uint8_t)data;
@@ -159,22 +168,23 @@ WRITE16_MEMBER(hp98034_io_card_device::reg_w)
m_force_flg = true;
update_flg();
- // PPU pauses for an instant to let NP see FLG=0 immediately
- // (see above)
- space.device().execute().spin_until_time(attotime::from_usec(5));
- LOG("write R%u=%04x\n" , offset + 4 , data);
+ // See reg_r above
+ 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());
}
-WRITE8_MEMBER(hp98034_io_card_device::dc_w)
+void hp98034_io_card_device::dc_w(uint8_t data)
{
if (data != m_dc) {
- //LOG("DC=%02x\n" , data);
+ LOG("%.06f DC=%02x\n" , machine().time().as_double() , data);
m_dc = data;
update_dc();
}
}
-READ8_MEMBER(hp98034_io_card_device::dc_r)
+uint8_t hp98034_io_card_device::dc_r()
{
uint8_t res;
@@ -188,19 +198,19 @@ READ8_MEMBER(hp98034_io_card_device::dc_r)
return res;
}
-WRITE8_MEMBER(hp98034_io_card_device::hpib_data_w)
+void hp98034_io_card_device::hpib_data_w(uint8_t data)
{
m_data_out = data;
update_data_out();
}
-WRITE8_MEMBER(hp98034_io_card_device::hpib_ctrl_w)
+void hp98034_io_card_device::hpib_ctrl_w(uint8_t data)
{
m_ctrl_out = data;
update_ctrl_out();
}
-READ8_MEMBER(hp98034_io_card_device::hpib_ctrl_r)
+uint8_t hp98034_io_card_device::hpib_ctrl_r()
{
uint8_t res = 0;
@@ -228,54 +238,60 @@ READ8_MEMBER(hp98034_io_card_device::hpib_ctrl_r)
if (!m_ieee488->eoi_r()) {
BIT_SET(res , 7);
}
-
+ LOG("%.06f DS2=%02x\n" , machine().time().as_double() , res);
return res;
}
-READ8_MEMBER(hp98034_io_card_device::hpib_data_r)
+uint8_t hp98034_io_card_device::hpib_data_r()
{
- return ~m_ieee488->read_dio();
+ return ~m_ieee488->dio_r();
}
-READ8_MEMBER(hp98034_io_card_device::idr_r)
+uint8_t hp98034_io_card_device::idr_r()
{
return m_idr;
}
-WRITE8_MEMBER(hp98034_io_card_device::odr_w)
+void hp98034_io_card_device::odr_w(uint8_t data)
{
m_odr = data;
}
-READ8_MEMBER(hp98034_io_card_device::mode_reg_r)
+uint8_t hp98034_io_card_device::mode_reg_r()
{
+ LOG("%.06f MR=%02x\n" , machine().time().as_double() , m_mode_reg);
return m_mode_reg;
}
-WRITE8_MEMBER(hp98034_io_card_device::mode_reg_clear_w)
+void hp98034_io_card_device::mode_reg_clear_w(uint8_t data)
{
+ LOG("%.06f clear_w\n" , machine().time().as_double());
m_mode_reg = 0xff;
m_force_flg = false;
- update_flg();
+ if (update_flg()) {
+ // See reg_r above
+ machine().scheduler().perfect_quantum(attotime::from_usec(100));
+ machine().scheduler().synchronize();
+ }
}
-READ8_MEMBER(hp98034_io_card_device::switch_r)
+uint8_t hp98034_io_card_device::switch_r()
{
return m_sw1->read() | 0xc0;
}
-IRQ_CALLBACK_MEMBER(hp98034_io_card_device::irq_callback)
+uint8_t hp98034_io_card_device::int_ack_r()
{
int res = 0xff;
- if (irqline == 0 && !m_ieee488->ifc_r()) {
+ if (!m_ieee488->ifc_r()) {
BIT_CLR(res, 1);
}
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();
}
@@ -284,13 +300,24 @@ void hp98034_io_card_device::update_dc()
{
irq_w(!BIT(m_dc , 0));
sts_w(BIT(m_dc , 4));
- update_flg();
+ if (update_flg()) {
+ // See reg_r above
+ machine().scheduler().perfect_quantum(attotime::from_usec(100));
+ machine().scheduler().synchronize();
+ }
update_clr_hpib();
}
-void hp98034_io_card_device::update_flg()
+bool hp98034_io_card_device::update_flg()
{
- flg_w(BIT(m_dc , 3) && !m_force_flg);
+ bool new_flg = BIT(m_dc , 3) && !m_force_flg;
+ if (new_flg != m_flg) {
+ m_flg = new_flg;
+ flg_w(m_flg);
+ return true;
+ } else {
+ return false;
+ }
}
void hp98034_io_card_device::update_np_irq()
@@ -303,7 +330,7 @@ void hp98034_io_card_device::update_data_out()
if (m_clr_hpib) {
m_data_out = 0;
}
- m_ieee488->write_dio(~m_data_out);
+ m_ieee488->host_dio_w(~m_data_out);
}
void hp98034_io_card_device::update_ctrl_out()
@@ -331,7 +358,6 @@ void hp98034_io_card_device::update_clr_hpib()
update_data_out();
update_ctrl_out();
update_np_irq();
- LOG("clr_hpib %d\n" , m_clr_hpib);
}
ROM_START(hp98034)
@@ -366,13 +392,14 @@ const tiny_rom_entry *hp98034_io_card_device::device_rom_region() const
void hp98034_io_card_device::device_add_mconfig(machine_config &config)
{
// Clock for NP is generated by a RC oscillator. Manual says its typical frequency
- // is around 2 MHz.
- HP_NANOPROCESSOR(config, m_cpu, 2000000);
+ // is around 2 MHz. A quick simulation of the oscillator gives the following data though:
+ // 2.5 MHz frequency, 33% duty cycle.
+ HP_NANOPROCESSOR(config, m_cpu, 2500000);
m_cpu->set_addrmap(AS_PROGRAM, &hp98034_io_card_device::np_program_map);
m_cpu->set_addrmap(AS_IO, &hp98034_io_card_device::np_io_map);
m_cpu->dc_changed().set(FUNC(hp98034_io_card_device::dc_w));
m_cpu->read_dc().set(FUNC(hp98034_io_card_device::dc_r));
- m_cpu->set_irq_acknowledge_callback(FUNC(hp98034_io_card_device::irq_callback));
+ m_cpu->int_ack().set(FUNC(hp98034_io_card_device::int_ack_r));
IEEE488_SLOT(config , "ieee_dev" , 0 , hp_ieee488_devices , nullptr);
IEEE488_SLOT(config , "ieee_rem" , 0 , remote488_devices , nullptr);
diff --git a/src/devices/bus/hp9845_io/98034.h b/src/devices/bus/hp9845_io/98034.h
index 45efc059a3a..1313c182735 100644
--- a/src/devices/bus/hp9845_io/98034.h
+++ b/src/devices/bus/hp9845_io/98034.h
@@ -17,7 +17,7 @@
#include "cpu/nanoprocessor/nanoprocessor.h"
#include "bus/ieee488/ieee488.h"
-class hp98034_io_card_device : public hp9845_io_card_device
+class hp98034_io_card_device : public device_t, public device_hp9845_io_interface
{
public:
// construction/destruction
@@ -25,37 +25,36 @@ public:
virtual ~hp98034_io_card_device();
protected:
- virtual void device_start() override;
- virtual void device_reset() override;
+ virtual void device_start() override ATTR_COLD;
+ virtual void device_reset() override ATTR_COLD;
// device-level overrides
- 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 ioport_constructor device_input_ports() const override ATTR_COLD;
+ virtual const tiny_rom_entry *device_rom_region() const override ATTR_COLD;
+ virtual void device_add_mconfig(machine_config &config) override ATTR_COLD;
- virtual DECLARE_READ16_MEMBER(reg_r) override;
- virtual DECLARE_WRITE16_MEMBER(reg_w) override;
+ virtual uint16_t reg_r(address_space &space, offs_t offset) override;
+ virtual void reg_w(address_space &space, offs_t offset, uint16_t data) override;
private:
- DECLARE_WRITE8_MEMBER(dc_w);
- DECLARE_READ8_MEMBER(dc_r);
+ void dc_w(uint8_t data);
+ uint8_t dc_r();
+ uint8_t int_ack_r();
- DECLARE_WRITE8_MEMBER(hpib_data_w);
- DECLARE_WRITE8_MEMBER(hpib_ctrl_w);
- DECLARE_READ8_MEMBER(hpib_ctrl_r);
- DECLARE_READ8_MEMBER(hpib_data_r);
- DECLARE_READ8_MEMBER(idr_r);
- DECLARE_WRITE8_MEMBER(odr_w);
- DECLARE_READ8_MEMBER(mode_reg_r);
- DECLARE_WRITE8_MEMBER(mode_reg_clear_w);
- DECLARE_READ8_MEMBER(switch_r);
+ void hpib_data_w(uint8_t data);
+ void hpib_ctrl_w(uint8_t data);
+ uint8_t hpib_ctrl_r();
+ uint8_t hpib_data_r();
+ uint8_t idr_r();
+ void odr_w(uint8_t data);
+ uint8_t mode_reg_r();
+ void mode_reg_clear_w(uint8_t data);
+ uint8_t switch_r();
- void np_io_map(address_map &map);
- void np_program_map(address_map &map);
+ void np_io_map(address_map &map) ATTR_COLD;
+ void np_program_map(address_map &map) ATTR_COLD;
- IRQ_CALLBACK_MEMBER(irq_callback);
-
- DECLARE_WRITE_LINE_MEMBER(ieee488_ctrl_w);
+ void ieee488_ctrl_w(int state);
required_device<hp_nanoprocessor_device> m_cpu;
required_ioport m_sw1;
@@ -69,6 +68,7 @@ private:
uint8_t m_odr; // Output Data Register
bool m_force_flg;
uint8_t m_mode_reg;
+ bool m_flg;
// 488 bus state
bool m_clr_hpib;
@@ -76,7 +76,7 @@ private:
uint8_t m_data_out;
void update_dc();
- void update_flg();
+ bool update_flg();
void update_np_irq();
void update_data_out();
void update_ctrl_out();
diff --git a/src/devices/bus/hp9845_io/98035.cpp b/src/devices/bus/hp9845_io/98035.cpp
index 891ff92a167..79017edd4c2 100644
--- a/src/devices/bus/hp9845_io/98035.cpp
+++ b/src/devices/bus/hp9845_io/98035.cpp
@@ -143,7 +143,8 @@ static const uint8_t dec_2_seven_segs[] = {
};
hp98035_io_card_device::hp98035_io_card_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
- : hp9845_io_card_device(mconfig , HP98035_IO_CARD , tag , owner , clock),
+ : device_t(mconfig , HP98035_IO_CARD , tag , owner , clock),
+ device_hp9845_io_interface(mconfig, *this),
device_rtc_interface(mconfig , *this),
m_cpu(*this , "np")
{
@@ -185,14 +186,12 @@ void hp98035_io_card_device::device_start()
save_item(NAME(m_prev_clock_keys));
save_item(NAME(m_clock_key_cnt));
- m_msec_timer = timer_alloc(MSEC_TMR_ID);
- m_clock_timer = timer_alloc(CLOCK_TMR_ID);
+ m_msec_timer = timer_alloc(FUNC(hp98035_io_card_device::msec_tick), this);
+ m_clock_timer = timer_alloc(FUNC(hp98035_io_card_device::clock_tick), this);
}
void hp98035_io_card_device::device_reset()
{
- hp9845_io_card_device::device_reset();
-
m_idr_full = false;
m_idr = 0;
m_odr = 0;
@@ -208,54 +207,55 @@ void hp98035_io_card_device::device_reset()
half_init();
}
-void hp98035_io_card_device::device_timer(emu_timer &timer, device_timer_id id, int param, void *ptr)
+TIMER_CALLBACK_MEMBER(hp98035_io_card_device::msec_tick)
{
- if (id == MSEC_TMR_ID) {
- // On real hw there's a full 4-bit decimal counter, but only the LSB is used to
- // generate interrupts
- m_np_irq = !m_np_irq;
- update_dc();
- } else if (id == CLOCK_TMR_ID) {
- // Update digit multiplexer
- if (m_clock_state == CLOCK_OFF) {
- m_clock_mux = 0;
- } else {
- m_clock_mux <<= 1;
- if ((m_clock_mux & 7) == 0) {
- m_clock_mux = 1;
- }
- }
- // Act on clock chip "keys"
- if (m_clock_keys == 0 || m_clock_keys != m_prev_clock_keys) {
- m_clock_key_cnt = 0;
- if (m_clock_keys == 0 && m_clock_state == CLOCK_HHMM) {
- // Keys released in HHMM state -> turn display off
- // In real hw there is probably 1 s delay
- m_clock_state = CLOCK_OFF;
- regen_clock_image();
- }
- } else if (m_clock_key_cnt < KEY_PRESS_LONG) {
- m_clock_key_cnt++;
- if (m_clock_key_cnt == KEY_PRESS_SHORT) {
- /// Short key press
- clock_short_press();
- } else if (m_clock_key_cnt == KEY_PRESS_LONG) {
- // Long key press
- clock_long_press();
- }
+ // On real hw there's a full 4-bit decimal counter, but only the LSB is used to
+ // generate interrupts
+ m_np_irq = !m_np_irq;
+ update_dc();
+}
+
+TIMER_CALLBACK_MEMBER(hp98035_io_card_device::clock_tick)
+{
+ // Update digit multiplexer
+ if (m_clock_state == CLOCK_OFF) {
+ m_clock_mux = 0;
+ } else {
+ m_clock_mux <<= 1;
+ if ((m_clock_mux & 7) == 0) {
+ m_clock_mux = 1;
}
- m_prev_clock_keys = m_clock_keys;
- // Count seconds
- m_clock_1s_div++;
- if (m_clock_1s_div >= DIGIT_MUX_FREQ.value()) {
- m_clock_1s_div = 0;
- advance_seconds();
+ }
+ // Act on clock chip "keys"
+ if (m_clock_keys == 0 || m_clock_keys != m_prev_clock_keys) {
+ m_clock_key_cnt = 0;
+ if (m_clock_keys == 0 && m_clock_state == CLOCK_HHMM) {
+ // Keys released in HHMM state -> turn display off
+ // In real hw there is probably 1 s delay
+ m_clock_state = CLOCK_OFF;
regen_clock_image();
}
+ } else if (m_clock_key_cnt < KEY_PRESS_LONG) {
+ m_clock_key_cnt++;
+ if (m_clock_key_cnt == KEY_PRESS_SHORT) {
+ /// Short key press
+ clock_short_press();
+ } else if (m_clock_key_cnt == KEY_PRESS_LONG) {
+ // Long key press
+ clock_long_press();
+ }
+ }
+ m_prev_clock_keys = m_clock_keys;
+ // Count seconds
+ m_clock_1s_div++;
+ if (m_clock_1s_div >= DIGIT_MUX_FREQ.value()) {
+ m_clock_1s_div = 0;
+ advance_seconds();
+ regen_clock_image();
}
}
-READ16_MEMBER(hp98035_io_card_device::reg_r)
+uint16_t hp98035_io_card_device::reg_r(address_space &space, offs_t offset)
{
uint16_t res;
@@ -288,7 +288,7 @@ READ16_MEMBER(hp98035_io_card_device::reg_r)
return res;
}
-WRITE16_MEMBER(hp98035_io_card_device::reg_w)
+void hp98035_io_card_device::reg_w(address_space &space, offs_t offset, uint16_t data)
{
bool new_inten;
@@ -318,33 +318,33 @@ WRITE16_MEMBER(hp98035_io_card_device::reg_w)
LOG(("write R%u=%04x\n" , offset + 4 , data));
}
-WRITE8_MEMBER(hp98035_io_card_device::ram_addr_w)
+void hp98035_io_card_device::ram_addr_w(uint8_t data)
{
m_ram_addr = data;
}
-READ8_MEMBER(hp98035_io_card_device::ram_data_r)
+uint8_t hp98035_io_card_device::ram_data_r()
{
return m_np_ram[ m_ram_addr ];
}
-WRITE8_MEMBER(hp98035_io_card_device::ram_addr_data_w)
+void hp98035_io_card_device::ram_addr_data_w(uint8_t data)
{
m_ram_addr = data;
m_np_ram[ m_ram_addr ] = m_ram_data_in;
}
-WRITE8_MEMBER(hp98035_io_card_device::ram_data_w)
+void hp98035_io_card_device::ram_data_w(uint8_t data)
{
m_ram_data_in = data;
}
-WRITE8_MEMBER(hp98035_io_card_device::clock_key_w)
+void hp98035_io_card_device::clock_key_w(uint8_t data)
{
m_clock_keys = data & 7;
}
-READ8_MEMBER(hp98035_io_card_device::clock_digit_r)
+uint8_t hp98035_io_card_device::clock_digit_r()
{
switch (m_clock_mux) {
case 1:
@@ -361,20 +361,20 @@ READ8_MEMBER(hp98035_io_card_device::clock_digit_r)
}
}
-WRITE8_MEMBER(hp98035_io_card_device::odr_w)
+void hp98035_io_card_device::odr_w(uint8_t data)
{
m_odr = data;
set_flg(true);
}
-READ8_MEMBER(hp98035_io_card_device::idr_r)
+uint8_t hp98035_io_card_device::idr_r()
{
set_flg(true);
m_idr_full = false;
return m_idr;
}
-READ8_MEMBER(hp98035_io_card_device::np_status_r)
+uint8_t hp98035_io_card_device::np_status_r()
{
// Bit 2 = 0: use US date format
uint8_t res = 0x03;
@@ -397,13 +397,13 @@ READ8_MEMBER(hp98035_io_card_device::np_status_r)
return res;
}
-WRITE8_MEMBER(hp98035_io_card_device::clear_np_irq_w)
+void hp98035_io_card_device::clear_np_irq_w(uint8_t data)
{
m_np_irq = false;
update_dc();
}
-READ8_MEMBER(hp98035_io_card_device::clock_mux_r)
+uint8_t hp98035_io_card_device::clock_mux_r()
{
// External input lines are always active (bits 7-4)
uint8_t res = 0xf0 | m_clock_mux;
@@ -414,13 +414,13 @@ READ8_MEMBER(hp98035_io_card_device::clock_mux_r)
return res;
}
-WRITE8_MEMBER(hp98035_io_card_device::set_irq_w)
+void hp98035_io_card_device::set_irq_w(uint8_t data)
{
m_irq = true;
update_irq();
}
-READ8_MEMBER(hp98035_io_card_device::clr_inten_r)
+uint8_t hp98035_io_card_device::clr_inten_r()
{
m_intflag = false;
m_inten = false;
@@ -429,14 +429,14 @@ READ8_MEMBER(hp98035_io_card_device::clr_inten_r)
return 0xff;
}
-WRITE8_MEMBER(hp98035_io_card_device::clr_inten_w)
+void hp98035_io_card_device::clr_inten_w(uint8_t data)
{
m_intflag = false;
m_inten = false;
update_irq();
}
-WRITE8_MEMBER(hp98035_io_card_device::dc_w)
+void hp98035_io_card_device::dc_w(uint8_t data)
{
if (data != m_dc) {
//LOG(("DC=%02x\n" , data));
diff --git a/src/devices/bus/hp9845_io/98035.h b/src/devices/bus/hp9845_io/98035.h
index 40f91883406..b6a9fe40264 100644
--- a/src/devices/bus/hp9845_io/98035.h
+++ b/src/devices/bus/hp9845_io/98035.h
@@ -8,8 +8,8 @@
*********************************************************************/
-#ifndef MAME_BUS_HP_9845_IO_98035_H
-#define MAME_BUS_HP_9845_IO_98035_H
+#ifndef MAME_BUS_HP9845_IO_98035_H
+#define MAME_BUS_HP9845_IO_98035_H
#pragma once
@@ -17,7 +17,7 @@
#include "cpu/nanoprocessor/nanoprocessor.h"
#include "dirtc.h"
-class hp98035_io_card_device : public hp9845_io_card_device, public device_rtc_interface
+class hp98035_io_card_device : public device_t, public device_hp9845_io_interface, public device_rtc_interface
{
public:
// construction/destruction
@@ -25,40 +25,42 @@ public:
virtual ~hp98035_io_card_device();
protected:
- virtual void device_start() override;
- virtual void device_reset() override;
- virtual void device_timer(emu_timer &timer, device_timer_id id, int param, void *ptr) override;
+ virtual void device_start() override ATTR_COLD;
+ virtual void device_reset() override ATTR_COLD;
// device-level overrides
- 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 ioport_constructor device_input_ports() const override ATTR_COLD;
+ virtual const tiny_rom_entry *device_rom_region() const override ATTR_COLD;
+ virtual void device_add_mconfig(machine_config &config) override ATTR_COLD;
- virtual DECLARE_READ16_MEMBER(reg_r) override;
- virtual DECLARE_WRITE16_MEMBER(reg_w) override;
+ virtual uint16_t reg_r(address_space &space, offs_t offset) override;
+ virtual void reg_w(address_space &space, offs_t offset, uint16_t data) override;
private:
- DECLARE_WRITE8_MEMBER(dc_w);
+ void dc_w(uint8_t data);
- DECLARE_WRITE8_MEMBER(ram_addr_w);
- DECLARE_READ8_MEMBER(ram_data_r);
- DECLARE_WRITE8_MEMBER(ram_addr_data_w);
- DECLARE_WRITE8_MEMBER(ram_data_w);
+ void ram_addr_w(uint8_t data);
+ uint8_t ram_data_r();
+ void ram_addr_data_w(uint8_t data);
+ void ram_data_w(uint8_t data);
- DECLARE_WRITE8_MEMBER(clock_key_w);
- DECLARE_READ8_MEMBER(clock_digit_r);
+ void clock_key_w(uint8_t data);
+ uint8_t clock_digit_r();
- DECLARE_WRITE8_MEMBER(odr_w);
- DECLARE_READ8_MEMBER(idr_r);
- DECLARE_READ8_MEMBER(np_status_r);
- DECLARE_WRITE8_MEMBER(clear_np_irq_w);
- DECLARE_READ8_MEMBER(clock_mux_r);
- DECLARE_WRITE8_MEMBER(set_irq_w);
- DECLARE_READ8_MEMBER(clr_inten_r);
- DECLARE_WRITE8_MEMBER(clr_inten_w);
+ void odr_w(uint8_t data);
+ uint8_t idr_r();
+ uint8_t np_status_r();
+ void clear_np_irq_w(uint8_t data);
+ uint8_t clock_mux_r();
+ void set_irq_w(uint8_t data);
+ uint8_t clr_inten_r();
+ void clr_inten_w(uint8_t data);
- void np_io_map(address_map &map);
- void np_program_map(address_map &map);
+ TIMER_CALLBACK_MEMBER(msec_tick);
+ TIMER_CALLBACK_MEMBER(clock_tick);
+
+ void np_io_map(address_map &map) ATTR_COLD;
+ void np_program_map(address_map &map) ATTR_COLD;
required_device<hp_nanoprocessor_device> m_cpu;
@@ -123,4 +125,4 @@ private:
// device type definition
DECLARE_DEVICE_TYPE(HP98035_IO_CARD, hp98035_io_card_device)
-#endif // MAME_BUS_HP_9845_IO_98035_H
+#endif // MAME_BUS_HP9845_IO_98035_H
diff --git a/src/devices/bus/hp9845_io/98036.cpp b/src/devices/bus/hp9845_io/98036.cpp
new file mode 100644
index 00000000000..cd1544b0379
--- /dev/null
+++ b/src/devices/bus/hp9845_io/98036.cpp
@@ -0,0 +1,505 @@
+// license:BSD-3-Clause
+// copyright-holders: F. Ulivi
+/*********************************************************************
+
+ 98036.cpp
+
+ 98036 module (RS232 interface)
+
+ Main reference for this module:
+ HP, 98036A Serial I/O interface installation & service manual
+
+*********************************************************************/
+
+#include "emu.h"
+#include "98036.h"
+
+// Debugging
+#define VERBOSE 0
+#include "logmacro.h"
+
+// Bit manipulation
+namespace {
+ template <typename T> constexpr T BIT_MASK(unsigned n)
+ {
+ return T(1U) << n;
+ }
+
+ template <typename T> void BIT_SET(T &w, unsigned n)
+ {
+ w |= BIT_MASK<T>(n);
+ }
+}
+
+// device type definitions
+DEFINE_DEVICE_TYPE(HP98036_IO_CARD, hp98036_io_card_device, "hp98036", "HP98036 card")
+
+hp98036_io_card_device::hp98036_io_card_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
+ : device_t(mconfig, HP98036_IO_CARD, tag, owner, clock)
+ , device_hp9845_io_interface(mconfig, *this)
+ , m_uart(*this, "uart")
+ , m_clock_gen(*this, "clock_gen")
+ , m_rs232(*this, "rs232")
+ , m_s1_input(*this, "s1")
+ , m_s2_input(*this, "s2")
+ , m_s3_input(*this, "s3")
+ , m_jumper_input(*this, "jumper")
+ , m_loopback_en(*this, "loop")
+{
+}
+
+hp98036_io_card_device::~hp98036_io_card_device()
+{
+}
+
+uint16_t hp98036_io_card_device::reg_r(address_space &space, offs_t offset)
+{
+ uint16_t res = 0;
+
+ switch (offset) {
+ case 0:
+ // R4IN
+ m_r4_dir = false;
+ res = m_r4in_data;
+ break;
+
+ case 1:
+ // R5IN
+ if (m_tx_int_en) {
+ BIT_SET(res, 0);
+ }
+ if (m_rx_int_en) {
+ BIT_SET(res, 1);
+ }
+ BIT_SET(res, 4);
+ if (m_int_en) {
+ BIT_SET(res, 7);
+ }
+ break;
+
+ case 2:
+ // R6IN
+ // Bits 3&4: jumpers
+ res = (m_jumper_input->read() & 3) << 3;
+ if (m_loopback) {
+ res |= m_lineout;
+ } else {
+ if (!m_rs232->dcd_r()) {
+ BIT_SET(res, 0);
+ }
+ if (!m_rs232->ri_r()) {
+ BIT_SET(res, 1);
+ }
+ // Bit 2: secondary CD, always 0
+ }
+ BIT_SET(res, 5);
+ BIT_SET(res, 6);
+ BIT_SET(res, 7);
+ break;
+
+ default:
+ logerror("Unmapped read @%u\n", offset);
+ }
+
+ LOG("RD R%u=%02x\n", offset + 4, res);
+ return res;
+}
+
+void hp98036_io_card_device::reg_w(address_space &space, offs_t offset, uint16_t data)
+{
+ LOG("WR R%u=%02x\n", offset + 4, data);
+
+ switch (offset) {
+ case 0:
+ // R4OUT
+ m_r4_dir = true;
+ m_wrrq = true;
+ m_r4out_data = data;
+ uart_wr();
+ update_flg();
+ break;
+
+ case 1:
+ // R5OUT
+ m_uart_cmd = BIT(data, 0);
+ m_tx_int_en = BIT(data, 1);
+ m_rx_int_en = BIT(data, 2);
+ m_int_en = BIT(data, 7);
+ if (BIT(data, 5)) {
+ int_reset();
+ } else {
+ uart_rd();
+ uart_wr();
+ update_irq();
+ update_flg();
+ }
+ break;
+
+ case 2:
+ // R6OUT
+ m_half_baud = BIT(data, 4);
+ m_lineout = data & 7;
+ break;
+
+ case 3:
+ // R7OUT
+ if (!m_r4_dir) {
+ m_rdrq = true;
+ uart_rd();
+ update_irq();
+ update_flg();
+ }
+ break;
+
+ default:
+ logerror("Unmapped write @%u\n", offset);
+ break;
+ }
+}
+
+void hp98036_io_card_device::device_add_mconfig(machine_config &config)
+{
+ I8251(config, m_uart, 0);
+ m_uart->txd_handler().set(FUNC(hp98036_io_card_device::txd_w));
+ m_uart->dtr_handler().set(FUNC(hp98036_io_card_device::dtr_w));
+ m_uart->rts_handler().set(FUNC(hp98036_io_card_device::rts_w));
+ m_uart->rxrdy_handler().set(FUNC(hp98036_io_card_device::rxrdy_w));
+ m_uart->txrdy_handler().set(FUNC(hp98036_io_card_device::txrdy_w));
+
+ MC14411(config, m_clock_gen, 1.8432_MHz_XTAL);
+ m_clock_gen->out_f<1>().set(FUNC(hp98036_io_card_device::bit_rate_clock));
+ m_clock_gen->out_f<3>().set(FUNC(hp98036_io_card_device::bit_rate_clock));
+ m_clock_gen->out_f<5>().set(FUNC(hp98036_io_card_device::bit_rate_clock));
+ m_clock_gen->out_f<6>().set(FUNC(hp98036_io_card_device::bit_rate_clock));
+ m_clock_gen->out_f<7>().set(FUNC(hp98036_io_card_device::bit_rate_clock));
+ m_clock_gen->out_f<8>().set(FUNC(hp98036_io_card_device::bit_rate_clock));
+ m_clock_gen->out_f<9>().set(FUNC(hp98036_io_card_device::bit_rate_clock));
+ m_clock_gen->out_f<11>().set(FUNC(hp98036_io_card_device::bit_rate_clock));
+ m_clock_gen->out_f<13>().set(FUNC(hp98036_io_card_device::bit_rate_clock));
+ m_clock_gen->out_f<14>().set(FUNC(hp98036_io_card_device::bit_rate_clock));
+ m_clock_gen->out_f<12>().set(FUNC(hp98036_io_card_device::slow_clock));
+
+ RS232_PORT(config, m_rs232, default_rs232_devices, nullptr);
+ m_rs232->rxd_handler().set(FUNC(hp98036_io_card_device::rxd_w));
+ m_rs232->dsr_handler().set(FUNC(hp98036_io_card_device::dsr_w));
+ m_rs232->cts_handler().set(FUNC(hp98036_io_card_device::cts_w));
+}
+
+static INPUT_PORTS_START(hp98036_port)
+ PORT_HP9845_IO_SC(11)
+
+ PORT_START("s1")
+ PORT_DIPNAME(3, 3, "Clock factor")
+ PORT_DIPLOCATION("S1:1,2")
+ PORT_DIPSETTING(1, "x1")
+ PORT_DIPSETTING(2, "x16")
+ PORT_DIPSETTING(3, "x64")
+ PORT_DIPNAME(0x0c, 0x0c, "Character length")
+ PORT_DIPLOCATION("S1:3,4")
+ PORT_DIPSETTING(0x00, "5")
+ PORT_DIPSETTING(0x04, "6")
+ PORT_DIPSETTING(0x08, "7")
+ PORT_DIPSETTING(0x0c, "8")
+ PORT_DIPNAME(0x10, 0, "Parity enable")
+ PORT_DIPLOCATION("S1:5")
+ PORT_DIPSETTING(0x00, DEF_STR(Off))
+ PORT_DIPSETTING(0x10, DEF_STR(On))
+ PORT_DIPNAME(0x20, 0, "Parity")
+ PORT_DIPLOCATION("S1:6")
+ PORT_DIPSETTING(0x00, "Odd")
+ PORT_DIPSETTING(0x20, "Even")
+ PORT_DIPNAME(0xc0, 0xc0, "Stop bits")
+ PORT_DIPLOCATION("S1:7,8")
+ PORT_DIPSETTING(0x40, "1")
+ PORT_DIPSETTING(0x80, "1.5")
+ PORT_DIPSETTING(0xc0, "2")
+
+ PORT_START("s2")
+ PORT_DIPNAME(1, 1, "CTS")
+ PORT_DIPLOCATION("S2:1")
+ PORT_DIPSETTING(0, "Device controlled")
+ PORT_DIPSETTING(1, "Always active")
+
+ PORT_START("s3")
+ PORT_CONFNAME(0xf, 6, "Baud rate")
+ PORT_CONFSETTING(0, "9600")
+ PORT_CONFSETTING(1, "4800")
+ PORT_CONFSETTING(2, "2400")
+ PORT_CONFSETTING(3, "1800")
+ PORT_CONFSETTING(4, "1200")
+ PORT_CONFSETTING(5, "600")
+ PORT_CONFSETTING(6, "300")
+ PORT_CONFSETTING(7, "150")
+ PORT_CONFSETTING(8, "110")
+ PORT_CONFSETTING(9, "75")
+
+ PORT_START("jumper")
+ PORT_CONFNAME(1, 0, "J1")
+ PORT_CONFSETTING(0, DEF_STR(Off))
+ PORT_CONFSETTING(1, DEF_STR(On))
+ PORT_CONFNAME(2, 0, "J2")
+ PORT_CONFSETTING(0, DEF_STR(Off))
+ PORT_CONFSETTING(2, DEF_STR(On))
+
+ PORT_START("loop")
+ PORT_CONFNAME(1, 0, "Test loopback")
+ PORT_CONFSETTING(0, DEF_STR(Off))
+ PORT_CONFSETTING(1, DEF_STR(On))
+INPUT_PORTS_END
+
+ioport_constructor hp98036_io_card_device::device_input_ports() const
+{
+ return INPUT_PORTS_NAME(hp98036_port);
+}
+
+void hp98036_io_card_device::device_start()
+{
+ save_item(NAME(m_init_state));
+ save_item(NAME(m_irq));
+ save_item(NAME(m_int_en));
+ save_item(NAME(m_tx_int_en));
+ save_item(NAME(m_rx_int_en));
+ save_item(NAME(m_txrdy));
+ save_item(NAME(m_rxrdy));
+ save_item(NAME(m_wrrq));
+ save_item(NAME(m_rdrq));
+ save_item(NAME(m_uart_cmd));
+ save_item(NAME(m_uart_wr_mode));
+ save_item(NAME(m_flg));
+ save_item(NAME(m_half_baud));
+ save_item(NAME(m_baud_div));
+ save_item(NAME(m_r4_dir));
+ save_item(NAME(m_r4in_data));
+ save_item(NAME(m_r4out_data));
+ save_item(NAME(m_lineout));
+}
+
+void hp98036_io_card_device::device_reset()
+{
+ sts_w(true);
+
+ ioport_value const baud_sel = m_s3_input->read();
+ m_clock_gen->timer_enable(mc14411_device::TIMER_F1, baud_sel == 0);
+ m_clock_gen->timer_enable(mc14411_device::TIMER_F3, baud_sel == 1);
+ m_clock_gen->timer_enable(mc14411_device::TIMER_F5, baud_sel == 2);
+ m_clock_gen->timer_enable(mc14411_device::TIMER_F6, baud_sel == 3);
+ m_clock_gen->timer_enable(mc14411_device::TIMER_F7, baud_sel == 4);
+ m_clock_gen->timer_enable(mc14411_device::TIMER_F8, baud_sel == 5);
+ m_clock_gen->timer_enable(mc14411_device::TIMER_F9, baud_sel == 6);
+ m_clock_gen->timer_enable(mc14411_device::TIMER_F11, baud_sel == 7);
+ m_clock_gen->timer_enable(mc14411_device::TIMER_F13, baud_sel == 8);
+ m_clock_gen->timer_enable(mc14411_device::TIMER_F14, baud_sel == 9);
+
+ m_loopback = m_loopback_en->read() != 0;
+
+ if (!m_loopback && BIT(m_s2_input->read(), 0)) {
+ m_uart->write_cts(0);
+ }
+
+ int_reset();
+}
+
+void hp98036_io_card_device::bit_rate_clock(int state)
+{
+ if (m_half_baud) {
+ if (state) {
+ m_baud_div = !m_baud_div;
+ m_uart->write_txc(m_baud_div);
+ m_uart->write_rxc(m_baud_div);
+ }
+ } else {
+ m_uart->write_txc(state);
+ m_uart->write_rxc(state);
+ }
+}
+
+void hp98036_io_card_device::slow_clock(int state)
+{
+ switch (m_init_state) {
+ case 0:
+ // Reset
+ if (state) {
+ m_init_state++;
+ }
+ break;
+
+ case 1:
+ // Write mode word
+ if (state) {
+ m_init_state++;
+ } else {
+ write_uart(true, uint8_t(m_s1_input->read()));
+ }
+ break;
+
+ case 2:
+ // Write default control word
+ if (state) {
+ m_init_state++;
+ update_flg();
+ } else {
+ write_uart(true, 0x05);
+ }
+ break;
+
+ default:
+ break;
+ }
+}
+
+void hp98036_io_card_device::txd_w(int state)
+{
+ if (m_loopback) {
+ m_uart->write_rxd(state);
+ } else {
+ m_rs232->write_txd(state);
+ }
+}
+
+void hp98036_io_card_device::dtr_w(int state)
+{
+ if (m_loopback) {
+ m_uart->write_dsr(state);
+ } else {
+ m_rs232->write_dtr(state);
+ }
+}
+
+void hp98036_io_card_device::rts_w(int state)
+{
+ if (m_loopback) {
+ m_uart->write_cts(state);
+ } else {
+ m_rs232->write_rts(state);
+ }
+}
+
+void hp98036_io_card_device::txrdy_w(int state)
+{
+ if (m_txrdy != state) {
+ m_txrdy = state;
+ LOG("txrdy %d\n", m_txrdy);
+ uart_wr();
+ update_irq();
+ update_flg();
+ }
+}
+
+void hp98036_io_card_device::rxrdy_w(int state)
+{
+ if (m_rxrdy != state) {
+ m_rxrdy = state;
+ LOG("rxrdy %d\n", m_rxrdy);
+ uart_rd();
+ update_irq();
+ update_flg();
+ }
+}
+
+void hp98036_io_card_device::rxd_w(int state)
+{
+ if (!m_loopback) {
+ m_uart->write_rxd(state);
+ }
+}
+
+void hp98036_io_card_device::dsr_w(int state)
+{
+ if (!m_loopback) {
+ m_uart->write_dsr(state);
+ }
+}
+
+void hp98036_io_card_device::cts_w(int state)
+{
+ if (!m_loopback && !BIT(m_s2_input->read(), 0)) {
+ m_uart->write_cts(state);
+ }
+}
+
+void hp98036_io_card_device::int_reset()
+{
+ m_init_state = 0;
+ m_r4in_data = 0;
+ m_r4out_data = 0;
+ m_wrrq = false;
+ m_rdrq = false;
+ m_int_en = false;
+ m_tx_int_en = false;
+ m_rx_int_en = false;
+ m_uart_cmd = false;
+ m_uart_wr_mode = true;
+ m_half_baud = false;
+ m_lineout = 0;
+ m_clock_gen->rate_select_w(0);
+ m_flg = true; // Ensure update in update_flg
+ update_flg();
+ m_irq = true; // Ensure update in update_irq
+ update_irq();
+ m_uart->reset();
+}
+
+void hp98036_io_card_device::update_flg()
+{
+ bool new_flg = (m_init_state == 3) && (!m_wrrq || m_tx_int_en) && (!m_rdrq || m_rx_int_en);
+
+ if (m_flg != new_flg) {
+ m_flg = new_flg;
+ LOG("FLG %d\n", m_flg);
+ flg_w(m_flg);
+ }
+}
+
+void hp98036_io_card_device::update_irq()
+{
+ bool new_irq = m_int_en && ((m_tx_int_en && m_txrdy) || (m_rx_int_en && !m_rdrq));
+
+ if (m_irq != new_irq) {
+ m_irq = new_irq;
+ LOG("IRQ %d\n", m_irq);
+ irq_w(m_irq);
+ }
+}
+
+void hp98036_io_card_device::uart_rd()
+{
+ if (m_rdrq && (m_rxrdy || m_uart_cmd)) {
+ m_rdrq = false;
+ m_r4in_data = m_uart->read(m_uart_cmd);
+ LOG("uart rd%d=%02x\n", m_uart_cmd, m_r4in_data);
+ update_flg();
+ }
+}
+
+void hp98036_io_card_device::uart_wr()
+{
+ if (m_wrrq && (m_txrdy || m_uart_cmd)) {
+ m_wrrq = false;
+ write_uart(m_uart_cmd, m_r4out_data);
+ update_flg();
+ }
+}
+
+void hp98036_io_card_device::write_uart(bool cmd, uint8_t data)
+{
+ if (cmd && m_uart_wr_mode) {
+ // Capture bits 1 & 0 of mode word (clock factor) and
+ // adjust rate selection in clock generator
+ // Mode word RSB/RSA Factor
+ // 0 0 0 0 -- INVALID --
+ // 0 1 0 0 x1
+ // 1 0 1 0 x16
+ // 1 1 1 1 x64
+ m_clock_gen->rate_select_w((BIT(data, 1) ? mc14411_device::RSB : 0) | ((BIT(data, 1) && BIT(data, 0)) ? mc14411_device::RSA : 0));
+ LOG("RS %u\n", data & 3);
+ }
+ if (cmd) {
+ if (BIT(data, 6)) {
+ m_uart_wr_mode = !m_uart_wr_mode;
+ } else {
+ m_uart_wr_mode = false;
+ }
+ }
+ LOG("uart wr%d=%02x\n", cmd, data);
+ m_uart->write(cmd, data);
+}
diff --git a/src/devices/bus/hp9845_io/98036.h b/src/devices/bus/hp9845_io/98036.h
new file mode 100644
index 00000000000..e13ef2a9bdd
--- /dev/null
+++ b/src/devices/bus/hp9845_io/98036.h
@@ -0,0 +1,96 @@
+// license:BSD-3-Clause
+// copyright-holders: F. Ulivi
+/*********************************************************************
+
+ 98036.h
+
+ 98036 module (RS232 interface)
+
+*********************************************************************/
+
+#ifndef MAME_BUS_HP9845_IO_98036_H
+#define MAME_BUS_HP9845_IO_98036_H
+
+#pragma once
+
+#include "hp9845_io.h"
+#include "machine/i8251.h"
+#include "machine/mc14411.h"
+#include "bus/rs232/rs232.h"
+
+class hp98036_io_card_device : public device_t, public device_hp9845_io_interface
+{
+public:
+ // construction/destruction
+ hp98036_io_card_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
+ virtual ~hp98036_io_card_device();
+
+ virtual uint16_t reg_r(address_space &space, offs_t offset) override;
+ virtual void reg_w(address_space &space, offs_t offset, uint16_t data) override;
+
+protected:
+ // device-level overrides
+ virtual void device_add_mconfig(machine_config &config) override ATTR_COLD;
+ virtual ioport_constructor device_input_ports() const override ATTR_COLD;
+ virtual void device_start() override ATTR_COLD;
+ virtual void device_reset() override ATTR_COLD;
+
+private:
+ required_device<i8251_device> m_uart;
+ required_device<mc14411_device> m_clock_gen;
+ required_device<rs232_port_device> m_rs232;
+ required_ioport m_s1_input;
+ required_ioport m_s2_input;
+ required_ioport m_s3_input;
+ required_ioport m_jumper_input;
+ required_ioport m_loopback_en;
+
+ 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
+ // 0 0 0
+ // 1 1 0 Load mode word
+ // 2 1 1 Load control word
+ // 3 0 1 Done
+ uint8_t m_init_state;
+ bool m_irq; // U9-2
+ bool m_int_en; // U10-2
+ bool m_tx_int_en; // U10-10
+ bool m_rx_int_en; // U10-7
+ bool m_txrdy; // U31-15
+ bool m_rxrdy; // U31-14
+ bool m_wrrq; // U19-13
+ bool m_rdrq; // U19-7
+ bool m_uart_cmd; // U10-15
+ bool m_uart_wr_mode;// U17-15
+ bool m_flg; // U9-10
+ bool m_half_baud; // U21-13
+ bool m_baud_div; // U21-1
+ bool m_r4_dir; // U19-4
+ bool m_loopback;
+ uint8_t m_r4in_data; // U29, U30
+ uint8_t m_r4out_data; // U26, U27
+ uint8_t m_lineout; // U28
+
+ void int_reset();
+ void update_flg();
+ void update_irq();
+ void uart_rd();
+ void uart_wr();
+ void write_uart(bool cmd, uint8_t data);
+};
+
+// device type definitions
+DECLARE_DEVICE_TYPE(HP98036_IO_CARD, hp98036_io_card_device)
+
+#endif // MAME_BUS_HP9845_IO_98036_H
diff --git a/src/devices/bus/hp9845_io/98046.cpp b/src/devices/bus/hp9845_io/98046.cpp
index 6a45a83e3df..4b40850d95d 100644
--- a/src/devices/bus/hp9845_io/98046.cpp
+++ b/src/devices/bus/hp9845_io/98046.cpp
@@ -55,21 +55,18 @@ namespace {
}
}
-// Timers
-enum {
- TMR_ID_RXC,
- TMR_ID_TXC
-};
-
// device type definition
DEFINE_DEVICE_TYPE(HP98046_IO_CARD, hp98046_io_card_device , "hp98046" , "HP98046 card")
hp98046_io_card_device::hp98046_io_card_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
- : hp9845_io_card_device(mconfig , HP98046_IO_CARD , tag , owner , clock)
- , m_cpu(*this , "cpu")
- , m_sio(*this , "sio")
- , m_rs232(*this , "rs232")
- , m_loopback_en(*this , "loop")
+ : device_t(mconfig, HP98046_IO_CARD, tag, owner, clock)
+ , device_hp9845_io_interface(mconfig, *this)
+ , m_cpu(*this, "cpu")
+ , m_sio(*this, "sio")
+ , m_rs232(*this, "rs232")
+ , m_tx_brg(*this , "tx_brg")
+ , m_rx_brg(*this , "rx_brg")
+ , m_loopback_en(*this, "loop")
{
}
@@ -77,7 +74,7 @@ hp98046_io_card_device::~hp98046_io_card_device()
{
}
-READ16_MEMBER(hp98046_io_card_device::reg_r)
+uint16_t hp98046_io_card_device::reg_r(address_space &space, offs_t offset)
{
uint16_t res = 0;
@@ -128,7 +125,7 @@ READ16_MEMBER(hp98046_io_card_device::reg_r)
return res;
}
-WRITE16_MEMBER(hp98046_io_card_device::reg_w)
+void hp98046_io_card_device::reg_w(address_space &space, offs_t offset, uint16_t data)
{
LOG_CPU("wr R%u=%04x\n" , offset + 4 , data);
@@ -194,7 +191,16 @@ void hp98046_io_card_device::device_add_mconfig(machine_config &config)
m_rs232->dcd_handler().set(FUNC(hp98046_io_card_device::rs232_dcd_w));
m_rs232->dsr_handler().set(FUNC(hp98046_io_card_device::rs232_dsr_w));
m_rs232->cts_handler().set(FUNC(hp98046_io_card_device::rs232_cts_w));
- config.m_minimum_quantum = attotime::from_hz(5000);
+ m_rs232->rxc_handler().set(FUNC(hp98046_io_card_device::rs232_rxc_w));
+ m_rs232->txc_handler().set(FUNC(hp98046_io_card_device::rs232_txc_w));
+ // There's just one 2.4576 MHz xtal, Tx BRG gets its clock from Rx BRG
+ F4702(config , m_tx_brg , 2.4576_MHz_XTAL);
+ m_tx_brg->s_callback().set([this]() { return m_txc_sel; });
+ m_tx_brg->z_callback().set(FUNC(hp98046_io_card_device::txc_w));
+ F4702(config , m_rx_brg , 2.4576_MHz_XTAL);
+ m_rx_brg->s_callback().set([this]() { return m_rxc_sel; });
+ m_rx_brg->z_callback().set(FUNC(hp98046_io_card_device::rxc_w));
+ config.set_maximum_quantum(attotime::from_hz(307200));
}
static INPUT_PORTS_START(hp98046_port)
@@ -232,9 +238,6 @@ void hp98046_io_card_device::device_start()
{
m_ram = std::make_unique<uint8_t[]>(1024);
save_pointer(NAME(m_ram) , 1024);
-
- m_rxc_timer = timer_alloc(TMR_ID_RXC);
- m_txc_timer = timer_alloc(TMR_ID_TXC);
}
void hp98046_io_card_device::device_reset()
@@ -246,36 +249,6 @@ void hp98046_io_card_device::device_reset()
update_sts();
update_irq();
m_loopback = m_loopback_en->read() != 0;
- // Ensure timers are loaded the 1st time BRGs are configured
- m_rxc_sel = ~0;
- m_txc_sel = ~0;
- m_rxc_timer->reset();
- m_txc_timer->reset();
-}
-
-void hp98046_io_card_device::device_timer(emu_timer &timer, device_timer_id id, int param, void *ptr)
-{
- switch (id) {
- case TMR_ID_RXC:
- m_rxc = !m_rxc;
- m_sio->rxca_w(m_rxc);
- if (m_loopback && (m_txc_sel == 0 || m_txc_sel == 1)) {
- m_sio->txca_w(m_rxc);
- m_sio->txcb_w(m_rxc);
- m_sio->rxcb_w(m_rxc);
- }
- break;
-
- case TMR_ID_TXC:
- m_txc = !m_txc;
- m_sio->txca_w(m_txc);
- m_sio->txcb_w(m_txc);
- m_sio->rxcb_w(m_txc);
- if (m_loopback && (m_rxc_sel == 0 || m_rxc_sel == 1)) {
- m_sio->rxca_w(m_txc);
- }
- break;
- }
}
void hp98046_io_card_device::cpu_program_map(address_map &map)
@@ -290,12 +263,12 @@ void hp98046_io_card_device::cpu_io_map(address_map &map)
map(0 , 0xff).rw(FUNC(hp98046_io_card_device::cpu_r) , FUNC(hp98046_io_card_device::cpu_w));
}
-READ8_MEMBER(hp98046_io_card_device::ram_r)
+uint8_t hp98046_io_card_device::ram_r(offs_t offset)
{
return m_ram[ offset ];
}
-READ8_MEMBER(hp98046_io_card_device::cpu_r)
+uint8_t hp98046_io_card_device::cpu_r(offs_t offset)
{
if (BIT(m_port_2 , 2)) {
return m_ram[ (offset & 0xff) | (uint16_t(m_port_2 & 3) << 8) ];
@@ -341,7 +314,7 @@ READ8_MEMBER(hp98046_io_card_device::cpu_r)
}
}
-WRITE8_MEMBER(hp98046_io_card_device::cpu_w)
+void hp98046_io_card_device::cpu_w(offs_t offset, uint8_t data)
{
if (BIT(m_port_2 , 2)) {
m_ram[ (offset & 0xff) | (uint16_t(m_port_2 & 3) << 8) ] = data;
@@ -404,7 +377,8 @@ WRITE8_MEMBER(hp98046_io_card_device::cpu_w)
case 3:
// xxxx'x111: write to BRGs
- set_brgs(data);
+ m_rxc_sel = (data >> 4) & 0xf;
+ m_txc_sel = data & 0xf;
break;
}
} else {
@@ -413,7 +387,7 @@ WRITE8_MEMBER(hp98046_io_card_device::cpu_w)
}
}
-READ8_MEMBER(hp98046_io_card_device::p1_r)
+uint8_t hp98046_io_card_device::p1_r()
{
uint8_t res = 0;
// b7: b8 of word @ txFIFO head
@@ -452,7 +426,7 @@ READ8_MEMBER(hp98046_io_card_device::p1_r)
return res;
}
-WRITE8_MEMBER(hp98046_io_card_device::p2_w)
+void hp98046_io_card_device::p2_w(uint8_t data)
{
LOG_MCU("p2=%02x\n" , data);
uint8_t diff = data ^ m_port_2;
@@ -472,7 +446,7 @@ WRITE8_MEMBER(hp98046_io_card_device::p2_w)
}
}
-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);
@@ -480,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) {
@@ -490,34 +464,48 @@ 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);
}
}
+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);
+ }
+}
+
+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);
+ }
+}
+
bool hp98046_io_card_device::rx_fifo_flag() const
{
return m_rx_fifo.queue_length() >= 16;
@@ -642,43 +630,36 @@ uint8_t hp98046_io_card_device::get_hs_input() const
return res;
}
-// Frequencies of HD4702 BRGs
-// All frequencies are doubled here because the timers expire twice per RxC/TxC period
-static const unsigned brg_freq[] = {
- // Sel: frequency Divisor
- // ============================
- 0, // 0: external clock -
- 0, // 1: external clock -
- 1600, // 2: 50 x16 /3072
- 2400, // 3: 75 x16 /2048
- 4267, // 4: ~134.5 x16 /1152
- 6400, // 5: 200 x16 /768
- 19200, // 6: 600 x16 /256
- 76800, // 7: 2400 x16 /64
- 307200, // 8: 9600 x16 /16
- 153600, // 9: 4800 x16 /32
- 57600, // 10: 1800 x16 / 256/3
- 38400, // 11: 1200 x16 /128
- 76800, // 12: 2400 x16 /64
- 9600, // 13: 300 x16 /512
- 4800, // 14: 150 x16 /1024
- 3491 // 15: ~110 x16 /1408
-};
-
-void hp98046_io_card_device::set_brgs(uint8_t sel)
-{
- LOG_MCU("BRG=%02x\n" , sel);
- uint8_t new_rxc_sel = (sel >> 4) & 0xf;
- uint8_t new_txc_sel = sel & 0xf;
-
- if (new_rxc_sel != m_rxc_sel) {
- m_rxc_sel = new_rxc_sel;
- auto period = attotime::from_hz(brg_freq[ m_rxc_sel ]);
- m_rxc_timer->adjust(period , 0 , period);
- }
- if (new_txc_sel != m_txc_sel) {
- m_txc_sel = new_txc_sel;
- auto period = attotime::from_hz(brg_freq[ m_txc_sel ]);
- m_txc_timer->adjust(period , 0 , period);
+void hp98046_io_card_device::rxc_w(int state)
+{
+ if (m_last_rxc != bool(state)) {
+ m_last_rxc = bool(state);
+ m_sio->rxca_w(m_last_rxc);
+ if (m_loopback) {
+ machine().scheduler().synchronize(timer_expired_delegate(FUNC(hp98046_io_card_device::sync_tx_im_w) , this) , state);
+ }
}
}
+
+void hp98046_io_card_device::txc_w(int state)
+{
+ if (m_last_txc != bool(state)) {
+ m_last_txc = bool(state);
+ m_sio->txca_w(m_last_txc);
+ m_sio->txcb_w(m_last_txc);
+ m_sio->rxcb_w(m_last_txc);
+ if (m_loopback) {
+ machine().scheduler().synchronize(timer_expired_delegate(FUNC(hp98046_io_card_device::sync_rx_im_w) , this) , state);
+ }
+ }
+}
+
+TIMER_CALLBACK_MEMBER(hp98046_io_card_device::sync_rx_im_w)
+{
+ m_rx_brg->im_w(param);
+}
+
+TIMER_CALLBACK_MEMBER(hp98046_io_card_device::sync_tx_im_w)
+{
+ m_tx_brg->im_w(param);
+}
diff --git a/src/devices/bus/hp9845_io/98046.h b/src/devices/bus/hp9845_io/98046.h
index 7b6f9f1669d..73a8072d935 100644
--- a/src/devices/bus/hp9845_io/98046.h
+++ b/src/devices/bus/hp9845_io/98046.h
@@ -17,32 +17,34 @@
#include "cpu/mcs48/mcs48.h"
#include "machine/z80sio.h"
#include "bus/rs232/rs232.h"
+#include "machine/f4702.h"
-class hp98046_io_card_device : public hp9845_io_card_device
+class hp98046_io_card_device : public device_t, public device_hp9845_io_interface
{
public:
// construction/destruction
hp98046_io_card_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
virtual ~hp98046_io_card_device();
- virtual DECLARE_READ16_MEMBER(reg_r) override;
- virtual DECLARE_WRITE16_MEMBER(reg_w) override;
+ virtual uint16_t reg_r(address_space &space, offs_t offset) override;
+ virtual void reg_w(address_space &space, offs_t offset, uint16_t data) override;
virtual bool has_dual_sc() const override;
protected:
// 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;
- virtual void device_start() override;
- virtual void device_reset() override;
- virtual void device_timer(emu_timer &timer, device_timer_id id, int param, void *ptr) override;
+ virtual void device_add_mconfig(machine_config &config) override ATTR_COLD;
+ virtual ioport_constructor device_input_ports() const override ATTR_COLD;
+ virtual const tiny_rom_entry *device_rom_region() const override ATTR_COLD;
+ virtual void device_start() override ATTR_COLD;
+ virtual void device_reset() override ATTR_COLD;
private:
required_device<i8048_device> m_cpu;
required_device<z80sio_device> m_sio;
required_device<rs232_port_device> m_rs232;
+ required_device<f4702_device> m_tx_brg;
+ required_device<f4702_device> m_rx_brg;
required_ioport m_loopback_en;
std::unique_ptr<uint8_t[]> m_ram;
@@ -64,27 +66,27 @@ private:
bool m_sio_int;
uint8_t m_port_2;
bool m_loopback;
+ bool m_last_rxc;
+ bool m_last_txc;
- emu_timer *m_rxc_timer;
- emu_timer *m_txc_timer;
uint8_t m_rxc_sel;
uint8_t m_txc_sel;
- bool m_rxc;
- bool m_txc;
-
- void cpu_program_map(address_map &map);
- void cpu_io_map(address_map &map);
- DECLARE_READ8_MEMBER(ram_r);
- DECLARE_READ8_MEMBER(cpu_r);
- DECLARE_WRITE8_MEMBER(cpu_w);
- DECLARE_READ8_MEMBER(p1_r);
- DECLARE_WRITE8_MEMBER(p2_w);
- 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);
+
+ void cpu_program_map(address_map &map) ATTR_COLD;
+ void cpu_io_map(address_map &map) ATTR_COLD;
+ uint8_t ram_r(offs_t offset);
+ uint8_t cpu_r(offs_t offset);
+ void cpu_w(offs_t offset, uint8_t data);
+ uint8_t p1_r();
+ void p2_w(uint8_t data);
+ 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();
@@ -94,7 +96,10 @@ private:
void load_tx_fifo();
void set_r6_r7_pending(bool state);
uint8_t get_hs_input() const;
- void set_brgs(uint8_t sel);
+ void rxc_w(int state);
+ void txc_w(int state);
+ TIMER_CALLBACK_MEMBER(sync_rx_im_w);
+ TIMER_CALLBACK_MEMBER(sync_tx_im_w);
};
// device type definitions
diff --git a/src/devices/bus/hp9845_io/hp9845_io.cpp b/src/devices/bus/hp9845_io/hp9845_io.cpp
index 663c8fd9977..6962dea066e 100644
--- a/src/devices/bus/hp9845_io/hp9845_io.cpp
+++ b/src/devices/bus/hp9845_io/hp9845_io.cpp
@@ -10,11 +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")
@@ -23,7 +26,7 @@ DEFINE_DEVICE_TYPE(HP9845_IO_SLOT, hp9845_io_slot_device, "hp98x5_io_slot", "HP9
// +---------------------+
hp9845_io_slot_device::hp9845_io_slot_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) :
device_t(mconfig, HP9845_IO_SLOT, tag, owner, clock),
- device_slot_interface(mconfig, *this),
+ device_single_card_slot_interface<device_hp9845_io_interface>(mconfig, *this),
m_irq_cb_func(*this),
m_sts_cb_func(*this),
m_flg_cb_func(*this),
@@ -36,6 +39,7 @@ hp9845_io_slot_device::hp9845_io_slot_device(const machine_config &mconfig, cons
option_add("98032_gpio" , HP98032_IO_CARD);
option_add("98034_hpib" , HP98034_IO_CARD);
option_add("98035_rtc" , HP98035_IO_CARD);
+ option_add("98036" , HP98036_IO_CARD);
option_add("98046" , HP98046_IO_CARD);
set_default_option(nullptr);
set_fixed(false);
@@ -47,63 +51,55 @@ 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();
-
- hp9845_io_card_device *card = dynamic_cast<hp9845_io_card_device*>(get_card_device());
+ device_hp9845_io_interface *card = get_card_device();
if (card != nullptr) {
- card->set_slot_device(this);
+ card->set_slot_device(*this);
}
}
-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);
}
-int hp9845_io_slot_device::get_rw_handlers(read16_delegate& rhandler , write16_delegate& whandler)
+int hp9845_io_slot_device::get_rw_handlers(read16m_delegate& rhandler , write16m_delegate& whandler)
{
- hp9845_io_card_device *card = dynamic_cast<hp9845_io_card_device*>(get_card_device());
+ device_hp9845_io_interface *card = get_card_device();
- if (card != nullptr) {
- rhandler = read16_delegate(FUNC(hp9845_io_card_device::reg_r) , card);
- whandler = write16_delegate(FUNC(hp9845_io_card_device::reg_w) , card);
+ if (card) {
+ rhandler = read16m_delegate(*card, FUNC(device_hp9845_io_interface::reg_r));
+ whandler = write16m_delegate(*card, FUNC(device_hp9845_io_interface::reg_w));
return card->get_sc();
} else {
return -1;
@@ -112,88 +108,93 @@ int hp9845_io_slot_device::get_rw_handlers(read16_delegate& rhandler , write16_d
bool hp9845_io_slot_device::has_dual_sc() const
{
- hp9845_io_card_device *card = dynamic_cast<hp9845_io_card_device*>(get_card_device());
+ device_hp9845_io_interface *card = get_card_device();
- if (card != nullptr) {
+ if (card) {
return card->has_dual_sc();
} else {
return false;
}
}
-// +---------------------+
-// |hp9845_io_card_device|
-// +---------------------+
-void hp9845_io_card_device::set_slot_device(hp9845_io_slot_device* dev)
+// +--------------------------+
+// |device_hp9845_io_interface|
+// +--------------------------+
+void device_hp9845_io_interface::set_slot_device(hp9845_io_slot_device &dev)
{
- m_slot_dev = dev;
+ m_slot_dev = &dev;
}
-uint8_t hp9845_io_card_device::get_sc(void)
+uint8_t device_hp9845_io_interface::get_sc()
{
return m_select_code_port->read() + HP9845_IO_FIRST_SC;
}
-bool hp9845_io_card_device::has_dual_sc() const
+bool device_hp9845_io_interface::has_dual_sc() const
{
return false;
}
-hp9845_io_card_device::hp9845_io_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_slot_card_interface(mconfig, *this),
+device_hp9845_io_interface::device_hp9845_io_interface(const machine_config &mconfig, device_t &device) :
+ device_interface(device, "hp9845io"),
m_slot_dev(nullptr),
m_select_code_port(*this , "SC")
{
}
-hp9845_io_card_device::~hp9845_io_card_device()
+device_hp9845_io_interface::~device_hp9845_io_interface()
+{
+}
+
+void device_hp9845_io_interface::interface_pre_start()
{
+ if (!m_slot_dev)
+ throw device_missing_dependencies();
}
-WRITE_LINE_MEMBER(hp9845_io_card_device::irq_w)
+void device_hp9845_io_interface::irq_w(int state)
{
if (m_slot_dev) {
m_slot_dev->irq_w(state);
}
}
-WRITE_LINE_MEMBER(hp9845_io_card_device::sts_w)
+void device_hp9845_io_interface::sts_w(int state)
{
if (m_slot_dev) {
m_slot_dev->sts_w(state);
}
}
-WRITE_LINE_MEMBER(hp9845_io_card_device::flg_w)
+void device_hp9845_io_interface::flg_w(int state)
{
if (m_slot_dev) {
m_slot_dev->flg_w(state);
}
}
-WRITE_LINE_MEMBER(hp9845_io_card_device::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(hp9845_io_card_device::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(hp9845_io_card_device::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(hp9845_io_card_device::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 c62c8625563..77f4b32fc5a 100644
--- a/src/devices/bus/hp9845_io/hp9845_io.h
+++ b/src/devices/bus/hp9845_io/hp9845_io.h
@@ -31,17 +31,16 @@
PORT_CONFSETTING(10 , "11")\
PORT_CONFSETTING(11 , "12")
+class device_hp9845_io_interface;
+
class hp9845_io_slot_device : public device_t,
- public device_slot_interface
+ public device_single_card_slot_interface<device_hp9845_io_interface>
{
public:
// construction/destruction
hp9845_io_slot_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
virtual ~hp9845_io_slot_device();
- // device-level overrides
- virtual void device_start() override;
-
// Callback setups
auto irq() { return m_irq_cb_func.bind(); }
auto sts() { return m_sts_cb_func.bind(); }
@@ -52,20 +51,24 @@ 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)
- int get_rw_handlers(read16_delegate& rhandler , write16_delegate& whandler);
+ int get_rw_handlers(read16m_delegate& rhandler , write16m_delegate& whandler);
bool has_dual_sc() const;
+protected:
+ // device-level overrides
+ virtual void device_start() override ATTR_COLD;
+
private:
devcb_write_line m_irq_cb_func;
devcb_write_line m_sts_cb_func;
@@ -76,36 +79,37 @@ private:
devcb_write_line m_dmar_cb_func;
};
-class hp9845_io_card_device : public device_t,
- public device_slot_card_interface
+class device_hp9845_io_interface : public device_interface
{
public:
- void set_slot_device(hp9845_io_slot_device* dev);
+ void set_slot_device(hp9845_io_slot_device &dev);
- virtual DECLARE_READ16_MEMBER(reg_r) = 0;
- virtual DECLARE_WRITE16_MEMBER(reg_w) = 0;
+ virtual uint16_t reg_r(address_space &space, offs_t offset) = 0;
+ virtual void reg_w(address_space &space, offs_t offset, uint16_t data) = 0;
// SC getter
- uint8_t get_sc(void);
+ uint8_t get_sc();
virtual bool has_dual_sc() const;
protected:
// construction/destruction
- hp9845_io_card_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock);
- virtual ~hp9845_io_card_device();
+ device_hp9845_io_interface(const machine_config &mconfig, device_t &device);
+ virtual ~device_hp9845_io_interface();
+
+ virtual void interface_pre_start() override;
hp9845_io_slot_device *m_slot_dev;
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..3e8104f54f8
--- /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 ATTR_COLD;
+ virtual void device_start() override ATTR_COLD;
+ virtual void device_reset() override ATTR_COLD;
+
+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 e4a2fc9f33c..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
@@ -225,7 +220,8 @@ enum : unsigned {
};
hp9885_device::hp9885_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
- : hp98032_gpio_card_device(mconfig , HP9885 , tag , owner , clock)
+ : device_t(mconfig , HP9885 , tag , owner , clock)
+ , device_hp98032_gpio_interface(mconfig, *this)
, m_drive_connector{*this , "floppy"}
{
}
@@ -267,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
@@ -278,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) {
@@ -292,20 +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 const floppy_format_type hp9885_floppy_formats[] = {
- FLOPPY_MFI_FORMAT,
- FLOPPY_HPI_FORMAT,
- nullptr
+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,12 +336,13 @@ 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));
- m_fsm_timer = timer_alloc(FSM_TMR_ID);
- m_head_timer = timer_alloc(HEAD_TMR_ID);
- m_bit_byte_timer = timer_alloc(BIT_BYTE_TMR_ID);
+ m_fsm_timer = timer_alloc(FUNC(hp9885_device::fsm_tick), this);
+ m_head_timer = timer_alloc(FUNC(hp9885_device::head_tick), this);
+ m_bit_byte_timer = timer_alloc(FUNC(hp9885_device::bit_byte_tick), this);
m_drive = m_drive_connector->get_device();
@@ -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,171 +361,249 @@ 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);
}
-void hp9885_device::device_timer(emu_timer &timer, device_timer_id id, int param, void *ptr)
+TIMER_CALLBACK_MEMBER(hp9885_device::fsm_tick)
{
- LOG_TIMER("Tmr %.06f ID %d FSM %d HD %d\n" , machine().time().as_double() , 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();
+}
- switch (id) {
- case FSM_TMR_ID:
+TIMER_CALLBACK_MEMBER(hp9885_device::head_tick)
+{
+ 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("%s Head loaded\n" , machine().time().as_string(6));
+ m_head_state = HEAD_LOADED;
+ // Trigger actions to be done on head loading
do_FSM();
- break;
+ m_head_timer->adjust(attotime::from_msec(HEAD_TO_MS - HD_SETTLE_MS));
+ } else {
+ LOG_HEAD("%s Head unloaded\n" , machine().time().as_string(6));
+ m_head_state = HEAD_UNLOADED;
+ }
+}
- case HEAD_TMR_ID:
- if (m_head_state == HEAD_SETTLING) {
- LOG_HEAD("%.06f Head loaded\n" , machine().time().as_double());
- 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());
- m_head_state = HEAD_UNLOADED;
- }
- break;
+TIMER_CALLBACK_MEMBER(hp9885_device::bit_byte_tick)
+{
+ LOG_TIMER("BIT Tmr %s FSM %d HD %d\n" , machine().time().as_string(6) , m_fsm_state , m_head_state);
- case BIT_BYTE_TMR_ID:
+ switch (m_fsm_state) {
+ case FSM_WAIT_ID_AM:
+ case FSM_WAIT_DATA_AM:
{
- switch (m_fsm_state) {
- case FSM_WAIT_ID_AM:
- case FSM_WAIT_DATA_AM:
- {
- attotime edge;
- attotime tm;
- edge = m_drive->get_next_transition(m_pll.ctime);
- bool half_bit = m_pll.feed_read_data(tm , edge , attotime::never);
- m_am_detector <<= 1;
- m_am_detector |= half_bit;
- if (m_am_detector == 0x55552a54) {
- // ID AM
- // CDCDCDCDCDCDCDCD
- // 0 0 0 0 1 1 1 0
- // 0 1 1 1 0 0 0 0
- LOG_DISK("Got ID AM\n");
+ attotime edge;
+ attotime tm;
+ edge = m_drive->get_next_transition(m_pll.ctime);
+ bool half_bit = m_pll.feed_read_data(tm , edge , attotime::never);
+ m_am_detector <<= 1;
+ m_am_detector |= half_bit;
+ if (m_am_detector == 0x55552a54) {
+ // ID AM
+ // CDCDCDCDCDCDCDCD
+ // 0 0 0 0 1 1 1 0
+ // 0 1 1 1 0 0 0 0
+ LOG_DISK("Got ID AM\n");
+ preset_crc();
+ m_word_cnt = 2;
+ set_state(FSM_RD_ID);
+ } else if (m_am_detector == 0x55552a44) {
+ // DATA AM
+ // CDCDCDCDCDCDCDCD
+ // 0 0 0 0 1 0 1 0
+ // 0 1 1 1 0 0 0 0
+ LOG_DISK("Got Data AM\n");
+ if (m_fsm_state == FSM_WAIT_DATA_AM) {
+ m_rev_cnt = 0;
+ if (BIT(m_status , STS_XFER_COMPLETE)) {
+ output_status();
+ return;
+ } else {
preset_crc();
- m_word_cnt = 2;
- set_state(FSM_RD_ID);
- } else if (m_am_detector == 0x55552a44) {
- // DATA AM
- // CDCDCDCDCDCDCDCD
- // 0 0 0 0 1 0 1 0
- // 0 1 1 1 0 0 0 0
- LOG_DISK("Got Data AM\n");
- if (m_fsm_state == FSM_WAIT_DATA_AM) {
- m_rev_cnt = 0;
- if (BIT(m_status , STS_XFER_COMPLETE)) {
- output_status();
- return;
- } else {
- preset_crc();
- m_word_cnt = 129;
- if (m_op == OP_READ) {
- set_state(FSM_RD_DATA);
- } else {
- set_state(FSM_WR_DATA);
- m_pll.start_writing(m_pll.ctime);
- m_had_transition = false;
- wr_word(m_input);
- set_ibf(false);
- }
- }
+ if (m_op == OP_READ) {
+ m_word_cnt = 129;
+ set_state(FSM_RD_DATA);
+ } else {
+ m_word_cnt = 130;
+ set_state(FSM_WR_DATA);
+ m_pll.start_writing(m_pll.ctime);
+ m_had_transition = false;
+ wr_word(m_input);
+ set_ibf(false);
}
}
}
- break;
+ }
+ }
+ break;
- case FSM_RD_ID:
- {
- // This is needed when state is switched to one of the AM waiting states
- m_am_detector = 0;
- auto word = rd_word();
- m_word_cnt--;
- LOG_DISK("W %04x C %u\n" , word , m_word_cnt);
- if (m_word_cnt && word != ((m_seek_sector << 8) | m_track)) {
- set_state(FSM_WAIT_ID_AM);
- } else if (m_word_cnt == 0) {
- if (m_crc) {
- LOG_DISK("Wrong CRC in ID\n");
- set_state(FSM_WAIT_ID_AM);
- } else {
- LOG_DISK("Sector found\n");
- set_state(FSM_WAIT_DATA_AM);
- }
- }
+ case FSM_RD_ID:
+ {
+ // This is needed when state is switched to one of the AM waiting states
+ m_am_detector = 0;
+ auto word = rd_word();
+ m_word_cnt--;
+ LOG_DISK("W %04x C %u\n" , word , m_word_cnt);
+ if (m_word_cnt && word != ((m_seek_sector << 8) | m_track)) {
+ set_state(FSM_WAIT_ID_AM);
+ } else if (m_word_cnt == 0) {
+ if (m_crc) {
+ LOG_DISK("Wrong CRC in ID\n");
+ set_state(FSM_WAIT_ID_AM);
+ } else {
+ LOG_DISK("Sector found\n");
+ set_state(FSM_WAIT_DATA_AM);
}
- break;
+ }
+ }
+ break;
- case FSM_RD_DATA:
- {
- auto word = rd_word();
- m_word_cnt--;
- LOG_DISK("W %04x C %u\n" , word , m_word_cnt);
- if (m_word_cnt >= 1) {
- if (!BIT(m_status , STS_XFER_COMPLETE)) {
- m_output = word;
- m_obf = true;
- update_busy();
- }
- } else if (m_word_cnt == 0) {
- if (m_crc) {
- LOG_DISK("Wrong CRC in data\n");
- }
- // Move to next sector
- adv_sector();
- if (BIT(m_status , STS_XFER_COMPLETE) || m_sector_cnt == 0) {
- BIT_SET(m_status , STS_XFER_COMPLETE);
- output_status();
- } else {
- set_state(FSM_POSITIONING);
- do_FSM();
- }
- return;
- }
+ case FSM_RD_DATA:
+ {
+ auto word = rd_word();
+ m_word_cnt--;
+ LOG_DISK("W %04x C %u\n" , word , m_word_cnt);
+ if (m_word_cnt >= 1) {
+ if (!BIT(m_status , STS_XFER_COMPLETE)) {
+ m_output = word;
+ m_obf = true;
+ update_busy();
}
- break;
+ } else if (m_word_cnt == 0) {
+ if (m_crc) {
+ LOG_DISK("Wrong CRC in data\n");
+ }
+ // Move to next sector
+ adv_sector();
+ if (BIT(m_status , STS_XFER_COMPLETE) || m_sector_cnt == 0) {
+ BIT_SET(m_status , STS_XFER_COMPLETE);
+ output_status();
+ } else {
+ set_state(FSM_POSITIONING);
+ do_FSM();
+ }
+ return;
+ }
+ }
+ break;
- case FSM_WR_DATA:
- {
- m_word_cnt--;
- if (m_word_cnt > 1) {
- if (BIT(m_status , STS_XFER_COMPLETE)) {
- wr_word(0);
- } else {
- wr_word(m_input);
- if (m_word_cnt > 2) {
- set_ibf(false);
- }
- }
- } else if (m_word_cnt == 1) {
- wr_word(m_crc);
- } else {
- m_pll.stop_writing(m_drive , m_pll.ctime);
- // Move to next sector
- adv_sector();
- if (BIT(m_status , STS_XFER_COMPLETE) || m_sector_cnt == 0) {
- BIT_SET(m_status , STS_XFER_COMPLETE);
- output_status();
- } else {
- set_ibf(false);
- set_state(FSM_POSITIONING);
- do_FSM();
- }
- return;
+ case FSM_WR_DATA:
+ {
+ m_word_cnt--;
+ if (m_word_cnt > 2) {
+ if (BIT(m_status , STS_XFER_COMPLETE)) {
+ wr_word(0);
+ } else {
+ wr_word(m_input);
+ if (m_word_cnt > 3) {
+ set_ibf(false);
}
}
- break;
-
- default:
- LOG("Invalid FSM state %d\n" , m_fsm_state);
- set_state(FSM_IDLE);
+ } else if (m_word_cnt == 2) {
+ wr_word(m_crc);
+ } else if (m_word_cnt == 1) {
+ // Post-amble
+ wr_word(0);
+ } else {
+ m_pll.stop_writing(m_drive , m_pll.ctime);
+ // Move to next sector
+ adv_sector();
+ if (BIT(m_status , STS_XFER_COMPLETE) || m_sector_cnt == 0) {
+ BIT_SET(m_status , STS_XFER_COMPLETE);
+ output_status();
+ } else {
+ set_ibf(false);
+ set_state(FSM_POSITIONING);
+ do_FSM();
+ }
return;
}
- timer.adjust(m_pll.ctime - machine().time());
}
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);
+ return;
}
+ m_bit_byte_timer->adjust(m_pll.ctime - machine().time());
}
void hp9885_device::floppy_ready_cb(floppy_image_device *floppy , int state)
@@ -534,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;
@@ -667,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:
@@ -742,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);
}
}
@@ -779,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();
@@ -824,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;
@@ -857,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);
@@ -907,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;
@@ -922,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 edb705c2504..a2732d8e599 100644
--- a/src/devices/bus/hp9845_io/hp9885.h
+++ b/src/devices/bus/hp9845_io/hp9885.h
@@ -17,7 +17,7 @@
#include "imagedev/floppy.h"
#include "machine/fdc_pll.h"
-class hp9885_device : public hp98032_gpio_card_device
+class hp9885_device : public device_t, public device_hp98032_gpio_interface
{
public:
hp9885_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
@@ -29,16 +29,15 @@ 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
- virtual void device_add_mconfig(machine_config &config) override;
- virtual void device_start() override;
- virtual void device_reset() override;
- virtual void device_timer(emu_timer &timer, device_timer_id id, int param, void *ptr) override;
+ 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:
// FSM states
@@ -56,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
@@ -72,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;
@@ -95,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
@@ -106,6 +110,10 @@ private:
// PLL
fdc_pll_t m_pll;
+ TIMER_CALLBACK_MEMBER(fsm_tick);
+ TIMER_CALLBACK_MEMBER(head_tick);
+ TIMER_CALLBACK_MEMBER(bit_byte_tick);
+
void floppy_ready_cb(floppy_image_device *floppy , int state);
void floppy_index_cb(floppy_image_device *floppy , int state);
@@ -122,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 623f2d00be1..dcfcf6d8a11 100644
--- a/src/devices/bus/hp_dio/hp98265a.cpp
+++ b/src/devices/bus/hp_dio/hp98265a.cpp
@@ -12,14 +12,64 @@
#include "machine/nscsi_bus.h"
#include "bus/nscsi/devices.h"
#include "machine/mb87030.h"
+#include "bus/scsi/scsi.h"
+#include "bus/scsi/scsicd.h"
#define VERBOSE 0
#include "logmacro.h"
+namespace {
-DEFINE_DEVICE_TYPE_NS(HPDIO_98265A, bus::hp_dio, dio16_98265a_device, "hp98265a", "HP98265A SCSI S16 Interface")
+class dio16_98265a_device :
+ public device_t,
+ public bus::hp_dio::device_dio32_card_interface
+{
+public:
+ // construction/destruction
+ dio16_98265a_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
+
+ void mb87030(device_t *device);
+
+protected:
+ dio16_98265a_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 ATTR_COLD;
+ virtual void device_reset() override ATTR_COLD;
+
+ virtual ioport_constructor device_input_ports() const override ATTR_COLD;
+ virtual void device_add_mconfig(machine_config &config) override ATTR_COLD;
+
+ uint16_t io_r(offs_t offset);
+ void io_w(offs_t offset, uint16_t data);
+
+ void dmack_w_in(int channel, uint8_t data) override;
+ uint8_t dmack_r_in(int channel) override;
-namespace bus { namespace hp_dio {
+ void dmar0_w(int state);
+
+ void irq_w(int state);
+
+ required_device<nscsi_bus_device> m_scsibus;
+ required_device<mb87030_device> m_spc;
+private:
+
+ static constexpr int REG_CONTROL_DE0 = (1 << 0);
+ static constexpr int REG_CONTROL_DE1 = (1 << 1);
+
+ static void mb87030_scsi_adapter(device_t *device);
+ required_ioport m_sw1;
+ required_ioport m_sw2;
+ int get_int_level();
+ void update_irq(bool state);
+ void update_dma();
+ bool m_installed_io;
+ uint8_t m_control;
+
+ bool m_irq_state;
+ bool m_dmar0;
+};
void dio16_98265a_device::mb87030_scsi_adapter(device_t *device)
{
@@ -42,9 +92,9 @@ void dio16_98265a_device::device_add_mconfig(machine_config &config)
default_scsi_devices(NSCSI_CONNECTOR(config, "scsibus:3", 0));
default_scsi_devices(NSCSI_CONNECTOR(config, "scsibus:4", 0));
- nscsi_connector &scsicon6(NSCSI_CONNECTOR(config, "scsibus:5", 0));
- default_scsi_devices(scsicon6);
- scsicon6.set_default_option("cdrom");
+ nscsi_connector &scsicon5(NSCSI_CONNECTOR(config, "scsibus:5", 0));
+ default_scsi_devices(scsicon5);
+ scsicon5.set_default_option("cdrom");
default_scsi_devices(NSCSI_CONNECTOR(config, "scsibus:6", 0));
nscsi_connector &scsicon7(NSCSI_CONNECTOR(config, "scsibus:7", 0));
@@ -66,7 +116,10 @@ dio16_98265a_device::dio16_98265a_device(const machine_config &mconfig, device_t
m_spc(*this, "scsibus:7:mb87030"),
m_sw1(*this, "SW1"),
m_sw2(*this, "SW2"),
- m_irq_state(false)
+ m_installed_io(false),
+ m_control(0),
+ m_irq_state(false),
+ m_dmar0(false)
{
}
@@ -164,9 +217,9 @@ void dio16_98265a_device::device_reset()
program_space().install_readwrite_handler(
0x600000 + (code * 0x10000),
0x6007ff + (code * 0x10000),
- read16_delegate(FUNC(dio16_98265a_device::io_r), this),
- write16_delegate(FUNC(dio16_98265a_device::io_w), this));
- program_space().install_device(0x6e0020, 0x6e003f, *m_spc, &mb87030_device::map, 0x00ff00ff);
+ read16sm_delegate(*this, FUNC(dio16_98265a_device::io_r)),
+ write16sm_delegate(*this, FUNC(dio16_98265a_device::io_w)));
+ program_space().install_device(0x600020 + (code * 0x10000), 0x60003f + (code * 0x10000), *m_spc, &mb87030_device::map, 0x00ff00ff);
m_installed_io = true;
}
m_control = 0;
@@ -181,7 +234,7 @@ int dio16_98265a_device::get_int_level()
REG_SW1_INT_LEVEL_MASK;
}
-READ16_MEMBER(dio16_98265a_device::io_r)
+uint16_t dio16_98265a_device::io_r(offs_t offset)
{
uint16_t ret = 0xffff;
@@ -204,7 +257,7 @@ READ16_MEMBER(dio16_98265a_device::io_r)
return ret;
}
-WRITE16_MEMBER(dio16_98265a_device::io_w)
+void dio16_98265a_device::io_w(offs_t offset, uint16_t data)
{
LOG("io_w: offset=%02X, data=%02X\n", offset, data);
@@ -250,7 +303,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");
@@ -265,7 +318,7 @@ void dio16_98265a_device::dmack_w_in(int channel, uint8_t data)
if(channel == 0 && !(m_control & REG_CONTROL_DE0))
return;
if(channel == 1 && !(m_control & REG_CONTROL_DE1))
- return;
+ return;
m_spc->dma_w(data);
}
@@ -285,11 +338,13 @@ 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();
}
-} } // namespace bus::hp_dio
+} // anonymous namespace
+
+DEFINE_DEVICE_TYPE_PRIVATE(HPDIO_98265A, bus::hp_dio::device_dio16_card_interface, dio16_98265a_device, "hp98265a", "HP98265A SCSI S16 Interface")
diff --git a/src/devices/bus/hp_dio/hp98265a.h b/src/devices/bus/hp_dio/hp98265a.h
index 995430b1f1b..945777f4418 100644
--- a/src/devices/bus/hp_dio/hp98265a.h
+++ b/src/devices/bus/hp_dio/hp98265a.h
@@ -1,72 +1,13 @@
// license:BSD-3-Clause
// copyright-holders:Sven Schnelle
-#ifndef MAME_BUS_HPDIO_98265A_H
-#define MAME_BUS_HPDIO_98265A_H
+#ifndef MAME_BUS_HP_DIO_HP98265A_H
+#define MAME_BUS_HP_DIO_HP98265A_H
#pragma once
#include "hp_dio.h"
-#include "machine/mb87030.h"
-#include "bus/scsi/scsi.h"
-#include "bus/scsi/scsicd.h"
-namespace bus {
- namespace hp_dio {
+DECLARE_DEVICE_TYPE_NS(HPDIO_98265A, bus::hp_dio, device_dio16_card_interface)
-class dio16_98265a_device :
- public device_t,
- public device_dio32_card_interface
-{
-public:
- // construction/destruction
- dio16_98265a_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
-
- void mb87030(device_t *device);
-
-protected:
- dio16_98265a_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 ioport_constructor device_input_ports() const override;
- virtual void device_add_mconfig(machine_config &config) override;
-
- DECLARE_READ16_MEMBER(io_r);
- DECLARE_WRITE16_MEMBER(io_w);
-
- void dmack_w_in(int channel, uint8_t data) override;
- uint8_t dmack_r_in(int channel) override;
-
- DECLARE_WRITE_LINE_MEMBER(dmar0_w);
-
- DECLARE_WRITE_LINE_MEMBER(irq_w);
-
- required_device<nscsi_bus_device> m_scsibus;
- required_device<mb87030_device> m_spc;
-private:
-
- static constexpr int REG_CONTROL_DE0 = (1 << 0);
- static constexpr int REG_CONTROL_DE1 = (1 << 1);
-
- static void mb87030_scsi_adapter(device_t *device);
- required_ioport m_sw1;
- required_ioport m_sw2;
- int get_int_level();
- void update_irq(bool state);
- void update_dma();
- bool m_installed_io;
- uint8_t m_control;
-
- bool m_irq_state;
- bool m_dmar0;
-};
-
-} } // namespace bus::hp_dio
-
-DECLARE_DEVICE_TYPE_NS(HPDIO_98265A, bus::hp_dio, dio16_98265a_device)
-
-#endif // MAME_BUS_HPDIO_98265A_H
+#endif // MAME_BUS_HP_DIO_HP98265A_H
diff --git a/src/devices/bus/hp_dio/hp98543.cpp b/src/devices/bus/hp_dio/hp98543.cpp
index a3bf039f35a..452ac3f3107 100644
--- a/src/devices/bus/hp_dio/hp98543.cpp
+++ b/src/devices/bus/hp_dio/hp98543.cpp
@@ -16,42 +16,92 @@
#define HP98543_SCREEN_NAME "98543_screen"
#define HP98543_ROM_REGION "98543_rom"
+namespace {
+
+class dio16_98543_device :
+ public device_t,
+ public bus::hp_dio::device_dio16_card_interface,
+ public device_memory_interface
+{
+public:
+ dio16_98543_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
+
+ uint16_t rom_r(offs_t offset);
+ void rom_w(offs_t offset, uint16_t data);
+
+ uint16_t ctrl_r(address_space &space, offs_t offset, uint16_t mem_mask = ~0);
+ void ctrl_w(address_space &space, offs_t offset, uint16_t data, uint16_t mem_mask = ~0);
+ uint16_t vram_r(offs_t offset, uint16_t mem_mask = ~0);
+ void vram_w(offs_t offset, uint16_t data, uint16_t mem_mask = ~0);
+
+ static constexpr int TOPCAT_COUNT = 4;
+
+ required_device_array<topcat_device, TOPCAT_COUNT> m_topcat;
+ required_device<nereid_device> m_nereid;
+
+ uint32_t screen_update(screen_device &screen, bitmap_rgb32 &bitmap, const rectangle &cliprect);
+protected:
+ dio16_98543_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock);
+
+ 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;
+ virtual const tiny_rom_entry *device_rom_region() const override ATTR_COLD;
+
+ virtual space_config_vector memory_space_config() const override;
+private:
+
+ 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) ATTR_COLD;
+ void update_int();
+ static constexpr int m_h_pix = 1024;
+ static constexpr int m_v_pix = 400;
+
+ required_region_ptr<uint8_t> m_rom;
+ required_shared_ptr<uint8_t> m_vram;
+
+ uint8_t m_intreg;
+ bool m_ints[4];
+};
+
ROM_START(hp98543)
ROM_REGION(0x2000, HP98543_ROM_REGION, 0)
ROM_LOAD("1818-3907.bin", 0x000000, 0x002000, CRC(5e2bf02a) SHA1(9ba9391cf39624ef8027ce42c84e100344b2a2b8))
ROM_END
-DEFINE_DEVICE_TYPE_NS(HPDIO_98543, bus::hp_dio, dio16_98543_device, "dio98543", "HP98543 medium-res color DIO video card")
-
-namespace bus {
- namespace hp_dio {
-
void dio16_98543_device::device_add_mconfig(machine_config &config)
{
screen_device &screen(SCREEN(config, HP98543_SCREEN_NAME, SCREEN_TYPE_RASTER));
screen.set_screen_update(FUNC(dio16_98543_device::screen_update));
screen.screen_vblank().set(FUNC(dio16_98543_device::vblank_w));
- screen.set_raw(XTAL(39'504'000), 1408, 0, 1024, 425, 0, 400);
+ screen.set_raw(35.904_MHz_XTAL, 1408, 0, 1024, 425, 0, 400);
- topcat_device &topcat0(TOPCAT(config, "topcat0", XTAL(35904000)));
+ topcat_device &topcat0(TOPCAT(config, "topcat0", 35.904_MHz_XTAL));
topcat0.set_fb_width(1024);
topcat0.set_fb_height(400);
topcat0.set_planemask(1);
topcat0.irq_out_cb().set(FUNC(dio16_98543_device::int0_w));
- topcat_device &topcat1(TOPCAT(config, "topcat1", XTAL(35904000)));
+ topcat_device &topcat1(TOPCAT(config, "topcat1", 35.904_MHz_XTAL));
topcat1.set_fb_width(1024);
topcat1.set_fb_height(400);
topcat1.set_planemask(2);
topcat1.irq_out_cb().set(FUNC(dio16_98543_device::int1_w));
- topcat_device &topcat2(TOPCAT(config, "topcat2", XTAL(35904000)));
+ topcat_device &topcat2(TOPCAT(config, "topcat2", 35.904_MHz_XTAL));
topcat2.set_fb_width(1024);
topcat2.set_fb_height(400);
topcat2.set_planemask(4);
topcat2.irq_out_cb().set(FUNC(dio16_98543_device::int2_w));
- topcat_device &topcat3(TOPCAT(config, "topcat3", XTAL(35904000)));
+ topcat_device &topcat3(TOPCAT(config, "topcat3", 35.904_MHz_XTAL));
topcat3.set_fb_width(1024);
topcat3.set_fb_height(400);
topcat3.set_planemask(8);
@@ -90,8 +140,8 @@ dio16_98543_device::dio16_98543_device(const machine_config &mconfig, device_typ
m_nereid(*this, "nereid"),
m_space_config("vram", ENDIANNESS_BIG, 8, 19, 0, address_map_constructor(FUNC(dio16_98543_device::map), this)),
m_rom(*this, HP98543_ROM_REGION),
- m_vram(*this, "vram")
-
+ m_vram(*this, "vram"),
+ m_intreg(0)
{
}
@@ -102,41 +152,42 @@ void dio16_98543_device::device_start()
dio().install_memory(
0x200000, 0x27ffff,
- read16_delegate(FUNC(dio16_98543_device::vram_r), this),
- write16_delegate(FUNC(dio16_98543_device::vram_w), this));
+ read16s_delegate(*this, FUNC(dio16_98543_device::vram_r)),
+ write16s_delegate(*this, FUNC(dio16_98543_device::vram_w)));
dio().install_memory(
0x560000, 0x563fff,
- read16_delegate(FUNC(dio16_98543_device::rom_r), this),
- write16_delegate(FUNC(dio16_98543_device::rom_w), this));
+ read16sm_delegate(*this, FUNC(dio16_98543_device::rom_r)),
+ write16sm_delegate(*this, FUNC(dio16_98543_device::rom_w)));
dio().install_memory(
0x564000, 0x565fff,
- read16_delegate(FUNC(dio16_98543_device::ctrl_r), this),
- write16_delegate(FUNC(dio16_98543_device::ctrl_w), this));
+ read16_delegate(*this, FUNC(dio16_98543_device::ctrl_r)),
+ write16_delegate(*this, FUNC(dio16_98543_device::ctrl_w)));
dio().install_memory(
0x566000, 0x567fff,
- read16_delegate(FUNC(nereid_device::ctrl_r), static_cast<nereid_device*>(m_nereid)),
- write16_delegate(FUNC(nereid_device::ctrl_w), static_cast<nereid_device*>(m_nereid)));
+ read16s_delegate(*m_nereid, FUNC(nereid_device::ctrl_r)),
+ write16s_delegate(*m_nereid, FUNC(nereid_device::ctrl_w)));
}
void dio16_98543_device::device_reset()
{
+ m_intreg = 0;
}
-READ16_MEMBER(dio16_98543_device::rom_r)
+uint16_t dio16_98543_device::rom_r(offs_t offset)
{
if (offset == 1)
return m_intreg;
return 0xff00 | m_rom[offset];
}
-WRITE16_MEMBER(dio16_98543_device::rom_w)
+void dio16_98543_device::rom_w(offs_t offset, uint16_t data)
{
if (offset == 1)
m_intreg = data;
}
-READ16_MEMBER(dio16_98543_device::ctrl_r)
+uint16_t dio16_98543_device::ctrl_r(address_space &space, offs_t offset, uint16_t mem_mask)
{
uint16_t ret = 0;
@@ -146,51 +197,51 @@ READ16_MEMBER(dio16_98543_device::ctrl_r)
return ret;
}
-WRITE16_MEMBER(dio16_98543_device::ctrl_w)
+void dio16_98543_device::ctrl_w(address_space &space, offs_t offset, uint16_t data, uint16_t mem_mask)
{
for (auto &tc: m_topcat)
tc->ctrl_w(space, offset, data, mem_mask);
}
-READ16_MEMBER(dio16_98543_device::vram_r)
+uint16_t dio16_98543_device::vram_r(offs_t offset, uint16_t mem_mask)
{
uint16_t ret = 0;
for (auto &tc: m_topcat)
- ret |= tc->vram_r(space, offset, mem_mask);
+ ret |= tc->vram_r(offset, mem_mask);
return ret;
}
-WRITE16_MEMBER(dio16_98543_device::vram_w)
+void dio16_98543_device::vram_w(offs_t offset, uint16_t data, uint16_t mem_mask)
{
for (auto &tc: m_topcat)
- tc->vram_w(space, offset, data, 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;
@@ -234,7 +285,7 @@ uint32_t dio16_98543_device::screen_update(screen_device &screen, bitmap_rgb32 &
}
for (int y = 0; y < m_v_pix; y++) {
- uint32_t *scanline = &bitmap.pix32(y);
+ uint32_t *scanline = &bitmap.pix(y);
for (int x = 0; x < m_h_pix; x++) {
uint8_t tmp = m_vram[y * m_h_pix + x];
@@ -251,5 +302,6 @@ uint32_t dio16_98543_device::screen_update(screen_device &screen, bitmap_rgb32 &
return 0;
}
-} // namespace bus::hp_dio
-} // namespace bus
+} // anonymous namespace
+
+DEFINE_DEVICE_TYPE_PRIVATE(HPDIO_98543, bus::hp_dio::device_dio16_card_interface, dio16_98543_device, "dio98543", "HP98543 medium-res color DIO video card")
diff --git a/src/devices/bus/hp_dio/hp98543.h b/src/devices/bus/hp_dio/hp98543.h
index d2cdd27ca89..2432380e5c3 100644
--- a/src/devices/bus/hp_dio/hp98543.h
+++ b/src/devices/bus/hp_dio/hp98543.h
@@ -1,75 +1,14 @@
// license:BSD-3-Clause
// copyright-holders:Sven Schnelle
-#ifndef MAME_BUS_HPDIO_98543_H
-#define MAME_BUS_HPDIO_98543_H
+#ifndef MAME_BUS_HP_DIO_HP98543_H
+#define MAME_BUS_HP_DIO_HP98543_H
#pragma once
#include "hp_dio.h"
-#include "video/topcat.h"
-#include "video/nereid.h"
-#include "machine/ram.h"
-
-namespace bus {
- namespace hp_dio {
-class dio16_98543_device :
- public device_t,
- public device_dio16_card_interface,
- public device_memory_interface
-{
-public:
- dio16_98543_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
-
- DECLARE_READ16_MEMBER(rom_r);
- DECLARE_WRITE16_MEMBER(rom_w);
-
- DECLARE_READ16_MEMBER(ctrl_r);
- DECLARE_WRITE16_MEMBER(ctrl_w);
- DECLARE_READ16_MEMBER(vram_r);
- DECLARE_WRITE16_MEMBER(vram_w);
-
- static constexpr int TOPCAT_COUNT = 4;
-
- required_device_array<topcat_device, TOPCAT_COUNT> m_topcat;
- required_device<nereid_device> m_nereid;
-
- uint32_t screen_update(screen_device &screen, bitmap_rgb32 &bitmap, const rectangle &cliprect);
-protected:
- dio16_98543_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 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);
-
- const address_space_config m_space_config;
- void map(address_map &map);
- void update_int();
- static constexpr int m_h_pix = 1024;
- static constexpr int m_v_pix = 400;
-
- required_region_ptr<uint8_t> m_rom;
- required_shared_ptr<uint8_t> m_vram;
-
- uint8_t m_intreg;
- bool m_ints[4];
-};
-
-} // namespace bus::hp_dio
-} // namespace bus
// device type definition
-DECLARE_DEVICE_TYPE_NS(HPDIO_98543, bus::hp_dio, dio16_98543_device)
+DECLARE_DEVICE_TYPE_NS(HPDIO_98543, bus::hp_dio, device_dio16_card_interface)
-#endif // MAME_BUS_HPDIO_98543_H
+#endif // MAME_BUS_HP_DIO_HP98543_H
diff --git a/src/devices/bus/hp_dio/hp98544.cpp b/src/devices/bus/hp_dio/hp98544.cpp
index 9565d4632d2..3eb9e7dfbcc 100644
--- a/src/devices/bus/hp_dio/hp98544.cpp
+++ b/src/devices/bus/hp_dio/hp98544.cpp
@@ -10,25 +10,66 @@
#include "emu.h"
#include "hp98544.h"
+
+#include "video/topcat.h"
+
#include "screen.h"
+
#define HP98544_SCREEN_NAME "98544_screen"
#define HP98544_ROM_REGION "98544_rom"
+namespace {
+
+class dio16_98544_device :
+ public device_t,
+ public bus::hp_dio::device_dio16_card_interface,
+ public device_memory_interface
+{
+public:
+ // construction/destruction
+ dio16_98544_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
+
+ uint16_t rom_r(offs_t offset);
+ void rom_w(offs_t offset, uint16_t data);
+
+ required_device<topcat_device> m_topcat;
+ uint32_t screen_update(screen_device &screen, bitmap_rgb32 &bitmap, const rectangle &cliprect);
+ protected:
+ dio16_98544_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 ATTR_COLD;
+ virtual void device_reset() override ATTR_COLD;
+
+ // optional information overrides
+ virtual void device_add_mconfig(machine_config &config) override ATTR_COLD;
+ virtual const tiny_rom_entry *device_rom_region() const override ATTR_COLD;
+ virtual space_config_vector memory_space_config() const override;
+private:
+
+ void vblank_w(int state);
+ void int_w(int state);
+
+ static constexpr int m_v_pix = 768;
+ static constexpr int m_h_pix = 1024;
+
+ const address_space_config m_space_config;
+ void map(address_map &map) ATTR_COLD;
+ required_region_ptr<uint8_t> m_rom;
+ required_shared_ptr<uint8_t> m_vram;
+
+ uint8_t m_intreg;
+};
+
//*************************************************************************
// GLOBAL VARIABLES
//**************************************************************************
-DEFINE_DEVICE_TYPE_NS(HPDIO_98544, bus::hp_dio, dio16_98544_device, "dio98544", "HP98544 high-res monochrome DIO video card")
-
-namespace bus {
- namespace hp_dio {
-
ROM_START( hp98544 )
ROM_REGION( 0x2000, HP98544_ROM_REGION, 0 )
ROM_LOAD( "98544_1818-1999.bin", 0x000000, 0x002000, CRC(8c7d6480) SHA1(d2bcfd39452c38bc652df39f84c7041cfdf6bd51) )
ROM_END
-
//-------------------------------------------------
// device_add_mconfig - add device configuration
//-------------------------------------------------
@@ -51,8 +92,6 @@ void dio16_98544_device::device_add_mconfig(machine_config &config)
// rom_region - device-specific ROM region
//-------------------------------------------------
-
-
const tiny_rom_entry *dio16_98544_device::device_rom_region() const
{
return ROM_NAME( hp98544 );
@@ -78,7 +117,8 @@ dio16_98544_device::dio16_98544_device(const machine_config &mconfig, device_typ
m_topcat(*this, "topcat"),
m_space_config("vram", ENDIANNESS_BIG, 8, 20, 0, address_map_constructor(FUNC(dio16_98544_device::map), this)),
m_rom(*this, HP98544_ROM_REGION),
- m_vram(*this, "vram")
+ m_vram(*this, "vram"),
+ m_intreg(0)
{
}
@@ -101,16 +141,16 @@ void dio16_98544_device::device_start()
save_item(NAME(m_intreg));
dio().install_memory(
0x200000, 0x2fffff,
- read16_delegate(FUNC(topcat_device::vram_r), static_cast<topcat_device*>(m_topcat)),
- write16_delegate(FUNC(topcat_device::vram_w), static_cast<topcat_device*>(m_topcat)));
+ read16s_delegate(*m_topcat, FUNC(topcat_device::vram_r)),
+ write16s_delegate(*m_topcat, FUNC(topcat_device::vram_w)));
dio().install_memory(
0x560000, 0x563fff,
- read16_delegate(FUNC(dio16_98544_device::rom_r), this),
- write16_delegate(FUNC(dio16_98544_device::rom_w), this));
+ read16sm_delegate(*this, FUNC(dio16_98544_device::rom_r)),
+ write16sm_delegate(*this, FUNC(dio16_98544_device::rom_w)));
dio().install_memory(
0x564000, 0x567fff,
- read16_delegate(FUNC(topcat_device::ctrl_r), static_cast<topcat_device*>(m_topcat)),
- write16_delegate(FUNC(topcat_device::ctrl_w), static_cast<topcat_device*>(m_topcat)));
+ read16_delegate(*m_topcat, FUNC(topcat_device::ctrl_r)),
+ write16_delegate(*m_topcat, FUNC(topcat_device::ctrl_w)));
}
//-------------------------------------------------
@@ -119,9 +159,10 @@ void dio16_98544_device::device_start()
void dio16_98544_device::device_reset()
{
+ m_intreg = 0;
}
-READ16_MEMBER(dio16_98544_device::rom_r)
+uint16_t dio16_98544_device::rom_r(offs_t offset)
{
if (offset == 1)
return m_intreg;
@@ -130,19 +171,19 @@ READ16_MEMBER(dio16_98544_device::rom_r)
}
// the video chip registers live here, so these writes are valid
-WRITE16_MEMBER(dio16_98544_device::rom_w)
+void dio16_98544_device::rom_w(offs_t offset, uint16_t data)
{
if (offset == 1) {
m_intreg = 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;
@@ -165,29 +206,24 @@ WRITE_LINE_MEMBER(dio16_98544_device::int_w)
uint32_t dio16_98544_device::screen_update(screen_device &screen, bitmap_rgb32 &bitmap, const rectangle &cliprect)
{
- int startx, starty, endx, endy;
-
-
if (!m_topcat->has_changed())
return UPDATE_HAS_NOT_CHANGED;
for (int y = 0; y < m_v_pix; y++) {
- uint32_t *scanline = &bitmap.pix32(y);
+ uint32_t *scanline = &bitmap.pix(y);
for (int x = 0; x < m_h_pix; x++) {
uint8_t tmp = m_vram[y * m_h_pix + x];
*scanline++ = tmp ? rgb_t(255,255,255) : rgb_t(0, 0, 0);
}
}
+ int startx, starty, endx, endy;
m_topcat->get_cursor_pos(startx, starty, endx, endy);
-
- for (int y = starty; y <= endy; y++) {
- uint32_t *scanline = &bitmap.pix32(y);
- memset(scanline + startx, 0xff, (endx - startx) << 2);
- }
+ bitmap.fill(rgb_t(255, 255, 255), rectangle(startx, endx, starty, endy));
return 0;
}
-} // namespace bus::hp_dio
-} // namespace bus
+} // anonymous namespace
+
+DEFINE_DEVICE_TYPE_PRIVATE(HPDIO_98544, bus::hp_dio::device_dio16_card_interface, dio16_98544_device, "dio98544", "HP98544 high-res monochrome DIO video card")
diff --git a/src/devices/bus/hp_dio/hp98544.h b/src/devices/bus/hp_dio/hp98544.h
index d009f8589fd..3b1116e307a 100644
--- a/src/devices/bus/hp_dio/hp98544.h
+++ b/src/devices/bus/hp_dio/hp98544.h
@@ -1,67 +1,12 @@
// license:BSD-3-Clause
// copyright-holders:R. Belmont
-
-#ifndef MAME_BUS_HPDIO_98544_H
-#define MAME_BUS_HPDIO_98544_H
+#ifndef MAME_BUS_HP_DIO_HP98544_H
+#define MAME_BUS_HP_DIO_HP98544_H
#pragma once
#include "hp_dio.h"
-#include "video/topcat.h"
-//**************************************************************************
-// TYPE DEFINITIONS
-//**************************************************************************
-
-// ======================> dio16_98544_device
-
-namespace bus {
- namespace hp_dio {
-
-class dio16_98544_device :
- public device_t,
- public device_dio16_card_interface,
- public device_memory_interface
-{
-public:
- // construction/destruction
- dio16_98544_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
-
- DECLARE_READ16_MEMBER(rom_r);
- DECLARE_WRITE16_MEMBER(rom_w);
-
- required_device<topcat_device> m_topcat;
- uint32_t screen_update(screen_device &screen, bitmap_rgb32 &bitmap, const rectangle &cliprect);
- protected:
- dio16_98544_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;
- virtual space_config_vector memory_space_config() const override;
-private:
-
- WRITE_LINE_MEMBER(vblank_w);
- WRITE_LINE_MEMBER(int_w);
-
- static constexpr int m_v_pix = 768;
- static constexpr int m_h_pix = 1024;
-
- const address_space_config m_space_config;
- void map(address_map &map);
- required_region_ptr<uint8_t> m_rom;
- required_shared_ptr<uint8_t> m_vram;
-
- uint8_t m_intreg;
-};
-
-} // namespace bus::hp_dio
-} // namespace bus
-// device type definition
-DECLARE_DEVICE_TYPE_NS(HPDIO_98544, bus::hp_dio, dio16_98544_device)
+DECLARE_DEVICE_TYPE_NS(HPDIO_98544, bus::hp_dio, device_dio16_card_interface)
-#endif // MAME_BUS_HPDIO_98544_H
+#endif // MAME_BUS_HP_DIO_HP98544_H
diff --git a/src/devices/bus/hp_dio/hp98550.cpp b/src/devices/bus/hp_dio/hp98550.cpp
index 28d87d5a52f..f93fddc5fdb 100644
--- a/src/devices/bus/hp_dio/hp98550.cpp
+++ b/src/devices/bus/hp_dio/hp98550.cpp
@@ -18,15 +18,67 @@ HP98550 high-resolution color board
//#define VERBOSE 1
#include "logmacro.h"
+namespace {
+
+class dio32_98550_device :
+ public device_t,
+ public bus::hp_dio::device_dio32_card_interface,
+ public device_memory_interface
+{
+public:
+ dio32_98550_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
+
+ uint16_t rom_r(offs_t offset, uint16_t mem_mask = ~0);
+ void rom_w(offs_t offset, uint16_t data, uint16_t mem_mask = ~0);
+
+ uint16_t catseye_r(address_space &space, offs_t offset, uint16_t mem_mask = ~0);
+ void catseye_w(address_space &space, offs_t offset, uint16_t data, uint16_t mem_mask = ~0);
+
+ uint16_t vram_r(offs_t offset, uint16_t mem_mask = ~0);
+ void vram_w(offs_t offset, uint16_t data, uint16_t mem_mask = ~0);
+
+ static constexpr int CATSEYE_COUNT = 8;
+
+
+ uint32_t screen_update(screen_device &screen, bitmap_rgb32 &bitmap, const rectangle &cliprect);
+protected:
+ required_device<nereid_device> m_nereid;
+ required_device_array<catseye_device, CATSEYE_COUNT> m_catseye;
+
+ dio32_98550_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock);
+
+ 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;
+ virtual const tiny_rom_entry *device_rom_region() const override ATTR_COLD;
+
+ virtual space_config_vector memory_space_config() const override;
+
+ void vblank_w(int state);
+ void int_w(offs_t offset, uint8_t data);
+
+ const address_space_config m_space_config;
+ void map(address_map &map) ATTR_COLD;
+ void update_int();
+
+ static constexpr int m_fb_width = 2048;
+ static constexpr int m_h_pix = 1280;
+ static constexpr int m_v_pix = 1024;
+
+ required_region_ptr<uint8_t> m_rom;
+ required_shared_ptr_array<uint8_t, 2> m_vram;
+
+ uint16_t m_plane_mask;
+ uint8_t m_intreg;
+ uint8_t m_ints;
+};
+
ROM_START(hp98550)
ROM_REGION(0x8000, "hp98550a_rom", 0)
ROM_LOAD("98550a.bin", 0x000000, 0x008000, CRC(9d639233) SHA1(d6b23a34850f24525ca5fb36de3deb91196d2dc5))
ROM_END
-DEFINE_DEVICE_TYPE_NS(HPDIO_98550, bus::hp_dio, dio32_98550_device, "dio98550", "HP98550A high-res color DIO video card")
-
-namespace bus { namespace hp_dio {
-
void dio32_98550_device::device_add_mconfig(machine_config &config)
{
screen_device &screen(SCREEN(config, "hp98550_screen", SCREEN_TYPE_RASTER));
@@ -70,13 +122,15 @@ dio32_98550_device::dio32_98550_device(const machine_config &mconfig, const char
dio32_98550_device::dio32_98550_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_dio16_card_interface(mconfig, *this),
+ device_dio32_card_interface(mconfig, *this),
device_memory_interface(mconfig, *this),
m_nereid(*this, "nereid"),
m_catseye(*this, "catseye%d", 0),
m_space_config("vram", ENDIANNESS_BIG, 8, 23, 0, address_map_constructor(FUNC(dio32_98550_device::map), this)),
m_rom(*this, "hp98550a_rom"),
- m_vram(*this, { "vram_video", "vram_overlay"})
+ m_vram(*this, { "vram_video", "vram_overlay"}),
+ m_intreg(0),
+ m_ints(0)
{
}
@@ -87,23 +141,23 @@ void dio32_98550_device::device_start()
dio().install_memory(
0x200000, 0x3fffff,
- read16_delegate(FUNC(dio32_98550_device::vram_r), this),
- write16_delegate(FUNC(dio32_98550_device::vram_w), this));
+ read16s_delegate(*this, FUNC(dio32_98550_device::vram_r)),
+ write16s_delegate(*this, FUNC(dio32_98550_device::vram_w)));
dio().install_memory(
0x560000, 0x56ffff,
- read16_delegate(FUNC(dio32_98550_device::rom_r), this),
- write16_delegate(FUNC(dio32_98550_device::rom_w), this));
+ read16s_delegate(*this, FUNC(dio32_98550_device::rom_r)),
+ write16s_delegate(*this, FUNC(dio32_98550_device::rom_w)));
dio().install_memory(
0x564000, 0x5648ff,
- read16_delegate(FUNC(dio32_98550_device::catseye_r), this),
- write16_delegate(FUNC(dio32_98550_device::catseye_w), this));
+ read16_delegate(*this, FUNC(dio32_98550_device::catseye_r)),
+ write16_delegate(*this, FUNC(dio32_98550_device::catseye_w)));
dio().install_memory(
0x566000, 0x5660ff,
- read16_delegate(FUNC(nereid_device::ctrl_r), &(*m_nereid)),
- write16_delegate(FUNC(nereid_device::ctrl_w), &(*m_nereid)));
+ read16s_delegate(*m_nereid, FUNC(nereid_device::ctrl_r)),
+ write16s_delegate(*m_nereid, FUNC(nereid_device::ctrl_w)));
}
void dio32_98550_device::device_reset()
@@ -112,7 +166,7 @@ void dio32_98550_device::device_reset()
m_ints = 0;
}
-READ16_MEMBER(dio32_98550_device::rom_r)
+uint16_t dio32_98550_device::rom_r(offs_t offset, uint16_t mem_mask)
{
LOG("%s: %04x\n", __func__, offset);
@@ -122,7 +176,7 @@ READ16_MEMBER(dio32_98550_device::rom_r)
return 0xff00 | m_rom[offset];
}
-WRITE16_MEMBER(dio32_98550_device::rom_w)
+void dio32_98550_device::rom_w(offs_t offset, uint16_t data, uint16_t mem_mask)
{
switch (offset) {
case 0:
@@ -139,7 +193,7 @@ WRITE16_MEMBER(dio32_98550_device::rom_w)
}
}
-READ16_MEMBER(dio32_98550_device::catseye_r)
+uint16_t dio32_98550_device::catseye_r(address_space &space, offs_t offset, uint16_t mem_mask)
{
uint16_t ret = 0;
@@ -149,36 +203,36 @@ READ16_MEMBER(dio32_98550_device::catseye_r)
return ret;
}
-WRITE16_MEMBER(dio32_98550_device::catseye_w)
+void dio32_98550_device::catseye_w(address_space &space, offs_t offset, uint16_t data, uint16_t mem_mask)
{
LOG("%s: %04X = %04X\n", __func__, offset << 1, data);
for (auto &ce: m_catseye)
- ce->ctrl_w(space, offset, data, mem_mask);
+ ce->ctrl_w(offset, data, mem_mask);
}
-READ16_MEMBER(dio32_98550_device::vram_r)
+uint16_t dio32_98550_device::vram_r(offs_t offset, uint16_t mem_mask)
{
uint16_t ret = 0;
for (auto &ce: m_catseye)
- ret |= ce->vram_r(space, offset, mem_mask);
+ ret |= ce->vram_r(offset, mem_mask);
return ret;
}
-WRITE16_MEMBER(dio32_98550_device::vram_w)
+void dio32_98550_device::vram_w(offs_t offset, uint16_t data, uint16_t mem_mask)
{
for (auto &ce: m_catseye)
- ce->vram_w(space, offset, data, 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);
}
-WRITE8_MEMBER(dio32_98550_device::int_w)
+void dio32_98550_device::int_w(offs_t offset, uint8_t data)
{
LOG("%s: plane%d = %s\n", __func__, offset, data ? "assert" : "deassert");
m_ints &= ~(1 << offset);
@@ -218,7 +272,7 @@ uint32_t dio32_98550_device::screen_update(screen_device &screen, bitmap_rgb32 &
mask |= ce->plane_enabled();
for (int y = 0; y < m_v_pix; y++) {
- uint32_t *scanline = &bitmap.pix32(y);
+ uint32_t *scanline = &bitmap.pix(y);
for (int x = 0; x < m_h_pix; x++) {
const int offset = y * m_fb_width +x;
@@ -230,5 +284,6 @@ uint32_t dio32_98550_device::screen_update(screen_device &screen, bitmap_rgb32 &
return 0;
}
-} // namespace bus::hp_dio
-} // namespace bus
+} // anonymous namespace
+
+DEFINE_DEVICE_TYPE_PRIVATE(HPDIO_98550, bus::hp_dio::device_dio32_card_interface, dio32_98550_device, "dio98550", "HP98550A high-res color DIO video card")
diff --git a/src/devices/bus/hp_dio/hp98550.h b/src/devices/bus/hp_dio/hp98550.h
index 47057f6da70..ca2e681fb02 100644
--- a/src/devices/bus/hp_dio/hp98550.h
+++ b/src/devices/bus/hp_dio/hp98550.h
@@ -1,78 +1,13 @@
// license:BSD-3-Clause
// copyright-holders:Sven Schnelle
-#ifndef MAME_BUS_HPDIO_98550_H
-#define MAME_BUS_HPDIO_98550_H
+#ifndef MAME_BUS_HP_DIO_HP98550_H
+#define MAME_BUS_HP_DIO_HP98550_H
#pragma once
#include "hp_dio.h"
-#include "video/catseye.h"
-#include "video/nereid.h"
-#include "machine/ram.h"
-namespace bus {
- namespace hp_dio {
-class dio32_98550_device :
- public device_t,
- public device_dio16_card_interface,
- public device_memory_interface
-{
-public:
- dio32_98550_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
+DECLARE_DEVICE_TYPE_NS(HPDIO_98550, bus::hp_dio, device_dio32_card_interface)
- DECLARE_READ16_MEMBER(rom_r);
- DECLARE_WRITE16_MEMBER(rom_w);
-
- DECLARE_READ16_MEMBER(topcat_r);
- DECLARE_WRITE16_MEMBER(topcat_w);
- DECLARE_READ16_MEMBER(catseye_r);
- DECLARE_WRITE16_MEMBER(catseye_w);
-
- DECLARE_READ16_MEMBER(vram_r);
- DECLARE_WRITE16_MEMBER(vram_w);
-
- static constexpr int CATSEYE_COUNT = 8;
-
-
- uint32_t screen_update(screen_device &screen, bitmap_rgb32 &bitmap, const rectangle &cliprect);
-protected:
- required_device<nereid_device> m_nereid;
- required_device_array<catseye_device, CATSEYE_COUNT> m_catseye;
-
- dio32_98550_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 space_config_vector memory_space_config() const override;
-
- DECLARE_WRITE_LINE_MEMBER(vblank_w);
- DECLARE_WRITE8_MEMBER(int_w);
-
- const address_space_config m_space_config;
- void map(address_map &map);
- void update_int();
-
- static constexpr int m_fb_width = 2048;
- static constexpr int m_h_pix = 1280;
- static constexpr int m_v_pix = 1024;
-
- required_region_ptr<uint8_t> m_rom;
- required_shared_ptr_array<uint8_t, 2> m_vram;
-
- uint16_t m_plane_mask;
- uint8_t m_intreg;
- uint8_t m_ints;
-};
-
-} // namespace bus::hp_dio
-} // namespace bus
-
-// device type definition
-DECLARE_DEVICE_TYPE_NS(HPDIO_98550, bus::hp_dio, dio32_98550_device)
-
-#endif // MAME_BUS_HPDIO_98550_H
+#endif // MAME_BUS_HP_DIO_HP98550_H
diff --git a/src/devices/bus/hp_dio/hp98603a.cpp b/src/devices/bus/hp_dio/hp98603a.cpp
index ac04f7479bd..d4ddb02239a 100644
--- a/src/devices/bus/hp_dio/hp98603a.cpp
+++ b/src/devices/bus/hp_dio/hp98603a.cpp
@@ -9,12 +9,35 @@
#include "emu.h"
#include "hp98603a.h"
-DEFINE_DEVICE_TYPE_NS(HPDIO_98603A, bus::hp_dio, dio16_98603a_device, "dio98603a", "HP98603A BASIC 4.0 ROM card")
#define HP98603A_ROM_REGION "98603a_rom"
-namespace bus {
- namespace hp_dio {
+namespace {
+
+class dio16_98603a_device :
+ public device_t,
+ public bus::hp_dio::device_dio16_card_interface
+{
+public:
+ // construction/destruction
+ dio16_98603a_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
+ uint16_t rom_r(offs_t offset);
+ void rom_w(offs_t offset, uint16_t data);
+
+protected:
+ dio16_98603a_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 ATTR_COLD;
+ virtual void device_reset() override ATTR_COLD;
+
+ // optional information overrides
+ virtual void device_add_mconfig(machine_config &config) override ATTR_COLD;
+ virtual const tiny_rom_entry *device_rom_region() const override ATTR_COLD;
+
+private:
+ uint8_t *m_rom;
+};
ROM_START(hp98603a)
ROM_REGION(0x80000, HP98603A_ROM_REGION, 0)
@@ -67,18 +90,19 @@ void dio16_98603a_device::device_reset()
{
m_rom = device().machine().root_device().memregion(this->subtag(HP98603A_ROM_REGION).c_str())->base();
dio().install_memory(0x80000, 0xfffff,
- read16_delegate(FUNC(dio16_98603a_device::rom_r), this),
- write16_delegate(FUNC(dio16_98603a_device::rom_w), this));
+ read16sm_delegate(*this, FUNC(dio16_98603a_device::rom_r)),
+ write16sm_delegate(*this, FUNC(dio16_98603a_device::rom_w)));
}
-READ16_MEMBER(dio16_98603a_device::rom_r)
+uint16_t dio16_98603a_device::rom_r(offs_t offset)
{
return m_rom[offset*2] | (m_rom[offset*2+1] << 8);
}
-WRITE16_MEMBER(dio16_98603a_device::rom_w)
+void dio16_98603a_device::rom_w(offs_t offset, uint16_t data)
{
}
-} // namespace bus::hp_dio
-} // namespace bus
+} // anonymous namespace
+
+DEFINE_DEVICE_TYPE_PRIVATE(HPDIO_98603A, bus::hp_dio::device_dio16_card_interface, dio16_98603a_device, "dio98603a", "HP98603A BASIC 4.0 ROM card")
diff --git a/src/devices/bus/hp_dio/hp98603a.h b/src/devices/bus/hp_dio/hp98603a.h
index 1d08cf83e0b..c5573a287c8 100644
--- a/src/devices/bus/hp_dio/hp98603a.h
+++ b/src/devices/bus/hp_dio/hp98603a.h
@@ -1,44 +1,13 @@
// license:BSD-3-Clause
// copyright-holders:Sven Schnelle
-#ifndef MAME_BUS_HPDIO_98603A_H
-#define MAME_BUS_HPDIO_98603A_H
+#ifndef MAME_BUS_HP_DIO_HP98603A_H
+#define MAME_BUS_HP_DIO_HP98603A_H
#pragma once
#include "hp_dio.h"
-namespace bus {
- namespace hp_dio {
+DECLARE_DEVICE_TYPE_NS(HPDIO_98603A, bus::hp_dio, device_dio16_card_interface)
-class dio16_98603a_device :
- public device_t,
- public device_dio16_card_interface
-{
-public:
- // construction/destruction
- dio16_98603a_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
- DECLARE_READ16_MEMBER(rom_r);
- DECLARE_WRITE16_MEMBER(rom_w);
-
-protected:
- dio16_98603a_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:
- uint8_t *m_rom;
-};
-
-} // namespace bus::hp_dio
-} // namespace bus
-
-DECLARE_DEVICE_TYPE_NS(HPDIO_98603A, bus::hp_dio, dio16_98603a_device)
-
-#endif // MAME_BUS_HPDIO_98603A_H
+#endif // MAME_BUS_HP_DIO_HP98603A_H
diff --git a/src/devices/bus/hp_dio/hp98603b.cpp b/src/devices/bus/hp_dio/hp98603b.cpp
index 6c8cff6b95a..34f2d440305 100644
--- a/src/devices/bus/hp_dio/hp98603b.cpp
+++ b/src/devices/bus/hp_dio/hp98603b.cpp
@@ -9,12 +9,35 @@
#include "emu.h"
#include "hp98603b.h"
-DEFINE_DEVICE_TYPE_NS(HPDIO_98603B, bus::hp_dio, dio16_98603b_device, "dio98603b", "HP98603 BASIC ROM card")
#define HP98603B_ROM_REGION "98603b_rom"
-namespace bus {
- namespace hp_dio {
+namespace {
+
+class dio16_98603b_device :
+ public device_t,
+ public bus::hp_dio::device_dio16_card_interface
+{
+public:
+ // construction/destruction
+ dio16_98603b_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
+ uint16_t rom_r(offs_t offset);
+ void rom_w(offs_t offset, uint16_t data);
+
+protected:
+ dio16_98603b_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 ATTR_COLD;
+ virtual void device_reset() override ATTR_COLD;
+
+ // optional information overrides
+ virtual void device_add_mconfig(machine_config &config) override ATTR_COLD;
+ virtual const tiny_rom_entry *device_rom_region() const override ATTR_COLD;
+
+private:
+ uint8_t *m_rom;
+};
ROM_START(hp98603b)
ROM_REGION(0x100000, HP98603B_ROM_REGION, 0)
@@ -61,18 +84,20 @@ void dio16_98603b_device::device_start()
void dio16_98603b_device::device_reset()
{
m_rom = device().machine().root_device().memregion(this->subtag(HP98603B_ROM_REGION).c_str())->base();
- dio().install_memory(0x100000, 0x1fffff, read16_delegate(FUNC(dio16_98603b_device::rom_r), this),
- write16_delegate(FUNC(dio16_98603b_device::rom_w), this));
+ dio().install_memory(0x100000, 0x1fffff,
+ read16sm_delegate(*this, FUNC(dio16_98603b_device::rom_r)),
+ write16sm_delegate(*this, FUNC(dio16_98603b_device::rom_w)));
}
-READ16_MEMBER(dio16_98603b_device::rom_r)
+uint16_t dio16_98603b_device::rom_r(offs_t offset)
{
return m_rom[offset*2] | (m_rom[offset*2+1] << 8);
}
-WRITE16_MEMBER(dio16_98603b_device::rom_w)
+void dio16_98603b_device::rom_w(offs_t offset, uint16_t data)
{
}
-} // namespace bus::hp_dio
-} // namespace bus
+} // anonymous namespace
+
+DEFINE_DEVICE_TYPE_PRIVATE(HPDIO_98603B, bus::hp_dio::device_dio16_card_interface, dio16_98603b_device, "dio98603b", "HP98603 BASIC ROM card")
diff --git a/src/devices/bus/hp_dio/hp98603b.h b/src/devices/bus/hp_dio/hp98603b.h
index ea16286c98e..e402eb9ca58 100644
--- a/src/devices/bus/hp_dio/hp98603b.h
+++ b/src/devices/bus/hp_dio/hp98603b.h
@@ -1,44 +1,13 @@
// license:BSD-3-Clause
// copyright-holders:Sven Schnelle
-#ifndef MAME_BUS_HPDIO_98603B_H
-#define MAME_BUS_HPDIO_98603B_H
+#ifndef MAME_BUS_HP_DIO_HP98603B_H
+#define MAME_BUS_HP_DIO_HP98603B_H
#pragma once
#include "hp_dio.h"
-namespace bus {
- namespace hp_dio {
+DECLARE_DEVICE_TYPE_NS(HPDIO_98603B, bus::hp_dio, device_dio16_card_interface)
-class dio16_98603b_device :
- public device_t,
- public device_dio16_card_interface
-{
-public:
- // construction/destruction
- dio16_98603b_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
- DECLARE_READ16_MEMBER(rom_r);
- DECLARE_WRITE16_MEMBER(rom_w);
-
-protected:
- dio16_98603b_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:
- uint8_t *m_rom;
-};
-
-} // namespace bus::hp_dio
-} // namespace bus
-
-DECLARE_DEVICE_TYPE_NS(HPDIO_98603B, bus::hp_dio, dio16_98603b_device)
-
-#endif // MAME_BUS_HPDIO_98603B_H
+#endif // MAME_BUS_HP_DIO_HP98603B_H
diff --git a/src/devices/bus/hp_dio/hp98620.cpp b/src/devices/bus/hp_dio/hp98620.cpp
index fcd0e9d95aa..5f49ca9496d 100644
--- a/src/devices/bus/hp_dio/hp98620.cpp
+++ b/src/devices/bus/hp_dio/hp98620.cpp
@@ -13,10 +13,122 @@
#include "logmacro.h"
-DEFINE_DEVICE_TYPE_NS(HPDIO_98620, bus::hp_dio, dio16_98620_device, "hp98620", "HP98620 DMA Controller")
+namespace {
-namespace bus {
- namespace hp_dio {
+class dio16_98620_device :
+ public device_t,
+ public device_execute_interface,
+ public bus::hp_dio::device_dio16_card_interface
+{
+public:
+ // construction/destruction
+ dio16_98620_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
+
+protected:
+ dio16_98620_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 ATTR_COLD;
+ virtual void device_reset() override ATTR_COLD;
+ virtual void execute_run() override;
+
+ uint16_t dma_r(offs_t offset);
+ void dma_w(offs_t offset, uint16_t data);
+
+ void irq_w(int state);
+
+private:
+
+ static constexpr int REG0_RESET_ARM_INT = 0x00;
+ static constexpr int REG0_ADDRESS_HIGH = 0x00;
+ static constexpr int REG0_ADDRESS_LOW = 0x02;
+ static constexpr int REG0_TRANSFER_COUNT = 0x04;
+ static constexpr int REG0_CONTROL_ARM = 0x06;
+ static constexpr int REG0_STATUS = 0x06;
+
+ static constexpr int REG1_RESET_ARM_INT = 0x08;
+ static constexpr int REG1_ADDRESS_HIGH = 0x08;
+ static constexpr int REG1_ADDRESS_LOW = 0x0a;
+ static constexpr int REG1_TRANSFER_COUNT = 0x0c;
+ static constexpr int REG1_CONTROL_ARM = 0x0e;
+ static constexpr int REG1_STATUS = 0x0e;
+
+ static constexpr uint8_t REG_CONTROL_IE = 1 << 0;
+ static constexpr uint8_t REG_CONTROL_WORD = 1 << 1;
+ static constexpr uint8_t REG_CONTROL_OUT = 1 << 2;
+ static constexpr uint8_t REG_CONTROL_PRI = 1 << 3;
+ static constexpr uint8_t REG_CONTROL_INT_MASK = 0x7;
+ static constexpr int REG_CONTROL_INT_SHIFT = 4;
+
+
+ static constexpr uint8_t REG_STATUS_ARMED = 1 << 0;
+ static constexpr uint8_t REG_STATUS_INT = 1 << 1;
+
+ /* general control registers */
+ static constexpr int REG_1TQ4_ID_LOW = 0x10;
+ static constexpr int REG_1TQ4_ID_HIGH = 0x12;
+ static constexpr int REG_GENERAL_CONTROL = 0x14;
+ static constexpr int REG_GENERAL_CONTROL_RESET0 = 1 << 4;
+ static constexpr int REG_GENERAL_CONTROL_RESET1 = 1 << 5;
+
+ /* channel specific registers */
+ static constexpr int REG0_1TQ4_ADDRESS_HIGH = 0x100;
+ static constexpr int REG0_1TQ4_ADDRESS_LOW = 0x102;
+ static constexpr int REG0_1TQ4_TRANSFER_COUNT_HIGH = 0x104;
+ static constexpr int REG0_1TQ4_TRANSFER_COUNT_LOW = 0x106;
+
+ static constexpr int REG0_1TQ4_CONTROL = 0x108;
+ static constexpr int REG0_1TQ4_STATUS = 0x10a;
+
+ static constexpr uint16_t REG_1TQ4_CONTROL_LWORD = 1 << 8;
+ static constexpr uint16_t REG_1TQ4_CONTROL_START = 1 << 15;
+
+ static constexpr uint16_t REG_1TQ4_STATUS_ARMED = 1 << 0;
+ static constexpr uint16_t REG_1TQ4_STATUS_INT = 1 << 1;
+
+ /* registers */
+ static constexpr int REG1_1TQ4_ADDRESS_HIGH = 0x200;
+ static constexpr int REG1_1TQ4_ADDRESS_LOW = 0x202;
+ static constexpr int REG1_1TQ4_TRANSFER_COUNT_HIGH = 0x204;
+ static constexpr int REG1_1TQ4_TRANSFER_COUNT_LOW = 0x206;
+
+ static constexpr int REG1_1TQ4_CONTROL = 0x208;
+ static constexpr int REG1_1TQ4_STATUS = 0x20a;
+
+ void dmar0_in(int state) override;
+ void dmar1_in(int state) override;
+
+ bool dma_transfer(int channel);
+ void update_irq();
+ void update_ctrl(const int channel, const uint16_t data, const bool is_1tq4);
+
+ bool m_installed_io;
+ int m_icount;
+ uint8_t m_control;
+ uint8_t m_data;
+ bool m_irq_state;
+
+ struct dma_regs {
+ uint32_t address = 0;
+ uint32_t tc = 0;
+ uint32_t control = 0;
+ /* control register */
+ int irq_level = 0;
+ int tsz = 0;
+ int subcount = 0;
+
+ bool irq = false;
+ bool ie = false;
+ bool armed = false;
+
+ bool dma_out = false;
+ bool dma_pri = false; // TODO
+ bool lword = false;
+ bool word = false;
+ } m_regs[2];
+
+ bool m_dmar[2];
+};
dio16_98620_device::dio16_98620_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) :
dio16_98620_device(mconfig, HPDIO_98620, tag, owner, clock)
@@ -24,50 +136,55 @@ dio16_98620_device::dio16_98620_device(const machine_config &mconfig, const char
}
dio16_98620_device::dio16_98620_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_dio32_card_interface(mconfig, *this),
- m_irq_state(false)
+ device_t{mconfig, type, tag, owner, clock},
+ device_execute_interface{mconfig, *this},
+ device_dio16_card_interface{mconfig, *this},
+ m_installed_io{false},
+ m_icount{0},
+ m_control{0},
+ m_data{0},
+ m_irq_state{false},
+ m_dmar {false}
{
}
+void dio16_98620_device::execute_run()
+{
+ bool busy0, busy1;
+
+ do {
+ busy0 = dma_transfer(0);
+ busy1 = dma_transfer(1);
+ if (!busy0 && !busy1)
+ suspend(SUSPEND_REASON_TRIGGER, 1);
+ } while(--m_icount > 0);
+}
+
void dio16_98620_device::device_start()
{
m_installed_io = false;
-
- save_item(NAME(m_regs[0].address));
- save_item(NAME(m_regs[0].tc));
- save_item(NAME(m_regs[0].control));
- save_item(NAME(m_regs[0].irq_level));
- save_item(NAME(m_regs[0].tsz));
- save_item(NAME(m_regs[0].subcount));
- save_item(NAME(m_regs[0].irq));
- save_item(NAME(m_regs[0].ie));
- save_item(NAME(m_regs[0].armed));
- save_item(NAME(m_regs[0].dma_out));
- save_item(NAME(m_regs[0].dma_pri));
- save_item(NAME(m_regs[0].lword));
- save_item(NAME(m_regs[0].word));
-
-
- save_item(NAME(m_regs[1].address));
- save_item(NAME(m_regs[1].tc));
- save_item(NAME(m_regs[1].control));
- save_item(NAME(m_regs[1].irq_level));
- save_item(NAME(m_regs[1].tsz));
- save_item(NAME(m_regs[1].subcount));
- save_item(NAME(m_regs[1].irq));
- save_item(NAME(m_regs[1].ie));
- save_item(NAME(m_regs[1].armed));
- save_item(NAME(m_regs[1].dma_out));
- save_item(NAME(m_regs[1].dma_pri));
- save_item(NAME(m_regs[1].lword));
- save_item(NAME(m_regs[1].word));
+ set_icountptr(m_icount);
+ set_clock(10_MHz_XTAL);
+
+ save_item(STRUCT_MEMBER(m_regs, address));
+ save_item(STRUCT_MEMBER(m_regs, tc));
+ save_item(STRUCT_MEMBER(m_regs, control));
+ save_item(STRUCT_MEMBER(m_regs, irq_level));
+ save_item(STRUCT_MEMBER(m_regs, tsz));
+ save_item(STRUCT_MEMBER(m_regs, subcount));
+ save_item(STRUCT_MEMBER(m_regs, irq));
+ save_item(STRUCT_MEMBER(m_regs, ie));
+ save_item(STRUCT_MEMBER(m_regs, armed));
+ save_item(STRUCT_MEMBER(m_regs, dma_out));
+ save_item(STRUCT_MEMBER(m_regs, dma_pri));
+ save_item(STRUCT_MEMBER(m_regs, lword));
+ save_item(STRUCT_MEMBER(m_regs, word));
save_item(NAME(m_installed_io));
save_item(NAME(m_control));
save_item(NAME(m_data));
save_item(NAME(m_irq_state));
- save_item(NAME(dmar));
+ save_item(NAME(m_dmar));
}
void dio16_98620_device::device_reset()
@@ -75,35 +192,15 @@ void dio16_98620_device::device_reset()
if (!m_installed_io)
{
program_space().install_readwrite_handler(0x500000, 0x50020f,
- read16_delegate(FUNC(dio16_98620_device::dma_r), this),
- write16_delegate(FUNC(dio16_98620_device::dma_w), this));
+ read16sm_delegate(*this, FUNC(dio16_98620_device::dma_r)),
+ write16sm_delegate(*this, FUNC(dio16_98620_device::dma_w)));
m_installed_io = true;
}
m_control = 0;
m_irq_state = false;
}
-uint16_t dio16_98620_device::get_ctrl(const int channel)
-{
- uint16_t ret = 0;
-
- if (m_regs[channel].ie)
- ret |= REG_CONTROL_IE;
- if (m_regs[channel].tsz == 2)
- ret |= REG_CONTROL_WORD;
- if (m_regs[channel].tsz == 4)
- ret |= REG_1TQ4_CONTROL_LWORD;
- if (m_regs[channel].dma_out)
- ret |= REG_CONTROL_OUT;
- if (m_regs[channel].dma_pri)
- ret |= REG_CONTROL_PRI;
-
- ret |= ((m_regs[channel].irq_level-3) & REG_CONTROL_INT_MASK) << REG_CONTROL_INT_SHIFT;
-
- return ret;
-}
-
-READ16_MEMBER(dio16_98620_device::dma_r)
+uint16_t dio16_98620_device::dma_r(offs_t offset)
{
uint16_t ret = 0;
@@ -228,12 +325,12 @@ void dio16_98620_device::update_ctrl(const int channel, const uint16_t data, con
m_regs[channel].subcount = m_regs[channel].tsz-1;
m_regs[channel].armed = true;
m_regs[channel].irq = false;
- if (dmar[channel])
+ if (m_dmar[channel])
dma_transfer(channel);
}
}
-WRITE16_MEMBER(dio16_98620_device::dma_w)
+void dio16_98620_device::dma_w(offs_t offset, uint16_t data)
{
LOG("dma_w: offset=%02X, data=%02X\n", offset << 1, data);
@@ -311,6 +408,7 @@ WRITE16_MEMBER(dio16_98620_device::dma_w)
LOG("%s: unknown register write: %02X\n", __FUNCTION__, offset << 1);
break;
}
+ trigger(0);
}
void dio16_98620_device::update_irq()
@@ -331,16 +429,19 @@ void dio16_98620_device::update_irq()
(m_regs[1].irq_level == 7 && m_regs[1].irq && m_regs[1].ie));
}
-void dio16_98620_device::dma_transfer(int channel)
+bool dio16_98620_device::dma_transfer(int channel)
{
assert(channel < 2);
if (!(m_regs[channel].armed))
- return;
+ return false;
- LOG("dma_transfer %s: tc %d/%d\n", m_regs[channel].dma_out ? "out" : "in",
- m_regs[channel].tc, m_regs[channel].subcount);
+ if (!m_dmar[channel])
+ return false;
+ LOG("dma_transfer %s: tc %d/%d\n",
+ m_regs[channel].dma_out ? "out" : "in",
+ m_regs[channel].tc, m_regs[channel].subcount);
if (m_regs[channel].dma_out) {
dmack_w_out(channel, program_space().read_byte(m_regs[channel].address++));
@@ -357,36 +458,29 @@ void dio16_98620_device::dma_transfer(int channel)
m_regs[channel].irq = true;
update_irq();
}
- return;
+ return false;
}
-
m_regs[channel].subcount = m_regs[channel].tsz;
}
m_regs[channel].subcount--;
+ return true;
}
-WRITE_LINE_MEMBER(dio16_98620_device::dmar0_in)
+void dio16_98620_device::dmar0_in(int state)
{
LOG("%s: %d\n", __FUNCTION__, state);
- dmar[0] = state;
- if (!state)
- return;
-
- dma_transfer(0);
+ m_dmar[0] = state;
+ trigger(0);
}
-WRITE_LINE_MEMBER(dio16_98620_device::dmar1_in)
+void dio16_98620_device::dmar1_in(int state)
{
LOG("%s: %d\n", __FUNCTION__, state);
- dmar[1] = state;
-
- if (!state)
- return;
-
- dma_transfer(1);
+ m_dmar[1] = state;
+ trigger(0);
}
-} // namespace bus::hp_dio
-} // namespace bus
+} // anonymous namespace
+DEFINE_DEVICE_TYPE_PRIVATE(HPDIO_98620, bus::hp_dio::device_dio16_card_interface, dio16_98620_device, "hp98620", "HP98620 DMA Controller")
diff --git a/src/devices/bus/hp_dio/hp98620.h b/src/devices/bus/hp_dio/hp98620.h
index e9fd2b8122b..887a1535ddf 100644
--- a/src/devices/bus/hp_dio/hp98620.h
+++ b/src/devices/bus/hp_dio/hp98620.h
@@ -1,132 +1,13 @@
// license:BSD-3-Clause
// copyright-holders:Sven Schnelle
-#ifndef MAME_BUS_HPDIO_98620_H
-#define MAME_BUS_HPDIO_98620_H
+#ifndef MAME_BUS_HP_DIO_HP98620_H
+#define MAME_BUS_HP_DIO_HP98620_H
#pragma once
#include "hp_dio.h"
+DECLARE_DEVICE_TYPE_NS(HPDIO_98620, bus::hp_dio, device_dio16_card_interface)
-namespace bus {
- namespace hp_dio {
-
-class dio16_98620_device :
- public device_t,
- public device_dio32_card_interface
-{
-public:
- // construction/destruction
- dio16_98620_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
-
-protected:
- dio16_98620_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;
-
- DECLARE_READ16_MEMBER(dma_r);
- DECLARE_WRITE16_MEMBER(dma_w);
-
- DECLARE_WRITE_LINE_MEMBER(irq_w);
-
-private:
-
- static constexpr int REG0_RESET_ARM_INT = 0x00;
- static constexpr int REG0_ADDRESS_HIGH = 0x00;
- static constexpr int REG0_ADDRESS_LOW = 0x02;
- static constexpr int REG0_TRANSFER_COUNT = 0x04;
- static constexpr int REG0_CONTROL_ARM = 0x06;
- static constexpr int REG0_STATUS = 0x06;
-
- static constexpr int REG1_RESET_ARM_INT = 0x08;
- static constexpr int REG1_ADDRESS_HIGH = 0x08;
- static constexpr int REG1_ADDRESS_LOW = 0x0a;
- static constexpr int REG1_TRANSFER_COUNT = 0x0c;
- static constexpr int REG1_CONTROL_ARM = 0x0e;
- static constexpr int REG1_STATUS = 0x0e;
-
- static constexpr uint8_t REG_CONTROL_IE = 1 << 0;
- static constexpr uint8_t REG_CONTROL_WORD = 1 << 1;
- static constexpr uint8_t REG_CONTROL_OUT = 1 << 2;
- static constexpr uint8_t REG_CONTROL_PRI = 1 << 3;
- static constexpr uint8_t REG_CONTROL_INT_MASK = 0x7;
- static constexpr int REG_CONTROL_INT_SHIFT = 4;
-
-
- static constexpr uint8_t REG_STATUS_ARMED = 1 << 0;
- static constexpr uint8_t REG_STATUS_INT = 1 << 1;
-
- /* general control registers */
- static constexpr int REG_1TQ4_ID_LOW = 0x10;
- static constexpr int REG_1TQ4_ID_HIGH = 0x12;
- static constexpr int REG_GENERAL_CONTROL = 0x14;
- static constexpr int REG_GENERAL_CONTROL_RESET0 = 1 << 4;
- static constexpr int REG_GENERAL_CONTROL_RESET1 = 1 << 5;
-
- /* channel specific registers */
- static constexpr int REG0_1TQ4_ADDRESS_HIGH = 0x100;
- static constexpr int REG0_1TQ4_ADDRESS_LOW = 0x102;
- static constexpr int REG0_1TQ4_TRANSFER_COUNT_HIGH = 0x104;
- static constexpr int REG0_1TQ4_TRANSFER_COUNT_LOW = 0x106;
-
- static constexpr int REG0_1TQ4_CONTROL = 0x108;
- static constexpr int REG0_1TQ4_STATUS = 0x10a;
-
- static constexpr uint16_t REG_1TQ4_CONTROL_LWORD = 1 << 8;
- static constexpr uint16_t REG_1TQ4_CONTROL_START = 1 << 15;
-
- static constexpr uint16_t REG_1TQ4_STATUS_ARMED = 1 << 0;
- static constexpr uint16_t REG_1TQ4_STATUS_INT = 1 << 1;
-
- /* registers */
- static constexpr int REG1_1TQ4_ADDRESS_HIGH = 0x200;
- static constexpr int REG1_1TQ4_ADDRESS_LOW = 0x202;
- static constexpr int REG1_1TQ4_TRANSFER_COUNT_HIGH = 0x204;
- static constexpr int REG1_1TQ4_TRANSFER_COUNT_LOW = 0x206;
-
- 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 dma_transfer(int channel);
- void update_irq();
- void update_ctrl(const int channel, const uint16_t data, const bool is_1tq4);
- uint16_t get_ctrl(const int channel);
-
- bool m_installed_io;
- uint8_t m_control;
- uint8_t m_data;
- bool m_irq_state;
-
- struct dma_regs {
- uint32_t address;
- uint32_t tc;
- uint32_t control;
- /* control register */
- int irq_level;
- int tsz;
- int subcount;
-
- bool irq;
- bool ie;
- bool armed;
-
- bool dma_out;
- bool dma_pri; // TODO
- bool lword;
- bool word;
- } m_regs[2];
-
- bool dmar[2];
-};
-
-} } // namespace bus::hp_dio
-
-DECLARE_DEVICE_TYPE_NS(HPDIO_98620, bus::hp_dio, dio16_98620_device)
-
-#endif // MAME_BUS_HPDIO_98620_H
+#endif // MAME_BUS_HP_DIO_HP98620_H
diff --git a/src/devices/bus/hp_dio/hp98624.cpp b/src/devices/bus/hp_dio/hp98624.cpp
new file mode 100644
index 00000000000..a5a8265e63b
--- /dev/null
+++ b/src/devices/bus/hp_dio/hp98624.cpp
@@ -0,0 +1,340 @@
+// license:BSD-3-Clause
+// copyright-holders:Sven Schnelle
+/***************************************************************************
+
+ HP98624 GPIB interface
+
+***************************************************************************/
+
+#include "emu.h"
+#include "hp98624.h"
+
+#include "bus/ieee488/ieee488.h"
+#include "machine/tms9914.h"
+
+//#define VERBOSE 1
+#include "logmacro.h"
+
+namespace {
+
+class dio16_98624_device :
+ public device_t,
+ public bus::hp_dio::device_dio16_card_interface
+{
+public:
+ dio16_98624_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
+
+protected:
+ dio16_98624_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock);
+
+ virtual void device_start() override ATTR_COLD;
+ virtual void device_reset() override ATTR_COLD;
+
+ virtual ioport_constructor device_input_ports() const override ATTR_COLD;
+ virtual void device_add_mconfig(machine_config &config) override ATTR_COLD;
+
+ void dmack_w_in(int channel, uint8_t data) override;
+ uint8_t dmack_r_in(int channel) override;
+
+ uint16_t io_r(offs_t offset);
+ void io_w(offs_t offset, uint16_t data);
+
+ required_device<tms9914_device> m_tms9914;
+ required_device<ieee488_device> m_ieee488;
+ required_ioport m_switches;
+
+private:
+ void update_gpib_irq();
+ void update_gpib_dma();
+ void gpib_irq(int state);
+ void gpib_dreq(int state);
+
+ bool m_gpib_irq_line;
+ bool m_gpib_dma_line;
+
+ bool m_installed_io;
+ uint8_t m_control;
+};
+
+void dio16_98624_device::device_add_mconfig(machine_config &config)
+{
+ tms9914_device &gpib(TMS9914(config, "tms9914", XTAL(5'000'000)));
+ gpib.eoi_write_cb().set(IEEE488_TAG, FUNC(ieee488_device::host_eoi_w));
+ gpib.dav_write_cb().set(IEEE488_TAG, FUNC(ieee488_device::host_dav_w));
+ gpib.nrfd_write_cb().set(IEEE488_TAG, FUNC(ieee488_device::host_nrfd_w));
+ gpib.ndac_write_cb().set(IEEE488_TAG, FUNC(ieee488_device::host_ndac_w));
+ gpib.ifc_write_cb().set(IEEE488_TAG, FUNC(ieee488_device::host_ifc_w));
+ gpib.srq_write_cb().set(IEEE488_TAG, FUNC(ieee488_device::host_srq_w));
+ gpib.atn_write_cb().set(IEEE488_TAG, FUNC(ieee488_device::host_atn_w));
+ gpib.ren_write_cb().set(IEEE488_TAG, FUNC(ieee488_device::host_ren_w));
+ gpib.dio_write_cb().set(IEEE488_TAG, FUNC(ieee488_device::host_dio_w));
+ gpib.dio_read_cb().set(IEEE488_TAG, FUNC(ieee488_device::dio_r));
+ gpib.int_write_cb().set(FUNC(dio16_98624_device::gpib_irq));
+ gpib.accrq_write_cb().set(FUNC(dio16_98624_device::gpib_dreq));
+
+ ieee488_device &ieee488(IEEE488(config, IEEE488_TAG, 0));
+ ieee488.eoi_callback().set(m_tms9914, FUNC(tms9914_device::eoi_w));
+ ieee488.dav_callback().set(m_tms9914, FUNC(tms9914_device::dav_w));
+ ieee488.nrfd_callback().set(m_tms9914, FUNC(tms9914_device::nrfd_w));
+ ieee488.ndac_callback().set(m_tms9914, FUNC(tms9914_device::ndac_w));
+ ieee488.ifc_callback().set(m_tms9914, FUNC(tms9914_device::ifc_w));
+ ieee488.srq_callback().set(m_tms9914, FUNC(tms9914_device::srq_w));
+ ieee488.atn_callback().set(m_tms9914, FUNC(tms9914_device::atn_w));
+ ieee488.ren_callback().set(m_tms9914, FUNC(tms9914_device::ren_w));
+
+ ieee488_slot_device &slot0(IEEE488_SLOT(config, "ieee0", 0));
+ hp_ieee488_devices(slot0);
+}
+
+dio16_98624_device::dio16_98624_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) :
+ dio16_98624_device(mconfig, HPDIO_98624, tag, owner, clock)
+{
+}
+
+dio16_98624_device::dio16_98624_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_dio16_card_interface(mconfig, *this),
+ m_tms9914{*this, "tms9914"},
+ m_ieee488{*this, IEEE488_TAG},
+ m_switches{*this, "switches"},
+ m_installed_io{false},
+ m_control{0}
+{
+}
+
+constexpr unsigned REG_SWITCHES_SC = 0x01;
+constexpr unsigned REG_SWITCHES_REMOTE = 0x02;
+
+constexpr unsigned REG_SWITCHES_INT_LEVEL_MASK = 3;
+constexpr unsigned REG_SWITCHES_INT_LEVEL_SHIFT = 2;
+
+constexpr unsigned REG_SWITCHES_SELECT_CODE_MASK = 31;
+constexpr unsigned REG_SWITCHES_SELECT_CODE_SHIFT = 4;
+
+constexpr unsigned REG_SWITCHES_GPIB_ADDR_MASK = 31;
+constexpr unsigned REG_SWITCHES_GPIB_ADDR_SHIFT = 9;
+
+static INPUT_PORTS_START(hp98624_port)
+ PORT_START("switches")
+ PORT_DIPNAME(REG_SWITCHES_SC, REG_SWITCHES_SC, "System Controller")
+ PORT_DIPSETTING(0x00, DEF_STR(Off))
+ PORT_DIPSETTING(REG_SWITCHES_SC, DEF_STR(On))
+
+ PORT_DIPNAME(REG_SWITCHES_REMOTE, 0x00, "Remote")
+ PORT_DIPSETTING(0x00, DEF_STR(Off))
+ PORT_DIPSETTING(REG_SWITCHES_REMOTE, DEF_STR(On))
+
+ PORT_DIPNAME(REG_SWITCHES_INT_LEVEL_MASK << REG_SWITCHES_INT_LEVEL_SHIFT, 0x00 << REG_SWITCHES_INT_LEVEL_SHIFT, "Interrupt level")
+ PORT_DIPSETTING(0 << REG_SWITCHES_INT_LEVEL_SHIFT, "3")
+ PORT_DIPSETTING(1 << REG_SWITCHES_INT_LEVEL_SHIFT, "4")
+ PORT_DIPSETTING(2 << REG_SWITCHES_INT_LEVEL_SHIFT, "5")
+ PORT_DIPSETTING(3 << REG_SWITCHES_INT_LEVEL_SHIFT, "6")
+
+ PORT_DIPNAME(REG_SWITCHES_SELECT_CODE_MASK << REG_SWITCHES_SELECT_CODE_SHIFT, 0x08 << REG_SWITCHES_SELECT_CODE_SHIFT, "Select code")
+ PORT_DIPSETTING(0 << REG_SWITCHES_SELECT_CODE_SHIFT, "0")
+ PORT_DIPSETTING(1 << REG_SWITCHES_SELECT_CODE_SHIFT, "1")
+ PORT_DIPSETTING(2 << REG_SWITCHES_SELECT_CODE_SHIFT, "2")
+ PORT_DIPSETTING(3 << REG_SWITCHES_SELECT_CODE_SHIFT, "3")
+ PORT_DIPSETTING(4 << REG_SWITCHES_SELECT_CODE_SHIFT, "4")
+ PORT_DIPSETTING(5 << REG_SWITCHES_SELECT_CODE_SHIFT, "5")
+ PORT_DIPSETTING(6 << REG_SWITCHES_SELECT_CODE_SHIFT, "6")
+ PORT_DIPSETTING(7 << REG_SWITCHES_SELECT_CODE_SHIFT, "7")
+ PORT_DIPSETTING(8 << REG_SWITCHES_SELECT_CODE_SHIFT, "8")
+ PORT_DIPSETTING(9 << REG_SWITCHES_SELECT_CODE_SHIFT, "9")
+ PORT_DIPSETTING(10 << REG_SWITCHES_SELECT_CODE_SHIFT, "10")
+ PORT_DIPSETTING(11 << REG_SWITCHES_SELECT_CODE_SHIFT, "11")
+ PORT_DIPSETTING(12 << REG_SWITCHES_SELECT_CODE_SHIFT, "12")
+ PORT_DIPSETTING(13 << REG_SWITCHES_SELECT_CODE_SHIFT, "13")
+ PORT_DIPSETTING(14 << REG_SWITCHES_SELECT_CODE_SHIFT, "14")
+ PORT_DIPSETTING(15 << REG_SWITCHES_SELECT_CODE_SHIFT, "15")
+ PORT_DIPSETTING(16 << REG_SWITCHES_SELECT_CODE_SHIFT, "16")
+ PORT_DIPSETTING(17 << REG_SWITCHES_SELECT_CODE_SHIFT, "17")
+ PORT_DIPSETTING(18 << REG_SWITCHES_SELECT_CODE_SHIFT, "18")
+ PORT_DIPSETTING(19 << REG_SWITCHES_SELECT_CODE_SHIFT, "19")
+ PORT_DIPSETTING(20 << REG_SWITCHES_SELECT_CODE_SHIFT, "20")
+ PORT_DIPSETTING(21 << REG_SWITCHES_SELECT_CODE_SHIFT, "21")
+ PORT_DIPSETTING(22 << REG_SWITCHES_SELECT_CODE_SHIFT, "22")
+ PORT_DIPSETTING(23 << REG_SWITCHES_SELECT_CODE_SHIFT, "23")
+ PORT_DIPSETTING(24 << REG_SWITCHES_SELECT_CODE_SHIFT, "24")
+ PORT_DIPSETTING(25 << REG_SWITCHES_SELECT_CODE_SHIFT, "25")
+ PORT_DIPSETTING(26 << REG_SWITCHES_SELECT_CODE_SHIFT, "26")
+ PORT_DIPSETTING(27 << REG_SWITCHES_SELECT_CODE_SHIFT, "27")
+ PORT_DIPSETTING(28 << REG_SWITCHES_SELECT_CODE_SHIFT, "28")
+ PORT_DIPSETTING(29 << REG_SWITCHES_SELECT_CODE_SHIFT, "29")
+ PORT_DIPSETTING(30 << REG_SWITCHES_SELECT_CODE_SHIFT, "30")
+ PORT_DIPSETTING(31 << REG_SWITCHES_SELECT_CODE_SHIFT, "31")
+
+ PORT_DIPNAME(REG_SWITCHES_GPIB_ADDR_MASK << REG_SWITCHES_GPIB_ADDR_SHIFT, 21 << REG_SWITCHES_GPIB_ADDR_SHIFT, "GPIB Adress")
+ PORT_DIPSETTING(0 << REG_SWITCHES_GPIB_ADDR_SHIFT, "0")
+ PORT_DIPSETTING(1 << REG_SWITCHES_GPIB_ADDR_SHIFT, "1")
+ PORT_DIPSETTING(2 << REG_SWITCHES_GPIB_ADDR_SHIFT, "2")
+ PORT_DIPSETTING(3 << REG_SWITCHES_GPIB_ADDR_SHIFT, "3")
+ PORT_DIPSETTING(4 << REG_SWITCHES_GPIB_ADDR_SHIFT, "4")
+ PORT_DIPSETTING(5 << REG_SWITCHES_GPIB_ADDR_SHIFT, "5")
+ PORT_DIPSETTING(6 << REG_SWITCHES_GPIB_ADDR_SHIFT, "6")
+ PORT_DIPSETTING(7 << REG_SWITCHES_GPIB_ADDR_SHIFT, "7")
+ PORT_DIPSETTING(8 << REG_SWITCHES_GPIB_ADDR_SHIFT, "8")
+ PORT_DIPSETTING(9 << REG_SWITCHES_GPIB_ADDR_SHIFT, "9")
+ PORT_DIPSETTING(10 << REG_SWITCHES_GPIB_ADDR_SHIFT, "10")
+ PORT_DIPSETTING(11 << REG_SWITCHES_GPIB_ADDR_SHIFT, "11")
+ PORT_DIPSETTING(12 << REG_SWITCHES_GPIB_ADDR_SHIFT, "12")
+ PORT_DIPSETTING(13 << REG_SWITCHES_GPIB_ADDR_SHIFT, "13")
+ PORT_DIPSETTING(14 << REG_SWITCHES_GPIB_ADDR_SHIFT, "14")
+ PORT_DIPSETTING(15 << REG_SWITCHES_GPIB_ADDR_SHIFT, "15")
+ PORT_DIPSETTING(16 << REG_SWITCHES_GPIB_ADDR_SHIFT, "16")
+ PORT_DIPSETTING(17 << REG_SWITCHES_GPIB_ADDR_SHIFT, "17")
+ PORT_DIPSETTING(18 << REG_SWITCHES_GPIB_ADDR_SHIFT, "18")
+ PORT_DIPSETTING(19 << REG_SWITCHES_GPIB_ADDR_SHIFT, "19")
+ PORT_DIPSETTING(20 << REG_SWITCHES_GPIB_ADDR_SHIFT, "20")
+ PORT_DIPSETTING(21 << REG_SWITCHES_GPIB_ADDR_SHIFT, "21")
+ PORT_DIPSETTING(22 << REG_SWITCHES_GPIB_ADDR_SHIFT, "22")
+ PORT_DIPSETTING(23 << REG_SWITCHES_GPIB_ADDR_SHIFT, "23")
+ PORT_DIPSETTING(24 << REG_SWITCHES_GPIB_ADDR_SHIFT, "24")
+ PORT_DIPSETTING(25 << REG_SWITCHES_GPIB_ADDR_SHIFT, "25")
+ PORT_DIPSETTING(26 << REG_SWITCHES_GPIB_ADDR_SHIFT, "26")
+ PORT_DIPSETTING(27 << REG_SWITCHES_GPIB_ADDR_SHIFT, "27")
+ PORT_DIPSETTING(28 << REG_SWITCHES_GPIB_ADDR_SHIFT, "28")
+ PORT_DIPSETTING(29 << REG_SWITCHES_GPIB_ADDR_SHIFT, "29")
+ PORT_DIPSETTING(30 << REG_SWITCHES_GPIB_ADDR_SHIFT, "30")
+ PORT_DIPSETTING(31 << REG_SWITCHES_GPIB_ADDR_SHIFT, "31")
+INPUT_PORTS_END
+
+ioport_constructor dio16_98624_device::device_input_ports() const
+{
+ return INPUT_PORTS_NAME(hp98624_port);
+}
+
+void dio16_98624_device::device_start()
+{
+ save_item(NAME(m_installed_io));
+ save_item(NAME(m_control));
+ m_installed_io = false;
+}
+
+void dio16_98624_device::device_reset()
+{
+ uint8_t code = m_switches->read() >> REG_SWITCHES_SELECT_CODE_SHIFT;
+ code &= REG_SWITCHES_SELECT_CODE_MASK;
+
+ if (!m_installed_io)
+ {
+ dio().install_memory(
+ 0x600000 + (code * 0x10000),
+ 0x6007ff + (code * 0x10000),
+ read16sm_delegate(*this, FUNC(dio16_98624_device::io_r)),
+ write16sm_delegate(*this, FUNC(dio16_98624_device::io_w)));
+ m_installed_io = true;
+ }
+ m_control = 0;
+}
+
+void dio16_98624_device::update_gpib_irq()
+{
+ bool enable = m_control & 0x80;
+
+ switch((m_switches->read() >> REG_SWITCHES_INT_LEVEL_SHIFT) & REG_SWITCHES_INT_LEVEL_MASK) {
+ case 0:
+ irq3_out(enable && m_gpib_irq_line);
+ break;
+ case 1:
+ irq4_out(enable && m_gpib_irq_line);
+ break;
+ case 2:
+ irq5_out(enable && m_gpib_irq_line);
+ break;
+ case 3:
+ irq6_out(enable && m_gpib_irq_line);
+ break;
+ }
+}
+
+void dio16_98624_device::gpib_irq(int state)
+{
+ m_gpib_irq_line = state;
+ update_gpib_irq();
+}
+
+void dio16_98624_device::update_gpib_dma()
+{
+ dmar0_out((m_control & 1) && m_gpib_dma_line);
+ dmar1_out((m_control & 2) && m_gpib_dma_line);
+}
+
+void dio16_98624_device::gpib_dreq(int state)
+{
+ m_gpib_dma_line = state;
+ update_gpib_dma();
+}
+
+uint16_t dio16_98624_device::io_r(offs_t offset)
+{
+ uint16_t ret = 0xffff;
+
+ if (offset & 8)
+ return m_tms9914->read(offset & 0x07);
+
+ switch(offset) {
+ case 0: /* ID */
+ ret = 0x01;
+ if (!(m_switches->read() & REG_SWITCHES_REMOTE))
+ ret |= 0x80;
+ break;
+
+ case 1:
+ ret = m_control;
+ ret |= m_gpib_irq_line ? 0x40 : 0;
+ ret |= ((m_switches->read() >> REG_SWITCHES_INT_LEVEL_SHIFT) & REG_SWITCHES_INT_LEVEL_MASK) << 4;
+ break;
+ case 2:
+ ret = (m_switches->read() & REG_SWITCHES_SC) ? 0x80 : 0;
+ ret |= (m_tms9914->cont_r() ? 0x0 : 0x40) | 0x80;
+ ret |= (m_switches->read() >> REG_SWITCHES_GPIB_ADDR_SHIFT) & REG_SWITCHES_GPIB_ADDR_MASK;
+ break;
+ default:
+ break;
+ }
+ LOG("%s: %02x = %02x\n", __func__, offset, ret);
+ return ret;
+}
+
+void dio16_98624_device::io_w(offs_t offset, uint16_t data)
+{
+ LOG("%s: %02x = %02x\n", __func__, offset, data);
+ if (offset & 0x08) {
+ m_tms9914->write(offset & 0x07, data);
+ return;
+ }
+
+ switch(offset) {
+ case 1:
+ m_control = data & 0x8b;
+ update_gpib_dma();
+ update_gpib_irq();
+ break;
+ default:
+ break;
+ }
+}
+
+void dio16_98624_device::dmack_w_in(int channel, uint8_t data)
+{
+ if (channel == 0 && (m_control & 1))
+ m_tms9914->write(7, data);
+ if (channel == 1 && (m_control & 2))
+ m_tms9914->write(7, data);
+}
+
+uint8_t dio16_98624_device::dmack_r_in(int channel)
+{
+ uint8_t ret = 0xff;
+
+ if (channel == 0 && (m_control & 1))
+ ret = m_tms9914->read(7);
+ if (channel == 1 && (m_control & 2))
+ ret = m_tms9914->read(7);
+ return ret;
+}
+
+} // anonymous namespace
+
+DEFINE_DEVICE_TYPE_PRIVATE(HPDIO_98624, bus::hp_dio::device_dio16_card_interface, dio16_98624_device, "dio98624", "HP98624 GPIB Interface")
diff --git a/src/devices/bus/hp_dio/hp98624.h b/src/devices/bus/hp_dio/hp98624.h
new file mode 100644
index 00000000000..71001500306
--- /dev/null
+++ b/src/devices/bus/hp_dio/hp98624.h
@@ -0,0 +1,13 @@
+// license:BSD-3-Clause
+// copyright-holders:Sven Schnelle
+
+#ifndef MAME_BUS_HP_DIO_HP98624_H
+#define MAME_BUS_HP_DIO_HP98624_H
+
+#pragma once
+
+#include "hp_dio.h"
+
+DECLARE_DEVICE_TYPE_NS(HPDIO_98624, bus::hp_dio, device_dio16_card_interface)
+
+#endif // MAME_BUS_HP_DIO_HP98624_H
diff --git a/src/devices/bus/hp_dio/hp98628_9.cpp b/src/devices/bus/hp_dio/hp98628_9.cpp
new file mode 100644
index 00000000000..e4bc6ed8b3a
--- /dev/null
+++ b/src/devices/bus/hp_dio/hp98628_9.cpp
@@ -0,0 +1,1152 @@
+// license:BSD-3-Clause
+// copyright-holders:F. Ulivi
+
+/*********************************************************************
+
+ HP98628 Data communication interface
+ HP98629 SRM interface
+
+ HP98628 is an asynchronous & synchronous serial interface card.
+ HP98629 is a special card to interface to what HP called a
+ SRM network (Shared Resource Manager). A SRM network connects
+ multiple workstations to a computer acting as a NAS (in modern
+ parlance). This MAME driver also emulates a HP98028 multiplexer,
+ which is a kind of 5-port network bridge. One port is connected
+ to emulated card, another port to a bitbanger interface and the
+ remaining 3 ports are not emulated.
+ For an overview of SRM see:
+ https://www.hp9845.net/9845/tutorials/networks/index.html
+
+ From the hardware point of view these cards are very similar,
+ they are both based on a Z80CPU-Z80SIO-Z80CTC trio and a dual
+ port RAM to interface to 68k. They differ in the firmware ROM
+ and in the amount of dual-port RAM.
+ A 50-pin custom connector exposes RS232 and RS422 signals on
+ these cards.
+
+ Reference docs for these cards:
+ - HP, 98028-90000, HP98629A Resource Management Interface
+ Schematic Diagram
+ - HP98628 schematic diagram by Tony Duell
+ - HP, 5955-6582, Jul 82, 98628/98629 Hardware External Reference
+ Specification
+ - HP, 98028-90000, HP98028A Resource Management Multiplexer
+ Schematic Diagram
+
+*********************************************************************/
+
+#include "emu.h"
+#include "hp98628_9.h"
+
+#include "bus/rs232/rs232.h"
+#include "cpu/z80/z80.h"
+#include "imagedev/bitbngr.h"
+#include "machine/timer.h"
+#include "machine/z80ctc.h"
+#include "machine/z80sio.h"
+
+// Debugging
+//#define VERBOSE 1
+#include "logmacro.h"
+
+namespace {
+
+// Clock
+constexpr auto CLOCK = 7.3728_MHz_XTAL;
+
+// Bit manipulation
+template<typename T> constexpr T BIT_MASK(unsigned n)
+{
+ return (T)1U << n;
+}
+
+template<typename T> void BIT_CLR(T& w , unsigned n)
+{
+ w &= ~BIT_MASK<T>(n);
+}
+
+template<typename T> void BIT_SET(T& w , unsigned n)
+{
+ w |= BIT_MASK<T>(n);
+}
+
+// +---------------------+
+// | base_98628_9_device |
+// +---------------------+
+class base_98628_9_device :
+ public device_t,
+ public bus::hp_dio::device_dio16_card_interface
+{
+public:
+ // Input signals
+ void rx_in(int state);
+ void cts_in(int state);
+ void dcd_in(int state);
+ void ri_in(int state);
+ void dsr_in(int state);
+ void st_in(int state);
+ void rt_in(int state);
+
+protected:
+ static inline constexpr unsigned LOW_RAM_SIZE = 2048;
+
+ base_98628_9_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock);
+
+ virtual void device_start() override ATTR_COLD;
+ virtual void device_reset() override ATTR_COLD;
+
+ virtual void reset_in(int state) override;
+
+ void reset(int state, bool nmi);
+ void update_irq();
+ void update_modem_ctrl();
+ void update_clocks();
+
+ void base_config(machine_config &config) ATTR_COLD;
+ virtual void cpu_program_mem_map(address_map &map) ATTR_COLD;
+ void cpu_io_mem_map(address_map &map) ATTR_COLD;
+ virtual void install_68k_map(offs_t base_addr) ATTR_COLD;
+ uint8_t reg_r(offs_t addr);
+ void reg_w(offs_t addr, uint8_t data);
+ uint8_t low_ram_r_z80(offs_t addr);
+ uint16_t low_ram_r_68k(offs_t addr);
+ void low_ram_w_z80(offs_t addr, uint8_t data);
+ void low_ram_w_68k(offs_t addr, uint16_t data);
+ uint8_t sio_r(offs_t addr);
+ void sio_w(offs_t addr, uint8_t data);
+ void to0_w(int state);
+ void tx_clock_w(int state);
+ void to1_w(int state);
+ void rx_clock_w(int state);
+ void update_cpu_wait();
+ void sio_wrdya_w(int state);
+ void sio_int_w(int state);
+ void ctc_int_w(int state);
+ uint8_t sw1_r(offs_t addr);
+ // Output signals
+ virtual void tx_out(int state) {}
+ virtual void tt_out(int state) {}
+ virtual void rts_out(int state) {}
+ virtual void dtr_out(int state) {}
+ virtual void ocd1_out(int state) {}
+
+ required_device<z80_device> m_cpu;
+ required_device<z80ctc_device> m_ctc;
+ required_device<z80sio_device> m_sio;
+ required_ioport m_sw1;
+ required_ioport m_sw2;
+
+ bool m_installed_io;
+ bool m_reset;
+ bool m_irq;
+ bool m_irq_enabled;
+ bool m_semaphore;
+ bool m_ctsb;
+ bool m_wait_a;
+ bool m_ctc_irq;
+ bool m_sio_irq;
+ bool m_cpu_wait;
+ bool m_cpu_waiting;
+ bool m_to0_div;
+ bool m_to1_div;
+ bool m_st_in;
+ bool m_rt_in;
+ uint8_t m_modem_ctrl;
+ uint8_t m_modem_status;
+ uint8_t m_low_ram[LOW_RAM_SIZE];
+};
+
+base_98628_9_device::base_98628_9_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock)
+ : device_t(mconfig, type, tag, owner, clock)
+ , bus::hp_dio::device_dio16_card_interface(mconfig, *this)
+ , m_cpu(*this, "cpu")
+ , m_ctc(*this, "ctc")
+ , m_sio(*this, "sio")
+ , m_sw1(*this, "sw1")
+ , m_sw2(*this, "sw2")
+ , m_installed_io{false}
+ , m_cpu_wait{false}
+ , m_cpu_waiting{false}
+ , m_modem_status{0}
+{
+}
+
+void base_98628_9_device::device_start()
+{
+ save_item(NAME(m_installed_io));
+ save_item(NAME(m_reset));
+ save_item(NAME(m_irq));
+ save_item(NAME(m_irq_enabled));
+ save_item(NAME(m_semaphore));
+ save_item(NAME(m_ctsb));
+ save_item(NAME(m_wait_a));
+ save_item(NAME(m_ctc_irq));
+ save_item(NAME(m_sio_irq));
+ save_item(NAME(m_cpu_wait));
+ save_item(NAME(m_cpu_waiting));
+ save_item(NAME(m_to0_div));
+ save_item(NAME(m_to1_div));
+ save_item(NAME(m_st_in));
+ save_item(NAME(m_rt_in));
+ save_item(NAME(m_modem_ctrl));
+ save_item(NAME(m_modem_status));
+ save_item(NAME(m_low_ram));
+}
+
+constexpr unsigned SW2_SWITCH8_BIT = 7;
+constexpr ioport_value SW2_SWITCH8_MASK = BIT_MASK<ioport_value>(SW2_SWITCH8_BIT);
+constexpr unsigned SW2_IRQ_LEVEL_SHIFT = 5;
+constexpr ioport_value SW2_IRQ_LEVEL_MASK = 3;
+constexpr ioport_value SW2_IRQ_LEVEL_IRQ3 = 0;
+constexpr ioport_value SW2_IRQ_LEVEL_IRQ4 = 1;
+constexpr ioport_value SW2_IRQ_LEVEL_IRQ5 = 2;
+constexpr ioport_value SW2_IRQ_LEVEL_IRQ6 = 3;
+constexpr ioport_value SW2_IRQ_LEVEL_DEF = SW2_IRQ_LEVEL_IRQ4;
+constexpr unsigned SW2_SC_SHIFT = 0;
+constexpr ioport_value SW2_SC_MASK = 0x1f;
+constexpr ioport_value SW2_SC_DEF = 21 << SW2_SC_SHIFT;
+
+void base_98628_9_device::device_reset()
+{
+ if (!m_installed_io) {
+ unsigned sc = (m_sw2->read() >> SW2_SC_SHIFT) & SW2_SC_MASK;
+ offs_t base_addr = 0x600000 + sc * 0x10000;
+ install_68k_map(base_addr);
+ m_installed_io = true;
+ }
+
+ m_reset = false;
+ reset(1, false);
+}
+
+void base_98628_9_device::reset_in(int state)
+{
+ if (state) {
+ reset(1, false);
+ m_cpu->reset();
+ }
+}
+
+void base_98628_9_device::reset(int state, bool nmi)
+{
+ bool new_reset = bool(state);
+ if (!m_reset && new_reset) {
+ m_irq = false;
+ m_irq_enabled = false;
+ m_semaphore = false;
+ m_to0_div = true;
+ m_to1_div = true;
+ m_ctc->reset();
+ m_sio->reset();
+ update_irq();
+ update_clocks();
+ }
+ if (new_reset != m_reset) {
+ m_reset = new_reset;
+ update_modem_ctrl();
+ }
+ LOG("NMI %d\n", nmi && state);
+ m_cpu->set_input_line(INPUT_LINE_NMI, nmi && state);
+}
+
+static INPUT_PORTS_START(base_98628_9_port)
+ PORT_START("sw2")
+ PORT_DIPNAME(SW2_SWITCH8_MASK, SW2_SWITCH8_MASK, "Switch 8")
+ PORT_DIPSETTING(0, DEF_STR(On))
+ PORT_DIPSETTING(SW2_SWITCH8_MASK, DEF_STR(Off))
+
+ PORT_DIPNAME(SW2_IRQ_LEVEL_MASK << SW2_IRQ_LEVEL_SHIFT, SW2_IRQ_LEVEL_DEF << SW2_IRQ_LEVEL_SHIFT, "IRQ level")
+ PORT_DIPSETTING(SW2_IRQ_LEVEL_IRQ3 << SW2_IRQ_LEVEL_SHIFT, "3")
+ PORT_DIPSETTING(SW2_IRQ_LEVEL_IRQ4 << SW2_IRQ_LEVEL_SHIFT, "4")
+ PORT_DIPSETTING(SW2_IRQ_LEVEL_IRQ5 << SW2_IRQ_LEVEL_SHIFT, "5")
+ PORT_DIPSETTING(SW2_IRQ_LEVEL_IRQ6 << SW2_IRQ_LEVEL_SHIFT, "6")
+
+ PORT_DIPNAME(SW2_SC_MASK << SW2_SC_SHIFT, SW2_SC_DEF, "Select code")
+ PORT_DIPSETTING(0 << SW2_SC_SHIFT, "0")
+ PORT_DIPSETTING(1 << SW2_SC_SHIFT, "1")
+ PORT_DIPSETTING(2 << SW2_SC_SHIFT, "2")
+ PORT_DIPSETTING(3 << SW2_SC_SHIFT, "3")
+ PORT_DIPSETTING(4 << SW2_SC_SHIFT, "4")
+ PORT_DIPSETTING(5 << SW2_SC_SHIFT, "5")
+ PORT_DIPSETTING(6 << SW2_SC_SHIFT, "6")
+ PORT_DIPSETTING(7 << SW2_SC_SHIFT, "7")
+ PORT_DIPSETTING(8 << SW2_SC_SHIFT, "8")
+ PORT_DIPSETTING(9 << SW2_SC_SHIFT, "9")
+ PORT_DIPSETTING(10 << SW2_SC_SHIFT, "10")
+ PORT_DIPSETTING(11 << SW2_SC_SHIFT, "11")
+ PORT_DIPSETTING(12 << SW2_SC_SHIFT, "12")
+ PORT_DIPSETTING(13 << SW2_SC_SHIFT, "13")
+ PORT_DIPSETTING(14 << SW2_SC_SHIFT, "14")
+ PORT_DIPSETTING(15 << SW2_SC_SHIFT, "15")
+ PORT_DIPSETTING(16 << SW2_SC_SHIFT, "16")
+ PORT_DIPSETTING(17 << SW2_SC_SHIFT, "17")
+ PORT_DIPSETTING(18 << SW2_SC_SHIFT, "18")
+ PORT_DIPSETTING(19 << SW2_SC_SHIFT, "19")
+ PORT_DIPSETTING(20 << SW2_SC_SHIFT, "20")
+ PORT_DIPSETTING(21 << SW2_SC_SHIFT, "21")
+ PORT_DIPSETTING(22 << SW2_SC_SHIFT, "22")
+ PORT_DIPSETTING(23 << SW2_SC_SHIFT, "23")
+ PORT_DIPSETTING(24 << SW2_SC_SHIFT, "24")
+ PORT_DIPSETTING(25 << SW2_SC_SHIFT, "25")
+ PORT_DIPSETTING(26 << SW2_SC_SHIFT, "26")
+ PORT_DIPSETTING(27 << SW2_SC_SHIFT, "27")
+ PORT_DIPSETTING(28 << SW2_SC_SHIFT, "28")
+ PORT_DIPSETTING(29 << SW2_SC_SHIFT, "29")
+ PORT_DIPSETTING(30 << SW2_SC_SHIFT, "30")
+ PORT_DIPSETTING(31 << SW2_SC_SHIFT, "31")
+
+INPUT_PORTS_END
+
+void base_98628_9_device::update_irq()
+{
+ auto level = (m_sw2->read() >> SW2_IRQ_LEVEL_SHIFT) & SW2_IRQ_LEVEL_MASK;
+ bool irq = m_irq && m_irq_enabled;
+ irq3_out(irq && level == SW2_IRQ_LEVEL_IRQ3);
+ irq4_out(irq && level == SW2_IRQ_LEVEL_IRQ4);
+ irq5_out(irq && level == SW2_IRQ_LEVEL_IRQ5);
+ irq6_out(irq && level == SW2_IRQ_LEVEL_IRQ6);
+}
+
+void base_98628_9_device::update_modem_ctrl()
+{
+ if (m_reset) {
+ rts_out(1);
+ dtr_out(1);
+ } else {
+ rts_out(!BIT(m_modem_ctrl, 0));
+ dtr_out(!BIT(m_modem_ctrl, 1));
+ }
+ ocd1_out(!BIT(m_modem_ctrl, 2));
+ // Bit 3 is OCD2
+ // Bit 4 is OCD3
+ // Bit 5 is OCD4
+}
+
+void base_98628_9_device::update_clocks()
+{
+ if (BIT(m_modem_ctrl, 6)) {
+ tx_clock_w(m_to0_div);
+ } else {
+ tx_clock_w(m_st_in);
+ }
+ if (BIT(m_modem_ctrl, 7)) {
+ rx_clock_w(m_to1_div);
+ } else {
+ rx_clock_w(m_rt_in);
+ }
+}
+
+static const z80_daisy_config daisy_chain_config[] = {
+ { "sio" },
+ { "ctc" },
+ { nullptr }
+};
+
+void base_98628_9_device::base_config(machine_config &config)
+{
+ Z80(config, m_cpu, CLOCK / 2);
+ m_cpu->set_addrmap(AS_PROGRAM, &base_98628_9_device::cpu_program_mem_map);
+ m_cpu->set_addrmap(AS_IO, &base_98628_9_device::cpu_io_mem_map);
+ m_cpu->set_daisy_config(daisy_chain_config);
+
+ Z80SIO(config, m_sio, CLOCK / 2);
+ m_sio->out_int_callback().set(FUNC(base_98628_9_device::sio_int_w));
+ m_sio->out_txda_callback().set(m_sio, FUNC(z80sio_device::rxb_w));
+ m_sio->out_txda_callback().append(FUNC(base_98628_9_device::tx_out));
+ m_sio->out_rtsb_callback().set(m_sio, FUNC(z80sio_device::dcdb_w));
+ m_sio->out_wrdya_callback().set(FUNC(base_98628_9_device::sio_wrdya_w));
+
+ Z80CTC(config, m_ctc, CLOCK / 2);
+ m_ctc->intr_callback().set(FUNC(base_98628_9_device::ctc_int_w));
+ m_ctc->zc_callback<0>().set(FUNC(base_98628_9_device::to0_w));
+ m_ctc->zc_callback<1>().set(FUNC(base_98628_9_device::to1_w));
+ m_ctc->zc_callback<2>().set(m_sio, FUNC(z80sio_device::txcb_w));
+ m_ctc->set_clk<0>(CLOCK / 4);
+ m_ctc->set_clk<1>(CLOCK / 4);
+}
+
+void base_98628_9_device::cpu_program_mem_map(address_map &map)
+{
+ map.unmap_value_low();
+ map(0x0000, 0x1fff).mirror(0x6000).rom();
+ map(0x8000, 0x8003).rw(FUNC(base_98628_9_device::reg_r), FUNC(base_98628_9_device::reg_w));
+ map(0xa000, 0xbfff).rw(FUNC(base_98628_9_device::low_ram_r_z80), FUNC(base_98628_9_device::low_ram_w_z80));
+}
+
+void base_98628_9_device::cpu_io_mem_map(address_map &map)
+{
+ map.unmap_value_high();
+ map.global_mask(0xff);
+ map(0x70, 0x73).rw(FUNC(base_98628_9_device::sio_r), FUNC(base_98628_9_device::sio_w));
+ map(0xb0, 0xb3).rw(m_ctc, FUNC(z80ctc_device::read), FUNC(z80ctc_device::write));
+ map(0xd0, 0xd1).r(FUNC(base_98628_9_device::sw1_r));
+}
+
+void base_98628_9_device::install_68k_map(offs_t base_addr)
+{
+ dio().install_memory(
+ 0x0000 + base_addr,
+ 0x0007 + base_addr,
+ read16sm_delegate(*this, NAME([this] (offs_t addr) { return reg_r(addr); })),
+ write16sm_delegate(*this, NAME([this] (offs_t addr, uint16_t data) { reg_w(addr, uint8_t(data)); })));
+ dio().install_memory(
+ 0x4000 + base_addr,
+ 0x7fff + base_addr,
+ read16sm_delegate(*this, FUNC(base_98628_9_device::low_ram_r_68k)),
+ write16sm_delegate(*this, FUNC(base_98628_9_device::low_ram_w_68k)));
+}
+
+uint8_t base_98628_9_device::reg_r(offs_t addr)
+{
+ uint8_t res = 0;
+
+ switch (addr & 3) {
+ case 0:
+ // ID register
+ res = 0x34;
+ if (!BIT(m_sw2->read(), SW2_SWITCH8_BIT)) {
+ BIT_SET(res, 7);
+ }
+ break;
+ case 1:
+ // IRQ register
+ //
+ // | Bit | Content |
+ // |------+-------------|
+ // | 7 | IRQ enabled |
+ // | 6 | IRQ pending |
+ // | 5..4 | IRQ level |
+ // | 3..0 | 0 |
+ if (m_irq_enabled) {
+ BIT_SET(res, 7);
+ }
+ if (m_irq) {
+ BIT_SET(res, 6);
+ }
+ res |= ((m_sw2->read() >> SW2_IRQ_LEVEL_SHIFT) & SW2_IRQ_LEVEL_MASK) << 4;
+ break;
+ case 2:
+ // Semaphore
+ // Read & clear
+ if (!m_semaphore) {
+ BIT_SET(res, 7);
+ }
+ if (!machine().side_effects_disabled()) {
+ m_semaphore = false;
+ }
+ break;
+ case 3:
+ // Modem status
+ //
+ // | Bit | Content |
+ // |------+-------------|
+ // | 7..6 | - |
+ // | 5 | !Wait/Rdy A |
+ // | 4 | OCR2 |
+ // | 3 | RI/OCR1 |
+ // | 2 | CTS/CS |
+ // | 1 | DCD/RR |
+ // | 0 | DSR/DM |
+ res = m_modem_status;
+ if (!m_wait_a) {
+ BIT_SET(res, 5);
+ }
+ break;
+ }
+
+ LOG("REG R %u=%02x\n", addr, res);
+ return res;
+}
+
+void base_98628_9_device::reg_w(offs_t addr, uint8_t data)
+{
+ LOG("REG W %u=%02x\n", addr, data);
+ switch (addr & 3) {
+ case 0:
+ // Reset control
+ reset(BIT(data, 7), true);
+ break;
+ case 1:
+ // IRQ enable
+ if (!m_reset) {
+ m_irq_enabled = BIT(data, 7);
+ update_irq();
+ }
+ break;
+ case 2:
+ // Semaphore
+ // Set
+ if (!m_reset && !machine().side_effects_disabled()) {
+ m_semaphore = true;
+ }
+ break;
+ case 3:
+ // Modem control
+ {
+ uint8_t diff = m_modem_ctrl ^ data;
+ m_modem_ctrl = data;
+ if (diff & 0xc0) {
+ update_clocks();
+ }
+ if (diff & 0x3f) {
+ update_modem_ctrl();
+ }
+ }
+ break;
+ }
+}
+
+uint8_t base_98628_9_device::low_ram_r_z80(offs_t addr)
+{
+ if (addr == 1 && !machine().side_effects_disabled()) {
+ // Clear CTSB/
+ m_ctsb = false;
+ m_sio->ctsb_w(m_ctsb);
+ LOG("CTSB 0\n");
+ }
+ return m_low_ram[addr & (LOW_RAM_SIZE - 1)];
+}
+
+uint16_t base_98628_9_device::low_ram_r_68k(offs_t addr)
+{
+ if (addr == 0 && !machine().side_effects_disabled()) {
+ // Clear IRQ
+ m_irq = false;
+ update_irq();
+ LOG("IRQ 0\n");
+ }
+ return m_low_ram[addr & (LOW_RAM_SIZE - 1)];
+}
+
+void base_98628_9_device::low_ram_w_z80(offs_t addr, uint8_t data)
+{
+ if (addr == 0 && !m_reset && !machine().side_effects_disabled()) {
+ // Set IRQ
+ m_irq = true;
+ LOG("IRQ 1\n");
+ update_irq();
+ }
+ m_low_ram[addr & (LOW_RAM_SIZE - 1)] = data;
+}
+
+void base_98628_9_device::low_ram_w_68k(offs_t addr, uint16_t data)
+{
+ if (addr == 1 && !machine().side_effects_disabled()) {
+ // Set CTSB/
+ m_ctsb = true;
+ LOG("CTSB 1\n");
+ m_sio->ctsb_w(m_ctsb);
+ }
+ m_low_ram[addr & (LOW_RAM_SIZE - 1)] = uint8_t(data);
+}
+
+uint8_t base_98628_9_device::sio_r(offs_t addr)
+{
+ uint8_t res;
+
+ if (addr == 0 && m_cpu_wait && !machine().side_effects_disabled()) {
+ // ch-A data register can't be read right now
+ m_cpu->set_input_line(Z80_INPUT_LINE_WAIT, ASSERT_LINE);
+ m_cpu->defer_access();
+ m_cpu_waiting = true;
+ res = 0;
+ LOG("Z80 stalled\n");
+ } else {
+ res = m_sio->ba_cd_r(addr);
+ }
+ LOG("SIO R %u=%02x\n", addr, res);
+ return res;
+}
+
+void base_98628_9_device::sio_w(offs_t addr, uint8_t data)
+{
+ LOG("SIO W %u=%02x\n", addr, data);
+ if (addr == 0 && m_cpu_wait && !machine().side_effects_disabled()) {
+ // ch-A data register can't be written right now
+ m_cpu->set_input_line(Z80_INPUT_LINE_WAIT, ASSERT_LINE);
+ m_cpu->defer_access();
+ m_cpu_waiting = true;
+ LOG("Z80 stalled\n");
+ } else {
+ m_sio->ba_cd_w(addr, data);
+ }
+}
+
+void base_98628_9_device::to0_w(int state)
+{
+ if (!m_reset && state) {
+ m_to0_div = !m_to0_div;
+ if (BIT(m_modem_ctrl, 6)) {
+ tx_clock_w(m_to0_div);
+ }
+ }
+}
+
+void base_98628_9_device::tx_clock_w(int state)
+{
+ m_sio->txca_w(state);
+ m_sio->rxcb_w(state);
+ m_ctc->trg2(state);
+ tt_out(state);
+}
+
+void base_98628_9_device::to1_w(int state)
+{
+ if (!m_reset && state) {
+ m_to1_div = !m_to1_div;
+ if (BIT(m_modem_ctrl, 7)) {
+ rx_clock_w(m_to1_div);
+ }
+ }
+}
+
+void base_98628_9_device::rx_clock_w(int state)
+{
+ m_sio->rxca_w(state);
+ m_ctc->trg3(state);
+}
+
+void base_98628_9_device::update_cpu_wait()
+{
+ m_cpu_wait = !m_wait_a && !m_sio_irq && !m_ctc_irq;
+ if (m_cpu_waiting && !m_cpu_wait) {
+ LOG("WAIT released wa %d si %d ci %d\n", m_wait_a, m_sio_irq, m_ctc_irq);
+ m_cpu->set_input_line(Z80_INPUT_LINE_WAIT, CLEAR_LINE);
+ m_cpu_waiting = false;
+ }
+}
+
+void base_98628_9_device::sio_wrdya_w(int state)
+{
+ LOG("WRDYA %d\n", state);
+ m_wait_a = bool(state);
+ update_cpu_wait();
+}
+
+void base_98628_9_device::sio_int_w(int state)
+{
+ LOG("SIO IRQ %d\n", state);
+ m_sio_irq = bool(state);
+ m_cpu->set_input_line(INPUT_LINE_IRQ0, m_sio_irq || m_ctc_irq);
+ update_cpu_wait();
+}
+
+void base_98628_9_device::ctc_int_w(int state)
+{
+ LOG("CTC IRQ %d\n", state);
+ m_ctc_irq = bool(state);
+ m_cpu->set_input_line(INPUT_LINE_IRQ0, m_sio_irq || m_ctc_irq);
+ update_cpu_wait();
+}
+
+uint8_t base_98628_9_device::sw1_r(offs_t addr)
+{
+ return uint8_t((m_sw1->read() >> (BIT(addr, 0) ? 4 : 0)) & 0x0f);
+}
+
+void base_98628_9_device::rx_in(int state)
+{
+ m_sio->rxa_w(state);
+}
+
+void base_98628_9_device::cts_in(int state)
+{
+ LOG("CTSA %d\n", state);
+ m_sio->ctsa_w(state);
+ if (state) {
+ BIT_CLR(m_modem_status, 2);
+ } else {
+ BIT_SET(m_modem_status, 2);
+ }
+}
+
+void base_98628_9_device::dcd_in(int state)
+{
+ m_sio->dcda_w(state);
+ if (state) {
+ BIT_CLR(m_modem_status, 1);
+ } else {
+ BIT_SET(m_modem_status, 1);
+ }
+}
+
+void base_98628_9_device::ri_in(int state)
+{
+ if (state) {
+ BIT_CLR(m_modem_status, 3);
+ } else {
+ BIT_SET(m_modem_status, 3);
+ }
+}
+
+void base_98628_9_device::dsr_in(int state)
+{
+ if (state) {
+ BIT_CLR(m_modem_status, 0);
+ } else {
+ BIT_SET(m_modem_status, 0);
+ }
+}
+
+void base_98628_9_device::st_in(int state)
+{
+ m_st_in = bool(state);
+ if (!BIT(m_modem_ctrl, 6)) {
+ tx_clock_w(state);
+ }
+}
+
+void base_98628_9_device::rt_in(int state)
+{
+ m_rt_in = bool(state);
+ if (!BIT(m_modem_ctrl, 7)) {
+ rx_clock_w(state);
+ }
+}
+
+// +--------------------+
+// | dio16_98628_device |
+// +--------------------+
+class dio16_98628_device :
+ public base_98628_9_device
+{
+public:
+ dio16_98628_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
+ : dio16_98628_device(mconfig, HPDIO_98628, tag, owner, clock)
+ {
+ }
+
+protected:
+ dio16_98628_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock)
+ : base_98628_9_device(mconfig, type, tag, owner, clock)
+ , m_rs232(*this, "rs232")
+ {
+ }
+
+ virtual void device_add_mconfig(machine_config &config) override ATTR_COLD;
+ virtual ioport_constructor device_input_ports() const override ATTR_COLD;
+ virtual const tiny_rom_entry *device_rom_region() const override ATTR_COLD;
+
+ virtual void tx_out(int state) override;
+ virtual void tt_out(int state) override;
+ virtual void rts_out(int state) override;
+ virtual void dtr_out(int state) override;
+ virtual void ocd1_out(int state) override;
+
+ required_device<rs232_port_device> m_rs232;
+};
+
+void dio16_98628_device::device_add_mconfig(machine_config &config)
+{
+ base_config(config);
+
+ RS232_PORT(config, m_rs232, default_rs232_devices, nullptr);
+ m_rs232->rxd_handler().set(FUNC(base_98628_9_device::rx_in));
+ m_rs232->dcd_handler().set(FUNC(base_98628_9_device::dcd_in));
+ m_rs232->dsr_handler().set(FUNC(base_98628_9_device::dsr_in));
+ m_rs232->ri_handler().set(FUNC(base_98628_9_device::ri_in));
+ m_rs232->cts_handler().set(FUNC(base_98628_9_device::cts_in));
+ m_rs232->rxc_handler().set(FUNC(base_98628_9_device::rt_in));
+ m_rs232->txc_handler().set(FUNC(base_98628_9_device::st_in));
+}
+
+static INPUT_PORTS_START(dio98628_port)
+ PORT_INCLUDE(base_98628_9_port)
+
+ PORT_START("sw1")
+ PORT_DIPNAME(0xc0, 0x80, "Parity,bits per char")
+ PORT_DIPSETTING(0x00, "N,8")
+ PORT_DIPSETTING(0x40, "N,7")
+ PORT_DIPSETTING(0x80, "O,7")
+ PORT_DIPSETTING(0xc0, "E,7")
+ PORT_DIPNAME(0x30, 0x10, "HW handshake")
+ PORT_DIPSETTING(0x00, "HS OFF,no modem")
+ PORT_DIPSETTING(0x10, "Full dplx modem")
+ PORT_DIPSETTING(0x20, "Half dplx modem")
+ PORT_DIPSETTING(0x30, "HS ON,no modem")
+ PORT_DIPNAME(0x0e, 0x04, "Speed,stop bits")
+ PORT_DIPSETTING(0x00, "110,2")
+ PORT_DIPSETTING(0x02, "150,2")
+ PORT_DIPSETTING(0x04, "300,1")
+ PORT_DIPSETTING(0x06, "600,1")
+ PORT_DIPSETTING(0x08, "1200,1")
+ PORT_DIPSETTING(0x0a, "2400,1")
+ PORT_DIPSETTING(0x0c, "4800,1")
+ PORT_DIPSETTING(0x0e, "9600,1")
+ PORT_DIPNAME(0x01, 0x00, "Mode")
+ PORT_DIPSETTING(0x00, "Asynchronuous")
+ PORT_DIPSETTING(0x01, "Data link")
+INPUT_PORTS_END
+
+ioport_constructor dio16_98628_device::device_input_ports() const
+{
+ return INPUT_PORTS_NAME(dio98628_port);
+}
+
+ROM_START(dio98628)
+ ROM_REGION(0x2000, "cpu", 0)
+ ROM_LOAD("98628-81003.bin", 0, 0x2000, CRC(ac51d596) SHA1(738fa16ac9a0f865938e7b197d26bd37c27b8660))
+ROM_END
+
+const tiny_rom_entry *dio16_98628_device::device_rom_region() const
+{
+ return ROM_NAME(dio98628);
+}
+
+void dio16_98628_device::tx_out(int state)
+{
+ m_rs232->write_txd(state);
+}
+
+void dio16_98628_device::tt_out(int state)
+{
+ m_rs232->write_etc(state);
+}
+
+void dio16_98628_device::rts_out(int state)
+{
+ m_rs232->write_rts(state);
+}
+
+void dio16_98628_device::dtr_out(int state)
+{
+ m_rs232->write_dtr(state);
+}
+
+void dio16_98628_device::ocd1_out(int state)
+{
+ m_rs232->write_spds(state);
+}
+
+// +--------------------+
+// | dio16_98629_device |
+// +--------------------+
+class dio16_98629_device :
+ public base_98628_9_device
+{
+public:
+ dio16_98629_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
+ : dio16_98629_device(mconfig, HPDIO_98629, tag, owner, clock)
+ {
+ }
+
+protected:
+ static inline constexpr unsigned HIGH_RAM_SIZE = 2048;
+ static inline constexpr unsigned MUX_FREQ = 700000;
+
+ enum class fsm_st {
+ ST_PROBING_MY_PORT,
+ ST_PROBING_EXT_PORT,
+ ST_MY_PORT_TX,
+ ST_MY_PORT_RX,
+ ST_WAITING_RX,
+ ST_PAUSE
+ };
+
+ dio16_98629_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock)
+ : base_98628_9_device(mconfig, type, tag, owner, clock)
+ , m_stream(*this, "stream")
+ , m_timer(*this, "tmr")
+ {
+ }
+
+ 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;
+ virtual ioport_constructor device_input_ports() const override ATTR_COLD;
+ virtual const tiny_rom_entry *device_rom_region() const override ATTR_COLD;
+
+ virtual void cpu_program_mem_map(address_map &map) override ATTR_COLD;
+ virtual void install_68k_map(offs_t base_addr) override ATTR_COLD;
+ uint8_t high_ram_r_z80(offs_t addr);
+ void high_ram_w_z80(offs_t addr, uint8_t data);
+ virtual void tx_out(int state) override;
+ virtual void tt_out(int state) override;
+
+ TIMER_DEVICE_CALLBACK_MEMBER(timer_to);
+
+ required_device<bitbanger_device> m_stream;
+ required_device<timer_device> m_timer;
+
+ fsm_st m_state;
+ unsigned m_byte_cnt;
+ bool m_half_cycle;
+ bool m_tx;
+ bool m_last_tt;
+ uint8_t m_sr;
+ uint8_t m_high_ram[HIGH_RAM_SIZE];
+};
+
+void dio16_98629_device::device_start()
+{
+ base_98628_9_device::device_start();
+ save_item(NAME(m_byte_cnt));
+ save_item(NAME(m_half_cycle));
+ save_item(NAME(m_tx));
+ save_item(NAME(m_last_tt));
+ save_item(NAME(m_sr));
+ save_item(NAME(m_high_ram));
+}
+
+void dio16_98629_device::device_reset()
+{
+ base_98628_9_device::device_reset();
+
+ m_state = fsm_st::ST_PROBING_MY_PORT;
+ m_byte_cnt = 0;
+ m_half_cycle = false;
+ m_sr = 0xff;
+ rx_in(1);
+ cts_in(1);
+ st_in(1);
+ rt_in(1);
+ m_timer->adjust(attotime::from_hz(MUX_FREQ / 8), 0, attotime::from_hz(MUX_FREQ / 8));
+}
+
+void dio16_98629_device::device_add_mconfig(machine_config &config)
+{
+ base_config(config);
+
+ BITBANGER(config, m_stream, 0);
+ TIMER(config, m_timer).configure_generic(FUNC(dio16_98629_device::timer_to));
+}
+
+static INPUT_PORTS_START(dio98629_port)
+ PORT_INCLUDE(base_98628_9_port)
+
+ PORT_START("sw1")
+ PORT_DIPNAME(0x3f, 0x0a, "Bus address")
+ PORT_DIPSETTING(0, "0")
+ PORT_DIPSETTING(1, "1")
+ PORT_DIPSETTING(2, "2")
+ PORT_DIPSETTING(3, "3")
+ PORT_DIPSETTING(4, "4")
+ PORT_DIPSETTING(5, "5")
+ PORT_DIPSETTING(6, "6")
+ PORT_DIPSETTING(7, "7")
+ PORT_DIPSETTING(8, "8")
+ PORT_DIPSETTING(9, "9")
+ PORT_DIPSETTING(10, "10")
+ PORT_DIPSETTING(11, "11")
+ PORT_DIPSETTING(12, "12")
+ PORT_DIPSETTING(13, "13")
+ PORT_DIPSETTING(14, "14")
+ PORT_DIPSETTING(15, "15")
+ PORT_DIPSETTING(16, "16")
+ PORT_DIPSETTING(17, "17")
+ PORT_DIPSETTING(18, "18")
+ PORT_DIPSETTING(19, "19")
+ PORT_DIPSETTING(20, "20")
+ PORT_DIPSETTING(21, "21")
+ PORT_DIPSETTING(22, "22")
+ PORT_DIPSETTING(23, "23")
+ PORT_DIPSETTING(24, "24")
+ PORT_DIPSETTING(25, "25")
+ PORT_DIPSETTING(26, "26")
+ PORT_DIPSETTING(27, "27")
+ PORT_DIPSETTING(28, "28")
+ PORT_DIPSETTING(29, "29")
+ PORT_DIPSETTING(30, "30")
+ PORT_DIPSETTING(31, "31")
+ PORT_DIPSETTING(32, "32")
+ PORT_DIPSETTING(33, "33")
+ PORT_DIPSETTING(34, "34")
+ PORT_DIPSETTING(35, "35")
+ PORT_DIPSETTING(36, "36")
+ PORT_DIPSETTING(37, "37")
+ PORT_DIPSETTING(38, "38")
+ PORT_DIPSETTING(39, "39")
+ PORT_DIPSETTING(40, "40")
+ PORT_DIPSETTING(41, "41")
+ PORT_DIPSETTING(42, "42")
+ PORT_DIPSETTING(43, "43")
+ PORT_DIPSETTING(44, "44")
+ PORT_DIPSETTING(45, "45")
+ PORT_DIPSETTING(46, "46")
+ PORT_DIPSETTING(47, "47")
+ PORT_DIPSETTING(48, "48")
+ PORT_DIPSETTING(49, "49")
+ PORT_DIPSETTING(50, "50")
+ PORT_DIPSETTING(51, "51")
+ PORT_DIPSETTING(52, "52")
+ PORT_DIPSETTING(53, "53")
+ PORT_DIPSETTING(54, "54")
+ PORT_DIPSETTING(55, "55")
+ PORT_DIPSETTING(56, "56")
+ PORT_DIPSETTING(57, "57")
+ PORT_DIPSETTING(58, "58")
+ PORT_DIPSETTING(59, "59")
+ PORT_DIPSETTING(60, "60")
+ PORT_DIPSETTING(61, "61")
+ PORT_DIPSETTING(62, "62")
+ PORT_DIPSETTING(63, "63")
+INPUT_PORTS_END
+
+ioport_constructor dio16_98629_device::device_input_ports() const
+{
+ return INPUT_PORTS_NAME(dio98629_port);
+}
+
+void dio16_98629_device::cpu_program_mem_map(address_map &map)
+{
+ base_98628_9_device::cpu_program_mem_map(map);
+ map(0xc000, 0xdfff).rw(FUNC(dio16_98629_device::high_ram_r_z80), FUNC(dio16_98629_device::high_ram_w_z80));
+}
+
+void dio16_98629_device::install_68k_map(offs_t base_addr)
+{
+ base_98628_9_device::install_68k_map(base_addr);
+ dio().install_memory(
+ 0x8000 + base_addr,
+ 0xbfff + base_addr,
+ read16sm_delegate(*this, NAME([this] (offs_t addr) { return high_ram_r_z80(addr); })),
+ write16sm_delegate(*this, NAME([this] (offs_t addr, uint16_t data) { high_ram_w_z80(addr, uint8_t(data)); })));
+}
+
+uint8_t dio16_98629_device::high_ram_r_z80(offs_t addr)
+{
+ return m_high_ram[addr & (HIGH_RAM_SIZE - 1)];
+}
+
+void dio16_98629_device::high_ram_w_z80(offs_t addr, uint8_t data)
+{
+ m_high_ram[addr & (HIGH_RAM_SIZE - 1)] = data;
+}
+
+void dio16_98629_device::tx_out(int state)
+{
+ m_tx = bool(state);
+ if (m_state == fsm_st::ST_PROBING_MY_PORT || m_state == fsm_st::ST_MY_PORT_TX) {
+ rx_in(state);
+ }
+}
+
+void dio16_98629_device::tt_out(int state)
+{
+ if (m_state != fsm_st::ST_PROBING_MY_PORT && m_state != fsm_st::ST_MY_PORT_TX) {
+ return;
+ }
+
+ if (!m_last_tt && state) {
+ // Sample bit on rising edge
+ m_sr >>= 1;
+ if (m_tx) {
+ BIT_SET(m_sr, 7);
+ }
+ cts_in(m_sr == 0xff);
+ }
+ m_last_tt = bool(state);
+}
+
+TIMER_DEVICE_CALLBACK_MEMBER(dio16_98629_device::timer_to)
+{
+ bool stay;
+ do {
+ stay = false;
+
+ switch (m_state) {
+ case fsm_st::ST_PROBING_MY_PORT:
+ for (unsigned i = 0; i < 8; i++) {
+ st_in(0);
+ rt_in(0);
+ st_in(1);
+ rt_in(1);
+ }
+ if (m_sr == 0xff) {
+ m_half_cycle = !m_half_cycle;
+ if (!m_half_cycle) {
+ m_state = fsm_st::ST_PROBING_EXT_PORT;
+ }
+ } else {
+ LOG("TX %02x (start)\n", m_sr);
+ m_stream->output(m_sr);
+ m_state = fsm_st::ST_MY_PORT_TX;
+ }
+ break;
+
+ case fsm_st::ST_PROBING_EXT_PORT:
+ if (m_stream->input(&m_sr, 1) == 1 && m_sr != 0xff) {
+ m_state = fsm_st::ST_MY_PORT_RX;
+ stay = true;
+ } else {
+ m_half_cycle = !m_half_cycle;
+ if (!m_half_cycle) {
+ m_byte_cnt = 0;
+ m_state = fsm_st::ST_PAUSE;
+ }
+ }
+ break;
+
+ case fsm_st::ST_MY_PORT_TX:
+ for (unsigned i = 0; i < 8; i++) {
+ st_in(0);
+ rt_in(0);
+ st_in(1);
+ rt_in(1);
+ }
+ LOG("TX %02x\n", m_sr);
+ m_stream->output(m_sr);
+ if (m_sr == 0xff) {
+ m_half_cycle = !m_half_cycle;
+ if (!m_half_cycle) {
+ LOG("TX ended\n");
+ m_state = fsm_st::ST_PROBING_EXT_PORT;
+ }
+ }
+ break;
+
+ case fsm_st::ST_WAITING_RX:
+ if (m_stream->input(&m_sr, 1) == 1) {
+ m_state = fsm_st::ST_MY_PORT_RX;
+ stay = true;
+ }
+ break;
+
+ case fsm_st::ST_MY_PORT_RX:
+ {
+ LOG("RX %02x\n", m_sr);
+ uint8_t tmp = m_sr;
+ for (unsigned i = 0; i < 8; i++) {
+ st_in(0);
+ rt_in(0);
+ rx_in(BIT(tmp, 0));
+ tmp >>= 1;
+ st_in(1);
+ rt_in(1);
+ }
+ m_state = fsm_st::ST_WAITING_RX;
+ if (m_sr == 0xff) {
+ m_half_cycle = !m_half_cycle;
+ if (!m_half_cycle) {
+ LOG("RX ended\n");
+ m_byte_cnt = 0;
+ m_state = fsm_st::ST_PAUSE;
+ }
+ }
+ }
+ break;
+
+ case fsm_st::ST_PAUSE:
+ m_byte_cnt++;
+ if (m_byte_cnt == 6) {
+ m_state = fsm_st::ST_PROBING_MY_PORT;
+ }
+ break;
+ }
+ } while (stay);
+}
+
+ROM_START(dio98629)
+ ROM_REGION(0x2000, "cpu", 0)
+ ROM_LOAD("1818-1739b.bin", 0, 0x2000, CRC(5955894e) SHA1(b02b3688a8e415701905c7a1d8ae8848fd9b8b42))
+ROM_END
+
+const tiny_rom_entry *dio16_98629_device::device_rom_region() const
+{
+ return ROM_NAME(dio98629);
+}
+
+} // anonymous namespace
+
+DEFINE_DEVICE_TYPE_PRIVATE(HPDIO_98628, bus::hp_dio::device_dio16_card_interface, dio16_98628_device, "dio98628", "HP98628 data communication interface")
+DEFINE_DEVICE_TYPE_PRIVATE(HPDIO_98629, bus::hp_dio::device_dio16_card_interface, dio16_98629_device, "dio98629", "HP98629 SRM interface")
diff --git a/src/devices/bus/hp_dio/hp98628_9.h b/src/devices/bus/hp_dio/hp98628_9.h
new file mode 100755
index 00000000000..873b9ead97b
--- /dev/null
+++ b/src/devices/bus/hp_dio/hp98628_9.h
@@ -0,0 +1,21 @@
+// license:BSD-3-Clause
+// copyright-holders:F. Ulivi
+
+/*********************************************************************
+
+ HP98628 Data communication interface
+ HP98629 SRM interface
+
+*********************************************************************/
+
+#ifndef MAME_BUS_HP_DIO_HP98628_9_H
+#define MAME_BUS_HP_DIO_HP98628_9_H
+
+#pragma once
+
+#include "hp_dio.h"
+
+DECLARE_DEVICE_TYPE_NS(HPDIO_98628, bus::hp_dio, device_dio16_card_interface)
+DECLARE_DEVICE_TYPE_NS(HPDIO_98629, bus::hp_dio, device_dio16_card_interface)
+
+#endif /* MAME_BUS_HP_DIO_HP98628_9_H */
diff --git a/src/devices/bus/hp_dio/hp98643.cpp b/src/devices/bus/hp_dio/hp98643.cpp
index 57bc4d1a283..04e08abbee1 100644
--- a/src/devices/bus/hp_dio/hp98643.cpp
+++ b/src/devices/bus/hp_dio/hp98643.cpp
@@ -13,9 +13,80 @@
//#define VERBOSE 1
#include "logmacro.h"
-DEFINE_DEVICE_TYPE_NS(HPDIO_98643, bus::hp_dio, dio16_98643_device, "dio98643", "HP98643A LANIC Ethernet card")
-namespace bus { namespace hp_dio {
+namespace {
+
+static constexpr int REG_SWITCHES_REMOTE = 0x80;
+
+static constexpr int REG_SWITCHES_SELECT_CODE_MASK = 0x1f;
+static constexpr int REG_SWITCHES_SELECT_CODE_SHIFT = 0x00;
+
+static constexpr int REG_SWITCHES_INT_LEVEL_MASK = 0x03;
+static constexpr int REG_SWITCHES_INT_LEVEL_SHIFT = 0x05;
+
+static constexpr uint16_t REG_ID = 0x15;
+
+static constexpr uint16_t REG_STATUS_ACK = 0x04;
+
+static constexpr uint16_t REG_SC_REV = 0x01;
+static constexpr uint16_t REG_SC_LOCK = 0x08;
+static constexpr uint16_t REG_SC_IP = 0x40;
+static constexpr uint16_t REG_SC_IE = 0x80;
+
+class dio16_98643_device :
+ public device_t,
+ public bus::hp_dio::device_dio16_card_interface
+{
+public:
+ // construction/destruction
+ dio16_98643_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
+
+protected:
+ dio16_98643_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 ATTR_COLD;
+ virtual void device_reset() override ATTR_COLD;
+
+ virtual ioport_constructor device_input_ports() const override ATTR_COLD;
+ virtual void device_add_mconfig(machine_config &config) override ATTR_COLD;
+
+private:
+ required_device<am7990_device> m_lance;
+ required_ioport m_switches;
+
+ void addrmap(address_map &map) ATTR_COLD;
+ void update_int();
+ int get_irq_line();
+
+ uint16_t sc_r();
+ void sc_w(uint16_t data);
+ uint16_t id_r();
+ void id_w(uint16_t data);
+ uint16_t novram_r(offs_t offset);
+ void novram_w(offs_t offset, uint16_t data, uint16_t mem_mask = ~0);
+
+ 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);
+
+ uint16_t m_novram[32] = {
+ 0xfff0, 0xfff0, 0xfff0, 0xfff0,
+ 0xfff0, 0xfff8, 0xfff0, 0xfff0,
+ 0xfff0, 0xfff9, 0xfff0, 0xfff6,
+ 0xfffa, 0xfff1, 0xffff, 0xfff1,
+ 0xfff0, 0xfff0, 0xfff0, 0xfff0,
+ 0xfff0, 0xfff0, 0xfff0, 0xfff0,
+ 0xfff0, 0xfff0, 0xfff0, 0xfff0,
+ 0xfff0, 0xfff0, 0xfffa, 0xfff9,
+ };
+
+ std::array<uint16_t, 8192> m_ram;
+
+ uint16_t m_sc;
+ bool m_installed_io;
+};
void dio16_98643_device::device_add_mconfig(machine_config &config)
{
@@ -95,6 +166,7 @@ void dio16_98643_device::device_start()
save_item(NAME(m_sc));
save_item(NAME(m_installed_io));
save_item(NAME(m_ram));
+ m_installed_io = false;
}
void dio16_98643_device::device_reset()
@@ -113,7 +185,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;
@@ -122,7 +194,7 @@ WRITE_LINE_MEMBER(dio16_98643_device::lance_int_w)
update_int();
}
-WRITE16_MEMBER(dio16_98643_device::sc_w)
+void dio16_98643_device::sc_w(uint16_t data)
{
LOG("%s: %02x\n", __func__, data);
data &= (REG_SC_LOCK|REG_SC_IE);
@@ -135,38 +207,38 @@ WRITE16_MEMBER(dio16_98643_device::sc_w)
update_int();
}
-READ16_MEMBER(dio16_98643_device::sc_r)
+uint16_t dio16_98643_device::sc_r()
{
LOG("%s: %02x\n", __func__, m_sc);
return m_sc;
}
-READ16_MEMBER(dio16_98643_device::id_r)
+uint16_t dio16_98643_device::id_r()
{
return (REG_ID | (m_switches->read() & REG_SWITCHES_REMOTE));
}
-WRITE16_MEMBER(dio16_98643_device::id_w)
+void dio16_98643_device::id_w(uint16_t data)
{
reset();
}
-READ16_MEMBER(dio16_98643_device::novram_r)
+uint16_t dio16_98643_device::novram_r(offs_t offset)
{
return m_novram[offset];
}
-WRITE16_MEMBER(dio16_98643_device::novram_w)
+void dio16_98643_device::novram_w(offs_t offset, uint16_t data, uint16_t mem_mask)
{
COMBINE_DATA(&m_novram[offset & 0x3f]);
}
-WRITE16_MEMBER(dio16_98643_device::lance_dma_out)
+void dio16_98643_device::lance_dma_out(offs_t offset, uint16_t data, uint16_t mem_mask)
{
LOG("%s: offset=%04x, data=%d\n", __func__, offset, data);
COMBINE_DATA(&m_ram[(offset >> 1) & 0x1fff]);
}
-READ16_MEMBER(dio16_98643_device::lance_dma_in)
+uint16_t dio16_98643_device::lance_dma_in(offs_t offset)
{
uint16_t ret = m_ram[(offset >> 1) & 0x1fff];
@@ -194,22 +266,23 @@ void dio16_98643_device::addrmap(address_map &map)
{
map(0x0000, 0x0001).rw(FUNC(dio16_98643_device::id_r), FUNC(dio16_98643_device::id_w));
map(0x0002, 0x0003).rw(FUNC(dio16_98643_device::sc_r), FUNC(dio16_98643_device::sc_w));
- map(0x4000, 0x4003).lrw16("lance",
- [this](address_space &space, offs_t offset, u16 mem_mask) -> u16 {
- m_sc |= REG_STATUS_ACK;
- return m_lance->regs_r(space, offset, mem_mask);
- },
- [this](address_space &space, offs_t offset, u16 data, u16 mem_mask) {
- m_sc |= REG_STATUS_ACK;
- return m_lance->regs_w(space, offset, data, mem_mask);
- });
-
- map(0x8000, 0xbfff).lrw16("lanceram",
- [this](offs_t offset) -> u16 { return m_ram[offset]; },
- [this](offs_t offset, u16 data, u16 mem_mask) { COMBINE_DATA(&m_ram[offset]); });
+ map(0x4000, 0x4003).lrw16(
+ [this] (address_space &space, offs_t offset) -> u16 {
+ m_sc |= REG_STATUS_ACK;
+ return m_lance->regs_r(space, offset);
+ }, "lance_r",
+ [this] (offs_t offset, u16 data) {
+ m_sc |= REG_STATUS_ACK;
+ return m_lance->regs_w(offset, data);
+ }, "lance_w");
+
+ map(0x8000, 0xbfff).lrw16(
+ NAME([this] (offs_t offset) -> u16 { return m_ram[offset]; }),
+ NAME([this] (offs_t offset, u16 data, u16 mem_mask) { COMBINE_DATA(&m_ram[offset]); }));
map(0xc000, 0xffff).rw(FUNC(dio16_98643_device::novram_r), FUNC(dio16_98643_device::novram_w));
}
-} // namespace bus::hp_dio
-} // namespace bus
+} // anonymous namespace
+
+DEFINE_DEVICE_TYPE_PRIVATE(HPDIO_98643, bus::hp_dio::device_dio16_card_interface, dio16_98643_device, "dio98643", "HP98643A LANIC Ethernet card")
diff --git a/src/devices/bus/hp_dio/hp98643.h b/src/devices/bus/hp_dio/hp98643.h
index d2b018c4b57..518ed54f9dc 100644
--- a/src/devices/bus/hp_dio/hp98643.h
+++ b/src/devices/bus/hp_dio/hp98643.h
@@ -1,92 +1,14 @@
// license:BSD-3-Clause
// copyright-holders:Sven Schnelle
-#ifndef MAME_BUS_HPDIO_98643_H
-#define MAME_BUS_HPDIO_98643_H
+#ifndef MAME_BUS_HP_DIO_HP98643_H
+#define MAME_BUS_HP_DIO_HP98643_H
#pragma once
#include "hp_dio.h"
-#include "machine/am79c90.h"
-
-namespace bus { namespace hp_dio {
-
-static constexpr int REG_SWITCHES_REMOTE = 0x80;
-
-static constexpr int REG_SWITCHES_SELECT_CODE_MASK = 0x1f;
-static constexpr int REG_SWITCHES_SELECT_CODE_SHIFT = 0x00;
-
-static constexpr int REG_SWITCHES_INT_LEVEL_MASK = 0x03;
-static constexpr int REG_SWITCHES_INT_LEVEL_SHIFT = 0x05;
-
-static constexpr uint16_t REG_ID = 0x15;
-
-static constexpr uint16_t REG_STATUS_ACK = 0x04;
-
-static constexpr uint16_t REG_SC_REV = 0x01;
-static constexpr uint16_t REG_SC_LOCK = 0x08;
-static constexpr uint16_t REG_SC_IP = 0x40;
-static constexpr uint16_t REG_SC_IE = 0x80;
-
-class dio16_98643_device :
- public device_t,
- public device_dio16_card_interface
-{
-public:
- // construction/destruction
- dio16_98643_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
-
-protected:
- dio16_98643_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 ioport_constructor device_input_ports() const override;
- virtual void device_add_mconfig(machine_config &config) override;
-
-private:
- required_device<am7990_device> m_lance;
- required_ioport m_switches;
-
- void addrmap(address_map &map);
- void update_int();
- int get_irq_line();
-
- READ16_MEMBER(sc_r);
- WRITE16_MEMBER(sc_w);
- READ16_MEMBER(id_r);
- WRITE16_MEMBER(id_w);
- READ16_MEMBER(novram_r);
- WRITE16_MEMBER(novram_w);
-
- DECLARE_WRITE_LINE_MEMBER(lance_int_w);
- DECLARE_WRITE16_MEMBER(lance_dma_out);
- DECLARE_READ16_MEMBER(lance_dma_in);
-
- uint16_t m_novram[32] = {
- 0xfff0, 0xfff0, 0xfff0, 0xfff0,
- 0xfff0, 0xfff8, 0xfff0, 0xfff0,
- 0xfff0, 0xfff9, 0xfff0, 0xfff6,
- 0xfffa, 0xfff1, 0xffff, 0xfff1,
- 0xfff0, 0xfff0, 0xfff0, 0xfff0,
- 0xfff0, 0xfff0, 0xfff0, 0xfff0,
- 0xfff0, 0xfff0, 0xfff0, 0xfff0,
- 0xfff0, 0xfff0, 0xfffa, 0xfff9,
- };
-
- std::array<uint16_t, 8192> m_ram;
-
- uint16_t m_sc;
- bool m_installed_io;
-};
-
-} // namespace bus::hp_dio
-} // namespace bus
// device type definition
-DECLARE_DEVICE_TYPE_NS(HPDIO_98643, bus::hp_dio, dio16_98643_device)
+DECLARE_DEVICE_TYPE_NS(HPDIO_98643, bus::hp_dio, device_dio16_card_interface)
-#endif // MAME_BUS_HPDIO_98643_H
+#endif // MAME_BUS_HP_DIO_HP98643_H
diff --git a/src/devices/bus/hp_dio/hp98644.cpp b/src/devices/bus/hp_dio/hp98644.cpp
index d3c347b6d31..7f3bf94c34e 100644
--- a/src/devices/bus/hp_dio/hp98644.cpp
+++ b/src/devices/bus/hp_dio/hp98644.cpp
@@ -8,17 +8,46 @@
#include "emu.h"
#include "hp98644.h"
+
#include "bus/rs232/rs232.h"
+#include "machine/ins8250.h"
-//**************************************************************************
-// GLOBAL VARIABLES
-//**************************************************************************
+namespace {
+
+class dio16_98644_device :
+ public device_t,
+ public bus::hp_dio::device_dio16_card_interface
+{
+public:
+ // construction/destruction
+ dio16_98644_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
+
+protected:
+ dio16_98644_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock);
+
-DEFINE_DEVICE_TYPE_NS(HPDIO_98644, bus::hp_dio, dio16_98644_device, "dio98644", "HP98644A Asynchronous Serial Interface")
+ // device-level overrides
+ virtual void device_start() override ATTR_COLD;
+ virtual void device_reset() override ATTR_COLD;
-namespace bus {
- namespace hp_dio {
+ virtual ioport_constructor device_input_ports() const override ATTR_COLD;
+ // optional information overrides
+ virtual void device_add_mconfig(machine_config &config) override ATTR_COLD;
+
+ uint16_t io_r(offs_t offset);
+ void io_w(offs_t offset, uint16_t data);
+
+ required_device<ins8250_device> m_uart;
+
+private:
+ required_ioport m_switches;
+ bool m_installed_io;
+ uint8_t m_control;
+
+ bool m_loopback;
+ uint8_t m_data;
+};
//-------------------------------------------------
// device_add_mconfig - add device configuration
@@ -58,8 +87,12 @@ dio16_98644_device::dio16_98644_device(const machine_config &mconfig, const char
dio16_98644_device::dio16_98644_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_dio16_card_interface(mconfig, *this),
- m_uart(*this, INS8250_TAG),
- m_switches{*this, "switches"}
+ m_uart{*this, INS8250_TAG},
+ m_switches{*this, "switches"},
+ m_installed_io{false},
+ m_control{0},
+ m_loopback{false},
+ m_data{0}
{
}
@@ -161,13 +194,15 @@ void dio16_98644_device::device_reset()
dio().install_memory(
0x600000 + (code * 0x10000),
0x6007ff + (code * 0x10000),
- read16_delegate(FUNC(dio16_98644_device::io_r), this),
- write16_delegate(FUNC(dio16_98644_device::io_w), this));
+ read16sm_delegate(*this, FUNC(dio16_98644_device::io_r)),
+ write16sm_delegate(*this, FUNC(dio16_98644_device::io_w)));
m_installed_io = true;
}
+ m_data = 0;
+ m_control = 0;
}
-READ16_MEMBER(dio16_98644_device::io_r)
+uint16_t dio16_98644_device::io_r(offs_t offset)
{
uint16_t ret = 0xffff;
@@ -181,7 +216,7 @@ READ16_MEMBER(dio16_98644_device::io_r)
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;
@@ -204,7 +239,7 @@ READ16_MEMBER(dio16_98644_device::io_r)
return ret;
}
-WRITE16_MEMBER(dio16_98644_device::io_w)
+void dio16_98644_device::io_w(offs_t offset, uint16_t data)
{
if (offset == 0x0c)
m_loopback = (data & 0x10) ? true : false;
@@ -235,5 +270,7 @@ WRITE16_MEMBER(dio16_98644_device::io_w)
}
}
-} // namespace bus::hp_dio
-} // namespace bus
+} // anonymous namespace
+
+DEFINE_DEVICE_TYPE_PRIVATE(HPDIO_98644, bus::hp_dio::device_dio16_card_interface, dio16_98644_device, "dio98644", "HP98644A Asynchronous Serial Interface")
+
diff --git a/src/devices/bus/hp_dio/hp98644.h b/src/devices/bus/hp_dio/hp98644.h
index c4ad925fc30..b8b3762c3b0 100644
--- a/src/devices/bus/hp_dio/hp98644.h
+++ b/src/devices/bus/hp_dio/hp98644.h
@@ -1,61 +1,14 @@
// license:BSD-3-Clause
-// copyright-holders:R. Belmont
+// copyright-holders:Sven Schnelle
-#ifndef MAME_BUS_HPDIO_98644_H
-#define MAME_BUS_HPDIO_98644_H
+#ifndef MAME_BUS_HP_DIO_HP98644_H
+#define MAME_BUS_HP_DIO_HP98644_H
#pragma once
#include "hp_dio.h"
-#include "machine/ins8250.h"
-
-//**************************************************************************
-// TYPE DEFINITIONS
-//**************************************************************************
-
-// ======================> dio16_98644_device
-
-namespace bus {
- namespace hp_dio {
-
-class dio16_98644_device :
- public device_t,
- public device_dio16_card_interface
-{
-public:
- // construction/destruction
- dio16_98644_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
-
-protected:
- dio16_98644_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 ioport_constructor device_input_ports() const override;
- // optional information overrides
- virtual void device_add_mconfig(machine_config &config) override;
-
- DECLARE_READ16_MEMBER(io_r);
- DECLARE_WRITE16_MEMBER(io_w);
-
- required_device<ins8250_device> m_uart;
-
-private:
- required_ioport m_switches;
- bool m_installed_io;
- uint8_t m_control;
-
- bool m_loopback;
- uint8_t m_data;
-};
-
-} // namespace bus::hp_dio
-} // namespace bus
// device type definition
-DECLARE_DEVICE_TYPE_NS(HPDIO_98644, bus::hp_dio, dio16_98644_device)
+DECLARE_DEVICE_TYPE_NS(HPDIO_98644, bus::hp_dio, device_dio16_card_interface)
-#endif // MAME_BUS_HPDIO_98644_H
+#endif // MAME_BUS_HP_DIO_HP98644_H
diff --git a/src/devices/bus/hp_dio/hp_dio.cpp b/src/devices/bus/hp_dio/hp_dio.cpp
index c2cbfa8e941..3675180350f 100644
--- a/src/devices/bus/hp_dio/hp_dio.cpp
+++ b/src/devices/bus/hp_dio/hp_dio.cpp
@@ -15,6 +15,8 @@
#include "hp98603a.h"
#include "hp98603b.h"
#include "hp98620.h"
+#include "hp98624.h"
+#include "hp98628_9.h"
#include "hp98643.h"
#include "hp98644.h"
#include "human_interface.h"
@@ -23,13 +25,12 @@
// GLOBAL VARIABLES
//**************************************************************************
-DEFINE_DEVICE_TYPE_NS(DIO16_SLOT, bus::hp_dio, dio16_slot_device, "dio16_slot", "16-bit DIO slot")
-DEFINE_DEVICE_TYPE_NS(DIO32_SLOT, bus::hp_dio, dio32_slot_device, "dio32_slot", "32-bit DIO-II slot")
-DEFINE_DEVICE_TYPE_NS(DIO16, bus::hp_dio, dio16_device, "dio16", "16-bit DIO bus")
-DEFINE_DEVICE_TYPE_NS(DIO32, bus::hp_dio, dio32_device, "dio32", "32-bit DIO-II bus")
+DEFINE_DEVICE_TYPE(DIO16_SLOT, bus::hp_dio::dio16_slot_device, "dio16_slot", "16-bit DIO slot")
+DEFINE_DEVICE_TYPE(DIO32_SLOT, bus::hp_dio::dio32_slot_device, "dio32_slot", "32-bit DIO-II slot")
+DEFINE_DEVICE_TYPE(DIO16, bus::hp_dio::dio16_device, "dio16", "16-bit DIO bus")
+DEFINE_DEVICE_TYPE(DIO32, bus::hp_dio::dio32_device, "dio32", "32-bit DIO-II bus")
-namespace bus {
- namespace hp_dio {
+namespace bus::hp_dio {
//**************************************************************************
// LIVE DEVICE
@@ -105,6 +106,9 @@ dio16_device::dio16_device(const machine_config &mconfig, const char *tag, devic
dio16_device::dio16_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_prgspace(*this, finder_base::DUMMY_TAG, -1),
+ m_bus_index{0},
+ m_irq{0},
+ m_dmar{0},
m_irq1_out_cb(*this),
m_irq2_out_cb(*this),
m_irq3_out_cb(*this),
@@ -125,16 +129,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));
@@ -243,7 +237,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)
@@ -251,9 +245,7 @@ WRITE_LINE_MEMBER(dio16_device::reset_in)
}
}
-void dio16_device::install_memory(offs_t start, offs_t end,
- read16_delegate rhandler,
- write16_delegate whandler) {
+template<typename R, typename W> void dio16_device::install_memory(offs_t start, offs_t end, R rhandler, W whandler) {
switch (m_prgwidth) {
case 16:
m_prgspace->install_readwrite_handler(start, end, rhandler,
@@ -268,10 +260,13 @@ void dio16_device::install_memory(offs_t start, offs_t end,
}
}
-void dio16_device::install_bank(offs_t start, offs_t end, const char *tag, uint8_t *data)
+template void dio16_device::install_memory<read16_delegate, write16_delegate >(offs_t start, offs_t end, read16_delegate rhandler, write16_delegate whandler);
+template void dio16_device::install_memory<read16s_delegate, write16s_delegate >(offs_t start, offs_t end, read16s_delegate rhandler, write16s_delegate whandler);
+template void dio16_device::install_memory<read16sm_delegate, write16sm_delegate >(offs_t start, offs_t end, read16sm_delegate rhandler, write16sm_delegate whandler);
+
+void dio16_device::install_bank(offs_t start, offs_t end, uint8_t *data)
{
- m_prgspace->install_readwrite_bank(start, end, 0, tag);
- machine().root_device().membank(m_prgspace->device().siblingtag(tag).c_str())->set_base(data);
+ m_prgspace->install_ram(start, end, data);
}
void dio16_device::unmap_bank(offs_t start, offs_t end)
@@ -279,10 +274,9 @@ void dio16_device::unmap_bank(offs_t start, offs_t end)
m_prgspace->unmap_readwrite(start, end);
}
-void dio16_device::install_rom(offs_t start, offs_t end, const char *tag, uint8_t *data)
+void dio16_device::install_rom(offs_t start, offs_t end, uint8_t *data)
{
- m_prgspace->install_read_bank(start, end, 0, tag);
- machine().root_device().membank(m_prgspace->device().siblingtag(tag).c_str())->set_base(data);
+ m_prgspace->install_rom(start, end, data);
}
void dio16_device::unmap_rom(offs_t start, offs_t end)
@@ -300,8 +294,8 @@ void device_dio16_card_interface::set_bus(dio16_device &bus)
//**************************************************************************
device_dio16_card_interface::device_dio16_card_interface(const machine_config &mconfig, device_t &device) :
- device_slot_card_interface(mconfig, device),
- m_dio_dev(nullptr), m_next(nullptr)
+ device_interface(device, "hpdio"),
+ m_dio_dev(nullptr)
{
}
@@ -351,7 +345,6 @@ void device_dio32_card_interface::interface_pre_start()
}
} // namespace bus::hp_dio
-} // namespace bus
void dio16_cards(device_slot_interface & device)
{
@@ -359,11 +352,18 @@ void dio16_cards(device_slot_interface & device)
device.option_add("98544", HPDIO_98544);
device.option_add("98603a", HPDIO_98603A);
device.option_add("98603b", HPDIO_98603B);
+ device.option_add("98624", HPDIO_98624);
device.option_add("98643", HPDIO_98643);
device.option_add("98644", HPDIO_98644);
device.option_add("human_interface", HPDIO_HUMAN_INTERFACE);
}
+void dio16_hp98x6_cards(device_slot_interface &device)
+{
+ device.option_add("98628", HPDIO_98628);
+ device.option_add("98629", HPDIO_98629);
+}
+
void dio32_cards(device_slot_interface & device)
{
dio16_cards(device);
diff --git a/src/devices/bus/hp_dio/hp_dio.h b/src/devices/bus/hp_dio/hp_dio.h
index ee680b08d4b..7cc29f84ce7 100644
--- a/src/devices/bus/hp_dio/hp_dio.h
+++ b/src/devices/bus/hp_dio/hp_dio.h
@@ -12,18 +12,18 @@
***************************************************************************/
-#ifndef MAME_BUS_HPDIO_HPDIO_H
-#define MAME_BUS_HPDIO_HPDIO_H
+#ifndef MAME_BUS_HP_DIO_HP_DIO_H
+#define MAME_BUS_HP_DIO_HP_DIO_H
#pragma once
-namespace bus {
- namespace hp_dio {
+namespace bus::hp_dio {
//**************************************************************************
// TYPE DEFINITIONS
//**************************************************************************
+class device_dio16_card_interface;
class dio16_device;
class dio16_slot_device : public device_t, public device_slot_interface
@@ -49,15 +49,14 @@ protected:
dio16_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;
+ virtual void device_resolve_objects() override ATTR_COLD;
virtual void device_validity_check(validity_checker &valid) const override;
- virtual void device_start() override;
+ virtual void device_start() override ATTR_COLD;
// configuration
required_device<dio16_device> m_dio;
};
-class device_dio16_card_interface;
// ======================> dio16_device
class dio16_device : public device_t
{
@@ -78,14 +77,14 @@ public:
auto irq6_out_cb() { return m_irq6_out_cb.bind(); }
auto irq7_out_cb() { return m_irq7_out_cb.bind(); }
- void install_memory(offs_t start, offs_t end, read16_delegate rhandler, write16_delegate whandler);
+ template<typename R, typename W> void install_memory(offs_t start, offs_t end, R rhandler, W whandler);
// DANGER: these will currently produce different results for a DIO-I card on DIO-I and DIO-II systems
// due to the varying bus widths. Using all install_memory() shields you from this problem.
// Either know what you're doing (m_prgwidth is available to cards for this purpose) or
// only use these for 32-bit DIO-II cards.
- void install_bank(offs_t start, offs_t end, const char *tag, uint8_t *data);
- void install_rom(offs_t start, offs_t end, const char *tag, uint8_t *data);
+ void install_bank(offs_t start, offs_t end, uint8_t *data);
+ void install_rom(offs_t start, offs_t end, uint8_t *data);
void unmap_bank(offs_t start, offs_t end);
void unmap_rom(offs_t start, offs_t end);
@@ -94,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; }
@@ -133,8 +132,8 @@ protected:
void install_space(int spacenum, offs_t start, offs_t end, read8_delegate rhandler, write8_delegate whandler);
// device-level overrides
- virtual void device_start() override;
- virtual void device_reset() override;
+ virtual void device_start() override ATTR_COLD;
+ virtual void device_reset() override ATTR_COLD;
// internal state
std::list<device_dio16_card_interface *> m_cards;
@@ -162,15 +161,13 @@ protected:
// ======================> device_dio16_card_interface
// class representing interface-specific live dio16 card
-class device_dio16_card_interface : public device_slot_card_interface
+class device_dio16_card_interface : public device_interface
{
friend class dio16_device;
- template <class ElementType> friend class simple_list;
public:
// construction/destruction
virtual ~device_dio16_card_interface();
- device_dio16_card_interface *next() const { return m_next; }
// inline configuration
void set_diobus(dio16_device &dio_device) {
m_dio_dev = &dio_device;
@@ -185,35 +182,35 @@ protected:
virtual void interface_pre_start() override;
- int get_index() { return m_index; };
+ 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(); }
@@ -222,7 +219,6 @@ protected:
private:
void set_bus(dio16_device & bus);
- device_dio16_card_interface *m_next;
unsigned int m_index;
};
@@ -246,7 +242,7 @@ public:
protected:
// device-level overrides
- virtual void device_start() override;
+ virtual void device_start() override ATTR_COLD;
};
// ======================> dio32_device
@@ -260,7 +256,7 @@ public:
protected:
// device-level overrides
- virtual void device_start() override;
+ virtual void device_start() override ATTR_COLD;
};
// ======================> device_dio32_card_interface
@@ -280,8 +276,8 @@ protected:
dio32_device &dio() { assert(m_dio_dev); return downcast<dio32_device &>(*m_dio_dev); }
};
+
} // namespace bus::hp_dio
-} // namespace bus
// device type definition
DECLARE_DEVICE_TYPE_NS(DIO16_SLOT, bus::hp_dio, dio16_slot_device)
@@ -290,6 +286,7 @@ DECLARE_DEVICE_TYPE_NS(DIO32_SLOT, bus::hp_dio, dio32_slot_device)
DECLARE_DEVICE_TYPE_NS(DIO16, bus::hp_dio, dio16_device)
void dio16_cards(device_slot_interface &device);
+void dio16_hp98x6_cards(device_slot_interface &device);
void dio32_cards(device_slot_interface &device);
-#endif // MAME_BUS_HPDIO_HPDIO_H
+#endif // MAME_BUS_HP_DIO_HP_DIO_H
diff --git a/src/devices/bus/hp_dio/human_interface.cpp b/src/devices/bus/hp_dio/human_interface.cpp
index 509a2151a3b..669c77e4ffb 100644
--- a/src/devices/bus/hp_dio/human_interface.cpp
+++ b/src/devices/bus/hp_dio/human_interface.cpp
@@ -19,10 +19,9 @@
//#define VERBOSE 1
#include "logmacro.h"
-DEFINE_DEVICE_TYPE_NS(HPDIO_HUMAN_INTERFACE, bus::hp_dio, human_interface_device, "human_interface", "HP human interface card")
+DEFINE_DEVICE_TYPE(HPDIO_HUMAN_INTERFACE, bus::hp_dio::human_interface_device, "human_interface", "HP human interface card")
-namespace bus {
- namespace hp_dio {
+namespace bus::hp_dio {
void human_interface_device::device_add_mconfig(machine_config &config)
{
@@ -108,19 +107,30 @@ human_interface_device::human_interface_device(const machine_config &mconfig, de
m_sound(*this, "sn76494"),
m_tms9914(*this, "tms9914"),
m_rtc(*this, "rtc"),
- m_ieee488(*this, IEEE488_TAG)
+ m_ieee488(*this, IEEE488_TAG),
+ m_hil_read(false),
+ m_kbd_nmi(false),
+ m_gpib_irq_line(false),
+ m_gpib_dma_line(false),
+ m_old_latch_enable(false),
+ m_gpib_dma_enable(false),
+ m_hil_data(0),
+ m_latch_data(0),
+ m_rtc_data(0),
+ m_ppoll_sc(0),
+ m_ppoll_mask(0)
{
}
void human_interface_device::device_start()
{
program_space().install_readwrite_handler(0x420000, 0x420003, 0x0003, 0xfffc, 0,
- read8_delegate(FUNC(upi41_cpu_device::upi41_master_r), &(*m_iocpu)),
- write8_delegate(FUNC(upi41_cpu_device::upi41_master_w), &(*m_iocpu)), 0x00ff00ff);
+ read8sm_delegate(*m_iocpu, FUNC(upi41_cpu_device::upi41_master_r)),
+ write8sm_delegate(*m_iocpu, FUNC(upi41_cpu_device::upi41_master_w)), 0x00ff00ff);
program_space().install_readwrite_handler(0x470000, 0x47001f, 0x1f, 0xffe0, 0,
- read8_delegate(FUNC(human_interface_device::gpib_r), this),
- write8_delegate(FUNC(human_interface_device::gpib_w), this), 0x00ff00ff);
+ read8sm_delegate(*this, FUNC(human_interface_device::gpib_r)),
+ write8sm_delegate(*this, FUNC(human_interface_device::gpib_w)), 0x00ff00ff);
save_item(NAME(m_hil_read));
save_item(NAME(m_kbd_nmi));
@@ -137,10 +147,17 @@ void human_interface_device::device_start()
void human_interface_device::device_reset()
{
- m_ppoll_sc = 0;
- m_gpib_irq_line = false;
+ m_hil_read = false;
m_kbd_nmi = false;
+ m_gpib_irq_line = false;
+ m_gpib_dma_line = false;
+ m_gpib_dma_enable = false;
m_old_latch_enable = true;
+ m_ppoll_sc = 0;
+ m_hil_data = 0;
+ m_latch_data = 0;
+ m_rtc_data = 0;
+ m_ppoll_mask = 0;
m_rtc->cs1_w(ASSERT_LINE);
m_rtc->cs2_w(CLEAR_LINE);
m_rtc->write_w(CLEAR_LINE);
@@ -149,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();
@@ -161,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();
@@ -172,13 +189,13 @@ 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();
}
-WRITE8_MEMBER(human_interface_device::ieee488_dio_w)
+void human_interface_device::ieee488_dio_w(uint8_t data)
{
if (m_ieee488->atn_r() || m_ieee488->eoi_r())
return;
@@ -191,7 +208,7 @@ WRITE8_MEMBER(human_interface_device::ieee488_dio_w)
}
}
-WRITE8_MEMBER(human_interface_device::gpib_w)
+void human_interface_device::gpib_w(offs_t offset, uint8_t data)
{
if (offset & 0x08) {
m_tms9914->write(offset & 0x07, data);
@@ -217,7 +234,7 @@ WRITE8_MEMBER(human_interface_device::gpib_w)
if (m_ppoll_sc & PPOLL_IE) {
LOG("%s: start parallel poll\n", __func__);
- ieee488_dio_w(space, 0, m_ieee488->dio_r(space, 0));
+ ieee488_dio_w(m_ieee488->dio_r());
}
break;
case 4:
@@ -229,7 +246,7 @@ WRITE8_MEMBER(human_interface_device::gpib_w)
LOG("gpib_w: %s %02X = %02X\n", machine().describe_context().c_str(), offset, data);
}
-READ8_MEMBER(human_interface_device::gpib_r)
+uint8_t human_interface_device::gpib_r(offs_t offset)
{
uint8_t data = 0xff;
@@ -266,7 +283,7 @@ READ8_MEMBER(human_interface_device::gpib_r)
}
-WRITE8_MEMBER(human_interface_device::iocpu_port1_w)
+void human_interface_device::iocpu_port1_w(uint8_t data)
{
m_hil_data = data;
m_rtc->d0_w(data & 0x01 ? ASSERT_LINE : CLEAR_LINE);
@@ -275,12 +292,12 @@ WRITE8_MEMBER(human_interface_device::iocpu_port1_w)
m_rtc->d3_w(data & 0x08 ? ASSERT_LINE : CLEAR_LINE);
}
-WRITE8_MEMBER(human_interface_device::iocpu_port2_w)
+void human_interface_device::iocpu_port2_w(uint8_t data)
{
bool latch_enable = data & LATCH_EN;
if ((data & (HIL_CS|HIL_WE)) == 0)
- m_mlc->write(space, (m_latch_data & 0xc0) >> 6, m_hil_data, 0xff);
+ m_mlc->write((m_latch_data & 0xc0) >> 6, m_hil_data);
if ((data & SN76494_EN) == 0)
m_sound->write(m_hil_data);
@@ -307,21 +324,21 @@ WRITE8_MEMBER(human_interface_device::iocpu_port2_w)
m_old_latch_enable = latch_enable;
}
-READ8_MEMBER(human_interface_device::iocpu_port1_r)
+uint8_t human_interface_device::iocpu_port1_r()
{
if (m_hil_read)
- return m_mlc->read(space, (m_latch_data & 0xc0) >> 6, 0xff);
+ return m_mlc->read((m_latch_data & 0xc0) >> 6);
if (m_latch_data & 0x20)
return m_rtc_data;
return 0xff;
}
-READ8_MEMBER(human_interface_device::iocpu_test0_r)
+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;
@@ -330,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;
@@ -338,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;
@@ -347,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;
@@ -371,4 +388,3 @@ uint8_t human_interface_device::dmack_r_in(int channel)
}
} // namespace bus::hp_dio
-} // namespace bus
diff --git a/src/devices/bus/hp_dio/human_interface.h b/src/devices/bus/hp_dio/human_interface.h
index 4a2e159d3f7..910e73b4039 100644
--- a/src/devices/bus/hp_dio/human_interface.h
+++ b/src/devices/bus/hp_dio/human_interface.h
@@ -1,8 +1,8 @@
// license:BSD-3-Clause
// copyright-holders:Sven Schnelle
-#ifndef MAME_BUS_HPDIO_HUMAN_INTERFACE_H
-#define MAME_BUS_HPDIO_HUMAN_INTERFACE_H
+#ifndef MAME_BUS_HP_DIO_HUMAN_INTERFACE_H
+#define MAME_BUS_HP_DIO_HUMAN_INTERFACE_H
#pragma once
@@ -14,8 +14,9 @@
#include "bus/hp_hil/hp_hil.h"
#include "bus/hp_hil/hil_devices.h"
#include "bus/ieee488/ieee488.h"
-namespace bus {
- namespace hp_dio {
+
+namespace bus::hp_dio {
+
class human_interface_device :
public device_t,
public device_dio16_card_interface
@@ -26,35 +27,35 @@ public:
protected:
human_interface_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_start() override ATTR_COLD;
+ virtual void device_reset() override ATTR_COLD;
- virtual void device_add_mconfig(machine_config &config) override;
- virtual const tiny_rom_entry *device_rom_region() const override;
+ virtual void device_add_mconfig(machine_config &config) override ATTR_COLD;
+ virtual const tiny_rom_entry *device_rom_region() const override ATTR_COLD;
private:
/* 8042 interface */
- DECLARE_WRITE8_MEMBER(iocpu_port1_w);
- DECLARE_WRITE8_MEMBER(iocpu_port2_w);
- DECLARE_READ8_MEMBER(iocpu_port1_r);
- DECLARE_READ8_MEMBER(iocpu_test0_r);
+ void iocpu_port1_w(uint8_t data);
+ void iocpu_port2_w(uint8_t data);
+ uint8_t iocpu_port1_r();
+ uint8_t iocpu_test0_r();
/* GPIB */
- DECLARE_READ8_MEMBER(gpib_r);
- DECLARE_WRITE8_MEMBER(gpib_w);
- DECLARE_WRITE8_MEMBER(ieee488_dio_w);
+ uint8_t gpib_r(offs_t offset);
+ 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;
@@ -68,7 +69,7 @@ private:
required_device<msm58321_device> m_rtc;
required_device<ieee488_device> m_ieee488;
- void iocpu_map(address_map &map);
+ void iocpu_map(address_map &map) ATTR_COLD;
static constexpr uint8_t HIL_CS = 0x01;
static constexpr uint8_t HIL_WE = 0x02;
@@ -96,9 +97,9 @@ private:
uint8_t m_ppoll_mask;
};
-} } // namespace bus::hp_dio
+} // namespace bus::hp_dio
// device type definition
DECLARE_DEVICE_TYPE_NS(HPDIO_HUMAN_INTERFACE, bus::hp_dio, human_interface_device)
-#endif // MAME_BUS_HPDIO_HUMAN_INTERFACE_H
+#endif // MAME_BUS_HP_DIO_HUMAN_INTERFACE_H
diff --git a/src/devices/bus/hp_hil/hlebase.cpp b/src/devices/bus/hp_hil/hlebase.cpp
index c7b121dcb44..247dafeea51 100644
--- a/src/devices/bus/hp_hil/hlebase.cpp
+++ b/src/devices/bus/hp_hil/hlebase.cpp
@@ -1,4 +1,4 @@
-// license:BSD-3-Cl ause
+// license:BSD-3-Clause
// copyright-holders:Sergey Svishchev
#include "emu.h"
#include "hlebase.h"
@@ -6,8 +6,7 @@
//#define VERBOSE 1
#include "logmacro.h"
-namespace bus {
- namespace hp_hil {
+namespace bus::hp_hil {
/***************************************************************************
BASE HLE KEYBOARD DEVICE
@@ -21,6 +20,8 @@ namespace bus {
hle_device_base::hle_device_base(machine_config const &mconfig, device_type type, char const *tag, device_t *owner, uint32_t clock)
: device_t(mconfig, type, tag, owner, clock)
, device_hp_hil_interface(mconfig, *this)
+ , m_powerup(true)
+ , m_passthru(false)
{ }
@@ -141,6 +142,12 @@ bool hle_device_base::hil_write(uint16_t *pdata)
return true;
break;
+ case HPHIL_DKA:
+ case HPHIL_EK1:
+ case HPHIL_EK2:
+ hil_typematic(data);
+ break;
+
default:
LOG("command %02X unknown\n", data);
break;
@@ -152,4 +159,3 @@ out:
}
} // namespace bus::hp_hil
-} // namespace bus
diff --git a/src/devices/bus/hp_hil/hlebase.h b/src/devices/bus/hp_hil/hlebase.h
index b5cbfa84bef..16cedab8ab2 100644
--- a/src/devices/bus/hp_hil/hlebase.h
+++ b/src/devices/bus/hp_hil/hlebase.h
@@ -1,7 +1,7 @@
// license:BSD-3-Clause
// copyright-holders:Sergey Svishchev
-#ifndef MAME_DEVICES_HP_HIL_HLEBASE_H
-#define MAME_DEVICES_HP_HIL_HLEBASE_H
+#ifndef MAME_BUS_HP_HIL_HLEBASE_H
+#define MAME_BUS_HP_HIL_HLEBASE_H
#pragma once
@@ -9,8 +9,7 @@
#include "machine/keyboard.h"
-namespace bus {
- namespace hp_hil {
+namespace bus::hp_hil {
class hle_device_base
: public device_t
@@ -24,12 +23,13 @@ protected:
hle_device_base(machine_config const &mconfig, device_type type, char const *tag, device_t *owner, uint32_t clock);
// device overrides
- virtual void device_start() override;
- virtual void device_reset() override;
+ virtual void device_start() override ATTR_COLD;
+ virtual void device_reset() override ATTR_COLD;
// device_hp_hil_interface overrides
virtual bool hil_write(uint16_t *data) override;
virtual void hil_idd() = 0;
+ virtual void hil_typematic(uint8_t command) {}
virtual int hil_poll() = 0;
private:
@@ -40,6 +40,5 @@ private:
};
} // namespace bus::hp_hil
-} // namespace bus
-#endif // MAME_DEVICES_HP_HIL_HLEBASE_H
+#endif // MAME_BUS_HP_HIL_HLEBASE_H
diff --git a/src/devices/bus/hp_hil/hlekbd.cpp b/src/devices/bus/hp_hil/hlekbd.cpp
index 398579e7f08..25414fc2de5 100644
--- a/src/devices/bus/hp_hil/hlekbd.cpp
+++ b/src/devices/bus/hp_hil/hlekbd.cpp
@@ -11,10 +11,10 @@
DEVICE TYPE GLOBALS
***************************************************************************/
-DEFINE_DEVICE_TYPE_NS(HP_IPC_HLE_KEYBOARD, bus::hp_hil, hle_hp_ipc_device, "hp_ipc_hle_kbd", "HP Integral Keyboard (HLE)")
-DEFINE_DEVICE_TYPE_NS(HP_ITF_HLE_KEYBOARD, bus::hp_hil, hle_hp_itf_device, "hp_itf_hle_kbd", "HP ITF Keyboard")
+DEFINE_DEVICE_TYPE(HP_IPC_HLE_KEYBOARD, bus::hp_hil::hle_hp_ipc_device, "hp_ipc_hle_kbd", "HP Integral Keyboard (HLE)")
+DEFINE_DEVICE_TYPE(HP_ITF_HLE_KEYBOARD, bus::hp_hil::hle_hp_itf_device, "hp_itf_hle_kbd", "HP ITF Keyboard")
-namespace bus { namespace hp_hil {
+namespace bus::hp_hil {
namespace {
@@ -439,6 +439,7 @@ void hle_hp_itf_device::transmit_byte(uint8_t byte)
hle_hp_ipc_device::hle_hp_ipc_device(machine_config const &mconfig, char const *tag, device_t *owner, uint32_t clock)
: hle_device_base(mconfig, HP_IPC_HLE_KEYBOARD, tag, owner, clock)
, device_matrix_keyboard_interface(mconfig, *this, "COL1", "COL2", "COL3", "COL4", "COL5", "COL6", "COL7", "COL8", "COL9", "COL10", "COL11", "COL12", "COL13", "COL14", "COL15")
+ , m_modifiers(*this, "COL8")
{ }
void hle_hp_ipc_device::device_reset()
@@ -446,25 +447,77 @@ void hle_hp_ipc_device::device_reset()
m_fifo.clear();
reset_key_state();
start_processing(attotime::from_hz(1'200));
+ typematic_stop();
+ m_typematic = false;
+ m_typematic_rate = 0;
}
void hle_hp_ipc_device::hil_idd()
{
- m_hp_hil_mlc->hil_write(0x0100 | ioport("COL0")->read());
+ m_hp_hil_mlc->hil_write(0x0100 | ioport("COL0")->read());
m_hp_hil_mlc->hil_write(m_device_id16 | 0);
}
+void hle_hp_ipc_device::hil_typematic(uint8_t command)
+{
+ switch (command)
+ {
+ case HPHIL_DKA:
+ typematic_stop();
+ m_typematic = false;
+ m_typematic_rate = 0;
+ break;
+
+ case HPHIL_EK1:
+ m_typematic = true;
+ m_typematic_rate = 30;
+ break;
+
+ case HPHIL_EK2:
+ m_typematic = true;
+ m_typematic_rate = 60;
+ break;
+ }
+}
+
void hle_hp_ipc_device::key_make(uint8_t row, uint8_t column)
{
transmit_byte((((row + 1) ^ 8) << 4) + (column << 1));
+ if (m_typematic)
+ typematic_start(row, column, typematic_delay(), typematic_period());
}
+void hle_hp_ipc_device::key_repeat(uint8_t row, uint8_t column)
+{
+ transmit_byte((((row + 1) ^ 8) << 4) + (column << 1));
+}
void hle_hp_ipc_device::key_break(uint8_t row, uint8_t column)
{
transmit_byte((((row + 1) ^ 8) << 4) + (column << 1) + 1);
+ typematic_stop();
}
+void hle_hp_ipc_device::will_scan_row(u8 row)
+{
+ u16 const modifiers(m_modifiers->read() & 0x7c);
+ if (modifiers != m_last_modifiers && m_typematic)
+ typematic_restart(typematic_delay(), typematic_period());
+
+ m_last_modifiers = modifiers;
+}
+
+attotime hle_hp_ipc_device::typematic_delay() const
+{
+ return attotime::from_msec(250); // FIXME
+}
+
+attotime hle_hp_ipc_device::typematic_period() const
+{
+ return attotime::from_hz(m_typematic_rate);
+}
+
+
int hle_hp_ipc_device::hil_poll()
{
int frames = 1;
@@ -553,8 +606,8 @@ ioport_constructor hle_hp_itf_device::device_input_ports() const
void hle_hp_itf_device::hil_idd()
{
- m_hp_hil_mlc->hil_write(m_device_id16 | ioport("COL0")->read());
+ m_hp_hil_mlc->hil_write(m_device_id16 | ioport("COL0")->read());
m_hp_hil_mlc->hil_write(m_device_id16 | 0x04);
}
-} } // namespace bus::hp_hil
+} // namespace bus::hp_hil
diff --git a/src/devices/bus/hp_hil/hlekbd.h b/src/devices/bus/hp_hil/hlekbd.h
index 25df57da3b3..921cf4bb757 100644
--- a/src/devices/bus/hp_hil/hlekbd.h
+++ b/src/devices/bus/hp_hil/hlekbd.h
@@ -1,7 +1,7 @@
// license:BSD-3-Clause
// copyright-holders:Sergey Svishchev
-#ifndef MAME_DEVICES_HP_HIL_HLEKBD_H
-#define MAME_DEVICES_HP_HIL_HLEKBD_H
+#ifndef MAME_BUS_HP_HIL_HLEKBD_H
+#define MAME_BUS_HP_HIL_HLEKBD_H
#pragma once
@@ -10,7 +10,7 @@
#include "machine/keyboard.h"
-namespace bus { namespace hp_hil {
+namespace bus::hp_hil {
class hle_hp_ipc_device
: public hle_device_base
@@ -19,17 +19,30 @@ class hle_hp_ipc_device
public:
hle_hp_ipc_device(machine_config const &mconfig, char const *tag, device_t *owner, uint32_t clock);
- virtual ioport_constructor device_input_ports() const override;
- virtual void device_reset() override;
+ virtual ioport_constructor device_input_ports() const override ATTR_COLD;
+ virtual void device_reset() override ATTR_COLD;
// device_matrix_keyboard_interface overrides
virtual void key_make(uint8_t row, uint8_t column) override;
+ virtual void key_repeat(uint8_t row, uint8_t column) override;
virtual void key_break(uint8_t row, uint8_t column) override;
virtual int hil_poll() override;
virtual void hil_idd() override;
+ virtual void hil_typematic(uint8_t command) override;
+
+ required_ioport m_modifiers;
+
private:
+ virtual void will_scan_row(u8 row) override;
+
util::fifo<uint8_t, 8> m_fifo;
void transmit_byte(uint8_t byte);
+ attotime typematic_delay() const;
+ attotime typematic_period() const;
+
+ u16 m_last_modifiers;
+ bool m_typematic;
+ int m_typematic_rate;
};
class hle_hp_itf_device
@@ -38,8 +51,8 @@ class hle_hp_itf_device
{
public:
hle_hp_itf_device(machine_config const &mconfig, char const *tag, device_t *owner, uint32_t clock);
- virtual void device_reset() override;
- virtual ioport_constructor device_input_ports() const override;
+ virtual void device_reset() override ATTR_COLD;
+ virtual ioport_constructor device_input_ports() const override ATTR_COLD;
// device_matrix_keyboard_interface overrides
virtual void key_make(uint8_t row, uint8_t column) override;
@@ -51,10 +64,10 @@ private:
void transmit_byte(uint8_t byte);
};
-} } // namespace bus::hp_hil
+} // namespace bus::hp_hil
DECLARE_DEVICE_TYPE_NS(HP_IPC_HLE_KEYBOARD, bus::hp_hil, hle_hp_ipc_device);
DECLARE_DEVICE_TYPE_NS(HP_ITF_HLE_KEYBOARD, bus::hp_hil, hle_hp_itf_device);
-#endif // MAME_DEVICES_HP_HIL_HLEKBD_H
+#endif // MAME_BUS_HP_HIL_HLEKBD_H
diff --git a/src/devices/bus/hp_hil/hlemouse.cpp b/src/devices/bus/hp_hil/hlemouse.cpp
index 2303f011272..cfaa0329ed4 100644
--- a/src/devices/bus/hp_hil/hlemouse.cpp
+++ b/src/devices/bus/hp_hil/hlemouse.cpp
@@ -10,10 +10,9 @@
DEVICE TYPE GLOBALS
***************************************************************************/
-DEFINE_DEVICE_TYPE_NS(HP_46060B_MOUSE, bus::hp_hil, hle_hp_46060b_device, "hp_46060b", "HP 46060B Mouse")
+DEFINE_DEVICE_TYPE(HP_46060B_MOUSE, bus::hp_hil::hle_hp_46060b_device, "hp_46060b", "HP 46060B Mouse")
-namespace bus {
- namespace hp_hil {
+namespace bus::hp_hil {
namespace {
@@ -23,24 +22,29 @@ namespace {
INPUT_PORTS_START( hle_hp_46060b_device )
PORT_START("mouse_buttons")
- PORT_BIT(hle_hp_46060b_device::MOUSE_LBUTTON, IP_ACTIVE_HIGH, IPT_BUTTON1) PORT_NAME("Mouse Left Button") PORT_CODE(MOUSECODE_BUTTON1) PORT_CHANGED_MEMBER(DEVICE_SELF, hle_hp_46060b_device, mouse_button, 0)
- PORT_BIT(hle_hp_46060b_device::MOUSE_MBUTTON, IP_ACTIVE_HIGH, IPT_BUTTON2) PORT_NAME("Mouse Middle Button") PORT_CODE(MOUSECODE_BUTTON3) PORT_CHANGED_MEMBER(DEVICE_SELF, hle_hp_46060b_device, mouse_button, 0)
- PORT_BIT(hle_hp_46060b_device::MOUSE_RBUTTON, IP_ACTIVE_HIGH, IPT_BUTTON3) PORT_NAME("Mouse Right Button") PORT_CODE(MOUSECODE_BUTTON2) PORT_CHANGED_MEMBER(DEVICE_SELF, hle_hp_46060b_device, mouse_button, 0)
+ PORT_BIT(hle_hp_46060b_device::MOUSE_LBUTTON, IP_ACTIVE_HIGH, IPT_BUTTON1) PORT_NAME("Mouse Left Button") PORT_CODE(MOUSECODE_BUTTON1) PORT_CHANGED_MEMBER(DEVICE_SELF, FUNC(hle_hp_46060b_device::mouse_button), 0)
+ PORT_BIT(hle_hp_46060b_device::MOUSE_MBUTTON, IP_ACTIVE_HIGH, IPT_BUTTON2) PORT_NAME("Mouse Middle Button") PORT_CODE(MOUSECODE_BUTTON3) PORT_CHANGED_MEMBER(DEVICE_SELF, FUNC(hle_hp_46060b_device::mouse_button), 0)
+ PORT_BIT(hle_hp_46060b_device::MOUSE_RBUTTON, IP_ACTIVE_HIGH, IPT_BUTTON3) PORT_NAME("Mouse Right Button") PORT_CODE(MOUSECODE_BUTTON2) PORT_CHANGED_MEMBER(DEVICE_SELF, FUNC(hle_hp_46060b_device::mouse_button), 0)
PORT_START("mouse_x")
- PORT_BIT(0xff, 0x00, IPT_MOUSE_X) PORT_SENSITIVITY(50) PORT_KEYDELTA(0) PORT_PLAYER(1) PORT_CHANGED_MEMBER(DEVICE_SELF, hle_hp_46060b_device, mouse_x, 0)
+ PORT_BIT(0xff, 0x00, IPT_MOUSE_X) PORT_SENSITIVITY(50) PORT_KEYDELTA(0) PORT_PLAYER(1) PORT_CHANGED_MEMBER(DEVICE_SELF, FUNC(hle_hp_46060b_device::mouse_x), 0)
PORT_START("mouse_y")
- PORT_BIT(0xff, 0x00, IPT_MOUSE_Y) PORT_SENSITIVITY(50) PORT_KEYDELTA(0) PORT_PLAYER(1) PORT_CHANGED_MEMBER(DEVICE_SELF, hle_hp_46060b_device, mouse_y, 0)
+ PORT_BIT(0xff, 0x00, IPT_MOUSE_Y) PORT_SENSITIVITY(50) PORT_KEYDELTA(0) PORT_PLAYER(1) PORT_CHANGED_MEMBER(DEVICE_SELF, FUNC(hle_hp_46060b_device::mouse_y), 0)
INPUT_PORTS_END
} // anonymous namespace
hle_hp_46060b_device::hle_hp_46060b_device(machine_config const &mconfig, char const *tag, device_t *owner, uint32_t clock)
- : hle_device_base(mconfig, HP_46060B_MOUSE, tag, owner, clock)
+ : hle_device_base(mconfig, HP_46060B_MOUSE, tag, owner, clock),
+ mouse_x_delta{0},
+ mouse_y_delta{0},
+ mouse_buttons{0}
{ }
void hle_hp_46060b_device::device_reset()
{
m_fifo.clear();
+
+ mouse_x_delta = mouse_y_delta = 0;
}
int hle_hp_46060b_device::hil_poll()
@@ -122,5 +126,4 @@ INPUT_CHANGED_MEMBER(hle_hp_46060b_device::mouse_button)
mouse_buttons = data;
}
-} // namesapce bus::hp_hil
-} // namespace bus
+} // namespace bus::hp_hil
diff --git a/src/devices/bus/hp_hil/hlemouse.h b/src/devices/bus/hp_hil/hlemouse.h
index 7abfc1d5192..f8f4c019368 100644
--- a/src/devices/bus/hp_hil/hlemouse.h
+++ b/src/devices/bus/hp_hil/hlemouse.h
@@ -1,7 +1,7 @@
// license:BSD-3-Clause
// copyright-holders:Sven Schnelle
-#ifndef MAME_DEVICES_HP_HIL_HLEMOUSE_H
-#define MAME_DEVICES_HP_HIL_HLEMOUSE_H
+#ifndef MAME_BUS_HP_HIL_HLEMOUSE_H
+#define MAME_BUS_HP_HIL_HLEMOUSE_H
#pragma once
@@ -10,16 +10,15 @@
#include "machine/keyboard.h"
-namespace bus {
- namespace hp_hil {
+namespace bus::hp_hil {
class hle_hp_46060b_device
: public hle_device_base
{
public:
hle_hp_46060b_device(machine_config const &mconfig, char const *tag, device_t *owner, uint32_t clock);
- virtual void device_reset() override;
- virtual ioport_constructor device_input_ports() const override;
+ virtual void device_reset() override ATTR_COLD;
+ virtual ioport_constructor device_input_ports() const override ATTR_COLD;
virtual int hil_poll() override;
virtual void hil_idd() override;
enum state_mask
@@ -45,8 +44,7 @@ public:
};
} // namespace bus::hp_hil
-} // namespace bus
DECLARE_DEVICE_TYPE_NS(HP_46060B_MOUSE, bus::hp_hil, hle_hp_46060b_device);
-#endif // MAME_DEVICES_HP_HIL_HLEMOUSE_H
+#endif // MAME_BUS_HP_HIL_HLEMOUSE_H
diff --git a/src/devices/bus/hp_hil/hp_hil.cpp b/src/devices/bus/hp_hil/hp_hil.cpp
index 2e8a904c97b..e1e477b5d58 100644
--- a/src/devices/bus/hp_hil/hp_hil.cpp
+++ b/src/devices/bus/hp_hil/hp_hil.cpp
@@ -27,7 +27,7 @@ DEFINE_DEVICE_TYPE(HP_HIL_SLOT, hp_hil_slot_device, "hp_hil_slot", "HP-HIL Slot"
//-------------------------------------------------
hp_hil_slot_device::hp_hil_slot_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
: device_t(mconfig, HP_HIL_SLOT, tag, owner, clock)
- , device_slot_interface(mconfig, *this)
+ , device_single_card_slot_interface<device_hp_hil_interface>(mconfig, *this)
, m_mlc(*this, finder_base::DUMMY_TAG)
{
}
@@ -39,7 +39,7 @@ hp_hil_slot_device::hp_hil_slot_device(const machine_config &mconfig, const char
void hp_hil_slot_device::device_start()
{
- device_hp_hil_interface *dev = dynamic_cast<device_hp_hil_interface *>(get_card_device());
+ device_hp_hil_interface *dev = get_card_device();
if (dev)
dev->set_hp_hil_mlc(*m_mlc);
}
@@ -56,14 +56,19 @@ DEFINE_DEVICE_TYPE(HP_HIL_MLC, hp_hil_mlc_device, "hp_hil_mlc", "HP-HIL Master L
// hp_hil_mlc_device - constructor
//-------------------------------------------------
hp_hil_mlc_device::hp_hil_mlc_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
- : device_t(mconfig, HP_HIL_MLC, tag, owner, clock)
- , int_cb(*this)
- , nmi_cb(*this)
+ : device_t{mconfig, HP_HIL_MLC, tag, owner, clock}
+ , m_r2{0}
+ , m_r3{0}
+ , m_w1{0}
+ , m_w2{0}
+ , m_w3{0}
+ , m_loop{1}
+ , int_cb{*this}
+ , nmi_cb{*this}
{
- m_loop = 1;
}
-void hp_hil_mlc_device::add_hp_hil_device( device_hp_hil_interface *device )
+void hp_hil_mlc_device::add_hp_hil_device(device_hp_hil_interface *device)
{
m_device_list.append(*device);
}
@@ -74,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));
@@ -96,10 +97,14 @@ void hp_hil_mlc_device::device_reset()
m_r2 = 0;
m_r3 = 0; // HPMLC_R3_NMI;
+ m_w1 = 0;
+ m_w2 = 0;
+ m_w3 = 0;
+ m_loop = 1;
}
-WRITE8_MEMBER(hp_hil_mlc_device::write)
+void hp_hil_mlc_device::write(offs_t offset, uint8_t data)
{
device_hp_hil_interface *entry = m_device_list.first();
uint16_t tmp = data | (m_w1 << 8);
@@ -154,7 +159,7 @@ WRITE8_MEMBER(hp_hil_mlc_device::write)
}
}
-READ8_MEMBER(hp_hil_mlc_device::read)
+uint8_t hp_hil_mlc_device::read(offs_t offset)
{
uint8_t data = 0;
@@ -216,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))
@@ -242,8 +247,10 @@ WRITE_LINE_MEMBER(hp_hil_mlc_device::ap_w)
//-------------------------------------------------
device_hp_hil_interface::device_hp_hil_interface(const machine_config &mconfig, device_t &device)
- : device_slot_card_interface(mconfig, device)
+ : device_interface(device, "hphil")
, m_hp_hil_mlc(nullptr)
+ , m_device_id(0)
+ , m_device_id16(0)
, m_next(nullptr)
{
}
diff --git a/src/devices/bus/hp_hil/hp_hil.h b/src/devices/bus/hp_hil/hp_hil.h
index 7ec8335a8fb..69724bdb2f4 100644
--- a/src/devices/bus/hp_hil/hp_hil.h
+++ b/src/devices/bus/hp_hil/hp_hil.h
@@ -59,7 +59,7 @@
#define HPHIL_DHR 0xFE // Device Hard Reset
/*
- * init sequnce (p. 4-13)
+ * init sequence (p. 4-13)
*
* DHR
* IFC
@@ -79,10 +79,11 @@
// TYPE DEFINITIONS
//**************************************************************************
+class device_hp_hil_interface;
class hp_hil_mlc_device;
-class hp_hil_slot_device : public device_t, public device_slot_interface
+class hp_hil_slot_device : public device_t, public device_single_card_slot_interface<device_hp_hil_interface>
{
public:
// construction/destruction
@@ -100,7 +101,7 @@ public:
protected:
// device-level overrides
- virtual void device_start() override;
+ virtual void device_start() override ATTR_COLD;
// configuration
required_device<hp_hil_mlc_device> m_mlc;
@@ -111,9 +112,7 @@ protected:
DECLARE_DEVICE_TYPE(HP_HIL_SLOT, hp_hil_slot_device)
-class device_hp_hil_interface;
-
-class hp_hil_mlc_device : public device_t
+class hp_hil_mlc_device : public device_t
{
public:
// construction/destruction
@@ -126,16 +125,16 @@ public:
void add_hp_hil_device(device_hp_hil_interface *device);
bool get_int(void) { return m_r3 & 1; }
- DECLARE_READ8_MEMBER(read);
- DECLARE_WRITE8_MEMBER(write);
- DECLARE_WRITE_LINE_MEMBER(ap_w);
+ uint8_t read(offs_t offset);
+ void write(offs_t offset, uint8_t data);
+ void ap_w(int state);
void hil_write(uint16_t data);
protected:
// device-level overrides
- virtual void device_start() override;
- virtual void device_reset() override;
+ virtual void device_start() override ATTR_COLD;
+ virtual void device_reset() override ATTR_COLD;
simple_list<device_hp_hil_interface> m_device_list;
@@ -153,7 +152,7 @@ DECLARE_DEVICE_TYPE(HP_HIL_MLC, hp_hil_mlc_device)
// ======================> device_hp_hil_interface
-class device_hp_hil_interface : public device_slot_card_interface
+class device_hp_hil_interface : public device_interface
{
friend class hp_hil_mlc_device;
template <class ElementType> friend class simple_list;
@@ -169,8 +168,8 @@ public:
// inline configuration
void set_hp_hil_mlc(hp_hil_mlc_device &mlc_device) { m_hp_hil_mlc = &mlc_device; }
- virtual bool hil_write(uint16_t *data) { return true; };
- int device_id() { return m_device_id; };
+ virtual bool hil_write(uint16_t *data) { return true; }
+ int device_id() { return m_device_id; }
protected:
device_hp_hil_interface(const machine_config &mconfig, device_t &device);
diff --git a/src/devices/bus/hp_ipc_io/82919.cpp b/src/devices/bus/hp_ipc_io/82919.cpp
new file mode 100644
index 00000000000..901350f5bdd
--- /dev/null
+++ b/src/devices/bus/hp_ipc_io/82919.cpp
@@ -0,0 +1,251 @@
+// license:BSD-3-Clause
+// copyright-holders: F. Ulivi
+/*********************************************************************
+
+ 82919.cpp
+
+ 82919 module (RS232 interface)
+
+ Main reference for this module is:
+ HP 82919-90009, feb 85, HP82919A Integral PC Serial Interface -
+ Component level service manual
+
+*********************************************************************/
+
+#include "emu.h"
+#include "82919.h"
+
+// Debugging
+#define VERBOSE 0
+#include "logmacro.h"
+
+// Bit manipulation
+namespace {
+ template<typename T> constexpr T BIT_MASK(unsigned n)
+ {
+ return (T)1U << n;
+ }
+
+ template<typename T> void BIT_SET(T& w , unsigned n)
+ {
+ w |= BIT_MASK<T>(n);
+ }
+}
+
+hp82919_io_card_device::hp82919_io_card_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
+ : device_t(mconfig , HP82919_IO_CARD , tag , owner , clock)
+ , device_hp_ipc_io_interface(mconfig, *this)
+ , m_rs232_prim(*this , "rs232_prim")
+ , m_rs232_sec(*this , "rs232_sec")
+ , m_uart(*this , "uart")
+ , m_loopback_en(*this, "loop")
+{
+}
+
+hp82919_io_card_device::~hp82919_io_card_device()
+{
+}
+
+uint8_t hp82919_io_card_device::read(offs_t addr)
+{
+ uint8_t res = 0;
+ offs_t uart_addr = (addr ^ 0xc) & 0xf;
+
+ if (BIT(addr , 4)) {
+ res = m_uart->read(uart_addr);
+ } else {
+ // 2 is 82919 ID code
+ res = 2;
+ res |= (m_int_level << 4);
+ if (m_int_pending) {
+ BIT_SET(res , 6);
+ }
+ if (m_int_en) {
+ BIT_SET(res , 7);
+ }
+ m_uart->write(uart_addr , res);
+ }
+ LOG("RD %04x=%02x\n" , addr , res);
+ return res;
+}
+
+void hp82919_io_card_device::write(offs_t addr , uint8_t data)
+{
+ LOG("WR %04x=%02x\n" , addr , data);
+ offs_t uart_addr = (addr ^ 0xc) & 0xf;
+ m_uart->write(uart_addr , data);
+ if (!BIT(addr , 4)) {
+ m_int_level = (data >> 4) & 3;
+ m_int_forced = BIT(data , 6);
+ m_int_en = BIT(data , 7);
+ update_irq();
+ }
+}
+
+void hp82919_io_card_device::uart_irq(int state)
+{
+ m_uart_int = state;
+ update_irq();
+}
+
+void hp82919_io_card_device::uart_a_tx(int state)
+{
+ m_rs232_prim->write_txd(state);
+ if (m_loopback) {
+ m_uart->rx_b_w(state);
+ }
+}
+
+void hp82919_io_card_device::uart_b_tx(int state)
+{
+ m_rs232_sec->write_txd(state);
+ if (m_loopback) {
+ m_uart->rx_a_w(state);
+ }
+}
+
+void hp82919_io_card_device::uart_output(uint8_t data)
+{
+ m_rs232_prim->write_dtr(BIT(data , 0));
+ m_rs232_prim->write_rts(BIT(data , 1));
+ // b2 is TxClock
+ m_rs232_prim->write_spds(BIT(data , 3));
+ m_rs232_sec->write_rts(BIT(data , 4));
+ if (m_loopback) {
+ m_uart->ip0_w(BIT(data , 0));
+ m_uart->ip1_w(BIT(data , 1));
+ m_uart->ip2_w(BIT(data , 2));
+ m_uart->ip3_w(BIT(data , 3));
+ m_uart->ip4_w(BIT(data , 4));
+ m_uart->ip5_w(BIT(data , 4));
+ }
+}
+
+void hp82919_io_card_device::prim_rxd(int state)
+{
+ if (!m_loopback) {
+ m_uart->rx_a_w(state);
+ }
+}
+
+void hp82919_io_card_device::prim_dcd(int state)
+{
+ if (!m_loopback) {
+ m_uart->ip3_w(state);
+ }
+}
+
+void hp82919_io_card_device::prim_dsr(int state)
+{
+ if (!m_loopback) {
+ m_uart->ip1_w(state);
+ }
+}
+
+void hp82919_io_card_device::prim_ri(int state)
+{
+ if (!m_loopback) {
+ m_uart->ip2_w(state);
+ }
+}
+
+void hp82919_io_card_device::prim_cts(int state)
+{
+ if (!m_loopback) {
+ m_uart->ip0_w(state);
+ }
+}
+
+void hp82919_io_card_device::sec_rxd(int state)
+{
+ if (!m_loopback) {
+ m_uart->rx_b_w(state);
+ }
+}
+
+void hp82919_io_card_device::sec_dcd(int state)
+{
+ if (!m_loopback) {
+ m_uart->ip5_w(state);
+ }
+}
+
+void hp82919_io_card_device::sec_cts(int state)
+{
+ if (!m_loopback) {
+ m_uart->ip4_w(state);
+ }
+}
+
+void hp82919_io_card_device::install_read_write_handlers(address_space& space , uint32_t base_addr)
+{
+ offs_t end_addr = base_addr + 0xffffU;
+
+ // Supervisor mode
+ space.install_readwrite_handler(base_addr, end_addr, read8sm_delegate(*this, FUNC(hp82919_io_card_device::read)), write8sm_delegate(*this, FUNC(hp82919_io_card_device::write)), 0x00ff);
+ // User mode
+ space.install_readwrite_handler(base_addr + USER_SPACE_OFFSET, end_addr + USER_SPACE_OFFSET, read8sm_delegate(*this, FUNC(hp82919_io_card_device::read)), write8sm_delegate(*this, FUNC(hp82919_io_card_device::write)), 0x00ff);
+}
+
+void hp82919_io_card_device::device_start()
+{
+}
+
+void hp82919_io_card_device::device_reset()
+{
+ m_loopback = m_loopback_en->read() != 0;
+ m_int_level = 0;
+ m_int_forced = false;
+ m_int_en = false;
+ m_uart_int = false;
+ m_irq = true;
+ update_irq();
+}
+
+void hp82919_io_card_device::device_add_mconfig(machine_config &config)
+{
+ RS232_PORT(config, m_rs232_prim, default_rs232_devices, nullptr);
+ RS232_PORT(config, m_rs232_sec, default_rs232_devices, nullptr);
+
+ MC68681(config , m_uart , 3.6864_MHz_XTAL);
+ m_uart->irq_cb().set(FUNC(hp82919_io_card_device::uart_irq));
+ m_uart->a_tx_cb().set(FUNC(hp82919_io_card_device::uart_a_tx));
+ m_uart->b_tx_cb().set(FUNC(hp82919_io_card_device::uart_b_tx));
+ m_uart->outport_cb().set(FUNC(hp82919_io_card_device::uart_output));
+
+ m_rs232_prim->rxd_handler().set(FUNC(hp82919_io_card_device::prim_rxd));
+ m_rs232_prim->dcd_handler().set(FUNC(hp82919_io_card_device::prim_dcd));
+ m_rs232_prim->dsr_handler().set(FUNC(hp82919_io_card_device::prim_dsr));
+ m_rs232_prim->ri_handler().set(FUNC(hp82919_io_card_device::prim_ri));
+ m_rs232_prim->cts_handler().set(FUNC(hp82919_io_card_device::prim_cts));
+
+ m_rs232_sec->rxd_handler().set(FUNC(hp82919_io_card_device::sec_rxd));
+ m_rs232_sec->dcd_handler().set(FUNC(hp82919_io_card_device::sec_dcd));
+ m_rs232_sec->cts_handler().set(FUNC(hp82919_io_card_device::sec_cts));
+}
+
+static INPUT_PORTS_START(hp82919_port)
+ PORT_START("loop")
+ PORT_CONFNAME(1 , 0 , "Test loopback")
+ PORT_CONFSETTING(0 , DEF_STR(Off))
+ PORT_CONFSETTING(1 , DEF_STR(On))
+INPUT_PORTS_END
+
+ioport_constructor hp82919_io_card_device::device_input_ports() const
+{
+ return INPUT_PORTS_NAME(hp82919_port);
+}
+
+void hp82919_io_card_device::update_irq()
+{
+ m_int_pending = m_int_forced || m_uart_int;
+ bool irq = m_int_en && m_int_pending;
+ if (m_irq != irq) {
+ m_irq = irq;
+ LOG("IRQ %u=%d\n" , m_int_level , irq);
+ irq_w(m_int_level , irq);
+ }
+}
+
+// device type definition
+DEFINE_DEVICE_TYPE(HP82919_IO_CARD, hp82919_io_card_device, "hp82919", "HP82919 card")
diff --git a/src/devices/bus/hp_ipc_io/82919.h b/src/devices/bus/hp_ipc_io/82919.h
new file mode 100644
index 00000000000..ab8b04c254f
--- /dev/null
+++ b/src/devices/bus/hp_ipc_io/82919.h
@@ -0,0 +1,73 @@
+// license:BSD-3-Clause
+// copyright-holders: F. Ulivi
+/*********************************************************************
+
+ 82919.h
+
+ 82919 module (RS232 interface)
+
+*********************************************************************/
+
+#ifndef MAME_BUS_HP_IPC_IO_82919_H
+#define MAME_BUS_HP_IPC_IO_82919_H
+
+#pragma once
+
+#include "hp_ipc_io.h"
+#include "machine/mc68681.h"
+#include "bus/rs232/rs232.h"
+
+class hp82919_io_card_device : public device_t, public device_hp_ipc_io_interface
+{
+public:
+ // construction/destruction
+ hp82919_io_card_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
+ virtual ~hp82919_io_card_device();
+
+ uint8_t read(offs_t addr);
+ void write(offs_t addr , uint8_t data);
+
+ void uart_irq(int state);
+ void uart_a_tx(int state);
+ void uart_b_tx(int state);
+ void uart_output(uint8_t data);
+ 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 ATTR_COLD;
+ virtual void device_reset() override ATTR_COLD;
+
+ // device-level overrides
+ virtual void device_add_mconfig(machine_config &config) override ATTR_COLD;
+ virtual ioport_constructor device_input_ports() const override ATTR_COLD;
+
+ virtual void install_read_write_handlers(address_space& space , uint32_t base_addr) override;
+
+private:
+ required_device<rs232_port_device> m_rs232_prim;
+ required_device<rs232_port_device> m_rs232_sec;
+ required_device<mc68681_device> m_uart;
+ required_ioport m_loopback_en;
+
+ uint8_t m_int_level;
+ bool m_int_en;
+ bool m_int_forced;
+ bool m_int_pending;
+ bool m_uart_int;
+ bool m_irq;
+ bool m_loopback;
+
+ void update_irq();
+};
+
+// device type definition
+DECLARE_DEVICE_TYPE(HP82919_IO_CARD, hp82919_io_card_device)
+
+#endif // MAME_BUS_HP_IPC_IO_82919_H
diff --git a/src/devices/bus/hp_ipc_io/hp_ipc_io.cpp b/src/devices/bus/hp_ipc_io/hp_ipc_io.cpp
new file mode 100644
index 00000000000..94b51b2f178
--- /dev/null
+++ b/src/devices/bus/hp_ipc_io/hp_ipc_io.cpp
@@ -0,0 +1,85 @@
+// license:BSD-3-Clause
+// copyright-holders: F. Ulivi
+/*********************************************************************
+
+ hp_ipc_io.cpp
+
+ I/O bus of HP IPC system
+
+*********************************************************************/
+
+#include "emu.h"
+#include "hp_ipc_io.h"
+
+// Debugging
+#define VERBOSE 0
+#include "logmacro.h"
+
+// device type definition
+DEFINE_DEVICE_TYPE(HP_IPC_IO_SLOT, hp_ipc_io_slot_device, "hp_ipc_io_slot", "HP IPC I/O Slot")
+
+// +---------------------+
+// |hp_ipc_io_slot_device|
+// +---------------------+
+hp_ipc_io_slot_device::hp_ipc_io_slot_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) :
+ device_t(mconfig, HP_IPC_IO_SLOT, tag, owner, clock),
+ device_single_card_slot_interface<device_hp_ipc_io_interface>(mconfig, *this),
+ m_irq_cb_func(*this),
+ m_slot_idx(0)
+{
+}
+
+hp_ipc_io_slot_device::~hp_ipc_io_slot_device()
+{
+}
+
+void hp_ipc_io_slot_device::device_start()
+{
+}
+
+uint32_t hp_ipc_io_slot_device::get_slot_base_addr() const
+{
+ return m_slot_idx ? 0x710000 : 0x700000;
+}
+
+void hp_ipc_io_slot_device::install_read_write_handlers(address_space& space)
+{
+ device_hp_ipc_io_interface *card = get_card_device();
+
+ if (card != nullptr) {
+ card->install_read_write_handlers(space , get_slot_base_addr());
+ }
+}
+
+void hp_ipc_io_slot_device::irq_w(unsigned idx , bool state)
+{
+ m_irq_cb_func[ 0 ](state && idx == 0);
+ m_irq_cb_func[ 1 ](state && idx == 1);
+ m_irq_cb_func[ 2 ](state && idx == 2);
+ m_irq_cb_func[ 3 ](state && idx == 3);
+}
+
+// +--------------------------+
+// |device_hp_ipc_io_interface|
+// +--------------------------+
+device_hp_ipc_io_interface::device_hp_ipc_io_interface(const machine_config &mconfig, device_t &device) :
+ device_interface(device, "hp_ipcio")
+{
+}
+
+device_hp_ipc_io_interface::~device_hp_ipc_io_interface()
+{
+}
+
+void device_hp_ipc_io_interface::irq_w(unsigned idx , bool state)
+{
+ hp_ipc_io_slot_device *slot = downcast<hp_ipc_io_slot_device *>(device().owner());
+ slot->irq_w(idx , state);
+}
+
+#include "82919.h"
+
+void hp_ipc_io_slot_devices(device_slot_interface &device)
+{
+ device.option_add("82919_serial" , HP82919_IO_CARD);
+}
diff --git a/src/devices/bus/hp_ipc_io/hp_ipc_io.h b/src/devices/bus/hp_ipc_io/hp_ipc_io.h
new file mode 100644
index 00000000000..079242c9554
--- /dev/null
+++ b/src/devices/bus/hp_ipc_io/hp_ipc_io.h
@@ -0,0 +1,82 @@
+// license:BSD-3-Clause
+// copyright-holders: F. Ulivi
+/*********************************************************************
+
+ hp_ipc_io.h
+
+ I/O bus of HP IPC system
+
+*********************************************************************/
+
+#ifndef MAME_BUS_HP_IPC_IO_HP_IPC_IO_H
+#define MAME_BUS_HP_IPC_IO_HP_IPC_IO_H
+
+#pragma once
+
+void hp_ipc_io_slot_devices(device_slot_interface &device);
+
+class device_hp_ipc_io_interface;
+
+class hp_ipc_io_slot_device : public device_t,
+ public device_single_card_slot_interface<device_hp_ipc_io_interface>
+{
+public:
+ // construction/destruction
+ hp_ipc_io_slot_device(machine_config const &mconfig, char const *tag, device_t *owner)
+ : hp_ipc_io_slot_device(mconfig, tag, owner, (uint32_t)0)
+ {
+ option_reset();
+ hp_ipc_io_slot_devices(*this);
+ set_default_option(nullptr);
+ set_fixed(false);
+ }
+
+ hp_ipc_io_slot_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
+ virtual ~hp_ipc_io_slot_device();
+
+ // Set A/B slot
+ void set_slot_idx(unsigned idx) { m_slot_idx = idx; }
+
+ // Callback setups
+ auto irq3_cb() { return m_irq_cb_func[ 0 ].bind(); }
+ auto irq4_cb() { return m_irq_cb_func[ 1 ].bind(); }
+ auto irq5_cb() { return m_irq_cb_func[ 2 ].bind(); }
+ auto irq6_cb() { return m_irq_cb_func[ 3 ].bind(); }
+
+ uint32_t get_slot_base_addr() const;
+
+ void install_read_write_handlers(address_space& space);
+
+ void irq_w(unsigned idx , bool state);
+
+protected:
+ // device-level overrides
+ virtual void device_start() override ATTR_COLD;
+
+private:
+ devcb_write_line::array<4> m_irq_cb_func;
+ // 0: slot A
+ // 1: slot B
+ unsigned m_slot_idx;
+};
+
+class device_hp_ipc_io_interface : public device_interface
+{
+public:
+ virtual ~device_hp_ipc_io_interface();
+
+ virtual void install_read_write_handlers(address_space& space , uint32_t base_addr) = 0;
+
+ static constexpr offs_t USER_SPACE_OFFSET = 0x1800000;
+
+protected:
+ device_hp_ipc_io_interface(const machine_config &mconfig, device_t &device);
+
+ // card device handling
+ void irq_w(unsigned idx , bool state);
+};
+
+// device type definition
+DECLARE_DEVICE_TYPE(HP_IPC_IO_SLOT, hp_ipc_io_slot_device)
+
+#endif // MAME_BUS_HP_IPC_IO_HP_IPC_IO_H
diff --git a/src/devices/bus/hp_optroms/hp_optrom.cpp b/src/devices/bus/hp_optroms/hp_optrom.cpp
deleted file mode 100644
index fc54a168c83..00000000000
--- a/src/devices/bus/hp_optroms/hp_optrom.cpp
+++ /dev/null
@@ -1,131 +0,0 @@
-// license:BSD-3-Clause
-// copyright-holders: F. Ulivi
-/*********************************************************************
-
- hp_optrom.cpp
-
- Optional ROMs for HP9845 systems
-
-*********************************************************************/
-
-#include "emu.h"
-#include "hp_optrom.h"
-#include "softlist.h"
-#include "cpu/hphybrid/hphybrid.h"
-
-DEFINE_DEVICE_TYPE(HP_OPTROM_CART, hp_optrom_cart_device, "hp_optrom_cart", "HP9845 optional ROM cartridge")
-DEFINE_DEVICE_TYPE(HP_OPTROM_SLOT, hp_optrom_slot_device, "hp_optrom_slot", "HP9845 optional ROM slot")
-
-// +---------------------+
-// |hp_optrom_cart_device|
-// +---------------------+
-hp_optrom_cart_device::hp_optrom_cart_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_card_interface(mconfig, *this)
-{
-}
-
-hp_optrom_cart_device::hp_optrom_cart_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) :
- hp_optrom_cart_device(mconfig, HP_OPTROM_CART, tag, owner, clock)
-{
-}
-
-// +---------------------+
-// |hp_optrom_slot_device|
-// +---------------------+
-hp_optrom_slot_device::hp_optrom_slot_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) :
- device_t(mconfig, HP_OPTROM_SLOT, tag, owner, clock),
- device_image_interface(mconfig, *this),
- device_slot_interface(mconfig, *this),
- m_cart(nullptr),
- m_base_addr(0),
- m_end_addr(0)
-{
- option_reset();
- option_add_internal("rom", HP_OPTROM_CART);
- set_default_option(nullptr);
- set_fixed(false);
-}
-
-hp_optrom_slot_device::~hp_optrom_slot_device()
-{
-}
-
-void hp_optrom_slot_device::device_start()
-{
- m_cart = dynamic_cast<hp_optrom_cart_device *>(get_card_device());
-}
-
-image_init_result hp_optrom_slot_device::call_load()
-{
- logerror("hp_optrom: call_load\n");
- if (m_cart == nullptr || !loaded_through_softlist()) {
- logerror("hp_optrom: must be loaded from sw list\n");
- return image_init_result::FAIL;
- }
-
- const char *base_feature = get_feature("base");
- if (base_feature == nullptr) {
- logerror("hp_optrom: no 'base' feature\n");
- return image_init_result::FAIL;
- }
-
- offs_t base_addr;
- if (base_feature[ 0 ] != '0' || base_feature[ 1 ] != 'x' || sscanf(&base_feature[ 2 ] , "%x" , &base_addr) != 1) {
- logerror("hp_optrom: can't parse 'base' feature\n");
- return image_init_result::FAIL;
- }
-
- // Valid BSC values for ROMs on LPU drawer: 0x07 0x0b .... 0x3b
- // Valid BSC values for ROMs on PPU drawer: 0x09 0x0d .... 0x3d
- // (BSC is field in bits 16..21 of base address)
- // Bit 15 of base address must be 0
- // Base address must be multiple of 0x1000
- if ((base_addr & ~0x3f7000UL) != 0 || ((base_addr & 0x30000) != 0x10000 && (base_addr & 0x30000) != 0x30000) || base_addr < 0x70000) {
- logerror("hp_optrom: illegal base address (%x)\n" , base_addr);
- return image_init_result::FAIL;
- }
-
- auto length = get_software_region_length("rom") / 2;
-
- if (length < 0x1000 || length > 0x8000 || (length & 0xfff) != 0 || ((base_addr & 0x7000) + length) > 0x8000) {
- logerror("hp_optrom: illegal region length (%x)\n" , length);
- return image_init_result::FAIL;
- }
-
- offs_t end_addr = base_addr + length - 1;
- logerror("hp_optrom: base_addr = %06x end_addr = %06x\n" , base_addr , end_addr);
-
- m_content.resize(length * 2);
- uint8_t *buffer = m_content.data();
- memcpy(buffer , get_software_region("rom") , length * 2);
-
- // Install ROM in address space of every CPU
- for (hp_hybrid_cpu_device& cpu : device_interface_iterator<hp_hybrid_cpu_device>(machine().root_device())) {
- logerror("hp_optrom: install in %s AS\n" , cpu.tag());
- cpu.space(AS_PROGRAM).install_rom(base_addr , end_addr , buffer);
- }
-
- m_base_addr = base_addr;
- m_end_addr = end_addr;
-
- return image_init_result::PASS;
-}
-
-void hp_optrom_slot_device::call_unload()
-{
- logerror("hp_optrom: call_unload\n");
- if (m_cart != nullptr && m_base_addr != 0 && m_end_addr != 0) {
- for (hp_hybrid_cpu_device& cpu : device_interface_iterator<hp_hybrid_cpu_device>(machine().root_device())) {
- cpu.space(AS_PROGRAM).unmap_read(m_base_addr , m_end_addr);
- }
- m_content.resize(0);
- m_base_addr = 0;
- m_end_addr = 0;
- }
-}
-
-std::string hp_optrom_slot_device::get_default_card_software(get_default_card_software_hook &hook) const
-{
- return software_get_default_slot("rom");
-}
diff --git a/src/devices/bus/hp_optroms/hp_optrom.h b/src/devices/bus/hp_optroms/hp_optrom.h
deleted file mode 100644
index 9b507ba64eb..00000000000
--- a/src/devices/bus/hp_optroms/hp_optrom.h
+++ /dev/null
@@ -1,73 +0,0 @@
-// license:BSD-3-Clause
-// copyright-holders: F. Ulivi
-/*********************************************************************
-
- hp_optrom.h
-
- Optional ROMs for HP9845 systems
-
-*********************************************************************/
-
-#ifndef MAME_BUS_HP_OPTROMS_HP_OPTROM_H
-#define MAME_BUS_HP_OPTROMS_HP_OPTROM_H
-
-#pragma once
-
-#include "softlist_dev.h"
-
-
-class hp_optrom_cart_device : public device_t,
- public device_slot_card_interface
-{
-public:
- // construction/destruction
- hp_optrom_cart_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
-
-protected:
- hp_optrom_cart_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 { }
-};
-
-class hp_optrom_slot_device : public device_t,
- public device_image_interface,
- public device_slot_interface
-{
-public:
- // construction/destruction
- hp_optrom_slot_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
- virtual ~hp_optrom_slot_device();
-
-protected:
- // device-level overrides
- virtual void device_start() override;
-
- // image-level overrides
- virtual image_init_result call_load() override;
- virtual void call_unload() override;
- virtual const software_list_loader &get_software_list_loader() const override { return rom_software_list_loader::instance(); }
-
- virtual iodevice_t image_type() const override { return IO_ROM; }
- virtual bool is_readable() const override { return true; }
- virtual bool is_writeable() const override { return false; }
- virtual bool is_creatable() const override { return false; }
- virtual bool must_be_loaded() const override { return false; }
- virtual bool is_reset_on_load() const override { return true; }
- virtual const char *image_interface() const override { return "hp9845b_rom"; }
- virtual const char *file_extensions() const override { return "bin"; }
-
- // slot interface overrides
- virtual std::string get_default_card_software(get_default_card_software_hook &hook) const override;
-
- hp_optrom_cart_device *m_cart;
- std::vector<uint8_t> m_content;
- offs_t m_base_addr;
- offs_t m_end_addr;
-};
-
-// device type definition
-DECLARE_DEVICE_TYPE(HP_OPTROM_SLOT, hp_optrom_slot_device)
-DECLARE_DEVICE_TYPE(HP_OPTROM_CART, hp_optrom_cart_device)
-
-#endif // MAME_BUS_HP_OPTROMS_HP_OPTROM_H
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..fd27bf5472f
--- /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 ATTR_COLD;
+ virtual void device_start() override ATTR_COLD;
+
+ // 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 ATTR_COLD;
+ virtual void device_reset() override ATTR_COLD;
+
+ // 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..bb0d3cfb015
--- /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 ATTR_COLD;
+ virtual void device_reset() override ATTR_COLD;
+ virtual void device_add_mconfig(machine_config &config) override ATTR_COLD;
+ virtual const tiny_rom_entry *device_rom_region() const override ATTR_COLD;
+
+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) ATTR_COLD;
+ 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) ATTR_COLD;
+ void attr_map(address_map &map) ATTR_COLD;
+
+ 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..c9376368f82
--- /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 ATTR_COLD;
+ virtual void device_reset() override ATTR_COLD;
+ virtual void device_add_mconfig(machine_config &config) override ATTR_COLD;
+
+ 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 fe488bde1f4..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,14 +72,14 @@ 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;
m_maincpu->set_input_line(INPUT_LINE_IRQ0, (m_via0_irq || m_via1_irq) ? ASSERT_LINE : CLEAR_LINE);
}
-READ8_MEMBER( c2031_device::via0_pa_r )
+uint8_t c2031_device::via0_pa_r()
{
/*
@@ -94,10 +96,10 @@ READ8_MEMBER( c2031_device::via0_pa_r )
*/
- return m_bus->read_dio();
+ return m_bus->dio_r();
}
-WRITE8_MEMBER( c2031_device::via0_pa_w )
+void c2031_device::via0_pa_w(uint8_t data)
{
/*
@@ -117,7 +119,7 @@ WRITE8_MEMBER( c2031_device::via0_pa_w )
m_bus->dio_w(this, data);
}
-READ8_MEMBER( c2031_device::via0_pb_r )
+uint8_t c2031_device::via0_pb_r()
{
/*
@@ -154,7 +156,7 @@ READ8_MEMBER( c2031_device::via0_pb_r )
return data;
}
-WRITE8_MEMBER( c2031_device::via0_pb_w )
+void c2031_device::via0_pb_w(uint8_t data)
{
/*
@@ -202,14 +204,14 @@ WRITE8_MEMBER( c2031_device::via0_pb_w )
}
-WRITE_LINE_MEMBER( c2031_device::via1_irq_w )
+void c2031_device::via1_irq_w(int state)
{
m_via1_irq = state;
m_maincpu->set_input_line(INPUT_LINE_IRQ0, (m_via0_irq || m_via1_irq) ? ASSERT_LINE : CLEAR_LINE);
}
-READ8_MEMBER( c2031_device::via1_pb_r )
+uint8_t c2031_device::via1_pb_r()
{
/*
@@ -237,7 +239,7 @@ READ8_MEMBER( c2031_device::via1_pb_r )
return data;
}
-WRITE8_MEMBER( c2031_device::via1_pb_w )
+void c2031_device::via1_pb_w(uint8_t data)
{
/*
@@ -272,7 +274,7 @@ WRITE8_MEMBER( c2031_device::via1_pb_w )
// 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);
@@ -284,10 +286,11 @@ WRITE_LINE_MEMBER( c2031_device::byte_w )
// FLOPPY_FORMATS( floppy_formats )
//-------------------------------------------------
-FLOPPY_FORMATS_MEMBER( c2031_device::floppy_formats )
- FLOPPY_D64_FORMAT,
- FLOPPY_G64_FORMAT
-FLOPPY_FORMATS_END
+void c2031_device::floppy_formats(format_registration &fr)
+{
+ fr.add(FLOPPY_D64_FORMAT);
+ fr.add(FLOPPY_G64_FORMAT);
+}
//-------------------------------------------------
@@ -298,16 +301,15 @@ 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.m_perfect_cpu_quantum = subtag(M6502_TAG);
- VIA6522(config, m_via0, XTAL(16'000'000)/16);
+ MOS6522(config, m_via0, XTAL(16'000'000)/16);
m_via0->readpa_handler().set(FUNC(c2031_device::via0_pa_r));
m_via0->readpb_handler().set(FUNC(c2031_device::via0_pb_r));
m_via0->writepa_handler().set(FUNC(c2031_device::via0_pa_w));
m_via0->writepb_handler().set(FUNC(c2031_device::via0_pb_w));
m_via0->irq_handler().set(FUNC(c2031_device::via0_irq_w));
- VIA6522(config, m_via1, XTAL(16'000'000)/16);
+ MOS6522(config, m_via1, XTAL(16'000'000)/16);
m_via1->readpa_handler().set(C64H156_TAG, FUNC(c64h156_device::yb_r));
m_via1->readpb_handler().set(FUNC(c2031_device::via1_pb_r));
m_via1->writepa_handler().set(C64H156_TAG, FUNC(c64h156_device::yb_w));
diff --git a/src/devices/bus/ieee488/c2031.h b/src/devices/bus/ieee488/c2031.h
index 7c6b9d738cc..f35b1eb1bc4 100644
--- a/src/devices/bus/ieee488/c2031.h
+++ b/src/devices/bus/ieee488/c2031.h
@@ -34,13 +34,13 @@ public:
protected:
// device-level overrides
- virtual void device_start() override;
- virtual void device_reset() override;
+ virtual void device_start() override ATTR_COLD;
+ virtual void device_reset() override ATTR_COLD;
// optional information 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 const tiny_rom_entry *device_rom_region() const override ATTR_COLD;
+ virtual void device_add_mconfig(machine_config &config) override ATTR_COLD;
+ virtual ioport_constructor device_input_ports() const override ATTR_COLD;
// device_ieee488_interface overrides
virtual void ieee488_atn(int state) override;
@@ -49,19 +49,19 @@ protected:
private:
inline int get_device_number();
- DECLARE_WRITE_LINE_MEMBER( via0_irq_w );
- DECLARE_READ8_MEMBER( via0_pa_r );
- DECLARE_WRITE8_MEMBER( via0_pa_w );
- DECLARE_READ8_MEMBER( via0_pb_r );
- DECLARE_WRITE8_MEMBER( via0_pb_w );
- DECLARE_WRITE_LINE_MEMBER( via1_irq_w );
- DECLARE_READ8_MEMBER( via1_pb_r );
- DECLARE_WRITE8_MEMBER( via1_pb_w );
- DECLARE_WRITE_LINE_MEMBER( byte_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);
+ void via1_irq_w(int state);
+ uint8_t via1_pb_r();
+ void via1_pb_w(uint8_t data);
+ void byte_w(int state);
- void c2031_mem(address_map &map);
+ void c2031_mem(address_map &map) ATTR_COLD;
- DECLARE_FLOPPY_FORMATS( floppy_formats );
+ static void floppy_formats(format_registration &fr);
required_device<m6502_device> m_maincpu;
required_device<via6522_device> m_via0;
diff --git a/src/devices/bus/ieee488/c2040.cpp b/src/devices/bus/ieee488/c2040.cpp
index 53a2f9f95e8..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");
@@ -205,7 +210,7 @@ void c2040_device::c2040_fdc_mem(address_map &map)
// riot6532 uc1
//-------------------------------------------------
-READ8_MEMBER( c2040_device::dio_r )
+uint8_t c2040_device::dio_r()
{
/*
@@ -222,10 +227,10 @@ READ8_MEMBER( c2040_device::dio_r )
*/
- return m_bus->read_dio();
+ return m_bus->dio_r();
}
-WRITE8_MEMBER( c2040_device::dio_w )
+void c2040_device::dio_w(uint8_t data)
{
/*
@@ -250,7 +255,7 @@ WRITE8_MEMBER( c2040_device::dio_w )
// riot6532 ue1
//-------------------------------------------------
-READ8_MEMBER( c2040_device::riot1_pa_r )
+uint8_t c2040_device::riot1_pa_r()
{
/*
@@ -281,7 +286,7 @@ READ8_MEMBER( c2040_device::riot1_pa_r )
return data;
}
-WRITE8_MEMBER( c2040_device::riot1_pa_w )
+void c2040_device::riot1_pa_w(uint8_t data)
{
/*
@@ -316,7 +321,7 @@ WRITE8_MEMBER( c2040_device::riot1_pa_w )
update_ieee_signals();
}
-READ8_MEMBER( c2040_device::riot1_pb_r )
+uint8_t c2040_device::riot1_pb_r()
{
/*
@@ -347,7 +352,7 @@ READ8_MEMBER( c2040_device::riot1_pb_r )
return data;
}
-WRITE8_MEMBER( c2040_device::riot1_pb_w )
+void c2040_device::riot1_pb_w(uint8_t data)
{
/*
@@ -375,7 +380,7 @@ WRITE8_MEMBER( c2040_device::riot1_pb_w )
}
-WRITE8_MEMBER( c2040_device::via_pb_w )
+void c2040_device::via_pb_w(uint8_t data)
{
/*
@@ -420,30 +425,33 @@ static void c2040_floppies(device_slot_interface &device)
// FLOPPY_FORMATS( floppy_formats )
//-------------------------------------------------
-FLOPPY_FORMATS_MEMBER( c2040_device::floppy_formats )
- FLOPPY_C3040_FORMAT,
- FLOPPY_G64_FORMAT
-FLOPPY_FORMATS_END
+void c2040_device::floppy_formats(format_registration &fr)
+{
+ fr.add(FLOPPY_C3040_FORMAT);
+ fr.add(FLOPPY_G64_FORMAT);
+}
//-------------------------------------------------
// FLOPPY_FORMATS( floppy_formats )
//-------------------------------------------------
-FLOPPY_FORMATS_MEMBER( c3040_device::floppy_formats )
- FLOPPY_C3040_FORMAT,
- FLOPPY_G64_FORMAT
-FLOPPY_FORMATS_END
+void c3040_device::floppy_formats(format_registration &fr)
+{
+ fr.add(FLOPPY_C3040_FORMAT);
+ fr.add(FLOPPY_G64_FORMAT);
+}
//-------------------------------------------------
// FLOPPY_FORMATS( floppy_formats )
//-------------------------------------------------
-FLOPPY_FORMATS_MEMBER( c4040_device::floppy_formats )
- FLOPPY_C4040_FORMAT,
- FLOPPY_G64_FORMAT
-FLOPPY_FORMATS_END
+void c4040_device::floppy_formats(format_registration &fr)
+{
+ fr.add(FLOPPY_C4040_FORMAT);
+ fr.add(FLOPPY_G64_FORMAT);
+}
//-------------------------------------------------
@@ -456,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));
@@ -471,22 +479,22 @@ void c2040_device::add_common_devices(machine_config &config)
M6504(config, m_fdccpu, XTAL(16'000'000)/16);
m_fdccpu->set_addrmap(AS_PROGRAM, &c2040_device::c2040_fdc_mem);
- VIA6522(config, m_via, XTAL(16'000'000)/16);
+ MOS6522(config, m_via, XTAL(16'000'000)/16);
m_via->readpa_handler().set(m_fdc, FUNC(c2040_fdc_device::read));
m_via->writepb_handler().set(FUNC(c2040_device::via_pb_w));
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));
}
@@ -655,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);
@@ -671,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 1b7c1c69618..e86011b3581 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"
@@ -32,27 +32,27 @@ public:
// construction/destruction
c2040_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
- DECLARE_READ8_MEMBER( dio_r );
- DECLARE_WRITE8_MEMBER( dio_w );
- DECLARE_READ8_MEMBER( riot1_pa_r );
- DECLARE_WRITE8_MEMBER( riot1_pa_w );
- DECLARE_READ8_MEMBER( riot1_pb_r );
- DECLARE_WRITE8_MEMBER( riot1_pb_w );
- DECLARE_WRITE8_MEMBER( via_pb_w );
+ uint8_t dio_r();
+ void dio_w(uint8_t data);
+ uint8_t riot1_pa_r();
+ void riot1_pa_w(uint8_t data);
+ uint8_t riot1_pb_r();
+ void riot1_pb_w(uint8_t data);
+ void via_pb_w(uint8_t data);
- void c2040_fdc_mem(address_map &map);
- void c2040_main_mem(address_map &map);
+ void c2040_fdc_mem(address_map &map) ATTR_COLD;
+ void c2040_main_mem(address_map &map) ATTR_COLD;
protected:
c2040_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_start() override ATTR_COLD;
+ virtual void device_reset() override ATTR_COLD;
// optional information 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 const tiny_rom_entry *device_rom_region() const override ATTR_COLD;
+ virtual void device_add_mconfig(machine_config &config) override ATTR_COLD;
+ virtual ioport_constructor device_input_ports() const override ATTR_COLD;
// device_ieee488_interface overrides
virtual void ieee488_atn(int state) override;
@@ -69,13 +69,13 @@ protected:
void add_common_devices(machine_config &config);
inline void update_ieee_signals();
- DECLARE_FLOPPY_FORMATS( floppy_formats );
+ static void floppy_formats(format_registration &fr);
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;
@@ -102,11 +102,11 @@ public:
protected:
// optional information overrides
- virtual const tiny_rom_entry *device_rom_region() const override;
- virtual void device_add_mconfig(machine_config &config) override;
+ virtual const tiny_rom_entry *device_rom_region() const override ATTR_COLD;
+ virtual void device_add_mconfig(machine_config &config) override ATTR_COLD;
private:
- DECLARE_FLOPPY_FORMATS( floppy_formats );
+ static void floppy_formats(format_registration &fr);
};
@@ -120,11 +120,11 @@ public:
protected:
// optional information overrides
- virtual const tiny_rom_entry *device_rom_region() const override;
- virtual void device_add_mconfig(machine_config &config) override;
+ virtual const tiny_rom_entry *device_rom_region() const override ATTR_COLD;
+ virtual void device_add_mconfig(machine_config &config) override ATTR_COLD;
private:
- DECLARE_FLOPPY_FORMATS( floppy_formats );
+ static void floppy_formats(format_registration &fr);
};
diff --git a/src/devices/bus/ieee488/c2040fdc.cpp b/src/devices/bus/ieee488/c2040fdc.cpp
index 7d99eb780cf..fa9ec6205a3 100644
--- a/src/devices/bus/ieee488/c2040fdc.cpp
+++ b/src/devices/bus/ieee488/c2040fdc.cpp
@@ -105,13 +105,8 @@ 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(0);
+ t_gen = timer_alloc(FUNC(c2040_fdc_device::update_state), this);
// register for state saving
save_item(NAME(m_mtr0));
@@ -149,10 +144,10 @@ void c2040_fdc_device::device_reset()
//-------------------------------------------------
-// device_timer - handler timer events
+// update_state - pump our 'live' events
//-------------------------------------------------
-void c2040_fdc_device::device_timer(emu_timer &timer, device_timer_id id, int param, void *ptr)
+TIMER_CALLBACK_MEMBER(c2040_fdc_device::update_state)
{
live_sync();
live_run();
@@ -220,7 +215,7 @@ bool c2040_fdc_device::write_next_bit(bool bit, const attotime &limit)
if(etime > limit)
return true;
- if(bit && cur_live.write_position < ARRAY_LENGTH(cur_live.write_buffer))
+ if(bit && cur_live.write_position < std::size(cur_live.write_buffer))
cur_live.write_buffer[cur_live.write_position++] = cur_live.tm - m_period;
if (LOG) logerror("%s write bit %u (%u)\n", cur_live.tm.as_string(), cur_live.bit_counter, bit);
@@ -443,7 +438,7 @@ int c2040_fdc_device::get_next_bit(attotime &tm, const attotime &limit)
return bit && cur_live.rw_sel;
}
-READ8_MEMBER( c2040_fdc_device::read )
+uint8_t c2040_fdc_device::read()
{
uint8_t e = checkpoint_live.e;
offs_t i = checkpoint_live.i;
@@ -455,7 +450,7 @@ READ8_MEMBER( c2040_fdc_device::read )
return data;
}
-WRITE8_MEMBER( c2040_fdc_device::write )
+void c2040_fdc_device::write(uint8_t data)
{
if (m_pi != data)
{
@@ -467,19 +462,19 @@ WRITE8_MEMBER( c2040_fdc_device::write )
}
}
-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 64239991222..f86a7f4811f 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"
@@ -34,19 +30,19 @@ public:
auto ready_wr_callback() { return m_write_ready.bind(); }
auto error_wr_callback() { return m_write_error.bind(); }
- DECLARE_READ8_MEMBER( read );
- DECLARE_WRITE8_MEMBER( write );
+ 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);
@@ -56,13 +52,14 @@ public:
protected:
// device-level overrides
- virtual void device_start() override;
+ virtual void device_start() override ATTR_COLD;
virtual void device_clock_changed() override;
- virtual void device_reset() override;
- virtual void device_timer(emu_timer &timer, device_timer_id id, int param, void *ptr) override;
+ virtual void device_reset() override ATTR_COLD;
// optional information overrides
- virtual const tiny_rom_entry *device_rom_region() const override;
+ virtual const tiny_rom_entry *device_rom_region() const override ATTR_COLD;
+
+ TIMER_CALLBACK_MEMBER(update_state);
void stp_w(floppy_image_device *floppy, int mtr, int &old_stp, int stp);
diff --git a/src/devices/bus/ieee488/c8050.cpp b/src/devices/bus/ieee488/c8050.cpp
index 9594b26cf7e..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");
@@ -257,7 +260,7 @@ void c8050_device::sfd1001_fdc_mem(address_map &map)
// riot6532 uc1
//-------------------------------------------------
-READ8_MEMBER( c8050_device::dio_r )
+uint8_t c8050_device::dio_r()
{
/*
@@ -274,10 +277,10 @@ READ8_MEMBER( c8050_device::dio_r )
*/
- return m_bus->read_dio();
+ return m_bus->dio_r();
}
-WRITE8_MEMBER( c8050_device::dio_w )
+void c8050_device::dio_w(uint8_t data)
{
/*
@@ -301,7 +304,7 @@ WRITE8_MEMBER( c8050_device::dio_w )
// riot6532 ue1
//-------------------------------------------------
-READ8_MEMBER( c8050_device::riot1_pa_r )
+uint8_t c8050_device::riot1_pa_r()
{
/*
@@ -332,7 +335,7 @@ READ8_MEMBER( c8050_device::riot1_pa_r )
return data;
}
-WRITE8_MEMBER( c8050_device::riot1_pa_w )
+void c8050_device::riot1_pa_w(uint8_t data)
{
/*
@@ -367,7 +370,7 @@ WRITE8_MEMBER( c8050_device::riot1_pa_w )
update_ieee_signals();
}
-READ8_MEMBER( c8050_device::riot1_pb_r )
+uint8_t c8050_device::riot1_pb_r()
{
/*
@@ -398,7 +401,7 @@ READ8_MEMBER( c8050_device::riot1_pb_r )
return data;
}
-WRITE8_MEMBER( c8050_device::riot1_pb_w )
+void c8050_device::riot1_pb_w(uint8_t data)
{
/*
@@ -425,7 +428,7 @@ WRITE8_MEMBER( c8050_device::riot1_pb_w )
m_leds[LED_ERR] = BIT(data, 5);
}
-WRITE8_MEMBER( c8050_device::via_pb_w )
+void c8050_device::via_pb_w(uint8_t data)
{
/*
@@ -473,9 +476,10 @@ static void c8050_floppies(device_slot_interface &device)
// FLOPPY_FORMATS( floppy_formats )
//-------------------------------------------------
-FLOPPY_FORMATS_MEMBER( c8050_device::floppy_formats )
- FLOPPY_D80_FORMAT
-FLOPPY_FORMATS_END
+void c8050_device::floppy_formats(format_registration &fr)
+{
+ fr.add(FLOPPY_D80_FORMAT);
+}
//-------------------------------------------------
@@ -502,30 +506,33 @@ static void sfd1001_floppies(device_slot_interface &device)
// FLOPPY_FORMATS( floppy_formats )
//-------------------------------------------------
-FLOPPY_FORMATS_MEMBER( c8250_device::floppy_formats )
- FLOPPY_D80_FORMAT,
- FLOPPY_D82_FORMAT
-FLOPPY_FORMATS_END
+void c8250_device::floppy_formats(format_registration &fr)
+{
+ fr.add(FLOPPY_D80_FORMAT);
+ fr.add(FLOPPY_D82_FORMAT);
+}
//-------------------------------------------------
// FLOPPY_FORMATS( floppy_formats )
//-------------------------------------------------
-FLOPPY_FORMATS_MEMBER( c8250lp_device::floppy_formats )
- FLOPPY_D80_FORMAT,
- FLOPPY_D82_FORMAT
-FLOPPY_FORMATS_END
+void c8250lp_device::floppy_formats(format_registration &fr)
+{
+ fr.add(FLOPPY_D80_FORMAT);
+ fr.add(FLOPPY_D82_FORMAT);
+}
//-------------------------------------------------
// FLOPPY_FORMATS( floppy_formats )
//-------------------------------------------------
-FLOPPY_FORMATS_MEMBER( sfd1001_device::floppy_formats )
- FLOPPY_D80_FORMAT,
- FLOPPY_D82_FORMAT
-FLOPPY_FORMATS_END
+void sfd1001_device::floppy_formats(format_registration &fr)
+{
+ fr.add(FLOPPY_D80_FORMAT);
+ fr.add(FLOPPY_D82_FORMAT);
+}
void c8050_device::add_common_devices(machine_config &config)
@@ -534,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));
@@ -548,19 +555,19 @@ void c8050_device::add_common_devices(machine_config &config)
// controller
M6504(config, m_fdccpu, XTAL(12'000'000)/12);
- VIA6522(config, m_via, XTAL(12'000'000)/12);
+ MOS6522(config, m_via, XTAL(12'000'000)/12);
m_via->readpa_handler().set(m_fdc, FUNC(c8050_fdc_device::read));
m_via->writepb_handler().set(FUNC(c8050_device::via_pb_w));
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));
@@ -770,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);
@@ -786,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 c8f96c4605f..19ce2f03156 100644
--- a/src/devices/bus/ieee488/c8050.h
+++ b/src/devices/bus/ieee488/c8050.h
@@ -6,8 +6,8 @@
**********************************************************************/
-#ifndef MAME_BUS_IEE488_C8050_H
-#define MAME_BUS_IEE488_C8050_H
+#ifndef MAME_BUS_IEEE488_C8050_H
+#define MAME_BUS_IEEE488_C8050_H
#pragma once
@@ -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"
@@ -32,29 +32,29 @@ public:
// construction/destruction
c8050_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
- DECLARE_READ8_MEMBER( dio_r );
- DECLARE_WRITE8_MEMBER( dio_w );
- DECLARE_READ8_MEMBER( riot1_pa_r );
- DECLARE_WRITE8_MEMBER( riot1_pa_w );
- DECLARE_READ8_MEMBER( riot1_pb_r );
- DECLARE_WRITE8_MEMBER( riot1_pb_w );
- DECLARE_WRITE8_MEMBER( via_pb_w );
-
- void c8050_fdc_mem(address_map &map);
- void c8050_main_mem(address_map &map);
- void c8250lp_fdc_mem(address_map &map);
- void sfd1001_fdc_mem(address_map &map);
+ uint8_t dio_r();
+ void dio_w(uint8_t data);
+ uint8_t riot1_pa_r();
+ void riot1_pa_w(uint8_t data);
+ uint8_t riot1_pb_r();
+ void riot1_pb_w(uint8_t data);
+ void via_pb_w(uint8_t data);
+
+ void c8050_fdc_mem(address_map &map) ATTR_COLD;
+ void c8050_main_mem(address_map &map) ATTR_COLD;
+ void c8250lp_fdc_mem(address_map &map) ATTR_COLD;
+ void sfd1001_fdc_mem(address_map &map) ATTR_COLD;
protected:
c8050_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_start() override ATTR_COLD;
+ virtual void device_reset() override ATTR_COLD;
// optional information 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 const tiny_rom_entry *device_rom_region() const override ATTR_COLD;
+ virtual void device_add_mconfig(machine_config &config) override ATTR_COLD;
+ virtual ioport_constructor device_input_ports() const override ATTR_COLD;
// device_ieee488_interface overrides
virtual void ieee488_atn(int state) override;
@@ -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;
@@ -82,7 +82,7 @@ protected:
int m_ifc;
private:
- DECLARE_FLOPPY_FORMATS( floppy_formats );
+ static void floppy_formats(format_registration &fr);
};
@@ -96,10 +96,10 @@ public:
protected:
// optional information overrides
- virtual void device_add_mconfig(machine_config &config) override;
+ virtual void device_add_mconfig(machine_config &config) override ATTR_COLD;
private:
- DECLARE_FLOPPY_FORMATS( floppy_formats );
+ static void floppy_formats(format_registration &fr);
};
@@ -113,11 +113,11 @@ public:
protected:
// optional information overrides
- virtual const tiny_rom_entry *device_rom_region() const override;
- virtual void device_add_mconfig(machine_config &config) override;
+ virtual const tiny_rom_entry *device_rom_region() const override ATTR_COLD;
+ virtual void device_add_mconfig(machine_config &config) override ATTR_COLD;
private:
- DECLARE_FLOPPY_FORMATS( floppy_formats );
+ static void floppy_formats(format_registration &fr);
};
@@ -131,11 +131,11 @@ public:
protected:
// optional information overrides
- virtual const tiny_rom_entry *device_rom_region() const override;
- virtual void device_add_mconfig(machine_config &config) override;
+ virtual const tiny_rom_entry *device_rom_region() const override ATTR_COLD;
+ virtual void device_add_mconfig(machine_config &config) override ATTR_COLD;
private:
- DECLARE_FLOPPY_FORMATS( floppy_formats );
+ static void floppy_formats(format_registration &fr);
};
@@ -146,4 +146,4 @@ DECLARE_DEVICE_TYPE(C8250LP, c8250lp_device)
DECLARE_DEVICE_TYPE(SFD1001, sfd1001_device)
-#endif // MAME_BUS_IEE488_C8050_H
+#endif // MAME_BUS_IEEE488_C8050_H
diff --git a/src/devices/bus/ieee488/c8050fdc.cpp b/src/devices/bus/ieee488/c8050fdc.cpp
index 50861316839..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,14 +106,8 @@ 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(0);
+ t_gen = timer_alloc(FUNC(c8050_fdc_device::update_state), this);
// register for state saving
save_item(NAME(m_mtr0));
@@ -141,10 +136,10 @@ void c8050_fdc_device::device_reset()
//-------------------------------------------------
-// device_timer - handler timer events
+// update_state - pump our 'live' events
//-------------------------------------------------
-void c8050_fdc_device::device_timer(emu_timer &timer, device_timer_id id, int param, void *ptr)
+TIMER_CALLBACK_MEMBER(c8050_fdc_device::update_state)
{
live_sync();
live_run();
@@ -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;
}
@@ -497,7 +490,7 @@ void c8050_fdc_device::live_run(const attotime &limit)
}
}
-READ8_MEMBER( c8050_fdc_device::read )
+uint8_t c8050_fdc_device::read()
{
uint8_t e = checkpoint_live.e;
offs_t i = checkpoint_live.i;
@@ -505,9 +498,9 @@ READ8_MEMBER( c8050_fdc_device::read )
return GCR_DECODE(e, i);
}
-WRITE8_MEMBER( c8050_fdc_device::write )
+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 @@ WRITE8_MEMBER( c8050_fdc_device::write )
}
}
-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 2f75511b817..d736d61dc44 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"
@@ -35,20 +33,20 @@ public:
auto brdy_wr_callback() { return m_write_brdy.bind(); }
auto error_wr_callback() { return m_write_error.bind(); }
- DECLARE_READ8_MEMBER( read );
- DECLARE_WRITE8_MEMBER( write );
+ 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 );
+ 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);
- DECLARE_READ_LINE_MEMBER( wps_r ) { return checkpoint_live.drv_sel ? m_floppy1->wpt_r() : m_floppy0->wpt_r(); }
+ 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);
@@ -58,12 +56,13 @@ public:
protected:
// device-level overrides
- virtual void device_start() override;
- virtual void device_reset() override;
- virtual void device_timer(emu_timer &timer, device_timer_id id, int param, void *ptr) override;
+ virtual void device_start() override ATTR_COLD;
+ virtual void device_reset() override ATTR_COLD;
// optional information overrides
- virtual const tiny_rom_entry *device_rom_region() const override;
+ virtual const tiny_rom_entry *device_rom_region() const override ATTR_COLD;
+
+ TIMER_CALLBACK_MEMBER(update_state);
void stp_w(floppy_image_device *floppy, int mtr, int &old_stp, int stp);
diff --git a/src/devices/bus/ieee488/c8280.cpp b/src/devices/bus/ieee488/c8280.cpp
index 63b5cbe2506..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");
@@ -110,7 +114,7 @@ void c8280_device::c8280_fdc_mem(address_map &map)
// riot6532 0
//-------------------------------------------------
-READ8_MEMBER( c8280_device::dio_r )
+uint8_t c8280_device::dio_r()
{
/*
@@ -127,10 +131,10 @@ READ8_MEMBER( c8280_device::dio_r )
*/
- return m_bus->read_dio();
+ return m_bus->dio_r();
}
-WRITE8_MEMBER( c8280_device::dio_w )
+void c8280_device::dio_w(uint8_t data)
{
/*
@@ -155,7 +159,7 @@ WRITE8_MEMBER( c8280_device::dio_w )
// riot6532 1
//-------------------------------------------------
-READ8_MEMBER( c8280_device::riot1_pa_r )
+uint8_t c8280_device::riot1_pa_r()
{
/*
@@ -186,7 +190,7 @@ READ8_MEMBER( c8280_device::riot1_pa_r )
return data;
}
-WRITE8_MEMBER( c8280_device::riot1_pa_w )
+void c8280_device::riot1_pa_w(uint8_t data)
{
/*
@@ -221,7 +225,7 @@ WRITE8_MEMBER( c8280_device::riot1_pa_w )
update_ieee_signals();
}
-READ8_MEMBER( c8280_device::riot1_pb_r )
+uint8_t c8280_device::riot1_pb_r()
{
/*
@@ -252,7 +256,7 @@ READ8_MEMBER( c8280_device::riot1_pb_r )
return data;
}
-WRITE8_MEMBER( c8280_device::riot1_pb_w )
+void c8280_device::riot1_pb_w(uint8_t data)
{
/*
@@ -284,9 +288,11 @@ static void c8280_floppies(device_slot_interface &device)
device.option_add("8dsdd", FLOPPY_8_DSDD);
}
-FLOPPY_FORMATS_MEMBER( c8280_device::floppy_formats )
- FLOPPY_C8280_FORMAT
-FLOPPY_FORMATS_END
+void c8280_device::floppy_formats(format_registration &fr)
+{
+ fr.add_mfm_containers();
+ fr.add(FLOPPY_C8280_FORMAT);
+}
//-------------------------------------------------
@@ -298,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));
@@ -315,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);
}
@@ -385,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),
@@ -432,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);
}
@@ -449,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);
}
@@ -467,7 +473,7 @@ void c8280_device::ieee488_ifc(int state)
m_ifc = state;
}
-READ8_MEMBER( c8280_device::fk5_r )
+uint8_t c8280_device::fk5_r()
{
/*
@@ -486,13 +492,13 @@ READ8_MEMBER( 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;
}
-WRITE8_MEMBER( c8280_device::fk5_w )
+void c8280_device::fk5_w(uint8_t data)
{
/*
@@ -512,14 +518,17 @@ WRITE8_MEMBER( c8280_device::fk5_w )
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 d5e0fc8ef1f..f5a1342f857 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"
@@ -34,13 +32,13 @@ public:
protected:
// device-level overrides
- virtual void device_start() override;
- virtual void device_reset() override;
+ virtual void device_start() override ATTR_COLD;
+ virtual void device_reset() override ATTR_COLD;
// optional information 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 const tiny_rom_entry *device_rom_region() const override ATTR_COLD;
+ virtual void device_add_mconfig(machine_config &config) override ATTR_COLD;
+ virtual ioport_constructor device_input_ports() const override ATTR_COLD;
// device_ieee488_interface overrides
void ieee488_atn(int state) override;
@@ -49,29 +47,28 @@ protected:
private:
inline void update_ieee_signals();
- DECLARE_READ8_MEMBER( dio_r );
- DECLARE_WRITE8_MEMBER( dio_w );
- DECLARE_READ8_MEMBER( riot1_pa_r );
- DECLARE_WRITE8_MEMBER( riot1_pa_w );
- DECLARE_READ8_MEMBER( riot1_pb_r );
- DECLARE_WRITE8_MEMBER( riot1_pb_w );
- DECLARE_READ8_MEMBER( fk5_r );
- DECLARE_WRITE8_MEMBER( fk5_w );
+ uint8_t dio_r();
+ void dio_w(uint8_t data);
+ uint8_t riot1_pa_r();
+ void riot1_pa_w(uint8_t data);
+ uint8_t riot1_pb_r();
+ void riot1_pb_w(uint8_t data);
+ uint8_t fk5_r();
+ void fk5_w(uint8_t data);
- void c8280_fdc_mem(address_map &map);
- void c8280_main_mem(address_map &map);
+ void c8280_fdc_mem(address_map &map) ATTR_COLD;
+ void c8280_main_mem(address_map &map) ATTR_COLD;
- DECLARE_FLOPPY_FORMATS( floppy_formats );
+ static void floppy_formats(format_registration &fr);
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 58a34acae64..3020fa41f42 100644
--- a/src/devices/bus/ieee488/d9060.cpp
+++ b/src/devices/bus/ieee488/d9060.cpp
@@ -19,8 +19,8 @@
Start the PET emulator with the D9060 attached on the IEEE-488 bus,
with the new CHD mounted:
- $ mess pet8032 -ieee8 d9060 -hard tm602s.chd
- $ mess pet8032 -ieee8 d9090 -hard tm603s.chd
+ $ mame pet8032 -ieee8 d9060 -hard tm602s.chd
+ $ mame pet8032 -ieee8 d9090 -hard tm603s.chd
Enter 'HEADER "LABEL",D0,I01' to format the hard drive.
Wait up to 1 hour and 20 minutes.
@@ -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");
@@ -136,7 +136,7 @@ void d9060_device_base::hdc_mem(address_map &map)
// riot6532 0
//-------------------------------------------------
-READ8_MEMBER( d9060_device_base::dio_r )
+uint8_t d9060_device_base::dio_r()
{
/*
@@ -153,11 +153,11 @@ READ8_MEMBER( d9060_device_base::dio_r )
*/
- return m_bus->read_dio();
+ return m_bus->dio_r();
}
-WRITE8_MEMBER( d9060_device_base::dio_w )
+void d9060_device_base::dio_w(uint8_t data)
{
/*
@@ -182,7 +182,7 @@ WRITE8_MEMBER( d9060_device_base::dio_w )
// riot6532 1
//-------------------------------------------------
-READ8_MEMBER( d9060_device_base::riot1_pa_r )
+uint8_t d9060_device_base::riot1_pa_r()
{
/*
@@ -213,7 +213,7 @@ READ8_MEMBER( d9060_device_base::riot1_pa_r )
return data;
}
-WRITE8_MEMBER( d9060_device_base::riot1_pa_w )
+void d9060_device_base::riot1_pa_w(uint8_t data)
{
/*
@@ -248,7 +248,7 @@ WRITE8_MEMBER( d9060_device_base::riot1_pa_w )
update_ieee_signals();
}
-READ8_MEMBER( d9060_device_base::riot1_pb_r )
+uint8_t d9060_device_base::riot1_pb_r()
{
/*
@@ -279,7 +279,7 @@ READ8_MEMBER( d9060_device_base::riot1_pb_r )
return data;
}
-WRITE8_MEMBER( d9060_device_base::riot1_pb_w )
+void d9060_device_base::riot1_pb_w(uint8_t data)
{
/*
@@ -307,7 +307,7 @@ WRITE8_MEMBER( d9060_device_base::riot1_pb_w )
}
-WRITE8_MEMBER( d9060_device_base::via_pb_w )
+void d9060_device_base::via_pb_w(uint8_t data)
{
/*
@@ -328,12 +328,12 @@ WRITE8_MEMBER( d9060_device_base::via_pb_w )
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;
@@ -347,7 +347,7 @@ WRITE_LINE_MEMBER( d9060_device_base::enable_w )
}
}
-WRITE8_MEMBER( d9060_device_base::scsi_data_w )
+void d9060_device_base::scsi_data_w(uint8_t data)
{
m_data = data;
@@ -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));
@@ -383,7 +383,7 @@ void d9060_device_base::device_add_mconfig(machine_config &config)
M6502(config, m_hdccpu, XTAL(4'000'000)/4);
m_hdccpu->set_addrmap(AS_PROGRAM, &d9060_device::hdc_mem);
- VIA6522(config, m_via, XTAL(4'000'000)/4);
+ MOS6522(config, m_via, XTAL(4'000'000)/4);
m_via->writepa_handler().set(FUNC(d9060_device_base::scsi_data_w));
m_via->writepb_handler().set(FUNC(d9060_device_base::via_pb_w));
m_via->ca2_handler().set(FUNC(d9060_device_base::ack_w));
@@ -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 b9d720090f2..8bf7d32ae6e 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"
@@ -39,13 +39,13 @@ protected:
d9060_device_base(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock, uint32_t variant);
// device-level overrides
- virtual void device_start() override;
- virtual void device_reset() override;
+ virtual void device_start() override ATTR_COLD;
+ virtual void device_reset() override ATTR_COLD;
// optional information 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 const tiny_rom_entry *device_rom_region() const override ATTR_COLD;
+ virtual void device_add_mconfig(machine_config &config) override ATTR_COLD;
+ virtual ioport_constructor device_input_ports() const override ATTR_COLD;
// device_ieee488_interface overrides
void ieee488_atn(int state) override;
@@ -54,21 +54,21 @@ protected:
private:
inline void update_ieee_signals();
- DECLARE_READ8_MEMBER( dio_r );
- DECLARE_WRITE8_MEMBER( dio_w );
- DECLARE_READ8_MEMBER( riot1_pa_r );
- DECLARE_WRITE8_MEMBER( riot1_pa_w );
- DECLARE_READ8_MEMBER( riot1_pb_r );
- DECLARE_WRITE8_MEMBER( riot1_pb_w );
- DECLARE_WRITE8_MEMBER( via_pb_w );
- DECLARE_WRITE_LINE_MEMBER( ack_w );
- DECLARE_WRITE_LINE_MEMBER( enable_w );
- DECLARE_WRITE8_MEMBER( scsi_data_w );
+ uint8_t dio_r();
+ void dio_w(uint8_t data);
+ uint8_t riot1_pa_r();
+ void riot1_pa_w(uint8_t data);
+ uint8_t riot1_pb_r();
+ void riot1_pb_w(uint8_t data);
+ void via_pb_w(uint8_t data);
+ 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;
@@ -86,8 +86,8 @@ private:
uint8_t m_data;
int m_variant;
- void hdc_mem(address_map &map);
- void main_mem(address_map &map);
+ void hdc_mem(address_map &map) ATTR_COLD;
+ void main_mem(address_map &map) ATTR_COLD;
};
diff --git a/src/devices/bus/ieee488/grid2102.cpp b/src/devices/bus/ieee488/grid2102.cpp
new file mode 100644
index 00000000000..4e6bc92c391
--- /dev/null
+++ b/src/devices/bus/ieee488/grid2102.cpp
@@ -0,0 +1,315 @@
+// license:BSD-3-Clause
+// copyright-holders:usernameak
+/**********************************************************************
+
+ GRiD 2102 Portable Floppy emulation
+
+ http://deltacxx.insomnia247.nl/gridcompass/disk_info.txt for some protocol info
+ http://deltacxx.insomnia247.nl/gridcompass/fdd_boards.jpg for floppy drive boards photo
+
+**********************************************************************/
+
+#include "emu.h"
+#include "grid2102.h"
+
+// device type definition
+DEFINE_DEVICE_TYPE(GRID2102, grid2102_device, "grid2102", "GRID2102")
+DEFINE_DEVICE_TYPE(GRID2101_FLOPPY, grid2101_floppy_device, "grid2101_floppy", "GRID2101_FLOPPY")
+DEFINE_DEVICE_TYPE(GRID2101_HDD, grid2101_hdd_device, "grid2101_hdd", "GRID2101_HDD")
+
+#define LOG_BYTES_MASK (LOG_GENERAL << 1)
+#define LOG_BYTES(...) LOGMASKED(LOG_BYTES_MASK, __VA_ARGS__)
+#define VERBOSE (LOG_GENERAL)
+#include "logmacro.h"
+
+#define GRID2102_FETCH32(Array, Offset) ((uint32_t)(\
+ (Array[Offset] << 0) |\
+ (Array[Offset + 1] << 8) |\
+ (Array[Offset + 2] << 16) |\
+ (Array[Offset + 3] << 24)\
+))
+
+#define GRID2102_FETCH16(Array, Offset) ((uint16_t)(\
+ (Array[Offset] << 0) |\
+ (Array[Offset + 1] << 8)\
+))
+
+#define GRID2101_HARDDISK_DEV_ADDR 4
+#define GRID2102_DEV_ADDR 6
+
+#define GRID210X_GPIB_STATE_IDLE 0
+#define GRID210X_GPIB_STATE_WAIT_DAV_FALSE 1
+#define GRID210X_GPIB_STATE_SEND_DATA_START 2
+#define GRID210X_GPIB_STATE_WAIT_NDAC_FALSE 3
+
+#define GRID210X_STATE_IDLE 0
+#define GRID210X_STATE_READING_DATA 1
+#define GRID210X_STATE_WRITING_DATA 2
+#define GRID210X_STATE_WRITING_DATA_WAIT 3
+
+uint8_t grid2102_device::identify_response[56] = {0x00, 0x02, 0xf8, 0x01, 0xD0, 0x02, 0x01, 0x20, 0x01, 0x21, 0x01, 0x01, 0x00, 0x00,
+ 0x34, 0x38, 0x20, 0x54, 0x50, 0x49, 0x20, 0x44, 0x53, 0x20, 0x44, 0x44, 0x20, 0x46,
+ 0x4c, 0x4f, 0x50, 0x50, 0x59, 0x20, 0x20, 0x20, 0x20, 0x33, 0x30, 0x32, 0x33, 0x37,
+ 0x2d, 0x30, 0x30, 0x00, 0x02, 0x09, 0x00};
+
+uint8_t grid2101_floppy_device::identify_response[56] = {0x00, 0x02, 0xf8, 0x01, 0xD0, 0x02, 0x01, 0x20, 0x01, 0x21, 0x01, 0x01, 0x00, 0x00,
+ 0x34, 0x38, 0x20, 0x54, 0x50, 0x49, 0x20, 0x44, 0x53, 0x20, 0x44, 0x44, 0x20, 0x46,
+ 0x4c, 0x4f, 0x50, 0x50, 0x59, 0x20, 0x20, 0x20, 0x20, 0x33, 0x30, 0x32, 0x33, 0x37,
+ 0x2d, 0x30, 0x30, 0x00, 0x02, 0x09, 0x00};
+
+uint8_t grid2101_hdd_device::identify_response[56] = {
+ 0x00, 0x02, 0xF8, 0x01, 0x8C, 0x51, 0x01, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x4D, 0x41,
+ 0x4D, 0x45, 0x20, 0x48, 0x41, 0x52, 0x44, 0x44, 0x49, 0x53, 0x4B, 0x20, 0x44, 0x52, 0x49, 0x56,
+ 0x45, 0x20, 0x20, 0x20, 0x20, 0x20, 0x47, 0x52, 0x49, 0x44, 0x32, 0x31, 0x30, 0x31, 0x00, 0x02,
+ 0x11, 0x00, 0x33, 0x01, 0x00, 0x00, 0x04, 0x00
+};
+
+
+grid210x_device::grid210x_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock, int bus_addr, uint8_t *identify_response, attotime read_delay)
+ : device_t(mconfig, type, tag, owner, clock),
+ device_ieee488_interface(mconfig, *this),
+ device_image_interface(mconfig, *this),
+ m_gpib_loop_state(GRID210X_GPIB_STATE_IDLE),
+ m_floppy_loop_state(GRID210X_STATE_IDLE),
+ listening(false),
+ talking(false),
+ serial_polling(false),
+ has_srq(false),
+ serial_poll_byte(0),
+ bus_addr(bus_addr),
+ identify_response_ptr(identify_response),
+ read_delay(read_delay)
+{
+
+}
+
+void grid210x_device::device_start() {
+ m_bus->ndac_w(this, 1);
+ m_bus->nrfd_w(this, 1);
+ m_delay_timer = timer_alloc(FUNC(grid210x_device::delay_tick), this);
+}
+
+TIMER_CALLBACK_MEMBER(grid210x_device::delay_tick) {
+ if (m_floppy_loop_state == GRID210X_STATE_READING_DATA) {
+ std::unique_ptr<uint8_t[]> data(new uint8_t[io_size]);
+ fseek(floppy_sector_number * 512, SEEK_SET);
+ fread(data.get(), io_size);
+ for (int i = 0; i < io_size; i++) {
+ m_output_data_buffer.push(data[i]);
+ }
+ serial_poll_byte = 0x0F;
+ has_srq = true;
+ m_bus->srq_w(this, 0);
+ m_floppy_loop_state = GRID210X_STATE_IDLE;
+ } else if (m_floppy_loop_state == GRID210X_STATE_WRITING_DATA_WAIT) {
+ // send an srq as success flag
+ for (int i = 0; i < 7; i++) { // FIXME:
+ m_output_data_buffer.push(0);
+ }
+ serial_poll_byte = 0x0F;
+ has_srq = true;
+ m_bus->srq_w(this, 0);
+ m_floppy_loop_state = GRID210X_STATE_IDLE;
+ }
+}
+
+void grid210x_device::ieee488_eoi(int state) {
+ // logerror("grid210x_device eoi state set to %d\n", state);
+}
+
+void grid210x_device::accept_transfer() {
+ if (m_floppy_loop_state == GRID210X_STATE_IDLE) {
+ if (m_data_buffer.size() >= 0xA) {
+ uint8_t command = m_data_buffer[0];
+ uint32_t sector_number = GRID2102_FETCH32(m_data_buffer, 3);
+ uint16_t data_size = GRID2102_FETCH16(m_data_buffer, 7);
+ LOG("grid210x_device command %u, data size %u, sector no %u\n", (unsigned)command, (unsigned)data_size, (unsigned)sector_number);
+ (void)(sector_number);
+ if (command == 0x1) { // ddGetStatus
+ for (int i = 0; i < 56 && i < data_size; i++) {
+ m_output_data_buffer.push(identify_response_ptr[i]);
+ }
+ } else if (command == 0x4) { // ddRead
+ floppy_sector_number = sector_number;
+ io_size = data_size;
+ m_floppy_loop_state = GRID210X_STATE_READING_DATA;
+ m_delay_timer->adjust(read_delay);
+ } else if (command == 0x5) {
+ floppy_sector_number = sector_number;
+ io_size = data_size;
+ m_floppy_loop_state = GRID210X_STATE_WRITING_DATA;
+ }
+ } // else something is wrong, ignore
+ } else if (m_floppy_loop_state == GRID210X_STATE_WRITING_DATA) {
+ // write
+ if (floppy_sector_number != 0xFFFFFFFF) {
+ fseek(floppy_sector_number * 512, SEEK_SET);
+ fwrite(m_data_buffer.data(), m_data_buffer.size());
+ } else {
+ // TODO: set status
+ }
+ // logerror("grid210x_device write sector %d\n", floppy_sector_number);
+ // wait
+ m_floppy_loop_state = GRID210X_STATE_WRITING_DATA_WAIT;
+ m_delay_timer->adjust(read_delay);
+ }
+}
+
+void grid210x_device::ieee488_dav(int state) {
+ if(state == 0 && m_gpib_loop_state == GRID210X_GPIB_STATE_IDLE) {
+ // read data and wait for transfer end
+ int atn = m_bus->atn_r() ^ 1;
+ m_bus->nrfd_w(this, 0);
+ uint8_t data = m_bus->dio_r() ^ 0xFF;
+ int eoi = m_bus->eoi_r() ^ 1;
+ LOG_BYTES("grid210x_device byte recv %02x atn %d eoi %d\n", data, atn, eoi);
+ m_last_recv_byte = data;
+ m_last_recv_atn = atn;
+ m_last_recv_eoi = eoi;
+ m_bus->ndac_w(this, 1);
+ m_gpib_loop_state = GRID210X_GPIB_STATE_WAIT_DAV_FALSE;
+ } else if (state == 1 && m_gpib_loop_state == GRID210X_GPIB_STATE_WAIT_DAV_FALSE) {
+ // restore initial state
+ // m_bus->ndac_w(this, 0);
+ m_bus->nrfd_w(this, 1);
+ m_gpib_loop_state = GRID210X_GPIB_STATE_IDLE;
+ update_ndac(m_bus->atn_r() ^ 1);
+
+ if (m_last_recv_atn) {
+ if ((m_last_recv_byte & 0xE0) == 0x20) {
+ if ((m_last_recv_byte & 0x1F) == bus_addr) {
+ // dev-id = 5
+ listening = true;
+ LOG("grid210x_device now listening\n");
+ } else if((m_last_recv_byte & 0x1F) == 0x1F) {
+ // reset listen
+ listening = false;
+ LOG("grid210x_device now not listening\n");
+ }
+ } else if ((m_last_recv_byte & 0xE0) == 0x40) {
+ if ((m_last_recv_byte & 0x1F) == bus_addr) {
+ // dev-id = 5
+ talking = true;
+ LOG("grid210x_device now talking\n");
+ } else {
+ // reset talk
+ talking = false;
+ LOG("grid210x_device now not talking\n");
+ }
+ } else if (m_last_recv_byte == 0x18) {
+ // serial poll enable
+ serial_polling = true;
+ } else if (m_last_recv_byte == 0x19) {
+ // serial poll disable
+ serial_polling = false;
+ }
+ } else if (listening) {
+ m_data_buffer.push_back(m_last_recv_byte);
+ if (m_last_recv_eoi) {
+ accept_transfer();
+ m_data_buffer.clear();
+ }
+ }
+
+ if (talking) {
+ if (serial_polling) {
+ bool had_srq = has_srq;
+ if (has_srq) {
+ has_srq = false;
+ m_bus->srq_w(this, 1);
+ }
+ m_byte_to_send = serial_poll_byte | (had_srq ? 0x40 : 0);
+ serial_poll_byte = 0;
+ m_send_eoi = 1;
+ m_gpib_loop_state = GRID210X_GPIB_STATE_SEND_DATA_START;
+ } else if (!m_output_data_buffer.empty()) {
+ m_byte_to_send = m_output_data_buffer.front();
+ m_output_data_buffer.pop();
+ m_send_eoi = m_output_data_buffer.empty() ? 1 : 0;
+ m_gpib_loop_state = GRID210X_GPIB_STATE_SEND_DATA_START;
+ }
+ }
+ }
+}
+
+void grid210x_device::ieee488_nrfd(int state) {
+ if (state == 1 && m_gpib_loop_state == GRID210X_GPIB_STATE_SEND_DATA_START) {
+ // set dio and assert dav
+ m_bus->host_dio_w(m_byte_to_send ^ 0xFF);
+ m_bus->eoi_w(this, m_send_eoi ^ 1);
+ m_bus->dav_w(this, 0);
+ m_bus->ndac_w(this, 1);
+ m_gpib_loop_state = GRID210X_GPIB_STATE_WAIT_NDAC_FALSE;
+ LOG_BYTES("grid210x_device byte send %02x eoi %d\n", m_byte_to_send, m_send_eoi);
+ ieee488_ndac(m_bus->ndac_r());
+ }
+ // logerror("grid210x_device nrfd state set to %d\n", state);
+}
+
+void grid210x_device::ieee488_ndac(int state) {
+ if (state == 1 && m_gpib_loop_state == GRID210X_GPIB_STATE_WAIT_NDAC_FALSE) {
+ // restore initial state
+ // logerror("grid210x_device restore ndac nrfd dav eoi\n");
+ m_bus->nrfd_w(this, 1);
+ m_bus->dav_w(this, 1);
+ m_bus->eoi_w(this, 1);
+ m_gpib_loop_state = GRID210X_GPIB_STATE_IDLE;
+ if (serial_polling) {
+ talking = false;
+ }
+ update_ndac(m_bus->atn_r() ^ 1);
+
+ if (!serial_polling && talking && !m_output_data_buffer.empty()) {
+ m_byte_to_send = m_output_data_buffer.front();
+ m_output_data_buffer.pop();
+ m_send_eoi = m_output_data_buffer.empty() ? 1 : 0;
+ m_gpib_loop_state = GRID210X_GPIB_STATE_SEND_DATA_START;
+ }
+ }
+ // logerror("grid210x_device ndac state set to %d\n", state);
+}
+
+void grid210x_device::ieee488_ifc(int state) {
+ // logerror("grid210x_device ifc state set to %d\n", state);
+}
+
+void grid210x_device::ieee488_srq(int state) {
+ // logerror("grid210x_device srq state set to %d\n", state);
+}
+
+void grid210x_device::ieee488_atn(int state) {
+ // logerror("grid210x_device atn state set to %d\n", state);
+ update_ndac(state ^ 1);
+}
+
+void grid210x_device::update_ndac(int atn) {
+ if (m_gpib_loop_state == GRID210X_GPIB_STATE_IDLE) {
+ if (atn) {
+ // pull NDAC low
+ m_bus->ndac_w(this, 0);
+ } else {
+ // pull NDAC high if not listener and low if listener
+ m_bus->ndac_w(this, listening ? 0 : 1);
+ }
+ }
+}
+
+void grid210x_device::ieee488_ren(int state) {
+ LOG("grid210x_device ren state set to %d\n", state);
+}
+
+grid2101_hdd_device::grid2101_hdd_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
+ : grid210x_device(mconfig, GRID2101_HDD, tag, owner, clock, 4, identify_response, attotime::from_usec(150))
+{
+
+}
+
+grid2101_floppy_device::grid2101_floppy_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) : grid210x_device(mconfig, GRID2101_FLOPPY, tag, owner, clock, 5, identify_response)
+{
+
+}
+
+grid2102_device::grid2102_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) : grid210x_device(mconfig, GRID2102, tag, owner, clock, 6, identify_response)
+{
+
+}
diff --git a/src/devices/bus/ieee488/grid2102.h b/src/devices/bus/ieee488/grid2102.h
new file mode 100644
index 00000000000..437bae8fb97
--- /dev/null
+++ b/src/devices/bus/ieee488/grid2102.h
@@ -0,0 +1,118 @@
+// license:BSD-3-Clause
+// copyright-holders:usernameak
+/**********************************************************************
+
+ GRiD 2102 Portable Floppy emulation
+
+**********************************************************************/
+
+#ifndef MAME_BUS_IEEE488_GRID2102_H
+#define MAME_BUS_IEEE488_GRID2102_H
+
+#pragma once
+
+#include "ieee488.h"
+
+#include <queue>
+#include <vector>
+
+
+//**************************************************************************
+// TYPE DEFINITIONS
+//**************************************************************************
+
+// ======================> grid210x_device
+class grid210x_device : public device_t,
+ public device_ieee488_interface,
+ public device_image_interface
+{
+public:
+ // construction/destruction
+ grid210x_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock, int bus_addr, uint8_t *identify_response, attotime read_delay = attotime::from_msec(5));
+
+protected:
+ // device-level overrides
+ virtual void device_start() override ATTR_COLD;
+
+ // device_ieee488_interface overrides
+ virtual void ieee488_eoi(int state) override;
+ virtual void ieee488_dav(int state) override;
+ virtual void ieee488_nrfd(int state) override;
+ virtual void ieee488_ndac(int state) override;
+ virtual void ieee488_ifc(int state) override;
+ virtual void ieee488_srq(int state) override;
+ virtual void ieee488_atn(int state) override;
+ virtual void ieee488_ren(int state) override;
+
+ // image-level overrides
+ 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; }
+ virtual bool is_reset_on_load() const noexcept override { return false; }
+ virtual const char *file_extensions() const noexcept override { return "img"; }
+ virtual const char *image_type_name() const noexcept override { return "floppydisk"; }
+ virtual const char *image_brief_type_name() const noexcept override { return "flop"; }
+
+ void accept_transfer();
+ void update_ndac(int atn);
+
+private:
+ TIMER_CALLBACK_MEMBER(delay_tick);
+
+ int m_gpib_loop_state;
+ int m_floppy_loop_state;
+ uint8_t m_last_recv_byte;
+ int m_last_recv_eoi;
+ int m_last_recv_atn;
+ uint8_t m_byte_to_send;
+ int m_send_eoi;
+ bool listening, talking, serial_polling;
+ bool has_srq;
+ uint8_t serial_poll_byte;
+ uint32_t floppy_sector_number;
+ int bus_addr;
+ uint8_t *identify_response_ptr;
+ std::vector<uint8_t> m_data_buffer;
+ std::queue<uint8_t> m_output_data_buffer;
+ uint16_t io_size;
+ emu_timer *m_delay_timer;
+
+protected:
+ attotime read_delay;
+};
+
+class grid2102_device : public grid210x_device {
+public:
+ // construction/destruction
+ grid2102_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
+private:
+ static uint8_t identify_response[];
+};
+
+class grid2101_floppy_device : public grid210x_device {
+public:
+ // construction/destruction
+ grid2101_floppy_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
+private:
+ static uint8_t identify_response[];
+};
+
+class grid2101_hdd_device : public grid210x_device {
+public:
+ // construction/destruction
+ grid2101_hdd_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
+
+ // image-level overrides
+ virtual const char *image_type_name() const noexcept override { return "harddisk"; }
+ virtual const char *image_brief_type_name() const noexcept override { return "hard"; }
+
+private:
+ static uint8_t identify_response[];
+};
+
+// device type definition
+DECLARE_DEVICE_TYPE(GRID2102, grid2102_device)
+DECLARE_DEVICE_TYPE(GRID2101_FLOPPY, grid2101_floppy_device)
+DECLARE_DEVICE_TYPE(GRID2101_HDD, grid2101_hdd_device)
+
+#endif // MAME_BUS_IEEE488_GRID2102_H
diff --git a/src/devices/bus/ieee488/hardbox.cpp b/src/devices/bus/ieee488/hardbox.cpp
index 0b982ee772d..0ad2db1abfb 100644
--- a/src/devices/bus/ieee488/hardbox.cpp
+++ b/src/devices/bus/ieee488/hardbox.cpp
@@ -129,17 +129,17 @@ void hardbox_device::hardbox_io(address_map &map)
// I8255A 0 interface
//-------------------------------------------------
-READ8_MEMBER( hardbox_device::ppi0_pa_r )
+uint8_t hardbox_device::ppi0_pa_r()
{
- return m_bus->read_dio() ^ 0xff;
+ return m_bus->dio_r() ^ 0xff;
}
-WRITE8_MEMBER( hardbox_device::ppi0_pb_w )
+void hardbox_device::ppi0_pb_w(uint8_t data)
{
m_bus->dio_w(this, data ^ 0xff);
}
-READ8_MEMBER( hardbox_device::ppi0_pc_r )
+uint8_t hardbox_device::ppi0_pc_r()
{
uint8_t data = ioport("SW1")->read();
@@ -154,7 +154,7 @@ READ8_MEMBER( hardbox_device::ppi0_pc_r )
// I8255A 1 interface
//-------------------------------------------------
-READ8_MEMBER( hardbox_device::ppi1_pa_r )
+uint8_t hardbox_device::ppi1_pa_r()
{
/*
@@ -185,7 +185,7 @@ READ8_MEMBER( hardbox_device::ppi1_pa_r )
return data;
}
-WRITE8_MEMBER( hardbox_device::ppi1_pb_w )
+void hardbox_device::ppi1_pb_w(uint8_t data)
{
/*
@@ -214,7 +214,7 @@ WRITE8_MEMBER( hardbox_device::ppi1_pb_w )
m_bus->ren_w(this, !BIT(data, 6));
}
-READ8_MEMBER( hardbox_device::ppi1_pc_r )
+uint8_t hardbox_device::ppi1_pc_r()
{
/*
@@ -231,7 +231,7 @@ READ8_MEMBER( hardbox_device::ppi1_pc_r )
*/
- uint8_t status = m_hdc->status_r(space, 0);
+ uint8_t status = m_hdc->status_r();
uint8_t data = 0;
data |= (status & corvus_hdc_device::CONTROLLER_BUSY) ? 0 : 0x10;
@@ -240,7 +240,7 @@ READ8_MEMBER( hardbox_device::ppi1_pc_r )
return data;
}
-WRITE8_MEMBER( hardbox_device::ppi1_pc_w )
+void hardbox_device::ppi1_pc_w(uint8_t data)
{
/*
diff --git a/src/devices/bus/ieee488/hardbox.h b/src/devices/bus/ieee488/hardbox.h
index 65736c4e04f..0e1be1ac840 100644
--- a/src/devices/bus/ieee488/hardbox.h
+++ b/src/devices/bus/ieee488/hardbox.h
@@ -35,29 +35,29 @@ public:
protected:
// device-level overrides
- virtual void device_start() override;
+ virtual void device_start() override ATTR_COLD;
virtual void device_reset_after_children() override;
// optional information 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 const tiny_rom_entry *device_rom_region() const override ATTR_COLD;
+ virtual void device_add_mconfig(machine_config &config) override ATTR_COLD;
+ virtual ioport_constructor device_input_ports() const override ATTR_COLD;
// device_ieee488_interface overrides
virtual void ieee488_ifc(int state) override;
private:
- DECLARE_READ8_MEMBER( ppi0_pa_r );
- DECLARE_WRITE8_MEMBER( ppi0_pb_w );
- DECLARE_READ8_MEMBER( ppi0_pc_r );
+ uint8_t ppi0_pa_r();
+ void ppi0_pb_w(uint8_t data);
+ uint8_t ppi0_pc_r();
- DECLARE_READ8_MEMBER( ppi1_pa_r );
- DECLARE_WRITE8_MEMBER( ppi1_pb_w );
- DECLARE_READ8_MEMBER( ppi1_pc_r );
- DECLARE_WRITE8_MEMBER( ppi1_pc_w );
+ uint8_t ppi1_pa_r();
+ void ppi1_pb_w(uint8_t data);
+ uint8_t ppi1_pc_r();
+ void ppi1_pc_w(uint8_t data);
- void hardbox_io(address_map &map);
- void hardbox_mem(address_map &map);
+ void hardbox_io(address_map &map) ATTR_COLD;
+ void hardbox_mem(address_map &map) ATTR_COLD;
enum
{
diff --git a/src/devices/bus/ieee488/hp9122c.cpp b/src/devices/bus/ieee488/hp9122c.cpp
index 808deae2069..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")
@@ -91,7 +92,7 @@ void hp9122c_device::device_start()
save_item(NAME(m_ds0));
save_item(NAME(m_ds1));
- m_motor_timer = machine().scheduler().timer_alloc(timer_expired_delegate(FUNC(hp9122c_device::motor_timeout), this));
+ m_motor_timer = timer_alloc(FUNC(hp9122c_device::motor_timeout), this);
}
TIMER_CALLBACK_MEMBER(hp9122c_device::motor_timeout)
@@ -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();
@@ -255,17 +256,17 @@ void hp9122c_device::update_intsel()
m_cpufirq = firq;
}
-READ8_MEMBER(hp9122c_device::i8291a_dio_r)
+uint8_t hp9122c_device::i8291a_dio_r()
{
- return m_bus->read_dio();
+ return m_bus->dio_r();
}
-WRITE8_MEMBER(hp9122c_device::i8291a_dio_w)
+void hp9122c_device::i8291a_dio_w(uint8_t data)
{
m_bus->dio_w(this, data);
}
-READ8_MEMBER(hp9122c_device::status_r)
+uint8_t hp9122c_device::status_r()
{
uint8_t ret = REG_STATUS_DUAL|REG_STATUS_DISKCHG;
auto addr = m_hpib_addr->read();
@@ -290,7 +291,7 @@ READ8_MEMBER(hp9122c_device::status_r)
return ret;
}
-WRITE8_MEMBER(hp9122c_device::cmd_w)
+void hp9122c_device::cmd_w(uint8_t data)
{
floppy_image_device *floppy0 = m_floppy[0]->get_device();
floppy_image_device *floppy1 = m_floppy[1]->get_device();
@@ -338,7 +339,7 @@ void hp9122c_device::index_pulse_cb(floppy_image_device *floppy, int state)
}
-WRITE8_MEMBER(hp9122c_device::clridx_w)
+void hp9122c_device::clridx_w(uint8_t data)
{
m_index_int = false;
update_intsel();
@@ -355,12 +356,6 @@ static void hp9122c_floppies(device_slot_interface &device)
device.option_add("35hd" , FLOPPY_35_HD);
}
-static const floppy_format_type hp9122c_floppy_formats[] = {
- FLOPPY_MFI_FORMAT,
- FLOPPY_TD0_FORMAT,
- nullptr
-};
-
const tiny_rom_entry *hp9122c_device::device_rom_region() const
{
return ROM_NAME(hp9122c);
@@ -381,9 +376,8 @@ void hp9122c_device::device_add_mconfig(machine_config &config)
MC6809(config, m_cpu, XTAL(8'000'000));
m_cpu->set_addrmap(AS_PROGRAM, &hp9122c_device::cpu_map);
- // without this flag, 'DMA' transfer via SYNC instruction
- // will not work
- config.m_perfect_cpu_quantum = subtag("cpu");
+ // without this flag, 'DMA' transfer via SYNC instruction will not work
+ //config.set_perfect_quantum(m_cpu); FIXME: not safe in a slot device - add barriers
MB8876(config, m_fdc, 8_MHz_XTAL / 4);
m_fdc->intrq_wr_callback().set(FUNC(hp9122c_device::fdc_intrq_w));
@@ -400,7 +394,7 @@ void hp9122c_device::device_add_mconfig(machine_config &config)
m_i8291a->int_write().set(FUNC(hp9122c_device::i8291a_int_w));
m_i8291a->dreq_write().set(FUNC(hp9122c_device::i8291a_dreq_w));
- FLOPPY_CONNECTOR(config, "floppy0" , hp9122c_floppies , "35hd" , hp9122c_floppy_formats, true).enable_sound(true);
- FLOPPY_CONNECTOR(config, "floppy1" , hp9122c_floppies , "35hd" , hp9122c_floppy_formats, true).enable_sound(true);
+ FLOPPY_CONNECTOR(config, "floppy0" , hp9122c_floppies , "35hd" , floppy_image_device::default_mfm_floppy_formats, true).enable_sound(true);
+ FLOPPY_CONNECTOR(config, "floppy1" , hp9122c_floppies , "35hd" , floppy_image_device::default_mfm_floppy_formats, true).enable_sound(true);
config.set_default_layout(layout_hp9122c);
}
diff --git a/src/devices/bus/ieee488/hp9122c.h b/src/devices/bus/ieee488/hp9122c.h
index 60e8f590db1..08847c8cb6d 100644
--- a/src/devices/bus/ieee488/hp9122c.h
+++ b/src/devices/bus/ieee488/hp9122c.h
@@ -28,13 +28,13 @@ public:
hp9122c_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_start() override ATTR_COLD;
+ virtual void device_reset() override ATTR_COLD;
// device-level overrides
- 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 ioport_constructor device_input_ports() const override ATTR_COLD;
+ virtual const tiny_rom_entry *device_rom_region() const override ATTR_COLD;
+ virtual void device_add_mconfig(machine_config &config) override ATTR_COLD;
// device_ieee488_interface overrides
virtual void ieee488_eoi(int state) override;
@@ -91,33 +91,29 @@ 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);
- DECLARE_READ8_MEMBER(i8291a_dio_r);
- DECLARE_WRITE8_MEMBER(i8291a_dio_w);
+ 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);
- DECLARE_WRITE8_MEMBER(cmd_w);
- DECLARE_READ8_MEMBER(status_r);
- DECLARE_WRITE8_MEMBER(clridx_w);
- // Floppy drive interface
+ void cmd_w(uint8_t data);
+ uint8_t status_r();
+ void clridx_w(uint8_t data);
- DECLARE_READ8_MEMBER(fdc_read);
- DECLARE_WRITE8_MEMBER(fdc_write);
-
- void cpu_map(address_map &map);
+ void cpu_map(address_map &map) ATTR_COLD;
required_device<cpu_device> m_cpu;
required_device<i8291a_device> m_i8291a;
diff --git a/src/devices/bus/ieee488/hp9133.cpp b/src/devices/bus/ieee488/hp9133.cpp
new file mode 100644
index 00000000000..c68d5198c38
--- /dev/null
+++ b/src/devices/bus/ieee488/hp9133.cpp
@@ -0,0 +1,879 @@
+// license:BSD-3-Clause
+// copyright-holders: Sven Schnelle
+/*********************************************************************
+
+ hp9133.cpp
+
+ HP9133 hard disk/floppy drive
+
+*********************************************************************/
+
+#include "emu.h"
+#include "hp9133.h"
+
+#include "ieee488.h"
+
+#include "cpu/m6809/m6809.h"
+#include "machine/i8291a.h"
+#include "machine/wd2010.h"
+#include "machine/wd_fdc.h"
+#include "imagedev/floppy.h"
+#include "imagedev/harddriv.h"
+
+#include <algorithm>
+
+//#define VERBOSE 1
+#include "logmacro.h"
+
+namespace {
+
+class hp9133_device : public device_t,
+ public device_ieee488_interface
+{
+public:
+ // construction/destruction
+ hp9133_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
+
+protected:
+ // device_t implementation
+ virtual void device_start() override ATTR_COLD;
+ virtual void device_reset() override ATTR_COLD;
+ virtual ioport_constructor device_input_ports() const override ATTR_COLD;
+ virtual const tiny_rom_entry *device_rom_region() const override ATTR_COLD;
+ virtual void device_add_mconfig(machine_config &config) override ATTR_COLD;
+
+ // device_ieee488_interface implementation
+ virtual void ieee488_eoi(int state) override;
+ virtual void ieee488_dav(int state) override;
+ virtual void ieee488_nrfd(int state) override;
+ virtual void ieee488_ndac(int state) override;
+ virtual void ieee488_ifc(int state) override;
+ virtual void ieee488_srq(int state) override;
+ virtual void ieee488_atn(int state) override;
+ virtual void ieee488_ren(int state) override;
+
+private:
+ static constexpr int IO1_R_BCS_N = 0x10;
+ static constexpr int IO1_R_BDRQ = 0x20;
+ static constexpr int IO1_R_HDINT = 0x40;
+ static constexpr int IO1_R_HDIND = 0x80;
+
+ static constexpr int IO2_R_FDCINT = 0x10;
+ static constexpr int IO2_R_FDKDCH_N = 0x20;
+ static constexpr int IO2_R_WRTFLTERR = 0x80;
+
+ static constexpr int IO3_R_FASTDON = 0x20;
+ static constexpr int IO3_R_SELTST = 0x40;
+ static constexpr int IO3_R_TEST = 0x80;
+
+ static constexpr int IO1_W_FLT_N = 0x01;
+ static constexpr int IO1_W_DS1 = 0x02;
+ static constexpr int IO1_W_BRDY = 0x40;
+ static constexpr int IO1_W_WDRESET_N = 0x80;
+
+ static constexpr int IO2_W_FDCRES_N = 0x01;
+ static constexpr int IO2_W_CLRIND_N = 0x04;
+ static constexpr int IO2_W_DKCHRES_N = 0x08;
+ static constexpr int IO2_W_FDHDLD_N = 0x10;
+ static constexpr int IO2_W_FDMOTON_N = 0x20;
+ static constexpr int IO2_W_FDHDSEL_N = 0x40;
+
+ static constexpr int IO3_W_INTSEL_MASK = 0x03;
+ static constexpr int IO3_W_INTENBL_N = 0x04;
+ static constexpr int IO3_W_FAST = 0x10;
+ static constexpr int IO3_W_DMAR_W_N = 0x20;
+ static constexpr int IO3_W_HPB_FDC_N = 0x40;
+ static constexpr int IO3_W_DMA = 0x80;
+
+ required_device<mc6809_device> m_cpu;
+ required_device<i8291a_device> m_gpib;
+ required_device<wd2010_device> m_hdc;
+ required_device<harddisk_image_device> m_harddisk;
+ required_device<wd2793_device> m_fdc;
+ required_device<floppy_connector> m_floppy;
+ required_ioport m_hpib_addr;
+ required_ioport m_selftest;
+ required_ioport m_selftesten;
+ required_ioport m_volcfg;
+ required_ioport m_model;
+
+ TIMER_CALLBACK_MEMBER(floppy_motor_timeout);
+ TIMER_CALLBACK_MEMBER(index_timer);
+ TIMER_CALLBACK_MEMBER(fast_timer);
+
+ 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);
+ void i8291a_dio_w(uint8_t data);
+ void i8291a_int_w(int state);
+ void i8291a_drq_w(int state);
+ void fdc_intrq_w(int state);
+ void fdc_drq_w(int state);
+ void hdc_reg_w(offs_t offset, uint8_t data);
+ uint8_t hdc_reg_r(offs_t offset);
+ uint8_t i8291a_dio_r();
+ void io1_w(uint8_t data);
+ void io2_w(uint8_t data);
+ void io3_w(uint8_t data);
+ uint8_t io1_r();
+ uint8_t io2_r();
+ uint8_t io3_r();
+
+ void dma_ram_w(uint8_t data);
+ uint8_t dma_ram_r(offs_t offset);
+ void cpu_map(address_map &map) ATTR_COLD;
+ void floppy_index_cb(floppy_image_device *floppy, int state);
+ void hdc_bcs_cb(int state);
+ void hdc_bcr_cb(int state);
+ void hdc_bdrq_cb(int state);
+ void hdc_intrq_cb(int state);
+ void hdc_wg_cb(int state);
+ void hdc_readwrite_sector(bool write);
+ void update_intsel();
+ void cpu_sync_ack(int state);
+
+ emu_timer *m_motor_timer;
+ emu_timer *m_index_timer;
+ emu_timer *m_fast_timer;
+ uint8_t m_dma_ram[2048];
+ int m_dma_addr;
+ int m_intsel;
+ int m_head;
+
+ bool m_harddisk_index;
+ bool m_floppy_index_int;
+ bool m_intenable;
+ bool m_dmaenable;
+ bool m_dmaack_switch;
+ bool m_dma_rwn;
+ bool m_gpib_irq;
+ bool m_gpib_drq;
+ bool m_fdc_irq;
+ bool m_fdc_drq;
+ bool m_cpuirq;
+ bool m_cpufirq;
+ bool m_hdc_intrq;
+ bool m_hdc_bdrq;
+ bool m_hdc_bcs;
+ bool m_hdc_wg;
+ bool m_fast;
+
+ uint16_t m_hdc_cylinder;
+ uint8_t m_hdc_sdh;
+ uint8_t m_hdc_sector_count;
+ uint8_t m_hdc_sector_number;
+ uint8_t m_hdc_cmd;
+};
+
+hp9133_device::hp9133_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) :
+ device_t{mconfig, HP9133, tag, owner, clock},
+ device_ieee488_interface{mconfig, *this},
+ m_cpu{*this, "cpu"},
+ m_gpib{*this, "i8291a"},
+ m_hdc{*this, "wd2010"},
+ m_harddisk{*this, "harddisk"},
+ m_fdc{*this, "wd2793"},
+ m_floppy{*this, "floppy0"},
+ m_hpib_addr{*this, "ADDRESS"},
+ m_selftest{*this, "SELFTEST"},
+ m_selftesten{*this, "SELFTESTEN"},
+ m_volcfg{*this, "VOLCFG"},
+ m_model{*this, "MODEL"}
+{
+}
+
+static INPUT_PORTS_START(hp9133_port)
+ PORT_START("ADDRESS")
+ PORT_CONFNAME(0xf, 0x00, "HPIB address")
+ PORT_CONFSETTING(0, "0")
+ PORT_CONFSETTING(1, "1")
+ PORT_CONFSETTING(2, "2")
+ PORT_CONFSETTING(3, "3")
+ PORT_CONFSETTING(4, "4")
+ PORT_CONFSETTING(5, "5")
+ PORT_CONFSETTING(6, "6")
+ PORT_CONFSETTING(7, "7")
+ PORT_CONFSETTING(8, "8")
+ PORT_CONFSETTING(9, "9")
+ PORT_CONFSETTING(10, "10")
+ PORT_CONFSETTING(11, "11")
+ PORT_CONFSETTING(12, "12")
+ PORT_CONFSETTING(13, "13")
+ PORT_CONFSETTING(14, "14")
+ PORT_CONFSETTING(15, "15")
+
+ PORT_START("SELFTESTEN")
+ PORT_CONFNAME(0x1, 0x00, "Selftest Enable")
+ PORT_CONFSETTING(0x0, DEF_STR(Off))
+ PORT_CONFSETTING(0x1, DEF_STR(On))
+
+ PORT_START("SELFTEST")
+ PORT_CONFNAME(0xf, 0x00, "Selftest")
+ PORT_CONFSETTING(0x0, "RAM")
+ PORT_CONFSETTING(0x1, "ROM checksum")
+ PORT_CONFSETTING(0x2, "GPIB")
+ PORT_CONFSETTING(0x3, "FDC Chip")
+ PORT_CONFSETTING(0x4, "Floppy Seek")
+ PORT_CONFSETTING(0x5, "Winchester Seek")
+ PORT_CONFSETTING(0x6, "Floppy Speed")
+ PORT_CONFSETTING(0x7, "Winchester Speed")
+ PORT_CONFSETTING(0x8, "Floppy Write Verify")
+ PORT_CONFSETTING(0x9, "Winchester Write Verify")
+ PORT_CONFSETTING(0xa, "Floppy Verify")
+ PORT_CONFSETTING(0xb, "Winchester Verify")
+ PORT_CONFSETTING(0xc, "Floppy format")
+ PORT_CONFSETTING(0xd, "HDC Check")
+ PORT_CONFSETTING(0xe, "WD1100 Check")
+ PORT_CONFSETTING(0xf, "WD1100 Buffer RAM")
+
+ PORT_START("VOLCFG")
+ PORT_CONFNAME(0x0f, 0x00, "Volume config")
+ PORT_CONFSETTING(0, "0")
+ PORT_CONFSETTING(1, "1")
+ PORT_CONFSETTING(2, "2")
+ PORT_CONFSETTING(3, "3")
+ PORT_CONFSETTING(4, "4")
+ PORT_CONFSETTING(5, "5")
+ PORT_CONFSETTING(6, "6")
+ PORT_CONFSETTING(7, "7")
+ PORT_CONFSETTING(8, "8")
+ PORT_CONFSETTING(9, "9")
+
+ PORT_START("MODEL")
+ PORT_CONFNAME(0x03, 0x00, "Disc Model")
+ PORT_CONFSETTING(0x0, "9133D")
+ PORT_CONFSETTING(0x1, "9133L")
+ PORT_CONFSETTING(0x2, "9133H")
+INPUT_PORTS_END
+
+ioport_constructor hp9133_device::device_input_ports() const
+{
+ return INPUT_PORTS_NAME(hp9133_port);
+}
+
+TIMER_CALLBACK_MEMBER(hp9133_device::floppy_motor_timeout)
+{
+ auto *floppy = m_floppy->get_device();
+
+ floppy->mon_w(1);
+}
+
+void hp9133_device::device_start()
+{
+ save_item(NAME(m_dma_ram));
+ save_item(NAME(m_dma_addr));
+ save_item(NAME(m_head));
+ save_item(NAME(m_intsel));
+ save_item(NAME(m_harddisk_index));
+ save_item(NAME(m_floppy_index_int));
+ save_item(NAME(m_intenable));
+ save_item(NAME(m_dmaenable));
+ save_item(NAME(m_dmaack_switch));
+ save_item(NAME(m_dma_rwn));
+ save_item(NAME(m_gpib_irq));
+ save_item(NAME(m_gpib_drq));
+ save_item(NAME(m_fdc_irq));
+ save_item(NAME(m_fdc_drq));
+ save_item(NAME(m_cpuirq));
+ save_item(NAME(m_cpufirq));
+ save_item(NAME(m_hdc_intrq));
+ save_item(NAME(m_hdc_bdrq));
+ save_item(NAME(m_hdc_bcs));
+ save_item(NAME(m_hdc_wg));
+ save_item(NAME(m_fast));
+ save_item(NAME(m_hdc_cylinder));
+ save_item(NAME(m_hdc_sdh));
+ save_item(NAME(m_hdc_sector_count));
+ save_item(NAME(m_hdc_sector_number));
+ save_item(NAME(m_hdc_cmd));
+
+ // HP firmware tests whether ECC errors are detected. MAME's WD2010
+ // doesn't emulate ECC so patch the ROM to ignore the ECC test result.
+ uint8_t *rom = memregion("cpu")->base();
+ rom[0x279e] = 0x12;
+ rom[0x279f] = 0x12;
+ // disable ROM checksum
+ rom[0x36ea] = 0x20;
+
+ m_motor_timer = timer_alloc(FUNC(hp9133_device::floppy_motor_timeout), this);
+ m_index_timer = timer_alloc(FUNC(hp9133_device::index_timer), this);
+ m_index_timer->adjust(attotime::from_hz(3600 / 60));
+ m_fast_timer = timer_alloc(FUNC(hp9133_device::fast_timer), this);
+ auto *floppy = m_floppy->get_device();
+ floppy->setup_index_pulse_cb(floppy_image_device::index_pulse_cb(&hp9133_device::floppy_index_cb, this));
+}
+
+void hp9133_device::device_reset()
+{
+ std::fill(std::begin(m_dma_ram), std::end(m_dma_ram), 0);
+ m_dma_addr = 0;
+ m_intsel = 0;
+ m_head = 0;
+ m_harddisk_index = false;
+ m_floppy_index_int = false;
+ m_intenable = false;
+ m_dmaenable = false;
+ m_dmaack_switch = false;
+ m_dma_rwn = false;
+ m_gpib_irq = false;
+ m_gpib_drq = false;
+ m_fdc_irq = false;
+ m_fdc_drq = false;
+ m_cpuirq = false;
+ m_cpufirq = false;
+ m_hdc_intrq = false;
+ m_hdc_bdrq = false;
+ m_hdc_bcs = false;
+ m_hdc_wg = false;
+ m_fast = false;
+ m_fdc->set_floppy(m_floppy->get_device());
+}
+
+void hp9133_device::ieee488_eoi(int state)
+{
+ m_gpib->eoi_w(state);
+}
+
+void hp9133_device::ieee488_dav(int state)
+{
+ m_gpib->dav_w(state);
+}
+
+void hp9133_device::ieee488_nrfd(int state)
+{
+ m_gpib->nrfd_w(state);
+}
+
+void hp9133_device::ieee488_ndac(int state)
+{
+ m_gpib->ndac_w(state);
+}
+
+void hp9133_device::ieee488_srq(int state)
+{
+ m_gpib->srq_w(state);
+}
+
+void hp9133_device::ieee488_ifc(int state)
+{
+ m_gpib->ifc_w(state);
+}
+
+void hp9133_device::ieee488_atn(int state)
+{
+ m_gpib->atn_w(state);
+}
+
+void hp9133_device::ieee488_ren(int state)
+{
+ m_gpib->ren_w(state);
+}
+
+void hp9133_device::i8291a_eoi_w(int state)
+{
+ m_bus->eoi_w(this, state);
+}
+
+void hp9133_device::i8291a_dav_w(int state)
+{
+ m_bus->dav_w(this, state);
+}
+
+void hp9133_device::i8291a_nrfd_w(int state)
+{
+ m_bus->nrfd_w(this, state);
+}
+
+void hp9133_device::i8291a_ndac_w(int state)
+{
+ m_bus->ndac_w(this, state);
+}
+
+void hp9133_device::i8291a_srq_w(int state)
+{
+ m_bus->srq_w(this, state);
+}
+
+void hp9133_device::i8291a_int_w(int state)
+{
+ LOG("%s: %d\n", __func__, state);
+ m_gpib_irq = state;
+ update_intsel();
+}
+
+uint8_t hp9133_device::i8291a_dio_r()
+{
+ uint8_t ret = m_bus->dio_r();
+ LOG("%s: %02x\n", __func__, (uint8_t)~ret);
+ return ret;
+}
+
+void hp9133_device::i8291a_dio_w(uint8_t data)
+{
+ m_bus->dio_w(this, data);
+}
+
+void hp9133_device::i8291a_drq_w(int state)
+{
+ LOG("%s: %d\n", __func__, state);
+ m_gpib_drq = state;
+ update_intsel();
+}
+
+TIMER_CALLBACK_MEMBER(hp9133_device::index_timer)
+{
+ attotime next = attotime::from_hz(3600 / 60);
+
+ m_harddisk_index ^= true;
+ if (!m_harddisk_index)
+ next /= 10;
+ else
+ next -= next / 10;
+ m_index_timer->adjust(next);
+}
+
+void hp9133_device::cpu_sync_ack(int state)
+{
+ LOG("%s: %d: enabled %d\n", __func__, state, m_dmaenable);
+ if (!m_dmaenable)
+ return;
+ if (state) {
+ if (m_gpib_drq)
+ m_cpu->set_input_line(M6809_IRQ_LINE, ASSERT_LINE);
+ } else {
+ uint8_t data;
+ if (!m_dma_rwn) {
+ data = dma_ram_r(0);
+ m_gpib->dout_w(data);
+ } else {
+ data = m_gpib->din_r();
+ dma_ram_w(data);
+ }
+ m_cpu->set_input_line(M6809_IRQ_LINE, CLEAR_LINE);
+ LOG("%s: sync data: %02x\n", __func__, data);
+ if (m_dma_addr > 256) {
+ LOG("DMA: all bytes transferred\n");
+ m_dmaenable = false;
+ }
+ }
+}
+
+void hp9133_device::update_intsel()
+{
+ bool irq = false, firq = false;
+
+ // IRQ Multiplexing:
+ // +--------+----------+-----------+-------------------+---------+
+ // | INTSEL | 0 | 1 | 2 | 3 |
+ // +--------+----------+-+---------+-------------------+---------+
+ // | IRQ# | GPIBDREQ | GND | DMASYNC | FDCDREQ |
+ // | FIRQ# | GPIBINT | INDEXINT | FDCINT || GPIBINT | FDCINT |
+ // +--------+---------+-----------+-------------------+----------+
+ switch (m_intsel) {
+ case 0:
+ irq = m_gpib_drq;
+ firq = m_gpib_irq;
+ break;
+ case 1:
+ irq = false;
+ firq = m_floppy_index_int;
+ break;
+ case 2:
+ irq = (m_dmaenable && m_gpib_drq);
+ firq = m_fdc_irq || m_gpib_irq;
+ break;
+ case 3:
+ irq = m_fdc_drq;
+ firq = m_fdc_irq;
+ break;
+ }
+
+ if (!m_intenable) {
+ irq = false;
+ firq = false;
+ }
+
+ if (m_cpuirq != irq) {
+ m_cpu->set_input_line(M6809_IRQ_LINE, irq ? ASSERT_LINE : CLEAR_LINE);
+ m_cpuirq = irq;
+ }
+
+ if (m_cpufirq != firq) {
+ m_cpu->set_input_line(M6809_FIRQ_LINE, firq ? ASSERT_LINE : CLEAR_LINE);
+ m_cpufirq = firq;
+ }
+}
+
+TIMER_CALLBACK_MEMBER(hp9133_device::fast_timer)
+{
+ if (!m_fast)
+ return;
+ if (m_gpib_drq) {
+ if (!m_dma_rwn)
+ m_gpib->dout_w(dma_ram_r(0));
+ else
+ dma_ram_w(m_gpib->din_r());
+ }
+ m_fast_timer->adjust(attotime::from_usec(50));
+}
+
+void hp9133_device::io1_w(uint8_t data)
+{
+ // 7 - HDC Rst#
+ // 6 - HDC BRDY
+ // 5 - HD Precomp#
+ // 4 - HD Head 2
+ // 3 - HD Head 1
+ // 2 - HD Head 0
+ // 1 - Active LED
+ // 0 - Fault LED#
+ m_head = (data >> 2) & 7;
+ LOG("%s: %02x Head %d %s%s%s%s\n", __func__,
+ data, m_head,
+ (data & IO1_W_BRDY) ? "BRDY " : "",
+ (data & IO1_W_WDRESET_N) ? "" : "HDCRESET ",
+ (data & IO1_W_DS1) ? "ACTIVE " : "",
+ (data & IO1_W_FLT_N) ? "" : "FAULT ");
+ if (!(data & IO1_W_WDRESET_N))
+ m_hdc->reset();
+ m_hdc->buffer_ready(data & IO1_W_BRDY);
+}
+
+void hp9133_device::io2_w(uint8_t data)
+{
+ auto *floppy = m_floppy->get_device();
+
+ // 7 - HDRecMode
+ // 6 - FlopHLO#?
+ // 5 - FlopMotor#
+ // 4 - FlopSide#
+ // 3 - Floppy Disk change reset
+ // 2 - ClrIdxInt
+ // 1
+ // 0 - FDCRst#
+ LOG("%s: %02x\n", __func__, data);
+ if (!(data & IO2_W_CLRIND_N))
+ m_floppy_index_int = false;
+ if (data & IO2_W_FDMOTON_N) {
+ m_motor_timer->adjust(attotime::from_msec(2000));
+ } else {
+ m_motor_timer->reset();
+ floppy->mon_w(0);
+ }
+ if (!(data & IO2_W_DKCHRES_N))
+ m_floppy->get_device()->dskchg_w(false);
+ m_floppy->get_device()->ss_w((data & IO2_W_FDHDSEL_N) ? 0 : 1);
+ if (!(data & IO2_W_FDCRES_N))
+ m_fdc->reset();
+}
+
+void hp9133_device::io3_w(uint8_t data)
+{
+ // 7 - DMA enable
+ // 6 - 1 GPIPACK, 0 FDCACK
+ // 5 - Write Precomp?
+ // 4 - FAST enable?
+ // 3 -
+ // 2 - Interrupt Enable
+ // 0:1 - Interrupt select
+
+ m_dmaenable = data & IO3_W_DMA;
+ m_dmaack_switch = data & IO3_W_HPB_FDC_N;
+ m_dma_rwn = data & IO3_W_DMAR_W_N;
+ m_intenable = !(data & IO3_W_INTENBL_N);
+ m_fast = data & IO3_W_FAST;
+ m_intsel = data & IO3_W_INTSEL_MASK;
+
+ LOG("%s: %02x = INTSEL %d, INT %d DMA %d DMA start %d DMA ACK %s\n", __func__,
+ data, m_intsel, m_intenable, m_dmaenable, BIT(data, 4),
+ m_dmaack_switch ? "GPIB" : "FDC");
+ update_intsel();
+ if (m_fast)
+ m_fast_timer->adjust(attotime::from_usec(1000));
+ else
+ m_fast_timer->adjust(attotime::never);
+}
+
+uint8_t hp9133_device::io1_r()
+{
+ uint8_t ret;
+
+ // 7 - hdindex
+ // 6 - HDC int
+ // 5 - HDC DRQ
+ // 4 - HDC BCS
+ // 3 - 0 Ident
+ ret = m_model->read() ^ 0xf;
+ if (m_harddisk_index)
+ ret |= IO1_R_HDIND;
+ if (m_hdc_intrq)
+ ret |= IO1_R_HDINT;
+ if (m_hdc_bdrq)
+ ret |= IO1_R_BDRQ;
+ if (m_hdc_bcs)
+ ret |= IO1_R_BCS_N;
+ if (!machine().side_effects_disabled())
+ LOG("%s: %02x\n", __func__, ret);
+ return ret;
+}
+
+uint8_t hp9133_device::io2_r()
+{
+ uint8_t ret = 0;
+
+ // 7 - Write Fault Latch
+ // 5 - FlopDC#
+ // 4 - FDC interrupt
+ // 3 - 0 GPIB Address
+
+ if (m_selftesten->read()) {
+ ret = (m_selftest->read() & 7) ^ 0xf;
+ } else {
+ ret = m_hpib_addr->read() ^ 0xf;
+ }
+ if (m_fdc_irq)
+ ret |= IO2_R_FDCINT;
+ if (!m_floppy->get_device()->dskchg_r())
+ ret |= IO2_R_FDKDCH_N;
+ if (!machine().side_effects_disabled())
+ LOG("%s: %02x\n", __func__, ret);
+ return ret;
+}
+
+uint8_t hp9133_device::io3_r()
+{
+ uint8_t ret = 0;
+
+ // 7 - self test enable
+ // 6 - self test MSB
+ // 5 - FASTDON
+ // 3-0 Volume switch
+ ret = m_volcfg->read() ^ 0xf;
+ if (!m_selftesten->read()) {
+ ret |= IO3_R_TEST;
+ } else {
+ if (m_selftest->read() & 8)
+ ret |= IO3_R_SELTST;
+ }
+
+ if (m_dma_addr >= 256)
+ ret |= IO3_R_FASTDON;
+ if (!machine().side_effects_disabled())
+ LOG("%s: %02x\n", __func__, ret);
+ return ret;
+}
+
+void hp9133_device::dma_ram_w(uint8_t data)
+{
+ LOG("%s: %03x = %02x\n", __func__, m_dma_addr, data);
+ if (m_dma_addr < sizeof(m_dma_ram))
+ m_dma_ram[m_dma_addr++] = data;
+}
+
+uint8_t hp9133_device::dma_ram_r(offs_t offset)
+{
+ if (m_dma_addr >= sizeof(m_dma_ram))
+ return 0;
+ uint8_t ret = m_dma_ram[m_dma_addr];
+ if (!machine().side_effects_disabled()) {
+ LOG("%s: %03x = %02x\n", __func__, m_dma_addr, ret);
+ m_dma_addr++;
+ }
+ return ret;
+}
+
+static int sdh_sector_size(uint8_t sdh)
+{
+ constexpr int sizes[4] = { 256, 512, 1024, 128 };
+
+ return sizes[(sdh >> 5) & 3];
+}
+
+static int sdh_devsel(uint8_t sdh)
+{
+ return (sdh >> 3) & 3;
+}
+
+void hp9133_device::hdc_readwrite_sector(bool write)
+{
+ int sector = m_hdc->read(3);
+ uint32_t lba;
+
+ if (sdh_devsel(m_hdc_sdh))
+ return;
+ if (sdh_sector_size(m_hdc_sdh) != 256)
+ return;
+ if (!m_harddisk->exists())
+ return;
+ const auto &info = m_harddisk->get_info();
+ lba = (m_hdc_cylinder * info.heads + m_head) * info.sectors + sector;
+ LOG("%s: %s cyl %4d, head %d, sector %2d lba %8d\n", __func__,
+ write ? "WRITE" : "READ ", m_hdc_cylinder, m_head, sector, lba);
+ if (write) {
+ m_harddisk->write(lba, m_dma_ram);
+ } else {
+ m_harddisk->read(lba, m_dma_ram);
+ m_dma_addr = 256;
+ }
+}
+
+void hp9133_device::fdc_intrq_w(int state)
+{
+ m_fdc_irq = state;
+ update_intsel();
+}
+
+void hp9133_device::fdc_drq_w(int state)
+{
+ m_fdc_drq = state;
+ update_intsel();
+}
+
+void hp9133_device::floppy_index_cb(floppy_image_device *floppy, int state)
+{
+ m_fdc->index_callback(floppy, state);
+ if (state)
+ m_floppy_index_int = true;
+ update_intsel();
+}
+
+void hp9133_device::hdc_bcs_cb(int state)
+{
+ m_hdc_bcs = state;
+}
+
+void hp9133_device::hdc_bcr_cb(int state)
+{
+ m_dma_addr = 0;
+}
+
+void hp9133_device::hdc_bdrq_cb(int state)
+{
+ bool is_read = m_hdc_cmd >> 4 == 2;
+
+ m_hdc_bdrq = state;
+ if (state && is_read)
+ hdc_readwrite_sector(false);
+}
+
+
+void hp9133_device::hdc_wg_cb(int state)
+{
+ bool is_write = (m_hdc_cmd >> 4) == 3;
+
+ m_hdc_wg = state;
+ if (state && is_write)
+ hdc_readwrite_sector(true);
+}
+
+void hp9133_device::hdc_intrq_cb(int state)
+{
+ m_hdc_intrq = state;
+ update_intsel();
+}
+
+uint8_t hp9133_device::hdc_reg_r(offs_t offset)
+{
+ return m_hdc->read(offset);
+}
+
+void hp9133_device::hdc_reg_w(offs_t offset, uint8_t data)
+{
+ switch (offset) {
+ case 2:
+ m_hdc_sector_count = data;
+ break;
+ case 3:
+ m_hdc_sector_number = data;
+ break;
+ case 4:
+ m_hdc_cylinder &= ~0xff;
+ m_hdc_cylinder |= data;
+ break;
+ case 5:
+ m_hdc_cylinder &= ~0xff00;
+ m_hdc_cylinder |= data << 8;
+ break;
+ case 6:
+ m_hdc_sdh = data;
+ break;
+ case 7:
+ m_hdc_cmd = data;
+ break;
+ }
+ m_hdc->write(offset, data);
+}
+
+void hp9133_device::cpu_map(address_map &map)
+{
+ map(0x0000, 0x0007).m(m_gpib, FUNC(i8291a_device::map));
+ map(0x0008, 0x000b).rw(m_fdc, FUNC(wd2793_device::read), FUNC(wd2793_device::write));
+ map(0x0010, 0x0017).rw(FUNC(hp9133_device::hdc_reg_r), FUNC(hp9133_device::hdc_reg_w));
+ map(0x0020, 0x0027).rw(FUNC(hp9133_device::dma_ram_r), FUNC(hp9133_device::dma_ram_w));
+ map(0x0028, 0x002f).lw8(NAME([this] (u8 data) { LOG("clear ram addr\n"); m_dma_addr = 0; }));
+ map(0x003f, 0x003f).nopw();
+ map(0x0040, 0x0040).rw(FUNC(hp9133_device::io1_r), FUNC(hp9133_device::io1_w)).mirror(0x3f3f);
+ map(0x0080, 0x0080).rw(FUNC(hp9133_device::io2_r), FUNC(hp9133_device::io2_w)).mirror(0x3f3f);
+ map(0x00c0, 0x00c0).rw(FUNC(hp9133_device::io3_r), FUNC(hp9133_device::io3_w)).mirror(0x3f3f);
+ map(0x4000, 0x47ff).ram().mirror(0x3800);
+ map(0x8000, 0xffff).rom().region("cpu", 0);
+}
+
+static void hp9133_floppies(device_slot_interface &device)
+{
+ device.option_add("d32w", SONY_OA_D32W);
+}
+
+void hp9133_device::device_add_mconfig(machine_config &config)
+{
+ MC6809(config, m_cpu, XTAL(8'000'000));
+ m_cpu->set_addrmap(AS_PROGRAM, &hp9133_device::cpu_map);
+ m_cpu->sync_acknowledge_write().set(FUNC(hp9133_device::cpu_sync_ack));
+
+ I8291A(config, m_gpib, XTAL(8'000'000));
+ m_gpib->eoi_write().set(FUNC(hp9133_device::i8291a_eoi_w));
+ m_gpib->dav_write().set(FUNC(hp9133_device::i8291a_dav_w));
+ m_gpib->nrfd_write().set(FUNC(hp9133_device::i8291a_nrfd_w));
+ m_gpib->ndac_write().set(FUNC(hp9133_device::i8291a_ndac_w));
+ m_gpib->srq_write().set(FUNC(hp9133_device::i8291a_srq_w));
+ m_gpib->dio_write().set(FUNC(hp9133_device::i8291a_dio_w));
+ m_gpib->dio_read().set(FUNC(hp9133_device::i8291a_dio_r));
+ m_gpib->int_write().set(FUNC(hp9133_device::i8291a_int_w));
+ m_gpib->dreq_write().set(FUNC(hp9133_device::i8291a_drq_w));
+
+ WD2010(config, m_hdc, XTAL(5'000'000));
+ m_hdc->in_sc_callback().set_constant(1);
+ m_hdc->in_drdy_callback().set_constant(1);
+ m_hdc->out_bcs_callback().set(FUNC(hp9133_device::hdc_bcs_cb));
+ m_hdc->out_bcr_callback().set(FUNC(hp9133_device::hdc_bcr_cb));
+ m_hdc->out_bdrq_callback().set(FUNC(hp9133_device::hdc_bdrq_cb));
+ m_hdc->out_intrq_callback().set(FUNC(hp9133_device::hdc_intrq_cb));
+ m_hdc->out_wg_callback().set(FUNC(hp9133_device::hdc_wg_cb));
+ HARDDISK(config, m_harddisk);
+
+ WD2793(config, m_fdc, XTAL(2'000'000));
+ m_fdc->intrq_wr_callback().set(FUNC(hp9133_device::fdc_intrq_w));
+ m_fdc->drq_wr_callback().set(FUNC(hp9133_device::fdc_drq_w));
+ FLOPPY_CONNECTOR(config, "floppy0", hp9133_floppies, "d32w",
+ floppy_image_device::default_mfm_floppy_formats, true).enable_sound(true);
+}
+
+ROM_START(hp9133)
+ ROM_REGION(0x8000, "cpu", 0)
+ ROM_LOAD("09133-89110_9133.bin", 0x0000, 0x4000, CRC(d7ff6b3e) SHA1(aeeae063fa43c3b163ba5c176f31df6ec1b73d0d))
+ ROM_LOAD("09133-89210_9133.bin", 0x4000, 0x4000, CRC(08f825e2) SHA1(61766b1f64473c17f01cbc97bd817f6076827d6a))
+ROM_END
+
+const tiny_rom_entry *hp9133_device::device_rom_region() const
+{
+ return ROM_NAME(hp9133);
+}
+
+} // anonymous namespace
+
+DEFINE_DEVICE_TYPE_PRIVATE(HP9133, device_ieee488_interface, hp9133_device, "hp9133", "HP9133 Floppy/Fixed disk drive")
diff --git a/src/devices/bus/ieee488/hp9133.h b/src/devices/bus/ieee488/hp9133.h
new file mode 100644
index 00000000000..b137596c004
--- /dev/null
+++ b/src/devices/bus/ieee488/hp9133.h
@@ -0,0 +1,18 @@
+// license:BSD-3-Clause
+// copyright-holders: Sven Schnelle
+/*********************************************************************
+
+ hp9133.h
+
+ HP9133 Fixed disk drive
+
+*********************************************************************/
+
+#ifndef MAME_BUS_IEEE488_HP9133_H
+#define MAME_BUS_IEEE488_HP9133_H
+
+#pragma once
+
+DECLARE_DEVICE_TYPE(HP9133, device_ieee488_interface)
+
+#endif // MAME_BUS_IEEE488_HP9133_H
diff --git a/src/devices/bus/ieee488/hp9895.cpp b/src/devices/bus/ieee488/hp9895.cpp
index 2e15e9d4279..ffc7ae29d70 100644
--- a/src/devices/bus/ieee488/hp9895.cpp
+++ b/src/devices/bus/ieee488/hp9895.cpp
@@ -56,13 +56,14 @@
#include "emu.h"
#include "hp9895.h"
+#include "formats/fs_hp98x5.h"
#include "formats/hpi_dsk.h"
-// Debugging
-#define VERBOSE 1
-#define LOG(x) do { if (VERBOSE) logerror x; } while (0)
-#define VERBOSE_0 0
-#define LOG_0(x) do { if (VERBOSE_0) logerror x; } while (0)
+#define LOG_LEVEL0 (0x1U << 1)
+#define LOG_LEVEL1 (0x3U << 1)
+
+#define VERBOSE (LOG_LEVEL1)
+#include "logmacro.h"
// Macros to clear/set single bits
#define BIT_MASK(n) (1U << (n))
@@ -116,13 +117,6 @@
#define REG_SWITCHES_TIMEOUT_BIT 6 // TIMEOUT (1)
#define REG_SWITCHES_AMDT_BIT 7 // Address mark detected (1)
-// Timers
-enum {
- TIMEOUT_TMR_ID,
- BYTE_TMR_ID,
- HALF_BIT_TMR_ID
-};
-
// Timings
#define TIMEOUT_MSEC 450 // Timeout duration (ms)
#define HPMODE_BIT_FREQ 500000 // HP-mode bit frequency (Hz)
@@ -144,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"}
{
}
@@ -198,9 +192,9 @@ void hp9895_device::device_start()
save_item(NAME(m_hiden));
save_item(NAME(m_mgnena));
- m_timeout_timer = timer_alloc(TIMEOUT_TMR_ID);
- m_byte_timer = timer_alloc(BYTE_TMR_ID);
- m_half_bit_timer = timer_alloc(HALF_BIT_TMR_ID);
+ m_timeout_timer = timer_alloc(FUNC(hp9895_device::timeout_timer_tick), this);
+ m_byte_timer = timer_alloc(FUNC(hp9895_device::byte_timer_tick), this);
+ m_half_bit_timer = timer_alloc(FUNC(hp9895_device::half_bit_timer_tick), this);
for (auto& d : m_drives) {
d->get_device()->setup_ready_cb(floppy_image_device::ready_cb(&hp9895_device::floppy_ready_cb , this));
@@ -236,159 +230,150 @@ void hp9895_device::device_reset()
m_half_bit_timer->reset();
}
-void hp9895_device::device_timer(emu_timer &timer, device_timer_id id, int param, void *ptr)
+TIMER_CALLBACK_MEMBER(hp9895_device::timeout_timer_tick)
{
- switch (id) {
- case TIMEOUT_TMR_ID:
- LOG(("Timeout!\n"));
- m_timeout = true;
- if (m_mgnena) {
- // CPU is resumed by timeout if MGNENA=1
- m_cpu->trigger(1);
- }
- break;
+ LOGMASKED(LOG_LEVEL1, "Timeout\n");
+ m_timeout = true;
+ if (m_mgnena) {
+ // CPU is resumed by timeout if MGNENA=1
+ m_cpu->trigger(1);
+ }
+}
+
+TIMER_CALLBACK_MEMBER(hp9895_device::byte_timer_tick)
+{
+ if (m_accdata) {
+ // Resume CPU when it's waiting for SDOK
+ m_cpu->trigger(1);
+ } else {
+ // No access to data register by CPU
+ LOGMASKED(LOG_LEVEL1, "Data overrun\n");
+ m_overrun = true;
+ }
+ m_accdata = false;
- case BYTE_TMR_ID:
- {
- if (m_accdata) {
- // Resume CPU when it's waiting for SDOK
- m_cpu->trigger(1);
+ m_crcerr_syn = m_crc != 0;
+
+ if (!BIT(m_cntl_reg , REG_CNTL_CRCON_BIT)) {
+ // CRC not enabled, keep it in preset state (all ones)
+ preset_crc();
+ }
+
+ attotime sdok_time{machine().time()};
+ LOGMASKED(LOG_LEVEL0, "SDOK @ %.06f\n" , sdok_time.as_double());
+ bool do_crc_upd = true;
+ if (BIT(m_cntl_reg , REG_CNTL_WRITON_BIT)) {
+ // Writing
+ m_pll.commit(get_write_device() , sdok_time);
+ m_pll.ctime = sdok_time;
+
+ // Check for AMDT when in loopback mode
+ if (!m_lckup && !m_amdt && BIT(m_cntl_reg , REG_CNTL_READON_BIT)) {
+ if (m_hiden) {
+ m_amdt = m_data_sr != 0xff;
} else {
- // No access to data register by CPU
- LOG(("Data overrun!\n"));
- m_overrun = true;
+ m_amdt = m_data_sr != 0;
}
- m_accdata = false;
-
- m_crcerr_syn = m_crc != 0;
+ }
- if (!BIT(m_cntl_reg , REG_CNTL_CRCON_BIT)) {
- // CRC not enabled, keep it in preset state (all ones)
- preset_crc();
+ LOGMASKED(LOG_LEVEL0, "WR D=%02x/C=%02x\n" , m_data_sr , m_clock_sr);
+ do_crc_upd = false;
+ for (unsigned i = 0; i < 8; i++) {
+ bool clock_bit;
+ bool data_bit;
+
+ clock_bit = shift_sr(m_clock_sr, false);
+ data_bit = shift_sr(m_data_sr, true);
+
+ if (BIT(m_cntl_reg , REG_CNTL_CRCOUT_BIT)) {
+ // Substitute data bits from DSR with those from CRC when CRCOUT=1
+ data_bit = BIT(m_crc , 15);
+ m_crc <<= 1;
+ } else if (BIT(m_cntl_reg , REG_CNTL_CRCON_BIT)) {
+ // Update CRC
+ update_crc(data_bit);
}
+ write_bit(data_bit, clock_bit);
+ }
+ // When shifting is done DSR is filled with 1s and CSR with 0s
+ }
+ if (BIT(m_cntl_reg , REG_CNTL_READON_BIT)) {
+ // Reading
+ m_pll.ctime = sdok_time;
- attotime sdok_time{machine().time()};
- LOG_0(("SDOK @ %.06f\n" , sdok_time.as_double()));
- bool do_crc_upd = true;
+ for (unsigned i = 0; i < 8; i++) {
+ read_bit(do_crc_upd);
+ }
+ LOGMASKED(LOG_LEVEL0, "RD D=%02x/C=%02x\n" , m_data_sr , m_clock_sr);
+ }
+ LOGMASKED(LOG_LEVEL0, "next SDOK @ %.06f\n" , m_pll.ctime.as_double());
+ m_byte_timer->adjust(m_pll.ctime - sdok_time);
+}
+
+TIMER_CALLBACK_MEMBER(hp9895_device::half_bit_timer_tick)
+{
+ m_pll.ctime = machine().time();
+ if (m_lckup) {
+ // Trying to lock on synchronization bytes
+ attotime edge;
+ attotime tm;
+ get_next_transition(m_pll.ctime, edge);
+ bool half_bit0 = m_pll.feed_read_data(tm , edge , attotime::never);
+ get_next_transition(m_pll.ctime, edge);
+ bool half_bit1 = m_pll.feed_read_data(tm , edge , attotime::never);
+ if (half_bit0 == half_bit1) {
+ // If half bits are equal, no synch
+ LOGMASKED(LOG_LEVEL0, "Reset sync_cnt\n");
+ m_sync_cnt = 0;
+ } else if (++m_sync_cnt >= MIN_SYNC_BITS) {
+ // Synchronized, now wait for AM
+ LOGMASKED(LOG_LEVEL0, "Synchronized @ %.6f\n" , machine().time().as_double());
+ m_lckup = false;
if (BIT(m_cntl_reg , REG_CNTL_WRITON_BIT)) {
- // Writing
- m_pll.commit(get_write_device() , sdok_time);
- m_pll.ctime = sdok_time;
-
- // Check for AMDT when in loopback mode
- if (!m_lckup && !m_amdt && BIT(m_cntl_reg , REG_CNTL_READON_BIT)) {
- if (m_hiden) {
- m_amdt = m_data_sr != 0xff;
- } else {
- m_amdt = m_data_sr != 0;
- }
+ // When loopback is active, leave AM detection to byte timer as
+ // byte boundary is already synchronized
+ m_half_bit_timer->reset();
+ return;
+ } else {
+ // Align with bit cell
+ // Synchronization bits in HP mode: 32x 1s -> C/D bits = 01010101...
+ // Synchronization bits in IBM mode: 32x 0s -> C/D bits = 10101010...
+ if (m_hiden != half_bit1) {
+ // Discard 1/2 bit cell if synchronization achieved in the clock part
+ get_next_transition(m_pll.ctime, edge);
+ m_pll.feed_read_data(tm , edge , attotime::never);
}
-
- LOG_0(("WR D=%02x/C=%02x\n" , m_data_sr , m_clock_sr));
- do_crc_upd = false;
- for (unsigned i = 0; i < 8; i++) {
- bool clock_bit;
- bool data_bit;
-
- clock_bit = shift_sr(m_clock_sr, false);
- data_bit = shift_sr(m_data_sr, true);
-
- if (BIT(m_cntl_reg , REG_CNTL_CRCOUT_BIT)) {
- // Substitute data bits from DSR with those from CRC when CRCOUT=1
- data_bit = BIT(m_crc , 15);
- m_crc <<= 1;
- } else if (BIT(m_cntl_reg , REG_CNTL_CRCON_BIT)) {
- // Update CRC
- update_crc(data_bit);
- }
- write_bit(data_bit, clock_bit);
+ // Load CSR & DSR as they are after synchronization bits
+ if (m_hiden) {
+ m_clock_sr = 0;
+ m_data_sr = ~0;
+ } else {
+ m_clock_sr = ~0;
+ m_data_sr = 0;
}
- // When shifting is done DSR is filled with 1s and CSR with 0s
}
- if (BIT(m_cntl_reg , REG_CNTL_READON_BIT)) {
- // Reading
- m_pll.ctime = sdok_time;
-
- for (unsigned i = 0; i < 8; i++) {
- read_bit(do_crc_upd);
- }
- LOG_0(("RD D=%02x/C=%02x\n" , m_data_sr , m_clock_sr));
- }
- LOG_0(("next SDOK @ %.06f\n" , m_pll.ctime.as_double()));
- timer.adjust(m_pll.ctime - sdok_time);
}
- break;
-
- case HALF_BIT_TMR_ID:
- {
- m_pll.ctime = machine().time();
- if (m_lckup) {
- // Trying to lock on synchronization bytes
- attotime edge;
- attotime tm;
- get_next_transition(m_pll.ctime, edge);
- bool half_bit0 = m_pll.feed_read_data(tm , edge , attotime::never);
- get_next_transition(m_pll.ctime, edge);
- bool half_bit1 = m_pll.feed_read_data(tm , edge , attotime::never);
- if (half_bit0 == half_bit1) {
- // If half bits are equal, no synch
- LOG_0(("Reset sync_cnt\n"));
- m_sync_cnt = 0;
- } else if (++m_sync_cnt >= MIN_SYNC_BITS) {
- // Synchronized, now wait for AM
- LOG_0(("Synchronized @ %.6f\n" , machine().time().as_double()));
- m_lckup = false;
- if (BIT(m_cntl_reg , REG_CNTL_WRITON_BIT)) {
- // When loopback is active, leave AM detection to byte timer as
- // byte boundary is already synchronized
- timer.reset();
- return;
- } else {
- // Align with bit cell
- // Synchronization bits in HP mode: 32x 1s -> C/D bits = 01010101...
- // Synchronization bits in IBM mode: 32x 0s -> C/D bits = 10101010...
- if (m_hiden != half_bit1) {
- // Discard 1/2 bit cell if synchronization achieved in the clock part
- get_next_transition(m_pll.ctime, edge);
- m_pll.feed_read_data(tm , edge , attotime::never);
- }
- // Load CSR & DSR as they are after synchronization bits
- if (m_hiden) {
- m_clock_sr = 0;
- m_data_sr = ~0;
- } else {
- m_clock_sr = ~0;
- m_data_sr = 0;
- }
- }
- }
- } else {
- // Looking for AM
- /// CRC is not updated because it can't be possibly enabled at this point
+ } else {
+ // Looking for AM
+ /// CRC is not updated because it can't be possibly enabled at this point
+ read_bit(false);
+ if ((m_hiden && !BIT(m_data_sr , 7)) ||
+ (!m_hiden && BIT(m_data_sr , 0))) {
+ // Got AM as soon as bits being shifted into DSR change value wrt synchronization bits
+ m_amdt = true;
+ // Finish the current byte
+ for (unsigned i = 0; i < 7; i++) {
read_bit(false);
- if ((m_hiden && !BIT(m_data_sr , 7)) ||
- (!m_hiden && BIT(m_data_sr , 0))) {
- // Got AM as soon as bits being shifted into DSR change value wrt synchronization bits
- m_amdt = true;
- // Finish the current byte
- for (unsigned i = 0; i < 7; i++) {
- read_bit(false);
- }
- attotime adjust{m_pll.ctime - machine().time()};
- LOG_0(("Got AM @ %.6f, ctime=%.6f, adj=%.6f, D=%02x/C=%02x\n" , machine().time().as_double() , m_pll.ctime.as_double() , adjust.as_double() , m_data_sr , m_clock_sr));
- // Disable half-bit timer & enable byte timer
- timer.reset();
- m_byte_timer->adjust(adjust);
- return;
- }
}
- timer.adjust(m_pll.ctime - machine().time());
+ attotime adjust{m_pll.ctime - machine().time()};
+ LOGMASKED(LOG_LEVEL0, "Got AM @ %.6f, ctime=%.6f, adj=%.6f, D=%02x/C=%02x\n" , machine().time().as_double() , m_pll.ctime.as_double() , adjust.as_double() , m_data_sr , m_clock_sr);
+ // Disable half-bit timer & enable byte timer
+ m_half_bit_timer->reset();
+ m_byte_timer->adjust(adjust);
+ return;
}
- break;
-
- default:
- break;
}
+ m_half_bit_timer->adjust(m_pll.ctime - machine().time());
}
void hp9895_device::ieee488_eoi(int state)
@@ -431,57 +416,57 @@ 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);
}
-READ8_MEMBER(hp9895_device::phi_dio_r)
+uint8_t hp9895_device::phi_dio_r()
{
- return m_bus->read_dio();
+ return m_bus->dio_r();
}
-WRITE8_MEMBER(hp9895_device::phi_dio_w)
+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) {
@@ -490,9 +475,9 @@ WRITE_LINE_MEMBER(hp9895_device::phi_int_w)
}
}
-READ8_MEMBER(hp9895_device::phi_reg_r)
+uint8_t hp9895_device::phi_reg_r(offs_t offset)
{
- uint16_t reg = m_phi->reg16_r(space , offset , mem_mask);
+ uint16_t reg = m_phi->reg16_r(offset);
// Reading D1=1 from a register sets the Z80 IRQ line
if (BIT(reg , 14) && !m_cpu_irq) {
@@ -503,7 +488,7 @@ READ8_MEMBER(hp9895_device::phi_reg_r)
return (uint8_t)reg;
}
-WRITE8_MEMBER(hp9895_device::z80_m1_w)
+void hp9895_device::z80_m1_w(uint8_t data)
{
// Every M1 cycle of Z80 clears the IRQ line
if (m_cpu_irq) {
@@ -512,9 +497,9 @@ WRITE8_MEMBER(hp9895_device::z80_m1_w)
}
}
-WRITE8_MEMBER(hp9895_device::data_w)
+void hp9895_device::data_w(uint8_t data)
{
- LOG_0(("W DATA=%02x\n" , data));
+ LOGMASKED(LOG_LEVEL0, "W DATA=%02x\n" , data);
// CPU stalls until next SDOK
m_cpu->suspend_until_trigger(1 , true);
m_data_sr = data;
@@ -522,15 +507,15 @@ WRITE8_MEMBER(hp9895_device::data_w)
m_accdata = true;
}
-WRITE8_MEMBER(hp9895_device::clock_w)
+void hp9895_device::clock_w(uint8_t data)
{
- LOG_0(("W CLOCK=%02x\n" , data));
+ LOGMASKED(LOG_LEVEL0, "W CLOCK=%02x\n" , data);
m_clock_reg = data;
}
-WRITE8_MEMBER(hp9895_device::reset_w)
+void hp9895_device::reset_w(uint8_t data)
{
- LOG_0(("W RESET=%02x\n" , data));
+ LOGMASKED(LOG_LEVEL0, "W RESET=%02x\n" , data);
if (BIT(data , REG_RESET_TIMEOUT_START_BIT)) {
m_timeout = false;
m_timeout_timer->adjust(attotime::from_msec(TIMEOUT_MSEC));
@@ -541,16 +526,16 @@ WRITE8_MEMBER(hp9895_device::reset_w)
// TODO: PROGRES
}
-WRITE8_MEMBER(hp9895_device::leds_w)
+void hp9895_device::leds_w(uint8_t data)
{
- LOG(("W LEDS=%02x %c%c%c%c%c\n" , data , BIT(data , 4) ? '.' : '*' , BIT(data , 3) ? '.' : '*' , BIT(data , 2) ? '.' : '*' , BIT(data , 1) ? '.' : '*' , BIT(data , 0) ? '.' : '*'));
+ LOGMASKED(LOG_LEVEL1, "W LEDS=%02x %c%c%c%c%c\n" , data , BIT(data , 4) ? '.' : '*' , BIT(data , 3) ? '.' : '*' , BIT(data , 2) ? '.' : '*' , BIT(data , 1) ? '.' : '*' , BIT(data , 0) ? '.' : '*');
// TODO:
}
-WRITE8_MEMBER(hp9895_device::cntl_w)
+void hp9895_device::cntl_w(uint8_t data)
{
if (data != m_cntl_reg) {
- LOG_0(("W CNTL=%02x -> %02x\n" , m_cntl_reg , data));
+ LOGMASKED(LOG_LEVEL0, "W CNTL=%02x -> %02x\n" , m_cntl_reg , data);
uint8_t old_cntl_reg = m_cntl_reg;
m_cntl_reg = data;
@@ -563,11 +548,11 @@ WRITE8_MEMBER(hp9895_device::cntl_w)
bool byte_timer_needed = new_writon || (new_readon && m_amdt);
if (!byte_timer_running && byte_timer_needed) {
- LOG_0(("Enable byte tmr\n"));
+ LOGMASKED(LOG_LEVEL0, "Enable byte tmr\n");
attotime byte_period = get_half_bit_cell_period() * 16;
m_byte_timer->adjust(byte_period);
} else if (byte_timer_running && !byte_timer_needed) {
- LOG_0(("Disable byte tmr\n"));
+ LOGMASKED(LOG_LEVEL0, "Disable byte tmr\n");
m_byte_timer->reset();
}
@@ -577,24 +562,24 @@ WRITE8_MEMBER(hp9895_device::cntl_w)
if (!old_writon && new_writon) {
// Writing enabled
- LOG_0(("Start writing..\n"));
+ LOGMASKED(LOG_LEVEL0, "Start writing\n");
m_pll.start_writing(machine().time());
m_wr_context = 0;
m_had_transition = false;
} else if (old_writon && !new_writon) {
// Writing disabled
- LOG_0(("Stop writing..\n"));
+ LOGMASKED(LOG_LEVEL0, "Stop writing\n");
m_pll.stop_writing(get_write_device() , machine().time());
}
if (!old_readon && new_readon) {
// Reading enabled
- LOG_0(("Start reading..\n"));
+ LOGMASKED(LOG_LEVEL0, "Start reading\n");
m_pll.read_reset(machine().time());
m_sync_cnt = 0;
m_half_bit_timer->adjust(get_half_bit_cell_period());
} else if (old_readon && !new_readon) {
// Reading disabled
- LOG_0(("Stop reading..\n"));
+ LOGMASKED(LOG_LEVEL0, "Stop reading\n");
m_half_bit_timer->reset();
m_lckup = true;
m_amdt = false;
@@ -608,9 +593,9 @@ WRITE8_MEMBER(hp9895_device::cntl_w)
}
}
-WRITE8_MEMBER(hp9895_device::drv_w)
+void hp9895_device::drv_w(uint8_t data)
{
- LOG_0(("W DRV=%02x\n" , data));
+ LOGMASKED(LOG_LEVEL0, "W DRV=%02x\n" , data);
m_mgnena = BIT(data , REG_DRV_MGNENA_BIT);
if (m_current_drive != nullptr) {
m_current_drive->stp_w(!BIT(data , REG_DRV_STEP_BIT));
@@ -620,13 +605,13 @@ WRITE8_MEMBER(hp9895_device::drv_w)
}
}
-WRITE8_MEMBER(hp9895_device::xv_w)
+void hp9895_device::xv_w(uint8_t data)
{
- LOG_0(("W XV=%02x\n" , data));
+ LOGMASKED(LOG_LEVEL0, "W XV=%02x\n" , data);
// Disk Changed flag is cleared when drive is ready and it is deselected
if (m_current_drive_idx < 2 && (data & xv_drive_masks[ m_current_drive_idx ]) == 0 && !m_current_drive->ready_r()) {
if (m_dskchg[ m_current_drive_idx ]) {
- LOG(("Dskchg %u cleared\n" , m_current_drive_idx));
+ LOGMASKED(LOG_LEVEL1, "Dskchg %u cleared\n" , m_current_drive_idx);
}
m_dskchg[ m_current_drive_idx ] = false;
}
@@ -644,22 +629,22 @@ WRITE8_MEMBER(hp9895_device::xv_w)
m_hiden = BIT(data , REG_XV_HIDEN_BIT);
}
-READ8_MEMBER(hp9895_device::data_r)
+uint8_t hp9895_device::data_r()
{
m_clock_reg = m_clock_sr;
m_accdata = true;
- LOG_0(("R DATA=%02x\n" , m_data_sr));
+ LOGMASKED(LOG_LEVEL0, "R DATA=%02x\n" , m_data_sr);
// CPU stalls until next SDOK
m_cpu->suspend_until_trigger(1 , true);
return m_data_sr;
}
-READ8_MEMBER(hp9895_device::clock_r)
+uint8_t hp9895_device::clock_r()
{
return m_clock_reg;
}
-READ8_MEMBER(hp9895_device::drivstat_r)
+uint8_t hp9895_device::drivstat_r()
{
uint8_t res = 0;
@@ -689,18 +674,18 @@ READ8_MEMBER(hp9895_device::drivstat_r)
if (m_overrun) {
BIT_SET(res , REG_DRIVSTAT_OVERUN_BIT);
}
- LOG_0(("R DRIVSTAT=%02x\n" , res));
+ LOGMASKED(LOG_LEVEL0, "R DRIVSTAT=%02x\n" , res);
return res;
}
-READ8_MEMBER(hp9895_device::switches_r)
+uint8_t hp9895_device::switches_r()
{
uint8_t res = get_switches2();
res |= m_switches->read();
return res;
}
-READ8_MEMBER(hp9895_device::switches2_r)
+uint8_t hp9895_device::switches2_r()
{
return get_switches2();
}
@@ -711,7 +696,7 @@ void hp9895_device::floppy_ready_cb(floppy_image_device *floppy , int state)
// Set Disk Changed flag when a drive is not ready
for (unsigned i = 0; i < 2; i++) {
if (floppy == m_drives[ i ]->get_device()) {
- LOG(("Dskchg %u set\n" , i));
+ LOGMASKED(LOG_LEVEL1, "Dskchg %u set\n" , i);
m_dskchg[ i ] = true;
break;
}
@@ -874,10 +859,11 @@ static void hp9895_floppies(device_slot_interface &device)
device.option_add("8dsdd" , FLOPPY_8_DSDD);
}
-static const floppy_format_type hp9895_floppy_formats[] = {
- FLOPPY_MFI_FORMAT,
- FLOPPY_HPI_FORMAT,
- nullptr
+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
@@ -893,14 +879,14 @@ void hp9895_device::device_add_mconfig(machine_config &config)
m_cpu->refresh_cb().set(FUNC(hp9895_device::z80_m1_w));
PHI(config, m_phi, 0);
- m_phi->signal_write_cb<phi_device::PHI_488_EOI>().set(FUNC(hp9895_device::phi_eoi_w));
- m_phi->signal_write_cb<phi_device::PHI_488_DAV>().set(FUNC(hp9895_device::phi_dav_w));
- m_phi->signal_write_cb<phi_device::PHI_488_NRFD>().set(FUNC(hp9895_device::phi_nrfd_w));
- m_phi->signal_write_cb<phi_device::PHI_488_NDAC>().set(FUNC(hp9895_device::phi_ndac_w));
- m_phi->signal_write_cb<phi_device::PHI_488_IFC>().set(FUNC(hp9895_device::phi_ifc_w));
- m_phi->signal_write_cb<phi_device::PHI_488_SRQ>().set(FUNC(hp9895_device::phi_srq_w));
- m_phi->signal_write_cb<phi_device::PHI_488_ATN>().set(FUNC(hp9895_device::phi_atn_w));
- m_phi->signal_write_cb<phi_device::PHI_488_REN>().set(FUNC(hp9895_device::phi_ren_w));
+ m_phi->eoi_write_cb().set(FUNC(hp9895_device::phi_eoi_w));
+ m_phi->dav_write_cb().set(FUNC(hp9895_device::phi_dav_w));
+ m_phi->nrfd_write_cb().set(FUNC(hp9895_device::phi_nrfd_w));
+ m_phi->ndac_write_cb().set(FUNC(hp9895_device::phi_ndac_w));
+ m_phi->ifc_write_cb().set(FUNC(hp9895_device::phi_ifc_w));
+ m_phi->srq_write_cb().set(FUNC(hp9895_device::phi_srq_w));
+ m_phi->atn_write_cb().set(FUNC(hp9895_device::phi_atn_w));
+ m_phi->ren_write_cb().set(FUNC(hp9895_device::phi_ren_w));
m_phi->dio_read_cb().set(FUNC(hp9895_device::phi_dio_r));
m_phi->dio_write_cb().set(FUNC(hp9895_device::phi_dio_w));
m_phi->int_write_cb().set(FUNC(hp9895_device::phi_int_w));
diff --git a/src/devices/bus/ieee488/hp9895.h b/src/devices/bus/ieee488/hp9895.h
index 60c41f63afd..501b94d185a 100644
--- a/src/devices/bus/ieee488/hp9895.h
+++ b/src/devices/bus/ieee488/hp9895.h
@@ -27,14 +27,13 @@ public:
hp9895_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_timer(emu_timer &timer, device_timer_id id, int param, void *ptr) override;
+ virtual void device_start() override ATTR_COLD;
+ virtual void device_reset() override ATTR_COLD;
// device-level overrides
- 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 ioport_constructor device_input_ports() const override ATTR_COLD;
+ virtual const tiny_rom_entry *device_rom_region() const override ATTR_COLD;
+ virtual void device_add_mconfig(machine_config &config) override ATTR_COLD;
// device_ieee488_interface overrides
virtual void ieee488_eoi(int state) override;
@@ -48,51 +47,65 @@ 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
- DECLARE_READ8_MEMBER(phi_dio_r);
- DECLARE_WRITE8_MEMBER(phi_dio_w);
+ 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
- DECLARE_WRITE8_MEMBER(z80_m1_w);
+ void z80_m1_w(uint8_t data);
// Floppy interface
- DECLARE_WRITE8_MEMBER(data_w);
- DECLARE_WRITE8_MEMBER(clock_w);
- DECLARE_WRITE8_MEMBER(reset_w);
- DECLARE_WRITE8_MEMBER(leds_w);
- DECLARE_WRITE8_MEMBER(cntl_w);
- DECLARE_WRITE8_MEMBER(drv_w);
- DECLARE_WRITE8_MEMBER(xv_w);
- DECLARE_READ8_MEMBER(data_r);
- DECLARE_READ8_MEMBER(clock_r);
- DECLARE_READ8_MEMBER(drivstat_r);
- DECLARE_READ8_MEMBER(switches_r);
- DECLARE_READ8_MEMBER(switches2_r);
+ void data_w(uint8_t data);
+ void clock_w(uint8_t data);
+ void reset_w(uint8_t data);
+ void leds_w(uint8_t data);
+ void cntl_w(uint8_t data);
+ void drv_w(uint8_t data);
+ void xv_w(uint8_t data);
+ uint8_t data_r();
+ uint8_t clock_r();
+ uint8_t drivstat_r();
+ uint8_t switches_r();
+ uint8_t switches2_r();
// PHI register read
- DECLARE_READ8_MEMBER(phi_reg_r);
+ uint8_t phi_reg_r(offs_t offset);
// Floppy drive interface
void floppy_ready_cb(floppy_image_device *floppy , int state);
- void z80_io_map(address_map &map);
- void z80_program_map(address_map &map);
+ TIMER_CALLBACK_MEMBER(timeout_timer_tick);
+ TIMER_CALLBACK_MEMBER(byte_timer_tick);
+ TIMER_CALLBACK_MEMBER(half_bit_timer_tick);
+
+ uint8_t get_switches2(void) const;
+ attotime get_half_bit_cell_period(void) const;
+ floppy_image_device *get_write_device(void) const;
+ void preset_crc(void);
+ void update_crc(bool bit);
+ bool shift_sr(uint8_t& sr , bool input_bit);
+ void get_next_transition(const attotime& from_when , attotime& edge);
+ void read_bit(bool crc_upd);
+ void write_bit(bool data_bit , bool clock_bit);
+
+ void z80_io_map(address_map &map) ATTR_COLD;
+ void z80_program_map(address_map &map) ATTR_COLD;
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;
@@ -123,16 +136,6 @@ private:
// PLL
fdc_pll_t m_pll;
-
- uint8_t get_switches2(void) const;
- attotime get_half_bit_cell_period(void) const;
- floppy_image_device *get_write_device(void) const;
- void preset_crc(void);
- void update_crc(bool bit);
- bool shift_sr(uint8_t& sr , bool input_bit);
- void get_next_transition(const attotime& from_when , attotime& edge);
- void read_bit(bool crc_upd);
- void write_bit(bool data_bit , bool clock_bit);
};
// device type definition
diff --git a/src/devices/bus/ieee488/ieee488.cpp b/src/devices/bus/ieee488/ieee488.cpp
index 6228136e1cd..686fc0ae5ad 100644
--- a/src/devices/bus/ieee488/ieee488.cpp
+++ b/src/devices/bus/ieee488/ieee488.cpp
@@ -41,7 +41,7 @@ DEFINE_DEVICE_TYPE(IEEE488_SLOT, ieee488_slot_device, "ieee488_slot", "IEEE-488
//-------------------------------------------------
device_ieee488_interface::device_ieee488_interface(const machine_config &mconfig, device_t &device)
- : device_slot_card_interface(mconfig, device), m_bus(nullptr), m_slot(nullptr), m_next(nullptr)
+ : device_interface(device, "ieee488"), m_bus(nullptr), m_slot(nullptr), m_next(nullptr)
{
}
@@ -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();
}
@@ -164,7 +154,7 @@ void ieee488_device::device_stop()
void ieee488_device::add_device(ieee488_slot_device *slot, device_t *target)
{
- auto entry = global_alloc(daisy_entry(target));
+ auto entry = new daisy_entry(target);
entry->m_interface->m_bus = this;
entry->m_interface->m_slot = slot;
@@ -431,11 +421,13 @@ void cbm_ieee488_devices(device_slot_interface &device)
// slot devices
#include "hp9122c.h"
+#include "hp9133.h"
#include "hp9895.h"
void hp_ieee488_devices(device_slot_interface &device)
{
device.option_add("hp9122c", HP9122C);
+ device.option_add("hp9133", HP9133);
device.option_add("hp9895", HP9895);
}
@@ -450,3 +442,18 @@ void remote488_devices(device_slot_interface &device)
{
device.option_add("remote488", REMOTE488);
}
+
+
+//-------------------------------------------------
+// SLOT_INTERFACE( grid_ieee488_devices )
+//-------------------------------------------------
+
+// slot devices
+#include "grid2102.h"
+
+void grid_ieee488_devices(device_slot_interface &device)
+{
+ device.option_add("grid2102", GRID2102).clock(XTAL(4'000'000));
+ device.option_add("grid2101_floppy", GRID2101_FLOPPY).clock(XTAL(4'000'000));
+ device.option_add("grid2101_hdd", GRID2101_HDD).clock(XTAL(4'000'000));
+}
diff --git a/src/devices/bus/ieee488/ieee488.h b/src/devices/bus/ieee488/ieee488.h
index cb29783d294..947085e4636 100644
--- a/src/devices/bus/ieee488/ieee488.h
+++ b/src/devices/bus/ieee488/ieee488.h
@@ -15,6 +15,7 @@
void cbm_ieee488_devices(device_slot_interface &device);
void hp_ieee488_devices(device_slot_interface &device);
void remote488_devices(device_slot_interface &device);
+void grid_ieee488_devices(device_slot_interface &device);
DECLARE_DEVICE_TYPE(IEEE488, ieee488_device)
DECLARE_DEVICE_TYPE(IEEE488_SLOT, ieee488_slot_device)
@@ -60,28 +61,26 @@ public:
void add_device(ieee488_slot_device *slot, device_t *target);
// reads for both host and peripherals
- uint8_t read_dio() { return get_data(); }
- DECLARE_READ8_MEMBER( 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); }
+ uint8_t dio_r() { return get_data(); }
+ 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 write_dio(uint8_t data) { set_data(this, data); }
- DECLARE_WRITE8_MEMBER( host_dio_w ) { 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_dio_w(uint8_t data) { set_data(this, data); }
+ 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); }
@@ -123,8 +122,8 @@ protected:
};
// device-level overrides
- virtual void device_start() override;
- virtual void device_stop() override;
+ virtual void device_start() override ATTR_COLD;
+ virtual void device_stop() override ATTR_COLD;
class daisy_entry
{
@@ -200,7 +199,7 @@ public:
int get_address() { return m_address; }
// device-level overrides
- virtual void device_start() override;
+ virtual void device_start() override ATTR_COLD;
protected:
int m_address;
@@ -209,7 +208,7 @@ protected:
// ======================> device_ieee488_interface
-class device_ieee488_interface : public device_slot_card_interface
+class device_ieee488_interface : public device_interface
{
friend class ieee488_device;
template <class ElementType> friend class simple_list;
diff --git a/src/devices/bus/ieee488/remote488.cpp b/src/devices/bus/ieee488/remote488.cpp
index b5eb0041632..d559622dad6 100644
--- a/src/devices/bus/ieee488/remote488.cpp
+++ b/src/devices/bus/ieee488/remote488.cpp
@@ -188,11 +188,12 @@
#include "remote488.h"
// Debugging
-#include "logmacro.h"
-#define LOG_PARSER_MASK (LOG_GENERAL << 1)
+#define LOG_PARSER_MASK (1U << 1)
#define LOG_PARSER(...) LOGMASKED(LOG_PARSER_MASK, __VA_ARGS__)
-#undef VERBOSE
-#define VERBOSE LOG_GENERAL
+
+#define VERBOSE (LOG_GENERAL)
+
+#include "logmacro.h"
// Bit manipulation
namespace {
@@ -222,16 +223,16 @@ namespace {
}
// Message types
-constexpr char MSG_SIGNAL_CLEAR = 'R'; // I/O: Clear signal(s)
-constexpr char MSG_SIGNAL_SET = 'S'; // I/O: Set signal(s)
-constexpr char MSG_DATA_BYTE = 'D'; // I/O: Cmd/data byte (no EOI)
-constexpr char MSG_END_BYTE = 'E'; // I/O: Data byte (with EOI)
-constexpr char MSG_PP_DATA = 'P'; // I: Parallel poll data
-constexpr char MSG_PP_REQUEST = 'Q'; // O: Request PP data
-constexpr char MSG_ECHO_REQ = 'J'; // O: Heartbeat msg: echo request
-constexpr char MSG_ECHO_REPLY = 'K'; // I: Heartbeat msg: echo reply
-constexpr char MSG_CHECKPOINT = 'X'; // I/O: Checkpoint in byte stream
-constexpr char MSG_CP_REACHED = 'Y'; // I/O: Checkpoint reached
+constexpr char MSG_SIGNAL_CLEAR = 'R'; // I/O: Clear signal(s)
+constexpr char MSG_SIGNAL_SET = 'S'; // I/O: Set signal(s)
+constexpr char MSG_DATA_BYTE = 'D'; // I/O: Cmd/data byte (no EOI)
+constexpr char MSG_END_BYTE = 'E'; // I/O: Data byte (with EOI)
+constexpr char MSG_PP_DATA = 'P'; // I: Parallel poll data
+constexpr char MSG_PP_REQUEST = 'Q'; // O: Request PP data
+constexpr char MSG_ECHO_REQ = 'J'; // O: Heartbeat msg: echo request
+constexpr char MSG_ECHO_REPLY = 'K'; // I: Heartbeat msg: echo reply
+constexpr char MSG_CHECKPOINT = 'X'; // I/O: Checkpoint in byte stream
+constexpr char MSG_CHECKPOINT_REACHED = 'Y'; // I/O: Checkpoint reached
// Timings
constexpr unsigned POLL_PERIOD_US = 20; // Poll period (µs)
@@ -304,9 +305,9 @@ void remote488_device::ieee488_ren(int state)
void remote488_device::device_start()
{
- m_poll_timer = timer_alloc(TMR_ID_POLL);
- m_hb_timer = timer_alloc(TMR_ID_HEARTBEAT);
- m_ah_timer = timer_alloc(TMR_ID_AH);
+ m_poll_timer = timer_alloc(FUNC(remote488_device::process_input_msgs), this);
+ m_hb_timer = timer_alloc(FUNC(remote488_device::heartbeat_tick), this);
+ m_ah_timer = timer_alloc(FUNC(remote488_device::checkpoint_timeout_tick), this);
}
void remote488_device::device_reset()
@@ -327,7 +328,7 @@ void remote488_device::device_reset()
m_ibf = false;
m_flush_bytes = false;
- m_waiting_cp = false;
+ m_waiting_checkpoint = false;
bus_reset();
}
@@ -344,7 +345,7 @@ void remote488_device::bus_reset()
update_pp();
}
-void remote488_device::process_input_msgs()
+TIMER_CALLBACK_MEMBER(remote488_device::process_input_msgs)
{
uint8_t data;
char msg_ch;
@@ -383,13 +384,13 @@ void remote488_device::process_input_msgs()
break;
case MSG_CHECKPOINT:
- send_update(MSG_CP_REACHED , m_flush_bytes);
+ send_update(MSG_CHECKPOINT_REACHED , m_flush_bytes);
m_flush_bytes = false;
break;
- case MSG_CP_REACHED:
- if (m_waiting_cp) {
- m_waiting_cp = false;
+ case MSG_CHECKPOINT_REACHED:
+ if (m_waiting_checkpoint) {
+ m_waiting_checkpoint = false;
update_ah_fsm();
}
break;
@@ -403,29 +404,19 @@ void remote488_device::process_input_msgs()
}
}
-void remote488_device::device_timer(emu_timer &timer, device_timer_id id, int param, void *ptr)
+TIMER_CALLBACK_MEMBER(remote488_device::heartbeat_tick)
{
- switch (id) {
- case TMR_ID_POLL:
- process_input_msgs();
- break;
-
- case TMR_ID_HEARTBEAT:
- if (m_connected && m_connect_cnt && --m_connect_cnt == 0) {
- set_connection(false);
- }
- send_update(MSG_ECHO_REQ , 0);
- break;
-
- case TMR_ID_AH:
- if (!m_waiting_cp) {
- LOG("CP T/O\n");
- ah_checkpoint();
- }
- break;
+ if (m_connected && m_connect_cnt && --m_connect_cnt == 0) {
+ set_connection(false);
+ }
+ send_update(MSG_ECHO_REQ , 0);
+}
- default:
- break;
+TIMER_CALLBACK_MEMBER(remote488_device::checkpoint_timeout_tick)
+{
+ if (!m_waiting_checkpoint) {
+ LOG("Checkpoint T/O\n");
+ ah_checkpoint();
}
}
@@ -487,32 +478,24 @@ void remote488_device::update_signals_from_rem(uint8_t to_set , uint8_t to_clear
m_in_signals |= to_set;
m_in_signals &= ~to_clear;
diff ^= m_in_signals;
- m_out_signals = m_in_signals;
//LOG("REM SIG %02x %02x\n" , m_in_signals , diff);
m_no_propagation = true;
- uint8_t tmp = m_out_signals;
if (BIT(diff , SIGNAL_ATN_BIT)) {
m_bus->atn_w(this , BIT(m_in_signals , SIGNAL_ATN_BIT));
- COPY_BIT(m_bus->atn_r() , tmp , SIGNAL_ATN_BIT);
}
if (BIT(diff , SIGNAL_IFC_BIT)) {
m_bus->ifc_w(this , BIT(m_in_signals , SIGNAL_IFC_BIT));
- COPY_BIT(m_bus->ifc_r() , tmp , SIGNAL_IFC_BIT);
}
if (BIT(diff , SIGNAL_REN_BIT)) {
m_bus->ren_w(this , BIT(m_in_signals , SIGNAL_REN_BIT));
- COPY_BIT(m_bus->ren_r() , tmp , SIGNAL_REN_BIT);
}
if (BIT(diff , SIGNAL_SRQ_BIT)) {
m_bus->srq_w(this , BIT(m_in_signals , SIGNAL_SRQ_BIT));
- COPY_BIT(m_bus->srq_r() , tmp , SIGNAL_SRQ_BIT);
}
m_no_propagation = false;
-
- update_state(tmp);
}
void remote488_device::update_signal(signal_bit bit , int state)
@@ -578,7 +561,7 @@ bool remote488_device::is_msg_type(char c)
c == MSG_PP_DATA ||
c == MSG_ECHO_REPLY ||
c == MSG_CHECKPOINT ||
- c == MSG_CP_REACHED;
+ c == MSG_CHECKPOINT_REACHED;
}
bool remote488_device::is_terminator(char c)
@@ -676,7 +659,7 @@ bool remote488_device::is_local_atn_active() const
void remote488_device::ah_checkpoint()
{
- m_waiting_cp = true;
+ m_waiting_checkpoint = true;
m_ah_timer->reset();
send_update(MSG_CHECKPOINT , 0);
}
@@ -706,8 +689,8 @@ void remote488_device::update_ah_fsm()
case REM_AH_ACDS:
if (m_bus->dav_r()) {
m_ah_state = REM_AH_ACRS;
- } else if (!m_waiting_cp) {
- uint8_t dio = ~m_bus->read_dio();
+ } else if (!m_waiting_checkpoint) {
+ uint8_t dio = ~m_bus->dio_r();
if (!m_bus->eoi_r()) {
send_update(MSG_END_BYTE , dio);
diff --git a/src/devices/bus/ieee488/remote488.h b/src/devices/bus/ieee488/remote488.h
index 312fc260f42..dcc989e62a9 100644
--- a/src/devices/bus/ieee488/remote488.h
+++ b/src/devices/bus/ieee488/remote488.h
@@ -31,18 +31,10 @@ public:
virtual void ieee488_atn(int state) override;
virtual void ieee488_ren(int state) override;
- // Timers
- enum {
- TMR_ID_POLL,
- TMR_ID_HEARTBEAT,
- TMR_ID_AH
- };
-
protected:
- virtual void device_start() override;
- virtual void device_reset() override;
- virtual void device_add_mconfig(machine_config &config) override;
- virtual void device_timer(emu_timer &timer, device_timer_id id, int param, void *ptr) override;
+ 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;
private:
// Position of signals in "S/R" msgs
@@ -101,10 +93,14 @@ private:
bool m_pp_requested;
uint8_t m_pp_dio;
uint8_t m_sh_dio;
- bool m_waiting_cp;
+ bool m_waiting_checkpoint;
+
+
+ TIMER_CALLBACK_MEMBER(process_input_msgs);
+ TIMER_CALLBACK_MEMBER(heartbeat_tick);
+ TIMER_CALLBACK_MEMBER(checkpoint_timeout_tick);
void bus_reset();
- void process_input_msgs();
void set_connection(bool state);
void recvd_data_byte(uint8_t data , bool eoi);
void flush_data();
diff --git a/src/devices/bus/ieee488/shark.h b/src/devices/bus/ieee488/shark.h
index 6ba13e138e8..e8d7de05b72 100644
--- a/src/devices/bus/ieee488/shark.h
+++ b/src/devices/bus/ieee488/shark.h
@@ -32,18 +32,18 @@ public:
protected:
// device-level overrides
- virtual void device_start() override;
+ virtual void device_start() override ATTR_COLD;
// optional information 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 const tiny_rom_entry *device_rom_region() const override ATTR_COLD;
+ virtual void device_add_mconfig(machine_config &config) override ATTR_COLD;
+ virtual ioport_constructor device_input_ports() const override ATTR_COLD;
private:
required_device<cpu_device> m_maincpu;
- void mshark_io(address_map &map);
- void mshark_mem(address_map &map);
+ void mshark_io(address_map &map) ATTR_COLD;
+ void mshark_mem(address_map &map) ATTR_COLD;
};
diff --git a/src/devices/bus/ieee488/softbox.cpp b/src/devices/bus/ieee488/softbox.cpp
index e2041d3e4e2..0a38d5ce9cf 100644
--- a/src/devices/bus/ieee488/softbox.cpp
+++ b/src/devices/bus/ieee488/softbox.cpp
@@ -98,12 +98,12 @@ void softbox_device::softbox_io(address_map &map)
// I8255A 0 Interface
//-------------------------------------------------
-READ8_MEMBER( softbox_device::ppi0_pa_r )
+uint8_t softbox_device::ppi0_pa_r()
{
- return m_bus->read_dio() ^ 0xff;
+ return m_bus->dio_r() ^ 0xff;
}
-WRITE8_MEMBER( softbox_device::ppi0_pb_w )
+void softbox_device::ppi0_pb_w(uint8_t data)
{
m_bus->dio_w(this, data ^ 0xff);
}
@@ -112,7 +112,7 @@ WRITE8_MEMBER( softbox_device::ppi0_pb_w )
// I8255A 1 Interface
//-------------------------------------------------
-READ8_MEMBER( softbox_device::ppi1_pa_r )
+uint8_t softbox_device::ppi1_pa_r()
{
/*
@@ -143,7 +143,7 @@ READ8_MEMBER( softbox_device::ppi1_pa_r )
return data;
}
-WRITE8_MEMBER( softbox_device::ppi1_pb_w )
+void softbox_device::ppi1_pb_w(uint8_t data)
{
/*
@@ -170,7 +170,7 @@ WRITE8_MEMBER( softbox_device::ppi1_pb_w )
m_bus->ifc_w(this, !BIT(data, 7));
}
-READ8_MEMBER( softbox_device::ppi1_pc_r )
+uint8_t softbox_device::ppi1_pc_r()
{
/*
@@ -187,7 +187,7 @@ READ8_MEMBER( softbox_device::ppi1_pc_r )
*/
- uint8_t status = m_hdc->status_r(space, 0);
+ uint8_t status = m_hdc->status_r();
uint8_t data = 0;
data |= (status & corvus_hdc_device::CONTROLLER_BUSY) ? 0 : 0x10;
@@ -196,7 +196,7 @@ READ8_MEMBER( softbox_device::ppi1_pc_r )
return data;
}
-WRITE8_MEMBER( softbox_device::ppi1_pc_w )
+void softbox_device::ppi1_pc_w(uint8_t data)
{
/*
@@ -221,7 +221,6 @@ WRITE8_MEMBER( softbox_device::ppi1_pc_w )
static DEVICE_INPUT_DEFAULTS_START( terminal )
DEVICE_INPUT_DEFAULTS( "RS232_TXBAUD", 0xff, RS232_BAUD_9600 )
DEVICE_INPUT_DEFAULTS( "RS232_RXBAUD", 0xff, RS232_BAUD_9600 )
- DEVICE_INPUT_DEFAULTS( "RS232_STARTBITS", 0xff, RS232_STARTBITS_1 )
DEVICE_INPUT_DEFAULTS( "RS232_DATABITS", 0xff, RS232_DATABITS_7 )
DEVICE_INPUT_DEFAULTS( "RS232_PARITY", 0xff, RS232_PARITY_EVEN )
DEVICE_INPUT_DEFAULTS( "RS232_STOPBITS", 0xff, RS232_STOPBITS_1 )
@@ -376,7 +375,7 @@ void softbox_device::ieee488_ifc(int state)
// dbrg_w - baud rate selection
//-------------------------------------------------
-WRITE8_MEMBER( softbox_device::dbrg_w )
+void softbox_device::dbrg_w(uint8_t data)
{
m_dbrg->str_w(data & 0x0f);
m_dbrg->stt_w(data >> 4);
diff --git a/src/devices/bus/ieee488/softbox.h b/src/devices/bus/ieee488/softbox.h
index 0fce3e9f8d1..11dc90b4c40 100644
--- a/src/devices/bus/ieee488/softbox.h
+++ b/src/devices/bus/ieee488/softbox.h
@@ -37,30 +37,30 @@ public:
protected:
// device-level overrides
- virtual void device_start() override;
+ virtual void device_start() override ATTR_COLD;
virtual void device_reset_after_children() override;
// optional information 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 const tiny_rom_entry *device_rom_region() const override ATTR_COLD;
+ virtual void device_add_mconfig(machine_config &config) override ATTR_COLD;
+ virtual ioport_constructor device_input_ports() const override ATTR_COLD;
// device_ieee488_interface overrides
virtual void ieee488_ifc(int state) override;
private:
- DECLARE_READ8_MEMBER( ppi0_pa_r );
- DECLARE_WRITE8_MEMBER( ppi0_pb_w );
+ uint8_t ppi0_pa_r();
+ void ppi0_pb_w(uint8_t data);
- DECLARE_READ8_MEMBER( ppi1_pa_r );
- DECLARE_WRITE8_MEMBER( ppi1_pb_w );
- DECLARE_READ8_MEMBER( ppi1_pc_r );
- DECLARE_WRITE8_MEMBER( ppi1_pc_w );
+ uint8_t ppi1_pa_r();
+ void ppi1_pb_w(uint8_t data);
+ uint8_t ppi1_pc_r();
+ void ppi1_pc_w(uint8_t data);
- DECLARE_WRITE8_MEMBER( dbrg_w );
+ void dbrg_w(uint8_t data);
- void softbox_io(address_map &map);
- void softbox_mem(address_map &map);
+ void softbox_io(address_map &map) ATTR_COLD;
+ void softbox_mem(address_map &map) ATTR_COLD;
enum
{
diff --git a/src/devices/bus/imi7000/imi5000h.cpp b/src/devices/bus/imi7000/imi5000h.cpp
index 6ad104d7b2f..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);
@@ -129,7 +129,7 @@ WRITE_LINE_MEMBER( imi5000h_device::ctc_z2_w )
// Z80PIO 1
//-------------------------------------------------
-READ8_MEMBER( imi5000h_device::pio0_pa_r )
+uint8_t imi5000h_device::pio0_pa_r()
{
/*
@@ -149,7 +149,7 @@ READ8_MEMBER( imi5000h_device::pio0_pa_r )
return 0;
}
-WRITE8_MEMBER( imi5000h_device::pio0_pa_w )
+void imi5000h_device::pio0_pa_w(uint8_t data)
{
/*
@@ -167,7 +167,7 @@ WRITE8_MEMBER( imi5000h_device::pio0_pa_w )
*/
}
-READ8_MEMBER( imi5000h_device::pio0_pb_r )
+uint8_t imi5000h_device::pio0_pb_r()
{
/*
@@ -187,7 +187,7 @@ READ8_MEMBER( imi5000h_device::pio0_pb_r )
return 0;
}
-WRITE8_MEMBER( imi5000h_device::pio0_pb_w )
+void imi5000h_device::pio0_pb_w(uint8_t data)
{
/*
@@ -209,7 +209,7 @@ WRITE8_MEMBER( imi5000h_device::pio0_pb_w )
// Z80PIO 2
//-------------------------------------------------
-READ8_MEMBER( imi5000h_device::pio2_pa_r )
+uint8_t imi5000h_device::pio2_pa_r()
{
/*
@@ -229,7 +229,7 @@ READ8_MEMBER( imi5000h_device::pio2_pa_r )
return 0;
}
-WRITE8_MEMBER( imi5000h_device::pio2_pa_w )
+void imi5000h_device::pio2_pa_w(uint8_t data)
{
/*
@@ -247,13 +247,13 @@ WRITE8_MEMBER( imi5000h_device::pio2_pa_w )
*/
}
-READ8_MEMBER( imi5000h_device::pio2_pb_r )
+uint8_t imi5000h_device::pio2_pb_r()
{
// command bus
return 0;
}
-WRITE8_MEMBER( imi5000h_device::pio2_pb_w )
+void imi5000h_device::pio2_pb_w(uint8_t data)
{
// command bus
}
@@ -262,7 +262,7 @@ WRITE8_MEMBER( imi5000h_device::pio2_pb_w )
// Z80PIO 3
//-------------------------------------------------
-READ8_MEMBER( imi5000h_device::pio3_pa_r )
+uint8_t imi5000h_device::pio3_pa_r()
{
/*
@@ -282,7 +282,7 @@ READ8_MEMBER( imi5000h_device::pio3_pa_r )
return 0;
}
-WRITE8_MEMBER( imi5000h_device::pio3_pa_w )
+void imi5000h_device::pio3_pa_w(uint8_t data)
{
/*
@@ -300,7 +300,7 @@ WRITE8_MEMBER( imi5000h_device::pio3_pa_w )
*/
}
-READ8_MEMBER( imi5000h_device::pio3_pb_r )
+uint8_t imi5000h_device::pio3_pb_r()
{
/*
@@ -320,7 +320,7 @@ READ8_MEMBER( imi5000h_device::pio3_pb_r )
return 0;
}
-WRITE8_MEMBER( imi5000h_device::pio3_pb_w )
+void imi5000h_device::pio3_pb_w(uint8_t data)
{
/*
diff --git a/src/devices/bus/imi7000/imi5000h.h b/src/devices/bus/imi7000/imi5000h.h
index 935b6d7046b..121fa8b2fc2 100644
--- a/src/devices/bus/imi7000/imi5000h.h
+++ b/src/devices/bus/imi7000/imi5000h.h
@@ -36,36 +36,36 @@ public:
protected:
// device-level overrides
- virtual void device_start() override;
- virtual void device_reset() override;
+ virtual void device_start() override ATTR_COLD;
+ virtual void device_reset() override ATTR_COLD;
// optional information 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 const tiny_rom_entry *device_rom_region() const override ATTR_COLD;
+ virtual void device_add_mconfig(machine_config &config) override ATTR_COLD;
+ virtual ioport_constructor device_input_ports() const override ATTR_COLD;
private:
- DECLARE_WRITE_LINE_MEMBER( ctc_z0_w );
- DECLARE_WRITE_LINE_MEMBER( ctc_z1_w );
- DECLARE_WRITE_LINE_MEMBER( ctc_z2_w );
-
- DECLARE_READ8_MEMBER( pio0_pa_r );
- DECLARE_WRITE8_MEMBER( pio0_pa_w );
- DECLARE_READ8_MEMBER( pio0_pb_r );
- DECLARE_WRITE8_MEMBER( pio0_pb_w );
-
- DECLARE_READ8_MEMBER( pio2_pa_r );
- DECLARE_WRITE8_MEMBER( pio2_pa_w );
- DECLARE_READ8_MEMBER( pio2_pb_r );
- DECLARE_WRITE8_MEMBER( pio2_pb_w );
-
- DECLARE_READ8_MEMBER( pio3_pa_r );
- DECLARE_WRITE8_MEMBER( pio3_pa_w );
- DECLARE_READ8_MEMBER( pio3_pb_r );
- DECLARE_WRITE8_MEMBER( pio3_pb_w );
-
- void imi5000h_io(address_map &map);
- void imi5000h_mem(address_map &map);
+ 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);
+ uint8_t pio0_pb_r();
+ void pio0_pb_w(uint8_t data);
+
+ uint8_t pio2_pa_r();
+ void pio2_pa_w(uint8_t data);
+ uint8_t pio2_pb_r();
+ void pio2_pb_w(uint8_t data);
+
+ uint8_t pio3_pa_r();
+ void pio3_pa_w(uint8_t data);
+ uint8_t pio3_pb_r();
+ void pio3_pb_w(uint8_t data);
+
+ void imi5000h_io(address_map &map) ATTR_COLD;
+ void imi5000h_mem(address_map &map) ATTR_COLD;
enum
{
diff --git a/src/devices/bus/imi7000/imi7000.cpp b/src/devices/bus/imi7000/imi7000.cpp
index f96e32d3da5..3c9e417867b 100644
--- a/src/devices/bus/imi7000/imi7000.cpp
+++ b/src/devices/bus/imi7000/imi7000.cpp
@@ -37,7 +37,8 @@ DEFINE_DEVICE_TYPE(IMI7000_SLOT, imi7000_slot_device, "imi7000_slot", "IMI7000 s
//-------------------------------------------------
device_imi7000_interface::device_imi7000_interface(const machine_config &mconfig, device_t &device)
- : device_slot_card_interface(mconfig, device), m_slot(nullptr)
+ : device_interface(device, "imi7000bus")
+ , m_slot(nullptr)
{
}
@@ -53,7 +54,7 @@ device_imi7000_interface::device_imi7000_interface(const machine_config &mconfig
imi7000_slot_device::imi7000_slot_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
: device_t(mconfig, IMI7000_SLOT, tag, owner, clock)
- , device_slot_interface(mconfig, *this)
+ , device_single_card_slot_interface<device_imi7000_interface>(mconfig, *this)
, m_card(nullptr)
{
}
@@ -79,10 +80,18 @@ void imi7000_slot_device::device_start()
imi7000_bus_device::imi7000_bus_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
: device_t(mconfig, IMI7000_BUS, tag, owner, clock)
+ , m_units(*this, "%u", 0U)
{
}
+void imi7000_bus_device::device_add_mconfig(machine_config &config)
+{
+ for (auto &unit : m_units)
+ IMI7000_SLOT(config, unit, imi7000_devices, nullptr);
+}
+
+
//-------------------------------------------------
// device_start - device-specific startup
//-------------------------------------------------
diff --git a/src/devices/bus/imi7000/imi7000.h b/src/devices/bus/imi7000/imi7000.h
index 38de3341ae5..5a35f82708a 100644
--- a/src/devices/bus/imi7000/imi7000.h
+++ b/src/devices/bus/imi7000/imi7000.h
@@ -36,77 +36,68 @@ void imi7000_devices(device_slot_interface &device);
DECLARE_DEVICE_TYPE(IMI7000_BUS, imi7000_bus_device)
DECLARE_DEVICE_TYPE(IMI7000_SLOT, imi7000_slot_device)
-//**************************************************************************
-// CONSTANTS
-//**************************************************************************
-
-#define IMI7000_BUS_TAG "imi7000"
-
-
//**************************************************************************
// TYPE DEFINITIONS
//**************************************************************************
-class imi7000_slot_device;
class device_imi7000_interface;
-// ======================> imi7000_bus_device
+// ======================> imi7000_slot_device
-class imi7000_bus_device : public device_t
+class imi7000_slot_device : public device_t, public device_single_card_slot_interface<device_imi7000_interface>
{
public:
// construction/destruction
- imi7000_bus_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock = 0);
-
- template <typename T, typename U, typename V, typename W>
- static void add_config(machine_config &config, T &&_def_slot1, U &&_def_slot2, V &&_def_slot3, W &&_def_slot4)
+ template <typename T>
+ imi7000_slot_device(machine_config const &mconfig, char const *tag, device_t *owner, T &&opts, char const *dflt)
+ : imi7000_slot_device(mconfig, tag, owner, (uint32_t)0)
{
- IMI7000_BUS(config, IMI7000_BUS_TAG);
- IMI7000_SLOT(config, IMI7000_BUS_TAG":0", imi7000_devices, std::forward<T>(_def_slot1));
- IMI7000_SLOT(config, IMI7000_BUS_TAG":1", imi7000_devices, std::forward<U>(_def_slot2));
- IMI7000_SLOT(config, IMI7000_BUS_TAG":2", imi7000_devices, std::forward<V>(_def_slot3));
- IMI7000_SLOT(config, IMI7000_BUS_TAG":3", imi7000_devices, std::forward<W>(_def_slot4));
+ option_reset();
+ opts(*this);
+ set_default_option(dflt);
+ set_fixed(false);
}
+ imi7000_slot_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_start() override ATTR_COLD;
- imi7000_slot_device *m_unit[4];
+ device_imi7000_interface *m_card;
};
-// ======================> imi7000_slot_device
+// ======================> imi7000_bus_device
-class imi7000_slot_device : public device_t,
- public device_slot_interface
+class imi7000_bus_device : public device_t
{
public:
// construction/destruction
- template <typename T>
- imi7000_slot_device(machine_config const &mconfig, char const *tag, device_t *owner, T &&opts, char const *dflt)
- : imi7000_slot_device(mconfig, tag, owner, (uint32_t)0)
+ imi7000_bus_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock = 0);
+
+ template <typename T, typename U, typename V, typename W>
+ void set_slot_default_options(T &&def1, U &&def2, V &&def3, W &&def4)
{
- option_reset();
- opts(*this);
- set_default_option(dflt);
- set_fixed(false);
+ 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));
}
- imi7000_slot_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 ATTR_COLD;
+ virtual void device_start() override ATTR_COLD;
- device_imi7000_interface *m_card;
+ required_device_array<imi7000_slot_device, 4> m_units;
};
// ======================> device_imi7000_interface
-class device_imi7000_interface : public device_slot_card_interface
+class device_imi7000_interface : public device_interface
{
friend class imi7000_slot_device;
diff --git a/src/devices/bus/intellec4/insdatastor.cpp b/src/devices/bus/intellec4/insdatastor.cpp
index f271ef4b91f..395c3806b5c 100644
--- a/src/devices/bus/intellec4/insdatastor.cpp
+++ b/src/devices/bus/intellec4/insdatastor.cpp
@@ -1,15 +1,147 @@
// license:BSD-3-Clause
// copyright-holders:Vas Crabb
+/*
+imm4-22 Instruction/Data Storage Module
+
+This card has four 4002 RAMs configured as a page, sockets for four
+1702A or similar 256×8 PROMs configured as a ROM page, buffers for four
+4-bit input ports, and latches for four 4-bit output ports.
+
+The 4002 RAMs may be jumpered to be selected by CM-RAM1, CM-RAM2 or
+CM-RAM3. Note that the CM-RAM lines are not decoded, so the 4002 RAMs
+will be mirrored. (With two or more imm4-22 cards installed, the 4002
+RAMs will fight for the bus if pages 4-7 are selected.)
+
+The PROMs and I/O ports may be jumpered to be mapped at 0x04xx...0x07xx,
+0x08xx...0x0bff or 0x0cff...0x0fff. Additionally, the card may be
+jumpered to enable the PROMs and I/O ports only when /ENABLE MON PROM is
+asserted, or at all times.
+
+This card may seem like a good way to expand three aspects of the system
+at once, but in practice the PROMs are of limited use:
+* If jumpered to enable the PROMs at all times, the PROMs will fight for
+ the bus if console RAM card program storage is selected.
+* If jumpered to enable the PROMs only when /ENABLE MON PROM is
+ asserted, the PROMs become effectively inaccessible as the boot vector
+ is in the onboard monitor PROM region, and the onboard monitor PROM
+ program provides no way to jump to or read from arbitrary locations.
+
+This card was probably most useful as the cheapest way to double RAM and
+I/O ports. Without PROMs installed, mapping I/O at 0x0400...0x07ff only
+when /ENABLE MON PROM is asserted would be a convenient way to provide
+the necessary connections for an imm4-90 high-speed paper tape reader.
+
+Image file for the PROMs must be an exact multiple of 256 bytes. PROMs
+are assumed to be filled in order from lowest to highest address.
+Jumper changes only take effect on hard reset.
+
+
+P1 Universal Slot edge connector
+
+ 1 2
+ GND 3 4 GND
+ 5 6
+ 7 8
+ 9 10
+ MA0 11 12 MA1
+ MA2 13 14 MA3
+ MA4 15 16 MA5
+ MA6 17 18 MA7
+ C0 19 20 C1
+ 21 22
+ /MDI0 23 24
+ /MDI1 25 26
+ /MDI3 27 28
+ /MDI2 29 30
+ /MDI5 31 32
+ /MDI4 33 34
+ /MDI7 35 36
+ /MDI6 37 38
+ 39 40
+ /OUT 41 42 /ENABLE MON PROM
+ -10V 43 44 -10V
+ 45 46
+ /CM-RAM2 47 48 /CM-RAM3
+ 49 50 /CM-RAM1
+ I/O 1 51 52 I/O 0
+ I/O 2 53 54 /IN
+ 55 56 I/O 3
+ 57 58
+ 59 60
+ 61 62
+ 63 64
+ 65 66
+ 67 68
+ 69 70
+ 71 72 /D3
+ 73 74
+ 75 76 /D2
+ 77 78
+ /SYNC 79 80 /D1
+ 81 82
+ /D0 83 84
+ 85 86
+ 87 88 /RESET-4002
+ 89 90
+ 91 92
+ /CM-ROM 93 94 C3
+ 95 96 C2
+ PHASE 2 97 98 PHASE 1
+ +5V 99 100 +5V
+
+
+P1 inputs (40-pin IDC)
+
+ ROM 4/8/12 IN0 1 2 ROM 4/8/12 IN1
+ ROM 4/8/12 IN2 3 4 ROM 4/8/12 IN3
+ GND 5 6 ROM 5/9/13 IN0
+ ROM 5/9/13 IN1 7 8 ROM 5/9/13 IN2
+ ROM 5/9/13 IN3 9 10 GND
+ ROM 6/10/14 IN0 11 12 ROM 6/10/14 IN1
+ ROM 6/10/14 IN2 13 14 ROM 6/10/14 IN3
+ GND 15 16 ROM 7/11/15 IN0
+ ROM 7/11/15 IN1 17 18 ROM 7/11/15 IN2
+ ROM 7/11/15 IN3 19 20 GND
+ 21 22
+ 23 24
+ 25 26
+ 27 28
+ 29 30
+ 31 32
+ 33 34
+ 35 36
+ 37 38
+ 39 40
+
+
+P2 outputs (40-pin IDC)
+
+ ROM 4/8/12 OUT0 1 2 ROM 4/8/12 OUT1
+ ROM 4/8/12 OUT2 3 4 ROM 4/8/12 OUT3
+ GND 5 6 ROM 5/9/13 OUT0
+ ROM 5/9/13 OUT1 7 8 ROM 5/9/13 OUT2
+ ROM 5/9/13 OUT3 9 10 GND
+ ROM 6/10/14 OUT0 11 12 ROM 6/10/14 OUT1
+ ROM 6/10/14 OUT2 13 14 ROM 6/10/14 OUT3
+ GND 15 16 ROM 7/11/15 OUT0
+ ROM 7/11/15 OUT1 17 18 ROM 7/11/15 OUT2
+ ROM 7/11/15 OUT3 19 20 GND
+ RAM 4/8/12 OUT0 21 22 RAM 4/8/12 OUT1
+ RAM 4/8/12 OUT2 23 24 RAM 4/8/12 OUT3
+ GND 25 26 RAM 5/9/13 OUT0
+ RAM 5/9/13 OUT1 27 28 RAM 5/9/13 OUT2
+ RAM 5/9/13 OUT3 29 30 GND
+ RAM 6/10/14 OUT0 31 32 RAM 6/10/14 OUT1
+ RAM 6/10/14 OUT2 33 34 RAM 6/10/14 OUT3
+ GND 35 36 RAM 7/11/15 OUT0
+ RAM 7/11/15 OUT1 37 38 RAM 7/11/15 OUT2
+ RAM 7/11/15 OUT3 39 40 GND
+*/
#include "emu.h"
#include "insdatastor.h"
-DEFINE_DEVICE_TYPE_NS(INTELLEC4_INST_DATA_STORAGE, bus::intellec4, imm4_22_device, "intlc4_imm4_22", "Intel imm4-22 Instruction/Data Storage Module")
-
-
-namespace bus { namespace intellec4 {
-
namespace {
INPUT_PORTS_START(imm4_22)
@@ -27,12 +159,58 @@ INPUT_PORTS_START(imm4_22)
PORT_CONFSETTING( 0x10, "MON only" )
INPUT_PORTS_END
-} // anonymous namespace
+
+class imm4_22_device
+ : public device_t
+ , public bus::intellec4::device_univ_card_interface
+ , public device_image_interface
+{
+public:
+ imm4_22_device(machine_config const &mconfig, char const *tag, device_t *owner, u32 clock);
+
+ 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; }
+ 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 char const *file_extensions() const noexcept override { return "rom,bin"; }
+ virtual char const *image_type_name() const noexcept override { return "promimage"; }
+ virtual char const *image_brief_type_name() const noexcept override { return "prom"; }
+
+protected:
+ virtual ioport_constructor device_input_ports() const override ATTR_COLD;
+ virtual void device_start() override ATTR_COLD;
+ virtual void device_reset() override ATTR_COLD;
+
+ virtual void reset_4002_in(int state) override;
+
+private:
+ void ram_out(offs_t offset, u8 data);
+ void rom_out(offs_t offset, u8 data);
+ u8 rom_in(offs_t offset);
+
+ void allocate();
+ void map_ram_io();
+ void map_prom();
+ void unmap_prom();
+
+ required_ioport m_jumpers;
+
+ bool m_ram_io_mapped;
+
+ u8 m_ram_page, m_rom_page;
+ bool m_rom_mirror;
+
+ u8 m_memory[256], m_status[64];
+ std::unique_ptr<u8 []> m_prom;
+};
imm4_22_device::imm4_22_device(machine_config const &mconfig, char const *tag, device_t *owner, u32 clock)
: device_t(mconfig, INTELLEC4_INST_DATA_STORAGE, tag, owner, clock)
- , device_univ_card_interface(mconfig, *this)
+ , bus::intellec4::device_univ_card_interface(mconfig, *this)
, device_image_interface(mconfig, *this)
, m_jumpers(*this, "JUMPERS")
, m_ram_io_mapped(false)
@@ -44,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()
@@ -89,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)
@@ -100,19 +282,19 @@ WRITE_LINE_MEMBER(imm4_22_device::reset_4002_in)
}
-WRITE8_MEMBER(imm4_22_device::ram_out)
+void imm4_22_device::ram_out(offs_t offset, u8 data)
{
// GPIO write - hooking this up would be a pain with MAME as it is
logerror("4002 A%u out %X\n", 13U + (offset & 0x03U), data & 0x0fU);
}
-WRITE8_MEMBER(imm4_22_device::rom_out)
+void imm4_22_device::rom_out(offs_t offset, u8 data)
{
// GPIO write - hooking this up would be a pain with MAME as it is
logerror("ROM %u out %X\n", (m_rom_page << 2) | ((offset >> 4) & 0x03U), data & 0x0fU);
}
-READ8_MEMBER(imm4_22_device::rom_in)
+u8 imm4_22_device::rom_in(offs_t offset)
{
// GPIO read - hooking this up would be a pain with MAME as it is
if (!machine().side_effects_disabled())
@@ -155,7 +337,7 @@ void imm4_22_device::map_ram_io()
{
memory_space().install_ram(start << 8, (start << 8) | 0x00ffU, m_memory);
status_space().install_ram(start << 6, (start << 6) | 0x003fU, m_status);
- ram_ports_space().install_write_handler(start << 2, (start << 2) | 0x03U, write8_delegate(FUNC(imm4_22_device::ram_out), this));
+ ram_ports_space().install_write_handler(start << 2, (start << 2) | 0x03U, write8sm_delegate(*this, FUNC(imm4_22_device::ram_out)));
}
offs_t const rom_ports_start(offs_t(m_rom_page) << 6);
@@ -163,7 +345,7 @@ void imm4_22_device::map_ram_io()
offs_t const rom_ports_mirror(m_rom_mirror ? 0x1f00U : 0x0700U);
rom_ports_space().install_readwrite_handler(
rom_ports_start, rom_ports_end, 0U, rom_ports_mirror, 0U,
- read8_delegate(FUNC(imm4_22_device::rom_in), this), write8_delegate(FUNC(imm4_22_device::rom_out), this));
+ read8sm_delegate(*this, FUNC(imm4_22_device::rom_in)), write8sm_delegate(*this, FUNC(imm4_22_device::rom_out)));
if (is_loaded())
map_prom();
@@ -188,4 +370,7 @@ void imm4_22_device::unmap_prom()
rom_space().unmap_read(offs_t(m_rom_page) << 10, (offs_t(m_rom_page) << 10) | 0x03ffU, m_rom_mirror ? 0x1000U : 0x0000U);
}
-} } // namespace bus::intellec4
+} // anonymous namespace
+
+
+DEFINE_DEVICE_TYPE_PRIVATE(INTELLEC4_INST_DATA_STORAGE, bus::intellec4::device_univ_card_interface, imm4_22_device, "intlc4_imm4_22", "Intel imm4-22 Instruction/Data Storage Module")
diff --git a/src/devices/bus/intellec4/insdatastor.h b/src/devices/bus/intellec4/insdatastor.h
index fa342d1f5bc..371b6a2bdc0 100644
--- a/src/devices/bus/intellec4/insdatastor.h
+++ b/src/devices/bus/intellec4/insdatastor.h
@@ -1,142 +1,5 @@
// license:BSD-3-Clause
// copyright-holders:Vas Crabb
-/*
-imm4-22 Instruction/Data Storage Module
-
-This card has four 4002 RAMs configured as a page, sockets for four
-1702A or similar 256×8 PROMs configured as a ROM page, buffers for four
-4-bit input ports, and latches for four 4-bit output ports.
-
-The 4002 RAMs may be jumpered to be selected by CM-RAM1, CM-RAM2 or
-CM-RAM3. Note that the CM-RAM lines are not decoded, so the 4002 RAMs
-will be mirrored. (With two or more imm4-22 cards are installed, the
-4002 RAMs will fight for the bus if pages 4-7 are selected.)
-
-The PROMs and I/O ports may be jumpered to be mapped at 0x04xx...0x07xx,
-0x08xx...0x0bff or 0x0cff...0x0fff. Additionally, the card may be
-jumpered to enable the PROMs and I/O ports only when /ENABLE MON PROM is
-asserted, or at all times.
-
-This card may seem like a good way to expand three aspects of the system
-at once, but in practice the PROMs are of limited use:
-* If jumpered to enable the PROMs at all times, the PROMs will fight for
- the bus if console RAM card program storage is selected.
-* If jumpered to enable the PROMs only when /ENABLE MON PROM is
- asserted, the PROMs become effectively inaccessible as the boot vector
- is in the onboard monitor PROM region, and the onboard monitor PROM
- program provides no way to jump to or read from arbitrary locations.
-
-This card was probably most useful as the cheapest way to double RAM and
-I/O ports. Without PROMs installed, mapping I/O at 0x0400...0x07ff only
-when /ENABLE MON PROM is asserted would be a convenient way to provide
-the necessary connections for an imm4-90 high-speed paper tape reader.
-
-Image file for the PROMs must be an exact multiple of 256 bytes. PROMs
-are assumed to be filled in order from lowest to highest address.
-Jumper changes only take effect on hard reset.
-
-
-P1 Universal Slot edge connector
-
- 1 2
- GND 3 4 GND
- 5 6
- 7 8
- 9 10
- MA0 11 12 MA1
- MA2 13 14 MA3
- MA4 15 16 MA5
- MA6 17 18 MA7
- C0 19 20 C1
- 21 22
- /MDI0 23 24
- /MDI1 25 26
- /MDI3 27 28
- /MDI2 29 30
- /MDI5 31 32
- /MDI4 33 34
- /MDI7 35 36
- /MDI6 37 38
- 39 40
- /OUT 41 42 /ENABLE MON PROM
- -10V 43 44 -10V
- 45 46
- /CM-RAM2 47 48 /CM-RAM3
- 49 50 /CM-RAM1
- I/O 1 51 52 I/O 0
- I/O 2 53 54 /IN
- 55 56 I/O 3
- 57 58
- 59 60
- 61 62
- 63 64
- 65 66
- 67 68
- 69 70
- 71 72 /D3
- 73 74
- 75 76 /D2
- 77 78
- /SYNC 79 80 /D1
- 81 82
- /D0 83 84
- 85 86
- 87 88 /RESET-4002
- 89 90
- 91 92
- /CM-ROM 93 94 C3
- 95 96 C2
- PHASE 2 97 98 PHASE 1
- +5V 99 100 +5V
-
-
-P1 inputs (40-pin IDC)
-
- ROM 4/8/12 IN0 1 2 ROM 4/8/12 IN1
- ROM 4/8/12 IN2 3 4 ROM 4/8/12 IN3
- GND 5 6 ROM 5/9/13 IN0
- ROM 5/9/13 IN1 7 8 ROM 5/9/13 IN2
- ROM 5/9/13 IN3 9 10 GND
- ROM 6/10/14 IN0 11 12 ROM 6/10/14 IN1
- ROM 6/10/14 IN2 13 14 ROM 6/10/14 IN3
- GND 15 16 ROM 7/11/15 IN0
- ROM 7/11/15 IN1 17 18 ROM 7/11/15 IN2
- ROM 7/11/15 IN3 19 20 GND
- 21 22
- 23 24
- 25 26
- 27 28
- 29 30
- 31 32
- 33 34
- 35 36
- 37 38
- 39 40
-
-
-P2 outputs (40-pin IDC)
-
- ROM 4/8/12 OUT0 1 2 ROM 4/8/12 OUT1
- ROM 4/8/12 OUT2 3 4 ROM 4/8/12 OUT3
- GND 5 6 ROM 5/9/13 OUT0
- ROM 5/9/13 OUT1 7 8 ROM 5/9/13 OUT2
- ROM 5/9/13 OUT3 9 10 GND
- ROM 6/10/14 OUT0 11 12 ROM 6/10/14 OUT1
- ROM 6/10/14 OUT2 13 14 ROM 6/10/14 OUT3
- GND 15 16 ROM 7/11/15 OUT0
- ROM 7/11/15 OUT1 17 18 ROM 7/11/15 OUT2
- ROM 7/11/15 OUT3 19 20 GND
- RAM 4/8/12 OUT0 21 22 RAM 4/8/12 OUT1
- RAM 4/8/12 OUT2 23 24 RAM 4/8/12 OUT3
- GND 25 26 RAM 5/9/13 OUT0
- RAM 5/9/13 OUT1 27 28 RAM 5/9/13 OUT2
- RAM 5/9/13 OUT3 29 30 GND
- RAM 6/10/14 OUT0 31 32 RAM 6/10/14 OUT1
- RAM 6/10/14 OUT2 33 34 RAM 6/10/14 OUT3
- GND 35 36 RAM 7/11/15 OUT0
- RAM 7/11/15 OUT1 37 38 RAM 7/11/15 OUT2
- RAM 7/11/15 OUT3 39 40 GND
-*/
#ifndef MAME_BUS_INTELLEC4_INSDATASTOR_H
#define MAME_BUS_INTELLEC4_INSDATASTOR_H
@@ -144,56 +7,6 @@ P2 outputs (40-pin IDC)
#include "intellec4.h"
-namespace bus { namespace intellec4 {
-
-class imm4_22_device : public device_t, public device_univ_card_interface, public device_image_interface
-{
-public:
- imm4_22_device(machine_config const &mconfig, char const *tag, device_t *owner, u32 clock);
-
- virtual image_init_result call_load() override;
- virtual void call_unload() override;
-
- virtual iodevice_t image_type() const override { return IO_ROM; }
- virtual bool is_readable() const override { return true; }
- virtual bool is_writeable() const override { return false; }
- virtual bool is_creatable() const override { return false; }
- virtual bool must_be_loaded() const override { return false; }
- virtual bool is_reset_on_load() const override { return false; }
- virtual char const *file_extensions() const override { return "rom,bin"; }
- virtual char const *custom_instance_name() const override { return "promimage"; }
- virtual char const *custom_brief_instance_name() const override { return "prom"; }
-
-protected:
- virtual ioport_constructor device_input_ports() const override;
- virtual void device_start() override;
- virtual void device_reset() override;
-
- virtual DECLARE_WRITE_LINE_MEMBER(reset_4002_in) override;
-
-private:
- DECLARE_WRITE8_MEMBER(ram_out);
- DECLARE_WRITE8_MEMBER(rom_out);
- DECLARE_READ8_MEMBER(rom_in);
-
- void allocate();
- void map_ram_io();
- void map_prom();
- void unmap_prom();
-
- required_ioport m_jumpers;
-
- bool m_ram_io_mapped;
-
- u8 m_ram_page, m_rom_page;
- bool m_rom_mirror;
-
- u8 m_memory[256], m_status[64];
- std::unique_ptr<u8 []> m_prom;
-};
-
-} } // namespace bus::intellec4
-
-DECLARE_DEVICE_TYPE_NS(INTELLEC4_INST_DATA_STORAGE, bus::intellec4, imm4_22_device)
+DECLARE_DEVICE_TYPE_NS(INTELLEC4_INST_DATA_STORAGE, bus::intellec4, device_univ_card_interface)
#endif // MAME_BUS_INTELLEC4_INSDATASTOR_H
diff --git a/src/devices/bus/intellec4/intellec4.cpp b/src/devices/bus/intellec4/intellec4.cpp
index c3742062454..fb980a2efd5 100644
--- a/src/devices/bus/intellec4/intellec4.cpp
+++ b/src/devices/bus/intellec4/intellec4.cpp
@@ -7,11 +7,11 @@
#include <algorithm>
-DEFINE_DEVICE_TYPE_NS(INTELLEC4_UNIV_SLOT, bus::intellec4, univ_slot_device, "intlc4univslot", "INTELLEC 4 Universal Slot")
-DEFINE_DEVICE_TYPE_NS(INTELLEC4_UNIV_BUS, bus::intellec4, univ_bus_device, "intlc4univbus", "INTELLEC 4 Universal Bus")
+DEFINE_DEVICE_TYPE(INTELLEC4_UNIV_SLOT, bus::intellec4::univ_slot_device, "intlc4univslot", "INTELLEC 4 Universal Slot")
+DEFINE_DEVICE_TYPE(INTELLEC4_UNIV_BUS, bus::intellec4::univ_bus_device, "intlc4univbus", "INTELLEC 4 Universal Bus")
-namespace bus { namespace intellec4 {
+namespace bus::intellec4 {
/***********************************************************************
SLOT DEVICE
@@ -19,7 +19,7 @@ namespace bus { namespace intellec4 {
univ_slot_device::univ_slot_device(machine_config const &mconfig, char const *tag, device_t *owner, uint32_t clock)
: device_t(mconfig, INTELLEC4_UNIV_SLOT, tag, owner, clock)
- , device_slot_interface(mconfig, *this)
+ , device_single_card_slot_interface<device_univ_card_interface>(mconfig, *this)
, m_bus(*this, finder_base::DUMMY_TAG)
{
}
@@ -29,29 +29,18 @@ univ_slot_device::univ_slot_device(machine_config const &mconfig, char const *ta
device_t implementation
----------------------------------*/
-void univ_slot_device::device_validity_check(validity_checker &valid) const
-{
- device_t *const card(get_card_device());
- if (card && !dynamic_cast<device_univ_card_interface *>(card))
- osd_printf_error("Card device %s (%s) does not implement device_univ_card_interface\n", card->tag(), card->name());
-}
-
void univ_slot_device::device_resolve_objects()
{
- device_univ_card_interface *const univ_card(dynamic_cast<device_univ_card_interface *>(get_card_device()));
+ device_univ_card_interface *const univ_card(get_card_device());
if (univ_card)
univ_card->set_bus(*m_bus);
}
void univ_slot_device::device_start()
{
- device_t *const card(get_card_device());
- if (card && !dynamic_cast<device_univ_card_interface *>(card))
- throw emu_fatalerror("univ_slot_device: card device %s (%s) does not implement device_univ_card_interface\n", card->tag(), card->name());
}
-
/***********************************************************************
BUS DEVICE
***********************************************************************/
@@ -80,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)
{
@@ -91,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)
{
@@ -102,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)
{
@@ -120,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));
@@ -138,7 +122,7 @@ void univ_bus_device::device_start()
unsigned univ_bus_device::add_card(device_univ_card_interface &card)
{
- for (unsigned i = 0; ARRAY_LENGTH(m_cards) > i; ++i)
+ for (unsigned i = 0; std::size(m_cards) > i; ++i)
{
if (!m_cards[i])
{
@@ -146,12 +130,12 @@ unsigned univ_bus_device::add_card(device_univ_card_interface &card)
return i;
}
}
- throw emu_fatalerror("univ_bus_device: maximum number of cards (%u) exceeded\n", unsigned(ARRAY_LENGTH(m_cards)));
+ throw emu_fatalerror("univ_bus_device: maximum number of cards (%u) exceeded\n", unsigned(std::size(m_cards)));
}
void univ_bus_device::set_test(unsigned index, int state)
{
- assert(ARRAY_LENGTH(m_cards) >= index);
+ assert(std::size(m_cards) >= index);
bool const changed(bool(state) != !BIT(m_test, index));
if (changed)
{
@@ -161,10 +145,10 @@ void univ_bus_device::set_test(unsigned index, int state)
else
m_test |= u16(1U) << index;
- if ((ARRAY_LENGTH(m_cards) != index) && !(other & ~(u16(1U) << ARRAY_LENGTH(m_cards))))
+ if ((std::size(m_cards) != index) && !(other & ~(u16(1U) << std::size(m_cards))))
m_test_out_cb(state);
- for (unsigned card = 0U; (ARRAY_LENGTH(m_cards) > card) && m_cards[card]; ++card)
+ for (unsigned card = 0U; (std::size(m_cards) > card) && m_cards[card]; ++card)
{
if ((index != card) && !(other & ~(u16(1U) << index)))
m_cards[card]->test_in(state);
@@ -174,7 +158,7 @@ void univ_bus_device::set_test(unsigned index, int state)
void univ_bus_device::set_stop(unsigned index, int state)
{
- assert(ARRAY_LENGTH(m_cards) >= index);
+ assert(std::size(m_cards) >= index);
bool const changed(bool(state) != !BIT(m_stop, index));
if (changed)
{
@@ -184,10 +168,10 @@ void univ_bus_device::set_stop(unsigned index, int state)
else
m_stop |= u16(1U) << index;
- if ((ARRAY_LENGTH(m_cards) != index) && !(other & ~(u16(1U) << ARRAY_LENGTH(m_cards))))
+ if ((std::size(m_cards) != index) && !(other & ~(u16(1U) << std::size(m_cards))))
m_stop_out_cb(state);
- for (unsigned card = 0U; (ARRAY_LENGTH(m_cards) > card) && m_cards[card]; ++card)
+ for (unsigned card = 0U; (std::size(m_cards) > card) && m_cards[card]; ++card)
{
if ((index != card) && !(other & ~(u16(1U) << index)))
m_cards[card]->stop_in(state);
@@ -197,7 +181,7 @@ void univ_bus_device::set_stop(unsigned index, int state)
void univ_bus_device::set_reset_4002(unsigned index, int state)
{
- assert(ARRAY_LENGTH(m_cards) >= index);
+ assert(std::size(m_cards) >= index);
bool const changed(bool(state) != !BIT(m_reset_4002, index));
if (changed)
{
@@ -207,10 +191,10 @@ void univ_bus_device::set_reset_4002(unsigned index, int state)
else
m_reset_4002 |= u16(1U) << index;
- if ((ARRAY_LENGTH(m_cards) != index) && !(other & ~(u16(1U) << ARRAY_LENGTH(m_cards))))
+ if ((std::size(m_cards) != index) && !(other & ~(u16(1U) << std::size(m_cards))))
m_reset_4002_out_cb(state);
- for (unsigned card = 0U; (ARRAY_LENGTH(m_cards) > card) && m_cards[card]; ++card)
+ for (unsigned card = 0U; (std::size(m_cards) > card) && m_cards[card]; ++card)
{
if ((index != card) && !(other & ~(u16(1U) << index)))
m_cards[card]->reset_4002_in(state);
@@ -220,7 +204,7 @@ void univ_bus_device::set_reset_4002(unsigned index, int state)
void univ_bus_device::set_user_reset(unsigned index, int state)
{
- assert(ARRAY_LENGTH(m_cards) > index);
+ assert(std::size(m_cards) > index);
bool const changed(bool(state) != !BIT(m_user_reset, index));
if (changed)
{
@@ -233,7 +217,7 @@ void univ_bus_device::set_user_reset(unsigned index, int state)
if (!other)
m_user_reset_out_cb(state);
- for (unsigned card = 0U; (ARRAY_LENGTH(m_cards) > card) && m_cards[card]; ++card)
+ for (unsigned card = 0U; (std::size(m_cards) > card) && m_cards[card]; ++card)
{
if ((index != card) && !(other & ~(u16(1U) << index)))
m_cards[card]->user_reset_in(state);
@@ -248,7 +232,7 @@ void univ_bus_device::set_user_reset(unsigned index, int state)
***********************************************************************/
device_univ_card_interface::device_univ_card_interface(const machine_config &mconfig, device_t &device)
- : device_slot_card_interface(mconfig, device)
+ : device_interface(device, "intellec4")
, m_bus(nullptr)
, m_index(~unsigned(0))
{
@@ -257,8 +241,6 @@ device_univ_card_interface::device_univ_card_interface(const machine_config &mco
void device_univ_card_interface::interface_pre_start()
{
- device_slot_card_interface::interface_pre_start();
-
if (!m_bus)
throw device_missing_dependencies();
}
@@ -269,7 +251,7 @@ void device_univ_card_interface::set_bus(univ_bus_device &bus)
m_index = (m_bus = &bus)->add_card(*this);
}
-} } // namespace bus::intellec4
+} // namespace bus::intellec4
@@ -277,6 +259,12 @@ void device_univ_card_interface::set_bus(univ_bus_device &bus)
#include "prommemory.h"
#include "tapereader.h"
+
+// must come after including the headers that declare these extern
+template class device_finder<bus::intellec4::device_univ_card_interface, false>;
+template class device_finder<bus::intellec4::device_univ_card_interface, true>;
+
+
void intellec4_univ_cards(device_slot_interface &device)
{
device.option_add("imm4_22", INTELLEC4_INST_DATA_STORAGE);
diff --git a/src/devices/bus/intellec4/intellec4.h b/src/devices/bus/intellec4/intellec4.h
index 68fa8a8080a..206134dadfb 100644
--- a/src/devices/bus/intellec4/intellec4.h
+++ b/src/devices/bus/intellec4/intellec4.h
@@ -114,14 +114,14 @@ to implement the card in both systems.
#pragma once
-namespace bus { namespace intellec4 {
+namespace bus::intellec4 {
class univ_slot_device;
class univ_bus_device;
class device_univ_card_interface;
-class univ_slot_device : public device_t, public device_slot_interface
+class univ_slot_device : public device_t, public device_single_card_slot_interface<device_univ_card_interface>
{
public:
template <typename T, typename U>
@@ -138,9 +138,8 @@ public:
protected:
// device_t implementation
- virtual void device_validity_check(validity_checker &valid) const override ATTR_COLD;
- virtual void device_resolve_objects() override;
- virtual void device_start() override;
+ virtual void device_resolve_objects() override ATTR_COLD;
+ virtual void device_start() override ATTR_COLD;
private:
required_device<univ_bus_device> m_bus;
@@ -168,22 +167,22 @@ 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(ARRAY_LENGTH(m_cards), state); }
- DECLARE_WRITE_LINE_MEMBER(stop_in) {set_stop(ARRAY_LENGTH(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(ARRAY_LENGTH(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) << ARRAY_LENGTH(m_cards))) ? 0 : 1; }
- DECLARE_READ_LINE_MEMBER(stop_out) const { return (m_stop & ~(u16(1U) << ARRAY_LENGTH(m_cards))) ? 0 : 1; }
- DECLARE_READ_LINE_MEMBER(reset_4002_out) const { return (m_reset_4002 & ~(u16(1U) << ARRAY_LENGTH(m_cards))) ? 0 : 1; }
- DECLARE_READ_LINE_MEMBER(user_reset_out) const { return (m_user_reset & ~(u16(1U) << ARRAY_LENGTH(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
- virtual void device_start() override;
+ virtual void device_start() override ATTR_COLD;
private:
// helpers for cards
@@ -211,7 +210,7 @@ private:
};
-class device_univ_card_interface : public device_slot_card_interface
+class device_univ_card_interface : public device_interface
{
protected:
friend class univ_slot_device;
@@ -220,7 +219,7 @@ protected:
device_univ_card_interface(const machine_config &mconfig, device_t &device);
// device_interface implementation
- void interface_pre_start() override;
+ void interface_pre_start() override ATTR_COLD;
address_space &rom_space() { return *m_bus->m_rom_space; }
address_space &rom_ports_space() { return *m_bus->m_rom_ports_space; }
@@ -228,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); }
+ 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 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) { }
+ 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);
@@ -248,7 +247,7 @@ private:
unsigned m_index;
};
-} } // namespace bus::intellec4
+} // namespace bus::intellec4
DECLARE_DEVICE_TYPE_NS(INTELLEC4_UNIV_SLOT, bus::intellec4, univ_slot_device)
diff --git a/src/devices/bus/intellec4/prommemory.cpp b/src/devices/bus/intellec4/prommemory.cpp
index 0eab857a72f..2a0c783d030 100644
--- a/src/devices/bus/intellec4/prommemory.cpp
+++ b/src/devices/bus/intellec4/prommemory.cpp
@@ -1,38 +1,151 @@
// license:BSD-3-Clause
// copyright-holders:Vas Crabb
+/*
+imm6-26 PROM Memory Module
+
+This card has sockets for sixteen 1702A or similar 256×8 PROMs providing
+up to 4KiB of program storage. This card has additional features for
+INTELLEC 8 systems, including module select lines and DIP switches for
+mapping PROMs in place of console RAM. These features are not emulated
+by this class.
+
+In theory you could populate any combination of sockets, and use
+multiple cards provided you don't populate corresponding sockets on two
+cards. To simplify things, we assume contiguous sockets are populated
+starting with PROM 0 (A2). In practice, you'd want to populate this
+socket as the boot vector is at address zero. If you want to simulate
+unpopulated sockets, just zero the corresponding area in your image
+file.
+
+
+Universal edge connector
+
+ 1 2
+ GND 3 4 GND
+ 5 6
+ 7 8
+ 9 10
+ MAD 0 11 12 MAD 1
+ MAD 2 13 14 MAD 3
+ MAD 4 15 16 MAD 5
+ MAD 6 17 18 MAD 7
+ MAD 8 19 20 MAD 9
+ 21 22
+ MDI 0 23 24
+ MDI 1 25 26
+ MDI 3 27 28
+ MDI 2 29 30
+ MDI 5 31 32
+ MDI 4 33 34
+ MDI 7 35 36
+ MDI 6 37 38
+ 39 40
+ 41 42
+ -10V 43 44 -10V
+ 45 46
+ 47 48
+ 49 50
+ 51 52
+ 53 54
+ 55 56
+ /MAD 12 57 58 MS 12
+ MAD 13 59 60 MAD 12
+ MS 13 61 62 /MAD 13
+ /MAD 14 63 64 MS 14
+ MAD 15 65 66 MAD 14
+ MS 15 67 68 /MAD 15
+ 69 70
+ 71 72
+ 73 74
+ 75 76
+ 77 78
+ 79 80
+ 81 82 /ASMB
+ 83 84
+ 85 86
+ 87 88
+ 89 90
+ /ADR STB 91 92
+ RAM MOD ENBL 93 94 MAD 11
+ 95 96 MAD 10
+ /PROM MOD ENBL 97 98
+ +5V 99 100 +5V
+
+MAD 0...MAD 7 mapped to MA0...MA7 on INTELLEC 4
+MAD 8...MAD 11 mapped to C0...C3 on INTELLEC 4
+MAD 12...MAD 15 not used on INTELLEC 4, used for module selection on INTELLEC 8
+/MAD 12.../MAD 15 not used on INTELLEC 4, used for module selection on INTELLEC 8
+MS 12...MS 15 not used on INTELLEC 4, used for module selection on INTELLEC 8
+MDI 0...7 data outputs
+/ASMB global enable mapped to /PROM SEL on INTELLEC 4, not jumpered in on INTELLEC 8
+/ADR STB not jumpered in on INTELLEC 4 and INTELLEC 8, latch enables jumpered to GND
+RAM MOD ENBL not jumpered in on INTELLEC 4, allows PROM to overlay RAM on INTELLEC 8
+/PROM MOD ENBL not jumpered in on INTELLEC 4, used as global enable on INTELLEC 8
+*/
#include "emu.h"
#include "prommemory.h"
-DEFINE_DEVICE_TYPE_NS(INTELLEC4_PROM_MEMORY, bus::intellec4, imm6_26_device, "intlc4_imm6_26", "Intel imm6-26 PROM Memory Module")
+namespace {
+class imm6_26_device
+ : public device_t
+ , public bus::intellec4::device_univ_card_interface
+ , public device_image_interface
+{
+public:
+ imm6_26_device(machine_config const &mconfig, char const *tag, device_t *owner, u32 clock);
+
+ 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; }
+ 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 char const *file_extensions() const noexcept override { return "rom,bin"; }
+ virtual char const *image_type_name() const noexcept override { return "promimage"; }
+ virtual char const *image_brief_type_name() const noexcept override { return "prom"; }
+
+protected:
+ virtual void device_start() override ATTR_COLD;
+
+private:
+ void allocate();
+ void unmap();
+
+ std::unique_ptr<u8 []> m_data;
+};
-namespace bus { namespace intellec4 {
imm6_26_device::imm6_26_device(machine_config const &mconfig, char const *tag, device_t *owner, u32 clock)
: device_t(mconfig, INTELLEC4_PROM_MEMORY, tag, owner, clock)
- , device_univ_card_interface(mconfig, *this)
+ , bus::intellec4::device_univ_card_interface(mconfig, *this)
, device_image_interface(mconfig, *this)
, m_data()
{
}
-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()
@@ -64,4 +177,7 @@ void imm6_26_device::unmap()
rom_space().unmap_read(0x1000U, 0x1fffU);
}
-} } // namespace bus::intellec4
+} // anonymous namespace
+
+
+DEFINE_DEVICE_TYPE_PRIVATE(INTELLEC4_PROM_MEMORY, bus::intellec4::device_univ_card_interface, imm6_26_device, "intlc4_imm6_26", "Intel imm6-26 PROM Memory Module")
diff --git a/src/devices/bus/intellec4/prommemory.h b/src/devices/bus/intellec4/prommemory.h
index 77605103af4..74f90f342c5 100644
--- a/src/devices/bus/intellec4/prommemory.h
+++ b/src/devices/bus/intellec4/prommemory.h
@@ -1,87 +1,5 @@
// license:BSD-3-Clause
// copyright-holders:Vas Crabb
-/*
-imm6-26 PROM Memory Module
-
-This card has sockets for sixteen 1702A or similar 256×8 PROMs providing
-up to 4KiB of program storage. This card has additional features for
-INTELLEC 8 systems, including module select lines and DIP switches for
-mapping PROMs in place of console RAM. These features are not emulated
-by this class.
-
-In theory you could populate any combination of sockets, and use
-multiple cards provided you don't populate corresponding sockets on two
-cards. To simplify things, we assume contiguous sockets are populated
-starting with PROM 0 (A2). In practice, you'd want to populate this
-socket as the boot vector is at address zero. If you want to simulate
-unpopulated sockets, just zero the corresponding area in your image
-file.
-
-
-Universal edge connector
-
- 1 2
- GND 3 4 GND
- 5 6
- 7 8
- 9 10
- MAD 0 11 12 MAD 1
- MAD 2 13 14 MAD 3
- MAD 4 15 16 MAD 5
- MAD 6 17 18 MAD 7
- MAD 8 19 20 MAD 9
- 21 22
- MDI 0 23 24
- MDI 1 25 26
- MDI 3 27 28
- MDI 2 29 30
- MDI 5 31 32
- MDI 4 33 34
- MDI 7 35 36
- MDI 6 37 38
- 39 40
- 41 42
- -10V 43 44 -10V
- 45 46
- 47 48
- 49 50
- 51 52
- 53 54
- 55 56
- /MAD 12 57 58 MS 12
- MAD 13 59 60 MAD 12
- MS 13 61 62 /MAD 13
- /MAD 14 63 64 MS 14
- MAD 15 65 66 MAD 14
- MS 15 67 68 /MAD 15
- 69 70
- 71 72
- 73 74
- 75 76
- 77 78
- 79 80
- 81 82 /ASMB
- 83 84
- 85 86
- 87 88
- 89 90
- /ADR STB 91 92
- RAM MOD ENBL 93 94 MAD 11
- 95 96 MAD 10
- /PROM MOD ENBL 97 98
- +5V 99 100 +5V
-
-MAD 0...MAD 7 mapped to MA0...MA7 on INTELLEC 4
-MAD 8...MAD 11 mapped to C0...C3 on INTELLEC 4
-MAD 12...MAD 15 not used on INTELLEC 4, used for module selection on INTELLEC 8
-/MAD 12.../MAD 15 not used on INTELLEC 4, used for module selection on INTELLEC 8
-MS 12...MS 15 not used on INTELLEC 4, used for module selection on INTELLEC 8
-MDI 0...7 data outputs
-/ASMB global enable mapped to /PROM SEL on INTELLEC 4, not jumpered in on INTELLEC 8
-/ADR STB not jumpered in on INTELLEC 4 and INTELLEC 8, latch enables jumpered to GND
-RAM MOD ENBL not jumpered in on INTELLEC 4, allows PROM to overlay RAM on INTELLEC 8
-/PROM MOD ENBL not jumpered in on INTELLEC 4, used as global enable on INTELLEC 8
-*/
#ifndef MAME_BUS_INTELLEC4_PROMMEMORY_H
#define MAME_BUS_INTELLEC4_PROMMEMORY_H
@@ -89,38 +7,6 @@ RAM MOD ENBL not jumpered in on INTELLEC 4, allows PROM to overlay RAM on
#include "intellec4.h"
-namespace bus { namespace intellec4 {
-
-class imm6_26_device : public device_t, public device_univ_card_interface, public device_image_interface
-{
-public:
- imm6_26_device(machine_config const &mconfig, char const *tag, device_t *owner, u32 clock);
-
- virtual image_init_result call_load() override;
- virtual void call_unload() override;
-
- virtual iodevice_t image_type() const override { return IO_ROM; }
- virtual bool is_readable() const override { return true; }
- virtual bool is_writeable() const override { return false; }
- virtual bool is_creatable() const override { return false; }
- virtual bool must_be_loaded() const override { return false; }
- virtual bool is_reset_on_load() const override { return false; }
- virtual char const *file_extensions() const override { return "rom,bin"; }
- virtual char const *custom_instance_name() const override { return "promimage"; }
- virtual char const *custom_brief_instance_name() const override { return "prom"; }
-
-protected:
- virtual void device_start() override;
-
-private:
- void allocate();
- void unmap();
-
- std::unique_ptr<u8 []> m_data;
-};
-
-} } // namespace bus::intellec4
-
-DECLARE_DEVICE_TYPE_NS(INTELLEC4_PROM_MEMORY, bus::intellec4, imm6_26_device)
+DECLARE_DEVICE_TYPE_NS(INTELLEC4_PROM_MEMORY, bus::intellec4, device_univ_card_interface)
#endif // MAME_BUS_INTELLEC4_PROMMEMORY_H
diff --git a/src/devices/bus/intellec4/tapereader.cpp b/src/devices/bus/intellec4/tapereader.cpp
index dad9c62f494..f935b7c216e 100644
--- a/src/devices/bus/intellec4/tapereader.cpp
+++ b/src/devices/bus/intellec4/tapereader.cpp
@@ -1,19 +1,61 @@
// license:BSD-3-Clause
// copyright-holders:Vas Crabb
+/*
+imm4-90 High-Speed Paper Tape Reader
+
+The monitor PROM has support for loading BNPF or Intel HEX from this
+device (use J command to select it), but it doesn't appear in any
+catalogues or manuals I've seen. Apparently it was announced in
+Computerworld.
+
+In practice you needed a GPIO card (e.g. an imm4-60 or imm4-22) to talk
+to the paper taper reader. To simplify configuration we emulate the I/O
+interface and paper tape reader as a single device.
+*/
#include "emu.h"
#include "tapereader.h"
+#include "imagedev/papertape.h"
+
+
+namespace {
+
+class imm4_90_device
+ : public paper_tape_reader_device
+ , public bus::intellec4::device_univ_card_interface
+{
+public:
+ imm4_90_device(machine_config const &mconfig, char const *tag, device_t *owner, u32 clock);
+
+ 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"; }
+
+protected:
+ virtual void device_start() override ATTR_COLD;
-DEFINE_DEVICE_TYPE_NS(INTELLEC4_TAPE_READER, bus::intellec4, imm4_90_device, "intlc4_imm4_90", "Intel imm4-90 High-Speed Paper Tape Reader")
+private:
+ u8 rom4_in() { return m_ready ? 0x07U : 0x0fU; }
+ u8 rom6_in() { return ~m_data & 0x0fU; }
+ u8 rom7_in() { return (~m_data >> 4) & 0x0fU; }
+ void rom4_out(u8 data) { advance(BIT(data, 3)); }
+ void advance(int state);
+ TIMER_CALLBACK_MEMBER(step);
+ emu_timer *m_step_timer;
+
+ u8 m_data;
+ bool m_ready;
+ bool m_advance;
+ bool m_stepping;
+};
-namespace bus { namespace intellec4 {
imm4_90_device::imm4_90_device(machine_config const &mconfig, char const *tag, device_t *owner, u32 clock)
- : device_t(mconfig, INTELLEC4_TAPE_READER, tag, owner, clock)
- , device_univ_card_interface(mconfig, *this)
- , device_image_interface(mconfig, *this)
+ : paper_tape_reader_device(mconfig, INTELLEC4_TAPE_READER, tag, owner, clock)
+ , bus::intellec4::device_univ_card_interface(mconfig, *this)
, m_step_timer(nullptr)
, m_data(0xffU)
, m_ready(false)
@@ -23,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()
@@ -43,21 +85,21 @@ void imm4_90_device::call_unload()
void imm4_90_device::device_start()
{
- m_step_timer = machine().scheduler().timer_alloc(timer_expired_delegate(FUNC(imm4_90_device::step), this));
+ m_step_timer = timer_alloc(FUNC(imm4_90_device::step), this);
save_item(NAME(m_data));
save_item(NAME(m_ready));
save_item(NAME(m_advance));
save_item(NAME(m_stepping));
- rom_ports_space().install_read_handler(0x0040U, 0x004fU, 0x0000U, 0x1f00U, 0x0000, read8_delegate(FUNC(imm4_90_device::rom4_in), this));
- rom_ports_space().install_read_handler(0x0060U, 0x006fU, 0x0000U, 0x1f00U, 0x0000, read8_delegate(FUNC(imm4_90_device::rom6_in), this));
- rom_ports_space().install_read_handler(0x0070U, 0x007fU, 0x0000U, 0x1f00U, 0x0000, read8_delegate(FUNC(imm4_90_device::rom7_in), this));
- rom_ports_space().install_write_handler(0x0040U, 0x004fU, 0x0000U, 0x1f00U, 0x0000, write8_delegate(FUNC(imm4_90_device::rom4_out), this));
+ rom_ports_space().install_read_handler(0x0040U, 0x004fU, 0x0000U, 0x1f00U, 0x0000, read8smo_delegate(*this, FUNC(imm4_90_device::rom4_in)));
+ rom_ports_space().install_read_handler(0x0060U, 0x006fU, 0x0000U, 0x1f00U, 0x0000, read8smo_delegate(*this, FUNC(imm4_90_device::rom6_in)));
+ rom_ports_space().install_read_handler(0x0070U, 0x007fU, 0x0000U, 0x1f00U, 0x0000, read8smo_delegate(*this, FUNC(imm4_90_device::rom7_in)));
+ rom_ports_space().install_write_handler(0x0040U, 0x004fU, 0x0000U, 0x1f00U, 0x0000, write8smo_delegate(*this, FUNC(imm4_90_device::rom4_out)));
}
-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)
@@ -83,4 +125,7 @@ TIMER_CALLBACK_MEMBER(imm4_90_device::step)
}
}
-} } // namespace bus::intellec4
+} // anonymous namespace
+
+
+DEFINE_DEVICE_TYPE_PRIVATE(INTELLEC4_TAPE_READER, bus::intellec4::device_univ_card_interface, imm4_90_device, "intlc4_imm4_90", "Intel imm4-90 High-Speed Paper Tape Reader")
diff --git a/src/devices/bus/intellec4/tapereader.h b/src/devices/bus/intellec4/tapereader.h
index 71153f042df..64baeb996ca 100644
--- a/src/devices/bus/intellec4/tapereader.h
+++ b/src/devices/bus/intellec4/tapereader.h
@@ -1,17 +1,5 @@
// license:BSD-3-Clause
// copyright-holders:Vas Crabb
-/*
-imm4-90 High-Speed Paper Tape Reader
-
-The monitor PROM has support for loading BNPF or Intel HEX from this
-device (use J command to select it), but it doesn't appear in any
-catalogues or manuals I've seen. Apparently it was announced in
-Computerworld.
-
-In practice you needed a GPIO card (e.g. an imm4-60 or imm4-22) to talk
-to the paper taper reader. To simplify configuration we emulate the I/O
-interface and paper tape reader as a single device.
-*/
#ifndef MAME_BUS_INTELLEC4_TAPEREADER_H
#define MAME_BUS_INTELLEC4_TAPEREADER_H
@@ -19,45 +7,6 @@ interface and paper tape reader as a single device.
#include "intellec4.h"
-namespace bus { namespace intellec4 {
-
-class imm4_90_device : public device_t, public device_univ_card_interface, public device_image_interface
-{
-public:
- imm4_90_device(machine_config const &mconfig, char const *tag, device_t *owner, u32 clock);
-
- virtual image_init_result call_load() override;
- virtual void call_unload() override;
-
- virtual iodevice_t image_type() const override { return IO_PUNCHTAPE; }
- virtual bool is_readable() const override { return true; }
- virtual bool is_writeable() const override { return false; }
- virtual bool is_creatable() const override { return false; }
- virtual bool must_be_loaded() const override { return false; }
- virtual bool is_reset_on_load() const override { return false; }
- virtual char const *file_extensions() const override { return "bnpf,hex,lst,txt"; }
-
-protected:
- virtual void device_start() override;
-
-private:
- DECLARE_READ8_MEMBER(rom4_in) { return m_ready ? 0x07U : 0x0fU; }
- DECLARE_READ8_MEMBER(rom6_in) { return ~m_data & 0x0fU; }
- DECLARE_READ8_MEMBER(rom7_in) { return (~m_data >> 4) & 0x0fU; }
- DECLARE_WRITE8_MEMBER(rom4_out) { advance(BIT(data, 3)); }
- DECLARE_WRITE_LINE_MEMBER(advance);
- TIMER_CALLBACK_MEMBER(step);
-
- emu_timer *m_step_timer;
-
- u8 m_data;
- bool m_ready;
- bool m_advance;
- bool m_stepping;
-};
-
-} } // namespace bus::intellec4
-
-DECLARE_DEVICE_TYPE_NS(INTELLEC4_TAPE_READER, bus::intellec4, imm4_90_device)
+DECLARE_DEVICE_TYPE_NS(INTELLEC4_TAPE_READER, bus::intellec4, device_univ_card_interface)
#endif // MAME_BUS_INTELLEC4_TAPEREADER_H
diff --git a/src/devices/bus/interpro/keyboard/hle.cpp b/src/devices/bus/interpro/keyboard/hle.cpp
index 15dd262eddf..9f2ddacdc39 100644
--- a/src/devices/bus/interpro/keyboard/hle.cpp
+++ b/src/devices/bus/interpro/keyboard/hle.cpp
@@ -120,9 +120,9 @@
#define VERBOSE 0
#include "logmacro.h"
-DEFINE_DEVICE_TYPE_NS(INTERPRO_HLE_EN_US_KEYBOARD, bus::interpro::keyboard, hle_en_us_device, "kbd_hle_en_us", "InterPro Keyboard (HLE, US English)")
+DEFINE_DEVICE_TYPE(INTERPRO_HLE_EN_US_KEYBOARD, bus::interpro::keyboard::hle_en_us_device, "kbd_hle_en_us", "InterPro Keyboard (HLE, US English)")
-namespace bus { namespace interpro { namespace keyboard {
+namespace bus::interpro::keyboard {
namespace {
@@ -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);
}
@@ -285,7 +285,7 @@ void hle_device_base::device_add_mconfig(machine_config &config)
void hle_device_base::device_start()
{
- m_click_timer = timer_alloc(CLICK_TIMER_ID);
+ m_click_timer = timer_alloc(FUNC(hle_device_base::click_tick), this);
save_item(NAME(m_make_count));
save_item(NAME(m_rx_state));
@@ -316,18 +316,10 @@ void hle_device_base::device_reset()
start_processing(attotime::from_hz(1'200));
}
-void hle_device_base::device_timer(emu_timer &timer, device_timer_id id, int param, void *ptr)
+TIMER_CALLBACK_MEMBER(hle_device_base::click_tick)
{
- switch (id)
- {
- case CLICK_TIMER_ID:
- m_beeper_state &= ~u8(BEEPER_CLICK);
- m_beeper->set_state(m_beeper_state ? 1 : 0);
- break;
-
- default:
- break;
- }
+ m_beeper_state &= ~u8(BEEPER_CLICK);
+ m_beeper->set_state(m_beeper_state ? 1 : 0);
}
void hle_device_base::tra_callback()
@@ -461,4 +453,4 @@ u8 hle_en_us_device::translate(u8 row, u8 column)
return TRANSLATION_TABLE[map][row][column];
}
-} } } // namespace bus::interpro::keyboard
+} // namespace bus::interpro::keyboard
diff --git a/src/devices/bus/interpro/keyboard/hle.h b/src/devices/bus/interpro/keyboard/hle.h
index 944569b9658..10953f9af0f 100644
--- a/src/devices/bus/interpro/keyboard/hle.h
+++ b/src/devices/bus/interpro/keyboard/hle.h
@@ -1,7 +1,7 @@
// license:BSD-3-Clause
// copyright-holders:Patrick Mackinlay
-#ifndef MAME_DEVICES_INTERPRO_KEYBOARD_HLE_H
-#define MAME_DEVICES_INTERPRO_KEYBOARD_HLE_H
+#ifndef MAME_BUS_INTERPRO_KEYBOARD_HLE_H
+#define MAME_BUS_INTERPRO_KEYBOARD_HLE_H
#pragma once
@@ -10,7 +10,7 @@
#include "sound/beep.h"
#include "diserial.h"
-namespace bus { namespace interpro { namespace keyboard {
+namespace bus::interpro::keyboard {
class hle_device_base
: public device_t
@@ -21,17 +21,16 @@ 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
hle_device_base(machine_config const &mconfig, device_type type, char const *tag, device_t *owner, u32 clock);
// device overrides
- virtual void device_add_mconfig(machine_config &config) override;
- virtual void device_start() override;
- virtual void device_reset() override;
- virtual void device_timer(emu_timer &timer, device_timer_id id, int param, void *ptr) override;
+ 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;
// device_buffered_serial_interface overrides
virtual void tra_callback() override;
@@ -87,6 +86,8 @@ private:
COMMAND_LAYOUT = 0x0fU
};
+ TIMER_CALLBACK_MEMBER(click_tick);
+
// device_buffered_serial_interface overrides
virtual void received_byte(u8 byte) override;
@@ -106,15 +107,15 @@ class hle_en_us_device : public hle_device_base
public:
hle_en_us_device(machine_config const &mconfig, char const *tag, device_t *owner, u32 clock);
- virtual ioport_constructor device_input_ports() const override;
+ virtual ioport_constructor device_input_ports() const override ATTR_COLD;
virtual u8 translate(u8 row, u8 column) override;
required_ioport m_modifiers;
};
-} } } // namespace bus::interpro::keyboard
+} // namespace bus::interpro::keyboard
DECLARE_DEVICE_TYPE_NS(INTERPRO_HLE_EN_US_KEYBOARD, bus::interpro::keyboard, hle_en_us_device)
-#endif // MAME_DEVICES_INTERPRO_KEYBOARD_HLE_H
+#endif // MAME_BUS_INTERPRO_KEYBOARD_HLE_H
diff --git a/src/devices/bus/interpro/keyboard/keyboard.cpp b/src/devices/bus/interpro/keyboard/keyboard.cpp
index 10b0a038d9e..0c108497ecb 100644
--- a/src/devices/bus/interpro/keyboard/keyboard.cpp
+++ b/src/devices/bus/interpro/keyboard/keyboard.cpp
@@ -11,7 +11,7 @@ DEFINE_DEVICE_TYPE(INTERPRO_KEYBOARD_PORT, interpro_keyboard_port_device, "inter
interpro_keyboard_port_device::interpro_keyboard_port_device(machine_config const &mconfig, char const *tag, device_t *owner, uint32_t clock)
: device_t(mconfig, INTERPRO_KEYBOARD_PORT, tag, owner, clock)
- , device_slot_interface(mconfig, *this)
+ , device_single_card_slot_interface<device_interpro_keyboard_port_interface>(mconfig, *this)
, m_rxd_handler(*this)
, m_dev(nullptr)
{
@@ -19,22 +19,21 @@ interpro_keyboard_port_device::interpro_keyboard_port_device(machine_config cons
void interpro_keyboard_port_device::device_config_complete()
{
- m_dev = dynamic_cast<device_interpro_keyboard_port_interface *>(get_card_device());
+ m_dev = get_card_device();
}
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);
}
device_interpro_keyboard_port_interface::device_interpro_keyboard_port_interface(machine_config const &mconfig, device_t &device)
- : device_slot_card_interface(mconfig, device)
+ : device_interface(device, "interprokbd")
, m_port(dynamic_cast<interpro_keyboard_port_device *>(device.owner()))
{
}
diff --git a/src/devices/bus/interpro/keyboard/keyboard.h b/src/devices/bus/interpro/keyboard/keyboard.h
index 05c672a0ad7..20cbff48f1f 100644
--- a/src/devices/bus/interpro/keyboard/keyboard.h
+++ b/src/devices/bus/interpro/keyboard/keyboard.h
@@ -7,7 +7,7 @@
class device_interpro_keyboard_port_interface;
-class interpro_keyboard_port_device : public device_t, public device_slot_interface
+class interpro_keyboard_port_device : public device_t, public device_single_card_slot_interface<device_interpro_keyboard_port_interface>
{
friend class device_interpro_keyboard_port_interface;
@@ -28,10 +28,10 @@ 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;
+ virtual void device_start() override ATTR_COLD;
virtual void device_config_complete() override;
private:
@@ -40,14 +40,14 @@ private:
device_interpro_keyboard_port_interface *m_dev;
};
-class device_interpro_keyboard_port_interface : public device_slot_card_interface
+class device_interpro_keyboard_port_interface : public device_interface
{
friend class interpro_keyboard_port_device;
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 595130b4c74..11deb78f137 100644
--- a/src/devices/bus/interpro/keyboard/lle.cpp
+++ b/src/devices/bus/interpro/keyboard/lle.cpp
@@ -148,16 +148,15 @@
#include "speaker.h"
#include "machine/keyboard.ipp"
-#define LOG_GENERAL (1U << 0)
#define LOG_RXTX (1U << 1)
#define LOG_PORT (1U << 2)
#define VERBOSE (0)
#include "logmacro.h"
-DEFINE_DEVICE_TYPE_NS(INTERPRO_LLE_EN_US_KEYBOARD, bus::interpro::keyboard, lle_en_us_device, "kbd_lle_en_us", "InterPro Keyboard (LLE, US English)")
+DEFINE_DEVICE_TYPE(INTERPRO_LLE_EN_US_KEYBOARD, bus::interpro::keyboard::lle_en_us_device, "kbd_lle_en_us", "InterPro Keyboard (LLE, US English)")
-namespace bus { namespace interpro { namespace keyboard {
+namespace bus::interpro::keyboard {
namespace {
@@ -480,14 +479,14 @@ void lle_device_base::ext_map(address_map &map)
// not clear what these addresses correspond to, possibly
// used in manufacturer testing?
if (VERBOSE & LOG_GENERAL)
- map(0x7fe, 0x7ff).lw8("write",
- [this](address_space &space, offs_t offset, u8 data, u8 mem_mask)
- {
- LOG("write offset 0x%03f data 0x%02x (%s)\n", offset, data, machine().describe_context());
- });
+ map(0x7fe, 0x7ff).lw8(
+ [this] (offs_t offset, u8 data, u8 mem_mask)
+ {
+ LOG("write offset 0x%03f data 0x%02x (%s)\n", offset, data, machine().describe_context());
+ }, "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,12 +501,12 @@ 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;
}
-WRITE8_MEMBER(lle_device_base::p1_w)
+void lle_device_base::p1_w(u8 data)
{
LOGMASKED(LOG_PORT, "p1_w 0x%02x (%s)\n", data, machine().describe_context());
@@ -534,7 +533,7 @@ WRITE8_MEMBER(lle_device_base::p1_w)
m_p1 = data;
}
-WRITE8_MEMBER(lle_device_base::p2_w)
+void lle_device_base::p2_w(u8 data)
{
LOGMASKED(LOG_PORT, "p2_w 0x%02x (%s)\n", data, machine().describe_context());
@@ -573,7 +572,7 @@ WRITE8_MEMBER(lle_device_base::p2_w)
m_p2 = data;
}
-READ8_MEMBER(lle_device_base::bus_r)
+u8 lle_device_base::bus_r()
{
if (!BIT(m_p1, 5))
{
@@ -587,7 +586,7 @@ READ8_MEMBER(lle_device_base::bus_r)
return 0xff;
}
-WRITE8_MEMBER(lle_device_base::bus_w)
+void lle_device_base::bus_w(u8 data)
{
if (data != 0xff)
LOGMASKED(LOG_PORT, "bus_w 0x%02x (%s)\n", data, machine().describe_context());
@@ -610,4 +609,4 @@ ioport_constructor lle_en_us_device::device_input_ports() const
return INPUT_PORTS_NAME(lle_en_us_device);
}
-} } } // namespace bus::interpro::keyboard
+} // namespace bus::interpro::keyboard
diff --git a/src/devices/bus/interpro/keyboard/lle.h b/src/devices/bus/interpro/keyboard/lle.h
index ef288bb0da6..9bd869adbfa 100644
--- a/src/devices/bus/interpro/keyboard/lle.h
+++ b/src/devices/bus/interpro/keyboard/lle.h
@@ -1,7 +1,7 @@
// license:BSD-3-Clause
// copyright-holders:Patrick Mackinlay
-#ifndef MAME_DEVICES_INTERPRO_KEYBOARD_LLE_H
-#define MAME_DEVICES_INTERPRO_KEYBOARD_LLE_H
+#ifndef MAME_BUS_INTERPRO_KEYBOARD_LLE_H
+#define MAME_BUS_INTERPRO_KEYBOARD_LLE_H
#pragma once
@@ -12,7 +12,7 @@
#include "machine/bankdev.h"
#include "sound/spkrdev.h"
-namespace bus { namespace interpro { namespace keyboard {
+namespace bus::interpro::keyboard {
class lle_device_base
: public device_t
@@ -23,21 +23,21 @@ protected:
lle_device_base(machine_config const &mconfig, device_type type, char const *tag, device_t *owner, u32 clock);
// device overrides
- virtual void device_add_mconfig(machine_config &config) override;
- virtual void device_start() override;
- virtual void device_reset() override;
+ 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;
- virtual void io_map(address_map &map);
- virtual void ext_map(address_map &map);
+ virtual void io_map(address_map &map) ATTR_COLD;
+ virtual void ext_map(address_map &map) ATTR_COLD;
- 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);
- DECLARE_WRITE8_MEMBER(p1_w);
- DECLARE_WRITE8_MEMBER(p2_w);
- DECLARE_READ8_MEMBER(bus_r);
- DECLARE_WRITE8_MEMBER(bus_w);
+ int t0_r();
+ int t1_r();
+ void p1_w(u8 data);
+ void p2_w(u8 data);
+ u8 bus_r();
+ void bus_w(u8 data);
private:
required_device<i8049_device> m_mcu;
@@ -62,12 +62,12 @@ class lle_en_us_device : public lle_device_base
public:
lle_en_us_device(machine_config const &mconfig, char const *tag, device_t *owner, u32 clock);
- virtual ioport_constructor device_input_ports() const override;
- virtual tiny_rom_entry const *device_rom_region() const override;
+ virtual ioport_constructor device_input_ports() const override ATTR_COLD;
+ virtual tiny_rom_entry const *device_rom_region() const override ATTR_COLD;
};
-} } } // namespace bus::interpro::keyboard
+} // namespace bus::interpro::keyboard
DECLARE_DEVICE_TYPE_NS(INTERPRO_LLE_EN_US_KEYBOARD, bus::interpro::keyboard, lle_en_us_device)
-#endif // MAME_DEVICES_INTERPRO_KEYBOARD_LLE_H
+#endif // MAME_BUS_INTERPRO_KEYBOARD_LLE_H
diff --git a/src/devices/bus/interpro/mouse/mouse.cpp b/src/devices/bus/interpro/mouse/mouse.cpp
index 5a8789db802..4da5259173d 100644
--- a/src/devices/bus/interpro/mouse/mouse.cpp
+++ b/src/devices/bus/interpro/mouse/mouse.cpp
@@ -26,19 +26,19 @@ DEFINE_DEVICE_TYPE(INTERPRO_MOUSE, interpro_mouse_device, "interpro_mouse", "Int
static INPUT_PORTS_START(interpro_mouse)
PORT_START("mouse_buttons")
- PORT_BIT(interpro_mouse_device::MOUSE_LBUTTON, IP_ACTIVE_HIGH, IPT_BUTTON1) PORT_NAME("Mouse Left Button") PORT_CODE(MOUSECODE_BUTTON1) PORT_CHANGED_MEMBER(DEVICE_SELF, interpro_mouse_device, mouse_button, 0)
- PORT_BIT(interpro_mouse_device::MOUSE_MBUTTON, IP_ACTIVE_HIGH, IPT_BUTTON2) PORT_NAME("Mouse Middle Button") PORT_CODE(MOUSECODE_BUTTON3) PORT_CHANGED_MEMBER(DEVICE_SELF, interpro_mouse_device, mouse_button, 0)
- PORT_BIT(interpro_mouse_device::MOUSE_RBUTTON, IP_ACTIVE_HIGH, IPT_BUTTON3) PORT_NAME("Mouse Right Button") PORT_CODE(MOUSECODE_BUTTON2) PORT_CHANGED_MEMBER(DEVICE_SELF, interpro_mouse_device, mouse_button, 0)
+ PORT_BIT(interpro_mouse_device::MOUSE_LBUTTON, IP_ACTIVE_HIGH, IPT_BUTTON1) PORT_NAME("Mouse Left Button") PORT_CODE(MOUSECODE_BUTTON1) PORT_CHANGED_MEMBER(DEVICE_SELF, FUNC(interpro_mouse_device::mouse_button), 0)
+ PORT_BIT(interpro_mouse_device::MOUSE_MBUTTON, IP_ACTIVE_HIGH, IPT_BUTTON2) PORT_NAME("Mouse Middle Button") PORT_CODE(MOUSECODE_BUTTON3) PORT_CHANGED_MEMBER(DEVICE_SELF, FUNC(interpro_mouse_device::mouse_button), 0)
+ PORT_BIT(interpro_mouse_device::MOUSE_RBUTTON, IP_ACTIVE_HIGH, IPT_BUTTON3) PORT_NAME("Mouse Right Button") PORT_CODE(MOUSECODE_BUTTON2) PORT_CHANGED_MEMBER(DEVICE_SELF, FUNC(interpro_mouse_device::mouse_button), 0)
PORT_START("mouse_x")
- PORT_BIT(0xff, 0x00, IPT_MOUSE_X) PORT_SENSITIVITY(50) PORT_KEYDELTA(0) PORT_PLAYER(1) PORT_CHANGED_MEMBER(DEVICE_SELF, interpro_mouse_device, mouse_x, 0)
+ PORT_BIT(0xff, 0x00, IPT_MOUSE_X) PORT_SENSITIVITY(50) PORT_KEYDELTA(0) PORT_PLAYER(1) PORT_CHANGED_MEMBER(DEVICE_SELF, FUNC(interpro_mouse_device::mouse_x), 0)
PORT_START("mouse_y")
- PORT_BIT(0xff, 0x00, IPT_MOUSE_Y) PORT_SENSITIVITY(50) PORT_KEYDELTA(0) PORT_PLAYER(1) PORT_CHANGED_MEMBER(DEVICE_SELF, interpro_mouse_device, mouse_y, 0)
+ PORT_BIT(0xff, 0x00, IPT_MOUSE_Y) PORT_SENSITIVITY(50) PORT_KEYDELTA(0) PORT_PLAYER(1) PORT_CHANGED_MEMBER(DEVICE_SELF, FUNC(interpro_mouse_device::mouse_y), 0)
INPUT_PORTS_END
interpro_mouse_port_device::interpro_mouse_port_device(machine_config const &mconfig, char const *tag, device_t *owner, uint32_t clock)
: device_t(mconfig, INTERPRO_MOUSE_PORT, tag, owner, clock)
- , device_slot_interface(mconfig, *this)
+ , device_single_card_slot_interface<device_interpro_mouse_port_interface>(mconfig, *this)
, m_state_func(*this)
, m_device(nullptr)
{
@@ -46,24 +46,15 @@ interpro_mouse_port_device::interpro_mouse_port_device(machine_config const &mco
void interpro_mouse_port_device::device_config_complete()
{
- m_device = dynamic_cast<device_interpro_mouse_port_interface *>(get_card_device());
-}
-
-void interpro_mouse_port_device::device_validity_check(validity_checker &valid) const
-{
- device_t *const card(get_card_device());
-
- if (card && !dynamic_cast<device_interpro_mouse_port_interface *>(card))
- osd_printf_error("Device %s (%s) does not implement device_interpro_mouse_port_interface\n", card->tag(), card->name());
+ m_device = get_card_device();
}
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)
- : device_slot_card_interface(mconfig, device)
+ : device_interface(device, "interpromouse")
, m_port(dynamic_cast<interpro_mouse_port_device *>(device.owner()))
{
}
@@ -98,7 +89,7 @@ INPUT_CHANGED_MEMBER(interpro_mouse_device::mouse_button)
LOG("mouse_button 0x%08x\n", data);
- state_w(machine().dummy_space(), 0, data & MOUSE_BUTTONS, MOUSE_BUTTONS);
+ state_w(data & MOUSE_BUTTONS, MOUSE_BUTTONS);
}
INPUT_CHANGED_MEMBER(interpro_mouse_device::mouse_x)
@@ -112,7 +103,7 @@ INPUT_CHANGED_MEMBER(interpro_mouse_device::mouse_x)
LOG("mouse_x delta %d\n", delta);
- state_w(machine().dummy_space(), 0, (delta << 8) & MOUSE_XPOS, MOUSE_XPOS);
+ state_w((delta << 8) & MOUSE_XPOS, MOUSE_XPOS);
}
INPUT_CHANGED_MEMBER(interpro_mouse_device::mouse_y)
@@ -126,5 +117,5 @@ INPUT_CHANGED_MEMBER(interpro_mouse_device::mouse_y)
LOG("mouse_y delta %d\n", delta);
- state_w(machine().dummy_space(), 0, (delta << 0) & MOUSE_YPOS, MOUSE_YPOS);
+ state_w((delta << 0) & MOUSE_YPOS, MOUSE_YPOS);
}
diff --git a/src/devices/bus/interpro/mouse/mouse.h b/src/devices/bus/interpro/mouse/mouse.h
index c5969ba4667..72d1bc816b7 100644
--- a/src/devices/bus/interpro/mouse/mouse.h
+++ b/src/devices/bus/interpro/mouse/mouse.h
@@ -7,7 +7,7 @@
class device_interpro_mouse_port_interface;
-class interpro_mouse_port_device : public device_t, public device_slot_interface
+class interpro_mouse_port_device : public device_t, public device_single_card_slot_interface<device_interpro_mouse_port_interface>
{
friend class device_interpro_mouse_port_interface;
@@ -29,8 +29,7 @@ public:
protected:
// device-level overrides
- virtual void device_validity_check(validity_checker &valid) const override;
- virtual void device_start() override;
+ virtual void device_start() override ATTR_COLD;
virtual void device_config_complete() override;
private:
@@ -39,16 +38,15 @@ private:
device_interpro_mouse_port_interface *m_device;
};
-class device_interpro_mouse_port_interface : public device_slot_card_interface
+class device_interpro_mouse_port_interface : public device_interface
{
friend class interpro_mouse_port_device;
-public:
- DECLARE_WRITE32_MEMBER(state_w) { m_port->m_state_func(space, offset, data, mem_mask); }
-
protected:
device_interpro_mouse_port_interface(machine_config const &mconfig, device_t &device);
+ void state_w(u32 data, u32 mem_mask) { m_port->m_state_func(offs_t(0), data, mem_mask); }
+
private:
interpro_mouse_port_device *m_port;
};
@@ -76,10 +74,10 @@ public:
protected:
// device overrides
- virtual void device_start() override;
- virtual void device_reset() override;
+ virtual void device_start() override ATTR_COLD;
+ virtual void device_reset() override ATTR_COLD;
- virtual ioport_constructor device_input_ports() const override;
+ virtual ioport_constructor device_input_ports() const override ATTR_COLD;
private:
};
diff --git a/src/devices/bus/interpro/sr/edge.cpp b/src/devices/bus/interpro/sr/edge.cpp
index 4c6453a5341..4d4df1113a1 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)
@@ -301,14 +300,14 @@ void edge1_device_base::map(address_map &map)
void edge1_device_base::map_dynamic(address_map &map)
{
// TODO: map using lambdas until mixed-size submaps work
- map(0x00000000, 0x0001ffff).lrw8("sram",
- [this](address_space &space, offs_t offset, u8 mem_mask) { return m_sram->read(offset); },
- [this](address_space &space, offs_t offset, u8 data, u8 mem_mask) { m_sram->write(offset, data); });
+ map(0x00000000, 0x0001ffff).lrw8(
+ NAME([this](address_space &space, offs_t offset, u8 mem_mask) { return m_sram->read(offset); }),
+ NAME([this](address_space &space, offs_t offset, u8 data, u8 mem_mask) { m_sram->write(offset, data); }));
- map(0x01000000, 0x013fffff).lrw8("vram",
- [this](address_space &space, offs_t offset, u8 mem_mask) { return m_vram->read((offset >> 2) | (offset & 0x3)); },
- [this](address_space &space, offs_t offset, u8 data, u8 mem_mask) { m_vram->write((offset >> 2) | (offset & 0x3), data); });
+ map(0x01000000, 0x013fffff).lrw8(
+ NAME([this](address_space &space, offs_t offset, u8 mem_mask) { return m_vram->read((offset >> 2) | (offset & 0x3)); }),
+ NAME([this](address_space &space, offs_t offset, u8 data, u8 mem_mask) { m_vram->write((offset >> 2) | (offset & 0x3), data); }));
//map(0x02028200, 0x0202827f).lr32("idprom",
// [this](address_space &space, offs_t offset, u8 mem_mask) { return memregion("idprom")->as_u32(offset); });
@@ -350,8 +349,8 @@ void edge2plus_processor_device_base::map(address_map &map)
{
map(0x000, 0x003).rw(FUNC(edge2plus_processor_device_base::reg0_r), FUNC(edge2plus_processor_device_base::reg0_w));
- map(0x008, 0x008).lr8("mouse_x", []() { return 0; });
- map(0x00c, 0x00c).lr8("mouse_y", []() { return 0; });
+ map(0x008, 0x008).lr8([]() { return 0; }, "mouse_x");
+ map(0x00c, 0x00c).lr8([]() { return 0; }, "mouse_y");
map(0x010, 0x01f).rw("scc", FUNC(z80scc_device::dc_ab_r), FUNC(z80scc_device::dc_ab_w)).umask32(0x000000ff);
@@ -377,18 +376,18 @@ void edge2plus_framebuffer_device_base::map_dynamic(address_map &map)
{
// TODO: map using lambdas until mixed-size submaps work
- map(0x00000000, 0x0003ffff).lrw8("sram",
- [this](address_space &space, offs_t offset, u8 mem_mask) { return m_sram->read(offset); },
- [this](address_space &space, offs_t offset, u8 data, u8 mem_mask) { m_sram->write(offset, data); });
+ map(0x00000000, 0x0003ffff).lrw8(
+ NAME([this](address_space &space, offs_t offset, u8 mem_mask) { return m_sram->read(offset); }),
+ NAME([this](address_space &space, offs_t offset, u8 data, u8 mem_mask) { m_sram->write(offset, data); }));
- map(0x01000000, 0x01ffffff).lrw8("vram",
- [this](address_space &space, offs_t offset, u8 mem_mask) { return m_vram->read(offset); },
- [this](address_space &space, offs_t offset, u8 data, u8 mem_mask) { m_vram->write(offset, data); });
+ map(0x01000000, 0x01ffffff).lrw8(
+ NAME([this](address_space &space, offs_t offset, u8 mem_mask) { return m_vram->read(offset); }),
+ NAME([this](address_space &space, offs_t offset, u8 data, u8 mem_mask) { m_vram->write(offset, data); }));
map(0x02028088, 0x0202808b).w(FUNC(edge2plus_framebuffer_device_base::select_w));
- map(0x02028200, 0x0202827f).lr32("idprom",
- [this](address_space &space, offs_t offset, u8 mem_mask) { return m_select == 0 ? memregion("idprom")->as_u32(offset) : space.unmap(); });
+ map(0x02028200, 0x0202827f).lr32(
+ NAME([this](address_space &space, offs_t offset, u8 mem_mask) { return m_select == 0 ? memregion("idprom")->as_u32(offset) : space.unmap(); }));
map(0x02028290, 0x02028293).w(FUNC(edge2plus_framebuffer_device_base::lut_select_w));
map(0x02028300, 0x02028303).w(FUNC(edge2plus_framebuffer_device_base::unk_300_w));
@@ -479,7 +478,7 @@ void mpcb828_device::device_add_mconfig(machine_config &config)
BT458(config, "ramdac", 83'020'800);
- SCC8530N(config, m_scc, 4.9152_MHz_XTAL);
+ SCC8530(config, m_scc, 4.9152_MHz_XTAL);
m_scc->out_int_callback().set(FUNC(mpcb828_device::scc_irq));
m_scc->out_txda_callback().set("kbd", FUNC(interpro_keyboard_port_device::write_txd));
@@ -510,7 +509,7 @@ void mpcb849_device::device_add_mconfig(machine_config &config)
BT458(config, "ramdac", 0); // unconfirmed clock
- SCC8530N(config, m_scc, 4.9152_MHz_XTAL);
+ SCC8530(config, m_scc, 4.9152_MHz_XTAL);
m_scc->out_int_callback().set(FUNC(mpcb849_device::scc_irq));
m_scc->out_txda_callback().set("kbd", FUNC(interpro_keyboard_port_device::write_txd));
@@ -562,7 +561,7 @@ void msmt094_device::device_add_mconfig(machine_config &config)
//TMS32030(config, m_dsp3, 40_MHz_XTAL);
// FIXME: actually Z0853006VSC
- scc8530_device& scc(SCC8530N(config, "scc", 4.9152_MHz_XTAL));
+ scc8530_device& scc(SCC8530(config, "scc", 4.9152_MHz_XTAL));
scc.out_int_callback().set(FUNC(msmt094_device::scc_irq));
scc.out_txda_callback().set("kbd", FUNC(interpro_keyboard_port_device::write_txd));
@@ -607,6 +606,7 @@ edge2plus_processor_device_base::edge2plus_processor_device_base(const machine_c
, device_srx_card_interface(mconfig, *this)
, m_dsp1(*this, "dsp1")
, m_screen(nullptr)
+ , m_sram(nullptr)
{
}
@@ -702,12 +702,11 @@ void edge2plus_framebuffer_device_base::device_start()
LOG("found processor device %s\n", processor->tag());
processor->register_screen(m_screen, m_sram);
+ processor->m_dsp1->set_addrmap(0, address_map_constructor(&edge2plus_framebuffer_device_base::map_dynamic, processor->m_dsp1->tag(), this));
}
// FIXME: dynamically allocate SR region 4
m_bus->install_map(*this, 0x90000000, 0x93ffffff, &edge2plus_framebuffer_device_base::map_dynamic);
-
- processor->m_dsp1->set_addrmap(0, address_map_constructor(&edge2plus_framebuffer_device_base::map_dynamic, processor->m_dsp1->tag(), this));
}
u32 mpcb849_device::screen_update(screen_device &screen, bitmap_rgb32 &bitmap, const rectangle &cliprect)
@@ -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)
{
@@ -763,7 +762,7 @@ u32 edge2plus_framebuffer_device_base::screen_update(screen_device &screen, bitm
return 0;
}
-WRITE32_MEMBER(edge1_device_base::control_w)
+void edge1_device_base::control_w(offs_t offset, u32 data, u32 mem_mask)
{
// clear interrupt
if (m_control & HOLDA_INT_H && !(data & HOLDA_INT_H))
@@ -780,7 +779,7 @@ WRITE32_MEMBER(edge1_device_base::control_w)
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);
@@ -799,7 +798,7 @@ WRITE_LINE_MEMBER(edge1_device_base::holda)
m_status &= ~DSP_1_HOLDA_H;
}
-WRITE32_MEMBER(edge2plus_processor_device_base::control_w)
+void edge2plus_processor_device_base::control_w(offs_t offset, u32 data, u32 mem_mask)
{
COMBINE_DATA(&m_control);
@@ -812,7 +811,7 @@ WRITE32_MEMBER(edge2plus_processor_device_base::control_w)
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);
@@ -832,16 +831,16 @@ WRITE_LINE_MEMBER(edge2plus_processor_device_base::holda)
void edge2plus_processor_device_base::dsp1_map(address_map &map)
{
- map(0x00000, 0x3ffff).lrw8("sram",
- [this](address_space &space, offs_t offset, u8 mem_mask) { return m_sram->read(offset); },
- [this](address_space &space, offs_t offset, u8 data, u8 mem_mask) { m_sram->write(offset, data); });
+ map(0x00000, 0x3ffff).lrw8(
+ NAME([this](address_space &space, offs_t offset, u8 mem_mask) { return m_sram ? m_sram->read(offset) : 0; }),
+ NAME([this](address_space &space, offs_t offset, u8 data, u8 mem_mask) { if (m_sram) m_sram->write(offset, data); }));
- map(0x40000, 0x7ffff).lr32("prg1",
- [this](address_space &space, offs_t offset, u32 mem_mask) { return memregion("prg1")->as_u32(offset); });
+ map(0x40000, 0x7ffff).lr32(
+ NAME([this](address_space &space, offs_t offset, u32 mem_mask) { return memregion("prg1")->as_u32(offset); }));
}
-WRITE32_MEMBER(edge2plus_framebuffer_device_base::lut_select_w)
+void edge2plus_framebuffer_device_base::lut_select_w(u32 data)
{
LOG("select ramdac %d\n", data);
@@ -855,7 +854,7 @@ WRITE32_MEMBER(edge2plus_framebuffer_device_base::lut_select_w)
// 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;
@@ -865,19 +864,19 @@ WRITE_LINE_MEMBER(edge1_device_base::scc_irq)
irq0(state);
}
-READ32_MEMBER(edge1_device_base::reg0_r)
+u32 edge1_device_base::reg0_r()
{
return ((m_reg0 & ~VBLANK) | (m_screen->vblank() ? VBLANK : 0));
}
-WRITE32_MEMBER(edge1_device_base::kernel_w)
+void edge1_device_base::kernel_w(offs_t offset, u32 data, u32 mem_mask)
{
COMBINE_DATA(&m_kernel);
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;
@@ -887,16 +886,17 @@ WRITE_LINE_MEMBER(edge2plus_processor_device_base::scc_irq)
irq0(state);
}
-WRITE32_MEMBER(edge2plus_processor_device_base::kernel_w)
+void edge2plus_processor_device_base::kernel_w(offs_t offset, u32 data, u32 mem_mask)
{
COMBINE_DATA(&m_kernel);
m_status |= KREG_IN_FULL; // FIXME: what clears this?
}
-READ32_MEMBER(edge2plus_processor_device_base::reg0_r)
+u32 edge2plus_processor_device_base::reg0_r()
{
- LOG("reg0_r vblank %d\n", m_screen->vblank());
+ if (m_screen)
+ LOG("reg0_r vblank %d\n", m_screen->vblank());
return (m_screen == nullptr) ? (m_reg0 & ~VBLANK) : ((m_reg0 & ~VBLANK) | (m_screen->vblank() ? VBLANK : 0));
}
diff --git a/src/devices/bus/interpro/sr/edge.h b/src/devices/bus/interpro/sr/edge.h
index ad6c6dfbb1b..45ece91a02f 100644
--- a/src/devices/bus/interpro/sr/edge.h
+++ b/src/devices/bus/interpro/sr/edge.h
@@ -17,40 +17,40 @@
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);
- virtual void map(address_map &map) override;
- virtual void map_dynamic(address_map &map);
- virtual void device_start() override;
+ virtual void map(address_map &map) override ATTR_COLD;
+ virtual void map_dynamic(address_map &map) ATTR_COLD;
+ virtual void device_start() override ATTR_COLD;
u32 screen_update(screen_device &screen, bitmap_rgb32 &bitmap, const rectangle &cliprect);
- DECLARE_WRITE_LINE_MEMBER(scc_irq);
+ void scc_irq(int state);
- DECLARE_READ32_MEMBER(reg0_r);
- DECLARE_WRITE32_MEMBER(reg0_w) { COMBINE_DATA(&m_reg0); }
+ u32 reg0_r();
+ void reg0_w(offs_t offset, u32 data, u32 mem_mask = ~0) { COMBINE_DATA(&m_reg0); }
- DECLARE_READ32_MEMBER(control_r) { return m_control; };
- DECLARE_WRITE32_MEMBER(control_w);
- DECLARE_READ32_MEMBER(status_r) { return m_status; };
- DECLARE_WRITE32_MEMBER(status_w) { COMBINE_DATA(&m_status); }
- DECLARE_READ32_MEMBER(fifo_r) { return m_fifo; };
- DECLARE_WRITE32_MEMBER(fifo_w) { COMBINE_DATA(&m_fifo); }
- DECLARE_READ32_MEMBER(kernel_r) { return m_kernel; };
- DECLARE_WRITE32_MEMBER(kernel_w);
+ u32 control_r() { return m_control; }
+ void control_w(offs_t offset, u32 data, u32 mem_mask = ~0);
+ u32 status_r() { return m_status; }
+ void status_w(offs_t offset, u32 data, u32 mem_mask = ~0) { COMBINE_DATA(&m_status); }
+ u32 fifo_r() { return m_fifo; }
+ void fifo_w(offs_t offset, u32 data, u32 mem_mask = ~0) { COMBINE_DATA(&m_fifo); }
+ u32 kernel_r() { return m_kernel; }
+ void kernel_w(offs_t offset, u32 data, u32 mem_mask = ~0);
- DECLARE_READ32_MEMBER(attention_r) { return m_attention; };
- DECLARE_WRITE32_MEMBER(attention_w) { COMBINE_DATA(&m_attention); }
+ u32 attention_r() { return m_attention; }
+ void attention_w(offs_t offset, u32 data, u32 mem_mask = ~0) { COMBINE_DATA(&m_attention); }
- DECLARE_WRITE32_MEMBER(ififo_lwm_w) { COMBINE_DATA(&m_ififo_lwm); }
- DECLARE_WRITE32_MEMBER(ififo_hwm_w) { COMBINE_DATA(&m_ififo_hwm); }
+ void ififo_lwm_w(offs_t offset, u32 data, u32 mem_mask = ~0) { COMBINE_DATA(&m_ififo_lwm); }
+ void ififo_hwm_w(offs_t offset, u32 data, u32 mem_mask = ~0) { COMBINE_DATA(&m_ififo_hwm); }
- DECLARE_READ32_MEMBER(srx_master_control_r) { return m_srx_master_control; }
- DECLARE_WRITE32_MEMBER(srx_master_control_w) { COMBINE_DATA(&m_srx_master_control); }
+ u32 srx_master_control_r() { return m_srx_master_control; }
+ void srx_master_control_w(offs_t offset, u32 data, u32 mem_mask = ~0) { COMBINE_DATA(&m_srx_master_control); }
required_device<screen_device> m_screen;
required_device<ram_device> m_sram;
@@ -79,9 +79,9 @@ class edge2_processor_device_base : public device_t, public device_srx_card_inte
protected:
edge2_processor_device_base(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock);
- virtual void map(address_map &map) override;
+ virtual void map(address_map &map) override ATTR_COLD;
- virtual void device_start() override {};
+ virtual void device_start() override {}
};
class edge2_framebuffer_device_base : public device_t, public device_srx_card_interface
@@ -89,9 +89,9 @@ class edge2_framebuffer_device_base : public device_t, public device_srx_card_in
protected:
edge2_framebuffer_device_base(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock);
- virtual void map(address_map &map) override;
+ virtual void map(address_map &map) override ATTR_COLD;
- virtual void device_start() override {};
+ virtual void device_start() override {}
};
class edge2plus_processor_device_base : public device_t, public device_srx_card_interface
@@ -103,30 +103,30 @@ public:
protected:
edge2plus_processor_device_base(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock);
- virtual void map(address_map &map) override;
+ virtual void map(address_map &map) override ATTR_COLD;
- void dsp1_map(address_map &map);
+ void dsp1_map(address_map &map) ATTR_COLD;
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);
- DECLARE_READ32_MEMBER(control_r) { return m_control; };
- DECLARE_WRITE32_MEMBER(control_w);
- DECLARE_READ32_MEMBER(status_r) { return m_status; };
- DECLARE_WRITE32_MEMBER(status_w) { COMBINE_DATA(&m_status); }
- DECLARE_READ32_MEMBER(kernel_r) { return m_kernel; };
- DECLARE_WRITE32_MEMBER(kernel_w);
- DECLARE_WRITE32_MEMBER(mapping_w) { COMBINE_DATA(&m_mapping); }
- DECLARE_READ32_MEMBER(attention_r) { return m_attention; };
- DECLARE_WRITE32_MEMBER(attention_w) { COMBINE_DATA(&m_attention); }
+ u32 control_r() { return m_control; }
+ void control_w(offs_t offset, u32 data, u32 mem_mask = ~0);
+ u32 status_r() { return m_status; }
+ void status_w(offs_t offset, u32 data, u32 mem_mask = ~0) { COMBINE_DATA(&m_status); }
+ u32 kernel_r() { return m_kernel; }
+ void kernel_w(offs_t offset, u32 data, u32 mem_mask = ~0);
+ void mapping_w(offs_t offset, u32 data, u32 mem_mask = ~0) { COMBINE_DATA(&m_mapping); }
+ u32 attention_r() { return m_attention; }
+ void attention_w(offs_t offset, u32 data, u32 mem_mask = ~0) { COMBINE_DATA(&m_attention); }
- DECLARE_WRITE32_MEMBER(ififo_lwm_w) { COMBINE_DATA(&m_ififo_lwm); }
- DECLARE_WRITE32_MEMBER(ififo_hwm_w) { COMBINE_DATA(&m_ififo_hwm); }
+ void ififo_lwm_w(offs_t offset, u32 data, u32 mem_mask = ~0) { COMBINE_DATA(&m_ififo_lwm); }
+ void ififo_hwm_w(offs_t offset, u32 data, u32 mem_mask = ~0) { COMBINE_DATA(&m_ififo_hwm); }
- DECLARE_READ32_MEMBER(reg0_r);
- DECLARE_WRITE32_MEMBER(reg0_w) { COMBINE_DATA(&m_reg0); }
+ u32 reg0_r();
+ void reg0_w(offs_t offset, u32 data, u32 mem_mask = ~0) { COMBINE_DATA(&m_reg0); }
private:
@@ -152,19 +152,19 @@ protected:
edge2plus_framebuffer_device_base(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock);
- virtual void map(address_map &map) override;
- virtual void device_start() override;
+ virtual void map(address_map &map) override ATTR_COLD;
+ virtual void device_start() override ATTR_COLD;
- virtual void map_dynamic(address_map &map);
+ virtual void map_dynamic(address_map &map) ATTR_COLD;
u32 screen_update(screen_device &screen, bitmap_rgb32 &bitmap, const rectangle &cliprect);
- DECLARE_WRITE32_MEMBER(lut_select_w);
+ void lut_select_w(u32 data);
- DECLARE_WRITE32_MEMBER(unk_300_w) { m_unk_304 = 0x1000; }
- DECLARE_READ32_MEMBER(unk_304_r) { m_unk_304 ^= 0x1000; return m_unk_304; }
+ void unk_300_w(u32 data) { m_unk_304 = 0x1000; }
+ u32 unk_304_r() { m_unk_304 ^= 0x1000; return m_unk_304; }
- DECLARE_WRITE32_MEMBER(select_w) { COMBINE_DATA(&m_select); }
+ void select_w(offs_t offset, u32 data, u32 mem_mask = ~0) { COMBINE_DATA(&m_select); }
required_device<screen_device> m_screen;
required_device<ram_device> m_sram;
@@ -182,8 +182,8 @@ public:
mpcb828_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;
- virtual void device_add_mconfig(machine_config &config) override;
+ virtual const tiny_rom_entry *device_rom_region() const override ATTR_COLD;
+ virtual void device_add_mconfig(machine_config &config) override ATTR_COLD;
};
class mpcb849_device : public edge1_device_base
@@ -192,8 +192,8 @@ public:
mpcb849_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;
- virtual void device_add_mconfig(machine_config &config) override;
+ virtual const tiny_rom_entry *device_rom_region() const override ATTR_COLD;
+ virtual void device_add_mconfig(machine_config &config) override ATTR_COLD;
u32 screen_update(screen_device &screen, bitmap_rgb32 &bitmap, const rectangle &cliprect);
};
@@ -204,8 +204,8 @@ public:
mpcb030_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;
- virtual void device_add_mconfig(machine_config &config) override;
+ virtual const tiny_rom_entry *device_rom_region() const override ATTR_COLD;
+ virtual void device_add_mconfig(machine_config &config) override ATTR_COLD;
};
class msmt094_device : public edge2plus_processor_device_base
@@ -214,8 +214,8 @@ public:
msmt094_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;
- virtual void device_add_mconfig(machine_config &config) override;
+ virtual const tiny_rom_entry *device_rom_region() const override ATTR_COLD;
+ virtual void device_add_mconfig(machine_config &config) override ATTR_COLD;
};
class mpcba63_device : public edge2_framebuffer_device_base
@@ -224,8 +224,8 @@ public:
mpcba63_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;
- virtual void device_add_mconfig(machine_config &config) override;
+ virtual const tiny_rom_entry *device_rom_region() const override ATTR_COLD;
+ virtual void device_add_mconfig(machine_config &config) override ATTR_COLD;
u32 screen_update(screen_device &screen, bitmap_rgb32 &bitmap, const rectangle &cliprect);
};
@@ -236,8 +236,8 @@ public:
mpcb896_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;
- virtual void device_add_mconfig(machine_config &config) override;
+ virtual const tiny_rom_entry *device_rom_region() const override ATTR_COLD;
+ virtual void device_add_mconfig(machine_config &config) override ATTR_COLD;
};
// device type definition
diff --git a/src/devices/bus/interpro/sr/gt.cpp b/src/devices/bus/interpro/sr/gt.cpp
index d3a7d99d2c7..5a7dc3c4639 100644
--- a/src/devices/bus/interpro/sr/gt.cpp
+++ b/src/devices/bus/interpro/sr/gt.cpp
@@ -107,7 +107,12 @@
#include "gt.h"
-#define LOG_GENERAL (1U << 0)
+#include "bus/rs232/rs232.h"
+#include "bus/rs232/loopback.h"
+
+#include "bus/interpro/keyboard/keyboard.h"
+#include "bus/interpro/mouse/mouse.h"
+
#define LOG_LINE (1U << 1)
#define LOG_BLIT (1U << 2)
@@ -182,18 +187,18 @@ void gt_device_base::map(address_map &map)
map(0x16c, 0x16f).w(FUNC(gt_device_base::ri_control_w)); // mask 1ff?
- //AM_RANGE(0x174, 0x177) AM_READWRITE(ri_xfer_r, ri_xfer_w)
- //AM_RANGE(0x178, 0x17b) AM_READWRITE(ri_xfer_r, ri_xfer_w)
+ //map(0x174, 0x177).rw(FUNC(gt_device_base::ri_xfer_r), FUNC(gt_device_base::ri_xfer_w));
+ //map(0x178, 0x17b).rw(FUNC(gt_device_base::ri_xfer_r), FUNC(gt_device_base::ri_xfer_w));
map(0x17c, 0x17f).w(FUNC(gt_device_base::ri_xfer_w));
map(0x1a4, 0x1ab).w(FUNC(gt_device_base::bsga_float_w));
map(0x1b0, 0x1b3).nopr(); //?
- //AM_RANGE(0x1c0, 0x1c3)
- //AM_RANGE(0x1c4, 0x1c7)
- //AM_RANGE(0x1c8, 0x1cb)
- //AM_RANGE(0x1cc, 0x1cf) // write32 - float conversion control (inhibit/enable overflow detection?)
+ //map(0x1c0, 0x1c3)
+ //map(0x1c4, 0x1c7)
+ //map(0x1c8, 0x1cb)
+ //map(0x1cc, 0x1cf) // write32 - float conversion control (inhibit/enable overflow detection?)
/*
* Don't know where/how these fifos come into play yet:
@@ -304,7 +309,7 @@ void gtdb_device::device_add_mconfig(machine_config &config)
{
gt_device_base::device_add_mconfig(config);
- SCC8530N(config, m_scc, 4.9152_MHz_XTAL);
+ SCC8530(config, m_scc, 4.9152_MHz_XTAL);
interpro_keyboard_port_device &keyboard(INTERPRO_KEYBOARD_PORT(config, "kbd", interpro_keyboard_devices, "lle_en_us"));
keyboard.rxd_handler_cb().set(m_scc, FUNC(z80scc_device::rxa_w));
@@ -500,6 +505,7 @@ gt_device_base::gt_device_base(const machine_config &mconfig, device_type type,
, m_vram(*this, "vram%u", 0)
, m_mram(*this, "mram%u", 0)
, m_bpu(*this, "bpu%u", 0)
+ , m_control(0)
, m_double_buffered(double_buffered)
, m_masked_reads(masked_reads)
{
@@ -609,12 +615,12 @@ void gt_device_base::device_start()
save_item(NAME(m_control));
// allocate timers
- m_blit_timer = machine().scheduler().timer_alloc(timer_expired_delegate(FUNC(gt_device_base::blit), this));
- m_line_timer = machine().scheduler().timer_alloc(timer_expired_delegate(FUNC(gt_device_base::line), this));
- m_done_timer = machine().scheduler().timer_alloc(timer_expired_delegate(FUNC(gt_device_base::done), this));
+ m_blit_timer = timer_alloc(FUNC(gt_device_base::blit), this);
+ m_line_timer = timer_alloc(FUNC(gt_device_base::line), this);
+ m_done_timer = timer_alloc(FUNC(gt_device_base::done), this);
}
-WRITE32_MEMBER(gt_device_base::control_w)
+void gt_device_base::control_w(offs_t offset, u32 data, u32 mem_mask)
{
if (data & GFX_BSGA_RST)
{
@@ -674,13 +680,13 @@ void gt_device_base::bsga_clip_status(s16 x, s16 y)
LOG("bsga_clip_status result 0x%04x\n", m_bsga_status);
}
-WRITE32_MEMBER(gt_device_base::ri_xfer_w)
+void gt_device_base::ri_xfer_w(offs_t offset, u32 data, u32 mem_mask)
{
LOG("ri_xfer_w 0x%08x mem_mask 0x%08x (%s)\n", data, mem_mask, machine().describe_context());
// initiate ri line draw
u32 address = m_ri_initial_address;
- u32 error = m_ri_initial_error;
+ s32 error = m_ri_initial_error;
for (int i = 0; i < m_ri_stop_count; i++)
{
@@ -700,7 +706,7 @@ WRITE32_MEMBER(gt_device_base::ri_xfer_w)
}
}
-WRITE32_MEMBER(gt_device_base::bsga_xin1yin1_w)
+void gt_device_base::bsga_xin1yin1_w(offs_t offset, u32 data, u32 mem_mask)
{
m_bsga_xin1 = (m_bsga_xin1 & ~(mem_mask >> 0)) | ((data & mem_mask) >> 0);
m_bsga_yin1 = (m_bsga_yin1 & ~(mem_mask >> 16)) | ((data & mem_mask) >> 16);
@@ -719,7 +725,7 @@ WRITE32_MEMBER(gt_device_base::bsga_xin1yin1_w)
m_bsga_tmp = m_bsga_xin1;
}
-WRITE32_MEMBER(gt_device_base::bsga_xin2yin2_w)
+void gt_device_base::bsga_xin2yin2_w(offs_t offset, u32 data, u32 mem_mask)
{
m_bsga_xin2 = (m_bsga_xin2 & ~(mem_mask >> 0)) | ((data & mem_mask) >> 0);
m_bsga_yin2 = (m_bsga_yin2 & ~(mem_mask >> 16)) | ((data & mem_mask) >> 16);
@@ -736,7 +742,7 @@ WRITE32_MEMBER(gt_device_base::bsga_xin2yin2_w)
m_line_timer->adjust(attotime::zero);
}
-WRITE16_MEMBER(gt_device_base::bsga_yin2_w)
+void gt_device_base::bsga_yin2_w(offs_t offset, u16 data, u16 mem_mask)
{
COMBINE_DATA(&m_bsga_yin2);
@@ -750,14 +756,14 @@ WRITE16_MEMBER(gt_device_base::bsga_yin2_w)
m_line_timer->adjust(attotime::zero);
}
-READ16_MEMBER(gt_device_base::bsga_status_r)
+u16 gt_device_base::bsga_status_r()
{
LOG("bsga_status_r 0x%04x (%s)\n", m_bsga_status, machine().describe_context());
return m_bsga_status;
}
-WRITE32_MEMBER(gt_device_base::bsga_float_w)
+void gt_device_base::bsga_float_w(offs_t offset, u32 data)
{
// TODO: when we figure out exactly what this is supposed to do, convert it
// to use softfloat instead.
@@ -805,7 +811,7 @@ WRITE32_MEMBER(gt_device_base::bsga_float_w)
LOG("bsga_float_w result 0x%04x overflow %s\n", m_bsga_xin, m_bsga_status & STATUS_FLOAT_OFLOW ? "set" : "clear");
}
-WRITE16_MEMBER(gt_device_base::blit_width_w)
+void gt_device_base::blit_width_w(offs_t offset, u16 data, u16 mem_mask)
{
// writing to blit width starts blit operation
LOG("blit_width_w 0x%04x (%s)\n", data, machine().describe_context());
@@ -953,7 +959,7 @@ TIMER_CALLBACK_MEMBER(gt_device_base::done)
m_control &= ~u32(param);
}
-WRITE8_MEMBER(gt_device_base::plane_enable_w)
+void gt_device_base::plane_enable_w(u8 data)
{
if (m_control & GFX_GRPHCS_BUSY)
return;
@@ -964,7 +970,7 @@ WRITE8_MEMBER(gt_device_base::plane_enable_w)
m_plane_enable = (data << 24) | (data << 16) | (data << 8) | (data << 0);
}
-WRITE8_MEMBER(gt_device_base::plane_data_w)
+void gt_device_base::plane_data_w(u8 data)
{
if (m_control & GFX_GRPHCS_BUSY)
return;
@@ -1366,7 +1372,7 @@ void gt_device_base::bresenham_line(s16 major, s16 minor, s16 major_step, s16 mi
LOG("bresenham_line end %d,%d\n", shallow ? major : minor, shallow ? minor : major);
}
-WRITE8_MEMBER(gt_device_base::contrast_dac_w)
+void gt_device_base::contrast_dac_w(u8 data)
{
m_ramdac[0]->set_contrast(data);
@@ -1377,14 +1383,14 @@ WRITE8_MEMBER(gt_device_base::contrast_dac_w)
/*
* GTDB support (SRX, SCC and mouse).
*/
-WRITE32_MEMBER(gtdb_device::srx_mapping_w)
+void gtdb_device::srx_mapping_w(u32 data)
{
const offs_t srx_base = data << 24;
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;
@@ -1394,7 +1400,7 @@ WRITE_LINE_MEMBER(gtdb_device::serial_irq)
irq0(state);
}
-WRITE32_MEMBER(gtdb_device::mouse_status_w)
+void gtdb_device::mouse_status_w(offs_t offset, u32 data, u32 mem_mask)
{
if (mem_mask & interpro_mouse_device::state_mask::MOUSE_XPOS)
{
@@ -1422,7 +1428,7 @@ WRITE32_MEMBER(gtdb_device::mouse_status_w)
irq0(CLEAR_LINE);
}
-READ32_MEMBER(gtdb_device::mouse_x_r)
+u32 gtdb_device::mouse_x_r()
{
const u32 result = m_mouse_x;
@@ -1431,7 +1437,7 @@ READ32_MEMBER(gtdb_device::mouse_x_r)
return result;
}
-READ32_MEMBER(gtdb_device::mouse_y_r)
+u32 gtdb_device::mouse_y_r()
{
const u32 result = m_mouse_y;
@@ -1564,7 +1570,7 @@ u32 gtdb_device::vram_r(offs_t offset, const bool linear) const
return gt_device_base::vram_r(offset, linear);
}
-void gtdb_device::vram_w(const offs_t offset, const u32 data, const u32 mem_mask, const bool linear) const
+void gtdb_device::vram_w(offs_t offset, const u32 data, u32 mem_mask, const bool linear) const
{
if (m_control & GFX_HILITE_SEL)
{
diff --git a/src/devices/bus/interpro/sr/gt.h b/src/devices/bus/interpro/sr/gt.h
index a1d069b9782..f4e2b99494e 100644
--- a/src/devices/bus/interpro/sr/gt.h
+++ b/src/devices/bus/interpro/sr/gt.h
@@ -12,18 +12,12 @@
#include "machine/ram.h"
#include "machine/z80scc.h"
-#include "bus/rs232/rs232.h"
-#include "bus/rs232/loopback.h"
-
-#include "bus/interpro/keyboard/keyboard.h"
-#include "bus/interpro/mouse/mouse.h"
-
class gt_device_base : public device_t
{
protected:
gt_device_base(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock, const bool double_buffered, const bool masked_reads);
- virtual void map(address_map &map);
+ virtual void map(address_map &map) ATTR_COLD;
public:
static constexpr u32 GT_MASK_BITS = 0x80808080; // mask RAM presents on high bit in each pixel/byte
@@ -62,44 +56,44 @@ public:
GFX_MONSENSE_60HZ = 0x0e000000,
};
- DECLARE_READ32_MEMBER(control_r) { return m_control | (m_screen[0]->vblank() ? GFX_VERT_BLNK : 0); }
- DECLARE_WRITE32_MEMBER(control_w);
+ u32 control_r() { return m_control | (m_screen[0]->vblank() ? GFX_VERT_BLNK : 0); }
+ void control_w(offs_t offset, u32 data, u32 mem_mask = ~0);
- DECLARE_WRITE8_MEMBER(contrast_dac_w);
+ void contrast_dac_w(u8 data);
- DECLARE_WRITE32_MEMBER(blit_src_address_w) { COMBINE_DATA(&m_blit_src_address); }
- DECLARE_WRITE32_MEMBER(blit_dst_address_w) { COMBINE_DATA(&m_blit_dst_address); }
- DECLARE_WRITE16_MEMBER(blit_width_w);
+ void blit_src_address_w(offs_t offset, u32 data, u32 mem_mask = ~0) { COMBINE_DATA(&m_blit_src_address); }
+ void blit_dst_address_w(offs_t offset, u32 data, u32 mem_mask = ~0) { COMBINE_DATA(&m_blit_dst_address); }
+ void blit_width_w(offs_t offset, u16 data, u16 mem_mask = ~0);
- DECLARE_READ8_MEMBER(plane_enable_r) { return m_plane_enable; }
- DECLARE_WRITE8_MEMBER(plane_enable_w);
- DECLARE_READ8_MEMBER(plane_data_r) { return m_plane_data; }
- DECLARE_WRITE8_MEMBER(plane_data_w);
+ u8 plane_enable_r() { return m_plane_enable; }
+ void plane_enable_w(u8 data);
+ u8 plane_data_r() { return m_plane_data; }
+ void plane_data_w(u8 data);
- DECLARE_READ16_MEMBER(bsga_width_r) { return m_bsga_width; }
- DECLARE_WRITE16_MEMBER(bsga_width_w) { COMBINE_DATA(&m_bsga_width); }
- DECLARE_READ16_MEMBER(bsga_tmp_r) { return m_bsga_tmp; }
- DECLARE_WRITE16_MEMBER(bsga_tmp_w) { COMBINE_DATA(&m_bsga_tmp); }
+ u16 bsga_width_r() { return m_bsga_width; }
+ void bsga_width_w(offs_t offset, u16 data, u16 mem_mask = ~0) { COMBINE_DATA(&m_bsga_width); }
+ u16 bsga_tmp_r() { return m_bsga_tmp; }
+ void bsga_tmp_w(offs_t offset, u16 data, u16 mem_mask = ~0) { COMBINE_DATA(&m_bsga_tmp); }
- DECLARE_READ16_MEMBER(bsga_xmin_r) { return m_bsga_xmin; }
- DECLARE_WRITE16_MEMBER(bsga_xmin_w) { COMBINE_DATA(&m_bsga_xmin); }
- DECLARE_READ16_MEMBER(bsga_ymin_r) { return m_bsga_ymin; }
- DECLARE_WRITE16_MEMBER(bsga_ymin_w) { COMBINE_DATA(&m_bsga_ymin); }
+ u16 bsga_xmin_r() { return m_bsga_xmin; }
+ void bsga_xmin_w(offs_t offset, u16 data, u16 mem_mask = ~0) { COMBINE_DATA(&m_bsga_xmin); }
+ u16 bsga_ymin_r() { return m_bsga_ymin; }
+ void bsga_ymin_w(offs_t offset, u16 data, u16 mem_mask = ~0) { COMBINE_DATA(&m_bsga_ymin); }
- DECLARE_READ16_MEMBER(bsga_acc0_r) { return (m_bsga_width - m_bsga_xin1); }
- DECLARE_READ16_MEMBER(bsga_acc1_r) { return -(m_bsga_width - m_bsga_xin1); }
+ u16 bsga_acc0_r() { return (m_bsga_width - m_bsga_xin1); }
+ u16 bsga_acc1_r() { return -(m_bsga_width - m_bsga_xin1); }
- DECLARE_READ16_MEMBER(bsga_xmax_r) { return m_bsga_xmax; }
- DECLARE_WRITE16_MEMBER(bsga_xmax_w) { COMBINE_DATA(&m_bsga_xmax); }
- DECLARE_READ16_MEMBER(bsga_ymax_r) { return m_bsga_ymax; }
- DECLARE_WRITE16_MEMBER(bsga_ymax_w) { COMBINE_DATA(&m_bsga_ymax); bsga_clip_status(m_bsga_xin1, m_bsga_yin1); }
+ u16 bsga_xmax_r() { return m_bsga_xmax; }
+ void bsga_xmax_w(offs_t offset, u16 data, u16 mem_mask = ~0) { COMBINE_DATA(&m_bsga_xmax); }
+ u16 bsga_ymax_r() { return m_bsga_ymax; }
+ void bsga_ymax_w(offs_t offset, u16 data, u16 mem_mask = ~0) { COMBINE_DATA(&m_bsga_ymax); bsga_clip_status(m_bsga_xin1, m_bsga_yin1); }
- DECLARE_READ16_MEMBER(bsga_src0_r) { return m_bsga_xin1; }
- DECLARE_READ16_MEMBER(bsga_src1_r) { return m_bsga_xin1; }
+ u16 bsga_src0_r() { return m_bsga_xin1; }
+ u16 bsga_src1_r() { return m_bsga_xin1; }
- DECLARE_WRITE16_MEMBER(bsga_xin1_w) { COMBINE_DATA(&m_bsga_xin1); m_bsga_xin = m_bsga_xin1; m_bsga_tmp = m_bsga_xin1; }
- DECLARE_WRITE16_MEMBER(bsga_yin1_w) { COMBINE_DATA(&m_bsga_yin1); m_bsga_yin = m_bsga_yin1; }
- DECLARE_WRITE32_MEMBER(bsga_xin1yin1_w);
+ void bsga_xin1_w(offs_t offset, u16 data, u16 mem_mask = ~0) { COMBINE_DATA(&m_bsga_xin1); m_bsga_xin = m_bsga_xin1; m_bsga_tmp = m_bsga_xin1; }
+ void bsga_yin1_w(offs_t offset, u16 data, u16 mem_mask = ~0) { COMBINE_DATA(&m_bsga_yin1); m_bsga_yin = m_bsga_yin1; }
+ void bsga_xin1yin1_w(offs_t offset, u32 data, u32 mem_mask = ~0);
enum bsga_status_mask : u16
{
@@ -121,36 +115,36 @@ public:
STATUS_CLIP1_MASK = 0x01e0,
STATUS_CLIP_MASK = 0x1fe0
};
- DECLARE_READ16_MEMBER(bsga_status_r);
+ u16 bsga_status_r();
- DECLARE_WRITE32_MEMBER(bsga_xin2yin2_w);
+ void bsga_xin2yin2_w(offs_t offset, u32 data, u32 mem_mask = ~0);
- DECLARE_WRITE16_MEMBER(bsga_xin2_w) { COMBINE_DATA(&m_bsga_xin2); m_bsga_xin = m_bsga_xin2; }
- DECLARE_WRITE16_MEMBER(bsga_yin2_w);
+ void bsga_xin2_w(offs_t offset, u16 data, u16 mem_mask = ~0) { COMBINE_DATA(&m_bsga_xin2); m_bsga_xin = m_bsga_xin2; }
+ void bsga_yin2_w(offs_t offset, u16 data, u16 mem_mask = ~0);
// FIXME: perhaps tmp is a counter of xin/yin and can be used to return correct value?
- DECLARE_READ16_MEMBER(bsga_xin_r) { return m_bsga_xin; }
- DECLARE_READ16_MEMBER(bsga_yin_r) { return m_bsga_yin; }
+ u16 bsga_xin_r() { return m_bsga_xin; }
+ u16 bsga_yin_r() { return m_bsga_yin; }
- DECLARE_WRITE32_MEMBER(ri_initial_distance_w) { COMBINE_DATA(&m_ri_initial_distance); }
- DECLARE_WRITE32_MEMBER(ri_distance_both_w) { COMBINE_DATA(&m_ri_distance_both); }
- DECLARE_WRITE32_MEMBER(ri_distance_major_w) { COMBINE_DATA(&m_ri_distance_major); }
- DECLARE_WRITE32_MEMBER(ri_initial_address_w) { COMBINE_DATA(&m_ri_initial_address); }
- DECLARE_WRITE32_MEMBER(ri_address_both_w) { COMBINE_DATA(&m_ri_address_both); }
- DECLARE_WRITE32_MEMBER(ri_address_major_w) { COMBINE_DATA(&m_ri_address_major); }
- DECLARE_WRITE32_MEMBER(ri_initial_error_w) { COMBINE_DATA(&m_ri_initial_error); }
- DECLARE_WRITE32_MEMBER(ri_error_both_w) { COMBINE_DATA(&m_ri_error_both); }
- DECLARE_WRITE32_MEMBER(ri_error_major_w) { COMBINE_DATA(&m_ri_error_major); }
+ void ri_initial_distance_w(offs_t offset, u32 data, u32 mem_mask = ~0) { COMBINE_DATA(&m_ri_initial_distance); }
+ void ri_distance_both_w(offs_t offset, u32 data, u32 mem_mask = ~0) { COMBINE_DATA(&m_ri_distance_both); }
+ void ri_distance_major_w(offs_t offset, u32 data, u32 mem_mask = ~0) { COMBINE_DATA(&m_ri_distance_major); }
+ void ri_initial_address_w(offs_t offset, u32 data, u32 mem_mask = ~0) { COMBINE_DATA(&m_ri_initial_address); }
+ void ri_address_both_w(offs_t offset, u32 data, u32 mem_mask = ~0) { COMBINE_DATA(&m_ri_address_both); }
+ void ri_address_major_w(offs_t offset, u32 data, u32 mem_mask = ~0) { COMBINE_DATA(&m_ri_address_major); }
+ void ri_initial_error_w(offs_t offset, u32 data, u32 mem_mask = ~0) { COMBINE_DATA(&m_ri_initial_error); }
+ void ri_error_both_w(offs_t offset, u32 data, u32 mem_mask = ~0) { COMBINE_DATA(&m_ri_error_both); }
+ void ri_error_major_w(offs_t offset, u32 data, u32 mem_mask = ~0) { COMBINE_DATA(&m_ri_error_major); }
- DECLARE_WRITE32_MEMBER(ri_stop_count_w) { COMBINE_DATA(&m_ri_stop_count); }
- DECLARE_WRITE32_MEMBER(ri_control_w) { COMBINE_DATA(&m_ri_control); }
- DECLARE_WRITE32_MEMBER(ri_xfer_w);
+ void ri_stop_count_w(offs_t offset, u32 data, u32 mem_mask = ~0) { COMBINE_DATA(&m_ri_stop_count); }
+ void ri_control_w(offs_t offset, u32 data, u32 mem_mask = ~0) { COMBINE_DATA(&m_ri_control); }
+ void ri_xfer_w(offs_t offset, u32 data, u32 mem_mask = ~0);
- DECLARE_WRITE32_MEMBER(bsga_float_w);
+ void bsga_float_w(offs_t offset, u32 data);
protected:
- virtual void device_start() override;
- virtual void device_add_mconfig(machine_config &config) override;
+ virtual void device_start() override ATTR_COLD;
+ virtual void device_add_mconfig(machine_config &config) override ATTR_COLD;
virtual void device_validity_check(validity_checker &valid) const override;
u32 buffer_r(const offs_t offset);
@@ -256,7 +250,7 @@ class gt_device : public gt_device_base, public device_cbus_card_interface
protected:
gt_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock, const bool double_buffered);
- virtual void map(address_map &map) override;
+ virtual void map(address_map &map) override ATTR_COLD;
};
class gtdb_device : public gt_device_base, public device_srx_card_interface
@@ -264,12 +258,12 @@ class gtdb_device : public gt_device_base, public device_srx_card_interface
protected:
gtdb_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock);
- virtual void map(address_map &map) override;
- virtual void map_dynamic(address_map &map);
+ virtual void map(address_map &map) override ATTR_COLD;
+ virtual void map_dynamic(address_map &map) ATTR_COLD;
- DECLARE_WRITE_LINE_MEMBER(serial_irq);
- DECLARE_WRITE32_MEMBER(mouse_status_w);
- DECLARE_WRITE32_MEMBER(srx_mapping_w);
+ void serial_irq(int state);
+ void mouse_status_w(offs_t offset, u32 data, u32 mem_mask = ~0);
+ void srx_mapping_w(u32 data);
enum int_status_mask
{
@@ -279,10 +273,10 @@ protected:
MOUSE_Y = 0x40,
SERIAL = 0x80,
};
- DECLARE_READ32_MEMBER(mouse_int_r) { return m_mouse_int; }
- DECLARE_WRITE32_MEMBER(mouse_int_w) { mem_mask &= ~0x7; COMBINE_DATA(&m_mouse_int); }
- DECLARE_READ32_MEMBER(mouse_x_r);
- DECLARE_READ32_MEMBER(mouse_y_r);
+ u32 mouse_int_r() { return m_mouse_int; }
+ void mouse_int_w(offs_t offset, u32 data, u32 mem_mask = ~0) { mem_mask &= ~0x7; COMBINE_DATA(&m_mouse_int); }
+ u32 mouse_x_r();
+ u32 mouse_y_r();
enum vfifo_control_mask
{
@@ -290,10 +284,10 @@ protected:
FIFO_LW_INTR = 0x40,
FIFO_HW_INTR = 0x80,
};
- DECLARE_READ32_MEMBER(fifo_control_r) { return m_fifo_control; }
+ u32 fifo_control_r() { return m_fifo_control; }
- //virtual void device_start() override;
- virtual void device_add_mconfig(machine_config &config) override;
+ //virtual void device_start() override ATTR_COLD;
+ virtual void device_add_mconfig(machine_config &config) override ATTR_COLD;
virtual u32 vram_r(offs_t offset, const bool linear = false) const override;
virtual void vram_w(offs_t offset, const u32 data, u32 mem_mask, const bool linear = false) const override;
@@ -315,8 +309,8 @@ public:
mpcb963_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;
- virtual void device_add_mconfig(machine_config &config) override;
+ virtual const tiny_rom_entry *device_rom_region() const override ATTR_COLD;
+ virtual void device_add_mconfig(machine_config &config) override ATTR_COLD;
};
class mpcba79_device : public gt_device
@@ -325,8 +319,8 @@ public:
mpcba79_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;
- virtual void device_add_mconfig(machine_config &config) override;
+ virtual const tiny_rom_entry *device_rom_region() const override ATTR_COLD;
+ virtual void device_add_mconfig(machine_config &config) override ATTR_COLD;
};
@@ -336,8 +330,8 @@ public:
msmt070_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;
- virtual void device_add_mconfig(machine_config &config) override;
+ virtual const tiny_rom_entry *device_rom_region() const override ATTR_COLD;
+ virtual void device_add_mconfig(machine_config &config) override ATTR_COLD;
};
class msmt071_device : public gt_device
@@ -346,8 +340,8 @@ public:
msmt071_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;
- virtual void device_add_mconfig(machine_config &config) override;
+ virtual const tiny_rom_entry *device_rom_region() const override ATTR_COLD;
+ virtual void device_add_mconfig(machine_config &config) override ATTR_COLD;
};
class msmt081_device : public gt_device
@@ -356,8 +350,8 @@ public:
msmt081_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;
- virtual void device_add_mconfig(machine_config &config) override;
+ virtual const tiny_rom_entry *device_rom_region() const override ATTR_COLD;
+ virtual void device_add_mconfig(machine_config &config) override ATTR_COLD;
};
class mpcbb68_device : public gtdb_device
@@ -366,8 +360,8 @@ public:
mpcbb68_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;
- virtual void device_add_mconfig(machine_config &config) override;
+ virtual const tiny_rom_entry *device_rom_region() const override ATTR_COLD;
+ virtual void device_add_mconfig(machine_config &config) override ATTR_COLD;
};
class mpcbb92_device : public gtdb_device
@@ -376,8 +370,8 @@ public:
mpcbb92_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;
- virtual void device_add_mconfig(machine_config &config) override;
+ virtual const tiny_rom_entry *device_rom_region() const override ATTR_COLD;
+ virtual void device_add_mconfig(machine_config &config) override ATTR_COLD;
};
// device type definition
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 858590f5075..ed5ae9466d8 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;
@@ -75,7 +72,7 @@ public:
offs_t end = start + (CBUS_SIZE - 1);
// install the idprom region
- read32_delegate idprom_r([idprom](address_space &space, offs_t offset, u32 mem_mask) { return idprom->as_u32(offset); }, idprom->name());
+ read32sm_delegate idprom_r(*this, [idprom] (offs_t offset) { return idprom->as_u32(offset); }, idprom->name().c_str());
m_main_space->install_read_handler(start, start | 0x7f, idprom_r);
m_io_space->install_read_handler(start, start | 0x7f, idprom_r);
@@ -87,8 +84,8 @@ public:
}
protected:
- // device-level overrides
- virtual void device_start() override;
+ // device_t implementation
+ virtual void device_start() override ATTR_COLD;
private:
device_cbus_card_interface *m_slot[CBUS_COUNT];
@@ -112,28 +109,28 @@ public:
cbus_slot_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock);
protected:
- // device-level overrides
- virtual void device_resolve_objects() override;
- virtual void device_start() override;
+ // device_t implementation
+ virtual void device_resolve_objects() override ATTR_COLD;
+ virtual void device_start() override ATTR_COLD;
private:
required_device<cbus_bus_device> m_bus;
};
-class device_cbus_card_interface : public device_slot_card_interface
+class device_cbus_card_interface : public device_interface
{
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")
- : device_slot_card_interface(mconfig, device)
+ : device_interface(device, "interprocbus")
, m_bus(nullptr)
, m_idprom_region(idprom_region)
{
@@ -171,7 +168,7 @@ public:
offs_t end = start + (SRX_SIZE - 1);
// install the idprom region
- read32_delegate idprom_r([idprom](address_space &space, offs_t offset, u32 mem_mask) { return idprom->as_u32(offset); }, idprom->name());
+ read32sm_delegate idprom_r(*this, [idprom] (offs_t offset) { return idprom->as_u32(offset); }, idprom->name().c_str());
m_main_space->install_read_handler(start | 0x7f80, start | 0x7fff, idprom_r);
m_io_space->install_read_handler(start | 0x7f80, start | 0x7fff, idprom_r);
@@ -199,8 +196,8 @@ public:
}
protected:
- // device-level overrides
- virtual void device_start() override;
+ // device_t implementation
+ virtual void device_start() override ATTR_COLD;
private:
device_srx_card_interface *m_slot[SRX_COUNT];
@@ -224,28 +221,28 @@ public:
srx_slot_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock);
protected:
- // device-level overrides
- virtual void device_resolve_objects() override;
- virtual void device_start() override;
+ // device_t implementation
+ virtual void device_resolve_objects() override ATTR_COLD;
+ virtual void device_start() override ATTR_COLD;
private:
required_device<srx_bus_device> m_bus;
};
-class device_srx_card_interface : public device_slot_card_interface
+class device_srx_card_interface : public device_interface
{
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")
- : device_slot_card_interface(mconfig, device)
+ : device_interface(device, "interprosrx")
, m_bus(nullptr)
, m_idprom_region(idprom_region)
{
diff --git a/src/devices/bus/intv/ecs.cpp b/src/devices/bus/intv/ecs.cpp
index 6fd321af36b..50d52a85c77 100644
--- a/src/devices/bus/intv/ecs.cpp
+++ b/src/devices/bus/intv/ecs.cpp
@@ -28,8 +28,8 @@
DEFINE_DEVICE_TYPE(INTV_ROM_ECS, intv_ecs_device, "intv_ecs", "Intellivision ECS Expansion")
-intv_ecs_device::intv_ecs_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
- : intv_rom_device(mconfig, INTV_ROM_ECS, tag, owner, clock),
+intv_ecs_device::intv_ecs_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) :
+ intv_rom_device(mconfig, INTV_ROM_ECS, tag, owner, clock),
m_snd(*this, "ay8914"),
m_subslot(*this, "subslot"),
m_voice_enabled(false),
@@ -99,9 +99,9 @@ void intv_ecs_device::device_add_mconfig(machine_config &config)
SPEAKER(config, "mono_ecs").front_center();
AY8914(config, m_snd, XTAL(3'579'545)/2);
- m_snd->port_a_read_callback().set("ctrl_port", FUNC(intvecs_control_port_device::portA_r));
- m_snd->port_b_read_callback().set("ctrl_port", FUNC(intvecs_control_port_device::portB_r));
- m_snd->port_a_write_callback().set("ctrl_port", FUNC(intvecs_control_port_device::portA_w));
+ m_snd->port_a_read_callback().set("ctrl_port", FUNC(intvecs_control_port_device::porta_r));
+ m_snd->port_b_read_callback().set("ctrl_port", FUNC(intvecs_control_port_device::portb_r));
+ m_snd->port_a_write_callback().set("ctrl_port", FUNC(intvecs_control_port_device::porta_w));
m_snd->add_route(ALL_OUTPUTS, "mono_ecs", 0.33);
INTVECS_CONTROL_PORT(config, "ctrl_port", intvecs_control_port_devices, "keybd");
diff --git a/src/devices/bus/intv/ecs.h b/src/devices/bus/intv/ecs.h
index 68911831c0a..de05f593421 100644
--- a/src/devices/bus/intv/ecs.h
+++ b/src/devices/bus/intv/ecs.h
@@ -63,10 +63,10 @@ public:
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;
+ 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;
+ virtual const tiny_rom_entry *device_rom_region() const override ATTR_COLD;
private:
diff --git a/src/devices/bus/intv/slot.cpp b/src/devices/bus/intv/slot.cpp
index 0c4ddae593a..2d905d273ae 100644
--- a/src/devices/bus/intv/slot.cpp
+++ b/src/devices/bus/intv/slot.cpp
@@ -74,9 +74,9 @@
***********************************************************************************************************/
-
#include "emu.h"
#include "slot.h"
+
#include "hashfile.h"
#define INTELLIVOICE_MASK 0x02
@@ -96,10 +96,10 @@ DEFINE_DEVICE_TYPE(INTV_CART_SLOT, intv_cart_slot_device, "intv_cart_slot", "Int
// device_intv_cart_interface - constructor
//-------------------------------------------------
-device_intv_cart_interface::device_intv_cart_interface(const machine_config &mconfig, device_t &device)
- : device_slot_card_interface(mconfig, device),
- m_rom(nullptr),
- m_rom_size(0)
+device_intv_cart_interface::device_intv_cart_interface(const machine_config &mconfig, device_t &device) :
+ device_interface(device, "intvcart"),
+ m_rom(nullptr),
+ m_rom_size(0)
{
}
@@ -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;
}
@@ -146,8 +146,8 @@ void device_intv_cart_interface::ram_alloc(uint32_t size)
//-------------------------------------------------
intv_cart_slot_device::intv_cart_slot_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) :
device_t(mconfig, INTV_CART_SLOT, tag, owner, clock),
- device_image_interface(mconfig, *this),
- device_slot_interface(mconfig, *this),
+ device_cartrom_image_interface(mconfig, *this),
+ device_single_card_slot_interface<device_intv_cart_interface>(mconfig, *this),
m_type(INTV_STD),
m_cart(nullptr)
{
@@ -168,7 +168,7 @@ intv_cart_slot_device::~intv_cart_slot_device()
void intv_cart_slot_device::device_start()
{
- m_cart = dynamic_cast<device_intv_cart_interface *>(get_card_device());
+ m_cart = get_card_device();
}
@@ -198,7 +198,7 @@ static int intv_get_pcb_id(const char *slot)
{
for (auto & elem : slot_list)
{
- if (!core_stricmp(elem.slot_option, slot))
+ if (!strcmp(elem.slot_option, slot))
return elem.pcb_id;
}
@@ -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,20 +372,20 @@ 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};
- const char* region_name[] = {"0400", "2000", "4000", "4800", "5000", "6000", "7000", "8000", "8800", "9000", "A000", "B000", "C000", "D000", "E000", "F000"};
+ const char* region_name[] = {"0400", "2000", "4000", "4800", "5000", "6000", "7000", "8000", "8800", "9000", "a000", "b000", "c000", "d000", "e000", "f000"};
const char *pcb_name = get_feature("slot");
bool extra_bank = false;
@@ -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());
}
@@ -440,13 +440,13 @@ std::string intv_cart_slot_device::get_default_card_software(get_default_card_so
{
if (hook.image_file())
{
- const char *slot_string;
- uint32_t len = hook.image_file()->size();
+ uint64_t len;
+ hook.image_file()->length(len); // FIXME: check error return, guard against excessively large files
std::vector<uint8_t> rom(len);
- int type = INTV_STD;
- hook.image_file()->read(&rom[0], len);
+ 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)))
{
// it's .ROM file, so that we don't have currently any way to distinguish RAM-equipped carts
@@ -454,18 +454,17 @@ std::string intv_cart_slot_device::get_default_card_software(get_default_card_so
else
{
// assume it's .BIN and try to use .hsi file to determine type (just RAM)
- int start;
- int mapper, rom[5], ram, extra;
std::string extrainfo;
if (hook.hashfile_extrainfo(extrainfo))
{
+ int mapper, rom[5], ram, extra;
sscanf(extrainfo.c_str() ,"%d %d %d %d %d %d %d", &mapper, &rom[0], &rom[1], &rom[2],
&rom[3], &ram, &extra);
if (ram)
{
- start = ((ram & 0xf0) >> 4) * 0x1000;
+ int const start = ((ram & 0xf0) >> 4) * 0x1000;
if (start == 0xd000)
type = INTV_RAM;
if (start == 0x8800)
@@ -475,7 +474,7 @@ std::string intv_cart_slot_device::get_default_card_software(get_default_card_so
}
- slot_string = intv_get_slot(type);
+ char const *const slot_string = intv_get_slot(type);
//printf("type: %s\n", slot_string);
diff --git a/src/devices/bus/intv/slot.h b/src/devices/bus/intv/slot.h
index ec79b148375..1cd770836d3 100644
--- a/src/devices/bus/intv/slot.h
+++ b/src/devices/bus/intv/slot.h
@@ -5,7 +5,7 @@
#pragma once
-#include "softlist_dev.h"
+#include "imagedev/cartrom.h"
/***************************************************************************
@@ -32,7 +32,7 @@ enum
// ======================> device_intv_cart_interface
-class device_intv_cart_interface : public device_slot_card_interface
+class device_intv_cart_interface : public device_interface
{
public:
// construction/destruction
@@ -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]; }
@@ -93,8 +93,8 @@ protected:
// ======================> intv_cart_slot_device
class intv_cart_slot_device : public device_t,
- public device_image_interface,
- public device_slot_interface
+ public device_cartrom_image_interface,
+ public device_single_card_slot_interface<device_intv_cart_interface>
{
public:
// construction/destruction
@@ -111,27 +111,21 @@ 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 const software_list_loader &get_software_list_loader() const override { return rom_software_list_loader::instance(); }
- int get_type() { return m_type; }
- image_init_result load_fullpath();
+ 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"; }
- void save_ram() { if (m_cart && m_cart->get_ram_size()) m_cart->save_ram(); }
+ // device_slot_interface implementation
+ virtual std::string get_default_card_software(get_default_card_software_hook &hook) const override;
- virtual iodevice_t image_type() const override { return IO_CARTSLOT; }
- virtual bool is_readable() const override { return 1; }
- virtual bool is_writeable() const override { return 0; }
- virtual bool is_creatable() const override { return 0; }
- virtual bool must_be_loaded() const override { return 0; }
- virtual bool is_reset_on_load() const override { return 1; }
- virtual const char *image_interface() const override { return "intv_cart"; }
- virtual const char *file_extensions() const override { return "bin,int,rom,itv"; }
+ int get_type() { return m_type; }
+ std::error_condition load_fullpath();
- // slot interface overrides
- virtual std::string get_default_card_software(get_default_card_software_hook &hook) const override;
+ void save_ram() { if (m_cart && m_cart->get_ram_size()) m_cart->save_ram(); }
// reading and writing
uint16_t read_rom04(offs_t offset) { if (m_cart) return m_cart->read_rom04(offset); else return 0xffff; }
@@ -171,7 +165,7 @@ public:
protected:
// device-level overrides
- virtual void device_start() override;
+ virtual void device_start() override ATTR_COLD;
int m_type;
device_intv_cart_interface* m_cart;
@@ -187,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/intv/voice.cpp b/src/devices/bus/intv/voice.cpp
index b8b07d84d34..8f5e542b0e2 100644
--- a/src/devices/bus/intv/voice.cpp
+++ b/src/devices/bus/intv/voice.cpp
@@ -98,7 +98,7 @@ const tiny_rom_entry *intv_voice_device::device_rom_region() const
uint16_t intv_voice_device::read_speech(offs_t offset)
{
- return 0xff00 | m_speech->spb640_r(offset);
+ return m_speech->spb640_r(offset);
}
/*-------------------------------------------------
@@ -107,7 +107,7 @@ uint16_t intv_voice_device::read_speech(offs_t offset)
void intv_voice_device::write_speech(offs_t offset, uint16_t data)
{
- m_speech->spb640_w(offset, data & 0x00ff);
+ m_speech->spb640_w(offset, data);
}
diff --git a/src/devices/bus/intv/voice.h b/src/devices/bus/intv/voice.h
index 7369058c435..937c28f0a89 100644
--- a/src/devices/bus/intv/voice.h
+++ b/src/devices/bus/intv/voice.h
@@ -1,10 +1,13 @@
// license:BSD-3-Clause
// copyright-holders:Fabio Priuli
-#ifndef __INTV_VOICE_H
-#define __INTV_VOICE_H
+#ifndef MAME_BUS_INTV_VOICE_H
+#define MAME_BUS_INTV_VOICE_H
+
+#pragma once
-#include "slot.h"
#include "rom.h"
+#include "slot.h"
+
#include "sound/sp0256.h"
@@ -48,9 +51,9 @@ public:
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;
+ virtual void device_start() override ATTR_COLD;
+ virtual void device_add_mconfig(machine_config &config) override ATTR_COLD;
+ virtual const tiny_rom_entry *device_rom_region() const override ATTR_COLD;
private:
required_device<sp0256_device> m_speech;
@@ -62,4 +65,4 @@ private:
// device type definition
DECLARE_DEVICE_TYPE(INTV_ROM_VOICE, intv_voice_device)
-#endif // MAME_BUS_INTV_SLOT_H
+#endif // MAME_BUS_INTV_VOICE_H
diff --git a/src/devices/bus/intv_ctrl/ctrl.cpp b/src/devices/bus/intv_ctrl/ctrl.cpp
index 122c98cf2ed..287789296a9 100644
--- a/src/devices/bus/intv_ctrl/ctrl.cpp
+++ b/src/devices/bus/intv_ctrl/ctrl.cpp
@@ -27,8 +27,8 @@ DEFINE_DEVICE_TYPE(INTV_CONTROL_PORT, intv_control_port_device, "intv_control_po
// device_intv_control_port_interface - constructor
//-------------------------------------------------
-device_intv_control_port_interface::device_intv_control_port_interface(const machine_config &mconfig, device_t &device)
- : device_slot_card_interface(mconfig,device)
+device_intv_control_port_interface::device_intv_control_port_interface(const machine_config &mconfig, device_t &device) :
+ device_interface(device, "intvctrl")
{
m_port = dynamic_cast<intv_control_port_device *>(device.owner());
}
@@ -53,7 +53,7 @@ device_intv_control_port_interface::~device_intv_control_port_interface()
intv_control_port_device::intv_control_port_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) :
device_t(mconfig, INTV_CONTROL_PORT, tag, owner, clock),
- device_slot_interface(mconfig, *this),
+ device_single_card_slot_interface<device_intv_control_port_interface>(mconfig, *this),
m_device(nullptr)
{
}
@@ -74,16 +74,7 @@ intv_control_port_device::~intv_control_port_device()
void intv_control_port_device::device_start()
{
- m_device = dynamic_cast<device_intv_control_port_interface *>(get_card_device());
-}
-
-
-uint8_t intv_control_port_device::read_ctrl()
-{
- uint8_t data = 0;
- if (m_device)
- data |= m_device->read_ctrl();
- return data;
+ m_device = get_card_device();
}
diff --git a/src/devices/bus/intv_ctrl/ctrl.h b/src/devices/bus/intv_ctrl/ctrl.h
index 1cf3968f933..71106e7d9f5 100644
--- a/src/devices/bus/intv_ctrl/ctrl.h
+++ b/src/devices/bus/intv_ctrl/ctrl.h
@@ -20,13 +20,13 @@ class intv_control_port_device;
// ======================> device_intv_control_port_interface
-class device_intv_control_port_interface : public device_slot_card_interface
+class device_intv_control_port_interface : public device_interface
{
public:
// construction/destruction
virtual ~device_intv_control_port_interface();
- virtual uint8_t read_ctrl() { return 0; };
+ virtual uint8_t read_ctrl() { return 0; }
protected:
device_intv_control_port_interface(const machine_config &mconfig, device_t &device);
@@ -36,8 +36,7 @@ protected:
// ======================> intv_control_port_device
-class intv_control_port_device : public device_t,
- public device_slot_interface
+class intv_control_port_device : public device_t, public device_single_card_slot_interface<device_intv_control_port_interface>
{
public:
// construction/destruction
@@ -54,12 +53,11 @@ public:
intv_control_port_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock = 0);
virtual ~intv_control_port_device();
- DECLARE_READ8_MEMBER( ctrl_r ) { return read_ctrl(); }
- uint8_t read_ctrl();
+ uint8_t ctrl_r() { return m_device ? m_device->read_ctrl() : 0; }
protected:
// device-level overrides
- virtual void device_start() override;
+ virtual void device_start() override ATTR_COLD;
device_intv_control_port_interface *m_device;
};
diff --git a/src/devices/bus/intv_ctrl/ecs_ctrl.cpp b/src/devices/bus/intv_ctrl/ecs_ctrl.cpp
index 3f6afda5f4b..ef873489015 100644
--- a/src/devices/bus/intv_ctrl/ecs_ctrl.cpp
+++ b/src/devices/bus/intv_ctrl/ecs_ctrl.cpp
@@ -41,8 +41,8 @@ DEFINE_DEVICE_TYPE(INTVECS_CONTROL_PORT, intvecs_control_port_device, "intvecs_c
// device_intvecs_control_port_interface - constructor
//-------------------------------------------------
-device_intvecs_control_port_interface::device_intvecs_control_port_interface(const machine_config &mconfig, device_t &device)
- : device_slot_card_interface(mconfig,device)
+device_intvecs_control_port_interface::device_intvecs_control_port_interface(const machine_config &mconfig, device_t &device) :
+ device_interface(device, "intvecsctrl")
{
m_port = dynamic_cast<intvecs_control_port_device *>(device.owner());
}
@@ -67,7 +67,8 @@ device_intvecs_control_port_interface::~device_intvecs_control_port_interface()
intvecs_control_port_device::intvecs_control_port_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) :
device_t(mconfig, INTVECS_CONTROL_PORT, tag, owner, clock),
- device_slot_interface(mconfig, *this), m_device(nullptr)
+ device_single_card_slot_interface<device_intvecs_control_port_interface>(mconfig, *this),
+ m_device(nullptr)
{
}
@@ -87,30 +88,7 @@ intvecs_control_port_device::~intvecs_control_port_device()
void intvecs_control_port_device::device_start()
{
- m_device = dynamic_cast<device_intvecs_control_port_interface *>(get_card_device());
-}
-
-
-uint8_t intvecs_control_port_device::read_portA()
-{
- uint8_t data = 0;
- if (m_device)
- data |= m_device->read_portA();
- return data;
-}
-
-uint8_t intvecs_control_port_device::read_portB()
-{
- uint8_t data = 0;
- if (m_device)
- data |= m_device->read_portB();
- return data;
-}
-
-void intvecs_control_port_device::write_portA(uint8_t data)
-{
- if (m_device)
- m_device->write_portA(data);
+ m_device = get_card_device();
}
@@ -170,12 +148,12 @@ void intvecs_ctrls_device::device_reset()
uint8_t intvecs_ctrls_device::read_portA()
{
- return m_hand1->read_ctrl();
+ return m_hand1->ctrl_r();
}
uint8_t intvecs_ctrls_device::read_portB()
{
- return m_hand2->read_ctrl();
+ return m_hand2->ctrl_r();
}
//-------------------------------------------------
diff --git a/src/devices/bus/intv_ctrl/ecs_ctrl.h b/src/devices/bus/intv_ctrl/ecs_ctrl.h
index 8a723c64949..427fe328067 100644
--- a/src/devices/bus/intv_ctrl/ecs_ctrl.h
+++ b/src/devices/bus/intv_ctrl/ecs_ctrl.h
@@ -23,7 +23,7 @@ class intvecs_control_port_device;
// ======================> device_intvecs_control_port_interface
-class device_intvecs_control_port_interface : public device_slot_card_interface
+class device_intvecs_control_port_interface : public device_interface
{
public:
// construction/destruction
@@ -41,8 +41,7 @@ protected:
// ======================> intvecs_control_port_device
-class intvecs_control_port_device : public device_t,
- public device_slot_interface
+class intvecs_control_port_device : public device_t, public device_single_card_slot_interface<device_intvecs_control_port_interface>
{
public:
// construction/destruction
@@ -59,16 +58,13 @@ public:
intvecs_control_port_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock = 0);
virtual ~intvecs_control_port_device();
- DECLARE_READ8_MEMBER( portA_r ) { return read_portA(); }
- DECLARE_READ8_MEMBER( portB_r ) { return read_portB(); }
- DECLARE_WRITE8_MEMBER( portA_w ) { return write_portA(data); }
+ uint8_t porta_r() { return m_device ? m_device->read_portA() : 0; }
+ uint8_t portb_r() { return m_device ? m_device->read_portB() : 0; }
+ void porta_w(uint8_t data) { if (m_device) m_device->write_portA(data); }
protected:
// device-level overrides
- virtual void device_start() override;
- uint8_t read_portA();
- uint8_t read_portB();
- void write_portA(uint8_t data);
+ virtual void device_start() override ATTR_COLD;
device_intvecs_control_port_interface *m_device;
};
@@ -96,11 +92,11 @@ public:
protected:
// device-level overrides
- virtual void device_start() override;
- virtual void device_reset() override;
+ virtual void device_start() override ATTR_COLD;
+ virtual void device_reset() override ATTR_COLD;
// optional information overrides
- virtual void device_add_mconfig(machine_config &config) override;
+ virtual void device_add_mconfig(machine_config &config) override ATTR_COLD;
virtual uint8_t read_portA() override;
virtual uint8_t read_portB() override;
@@ -120,12 +116,12 @@ public:
intvecs_keybd_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;
+ virtual ioport_constructor device_input_ports() const override ATTR_COLD;
protected:
// device-level overrides
- virtual void device_start() override;
- virtual void device_reset() override;
+ virtual void device_start() override ATTR_COLD;
+ virtual void device_reset() override ATTR_COLD;
virtual uint8_t read_portB() override;
virtual void write_portA(uint8_t data) override;
@@ -145,12 +141,12 @@ public:
intvecs_synth_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;
+ virtual ioport_constructor device_input_ports() const override ATTR_COLD;
protected:
// device-level overrides
- virtual void device_start() override;
- virtual void device_reset() override;
+ virtual void device_start() override ATTR_COLD;
+ virtual void device_reset() override ATTR_COLD;
virtual uint8_t read_portB() override;
virtual void write_portA(uint8_t data) override;
diff --git a/src/devices/bus/intv_ctrl/handctrl.h b/src/devices/bus/intv_ctrl/handctrl.h
index 4aa021c1ff8..6ce221e74ee 100644
--- a/src/devices/bus/intv_ctrl/handctrl.h
+++ b/src/devices/bus/intv_ctrl/handctrl.h
@@ -28,12 +28,12 @@ public:
intv_handctrl_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;
+ virtual ioport_constructor device_input_ports() const override ATTR_COLD;
protected:
// device-level overrides
- virtual void device_start() override;
- virtual void device_reset() override;
+ virtual void device_start() override ATTR_COLD;
+ virtual void device_reset() override ATTR_COLD;
// device_intv_control_port_interface overrides
virtual uint8_t read_ctrl() override;
diff --git a/src/devices/bus/iq151/disc2.cpp b/src/devices/bus/iq151/disc2.cpp
index 0fde6792d40..76dfcf2ce13 100644
--- a/src/devices/bus/iq151/disc2.cpp
+++ b/src/devices/bus/iq151/disc2.cpp
@@ -15,9 +15,11 @@
IMPLEMENTATION
***************************************************************************/
-FLOPPY_FORMATS_MEMBER( iq151_disc2_device::floppy_formats )
- FLOPPY_IQ151_FORMAT
-FLOPPY_FORMATS_END
+void iq151_disc2_device::floppy_formats(format_registration &fr)
+{
+ fr.add_fm_containers();
+ fr.add(FLOPPY_IQ151_FORMAT);
+}
static void iq151_disc2_floppies(device_slot_interface &device)
{
diff --git a/src/devices/bus/iq151/disc2.h b/src/devices/bus/iq151/disc2.h
index b0421418363..8c2e9fff210 100644
--- a/src/devices/bus/iq151/disc2.h
+++ b/src/devices/bus/iq151/disc2.h
@@ -25,12 +25,12 @@ public:
protected:
// device-level overrides
- virtual void device_start() override;
- virtual void device_reset() override;
+ virtual void device_start() override ATTR_COLD;
+ virtual void device_reset() override ATTR_COLD;
// optional information overrides
- virtual void device_add_mconfig(machine_config &config) override;
- virtual const tiny_rom_entry *device_rom_region() const override;
+ virtual void device_add_mconfig(machine_config &config) override ATTR_COLD;
+ virtual const tiny_rom_entry *device_rom_region() const override ATTR_COLD;
// iq151cart_interface overrides
virtual void read(offs_t offset, uint8_t &data) override;
@@ -38,7 +38,7 @@ protected:
virtual void io_write(offs_t offset, uint8_t data) override;
private:
- DECLARE_FLOPPY_FORMATS( floppy_formats );
+ static void floppy_formats(format_registration &fr);
required_device<upd765a_device> m_fdc;
uint8_t * m_rom;
diff --git a/src/devices/bus/iq151/grafik.cpp b/src/devices/bus/iq151/grafik.cpp
index ce107cf81da..497012cf2cd 100644
--- a/src/devices/bus/iq151/grafik.cpp
+++ b/src/devices/bus/iq151/grafik.cpp
@@ -78,7 +78,7 @@ void iq151_grafik_device::device_add_mconfig(machine_config &config)
// I8255 port a
//-------------------------------------------------
-WRITE8_MEMBER(iq151_grafik_device::x_write)
+void iq151_grafik_device::x_write(uint8_t data)
{
if (LOG) logerror("Grafik: set posx 0x%02x\n", data);
@@ -89,7 +89,7 @@ WRITE8_MEMBER(iq151_grafik_device::x_write)
// I8255 port b
//-------------------------------------------------
-WRITE8_MEMBER(iq151_grafik_device::y_write)
+void iq151_grafik_device::y_write(uint8_t data)
{
if (LOG) logerror("Grafik: set posy 0x%02x\n", data);
@@ -100,7 +100,7 @@ WRITE8_MEMBER(iq151_grafik_device::y_write)
// I8255 port c
//-------------------------------------------------
-WRITE8_MEMBER(iq151_grafik_device::control_w)
+void iq151_grafik_device::control_w(uint8_t data)
{
if (LOG) logerror("Grafik: control write 0x%02x\n", data);
@@ -178,7 +178,7 @@ void iq151_grafik_device::video_update(bitmap_ind16 &bitmap, const rectangle &cl
{
for (int ra = 0; ra < 8; ra++)
{
- bitmap.pix16(y, x*8 + ra) |= BIT(m_videoram[(32*8 -1 - y)*64 + x], ra);
+ bitmap.pix(y, x*8 + ra) |= BIT(m_videoram[(32*8 -1 - y)*64 + x], ra);
}
}
}
diff --git a/src/devices/bus/iq151/grafik.h b/src/devices/bus/iq151/grafik.h
index 6b1fe79bc8c..f774fe6580e 100644
--- a/src/devices/bus/iq151/grafik.h
+++ b/src/devices/bus/iq151/grafik.h
@@ -24,11 +24,11 @@ public:
protected:
// device-level overrides
- virtual void device_start() override;
- virtual void device_reset() override;
+ virtual void device_start() override ATTR_COLD;
+ virtual void device_reset() override ATTR_COLD;
// optional information overrides
- virtual void device_add_mconfig(machine_config &config) override;
+ virtual void device_add_mconfig(machine_config &config) override ATTR_COLD;
// iq151cart_interface overrides
virtual void io_read(offs_t offset, uint8_t &data) override;
@@ -37,9 +37,9 @@ protected:
private:
// ppi8255 callback
- DECLARE_WRITE8_MEMBER(x_write);
- DECLARE_WRITE8_MEMBER(y_write);
- DECLARE_WRITE8_MEMBER(control_w);
+ void x_write(uint8_t data);
+ void y_write(uint8_t data);
+ void control_w(uint8_t data);
required_device<i8255_device> m_ppi8255;
diff --git a/src/devices/bus/iq151/iq151.cpp b/src/devices/bus/iq151/iq151.cpp
index 58db5dde6ba..aa729cefce3 100644
--- a/src/devices/bus/iq151/iq151.cpp
+++ b/src/devices/bus/iq151/iq151.cpp
@@ -31,7 +31,7 @@ DEFINE_DEVICE_TYPE(IQ151CART_SLOT, iq151cart_slot_device, "iq151cart_slot", "IQ1
//-------------------------------------------------
device_iq151cart_interface::device_iq151cart_interface(const machine_config &mconfig, device_t &device)
- : device_slot_card_interface(mconfig, device)
+ : device_interface(device, "iq151cart")
, m_screen(nullptr)
{
}
@@ -55,8 +55,8 @@ device_iq151cart_interface::~device_iq151cart_interface()
//-------------------------------------------------
iq151cart_slot_device::iq151cart_slot_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
: device_t(mconfig, IQ151CART_SLOT, tag, owner, clock)
- , device_slot_interface(mconfig, *this)
- , device_image_interface(mconfig, *this)
+ , device_single_card_slot_interface<device_iq151cart_interface>(mconfig, *this)
+ , device_cartrom_image_interface(mconfig, *this)
, m_out_irq0_cb(*this)
, m_out_irq1_cb(*this)
, m_out_irq2_cb(*this)
@@ -83,18 +83,9 @@ iq151cart_slot_device::~iq151cart_slot_device()
void iq151cart_slot_device::device_start()
{
- m_cart = dynamic_cast<device_iq151cart_interface *>(get_card_device());
+ 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();
-
+ m_cart->set_screen_device(*m_screen);
}
@@ -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 306fef47ee6..452165761a1 100644
--- a/src/devices/bus/iq151/iq151.h
+++ b/src/devices/bus/iq151/iq151.h
@@ -47,7 +47,7 @@
#pragma once
-#include "softlist_dev.h"
+#include "imagedev/cartrom.h"
#include "screen.h"
/***************************************************************************
@@ -56,7 +56,7 @@
// ======================> device_iq151cart_interface
-class device_iq151cart_interface : public device_slot_card_interface
+class device_iq151cart_interface : public device_interface
{
public:
// construction/destruction
@@ -68,7 +68,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 void set_screen_device(screen_device *screen) { m_screen = screen; }
+ virtual void set_screen_device(screen_device &screen) { m_screen = &screen; }
// video update
virtual void video_update(bitmap_ind16 &bitmap, const rectangle &cliprect) { }
@@ -82,8 +82,8 @@ protected:
// ======================> iq151cart_slot_device
class iq151cart_slot_device : public device_t,
- public device_slot_interface,
- public device_image_interface
+ public device_single_card_slot_interface<device_iq151cart_interface>,
+ public device_cartrom_image_interface
{
public:
// construction/destruction
@@ -108,23 +108,14 @@ public:
auto out_irq4_callback() { return m_out_irq4_cb.bind(); }
auto out_drq_callback() { return m_out_drq_cb.bind(); }
- // device-level overrides
- virtual void device_start() override;
+ // device_image_interface implementation
+ virtual std::pair<std::error_condition, std::string> call_load() override;
- // image-level overrides
- virtual image_init_result call_load() override;
- virtual const software_list_loader &get_software_list_loader() const override { return rom_software_list_loader::instance(); }
+ 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"; }
- virtual iodevice_t image_type() const override { return IO_CARTSLOT; }
- virtual bool is_readable() const override { return true; }
- virtual bool is_writeable() const override { return false; }
- virtual bool is_creatable() const override { return false; }
- virtual bool must_be_loaded() const override { return false; }
- virtual bool is_reset_on_load() const override { return true; }
- virtual const char *image_interface() const override { return "iq151_cart"; }
- virtual const char *file_extensions() const 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
@@ -134,6 +125,10 @@ public:
virtual void io_write(offs_t offset, uint8_t data);
virtual void video_update(bitmap_ind16 &bitmap, const rectangle &cliprect);
+protected:
+ // device_t implementation
+ virtual void device_start() override ATTR_COLD;
+
devcb_write_line m_out_irq0_cb;
devcb_write_line m_out_irq1_cb;
devcb_write_line m_out_irq2_cb;
diff --git a/src/devices/bus/iq151/minigraf.cpp b/src/devices/bus/iq151/minigraf.cpp
index d5bf2da1f8b..b3d51bdf8d3 100644
--- a/src/devices/bus/iq151/minigraf.cpp
+++ b/src/devices/bus/iq151/minigraf.cpp
@@ -10,6 +10,7 @@
#include "minigraf.h"
#include "emuopts.h"
+#include "fileio.h"
#include "png.h"
// paper is A4 (297x210mm)
@@ -162,7 +163,7 @@ void iq151_minigraf_device::plotter_update(uint8_t control)
// if pen is down draws a point
if (m_pen)
- m_paper->pix16(((PAPER_HEIGHT-PAPER_MAX_Y)/2) + m_posy, ((PAPER_WIDTH-PAPER_MAX_X)/2) + m_posx) = 1;
+ m_paper->pix(((PAPER_HEIGHT-PAPER_MAX_Y)/2) + m_posy, ((PAPER_WIDTH-PAPER_MAX_X)/2) + m_posx) = 1;
m_control = control;
}
diff --git a/src/devices/bus/iq151/minigraf.h b/src/devices/bus/iq151/minigraf.h
index 16113288094..8a479593a2b 100644
--- a/src/devices/bus/iq151/minigraf.h
+++ b/src/devices/bus/iq151/minigraf.h
@@ -22,12 +22,12 @@ public:
iq151_minigraf_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 const tiny_rom_entry *device_rom_region() const override ATTR_COLD;
protected:
// device-level overrides
- virtual void device_start() override;
- virtual void device_stop() override;
+ virtual void device_start() override ATTR_COLD;
+ virtual void device_stop() override ATTR_COLD;
// iq151cart_interface overrides
virtual void read(offs_t offset, uint8_t &data) override;
diff --git a/src/devices/bus/iq151/ms151a.cpp b/src/devices/bus/iq151/ms151a.cpp
index 447c9f0d43a..6b4116f3d42 100644
--- a/src/devices/bus/iq151/ms151a.cpp
+++ b/src/devices/bus/iq151/ms151a.cpp
@@ -10,6 +10,7 @@
#include "ms151a.h"
#include "emuopts.h"
+#include "fileio.h"
#include "png.h"
// paper is A4 (210x297mm)
@@ -164,5 +165,5 @@ void iq151_ms151a_device::plotter_update(uint8_t offset, uint8_t data)
// if pen is down draws a point
if (m_pen)
- m_paper->pix16(((PAPER_HEIGHT-PAPER_MAX_Y)/2) + m_posy, ((PAPER_WIDTH-PAPER_MAX_X)/2) + m_posx) = 1;
+ m_paper->pix(((PAPER_HEIGHT-PAPER_MAX_Y)/2) + m_posy, ((PAPER_WIDTH-PAPER_MAX_X)/2) + m_posx) = 1;
}
diff --git a/src/devices/bus/iq151/ms151a.h b/src/devices/bus/iq151/ms151a.h
index 735729b15f1..1e710b615a1 100644
--- a/src/devices/bus/iq151/ms151a.h
+++ b/src/devices/bus/iq151/ms151a.h
@@ -22,12 +22,12 @@ public:
iq151_ms151a_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 const tiny_rom_entry *device_rom_region() const override ATTR_COLD;
protected:
// device-level overrides
- virtual void device_start() override;
- virtual void device_stop() override;
+ virtual void device_start() override ATTR_COLD;
+ virtual void device_stop() override ATTR_COLD;
// iq151cart_interface overrides
virtual void read(offs_t offset, uint8_t &data) override;
diff --git a/src/devices/bus/iq151/rom.h b/src/devices/bus/iq151/rom.h
index 56544a24d9f..866032097a9 100644
--- a/src/devices/bus/iq151/rom.h
+++ b/src/devices/bus/iq151/rom.h
@@ -20,14 +20,14 @@ class iq151_rom_device :
{
public:
// optional information overrides
- virtual const tiny_rom_entry *device_rom_region() const override;
+ virtual const tiny_rom_entry *device_rom_region() const override ATTR_COLD;
protected:
// construction/destruction
iq151_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_start() override ATTR_COLD;
// iq151cart_interface overrides
virtual uint8_t* get_cart_base() override;
diff --git a/src/devices/bus/iq151/staper.cpp b/src/devices/bus/iq151/staper.cpp
index 37379f590f8..63a365282d0 100644
--- a/src/devices/bus/iq151/staper.cpp
+++ b/src/devices/bus/iq151/staper.cpp
@@ -52,8 +52,15 @@ iq151_staper_device::iq151_staper_device(const machine_config &mconfig, const ch
void iq151_staper_device::device_start()
{
- m_printer_timer = timer_alloc(TIMER_PRINTER);
- m_printer_timer->reset();
+ m_printer_timer = timer_alloc(FUNC(iq151_staper_device::pc2_low_tick), this);
+}
+
+//-------------------------------------------------
+// device_reset - device-specific reset
+//-------------------------------------------------
+
+void iq151_staper_device::device_reset()
+{
}
//-------------------------------------------------
@@ -71,13 +78,12 @@ void iq151_staper_device::device_add_mconfig(machine_config &config)
}
//-------------------------------------------------
-// device_timer - handler timer events
+// pc2_low_tick - lower PPI Port C bit 2
//-------------------------------------------------
-void iq151_staper_device::device_timer(emu_timer &timer, device_timer_id id, int param, void *ptr)
+TIMER_CALLBACK_MEMBER(iq151_staper_device::pc2_low_tick)
{
- if (id == TIMER_PRINTER)
- m_ppi->pc2_w(0);
+ m_ppi->pc2_w(0);
}
@@ -106,13 +112,13 @@ void iq151_staper_device::io_write(offs_t offset, uint8_t data)
// I8255 interface
//**************************************************************************
-READ8_MEMBER( iq151_staper_device::ppi_porta_r )
+uint8_t iq151_staper_device::ppi_porta_r()
{
// TODO: paper tape reader input
return 0;
}
-WRITE8_MEMBER( iq151_staper_device::ppi_portb_w )
+void iq151_staper_device::ppi_portb_w(uint8_t data)
{
if (m_ppi_portc & 0x80)
{
@@ -128,7 +134,7 @@ WRITE8_MEMBER( iq151_staper_device::ppi_portb_w )
}
}
-WRITE8_MEMBER( iq151_staper_device::ppi_portc_w )
+void iq151_staper_device::ppi_portc_w(uint8_t data)
{
/*
x--- ---- printer select
diff --git a/src/devices/bus/iq151/staper.h b/src/devices/bus/iq151/staper.h
index 8e0c5e2b094..b9fb63be4b9 100644
--- a/src/devices/bus/iq151/staper.h
+++ b/src/devices/bus/iq151/staper.h
@@ -25,11 +25,11 @@ public:
protected:
// device-level overrides
- virtual void device_start() override;
- virtual void device_timer(emu_timer &timer, device_timer_id id, int param, void *ptr) override;
+ virtual void device_start() override ATTR_COLD;
+ virtual void device_reset() override ATTR_COLD;
// optional information overrides
- virtual void device_add_mconfig(machine_config &config) override;
+ virtual void device_add_mconfig(machine_config &config) override ATTR_COLD;
// iq151cart_interface overrides
virtual void io_read(offs_t offset, uint8_t &data) override;
@@ -37,11 +37,11 @@ protected:
private:
// i8255 callbacks
- DECLARE_READ8_MEMBER( ppi_porta_r );
- DECLARE_WRITE8_MEMBER( ppi_portb_w );
- DECLARE_WRITE8_MEMBER( ppi_portc_w );
+ uint8_t ppi_porta_r();
+ void ppi_portb_w(uint8_t data);
+ void ppi_portc_w(uint8_t data);
- static const device_timer_id TIMER_PRINTER = 0;
+ TIMER_CALLBACK_MEMBER(pc2_low_tick);
required_device<i8255_device> m_ppi;
required_device<printer_image_device> m_printer;
diff --git a/src/devices/bus/iq151/video32.cpp b/src/devices/bus/iq151/video32.cpp
index fce21b963e9..2d3f75b66ed 100644
--- a/src/devices/bus/iq151/video32.cpp
+++ b/src/devices/bus/iq151/video32.cpp
@@ -126,7 +126,7 @@ void iq151_video32_device::video_update(bitmap_ind16 &bitmap, const rectangle &c
{
for (int ra = 0; ra < 8; ra++)
{
- uint16_t *p = &bitmap.pix16(sy++);
+ uint16_t *p = &bitmap.pix(sy++);
for (int x = ma; x < ma + 32; x++)
{
diff --git a/src/devices/bus/iq151/video32.h b/src/devices/bus/iq151/video32.h
index 9dc32765f6b..5997b4015e4 100644
--- a/src/devices/bus/iq151/video32.h
+++ b/src/devices/bus/iq151/video32.h
@@ -23,12 +23,12 @@ public:
iq151_video32_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 const tiny_rom_entry *device_rom_region() const override ATTR_COLD;
protected:
// device-level overrides
- virtual void device_start() override;
- virtual void device_reset() override;
+ virtual void device_start() override ATTR_COLD;
+ virtual void device_reset() override ATTR_COLD;
// iq151cart_interface overrides
virtual void read(offs_t offset, uint8_t &data) override;
diff --git a/src/devices/bus/iq151/video64.cpp b/src/devices/bus/iq151/video64.cpp
index a965abbd19e..487bf63ca33 100644
--- a/src/devices/bus/iq151/video64.cpp
+++ b/src/devices/bus/iq151/video64.cpp
@@ -140,7 +140,7 @@ void iq151_video64_device::video_update(bitmap_ind16 &bitmap, const rectangle &c
{
for (int ra = 0; ra < 8; ra++)
{
- uint16_t *p = &bitmap.pix16(sy++);
+ uint16_t *p = &bitmap.pix(sy++);
for (int x = ma; x < ma + 64; x++)
{
diff --git a/src/devices/bus/iq151/video64.h b/src/devices/bus/iq151/video64.h
index 7b152fc8fd6..61d3c55d895 100644
--- a/src/devices/bus/iq151/video64.h
+++ b/src/devices/bus/iq151/video64.h
@@ -23,12 +23,12 @@ public:
iq151_video64_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 const tiny_rom_entry *device_rom_region() const override ATTR_COLD;
protected:
// device-level overrides
- virtual void device_start() override;
- virtual void device_reset() override;
+ virtual void device_start() override ATTR_COLD;
+ virtual void device_reset() override ATTR_COLD;
// iq151cart_interface overrides
virtual void read(offs_t offset, uint8_t &data) override;
diff --git a/src/devices/bus/isa/3c503.cpp b/src/devices/bus/isa/3c503.cpp
index 34202e2246d..34a9f970740 100644
--- a/src/devices/bus/isa/3c503.cpp
+++ b/src/devices/bus/isa/3c503.cpp
@@ -3,14 +3,16 @@
#include "emu.h"
#include "3c503.h"
+#include "multibyte.h"
+
#define SADDR 0xcc000
void el2_3c503_device::device_add_mconfig(machine_config &config)
{
DP8390D(config, m_dp8390, 0);
m_dp8390->irq_callback().set(FUNC(el2_3c503_device::el2_3c503_irq_w));
- m_dp8390->mem_read_callback().set(FUNC(el2_3c503_device::el2_3c503_mem_r));
- m_dp8390->mem_write_callback().set(FUNC(el2_3c503_device::el2_3c503_mem_w));
+ m_dp8390->mem_read_callback().set(FUNC(el2_3c503_device::el2_3c503_mem_read));
+ m_dp8390->mem_write_callback().set(FUNC(el2_3c503_device::el2_3c503_mem_write));
}
DEFINE_DEVICE_TYPE(EL2_3C503, el2_3c503_device, "el2_3c503", "3C503 Network Adapter")
@@ -24,16 +26,19 @@ 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);
set_isa_device();
- m_isa->install_device(0x0300, 0x030f, read8_delegate(FUNC(el2_3c503_device::el2_3c503_loport_r), this), write8_delegate(FUNC(el2_3c503_device::el2_3c503_loport_w), this));
- m_isa->install_device(0x0700, 0x070f, read8_delegate(FUNC(el2_3c503_device::el2_3c503_hiport_r), this), write8_delegate(FUNC(el2_3c503_device::el2_3c503_hiport_w), this));
+ m_isa->install_device(0x0300, 0x030f, read8sm_delegate(*this, FUNC(el2_3c503_device::el2_3c503_loport_r)), write8sm_delegate(*this, FUNC(el2_3c503_device::el2_3c503_loport_w)));
+ m_isa->install_device(0x0700, 0x070f, read8sm_delegate(*this, FUNC(el2_3c503_device::el2_3c503_hiport_r)), write8sm_delegate(*this, FUNC(el2_3c503_device::el2_3c503_hiport_w)));
// TODO: This is wrong, fix if anything actually uses it
// DMA can change in runtime
@@ -48,14 +53,14 @@ 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
m_regs.ctrl = 0x0a;
m_irq_state = CLEAR_LINE;
m_isa->unmap_bank(SADDR, SADDR + 0x1fff);
- m_isa->install_bank(SADDR, SADDR + 0x1fff, "3c503 rom", m_rom);
+ m_isa->install_bank(SADDR, SADDR + 0x1fff, m_rom);
}
void el2_3c503_device::set_irq(int state) {
@@ -107,11 +112,10 @@ void el2_3c503_device::dack_w(int line, uint8_t data) {
el2_3c503_mem_write(m_regs.da++, data);
}
-READ8_MEMBER(el2_3c503_device::el2_3c503_loport_r) {
+uint8_t el2_3c503_device::el2_3c503_loport_r(offs_t offset) {
switch((m_regs.ctrl >> 2) & 3) {
case 0:
- m_dp8390->dp8390_cs(CLEAR_LINE);
- return m_dp8390->dp8390_r(space, offset, mem_mask);
+ return m_dp8390->cs_read(offset);
case 1:
return m_prom[offset];
case 2:
@@ -122,11 +126,10 @@ READ8_MEMBER(el2_3c503_device::el2_3c503_loport_r) {
return 0;
}
-WRITE8_MEMBER(el2_3c503_device::el2_3c503_loport_w) {
+void el2_3c503_device::el2_3c503_loport_w(offs_t offset, uint8_t data) {
switch((m_regs.ctrl >> 2) & 3) {
case 0:
- m_dp8390->dp8390_cs(CLEAR_LINE);
- return m_dp8390->dp8390_w(space, offset, data, mem_mask);
+ return m_dp8390->cs_write(offset, data);
case 1:
case 2:
logerror("3c503: invalid attempt to write to prom\n");
@@ -137,7 +140,7 @@ WRITE8_MEMBER(el2_3c503_device::el2_3c503_loport_w) {
}
}
-READ8_MEMBER(el2_3c503_device::el2_3c503_hiport_r) {
+uint8_t el2_3c503_device::el2_3c503_hiport_r(offs_t offset) {
switch(offset) {
case 0:
return m_regs.pstr;
@@ -169,15 +172,15 @@ READ8_MEMBER(el2_3c503_device::el2_3c503_hiport_r) {
return (m_regs.vptr & 0x0f) << 4;
case 14:
if(!(m_regs.ctrl & 0x80)) return 0xff;
- return el2_3c503_mem_r(space, machine().side_effects_disabled() ? m_regs.da : m_regs.da++, mem_mask);
+ return el2_3c503_mem_read(machine().side_effects_disabled() ? m_regs.da : m_regs.da++);
case 15:
if(!(m_regs.ctrl & 0x80)) return 0xff;
- return el2_3c503_mem_r(space, machine().side_effects_disabled() ? m_regs.da : m_regs.da++, mem_mask);
+ return el2_3c503_mem_read(machine().side_effects_disabled() ? m_regs.da : m_regs.da++);
}
return 0;
}
-WRITE8_MEMBER(el2_3c503_device::el2_3c503_hiport_w) {
+void el2_3c503_device::el2_3c503_hiport_w(offs_t offset, uint8_t data) {
switch(offset) {
case 0:
m_regs.pstr = data; // pstr and pspr are supposed to be set same as 8390 pstart and pstop
@@ -193,13 +196,13 @@ WRITE8_MEMBER(el2_3c503_device::el2_3c503_hiport_w) {
m_isa->unmap_bank(SADDR, SADDR + 0x1fff);
switch(data & 0xf) {
case 0:
- m_isa->install_bank(SADDR, SADDR + 0x1fff, "3c503 rom", m_rom);
+ m_isa->install_bank(SADDR, SADDR + 0x1fff, m_rom);
break;
case 9:
- m_isa->install_bank(SADDR, SADDR + 0x1fff, "3c503 ram", m_board_ram);
+ m_isa->install_bank(SADDR, SADDR + 0x1fff, m_board_ram);
break;
default:
- m_isa->install_bank(SADDR, SADDR + 0x1fff, "3c503 no map", m_rom);
+ m_isa->install_bank(SADDR, SADDR + 0x1fff, m_rom);
break;
}
}
@@ -247,6 +250,7 @@ WRITE8_MEMBER(el2_3c503_device::el2_3c503_hiport_w) {
default:
logerror("3c503: trying to set multiple drqs %X\n", data);
}
+ break;
case 9:
if(m_regs.ctrl & 0x80) logerror("3c503: changing dma address during dma is undefined\n");
m_regs.da = (data << 8) | (m_regs.da & 0xff);
@@ -268,18 +272,18 @@ WRITE8_MEMBER(el2_3c503_device::el2_3c503_hiport_w) {
return;
case 14:
if(!(m_regs.ctrl & 0x80)) return;
- el2_3c503_mem_w(space, m_regs.da++, data, mem_mask);
+ el2_3c503_mem_write(m_regs.da++, data);
return;
case 15:
if(!(m_regs.ctrl & 0x80)) return;
- el2_3c503_mem_w(space, m_regs.da++, data, mem_mask);
+ el2_3c503_mem_write(m_regs.da++, data);
return;
default:
logerror("3c503: invalid high register write %02x\n", offset);
}
}
-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/3c503.h b/src/devices/bus/isa/3c503.h
index d987dc79cb2..9d51b658d6c 100644
--- a/src/devices/bus/isa/3c503.h
+++ b/src/devices/bus/isa/3c503.h
@@ -15,23 +15,21 @@ class el2_3c503_device : public device_t, public device_isa8_card_interface
public:
el2_3c503_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
- DECLARE_READ8_MEMBER(el2_3c503_loport_r);
- DECLARE_WRITE8_MEMBER(el2_3c503_loport_w);
- DECLARE_READ8_MEMBER(el2_3c503_hiport_r);
- DECLARE_WRITE8_MEMBER(el2_3c503_hiport_w);
+ uint8_t el2_3c503_loport_r(offs_t offset);
+ void el2_3c503_loport_w(offs_t offset, uint8_t data);
+ uint8_t el2_3c503_hiport_r(offs_t offset);
+ void el2_3c503_hiport_w(offs_t offset, uint8_t data);
void eop_w(int state) override;
uint8_t dack_r(int line) override;
void dack_w(int line, uint8_t data) override;
protected:
- virtual void device_start() override;
- virtual void device_reset() override;
- virtual void device_add_mconfig(machine_config &config) override;
+ 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;
private:
void el2_3c503_irq_w(int state);
- DECLARE_READ8_MEMBER(el2_3c503_mem_r) { return el2_3c503_mem_read(offset); }
- DECLARE_WRITE8_MEMBER(el2_3c503_mem_w) { el2_3c503_mem_write(offset, data); }
required_device<dp8390d_device> m_dp8390;
uint8_t m_board_ram[8*1024];
diff --git a/src/devices/bus/isa/3c505.cpp b/src/devices/bus/isa/3c505.cpp
index 6dd695165c2..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)
@@ -280,7 +279,7 @@ void isa16_3c505_device::device_reset()
offs_t const rom_base = (m_romopts->read() & 0xfe) << 12;
if (m_isa->is_option_rom_space_available(rom_base, 0x2000))
- m_isa->install_rom(this, rom_base, rom_base | 0x01fff, "host", "host");
+ m_isa->install_rom(this, rom_base, rom_base | 0x01fff, "host");
}
m_isa->set_dma_channel(m_isa_drq, this, true);
@@ -318,6 +317,9 @@ void isa16_3c505_device::map_main(address_map &map)
// i82586 upper 4 address lines are ignored
map.global_mask(0x0fffff);
+ // suppress logging when sizing RAM
+ map(0x00000, 0x7ffff).noprw();
+
map(0xfc000, 0xfffff).rom().region("system", 0);
}
@@ -327,19 +329,19 @@ void isa16_3c505_device::map_io(address_map &map)
* A read or write to I/O location 00H will cause an active transition on
* the CA input.
*/
- map(0x0000, 0x0000).lrw8("ca",
- [this]()
- {
- m_net->ca(1);
- m_net->ca(0);
-
- return 0;
- },
- [this](u8 data)
- {
- m_net->ca(1);
- m_net->ca(0);
- });
+ map(0x0000, 0x0000).lrw8(
+ NAME([this]()
+ {
+ m_net->ca(1);
+ m_net->ca(0);
+
+ return 0;
+ }),
+ NAME([this](u8 data)
+ {
+ m_net->ca(1);
+ m_net->ca(0);
+ }));
/*
* A read or write to I/O location 80H will produce a CAS before RAS cycle
@@ -397,12 +399,13 @@ void isa16_3c505_device::acr_w(u8 data)
m_hsr = (m_hsr & ~HSR_ASF) | (data & ACR_ASF);
if ((data ^ m_acr) & ACR_LED1)
- m_led[0] = !!(data & ACR_LED1);
+ m_led[0] = bool(data & ACR_LED1);
if ((data ^ m_acr) & ACR_LED2)
- m_led[1] = !!(data & 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)
{
@@ -487,6 +490,26 @@ void isa16_3c505_device::hcr_w(u8 data)
{
LOGMASKED(LOG_REG, "hcr_w 0x%02x (%s)\n", data, machine().describe_context());
+ // attention condition
+ if (!(m_hcr & HCR_ATTN) && (data & HCR_ATTN))
+ {
+ if (!(data & HCR_FLSH))
+ {
+ LOGMASKED(LOG_REG, "soft reset\n");
+
+ // soft reset
+ m_cpu->set_input_line(INPUT_LINE_NMI, 1);
+ m_cpu->set_input_line(INPUT_LINE_NMI, 0);
+ }
+ else
+ {
+ LOGMASKED(LOG_REG, "hard reset\n");
+
+ // hard reset
+ reset();
+ }
+ }
+
// update host status flags
if ((data ^ m_hcr) & HCR_HSF)
m_asr = (m_asr & ~ASR_HSF) | (data & HCR_HSF);
@@ -530,26 +553,6 @@ void isa16_3c505_device::hcr_w(u8 data)
update_rdy(m_acr, data);
}
- // attention condition
- if (!(m_hcr & HCR_ATTN) && (data & HCR_ATTN))
- {
- if (!(data & HCR_FLSH))
- {
- LOGMASKED(LOG_REG, "soft reset\n");
-
- // soft reset
- m_cpu->set_input_line(INPUT_LINE_NMI, 1);
- m_cpu->set_input_line(INPUT_LINE_NMI, 0);
- }
- else
- {
- LOGMASKED(LOG_REG, "hard reset\n");
-
- // hard reset
- reset();
- }
- }
-
m_hcr = data;
}
@@ -635,7 +638,7 @@ void isa16_3c505_device::update_rdy(u8 const acr, u8 const hcr)
m_hsr &= ~HSR_HRDY;
}
- update_cpu_drq(!!(m_asr & ASR_ARDY));
+ update_cpu_drq(bool(m_asr & ASR_ARDY));
update_isa_drq((m_hsr & HSR_HRDY) && (hcr & HCR_DMAE));
}
diff --git a/src/devices/bus/isa/3c505.h b/src/devices/bus/isa/3c505.h
index 115c0c9978e..7323318dbbd 100644
--- a/src/devices/bus/isa/3c505.h
+++ b/src/devices/bus/isa/3c505.h
@@ -21,15 +21,15 @@ public:
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;
+ virtual const tiny_rom_entry *device_rom_region() const override ATTR_COLD;
+ virtual void device_add_mconfig(machine_config &config) override ATTR_COLD;
+ virtual ioport_constructor device_input_ports() const override ATTR_COLD;
+ virtual void device_start() override ATTR_COLD;
+ virtual void device_reset() override ATTR_COLD;
- void map_main(address_map &map);
- void map_io(address_map &map);
- void map_isa(address_map &map);
+ void map_main(address_map &map) ATTR_COLD;
+ void map_io(address_map &map) ATTR_COLD;
+ void map_isa(address_map &map) ATTR_COLD;
enum acr_mask : u8
{
@@ -90,8 +90,8 @@ protected:
// adapter register helpers
u8 acmd_r();
- u8 acr_r() { return m_acr; };
- u8 asr_r() { return m_asr; };
+ u8 acr_r() { return m_acr; }
+ u8 asr_r() { return m_asr; }
u16 adata_r();
void acmd_w(u8 data);
void acr_w(u8 data);
diff --git a/src/devices/bus/isa/3xtwin.cpp b/src/devices/bus/isa/3xtwin.cpp
new file mode 100644
index 00000000000..b30c83ab1ce
--- /dev/null
+++ b/src/devices/bus/isa/3xtwin.cpp
@@ -0,0 +1,95 @@
+// license:BSD-3-Clause
+// copyright-holders:AJR
+/***************************************************************************
+
+ Emerald Technology Inc. 3XTwin IBM 5251/11 twinax emulation board
+
+ This smallish card is rather tightly packed with DIP ICs (mostly simple
+ LSTTL and a few line drivers/receivers) to the point where their
+ location numbers are difficult to read. There is no host BIOS, and the
+ 65C02's "TWINMON" firmware does very little, clearly relying on
+ external software.
+
+ Communication between the host system and local CPU seems to take place
+ via shared access to a KM62256LP-10 SRAM.
+
+***************************************************************************/
+
+#include "emu.h"
+#include "3xtwin.h"
+
+#include "cpu/m6502/r65c02.h"
+#include "machine/com52c50.h"
+
+
+// device type definition
+DEFINE_DEVICE_TYPE(ISA8_3XTWIN, isa8_3xtwin_device, "3xtwin", "Emerald Technology 3XTwin Twinax Emulation Card")
+
+isa8_3xtwin_device::isa8_3xtwin_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock)
+ : device_t(mconfig, ISA8_3XTWIN, tag, owner, clock)
+ , device_isa8_card_interface(mconfig, *this)
+{
+}
+
+void isa8_3xtwin_device::device_start()
+{
+}
+
+void isa8_3xtwin_device::mpu_map(address_map &map)
+{
+ map(0x0000, 0x1fff).ram();
+ map(0x2000, 0x2007).m("tic", FUNC(com52c50_device::map));
+ map(0x4000, 0xbfff).ram();
+ map(0xe000, 0xffff).rom().region("firmware", 0);
+}
+
+
+static INPUT_PORTS_START(3xtwin)
+ PORT_START("IOBASE")
+ PORT_DIPNAME(0x1f, 0x19, "Base I/O Address") PORT_DIPLOCATION("S1:5,4,3,2,1")
+ PORT_DIPSETTING(0x10, "200")
+ PORT_DIPSETTING(0x11, "220")
+ PORT_DIPSETTING(0x12, "240")
+ PORT_DIPSETTING(0x13, "260")
+ PORT_DIPSETTING(0x14, "280")
+ PORT_DIPSETTING(0x15, "2A0")
+ PORT_DIPSETTING(0x16, "2C0")
+ PORT_DIPSETTING(0x17, "2E0")
+ PORT_DIPSETTING(0x18, "300")
+ PORT_DIPSETTING(0x19, "320")
+ PORT_DIPSETTING(0x1a, "340")
+ PORT_DIPSETTING(0x1b, "360")
+ PORT_DIPSETTING(0x1c, "380")
+ PORT_DIPSETTING(0x1d, "3A0")
+ PORT_DIPSETTING(0x1e, "3C0")
+ PORT_DIPSETTING(0x1f, "3E0")
+
+ // TODO: IRQ jumpers
+INPUT_PORTS_END
+
+ioport_constructor isa8_3xtwin_device::device_input_ports() const
+{
+ return INPUT_PORTS_NAME(3xtwin);
+}
+
+void isa8_3xtwin_device::device_add_mconfig(machine_config &config)
+{
+ r65c02_device &mpu(R65C02(config, "mpu", 16_MHz_XTAL / 4)); // R65C02P4
+ mpu.set_addrmap(AS_PROGRAM, &isa8_3xtwin_device::mpu_map);
+
+ com52c50_device &tic(COM52C50(config, "tic", 16_MHz_XTAL));
+ tic.int1_callback().set_inputline("mpu", r65c02_device::IRQ_LINE);
+ tic.int2_callback().set_inputline("mpu", r65c02_device::NMI_LINE);
+}
+
+ROM_START(3xtwin)
+ ROM_REGION(0x2000, "firmware", 0) // "MON VER E.01"
+ ROM_LOAD("370906502.u2", 0x0000, 0x2000, CRC(d4157bc4) SHA1(359428ce0047f9192a44790c8670af956cf6ed70))
+
+ // PLDs (undumped) marked "TWINCLK" (U9: ULC24/22V10-15) and "TWINLGC" (U12: PAL20L10ACNS)
+ROM_END
+
+const tiny_rom_entry *isa8_3xtwin_device::device_rom_region() const
+{
+ return ROM_NAME(3xtwin);
+}
diff --git a/src/devices/bus/isa/3xtwin.h b/src/devices/bus/isa/3xtwin.h
new file mode 100644
index 00000000000..a3f9c7296ad
--- /dev/null
+++ b/src/devices/bus/isa/3xtwin.h
@@ -0,0 +1,40 @@
+// license:BSD-3-Clause
+// copyright-holders:AJR
+/***************************************************************************
+
+ Emerald Technology Inc. 3XTwin IBM 5251/11 emulation board
+
+***************************************************************************/
+
+#ifndef MAME_BUS_ISA_3XTWIN_H
+#define MAME_BUS_ISA_3XTWIN_H
+
+#pragma once
+
+#include "isa.h"
+
+
+// ======================> isa8_3xtwin_device
+
+class isa8_3xtwin_device : public device_t, public device_isa8_card_interface
+{
+public:
+ // device type constructor
+ isa8_3xtwin_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock);
+
+protected:
+ // device-level overrides
+ virtual void device_start() override ATTR_COLD;
+ virtual ioport_constructor device_input_ports() const override ATTR_COLD;
+ virtual void device_add_mconfig(machine_config &config) override ATTR_COLD;
+ virtual const tiny_rom_entry *device_rom_region() const override ATTR_COLD;
+
+private:
+ // local memory map
+ void mpu_map(address_map &map) ATTR_COLD;
+};
+
+// device type declaration
+DECLARE_DEVICE_TYPE(ISA8_3XTWIN, isa8_3xtwin_device)
+
+#endif // MAME_BUS_ISA_3XTWIN_H
diff --git a/src/devices/bus/isa/acb2072.cpp b/src/devices/bus/isa/acb2072.cpp
new file mode 100644
index 00000000000..c9d7917a114
--- /dev/null
+++ b/src/devices/bus/isa/acb2072.cpp
@@ -0,0 +1,118 @@
+// license:BSD-3-Clause
+// copyright-holders:AJR
+/***************************************************************************
+
+ Adaptec ACB-2072 RLL Drive Controller
+
+ The PCB features the following ASICs:
+ — AIC-010FL Programmable Mass Storage Controller
+ — AIC-270L 2,7 RLL Encoder/Decoder
+ — AIC-280L (?)
+ — AIC-530L (bus interface?)
+ — AIC-540L (bus interface?)
+ — AIC-6225-15 High-Performance Monolithic Data Separator
+
+ In addition, there is a custom-badged “ACB-2072” 44-pin AMD PLCC which,
+ given that it also bears a 1980 Intel copyright as well as Adaptec's,
+ is almost certainly a Am8051, Am8053 or equivalent MCU with internal
+ ROM. A later revision replaces this IC with a Siemens SAB8052A.
+
+***************************************************************************/
+
+#include "emu.h"
+#include "acb2072.h"
+
+#include "cpu/mcs51/mcs51.h"
+
+// device type definition
+DEFINE_DEVICE_TYPE(ACB2072, acb2072_device, "acb2072", "ACB-2072 RLL Drive Controller")
+
+
+acb2072_device::acb2072_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock)
+ : device_t(mconfig, ACB2072, tag, owner, clock)
+ , device_isa8_card_interface(mconfig, *this)
+ , m_mcu(*this, "mcu")
+ , m_bios(*this, "bios")
+{
+}
+
+void acb2072_device::device_start()
+{
+}
+
+void acb2072_device::device_reset()
+{
+}
+
+
+static INPUT_PORTS_START(acb2072)
+ PORT_START("ADDR")
+ PORT_DIPNAME(0x07, 0x07, "BIOS Address") PORT_DIPLOCATION("J8:3,4,1") // BD, W-X, U-V
+ PORT_DIPSETTING(0x03, "Disabled")
+ PORT_DIPSETTING(0x07, "C800")
+ PORT_DIPSETTING(0x05, "CA00")
+ PORT_DIPSETTING(0x04, "CC00")
+ PORT_DIPSETTING(0x06, "F400")
+ PORT_DIPNAME(0x08, 0x08, "Port Address") PORT_DIPLOCATION("J8:2") // 324
+ PORT_DIPSETTING(0x08, "Normal")
+ PORT_DIPSETTING(0x00, "Alternate (324)")
+ PORT_DIPNAME(0x10, 0x10, "Reserved") PORT_DIPLOCATION("J5:3") // E-F
+ PORT_DIPSETTING(0x10, DEF_STR(Off))
+ PORT_DIPSETTING(0x00, DEF_STR(On))
+ PORT_DIPNAME(0x20, 0x20, "Reserved") PORT_DIPLOCATION("J5:4") // G-H
+ PORT_DIPSETTING(0x20, DEF_STR(Off))
+ PORT_DIPSETTING(0x00, DEF_STR(On))
+ PORT_DIPNAME(0x40, 0x40, "Reserved") PORT_DIPLOCATION("J5:5") // I-J
+ PORT_DIPSETTING(0x40, DEF_STR(Off))
+ PORT_DIPSETTING(0x00, DEF_STR(On))
+
+ PORT_START("TABLES")
+ PORT_DIPNAME(0x03, 0x03, "Drive 0 Defaults") PORT_DIPLOCATION("J9:2,1") // M-N, O-P
+ PORT_DIPSETTING(0x00, "4 Heads, 612 Cylinders (30 MB)")
+ PORT_DIPSETTING(0x01, "2 Heads, 612 Cylinders (15 MB)")
+ PORT_DIPSETTING(0x02, "5 Heads, 981 Cylinders (60 MB)")
+ PORT_DIPSETTING(0x03, "4 Heads, 615 Cylinders (20 MB)")
+ PORT_DIPNAME(0x0c, 0x0c, "Drive 1 Defaults") PORT_DIPLOCATION("J9:4,3") // Q-R, S-T
+ PORT_DIPSETTING(0x00, "4 Heads, 612 Cylinders (30 MB)")
+ PORT_DIPSETTING(0x04, "2 Heads, 612 Cylinders (15 MB)")
+ PORT_DIPSETTING(0x08, "5 Heads, 981 Cylinders (60 MB)")
+ PORT_DIPSETTING(0x0c, "4 Heads, 615 Cylinders (20 MB)")
+ PORT_DIPNAME(0x10, 0x10, "Drive 0 Type") PORT_DIPLOCATION("J5:1") // A-B
+ PORT_DIPSETTING(0x10, "Normal")
+ PORT_DIPSETTING(0x00, "Syquest")
+ PORT_DIPNAME(0x20, 0x20, "Drive 1 Type") PORT_DIPLOCATION("J5:2") // C-D
+ PORT_DIPSETTING(0x20, "Normal")
+ PORT_DIPSETTING(0x00, "Syquest")
+ PORT_DIPNAME(0x40, 0x40, "Self Diagnostics") PORT_DIPLOCATION("J5:6") // K-L
+ PORT_DIPSETTING(0x40, DEF_STR(Off))
+ PORT_DIPSETTING(0x00, DEF_STR(On))
+INPUT_PORTS_END
+
+ioport_constructor acb2072_device::device_input_ports() const
+{
+ return INPUT_PORTS_NAME(acb2072);
+}
+
+void acb2072_device::device_add_mconfig(machine_config &config)
+{
+ // XTAL is marked 49S150
+ AM8753(config, m_mcu, 15_MHz_XTAL / 2).set_disable();
+}
+
+
+ROM_START(acb2072)
+ ROM_REGION(0x2000, "bios", 0)
+ ROM_SYSTEM_BIOS(0, "b", "Rev. B")
+ ROMX_LOAD("adaptec_inc_408100k_bios_1987_411503_00b.u11", 0x0000, 0x2000, CRC(1b1a854e) SHA1(3550ae7a94e03e77f40bff91024dfc9aed8f6c2f), ROM_BIOS(0)) // M2764AFI
+ ROM_SYSTEM_BIOS(1, "a", "Rev. A")
+ ROMX_LOAD("adaptec_acb2072_bios_408100_h_411503-00a.u11", 0x0000, 0x2000, CRC(5ca303cf) SHA1(82800005d532f0dc35cbf9ea6af75a97cb8b2e71), ROM_BIOS(1))
+
+ ROM_REGION(0x2000, "mcu", 0)
+ ROM_LOAD("adaptec_inc_c86_acb-2072_408101-00b.u8", 0x0000, 0x2000, NO_DUMP)
+ //ROM_LOAD("adaptec_inc_c86_acb-2072mcode_408101-00c.u8", 0x0000, 0x2000, NO_DUMP) // SAB8052A-N
+ROM_END
+
+const tiny_rom_entry *acb2072_device::device_rom_region() const
+{
+ return ROM_NAME(acb2072);
+}
diff --git a/src/devices/bus/isa/acb2072.h b/src/devices/bus/isa/acb2072.h
new file mode 100644
index 00000000000..d3577ce32f1
--- /dev/null
+++ b/src/devices/bus/isa/acb2072.h
@@ -0,0 +1,38 @@
+// license:BSD-3-Clause
+// copyright-holders:AJR
+/***************************************************************************
+
+ Adaptec ACB-2072 RLL Drive Controller
+
+***************************************************************************/
+
+#ifndef MAME_BUS_ISA_ACB2072_H
+#define MAME_BUS_ISA_ACB2072_H
+
+#pragma once
+
+#include "isa.h"
+
+class acb2072_device : public device_t, public device_isa8_card_interface
+{
+public:
+ acb2072_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 ATTR_COLD;
+ virtual void device_reset() override ATTR_COLD;
+ virtual ioport_constructor device_input_ports() const override ATTR_COLD;
+ virtual const tiny_rom_entry *device_rom_region() const override ATTR_COLD;
+ virtual void device_add_mconfig(machine_config &config) override ATTR_COLD;
+
+private:
+ required_device<cpu_device> m_mcu;
+ required_region_ptr<u8> m_bios;
+};
+
+// device type declaration
+DECLARE_DEVICE_TYPE(ACB2072, acb2072_device)
+
+#endif // MAME_BUS_ISA_ACB2072_H
diff --git a/src/devices/bus/isa/adlib.cpp b/src/devices/bus/isa/adlib.cpp
index 6a900b0e09d..0f859a0ebbd 100644
--- a/src/devices/bus/isa/adlib.cpp
+++ b/src/devices/bus/isa/adlib.cpp
@@ -15,22 +15,22 @@
#define ym3812_StdClock 3579545
-READ8_MEMBER( isa8_adlib_device::ym3812_16_r )
+uint8_t isa8_adlib_device::ym3812_16_r(offs_t offset)
{
uint8_t retVal = 0xff;
switch(offset)
{
- case 0 : retVal = m_ym3812->status_port_r(); break;
+ case 0 : retVal = m_ym3812->status_r(); break;
}
return retVal;
}
-WRITE8_MEMBER( isa8_adlib_device::ym3812_16_w )
+void isa8_adlib_device::ym3812_16_w(offs_t offset, uint8_t data)
{
switch(offset)
{
- case 0 : m_ym3812->control_port_w(data); break;
- case 1 : m_ym3812->write_port_w(data); break;
+ case 0 : m_ym3812->address_w(data); break;
+ case 1 : m_ym3812->data_w(data); break;
}
}
@@ -72,7 +72,7 @@ isa8_adlib_device::isa8_adlib_device(const machine_config &mconfig, const char *
void isa8_adlib_device::device_start()
{
set_isa_device();
- m_isa->install_device(0x0388, 0x0389, read8_delegate( FUNC(isa8_adlib_device::ym3812_16_r), this ), write8_delegate( FUNC(isa8_adlib_device::ym3812_16_w), this ) );
+ m_isa->install_device(0x0388, 0x0389, read8sm_delegate(*this, FUNC(isa8_adlib_device::ym3812_16_r)), write8sm_delegate(*this, FUNC(isa8_adlib_device::ym3812_16_w)));
}
//-------------------------------------------------
diff --git a/src/devices/bus/isa/adlib.h b/src/devices/bus/isa/adlib.h
index 590ea4f675e..138f6614b0d 100644
--- a/src/devices/bus/isa/adlib.h
+++ b/src/devices/bus/isa/adlib.h
@@ -6,7 +6,7 @@
#pragma once
#include "isa.h"
-#include "sound/3812intf.h"
+#include "sound/ymopl.h"
//**************************************************************************
// TYPE DEFINITIONS
@@ -22,16 +22,16 @@ public:
// construction/destruction
isa8_adlib_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
- DECLARE_READ8_MEMBER(ym3812_16_r);
- DECLARE_WRITE8_MEMBER(ym3812_16_w);
+ uint8_t ym3812_16_r(offs_t offset);
+ void ym3812_16_w(offs_t offset, uint8_t data);
protected:
// device-level overrides
- virtual void device_start() override;
- virtual void device_reset() override;
+ virtual void device_start() override ATTR_COLD;
+ virtual void device_reset() override ATTR_COLD;
// optional information overrides
- virtual void device_add_mconfig(machine_config &config) override;
+ virtual void device_add_mconfig(machine_config &config) override ATTR_COLD;
private:
// internal state
diff --git a/src/devices/bus/isa/aga.cpp b/src/devices/bus/isa/aga.cpp
index f15abd2eb51..daf44fa9750 100644
--- a/src/devices/bus/isa/aga.cpp
+++ b/src/devices/bus/isa/aga.cpp
@@ -9,6 +9,9 @@
#include "aga.h"
#include "video/cgapal.h"
+//#define VERBOSE 1
+#include "logmacro.h"
+
#define CGA_HCLK (XTAL(14'318'181)/8)
#define CGA_LCLK (XTAL(14'318'181)/16)
@@ -51,7 +54,9 @@ INPUT_PORTS_END
#define CGA_MONITOR (m_cga_config->read()&0x1C)
#define CGA_MONITOR_COMPOSITE 0x08 /* Colour composite */
-DEFINE_DEVICE_TYPE(ISA8_AGA, isa8_aga_device, "aga", "AGA")
+DEFINE_DEVICE_TYPE(ISA8_AGA, isa8_aga_device, "isa_aga", "AGA")
+DEFINE_DEVICE_TYPE(ISA8_AGA_PC200, isa8_aga_pc200_device, "isa_aga_pc200", "AGA PC200")
+
//-------------------------------------------------
// isa8_aga_device - constructor
@@ -89,7 +94,7 @@ isa8_aga_device::isa8_aga_device(const machine_config &mconfig, device_type type
void isa8_aga_device::device_start()
{
- if (m_palette != nullptr && !m_palette->started())
+ if (m_palette && !m_palette->started())
throw device_missing_dependencies();
m_mode = AGA_COLOR;
@@ -98,26 +103,19 @@ void isa8_aga_device::device_start()
m_videoram = std::make_unique<uint8_t[]>(0x10000);
set_isa_device();
- m_isa->install_memory(0xb0000, 0xbffff, read8_delegate(FUNC(isa8_aga_device::pc_aga_videoram_r),this), write8_delegate(FUNC(isa8_aga_device::pc_aga_videoram_w),this));
- m_isa->install_device(0x3b0, 0x3bf, read8_delegate( FUNC(isa8_aga_device::pc_aga_mda_r), this ), write8_delegate( FUNC(isa8_aga_device::pc_aga_mda_w), this ) );
- m_isa->install_device(0x3d0, 0x3df, read8_delegate( FUNC(isa8_aga_device::pc_aga_cga_r), this ), write8_delegate( FUNC(isa8_aga_device::pc_aga_cga_w), this ) );
+ m_isa->install_memory(0xb0000, 0xbffff, read8sm_delegate(*this, FUNC(isa8_aga_device::pc_aga_videoram_r)), write8sm_delegate(*this, FUNC(isa8_aga_device::pc_aga_videoram_w)));
+ m_isa->install_device(0x3b0, 0x3bf, read8sm_delegate(*this, FUNC(isa8_aga_device::pc_aga_mda_r)), write8sm_delegate(*this, FUNC(isa8_aga_device::pc_aga_mda_w)));
+ m_isa->install_device(0x3d0, 0x3df, read8sm_delegate(*this, FUNC(isa8_aga_device::pc_aga_cga_r)), write8sm_delegate(*this, FUNC(isa8_aga_device::pc_aga_cga_w)));
/* Initialise the cga palette */
- int i;
- for ( i = 0; i < CGA_PALETTE_SETS * 16; i++ )
- {
- m_palette->set_pen_color( i, cga_palette[i][0], cga_palette[i][1], cga_palette[i][2] );
- }
+ for (int i = 0; i < CGA_PALETTE_SETS * 16; i++)
+ m_palette->set_pen_color(i, cga_palette[i][0], cga_palette[i][1], cga_palette[i][2]);
- i = 0x8000;
- for ( int r = 0; r < 32; r++ )
- {
- for ( int g = 0; g < 32; g++ )
- {
- for ( int b = 0; b < 32; b++ )
- {
- m_palette->set_pen_color( i, r << 3, g << 3, b << 3 );
+ for (int i = 0x8000, r = 0; r < 32; r++) {
+ for (int g = 0; g < 32; g++) {
+ for (int b = 0; b < 32; b++) {
+ m_palette->set_pen_color(i, r << 3, g << 3, b << 3);
i++;
}
}
@@ -125,7 +123,7 @@ void isa8_aga_device::device_start()
uint8_t *gfx = &memregion("gfx1")->base()[0x8000];
/* just a plain bit pattern for graphics data generation */
- for (i = 0; i < 256; i++)
+ for (int i = 0; i < 256; i++)
gfx[i] = i;
}
@@ -136,18 +134,16 @@ ROM_END
const tiny_rom_entry *isa8_aga_device::device_rom_region() const
{
- return ROM_NAME( aga );
+ return ROM_NAME(aga);
}
ioport_constructor isa8_aga_device::device_input_ports() const
{
- return INPUT_PORTS_NAME( aga );
+ return INPUT_PORTS_NAME(aga);
}
-DEFINE_DEVICE_TYPE(ISA8_AGA_PC200, isa8_aga_pc200_device, "aga_pc200", "AGA PC200")
-
//-------------------------------------------------
// isa8_aga_pc200_device - constructor
//-------------------------------------------------
@@ -167,7 +163,7 @@ ROM_END
const tiny_rom_entry *isa8_aga_pc200_device::device_rom_region() const
{
- return ROM_NAME( aga_pc200 );
+ return ROM_NAME(aga_pc200);
}
//-------------------------------------------------
@@ -176,7 +172,7 @@ const tiny_rom_entry *isa8_aga_pc200_device::device_rom_region() const
void isa8_aga_pc200_device::device_start()
{
- if (m_palette != nullptr && !m_palette->started())
+ if (m_palette && !m_palette->started())
throw device_missing_dependencies();
m_mode = AGA_COLOR;
@@ -185,26 +181,19 @@ void isa8_aga_pc200_device::device_start()
m_videoram = std::make_unique<uint8_t[]>(0x10000);
set_isa_device();
- m_isa->install_memory(0xb0000, 0xbffff, read8_delegate(FUNC(isa8_aga_pc200_device::pc200_videoram_r),this), write8_delegate(FUNC(isa8_aga_pc200_device::pc200_videoram_w),this));
- m_isa->install_device(0x3b0, 0x3bf, read8_delegate( FUNC(isa8_aga_device::pc_aga_mda_r), this ), write8_delegate( FUNC(isa8_aga_device::pc_aga_mda_w), this ) );
- m_isa->install_device(0x3d0, 0x3df, read8_delegate( FUNC(isa8_aga_pc200_device::pc200_cga_r), this ), write8_delegate( FUNC(isa8_aga_pc200_device::pc200_cga_w), this ) );
+ m_isa->install_memory(0xb0000, 0xbffff, read8sm_delegate(*this, FUNC(isa8_aga_pc200_device::pc200_videoram_r)), write8sm_delegate(*this, FUNC(isa8_aga_pc200_device::pc200_videoram_w)));
+ m_isa->install_device(0x3b0, 0x3bf, read8sm_delegate(*this, FUNC(isa8_aga_pc200_device::pc_aga_mda_r)), write8sm_delegate(*this, FUNC(isa8_aga_pc200_device::pc_aga_mda_w)));
+ m_isa->install_device(0x3d0, 0x3df, read8sm_delegate(*this, FUNC(isa8_aga_pc200_device::pc200_cga_r)), write8sm_delegate(*this, FUNC(isa8_aga_pc200_device::pc200_cga_w)));
/* Initialise the cga palette */
- int i;
- for ( i = 0; i < CGA_PALETTE_SETS * 16; i++ )
- {
- m_palette->set_pen_color( i, cga_palette[i][0], cga_palette[i][1], cga_palette[i][2] );
- }
+ for (int i = 0; i < CGA_PALETTE_SETS * 16; i++)
+ m_palette->set_pen_color(i, cga_palette[i][0], cga_palette[i][1], cga_palette[i][2]);
- i = 0x8000;
- for ( int r = 0; r < 32; r++ )
- {
- for ( int g = 0; g < 32; g++ )
- {
- for ( int b = 0; b < 32; b++ )
- {
- m_palette->set_pen_color( i, r << 3, g << 3, b << 3 );
+ for (int i = 0x8000, r = 0; r < 32; r++) {
+ for (int g = 0; g < 32; g++) {
+ for (int b = 0; b < 32; b++) {
+ m_palette->set_pen_color(i, r << 3, g << 3, b << 3);
i++;
}
}
@@ -212,23 +201,21 @@ void isa8_aga_pc200_device::device_start()
uint8_t *gfx = &memregion("gfx1")->base()[0x8000];
/* just a plain bit pattern for graphics data generation */
- for (i = 0; i < 256; i++)
+ for (int i = 0; i < 256; i++)
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 )
- {
+ if (state)
m_framecnt++;
- }
}
@@ -237,38 +224,37 @@ MC6845_UPDATE_ROW( isa8_aga_device::aga_update_row )
if (m_update_row_type == -1)
return;
- switch (m_update_row_type)
- {
- case MDA_TEXT_INTEN:
- mda_text_inten_update_row(bitmap, cliprect, ma, ra, y, x_count, cursor_x, de, hbp, vbp);
- break;
- case MDA_TEXT_BLINK:
- mda_text_blink_update_row(bitmap, cliprect, ma, ra, y, x_count, cursor_x, de, hbp, vbp);
- break;
- case CGA_TEXT_INTEN:
- cga_text_inten_update_row(bitmap, cliprect, ma, ra, y, x_count, cursor_x, de, hbp, vbp);
- break;
- case CGA_TEXT_INTEN_ALT:
- cga_text_inten_alt_update_row(bitmap, cliprect, ma, ra, y, x_count, cursor_x, de, hbp, vbp);
- break;
- case CGA_TEXT_BLINK:
- cga_text_blink_update_row(bitmap, cliprect, ma, ra, y, x_count, cursor_x, de, hbp, vbp);
- break;
- case CGA_TEXT_BLINK_ALT:
- cga_text_blink_alt_update_row(bitmap, cliprect, ma, ra, y, x_count, cursor_x, de, hbp, vbp);
- break;
- case CGA_GFX_1BPP:
- cga_gfx_1bpp_update_row(bitmap, cliprect, ma, ra, y, x_count, cursor_x, de, hbp, vbp);
- break;
- case CGA_GFX_2BPP:
- cga_gfx_2bpp_update_row(bitmap, cliprect, ma, ra, y, x_count, cursor_x, de, hbp, vbp);
- break;
- case CGA_GFX_4BPPL:
- cga_gfx_4bppl_update_row(bitmap, cliprect, ma, ra, y, x_count, cursor_x, de, hbp, vbp);
- break;
- case CGA_GFX_4BPPH:
- cga_gfx_4bpph_update_row(bitmap, cliprect, ma, ra, y, x_count, cursor_x, de, hbp, vbp);
- break;
+ switch (m_update_row_type) {
+ case MDA_TEXT_INTEN:
+ mda_text_inten_update_row(bitmap, cliprect, ma, ra, y, x_count, cursor_x, de, hbp, vbp);
+ break;
+ case MDA_TEXT_BLINK:
+ mda_text_blink_update_row(bitmap, cliprect, ma, ra, y, x_count, cursor_x, de, hbp, vbp);
+ break;
+ case CGA_TEXT_INTEN:
+ cga_text_inten_update_row(bitmap, cliprect, ma, ra, y, x_count, cursor_x, de, hbp, vbp);
+ break;
+ case CGA_TEXT_INTEN_ALT:
+ cga_text_inten_alt_update_row(bitmap, cliprect, ma, ra, y, x_count, cursor_x, de, hbp, vbp);
+ break;
+ case CGA_TEXT_BLINK:
+ cga_text_blink_update_row(bitmap, cliprect, ma, ra, y, x_count, cursor_x, de, hbp, vbp);
+ break;
+ case CGA_TEXT_BLINK_ALT:
+ cga_text_blink_alt_update_row(bitmap, cliprect, ma, ra, y, x_count, cursor_x, de, hbp, vbp);
+ break;
+ case CGA_GFX_1BPP:
+ cga_gfx_1bpp_update_row(bitmap, cliprect, ma, ra, y, x_count, cursor_x, de, hbp, vbp);
+ break;
+ case CGA_GFX_2BPP:
+ cga_gfx_2bpp_update_row(bitmap, cliprect, ma, ra, y, x_count, cursor_x, de, hbp, vbp);
+ break;
+ case CGA_GFX_4BPPL:
+ cga_gfx_4bppl_update_row(bitmap, cliprect, ma, ra, y, x_count, cursor_x, de, hbp, vbp);
+ break;
+ case CGA_GFX_4BPPH:
+ cga_gfx_4bpph_update_row(bitmap, cliprect, ma, ra, y, x_count, cursor_x, de, hbp, vbp);
+ break;
}
}
@@ -281,11 +267,11 @@ void isa8_aga_device::device_add_mconfig(machine_config &config)
PALETTE(config, m_palette).set_entries(/* CGA_PALETTE_SETS * 16*/ 65536);
- MC6845(config, m_mc6845, XTAL(14'318'181)/8);
+ MC6845(config, m_mc6845, XTAL(14'318'181) / 8);
m_mc6845->set_screen(AGA_SCREEN_NAME);
m_mc6845->set_show_border_area(false);
m_mc6845->set_char_width(8);
- m_mc6845->set_update_row_callback(FUNC(isa8_aga_device::aga_update_row), this);
+ m_mc6845->set_update_row_callback(FUNC(isa8_aga_device::aga_update_row));
m_mc6845->out_hsync_callback().set(FUNC(isa8_aga_device::hsync_changed));
m_mc6845->out_vsync_callback().set(FUNC(isa8_aga_device::vsync_changed));
}
@@ -300,26 +286,24 @@ void isa8_aga_device::device_add_mconfig(machine_config &config)
/* colors need fixing in the mda_text_* functions ! */
MC6845_UPDATE_ROW( isa8_aga_device::mda_text_inten_update_row )
{
- const rgb_t *palette = m_palette->palette()->entry_list_raw();
- uint8_t *videoram = m_videoram.get();
- uint32_t *p = &bitmap.pix32(y);
- uint16_t chr_base = ( ra & 0x08 ) ? 0x800 | ( ra & 0x07 ) : ra;
- int i;
-
- if ( y == 0 ) logerror("mda_text_inten_update_row\n");
- for ( i = 0; i < x_count; i++ ) {
- uint16_t offset = ( ( ma + i ) << 1 ) & 0x0FFF;
- uint8_t chr = videoram[ offset ];
- uint8_t attr = videoram[ offset + 1 ];
- uint8_t data = m_mda_chr_gen[ chr_base + chr * 8 ];
- uint8_t fg = ( attr & 0x08 ) ? 3 : 2;
+ rgb_t const *const palette = m_palette->palette()->entry_list_raw();
+ uint8_t const *const videoram = m_videoram.get();
+ uint32_t *p = &bitmap.pix(y);
+ uint16_t const chr_base = (ra & 0x08) ? 0x800 | (ra & 0x07) : ra;
+
+ if (y == 0) logerror("mda_text_inten_update_row\n");
+ for (int i = 0; i < x_count; i++) {
+ uint16_t const offset = ((ma + i) << 1) & 0x0fff;
+ uint8_t const chr = videoram[offset];
+ uint8_t const attr = videoram[offset + 1];
+ uint8_t data = m_mda_chr_gen[chr_base + chr * 8];
+ uint8_t fg = (attr & 0x08) ? 3 : 2;
uint8_t bg = 0;
- if ( ( attr & ~0x88 ) == 0 ) {
+ if (!(attr & ~0x88))
data = 0x00;
- }
- switch( attr ) {
+ switch (attr) {
case 0x70:
bg = 2;
fg = 0;
@@ -328,348 +312,330 @@ MC6845_UPDATE_ROW( isa8_aga_device::mda_text_inten_update_row )
bg = 2;
fg = 1;
break;
- case 0xF0:
+ case 0xf0:
bg = 3;
fg = 0;
break;
- case 0xF8:
+ case 0xf8:
bg = 3;
fg = 1;
break;
}
- if ( i == cursor_x || ( attr & 0x07 ) == 0x01 ) {
- data = 0xFF;
- }
-
- *p = palette[( data & 0x80 ) ? fg : bg]; p++;
- *p = palette[( data & 0x40 ) ? fg : bg]; p++;
- *p = palette[( data & 0x20 ) ? fg : bg]; p++;
- *p = palette[( data & 0x10 ) ? fg : bg]; p++;
- *p = palette[( data & 0x08 ) ? fg : bg]; p++;
- *p = palette[( data & 0x04 ) ? fg : bg]; p++;
- *p = palette[( data & 0x02 ) ? fg : bg]; p++;
- *p = palette[( data & 0x01 ) ? fg : bg]; p++;
- if ( ( chr & 0xE0 ) == 0xC0 ) {
- *p = palette[( data & 0x01 ) ? fg : bg]; p++;
- } else {
- *p = palette[bg]; p++;
- }
+ if (i == cursor_x || (attr & 0x07) == 0x01)
+ data = 0xff;
+
+ *p++ = palette[BIT(data, 7) ? fg : bg];
+ *p++ = palette[BIT(data, 6) ? fg : bg];
+ *p++ = palette[BIT(data, 5) ? fg : bg];
+ *p++ = palette[BIT(data, 4) ? fg : bg];
+ *p++ = palette[BIT(data, 3) ? fg : bg];
+ *p++ = palette[BIT(data, 2) ? fg : bg];
+ *p++ = palette[BIT(data, 1) ? fg : bg];
+ *p++ = palette[BIT(data, 0) ? fg : bg];
+ if ((chr & 0xe0) == 0xc0)
+ *p++ = palette[BIT(data, 0) ? fg : bg];
+ else
+ *p++ = palette[bg];
}
}
MC6845_UPDATE_ROW( isa8_aga_device::mda_text_blink_update_row )
{
- uint8_t *videoram = m_videoram.get();
- const rgb_t *palette = m_palette->palette()->entry_list_raw();
- uint32_t *p = &bitmap.pix32(y);
- uint16_t chr_base = ( ra & 0x08 ) ? 0x800 | ( ra & 0x07 ) : ra;
- int i;
-
- if ( y == 0 ) logerror("mda_text_blink_update_row\n");
- for ( i = 0; i < x_count; i++ ) {
- uint16_t offset = ( ( ma + i ) << 1 ) & 0x0FFF;
- uint8_t chr = videoram[ offset ];
- uint8_t attr = videoram[ offset + 1 ];
- uint8_t data = m_mda_chr_gen[ chr_base + chr * 8 ];
- uint8_t fg = ( attr & 0x08 ) ? 3 : 2;
+ uint8_t const *const videoram = m_videoram.get();
+ rgb_t const *const palette = m_palette->palette()->entry_list_raw();
+ uint32_t *p = &bitmap.pix(y);
+ uint16_t const chr_base = (ra & 0x08) ? 0x800 | (ra & 0x07) : ra;
+
+ if (y == 0) logerror("mda_text_blink_update_row\n");
+ for (int i = 0; i < x_count; i++) {
+ uint16_t const offset = ((ma + i) << 1) & 0x0fff;
+ uint8_t const chr = videoram[offset];
+ uint8_t const attr = videoram[offset + 1];
+ uint8_t data = m_mda_chr_gen[chr_base + chr * 8];
+ uint8_t fg = (attr & 0x08) ? 3 : 2;
uint8_t bg = 0;
- if ( ( attr & ~0x88 ) == 0 ) {
+ if (!(attr & ~0x88))
data = 0x00;
- }
- switch( attr ) {
+ switch (attr) {
case 0x70:
- case 0xF0:
+ case 0xf0:
bg = 2;
fg = 0;
break;
case 0x78:
- case 0xF8:
+ case 0xf8:
bg = 2;
fg = 1;
break;
}
- if ( i == cursor_x ) {
- data = 0xFF;
+ if (i == cursor_x) {
+ data = 0xff;
} else {
- if ( ( attr & 0x07 ) == 0x01 ) {
- data = 0xFF;
- }
- if ( ( attr & 0x80 ) && ( m_framecnt & 0x40 ) ) {
+ if ((attr & 0x07) == 0x01)
+ data = 0xff;
+ if ((attr & 0x80) && (m_framecnt & 0x40))
data = 0x00;
- }
}
- *p = palette[( data & 0x80 ) ? fg : bg]; p++;
- *p = palette[( data & 0x40 ) ? fg : bg]; p++;
- *p = palette[( data & 0x20 ) ? fg : bg]; p++;
- *p = palette[( data & 0x10 ) ? fg : bg]; p++;
- *p = palette[( data & 0x08 ) ? fg : bg]; p++;
- *p = palette[( data & 0x04 ) ? fg : bg]; p++;
- *p = palette[( data & 0x02 ) ? fg : bg]; p++;
- *p = palette[( data & 0x01 ) ? fg : bg]; p++;
- if ( ( chr & 0xE0 ) == 0xC0 ) {
- *p = palette[( data & 0x01 ) ? fg : bg]; p++;
- } else {
- *p = palette[bg]; p++;
- }
+ *p++ = palette[BIT(data, 7) ? fg : bg];
+ *p++ = palette[BIT(data, 6) ? fg : bg];
+ *p++ = palette[BIT(data, 5) ? fg : bg];
+ *p++ = palette[BIT(data, 4) ? fg : bg];
+ *p++ = palette[BIT(data, 3) ? fg : bg];
+ *p++ = palette[BIT(data, 2) ? fg : bg];
+ *p++ = palette[BIT(data, 1) ? fg : bg];
+ *p++ = palette[BIT(data, 0) ? fg : bg];
+ if ((chr & 0xe0) == 0xc0)
+ *p++ = palette[BIT(data, 0) ? fg : bg];
+ else
+ *p++ = palette[bg];
}
}
MC6845_UPDATE_ROW( isa8_aga_device::cga_text_inten_update_row )
{
- uint8_t *videoram = m_videoram.get();
- const rgb_t *palette = m_palette->palette()->entry_list_raw();
- uint32_t *p = &bitmap.pix32(y);
- int i;
-
- if ( y == 0 ) logerror("cga_text_inten_update_row\n");
- for ( i = 0; i < x_count; i++ ) {
- uint16_t offset = ( ( ma + i ) << 1 ) & 0x3fff;
- uint8_t chr = videoram[ offset ];
- uint8_t attr = videoram[ offset +1 ];
- uint8_t data = m_cga_chr_gen[ chr * 16 + ra ];
- uint16_t fg = attr & 0x0F;
- uint16_t bg = ( attr >> 4 ) & 0x07;
-
- if ( i == cursor_x ) {
- data = 0xFF;
- }
+ uint8_t const *const videoram = m_videoram.get();
+ rgb_t const *const palette = m_palette->palette()->entry_list_raw();
+ uint32_t *p = &bitmap.pix(y);
+
+ if (y == 0) logerror("cga_text_inten_update_row\n");
+ for (int i = 0; i < x_count; i++) {
+ uint16_t const offset = ((ma + i) << 1 ) & 0x3fff;
+ uint8_t const chr = videoram[offset];
+ uint8_t const attr = videoram[offset + 1];
+ uint8_t data = m_cga_chr_gen[chr * 16 + ra];
+ uint16_t fg = attr & 0x0f;
+ uint16_t bg = (attr >> 4) & 0x07;
- *p = palette[( data & 0x80 ) ? fg : bg]; p++;
- *p = palette[( data & 0x40 ) ? fg : bg]; p++;
- *p = palette[( data & 0x20 ) ? fg : bg]; p++;
- *p = palette[( data & 0x10 ) ? fg : bg]; p++;
- *p = palette[( data & 0x08 ) ? fg : bg]; p++;
- *p = palette[( data & 0x04 ) ? fg : bg]; p++;
- *p = palette[( data & 0x02 ) ? fg : bg]; p++;
- *p = palette[( data & 0x01 ) ? fg : bg]; p++;
+ if (i == cursor_x)
+ data = 0xff;
+
+ *p++ = palette[BIT(data, 7) ? fg : bg];
+ *p++ = palette[BIT(data, 6) ? fg : bg];
+ *p++ = palette[BIT(data, 5) ? fg : bg];
+ *p++ = palette[BIT(data, 4) ? fg : bg];
+ *p++ = palette[BIT(data, 3) ? fg : bg];
+ *p++ = palette[BIT(data, 2) ? fg : bg];
+ *p++ = palette[BIT(data, 1) ? fg : bg];
+ *p++ = palette[BIT(data, 0) ? fg : bg];
}
}
MC6845_UPDATE_ROW( isa8_aga_device::cga_text_inten_alt_update_row )
{
- const rgb_t *palette = m_palette->palette()->entry_list_raw();
- uint8_t *videoram = m_videoram.get();
- uint32_t *p = &bitmap.pix32(y);
- int i;
-
- if ( y == 0 ) logerror("cga_text_inten_alt_update_row\n");
- for ( i = 0; i < x_count; i++ ) {
- uint16_t offset = ( ( ma + i ) << 1 ) & 0x3fff;
- uint8_t chr = videoram[ offset ];
- uint8_t attr = videoram[ offset +1 ];
- uint8_t data = m_cga_chr_gen[ chr * 16 + ra ];
- uint16_t fg = attr & 0x0F;
-
- if ( i == cursor_x ) {
- data = 0xFF;
- }
-
- *p = palette[( data & 0x80 ) ? fg : 0]; p++;
- *p = palette[( data & 0x40 ) ? fg : 0]; p++;
- *p = palette[( data & 0x20 ) ? fg : 0]; p++;
- *p = palette[( data & 0x10 ) ? fg : 0]; p++;
- *p = palette[( data & 0x08 ) ? fg : 0]; p++;
- *p = palette[( data & 0x04 ) ? fg : 0]; p++;
- *p = palette[( data & 0x02 ) ? fg : 0]; p++;
- *p = palette[( data & 0x01 ) ? fg : 0]; p++;
+ rgb_t const *const palette = m_palette->palette()->entry_list_raw();
+ uint8_t const *const videoram = m_videoram.get();
+ uint32_t *p = &bitmap.pix(y);
+
+ if (y == 0) logerror("cga_text_inten_alt_update_row\n");
+ for (int i = 0; i < x_count; i++) {
+ uint16_t const offset = ((ma + i) << 1) & 0x3fff;
+ uint8_t const chr = videoram[offset];
+ uint8_t const attr = videoram[offset + 1];
+ uint8_t data = m_cga_chr_gen[chr * 16 + ra];
+ uint16_t fg = attr & 0x0f;
+
+ if (i == cursor_x)
+ data = 0xff;
+
+ *p++ = palette[BIT(data, 7) ? fg : 0];
+ *p++ = palette[BIT(data, 6) ? fg : 0];
+ *p++ = palette[BIT(data, 5) ? fg : 0];
+ *p++ = palette[BIT(data, 4) ? fg : 0];
+ *p++ = palette[BIT(data, 3) ? fg : 0];
+ *p++ = palette[BIT(data, 2) ? fg : 0];
+ *p++ = palette[BIT(data, 1) ? fg : 0];
+ *p++ = palette[BIT(data, 0) ? fg : 0];
}
}
MC6845_UPDATE_ROW( isa8_aga_device::cga_text_blink_update_row )
{
- const rgb_t *palette = m_palette->palette()->entry_list_raw();
- uint8_t *videoram = m_videoram.get();
- uint32_t *p = &bitmap.pix32(y);
- int i;
-
- for ( i = 0; i < x_count; i++ ) {
- uint16_t offset = ( ( ma + i ) << 1 ) & 0x3fff;
- uint8_t chr = videoram[ offset ];
- uint8_t attr = videoram[ offset +1 ];
- uint8_t data = m_cga_chr_gen[ chr * 16 + ra ];
- uint16_t fg = attr & 0x0F;
+ rgb_t const *const palette = m_palette->palette()->entry_list_raw();
+ uint8_t const *const videoram = m_videoram.get();
+ uint32_t *p = &bitmap.pix(y);
+
+ for (int i = 0; i < x_count; i++) {
+ uint16_t const offset = ((ma + i) << 1) & 0x3fff;
+ uint8_t const chr = videoram[offset];
+ uint8_t const attr = videoram[offset + 1];
+ uint8_t data = m_cga_chr_gen[chr * 16 + ra];
+ uint16_t fg = attr & 0x0f;
uint16_t bg = (attr >> 4) & 0x07;
- if ( i == cursor_x ) {
- data = 0xFF;
+ if (i == cursor_x) {
+ data = 0xff;
} else {
- if ( ( attr & 0x80 ) && ( m_framecnt & 0x10 ) ) {
+ if ((attr & 0x80) && (m_framecnt & 0x10))
data = 0x00;
- }
}
- *p = palette[( data & 0x80 ) ? fg : bg]; p++;
- *p = palette[( data & 0x40 ) ? fg : bg]; p++;
- *p = palette[( data & 0x20 ) ? fg : bg]; p++;
- *p = palette[( data & 0x10 ) ? fg : bg]; p++;
- *p = palette[( data & 0x08 ) ? fg : bg]; p++;
- *p = palette[( data & 0x04 ) ? fg : bg]; p++;
- *p = palette[( data & 0x02 ) ? fg : bg]; p++;
- *p = palette[( data & 0x01 ) ? fg : bg]; p++;
+ *p++ = palette[BIT(data, 7) ? fg : bg];
+ *p++ = palette[BIT(data, 6) ? fg : bg];
+ *p++ = palette[BIT(data, 5) ? fg : bg];
+ *p++ = palette[BIT(data, 4) ? fg : bg];
+ *p++ = palette[BIT(data, 3) ? fg : bg];
+ *p++ = palette[BIT(data, 2) ? fg : bg];
+ *p++ = palette[BIT(data, 1) ? fg : bg];
+ *p++ = palette[BIT(data, 0) ? fg : bg];
}
}
MC6845_UPDATE_ROW( isa8_aga_device::cga_text_blink_alt_update_row )
{
- const rgb_t *palette = m_palette->palette()->entry_list_raw();
- uint8_t *videoram = m_videoram.get();
- uint32_t *p = &bitmap.pix32(y);
- int i;
-
- if ( y == 0 ) logerror("cga_text_blink_alt_update_row\n");
- for ( i = 0; i < x_count; i++ ) {
- uint16_t offset = ( ( ma + i ) << 1 ) & 0x3fff;
- uint8_t chr = videoram[ offset ];
- uint8_t attr = videoram[ offset +1 ];
- uint8_t data = m_cga_chr_gen[ chr * 16 + ra ];
+ rgb_t const *const palette = m_palette->palette()->entry_list_raw();
+ uint8_t const *const videoram = m_videoram.get();
+ uint32_t *p = &bitmap.pix(y);
+
+ if (y == 0) logerror("cga_text_blink_alt_update_row\n");
+ for (int i = 0; i < x_count; i++) {
+ uint16_t const offset = ((ma + i) << 1) & 0x3fff;
+ uint8_t const chr = videoram[offset];
+ uint8_t const attr = videoram[offset + 1];
+ uint8_t data = m_cga_chr_gen[chr * 16 + ra];
uint16_t fg = attr & 0x07;
uint16_t bg = 0;
- if ( i == cursor_x ) {
+ if (i == cursor_x) {
data = 0xFF;
} else {
- if ( ( attr & 0x80 ) && ( m_framecnt & 0x10 ) ) {
+ if ((attr & 0x80) && (m_framecnt & 0x10)) {
data = 0x00;
- bg = ( attr >> 4 ) & 0x07;
+ bg = (attr >> 4) & 0x07;
}
}
- *p = palette[( data & 0x80 ) ? fg : bg]; p++;
- *p = palette[( data & 0x40 ) ? fg : bg]; p++;
- *p = palette[( data & 0x20 ) ? fg : bg]; p++;
- *p = palette[( data & 0x10 ) ? fg : bg]; p++;
- *p = palette[( data & 0x08 ) ? fg : bg]; p++;
- *p = palette[( data & 0x04 ) ? fg : bg]; p++;
- *p = palette[( data & 0x02 ) ? fg : bg]; p++;
- *p = palette[( data & 0x01 ) ? fg : bg]; p++;
+ *p++ = palette[BIT(data, 7) ? fg : bg];
+ *p++ = palette[BIT(data, 6) ? fg : bg];
+ *p++ = palette[BIT(data, 5) ? fg : bg];
+ *p++ = palette[BIT(data, 4) ? fg : bg];
+ *p++ = palette[BIT(data, 3) ? fg : bg];
+ *p++ = palette[BIT(data, 2) ? fg : bg];
+ *p++ = palette[BIT(data, 1) ? fg : bg];
+ *p++ = palette[BIT(data, 0) ? fg : bg];
}
}
MC6845_UPDATE_ROW( isa8_aga_device::cga_gfx_4bppl_update_row )
{
- const rgb_t *palette = m_palette->palette()->entry_list_raw();
- uint8_t *videoram = m_videoram.get();
- uint32_t *p = &bitmap.pix32(y);
- int i;
+ rgb_t const *const palette = m_palette->palette()->entry_list_raw();
+ uint8_t const *const videoram = m_videoram.get();
+ uint32_t *p = &bitmap.pix(y);
- if ( y == 0 ) logerror("cga_gfx_4bppl_update_row\n");
- for ( i = 0; i < x_count; i++ ) {
- uint16_t offset = ( ( ( ma + i ) << 1 ) & 0x1fff ) | ( ( y & 1 ) << 13 );
- uint8_t data = videoram[ offset ];
+ if (y == 0) logerror("cga_gfx_4bppl_update_row\n");
+ for (int i = 0; i < x_count; i++) {
+ uint16_t const offset = (((ma + i) << 1) & 0x1fff) | ((y & 1) << 13);
+ uint8_t data = videoram[offset];
- *p = palette[data >> 4]; p++;
- *p = palette[data >> 4]; p++;
- *p = palette[data & 0x0F]; p++;
- *p = palette[data & 0x0F]; p++;
+ *p++ = palette[data >> 4];
+ *p++ = palette[data >> 4];
+ *p++ = palette[data & 0x0f];
+ *p++ = palette[data & 0x0f];
- data = videoram[ offset + 1 ];
+ data = videoram[offset + 1];
- *p = palette[data >> 4]; p++;
- *p = palette[data >> 4]; p++;
- *p = palette[data & 0x0F]; p++;
- *p = palette[data & 0x0F]; p++;
+ *p++ = palette[data >> 4];
+ *p++ = palette[data >> 4];
+ *p++ = palette[data & 0x0f];
+ *p++ = palette[data & 0x0f];
}
}
MC6845_UPDATE_ROW( isa8_aga_device::cga_gfx_4bpph_update_row )
{
- uint8_t *videoram = m_videoram.get();
- const rgb_t *palette = m_palette->palette()->entry_list_raw();
- uint32_t *p = &bitmap.pix32(y);
- int i;
-
- if ( y == 0 ) logerror("cga_gfx_4bpph_update_row\n");
- for ( i = 0; i < x_count; i++ ) {
- uint16_t offset = ( ( ( ma + i ) << 1 ) & 0x1fff ) | ( ( y & 1 ) << 13 );
- uint8_t data = videoram[ offset ];
-
- *p = palette[data >> 4]; p++;
- *p = palette[data >> 4]; p++;
- *p = palette[data >> 4]; p++;
- *p = palette[data >> 4]; p++;
- *p = palette[data & 0x0F]; p++;
- *p = palette[data & 0x0F]; p++;
- *p = palette[data & 0x0F]; p++;
- *p = palette[data & 0x0F]; p++;
-
- data = videoram[ offset + 1 ];
-
- *p = palette[data >> 4]; p++;
- *p = palette[data >> 4]; p++;
- *p = palette[data >> 4]; p++;
- *p = palette[data >> 4]; p++;
- *p = palette[data & 0x0F]; p++;
- *p = palette[data & 0x0F]; p++;
- *p = palette[data & 0x0F]; p++;
- *p = palette[data & 0x0F]; p++;
+ uint8_t const *const videoram = m_videoram.get();
+ rgb_t const *const palette = m_palette->palette()->entry_list_raw();
+ uint32_t *p = &bitmap.pix(y);
+
+ if (y == 0) logerror("cga_gfx_4bpph_update_row\n");
+ for (int i = 0; i < x_count; i++) {
+ uint16_t const offset = (((ma + i) << 1) & 0x1fff) | ((y & 1) << 13);
+ uint8_t data = videoram[offset];
+
+ *p++ = palette[data >> 4];
+ *p++ = palette[data >> 4];
+ *p++ = palette[data >> 4];
+ *p++ = palette[data >> 4];
+ *p++ = palette[data & 0x0f];
+ *p++ = palette[data & 0x0f];
+ *p++ = palette[data & 0x0f];
+ *p++ = palette[data & 0x0f];
+
+ data = videoram[offset + 1];
+
+ *p++ = palette[data >> 4];
+ *p++ = palette[data >> 4];
+ *p++ = palette[data >> 4];
+ *p++ = palette[data >> 4];
+ *p++ = palette[data & 0x0f];
+ *p++ = palette[data & 0x0f];
+ *p++ = palette[data & 0x0f];
+ *p++ = palette[data & 0x0f];
}
}
MC6845_UPDATE_ROW( isa8_aga_device::cga_gfx_2bpp_update_row )
{
- uint8_t *videoram = m_videoram.get();
- const rgb_t *palette = m_palette->palette()->entry_list_raw();
- uint32_t *p = &bitmap.pix32(y);
- int i;
+ uint8_t const *const videoram = m_videoram.get();
+ rgb_t const *const palette = m_palette->palette()->entry_list_raw();
+ uint32_t *p = &bitmap.pix(y);
-// if ( y == 0 ) logerror("cga_gfx_2bpp_update_row\n");
- for ( i = 0; i < x_count; i++ ) {
- uint16_t offset = ( ( ( ma + i ) << 1 ) & 0x1fff ) | ( ( y & 1 ) << 13 );
- uint8_t data = videoram[ offset ];
+ //if (y == 0) logerror("cga_gfx_2bpp_update_row\n");
+ for (int i = 0; i < x_count; i++) {
+ uint16_t const offset = (((ma + i) << 1) & 0x1fff) | ((y & 1) << 13);
+ uint8_t data = videoram[offset];
- *p = palette[m_cga_palette_lut_2bpp[ ( data >> 6 ) & 0x03 ]]; p++;
- *p = palette[m_cga_palette_lut_2bpp[ ( data >> 4 ) & 0x03 ]]; p++;
- *p = palette[m_cga_palette_lut_2bpp[ ( data >> 2 ) & 0x03 ]]; p++;
- *p = palette[m_cga_palette_lut_2bpp[ data & 0x03 ]]; p++;
+ *p++ = palette[m_cga_palette_lut_2bpp[(data >> 6) & 0x03]];
+ *p++ = palette[m_cga_palette_lut_2bpp[(data >> 4) & 0x03]];
+ *p++ = palette[m_cga_palette_lut_2bpp[(data >> 2) & 0x03]];
+ *p++ = palette[m_cga_palette_lut_2bpp[(data >> 0) & 0x03]];
- data = videoram[ offset+1 ];
+ data = videoram[offset + 1];
- *p = palette[m_cga_palette_lut_2bpp[ ( data >> 6 ) & 0x03 ]]; p++;
- *p = palette[m_cga_palette_lut_2bpp[ ( data >> 4 ) & 0x03 ]]; p++;
- *p = palette[m_cga_palette_lut_2bpp[ ( data >> 2 ) & 0x03 ]]; p++;
- *p = palette[m_cga_palette_lut_2bpp[ data & 0x03 ]]; p++;
+ *p++ = palette[m_cga_palette_lut_2bpp[(data >> 6) & 0x03]];
+ *p++ = palette[m_cga_palette_lut_2bpp[(data >> 4) & 0x03]];
+ *p++ = palette[m_cga_palette_lut_2bpp[(data >> 2) & 0x03]];
+ *p++ = palette[m_cga_palette_lut_2bpp[(data >> 0) & 0x03]];
}
}
MC6845_UPDATE_ROW( isa8_aga_device::cga_gfx_1bpp_update_row )
{
- uint8_t *videoram = m_videoram.get();
- const rgb_t *palette = m_palette->palette()->entry_list_raw();
- uint32_t *p = &bitmap.pix32(y);
- uint8_t fg = m_cga_color_select & 0x0F;
- int i;
-
- if ( y == 0 ) logerror("cga_gfx_1bpp_update_row\n");
- for ( i = 0; i < x_count; i++ ) {
- uint16_t offset = ( ( ( ma + i ) << 1 ) & 0x1fff ) | ( ( ra & 1 ) << 13 );
- uint8_t data = videoram[ offset ];
-
- *p = palette[( data & 0x80 ) ? fg : 0]; p++;
- *p = palette[( data & 0x40 ) ? fg : 0]; p++;
- *p = palette[( data & 0x20 ) ? fg : 0]; p++;
- *p = palette[( data & 0x10 ) ? fg : 0]; p++;
- *p = palette[( data & 0x08 ) ? fg : 0]; p++;
- *p = palette[( data & 0x04 ) ? fg : 0]; p++;
- *p = palette[( data & 0x02 ) ? fg : 0]; p++;
- *p = palette[( data & 0x01 ) ? fg : 0]; p++;
-
- data = videoram[ offset + 1 ];
-
- *p = palette[( data & 0x80 ) ? fg : 0]; p++;
- *p = palette[( data & 0x40 ) ? fg : 0]; p++;
- *p = palette[( data & 0x20 ) ? fg : 0]; p++;
- *p = palette[( data & 0x10 ) ? fg : 0]; p++;
- *p = palette[( data & 0x08 ) ? fg : 0]; p++;
- *p = palette[( data & 0x04 ) ? fg : 0]; p++;
- *p = palette[( data & 0x02 ) ? fg : 0]; p++;
- *p = palette[( data & 0x01 ) ? fg : 0]; p++;
+ uint8_t const *const videoram = m_videoram.get();
+ rgb_t const *const palette = m_palette->palette()->entry_list_raw();
+ uint32_t *p = &bitmap.pix(y);
+ uint8_t const fg = m_cga_color_select & 0x0f;
+
+ if (y == 0) logerror("cga_gfx_1bpp_update_row\n");
+ for (int i = 0; i < x_count; i++) {
+ uint16_t const offset = (((ma + i) << 1) & 0x1fff) | ((ra & 1) << 13);
+ uint8_t data = videoram[offset];
+
+ *p++ = palette[BIT(data, 7) ? fg : 0];
+ *p++ = palette[BIT(data, 6) ? fg : 0];
+ *p++ = palette[BIT(data, 5) ? fg : 0];
+ *p++ = palette[BIT(data, 4) ? fg : 0];
+ *p++ = palette[BIT(data, 3) ? fg : 0];
+ *p++ = palette[BIT(data, 2) ? fg : 0];
+ *p++ = palette[BIT(data, 1) ? fg : 0];
+ *p++ = palette[BIT(data, 0) ? fg : 0];
+
+ data = videoram[offset + 1];
+
+ *p++ = palette[BIT(data, 7) ? fg : 0];
+ *p++ = palette[BIT(data, 6) ? fg : 0];
+ *p++ = palette[BIT(data, 5) ? fg : 0];
+ *p++ = palette[BIT(data, 4) ? fg : 0];
+ *p++ = palette[BIT(data, 3) ? fg : 0];
+ *p++ = palette[BIT(data, 2) ? fg : 0];
+ *p++ = palette[BIT(data, 1) ? fg : 0];
+ *p++ = palette[BIT(data, 0) ? fg : 0];
}
}
@@ -679,13 +645,12 @@ MC6845_UPDATE_ROW( isa8_aga_device::cga_gfx_1bpp_update_row )
*
*************************************/
-READ8_MEMBER ( isa8_aga_device::pc_aga_mda_r )
+uint8_t isa8_aga_device::pc_aga_mda_r(offs_t offset)
{
- uint8_t data = 0xFF;
+ uint8_t data = 0xff;
- if ( m_mode == AGA_MONO ) {
- switch( offset )
- {
+ if (m_mode == AGA_MONO) {
+ switch (offset) {
case 0: case 2: case 4: case 6:
/* return last written mc6845 address value here? */
break;
@@ -701,42 +666,40 @@ READ8_MEMBER ( isa8_aga_device::pc_aga_mda_r )
return data;
}
-WRITE8_MEMBER ( isa8_aga_device::pc_aga_mda_w )
+void isa8_aga_device::pc_aga_mda_w(offs_t offset, uint8_t data)
{
- if ( m_mode == AGA_MONO ) {
- switch( offset )
- {
- case 0: case 2: case 4: case 6:
- m_mc6845->address_w(data);
- break;
- case 1: case 3: case 5: case 7:
- m_mc6845->register_w(data);
+ if (m_mode == AGA_MONO) {
+ switch (offset) {
+ case 0: case 2: case 4: case 6:
+ m_mc6845->address_w(data);
+ break;
+ case 1: case 3: case 5: case 7:
+ m_mc6845->register_w(data);
+ break;
+ case 8:
+ m_mda_mode_control = data;
+
+ switch (m_mda_mode_control & 0x2a) {
+ case 0x08:
+ m_update_row_type = MDA_TEXT_INTEN;
break;
- case 8:
- m_mda_mode_control = data;
-
- switch (m_mda_mode_control & 0x2a)
- {
- case 0x08:
- m_update_row_type = MDA_TEXT_INTEN;
- break;
- case 0x28:
- m_update_row_type = MDA_TEXT_BLINK;
- break;
- default:
- m_update_row_type = -1;
- }
+ case 0x28:
+ m_update_row_type = MDA_TEXT_BLINK;
break;
+ default:
+ m_update_row_type = -1;
+ }
+ break;
}
}
}
-READ8_MEMBER ( isa8_aga_device::pc_aga_cga_r )
+uint8_t isa8_aga_device::pc_aga_cga_r(offs_t offset)
{
- uint8_t data = 0xFF;
+ uint8_t data = 0xff;
- if ( m_mode == AGA_COLOR ) {
- switch( offset ) {
+ if (m_mode == AGA_COLOR) {
+ switch (offset) {
case 0: case 2: case 4: case 6:
/* return last written mc6845 address value here? */
break;
@@ -744,53 +707,42 @@ READ8_MEMBER ( isa8_aga_device::pc_aga_cga_r )
data = m_mc6845->register_r();
break;
case 10:
- data = m_vsync | ( ( data & 0x40 ) >> 4 ) | m_hsync;
+ data = m_vsync | ((data & 0x40) >> 4) | m_hsync;
break;
}
}
return data;
}
-void isa8_aga_device::set_palette_luts(void)
+void isa8_aga_device::set_palette_luts()
{
/* Setup 2bpp palette lookup table */
- if ( m_cga_mode_control & 0x10 )
- {
+ if (m_cga_mode_control & 0x10)
m_cga_palette_lut_2bpp[0] = 0;
- }
else
- {
m_cga_palette_lut_2bpp[0] = m_cga_color_select & 0x0F;
+
+ if (m_cga_mode_control & 0x04) {
+ m_cga_palette_lut_2bpp[1] = ((m_cga_color_select & 0x10) >> 1) | 3;
+ m_cga_palette_lut_2bpp[2] = ((m_cga_color_select & 0x10) >> 1) | 4;
+ m_cga_palette_lut_2bpp[3] = ((m_cga_color_select & 0x10) >> 1) | 7;
+ } else if (m_cga_color_select & 0x20) {
+ m_cga_palette_lut_2bpp[1] = ((m_cga_color_select & 0x10) >> 1) | 3;
+ m_cga_palette_lut_2bpp[2] = ((m_cga_color_select & 0x10) >> 1) | 5;
+ m_cga_palette_lut_2bpp[3] = ((m_cga_color_select & 0x10) >> 1) | 7;
+ } else {
+ m_cga_palette_lut_2bpp[1] = ((m_cga_color_select & 0x10) >> 1) | 2;
+ m_cga_palette_lut_2bpp[2] = ((m_cga_color_select & 0x10) >> 1) | 4;
+ m_cga_palette_lut_2bpp[3] = ((m_cga_color_select & 0x10) >> 1) | 6;
}
- if ( m_cga_mode_control & 0x04 )
- {
- m_cga_palette_lut_2bpp[1] = ( ( m_cga_color_select & 0x10 ) >> 1 ) | 3;
- m_cga_palette_lut_2bpp[2] = ( ( m_cga_color_select & 0x10 ) >> 1 ) | 4;
- m_cga_palette_lut_2bpp[3] = ( ( m_cga_color_select & 0x10 ) >> 1 ) | 7;
- }
- else
- {
- if ( m_cga_color_select & 0x20 )
- {
- m_cga_palette_lut_2bpp[1] = ( ( m_cga_color_select & 0x10 ) >> 1 ) | 3;
- m_cga_palette_lut_2bpp[2] = ( ( m_cga_color_select & 0x10 ) >> 1 ) | 5;
- m_cga_palette_lut_2bpp[3] = ( ( m_cga_color_select & 0x10 ) >> 1 ) | 7;
- }
- else
- {
- m_cga_palette_lut_2bpp[1] = ( ( m_cga_color_select & 0x10 ) >> 1 ) | 2;
- m_cga_palette_lut_2bpp[2] = ( ( m_cga_color_select & 0x10 ) >> 1 ) | 4;
- m_cga_palette_lut_2bpp[3] = ( ( m_cga_color_select & 0x10 ) >> 1 ) | 6;
- }
- }
- //logerror("2bpp lut set to %d,%d,%d,%d\n", cga.palette_lut_2bpp[0], cga.palette_lut_2bpp[1], cga.palette_lut_2bpp[2], cga.palette_lut_2bpp[3]);
+ LOG("2bpp lut set to %d,%d,%d,%d\n", m_cga_palette_lut_2bpp[0], m_cga_palette_lut_2bpp[1], m_cga_palette_lut_2bpp[2], m_cga_palette_lut_2bpp[3]);
}
-WRITE8_MEMBER (isa8_aga_device:: pc_aga_cga_w )
+void isa8_aga_device::pc_aga_cga_w(offs_t offset, uint8_t data)
{
- if ( m_mode == AGA_COLOR ) {
- switch(offset) {
+ if (m_mode == AGA_COLOR) {
+ switch (offset) {
case 0: case 2: case 4: case 6:
m_mc6845->address_w(data);
break;
@@ -800,46 +752,44 @@ WRITE8_MEMBER (isa8_aga_device:: pc_aga_cga_w )
case 8:
m_cga_mode_control = data;
- //logerror("mode set to %02X\n", m_cga_mode_control & 0x3F );
- switch ( m_cga_mode_control & 0x3F ) {
- case 0x08: case 0x09: case 0x0C: case 0x0D:
- m_mc6845->set_hpixels_per_column( 8 );
+ LOG("mode set to %02X\n", m_cga_mode_control & 0x3f);
+ switch (m_cga_mode_control & 0x3f) {
+ case 0x08: case 0x09: case 0x0c: case 0x0d:
+ m_mc6845->set_hpixels_per_column(8);
m_update_row_type = CGA_TEXT_INTEN;
break;
- case 0x0A: case 0x0B: case 0x2A: case 0x2B:
- m_mc6845->set_hpixels_per_column( 8 );
- if ( CGA_MONITOR == CGA_MONITOR_COMPOSITE ) {
+ case 0x0a: case 0x0b: case 0x2a: case 0x2b:
+ m_mc6845->set_hpixels_per_column(8);
+ if (CGA_MONITOR == CGA_MONITOR_COMPOSITE)
m_update_row_type = CGA_GFX_4BPPL;
- } else {
+ else
m_update_row_type = CGA_GFX_2BPP;
- }
- break;
- case 0x0E: case 0x0F: case 0x2E: case 0x2F:
- m_mc6845->set_hpixels_per_column( 8 );
+ break;
+ case 0x0e: case 0x0f: case 0x2e: case 0x2f:
+ m_mc6845->set_hpixels_per_column(8);
m_update_row_type = CGA_GFX_2BPP;
break;
- case 0x18: case 0x19: case 0x1C: case 0x1D:
- m_mc6845->set_hpixels_per_column( 8 );
+ case 0x18: case 0x19: case 0x1c: case 0x1d:
+ m_mc6845->set_hpixels_per_column(8);
m_update_row_type = CGA_TEXT_INTEN_ALT;
break;
- case 0x1A: case 0x1B: case 0x3A: case 0x3B:
- m_mc6845->set_hpixels_per_column( 8 );
- if ( CGA_MONITOR == CGA_MONITOR_COMPOSITE ) {
+ case 0x1a: case 0x1b: case 0x3a: case 0x3b:
+ m_mc6845->set_hpixels_per_column(8);
+ if (CGA_MONITOR == CGA_MONITOR_COMPOSITE)
m_update_row_type = CGA_GFX_4BPPH;
- } else {
+ else
m_update_row_type = CGA_GFX_1BPP;
- }
- break;
- case 0x1E: case 0x1F: case 0x3E: case 0x3F:
- m_mc6845->set_hpixels_per_column( 16 );
+ break;
+ case 0x1e: case 0x1f: case 0x3e: case 0x3f:
+ m_mc6845->set_hpixels_per_column(16);
m_update_row_type = CGA_GFX_1BPP;
break;
- case 0x28: case 0x29: case 0x2C: case 0x2D:
- m_mc6845->set_hpixels_per_column( 8 );
+ case 0x28: case 0x29: case 0x2c: case 0x2d:
+ m_mc6845->set_hpixels_per_column(8);
m_update_row_type = CGA_TEXT_BLINK;
break;
- case 0x38: case 0x39: case 0x3C: case 0x3D:
- m_mc6845->set_hpixels_per_column( 8 );
+ case 0x38: case 0x39: case 0x3c: case 0x3d:
+ m_mc6845->set_hpixels_per_column(8);
m_update_row_type = CGA_TEXT_BLINK_ALT;
break;
default:
@@ -859,16 +809,16 @@ WRITE8_MEMBER (isa8_aga_device:: pc_aga_cga_w )
/*************************************/
-void isa8_aga_device::pc_aga_set_mode( AGA_MODE mode)
+void isa8_aga_device::pc_aga_set_mode(mode_t mode)
{
m_mode = mode;
switch (m_mode) {
case AGA_COLOR:
- m_mc6845->set_unscaled_clock( XTAL(14'318'181)/8 );
+ m_mc6845->set_unscaled_clock(XTAL(14'318'181) / 8);
break;
case AGA_MONO:
- m_mc6845->set_unscaled_clock( 16257000/9 );
+ m_mc6845->set_unscaled_clock(16257000 / 9);
break;
case AGA_OFF:
break;
@@ -876,65 +826,68 @@ void isa8_aga_device::pc_aga_set_mode( AGA_MODE mode)
}
-WRITE8_MEMBER ( isa8_aga_device::pc_aga_videoram_w )
+void isa8_aga_device::pc_aga_videoram_w(offs_t offset, uint8_t data)
{
switch (m_mode) {
case AGA_COLOR:
- if (offset>=0x8000)
- m_videoram[offset-0x8000]=data;
+ if (offset >= 0x8000)
+ m_videoram[offset - 0x8000] = data;
break;
case AGA_MONO:
- m_videoram[offset]=data;
+ m_videoram[offset] = data;
+ break;
+ case AGA_OFF:
break;
- case AGA_OFF: break;
}
}
-READ8_MEMBER( isa8_aga_device::pc_aga_videoram_r )
+uint8_t isa8_aga_device::pc_aga_videoram_r(offs_t offset)
{
switch (m_mode) {
case AGA_COLOR:
- if (offset>=0x8000) return m_videoram[offset-0x8000];
+ if (offset >= 0x8000)
+ return m_videoram[offset - 0x8000];
return 0;
case AGA_MONO:
return m_videoram[offset];
- case AGA_OFF: break;
+ case AGA_OFF:
+ break;
}
return 0;
}
-READ8_MEMBER( isa8_aga_pc200_device::pc200_videoram_r )
+uint8_t isa8_aga_pc200_device::pc200_videoram_r(offs_t offset)
{
switch (m_mode)
{
- default:
- if (offset>=0x8000) return m_videoram[offset-0x8000];
- return 0;
- case AGA_MONO:
- return m_videoram[offset];
+ default:
+ if (offset >= 0x8000)
+ return m_videoram[offset - 0x8000];
+ return 0;
+ case AGA_MONO:
+ return m_videoram[offset];
}
}
-WRITE8_MEMBER ( isa8_aga_pc200_device::pc200_videoram_w )
+void isa8_aga_pc200_device::pc200_videoram_w(offs_t offset, uint8_t data)
{
- switch (m_mode)
- {
- default:
- if (offset>=0x8000)
- m_videoram[offset-0x8000]=data;
- break;
- case AGA_MONO:
- m_videoram[offset]=data;
- break;
+ switch (m_mode) {
+ default:
+ if (offset >= 0x8000)
+ m_videoram[offset - 0x8000] = data;
+ break;
+ case AGA_MONO:
+ m_videoram[offset] = data;
+ break;
}
}
// in reality it is of course only 1 graphics adapter,
// but now cga and mda are splitted in mess
-WRITE8_MEMBER( isa8_aga_pc200_device::pc200_cga_w )
+void isa8_aga_pc200_device::pc200_cga_w(offs_t offset, uint8_t data)
{
- pc_aga_cga_w(space, offset,data,mem_mask);
- switch(offset) {
+ pc_aga_cga_w(offset,data);
+ switch (offset) {
case 4:
m_portd |= 0x20;
break;
@@ -947,13 +900,12 @@ WRITE8_MEMBER( isa8_aga_pc200_device::pc200_cga_w )
if (data & 0x80)
m_portd |= 0x40;
-/* The bottom 3 bits of this port are:
- * Bit 2: Disable AGA
- * Bit 1: Select MDA
- * Bit 0: Select external display (monitor) rather than internal display
- * (TV for PC200; LCD for PPC512) */
- if ((m_porte & 7) != (data & 7))
- {
+ /* The bottom 3 bits of this port are:
+ * Bit 2: Disable AGA
+ * Bit 1: Select MDA
+ * Bit 0: Select external display (monitor) rather than internal display
+ * (TV for PC200; LCD for PPC512) */
+ if ((m_porte & 7) != (data & 7)) {
if (data & 4)
pc_aga_set_mode(AGA_OFF);
else if (data & 2)
@@ -969,19 +921,19 @@ WRITE8_MEMBER( isa8_aga_pc200_device::pc200_cga_w )
}
}
-READ8_MEMBER ( isa8_aga_pc200_device::pc200_cga_r )
+uint8_t isa8_aga_pc200_device::pc200_cga_r(offs_t offset)
{
uint8_t result;
- switch(offset) {
+ switch (offset) {
case 8:
result = m_port8;
break;
case 0xd:
// after writing 0x80 to 0x3de, bits 7..5 of 0x3dd from the 2nd read must be 0
- result=m_portd;
- m_portd&=0x1f;
+ result = m_portd;
+ m_portd &= 0x1f;
break;
case 0xe:
@@ -991,7 +943,7 @@ READ8_MEMBER ( isa8_aga_pc200_device::pc200_cga_r )
break;
default:
- result = pc_aga_cga_r(space, offset, mem_mask);
+ result = pc_aga_cga_r(offset);
break;
}
return result;
diff --git a/src/devices/bus/isa/aga.h b/src/devices/bus/isa/aga.h
index 990bd5d3182..3e290ff3c82 100644
--- a/src/devices/bus/isa/aga.h
+++ b/src/devices/bus/isa/aga.h
@@ -14,9 +14,9 @@
// 256 8x8 thick chars
// 256 8x8 thin chars
// 256 9x14 in 8x16 chars, line 3 is connected to a10
- ROM_LOAD("aga.chr", 0x00000, 0x02000, CRC(aca81498))
+ ROM_LOAD("aga.chr", 0x0000, 0x2000, CRC(aca81498) SHA1(0d84c89487ee7a6ac4c9e73fdb30c5fd8aa595f8) )
// hercules font of above
- ROM_LOAD("hercules.chr", 0x00000, 0x1000, CRC(7e8c9d76))
+ ROM_LOAD("hercules.chr", 0x0000, 0x1000, CRC(7e8c9d76))
*/
#ifndef MAME_BUS_ISA_AGA_H
@@ -27,27 +27,30 @@
#include "video/mc6845.h"
#include "emupal.h"
-enum AGA_MODE { AGA_OFF, AGA_COLOR, AGA_MONO };
-
-// ======================> isa8_aga_device
class isa8_aga_device :
public device_t,
public device_isa8_card_interface
{
public:
+ enum mode_t { AGA_OFF, AGA_COLOR, AGA_MONO };
+
// construction/destruction
isa8_aga_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
- DECLARE_READ8_MEMBER( pc_aga_mda_r );
- DECLARE_WRITE8_MEMBER( pc_aga_mda_w );
- DECLARE_READ8_MEMBER( pc_aga_cga_r );
- DECLARE_WRITE8_MEMBER( pc_aga_cga_w );
- void set_palette_luts(void);
- void pc_aga_set_mode(AGA_MODE mode);
- DECLARE_WRITE8_MEMBER( pc_aga_videoram_w );
- DECLARE_READ8_MEMBER( pc_aga_videoram_r );
+protected:
+ isa8_aga_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock);
+
+ uint8_t pc_aga_mda_r(offs_t offset);
+ void pc_aga_mda_w(offs_t offset, uint8_t data);
+ uint8_t pc_aga_cga_r(offs_t offset);
+ void pc_aga_cga_w(offs_t offset, uint8_t data);
+ void set_palette_luts();
+ void pc_aga_set_mode(mode_t mode);
+ void pc_aga_videoram_w(offs_t offset, uint8_t data);
+ uint8_t pc_aga_videoram_r(offs_t offset);
+ MC6845_UPDATE_ROW( aga_update_row );
MC6845_UPDATE_ROW( mda_text_inten_update_row );
MC6845_UPDATE_ROW( mda_text_blink_update_row );
MC6845_UPDATE_ROW( cga_text_inten_update_row );
@@ -59,24 +62,24 @@ public:
MC6845_UPDATE_ROW( cga_gfx_2bpp_update_row );
MC6845_UPDATE_ROW( cga_gfx_1bpp_update_row );
+ void hsync_changed(int state);
+ void vsync_changed(int state);
+
required_device<palette_device> m_palette;
required_device<mc6845_device> m_mc6845;
-protected:
- isa8_aga_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_start() override ATTR_COLD;
// 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 void device_add_mconfig(machine_config &config) override ATTR_COLD;
+ virtual const tiny_rom_entry *device_rom_region() const override ATTR_COLD;
+ virtual ioport_constructor device_input_ports() const override ATTR_COLD;
required_ioport m_cga_config;
- int m_update_row_type;
- AGA_MODE m_mode;
+ int m_update_row_type;
+ mode_t m_mode;
uint8_t m_mda_mode_control;
uint8_t m_mda_status;
uint8_t *m_mda_chr_gen;
@@ -86,7 +89,7 @@ protected:
uint8_t m_cga_status;
uint8_t *m_cga_chr_gen;
- int m_framecnt;
+ int m_framecnt;
uint8_t m_vsync;
uint8_t m_hsync;
@@ -94,17 +97,8 @@ protected:
uint8_t m_cga_palette_lut_2bpp[4];
std::unique_ptr<uint8_t[]> m_videoram;
-
-private:
- MC6845_UPDATE_ROW( aga_update_row );
- DECLARE_WRITE_LINE_MEMBER( hsync_changed );
- DECLARE_WRITE_LINE_MEMBER( vsync_changed );
};
-// device type definition
-DECLARE_DEVICE_TYPE(ISA8_AGA, isa8_aga_device)
-
-// ======================> isa8_aga_pc200_device
class isa8_aga_pc200_device :
public isa8_aga_device
@@ -112,24 +106,24 @@ class isa8_aga_pc200_device :
public:
// construction/destruction
isa8_aga_pc200_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;
-
- DECLARE_READ8_MEMBER( pc200_videoram_r );
- DECLARE_WRITE8_MEMBER( pc200_videoram_w );
- DECLARE_WRITE8_MEMBER( pc200_cga_w );
- DECLARE_READ8_MEMBER( pc200_cga_r );
protected:
+ uint8_t pc200_videoram_r(offs_t offset);
+ void pc200_videoram_w(offs_t offset, uint8_t data);
+ void pc200_cga_w(offs_t offset, uint8_t data);
+ uint8_t pc200_cga_r(offs_t offset);
+
// device-level overrides
- virtual void device_start() override;
+ virtual const tiny_rom_entry *device_rom_region() const override ATTR_COLD;
+ virtual void device_start() override ATTR_COLD;
uint8_t m_port8;
uint8_t m_portd;
uint8_t m_porte;
};
-// device type definition
+
+DECLARE_DEVICE_TYPE(ISA8_AGA, isa8_aga_device)
DECLARE_DEVICE_TYPE(ISA8_AGA_PC200, isa8_aga_pc200_device)
#endif // MAME_BUS_ISA_AGA_H
diff --git a/src/devices/bus/isa/aha1542b.cpp b/src/devices/bus/isa/aha1542b.cpp
index f1b26839fd1..ec0591163c6 100644
--- a/src/devices/bus/isa/aha1542b.cpp
+++ b/src/devices/bus/isa/aha1542b.cpp
@@ -14,6 +14,7 @@
#include "bus/nscsi/devices.h"
#include "cpu/i8085/i8085.h"
+#include "machine/aic580.h"
#include "machine/gen_latch.h"
#include "machine/nscsi_bus.h"
@@ -29,10 +30,6 @@ aha154x_device::aha154x_device(const machine_config &mconfig, device_type type,
, m_scsic(*this, "scsi:7:scsic")
, m_fdc(*this, "fdc")
, m_bios(*this, "bios")
- , m_fifo_data(*this, "fifo_data")
- , m_fifo_read_index(0)
- , m_fifo_write_index(0)
- , m_dma_mode(0)
{
}
@@ -49,85 +46,17 @@ aha1542b_device::aha1542b_device(const machine_config &mconfig, const char *tag,
void aha154x_device::device_start()
{
- save_item(NAME(m_fifo_read_index));
- save_item(NAME(m_fifo_write_index));
- save_item(NAME(m_dma_mode));
}
void aha154x_device::device_reset()
{
- m_fifo_read_index = 0;
- m_fifo_write_index = 0;
- m_dma_mode = 0;
-}
-
-void aha154x_device::transfer_speed_w(u8 data)
-{
- const unsigned div = BIT(data, 3) ? (data & 3) + 5 : 4;
- logerror("Transfer speed = %.2f MB/s\n", 20.0 * 2 / div);
-}
-
-void aha154x_device::dma_mode_w(u8 data)
-{
- m_dma_mode = data;
-}
-
-void aha154x_device::bus_on_time_w(u8 data)
-{
- logerror("Bus on time = %d microseconds\n", data & 0x0f);
-}
-
-void aha154x_device::bus_off_time_w(u8 data)
-{
- logerror("Bus off time = %d microseconds\n", std::max(1, (data & 0x0f) * 4));
-}
-
-u8 aha154x_device::fifo_data_r()
-{
- const u8 data = m_fifo_data[m_fifo_read_index];
- if (!machine().side_effects_disabled())
- m_fifo_read_index = (m_fifo_read_index + 1) % 10;
- return data;
-}
-
-void aha154x_device::fifo_data_w(u8 data)
-{
- m_fifo_data[m_fifo_write_index] = data;
- if (!machine().side_effects_disabled())
- m_fifo_write_index = (m_fifo_write_index + 1) % 10;
-}
-
-WRITE_LINE_MEMBER(aha154x_device::aic_breq_w)
-{
- if (state)
- {
- if (m_dma_mode == 0x80)
- {
- m_fifo_data[m_fifo_write_index] = m_scsic->dma_r();
- m_fifo_write_index = (m_fifo_write_index + 1) % 10;
- m_scsic->back_w(0);
- }
- else if (m_dma_mode == 0x90)
- {
- m_scsic->dma_w(m_fifo_data[m_fifo_read_index]);
- m_fifo_read_index = (m_fifo_read_index + 1) % 10;
- m_scsic->back_w(0);
- }
- else
- logerror("AIC-6250 BREQ (DMA mode %02X)\n", m_dma_mode);
- }
}
void aha154x_device::i8085_base_map(address_map &map)
{
map(0x0000, 0x3fff).rom().region("mcode", 0);
map(0x8000, 0x800f).m(m_scsic, FUNC(aic6250_device::map));
- map(0xc080, 0xc080).w(FUNC(aha154x_device::transfer_speed_w));
- map(0xc082, 0xc082).w(FUNC(aha154x_device::dma_mode_w));
- map(0xc08c, 0xc08c).w(FUNC(aha154x_device::bus_on_time_w));
- map(0xc08d, 0xc08d).w(FUNC(aha154x_device::bus_off_time_w));
- map(0xc0ac, 0xc0ac).rw(FUNC(aha154x_device::fifo_data_r), FUNC(aha154x_device::fifo_data_w));
- map(0xc0c0, 0xc0c9).ram().share("fifo_data");
+ map(0xc000, 0xc0ff).m("dmaaic", FUNC(aic580_device::mpu_map));
map(0xe000, 0xe7ff).ram();
}
@@ -150,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;
}
@@ -185,8 +114,8 @@ static INPUT_PORTS_START(aha1542a)
PORT_DIPNAME(0x02, 0x02, "Diagnostic Test Loop") PORT_DIPLOCATION("J1:2")
PORT_DIPSETTING(0x02, DEF_STR(Off))
PORT_DIPSETTING(0x00, DEF_STR(On))
- PORT_BIT(0x04, IP_ACTIVE_HIGH, IPT_CUSTOM) PORT_READ_LINE_DEVICE_MEMBER("tohost", generic_latch_8_device, pending_r)
- PORT_BIT(0x08, IP_ACTIVE_HIGH, IPT_CUSTOM) PORT_READ_LINE_DEVICE_MEMBER(DEVICE_SELF, aha1542a_device, host_int_r)
+ PORT_BIT(0x04, IP_ACTIVE_HIGH, IPT_CUSTOM) PORT_READ_LINE_DEVICE_MEMBER("tohost", FUNC(generic_latch_8_device::pending_r))
+ PORT_BIT(0x08, IP_ACTIVE_HIGH, IPT_CUSTOM) PORT_READ_LINE_DEVICE_MEMBER(DEVICE_SELF, FUNC(aha1542a_device::host_int_r))
PORT_DIPNAME(0x10, 0x10, "SCSI Parity Checking") PORT_DIPLOCATION("J1:3")
PORT_DIPSETTING(0x00, "Disabled")
PORT_DIPSETTING(0x10, "Enabled")
@@ -195,7 +124,7 @@ static INPUT_PORTS_START(aha1542a)
PORT_DIPSETTING(0x40, "5.7 MB/s")
PORT_DIPSETTING(0x20, "6.7 MB/s")
PORT_DIPSETTING(0x00, "8.0 MB/s")
- PORT_BIT(0x80, IP_ACTIVE_HIGH, IPT_CUSTOM) PORT_READ_LINE_DEVICE_MEMBER(DEVICE_SELF, aha1542a_device, scsi_rstreq_r)
+ PORT_BIT(0x80, IP_ACTIVE_HIGH, IPT_CUSTOM) PORT_READ_LINE_DEVICE_MEMBER(DEVICE_SELF, FUNC(aha1542a_device::scsi_rstreq_r))
PORT_START("CONFIG")
PORT_DIPNAME(0x07, 0x07, "SCSI Address ID") PORT_DIPLOCATION("J1:4,5,6")
@@ -452,9 +381,9 @@ ioport_constructor aha1542b_device::device_input_ports() const
void aha154x_device::scsic_config(device_t *device)
{
- device->set_clock(20'000'000);
+ device->set_clock(20_MHz_XTAL);
downcast<aic6250_device &>(*device).int_cb().set_inputline("^^localcpu", I8085_RST65_LINE);
- downcast<aic6250_device &>(*device).breq_cb().set("^^", FUNC(aha154x_device::aic_breq_w));
+ downcast<aic6250_device &>(*device).breq_cb().set("^^dmaaic", FUNC(aic580_device::breq_w));
downcast<aic6250_device &>(*device).port_a_r_cb().set_ioport("^^SETUP");
downcast<aic6250_device &>(*device).port_b_r_cb().set_ioport("^^CONFIG");
}
@@ -471,11 +400,16 @@ void aha154x_device::scsi_add(machine_config &config)
NSCSI_CONNECTOR(config, "scsi:6", default_scsi_devices, nullptr);
NSCSI_CONNECTOR(config, "scsi:7").option_set("scsic", AIC6250)
.machine_config([this] (device_t *device) { scsic_config(device); });
+
+ aic580_device &dmaaic(AIC580(config, "dmaaic", 20_MHz_XTAL));
+ dmaaic.bdin_callback().set(m_scsic, FUNC(aic6250_device::dma_r));
+ dmaaic.bdout_callback().set(m_scsic, FUNC(aic6250_device::dma_w));
+ dmaaic.back_callback().set(m_scsic, FUNC(aic6250_device::back_w));
}
void aha1542a_device::device_add_mconfig(machine_config &config)
{
- i8085a_cpu_device &localcpu(I8085A(config, m_localcpu, 10'000'000));
+ i8085a_cpu_device &localcpu(I8085A(config, m_localcpu, 20_MHz_XTAL / 2));
localcpu.set_addrmap(AS_PROGRAM, &aha1542a_device::i8085_map);
generic_latch_8_device &fromhost(GENERIC_LATCH_8(config, "fromhost"));
@@ -490,7 +424,7 @@ void aha1542a_device::device_add_mconfig(machine_config &config)
void aha1542b_device::device_add_mconfig(machine_config &config)
{
- i8085a_cpu_device &localcpu(I8085A(config, m_localcpu, 10'000'000));
+ i8085a_cpu_device &localcpu(I8085A(config, m_localcpu, 20_MHz_XTAL / 2));
localcpu.set_addrmap(AS_PROGRAM, &aha1542b_device::i8085_map);
AIC565(config, m_busaic);
diff --git a/src/devices/bus/isa/aha1542b.h b/src/devices/bus/isa/aha1542b.h
index f2d7fe85501..a0ff55a93fd 100644
--- a/src/devices/bus/isa/aha1542b.h
+++ b/src/devices/bus/isa/aha1542b.h
@@ -21,18 +21,10 @@ class aha154x_device : public device_t, public device_isa16_card_interface
protected:
aha154x_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;
-
- void transfer_speed_w(u8 data);
- void dma_mode_w(u8 data);
- void bus_on_time_w(u8 data);
- void bus_off_time_w(u8 data);
- u8 fifo_data_r();
- void fifo_data_w(u8 data);
- DECLARE_WRITE_LINE_MEMBER(aic_breq_w);
-
- void i8085_base_map(address_map &map);
+ virtual void device_start() override ATTR_COLD;
+ virtual void device_reset() override ATTR_COLD;
+
+ void i8085_base_map(address_map &map) ATTR_COLD;
void scsi_add(machine_config &config);
void scsic_config(device_t *device);
@@ -40,11 +32,6 @@ protected:
required_device<aic6250_device> m_scsic;
required_device<upd765_family_device> m_fdc;
required_region_ptr<u8> m_bios;
- required_shared_ptr<u8> m_fifo_data;
-
- u8 m_fifo_read_index;
- u8 m_fifo_write_index;
- u8 m_dma_mode;
};
class aha1542a_device : public aha154x_device
@@ -54,13 +41,13 @@ 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;
- 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 ATTR_COLD;
+ virtual const tiny_rom_entry *device_rom_region() const override ATTR_COLD;
+ virtual void device_add_mconfig(machine_config &config) override ATTR_COLD;
private:
void local_status_w(u8 data);
@@ -68,7 +55,7 @@ private:
void srst_clear_w(u8 data);
void scsi_rstreq_clear_w(u8 data);
- void i8085_map(address_map &map);
+ void i8085_map(address_map &map) ATTR_COLD;
};
class aha1542b_device : public aha154x_device
@@ -79,12 +66,12 @@ public:
static constexpr feature_type unemulated_features() { return feature::DISK; }
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 ioport_constructor device_input_ports() const override ATTR_COLD;
+ virtual const tiny_rom_entry *device_rom_region() const override ATTR_COLD;
+ virtual void device_add_mconfig(machine_config &config) override ATTR_COLD;
private:
- void i8085_map(address_map &map);
+ void i8085_map(address_map &map) ATTR_COLD;
required_device<aic565_device> m_busaic;
};
diff --git a/src/devices/bus/isa/aha1542c.cpp b/src/devices/bus/isa/aha1542c.cpp
index d5c35166b1f..9e11e32ced7 100644
--- a/src/devices/bus/isa/aha1542c.cpp
+++ b/src/devices/bus/isa/aha1542c.cpp
@@ -99,6 +99,13 @@ Adaptec AHA-1540CF/1542CF Installation Guide
http://download.adaptec.com/pdfs/installation_guides/aha1540cf_ig.pdf
*/
+/*
+Adaptec QFP ASICs
+— AHA-1540/42C: AIC-???? (covered by sticker)
+— AHA-1540/42CP: AIC-7970Q
+— AHA-1540/42CF: AIC-3370P, AIC-???? (covered by sticker)
+*/
+
#include "emu.h"
#include "aha1542c.h"
#include "cpu/z80/z80.h"
@@ -141,7 +148,7 @@ http://download.adaptec.com/pdfs/installation_guides/aha1540cf_ig.pdf
#define CMD_NOP 0x00 // No operation
#define CMD_MBINIT 0x01 // mailbox initialization
#define CMD_START_SCSI 0x02 // Start SCSI command
-#define CMD_BIOSCMD 0x03 // undocumented BIOS conmmand (shadow RAM etc.)
+#define CMD_BIOSCMD 0x03 // undocumented BIOS command (shadow RAM etc.)
#define CMD_INQUIRY 0x04 // Adapter inquiry
#define CMD_EMBOI 0x05 // enable Mailbox Out Interrupt
#define CMD_SELTIMEOUT 0x06 // Set SEL timeout
@@ -165,13 +172,13 @@ DEFINE_DEVICE_TYPE(AHA1542CP, aha1542cp_device, "aha1542cp", "AHA-1542CP SCSI Co
#define Z84C0010_TAG "z84c0010"
-READ8_MEMBER( aha1542c_device::aha1542_r )
+u8 aha1542c_device::aha1542_r(offs_t offset)
{
logerror("%s aha1542_r(): offset=%d\n", machine().describe_context(), offset);
return 0xff;
}
-WRITE8_MEMBER( aha1542c_device::aha1542_w )
+void aha1542c_device::aha1542_w(offs_t offset, u8 data)
{
logerror("%s aha1542_w(): offset=%d data=0x%02x\n", machine().describe_context(), offset, data);
}
@@ -225,10 +232,10 @@ void aha1542c_device::z84c0010_mem(address_map &map)
{
map(0x0000, 0x7fff).rom().region(Z84C0010_TAG, 0);
map(0x8000, 0x9fff).ram(); // 2kb RAM chip
- map(0xa000, 0xa000).portr("SWITCHES");
+ map(0xa000, 0xa000).portr(m_switches);
map(0xb000, 0xb000).w(FUNC(aha1542c_device::local_latch_w));
map(0xe000, 0xe0ff).ram(); // probably PC<->Z80 communication area
- map(0xe003, 0xe003).lr8("e003_r", []() { return 0x20; });
+ map(0xe003, 0xe003).lr8(NAME([] () { return 0x20; }));
}
u8 aha1542cp_device::eeprom_r()
@@ -248,7 +255,7 @@ void aha1542cp_device::local_mem(address_map &map)
{
map(0x0000, 0x7fff).rom().region(Z84C0010_TAG, 0);
map(0x8000, 0x9fff).ram();
- map(0xc000, 0xc000).portr("SWITCHES");
+ map(0xc000, 0xc000).portr(m_switches);
map(0xc001, 0xc001).rw(FUNC(aha1542cp_device::eeprom_r), FUNC(aha1542cp_device::eeprom_w));
map(0xe003, 0xe003).nopr();
}
@@ -274,7 +281,7 @@ static INPUT_PORTS_START( aha1542c )
PORT_DIPSETTING(0x50, "D4000h")
PORT_DIPSETTING(0x60, "D8000h")
PORT_DIPSETTING(0x70, "DC000h")
- PORT_BIT(0x80, IP_ACTIVE_HIGH, IPT_CUSTOM) PORT_READ_LINE_DEVICE_MEMBER("eeprom", eeprom_serial_93cxx_device, do_read)
+ PORT_BIT(0x80, IP_ACTIVE_HIGH, IPT_CUSTOM) PORT_READ_LINE_DEVICE_MEMBER("eeprom", FUNC(eeprom_serial_93cxx_device::do_read))
PORT_START("FDC_CONFIG")
PORT_DIPNAME(0x1, 0x1, "Floppy Disk Controller") PORT_DIPLOCATION("S1:5")
@@ -355,6 +362,7 @@ aha1542c_device::aha1542c_device(const machine_config &mconfig, device_type type
: device_t(mconfig, type, tag, owner, clock)
, device_isa16_card_interface(mconfig, *this)
, m_eeprom(*this, "eeprom")
+ , m_switches(*this, "SWITCHES")
{
}
@@ -376,9 +384,10 @@ aha1542cp_device::aha1542cp_device(const machine_config &mconfig, const char *ta
void aha1542c_device::device_start()
{
set_isa_device();
- m_isa->install_rom(this, 0xdc000, 0xdffff, "aha1542", "aha1542");
- m_isa->install_device(0x330, 0x333, read8_delegate(FUNC( aha1542cf_device::aha1542_r ), this),
- write8_delegate(FUNC( aha1542cf_device::aha1542_w ), this) );
+ m_isa->install_rom(this, 0xdc000, 0xdffff, "aha1542");
+ m_isa->install_device(0x330, 0x333,
+ read8sm_delegate(*this, FUNC(aha1542cf_device::aha1542_r)),
+ write8sm_delegate(*this, FUNC(aha1542cf_device::aha1542_w)));
}
diff --git a/src/devices/bus/isa/aha1542c.h b/src/devices/bus/isa/aha1542c.h
index 005c688c053..b3c1b556798 100644
--- a/src/devices/bus/isa/aha1542c.h
+++ b/src/devices/bus/isa/aha1542c.h
@@ -10,8 +10,8 @@
**********************************************************************/
-#ifndef MAME_BUS_AHA1542C_H
-#define MAME_BUS_AHA1542C_H
+#ifndef MAME_BUS_ISA_AHA1542C_H
+#define MAME_BUS_ISA_AHA1542C_H
#pragma once
@@ -33,8 +33,8 @@ public:
// construction/destruction
aha1542c_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock);
- DECLARE_READ8_MEMBER( aha1542_r );
- DECLARE_WRITE8_MEMBER( aha1542_w );
+ u8 aha1542_r(offs_t offset);
+ void aha1542_w(offs_t offset, u8 data);
protected:
aha1542c_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock);
@@ -42,18 +42,19 @@ protected:
void local_latch_w(u8 data);
// device-level overrides
- virtual void device_start() override;
- virtual void device_reset() override;
+ virtual void device_start() override ATTR_COLD;
+ virtual void device_reset() override ATTR_COLD;
// optional information overrides
- 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 ioport_constructor device_input_ports() const override ATTR_COLD;
+ virtual const tiny_rom_entry *device_rom_region() const override ATTR_COLD;
+ virtual void device_add_mconfig(machine_config &config) override ATTR_COLD;
required_device<eeprom_serial_93cxx_device> m_eeprom;
+ required_ioport m_switches;
private:
- void z84c0010_mem(address_map &map);
+ void z84c0010_mem(address_map &map) ATTR_COLD;
};
// ====================> aha1542cf_device
@@ -65,7 +66,7 @@ public:
aha1542cf_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock);
protected:
- virtual const tiny_rom_entry *device_rom_region() const override;
+ virtual const tiny_rom_entry *device_rom_region() const override ATTR_COLD;
};
// ====================> aha1542cp_device
@@ -77,15 +78,15 @@ public:
aha1542cp_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock);
protected:
- virtual ioport_constructor device_input_ports() const 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 ATTR_COLD;
+ virtual void device_add_mconfig(machine_config &config) override ATTR_COLD;
+ virtual const tiny_rom_entry *device_rom_region() const override ATTR_COLD;
private:
u8 eeprom_r();
void eeprom_w(u8 data);
- void local_mem(address_map &map);
+ void local_mem(address_map &map) ATTR_COLD;
};
// device type definitions
@@ -93,4 +94,4 @@ DECLARE_DEVICE_TYPE(AHA1542C, aha1542c_device)
DECLARE_DEVICE_TYPE(AHA1542CF, aha1542cf_device)
DECLARE_DEVICE_TYPE(AHA1542CP, aha1542cp_device)
-#endif // MAME_BUS_AHA1542C_H
+#endif // MAME_BUS_ISA_AHA1542C_H
diff --git a/src/devices/bus/isa/aha174x.h b/src/devices/bus/isa/aha174x.h
index 1b96d78a690..1320dd02e9c 100644
--- a/src/devices/bus/isa/aha174x.h
+++ b/src/devices/bus/isa/aha174x.h
@@ -22,9 +22,9 @@ class aha174x_device : public device_t, public device_isa16_card_interface
protected:
aha174x_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, u32 clock);
- virtual void device_start() override;
+ virtual void device_start() override ATTR_COLD;
- void hpc_map(address_map &map);
+ void hpc_map(address_map &map) ATTR_COLD;
void scsic_config(device_t *device);
required_device<hpc46003_device> m_hpc;
@@ -41,8 +41,8 @@ public:
static constexpr feature_type unemulated_features() { return feature::DISK; }
protected:
- virtual void device_add_mconfig(machine_config &config) override;
- virtual const tiny_rom_entry *device_rom_region() const override;
+ virtual void device_add_mconfig(machine_config &config) override ATTR_COLD;
+ virtual const tiny_rom_entry *device_rom_region() const override ATTR_COLD;
};
class aha1742a_device : public aha174x_device
@@ -53,8 +53,8 @@ public:
static constexpr feature_type unemulated_features() { return feature::DISK; }
protected:
- virtual void device_add_mconfig(machine_config &config) override;
- virtual const tiny_rom_entry *device_rom_region() const override;
+ virtual void device_add_mconfig(machine_config &config) override ATTR_COLD;
+ virtual const tiny_rom_entry *device_rom_region() const override ATTR_COLD;
required_device<upd765_family_device> m_fdc;
};
diff --git a/src/devices/bus/isa/asc88.cpp b/src/devices/bus/isa/asc88.cpp
index c04570725f8..d809b4e4c8e 100644
--- a/src/devices/bus/isa/asc88.cpp
+++ b/src/devices/bus/isa/asc88.cpp
@@ -50,19 +50,19 @@ void asc88_device::device_start()
void asc88_device::device_reset()
{
const offs_t baseaddr = 0xc0000 | (u32(m_baseaddr->read()) << 14);
- m_isa->install_rom(this, baseaddr, baseaddr | 0x37ff, "asc88", "bios");
- m_isa->install_bank(baseaddr | 0x3800, baseaddr | 0x3fef, "ascram", m_ram.get());
+ m_isa->install_rom(this, baseaddr, baseaddr | 0x37ff, "bios");
+ m_isa->install_bank(baseaddr | 0x3800, baseaddr | 0x3fef, m_ram.get());
m_isa->install_memory(baseaddr | 0x3ff0, baseaddr | 0x3ff7,
- read8sm_delegate(FUNC(ncr5380n_device::read), &*m_scsic),
- write8sm_delegate(FUNC(ncr5380n_device::write), &*m_scsic));
+ read8sm_delegate(*m_scsic, FUNC(ncr5380_device::read)),
+ write8sm_delegate(*m_scsic, FUNC(ncr5380_device::write)));
m_isa->install_memory(baseaddr | 0x3ff8, baseaddr | 0x3ff8,
- read8smo_delegate(FUNC(asc88_device::eeprom_r), this),
- write8smo_delegate(FUNC(asc88_device::control_w), this));
+ read8smo_delegate(*this, FUNC(asc88_device::eeprom_r)),
+ write8smo_delegate(*this, FUNC(asc88_device::control_w)));
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)
{
@@ -152,8 +152,8 @@ ioport_constructor asc88_device::device_input_ports() const
void asc88_device::scsic_config(device_t *device)
{
- downcast<ncr5380n_device &>(*device).irq_handler().set("^^", FUNC(asc88_device::irq_w));
- downcast<ncr5380n_device &>(*device).drq_handler().set("^^", FUNC(asc88_device::drq_w));
+ downcast<ncr5380_device &>(*device).irq_handler().set("^^", FUNC(asc88_device::irq_w));
+ downcast<ncr5380_device &>(*device).drq_handler().set("^^", FUNC(asc88_device::drq_w));
}
void asc88_device::device_add_mconfig(machine_config &config)
@@ -167,7 +167,7 @@ void asc88_device::device_add_mconfig(machine_config &config)
NSCSI_CONNECTOR(config, "scsi:5", default_scsi_devices, nullptr);
NSCSI_CONNECTOR(config, "scsi:6", default_scsi_devices, nullptr);
NSCSI_CONNECTOR(config, "scsi:7", default_scsi_devices, "scsic", true)
- .option_add_internal("scsic", NCR5380N)
+ .option_add_internal("scsic", NCR5380)
.machine_config([this] (device_t *device) { scsic_config(device); });
EEPROM_93C06_16BIT(config, m_eeprom); // NMC9306N
diff --git a/src/devices/bus/isa/asc88.h b/src/devices/bus/isa/asc88.h
index 101f995760c..7b1afe42033 100644
--- a/src/devices/bus/isa/asc88.h
+++ b/src/devices/bus/isa/asc88.h
@@ -14,7 +14,7 @@
#include "isa.h"
#include "machine/eepromser.h"
-#include "machine/ncr5380n.h"
+#include "machine/ncr5380.h"
class asc88_device : public device_t, public device_isa8_card_interface
{
@@ -22,25 +22,25 @@ public:
asc88_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 ioport_constructor device_input_ports() const override;
- virtual void device_add_mconfig(machine_config &config) override;
- virtual const tiny_rom_entry *device_rom_region() const override;
+ virtual void device_start() override ATTR_COLD;
+ virtual void device_reset() override ATTR_COLD;
+ virtual ioport_constructor device_input_ports() const override ATTR_COLD;
+ virtual void device_add_mconfig(machine_config &config) override ATTR_COLD;
+ virtual const tiny_rom_entry *device_rom_region() const override ATTR_COLD;
virtual u8 dack_r(int line) override;
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();
void scsic_config(device_t *device);
- required_device<ncr5380n_device> m_scsic;
+ required_device<ncr5380_device> m_scsic;
required_device<eeprom_serial_93cxx_device> m_eeprom;
required_ioport m_baseaddr;
diff --git a/src/devices/bus/isa/bblue2.cpp b/src/devices/bus/isa/bblue2.cpp
new file mode 100644
index 00000000000..58ef846a897
--- /dev/null
+++ b/src/devices/bus/isa/bblue2.cpp
@@ -0,0 +1,253 @@
+// license:BSD-3-Clause
+// copyright-holders:Barry Rodewald
+/*
+ * Microlog Baby Blue II CPU Plus
+ *
+ * ISA card used to emulate CP/M-80 on a PC or XT
+ * Includes a Z80B CPU, 2 DB25 RS-232C serial ports (8250), a Centronics parallel port, and an RTC
+ *
+ * Issues:
+ * RTC type is unknown
+ * Z80 location test and Interrupt test sometimes fail
+ * Parallel port test fails if set to LPT2
+ */
+
+#include "emu.h"
+
+#include "bblue2.h"
+#include "bus/rs232/terminal.h"
+#include "bus/rs232/null_modem.h"
+
+//**************************************************************************
+// GLOBAL VARIABLES
+//**************************************************************************
+
+DEFINE_DEVICE_TYPE(ISA8_BABYBLUE2, isa8_babyblue2_device, "isa_bblue2", "Microlog Baby Blue II CPU Plus")
+
+static void isa_com(device_slot_interface &device)
+{
+// device.option_add("microsoft_mouse", MSFT_HLE_SERIAL_MOUSE);
+// device.option_add("logitech_mouse", LOGITECH_HLE_SERIAL_MOUSE);
+// device.option_add("wheel_mouse", WHEEL_HLE_SERIAL_MOUSE);
+// device.option_add("msystems_mouse", MSYSTEMS_HLE_SERIAL_MOUSE);
+// device.option_add("rotatable_mouse", ROTATABLE_HLE_SERIAL_MOUSE);
+ device.option_add("terminal", SERIAL_TERMINAL);
+ device.option_add("null_modem", NULL_MODEM);
+// device.option_add("sun_kbd", SUN_KBD_ADAPTOR);
+}
+
+void isa8_babyblue2_device::z80_program_map(address_map &map)
+{
+ map(0x0000, 0xffff).ram().rw(FUNC(isa8_babyblue2_device::z80_ram_r),FUNC(isa8_babyblue2_device::z80_ram_w));
+}
+
+void isa8_babyblue2_device::z80_io_map(address_map &map)
+{
+ map(0x0030, 0x0037).rw(m_serial2, FUNC(ins8250_device::ins8250_r), FUNC(ins8250_device::ins8250_w));
+ // 0x40-0x47 - RTC
+ map(0x0070, 0x0077).rw(m_serial1, FUNC(ins8250_device::ins8250_r), FUNC(ins8250_device::ins8250_w));
+ // LPT mapped at reset
+}
+
+//-------------------------------------------------
+// device_add_mconfig - add device configuration
+//-------------------------------------------------
+
+void isa8_babyblue2_device::device_add_mconfig(machine_config &config)
+{
+ Z80(config, m_z80, 6_MHz_XTAL);
+ m_z80->set_addrmap(AS_PROGRAM, &isa8_babyblue2_device::z80_program_map);
+ m_z80->set_addrmap(AS_IO, &isa8_babyblue2_device::z80_io_map);
+
+ RAM(config, m_ram);
+ m_ram->set_default_size("64k");
+
+ INS8250(config, m_serial1, XTAL(1'843'200));
+ m_serial1->out_tx_callback().set("rs232_1", FUNC(rs232_port_device::write_txd));
+ m_serial1->out_dtr_callback().set("rs232_1", FUNC(rs232_port_device::write_dtr));
+ m_serial1->out_rts_callback().set("rs232_1", FUNC(rs232_port_device::write_rts));
+ m_serial1->out_int_callback().set(FUNC(isa8_babyblue2_device::port1_irq));
+ INS8250(config, m_serial2, XTAL(1'843'200));
+ m_serial2->out_tx_callback().set("rs232_2", FUNC(rs232_port_device::write_txd));
+ m_serial2->out_dtr_callback().set("rs232_2", FUNC(rs232_port_device::write_dtr));
+ m_serial2->out_rts_callback().set("rs232_2", FUNC(rs232_port_device::write_rts));
+ m_serial2->out_int_callback().set(FUNC(isa8_babyblue2_device::port2_irq));
+
+ RS232_PORT(config, m_rs232_1, isa_com, nullptr);
+ m_rs232_1->rxd_handler().set(m_serial1, FUNC(ins8250_uart_device::rx_w));
+ m_rs232_1->dcd_handler().set(m_serial1, FUNC(ins8250_uart_device::dcd_w));
+ m_rs232_1->dsr_handler().set(m_serial1, FUNC(ins8250_uart_device::dsr_w));
+ m_rs232_1->ri_handler().set(m_serial1, FUNC(ins8250_uart_device::ri_w));
+ m_rs232_1->cts_handler().set(m_serial1, FUNC(ins8250_uart_device::cts_w));
+ RS232_PORT(config, m_rs232_2, isa_com, nullptr);
+ m_rs232_2->rxd_handler().set(m_serial2, FUNC(ins8250_uart_device::rx_w));
+ m_rs232_2->dcd_handler().set(m_serial2, FUNC(ins8250_uart_device::dcd_w));
+ m_rs232_2->dsr_handler().set(m_serial2, FUNC(ins8250_uart_device::dsr_w));
+ m_rs232_2->ri_handler().set(m_serial2, FUNC(ins8250_uart_device::ri_w));
+ m_rs232_2->cts_handler().set(m_serial2, FUNC(ins8250_uart_device::cts_w));
+
+ PC_LPT(config, m_parallel);
+}
+
+
+static INPUT_PORTS_START( babyblue2 )
+ PORT_START("SW1")
+ PORT_DIPNAME( 0x0f, 0x0e, "Z80 Memory and Port location" ) PORT_DIPLOCATION( "SW1:7,6,5,4" )
+ PORT_DIPSETTING( 0x00, "Invalid?" )
+ PORT_DIPSETTING( 0x01, "RAM: 10000 I/O: 302" )
+ PORT_DIPSETTING( 0x02, "RAM: 20000 I/O: 304" )
+ PORT_DIPSETTING( 0x03, "RAM: 30000 I/O: 306" )
+ PORT_DIPSETTING( 0x04, "RAM: 40000 I/O: 308" )
+ PORT_DIPSETTING( 0x05, "RAM: 50000 I/O: 30a" )
+ PORT_DIPSETTING( 0x06, "RAM: 60000 I/O: 30c" )
+ PORT_DIPSETTING( 0x07, "RAM: 70000 I/O: 30e" )
+ PORT_DIPSETTING( 0x08, "RAM: 80000 I/O: 310" )
+ PORT_DIPSETTING( 0x09, "RAM: 90000 I/O: 312" )
+ PORT_DIPSETTING( 0x0a, "RAM: A0000 I/O: 314" )
+ PORT_DIPSETTING( 0x0b, "RAM: B0000 I/O: 316" )
+ PORT_DIPSETTING( 0x0c, "RAM: C0000 I/O: 318" )
+ PORT_DIPSETTING( 0x0d, "RAM: D0000 I/O: 31a" )
+ PORT_DIPSETTING( 0x0e, "RAM: E0000 I/O: 31c" )
+ PORT_DIPSETTING( 0x0f, "RAM: F0000 I/O: 31f" )
+ PORT_DIPUNKNOWN( 0x70, 0x00 ) PORT_DIPLOCATION( "SW1:3,2,1" )
+
+ // exact setting unknown at this stage
+ PORT_START("SW2")
+ PORT_DIPNAME( 0x07, 0x07, "Device Module Ports" ) PORT_DIPLOCATION( "SW2:3,2,1" )
+ PORT_DIPSETTING( 0x00, "0x00" )
+ PORT_DIPSETTING( 0x01, "0x01" )
+ PORT_DIPSETTING( 0x02, "0x02" )
+ PORT_DIPSETTING( 0x03, "0x03" )
+ PORT_DIPSETTING( 0x04, "0x04" )
+ PORT_DIPSETTING( 0x05, "0x05" )
+ PORT_DIPSETTING( 0x06, "0x06" )
+ PORT_DIPSETTING( 0x07, "0x07" )
+
+ // exact setting unknown at this stage
+ PORT_START("SW3")
+ PORT_DIPNAME( 0x0f, 0x0e, "RAM Module Page" ) PORT_DIPLOCATION( "SW3:7,6,5,4" )
+ PORT_DIPSETTING( 0x00, "0x00" )
+ PORT_DIPSETTING( 0x01, "0x01" )
+ PORT_DIPSETTING( 0x02, "0x02" )
+ PORT_DIPSETTING( 0x03, "0x03" )
+ PORT_DIPSETTING( 0x04, "0x04" )
+ PORT_DIPSETTING( 0x05, "0x05" )
+ PORT_DIPSETTING( 0x06, "0x06" )
+ PORT_DIPSETTING( 0x07, "0x07" )
+ PORT_DIPSETTING( 0x08, "0x08" )
+ PORT_DIPSETTING( 0x09, "0x09" )
+ PORT_DIPSETTING( 0x0a, "0x0a" )
+ PORT_DIPSETTING( 0x0b, "0x0b" )
+ PORT_DIPSETTING( 0x0c, "0x0c" )
+ PORT_DIPSETTING( 0x0d, "0x0d" )
+ PORT_DIPSETTING( 0x0e, "0x0e" )
+ PORT_DIPSETTING( 0x0f, "0x0f" )
+
+ PORT_DIPNAME(0x40, 0x40, "RAM Bank I" ) PORT_DIPLOCATION( "SW3:1" )
+ PORT_DIPSETTING( 0x00, "Enabled" )
+ PORT_DIPSETTING( 0x40, "Disabled" )
+ PORT_DIPNAME(0x20, 0x40, "RAM Bank II" ) PORT_DIPLOCATION( "SW3:2" )
+ PORT_DIPSETTING( 0x00, "Enabled" )
+ PORT_DIPSETTING( 0x20, "Disabled" )
+ PORT_DIPNAME(0x10, 0x40, "RAM Bank III" ) PORT_DIPLOCATION( "SW3:3" )
+ PORT_DIPSETTING( 0x00, "Enabled" )
+ PORT_DIPSETTING( 0x10, "Disabled" )
+
+ PORT_START("H2")
+ PORT_CONFNAME( 0x01, 0x01, "LPT port config" )
+ PORT_CONFSETTING( 0x00, "LPT1" )
+ PORT_CONFSETTING( 0x01, "LPT2" )
+INPUT_PORTS_END
+
+//-------------------------------------------------
+// isa8_adlib_device - constructor
+//-------------------------------------------------
+
+isa8_babyblue2_device::isa8_babyblue2_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
+ : device_t(mconfig, ISA8_BABYBLUE2, tag, owner, clock)
+ , device_isa8_card_interface(mconfig, *this)
+ , m_z80(*this, "z80cpu")
+ , m_serial1(*this, "serial1")
+ , m_serial2(*this, "serial2")
+ , m_rs232_1(*this, "rs232_1")
+ , m_rs232_2(*this, "rs232_2")
+ , m_parallel(*this, "parallel")
+ , m_dsw1(*this, "SW1")
+ , m_dsw2(*this, "SW2")
+ , m_dsw3(*this, "SW3")
+ , m_h2(*this, "H2")
+ , m_ram(*this, "z80ram")
+ , m_devices_installed(false)
+{
+}
+
+ioport_constructor isa8_babyblue2_device::device_input_ports() const
+{
+ return INPUT_PORTS_NAME( babyblue2 );
+}
+
+//-------------------------------------------------
+// device_start - device-specific startup
+//-------------------------------------------------
+
+void isa8_babyblue2_device::device_start()
+{
+ set_isa_device();
+}
+
+//-------------------------------------------------
+// device_reset - device-specific reset
+//-------------------------------------------------
+
+void isa8_babyblue2_device::device_reset()
+{
+ uint32_t ramloc;
+ uint16_t ioloc, lptloc, z80lptloc;
+
+ ramloc = (m_dsw1->read() & 0x0f) << 16;
+ ioloc = ((m_dsw1->read() & 0x0f) << 1) | 0x300;
+ lptloc = (m_h2->read() & 0x01) ? 0x278 : 0x378;
+ z80lptloc = (m_h2->read() & 0x01) ? 0x10 : 0x50;
+
+ // halt Z80
+ m_z80->set_input_line(INPUT_LINE_HALT, ASSERT_LINE);
+
+ if(!m_devices_installed) // will need a hard reset to put DIP switch and jumper changes into effect
+ {
+ // map Z80 LPT port based on jumper setting
+ m_z80->space(AS_IO).install_readwrite_handler(z80lptloc, z80lptloc+7, read8sm_delegate(m_parallel, FUNC(pc_lpt_device::read)), write8sm_delegate(m_parallel, FUNC(pc_lpt_device::write)));
+
+ m_isa->install_device(ioloc, ioloc+1, read8sm_delegate(*this, FUNC(isa8_babyblue2_device::z80_control_r)), write8sm_delegate(*this, FUNC(isa8_babyblue2_device::z80_control_w)));
+ m_isa->install_device(lptloc, lptloc+7, read8sm_delegate(m_parallel, FUNC(pc_lpt_device::read)), write8sm_delegate(m_parallel, FUNC(pc_lpt_device::write)));
+ m_isa->install_device(0x3f8, 0x03ff, read8sm_delegate(m_serial1, FUNC(ins8250_device::ins8250_r)), write8sm_delegate(m_serial1, FUNC(ins8250_device::ins8250_w)));
+ m_isa->install_device(0x2f8, 0x02ff, read8sm_delegate(m_serial2, FUNC(ins8250_device::ins8250_r)), write8sm_delegate(m_serial2, FUNC(ins8250_device::ins8250_w)));
+ // TODO: RTC
+ m_isa->install_memory(ramloc, ramloc+0xffff, read8sm_delegate(*this, FUNC(isa8_babyblue2_device::z80_ram_r)),write8sm_delegate(*this, FUNC(isa8_babyblue2_device::z80_ram_w)));
+ m_devices_installed = true;
+ }
+}
+
+uint8_t isa8_babyblue2_device::z80_control_r(offs_t offset)
+{
+ logerror("Z80 control line read\b");
+ return 0xff;
+}
+
+void isa8_babyblue2_device::z80_control_w(offs_t offset, uint8_t data)
+{
+ if(offset == 0)
+ {
+ m_z80->set_input_line(INPUT_LINE_HALT, (data & 0x01) ? CLEAR_LINE : ASSERT_LINE);
+ m_z80->set_input_line(INPUT_LINE_IRQ0, (data & 0x04) ? ASSERT_LINE : CLEAR_LINE);
+ m_z80->set_input_line(INPUT_LINE_NMI, (data & 0x08) ? ASSERT_LINE : CLEAR_LINE);
+ logerror("Z80 control write: %02x\n",data);
+ }
+}
+
+void isa8_babyblue2_device::lpt_irq(int state)
+{
+ if(m_h2->read() & 0x01)
+ m_isa->irq5_w(state);
+ else
+ m_isa->irq7_w(state);
+}
diff --git a/src/devices/bus/isa/bblue2.h b/src/devices/bus/isa/bblue2.h
new file mode 100644
index 00000000000..aba026a044e
--- /dev/null
+++ b/src/devices/bus/isa/bblue2.h
@@ -0,0 +1,68 @@
+// license:BSD-3-Clause
+// copyright-holders:Barry Rodewald
+/*
+ * Microlog Baby Blue II CPU Plus ISA card
+ */
+
+#ifndef MAME_BUS_ISA_BBLUE2_H
+#define MAME_BUS_ISA_BBLUE2_H
+
+#pragma once
+
+#include "machine/ins8250.h"
+#include "bus/rs232/rs232.h"
+#include "machine/pc_lpt.h"
+#include "cpu/z80/z80.h"
+#include "machine/ram.h"
+
+#include "isa.h"
+
+class isa8_babyblue2_device :
+ public device_t,
+ public device_isa8_card_interface
+{
+public:
+ // construction/destruction
+ isa8_babyblue2_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
+
+ uint8_t z80_control_r(offs_t offset);
+ void z80_control_w(offs_t offset, uint8_t data);
+ 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); }
+
+ 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 ATTR_COLD;
+ virtual void device_reset() override ATTR_COLD;
+
+ // optional information overrides
+ virtual void device_add_mconfig(machine_config &config) override ATTR_COLD;
+ virtual ioport_constructor device_input_ports() const override ATTR_COLD;
+
+
+private:
+ required_device<z80_device> m_z80;
+ required_device<ins8250_device> m_serial1;
+ required_device<ins8250_device> m_serial2;
+ required_device<rs232_port_device> m_rs232_1;
+ required_device<rs232_port_device> m_rs232_2;
+ required_device<pc_lpt_device> m_parallel;
+ required_ioport m_dsw1;
+ required_ioport m_dsw2;
+ required_ioport m_dsw3;
+ required_ioport m_h2;
+ required_device<ram_device> m_ram;
+
+ void z80_program_map(address_map &map) ATTR_COLD;
+ void z80_io_map(address_map &map) ATTR_COLD;
+
+ bool m_devices_installed;
+};
+
+// device type definition
+DECLARE_DEVICE_TYPE(ISA8_BABYBLUE2, isa8_babyblue2_device)
+
+#endif // MAME_BUS_ISA_BBLUE2_H
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/bt54x.h b/src/devices/bus/isa/bt54x.h
index dfdd0009416..191bbd17193 100644
--- a/src/devices/bus/isa/bt54x.h
+++ b/src/devices/bus/isa/bt54x.h
@@ -23,11 +23,11 @@ public:
protected:
bt54x_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, u32 clock);
- virtual void device_start() override;
+ virtual void device_start() override ATTR_COLD;
u8 local_status_r();
- void local_map(address_map &map);
+ void local_map(address_map &map) ATTR_COLD;
void asc_config(device_t *device);
void fsc_config(device_t *device);
void fsc_base(machine_config &config);
@@ -43,8 +43,8 @@ public:
bt542b_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;
+ virtual void device_add_mconfig(machine_config &config) override ATTR_COLD;
+ virtual const tiny_rom_entry *device_rom_region() const override ATTR_COLD;
};
class bt542bh_device : public bt54x_device
@@ -53,8 +53,8 @@ public:
bt542bh_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;
+ virtual void device_add_mconfig(machine_config &config) override ATTR_COLD;
+ virtual const tiny_rom_entry *device_rom_region() const override ATTR_COLD;
};
class bt545s_device : public bt54x_device
@@ -63,8 +63,8 @@ public:
bt545s_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;
+ virtual void device_add_mconfig(machine_config &config) override ATTR_COLD;
+ virtual const tiny_rom_entry *device_rom_region() const override ATTR_COLD;
};
DECLARE_DEVICE_TYPE(BT542B, bt542b_device)
diff --git a/src/devices/bus/isa/cga.cpp b/src/devices/bus/isa/cga.cpp
index 78c35957884..c431772bcb9 100644
--- a/src/devices/bus/isa/cga.cpp
+++ b/src/devices/bus/isa/cga.cpp
@@ -77,7 +77,7 @@
TODO:
-- Update more drivers in MESS and MAME and unify with src/emu/video/pc_cga.c
+- Update more drivers in MAME and unify with src/emu/video/pc_cga.c
- Separate out more cards/implementations
***************************************************************************/
@@ -273,10 +273,10 @@ void isa8_cga_device::device_add_mconfig(machine_config &config)
m_crtc->set_screen(nullptr);
m_crtc->set_show_border_area(false);
m_crtc->set_char_width(8);
- m_crtc->set_update_row_callback(FUNC(isa8_cga_device::crtc_update_row), this);
+ m_crtc->set_update_row_callback(FUNC(isa8_cga_device::crtc_update_row));
m_crtc->out_hsync_callback().set(FUNC(isa8_cga_device::hsync_changed));
m_crtc->out_vsync_callback().set(FUNC(isa8_cga_device::vsync_changed));
- m_crtc->set_reconfigure_callback(FUNC(isa8_cga_device::reconfigure), this);
+ m_crtc->set_reconfigure_callback(FUNC(isa8_cga_device::reconfigure));
}
ioport_constructor isa8_cga_device::device_input_ports() const
@@ -331,10 +331,10 @@ void isa8_cga_device::device_start()
set_isa_device();
m_vram.resize(m_vram_size);
- m_isa->install_device(0x3d0, 0x3df, read8_delegate( FUNC(isa8_cga_device::io_read), this ), write8_delegate( FUNC(isa8_cga_device::io_write), this ) );
- m_isa->install_bank(0xb8000, 0xb8000 + (std::min<size_t>)(0x8000, m_vram_size) - 1, "bank_cga", &m_vram[0]);
+ m_isa->install_device(0x3d0, 0x3df, read8sm_delegate(*this, FUNC(isa8_cga_device::io_read)), write8sm_delegate(*this, FUNC(isa8_cga_device::io_write)));
+ m_isa->install_bank(0xb8000, 0xb8000 + (std::min<size_t>)(0x8000, m_vram_size) - 1, &m_vram[0]);
if(m_vram_size == 0x4000)
- m_isa->install_bank(0xbc000, 0xbffff, "bank_cga", &m_vram[0]);
+ m_isa->install_bank(0xbc000, 0xbffff, &m_vram[0]);
/* Initialise the cga palette */
int i;
@@ -469,47 +469,43 @@ isa8_cga_superimpose_device::isa8_cga_superimpose_device(const machine_config &m
template<bool blink, bool si, bool comp, bool alt, int width>
MC6845_UPDATE_ROW( isa8_cga_device::cga_text )
{
- uint8_t *videoram = &m_vram[m_start_offset];
- uint32_t *p = &bitmap.pix32(y);
- const rgb_t *palette = m_palette->palette()->entry_list_raw();
- int i;
+ uint8_t const *const videoram = &m_vram[m_start_offset];
+ uint32_t *p = &bitmap.pix(y);
+ rgb_t const *const palette = m_palette->palette()->entry_list_raw();
- if ( y == 0 ) CGA_LOG(1,"cga_text_8",("\n"));
- for ( i = 0; i < x_count; i++ )
+ if (y == 0) CGA_LOG(1,"cga_text_8",("\n"));
+ for (int i = 0; i < x_count; i++)
{
- uint16_t offset = ( ( ma + i ) << 1 ) & 0x3fff;
- uint8_t chr = videoram[ offset ];
- uint8_t attr = videoram[ offset +1 ];
- uint8_t data = m_chr_gen[ chr * width + ra ];
+ uint16_t const offset = ((ma + i) << 1) & 0x3fff;
+ uint8_t const chr = videoram[offset];
+ uint8_t const attr = videoram[offset +1];
+ uint8_t data = m_chr_gen[chr * width + ra];
uint16_t fg, bg;
- uint8_t xi;
- if ( comp )
+ if (comp)
{
- fg = 0x10 + ( attr & 0x0F );
- bg = alt ? 0 : ( 0x10 + ( ( attr >> 4 ) & 0x07 ) );
+ fg = 0x10 + (attr & 0x0f);
+ bg = alt ? 0 : (0x10 + ((attr >> 4) & 0x07));
}
else
{
fg = attr & 0x0F;
- bg = alt ? 0 : ( ( attr >> 4 ) & ( blink ? 0x07 : 0x0f ) );
+ bg = alt ? 0 : ((attr >> 4) & (blink ? 0x07 : 0x0f));
}
- if ( ( i == cursor_x ) && ( m_framecnt & 0x08 ) )
- data = 0xFF;
- else if ( blink && ( attr & 0x80 ) && ( m_framecnt & 0x10 ) )
+ if ((i == cursor_x) && (m_framecnt & 0x08))
+ data = 0xff;
+ else if (blink && (attr & 0x80) && (m_framecnt & 0x10))
{
data = 0x00;
- bg = ( attr >> 4 ) & 0x07;
+ bg = (attr >> 4) & 0x07;
}
- for(xi=0;xi<8;xi++)
+ for (int xi = 0; xi < 8; xi++)
{
- uint8_t pen_data, dot;
-
- dot = (data & (1 << (7-xi)));
- pen_data = dot ? fg : bg;
- if(!si || (pen_data || dot))
+ uint8_t const dot = (data & (1 << (7 - xi)));
+ uint8_t const pen_data = dot ? fg : bg;
+ if (!si || (pen_data || dot))
*p = palette[pen_data];
p++;
}
@@ -521,28 +517,29 @@ MC6845_UPDATE_ROW( isa8_cga_device::cga_text )
MC6845_UPDATE_ROW( isa8_cga_device::cga_gfx_4bppl_update_row )
{
- uint8_t *videoram = &m_vram[m_start_offset];
- uint32_t *p = &bitmap.pix32(y);
- const rgb_t *palette = m_palette->palette()->entry_list_raw();
- int i;
+ uint8_t const *const videoram = &m_vram[m_start_offset];
+ uint32_t *p = &bitmap.pix(y);
+ rgb_t const *const palette = m_palette->palette()->entry_list_raw();
- if ( y == 0 ) CGA_LOG(1,"cga_gfx_4bppl_update_row",("\n"));
- for ( i = 0; i < x_count; i++ )
+ if (y == 0) CGA_LOG(1,"cga_gfx_4bppl_update_row",("\n"));
+ for (int i = 0; i < x_count; i++)
{
- uint16_t offset = ( ( ( ma + i ) << 1 ) & 0x1fff ) | ( ( y & 1 ) << 13 );
- uint8_t data = videoram[ offset ];
+ uint16_t const offset = (((ma + i) << 1) & 0x1fff) | ((y & 1) << 13);
+ uint8_t data;
- *p = palette[data >> 4]; p++;
- *p = palette[data >> 4]; p++;
- *p = palette[data & 0x0F]; p++;
- *p = palette[data & 0x0F]; p++;
+ data = videoram[offset];
- data = videoram[ offset + 1 ];
+ *p++ = palette[data >> 4];
+ *p++ = palette[data >> 4];
+ *p++ = palette[data & 0x0f];
+ *p++ = palette[data & 0x0f];
- *p = palette[data >> 4]; p++;
- *p = palette[data >> 4]; p++;
- *p = palette[data & 0x0F]; p++;
- *p = palette[data & 0x0F]; p++;
+ data = videoram[offset + 1];
+
+ *p++ = palette[data >> 4];
+ *p++ = palette[data >> 4];
+ *p++ = palette[data & 0x0f];
+ *p++ = palette[data & 0x0f];
}
}
@@ -580,37 +577,37 @@ static const uint8_t yc_lut[16][8] =
MC6845_UPDATE_ROW( isa8_cga_device::cga_gfx_4bpph_update_row )
{
- uint8_t *videoram = &m_vram[m_start_offset];
- uint32_t *p = &bitmap.pix32(y);
- const rgb_t *palette = m_palette->palette()->entry_list_raw();
- int i;
+ uint8_t const *const videoram = &m_vram[m_start_offset];
+ uint32_t *p = &bitmap.pix(y);
+ rgb_t const *const palette = m_palette->palette()->entry_list_raw();
- if ( y == 0 ) CGA_LOG(1,"cga_gfx_4bpph_update_row",("\n"));
-
- for ( i = 0; i < x_count; i++ )
+ if (y == 0) CGA_LOG(1,"cga_gfx_4bpph_update_row",("\n"));
+ for (int i = 0; i < x_count; i++)
{
- uint16_t offset = ( ( ( ma + i ) << 1 ) & 0x1fff ) | ( ( y & 1 ) << 13 );
- uint8_t data = videoram[ offset ];
-
- *p = palette[data >> 4]; p++;
- *p = palette[data >> 4]; p++;
- *p = palette[data >> 4]; p++;
- *p = palette[data >> 4]; p++;
- *p = palette[data & 0x0F]; p++;
- *p = palette[data & 0x0F]; p++;
- *p = palette[data & 0x0F]; p++;
- *p = palette[data & 0x0F]; p++;
-
- data = videoram[ offset + 1 ];
-
- *p = palette[data >> 4]; p++;
- *p = palette[data >> 4]; p++;
- *p = palette[data >> 4]; p++;
- *p = palette[data >> 4]; p++;
- *p = palette[data & 0x0F]; p++;
- *p = palette[data & 0x0F]; p++;
- *p = palette[data & 0x0F]; p++;
- *p = palette[data & 0x0F]; p++;
+ uint16_t const offset = (((ma + i) << 1) & 0x1fff) | ((y & 1) << 13);
+ uint8_t data;
+
+ data = videoram[offset];
+
+ *p++ = palette[data >> 4];
+ *p++ = palette[data >> 4];
+ *p++ = palette[data >> 4];
+ *p++ = palette[data >> 4];
+ *p++ = palette[data & 0x0f];
+ *p++ = palette[data & 0x0f];
+ *p++ = palette[data & 0x0f];
+ *p++ = palette[data & 0x0f];
+
+ data = videoram[offset + 1];
+
+ *p++ = palette[data >> 4];
+ *p++ = palette[data >> 4];
+ *p++ = palette[data >> 4];
+ *p++ = palette[data >> 4];
+ *p++ = palette[data & 0x0f];
+ *p++ = palette[data & 0x0f];
+ *p++ = palette[data & 0x0f];
+ *p++ = palette[data & 0x0f];
}
}
@@ -623,28 +620,29 @@ MC6845_UPDATE_ROW( isa8_cga_device::cga_gfx_4bpph_update_row )
MC6845_UPDATE_ROW( isa8_cga_device::cga_gfx_2bpp_update_row )
{
- uint8_t *videoram = &m_vram[m_start_offset];
- uint32_t *p = &bitmap.pix32(y);
- const rgb_t *palette = m_palette->palette()->entry_list_raw();
- int i;
+ uint8_t const *const videoram = &m_vram[m_start_offset];
+ uint32_t *p = &bitmap.pix(y);
+ rgb_t const *const palette = m_palette->palette()->entry_list_raw();
- if ( y == 0 ) CGA_LOG(1,"cga_gfx_2bpp_update_row",("\n"));
- for ( i = 0; i < x_count; i++ )
+ if (y == 0) CGA_LOG(1,"cga_gfx_2bpp_update_row",("\n"));
+ for (int i = 0; i < x_count; i++)
{
- uint16_t offset = ( ( ( ma + i ) << 1 ) & 0x1fff ) | ( ( ra & 1 ) << 13 );
- uint8_t data = videoram[ offset ];
+ uint16_t const offset = (((ma + i) << 1) & 0x1fff) | ((ra & 1) << 13);
+ uint8_t data;
- *p = palette[m_palette_lut_2bpp[ ( data >> 6 ) & 0x03 ]]; p++;
- *p = palette[m_palette_lut_2bpp[ ( data >> 4 ) & 0x03 ]]; p++;
- *p = palette[m_palette_lut_2bpp[ ( data >> 2 ) & 0x03 ]]; p++;
- *p = palette[m_palette_lut_2bpp[ data & 0x03 ]]; p++;
+ data = videoram[offset];
- data = videoram[ offset+1 ];
+ *p++ = palette[m_palette_lut_2bpp[(data >> 6) & 0x03]];
+ *p++ = palette[m_palette_lut_2bpp[(data >> 4) & 0x03]];
+ *p++ = palette[m_palette_lut_2bpp[(data >> 2) & 0x03]];
+ *p++ = palette[m_palette_lut_2bpp[ data & 0x03]];
- *p = palette[m_palette_lut_2bpp[ ( data >> 6 ) & 0x03 ]]; p++;
- *p = palette[m_palette_lut_2bpp[ ( data >> 4 ) & 0x03 ]]; p++;
- *p = palette[m_palette_lut_2bpp[ ( data >> 2 ) & 0x03 ]]; p++;
- *p = palette[m_palette_lut_2bpp[ data & 0x03 ]]; p++;
+ data = videoram[offset + 1];
+
+ *p++ = palette[m_palette_lut_2bpp[(data >> 6) & 0x03]];
+ *p++ = palette[m_palette_lut_2bpp[(data >> 4) & 0x03]];
+ *p++ = palette[m_palette_lut_2bpp[(data >> 2) & 0x03]];
+ *p++ = palette[m_palette_lut_2bpp[ data & 0x03]];
}
}
@@ -658,42 +656,43 @@ MC6845_UPDATE_ROW( isa8_cga_device::cga_gfx_2bpp_update_row )
MC6845_UPDATE_ROW( isa8_cga_device::cga_gfx_1bpp_update_row )
{
- uint8_t *videoram = &m_vram[m_start_offset];
- uint32_t *p = &bitmap.pix32(y);
- const rgb_t *palette = m_palette->palette()->entry_list_raw();
- uint8_t fg = m_color_select & 0x0F;
- int i;
+ uint8_t const *const videoram = &m_vram[m_start_offset];
+ uint32_t *p = &bitmap.pix(y);
+ rgb_t const *const palette = m_palette->palette()->entry_list_raw();
+ uint8_t const fg = m_color_select & 0x0f;
- if ( y == 0 ) CGA_LOG(1,"cga_gfx_1bpp_update_row",("\n"));
- for ( i = 0; i < x_count; i++ )
+ if (y == 0) CGA_LOG(1,"cga_gfx_1bpp_update_row",("\n"));
+ for (int i = 0; i < x_count; i++)
{
- uint16_t offset = ( ( ( ma + i ) << 1 ) & 0x1fff ) | ( ( ra & 1 ) << 13 );
- uint8_t data = videoram[ offset ];
-
- *p = palette[( data & 0x80 ) ? fg : 0]; p++;
- *p = palette[( data & 0x40 ) ? fg : 0]; p++;
- *p = palette[( data & 0x20 ) ? fg : 0]; p++;
- *p = palette[( data & 0x10 ) ? fg : 0]; p++;
- *p = palette[( data & 0x08 ) ? fg : 0]; p++;
- *p = palette[( data & 0x04 ) ? fg : 0]; p++;
- *p = palette[( data & 0x02 ) ? fg : 0]; p++;
- *p = palette[( data & 0x01 ) ? fg : 0]; p++;
-
- data = videoram[ offset + 1 ];
-
- *p = palette[( data & 0x80 ) ? fg : 0]; p++;
- *p = palette[( data & 0x40 ) ? fg : 0]; p++;
- *p = palette[( data & 0x20 ) ? fg : 0]; p++;
- *p = palette[( data & 0x10 ) ? fg : 0]; p++;
- *p = palette[( data & 0x08 ) ? fg : 0]; p++;
- *p = palette[( data & 0x04 ) ? fg : 0]; p++;
- *p = palette[( data & 0x02 ) ? fg : 0]; p++;
- *p = palette[( data & 0x01 ) ? fg : 0]; p++;
+ uint16_t const offset = (((ma + i) << 1) & 0x1fff) | ((ra & 1) << 13);
+ uint8_t data;
+
+ data = videoram[offset];
+
+ *p++ = palette[(data & 0x80) ? fg : 0];
+ *p++ = palette[(data & 0x40) ? fg : 0];
+ *p++ = palette[(data & 0x20) ? fg : 0];
+ *p++ = palette[(data & 0x10) ? fg : 0];
+ *p++ = palette[(data & 0x08) ? fg : 0];
+ *p++ = palette[(data & 0x04) ? fg : 0];
+ *p++ = palette[(data & 0x02) ? fg : 0];
+ *p++ = palette[(data & 0x01) ? fg : 0];
+
+ data = videoram[offset + 1];
+
+ *p++ = palette[(data & 0x80) ? fg : 0];
+ *p++ = palette[(data & 0x40) ? fg : 0];
+ *p++ = palette[(data & 0x20) ? fg : 0];
+ *p++ = palette[(data & 0x10) ? fg : 0];
+ *p++ = palette[(data & 0x08) ? fg : 0];
+ *p++ = palette[(data & 0x04) ? fg : 0];
+ *p++ = palette[(data & 0x02) ? fg : 0];
+ *p++ = palette[(data & 0x01) ? fg : 0];
}
}
-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)
@@ -704,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 )
{
@@ -903,7 +902,7 @@ void isa8_cga_device::plantronics_w(uint8_t data)
*************************************************************************/
-READ8_MEMBER( isa8_cga_device::io_read )
+uint8_t isa8_cga_device::io_read(offs_t offset)
{
uint8_t data = 0xff;
@@ -924,7 +923,7 @@ READ8_MEMBER( isa8_cga_device::io_read )
-WRITE8_MEMBER( isa8_cga_device::io_write )
+void isa8_cga_device::io_write(offs_t offset, uint8_t data)
{
switch(offset) {
case 0: case 2: case 4: case 6:
@@ -961,210 +960,205 @@ WRITE8_MEMBER( isa8_cga_device::io_write )
// proc = cga_pgfx_4bpp;
//
-//static inline void pgfx_plot_unit_4bpp(bitmap_ind16 &bitmap,
-// int x, int y, int offs)
-//{
-// int color, values[2];
-// int i;
-//
-// if (cga.plantronics & 0x40)
-// {
-// values[0] = videoram[offs | 0x4000];
-// values[1] = videoram[offs];
-// }
-// else
-// {
-// values[0] = videoram[offs];
-// values[1] = videoram[offs | 0x4000];
-// }
-// for (i=3; i>=0; i--)
-// {
-// color = ((values[0] & 0x3) << 1) |
-// ((values[1] & 2) >> 1) |
-// ((values[1] & 1) << 3);
-// bitmap.pix16(y, x+i) = Machine->pens[color];
-// values[0]>>=2;
-// values[1]>>=2;
-// }
-//}
-//
-//
-//
+#if 0
+static inline void pgfx_plot_unit_4bpp(bitmap_ind16 &bitmap, int x, int y, int offs)
+{
+ int values[2];
+
+ if (cga.plantronics & 0x40)
+ {
+ values[0] = videoram[offs | 0x4000];
+ values[1] = videoram[offs];
+ }
+ else
+ {
+ values[0] = videoram[offs];
+ values[1] = videoram[offs | 0x4000];
+ }
+ for (int i = 3; i >= 0; i--)
+ {
+ int const color =
+ ((values[0] & 0x3) << 1) |
+ ((values[1] & 2) >> 1) |
+ ((values[1] & 1) << 3);
+ bitmap.pix(y, x + i) = Machine->pens[color];
+ values[0] >>= 2;
+ values[1] >>= 2;
+ }
+}
+#endif
+
+
///***************************************************************************
// Draw graphics mode with 640x200 pixels (default) with 2 bits/pixel.
// Even scanlines are from CGA_base + 0x0000, odd from CGA_base + 0x2000
// Second plane at CGA_base + 0x4000 / 0x6000
-//***************************************************************************/
-//
-//static void cga_pgfx_4bpp(bitmap_ind16 &bitmap, struct mscrtc6845 *crtc)
-//{
-// int i, sx, sy, sh;
-// int offs = mscrtc6845_get_start(crtc)*2;
-// int lines = mscrtc6845_get_char_lines(crtc);
-// int height = mscrtc6845_get_char_height(crtc);
-// int columns = mscrtc6845_get_char_columns(crtc)*2;
-//
-// for (sy=0; sy<lines; sy++,offs=(offs+columns)&0x1fff)
-// {
-// for (sh=0; sh<height; sh++, offs|=0x2000)
-// {
-// // char line 0 used as a12 line in graphic mode
-// if (!(sh & 1))
-// {
-// for (i=offs, sx=0; sx<columns; sx++, i=(i+1)&0x1fff)
-// {
-// pgfx_plot_unit_4bpp(bitmap, sx*4, sy*height+sh, i);
-// }
-// }
-// else
-// {
-// for (i=offs|0x2000, sx=0; sx<columns; sx++, i=((i+1)&0x1fff)|0x2000)
-// {
-// pgfx_plot_unit_4bpp(bitmap, sx*4, sy*height+sh, i);
-// }
-// }
-// }
-// }
-//}
-//
-//
-//
-//static inline void pgfx_plot_unit_2bpp(bitmap_ind16 &bitmap,
-// int x, int y, const uint16_t *palette, int offs)
-//{
-// int i;
-// uint8_t bmap[2], values[2];
-// uint16_t *dest;
-//
-// if (cga.plantronics & 0x40)
-// {
-// values[0] = videoram[offs];
-// values[1] = videoram[offs | 0x4000];
-// }
-// else
-// {
-// values[0] = videoram[offs | 0x4000];
-// values[1] = videoram[offs];
-// }
-// bmap[0] = bmap[1] = 0;
-// for (i=3; i>=0; i--)
-// {
-// bmap[0] = bmap[0] << 1; if (values[0] & 0x80) bmap[0] |= 1;
-// bmap[0] = bmap[0] << 1; if (values[1] & 0x80) bmap[0] |= 1;
-// bmap[1] = bmap[1] << 1; if (values[0] & 0x08) bmap[1] |= 1;
-// bmap[1] = bmap[1] << 1; if (values[1] & 0x08) bmap[1] |= 1;
-// values[0] = values[0] << 1;
-// values[1] = values[1] << 1;
-// }
-//
-// dest = &bitmap.pix16(y, x);
-// *(dest++) = palette[(bmap[0] >> 6) & 0x03];
-// *(dest++) = palette[(bmap[0] >> 4) & 0x03];
-// *(dest++) = palette[(bmap[0] >> 2) & 0x03];
-// *(dest++) = palette[(bmap[0] >> 0) & 0x03];
-// *(dest++) = palette[(bmap[1] >> 6) & 0x03];
-// *(dest++) = palette[(bmap[1] >> 4) & 0x03];
-// *(dest++) = palette[(bmap[1] >> 2) & 0x03];
-// *(dest++) = palette[(bmap[1] >> 0) & 0x03];
-//}
-//
-//
-//
+//****************************************************************************
+
+#if 0
+static void cga_pgfx_4bpp(bitmap_ind16 &bitmap, struct mscrtc6845 *crtc)
+{
+ int offs = mscrtc6845_get_start(crtc) * 2;
+ int const lines = mscrtc6845_get_char_lines(crtc);
+ int const height = mscrtc6845_get_char_height(crtc);
+ int columns = mscrtc6845_get_char_columns(crtc) * 2;
+
+ for (int sy = 0; sy < lines; sy++, offs = (offs + columns) & 0x1fff)
+ {
+ for (int sh = 0; sh < height; sh++, offs |= 0x2000)
+ {
+ // char line 0 used as a12 line in graphic mode
+ if (!(sh & 1))
+ {
+ for (int i = offs, sx = 0; sx < columns; sx++, i = (i + 1) & 0x1fff)
+ {
+ pgfx_plot_unit_4bpp(bitmap, sx * 4, sy * height + sh, i);
+ }
+ }
+ else
+ {
+ for (int i = offs | 0x2000, sx = 0; sx < columns; sx++, i = ((i + 1) & 0x1fff) | 0x2000)
+ {
+ pgfx_plot_unit_4bpp(bitmap, sx * 4, sy * height + sh, i);
+ }
+ }
+ }
+ }
+}
+#endif
+
+
+#if 0
+static inline void pgfx_plot_unit_2bpp(bitmap_ind16 &bitmap, int x, int y, const uint16_t *palette, int offs)
+{
+ uint8_t values[2];
+ if (cga.plantronics & 0x40)
+ {
+ values[0] = videoram[offs];
+ values[1] = videoram[offs | 0x4000];
+ }
+ else
+ {
+ values[0] = videoram[offs | 0x4000];
+ values[1] = videoram[offs];
+ }
+ uint8_t bmap[2] = { 0, 0 };
+ for (int i = 3; i >= 0; i--)
+ {
+ bmap[0] = (bmap[0] << 1) | BIT(values[0], 7);
+ bmap[0] = (bmap[0] << 1) | BIT(values[1], 7);
+ bmap[1] = (bmap[1] << 1) | BIT(values[0], 3);
+ bmap[1] = (bmap[1] << 1) | BIT(values[1], 3);
+ values[0] <<= 1;
+ values[1] <<= 1;
+ }
+
+ uint16_t *dest = &bitmap.pix(y, x);
+ *dest++ = palette[(bmap[0] >> 6) & 0x03];
+ *dest++ = palette[(bmap[0] >> 4) & 0x03];
+ *dest++ = palette[(bmap[0] >> 2) & 0x03];
+ *dest++ = palette[(bmap[0] >> 0) & 0x03];
+ *dest++ = palette[(bmap[1] >> 6) & 0x03];
+ *dest++ = palette[(bmap[1] >> 4) & 0x03];
+ *dest++ = palette[(bmap[1] >> 2) & 0x03];
+ *dest++ = palette[(bmap[1] >> 0) & 0x03];
+}
+#endif
+
+
///***************************************************************************
// Draw graphics mode with 320x200 pixels (default) with 2 bits/pixel.
// Even scanlines are from CGA_base + 0x0000, odd from CGA_base + 0x2000
// cga fetches 2 byte per mscrtc6845 access (not modeled here)!
-//***************************************************************************/
-//
-//static void cga_pgfx_2bpp(bitmap_ind16 &bitmap, struct mscrtc6845 *crtc)
-//{
-// int i, sx, sy, sh;
-// int offs = mscrtc6845_get_start(crtc)*2;
-// int lines = mscrtc6845_get_char_lines(crtc);
-// int height = mscrtc6845_get_char_height(crtc);
-// int columns = mscrtc6845_get_char_columns(crtc)*2;
-// int colorset = cga.color_select & 0x3F;
-// const uint16_t *palette;
-//
-// /* Most chipsets use bit 2 of the mode control register to
-// * access a third palette. But not consistently. */
-// pc_cga_check_palette();
-// switch(CGA_CHIPSET)
-// {
-// /* The IBM Professional Graphics Controller behaves like
-// * the PC1512, btw. */
-// case CGA_CHIPSET_PC1512:
-// if ((colorset < 32) && (cga.mode_control & 4)) colorset += 64;
-// break;
-//
-// case CGA_CHIPSET_IBM:
-// case CGA_CHIPSET_PC200:
-// case CGA_CHIPSET_ATI:
-// case CGA_CHIPSET_PARADISE:
-// if (cga.mode_control & 4) colorset = (colorset & 0x1F) + 64;
-// break;
-// }
-//
-//
-// /* The fact that our palette is located in cga_colortable is a vestigial
-// * aspect from when we were doing that ugly trick where drawgfx() would
-// * handle graphics drawing. Truthfully, we should probably be using
-// * palette_set_color_rgb() here and not doing the palette lookup in the loop
-// */
-// palette = &cga_colortable[256*2 + 16*2] + colorset * 4;
-//
-// for (sy=0; sy<lines; sy++,offs=(offs+columns)&0x1fff) {
-//
-// for (sh=0; sh<height; sh++)
-// {
-// if (!(sh&1)) { // char line 0 used as a12 line in graphic mode
-// for (i=offs, sx=0; sx<columns; sx++, i=(i+1)&0x1fff)
-// {
-// pgfx_plot_unit_2bpp(bitmap, sx*8, sy*height+sh, palette, i);
-// }
-// }
-// else
-// {
-// for (i=offs|0x2000, sx=0; sx<columns; sx++, i=((i+1)&0x1fff)|0x2000)
-// {
-// pgfx_plot_unit_2bpp(bitmap, sx*8, sy*height+sh, palette, i);
-// }
-// }
-// }
-// }
-//}
+//****************************************************************************
+
+#if 0
+static void cga_pgfx_2bpp(bitmap_ind16 &bitmap, struct mscrtc6845 *crtc)
+{
+ int offs = mscrtc6845_get_start(crtc) * 2;
+ int const lines = mscrtc6845_get_char_lines(crtc);
+ int const height = mscrtc6845_get_char_height(crtc);
+ int const columns = mscrtc6845_get_char_columns(crtc) * 2;
+
+ /* Most chipsets use bit 2 of the mode control register to access a third palette. But not consistently. */
+ int colorset = cga.color_select & 0x3f;
+ pc_cga_check_palette();
+ switch (CGA_CHIPSET)
+ {
+ /* The IBM Professional Graphics Controller behaves like the PC1512, btw. */
+ case CGA_CHIPSET_PC1512:
+ if ((colorset < 32) && (cga.mode_control & 4)) colorset += 64;
+ break;
+
+ case CGA_CHIPSET_IBM:
+ case CGA_CHIPSET_PC200:
+ case CGA_CHIPSET_ATI:
+ case CGA_CHIPSET_PARADISE:
+ if (cga.mode_control & 4) colorset = (colorset & 0x1f) + 64;
+ break;
+ }
+
+ /* The fact that our palette is located in cga_colortable is a vestigial
+ * aspect from when we were doing that ugly trick where drawgfx() would
+ * handle graphics drawing. Truthfully, we should probably be using
+ * palette_set_color_rgb() here and not doing the palette lookup in the loop
+ */
+ uint16_t const *const palette = &cga_colortable[256*2 + 16*2] + colorset * 4;
+
+ for (int sy = 0; sy < lines; sy++, offs = (offs + columns) & 0x1fff)
+ {
+
+ for (int sh = 0; sh < height; sh++)
+ {
+ if (!(sh & 1)) // char line 0 used as a12 line in graphic mode
+ {
+ for (int i = offs, sx = 0; sx < columns; sx++, i = (i + 1) & 0x1fff)
+ {
+ pgfx_plot_unit_2bpp(bitmap, sx * 8, sy * height + sh, palette, i);
+ }
+ }
+ else
+ {
+ for (int i = offs | 0x2000, sx = 0; sx < columns; sx++, i= ((i + 1) & 0x1fff) | 0x2000)
+ {
+ pgfx_plot_unit_2bpp(bitmap, sx * 8, sy * height + sh, palette, i);
+ }
+ }
+ }
+ }
+}
+#endif
MC6845_UPDATE_ROW( isa8_cga_pc1512_device::pc1512_gfx_4bpp_update_row )
{
- uint8_t *videoram = &m_vram[m_start_offset];
- uint32_t *p = &bitmap.pix32(y);
- const rgb_t *palette = m_palette->palette()->entry_list_raw();
- uint16_t offset_base = ra << 13;
- int j;
+ uint8_t const *const videoram = &m_vram[m_start_offset];
+ uint32_t *p = &bitmap.pix(y);
+ rgb_t const *const palette = m_palette->palette()->entry_list_raw();
+ uint16_t const offset_base = ra << 13;
- if ( y == 0 ) CGA_LOG(1,"pc1512_gfx_4bpp_update_row",("\n"));
- for ( j = 0; j < x_count; j++ )
+ if (y == 0) CGA_LOG(1,"pc1512_gfx_4bpp_update_row",("\n"));
+ for (int j = 0; j < x_count; j++)
{
- uint16_t offset = offset_base | ( ( ma + j ) & 0x1FFF );
- uint16_t i = ( m_color_select & 8 ) ? videoram[ isa8_cga_pc1512_device::vram_offset[3] | offset ] << 3 : 0;
- uint16_t r = ( m_color_select & 4 ) ? videoram[ isa8_cga_pc1512_device::vram_offset[2] | offset ] << 2 : 0;
- uint16_t g = ( m_color_select & 2 ) ? videoram[ isa8_cga_pc1512_device::vram_offset[1] | offset ] << 1 : 0;
- uint16_t b = ( m_color_select & 1 ) ? videoram[ isa8_cga_pc1512_device::vram_offset[0] | offset ] : 0;
-
- *p = palette[( ( i & 0x400 ) | ( r & 0x200 ) | ( g & 0x100 ) | ( b & 0x80 ) ) >> 7]; p++;
- *p = palette[( ( i & 0x200 ) | ( r & 0x100 ) | ( g & 0x080 ) | ( b & 0x40 ) ) >> 6]; p++;
- *p = palette[( ( i & 0x100 ) | ( r & 0x080 ) | ( g & 0x040 ) | ( b & 0x20 ) ) >> 5]; p++;
- *p = palette[( ( i & 0x080 ) | ( r & 0x040 ) | ( g & 0x020 ) | ( b & 0x10 ) ) >> 4]; p++;
- *p = palette[( ( i & 0x040 ) | ( r & 0x020 ) | ( g & 0x010 ) | ( b & 0x08 ) ) >> 3]; p++;
- *p = palette[( ( i & 0x020 ) | ( r & 0x010 ) | ( g & 0x008 ) | ( b & 0x04 ) ) >> 2]; p++;
- *p = palette[( ( i & 0x010 ) | ( r & 0x008 ) | ( g & 0x004 ) | ( b & 0x02 ) ) >> 1]; p++;
- *p = palette[ ( i & 0x008 ) | ( r & 0x004 ) | ( g & 0x002 ) | ( b & 0x01 ) ]; p++;
+ uint16_t const offset = offset_base | ((ma + j) & 0x1fff);
+ uint16_t const i = (m_color_select & 8) ? videoram[isa8_cga_pc1512_device::vram_offset[3] | offset] << 3 : 0;
+ uint16_t const r = (m_color_select & 4) ? videoram[isa8_cga_pc1512_device::vram_offset[2] | offset] << 2 : 0;
+ uint16_t const g = (m_color_select & 2) ? videoram[isa8_cga_pc1512_device::vram_offset[1] | offset] << 1 : 0;
+ uint16_t const b = (m_color_select & 1) ? videoram[isa8_cga_pc1512_device::vram_offset[0] | offset] : 0;
+
+ *p++ = palette[((i & 0x400) | (r & 0x200) | (g & 0x100) | (b & 0x80) ) >> 7];
+ *p++ = palette[((i & 0x200) | (r & 0x100) | (g & 0x080) | (b & 0x40) ) >> 6];
+ *p++ = palette[((i & 0x100) | (r & 0x080) | (g & 0x040) | (b & 0x20) ) >> 5];
+ *p++ = palette[((i & 0x080) | (r & 0x040) | (g & 0x020) | (b & 0x10) ) >> 4];
+ *p++ = palette[((i & 0x040) | (r & 0x020) | (g & 0x010) | (b & 0x08) ) >> 3];
+ *p++ = palette[((i & 0x020) | (r & 0x010) | (g & 0x008) | (b & 0x04) ) >> 2];
+ *p++ = palette[((i & 0x010) | (r & 0x008) | (g & 0x004) | (b & 0x02) ) >> 1];
+ *p++ = palette[ (i & 0x008) | (r & 0x004) | (g & 0x002) | (b & 0x01) ];
}
}
-WRITE8_MEMBER( isa8_cga_pc1512_device::io_write )
+void isa8_cga_pc1512_device::io_write(offs_t offset, uint8_t data)
{
switch (offset)
{
@@ -1256,13 +1250,13 @@ WRITE8_MEMBER( isa8_cga_pc1512_device::io_write )
break;
default:
- isa8_cga_device::io_write(space, offset,data);
+ isa8_cga_device::io_write(offset, data);
break;
}
}
-READ8_MEMBER( isa8_cga_pc1512_device::io_read )
+uint8_t isa8_cga_pc1512_device::io_read(offs_t offset)
{
uint8_t data;
@@ -1277,14 +1271,14 @@ READ8_MEMBER( isa8_cga_pc1512_device::io_read )
break;
default:
- data = isa8_cga_device::io_read(space, offset);
+ data = isa8_cga_device::io_read(offset);
break;
}
return data;
}
-WRITE8_MEMBER( isa8_cga_pc1512_device::vram_w )
+void isa8_cga_pc1512_device::vram_w(offs_t offset, uint8_t data)
{
if ( ( m_mode_control & 0x12 ) == 0x12 )
{
@@ -1346,13 +1340,13 @@ void isa8_cga_pc1512_device::device_start()
{
isa8_cga_device::device_start();
- m_isa->install_device(0x3d0, 0x3df, read8_delegate( FUNC(isa8_cga_pc1512_device::io_read), this ), write8_delegate( FUNC(isa8_cga_pc1512_device::io_write), this ) );
- m_isa->install_bank(0xb8000, 0xbbfff, "bank1", &m_vram[0]);
+ m_isa->install_device(0x3d0, 0x3df, read8sm_delegate(*this, FUNC(isa8_cga_pc1512_device::io_read)), write8sm_delegate(*this, FUNC(isa8_cga_pc1512_device::io_write)));
+ m_isa->install_bank(0xb8000, 0xbbfff, &m_vram[0]);
address_space &space = m_isa->memspace();
- space.install_write_handler( 0xb8000, 0xbbfff, write8_delegate( FUNC(isa8_cga_pc1512_device::vram_w), this ) );
- space.install_write_handler( 0xbc000, 0xbffff, write8_delegate( FUNC(isa8_cga_pc1512_device::vram_w), this ) );
+ space.install_write_handler(0xb8000, 0xbbfff, write8sm_delegate(*this, FUNC(isa8_cga_pc1512_device::vram_w)));
+ space.install_write_handler(0xbc000, 0xbffff, write8sm_delegate(*this, FUNC(isa8_cga_pc1512_device::vram_w)));
}
void isa8_cga_pc1512_device::device_reset()
@@ -1373,11 +1367,7 @@ void isa8_cga_pc1512_device::device_reset()
void isa8_wyse700_device::change_resolution(uint8_t mode)
{
int width = 0, height = 0;
- if (mode & 2) {
- machine().root_device().membank("bank_wy1")->set_base(&m_vram[0x10000]);
- } else {
- machine().root_device().membank("bank_wy1")->set_base(&m_vram[0x00000]);
- }
+ m_vrambank->set_entry((mode >> 1) & 1);
if ((m_control & 0xf0) == (mode & 0xf0)) return;
switch(mode & 0xf0) {
@@ -1391,7 +1381,7 @@ void isa8_wyse700_device::change_resolution(uint8_t mode)
}
-WRITE8_MEMBER( isa8_wyse700_device::io_write )
+void isa8_wyse700_device::io_write(offs_t offset, uint8_t data)
{
switch (offset)
{
@@ -1408,13 +1398,13 @@ WRITE8_MEMBER( isa8_wyse700_device::io_write )
m_control = data;
break;
default:
- isa8_cga_device::io_write(space, offset,data);
+ isa8_cga_device::io_write(offset, data);
break;
}
}
-READ8_MEMBER( isa8_wyse700_device::io_read )
+uint8_t isa8_wyse700_device::io_read(offs_t offset)
{
uint8_t data;
@@ -1432,7 +1422,7 @@ READ8_MEMBER( isa8_wyse700_device::io_read )
data = m_control;
break;
default:
- data = isa8_cga_device::io_read(space, offset);
+ data = isa8_cga_device::io_read(offset);
break;
}
return data;
@@ -1447,7 +1437,7 @@ DEFINE_DEVICE_TYPE(ISA8_WYSE700, isa8_wyse700_device, "wyse700", "Wyse 700")
//-------------------------------------------------
isa8_wyse700_device::isa8_wyse700_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) :
- isa8_cga_device(mconfig, ISA8_WYSE700, tag, owner, clock), m_bank_offset(0), m_bank_base(0), m_control(0)
+ isa8_cga_device(mconfig, ISA8_WYSE700, tag, owner, clock), m_vrambank(*this, "wy1"), m_bank_offset(0), m_bank_base(0), m_control(0)
{
m_vram_size = 0x20000;
m_start_offset = 0x18000;
@@ -1485,9 +1475,10 @@ void isa8_wyse700_device::device_start()
{
isa8_cga_device::device_start();
- m_isa->install_device(0x3d0, 0x3df, read8_delegate( FUNC(isa8_wyse700_device::io_read), this ), write8_delegate( FUNC(isa8_wyse700_device::io_write), this ) );
- m_isa->install_bank(0xa0000, 0xaffff, "bank_wy1", &m_vram[0x00000]);
- m_isa->install_bank(0xb0000, 0xbffff, "bank_cga", &m_vram[0x10000]);
+ m_isa->install_device(0x3d0, 0x3df, read8sm_delegate(*this, FUNC(isa8_wyse700_device::io_read)), write8sm_delegate(*this, FUNC(isa8_wyse700_device::io_write)));
+ m_vrambank->configure_entries(0, 2, m_vram.data(), 0x10000);
+ m_isa->install_bank(0xa0000, 0xaffff, m_vrambank);
+ m_isa->install_bank(0xb0000, 0xbffff, &m_vram[0x10000]);
}
void isa8_wyse700_device::device_reset()
@@ -1496,35 +1487,45 @@ void isa8_wyse700_device::device_reset()
m_control = 0;
m_bank_offset = 0;
m_bank_base = 0;
+ int width = 640, height = 400;
+ rectangle visarea(0, width-1, 0, height-1);
+ m_screen->configure(width, height, visarea, HZ_TO_ATTOSECONDS(60));
}
uint32_t isa8_wyse700_device::screen_update(screen_device &screen, bitmap_rgb32 &bitmap, const rectangle &cliprect)
{
- if (m_control & 0x08) {
- const rgb_t *palette = m_palette->palette()->entry_list_raw();
- uint8_t fg = m_color_select & 0x0F;
+ if (m_control & 0x08)
+ {
+ rgb_t const *const palette = m_palette->palette()->entry_list_raw();
+ uint8_t const fg = m_color_select & 0x0F;
uint32_t addr = 0;
- for (int y = 0; y < 800; y++) {
- uint8_t *src = &m_vram[addr];
+ for (int y = 0; y < 800; y++)
+ {
+ uint8_t const *src = &m_vram[addr];
- if (y & 1) {
+ if (y & 1)
+ {
src += 0x10000;
addr += 160;
}
- for (int x = 0; x < (1280 / 8); x++) {
+ for (int x = 0; x < (1280 / 8); x++)
+ {
uint8_t val = src[x];
- for (int i = 0; i < 8; i++) {
- bitmap.pix32(y,x*8+i) = (val & 0x80) ? palette[fg] : palette[0x00];
+ for (int i = 0; i < 8; i++)
+ {
+ bitmap.pix(y, x * 8 + i) = (val & 0x80) ? palette[fg] : palette[0x00];
val <<= 1;
}
}
}
- } else {
+ return 0;
+ }
+ else
+ {
return isa8_cga_device::screen_update(screen, bitmap, cliprect);
}
- return 0;
}
@@ -1547,7 +1548,7 @@ void isa8_ec1841_0002_device::device_start()
{
isa8_cga_device::device_start();
- m_isa->install_device(0x3d0, 0x3df, read8_delegate( FUNC(isa8_ec1841_0002_device::io_read), this ), write8_delegate( FUNC(isa8_ec1841_0002_device::io_write), this ) );
+ m_isa->install_device(0x3d0, 0x3df, read8sm_delegate(*this, FUNC(isa8_ec1841_0002_device::io_read)), write8sm_delegate(*this, FUNC(isa8_ec1841_0002_device::io_write)));
}
void isa8_ec1841_0002_device::device_reset()
@@ -1556,7 +1557,7 @@ void isa8_ec1841_0002_device::device_reset()
m_p3df = 0;
}
-WRITE8_MEMBER( isa8_ec1841_0002_device::char_ram_write )
+void isa8_ec1841_0002_device::char_ram_write(offs_t offset, uint8_t data)
{
offset ^= BIT(offset, 12);
// logerror("write char ram %04x %02x\n",offset,data);
@@ -1566,13 +1567,13 @@ WRITE8_MEMBER( isa8_ec1841_0002_device::char_ram_write )
m_chr_gen_base[offset + 0x1800] = data;
}
-READ8_MEMBER( isa8_ec1841_0002_device::char_ram_read )
+uint8_t isa8_ec1841_0002_device::char_ram_read(offs_t offset)
{
offset ^= BIT(offset, 12);
return m_chr_gen_base[offset];
}
-WRITE8_MEMBER( isa8_ec1841_0002_device::io_write )
+void isa8_ec1841_0002_device::io_write(offs_t offset, uint8_t data)
{
switch (offset)
{
@@ -1580,25 +1581,25 @@ WRITE8_MEMBER( isa8_ec1841_0002_device::io_write )
m_p3df = data;
if (data & 1) {
m_isa->install_memory(0xb8000, 0xb9fff,
- read8_delegate( FUNC(isa8_ec1841_0002_device::char_ram_read), this),
- write8_delegate(FUNC(isa8_ec1841_0002_device::char_ram_write), this) );
+ read8sm_delegate( *this, FUNC(isa8_ec1841_0002_device::char_ram_read)),
+ write8sm_delegate(*this, FUNC(isa8_ec1841_0002_device::char_ram_write)));
if(m_vram_size == 0x4000)
m_isa->install_memory(0xbc000, 0xbdfff,
- read8_delegate( FUNC(isa8_ec1841_0002_device::char_ram_read), this),
- write8_delegate(FUNC(isa8_ec1841_0002_device::char_ram_write), this) );
+ read8sm_delegate( *this, FUNC(isa8_ec1841_0002_device::char_ram_read)),
+ write8sm_delegate(*this, FUNC(isa8_ec1841_0002_device::char_ram_write)));
} else {
- m_isa->install_bank(0xb8000, 0xb8000 + (std::min<size_t>)(0x8000, m_vram_size) - 1, "bank_cga", &m_vram[0]);
+ m_isa->install_bank(0xb8000, 0xb8000 + (std::min<size_t>)(0x8000, m_vram_size) - 1, &m_vram[0]);
if(m_vram_size == 0x4000)
- m_isa->install_bank(0xbc000, 0xbffff, "bank_cga", &m_vram[0]);
+ m_isa->install_bank(0xbc000, 0xbffff, &m_vram[0]);
}
break;
default:
- isa8_cga_device::io_write(space, offset, data);
+ isa8_cga_device::io_write(offset, data);
break;
}
}
-READ8_MEMBER( isa8_ec1841_0002_device::io_read )
+uint8_t isa8_ec1841_0002_device::io_read(offs_t offset)
{
uint8_t data;
@@ -1608,7 +1609,7 @@ READ8_MEMBER( isa8_ec1841_0002_device::io_read )
data = m_p3df;
break;
default:
- data = isa8_cga_device::io_read(space, offset);
+ data = isa8_cga_device::io_read(offset);
break;
}
return data;
@@ -1616,6 +1617,30 @@ READ8_MEMBER( isa8_ec1841_0002_device::io_read )
DEFINE_DEVICE_TYPE(ISA8_CGA_MC1502, isa8_cga_mc1502_device, "cga_mc1502", "MC1502 CGA")
+void isa8_cga_mc1502_device::device_add_mconfig(machine_config &config)
+{
+ screen_device &screen(SCREEN(config, CGA_SCREEN_NAME, SCREEN_TYPE_RASTER));
+ screen.set_raw(XTAL(16'000'000), 912, 0, 640, 462, 0, 400);
+ screen.set_screen_update(FUNC(isa8_cga_mc1502_device::screen_update));
+
+ PALETTE(config, m_palette).set_entries(/* CGA_PALETTE_SETS * 16*/ 65536);
+
+ MC6845(config, m_crtc, XTAL(16'000'000)/16); // soviet clone
+ m_crtc->set_screen(nullptr);
+ m_crtc->set_show_border_area(false);
+ m_crtc->set_char_width(8);
+ m_crtc->set_update_row_callback(FUNC(isa8_cga_mc1502_device::crtc_update_row));
+ m_crtc->out_hsync_callback().set(FUNC(isa8_cga_mc1502_device::hsync_changed));
+ m_crtc->out_vsync_callback().set(FUNC(isa8_cga_mc1502_device::vsync_changed));
+ m_crtc->set_reconfigure_callback(FUNC(isa8_cga_mc1502_device::reconfigure));
+}
+
+MC6845_RECONFIGURE( isa8_cga_mc1502_device::reconfigure )
+{
+ // this has a different horiz freq
+ m_screen->configure(width, height, visarea, frame_period);
+}
+
//-------------------------------------------------
// isa8_cga_mc1502_device - constructor
//-------------------------------------------------
@@ -1696,10 +1721,20 @@ DEFINE_DEVICE_TYPE(ISA8_CGA_M24, isa8_cga_m24_device, "cga_m24", "Olivetti M24 C
void isa8_cga_m24_device::device_add_mconfig(machine_config &config)
{
- isa8_cga_device::device_add_mconfig(config);
+ screen_device &screen(SCREEN(config, CGA_SCREEN_NAME, SCREEN_TYPE_RASTER));
+ screen.set_raw(XTAL(14'318'181), 912, 0, 640, 462, 0, 400);
+ screen.set_screen_update(FUNC(isa8_cga_m24_device::screen_update));
+
+ PALETTE(config, m_palette).set_entries(/* CGA_PALETTE_SETS * 16*/ 65536);
- subdevice<screen_device>(CGA_SCREEN_NAME)->set_raw(XTAL(14'318'181), 912, 0, 640, 462, 0, 400);
- m_crtc->set_reconfigure_callback(FUNC(isa8_cga_m24_device::reconfigure), this);
+ HD6845S(config, m_crtc, XTAL(14'318'181)/16);
+ m_crtc->set_screen(nullptr);
+ m_crtc->set_show_border_area(false);
+ m_crtc->set_char_width(8);
+ m_crtc->set_update_row_callback(FUNC(isa8_cga_m24_device::crtc_update_row));
+ m_crtc->out_hsync_callback().set(FUNC(isa8_cga_m24_device::hsync_changed));
+ m_crtc->out_vsync_callback().set(FUNC(isa8_cga_m24_device::vsync_changed));
+ m_crtc->set_reconfigure_callback(FUNC(isa8_cga_m24_device::reconfigure));
}
isa8_cga_m24_device::isa8_cga_m24_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) :
@@ -1741,7 +1776,7 @@ MC6845_RECONFIGURE( isa8_cga_m24_device::reconfigure )
m_screen->configure(width, height, visarea, frame_period);
}
-WRITE8_MEMBER( isa8_cga_m24_device::io_write )
+void isa8_cga_m24_device::io_write(offs_t offset, uint8_t data)
{
switch(offset)
{
@@ -1776,12 +1811,12 @@ WRITE8_MEMBER( isa8_cga_m24_device::io_write )
m_start_offset = 0;
break;
default:
- isa8_cga_device::io_write(space, offset, data);
+ isa8_cga_device::io_write(offset, data);
break;
}
}
-READ8_MEMBER( isa8_cga_m24_device::io_read )
+uint8_t isa8_cga_m24_device::io_read(offs_t offset)
{
uint8_t data = 0xff;
@@ -1794,7 +1829,7 @@ READ8_MEMBER( isa8_cga_m24_device::io_read )
data = m_mode2;
break;
default:
- data = isa8_cga_device::io_read(space, offset);
+ data = isa8_cga_device::io_read(offset);
break;
}
return data;
@@ -1803,7 +1838,7 @@ READ8_MEMBER( isa8_cga_m24_device::io_read )
MC6845_UPDATE_ROW(isa8_cga_m24_device::crtc_update_row)
{
- if(m_mode2 & 1)
+ if (m_mode2 & 1)
{
m24_gfx_1bpp_m24_update_row(bitmap, cliprect, ma, ra, y, x_count, cursor_x, de, hbp, vbp);
return;
@@ -1813,7 +1848,7 @@ MC6845_UPDATE_ROW(isa8_cga_m24_device::crtc_update_row)
return;
y = m_y;
- if(m_y >= bitmap.height())
+ if (m_y >= bitmap.height())
return;
switch (m_update_row_type)
@@ -1851,37 +1886,38 @@ MC6845_UPDATE_ROW(isa8_cga_m24_device::crtc_update_row)
MC6845_UPDATE_ROW( isa8_cga_m24_device::m24_gfx_1bpp_m24_update_row )
{
- uint8_t *videoram = &m_vram[m_start_offset];
- uint32_t *p = &bitmap.pix32(y);
- const rgb_t *palette = m_palette->palette()->entry_list_raw();
- uint8_t fg = m_color_select & 0x0F;
- int i;
+ uint8_t const *const videoram = &m_vram[m_start_offset];
+ uint32_t *p = &bitmap.pix(y);
+ rgb_t const *const palette = m_palette->palette()->entry_list_raw();
+ uint8_t const fg = m_color_select & 0x0f;
- if ( y == 0 ) CGA_LOG(1,"m24_gfx_1bpp_m24_update_row",("\n"));
- for ( i = 0; i < x_count; i++ )
+ if (y == 0) CGA_LOG(1,"m24_gfx_1bpp_m24_update_row",("\n"));
+ for (int i = 0; i < x_count; i++)
{
- uint16_t offset = ( ( ( ma + i ) << 1 ) & 0x1fff ) | ( ( ra & 3 ) << 13 );
- uint8_t data = videoram[ offset ];
-
- *p = palette[( data & 0x80 ) ? fg : 0]; p++;
- *p = palette[( data & 0x40 ) ? fg : 0]; p++;
- *p = palette[( data & 0x20 ) ? fg : 0]; p++;
- *p = palette[( data & 0x10 ) ? fg : 0]; p++;
- *p = palette[( data & 0x08 ) ? fg : 0]; p++;
- *p = palette[( data & 0x04 ) ? fg : 0]; p++;
- *p = palette[( data & 0x02 ) ? fg : 0]; p++;
- *p = palette[( data & 0x01 ) ? fg : 0]; p++;
-
- data = videoram[ offset + 1 ];
-
- *p = palette[( data & 0x80 ) ? fg : 0]; p++;
- *p = palette[( data & 0x40 ) ? fg : 0]; p++;
- *p = palette[( data & 0x20 ) ? fg : 0]; p++;
- *p = palette[( data & 0x10 ) ? fg : 0]; p++;
- *p = palette[( data & 0x08 ) ? fg : 0]; p++;
- *p = palette[( data & 0x04 ) ? fg : 0]; p++;
- *p = palette[( data & 0x02 ) ? fg : 0]; p++;
- *p = palette[( data & 0x01 ) ? fg : 0]; p++;
+ uint16_t const offset = (((ma + i) << 1 ) & 0x1fff) | ((ra & 3) << 13);
+ uint8_t data;
+
+ data = videoram[offset];
+
+ *p++ = palette[(data & 0x80) ? fg : 0];
+ *p++ = palette[(data & 0x40) ? fg : 0];
+ *p++ = palette[(data & 0x20) ? fg : 0];
+ *p++ = palette[(data & 0x10) ? fg : 0];
+ *p++ = palette[(data & 0x08) ? fg : 0];
+ *p++ = palette[(data & 0x04) ? fg : 0];
+ *p++ = palette[(data & 0x02) ? fg : 0];
+ *p++ = palette[(data & 0x01) ? fg : 0];
+
+ data = videoram[offset + 1];
+
+ *p++ = palette[(data & 0x80) ? fg : 0];
+ *p++ = palette[(data & 0x40) ? fg : 0];
+ *p++ = palette[(data & 0x20) ? fg : 0];
+ *p++ = palette[(data & 0x10) ? fg : 0];
+ *p++ = palette[(data & 0x08) ? fg : 0];
+ *p++ = palette[(data & 0x04) ? fg : 0];
+ *p++ = palette[(data & 0x02) ? fg : 0];
+ *p++ = palette[(data & 0x01) ? fg : 0];
}
}
@@ -1912,43 +1948,43 @@ const tiny_rom_entry *isa8_cga_cportiii_device::device_rom_region() const
void isa8_cga_cportiii_device::device_reset()
{
isa8_cga_m24_device::device_reset();
- m_isa->install_device(0x13c6, 0x13c7, read8_delegate(FUNC(isa8_cga_cportiii_device::port_13c6_r), this), write8_delegate(FUNC(isa8_cga_cportiii_device::port_13c6_w), this));
- m_isa->install_device(0x23c6, 0x23c7, read8_delegate(FUNC(isa8_cga_cportiii_device::port_23c6_r), this), write8_delegate(FUNC(isa8_cga_cportiii_device::port_23c6_w), this));
+ m_isa->install_device(0x13c6, 0x13c7, read8smo_delegate(*this, FUNC(isa8_cga_cportiii_device::port_13c6_r)), write8smo_delegate(*this, FUNC(isa8_cga_cportiii_device::port_13c6_w)));
+ m_isa->install_device(0x23c6, 0x23c7, read8smo_delegate(*this, FUNC(isa8_cga_cportiii_device::port_23c6_r)), write8smo_delegate(*this, FUNC(isa8_cga_cportiii_device::port_23c6_w)));
m_palette->set_pen_color(0, 100, 25, 0);
m_chr_gen_offset[0] = m_chr_gen_offset[2] = 0x0000;
m_chr_gen_offset[1] = m_chr_gen_offset[3] = 0x1000;
}
-WRITE8_MEMBER(isa8_cga_cportiii_device::char_ram_write)
+void isa8_cga_cportiii_device::char_ram_write(offs_t offset, uint8_t data)
{
m_chr_gen_base[offset] = data;
}
-READ8_MEMBER(isa8_cga_cportiii_device::char_ram_read)
+uint8_t isa8_cga_cportiii_device::char_ram_read(offs_t offset)
{
return m_chr_gen_base[offset];
}
-READ8_MEMBER(isa8_cga_cportiii_device::port_13c6_r)
+uint8_t isa8_cga_cportiii_device::port_13c6_r()
{
return 0x04;
}
-WRITE8_MEMBER(isa8_cga_cportiii_device::port_13c6_w)
+void isa8_cga_cportiii_device::port_13c6_w(uint8_t data)
{
}
-READ8_MEMBER(isa8_cga_cportiii_device::port_23c6_r)
+uint8_t isa8_cga_cportiii_device::port_23c6_r()
{
return 0;
}
-WRITE8_MEMBER(isa8_cga_cportiii_device::port_23c6_w)
+void isa8_cga_cportiii_device::port_23c6_w(uint8_t data)
{
m_mode2 = data & 1;
if(BIT(data, 3))
- m_isa->install_memory(0xb8000, 0xb9fff, read8_delegate(FUNC(isa8_cga_cportiii_device::char_ram_read), this), write8_delegate(FUNC(isa8_cga_cportiii_device::char_ram_write), this));
+ m_isa->install_memory(0xb8000, 0xb9fff, read8sm_delegate(*this, FUNC(isa8_cga_cportiii_device::char_ram_read)), write8sm_delegate(*this, FUNC(isa8_cga_cportiii_device::char_ram_write)));
else
- m_isa->install_bank(0xb8000, 0xb8000 + 0x8000 - 1, "bank_cga", &m_vram[0]);
+ m_isa->install_bank(0xb8000, 0xb8000 + 0x8000 - 1, &m_vram[0]);
}
diff --git a/src/devices/bus/isa/cga.h b/src/devices/bus/isa/cga.h
index ccb0ea603ab..dd08fb68ea2 100644
--- a/src/devices/bus/isa/cga.h
+++ b/src/devices/bus/isa/cga.h
@@ -45,22 +45,25 @@ protected:
required_ioport m_cga_config;
// device-level overrides
- virtual void device_start() override;
- virtual void device_reset() override;
+ virtual void device_start() override ATTR_COLD;
+ virtual void device_reset() override ATTR_COLD;
// optional information 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;
+ virtual void device_add_mconfig(machine_config &config) override ATTR_COLD;
+ virtual ioport_constructor device_input_ports() const override ATTR_COLD;
+ virtual const tiny_rom_entry *device_rom_region() const override ATTR_COLD;
virtual uint32_t screen_update(screen_device &screen, bitmap_rgb32 &bitmap, const rectangle &cliprect);
+ void hsync_changed(int state);
+ void vsync_changed(int state);
+
public:
void mode_control_w(uint8_t data);
void set_palette_luts();
void plantronics_w(uint8_t data);
- virtual DECLARE_READ8_MEMBER( io_read );
- virtual DECLARE_WRITE8_MEMBER( io_write );
+ virtual uint8_t io_read(offs_t offset);
+ virtual void io_write(offs_t offset, uint8_t data);
public:
int m_framecnt;
@@ -86,8 +89,6 @@ public:
required_device<screen_device> m_screen;
private:
- DECLARE_WRITE_LINE_MEMBER( hsync_changed );
- DECLARE_WRITE_LINE_MEMBER( vsync_changed );
MC6845_RECONFIGURE(reconfigure);
};
@@ -120,7 +121,7 @@ public:
// construction/destruction
isa8_cga_poisk2_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 const tiny_rom_entry *device_rom_region() const override ATTR_COLD;
};
// device type definition
@@ -136,16 +137,16 @@ public:
// construction/destruction
isa8_cga_pc1512_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;
- virtual const tiny_rom_entry *device_rom_region() const override;
+ virtual ioport_constructor device_input_ports() const override ATTR_COLD;
+ virtual const tiny_rom_entry *device_rom_region() const override ATTR_COLD;
virtual MC6845_UPDATE_ROW( crtc_update_row ) override;
MC6845_UPDATE_ROW( pc1512_gfx_4bpp_update_row );
protected:
// device-level overrides
- virtual void device_start() override;
- virtual void device_reset() override;
+ virtual void device_start() override ATTR_COLD;
+ virtual void device_reset() override ATTR_COLD;
public:
uint8_t m_write;
@@ -160,10 +161,10 @@ public:
static const offs_t vram_offset[4];
static const uint8_t mc6845_writeonce_register[31];
- virtual DECLARE_READ8_MEMBER( io_read ) override;
- virtual DECLARE_WRITE8_MEMBER( io_write ) override;
+ virtual uint8_t io_read(offs_t offset) override;
+ virtual void io_write(offs_t offset, uint8_t data) override;
- DECLARE_WRITE8_MEMBER( vram_w );
+ void vram_w(offs_t offset, uint8_t data);
};
// device type definition
@@ -178,19 +179,20 @@ public:
// construction/destruction
isa8_wyse700_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 const tiny_rom_entry *device_rom_region() const override ATTR_COLD;
protected:
// device-level overrides
- virtual void device_start() override;
- virtual void device_reset() override;
+ virtual void device_start() override ATTR_COLD;
+ virtual void device_reset() override ATTR_COLD;
public:
- virtual DECLARE_READ8_MEMBER( io_read ) override;
- virtual DECLARE_WRITE8_MEMBER( io_write ) override;
+ virtual uint8_t io_read(offs_t offset) override;
+ virtual void io_write(offs_t offset, uint8_t data) override;
virtual uint32_t screen_update(screen_device &screen, bitmap_rgb32 &bitmap, const rectangle &cliprect) override;
void change_resolution(uint8_t mode);
+ memory_bank_creator m_vrambank;
uint8_t m_bank_offset;
uint8_t m_bank_base;
uint8_t m_control;
@@ -210,16 +212,16 @@ public:
protected:
// device-level overrides
- virtual void device_start() override;
- virtual void device_reset() override;
+ virtual void device_start() override ATTR_COLD;
+ virtual void device_reset() override ATTR_COLD;
public:
- virtual DECLARE_READ8_MEMBER( io_read ) override;
- virtual DECLARE_WRITE8_MEMBER( io_write ) override;
+ virtual uint8_t io_read(offs_t offset) override;
+ virtual void io_write(offs_t offset, uint8_t data) override;
uint8_t m_p3df;
- DECLARE_READ8_MEMBER( char_ram_read );
- DECLARE_WRITE8_MEMBER( char_ram_write );
+ uint8_t char_ram_read(offs_t offset);
+ void char_ram_write(offs_t offset, uint8_t data);
};
// device type definition
@@ -233,7 +235,7 @@ class isa8_cga_iskr1030m_device :
public:
// construction/destruction
isa8_cga_iskr1030m_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
- virtual const tiny_rom_entry *device_rom_region() const override;
+ virtual const tiny_rom_entry *device_rom_region() const override ATTR_COLD;
};
// device type definition
@@ -247,7 +249,7 @@ class isa8_cga_iskr1031_device :
public:
// construction/destruction
isa8_cga_iskr1031_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
- virtual const tiny_rom_entry *device_rom_region() const override;
+ virtual const tiny_rom_entry *device_rom_region() const override ATTR_COLD;
};
// device type definition
@@ -262,7 +264,10 @@ public:
// construction/destruction
isa8_cga_mc1502_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 ATTR_COLD;
+ virtual const tiny_rom_entry *device_rom_region() const override ATTR_COLD;
+private:
+ MC6845_RECONFIGURE(reconfigure);
};
// device type definition
@@ -275,18 +280,18 @@ class isa8_cga_m24_device :
public:
// construction/destruction
isa8_cga_m24_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
- virtual DECLARE_READ8_MEMBER( io_read ) override;
- virtual DECLARE_WRITE8_MEMBER( io_write ) override;
+ virtual uint8_t io_read(offs_t offset) override;
+ virtual void io_write(offs_t offset, uint8_t data) override;
virtual MC6845_UPDATE_ROW( crtc_update_row ) override;
MC6845_UPDATE_ROW( m24_gfx_1bpp_m24_update_row );
MC6845_RECONFIGURE(reconfigure);
protected:
isa8_cga_m24_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock);
- virtual void device_reset() override;
+ virtual void device_reset() override ATTR_COLD;
// optional information overrides
- virtual void device_add_mconfig(machine_config &config) override;
- virtual const tiny_rom_entry *device_rom_region() const override;
+ virtual void device_add_mconfig(machine_config &config) override ATTR_COLD;
+ virtual const tiny_rom_entry *device_rom_region() const override ATTR_COLD;
uint8_t m_mode2, m_index;
};
@@ -298,16 +303,16 @@ class isa8_cga_cportiii_device :
{
public:
isa8_cga_cportiii_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
- DECLARE_READ8_MEMBER(port_13c6_r);
- DECLARE_WRITE8_MEMBER(port_13c6_w);
- DECLARE_READ8_MEMBER(port_23c6_r);
- DECLARE_WRITE8_MEMBER(port_23c6_w);
- DECLARE_READ8_MEMBER(char_ram_read);
- DECLARE_WRITE8_MEMBER(char_ram_write);
+ uint8_t port_13c6_r();
+ void port_13c6_w(uint8_t data);
+ uint8_t port_23c6_r();
+ void port_23c6_w(uint8_t data);
+ uint8_t char_ram_read(offs_t offset);
+ void char_ram_write(offs_t offset, uint8_t data);
protected:
- 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 device_reset() override ATTR_COLD;
+ virtual void device_add_mconfig(machine_config &config) override ATTR_COLD;
+ virtual const tiny_rom_entry *device_rom_region() const override ATTR_COLD;
};
DECLARE_DEVICE_TYPE(ISA8_CGA_CPORTIII, isa8_cga_cportiii_device)
diff --git a/src/devices/bus/isa/chessmdr.cpp b/src/devices/bus/isa/chessmdr.cpp
index 00182d9e5ff..b1035945761 100644
--- a/src/devices/bus/isa/chessmdr.cpp
+++ b/src/devices/bus/isa/chessmdr.cpp
@@ -35,6 +35,8 @@ void isa8_chessmdr_device::device_start()
{
set_isa_device();
m_installed = false;
+
+ save_item(NAME(m_installed));
}
@@ -49,7 +51,7 @@ void isa8_chessmdr_device::device_reset()
{
// MAME doesn't allow reading ioport at device_start
u16 port = ioport("DSW")->read() * 0x40 + 0x10;
- m_isa->install_device(port, port+1, read8_delegate(FUNC(isa8_chessmdr_device::chessmdr_r), this), write8_delegate(FUNC(isa8_chessmdr_device::chessmdr_w), this));
+ m_isa->install_device(port, port+1, read8sm_delegate(*this, FUNC(isa8_chessmdr_device::chessmdr_r)), write8sm_delegate(*this, FUNC(isa8_chessmdr_device::chessmdr_w)));
m_installed = true;
}
@@ -104,7 +106,7 @@ void isa8_chessmdr_device::device_add_mconfig(machine_config &config)
I/O
******************************************************************************/
-READ8_MEMBER(isa8_chessmdr_device::chessmdr_r)
+uint8_t isa8_chessmdr_device::chessmdr_r(offs_t offset)
{
if (offset == 1)
return m_chessm->data_r() ? 0 : 0x80;
@@ -112,7 +114,7 @@ READ8_MEMBER(isa8_chessmdr_device::chessmdr_r)
return 0xff;
}
-WRITE8_MEMBER(isa8_chessmdr_device::chessmdr_w)
+void isa8_chessmdr_device::chessmdr_w(offs_t offset, uint8_t data)
{
if (offset == 0)
{
diff --git a/src/devices/bus/isa/chessmdr.h b/src/devices/bus/isa/chessmdr.h
index 8607dac26b0..92182c56259 100644
--- a/src/devices/bus/isa/chessmdr.h
+++ b/src/devices/bus/isa/chessmdr.h
@@ -25,19 +25,19 @@ public:
protected:
// device-level overrides
- virtual void device_start() override;
- virtual void device_reset() override;
- virtual void device_add_mconfig(machine_config &config) override;
+ 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;
- virtual ioport_constructor device_input_ports() const override;
+ virtual ioport_constructor device_input_ports() const override ATTR_COLD;
private:
required_device<chessmachine_device> m_chessm;
bool m_installed;
- DECLARE_READ8_MEMBER(chessmdr_r);
- DECLARE_WRITE8_MEMBER(chessmdr_w);
+ uint8_t chessmdr_r(offs_t offset);
+ void chessmdr_w(offs_t offset, uint8_t data);
};
diff --git a/src/devices/bus/isa/chessmsr.cpp b/src/devices/bus/isa/chessmsr.cpp
index bd878b18a67..f466f392227 100644
--- a/src/devices/bus/isa/chessmsr.cpp
+++ b/src/devices/bus/isa/chessmsr.cpp
@@ -32,8 +32,7 @@ isa8_chessmsr_device::isa8_chessmsr_device(const machine_config &mconfig, const
device_isa8_card_interface(mconfig, *this),
m_maincpu(*this, "maincpu"),
m_mainlatch(*this, "mainlatch"),
- m_sublatch(*this, "sublatch"),
- m_ram(*this, "ram")
+ m_sublatch(*this, "sublatch")
{ }
@@ -46,6 +45,15 @@ void isa8_chessmsr_device::device_start()
{
set_isa_device();
m_installed = false;
+
+ save_item(NAME(m_installed));
+ save_item(NAME(m_suspended));
+ save_item(NAME(m_ram_offset));
+
+ // allocate maximum RAM beforehand
+ const u32 maxram = 1 << 21;
+ m_ram = std::make_unique<u32[]>(maxram / 4);
+ save_pointer(NAME(m_ram), maxram / 4);
}
@@ -60,14 +68,13 @@ void isa8_chessmsr_device::device_reset()
{
// MAME doesn't allow reading ioport at device_start
u16 port = ioport("DSW")->read() * 0x40 + 0x10;
- m_isa->install_device(port, port+1, read8_delegate(FUNC(isa8_chessmsr_device::chessmsr_r), this), write8_delegate(FUNC(isa8_chessmsr_device::chessmsr_w), this));
+ m_isa->install_device(port, port+1, read8sm_delegate(*this, FUNC(isa8_chessmsr_device::chessmsr_r)), write8sm_delegate(*this, FUNC(isa8_chessmsr_device::chessmsr_w)));
m_maincpu->set_unscaled_clock(ioport("CPU")->read() ? (32_MHz_XTAL) : (30_MHz_XTAL/2));
// install RAM
u32 ramsize = 1 << ioport("RAM")->read();
- m_ram.allocate(ramsize / 4);
- m_maincpu->space(AS_PROGRAM).install_ram(0, ramsize - 1, m_ram);
+ m_maincpu->space(AS_PROGRAM).install_ram(0, ramsize - 1, m_ram.get());
m_installed = true;
}
@@ -76,7 +83,7 @@ void isa8_chessmsr_device::device_reset()
void isa8_chessmsr_device::device_reset_after_children()
{
// hold ARM CPU in reset state
- chessmsr_w(machine().dummy_space(), 1, 0);
+ chessmsr_w(1, 0);
}
@@ -148,7 +155,7 @@ void isa8_chessmsr_device::device_add_mconfig(machine_config &config)
// External handlers
-READ8_MEMBER(isa8_chessmsr_device::chessmsr_r)
+uint8_t isa8_chessmsr_device::chessmsr_r(offs_t offset)
{
if (offset == 0)
return m_mainlatch->read();
@@ -156,7 +163,7 @@ READ8_MEMBER(isa8_chessmsr_device::chessmsr_r)
return m_mainlatch->pending_r() ? 0 : 2;
}
-WRITE8_MEMBER(isa8_chessmsr_device::chessmsr_w)
+void isa8_chessmsr_device::chessmsr_w(offs_t offset, uint8_t data)
{
if (offset == 0)
{
diff --git a/src/devices/bus/isa/chessmsr.h b/src/devices/bus/isa/chessmsr.h
index 2d79226d4ce..2e324fe6c06 100644
--- a/src/devices/bus/isa/chessmsr.h
+++ b/src/devices/bus/isa/chessmsr.h
@@ -26,27 +26,27 @@ public:
protected:
// device-level overrides
- virtual void device_start() override;
- virtual void device_reset() override;
+ virtual void device_start() override ATTR_COLD;
+ virtual void device_reset() override ATTR_COLD;
virtual void device_reset_after_children() override;
- virtual void device_add_mconfig(machine_config &config) override;
+ virtual void device_add_mconfig(machine_config &config) override ATTR_COLD;
- virtual ioport_constructor device_input_ports() const override;
+ virtual ioport_constructor device_input_ports() const override ATTR_COLD;
private:
required_device<arm_cpu_device> m_maincpu;
required_device<generic_latch_8_device> m_mainlatch;
required_device<generic_latch_8_device> m_sublatch;
- optional_shared_ptr<u32> m_ram;
+ std::unique_ptr<u32[]> m_ram;
u8 m_ram_offset;
bool m_suspended;
bool m_installed;
- DECLARE_READ8_MEMBER(chessmsr_r);
- DECLARE_WRITE8_MEMBER(chessmsr_w);
+ uint8_t chessmsr_r(offs_t offset);
+ void chessmsr_w(offs_t offset, uint8_t data);
- void chessmsr_mem(address_map &map);
+ void chessmsr_mem(address_map &map) ATTR_COLD;
};
diff --git a/src/devices/bus/isa/cl_sh260.h b/src/devices/bus/isa/cl_sh260.h
index 18612ab6456..b27eaae32ec 100644
--- a/src/devices/bus/isa/cl_sh260.h
+++ b/src/devices/bus/isa/cl_sh260.h
@@ -21,9 +21,9 @@ class isa16_cl_sh260_device : public device_t, public device_isa16_card_interfac
protected:
isa16_cl_sh260_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, u32 clock);
- virtual void device_start() override;
+ virtual void device_start() override ATTR_COLD;
- void i8031_map(address_map &map);
+ void i8031_map(address_map &map) ATTR_COLD;
required_device<upd765_family_device> m_fdc;
};
@@ -36,11 +36,11 @@ public:
static constexpr feature_type unemulated_features() { return feature::DISK; }
protected:
- virtual void device_add_mconfig(machine_config &config) override;
- virtual const tiny_rom_entry *device_rom_region() const override;
+ virtual void device_add_mconfig(machine_config &config) override ATTR_COLD;
+ virtual const tiny_rom_entry *device_rom_region() const override ATTR_COLD;
private:
- void ext_map(address_map &map);
+ void ext_map(address_map &map) ATTR_COLD;
};
class isa16_jc1310_device : public isa16_cl_sh260_device
@@ -51,11 +51,11 @@ public:
static constexpr feature_type unemulated_features() { return feature::DISK; }
protected:
- virtual void device_add_mconfig(machine_config &config) override;
- virtual const tiny_rom_entry *device_rom_region() const override;
+ virtual void device_add_mconfig(machine_config &config) override ATTR_COLD;
+ virtual const tiny_rom_entry *device_rom_region() const override ATTR_COLD;
private:
- void ext_map(address_map &map);
+ void ext_map(address_map &map) ATTR_COLD;
};
DECLARE_DEVICE_TYPE(EV346, isa16_ev346_device)
diff --git a/src/devices/bus/isa/com.cpp b/src/devices/bus/isa/com.cpp
index 6ab3c393ccd..4a1cc1ebd00 100644
--- a/src/devices/bus/isa/com.cpp
+++ b/src/devices/bus/isa/com.cpp
@@ -118,10 +118,10 @@ isa8_com_device::isa8_com_device(const machine_config &mconfig, device_type type
void isa8_com_device::device_start()
{
set_isa_device();
- m_isa->install_device(0x03f8, 0x03ff, read8sm_delegate(FUNC(ins8250_device::ins8250_r), subdevice<ins8250_uart_device>("uart_0")), write8sm_delegate(FUNC(ins8250_device::ins8250_w), subdevice<ins8250_uart_device>("uart_0")) );
- m_isa->install_device(0x02f8, 0x02ff, read8sm_delegate(FUNC(ins8250_device::ins8250_r), subdevice<ins8250_uart_device>("uart_1")), write8sm_delegate(FUNC(ins8250_device::ins8250_w), subdevice<ins8250_uart_device>("uart_1")) );
-// m_isa->install_device(0x03e8, 0x03ef, read8sm_delegate(FUNC(ins8250_device::ins8250_r), subdevice<ins8250_uart_device>("uart_2")), write8sm_delegate(FUNC(ins8250_device::ins8250_w), subdevice<ins8250_uart_device>("uart_2")) );
-// m_isa->install_device(0x02e8, 0x02ef, read8sm_delegate(FUNC(ins8250_device::ins8250_r), subdevice<ins8250_uart_device>("uart_3")), write8sm_delegate(FUNC(ins8250_device::ins8250_w), subdevice<ins8250_uart_device>("uart_3")) );
+ m_isa->install_device(0x03f8, 0x03ff, read8sm_delegate(*subdevice<ins8250_uart_device>("uart_0"), FUNC(ins8250_device::ins8250_r)), write8sm_delegate(*subdevice<ins8250_uart_device>("uart_0"), FUNC(ins8250_device::ins8250_w)));
+ m_isa->install_device(0x02f8, 0x02ff, read8sm_delegate(*subdevice<ins8250_uart_device>("uart_1"), FUNC(ins8250_device::ins8250_r)), write8sm_delegate(*subdevice<ins8250_uart_device>("uart_1"), FUNC(ins8250_device::ins8250_w)));
+// m_isa->install_device(0x03e8, 0x03ef, read8sm_delegate(*subdevice<ins8250_uart_device>("uart_2"), FUNC(ins8250_device::ins8250_r)), write8sm_delegate(*subdevice<ins8250_uart_device>("uart_2"), FUNC(ins8250_device::ins8250_w)));
+// m_isa->install_device(0x02e8, 0x02ef, read8sm_delegate(*subdevice<ins8250_uart_device>("uart_3"), FUNC(ins8250_device::ins8250_r)), write8sm_delegate(*subdevice<ins8250_uart_device>("uart_3"), FUNC(ins8250_device::ins8250_w)));
}
//-------------------------------------------------
diff --git a/src/devices/bus/isa/com.h b/src/devices/bus/isa/com.h
index ff7b5e4eef8..0d107f75c94 100644
--- a/src/devices/bus/isa/com.h
+++ b/src/devices/bus/isa/com.h
@@ -22,18 +22,18 @@ 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);
// device-level overrides
- virtual void device_start() override;
- virtual void device_reset() override;
+ virtual void device_start() override ATTR_COLD;
+ virtual void device_reset() override ATTR_COLD;
// optional information overrides
- virtual void device_add_mconfig(machine_config &config) override;
+ virtual void device_add_mconfig(machine_config &config) override ATTR_COLD;
};
@@ -51,7 +51,7 @@ public:
protected:
// optional information overrides
- virtual void device_add_mconfig(machine_config &config) override;
+ virtual void device_add_mconfig(machine_config &config) override ATTR_COLD;
};
diff --git a/src/devices/bus/isa/dcb.h b/src/devices/bus/isa/dcb.h
index fbca0303978..483a37ffff0 100644
--- a/src/devices/bus/isa/dcb.h
+++ b/src/devices/bus/isa/dcb.h
@@ -23,16 +23,16 @@ public:
static constexpr feature_type unemulated_features() { return feature::DISK; }
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_add_mconfig(machine_config &config) override ATTR_COLD;
+ virtual const tiny_rom_entry *device_rom_region() const override ATTR_COLD;
+ virtual void device_start() override ATTR_COLD;
private:
void eeprom_w(u8 data);
u8 misc_r();
- void mem_map(address_map &map);
- void io_map(address_map &map);
+ void mem_map(address_map &map) ATTR_COLD;
+ void io_map(address_map &map) ATTR_COLD;
required_device<i80188_cpu_device> m_localcpu;
required_device<eeprom_serial_93cxx_device> m_eeprom;
diff --git a/src/devices/bus/isa/dectalk.cpp b/src/devices/bus/isa/dectalk.cpp
index da45a2ec18b..141a7c06c43 100644
--- a/src/devices/bus/isa/dectalk.cpp
+++ b/src/devices/bus/isa/dectalk.cpp
@@ -3,7 +3,6 @@
#include "emu.h"
#include "dectalk.h"
-#include "sound/volt_reg.h"
#include "speaker.h"
@@ -26,50 +25,48 @@ dectalk_isa_device::dectalk_isa_device(const machine_config& mconfig, const char
{
}
-WRITE16_MEMBER(dectalk_isa_device::status_w)
+void dectalk_isa_device::status_w(uint16_t data)
{
m_stat = data;
}
-READ16_MEMBER(dectalk_isa_device::cmd_r)
+uint16_t dectalk_isa_device::cmd_r()
{
return m_cmd;
}
-WRITE16_MEMBER(dectalk_isa_device::data_w)
+void dectalk_isa_device::data_w(uint16_t data)
{
m_data = data;
}
-READ16_MEMBER(dectalk_isa_device::data_r)
+uint16_t dectalk_isa_device::data_r()
{
return m_data;
}
-READ16_MEMBER(dectalk_isa_device::host_irq_r)
+uint16_t dectalk_isa_device::host_irq_r()
{
//m_isa->ir?_w(1);
return 0;
}
-READ8_MEMBER(dectalk_isa_device::dma_r)
+uint8_t dectalk_isa_device::dma_r()
{
- m_cpu->drq1_w(0);
return m_dma;
}
-WRITE8_MEMBER(dectalk_isa_device::dma_w)
+void dectalk_isa_device::dma_w(uint8_t data)
{
- m_cpu->drq1_w(0);
m_dma = data;
}
-WRITE16_MEMBER(dectalk_isa_device::dac_w)
+void dectalk_isa_device::dac_w(uint16_t data)
{
m_dac->write(data >> 4);
}
-WRITE16_MEMBER(dectalk_isa_device::output_ctl_w)
+void dectalk_isa_device::output_ctl_w(uint16_t data)
{
// X9C503P potentiometer, 8-CS, 4-U/D, 2-INC
if(!(data & 8) && !(m_ctl & 2) && (data & 2))
@@ -85,33 +82,32 @@ WRITE16_MEMBER(dectalk_isa_device::output_ctl_w)
m_ctl = data;
}
-READ16_MEMBER(dectalk_isa_device::dsp_dma_r)
+uint16_t dectalk_isa_device::dsp_dma_r()
{
m_bio = ASSERT_LINE;
- m_cpu->drq1_w(0);
return m_dsp_dma;
}
-WRITE16_MEMBER(dectalk_isa_device::dsp_dma_w)
+void dectalk_isa_device::dsp_dma_w(uint16_t data)
{
m_bio = CLEAR_LINE;
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)
- m_cpu->drq0_w(1);
+ m_cpu->dma_sync_req(0);
return m_bio;
}
-WRITE16_MEMBER(dectalk_isa_device::irq_line_w)
+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);
}
@@ -159,24 +155,21 @@ const tiny_rom_entry* dectalk_isa_device::device_rom_region() const
void dectalk_isa_device::device_add_mconfig(machine_config &config)
{
- I80186(config, m_cpu, XTAL(20'000'000));
+ I80186(config, m_cpu, 20_MHz_XTAL);
m_cpu->set_addrmap(AS_PROGRAM, &dectalk_isa_device::dectalk_cpu_map);
m_cpu->set_addrmap(AS_IO, &dectalk_isa_device::dectalk_cpu_io);
m_cpu->tmrout0_handler().set(FUNC(dectalk_isa_device::clock_w));
- TMS32015(config, m_dsp, XTAL(20'000'000));
+ TMS32015(config, m_dsp, 80'000'000); // the a 20MHz oscillator is present - clock frequency hacked to make it "work"
m_dsp->set_addrmap(AS_PROGRAM, &dectalk_isa_device::dectalk_dsp_map);
m_dsp->set_addrmap(AS_IO, &dectalk_isa_device::dectalk_dsp_io);
m_dsp->bio().set(FUNC(dectalk_isa_device::bio_line_r));
SPEAKER(config, "speaker").front_center();
- DAC_12BIT_R2R(config, m_dac, 0).add_route(0, "speaker", 1.0); // unknown DAC
- voltage_regulator_device &vref(VOLTAGE_REGULATOR(config, "vref", 0));
- vref.add_route(0, "dac", 1.0, DAC_VREF_POS_INPUT);
- vref.add_route(0, "dac", -1.0, DAC_VREF_NEG_INPUT);
+ DAC_12BIT_R2R_TWOS_COMPLEMENT(config, m_dac, 0).add_route(0, "speaker", 1.0); // AD7541 DAC
}
-WRITE8_MEMBER(dectalk_isa_device::write)
+void dectalk_isa_device::write(offs_t offset, uint8_t data)
{
switch(offset)
{
@@ -194,7 +187,7 @@ WRITE8_MEMBER(dectalk_isa_device::write)
break;
case 4:
m_dma = data;
- m_cpu->drq1_w(1);
+ m_cpu->dma_sync_req(1);
break;
case 6:
m_cpu->int1_w(1);
@@ -202,7 +195,7 @@ WRITE8_MEMBER(dectalk_isa_device::write)
}
}
-READ8_MEMBER(dectalk_isa_device::read)
+uint8_t dectalk_isa_device::read(offs_t offset)
{
switch(offset)
{
@@ -215,7 +208,8 @@ READ8_MEMBER(dectalk_isa_device::read)
case 3:
return m_data >> 8;
case 4:
- m_cpu->drq1_w(1);
+ if (!machine().side_effects_disabled())
+ m_cpu->dma_sync_req(1);
return m_dma;
}
return 0;
@@ -224,7 +218,7 @@ READ8_MEMBER(dectalk_isa_device::read)
void dectalk_isa_device::device_start()
{
set_isa_device();
- m_isa->install_device(0x0250, 0x0257, read8_delegate(FUNC(dectalk_isa_device::read), this), write8_delegate(FUNC(dectalk_isa_device::write), this));
+ m_isa->install_device(0x0250, 0x0257, read8sm_delegate(*this, FUNC(dectalk_isa_device::read)), write8sm_delegate(*this, FUNC(dectalk_isa_device::write)));
}
void dectalk_isa_device::device_reset()
diff --git a/src/devices/bus/isa/dectalk.h b/src/devices/bus/isa/dectalk.h
index 373c33e5ac1..470dfb03bbd 100644
--- a/src/devices/bus/isa/dectalk.h
+++ b/src/devices/bus/isa/dectalk.h
@@ -18,43 +18,43 @@ public:
protected:
// device-level overrides
- virtual void device_start() override;
- virtual void device_reset() override;
+ virtual void device_start() override ATTR_COLD;
+ virtual void device_reset() override ATTR_COLD;
// optional information overrides
- virtual const tiny_rom_entry *device_rom_region() const override;
- virtual void device_add_mconfig(machine_config &config) override;
+ virtual const tiny_rom_entry *device_rom_region() const override ATTR_COLD;
+ virtual void device_add_mconfig(machine_config &config) override ATTR_COLD;
private:
- DECLARE_READ_LINE_MEMBER(bio_line_r);
- DECLARE_WRITE_LINE_MEMBER(clock_w);
-
- DECLARE_WRITE8_MEMBER(write);
- DECLARE_READ8_MEMBER(read);
-
- DECLARE_WRITE16_MEMBER(status_w);
- DECLARE_READ16_MEMBER(cmd_r);
- DECLARE_WRITE16_MEMBER(data_w);
- DECLARE_READ16_MEMBER(data_r);
- DECLARE_READ16_MEMBER(host_irq_r);
- DECLARE_READ8_MEMBER(dma_r);
- DECLARE_WRITE8_MEMBER(dma_w);
- DECLARE_WRITE16_MEMBER(dac_w);
- DECLARE_READ16_MEMBER(dsp_dma_r);
- DECLARE_WRITE16_MEMBER(dsp_dma_w);
- DECLARE_WRITE16_MEMBER(output_ctl_w);
- DECLARE_WRITE16_MEMBER(irq_line_w);
-
- void dectalk_cpu_io(address_map &map);
- void dectalk_cpu_map(address_map &map);
- void dectalk_dsp_io(address_map &map);
- void dectalk_dsp_map(address_map &map);
+ int bio_line_r();
+ void clock_w(int state);
+
+ void write(offs_t offset, uint8_t data);
+ uint8_t read(offs_t offset);
+
+ void status_w(uint16_t data);
+ uint16_t cmd_r();
+ void data_w(uint16_t data);
+ uint16_t data_r();
+ uint16_t host_irq_r();
+ uint8_t dma_r();
+ void dma_w(uint8_t data);
+ void dac_w(uint16_t data);
+ uint16_t dsp_dma_r();
+ void dsp_dma_w(uint16_t data);
+ void output_ctl_w(uint16_t data);
+ void irq_line_w(uint16_t data);
+
+ void dectalk_cpu_io(address_map &map) ATTR_COLD;
+ void dectalk_cpu_map(address_map &map) ATTR_COLD;
+ void dectalk_dsp_io(address_map &map) ATTR_COLD;
+ void dectalk_dsp_map(address_map &map) ATTR_COLD;
uint16_t m_cmd, m_stat, m_data, m_dsp_dma, m_ctl;
uint8_t m_dma, m_vol, m_bio;
required_device<i80186_cpu_device> m_cpu;
- required_device<dac_12bit_r2r_device> m_dac;
+ required_device<dac_12bit_r2r_twos_complement_device> m_dac;
required_device<tms32015_device> m_dsp;
};
diff --git a/src/devices/bus/isa/ega.cpp b/src/devices/bus/isa/ega.cpp
index 5da3c263384..9c61fc0a5a1 100644
--- a/src/devices/bus/isa/ega.cpp
+++ b/src/devices/bus/isa/ega.cpp
@@ -446,24 +446,31 @@ 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)
+//#define VERBOSE (LOG_GENERAL | LOG_SETUP | LOG_MODE)
+//#define LOG_OUTPUT_STREAM std::cout
-#define VERBOSE_EGA 1
+#include "logmacro.h"
+
+#define LOGR(...) LOGMASKED(LOG_READ, __VA_ARGS__)
+#define LOGSETUP(...) LOGMASKED(LOG_SETUP, __VA_ARGS__)
+#define LOGMODE(...) LOGMASKED(LOG_MODE, __VA_ARGS__)
+
+#ifdef _MSC_VER
+#define FUNCNAME __func__
+#else
+#define FUNCNAME __PRETTY_FUNCTION__
+#endif
#define EGA_SCREEN_NAME "ega_screen"
#define EGA_CRTC_NAME "crtc_ega_ega"
-
#define EGA_MODE_GRAPHICS 1
#define EGA_MODE_TEXT 2
-
-/*
- Prototypes
-*/
-
-
ROM_START( ega )
ROM_REGION(0x4000, "user1", 0)
ROM_DEFAULT_BIOS("ega")
@@ -498,23 +505,23 @@ ROM_END
INPUT_PORTS_START( ega )
PORT_START( "config" )
- PORT_CONFNAME( 0x0f, 0x09, "dipswitches" )
- PORT_CONFSETTING( 0x00, "0000 - MDA PRIMARY, EGA COLOR, 40x25" ) /* DIAG: ?? 40 cols, RGBI */
- PORT_CONFSETTING( 0x08, "0001 - MDA PRIMARY, EGA COLOR, 80x25" ) /* DIAG: ?? 80 cols, RGBI */
- PORT_CONFSETTING( 0x04, "0010 - MDA PRIMARY, EGA HI RES EMULATE (SAME AS 0001)" ) /* DIAG: ?? 80 cols, RGBI */
- PORT_CONFSETTING( 0x0c, "0011 - MDA PRIMARY, EGA HI RES ENHANCED" ) /* DIAG: Color Display 40 cols, RrGgBb */
- PORT_CONFSETTING( 0x02, "0100 - CGA 40 PRIMARY, EGA MONOCHROME" ) /* DIAG: ??, Mono RGBI */
- PORT_CONFSETTING( 0x0a, "0101 - CGA 80 PRIMARY, EGA MONOCHROME" ) /* DIAG: ??, Mono RGBI */
- PORT_CONFSETTING( 0x06, "0110 - MDA SECONDARY, EGA COLOR, 40x25" ) /* DIAG: Color Display 40 cols, RGBI */
- PORT_CONFSETTING( 0x0e, "0111 - MDA SECONDARY, EGA COLOR, 80x25" ) /* DIAG: Color Display 80 cols, RGBI */
- PORT_CONFSETTING( 0x01, "1000 - MDA SECONDARY, EGA HI RES EMULATE (SAME AS 0111)" ) /* DIAG: Color Display 80 cols, RGBI */
- PORT_CONFSETTING( 0x09, "1001 - MDA SECONDARY, EGA HI RES ENHANCED" ) /* DIAG: Color Display 40 cols, RrGgBb */
- PORT_CONFSETTING( 0x05, "1010 - COLOR 40 SECONDARY, EGA" ) /* DIAG: Monochrome display, Mono RGBI */
- PORT_CONFSETTING( 0x0d, "1011 - COLOR 80 SECONDARY, EGA" ) /* DIAG: Monochrome display, Mono RGBI */
- PORT_CONFSETTING( 0x03, "1100 - RESERVED" ) /* ??, RGBI */
- PORT_CONFSETTING( 0x0b, "1101 - RESERVED" ) /* ??, RGBI */
- PORT_CONFSETTING( 0x07, "1110 - RESERVED" ) /* ??, RGBI */
- PORT_CONFSETTING( 0x0f, "1111 - RESERVED" ) /* ??, RGBI */
+ PORT_DIPNAME( 0x0f, 0x09, "Display Type" )
+ PORT_DIPSETTING( 0x00, "0000 - MDA PRIMARY, EGA COLOR, 40x25" ) /* DIAG: ?? 40 cols, RGBI */
+ PORT_DIPSETTING( 0x08, "0001 - MDA PRIMARY, EGA COLOR, 80x25" ) /* DIAG: ?? 80 cols, RGBI */
+ PORT_DIPSETTING( 0x04, "0010 - MDA PRIMARY, EGA HI RES EMULATE (SAME AS 0001)" ) /* DIAG: ?? 80 cols, RGBI */
+ PORT_DIPSETTING( 0x0c, "0011 - MDA PRIMARY, EGA HI RES ENHANCED" ) /* DIAG: Color Display 40 cols, RrGgBb */
+ PORT_DIPSETTING( 0x02, "0100 - CGA 40 PRIMARY, EGA MONOCHROME" ) /* DIAG: ??, Mono RGBI */
+ PORT_DIPSETTING( 0x0a, "0101 - CGA 80 PRIMARY, EGA MONOCHROME" ) /* DIAG: ??, Mono RGBI */
+ PORT_DIPSETTING( 0x06, "0110 - MDA SECONDARY, EGA COLOR, 40x25" ) /* DIAG: Color Display 40 cols, RGBI */
+ PORT_DIPSETTING( 0x0e, "0111 - MDA SECONDARY, EGA COLOR, 80x25" ) /* DIAG: Color Display 80 cols, RGBI */
+ PORT_DIPSETTING( 0x01, "1000 - MDA SECONDARY, EGA HI RES EMULATE (SAME AS 0111)" ) /* DIAG: Color Display 80 cols, RGBI */
+ PORT_DIPSETTING( 0x09, "1001 - MDA SECONDARY, EGA HI RES ENHANCED" ) /* DIAG: Color Display 40 cols, RrGgBb */
+ PORT_DIPSETTING( 0x05, "1010 - COLOR 40 SECONDARY, EGA" ) /* DIAG: Monochrome display, Mono RGBI */
+ PORT_DIPSETTING( 0x0d, "1011 - COLOR 80 SECONDARY, EGA" ) /* DIAG: Monochrome display, Mono RGBI */
+ PORT_DIPSETTING( 0x03, "1100 - RESERVED" ) /* ??, RGBI */
+ PORT_DIPSETTING( 0x0b, "1101 - RESERVED" ) /* ??, RGBI */
+ PORT_DIPSETTING( 0x07, "1110 - RESERVED" ) /* ??, RGBI */
+ PORT_DIPSETTING( 0x0f, "1111 - RESERVED" ) /* ??, RGBI */
INPUT_PORTS_END
//**************************************************************************
@@ -530,21 +537,22 @@ 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);
CRTC_EGA(config, m_crtc_ega, 16.257_MHz_XTAL/8);
m_crtc_ega->set_screen(EGA_SCREEN_NAME);
m_crtc_ega->config_set_hpixels_per_column(8);
- m_crtc_ega->set_row_update_callback(FUNC(isa8_ega_device::ega_update_row), this);
+ m_crtc_ega->set_row_update_callback(FUNC(isa8_ega_device::ega_update_row));
m_crtc_ega->res_out_de_callback().set(FUNC(isa8_ega_device::de_changed));
m_crtc_ega->res_out_hsync_callback().set(FUNC(isa8_ega_device::hsync_changed));
m_crtc_ega->res_out_vsync_callback().set(FUNC(isa8_ega_device::vsync_changed));
m_crtc_ega->res_out_vblank_callback().set(FUNC(isa8_ega_device::vblank_changed));
+ m_crtc_ega->res_out_irq_callback().set([this](int state) { m_irq = state; m_isa->irq2_w(state); });
}
//-------------------------------------------------
@@ -578,8 +586,8 @@ isa8_ega_device::isa8_ega_device(const machine_config &mconfig, device_type type
device_t(mconfig, type, tag, owner, clock),
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_video_mode(0),
- m_palette(*this, "palette")
+ 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_screen(*this, EGA_SCREEN_NAME)
{
}
@@ -627,10 +635,19 @@ void isa8_ega_device::device_start()
m_plane[2] = m_videoram + 0x20000;
m_plane[3] = m_videoram + 0x30000;
- m_isa->install_rom(this, 0xc0000, 0xc3fff, "ega", "user2");
- m_isa->install_device(0x3b0, 0x3bf, read8_delegate(FUNC(isa8_ega_device::pc_ega8_3b0_r), this), write8_delegate(FUNC(isa8_ega_device::pc_ega8_3b0_w), this));
- m_isa->install_device(0x3c0, 0x3cf, read8_delegate(FUNC(isa8_ega_device::pc_ega8_3c0_r), this), write8_delegate(FUNC(isa8_ega_device::pc_ega8_3c0_w), this));
- m_isa->install_device(0x3d0, 0x3df, read8_delegate(FUNC(isa8_ega_device::pc_ega8_3d0_r), this), write8_delegate(FUNC(isa8_ega_device::pc_ega8_3d0_w), this));
+ save_item(STRUCT_MEMBER(m_graphics_controller, index));
+ save_item(STRUCT_MEMBER(m_graphics_controller, data));
+ save_item(STRUCT_MEMBER(m_sequencer, index));
+ save_item(STRUCT_MEMBER(m_sequencer, data));
+ save_item(STRUCT_MEMBER(m_attribute, index));
+ save_item(STRUCT_MEMBER(m_attribute, data));
+ save_item(STRUCT_MEMBER(m_attribute, index_write));
+ save_pointer(NAME(m_vram), 256 * 1024);
+
+ m_isa->install_rom(this, 0xc0000, 0xc3fff, "user2");
+ m_isa->install_device(0x3b0, 0x3bf, read8sm_delegate(*this, FUNC(isa8_ega_device::pc_ega8_3b0_r)), write8sm_delegate(*this, FUNC(isa8_ega_device::pc_ega8_3b0_w)));
+ m_isa->install_device(0x3c0, 0x3cf, read8sm_delegate(*this, FUNC(isa8_ega_device::pc_ega8_3c0_r)), write8sm_delegate(*this, FUNC(isa8_ega_device::pc_ega8_3c0_w)));
+ m_isa->install_device(0x3d0, 0x3df, read8sm_delegate(*this, FUNC(isa8_ega_device::pc_ega8_3d0_r)), write8sm_delegate(*this, FUNC(isa8_ega_device::pc_ega8_3d0_w)));
}
//-------------------------------------------------
@@ -650,6 +667,7 @@ void isa8_ega_device::device_reset()
m_vsync = 0;
m_vblank = 0;
m_display_enable = 0;
+ m_irq = 0;
install_banks();
@@ -684,7 +702,7 @@ void isa8_ega_device::install_banks()
case 0x00: /* 0xA0000, 128KB */
if ( m_misc_output & 0x02 )
{
- m_isa->install_memory(0xa0000, 0xbffff, read8_delegate(FUNC(isa8_ega_device::read), this), write8_delegate(FUNC(isa8_ega_device::write), this));
+ m_isa->install_memory(0xa0000, 0xbffff, read8sm_delegate(*this, FUNC(isa8_ega_device::read)), write8sm_delegate(*this, FUNC(isa8_ega_device::write)));
}
else
{
@@ -696,7 +714,7 @@ void isa8_ega_device::install_banks()
case 0x04: /* 0xA0000, 64KB */
if ( m_misc_output & 0x02 )
{
- m_isa->install_memory(0xa0000, 0xaffff, read8_delegate(FUNC(isa8_ega_device::read), this), write8_delegate(FUNC(isa8_ega_device::write), this));
+ m_isa->install_memory(0xa0000, 0xaffff, read8sm_delegate(*this, FUNC(isa8_ega_device::read)), write8sm_delegate(*this, FUNC(isa8_ega_device::write)));
}
else
{
@@ -709,7 +727,7 @@ void isa8_ega_device::install_banks()
case 0x08: /* 0xB0000, 32KB */
if ( m_misc_output & 0x02 )
{
- m_isa->install_memory(0xb0000, 0xb7fff, read8_delegate(FUNC(isa8_ega_device::read), this), write8_delegate(FUNC(isa8_ega_device::write), this));
+ m_isa->install_memory(0xb0000, 0xb7fff, read8sm_delegate(*this, FUNC(isa8_ega_device::read)), write8sm_delegate(*this, FUNC(isa8_ega_device::write)));
}
else
{
@@ -722,7 +740,7 @@ void isa8_ega_device::install_banks()
case 0x0c: /* 0xB8000, 32KB */
if ( m_misc_output & 0x02 )
{
- m_isa->install_memory(0xb8000, 0xbffff, read8_delegate(FUNC(isa8_ega_device::read), this), write8_delegate(FUNC(isa8_ega_device::write), this));
+ m_isa->install_memory(0xb8000, 0xbffff, read8sm_delegate(*this, FUNC(isa8_ega_device::read)), write8sm_delegate(*this, FUNC(isa8_ega_device::write)));
}
else
{
@@ -735,28 +753,28 @@ void isa8_ega_device::install_banks()
}
}
-CRTC_EGA_ROW_UPDATE( isa8_ega_device::ega_update_row )
+CRTC_EGA_PIXEL_UPDATE( isa8_ega_device::ega_update_row )
{
if (m_video_mode == EGA_MODE_GRAPHICS)
- pc_ega_graphics(bitmap, cliprect, ma, ra, y, x_count, cursor_x);
+ pc_ega_graphics(bitmap, cliprect, ma, ra, y, x, cursor_x);
else if (m_video_mode == EGA_MODE_TEXT)
- pc_ega_text(bitmap, cliprect, ma, ra, y, x_count, cursor_x);
+ pc_ega_text(bitmap, cliprect, ma, ra, y, x, cursor_x);
}
-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 )
@@ -766,39 +784,36 @@ 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;
}
-CRTC_EGA_ROW_UPDATE( isa8_ega_device::pc_ega_graphics )
+CRTC_EGA_PIXEL_UPDATE( isa8_ega_device::pc_ega_graphics )
{
- uint16_t *p = &bitmap.pix16(y);
+ uint16_t *p = &bitmap.pix(y, x * 8);
-// logerror( "pc_ega_graphics: y = %d, x_count = %d, ma = %d, ra = %d\n", y, x_count, ma, ra );
+ LOG("%s: y = %d, x = %d, ma = %d, ra = %d\n", FUNCNAME, y, x, ma, ra );
if ( m_graphics_controller.data[5] & 0x10 )
{
// Odd/Even mode (CGA compatible)
- for ( int i = 0; i < x_count; i++ )
- {
- uint16_t offset = ( ( ma + i ) & 0x1fff ) | ( ( y & 1 ) << 12 );
- uint8_t data = m_plane[0][offset];
+ uint16_t offset = ( ma & 0x1fff ) | ( ( y & 1 ) << 12 );
+ uint8_t data = m_plane[BIT(m_misc_output, 5) ? 2 : 0][offset];
- *p = m_attribute.data[ ( data >> 6 ) ]; p++;
- *p = m_attribute.data[ ( data >> 4 ) & 0x03 ]; p++;
- *p = m_attribute.data[ ( data >> 2 ) & 0x03 ]; p++;
- *p = m_attribute.data[ data & 0x03 ]; p++;
+ *p = m_attribute.data[ ( data >> 6 ) ]; p++;
+ *p = m_attribute.data[ ( data >> 4 ) & 0x03 ]; p++;
+ *p = m_attribute.data[ ( data >> 2 ) & 0x03 ]; p++;
+ *p = m_attribute.data[ data & 0x03 ]; p++;
- data = m_plane[1][offset];
+ data = m_plane[BIT(m_misc_output, 5) ? 3 : 1][offset];
- *p = m_attribute.data[ ( data >> 6 ) ]; p++;
- *p = m_attribute.data[ ( data >> 4 ) & 0x03 ]; p++;
- *p = m_attribute.data[ ( data >> 2 ) & 0x03 ]; p++;
- *p = m_attribute.data[ data & 0x03 ]; p++;
- }
+ *p = m_attribute.data[ ( data >> 6 ) ]; p++;
+ *p = m_attribute.data[ ( data >> 4 ) & 0x03 ]; p++;
+ *p = m_attribute.data[ ( data >> 2 ) & 0x03 ]; p++;
+ *p = m_attribute.data[ data & 0x03 ]; p++;
}
else
{
@@ -806,94 +821,100 @@ CRTC_EGA_ROW_UPDATE( isa8_ega_device::pc_ega_graphics )
uint8_t mask = m_attribute.data[0x12] & 0x0f;
- for ( int i = 0; i < x_count; i++ )
- {
- uint16_t offset = ma + i;
- uint16_t data0 = m_plane[0][offset];
- uint16_t data1 = m_plane[1][offset] << 1;
- uint16_t data2 = m_plane[2][offset] << 2;
- uint16_t data3 = m_plane[3][offset] << 3;
+ uint16_t offset = ma;
+ uint16_t data0 = m_plane[0][offset];
+ uint16_t data1 = m_plane[1][offset] << 1;
+ uint16_t data2 = m_plane[2][offset] << 2;
+ uint16_t data3 = m_plane[3][offset] << 3;
- for ( int j = 7; j >= 0; j-- )
- {
- uint16_t col = ( data0 & 0x01 ) | ( data1 & 0x02 ) | ( data2 & 0x04 ) | ( data3 & 0x08 );
+ for ( int j = 7; j >= 0; j-- )
+ {
+ uint16_t col = ( data0 & 0x01 ) | ( data1 & 0x02 ) | ( data2 & 0x04 ) | ( data3 & 0x08 );
- col &= mask;
+ col &= mask;
+ if ( m_misc_output & 0x80 )
p[j] = m_attribute.data[col];
-
- data0 >>= 1;
- data1 >>= 1;
- data2 >>= 1;
- data3 >>= 1;
+ else
+ {
+ p[j] = m_attribute.data[col] | (BIT(m_attribute.data[col], 4) ? 0x38 : 0);
+ if ( p[j] == 6 )
+ p[j] = 0x14;
}
- p += 8;
+
+ data0 >>= 1;
+ data1 >>= 1;
+ data2 >>= 1;
+ data3 >>= 1;
}
}
}
-CRTC_EGA_ROW_UPDATE( isa8_ega_device::pc_ega_text )
+CRTC_EGA_PIXEL_UPDATE( isa8_ega_device::pc_ega_text )
{
- uint16_t *p = &bitmap.pix16(y);
- int i;
+ uint16_t *p = &bitmap.pix(y, x * ( ( m_sequencer.data[0x01] & 0x01 ) ? 8 : 9 ) );
+
+ LOG("%s: y = %d, x = %d, ma = %d, ra = %d\n", FUNCNAME, y, x, ma, ra );
-// logerror( "pc_ega_text: y = %d, x_count = %d, ma = %d, ra = %d\n", y, x_count, ma, ra );
+ uint16_t offset = ma;
+ uint8_t chr = m_plane[0][ offset ];
+ uint8_t attr = m_plane[1][ offset ];
+ uint8_t data;
+ 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) ];
- for ( i = 0; i < x_count; i++ )
+ if ( m_charA == m_charB )
+ data = m_charB[ chr * 32 + ra ];
+ else
{
- uint16_t offset = ma + i;
- 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 ];
-
- /* 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 ];
- fg += ( attr & 0x08 ) ? 0x38 : 0x00;
- }
- else
- {
- /* character set selector */
- data = ( attr & 0x08 ) ? m_charA[ chr * 32 + ra ] : m_charB[ chr * 32 + ra ];
- }
+ /* character set selector */
+ data = ( attr & 0x08 ) ? m_charA[ chr * 32 + ra ] : m_charB[ chr * 32 + ra ];
+ fg &= 0x07;
+ }
- if ( i == cursor_x )
+ 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 )
+ {
+ if ( m_frame_cnt & 0x08 )
{
- if ( m_frame_cnt & 0x08 )
- {
- data = 0xFF;
- }
+ data = 0xFF;
}
- else
+ }
+ else
+ {
+ /* Check for blinking */
+ if ( ( m_attribute.data[0x10] & 0x08 ) && ( attr & 0x80 ) && ( m_frame_cnt & 0x10 ) )
{
- /* Check for blinking */
- if ( ( m_attribute.data[0x10] & 0x08 ) && ( attr & 0x80 ) && ( m_frame_cnt & 0x10 ) )
- {
- data = 0x00;
- }
+ data = 0x00;
}
-
- *p = ( data & 0x80 ) ? fg : bg; p++;
- *p = ( data & 0x40 ) ? fg : bg; p++;
- *p = ( data & 0x20 ) ? fg : bg; p++;
- *p = ( data & 0x10 ) ? fg : bg; p++;
- *p = ( data & 0x08 ) ? fg : bg; p++;
- *p = ( data & 0x04 ) ? fg : bg; p++;
- *p = ( data & 0x02 ) ? fg : bg; p++;
- *p = ( data & 0x01 ) ? fg : bg; p++;
}
+
+ *p = ( data & 0x80 ) ? fg : bg; p++;
+ *p = ( data & 0x40 ) ? fg : bg; p++;
+ *p = ( data & 0x20 ) ? fg : bg; p++;
+ *p = ( data & 0x10 ) ? fg : bg; p++;
+ *p = ( data & 0x08 ) ? fg : bg; p++;
+ *p = ( data & 0x04 ) ? fg : bg; p++;
+ *p = ( data & 0x02 ) ? fg : bg; p++;
+ *p = ( data & 0x01 ) ? fg : bg; p++;
+ if ( !( m_sequencer.data[0x01] & 0x01 ) )
+ *p = ( m_attribute.data[0x10] & 0x04 ) ? *(p - 1) : bg;
}
void isa8_ega_device::change_mode()
{
- int clock, pixels;
-
m_video_mode = 0;
/* Check for graphics mode */
@@ -901,10 +922,7 @@ void isa8_ega_device::change_mode()
! ( m_sequencer.data[0x04] & 0x01 ) &&
( m_graphics_controller.data[0x06] & 0x01 ) )
{
- if ( VERBOSE_EGA )
- {
- logerror("change_mode(): Switch to graphics mode\n");
- }
+ LOGMODE("%s: Switch to graphics mode\n", FUNCNAME);
m_video_mode = EGA_MODE_GRAPHICS;
}
@@ -914,18 +932,15 @@ void isa8_ega_device::change_mode()
( m_sequencer.data[0x04] & 0x01 ) &&
! ( m_graphics_controller.data[0x06] & 0x01 ) )
{
- if ( VERBOSE_EGA )
- {
- logerror("chnage_mode(): Switching to text mode\n");
- }
+ LOGMODE("%s: Switching to text mode\n", FUNCNAME);
m_video_mode = EGA_MODE_TEXT;
/* Set character maps */
- if ( m_sequencer.data[0x04] & 0x02 )
+ if ( m_sequencer.data[0x04] & 0x01 )
{
- m_charA = m_plane[2] + ( ( m_sequencer.data[0x03] & 0x0c ) >> 1 ) * 0x2000;
- m_charB = m_plane[2] + ( m_sequencer.data[0x03] & 0x03 ) * 0x2000;
+ m_charA = m_plane[2] + ( ( m_sequencer.data[0x03] & 0x0c ) >> 2 ) * 0x4000;
+ m_charB = m_plane[2] + ( m_sequencer.data[0x03] & 0x03 ) * 0x4000;
}
else
{
@@ -935,8 +950,8 @@ void isa8_ega_device::change_mode()
}
/* Check for changes to the crtc input clock and number of pixels per clock */
- clock = ( ( m_misc_output & 0x0c ) ? 16257000 : 14318181 );
- pixels = ( ( m_sequencer.data[0x01] & 0x01 ) ? 8 : 9 );
+ int clock = ( ( m_misc_output & 0x0c ) ? 16257000 : 14318181 );
+ int pixels = ( ( m_sequencer.data[0x01] & 0x01 ) ? 8 : 9 );
if ( m_sequencer.data[0x01] & 0x08 )
{
@@ -950,11 +965,11 @@ void isa8_ega_device::change_mode()
}
-READ8_MEMBER( isa8_ega_device::read )
+uint8_t isa8_ega_device::read(offs_t offset)
{
uint8_t data = 0xFF;
- if ( !machine().side_effects_disabled() && ! ( m_sequencer.data[4] & 0x04 ) )
+ if ( !machine().side_effects_disabled() && !( m_graphics_controller.data[5] & 0x10 ) )
{
/* Fill read latches */
m_read_latch[0] = m_plane[0][offset & 0xffff];
@@ -972,15 +987,22 @@ READ8_MEMBER( isa8_ega_device::read )
else
{
// Read mode #0
- if ( m_sequencer.data[4] & 0x04 )
+ if ( !( m_graphics_controller.data[5] & 0x10 ) )
{
// Normal addressing mode
- data = m_plane[ m_graphics_controller.data[4] & 0x03 ][offset & 0xffff];
+ if ( m_graphics_controller.data[6] & 2 )
+ {
+ data = m_plane[ m_graphics_controller.data[4] & 0x03 ][offset & 0xfffe];
+ }
+ else
+ {
+ data = m_plane[ m_graphics_controller.data[4] & 0x03 ][offset & 0xffff];
+ }
}
else
{
// Odd/Even addressing mode
- data = m_plane[offset & 1][(offset & 0xffff) >> 1];
+ data = m_plane[offset & 1][offset & 0xfffe];
}
}
@@ -1010,11 +1032,10 @@ uint8_t isa8_ega_device::alu_op( uint8_t data, uint8_t latch_data )
}
-WRITE8_MEMBER( isa8_ega_device::write )
+void isa8_ega_device::write(offs_t offset, uint8_t data)
{
uint8_t d[4];
uint8_t alu[4];
- uint8_t target_mask = m_graphics_controller.data[8];
alu[0] =alu[1] = alu[2] = alu[3] = 0;
@@ -1057,8 +1078,7 @@ WRITE8_MEMBER( isa8_ega_device::write )
alu[1] = m_read_latch[1];
alu[2] = m_read_latch[2];
alu[3] = m_read_latch[3];
- target_mask = 0xff;
- return;
+ break;
case 2: // Write mode 2
d[0] = ( data & 0x01 ) ? 0xff : 0x00;
@@ -1090,25 +1110,25 @@ WRITE8_MEMBER( isa8_ega_device::write )
{
// Plane 0
// Bit selection
- m_plane[0][offset] = ( m_plane[0][offset] & ~ target_mask ) | ( alu[0] & target_mask );
+ m_plane[0][offset] = alu[0];
}
if ( m_sequencer.data[2] & 0x02 )
{
// Plane 1
// Bit selection
- m_plane[1][offset] = ( m_plane[1][offset] & ~ target_mask ) | ( alu[1] & target_mask );
+ m_plane[1][offset] = alu[1];
}
if ( m_sequencer.data[2] & 0x04 )
{
// Plane 2
// Bit selection
- m_plane[2][offset] = ( m_plane[2][offset] & ~ target_mask ) | ( alu[2] & target_mask );
+ m_plane[2][offset] = alu[2];
}
if ( m_sequencer.data[2] & 0x08 )
{
// Plane 3
// Bit selection
- m_plane[3][offset] = ( m_plane[3][offset] & ~ target_mask ) | ( alu[3] & target_mask );
+ m_plane[3][offset] = alu[3];
}
}
else
@@ -1117,46 +1137,43 @@ WRITE8_MEMBER( isa8_ega_device::write )
if ( offset & 1 )
{
// Odd addresses go to planes 1 and 3
-
- offset >>= 1;
+ offset &= ~1;
if ( m_sequencer.data[2] & 0x02 )
{
// Plane 1
// Bit selection
- m_plane[1][offset] = ( m_plane[1][offset] & ~ target_mask ) | ( alu[1] & target_mask );
+ m_plane[1][offset] = alu[1];
}
if ( ( m_sequencer.data[2] & 0x08 ) && ! ( m_sequencer.data[4] & 0x01 ) )
{
// Plane 3
// Bit selection
- m_plane[3][offset] = ( m_plane[3][offset] & ~ target_mask ) | ( alu[3] & target_mask );
+ m_plane[3][offset] = alu[3];
}
}
else
{
// Even addresses go to planes 0 and 2
- offset >>= 1;
-
if ( m_sequencer.data[2] & 0x01 )
{
// Plane 0
// Bit selection
- m_plane[0][offset] = ( m_plane[0][offset] & ~ target_mask ) | ( alu[0] & target_mask );
+ m_plane[0][offset] = alu[0];
}
if ( ( m_sequencer.data[2] & 0x04 ) && ! ( m_sequencer.data[4] & 0x01 ) )
{
// Plane 2
// Bit selection
- m_plane[2][offset] = ( m_plane[2][offset] & ~ target_mask ) | ( alu[2] & target_mask );
+ m_plane[2][offset] = alu[2];
}
}
}
}
-READ8_MEMBER( isa8_ega_device::pc_ega8_3X0_r )
+uint8_t isa8_ega_device::pc_ega8_3X0_r(offs_t offset)
{
int data = 0xff;
@@ -1193,12 +1210,9 @@ READ8_MEMBER( isa8_ega_device::pc_ega8_3X0_r )
return data;
}
-WRITE8_MEMBER( isa8_ega_device::pc_ega8_3X0_w )
+void isa8_ega_device::pc_ega8_3X0_w(offs_t offset, uint8_t data)
{
- if ( VERBOSE_EGA )
- {
-// logerror("pc_ega_3X0_w: offset = %02x, data = %02x\n", offset, data );
- }
+ LOGSETUP("%s: offset = %02x, data = %02x\n", FUNCNAME, offset, data );
switch ( offset )
{
@@ -1229,44 +1243,41 @@ WRITE8_MEMBER( isa8_ega_device::pc_ega8_3X0_w )
-READ8_MEMBER(isa8_ega_device::pc_ega8_3b0_r )
+uint8_t isa8_ega_device::pc_ega8_3b0_r(offs_t offset)
{
- return ( m_misc_output & 0x01 ) ? 0xFF : pc_ega8_3X0_r(space, offset);
+ return ( m_misc_output & 0x01 ) ? 0xFF : pc_ega8_3X0_r(offset);
}
-READ8_MEMBER(isa8_ega_device::pc_ega8_3d0_r )
+uint8_t isa8_ega_device::pc_ega8_3d0_r(offs_t offset)
{
- return ( m_misc_output & 0x01 ) ? pc_ega8_3X0_r(space, offset) : 0xFF;
+ return ( m_misc_output & 0x01 ) ? pc_ega8_3X0_r(offset) : 0xFF;
}
-WRITE8_MEMBER(isa8_ega_device::pc_ega8_3b0_w )
+void isa8_ega_device::pc_ega8_3b0_w(offs_t offset, uint8_t data)
{
if ( ! ( m_misc_output & 0x01 ) )
{
- pc_ega8_3X0_w( space, offset, data );
+ pc_ega8_3X0_w( offset, data );
}
}
-WRITE8_MEMBER(isa8_ega_device::pc_ega8_3d0_w )
+void isa8_ega_device::pc_ega8_3d0_w(offs_t offset, uint8_t data)
{
if ( m_misc_output & 0x01 )
{
- pc_ega8_3X0_w( space, offset, data );
+ pc_ega8_3X0_w( offset, data );
}
}
-READ8_MEMBER(isa8_ega_device::pc_ega8_3c0_r )
+uint8_t isa8_ega_device::pc_ega8_3c0_r(offs_t offset)
{
int data = 0xff;
- if ( VERBOSE_EGA )
- {
-// logerror("pc_ega_3c0_r: offset = %02x\n", offset );
- }
+ LOGR("%s: offset = %02x\n", FUNCNAME, offset );
switch ( offset )
{
@@ -1281,7 +1292,7 @@ READ8_MEMBER(isa8_ega_device::pc_ega8_3c0_r )
data = ( data & 0x0f );
data |= ( ( m_feature_control & 0x03 ) << 5 );
- data |= ( m_vsync ? 0x00 : 0x80 );
+ data |= ( m_irq ? 0x00 : 0x80 );
data |= ( ( ( dips >> ( ( ( m_misc_output & 0x0c ) >> 2 ) ) ) & 0x01 ) << 4 );
}
break;
@@ -1302,7 +1313,7 @@ READ8_MEMBER(isa8_ega_device::pc_ega8_3c0_r )
}
-WRITE8_MEMBER(isa8_ega_device::pc_ega8_3c0_w )
+void isa8_ega_device::pc_ega8_3c0_w(offs_t offset, uint8_t data)
{
static const uint8_t ar_reg_mask[0x20] =
{
@@ -1322,10 +1333,7 @@ WRITE8_MEMBER(isa8_ega_device::pc_ega8_3c0_w )
};
int index;
- if ( VERBOSE_EGA )
- {
-// logerror("pc_ega_3c0_w: offset = %02x, data = %02x\n", offset, data );
- }
+ LOGSETUP("%s: offset = %02x, data = %02x\n", FUNCNAME, offset, data );
switch ( offset )
{
@@ -1339,7 +1347,7 @@ WRITE8_MEMBER(isa8_ega_device::pc_ega8_3c0_w )
{
index = m_attribute.index & 0x1F;
- logerror("AR%02X = 0x%02x\n", index, data );
+ LOGSETUP(" - AR%02X = 0x%02x\n", index, data );
/* Clear unused bits */
m_attribute.data[ index ] = data & ar_reg_mask[ index ];
@@ -1354,7 +1362,7 @@ WRITE8_MEMBER(isa8_ega_device::pc_ega8_3c0_w )
m_attribute.index_write ^= 0x01;
break;
- /* Misccellaneous Output */
+ /* Miscellaneous Output */
case 2:
m_misc_output = data;
install_banks();
@@ -1368,7 +1376,7 @@ WRITE8_MEMBER(isa8_ega_device::pc_ega8_3c0_w )
case 5:
index = m_sequencer.index & 0x07;
- logerror("SR%02X = 0x%02x\n", index & 0x07, data );
+ LOGSETUP(" - SR%02X = 0x%02x\n", index & 0x07, data );
/* Clear unused bits */
m_sequencer.data[ index ] = data & sr_reg_mask[ index ];
@@ -1390,7 +1398,7 @@ WRITE8_MEMBER(isa8_ega_device::pc_ega8_3c0_w )
case 15:
index = m_graphics_controller.index & 0x0F;
- logerror("GR%02X = 0x%02x\n", index, data );
+ LOGSETUP(" - GR%02X = 0x%02x\n", index, data );
/* Clear unused bits */
m_graphics_controller.data[ index ] = data & gr_reg_mask[ index ];
diff --git a/src/devices/bus/isa/ega.h b/src/devices/bus/isa/ega.h
index 4334604b9a8..82069fe272e 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"
//**************************************************************************
@@ -23,47 +24,47 @@ public:
// construction/destruction
isa8_ega_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
- DECLARE_READ8_MEMBER(read);
- DECLARE_WRITE8_MEMBER(write);
- DECLARE_READ8_MEMBER(pc_ega8_3b0_r);
- DECLARE_WRITE8_MEMBER(pc_ega8_3b0_w);
- DECLARE_READ8_MEMBER(pc_ega8_3c0_r);
- DECLARE_WRITE8_MEMBER(pc_ega8_3c0_w);
- DECLARE_READ8_MEMBER(pc_ega8_3d0_r);
- DECLARE_WRITE8_MEMBER(pc_ega8_3d0_w);
+ uint8_t read(offs_t offset);
+ void write(offs_t offset, uint8_t data);
+ uint8_t pc_ega8_3b0_r(offs_t offset);
+ void pc_ega8_3b0_w(offs_t offset, uint8_t data);
+ uint8_t pc_ega8_3c0_r(offs_t offset);
+ void pc_ega8_3c0_w(offs_t offset, uint8_t data);
+ uint8_t pc_ega8_3d0_r(offs_t offset);
+ void pc_ega8_3d0_w(offs_t offset, uint8_t data);
- CRTC_EGA_ROW_UPDATE(pc_ega_graphics);
- CRTC_EGA_ROW_UPDATE(pc_ega_text);
+ CRTC_EGA_PIXEL_UPDATE(pc_ega_graphics);
+ CRTC_EGA_PIXEL_UPDATE(pc_ega_text);
protected:
isa8_ega_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_start() override ATTR_COLD;
+ virtual void device_reset() override ATTR_COLD;
// 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 void device_add_mconfig(machine_config &config) override ATTR_COLD;
+ virtual const tiny_rom_entry *device_rom_region() const override ATTR_COLD;
+ virtual ioport_constructor device_input_ports() const override ATTR_COLD;
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_ROW_UPDATE(ega_update_row);
+ CRTC_EGA_PIXEL_UPDATE(ega_update_row);
public:
required_device<crtc_ega_device> m_crtc_ega;
void install_banks();
void change_mode();
- DECLARE_WRITE8_MEMBER(pc_ega8_3X0_w);
- DECLARE_READ8_MEMBER(pc_ega8_3X0_r);
+ void pc_ega8_3X0_w(offs_t offset, uint8_t data);
+ uint8_t pc_ega8_3X0_r(offs_t offset);
/* Video memory and related variables */
std::unique_ptr<uint8_t[]> m_vram;
@@ -104,8 +105,10 @@ public:
uint8_t m_vsync;
uint8_t m_vblank;
uint8_t m_display_enable;
+ 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
new file mode 100644
index 00000000000..768975a3ca0
--- /dev/null
+++ b/src/devices/bus/isa/eis_hgb107x.cpp
@@ -0,0 +1,603 @@
+// license:BSD-3-Clause
+// copyright-holders: Joakim Larsson Edström
+/*****************************************************************************
+
+ Ericsson PC Monochrome HR Graphics Board 1070
+
+******************************************************************************/
+
+/* PCB layouts and assembly years from online pictures and physical unit.
+ Ericsson - marked SPVT02 8301 60 53-10, assembled in 1985 indicated by chip dates
+ +--------------------------------------------------------------------------------------+ ___
+ | IC1 IC2 IC3 IC4 IC5 +-IC15--EPROM-+ IC6 IC7 IC8 S1 ||
+ | |8363 65 14-80| ||
+ | IC9 IC10 IC11 IC12 IC13 IC14|CG 50821 A64 |+------------------++-IC24 EPROM--+ ||
+ | +-------------+| CRTC HD46505SP-1 ||10-40VP | ||
+ | IC16 IC17 IC18 IC19 IC20 IC21 IC22 | IC23 HD68A45SP ||402 28 A19 | J4|| not
+ | +------------------++-------------+ || mounted
+ | IC25 IC26 IC27 IC28 IC29 IC30 IC31 IC32 IC33 IC34 ||
+ | O-|__
+ | IC35 IC36 IC37 IC38 IC39 IC40 IC41 IC42 IC43 IC44 || |
+ | ||DB15
+ | IC45 IC46 IC47 IC48 IC49 IC50 IC51 IC52 IC53 IC54 || |
+ | ||__|
+ | IC55 IC56 IC57 IC58 IC59 IC60 IC61 IC62 IC63 IC64 O-|
+ | J1A ||
+ | IC65 IC66 IC67 IC68 IC69 IC70 IC71 IC72 +--------------------------------------------+|
+ +-----------------------------------------+ ||||||||| ||||||||||||||||||||||||| |
+ I85565 A85571 (labels) |
+ |
+
+ IC's (from photos)
+ ------------------------------------------------------------------------------
+ IC1 74F109 IC26 74F86 IC51 TMS4416-15NL 4 x 16Kbits DRAM
+ IC2 74LS393 IC27 74LS08 IC52 74ALS574
+ IC3 74F64 IC28 74F153 IC53 74LS138
+ IC4 74ALS299 IC29 74LS174 IC54 74F86
+ IC5 74LS375 IC30 74LS374 IC55 74F109
+ IC6 74LS151 IC31 74LS374 IC56 74F32
+ IC7 74LS153 IC32 74ALS574 IC57 74F109
+ IC8 74LS389? IC33 74LS08 IC58 74F00?
+ IC9 74F02 IC34 74LS245 IC59 74LS244
+ IC10 74ALS109 IC35 74F10? IC60 TMS4416-15NL 4 x 16Kbits DRAM
+ IC11 Crystal 17.040MHz IC36 74LS02 IC61 TMS4416-15NL 4 x 16Kbits DRAM
+ IC12 74F64 IC37 74LS00 IC62 74ALS574
+ IC13 74ALS299 IC38 74F374 IC63 74LS138
+ IC14 PAL? 10-70ART40101 IC39 74LS125 IC64 74LS245
+ IC15 EPROM 8363 65 14-80 CG 50821 A64 IC40 74LS244 IC65 74LS00
+ IC16 Crystal 19.170MHz IC41 74LS244 IC66 74LS02
+ IC17 74LS10 IC42 74LS574 IC67 74LS51
+ IC18 74F08 IC43 74LS32 IC68 74LS04
+ IC19 74ALS574 IC44 MC10124 - TTL to MECL converter IC69 74LS153
+ IC20 74LS299 IC45 74LS109 IC70 74LS109
+ IC21 74LS273 IC46 74LS00 IC71 74LS138
+ IC22 74ALS574 IC47 74F194 IC72 74LS139
+ IC23 CRTC HD46505SP,HD68A45SP IC48 74F04
+ IC24 EPROM 2764, 10-40 VP 402 28 A19 IC49 74LS174
+ IC25 74ALS109 IC50 TMS4416-15NL 4 x 16Kbits DRAM
+
+ General description
+ -------------------
+ The PCB has a 2 bit DIP switch S1 and a DB15 non standard video connector. There is also an unsoldered J4 connector
+ above the DB15 but no hole prepared for a connector in the plate. Above the J4 connector there is a two pin PCB connector
+ that probably receives the power for the monitor for the DB15 from the PSU.
+
+ Just below IC65 and IC66 there are two labels saying "I 85565" and "A E85571" respectively
+
+ Video cable, card DB15 <---> monitor DB25
+ ---------------------------------------------------
+ Ericsson 2 +VS 4 Ericsson
+ Monochrome 3 VS return 2 Monochrome HR
+ HR Graphics 10 +VS 17 Monitors 3111 (Amber) or
+ Board 1070 11 VS return 15 3712/3715 (Black & White)
+ 4 VSYNC 6
+ 12 VSYNC 19
+ 5 HSYNC 7
+ 13 HSYNC 20
+ 6 High intensity 8
+ 14 High intensity 21
+ 7 Video 9
+ 15 Video 22
+ 8 GND 11
+
+ This board is normaly used with an Ericsson monitor due to the non standard connector.
+ Trivia: https://www.pinterest.se/pin/203084264425177097/
+ */
+
+#include "emu.h"
+#include "eis_hgb107x.h"
+
+#include "screen.h"
+
+#define LOG_READ (1U << 1)
+#define LOG_SETUP (1U << 2)
+#define LOG_ROW (1U << 3)
+#define LOG_MODE (1U << 4)
+#define LOG_CHRG (1U << 5)
+#define LOG_STAT (1U << 6)
+
+//#define VERBOSE (LOG_MODE|LOG_SETUP|LOG_ROW)
+//#define LOG_OUTPUT_STREAM std::cout
+
+#include "logmacro.h"
+
+#define LOGR(...) LOGMASKED(LOG_READ, __VA_ARGS__)
+#define LOGSETUP(...) LOGMASKED(LOG_SETUP, __VA_ARGS__)
+#define LOGROW(...) LOGMASKED(LOG_ROW, __VA_ARGS__)
+#define LOGMODE(...) LOGMASKED(LOG_MODE, __VA_ARGS__)
+#define LOGCHRG(...) LOGMASKED(LOG_CHRG, __VA_ARGS__)
+#define LOGSTAT(...) LOGMASKED(LOG_STAT, __VA_ARGS__)
+
+#ifdef _MSC_VER
+#define FUNCNAME __func__
+#else
+#define FUNCNAME __PRETTY_FUNCTION__
+#endif
+
+#define MC6845_NAME "mc6845"
+
+enum
+{
+ MDA_TEXT_INTEN = 0,
+ MDA_TEXT_BLINK,
+ MDA_LOWRES_TEXT_INTEN,
+ MDA_LOWRES_TEXT_BLINK
+};
+
+#define EPC_MDA_SCREEN "epc_mda_screen" // TODO: use a device finder reference instead
+
+ROM_START( epc )
+ ROM_REGION(0x2000,"chargen", 0)
+ ROM_LOAD("8363_65_14_80_cg_50821_a64.bin", 0x00000, 0x2000, CRC(be709786) SHA1(38ab26224bbe66bbe2bb2ccac29b41cbf78bdbf8))
+ //ROM_LOAD("10_40_vp_402_28_ic_24_a19.bin", 0x00000, 0x2000, CRC(2aa53b92) SHA1(87051a037249eb631d7d2191bc0e925125c60f39))
+ROM_END
+
+//**************************************************************************
+// GLOBAL VARIABLES
+//**************************************************************************
+DEFINE_DEVICE_TYPE(ISA8_EPC_MDA, isa8_epc_mda_device, "isa_epc_mda", "Ericsson PC Monochrome HR Graphics Board 1070")
+
+//-------------------------------------------------
+// device_add_mconfig - add device configuration
+//-------------------------------------------------
+/* There are two crystals on the board: 19.170Mhz and 17.040MHz TODO: verify use */
+/* Text modes uses 720x400 base resolution and the Graphics modes 320/640x200/400 */
+/* This matches the difference between the crystals so we assume this for now */
+void isa8_epc_mda_device::device_add_mconfig(machine_config &config)
+{
+ screen_device &screen(SCREEN(config, EPC_MDA_SCREEN, SCREEN_TYPE_RASTER));
+ screen.set_raw(XTAL(19'170'000) / 4, 720, 0, 720, 400, 0, 400);
+ screen.set_screen_update(MC6845_NAME, FUNC(mc6845_device::screen_update));
+
+ HD6845S(config, m_crtc, XTAL(19'170'000) / 16); // clock and divider are guesswork
+ m_crtc->set_screen(EPC_MDA_SCREEN);
+ m_crtc->set_show_border_area(false);
+ m_crtc->set_char_width(8);
+
+ m_crtc->set_update_row_callback(FUNC(isa8_epc_mda_device::crtc_update_row));
+ m_crtc->out_hsync_callback().set(FUNC(isa8_epc_mda_device::hsync_changed));
+ m_crtc->out_vsync_callback().set(FUNC(isa8_epc_mda_device::vsync_changed));
+}
+
+//-------------------------------------------------
+// rom_region - device-specific ROM region
+//-------------------------------------------------
+const tiny_rom_entry *isa8_epc_mda_device::device_rom_region() const
+{
+ return ROM_NAME( epc );
+}
+
+//**************************************************************************
+// LIVE DEVICE
+//**************************************************************************
+
+//-------------------------------------------------
+// isa8_epc_mda_device - constructor
+//-------------------------------------------------
+isa8_epc_mda_device::isa8_epc_mda_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) :
+ isa8_epc_mda_device(mconfig, ISA8_EPC_MDA, tag, owner, clock)
+{
+}
+
+isa8_epc_mda_device::isa8_epc_mda_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_crtc(*this, MC6845_NAME),
+ m_soft_chr_gen(nullptr),
+ m_s1(*this, "S1"),
+ m_color_mode(0),
+ m_mode_control2(0),
+ m_screen(*this, EPC_MDA_SCREEN),
+ m_io_monitor(*this, "MONITOR"),
+ m_chargen(*this, "chargen"),
+ m_installed(false),
+ m_framecnt(0),
+ m_mode_control(0),
+ m_update_row_type(-1),
+ m_chr_gen(nullptr),
+ m_vsync(0),
+ m_hsync(0),
+ m_pixel(0)
+{
+}
+
+//-------------------------------------------------
+// device_start - device-specific startup
+//-------------------------------------------------
+
+void isa8_epc_mda_device::device_start()
+{
+ /* Palette for use with the Ericsson Amber Monochrome HR CRT monitor 3111, P3 phospor 602nm 255,183, 0 */
+ m_3111_pal[0] = rgb_t( 0, 0, 0); // black
+ m_3111_pal[1] = rgb_t( 143, 103, 0); // dim
+ m_3111_pal[2] = rgb_t( 191, 137, 0); // normal
+ m_3111_pal[3] = rgb_t( 255, 183, 0); // bright
+
+ /* Palette for use with the Ericsson B&W Monochrome HR CRT monitor 3712/3715 */
+ m_371x_pal[0] = rgb_t( 0, 0, 0); // black
+ m_371x_pal[1] = rgb_t( 143, 143, 143); // dim
+ m_371x_pal[2] = rgb_t( 191, 191, 191); // normal
+ m_371x_pal[3] = rgb_t( 255, 255, 255); // bright
+
+ /* Init a default palette */
+ m_pal = &m_3111_pal; // In case screen starts rendering before device_reset where we read the settings
+ m_videoram.resize(0x8000);
+ set_isa_device();
+ m_installed = false;
+ m_hd6845s = subdevice<hd6845s_device>(MC6845_NAME);
+}
+
+void isa8_epc_mda_device::device_reset()
+{
+ m_framecnt = 0;
+ m_mode_control = 0;
+ m_vsync = 0;
+ m_hsync = 0;
+ m_pixel = 0;
+
+ m_color_mode = m_s1->read();
+ LOGSETUP("%s: m_color_mode:%02x\n", FUNCNAME, m_color_mode);
+ m_pal = (m_io_monitor-> read() & 1) == 1 ? &m_371x_pal : &m_3111_pal;
+ m_vmode = 0;
+
+ if (m_installed == false)
+ {
+ m_isa->install_device(0x3b0, 0x3bf, read8sm_delegate(*this, FUNC(isa8_epc_mda_device::io_read)), write8sm_delegate(*this, FUNC(isa8_epc_mda_device::io_write)));
+ m_isa->install_bank(0xb0000, 0xb7fff, &m_videoram[0]); // Monochrome emulation mode VRAM address
+
+ // This check allows a color monitor adapter to be installed at this address range if color emulation is disabled
+ if (m_color_mode & 1)
+ {
+ m_isa->install_device(0x3d0, 0x3df, read8sm_delegate(*this, FUNC(isa8_epc_mda_device::io_read)), write8sm_delegate(*this, FUNC(isa8_epc_mda_device::io_write)));
+ m_isa->install_bank(0xb8000, 0xbffff, &m_videoram[0]); // Color emulation mode VRAM address, but same 32KB areas as there are only this amount on the board
+ }
+ m_installed = true;
+ }
+}
+
+/*
+ * Register Address table from the manual
+ * Ericsson name MDA mode CGA mode Standard name
+ *-------------------------------------------------------------------------------
+ * 6845 Address Registers 0x3b4 0x3d4 wo CRT Index reg
+ * 6845 Data Registers 0x3b5 0x3d5 wo CRT Data reg
+ * Mode Register 1 0x3b8 0x3d8 rw MDA/CGA mode reg (bit 0,1 & 4 incompatible)
+ * Mode Register 2 0x3bf 0x3df rw CRT/CPU page reg (incompatible w PCjr only)
+ * Status Register 0x3ba 0x3da r CGA/MDA status reg (incompatible)
+ * w EGA/VGA feature ccontrol reg (not used by this board)
+ */
+void isa8_epc_mda_device::io_write(offs_t offset, uint8_t data)
+{
+ LOG("%s: %04x <- %02x\n", FUNCNAME, offset, data);
+ switch( offset )
+ {
+ case 0x04:
+ //LOGSETUP(" - HD6845S address write\n");
+ m_hd6845s->address_w( data );
+ break;
+ case 0x05:
+ //LOGSETUP(" - HD6845S register write\n");
+ m_hd6845s->register_w( data );
+ break;
+ case 0x08: // Mode 1 reg
+ LOGMODE(" - Mode register 1 write: %02x\n", data);
+ LOGMODE(" MSB attribute: %s\n", (data & 0x20) == 0 ? "intensity" : "blink");
+ LOGMODE(" Horizontal px: %s\n", (data & 0x10) == 0 ? "320/LR" : "640/HR");
+ LOGMODE(" Video : %s\n", (data & 0x08) == 0 ? "Disabled" : "Enabled");
+ LOGMODE(" Mode : %s\n", (data & 0x02) == 0 ? "Text" : "Graphics");
+ LOGMODE(" Text columns : %d\n", (data & 0x01) == 0 ? 40 : 80);
+ m_mode_control = data;
+ m_vmode &= ~(VM_GRAPH | VM_COLS80 | VM_HOR640);
+ m_vmode |= ((m_mode_control & 0x01) ? VM_COLS80 : 0);
+ m_vmode |= ((m_mode_control & 0x02) ? VM_GRAPH : 0);
+ m_vmode |= ((m_mode_control & 0x10) ? VM_HOR640 : 0);
+ m_update_row_type = ((data & 0x20) == 0 ? MDA_LOWRES_TEXT_INTEN : MDA_LOWRES_TEXT_BLINK);
+ {
+ rectangle rect(0, get_xres() - 1, 0, get_yres() -1);
+ m_screen->configure(get_xres(), get_yres(), rect, HZ_TO_ATTOSECONDS(50));
+ }
+ LOGMODE("Video Mode:%02x\n\n", m_vmode);
+ break;
+ case 0x0f: // Mode 2 reg
+ LOGMODE(" - Mode register 2 write: %02x\n", data);
+ LOGMODE(" Vertical px : %s\n", (data & MR2_VER400) == 0 ? "200" : "400");
+ LOGMODE(" Character set: %s\n", (data & MR2_CHRSET) == 0 ? "0" : "1");
+ LOGMODE(" Emulated : %s\n", (data & MR2_COLEMU) == 0 ? "Color" : "Monochrome");
+ m_mode_control2 = data;
+ m_vmode &= ~(VM_MONO | VM_VER400);
+ m_vmode |= ((m_mode_control2 & 0x04) ? VM_MONO : 0);
+ m_vmode |= ((m_mode_control2 & 0x80) ? VM_VER400 : 0);
+ {
+ rectangle rect(0, get_xres() - 1, 0, get_yres() -1);
+ m_screen->configure(get_xres(), get_yres(), rect, HZ_TO_ATTOSECONDS(50));
+ }
+ LOGMODE("Video Mode:%02x\n\n", m_vmode);
+ break;
+ default:
+ LOG("EPC MDA: io_write at wrong offset:%02x\n", offset);
+ }
+}
+
+uint8_t isa8_epc_mda_device::io_read(offs_t offset)
+{
+ LOG("%s: %04x <- ???\n", FUNCNAME, offset);
+ int data = 0xff;
+ switch( offset )
+ {
+ case 0x04:
+ LOGR(" - hd6845s address read\n");
+ break;
+ case 0x05:
+ LOGR(" - hd6845s register read\n");
+ data = m_hd6845s->register_r();
+ break;
+ case 0x08: // Mode 1 reg
+ data = m_mode_control;
+ LOGMODE(" - Mode register 1 read: %02x\n", data);
+ break;
+ case 0x0a: // Status reg: b7-6=00 board ID; b3 vert retrace; b0 horiz retrace; b5,4,2,1 unused
+ data = (m_vsync != 0 ? 0x08 : 0x00) | (m_hsync != 0 ? 0x01 : 0x00);
+ LOGSTAT(" - Status register read: %02x\n", data);
+ break;
+ case 0x0f: // Mode 2 reg
+ data = m_mode_control2;
+ LOGMODE(" - Mode register 2 read: %02x\n", data);
+ break;
+ default:
+ LOG("EPC MDA: io_read at wrong offset:%02x\n", offset);
+ logerror("EPC MDA: io_read at wrong offset:%02x\n", offset);
+ }
+ LOG(" !!!: %04x <- %02x\n", offset, data);
+ return data;
+}
+
+void isa8_epc_mda_device::hsync_changed(int state)
+{
+ m_hsync = state ? 1 : 0;
+}
+
+
+void isa8_epc_mda_device::vsync_changed(int state)
+{
+ m_vsync = state ? 0x80 : 0;
+ if ( state )
+ {
+ m_framecnt++;
+ }
+}
+
+
+/*
+ * rW MDA mode control register (see #P138)
+ */
+void isa8_epc_mda_device::mode_control_w(uint8_t data)
+{
+ m_mode_control = data;
+
+ switch( m_mode_control & 0x2a )
+ {
+ case 0x08:
+ m_update_row_type = MDA_TEXT_INTEN;
+ break;
+ case 0x28:
+ m_update_row_type = MDA_TEXT_BLINK;
+ break;
+ default:
+ m_update_row_type = -1;
+ }
+}
+
+
+/* R- CRT status register (see #P139)
+ * (EGA/VGA) input status 1 register
+ * 7 HGC vertical sync in progress
+ * 6-4 adapter 000 hercules
+ * 001 hercules+
+ * 101 hercules InColor
+ * else unknown
+ * 3 pixel stream (0 black, 1 white)
+ * 2-1 reserved
+ * 0 horizontal drive enable
+ */
+uint8_t isa8_epc_mda_device::status_r()
+{
+ // Faking pixel stream here
+ if (!machine().side_effects_disabled())
+ m_pixel++;
+
+ return 0xF0 | (m_pixel & 0x08) | m_hsync;
+}
+
+inline int isa8_epc_mda_device::get_xres()
+{
+ return (m_vmode & VM_GRAPH) ? ( (m_vmode & VM_HOR640) ? 640 : 320 ) : 720;
+}
+
+inline int isa8_epc_mda_device::get_yres()
+{
+ return (m_vmode & VM_GRAPH) ? ( (m_vmode & VM_VER400) ? 400 : 200 ) : 400;
+}
+
+MC6845_UPDATE_ROW(isa8_epc_mda_device::crtc_update_row)
+{
+ // Get som debug data from a couple of rows now and then
+ if ( y < (16 * 0 + 0x20) && (m_framecnt & 0xff) == 0 )
+ {
+ LOGROW("%11.6f %s\n - y:%d chr_base:%d ra:%d ma:%d x_count:%d\n", machine().time().as_double(), FUNCNAME,
+ y, y % 16, ra, ma, x_count);
+ }
+
+ // Video Off handling
+ if ((m_mode_control & MR1_VIDEO) == 0)
+ {
+ for (int i = 0; i < get_xres(); i++)
+ {
+ bitmap.pix(y, i) = rgb_t::black();
+ }
+ }
+
+ // Graphic modes using only pixeldata, soft fonts are 8x8 or 8x16 but this is transparant to the code
+ else if ((m_vmode & VM_GRAPH) != 0)
+ {
+ logerror("EPC MDA: graphic modes not supported yet\n");
+ }
+
+ // Text modes using one of two 9x16 fonts in character rom
+ else
+ {
+ uint32_t *p = &bitmap.pix(y);
+ uint16_t chr_base = ra;
+
+ // Adjust row pointer if in monochrome text mode as we insert two scanlines per row of characters (see below)
+ if (m_vmode & VM_MONO)
+ {
+ p = &bitmap.pix((y / 14) * 16 + y % 14);
+ }
+
+ // Loop over each character in a row
+ for ( int i = 0; i < x_count; i++ )
+ {
+ uint16_t offset = ( ( ma + i ) << 1 ) & 0x0FFF;
+ uint8_t chr = m_videoram[ offset ];
+ uint8_t attr = m_videoram[ offset + 1 ];
+ uint8_t data = m_chargen[ ((m_mode_control2 & MR2_CHRSET) ? 0x1000 : 0) + chr_base + chr * 16];
+
+ // Default to light text on dark background
+ uint8_t fg = 2;
+ uint8_t bg = 0;
+
+ if (y == 0 && i == 0) LOGCHRG(" - Offset: %04x Chr: '%c'[%02x] Attr: %02x Chr_base: %04x\n", offset, chr, chr, attr, chr_base);
+
+ // Prepare some special monochrome emulation cases
+ if ( m_vmode & VM_MONO)
+ {
+ // Handle invisible characters
+ if ( (attr & (ATTR_FOREG | ATTR_BACKG)) == 0 )
+ {
+ data = 0x00;
+ }
+ // Handle reversed characters
+ else if ( (attr & (ATTR_BACKG)) == ATTR_BACKG )
+ {
+ fg = 0;
+ bg = 2;
+ }
+ }
+ else // prepare some special color emulation cases
+ {
+ // Handle invisible characters
+ if ( (attr & (ATTR_FOREG)) == ((attr & ATTR_BACKG) >> 4))
+ {
+ data = 0x00;
+ }
+ // Handle reversed characters
+ else if ( (attr & ATTR_BACKG) == ATTR_BACKG ||
+ (attr & ATTR_FOREG) == 0 )
+ {
+ fg = 0;
+ bg = 2;
+ }
+ }
+
+ // Handle intense foreground
+ if ((attr & ATTR_INTEN) != 0 && fg == 2)
+ {
+ fg = 3;
+ }
+
+ // Handle intense background if blinking is disabled
+ if ((m_mode_control & MR1_BLINK) == 0 &&
+ (attr & ATTR_BLINK) != 0 && bg == 2)
+ {
+ bg = 3;
+ }
+
+ // Handle cursor and blinks
+ if ( i == (cursor_x))
+ {
+ if ( m_framecnt & 0x08 )
+ {
+ data = 0xFF;
+ }
+ }
+ else
+ {
+ if ( (m_mode_control & MR1_BLINK) &&
+ ( attr & ATTR_BLINK ) && ( m_framecnt & 0x10 ) )
+ {
+ data = 0x00;
+ }
+ }
+
+ *p = (*m_pal)[( data & 0x80 ) ? fg : bg]; p++;
+ *p = (*m_pal)[( data & 0x40 ) ? fg : bg]; p++;
+ *p = (*m_pal)[( data & 0x20 ) ? fg : bg]; p++;
+ *p = (*m_pal)[( data & 0x10 ) ? fg : bg]; p++;
+ *p = (*m_pal)[( data & 0x08 ) ? fg : bg]; p++;
+ *p = (*m_pal)[( data & 0x04 ) ? fg : bg]; p++;
+ *p = (*m_pal)[( data & 0x02 ) ? fg : bg]; p++;
+ *p = (*m_pal)[( data & 0x01 ) ? fg : bg]; p++;
+ if (chr >= 0xc0 && chr <= 0xdf)
+ *p = (*m_pal)[( data & 0x01 ) ? fg : bg]; // 9th pixel col is a copy of col 8
+ else
+ *p = (*m_pal)[bg]; // 9th pixel col is just background
+ p++;
+
+ // Insert two extra scanlines in monochrome text mode to get 400 lines and support underline, needs verification on actual hardware.
+ // The technical manual says that the character box is 9x16 pixels in 80x25 character mode which equals 720x400 resolution but the
+ // CRTC calls back for only 350 lines. Assumption is that there is hardware adding these lines and that handles underlining. In color
+ // emulation text mode all 400 lines are called for in 80x25 and this mode does not support underlining according to the technical manual
+ if ( ra == 13 && (m_vmode & VM_MONO) )
+ {
+ uint16_t row = ra + (y / 14) * 16; // Calculate correct row number including the extra 2 lines per each row of characters
+ for ( int j = 0; j < 9; j++)
+ {
+ if (chr >= 0xb3 && chr <= 0xdf) // Handle the meta graphics characters
+ {
+ bitmap.pix(row + 1, j + i * 9) = (*m_pal)[( data & (0x80 >> j) ) || (j == 8 && (data & 0x01)) ? fg : bg];
+ bitmap.pix(row + 2, j + i * 9) = (*m_pal)[( data & (0x80 >> j) ) || (j == 8 && (data & 0x01)) ? fg : bg];
+ }
+ else
+ {
+ // Handle underline
+ bitmap.pix(row + 1, j + i * 9) =(*m_pal)[( attr & ATTR_FOREG ) == ATTR_ULINE ? fg : bg];
+ bitmap.pix(row + 2, j + i * 9) = (*m_pal)[bg];
+ }
+ }
+ }
+ }
+ }
+}
+
+//--------------------------------------------------------------------
+// Port definitions
+//--------------------------------------------------------------------
+static INPUT_PORTS_START( epc_mda )
+ PORT_START( "S1" )
+ PORT_DIPNAME( 0x01, 0x00, "Color emulation") PORT_DIPLOCATION("S1:1")
+ PORT_DIPSETTING( 0x00, "Disabled" )
+ PORT_DIPSETTING( 0x01, "Enabled" )
+ PORT_DIPUNUSED_DIPLOC(0x02, 0x02, "S1:2")
+
+ PORT_START( "MONITOR" )
+ PORT_CONFNAME( 0x01, 0x00, "Ericsson Monochrome HR Monitors") PORT_CHANGED_MEMBER(DEVICE_SELF, FUNC(isa8_epc_mda_device::monitor_changed), 0)
+ PORT_CONFSETTING( 0x00, "Amber 3111")
+ PORT_CONFSETTING( 0x01, "B&W 3712/3715")
+INPUT_PORTS_END
+
+INPUT_CHANGED_MEMBER( isa8_epc_mda_device::monitor_changed )
+{
+ if ((m_io_monitor->read() & 1) == 1)
+ {
+ m_pal = &m_371x_pal;
+ }
+ else
+ {
+ m_pal = &m_3111_pal;
+ }
+}
+
+ioport_constructor isa8_epc_mda_device::device_input_ports() const
+{
+ return INPUT_PORTS_NAME( epc_mda );
+}
diff --git a/src/devices/bus/isa/eis_hgb107x.h b/src/devices/bus/isa/eis_hgb107x.h
new file mode 100644
index 00000000000..dc48dce786c
--- /dev/null
+++ b/src/devices/bus/isa/eis_hgb107x.h
@@ -0,0 +1,112 @@
+// license:BSD-3-Clause
+// copyright-holders: Joakim Larsson Edström
+#ifndef MAME_BUS_ISA_EIS_HGB107X_H
+#define MAME_BUS_ISA_EIS_HGB107X_H
+
+#pragma once
+
+#include "isa.h"
+#include "video/mc6845.h"
+#include "emupal.h"
+#include "screen.h"
+
+//**************************************************************************
+// TYPE DEFINITIONS
+//**************************************************************************
+
+class isa8_epc_mda_device : public device_t, public device_isa8_card_interface
+{
+public:
+ // construction/destruction
+ isa8_epc_mda_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);
+ uint8_t status_r();
+ void mode_control_w(uint8_t data);
+ void hsync_changed(int state);
+ void vsync_changed(int state);
+
+ /* Monitor */
+ DECLARE_INPUT_CHANGED_MEMBER(monitor_changed);
+
+protected:
+ isa8_epc_mda_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 ATTR_COLD;
+ virtual void device_reset() override ATTR_COLD;
+
+ // optional information overrides
+ virtual void device_add_mconfig(machine_config &config) override ATTR_COLD;
+ virtual const tiny_rom_entry *device_rom_region() const override ATTR_COLD;
+ virtual ioport_constructor device_input_ports() const override ATTR_COLD;
+
+private:
+ inline int get_xres();
+ inline int get_yres();
+
+ enum {
+ VM_COLS80 = 0x01,
+ VM_GRAPH = 0x02,
+ VM_HOR640 = 0x04,
+ VM_MONO = 0x08,
+ VM_VER400 = 0x10
+ };
+
+ enum {
+ MR1_COLS80 = 0x01,
+ MR1_GRAPH = 0x02,
+ MR1_VIDEO = 0x08,
+ MR1_HOR640 = 0x10,
+ MR1_BLINK = 0x20
+ };
+
+ enum {
+ MR2_COLEMU = 0x04,
+ MR2_CHRSET = 0x40,
+ MR2_VER400 = 0x80
+ };
+
+ enum {
+ ATTR_BLINK = 0x80,
+ ATTR_BACKG = 0x70,
+ ATTR_INTEN = 0x08,
+ ATTR_FOREG = 0x07,
+ ATTR_ULINE = 0x01,
+ };
+
+ required_device<mc6845_device> m_crtc;
+ MC6845_UPDATE_ROW( crtc_update_row );
+
+ std::unique_ptr<uint8_t[]> m_soft_chr_gen;
+ required_ioport m_s1;
+ uint8_t m_color_mode;
+ uint8_t m_mode_control2;
+ required_device<screen_device> m_screen;
+ required_ioport m_io_monitor;
+ required_region_ptr<uint8_t> m_chargen;
+
+ uint8_t m_vmode;
+ rgb_t (*m_pal)[4];
+ rgb_t m_3111_pal[4];
+ rgb_t m_371x_pal[4];
+ bool m_installed;
+ hd6845s_device *m_hd6845s;
+public:
+ int m_framecnt;
+
+ uint8_t m_mode_control;
+
+ int m_update_row_type;
+ uint8_t *m_chr_gen;
+ uint8_t m_vsync;
+ uint8_t m_hsync;
+ std::vector<uint8_t> m_videoram;
+ uint8_t m_pixel;
+};
+
+// device type definition
+DECLARE_DEVICE_TYPE(ISA8_EPC_MDA, isa8_epc_mda_device)
+
+#endif // MAME_BUS_ISA_EIS_HGB107X_H
diff --git a/src/devices/bus/isa/eis_sad8852.cpp b/src/devices/bus/isa/eis_sad8852.cpp
index f4d634d1033..d8b1fec4d87 100644
--- a/src/devices/bus/isa/eis_sad8852.cpp
+++ b/src/devices/bus/isa/eis_sad8852.cpp
@@ -122,13 +122,13 @@ DEFINE_DEVICE_TYPE(ISA16_SAD8852, isa16_sad8852_device, "sad8852", "SAD8852 IBM
//-------------------------------------------------
// Access methods from ISA bus
//-------------------------------------------------
-READ8_MEMBER( isa16_sad8852_device::sad8852_r )
+uint8_t isa16_sad8852_device::sad8852_r(offs_t offset)
{
LOG("%s sad8852_r(): offset=%d\n", FUNCNAME, offset);
return 0xff;
}
-WRITE8_MEMBER( isa16_sad8852_device::sad8852_w )
+void isa16_sad8852_device::sad8852_w(offs_t offset, uint8_t data)
{
LOG("%s : offset=%d data=0x%02x\n", FUNCNAME, offset, data);
}
@@ -201,11 +201,11 @@ ioport_constructor isa16_sad8852_device::device_input_ports() const
//-------------------------------------------------
void isa16_sad8852_device::device_add_mconfig(machine_config &config)
{
- i80188_cpu_device &cpu(I80188(config, I80188_TAG, XTAL(12'000'000) / 2)); // Chip revision is 6 MHz
+ i80188_cpu_device &cpu(I80188(config, I80188_TAG, XTAL(12'000'000))); // Chip revision is 6 MHz
cpu.set_addrmap(AS_PROGRAM, &isa16_sad8852_device::sad8852_mem);
cpu.set_addrmap(AS_IO, &isa16_sad8852_device::sad8852_io);
- I8274_NEW(config, "terminal", XTAL(12'000'000) / 3); // Needs verification
+ I8274(config, "terminal", XTAL(12'000'000) / 3); // Needs verification
}
isa16_sad8852_device::isa16_sad8852_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) :
@@ -236,8 +236,8 @@ void isa16_sad8852_device::device_reset()
{
m_isa->install_device(
0x378, 0x378, // Wrong, need to find real i/o addresses
- read8_delegate(FUNC( isa16_sad8852_device::sad8852_r ), this),
- write8_delegate(FUNC( isa16_sad8852_device::sad8852_w ), this));
+ read8sm_delegate(*this, FUNC(isa16_sad8852_device::sad8852_r)),
+ write8sm_delegate(*this, FUNC(isa16_sad8852_device::sad8852_w)));
m_irq = m_isairq->read();
m_installed = true;
}
diff --git a/src/devices/bus/isa/eis_sad8852.h b/src/devices/bus/isa/eis_sad8852.h
index 1e2b79be092..384ee297f69 100644
--- a/src/devices/bus/isa/eis_sad8852.h
+++ b/src/devices/bus/isa/eis_sad8852.h
@@ -15,22 +15,22 @@ public:
// construction/destruction
isa16_sad8852_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
- DECLARE_READ8_MEMBER(sad8852_r);
- DECLARE_WRITE8_MEMBER(sad8852_w);
+ uint8_t sad8852_r(offs_t offset);
+ void sad8852_w(offs_t offset, uint8_t data);
protected:
// device-level overrides
- virtual void device_start() override;
- virtual void device_reset() override;
+ virtual void device_start() override ATTR_COLD;
+ virtual void device_reset() override ATTR_COLD;
// address maps
- void sad8852_mem(address_map &map);
- void sad8852_io(address_map &map);
+ void sad8852_mem(address_map &map) ATTR_COLD;
+ void sad8852_io(address_map &map) ATTR_COLD;
// optional information 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 const tiny_rom_entry *device_rom_region() const override ATTR_COLD;
+ virtual void device_add_mconfig(machine_config &config) override ATTR_COLD;
+ virtual ioport_constructor device_input_ports() const override ATTR_COLD;
// helpers
required_ioport m_sw1;
diff --git a/src/devices/bus/isa/eis_twib.cpp b/src/devices/bus/isa/eis_twib.cpp
new file mode 100644
index 00000000000..4ca179e5055
--- /dev/null
+++ b/src/devices/bus/isa/eis_twib.cpp
@@ -0,0 +1,259 @@
+// license:BSD-3-Clause
+// copyright-holders:Joakim Larsson Edstrom
+/***********************************************************************************************************
+ *
+ * Ericsson Information Systems/Nokia Data/ICL, SAD 8852 IBM 3270/5250 terminal emulation adapter
+ *
+ * This board is a terminal adapter for XT class PC machines to be connected as a terminal to
+ * IBM mainframes. There are two on board connectors, a BNC connector to act as a 3270 terminal
+ * and a twinax connector for the older 5250 terminal.
+ *
+ * TODO:
+ * - Hook up 8274 fully
+ * - Add bitbanger device and hook it up to an (emulated?!) IBM mainframe
+ *
+ ************************************************************************************************************/
+/*
+ Links:
+ ------
+ https://github.com/MattisLind/alfaskop_emu
+
+ Ericsson manufactured board - marked 83016053-30, assembled in 1984 indicated by chip dates
+ +--------------------------------------------------------------------------------------+ ___
+ |O 83016053-30 IC11 IC20 X1 |o|_||
+ | IC14 IC15 74LS74 74S37 19.170MHz |____|
+ | NDK 4Y ||
+ | RS232 IC13 IC18 ||
+ | IC12 ULA 2C143E Ferranti ||---
+ | X.27 i8274 MPSC P1|| |= Twinax (5250)
+ | serial controller IC19 IC17 ||---
+ | P3 IC16 754528P LM339 1234567890 ||
+ | IC10 SW2 DIP ||
+ | 74LS08 IC21 RP2 Resistor SIL ||
+ | W2 74LS30 IC2 IC8 ||
+ | IC5 IC1 IC7 74LS125 74LS240 ||
+ | 74LS04 74LS244 RP1 74LS86 W1 CSA1 CSA2 ||---
+ | IC4 IC3 Resistor DIL IC6 ooooo o5 o5 IC9 P2|| |- BNC(3270)
+ | 74LS00 74LS00 1234567890 74LS86 ooooo 1o o4 1o o4 74LS245 ||---
+ | SW1 DIP 2o o3 2o o3 ____|
+ +----------------------------------------------------------------------------------|o___|
+ ||||||||||||||||||||||||| |
+ Notes |
+ ------------------------------------------------------------------------------ |
+ IC13-IC16 unpopulated IC:s
+ CSA1,CSA2 unpopulated jumper areas
+ W2 unpopulated jumper area
+ P3 unpopulated connector RS232/X.27(RS422)
+
+ General description
+ -------------------
+ This is a passive ISA8 board that should be fitted into an Ericsson PC (epc) and
+ driven by suitable software. It was replaced by the ISA16 SAD8852 intelligent TWIB
+ board for WS286 and higher a few years later.
+
+ */
+
+#include "emu.h"
+#include "eis_twib.h"
+#include "machine/z80sio.h"
+
+#define LOG_READ (1U << 1)
+#define LOG_IRQ (1U << 2)
+
+//#define VERBOSE (LOG_IRQ)
+//#define LOG_OUTPUT_STREAM std::cout
+
+#include "logmacro.h"
+
+#define LOGR(...) LOGMASKED(LOG_READ, __VA_ARGS__)
+#define LOGIRQ(...) LOGMASKED(LOG_IRQ, __VA_ARGS__)
+
+#ifdef _MSC_VER
+#define FUNCNAME __func__
+#else
+#define FUNCNAME __PRETTY_FUNCTION__
+#endif
+
+DEFINE_DEVICE_TYPE(ISA8_EIS_TWIB, isa8_eistwib_device, "eistwib", "EIS TWIB IBM mainframe terminal adapter")
+
+//-------------------------------------------------
+// Access methods from ISA bus
+//-------------------------------------------------
+uint8_t isa8_eistwib_device::twib_r(offs_t offset)
+{
+ LOGR("%s : offset=%d\n", FUNCNAME, offset);
+ return m_uart8274->cd_ba_r(offset);
+}
+
+void isa8_eistwib_device::twib_w(offs_t offset, uint8_t data)
+{
+ LOG("%s : offset=%d data=0x%02x\n", FUNCNAME, offset, data);
+ m_uart8274->cd_ba_w(offset, data);
+}
+
+TIMER_DEVICE_CALLBACK_MEMBER(isa8_eistwib_device::tick_bitclock)
+{
+ m_uart8274->txca_w(m_bitclock);
+ m_uart8274->rxca_w(m_bitclock);
+ m_sdlclogger->clock_w(m_bitclock);
+ m_bitclock = !m_bitclock;
+}
+
+
+//----------------------------------------------------------
+// UI I/O
+//----------------------------------------------------------
+static INPUT_PORTS_START( eistwib_ports )
+ PORT_START("SW1")
+ PORT_DIPNAME( 0x3f0, 0x380, "I/O Base address" )
+ PORT_DIPSETTING( 0x000, "0x000" )
+ PORT_DIPSETTING( 0x010, "0x010" )
+ PORT_DIPSETTING( 0x020, "0x020" )
+ PORT_DIPSETTING( 0x030, "0x030" )
+ PORT_DIPSETTING( 0x040, "0x040" )
+ PORT_DIPSETTING( 0x050, "0x050" )
+ PORT_DIPSETTING( 0x060, "0x060" )
+ PORT_DIPSETTING( 0x070, "0x070" )
+ PORT_DIPSETTING( 0x080, "0x080" )
+ PORT_DIPSETTING( 0x090, "0x090" )
+ PORT_DIPSETTING( 0x0a0, "0x0a0" )
+ PORT_DIPSETTING( 0x0b0, "0x0b0" )
+ PORT_DIPSETTING( 0x0c0, "0x0c0" )
+ PORT_DIPSETTING( 0x0d0, "0x0d0" )
+ PORT_DIPSETTING( 0x0e0, "0x0e0" )
+ PORT_DIPSETTING( 0x0f0, "0x0f0" )
+ PORT_DIPSETTING( 0x100, "0x100" )
+ PORT_DIPSETTING( 0x110, "0x110" )
+ PORT_DIPSETTING( 0x120, "0x120" )
+ PORT_DIPSETTING( 0x130, "0x130" )
+ PORT_DIPSETTING( 0x140, "0x140" )
+ PORT_DIPSETTING( 0x150, "0x150" )
+ PORT_DIPSETTING( 0x160, "0x160" )
+ PORT_DIPSETTING( 0x170, "0x170" )
+ PORT_DIPSETTING( 0x180, "0x180" )
+ PORT_DIPSETTING( 0x190, "0x190" )
+ PORT_DIPSETTING( 0x1a0, "0x1a0" )
+ PORT_DIPSETTING( 0x1b0, "0x1b0" )
+ PORT_DIPSETTING( 0x1c0, "0x1c0" )
+ PORT_DIPSETTING( 0x1d0, "0x1d0" )
+ PORT_DIPSETTING( 0x1e0, "0x1e0" )
+ PORT_DIPSETTING( 0x1f0, "0x1f0" )
+ PORT_DIPSETTING( 0x200, "0x200" )
+ PORT_DIPSETTING( 0x210, "0x210" )
+ PORT_DIPSETTING( 0x220, "0x220" )
+ PORT_DIPSETTING( 0x230, "0x230" )
+ PORT_DIPSETTING( 0x240, "0x240" )
+ PORT_DIPSETTING( 0x250, "0x250" )
+ PORT_DIPSETTING( 0x260, "0x260" )
+ PORT_DIPSETTING( 0x270, "0x270" )
+ PORT_DIPSETTING( 0x280, "0x280" )
+ PORT_DIPSETTING( 0x290, "0x290" )
+ PORT_DIPSETTING( 0x2a0, "0x2a0" )
+ PORT_DIPSETTING( 0x2b0, "0x2b0" )
+ PORT_DIPSETTING( 0x2c0, "0x2c0" )
+ PORT_DIPSETTING( 0x2d0, "0x2d0" )
+ PORT_DIPSETTING( 0x2e0, "0x2e0" )
+ PORT_DIPSETTING( 0x2f0, "0x2f0" )
+ PORT_DIPSETTING( 0x300, "0x300" )
+ PORT_DIPSETTING( 0x310, "0x310" )
+ PORT_DIPSETTING( 0x320, "0x320" )
+ PORT_DIPSETTING( 0x330, "0x330" )
+ PORT_DIPSETTING( 0x340, "0x340" )
+ PORT_DIPSETTING( 0x350, "0x350" )
+ PORT_DIPSETTING( 0x360, "0x360" )
+ PORT_DIPSETTING( 0x370, "0x370" )
+ PORT_DIPSETTING( 0x380, "0x380" )
+ PORT_DIPSETTING( 0x390, "0x390" )
+ PORT_DIPSETTING( 0x3a0, "0x3a0" )
+ PORT_DIPSETTING( 0x3b0, "0x3b0" )
+ PORT_DIPSETTING( 0x3c0, "0x3c0" )
+ PORT_DIPSETTING( 0x3d0, "0x3d0" )
+ PORT_DIPSETTING( 0x3e0, "0x3e0" )
+ PORT_DIPSETTING( 0x3f0, "0x3f0" )
+
+ PORT_START("W1") // Jumper area, field 0=no jumper 1=LPT 2=COM 3=n/a
+ PORT_DIPNAME(0x01, 0x00, "ISA IRQ2")
+ PORT_DIPSETTING(0x00, "no jumper")
+ PORT_DIPSETTING(0x01, "8274 INT")
+ PORT_DIPNAME(0x02, 0x00, "ISA IRQ3")
+ PORT_DIPSETTING(0x00, "no jumper")
+ PORT_DIPSETTING(0x02, "8274 INT")
+ PORT_DIPNAME(0x04, 0x04, "ISA IRQ4")
+ PORT_DIPSETTING(0x00, "no jumper")
+ PORT_DIPSETTING(0x04, "8274 INT")
+ PORT_DIPNAME(0x08, 0x00, "ISA IRQ5")
+ PORT_DIPSETTING(0x00, "no jumper")
+ PORT_DIPSETTING(0x08, "8274 INT")
+ PORT_DIPNAME(0x10, 0x00, "ISA IRQ6")
+ PORT_DIPSETTING(0x00, "no jumper")
+ PORT_DIPSETTING(0x10, "8274 INT")
+INPUT_PORTS_END
+
+ioport_constructor isa8_eistwib_device::device_input_ports() const
+{
+ return INPUT_PORTS_NAME( eistwib_ports );
+}
+
+//-------------------------------------------------
+// Board configuration
+//-------------------------------------------------
+void isa8_eistwib_device::device_add_mconfig(machine_config &config)
+{
+ SDLC_LOGGER(config, m_sdlclogger, 0); // To decode the frames
+ I8274(config, m_uart8274, (XTAL(14'318'181)/ 3) / 2); // Half the 4,77 MHz ISA bus CLK signal
+ //m_uart8274->out_rtsa_callback().set([this] (int state) { m_rts = state; });
+ m_uart8274->out_txda_callback().set([this] (int state) { m_txd = state; m_sdlclogger->data_w(state); });
+ m_uart8274->out_int_callback().set([this] (int state)
+ { // Jumper field W1 decides what IRQs to pull
+ if (m_isairq->read() & 0x01) { LOGIRQ("TWIB IRQ2: %d\n", state); m_isa->irq2_w(state); }
+ if (m_isairq->read() & 0x02) { LOGIRQ("TWIB IRQ3: %d\n", state); m_isa->irq3_w(state); }
+ if (m_isairq->read() & 0x04) { LOGIRQ("TWIB IRQ4: %d\n", state); m_isa->irq4_w(state); }
+ if (m_isairq->read() & 0x08) { LOGIRQ("TWIB IRQ5: %d\n", state); m_isa->irq5_w(state); }
+ if (m_isairq->read() & 0x10) { LOGIRQ("TWIB IRQ6: %d\n", state); m_isa->irq6_w(state); }
+ });
+
+ TIMER(config, "bitclock").configure_periodic(FUNC(isa8_eistwib_device::tick_bitclock), attotime::from_hz(300000));
+}
+
+isa8_eistwib_device::isa8_eistwib_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) :
+ device_t(mconfig, ISA8_EIS_TWIB, tag, owner, clock)
+ , device_isa8_card_interface(mconfig, *this)
+ , m_uart8274(*this, "terminal")
+ , m_sdlclogger(*this, "logger")
+ , m_bitclock(false)
+ , m_rts(false)
+ , m_txd(false)
+ , m_sw1(*this, "SW1")
+ , m_isairq(*this, "W1")
+ , m_installed(false)
+{
+}
+
+//-------------------------------------------------
+// Overloading methods
+//-------------------------------------------------
+void isa8_eistwib_device::device_start()
+{
+ set_isa_device();
+ m_installed = false;
+ m_bitclock = false;
+ save_item(NAME(m_installed));
+ save_item(NAME(m_bitclock));
+}
+
+void isa8_eistwib_device::device_reset()
+{
+ int base = m_sw1->read();
+ if (!m_installed)
+ {
+ LOG("Installing twib device at %04x\n", base);
+ m_isa->install_device(
+ base, base + 0x0f,
+ read8sm_delegate(*this, FUNC( isa8_eistwib_device::twib_r )),
+ write8sm_delegate(*this, FUNC( isa8_eistwib_device::twib_w )));
+ m_installed = true;
+ }
+ // CD and CTS input are tied to ground
+ m_uart8274->ctsa_w(0);
+ m_uart8274->dcda_w(0);
+}
diff --git a/src/devices/bus/isa/eis_twib.h b/src/devices/bus/isa/eis_twib.h
new file mode 100644
index 00000000000..7ee5d0b7769
--- /dev/null
+++ b/src/devices/bus/isa/eis_twib.h
@@ -0,0 +1,52 @@
+// license:BSD-3-Clause
+// copyright-holders: Joakim Larsson Edstrom
+#ifndef MAME_BUS_ISA_EIS_TWIB_H
+#define MAME_BUS_ISA_EIS_TWIB_H
+
+#pragma once
+
+#include "isa.h"
+#include "machine/z80sio.h"
+#include "machine/timer.h"
+#include "machine/sdlc.h"
+
+class isa8_eistwib_device :
+ public device_t,
+ public device_isa8_card_interface
+{
+public:
+ // construction/destruction
+ isa8_eistwib_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
+
+ uint8_t twib_r(offs_t offset);
+ void twib_w(offs_t offset, uint8_t data);
+
+protected:
+ // device-level overrides
+ virtual void device_start() override ATTR_COLD;
+ virtual void device_reset() override ATTR_COLD;
+
+ // devices
+ required_device<i8274_device> m_uart8274;
+ required_device<sdlc_logger_device> m_sdlclogger;
+
+ // optional information overrides
+ virtual void device_add_mconfig(machine_config &config) override ATTR_COLD;
+ virtual ioport_constructor device_input_ports() const override ATTR_COLD;
+
+ // Timers
+ TIMER_DEVICE_CALLBACK_MEMBER(tick_bitclock);
+ bool m_bitclock;
+ bool m_rts;
+ bool m_txd;
+
+ // helpers
+ required_ioport m_sw1;
+ required_ioport m_isairq;
+ bool m_installed;
+};
+
+// device type definition
+DECLARE_DEVICE_TYPE(ISA8_EIS_TWIB, isa8_eistwib_device)
+
+#endif // MAME_BUS_ISA_EIS_TWIB_H
diff --git a/src/devices/bus/isa/ex1280.cpp b/src/devices/bus/isa/ex1280.cpp
new file mode 100644
index 00000000000..d96b9d74d53
--- /dev/null
+++ b/src/devices/bus/isa/ex1280.cpp
@@ -0,0 +1,216 @@
+// license:BSD-3-Clause
+// copyright-holders:Ryan Holtz
+
+#include "emu.h"
+#include "ex1280.h"
+
+
+DEFINE_DEVICE_TYPE(ISA16_EX1280, isa16_ex1280_device, "ex1280", "Vectrix EX1280")
+
+//-------------------------------------------------
+// isa16_ex1280_device - constructor
+//-------------------------------------------------
+
+isa16_ex1280_device::isa16_ex1280_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
+ : device_t(mconfig, ISA16_EX1280, tag, owner, clock)
+ , device_isa16_card_interface(mconfig, *this)
+ , m_cpu(*this, "maincpu")
+ , m_ramdac(*this, "ramdac")
+ , m_screen(*this, "screen")
+{
+}
+
+
+//-------------------------------------------------
+// device_start - device-specific startup
+//-------------------------------------------------
+
+void isa16_ex1280_device::device_start()
+{
+ set_isa_device();
+
+ save_item(NAME(m_flags));
+}
+
+
+//-------------------------------------------------
+// device_reset - device-specific reset
+//-------------------------------------------------
+
+void isa16_ex1280_device::device_reset()
+{
+ m_vram.clear();
+ m_vram.resize(0xa00000);
+ m_flags = 0x0002;
+}
+
+
+//-------------------------------------------------
+// main_map - memory map for the card's TMS34010
+//-------------------------------------------------
+
+void isa16_ex1280_device::main_map(address_map &map)
+{
+ map(0x00000000, 0x009fffff).rw(FUNC(isa16_ex1280_device::vram_r), FUNC(isa16_ex1280_device::vram_w));
+ map(0x04000000, 0x04000fff).rw(FUNC(isa16_ex1280_device::regs_r), FUNC(isa16_ex1280_device::regs_w));
+ map(0xfff00000, 0xfffbffff).ram();
+ map(0xfffc0000, 0xffffffff).rom().region("ex1280", 0);
+}
+
+
+//-------------------------------------------------
+// device_add_mconfig - add device configuration
+//-------------------------------------------------
+
+void isa16_ex1280_device::device_add_mconfig(machine_config &config)
+{
+ TMS34010(config, m_cpu, 64000000);
+ m_cpu->set_addrmap(AS_PROGRAM, &isa16_ex1280_device::main_map);
+ m_cpu->set_halt_on_reset(false);
+ m_cpu->set_pixel_clock(64000000);
+ m_cpu->set_pixels_per_clock(1);
+ m_cpu->set_scanline_rgb32_callback(FUNC(isa16_ex1280_device::scanline_update));
+ m_cpu->set_shiftreg_in_callback(FUNC(isa16_ex1280_device::to_shiftreg)); /* write to shiftreg function */
+ m_cpu->set_shiftreg_out_callback(FUNC(isa16_ex1280_device::from_shiftreg)); /* read from shiftreg function */
+ m_cpu->set_screen(m_screen);
+
+ SCREEN(config, m_screen, SCREEN_TYPE_RASTER);
+ m_screen->set_refresh_hz(60);
+ m_screen->set_vblank_time(ATTOSECONDS_IN_USEC(2500)); // Not accurate
+ m_screen->set_size(640, 480);
+ m_screen->set_visarea(0, 640-1, 0, 480-1);
+ m_screen->set_screen_update(m_cpu, FUNC(tms34010_device::tms340x0_rgb32));
+ m_screen->screen_vblank().set(FUNC(isa16_ex1280_device::vblank_w));
+
+ BT451(config, m_ramdac, 0);
+}
+
+
+//-------------------------------------------------
+// regs_r - register read handler
+//-------------------------------------------------
+
+uint16_t isa16_ex1280_device::regs_r(offs_t offset, uint16_t mem_mask)
+{
+ uint16_t data = 0;
+ if (offset == 0)
+ {
+ data = m_flags;
+ }
+ else if (offset == 4)
+ {
+ data = 0x0000;
+ }
+ logerror("%s: regs_r: %08x: %04x & %04x\n", machine().describe_context(), 0x04000000 | (offset << 1), data, mem_mask);
+ return data;
+}
+
+
+//-------------------------------------------------
+// regs_w - register write handler
+//-------------------------------------------------
+
+void isa16_ex1280_device::regs_w(offs_t offset, uint16_t data, uint16_t mem_mask)
+{
+ logerror("%s: regs_w: %08x = %04x & %04x\n", machine().describe_context(), 0x04000000 | (offset << 1), data, mem_mask);
+}
+
+
+//-------------------------------------------------
+// vram_r - VRAM direct read handler
+//-------------------------------------------------
+
+uint16_t isa16_ex1280_device::vram_r(offs_t offset)
+{
+ logerror("vram_r: %08x = %04x\n", offset, m_vram[offset]);
+ return m_vram[offset];
+}
+
+
+//-------------------------------------------------
+// vram_w - VRAM direct write handler
+//-------------------------------------------------
+
+void isa16_ex1280_device::vram_w(offs_t offset, uint16_t data, uint16_t mem_mask)
+{
+ logerror("vram_r: %08x = %04x & %04x\n", offset, data, mem_mask);
+ COMBINE_DATA(&m_vram[offset]);
+}
+
+
+//-------------------------------------------------
+// scanline_update -
+//-------------------------------------------------
+
+TMS340X0_SCANLINE_RGB32_CB_MEMBER(isa16_ex1280_device::scanline_update)
+{
+ uint16_t const *const src = &m_vram[params->rowaddr << 8];
+ uint32_t *const dest = &bitmap.pix(scanline);
+ pen_t const *const pens = m_ramdac->pens();
+ int coladdr = params->coladdr << 1;
+
+ /* copy the non-blanked portions of this scanline */
+ for (int x = params->heblnk; x < params->hsblnk; x += 4)
+ {
+ uint16_t const pixels = src[coladdr++];
+ dest[x + 0] = pens[pixels & 0x0f];
+ dest[x + 1] = pens[(pixels >> 4) & 0x0f];
+ dest[x + 2] = pens[(pixels >> 8) & 0x0f];
+ dest[x + 3] = pens[(pixels >> 12) & 0x0f];
+ }
+}
+
+
+//-------------------------------------------------
+// to_shiftreg - handle VRAM->TMS shift register
+//-------------------------------------------------
+
+TMS340X0_TO_SHIFTREG_CB_MEMBER(isa16_ex1280_device::to_shiftreg)
+{
+ printf("address to shiftreg: %08x\n", address);
+ if (address < 0xa00000)
+ {
+ memcpy(shiftreg, &m_vram[address >> 4], 0x400);
+ }
+}
+
+
+//---------------------------------------------------
+// from_shiftreg - handle TMS shift register->VRAM
+//---------------------------------------------------
+
+TMS340X0_FROM_SHIFTREG_CB_MEMBER(isa16_ex1280_device::from_shiftreg)
+{
+ printf("address from shiftreg: %08x\n", address);
+ if (address < 0xa00000)
+ {
+ memcpy(&m_vram[address >> 4], shiftreg, 0x400);
+ }
+}
+
+
+//-------------------------------------------------
+// vblank_w - toggle vblank bit(?)
+//-------------------------------------------------
+
+void isa16_ex1280_device::vblank_w(int state)
+{
+ //m_flags &= ~(1 << 1);
+ //m_flags |= (state << 1);
+}
+
+
+//-------------------------------------------------
+// rom_region - device-specific ROM region
+//-------------------------------------------------
+
+ROM_START( ex1280 )
+ ROM_REGION16_LE(0x8000, "ex1280", 0)
+ ROM_LOAD16_BYTE("hbv10lo.bin", 0x0000, 0x4000, CRC(4de578b8) SHA1(cd7bc7859dd44f978adca7506afb0a1a73cb1121) )
+ ROM_LOAD16_BYTE("hbv10hi.bin", 0x0001, 0x4000, CRC(b87caa0c) SHA1(88c19cf36cb98e59810dad2a2f1f0e6c884cd7eb) )
+ROM_END
+
+const tiny_rom_entry *isa16_ex1280_device::device_rom_region() const
+{
+ return ROM_NAME( ex1280 );
+}
diff --git a/src/devices/bus/isa/ex1280.h b/src/devices/bus/isa/ex1280.h
new file mode 100644
index 00000000000..44396e8dc8f
--- /dev/null
+++ b/src/devices/bus/isa/ex1280.h
@@ -0,0 +1,62 @@
+// license:BSD-3-Clause
+// copyright-holders:Ryan Holtz
+#ifndef MAME_BUS_ISA_EX1280_H
+#define MAME_BUS_ISA_EX1280_H
+
+#pragma once
+
+#include "isa.h"
+#include "cpu/tms34010/tms34010.h"
+#include "video/bt45x.h"
+#include "screen.h"
+
+//**************************************************************************
+// TYPE DEFINITIONS
+//**************************************************************************
+
+// ======================> isa16_ex1280_device
+
+class isa16_ex1280_device : public device_t,
+ public device_isa16_card_interface
+{
+public:
+ // construction/destruction
+ isa16_ex1280_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
+
+ // Flag non working features
+ static constexpr feature_type unemulated_features() { return feature::GRAPHICS | feature::PALETTE; }
+
+protected:
+ // device-level overrides
+ virtual void device_start() override ATTR_COLD;
+ virtual void device_reset() override ATTR_COLD;
+
+ // optional information overrides
+ virtual void device_add_mconfig(machine_config &config) override ATTR_COLD;
+ virtual const tiny_rom_entry *device_rom_region() const override ATTR_COLD;
+
+ uint16_t vram_r(offs_t offset);
+ 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);
+ void vblank_w(int state);
+
+ required_device<tms34010_device> m_cpu;
+ required_device<bt451_device> m_ramdac;
+ required_device<screen_device> m_screen;
+
+ TMS340X0_TO_SHIFTREG_CB_MEMBER(to_shiftreg);
+ TMS340X0_FROM_SHIFTREG_CB_MEMBER(from_shiftreg);
+ TMS340X0_SCANLINE_RGB32_CB_MEMBER(scanline_update);
+
+ void main_map(address_map &map) ATTR_COLD;
+
+ std::vector<uint16_t> m_vram;
+ uint16_t m_flags;
+};
+
+
+// device type definition
+DECLARE_DEVICE_TYPE(ISA16_EX1280, isa16_ex1280_device)
+
+#endif // MAME_BUS_ISA_EX1280_H
diff --git a/src/devices/bus/isa/fdc.cpp b/src/devices/bus/isa/fdc.cpp
index 9c9f52d7a1d..1d41a496e75 100644
--- a/src/devices/bus/isa/fdc.cpp
+++ b/src/devices/bus/isa/fdc.cpp
@@ -1,5 +1,5 @@
// license:BSD-3-Clause
-// copyright-holders:Miodrag Milanovic
+// copyright-holders:Miodrag Milanovic, Wilbert Pol
/**********************************************************************
ISA 8 bit Floppy Disk Controller
@@ -9,15 +9,19 @@
#include "emu.h"
#include "fdc.h"
#include "machine/busmouse.h"
-#include "machine/pc_fdc.h"
-#include "formats/pc_dsk.h"
#include "formats/naslite_dsk.h"
+#include "formats/ibmxdf_dsk.h"
+#define VERBOSE 0
+#include "logmacro.h"
-FLOPPY_FORMATS_MEMBER( isa8_fdc_device::floppy_formats )
- FLOPPY_PC_FORMAT,
- FLOPPY_NASLITE_FORMAT
-FLOPPY_FORMATS_END
+
+void isa8_fdc_device::floppy_formats(format_registration &fr)
+{
+ fr.add_pc_formats();
+ fr.add(FLOPPY_NASLITE_FORMAT);
+ fr.add(FLOPPY_IBMXDF_FORMAT);
+}
static void pc_dd_floppies(device_slot_interface &device)
{
@@ -41,23 +45,12 @@ isa8_fdc_device::isa8_fdc_device(const machine_config &mconfig, device_type type
{
}
-void isa8_fdc_device::device_start()
-{
- set_isa_device();
- m_isa->install_device(0x03f0, 0x03f7, *m_fdc, &pc_fdc_interface::map);
- m_isa->set_dma_channel(2, this, true);
-}
-
-void isa8_fdc_device::device_reset()
-{
-}
-
-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);
}
@@ -83,31 +76,179 @@ void isa8_fdc_device::eop_w(int state)
}
-isa8_fdc_xt_device::isa8_fdc_xt_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) : isa8_fdc_device(mconfig, ISA8_FDC_XT, tag, owner, clock)
+isa8_upd765_fdc_device::isa8_upd765_fdc_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock)
+ : isa8_fdc_device(mconfig, type, tag, owner, clock)
+ , dor(0x00)
+{
+}
+
+void isa8_upd765_fdc_device::device_start()
+{
+ for(int i=0; i<4; i++) {
+ char name[2] = {static_cast<char>('0'+i), 0};
+ floppy_connector *conn = m_fdc->subdevice<floppy_connector>(name);
+ floppy[i] = conn ? conn->get_device() : nullptr;
+ }
+
+ irq = drq = false;
+ fdc_irq = fdc_drq = false;
+}
+
+void isa8_upd765_fdc_device::device_reset()
+{
+ dor_w(0x00);
+}
+
+// Bits 0-1 select one of the 4 drives, but only if the associated
+// motor bit is on
+
+// Bit 2 is tied to the upd765 reset line
+
+// Bit 3 enables the irq and drq lines
+
+// Bit 4-7 control the drive motors
+
+void isa8_upd765_fdc_device::dor_w(uint8_t data)
+{
+ LOG("dor = %02x\n", data);
+ dor = data;
+
+ for(int i=0; i<4; i++)
+ if(floppy[i])
+ floppy[i]->mon_w(!(dor & (0x10 << i)));
+
+ int fid = dor & 3;
+ if(dor & (0x10 << fid))
+ m_fdc->set_floppy(floppy[fid]);
+ else
+ m_fdc->set_floppy(nullptr);
+
+ check_irq();
+ check_drq();
+ m_fdc->reset_w(!BIT(dor, 2));
+}
+
+uint8_t isa8_upd765_fdc_device::dor_r()
+{
+ return dor;
+}
+
+void isa8_upd765_fdc_device::ccr_w(uint8_t data)
+{
+ static const int rates[4] = { 500000, 300000, 250000, 1000000 };
+ LOG("ccr = %02x\n", data);
+ m_fdc->set_rate(rates[data & 3]);
+}
+
+uint8_t isa8_upd765_fdc_device::dir_r()
+{
+ if(floppy[dor & 3])
+ return floppy[dor & 3]->dskchg_r() ? 0x00 : 0x80;
+ return 0x00;
+}
+
+void isa8_upd765_fdc_device::fdc_irq_w(int state)
+{
+ fdc_irq = state;
+ check_irq();
+}
+
+void isa8_upd765_fdc_device::fdc_drq_w(int state)
+{
+ fdc_drq = state;
+ check_drq();
+}
+
+void isa8_upd765_fdc_device::check_irq()
+{
+ bool pirq = irq;
+ irq = fdc_irq && (dor & 4) && (dor & 8);
+ if(irq != pirq) {
+ LOG("pc_irq = %d\n", irq);
+ irq_w(irq);
+ }
+}
+
+void isa8_upd765_fdc_device::check_drq()
+{
+ bool pdrq = drq;
+ drq = fdc_drq && (dor & 4) && (dor & 8);
+ if(drq != pdrq)
+ drq_w(drq);
+}
+
+
+isa8_fdc_xt_device::isa8_fdc_xt_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) : isa8_fdc_xt_device(mconfig, ISA8_FDC_XT, tag, owner, clock)
+{
+}
+
+isa8_fdc_xt_device::isa8_fdc_xt_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock) : isa8_upd765_fdc_device(mconfig, type, tag, owner, clock)
{
}
void isa8_fdc_xt_device::device_add_mconfig(machine_config &config)
{
- pc_fdc_xt_device &pc_fdc_xt(PC_FDC_XT(config, m_fdc, 0));
- pc_fdc_xt.intrq_wr_callback().set(FUNC(isa8_fdc_device::irq_w));
- pc_fdc_xt.drq_wr_callback().set(FUNC(isa8_fdc_device::drq_w));
- FLOPPY_CONNECTOR(config, "fdc:0", pc_dd_floppies, "525dd", isa8_fdc_device::floppy_formats);
- FLOPPY_CONNECTOR(config, "fdc:1", pc_dd_floppies, "525dd", isa8_fdc_device::floppy_formats);
+ upd765a_device &upd765a(UPD765A(config, m_fdc, 8'000'000, false, false));
+ upd765a.intrq_wr_callback().set(FUNC(isa8_fdc_xt_device::fdc_irq_w));
+ upd765a.drq_wr_callback().set(FUNC(isa8_fdc_xt_device::fdc_drq_w));
+ FLOPPY_CONNECTOR(config, "fdc:0", pc_dd_floppies, "525dd", isa8_fdc_device::floppy_formats).enable_sound(true);
+ FLOPPY_CONNECTOR(config, "fdc:1", pc_dd_floppies, "525dd", isa8_fdc_device::floppy_formats).enable_sound(true);
+}
+
+void isa8_fdc_xt_device::device_start()
+{
+ set_isa_device();
+ m_isa->install_device(0x03f0, 0x03f7, *this, &isa8_fdc_xt_device::map);
+ m_isa->set_dma_channel(2, this, true);
+
+ isa8_upd765_fdc_device::device_start();
}
+// The schematics show address decoding is minimal
+void isa8_fdc_xt_device::map(address_map &map)
+{
+ map(0x0, 0x0).r(m_fdc, FUNC(upd765a_device::msr_r)).w(FUNC(isa8_fdc_xt_device::dor_w));
+ map(0x1, 0x1).r(m_fdc, FUNC(upd765a_device::fifo_r)).w(FUNC(isa8_fdc_xt_device::dor_fifo_w));
+ map(0x2, 0x2).w(FUNC(isa8_fdc_xt_device::dor_w));
+ map(0x3, 0x3).w(FUNC(isa8_fdc_xt_device::dor_w));
+ map(0x4, 0x5).m(m_fdc, FUNC(upd765a_device::map));
+}
-isa8_fdc_at_device::isa8_fdc_at_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) : isa8_fdc_device(mconfig, ISA8_FDC_AT, tag, owner, clock)
+void isa8_fdc_xt_device::dor_fifo_w(uint8_t data)
+{
+ m_fdc->fifo_w(data);
+ dor_w(data);
+}
+
+
+isa8_fdc_at_device::isa8_fdc_at_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) : isa8_upd765_fdc_device(mconfig, ISA8_FDC_AT, tag, owner, clock)
{
}
void isa8_fdc_at_device::device_add_mconfig(machine_config &config)
{
- pc_fdc_at_device &pc_fdc_at(PC_FDC_AT(config, m_fdc, 0));
- pc_fdc_at.intrq_wr_callback().set(FUNC(isa8_fdc_device::irq_w));
- pc_fdc_at.drq_wr_callback().set(FUNC(isa8_fdc_device::drq_w));
- FLOPPY_CONNECTOR(config, "fdc:0", pc_hd_floppies, "35hd", isa8_fdc_device::floppy_formats);
- FLOPPY_CONNECTOR(config, "fdc:1", pc_hd_floppies, "35hd", isa8_fdc_device::floppy_formats);
+ upd765a_device &upd765a(UPD765A(config, m_fdc, 8'000'000, false, false));
+ upd765a.intrq_wr_callback().set(FUNC(isa8_fdc_at_device::fdc_irq_w));
+ upd765a.drq_wr_callback().set(FUNC(isa8_fdc_at_device::fdc_drq_w));
+ FLOPPY_CONNECTOR(config, "fdc:0", pc_hd_floppies, "35hd", isa8_fdc_device::floppy_formats).enable_sound(true);
+ FLOPPY_CONNECTOR(config, "fdc:1", pc_hd_floppies, "35hd", isa8_fdc_device::floppy_formats).enable_sound(true);
+}
+
+// Decoding is through a PAL, so presumably complete
+void isa8_fdc_at_device::map(address_map &map)
+{
+ map(0x2, 0x2).rw(FUNC(isa8_fdc_at_device::dor_r), FUNC(isa8_fdc_at_device::dor_w));
+ map(0x4, 0x5).m(m_fdc, FUNC(upd765a_device::map));
+ map(0x7, 0x7).rw(FUNC(isa8_fdc_at_device::dir_r), FUNC(isa8_fdc_at_device::ccr_w));
+}
+
+void isa8_fdc_at_device::device_start()
+{
+ set_isa_device();
+ m_isa->install_device(0x03f0, 0x03f7, *this, &isa8_fdc_at_device::map);
+ m_isa->set_dma_channel(2, this, true);
+
+ isa8_upd765_fdc_device::device_start();
}
isa8_fdc_smc_device::isa8_fdc_smc_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) : isa8_fdc_device(mconfig, ISA8_FDC_SMC, tag, owner, clock)
@@ -119,8 +260,15 @@ void isa8_fdc_smc_device::device_add_mconfig(machine_config &config)
smc37c78_device &smc(SMC37C78(config, m_fdc, 24'000'000));
smc.intrq_wr_callback().set(FUNC(isa8_fdc_device::irq_w));
smc.drq_wr_callback().set(FUNC(isa8_fdc_device::drq_w));
- FLOPPY_CONNECTOR(config, "fdc:0", pc_hd_floppies, "35hd", isa8_fdc_device::floppy_formats);
- FLOPPY_CONNECTOR(config, "fdc:1", pc_hd_floppies, "35hd", isa8_fdc_device::floppy_formats);
+ FLOPPY_CONNECTOR(config, "fdc:0", pc_hd_floppies, "35hd", isa8_fdc_device::floppy_formats).enable_sound(true);
+ FLOPPY_CONNECTOR(config, "fdc:1", pc_hd_floppies, "35hd", isa8_fdc_device::floppy_formats).enable_sound(true);
+}
+
+void isa8_fdc_smc_device::device_start()
+{
+ set_isa_device();
+ m_isa->install_device(0x03f0, 0x03f7, downcast<smc37c78_device &>(*m_fdc), &smc37c78_device::map);
+ m_isa->set_dma_channel(2, this, true);
}
isa8_fdc_ps2_device::isa8_fdc_ps2_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) : isa8_fdc_device(mconfig, ISA8_FDC_PS2, tag, owner, clock)
@@ -129,11 +277,19 @@ isa8_fdc_ps2_device::isa8_fdc_ps2_device(const machine_config &mconfig, const ch
void isa8_fdc_ps2_device::device_add_mconfig(machine_config &config)
{
- n82077aa_device &n82077aa(N82077AA(config, m_fdc, 24'000'000, n82077aa_device::MODE_PS2));
+ n82077aa_device &n82077aa(N82077AA(config, m_fdc, 24'000'000));
+ n82077aa.set_mode(n82077aa_device::mode_t::PS2);
n82077aa.intrq_wr_callback().set(FUNC(isa8_fdc_device::irq_w));
n82077aa.drq_wr_callback().set(FUNC(isa8_fdc_device::drq_w));
- FLOPPY_CONNECTOR(config, "fdc:0", pc_hd_floppies, "35hd", isa8_fdc_device::floppy_formats);
- FLOPPY_CONNECTOR(config, "fdc:1", pc_hd_floppies, "35hd", isa8_fdc_device::floppy_formats);
+ FLOPPY_CONNECTOR(config, "fdc:0", pc_hd_floppies, "35hd", isa8_fdc_device::floppy_formats).enable_sound(true);
+ FLOPPY_CONNECTOR(config, "fdc:1", pc_hd_floppies, "35hd", isa8_fdc_device::floppy_formats).enable_sound(true);
+}
+
+void isa8_fdc_ps2_device::device_start()
+{
+ set_isa_device();
+ m_isa->install_device(0x03f0, 0x03f7, downcast<n82077aa_device &>(*m_fdc), &n82077aa_device::map);
+ m_isa->set_dma_channel(2, this, true);
}
isa8_fdc_superio_device::isa8_fdc_superio_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) : isa8_fdc_device(mconfig, ISA8_FDC_SUPERIO, tag, owner, clock)
@@ -145,34 +301,37 @@ void isa8_fdc_superio_device::device_add_mconfig(machine_config &config)
pc_fdc_superio_device &superio(PC_FDC_SUPERIO(config, m_fdc, 24'000'000));
superio.intrq_wr_callback().set(FUNC(isa8_fdc_device::irq_w));
superio.drq_wr_callback().set(FUNC(isa8_fdc_device::drq_w));
- FLOPPY_CONNECTOR(config, "fdc:0", pc_hd_floppies, "35hd", isa8_fdc_device::floppy_formats);
- FLOPPY_CONNECTOR(config, "fdc:1", pc_hd_floppies, "35hd", isa8_fdc_device::floppy_formats);
+ FLOPPY_CONNECTOR(config, "fdc:0", pc_hd_floppies, "35hd", isa8_fdc_device::floppy_formats).enable_sound(true);
+ FLOPPY_CONNECTOR(config, "fdc:1", pc_hd_floppies, "35hd", isa8_fdc_device::floppy_formats).enable_sound(true);
+}
+
+void isa8_fdc_superio_device::device_start()
+{
+ set_isa_device();
+ m_isa->install_device(0x03f0, 0x03f7, downcast<pc_fdc_superio_device &>(*m_fdc), &pc_fdc_superio_device::map);
+ m_isa->set_dma_channel(2, this, true);
}
isa8_ec1841_0003_device::isa8_ec1841_0003_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
- : isa8_fdc_device(mconfig, ISA8_EC1841_0003, tag, owner, clock)
+ : isa8_fdc_xt_device(mconfig, ISA8_EC1841_0003, tag, owner, clock)
, m_bus_mouse(*this, "bus_mouse")
{
}
void isa8_ec1841_0003_device::device_start()
{
- isa8_fdc_device::device_start();
+ isa8_fdc_xt_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);
}
void isa8_ec1841_0003_device::device_add_mconfig(machine_config &config)
{
- pc_fdc_xt_device &pc_fdc_xt(PC_FDC_XT(config, m_fdc, 0));
- pc_fdc_xt.intrq_wr_callback().set(FUNC(isa8_fdc_device::irq_w));
- pc_fdc_xt.drq_wr_callback().set(FUNC(isa8_fdc_device::drq_w));
- FLOPPY_CONNECTOR(config, "fdc:0", pc_dd_floppies, "525dd", isa8_fdc_device::floppy_formats);
- FLOPPY_CONNECTOR(config, "fdc:1", pc_dd_floppies, "525dd", isa8_fdc_device::floppy_formats);
+ isa8_fdc_xt_device::device_add_mconfig(config);
BUS_MOUSE(config, "bus_mouse", 0).extint_callback().set(FUNC(isa8_ec1841_0003_device::aux_irq_w));
}
diff --git a/src/devices/bus/isa/fdc.h b/src/devices/bus/isa/fdc.h
index cec5f7dd06e..8dfc1a3d3d3 100644
--- a/src/devices/bus/isa/fdc.h
+++ b/src/devices/bus/isa/fdc.h
@@ -1,5 +1,5 @@
// license:BSD-3-Clause
-// copyright-holders:Miodrag Milanovic
+// copyright-holders:Miodrag Milanovic, Wilbert Pol
/**********************************************************************
ISA 8 bit Floppy Disk Controller
@@ -26,40 +26,75 @@ class isa8_fdc_device :
public device_isa8_card_interface
{
public:
- DECLARE_WRITE_LINE_MEMBER( irq_w );
- DECLARE_WRITE_LINE_MEMBER( drq_w );
- DECLARE_FLOPPY_FORMATS( floppy_formats );
+ void irq_w(int state);
+ void drq_w(int state);
+ static void floppy_formats(format_registration &fr);
protected:
// construction/destruction
isa8_fdc_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 dack_r(int line) override;
virtual void dack_w(int line, uint8_t data) override;
virtual void dack_line_w(int line, int state) override;
virtual void eop_w(int state) override;
- required_device<pc_fdc_interface> m_fdc;
+ required_device<upd765_family_device> m_fdc;
+};
+
+class isa8_upd765_fdc_device : public isa8_fdc_device
+{
+protected:
+ // construction/destruction
+ isa8_upd765_fdc_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 ATTR_COLD;
+ virtual void device_reset() override ATTR_COLD;
+
+ uint8_t dor_r();
+ void dor_w(uint8_t data);
+ uint8_t dir_r();
+ void ccr_w(uint8_t data);
+
+ void fdc_irq_w(int state);
+ void fdc_drq_w(int state);
+
+private:
+ bool irq, drq, fdc_drq, fdc_irq;
+ uint8_t dor;
+
+ floppy_image_device *floppy[4];
+
+ void check_irq();
+ void check_drq();
};
-class isa8_fdc_xt_device : public isa8_fdc_device {
+class isa8_fdc_xt_device : public isa8_upd765_fdc_device {
public:
isa8_fdc_xt_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
protected:
- virtual void device_add_mconfig(machine_config &config) override;
+ isa8_fdc_xt_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock);
+
+ // device-level overrides
+ virtual void device_add_mconfig(machine_config &config) override ATTR_COLD;
+ virtual void device_start() override ATTR_COLD;
+
+ void map(address_map &map) ATTR_COLD;
+ void dor_fifo_w(uint8_t data);
};
-class isa8_fdc_at_device : public isa8_fdc_device {
+class isa8_fdc_at_device : public isa8_upd765_fdc_device {
public:
isa8_fdc_at_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-level overrides
+ virtual void device_add_mconfig(machine_config &config) override ATTR_COLD;
+ virtual void device_start() override ATTR_COLD;
+
+ void map(address_map &map) ATTR_COLD;
};
class isa8_fdc_smc_device : public isa8_fdc_device {
@@ -67,7 +102,9 @@ public:
isa8_fdc_smc_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-level overrides
+ virtual void device_add_mconfig(machine_config &config) override ATTR_COLD;
+ virtual void device_start() override ATTR_COLD;
};
class isa8_fdc_ps2_device : public isa8_fdc_device {
@@ -75,7 +112,9 @@ public:
isa8_fdc_ps2_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-level overrides
+ virtual void device_add_mconfig(machine_config &config) override ATTR_COLD;
+ virtual void device_start() override ATTR_COLD;
};
class isa8_fdc_superio_device : public isa8_fdc_device {
@@ -83,18 +122,20 @@ public:
isa8_fdc_superio_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-level overrides
+ virtual void device_add_mconfig(machine_config &config) override ATTR_COLD;
+ virtual void device_start() override ATTR_COLD;
};
-class isa8_ec1841_0003_device : public isa8_fdc_device {
+class isa8_ec1841_0003_device : public isa8_fdc_xt_device {
public:
isa8_ec1841_0003_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 void device_start() override ATTR_COLD;
+ virtual void device_add_mconfig(machine_config &config) override ATTR_COLD;
- 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/finalchs.cpp b/src/devices/bus/isa/finalchs.cpp
index 84b81220c42..6fb49bbf5c6 100644
--- a/src/devices/bus/isa/finalchs.cpp
+++ b/src/devices/bus/isa/finalchs.cpp
@@ -58,7 +58,7 @@ void isa8_finalchs_device::device_reset()
{
// MAME doesn't allow reading ioport at device_start
u16 port = ioport("DSW")->read() * 0x10 + 0x100;
- m_isa->install_device(port, port+1, read8_delegate(FUNC(isa8_finalchs_device::finalchs_r), this), write8_delegate(FUNC(isa8_finalchs_device::finalchs_w), this));
+ m_isa->install_device(port, port+1, read8sm_delegate(*this, FUNC(isa8_finalchs_device::finalchs_r)), write8sm_delegate(*this, FUNC(isa8_finalchs_device::finalchs_w)));
m_installed = true;
}
@@ -123,7 +123,7 @@ ioport_constructor isa8_finalchs_device::device_input_ports() const
void isa8_finalchs_device::device_add_mconfig(machine_config &config)
{
- M65SC02(config, m_maincpu, 5_MHz_XTAL);
+ G65SC02(config, m_maincpu, 5_MHz_XTAL);
m_maincpu->set_addrmap(AS_PROGRAM, &isa8_finalchs_device::finalchs_mem);
GENERIC_LATCH_8(config, m_mainlatch);
@@ -139,7 +139,7 @@ void isa8_finalchs_device::device_add_mconfig(machine_config &config)
// External handlers
-READ8_MEMBER(isa8_finalchs_device::finalchs_r)
+uint8_t isa8_finalchs_device::finalchs_r(offs_t offset)
{
if (offset == 0)
return m_mainlatch->read();
@@ -147,7 +147,7 @@ READ8_MEMBER(isa8_finalchs_device::finalchs_r)
return m_mainlatch->pending_r() ? 0 : 1;
}
-WRITE8_MEMBER(isa8_finalchs_device::finalchs_w)
+void isa8_finalchs_device::finalchs_w(offs_t offset, uint8_t data)
{
if (offset == 0)
m_sublatch->write(data);
diff --git a/src/devices/bus/isa/finalchs.h b/src/devices/bus/isa/finalchs.h
index d00573ebab6..9083f9529a3 100644
--- a/src/devices/bus/isa/finalchs.h
+++ b/src/devices/bus/isa/finalchs.h
@@ -12,7 +12,7 @@
#pragma once
#include "isa.h"
-#include "cpu/m6502/m65sc02.h"
+#include "cpu/m6502/g65sc02.h"
#include "machine/gen_latch.h"
@@ -26,25 +26,25 @@ public:
protected:
// device-level overrides
- virtual void device_start() override;
- virtual void device_reset() override;
- virtual void device_add_mconfig(machine_config &config) override;
+ 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;
// optional information overrides
- virtual const tiny_rom_entry *device_rom_region() const override;
- virtual ioport_constructor device_input_ports() const override;
+ virtual const tiny_rom_entry *device_rom_region() const override ATTR_COLD;
+ virtual ioport_constructor device_input_ports() const override ATTR_COLD;
private:
- required_device<m65sc02_device> m_maincpu;
+ required_device<g65sc02_device> m_maincpu;
required_device<generic_latch_8_device> m_mainlatch;
required_device<generic_latch_8_device> m_sublatch;
bool m_installed;
- DECLARE_READ8_MEMBER(finalchs_r);
- DECLARE_WRITE8_MEMBER(finalchs_w);
+ uint8_t finalchs_r(offs_t offset);
+ void finalchs_w(offs_t offset, uint8_t data);
- void finalchs_mem(address_map &map);
+ void finalchs_mem(address_map &map) ATTR_COLD;
};
diff --git a/src/devices/bus/isa/gblaster.cpp b/src/devices/bus/isa/gblaster.cpp
index e579070fbf6..3b6d66adb14 100644
--- a/src/devices/bus/isa/gblaster.cpp
+++ b/src/devices/bus/isa/gblaster.cpp
@@ -22,22 +22,22 @@
*/
-READ8_MEMBER( isa8_gblaster_device::saa1099_16_r )
+uint8_t isa8_gblaster_device::saa1099_16_r(offs_t offset)
{
return 0xff;
}
-WRITE8_MEMBER( isa8_gblaster_device::saa1099_1_16_w )
+void isa8_gblaster_device::saa1099_1_16_w(offs_t offset, uint8_t data)
{
m_saa1099_1->write(offset, data);
}
-WRITE8_MEMBER( isa8_gblaster_device::saa1099_2_16_w )
+void isa8_gblaster_device::saa1099_2_16_w(offs_t offset, uint8_t data)
{
m_saa1099_2->write(offset, data);
}
-READ8_MEMBER( isa8_gblaster_device::detect_r )
+uint8_t isa8_gblaster_device::detect_r(offs_t offset)
{
switch(offset)
{
@@ -49,7 +49,7 @@ READ8_MEMBER( isa8_gblaster_device::detect_r )
}
}
-WRITE8_MEMBER( isa8_gblaster_device::detect_w )
+void isa8_gblaster_device::detect_w(offs_t offset, uint8_t data)
{
switch(offset)
{
@@ -70,14 +70,13 @@ DEFINE_DEVICE_TYPE(ISA8_GAME_BLASTER, isa8_gblaster_device, "isa_gblaster", "Gam
void isa8_gblaster_device::device_add_mconfig(machine_config &config)
{
- SPEAKER(config, "lspeaker").front_left();
- SPEAKER(config, "rspeaker").front_right();
- SAA1099(config, m_saa1099_1, 7159090);
- m_saa1099_1->add_route(ALL_OUTPUTS, "lspeaker", 0.50);
- m_saa1099_1->add_route(ALL_OUTPUTS, "rspeaker", 0.50);
- SAA1099(config, m_saa1099_2, 7159090);
- m_saa1099_2->add_route(ALL_OUTPUTS, "lspeaker", 0.50);
- m_saa1099_2->add_route(ALL_OUTPUTS, "rspeaker", 0.50);
+ SPEAKER(config, "speaker", 2).front();
+ SAA1099(config, m_saa1099_1, XTAL(14'318'181) / 2); // or CMS-301, from OSC pin in ISA bus
+ m_saa1099_1->add_route(0, "speaker", 0.50, 0);
+ m_saa1099_1->add_route(1, "speaker", 0.50, 1);
+ SAA1099(config, m_saa1099_2, XTAL(14'318'181) / 2); // or CMS-301, from OSC pin in ISA bus
+ m_saa1099_2->add_route(0, "speaker", 0.50, 0);
+ m_saa1099_2->add_route(1, "speaker", 0.50, 1);
}
//**************************************************************************
@@ -104,9 +103,9 @@ isa8_gblaster_device::isa8_gblaster_device(const machine_config &mconfig, const
void isa8_gblaster_device::device_start()
{
set_isa_device();
- m_isa->install_device(0x0220, 0x0221, read8_delegate( FUNC(isa8_gblaster_device::saa1099_16_r), this ), write8_delegate( FUNC(isa8_gblaster_device::saa1099_1_16_w), this ) );
- m_isa->install_device(0x0222, 0x0223, read8_delegate( FUNC(isa8_gblaster_device::saa1099_16_r), this ), write8_delegate( FUNC(isa8_gblaster_device::saa1099_2_16_w), this ) );
- m_isa->install_device(0x0224, 0x022F, read8_delegate( FUNC(isa8_gblaster_device::detect_r), this ), write8_delegate( FUNC(isa8_gblaster_device::detect_w), this ) );
+ m_isa->install_device(0x0220, 0x0221, read8sm_delegate(*this, FUNC(isa8_gblaster_device::saa1099_16_r)), write8sm_delegate(*this, FUNC(isa8_gblaster_device::saa1099_1_16_w)));
+ m_isa->install_device(0x0222, 0x0223, read8sm_delegate(*this, FUNC(isa8_gblaster_device::saa1099_16_r)), write8sm_delegate(*this, FUNC(isa8_gblaster_device::saa1099_2_16_w)));
+ m_isa->install_device(0x0224, 0x022F, read8sm_delegate(*this, FUNC(isa8_gblaster_device::detect_r)), write8sm_delegate(*this, FUNC(isa8_gblaster_device::detect_w)));
}
//-------------------------------------------------
diff --git a/src/devices/bus/isa/gblaster.h b/src/devices/bus/isa/gblaster.h
index 03b1fcea87d..b744198ad08 100644
--- a/src/devices/bus/isa/gblaster.h
+++ b/src/devices/bus/isa/gblaster.h
@@ -22,19 +22,19 @@ public:
// construction/destruction
isa8_gblaster_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
- DECLARE_READ8_MEMBER(saa1099_16_r);
- DECLARE_WRITE8_MEMBER(saa1099_1_16_w);
- DECLARE_WRITE8_MEMBER(saa1099_2_16_w);
- DECLARE_READ8_MEMBER(detect_r);
- DECLARE_WRITE8_MEMBER(detect_w);
+ uint8_t saa1099_16_r(offs_t offset);
+ void saa1099_1_16_w(offs_t offset, uint8_t data);
+ void saa1099_2_16_w(offs_t offset, uint8_t data);
+ uint8_t detect_r(offs_t offset);
+ void detect_w(offs_t offset, uint8_t data);
protected:
// device-level overrides
- virtual void device_start() override;
- virtual void device_reset() override;
+ virtual void device_start() override ATTR_COLD;
+ virtual void device_reset() override ATTR_COLD;
// optional information overrides
- virtual void device_add_mconfig(machine_config &config) override;
+ virtual void device_add_mconfig(machine_config &config) override ATTR_COLD;
private:
// internal state
diff --git a/src/devices/bus/isa/gus.cpp b/src/devices/bus/isa/gus.cpp
index 423c1e3629f..3d9fd1c073f 100644
--- a/src/devices/bus/isa/gus.cpp
+++ b/src/devices/bus/isa/gus.cpp
@@ -4,6 +4,9 @@
* Gravis Ultrasound ISA card
*
* Started: 28/01/2012
+ *
+ * to do: xref with lowsrc.doc from GUS SDK
+ * - 256K DMA and 16-bit sample playback boundaries
*/
@@ -33,14 +36,6 @@
//#define SAVE_WAVE_RAM 1
//#define LOG_SOUND 1
-static const uint16_t rate_table[33] =
-{
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 44100, 41160, 38587, 36317, 34300, 32494, 30870, 29400,
- 28063, 26843, 25725, 24696, 23746, 22866, 22050, 21289,
- 20580, 19916, 19293
-};
-
static const uint16_t volume_ramp_table[4] =
{
1, 8, 64, 512
@@ -73,7 +68,7 @@ void gf1_device::update_irq()
}
/* only the Adlib timers are implemented in hardware */
-READ8_MEMBER( gf1_device::adlib_r )
+uint8_t gf1_device::adlib_r(offs_t offset)
{
uint8_t retVal = 0xff;
switch(offset)
@@ -88,7 +83,7 @@ READ8_MEMBER( gf1_device::adlib_r )
return retVal;
}
-WRITE8_MEMBER( gf1_device::adlib_w )
+void gf1_device::adlib_w(offs_t offset, uint8_t data)
{
switch(offset)
{
@@ -145,7 +140,7 @@ WRITE8_MEMBER( gf1_device::adlib_w )
}
}
-void gf1_device::update_volume_ramps()
+TIMER_CALLBACK_MEMBER(gf1_device::update_volume_ramps)
{
int x;
@@ -212,68 +207,54 @@ void gf1_device::update_volume_ramps()
}
}
-void gf1_device::device_timer(emu_timer &timer, device_timer_id id, int param, void *ptr)
+TIMER_CALLBACK_MEMBER(gf1_device::adlib_timer1_tick)
{
- switch(id)
+ if(m_adlib_timer1_enable != 0)
{
- case ADLIB_TIMER1:
- if(m_adlib_timer1_enable != 0)
+ if(m_timer1_count == 0xff)
{
- if(m_timer1_count == 0xff)
- {
- m_adlib_status |= 0xc0;
- m_timer1_count = m_timer1_value;
- if(m_timer_ctrl & 0x04)
- m_timer1_irq_handler(1);
- }
- m_timer1_count++;
+ m_adlib_status |= 0xc0;
+ m_timer1_count = m_timer1_value;
+ if(m_timer_ctrl & 0x04)
+ m_timer1_irq_handler(1);
}
- break;
- case ADLIB_TIMER2:
- if(m_adlib_timer2_enable != 0)
+ m_timer1_count++;
+ }
+}
+
+TIMER_CALLBACK_MEMBER(gf1_device::adlib_timer2_tick)
+{
+ if(m_adlib_timer2_enable != 0)
+ {
+ if(m_timer2_count == 0xff)
{
- if(m_timer2_count == 0xff)
- {
- m_adlib_status |= 0xa0;
- m_timer2_count = m_timer2_value;
- if(m_timer_ctrl & 0x08)
- m_timer2_irq_handler(1);
- }
- m_timer2_count++;
+ m_adlib_status |= 0xa0;
+ m_timer2_count = m_timer2_value;
+ if(m_timer_ctrl & 0x08)
+ m_timer2_irq_handler(1);
}
- break;
- case DMA_TIMER:
- m_drq1_handler(1);
- break;
- case VOL_RAMP_TIMER:
- update_volume_ramps();
- break;
+ m_timer2_count++;
}
}
-void gf1_device::sound_stream_update(sound_stream &stream, stream_sample_t **inputs, stream_sample_t **outputs, int samples)
+TIMER_CALLBACK_MEMBER(gf1_device::dma_tick)
{
- int x,y;
- //uint32_t count;
+ m_drq1_handler(1);
+}
- stream_sample_t* outputl = outputs[0];
- stream_sample_t* outputr = outputs[1];
- memset( outputl, 0x00, samples * sizeof(*outputl) );
- memset( outputr, 0x00, samples * sizeof(*outputr) );
+void gf1_device::sound_stream_update(sound_stream &stream)
+{
+ int x;
for(x=0;x<32;x++) // for each voice
{
- stream_sample_t* left = outputl;
- stream_sample_t* right = outputr;
uint16_t vol = (m_volume_table[(m_voice[x].current_vol & 0xfff0) >> 4]);
- for(y=samples-1; y>=0; y--)
+ for (int sampindex = 0; sampindex < stream.samples(); sampindex++)
{
uint32_t current = m_voice[x].current_addr >> 9;
// TODO: implement proper panning
- (*left) += ((m_voice[x].sample) * (vol/8192.0));
- (*right) += ((m_voice[x].sample) * (vol/8192.0));
- left++;
- right++;
+ stream.add_int(0, sampindex, m_voice[x].sample * vol, 32768 * 8192);
+ stream.add_int(1, sampindex, m_voice[x].sample * vol, 32768 * 8192);
if((!(m_voice[x].voice_ctrl & 0x40)) && (m_voice[x].current_addr >= m_voice[x].end_addr) && !m_voice[x].rollover && !(m_voice[x].voice_ctrl & 0x01))
{
if(m_voice[x].vol_ramp_ctrl & 0x04)
@@ -366,7 +347,7 @@ void gf1_device::sound_stream_update(sound_stream &stream, stream_sample_t **inp
gf1_device::gf1_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) :
acia6850_device(mconfig, GGF1, tag, owner, clock),
device_sound_interface(mconfig, *this),
- m_dma_dram_ctrl(0), m_dma_start_addr(0), m_dram_addr(0), m_timer_ctrl(0), m_timer1_count(0), m_timer2_count(0), m_timer1_value(0), m_timer2_value(0), m_sampling_freq(0), m_sampling_ctrl(0), m_joy_trim_dac(0), m_reset(0), m_active_voices(0), m_irq_source(0),
+ m_dma_dram_ctrl(0), m_dma_start_addr(0), m_dram_addr(0), m_timer_ctrl(0), m_timer1_count(0), m_timer2_count(0), m_timer1_value(0), m_timer2_value(0), m_sampling_freq(0), m_sampling_ctrl(0), m_joy_trim_dac(0), m_reset(0), m_active_voices(14), m_irq_source(0),
m_stream(nullptr),
m_timer1(nullptr), m_timer2(nullptr), m_dmatimer(nullptr), m_voltimer(nullptr),
m_current_voice(0), m_current_reg(0), m_adlib_cmd(0), m_mix_ctrl(0), m_gf1_irq(0), m_midi_irq(0), m_dma_channel1(0), m_dma_channel2(0), m_irq_combine(0), m_dma_combine(0), m_adlib_timer_cmd(0), m_adlib_timer1_enable(0), m_adlib_timer2_enable(0), m_adlib_status(0), m_adlib_data(0), m_voice_irq_ptr(0), m_voice_irq_current(0), m_dma_16bit(0), m_statread(0), m_sb_data_2xc(0), m_sb_data_2xe(0), m_reg_ctrl(0), m_fake_adlib_status(0), m_dma_current(0), m_txirq(0), m_rxirq(0),
@@ -392,32 +373,17 @@ 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);
- m_stream = stream_alloc(0,2,44100);
+ m_stream = stream_alloc(0,2,clock() / (14 * 16));
// init timers
- m_timer1 = timer_alloc(ADLIB_TIMER1);
- m_timer2 = timer_alloc(ADLIB_TIMER2);
- m_dmatimer = timer_alloc(DMA_TIMER);
- m_voltimer = timer_alloc(VOL_RAMP_TIMER);
+ m_timer1 = timer_alloc(FUNC(gf1_device::adlib_timer1_tick), this);
+ m_timer2 = timer_alloc(FUNC(gf1_device::adlib_timer2_tick), this);
+ m_dmatimer = timer_alloc(FUNC(gf1_device::dma_tick), this);
+ m_voltimer = timer_alloc(FUNC(gf1_device::update_volume_ramps), this);
save_item(NAME(m_wave_ram));
@@ -428,9 +394,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 */
}
@@ -458,7 +425,7 @@ void gf1_device::device_reset()
m_irq_source = 0xe0;
m_reg_ctrl = 0;
m_active_voices = 14;
- m_stream->set_sample_rate(44100);
+ m_stream->set_sample_rate(clock() / (m_active_voices * 16));
m_voltimer->adjust(attotime::zero,0,attotime::from_usec(1000/(1.6*m_active_voices)));
}
@@ -474,11 +441,16 @@ void gf1_device::device_stop()
fclose(f);
#endif
}
+
+void gf1_device::device_clock_changed()
+{
+ m_stream->set_sample_rate(clock() / (m_active_voices * 16));
+}
// ------------------------------------------------
// device I/O handlers
// ------------------------------------------------
-READ8_MEMBER(gf1_device::global_reg_select_r)
+uint8_t gf1_device::global_reg_select_r(offs_t offset)
{
if(offset == 0)
return m_current_voice;
@@ -486,7 +458,7 @@ READ8_MEMBER(gf1_device::global_reg_select_r)
return m_current_reg | 0xc0;
}
-WRITE8_MEMBER(gf1_device::global_reg_select_w)
+void gf1_device::global_reg_select_w(offs_t offset, uint8_t data)
{
if(offset == 0)
m_current_voice = data & 0x1f;
@@ -494,7 +466,7 @@ WRITE8_MEMBER(gf1_device::global_reg_select_w)
m_current_reg = data;
}
-READ8_MEMBER(gf1_device::global_reg_data_r)
+uint8_t gf1_device::global_reg_data_r(offs_t offset)
{
uint16_t ret;
@@ -508,6 +480,7 @@ READ8_MEMBER(gf1_device::global_reg_data_r)
m_dma_irq_handler(0);
return ret;
}
+ break;
case 0x45: // Timer control
if(offset == 1)
return m_timer_ctrl & 0x0c;
@@ -515,15 +488,18 @@ READ8_MEMBER(gf1_device::global_reg_data_r)
case 0x49: // Sampling control
if(offset == 1)
return m_sampling_ctrl & 0xe7;
+ break;
case 0x4c: // Reset
if(offset == 1)
return m_reset;
+ break;
case 0x80: // Voice control
/* bit 0 - 1 if voice is stopped
* bit 6 - 1 if addresses are decreasing, can change when looping is enabled
* bit 7 - 1 if Wavetable IRQ is pending */
if(offset == 1)
return m_voice[m_current_voice].voice_ctrl & 0xff;
+ break;
case 0x81: // Frequency Control
ret = m_voice[m_current_voice].freq_ctrl;
if(offset == 0)
@@ -557,12 +533,15 @@ READ8_MEMBER(gf1_device::global_reg_data_r)
case 0x86: // Volume Ramp rate
if(offset == 1)
return m_voice[m_current_voice].vol_ramp_rate;
+ break;
case 0x87: // Volume Ramp start (high 4 bits = exponent, low 4 bits = mantissa)
if(offset == 1)
return m_voice[m_current_voice].vol_ramp_start;
+ break;
case 0x88: // Volume Ramp end (high 4 bits = exponent, low 4 bits = mantissa)
if(offset == 1)
return m_voice[m_current_voice].vol_ramp_end;
+ break;
case 0x89: // Current Volume (high 4 bits = exponent, middle 8 bits = mantissa, low 4 bits = 0 [reserved])
ret = m_voice[m_current_voice].current_vol;
if(offset == 0)
@@ -584,15 +563,18 @@ READ8_MEMBER(gf1_device::global_reg_data_r)
case 0x8c: // Pan position (4 bits, 0=full left, 15=full right)
if(offset == 1)
return m_voice[m_current_voice].pan_position;
+ break;
case 0x8d: // Volume Ramp control
/* bit 0 - Ramp has stopped
* bit 6 - Ramp direction
* bit 7 - Ramp IRQ pending */
if(offset == 1)
return m_voice[m_current_voice].vol_ramp_ctrl;
+ break;
case 0x8e: // Active voices (6 bits, high 2 bits are always 1)
if(offset == 1)
- return m_active_voices | 0xc0;
+ return (m_active_voices - 1) | 0xc0;
+ break;
case 0x8f: // IRQ source register
if(offset == 1)
{
@@ -613,7 +595,7 @@ READ8_MEMBER(gf1_device::global_reg_data_r)
return 0xff;
}
-WRITE8_MEMBER(gf1_device::global_reg_data_w)
+void gf1_device::global_reg_data_w(offs_t offset, uint8_t data)
{
switch(m_current_reg)
{
@@ -716,7 +698,7 @@ WRITE8_MEMBER(gf1_device::global_reg_data_w)
* bit 2 - roll over condition (generate IRQ, and not stop playing voice, no looping)
* bit 3 - enable looping
* bit 4 - enable bi-directional looping
- * bit 5 - rnable IRQ at end of ramp */
+ * bit 5 - enable IRQ at end of ramp */
if(offset == 1)
{
m_voice[m_current_voice].vol_ramp_ctrl = data & 0x7f;
@@ -738,15 +720,15 @@ WRITE8_MEMBER(gf1_device::global_reg_data_w)
case 0x0e: // Active voices (6 bits, high 2 bits are always 1)
if(offset == 1)
{
- m_active_voices = data & 0x3f;
- if((data & 0x3f) < 14)
+ m_active_voices = (data & 0x3f) + 1;
+ if(m_active_voices < 14)
m_active_voices = 14;
- if((data & 0x3f) > 32)
+ if(m_active_voices > 32)
m_active_voices = 32;
- m_stream->set_sample_rate(rate_table[m_active_voices]);
+ m_stream->set_sample_rate(clock() / (m_active_voices * 16));
m_voltimer->adjust(attotime::zero,0,attotime::from_usec(1000/(1.6*m_active_voices)));
}
- logerror("GUS: Active Voices write %02x (%i Hz)\n", data, rate_table[m_active_voices]);
+ logerror("GUS: Active Voices write %02x (%d voices at %u Hz)\n", data, m_active_voices, clock() / (m_active_voices * 16));
break;
case 0x41:
/* bit 0 - Enable the DMA channel.
@@ -826,7 +808,7 @@ WRITE8_MEMBER(gf1_device::global_reg_data_w)
{
m_timer1_count = data;
m_timer1_value = data;
- logerror("GUS: Timer 1 count write %02x\n",data);
+ logerror("GUS: Timer 1 count write %02x (%d usec)\n",data,data*80);
}
break;
case 0x47: // Timer 2 count
@@ -834,7 +816,7 @@ WRITE8_MEMBER(gf1_device::global_reg_data_w)
{
m_timer2_count = data;
m_timer2_value = data;
- logerror("GUS: Timer 2 count write %02x\n",data);
+ logerror("GUS: Timer 2 count write %02x (%d usec)\n",data,data*320);
}
break;
case 0x48: // Sampling Frequency - 9878400/(16*(FREQ+2))
@@ -876,7 +858,7 @@ WRITE8_MEMBER(gf1_device::global_reg_data_w)
/* port 0x3X7 - DRAM I/O
* read and write bytes directly to wavetable DRAM */
-READ8_MEMBER(gf1_device::dram_r)
+uint8_t gf1_device::dram_r(offs_t offset)
{
if(offset == 1)
{
@@ -886,7 +868,7 @@ READ8_MEMBER(gf1_device::dram_r)
return 0xff;
}
-WRITE8_MEMBER(gf1_device::dram_w)
+void gf1_device::dram_w(offs_t offset, uint8_t data)
{
if(offset == 1)
{
@@ -896,7 +878,7 @@ WRITE8_MEMBER(gf1_device::dram_w)
/* port 2XA - read selected adlib command?
* the GUS driver installation writes 0x55 to port 0x388, then expects to reads the same from 0x2XA */
-READ8_MEMBER(gf1_device::adlib_cmd_r)
+uint8_t gf1_device::adlib_cmd_r(offs_t offset)
{
if(offset == 0)
{
@@ -922,7 +904,7 @@ READ8_MEMBER(gf1_device::adlib_cmd_r)
* bits 5-3 = DMA select register 2 (values same as reg 1)
* bit 6 = combine both on same DMA channel
*/
-WRITE8_MEMBER(gf1_device::adlib_cmd_w)
+void gf1_device::adlib_cmd_w(offs_t offset, uint8_t data)
{
if(offset == 1)
{
@@ -1072,18 +1054,18 @@ WRITE8_MEMBER(gf1_device::adlib_cmd_w)
* bit 4 - Combine GF1 IRQs with MIDI IRQs
* bit 5 - Enable MIDI TxD to RxD loopback
* bit 6 - Control Reg Select - set next I/O write to 0x2XB to be DMA (0) or IRQ (1) channel latches */
-READ8_MEMBER(gf1_device::mix_ctrl_r)
+uint8_t gf1_device::mix_ctrl_r(offs_t offset)
{
return 0xff; // read only
}
-WRITE8_MEMBER(gf1_device::mix_ctrl_w)
+void gf1_device::mix_ctrl_w(offs_t offset, uint8_t data)
{
if(offset == 0)
m_mix_ctrl = data;
}
-READ8_MEMBER(gf1_device::sb_r)
+uint8_t gf1_device::sb_r(offs_t offset)
{
uint8_t val;
@@ -1106,7 +1088,7 @@ READ8_MEMBER(gf1_device::sb_r)
return 0xff;
}
-WRITE8_MEMBER(gf1_device::sb_w)
+void gf1_device::sb_w(offs_t offset, uint8_t data)
{
switch(offset)
{
@@ -1127,20 +1109,17 @@ WRITE8_MEMBER(gf1_device::sb_w)
}
}
-WRITE8_MEMBER(gf1_device::sb2x6_w)
+void gf1_device::sb2x6_w(uint8_t data)
{
- if(offset==0)
+ if(m_timer_ctrl & 0x20)
{
- if(m_timer_ctrl & 0x20)
- {
- m_adlib_status |= 0x08;
- m_nmi_handler(1);
- logerror("GUS: SB 0x2X6 IRQ active\n");
- }
+ m_adlib_status |= 0x08;
+ m_nmi_handler(1);
+ logerror("GUS: SB 0x2X6 IRQ active\n");
}
}
-READ8_MEMBER(gf1_device::stat_r)
+uint8_t gf1_device::stat_r()
{
uint8_t val = m_statread & 0xf9;
if(m_mix_ctrl & 0x08)
@@ -1148,7 +1127,7 @@ READ8_MEMBER(gf1_device::stat_r)
return val;
}
-WRITE8_MEMBER(gf1_device::stat_w)
+void gf1_device::stat_w(uint8_t data)
{
m_reg_ctrl = data;
}
@@ -1252,11 +1231,10 @@ INPUT_PORTS_END
void isa16_gus_device::device_add_mconfig(machine_config &config)
{
- SPEAKER(config, "lspeaker").front_left();
- SPEAKER(config, "rspeaker").front_right();
+ SPEAKER(config, "speaker", 2).front();
GGF1(config, m_gf1, GF1_CLOCK);
- m_gf1->add_route(0, "lspeaker", 0.50);
- m_gf1->add_route(1, "rspeaker", 0.50);
+ m_gf1->add_route(0, "speaker", 0.50, 0);
+ m_gf1->add_route(1, "speaker", 0.50, 1);
m_gf1->txd_handler().set("mdout", FUNC(midi_port_device::write_txd));
m_gf1->txirq_handler().set(FUNC(isa16_gus_device::midi_txirq));
@@ -1296,10 +1274,10 @@ isa16_gus_device::isa16_gus_device(const machine_config &mconfig, const char *ta
void isa16_gus_device::device_start()
{
set_isa_device();
- m_isa->install_device(0x0200, 0x0201, read8_delegate(FUNC(isa16_gus_device::joy_r),this), write8_delegate(FUNC(isa16_gus_device::joy_w),this) );
- m_isa->install_device(0x0220, 0x022f, read8_delegate(FUNC(isa16_gus_device::board_r),this), write8_delegate(FUNC(isa16_gus_device::board_w),this) );
- m_isa->install_device(0x0320, 0x0327, read8_delegate(FUNC(isa16_gus_device::synth_r),this), write8_delegate(FUNC(isa16_gus_device::synth_w),this) );
- m_isa->install_device(0x0388, 0x0389, read8_delegate(FUNC(isa16_gus_device::adlib_r),this), write8_delegate(FUNC(isa16_gus_device::adlib_w),this) );
+ m_isa->install_device(0x0200, 0x0201, read8sm_delegate(*this, FUNC(isa16_gus_device::joy_r)), write8sm_delegate(*this, FUNC(isa16_gus_device::joy_w)));
+ m_isa->install_device(0x0220, 0x022f, read8sm_delegate(*this, FUNC(isa16_gus_device::board_r)), write8sm_delegate(*this, FUNC(isa16_gus_device::board_w)));
+ m_isa->install_device(0x0320, 0x0327, read8sm_delegate(*this, FUNC(isa16_gus_device::synth_r)), write8sm_delegate(*this, FUNC(isa16_gus_device::synth_w)));
+ m_isa->install_device(0x0388, 0x0389, read8sm_delegate(*this, FUNC(isa16_gus_device::adlib_r)), write8sm_delegate(*this, FUNC(isa16_gus_device::adlib_w)));
}
void isa16_gus_device::device_reset()
@@ -1310,13 +1288,13 @@ void isa16_gus_device::device_stop()
{
}
-READ8_MEMBER(isa16_gus_device::board_r)
+uint8_t isa16_gus_device::board_r(offs_t offset)
{
switch(offset)
{
case 0x00:
case 0x01:
- return m_gf1->mix_ctrl_r(space,offset);
+ return m_gf1->mix_ctrl_r(offset);
/* port 0x2X6 - IRQ status (active high)
* bit 0 - MIDI transmit IRQ
* bit 1 - MIDI receive IRQ
@@ -1331,55 +1309,55 @@ READ8_MEMBER(isa16_gus_device::board_r)
return m_irq_status;
case 0x08:
case 0x09:
- return m_gf1->adlib_r(space,offset-8);
+ return m_gf1->adlib_r(offset-8);
case 0x0a:
case 0x0b:
- return m_gf1->adlib_cmd_r(space,offset-10);
+ return m_gf1->adlib_cmd_r(offset-10);
case 0x0c:
case 0x0d:
case 0x0e:
- return m_gf1->sb_r(space,offset-12);
+ return m_gf1->sb_r(offset-12);
case 0x0f:
- return m_gf1->stat_r(space,offset-15);
+ return m_gf1->stat_r();
default:
logerror("GUS: Invalid or unimplemented read of port 0x2X%01x\n",offset);
return 0xff;
}
}
-WRITE8_MEMBER(isa16_gus_device::board_w)
+void isa16_gus_device::board_w(offs_t offset, uint8_t data)
{
switch(offset)
{
case 0x00:
case 0x01:
- m_gf1->mix_ctrl_w(space,offset,data);
+ m_gf1->mix_ctrl_w(offset,data);
break;
case 0x06:
- m_gf1->sb2x6_w(space,offset-6,data);
+ m_gf1->sb2x6_w(data);
break;
case 0x08:
case 0x09:
- m_gf1->adlib_w(space,offset-8,data);
+ m_gf1->adlib_w(offset-8,data);
break;
case 0x0a:
case 0x0b:
- m_gf1->adlib_cmd_w(space,offset-10,data);
+ m_gf1->adlib_cmd_w(offset-10,data);
break;
case 0x0c:
case 0x0d:
case 0x0e:
- m_gf1->sb_w(space,offset-12,data);
+ m_gf1->sb_w(offset-12,data);
break;
case 0x0f:
- m_gf1->stat_w(space,offset-15,data);
+ m_gf1->stat_w(data);
break;
default:
logerror("GUS: Invalid or unimplemented register write %02x of port 0x2X%01x\n",data,offset);
}
}
-READ8_MEMBER(isa16_gus_device::synth_r)
+uint8_t isa16_gus_device::synth_r(offs_t offset)
{
switch(offset)
{
@@ -1389,20 +1367,20 @@ READ8_MEMBER(isa16_gus_device::synth_r)
return m_gf1->data_r();
case 0x02:
case 0x03:
- return m_gf1->global_reg_select_r(space,offset-2);
+ return m_gf1->global_reg_select_r(offset-2);
case 0x04:
case 0x05:
- return m_gf1->global_reg_data_r(space,offset-4);
+ return m_gf1->global_reg_data_r(offset-4);
case 0x06:
case 0x07:
- return m_gf1->dram_r(space,offset-6);
+ return m_gf1->dram_r(offset-6);
default:
logerror("GUS: Invalid or unimplemented register read of port 0x3X%01x\n",offset);
return 0xff;
}
}
-WRITE8_MEMBER(isa16_gus_device::synth_w)
+void isa16_gus_device::synth_w(offs_t offset, uint8_t data)
{
switch(offset)
{
@@ -1414,32 +1392,32 @@ WRITE8_MEMBER(isa16_gus_device::synth_w)
break;
case 0x02:
case 0x03:
- m_gf1->global_reg_select_w(space,offset-2,data);
+ m_gf1->global_reg_select_w(offset-2,data);
break;
case 0x04:
case 0x05:
- m_gf1->global_reg_data_w(space,offset-4,data);
+ m_gf1->global_reg_data_w(offset-4,data);
break;
case 0x06:
case 0x07:
- m_gf1->dram_w(space,offset-6,data);
+ m_gf1->dram_w(offset-6,data);
break;
default:
logerror("GUS: Invalid or unimplemented register write %02x of port 0x3X%01x\n",data,offset);
}
}
-READ8_MEMBER(isa16_gus_device::adlib_r)
+uint8_t isa16_gus_device::adlib_r(offs_t offset)
{
- return m_gf1->adlib_r(space,offset);
+ return m_gf1->adlib_r(offset);
}
-WRITE8_MEMBER(isa16_gus_device::adlib_w)
+void isa16_gus_device::adlib_w(offs_t offset, uint8_t data)
{
- m_gf1->adlib_w(space,offset,data);
+ m_gf1->adlib_w(offset,data);
}
-READ8_MEMBER(isa16_gus_device::joy_r)
+uint8_t isa16_gus_device::joy_r(offs_t offset)
{
if(offset == 1)
{
@@ -1462,12 +1440,12 @@ READ8_MEMBER(isa16_gus_device::joy_r)
return 0xff;
}
-WRITE8_MEMBER(isa16_gus_device::joy_w)
+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 +1453,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 +1461,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 +1469,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 +1477,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 +1485,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 +1493,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 +1518,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 +1667,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 +1675,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 +1683,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 0009510b81f..e58fea6c9fa 100644
--- a/src/devices/bus/isa/gus.h
+++ b/src/devices/bus/isa/gus.h
@@ -98,34 +98,41 @@ public:
uint8_t dma_channel1() { return m_dma_channel1; }
uint8_t dma_channel2() { if(m_dma_combine == 0) return m_dma_channel2; else return m_dma_channel1; }
- DECLARE_READ8_MEMBER(global_reg_select_r);
- DECLARE_WRITE8_MEMBER(global_reg_select_w);
- DECLARE_READ8_MEMBER(global_reg_data_r);
- DECLARE_WRITE8_MEMBER(global_reg_data_w);
- DECLARE_READ8_MEMBER(dram_r);
- DECLARE_WRITE8_MEMBER(dram_w);
- DECLARE_READ8_MEMBER(adlib_r);
- DECLARE_WRITE8_MEMBER(adlib_w);
- DECLARE_READ8_MEMBER(adlib_cmd_r);
- DECLARE_WRITE8_MEMBER(adlib_cmd_w);
- DECLARE_READ8_MEMBER(mix_ctrl_r);
- DECLARE_WRITE8_MEMBER(mix_ctrl_w);
- DECLARE_READ8_MEMBER(stat_r);
- DECLARE_WRITE8_MEMBER(stat_w);
- DECLARE_READ8_MEMBER(sb_r);
- DECLARE_WRITE8_MEMBER(sb_w);
- DECLARE_WRITE8_MEMBER(sb2x6_w);
+ uint8_t global_reg_select_r(offs_t offset);
+ void global_reg_select_w(offs_t offset, uint8_t data);
+ uint8_t global_reg_data_r(offs_t offset);
+ void global_reg_data_w(offs_t offset, uint8_t data);
+ uint8_t dram_r(offs_t offset);
+ void dram_w(offs_t offset, uint8_t data);
+ uint8_t adlib_r(offs_t offset);
+ void adlib_w(offs_t offset, uint8_t data);
+ uint8_t adlib_cmd_r(offs_t offset);
+ void adlib_cmd_w(offs_t offset, uint8_t data);
+ uint8_t mix_ctrl_r(offs_t offset);
+ void mix_ctrl_w(offs_t offset, uint8_t data);
+ uint8_t stat_r();
+ void stat_w(uint8_t data);
+ uint8_t sb_r(offs_t offset);
+ void sb_w(offs_t offset, uint8_t data);
+ void sb2x6_w(uint8_t data);
// DMA signals
uint8_t dack_r(int line);
void dack_w(int line,uint8_t data);
void eop_w(int state);
- // optional information overrides
- virtual void device_timer(emu_timer &timer, device_timer_id id, int param, void *ptr) override;
- virtual void sound_stream_update(sound_stream &stream, stream_sample_t **inputs, stream_sample_t **outputs, int samples) override;
+ // device_sound_interface overrides
+ virtual void sound_stream_update(sound_stream &stream) override;
protected:
+ // device-level overrides
+ virtual void device_start() override ATTR_COLD;
+ virtual void device_reset() override ATTR_COLD;
+ virtual void device_stop() override ATTR_COLD;
+ virtual void device_clock_changed() override;
+
+ virtual void update_irq() override;
+
// voice-specific registers
gus_voice m_voice[32];
@@ -147,17 +154,13 @@ protected:
void set_irq(uint8_t source, uint8_t voice);
void reset_irq(uint8_t source);
- void update_volume_ramps();
-
- std::vector<uint8_t> m_wave_ram;
-
- // device-level overrides
- virtual void device_start() override;
- virtual void device_reset() override;
- virtual void device_stop() override;
- virtual void update_irq() override;
+ TIMER_CALLBACK_MEMBER(adlib_timer1_tick);
+ TIMER_CALLBACK_MEMBER(adlib_timer2_tick);
+ TIMER_CALLBACK_MEMBER(dma_tick);
+ TIMER_CALLBACK_MEMBER(update_volume_ramps);
+ std::vector<uint8_t> m_wave_ram;
private:
// internal state
sound_stream* m_stream;
@@ -198,11 +201,6 @@ private:
uint32_t m_dma_current;
uint16_t m_volume_table[4096];
- static const device_timer_id ADLIB_TIMER1 = 0;
- static const device_timer_id ADLIB_TIMER2 = 1;
- static const device_timer_id DMA_TIMER = 2;
- static const device_timer_id VOL_RAMP_TIMER = 3;
-
int m_txirq;
int m_rxirq;
@@ -230,14 +228,14 @@ public:
void set_midi_irq(uint8_t source);
void reset_midi_irq(uint8_t source);
- DECLARE_READ8_MEMBER(board_r);
- DECLARE_READ8_MEMBER(synth_r);
- DECLARE_WRITE8_MEMBER(board_w);
- DECLARE_WRITE8_MEMBER(synth_w);
- DECLARE_READ8_MEMBER(adlib_r);
- DECLARE_WRITE8_MEMBER(adlib_w);
- DECLARE_READ8_MEMBER(joy_r);
- DECLARE_WRITE8_MEMBER(joy_w);
+ uint8_t board_r(offs_t offset);
+ uint8_t synth_r(offs_t offset);
+ void board_w(offs_t offset, uint8_t data);
+ void synth_w(offs_t offset, uint8_t data);
+ uint8_t adlib_r(offs_t offset);
+ void adlib_w(offs_t offset, uint8_t data);
+ uint8_t joy_r(offs_t offset);
+ void joy_w(offs_t offset, uint8_t data);
// DMA overrides
virtual uint8_t dack_r(int line) override;
@@ -246,27 +244,27 @@ public:
protected:
// device-level overrides
- virtual void device_start() override;
- virtual void device_reset() override;
- virtual void device_stop() override;
+ virtual void device_start() override ATTR_COLD;
+ virtual void device_reset() override ATTR_COLD;
+ virtual void device_stop() override ATTR_COLD;
// optional information overrides
- virtual void device_add_mconfig(machine_config &config) override;
- virtual ioport_constructor device_input_ports() const override;
+ virtual void device_add_mconfig(machine_config &config) override ATTR_COLD;
+ virtual ioport_constructor device_input_ports() const override ATTR_COLD;
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 2492d0eaa89..d4cc9e23e5f 100644
--- a/src/devices/bus/isa/hdc.cpp
+++ b/src/devices/bus/isa/hdc.cpp
@@ -9,9 +9,12 @@
#include "emu.h"
#include "hdc.h"
-#define LOG_HDC_STATUS 0
-#define LOG_HDC_CALL 0
-#define LOG_HDC_DATA 0
+#define LOG_HDC_STATUS (1U << 1)
+#define LOG_HDC_CALL (1U << 2)
+#define LOG_HDC_DATA (1U << 3)
+
+#define VERBOSE (0)
+#include "logmacro.h"
#define CMD_TESTREADY 0x00
#define CMD_RECALIBRATE 0x01
@@ -52,7 +55,7 @@
#define CTL_PIO 0x00
#define CTL_DMA 0x01
-static const char *const hdc_command_names[] =
+const char *const s_hdc_command_names[] =
{
"CMD_TESTREADY", /* 0x00 */
"CMD_RECALIBRATE", /* 0x01 */
@@ -114,7 +117,7 @@ static const char *const 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
@@ -153,9 +156,23 @@ xt_hdc_device::xt_hdc_device(const machine_config &mconfig, const char *tag, dev
xt_hdc_device::xt_hdc_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock) :
device_t(mconfig, type, tag, owner, clock),
- buffer_ptr(nullptr), csb(0), status(0), error(0), m_type(0), m_current_cmd(0),
+ m_buffer_ptr(nullptr),
+ m_csb(0),
+ m_status(0),
+ m_error(0),
+ m_type(0),
+ m_current_cmd(0),
m_irq_handler(*this),
- m_drq_handler(*this), drv(0), timer(nullptr), data_cnt(0), hdc_control(0), hdcdma_src(nullptr), hdcdma_dst(nullptr), hdcdma_read(0), hdcdma_write(0), hdcdma_size(0)
+ m_drq_handler(*this),
+ m_drv(0),
+ m_timer(nullptr),
+ m_data_cnt(0),
+ m_hdc_control(0),
+ m_hdcdma_src(nullptr),
+ m_hdcdma_dst(nullptr),
+ m_hdcdma_read(0),
+ m_hdcdma_write(0),
+ m_hdcdma_size(0)
{
}
@@ -177,43 +194,41 @@ st11m_device::st11m_device(const machine_config &mconfig, const char *tag, devic
void xt_hdc_device::device_start()
{
- buffer.resize(256*512); // maximum possible transfer
- timer = timer_alloc();
- m_irq_handler.resolve_safe();
- m_drq_handler.resolve_safe();
+ m_buffer = std::make_unique<uint8_t[]>(256 * 512); // maximum possible transfer
+ m_timer = timer_alloc(FUNC(xt_hdc_device::process_command), this);
}
void xt_hdc_device::device_reset()
{
- drv = 0;
- data_cnt = 0;
- buffer_ptr = nullptr;
- hdc_control = 0;
+ m_drv = 0;
+ m_data_cnt = 0;
+ m_buffer_ptr = &m_buffer[0];
+ m_hdc_control = 0;
for (int i = 0; i < 2; i++)
{
- cylinders[i] = 612;
- rwc[i] = 613;
- wp[i] = 613;
- heads[i] = 4;
- ecc[i] = 11;
+ m_cylinders[i] = 612;
+ m_rwc[i] = 613;
+ m_wp[i] = 613;
+ m_heads[i] = 4;
+ m_ecc[i] = 11;
/* indexes */
- cylinder[i] = 0;
- head[i] = 0;
- sector[i] = 0;
- sector_cnt[i] = 0;
- control[i] = 0;
+ m_cylinder[i] = 0;
+ m_head[i] = 0;
+ m_sector[i] = 0;
+ m_sector_cnt[i] = 0;
+ m_control[i] = 0;
}
- csb = 0;
- status = 0;
- error = 0;
+ m_csb = 0;
+ m_status = STA_COMMAND | STA_READY;
+ 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 )
+ switch (id)
{
case 0:
img = subdevice<harddisk_image_device>("primary");
@@ -222,75 +237,66 @@ hard_disk_file *xt_hdc_device::pc_hdc_file(int id)
img = subdevice<harddisk_image_device>("slave");
break;
}
- if ( img == nullptr )
+ if (img == nullptr)
return nullptr;
if (!img->exists())
return nullptr;
- return img->get_hard_disk_file();
+ return img;
}
-void xt_hdc_device::pc_hdc_result(int set_error_info)
+void xt_hdc_device::pc_hdc_result(bool set_error_info)
{
- if ( ( hdc_control & 0x02 ))
+ if (m_hdc_control & 0x02)
{
// dip switch selected IRQ 5 or 2
m_irq_handler(1);
}
- if (LOG_HDC_STATUS)
- logerror("pc_hdc_result(): $%02x to $%04x\n", csb, data_cnt);
+ LOGMASKED(LOG_HDC_STATUS, "pc_hdc_result(): $%02x to $%04x\n", m_csb, m_data_cnt);
- buffer[data_cnt++] = csb;
+ m_buffer[m_data_cnt++] = m_csb;
- if (set_error_info && ( csb & CSB_ERROR ) )
+ if (set_error_info && (m_csb & CSB_ERROR))
{
- buffer[data_cnt++] = error;
- if (error & 0x80)
+ m_buffer[m_data_cnt++] = m_error;
+ if (m_error & 0x80)
{
- buffer[data_cnt++] = (drv << 5) | head[drv];
- buffer[data_cnt++] = ((cylinder[drv] >> 2) & 0xc0) | sector[drv];
- buffer[data_cnt++] = cylinder[drv] & 0xff;
+ m_buffer[m_data_cnt++] = (m_drv << 5) | m_head[m_drv];
+ m_buffer[m_data_cnt++] = ((m_cylinder[m_drv] >> 2) & 0xc0) | m_sector[m_drv];
+ m_buffer[m_data_cnt++] = m_cylinder[m_drv] & 0xff;
- if (LOG_HDC_STATUS)
- {
- logerror("pc_hdc_result(): result [%02x %02x %02x %02x]\n",
- buffer[data_cnt-4], buffer[data_cnt-3], buffer[data_cnt-2], buffer[data_cnt-1]);
- }
+ LOGMASKED(LOG_HDC_STATUS, "pc_hdc_result(): result [%02x %02x %02x %02x]\n",
+ m_buffer[m_data_cnt - 4], m_buffer[m_data_cnt - 3], m_buffer[m_data_cnt - 2], m_buffer[m_data_cnt - 1]);
}
else
{
- if (LOG_HDC_STATUS)
- logerror("pc_hdc_result(): result [%02x]\n", buffer[data_cnt-1]);
+ LOGMASKED(LOG_HDC_STATUS, "pc_hdc_result(): result [%02x]\n", m_buffer[m_data_cnt - 1]);
}
}
- status |= STA_INTERRUPT | STA_INPUT | STA_REQUEST | STA_COMMAND | STA_READY;
+ m_status |= STA_INTERRUPT | STA_INPUT | STA_REQUEST | STA_COMMAND | STA_READY;
}
-int xt_hdc_device::no_dma(void)
+bool xt_hdc_device::no_dma()
{
- return (hdc_control & CTL_DMA) == 0;
+ return (m_hdc_control & CTL_DMA) == 0;
}
int xt_hdc_device::get_lbasector()
{
- hard_disk_info *info;
- hard_disk_file *file;
- int lbasector;
-
- file = pc_hdc_file(drv);
- info = hard_disk_get_info(file);
-
- lbasector = cylinder[drv];
- lbasector *= info->heads;
- lbasector += head[drv];
- lbasector *= info->sectors;
- lbasector += sector[drv];
+ harddisk_image_device *file = pc_hdc_file(m_drv);
+ const auto &info = file->get_info();
+
+ int lbasector = m_cylinder[m_drv];
+ lbasector *= info.heads;
+ lbasector += m_head[m_drv];
+ lbasector *= info.sectors;
+ lbasector += m_sector[m_drv];
return lbasector;
}
@@ -304,134 +310,137 @@ int xt_hdc_device::get_lbasector()
* implementation that threw the idea of "emulating the hardware" to the wind
*/
-int xt_hdc_device::dack_r()
+uint8_t xt_hdc_device::dack_r()
{
- uint8_t result;
- hard_disk_info *info;
- hard_disk_file *file;
-
- file = pc_hdc_file(drv);
+ harddisk_image_device *file = pc_hdc_file(m_drv);
if (!file)
return 0;
- info = hard_disk_get_info(file);
+ const auto &info = file->get_info();
- if (hdcdma_read == 0)
+ if (m_hdcdma_read == 0)
{
- hard_disk_read(file, get_lbasector(), hdcdma_data);
- hdcdma_read = 512;
- hdcdma_size -= 512;
- hdcdma_src = hdcdma_data;
- sector[drv]++;
+ file->read(get_lbasector(), m_hdcdma_data);
+ m_hdcdma_read = 512;
+ m_hdcdma_size -= 512;
+ m_hdcdma_src = m_hdcdma_data;
+ m_sector[m_drv]++;
}
- result = *(hdcdma_src++);
+ uint8_t result = *(m_hdcdma_src++);
- if( --hdcdma_read == 0 )
+ if (--m_hdcdma_read == 0)
{
/* end of cylinder ? */
- if (sector[drv] >= info->sectors)
+ if (m_sector[m_drv] >= info.sectors)
{
- sector[drv] = 0;
- if (++head[drv] >= info->heads) /* beyond heads? */
+ m_sector[m_drv] = 0;
+ if (++m_head[m_drv] >= info.heads) /* beyond heads? */
{
- head[drv] = 0; /* reset head */
- cylinder[drv]++; /* next cylinder */
+ m_head[m_drv] = 0; /* reset head */
+ m_cylinder[m_drv]++; /* next cylinder */
}
}
}
if (!no_dma())
{
- m_drq_handler((hdcdma_read || hdcdma_size ) ? 1 : 0);
- if(!(hdcdma_read || hdcdma_size)) pc_hdc_result(0);
+ m_drq_handler((m_hdcdma_read || m_hdcdma_size) ? 1 : 0);
+ if (!(m_hdcdma_read || m_hdcdma_size))
+ {
+ pc_hdc_result(false);
+ }
}
return result;
}
-int xt_hdc_device::dack_rs()
+uint8_t xt_hdc_device::dack_rs()
{
- uint8_t result;
-
- logerror("%s dack_rs(%d %d)\n", machine().describe_context(), hdcdma_read, hdcdma_size);
+ logerror("%s dack_rs(%d %d)\n", machine().describe_context(), m_hdcdma_read, m_hdcdma_size);
- if (hdcdma_read == 0)
+ if (m_hdcdma_read == 0)
{
- hdcdma_read = 512;
- hdcdma_size -= 512;
- hdcdma_src = hdcdma_data;
+ m_hdcdma_read = 512;
+ m_hdcdma_size -= 512;
+ m_hdcdma_src = m_hdcdma_data;
}
- result = *(hdcdma_src++);
+ uint8_t m_result = *(m_hdcdma_src++);
- hdcdma_read--;
+ m_hdcdma_read--;
if (!no_dma())
{
- m_drq_handler((hdcdma_read) ? 1 : 0);
- if(!(hdcdma_read)) pc_hdc_result(0);
+ m_drq_handler(m_hdcdma_read ? 1 : 0);
+ if (!m_hdcdma_read)
+ {
+ pc_hdc_result(false);
+ }
}
- return result;
+ return m_result;
}
-void xt_hdc_device::dack_w(int data)
+void xt_hdc_device::dack_w(uint8_t data)
{
- hard_disk_info *info;
- hard_disk_file *file;
-
- file = pc_hdc_file(drv);
+ harddisk_image_device *file = pc_hdc_file(m_drv);
if (!file)
return;
- info = hard_disk_get_info(file);
+ const auto &info = file->get_info();
- *(hdcdma_dst++) = data;
+ *(m_hdcdma_dst++) = data;
- if( --hdcdma_write == 0 )
+ if (--m_hdcdma_write == 0)
{
- hard_disk_write(file, get_lbasector(), hdcdma_data);
- hdcdma_write = 512;
- hdcdma_size -= 512;
+ file->write(get_lbasector(), m_hdcdma_data);
+ m_hdcdma_write = 512;
+ m_hdcdma_size -= 512;
/* end of cylinder ? */
- if( ++sector[drv] >= info->sectors )
+ if (++m_sector[m_drv] >= info.sectors)
{
- sector[drv] = 0;
- if (++head[drv] >= info->heads) /* beyond heads? */
+ m_sector[m_drv] = 0;
+ if (++m_head[m_drv] >= info.heads) /* beyond heads? */
{
- head[drv] = 0; /* reset head */
- cylinder[drv]++; /* next cylinder */
+ m_head[m_drv] = 0; /* reset head */
+ m_cylinder[m_drv]++; /* next cylinder */
}
}
- hdcdma_dst = hdcdma_data;
+ m_hdcdma_dst = m_hdcdma_data;
}
if (!no_dma())
{
- m_drq_handler(hdcdma_size ? 1 : 0);
- if(!hdcdma_size) pc_hdc_result(1);
+ m_drq_handler(m_hdcdma_size ? 1 : 0);
+ if (!m_hdcdma_size)
+ {
+ pc_hdc_result(true);
+ }
}
}
-void xt_hdc_device::dack_ws(int data)
+void xt_hdc_device::dack_ws(uint8_t data)
{
- *(hdcdma_dst++) = data;
+ *(m_hdcdma_dst++) = data;
- if( --hdcdma_write == 0 )
+ if (--m_hdcdma_write == 0)
{
- hdcdma_write = 512;
- hdcdma_size -= 512;
- hdcdma_dst = hdcdma_data;
+ m_hdcdma_write = 512;
+ m_hdcdma_size -= 512;
+ m_hdcdma_dst = m_hdcdma_data;
}
if (!no_dma())
{
- m_drq_handler(hdcdma_size ? 1 : 0);
- if(!hdcdma_size) pc_hdc_result(1);
+ m_drq_handler(m_hdcdma_size ? 1 : 0);
+ if (!m_hdcdma_size)
+ {
+ pc_hdc_result(true);
+ }
}
}
@@ -439,46 +448,48 @@ void xt_hdc_device::dack_ws(int data)
void xt_hdc_device::execute_read()
{
- hard_disk_file *disk;
- int size = sector_cnt[drv] * 512;
- int read_ = 0;
+ int size = m_sector_cnt[m_drv] * 512;
- if(sector_cnt[drv] == 0)
+ if (m_sector_cnt[m_drv] == 0)
size = 256 * 512;
- disk = pc_hdc_file(drv);
+ harddisk_image_device *disk = pc_hdc_file(m_drv);
if (!disk)
return;
- status |= STA_READY; // ready to receive data
- status &= ~STA_INPUT;
- status &= ~STA_COMMAND;
+ m_status |= STA_READY; // ready to receive data
+ m_status &= ~(STA_INPUT | STA_COMMAND);
- hdcdma_src = hdcdma_data;
- hdcdma_read = read_;
- hdcdma_size = size;
+ m_hdcdma_src = m_hdcdma_data;
+ m_hdcdma_read = 0;
+ m_hdcdma_size = size;
- if(!no_dma())
+ if (!no_dma())
{
m_drq_handler(1);
- if(!hdcdma_size) pc_hdc_result(0);
+ if (!m_hdcdma_size)
+ {
+ pc_hdc_result(false);
+ }
}
}
void xt_hdc_device::execute_readsbuff()
{
- status |= STA_READY; // ready to receive data
- status &= ~STA_INPUT;
- status &= ~STA_COMMAND;
+ m_status |= STA_READY; // ready to receive data
+ m_status &= ~(STA_INPUT | STA_COMMAND);
- hdcdma_src = hdcdma_data;
- hdcdma_read = 512;
- hdcdma_size = 512;
+ m_hdcdma_src = m_hdcdma_data;
+ m_hdcdma_read = 512;
+ m_hdcdma_size = 512;
- if(!no_dma())
+ if (!no_dma())
{
m_drq_handler(1);
- if(!hdcdma_size) pc_hdc_result(0);
+ if (!m_hdcdma_size)
+ {
+ pc_hdc_result(false);
+ }
}
}
@@ -486,24 +497,22 @@ void xt_hdc_device::execute_readsbuff()
void xt_hdc_device::execute_write()
{
- hard_disk_file *disk;
- int size = sector_cnt[drv] * 512;
- int write_ = 512;
+ int size = m_sector_cnt[m_drv] * 512;
- if(sector_cnt[drv] == 0)
+ if (m_sector_cnt[m_drv] == 0)
size = 256 * 512;
- disk = pc_hdc_file(drv);
+ harddisk_image_device *disk = pc_hdc_file(m_drv);
if (!disk)
return;
- status |= STA_READY; // ready to receive data
- status |= STA_INPUT;
- status &= ~STA_COMMAND;
+ m_status |= STA_READY; // ready to receive data
+ m_status |= STA_INPUT;
+ m_status &= ~STA_COMMAND;
- hdcdma_dst = hdcdma_data;
- hdcdma_write = write_;
- hdcdma_size = size;
+ m_hdcdma_dst = m_hdcdma_data;
+ m_hdcdma_write = 512;
+ m_hdcdma_size = size;
if (!no_dma())
{
@@ -515,13 +524,13 @@ void xt_hdc_device::execute_write()
void xt_hdc_device::execute_writesbuff()
{
- hdcdma_dst = hdcdma_data;
- hdcdma_write = 512;
- hdcdma_size = 512;
+ m_hdcdma_dst = m_hdcdma_data;
+ m_hdcdma_write = 512;
+ m_hdcdma_size = 512;
- status |= STA_READY; // ready to receive data
- status |= STA_INPUT;
- status &= ~STA_COMMAND;
+ m_status |= STA_READY; // ready to receive data
+ m_status |= STA_INPUT;
+ m_status &= ~STA_COMMAND;
if (!no_dma())
{
@@ -533,75 +542,76 @@ void xt_hdc_device::execute_writesbuff()
void xt_hdc_device::get_drive()
{
- drv = (buffer[1] >> 5) & 1;
- csb = (drv) ? CSB_LUN : 0x00;
+ m_drv = BIT(m_buffer[1], 5);
+ m_csb = m_drv ? CSB_LUN : 0x00;
}
void xt_hdc_device::get_chsn()
{
- head[drv] = buffer[1] & 0x1f;
- sector[drv] = buffer[2] & 0x3f;
- cylinder[drv] = (buffer[2] & 0xc0) << 2;
- cylinder[drv] |= buffer[3];
- sector_cnt[drv] = buffer[4];
- control[drv] = buffer[5]; /* 7: no retry, 6: no ecc retry, 210: step rate */
-
- error = 0x80; /* a potential error has C/H/S/N info */
+ m_head[m_drv] = m_buffer[1] & 0x1f;
+ m_sector[m_drv] = m_buffer[2] & 0x3f;
+ m_cylinder[m_drv] = (m_buffer[2] & 0xc0) << 2;
+ m_cylinder[m_drv] |= m_buffer[3];
+ m_sector_cnt[m_drv] = m_buffer[4];
+ m_control[m_drv] = m_buffer[5]; /* 7: no retry, 6: no ecc retry, 210: step rate */
+
+ m_error = 0x80; /* a potential error has C/H/S/N info */
}
-int xt_hdc_device::test_ready()
+bool xt_hdc_device::test_ready()
{
- if( !pc_hdc_file(drv) )
+ if (!pc_hdc_file(m_drv))
{
- csb |= CSB_ERROR;
- error |= 0x04; /* drive not ready */
- return 0;
+ m_csb |= CSB_ERROR;
+ m_error |= 0x04; /* drive not ready */
+ return false;
}
- return 1;
+ return true;
}
-void xt_hdc_device::command()
+TIMER_CALLBACK_MEMBER(xt_hdc_device::process_command)
{
- int set_error_info = 1;
- int old_error = error; /* Previous error data is needed for CMD_SENSE */
- const char *command_name;
+ int old_error = m_error; /* Previous error data is needed for CMD_SENSE */
- csb = 0x00;
- error = 0;
+ m_csb = 0x00;
+ m_error = 0;
- buffer_ptr = &buffer[0];
+ m_buffer_ptr = &m_buffer[0];
get_drive();
- data_cnt = 0;
+ m_data_cnt = 0;
- if (LOG_HDC_STATUS)
- {
- command_name = hdc_command_names[m_current_cmd] ? hdc_command_names[m_current_cmd] : "Unknown";
- logerror("%s pc_hdc_command(): Executing command; cmd=0x%02x (%s) drv=%d\n",
- machine().describe_context(), m_current_cmd, command_name, drv);
- }
+ LOGMASKED(LOG_HDC_STATUS, "%s pc_hdc_command(): Executing command; cmd=0x%02x (%s) drv=%d\n",
+ machine().describe_context(), m_current_cmd, s_hdc_command_names[m_current_cmd] ? s_hdc_command_names[m_current_cmd] : "Unknown", m_drv);
switch (m_current_cmd)
{
case CMD_TESTREADY:
- set_error_info = 0;
test_ready();
- if(no_dma()) pc_hdc_result(set_error_info);
+ if (no_dma())
+ {
+ pc_hdc_result(false);
+ }
break;
case CMD_SENSE:
/* Perform error code translation. This may need to be expanded in the future. */
- buffer[data_cnt++] = ( old_error & 0xC0 ) | ( ( old_error & 0x04 ) ? 0x04 : 0x00 ) ;
- buffer[data_cnt++] = (drv << 5) | head[drv];
- buffer[data_cnt++] = ((cylinder[drv] >> 2) & 0xc0) | sector[drv];
- buffer[data_cnt++] = cylinder[drv] & 0xff;
- set_error_info = 0;
- if(no_dma()) pc_hdc_result(set_error_info);
+ m_buffer[m_data_cnt++] = (old_error & 0xc0) | (old_error & 0x04);
+ m_buffer[m_data_cnt++] = (m_drv << 5) | m_head[m_drv];
+ m_buffer[m_data_cnt++] = ((m_cylinder[m_drv] >> 2) & 0xc0) | m_sector[m_drv];
+ m_buffer[m_data_cnt++] = m_cylinder[m_drv] & 0xff;
+ if (no_dma())
+ {
+ pc_hdc_result(false);
+ }
break;
case CMD_RECALIBRATE:
get_chsn();
- if(no_dma()) pc_hdc_result(set_error_info);
+ if (no_dma())
+ {
+ pc_hdc_result(true);
+ }
break;
case CMD_FORMATDRV:
@@ -612,31 +622,27 @@ void xt_hdc_device::command()
case CMD_DRIVEDIAG:
get_chsn();
test_ready();
- if(no_dma()) pc_hdc_result(set_error_info);
+ if (no_dma())
+ {
+ pc_hdc_result(true);
+ }
break;
case CMD_READ:
case CMD_READLONG:
get_chsn();
- if (LOG_HDC_STATUS)
- {
- logerror("%s hdc read D:%d C:%d H:%d S:%d N:%d CTL:$%02x\n",
- machine().describe_context(), drv, cylinder[drv], head[drv], sector[drv], sector_cnt[drv], control[drv]);
- }
+ LOGMASKED(LOG_HDC_STATUS, "%s hdc read D:%d C:%d H:%d S:%d N:%d CTL:$%02x\n",
+ machine().describe_context(), m_drv, m_cylinder[m_drv], m_head[m_drv], m_sector[m_drv], m_sector_cnt[m_drv], m_control[m_drv]);
if (test_ready())
execute_read();
else
- pc_hdc_result(1);
- set_error_info = 0;
+ pc_hdc_result(true);
break;
case CMD_READSBUFF:
- if (LOG_HDC_STATUS)
- {
- logerror("%s hdc read sector buffer\n", machine().describe_context());
- }
+ LOGMASKED(LOG_HDC_STATUS, "%s hdc read sector buffer\n", machine().describe_context());
execute_readsbuff();
break;
@@ -645,53 +651,50 @@ void xt_hdc_device::command()
case CMD_WRITELONG:
get_chsn();
- if (LOG_HDC_STATUS)
- {
- logerror("%s hdc write D:%d C:%d H:%d S:%d N:%d CTL:$%02x\n",
- machine().describe_context(), drv, cylinder[drv], head[drv], sector[drv], sector_cnt[drv], control[drv]);
- }
+ LOGMASKED(LOG_HDC_STATUS, "%s hdc write D:%d C:%d H:%d S:%d N:%d CTL:$%02x\n",
+ machine().describe_context(), m_drv, m_cylinder[m_drv], m_head[m_drv], m_sector[m_drv], m_sector_cnt[m_drv], m_control[m_drv]);
if (test_ready())
execute_write();
break;
case CMD_WRITESBUFF:
- if (LOG_HDC_STATUS)
- {
- logerror("%s hdc write sector buffer\n", machine().describe_context());
- }
+ LOGMASKED(LOG_HDC_STATUS, "%s hdc write sector buffer\n", machine().describe_context());
execute_writesbuff();
break;
case CMD_SETPARAM:
get_chsn();
- cylinders[drv] = ((buffer[6]&3)<<8) | buffer[7];
- heads[drv] = buffer[8] & 0x1f;
- rwc[drv] = ((buffer[9]&3)<<8) | buffer[10];
- wp[drv] = ((buffer[11]&3)<<8) | buffer[12];
- ecc[drv] = buffer[13];
- if(no_dma()) pc_hdc_result(set_error_info);
+ m_cylinders[m_drv] = ((m_buffer[6] & 3) << 8) | m_buffer[7];
+ m_heads[m_drv] = m_buffer[8] & 0x1f;
+ m_rwc[m_drv] = ((m_buffer[9] & 3) << 8) | m_buffer[10];
+ m_wp[m_drv] = ((m_buffer[11] & 3) << 8) | m_buffer[12];
+ m_ecc[m_drv] = m_buffer[13];
+ if (no_dma())
+ {
+ pc_hdc_result(true);
+ }
break;
case CMD_GETECC:
- buffer[data_cnt++] = ecc[drv];
- if(no_dma()) pc_hdc_result(set_error_info);
+ m_buffer[m_data_cnt++] = m_ecc[m_drv];
+ if (no_dma())
+ {
+ pc_hdc_result(true);
+ }
break;
case CMD_RAMDIAG:
case CMD_INTERNDIAG:
- if(no_dma()) pc_hdc_result(set_error_info);
+ if (no_dma())
+ {
+ pc_hdc_result(true);
+ }
break;
}
}
-void xt_hdc_device::device_timer(emu_timer &timer, device_timer_id id, int param, void *ptr)
-{
- command();
-}
-
-
/* Command format
* Bits Description
* 7 0
@@ -712,43 +715,41 @@ void xt_hdc_device::device_timer(emu_timer &timer, device_timer_id id, int param
* cccccccc write precomp l
* eeeeeeee ecc
*/
-void xt_hdc_device::data_w(int data)
+void xt_hdc_device::data_w(uint8_t data)
{
- if(!(status & STA_COMMAND) && m_current_cmd != CMD_SETPARAM)
+ if (!(m_status & STA_COMMAND) && m_current_cmd != CMD_SETPARAM)
{
- if (LOG_HDC_DATA)
- logerror("hdc_data_w PIO $%02x (%i) (%s): \n", data,data_cnt,hdc_command_names[m_current_cmd] ? hdc_command_names[m_current_cmd] : "Unknown");
+ LOGMASKED(LOG_HDC_DATA, "hdc_data_w PIO $%02x (%i) (%s): \n", data, m_data_cnt, s_hdc_command_names[m_current_cmd] ? s_hdc_command_names[m_current_cmd] : "Unknown");
// PIO data transfer
- buffer[data_cnt++] = data;
- if(data_cnt >= hdcdma_size)
+ m_buffer[m_data_cnt++] = data;
+ if (m_data_cnt >= m_hdcdma_size)
{
- data_cnt = 0;
+ m_data_cnt = 0;
// write to disk
do
{
- if(m_current_cmd == CMD_WRITESBUFF)
- dack_ws(buffer[data_cnt++]);
+ if (m_current_cmd == CMD_WRITESBUFF)
+ dack_ws(m_buffer[m_data_cnt++]);
else
- dack_w(buffer[data_cnt++]);
+ dack_w(m_buffer[m_data_cnt++]);
}
- while (hdcdma_size);
- data_cnt = 0;
- pc_hdc_result(1);
+ while (m_hdcdma_size);
+ m_data_cnt = 0;
+ pc_hdc_result(true);
}
return;
}
- if( data_cnt == 0 )
+ if (m_data_cnt == 0)
{
- buffer_ptr = &buffer[0];
+ m_buffer_ptr = &m_buffer[0];
m_current_cmd = data;
- data_cnt = 6; /* expect 6 bytes including this one */
- status &= ~STA_READY;
- status &= ~STA_INPUT;
+ m_data_cnt = 6; /* expect 6 bytes including this one */
+ m_status &= ~(STA_READY | STA_INPUT);
switch (data)
{
case CMD_SETPARAM:
- data_cnt += 8;
+ m_data_cnt += 8;
break;
case CMD_TESTREADY:
@@ -772,76 +773,74 @@ void xt_hdc_device::data_w(int data)
break;
default:
- data_cnt = 0;
- status |= STA_INPUT;
- csb |= CSB_ERROR | 0x20; /* unknown command */
- pc_hdc_result(1);
+ m_data_cnt = 0;
+ m_status |= STA_INPUT;
+ m_csb |= CSB_ERROR | 0x20; /* unknown command */
+ pc_hdc_result(true);
break;
}
- if( data_cnt )
- status |= STA_REQUEST;
+ if (m_data_cnt)
+ m_status |= STA_REQUEST;
}
- if (data_cnt)
+ if (m_data_cnt)
{
- if (LOG_HDC_DATA)
- logerror("hdc_data_w $%02x (%i) (%s): \n", data,data_cnt,hdc_command_names[m_current_cmd] ? hdc_command_names[m_current_cmd] : "Unknown");
+ LOGMASKED(LOG_HDC_DATA, "hdc_data_w $%02x (%i) (%s): \n", data, m_data_cnt, s_hdc_command_names[m_current_cmd] ? s_hdc_command_names[m_current_cmd] : "Unknown");
- *buffer_ptr++ = data;
+ *m_buffer_ptr++ = data;
// XXX ec1841 wants this
- if (m_current_cmd == CMD_SETPARAM && data_cnt == 9 && (m_type == EC1841)) {
- status &= ~STA_READY;
- } else {
- status |= STA_READY;
- if(m_current_cmd == CMD_SETPARAM && data_cnt == 9) // some controllers want geometry info as data, not as a command (true for the Seagate ST11M?)
- status &= ~STA_COMMAND;
+ if (m_current_cmd == CMD_SETPARAM && m_data_cnt == 9 && m_type == EC1841)
+ {
+ m_status &= ~STA_READY;
}
- if (--data_cnt == 0)
+ else
{
- if (LOG_HDC_STATUS)
- logerror("%s pc_hdc_data_w(): Launching command\n", machine().describe_context());
-
- status &= ~STA_COMMAND;
- status &= ~STA_REQUEST;
- status &= ~STA_READY;
- status &= ~STA_INPUT;
- timer->adjust(attotime::from_msec(1),0);
+ m_status |= STA_READY;
+ if (m_current_cmd == CMD_SETPARAM && m_data_cnt == 9) // some controllers want geometry info as data, not as a command (true for the Seagate ST11M?)
+ m_status &= ~STA_COMMAND;
+ }
+ if (--m_data_cnt == 0)
+ {
+ LOGMASKED(LOG_HDC_STATUS, "%s pc_hdc_data_w(): Launching command\n", machine().describe_context());
+
+ m_status &= ~(STA_COMMAND | STA_REQUEST | STA_READY | STA_INPUT);
+ m_timer->adjust(attotime::from_msec(1));
}
}
}
-void xt_hdc_device::reset_w(int data)
+void xt_hdc_device::reset_w(uint8_t data)
{
- cylinder[0] = cylinder[1] = 0;
- head[0] = head[1] = 0;
- sector[0] = sector[1] = 0;
- csb = 0;
- status = STA_COMMAND | STA_READY;
- memset(&buffer[0], 0, buffer.size());
- buffer_ptr = &buffer[0];
- data_cnt = 0;
+ m_cylinder[0] = m_cylinder[1] = 0;
+ m_head[0] = m_head[1] = 0;
+ m_sector[0] = m_sector[1] = 0;
+ m_csb = 0;
+ m_status = STA_COMMAND | STA_READY;
+ std::fill_n(&m_buffer[0], 256*512, 0);
+ m_buffer_ptr = &m_buffer[0];
+ m_data_cnt = 0;
}
-void xt_hdc_device::select_w(int data)
+void xt_hdc_device::select_w(uint8_t data)
{
- status &= ~STA_INTERRUPT;
- status |= STA_SELECT;
+ m_status &= ~STA_INTERRUPT;
+ m_status |= STA_SELECT;
+ m_status |= STA_READY;
}
-void xt_hdc_device::control_w(int data)
+void xt_hdc_device::control_w(uint8_t data)
{
- if (LOG_HDC_STATUS)
- logerror("%s: pc_hdc_control_w(): control write %d\n", machine().describe_context(), data);
+ LOGMASKED(LOG_HDC_STATUS, "%s: pc_hdc_control_w(): control write %d\n", machine().describe_context(), data);
- hdc_control = data;
+ m_hdc_control = data;
- if (!(hdc_control & 0x02))
+ if (!(m_hdc_control & 0x02))
{
m_irq_handler(0);
}
@@ -853,44 +852,40 @@ uint8_t xt_hdc_device::data_r()
{
uint8_t data = 0xff;
- if(!(status & STA_COMMAND) && (m_current_cmd == CMD_READ || m_current_cmd == CMD_READLONG || m_current_cmd == CMD_READSBUFF))
+ if (!(m_status & STA_COMMAND) && (m_current_cmd == CMD_READ || m_current_cmd == CMD_READLONG || m_current_cmd == CMD_READSBUFF))
{
// PIO data transfer
- if(data_cnt == 0)
+ if (m_data_cnt == 0)
{
do
{
if (m_current_cmd == CMD_READSBUFF)
- buffer[data_cnt++] = dack_rs();
+ m_buffer[m_data_cnt++] = dack_rs();
else
- buffer[data_cnt++] = dack_r();
- } while (hdcdma_read);
- data_cnt = 0;
+ m_buffer[m_data_cnt++] = dack_r();
+ } while (m_hdcdma_read);
+ m_data_cnt = 0;
}
- data = buffer[data_cnt++];
- if(data_cnt >= ((sector_cnt[drv]!=0) ? (sector_cnt[drv] * 512) : (256 * 512)))
+ data = m_buffer[m_data_cnt++];
+ if (m_data_cnt >= ((m_sector_cnt[m_drv] != 0) ? (m_sector_cnt[m_drv] * 512) : (256 * 512)))
{
- data_cnt = 0;
- pc_hdc_result(1);
+ m_data_cnt = 0;
+ pc_hdc_result(true);
}
- if (LOG_HDC_DATA)
- logerror("hdc_data_r PIO $%02x (%i): \n", data,data_cnt);
+ LOGMASKED(LOG_HDC_DATA, "hdc_data_r PIO $%02x (%i): \n", data, m_data_cnt);
return data;
}
- if( data_cnt )
+ if (m_data_cnt)
{
- data = *buffer_ptr++;
- status &= ~STA_INTERRUPT;
- if( --data_cnt == 0 )
+ data = *m_buffer_ptr++;
+ m_status &= ~STA_INTERRUPT;
+ if (--m_data_cnt == 0)
{
- status &= ~STA_INPUT;
- status &= ~STA_REQUEST;
- status &= ~STA_SELECT;
- status |= STA_COMMAND;
+ m_status &= ~(STA_INPUT | STA_REQUEST | STA_SELECT);
+ m_status |= STA_COMMAND;
}
- if (LOG_HDC_DATA)
- logerror("hdc_data_r $%02x (%i): \n", data,data_cnt);
+ LOGMASKED(LOG_HDC_DATA, "hdc_data_r $%02x (%i): \n", data, m_data_cnt);
}
return data;
}
@@ -899,12 +894,12 @@ uint8_t xt_hdc_device::data_r()
uint8_t xt_hdc_device::status_r()
{
- return status;
+ return m_status;
}
void xt_hdc_device::set_ready()
{
- status |= STA_READY; // XXX
+ m_status |= STA_READY; // XXX
}
//**************************************************************************
@@ -923,8 +918,8 @@ void isa8_hdc_device::device_add_mconfig(machine_config &config)
XT_HDC(config, m_hdc,0);
m_hdc->irq_handler().set(FUNC(isa8_hdc_device::irq_w));
m_hdc->drq_handler().set(FUNC(isa8_hdc_device::drq_w));
- HARDDISK(config, "hdc:primary");
- HARDDISK(config, "hdc:slave");
+ HARDDISK(config, "hdc:primary", "st_hdd");
+ HARDDISK(config, "hdc:slave", "st_hdd");
}
void isa8_hdc_ec1841_device::device_add_mconfig(machine_config &config)
@@ -932,8 +927,8 @@ void isa8_hdc_ec1841_device::device_add_mconfig(machine_config &config)
EC1841_HDC(config, m_hdc,0);
m_hdc->irq_handler().set(FUNC(isa8_hdc_ec1841_device::irq_w));
m_hdc->drq_handler().set(FUNC(isa8_hdc_ec1841_device::drq_w));
- HARDDISK(config, "hdc:primary");
- HARDDISK(config, "hdc:slave");
+ HARDDISK(config, "hdc:primary", "st_hdd");
+ HARDDISK(config, "hdc:slave", "st_hdd");
}
//-------------------------------------------------
@@ -970,7 +965,8 @@ isa8_hdc_device::isa8_hdc_device(const machine_config &mconfig, const char *tag,
isa8_hdc_device::isa8_hdc_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_hdc(*this,"hdc"), dip(0)
+ m_hdc(*this,"hdc"),
+ m_dip(0)
{
}
@@ -987,7 +983,7 @@ isa8_hdc_ec1841_device::isa8_hdc_ec1841_device(const machine_config &mconfig, co
void isa8_hdc_device::device_start()
{
set_isa_device();
- m_isa->install_device(0x0320, 0x0323, read8_delegate( FUNC(isa8_hdc_device::pc_hdc_r), this ), write8_delegate( FUNC(isa8_hdc_device::pc_hdc_w), this ) );
+ m_isa->install_device(0x0320, 0x0323, read8sm_delegate(*this, FUNC(isa8_hdc_device::pc_hdc_r)), write8sm_delegate(*this, FUNC(isa8_hdc_device::pc_hdc_w)));
m_isa->set_dma_channel(3, this, false);
}
@@ -997,10 +993,10 @@ void isa8_hdc_device::device_start()
void isa8_hdc_device::device_reset()
{
- dip = ioport("HDD")->read();
+ m_dip = ioport("HDD")->read();
if (ioport("ROM")->read() == 1 && m_hdc->install_rom())
- m_isa->install_rom(this, 0xc8000, 0xc9fff, "hdc", "hdc");
+ m_isa->install_rom(this, 0xc8000, 0xc9fff, "hdc");
}
/*************************************************************************
@@ -1009,11 +1005,12 @@ void isa8_hdc_device::device_reset()
* hard disk controller
*
*************************************************************************/
-READ8_MEMBER( isa8_hdc_device::pc_hdc_r )
+
+uint8_t isa8_hdc_device::pc_hdc_r(offs_t offset)
{
uint8_t data = 0xff;
- switch( offset )
+ switch (offset)
{
case 0: data = m_hdc->data_r(); break;
case 1: data = m_hdc->status_r(); break;
@@ -1021,18 +1018,16 @@ READ8_MEMBER( isa8_hdc_device::pc_hdc_r )
case 3: break;
}
- if (LOG_HDC_CALL)
- logerror("%s pc_hdc_r(): offs=%d result=0x%02x\n", machine().describe_context(), offset, data);
+ LOGMASKED(LOG_HDC_CALL, "%s pc_hdc_r(): offs=%d result=0x%02x\n", machine().describe_context(), offset, data);
return data;
}
-WRITE8_MEMBER( isa8_hdc_device::pc_hdc_w )
+void isa8_hdc_device::pc_hdc_w(offs_t offset, uint8_t data)
{
- if (LOG_HDC_CALL)
- logerror("%s pc_hdc_w(): offs=%d data=0x%02x\n", machine().describe_context(), offset, data);
+ LOGMASKED(LOG_HDC_CALL, "%s pc_hdc_w(): offs=%d data=0x%02x\n", machine().describe_context(), offset, data);
- switch( offset )
+ switch (offset)
{
case 0: m_hdc->data_w(data); break;
case 1: m_hdc->reset_w(data); break;
@@ -1050,7 +1045,7 @@ uint8_t isa8_hdc_device::dack_r(int line)
return m_hdc->dack_r();
}
-void isa8_hdc_device::dack_w(int line,uint8_t data)
+void isa8_hdc_device::dack_w(int line, uint8_t data)
{
if (m_hdc->get_command() == CMD_WRITESBUFF)
m_hdc->dack_ws(data);
@@ -1076,20 +1071,19 @@ void isa8_hdc_device::dack_w(int line,uint8_t data)
uint8_t isa8_hdc_device::pc_hdc_dipswitch_r()
{
m_hdc->set_ready();
- if (LOG_HDC_STATUS)
- logerror("%s: pc_hdc_dipswitch_r: status $%02X\n", machine().describe_context(), m_hdc->status_r());
- return dip;
+ LOGMASKED(LOG_HDC_STATUS, "%s: pc_hdc_dipswitch_r: status $%02X\n", machine().describe_context(), m_hdc->status_r());
+ return m_dip;
}
-WRITE_LINE_MEMBER( isa8_hdc_device::irq_w )
+void isa8_hdc_device::irq_w(int state)
{
- if (BIT(dip, 6))
+ if (BIT(m_dip, 6))
m_isa->irq5_w(state);
else
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 7d60d40b7a5..905f3b7b20d 100644
--- a/src/devices/bus/isa/hdc.h
+++ b/src/devices/bus/isa/hdc.h
@@ -30,32 +30,31 @@ public:
auto irq_handler() { return m_irq_handler.bind(); }
auto drq_handler() { return m_drq_handler.bind(); }
- int dack_r();
- int dack_rs();
- void dack_w(int data);
- void dack_ws(int data);
-
- virtual void command();
- void data_w(int data);
- void reset_w(int data);
- void select_w(int data);
- void control_w(int data);
+ uint8_t dack_r();
+ uint8_t dack_rs();
+ void dack_w(uint8_t data);
+ void dack_ws(uint8_t data);
+
+ void data_w(uint8_t data);
+ void reset_w(uint8_t data);
+ void select_w(uint8_t data);
+ void control_w(uint8_t data);
uint8_t data_r();
uint8_t status_r();
void set_ready();
- uint8_t get_command() { return buffer[0]; }
+ uint8_t get_command() { return m_buffer[0]; }
bool install_rom() { return (m_type != EC1841); }
protected:
xt_hdc_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_timer(emu_timer &timer, device_timer_id id, int param, void *ptr) override;
- hard_disk_file *pc_hdc_file(int id);
- void pc_hdc_result(int set_error_info);
- int no_dma(void);
+ virtual void device_start() override ATTR_COLD;
+ virtual void device_reset() override ATTR_COLD;
+
+ harddisk_image_device *pc_hdc_file(int id);
+ void pc_hdc_result(bool set_error_info);
+ bool no_dma();
int get_lbasector();
void execute_read();
void execute_readsbuff();
@@ -63,13 +62,15 @@ protected:
void execute_writesbuff();
void get_drive();
void get_chsn();
- int test_ready();
+ bool test_ready();
+
+ TIMER_CALLBACK_MEMBER(process_command);
- std::vector<uint8_t> buffer; /* data buffer */
- uint8_t *buffer_ptr; /* data pointer */
- int csb; /* command status byte */
- int status; /* drive status */
- int error; /* error code */
+ std::unique_ptr<uint8_t[]> m_buffer; /* data buffer */
+ uint8_t *m_buffer_ptr; /* data pointer */
+ int m_csb; /* command status byte */
+ int m_status; /* drive status */
+ int m_error; /* error code */
enum {
STANDARD,
@@ -82,31 +83,31 @@ protected:
devcb_write_line m_drq_handler;
private:
- int drv; /* 0 master, 1 slave drive */
- int cylinders[2]; /* number of cylinders */
- int rwc[2]; /* reduced write current from cyl */
- int wp[2]; /* write precompensation from cyl */
- int heads[2]; /* heads */
- int ecc[2]; /* ECC bytes */
+ int m_drv; /* 0 master, 1 slave drive */
+ int m_cylinders[2]; /* number of cylinders */
+ int m_rwc[2]; /* reduced write current from cyl */
+ int m_wp[2]; /* write precompensation from cyl */
+ int m_heads[2]; /* heads */
+ int m_ecc[2]; /* ECC bytes */
/* indexes */
- int cylinder[2]; /* current cylinder */
- int head[2]; /* current head */
- int sector[2]; /* current sector */
- int sector_cnt[2]; /* sector count */
- int control[2]; /* control */
-
- emu_timer *timer;
-
- int data_cnt; /* data count */
- uint8_t hdc_control;
-
- uint8_t hdcdma_data[512];
- uint8_t *hdcdma_src;
- uint8_t *hdcdma_dst;
- int hdcdma_read;
- int hdcdma_write;
- int hdcdma_size;
+ int m_cylinder[2]; /* current cylinder */
+ int m_head[2]; /* current head */
+ int m_sector[2]; /* current sector */
+ int m_sector_cnt[2]; /* sector count */
+ int m_control[2]; /* control */
+
+ emu_timer *m_timer;
+
+ int m_data_cnt; /* data count */
+ uint8_t m_hdc_control;
+
+ uint8_t m_hdcdma_data[512];
+ uint8_t *m_hdcdma_src;
+ uint8_t *m_hdcdma_dst;
+ int m_hdcdma_read;
+ int m_hdcdma_write;
+ int m_hdcdma_size;
};
class ec1841_device : public xt_hdc_device
@@ -142,31 +143,31 @@ public:
// construction/destruction
isa8_hdc_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
- DECLARE_READ8_MEMBER(pc_hdc_r);
- DECLARE_WRITE8_MEMBER(pc_hdc_w);
+ uint8_t pc_hdc_r(offs_t offset);
+ void pc_hdc_w(offs_t offset, uint8_t data);
required_device<xt_hdc_device> m_hdc;
protected:
isa8_hdc_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_start() override ATTR_COLD;
+ virtual void device_reset() override ATTR_COLD;
// 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 void device_add_mconfig(machine_config &config) override ATTR_COLD;
+ virtual const tiny_rom_entry *device_rom_region() const override ATTR_COLD;
+ virtual ioport_constructor device_input_ports() const override ATTR_COLD;
- 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;
virtual void dack_w(int line,uint8_t data) override;
uint8_t pc_hdc_dipswitch_r();
- int dip; /* dip switches */
+ int m_dip; /* dip switches */
};
@@ -177,7 +178,7 @@ public:
protected:
// optional information overrides
- virtual void device_add_mconfig(machine_config &config) override;
+ virtual void device_add_mconfig(machine_config &config) override ATTR_COLD;
required_device<ec1841_device> m_hdc;
};
diff --git a/src/devices/bus/isa/hpblp.cpp b/src/devices/bus/isa/hpblp.cpp
new file mode 100644
index 00000000000..e8bbd9b3e12
--- /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:1,2")
+ 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:1,2,3")
+ 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..cea8bac519c
--- /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 ATTR_COLD;
+ 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;
+ virtual const tiny_rom_entry *device_rom_region() const override ATTR_COLD;
+
+private:
+ // ISA part
+ void isamap(address_map &map) ATTR_COLD;
+
+ 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) ATTR_COLD;
+
+ 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 40ce54ff6fc..9f57836fd3e 100644
--- a/src/devices/bus/isa/ibm_mfc.cpp
+++ b/src/devices/bus/isa/ibm_mfc.cpp
@@ -5,7 +5,6 @@
ISA 8 bit IBM PC Music Feature Card
TODO:
- - YM-2164
- MIDI
- IRQ/base address selection
@@ -126,7 +125,7 @@ void isa8_ibm_mfc_device::io_map(address_map &map)
{
map.unmap_value_high();
map.global_mask(0xff);
- map(0x00, 0x01).rw(m_ym2151, FUNC(ym2151_device::read), FUNC(ym2151_device::write));
+ map(0x00, 0x01).rw(m_ym2164, FUNC(ym2164_device::read), FUNC(ym2164_device::write));
map(0x10, 0x10).rw("d71051", FUNC(i8251_device::data_r), FUNC(i8251_device::data_w));
map(0x11, 0x11).rw("d71051", FUNC(i8251_device::status_r), FUNC(i8251_device::control_w));
map(0x20, 0x23).rw("d71055c_1", FUNC(i8255_device::read), FUNC(i8255_device::write));
@@ -159,18 +158,18 @@ INPUT_PORTS_END
// D71055C PPI (PC)
//-------------------------------------------------
-READ8_MEMBER( isa8_ibm_mfc_device::ppi0_i_a )
+uint8_t isa8_ibm_mfc_device::ppi0_i_a()
{
// Read data from the Z80 PIU
return m_d71055c_1->pa_r();
}
-WRITE8_MEMBER( isa8_ibm_mfc_device::ppi0_o_b )
+void isa8_ibm_mfc_device::ppi0_o_b(uint8_t data)
{
// Write data to the Z80 PIU - no action required
}
-WRITE8_MEMBER( isa8_ibm_mfc_device::ppi0_o_c )
+void isa8_ibm_mfc_device::ppi0_o_c(uint8_t data)
{
// PC Port B /OBF (C1) -> Z80 Port B /STB (C2)
m_d71055c_1->pc2_w(BIT(data, 1));
@@ -192,7 +191,7 @@ WRITE8_MEMBER( isa8_ibm_mfc_device::ppi0_o_c )
m_pc_ppi_c = data;
}
-READ8_MEMBER( isa8_ibm_mfc_device::ppi0_i_c )
+uint8_t isa8_ibm_mfc_device::ppi0_i_c()
{
// Receive data bit 8
return BIT(m_z80_ppi_c, 5) << 7;
@@ -202,18 +201,18 @@ READ8_MEMBER( isa8_ibm_mfc_device::ppi0_i_c )
// D71055C PPI (Z80)
//-------------------------------------------------
-WRITE8_MEMBER( isa8_ibm_mfc_device::ppi1_o_a )
+void isa8_ibm_mfc_device::ppi1_o_a(uint8_t data)
{
// Write data to the PC PIU - no action required
}
-READ8_MEMBER( isa8_ibm_mfc_device::ppi1_i_b )
+uint8_t isa8_ibm_mfc_device::ppi1_i_b()
{
// Read data from the PC PIU
return m_d71055c_0->pb_r();
}
-WRITE8_MEMBER( isa8_ibm_mfc_device::ppi1_o_c )
+void isa8_ibm_mfc_device::ppi1_o_c(uint8_t data)
{
// PortA /OBF (C7) -> PortA /STB (C2)
m_d71055c_0->pc4_w(BIT(data, 7));
@@ -236,13 +235,13 @@ WRITE8_MEMBER( isa8_ibm_mfc_device::ppi1_o_c )
// 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);
@@ -253,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);
@@ -264,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);
}
@@ -274,7 +273,7 @@ WRITE_LINE_MEMBER(isa8_ibm_mfc_device::ibm_mfc_ym_irq)
// ISA interface
//-------------------------------------------------
-READ8_MEMBER( isa8_ibm_mfc_device::ibm_mfc_r )
+uint8_t isa8_ibm_mfc_device::ibm_mfc_r(offs_t offset)
{
uint8_t val;
@@ -307,7 +306,7 @@ READ8_MEMBER( isa8_ibm_mfc_device::ibm_mfc_r )
return val;
}
-WRITE8_MEMBER( isa8_ibm_mfc_device::ibm_mfc_w )
+void isa8_ibm_mfc_device::ibm_mfc_w(offs_t offset, uint8_t data)
{
switch (offset)
{
@@ -316,7 +315,7 @@ WRITE8_MEMBER( isa8_ibm_mfc_device::ibm_mfc_w )
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;
}
@@ -396,7 +395,7 @@ void isa8_ibm_mfc_device::device_add_mconfig(machine_config &config)
clock_device &usart_clock(CLOCK(config, "usart_clock", XTAL(4'000'000) / 8)); // 500KHz
usart_clock.signal_handler().set(FUNC(isa8_ibm_mfc_device::write_usart_clock));
- PIT8253(config, m_d8253, 0);
+ PIT8253(config, m_d8253);
m_d8253->set_clk<0>(XTAL(4'000'000) / 8);
m_d8253->out_handler<0>().set(FUNC(isa8_ibm_mfc_device::d8253_out0));
m_d8253->set_clk<1>(0);
@@ -406,10 +405,10 @@ void isa8_ibm_mfc_device::device_add_mconfig(machine_config &config)
SPEAKER(config, "ymleft").front_left();
SPEAKER(config, "ymright").front_right();
- YM2151(config, m_ym2151, XTAL(4'000'000));
- m_ym2151->irq_handler().set(FUNC(isa8_ibm_mfc_device::ibm_mfc_ym_irq));
- m_ym2151->add_route(0, "ymleft", 1.00);
- m_ym2151->add_route(1, "ymright", 1.00);
+ YM2164(config, m_ym2164, XTAL(4'000'000));
+ m_ym2164->irq_handler().set(FUNC(isa8_ibm_mfc_device::ibm_mfc_ym_irq));
+ m_ym2164->add_route(0, "ymleft", 1.00);
+ m_ym2164->add_route(1, "ymright", 1.00);
}
@@ -447,7 +446,7 @@ isa8_ibm_mfc_device::isa8_ibm_mfc_device(const machine_config &mconfig, const ch
device_isa8_card_interface(mconfig, *this),
m_tcr(0), m_pc_ppi_c(0), m_z80_ppi_c(0), m_pc_irq_state(0), m_z80_irq_state(0),
m_cpu(*this, "ibm_mfc"),
- m_ym2151(*this, "ym2151"),
+ m_ym2164(*this, "ym2164"),
m_d8253(*this, "d8253"),
m_d71051(*this, "d71051"),
m_d71055c_0(*this, "d71055c_0"),
@@ -463,7 +462,7 @@ isa8_ibm_mfc_device::isa8_ibm_mfc_device(const machine_config &mconfig, const ch
void isa8_ibm_mfc_device::device_start()
{
set_isa_device();
- m_isa->install_device(0x2a20, 0x2a20 + 15, read8_delegate(FUNC(isa8_ibm_mfc_device::ibm_mfc_r), this), write8_delegate(FUNC(isa8_ibm_mfc_device::ibm_mfc_w), this));
+ m_isa->install_device(0x2a20, 0x2a20 + 15, read8sm_delegate(*this, FUNC(isa8_ibm_mfc_device::ibm_mfc_r)), write8sm_delegate(*this, FUNC(isa8_ibm_mfc_device::ibm_mfc_w)));
}
diff --git a/src/devices/bus/isa/ibm_mfc.h b/src/devices/bus/isa/ibm_mfc.h
index febb741c3b3..6bd4172b575 100644
--- a/src/devices/bus/isa/ibm_mfc.h
+++ b/src/devices/bus/isa/ibm_mfc.h
@@ -16,7 +16,7 @@
#include "machine/i8255.h"
#include "machine/i8251.h"
#include "machine/pit8253.h"
-#include "sound/ym2151.h"
+#include "sound/ymopm.h"
//**************************************************************************
// TYPE DEFINITIONS
@@ -36,34 +36,34 @@ protected:
virtual void device_start() override;
virtual void device_reset() override;
- virtual void device_add_mconfig(machine_config &config) override;
+ virtual void device_add_mconfig(machine_config &config) override ATTR_COLD;
virtual ioport_constructor device_input_ports() const override;
virtual const tiny_rom_entry* device_rom_region() const override;
private:
- DECLARE_READ8_MEMBER( ppi0_i_a );
- DECLARE_WRITE8_MEMBER( ppi0_o_b );
- DECLARE_READ8_MEMBER( ppi0_i_c );
- DECLARE_WRITE8_MEMBER( ppi0_o_c );
+ uint8_t ppi0_i_a();
+ void ppi0_o_b(uint8_t data);
+ uint8_t ppi0_i_c();
+ void ppi0_o_c(uint8_t data);
- DECLARE_WRITE8_MEMBER( ppi1_o_a );
- DECLARE_READ8_MEMBER( ppi1_i_b );
+ void ppi1_o_a(uint8_t data);
+ uint8_t ppi1_i_b();
- DECLARE_WRITE8_MEMBER( ppi1_o_c );
+ 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);
- DECLARE_READ8_MEMBER( ibm_mfc_r );
- DECLARE_WRITE8_MEMBER( ibm_mfc_w );
+ uint8_t ibm_mfc_r(offs_t offset);
+ void ibm_mfc_w(offs_t offset, uint8_t data);
- void io_map(address_map &map);
- void prg_map(address_map &map);
+ void io_map(address_map &map) ATTR_COLD;
+ void prg_map(address_map &map) ATTR_COLD;
void set_z80_interrupt(int src, int state);
void set_pc_interrupt(int src, int state);
@@ -78,7 +78,7 @@ private:
uint8_t m_z80_irq_state;
required_device<cpu_device> m_cpu;
- required_device<ym2151_device> m_ym2151;
+ required_device<ym2164_device> m_ym2164;
required_device<pit8253_device> m_d8253;
required_device<i8251_device> m_d71051;
required_device<i8255_device> m_d71055c_0;
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..eb6ca256e05
--- /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 ATTR_COLD;
+ virtual void device_reset() override ATTR_COLD;
+ virtual void device_reset_after_children() override;
+ virtual void device_add_mconfig(machine_config &config) override ATTR_COLD;
+ virtual const tiny_rom_entry *device_rom_region() const override ATTR_COLD;
+
+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 1b1c832cc9c..9565851fafc 100644
--- a/src/devices/bus/isa/ide.cpp
+++ b/src/devices/bus/isa/ide.cpp
@@ -9,18 +9,18 @@
#include "emu.h"
#include "ide.h"
+#include "bus/ata/atadev.h"
#include "imagedev/harddriv.h"
-#include "machine/idectrl.h"
#include "sound/cdda.h"
#include "speaker.h"
-READ8_MEMBER(isa16_ide_device::ide16_alt_r )
+uint8_t isa16_ide_device::ide16_alt_r()
{
return m_ide->read_cs1(6/2, 0xff);
}
-WRITE8_MEMBER(isa16_ide_device::ide16_alt_w )
+void isa16_ide_device::ide16_alt_w(uint8_t data)
{
m_ide->write_cs1(6/2, data, 0xff);
}
@@ -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 e0e58661389..311d2dd0edb 100644
--- a/src/devices/bus/isa/ide.h
+++ b/src/devices/bus/isa/ide.h
@@ -25,21 +25,21 @@ public:
protected:
// device-level overrides
- virtual void device_start() override;
- virtual void device_reset() override;
+ virtual void device_start() override ATTR_COLD;
+ virtual void device_reset() override ATTR_COLD;
// optional information overrides
- virtual void device_add_mconfig(machine_config &config) override;
- virtual ioport_constructor device_input_ports() const override;
+ virtual void device_add_mconfig(machine_config &config) override ATTR_COLD;
+ virtual ioport_constructor device_input_ports() const override ATTR_COLD;
private:
- DECLARE_WRITE_LINE_MEMBER(ide_interrupt);
- READ8_MEMBER(ide16_alt_r);
- WRITE8_MEMBER(ide16_alt_w);
+ void ide_interrupt(int state);
+ uint8_t ide16_alt_r();
+ void ide16_alt_w(uint8_t data);
bool is_primary() { return m_is_primary; }
- void map(address_map &map);
- void alt_map(address_map &map);
+ void map(address_map &map) ATTR_COLD;
+ void alt_map(address_map &map) ATTR_COLD;
// internal state
bool m_is_primary;
diff --git a/src/devices/bus/isa/isa.cpp b/src/devices/bus/isa/isa.cpp
index 92ead5df95b..f212f61d3d7 100644
--- a/src/devices/bus/isa/isa.cpp
+++ b/src/devices/bus/isa/isa.cpp
@@ -107,10 +107,10 @@ isa8_device::isa8_device(const machine_config &mconfig, const char *tag, device_
isa8_device::isa8_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_mem_config("ISA 8-bit mem", ENDIANNESS_LITTLE, 8, 24, 0, address_map_constructor()),
- m_io_config("ISA 8-bit I/O", ENDIANNESS_LITTLE, 8, 16, 0, address_map_constructor()),
- m_mem16_config("ISA 16-bit mem", ENDIANNESS_LITTLE, 16, 24, 0, address_map_constructor()),
- m_io16_config("ISA 16-bit I/O", ENDIANNESS_LITTLE, 16, 16, 0, address_map_constructor()),
+ m_mem_config("mem8", ENDIANNESS_LITTLE, 8, 24, 0, address_map_constructor()),
+ m_io_config("io8", ENDIANNESS_LITTLE, 8, 16, 0, address_map_constructor()),
+ m_mem16_config("mem16", ENDIANNESS_LITTLE, 16, 24, 0, address_map_constructor()),
+ m_io16_config("io16", ENDIANNESS_LITTLE, 16, 16, 0, address_map_constructor()),
m_memspace(*this, finder_base::DUMMY_TAG, -1),
m_iospace(*this, finder_base::DUMMY_TAG, -1),
m_memwidth(0),
@@ -125,6 +125,7 @@ isa8_device::isa8_device(const machine_config &mconfig, device_type type, const
m_out_drq1_cb(*this),
m_out_drq2_cb(*this),
m_out_drq3_cb(*this),
+ m_write_iochrdy(*this),
m_write_iochck(*this)
{
std::fill(std::begin(m_dma_device), std::end(m_dma_device), nullptr);
@@ -151,22 +152,22 @@ device_memory_interface::space_config_vector isa16_device::memory_space_config()
};
}
-READ8_MEMBER(isa8_device::mem_r)
+uint8_t isa8_device::mem_r(offs_t offset)
{
return m_memspace->read_byte(offset);
}
-WRITE8_MEMBER(isa8_device::mem_w)
+void isa8_device::mem_w(offs_t offset, uint8_t data)
{
m_memspace->write_byte(offset, data);
}
-READ8_MEMBER(isa8_device::io_r)
+uint8_t isa8_device::io_r(offs_t offset)
{
return m_iospace->read_byte(offset);
}
-WRITE8_MEMBER(isa8_device::io_w)
+void isa8_device::io_w(offs_t offset, uint8_t data)
{
m_iospace->write_byte(offset, data);
}
@@ -222,19 +223,6 @@ void isa8_device::device_config_complete()
void isa8_device::device_resolve_objects()
{
- // resolve callbacks
- 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();
}
@@ -256,7 +244,7 @@ void isa8_device::device_reset()
}
-template<typename R, typename W> void isa8_device::install_space(int spacenum, offs_t start, offs_t end, R rhandler, W whandler)
+template <typename R, typename W> void isa8_device::install_space(int spacenum, offs_t start, offs_t end, R rhandler, W whandler)
{
int buswidth;
address_space *space;
@@ -276,24 +264,35 @@ template<typename R, typename W> void isa8_device::install_space(int spacenum, o
fatalerror("Unknown space passed to isa8_device::install_space!\n");
}
- switch(buswidth)
+ switch (buswidth)
{
case 8:
- space->install_readwrite_handler(start, end, rhandler, whandler, 0);
+ space->install_read_handler(start, end, rhandler, 0);
+ space->install_write_handler(start, end, whandler, 0);
break;
case 16:
- space->install_readwrite_handler(start, end, rhandler, whandler, 0xffff);
+ space->install_read_handler(start, end, rhandler, 0xffff);
+ space->install_write_handler(start, end, whandler, 0xffff);
break;
case 32:
- if ((start % 4) == 0) {
- if ((end-start)==1) {
- space->install_readwrite_handler(start, end+2, rhandler, whandler, 0x0000ffff);
- } else {
- space->install_readwrite_handler(start, end, rhandler, whandler, 0xffffffff);
+ if ((start % 4) == 0)
+ {
+ if ((end - start) == 1)
+ {
+ space->install_read_handler(start, end + 2, rhandler, 0x0000ffff);
+ space->install_write_handler(start, end + 2, whandler, 0x0000ffff);
}
- } else {
+ else
+ {
+ space->install_read_handler(start, end, rhandler, 0xffffffff);
+ space->install_write_handler(start, end, whandler, 0xffffffff);
+ }
+ }
+ else
+ {
// we handle just misaligned by 2
- space->install_readwrite_handler(start-2, end, rhandler, whandler, 0xffff0000);
+ space->install_read_handler(start - 2, end, rhandler, 0xffff0000);
+ space->install_write_handler(start - 2, end, whandler, 0xffff0000);
}
break;
default:
@@ -301,42 +300,56 @@ template<typename R, typename W> void isa8_device::install_space(int spacenum, o
}
}
-template<typename R, typename W> void isa8_device::install_memory(offs_t start, offs_t end, R rhandler, W whandler)
-{
- install_space(AS_ISA_MEM, start, end, rhandler, whandler);
-}
-
-template<typename R, typename W> void isa8_device::install_device(offs_t start, offs_t end, R rhandler, W whandler)
-{
- install_space(AS_ISA_IO, start, end, rhandler, whandler);
-}
-
template void isa8_device::install_space<read8_delegate, write8_delegate >(int spacenum, offs_t start, offs_t end, read8_delegate rhandler, write8_delegate whandler);
+template void isa8_device::install_space<read8_delegate, write8m_delegate >(int spacenum, offs_t start, offs_t end, read8_delegate rhandler, write8m_delegate whandler);
+template void isa8_device::install_space<read8_delegate, write8s_delegate >(int spacenum, offs_t start, offs_t end, read8_delegate rhandler, write8s_delegate whandler);
+template void isa8_device::install_space<read8_delegate, write8sm_delegate >(int spacenum, offs_t start, offs_t end, read8_delegate rhandler, write8sm_delegate whandler);
+template void isa8_device::install_space<read8_delegate, write8mo_delegate >(int spacenum, offs_t start, offs_t end, read8_delegate rhandler, write8mo_delegate whandler);
+template void isa8_device::install_space<read8_delegate, write8smo_delegate>(int spacenum, offs_t start, offs_t end, read8_delegate rhandler, write8smo_delegate whandler);
+
+template void isa8_device::install_space<read8m_delegate, write8_delegate >(int spacenum, offs_t start, offs_t end, read8m_delegate rhandler, write8_delegate whandler);
template void isa8_device::install_space<read8m_delegate, write8m_delegate >(int spacenum, offs_t start, offs_t end, read8m_delegate rhandler, write8m_delegate whandler);
+template void isa8_device::install_space<read8m_delegate, write8s_delegate >(int spacenum, offs_t start, offs_t end, read8m_delegate rhandler, write8s_delegate whandler);
+template void isa8_device::install_space<read8m_delegate, write8sm_delegate >(int spacenum, offs_t start, offs_t end, read8m_delegate rhandler, write8sm_delegate whandler);
+template void isa8_device::install_space<read8m_delegate, write8mo_delegate >(int spacenum, offs_t start, offs_t end, read8m_delegate rhandler, write8mo_delegate whandler);
+template void isa8_device::install_space<read8m_delegate, write8smo_delegate>(int spacenum, offs_t start, offs_t end, read8m_delegate rhandler, write8smo_delegate whandler);
+
+template void isa8_device::install_space<read8s_delegate, write8_delegate >(int spacenum, offs_t start, offs_t end, read8s_delegate rhandler, write8_delegate whandler);
+template void isa8_device::install_space<read8s_delegate, write8m_delegate >(int spacenum, offs_t start, offs_t end, read8s_delegate rhandler, write8m_delegate whandler);
template void isa8_device::install_space<read8s_delegate, write8s_delegate >(int spacenum, offs_t start, offs_t end, read8s_delegate rhandler, write8s_delegate whandler);
+template void isa8_device::install_space<read8s_delegate, write8sm_delegate >(int spacenum, offs_t start, offs_t end, read8s_delegate rhandler, write8sm_delegate whandler);
+template void isa8_device::install_space<read8s_delegate, write8mo_delegate >(int spacenum, offs_t start, offs_t end, read8s_delegate rhandler, write8mo_delegate whandler);
+template void isa8_device::install_space<read8s_delegate, write8smo_delegate>(int spacenum, offs_t start, offs_t end, read8s_delegate rhandler, write8smo_delegate whandler);
+
+template void isa8_device::install_space<read8sm_delegate, write8_delegate >(int spacenum, offs_t start, offs_t end, read8sm_delegate rhandler, write8_delegate whandler);
+template void isa8_device::install_space<read8sm_delegate, write8m_delegate >(int spacenum, offs_t start, offs_t end, read8sm_delegate rhandler, write8m_delegate whandler);
+template void isa8_device::install_space<read8sm_delegate, write8s_delegate >(int spacenum, offs_t start, offs_t end, read8sm_delegate rhandler, write8s_delegate whandler);
template void isa8_device::install_space<read8sm_delegate, write8sm_delegate >(int spacenum, offs_t start, offs_t end, read8sm_delegate rhandler, write8sm_delegate whandler);
-template void isa8_device::install_space<read8mo_delegate, write8mo_delegate >(int spacenum, offs_t start, offs_t end, read8mo_delegate rhandler, write8mo_delegate whandler);
-template void isa8_device::install_space<read8smo_delegate, write8smo_delegate>(int spacenum, offs_t start, offs_t end, read8smo_delegate rhandler, write8smo_delegate whandler);
+template void isa8_device::install_space<read8sm_delegate, write8mo_delegate >(int spacenum, offs_t start, offs_t end, read8sm_delegate rhandler, write8mo_delegate whandler);
+template void isa8_device::install_space<read8sm_delegate, write8smo_delegate>(int spacenum, offs_t start, offs_t end, read8sm_delegate rhandler, write8smo_delegate whandler);
-template void isa8_device::install_memory<read8_delegate, write8_delegate >(offs_t start, offs_t end, read8_delegate rhandler, write8_delegate whandler);
-template void isa8_device::install_memory<read8m_delegate, write8m_delegate >(offs_t start, offs_t end, read8m_delegate rhandler, write8m_delegate whandler);
-template void isa8_device::install_memory<read8s_delegate, write8s_delegate >(offs_t start, offs_t end, read8s_delegate rhandler, write8s_delegate whandler);
-template void isa8_device::install_memory<read8sm_delegate, write8sm_delegate >(offs_t start, offs_t end, read8sm_delegate rhandler, write8sm_delegate whandler);
-template void isa8_device::install_memory<read8mo_delegate, write8mo_delegate >(offs_t start, offs_t end, read8mo_delegate rhandler, write8mo_delegate whandler);
-template void isa8_device::install_memory<read8smo_delegate, write8smo_delegate>(offs_t start, offs_t end, read8smo_delegate rhandler, write8smo_delegate whandler);
+template void isa8_device::install_space<read8mo_delegate, write8_delegate >(int spacenum, offs_t start, offs_t end, read8mo_delegate rhandler, write8_delegate whandler);
+template void isa8_device::install_space<read8mo_delegate, write8m_delegate >(int spacenum, offs_t start, offs_t end, read8mo_delegate rhandler, write8m_delegate whandler);
+template void isa8_device::install_space<read8mo_delegate, write8s_delegate >(int spacenum, offs_t start, offs_t end, read8mo_delegate rhandler, write8s_delegate whandler);
+template void isa8_device::install_space<read8mo_delegate, write8sm_delegate >(int spacenum, offs_t start, offs_t end, read8mo_delegate rhandler, write8sm_delegate whandler);
+template void isa8_device::install_space<read8mo_delegate, write8mo_delegate >(int spacenum, offs_t start, offs_t end, read8mo_delegate rhandler, write8mo_delegate whandler);
+template void isa8_device::install_space<read8mo_delegate, write8smo_delegate>(int spacenum, offs_t start, offs_t end, read8mo_delegate rhandler, write8smo_delegate whandler);
-template void isa8_device::install_device<read8_delegate, write8_delegate >(offs_t start, offs_t end, read8_delegate rhandler, write8_delegate whandler);
-template void isa8_device::install_device<read8m_delegate, write8m_delegate >(offs_t start, offs_t end, read8m_delegate rhandler, write8m_delegate whandler);
-template void isa8_device::install_device<read8s_delegate, write8s_delegate >(offs_t start, offs_t end, read8s_delegate rhandler, write8s_delegate whandler);
-template void isa8_device::install_device<read8sm_delegate, write8sm_delegate >(offs_t start, offs_t end, read8sm_delegate rhandler, write8sm_delegate whandler);
-template void isa8_device::install_device<read8mo_delegate, write8mo_delegate >(offs_t start, offs_t end, read8mo_delegate rhandler, write8mo_delegate whandler);
-template void isa8_device::install_device<read8smo_delegate, write8smo_delegate>(offs_t start, offs_t end, read8smo_delegate rhandler, write8smo_delegate whandler);
+template void isa8_device::install_space<read8smo_delegate, write8_delegate >(int spacenum, offs_t start, offs_t end, read8smo_delegate rhandler, write8_delegate whandler);
+template void isa8_device::install_space<read8smo_delegate, write8m_delegate >(int spacenum, offs_t start, offs_t end, read8smo_delegate rhandler, write8m_delegate whandler);
+template void isa8_device::install_space<read8smo_delegate, write8s_delegate >(int spacenum, offs_t start, offs_t end, read8smo_delegate rhandler, write8s_delegate whandler);
+template void isa8_device::install_space<read8smo_delegate, write8sm_delegate >(int spacenum, offs_t start, offs_t end, read8smo_delegate rhandler, write8sm_delegate whandler);
+template void isa8_device::install_space<read8smo_delegate, write8mo_delegate >(int spacenum, offs_t start, offs_t end, read8smo_delegate rhandler, write8mo_delegate whandler);
+template void isa8_device::install_space<read8smo_delegate, write8smo_delegate>(int spacenum, offs_t start, offs_t end, read8smo_delegate rhandler, write8smo_delegate whandler);
+void isa8_device::install_bank(offs_t start, offs_t end, uint8_t *data)
+{
+ m_memspace->install_ram(start, end, data);
+}
-void isa8_device::install_bank(offs_t start, offs_t end, const char *tag, uint8_t *data)
+void isa8_device::install_bank(offs_t start, offs_t end, memory_bank *bank)
{
- m_memspace->install_readwrite_bank(start, end, 0, tag );
- machine().root_device().membank(m_memspace->device().siblingtag(tag).c_str())->set_base(data);
+ m_memspace->install_readwrite_bank(start, end, bank);
}
void isa8_device::unmap_bank(offs_t start, offs_t end)
@@ -344,16 +357,15 @@ void isa8_device::unmap_bank(offs_t start, offs_t end)
m_memspace->unmap_readwrite(start, end);
}
-void isa8_device::install_rom(device_t *dev, offs_t start, offs_t end, const char *tag, const char *region)
+void isa8_device::install_rom(device_t *dev, offs_t start, offs_t end, const char *region)
{
if (machine().root_device().memregion("isa")) {
uint8_t *src = dev->memregion(region)->base();
uint8_t *dest = machine().root_device().memregion("isa")->base() + start - 0xc0000;
memcpy(dest,src, end - start + 1);
} else {
- m_memspace->install_read_bank(start, end, 0, tag);
+ m_memspace->install_rom(start, end, machine().root_device().memregion(dev->subtag(region).c_str())->base());
m_memspace->unmap_write(start, end);
- machine().root_device().membank(m_memspace->device().siblingtag(tag).c_str())->set_base(machine().root_device().memregion(dev->subtag(region).c_str())->base());
}
}
@@ -369,18 +381,23 @@ bool isa8_device::is_option_rom_space_available(offs_t start, int size)
return true;
}
+void isa8_device::unmap_readwrite(offs_t start, offs_t end)
+{
+ m_memspace->unmap_readwrite(start, 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)
{
@@ -407,6 +424,11 @@ void isa8_device::eop_w(int channel, int state)
m_dma_device[channel]->eop_w(state);
}
+void isa8_device::set_ready(int state)
+{
+ m_write_iochrdy(state);
+}
+
void isa8_device::nmi()
{
// active low pulse
@@ -428,8 +450,8 @@ void isa8_device::nmi()
//-------------------------------------------------
device_isa8_card_interface::device_isa8_card_interface(const machine_config &mconfig, device_t &device)
- : device_slot_card_interface(mconfig, device),
- m_isa(nullptr), m_isa_dev(nullptr), m_next(nullptr)
+ : device_interface(device, "isa"),
+ m_isa(nullptr), m_isa_dev(nullptr)
{
}
@@ -485,28 +507,7 @@ 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();
-}
-
-void isa16_device::install16_device(offs_t start, offs_t end, read16_delegate rhandler, write16_delegate whandler)
+template<typename R, typename W> void isa16_device::install16_device(offs_t start, offs_t end, R rhandler, W whandler)
{
int buswidth = m_iowidth;
switch(buswidth)
@@ -523,7 +524,7 @@ void isa16_device::install16_device(offs_t start, offs_t end, read16_delegate rh
m_iospace->install_readwrite_handler(start, end, rhandler, whandler, 0xffffffff);
}
} else {
- // we handle just misalligned by 2
+ // we handle just misaligned by 2
m_iospace->install_readwrite_handler(start-2, end, rhandler, whandler, 0xffff0000);
}
@@ -533,72 +534,75 @@ void isa16_device::install16_device(offs_t start, offs_t end, read16_delegate rh
}
}
-READ16_MEMBER(isa16_device::mem16_r)
+template void isa16_device::install16_device<read16_delegate, write16_delegate >(offs_t start, offs_t end, read16_delegate rhandler, write16_delegate whandler);
+template void isa16_device::install16_device<read16s_delegate, write16s_delegate >(offs_t start, offs_t end, read16s_delegate rhandler, write16s_delegate whandler);
+template void isa16_device::install16_device<read16sm_delegate, write16sm_delegate >(offs_t start, offs_t end, read16sm_delegate rhandler, write16sm_delegate whandler);
+template void isa16_device::install16_device<read16smo_delegate, write16smo_delegate>(offs_t start, offs_t end, read16smo_delegate rhandler, write16smo_delegate whandler);
+
+uint16_t isa16_device::mem16_r(offs_t offset, uint16_t mem_mask)
{
return m_memspace->read_word(offset<<1, mem_mask);
}
-WRITE16_MEMBER(isa16_device::mem16_w)
+void isa16_device::mem16_w(offs_t offset, uint16_t data, uint16_t mem_mask)
{
m_memspace->write_word(offset<<1, data, mem_mask);
}
-READ16_MEMBER(isa16_device::io16_r)
+uint16_t isa16_device::io16_r(offs_t offset, uint16_t mem_mask)
{
return m_iospace->read_word(offset<<1, mem_mask);
}
-WRITE16_MEMBER(isa16_device::io16_w)
+void isa16_device::io16_w(offs_t offset, uint16_t data, uint16_t mem_mask)
{
m_iospace->write_word(offset<<1, data, mem_mask);
}
-READ16_MEMBER(isa16_device::mem16_swap_r)
+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);
}
-WRITE16_MEMBER(isa16_device::mem16_swap_w)
+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);
}
-READ16_MEMBER(isa16_device::io16_swap_r)
+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);
}
-WRITE16_MEMBER(isa16_device::io16_swap_w)
+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 fff65de82f6..225663a4da1 100644
--- a/src/devices/bus/isa/isa.h
+++ b/src/devices/bus/isa/isa.h
@@ -95,8 +95,8 @@ public:
protected:
isa8_slot_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_t implementation
+ virtual void device_start() override ATTR_COLD;
// configuration
required_device<device_t> m_isa_bus;
@@ -125,6 +125,7 @@ public:
// inline configuration
template <typename T> void set_memspace(T &&tag, int spacenum) { m_memspace.set_tag(std::forward<T>(tag), spacenum); }
template <typename T> void set_iospace(T &&tag, int spacenum) { m_iospace.set_tag(std::forward<T>(tag), spacenum); }
+ auto iochrdy_callback() { return m_write_iochrdy.bind(); }
auto iochck_callback() { return m_write_iochck.bind(); }
auto irq2_callback() { return m_out_irq2_cb.bind(); }
auto irq3_callback() { return m_out_irq3_cb.bind(); }
@@ -142,45 +143,58 @@ public:
// for ISA8, put the 8-bit configs in the primary slots and the 16-bit configs in the secondary
virtual space_config_vector memory_space_config() const override;
- template<typename R, typename W> void install_device(offs_t start, offs_t end, R rhandler, W whandler);
+ template<typename R, typename W> void install_device(offs_t start, offs_t end, R rhandler, W whandler)
+ {
+ install_space(AS_ISA_IO, start, end, rhandler, whandler);
+ }
template<typename T> void install_device(offs_t addrstart, offs_t addrend, T &device, void (T::*map)(class address_map &map), uint64_t unitmask = ~u64(0))
{
m_iospace->install_device(addrstart, addrend, device, map, unitmask);
}
- void install_bank(offs_t start, offs_t end, const char *tag, uint8_t *data);
- void install_rom(device_t *dev, offs_t start, offs_t end, const char *tag, const char *region);
- template<typename R, typename W> void install_memory(offs_t start, offs_t end, R rhandler, W whandler);
+ void install_bank(offs_t start, offs_t end, uint8_t *data);
+ void install_bank(offs_t start, offs_t end, memory_bank *bank);
+ void install_rom(device_t *dev, offs_t start, offs_t end, const char *region);
+ template<typename R, typename W> void install_memory(offs_t start, offs_t end, R rhandler, W whandler)
+ {
+ install_space(AS_ISA_MEM, start, end, rhandler, whandler);
+ }
+ template<typename T> void install_memory(offs_t addrstart, offs_t addrend, T &device, void (T:: *map)(class address_map &map), uint64_t unitmask = ~u64(0))
+ {
+ m_memspace->install_device(addrstart, addrend, device, map, unitmask);
+ }
void unmap_device(offs_t start, offs_t end) const { m_iospace->unmap_readwrite(start, end); }
void unmap_bank(offs_t start, offs_t end);
void unmap_rom(offs_t start, offs_t end);
+ void unmap_readwrite(offs_t start, offs_t end);
bool is_option_rom_space_available(offs_t start, int size);
// 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
- DECLARE_READ8_MEMBER(mem_r);
- DECLARE_WRITE8_MEMBER(mem_w);
- DECLARE_READ8_MEMBER(io_r);
- DECLARE_WRITE8_MEMBER(io_w);
+ uint8_t mem_r(offs_t offset);
+ void mem_w(offs_t offset, uint8_t data);
+ uint8_t io_r(offs_t offset);
+ void io_w(offs_t offset, uint8_t data);
uint8_t dack_r(int line);
void dack_w(int line, uint8_t data);
void dack_line_w(int line, int state);
void eop_w(int channels, int state);
+ void set_ready(int state);
void nmi();
virtual void set_dma_channel(uint8_t channel, device_isa8_card_interface *dev, bool do_eop);
@@ -196,11 +210,11 @@ 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;
- virtual void device_reset() override;
+ virtual void device_resolve_objects() override ATTR_COLD;
+ virtual void device_start() override ATTR_COLD;
+ virtual void device_reset() override ATTR_COLD;
// address spaces
required_address_space m_memspace, m_iospace;
@@ -222,6 +236,7 @@ protected:
std::forward_list<device_slot_interface *> m_slot_list;
private:
+ devcb_write_line m_write_iochrdy;
devcb_write_line m_write_iochck;
};
@@ -232,16 +247,13 @@ DECLARE_DEVICE_TYPE(ISA8, isa8_device)
// ======================> device_isa8_card_interface
// class representing interface-specific live isa8 card
-class device_isa8_card_interface : public device_slot_card_interface
+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);
@@ -259,9 +271,6 @@ public:
isa8_device *m_isa;
device_t *m_isa_dev;
-
-private:
- device_isa8_card_interface *m_next;
};
class isa16_device;
@@ -283,8 +292,8 @@ public:
isa16_slot_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
protected:
- // device-level overrides
- virtual void device_start() override;
+ // device_t implementation
+ virtual void device_start() override ATTR_COLD;
};
@@ -308,40 +317,36 @@ public:
auto drq6_callback() { return m_out_drq6_cb.bind(); }
auto drq7_callback() { return m_out_drq7_cb.bind(); }
- void install16_device(offs_t start, offs_t end, read16_delegate rhandler, write16_delegate whandler);
+ template<typename R, typename W> void install16_device(offs_t start, offs_t end, R rhandler, W whandler);
// 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);
virtual void remap(int space_id, offs_t start, offs_t end) override;
// 16 bit accessors for ISA-defined address spaces
- DECLARE_READ16_MEMBER(mem16_r);
- DECLARE_WRITE16_MEMBER(mem16_w);
- DECLARE_READ16_MEMBER(io16_r);
- DECLARE_WRITE16_MEMBER(io16_w);
+ uint16_t mem16_r(offs_t offset, uint16_t mem_mask = 0xffff);
+ void mem16_w(offs_t offset, uint16_t data, uint16_t mem_mask = 0xffff);
+ uint16_t io16_r(offs_t offset, uint16_t mem_mask = 0xffff);
+ void io16_w(offs_t offset, uint16_t data, uint16_t mem_mask = 0xffff);
// byte-swapped versions of 16-bit accessors
- DECLARE_READ16_MEMBER(mem16_swap_r);
- DECLARE_WRITE16_MEMBER(mem16_swap_w);
- DECLARE_READ16_MEMBER(io16_swap_r);
- DECLARE_WRITE16_MEMBER(io16_swap_w);
-
-protected:
- // device-level overrides
- virtual void device_start() override;
+ uint16_t mem16_swap_r(offs_t offset, uint16_t mem_mask = 0xffff);
+ void mem16_swap_w(offs_t offset, uint16_t data, uint16_t mem_mask = 0xffff);
+ 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);
private:
// internal state
diff --git a/src/devices/bus/isa/isa_cards.cpp b/src/devices/bus/isa/isa_cards.cpp
index c97866bdf5e..b11bbc87fa1 100644
--- a/src/devices/bus/isa/isa_cards.cpp
+++ b/src/devices/bus/isa/isa_cards.cpp
@@ -10,72 +10,94 @@
#include "isa_cards.h"
// video
-#include "mda.h"
-#include "cga.h"
#include "aga.h"
+#include "cga.h"
#include "ega.h"
+#include "eis_hgb107x.h"
+#include "ex1280.h"
+#include "mda.h"
+#include "num9rev.h"
#include "pgc.h"
-#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"
-#include "num9rev.h"
+#include "svga_tseng.h"
+#include "vga.h"
+#include "vga_ati.h"
-// storage
+// storage (floppy only)
#include "fdc.h"
#include "mufdc.h"
+
+// storage (MFM/RLL/ESDI)
+#include "acb2072.h"
+#include "cl_sh260.h"
#include "hdc.h"
+#include "lrk330.h"
+#include "omti8621.h"
+#include "ultra12f.h"
+#include "wd1002a_wx1.h"
+#include "wd1007a.h"
#include "wdxt_gen.h"
-#include "ide.h"
-#include "xtide.h"
-#include "side116.h"
+
+// storage (SCSI)
#include "aha1542b.h"
#include "aha1542c.h"
#include "aha174x.h"
-#include "wd1002a_wx1.h"
-#include "wd1007a.h"
-#include "mcd.h"
-#include "lbaenhancer.h"
-#include "cl_sh260.h"
+#include "asc88.h"
#include "bt54x.h"
#include "dcb.h"
-#include "ultra12f.h"
+#include "tekram_dc820.h"
#include "ultra14f.h"
#include "ultra24f.h"
-#include "tekram_dc820.h"
-#include "asc88.h"
+
+// storage (IDE/XT-IDE)
+#include "ide.h"
+#include "side116.h"
+#include "xtide.h"
+
+// storage (miscellaneous)
+#include "lbaenhancer.h"
+#include "mcd.h"
// sound
#include "adlib.h"
+#include "dectalk.h"
#include "gblaster.h"
#include "gus.h"
#include "ibm_mfc.h"
+#include "ibm_speech.h"
#include "mpu401.h"
+#include "pcmidi.h"
+#include "prose4k1.h"
+#include "sb16.h"
#include "sblaster.h"
#include "ssi2001.h"
#include "stereo_fx.h"
-#include "dectalk.h"
-#include "sb16.h"
// network
#include "3c503.h"
-#include "ne1000.h"
-#include "ne2000.h"
#include "3c505.h"
+#include "3xtwin.h"
#include "eis_sad8852.h"
+#include "eis_twib.h"
+#include "ne1000.h"
+#include "ne2000.h"
#include "np600.h"
// communication ports
-#include "lpt.h"
#include "com.h"
+#include "lpt.h"
#include "pds.h"
// other
+#include "bblue2.h"
#include "chessmdr.h"
#include "chessmsr.h"
#include "finalchs.h"
+#include "hpblp.h"
+#include "opus100pm.h"
void pc_isa8_cards(device_slot_interface &device)
@@ -92,7 +114,7 @@ void pc_isa8_cards(device_slot_interface &device)
device.option_add("ega", ISA8_EGA);
device.option_add("pgc", ISA8_PGC);
device.option_add("vga", ISA8_VGA);
- device.option_add("svga_et4k", ISA8_SVGA_ET4K);
+ 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);
@@ -114,18 +136,26 @@ void pc_isa8_cards(device_slot_interface &device)
device.option_add("stereo_fx", ISA8_STEREO_FX);
device.option_add("ssi2001", ISA8_SSI2001);
device.option_add("mpu401", ISA8_MPU401);
+ device.option_add("pcmidi", ISA8_PCMIDI);
device.option_add("ne1000", NE1000);
device.option_add("3c503", EL2_3C503);
device.option_add("lpt", ISA8_LPT);
device.option_add("ibm_mfc", ISA8_IBM_MFC);
device.option_add("wd1002a_wx1", ISA8_WD1002A_WX1);
device.option_add("dectalk", ISA8_DECTALK);
+ device.option_add("prose4k1", ISA8_PROSE4001);
device.option_add("pds", ISA8_PDS);
device.option_add("lba_enhancer", ISA8_LBA_ENHANCER);
device.option_add("asc88", ASC88);
device.option_add("chessmdr", ISA8_CHESSMDR);
device.option_add("chessmsr", ISA8_CHESSMSR);
device.option_add("finalchs", ISA8_FINALCHS);
+ device.option_add("epc_mda", ISA8_EPC_MDA);
+ device.option_add("epc_twib", ISA8_EIS_TWIB);
+ device.option_add("babyblue2", ISA8_BABYBLUE2);
+ device.option_add("acb2072", ACB2072);
+ device.option_add("3xtwin", ISA8_3XTWIN);
+ device.option_add("opus108pm", ISA8_OPUS108PM);
}
void pc_isa16_cards(device_slot_interface &device)
@@ -138,7 +168,7 @@ void pc_isa16_cards(device_slot_interface &device)
device.option_add("ega", ISA8_EGA);
device.option_add("pgc", ISA8_PGC);
device.option_add("vga", ISA8_VGA);
- device.option_add("svga_et4k", ISA8_SVGA_ET4K);
+ 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);
@@ -157,15 +187,24 @@ void pc_isa16_cards(device_slot_interface &device)
device.option_add("ne1000", NE1000);
device.option_add("3c503", EL2_3C503);
device.option_add("mpu401", ISA8_MPU401);
+ device.option_add("pcmidi", ISA8_PCMIDI);
device.option_add("lpt", ISA8_LPT);
device.option_add("ibm_mfc", ISA8_IBM_MFC);
device.option_add("fdcsmc", ISA8_FDC_SMC);
device.option_add("dectalk", ISA8_DECTALK);
+ device.option_add("prose4k1", ISA8_PROSE4001);
device.option_add("pds", ISA8_PDS);
device.option_add("lba_enhancer", ISA8_LBA_ENHANCER);
device.option_add("chessmdr", ISA8_CHESSMDR);
device.option_add("chessmsr", ISA8_CHESSMSR);
device.option_add("finalchs", ISA8_FINALCHS);
+ device.option_add("epc_mda", ISA8_EPC_MDA);
+ device.option_add("epc_twib", ISA8_EIS_TWIB);
+ device.option_add("babyblue2", ISA8_BABYBLUE2);
+ 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);
@@ -179,14 +218,24 @@ 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("svga_et4k", ISA16_SVGA_ET4K);
+ device.option_add("svga_et4k_kasan16", ISA16_SVGA_ET4K_KASAN16);
+ device.option_add("svga_et4kw32i", ISA16_SVGA_ET4K_W32I);
+ 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);
@@ -200,11 +249,16 @@ void pc_isa16_cards(device_slot_interface &device)
device.option_add("bt542bh", BT542BH);
device.option_add("bt545s", BT545S);
device.option_add("dcb", NOVELL_DCB);
+ device.option_add("ex1280", ISA16_EX1280);
device.option_add("ultra12f", ULTRA12F);
+ device.option_add("ultra12f32", ULTRA12F32);
device.option_add("ultra14f", ULTRA14F);
device.option_add("ultra24f", ULTRA24F); // actually an EISA card
device.option_add("dc320b", TEKRAM_DC320B); // actually an EISA card
device.option_add("dc320e", TEKRAM_DC320E); // actually an EISA card
device.option_add("dc820", TEKRAM_DC820); // actually an EISA card
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 f8ebedb130c..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)
@@ -133,7 +133,7 @@ void lba_enhancer_device::device_reset()
m_current_rom_start = 0xc8000 + (ioport("ROM_ADDRESS")->read()* 0x4000);
uint32_t current_rom_end = m_current_rom_start + 0x04000 - 1;
- m_isa->install_rom(this, m_current_rom_start, current_rom_end, "lbabios", "lbabios");
+ m_isa->install_rom(this, m_current_rom_start, current_rom_end, "lbabios");
logerror("LBA enhancer (for 28 bit LBA) located at BIOS address %x - %x\n", m_current_rom_start, current_rom_end);
}
diff --git a/src/devices/bus/isa/lbaenhancer.h b/src/devices/bus/isa/lbaenhancer.h
index 71e36c02665..c025752ede2 100644
--- a/src/devices/bus/isa/lbaenhancer.h
+++ b/src/devices/bus/isa/lbaenhancer.h
@@ -6,8 +6,8 @@
**********************************************************************/
-#ifndef MAME_BUS_ISA_LBA_ENHANCER_H
-#define MAME_BUS_ISA_LBA_ENHANCER_H
+#ifndef MAME_BUS_ISA_LBAENHANCER_H
+#define MAME_BUS_ISA_LBAENHANCER_H
#pragma once
@@ -26,14 +26,14 @@ public:
protected:
// device-level overrides
- virtual void device_start() override;
- virtual void device_reset() override;
+ virtual void device_start() override ATTR_COLD;
+ virtual void device_reset() override ATTR_COLD;
// optional information overrides
- virtual void device_add_mconfig(machine_config &config) override;
- virtual ioport_constructor device_input_ports() const override;
+ virtual void device_add_mconfig(machine_config &config) override ATTR_COLD;
+ virtual ioport_constructor device_input_ports() const override ATTR_COLD;
- virtual const tiny_rom_entry *device_rom_region() const override;
+ virtual const tiny_rom_entry *device_rom_region() const override ATTR_COLD;
private:
uint32_t m_current_rom_start;
};
@@ -41,4 +41,4 @@ private:
// device type definition
DECLARE_DEVICE_TYPE(ISA8_LBA_ENHANCER, lba_enhancer_device)
-#endif // MAME_BUS_ISA_LBA_ENHANCER_H
+#endif // MAME_BUS_ISA_LBAENHANCER_H
diff --git a/src/devices/bus/isa/lpt.cpp b/src/devices/bus/isa/lpt.cpp
index e47404a498d..548e3a57989 100644
--- a/src/devices/bus/isa/lpt.cpp
+++ b/src/devices/bus/isa/lpt.cpp
@@ -45,17 +45,14 @@ void isa8_lpt_device::device_start()
void isa8_lpt_device::device_reset()
{
m_is_primary = (ioport("DSW")->read() & 1) ? false : true;
+ pc_lpt_device &lpt(*subdevice<pc_lpt_device>("lpt"));
if (m_is_primary)
- {
- m_isa->install_device(0x0378, 0x037b, read8_delegate(FUNC(pc_lpt_device::read), subdevice<pc_lpt_device>("lpt")), write8_delegate(FUNC(pc_lpt_device::write), subdevice<pc_lpt_device>("lpt")));
- }
+ m_isa->install_device(0x0378, 0x037b, read8sm_delegate(lpt, FUNC(pc_lpt_device::read)), write8sm_delegate(lpt, FUNC(pc_lpt_device::write)));
else
- {
- m_isa->install_device(0x0278, 0x027b, read8_delegate(FUNC(pc_lpt_device::read), subdevice<pc_lpt_device>("lpt")), write8_delegate(FUNC(pc_lpt_device::write), subdevice<pc_lpt_device>("lpt")));
- }
+ 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..a3acf8cf349 100644
--- a/src/devices/bus/isa/lpt.h
+++ b/src/devices/bus/isa/lpt.h
@@ -31,15 +31,15 @@ public:
protected:
// device-level overrides
- virtual void device_start() override;
- virtual void device_reset() override;
+ virtual void device_start() override ATTR_COLD;
+ virtual void device_reset() override ATTR_COLD;
// optional information overrides
- virtual void device_add_mconfig(machine_config &config) override;
- virtual ioport_constructor device_input_ports() const override;
+ virtual void device_add_mconfig(machine_config &config) override ATTR_COLD;
+ virtual ioport_constructor device_input_ports() const override ATTR_COLD;
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/lrk330.cpp b/src/devices/bus/isa/lrk330.cpp
new file mode 100644
index 00000000000..18cd1bfe29e
--- /dev/null
+++ b/src/devices/bus/isa/lrk330.cpp
@@ -0,0 +1,130 @@
+// license:BSD-3-Clause
+// copyright-holders:AJR
+/***************************************************************************
+
+ Skeleton driver for ESDI controllers by Lark Associates Inc.
+
+ Major ICs excluding EPROMs, in order of decreasing pin count:
+ * Silicon Logic LD1111 HDC (QFP128, U1)
+ * Xilinx XC2018-70PC68C Logic Cell Array (PLCC84, U11)
+ * National DP8473V Floppy Disk Controller PLUS-2 (PLCC52, U4)
+ * Signetics SCN8032HCCA44 8-Bit Microcontroller (PLCC44, U20)
+ * Sharp LH52258D-45 32Kx8 CMOS Static RAM (SDIP28, U2 & U3)
+ * Vitelic V61C16F70L 2Kx8 CMOS Static RAM (SSOP24, U19)
+
+ The purpose of the small SRAM is not clear. Perhaps it can be banked
+ into the lower part of the 8032 program space after loading patches
+ for the EPROM microcode, since that uses the upper mirror addresses
+ almost exclusively.
+
+ A transfer rate of up to 24 megabits per second was advertised.
+
+ LRK-330 is presumably identical to LRK-331, only without the FDC or
+ 34-pin floppy drive cable connector installed.
+
+***************************************************************************/
+
+#include "emu.h"
+#include "lrk330.h"
+
+#include "imagedev/floppy.h"
+#include "machine/upd765.h"
+
+// device type definition
+DEFINE_DEVICE_TYPE(LRK331, lrk331_device, "lrk331", "Lark Associates LRK-331 ESDI Controller")
+
+
+lrk331_device::lrk331_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock)
+ : device_t(mconfig, LRK331, tag, owner, clock)
+ , device_isa16_card_interface(mconfig, *this)
+ , m_mcu(*this, "mcu")
+ , m_bios(*this, "bios")
+ , m_config(*this, "CONFIG")
+{
+}
+
+void lrk331_device::device_start()
+{
+}
+
+void lrk331_device::device_reset()
+{
+}
+
+void lrk331_device::ucode_map(address_map &map)
+{
+ map(0x0000, 0x3fff).mirror(0x4000).rom().region("ucode", 0);
+}
+
+void lrk331_device::ext_map(address_map &map)
+{
+ map.global_mask(0xff);
+ map(0x0b, 0x0b).nopw();
+}
+
+static INPUT_PORTS_START(lrk331)
+ PORT_START("CONFIG")
+ PORT_DIPNAME(0x001, 0x001, "Drive Addresses") PORT_DIPLOCATION("W1:1")
+ PORT_DIPSETTING(0x001, "Primary (1F0h-1F7h, 3F0h-3F7h)")
+ PORT_DIPSETTING(0x000, "Secondary (170h-177h, 370h-377h)")
+ PORT_DIPNAME(0x002, 0x002, "Floppy Drive Speed") PORT_DIPLOCATION("W2:2")
+ PORT_DIPSETTING(0x002, "Single")
+ PORT_DIPSETTING(0x000, "Dual")
+ PORT_DIPNAME(0x004, 0x004, "Interrupt Delay") PORT_DIPLOCATION("W3:1")
+ PORT_DIPSETTING(0x004, "Disabled")
+ PORT_DIPSETTING(0x000, "Enabled")
+ PORT_DIPNAME(0x008, 0x008, "Factory Configured - Do Not Alter") PORT_DIPLOCATION("W4:1")
+ PORT_DIPSETTING(0x008, DEF_STR(Off))
+ PORT_DIPSETTING(0x000, DEF_STR(On))
+ PORT_DIPNAME(0x0f0, 0x0e0, "BIOS Address") PORT_DIPLOCATION("W5-W8:1,2,3,4")
+ PORT_DIPSETTING(0x0f0, "Disabled")
+ PORT_DIPSETTING(0x0e0, "C800h")
+ PORT_DIPSETTING(0x0d0, "CC00h")
+ PORT_DIPSETTING(0x0b0, "D000h")
+ PORT_DIPSETTING(0x070, "D400h")
+ PORT_DIPNAME(0x300, 0x200, "IRQ Select") PORT_DIPLOCATION("W9-W10:1,2")
+ PORT_DIPSETTING(0x200, "IRQ 14")
+ PORT_DIPSETTING(0x100, "IRQ 15")
+ PORT_DIPNAME(0x400, 0x000, "Floppy Drive Interface") PORT_DIPLOCATION("W11:1")
+ PORT_DIPSETTING(0x400, "Disabled")
+ PORT_DIPSETTING(0x000, "Enabled")
+INPUT_PORTS_END
+
+ioport_constructor lrk331_device::device_input_ports() const
+{
+ return INPUT_PORTS_NAME(lrk331);
+}
+
+static void pc_hd_floppies(device_slot_interface &device)
+{
+ device.option_add("525hd", FLOPPY_525_HD);
+ device.option_add("35hd", FLOPPY_35_HD);
+ device.option_add("525dd", FLOPPY_525_DD);
+ device.option_add("35dd", FLOPPY_35_DD);
+}
+
+void lrk331_device::device_add_mconfig(machine_config &config)
+{
+ I8032(config, m_mcu, 24_MHz_XTAL / 2);
+ m_mcu->set_addrmap(AS_PROGRAM, &lrk331_device::ucode_map);
+ m_mcu->set_addrmap(AS_IO, &lrk331_device::ext_map);
+
+ //LD1111(config, m_hdc, 24_MHz_XTAL);
+
+ DP8473(config, "fdc", 24_MHz_XTAL);
+ FLOPPY_CONNECTOR(config, "fdc:0", pc_hd_floppies, "525hd", floppy_image_device::default_pc_floppy_formats);
+ FLOPPY_CONNECTOR(config, "fdc:1", pc_hd_floppies, nullptr, floppy_image_device::default_pc_floppy_formats);
+}
+
+ROM_START(lrk331)
+ ROM_REGION(0x2000, "bios", 0)
+ ROM_LOAD("63308-10.bin", 0x0000, 0x2000, CRC(f16d4f25) SHA1(437664ff9723c8036a40f1e504899b7cacd21ad0))
+
+ ROM_REGION(0x4000, "ucode", 0)
+ ROM_LOAD("63307-08.bin", 0x0000, 0x4000, CRC(6d2e8b26) SHA1(1a33462a29b306b01960cf2ac0b209b2adf58dbe))
+ROM_END
+
+const tiny_rom_entry *lrk331_device::device_rom_region() const
+{
+ return ROM_NAME(lrk331);
+}
diff --git a/src/devices/bus/isa/lrk330.h b/src/devices/bus/isa/lrk330.h
new file mode 100644
index 00000000000..928b3ef0689
--- /dev/null
+++ b/src/devices/bus/isa/lrk330.h
@@ -0,0 +1,38 @@
+// license:BSD-3-Clause
+// copyright-holders:AJR
+
+#ifndef MAME_BUS_ISA_LRK330_H
+#define MAME_BUS_ISA_LRK330_H
+
+#pragma once
+
+#include "isa.h"
+#include "cpu/mcs51/mcs51.h"
+
+class lrk331_device : public device_t, public device_isa16_card_interface
+{
+public:
+ lrk331_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 ATTR_COLD;
+ virtual void device_reset() override ATTR_COLD;
+
+ virtual ioport_constructor device_input_ports() const override ATTR_COLD;
+ virtual const tiny_rom_entry *device_rom_region() const override ATTR_COLD;
+ virtual void device_add_mconfig(machine_config &config) override ATTR_COLD;
+
+private:
+ void ucode_map(address_map &map) ATTR_COLD;
+ void ext_map(address_map &map) ATTR_COLD;
+
+ required_device<mcs51_cpu_device> m_mcu;
+ required_region_ptr<u8> m_bios;
+ required_ioport m_config;
+};
+
+DECLARE_DEVICE_TYPE(LRK331, lrk331_device)
+
+#endif // MAME_BUS_ISA_LRK330_H
diff --git a/src/devices/bus/isa/mach32.h b/src/devices/bus/isa/mach32.h
deleted file mode 100644
index 18d4673ab0f..00000000000
--- a/src/devices/bus/isa/mach32.h
+++ /dev/null
@@ -1,229 +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);
-
- DECLARE_READ16_MEMBER(mach32_chipid_r) { return m_chip_ID; }
- DECLARE_READ16_MEMBER(mach32_mem_boundary_r) { return m_membounds; }
- DECLARE_WRITE16_MEMBER(mach32_mem_boundary_w) { m_membounds = data; if(data & 0x10) logerror("ATI: Unimplemented memory boundary activated."); }
- DECLARE_WRITE16_MEMBER(mach32_ge_ext_config_w);
-
- DECLARE_READ16_MEMBER(mach32_config1_r);
- DECLARE_WRITE16_MEMBER(mach32_horz_overscan_w) {} // TODO
- DECLARE_READ16_MEMBER(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
- DECLARE_READ16_MEMBER(mach8_ec0_r) { return m_8514a->mach8_ec0_r(space,offset,mem_mask); }
- DECLARE_WRITE16_MEMBER(mach8_ec0_w) { m_8514a->mach8_ec0_w(space,offset,data,mem_mask); }
- DECLARE_READ16_MEMBER(mach8_ec1_r) { return m_8514a->mach8_ec1_r(space,offset,mem_mask); }
- DECLARE_WRITE16_MEMBER(mach8_ec1_w) { m_8514a->mach8_ec1_w(space,offset,data,mem_mask); }
- DECLARE_READ16_MEMBER(mach8_ec2_r) { return m_8514a->mach8_ec2_r(space,offset,mem_mask); }
- DECLARE_WRITE16_MEMBER(mach8_ec2_w) { m_8514a->mach8_ec2_w(space,offset,data,mem_mask); }
- DECLARE_READ16_MEMBER(mach8_ec3_r) { return m_8514a->mach8_ec3_r(space,offset,mem_mask); }
- DECLARE_WRITE16_MEMBER(mach8_ec3_w) { m_8514a->mach8_ec3_w(space,offset,data,mem_mask); }
- DECLARE_READ16_MEMBER(mach8_ext_fifo_r) { return m_8514a->mach8_ext_fifo_r(space,offset,mem_mask); }
- DECLARE_WRITE16_MEMBER(mach8_linedraw_index_w) { m_8514a->mach8_linedraw_index_w(space,offset,data,mem_mask); }
- DECLARE_READ16_MEMBER(mach8_bresenham_count_r) { return m_8514a->mach8_bresenham_count_r(space,offset,mem_mask); }
- DECLARE_WRITE16_MEMBER(mach8_bresenham_count_w) { m_8514a->mach8_bresenham_count_w(space,offset,data,mem_mask); }
- DECLARE_WRITE16_MEMBER(mach8_linedraw_w) { m_8514a->mach8_linedraw_w(space,offset,data,mem_mask); }
- DECLARE_READ16_MEMBER(mach8_linedraw_r) { return m_8514a->mach8_linedraw_r(space,offset,mem_mask); }
- DECLARE_READ16_MEMBER(mach8_scratch0_r) { return m_8514a->mach8_scratch0_r(space,offset,mem_mask); }
- DECLARE_WRITE16_MEMBER(mach8_scratch0_w) { m_8514a->mach8_scratch0_w(space,offset,data,mem_mask); }
- DECLARE_READ16_MEMBER(mach8_scratch1_r) { return m_8514a->mach8_scratch1_r(space,offset,mem_mask); }
- DECLARE_WRITE16_MEMBER(mach8_scratch1_w) { m_8514a->mach8_scratch1_w(space,offset,data,mem_mask); }
- DECLARE_WRITE16_MEMBER(mach8_crt_pitch_w) { m_8514a->mach8_crt_pitch_w(space,offset,data,mem_mask); }
- DECLARE_READ16_MEMBER(mach8_config1_r) { return m_8514a->mach8_config1_r(space,offset,mem_mask); }
- DECLARE_READ16_MEMBER(mach8_config2_r) { return m_8514a->mach8_config2_r(space,offset,mem_mask); }
- DECLARE_READ16_MEMBER(mach8_sourcex_r) { return m_8514a->mach8_sourcex_r(space,offset,mem_mask); }
- DECLARE_READ16_MEMBER(mach8_sourcey_r) { return m_8514a->mach8_sourcey_r(space,offset,mem_mask); }
- DECLARE_WRITE16_MEMBER(mach8_ext_leftscissor_w) { m_8514a->mach8_ext_leftscissor_w(space,offset,data,mem_mask); }
- DECLARE_WRITE16_MEMBER(mach8_ext_topscissor_w) { m_8514a->mach8_ext_topscissor_w(space,offset,data,mem_mask); }
- DECLARE_WRITE16_MEMBER(mach8_ge_offset_l_w) { m_8514a->mach8_ge_offset_l_w(space,offset,data,mem_mask); }
- DECLARE_WRITE16_MEMBER(mach8_ge_offset_h_w) { m_8514a->mach8_ge_offset_h_w(space,offset,data,mem_mask); }
- DECLARE_WRITE16_MEMBER(mach8_scan_x_w) { m_8514a->mach8_scan_x_w(space,offset,data,mem_mask); }
- DECLARE_WRITE16_MEMBER(mach8_dp_config_w) { m_8514a->mach8_dp_config_w(space,offset,data,mem_mask); }
- DECLARE_WRITE16_MEMBER(mach8_ge_pitch_w) { m_8514a->mach8_ge_pitch_w(space,offset,data,mem_mask); }
- DECLARE_READ16_MEMBER(mach8_ge_ext_config_r) { return m_8514a->mach8_ge_ext_config_r(space,offset,mem_mask); }
- DECLARE_WRITE16_MEMBER(mach8_patt_data_w) { m_8514a->mach8_patt_data_w(space,offset,data,mem_mask); }
-
- DECLARE_READ16_MEMBER(ibm8514_vtotal_r) { return m_8514a->ibm8514_vtotal_r(space,offset,mem_mask); }
- DECLARE_WRITE16_MEMBER(ibm8514_vtotal_w) { m_8514a->ibm8514_vtotal_w(space,offset,data,mem_mask); }
- DECLARE_READ16_MEMBER(ibm8514_htotal_r) { return m_8514a->ibm8514_htotal_r(space,offset,mem_mask); }
- DECLARE_WRITE8_MEMBER(ibm8514_htotal_w) { m_8514a->ibm8514_htotal_w(space,offset,data,mem_mask); }
- DECLARE_READ16_MEMBER(ibm8514_vdisp_r) { return m_8514a->ibm8514_vdisp_r(space,offset,mem_mask); }
- DECLARE_WRITE16_MEMBER(ibm8514_vdisp_w) { m_8514a->ibm8514_vdisp_w(space,offset,data,mem_mask); }
- DECLARE_READ16_MEMBER(ibm8514_vsync_r) { return m_8514a->ibm8514_vsync_r(space,offset,mem_mask); }
- DECLARE_WRITE16_MEMBER(ibm8514_vsync_w) { m_8514a->ibm8514_vsync_w(space,offset,data,mem_mask); }
- DECLARE_READ16_MEMBER(ibm8514_substatus_r) { return m_8514a->ibm8514_substatus_r(space,offset,mem_mask); }
- DECLARE_WRITE16_MEMBER(ibm8514_subcontrol_w) { m_8514a->ibm8514_subcontrol_w(space,offset,data,mem_mask); }
- DECLARE_READ16_MEMBER(ibm8514_subcontrol_r) { return m_8514a->ibm8514_subcontrol_r(space,offset,mem_mask); }
- DECLARE_READ16_MEMBER(ibm8514_currentx_r) { return m_8514a->ibm8514_currentx_r(space,offset,mem_mask); }
- DECLARE_WRITE16_MEMBER(ibm8514_currentx_w) { m_8514a->ibm8514_currentx_w(space,offset,data,mem_mask); }
- DECLARE_READ16_MEMBER(ibm8514_currenty_r) { return m_8514a->ibm8514_currenty_r(space,offset,mem_mask); }
- DECLARE_WRITE16_MEMBER(ibm8514_currenty_w) { m_8514a->ibm8514_currenty_w(space,offset,data,mem_mask); }
- DECLARE_READ16_MEMBER(ibm8514_desty_r) { return m_8514a->ibm8514_desty_r(space,offset,mem_mask); }
- DECLARE_WRITE16_MEMBER(ibm8514_desty_w) { m_8514a->ibm8514_desty_w(space,offset,data,mem_mask); }
- DECLARE_READ16_MEMBER(ibm8514_destx_r) { return m_8514a->ibm8514_destx_r(space,offset,mem_mask); }
- DECLARE_WRITE16_MEMBER(ibm8514_destx_w) { m_8514a->ibm8514_destx_w(space,offset,data,mem_mask); }
- DECLARE_READ16_MEMBER(ibm8514_line_error_r) { return m_8514a->ibm8514_line_error_r(space,offset,mem_mask); }
- DECLARE_WRITE16_MEMBER(ibm8514_line_error_w) { m_8514a->ibm8514_line_error_w(space,offset,data,mem_mask); }
- DECLARE_READ16_MEMBER(ibm8514_width_r) { return m_8514a->ibm8514_width_r(space,offset,mem_mask); }
- DECLARE_WRITE16_MEMBER(ibm8514_width_w) { m_8514a->ibm8514_width_w(space,offset,data,mem_mask); }
- DECLARE_READ16_MEMBER(ibm8514_gpstatus_r) { return m_8514a->ibm8514_gpstatus_r(space,offset,mem_mask); }
- DECLARE_WRITE16_MEMBER(ibm8514_cmd_w) { m_8514a->ibm8514_cmd_w(space,offset,data,mem_mask); }
- DECLARE_READ16_MEMBER(ibm8514_ssv_r) { return m_8514a->ibm8514_ssv_r(space,offset,mem_mask); }
- DECLARE_WRITE16_MEMBER(ibm8514_ssv_w) { m_8514a->ibm8514_ssv_w(space,offset,data,mem_mask); }
- DECLARE_READ16_MEMBER(ibm8514_fgcolour_r) { return m_8514a->ibm8514_fgcolour_r(space,offset,mem_mask); }
- DECLARE_WRITE16_MEMBER(ibm8514_fgcolour_w) { m_8514a->ibm8514_fgcolour_w(space,offset,data,mem_mask); }
- DECLARE_READ16_MEMBER(ibm8514_bgcolour_r) { return m_8514a->ibm8514_bgcolour_r(space,offset,mem_mask); }
- DECLARE_WRITE16_MEMBER(ibm8514_bgcolour_w) { m_8514a->ibm8514_bgcolour_w(space,offset,data,mem_mask); }
- DECLARE_READ16_MEMBER(ibm8514_read_mask_r) { return m_8514a->ibm8514_read_mask_r(space,offset,mem_mask); }
- DECLARE_WRITE16_MEMBER(ibm8514_read_mask_w) { m_8514a->ibm8514_read_mask_w(space,offset,data,mem_mask); }
- DECLARE_READ16_MEMBER(ibm8514_write_mask_r) { return m_8514a->ibm8514_write_mask_r(space,offset,mem_mask); }
- DECLARE_WRITE16_MEMBER(ibm8514_write_mask_w) { m_8514a->ibm8514_write_mask_w(space,offset,data,mem_mask); }
- DECLARE_READ16_MEMBER(ibm8514_backmix_r) { return m_8514a->ibm8514_backmix_r(space,offset,mem_mask); }
- DECLARE_WRITE16_MEMBER(ibm8514_backmix_w) { m_8514a->ibm8514_backmix_w(space,offset,data,mem_mask); }
- DECLARE_READ16_MEMBER(ibm8514_foremix_r) { return m_8514a->ibm8514_foremix_r(space,offset,mem_mask); }
- DECLARE_WRITE16_MEMBER(ibm8514_foremix_w) { m_8514a->ibm8514_foremix_w(space,offset,data,mem_mask); }
- DECLARE_READ16_MEMBER(ibm8514_multifunc_r) { return m_8514a->ibm8514_multifunc_r(space,offset,mem_mask); }
- DECLARE_WRITE16_MEMBER(ibm8514_multifunc_w) { m_8514a->ibm8514_multifunc_w(space,offset,data,mem_mask); }
- DECLARE_READ16_MEMBER(ibm8514_pixel_xfer_r) { return m_8514a->ibm8514_pixel_xfer_r(space,offset,mem_mask); }
- DECLARE_WRITE16_MEMBER(mach8_pixel_xfer_w) { m_8514a->mach8_pixel_xfer_w(space,offset,data,mem_mask); }
- DECLARE_WRITE16_MEMBER(mach8_advfunc_w) { m_8514a->mach8_advfunc_w(space,offset,data,mem_mask); }
-
- DECLARE_READ16_MEMBER(mach32_chipid_r) { return m_8514a->mach32_chipid_r(space,offset,mem_mask); }
- DECLARE_READ16_MEMBER(mach8_clksel_r) { return m_8514a->mach8_clksel_r(space,offset,mem_mask); }
- DECLARE_WRITE16_MEMBER(mach8_clksel_w) { m_8514a->mach8_clksel_w(space,offset,data,mem_mask); } // read only on the mach8
- DECLARE_READ16_MEMBER(mach32_mem_boundary_r) { return m_8514a->mach32_mem_boundary_r(space,offset,mem_mask); }
- DECLARE_WRITE16_MEMBER(mach32_mem_boundary_w) { m_8514a->mach32_mem_boundary_w(space,offset,data,mem_mask); } // read only on the mach8
- DECLARE_READ8_MEMBER(mach32_status_r) { return m_8514a->ibm8514_status_r(space,offset,mem_mask); }
- DECLARE_READ16_MEMBER(mach32_config1_r) { return m_8514a->mach32_config1_r(space,offset,mem_mask); }
- DECLARE_WRITE16_MEMBER(mach32_horz_overscan_w) { m_8514a->mach32_horz_overscan_w(space,offset,data,mem_mask); }
- DECLARE_WRITE16_MEMBER(mach32_ge_ext_config_w) { m_8514a->mach32_ge_ext_config_w(space,offset,data,mem_mask); ati_define_video_mode(); }
- DECLARE_READ16_MEMBER(mach32_ext_ge_r) { return m_8514a->mach32_ext_ge_r(space,offset,mem_mask); }
- DECLARE_READ16_MEMBER(mach32_readonly_r) { return 0; }
- DECLARE_WRITE16_MEMBER(mach32_cursor_pos_h);
- DECLARE_WRITE16_MEMBER(mach32_cursor_pos_v);
- DECLARE_WRITE16_MEMBER(mach32_cursor_colour_b_w);
- DECLARE_WRITE16_MEMBER(mach32_cursor_colour_0_w);
- DECLARE_WRITE16_MEMBER(mach32_cursor_colour_1_w);
- DECLARE_WRITE16_MEMBER(mach32_cursor_l_w);
- DECLARE_WRITE16_MEMBER(mach32_cursor_h_w);
- DECLARE_WRITE16_MEMBER(mach32_cursor_offset_w);
-
-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);
-
- DECLARE_WRITE16_MEMBER(mach64_config1_w) { } // why does the mach64 BIOS write to these, they are read only on the mach32 and earlier
- DECLARE_WRITE16_MEMBER(mach64_config2_w) { }
-
-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 3f85534a72b..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"
//**************************************************************************
@@ -19,10 +18,6 @@
DEFINE_DEVICE_TYPE(MC1502_FDC, mc1502_fdc_device, "mc1502_fdc", "MC-1502 floppy")
-FLOPPY_FORMATS_MEMBER( mc1502_fdc_device::floppy_formats )
- FLOPPY_PC_FORMAT
-FLOPPY_FORMATS_END
-
static void mc1502_floppies(device_slot_interface &device)
{
device.option_add("525qd", FLOPPY_525_QD);
@@ -45,8 +40,8 @@ void mc1502_fdc_device::device_add_mconfig(machine_config &config)
FD1793(config, m_fdc, 16_MHz_XTAL / 16);
m_fdc->intrq_wr_callback().set(FUNC(mc1502_fdc_device::mc1502_fdc_irq_drq));
m_fdc->drq_wr_callback().set(FUNC(mc1502_fdc_device::mc1502_fdc_irq_drq));
- FLOPPY_CONNECTOR(config, "fdc:0", mc1502_floppies, "525qd", mc1502_fdc_device::floppy_formats);
- FLOPPY_CONNECTOR(config, "fdc:1", mc1502_floppies, "525qd", mc1502_fdc_device::floppy_formats);
+ FLOPPY_CONNECTOR(config, "fdc:0", mc1502_floppies, "525qd", floppy_image_device::default_pc_floppy_formats);
+ FLOPPY_CONNECTOR(config, "fdc:1", mc1502_floppies, "525qd", floppy_image_device::default_pc_floppy_formats);
}
//-------------------------------------------------
@@ -70,13 +65,30 @@ TIMER_CALLBACK_MEMBER(mc1502_fdc_device::motor_callback)
motor_on = 0;
}
-uint8_t mc1502_fdc_device::mc1502_wd17xx_aux_r()
+void mc1502_fdc_device::motors_onoff()
{
- 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();
- data = 0;
+ if (motor_on)
+ {
+ // bits 2, 3 -- motor on (drive 0, 1)
+ floppy0->mon_w(!(m_control & 4));
+ floppy1->mon_w(!(m_control & 8));
+ }
+ else
+ {
+ floppy0->mon_w(ASSERT_LINE);
+ floppy1->mon_w(ASSERT_LINE);
+ }
+}
- return data;
+uint8_t mc1502_fdc_device::mc1502_wd17xx_aux_r()
+{
+ motor_timer->adjust(attotime::from_msec(3000));
+ motor_on = 1;
+ motors_onoff();
+ return 0;
}
void mc1502_fdc_device::mc1502_wd17xx_aux_w(uint8_t data)
@@ -86,22 +98,15 @@ void mc1502_fdc_device::mc1502_wd17xx_aux_w(uint8_t data)
floppy_image_device *floppy = ((data & 0x10) ? floppy1 : floppy0);
// master reset
- if ((data & 1) == 0) m_fdc->reset();
+ m_fdc->mr_w(data & 1);
m_fdc->set_floppy(floppy);
// SIDE ONE
floppy->ss_w((data & 2) ? 1 : 0);
- // bits 2, 3 -- motor on (drive 0, 1)
- floppy0->mon_w(!(data & 4));
- floppy1->mon_w(!(data & 8));
-
- if (data & 12)
- {
- motor_timer->adjust(attotime::from_msec(3000));
- motor_on = 1;
- }
+ m_control = data;
+ motors_onoff();
}
/*
@@ -109,13 +114,11 @@ void mc1502_fdc_device::mc1502_wd17xx_aux_w(uint8_t data)
*/
uint8_t mc1502_fdc_device::mc1502_wd17xx_drq_r()
{
- cpu_device *maincpu = machine().device<cpu_device>("maincpu");
-
if (!m_fdc->drq_r() && !m_fdc->intrq_r())
{
// fake cpu wait by resetting PC one insn back
- maincpu->set_state_int(I8086_IP, maincpu->state_int(I8086_IP) - 1);
- maincpu->set_input_line(INPUT_LINE_HALT, ASSERT_LINE);
+ m_cpu->set_state_int(I8086_IP, m_cpu->state_int(I8086_IP) - 1);
+ m_isa->set_ready(ASSERT_LINE); // assert I/O CH RDY
}
return m_fdc->drq_r();
@@ -126,14 +129,13 @@ 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)
{
- cpu_device *maincpu = machine().device<cpu_device>("maincpu");
-
- if (state) maincpu->set_input_line(INPUT_LINE_HALT, CLEAR_LINE);
+ if (state)
+ m_isa->set_ready(CLEAR_LINE); // deassert I/O CH RDY
}
-READ8_MEMBER(mc1502_fdc_device::mc1502_fdc_r)
+uint8_t mc1502_fdc_device::mc1502_fdc_r(offs_t offset)
{
uint8_t data = 0xff;
@@ -153,7 +155,7 @@ READ8_MEMBER(mc1502_fdc_device::mc1502_fdc_r)
return data;
}
-READ8_MEMBER(mc1502_fdc_device::mc1502_fdcv2_r)
+uint8_t mc1502_fdc_device::mc1502_fdcv2_r(offs_t offset)
{
uint8_t data = 0xff;
@@ -173,7 +175,7 @@ READ8_MEMBER(mc1502_fdc_device::mc1502_fdcv2_r)
return data;
}
-WRITE8_MEMBER(mc1502_fdc_device::mc1502_fdc_w)
+void mc1502_fdc_device::mc1502_fdc_w(offs_t offset, uint8_t data)
{
switch (offset)
{
@@ -192,7 +194,9 @@ mc1502_fdc_device::mc1502_fdc_device(const machine_config &mconfig, const char *
, device_isa8_card_interface(mconfig, *this)
, m_fdc(*this, "fdc")
, motor_on(0)
+ , m_control(0)
, motor_timer(nullptr)
+ , m_cpu(*this, finder_base::DUMMY_TAG)
{
}
@@ -205,17 +209,14 @@ void mc1502_fdc_device::device_start()
set_isa_device();
// BIOS 5.0-5.2x
- m_isa->install_device(0x010c, 0x010f,
- read8sm_delegate(FUNC(fd1793_device::read), m_fdc.target()),
- write8sm_delegate(FUNC(fd1793_device::write), m_fdc.target()));
- m_isa->install_device(0x0100, 0x010b, read8_delegate( FUNC(mc1502_fdc_device::mc1502_fdc_r), this ), write8_delegate( FUNC(mc1502_fdc_device::mc1502_fdc_w), this ) );
+ m_isa->install_device(0x010c, 0x010f, read8sm_delegate(*m_fdc, FUNC(fd1793_device::read)), write8sm_delegate(*m_fdc, FUNC(fd1793_device::write)));
+ m_isa->install_device(0x0100, 0x010b, read8sm_delegate(*this, FUNC(mc1502_fdc_device::mc1502_fdc_r)), write8sm_delegate(*this, FUNC(mc1502_fdc_device::mc1502_fdc_w)));
// BIOS 5.3x
- m_isa->install_device(0x0048, 0x004b,
- read8sm_delegate(FUNC(fd1793_device::read), m_fdc.target()),
- write8sm_delegate(FUNC(fd1793_device::write), m_fdc.target()));
- m_isa->install_device(0x004c, 0x004f, read8_delegate( FUNC(mc1502_fdc_device::mc1502_fdcv2_r), this ), write8_delegate( FUNC(mc1502_fdc_device::mc1502_fdc_w), this ) );
+ m_isa->install_device(0x0048, 0x004b, read8sm_delegate(*m_fdc, FUNC(fd1793_device::read)), write8sm_delegate(*m_fdc, FUNC(fd1793_device::write)));
+ m_isa->install_device(0x004c, 0x004f, read8sm_delegate(*this, FUNC(mc1502_fdc_device::mc1502_fdcv2_r)), write8sm_delegate(*this, FUNC(mc1502_fdc_device::mc1502_fdc_w)));
- motor_timer = machine().scheduler().timer_alloc(timer_expired_delegate(FUNC(mc1502_fdc_device::motor_callback),this));
+ motor_timer = timer_alloc(FUNC(mc1502_fdc_device::motor_callback), this);
motor_on = 0;
+ m_control = 0;
}
diff --git a/src/devices/bus/isa/mc1502_fdc.h b/src/devices/bus/isa/mc1502_fdc.h
index 57edc2d3a9c..aa48dcaefb1 100644
--- a/src/devices/bus/isa/mc1502_fdc.h
+++ b/src/devices/bus/isa/mc1502_fdc.h
@@ -27,30 +27,32 @@ public:
// construction/destruction
mc1502_fdc_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
+ template <typename T>
+ void set_cpu(T &&tag) { m_cpu.set_tag(std::forward<T>(tag)); }
TIMER_CALLBACK_MEMBER(motor_callback);
- DECLARE_READ8_MEMBER(mc1502_fdc_r);
- DECLARE_READ8_MEMBER(mc1502_fdcv2_r);
- DECLARE_WRITE8_MEMBER(mc1502_fdc_w);
+ uint8_t mc1502_fdc_r(offs_t offset);
+ uint8_t mc1502_fdcv2_r(offs_t offset);
+ void mc1502_fdc_w(offs_t offset, uint8_t data);
protected:
// device-level overrides
- virtual void device_start() override;
+ virtual void device_start() override ATTR_COLD;
// optional information overrides
- virtual void device_add_mconfig(machine_config &config) override;
- virtual const tiny_rom_entry *device_rom_region() const override;
+ virtual void device_add_mconfig(machine_config &config) override ATTR_COLD;
+ virtual const tiny_rom_entry *device_rom_region() const override ATTR_COLD;
private:
- DECLARE_FLOPPY_FORMATS(floppy_formats);
-
- DECLARE_WRITE_LINE_MEMBER(mc1502_fdc_irq_drq);
+ void mc1502_fdc_irq_drq(int state);
required_device<fd1793_device> m_fdc;
int motor_on;
+ u8 m_control;
emu_timer *motor_timer;
-
+ required_device<cpu_device> m_cpu;
+ void motors_onoff();
public:
void mc1502_wd17xx_aux_w(uint8_t data);
uint8_t mc1502_wd17xx_aux_r();
diff --git a/src/devices/bus/isa/mc1502_rom.cpp b/src/devices/bus/isa/mc1502_rom.cpp
index 7e612c10832..f3a78cb93a6 100644
--- a/src/devices/bus/isa/mc1502_rom.cpp
+++ b/src/devices/bus/isa/mc1502_rom.cpp
@@ -59,7 +59,7 @@ mc1502_rom_device::mc1502_rom_device(const machine_config &mconfig, const char *
void mc1502_rom_device::device_start()
{
set_isa_device();
- m_isa->install_rom(this, 0xe8000, 0xeffff, "XXX", "mc1502_rom");
+ m_isa->install_rom(this, 0xe8000, 0xeffff, "mc1502_rom");
}
diff --git a/src/devices/bus/isa/mc1502_rom.h b/src/devices/bus/isa/mc1502_rom.h
index bbb152df72f..890ca169578 100644
--- a/src/devices/bus/isa/mc1502_rom.h
+++ b/src/devices/bus/isa/mc1502_rom.h
@@ -25,12 +25,12 @@ public:
mc1502_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 const tiny_rom_entry *device_rom_region() const override ATTR_COLD;
protected:
// device-level overrides
- virtual void device_start() override;
- virtual void device_reset() override;
+ virtual void device_start() override ATTR_COLD;
+ virtual void device_reset() override ATTR_COLD;
};
diff --git a/src/devices/bus/isa/mcd.cpp b/src/devices/bus/isa/mcd.cpp
index 69a0ca5e844..085ab3676b9 100644
--- a/src/devices/bus/isa/mcd.cpp
+++ b/src/devices/bus/isa/mcd.cpp
@@ -3,7 +3,10 @@
#include "emu.h"
#include "mcd.h"
+#include "speaker.h"
+
#include "coreutil.h"
+#include "multibyte.h"
void mcd_isa_device::map(address_map &map)
{
@@ -11,36 +14,36 @@ void mcd_isa_device::map(address_map &map)
map(0x1, 0x1).rw(FUNC(mcd_isa_device::flag_r), FUNC(mcd_isa_device::reset_w));
}
-static INPUT_PORTS_START( ide )
-INPUT_PORTS_END
-
//**************************************************************************
// GLOBAL VARIABLES
//**************************************************************************
DEFINE_DEVICE_TYPE(ISA16_MCD, mcd_isa_device, "mcd_isa", "Mitsumi ISA CD-ROM Adapter")
-//-------------------------------------------------
-// input_ports - device-specific input ports
-//-------------------------------------------------
-
-ioport_constructor mcd_isa_device::device_input_ports() const
-{
- return INPUT_PORTS_NAME( ide );
-}
-
//**************************************************************************
// LIVE DEVICE
//**************************************************************************
+void mcd_isa_device::device_add_mconfig(machine_config &config)
+{
+ SPEAKER(config, "lheadphone").front_left();
+ SPEAKER(config, "rheadphone").front_right();
+ 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);
+}
+
//-------------------------------------------------
// mcd_isa_device - constructor
//-------------------------------------------------
mcd_isa_device::mcd_isa_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) :
cdrom_image_device(mconfig, ISA16_MCD, tag, owner, clock),
- device_isa16_card_interface( mconfig, *this )
+ device_isa16_card_interface( mconfig, *this ),
+ m_cdda(*this, "cdda")
{
+ set_interface("cdrom");
}
//-------------------------------------------------
@@ -65,7 +68,7 @@ void mcd_isa_device::device_reset()
m_cmdrd_count = 0;
m_cmdbuf_count = 0;
m_buf_count = 0;
- m_curtoctrk = 1;
+ m_curtoctrk = 0;
m_dma = 0;
m_irq = 0;
m_conf = 0;
@@ -78,6 +81,18 @@ void mcd_isa_device::device_reset()
bool mcd_isa_device::read_sector(bool first)
{
+ uint32_t lba = cdrom_file::msf_to_lba(m_readmsf);
+ if(m_drvmode == DRV_MODE_CDDA)
+ {
+ if(m_cdrom_handle->get_track_type(m_cdrom_handle->get_track(lba)) == cdrom_file::CD_TRACK_AUDIO)
+ {
+ m_cdda->stop_audio();
+ m_cdda->start_audio(lba, m_readcount);
+ return true;
+ }
+ else
+ m_drvmode = DRV_MODE_READ;
+ }
if((m_irq & IRQ_DATACOMP) && !first)
m_isa->irq5_w(ASSERT_LINE);
if(!m_readcount)
@@ -86,15 +101,15 @@ bool mcd_isa_device::read_sector(bool first)
m_data = false;
return false;
}
- uint32_t lba = msf_to_lba(m_readmsf);
- cdrom_read_data(m_cdrom_handle, lba - 150, m_buf, m_mode & 0x40 ? CD_TRACK_MODE1_RAW : CD_TRACK_MODE1);
+ m_cdda->stop_audio();
+ m_cdrom_handle->read_data(lba - 150, m_buf, m_mode & 0x40 ? cdrom_file::CD_TRACK_MODE1_RAW : cdrom_file::CD_TRACK_MODE1);
if(m_mode & 0x40)
{
//correct the header
m_buf[12] = dec_2_bcd((m_readmsf >> 16) & 0xff);
m_buf[13] = dec_2_bcd((m_readmsf >> 8) & 0xff);
}
- m_readmsf = lba_to_msf_alt(lba + 1);
+ m_readmsf = cdrom_file::lba_to_msf_alt(lba + 1);
m_buf_count = m_dmalen + 1;
m_buf_idx = 0;
m_data = true;
@@ -106,10 +121,11 @@ bool mcd_isa_device::read_sector(bool first)
return true;
}
-READ8_MEMBER(mcd_isa_device::flag_r)
+uint8_t mcd_isa_device::flag_r()
{
uint8_t ret = 0;
- m_isa->irq5_w(CLEAR_LINE);
+ if (!machine().side_effects_disabled())
+ m_isa->irq5_w(CLEAR_LINE);
if(!m_buf_count || !m_data || m_dma) // if dma enabled the cpu will never not see that flag as it will be halted
ret |= FLAG_NODATA;
if(!m_cmdbuf_count || !m_newstat)
@@ -117,19 +133,28 @@ READ8_MEMBER(mcd_isa_device::flag_r)
return ret | FLAG_UNK;
}
-READ8_MEMBER(mcd_isa_device::data_r)
+uint8_t mcd_isa_device::data_r()
{
if(m_cmdbuf_count)
{
- m_cmdbuf_count--;
- return m_cmdbuf[m_cmdbuf_idx++];
+ if(machine().side_effects_disabled())
+ return m_cmdbuf[m_cmdbuf_idx];
+ else
+ {
+ m_cmdbuf_count--;
+ return m_cmdbuf[m_cmdbuf_idx++];
+ }
}
else if(m_buf_count)
{
- uint8_t ret = m_buf_idx < 2352 ? m_buf[m_buf_idx++] : 0;
- m_buf_count--;
- if(!m_buf_count)
- read_sector();
+ uint8_t ret = m_buf_idx < 2352 ? m_buf[m_buf_idx] : 0;
+ if(!machine().side_effects_disabled())
+ {
+ m_buf_idx++;
+ m_buf_count--;
+ if(!m_buf_count)
+ read_sector();
+ }
return ret;
}
return m_stat;
@@ -142,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)
@@ -153,12 +178,12 @@ uint16_t mcd_isa_device::dack16_r(int line)
return 0;
}
-WRITE8_MEMBER(mcd_isa_device::reset_w)
+void mcd_isa_device::reset_w(uint8_t data)
{
reset();
}
-WRITE8_MEMBER(mcd_isa_device::cmd_w)
+void mcd_isa_device::cmd_w(uint8_t data)
{
if(m_cmdrd_count)
{
@@ -214,6 +239,7 @@ WRITE8_MEMBER(mcd_isa_device::cmd_w)
{
case 5:
m_readmsf = 0;
+ [[fallthrough]];
case 4:
case 3:
m_readmsf |= bcd_2_dec(data) << ((m_cmdrd_count - 3) * 8);
@@ -248,15 +274,11 @@ WRITE8_MEMBER(mcd_isa_device::cmd_w)
case CMD_GET_INFO:
if(m_cdrom_handle)
{
- uint32_t first = lba_to_msf(150), last = lba_to_msf(cdrom_get_track_start(m_cdrom_handle, 0xaa));
+ 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(cdrom_get_last_track(m_cdrom_handle));
- m_cmdbuf[3] = dec_2_bcd((last >> 16) & 0xff);
- m_cmdbuf[4] = dec_2_bcd((last >> 8) & 0xff);
- m_cmdbuf[5] = dec_2_bcd(last & 0xff);
- m_cmdbuf[6] = dec_2_bcd((first >> 16) & 0xff);
- m_cmdbuf[7] = dec_2_bcd((first >> 8) & 0xff);
- m_cmdbuf[8] = dec_2_bcd(first & 0xff);
+ m_cmdbuf[2] = dec_2_bcd(m_cdrom_handle->get_last_track());
+ put_u24be(&m_cmdbuf[3], last);
+ put_u24be(&m_cmdbuf[6], first);
m_cmdbuf[9] = 0;
m_cmdbuf_count = 10;
m_readcount = 0;
@@ -270,21 +292,20 @@ WRITE8_MEMBER(mcd_isa_device::cmd_w)
case CMD_GET_Q:
if(m_cdrom_handle)
{
- int tracks = cdrom_get_last_track(m_cdrom_handle);
- uint32_t start = lba_to_msf(cdrom_get_track_start(m_cdrom_handle, m_curtoctrk));
- uint32_t end = lba_to_msf(cdrom_get_track_start(m_cdrom_handle, m_curtoctrk < tracks ? m_curtoctrk + 1 : 0xaa));
- m_cmdbuf[1] = (cdrom_get_adr_control(m_cdrom_handle, m_curtoctrk) << 4) & 0xf0;
+ int tracks = m_cdrom_handle->get_last_track();
+ uint32_t start = m_cdrom_handle->get_track_start(m_curtoctrk);
+ uint32_t len = cdrom_file::lba_to_msf(m_cdrom_handle->get_track_start(m_curtoctrk < (tracks - 1) ? m_curtoctrk + 1 : 0xaa) - start);
+ start = cdrom_file::lba_to_msf(start);
+ 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); // index
- m_cmdbuf[4] = dec_2_bcd((start >> 16) & 0xff);
- m_cmdbuf[5] = dec_2_bcd((start >> 8) & 0xff);
- m_cmdbuf[6] = dec_2_bcd(start & 0xff);
+ m_cmdbuf[3] = dec_2_bcd(m_curtoctrk + 1); // index
+ put_u24be(&m_cmdbuf[4], len);
m_cmdbuf[7] = 0;
- m_cmdbuf[8] = dec_2_bcd((end >> 16) & 0xff);
- m_cmdbuf[9] = dec_2_bcd((end >> 8) & 0xff);
- m_cmdbuf[10] = dec_2_bcd(end & 0xff);
+ put_u24be(&m_cmdbuf[8], start);
if(m_curtoctrk >= tracks)
- m_curtoctrk = 1;
+ m_curtoctrk = 0;
+ else if(m_mode & MODE_GET_TOC)
+ m_curtoctrk++;
m_cmdbuf_count = 11;
m_readcount = 0;
}
@@ -302,8 +323,9 @@ WRITE8_MEMBER(mcd_isa_device::cmd_w)
break;
case CMD_STOPCDDA:
case CMD_STOP:
+ m_cdda->stop_audio();
m_drvmode = DRV_MODE_STOP;
- m_curtoctrk = 1;
+ m_curtoctrk = 0;
break;
case CMD_CONFIG:
m_cmdrd_count = 2;
@@ -313,7 +335,7 @@ WRITE8_MEMBER(mcd_isa_device::cmd_w)
if(m_cdrom_handle)
{
m_readcount = 0;
- m_drvmode = DRV_MODE_READ;
+ m_drvmode = data == CMD_READ1X ? DRV_MODE_CDDA : DRV_MODE_READ;
m_cmdrd_count = 6;
}
else
diff --git a/src/devices/bus/isa/mcd.h b/src/devices/bus/isa/mcd.h
index 26f3a7a31d3..5234847887a 100644
--- a/src/devices/bus/isa/mcd.h
+++ b/src/devices/bus/isa/mcd.h
@@ -6,7 +6,8 @@
#pragma once
#include "isa.h"
-#include "imagedev/chd_cd.h"
+#include "imagedev/cdromimg.h"
+#include "sound/cdda.h"
//**************************************************************************
// TYPE DEFINITIONS
@@ -22,23 +23,19 @@ public:
mcd_isa_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
protected:
- // optional information overrides
- virtual ioport_constructor device_input_ports() const override;
-
virtual uint16_t dack16_r(int line) override;
-
-protected:
- // device-level overrides
- virtual void device_start() override;
- virtual void device_reset() override;
+ 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;
private:
- DECLARE_READ8_MEMBER(data_r);
- DECLARE_READ8_MEMBER(flag_r);
- DECLARE_WRITE8_MEMBER(cmd_w);
- DECLARE_WRITE8_MEMBER(reset_w);
+ required_device<cdda_device> m_cdda;
+ uint8_t data_r();
+ uint8_t flag_r();
+ void cmd_w(uint8_t data);
+ void reset_w(uint8_t data);
- void map(address_map &map);
+ void map(address_map &map) ATTR_COLD;
bool read_sector(bool first = false);
diff --git a/src/devices/bus/isa/mda.cpp b/src/devices/bus/isa/mda.cpp
index 823ff040676..77ac7d6028e 100644
--- a/src/devices/bus/isa/mda.cpp
+++ b/src/devices/bus/isa/mda.cpp
@@ -12,6 +12,31 @@
#include "screen.h"
+#define LOG_READ (1U << 1)
+#define LOG_SETUP (1U << 2)
+#define LOG_ROW (1U << 3)
+#define LOG_MODE (1U << 4)
+#define LOG_CHRG (1U << 5)
+#define LOG_STAT (1U << 6)
+
+//#define VERBOSE (LOG_MODE|LOG_STAT)
+//#define LOG_OUTPUT_STREAM std::cout
+
+#include "logmacro.h"
+
+#define LOGR(...) LOGMASKED(LOG_READ, __VA_ARGS__)
+#define LOGSETUP(...) LOGMASKED(LOG_SETUP, __VA_ARGS__)
+#define LOGROW(...) LOGMASKED(LOG_ROW, __VA_ARGS__)
+#define LOGMODE(...) LOGMASKED(LOG_MODE, __VA_ARGS__)
+#define LOGCHRG(...) LOGMASKED(LOG_CHRG, __VA_ARGS__)
+#define LOGSTAT(...) LOGMASKED(LOG_STAT, __VA_ARGS__)
+
+#ifdef _MSC_VER
+#define FUNCNAME __func__
+#else
+#define FUNCNAME __PRETTY_FUNCTION__
+#endif
+
#define MDA_SCREEN_NAME "mda_screen"
#define MC6845_NAME "mc6845"
@@ -19,20 +44,7 @@
Hercules video card
*/
#define HERCULES_SCREEN_NAME "hercules_screen"
-
-#define VERBOSE_MDA 0 /* MDA (Monochrome Display Adapter) */
-
-#define MDA_CLOCK 16.257_MHz_XTAL
-
-#define MDA_LOG(N,M,A) \
- do { \
- if(VERBOSE_MDA>=N) \
- { \
- if( M ) \
- logerror("%11.6f: %-24s",machine().time().as_double(),(char*)M ); \
- logerror A; \
- } \
- } while (0)
+#define MDA_CLOCK XTAL(16'257'000)
static const unsigned char mda_palette[4][3] =
{
@@ -84,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);
}
@@ -119,7 +131,7 @@ void isa8_mda_device::device_add_mconfig(machine_config &config)
m_crtc->set_screen(MDA_SCREEN_NAME);
m_crtc->set_show_border_area(false);
m_crtc->set_char_width(9);
- m_crtc->set_update_row_callback(FUNC(isa8_mda_device::crtc_update_row), this);
+ m_crtc->set_update_row_callback(FUNC(isa8_mda_device::crtc_update_row));
m_crtc->out_hsync_callback().set(FUNC(isa8_mda_device::hsync_changed));
m_crtc->out_vsync_callback().set(FUNC(isa8_mda_device::vsync_changed));
@@ -170,15 +182,15 @@ void isa8_mda_device::device_start()
set_isa_device();
m_videoram.resize(0x1000);
- m_isa->install_device(0x3b0, 0x3bf, read8_delegate( FUNC(isa8_mda_device::io_read), this ), write8_delegate( FUNC(isa8_mda_device::io_write), this ) );
- m_isa->install_bank(0xb0000, 0xb0fff, "bank_mda", &m_videoram[0]);
- m_isa->install_bank(0xb1000, 0xb1fff, "bank_mda", &m_videoram[0]);
- m_isa->install_bank(0xb2000, 0xb2fff, "bank_mda", &m_videoram[0]);
- m_isa->install_bank(0xb3000, 0xb3fff, "bank_mda", &m_videoram[0]);
- m_isa->install_bank(0xb4000, 0xb4fff, "bank_mda", &m_videoram[0]);
- m_isa->install_bank(0xb5000, 0xb5fff, "bank_mda", &m_videoram[0]);
- m_isa->install_bank(0xb6000, 0xb6fff, "bank_mda", &m_videoram[0]);
- m_isa->install_bank(0xb7000, 0xb7fff, "bank_mda", &m_videoram[0]);
+ m_isa->install_device(0x3b0, 0x3bf, read8sm_delegate(*this, FUNC(isa8_mda_device::io_read)), write8sm_delegate(*this, FUNC(isa8_mda_device::io_write)));
+ m_isa->install_bank(0xb0000, 0xb0fff, &m_videoram[0]);
+ m_isa->install_bank(0xb1000, 0xb1fff, &m_videoram[0]);
+ m_isa->install_bank(0xb2000, 0xb2fff, &m_videoram[0]);
+ m_isa->install_bank(0xb3000, 0xb3fff, &m_videoram[0]);
+ m_isa->install_bank(0xb4000, 0xb4fff, &m_videoram[0]);
+ m_isa->install_bank(0xb5000, 0xb5fff, &m_videoram[0]);
+ m_isa->install_bank(0xb6000, 0xb6fff, &m_videoram[0]);
+ m_isa->install_bank(0xb7000, 0xb7fff, &m_videoram[0]);
/* Initialise the mda palette */
for (int i = 0; i < 4; i++)
@@ -211,30 +223,28 @@ void isa8_mda_device::device_reset()
The character cell size is 9x15. Column 9 is column 8 repeated for
character codes 176 to 223.
***************************************************************************/
-
MC6845_UPDATE_ROW( isa8_mda_device::mda_text_inten_update_row )
{
- const rgb_t *palette = m_palette->palette()->entry_list_raw();
- uint32_t *p = &bitmap.pix32(y);
- uint16_t chr_base = ( ra & 0x08 ) ? 0x800 | ( ra & 0x07 ) : ra;
- int i;
+ rgb_t const *const palette = m_palette->palette()->entry_list_raw();
+ uint32_t *p = &bitmap.pix(y);
+ uint16_t const chr_base = (ra & 0x08) ? 0x800 | (ra & 0x07) : ra;
- if ( y == 0 ) MDA_LOG(1,"mda_text_inten_update_row",("\n"));
- for ( i = 0; i < x_count; i++ )
+ if (y == 0) LOGROW("%11.6f: %-24s\n", machine().time().as_double(), FUNCNAME);
+ for (int i = 0; i < x_count; i++)
{
- uint16_t offset = ( ( ma + i ) << 1 ) & 0x0FFF;
- uint8_t chr = m_videoram[ offset ];
- uint8_t attr = m_videoram[ offset + 1 ];
- uint8_t data = m_chr_gen[ chr_base + chr * 8 ];
- uint8_t fg = ( attr & 0x08 ) ? 3 : 2;
+ uint16_t const offset = ((ma + i) << 1) & 0x0fff;
+ uint8_t const chr = m_videoram[offset];
+ uint8_t const attr = m_videoram[offset + 1];
+ uint8_t data = m_chr_gen[chr_base + chr * 8];
+ uint8_t fg = (attr & 0x08) ? 3 : 2;
uint8_t bg = 0;
- if ( ( attr & ~0x88 ) == 0 )
+ if ((attr & ~0x88) == 0)
{
data = 0x00;
}
- switch( attr )
+ switch (attr)
{
case 0x70:
bg = 2;
@@ -244,36 +254,36 @@ MC6845_UPDATE_ROW( isa8_mda_device::mda_text_inten_update_row )
bg = 2;
fg = 1;
break;
- case 0xF0:
+ case 0xf0:
bg = 3;
fg = 0;
break;
- case 0xF8:
+ case 0xf8:
bg = 3;
fg = 1;
break;
}
- if ( ( i == cursor_x && ( m_framecnt & 0x08 ) ) || ( attr & 0x07 ) == 0x01 )
+ if ((i == cursor_x && (m_framecnt & 0x08)) || (attr & 0x07) == 0x01)
{
- data = 0xFF;
+ data = 0xff;
}
- *p = palette[( data & 0x80 ) ? fg : bg]; p++;
- *p = palette[( data & 0x40 ) ? fg : bg]; p++;
- *p = palette[( data & 0x20 ) ? fg : bg]; p++;
- *p = palette[( data & 0x10 ) ? fg : bg]; p++;
- *p = palette[( data & 0x08 ) ? fg : bg]; p++;
- *p = palette[( data & 0x04 ) ? fg : bg]; p++;
- *p = palette[( data & 0x02 ) ? fg : bg]; p++;
- *p = palette[( data & 0x01 ) ? fg : bg]; p++;
- if ( ( chr & 0xE0 ) == 0xC0 )
+ *p++ = palette[(data & 0x80) ? fg : bg];
+ *p++ = palette[(data & 0x40) ? fg : bg];
+ *p++ = palette[(data & 0x20) ? fg : bg];
+ *p++ = palette[(data & 0x10) ? fg : bg];
+ *p++ = palette[(data & 0x08) ? fg : bg];
+ *p++ = palette[(data & 0x04) ? fg : bg];
+ *p++ = palette[(data & 0x02) ? fg : bg];
+ *p++ = palette[(data & 0x01) ? fg : bg];
+ if ((chr & 0xe0) == 0xc0)
{
- *p = palette[( data & 0x01 ) ? fg : bg]; p++;
+ *p++ = palette[(data & 0x01) ? fg : bg];
}
else
{
- *p = palette[bg]; p++;
+ *p++ = palette[bg];
}
}
}
@@ -287,80 +297,78 @@ MC6845_UPDATE_ROW( isa8_mda_device::mda_text_inten_update_row )
MC6845_UPDATE_ROW( isa8_mda_device::mda_text_blink_update_row )
{
- const rgb_t *palette = m_palette->palette()->entry_list_raw();
- uint32_t *p = &bitmap.pix32(y);
- uint16_t chr_base = ( ra & 0x08 ) ? 0x800 | ( ra & 0x07 ) : ra;
- int i;
+ rgb_t const *const palette = m_palette->palette()->entry_list_raw();
+ uint32_t *p = &bitmap.pix(y);
+ uint16_t const chr_base = (ra & 0x08) ? 0x800 | (ra & 0x07) : ra;
- if ( y == 0 ) MDA_LOG(1,"mda_text_blink_update_row",("\n"));
- for ( i = 0; i < x_count; i++ )
+ if (y == 0) LOGROW("%11.6f: %-24s\n", machine().time().as_double(), FUNCNAME);
+ for (int i = 0; i < x_count; i++)
{
- uint16_t offset = ( ( ma + i ) << 1 ) & 0x0FFF;
- uint8_t chr = m_videoram[ offset ];
- uint8_t attr = m_videoram[ offset + 1 ];
- uint8_t data = m_chr_gen[ chr_base + chr * 8 ];
- uint8_t fg = ( attr & 0x08 ) ? 3 : 2;
+ uint16_t const offset = ((ma + i) << 1) & 0x0fff;
+ uint8_t const chr = m_videoram[offset];
+ uint8_t const attr = m_videoram[offset + 1];
+ uint8_t data = m_chr_gen[chr_base + chr * 8];
+ uint8_t fg = (attr & 0x08) ? 3 : 2;
uint8_t bg = 0;
- if ( ( attr & ~0x88 ) == 0 )
+ if ((attr & ~0x88) == 0)
{
data = 0x00;
}
- switch( attr )
+ switch (attr)
{
case 0x70:
- case 0xF0:
+ case 0xf0:
bg = 2;
fg = 0;
break;
case 0x78:
- case 0xF8:
+ case 0xf8:
bg = 2;
fg = 1;
break;
}
- if ( ( attr & 0x07 ) == 0x01 )
+ if ((attr & 0x07) == 0x01)
{
- data = 0xFF;
+ data = 0xff;
}
- if ( i == cursor_x )
+ if (i == cursor_x)
{
- if ( m_framecnt & 0x08 )
+ if (m_framecnt & 0x08)
{
- data = 0xFF;
+ data = 0xff;
}
}
else
{
- if ( ( attr & 0x80 ) && ( m_framecnt & 0x10 ) )
+ if ((attr & 0x80) && (m_framecnt & 0x10))
{
data = 0x00;
}
}
- *p = palette[( data & 0x80 ) ? fg : bg]; p++;
- *p = palette[( data & 0x40 ) ? fg : bg]; p++;
- *p = palette[( data & 0x20 ) ? fg : bg]; p++;
- *p = palette[( data & 0x10 ) ? fg : bg]; p++;
- *p = palette[( data & 0x08 ) ? fg : bg]; p++;
- *p = palette[( data & 0x04 ) ? fg : bg]; p++;
- *p = palette[( data & 0x02 ) ? fg : bg]; p++;
- *p = palette[( data & 0x01 ) ? fg : bg]; p++;
- if ( ( chr & 0xE0 ) == 0xC0 )
+ *p++ = palette[(data & 0x80) ? fg : bg];
+ *p++ = palette[(data & 0x40) ? fg : bg];
+ *p++ = palette[(data & 0x20) ? fg : bg];
+ *p++ = palette[(data & 0x10) ? fg : bg];
+ *p++ = palette[(data & 0x08) ? fg : bg];
+ *p++ = palette[(data & 0x04) ? fg : bg];
+ *p++ = palette[(data & 0x02) ? fg : bg];
+ *p++ = palette[(data & 0x01) ? fg : bg];
+ if ((chr & 0xe0) == 0xc0)
{
- *p = palette[( data & 0x01 ) ? fg : bg]; p++;
+ *p++ = palette[(data & 0x01) ? fg : bg];
}
else
{
- *p = palette[bg]; p++;
+ *p++ = palette[bg];
}
}
}
-
MC6845_UPDATE_ROW( isa8_mda_device::crtc_update_row )
{
if (m_update_row_type == -1)
@@ -395,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 )
@@ -414,7 +422,7 @@ WRITE_LINE_MEMBER( isa8_mda_device::vsync_changed )
/*
* rW MDA mode control register (see #P138)
*/
-WRITE8_MEMBER( isa8_mda_device::mode_control_w )
+void isa8_mda_device::mode_control_w(uint8_t data)
{
m_mode_control = data;
@@ -443,10 +451,11 @@ WRITE8_MEMBER( isa8_mda_device::mode_control_w )
* 2-1 reserved
* 0 horizontal drive enable
*/
-READ8_MEMBER( isa8_mda_device::status_r)
+uint8_t isa8_mda_device::status_r()
{
// Faking pixel stream here
- m_pixel++;
+ if (!machine().side_effects_disabled())
+ m_pixel++;
return 0xF0 | (m_pixel & 0x08) | m_hsync;
}
@@ -458,42 +467,42 @@ READ8_MEMBER( isa8_mda_device::status_r)
* monochrome display adapter
*
*************************************************************************/
-WRITE8_MEMBER( isa8_mda_device::io_write)
+void isa8_mda_device::io_write(offs_t offset, uint8_t data)
{
switch( offset )
{
- case 0: case 2: case 4: case 6:
+ case 0x00: case 0x02: case 0x04: case 0x06:
m_crtc->address_w(data);
break;
- case 1: case 3: case 5: case 7:
+ case 0x01: case 0x03: case 0x05: case 0x07:
m_crtc->register_w(data);
break;
- case 8:
- mode_control_w(space, offset, data);
+ case 0x08:
+ mode_control_w(data);
break;
- case 12: case 13: case 14:
- m_lpt->write(space, offset - 12, data);
+ case 0x0c: case 0x0d: case 0x0e:
+ m_lpt->write(offset - 0x0c, data);
break;
}
}
-READ8_MEMBER( isa8_mda_device::io_read)
+uint8_t isa8_mda_device::io_read(offs_t offset)
{
int data = 0xff;
switch( offset )
{
- case 0: case 2: case 4: case 6:
+ case 0x00: case 0x02: case 0x04: case 0x06:
/* return last written mc6845 address value here? */
break;
- case 1: case 3: case 5: case 7:
+ case 0x01: case 0x03: case 0x05: case 0x07:
data = m_crtc->register_r();
break;
- case 10:
- data = status_r(space, offset);
+ case 0x0a:
+ data = status_r();
break;
- /* 12, 13, 14 are the LPT ports */
- case 12: case 13: case 14:
- data = m_lpt->read(space, offset - 12);
+ /* LPT ports */
+ case 0x0c: case 0x0d: case 0x0e:
+ data = m_lpt->read(offset - 0x0c);
break;
}
return data;
@@ -548,7 +557,7 @@ void isa8_hercules_device::device_add_mconfig(machine_config &config)
m_crtc->set_screen(HERCULES_SCREEN_NAME);
m_crtc->set_show_border_area(false);
m_crtc->set_char_width(9);
- m_crtc->set_update_row_callback(FUNC(isa8_hercules_device::crtc_update_row), this);
+ m_crtc->set_update_row_callback(FUNC(isa8_hercules_device::crtc_update_row));
m_crtc->out_hsync_callback().set(FUNC(isa8_mda_device::hsync_changed));
m_crtc->out_vsync_callback().set(FUNC(isa8_mda_device::vsync_changed));
@@ -591,8 +600,8 @@ void isa8_hercules_device::device_start()
m_videoram.resize(0x10000);
set_isa_device();
- m_isa->install_device(0x3b0, 0x3bf, read8_delegate( FUNC(isa8_hercules_device::io_read), this ), write8_delegate( FUNC(isa8_hercules_device::io_write), this ) );
- m_isa->install_bank(0xb0000, 0xbffff, "bank_hercules", &m_videoram[0]);
+ m_isa->install_device(0x3b0, 0x3bf, read8sm_delegate(*this, FUNC(isa8_hercules_device::io_read)), write8sm_delegate(*this, FUNC(isa8_hercules_device::io_write)));
+ m_isa->install_bank(0xb0000, 0xbffff, &m_videoram[0]);
/* Initialise the mda palette */
for(int i = 0; i < (sizeof(mda_palette) / 3); i++)
@@ -620,39 +629,41 @@ void isa8_hercules_device::device_reset()
MC6845_UPDATE_ROW( isa8_hercules_device::hercules_gfx_update_row )
{
- const rgb_t *palette = m_palette->palette()->entry_list_raw();
- uint32_t *p = &bitmap.pix32(y);
- uint16_t gfx_base = ( ( m_mode_control & 0x80 ) ? 0x8000 : 0x0000 ) | ( ( ra & 0x03 ) << 13 );
- int i;
- if ( y == 0 ) MDA_LOG(1,"hercules_gfx_update_row",("\n"));
- for ( i = 0; i < x_count; i++ )
+ rgb_t const *const palette = m_palette->palette()->entry_list_raw();
+ uint32_t *p = &bitmap.pix(y);
+ uint16_t const gfx_base = ((m_mode_control & 0x80) ? 0x8000 : 0x0000) | ((ra & 0x03) << 13);
+
+ if (y == 0) LOGROW("%11.6f: %-24s\n", machine().time().as_double(), FUNCNAME);
+ for (int i = 0; i < x_count; i++)
{
- uint8_t data = m_videoram[ gfx_base + ( ( ma + i ) << 1 ) ];
-
- *p = palette[( data & 0x80 ) ? 2 : 0]; p++;
- *p = palette[( data & 0x40 ) ? 2 : 0]; p++;
- *p = palette[( data & 0x20 ) ? 2 : 0]; p++;
- *p = palette[( data & 0x10 ) ? 2 : 0]; p++;
- *p = palette[( data & 0x08 ) ? 2 : 0]; p++;
- *p = palette[( data & 0x04 ) ? 2 : 0]; p++;
- *p = palette[( data & 0x02 ) ? 2 : 0]; p++;
- *p = palette[( data & 0x01 ) ? 2 : 0]; p++;
-
- data = m_videoram[ gfx_base + ( ( ma + i ) << 1 ) + 1 ];
-
- *p = palette[( data & 0x80 ) ? 2 : 0]; p++;
- *p = palette[( data & 0x40 ) ? 2 : 0]; p++;
- *p = palette[( data & 0x20 ) ? 2 : 0]; p++;
- *p = palette[( data & 0x10 ) ? 2 : 0]; p++;
- *p = palette[( data & 0x08 ) ? 2 : 0]; p++;
- *p = palette[( data & 0x04 ) ? 2 : 0]; p++;
- *p = palette[( data & 0x02 ) ? 2 : 0]; p++;
- *p = palette[( data & 0x01 ) ? 2 : 0]; p++;
+ uint8_t data;
+
+ data = m_videoram[gfx_base + ((ma + i) << 1)];
+
+ *p++ = palette[(data & 0x80) ? 2 : 0];
+ *p++ = palette[(data & 0x40) ? 2 : 0];
+ *p++ = palette[(data & 0x20) ? 2 : 0];
+ *p++ = palette[(data & 0x10) ? 2 : 0];
+ *p++ = palette[(data & 0x08) ? 2 : 0];
+ *p++ = palette[(data & 0x04) ? 2 : 0];
+ *p++ = palette[(data & 0x02) ? 2 : 0];
+ *p++ = palette[(data & 0x01) ? 2 : 0];
+
+ data = m_videoram[gfx_base + ((ma + i) << 1) + 1];
+
+ *p++ = palette[(data & 0x80) ? 2 : 0];
+ *p++ = palette[(data & 0x40) ? 2 : 0];
+ *p++ = palette[(data & 0x20) ? 2 : 0];
+ *p++ = palette[(data & 0x10) ? 2 : 0];
+ *p++ = palette[(data & 0x08) ? 2 : 0];
+ *p++ = palette[(data & 0x04) ? 2 : 0];
+ *p++ = palette[(data & 0x02) ? 2 : 0];
+ *p++ = palette[(data & 0x01) ? 2 : 0];
}
}
-WRITE8_MEMBER( isa8_hercules_device::mode_control_w )
+void isa8_hercules_device::mode_control_w(uint8_t data)
{
m_mode_control = data;
@@ -677,23 +688,23 @@ WRITE8_MEMBER( isa8_hercules_device::mode_control_w )
}
-WRITE8_MEMBER( isa8_hercules_device::io_write )
+void isa8_hercules_device::io_write(offs_t offset, uint8_t data)
{
switch( offset )
{
- case 0: case 2: case 4: case 6:
+ case 0x00: case 0x02: case 0x04: case 0x06:
m_crtc->address_w(data);
break;
- case 1: case 3: case 5: case 7:
+ case 0x01: case 0x03: case 0x05: case 0x07:
m_crtc->register_w(data);
break;
- case 8:
- mode_control_w(space, offset, data);
+ case 0x08:
+ mode_control_w(data);
break;
- case 12: case 13: case 14:
- m_lpt->write(space, offset - 12, data);
+ case 0x0c: case 0x0d: case 0x0e:
+ m_lpt->write(offset - 12, data);
break;
- case 15:
+ case 0x0f:
m_configuration_switch = data;
break;
}
@@ -711,32 +722,33 @@ WRITE8_MEMBER( isa8_hercules_device::io_write )
* 2-1 reserved
* 0 horizontal drive enable
*/
-READ8_MEMBER( isa8_hercules_device::status_r )
+uint8_t isa8_hercules_device::status_r()
{
// Faking pixel stream here
- m_pixel++;
+ if (!machine().side_effects_disabled())
+ m_pixel++;
return m_vsync | ( m_pixel & 0x08 ) | m_hsync;
}
-READ8_MEMBER( isa8_hercules_device::io_read )
+uint8_t isa8_hercules_device::io_read(offs_t offset)
{
int data = 0xff;
switch( offset )
{
- case 0: case 2: case 4: case 6:
+ case 0x00: case 0x02: case 0x04: case 0x06:
/* return last written mc6845 address value here? */
break;
- case 1: case 3: case 5: case 7:
+ case 0x01: case 0x03: case 0x05: case 0x07:
data = m_crtc->register_r();
break;
- case 10:
- data = status_r(space, offset);
+ case 0x0a:
+ data = status_r();
break;
- /* 12, 13, 14 are the LPT ports */
- case 12: case 13: case 14:
- data = m_lpt->read(space, offset - 12);
+ /* LPT ports */
+ case 0xc: case 0xd: case 0xe:
+ data = m_lpt->read(offset - 0x0c);
break;
}
return data;
@@ -762,7 +774,7 @@ void isa8_ec1840_0002_device::device_add_mconfig(machine_config &config)
m_crtc->set_screen(MDA_SCREEN_NAME);
m_crtc->set_show_border_area(false);
m_crtc->set_char_width(8);
- m_crtc->set_update_row_callback(FUNC(isa8_mda_device::crtc_update_row), this);
+ m_crtc->set_update_row_callback(FUNC(isa8_mda_device::crtc_update_row));
m_crtc->out_hsync_callback().set(FUNC(isa8_mda_device::hsync_changed));
m_crtc->out_vsync_callback().set(FUNC(isa8_mda_device::vsync_changed));
}
@@ -785,8 +797,8 @@ void isa8_ec1840_0002_device::device_start()
isa8_mda_device::device_start();
m_soft_chr_gen = std::make_unique<uint8_t[]>(0x2000);
- m_isa->install_bank(0xdc000, 0xddfff, "bank_chargen", m_soft_chr_gen.get());
- m_isa->install_bank(0xde000, 0xdffff, "bank_chargen", m_soft_chr_gen.get());
+ m_isa->install_bank(0xdc000, 0xddfff, m_soft_chr_gen.get());
+ m_isa->install_bank(0xde000, 0xdffff, m_soft_chr_gen.get());
}
void isa8_ec1840_0002_device::device_reset()
@@ -804,27 +816,26 @@ void isa8_ec1840_0002_device::device_reset()
MC6845_UPDATE_ROW( isa8_ec1840_0002_device::mda_lowres_text_inten_update_row )
{
- const rgb_t *palette = m_palette->palette()->entry_list_raw();
- uint32_t *p = &bitmap.pix32(y);
- uint16_t chr_base = ra;
- int i;
+ rgb_t const *const palette = m_palette->palette()->entry_list_raw();
+ uint32_t *p = &bitmap.pix(y);
+ uint16_t const chr_base = ra;
- if ( y == 0 ) MDA_LOG(1,"mda_lowres_text_inten_update_row",("\n"));
- for ( i = 0; i < x_count; i++ )
+ if (y == 0) LOGROW("%11.6f: %-24s\n", machine().time().as_double(), FUNCNAME);
+ for (int i = 0; i < x_count; i++)
{
- uint16_t offset = ( ( ma + i ) << 1 ) & 0x0FFF;
- uint8_t chr = m_videoram[ offset ];
- uint8_t attr = m_videoram[ offset + 1 ];
- uint8_t data = m_chr_gen[ (chr_base + chr * 16) << 1 ];
- uint8_t fg = ( attr & 0x08 ) ? 3 : 2;
+ uint16_t const offset = ((ma + i) << 1) & 0x0fff;
+ uint8_t const chr = m_videoram[offset];
+ uint8_t const attr = m_videoram[offset + 1];
+ uint8_t data = m_chr_gen[(chr_base + chr * 16) << 1];
+ uint8_t fg = (attr & 0x08) ? 3 : 2;
uint8_t bg = 0;
- if ( ( attr & ~0x88 ) == 0 )
+ if ((attr & ~0x88) == 0)
{
data = 0x00;
}
- switch( attr )
+ switch (attr)
{
case 0x70:
bg = 2;
@@ -834,29 +845,29 @@ MC6845_UPDATE_ROW( isa8_ec1840_0002_device::mda_lowres_text_inten_update_row )
bg = 2;
fg = 1;
break;
- case 0xF0:
+ case 0xf0:
bg = 3;
fg = 0;
break;
- case 0xF8:
+ case 0xf8:
bg = 3;
fg = 1;
break;
}
- if ( ( i == cursor_x && ( m_framecnt & 0x08 ) ) || ( attr & 0x07 ) == 0x01 )
+ if ((i == cursor_x && (m_framecnt & 0x08)) || (attr & 0x07) == 0x01)
{
- data = 0xFF;
+ data = 0xff;
}
- *p = palette[( data & 0x80 ) ? fg : bg]; p++;
- *p = palette[( data & 0x40 ) ? fg : bg]; p++;
- *p = palette[( data & 0x20 ) ? fg : bg]; p++;
- *p = palette[( data & 0x10 ) ? fg : bg]; p++;
- *p = palette[( data & 0x08 ) ? fg : bg]; p++;
- *p = palette[( data & 0x04 ) ? fg : bg]; p++;
- *p = palette[( data & 0x02 ) ? fg : bg]; p++;
- *p = palette[( data & 0x01 ) ? fg : bg]; p++;
+ *p++ = palette[(data & 0x80) ? fg : bg];
+ *p++ = palette[(data & 0x40) ? fg : bg];
+ *p++ = palette[(data & 0x20) ? fg : bg];
+ *p++ = palette[(data & 0x10) ? fg : bg];
+ *p++ = palette[(data & 0x08) ? fg : bg];
+ *p++ = palette[(data & 0x04) ? fg : bg];
+ *p++ = palette[(data & 0x02) ? fg : bg];
+ *p++ = palette[(data & 0x01) ? fg : bg];
}
}
@@ -868,72 +879,71 @@ MC6845_UPDATE_ROW( isa8_ec1840_0002_device::mda_lowres_text_inten_update_row )
MC6845_UPDATE_ROW( isa8_ec1840_0002_device::mda_lowres_text_blink_update_row )
{
- const rgb_t *palette = m_palette->palette()->entry_list_raw();
- uint32_t *p = &bitmap.pix32(y);
- uint16_t chr_base = ra;
- int i;
+ rgb_t const *const palette = m_palette->palette()->entry_list_raw();
+ uint32_t *p = &bitmap.pix(y);
+ uint16_t const chr_base = ra;
- if ( y == 0 ) MDA_LOG(1,"mda_lowres_text_blink_update_row",("\n"));
- for ( i = 0; i < x_count; i++ )
+ if (y == 0) LOGROW("%11.6f: %-24s\n", machine().time().as_double(), FUNCNAME);
+ for (int i = 0; i < x_count; i++)
{
- uint16_t offset = ( ( ma + i ) << 1 ) & 0x0FFF;
- uint8_t chr = m_videoram[ offset ];
- uint8_t attr = m_videoram[ offset + 1 ];
- uint8_t data = m_chr_gen[ (chr_base + chr * 16) << 1 ];
- uint8_t fg = ( attr & 0x08 ) ? 3 : 2;
+ uint16_t const offset = ((ma + i) << 1) & 0x0fff;
+ uint8_t const chr = m_videoram[offset];
+ uint8_t const attr = m_videoram[offset + 1];
+ uint8_t data = m_chr_gen[(chr_base + chr * 16) << 1];
+ uint8_t fg = (attr & 0x08) ? 3 : 2;
uint8_t bg = 0;
- if ( ( attr & ~0x88 ) == 0 )
+ if ((attr & ~0x88) == 0)
{
data = 0x00;
}
- switch( attr )
+ switch (attr)
{
case 0x70:
- case 0xF0:
+ case 0xf0:
bg = 2;
fg = 0;
break;
case 0x78:
- case 0xF8:
+ case 0xf8:
bg = 2;
fg = 1;
break;
}
- if ( ( attr & 0x07 ) == 0x01 )
+ if ((attr & 0x07) == 0x01)
{
- data = 0xFF;
+ data = 0xff;
}
- if ( i == cursor_x )
+ if (i == cursor_x)
{
- if ( m_framecnt & 0x08 )
+ if (m_framecnt & 0x08)
{
- data = 0xFF;
+ data = 0xff;
}
}
else
{
- if ( ( attr & 0x80 ) && ( m_framecnt & 0x10 ) )
+ if ((attr & 0x80) && (m_framecnt & 0x10))
{
data = 0x00;
}
}
- *p = palette[( data & 0x80 ) ? fg : bg]; p++;
- *p = palette[( data & 0x40 ) ? fg : bg]; p++;
- *p = palette[( data & 0x20 ) ? fg : bg]; p++;
- *p = palette[( data & 0x10 ) ? fg : bg]; p++;
- *p = palette[( data & 0x08 ) ? fg : bg]; p++;
- *p = palette[( data & 0x04 ) ? fg : bg]; p++;
- *p = palette[( data & 0x02 ) ? fg : bg]; p++;
- *p = palette[( data & 0x01 ) ? fg : bg]; p++;
+ *p++ = palette[(data & 0x80) ? fg : bg];
+ *p++ = palette[(data & 0x40) ? fg : bg];
+ *p++ = palette[(data & 0x20) ? fg : bg];
+ *p++ = palette[(data & 0x10) ? fg : bg];
+ *p++ = palette[(data & 0x08) ? fg : bg];
+ *p++ = palette[(data & 0x04) ? fg : bg];
+ *p++ = palette[(data & 0x02) ? fg : bg];
+ *p++ = palette[(data & 0x01) ? fg : bg];
}
}
-WRITE8_MEMBER( isa8_ec1840_0002_device::mode_control_w )
+void isa8_ec1840_0002_device::mode_control_w(uint8_t data)
{
m_mode_control = data;
diff --git a/src/devices/bus/isa/mda.h b/src/devices/bus/isa/mda.h
index c8b259f1fb3..a54c34496b5 100644
--- a/src/devices/bus/isa/mda.h
+++ b/src/devices/bus/isa/mda.h
@@ -9,6 +9,7 @@
#include "machine/pc_lpt.h"
#include "video/mc6845.h"
#include "emupal.h"
+#include "screen.h"
//**************************************************************************
// TYPE DEFINITIONS
@@ -25,13 +26,13 @@ public:
// construction/destruction
isa8_mda_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
- virtual DECLARE_READ8_MEMBER(io_read);
- virtual DECLARE_WRITE8_MEMBER(io_write);
- virtual DECLARE_READ8_MEMBER(status_r);
- virtual DECLARE_WRITE8_MEMBER(mode_control_w);
+ virtual uint8_t io_read(offs_t offset);
+ virtual void io_write(offs_t offset, uint8_t data);
+ 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 );
@@ -39,18 +40,18 @@ protected:
isa8_mda_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_start() override ATTR_COLD;
+ virtual void device_reset() override ATTR_COLD;
// optional information overrides
- virtual void device_add_mconfig(machine_config &config) override;
- virtual const tiny_rom_entry *device_rom_region() const override;
+ virtual void device_add_mconfig(machine_config &config) override ATTR_COLD;
+ virtual const tiny_rom_entry *device_rom_region() const override ATTR_COLD;
required_device<mc6845_device> m_crtc;
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 );
@@ -82,19 +83,19 @@ public:
// construction/destruction
isa8_hercules_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
- virtual DECLARE_READ8_MEMBER(io_read) override;
- virtual DECLARE_WRITE8_MEMBER(io_write) override;
- virtual DECLARE_READ8_MEMBER(status_r) override;
- virtual DECLARE_WRITE8_MEMBER(mode_control_w) override;
+ virtual uint8_t io_read(offs_t offset) override;
+ virtual void io_write(offs_t offset, uint8_t data) override;
+ virtual uint8_t status_r() override;
+ virtual void mode_control_w(uint8_t data) override;
protected:
// device-level overrides
- virtual void device_start() override;
- virtual void device_reset() override;
+ virtual void device_start() override ATTR_COLD;
+ virtual void device_reset() override ATTR_COLD;
// optional information overrides
- virtual void device_add_mconfig(machine_config &config) override;
- virtual const tiny_rom_entry *device_rom_region() const override;
+ virtual void device_add_mconfig(machine_config &config) override ATTR_COLD;
+ virtual const tiny_rom_entry *device_rom_region() const override ATTR_COLD;
private:
virtual MC6845_UPDATE_ROW( crtc_update_row ) override;
@@ -118,14 +119,14 @@ public:
protected:
// device-level overrides
- virtual void device_start() override;
- virtual void device_reset() override;
+ virtual void device_start() override ATTR_COLD;
+ virtual void device_reset() override ATTR_COLD;
// optional information overrides
- virtual void device_add_mconfig(machine_config &config) override;
+ virtual void device_add_mconfig(machine_config &config) override ATTR_COLD;
private:
- virtual DECLARE_WRITE8_MEMBER(mode_control_w) override;
+ virtual void mode_control_w(uint8_t data) override;
virtual MC6845_UPDATE_ROW( crtc_update_row ) override;
MC6845_UPDATE_ROW( mda_lowres_text_inten_update_row );
diff --git a/src/devices/bus/isa/mpu401.cpp b/src/devices/bus/isa/mpu401.cpp
index 2ce9e1feae2..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)
{
}
@@ -77,7 +77,7 @@ void isa8_mpu401_device::device_start()
{
set_isa_device();
- m_isa->install_device(0x330, 0x0331, READ8_DEVICE_DELEGATE(m_mpu401, mpu401_device, mpu_r), WRITE8_DEVICE_DELEGATE(m_mpu401, mpu401_device, mpu_w));
+ m_isa->install_device(0x330, 0x0331, read8sm_delegate(*m_mpu401, FUNC(mpu401_device::mpu_r)), write8sm_delegate(*m_mpu401, FUNC(mpu401_device::mpu_w)));
}
//-------------------------------------------------
diff --git a/src/devices/bus/isa/mpu401.h b/src/devices/bus/isa/mpu401.h
index 89974be7b84..e574f5f4553 100644
--- a/src/devices/bus/isa/mpu401.h
+++ b/src/devices/bus/isa/mpu401.h
@@ -24,15 +24,15 @@ public:
protected:
// device-level overrides
- virtual void device_start() override;
- virtual void device_reset() override;
+ virtual void device_start() override ATTR_COLD;
+ virtual void device_reset() override ATTR_COLD;
// optional information overrides
- virtual void device_add_mconfig(machine_config &config) override;
+ virtual void device_add_mconfig(machine_config &config) override ATTR_COLD;
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 3e40653e175..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"
//**************************************************************************
@@ -28,10 +27,11 @@
DEFINE_DEVICE_TYPE(ISA8_FDC344, fdc344_device, "fdc344", "Ably-Tech FDC-344")
DEFINE_DEVICE_TYPE(ISA8_FDCMAG, fdcmag_device, "fdcmag", "Magitronic Multi Floppy Controller Card")
-FLOPPY_FORMATS_MEMBER( mufdc_device::floppy_formats )
- FLOPPY_PC_FORMAT,
- FLOPPY_NASLITE_FORMAT
-FLOPPY_FORMATS_END
+void mufdc_device::floppy_formats(format_registration &fr)
+{
+ fr.add_pc_formats();
+ fr.add(FLOPPY_NASLITE_FORMAT);
+}
static void drives(device_slot_interface &device)
{
@@ -160,8 +160,8 @@ void mufdc_device::device_start()
void mufdc_device::device_reset()
{
- m_isa->install_rom(this, 0xc8000, 0xc9fff, shortname(), "option");
- m_isa->install_device(0x3f0, 0x3f7, *m_fdc, &pc_fdc_interface::map);
+ m_isa->install_rom(this, 0xc8000, 0xc9fff, "option");
+ m_isa->install_device(0x3f0, 0x3f7, *m_fdc, &mcs3201_device::map);
m_isa->set_dma_channel(2, this, true);
}
@@ -170,17 +170,17 @@ void mufdc_device::device_reset()
// FDC INTERFACE
//**************************************************************************
-READ8_MEMBER( mufdc_device::fdc_input_r )
+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 2fa000757e4..fc16719ccab 100644
--- a/src/devices/bus/isa/mufdc.h
+++ b/src/devices/bus/isa/mufdc.h
@@ -37,12 +37,12 @@ protected:
mufdc_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_start() override ATTR_COLD;
+ virtual void device_reset() override ATTR_COLD;
// optional information overrides
- virtual void device_add_mconfig(machine_config &config) override;
- virtual ioport_constructor device_input_ports() const override;
+ virtual void device_add_mconfig(machine_config &config) override ATTR_COLD;
+ virtual ioport_constructor device_input_ports() const override ATTR_COLD;
// device_isa8_card_interface
virtual uint8_t dack_r(int line) override;
@@ -51,13 +51,13 @@ protected:
virtual void eop_w(int state) override;
private:
- DECLARE_FLOPPY_FORMATS( floppy_formats );
+ static void floppy_formats(format_registration &fr);
- DECLARE_READ8_MEMBER( fdc_input_r );
- DECLARE_WRITE_LINE_MEMBER( fdc_irq_w );
- DECLARE_WRITE_LINE_MEMBER( fdc_drq_w );
+ uint8_t fdc_input_r();
+ void fdc_irq_w(int state);
+ void fdc_drq_w(int state);
- required_device<pc_fdc_interface> m_fdc;
+ required_device<mcs3201_device> m_fdc;
required_ioport m_config;
};
@@ -67,7 +67,7 @@ public:
// construction/destruction
fdc344_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
- virtual const tiny_rom_entry *device_rom_region() const override;
+ virtual const tiny_rom_entry *device_rom_region() const override ATTR_COLD;
};
class fdcmag_device : public mufdc_device
@@ -76,7 +76,7 @@ public:
// construction/destruction
fdcmag_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
- virtual const tiny_rom_entry *device_rom_region() const override;
+ virtual const tiny_rom_entry *device_rom_region() const override ATTR_COLD;
};
// device type definition
diff --git a/src/devices/bus/isa/myb3k_com.cpp b/src/devices/bus/isa/myb3k_com.cpp
index 88987e87e41..e4a8ce30ca8 100644
--- a/src/devices/bus/isa/myb3k_com.cpp
+++ b/src/devices/bus/isa/myb3k_com.cpp
@@ -103,16 +103,16 @@ void isa8_myb3k_com_device::device_reset()
// IO base factory setting is 0x540
uint32_t base = m_iobase->read();
m_isa->install_device(base, base + 1,
- read8sm_delegate(FUNC(i8251_device::read), m_usart.target()),
- write8sm_delegate(FUNC(i8251_device::write), m_usart.target()) );
+ read8sm_delegate(*m_usart, FUNC(i8251_device::read)),
+ write8sm_delegate(*m_usart, FUNC(i8251_device::write)));
m_isa->install_device(base + 2, base + 2,
- read8_delegate(FUNC(isa8_myb3k_com_device::dce_status), this),
- write8_delegate(FUNC(isa8_myb3k_com_device::dce_control), this) );
+ read8smo_delegate(*this, FUNC(isa8_myb3k_com_device::dce_status)),
+ write8smo_delegate(*this, FUNC(isa8_myb3k_com_device::dce_control)));
m_isa->install_device(base + 4, base + 7,
- read8sm_delegate(FUNC(pit8253_device::read), subdevice<pit8253_device>("pit")),
- write8sm_delegate(FUNC(pit8253_device::write), subdevice<pit8253_device>("pit")) );
+ read8sm_delegate(*subdevice<pit8253_device>("pit"), FUNC(pit8253_device::read)),
+ write8sm_delegate(*subdevice<pit8253_device>("pit"), FUNC(pit8253_device::write)));
m_irq = m_isairq->read();
m_installed = true;
@@ -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)
{
@@ -234,7 +234,7 @@ WRITE_LINE_MEMBER(isa8_myb3k_com_device::ri_w)
// dce_control -
//------------------------------------------------
#define TX_IRQ_RESET_BIT 0x40
-WRITE8_MEMBER(isa8_myb3k_com_device::dce_control)
+void isa8_myb3k_com_device::dce_control(uint8_t data)
{
m_control = data;
if (m_control & TX_IRQ_RESET_BIT)
@@ -247,7 +247,7 @@ WRITE8_MEMBER(isa8_myb3k_com_device::dce_control)
//------------------------------------------------
// dce_status - open LS368 gate and read status
//------------------------------------------------
-READ8_MEMBER(isa8_myb3k_com_device::dce_status)
+uint8_t isa8_myb3k_com_device::dce_status()
{
return m_status;
}
diff --git a/src/devices/bus/isa/myb3k_com.h b/src/devices/bus/isa/myb3k_com.h
index 73f87d73b48..1e765cf2568 100644
--- a/src/devices/bus/isa/myb3k_com.h
+++ b/src/devices/bus/isa/myb3k_com.h
@@ -39,27 +39,27 @@ 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);
- DECLARE_WRITE8_MEMBER(dce_control);
- DECLARE_READ8_MEMBER(dce_status);
+ 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();
protected:
isa8_myb3k_com_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_start() override ATTR_COLD;
+ virtual void device_reset() override ATTR_COLD;
// optional information overrides
- virtual void device_add_mconfig(machine_config &config) override;
- virtual ioport_constructor device_input_ports() const override;
+ virtual void device_add_mconfig(machine_config &config) override ATTR_COLD;
+ virtual ioport_constructor device_input_ports() const override ATTR_COLD;
// helpers
void com_int();
diff --git a/src/devices/bus/isa/myb3k_fdc.cpp b/src/devices/bus/isa/myb3k_fdc.cpp
index 90eb28c706b..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)
@@ -56,19 +53,6 @@ void isa8_myb3k_fdc471x_device_base::map(address_map &map)
map(0x05, 0x05).r(FUNC(isa8_myb3k_fdc471x_device_base::myb3k_fdc_status));
}
-FLOPPY_FORMATS_MEMBER( isa8_myb3k_fdc4710_device::myb3k_floppy_formats )
- FLOPPY_IMD_FORMAT
-FLOPPY_FORMATS_END
-
-FLOPPY_FORMATS_MEMBER( isa8_myb3k_fdc4711_device::myb3k_floppy_formats )
- FLOPPY_PC_FORMAT,
- FLOPPY_IMD_FORMAT
-FLOPPY_FORMATS_END
-
-FLOPPY_FORMATS_MEMBER( isa8_myb3k_fdc4712_device::myb3k_floppy_formats )
- FLOPPY_IMD_FORMAT
-FLOPPY_FORMATS_END
-
static void myb3k_sd_floppies(device_slot_interface &device)
{
device.option_add("525sd", FLOPPY_525_SD);
@@ -97,8 +81,8 @@ void isa8_myb3k_fdc471x_device_base::device_add_mconfig(machine_config &config)
void isa8_myb3k_fdc4710_device::device_add_mconfig(machine_config &config)
{
MB8876(config, m_fdc, XTAL(15'974'400) / 8); /* From StepOne schematics */
- FLOPPY_CONNECTOR(config, m_floppy_connectors[0], myb3k_sd_floppies, "525sd", isa8_myb3k_fdc4710_device::myb3k_floppy_formats);
- FLOPPY_CONNECTOR(config, m_floppy_connectors[1], myb3k_sd_floppies, "525sd", isa8_myb3k_fdc4710_device::myb3k_floppy_formats);
+ FLOPPY_CONNECTOR(config, m_floppy_connectors[0], myb3k_sd_floppies, "525sd", floppy_image_device::default_mfm_floppy_formats);
+ FLOPPY_CONNECTOR(config, m_floppy_connectors[1], myb3k_sd_floppies, "525sd", floppy_image_device::default_mfm_floppy_formats);
isa8_myb3k_fdc471x_device_base::device_add_mconfig(config);
}
@@ -107,10 +91,10 @@ void isa8_myb3k_fdc4710_device::device_add_mconfig(machine_config &config)
void isa8_myb3k_fdc4711_device::device_add_mconfig(machine_config &config)
{
FD1791(config, m_fdc, XTAL(15'974'400) / 16);
- FLOPPY_CONNECTOR(config, m_floppy_connectors[0], myb3k_qd_floppies, "525qd", isa8_myb3k_fdc4711_device::myb3k_floppy_formats);
- FLOPPY_CONNECTOR(config, m_floppy_connectors[1], myb3k_qd_floppies, "525qd", isa8_myb3k_fdc4711_device::myb3k_floppy_formats);
- FLOPPY_CONNECTOR(config, m_floppy_connectors[2], myb3k_qd_floppies, "525qd", isa8_myb3k_fdc4711_device::myb3k_floppy_formats);
- FLOPPY_CONNECTOR(config, m_floppy_connectors[3], myb3k_qd_floppies, "525qd", isa8_myb3k_fdc4711_device::myb3k_floppy_formats);
+ FLOPPY_CONNECTOR(config, m_floppy_connectors[0], myb3k_qd_floppies, "525qd", floppy_image_device::default_pc_floppy_formats);
+ FLOPPY_CONNECTOR(config, m_floppy_connectors[1], myb3k_qd_floppies, "525qd", floppy_image_device::default_pc_floppy_formats);
+ FLOPPY_CONNECTOR(config, m_floppy_connectors[2], myb3k_qd_floppies, "525qd", floppy_image_device::default_pc_floppy_formats);
+ FLOPPY_CONNECTOR(config, m_floppy_connectors[3], myb3k_qd_floppies, "525qd", floppy_image_device::default_pc_floppy_formats);
isa8_myb3k_fdc471x_device_base::device_add_mconfig(config);
}
@@ -118,10 +102,10 @@ void isa8_myb3k_fdc4711_device::device_add_mconfig(machine_config &config)
void isa8_myb3k_fdc4712_device::device_add_mconfig(machine_config &config)
{
MB8876(config, m_fdc, XTAL(15'974'400) / 8);
- FLOPPY_CONNECTOR(config, m_floppy_connectors[0], myb3k_8inch_floppies, "8dsdd", isa8_myb3k_fdc4712_device::myb3k_floppy_formats);
- FLOPPY_CONNECTOR(config, m_floppy_connectors[1], myb3k_8inch_floppies, "8dsdd", isa8_myb3k_fdc4712_device::myb3k_floppy_formats);
- FLOPPY_CONNECTOR(config, m_floppy_connectors[2], myb3k_8inch_floppies, "8dsdd", isa8_myb3k_fdc4712_device::myb3k_floppy_formats);
- FLOPPY_CONNECTOR(config, m_floppy_connectors[3], myb3k_8inch_floppies, "8dsdd", isa8_myb3k_fdc4712_device::myb3k_floppy_formats);
+ FLOPPY_CONNECTOR(config, m_floppy_connectors[0], myb3k_8inch_floppies, "8dsdd", floppy_image_device::default_mfm_floppy_formats);
+ FLOPPY_CONNECTOR(config, m_floppy_connectors[1], myb3k_8inch_floppies, "8dsdd", floppy_image_device::default_mfm_floppy_formats);
+ FLOPPY_CONNECTOR(config, m_floppy_connectors[2], myb3k_8inch_floppies, "8dsdd", floppy_image_device::default_mfm_floppy_formats);
+ FLOPPY_CONNECTOR(config, m_floppy_connectors[3], myb3k_8inch_floppies, "8dsdd", floppy_image_device::default_mfm_floppy_formats);
isa8_myb3k_fdc471x_device_base::device_add_mconfig(config);
}
@@ -177,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);
@@ -186,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);
@@ -194,8 +178,10 @@ WRITE_LINE_MEMBER( isa8_myb3k_fdc471x_device_base::drq_w )
{
case 1:
m_isa->drq1_w(state);
+ [[fallthrough]]; // FIXME: really?
case 2:
m_isa->drq2_w(state);
+ [[fallthrough]]; // FIXME: really?
default:
break;
}
@@ -227,7 +213,7 @@ void isa8_myb3k_fdc471x_device_base::eop_w(int state)
//--------------------------------------------------------
// myb3k_inv_fdc_data_r - a LS240 inverts databus for FDC
//--------------------------------------------------------
-READ8_MEMBER( isa8_myb3k_fdc471x_device_base::myb3k_inv_fdc_data_r )
+uint8_t isa8_myb3k_fdc471x_device_base::myb3k_inv_fdc_data_r(offs_t offset)
{
uint8_t tmp = m_fdc->read(offset);
LOGR("%s: %02x -> %02x\n", FUNCNAME, tmp, (~tmp) & 0xff);
@@ -237,7 +223,7 @@ READ8_MEMBER( isa8_myb3k_fdc471x_device_base::myb3k_inv_fdc_data_r )
//--------------------------------------------------------
// myb3k_inv_fdc_data_w - a LS240 inverts databus for FDC
//--------------------------------------------------------
-WRITE8_MEMBER( isa8_myb3k_fdc471x_device_base::myb3k_inv_fdc_data_w )
+void isa8_myb3k_fdc471x_device_base::myb3k_inv_fdc_data_w(offs_t offset, uint8_t data)
{
LOG("%s: %02x -> %02x\n", FUNCNAME, data, (~data) & 0xff);
m_fdc->write(offset, (~data) & 0xff);
@@ -247,7 +233,7 @@ WRITE8_MEMBER( isa8_myb3k_fdc471x_device_base::myb3k_inv_fdc_data_w )
// myb3k_fdc_command - descrete fdc card features
//-------------------------------------------------
-WRITE8_MEMBER( isa8_myb3k_fdc471x_device_base::myb3k_fdc_command )
+void isa8_myb3k_fdc471x_device_base::myb3k_fdc_command(uint8_t data)
{
LOG("%s: %02x\n", FUNCNAME, data);
@@ -282,10 +268,10 @@ WRITE8_MEMBER( isa8_myb3k_fdc471x_device_base::myb3k_fdc_command )
m_fdc->dden_w(dden ? 0 : 1); // active low == MFM
}
-WRITE8_MEMBER( isa8_myb3k_fdc4712_device::myb3k_fdc_command )
+void isa8_myb3k_fdc4712_device::myb3k_fdc_command(uint8_t data)
{
selected_drive = data & FDC_DRIVE_SEL;
- isa8_myb3k_fdc471x_device_base::myb3k_fdc_command(space, offset, data, mem_mask);
+ isa8_myb3k_fdc471x_device_base::myb3k_fdc_command(data);
}
//-------------------------------------------------
@@ -293,7 +279,7 @@ WRITE8_MEMBER( isa8_myb3k_fdc4712_device::myb3k_fdc_command )
//-------------------------------------------------
#define FDC_MSM_END_IR 0x01
-READ8_MEMBER( isa8_myb3k_fdc471x_device_base::myb3k_fdc_status )
+uint8_t isa8_myb3k_fdc471x_device_base::myb3k_fdc_status()
{
LOG("%s\n", FUNCNAME);
@@ -301,9 +287,9 @@ READ8_MEMBER( isa8_myb3k_fdc471x_device_base::myb3k_fdc_status )
return 0x00;
}
-READ8_MEMBER( isa8_myb3k_fdc4712_device::myb3k_fdc_status )
+uint8_t isa8_myb3k_fdc4712_device::myb3k_fdc_status()
{
- uint8_t status = isa8_myb3k_fdc471x_device_base::myb3k_fdc_status(space, offset, mem_mask);
+ uint8_t status = isa8_myb3k_fdc471x_device_base::myb3k_fdc_status();
auto floppy_connector = m_floppy_connectors[selected_drive];
floppy_image_device *floppy = nullptr;
diff --git a/src/devices/bus/isa/myb3k_fdc.h b/src/devices/bus/isa/myb3k_fdc.h
index ccec57c7468..30ed5ce88de 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,
@@ -23,23 +22,23 @@ protected:
isa8_myb3k_fdc471x_device_base(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock);
// device-level overrides
- virtual void device_add_mconfig(machine_config &config) override;
- virtual void device_start() override;
- virtual void device_reset() override { };
+ virtual void device_add_mconfig(machine_config &config) override ATTR_COLD;
+ virtual void device_start() override ATTR_COLD;
+ virtual void device_reset() override { }
- void map(address_map &map);
+ void map(address_map &map) ATTR_COLD;
virtual uint8_t dack_r(int line) override;
virtual void dack_w(int line, uint8_t data) override;
// virtual void eop_w(int state) override;
- virtual DECLARE_READ8_MEMBER(myb3k_inv_fdc_data_r);
- virtual DECLARE_WRITE8_MEMBER(myb3k_inv_fdc_data_w);
- virtual DECLARE_READ8_MEMBER(myb3k_fdc_status);
- virtual DECLARE_WRITE8_MEMBER(myb3k_fdc_command);
+ virtual uint8_t myb3k_inv_fdc_data_r(offs_t offset);
+ virtual void myb3k_inv_fdc_data_w(offs_t offset, uint8_t data);
+ 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;
@@ -74,10 +73,7 @@ protected:
isa8_myb3k_fdc4710_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock);
// device-level overrides
- virtual void device_add_mconfig(machine_config &config) override;
-
-private:
- DECLARE_FLOPPY_FORMATS( myb3k_floppy_formats );
+ virtual void device_add_mconfig(machine_config &config) override ATTR_COLD;
};
class isa8_myb3k_fdc4711_device : public isa8_myb3k_fdc471x_device_base
@@ -91,10 +87,7 @@ protected:
isa8_myb3k_fdc4711_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock);
// device-level overrides
- virtual void device_add_mconfig(machine_config &config) override;
-
-private:
- DECLARE_FLOPPY_FORMATS( myb3k_floppy_formats );
+ virtual void device_add_mconfig(machine_config &config) override ATTR_COLD;
};
class isa8_myb3k_fdc4712_device : public isa8_myb3k_fdc471x_device_base
@@ -108,15 +101,12 @@ protected:
isa8_myb3k_fdc4712_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock);
// device-level overrides
- virtual void device_add_mconfig(machine_config &config) override;
+ virtual void device_add_mconfig(machine_config &config) override ATTR_COLD;
- virtual DECLARE_WRITE8_MEMBER(myb3k_fdc_command) override;
- virtual DECLARE_READ8_MEMBER(myb3k_fdc_status) override;
+ virtual void myb3k_fdc_command(uint8_t data) override;
+ virtual uint8_t myb3k_fdc_status() override;
uint8_t selected_drive;
-
-private:
- DECLARE_FLOPPY_FORMATS( myb3k_floppy_formats );
};
// device type definition
diff --git a/src/devices/bus/isa/ne1000.cpp b/src/devices/bus/isa/ne1000.cpp
index 1eaef942105..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,31 +25,30 @@ 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);
set_isa_device();
- m_isa->install_device(0x0300, 0x031f, read8_delegate(FUNC(ne1000_device::ne1000_port_r), this), write8_delegate(FUNC(ne1000_device::ne1000_port_w), this));
+ m_isa->install_device(0x0300, 0x031f, read8sm_delegate(*this, FUNC(ne1000_device::ne1000_port_r)), write8sm_delegate(*this, FUNC(ne1000_device::ne1000_port_w)));
}
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;
}
-READ8_MEMBER(ne1000_device::ne1000_port_r) {
+uint8_t ne1000_device::ne1000_port_r(offs_t offset) {
if(offset < 16) {
- m_dp8390->dp8390_cs(CLEAR_LINE);
- return m_dp8390->dp8390_r(space, offset, mem_mask);
+ return m_dp8390->cs_read(offset);
}
switch(offset) {
case 16:
- m_dp8390->dp8390_cs(ASSERT_LINE);
- return m_dp8390->dp8390_r(space, offset, mem_mask);
+ return m_dp8390->remote_read();
case 31:
m_dp8390->dp8390_reset(CLEAR_LINE);
return 0;
@@ -57,16 +58,14 @@ READ8_MEMBER(ne1000_device::ne1000_port_r) {
return 0;
}
-WRITE8_MEMBER(ne1000_device::ne1000_port_w) {
+void ne1000_device::ne1000_port_w(offs_t offset, uint8_t data) {
if(offset < 16) {
- m_dp8390->dp8390_cs(CLEAR_LINE);
- m_dp8390->dp8390_w(space, offset, data, mem_mask);
+ m_dp8390->cs_write(offset, data);
return;
}
switch(offset) {
case 16:
- m_dp8390->dp8390_cs(ASSERT_LINE);
- m_dp8390->dp8390_w(space, offset, data, mem_mask);
+ m_dp8390->remote_write(data);
return;
case 31:
m_dp8390->dp8390_reset(ASSERT_LINE);
@@ -77,7 +76,7 @@ WRITE8_MEMBER(ne1000_device::ne1000_port_w) {
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);
@@ -94,7 +93,7 @@ WRITE_LINE_MEMBER(ne1000_device::ne1000_irq_w) {
}
}
-READ8_MEMBER(ne1000_device::ne1000_mem_read) {
+uint8_t ne1000_device::ne1000_mem_read(offs_t offset) {
offset &= ~0xc000; // verify
if(offset < 16) return m_prom[offset];
if((offset < (8*1024)) || (offset >= (16*1024))) {
@@ -104,7 +103,7 @@ READ8_MEMBER(ne1000_device::ne1000_mem_read) {
return m_board_ram[offset - (8*1024)];
}
-WRITE8_MEMBER(ne1000_device::ne1000_mem_write) {
+void ne1000_device::ne1000_mem_write(offs_t offset, uint8_t data) {
offset &= ~0xc000; // verify
if((offset < (8*1024)) || (offset >= (16*1024))) {
logerror("ne1000: invalid memory write %04X\n", offset);
diff --git a/src/devices/bus/isa/ne1000.h b/src/devices/bus/isa/ne1000.h
index a59e24374ed..b40b1220b96 100644
--- a/src/devices/bus/isa/ne1000.h
+++ b/src/devices/bus/isa/ne1000.h
@@ -16,20 +16,20 @@ class ne1000_device: public device_t,
public:
ne1000_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
- DECLARE_READ8_MEMBER(ne1000_port_r);
- DECLARE_WRITE8_MEMBER(ne1000_port_w);
+ uint8_t ne1000_port_r(offs_t offset);
+ void ne1000_port_w(offs_t offset, uint8_t data);
protected:
- virtual void device_start() override;
- virtual void device_reset() override;
+ virtual void device_start() override ATTR_COLD;
+ virtual void device_reset() override ATTR_COLD;
- virtual void device_add_mconfig(machine_config &config) override;
- virtual ioport_constructor device_input_ports() const override;
+ virtual void device_add_mconfig(machine_config &config) override ATTR_COLD;
+ virtual ioport_constructor device_input_ports() const override ATTR_COLD;
private:
void ne1000_irq_w(int state);
- DECLARE_READ8_MEMBER(ne1000_mem_read);
- DECLARE_WRITE8_MEMBER(ne1000_mem_write);
+ uint8_t ne1000_mem_read(offs_t offset);
+ void ne1000_mem_write(offs_t offset, uint8_t data);
required_device<dp8390d_device> m_dp8390;
uint8_t m_irq;
diff --git a/src/devices/bus/isa/ne2000.cpp b/src/devices/bus/isa/ne2000.cpp
index 3ad2cc592ef..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,34 +25,33 @@ 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);
set_isa_device();
- m_isa->install16_device(0x0300, 0x031f, read16_delegate(FUNC(ne2000_device::ne2000_port_r), this), write16_delegate(FUNC(ne2000_device::ne2000_port_w), this));
+ m_isa->install16_device(0x0300, 0x031f, read16s_delegate(*this, FUNC(ne2000_device::ne2000_port_r)), write16s_delegate(*this, FUNC(ne2000_device::ne2000_port_w)));
}
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;
}
-READ16_MEMBER(ne2000_device::ne2000_port_r) {
+uint16_t ne2000_device::ne2000_port_r(offs_t offset, uint16_t mem_mask) {
offset <<= 1;
if(offset < 16) {
- m_dp8390->dp8390_cs(CLEAR_LINE);
- return m_dp8390->dp8390_r(space, offset, 0xff) |
- m_dp8390->dp8390_r(space, offset+1, 0xff) << 8;
+ return m_dp8390->cs_read(offset) |
+ m_dp8390->cs_read(offset+1) << 8;
}
if(mem_mask == 0xff00) offset++;
switch(offset) {
case 16:
- m_dp8390->dp8390_cs(ASSERT_LINE);
- return m_dp8390->dp8390_r(space, offset, mem_mask);
+ return m_dp8390->remote_read();
case 31:
m_dp8390->dp8390_reset(CLEAR_LINE);
return 0;
@@ -60,23 +61,21 @@ READ16_MEMBER(ne2000_device::ne2000_port_r) {
return 0;
}
-WRITE16_MEMBER(ne2000_device::ne2000_port_w) {
+void ne2000_device::ne2000_port_w(offs_t offset, uint16_t data, uint16_t mem_mask) {
offset <<= 1;
if(offset < 16) {
- m_dp8390->dp8390_cs(CLEAR_LINE);
if(mem_mask == 0xff00) {
data >>= 8;
offset++;
}
- m_dp8390->dp8390_w(space, offset, data & 0xff, 0xff);
- if(mem_mask == 0xffff) m_dp8390->dp8390_w(space, offset+1, data>>8, 0xff);
+ m_dp8390->cs_write(offset, data & 0xff);
+ if(mem_mask == 0xffff) m_dp8390->cs_write(offset+1, data>>8);
return;
}
if(mem_mask == 0xff00) offset++;
switch(offset) {
case 16:
- m_dp8390->dp8390_cs(ASSERT_LINE);
- m_dp8390->dp8390_w(space, offset, data, mem_mask);
+ m_dp8390->remote_write(data);
return;
case 31:
m_dp8390->dp8390_reset(ASSERT_LINE);
@@ -87,7 +86,7 @@ WRITE16_MEMBER(ne2000_device::ne2000_port_w) {
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);
@@ -104,7 +103,7 @@ WRITE_LINE_MEMBER(ne2000_device::ne2000_irq_w) {
}
}
-READ8_MEMBER(ne2000_device::ne2000_mem_read) {
+uint8_t ne2000_device::ne2000_mem_read(offs_t offset) {
offset &= ~0x8000;
if(offset < 32) return m_prom[offset>>1];
if((offset < (16*1024)) || (offset >= (32*1024))) {
@@ -114,7 +113,7 @@ READ8_MEMBER(ne2000_device::ne2000_mem_read) {
return m_board_ram[offset - (16*1024)];
}
-WRITE8_MEMBER(ne2000_device::ne2000_mem_write) {
+void ne2000_device::ne2000_mem_write(offs_t offset, uint8_t data) {
offset &= ~0x8000;
if((offset < (16*1024)) || (offset >= (32*1024))) {
logerror("ne2000: invalid memory write %04X\n", offset);
diff --git a/src/devices/bus/isa/ne2000.h b/src/devices/bus/isa/ne2000.h
index 868d78b35a6..2d035c4072f 100644
--- a/src/devices/bus/isa/ne2000.h
+++ b/src/devices/bus/isa/ne2000.h
@@ -14,20 +14,20 @@ class ne2000_device: public device_t,
public:
ne2000_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
- DECLARE_READ16_MEMBER(ne2000_port_r);
- DECLARE_WRITE16_MEMBER(ne2000_port_w);
+ uint16_t ne2000_port_r(offs_t offset, uint16_t mem_mask = ~0);
+ void ne2000_port_w(offs_t offset, uint16_t data, uint16_t mem_mask = ~0);
protected:
- virtual void device_start() override;
- virtual void device_reset() override;
+ virtual void device_start() override ATTR_COLD;
+ virtual void device_reset() override ATTR_COLD;
- virtual void device_add_mconfig(machine_config &config) override;
- virtual ioport_constructor device_input_ports() const override;
+ virtual void device_add_mconfig(machine_config &config) override ATTR_COLD;
+ virtual ioport_constructor device_input_ports() const override ATTR_COLD;
private:
void ne2000_irq_w(int state);
- DECLARE_READ8_MEMBER(ne2000_mem_read);
- DECLARE_WRITE8_MEMBER(ne2000_mem_write);
+ uint8_t ne2000_mem_read(offs_t offset);
+ void ne2000_mem_write(offs_t offset, uint8_t data);
required_device<dp8390d_device> m_dp8390;
uint8_t m_irq;
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..b4f50a35eee 100644
--- a/src/devices/bus/isa/np600.h
+++ b/src/devices/bus/isa/np600.h
@@ -22,21 +22,24 @@ public:
static constexpr feature_type unemulated_features() { return feature::LAN; }
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 device_start() override ATTR_COLD;
+ virtual void device_add_mconfig(machine_config &config) override ATTR_COLD;
+ virtual const tiny_rom_entry *device_rom_region() const override ATTR_COLD;
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);
- void lcc_map(address_map &map);
+ void mem_map(address_map &map) ATTR_COLD;
+ void io_map(address_map &map) ATTR_COLD;
+ void lcc_map(address_map &map) ATTR_COLD;
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/num9rev.cpp b/src/devices/bus/isa/num9rev.cpp
index ebe44a379f4..c7756b8294b 100644
--- a/src/devices/bus/isa/num9rev.cpp
+++ b/src/devices/bus/isa/num9rev.cpp
@@ -26,25 +26,25 @@ UPD7220_DISPLAY_PIXELS_MEMBER( isa8_number_9_rev_device::hgdc_display_pixels )
{
rgb_t color(0);
uint16_t overlay;
- if(((address << 3) + 0xc0016) > (1024*1024))
+ if(((address << 4) + 0xc0016) > (1024*1024))
return;
for(int i = 0; i < 16; i++)
{
- uint32_t addr = (address << 3) + i;
+ uint32_t addr = (address << 4) + i;
overlay = m_ram[addr + 0xc0000] << 1;
overlay = m_overlay[overlay + ((m_mode & 8) ? 512 : 0)] | (m_overlay[overlay + 1 + ((m_mode & 8) ? 512 : 0)] << 8);
color.set_r(pal->entry_color(m_ram[addr] | ((overlay & 0xf) << 8)).r());
color.set_g(pal->entry_color(m_ram[addr + 0x40000] | ((overlay & 0xf0) << 4)).g());
color.set_b(pal->entry_color(m_ram[addr + 0x80000] | (overlay & 0xf00)).b());
- bitmap.pix32(y, x + i) = color;
+ bitmap.pix(y, x + i) = color;
}
}
else
{
- if(((address << 3) + 16) > (1024*1024))
+ if(((address << 4) + 16) > (1024*1024))
return;
for(int i = 0; i < 16; i++)
- bitmap.pix32(y, x + i) = pal->entry_color(m_ram[(address << 4) + i]);
+ bitmap.pix(y, x + i) = pal->entry_color(m_ram[(address << 4) + i]);
}
}
@@ -94,13 +94,13 @@ void isa8_number_9_rev_device::device_start()
{
set_isa_device();
- m_isa->install_memory(0xc0000, 0xc0001, read8sm_delegate(FUNC(upd7220_device::read), (upd7220_device *)m_upd7220), write8sm_delegate(FUNC(upd7220_device::write), (upd7220_device *)m_upd7220));
- m_isa->install_memory(0xc0100, 0xc03ff, read8_delegate(FUNC(isa8_number_9_rev_device::pal8_r), this), write8_delegate(FUNC(isa8_number_9_rev_device::pal8_w), this));
- m_isa->install_memory(0xc0400, 0xc0401, read8_delegate(FUNC(isa8_number_9_rev_device::bank_r), this), write8_delegate(FUNC(isa8_number_9_rev_device::bank_w), this));
- m_isa->install_memory(0xc0500, 0xc06ff, read8_delegate(FUNC(isa8_number_9_rev_device::overlay_r), this), write8_delegate(FUNC(isa8_number_9_rev_device::overlay_w), this));
- m_isa->install_memory(0xc0700, 0xc070f, read8_delegate(FUNC(isa8_number_9_rev_device::ctrl_r), this), write8_delegate(FUNC(isa8_number_9_rev_device::ctrl_w), this));
- m_isa->install_memory(0xc1000, 0xc3fff, read8_delegate(FUNC(isa8_number_9_rev_device::pal12_r), this), write8_delegate(FUNC(isa8_number_9_rev_device::pal12_w), this));
- m_isa->install_memory(0xa0000, 0xaffff, read8_delegate(FUNC(isa8_number_9_rev_device::read8), this), write8_delegate(FUNC(isa8_number_9_rev_device::write8), this));
+ m_isa->install_memory(0xc0000, 0xc0001, read8sm_delegate(*m_upd7220, FUNC(upd7220_device::read)), write8sm_delegate(*m_upd7220, FUNC(upd7220_device::write)));
+ m_isa->install_memory(0xc0100, 0xc03ff, read8sm_delegate(*this, FUNC(isa8_number_9_rev_device::pal8_r)), write8sm_delegate(*this, FUNC(isa8_number_9_rev_device::pal8_w)));
+ m_isa->install_memory(0xc0400, 0xc0401, read8smo_delegate(*this, FUNC(isa8_number_9_rev_device::bank_r)), write8smo_delegate(*this, FUNC(isa8_number_9_rev_device::bank_w)));
+ m_isa->install_memory(0xc0500, 0xc06ff, read8sm_delegate(*this, FUNC(isa8_number_9_rev_device::overlay_r)), write8sm_delegate(*this, FUNC(isa8_number_9_rev_device::overlay_w)));
+ m_isa->install_memory(0xc0700, 0xc070f, read8sm_delegate(*this, FUNC(isa8_number_9_rev_device::ctrl_r)), write8sm_delegate(*this, FUNC(isa8_number_9_rev_device::ctrl_w)));
+ m_isa->install_memory(0xc1000, 0xc3fff, read8sm_delegate(*this, FUNC(isa8_number_9_rev_device::pal12_r)), write8sm_delegate(*this, FUNC(isa8_number_9_rev_device::pal12_w)));
+ m_isa->install_memory(0xa0000, 0xaffff, read8sm_delegate(*this, FUNC(isa8_number_9_rev_device::read8)), write8sm_delegate(*this, FUNC(isa8_number_9_rev_device::write8)));
}
//-------------------------------------------------
@@ -114,7 +114,7 @@ void isa8_number_9_rev_device::device_reset()
m_1024 = false;
}
-READ8_MEMBER(isa8_number_9_rev_device::read8)
+uint8_t isa8_number_9_rev_device::read8(offs_t offset)
{
if((m_mode & 1) && !m_1024)
return m_ram[offset + ((m_mode & 0xc) << 14)];
@@ -127,7 +127,7 @@ READ8_MEMBER(isa8_number_9_rev_device::read8)
return m_ram[offset + (m_bank << 16)];
}
-WRITE8_MEMBER(isa8_number_9_rev_device::write8)
+void isa8_number_9_rev_device::write8(offs_t offset, uint8_t data)
{
if(m_1024 || ((m_mode & 6) == 0))
m_ram[offset + (m_bank << 16)] = data;
@@ -159,7 +159,7 @@ WRITE8_MEMBER(isa8_number_9_rev_device::write8)
}
}
-READ8_MEMBER(isa8_number_9_rev_device::pal8_r)
+uint8_t isa8_number_9_rev_device::pal8_r(offs_t offset)
{
offset += 0x100;
palette_t *pal = m_palette->palette();
@@ -175,7 +175,7 @@ READ8_MEMBER(isa8_number_9_rev_device::pal8_r)
return 0;
}
-WRITE8_MEMBER(isa8_number_9_rev_device::pal8_w)
+void isa8_number_9_rev_device::pal8_w(offs_t offset, uint8_t data)
{
offset += 0x100;
palette_t *pal = m_palette->palette();
@@ -195,7 +195,7 @@ WRITE8_MEMBER(isa8_number_9_rev_device::pal8_w)
pal->entry_set_color(offset, pen);
}
-READ8_MEMBER(isa8_number_9_rev_device::pal12_r)
+uint8_t isa8_number_9_rev_device::pal12_r(offs_t offset)
{
uint16_t color = offset & 0xfff;
palette_t *pal = m_palette->palette();
@@ -211,7 +211,7 @@ READ8_MEMBER(isa8_number_9_rev_device::pal12_r)
return 0;
}
-WRITE8_MEMBER(isa8_number_9_rev_device::pal12_w)
+void isa8_number_9_rev_device::pal12_w(offs_t offset, uint8_t data)
{
uint16_t color = offset & 0xfff;
palette_t *pal = m_palette->palette();
@@ -231,26 +231,26 @@ WRITE8_MEMBER(isa8_number_9_rev_device::pal12_w)
pal->entry_set_color(color, pen);
}
-READ8_MEMBER(isa8_number_9_rev_device::overlay_r)
+uint8_t isa8_number_9_rev_device::overlay_r(offs_t offset)
{
return m_overlay[offset + ((m_mode & 8) ? 512 : 0)];
}
-WRITE8_MEMBER(isa8_number_9_rev_device::overlay_w)
+void isa8_number_9_rev_device::overlay_w(offs_t offset, uint8_t data)
{
m_overlay[offset + ((m_mode & 8) ? 512 : 0)] = data;
}
-READ8_MEMBER(isa8_number_9_rev_device::bank_r)
+uint8_t isa8_number_9_rev_device::bank_r()
{
return m_bank;
}
-WRITE8_MEMBER(isa8_number_9_rev_device::bank_w)
+void isa8_number_9_rev_device::bank_w(uint8_t data)
{
m_bank = data & 0xf;
}
-READ8_MEMBER(isa8_number_9_rev_device::ctrl_r)
+uint8_t isa8_number_9_rev_device::ctrl_r(offs_t offset)
{
switch(offset & 0xf)
{
@@ -272,7 +272,7 @@ READ8_MEMBER(isa8_number_9_rev_device::ctrl_r)
return 0;
}
-WRITE8_MEMBER(isa8_number_9_rev_device::ctrl_w)
+void isa8_number_9_rev_device::ctrl_w(offs_t offset, uint8_t data)
{
switch(offset & 0xf)
{
diff --git a/src/devices/bus/isa/num9rev.h b/src/devices/bus/isa/num9rev.h
index 1e176f121f4..edfc0a977f2 100644
--- a/src/devices/bus/isa/num9rev.h
+++ b/src/devices/bus/isa/num9rev.h
@@ -26,31 +26,31 @@ public:
protected:
// device-level overrides
- virtual void device_start() override;
- virtual void device_reset() override;
+ virtual void device_start() override ATTR_COLD;
+ virtual void device_reset() override ATTR_COLD;
// optional information overrides
- virtual void device_add_mconfig(machine_config &config) override;
+ virtual void device_add_mconfig(machine_config &config) override ATTR_COLD;
private:
UPD7220_DISPLAY_PIXELS_MEMBER(hgdc_display_pixels);
uint32_t screen_update(screen_device &screen, bitmap_rgb32 &bitmap, const rectangle &cliprect);
- DECLARE_READ8_MEMBER(pal8_r);
- DECLARE_WRITE8_MEMBER(pal8_w);
- DECLARE_READ8_MEMBER(pal12_r);
- DECLARE_WRITE8_MEMBER(pal12_w);
- DECLARE_READ8_MEMBER(overlay_r);
- DECLARE_WRITE8_MEMBER(overlay_w);
- DECLARE_READ8_MEMBER(bank_r);
- DECLARE_WRITE8_MEMBER(bank_w);
- DECLARE_READ8_MEMBER(ctrl_r);
- DECLARE_WRITE8_MEMBER(ctrl_w);
- DECLARE_READ8_MEMBER(read8);
- DECLARE_WRITE8_MEMBER(write8);
+ uint8_t pal8_r(offs_t offset);
+ void pal8_w(offs_t offset, uint8_t data);
+ uint8_t pal12_r(offs_t offset);
+ void pal12_w(offs_t offset, uint8_t data);
+ uint8_t overlay_r(offs_t offset);
+ void overlay_w(offs_t offset, uint8_t data);
+ uint8_t bank_r();
+ void bank_w(uint8_t data);
+ uint8_t ctrl_r(offs_t offset);
+ void ctrl_w(offs_t offset, uint8_t data);
+ uint8_t read8(offs_t offset);
+ void write8(offs_t offset, uint8_t data);
- void upd7220_map(address_map &map);
+ void upd7220_map(address_map &map) ATTR_COLD;
required_device<upd7220_device> m_upd7220;
required_device<palette_device> m_palette;
diff --git a/src/devices/bus/isa/omti8621.cpp b/src/devices/bus/isa/omti8621.cpp
index bea87f420ee..3c88e65442e 100644
--- a/src/devices/bus/isa/omti8621.cpp
+++ b/src/devices/bus/isa/omti8621.cpp
@@ -15,18 +15,17 @@
#include "emu.h"
#include "omti8621.h"
#include "image.h"
-#include "formats/pc_dsk.h"
+#include "imagedev/harddriv.h"
#include "formats/naslite_dsk.h"
#include "formats/apollo_dsk.h"
-#define VERBOSE 0
+#define LOG_LEVEL0 (0x1U << 1)
+#define LOG_LEVEL1 (0x3U << 1)
+#define LOG_LEVEL2 (0x7U << 1)
+#define LOG_LEVEL3 (0xfU << 1)
-static int verbose = VERBOSE;
-
-#define LOG(x) { logerror ("%s: ", cpu_context()); logerror x; logerror ("\n"); }
-#define LOG1(x) { if (verbose > 0) LOG(x)}
-#define LOG2(x) { if (verbose > 1) LOG(x)}
-#define LOG3(x) { if (verbose > 2) LOG(x)}
+#define VERBOSE (LOG_LEVEL0)
+#include "logmacro.h"
#define OMTI_DISK_SECTOR_SIZE 1056
@@ -47,31 +46,24 @@ static int verbose = VERBOSE;
// forward declaration of image class
DECLARE_DEVICE_TYPE(OMTI_DISK, omti_disk_image_device)
-class omti_disk_image_device : public device_t,
- public device_image_interface
+class omti_disk_image_device : public harddisk_image_base_device
{
public:
// construction/destruction
omti_disk_image_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
- // image-level overrides
- virtual iodevice_t image_type() const override { return IO_HARDDISK; }
+ // 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 bool is_readable() const override { return 1; }
- virtual bool is_writeable() const override { return 1; }
- virtual bool is_creatable() const override { return 1; }
- virtual bool must_be_loaded() const override { return 0; }
- virtual bool is_reset_on_load() const override { return 0; }
- virtual bool support_command_line_image_creation() const override { return 1; }
- virtual const char *file_extensions() const override { return "awd"; }
- virtual const char *custom_instance_name() const override { return "winchester"; }
- virtual const char *custom_brief_instance_name() const override { return "disk"; }
+ virtual std::pair<std::error_condition, std::string> call_create(int format_type, util::option_resolution *format_options) override;
- virtual image_init_result call_create(int format_type, util::option_resolution *format_options) override;
protected:
- // device-level overrides
- virtual void device_start() override;
- virtual void device_reset() override;
+ // device_t implementation
+ virtual void device_start() override ATTR_COLD;
+ virtual void device_reset() override ATTR_COLD;
void omti_disk_config(uint16_t disk_type);
@@ -111,7 +103,7 @@ public:
#define OMTI_STATUS_REQ 0x01 // Request (1 = request transfer of data via data in/out register)
#define OMTI_STATUS_IO 0x02 // In/Out (1 = direction of transfer is from controller to host)
-#define OMTI_STATUS_CD 0x04 // Command/Data ( 1 = byte transferred is command or status byte)
+#define OMTI_STATUS_CD 0x04 // Command/Data (1 = byte transferred is command or status byte)
#define OMTI_STATUS_BUSY 0x08 // Busy (0 = controller is idle, 1 = controller selected)
#define OMTI_STATUS_DREQ 0x10 // Data Request (0 = no DMA request, 1 = DMA cycle requested)
#define OMTI_STATUS_IREQ 0x20 // Interrupt Request (0 = no interrupt, 1 = command complete)
@@ -203,11 +195,12 @@ static void pc_hd_floppies(device_slot_interface &device)
device.option_add("35dd", FLOPPY_35_DD);
}
-FLOPPY_FORMATS_MEMBER( omti8621_device::floppy_formats )
- FLOPPY_APOLLO_FORMAT,
- FLOPPY_PC_FORMAT,
- FLOPPY_NASLITE_FORMAT
-FLOPPY_FORMATS_END
+void omti8621_device::floppy_formats(format_registration &fr)
+{
+ fr.add_pc_formats();
+ fr.add(FLOPPY_APOLLO_FORMAT);
+ fr.add(FLOPPY_NASLITE_FORMAT);
+}
// this card has two EPROMs: a program for the on-board Z8 CPU,
// and a PC BIOS to make the card bootable on a PC.
@@ -248,12 +241,19 @@ void omti8621_device::device_add_mconfig(machine_config &config)
OMTI_DISK(config, OMTI_DISK0_TAG, 0);
OMTI_DISK(config, OMTI_DISK1_TAG, 0);
- pc_fdc_at_device &pc_fdc_at(PC_FDC_AT(config, m_fdc, 0));
- pc_fdc_at.intrq_wr_callback().set(FUNC(omti8621_device::fdc_irq_w));
- pc_fdc_at.drq_wr_callback().set(FUNC(omti8621_device::fdc_drq_w));
- FLOPPY_CONNECTOR(config, OMTI_FDC_TAG":0", pc_hd_floppies, "525hd", omti8621_device::floppy_formats);
-// Apollo workstations never have more then 1 floppy drive
-// FLOPPY_CONNECTOR(config, OMTI_FDC_TAG":1", pc_hd_floppies, "525hd", omti8621_device::floppy_formats);
+ UPD765A(config, m_fdc, 48_MHz_XTAL / 6, false, false); // clocked through FDC9239BT
+ m_fdc->intrq_wr_callback().set(FUNC(omti8621_device::fdc_irq_w));
+ m_fdc->drq_wr_callback().set(FUNC(omti8621_device::fdc_drq_w));
+ FLOPPY_CONNECTOR(config, m_floppy[0], pc_hd_floppies, "525hd", omti8621_device::floppy_formats);
+ FLOPPY_CONNECTOR(config, m_floppy[1], pc_hd_floppies, nullptr, omti8621_device::floppy_formats);
+}
+
+void omti8621_apollo_device::device_add_mconfig(machine_config &config)
+{
+ omti8621_device::device_add_mconfig(config);
+
+ // Apollo workstations never have more then 1 floppy drive
+ config.device_remove(OMTI_FDC_TAG":1");
}
const tiny_rom_entry *omti8621_device::device_rom_region() const
@@ -279,15 +279,15 @@ ioport_constructor omti8621_device::device_input_ports() const
void omti8621_device::device_start()
{
- LOG2(("device_start"));
+ LOGMASKED(LOG_LEVEL2, "device_start");
set_isa_device();
m_installed = false;
- sector_buffer.resize(OMTI_DISK_SECTOR_SIZE*OMTI_MAX_BLOCK_COUNT);
+ m_sector_buffer.resize(OMTI_DISK_SECTOR_SIZE*OMTI_MAX_BLOCK_COUNT);
- m_timer = timer_alloc(0, nullptr);
+ m_timer = timer_alloc(FUNC(omti8621_device::trigger_interrupt), this);
our_disks[0] = subdevice<omti_disk_image_device>(OMTI_DISK0_TAG);
our_disks[1] = subdevice<omti_disk_image_device>(OMTI_DISK1_TAG);
@@ -301,7 +301,7 @@ void omti8621_device::device_reset()
{
static const int io_bases[8] = { 0x320, 0x324, 0x328, 0x32c, 0x1a0, 0x1a4, 0x1a8, 0x1ac };
- LOG2(("device_reset"));
+ LOGMASKED(LOG_LEVEL2, "device_reset");
// you can't read I/O ports in device_start() even if they're required_ioport<> in your class!
if (!m_installed)
@@ -309,16 +309,16 @@ void omti8621_device::device_reset()
int esdi_base = io_bases[m_iobase->read() & 7];
// install the ESDI ports
- m_isa->install16_device(esdi_base, esdi_base + 7, read16_delegate(FUNC(omti8621_device::read), this), write16_delegate(FUNC(omti8621_device::write), this));
+ m_isa->install16_device(esdi_base, esdi_base + 7, read16s_delegate(*this, FUNC(omti8621_device::read)), write16s_delegate(*this, FUNC(omti8621_device::write)));
// and the onboard AT FDC ports
if (m_iobase->read() & 8)
{
- m_isa->install_device(0x0370, 0x0377, *m_fdc, &pc_fdc_interface::map);
+ m_isa->install_device(0x0370, 0x0377, *this, &omti8621_device::fdc_map);
}
else
{
- m_isa->install_device(0x03f0, 0x03f7, *m_fdc, &pc_fdc_interface::map);
+ m_isa->install_device(0x03f0, 0x03f7, *this, &omti8621_device::fdc_map);
}
m_isa->set_dma_channel(2, this, true);
@@ -329,38 +329,42 @@ void omti8621_device::device_reset()
set_jumper(our_disks[0]->m_type);
// should go from reset to idle after 100 us
- // state->omti_state = OMTI_STATE_RESET;
- omti_state = OMTI_STATE_IDLE;
+ // m_omti_state = OMTI_STATE_RESET;
+ m_omti_state = OMTI_STATE_IDLE;
- status_port = OMTI_STATUS_NU6 | OMTI_STATUS_NU7;
- config_port = ~jumper;
- mask_port = 0;
+ m_status_port = OMTI_STATUS_NU6 | OMTI_STATUS_NU7;
+ m_config_port = ~m_jumper;
+ m_mask_port = 0;
// default the sector data buffer with model and status information
// (i.e. set sector data buffer for cmd=0x0e READ SECTOR BUFFER)
- memset(&sector_buffer[0], 0, OMTI_DISK_SECTOR_SIZE);
- memcpy(&sector_buffer[0], "8621VB.4060487xx", 0x10);
- sector_buffer[0x10] = 0; // ROM Checksum error
- sector_buffer[0x11] = 0; // Processor Register error
- sector_buffer[0x12] = 0; // Buffer RAM error
- sector_buffer[0x13] = 0; // Sequencer Register File error
- sector_buffer[0x14] = 0xc0; // 32K buffer size
+ memset(&m_sector_buffer[0], 0, OMTI_DISK_SECTOR_SIZE);
+ memcpy(&m_sector_buffer[0], "8621VB.4060487xx", 0x10);
+ m_sector_buffer[0x10] = 0; // ROM Checksum error
+ m_sector_buffer[0x11] = 0; // Processor Register error
+ m_sector_buffer[0x12] = 0; // Buffer RAM error
+ m_sector_buffer[0x13] = 0; // Sequencer Register File error
+ m_sector_buffer[0x14] = 0xc0; // 32K buffer size
// TODO: add missing Default values for LUN 0, 1 and 3
- command_length = 0;
- command_index = 0;
- command_status = 0;
+ m_command_length = 0;
+ m_command_index = 0;
+ m_command_status = 0;
- data_index = 0;
- data_length = 0;
+ m_data_index = 0;
+ m_data_length = 0;
clear_sense_data();
- diskaddr_ecc_error = 0;
- diskaddr_format_bad_track = 0;
- alternate_track_address[0] = 0;
- alternate_track_address[1] = 0;
+ m_diskaddr_ecc_error = 0;
+ m_diskaddr_format_bad_track = 0;
+ m_alternate_track_address[0] = 0;
+ m_alternate_track_address[1] = 0;
+
+ fd_moten_w(0);
+ fd_rate_w(0);
+ fd_extra_w(0);
}
DEFINE_DEVICE_TYPE(ISA16_OMTI8621, omti8621_pc_device, "omti8621isa", "OMTI 8621 ESDI/floppy controller (ISA)")
@@ -386,10 +390,25 @@ omti8621_device::omti8621_device(
: device_t(mconfig, type, tag, owner, clock)
, device_isa16_card_interface(mconfig, *this)
, m_fdc(*this, OMTI_FDC_TAG)
+ , m_floppy(*this, OMTI_FDC_TAG":%u", 0U)
, m_iobase(*this, "IO_BASE")
, m_biosopts(*this, "BIOS_OPTS")
- , jumper(0), omti_state(0), status_port(0), config_port(0), mask_port(0), command_length(0), command_index(0), command_status(0), data_buffer(nullptr)
- , data_length(0), data_index(0), diskaddr_ecc_error(0), diskaddr_format_bad_track(0), m_timer(nullptr), m_installed(false)
+ , m_jumper(0)
+ , m_omti_state(0)
+ , m_status_port(0)
+ , m_config_port(0)
+ , m_mask_port(0)
+ , m_command_length(0)
+ , m_command_index(0)
+ , m_command_status(0)
+ , m_data_buffer(nullptr)
+ , m_data_length(0)
+ , m_data_index(0)
+ , m_diskaddr_ecc_error(0)
+ , m_diskaddr_format_bad_track(0)
+ , m_timer(nullptr)
+ , m_moten(0)
+ , m_installed(false)
{
}
@@ -397,13 +416,13 @@ omti8621_device::omti8621_device(
set_interrupt - update the IRQ state
-------------------------------------------------*/
-void omti8621_device::set_interrupt(enum line_state line_state)
+void omti8621_device::set_interrupt(line_state state)
{
- LOG2(("set_interrupt: status_port=%x, line_state %d", status_port, line_state));
- m_isa->irq14_w(line_state);
+ LOGMASKED(LOG_LEVEL2, "%s: set_interrupt: status_port=%x, line_state %d", cpu_context(), m_status_port, state);
+ m_isa->irq14_w(state);
}
-void omti8621_device::device_timer(emu_timer &timer, device_timer_id id, int param, void *ptr)
+TIMER_CALLBACK_MEMBER(omti8621_device::trigger_interrupt)
{
set_interrupt(ASSERT_LINE);
}
@@ -413,8 +432,8 @@ void omti8621_device::device_timer(emu_timer &timer, device_timer_id id, int par
***************************************************************************/
void omti8621_device::clear_sense_data() {
- LOG2(("clear_sense_data"));
- memset(sense_data, 0, sizeof(sense_data));
+ LOGMASKED(LOG_LEVEL2, "%s: clear_sense_data", cpu_context());
+ std::fill_n(m_sense_data, std::size(m_sense_data), 0);
}
/***************************************************************************
@@ -422,11 +441,11 @@ void omti8621_device::clear_sense_data() {
***************************************************************************/
void omti8621_device::set_sense_data(uint8_t code, const uint8_t * cdb) {
- LOG2(("set_sense_data code=%x", code));
- sense_data[0]=code;
- sense_data[1]=cdb[1];
- sense_data[2]=cdb[2];
- sense_data[3]=cdb[3];
+ LOGMASKED(LOG_LEVEL2, "%s: set_sense_data code=%x", cpu_context(), code);
+ m_sense_data[0] = code;
+ m_sense_data[1] = cdb[1];
+ m_sense_data[2] = cdb[2];
+ m_sense_data[3] = cdb[3];
}
/***************************************************************************
@@ -434,7 +453,7 @@ void omti8621_device::set_sense_data(uint8_t code, const uint8_t * cdb) {
***************************************************************************/
void omti8621_device::set_configuration_data(uint8_t lun) {
- LOG2(("set_configuration_data lun=%x", lun));
+ LOGMASKED(LOG_LEVEL2, "%s: set_configuration_data lun=%x", cpu_context(), lun);
// initialize the configuration data
omti_disk_image_device *disk = our_disks[lun];
@@ -478,7 +497,7 @@ uint8_t omti8621_device::check_disk_address(const uint8_t *cdb)
uint32_t disk_addr = (disk_track * disk->m_sectors) + sector;
if (block_count > OMTI_MAX_BLOCK_COUNT) {
- LOG(("########### check_disk_address: unexpected block count %x", block_count));
+ LOGMASKED(LOG_LEVEL0, "%s: ########### check_disk_address: unexpected block count %x", cpu_context(), block_count);
sense_code = OMTI_SENSE_CODE_ILLEGAL_ADDRESS | OMTI_SENSE_CODE_ADDRESS_VALID;
}
@@ -492,18 +511,18 @@ uint8_t omti8621_device::check_disk_address(const uint8_t *cdb)
sense_code = OMTI_SENSE_CODE_ILLEGAL_ADDRESS | OMTI_SENSE_CODE_ADDRESS_VALID;
} else if (cylinder >= disk->m_cylinders) {
sense_code = OMTI_SENSE_CODE_ILLEGAL_ADDRESS | OMTI_SENSE_CODE_ADDRESS_VALID;
- } else if ( disk_track == diskaddr_format_bad_track && disk_track != 0) {
+ } else if (disk_track == m_diskaddr_format_bad_track && disk_track != 0) {
sense_code = OMTI_SENSE_CODE_BAD_TRACK;
- } else if (disk_addr == diskaddr_ecc_error && disk_addr != 0) {
+ } else if (disk_addr == m_diskaddr_ecc_error && disk_addr != 0) {
sense_code = OMTI_SENSE_CODE_ECC_ERROR;
- } else if (disk_track == alternate_track_address[1] && disk_track != 0) {
+ } else if (disk_track == m_alternate_track_address[1] && disk_track != 0) {
sense_code = OMTI_SENSE_CODE_ALTERNATE_TRACK;
}
if (sense_code == OMTI_SENSE_CODE_NO_ERROR) {
clear_sense_data();
} else {
- command_status |= OMTI_COMMAND_STATUS_ERROR;
+ m_command_status |= OMTI_COMMAND_STATUS_ERROR;
set_sense_data(sense_code, cdb);
}
return sense_code == OMTI_SENSE_CODE_NO_ERROR;
@@ -537,29 +556,29 @@ uint32_t omti8621_device::get_disk_address(const uint8_t * cdb) {
void omti8621_device::set_data_transfer(uint8_t *data, uint16_t length)
{
// set controller for read data transfer
- omti_state = OMTI_STATE_DATA;
- status_port |= OMTI_STATUS_REQ | OMTI_STATUS_IO | OMTI_STATUS_BUSY;
- status_port &= ~OMTI_STATUS_CD;
+ m_omti_state = OMTI_STATE_DATA;
+ m_status_port |= OMTI_STATUS_REQ | OMTI_STATUS_IO | OMTI_STATUS_BUSY;
+ m_status_port &= ~OMTI_STATUS_CD;
- data_buffer = data;
- data_length = length;
- data_index = 0;
+ m_data_buffer = data;
+ m_data_length = length;
+ m_data_index = 0;
}
/***************************************************************************
- read_sectors_from_disk - read sectors starting at diskaddr into sector_buffer
+ read_sectors_from_disk - read sectors starting at diskaddr into m_sector_buffer
***************************************************************************/
void omti8621_device::read_sectors_from_disk(int32_t diskaddr, uint8_t count, uint8_t lun)
{
- uint8_t *data_buffer = &sector_buffer[0];
+ uint8_t *data_buffer = &m_sector_buffer[0];
device_image_interface *image = our_disks[lun]->m_image;
while (count-- > 0) {
- LOG2(("read_sectors_from_disk lun=%d diskaddr=%x", lun, diskaddr));
+ LOGMASKED(LOG_LEVEL2, "%s: read_sectors_from_disk lun=%d diskaddr=%x", cpu_context(), lun, diskaddr);
- image->fseek( diskaddr * OMTI_DISK_SECTOR_SIZE, SEEK_SET);
- image->fread( data_buffer, OMTI_DISK_SECTOR_SIZE);
+ image->fseek(diskaddr * OMTI_DISK_SECTOR_SIZE, SEEK_SET);
+ image->fread(data_buffer, OMTI_DISK_SECTOR_SIZE);
diskaddr++;
data_buffer += OMTI_DISK_SECTOR_SIZE;
@@ -567,23 +586,23 @@ void omti8621_device::read_sectors_from_disk(int32_t diskaddr, uint8_t count, ui
}
/***************************************************************************
- write_sectors_to_disk - write sectors starting at diskaddr from sector_buffer
+ write_sectors_to_disk - write sectors starting at diskaddr from m_sector_buffer
***************************************************************************/
void omti8621_device::write_sectors_to_disk(int32_t diskaddr, uint8_t count, uint8_t lun)
{
- uint8_t *data_buffer = &sector_buffer[0];
+ uint8_t *data_buffer = &m_sector_buffer[0];
device_image_interface *image = our_disks[lun]->m_image;
while (count-- > 0) {
- LOG2(("write_sectors_to_disk lun=%d diskaddr=%x", lun, diskaddr));
+ LOGMASKED(LOG_LEVEL2, "%s: write_sectors_to_disk lun=%d diskaddr=%x", cpu_context(), lun, diskaddr);
- image->fseek( diskaddr * OMTI_DISK_SECTOR_SIZE, SEEK_SET);
- image->fwrite( data_buffer, OMTI_DISK_SECTOR_SIZE);
+ image->fseek(diskaddr * OMTI_DISK_SECTOR_SIZE, SEEK_SET);
+ image->fwrite(data_buffer, OMTI_DISK_SECTOR_SIZE);
- if (diskaddr == diskaddr_ecc_error) {
+ if (diskaddr == m_diskaddr_ecc_error) {
// reset previous ECC error
- diskaddr_ecc_error = 0;
+ m_diskaddr_ecc_error = 0;
}
diskaddr++;
@@ -599,18 +618,18 @@ void omti8621_device::copy_sectors(int32_t dst_addr, int32_t src_addr, uint8_t c
{
device_image_interface *image = our_disks[lun]->m_image;
- LOG2(("copy_sectors lun=%d src_addr=%x dst_addr=%x count=%x", lun, src_addr, dst_addr, count));
+ LOGMASKED(LOG_LEVEL2, "%s: copy_sectors lun=%d src_addr=%x dst_addr=%x count=%x", cpu_context(), lun, src_addr, dst_addr, count);
while (count-- > 0) {
- image->fseek( src_addr * OMTI_DISK_SECTOR_SIZE, SEEK_SET);
- image->fread( &sector_buffer[0], OMTI_DISK_SECTOR_SIZE);
+ image->fseek(src_addr * OMTI_DISK_SECTOR_SIZE, SEEK_SET);
+ image->fread(&m_sector_buffer[0], OMTI_DISK_SECTOR_SIZE);
- image->fseek( dst_addr * OMTI_DISK_SECTOR_SIZE, SEEK_SET);
- image->fwrite( &sector_buffer[0], OMTI_DISK_SECTOR_SIZE);
+ image->fseek(dst_addr * OMTI_DISK_SECTOR_SIZE, SEEK_SET);
+ image->fwrite(&m_sector_buffer[0], OMTI_DISK_SECTOR_SIZE);
- if (dst_addr == diskaddr_ecc_error) {
+ if (dst_addr == m_diskaddr_ecc_error) {
// reset previous ECC error
- diskaddr_ecc_error = 0;
+ m_diskaddr_ecc_error = 0;
}
src_addr++;
@@ -628,29 +647,29 @@ void omti8621_device::format_track(const uint8_t * cdb)
uint32_t disk_addr = get_disk_address(cdb);
uint32_t disk_track = get_disk_track(cdb);
- if (diskaddr_ecc_error == disk_addr) {
+ if (m_diskaddr_ecc_error == disk_addr) {
// reset previous ECC error
- diskaddr_ecc_error = 0;
+ m_diskaddr_ecc_error = 0;
}
- if (diskaddr_format_bad_track == disk_track) {
+ if (m_diskaddr_format_bad_track == disk_track) {
// reset previous bad track formatting
- diskaddr_format_bad_track = 0;
+ m_diskaddr_format_bad_track = 0;
}
- if (alternate_track_address[0] == disk_track) {
+ if (m_alternate_track_address[0] == disk_track) {
// reset source of alternate track address
- alternate_track_address[0] = 0;
+ m_alternate_track_address[0] = 0;
}
- if (alternate_track_address[1] == disk_track) {
+ if (m_alternate_track_address[1] == disk_track) {
// reset alternate track address
- alternate_track_address[1] = 0;
+ m_alternate_track_address[1] = 0;
}
if (check_disk_address(cdb) ) {
if ((cdb[5] & 0x40) == 0) {
- memset(&sector_buffer[0], 0x6C, OMTI_DISK_SECTOR_SIZE * our_disks[lun]->m_sectors);
+ memset(&m_sector_buffer[0], 0x6C, OMTI_DISK_SECTOR_SIZE * our_disks[lun]->m_sectors);
}
write_sectors_to_disk(disk_addr, our_disks[lun]->m_sectors, lun);
}
@@ -689,8 +708,7 @@ void omti8621_device::logerror(Format &&fmt, Params &&... args) const
void omti8621_device::log_command(const uint8_t cdb[], const uint16_t cdb_length)
{
- if (verbose > 0) {
- int i;
+ if (VERBOSE & (LOG_LEVEL1 | LOG_LEVEL2 | LOG_LEVEL3)) {
logerror("%s: OMTI command ", cpu_context());
switch (cdb[0]) {
case OMTI_CMD_TEST_DRIVE_READY: // 0x00
@@ -763,7 +781,7 @@ void omti8621_device::log_command(const uint8_t cdb[], const uint16_t cdb_length
logerror("!!! Unexpected Command !!!");
}
// logerror(" (%02x, length=%02x)", cdb[0], cdb_length);
- for (i = 0; i < cdb_length; i++) {
+ for (int i = 0; i < cdb_length; i++) {
logerror(" %02x", cdb[i]);
}
@@ -788,15 +806,14 @@ void omti8621_device::log_command(const uint8_t cdb[], const uint16_t cdb_length
void omti8621_device::log_data()
{
- if (verbose > 0) {
- int i;
- logerror("%s: OMTI data (length=%02x)", cpu_context(),
- data_length);
- for (i = 0; i < data_length && i < OMTI_DISK_SECTOR_SIZE; i++) {
- logerror(" %02x", data_buffer[i]);
+ if (VERBOSE & LOG_LEVEL1) {
+ logerror("%s: OMTI data (length=%02x)", cpu_context(), m_data_length);
+ uint16_t i;
+ for (i = 0; i < m_data_length && i < OMTI_DISK_SECTOR_SIZE; i++) {
+ logerror(" %02x", m_data_buffer[i]);
}
- if (i < data_length) {
+ if (i < m_data_length) {
logerror(" ...");
}
logerror("\n");
@@ -813,19 +830,19 @@ void omti8621_device::do_command(const uint8_t cdb[], const uint16_t cdb_length)
omti_disk_image_device *disk = our_disks[lun];
int command_duration = 0; // ms
- log_command( cdb, cdb_length);
+ log_command(cdb, cdb_length);
// default to read status and status is successful completion
- omti_state = OMTI_STATE_STATUS;
- status_port |= OMTI_STATUS_IO | OMTI_STATUS_CD;
- command_status = lun ? OMTI_COMMAND_STATUS_LUN : 0;
+ m_omti_state = OMTI_STATE_STATUS;
+ m_status_port |= OMTI_STATUS_IO | OMTI_STATUS_CD;
+ m_command_status = lun ? OMTI_COMMAND_STATUS_LUN : 0;
- if (mask_port & OMTI_MASK_INTE) {
+ if (m_mask_port & OMTI_MASK_INTE) {
set_interrupt(CLEAR_LINE);
}
if (!disk->m_image->exists()) {
- command_status |= OMTI_COMMAND_STATUS_ERROR; // no such drive
+ m_command_status |= OMTI_COMMAND_STATUS_ERROR; // no such drive
}
switch (cdb[0]) {
@@ -840,7 +857,7 @@ void omti8621_device::do_command(const uint8_t cdb[], const uint16_t cdb_length)
break;
case OMTI_CMD_REQUEST_SENSE: // 0x03
- set_data_transfer(sense_data, sizeof(sense_data));
+ set_data_transfer(m_sense_data, sizeof(m_sense_data));
break;
case OMTI_CMD_READ_VERIFY: // 0x05
@@ -852,14 +869,14 @@ void omti8621_device::do_command(const uint8_t cdb[], const uint16_t cdb_length)
break;
case OMTI_CMD_FORMAT_BAD_TRACK: // 0x07
- diskaddr_format_bad_track = get_disk_address(cdb);
+ m_diskaddr_format_bad_track = get_disk_address(cdb);
break;
case OMTI_CMD_READ: // 0x08
if (check_disk_address(cdb)) {
// read data from controller
read_sectors_from_disk(get_disk_address(cdb), cdb[4], lun);
- set_data_transfer(&sector_buffer[0], OMTI_DISK_SECTOR_SIZE*cdb[4]);
+ set_data_transfer(&m_sector_buffer[0], OMTI_DISK_SECTOR_SIZE*cdb[4]);
}
break;
@@ -875,7 +892,7 @@ void omti8621_device::do_command(const uint8_t cdb[], const uint16_t cdb_length)
break;
case OMTI_CMD_READ_SECTOR_BUFFER: // 0x0E
- set_data_transfer(&sector_buffer[0], OMTI_DISK_SECTOR_SIZE*cdb[4]);
+ set_data_transfer(&m_sector_buffer[0], OMTI_DISK_SECTOR_SIZE*cdb[4]);
break;
case OMTI_CMD_WRITE_SECTOR_BUFFER: // 0x0F
@@ -897,8 +914,8 @@ void omti8621_device::do_command(const uint8_t cdb[], const uint16_t cdb_length)
#if 0 // this command seems unused by Domain/OS, and it's unclear what the intent of the code is (it makes some versions of GCC quite unhappy)
case OMTI_CMD_ASSIGN_ALTERNATE_TRACK: // 0x11
log_data();
- alternate_track_address[0] = get_disk_track(cdb);
- alternate_track_address[1] = get_disk_track(alternate_track_buffer-1);
+ m_alternate_track_address[0] = get_disk_track(cdb);
+ m_alternate_track_address[1] = get_disk_track(m_alternate_track_buffer - 1);
break;
#endif
@@ -928,7 +945,7 @@ void omti8621_device::do_command(const uint8_t cdb[], const uint16_t cdb_length)
if (check_disk_address(cdb)) {
// read data from controller
read_sectors_from_disk(get_disk_address(cdb), cdb[4], lun);
- set_data_transfer(&sector_buffer[0], OMTI_DISK_SECTOR_SIZE+6);
+ set_data_transfer(&m_sector_buffer[0], OMTI_DISK_SECTOR_SIZE+6);
}
break;
@@ -938,7 +955,7 @@ void omti8621_device::do_command(const uint8_t cdb[], const uint16_t cdb_length)
uint32_t diskaddr = get_disk_address(cdb);
write_sectors_to_disk(diskaddr, cdb[4], lun);
// this will spoil the ECC code
- diskaddr_ecc_error = diskaddr;
+ m_diskaddr_ecc_error = diskaddr;
}
break;
@@ -949,28 +966,28 @@ void omti8621_device::do_command(const uint8_t cdb[], const uint16_t cdb_length)
case OMTI_CMD_INVALID_COMMAND: // 0xFF
set_sense_data(OMTI_SENSE_CODE_INVALID_COMMAND, cdb);
- command_status |= OMTI_COMMAND_STATUS_ERROR;
+ m_command_status |= OMTI_COMMAND_STATUS_ERROR;
break;
default:
- LOG(("do_command: UNEXPECTED command %02x",cdb[0]));
+ LOGMASKED(LOG_LEVEL0, "%s: do_command: UNEXPECTED command %02x", cpu_context(), cdb[0]);
set_sense_data(OMTI_SENSE_CODE_INVALID_COMMAND, cdb);
- command_status |= OMTI_COMMAND_STATUS_ERROR;
+ m_command_status |= OMTI_COMMAND_STATUS_ERROR;
break;
}
- if (mask_port & OMTI_MASK_INTE) {
-// if (omti_state != OMTI_STATE_STATUS) {
-// LOG(("do_command: UNEXPECTED omti_state %02x",omti_state));
+ if (m_mask_port & OMTI_MASK_INTE) {
+// if (m_omti_state != OMTI_STATE_STATUS) {
+// LOGMASKED(LOG_LEVEL0, "%s: do_command: UNEXPECTED omti_state %02x", cpu_context(), m_omti_state));
// }
- status_port |= OMTI_STATUS_IREQ;
+ m_status_port |= OMTI_STATUS_IREQ;
if (command_duration == 0)
{
set_interrupt(ASSERT_LINE);
}
else
{
- // FIXME: should delay omti_state and status_port as well
+ // FIXME: should delay m_omti_state and m_status_port as well
m_timer->adjust(attotime::from_msec(command_duration), 0);
}
}
@@ -992,16 +1009,16 @@ uint8_t omti8621_device::get_command_length(uint8_t command_byte)
uint16_t omti8621_device::get_data()
{
uint16_t data = 0xff;
- if (data_index < data_length) {
- data = data_buffer[data_index++];
- data |= data_buffer[data_index++] << 8;
- if (data_index >= data_length) {
- omti_state = OMTI_STATE_STATUS;
- status_port |= OMTI_STATUS_IO | OMTI_STATUS_CD;
+ if (m_data_index < m_data_length) {
+ data = m_data_buffer[m_data_index++];
+ data |= m_data_buffer[m_data_index++] << 8;
+ if (m_data_index >= m_data_length) {
+ m_omti_state = OMTI_STATE_STATUS;
+ m_status_port |= OMTI_STATUS_IO | OMTI_STATUS_CD;
log_data();
}
} else {
- LOG(("UNEXPECTED reading OMTI 8621 data (buffer length exceeded)"));
+ LOGMASKED(LOG_LEVEL0, "%s: UNEXPECTED reading OMTI 8621 data (buffer length exceeded)", cpu_context());
}
return data;
}
@@ -1012,14 +1029,14 @@ uint16_t omti8621_device::get_data()
void omti8621_device::set_data(uint16_t data)
{
- if (data_index < data_length) {
- data_buffer[data_index++] = data & 0xff;
- data_buffer[data_index++] = data >> 8;
- if (data_index >= data_length) {
- do_command(command_buffer, command_index);
+ if (m_data_index < m_data_length) {
+ m_data_buffer[m_data_index++] = data & 0xff;
+ m_data_buffer[m_data_index++] = data >> 8;
+ if (m_data_index >= m_data_length) {
+ do_command(m_command_buffer, m_command_index);
}
} else {
- LOG(("UNEXPECTED writing OMTI 8621 data (buffer length exceeded)"));
+ LOGMASKED(LOG_LEVEL0, "%s: UNEXPECTED writing OMTI 8621 data (buffer length exceeded)", cpu_context());
}
}
@@ -1027,16 +1044,16 @@ void omti8621_device::set_data(uint16_t data)
OMTI8621 Disk Controller-AT Registers
***************************************************************************/
-WRITE16_MEMBER(omti8621_device::write)
+void omti8621_device::write(offs_t offset, uint16_t data, uint16_t mem_mask)
{
switch (mem_mask)
{
case 0x00ff:
- write8(space, offset*2, data, mem_mask);
+ write8(offset*2, data);
break;
case 0xff00:
- write8(space, offset*2+1, data>>8, mem_mask>>8);
+ write8(offset*2+1, data>>8);
break;
default:
@@ -1045,183 +1062,176 @@ WRITE16_MEMBER(omti8621_device::write)
}
}
-WRITE8_MEMBER(omti8621_device::write8)
+void omti8621_device::write8(offs_t offset, uint8_t data)
{
switch (offset)
{
case OMTI_PORT_DATA_OUT: // 0x00
- switch (omti_state) {
+ switch (m_omti_state) {
case OMTI_STATE_COMMAND:
- LOG2(("writing OMTI 8621 Command Register at offset %02x = %02x", offset, data));
- if (command_index == 0) {
- command_length = get_command_length(data);
+ LOGMASKED(LOG_LEVEL2, "%s: writing OMTI 8621 Command Register at offset %02x = %02x", cpu_context(), offset, data);
+ if (m_command_index == 0) {
+ m_command_length = get_command_length(data);
}
- if (command_index < command_length) {
- command_buffer[command_index++] = data;
+ if (m_command_index < m_command_length) {
+ m_command_buffer[m_command_index++] = data;
} else {
- LOG(("UNEXPECTED writing OMTI 8621 Data Register at offset %02x = %02x (command length exceeded)", offset, data));
+ LOGMASKED(LOG_LEVEL0, "%s: UNEXPECTED writing OMTI 8621 Data Register at offset %02x = %02x (command length exceeded)", cpu_context(), offset, data);
}
- if (command_index == command_length) {
- switch (command_buffer[0]) {
+ if (m_command_index == m_command_length) {
+ switch (m_command_buffer[0]) {
case OMTI_CMD_WRITE: // 0x0A
// TODO: check diskaddr
- // Fall through
+ [[fallthrough]];
case OMTI_CMD_WRITE_SECTOR_BUFFER: // 0x0F
- set_data_transfer(&sector_buffer[0],
- OMTI_DISK_SECTOR_SIZE * command_buffer[4]);
- status_port &= ~OMTI_STATUS_IO;
+ set_data_transfer(&m_sector_buffer[0], OMTI_DISK_SECTOR_SIZE * m_command_buffer[4]);
+ m_status_port &= ~OMTI_STATUS_IO;
break;
case OMTI_CMD_ASSIGN_ALTERNATE_TRACK: // 0x11
- set_data_transfer(alternate_track_buffer, sizeof(alternate_track_buffer));
- status_port &= ~OMTI_STATUS_IO;
+ set_data_transfer(m_alternate_track_buffer, sizeof(m_alternate_track_buffer));
+ m_status_port &= ~OMTI_STATUS_IO;
break;
case OMTI_CMD_WRITE_LONG: // 0xE6
// TODO: check diskaddr
- set_data_transfer(&sector_buffer[0],
- (OMTI_DISK_SECTOR_SIZE +6) * command_buffer[4]);
- status_port &= ~OMTI_STATUS_IO;
+ set_data_transfer(&m_sector_buffer[0], (OMTI_DISK_SECTOR_SIZE +6) * m_command_buffer[4]);
+ m_status_port &= ~OMTI_STATUS_IO;
break;
default:
- do_command(command_buffer, command_index);
+ do_command(m_command_buffer, m_command_index);
break;
}
}
break;
case OMTI_STATE_DATA:
- LOG(("UNEXPECTED: writing OMTI 8621 Data Register at offset %02x = %02x", offset, data));
+ LOGMASKED(LOG_LEVEL0, "%s: UNEXPECTED: writing OMTI 8621 Data Register at offset %02x = %02x", cpu_context(), offset, data);
break;
default:
- LOG(("UNEXPECTED writing OMTI 8621 Data Register at offset %02x = %02x (omti state = %02x)", offset, data, omti_state));
+ LOGMASKED(LOG_LEVEL0, "%s: UNEXPECTED writing OMTI 8621 Data Register at offset %02x = %02x (omti state = %02x)", cpu_context(), offset, data, m_omti_state);
break;
}
break;
case OMTI_PORT_RESET: // 0x01
- LOG2(("writing OMTI 8621 Reset Register at offset %02x = %02x", offset, data));
+ LOGMASKED(LOG_LEVEL2, "%s: writing OMTI 8621 Reset Register at offset %02x = %02x", cpu_context(), offset, data);
device_reset();
break;
case OMTI_PORT_SELECT: // 0x02
- LOG2(("writing OMTI 8621 Select Register at offset %02x = %02x (omti state = %02x)", offset, data, omti_state));
- omti_state = OMTI_STATE_COMMAND;
+ LOGMASKED(LOG_LEVEL2, "%s: writing OMTI 8621 Select Register at offset %02x = %02x (omti state = %02x)", cpu_context(), offset, data, m_omti_state);
+ m_omti_state = OMTI_STATE_COMMAND;
- status_port |= OMTI_STATUS_BUSY | OMTI_STATUS_REQ | OMTI_STATUS_CD;
- status_port &= ~OMTI_STATUS_IO;
+ m_status_port |= OMTI_STATUS_BUSY | OMTI_STATUS_REQ | OMTI_STATUS_CD;
+ m_status_port &= ~OMTI_STATUS_IO;
- command_status = 0;
- command_index = 0;
+ m_command_status = 0;
+ m_command_index = 0;
break;
case OMTI_PORT_MASK: // 0x03
- LOG2(("writing OMTI 8621 Mask Register at offset %02x = %02x", offset, data));
- mask_port = data;
+ LOGMASKED(LOG_LEVEL2, "%s: writing OMTI 8621 Mask Register at offset %02x = %02x", cpu_context(), offset, data);
+ m_mask_port = data;
if ((data & OMTI_MASK_INTE) == 0) {
- status_port &= ~OMTI_STATUS_IREQ;
+ m_status_port &= ~OMTI_STATUS_IREQ;
set_interrupt(CLEAR_LINE);
}
if ((data & OMTI_MASK_DMAE) == 0) {
- status_port &= ~OMTI_STATUS_DREQ;
+ m_status_port &= ~OMTI_STATUS_DREQ;
}
break;
default:
- LOG(("UNEXPECTED writing OMTI 8621 Register at offset %02x = %02x", offset, data));
+ LOGMASKED(LOG_LEVEL0, "%s: UNEXPECTED writing OMTI 8621 Register at offset %02x = %02x", cpu_context(), offset, data);
break;
}
}
-READ16_MEMBER(omti8621_device::read)
+uint16_t omti8621_device::read(offs_t offset, uint16_t mem_mask)
{
switch (mem_mask)
{
case 0x00ff:
- return read8(space, offset*2, mem_mask);
+ return read8(offset*2);
case 0xff00:
- return read8(space, offset*2+1, mem_mask >> 8) << 8;
+ return read8(offset*2+1) << 8;
default:
return get_data();
}
}
-READ8_MEMBER(omti8621_device::read8)
+uint8_t omti8621_device::read8(offs_t offset)
{
uint8_t data = 0xff;
static uint8_t last_data = 0xff;
switch (offset) {
case OMTI_PORT_DATA_IN: // 0x00
- if (status_port & OMTI_STATUS_CD)
+ if (m_status_port & OMTI_STATUS_CD)
{
- data = command_status;
- switch (omti_state)
+ data = m_command_status;
+ switch (m_omti_state)
{
case OMTI_STATE_COMMAND:
- LOG2(("reading OMTI 8621 Data Status Register 1 at offset %02x = %02x (omti state = %02x)", offset, data, omti_state));
+ LOGMASKED(LOG_LEVEL2, "%s: reading OMTI 8621 Data Status Register 1 at offset %02x = %02x (omti state = %02x)", cpu_context(), offset, data, m_omti_state);
break;
case OMTI_STATE_STATUS:
- omti_state = OMTI_STATE_IDLE;
- status_port &= ~(OMTI_STATUS_BUSY | OMTI_STATUS_CD | OMTI_STATUS_IO | OMTI_STATUS_REQ);
- LOG2(("reading OMTI 8621 Data Status Register 2 at offset %02x = %02x", offset, data));
+ m_omti_state = OMTI_STATE_IDLE;
+ m_status_port &= ~(OMTI_STATUS_BUSY | OMTI_STATUS_CD | OMTI_STATUS_IO | OMTI_STATUS_REQ);
+ LOGMASKED(LOG_LEVEL2, "%s: reading OMTI 8621 Data Status Register 2 at offset %02x = %02x", cpu_context(), offset, data);
break;
default:
- LOG(("UNEXPECTED reading OMTI 8621 Data Status Register 3 at offset %02x = %02x (omti state = %02x)", offset, data, omti_state));
+ LOGMASKED(LOG_LEVEL0, "%s: UNEXPECTED reading OMTI 8621 Data Status Register 3 at offset %02x = %02x (omti state = %02x)", cpu_context(), offset, data, m_omti_state);
break;
}
}
else
{
- LOG(("UNEXPECTED reading OMTI 8621 Data Register 4 at offset %02x = %02x (status bit C/D = 0)", offset, data));
+ LOGMASKED(LOG_LEVEL0, "%s: UNEXPECTED reading OMTI 8621 Data Register 4 at offset %02x = %02x (status bit C/D = 0)", cpu_context(), offset, data);
}
break;
case OMTI_PORT_STATUS: // 0x01
- data = status_port;
+ data = m_status_port;
// omit excessive logging
if (data != last_data)
{
- LOG2(("reading OMTI 8621 Status Register 5 at offset %02x = %02x", offset, data));
+ LOGMASKED(LOG_LEVEL2, "%s: reading OMTI 8621 Status Register 5 at offset %02x = %02x", cpu_context(), offset, data);
// last_data = data;
}
break;
case OMTI_PORT_CONFIG: // 0x02
- data = config_port;
- LOG2(("reading OMTI 8621 Configuration Register at offset %02x = %02x", offset, data));
+ data = m_config_port;
+ LOGMASKED(LOG_LEVEL2, "%s: reading OMTI 8621 Configuration Register at offset %02x = %02x", cpu_context(), offset, data);
break;
case OMTI_PORT_MASK: // 0x03
- data = mask_port ;
+ data = m_mask_port;
// win.dex will update the mask register with read-modify-write
- // LOG2(("reading OMTI 8621 Mask Register at offset %02x = %02x (UNEXPECTED!)", offset, data));
+ // LOGMASKED(LOG_LEVEL2, "%s: reading OMTI 8621 Mask Register at offset %02x = %02x (UNEXPECTED!)", cpu_context(), offset, data);
break;
default:
- LOG(("UNEXPECTED reading OMTI 8621 Register at offset %02x = %02x", offset, data));
+ LOGMASKED(LOG_LEVEL0, "%s: UNEXPECTED reading OMTI 8621 Register at offset %02x = %02x", cpu_context(), offset, data);
break;
}
return data;
}
-void omti8621_device::set_verbose(int on_off)
-{
- verbose = on_off == 0 ? 0 : VERBOSE > 1 ? VERBOSE : 1;
-}
-
/***************************************************************************
get_sector - get sector diskaddr of logical unit lun into data_buffer
***************************************************************************/
-uint32_t omti8621_apollo_device::get_sector(int32_t diskaddr, uint8_t *data_buffer, uint32_t length, uint8_t lun)
+uint32_t omti8621_apollo_device::get_sector(int32_t diskaddr, uint8_t *buffer, uint32_t length, uint8_t lun)
{
omti_disk_image_device *disk = our_disks[lun];
@@ -1231,13 +1241,13 @@ uint32_t omti8621_apollo_device::get_sector(int32_t diskaddr, uint8_t *data_buff
}
else
{
-// LOG1(("omti8621_get_sector %x on lun %d", diskaddr, lun));
+// LOGMASKED(LOG_LEVEL1, "%s: omti8621_get_sector %x on lun %d", cpu_context(), diskaddr, lun);
// restrict length to size of 1 sector (i.e. 1024 Byte)
length = length < OMTI_DISK_SECTOR_SIZE ? length : OMTI_DISK_SECTOR_SIZE;
disk->m_image->fseek(diskaddr * OMTI_DISK_SECTOR_SIZE, SEEK_SET);
- disk->m_image->fread(data_buffer, length);
+ disk->m_image->fread(buffer, length);
return length;
}
@@ -1249,30 +1259,32 @@ uint32_t omti8621_apollo_device::get_sector(int32_t diskaddr, uint8_t *data_buff
void omti8621_device::set_jumper(uint16_t disk_type)
{
- LOG1(("set_jumper: disk type=%x", disk_type));
+ LOGMASKED(LOG_LEVEL1, "%s: set_jumper: disk type=%x", cpu_context(), disk_type);
switch (disk_type)
{
case OMTI_DISK_TYPE_348_MB: // Maxtor 380 MB (348-MB FA formatted)
- jumper = OMTI_CONFIG_W22 | OMTI_CONFIG_W23;
+ m_jumper = OMTI_CONFIG_W22 | OMTI_CONFIG_W23;
break;
case OMTI_DISK_TYPE_155_MB: // Micropolis 170 MB (155-MB formatted)
default:
- jumper = OMTI_CONFIG_W20;
+ m_jumper = OMTI_CONFIG_W20;
break;
}
}
// 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)
{
- m_isa->irq6_w(state ? ASSERT_LINE : CLEAR_LINE);
+ 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)
{
- m_isa->drq2_w(state ? ASSERT_LINE : CLEAR_LINE);
+ if (BIT(m_moten, 3))
+ m_isa->drq2_w(state ? ASSERT_LINE : CLEAR_LINE);
}
uint8_t omti8621_device::dack_r(int line)
@@ -1295,14 +1307,79 @@ void omti8621_device::eop_w(int state)
m_fdc->tc_w(state == ASSERT_LINE);
}
+void omti8621_device::fdc_map(address_map &map)
+{
+ map(2, 2).w(FUNC(omti8621_device::fd_moten_w));
+ map(4, 5).m(m_fdc, FUNC(upd765a_device::map));
+ map(6, 6).w(FUNC(omti8621_device::fd_extra_w));
+ map(7, 7).rw(FUNC(omti8621_device::fd_disk_chg_r), FUNC(omti8621_device::fd_rate_w));
+}
+
+void omti8621_device::fd_moten_w(uint8_t data)
+{
+ if (BIT(data, 3) && !BIT(m_moten, 3))
+ {
+ m_isa->irq6_w(m_fdc->get_irq() ? ASSERT_LINE : CLEAR_LINE);
+ m_isa->drq2_w(m_fdc->get_drq() ? ASSERT_LINE : CLEAR_LINE);
+ }
+ else if (!BIT(data, 3) && BIT(m_moten, 3))
+ {
+ m_isa->irq6_w(CLEAR_LINE);
+ m_isa->drq2_w(CLEAR_LINE);
+ }
+
+ m_moten = data;
+
+ m_fdc->reset_w(!BIT(data, 2));
+
+ for (int i = 0; i < 2; i++)
+ {
+ floppy_image_device *floppy = m_floppy[i].found() ? m_floppy[i]->get_device() : nullptr;
+ if (floppy != nullptr)
+ floppy->mon_w(!BIT(data, i + 4));
+
+ if (i == (data & 0x01))
+ m_fdc->set_floppy(BIT(data, i + 4) ? floppy : nullptr);
+ }
+}
+
+void omti8621_device::fd_rate_w(uint8_t data)
+{
+ // Bit 1 = FD_MINI (connects to pin 3 of FDC9239)
+ // Bit 0 = FD_RATE (inverted output connects to pin 4 of 74F163)
+ u32 fdc_clk = (48_MHz_XTAL / (BIT(data, 0) ? 5 : 3) / (BIT(data, 1) ? 4 : 2)).value();
+ m_fdc->set_unscaled_clock(fdc_clk);
+ m_fdc->set_rate(fdc_clk / 16);
+}
+
+void omti8621_device::fd_extra_w(uint8_t data)
+{
+ // Bit 7 = FD_EXTRA-2 (NC)
+ // Bit 6 = FD_EXTRA-1 (NC)
+ // Bit 5 = FD_PIN_6 (TODO)
+ // Bit 4 = FD_IUSE_HLD (TODO)
+ // Bit 3 = FD_DEN_SEL (TODO)
+ // Bit 2 = FD_PRE-2 (TODO)
+ // Bit 1 = FD_PRE-1 (TODO)
+ // Bit 0 = FD_PRE-0 (TODO)
+}
+
+uint8_t omti8621_device::fd_disk_chg_r()
+{
+ floppy_image_device *floppy = m_floppy[m_moten & 0x01].found() ? m_floppy[m_moten & 0x01]->get_device() : nullptr;
+ if (floppy == nullptr || floppy->dskchg_r())
+ return 0x00;
+ else
+ return 0x80;
+}
+
//##########################################################################
// device type definition
DEFINE_DEVICE_TYPE(OMTI_DISK, omti_disk_image_device, "omti_disk_image", "OMTI 8621 ESDI disk")
omti_disk_image_device::omti_disk_image_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
- : device_t(mconfig, OMTI_DISK, tag, owner, clock)
- , device_image_interface(mconfig, *this)
+ : harddisk_image_base_device(mconfig, OMTI_DISK, tag, owner, clock)
, m_type(0), m_cylinders(0), m_heads(0), m_sectors(0), m_sectorbytes(0), m_sector_count(0), m_image(nullptr)
{
}
@@ -1376,9 +1453,9 @@ void omti_disk_image_device::device_reset()
{
logerror("device_reset_omti_disk\n");
- if (exists() && fseek(0, SEEK_END) == 0)
+ if (exists() && !fseek(0, SEEK_END))
{
- uint32_t disk_size = (uint32_t)(ftell() / OMTI_DISK_SECTOR_SIZE);
+ uint32_t disk_size = uint32_t(ftell() / OMTI_DISK_SECTOR_SIZE);
uint16_t disk_type = disk_size >= 300000 ? OMTI_DISK_TYPE_348_MB : OMTI_DISK_TYPE_155_MB;
if (disk_type != m_type) {
logerror("device_reset_omti_disk: disk size=%d blocks, disk type=%x\n", disk_size, disk_type);
@@ -1391,22 +1468,18 @@ 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);
- int x;
unsigned char sectordata[OMTI_DISK_SECTOR_SIZE]; // empty block data
-
-
memset(sectordata, 0x55, sizeof(sectordata));
- for (x = 0; x < m_sector_count; x++)
+
+ 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 1258af71854..11d4263a996 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/pc_fdc.h"
+
#include "imagedev/floppy.h"
+#include "machine/upd765.h"
+
/***************************************************************************
FUNCTION PROTOTYPES
@@ -30,10 +32,8 @@ class omti_disk_image_device;
class omti8621_device : public device_t, public device_isa16_card_interface
{
public:
- DECLARE_READ16_MEMBER(read);
- DECLARE_WRITE16_MEMBER(write);
-
- static void set_verbose(int on_off);
+ uint16_t read(offs_t offset, uint16_t mem_mask = 0xffff);
+ void write(offs_t offset, uint16_t data, uint16_t mem_mask = 0xffff);
protected:
static constexpr unsigned OMTI_MAX_LUN = 1;
@@ -46,22 +46,24 @@ protected:
device_t *owner,
uint32_t clock);
- // device-level overrides
- virtual void device_start() override;
- virtual void device_reset() override;
- virtual const tiny_rom_entry *device_rom_region() const override;
- virtual void device_timer(emu_timer &timer, device_timer_id id, int param, void *ptr) override;
- virtual void device_add_mconfig(machine_config &config) override;
- virtual ioport_constructor device_input_ports() const override;
+ // device_t implementation
+ virtual void device_start() override ATTR_COLD;
+ virtual void device_reset() override ATTR_COLD;
+ virtual const tiny_rom_entry *device_rom_region() const override ATTR_COLD;
+ virtual void device_add_mconfig(machine_config &config) override ATTR_COLD;
+ virtual ioport_constructor device_input_ports() const override ATTR_COLD;
virtual uint8_t dack_r(int line) override;
virtual void dack_w(int line, uint8_t data) override;
virtual void dack_line_w(int line, int state) override;
virtual void eop_w(int state) override;
- void set_interrupt(enum line_state line_state);
+ void set_interrupt(line_state state);
+
+ TIMER_CALLBACK_MEMBER(trigger_interrupt);
- required_device<pc_fdc_interface> m_fdc;
+ required_device<upd765a_device> m_fdc;
+ optional_device_array<floppy_connector, 2> m_floppy;
required_ioport m_iobase;
required_ioport m_biosopts;
@@ -70,41 +72,50 @@ protected:
std::string cpu_context() const;
private:
- DECLARE_WRITE_LINE_MEMBER( fdc_irq_w );
- DECLARE_WRITE_LINE_MEMBER( fdc_drq_w );
- DECLARE_FLOPPY_FORMATS( floppy_formats );
+ void fdc_irq_w(int state);
+ void fdc_drq_w(int state);
+ static void floppy_formats(format_registration &fr);
- uint16_t jumper;
+ void fd_moten_w(uint8_t data);
+ void fd_rate_w(uint8_t data);
+ void fd_extra_w(uint8_t data);
+ uint8_t fd_disk_chg_r();
- uint8_t omti_state;
+ void fdc_map(address_map &map) ATTR_COLD;
- uint8_t status_port;
- uint8_t config_port;
- uint8_t mask_port;
+ uint16_t m_jumper;
+
+ uint8_t m_omti_state;
+
+ uint8_t m_status_port;
+ uint8_t m_config_port;
+ uint8_t m_mask_port;
// command descriptor block
- uint8_t command_buffer[CDB_SIZE];
- int command_length;
- int command_index;
- int command_status;
+ uint8_t m_command_buffer[CDB_SIZE];
+ uint8_t m_command_length;
+ uint16_t m_command_index;
+ uint8_t m_command_status;
// data buffer
- std::vector<uint8_t> sector_buffer;
- uint8_t *data_buffer;
- int data_length;
- int data_index;
+ std::vector<uint8_t> m_sector_buffer;
+ uint8_t *m_data_buffer;
+ uint16_t m_data_length;
+ uint16_t m_data_index;
// sense data
- uint8_t sense_data[4];
+ uint8_t m_sense_data[4];
// these are used only to satisfy dex
- uint32_t diskaddr_ecc_error;
- uint32_t diskaddr_format_bad_track;
- uint8_t alternate_track_buffer[4];
- uint32_t alternate_track_address[2];
+ uint32_t m_diskaddr_ecc_error;
+ uint32_t m_diskaddr_format_bad_track;
+ uint8_t m_alternate_track_buffer[4];
+ uint32_t m_alternate_track_address[2];
emu_timer *m_timer;
+ uint8_t m_moten;
+
bool m_installed;
void clear_sense_data();
@@ -130,8 +141,8 @@ private:
uint16_t get_data();
void set_data(uint16_t data);
void set_jumper(uint16_t disk_type);
- DECLARE_READ8_MEMBER(read8);
- DECLARE_WRITE8_MEMBER(write8);
+ uint8_t read8(offs_t offset);
+ void write8(offs_t offset, uint8_t data);
};
/* ----- omti8621 for PC device interface ----- */
@@ -152,9 +163,11 @@ public:
omti8621_apollo_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
// get sector diskaddr of logical unit lun into data_buffer
- uint32_t get_sector(int32_t diskaddr, uint8_t *data_buffer, uint32_t length, uint8_t lun);
+ uint32_t get_sector(int32_t diskaddr, uint8_t *buffer, uint32_t length, uint8_t lun);
+
protected:
- virtual const tiny_rom_entry *device_rom_region() const override;
+ virtual void device_add_mconfig(machine_config &config) override ATTR_COLD;
+ virtual const tiny_rom_entry *device_rom_region() const override ATTR_COLD;
};
DECLARE_DEVICE_TYPE(ISA16_OMTI8621_APOLLO, omti8621_apollo_device)
diff --git a/src/devices/bus/isa/opus100pm.cpp b/src/devices/bus/isa/opus100pm.cpp
new file mode 100644
index 00000000000..cfa070eacf3
--- /dev/null
+++ b/src/devices/bus/isa/opus100pm.cpp
@@ -0,0 +1,351 @@
+// license:BSD-3-Clause
+// copyright-holders:Patrick Mackinlay
+
+/*
+ * Opus 100PM (Personal Mainframe) UNIX processor subsystem
+ *
+ * Sources:
+ * - http://bitsavers.org/pdf/opusSystems/32k/800-00237-000_Opus_100pm_User_Manual_1987.pdf
+ *
+ * TODO
+ * - 32032-based 110PM
+ */
+
+ /*
+ * WIP
+ * ---
+ * Using IBM 5160 as host avoids boot problem with 5170 and issues with
+ * shadowing in ct486.
+ *
+ * - opus ibm5160 -window -nomax -hard1 opus_c.chd -hard2 opus_d.chd -isa5 opus108pm
+ *
+ * System configuration and software installation from boot and kernel floppies
+ * appears successful. Valid Systems hard disk images appear to expect a card
+ * with different registers?
+ *
+ * Booting Opus5 from swap hangs with WAIT instruction at 0xf0087c, presume
+ * requires an interrupt from PC which never arrives. Maybe clock device isn't
+ * working properly?
+ */
+
+#include "emu.h"
+#include "opus100pm.h"
+
+#define LOG_STAT (1U << 1)
+#define LOG_REG (1U << 2)
+
+//#define VERBOSE (LOG_GENERAL|LOG_REG)
+#include "logmacro.h"
+
+DEFINE_DEVICE_TYPE(ISA8_OPUS108PM, isa8_opus108pm_device, "opus108pm", "Opus 108PM")
+
+// CPU bit definition here matches software, but differs from documentation
+enum card_stat_mask : u8
+{
+ CARD_STAT_CPU = 0x01, // CPU type (0=32016, 1=32032)
+ CARD_STAT_EIRQ = 0x04, // IRQ enabled
+ CARD_STAT_OPT = 0x08, // option switch open
+ CARD_STAT_DMA = 0x10, // DMA abort
+ CARD_STAT_PAR = 0x20, // parity error
+ CARD_STAT_IRQ = 0x40, // interrupt to host active
+ CARD_STAT_INT = 0x80, // interrupt to card active
+};
+
+// the three low bits in the host status register probably correspond to
+// unemulated CTTL, /TSO and /CWAIT signals from the TCU
+enum host_stat_mask : u8
+{
+ HOST_STAT_CTTL = 0x01, // CTTL (diagnostic only)
+ HOST_STAT_TSO = 0x02, // TSO* (diagnostic only)
+ HOST_STAT_CWT = 0x04, // CWT* (diagnostic only)
+ HOST_STAT_RUN = 0x08, // RUN* (diagnostic only)
+ HOST_STAT_DMA = 0x10, // DMA abort
+ HOST_STAT_PAR = 0x20, // parity error
+ HOST_STAT_IRQ = 0x40, // interrupt to host active
+ HOST_STAT_INT = 0x80, // interrupt to card active
+};
+
+static INPUT_PORTS_START(opus108pm)
+ PORT_START("BASE")
+ PORT_DIPNAME(0xf0000, 0xa0000, "Base Address")
+ PORT_DIPSETTING( 0x00000, "00000")
+ PORT_DIPSETTING( 0x10000, "10000")
+ PORT_DIPSETTING( 0x20000, "20000")
+ PORT_DIPSETTING( 0x30000, "30000")
+ PORT_DIPSETTING( 0x40000, "40000")
+ PORT_DIPSETTING( 0x50000, "50000")
+ PORT_DIPSETTING( 0x60000, "60000")
+ PORT_DIPSETTING( 0x70000, "70000")
+ PORT_DIPSETTING( 0x80000, "80000")
+ PORT_DIPSETTING( 0x90000, "90000")
+ PORT_DIPSETTING( 0xa0000, "A0000")
+ PORT_DIPSETTING( 0xb0000, "B0000")
+ PORT_DIPSETTING( 0xc0000, "C0000")
+ PORT_DIPSETTING( 0xd0000, "D0000")
+ PORT_DIPSETTING( 0xe0000, "E0000")
+ PORT_DIPSETTING( 0xf0000, "F0000")
+
+ PORT_START("IRQ")
+ PORT_DIPNAME(0x0f, 0x07, "IRQ")
+ PORT_DIPSETTING( 0x02, "IRQ 2")
+ PORT_DIPSETTING( 0x03, "IRQ 3")
+ PORT_DIPSETTING( 0x07, "IRQ 7")
+INPUT_PORTS_END
+
+isa8_opus108pm_device::isa8_opus108pm_device(machine_config const &mconfig, char const *tag, device_t *owner, u32 clock)
+ : device_t(mconfig, ISA8_OPUS108PM, tag, owner, clock)
+ , device_isa8_card_interface(mconfig, *this)
+ , m_cpu(*this, "cpu")
+ , m_fpu(*this, "fpu")
+ , m_mmu(*this, "mmu")
+ , m_ram(*this, "ram")
+ , m_base(*this, "BASE")
+ , m_irq(*this, "IRQ")
+ , m_installed(false)
+{
+}
+
+void isa8_opus108pm_device::device_add_mconfig(machine_config &config)
+{
+ NS32016(config, m_cpu, 20_MHz_XTAL / 2);
+ m_cpu->set_addrmap(0, &isa8_opus108pm_device::map_cpu);
+
+ NS32081(config, m_fpu, 20_MHz_XTAL / 2);
+ m_cpu->set_fpu(m_fpu);
+
+ NS32082(config, m_mmu, 20_MHz_XTAL / 2);
+ m_cpu->set_mmu(m_mmu);
+
+ RAM(config, m_ram);
+ m_ram->set_default_size("1MiB");
+ m_ram->set_extra_options("2MiB");
+}
+
+ioport_constructor isa8_opus108pm_device::device_input_ports() const
+{
+ return INPUT_PORTS_NAME(opus108pm);
+}
+
+void isa8_opus108pm_device::device_start()
+{
+ set_isa_device();
+
+ if (!m_ram->started())
+ throw device_missing_dependencies();
+
+ save_item(NAME(m_card_stat));
+ save_item(NAME(m_host_stat));
+
+ m_cpu->space(0).install_ram(0, m_ram->mask(), m_ram->pointer());
+}
+
+void isa8_opus108pm_device::device_reset()
+{
+ if (!m_installed)
+ {
+ u32 const base = m_base->read();
+
+ m_isa->install_memory(base, base | 0xffff, *this, &isa8_opus108pm_device::map_isa);
+
+ m_installed = true;
+ }
+
+ m_card_stat = CARD_STAT_OPT;
+ m_host_stat = HOST_STAT_RUN;
+}
+
+void isa8_opus108pm_device::device_reset_after_children()
+{
+ m_cpu->suspend(SUSPEND_REASON_HALT, true);
+ m_cpu->suspend(SUSPEND_REASON_RESET, false);
+}
+
+void isa8_opus108pm_device::map_cpu(address_map &map)
+{
+ // TODO: should unmapped memory accesses cause parity errors and NMI?
+
+ // silence double-word access to byte-sized registers
+ map(0x800000, 0x800003).noprw().mirror(0x030000);
+
+ map(0x800000, 0x800000).r(FUNC(isa8_opus108pm_device::card_wait_r));
+ map(0x810000, 0x810000).r(FUNC(isa8_opus108pm_device::card_stat_r));
+ map(0x810000, 0x810000).w(FUNC(isa8_opus108pm_device::card_rste_w));
+ map(0x820000, 0x820000).w(FUNC(isa8_opus108pm_device::card_ack_w));
+ map(0x830000, 0x830000).w(FUNC(isa8_opus108pm_device::card_irq_w));
+}
+
+void isa8_opus108pm_device::map_isa(address_map &map)
+{
+ map(0x0000, 0xefff).lrw8(
+ [this](offs_t offset)
+ {
+ if (!(m_host_stat & HOST_STAT_RUN))
+ offset |= 0xff0000;
+
+ // FIXME: invalid translation probably triggers "DMA abort" status
+ // and generates an NMI; unsure what else is reported to the host
+ if (m_mmu->translate(m_cpu->space(0), 0xa, offset, false, false) != ns32000_mmu_interface::COMPLETE)
+ fatalerror("%s: host address translation failed (%s)\n", tag(), machine().describe_context());
+
+ return m_ram->read(offset);
+ }, "ram_r",
+ [this](offs_t offset, u8 data)
+ {
+ if (!(m_host_stat & HOST_STAT_RUN))
+ offset |= 0xff0000;
+
+ // FIXME: invalid translation probably triggers "DMA abort" status
+ // and generates an NMI; unsure what else is reported to the host
+ if (m_mmu->translate(m_cpu->space(0), 0xa, offset, false, true) != ns32000_mmu_interface::COMPLETE)
+ fatalerror("%s: host address translation failed (%s)\n", tag(), machine().describe_context());
+
+ m_ram->write(offset, data);
+ }, "ram_w");
+
+ // software expects these registers at 0xfffN, not 0xf00N per documentation,
+ // assume they are mirrored throughout the whole 4k range
+ map(0xf000, 0xf000).mirror(0x0ff0).r(FUNC(isa8_opus108pm_device::host_stat_r));
+ map(0xf001, 0xf001).mirror(0x0ff0).w(FUNC(isa8_opus108pm_device::host_eirq_w));
+ map(0xf002, 0xf002).mirror(0x0ff0).w(FUNC(isa8_opus108pm_device::host_ack_w));
+ map(0xf003, 0xf003).mirror(0x0ff0).w(FUNC(isa8_opus108pm_device::host_int_w));
+ map(0xf004, 0xf004).mirror(0x0ff0).w(FUNC(isa8_opus108pm_device::host_nmi_w));
+ map(0xf005, 0xf005).mirror(0x0ff0).w(FUNC(isa8_opus108pm_device::host_go_w));
+ map(0xf006, 0xf006).mirror(0x0ff0).w(FUNC(isa8_opus108pm_device::host_run_w));
+ map(0xf007, 0xf007).mirror(0x0ff0).w(FUNC(isa8_opus108pm_device::host_rst_w));
+}
+
+void isa8_opus108pm_device::update_isa_irq(int state)
+{
+ LOG("update_isa_irq %d\n", state);
+
+ switch (m_irq->read())
+ {
+ case 2: m_isa->irq2_w(state); break;
+ case 3: m_isa->irq3_w(state); break;
+ case 7: m_isa->irq7_w(state); break;
+
+ default:
+ fatalerror("%s: invalid isa irq %d\n", tag(), m_irq->read());
+ }
+}
+
+u8 isa8_opus108pm_device::card_stat_r()
+{
+ LOGMASKED(LOG_STAT, "card_stat_r 0x%02x (%s)\n", m_card_stat, machine().describe_context());
+
+ return m_card_stat;
+}
+
+void isa8_opus108pm_device::card_rste_w(u8 data)
+{
+ LOG("card_rste_w (%s)\n", machine().describe_context());
+
+ m_card_stat &= ~(CARD_STAT_PAR | CARD_STAT_DMA);
+ m_host_stat &= ~(HOST_STAT_PAR | HOST_STAT_DMA);
+}
+
+void isa8_opus108pm_device::card_ack_w(u8 data)
+{
+ if (m_card_stat & CARD_STAT_INT)
+ {
+ LOG("card_ack_w (%s)\n", machine().describe_context());
+ m_card_stat &= ~CARD_STAT_INT;
+ m_host_stat &= ~HOST_STAT_INT;
+ m_cpu->set_input_line(INPUT_LINE_IRQ0, CLEAR_LINE);
+ }
+}
+
+void isa8_opus108pm_device::card_irq_w(u8 data)
+{
+ if (!(m_card_stat & CARD_STAT_IRQ))
+ {
+ LOG("card_irq_w (%s)\n", machine().describe_context());
+ m_card_stat |= CARD_STAT_IRQ;
+ m_host_stat |= HOST_STAT_IRQ;
+
+ if (m_card_stat & CARD_STAT_EIRQ)
+ update_isa_irq(1);
+ }
+}
+
+u8 isa8_opus108pm_device::host_stat_r()
+{
+ // HACK: diagnostic test requires changes in this host status bit, this
+ // arbitrary toggle satisfies the test but is not accurate
+ m_host_stat ^= HOST_STAT_CWT;
+
+ LOGMASKED(LOG_STAT, "host_stat_r 0x%02x (%s)\n", m_host_stat, machine().describe_context());
+ return m_host_stat;
+}
+
+void isa8_opus108pm_device::host_eirq_w(u8 data)
+{
+ if (!(m_card_stat & CARD_STAT_EIRQ))
+ {
+ LOG("host_eirq_w (%s)\n", machine().describe_context());
+ m_card_stat |= CARD_STAT_EIRQ;
+
+ if (m_card_stat & CARD_STAT_IRQ)
+ update_isa_irq(1);
+ }
+}
+
+void isa8_opus108pm_device::host_ack_w(u8 data)
+{
+ if (m_host_stat & HOST_STAT_IRQ)
+ {
+ LOG("host_ack_w (%s)\n", machine().describe_context());
+ m_card_stat &= ~CARD_STAT_IRQ;
+ m_host_stat &= ~HOST_STAT_IRQ;
+
+ update_isa_irq(0);
+ }
+}
+
+void isa8_opus108pm_device::host_int_w(u8 data)
+{
+ if (!(m_host_stat & HOST_STAT_INT))
+ {
+ LOG("host_int_w (%s)\n", machine().describe_context());
+ m_card_stat |= CARD_STAT_INT;
+ m_host_stat |= HOST_STAT_INT;
+ m_cpu->set_input_line(INPUT_LINE_IRQ0, ASSERT_LINE);
+ }
+}
+
+void isa8_opus108pm_device::host_nmi_w(u8 data)
+{
+ LOG("host_nmi_w (%s)\n", machine().describe_context());
+ m_cpu->set_input_line(INPUT_LINE_NMI, ASSERT_LINE);
+ m_cpu->set_input_line(INPUT_LINE_NMI, CLEAR_LINE);
+}
+
+void isa8_opus108pm_device::host_go_w(u8 data)
+{
+ LOG("host_go_w (%s)\n", machine().describe_context());
+
+ m_cpu->resume(SUSPEND_REASON_RESET);
+}
+
+void isa8_opus108pm_device::host_run_w(u8 data)
+{
+ LOG("host_run_w (%s)\n", machine().describe_context());
+
+ m_host_stat &= ~HOST_STAT_RUN;
+ m_cpu->resume(SUSPEND_REASON_HALT);
+}
+
+void isa8_opus108pm_device::host_rst_w(u8 data)
+{
+ LOG("host_rst_w (%s)\n", machine().describe_context());
+
+ m_card_stat &= (CARD_STAT_OPT | CARD_STAT_CPU);
+ m_host_stat = HOST_STAT_RUN;
+
+ m_cpu->reset();
+ m_fpu->reset();
+ m_mmu->reset();
+
+ m_cpu->suspend(SUSPEND_REASON_HALT, true);
+ m_cpu->suspend(SUSPEND_REASON_RESET, false);
+}
diff --git a/src/devices/bus/isa/opus100pm.h b/src/devices/bus/isa/opus100pm.h
new file mode 100644
index 00000000000..da2565762eb
--- /dev/null
+++ b/src/devices/bus/isa/opus100pm.h
@@ -0,0 +1,71 @@
+// license:BSD-3-Clause
+// copyright-holders:Patrick Mackinlay
+
+#ifndef MAME_BUS_ISA_OPUS100PM_H
+#define MAME_BUS_ISA_OPUS100PM_H
+
+#pragma once
+
+#include "cpu/ns32000/ns32000.h"
+#include "machine/ns32081.h"
+#include "machine/ns32082.h"
+#include "machine/ram.h"
+
+#include "bus/isa/isa.h"
+
+class isa8_opus108pm_device
+ : public device_t
+ , public device_isa8_card_interface
+{
+public:
+ isa8_opus108pm_device(machine_config const &mconfig, char const *tag, device_t *owner, u32 clock);
+
+protected:
+ // device_t overrides
+ virtual void device_add_mconfig(machine_config &config) override ATTR_COLD;
+ virtual ioport_constructor device_input_ports() const override ATTR_COLD;
+ virtual void device_start() override ATTR_COLD;
+ virtual void device_reset() override ATTR_COLD;
+ virtual void device_reset_after_children() override;
+
+ void map_cpu(address_map &map) ATTR_COLD;
+ void map_isa(address_map &map) ATTR_COLD;
+
+ // adapter register helpers
+ u8 card_wait_r() { return 0xb2; }
+ u8 card_stat_r();
+ void card_rste_w(u8 data);
+ void card_ack_w(u8 data);
+ void card_irq_w(u8 data);
+
+ // host register helpers
+ u8 host_stat_r();
+ void host_eirq_w(u8 data);
+ void host_ack_w(u8 data);
+ void host_int_w(u8 data);
+ void host_nmi_w(u8 data);
+ void host_go_w(u8 data);
+ void host_run_w(u8 data);
+ void host_rst_w(u8 data);
+
+ void update_isa_irq(int state);
+
+private:
+ required_device<ns32016_device> m_cpu;
+ required_device<ns32081_device> m_fpu;
+ required_device<ns32082_device> m_mmu;
+ required_device<ram_device> m_ram;
+
+ required_ioport m_base;
+ required_ioport m_irq;
+
+ bool m_installed;
+
+ u8 m_card_stat;
+ u8 m_host_stat;
+};
+
+// device type definition
+DECLARE_DEVICE_TYPE(ISA8_OPUS108PM, isa8_opus108pm_device)
+
+#endif // MAME_BUS_ISA_OPUS100PM_H
diff --git a/src/devices/bus/isa/p1_fdc.cpp b/src/devices/bus/isa/p1_fdc.cpp
index 9b62451e65a..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"
//**************************************************************************
@@ -19,10 +18,6 @@
DEFINE_DEVICE_TYPE(P1_FDC, p1_fdc_device, "p1_fdc", "Poisk-1 floppy B504")
-FLOPPY_FORMATS_MEMBER( p1_fdc_device::floppy_formats )
- FLOPPY_PC_FORMAT
-FLOPPY_FORMATS_END
-
static void poisk1_floppies(device_slot_interface &device)
{
device.option_add("525qd", FLOPPY_525_QD);
@@ -55,8 +50,8 @@ void p1_fdc_device::device_add_mconfig(machine_config &config)
FD1793(config, m_fdc, 16_MHz_XTAL / 16);
m_fdc->intrq_wr_callback().set(FUNC(p1_fdc_device::p1_fdc_irq_drq));
m_fdc->drq_wr_callback().set(FUNC(p1_fdc_device::p1_fdc_irq_drq));
- FLOPPY_CONNECTOR(config, "fdc:0", poisk1_floppies, "525qd", p1_fdc_device::floppy_formats);
- FLOPPY_CONNECTOR(config, "fdc:1", poisk1_floppies, "525qd", p1_fdc_device::floppy_formats);
+ FLOPPY_CONNECTOR(config, "fdc:0", poisk1_floppies, "525qd", floppy_image_device::default_pc_floppy_formats);
+ FLOPPY_CONNECTOR(config, "fdc:1", poisk1_floppies, "525qd", floppy_image_device::default_pc_floppy_formats);
}
//-------------------------------------------------
@@ -81,13 +76,11 @@ uint8_t p1_fdc_device::p1_wd17xx_motor_r()
uint8_t p1_fdc_device::p1_wd17xx_aux_r()
{
- cpu_device *maincpu = machine().device<cpu_device>("maincpu");
-
if (!m_fdc->drq_r() && !m_fdc->intrq_r())
{
// fake cpu wait by resetting PC one insn back
- maincpu->set_state_int(I8086_IP, maincpu->state_int(I8086_IP) - 2);
- maincpu->set_input_line(INPUT_LINE_HALT, ASSERT_LINE);
+ m_cpu->set_state_int(I8086_IP, m_cpu->state_int(I8086_IP) - 2);
+ m_isa->set_ready(ASSERT_LINE); // assert I/O CH RDY
}
return m_fdc->drq_r();
@@ -109,7 +102,8 @@ void p1_fdc_device::p1_wd17xx_aux_w(int data)
floppy_image_device *floppy1 = m_fdc->subdevice<floppy_connector>("1")->get_device();
floppy_image_device *floppy = ((data & 2) ? floppy1 : floppy0);
- if (!BIT(data, 6)) m_fdc->reset();
+ if (!BIT(data, 6))
+ m_fdc->reset();
m_fdc->set_floppy(floppy);
@@ -120,14 +114,13 @@ 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)
{
- cpu_device *maincpu = machine().device<cpu_device>("maincpu");
-
- if (state) maincpu->set_input_line(INPUT_LINE_HALT, CLEAR_LINE);
+ if (state)
+ m_isa->set_ready(CLEAR_LINE); // deassert I/O CH RDY
}
-READ8_MEMBER(p1_fdc_device::p1_fdc_r)
+uint8_t p1_fdc_device::p1_fdc_r(offs_t offset)
{
uint8_t data = 0xff;
@@ -144,7 +137,7 @@ READ8_MEMBER(p1_fdc_device::p1_fdc_r)
return data;
}
-WRITE8_MEMBER(p1_fdc_device::p1_fdc_w)
+void p1_fdc_device::p1_fdc_w(offs_t offset, uint8_t data)
{
switch (offset)
{
@@ -162,6 +155,7 @@ p1_fdc_device::p1_fdc_device(const machine_config &mconfig, const char *tag, dev
: device_t(mconfig, P1_FDC, tag, owner, clock)
, device_isa8_card_interface(mconfig, *this)
, m_fdc(*this, "fdc")
+ , m_cpu(*this, finder_base::DUMMY_TAG)
{
}
@@ -173,11 +167,9 @@ p1_fdc_device::p1_fdc_device(const machine_config &mconfig, const char *tag, dev
void p1_fdc_device::device_start()
{
set_isa_device();
- m_isa->install_rom(this, 0xe0000, 0xe07ff, "XXX", "p1_fdc");
- m_isa->install_device(0x00c0, 0x00c3,
- read8sm_delegate(FUNC(fd1793_device::read), m_fdc.target()),
- write8sm_delegate(FUNC(fd1793_device::write), m_fdc.target()));
- m_isa->install_device(0x00c4, 0x00c7, read8_delegate( FUNC(p1_fdc_device::p1_fdc_r), this ), write8_delegate( FUNC(p1_fdc_device::p1_fdc_w), this ) );
+ m_isa->install_rom(this, 0xe0000, 0xe07ff, "p1_fdc");
+ m_isa->install_device(0x00c0, 0x00c3, read8sm_delegate(*m_fdc, FUNC(fd1793_device::read)), write8sm_delegate(*m_fdc, FUNC(fd1793_device::write)));
+ m_isa->install_device(0x00c4, 0x00c7, read8sm_delegate(*this, FUNC(p1_fdc_device::p1_fdc_r)), write8sm_delegate(*this, FUNC(p1_fdc_device::p1_fdc_w)));
}
diff --git a/src/devices/bus/isa/p1_fdc.h b/src/devices/bus/isa/p1_fdc.h
index 58a4532b96d..3ddc5fa2e81 100644
--- a/src/devices/bus/isa/p1_fdc.h
+++ b/src/devices/bus/isa/p1_fdc.h
@@ -27,24 +27,26 @@ public:
// construction/destruction
p1_fdc_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
- DECLARE_READ8_MEMBER(p1_fdc_r);
- DECLARE_WRITE8_MEMBER(p1_fdc_w);
+ template <typename T>
+ void set_cpu(T &&tag) { m_cpu.set_tag(std::forward<T>(tag)); }
+
+ uint8_t p1_fdc_r(offs_t offset);
+ void p1_fdc_w(offs_t offset, uint8_t data);
protected:
// device-level overrides
- virtual void device_start() override;
- virtual void device_reset() override;
+ virtual void device_start() override ATTR_COLD;
+ virtual void device_reset() override ATTR_COLD;
// optional information overrides
- virtual void device_add_mconfig(machine_config &config) override;
- virtual const tiny_rom_entry *device_rom_region() const override;
+ virtual void device_add_mconfig(machine_config &config) override ATTR_COLD;
+ virtual const tiny_rom_entry *device_rom_region() const override ATTR_COLD;
private:
- DECLARE_FLOPPY_FORMATS(floppy_formats);
-
- 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;
public:
void p1_wd17xx_aux_w(int data);
diff --git a/src/devices/bus/isa/p1_hdc.cpp b/src/devices/bus/isa/p1_hdc.cpp
index 129c7a6ce37..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
@@ -82,7 +81,7 @@ const tiny_rom_entry *p1_hdc_device::device_rom_region() const
//**************************************************************************
-READ8_MEMBER(p1_hdc_device::p1_HDC_r)
+uint8_t p1_hdc_device::p1_HDC_r(offs_t offset)
{
uint8_t data = 0x00;
@@ -96,7 +95,7 @@ READ8_MEMBER(p1_hdc_device::p1_HDC_r)
return data;
}
-WRITE8_MEMBER(p1_hdc_device::p1_HDC_w)
+void p1_hdc_device::p1_HDC_w(offs_t offset, uint8_t data)
{
LOG("hdc W $%04x <- $%02x\n", offset, data);
@@ -126,10 +125,8 @@ p1_hdc_device::p1_hdc_device(const machine_config &mconfig, const char *tag, dev
void p1_hdc_device::device_start()
{
set_isa_device();
- m_isa->install_rom(this, 0xe2000, 0xe27ff, "XXX", "p1_hdc");
- m_isa->install_memory(0xd0000, 0xd0fff,
- READ8_DELEGATE(p1_hdc_device, p1_HDC_r),
- WRITE8_DELEGATE(p1_hdc_device, p1_HDC_w) );
+ m_isa->install_rom(this, 0xe2000, 0xe27ff, "p1_hdc");
+ m_isa->install_memory(0xd0000, 0xd0fff, read8sm_delegate(*this, FUNC(p1_hdc_device::p1_HDC_r)), write8sm_delegate(*this, FUNC(p1_hdc_device::p1_HDC_w)));
}
diff --git a/src/devices/bus/isa/p1_hdc.h b/src/devices/bus/isa/p1_hdc.h
index 65fbb801886..2f767167a91 100644
--- a/src/devices/bus/isa/p1_hdc.h
+++ b/src/devices/bus/isa/p1_hdc.h
@@ -29,12 +29,12 @@ public:
protected:
// device-level overrides
- virtual void device_start() override;
- virtual void device_reset() override;
+ virtual void device_start() override ATTR_COLD;
+ virtual void device_reset() override ATTR_COLD;
// optional information overrides
- virtual void device_add_mconfig(machine_config &config) override;
- virtual const tiny_rom_entry *device_rom_region() const override;
+ virtual void device_add_mconfig(machine_config &config) override ATTR_COLD;
+ virtual const tiny_rom_entry *device_rom_region() const override ATTR_COLD;
private:
required_device<wd2010_device> m_hdc;
@@ -42,8 +42,8 @@ private:
// uint8_t m_ram[0x800];
public:
- DECLARE_READ8_MEMBER(p1_HDC_r);
- DECLARE_WRITE8_MEMBER(p1_HDC_w);
+ uint8_t p1_HDC_r(offs_t offset);
+ void p1_HDC_w(offs_t offset, uint8_t data);
};
diff --git a/src/devices/bus/isa/p1_rom.cpp b/src/devices/bus/isa/p1_rom.cpp
index 22faf40df01..76013aca719 100644
--- a/src/devices/bus/isa/p1_rom.cpp
+++ b/src/devices/bus/isa/p1_rom.cpp
@@ -64,7 +64,7 @@ p1_rom_device::p1_rom_device(const machine_config &mconfig, const char *tag, dev
void p1_rom_device::device_start()
{
set_isa_device();
- m_isa->install_rom(this, 0xc0000, 0xc1fff, "XXX", "p1_rom");
+ m_isa->install_rom(this, 0xc0000, 0xc1fff, "p1_rom");
}
diff --git a/src/devices/bus/isa/p1_rom.h b/src/devices/bus/isa/p1_rom.h
index d5fd89662d5..7d9d566d57d 100644
--- a/src/devices/bus/isa/p1_rom.h
+++ b/src/devices/bus/isa/p1_rom.h
@@ -25,12 +25,12 @@ public:
p1_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 const tiny_rom_entry *device_rom_region() const override ATTR_COLD;
protected:
// device-level overrides
- virtual void device_start() override;
- virtual void device_reset() override;
+ virtual void device_start() override ATTR_COLD;
+ virtual void device_reset() override ATTR_COLD;
};
diff --git a/src/devices/bus/isa/p1_sound.cpp b/src/devices/bus/isa/p1_sound.cpp
index b8e37a57368..11fe4c53c43 100644
--- a/src/devices/bus/isa/p1_sound.cpp
+++ b/src/devices/bus/isa/p1_sound.cpp
@@ -6,15 +6,11 @@
Memory-mapped, uses IRQ3 and IRQ7, no DMA.
- Copyright MESS Team.
- Visit http://mamedev.org for licensing and usage restrictions.
-
**********************************************************************/
#include "emu.h"
#include "p1_sound.h"
-#include "sound/volt_reg.h"
#include "speaker.h"
@@ -67,9 +63,6 @@ void p1_sound_device::device_add_mconfig(machine_config &config)
SPEAKER(config, "speaker").front_center();
FILTER_RC(config, m_filter).add_route(ALL_OUTPUTS, "speaker", 1.0);
DAC_8BIT_R2R(config, m_dac, 0).add_route(ALL_OUTPUTS, "filter", 0.5); // unknown DAC
- voltage_regulator_device &vref(VOLTAGE_REGULATOR(config, "vref"));
- vref.add_route(0, "dac", 1.0, DAC_VREF_POS_INPUT);
- vref.add_route(0, "dac", -1.0, DAC_VREF_NEG_INPUT);
}
@@ -93,49 +86,49 @@ p1_sound_device::p1_sound_device(const machine_config &mconfig, const char *tag,
{
}
-READ8_MEMBER(p1_sound_device::d14_r)
+uint8_t p1_sound_device::d14_r(offs_t offset)
{
return m_d14->read(offset >> 1);
}
-WRITE8_MEMBER(p1_sound_device::d14_w)
+void p1_sound_device::d14_w(offs_t offset, uint8_t data)
{
m_d14->write(offset >> 1, data);
}
-READ8_MEMBER(p1_sound_device::d16_r)
+uint8_t p1_sound_device::d16_r(offs_t offset)
{
return m_d16->read(offset >> 1);
}
-WRITE8_MEMBER(p1_sound_device::d16_w)
+void p1_sound_device::d16_w(offs_t offset, uint8_t data)
{
m_d16->write(offset >> 1, data);
}
-READ8_MEMBER(p1_sound_device::d17_r)
+uint8_t p1_sound_device::d17_r(offs_t offset)
{
return m_d17->read(offset >> 1);
}
-WRITE8_MEMBER(p1_sound_device::d17_w)
+void p1_sound_device::d17_w(offs_t offset, uint8_t data)
{
m_d17->write(offset >> 1, data);
}
-READ8_MEMBER(p1_sound_device::adc_r)
+uint8_t p1_sound_device::adc_r(offs_t offset)
{
return 0;
}
-WRITE8_MEMBER(p1_sound_device::dac_w)
+void p1_sound_device::dac_w(offs_t offset, uint8_t data)
{
// logerror("DAC write: %02x <- %02x\n", offset>>1, data);
m_dac_data[offset >> 1] = 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)
{
@@ -161,28 +154,28 @@ void p1_sound_device::device_start()
// EFC00 -- ADC output
m_isa->install_memory(0xea000, 0xea01f,
- read8_delegate(FUNC(p1_sound_device::adc_r), this), // XXX not really
- write8_delegate(FUNC(p1_sound_device::dac_w), this));
+ read8sm_delegate(*this, FUNC(p1_sound_device::adc_r)), // XXX not really
+ write8sm_delegate(*this, FUNC(p1_sound_device::dac_w)));
m_isa->install_memory(0xee000, 0xee000,
- read8smo_delegate(FUNC(i8251_device::data_r), m_midi.target()),
- write8smo_delegate(FUNC(i8251_device::data_w), m_midi.target()));
+ read8smo_delegate(*m_midi, FUNC(i8251_device::data_r)),
+ write8smo_delegate(*m_midi, FUNC(i8251_device::data_w)));
m_isa->install_memory(0xee002, 0xee002,
- read8smo_delegate(FUNC(i8251_device::status_r), m_midi.target()),
- write8smo_delegate(FUNC(i8251_device::control_w), m_midi.target()));
+ read8smo_delegate(*m_midi, FUNC(i8251_device::status_r)),
+ write8smo_delegate(*m_midi, FUNC(i8251_device::control_w)));
// sync generator
m_isa->install_memory(0xef000, 0xef007,
- read8_delegate(FUNC(p1_sound_device::d14_r), this),
- write8_delegate(FUNC(p1_sound_device::d14_w), this));
+ read8sm_delegate(*this, FUNC(p1_sound_device::d14_r)),
+ write8sm_delegate(*this, FUNC(p1_sound_device::d14_w)));
// 6 music channels
m_isa->install_memory(0xef400, 0xef407,
- read8_delegate(FUNC(p1_sound_device::d16_r), this),
- write8_delegate(FUNC(p1_sound_device::d16_w), this));
+ read8sm_delegate(*this, FUNC(p1_sound_device::d16_r)),
+ write8sm_delegate(*this, FUNC(p1_sound_device::d16_w)));
m_isa->install_memory(0xef800, 0xef807,
- read8_delegate(FUNC(p1_sound_device::d17_r), this),
- write8_delegate(FUNC(p1_sound_device::d17_w), this));
+ read8sm_delegate(*this, FUNC(p1_sound_device::d17_r)),
+ write8sm_delegate(*this, FUNC(p1_sound_device::d17_w)));
}
diff --git a/src/devices/bus/isa/p1_sound.h b/src/devices/bus/isa/p1_sound.h
index e0d105300ba..54f84c07327 100644
--- a/src/devices/bus/isa/p1_sound.h
+++ b/src/devices/bus/isa/p1_sound.h
@@ -4,13 +4,10 @@
Poisk-1 sound card
- Copyright MESS Team.
- Visit http://mamedev.org for licensing and usage restrictions.
-
**********************************************************************/
-#ifndef MAME_BUS_P1_SOUND_H
-#define MAME_BUS_P1_SOUND_H
+#ifndef MAME_BUS_ISA_P1_SOUND_H
+#define MAME_BUS_ISA_P1_SOUND_H
#pragma once
@@ -33,26 +30,26 @@ public:
// construction/destruction
p1_sound_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
- DECLARE_READ8_MEMBER(d14_r);
- DECLARE_READ8_MEMBER(d16_r);
- DECLARE_READ8_MEMBER(d17_r);
- DECLARE_WRITE8_MEMBER(d14_w);
- DECLARE_WRITE8_MEMBER(d16_w);
- DECLARE_WRITE8_MEMBER(d17_w);
+ uint8_t d14_r(offs_t offset);
+ uint8_t d16_r(offs_t offset);
+ uint8_t d17_r(offs_t offset);
+ void d14_w(offs_t offset, uint8_t data);
+ void d16_w(offs_t offset, uint8_t data);
+ void d17_w(offs_t offset, uint8_t data);
- DECLARE_READ8_MEMBER(adc_r);
- DECLARE_WRITE8_MEMBER(dac_w);
+ uint8_t adc_r(offs_t offset);
+ void dac_w(offs_t offset, uint8_t data);
protected:
// device-level overrides
- virtual void device_start() override;
- virtual void device_reset() override;
+ virtual void device_start() override ATTR_COLD;
+ virtual void device_reset() override ATTR_COLD;
// Optional information overrides
- virtual void device_add_mconfig(machine_config &config) override;
+ virtual void device_add_mconfig(machine_config &config) override ATTR_COLD;
private:
- DECLARE_WRITE_LINE_MEMBER(sampler_sync);
+ void sampler_sync(int state);
uint8_t m_dac_data[16];
int m_dac_ptr;
@@ -70,4 +67,4 @@ private:
DECLARE_DEVICE_TYPE(P1_SOUND, p1_sound_device)
-#endif // MAME_BUS_P1_SOUND_H
+#endif // MAME_BUS_ISA_P1_SOUND_H
diff --git a/src/devices/bus/isa/pc1640_iga.cpp b/src/devices/bus/isa/pc1640_iga.cpp
index dfab59f2e76..96ae2da109b 100644
--- a/src/devices/bus/isa/pc1640_iga.cpp
+++ b/src/devices/bus/isa/pc1640_iga.cpp
@@ -101,8 +101,8 @@ void isa8_pc1640_iga_device::device_start()
m_plane[2] = m_videoram + 0x20000;
m_plane[3] = m_videoram + 0x30000;
- m_isa->install_rom(this, 0xc0000, 0xc7fff, "ega", "iga");
- m_isa->install_device(0x3b0, 0x3bf, read8_delegate(FUNC(isa8_ega_device::pc_ega8_3b0_r), this), write8_delegate(FUNC(isa8_ega_device::pc_ega8_3b0_w), this));
- m_isa->install_device(0x3c0, 0x3cf, read8_delegate(FUNC(isa8_ega_device::pc_ega8_3c0_r), this), write8_delegate(FUNC(isa8_ega_device::pc_ega8_3c0_w), this));
- m_isa->install_device(0x3d0, 0x3df, read8_delegate(FUNC(isa8_ega_device::pc_ega8_3d0_r), this), write8_delegate(FUNC(isa8_ega_device::pc_ega8_3d0_w), this));
+ m_isa->install_rom(this, 0xc0000, 0xc7fff, "iga");
+ m_isa->install_device(0x3b0, 0x3bf, read8sm_delegate(*this, FUNC(isa8_ega_device::pc_ega8_3b0_r)), write8sm_delegate(*this, FUNC(isa8_ega_device::pc_ega8_3b0_w)));
+ m_isa->install_device(0x3c0, 0x3cf, read8sm_delegate(*this, FUNC(isa8_ega_device::pc_ega8_3c0_r)), write8sm_delegate(*this, FUNC(isa8_ega_device::pc_ega8_3c0_w)));
+ m_isa->install_device(0x3d0, 0x3df, read8sm_delegate(*this, FUNC(isa8_ega_device::pc_ega8_3d0_r)), write8sm_delegate(*this, FUNC(isa8_ega_device::pc_ega8_3d0_w)));
}
diff --git a/src/devices/bus/isa/pc1640_iga.h b/src/devices/bus/isa/pc1640_iga.h
index 0cee53d6329..8221ce86fa2 100644
--- a/src/devices/bus/isa/pc1640_iga.h
+++ b/src/devices/bus/isa/pc1640_iga.h
@@ -29,11 +29,11 @@ public:
isa8_pc1640_iga_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 const tiny_rom_entry *device_rom_region() const override ATTR_COLD;
protected:
// device-level overrides
- virtual void device_start() override;
+ virtual void device_start() override ATTR_COLD;
};
diff --git a/src/devices/bus/isa/pcmidi.cpp b/src/devices/bus/isa/pcmidi.cpp
new file mode 100644
index 00000000000..45cc41ff4f4
--- /dev/null
+++ b/src/devices/bus/isa/pcmidi.cpp
@@ -0,0 +1,262 @@
+// license:BSD-3-Clause
+// copyright-holders:AJR
+/***************************************************************************
+
+ PC MIDI Card
+ Copyright (C) 1989 Music Quest, Inc.
+ FCC ID: IH9MQ9
+
+ This is one of several Z8681-based MIDI cards by Music Quest. Its
+ interface is more or less compatible with the Roland MPU401.
+
+****************************************************************************
+
+Music Quest PC MIDI CARD IH9MQ9 component list:
+
+C1 : 2.2uf 50v electrolytic capacitor
+C2 : 100nf tantalum capacitor
+C3 : 100nf tantalum capacitor
+C4 : 100nf tantalum capacitor
+C5 : 100nf tantalum capacitor
+C6 : 100nf tantalum capacitor
+C7 : 100nf tantalum capacitor
+C9 : 100nf tantalum capacitor
+
+D1 : diode (IN4148 ?)
+Y1 : 12,000 MHz crystal 2 pin
+
+R1 : 15K ohm resistor +-5%
+R2 : 390 ohm resistor +-5%
+
+RP1 : 10K ohm Commoned (?) resistor network 2% SIP package (code used A103GA)
+RP2 : 220 ohm Commoned (?) resistor network 2% SIP package (code used B221GA)
+
+
+
+U1 : 74LS374N
+U2 : Zilog Z8 ROMLESS MCU Z0868112PSC
+U3 : 74LS139N
+U4 : 74LS74AN
+U5 : PAL-16L8-25N - read protected , unknown code
+U6 : OTP firmware rom chip compatible with 27C512 eproms/eeproms , 64kbyte
+U7 : HYUNDAI HY611ALP-10 or compatible 2K x8bits CMOS SRAM IC
+U8 : 74LS125AN
+U9 : 74LS374N
+U10 : 74LS374N
+U11 : SHARP PC900V or compatible photocoupler
+
+***************************************************************************/
+
+#include "emu.h"
+#include "pcmidi.h"
+
+//**************************************************************************
+// GLOBAL VARIABLES
+//**************************************************************************
+
+DEFINE_DEVICE_TYPE(ISA8_PCMIDI, isa8_pcmidi_device, "isa_pcmidi", "Music Quest PC MIDI Card (IHQMQ9)")
+
+
+//**************************************************************************
+// DEVICE SETUP
+//**************************************************************************
+
+//-------------------------------------------------
+// isa8_pcmidi_device - constructor
+//-------------------------------------------------
+
+isa8_pcmidi_device::isa8_pcmidi_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock)
+ : device_t(mconfig, ISA8_PCMIDI, tag, owner, clock)
+ , device_isa8_card_interface(mconfig, *this)
+ , m_mpu(*this, "mpu")
+ , m_cmdlatch(*this, "cmdlatch")
+ , m_statlatch(*this, "statlatch")
+ , m_midiout(*this, "midiout")
+ , m_config(*this, "CONFIG")
+ , m_mpu_p3(0)
+ , m_host_irq(false)
+{
+}
+
+
+//-------------------------------------------------
+// device_start - device-specific startup
+//-------------------------------------------------
+
+void isa8_pcmidi_device::device_start()
+{
+ set_isa_device();
+
+ save_item(NAME(m_mpu_p3));
+ save_item(NAME(m_host_irq));
+}
+
+
+//-------------------------------------------------
+// device_reset - device-specific reset
+//-------------------------------------------------
+
+void isa8_pcmidi_device::device_reset()
+{
+ offs_t ioaddr = BIT(m_config->read(), 0) ? 0x300 : 0x330;
+ m_isa->install_device(ioaddr, ioaddr + 1,
+ read8sm_delegate(*this, FUNC(isa8_pcmidi_device::host_r)),
+ write8sm_delegate(*this, FUNC(isa8_pcmidi_device::host_w)));
+
+ set_host_irq(false);
+}
+
+
+//**************************************************************************
+// LATCHES AND IRQS
+//**************************************************************************
+
+//-------------------------------------------------
+// set_host_irq - update the host IRQ level
+//-------------------------------------------------
+
+void isa8_pcmidi_device::set_host_irq(bool state)
+{
+ if (m_host_irq != state)
+ {
+ m_host_irq = state;
+
+ ioport_value config = m_config->read();
+ if (!BIT(config, 1))
+ m_isa->irq3_w(state);
+ if (!BIT(config, 2))
+ m_isa->irq5_w(state);
+ if (!BIT(config, 3))
+ m_isa->irq7_w(state);
+ if (!BIT(config, 4))
+ m_isa->irq2_w(state);
+ }
+}
+
+
+//-------------------------------------------------
+// host_r - read from data or status port
+//-------------------------------------------------
+
+u8 isa8_pcmidi_device::host_r(offs_t offset)
+{
+ if (!machine().side_effects_disabled())
+ {
+ set_host_irq(false);
+ m_mpu->set_input_line(INPUT_LINE_IRQ1, ASSERT_LINE);
+ }
+ return m_statlatch->read();
+}
+
+
+//-------------------------------------------------
+// host_w - write to data or command port
+//-------------------------------------------------
+
+void isa8_pcmidi_device::host_w(offs_t offset, u8 data)
+{
+ m_cmdlatch->write(data);
+
+ // IRQs are latched and acknowledged internally
+ m_mpu->pulse_input_line(offset ? INPUT_LINE_IRQ0 : INPUT_LINE_IRQ2, attotime::zero);
+}
+
+
+//-------------------------------------------------
+// status_w - mailbox write from local processor
+//-------------------------------------------------
+
+void isa8_pcmidi_device::status_w(u8 data)
+{
+ m_statlatch->write(data);
+ if (!BIT(m_mpu_p3, 5))
+ {
+ set_host_irq(true);
+ m_mpu->set_input_line(INPUT_LINE_IRQ1, CLEAR_LINE);
+ }
+}
+
+
+//-------------------------------------------------
+// mpu_p3_w - write to output port
+//-------------------------------------------------
+
+void isa8_pcmidi_device::mpu_p3_w(u8 data)
+{
+ m_midiout->write_txd(BIT(data, 7));
+
+ // P36 = error LED output?
+
+ if (BIT(m_mpu_p3, 5) && !BIT(data, 5))
+ set_host_irq(false);
+
+ m_mpu_p3 = data;
+}
+
+
+//-------------------------------------------------
+// mpu_map - Z8681 address map
+//-------------------------------------------------
+
+void isa8_pcmidi_device::mpu_map(address_map &map)
+{
+ map(0x0000, 0x1fff).rom().region("microcode", 0);
+ map(0x6000, 0x7fff).rom().mirror(0x8000).region("microcode", 0);
+ map(0xa000, 0xa7ff).ram();
+ map(0xc000, 0xc000).mirror(0xff).r(m_cmdlatch, FUNC(generic_latch_8_device::read)).w(FUNC(isa8_pcmidi_device::status_w));
+}
+
+
+//**************************************************************************
+// DEVICE CONFIGURATION
+//**************************************************************************
+
+static INPUT_PORTS_START(isa_pcmidi)
+ PORT_START("CONFIG") // dual inline block of jumpers with idiosyncratic numbering
+ PORT_DIPNAME(0x01, 0x00, "I/O Address (P)") PORT_DIPLOCATION("J1:1")
+ PORT_DIPSETTING(0x01, "300")
+ PORT_DIPSETTING(0x00, "330")
+ PORT_DIPNAME(0x1e, 0x0e, "Interrupt") PORT_DIPLOCATION("J1:2,3,4,5")
+ PORT_DIPSETTING(0x0e, "IRQ2")
+ PORT_DIPSETTING(0x1c, "IRQ3")
+ PORT_DIPSETTING(0x1a, "IRQ5")
+ PORT_DIPSETTING(0x16, "IRQ7")
+INPUT_PORTS_END
+
+ioport_constructor isa8_pcmidi_device::device_input_ports() const
+{
+ return INPUT_PORTS_NAME(isa_pcmidi);
+}
+
+
+//-------------------------------------------------
+// device_add_mconfig - add device configuration
+//-------------------------------------------------
+
+void isa8_pcmidi_device::device_add_mconfig(machine_config &config)
+{
+ Z8681(config, m_mpu, 12_MHz_XTAL);
+ m_mpu->set_addrmap(AS_PROGRAM, &isa8_pcmidi_device::mpu_map);
+ m_mpu->p3_out_cb().set(FUNC(isa8_pcmidi_device::mpu_p3_w));
+
+ GENERIC_LATCH_8(config, m_cmdlatch);
+ GENERIC_LATCH_8(config, m_statlatch);
+
+ MIDI_PORT(config, m_midiout, midiout_slot, "midiout");
+ MIDI_PORT(config, "midiin", midiin_slot, "midiin").rxd_handler().set_inputline(m_mpu, INPUT_LINE_IRQ3).invert();
+}
+
+
+//**************************************************************************
+// ROM DEFINITION
+//**************************************************************************
+
+ROM_START(isa_pcmidi)
+ ROM_REGION(0x10000, "microcode", 0)
+ ROM_LOAD("ih9mq9_firmware_v010.bin", 0x00000, 0x10000, CRC(d4cab098) SHA1(9446c4939de557f839a74ca6fe7f41df46752e25))
+ROM_END
+
+const tiny_rom_entry *isa8_pcmidi_device::device_rom_region() const
+{
+ return ROM_NAME(isa_pcmidi);
+}
diff --git a/src/devices/bus/isa/pcmidi.h b/src/devices/bus/isa/pcmidi.h
new file mode 100644
index 00000000000..eaef7cd7bf7
--- /dev/null
+++ b/src/devices/bus/isa/pcmidi.h
@@ -0,0 +1,47 @@
+// license:BSD-3-Clause
+// copyright-holders:AJR
+
+#ifndef MAME_BUS_ISA_PCMIDI_H
+#define MAME_BUS_ISA_PCMIDI_H
+
+#pragma once
+
+#include "isa.h"
+#include "bus/midi/midi.h"
+#include "cpu/z8/z8.h"
+#include "machine/gen_latch.h"
+
+class isa8_pcmidi_device : public device_t, public device_isa8_card_interface
+{
+public:
+ isa8_pcmidi_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock);
+
+protected:
+ virtual void device_start() override ATTR_COLD;
+ virtual void device_reset() override ATTR_COLD;
+ virtual ioport_constructor device_input_ports() const override ATTR_COLD;
+ virtual void device_add_mconfig(machine_config &config) override ATTR_COLD;
+ virtual const tiny_rom_entry *device_rom_region() const override ATTR_COLD;
+
+private:
+ void set_host_irq(bool state);
+ u8 host_r(offs_t offset);
+ void host_w(offs_t offset, u8 data);
+ void status_w(u8 data);
+ void mpu_p3_w(u8 data);
+
+ void mpu_map(address_map &map) ATTR_COLD;
+
+ required_device<z8_device> m_mpu;
+ required_device<generic_latch_8_device> m_cmdlatch;
+ required_device<generic_latch_8_device> m_statlatch;
+ required_device<midi_port_device> m_midiout;
+ required_ioport m_config;
+
+ u8 m_mpu_p3;
+ bool m_host_irq;
+};
+
+DECLARE_DEVICE_TYPE(ISA8_PCMIDI, isa8_pcmidi_device)
+
+#endif // MAME_BUS_ISA_PCMIDI_H
diff --git a/src/devices/bus/isa/pds.cpp b/src/devices/bus/isa/pds.cpp
index 65a35db2b14..255d0f7dbe0 100644
--- a/src/devices/bus/isa/pds.cpp
+++ b/src/devices/bus/isa/pds.cpp
@@ -6,7 +6,7 @@
* Used to connect up to two 8-bit systems to the PC, allowing the download of assembled code directly to the
* target 8-bit system (Spectrum, CPC, MSX, C64 and maybe the BBC?)
*
- * The editor software require the ISA card to be present.
+ * The editor software requires the ISA card to be present.
*
* The PC end hardware consists of an 8-bit ISA card containing an 8255 PPI hooked up to the two connectors on the
* back of the card.
@@ -29,14 +29,14 @@ isa8_pds_device::isa8_pds_device(const machine_config &mconfig, const char *tag,
}
-READ8_MEMBER(isa8_pds_device::ppi_r)
+uint8_t isa8_pds_device::ppi_r(offs_t offset)
{
if(!(offset & 0x01))
return m_ppi->read(offset/2);
return 0xff;
}
-WRITE8_MEMBER(isa8_pds_device::ppi_w)
+void isa8_pds_device::ppi_w(offs_t offset, uint8_t data)
{
if(!(offset & 0x01))
m_ppi->write(offset/2,data);
@@ -45,7 +45,7 @@ WRITE8_MEMBER(isa8_pds_device::ppi_w)
void isa8_pds_device::device_start()
{
set_isa_device();
- m_isa->install_device(0x0300, 0x0307, read8_delegate(FUNC(isa8_pds_device::ppi_r),this), write8_delegate(FUNC(isa8_pds_device::ppi_w),this) );
+ m_isa->install_device(0x0300, 0x0307, read8sm_delegate(*this, FUNC(isa8_pds_device::ppi_r)), write8sm_delegate(*this, FUNC(isa8_pds_device::ppi_w)));
}
void isa8_pds_device::device_reset()
diff --git a/src/devices/bus/isa/pds.h b/src/devices/bus/isa/pds.h
index 5e8bf16bb88..8613d704134 100644
--- a/src/devices/bus/isa/pds.h
+++ b/src/devices/bus/isa/pds.h
@@ -19,17 +19,17 @@ class isa8_pds_device :
public:
isa8_pds_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
- DECLARE_READ8_MEMBER(ppi_r);
- DECLARE_WRITE8_MEMBER(ppi_w);
+ uint8_t ppi_r(offs_t offset);
+ void ppi_w(offs_t offset, uint8_t data);
protected:
// device-level overrides
- virtual void device_start() override;
- virtual void device_reset() override;
- virtual void device_stop() override;
+ virtual void device_start() override ATTR_COLD;
+ virtual void device_reset() override ATTR_COLD;
+ virtual void device_stop() override ATTR_COLD;
// optional information overrides
- virtual void device_add_mconfig(machine_config &config) override;
+ virtual void device_add_mconfig(machine_config &config) override ATTR_COLD;
required_device<i8255_device> m_ppi;
};
diff --git a/src/devices/bus/isa/pgc.cpp b/src/devices/bus/isa/pgc.cpp
index 9e65cd819d0..1a67e545378 100644
--- a/src/devices/bus/isa/pgc.cpp
+++ b/src/devices/bus/isa/pgc.cpp
@@ -16,7 +16,7 @@
http://www.seasip.info/VintagePC/pgc.html
To do:
- - pass IBM diagnostics (currently fail with code 3905)
+ - pass IBM diagnostics (currently fail with code 3905 - 'Cold start cycle power error')
- CGA emulator
- what's up with irq 3 (= vblank irq)? (causes soft reset)
- "test pin of the microprocessor samples the hsync pulse"
@@ -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)
@@ -71,8 +70,6 @@ ROM_START( pgc )
ROMX_LOAD("pgc_u44.bin", 0x00000, 0x8000, CRC(71280241) SHA1(7042ccd4ebd03f576a256a433b8aa38d1b4fefa8), ROM_BIOS(1))
ROMX_LOAD("pgc_u43.bin", 0x08000, 0x8000, CRC(923f5ea3) SHA1(2b2a55d64b20d3a613b00c51443105aa03eca5d6), ROM_BIOS(1))
- ROM_REGION(0x800, "commarea", ROMREGION_ERASE00)
-
ROM_REGION(0x1000, "chargen", 0)
ROM_LOAD("pgc_u27.bin", 0x0000, 0x1000, CRC(6be256cc) SHA1(deb1195886268dcddce10459911e020f7a9f74f7))
ROM_END
@@ -113,7 +110,7 @@ void isa8_pgc_device::pgc_map(address_map &map)
map(0x08000, 0x0ffff).rom().region("maincpu", 0x8000);
map(0x10000, 0x1001f).rw(FUNC(isa8_pgc_device::stateparam_r), FUNC(isa8_pgc_device::stateparam_w));
// map(0x18000, 0x18fff).ram(); // ??
- map(0x28000, 0x287ff).ram().region("commarea", 0).mirror(0x800);
+ map(0x28000, 0x287ff).ram().share("commarea").mirror(0x800);
map(0x32001, 0x32001).nopw();
map(0x32020, 0x3203f).w(FUNC(isa8_pgc_device::accel_w));
map(0x3c000, 0x3c001).r(FUNC(isa8_pgc_device::init_r));
@@ -210,7 +207,8 @@ isa8_pgc_device::isa8_pgc_device(const machine_config &mconfig, device_type type
m_cpu(*this, "maincpu"),
m_screen(*this, PGC_SCREEN_NAME),
m_palette(*this, "palette"),
- m_commarea(nullptr), m_vram(nullptr), m_eram(nullptr)
+ m_commarea(*this, "commarea"),
+ m_vram(nullptr), m_eram(nullptr)
{
}
@@ -246,16 +244,15 @@ void isa8_pgc_device::device_reset()
memset(m_lut, 0, sizeof(m_lut));
m_accel = 0;
- m_commarea = memregion("commarea")->base();
if (BIT(ioport("DSW")->read(), 1))
- m_isa->install_bank(0xc6400, 0xc67ff, "commarea", m_commarea);
+ m_isa->install_bank(0xc6400, 0xc67ff, m_commarea);
else
- m_isa->install_bank(0xc6000, 0xc63ff, "commarea", m_commarea);
+ m_isa->install_bank(0xc6000, 0xc63ff, m_commarea);
}
//
-WRITE_LINE_MEMBER(isa8_pgc_device::vblank_irq)
+void isa8_pgc_device::vblank_irq(int state)
{
if (state)
{
@@ -273,7 +270,7 @@ IRQ_CALLBACK_MEMBER(isa8_pgc_device::irq_callback)
// memory handlers
-READ8_MEMBER(isa8_pgc_device::vram_r)
+uint8_t isa8_pgc_device::vram_r(offs_t offset)
{
uint8_t ret;
@@ -293,7 +290,7 @@ READ8_MEMBER(isa8_pgc_device::vram_r)
* 9 - write up to 5 pixel groups, ending at offset. offset may be in the middle of pixel group.
* 13 - write up to 5 pixel groups, starting at offset.
*/
-WRITE8_MEMBER(isa8_pgc_device::vram_w)
+void isa8_pgc_device::vram_w(offs_t offset, uint8_t data)
{
bool handled = true;
@@ -336,13 +333,13 @@ WRITE8_MEMBER(isa8_pgc_device::vram_w)
handled ? "" : " (unsupported)");
}
-WRITE8_MEMBER(isa8_pgc_device::accel_w)
+void isa8_pgc_device::accel_w(offs_t offset, uint8_t data)
{
m_accel = offset >> 1;
LOGV("accel @ %05x <- %02x (%d)\n", 0x32020 + offset, data, m_accel);
}
-READ8_MEMBER(isa8_pgc_device::stateparam_r)
+uint8_t isa8_pgc_device::stateparam_r(offs_t offset)
{
uint8_t ret;
@@ -354,7 +351,7 @@ READ8_MEMBER(isa8_pgc_device::stateparam_r)
return ret;
}
-WRITE8_MEMBER(isa8_pgc_device::stateparam_w)
+void isa8_pgc_device::stateparam_w(offs_t offset, uint8_t data)
{
if ((machine().debug_flags & DEBUG_FLAG_ENABLED) != 0)
{
@@ -363,7 +360,7 @@ WRITE8_MEMBER(isa8_pgc_device::stateparam_w)
m_stateparam[offset >> 1] = data;
}
-WRITE8_MEMBER(isa8_pgc_device::lut_w)
+void isa8_pgc_device::lut_w(offs_t offset, uint8_t data)
{
uint8_t o = (offset >> 1) * 3;
@@ -379,32 +376,32 @@ WRITE8_MEMBER(isa8_pgc_device::lut_w)
}
}
-READ8_MEMBER(isa8_pgc_device::init_r)
+uint8_t isa8_pgc_device::init_r()
{
- LOG("INIT: unmapping ROM\n");
- space.unmap_read(0xf8000, 0xfffff);
+ if (!machine().side_effects_disabled())
+ {
+ address_space &space = m_cpu->space(AS_PROGRAM);
- LOG("INIT: mapping emulator RAM\n");
- space.install_readwrite_bank(0xf8000, 0xfffff, "eram");
- membank("eram")->set_base(m_eram.get());
+ LOG("INIT: unmapping ROM\n");
+ space.unmap_read(0xf8000, 0xfffff);
- LOG("INIT: mapping LUT\n");
- space.install_write_handler(0xf8400, 0xf85ff,
- write8_delegate(FUNC(isa8_pgc_device::lut_w), this));
+ LOG("INIT: mapping emulator RAM\n");
+ space.install_ram(0xf8000, 0xfffff, m_eram.get());
+
+ LOG("INIT: mapping LUT\n");
+ space.install_write_handler(0xf8400, 0xf85ff, write8sm_delegate(*this, FUNC(isa8_pgc_device::lut_w)));
+ }
return 0; // XXX ignored
}
uint32_t isa8_pgc_device::screen_update(screen_device &screen, bitmap_ind16 &bitmap, const rectangle &cliprect)
{
- uint16_t *p;
- uint8_t *v;
-
for (int y = 0; y < PGC_DISP_VERT; y++)
{
// XXX address translation happens in hardware
- v = &m_vram[y * 1024];
- p = &bitmap.pix16(y + PGC_VERT_START, PGC_HORZ_START);
+ uint8_t const *v = &m_vram[y * 1024];
+ uint16_t *p = &bitmap.pix(y + PGC_VERT_START, PGC_HORZ_START);
for (int x = 0; x < PGC_DISP_HORZ; x++)
{
diff --git a/src/devices/bus/isa/pgc.h b/src/devices/bus/isa/pgc.h
index a022812cd52..f08d613ceba 100644
--- a/src/devices/bus/isa/pgc.h
+++ b/src/devices/bus/isa/pgc.h
@@ -30,38 +30,38 @@ protected:
isa8_pgc_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_start() override ATTR_COLD;
+ virtual void device_reset() override ATTR_COLD;
// 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 void device_add_mconfig(machine_config &config) override ATTR_COLD;
+ virtual const tiny_rom_entry *device_rom_region() const override ATTR_COLD;
+ virtual ioport_constructor device_input_ports() const override ATTR_COLD;
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);
- DECLARE_WRITE8_MEMBER(vram_w);
- DECLARE_READ8_MEMBER(vram_r);
- DECLARE_WRITE8_MEMBER(stateparam_w);
- DECLARE_READ8_MEMBER(stateparam_r);
- DECLARE_WRITE8_MEMBER(lut_w);
- DECLARE_READ8_MEMBER(init_r);
- DECLARE_WRITE8_MEMBER(accel_w);
+ void vram_w(offs_t offset, uint8_t data);
+ uint8_t vram_r(offs_t offset);
+ void stateparam_w(offs_t offset, uint8_t data);
+ uint8_t stateparam_r(offs_t offset);
+ void lut_w(offs_t offset, uint8_t data);
+ uint8_t init_r();
+ void accel_w(offs_t offset, uint8_t data);
void reset_common();
- void pgc_io(address_map &map);
- void pgc_map(address_map &map);
+ void pgc_io(address_map &map) ATTR_COLD;
+ void pgc_map(address_map &map) ATTR_COLD;
required_device<i8088_cpu_device> m_cpu;
required_device<screen_device> m_screen;
required_device<palette_device> m_palette;
+ required_shared_ptr<uint8_t> m_commarea;
- uint8_t *m_commarea;
std::unique_ptr<uint8_t[]> m_vram;
std::unique_ptr<uint8_t[]> m_eram;
uint8_t m_stateparam[16];
diff --git a/src/devices/bus/isa/prose4k1.cpp b/src/devices/bus/isa/prose4k1.cpp
new file mode 100644
index 00000000000..abaadbc6a96
--- /dev/null
+++ b/src/devices/bus/isa/prose4k1.cpp
@@ -0,0 +1,92 @@
+// license:BSD-3-Clause
+// copyright-holders:Vas Crabb
+/*
+ Speech Plus Prose 4001 speech synthesiser
+
+ Full-length ISA card. Supports operation in IBM PC mode (as an ISA bus
+ card) and standalone mode (controlled over a seria connection). The
+ example the ROMs were dumped from had many components unpopulated.
+
+ Major components include:
+ * Siemens 80188-N CPU
+ * NEC D77P20 DSP with EPROM memory
+ * Three TI 27C512 EPROMS
+ * 256 kbit SRAM
+ * Intel P8251A UART
+ * Three banks of eight DIP switches
+ */
+#include "emu.h"
+#include "prose4k1.h"
+
+#include "cpu/i86/i186.h"
+#include "machine/i8251.h"
+
+
+namespace {
+
+class prose4k1_device : public device_t, public device_isa8_card_interface
+{
+public:
+ static constexpr feature_type unemulated_features() { return feature::SOUND; }
+
+ prose4k1_device(machine_config const &mconfig, char const *tag, device_t *owner, u32 clock) :
+ device_t(mconfig, ISA8_PROSE4001, tag, owner, clock),
+ device_isa8_card_interface(mconfig, *this)
+ {
+ }
+
+protected:
+ // device_t implementation
+ virtual tiny_rom_entry const *device_rom_region() const override ATTR_COLD;
+ virtual void device_add_mconfig(machine_config &config) override ATTR_COLD;
+ virtual void device_start() override ATTR_COLD;
+
+private:
+ void main_map(address_map &map) ATTR_COLD;
+};
+
+
+ROM_START(prose4k1)
+ ROM_REGION(0x3'0000, "u8", 0)
+ ROM_LOAD("v3.4.1_pr4001.u3", 0x0'0000, 0x1'0000, CRC(12dac3ed) SHA1(cf8c0b9de1f00facbc5cb5dc8e2dcbb09d6ff479)) // TMS27C512, printed label
+ ROM_LOAD("v3.4.1_pr4001.u2", 0x1'0000, 0x1'0000, CRC(2ee241b7) SHA1(35b81f3b4deb552511f8d8f2d0aac9100fdee49d)) // TMS27C512, printed label
+ ROM_LOAD("v3.4.1_pr4001.u1", 0x2'0000, 0x1'0000, CRC(559f4950) SHA1(5c8709c82dadaea7012859c20141ef8f59d5e473)) // TMS27C512, handwritten label
+
+ ROM_REGION32_BE(0x0800, "dsp:prg", 0) // 512*23-bit words
+ ROM_LOAD("v3.12_5_04_90.prg", 0x0000, 0x0800, NO_DUMP)
+
+ ROM_REGION16_BE(0x0400, "dsp:dat", 0) // 512*13-bit words
+ ROM_LOAD("v3.12_5_04_90.dat", 0x0000, 0x0400, NO_DUMP)
+ROM_END
+
+
+tiny_rom_entry const *prose4k1_device::device_rom_region() const
+{
+ return ROM_NAME(prose4k1);
+}
+
+
+void prose4k1_device::device_add_mconfig(machine_config &config)
+{
+ I80188(config, "u8", 8'000'000).set_addrmap(AS_PROGRAM, &prose4k1_device::main_map); // TODO: measure clock
+
+ I8251(config, "u27", 0);
+}
+
+
+void prose4k1_device::device_start()
+{
+}
+
+
+void prose4k1_device::main_map(address_map &map)
+{
+ map(0x0'0000, 0x0'8000).ram();
+
+ map(0xd'0000, 0xf'ffff).rom().region("u8", 0x0'0000);
+}
+
+} // anonymous namespace
+
+
+DEFINE_DEVICE_TYPE_PRIVATE(ISA8_PROSE4001, device_isa8_card_interface, prose4k1_device, "isa_prose4001", "Speech Plus Prose 4001 (IBM PC mode)")
diff --git a/src/devices/bus/isa/prose4k1.h b/src/devices/bus/isa/prose4k1.h
new file mode 100644
index 00000000000..38ecab6e67b
--- /dev/null
+++ b/src/devices/bus/isa/prose4k1.h
@@ -0,0 +1,13 @@
+// license:BSD-3-Clause
+// copyright-holders:Vas Crabb
+#ifndef MAME_BUS_ISA_PROSE4K1_H
+#define MAME_BUS_ISA_PROSE4K1_H
+
+#pragma once
+
+#include "isa.h"
+
+
+DECLARE_DEVICE_TYPE(ISA8_PROSE4001, device_isa8_card_interface)
+
+#endif // MAME_BUS_ISA_PROSE4K1_H
diff --git a/src/devices/bus/isa/s3virge.cpp b/src/devices/bus/isa/s3virge.cpp
deleted file mode 100644
index 5dae6c8afa2..00000000000
--- a/src/devices/bus/isa/s3virge.cpp
+++ /dev/null
@@ -1,993 +0,0 @@
-// license:BSD-3-Clause
-// copyright-holders:Barry Rodewald
-/*
- * s3virge.c
- *
- * 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)
-{
-}
-
-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();
-
- int x;
- int i;
- for (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 = read8_delegate(); //read_dipswitch;
- vga.svga_intf.seq_regcount = 0x1c;
- vga.svga_intf.crtc_regcount = 0x19;
- vga.svga_intf.vram_size = 0x400000;
- vga.memory.resize(vga.svga_intf.vram_size);
- memset(&vga.memory[0], 0, vga.svga_intf.vram_size);
- save_item(vga.memory,"Video RAM");
- save_pointer(vga.crtc.data,"CRTC Registers",0x100);
- save_pointer(vga.sequencer.data,"Sequencer Registers",0x100);
- save_pointer(vga.attribute.data,"Attribute Registers", 0x15);
-
- m_vblank_timer = machine().scheduler().timer_alloc(timer_expired_delegate(FUNC(vga_device::vblank_timer_cb),this));
-
- memset(&s3, 0, sizeof(s3));
- memset(&s3virge, 0, sizeof(s3virge));
- s3virge.linear_address = 0x70000000;
- // Initialise hardware graphics cursor colours, Windows 95 doesn't touch the registers for some reason
- for(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;
-}
-
-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.rgb32_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.rgb32_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.rgb32_en = 0;
- }
- if(s3.cr43 & 0x80) // Horizontal clock doubling (techincally, 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);
- 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);
- break;
- case 0x4d:
- s3.cursor_start_addr = (s3.cursor_start_addr & 0xff00) | data;
- 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:
- 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;
- }
- LOGREG("CR58: write %02x\n", data);
- break;
- case 0x59:
- s3virge.linear_address = (s3virge.linear_address & 0x00ff0000) | (data << 24);
- LOGREG("Linear framebuffer address = %08x\n",s3virge.linear_address);
- break;
- case 0x5a:
- s3virge.linear_address = (s3virge.linear_address & 0xff000000) | (data << 16);
- LOGREG("Linear framebuffer address = %08x\n",s3virge.linear_address);
- 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;
- }
- }
-}
-
-
-READ8_MEMBER(s3virge_vga_device::port_03b0_r)
-{
- 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(space,offset,mem_mask);
- break;
- }
- }
-
- return res;
-}
-
-WRITE8_MEMBER(s3virge_vga_device::port_03b0_w)
-{
- 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(space,offset,data,mem_mask);
- break;
- }
- }
-}
-
-READ8_MEMBER(s3virge_vga_device::port_03c0_r)
-{
- uint8_t res;
-
- switch(offset)
- {
- default:
- res = s3_vga_device::port_03c0_r(space,offset,mem_mask);
- break;
- }
-
- return res;
-}
-
-WRITE8_MEMBER(s3virge_vga_device::port_03c0_w)
-{
- switch(offset)
- {
- default:
- s3_vga_device::port_03c0_w(space,offset,data,mem_mask);
- break;
- }
-}
-
-READ8_MEMBER(s3virge_vga_device::port_03d0_r)
-{
- 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(space,offset,mem_mask);
- break;
- }
- }
-
- return res;
-}
-
-WRITE8_MEMBER(s3virge_vga_device::port_03d0_w)
-{
- 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(space,offset,data,mem_mask);
- break;
- }
- }
-}
-
-READ8_MEMBER(s3virge_vga_device::mem_r)
-{
- if (svga.rgb8_en || svga.rgb15_en || svga.rgb16_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(space,offset,mem_mask);
- else
- return 0xff;
-}
-
-WRITE8_MEMBER(s3virge_vga_device::mem_w)
-{
- // 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(space,offset,data,mem_mask);
-}
-
-READ8_MEMBER(s3virge_vga_device::fb_r)
-{
- if(offset < s3virge.linear_address_size_full)
- return vga.memory[offset % vga.svga_intf.vram_size];
- return 0xff;
-}
-
-WRITE8_MEMBER(s3virge_vga_device::fb_w)
-{
- if(offset < s3virge.linear_address_size_full)
- vga.memory[offset % vga.svga_intf.vram_size] = data;
-}
-
-// 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
-
-
-READ32_MEMBER(s3virge_vga_device::s3d_sub_status_r)
-{
- return 0x00003000; // S3D engine idle, all FIFO slots free
-}
-
-WRITE32_MEMBER(s3virge_vga_device::s3d_sub_control_w)
-{
- s3virge.interrupt_enable = data & 0x00003f80;
- // TODO: bits 14-15==10 - reset engine
- LOGMMIO("Sub control = %08x\n", data);
-}
-
-READ32_MEMBER(s3virge_vga_device::s3d_register_r)
-{
- uint32_t res = 0;
- int op_type = (((offset*4) & 0x0f00) / 4) - 1;
-
- switch(offset)
- {
- case 0x4d4/4:
- case 0x8d4/4:
- case 0xcd4/4:
- res = s3virge.s3d.src_base[op_type];
- break;
- case 0xad8/4:
- case 0x8d8/4:
- case 0xcd8/4:
- res = s3virge.s3d.dest_base[op_type];
- break;
- case 0x500/4:
- case 0x900/4:
- case 0xd00/4:
- res = s3virge.s3d.command[op_type];
- break;
- case 0x504/4:
- res = s3virge.s3d.rect_height[op_type];
- res |= (s3virge.s3d.rect_width[op_type] << 16);
- break;
- case 0x508/4:
- res = s3virge.s3d.source_y[op_type];
- res |= (s3virge.s3d.source_x[op_type] << 16);
- break;
- case 0x50c/4:
- res = s3virge.s3d.dest_y[op_type];
- res |= (s3virge.s3d.dest_x[op_type] << 16);
- break;
- default:
- res = 0xffffffff;
- LOGMMIO("MMIO unknown/unused register read MM%04X\n", (offset*4)+0xa000);
- }
-
- return res;
-}
-
-WRITE32_MEMBER(s3virge_vga_device::s3d_register_w)
-{
- int op_type = (((offset*4) & 0x0f00) / 4) - 1;
-
- switch(offset)
- {
- case 0x4d4/4:
- case 0x8d4/4:
- case 0xcd4/4:
- s3virge.s3d.src_base[op_type] = data;
- LOGMMIO("MM%04X: Source Base = %08x\n", (offset*4)+0xa000, data);
- break;
- case 0xad8/4:
- case 0x8d8/4:
- case 0xcd8/4:
- s3virge.s3d.dest_base[op_type] = data;
- LOGMMIO("MM%04X: Destination base address = %08x\n", (offset*4)+0xa000, data);
- break;
- case 0x500/4:
- s3virge.s3d.command[OP_BITBLT] = data;
- // TODO:if bit 0 is reset, then execute now
- LOGMMIO("MM%04X: Command [BitBLT/FilledRect] = %08x\n", (offset*4)+0xa000, data);
- break;
- case 0x900/4:
- s3virge.s3d.command[OP_2DLINE] = data;
- // TODO:if bit 0 is reset, then execute now
- LOGMMIO("MM%04X: Command [2D Line] = %08x\n", (offset*4)+0xa000, data);
- break;
- case 0xd00/4:
- s3virge.s3d.command[OP_2DPOLY] = data;
- // TODO:if bit 0 is reset, then execute now
- LOGMMIO("MM%04X: Command [2D Polygon] = %08x\n", (offset*4)+0xa000, data);
- break;
- case 0x504/4:
- s3virge.s3d.rect_height[OP_BITBLT] = data & 0x000003ff;
- s3virge.s3d.rect_width[OP_BITBLT] = (data & 0x03ff0000) >> 16;
- LOGMMIO("MM%04X: Rectangle Width/Height = %08x (%ix%i)\n", (offset*4)+0xa000, data, s3virge.s3d.rect_width[OP_BITBLT], s3virge.s3d.rect_height[OP_BITBLT]);
- break;
- case 0x508/4:
- s3virge.s3d.source_y[OP_BITBLT] = data & 0x000003ff;
- s3virge.s3d.source_x[OP_BITBLT] = (data & 0x03ff0000) >> 16;
- LOGMMIO("MM%04X: Rectangle Source X/Y = %08x (%i, %i)\n",(offset*4)+0xa000, data, s3virge.s3d.source_x[OP_BITBLT], s3virge.s3d.source_y[OP_BITBLT]);
- break;
- case 0x50c/4:
- s3virge.s3d.dest_y[OP_BITBLT] = data & 0x000003ff;
- s3virge.s3d.dest_x[OP_BITBLT] = (data & 0x03ff0000) >> 16;
- // TODO:if previous command has bit 0 set, then execute here
- LOGMMIO("MM%04X: Rectangle Destination X/Y = %08x (%i, %i)\n", (offset*4)+0xa000, data, s3virge.s3d.dest_x[OP_BITBLT], s3virge.s3d.dest_y[OP_BITBLT]);
- break;
- default:
- LOGMMIO("MMIO unknown/unused register write MM%04X = %08x\n", (offset*4)+0xa000, data);
- }
-}
-
diff --git a/src/devices/bus/isa/s3virge.h b/src/devices/bus/isa/s3virge.h
deleted file mode 100644
index 649910dcce8..00000000000
--- a/src/devices/bus/isa/s3virge.h
+++ /dev/null
@@ -1,140 +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);
-
- virtual READ8_MEMBER(port_03b0_r) override;
- virtual WRITE8_MEMBER(port_03b0_w) override;
- virtual READ8_MEMBER(port_03c0_r) override;
- virtual WRITE8_MEMBER(port_03c0_w) override;
- virtual READ8_MEMBER(port_03d0_r) override;
- virtual WRITE8_MEMBER(port_03d0_w) override;
- virtual READ8_MEMBER(mem_r) override;
- virtual WRITE8_MEMBER(mem_w) override;
-
- DECLARE_READ8_MEMBER(fb_r);
- DECLARE_WRITE8_MEMBER(fb_w);
- DECLARE_READ32_MEMBER(s3d_sub_status_r);
- DECLARE_WRITE32_MEMBER(s3d_sub_control_w);
-
- DECLARE_READ32_MEMBER(s3d_register_r);
- DECLARE_WRITE32_MEMBER(s3d_register_w);
-
- 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; }
- bool is_linear_address_active() { return s3virge.linear_address_enable; }
- bool is_new_mmio_active() { return s3.cr53 & 0x08; }
-
- ibm8514a_device* get_8514() { fatalerror("s3virge requested non-existant 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;
-
- enum
- {
- LAW_64K = 0,
- LAW_1MB,
- LAW_2MB,
- LAW_4MB
- };
-
- enum
- {
- OP_BITBLT = 0,
- OP_2DLINE,
- OP_2DPOLY,
- OP_3DLINE,
- OP_3DTRI
- };
-
- 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
- {
- uint32_t src_base[5];
- uint32_t dest_base[5];
- uint32_t command[5];
- uint16_t source_x[5];
- uint16_t source_y[5];
- uint16_t dest_x[5];
- uint16_t dest_y[5];
- uint16_t rect_width[5];
- uint16_t rect_height[5];
- } s3d;
- } s3virge;
-
-private:
- 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/sb16.cpp b/src/devices/bus/isa/sb16.cpp
index 6bce4b4198c..b260edca7b9 100644
--- a/src/devices/bus/isa/sb16.cpp
+++ b/src/devices/bus/isa/sb16.cpp
@@ -14,7 +14,7 @@
DEFINE_DEVICE_TYPE(ISA16_SB16, sb16_lle_device, "sb16", "SoundBlaster 16 Audio Adapter LLE")
-READ8_MEMBER( sb16_lle_device::dsp_data_r )
+uint8_t sb16_lle_device::dsp_data_r()
{
if(!machine().side_effects_disabled())
m_data_in = false;
@@ -22,18 +22,18 @@ READ8_MEMBER( sb16_lle_device::dsp_data_r )
return m_in_byte;
}
-WRITE8_MEMBER( sb16_lle_device::dsp_data_w )
+void sb16_lle_device::dsp_data_w(uint8_t data)
{
m_data_out = true;
m_out_byte = data;
}
-READ8_MEMBER( sb16_lle_device::dac_ctrl_r )
+uint8_t sb16_lle_device::dac_ctrl_r()
{
return 0;
}
-WRITE8_MEMBER( sb16_lle_device::dac_ctrl_w )
+void sb16_lle_device::dac_ctrl_w(uint8_t data)
{
/* port 0x05
* bit0 -
@@ -52,18 +52,18 @@ WRITE8_MEMBER( sb16_lle_device::dac_ctrl_w )
}
}
-READ8_MEMBER( sb16_lle_device::adc_data_r )
+uint8_t sb16_lle_device::adc_data_r()
{
return 0;
}
-WRITE8_MEMBER( sb16_lle_device::dac_data_w )
+void sb16_lle_device::dac_data_w(uint8_t data)
{
m_ldac->write(data << 8);
m_rdac->write(data << 8);
}
-READ8_MEMBER( sb16_lle_device::p1_r )
+uint8_t sb16_lle_device::p1_r()
{
uint8_t ret = 0;
ret |= m_data_out << 0;
@@ -71,7 +71,7 @@ READ8_MEMBER( sb16_lle_device::p1_r )
return ret;
}
-WRITE8_MEMBER( sb16_lle_device::p1_w )
+void sb16_lle_device::p1_w(uint8_t data)
{
/* port P1
* bit0 - output byte ready
@@ -85,12 +85,12 @@ WRITE8_MEMBER( sb16_lle_device::p1_w )
*/
}
-READ8_MEMBER( sb16_lle_device::p2_r )
+uint8_t sb16_lle_device::p2_r()
{
return 0;
}
-WRITE8_MEMBER( sb16_lle_device::p2_w )
+void sb16_lle_device::p2_w(uint8_t data)
{
/* port P2
* bit0 -
@@ -115,25 +115,25 @@ void sb16_lle_device::control_timer(bool start)
m_timer->adjust(attotime::never);
}
-WRITE8_MEMBER( sb16_lle_device::rate_w )
+void sb16_lle_device::rate_w(uint8_t data)
{
m_freq = data;
if(!(m_ctrl8 & 2) || !(m_ctrl16 & 2))
control_timer(true);
}
-READ8_MEMBER( sb16_lle_device::dma8_r )
+uint8_t sb16_lle_device::dma8_r()
{
return m_dac_fifo[0].b[0];
}
-WRITE8_MEMBER( sb16_lle_device::dma8_w )
+void sb16_lle_device::dma8_w(uint8_t data)
{
m_adc_fifo[0].b[0] = data;
m_isa->drq1_w(0);
}
-READ8_MEMBER( sb16_lle_device::dma_stat_r )
+uint8_t sb16_lle_device::dma_stat_r()
{
/* port 0x06
* bit0 - 8 bit complete
@@ -149,12 +149,12 @@ READ8_MEMBER( sb16_lle_device::dma_stat_r )
return ret;
}
-READ8_MEMBER( sb16_lle_device::ctrl8_r )
+uint8_t sb16_lle_device::ctrl8_r()
{
return m_ctrl8;
}
-WRITE8_MEMBER( sb16_lle_device::ctrl8_w )
+void sb16_lle_device::ctrl8_w(uint8_t data)
{
/* port 0x08
* bit0 - ?
@@ -163,12 +163,15 @@ WRITE8_MEMBER( sb16_lle_device::ctrl8_w )
* bit3 -
* bit4 -
* bit5 -
- * bit6 - ?
+ * bit6 - ? (wolf3d)
* bit7 - toggle for 8bit irq
*/
if(data & 4)
{
m_dma8_cnt = m_dma8_len;
+ if (!(BIT(m_mode, 6)))
+ m_dma8_cnt >>= 1;
+ m_dma8_cnt ++;
m_dma8_done = false;
}
if(!(data & 2) || !(m_ctrl16 & 2))
@@ -190,12 +193,12 @@ WRITE8_MEMBER( sb16_lle_device::ctrl8_w )
m_ctrl8 = data;
}
-READ8_MEMBER( sb16_lle_device::ctrl16_r )
+uint8_t sb16_lle_device::ctrl16_r()
{
return m_ctrl16;
}
-WRITE8_MEMBER( sb16_lle_device::ctrl16_w )
+void sb16_lle_device::ctrl16_w(uint8_t data)
{
/* port 0x10
* bit0 -
@@ -210,6 +213,9 @@ WRITE8_MEMBER( sb16_lle_device::ctrl16_w )
if(data & 4)
{
m_dma16_cnt = m_dma16_len;
+ if (!(BIT(m_mode, 7)))
+ m_dma16_cnt >>= 1;
+ m_dma16_cnt ++;
m_dma16_done = false;
}
if(!(data & 2) || !(m_ctrl8 & 2))
@@ -231,16 +237,16 @@ WRITE8_MEMBER( sb16_lle_device::ctrl16_w )
m_ctrl16 = data;
}
-READ8_MEMBER( sb16_lle_device::dac_fifo_ctrl_r )
+uint8_t sb16_lle_device::dac_fifo_ctrl_r()
{
return m_dac_fifo_ctrl;
}
-WRITE8_MEMBER( sb16_lle_device::dac_fifo_ctrl_w )
+void sb16_lle_device::dac_fifo_ctrl_w(uint8_t data)
{
/* port 0x0E
* bit0 - reset fifo
- * bit1 - ?
+ * bit1 - DAC output sw off?
* bit2 - disable fifo
* bit3 -
* bit4 -
@@ -255,15 +261,16 @@ WRITE8_MEMBER( sb16_lle_device::dac_fifo_ctrl_w )
m_dac_r = false;
m_dac_h = false;
}
+ m_mixer->dac_speaker_off_cb(BIT(data, 1));
m_dac_fifo_ctrl = data;
}
-READ8_MEMBER( sb16_lle_device::adc_fifo_ctrl_r )
+uint8_t sb16_lle_device::adc_fifo_ctrl_r()
{
return m_adc_fifo_ctrl;
}
-WRITE8_MEMBER( sb16_lle_device::adc_fifo_ctrl_w )
+void sb16_lle_device::adc_fifo_ctrl_w(uint8_t data)
{
/* port 0x16
* bit0 - reset fifo
@@ -285,12 +292,12 @@ WRITE8_MEMBER( sb16_lle_device::adc_fifo_ctrl_w )
m_adc_fifo_ctrl = data;
}
-READ8_MEMBER( sb16_lle_device::mode_r )
+uint8_t sb16_lle_device::mode_r()
{
return m_mode;
}
-WRITE8_MEMBER( sb16_lle_device::mode_w )
+void sb16_lle_device::mode_w(uint8_t data)
{
/* port 0x04
* bit0 - 1 -- dac 16, adc 8; 0 -- adc 16, dac 8
@@ -305,7 +312,7 @@ WRITE8_MEMBER( sb16_lle_device::mode_w )
m_mode = data;
}
-READ8_MEMBER( sb16_lle_device::dma8_ready_r )
+uint8_t sb16_lle_device::dma8_ready_r()
{
/* port 0x0F
* bit0 -
@@ -320,7 +327,7 @@ READ8_MEMBER( sb16_lle_device::dma8_ready_r )
return ((m_dac_fifo_tail - m_dac_fifo_head) != 1) << 6;
}
-READ8_MEMBER( sb16_lle_device::adc_data_ready_r )
+uint8_t sb16_lle_device::adc_data_ready_r()
{
/* port 0x17
* bit0 -
@@ -335,32 +342,32 @@ READ8_MEMBER( sb16_lle_device::adc_data_ready_r )
return (m_mode & 1) ? 0x80 : 0;
}
-READ8_MEMBER( sb16_lle_device::dma8_cnt_lo_r )
+uint8_t sb16_lle_device::dma8_cnt_lo_r()
{
return m_dma8_cnt & 0xff;
}
-READ8_MEMBER( sb16_lle_device::dma8_cnt_hi_r )
+uint8_t sb16_lle_device::dma8_cnt_hi_r()
{
return m_dma8_cnt >> 8;
}
-WRITE8_MEMBER( sb16_lle_device::dma8_len_lo_w )
+void sb16_lle_device::dma8_len_lo_w(uint8_t data)
{
m_dma8_len = (m_dma8_len & 0xff00) | data;
}
-WRITE8_MEMBER( sb16_lle_device::dma8_len_hi_w )
+void sb16_lle_device::dma8_len_hi_w(uint8_t data)
{
m_dma8_len = (m_dma8_len & 0xff) | (data << 8);
}
-WRITE8_MEMBER( sb16_lle_device::dma16_len_lo_w )
+void sb16_lle_device::dma16_len_lo_w(uint8_t data)
{
m_dma16_len = (m_dma16_len & 0xff00) | data;
}
-WRITE8_MEMBER( sb16_lle_device::dma16_len_hi_w )
+void sb16_lle_device::dma16_len_hi_w(uint8_t data)
{
m_dma16_len = (m_dma16_len & 0xff) | (data << 8);
}
@@ -376,12 +383,12 @@ ROM_END
void sb16_lle_device::sb16_io(address_map &map)
{
map(0x0000, 0x0000).mirror(0xff00).rw(FUNC(sb16_lle_device::dsp_data_r), FUNC(sb16_lle_device::dsp_data_w));
-// AM_RANGE(0x0001, 0x0001) // MIDI related?
-// AM_RANGE(0x0002, 0x0002)
+// map(0x0001, 0x0001) // MIDI related?
+// map(0x0002, 0x0002)
map(0x0004, 0x0004).mirror(0xff00).rw(FUNC(sb16_lle_device::mode_r), FUNC(sb16_lle_device::mode_w));
map(0x0005, 0x0005).mirror(0xff00).rw(FUNC(sb16_lle_device::dac_ctrl_r), FUNC(sb16_lle_device::dac_ctrl_w));
map(0x0006, 0x0006).mirror(0xff00).r(FUNC(sb16_lle_device::dma_stat_r));
-// AM_RANGE(0x0007, 0x0007) // unknown
+// map(0x0007, 0x0007) // unknown, readback status of stereo f/f?
map(0x0008, 0x0008).mirror(0xff00).rw(FUNC(sb16_lle_device::ctrl8_r), FUNC(sb16_lle_device::ctrl8_w));
map(0x0009, 0x0009).mirror(0xff00).w(FUNC(sb16_lle_device::rate_w));
map(0x000A, 0x000A).mirror(0xff00).r(FUNC(sb16_lle_device::dma8_cnt_lo_r));
@@ -399,9 +406,18 @@ void sb16_lle_device::sb16_io(address_map &map)
map(0x001B, 0x001B).mirror(0xff00).r(FUNC(sb16_lle_device::adc_data_r));
map(0x001D, 0x001D).mirror(0xff00).w(FUNC(sb16_lle_device::dma8_w));
map(0x001F, 0x001F).mirror(0xff00).r(FUNC(sb16_lle_device::dma8_r));
-// AM_RANGE(0x0080, 0x0080) // ASP comms
-// AM_RANGE(0x0081, 0x0081)
-// AM_RANGE(0x0082, 0x0082)
+// map(0x0080, 0x0080) // ASP comms
+// map(0x0081, 0x0081)
+// map(0x0082, 0x0082)
+}
+
+void sb16_lle_device::host_io(address_map &map)
+{
+ map(0x4, 0x5).rw(m_mixer, FUNC(ct1745_mixer_device::read), FUNC(ct1745_mixer_device::write));
+ map(0x6, 0x7).w(FUNC(sb16_lle_device::dsp_reset_w));
+ map(0xa, 0xb).r(FUNC(sb16_lle_device::host_data_r));
+ map(0xc, 0xd).rw(FUNC(sb16_lle_device::dsp_wbuf_status_r), FUNC(sb16_lle_device::host_cmd_w));
+ map(0xe, 0xf).r(FUNC(sb16_lle_device::dsp_rbuf_status_r));
}
const tiny_rom_entry *sb16_lle_device::device_rom_region() const
@@ -418,27 +434,38 @@ void sb16_lle_device::device_add_mconfig(machine_config &config)
m_cpu->port_in_cb<2>().set(FUNC(sb16_lle_device::p2_r));
m_cpu->port_out_cb<2>().set(FUNC(sb16_lle_device::p2_w));
- SPEAKER(config, "lspeaker").front_left();
- SPEAKER(config, "rspeaker").front_right();
- ymf262_device &ymf262(YMF262(config, "ymf262", XTAL(14'318'181)));
- ymf262.add_route(0, "lspeaker", 1.00);
- ymf262.add_route(1, "rspeaker", 1.00);
- ymf262.add_route(2, "lspeaker", 1.00);
- ymf262.add_route(3, "rspeaker", 1.00);
+ SPEAKER(config, "speaker", 2).front();
+
+ CT1745(config, m_mixer);
+ m_mixer->set_fm_tag("ymf262");
+ m_mixer->set_ldac_tag(m_ldac);
+ m_mixer->set_rdac_tag(m_rdac);
+ m_mixer->add_route(0, "speaker", 1.0, 0);
+ m_mixer->add_route(1, "speaker", 1.0, 1);
+ m_mixer->irq_status_cb().set([this] () {
+ return (m_irq8 << 0) | (m_irq16 << 1) | (m_irq_midi << 2) | (0x8 << 4);
+ });
- 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
+ DAC_16BIT_R2R(config, m_ldac, 0).add_route(ALL_OUTPUTS, m_mixer, 0.5, 0); // unknown DAC
+ DAC_16BIT_R2R(config, m_rdac, 0).add_route(ALL_OUTPUTS, m_mixer, 0.5, 1); // unknown DAC
+
+ ymf262_device &ymf262(YMF262(config, "ymf262", XTAL(14'318'181)));
+ ymf262.add_route(0, m_mixer, 1.00, 0);
+ ymf262.add_route(1, m_mixer, 1.00, 1);
+ ymf262.add_route(2, m_mixer, 1.00, 0);
+ ymf262.add_route(3, m_mixer, 1.00, 1);
PC_JOY(config, m_joy);
}
-READ8_MEMBER( sb16_lle_device::host_data_r )
+uint8_t sb16_lle_device::host_data_r()
{
- m_data_out = false;
+ if (!machine().side_effects_disabled())
+ m_data_out = false;
return m_out_byte;
}
-WRITE8_MEMBER( sb16_lle_device::host_cmd_w )
+void sb16_lle_device::host_cmd_w(uint8_t data)
{
m_data_in = true;
m_in_byte = data;
@@ -474,7 +501,7 @@ uint8_t sb16_lle_device::dack_r(int line)
return ret;
}
- ++m_adc_fifo_tail %= 16;
+ ++m_adc_fifo_tail %= FIFO_SIZE;
if(m_adc_fifo_ctrl & 4)
{
@@ -482,7 +509,7 @@ uint8_t sb16_lle_device::dack_r(int line)
return ret;
}
- if(m_adc_fifo_head == ((m_adc_fifo_tail + 1) % 16))
+ if(m_adc_fifo_head == ((m_adc_fifo_tail + 1) % FIFO_SIZE))
m_isa->drq1_w(0);
return ret;
}
@@ -517,7 +544,7 @@ void sb16_lle_device::dack_w(int line, uint8_t data)
return;
}
- ++m_dac_fifo_head %= 16;
+ ++m_dac_fifo_head %= FIFO_SIZE;
if(m_dac_fifo_ctrl & 4)
{
@@ -551,7 +578,7 @@ uint16_t sb16_lle_device::dack16_r(int line)
m_isa->drq5_w(0);
return ret;
}
- ++m_adc_fifo_tail %= 16;
+ ++m_adc_fifo_tail %= FIFO_SIZE;
if(m_adc_fifo_ctrl & 4)
{
@@ -559,7 +586,7 @@ uint16_t sb16_lle_device::dack16_r(int line)
return ret;
}
- if(m_adc_fifo_head == ((m_adc_fifo_tail + 1) % 16))
+ if(m_adc_fifo_head == ((m_adc_fifo_tail + 1) % FIFO_SIZE))
m_isa->drq5_w(0);
return ret;
}
@@ -586,7 +613,7 @@ void sb16_lle_device::dack16_w(int line, uint16_t data)
m_isa->drq5_w(0);
return;
}
- ++m_dac_fifo_head %= 16;
+ ++m_dac_fifo_head %= FIFO_SIZE;
if(m_dac_fifo_ctrl & 4)
{
@@ -598,7 +625,7 @@ void sb16_lle_device::dack16_w(int line, uint16_t data)
m_isa->drq5_w(0);
}
-WRITE8_MEMBER( sb16_lle_device::dsp_reset_w )
+void sb16_lle_device::dsp_reset_w(uint8_t data)
{
if(data & 1)
{
@@ -607,39 +634,34 @@ WRITE8_MEMBER( sb16_lle_device::dsp_reset_w )
}
}
-READ8_MEMBER( sb16_lle_device::dsp_wbuf_status_r )
+uint8_t sb16_lle_device::dsp_wbuf_status_r(offs_t offset)
{
if(offset)
return 0xff;
return m_data_in << 7;
}
-READ8_MEMBER( sb16_lle_device::dsp_rbuf_status_r )
+uint8_t sb16_lle_device::dsp_rbuf_status_r(offs_t offset)
{
if(offset)
{
- m_irq16 = false;
- m_isa->irq5_w((m_irq8 || m_irq16 || m_irq_midi) ? ASSERT_LINE : CLEAR_LINE);
+ if(!machine().side_effects_disabled())
+ {
+ m_irq16 = false;
+ m_isa->irq5_w((m_irq8 || m_irq16 || m_irq_midi) ? ASSERT_LINE : CLEAR_LINE);
+ }
return 0xff;
}
- m_irq8 = false;
- m_isa->irq5_w((m_irq8 || m_irq16 || m_irq_midi) ? ASSERT_LINE : CLEAR_LINE);
+ if(!machine().side_effects_disabled())
+ {
+ m_irq8 = false;
+ m_isa->irq5_w((m_irq8 || m_irq16 || m_irq_midi) ? ASSERT_LINE : CLEAR_LINE);
+ }
return m_data_out << 7;
}
-WRITE8_MEMBER( sb16_lle_device::invalid_w )
-{
- logerror("sb16: invalid port write\n");
-}
-
-READ8_MEMBER( sb16_lle_device::invalid_r )
-{
- logerror("sb16: invalid port read\n");
- return 0xff;
-}
-
// just using the old dummy mpu401 for now
-READ8_MEMBER( sb16_lle_device::mpu401_r )
+uint8_t sb16_lle_device::mpu401_r(offs_t offset)
{
uint8_t res;
@@ -658,7 +680,7 @@ READ8_MEMBER( sb16_lle_device::mpu401_r )
return res;
}
-WRITE8_MEMBER( sb16_lle_device::mpu401_w )
+void sb16_lle_device::mpu401_w(offs_t offset, uint8_t data)
{
if(offset == 0) // data
{
@@ -683,6 +705,7 @@ WRITE8_MEMBER( sb16_lle_device::mpu401_w )
sb16_lle_device::sb16_lle_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) :
device_t(mconfig, ISA16_SB16, tag, owner, clock),
device_isa16_card_interface(mconfig, *this),
+ m_mixer(*this, "mixer"),
m_ldac(*this, "ldac"),
m_rdac(*this, "rdac"),
m_joy(*this, "pc_joy"),
@@ -702,21 +725,18 @@ void sb16_lle_device::device_start()
rom[i] = rom[i] ^ xor_table[i & 0x3f];
- ymf262_device *ymf262 = subdevice<ymf262_device>("ymf262");
+ ymf262_device &ymf262 = *subdevice<ymf262_device>("ymf262");
set_isa_device();
- m_isa->install_device(0x0200, 0x0207, read8_delegate(FUNC(pc_joy_device::joy_port_r), subdevice<pc_joy_device>("pc_joy")), write8_delegate(FUNC(pc_joy_device::joy_port_w), subdevice<pc_joy_device>("pc_joy")));
- m_isa->install_device(0x0226, 0x0227, read8_delegate(FUNC(sb16_lle_device::invalid_r), this), write8_delegate(FUNC(sb16_lle_device::dsp_reset_w), this));
- m_isa->install_device(0x022a, 0x022b, read8_delegate(FUNC(sb16_lle_device::host_data_r), this), write8_delegate(FUNC(sb16_lle_device::invalid_w), this) );
- m_isa->install_device(0x022c, 0x022d, read8_delegate(FUNC(sb16_lle_device::dsp_wbuf_status_r), this), write8_delegate(FUNC(sb16_lle_device::host_cmd_w), this) );
- m_isa->install_device(0x022e, 0x022f, read8_delegate(FUNC(sb16_lle_device::dsp_rbuf_status_r), this), write8_delegate(FUNC(sb16_lle_device::invalid_w), this) );
- m_isa->install_device(0x0330, 0x0331, read8_delegate(FUNC(sb16_lle_device::mpu401_r), this), write8_delegate(FUNC(sb16_lle_device::mpu401_w), this));
- m_isa->install_device(0x0388, 0x0389, read8sm_delegate(FUNC(ymf262_device::read), ymf262), write8sm_delegate(FUNC(ymf262_device::write), ymf262));
- m_isa->install_device(0x0220, 0x0223, read8sm_delegate(FUNC(ymf262_device::read), ymf262), write8sm_delegate(FUNC(ymf262_device::write), ymf262));
- m_isa->install_device(0x0228, 0x0229, read8sm_delegate(FUNC(ymf262_device::read), ymf262), write8sm_delegate(FUNC(ymf262_device::write), 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(0x0220, 0x022f, *this, &sb16_lle_device::host_io);
+ m_isa->install_device(0x0330, 0x0331, read8sm_delegate(*this, FUNC(sb16_lle_device::mpu401_r)), write8sm_delegate(*this, FUNC(sb16_lle_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)));
m_isa->set_dma_channel(1, this, false);
m_isa->set_dma_channel(5, this, false);
- m_timer = timer_alloc();
+ m_timer = timer_alloc(FUNC(sb16_lle_device::timer_tick), this);
}
@@ -741,7 +761,7 @@ void sb16_lle_device::device_reset()
m_dma8_done = m_dma16_done = false;
}
-void sb16_lle_device::device_timer(emu_timer &timer, device_timer_id tid, int param, void *ptr)
+TIMER_CALLBACK_MEMBER(sb16_lle_device::timer_tick)
{
uint16_t dacl = 0, dacr = 0, adcl = 0, adcr = 0;
if(m_mode & 2)
@@ -751,6 +771,7 @@ void sb16_lle_device::device_timer(emu_timer &timer, device_timer_id tid, int pa
m_cpu->set_input_line(MCS51_INT0_LINE, ASSERT_LINE);
return;
}
+
if(m_mode & 1)
{
switch(m_mode & 0xa0) // dac 16
@@ -843,12 +864,12 @@ void sb16_lle_device::device_timer(emu_timer &timer, device_timer_id tid, int pa
m_isa->drq5_w(1);
if((!(m_ctrl8 & 2) && !(m_mode & 1)) || (!(m_ctrl16 & 2) && (m_mode & 1)))
- ++m_dac_fifo_tail %= 16;
+ ++m_dac_fifo_tail %= FIFO_SIZE;
if((!(m_ctrl8 & 2) && (m_mode & 1)) || (!(m_ctrl16 & 2) && !(m_mode & 1)))
{
m_adc_fifo[m_adc_fifo_head].h[0] = adcl;
m_adc_fifo[m_adc_fifo_head].h[1] = adcr;
- ++m_adc_fifo_head %= 16;
+ ++m_adc_fifo_head %= FIFO_SIZE;
}
}
diff --git a/src/devices/bus/isa/sb16.h b/src/devices/bus/isa/sb16.h
index 4eb9be9d804..9facc1e201e 100644
--- a/src/devices/bus/isa/sb16.h
+++ b/src/devices/bus/isa/sb16.h
@@ -7,8 +7,9 @@
#include "isa.h"
#include "bus/pc_joy/pc_joy.h"
#include "cpu/mcs51/mcs51.h"
-#include "sound/262intf.h"
+#include "sound/ct1745.h"
#include "sound/dac.h"
+#include "sound/ymopl.h"
//*********************************************************************
// TYPE DEFINITIONS
@@ -24,14 +25,12 @@ public:
protected:
// device-level overrides
- virtual void device_start() override;
- virtual void device_reset() override;
-
- virtual void device_timer(emu_timer &timer, device_timer_id id, int param, void *ptr) override;
+ virtual void device_start() override ATTR_COLD;
+ virtual void device_reset() override ATTR_COLD;
// optional information overrides
- virtual const tiny_rom_entry *device_rom_region() const override;
- virtual void device_add_mconfig(machine_config &config) override;
+ virtual const tiny_rom_entry *device_rom_region() const override ATTR_COLD;
+ virtual void device_add_mconfig(machine_config &config) override ATTR_COLD;
uint8_t dack_r(int line) override;
void dack_w(int line, uint8_t data) override;
@@ -39,58 +38,60 @@ protected:
void dack16_w(int line, uint16_t data) override;
private:
- READ8_MEMBER( mpu401_r );
- WRITE8_MEMBER( mpu401_w );
+ uint8_t mpu401_r(offs_t offset);
+ void mpu401_w(offs_t offset, uint8_t data);
// mcu ports
- DECLARE_READ8_MEMBER( dsp_data_r );
- DECLARE_WRITE8_MEMBER( dsp_data_w );
- DECLARE_READ8_MEMBER( p1_r );
- DECLARE_WRITE8_MEMBER( p1_w );
- DECLARE_READ8_MEMBER( p2_r );
- DECLARE_WRITE8_MEMBER( p2_w );
- DECLARE_WRITE8_MEMBER( rate_w );
- DECLARE_READ8_MEMBER( dma8_r );
- DECLARE_WRITE8_MEMBER( dma8_w );
- DECLARE_READ8_MEMBER( ctrl8_r );
- DECLARE_WRITE8_MEMBER( ctrl8_w );
- DECLARE_READ8_MEMBER( ctrl16_r );
- DECLARE_WRITE8_MEMBER( ctrl16_w );
- DECLARE_READ8_MEMBER( dac_ctrl_r );
- DECLARE_WRITE8_MEMBER( dac_ctrl_w );
- DECLARE_READ8_MEMBER( dac_fifo_ctrl_r );
- DECLARE_WRITE8_MEMBER( dac_fifo_ctrl_w );
- DECLARE_READ8_MEMBER( adc_fifo_ctrl_r );
- DECLARE_WRITE8_MEMBER( adc_fifo_ctrl_w );
- DECLARE_READ8_MEMBER( dma_stat_r );
- DECLARE_WRITE8_MEMBER( dac_data_w );
- DECLARE_READ8_MEMBER( adc_data_r );
- DECLARE_READ8_MEMBER( dma8_ready_r );
- DECLARE_READ8_MEMBER( adc_data_ready_r );
- DECLARE_READ8_MEMBER( dma8_cnt_lo_r );
- DECLARE_READ8_MEMBER( dma8_cnt_hi_r );
- DECLARE_WRITE8_MEMBER( dma8_len_lo_w );
- DECLARE_WRITE8_MEMBER( dma8_len_hi_w );
- DECLARE_WRITE8_MEMBER( dma16_len_lo_w );
- DECLARE_WRITE8_MEMBER( dma16_len_hi_w );
- DECLARE_READ8_MEMBER( mode_r );
- DECLARE_WRITE8_MEMBER( mode_w );
+ uint8_t dsp_data_r();
+ void dsp_data_w(uint8_t data);
+ uint8_t p1_r();
+ void p1_w(uint8_t data);
+ uint8_t p2_r();
+ void p2_w(uint8_t data);
+ void rate_w(uint8_t data);
+ uint8_t dma8_r();
+ void dma8_w(uint8_t data);
+ uint8_t ctrl8_r();
+ void ctrl8_w(uint8_t data);
+ uint8_t ctrl16_r();
+ void ctrl16_w(uint8_t data);
+ uint8_t dac_ctrl_r();
+ void dac_ctrl_w(uint8_t data);
+ uint8_t dac_fifo_ctrl_r();
+ void dac_fifo_ctrl_w(uint8_t data);
+ uint8_t adc_fifo_ctrl_r();
+ void adc_fifo_ctrl_w(uint8_t data);
+ uint8_t dma_stat_r();
+ void dac_data_w(uint8_t data);
+ uint8_t adc_data_r();
+ uint8_t dma8_ready_r();
+ uint8_t adc_data_ready_r();
+ uint8_t dma8_cnt_lo_r();
+ uint8_t dma8_cnt_hi_r();
+ void dma8_len_lo_w(uint8_t data);
+ void dma8_len_hi_w(uint8_t data);
+ void dma16_len_lo_w(uint8_t data);
+ void dma16_len_hi_w(uint8_t data);
+ uint8_t mode_r();
+ void mode_w(uint8_t data);
// host ports
- DECLARE_READ8_MEMBER( host_data_r );
- DECLARE_WRITE8_MEMBER( host_cmd_w );
- DECLARE_WRITE8_MEMBER( dsp_reset_w );
- DECLARE_READ8_MEMBER( dsp_wbuf_status_r );
- DECLARE_READ8_MEMBER( dsp_rbuf_status_r );
- DECLARE_READ8_MEMBER( invalid_r );
- DECLARE_WRITE8_MEMBER( invalid_w );
+ uint8_t host_data_r();
+ void host_cmd_w(uint8_t data);
+ void dsp_reset_w(uint8_t data);
+ uint8_t dsp_wbuf_status_r(offs_t offset);
+ uint8_t dsp_rbuf_status_r(offs_t offset);
- void sb16_io(address_map &map);
+ void sb16_io(address_map &map) ATTR_COLD;
+ void host_io(address_map &map) ATTR_COLD;
void control_timer(bool start);
- required_device<dac_word_interface> m_ldac;
- required_device<dac_word_interface> m_rdac;
+ TIMER_CALLBACK_MEMBER(timer_tick);
+
+ required_device<ct1745_mixer_device> m_mixer;
+ required_device<dac_16bit_r2r_device> m_ldac;
+ required_device<dac_16bit_r2r_device> m_rdac;
required_device<pc_joy_device> m_joy;
required_device<i80c52_device> m_cpu;
@@ -107,7 +108,8 @@ private:
uint16_t h[2];
uint8_t b[4];
} samples;
- samples m_adc_fifo[16], m_dac_fifo[16];
+ static constexpr int FIFO_SIZE = 16;
+ samples m_adc_fifo[FIFO_SIZE], m_dac_fifo[FIFO_SIZE];
int m_adc_fifo_head, m_adc_fifo_tail, m_dac_fifo_head, m_dac_fifo_tail;
bool m_adc_r, m_dac_r, m_adc_h, m_dac_h, m_irq8, m_irq16, m_irq_midi;
bool m_dma8_done, m_dma16_done;
diff --git a/src/devices/bus/isa/sblaster.cpp b/src/devices/bus/isa/sblaster.cpp
index 73e98a297f8..a17d808cebd 100644
--- a/src/devices/bus/isa/sblaster.cpp
+++ b/src/devices/bus/isa/sblaster.cpp
@@ -14,9 +14,8 @@
#include "sblaster.h"
#include "machine/pic8259.h"
-#include "sound/262intf.h"
#include "sound/spkrdev.h"
-#include "sound/volt_reg.h"
+#include "sound/ymopl.h"
#include "speaker.h"
@@ -66,47 +65,47 @@ static const int m_cmd_fifo_length[256] =
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, /* 6x */
-1, -1, -1, -1, 3, 3, 3, 3, -1, -1, -1, -1, -1, 1, -1, 1, /* 7x */
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, /* 8x */
- 1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, /* 9x */
+ 1, 1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, /* 9x */
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, /* Ax */
- 4, -1, -1, -1, -1, -1, 4, -1, 4, -1, -1, -1, -1, -1, 4, -1, /* Bx */
- 4, -1, -1, -1, -1, -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 */
+ 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 */
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 */
};
static const int protection_magic[4] = { 0x96, 0xa5, 0x69, 0x5a };
-READ8_MEMBER( sb8_device::ym3812_16_r )
+uint8_t sb8_device::ym3812_16_r(offs_t offset)
{
uint8_t retVal = 0xff;
switch(offset)
{
- case 0 : retVal = m_ym3812->status_port_r(); break;
+ case 0 : retVal = m_ym3812->status_r(); break;
}
return retVal;
}
-WRITE8_MEMBER( sb8_device::ym3812_16_w )
+void sb8_device::ym3812_16_w(offs_t offset, uint8_t data)
{
switch(offset)
{
- case 0 : m_ym3812->control_port_w(data); break;
- case 1 : m_ym3812->write_port_w(data); break;
+ case 0 : m_ym3812->address_w(data); break;
+ case 1 : m_ym3812->data_w(data); break;
}
}
-READ8_MEMBER( isa8_sblaster1_0_device::saa1099_16_r )
+uint8_t isa8_sblaster1_0_device::saa1099_16_r(offs_t offset)
{
return 0xff;
}
-WRITE8_MEMBER( isa8_sblaster1_0_device::saa1099_1_16_w )
+void isa8_sblaster1_0_device::saa1099_1_16_w(offs_t offset, uint8_t data)
{
m_saa1099_1->write(offset, data);
}
-WRITE8_MEMBER( isa8_sblaster1_0_device::saa1099_2_16_w )
+void isa8_sblaster1_0_device::saa1099_2_16_w(offs_t offset, uint8_t data)
{
m_saa1099_2->write(offset, data);
}
@@ -164,7 +163,7 @@ uint8_t sb_device::dequeue_r()
}
-READ8_MEMBER( sb_device::dsp_reset_r )
+uint8_t sb_device::dsp_reset_r(offs_t offset)
{
// printf("read DSP reset @ %x\n", offset);
if(offset)
@@ -173,7 +172,7 @@ READ8_MEMBER( sb_device::dsp_reset_r )
return 0xff;
}
-WRITE8_MEMBER( sb_device::dsp_reset_w )
+void sb_device::dsp_reset_w(offs_t offset, uint8_t data)
{
// printf("%02x to DSP reset @ %x\n", data, offset);
if(offset)
@@ -219,7 +218,7 @@ WRITE8_MEMBER( sb_device::dsp_reset_w )
//printf("%02x\n",data);
}
-READ8_MEMBER( sb_device::dsp_data_r )
+uint8_t sb_device::dsp_data_r(offs_t offset)
{
// printf("read DSP data @ %x\n", offset);
if(offset)
@@ -244,7 +243,7 @@ READ8_MEMBER( sb_device::dsp_data_r )
return dequeue_r();
}
-WRITE8_MEMBER( sb_device::dsp_data_w )
+void sb_device::dsp_data_w(offs_t offset, uint8_t data)
{
// printf("%02x to DSP data @ %x\n", data, offset);
if(offset)
@@ -252,7 +251,7 @@ WRITE8_MEMBER( sb_device::dsp_data_w )
logerror("Soundblaster DSP data port undocumented write\n");
}
-READ8_MEMBER(sb_device::dsp_rbuf_status_r)
+uint8_t sb_device::dsp_rbuf_status_r(offs_t offset)
{
// printf("read Rbufstat @ %x\n", offset);
@@ -281,7 +280,7 @@ READ8_MEMBER(sb_device::dsp_rbuf_status_r)
return m_dsp.rbuf_status;
}
-READ8_MEMBER(sb_device::dsp_wbuf_status_r)
+uint8_t sb_device::dsp_wbuf_status_r(offs_t offset)
{
// printf("read Wbufstat @ %x\n", offset);
@@ -303,7 +302,7 @@ READ8_MEMBER(sb_device::dsp_wbuf_status_r)
return m_dsp.wbuf_status;
}
-WRITE8_MEMBER(sb_device::dsp_rbuf_status_w)
+void sb_device::dsp_rbuf_status_w(offs_t offset, uint8_t data)
{
// printf("%02x to Rbufstat @ %x\n", data, offset);
if(offset)
@@ -331,6 +330,7 @@ void sb_device::process_fifo(uint8_t cmd)
break;
case 0x14: // 8-bit DMA, no autoinit
+ case 0x91: // 8-bit DMA, no autoinit, high speed. XXX only on DSP 3.xx
m_dsp.dma_length = (m_dsp.fifo[1] + (m_dsp.fifo[2]<<8)) + 1;
// printf("Start DMA (not autoinit, size = %x)\n", m_dsp.dma_length);
m_dsp.dma_transferred = 0;
@@ -344,6 +344,7 @@ void sb_device::process_fifo(uint8_t cmd)
case 0x17: // 2-bit ADPCM w/new reference
m_dsp.adpcm_new_ref = true;
m_dsp.adpcm_step = 0;
+ [[fallthrough]];
case 0x16: // 2-bit ADPCM
m_dsp.adpcm_count = 0;
m_dsp.dma_length = (m_dsp.fifo[1] + (m_dsp.fifo[2]<<8)) + 1;
@@ -406,6 +407,7 @@ void sb_device::process_fifo(uint8_t cmd)
case 0x75: // 4-bit ADPCM w/new reference
m_dsp.adpcm_new_ref = true;
m_dsp.adpcm_step = 0;
+ [[fallthrough]];
case 0x74: // 4-bit ADPCM
m_dsp.adpcm_count = 0;
m_dsp.dma_length = (m_dsp.fifo[1] + (m_dsp.fifo[2]<<8)) + 1;
@@ -420,6 +422,7 @@ void sb_device::process_fifo(uint8_t cmd)
case 0x77: // 2.6-bit ADPCM w/new reference
m_dsp.adpcm_new_ref = true;
m_dsp.adpcm_step = 0;
+ [[fallthrough]];
case 0x76: // 2.6-bit ADPCM
m_dsp.adpcm_count = 0;
m_dsp.dma_length = (m_dsp.fifo[1] + (m_dsp.fifo[2]<<8)) + 1;
@@ -553,6 +556,7 @@ void sb_device::process_fifo(uint8_t cmd)
{
case 0x0f: // read asp reg
queue_r(0);
+ [[fallthrough]];
case 0x0e: // write asp reg
case 0x02: // get asp version
case 0x04: // set asp mode register
@@ -565,21 +569,28 @@ 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
m_dsp.dma_autoinit = 0;
break;
case 0xb0:
+ case 0xb2:
+ case 0xb4:
case 0xb6:
case 0xc0:
+ case 0xc2:
+ case 0xc4:
case 0xc6:
mode = m_dsp.fifo[1];
m_dsp.flags = 0;
@@ -635,7 +646,7 @@ void sb_device::process_fifo(uint8_t cmd)
}
}
-WRITE8_MEMBER(sb_device::dsp_cmd_w)
+void sb_device::dsp_cmd_w(offs_t offset, uint8_t data)
{
// printf("%02x to DSP command @ %x\n", data, offset);
@@ -705,7 +716,7 @@ void sb_device::adpcm_decode(uint8_t sample, int size)
m_rdac->write(m_dsp.adpcm_ref << 8);
}
-READ8_MEMBER( sb16_device::mpu401_r )
+uint8_t sb16_device::mpu401_r(offs_t offset)
{
uint8_t res;
@@ -739,7 +750,7 @@ READ8_MEMBER( sb16_device::mpu401_r )
return res;
}
-WRITE8_MEMBER( sb16_device::mpu401_w )
+void sb16_device::mpu401_w(offs_t offset, uint8_t data)
{
if(offset == 0) // data
{
@@ -819,14 +830,14 @@ void sb16_device::mixer_reset()
mixer_set();
}
-READ8_MEMBER( sb16_device::mixer_r )
+uint8_t sb16_device::mixer_r(offs_t offset)
{
if(offset == 0)
return m_mixer.status;
return m_mixer.data;
}
-WRITE8_MEMBER( sb16_device::mixer_w )
+void sb16_device::mixer_w(offs_t offset, uint8_t data)
{
if(offset == 0)
{
@@ -1141,16 +1152,10 @@ DEFINE_DEVICE_TYPE(ISA16_SOUND_BLASTER_16, isa16_sblaster16_device, "isa_sblaste
void sb_device::common(machine_config &config)
{
- SPEAKER(config, "lspeaker").front_left();
- SPEAKER(config, "rspeaker").front_right();
+ SPEAKER(config, "speaker", 2).front();
- 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
- voltage_regulator_device &vref(VOLTAGE_REGULATOR(config, "vref", 0));
- vref.add_route(0, "ldac", 1.0, DAC_VREF_POS_INPUT);
- vref.add_route(0, "ldac", -1.0, DAC_VREF_NEG_INPUT);
- vref.add_route(0, "rdac", 1.0, DAC_VREF_POS_INPUT);
- vref.add_route(0, "rdac", -1.0, DAC_VREF_NEG_INPUT);
+ DAC_16BIT_R2R(config, m_ldac, 0).add_route(ALL_OUTPUTS, "speaker", 0.5, 0); // unknown DAC
+ DAC_16BIT_R2R(config, m_rdac, 0).add_route(ALL_OUTPUTS, "speaker", 0.5, 1); // unknown DAC
PC_JOY(config, m_joy);
@@ -1163,16 +1168,16 @@ void isa8_sblaster1_0_device::device_add_mconfig(machine_config &config)
common(config);
YM3812(config, m_ym3812, ym3812_StdClock);
- m_ym3812->add_route(ALL_OUTPUTS, "lspeaker", 3.0);
- m_ym3812->add_route(ALL_OUTPUTS, "rspeaker", 3.0);
+ m_ym3812->add_route(ALL_OUTPUTS, "speaker", 3.0, 0);
+ m_ym3812->add_route(ALL_OUTPUTS, "speaker", 3.0, 1);
- SAA1099(config, m_saa1099_1, 7159090);
- m_saa1099_1->add_route(ALL_OUTPUTS, "lspeaker", 0.5);
- m_saa1099_1->add_route(ALL_OUTPUTS, "rspeaker", 0.5);
+ SAA1099(config, m_saa1099_1, XTAL(14'318'181) / 2); // or CMS-301, from OSC pin in ISA bus
+ m_saa1099_1->add_route(0, "speaker", 0.5, 0);
+ m_saa1099_1->add_route(1, "speaker", 0.5, 1);
- SAA1099(config, m_saa1099_2, 7159090);
- m_saa1099_2->add_route(ALL_OUTPUTS, "lspeaker", 0.5);
- m_saa1099_2->add_route(ALL_OUTPUTS, "rspeaker", 0.5);
+ SAA1099(config, m_saa1099_2, XTAL(14'318'181) / 2); // or CMS-301, from OSC pin in ISA bus
+ m_saa1099_2->add_route(0, "speaker", 0.5, 0);
+ m_saa1099_2->add_route(1, "speaker", 0.5, 1);
}
void isa8_sblaster1_5_device::device_add_mconfig(machine_config &config)
@@ -1180,8 +1185,8 @@ void isa8_sblaster1_5_device::device_add_mconfig(machine_config &config)
common(config);
YM3812(config, m_ym3812, ym3812_StdClock);
- m_ym3812->add_route(ALL_OUTPUTS, "lspeaker", 1.0);
- m_ym3812->add_route(ALL_OUTPUTS, "rspeaker", 1.0);
+ m_ym3812->add_route(ALL_OUTPUTS, "speaker", 1.0, 0);
+ m_ym3812->add_route(ALL_OUTPUTS, "speaker", 1.0, 1);
/* no CM/S support (empty sockets) */
}
@@ -1190,10 +1195,10 @@ void isa16_sblaster16_device::device_add_mconfig(machine_config &config)
common(config);
ymf262_device &ymf262(YMF262(config, "ymf262", ymf262_StdClock));
- ymf262.add_route(0, "lspeaker", 1.0);
- ymf262.add_route(1, "rspeaker", 1.0);
- ymf262.add_route(2, "lspeaker", 1.0);
- ymf262.add_route(3, "rspeaker", 1.0);
+ ymf262.add_route(0, "speaker", 1.0, 0);
+ ymf262.add_route(1, "speaker", 1.0, 1);
+ ymf262.add_route(2, "speaker", 1.0, 0);
+ ymf262.add_route(3, "speaker", 1.0, 1);
}
//**************************************************************************
@@ -1251,23 +1256,23 @@ isa16_sblaster16_device::isa16_sblaster16_device(const machine_config &mconfig,
void sb8_device::device_start()
{
- m_isa->install_device(0x0200, 0x0207, read8_delegate(FUNC(pc_joy_device::joy_port_r), subdevice<pc_joy_device>("pc_joy")), write8_delegate(FUNC(pc_joy_device::joy_port_w), subdevice<pc_joy_device>("pc_joy")));
- m_isa->install_device(0x0226, 0x0227, read8_delegate(FUNC(sb_device::dsp_reset_r), this), write8_delegate(FUNC(sb_device::dsp_reset_w), this));
- m_isa->install_device(0x022a, 0x022b, read8_delegate(FUNC(sb_device::dsp_data_r), this), write8_delegate(FUNC(sb_device::dsp_data_w), this) );
- m_isa->install_device(0x022c, 0x022d, read8_delegate(FUNC(sb_device::dsp_wbuf_status_r), this), write8_delegate(FUNC(sb_device::dsp_cmd_w), this) );
- m_isa->install_device(0x022e, 0x022f, read8_delegate(FUNC(sb_device::dsp_rbuf_status_r), this), write8_delegate(FUNC(sb_device::dsp_rbuf_status_w), this) );
+ 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)));
if(m_dsp.version >= 0x0301)
{
- ymf262_device *ymf262 = subdevice<ymf262_device>("ymf262");
+ ymf262_device &ymf262 = *subdevice<ymf262_device>("ymf262");
- m_isa->install_device(0x0388, 0x038b, read8sm_delegate(FUNC(ymf262_device::read), ymf262), write8sm_delegate(FUNC(ymf262_device::write), ymf262));
- m_isa->install_device(0x0220, 0x0223, read8sm_delegate(FUNC(ymf262_device::read), ymf262), write8sm_delegate(FUNC(ymf262_device::write), ymf262));
- m_isa->install_device(0x0228, 0x0229, read8sm_delegate(FUNC(ymf262_device::read), ymf262), write8sm_delegate(FUNC(ymf262_device::write), ymf262));
+ 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)));
}
else
{
- m_isa->install_device(0x0388, 0x0389, read8_delegate( FUNC(sb8_device::ym3812_16_r), this ), write8_delegate( FUNC(sb8_device::ym3812_16_w), this ) );
- m_isa->install_device(0x0228, 0x0229, read8_delegate( FUNC(sb8_device::ym3812_16_r), this ), write8_delegate( FUNC(sb8_device::ym3812_16_w), this ) );
+ m_isa->install_device(0x0388, 0x0389, read8sm_delegate(*this, FUNC(sb8_device::ym3812_16_r)), write8sm_delegate(*this, FUNC(sb8_device::ym3812_16_w)));
+ m_isa->install_device(0x0228, 0x0229, read8sm_delegate(*this, FUNC(sb8_device::ym3812_16_r)), write8sm_delegate(*this, FUNC(sb8_device::ym3812_16_w)));
}
sb_device::device_start();
@@ -1277,8 +1282,8 @@ void isa8_sblaster1_0_device::device_start()
{
set_isa_device();
// 1.0 always has the SAA1099s for CMS back-compatibility
- m_isa->install_device(0x0220, 0x0221, read8_delegate( FUNC(isa8_sblaster1_0_device::saa1099_16_r), this ), write8_delegate( FUNC(isa8_sblaster1_0_device::saa1099_1_16_w), this ) );
- m_isa->install_device(0x0222, 0x0223, read8_delegate( FUNC(isa8_sblaster1_0_device::saa1099_16_r), this ), write8_delegate( FUNC(isa8_sblaster1_0_device::saa1099_2_16_w), this ) );
+ m_isa->install_device(0x0220, 0x0221, read8sm_delegate(*this, FUNC(isa8_sblaster1_0_device::saa1099_16_r)), write8sm_delegate(*this, FUNC(isa8_sblaster1_0_device::saa1099_1_16_w)));
+ m_isa->install_device(0x0222, 0x0223, read8sm_delegate(*this, FUNC(isa8_sblaster1_0_device::saa1099_16_r)), write8sm_delegate(*this, FUNC(isa8_sblaster1_0_device::saa1099_2_16_w)));
m_isa->set_dma_channel(1, this, false);
m_dsp.version = 0x0105;
sb8_device::device_start();
@@ -1295,17 +1300,17 @@ void isa8_sblaster1_5_device::device_start()
void sb16_device::device_start()
{
- ymf262_device *ymf262 = subdevice<ymf262_device>("ymf262");
- m_isa->install_device(0x0200, 0x0207, read8_delegate(FUNC(pc_joy_device::joy_port_r), subdevice<pc_joy_device>("pc_joy")), write8_delegate(FUNC(pc_joy_device::joy_port_w), subdevice<pc_joy_device>("pc_joy")));
- m_isa->install_device(0x0226, 0x0227, read8_delegate(FUNC(sb_device::dsp_reset_r), this), write8_delegate(FUNC(sb_device::dsp_reset_w), this));
- m_isa->install_device(0x022a, 0x022b, read8_delegate(FUNC(sb_device::dsp_data_r), this), write8_delegate(FUNC(sb_device::dsp_data_w), this) );
- m_isa->install_device(0x022c, 0x022d, read8_delegate(FUNC(sb_device::dsp_wbuf_status_r), this), write8_delegate(FUNC(sb_device::dsp_cmd_w), this) );
- m_isa->install_device(0x022e, 0x022f, read8_delegate(FUNC(sb_device::dsp_rbuf_status_r), this), write8_delegate(FUNC(sb_device::dsp_rbuf_status_w), this) );
- m_isa->install_device(0x0224, 0x0225, read8_delegate(FUNC(sb16_device::mixer_r), this), write8_delegate(FUNC(sb16_device::mixer_w), this));
- m_isa->install_device(0x0330, 0x0331, read8_delegate(FUNC(sb16_device::mpu401_r), this), write8_delegate(FUNC(sb16_device::mpu401_w), this));
- m_isa->install_device(0x0388, 0x038b, read8sm_delegate(FUNC(ymf262_device::read), ymf262), write8sm_delegate(FUNC(ymf262_device::write), ymf262));
- m_isa->install_device(0x0220, 0x0223, read8sm_delegate(FUNC(ymf262_device::read), ymf262), write8sm_delegate(FUNC(ymf262_device::write), ymf262));
- m_isa->install_device(0x0228, 0x0229, read8sm_delegate(FUNC(ymf262_device::read), ymf262), write8sm_delegate(FUNC(ymf262_device::write), ymf262));
+ 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(0x0224, 0x0225, read8sm_delegate(*this, FUNC(sb16_device::mixer_r)), write8sm_delegate(*this, FUNC(sb16_device::mixer_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(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)));
save_item(NAME(m_mixer.data));
save_item(NAME(m_mixer.status));
@@ -1338,7 +1343,7 @@ void isa16_sblaster16_device::device_start()
void sb_device::device_start()
{
- m_timer = timer_alloc(0, nullptr);
+ m_timer = timer_alloc(FUNC(sb_device::timer_tick), this);
save_item(NAME(m_dack_out));
save_item(NAME(m_onebyte_midi));
@@ -1556,11 +1561,8 @@ void sb_device::dack_w(int line, uint8_t data)
}
}
-void sb_device::device_timer(emu_timer &timer, device_timer_id tid, int param, void *ptr)
+TIMER_CALLBACK_MEMBER(sb_device::timer_tick)
{
- if (tid)
- return;
-
// printf("DMA timer expire\n");
uint16_t lsample, rsample;
switch (m_dsp.flags) {
@@ -1818,3 +1820,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 1517ef64308..6fe3782fc95 100644
--- a/src/devices/bus/isa/sblaster.h
+++ b/src/devices/bus/isa/sblaster.h
@@ -8,9 +8,9 @@
#include "isa.h"
#include "bus/midi/midi.h"
#include "bus/pc_joy/pc_joy.h"
-#include "sound/3812intf.h"
#include "sound/dac.h"
#include "sound/saa1099.h"
+#include "sound/ymopl.h"
#include "diserial.h"
//**************************************************************************
@@ -28,16 +28,16 @@ public:
void queue_r(uint8_t data);
uint8_t dequeue_r();
- DECLARE_READ8_MEMBER(dsp_reset_r);
- DECLARE_WRITE8_MEMBER(dsp_reset_w);
- DECLARE_READ8_MEMBER(dsp_data_r);
- DECLARE_WRITE8_MEMBER(dsp_data_w);
- DECLARE_READ8_MEMBER(dsp_rbuf_status_r);
- DECLARE_READ8_MEMBER(dsp_wbuf_status_r);
- DECLARE_WRITE8_MEMBER(dsp_rbuf_status_w);
- DECLARE_WRITE8_MEMBER(dsp_cmd_w);
+ uint8_t dsp_reset_r(offs_t offset);
+ void dsp_reset_w(offs_t offset, uint8_t data);
+ uint8_t dsp_data_r(offs_t offset);
+ void dsp_data_w(offs_t offset, uint8_t data);
+ uint8_t dsp_rbuf_status_r(offs_t offset);
+ uint8_t dsp_wbuf_status_r(offs_t offset);
+ 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);
@@ -108,15 +108,15 @@ protected:
sb_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_start() override ATTR_COLD;
+ virtual void device_reset() override ATTR_COLD;
+
uint8_t dack_r(int line);
void dack_w(int line, uint8_t data);
- virtual void device_timer(emu_timer &timer, device_timer_id id, int param, void *ptr) override;
virtual void drq16_w(int state) { }
virtual void drq_w(int state) { }
virtual void irq_w(int state, int source) { }
- virtual void mixer_reset() {}
+ virtual void mixer_reset() { }
void adpcm_decode(uint8_t sample, int size);
// serial overrides
@@ -126,6 +126,8 @@ protected:
static constexpr unsigned MIDI_RING_SIZE = 2048;
+ TIMER_CALLBACK_MEMBER(timer_tick);
+
required_device<dac_16bit_r2r_device> m_ldac;
required_device<dac_16bit_r2r_device> m_rdac;
required_device<pc_joy_device> m_joy;
@@ -150,14 +152,14 @@ class sb8_device : public sb_device,
public device_isa8_card_interface
{
public:
- DECLARE_READ8_MEMBER(ym3812_16_r);
- DECLARE_WRITE8_MEMBER(ym3812_16_w);
- virtual ioport_constructor device_input_ports() const override;
+ uint8_t ym3812_16_r(offs_t offset);
+ void ym3812_16_w(offs_t offset, uint8_t data);
+ virtual ioport_constructor device_input_ports() const override ATTR_COLD;
protected:
// construction/destruction
sb8_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_start() override ATTR_COLD;
virtual void drq_w(int state) override;
virtual void irq_w(int state, int source) override;
virtual uint8_t dack_r(int line) override { return sb_device::dack_r(line); }
@@ -172,16 +174,16 @@ public:
// construction/destruction
isa8_sblaster1_0_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
- DECLARE_READ8_MEMBER(saa1099_16_r);
- DECLARE_WRITE8_MEMBER(saa1099_1_16_w);
- DECLARE_WRITE8_MEMBER(saa1099_2_16_w);
+ uint8_t saa1099_16_r(offs_t offset);
+ void saa1099_1_16_w(offs_t offset, uint8_t data);
+ void saa1099_2_16_w(offs_t offset, uint8_t data);
protected:
// device-level overrides
- virtual void device_start() override;
+ virtual void device_start() override ATTR_COLD;
// optional information overrides
- virtual void device_add_mconfig(machine_config &config) override;
+ virtual void device_add_mconfig(machine_config &config) override ATTR_COLD;
private:
// internal state
@@ -197,25 +199,25 @@ public:
protected:
// device-level overrides
- virtual void device_start() override;
+ virtual void device_start() override ATTR_COLD;
// optional information overrides
- virtual void device_add_mconfig(machine_config &config) override;
+ virtual void device_add_mconfig(machine_config &config) override ATTR_COLD;
};
class sb16_device : public sb_device,
public device_isa16_card_interface
{
public:
- DECLARE_READ8_MEMBER(mpu401_r);
- DECLARE_WRITE8_MEMBER(mpu401_w);
- DECLARE_READ8_MEMBER(mixer_r);
- DECLARE_WRITE8_MEMBER(mixer_w);
- virtual ioport_constructor device_input_ports() const override;
+ uint8_t mpu401_r(offs_t offset);
+ void mpu401_w(offs_t offset, uint8_t data);
+ uint8_t mixer_r(offs_t offset);
+ void mixer_w(offs_t offset, uint8_t data);
+ virtual ioport_constructor device_input_ports() const override ATTR_COLD;
protected:
// construction/destruction
sb16_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_start() override ATTR_COLD;
virtual uint16_t dack16_r(int line) override;
virtual uint8_t dack_r(int line) override { return sb_device::dack_r(line); }
virtual void dack_w(int line, uint8_t data) override { sb_device::dack_w(line, data); }
@@ -238,10 +240,11 @@ public:
protected:
// device-level overrides
- virtual void device_start() override;
+ virtual void device_start() override ATTR_COLD;
// optional information overrides
- virtual void device_add_mconfig(machine_config &config) override;
+ virtual void device_add_mconfig(machine_config &config) override ATTR_COLD;
+ 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 92f049f0402..f7775f83a75 100644
--- a/src/devices/bus/isa/sc499.cpp
+++ b/src/devices/bus/isa/sc499.cpp
@@ -16,16 +16,14 @@
#include "emu.h"
#include "sc499.h"
-#include "formats/ioprocs.h"
-#define VERBOSE 0
+#define LOG_LEVEL0 (0x1U << 1)
+#define LOG_LEVEL1 (0x3U << 1)
+#define LOG_LEVEL2 (0x7U << 1)
+#define LOG_LEVEL3 (0xfU << 1)
-static int verbose = VERBOSE;
-
-#define LOG(x) { logerror ("%s: ", cpu_context()); logerror x; logerror ("\n"); }
-#define LOG1(x) { if (verbose > 0) LOG(x)}
-#define LOG2(x) { if (verbose > 1) LOG(x)}
-#define LOG3(x) { if (verbose > 2) LOG(x)}
+#define VERBOSE (LOG_LEVEL0)
+#include "logmacro.h"
#define SC499_CTAPE_TAG "sc499_ctape"
DECLARE_DEVICE_TYPE(SC499_CTAPE, sc499_ctape_image_device)
@@ -332,20 +330,20 @@ void sc499_device::device_start()
{
set_isa_device();
- LOG1(("start sc499"));
+ LOGMASKED(LOG_LEVEL1, "%s: start sc499", cpu_context());
- m_timer = timer_alloc(0, nullptr);
- m_timer1 = timer_alloc(1, nullptr);
+ m_timer = timer_alloc(FUNC(sc499_device::timer_func), this);
+ m_timer1 = timer_alloc(FUNC(sc499_device::timer_func), this);
m_installed = false;
if (!m_image->is_open())
{
- LOG2(("start sc499: no cartridge tape"));
+ LOGMASKED(LOG_LEVEL2, "%s: start sc499: no cartridge tape", cpu_context());
}
else
{
- LOG2(("start sc499: cartridge tape image is %s", m_image->filename()));
+ LOGMASKED(LOG_LEVEL2, "%s: start sc499: cartridge tape image is %s", cpu_context(), m_image->filename());
}
m_ctape_block_buffer.resize(SC499_CTAPE_BLOCK_SIZE);
@@ -389,7 +387,7 @@ void sc499_device::device_reset()
m_irq = m_irqdrq->read() & 7;
m_drq = m_irqdrq->read()>>4;
- m_isa->install_device(base, base+7, read8_delegate(FUNC(sc499_device::read), this), write8_delegate(FUNC(sc499_device::write), this));
+ m_isa->install_device(base, base+7, read8sm_delegate(*this, FUNC(sc499_device::read)), write8sm_delegate(*this, FUNC(sc499_device::write)));
m_isa->set_dma_channel(m_drq, this, true);
m_installed = true;
@@ -410,16 +408,6 @@ std::string sc499_device::cpu_context() const
}
/*-------------------------------------------------
- logerror - log an error message (w/o device tags)
- -------------------------------------------------*/
-
-template <typename Format, typename... Params>
-void sc499_device::logerror(Format &&fmt, Params &&... args) const
-{
- machine().logerror(std::forward<Format>(fmt), std::forward<Params>(args)...);
-}
-
-/*-------------------------------------------------
tape_status_clear - clear bits in tape status
-------------------------------------------------*/
@@ -472,7 +460,7 @@ void sc499_device::check_tape()
m_ctape_block_count = (uint32_t)((m_image_length + SC499_CTAPE_BLOCK_SIZE - 1) / SC499_CTAPE_BLOCK_SIZE);
}
- LOG1(("check_tape: tape image is %s with %d blocks", m_image->filename(), m_ctape_block_count));
+ LOGMASKED(LOG_LEVEL1, "%s: check_tape: tape image is %s with %d blocks", cpu_context(), m_image->filename(), m_ctape_block_count);
}
else
{
@@ -481,7 +469,7 @@ void sc499_device::check_tape()
m_image_length = 0;
m_ctape_block_count = 0;
- LOG1(("check_tape: no cartridge tape"));
+ LOGMASKED(LOG_LEVEL1, "%s: check_tape: no cartridge tape", cpu_context());
}
}
@@ -489,9 +477,9 @@ void sc499_device::check_tape()
timer_func - handle timer interrupts
-------------------------------------------------*/
-void sc499_device::device_timer(emu_timer &timer, device_timer_id id, int param, void *ptr)
+TIMER_CALLBACK_MEMBER(sc499_device::timer_func)
{
- LOG2(("timer_func param=%d status=%x", param, m_status));
+ LOGMASKED(LOG_LEVEL2, "%s: timer_func param=%d status=%x", cpu_context(), param, m_status);
switch (param)
{
@@ -556,20 +544,20 @@ void sc499_device::device_timer(emu_timer &timer, device_timer_id id, int param,
tape_status_clear(SC499_ST_CLEAR_ALL);
tape_status_set(SC499_ST_READ_ERROR);
- LOG(("timer_func param=%d status=%x tape_pos=%d - read data underrun aborted at %d",
- param, m_status, m_tape_pos, m_underrun_counter));
+ LOGMASKED(LOG_LEVEL0, "%s: timer_func param=%d status=%x tape_pos=%d - read data underrun aborted at %d",
+ cpu_context(), param, m_status, m_tape_pos, m_underrun_counter);
}
else
{
- LOG2(("timer_func param=%d status=%x tape_pos=%d - read data underrun %d",
- param, m_status, m_tape_pos, m_underrun_counter));
+ LOGMASKED(LOG_LEVEL2, "%s: timer_func param=%d status=%x tape_pos=%d - read data underrun %d",
+ cpu_context(), param, m_status, m_tape_pos, m_underrun_counter);
}
break;
}
else if ( m_tape_pos > m_ctape_block_count || !(m_status & SC499_STAT_RDY))
{
- LOG1(("timer_func param=%d status=%x tape_pos=%d - end-of-tape or not ready",
- param, m_status, m_tape_pos));
+ LOGMASKED(LOG_LEVEL1, "%s: timer_func param=%d status=%x tape_pos=%d - end-of-tape or not ready",
+ cpu_context(), param, m_status, m_tape_pos);
m_timer1->adjust(attotime::never, param, attotime::never);
m_status &= ~SC499_STAT_EXC;
m_status &= ~SC499_STAT_DIR;
@@ -584,8 +572,8 @@ void sc499_device::device_timer(emu_timer &timer, device_timer_id id, int param,
{
if (m_underrun_counter > 0)
{
- LOG1(("timer_func param=%d status=%x tape_pos=%d - read data underrun ended at %d",
- param, m_status, m_tape_pos, m_underrun_counter));
+ LOGMASKED(LOG_LEVEL1, "%s: timer_func param=%d status=%x tape_pos=%d - read data underrun ended at %d",
+ cpu_context(), param, m_status, m_tape_pos, m_underrun_counter);
}
read_block();
@@ -623,7 +611,7 @@ void sc499_device::device_timer(emu_timer &timer, device_timer_id id, int param,
break;
default:
- LOG(("timer_func param=%d UNEXPECTED", param));
+ LOGMASKED(LOG_LEVEL0, "%s: timer_func param=%d UNEXPECTED", cpu_context(), param);
m_timer->reset();
break;
}
@@ -638,7 +626,7 @@ void sc499_device::set_interrupt(enum line_state state)
{
if (state != irq_state)
{
- LOG2(("set_interrupt(%d)",state));
+ LOGMASKED(LOG_LEVEL2, "%s: set_interrupt(%d)", cpu_context(), state);
switch (m_irq)
{
case 2: m_isa->irq2_w(state); break;
@@ -661,7 +649,7 @@ void sc499_device::set_dma_drq(enum line_state state)
{
if (state != dma_drq_state)
{
- LOG2(("set_dma_drq(%d)",state));
+ LOGMASKED(LOG_LEVEL2, "%s: set_dma_drq(%d)", cpu_context(), state);
switch (m_drq)
{
@@ -686,36 +674,36 @@ void sc499_device::log_command(uint8_t data)
case SC499_CMD_SEL_2:
case SC499_CMD_SEL_3:
case SC499_CMD_SEL_4:
- LOG1(("write_command_port: %02x Select %x", data, data & 0x1f));
+ LOGMASKED(LOG_LEVEL1, "%s: write_command_port: %02x Select %x", cpu_context(), data, data & 0x1f);
break;
case SC499_CMD_REWIND: // rewind tape
- LOG1(("write_command_port: %02x Rewind Tape", data));
+ LOGMASKED(LOG_LEVEL1, "%s: write_command_port: %02x Rewind Tape", cpu_context(), data);
break;
case SC499_CMD_ERASE: // erase tape
- LOG1(("write_command_port: %02x Erase Tape", data));
+ LOGMASKED(LOG_LEVEL1, "%s: write_command_port: %02x Erase Tape", cpu_context(), data);
break;
case SC499_CMD_RETEN: // retention tape
- LOG1(("write_command_port: %02x Retention Tape", data));
+ LOGMASKED(LOG_LEVEL1, "%s: write_command_port: %02x Retention Tape", cpu_context(), data);
break;
case SC499_CMD_WRITE_DATA:
- LOG1(("write_command_port: %02x Write Data %d ...", data, m_tape_pos));
+ LOGMASKED(LOG_LEVEL1, "%s: write_command_port: %02x Write Data %d ...", cpu_context(), data, m_tape_pos);
break;
case SC499_CMD_WRITE_FILEMARK:
- LOG1(("write_command_port: %02x Write File Mark %d", data, m_tape_pos));
+ LOGMASKED(LOG_LEVEL1, "%s: write_command_port: %02x Write File Mark %d", cpu_context(), data, m_tape_pos);
break;
case SC499_CMD_READ_DATA:
- LOG1(("write_command_port: %02x Read Data %d ...", data, m_tape_pos));
+ LOGMASKED(LOG_LEVEL1, "%s: write_command_port: %02x Read Data %d ...", cpu_context(), data, m_tape_pos);
break;
case SC499_CMD_READ_FILE_MARK:
- LOG1(("write_command_port: %02x Read File Mark %d", data, m_tape_pos));
+ LOGMASKED(LOG_LEVEL1, "%s: write_command_port: %02x Read File Mark %d", cpu_context(), data, m_tape_pos);
break;
case SC499_CMD_READ_STATUS:
- LOG1(("write_command_port: %02x Read Status (%04x %04x %04x)", data,
- m_tape_status, m_data_error_counter, m_underrun_counter));
+ LOGMASKED(LOG_LEVEL1, "%s: write_command_port: %02x Read Status (%04x %04x %04x)", cpu_context(), data,
+ m_tape_status, m_data_error_counter, m_underrun_counter);
break;
case SC499_CMD_RESERVED: // Reserved
default:
- LOG(("write_command_port: %02x Unexpected Command!", data));
+ LOGMASKED(LOG_LEVEL0, "%s: write_command_port: %02x Unexpected Command!", cpu_context(), data);
break;
}
}
@@ -784,7 +772,7 @@ void sc499_device::do_command(uint8_t data)
{
// SC499_CMD_READ_DATA pending
m_status &= ~SC499_STAT_DIR;
- LOG1(("do_command: Read data -> Read File Mark at %d", m_tape_pos));
+ LOGMASKED(LOG_LEVEL1, "%s: do_command: Read data -> Read File Mark at %d", cpu_context(), m_tape_pos);
}
else
{
@@ -819,7 +807,7 @@ void sc499_device::do_command(uint8_t data)
void sc499_device::do_reset()
{
- LOG1(("do_reset: Reset controller microprocessor"));
+ LOGMASKED(LOG_LEVEL1, "%s: do_reset: Reset controller microprocessor", cpu_context());
m_data = 0;
m_command = SC499_CMD_NO_COMMAND;
@@ -861,7 +849,7 @@ uint8_t sc499_device::read_data_port()
// omit excessive logging
if (m_last_data != m_data)
{
- LOG2(("read_data_port: %02x", m_data));
+ LOGMASKED(LOG_LEVEL2, "%s: read_data_port: %02x", cpu_context(), m_data);
m_last_data = m_data;
}
@@ -876,7 +864,7 @@ uint8_t sc499_device::read_data_port()
void sc499_device::write_control_port( uint8_t data)
{
- LOG2(("write_control_port: %02x", data));
+ LOGMASKED(LOG_LEVEL2, "%s: write_control_port: %02x", cpu_context(), data);
if ((data ^ m_control) & SC499_CTR_RST)
{
@@ -897,7 +885,7 @@ void sc499_device::write_control_port( uint8_t data)
// Request to LSI chip has changed
if (data & SC499_CTR_REQ)
{
- LOG3(("write_control_port: Request to LSI chip = On"));
+ LOGMASKED(LOG_LEVEL3, "%s: write_control_port: Request to LSI chip = On", cpu_context());
if (m_command == SC499_CMD_READ_STATUS) {
m_status |= SC499_STAT_EXC;
@@ -922,7 +910,7 @@ void sc499_device::write_control_port( uint8_t data)
}
else
{
- LOG2(("write_control_port: Request to LSI chip = Off (%d)", m_data_index));
+ LOGMASKED(LOG_LEVEL2, "%s: write_control_port: Request to LSI chip = Off (%d)", cpu_context(), m_data_index);
if (!(m_status & SC499_STAT_DIR))
{
@@ -948,7 +936,7 @@ uint8_t sc499_device::read_status_port()
// omit excessive logging
if (m_last_status != m_status)
{
- LOG2(("read_status_port: %02x", m_status));
+ LOGMASKED(LOG_LEVEL2, "%s: read_status_port: %02x", cpu_context(), m_status);
m_last_status = m_status;
}
@@ -963,7 +951,7 @@ uint8_t sc499_device::read_status_port()
void sc499_device::write_dma_go( uint8_t data)
{
- LOG2(("write_dma_go: %02x", data));
+ LOGMASKED(LOG_LEVEL2, "%s: write_dma_go: %02x", cpu_context(), data);
m_status &= ~SC499_STAT_DON;
@@ -1008,13 +996,13 @@ void sc499_device::write_dma_go( uint8_t data)
void sc499_device::write_dma_reset( uint8_t data)
{
- LOG2(("write_dma_reset: %02x", data));
+ LOGMASKED(LOG_LEVEL2, "%s: write_dma_reset: %02x", cpu_context(), data);
m_status &= ~SC499_STAT_DON;
m_control = 0;
}
-WRITE8_MEMBER(sc499_device::write)
+void sc499_device::write(offs_t offset, uint8_t data)
{
switch (offset)
{
@@ -1031,12 +1019,12 @@ WRITE8_MEMBER(sc499_device::write)
write_dma_reset(data);
break;
default:
- LOG(("writing sc499 Register at offset %02x = %02x", offset, data));
+ LOGMASKED(LOG_LEVEL0, "%s: writing sc499 Register at offset %02x = %02x", cpu_context(), offset, data);
break;
}
}
-READ8_MEMBER(sc499_device::read)
+uint8_t sc499_device::read(offs_t offset)
{
uint8_t data = 0xff;
@@ -1050,7 +1038,7 @@ READ8_MEMBER(sc499_device::read)
// set_interrupt(CLEAR_LINE);
break;
default:
- LOG(("reading sc499 Register at offset %02x = %02x", offset, data));
+ LOGMASKED(LOG_LEVEL0, "%s: reading sc499 Register at offset %02x = %02x", cpu_context(), offset, data);
break;
}
@@ -1059,7 +1047,7 @@ READ8_MEMBER(sc499_device::read)
void sc499_device::eop_w(int state)
{
- LOG2(("set_tc_state: block=%d state=%x", m_tape_pos-1, state));
+ LOGMASKED(LOG_LEVEL2, "%s: set_tc_state: block=%d state=%x", cpu_context(), m_tape_pos - 1, state);
if (state == 0)
{
m_status |= SC499_STAT_DON; // 37ec
@@ -1091,7 +1079,7 @@ uint8_t sc499_device::dack_r(int line)
if (m_ctape_block_index >= SC499_CTAPE_BLOCK_SIZE)
{
- LOG3(("dack_read: read_block"));
+ LOGMASKED(LOG_LEVEL3, "%s: dack_read: read_block", cpu_context());
read_block();
m_nasty_readahead++;
@@ -1106,7 +1094,7 @@ uint8_t sc499_device::dack_r(int line)
data = m_ctape_block_buffer[m_ctape_block_index++];
if (m_ctape_block_index < 2 || m_ctape_block_index > 511)
{
- LOG2(("dack_read: data[%d]=%x status=%x", m_ctape_block_index-1, data, m_status));
+ LOGMASKED(LOG_LEVEL2, "%s: dack_read: data[%d]=%x status=%x", cpu_context(), m_ctape_block_index - 1, data, m_status);
}
// if (m_ctape_block_index < SC499_CTAPE_BLOCK_SIZE)
@@ -1119,7 +1107,7 @@ uint8_t sc499_device::dack_r(int line)
void sc499_device::dack_w(int line, uint8_t data)
{
- LOG3(("dack_write: data=%x", data));
+ LOGMASKED(LOG_LEVEL3, "%s: dack_write: data=%x", cpu_context(), data);
if (m_ctape_block_index < SC499_CTAPE_BLOCK_SIZE)
{
@@ -1128,7 +1116,7 @@ void sc499_device::dack_w(int line, uint8_t data)
if (m_ctape_block_index == SC499_CTAPE_BLOCK_SIZE)
{
- LOG3(("dack_write: write_block"));
+ LOGMASKED(LOG_LEVEL3, "%s: dack_write: write_block", cpu_context());
write_block();
}
}
@@ -1141,7 +1129,7 @@ void sc499_device::log_block(const char *text)
{
int data_length = 16;
- if (verbose > 0) {
+ if (VERBOSE & (LOG_LEVEL1 | LOG_LEVEL2 | LOG_LEVEL3)) {
int i;
logerror("%s: %s %d -", cpu_context(), text, m_tape_pos);
for (i = 0; i < data_length && i < SC499_CTAPE_BLOCK_SIZE; i++) {
@@ -1190,7 +1178,7 @@ void sc499_device::read_block()
{
memcpy(&m_ctape_block_buffer[0], tape, SC499_CTAPE_BLOCK_SIZE);
- // if (verbose > 1 || m_tape_pos % 100 == 0)
+ // if (m_tape_pos % 100 == 0)
{
log_block("read_block");
}
@@ -1203,7 +1191,7 @@ void sc499_device::read_block()
// FIXME: we must read first block twice (in MD for 'di c' and 'ld' or 'ex ...')
// why is this necessary???
m_tape_pos = 0;
- LOG(("read_block - duplicating block %d", m_tape_pos));
+ LOGMASKED(LOG_LEVEL0, "%s: read_block - duplicating block %d", cpu_context(), m_tape_pos);
}
m_first_block_hack = 0;
@@ -1261,9 +1249,9 @@ int sc499_device::block_is_filemark()
static const uint8_t fm_pattern[] = {0xDE, 0xAF, 0xFA, 0xED};
int is_filemark = memcmp(&m_ctape_block_buffer[0], fm_pattern, 4) == 0 &&
- memcmp(&m_ctape_block_buffer[0], &m_ctape_block_buffer[4], SC499_CTAPE_BLOCK_SIZE-4) == 0;
+ memcmp(&m_ctape_block_buffer[0], &m_ctape_block_buffer[4], SC499_CTAPE_BLOCK_SIZE - 4) == 0;
- LOG3(("block_is_filemark for block %d = %d", m_tape_pos-1, is_filemark));
+ LOGMASKED(LOG_LEVEL3, "%s: block_is_filemark for block %d = %d", cpu_context(), m_tape_pos - 1, is_filemark);
return is_filemark;
}
@@ -1285,8 +1273,7 @@ void sc499_device::block_set_filemark()
DEFINE_DEVICE_TYPE(SC499_CTAPE, sc499_ctape_image_device, "sc499_ctape", "SC-499 Cartridge Tape")
sc499_ctape_image_device::sc499_ctape_image_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
- : device_t(mconfig, SC499_CTAPE, tag, owner, clock)
- , device_image_interface(mconfig, *this)
+ : microtape_image_device(mconfig, SC499_CTAPE, tag, owner, clock)
{
}
@@ -1308,20 +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()
{
- uint32_t size;
- io_generic io;
- io.file = (device_image_interface *)this;
- io.procs = &image_ioprocs;
- io.filler = 0xff;
-
- size = io_generic_size(&io);
- m_ctape_data.resize(size);
-
- io_generic_read(&io, &m_ctape_data[0], 0, size);
-
- return image_init_result::PASS;
+ try
+ {
+ auto const size = length();
+ m_ctape_data.resize(size);
+ if (!fseek(0, SEEK_SET) && (fread(m_ctape_data.data(), size) == size))
+ return std::make_pair(std::error_condition(), std::string());
+ }
+ catch (...)
+ {
+ }
+ return std::make_pair(image_error::UNSPECIFIED, std::string());
}
void sc499_ctape_image_device::call_unload()
@@ -1334,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 70bb647463f..76f59996452 100644
--- a/src/devices/bus/isa/sc499.h
+++ b/src/devices/bus/isa/sc499.h
@@ -13,8 +13,9 @@
#pragma once
-#include "bus/isa/isa.h"
-#include "softlist_dev.h"
+#include "isa.h"
+
+#include "imagedev/magtape.h"
//**************************************************************************
@@ -23,36 +24,29 @@
// ======================> sc499_ctape_image_device
-class sc499_ctape_image_device : public device_t, public device_image_interface
+class sc499_ctape_image_device : public microtape_image_device
{
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;
- virtual const software_list_loader &get_software_list_loader() const override { return image_software_list_loader::instance(); }
+ // device_image_interface implementation
+ virtual std::pair<std::error_condition, std::string> call_load() override;
virtual void call_unload() override;
- virtual iodevice_t image_type() const override { return IO_MAGTAPE; }
-
- virtual bool is_readable() const override { return 1; }
- virtual bool is_writeable() const override { return 1; }
- virtual bool is_creatable() const override { return 1; }
- virtual bool must_be_loaded() const override { return 0; }
- virtual bool is_reset_on_load() const override { return 0; }
- virtual bool support_command_line_image_creation() const override { return 1; }
- virtual const char *image_interface() const override { return "sc499_cass"; }
- virtual const char *file_extensions() const override { return "act,ct"; }
- virtual const char *custom_instance_name() const override { return "ctape"; }
- virtual const char *custom_brief_instance_name() const override { return "ct"; }
+
+ virtual bool support_command_line_image_creation() const noexcept override { return true; }
+ virtual const char *image_interface() const noexcept override { return "sc499_cass"; }
+ virtual const char *file_extensions() const noexcept override { return "act,ct"; }
+ virtual const char *image_type_name() const noexcept override { return "ctape"; }
+ virtual const char *image_brief_type_name() const noexcept override { return "ct"; }
uint8_t *read_block(int block_num);
void write_block(int block_num, uint8_t *ptr);
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 ATTR_COLD;
std::vector<uint8_t> m_ctape_data;
};
@@ -71,11 +65,10 @@ protected:
private:
// device-level overrides
- virtual void device_start() override;
- virtual void device_reset() override;
- virtual void device_timer(emu_timer &timer, device_timer_id id, int param, void *ptr) override;
- virtual void device_add_mconfig(machine_config &config) override;
- virtual ioport_constructor device_input_ports() const override;
+ 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;
+ virtual ioport_constructor device_input_ports() const override ATTR_COLD;
// ISA overrides
virtual uint8_t dack_r(int line) override;
@@ -83,14 +76,13 @@ private:
virtual void eop_w(int state) override;
std::string cpu_context() const;
- template <typename Format, typename... Params> void logerror(Format &&fmt, Params &&... args) const;
void tape_status_clear(uint16_t value);
void tape_status_set(uint16_t value);
// device register I/O
- DECLARE_READ8_MEMBER(read);
- DECLARE_WRITE8_MEMBER(write);
+ uint8_t read(offs_t offset);
+ void write(offs_t offset, uint8_t data);
void check_tape();
@@ -115,6 +107,8 @@ private:
int block_is_filemark();
void block_set_filemark();
+ TIMER_CALLBACK_MEMBER(timer_func);
+
uint8_t m_data;
uint8_t m_command;
uint8_t m_status;
diff --git a/src/devices/bus/isa/side116.cpp b/src/devices/bus/isa/side116.cpp
index 19c806ec8be..de47081b9fd 100644
--- a/src/devices/bus/isa/side116.cpp
+++ b/src/devices/bus/isa/side116.cpp
@@ -112,16 +112,16 @@ void side116_device::device_reset()
{
switch ((m_config->read() >> 1) & 0x03)
{
- case 0: m_isa->install_rom(this, 0xc8000, 0xc9fff, "side116", "option"); break;
- case 1: m_isa->install_rom(this, 0xd8000, 0xd9fff, "side116", "option"); break;
- case 2: m_isa->install_rom(this, 0xcc000, 0xcdfff, "side116", "option"); break;
- case 3: m_isa->install_rom(this, 0xdc000, 0xddfff, "side116", "option"); break;
+ case 0: m_isa->install_rom(this, 0xc8000, 0xc9fff, "option"); break;
+ case 1: m_isa->install_rom(this, 0xd8000, 0xd9fff, "option"); break;
+ case 2: m_isa->install_rom(this, 0xcc000, 0xcdfff, "option"); break;
+ case 3: m_isa->install_rom(this, 0xdc000, 0xddfff, "option"); break;
}
}
// install io access
if ((m_config->read() & 0x20) == 0x20)
- m_isa->install_device(0x360, 0x36f, read8_delegate(FUNC(side116_device::read), this), write8_delegate(FUNC(side116_device::write), this));
+ m_isa->install_device(0x360, 0x36f, read8sm_delegate(*this, FUNC(side116_device::read)), write8sm_delegate(*this, FUNC(side116_device::write)));
}
@@ -129,19 +129,19 @@ void side116_device::device_reset()
// IDE INTERFACE
//**************************************************************************
-READ8_MEMBER( side116_device::read )
+uint8_t side116_device::read(offs_t offset)
{
uint8_t data;
if (offset == 0)
{
- uint16_t ide_data = m_ata->read_cs0(0);
+ uint16_t ide_data = m_ata->cs0_r(0);
data = ide_data & 0xff;
m_latch = ide_data >> 8;
}
else if (offset < 8)
{
- data = m_ata->read_cs0(offset & 7, 0xff);
+ data = m_ata->cs0_r(offset & 7, 0xff);
}
else if (offset == 8)
{
@@ -149,22 +149,22 @@ READ8_MEMBER( side116_device::read )
}
else
{
- data = m_ata->read_cs1(offset & 7, 0xff);
+ data = m_ata->cs1_r(offset & 7, 0xff);
}
return data;
}
-WRITE8_MEMBER( side116_device::write )
+void side116_device::write(offs_t offset, uint8_t data)
{
if (offset == 0)
{
uint16_t ide_data = (m_latch << 8) | data;
- m_ata->write_cs0(0, ide_data);
+ m_ata->cs0_w(0, ide_data);
}
else if (offset < 8)
{
- m_ata->write_cs0(offset & 7, data, 0xff);
+ m_ata->cs0_w(offset & 7, data, 0xff);
}
else if (offset == 8)
{
@@ -172,11 +172,11 @@ WRITE8_MEMBER( side116_device::write )
}
else
{
- m_ata->write_cs1(offset & 7, data, 0xff);
+ m_ata->cs1_w(offset & 7, data, 0xff);
}
}
-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 ac49b3efead..db40b4bee7b 100644
--- a/src/devices/bus/isa/side116.h
+++ b/src/devices/bus/isa/side116.h
@@ -13,7 +13,7 @@
#pragma once
-#include "machine/ataintf.h"
+#include "bus/ata/ataintf.h"
#include "isa.h"
@@ -29,21 +29,21 @@ public:
// construction/destruction
side116_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
- DECLARE_READ8_MEMBER( read );
- DECLARE_WRITE8_MEMBER( write );
+ uint8_t read(offs_t offset);
+ void write(offs_t offset, uint8_t data);
protected:
// device-level overrides
- virtual void device_start() override;
- virtual void device_reset() override;
+ virtual void device_start() override ATTR_COLD;
+ virtual void device_reset() override ATTR_COLD;
// optional information 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;
+ virtual void device_add_mconfig(machine_config &config) override ATTR_COLD;
+ virtual ioport_constructor device_input_ports() const override ATTR_COLD;
+ virtual const tiny_rom_entry *device_rom_region() const override ATTR_COLD;
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/ssi2001.cpp b/src/devices/bus/isa/ssi2001.cpp
index 2c433321847..e1d271dc6b4 100644
--- a/src/devices/bus/isa/ssi2001.cpp
+++ b/src/devices/bus/isa/ssi2001.cpp
@@ -29,11 +29,10 @@ ssi2001_device::ssi2001_device(const machine_config &mconfig, const char *tag, d
void ssi2001_device::device_start()
{
set_isa_device();
- m_isa->install_device(0x0200, 0x0207, read8_delegate(FUNC(pc_joy_device::joy_port_r), subdevice<pc_joy_device>("pc_joy")), write8_delegate(FUNC(pc_joy_device::joy_port_w), subdevice<pc_joy_device>("pc_joy")));
- m_isa->install_device(0x0280, 0x029F, read8sm_delegate(FUNC(mos6581_device::read), subdevice<mos6581_device>("sid6581")), write8sm_delegate(FUNC(mos6581_device::write), subdevice<mos6581_device>("sid6581")));
+ 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(0x0280, 0x029F, read8sm_delegate(*subdevice<mos6581_device>("sid6581"), FUNC(mos6581_device::read)), write8sm_delegate(*subdevice<mos6581_device>("sid6581"), FUNC(mos6581_device::write)));
}
-
void ssi2001_device::device_reset()
{
}
diff --git a/src/devices/bus/isa/ssi2001.h b/src/devices/bus/isa/ssi2001.h
index 85efa17c5ac..329a2a12c26 100644
--- a/src/devices/bus/isa/ssi2001.h
+++ b/src/devices/bus/isa/ssi2001.h
@@ -24,11 +24,11 @@ public:
protected:
// device-level overrides
- virtual void device_start() override;
- virtual void device_reset() override;
+ virtual void device_start() override ATTR_COLD;
+ virtual void device_reset() override ATTR_COLD;
// optional information overrides
- virtual void device_add_mconfig(machine_config &config) override;
+ virtual void device_add_mconfig(machine_config &config) override ATTR_COLD;
required_device<pc_joy_device> m_joy;
required_device<mos6581_device> m_sid;
diff --git a/src/devices/bus/isa/stereo_fx.cpp b/src/devices/bus/isa/stereo_fx.cpp
index b23a0dbe454..bfd6eb6cfe5 100644
--- a/src/devices/bus/isa/stereo_fx.cpp
+++ b/src/devices/bus/isa/stereo_fx.cpp
@@ -8,31 +8,31 @@
#include "stereo_fx.h"
#include "sound/dac.h"
-#include "sound/volt_reg.h"
#include "speaker.h"
DEFINE_DEVICE_TYPE(ISA8_STEREO_FX, stereo_fx_device, "stereo_fx", "ATi Stereo F/X Audio Adapter")
-READ8_MEMBER( stereo_fx_device::dev_dsp_data_r )
+uint8_t stereo_fx_device::dev_dsp_data_r()
{
- m_data_in = false;
+ if (!machine().side_effects_disabled())
+ m_data_in = false;
return m_in_byte;
}
-WRITE8_MEMBER( stereo_fx_device::dev_dsp_data_w )
+void stereo_fx_device::dev_dsp_data_w(uint8_t data)
{
m_data_out = true;
m_out_byte = data;
}
// port 1 is the left DAC but is written and read bitwise during capture
-READ8_MEMBER( stereo_fx_device::p1_r )
+uint8_t stereo_fx_device::p1_r()
{
return 0x80;
}
-READ8_MEMBER( stereo_fx_device::p3_r )
+uint8_t stereo_fx_device::p3_r()
{
uint8_t ret = 0;
@@ -43,17 +43,17 @@ READ8_MEMBER( stereo_fx_device::p3_r )
return ret;
}
-WRITE8_MEMBER( stereo_fx_device::p3_w )
+void stereo_fx_device::p3_w(uint8_t data)
{
m_t1 = (data & 0x20) >> 5;
}
-WRITE8_MEMBER( stereo_fx_device::dev_host_irq_w )
+void stereo_fx_device::dev_host_irq_w(uint8_t data)
{
m_isa->irq5_w(1);
}
-WRITE8_MEMBER( stereo_fx_device::raise_drq_w )
+void stereo_fx_device::raise_drq_w(uint8_t data)
{
m_isa->drq1_w(1);
}
@@ -68,7 +68,7 @@ WRITE8_MEMBER( stereo_fx_device::raise_drq_w )
* bit6 -
* bit7 -
*/
-WRITE8_MEMBER( stereo_fx_device::port20_w )
+void stereo_fx_device::port20_w(uint8_t data)
{
m_port20 = data;
}
@@ -83,7 +83,7 @@ WRITE8_MEMBER( stereo_fx_device::port20_w )
* bit6 -
* bit7 -
*/
-WRITE8_MEMBER( stereo_fx_device::port00_w )
+void stereo_fx_device::port00_w(uint8_t data)
{
m_port00 = data;
}
@@ -98,7 +98,7 @@ void stereo_fx_device::stereo_fx_io(address_map &map)
map(0xFF00, 0xFF00).w(FUNC(stereo_fx_device::port00_w));
map(0xFF10, 0xFF10).w("rdac", FUNC(dac_byte_interface::data_w));
map(0xFF20, 0xFF20).w(FUNC(stereo_fx_device::port20_w));
- //AM_RANGE(0xFF30, 0xFF30) AM_WRITE() // used only on reset and undocumented cmd 0xc4
+ //map(0xFF30, 0xFF30).w(FUNC(stereo_fx_device::)); // used only on reset and undocumented cmd 0xc4
map(0xFF40, 0xFF40).rw(FUNC(stereo_fx_device::dev_dsp_data_r), FUNC(stereo_fx_device::dev_dsp_data_w));
map(0xFF50, 0xFF50).w(FUNC(stereo_fx_device::raise_drq_w));
map(0xFF60, 0xFF60).w(FUNC(stereo_fx_device::dev_host_irq_w));
@@ -124,31 +124,26 @@ void stereo_fx_device::device_add_mconfig(machine_config &config)
m_cpu->port_in_cb<3>().set(FUNC(stereo_fx_device::p3_r));
m_cpu->port_out_cb<3>().set(FUNC(stereo_fx_device::p3_w));
- SPEAKER(config, "lspeaker").front_left();
- SPEAKER(config, "rspeaker").front_right();
+ SPEAKER(config, "speaker", 2).front();
ym3812_device &ym3812(YM3812(config, "ym3812", XTAL(3'579'545)));
- ym3812.add_route(ALL_OUTPUTS, "lspeaker", 1.00);
- ym3812.add_route(ALL_OUTPUTS, "rspeaker", 1.00);
+ ym3812.add_route(ALL_OUTPUTS, "speaker", 1.00, 0);
+ ym3812.add_route(ALL_OUTPUTS, "speaker", 1.00, 1);
/* no CM/S support (empty sockets) */
- DAC_8BIT_R2R(config, "ldac", 0).add_route(ALL_OUTPUTS, "lspeaker", 0.5); // unknown DAC
- DAC_8BIT_R2R(config, "rdac", 0).add_route(ALL_OUTPUTS, "rspeaker", 0.5); // unknown DAC
- voltage_regulator_device &vref(VOLTAGE_REGULATOR(config, "vref", 0));
- vref.add_route(0, "ldac", 1.0, DAC_VREF_POS_INPUT);
- vref.add_route(0, "ldac", -1.0, DAC_VREF_NEG_INPUT);
- vref.add_route(0, "rdac", 1.0, DAC_VREF_POS_INPUT);
- vref.add_route(0, "rdac", -1.0, DAC_VREF_NEG_INPUT);
+ DAC_8BIT_R2R(config, "ldac", 0).add_route(ALL_OUTPUTS, "speaker", 0.5, 0); // unknown DAC
+ DAC_8BIT_R2R(config, "rdac", 0).add_route(ALL_OUTPUTS, "speaker", 0.5, 1); // unknown DAC
PC_JOY(config, m_joy);
}
-READ8_MEMBER( stereo_fx_device::dsp_data_r )
+uint8_t stereo_fx_device::dsp_data_r()
{
- m_data_out = false;
+ if (!machine().side_effects_disabled())
+ m_data_out = false;
return m_out_byte;
}
-WRITE8_MEMBER( stereo_fx_device::dsp_cmd_w )
+void stereo_fx_device::dsp_cmd_w(uint8_t data)
{
m_data_in = true;
m_in_byte = data;
@@ -168,31 +163,33 @@ void stereo_fx_device::dack_w(int line, uint8_t data)
m_in_byte = data;
}
-WRITE8_MEMBER( stereo_fx_device::dsp_reset_w )
+void stereo_fx_device::dsp_reset_w(uint8_t data)
{
device_reset();
m_cpu->pulse_input_line(INPUT_LINE_RESET, attotime::zero);
}
-READ8_MEMBER( stereo_fx_device::dsp_wbuf_status_r )
+uint8_t stereo_fx_device::dsp_wbuf_status_r()
{
return m_data_in << 7;
}
-READ8_MEMBER( stereo_fx_device::dsp_rbuf_status_r )
+uint8_t stereo_fx_device::dsp_rbuf_status_r()
{
- m_isa->irq5_w(0);
+ if (!machine().side_effects_disabled())
+ m_isa->irq5_w(0);
return m_data_out << 7;
}
-WRITE8_MEMBER( stereo_fx_device::invalid_w )
+void stereo_fx_device::invalid_w(uint8_t data)
{
logerror("stereo fx: invalid port write\n");
}
-READ8_MEMBER( stereo_fx_device::invalid_r )
+uint8_t stereo_fx_device::invalid_r()
{
- logerror("stereo fx: invalid port read\n");
+ if (!machine().side_effects_disabled())
+ logerror("stereo fx: invalid port read\n");
return 0xff;
}
@@ -207,17 +204,17 @@ stereo_fx_device::stereo_fx_device(const machine_config &mconfig, const char *ta
void stereo_fx_device::device_start()
{
- ym3812_device *ym3812 = subdevice<ym3812_device>("ym3812");
+ ym3812_device &ym3812 = *subdevice<ym3812_device>("ym3812");
set_isa_device();
- m_isa->install_device(0x0200, 0x0207, read8_delegate(FUNC(pc_joy_device::joy_port_r), subdevice<pc_joy_device>("pc_joy")), write8_delegate(FUNC(pc_joy_device::joy_port_w), subdevice<pc_joy_device>("pc_joy")));
- m_isa->install_device(0x0226, 0x0227, read8_delegate(FUNC(stereo_fx_device::invalid_r), this), write8_delegate(FUNC(stereo_fx_device::dsp_reset_w), this));
- m_isa->install_device(0x022a, 0x022b, read8_delegate(FUNC(stereo_fx_device::dsp_data_r), this), write8_delegate(FUNC(stereo_fx_device::invalid_w), this) );
- m_isa->install_device(0x022c, 0x022d, read8_delegate(FUNC(stereo_fx_device::dsp_wbuf_status_r), this), write8_delegate(FUNC(stereo_fx_device::dsp_cmd_w), this) );
- m_isa->install_device(0x022e, 0x022f, read8_delegate(FUNC(stereo_fx_device::dsp_rbuf_status_r), this), write8_delegate(FUNC(stereo_fx_device::invalid_w), this) );
- m_isa->install_device(0x0388, 0x0389, read8sm_delegate(FUNC(ym3812_device::read), ym3812), write8sm_delegate(FUNC(ym3812_device::write), ym3812));
- m_isa->install_device(0x0228, 0x0229, read8sm_delegate(FUNC(ym3812_device::read), ym3812), write8sm_delegate(FUNC(ym3812_device::write), ym3812));
- m_timer = timer_alloc();
+ 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, read8smo_delegate(*this, FUNC(stereo_fx_device::invalid_r)), write8smo_delegate(*this, FUNC(stereo_fx_device::dsp_reset_w)));
+ m_isa->install_device(0x022a, 0x022b, read8smo_delegate(*this, FUNC(stereo_fx_device::dsp_data_r)), write8smo_delegate(*this, FUNC(stereo_fx_device::invalid_w)));
+ m_isa->install_device(0x022c, 0x022d, read8smo_delegate(*this, FUNC(stereo_fx_device::dsp_wbuf_status_r)), write8smo_delegate(*this, FUNC(stereo_fx_device::dsp_cmd_w)));
+ m_isa->install_device(0x022e, 0x022f, read8smo_delegate(*this, FUNC(stereo_fx_device::dsp_rbuf_status_r)), write8smo_delegate(*this, FUNC(stereo_fx_device::invalid_w)));
+ m_isa->install_device(0x0388, 0x0389, read8sm_delegate(ym3812, FUNC(ym3812_device::read)), write8sm_delegate(ym3812, FUNC(ym3812_device::write)));
+ m_isa->install_device(0x0228, 0x0229, read8sm_delegate(ym3812, FUNC(ym3812_device::read)), write8sm_delegate(ym3812, FUNC(ym3812_device::write)));
+ m_timer = timer_alloc(FUNC(stereo_fx_device::clock_tick), this);
m_timer->adjust(attotime::from_hz(2000000), 0, attotime::from_hz(2000000));
m_isa->set_dma_channel(1, this, false);
}
@@ -234,7 +231,7 @@ void stereo_fx_device::device_reset()
m_t0 = CLEAR_LINE;
}
-void stereo_fx_device::device_timer(emu_timer &timer, device_timer_id tid, int param, void *ptr)
+TIMER_CALLBACK_MEMBER(stereo_fx_device::clock_tick)
{
m_t0 = !m_t0;
m_cpu->set_input_line(MCS51_T0_LINE, m_t0);
diff --git a/src/devices/bus/isa/stereo_fx.h b/src/devices/bus/isa/stereo_fx.h
index c3fa08339b8..e31fbe35e25 100644
--- a/src/devices/bus/isa/stereo_fx.h
+++ b/src/devices/bus/isa/stereo_fx.h
@@ -8,7 +8,7 @@
#include "isa.h"
#include "bus/pc_joy/pc_joy.h"
#include "cpu/mcs51/mcs51.h"
-#include "sound/3812intf.h"
+#include "sound/ymopl.h"
//*********************************************************************
// TYPE DEFINITIONS
@@ -25,14 +25,12 @@ public:
protected:
// device-level overrides
- virtual void device_start() override;
- virtual void device_reset() override;
-
- virtual void device_timer(emu_timer &timer, device_timer_id id, int param, void *ptr) override;
+ virtual void device_start() override ATTR_COLD;
+ virtual void device_reset() override ATTR_COLD;
// optional information overrides
- virtual const tiny_rom_entry *device_rom_region() const override;
- virtual void device_add_mconfig(machine_config &config) override;
+ virtual const tiny_rom_entry *device_rom_region() const override ATTR_COLD;
+ virtual void device_add_mconfig(machine_config &config) override ATTR_COLD;
uint8_t dack_r(int line) override;
void dack_w(int line, uint8_t data) override;
@@ -53,28 +51,30 @@ private:
uint8_t m_t0;
uint8_t m_t1;
+ TIMER_CALLBACK_MEMBER(clock_tick);
+
// mcu ports
- DECLARE_READ8_MEMBER( dev_dsp_data_r );
- DECLARE_WRITE8_MEMBER( dev_dsp_data_w );
- DECLARE_READ8_MEMBER( p1_r );
- DECLARE_READ8_MEMBER( p3_r );
- DECLARE_WRITE8_MEMBER( p3_w );
- DECLARE_WRITE8_MEMBER( dev_host_irq_w );
- DECLARE_WRITE8_MEMBER( raise_drq_w );
- DECLARE_WRITE8_MEMBER( port20_w );
- DECLARE_WRITE8_MEMBER( port00_w );
+ uint8_t dev_dsp_data_r();
+ void dev_dsp_data_w(uint8_t data);
+ uint8_t p1_r();
+ uint8_t p3_r();
+ void p3_w(uint8_t data);
+ void dev_host_irq_w(uint8_t data);
+ void raise_drq_w(uint8_t data);
+ void port20_w(uint8_t data);
+ void port00_w(uint8_t data);
// host ports
- DECLARE_READ8_MEMBER( dsp_data_r );
- DECLARE_WRITE8_MEMBER( dsp_cmd_w );
- DECLARE_WRITE8_MEMBER( dsp_reset_w );
- DECLARE_READ8_MEMBER( dsp_wbuf_status_r );
- DECLARE_READ8_MEMBER( dsp_rbuf_status_r );
- DECLARE_READ8_MEMBER( invalid_r );
- DECLARE_WRITE8_MEMBER( invalid_w );
-
- void stereo_fx_io(address_map &map);
- void stereo_fx_rom(address_map &map);
+ uint8_t dsp_data_r();
+ void dsp_cmd_w(uint8_t data);
+ void dsp_reset_w(uint8_t data);
+ uint8_t dsp_wbuf_status_r();
+ uint8_t dsp_rbuf_status_r();
+ uint8_t invalid_r();
+ void invalid_w(uint8_t data);
+
+ void stereo_fx_io(address_map &map) ATTR_COLD;
+ void stereo_fx_rom(address_map &map) ATTR_COLD;
};
// device type definition
diff --git a/src/devices/bus/isa/svga_cirrus.cpp b/src/devices/bus/isa/svga_cirrus.cpp
index 7ee541184d2..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,11 @@ 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, "vga", 0).set_screen("screen");
+ CIRRUS_GD5430_VGA(config, m_vga, 0);
+ m_vga->set_screen("screen");
+ m_vga->set_vram_size(0x200000);
}
//-------------------------------------------------
@@ -59,28 +104,28 @@ const tiny_rom_entry *isa16_svga_cirrus_device::device_rom_region() const
isa16_svga_cirrus_device::isa16_svga_cirrus_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) :
device_t(mconfig, ISA16_SVGA_CIRRUS, tag, owner, clock),
device_isa16_card_interface(mconfig, *this),
- m_vga(nullptr)
+ m_vga(*this, "vga")
+{
+}
+
+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
//-------------------------------------------------
-READ8_MEMBER(isa16_svga_cirrus_device::input_port_0_r ) { return 0xff; } //return machine().root_device().ioport("IN0")->read(); }
+uint8_t isa16_svga_cirrus_device::input_port_0_r() { return 0xff; } //return machine().root_device().ioport("IN0")->read(); }
void isa16_svga_cirrus_device::device_start()
{
set_isa_device();
- m_vga = subdevice<cirrus_gd5430_device>("vga");
+ m_isa->install_rom(this, 0xc0000, 0xc7fff, "dm_clgd5430");
- m_isa->install_rom(this, 0xc0000, 0xc7fff, "svga", "dm_clgd5430");
-
- m_isa->install_device(0x03b0, 0x03bf, read8_delegate(FUNC(cirrus_gd5430_device::port_03b0_r),m_vga), write8_delegate(FUNC(cirrus_gd5430_device::port_03b0_w),m_vga));
- m_isa->install_device(0x03c0, 0x03cf, read8_delegate(FUNC(cirrus_gd5430_device::port_03c0_r),m_vga), write8_delegate(FUNC(cirrus_gd5430_device::port_03c0_w),m_vga));
- m_isa->install_device(0x03d0, 0x03df, read8_delegate(FUNC(cirrus_gd5430_device::port_03d0_r),m_vga), write8_delegate(FUNC(cirrus_gd5430_device::port_03d0_w),m_vga));
-
- m_isa->install_memory(0xa0000, 0xbffff, read8_delegate(FUNC(cirrus_gd5430_device::mem_r),m_vga), write8_delegate(FUNC(cirrus_gd5430_device::mem_w),m_vga));
+ 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,11 @@ 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, "vga", 0).set_screen("screen");
+ CIRRUS_GD5428_VGA(config, m_vga, 0);
+ m_vga->set_screen("screen");
+ m_vga->set_vram_size(0x200000);
}
//-------------------------------------------------
@@ -139,28 +331,39 @@ const tiny_rom_entry *isa16_svga_cirrus_gd542x_device::device_rom_region() const
isa16_svga_cirrus_gd542x_device::isa16_svga_cirrus_gd542x_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) :
device_t(mconfig, ISA16_SVGA_CIRRUS_GD542X, tag, owner, clock),
device_isa16_card_interface(mconfig, *this),
- m_vga(nullptr)
+ m_vga(*this, "vga")
+{
+}
+
+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
//-------------------------------------------------
-READ8_MEMBER(isa16_svga_cirrus_gd542x_device::input_port_0_r ) { return 0xff; } //return machine().root_device().ioport("IN0")->read(); }
+uint8_t isa16_svga_cirrus_gd542x_device::input_port_0_r() { return 0xff; } //return machine().root_device().ioport("IN0")->read(); }
void isa16_svga_cirrus_gd542x_device::device_start()
{
set_isa_device();
- m_vga = subdevice<cirrus_gd5428_device>("vga");
+ m_isa->install_rom(this, 0xc0000, 0xc7fff, "clgd542x");
- m_isa->install_rom(this, 0xc0000, 0xc7fff, "svga", "clgd542x");
-
- m_isa->install_device(0x03b0, 0x03bf, read8_delegate(FUNC(cirrus_gd5428_device::port_03b0_r),m_vga), write8_delegate(FUNC(cirrus_gd5428_device::port_03b0_w),m_vga));
- m_isa->install_device(0x03c0, 0x03cf, read8_delegate(FUNC(cirrus_gd5428_device::port_03c0_r),m_vga), write8_delegate(FUNC(cirrus_gd5428_device::port_03c0_w),m_vga));
- m_isa->install_device(0x03d0, 0x03df, read8_delegate(FUNC(cirrus_gd5428_device::port_03d0_r),m_vga), write8_delegate(FUNC(cirrus_gd5428_device::port_03d0_w),m_vga));
+ 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, read8_delegate(FUNC(cirrus_gd5428_device::mem_r),m_vga), write8_delegate(FUNC(cirrus_gd5428_device::mem_w),m_vga));
+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 46b0cfcfc04..14481e23aa8 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
@@ -20,19 +20,21 @@ public:
// construction/destruction
isa16_svga_cirrus_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
- DECLARE_READ8_MEMBER(input_port_0_r);
+ uint8_t input_port_0_r();
protected:
// device-level overrides
- virtual void device_start() override;
- virtual void device_reset() override;
+ virtual void device_start() override ATTR_COLD;
+ virtual void device_reset() override ATTR_COLD;
// optional information overrides
- virtual void device_add_mconfig(machine_config &config) override;
- virtual const tiny_rom_entry *device_rom_region() const override;
+ virtual void device_add_mconfig(machine_config &config) override ATTR_COLD;
+ virtual const tiny_rom_entry *device_rom_region() const override ATTR_COLD;
+
+ void io_isa_map(address_map &map) ATTR_COLD;
private:
- cirrus_gd5430_device *m_vga;
+ required_device<cirrus_gd5430_vga_device> m_vga;
};
class isa16_svga_cirrus_gd542x_device :
@@ -43,19 +45,22 @@ public:
// construction/destruction
isa16_svga_cirrus_gd542x_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
- DECLARE_READ8_MEMBER(input_port_0_r);
+ 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;
- virtual void device_reset() override;
+ virtual void device_start() override ATTR_COLD;
+ virtual void device_reset() override ATTR_COLD;
// optional information overrides
- virtual void device_add_mconfig(machine_config &config) override;
- virtual const tiny_rom_entry *device_rom_region() const override;
+ virtual void device_add_mconfig(machine_config &config) override ATTR_COLD;
+ virtual const tiny_rom_entry *device_rom_region() const override ATTR_COLD;
+
+ void io_isa_map(address_map &map) ATTR_COLD;
private:
- 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..6be6e334924
--- /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: 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..78302b680be
--- /dev/null
+++ b/src/devices/bus/isa/svga_paradise.h
@@ -0,0 +1,256 @@
+// 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 ATTR_COLD;
+
+ // optional information overrides
+ virtual void device_add_mconfig(machine_config &config) override ATTR_COLD;
+ virtual const tiny_rom_entry *device_rom_region() const override ATTR_COLD;
+
+ void io_isa_map(address_map &map) ATTR_COLD;
+
+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 ATTR_COLD;
+
+ // optional information overrides
+ virtual void device_add_mconfig(machine_config &config) override ATTR_COLD;
+ virtual const tiny_rom_entry *device_rom_region() const override ATTR_COLD;
+
+ void io_isa_map(address_map &map) ATTR_COLD;
+
+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 ATTR_COLD;
+
+ // optional information overrides
+ virtual void device_add_mconfig(machine_config &config) override ATTR_COLD;
+ virtual const tiny_rom_entry *device_rom_region() const override ATTR_COLD;
+
+ void io_isa_map(address_map &map) ATTR_COLD;
+
+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);
+
+ // resets itself at card POST for accessing $c6xxx area, plays with input sense later
+ static constexpr feature_type unemulated_features() { return feature::PROTECTION; }
+
+protected:
+ // device-level overrides
+ virtual void device_start() override ATTR_COLD;
+
+ // optional information overrides
+ virtual void device_add_mconfig(machine_config &config) override ATTR_COLD;
+ virtual const tiny_rom_entry *device_rom_region() const override ATTR_COLD;
+
+ void io_isa_map(address_map &map) ATTR_COLD;
+
+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 ATTR_COLD;
+
+ // optional information overrides
+ virtual void device_add_mconfig(machine_config &config) override ATTR_COLD;
+ virtual const tiny_rom_entry *device_rom_region() const override ATTR_COLD;
+
+ void io_isa_map(address_map &map) ATTR_COLD;
+
+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 ATTR_COLD;
+
+ // optional information overrides
+ virtual void device_add_mconfig(machine_config &config) override ATTR_COLD;
+ virtual const tiny_rom_entry *device_rom_region() const override ATTR_COLD;
+
+ void io_isa_map(address_map &map) ATTR_COLD;
+
+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 ATTR_COLD;
+
+ // optional information overrides
+ virtual void device_add_mconfig(machine_config &config) override ATTR_COLD;
+ virtual const tiny_rom_entry *device_rom_region() const override ATTR_COLD;
+
+ void io_isa_map(address_map &map) ATTR_COLD;
+
+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 ATTR_COLD;
+
+ // optional information overrides
+ virtual void device_add_mconfig(machine_config &config) override ATTR_COLD;
+ virtual const tiny_rom_entry *device_rom_region() const override ATTR_COLD;
+
+ void io_isa_map(address_map &map) ATTR_COLD;
+
+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 ATTR_COLD;
+
+ // optional information overrides
+ virtual void device_add_mconfig(machine_config &config) override ATTR_COLD;
+ virtual const tiny_rom_entry *device_rom_region() const override ATTR_COLD;
+
+ void io_isa_map(address_map &map) ATTR_COLD;
+
+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 ATTR_COLD;
+
+ // optional information overrides
+ virtual void device_add_mconfig(machine_config &config) override ATTR_COLD;
+ virtual const tiny_rom_entry *device_rom_region() const override ATTR_COLD;
+
+ void io_isa_map(address_map &map) ATTR_COLD;
+
+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 0734a286998..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"
@@ -16,17 +36,28 @@ ROM_START( s3_764 )
ROM_REGION(0x8000,"s3_764", 0)
ROM_DEFAULT_BIOS("9fxv330")
+ // Number Nine Visual Technology 9FX Vision 330. Now I'm 64... (c)1995 Number Nine Visual Technology Corp. All Rights Reserved. #9-764 BIOS Version 2.03.10. (c)1995 S3 Inc Version 2.00.1.3-08
ROM_SYSTEM_BIOS( 0, "9fxv330", "PCI Number Nine 9FX Vision 330 2.03.10 (S3 Trio64)" )
ROMX_LOAD("s3_764.bin", 0x00000, 0x8000, CRC(4f10aac7) SHA1(c77b3f11cc15679121314823588887dd547cd715), ROM_BIOS(0) )
ROM_IGNORE( 0x8000 )
// The following are from Trio64V2/DX based cards
- ROM_SYSTEM_BIOS( 1, "trio64v2", "PCI S3 86C765 v1.03-08N (S3 Trio64V2/DX)" )
+
+ // S3 86C765 Video BIOS. Version 1.03-08N Copyright 1996 S3 Incorporated.
+ ROM_SYSTEM_BIOS( 1, "trio64v2_765", "PCI S3 86C765 v1.03-08N (S3 Trio64V2/DX)" )
ROMX_LOAD("pci_9503-62_s3.bin", 0x00000, 0x8000, CRC(0e9d79d8) SHA1(274b5b98cc998f2783567000cdb12b14308bc290), ROM_BIOS(1) )
+ // ELSA WINNER 1000/T2D VBE 2.0 DDC2B DPMS Video BIOS Ver. 6.01.00 (IP/-/-) Copyright (c) 1994-97 ELSA GmbH, Aachen (Germany) All Rights Reserved
ROM_SYSTEM_BIOS( 2, "winner1k", "PCI Elsa Winner 1000/T2D 6.01.00 (S3 Trio64V2/DX)" )
ROMX_LOAD("pci_elsa_winner_1000-t2d_6.01.00.bin", 0x00000, 0x8000, CRC(1c9532b8) SHA1(d27d60b9a3566aa42a01ad497046af16eaa2ed87), ROM_BIOS(2) )
+ // S3 86C775/86C785 Video BIOS. Version 1.01.04 Copyright 1996 S3 Incorporated.
+ ROM_SYSTEM_BIOS( 3, "trio64v2_775", "PCI S3 86C775/86C785 v1.01.04 (S3 Trio64V2/DX)" )
+ ROMX_LOAD("utd88a.bin", 0x00000, 0x8000, CRC(8df4524d) SHA1(e652dd2cec49d5edf3cb207e410233963efa22b8), ROM_BIOS(3) )
+
+ // S3 86C775/86C785 Video BIOS. Version 1.01.04 775 EDO M50-02
+ ROM_SYSTEM_BIOS( 4, "exprtclr_775", "PCI ExpertColor M50-02 (Trio64V2/DX, 86C775)" )
+ ROMX_LOAD("s3_86c775-86c785_video_bios_v1.01.04.u5", 0x00000, 0x8000, CRC(e718418f) SHA1(1288ce51bb732a346eb7c61d5bdf80ea22454d45), ROM_BIOS(4) )
ROM_END
//**************************************************************************
@@ -44,9 +75,11 @@ 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("vga", FUNC(s3_vga_device::screen_update));
+ screen.set_screen_update(m_vga, FUNC(s3trio64_vga_device::screen_update));
- S3_VGA(config, "vga", 0).set_screen("screen");
+ S3_TRIO64_VGA(config, m_vga, 0);
+ m_vga->set_screen("screen");
+ m_vga->set_vram_size(0x100000);
}
//-------------------------------------------------
@@ -69,303 +102,52 @@ const tiny_rom_entry *isa16_svga_s3_device::device_rom_region() const
isa16_svga_s3_device::isa16_svga_s3_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) :
device_t(mconfig, ISA16_SVGA_S3, tag, owner, clock),
device_isa16_card_interface(mconfig, *this),
- m_vga(nullptr), m_8514(nullptr)
-{
-}
-
-//-------------------------------------------------
-// device_start - device-specific startup
-//-------------------------------------------------
-READ8_MEMBER(isa16_svga_s3_device::input_port_0_r ) { return 0xff; } //return machine().root_device().ioport("IN0")->read(); }
-
-void isa16_svga_s3_device::device_start()
-{
- set_isa_device();
-
- m_vga = subdevice<s3_vga_device>("vga");
- m_8514 = subdevice<ibm8514a_device>("vga:8514a");
-
- m_isa->install_rom(this, 0xc0000, 0xc7fff, "svga", "s3_764");
-
- m_isa->install_device(0x03b0, 0x03bf, read8_delegate(FUNC(s3_vga_device::port_03b0_r),m_vga), write8_delegate(FUNC(s3_vga_device::port_03b0_w),m_vga));
- m_isa->install_device(0x03c0, 0x03cf, read8_delegate(FUNC(s3_vga_device::port_03c0_r),m_vga), write8_delegate(FUNC(s3_vga_device::port_03c0_w),m_vga));
- m_isa->install_device(0x03d0, 0x03df, read8_delegate(FUNC(s3_vga_device::port_03d0_r),m_vga), write8_delegate(FUNC(s3_vga_device::port_03d0_w),m_vga));
- m_isa->install16_device(0x82e8, 0x82eb, read16_delegate(FUNC(ibm8514a_device::ibm8514_currenty_r),m_8514), write16_delegate(FUNC(ibm8514a_device::ibm8514_currenty_w),m_8514));
- m_isa->install16_device(0x86e8, 0x86eb, read16_delegate(FUNC(ibm8514a_device::ibm8514_currentx_r),m_8514), write16_delegate(FUNC(ibm8514a_device::ibm8514_currentx_w),m_8514));
- m_isa->install16_device(0x8ae8, 0x8aeb, read16_delegate(FUNC(ibm8514a_device::ibm8514_desty_r),m_8514), write16_delegate(FUNC(ibm8514a_device::ibm8514_desty_w),m_8514));
- m_isa->install16_device(0x8ee8, 0x8eeb, read16_delegate(FUNC(ibm8514a_device::ibm8514_destx_r),m_8514), write16_delegate(FUNC(ibm8514a_device::ibm8514_destx_w),m_8514));
- m_isa->install16_device(0x92e8, 0x92eb, read16_delegate(FUNC(ibm8514a_device::ibm8514_line_error_r),m_8514), write16_delegate(FUNC(ibm8514a_device::ibm8514_line_error_w),m_8514));
- m_isa->install16_device(0x96e8, 0x96eb, read16_delegate(FUNC(ibm8514a_device::ibm8514_width_r),m_8514), write16_delegate(FUNC(ibm8514a_device::ibm8514_width_w),m_8514));
- m_isa->install16_device(0x9ae8, 0x9aeb, read16_delegate(FUNC(ibm8514a_device::ibm8514_gpstatus_r),m_8514), write16_delegate(FUNC(ibm8514a_device::ibm8514_cmd_w),m_8514));
- m_isa->install16_device(0x9ee8, 0x9eeb, read16_delegate(FUNC(ibm8514a_device::ibm8514_ssv_r),m_8514), write16_delegate(FUNC(ibm8514a_device::ibm8514_ssv_w),m_8514));
- m_isa->install16_device(0xa2e8, 0xa2eb, read16_delegate(FUNC(ibm8514a_device::ibm8514_bgcolour_r),m_8514), write16_delegate(FUNC(ibm8514a_device::ibm8514_bgcolour_w),m_8514));
- m_isa->install16_device(0xa6e8, 0xa6eb, read16_delegate(FUNC(ibm8514a_device::ibm8514_fgcolour_r),m_8514), write16_delegate(FUNC(ibm8514a_device::ibm8514_fgcolour_w),m_8514));
- m_isa->install16_device(0xaae8, 0xaaeb, read16_delegate(FUNC(ibm8514a_device::ibm8514_write_mask_r),m_8514), write16_delegate(FUNC(ibm8514a_device::ibm8514_write_mask_w),m_8514));
- m_isa->install16_device(0xaee8, 0xaeeb, read16_delegate(FUNC(ibm8514a_device::ibm8514_read_mask_r),m_8514), write16_delegate(FUNC(ibm8514a_device::ibm8514_read_mask_w),m_8514));
- m_isa->install16_device(0xb6e8, 0xb6eb, read16_delegate(FUNC(ibm8514a_device::ibm8514_backmix_r),m_8514), write16_delegate(FUNC(ibm8514a_device::ibm8514_backmix_w),m_8514));
- m_isa->install16_device(0xbae8, 0xbaeb, read16_delegate(FUNC(ibm8514a_device::ibm8514_foremix_r),m_8514), write16_delegate(FUNC(ibm8514a_device::ibm8514_foremix_w),m_8514));
- m_isa->install16_device(0xbee8, 0xbeeb, read16_delegate(FUNC(ibm8514a_device::ibm8514_multifunc_r),m_8514), write16_delegate(FUNC(ibm8514a_device::ibm8514_multifunc_w),m_8514));
- m_isa->install16_device(0xe2e8, 0xe2eb, read16_delegate(FUNC(ibm8514a_device::ibm8514_pixel_xfer_r),m_8514), write16_delegate(FUNC(ibm8514a_device::ibm8514_pixel_xfer_w),m_8514));
-
- m_isa->install_memory(0xa0000, 0xbffff, read8_delegate(FUNC(s3_vga_device::mem_r),m_vga), write8_delegate(FUNC(s3_vga_device::mem_w),m_vga));
-}
-
-//-------------------------------------------------
-// device_reset - device-specific reset
-//-------------------------------------------------
-
-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("vga", FUNC(s3virge_vga_device::screen_update));
-
- S3VIRGE(config, "vga", 0).set_screen("screen");
-}
-
-//-------------------------------------------------
-// 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(nullptr)
-{
-}
-
-//-------------------------------------------------
-// device_start - device-specific startup
-//-------------------------------------------------
-READ8_MEMBER(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_vga = subdevice<s3virge_vga_device>("vga");
-
- m_isa->install_rom(this, 0xc0000, 0xc7fff, "svga", "s3virge");
-
- m_isa->install_device(0x03b0, 0x03bf, read8_delegate(FUNC(s3virge_vga_device::port_03b0_r),m_vga), write8_delegate(FUNC(s3virge_vga_device::port_03b0_w),m_vga));
- m_isa->install_device(0x03c0, 0x03cf, read8_delegate(FUNC(s3virge_vga_device::port_03c0_r),m_vga), write8_delegate(FUNC(s3virge_vga_device::port_03c0_w),m_vga));
- m_isa->install_device(0x03d0, 0x03df, read8_delegate(FUNC(s3virge_vga_device::port_03d0_r),m_vga), write8_delegate(FUNC(s3virge_vga_device::port_03d0_w),m_vga));
-
- m_isa->install_memory(0xa0000, 0xbffff, read8_delegate(FUNC(s3virge_vga_device::mem_r),m_vga), write8_delegate(FUNC(s3virge_vga_device::mem_w),m_vga));
-}
-
-//-------------------------------------------------
-// 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("vga", FUNC(s3virgedx_vga_device::screen_update));
-
- S3VIRGEDX(config, "vga", 0).set_screen("screen");
-}
-
-//-------------------------------------------------
-// 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(nullptr)
-{
-}
-
-//-------------------------------------------------
-// device_start - device-specific startup
-//-------------------------------------------------
-READ8_MEMBER(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_vga = subdevice<s3virgedx_vga_device>("vga");
-
- m_isa->install_rom(this, 0xc0000, 0xc7fff, "svga", "s3virgedx");
-
- m_isa->install_device(0x03b0, 0x03bf, read8_delegate(FUNC(s3virge_vga_device::port_03b0_r),m_vga), write8_delegate(FUNC(s3virge_vga_device::port_03b0_w),m_vga));
- m_isa->install_device(0x03c0, 0x03cf, read8_delegate(FUNC(s3virge_vga_device::port_03c0_r),m_vga), write8_delegate(FUNC(s3virge_vga_device::port_03c0_w),m_vga));
- m_isa->install_device(0x03d0, 0x03df, read8_delegate(FUNC(s3virge_vga_device::port_03d0_r),m_vga), write8_delegate(FUNC(s3virge_vga_device::port_03d0_w),m_vga));
-
- m_isa->install_memory(0xa0000, 0xbffff, read8_delegate(FUNC(s3virge_vga_device::mem_r),m_vga), write8_delegate(FUNC(s3virge_vga_device::mem_w),m_vga));
-}
-
-//-------------------------------------------------
-// device_reset - device-specific reset
-//-------------------------------------------------
-
-void isa16_s3virgedx_device::device_reset()
-{
-}
-
-
-/*
- * 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("vga", FUNC(s3virgedx_rev1_vga_device::screen_update));
-
- S3VIRGEDX1(config, "vga", 0).set_screen("screen");
-}
-
-//-------------------------------------------------
-// rom_region - device-specific ROM region
-//-------------------------------------------------
-
-const tiny_rom_entry *isa16_stealth3d2kpro_device::device_rom_region() const
+ m_vga(*this, "vga"), m_8514(*this, "vga:8514a")
{
- 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(nullptr)
+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
//-------------------------------------------------
-READ8_MEMBER(isa16_stealth3d2kpro_device::input_port_0_r ) { return 0xff; } //return machine().root_device().ioport("IN0")->read(); }
+uint8_t isa16_svga_s3_device::input_port_0_r() { return 0xff; } //return machine().root_device().ioport("IN0")->read(); }
-void isa16_stealth3d2kpro_device::device_start()
+void isa16_svga_s3_device::device_start()
{
set_isa_device();
- m_vga = subdevice<s3virgedx_vga_device>("vga");
+ m_isa->install_rom(this, 0xc0000, 0xc7fff, "s3_764");
- m_isa->install_rom(this, 0xc0000, 0xc7fff, "svga", "stealth3d");
+ m_isa->install_device(0x03b0, 0x03df, *this, &isa16_svga_s3_device::io_isa_map);
- m_isa->install_device(0x03b0, 0x03bf, read8_delegate(FUNC(s3virge_vga_device::port_03b0_r),m_vga), write8_delegate(FUNC(s3virge_vga_device::port_03b0_w),m_vga));
- m_isa->install_device(0x03c0, 0x03cf, read8_delegate(FUNC(s3virge_vga_device::port_03c0_r),m_vga), write8_delegate(FUNC(s3virge_vga_device::port_03c0_w),m_vga));
- m_isa->install_device(0x03d0, 0x03df, read8_delegate(FUNC(s3virge_vga_device::port_03d0_r),m_vga), write8_delegate(FUNC(s3virge_vga_device::port_03d0_w),m_vga));
+ 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)));
+ m_isa->install16_device(0x8ee8, 0x8eeb, read16smo_delegate(*m_8514, FUNC(ibm8514a_device::ibm8514_destx_r)), write16smo_delegate(*m_8514, FUNC(ibm8514a_device::ibm8514_destx_w)));
+ m_isa->install16_device(0x92e8, 0x92eb, read16smo_delegate(*m_8514, FUNC(ibm8514a_device::ibm8514_line_error_r)), write16smo_delegate(*m_8514, FUNC(ibm8514a_device::ibm8514_line_error_w)));
+ m_isa->install16_device(0x96e8, 0x96eb, read16smo_delegate(*m_8514, FUNC(ibm8514a_device::ibm8514_width_r)), write16smo_delegate(*m_8514, FUNC(ibm8514a_device::ibm8514_width_w)));
+ m_isa->install16_device(0x9ae8, 0x9aeb, read16smo_delegate(*m_8514, FUNC(ibm8514a_device::ibm8514_gpstatus_r)), write16smo_delegate(*m_8514, FUNC(ibm8514a_device::ibm8514_cmd_w)));
+ m_isa->install16_device(0x9ee8, 0x9eeb, read16smo_delegate(*m_8514, FUNC(ibm8514a_device::ibm8514_ssv_r)), write16smo_delegate(*m_8514, FUNC(ibm8514a_device::ibm8514_ssv_w)));
+ m_isa->install16_device(0xa2e8, 0xa2eb, read16smo_delegate(*m_8514, FUNC(ibm8514a_device::ibm8514_bgcolour_r)), write16smo_delegate(*m_8514, FUNC(ibm8514a_device::ibm8514_bgcolour_w)));
+ m_isa->install16_device(0xa6e8, 0xa6eb, read16smo_delegate(*m_8514, FUNC(ibm8514a_device::ibm8514_fgcolour_r)), write16smo_delegate(*m_8514, FUNC(ibm8514a_device::ibm8514_fgcolour_w)));
+ m_isa->install16_device(0xaae8, 0xaaeb, read16smo_delegate(*m_8514, FUNC(ibm8514a_device::ibm8514_write_mask_r)), write16smo_delegate(*m_8514, FUNC(ibm8514a_device::ibm8514_write_mask_w)));
+ m_isa->install16_device(0xaee8, 0xaeeb, read16smo_delegate(*m_8514, FUNC(ibm8514a_device::ibm8514_read_mask_r)), write16smo_delegate(*m_8514, FUNC(ibm8514a_device::ibm8514_read_mask_w)));
+ m_isa->install16_device(0xb6e8, 0xb6eb, read16smo_delegate(*m_8514, FUNC(ibm8514a_device::ibm8514_backmix_r)), write16smo_delegate(*m_8514, FUNC(ibm8514a_device::ibm8514_backmix_w)));
+ m_isa->install16_device(0xbae8, 0xbaeb, read16smo_delegate(*m_8514, FUNC(ibm8514a_device::ibm8514_foremix_r)), write16smo_delegate(*m_8514, FUNC(ibm8514a_device::ibm8514_foremix_w)));
+ 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, read8_delegate(FUNC(s3virge_vga_device::mem_r),m_vga), write8_delegate(FUNC(s3virge_vga_device::mem_w),m_vga));
+ 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)));
}
//-------------------------------------------------
// device_reset - device-specific reset
//-------------------------------------------------
-void isa16_stealth3d2kpro_device::device_reset()
+void isa16_svga_s3_device::device_reset()
{
}
diff --git a/src/devices/bus/isa/svga_s3.h b/src/devices/bus/isa/svga_s3.h
index f60141518de..7fe5dda6458 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
@@ -23,96 +23,25 @@ public:
// construction/destruction
isa16_svga_s3_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
- DECLARE_READ8_MEMBER(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;
-
-private:
- s3_vga_device *m_vga;
- 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);
-
- DECLARE_READ8_MEMBER(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;
-
-private:
- 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);
-
- DECLARE_READ8_MEMBER(input_port_0_r);
+ uint8_t input_port_0_r();
protected:
// device-level overrides
- virtual void device_start() override;
- virtual void device_reset() override;
+ virtual void device_start() override ATTR_COLD;
+ virtual void device_reset() override ATTR_COLD;
// optional information overrides
- virtual void device_add_mconfig(machine_config &config) override;
- virtual const tiny_rom_entry *device_rom_region() const override;
+ virtual void device_add_mconfig(machine_config &config) override ATTR_COLD;
+ virtual const tiny_rom_entry *device_rom_region() const override ATTR_COLD;
-private:
- s3virgedx_vga_device *m_vga;
-};
-
-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);
-
- DECLARE_READ8_MEMBER(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;
+ void io_isa_map(address_map &map) ATTR_COLD;
private:
- 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 31f2120f548..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)")
@@ -34,9 +95,11 @@ void isa16_svga_tgui9680_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(trident_vga_device::screen_update));
+ screen.set_screen_update(m_vga, FUNC(trident_vga_device::screen_update));
- TRIDENT_VGA(config, "vga", 0).set_screen("screen");
+ TRIDENT_VGA(config, m_vga, 0);
+ m_vga->set_screen("screen");
+ m_vga->set_vram_size(0x200000);
}
//-------------------------------------------------
@@ -56,48 +119,42 @@ 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(nullptr)
+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));
+}
+
//-------------------------------------------------
// device_start - device-specific startup
//-------------------------------------------------
-READ8_MEMBER(isa16_svga_tgui9680_device::input_port_0_r ) { return 0xff; } //return machine().root_device().ioport("IN0")->read(); }
+uint8_t isa16_svga_tgui9680_device::input_port_0_r() { return 0xff; } //return machine().root_device().ioport("IN0")->read(); }
void isa16_svga_tgui9680_device::device_start()
{
set_isa_device();
- m_vga = subdevice<trident_vga_device>("vga");
+ m_isa->install_rom(this, 0xc0000, 0xc7fff, "tgui9680");
- m_isa->install_rom(this, 0xc0000, 0xc7fff, "tgui9680", "tgui9680");
+ m_isa->install_device(0x03b0, 0x03df, *this, &isa16_svga_tgui9680_device::io_isa_map);
- m_isa->install_device(0x3b0, 0x3bf, read8_delegate(FUNC(trident_vga_device::port_03b0_r),m_vga), write8_delegate(FUNC(trident_vga_device::port_03b0_w),m_vga));
- m_isa->install_device(0x3c0, 0x3cf, read8_delegate(FUNC(trident_vga_device::port_03c0_r),m_vga), write8_delegate(FUNC(trident_vga_device::port_03c0_w),m_vga));
- m_isa->install_device(0x3d0, 0x3df, read8_delegate(FUNC(trident_vga_device::port_03d0_r),m_vga), write8_delegate(FUNC(trident_vga_device::port_03d0_w),m_vga));
- m_isa->install_device(0x43c4, 0x43cb, read8_delegate(FUNC(trident_vga_device::port_43c6_r),m_vga), write8_delegate(FUNC(trident_vga_device::port_43c6_w),m_vga));
- m_isa->install_device(0x83c4, 0x83cb, read8_delegate(FUNC(trident_vga_device::port_83c6_r),m_vga), write8_delegate(FUNC(trident_vga_device::port_83c6_w),m_vga));
+ 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)));
- m_isa->install_memory(0xa0000, 0xbffff, read8_delegate(FUNC(trident_vga_device::mem_r),m_vga), write8_delegate(FUNC(trident_vga_device::mem_w),m_vga));
+ m_isa->install_memory(0xa0000, 0xbffff, read8sm_delegate(*m_vga, FUNC(trident_vga_device::mem_r)), write8sm_delegate(*m_vga, FUNC(trident_vga_device::mem_w)));
// uncomment to test Windows 3.1 TGUI9440AGi driver
-// m_isa->install_memory(0x4400000, 0x45fffff, read8_delegate(FUNC(trident_vga_device::vram_r),m_vga), write8_delegate(FUNC(trident_vga_device::vram_w),m_vga));
+// 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, read8_delegate(FUNC(trident_vga_device::vram_r),m_vga), write8_delegate(FUNC(trident_vga_device::vram_w),m_vga));
+// 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, read8_delegate(FUNC(trident_vga_device::accel_r),m_vga), write8_delegate(FUNC(trident_vga_device::accel_w),m_vga));
-}
-
-//-------------------------------------------------
-// device_reset - device-specific reset
-//-------------------------------------------------
-
-void isa16_svga_tgui9680_device::device_reset()
-{
+ 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)));
}
diff --git a/src/devices/bus/isa/svga_trident.h b/src/devices/bus/isa/svga_trident.h
index d8be1458591..a45abacda9f 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 ATTR_COLD;
+
+ // optional information overrides
+ virtual void device_add_mconfig(machine_config &config) override ATTR_COLD;
+ virtual const tiny_rom_entry *device_rom_region() const override ATTR_COLD;
+
+ void io_isa_map(address_map &map) ATTR_COLD;
+
+private:
+ required_device<tvga9000_device> m_vga;
+};
class isa16_svga_tgui9680_device :
public device_t,
@@ -27,23 +48,25 @@ public:
// construction/destruction
isa16_svga_tgui9680_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
- DECLARE_READ8_MEMBER(input_port_0_r);
+ uint8_t input_port_0_r();
protected:
// device-level overrides
- virtual void device_start() override;
- virtual void device_reset() override;
+ virtual void device_start() override ATTR_COLD;
// optional information overrides
- virtual void device_add_mconfig(machine_config &config) override;
- virtual const tiny_rom_entry *device_rom_region() const override;
+ virtual void device_add_mconfig(machine_config &config) override ATTR_COLD;
+ virtual const tiny_rom_entry *device_rom_region() const override ATTR_COLD;
+
+ void io_isa_map(address_map &map) ATTR_COLD;
private:
- trident_vga_device *m_vga;
+ 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 354643fd96d..4ee430108eb 100644
--- a/src/devices/bus/isa/svga_tseng.cpp
+++ b/src/devices/bus/isa/svga_tseng.cpp
@@ -4,47 +4,61 @@
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"
-
-ROM_START( et4000 )
- ROM_REGION(0x8000,"et4000", 0)
- ROM_LOAD("et4000.bin", 0x00000, 0x8000, CRC(f1e817a8) SHA1(945d405b0fb4b8f26830d495881f8587d90e5ef9) )
-ROM_END
//**************************************************************************
// GLOBAL VARIABLES
//**************************************************************************
-DEFINE_DEVICE_TYPE(ISA8_SVGA_ET4K, isa8_svga_et4k_device, "et4000", "SVGA Tseng ET4000 Graphics Card")
-
+DEFINE_DEVICE_TYPE(ISA16_SVGA_ET4K, isa16_svga_et4k_device, "et4000", "SVGA Tseng ET4000AX Graphics Card")
+DEFINE_DEVICE_TYPE(ISA16_SVGA_ET4K_KASAN16, isa16_svga_et4k_kasan16_device, "et4000_kasan16", "SVGA Kasan Hangulmadang-16 ET4000AX Graphics Card")
+DEFINE_DEVICE_TYPE(ISA16_SVGA_ET4K_W32I, isa16_svga_et4k_w32i_device, "et4kw32i", "SVGA Tseng ET4000/W32i Graphics Card")
//-------------------------------------------------
-// device_add_mconfig - add device configuration
+// rom_region - device-specific ROM region
//-------------------------------------------------
-void isa8_svga_et4k_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(tseng_vga_device::screen_update));
+/*
+ * (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,"vga_rom", 0)
+ 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
- TSENG_VGA(config, "vga", 0).set_screen("screen");
+const tiny_rom_entry *isa16_svga_et4k_device::device_rom_region() const
+{
+ return ROM_NAME( et4000 );
}
//-------------------------------------------------
-// rom_region - device-specific ROM region
+// device_add_mconfig - add device configuration
//-------------------------------------------------
-const tiny_rom_entry *isa8_svga_et4k_device::device_rom_region() const
+void isa16_svga_et4k_device::device_add_mconfig(machine_config &config)
{
- return ROM_NAME( et4000 );
+ 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(tseng_vga_device::screen_update));
+
+ TSENG_VGA(config, m_vga, 0);
+ m_vga->set_screen("screen");
+ m_vga->set_vram_size(1*1024*1024);
}
//**************************************************************************
@@ -52,37 +66,39 @@ const tiny_rom_entry *isa8_svga_et4k_device::device_rom_region() const
//**************************************************************************
//-------------------------------------------------
-// isa8_vga_device - constructor
+// isa16_vga_device - constructor
//-------------------------------------------------
-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(nullptr)
+isa16_svga_et4k_device::isa16_svga_et4k_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) :
+ isa16_svga_et4k_device(mconfig, ISA16_SVGA_ET4K, tag, owner, clock)
+{
+}
+
+isa16_svga_et4k_device::isa16_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_isa16_card_interface(mconfig, *this)
+ , m_vga(*this, "vga")
{
}
//-------------------------------------------------
// device_start - device-specific startup
//-------------------------------------------------
-READ8_MEMBER(isa8_svga_et4k_device::input_port_0_r ) { return 0xff; } //return machine().root_device().ioport("IN0")->read(); }
+uint8_t isa16_svga_et4k_device::input_port_0_r() { return 0xff; } //return machine().root_device().ioport("IN0")->read(); }
-void isa8_svga_et4k_device::device_start()
+void isa16_svga_et4k_device::device_start()
{
set_isa_device();
- m_vga = subdevice<tseng_vga_device>("vga");
-
- map_io();
- map_ram();
- map_rom();
+ remap(AS_PROGRAM, 0, 0xfffff);
+ remap(AS_IO, 0, 0x3ff);
}
//-------------------------------------------------
// device_reset - device-specific reset
//-------------------------------------------------
-void isa8_svga_et4k_device::device_reset()
+void isa16_svga_et4k_device::device_reset()
{
}
@@ -91,30 +107,114 @@ void isa8_svga_et4k_device::device_reset()
// could have unmapped it
//-------------------------------------------------
-void isa8_svga_et4k_device::remap(int space_id, offs_t start, offs_t end)
+void isa16_svga_et4k_device::remap(int space_id, offs_t start, offs_t end)
{
if (space_id == AS_PROGRAM)
{
- map_ram();
- map_rom();
+ m_isa->install_memory(0xa0000, 0xbffff, read8sm_delegate(*m_vga, FUNC(tseng_vga_device::mem_r)), write8sm_delegate(*m_vga, FUNC(tseng_vga_device::mem_w)));
+ m_isa->install_rom(this, 0xc0000, 0xc7fff, "vga_rom");
}
else if (space_id == AS_IO)
- map_io();
+ m_isa->install_device(0x03b0, 0x03df, *this, &isa16_svga_et4k_device::io_isa_map);
+}
+
+void isa16_svga_et4k_device::io_isa_map(address_map &map)
+{
+ map(0x00, 0x2f).m(m_vga, FUNC(tseng_vga_device::io_map));
+}
+
+/*
+ * Korean cards
+ *
+ * Same as regular ET4000AX with extra font I/Os
+ */
+
+isa16_svga_et4k_kasan16_device::isa16_svga_et4k_kasan16_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
+ : isa16_svga_et4k_device(mconfig, ISA16_SVGA_ET4K_KASAN16, tag, owner, clock)
+ , m_hangul_rom(*this, "hangul")
+{
+}
+
+ROM_START( kasan16 )
+ ROM_REGION(0x8000,"vga_rom", 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 *isa16_svga_et4k_kasan16_device::device_rom_region() const
+{
+ return ROM_NAME( kasan16 );
}
-void isa8_svga_et4k_device::map_io()
+/*
+ * ET4000/w32i
+ */
+
+isa16_svga_et4k_w32i_device::isa16_svga_et4k_w32i_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
+ : device_t(mconfig, ISA16_SVGA_ET4K_W32I, tag, owner, clock)
+ , device_isa16_card_interface(mconfig, *this)
+ , m_vga(*this, "vga")
{
- m_isa->install_device(0x3b0, 0x3bf, read8_delegate(FUNC(tseng_vga_device::port_03b0_r), m_vga), write8_delegate(FUNC(tseng_vga_device::port_03b0_w), m_vga));
- m_isa->install_device(0x3c0, 0x3cf, read8_delegate(FUNC(tseng_vga_device::port_03c0_r), m_vga), write8_delegate(FUNC(tseng_vga_device::port_03c0_w), m_vga));
- m_isa->install_device(0x3d0, 0x3df, read8_delegate(FUNC(tseng_vga_device::port_03d0_r), m_vga), write8_delegate(FUNC(tseng_vga_device::port_03d0_w), m_vga));
}
-void isa8_svga_et4k_device::map_ram()
+
+ROM_START( et4kw32i )
+ ROM_REGION(0x8000,"vga_rom", 0)
+ ROM_SYSTEM_BIOS(0, "v800n", "Tseng Version 8.00N 04/28/95 ISA 06/17/95")
+ ROMX_LOAD("et4kw32i.vbi", 0x00000, 0x8000, CRC(14542962) SHA1(d5aee7205af8bd1fef0ecf1db2c07308a2b10b17), ROM_BIOS(0) )
+ROM_END
+
+const tiny_rom_entry *isa16_svga_et4k_w32i_device::device_rom_region() const
{
- m_isa->install_memory(0xa0000, 0xbffff, read8_delegate(FUNC(tseng_vga_device::mem_r), m_vga), write8_delegate(FUNC(tseng_vga_device::mem_w), m_vga));
+ return ROM_NAME( et4kw32i );
}
-void isa8_svga_et4k_device::map_rom()
+void isa16_svga_et4k_w32i_device::device_add_mconfig(machine_config &config)
{
- m_isa->install_rom(this, 0xc0000, 0xc7fff, "et4000", "et4000");
+ 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(et4kw32i_vga_device::screen_update));
+
+ ET4KW32I_VGA(config, m_vga, 0);
+ m_vga->set_screen("screen");
+ // 1MB default, 4MB max
+ m_vga->set_vram_size(1*1024*1024);
+}
+
+void isa16_svga_et4k_w32i_device::device_start()
+{
+ set_isa_device();
+
+ remap(AS_PROGRAM, 0, 0xfffff);
+ remap(AS_IO, 0, 0xffff);
}
+
+void isa16_svga_et4k_w32i_device::device_reset()
+{
+}
+
+void isa16_svga_et4k_w32i_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(tseng_vga_device::mem_r)), write8sm_delegate(*m_vga, FUNC(tseng_vga_device::mem_w)));
+ // TODO: can be disabled or narrowed thru TS Auxiliary Mode
+ m_isa->install_rom(this, 0xc0000, 0xc7fff, "vga_rom");
+ }
+ else if (space_id == AS_IO)
+ {
+ m_isa->install_device(0x0000, 0xffff, *this, &isa16_svga_et4k_w32i_device::io_isa_map);
+ }
+}
+
+void isa16_svga_et4k_w32i_device::io_isa_map(address_map &map)
+{
+ map(0x03b0, 0x03df).m(m_vga, FUNC(et4kw32i_vga_device::io_map));
+ // IOD controls mirroring
+ map(0x210a, 0x210a).mirror(0x70).rw(m_vga, FUNC(et4kw32i_vga_device::acl_index_r), FUNC(et4kw32i_vga_device::acl_index_w));
+ map(0x210b, 0x210b).mirror(0x70).rw(m_vga, FUNC(et4kw32i_vga_device::acl_data_r), FUNC(et4kw32i_vga_device::acl_data_w));
+}
+
diff --git a/src/devices/bus/isa/svga_tseng.h b/src/devices/bus/isa/svga_tseng.h
index f83460e86ff..5e36909b783 100644
--- a/src/devices/bus/isa/svga_tseng.h
+++ b/src/devices/bus/isa/svga_tseng.h
@@ -6,44 +6,86 @@
#pragma once
#include "isa.h"
-#include "video/pc_vga.h"
+
+#include "video/pc_vga_tseng.h"
+
+#include "screen.h"
+
//**************************************************************************
// TYPE DEFINITIONS
//**************************************************************************
-// ======================> isa8_vga_device
+// ======================> isa16_vga_device
-class isa8_svga_et4k_device :
+class isa16_svga_et4k_device :
public device_t,
- public device_isa8_card_interface
+ public device_isa16_card_interface
{
public:
// construction/destruction
- isa8_svga_et4k_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
+ isa16_svga_et4k_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
- DECLARE_READ8_MEMBER(input_port_0_r);
+ uint8_t input_port_0_r();
virtual void remap(int space_id, offs_t start, offs_t end) override;
protected:
+ isa16_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;
+ virtual void device_start() override ATTR_COLD;
+ virtual void device_reset() override ATTR_COLD;
// optional information overrides
- virtual void device_add_mconfig(machine_config &config) override;
- virtual const tiny_rom_entry *device_rom_region() const override;
+ virtual void device_add_mconfig(machine_config &config) override ATTR_COLD;
+ virtual const tiny_rom_entry *device_rom_region() const override ATTR_COLD;
+
+ void io_isa_map(address_map &map) ATTR_COLD;
+
+private:
+ required_device<tseng_vga_device> m_vga;
+};
+
+class isa16_svga_et4k_kasan16_device :
+ public isa16_svga_et4k_device
+{
+public:
+ isa16_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 ATTR_COLD;
+
+private:
+ required_region_ptr<uint8_t> m_hangul_rom;
+};
+
+class isa16_svga_et4k_w32i_device :
+ public device_t,
+ public device_isa16_card_interface
+{
+public:
+ isa16_svga_et4k_w32i_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:
+ 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;
+ virtual const tiny_rom_entry *device_rom_region() const override ATTR_COLD;
+
+ void io_isa_map(address_map &map) ATTR_COLD;
private:
- void map_io();
- void map_ram();
- void map_rom();
- tseng_vga_device *m_vga;
+ required_device<et4kw32i_vga_device> m_vga;
};
// device type definition
-DECLARE_DEVICE_TYPE(ISA8_SVGA_ET4K, isa8_svga_et4k_device)
+DECLARE_DEVICE_TYPE(ISA16_SVGA_ET4K, isa16_svga_et4k_device)
+DECLARE_DEVICE_TYPE(ISA16_SVGA_ET4K_KASAN16, isa16_svga_et4k_kasan16_device)
+DECLARE_DEVICE_TYPE(ISA16_SVGA_ET4K_W32I, isa16_svga_et4k_w32i_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/tekram_dc820.h b/src/devices/bus/isa/tekram_dc820.h
index 2308eb8655a..4e59b06239f 100644
--- a/src/devices/bus/isa/tekram_dc820.h
+++ b/src/devices/bus/isa/tekram_dc820.h
@@ -24,7 +24,7 @@ public:
protected:
tekram_eisa_scsi_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, u32 clock);
- virtual void device_start() override;
+ virtual void device_start() override ATTR_COLD;
u8 latch_status_r();
void int0_ack_w(u8 data);
@@ -34,7 +34,7 @@ protected:
void mask_w(u8 data);
void eeprom_w(u8 data);
- void common_map(address_map &map);
+ void common_map(address_map &map) ATTR_COLD;
void scsic_config(device_t *device);
void scsi_add(machine_config &config);
@@ -52,15 +52,15 @@ public:
tekram_dc320b_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;
+ virtual void device_add_mconfig(machine_config &config) override ATTR_COLD;
+ virtual const tiny_rom_entry *device_rom_region() const override ATTR_COLD;
private:
void eeprom_w(u8 data);
u8 latch_status_r();
u8 status_r();
- void mpu_map(address_map &map);
+ void mpu_map(address_map &map) ATTR_COLD;
};
class tekram_dc320e_device : public tekram_eisa_scsi_device
@@ -69,11 +69,11 @@ public:
tekram_dc320e_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;
+ virtual void device_add_mconfig(machine_config &config) override ATTR_COLD;
+ virtual const tiny_rom_entry *device_rom_region() const override ATTR_COLD;
private:
- void mpu_map(address_map &map);
+ void mpu_map(address_map &map) ATTR_COLD;
};
class tekram_dc820_device : public tekram_eisa_scsi_device
@@ -82,13 +82,13 @@ public:
tekram_dc820_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;
+ virtual void device_add_mconfig(machine_config &config) override ATTR_COLD;
+ virtual const tiny_rom_entry *device_rom_region() const override ATTR_COLD;
private:
void eeprom_w(u8 data);
- void mpu_map(address_map &map);
+ void mpu_map(address_map &map) ATTR_COLD;
};
class tekram_dc820b_device : public tekram_eisa_scsi_device
@@ -97,11 +97,11 @@ public:
tekram_dc820b_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;
+ virtual void device_add_mconfig(machine_config &config) override ATTR_COLD;
+ virtual const tiny_rom_entry *device_rom_region() const override ATTR_COLD;
private:
- void mpu_map(address_map &map);
+ void mpu_map(address_map &map) ATTR_COLD;
};
DECLARE_DEVICE_TYPE(TEKRAM_DC320B, tekram_dc320b_device)
diff --git a/src/devices/bus/isa/ultra12f.cpp b/src/devices/bus/isa/ultra12f.cpp
index f0a30875fb0..fb5f89e485c 100644
--- a/src/devices/bus/isa/ultra12f.cpp
+++ b/src/devices/bus/isa/ultra12f.cpp
@@ -4,9 +4,10 @@
UltraStor Ultra 12F ESDI Caching Disk Controller
- Two versions of this card are known as 12F/24 and 12F/32. The hardware
- differences between these apparently have to do with drive speed; the
- same firmware and microcode may be applicable to both.
+ The original version of this card supported drive speeds up to 22 MHz.
+ The 12F/24 model supports a 24 MHz speed as well, and the 12F/32 model
+ presumably supports up to 32 MHz. There do not appear to be any major
+ hardware differences between these models.
***************************************************************************/
@@ -14,9 +15,10 @@
#include "ultra12f.h"
DEFINE_DEVICE_TYPE(ULTRA12F, ultra12f_device, "ultra12f", "Ultra 12F ESDI Caching Disk Controller")
+DEFINE_DEVICE_TYPE(ULTRA12F32, ultra12f32_device, "ultra12f32", "Ultra 12F/32 ESDI Caching Disk Controller")
-ultra12f_device::ultra12f_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock)
- : device_t(mconfig, ULTRA12F, tag, owner, clock)
+ultra12f_device::ultra12f_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, u32 clock)
+ : device_t(mconfig, type, tag, owner, clock)
, device_isa16_card_interface(mconfig, *this)
, m_hpc(*this, "hpc")
, m_fdc(*this, "fdc")
@@ -24,6 +26,16 @@ ultra12f_device::ultra12f_device(const machine_config &mconfig, const char *tag,
{
}
+ultra12f_device::ultra12f_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock)
+ : ultra12f_device(mconfig, ULTRA12F, tag, owner, clock)
+{
+}
+
+ultra12f32_device::ultra12f32_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock)
+ : ultra12f_device(mconfig, ULTRA12F32, tag, owner, clock)
+{
+}
+
void ultra12f_device::device_start()
{
// Firmware EPROM has a couple of lines scrambled
@@ -42,27 +54,76 @@ void ultra12f_device::hpc_map(address_map &map)
map(0x8000, 0xffff).rom().region("firmware", 0);
}
+static INPUT_PORTS_START(ultra12f)
+ PORT_START("BIOSADDR")
+ PORT_DIPNAME(0x7, 0x6, "BIOS Address") PORT_DIPLOCATION("JP10:3,2,1") // numbered as 5-6, 3-4 and 1-2
+ PORT_DIPSETTING(0x7, "Disable BIOS")
+ PORT_DIPSETTING(0x6, "C800:0") // Primary port
+ PORT_DIPSETTING(0x5, "CC00:0") // Secondary port
+ PORT_DIPSETTING(0x4, "D000:0") // Primary port
+ PORT_DIPSETTING(0x3, "D400:0") // Secondary port
+ PORT_DIPSETTING(0x2, "D800:0") // Primary port
+ PORT_DIPSETTING(0x1, "DC00:0") // Secondary port
+ //PORT_DIPSETTING(0x0, "Disable BIOS")
+
+ PORT_START("FDCCONF")
+ PORT_DIPNAME(0x1, 0x0, "Floppy Controller") PORT_DIPLOCATION("JP17:1")
+ PORT_DIPSETTING(0x1, "Disable")
+ PORT_DIPSETTING(0x0, "Enable")
+ // TODO: other jumpers on JP11
+
+ PORT_START("HDCPORT")
+ PORT_DIPNAME(0x1, 0x1, "Hard Disk I/O Port Address") PORT_DIPLOCATION("JP12:1")
+ PORT_DIPSETTING(0x0, "170-177") // Secondary
+ PORT_DIPSETTING(0x1, "1F0-1F7") // Primary
+
+ PORT_START("IRQSEL")
+ PORT_DIPNAME(0x3, 0x1, "IRQ Select") PORT_DIPLOCATION("JP20:1,2")
+ PORT_DIPSETTING(0x1, "IRQ14") // 2-3 jumpered
+ PORT_DIPSETTING(0x2, "IRQ15") // 1-2 jumpered
+INPUT_PORTS_END
+
+ioport_constructor ultra12f_device::device_input_ports() const
+{
+ return INPUT_PORTS_NAME(ultra12f);
+}
+
void ultra12f_device::device_add_mconfig(machine_config &config)
{
HPC46003(config, m_hpc, 24_MHz_XTAL); // apparently a HPC46003V30 custom-marked as "USC010-1-30"
m_hpc->set_addrmap(AS_PROGRAM, &ultra12f_device::hpc_map);
- DP8473(config, m_fdc, 24_MHz_XTAL); // unknown quad 52-pin floppy controller marked as "USC020-1-24"
+ //CL_SH260(config, "diskc", 24_MHz_XTAL / 2); // 84-pin PLCC IC custom-marked as "USC030-1-15"
+
+ DP8473(config, m_fdc, 24_MHz_XTAL); // unknown 52-pin PLCC floppy controller marked as "USC020-1-24"
}
ROM_START(ultra12f)
ROM_REGION(0x4000, "bios", 0)
ROM_SYSTEM_BIOS(0, "v202", "UBIOS 2.02") // "Date : 04/05/90 Version 2.02"
- ROMX_LOAD("38001-009.bin", 0x0000, 0x4000, CRC(b96c4839) SHA1(4e601c4ff1deae959c0807479d25de6db4e6cf3e), ROM_BIOS(0)) // 27C128, 150ns EPROM
+ ROMX_LOAD("38001-009_ultrastor_corp_89_otp.u15", 0x0000, 0x4000, CRC(b96c4839) SHA1(4e601c4ff1deae959c0807479d25de6db4e6cf3e), ROM_BIOS(0)) // 27C128, 150ns EPROM
ROM_SYSTEM_BIOS(1, "v300", "UBIOS 3.00") // "Date : 06/18/91 Version 3.00"
ROMX_LOAD("38001-010.bin", 0x0000, 0x4000, CRC(aa80d74e) SHA1(b507e6ead79e836969b8b6f2fa88ca99d6b354ad), ROM_BIOS(1)) // 27C128-12
- ROM_REGION(0x8000, "firmware", 0)
- ROMX_LOAD("28001-009.bin", 0x0000, 0x8000, CRC(0b6c74a1) SHA1(1a9eb5866f2104e94295d0915fe10c4c1745665b), ROM_BIOS(0)) // 27C256, 120ns EPROM
+ ROM_REGION16_LE(0x8000, "firmware", 0)
+ ROMX_LOAD("28001-009_uc_89.u1", 0x0000, 0x8000, CRC(0b6c74a1) SHA1(1a9eb5866f2104e94295d0915fe10c4c1745665b), ROM_BIOS(0)) // 27C256, 120ns EPROM
ROMX_LOAD("28001-012.bin", 0x0000, 0x8000, CRC(62fd2f69) SHA1(48d6e65001a262b3e99d373fa59e0672c5ec4284), ROM_BIOS(1)) // 27C256-12
ROM_END
+ROM_START(ultra12f32)
+ ROM_REGION(0x4000, "bios", 0) // "UBIOS 1.15"
+ ROM_LOAD("38001-006_usc_89_4cf3.u15", 0x0000, 0x4000, CRC(f09faeca) SHA1(b9e4edd5b16089c07d87b0c07a927c2d741b1f5e))
+
+ ROM_REGION16_LE(0x8000, "firmware", 0)
+ ROM_LOAD("28001-005_usc_89_beeb.u1", 0x0000, 0x8000, CRC(e28640ac) SHA1(110e724b4116fc2cbd050d9f2e541d2366fd9f4c))
+ROM_END
+
const tiny_rom_entry *ultra12f_device::device_rom_region() const
{
return ROM_NAME(ultra12f);
}
+
+const tiny_rom_entry *ultra12f32_device::device_rom_region() const
+{
+ return ROM_NAME(ultra12f32);
+}
diff --git a/src/devices/bus/isa/ultra12f.h b/src/devices/bus/isa/ultra12f.h
index 6da72e3c836..68af561f622 100644
--- a/src/devices/bus/isa/ultra12f.h
+++ b/src/devices/bus/isa/ultra12f.h
@@ -23,18 +23,31 @@ public:
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;
+ ultra12f_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, u32 clock);
+
+ virtual void device_start() override ATTR_COLD;
+ virtual ioport_constructor device_input_ports() const override ATTR_COLD;
+ virtual void device_add_mconfig(machine_config &config) override ATTR_COLD;
+ virtual const tiny_rom_entry *device_rom_region() const override ATTR_COLD;
private:
- void hpc_map(address_map &map);
+ void hpc_map(address_map &map) ATTR_COLD;
required_device<hpc_device> m_hpc;
required_device<upd765_family_device> m_fdc;
required_region_ptr<u8> m_bios;
};
+class ultra12f32_device : public ultra12f_device
+{
+public:
+ ultra12f32_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock);
+
+protected:
+ virtual const tiny_rom_entry *device_rom_region() const override ATTR_COLD;
+};
+
DECLARE_DEVICE_TYPE(ULTRA12F, ultra12f_device)
+DECLARE_DEVICE_TYPE(ULTRA12F32, ultra12f32_device)
#endif // MAME_BUS_ISA_ULTRA12F_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/ultra14f.h b/src/devices/bus/isa/ultra14f.h
index 9661e24a4b3..bc5562b1ef0 100644
--- a/src/devices/bus/isa/ultra14f.h
+++ b/src/devices/bus/isa/ultra14f.h
@@ -22,12 +22,12 @@ public:
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 void device_start() override ATTR_COLD;
+ virtual void device_add_mconfig(machine_config &config) override ATTR_COLD;
+ virtual const tiny_rom_entry *device_rom_region() const override ATTR_COLD;
private:
- void uscpu_map(address_map &map);
+ void uscpu_map(address_map &map) ATTR_COLD;
void scsic_config(device_t *device);
required_device<cpu_device> m_uscpu;
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/ultra24f.h b/src/devices/bus/isa/ultra24f.h
index 69a5d3a29d2..0b567c73228 100644
--- a/src/devices/bus/isa/ultra24f.h
+++ b/src/devices/bus/isa/ultra24f.h
@@ -23,15 +23,15 @@ public:
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 void device_start() override ATTR_COLD;
+ virtual void device_add_mconfig(machine_config &config) override ATTR_COLD;
+ virtual const tiny_rom_entry *device_rom_region() const override ATTR_COLD;
private:
u8 bmic_r(offs_t offset);
void bmic_w(offs_t offset, u8 data);
- void uscpu_map(address_map &map);
+ void uscpu_map(address_map &map) ATTR_COLD;
void scsic_config(device_t *device);
required_device<cpu_device> m_uscpu;
diff --git a/src/devices/bus/isa/vga.cpp b/src/devices/bus/isa/vga.cpp
index 121f689d711..3fa8752ae91 100644
--- a/src/devices/bus/isa/vga.cpp
+++ b/src/devices/bus/isa/vga.cpp
@@ -31,9 +31,11 @@ void isa8_vga_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(vga_device::screen_update));
+ screen.set_screen_update(m_vga, FUNC(vga_device::screen_update));
- VGA(config, "vga", 0).set_screen("screen");
+ VGA(config, m_vga, 0);
+ m_vga->set_screen("screen");
+ m_vga->set_vram_size(0x100000);
}
//-------------------------------------------------
@@ -55,28 +57,30 @@ const tiny_rom_entry *isa8_vga_device::device_rom_region() const
isa8_vga_device::isa8_vga_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) :
device_t(mconfig, ISA8_VGA, tag, owner, clock),
- device_isa8_card_interface(mconfig, *this), m_vga(nullptr)
+ device_isa8_card_interface(mconfig, *this),
+ m_vga(*this, "vga")
{
}
+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
//-------------------------------------------------
-READ8_MEMBER( isa8_vga_device::input_port_0_r ) { return 0xff; } //return machine().root_device().ioport("IN0")->read(); }
+uint8_t isa8_vga_device::input_port_0_r() { return 0xff; } //return machine().root_device().ioport("IN0")->read(); }
void isa8_vga_device::device_start()
{
set_isa_device();
- m_vga = subdevice<vga_device>("vga");
-
- m_isa->install_rom(this, 0xc0000, 0xc7fff, "ibm_vga", "ibm_vga");
+ m_isa->install_rom(this, 0xc0000, 0xc7fff, "ibm_vga");
- m_isa->install_device(0x3b0, 0x3bf, read8_delegate(FUNC(vga_device::port_03b0_r),m_vga), write8_delegate(FUNC(vga_device::port_03b0_w),m_vga));
- m_isa->install_device(0x3c0, 0x3cf, read8_delegate(FUNC(vga_device::port_03c0_r),m_vga), write8_delegate(FUNC(vga_device::port_03c0_w),m_vga));
- m_isa->install_device(0x3d0, 0x3df, read8_delegate(FUNC(vga_device::port_03d0_r),m_vga), write8_delegate(FUNC(vga_device::port_03d0_w),m_vga));
+ m_isa->install_device(0x03b0, 0x03df, *this, &isa8_vga_device::io_isa_map);
- m_isa->install_memory(0xa0000, 0xbffff, read8_delegate(FUNC(vga_device::mem_r),m_vga), write8_delegate(FUNC(vga_device::mem_w),m_vga));
+ 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 856016ecc5a..94cb388674a 100644
--- a/src/devices/bus/isa/vga.h
+++ b/src/devices/bus/isa/vga.h
@@ -22,19 +22,21 @@ public:
// construction/destruction
isa8_vga_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
- DECLARE_READ8_MEMBER(input_port_0_r);
+ uint8_t input_port_0_r();
protected:
// device-level overrides
- virtual void device_start() override;
- virtual void device_reset() override;
+ virtual void device_start() override ATTR_COLD;
+ virtual void device_reset() override ATTR_COLD;
// optional information overrides
- virtual void device_add_mconfig(machine_config &config) override;
- virtual const tiny_rom_entry *device_rom_region() const override;
+ virtual void device_add_mconfig(machine_config &config) override ATTR_COLD;
+ virtual const tiny_rom_entry *device_rom_region() const override ATTR_COLD;
+
+ void io_isa_map(address_map &map) ATTR_COLD;
private:
- vga_device *m_vga;
+ 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 63f9a1ec987..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"
@@ -80,27 +81,33 @@ void isa16_vga_gfxultra_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(ati_vga_device::screen_update));
+ screen.set_screen_update(m_vga, FUNC(ati_vga_device::screen_update));
- ATI_VGA(config, "vga", 0).set_screen("screen");
+ ATI_VGA(config, m_vga, 0);
+ m_vga->set_screen("screen");
+ m_vga->set_vram_size(0x100000);
}
void isa16_vga_gfxultrapro_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(mach32_device::screen_update));
+ screen.set_screen_update(m_vga, FUNC(mach32_device::screen_update));
- ATIMACH32(config, "vga", 0).set_screen("screen");
+ ATIMACH32(config, m_vga, 0);
+ m_vga->set_screen("screen");
+ m_vga->set_vram_size(0x400000);
}
void isa16_vga_mach64_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(mach64_device::screen_update));
+ screen.set_screen_update(m_vga, FUNC(mach64_device::screen_update));
- ATIMACH64(config, "vga", 0).set_screen("screen");
+ ATIMACH64(config, m_vga, 0);
+ m_vga->set_screen("screen");
+ m_vga->set_vram_size(0x400000);
}
@@ -134,228 +141,236 @@ const tiny_rom_entry *isa16_vga_mach64_device::device_rom_region() const
isa16_vga_gfxultra_device::isa16_vga_gfxultra_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) :
device_t(mconfig, ISA16_VGA_GFXULTRA, tag, owner, clock),
device_isa16_card_interface(mconfig, *this),
- m_vga(nullptr), m_8514(nullptr)
+ m_vga(*this, "vga"), m_8514(*this, "vga:8514a")
{
}
isa16_vga_gfxultrapro_device::isa16_vga_gfxultrapro_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) :
device_t(mconfig, ISA16_SVGA_GFXULTRAPRO, tag, owner, clock),
device_isa16_card_interface(mconfig, *this),
- m_vga(nullptr)
+ m_vga(*this, "vga")
{
}
isa16_vga_mach64_device::isa16_vga_mach64_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) :
device_t(mconfig, ISA16_SVGA_MACH64, tag, owner, clock),
device_isa16_card_interface(mconfig, *this),
- m_vga(nullptr)
+ m_vga(*this, "vga")
{
}
+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
//-------------------------------------------------
-READ8_MEMBER(isa16_vga_gfxultra_device::input_port_0_r ) { return 0xff; } //return machine().root_device().ioport("IN0")->read(); }
-READ8_MEMBER(isa16_vga_gfxultrapro_device::input_port_0_r ) { return 0xff; } //return machine().root_device().ioport("IN0")->read(); }
-READ8_MEMBER(isa16_vga_mach64_device::input_port_0_r ) { return 0xff; } //return machine().root_device().ioport("IN0")->read(); }
+uint8_t isa16_vga_gfxultra_device::input_port_0_r() { return 0xff; } //return machine().root_device().ioport("IN0")->read(); }
+uint8_t isa16_vga_gfxultrapro_device::input_port_0_r() { return 0xff; } //return machine().root_device().ioport("IN0")->read(); }
+uint8_t isa16_vga_mach64_device::input_port_0_r() { return 0xff; } //return machine().root_device().ioport("IN0")->read(); }
void isa16_vga_gfxultra_device::device_start()
{
set_isa_device();
- m_vga = subdevice<ati_vga_device>("vga");
- m_8514 = subdevice<mach8_device>("vga:8514a");
-
- m_isa->install_rom(this, 0xc0000, 0xc7fff, "vga", "gfxultra");
-
- m_isa->install_device(0x1ce, 0x1cf, read8_delegate(FUNC(ati_vga_device::ati_port_ext_r),m_vga), write8_delegate(FUNC(ati_vga_device::ati_port_ext_w),m_vga));
- m_isa->install_device(0x2e8, 0x2ef, read8_delegate(FUNC(mach8_device::ibm8514_status_r),m_8514), write8_delegate(FUNC(mach8_device::ibm8514_htotal_w),m_8514));
- m_isa->install_device(0x3b0, 0x3bf, read8_delegate(FUNC(ati_vga_device::port_03b0_r),m_vga), write8_delegate(FUNC(vga_device::port_03b0_w),m_vga));
- m_isa->install_device(0x3c0, 0x3cf, read8_delegate(FUNC(ati_vga_device::port_03c0_r),m_vga), write8_delegate(FUNC(vga_device::port_03c0_w),m_vga));
- m_isa->install_device(0x3d0, 0x3df, read8_delegate(FUNC(ati_vga_device::port_03d0_r),m_vga), write8_delegate(FUNC(vga_device::port_03d0_w),m_vga));
- m_isa->install16_device(0x12e8, 0x12eb, read16_delegate(FUNC(mach8_device::ibm8514_vtotal_r),m_8514), write16_delegate(FUNC(mach8_device::ibm8514_vtotal_w),m_8514));
- m_isa->install16_device(0x12ec, 0x12ef, read16_delegate(FUNC(mach8_device::mach8_config1_r),m_8514), write16_delegate());
- m_isa->install16_device(0x16e8, 0x16eb, read16_delegate(FUNC(mach8_device::ibm8514_vdisp_r),m_8514), write16_delegate(FUNC(mach8_device::ibm8514_vdisp_w),m_8514));
- m_isa->install16_device(0x16ec, 0x16ef, read16_delegate(FUNC(mach8_device::mach8_config2_r),m_8514), write16_delegate());
- m_isa->install16_device(0x1ae8, 0x1aeb, read16_delegate(FUNC(mach8_device::ibm8514_vsync_r),m_8514), write16_delegate(FUNC(mach8_device::ibm8514_vsync_w),m_8514));
- m_isa->install16_device(0x22e8, 0x22eb, read16_delegate(FUNC(mach8_device::mach8_readonly_r),m_8514),write16_delegate(FUNC(mach8_device::ibm8514_display_ctrl_w),m_8514));
- m_isa->install16_device(0x26e8, 0x26eb, read16_delegate(FUNC(mach8_device::ibm8514_htotal_r),m_8514),write16_delegate());
- m_isa->install16_device(0x26ec, 0x26ef, read16_delegate(FUNC(mach8_device::mach8_readonly_r),m_8514),write16_delegate(FUNC(mach8_device::mach8_crt_pitch_w),m_8514));
- m_isa->install16_device(0x2ee8, 0x2eeb, read16_delegate(FUNC(mach8_device::ibm8514_subcontrol_r),m_8514),write16_delegate());
- m_isa->install16_device(0x42e8, 0x42eb, read16_delegate(FUNC(mach8_device::ibm8514_substatus_r),m_8514), write16_delegate(FUNC(mach8_device::ibm8514_subcontrol_w),m_8514));
- m_isa->install16_device(0x4ae8, 0x4aeb, read16_delegate(FUNC(mach8_device::mach8_readonly_r),m_8514), write16_delegate(FUNC(mach8_device::mach8_advfunc_w),m_8514));
- m_isa->install16_device(0x4aec, 0x4aef, read16_delegate(FUNC(mach8_device::mach8_clksel_r),m_8514), write16_delegate(FUNC(mach8_device::mach8_clksel_w),m_8514));
- m_isa->install16_device(0x52e8, 0x52eb, read16_delegate(FUNC(mach8_device::mach8_ec0_r),m_8514), write16_delegate(FUNC(mach8_device::mach8_ec0_w),m_8514));
- m_isa->install16_device(0x52ec, 0x52ef, read16_delegate(FUNC(mach8_device::mach8_scratch0_r),m_8514), write16_delegate(FUNC(mach8_device::mach8_scratch0_w),m_8514));
- m_isa->install16_device(0x56e8, 0x56eb, read16_delegate(FUNC(mach8_device::mach8_ec1_r),m_8514), write16_delegate(FUNC(mach8_device::mach8_ec1_w),m_8514));
- m_isa->install16_device(0x56ec, 0x56ef, read16_delegate(FUNC(mach8_device::mach8_scratch0_r),m_8514), write16_delegate(FUNC(mach8_device::mach8_scratch0_w),m_8514));
- m_isa->install16_device(0x5ae8, 0x5aeb, read16_delegate(FUNC(mach8_device::mach8_ec2_r),m_8514), write16_delegate(FUNC(mach8_device::mach8_ec2_w),m_8514));
- m_isa->install16_device(0x5ee8, 0x5eeb, read16_delegate(FUNC(mach8_device::mach8_ec3_r),m_8514), write16_delegate(FUNC(mach8_device::mach8_ec3_w),m_8514));
- m_isa->install16_device(0x6eec, 0x6eef, read16_delegate(FUNC(mach8_device::mach8_readonly_r),m_8514), write16_delegate(FUNC(mach8_device::mach8_ge_offset_l_w),m_8514));
- m_isa->install16_device(0x72ec, 0x72ef, read16_delegate(FUNC(mach8_device::mach8_readonly_r),m_8514), write16_delegate(FUNC(mach8_device::mach8_ge_offset_h_w),m_8514));
- m_isa->install16_device(0x76ec, 0x76ef, read16_delegate(FUNC(mach8_device::mach8_readonly_r),m_8514), write16_delegate(FUNC(mach8_device::mach8_ge_pitch_w),m_8514));
- m_isa->install16_device(0x7aec, 0x7aef, read16_delegate(FUNC(mach8_device::mach8_readonly_r),m_8514), write16_delegate(FUNC(mach8_device::mach8_ge_ext_config_w),m_8514));
- m_isa->install16_device(0x82e8, 0x82eb, read16_delegate(FUNC(mach8_device::ibm8514_currenty_r),m_8514), write16_delegate(FUNC(mach8_device::ibm8514_currenty_w),m_8514));
- m_isa->install16_device(0x86e8, 0x86eb, read16_delegate(FUNC(mach8_device::ibm8514_currentx_r),m_8514), write16_delegate(FUNC(mach8_device::ibm8514_currentx_w),m_8514));
- m_isa->install16_device(0x8ae8, 0x8aeb, read16_delegate(FUNC(mach8_device::ibm8514_desty_r),m_8514), write16_delegate(FUNC(mach8_device::ibm8514_desty_w),m_8514));
- m_isa->install16_device(0x8ee8, 0x8eeb, read16_delegate(FUNC(mach8_device::ibm8514_destx_r),m_8514), write16_delegate(FUNC(mach8_device::ibm8514_destx_w),m_8514));
- m_isa->install16_device(0x8eec, 0x8eef, read16_delegate(FUNC(mach8_device::mach8_ge_ext_config_r),m_8514), write16_delegate(FUNC(mach8_device::mach8_patt_data_w),m_8514));
- m_isa->install16_device(0x92e8, 0x92eb, read16_delegate(FUNC(mach8_device::ibm8514_line_error_r),m_8514), write16_delegate(FUNC(mach8_device::ibm8514_line_error_w),m_8514));
- m_isa->install16_device(0x96e8, 0x96eb, read16_delegate(FUNC(mach8_device::ibm8514_width_r),m_8514), write16_delegate(FUNC(mach8_device::ibm8514_width_w),m_8514));
- m_isa->install16_device(0x96ec, 0x96ef, read16_delegate(FUNC(mach8_device::mach8_bresenham_count_r),m_8514), write16_delegate(FUNC(mach8_device::mach8_bresenham_count_w),m_8514));
- m_isa->install16_device(0x9ae8, 0x9aeb, read16_delegate(FUNC(mach8_device::ibm8514_gpstatus_r),m_8514), write16_delegate(FUNC(mach8_device::ibm8514_cmd_w),m_8514));
- m_isa->install16_device(0x9aec, 0x9aef, read16_delegate(FUNC(mach8_device::mach8_ext_fifo_r),m_8514), write16_delegate(FUNC(mach8_device::mach8_linedraw_index_w),m_8514));
- m_isa->install16_device(0x9ee8, 0x9eeb, read16_delegate(FUNC(mach8_device::ibm8514_ssv_r),m_8514), write16_delegate(FUNC(mach8_device::ibm8514_ssv_w),m_8514));
- m_isa->install16_device(0xa2e8, 0xa2eb, read16_delegate(FUNC(mach8_device::ibm8514_bgcolour_r),m_8514), write16_delegate(FUNC(mach8_device::ibm8514_bgcolour_w),m_8514));
- m_isa->install16_device(0xa6e8, 0xa6eb, read16_delegate(FUNC(mach8_device::ibm8514_fgcolour_r),m_8514), write16_delegate(FUNC(mach8_device::ibm8514_fgcolour_w),m_8514));
- m_isa->install16_device(0xaae8, 0xaaeb, read16_delegate(FUNC(ibm8514a_device::ibm8514_write_mask_r),m_8514), write16_delegate(FUNC(ibm8514a_device::ibm8514_write_mask_w),m_8514));
- m_isa->install16_device(0xaee8, 0xaeeb, read16_delegate(FUNC(ibm8514a_device::ibm8514_read_mask_r),m_8514), write16_delegate(FUNC(ibm8514a_device::ibm8514_read_mask_w),m_8514));
- m_isa->install16_device(0xb6e8, 0xb6eb, read16_delegate(FUNC(mach8_device::ibm8514_backmix_r),m_8514), write16_delegate(FUNC(mach8_device::ibm8514_backmix_w),m_8514));
- m_isa->install16_device(0xbae8, 0xbaeb, read16_delegate(FUNC(mach8_device::ibm8514_foremix_r),m_8514), write16_delegate(FUNC(mach8_device::ibm8514_foremix_w),m_8514));
- m_isa->install16_device(0xbee8, 0xbeeb, read16_delegate(FUNC(mach8_device::ibm8514_multifunc_r),m_8514), write16_delegate(FUNC(mach8_device::ibm8514_multifunc_w),m_8514));
- m_isa->install16_device(0xcaec, 0xcaef, read16_delegate(FUNC(mach8_device::mach8_readonly_r),m_8514), write16_delegate(FUNC(mach8_device::mach8_scan_x_w),m_8514));
- m_isa->install16_device(0xceec, 0xceef, read16_delegate(FUNC(mach8_device::mach8_readonly_r),m_8514), write16_delegate(FUNC(mach8_device::mach8_dp_config_w),m_8514));
- m_isa->install16_device(0xe2e8, 0xe2eb, read16_delegate(FUNC(mach8_device::ibm8514_pixel_xfer_r),m_8514), write16_delegate(FUNC(mach8_device::mach8_pixel_xfer_w),m_8514));
- m_isa->install16_device(0xdaec, 0xdaef, read16_delegate(FUNC(mach8_device::mach8_sourcex_r),m_8514), write16_delegate(FUNC(mach8_device::mach8_ext_leftscissor_w),m_8514));
- m_isa->install16_device(0xdeec, 0xdeef, read16_delegate(FUNC(mach8_device::mach8_sourcey_r),m_8514), write16_delegate(FUNC(mach8_device::mach8_ext_topscissor_w),m_8514));
- m_isa->install16_device(0xfeec, 0xfeef, read16_delegate(FUNC(mach8_device::mach8_linedraw_r),m_8514), write16_delegate(FUNC(mach8_device::mach8_linedraw_w),m_8514));
-
- m_isa->install_memory(0xa0000, 0xbffff, read8_delegate(FUNC(ati_vga_device::mem_r),m_vga), write8_delegate(FUNC(ati_vga_device::mem_w),m_vga));
+ m_isa->install_rom(this, 0xc0000, 0xc7fff, "gfxultra");
+
+ 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(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)));
+ m_isa->install16_device(0x16ec, 0x16ef, read16smo_delegate(*m_8514, FUNC(mach8_device::mach8_config2_r)), write16smo_delegate(*this));
+ m_isa->install16_device(0x1ae8, 0x1aeb, read16smo_delegate(*m_8514, FUNC(mach8_device::ibm8514_vsync_r)), write16smo_delegate(*m_8514, FUNC(mach8_device::ibm8514_vsync_w)));
+ m_isa->install16_device(0x22e8, 0x22eb, read16smo_delegate(*m_8514, FUNC(mach8_device::mach8_readonly_r)), write16smo_delegate(*m_8514, FUNC(mach8_device::ibm8514_display_ctrl_w)));
+ m_isa->install16_device(0x26e8, 0x26eb, read16smo_delegate(*m_8514, FUNC(mach8_device::ibm8514_htotal_r)), write16smo_delegate(*this));
+ m_isa->install16_device(0x26ec, 0x26ef, read16smo_delegate(*m_8514, FUNC(mach8_device::mach8_readonly_r)), write16smo_delegate(*m_8514, FUNC(mach8_device::mach8_crt_pitch_w)));
+ m_isa->install16_device(0x2ee8, 0x2eeb, read16smo_delegate(*m_8514, FUNC(mach8_device::ibm8514_subcontrol_r)), write16smo_delegate(*this));
+ m_isa->install16_device(0x42e8, 0x42eb, read16smo_delegate(*m_8514, FUNC(mach8_device::ibm8514_substatus_r)), write16smo_delegate(*m_8514, FUNC(mach8_device::ibm8514_subcontrol_w)));
+ m_isa->install16_device(0x4ae8, 0x4aeb, read16smo_delegate(*m_8514, FUNC(mach8_device::mach8_readonly_r)), write16smo_delegate(*m_8514, FUNC(mach8_device::mach8_advfunc_w)));
+ m_isa->install16_device(0x4aec, 0x4aef, read16smo_delegate(*m_8514, FUNC(mach8_device::mach8_clksel_r)), write16smo_delegate(*m_8514, FUNC(mach8_device::mach8_clksel_w)));
+ m_isa->install16_device(0x52e8, 0x52eb, read16smo_delegate(*m_8514, FUNC(mach8_device::mach8_ec0_r)), write16smo_delegate(*m_8514, FUNC(mach8_device::mach8_ec0_w)));
+ m_isa->install16_device(0x52ec, 0x52ef, read16smo_delegate(*m_8514, FUNC(mach8_device::mach8_scratch0_r)), write16smo_delegate(*m_8514, FUNC(mach8_device::mach8_scratch0_w)));
+ m_isa->install16_device(0x56e8, 0x56eb, read16smo_delegate(*m_8514, FUNC(mach8_device::mach8_ec1_r)), write16smo_delegate(*m_8514, FUNC(mach8_device::mach8_ec1_w)));
+ m_isa->install16_device(0x56ec, 0x56ef, read16smo_delegate(*m_8514, FUNC(mach8_device::mach8_scratch0_r)), write16smo_delegate(*m_8514, FUNC(mach8_device::mach8_scratch0_w)));
+ m_isa->install16_device(0x5ae8, 0x5aeb, read16smo_delegate(*m_8514, FUNC(mach8_device::mach8_ec2_r)), write16smo_delegate(*m_8514, FUNC(mach8_device::mach8_ec2_w)));
+ m_isa->install16_device(0x5ee8, 0x5eeb, read16smo_delegate(*m_8514, FUNC(mach8_device::mach8_ec3_r)), write16smo_delegate(*m_8514, FUNC(mach8_device::mach8_ec3_w)));
+ m_isa->install16_device(0x6eec, 0x6eef, read16smo_delegate(*m_8514, FUNC(mach8_device::mach8_readonly_r)), write16smo_delegate(*m_8514, FUNC(mach8_device::mach8_ge_offset_l_w)));
+ m_isa->install16_device(0x72ec, 0x72ef, read16smo_delegate(*m_8514, FUNC(mach8_device::mach8_readonly_r)), write16smo_delegate(*m_8514, FUNC(mach8_device::mach8_ge_offset_h_w)));
+ m_isa->install16_device(0x76ec, 0x76ef, read16smo_delegate(*m_8514, FUNC(mach8_device::mach8_readonly_r)), write16smo_delegate(*m_8514, FUNC(mach8_device::mach8_ge_pitch_w)));
+ m_isa->install16_device(0x7aec, 0x7aef, read16smo_delegate(*m_8514, FUNC(mach8_device::mach8_readonly_r)), write16smo_delegate(*m_8514, FUNC(mach8_device::mach8_ge_ext_config_w)));
+ m_isa->install16_device(0x82e8, 0x82eb, read16smo_delegate(*m_8514, FUNC(mach8_device::ibm8514_currenty_r)), write16smo_delegate(*m_8514, FUNC(mach8_device::ibm8514_currenty_w)));
+ m_isa->install16_device(0x86e8, 0x86eb, read16smo_delegate(*m_8514, FUNC(mach8_device::ibm8514_currentx_r)), write16smo_delegate(*m_8514, FUNC(mach8_device::ibm8514_currentx_w)));
+ m_isa->install16_device(0x8ae8, 0x8aeb, read16smo_delegate(*m_8514, FUNC(mach8_device::ibm8514_desty_r)), write16smo_delegate(*m_8514, FUNC(mach8_device::ibm8514_desty_w)));
+ m_isa->install16_device(0x8ee8, 0x8eeb, read16smo_delegate(*m_8514, FUNC(mach8_device::ibm8514_destx_r)), write16smo_delegate(*m_8514, FUNC(mach8_device::ibm8514_destx_w)));
+ m_isa->install16_device(0x8eec, 0x8eef, read16smo_delegate(*m_8514, FUNC(mach8_device::mach8_ge_ext_config_r)), write16smo_delegate(*m_8514, FUNC(mach8_device::mach8_patt_data_w)));
+ m_isa->install16_device(0x92e8, 0x92eb, read16smo_delegate(*m_8514, FUNC(mach8_device::ibm8514_line_error_r)), write16smo_delegate(*m_8514, FUNC(mach8_device::ibm8514_line_error_w)));
+ m_isa->install16_device(0x96e8, 0x96eb, read16smo_delegate(*m_8514, FUNC(mach8_device::ibm8514_width_r)), write16smo_delegate(*m_8514, FUNC(mach8_device::ibm8514_width_w)));
+ m_isa->install16_device(0x96ec, 0x96ef, read16smo_delegate(*m_8514, FUNC(mach8_device::mach8_bresenham_count_r)), write16smo_delegate(*m_8514, FUNC(mach8_device::mach8_bresenham_count_w)));
+ m_isa->install16_device(0x9ae8, 0x9aeb, read16smo_delegate(*m_8514, FUNC(mach8_device::ibm8514_gpstatus_r)), write16smo_delegate(*m_8514, FUNC(mach8_device::ibm8514_cmd_w)));
+ m_isa->install16_device(0x9aec, 0x9aef, read16smo_delegate(*m_8514, FUNC(mach8_device::mach8_ext_fifo_r)), write16smo_delegate(*m_8514, FUNC(mach8_device::mach8_linedraw_index_w)));
+ m_isa->install16_device(0x9ee8, 0x9eeb, read16smo_delegate(*m_8514, FUNC(mach8_device::ibm8514_ssv_r)), write16smo_delegate(*m_8514, FUNC(mach8_device::ibm8514_ssv_w)));
+ m_isa->install16_device(0xa2e8, 0xa2eb, read16smo_delegate(*m_8514, FUNC(mach8_device::ibm8514_bgcolour_r)), write16smo_delegate(*m_8514, FUNC(mach8_device::ibm8514_bgcolour_w)));
+ m_isa->install16_device(0xa6e8, 0xa6eb, read16smo_delegate(*m_8514, FUNC(mach8_device::ibm8514_fgcolour_r)), write16smo_delegate(*m_8514, FUNC(mach8_device::ibm8514_fgcolour_w)));
+ m_isa->install16_device(0xaae8, 0xaaeb, read16smo_delegate(*m_8514, FUNC(ibm8514a_device::ibm8514_write_mask_r)), write16smo_delegate(*m_8514, FUNC(ibm8514a_device::ibm8514_write_mask_w)));
+ m_isa->install16_device(0xaee8, 0xaeeb, read16smo_delegate(*m_8514, FUNC(ibm8514a_device::ibm8514_read_mask_r)), write16smo_delegate(*m_8514, FUNC(ibm8514a_device::ibm8514_read_mask_w)));
+ m_isa->install16_device(0xb6e8, 0xb6eb, read16smo_delegate(*m_8514, FUNC(mach8_device::ibm8514_backmix_r)), write16smo_delegate(*m_8514, FUNC(mach8_device::ibm8514_backmix_w)));
+ m_isa->install16_device(0xbae8, 0xbaeb, read16smo_delegate(*m_8514, FUNC(mach8_device::ibm8514_foremix_r)), write16smo_delegate(*m_8514, FUNC(mach8_device::ibm8514_foremix_w)));
+ m_isa->install16_device(0xbee8, 0xbeeb, read16smo_delegate(*m_8514, FUNC(mach8_device::ibm8514_multifunc_r)), write16smo_delegate(*m_8514, FUNC(mach8_device::ibm8514_multifunc_w)));
+ m_isa->install16_device(0xcaec, 0xcaef, read16smo_delegate(*m_8514, FUNC(mach8_device::mach8_readonly_r)), write16smo_delegate(*m_8514, FUNC(mach8_device::mach8_scan_x_w)));
+ m_isa->install16_device(0xceec, 0xceef, read16smo_delegate(*m_8514, FUNC(mach8_device::mach8_readonly_r)), write16smo_delegate(*m_8514, FUNC(mach8_device::mach8_dp_config_w)));
+ m_isa->install16_device(0xe2e8, 0xe2eb, read16sm_delegate(*m_8514, FUNC(mach8_device::ibm8514_pixel_xfer_r)), write16sm_delegate(*m_8514, FUNC(mach8_device::mach8_pixel_xfer_w)));
+ m_isa->install16_device(0xdaec, 0xdaef, read16smo_delegate(*m_8514, FUNC(mach8_device::mach8_sourcex_r)), write16smo_delegate(*m_8514, FUNC(mach8_device::mach8_ext_leftscissor_w)));
+ m_isa->install16_device(0xdeec, 0xdeef, read16smo_delegate(*m_8514, FUNC(mach8_device::mach8_sourcey_r)), write16smo_delegate(*m_8514, FUNC(mach8_device::mach8_ext_topscissor_w)));
+ m_isa->install16_device(0xfeec, 0xfeef, read16smo_delegate(*m_8514, FUNC(mach8_device::mach8_linedraw_r)), write16smo_delegate(*m_8514, FUNC(mach8_device::mach8_linedraw_w)));
+
+ m_isa->install_memory(0xa0000, 0xbffff, read8sm_delegate(*m_vga, FUNC(ati_vga_device::mem_r)), write8sm_delegate(*m_vga, FUNC(ati_vga_device::mem_w)));
}
void isa16_vga_gfxultrapro_device::device_start()
{
set_isa_device();
- m_vga = subdevice<mach32_device>("vga");
-
- m_isa->install_rom(this, 0xc0000, 0xc7fff, "vga", "gfxultrapro");
-
- m_isa->install_device(0x1ce, 0x1cf, read8_delegate(FUNC(mach32_device::ati_port_ext_r),m_vga), write8_delegate(FUNC(mach32_device::ati_port_ext_w),m_vga));
- m_isa->install_device(0x2e8, 0x2ef, read8_delegate(FUNC(mach32_device::mach32_status_r),m_vga), write8_delegate(FUNC(mach32_device::ibm8514_htotal_w),m_vga));
- m_isa->install_device(0x3b0, 0x3bf, read8_delegate(FUNC(mach32_device::port_03b0_r),m_vga), write8_delegate(FUNC(mach32_device::port_03b0_w),m_vga));
- m_isa->install_device(0x3c0, 0x3cf, read8_delegate(FUNC(mach32_device::port_03c0_r),m_vga), write8_delegate(FUNC(mach32_device::port_03c0_w),m_vga));
- m_isa->install_device(0x3d0, 0x3df, read8_delegate(FUNC(mach32_device::port_03d0_r),m_vga), write8_delegate(FUNC(mach32_device::port_03d0_w),m_vga));
- m_isa->install16_device(0xaec, 0xaef, read16_delegate(FUNC(mach32_device::mach32_readonly_r),m_vga), write16_delegate(FUNC(mach32_device::mach32_cursor_l_w),m_vga));
- m_isa->install16_device(0xeec, 0xeef, read16_delegate(FUNC(mach32_device::mach32_readonly_r),m_vga), write16_delegate(FUNC(mach32_device::mach32_cursor_h_w),m_vga));
- m_isa->install16_device(0x12e8, 0x12eb, read16_delegate(FUNC(mach32_device::ibm8514_vtotal_r),m_vga), write16_delegate(FUNC(mach32_device::ibm8514_vtotal_w),m_vga));
- m_isa->install16_device(0x12ec, 0x12ef, read16_delegate(FUNC(mach32_device::mach32_config1_r),m_vga), write16_delegate(FUNC(mach32_device::mach32_cursor_pos_h),m_vga));
- m_isa->install16_device(0x16e8, 0x16eb, read16_delegate(FUNC(mach32_device::ibm8514_vdisp_r),m_vga), write16_delegate(FUNC(mach32_device::ibm8514_vdisp_w),m_vga));
- m_isa->install16_device(0x16ec, 0x16ef, read16_delegate(FUNC(mach32_device::mach8_config2_r),m_vga), write16_delegate(FUNC(mach32_device::mach32_cursor_pos_v),m_vga));
- m_isa->install16_device(0x1ae8, 0x1aeb, read16_delegate(FUNC(mach32_device::ibm8514_vsync_r),m_vga), write16_delegate(FUNC(mach32_device::ibm8514_vsync_w),m_vga));
- m_isa->install16_device(0x1aec, 0x1aef, read16_delegate(FUNC(mach32_device::mach32_readonly_r),m_vga), write16_delegate(FUNC(mach32_device::mach32_cursor_colour_b_w),m_vga));
- m_isa->install16_device(0x1eec, 0x1eef, read16_delegate(FUNC(mach32_device::mach32_readonly_r),m_vga), write16_delegate(FUNC(mach32_device::mach32_cursor_offset_w),m_vga));
- m_isa->install16_device(0x26e8, 0x26eb, read16_delegate(FUNC(mach32_device::ibm8514_htotal_r),m_vga),write16_delegate());
- m_isa->install16_device(0x26ec, 0x26ef, read16_delegate(FUNC(mach32_device::mach32_readonly_r),m_vga),write16_delegate(FUNC(mach32_device::mach8_crt_pitch_w),m_vga));
- m_isa->install16_device(0x2ee8, 0x2eeb, read16_delegate(FUNC(mach32_device::ibm8514_subcontrol_r),m_vga),write16_delegate());
- m_isa->install16_device(0x3aec, 0x3aef, read16_delegate(FUNC(mach32_device::mach32_readonly_r),m_vga), write16_delegate(FUNC(mach32_device::mach32_cursor_colour_0_w),m_vga));
- m_isa->install16_device(0x3eec, 0x3eef, read16_delegate(FUNC(mach32_device::mach32_readonly_r),m_vga), write16_delegate(FUNC(mach32_device::mach32_cursor_colour_0_w),m_vga));
- m_isa->install16_device(0x42e8, 0x42eb, read16_delegate(FUNC(mach32_device::ibm8514_substatus_r),m_vga), write16_delegate(FUNC(mach32_device::ibm8514_subcontrol_w),m_vga));
- m_isa->install16_device(0x42ec, 0x42ef, read16_delegate(FUNC(mach32_device::mach32_mem_boundary_r),m_vga), write16_delegate(FUNC(mach32_device::mach32_mem_boundary_w),m_vga));
- m_isa->install16_device(0x4ae8, 0x4aeb, read16_delegate(FUNC(mach32_device::mach32_readonly_r),m_vga), write16_delegate(FUNC(mach32_device::mach8_advfunc_w),m_vga));
- m_isa->install16_device(0x4aec, 0x4aef, read16_delegate(FUNC(mach32_device::mach8_clksel_r),m_vga), write16_delegate(FUNC(mach32_device::mach8_clksel_w),m_vga));
- m_isa->install16_device(0x52e8, 0x52eb, read16_delegate(FUNC(mach32_device::mach8_ec0_r),m_vga), write16_delegate(FUNC(mach32_device::mach8_ec0_w),m_vga));
- m_isa->install16_device(0x52ec, 0x52ef, read16_delegate(FUNC(mach32_device::mach8_scratch0_r),m_vga), write16_delegate(FUNC(mach32_device::mach8_scratch0_w),m_vga));
- m_isa->install16_device(0x56e8, 0x56eb, read16_delegate(FUNC(mach32_device::mach8_ec1_r),m_vga), write16_delegate(FUNC(mach32_device::mach8_ec1_w),m_vga));
- m_isa->install16_device(0x56ec, 0x56ef, read16_delegate(FUNC(mach32_device::mach8_scratch0_r),m_vga), write16_delegate(FUNC(mach32_device::mach8_scratch0_w),m_vga));
- m_isa->install16_device(0x5ae8, 0x5aeb, read16_delegate(FUNC(mach32_device::mach8_ec2_r),m_vga), write16_delegate(FUNC(mach32_device::mach8_ec2_w),m_vga));
- m_isa->install16_device(0x5ee8, 0x5eeb, read16_delegate(FUNC(mach32_device::mach8_ec3_r),m_vga), write16_delegate(FUNC(mach32_device::mach8_ec3_w),m_vga));
- m_isa->install16_device(0x62ec, 0x62ef, read16_delegate(FUNC(mach32_device::mach32_ext_ge_r),m_vga), write16_delegate(FUNC(mach32_device::mach32_horz_overscan_w),m_vga));
- m_isa->install16_device(0x6eec, 0x6eef, read16_delegate(FUNC(mach32_device::mach32_readonly_r),m_vga), write16_delegate(FUNC(mach32_device::mach8_ge_offset_l_w),m_vga));
- m_isa->install16_device(0x72ec, 0x72ef, read16_delegate(FUNC(mach32_device::mach32_readonly_r),m_vga), write16_delegate(FUNC(mach32_device::mach8_ge_offset_h_w),m_vga));
- m_isa->install16_device(0x76ec, 0x76ef, read16_delegate(FUNC(mach32_device::mach32_readonly_r),m_vga), write16_delegate(FUNC(mach32_device::mach8_ge_pitch_w),m_vga));
- m_isa->install16_device(0x7aec, 0x7aef, read16_delegate(FUNC(mach32_device::mach32_readonly_r),m_vga), write16_delegate(FUNC(mach32_device::mach32_ge_ext_config_w),m_vga));
- m_isa->install16_device(0x82e8, 0x82eb, read16_delegate(FUNC(mach32_device::ibm8514_currenty_r),m_vga), write16_delegate(FUNC(mach32_device::ibm8514_currenty_w),m_vga));
- m_isa->install16_device(0x86e8, 0x86eb, read16_delegate(FUNC(mach32_device::ibm8514_currentx_r),m_vga), write16_delegate(FUNC(mach32_device::ibm8514_currentx_w),m_vga));
- m_isa->install16_device(0x8ae8, 0x8aeb, read16_delegate(FUNC(mach32_device::ibm8514_desty_r),m_vga), write16_delegate(FUNC(mach32_device::ibm8514_desty_w),m_vga));
- m_isa->install16_device(0x8ee8, 0x8eeb, read16_delegate(FUNC(mach32_device::ibm8514_destx_r),m_vga), write16_delegate(FUNC(mach32_device::ibm8514_destx_w),m_vga));
- m_isa->install16_device(0x8eec, 0x8eef, read16_delegate(FUNC(mach32_device::mach8_ge_ext_config_r),m_vga), write16_delegate(FUNC(mach32_device::mach8_patt_data_w),m_vga));
- m_isa->install16_device(0x92e8, 0x92eb, read16_delegate(FUNC(mach32_device::ibm8514_line_error_r),m_vga), write16_delegate(FUNC(mach32_device::ibm8514_line_error_w),m_vga));
- m_isa->install16_device(0x96e8, 0x96eb, read16_delegate(FUNC(mach32_device::ibm8514_width_r),m_vga), write16_delegate(FUNC(mach32_device::ibm8514_width_w),m_vga));
- m_isa->install16_device(0x96ec, 0x96ef, read16_delegate(FUNC(mach32_device::mach8_bresenham_count_r),m_vga), write16_delegate(FUNC(mach32_device::mach8_bresenham_count_w),m_vga));
- m_isa->install16_device(0x9ae8, 0x9aeb, read16_delegate(FUNC(mach32_device::ibm8514_gpstatus_r),m_vga), write16_delegate(FUNC(mach32_device::ibm8514_cmd_w),m_vga));
- m_isa->install16_device(0x9aec, 0x9aef, read16_delegate(FUNC(mach32_device::mach8_ext_fifo_r),m_vga), write16_delegate(FUNC(mach32_device::mach8_linedraw_index_w),m_vga));
- m_isa->install16_device(0x9ee8, 0x9eeb, read16_delegate(FUNC(mach32_device::ibm8514_ssv_r),m_vga), write16_delegate(FUNC(mach32_device::ibm8514_ssv_w),m_vga));
- m_isa->install16_device(0xa2e8, 0xa2eb, read16_delegate(FUNC(mach32_device::ibm8514_bgcolour_r),m_vga), write16_delegate(FUNC(mach32_device::ibm8514_bgcolour_w),m_vga));
- m_isa->install16_device(0xa6e8, 0xa6eb, read16_delegate(FUNC(mach32_device::ibm8514_fgcolour_r),m_vga), write16_delegate(FUNC(mach32_device::ibm8514_fgcolour_w),m_vga));
- m_isa->install16_device(0xaae8, 0xaaeb, read16_delegate(FUNC(mach32_device::ibm8514_write_mask_r),m_vga), write16_delegate(FUNC(mach32_device::ibm8514_write_mask_w),m_vga));
- m_isa->install16_device(0xaee8, 0xaeeb, read16_delegate(FUNC(mach32_device::ibm8514_read_mask_r),m_vga), write16_delegate(FUNC(mach32_device::ibm8514_read_mask_w),m_vga));
- m_isa->install16_device(0xb6e8, 0xb6eb, read16_delegate(FUNC(mach32_device::ibm8514_backmix_r),m_vga), write16_delegate(FUNC(mach32_device::ibm8514_backmix_w),m_vga));
- m_isa->install16_device(0xbae8, 0xbaeb, read16_delegate(FUNC(mach32_device::ibm8514_foremix_r),m_vga), write16_delegate(FUNC(mach32_device::ibm8514_foremix_w),m_vga));
- m_isa->install16_device(0xbee8, 0xbeeb, read16_delegate(FUNC(mach32_device::ibm8514_multifunc_r),m_vga), write16_delegate(FUNC(mach32_device::ibm8514_multifunc_w),m_vga));
- m_isa->install16_device(0xcaec, 0xcaef, read16_delegate(FUNC(mach32_device::mach32_readonly_r),m_vga), write16_delegate(FUNC(mach32_device::mach8_scan_x_w),m_vga));
- m_isa->install16_device(0xceec, 0xceef, read16_delegate(FUNC(mach32_device::mach32_readonly_r),m_vga), write16_delegate(FUNC(mach32_device::mach8_dp_config_w),m_vga));
- m_isa->install16_device(0xe2e8, 0xe2eb, read16_delegate(FUNC(mach32_device::ibm8514_pixel_xfer_r),m_vga), write16_delegate(FUNC(mach32_device::mach8_pixel_xfer_w),m_vga));
- m_isa->install16_device(0xdaec, 0xdaef, read16_delegate(FUNC(mach32_device::mach8_sourcex_r),m_vga), write16_delegate(FUNC(mach32_device::mach8_ext_leftscissor_w),m_vga));
- m_isa->install16_device(0xdeec, 0xdeef, read16_delegate(FUNC(mach32_device::mach8_sourcey_r),m_vga), write16_delegate(FUNC(mach32_device::mach8_ext_topscissor_w),m_vga));
- m_isa->install16_device(0xfaec, 0xfaef, read16_delegate(FUNC(mach32_device::mach32_chipid_r),m_vga), write16_delegate());
- m_isa->install16_device(0xfeec, 0xfeef, read16_delegate(FUNC(mach32_device::mach8_linedraw_r),m_vga), write16_delegate(FUNC(mach32_device::mach8_linedraw_w),m_vga));
-
- m_isa->install_memory(0xa0000, 0xbffff, read8_delegate(FUNC(mach32_device::mem_r),m_vga), write8_delegate(FUNC(mach32_device::mem_w),m_vga));
+ m_isa->install_rom(this, 0xc0000, 0xc7fff, "gfxultrapro");
+
+ 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(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)));
+ m_isa->install16_device(0x12ec, 0x12ef, read16sm_delegate(*m_vga, FUNC(mach32_device::mach32_config1_sm_r)), write16sm_delegate(*m_vga, FUNC(mach32_device::mach32_cursor_pos_h)));
+ m_isa->install16_device(0x16e8, 0x16eb, read16smo_delegate(*m_vga, FUNC(mach32_device::ibm8514_vdisp_r)), write16smo_delegate(*m_vga, FUNC(mach32_device::ibm8514_vdisp_w)));
+ m_isa->install16_device(0x16ec, 0x16ef, read16sm_delegate(*m_vga, FUNC(mach32_device::mach8_config2_sm_r)), write16sm_delegate(*m_vga, FUNC(mach32_device::mach32_cursor_pos_v)));
+ m_isa->install16_device(0x1ae8, 0x1aeb, read16smo_delegate(*m_vga, FUNC(mach32_device::ibm8514_vsync_r)), write16smo_delegate(*m_vga, FUNC(mach32_device::ibm8514_vsync_w)));
+ m_isa->install16_device(0x1aec, 0x1aef, read16sm_delegate(*m_vga, FUNC(mach32_device::mach32_readonly_sm_r)), write16sm_delegate(*m_vga, FUNC(mach32_device::mach32_cursor_colour_b_w)));
+ m_isa->install16_device(0x1eec, 0x1eef, read16s_delegate(*m_vga, FUNC(mach32_device::mach32_readonly_s_r)), write16s_delegate(*m_vga, FUNC(mach32_device::mach32_cursor_offset_w)));
+ m_isa->install16_device(0x26e8, 0x26eb, read16smo_delegate(*m_vga, FUNC(mach32_device::ibm8514_htotal_r)), write16smo_delegate(*this));
+ m_isa->install16_device(0x26ec, 0x26ef, read16smo_delegate(*m_vga, FUNC(mach32_device::mach32_readonly_smo_r)), write16smo_delegate(*m_vga, FUNC(mach32_device::mach8_crt_pitch_w)));
+ m_isa->install16_device(0x2ee8, 0x2eeb, read16smo_delegate(*m_vga, FUNC(mach32_device::ibm8514_subcontrol_r)), write16smo_delegate(*this));
+ m_isa->install16_device(0x3aec, 0x3aef, read16sm_delegate(*m_vga, FUNC(mach32_device::mach32_readonly_sm_r)), write16sm_delegate(*m_vga, FUNC(mach32_device::mach32_cursor_colour_0_w)));
+ m_isa->install16_device(0x3eec, 0x3eef, read16sm_delegate(*m_vga, FUNC(mach32_device::mach32_readonly_sm_r)), write16sm_delegate(*m_vga, FUNC(mach32_device::mach32_cursor_colour_0_w)));
+ m_isa->install16_device(0x42e8, 0x42eb, read16smo_delegate(*m_vga, FUNC(mach32_device::ibm8514_substatus_r)), write16smo_delegate(*m_vga, FUNC(mach32_device::ibm8514_subcontrol_w)));
+ m_isa->install16_device(0x42ec, 0x42ef, read16smo_delegate(*m_vga, FUNC(mach32_device::mach32_mem_boundary_r)), write16smo_delegate(*m_vga, FUNC(mach32_device::mach32_mem_boundary_w)));
+ m_isa->install16_device(0x4ae8, 0x4aeb, read16smo_delegate(*m_vga, FUNC(mach32_device::mach32_readonly_smo_r)), write16smo_delegate(*m_vga, FUNC(mach32_device::mach8_advfunc_w)));
+ m_isa->install16_device(0x4aec, 0x4aef, read16smo_delegate(*m_vga, FUNC(mach32_device::mach8_clksel_r)), write16smo_delegate(*m_vga, FUNC(mach32_device::mach8_clksel_w)));
+ m_isa->install16_device(0x52e8, 0x52eb, read16smo_delegate(*m_vga, FUNC(mach32_device::mach8_ec0_r)), write16smo_delegate(*m_vga, FUNC(mach32_device::mach8_ec0_w)));
+ m_isa->install16_device(0x52ec, 0x52ef, read16smo_delegate(*m_vga, FUNC(mach32_device::mach8_scratch0_r)), write16smo_delegate(*m_vga, FUNC(mach32_device::mach8_scratch0_w)));
+ m_isa->install16_device(0x56e8, 0x56eb, read16smo_delegate(*m_vga, FUNC(mach32_device::mach8_ec1_r)), write16smo_delegate(*m_vga, FUNC(mach32_device::mach8_ec1_w)));
+ m_isa->install16_device(0x56ec, 0x56ef, read16smo_delegate(*m_vga, FUNC(mach32_device::mach8_scratch0_r)), write16smo_delegate(*m_vga, FUNC(mach32_device::mach8_scratch0_w)));
+ m_isa->install16_device(0x5ae8, 0x5aeb, read16smo_delegate(*m_vga, FUNC(mach32_device::mach8_ec2_r)), write16smo_delegate(*m_vga, FUNC(mach32_device::mach8_ec2_w)));
+ m_isa->install16_device(0x5ee8, 0x5eeb, read16smo_delegate(*m_vga, FUNC(mach32_device::mach8_ec3_r)), write16smo_delegate(*m_vga, FUNC(mach32_device::mach8_ec3_w)));
+ m_isa->install16_device(0x62ec, 0x62ef, read16smo_delegate(*m_vga, FUNC(mach32_device::mach32_ext_ge_r)), write16smo_delegate(*m_vga, FUNC(mach32_device::mach32_horz_overscan_w)));
+ m_isa->install16_device(0x6eec, 0x6eef, read16smo_delegate(*m_vga, FUNC(mach32_device::mach32_readonly_smo_r)), write16smo_delegate(*m_vga, FUNC(mach32_device::mach8_ge_offset_l_w)));
+ m_isa->install16_device(0x72ec, 0x72ef, read16smo_delegate(*m_vga, FUNC(mach32_device::mach32_readonly_smo_r)), write16smo_delegate(*m_vga, FUNC(mach32_device::mach8_ge_offset_h_w)));
+ m_isa->install16_device(0x76ec, 0x76ef, read16smo_delegate(*m_vga, FUNC(mach32_device::mach32_readonly_smo_r)), write16smo_delegate(*m_vga, FUNC(mach32_device::mach8_ge_pitch_w)));
+ m_isa->install16_device(0x7aec, 0x7aef, read16s_delegate(*m_vga, FUNC(mach32_device::mach32_readonly_s_r)), write16s_delegate(*m_vga, FUNC(mach32_device::mach32_ge_ext_config_w)));
+ m_isa->install16_device(0x82e8, 0x82eb, read16smo_delegate(*m_vga, FUNC(mach32_device::ibm8514_currenty_r)), write16smo_delegate(*m_vga, FUNC(mach32_device::ibm8514_currenty_w)));
+ m_isa->install16_device(0x86e8, 0x86eb, read16smo_delegate(*m_vga, FUNC(mach32_device::ibm8514_currentx_r)), write16smo_delegate(*m_vga, FUNC(mach32_device::ibm8514_currentx_w)));
+ m_isa->install16_device(0x8ae8, 0x8aeb, read16smo_delegate(*m_vga, FUNC(mach32_device::ibm8514_desty_r)), write16smo_delegate(*m_vga, FUNC(mach32_device::ibm8514_desty_w)));
+ m_isa->install16_device(0x8ee8, 0x8eeb, read16smo_delegate(*m_vga, FUNC(mach32_device::ibm8514_destx_r)), write16smo_delegate(*m_vga, FUNC(mach32_device::ibm8514_destx_w)));
+ m_isa->install16_device(0x8eec, 0x8eef, read16smo_delegate(*m_vga, FUNC(mach32_device::mach8_ge_ext_config_r)), write16smo_delegate(*m_vga, FUNC(mach32_device::mach8_patt_data_w)));
+ m_isa->install16_device(0x92e8, 0x92eb, read16smo_delegate(*m_vga, FUNC(mach32_device::ibm8514_line_error_r)), write16smo_delegate(*m_vga, FUNC(mach32_device::ibm8514_line_error_w)));
+ m_isa->install16_device(0x96e8, 0x96eb, read16smo_delegate(*m_vga, FUNC(mach32_device::ibm8514_width_r)), write16smo_delegate(*m_vga, FUNC(mach32_device::ibm8514_width_w)));
+ m_isa->install16_device(0x96ec, 0x96ef, read16smo_delegate(*m_vga, FUNC(mach32_device::mach8_bresenham_count_r)), write16smo_delegate(*m_vga, FUNC(mach32_device::mach8_bresenham_count_w)));
+ m_isa->install16_device(0x9ae8, 0x9aeb, read16smo_delegate(*m_vga, FUNC(mach32_device::ibm8514_gpstatus_r)), write16smo_delegate(*m_vga, FUNC(mach32_device::ibm8514_cmd_w)));
+ m_isa->install16_device(0x9aec, 0x9aef, read16smo_delegate(*m_vga, FUNC(mach32_device::mach8_ext_fifo_r)), write16smo_delegate(*m_vga, FUNC(mach32_device::mach8_linedraw_index_w)));
+ m_isa->install16_device(0x9ee8, 0x9eeb, read16smo_delegate(*m_vga, FUNC(mach32_device::ibm8514_ssv_r)), write16smo_delegate(*m_vga, FUNC(mach32_device::ibm8514_ssv_w)));
+ m_isa->install16_device(0xa2e8, 0xa2eb, read16smo_delegate(*m_vga, FUNC(mach32_device::ibm8514_bgcolour_r)), write16smo_delegate(*m_vga, FUNC(mach32_device::ibm8514_bgcolour_w)));
+ m_isa->install16_device(0xa6e8, 0xa6eb, read16smo_delegate(*m_vga, FUNC(mach32_device::ibm8514_fgcolour_r)), write16smo_delegate(*m_vga, FUNC(mach32_device::ibm8514_fgcolour_w)));
+ m_isa->install16_device(0xaae8, 0xaaeb, read16smo_delegate(*m_vga, FUNC(mach32_device::ibm8514_write_mask_r)), write16smo_delegate(*m_vga, FUNC(mach32_device::ibm8514_write_mask_w)));
+ m_isa->install16_device(0xaee8, 0xaeeb, read16smo_delegate(*m_vga, FUNC(mach32_device::ibm8514_read_mask_r)), write16smo_delegate(*m_vga, FUNC(mach32_device::ibm8514_read_mask_w)));
+ m_isa->install16_device(0xb6e8, 0xb6eb, read16smo_delegate(*m_vga, FUNC(mach32_device::ibm8514_backmix_r)), write16smo_delegate(*m_vga, FUNC(mach32_device::ibm8514_backmix_w)));
+ m_isa->install16_device(0xbae8, 0xbaeb, read16smo_delegate(*m_vga, FUNC(mach32_device::ibm8514_foremix_r)), write16smo_delegate(*m_vga, FUNC(mach32_device::ibm8514_foremix_w)));
+ m_isa->install16_device(0xbee8, 0xbeeb, read16smo_delegate(*m_vga, FUNC(mach32_device::ibm8514_multifunc_r)), write16smo_delegate(*m_vga, FUNC(mach32_device::ibm8514_multifunc_w)));
+ m_isa->install16_device(0xcaec, 0xcaef, read16smo_delegate(*m_vga, FUNC(mach32_device::mach32_readonly_smo_r)), write16smo_delegate(*m_vga, FUNC(mach32_device::mach8_scan_x_w)));
+ m_isa->install16_device(0xceec, 0xceef, read16smo_delegate(*m_vga, FUNC(mach32_device::mach32_readonly_smo_r)), write16smo_delegate(*m_vga, FUNC(mach32_device::mach8_dp_config_w)));
+ m_isa->install16_device(0xe2e8, 0xe2eb, read16sm_delegate(*m_vga, FUNC(mach32_device::ibm8514_pixel_xfer_r)), write16sm_delegate(*m_vga, FUNC(mach32_device::mach8_pixel_xfer_w)));
+ m_isa->install16_device(0xdaec, 0xdaef, read16smo_delegate(*m_vga, FUNC(mach32_device::mach8_sourcex_r)), write16smo_delegate(*m_vga, FUNC(mach32_device::mach8_ext_leftscissor_w)));
+ m_isa->install16_device(0xdeec, 0xdeef, read16smo_delegate(*m_vga, FUNC(mach32_device::mach8_sourcey_r)), write16smo_delegate(*m_vga, FUNC(mach32_device::mach8_ext_topscissor_w)));
+ m_isa->install16_device(0xfaec, 0xfaef, read16smo_delegate(*m_vga, FUNC(mach32_device::mach32_chipid_r)), write16smo_delegate(*this));
+ m_isa->install16_device(0xfeec, 0xfeef, read16smo_delegate(*m_vga, FUNC(mach32_device::mach8_linedraw_r)), write16smo_delegate(*m_vga, FUNC(mach32_device::mach8_linedraw_w)));
+
+ m_isa->install_memory(0xa0000, 0xbffff, read8sm_delegate(*m_vga, FUNC(mach32_device::mem_r)), write8sm_delegate(*m_vga, FUNC(mach32_device::mem_w)));
}
void isa16_vga_mach64_device::device_start()
{
set_isa_device();
- m_vga = subdevice<mach64_device>("vga");
-
- m_isa->install_rom(this, 0xc0000, 0xc7fff, "vga", "mach64");
-
- m_isa->install_device(0x1ce, 0x1cf, read8_delegate(FUNC(mach64_device::ati_port_ext_r),m_vga), write8_delegate(FUNC(mach64_device::ati_port_ext_w),m_vga));
- m_isa->install_device(0x2e8, 0x2ef, read8_delegate(FUNC(mach64_device::mach32_status_r),m_vga), write8_delegate(FUNC(mach64_device::ibm8514_htotal_w),m_vga));
- m_isa->install_device(0x3b0, 0x3bf, read8_delegate(FUNC(mach64_device::port_03b0_r),m_vga), write8_delegate(FUNC(mach64_device::port_03b0_w),m_vga));
- m_isa->install_device(0x3c0, 0x3cf, read8_delegate(FUNC(mach64_device::port_03c0_r),m_vga), write8_delegate(FUNC(mach64_device::port_03c0_w),m_vga));
- m_isa->install_device(0x3d0, 0x3df, read8_delegate(FUNC(mach64_device::port_03d0_r),m_vga), write8_delegate(FUNC(mach64_device::port_03d0_w),m_vga));
- m_isa->install16_device(0x12e8, 0x12eb, read16_delegate(FUNC(mach64_device::ibm8514_vtotal_r),m_vga), write16_delegate(FUNC(mach64_device::ibm8514_vtotal_w),m_vga));
- m_isa->install16_device(0x12ec, 0x12ef, read16_delegate(FUNC(mach64_device::mach32_config1_r),m_vga), write16_delegate(FUNC(mach64_device::mach64_config1_w),m_vga));
- m_isa->install16_device(0x16e8, 0x16eb, read16_delegate(FUNC(mach64_device::ibm8514_vdisp_r),m_vga), write16_delegate(FUNC(mach64_device::ibm8514_vdisp_w),m_vga));
- m_isa->install16_device(0x16ec, 0x16ef, read16_delegate(FUNC(mach64_device::mach8_config2_r),m_vga), write16_delegate(FUNC(mach64_device::mach64_config2_w),m_vga));
- m_isa->install16_device(0x1ae8, 0x1aeb, read16_delegate(FUNC(mach64_device::ibm8514_vsync_r),m_vga), write16_delegate(FUNC(mach64_device::ibm8514_vsync_w),m_vga));
- m_isa->install16_device(0x26e8, 0x26eb, read16_delegate(FUNC(mach64_device::ibm8514_htotal_r),m_vga),write16_delegate());
- m_isa->install16_device(0x26ec, 0x26ef, read16_delegate(FUNC(mach64_device::mach32_readonly_r),m_vga),write16_delegate(FUNC(mach64_device::mach8_crt_pitch_w),m_vga));
- m_isa->install16_device(0x2ee8, 0x2eeb, read16_delegate(FUNC(mach64_device::ibm8514_subcontrol_r),m_vga),write16_delegate());
- m_isa->install16_device(0x42e8, 0x42eb, read16_delegate(FUNC(mach64_device::ibm8514_substatus_r),m_vga), write16_delegate(FUNC(mach64_device::ibm8514_subcontrol_w),m_vga));
- m_isa->install16_device(0x42ec, 0x42ef, read16_delegate(FUNC(mach64_device::mach32_mem_boundary_r),m_vga), write16_delegate(FUNC(mach64_device::mach32_mem_boundary_w),m_vga));
- m_isa->install16_device(0x4ae8, 0x4aeb, read16_delegate(FUNC(mach64_device::mach32_readonly_r),m_vga), write16_delegate(FUNC(mach64_device::mach8_advfunc_w),m_vga));
- m_isa->install16_device(0x4aec, 0x4aef, read16_delegate(FUNC(mach64_device::mach8_clksel_r),m_vga), write16_delegate(FUNC(mach64_device::mach8_clksel_w),m_vga));
- m_isa->install16_device(0x52e8, 0x52eb, read16_delegate(FUNC(mach64_device::mach8_ec0_r),m_vga), write16_delegate(FUNC(mach64_device::mach8_ec0_w),m_vga));
- m_isa->install16_device(0x52ec, 0x52ef, read16_delegate(FUNC(mach64_device::mach8_scratch0_r),m_vga), write16_delegate(FUNC(mach64_device::mach8_scratch0_w),m_vga));
- m_isa->install16_device(0x56e8, 0x56eb, read16_delegate(FUNC(mach64_device::mach8_ec1_r),m_vga), write16_delegate(FUNC(mach64_device::mach8_ec1_w),m_vga));
- m_isa->install16_device(0x56ec, 0x56ef, read16_delegate(FUNC(mach64_device::mach8_scratch0_r),m_vga), write16_delegate(FUNC(mach64_device::mach8_scratch0_w),m_vga));
- m_isa->install16_device(0x5ae8, 0x5aeb, read16_delegate(FUNC(mach64_device::mach8_ec2_r),m_vga), write16_delegate(FUNC(mach64_device::mach8_ec2_w),m_vga));
- m_isa->install16_device(0x5ee8, 0x5eeb, read16_delegate(FUNC(mach64_device::mach8_ec3_r),m_vga), write16_delegate(FUNC(mach64_device::mach8_ec3_w),m_vga));
- m_isa->install16_device(0x6eec, 0x6eef, read16_delegate(FUNC(mach64_device::mach32_readonly_r),m_vga), write16_delegate(FUNC(mach64_device::mach8_ge_offset_l_w),m_vga));
- m_isa->install16_device(0x72ec, 0x72ef, read16_delegate(FUNC(mach64_device::mach32_readonly_r),m_vga), write16_delegate(FUNC(mach64_device::mach8_ge_offset_h_w),m_vga));
- m_isa->install16_device(0x76ec, 0x76ef, read16_delegate(FUNC(mach64_device::mach32_readonly_r),m_vga), write16_delegate(FUNC(mach64_device::mach8_ge_pitch_w),m_vga));
- m_isa->install16_device(0x7aec, 0x7aef, read16_delegate(FUNC(mach64_device::mach32_readonly_r),m_vga), write16_delegate(FUNC(mach64_device::mach32_ge_ext_config_w),m_vga));
- m_isa->install16_device(0x82e8, 0x82eb, read16_delegate(FUNC(mach64_device::ibm8514_currenty_r),m_vga), write16_delegate(FUNC(mach64_device::ibm8514_currenty_w),m_vga));
- m_isa->install16_device(0x86e8, 0x86eb, read16_delegate(FUNC(mach64_device::ibm8514_currentx_r),m_vga), write16_delegate(FUNC(mach64_device::ibm8514_currentx_w),m_vga));
- m_isa->install16_device(0x8ae8, 0x8aeb, read16_delegate(FUNC(mach64_device::ibm8514_desty_r),m_vga), write16_delegate(FUNC(mach64_device::ibm8514_desty_w),m_vga));
- m_isa->install16_device(0x8ee8, 0x8eeb, read16_delegate(FUNC(mach64_device::ibm8514_destx_r),m_vga), write16_delegate(FUNC(mach64_device::ibm8514_destx_w),m_vga));
- m_isa->install16_device(0x8eec, 0x8eef, read16_delegate(FUNC(mach64_device::mach8_ge_ext_config_r),m_vga), write16_delegate(FUNC(mach64_device::mach8_patt_data_w),m_vga));
- m_isa->install16_device(0x92e8, 0x92eb, read16_delegate(FUNC(mach64_device::ibm8514_line_error_r),m_vga), write16_delegate(FUNC(mach64_device::ibm8514_line_error_w),m_vga));
- m_isa->install16_device(0x96e8, 0x96eb, read16_delegate(FUNC(mach64_device::ibm8514_width_r),m_vga), write16_delegate(FUNC(mach64_device::ibm8514_width_w),m_vga));
- m_isa->install16_device(0x96ec, 0x96ef, read16_delegate(FUNC(mach64_device::mach8_bresenham_count_r),m_vga), write16_delegate(FUNC(mach64_device::mach8_bresenham_count_w),m_vga));
- m_isa->install16_device(0x9ae8, 0x9aeb, read16_delegate(FUNC(mach64_device::ibm8514_gpstatus_r),m_vga), write16_delegate(FUNC(mach64_device::ibm8514_cmd_w),m_vga));
- m_isa->install16_device(0x9aec, 0x9aef, read16_delegate(FUNC(mach64_device::mach8_ext_fifo_r),m_vga), write16_delegate(FUNC(mach64_device::mach8_linedraw_index_w),m_vga));
- m_isa->install16_device(0x9ee8, 0x9eeb, read16_delegate(FUNC(mach64_device::ibm8514_ssv_r),m_vga), write16_delegate(FUNC(mach64_device::ibm8514_ssv_w),m_vga));
- m_isa->install16_device(0xa2e8, 0xa2eb, read16_delegate(FUNC(mach64_device::ibm8514_bgcolour_r),m_vga), write16_delegate(FUNC(mach64_device::ibm8514_bgcolour_w),m_vga));
- m_isa->install16_device(0xa6e8, 0xa6eb, read16_delegate(FUNC(mach64_device::ibm8514_fgcolour_r),m_vga), write16_delegate(FUNC(mach64_device::ibm8514_fgcolour_w),m_vga));
- m_isa->install16_device(0xaae8, 0xaaeb, read16_delegate(FUNC(mach64_device::ibm8514_write_mask_r),m_vga), write16_delegate(FUNC(mach64_device::ibm8514_write_mask_w),m_vga));
- m_isa->install16_device(0xaee8, 0xaeeb, read16_delegate(FUNC(mach64_device::ibm8514_read_mask_r),m_vga), write16_delegate(FUNC(mach64_device::ibm8514_read_mask_w),m_vga));
- m_isa->install16_device(0xb6e8, 0xb6eb, read16_delegate(FUNC(mach64_device::ibm8514_backmix_r),m_vga), write16_delegate(FUNC(mach64_device::ibm8514_backmix_w),m_vga));
- m_isa->install16_device(0xbae8, 0xbaeb, read16_delegate(FUNC(mach64_device::ibm8514_foremix_r),m_vga), write16_delegate(FUNC(mach64_device::ibm8514_foremix_w),m_vga));
- m_isa->install16_device(0xbee8, 0xbeeb, read16_delegate(FUNC(mach64_device::ibm8514_multifunc_r),m_vga), write16_delegate(FUNC(mach64_device::ibm8514_multifunc_w),m_vga));
- m_isa->install16_device(0xcaec, 0xcaef, read16_delegate(FUNC(mach64_device::mach32_readonly_r),m_vga), write16_delegate(FUNC(mach64_device::mach8_scan_x_w),m_vga));
- m_isa->install16_device(0xceec, 0xceef, read16_delegate(FUNC(mach64_device::mach32_readonly_r),m_vga), write16_delegate(FUNC(mach64_device::mach8_dp_config_w),m_vga));
- m_isa->install16_device(0xe2e8, 0xe2eb, read16_delegate(FUNC(mach64_device::ibm8514_pixel_xfer_r),m_vga), write16_delegate(FUNC(mach64_device::mach8_pixel_xfer_w),m_vga));
- m_isa->install16_device(0xdaec, 0xdaef, read16_delegate(FUNC(mach64_device::mach8_sourcex_r),m_vga), write16_delegate(FUNC(mach64_device::mach8_ext_leftscissor_w),m_vga));
- m_isa->install16_device(0xdeec, 0xdeef, read16_delegate(FUNC(mach64_device::mach8_sourcey_r),m_vga), write16_delegate(FUNC(mach64_device::mach8_ext_topscissor_w),m_vga));
- m_isa->install16_device(0xfaec, 0xfaef, read16_delegate(FUNC(mach64_device::mach32_chipid_r),m_vga), write16_delegate());
- m_isa->install16_device(0xfeec, 0xfeef, read16_delegate(FUNC(mach64_device::mach8_linedraw_r),m_vga), write16_delegate(FUNC(mach64_device::mach8_linedraw_w),m_vga));
-
- m_isa->install_memory(0xa0000, 0xbffff, read8_delegate(FUNC(mach64_device::mem_r),m_vga), write8_delegate(FUNC(mach64_device::mem_w),m_vga));
+ m_isa->install_rom(this, 0xc0000, 0xc7fff, "mach64");
+
+ 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(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)));
+ m_isa->install16_device(0x16ec, 0x16ef, read16smo_delegate(*m_vga, FUNC(mach64_device::mach8_config2_smo_r)), write16smo_delegate(*m_vga, FUNC(mach64_device::mach64_config2_w)));
+ m_isa->install16_device(0x1ae8, 0x1aeb, read16smo_delegate(*m_vga, FUNC(mach64_device::ibm8514_vsync_r)), write16smo_delegate(*m_vga, FUNC(mach64_device::ibm8514_vsync_w)));
+ m_isa->install16_device(0x26e8, 0x26eb, read16smo_delegate(*m_vga, FUNC(mach64_device::ibm8514_htotal_r)), write16smo_delegate(*this));
+ m_isa->install16_device(0x26ec, 0x26ef, read16smo_delegate(*m_vga, FUNC(mach64_device::mach32_readonly_smo_r)), write16smo_delegate(*m_vga, FUNC(mach64_device::mach8_crt_pitch_w)));
+ m_isa->install16_device(0x2ee8, 0x2eeb, read16smo_delegate(*m_vga, FUNC(mach64_device::ibm8514_subcontrol_r)),write16smo_delegate(*this));
+ m_isa->install16_device(0x42e8, 0x42eb, read16smo_delegate(*m_vga, FUNC(mach64_device::ibm8514_substatus_r)), write16smo_delegate(*m_vga, FUNC(mach64_device::ibm8514_subcontrol_w)));
+ m_isa->install16_device(0x42ec, 0x42ef, read16smo_delegate(*m_vga, FUNC(mach64_device::mach32_mem_boundary_r)), write16smo_delegate(*m_vga, FUNC(mach64_device::mach32_mem_boundary_w)));
+ m_isa->install16_device(0x4ae8, 0x4aeb, read16smo_delegate(*m_vga, FUNC(mach64_device::mach32_readonly_smo_r)), write16smo_delegate(*m_vga, FUNC(mach64_device::mach8_advfunc_w)));
+ m_isa->install16_device(0x4aec, 0x4aef, read16smo_delegate(*m_vga, FUNC(mach64_device::mach8_clksel_r)), write16smo_delegate(*m_vga, FUNC(mach64_device::mach8_clksel_w)));
+ m_isa->install16_device(0x52e8, 0x52eb, read16smo_delegate(*m_vga, FUNC(mach64_device::mach8_ec0_r)), write16smo_delegate(*m_vga, FUNC(mach64_device::mach8_ec0_w)));
+ m_isa->install16_device(0x52ec, 0x52ef, read16smo_delegate(*m_vga, FUNC(mach64_device::mach8_scratch0_r)), write16smo_delegate(*m_vga, FUNC(mach64_device::mach8_scratch0_w)));
+ m_isa->install16_device(0x56e8, 0x56eb, read16smo_delegate(*m_vga, FUNC(mach64_device::mach8_ec1_r)), write16smo_delegate(*m_vga, FUNC(mach64_device::mach8_ec1_w)));
+ m_isa->install16_device(0x56ec, 0x56ef, read16smo_delegate(*m_vga, FUNC(mach64_device::mach8_scratch0_r)), write16smo_delegate(*m_vga, FUNC(mach64_device::mach8_scratch0_w)));
+ m_isa->install16_device(0x5ae8, 0x5aeb, read16smo_delegate(*m_vga, FUNC(mach64_device::mach8_ec2_r)), write16smo_delegate(*m_vga, FUNC(mach64_device::mach8_ec2_w)));
+ m_isa->install16_device(0x5ee8, 0x5eeb, read16smo_delegate(*m_vga, FUNC(mach64_device::mach8_ec3_r)), write16smo_delegate(*m_vga, FUNC(mach64_device::mach8_ec3_w)));
+ m_isa->install16_device(0x6eec, 0x6eef, read16smo_delegate(*m_vga, FUNC(mach64_device::mach32_readonly_smo_r)), write16smo_delegate(*m_vga, FUNC(mach64_device::mach8_ge_offset_l_w)));
+ m_isa->install16_device(0x72ec, 0x72ef, read16smo_delegate(*m_vga, FUNC(mach64_device::mach32_readonly_smo_r)), write16smo_delegate(*m_vga, FUNC(mach64_device::mach8_ge_offset_h_w)));
+ m_isa->install16_device(0x76ec, 0x76ef, read16smo_delegate(*m_vga, FUNC(mach64_device::mach32_readonly_smo_r)), write16smo_delegate(*m_vga, FUNC(mach64_device::mach8_ge_pitch_w)));
+ m_isa->install16_device(0x7aec, 0x7aef, read16s_delegate(*m_vga, FUNC(mach64_device::mach32_readonly_s_r)), write16s_delegate(*m_vga, FUNC(mach64_device::mach32_ge_ext_config_w)));
+ m_isa->install16_device(0x82e8, 0x82eb, read16smo_delegate(*m_vga, FUNC(mach64_device::ibm8514_currenty_r)), write16smo_delegate(*m_vga, FUNC(mach64_device::ibm8514_currenty_w)));
+ m_isa->install16_device(0x86e8, 0x86eb, read16smo_delegate(*m_vga, FUNC(mach64_device::ibm8514_currentx_r)), write16smo_delegate(*m_vga, FUNC(mach64_device::ibm8514_currentx_w)));
+ m_isa->install16_device(0x8ae8, 0x8aeb, read16smo_delegate(*m_vga, FUNC(mach64_device::ibm8514_desty_r)), write16smo_delegate(*m_vga, FUNC(mach64_device::ibm8514_desty_w)));
+ m_isa->install16_device(0x8ee8, 0x8eeb, read16smo_delegate(*m_vga, FUNC(mach64_device::ibm8514_destx_r)), write16smo_delegate(*m_vga, FUNC(mach64_device::ibm8514_destx_w)));
+ m_isa->install16_device(0x8eec, 0x8eef, read16smo_delegate(*m_vga, FUNC(mach64_device::mach8_ge_ext_config_r)), write16smo_delegate(*m_vga, FUNC(mach64_device::mach8_patt_data_w)));
+ m_isa->install16_device(0x92e8, 0x92eb, read16smo_delegate(*m_vga, FUNC(mach64_device::ibm8514_line_error_r)), write16smo_delegate(*m_vga, FUNC(mach64_device::ibm8514_line_error_w)));
+ m_isa->install16_device(0x96e8, 0x96eb, read16smo_delegate(*m_vga, FUNC(mach64_device::ibm8514_width_r)), write16smo_delegate(*m_vga, FUNC(mach64_device::ibm8514_width_w)));
+ m_isa->install16_device(0x96ec, 0x96ef, read16smo_delegate(*m_vga, FUNC(mach64_device::mach8_bresenham_count_r)), write16smo_delegate(*m_vga, FUNC(mach64_device::mach8_bresenham_count_w)));
+ m_isa->install16_device(0x9ae8, 0x9aeb, read16smo_delegate(*m_vga, FUNC(mach64_device::ibm8514_gpstatus_r)), write16smo_delegate(*m_vga, FUNC(mach64_device::ibm8514_cmd_w)));
+ m_isa->install16_device(0x9aec, 0x9aef, read16smo_delegate(*m_vga, FUNC(mach64_device::mach8_ext_fifo_r)), write16smo_delegate(*m_vga, FUNC(mach64_device::mach8_linedraw_index_w)));
+ m_isa->install16_device(0x9ee8, 0x9eeb, read16smo_delegate(*m_vga, FUNC(mach64_device::ibm8514_ssv_r)), write16smo_delegate(*m_vga, FUNC(mach64_device::ibm8514_ssv_w)));
+ m_isa->install16_device(0xa2e8, 0xa2eb, read16smo_delegate(*m_vga, FUNC(mach64_device::ibm8514_bgcolour_r)), write16smo_delegate(*m_vga, FUNC(mach64_device::ibm8514_bgcolour_w)));
+ m_isa->install16_device(0xa6e8, 0xa6eb, read16smo_delegate(*m_vga, FUNC(mach64_device::ibm8514_fgcolour_r)), write16smo_delegate(*m_vga, FUNC(mach64_device::ibm8514_fgcolour_w)));
+ m_isa->install16_device(0xaae8, 0xaaeb, read16smo_delegate(*m_vga, FUNC(mach64_device::ibm8514_write_mask_r)), write16smo_delegate(*m_vga, FUNC(mach64_device::ibm8514_write_mask_w)));
+ m_isa->install16_device(0xaee8, 0xaeeb, read16smo_delegate(*m_vga, FUNC(mach64_device::ibm8514_read_mask_r)), write16smo_delegate(*m_vga, FUNC(mach64_device::ibm8514_read_mask_w)));
+ m_isa->install16_device(0xb6e8, 0xb6eb, read16smo_delegate(*m_vga, FUNC(mach64_device::ibm8514_backmix_r)), write16smo_delegate(*m_vga, FUNC(mach64_device::ibm8514_backmix_w)));
+ m_isa->install16_device(0xbae8, 0xbaeb, read16smo_delegate(*m_vga, FUNC(mach64_device::ibm8514_foremix_r)), write16smo_delegate(*m_vga, FUNC(mach64_device::ibm8514_foremix_w)));
+ m_isa->install16_device(0xbee8, 0xbeeb, read16smo_delegate(*m_vga, FUNC(mach64_device::ibm8514_multifunc_r)), write16smo_delegate(*m_vga, FUNC(mach64_device::ibm8514_multifunc_w)));
+ m_isa->install16_device(0xcaec, 0xcaef, read16smo_delegate(*m_vga, FUNC(mach64_device::mach32_readonly_smo_r)), write16smo_delegate(*m_vga, FUNC(mach64_device::mach8_scan_x_w)));
+ m_isa->install16_device(0xceec, 0xceef, read16smo_delegate(*m_vga, FUNC(mach64_device::mach32_readonly_smo_r)), write16smo_delegate(*m_vga, FUNC(mach64_device::mach8_dp_config_w)));
+ m_isa->install16_device(0xe2e8, 0xe2eb, read16sm_delegate(*m_vga, FUNC(mach64_device::ibm8514_pixel_xfer_r)), write16sm_delegate(*m_vga, FUNC(mach64_device::mach8_pixel_xfer_w)));
+ m_isa->install16_device(0xdaec, 0xdaef, read16smo_delegate(*m_vga, FUNC(mach64_device::mach8_sourcex_r)), write16smo_delegate(*m_vga, FUNC(mach64_device::mach8_ext_leftscissor_w)));
+ m_isa->install16_device(0xdeec, 0xdeef, read16smo_delegate(*m_vga, FUNC(mach64_device::mach8_sourcey_r)), write16smo_delegate(*m_vga, FUNC(mach64_device::mach8_ext_topscissor_w)));
+ m_isa->install16_device(0xfaec, 0xfaef, read16smo_delegate(*m_vga, FUNC(mach64_device::mach32_chipid_r)), write16smo_delegate(*this));
+ m_isa->install16_device(0xfeec, 0xfeef, read16smo_delegate(*m_vga, FUNC(mach64_device::mach8_linedraw_r)), write16smo_delegate(*m_vga, FUNC(mach64_device::mach8_linedraw_w)));
+
+ m_isa->install_memory(0xa0000, 0xbffff, read8sm_delegate(*m_vga, FUNC(mach64_device::mem_r)), write8sm_delegate(*m_vga, FUNC(mach64_device::mem_w)));
}
//-------------------------------------------------
diff --git a/src/devices/bus/isa/vga_ati.h b/src/devices/bus/isa/vga_ati.h
index e626f8a45ab..39fdb19cce2 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
@@ -30,20 +31,22 @@ public:
// construction/destruction
isa16_vga_gfxultra_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
- DECLARE_READ8_MEMBER(input_port_0_r);
+ uint8_t input_port_0_r();
protected:
// device-level overrides
- virtual void device_start() override;
- virtual void device_reset() override;
+ virtual void device_start() override ATTR_COLD;
+ virtual void device_reset() override ATTR_COLD;
// optional information overrides
- virtual void device_add_mconfig(machine_config &config) override;
- virtual const tiny_rom_entry *device_rom_region() const override;
+ virtual void device_add_mconfig(machine_config &config) override ATTR_COLD;
+ virtual const tiny_rom_entry *device_rom_region() const override ATTR_COLD;
+
+ void io_isa_map(address_map &map) ATTR_COLD;
private:
- ati_vga_device *m_vga;
- mach8_device *m_8514;
+ required_device<ati_vga_device> m_vga;
+ required_device<mach8_device> m_8514;
};
class isa16_vga_gfxultrapro_device :
@@ -54,19 +57,21 @@ public:
// construction/destruction
isa16_vga_gfxultrapro_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
- DECLARE_READ8_MEMBER(input_port_0_r);
+ uint8_t input_port_0_r();
protected:
// device-level overrides
- virtual void device_start() override;
- virtual void device_reset() override;
+ virtual void device_start() override ATTR_COLD;
+ virtual void device_reset() override ATTR_COLD;
// optional information overrides
- virtual void device_add_mconfig(machine_config &config) override;
- virtual const tiny_rom_entry *device_rom_region() const override;
+ virtual void device_add_mconfig(machine_config &config) override ATTR_COLD;
+ virtual const tiny_rom_entry *device_rom_region() const override ATTR_COLD;
+
+ void io_isa_map(address_map &map) ATTR_COLD;
- private:
- mach32_device *m_vga;
+private:
+ required_device<mach32_device> m_vga;
};
class isa16_vga_mach64_device :
@@ -77,19 +82,20 @@ public:
// construction/destruction
isa16_vga_mach64_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
- DECLARE_READ8_MEMBER(input_port_0_r);
+ uint8_t input_port_0_r();
protected:
// device-level overrides
- virtual void device_start() override;
- virtual void device_reset() override;
+ virtual void device_start() override ATTR_COLD;
+ virtual void device_reset() override ATTR_COLD;
// optional information overrides
- virtual void device_add_mconfig(machine_config &config) override;
- virtual const tiny_rom_entry *device_rom_region() const override;
+ virtual void device_add_mconfig(machine_config &config) override ATTR_COLD;
+ virtual const tiny_rom_entry *device_rom_region() const override ATTR_COLD;
+ void io_isa_map(address_map &map) ATTR_COLD;
private:
- mach64_device *m_vga;
+ required_device<mach64_device> m_vga;
};
diff --git a/src/devices/bus/isa/wd1002a_wx1.h b/src/devices/bus/isa/wd1002a_wx1.h
index 7a66db54dd5..168152c6039 100644
--- a/src/devices/bus/isa/wd1002a_wx1.h
+++ b/src/devices/bus/isa/wd1002a_wx1.h
@@ -29,12 +29,12 @@ public:
isa8_wd1002a_wx1_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 const tiny_rom_entry *device_rom_region() const override ATTR_COLD;
protected:
// device-level overrides
- virtual void device_start() override;
- virtual void device_reset() override;
+ virtual void device_start() override ATTR_COLD;
+ virtual void device_reset() override ATTR_COLD;
};
diff --git a/src/devices/bus/isa/wd1007a.h b/src/devices/bus/isa/wd1007a.h
index 1a761ecb66d..f9c3b963d1a 100644
--- a/src/devices/bus/isa/wd1007a.h
+++ b/src/devices/bus/isa/wd1007a.h
@@ -30,9 +30,9 @@ public:
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;
+ virtual void device_start() override ATTR_COLD;
+ virtual void device_add_mconfig(machine_config &config) override ATTR_COLD;
+ virtual const tiny_rom_entry *device_rom_region() const override ATTR_COLD;
};
diff --git a/src/devices/bus/isa/wdxt_gen.cpp b/src/devices/bus/isa/wdxt_gen.cpp
index 57dec00af89..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)
{
@@ -118,17 +118,17 @@ WRITE_LINE_MEMBER( wdxt_gen_device::mr_w )
}
}
-READ8_MEMBER( wdxt_gen_device::rd322_r )
+uint8_t wdxt_gen_device::rd322_r()
{
return 0xff;
}
-READ8_MEMBER( wdxt_gen_device::ram_r )
+uint8_t wdxt_gen_device::ram_r(offs_t offset)
{
return m_ram[offset];
}
-WRITE8_MEMBER( wdxt_gen_device::ram_w )
+void wdxt_gen_device::ram_w(offs_t offset, uint8_t data)
{
m_ram[offset] = data;
}
@@ -199,8 +199,8 @@ wdxt_gen_device::wdxt_gen_device(const machine_config &mconfig, const char *tag,
void wdxt_gen_device::device_start()
{
set_isa_device();
- m_isa->install_rom(this, 0xc8000, 0xc9fff, "hdc", "hdc");
- m_isa->install_device(0x0320, 0x0323, READ8_DEVICE_DELEGATE(m_host, wd11c00_17_device, io_r), WRITE8_DEVICE_DELEGATE(m_host, wd11c00_17_device, io_w));
+ m_isa->install_rom(this, 0xc8000, 0xc9fff, "hdc");
+ m_isa->install_device(0x0320, 0x0323, read8sm_delegate(*m_host, FUNC(wd11c00_17_device::io_r)), write8sm_delegate(*m_host, FUNC(wd11c00_17_device::io_w)));
m_isa->set_dma_channel(3, this, false);
}
@@ -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
}
@@ -260,7 +260,7 @@ READ_LINE_MEMBER( wdxt_gen_device::wd1015_t1_r )
// wd1015_p1_r -
//-------------------------------------------------
-READ8_MEMBER( wdxt_gen_device::wd1015_p1_r )
+uint8_t wdxt_gen_device::wd1015_p1_r()
{
/*
@@ -289,7 +289,7 @@ READ8_MEMBER( wdxt_gen_device::wd1015_p1_r )
// wd1015_p1_w -
//-------------------------------------------------
-WRITE8_MEMBER( wdxt_gen_device::wd1015_p1_w )
+void wdxt_gen_device::wd1015_p1_w(uint8_t data)
{
/*
@@ -316,7 +316,7 @@ WRITE8_MEMBER( wdxt_gen_device::wd1015_p1_w )
// wd1015_p2_r -
//-------------------------------------------------
-READ8_MEMBER( wdxt_gen_device::wd1015_p2_r )
+uint8_t wdxt_gen_device::wd1015_p2_r()
{
/*
@@ -347,7 +347,7 @@ READ8_MEMBER( wdxt_gen_device::wd1015_p2_r )
// wd1015_p2_w -
//-------------------------------------------------
-WRITE8_MEMBER( wdxt_gen_device::wd1015_p2_w )
+void wdxt_gen_device::wd1015_p2_w(uint8_t data)
{
/*
diff --git a/src/devices/bus/isa/wdxt_gen.h b/src/devices/bus/isa/wdxt_gen.h
index d909b7bd155..2c2f2ed24a2 100644
--- a/src/devices/bus/isa/wdxt_gen.h
+++ b/src/devices/bus/isa/wdxt_gen.h
@@ -13,8 +13,8 @@
**********************************************************************/
-#ifndef MAME_BUS_ISA8_WDXT_GEN_H
-#define MAME_BUS_ISA8_WDXT_GEN_H
+#ifndef MAME_BUS_ISA_WDXT_GEN_H
+#define MAME_BUS_ISA_WDXT_GEN_H
#pragma once
@@ -42,12 +42,12 @@ public:
protected:
// device-level overrides
- virtual void device_start() override;
- virtual void device_reset() override;
+ virtual void device_start() override ATTR_COLD;
+ virtual void device_reset() override ATTR_COLD;
// optional information overrides
- virtual void device_add_mconfig(machine_config &config) override;
- virtual const tiny_rom_entry *device_rom_region() const override;
+ virtual void device_add_mconfig(machine_config &config) override ATTR_COLD;
+ virtual const tiny_rom_entry *device_rom_region() const override ATTR_COLD;
// device_isa8_card_interface
virtual uint8_t dack_r(int line) override;
@@ -55,19 +55,19 @@ 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 );
- DECLARE_READ8_MEMBER( rd322_r );
- DECLARE_READ8_MEMBER( ram_r );
- DECLARE_WRITE8_MEMBER( ram_w );
- DECLARE_READ_LINE_MEMBER( wd1015_t1_r );
- DECLARE_READ8_MEMBER( wd1015_p1_r );
- DECLARE_WRITE8_MEMBER( wd1015_p1_w );
- DECLARE_READ8_MEMBER( wd1015_p2_r );
- DECLARE_WRITE8_MEMBER( wd1015_p2_w );
-
- void wd1015_io(address_map &map);
+ 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);
+ int wd1015_t1_r();
+ uint8_t wd1015_p1_r();
+ void wd1015_p1_w(uint8_t data);
+ uint8_t wd1015_p2_r();
+ void wd1015_p2_w(uint8_t data);
+
+ void wd1015_io(address_map &map) ATTR_COLD;
required_device<cpu_device> m_maincpu;
required_device<wd11c00_17_device> m_host;
@@ -82,4 +82,4 @@ private:
// device type definition
DECLARE_DEVICE_TYPE(ISA8_WDXT_GEN, wdxt_gen_device)
-#endif // MAME_BUS_ISA8_WDXT_GEN_H
+#endif // MAME_BUS_ISA_WDXT_GEN_H
diff --git a/src/devices/bus/isa/xsu_cards.cpp b/src/devices/bus/isa/xsu_cards.cpp
index 6a1e09bf8f9..3be4e40a67c 100644
--- a/src/devices/bus/isa/xsu_cards.cpp
+++ b/src/devices/bus/isa/xsu_cards.cpp
@@ -65,13 +65,11 @@ void ec184x_isa8_cards(device_slot_interface &device)
{
device.option_add("ec1840.0002", ISA8_EC1840_0002); // MDA with downloadable font
device.option_add("ec1840.0003", ISA8_FDC_XT);
+ device.option_add("ec1840.0004", ISA8_LPT);
device.option_add("ec1841.0002", ISA8_EC1841_0002); // CGA with downloadable font
device.option_add("ec1841.0003", ISA8_EC1841_0003); // FDC + mouse port
- device.option_add("ec1841.0004", ISA8_LPT);
-/*
- device.option_add("ec1841.0004", ISA8_EC1841_0004); // BSC-like serial ports + parallel port
- device.option_add("ec1841.0010", ISA8_EC1841_0010); // 8089-based HDC
-*/
+// device.option_add("ec1840.0004", ISA8_EC1840_0004); // BSC-like serial ports + parallel port
+// device.option_add("ec1841.0010", ISA8_EC1841_0010); // 8089-based HDC
device.option_add("mda", ISA8_MDA);
device.option_add("hdc", ISA8_HDC_EC1841);
device.option_add("pccom", ISA8_COM);
diff --git a/src/devices/bus/isa/xtide.cpp b/src/devices/bus/isa/xtide.cpp
index 1388a7d174b..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
@@ -57,19 +57,19 @@ Device Control (out) 14 7
#include "xtide.h"
-READ8_MEMBER( xtide_device::read )
+uint8_t xtide_device::read(offs_t offset)
{
uint8_t result;
if (offset == 0)
{
- uint16_t data16 = m_ata->read_cs0(offset & 7);
+ uint16_t data16 = m_ata->cs0_r(offset & 7);
result = data16 & 0xff;
m_d8_d15_latch = data16 >> 8;
}
else if (offset < 8)
{
- result = m_ata->read_cs0(offset & 7, 0xff);
+ result = m_ata->cs0_r(offset & 7, 0xff);
}
else if (offset == 8)
{
@@ -77,7 +77,7 @@ READ8_MEMBER( xtide_device::read )
}
else
{
- result = m_ata->read_cs1(offset & 7, 0xff);
+ result = m_ata->cs1_r(offset & 7, 0xff);
}
// logerror("%s xtide_device::read: offset=%d, result=%2X\n",device->machine().describe_context(),offset,result);
@@ -85,7 +85,7 @@ READ8_MEMBER( xtide_device::read )
return result;
}
-WRITE8_MEMBER( xtide_device::write )
+void xtide_device::write(offs_t offset, uint8_t data)
{
// logerror("%s xtide_device::write: offset=%d, data=%2X\n",device->machine().describe_context(),offset,data);
@@ -93,11 +93,11 @@ WRITE8_MEMBER( xtide_device::write )
{
// Data register transfer low byte and latched high
uint16_t data16 = (m_d8_d15_latch << 8) | data;
- m_ata->write_cs0(offset & 7, data16);
+ m_ata->cs0_w(offset & 7, data16);
}
else if (offset < 8)
{
- m_ata->write_cs0(offset & 7, data, 0xff);
+ m_ata->cs0_w(offset & 7, data, 0xff);
}
else if (offset == 8)
{
@@ -105,12 +105,11 @@ WRITE8_MEMBER( xtide_device::write )
}
else
{
- m_ata->write_cs1(offset & 7, data, 0xff);
+ m_ata->cs1_w(offset & 7, data, 0xff);
}
}
-
-WRITE_LINE_MEMBER(xtide_device::ide_interrupt)
+void xtide_device::ide_interrupt(int state)
{
switch (m_irq_number)
{
@@ -176,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)" )
@@ -323,8 +322,8 @@ void xtide_device::device_reset()
int io_address = ((ioport("IO_ADDRESS")->read() & 0x0F) * 0x20) + 0x200;
m_irq_number = (ioport("IRQ")->read() & 0x07);
- m_isa->install_memory(base_address, base_address + 0x1fff, read8_delegate(FUNC(eeprom_parallel_28xx_device::read), &(*m_eeprom)), write8_delegate(FUNC(eeprom_parallel_28xx_device::write), &(*m_eeprom)));
- m_isa->install_device(io_address, io_address + 0xf, read8_delegate(FUNC(xtide_device::read), this), write8_delegate(FUNC(xtide_device::write), this));
+ m_isa->install_memory(base_address, base_address + 0x1fff, read8m_delegate(*m_eeprom, FUNC(eeprom_parallel_28xx_device::read)), write8sm_delegate(*m_eeprom, FUNC(eeprom_parallel_28xx_device::write)));
+ m_isa->install_device(io_address, io_address + 0xf, read8sm_delegate(*this, FUNC(xtide_device::read)), write8sm_delegate(*this, FUNC(xtide_device::write)));
//logerror("xtide_device::device_reset(), bios_base=0x%5X to 0x%5X, I/O=0x%3X, IRQ=%d\n",base_address,base_address + (16*1024) -1 ,io_address,irq);
}
diff --git a/src/devices/bus/isa/xtide.h b/src/devices/bus/isa/xtide.h
index 4402aa991fd..293a3bd4576 100644
--- a/src/devices/bus/isa/xtide.h
+++ b/src/devices/bus/isa/xtide.h
@@ -6,7 +6,7 @@
#pragma once
#include "isa.h"
-#include "machine/ataintf.h"
+#include "bus/ata/ataintf.h"
#include "machine/eeprompar.h"
//**************************************************************************
@@ -19,21 +19,21 @@ public:
// construction/destruction
xtide_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
- DECLARE_READ8_MEMBER(read);
- DECLARE_WRITE8_MEMBER(write);
+ uint8_t read(offs_t offset);
+ void write(offs_t offset, uint8_t data);
protected:
// device-level overrides
- virtual void device_start() override;
- virtual void device_reset() override;
+ virtual void device_start() override ATTR_COLD;
+ virtual void device_reset() override ATTR_COLD;
// optional information 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;
+ virtual void device_add_mconfig(machine_config &config) override ATTR_COLD;
+ virtual ioport_constructor device_input_ports() const override ATTR_COLD;
+ virtual const tiny_rom_entry *device_rom_region() const override ATTR_COLD;
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 fea0e7f59b5..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
@@ -26,22 +28,24 @@ DEFINE_DEVICE_TYPE(COMPIS_FDC, compis_fdc_device, "compis_fdc", "Compis FDC")
//-------------------------------------------------
-// floppy_format_type floppy_formats
+// 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);
}
-FLOPPY_FORMATS_MEMBER( compis_fdc_device::floppy_formats )
- FLOPPY_CPIS_FORMAT
-FLOPPY_FORMATS_END
+void compis_fdc_device::floppy_formats(format_registration &fr)
+{
+ fr.add_mfm_containers();
+ fr.add(FLOPPY_CPIS_FORMAT);
+}
static void compis_floppies(device_slot_interface &device)
{
@@ -59,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);
}
@@ -77,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)
{
}
@@ -169,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 af1d71a3af2..b1899a5b812 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"
@@ -33,11 +32,11 @@ public:
protected:
// device-level overrides
- virtual void device_start() override;
- virtual void device_reset() override;
+ virtual void device_start() override ATTR_COLD;
+ virtual void device_reset() override ATTR_COLD;
// optional information overrides
- virtual void device_add_mconfig(machine_config &config) override;
+ virtual void device_add_mconfig(machine_config &config) override ATTR_COLD;
// device_isbx_card_interface overrides
virtual uint8_t mcs0_r(offs_t offset) override;
@@ -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 );
- DECLARE_FLOPPY_FORMATS( floppy_formats );
+ 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 0a1cff5f235..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,29 +26,21 @@
DEFINE_DEVICE_TYPE(ISBC_218A, isbc_218a_device, "isbc_218a", "ISBX 218a for ISBC")
-
-//-------------------------------------------------
-// floppy_format_type floppy_formats
-//-------------------------------------------------
-
-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);
}
-FLOPPY_FORMATS_MEMBER( isbc_218a_device::floppy_formats )
- FLOPPY_PC_FORMAT
-FLOPPY_FORMATS_END
-
static void isbc_218a_floppies(device_slot_interface &device)
{
device.option_add("8dd", FLOPPY_8_DSDD);
device.option_add("525dd", FLOPPY_525_DD);
+ device.option_add("525qd", FLOPPY_525_QD);
}
@@ -59,7 +53,7 @@ void isbc_218a_device::device_add_mconfig(machine_config &config)
I8272A(config, m_fdc, 8_MHz_XTAL, true);
m_fdc->intrq_wr_callback().set(FUNC(isbc_218a_device::fdc_irq));
m_fdc->drq_wr_callback().set(FUNC(isbc_218a_device::fdc_drq));
- FLOPPY_CONNECTOR(config, m_floppy0, isbc_218a_floppies, "525dd", isbc_218a_device::floppy_formats);
+ FLOPPY_CONNECTOR(config, m_floppy0, isbc_218a_floppies, "525dd", floppy_image_device::default_pc_floppy_formats);
}
diff --git a/src/devices/bus/isbx/isbc_218a.h b/src/devices/bus/isbx/isbc_218a.h
index bdf37c52806..64f16732198 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"
@@ -33,11 +32,11 @@ public:
protected:
// device-level overrides
- virtual void device_start() override;
- virtual void device_reset() override;
+ virtual void device_start() override ATTR_COLD;
+ virtual void device_reset() override ATTR_COLD;
// optional information overrides
- virtual void device_add_mconfig(machine_config &config) override;
+ virtual void device_add_mconfig(machine_config &config) override ATTR_COLD;
// device_isbx_card_interface overrides
virtual uint8_t mcs0_r(offs_t offset) override;
@@ -49,9 +48,9 @@ protected:
virtual void opt0_w(int state) override;
private:
- DECLARE_WRITE_LINE_MEMBER( fdc_irq );
- DECLARE_WRITE_LINE_MEMBER( fdc_drq );
- DECLARE_FLOPPY_FORMATS( floppy_formats );
+ 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;
diff --git a/src/devices/bus/isbx/isbx.cpp b/src/devices/bus/isbx/isbx.cpp
index ae3754e6d62..178f2215ab2 100644
--- a/src/devices/bus/isbx/isbx.cpp
+++ b/src/devices/bus/isbx/isbx.cpp
@@ -27,8 +27,8 @@ DEFINE_DEVICE_TYPE(ISBX_SLOT, isbx_slot_device, "isbx_slot", "iSBX bus slot")
// device_isbx_card_interface - constructor
//-------------------------------------------------
-device_isbx_card_interface::device_isbx_card_interface(const machine_config &mconfig, device_t &device)
- : device_slot_card_interface(mconfig, device)
+device_isbx_card_interface::device_isbx_card_interface(const machine_config &mconfig, device_t &device) :
+ device_interface(device, "isbxbus")
{
m_slot = dynamic_cast<isbx_slot_device *>(device.owner());
}
@@ -40,11 +40,12 @@ device_isbx_card_interface::device_isbx_card_interface(const machine_config &mco
isbx_slot_device::isbx_slot_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) :
device_t(mconfig, ISBX_SLOT, tag, owner, clock),
- device_slot_interface(mconfig, *this),
+ device_single_card_slot_interface<device_isbx_card_interface>(mconfig, *this),
m_write_mintr0(*this),
m_write_mintr1(*this),
m_write_mdrqt(*this),
- m_write_mwait(*this), m_card(nullptr)
+ m_write_mwait(*this),
+ m_card(nullptr)
{
}
@@ -55,13 +56,7 @@ isbx_slot_device::isbx_slot_device(const machine_config &mconfig, const char *ta
void isbx_slot_device::device_start()
{
- m_card = dynamic_cast<device_isbx_card_interface *>(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();
+ m_card = get_card_device();
}
diff --git a/src/devices/bus/isbx/isbx.h b/src/devices/bus/isbx/isbx.h
index 0535e461cd7..769d7bde8b7 100644
--- a/src/devices/bus/isbx/isbx.h
+++ b/src/devices/bus/isbx/isbx.h
@@ -31,8 +31,8 @@
**********************************************************************/
-#ifndef MAME_BUS_ISBX_ISBX_SLOT_H
-#define MAME_BUS_ISBX_ISBX_SLOT_H
+#ifndef MAME_BUS_ISBX_ISBX_H
+#define MAME_BUS_ISBX_ISBX_H
#pragma once
@@ -44,7 +44,7 @@
class isbx_slot_device;
-class device_isbx_card_interface : public device_slot_card_interface
+class device_isbx_card_interface : public device_interface
{
public:
virtual uint8_t mcs0_r(offs_t offset) { return 0xff; }
@@ -70,8 +70,7 @@ protected:
// ======================> isbx_slot_device
-class isbx_slot_device : public device_t,
- public device_slot_interface
+class isbx_slot_device : public device_t, public device_single_card_slot_interface<device_isbx_card_interface>
{
public:
// construction/destruction
@@ -98,24 +97,23 @@ 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
- virtual void device_start() override;
- virtual void device_reset() override { if (m_card) get_card_device()->reset(); }
+ virtual void device_start() override ATTR_COLD;
devcb_write_line m_write_mintr0;
devcb_write_line m_write_mintr1;
@@ -133,4 +131,4 @@ DECLARE_DEVICE_TYPE(ISBX_SLOT, isbx_slot_device)
void isbx_cards(device_slot_interface &device);
-#endif // MAME_BUS_ISBX_ISBX_SLOT_H
+#endif // MAME_BUS_ISBX_ISBX_H
diff --git a/src/devices/bus/jakks_gamekey/rom.cpp b/src/devices/bus/jakks_gamekey/rom.cpp
index 0ca9b7024d9..4492d62bddb 100644
--- a/src/devices/bus/jakks_gamekey/rom.cpp
+++ b/src/devices/bus/jakks_gamekey/rom.cpp
@@ -45,34 +45,34 @@ jakks_gamekey_rom_i2c_24lc04_device::jakks_gamekey_rom_i2c_24lc04_device(const m
// plain
-READ16_MEMBER(jakks_gamekey_rom_plain_device::read_cart)
+uint16_t jakks_gamekey_rom_plain_device::read_cart(offs_t offset)
{
- return read_rom(space, offset, mem_mask);
+ return read_rom(offset);
}
-READ16_MEMBER(jakks_gamekey_rom_plain_device::read_rom)
+uint16_t jakks_gamekey_rom_plain_device::read_rom(offs_t offset)
{
return m_rom[offset & (m_rom_size-1)];
}
-WRITE16_MEMBER(jakks_gamekey_rom_plain_device::write_cart)
+void jakks_gamekey_rom_plain_device::write_cart(offs_t offset, uint16_t data)
{
- write_rom(space, offset, data, mem_mask);
+ write_rom(offset, data);
}
-WRITE16_MEMBER(jakks_gamekey_rom_plain_device::write_rom)
+void jakks_gamekey_rom_plain_device::write_rom(offs_t offset, uint16_t data)
{
- logerror("jakks_gamekey_rom_plain_device::write_rom %08x %02x\n", offset, data);
+ logerror("jakks_gamekey_rom_plain_device::write_rom %08x %04x\n", offset, data);
}
// i2c base
-WRITE16_MEMBER(jakks_gamekey_rom_i2c_base_device::write_rom)
+void jakks_gamekey_rom_i2c_base_device::write_rom(offs_t offset, uint16_t data)
{
- logerror("jakks_gamekey_rom_i2c_base_device::write_rom %08x %02x\n", offset, data);
+ logerror("jakks_gamekey_rom_i2c_base_device::write_rom %08x %04x\n", offset, data);
}
-READ16_MEMBER(jakks_gamekey_rom_i2c_base_device::read_rom)
+uint16_t jakks_gamekey_rom_i2c_base_device::read_rom(offs_t offset)
{
return m_rom[offset & (m_rom_size - 1)];
}
@@ -84,7 +84,7 @@ uint8_t jakks_gamekey_rom_i2c_base_device::read_cart_seeprom(void)
return m_i2cmem->read_sda();
}
-WRITE16_MEMBER(jakks_gamekey_rom_i2c_base_device::write_cart_seeprom)
+void jakks_gamekey_rom_i2c_base_device::write_cart_seeprom(offs_t offset, uint16_t data, uint16_t mem_mask)
{
if (BIT(mem_mask, 1))
m_i2cmem->write_scl(BIT(data, 1));
@@ -96,7 +96,7 @@ WRITE16_MEMBER(jakks_gamekey_rom_i2c_base_device::write_cart_seeprom)
void jakks_gamekey_rom_i2c_24lc04_device::device_add_mconfig(machine_config &config)
{
- I2CMEM(config, "i2cmem", 0)/*.set_page_size(16)*/.set_data_size(0x200); // 24LC04
+ I2C_24C04(config, "i2cmem", 0); // 24LC04
}
diff --git a/src/devices/bus/jakks_gamekey/rom.h b/src/devices/bus/jakks_gamekey/rom.h
index 7f85e9f21fb..fe43b90cdad 100644
--- a/src/devices/bus/jakks_gamekey/rom.h
+++ b/src/devices/bus/jakks_gamekey/rom.h
@@ -18,14 +18,14 @@ public:
jakks_gamekey_rom_plain_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
// reading and writing
- virtual DECLARE_READ16_MEMBER(read_cart) override;
- virtual DECLARE_WRITE16_MEMBER(write_cart) override;
+ virtual uint16_t read_cart(offs_t offset) override;
+ virtual void write_cart(offs_t offset, uint16_t data) override;
- virtual uint8_t read_cart_seeprom(void) override { return 1; };
- virtual DECLARE_WRITE16_MEMBER(write_cart_seeprom) override { };
+ virtual uint8_t read_cart_seeprom(void) override { return 1; }
+ virtual void write_cart_seeprom(offs_t offset, uint16_t data, uint16_t mem_mask = ~0) override { }
- virtual READ16_MEMBER(read_rom);
- virtual WRITE16_MEMBER(write_rom);
+ virtual uint16_t read_rom(offs_t offset);
+ virtual void write_rom(offs_t offset, uint16_t data);
protected:
jakks_gamekey_rom_plain_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock);
@@ -47,13 +47,13 @@ protected:
jakks_gamekey_rom_i2c_base_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock);
// reading and writing
- virtual READ16_MEMBER(read_rom) override;
- virtual WRITE16_MEMBER(write_rom) override;
+ virtual uint16_t read_rom(offs_t offset) override;
+ virtual void write_rom(offs_t offset, uint16_t data) override;
optional_device<i2cmem_device> m_i2cmem;
virtual uint8_t read_cart_seeprom(void) override;
- virtual DECLARE_WRITE16_MEMBER(write_cart_seeprom) override;
+ virtual void write_cart_seeprom(offs_t offset, uint16_t data, uint16_t mem_mask = ~0) override;
};
@@ -66,7 +66,7 @@ public:
jakks_gamekey_rom_i2c_24lc04_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_add_mconfig(machine_config &config) override ATTR_COLD;
};
// device type definition
diff --git a/src/devices/bus/jakks_gamekey/slot.cpp b/src/devices/bus/jakks_gamekey/slot.cpp
index 6a5196875b1..7da3904f32c 100644
--- a/src/devices/bus/jakks_gamekey/slot.cpp
+++ b/src/devices/bus/jakks_gamekey/slot.cpp
@@ -18,10 +18,10 @@ DEFINE_DEVICE_TYPE(JAKKS_GAMEKEY_SLOT, jakks_gamekey_slot_device, "jakks_gamekey
// device_jakks_gamekey_interface - constructor
//-------------------------------------------------
-device_jakks_gamekey_interface::device_jakks_gamekey_interface(const machine_config &mconfig, device_t &device)
- : device_slot_card_interface(mconfig, device),
- m_rom(nullptr),
- m_rom_size(0)
+device_jakks_gamekey_interface::device_jakks_gamekey_interface(const machine_config &mconfig, device_t &device) :
+ device_interface(device, "jakksgamekey"),
+ m_rom(nullptr),
+ m_rom_size(0)
{
}
@@ -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;
}
}
@@ -56,8 +56,8 @@ void device_jakks_gamekey_interface::rom_alloc(uint32_t size, const char *tag)
//-------------------------------------------------
jakks_gamekey_slot_device::jakks_gamekey_slot_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) :
device_t(mconfig, JAKKS_GAMEKEY_SLOT, tag, owner, clock),
- device_image_interface(mconfig, *this),
- device_slot_interface(mconfig, *this),
+ device_cartrom_image_interface(mconfig, *this),
+ device_single_card_slot_interface<device_jakks_gamekey_interface>(mconfig, *this),
m_type(JAKKS_GAMEKEY_PLAIN),
m_cart(nullptr)
{
@@ -77,7 +77,7 @@ jakks_gamekey_slot_device::~jakks_gamekey_slot_device()
void jakks_gamekey_slot_device::device_start()
{
- m_cart = dynamic_cast<device_jakks_gamekey_interface *>(get_card_device());
+ m_cart = get_card_device();
}
//-------------------------------------------------
@@ -102,7 +102,7 @@ static int jakks_gamekey_get_pcb_id(const char *slot)
{
for (auto & elem : slot_list)
{
- if (!core_stricmp(elem.slot_option, slot))
+ if (!strcmp(elem.slot_option, slot))
return elem.pcb_id;
}
@@ -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());
}
@@ -182,17 +179,16 @@ std::string jakks_gamekey_slot_device::get_default_card_software(get_default_car
{
if (hook.image_file())
{
- const char *slot_string;
- uint32_t len = hook.image_file()->size();
+ uint64_t len;
+ hook.image_file()->length(len); // FIXME: check error return, guard against excessively large files
std::vector<uint8_t> rom(len);
- int type;
- hook.image_file()->read(&rom[0], len);
+ read(*hook.image_file(), &rom[0], len); // FIXME: check error return or read returning short
- type = get_cart_type(&rom[0], len);
- slot_string = jakks_gamekey_get_slot(type);
+ int const type = get_cart_type(&rom[0], len);
+ char const *const slot_string = jakks_gamekey_get_slot(type);
- printf("type: %s\n", slot_string);
+ //printf("type: %s\n", slot_string);
return std::string(slot_string);
}
@@ -204,18 +200,18 @@ std::string jakks_gamekey_slot_device::get_default_card_software(get_default_car
read
-------------------------------------------------*/
-READ16_MEMBER(jakks_gamekey_slot_device::read_cart)
+uint16_t jakks_gamekey_slot_device::read_cart(offs_t offset)
{
- return m_cart->read_cart(space, offset);
+ return m_cart->read_cart(offset);
}
/*-------------------------------------------------
write
-------------------------------------------------*/
-WRITE16_MEMBER(jakks_gamekey_slot_device::write_cart)
+void jakks_gamekey_slot_device::write_cart(offs_t offset, uint16_t data)
{
- m_cart->write_cart(space, offset, data);
+ m_cart->write_cart(offset, data);
}
/*-------------------------------------------------
@@ -231,7 +227,7 @@ uint8_t jakks_gamekey_slot_device::read_cart_seeprom(void)
write seeprom
-------------------------------------------------*/
-WRITE16_MEMBER(jakks_gamekey_slot_device::write_cart_seeprom)
+void jakks_gamekey_slot_device::write_cart_seeprom(offs_t offset, uint16_t data, uint16_t mem_mask)
{
- m_cart->write_cart_seeprom(space, offset, data);
+ m_cart->write_cart_seeprom(offset, data);
}
diff --git a/src/devices/bus/jakks_gamekey/slot.h b/src/devices/bus/jakks_gamekey/slot.h
index 8fd0961aad8..5dc328ce853 100644
--- a/src/devices/bus/jakks_gamekey/slot.h
+++ b/src/devices/bus/jakks_gamekey/slot.h
@@ -5,7 +5,7 @@
#pragma once
-#include "softlist_dev.h"
+#include "imagedev/cartrom.h"
/***************************************************************************
TYPE DEFINITIONS
@@ -21,18 +21,18 @@ enum
// ======================> device_jakks_gamekey_interface
-class device_jakks_gamekey_interface : public device_slot_card_interface
+class device_jakks_gamekey_interface : public device_interface
{
public:
// construction/destruction
virtual ~device_jakks_gamekey_interface();
// reading and writing
- virtual DECLARE_READ16_MEMBER(read_cart) { return 0xffff; }
- virtual DECLARE_WRITE16_MEMBER(write_cart) { }
+ virtual uint16_t read_cart(offs_t offset) { return 0xffff; }
+ virtual void write_cart(offs_t offset, uint16_t data) { }
virtual uint8_t read_cart_seeprom(void) { return 1; }
- virtual DECLARE_WRITE16_MEMBER(write_cart_seeprom) { }
+ virtual void write_cart_seeprom(offs_t offset, uint16_t data, uint16_t mem_mask = ~0) { }
void rom_alloc(uint32_t size, const char *tag);
uint8_t* get_rom_base() { return m_rom; }
@@ -49,8 +49,8 @@ protected:
// ======================> jakks_gamekey_slot_device
class jakks_gamekey_slot_device : public device_t,
- public device_image_interface,
- public device_slot_interface
+ public device_cartrom_image_interface,
+ public device_single_card_slot_interface<device_jakks_gamekey_interface>
{
public:
// construction/destruction
@@ -68,41 +68,35 @@ public:
virtual ~jakks_gamekey_slot_device();
- // image-level overrides
- virtual image_init_result call_load() override;
- virtual void call_unload() override {}
- virtual const software_list_loader &get_software_list_loader() const override { return rom_software_list_loader::instance(); }
+ // device_image_interface implementation
+ virtual std::pair<std::error_condition, std::string> call_load() override;
+ virtual void call_unload() override { }
- int get_type() { return m_type; }
- static int get_cart_type(const uint8_t *ROM, uint32_t len);
-
- virtual iodevice_t image_type() const override { return IO_CARTSLOT; }
- virtual bool is_readable() const override { return 1; }
- virtual bool is_writeable() const override { return 0; }
- virtual bool is_creatable() const override { return 0; }
- virtual bool must_be_loaded() const override { return 0; }
- virtual bool is_reset_on_load() const override { return 1; }
- virtual const char *image_interface() const override { return "jakks_gamekey"; }
- virtual const char *file_extensions() const override { return "bin,u1"; }
+ 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; }
+ static int get_cart_type(const uint8_t *ROM, uint32_t len);
+
// reading and writing
- virtual DECLARE_READ16_MEMBER(read_cart);
- virtual DECLARE_WRITE16_MEMBER(write_cart);
+ uint16_t read_cart(offs_t offset);
+ void write_cart(offs_t offset, uint16_t data);
virtual uint8_t read_cart_seeprom(void);
- virtual DECLARE_WRITE16_MEMBER(write_cart_seeprom);
+ virtual void write_cart_seeprom(offs_t offset, uint16_t data, uint16_t mem_mask = ~0);
bool has_cart() { return m_cart ? true : false; }
protected:
- // device-level overrides
- virtual void device_start() override;
+ // device_t implementation
+ virtual void device_start() override ATTR_COLD;
int m_type;
- device_jakks_gamekey_interface* m_cart;
+ device_jakks_gamekey_interface *m_cart;
};
// device type definition
diff --git a/src/devices/bus/jvs/cyberlead.cpp b/src/devices/bus/jvs/cyberlead.cpp
new file mode 100644
index 00000000000..5598da24cd9
--- /dev/null
+++ b/src/devices/bus/jvs/cyberlead.cpp
@@ -0,0 +1,486 @@
+// license:BSD-3-Clause
+// copyright-holders:smf
+/*
+ Namco Cyber Lead cabinet PCB
+
+ CL1 I/OB I/O LED (I/O) PCB 8699014200
+ CL1 LEDA I/O LED (LED) PCB 8699014500
+ Both boards are required and use the same PCB, populated differently
+ |------------------------------------------------------------------------------------------------|
+ | J3 J4 J6 |
+ | J2 J5 |
+ | PROG I/OLEDM1 |
+ | AT29C020 SED1351F B A |
+ | C77 14.764Mhz PST592F J7 |
+ | HC257 HC257 HC257 N341256 |
+ | J1 |
+ | SW1 SW2 SW3 SW4 SW5 9264LF10L 12MHZ |
+ | 1P 2P |
+ | J13 J12 J11 J10 |
+ |------------------------------------------------------------------------------------------------|
+
+Notes:
+ J1 - 6 pin connector (I/O Only)
+ J2 - 2 pin power connector
+ J3 - 10 pin connector (I/O Only)
+ J4 - 12 pin connector (I/O Only)
+ J5 PROG - ?
+ J6 - 6 pin Mini DIN connector
+ J7 - 20 pin connector (LED Only)
+ J10 - 2 pin connector (I/O Only)
+ J11 - 12 pin connector (I/O Only)
+ J12 - 12 pin connector (I/O Only)
+ J13 - 2 pin connector (I/O Only)
+ A - USB A connector (I/O Only)
+ B - USB B connector (I/O Only)
+ HC257 - Quad 2-input multiplexer; 3-state (I/O Only) @IC1,IC2,IC3
+ N341256 - NEC N341256 32k x8 SRAM @IC4
+ AT29C020 - Atmel AT29C020 256k x8 FlashROM @IC5
+ C77 - Namco C77 H8 MCU @IC6
+ 14.76 - X1 14.7SC6M
+ SW1 - A push button
+ SW2 - B push button
+ SW3 - DSW4
+ SW4 - Service push button
+ SW5 - Test push button
+ SED1351F - EPSON SED1351F LCD controller (LED Only) @IC7
+ 9264LF10L - 8192x8 Bit Static RAM (LED Only) @IC8
+ I/OLEDM1 - Altera EPM7064 @IC9
+ PST592F - System reset @IC10
+ 12MHz - OSC1 (LED Only)
+ ADM485JR - Analog Devices ADM485 low power EIA RS-485 transceiver (I/O Only) @IC11
+
+Known games with LED data
+
+ Aqua Rush
+ Attack Pla Rail (*)
+ Ehrgeiz (*)
+ Fighting Layer (Japan) (*)
+ Libero Grande
+ Mr. Driller
+ Soul Calibur
+ Super World Stadium '98
+ Super World Stadium '99
+ Tekken 3 (* up to rev D)
+ Tekken Tag Tournament
+
+ (*) The only games that work with the unpatched CL1 I/OB Ver 1.03 rom
+*/
+
+#include "emu.h"
+#include "cyberlead.h"
+#include "cyberlead.lh"
+
+namco_cyberlead_device::namco_cyberlead_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) :
+ namco_cyberlead_device(mconfig, NAMCO_CYBERLEAD, tag, owner, clock)
+{
+}
+
+namco_cyberlead_device::namco_cyberlead_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_jvs_interface(mconfig, *this),
+ m_iocpu(*this, "iocpu"),
+ m_dsw(*this, "DSW"),
+ m_port7(*this, "PORT7"),
+ m_rs232(*this, "rs232")
+{
+}
+
+void namco_cyberlead_device::device_add_mconfig(machine_config &config)
+{
+ NAMCO_C77(config, m_iocpu, 14.7456_MHz_XTAL);
+ m_iocpu->set_addrmap(AS_PROGRAM, &namco_cyberlead_device::iocpu_program_map);
+ m_iocpu->read_port4().set(FUNC(namco_cyberlead_device::iocpu_port_4_r));
+ m_iocpu->write_port4().set(FUNC(namco_cyberlead_device::iocpu_port_4_w));
+ m_iocpu->read_port5().set(FUNC(namco_cyberlead_device::iocpu_port_5_r));
+ m_iocpu->write_port5().set(FUNC(namco_cyberlead_device::iocpu_port_5_w));
+ m_iocpu->read_port6().set(FUNC(namco_cyberlead_device::iocpu_port_6_r));
+ m_iocpu->write_port6().set(FUNC(namco_cyberlead_device::iocpu_port_6_w));
+ m_iocpu->read_port7().set(FUNC(namco_cyberlead_device::iocpu_port_7_r));
+
+ m_iocpu->write_sci_tx<0>().set(FUNC(namco_cyberlead_device::txd));
+
+ config.set_maximum_quantum(attotime::from_hz(2 * 115200));
+
+ RS232_PORT(config, m_rs232);
+ m_rs232->option_add("namco_cyberlead_led", NAMCO_CYBERLEAD_LED);
+ m_rs232->set_option_machine_config("namco_cyberlead_led", [&config](device_t *device)
+ {
+ if (!(config.gamedrv().flags & machine_flags::SWAP_XY))
+ config.set_default_layout(layout_cyberlead);
+ });
+
+ m_rs232->set_default_option("namco_cyberlead_led");
+ m_rs232->rxd_handler().set(m_iocpu, FUNC(h8_device::sci_rx_w<1>));
+ m_iocpu->write_sci_tx<1>().set(m_rs232, FUNC(rs232_port_device::write_txd));
+
+ add_jvs_port(config);
+}
+
+namespace {
+
+static INPUT_PORTS_START(cyberleadjvs)
+ PORT_START("DSW")
+ PORT_DIPUNKNOWN_DIPLOC(0x08, IP_ACTIVE_LOW, "SW3:1")
+ PORT_DIPUNKNOWN_DIPLOC(0x04, IP_ACTIVE_LOW, "SW3:2")
+ PORT_DIPUNKNOWN_DIPLOC(0x02, IP_ACTIVE_LOW, "SW3:3")
+ PORT_DIPUNUSED_DIPLOC(0x01, IP_ACTIVE_LOW, "SW3:4")
+
+ PORT_START("PORT7")
+ PORT_BIT(0x01, IP_ACTIVE_LOW, IPT_KEYPAD) PORT_NAME("LED Mode B") PORT_CODE(KEYCODE_B)
+ PORT_BIT(0x02, IP_ACTIVE_LOW, IPT_KEYPAD) PORT_NAME("LED Mode A") PORT_CODE(KEYCODE_A)
+ PORT_BIT(0x8c, IP_ACTIVE_LOW, IPT_UNKNOWN) // inputs?
+ PORT_BIT(0x70, IP_ACTIVE_LOW, IPT_UNKNOWN) // outputs?
+INPUT_PORTS_END
+
+static INPUT_PORTS_START(cyberleadjvs_default)
+ PORT_INCLUDE(cyberleadjvs)
+
+ PORT_START("SYSTEM")
+ PORT_SERVICE_NO_TOGGLE(0x80, IP_ACTIVE_HIGH)
+
+ PORT_START("PLAYER1")
+ PORT_BIT(0x00000080, IP_ACTIVE_HIGH, IPT_START)
+ PORT_BIT(0x00000040, IP_ACTIVE_HIGH, IPT_SERVICE1)
+ PORT_BIT(0x00000020, IP_ACTIVE_HIGH, IPT_JOYSTICK_UP)
+ PORT_BIT(0x00000010, IP_ACTIVE_HIGH, IPT_JOYSTICK_DOWN)
+ PORT_BIT(0x00000008, IP_ACTIVE_HIGH, IPT_JOYSTICK_LEFT)
+ PORT_BIT(0x00000004, IP_ACTIVE_HIGH, IPT_JOYSTICK_RIGHT)
+ PORT_BIT(0x00000002, IP_ACTIVE_HIGH, IPT_BUTTON1)
+ PORT_BIT(0x00000001, IP_ACTIVE_HIGH, IPT_BUTTON2)
+ PORT_BIT(0x00008000, IP_ACTIVE_HIGH, IPT_BUTTON3)
+ PORT_BIT(0x00004000, IP_ACTIVE_HIGH, IPT_BUTTON4)
+ PORT_BIT(0x00002000, IP_ACTIVE_HIGH, IPT_BUTTON5)
+ PORT_BIT(0x00001000, IP_ACTIVE_HIGH, IPT_BUTTON6)
+
+ PORT_START("PLAYER2")
+ PORT_BIT(0x00000080, IP_ACTIVE_HIGH, IPT_START) PORT_PLAYER(2)
+ PORT_BIT(0x00000020, IP_ACTIVE_HIGH, IPT_JOYSTICK_UP) PORT_PLAYER(2)
+ PORT_BIT(0x00000010, IP_ACTIVE_HIGH, IPT_JOYSTICK_DOWN) PORT_PLAYER(2)
+ PORT_BIT(0x00000008, IP_ACTIVE_HIGH, IPT_JOYSTICK_LEFT) PORT_PLAYER(2)
+ PORT_BIT(0x00000004, IP_ACTIVE_HIGH, IPT_JOYSTICK_RIGHT) PORT_PLAYER(2)
+ PORT_BIT(0x00000002, IP_ACTIVE_HIGH, IPT_BUTTON1) PORT_PLAYER(2)
+ PORT_BIT(0x00000001, IP_ACTIVE_HIGH, IPT_BUTTON2) PORT_PLAYER(2)
+ PORT_BIT(0x00008000, IP_ACTIVE_HIGH, IPT_BUTTON3) PORT_PLAYER(2)
+ PORT_BIT(0x00004000, IP_ACTIVE_HIGH, IPT_BUTTON4) PORT_PLAYER(2)
+ PORT_BIT(0x00002000, IP_ACTIVE_HIGH, IPT_BUTTON5) PORT_PLAYER(2)
+ PORT_BIT(0x00001000, IP_ACTIVE_HIGH, IPT_BUTTON6) PORT_PLAYER(2)
+
+ PORT_START("COIN1")
+ PORT_BIT(0x01, IP_ACTIVE_HIGH, IPT_COIN1)
+
+ PORT_START("COIN2")
+ PORT_BIT(0x01, IP_ACTIVE_HIGH, IPT_COIN2)
+INPUT_PORTS_END
+
+} // anonymous namespace
+
+ioport_constructor namco_cyberlead_device::device_input_ports() const
+{
+ return m_default_inputs ? INPUT_PORTS_NAME(cyberleadjvs_default) : INPUT_PORTS_NAME(cyberleadjvs);
+}
+
+namespace {
+
+ROM_START( cyberleadjvs )
+ ROM_REGION( 0x040000, "iocpu", 0 )
+ ROM_LOAD( "cl1-iob.ic5", 0x000000, 0x040000, CRC(abb90360) SHA1(d938b1e1ae596d0ab1007352f61b0b800363c762) )
+ ROM_FILL( 0xa6b, 0x1, 0x12 ) // HACK to improve compatibility, until newer revision is dumped
+ROM_END
+
+} // anonymous namespace
+
+const tiny_rom_entry *namco_cyberlead_device::device_rom_region() const
+{
+ return ROM_NAME(cyberleadjvs);
+}
+
+void namco_cyberlead_device::device_start()
+{
+}
+
+void namco_cyberlead_device::rxd(int state)
+{
+ m_iocpu->sci_rx_w<0>(state);
+}
+
+void namco_cyberlead_device::iocpu_program_map(address_map &map)
+{
+ map(0x0000, 0x3fff).rom().region("iocpu", 0);
+ map(0xc000, 0xfb7f).ram();
+ map(0xff80, 0xff83).r(FUNC(namco_cyberlead_device::iocpu_in_r));
+}
+
+uint8_t namco_cyberlead_device::iocpu_in_r(offs_t offset)
+{
+ if (offset == 0)
+ {
+ const auto p1 = player_r(0, 0x80bf);
+ return ~bitswap<8>(p1, 15, 0, 1, 7, 2, 3, 4, 5); // BUTTON3, BUTTON2, BUTTON1, START, RIGHT, LEFT, DOWN, UP
+ }
+ else if (offset == 1)
+ {
+ const auto p2 = player_r(1, 0x80bf);
+ return ~bitswap<8>(p2, 15, 0, 1, 7, 2, 3, 4, 5); // BUTTON3, BUTTON2, BUTTON1, START, RIGHT, LEFT, DOWN, UP
+ }
+ else if (offset == 2)
+ {
+ const auto p1 = player_r(0, 0x7000);
+ const auto c1 = coin_r(0, 0x01);
+ return ~((BIT(c1, 0) << 3) | bitswap<3>(p1, 12, 13, 14)); // COIN, BUTTON6, BUTTON5, BUTTON4
+ }
+ else if (offset == 3)
+ {
+ const auto p2 = player_r(1, 0x7000);
+ const auto c2 = coin_r(1, 0x01);
+ return ~((BIT(c2, 0) << 3) | bitswap<3>(p2, 12, 13, 14)); // COIN, BUTTON6, BUTTON5, BUTTON4
+ }
+
+ return 0xff;
+}
+
+uint8_t namco_cyberlead_device::iocpu_port_4_r()
+{
+ return (1 << 7) | // unknown input
+ 0x63 | // unknown outputs
+ ((m_jvs_sense != jvs_port_device::sense::None) << 4) | ((m_jvs_sense != jvs_port_device::sense::Initialized) << 3) |
+ (1 << 2);// sense output
+}
+
+void namco_cyberlead_device::iocpu_port_4_w(uint8_t data)
+{
+ sense(BIT(data, 2) ? jvs_port_device::sense::Initialized : jvs_port_device::sense::Uninitialized);
+}
+
+uint8_t namco_cyberlead_device::iocpu_port_5_r()
+{
+ return 0xe9 | // unknown outputs
+ (1 << 4) | // unknown input
+ (1 << 2) | // rts
+ (1 << 1); // unknown input
+}
+
+void namco_cyberlead_device::iocpu_port_5_w(uint8_t data)
+{
+ rts(BIT(data, 2));
+}
+
+uint8_t namco_cyberlead_device::iocpu_port_6_r()
+{
+ const auto system = system_r(0x80);
+ const auto p1 = player_r(0, 0x40);
+
+ return (1 << 7) | // unknown
+ (3 << 5) | // coin counters
+ (BIT(~p1, 6) << 4) | // SERVICE1
+ (BIT(m_dsw->read(), 1, 3) << 1) | // DSW1-3 TODO: confirm
+ (BIT(~system, 7) << 0); // TEST
+}
+
+void namco_cyberlead_device::iocpu_port_6_w(uint8_t data)
+{
+ machine().bookkeeping().coin_counter_w(0, BIT(data, 6));
+ machine().bookkeeping().coin_counter_w(1, BIT(data, 5));
+}
+
+uint8_t namco_cyberlead_device::iocpu_port_7_r()
+{
+ return m_port7->read();
+}
+
+
+namco_cyberlead_led_device::namco_cyberlead_led_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) :
+ device_t(mconfig, NAMCO_CYBERLEAD_LED, tag, owner, clock),
+ device_rs232_port_interface(mconfig, *this),
+ m_ledcpu(*this, "ledcpu"),
+ m_flash(*this, "flash"),
+ m_screen(*this, "led"),
+ m_scroll(*this, "scroll"),
+ m_sed1351f_ram(*this, "sed1351f_ram"),
+ m_sed1351f_control(*this, "sed1351f_control"),
+ m_dsw(*this, "DSW")
+{
+}
+
+namespace {
+
+} // anonymous namespace
+
+void namco_cyberlead_led_device::device_add_mconfig(machine_config &config)
+{
+ NAMCO_C77(config, m_ledcpu, 14.7456_MHz_XTAL);
+ m_ledcpu->set_addrmap(AS_PROGRAM, &namco_cyberlead_led_device::ledcpu_program_map);
+ m_ledcpu->read_port6().set(FUNC(namco_cyberlead_led_device::ledcpu_port_6_r));
+
+ m_ledcpu->write_sci_tx<1>().set(FUNC(namco_cyberlead_led_device::output_rxd));
+
+ ATMEL_29C020(config, m_flash);
+
+ SCREEN(config, m_screen, SCREEN_TYPE_RASTER);
+ m_screen->set_native_aspect();
+ m_screen->set_size(96 * 8, 16 * 8);
+ m_screen->set_visarea(0, (96 * 8) - 1, 0, (16 * 8) - 1);
+ m_screen->set_screen_update(FUNC(namco_cyberlead_led_device::screen_update));
+ m_screen->set_refresh_hz(60);
+ m_screen->set_vblank_time(ATTOSECONDS_IN_USEC(2500));
+ m_screen->set_orientation(ROT180);
+ m_screen->screen_vblank().set([this](int state)
+ {
+ m_ledcpu->set_input_line(6, state ? ASSERT_LINE : CLEAR_LINE);
+ });
+}
+
+namespace {
+
+static INPUT_PORTS_START(cyberleadled)
+ PORT_START("DSW")
+ PORT_DIPNAME(0x08, 0x08, "Display Test") PORT_DIPLOCATION("SW3:1") // c9fb
+ PORT_DIPSETTING(0x08, "1 Time")
+ PORT_DIPSETTING(0x00, "4 Times")
+ PORT_DIPNAME(0x04, 0x04, "Disable Epilepsy Filter") PORT_DIPLOCATION("SW3:2") // c9fc
+ PORT_DIPSETTING(0x04, DEF_STR(Off))
+ PORT_DIPSETTING(0x00, DEF_STR(On))
+ PORT_DIPUNKNOWN_DIPLOC(0x02, IP_ACTIVE_LOW, "SW3:3")
+ PORT_DIPUNUSED_DIPLOC(0x01, IP_ACTIVE_LOW, "SW3:4")
+INPUT_PORTS_END
+
+} // anonymous namespace
+
+ioport_constructor namco_cyberlead_led_device::device_input_ports() const
+{
+ return INPUT_PORTS_NAME(cyberleadled);
+}
+
+namespace {
+
+static const uint16_t led_gfx[] =
+{
+ 0b0001101010010000,
+ 0b0110111111100100,
+ 0b1011111111111001,
+ 0b1011111111111001,
+ 0b1011111111111001,
+ 0b0110111111100100,
+ 0b0001101010010000,
+ 0b0000010101000000,
+};
+
+ROM_START( cyberleadled )
+ ROM_REGION( 0x40000, "flash", 0 )
+ ROM_LOAD( "cl1-leda.ic5", 0x000000, 0x040000, CRC(5717e05f) SHA1(61d61338e1bb414af32dbdc1e24d54c02fb9196e) )
+ROM_END
+
+} // anonymous namespace
+
+const tiny_rom_entry *namco_cyberlead_led_device::device_rom_region() const
+{
+ return ROM_NAME(cyberleadled);
+}
+
+void namco_cyberlead_led_device::device_start()
+{
+ for (int c = 0; c < 4; c++)
+ for (int i = 0; i < 4; i++)
+ {
+ int r = ((((0xff * c) / 3) + 0x2f) * i) / 3;
+ m_palette[c][i] = rgb_t(std::min(r, 0xff), r / 4, r / 3);
+ }
+
+ m_flash_bank = 0;
+
+ save_item(NAME(m_flash_bank));
+}
+
+void namco_cyberlead_led_device::input_txd(int state)
+{
+ m_ledcpu->sci_rx_w<1>(state);
+}
+
+void namco_cyberlead_led_device::ledcpu_program_map(address_map &map)
+{
+ map(0x0000, 0x3fff).rw(m_flash, FUNC(intelfsh8_device::read), FUNC(intelfsh8_device::write));
+ map(0x4000, 0x5fff).ram().share(m_sed1351f_ram);
+ map(0x6000, 0x600f).ram().share(m_sed1351f_control);
+ map(0x7000, 0x7001).ram().share(m_scroll);
+ map(0x8000, 0xbfff).rw(FUNC(namco_cyberlead_led_device::ledcpu_banked_flash_r), FUNC(namco_cyberlead_led_device::ledcpu_banked_flash_w));
+ map(0xc000, 0xfb7f).ram();
+ map(0xff84, 0xff87).w(FUNC(namco_cyberlead_led_device::ledcpu_flash_bank_w));
+}
+
+uint8_t namco_cyberlead_led_device::ledcpu_banked_flash_r(offs_t offset)
+{
+ return m_flash->read(offset + m_flash_bank);
+}
+
+void namco_cyberlead_led_device::ledcpu_banked_flash_w(offs_t offset, uint8_t data)
+{
+ m_flash->write(offset + m_flash_bank, data);
+}
+
+void namco_cyberlead_led_device::ledcpu_flash_bank_w(offs_t offset, uint8_t data)
+{
+ m_flash_bank = 0x4000 * (offset | (data << 2));
+}
+
+uint8_t namco_cyberlead_led_device::ledcpu_port_6_r()
+{
+ const auto system = 0;
+ const auto p1 = 0;
+
+ return (1 << 7) | // unknown
+ (3 << 5) | // coin counters
+ (BIT(~p1, 6) << 4) | // SERVICE1
+ (BIT(m_dsw->read(), 1, 3) << 1) | // DSW1-3 TODO: confirm
+ (BIT(~system, 7) << 0); // TEST
+}
+
+uint32_t namco_cyberlead_led_device::screen_update(screen_device &screen, bitmap_rgb32 &bitmap, const rectangle &cliprect)
+{
+ int start = swapendian_int16(m_sed1351f_control[6 / 2]) & 0x1fff;
+ int scroll = ~m_ledcpu->space(AS_PROGRAM).read_byte(0xd0bf) & 3;
+ int scrollx = ((start & 0x1f) * 4) + scroll;
+ int scrolly = start >> 5;
+
+ for (int y = cliprect.min_y; y <= cliprect.max_y; y++)
+ {
+ uint32_t *dst = &bitmap.pix(y, cliprect.min_x);
+ uint16_t *src = &m_sed1351f_ram[((scrolly + (y >> 3)) & 511) * 16];
+ uint16_t gfx = led_gfx[y & 7];
+ for (int x = cliprect.min_x; x <= cliprect.max_x; x++)
+ {
+ int p = (scrollx + (x >> 3)) & 127;
+ *dst++ = m_palette[BIT(src[p >> 3], (~p & 7) * 2, 2)][BIT(gfx, (x & 7) << 1, 2)];
+ }
+ }
+ return 0;
+}
+
+namespace {
+
+ROM_START( cyberleadajvs )
+ ROM_REGION( 0x040000, "iocpu", 0 )
+ ROM_LOAD( "cl1-iob.ic5", 0x000000, 0x040000, CRC(abb90360) SHA1(d938b1e1ae596d0ab1007352f61b0b800363c762) )
+ROM_END
+
+class namco_cyberleada_device :
+ public namco_cyberlead_device
+{
+public:
+ namco_cyberleada_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock = 0)
+ : namco_cyberlead_device(mconfig, NAMCO_CYBERLEADA, tag, owner, clock)
+ {
+ }
+
+protected:
+ virtual const tiny_rom_entry *device_rom_region() const override ATTR_COLD
+ {
+ return ROM_NAME(cyberleadajvs);
+ }
+};
+
+} // anonymous namespace
+
+
+DEFINE_DEVICE_TYPE(NAMCO_CYBERLEAD, namco_cyberlead_device, "namco_cyberlead", "Namco Cyber Lead I/O LED(I/O) PCB 8699014200 (compatibility patch)")
+DEFINE_DEVICE_TYPE_PRIVATE(NAMCO_CYBERLEADA, device_jvs_interface, namco_cyberleada_device, "namco_cyberleada", "Namco Cyber Lead I/O LED(I/O) PCB 8699014200")
+DEFINE_DEVICE_TYPE(NAMCO_CYBERLEAD_LED, namco_cyberlead_led_device, "namco_cyberlead_led", "Namco Cyber Lead I/O LED(LED) PCB 8699014500")
diff --git a/src/devices/bus/jvs/cyberlead.h b/src/devices/bus/jvs/cyberlead.h
new file mode 100644
index 00000000000..08c1873a4ad
--- /dev/null
+++ b/src/devices/bus/jvs/cyberlead.h
@@ -0,0 +1,95 @@
+// license:BSD-3-Clause
+// copyright-holders:smf
+
+#ifndef MAME_BUS_JVS_CYBERLEAD_H
+#define MAME_BUS_JVS_CYBERLEAD_H
+
+#pragma once
+
+#include "jvs.h"
+#include "bus/rs232/rs232.h"
+#include "cpu/h8/c77.h"
+#include "machine/intelfsh.h"
+#include "emupal.h"
+#include "screen.h"
+#include "tilemap.h"
+
+class namco_cyberlead_device :
+ public device_t,
+ public device_jvs_interface
+{
+public:
+ namco_cyberlead_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock = 0);
+
+ auto &rs232() const { if (m_rs232) return *m_rs232; return *subdevice<rs232_port_device>(m_rs232.finder_tag()); }
+
+protected:
+ namco_cyberlead_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock = 0);
+
+ // device_t
+ virtual void device_add_mconfig(machine_config &config) override ATTR_COLD;
+ virtual ioport_constructor device_input_ports() const override ATTR_COLD;
+ virtual const tiny_rom_entry *device_rom_region() const override ATTR_COLD;
+ virtual void device_start() override ATTR_COLD;
+
+ // device_jvs_interface
+ virtual void rxd(int state) override;
+
+private:
+ void iocpu_program_map(address_map &map);
+
+ uint8_t iocpu_in_r(offs_t offset);
+ uint8_t iocpu_port_4_r();
+ void iocpu_port_4_w(uint8_t data);
+ uint8_t iocpu_port_5_r();
+ void iocpu_port_5_w(uint8_t data);
+ uint8_t iocpu_port_6_r();
+ void iocpu_port_6_w(uint8_t data);
+ uint8_t iocpu_port_7_r();
+
+ required_device<namco_c77_device> m_iocpu;
+ required_ioport m_dsw;
+ required_ioport m_port7;
+ required_device<rs232_port_device> m_rs232;
+};
+
+class namco_cyberlead_led_device :
+ public device_t,
+ public device_rs232_port_interface
+{
+public:
+ namco_cyberlead_led_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock = 0);
+
+protected:
+ // device_t
+ virtual void device_add_mconfig(machine_config &config) override ATTR_COLD;
+ virtual ioport_constructor device_input_ports() const override ATTR_COLD;
+ virtual const tiny_rom_entry *device_rom_region() const override ATTR_COLD;
+ virtual void device_start() override ATTR_COLD;
+
+ // device_rs232_port_interface
+ virtual void input_txd(int state) override;
+
+ uint32_t screen_update(screen_device &screen, bitmap_rgb32 &bitmap, const rectangle &cliprect);
+ void ledcpu_program_map(address_map &map);
+ uint8_t ledcpu_banked_flash_r(offs_t offset);
+ void ledcpu_banked_flash_w(offs_t offset, uint8_t data);
+ void ledcpu_flash_bank_w(offs_t offset, uint8_t data);
+ uint8_t ledcpu_port_6_r();
+
+ required_device<namco_c77_device> m_ledcpu;
+ required_device<intelfsh8_device> m_flash;
+ required_device<screen_device> m_screen;
+ required_shared_ptr<uint16_t> m_scroll;
+ required_shared_ptr<uint16_t> m_sed1351f_ram;
+ required_shared_ptr<uint16_t> m_sed1351f_control;
+ required_ioport m_dsw;
+ rgb_t m_palette[4][4];
+ int m_flash_bank;
+};
+
+DECLARE_DEVICE_TYPE(NAMCO_CYBERLEAD, namco_cyberlead_device)
+DECLARE_DEVICE_TYPE(NAMCO_CYBERLEADA, device_jvs_interface)
+DECLARE_DEVICE_TYPE(NAMCO_CYBERLEAD_LED, namco_cyberlead_led_device)
+
+#endif
diff --git a/src/devices/bus/jvs/jvs.cpp b/src/devices/bus/jvs/jvs.cpp
new file mode 100644
index 00000000000..663bff4ccd0
--- /dev/null
+++ b/src/devices/bus/jvs/jvs.cpp
@@ -0,0 +1,449 @@
+// license:BSD-3-Clause
+// copyright-holders:smf
+
+#include "emu.h"
+#include "jvs.h"
+
+#define LOG_PACKETS (1U << 1)
+#define LOG_SIGNALS (1U << 2)
+#define LOG_IGNORED (1U << 3)
+#define LOG_CONFLICT (1U << 4)
+
+//#define VERBOSE (LOG_PACKETS /*| LOG_SIGNALS | LOG_IGNORED | LOG_CONFLICT*/)
+//#define LOG_OUTPUT_FUNC osd_printf_info
+#include "logmacro.h"
+
+#define LOGPACKETS(...) LOGMASKED(LOG_PACKETS, __VA_ARGS__)
+#define LOGSIGNALS(...) LOGMASKED(LOG_SIGNALS, __VA_ARGS__)
+#define LOGIGNORED(...) LOGMASKED(LOG_IGNORED, __VA_ARGS__)
+#define LOGCONFLICT(...) LOGMASKED(LOG_CONFLICT, __VA_ARGS__)
+
+DEFINE_DEVICE_TYPE(JVS_PORT, jvs_port_device, "jvs_port", "JVS IO Port")
+
+#define FIX_CONFLICT (1)
+
+jvs_port_device::jvs_port_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) :
+ device_t(mconfig, JVS_PORT, tag, owner, clock),
+ device_single_card_slot_interface<device_jvs_interface>(mconfig, *this),
+ m_device(nullptr),
+ m_debug_timer(nullptr),
+ m_rxd_cb(*this),
+ m_sense_cb(*this),
+ m_rts(0),
+ m_rxd(0),
+ m_txd(1)
+{
+}
+
+jvs_port_device::~jvs_port_device()
+{
+}
+
+void jvs_port_device::device_config_complete()
+{
+ m_device = get_card_device();
+}
+
+void jvs_port_device::device_start()
+{
+ device_jvs_interface *intf;
+ if (!owner()->interface(intf))
+ {
+ if (VERBOSE & LOG_PACKETS)
+ m_debug_timer = timer_alloc(FUNC(jvs_port_device::debug_timer_callback), this);
+
+ m_debug_bit = -1;
+ m_debug_index = 0;
+ m_debug_rxd = 1;
+ std::fill_n(m_debug_buffer, std::size(m_debug_buffer), 0);
+
+ update_rxd();
+
+ save_item(NAME(m_debug_bit));
+ save_item(NAME(m_debug_index));
+ save_item(NAME(m_debug_rxd));
+ save_item(NAME(m_debug_buffer));
+ }
+
+ save_item(NAME(m_rts));
+ save_item(NAME(m_txd));
+ save_item(NAME(m_rxd));
+}
+
+void jvs_port_device::rts(int state)
+{
+ if (m_rts != state)
+ {
+ LOGSIGNALS("%s rts %d\n", machine().describe_context(), state);
+
+ if (machine().scheduler().currently_executing())
+ machine().scheduler().synchronize(timer_expired_delegate(FUNC(jvs_port_device::update_rts), this), state);
+ else
+ update_rts(state);
+ }
+}
+
+void jvs_port_device::update_rts(s32 state)
+{
+ debug_flush();
+ debug_stop();
+
+ m_rts = state;
+
+ if (m_device)
+ {
+ if (m_rts && !m_rxd && !(FIX_CONFLICT && m_txd))
+ m_rxd_cb(1);
+
+ update_rxd();
+ }
+}
+
+void jvs_port_device::txd(int state)
+{
+ if (m_txd != state)
+ {
+ LOGSIGNALS("%s txd %d\n", machine().describe_context(), state);
+ m_txd = state;
+
+ update_rxd();
+ }
+}
+
+void jvs_port_device::update_rxd()
+{
+ int high = 0;
+ int low = 0;
+
+ if (m_rts)
+ {
+ high += (m_txd != 0);
+ low += (m_txd == 0);
+ }
+ else if (!m_txd)
+ LOGIGNORED("ignored txd\n");
+
+ for (device_jvs_interface *intf = m_device; intf; intf = intf->m_jvs ? intf->m_jvs->m_device : nullptr)
+ {
+ if (intf->m_rts)
+ {
+ high += (intf->m_txd != 0);
+ low += (intf->m_txd == 0);
+ }
+ else if (!intf->m_txd)
+ LOGIGNORED("ignored txd %s\n", intf->device().tag());
+ }
+
+ if (high + low > 1 && ((VERBOSE & LOG_CONFLICT) || FIX_CONFLICT))
+ {
+ debug_flush('@');
+
+ std::string conflict;
+ if (VERBOSE & LOG_CONFLICT)
+ conflict = util::string_format("conflict detected between %d devices (%d high, %d low)", high + low, high, low);
+
+ if (m_rts)
+ {
+ if (VERBOSE & LOG_CONFLICT)
+ conflict += util::string_format(",%s (%d)", tag(), m_txd);
+
+ if (FIX_CONFLICT && low && m_txd)
+ m_rts = 0;
+ }
+
+ for (device_jvs_interface *intf = m_device; intf; intf = intf->m_jvs ? intf->m_jvs->m_device : nullptr)
+ if (intf->m_rts)
+ {
+ if (VERBOSE & LOG_CONFLICT)
+ conflict += util::string_format(",%s (%d)", intf->device().tag(), intf->m_txd);
+
+ if (FIX_CONFLICT && low && intf->m_txd)
+ intf->m_rts = 0;
+ }
+
+ LOGCONFLICT("%s\n", conflict);
+
+ if (FIX_CONFLICT && low)
+ high = 0;
+ }
+
+ int rxd = low && !high ? 0 : 1;
+ if (m_rxd != rxd)
+ {
+ m_rxd = rxd;
+
+ for (device_jvs_interface *intf = m_device; intf; intf = intf->m_jvs ? intf->m_jvs->m_device : nullptr)
+ if (!intf->m_rts)
+ intf->rxd(m_rxd);
+
+ if (!m_rts)
+ m_rxd_cb(m_rxd);
+
+ debug_rxd(m_rxd);
+ }
+
+ if (high + low == 0)
+ {
+ debug_flush();
+ debug_stop();
+ }
+}
+
+void jvs_port_device::debug_rxd(int state)
+{
+ if (!state && m_debug_rxd && m_debug_timer && m_debug_timer->expire().is_never())
+ m_debug_timer->adjust(attotime::from_hz(115200 * 2), 0, attotime::from_hz(115200));
+
+ m_debug_rxd = state;
+}
+
+void jvs_port_device::debug_flush(wchar_t ch)
+{
+ if (m_debug_index)
+ {
+ if (VERBOSE & LOG_PACKETS)
+ {
+ std::string debug;
+ debug += m_rts ? ">" : "<";
+ for (int i = 0; i < m_debug_index; i++)
+ debug += util::string_format(" %02x", m_debug_buffer[i]);
+ if (ch)
+ debug += ch;
+ debug += "\n";
+
+ LOGPACKETS("%s", debug);
+ }
+
+ std::fill_n(m_debug_buffer, m_debug_index, 0);
+ m_debug_index = 0;
+
+ debug_stop();
+ }
+}
+
+void jvs_port_device::debug_stop()
+{
+ if (m_debug_timer)
+ m_debug_timer->adjust(attotime::never);
+ m_debug_bit = -1;
+}
+
+TIMER_CALLBACK_MEMBER(jvs_port_device::debug_timer_callback)
+{
+ if (m_debug_bit < 0)
+ {
+ if (m_debug_rxd)
+ debug_stop();
+ else
+ m_debug_bit = 0;
+ }
+ else if (m_debug_bit == 8)
+ {
+ m_debug_index++;
+
+ if (!m_debug_rxd)
+ debug_flush('*');
+ else if (m_debug_index >= std::size(m_debug_buffer))
+ debug_flush('!');
+
+ debug_stop();
+ }
+ else
+ {
+ if (m_debug_rxd)
+ m_debug_buffer[m_debug_index] |= 1 << m_debug_bit;
+
+ m_debug_bit++;
+ }
+}
+
+device_jvs_interface::device_jvs_interface(const machine_config &mconfig, device_t &device) :
+ device_interface(device, "jvs"),
+ m_jvs(*this, "jvs"),
+ m_jvs_sense(jvs_port_device::sense::None),
+ m_default_inputs(true),
+ m_output_cb(*this),
+ m_analog_output_cb(*this),
+ m_system(*this, "SYSTEM"),
+ m_system_cb(*this, 0),
+ m_player(*this, "PLAYER%u", 1U),
+ m_player_cb(*this, 0),
+ m_coin(*this, "COIN%u", 1U),
+ m_coin_cb(*this, 0),
+ m_analog_input(*this, "ANALOG_INPUT%u", 1U),
+ m_analog_input_cb(*this, 0),
+ m_rotary_input(*this, "ROTARY_INPUT%u", 1U),
+ m_rotary_input_cb(*this, 0),
+ m_screen_position_enable(*this, "SCREEN_POSITION_INPUT_ENABLE%u", 1U),
+ m_screen_position_enable_cb(*this, 0xffff),
+ m_screen_position_x(*this, "SCREEN_POSITION_INPUT_X%u", 1U),
+ m_screen_position_x_cb(*this, 0),
+ m_screen_position_y(*this, "SCREEN_POSITION_INPUT_Y%u", 1U),
+ m_screen_position_y_cb(*this, 0),
+ m_rts(0),
+ m_sense(jvs_port_device::sense::None),
+ m_txd(1)
+{
+ m_port = dynamic_cast<jvs_port_device *>(device.owner());
+
+ m_root = m_port;
+ if (m_root)
+ {
+ while (m_root->owner() && dynamic_cast<jvs_port_device *>(m_root->owner()->owner()))
+ m_root = dynamic_cast<jvs_port_device *>(m_root->owner()->owner());
+ }
+}
+
+void device_jvs_interface::interface_post_start()
+{
+ sense(jvs_port_device::sense::Uninitialized);
+
+ device().save_item(NAME(m_jvs_sense));
+ device().save_item(NAME(m_rts));
+ device().save_item(NAME(m_sense));
+ device().save_item(NAME(m_txd));
+}
+
+device_jvs_interface::~device_jvs_interface()
+{
+}
+
+void device_jvs_interface::rts(int state)
+{
+ if (m_rts != state)
+ {
+ if (device().machine().scheduler().currently_executing())
+ device().machine().scheduler().synchronize(timer_expired_delegate(FUNC(device_jvs_interface::update_rts), this), state);
+ else
+ update_rts(state);
+ }
+}
+
+void device_jvs_interface::update_rts(int32_t state)
+{
+ m_rts = state;
+
+ if (m_root)
+ {
+ if (m_rts && !m_root->m_rxd && !(FIX_CONFLICT && m_txd))
+ rxd(1);
+
+ m_root->update_rxd();
+ }
+}
+
+void device_jvs_interface::txd(int state)
+{
+ if (m_txd != state)
+ {
+ m_txd = state;
+
+ if (m_root)
+ m_root->update_rxd();
+ }
+}
+
+void device_jvs_interface::sense(uint8_t state)
+{
+ if (m_sense != state)
+ {
+ if (device().machine().scheduler().currently_executing())
+ device().machine().scheduler().synchronize(timer_expired_delegate(FUNC(device_jvs_interface::update_sense), this), state);
+ else
+ update_sense(state);
+ }
+}
+
+void device_jvs_interface::update_sense(int32_t state)
+{
+ m_sense = state;
+
+ if (m_port)
+ {
+#if VERBOSE & LOG_SIGNALS
+ device().
+ LOG_OUTPUT_FUNC("%s sense %s %d\n", device().tag(),
+ m_sense == jvs_port_device::sense::Initialized ? "Initialized" :
+ m_sense == jvs_port_device::sense::Uninitialized ? "Uninitialized" :
+ m_sense == jvs_port_device::sense::None ? "None" : "", state);
+#endif
+
+ device_jvs_interface *intf;
+ if (m_port->owner()->interface(intf))
+ intf->jvs_sense(m_sense);
+ else
+ m_port->m_sense_cb(m_sense);
+ }
+}
+
+uint8_t device_jvs_interface::system_r(uint8_t mem_mask)
+{
+ return (m_default_inputs ? m_system.read_safe(0) : m_system_cb(mem_mask)) & mem_mask;
+}
+
+uint32_t device_jvs_interface::player_r(offs_t offset, uint32_t mem_mask)
+{
+ return (m_default_inputs ? m_player[offset].read_safe(0) : m_player_cb[offset](0, mem_mask)) & mem_mask;
+}
+
+uint8_t device_jvs_interface::coin_r(offs_t offset, uint8_t mem_mask)
+{
+ return (m_default_inputs ? m_coin[offset].read_safe(0) : m_coin_cb[offset](0, mem_mask)) & mem_mask;
+}
+
+uint16_t device_jvs_interface::analog_input_r(offs_t offset, uint16_t mem_mask)
+{
+ return (m_default_inputs ? m_analog_input[offset].read_safe(0) : m_analog_input_cb[offset](0, mem_mask)) & mem_mask;
+}
+
+uint16_t device_jvs_interface::rotary_input_r(offs_t offset)
+{
+ return m_default_inputs ? m_rotary_input[offset].read_safe(0) : m_rotary_input_cb[offset]();
+}
+
+uint16_t device_jvs_interface::screen_position_enable_r(offs_t offset)
+{
+ return m_default_inputs ? m_screen_position_enable[offset].read_safe(0xffff) : m_screen_position_enable_cb[offset]();
+}
+
+uint16_t device_jvs_interface::screen_position_x_r(offs_t offset)
+{
+ return m_default_inputs ? m_screen_position_x[offset].read_safe(0) : m_screen_position_x_cb[offset]();
+}
+
+uint16_t device_jvs_interface::screen_position_y_r(offs_t offset)
+{
+ return m_default_inputs ? m_screen_position_y[offset].read_safe(0) : m_screen_position_y_cb[offset]();
+}
+
+void device_jvs_interface::add_jvs_port(machine_config &config)
+{
+ JVS_PORT(config, m_jvs, jvs_port_devices, nullptr);
+}
+
+void device_jvs_interface::jvs_sense(uint8_t state)
+{
+ m_jvs_sense = state;
+}
+
+#include "cyberlead.h"
+#include "namcoio.h"
+
+void jvs_port_devices(device_slot_interface &device)
+{
+ device.option_add("namco_amc", NAMCO_AMC);
+ device.option_add("namco_asca1", NAMCO_ASCA1);
+ device.option_add("namco_asca3", NAMCO_ASCA3);
+ device.option_add("namco_asca3a", NAMCO_ASCA3A);
+ device.option_add("namco_asca5", NAMCO_ASCA5);
+ device.option_add("namco_csz1", NAMCO_CSZ1);
+ device.option_add("namco_cyberlead", NAMCO_CYBERLEAD);
+ device.option_add("namco_cyberleada", NAMCO_CYBERLEADA);
+ device.option_add("namco_emio102", NAMCO_EMIO102);
+ device.option_add("namco_empri101", NAMCO_EMPRI101);
+ device.option_add("namco_fca10", NAMCO_FCA10);
+ device.option_add("namco_fca11", NAMCO_FCA11);
+ device.option_add("namco_fcb", NAMCO_FCB);
+ device.option_add("namco_tssio", NAMCO_TSSIO);
+ device.option_add("namco_xmiu1", NAMCO_XMIU1);
+}
diff --git a/src/devices/bus/jvs/jvs.h b/src/devices/bus/jvs/jvs.h
new file mode 100644
index 00000000000..66b62c26ba9
--- /dev/null
+++ b/src/devices/bus/jvs/jvs.h
@@ -0,0 +1,157 @@
+// license:BSD-3-Clause
+// copyright-holders:smf
+
+#ifndef MAME_BUS_JVS_JVS_H
+#define MAME_BUS_JVS_JVS_H
+
+#pragma once
+
+class device_jvs_interface;
+
+class jvs_port_device :
+ public device_t,
+ public device_single_card_slot_interface<device_jvs_interface>
+{
+ friend class device_jvs_interface;
+
+public:
+ template <typename T>
+ jvs_port_device(machine_config const &mconfig, char const *tag, device_t *owner, T &&opts, char const *dflt)
+ : jvs_port_device(mconfig, tag, owner, 0)
+ {
+ option_reset();
+ opts(*this);
+ set_default_option(dflt);
+ set_fixed(false);
+ }
+
+ jvs_port_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock = 0);
+ virtual ~jvs_port_device();
+
+ struct sense { enum : uint8_t
+ {
+ Initialized = 0, // 0V
+ Uninitialized = 1, // 2.5V
+ None = 2 // 5v
+ }; };
+
+ auto rxd() { return m_rxd_cb.bind(); }
+ auto sense() { return m_sense_cb.bind(); }
+
+ void txd(int state);
+ void rts(int state);
+
+protected:
+ // device_t
+ virtual void device_config_complete() override;
+ virtual void device_start() override ATTR_COLD;
+
+ device_jvs_interface *m_device;
+
+private:
+ void debug_rxd(int state);
+ void debug_flush(wchar_t ch = 0);
+ void debug_stop();
+ TIMER_CALLBACK_MEMBER(debug_timer_callback);
+
+ emu_timer *m_debug_timer;
+ int8_t m_debug_bit;
+ uint16_t m_debug_index;
+ int8_t m_debug_rxd;
+ uint8_t m_debug_buffer[0x102];
+
+ void update_rts(int32_t state);
+ void update_rxd();
+
+ devcb_write_line m_rxd_cb;
+ devcb_write8 m_sense_cb;
+ int8_t m_rts;
+ int8_t m_rxd;
+ int8_t m_txd;
+};
+
+class device_jvs_interface :
+ public device_interface
+{
+ friend class jvs_port_device;
+
+public:
+ virtual ~device_jvs_interface();
+
+ auto system() { m_default_inputs = false; return m_system_cb.bind(); }
+ template<unsigned N> auto player() { m_default_inputs = false; return m_player_cb[N].bind(); }
+ template<unsigned N> auto coin() { m_default_inputs = false; return m_coin_cb[N].bind(); }
+ template<unsigned N> auto analog_input() { m_default_inputs = false; return m_analog_input_cb[N].bind(); }
+ template<unsigned N> auto rotary_input() { m_default_inputs = false; return m_rotary_input_cb[N].bind(); }
+ template<unsigned N> auto screen_position_enable() { m_default_inputs = false; return m_screen_position_enable_cb[N].bind(); }
+ template<unsigned N> auto screen_position_x() { m_default_inputs = false; return m_screen_position_x_cb[N].bind(); }
+ template<unsigned N> auto screen_position_y() { m_default_inputs = false; return m_screen_position_y_cb[N].bind(); }
+ auto output() { return m_output_cb.bind(); }
+ template<unsigned N> auto analog_output() { return m_analog_output_cb[N].bind(); }
+
+ auto jvs() const { if (m_jvs.target()) return m_jvs.target(); return device().subdevice<jvs_port_device>(m_jvs.finder_tag()); }
+
+protected:
+ device_jvs_interface(const machine_config &mconfig, device_t &device);
+
+ // device_interface
+ virtual void interface_post_start() override;
+
+ virtual void rxd(int state) = 0;
+
+ void rts(int state);
+ void txd(int state);
+ void sense(uint8_t state);
+ virtual void jvs_sense(uint8_t state);
+
+ void add_jvs_port(machine_config &config);
+
+ uint8_t system_r(uint8_t mem_mask);
+ uint32_t player_r(offs_t offset, uint32_t mem_mask);
+ uint8_t coin_r(offs_t offset, uint8_t mem_mask);
+ uint16_t analog_input_r(offs_t offset, uint16_t mem_mask);
+ uint16_t rotary_input_r(offs_t offset);
+ uint16_t screen_position_enable_r(offs_t offset);
+ uint16_t screen_position_x_r(offs_t offset);
+ uint16_t screen_position_y_r(offs_t offset);
+
+ optional_device<jvs_port_device> m_jvs;
+ uint8_t m_jvs_sense;
+
+ bool m_default_inputs;
+ devcb_write64 m_output_cb;
+ devcb_write16::array<8> m_analog_output_cb;
+
+private:
+ optional_ioport m_system;
+ devcb_read8 m_system_cb;
+ optional_ioport_array<8> m_player;
+ devcb_read32::array<8> m_player_cb;
+ optional_ioport_array<8> m_coin;
+ devcb_read8::array<8> m_coin_cb;
+ optional_ioport_array<8> m_analog_input;
+ devcb_read16::array<8> m_analog_input_cb;
+ optional_ioport_array<8> m_rotary_input;
+ devcb_read16::array<8> m_rotary_input_cb;
+ optional_ioport_array<8> m_screen_position_enable;
+ devcb_read16::array<8> m_screen_position_enable_cb;
+ optional_ioport_array<8> m_screen_position_x;
+ devcb_read16::array<8> m_screen_position_x_cb;
+ optional_ioport_array<8> m_screen_position_y;
+ devcb_read16::array<8> m_screen_position_y_cb;
+
+ jvs_port_device *m_port;
+ jvs_port_device *m_root;
+ void update_rts(int32_t state);
+ void update_sense(int32_t state);
+
+ int8_t m_rts;
+ uint8_t m_sense;
+ int8_t m_txd;
+};
+
+DECLARE_DEVICE_TYPE(JVS_PORT, jvs_port_device)
+
+void jvs_port_devices(device_slot_interface &device);
+
+#endif // MAME_BUS_JVS_JVS_H
diff --git a/src/devices/bus/jvs/jvshle.cpp b/src/devices/bus/jvs/jvshle.cpp
new file mode 100644
index 00000000000..50ef59402c1
--- /dev/null
+++ b/src/devices/bus/jvs/jvshle.cpp
@@ -0,0 +1,868 @@
+// license:BSD-3-Clause
+// copyright-holders:smf
+
+#include "emu.h"
+#include "jvshle.h"
+#include <algorithm>
+
+#define LOG_COMMAND (1U << 1)
+#define LOG_ERROR (1U << 2)
+#define LOG_OUTPUT (1U << 3)
+
+//#define VERBOSE (/*LOG_COMMAND | */LOG_ERROR | LOG_OUTPUT)
+//#define LOG_OUTPUT_FUNC osd_printf_info
+#include "logmacro.h"
+
+#define LOGCOMMAND(...) LOGMASKED(LOG_COMMAND, __VA_ARGS__)
+#define LOGERROR(...) LOGMASKED(LOG_ERROR, __VA_ARGS__)
+#define LOGOUTPUT(...) LOGMASKED(LOG_OUTPUT, __VA_ARGS__)
+
+namespace {
+
+struct State { enum : uint8_t
+{
+ Sync,
+ Escape,
+ EscapedData,
+ Data
+}; };
+
+static constexpr uint8_t Sync = 0xe0;
+static constexpr uint8_t Escape = 0xd0;
+
+} // anonymous namespace
+
+jvs_hle_device::jvs_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_jvs_interface(mconfig, *this),
+ m_rxd(1),
+ m_output(0),
+ m_analog_output{},
+ m_analog_output_channels(0)
+{
+}
+
+void jvs_hle_device::device_start()
+{
+ m_rx_timer = timer_alloc(FUNC(jvs_hle_device::rx_timer_callback), this);
+ m_tx_timer = timer_alloc(FUNC(jvs_hle_device::tx_timer_callback), this);
+
+ m_coin_timer = timer_alloc(FUNC(jvs_hle_device::coin_timer_callback), this);
+
+ m_mainid.resize(100);
+ m_mainid_length = 0;
+ m_retransmit_buffer.resize(0x102);
+ m_retransmit_length = 3;
+ m_rx_bit = -1;
+ m_rx_buffer.resize(0x102);
+ m_rx_length = 0;
+ m_rx_state = State::Sync;
+ m_tx_bit = -1;
+ m_tx_buffer.resize(0x102);
+ m_tx_index = 0;
+ m_tx_length = 0;
+ m_tx_state = State::Sync;
+
+ save_item(NAME(m_address));
+ save_item(NAME(m_mainid));
+ save_item(NAME(m_mainid_length));
+ save_item(NAME(m_retransmit_buffer));
+ save_item(NAME(m_retransmit_length));
+ save_item(NAME(m_rx_bit));
+ save_item(NAME(m_rx_buffer));
+ save_item(NAME(m_rx_index));
+ save_item(NAME(m_rx_length));
+ save_item(NAME(m_rx_state));
+ save_item(NAME(m_rxd));
+ save_item(NAME(m_tx_bit));
+ save_item(NAME(m_tx_buffer));
+ save_item(NAME(m_tx_index));
+ save_item(NAME(m_tx_length));
+ save_item(NAME(m_tx_safe_length));
+ save_item(NAME(m_tx_state));
+
+ save_item(NAME(m_player_count));
+ save_item(NAME(m_switch_count));
+ save_item(NAME(m_switch_mask));
+ save_item(NAME(m_coin_counter));
+ save_item(NAME(m_coin_offset));
+ save_item(NAME(m_coin_prev));
+ save_item(NAME(m_analog_input_channels));
+ save_item(NAME(m_analog_input_bits));
+ save_item(NAME(m_rotary_input_channels));
+ save_item(NAME(m_screen_position_input_channels));
+ save_item(NAME(m_screen_position_input_xbits));
+ save_item(NAME(m_screen_position_input_ybits));
+ save_item(NAME(m_output));
+ save_item(NAME(m_output_mask));
+ save_item(NAME(m_output_slots));
+ save_item(NAME(m_analog_output));
+ save_item(NAME(m_analog_output_channels));
+}
+
+void jvs_hle_device::device_reset()
+{
+ rts(0);
+ sense(jvs_port_device::sense::Uninitialized);
+ rx_stop();
+ rx_clear();
+
+ std::fill_n(m_mainid.begin(), m_mainid_length, 0);
+ m_mainid_length = 0;
+ m_address = 0xff;
+ m_retransmit_buffer[0] = 0x00; // destination
+ m_retransmit_buffer[2] = StatusCode::Normal;
+ std::fill_n(m_retransmit_buffer.begin() + 3, m_retransmit_length - 3, 0);
+ m_retransmit_length = 3;
+ m_rx_index = 0;
+
+ m_player_count = player_count();
+ m_switch_count = switch_count();
+ m_switch_mask = switch_mask();
+ m_coin_slots = coin_slots();
+ m_coin_offset = coin_offset();
+
+ m_coin_counter.fill(0);
+ attotime const coin_timer_rate = m_coin_slots ? attotime::from_hz(120) : attotime::never;
+ m_coin_timer->adjust(coin_timer_rate, 0, coin_timer_rate);
+ m_coin_prev.fill(0xff);
+
+ m_analog_input_channels = analog_input_channels();
+ m_analog_input_bits = analog_input_bits();
+ m_rotary_input_channels = rotary_input_channels();
+ m_screen_position_input_channels = screen_position_input_channels();
+ m_screen_position_input_xbits = screen_position_input_xbits();
+ m_screen_position_input_xbits = screen_position_input_ybits();
+
+ m_output_slots = output_slots();
+ m_output_mask = jvs_bitmask<uint64_t>(m_output_slots);
+ update_output(0);
+
+ for (int i = 0; i < m_analog_output_channels; i++)
+ update_analog_output(i, 0);
+
+ m_analog_output_channels = analog_output_channels();
+}
+
+const char *jvs_hle_device::device_id()
+{
+ return "";
+}
+
+uint8_t jvs_hle_device::command_revision()
+{
+ return 0x13;
+}
+
+uint8_t jvs_hle_device::jvs_revision()
+{
+ return 0x30;
+}
+
+uint8_t jvs_hle_device::communication_revision()
+{
+ return 0x10;
+}
+
+void jvs_hle_device::feature_check()
+{
+ uint8_t *response;
+ if (m_player_count && m_switch_count && produce(4, response))
+ {
+ response[0] = FunctionCode::SwitchInput;
+ response[1] = m_player_count;
+ response[2] = m_switch_count;
+ response[3] = 0;
+ }
+
+ if (m_coin_slots && produce(4, response))
+ {
+ response[0] = FunctionCode::CoinInput;
+ response[1] = m_coin_slots;
+ response[2] = 0;
+ response[3] = 0;
+ }
+
+ if (m_analog_input_channels && produce(4, response))
+ {
+ response[0] = FunctionCode::AnalogInput;
+ response[1] = m_analog_input_channels;
+ response[2] = m_analog_input_bits;
+ response[3] = 0;
+ }
+
+ if (m_rotary_input_channels && produce(4, response))
+ {
+ response[0] = FunctionCode::RotaryInput;
+ response[1] = m_rotary_input_channels;
+ response[2] = 0;
+ response[3] = 0;
+ }
+
+ if (m_screen_position_input_channels && produce(4, response))
+ {
+ response[0] = FunctionCode::ScreenPositionInput;
+ response[1] = m_screen_position_input_xbits;
+ response[2] = m_screen_position_input_ybits;
+ response[3] = m_screen_position_input_channels;
+ }
+
+ if (m_output_slots && produce(4, response))
+ {
+ response[0] = FunctionCode::GeneralPurposeOutput;
+ response[1] = m_output_slots;
+ response[2] = 0;
+ response[3] = 0;
+ }
+
+ if (m_analog_output_channels && produce(4, response))
+ {
+ response[0] = FunctionCode::AnalogOutput;
+ response[1] = m_analog_output_channels;
+ response[2] = 0;
+ response[3] = 0;
+ }
+}
+
+void jvs_hle_device::execute(uint8_t command)
+{
+ uint8_t const *parameters;
+ uint8_t *response;
+
+ switch (command)
+ {
+ case CommandCode::Reset:
+ if (consume(1, parameters) && parameters[0] == 0xd9)
+ device_reset();
+ break;
+
+ case CommandCode::SetAddress:
+ if (consume(1, parameters) && m_jvs_sense != jvs_port_device::sense::Uninitialized && m_address == 0xff &&
+ produce(1, response))
+ {
+ m_address = parameters[0];
+ response[0] = ReportCode::Normal;
+ }
+ break;
+
+ case CommandCode::IOIDENT:
+ {
+ const char *id = device_id();
+ int len = strlen(id) + 1;
+ if (produce(1 + len, response))
+ {
+ response[0] = ReportCode::Normal;
+ memcpy(&response[1], id, len);
+ }
+ break;
+ }
+
+ case CommandCode::CMDREV:
+ if (produce(2, response))
+ {
+ response[0] = ReportCode::Normal;
+ response[1] = command_revision();
+ }
+ break;
+
+ case CommandCode::JVSREV:
+ if (produce(2, response))
+ {
+ response[0] = ReportCode::Normal;
+ response[1] = jvs_revision();
+ }
+ break;
+
+ case CommandCode::COMMVER:
+ if (produce(2, response))
+ {
+ response[0] = ReportCode::Normal;
+ response[1] = communication_revision();
+ }
+ break;
+
+ case CommandCode::FEATCHK:
+ if (produce(1, response))
+ {
+ response[0] = ReportCode::Normal;
+ feature_check();
+ if (produce(1, response))
+ response[0] = 0x00;
+ }
+ break;
+
+ case CommandCode::MAINID:
+ if (consume(1, parameters))
+ {
+ uint8_t const *mainid = parameters;
+ size_t const size = m_rx_length - m_rx_index;
+ size_t length = 0;
+ while (mainid[length] && length < size)
+ length++;
+
+ if (consume(length, parameters))
+ {
+ if (length < size && length < m_mainid.size())
+ {
+ if (produce(1, response))
+ {
+ std::copy_n(mainid, length, m_mainid.begin());
+ if (m_mainid_length > length)
+ std::fill_n(&m_mainid[length], m_mainid_length - length, 0);
+ m_mainid_length = length;
+
+ //std::string s(m_mainid.begin(), m_mainid.begin() + length);
+ //osd_printf_info("mainid = %s\n", s);
+
+ response[0] = ReportCode::Normal;
+ }
+ }
+ else if (produce(1, response))
+ response[0] = ReportCode::InvalidParameter;
+ }
+ }
+ break;
+
+ case CommandCode::SWINP:
+ if (consume(2, parameters))
+ {
+ uint8_t const players = parameters[0];
+ uint8_t const bytes = parameters[1];
+
+ if (players <= m_player_count && bytes <= (m_switch_count + 7) / 8)
+ {
+ if (produce((players * bytes) + 2, response))
+ {
+ response[0] = ReportCode::Normal;
+ response[1] = system_r(0xff);
+
+ uint32_t mask = m_switch_mask & jvs_bitmask<uint32_t>(bytes * 8);
+ for (int i = 0; i < players; i++)
+ {
+ uint32_t val = player_r(i, mask);
+ for (int j = 0; j < bytes; j++)
+ response[(i * bytes) + j + 2] = val >> (j * 8);
+ }
+ }
+ }
+ else if (produce(1, response))
+ response[0] = ReportCode::InvalidParameter;
+ }
+ break;
+
+ case CommandCode::COININP:
+ if (consume(1, parameters))
+ {
+ uint8_t const count = parameters[0];
+
+ if (count <= m_coin_slots)
+ {
+ if (produce((count * 2) + 1, response))
+ {
+ response[0] = ReportCode::Normal;
+
+ for (int i = 0; i < count; i++)
+ {
+ response[(i * 2) + 1] = (m_coin_counter[i] >> 8) & 0x3f;
+ response[(i * 2) + 2] = m_coin_counter[i];
+ }
+ }
+ }
+ else if (produce(1, response))
+ response[0] = ReportCode::InvalidParameter;
+ }
+ break;
+
+ case CommandCode::ANLINP:
+ if (consume(1, parameters))
+ {
+ uint8_t const count = parameters[0];
+
+ if (count <= m_analog_input_channels)
+ {
+ if (produce((count * 2) + 1, response))
+ {
+ uint16_t const analog_input_mask = m_analog_input_bits > 0 && m_analog_input_bits < 16 ? make_bitmask<uint16_t>(m_analog_input_bits) << (16 - m_analog_input_bits) : 0xffff;
+
+ response[0] = ReportCode::Normal;
+
+ for (int i = 0; i < count; i++)
+ {
+ uint16_t const analog_input = analog_input_r(i, analog_input_mask);
+ response[(i * 2) + 1] = analog_input >> 8;
+ response[(i * 2) + 2] = analog_input;
+ }
+ }
+ }
+ else if (produce(1, response))
+ response[0] = ReportCode::InvalidParameter;
+ }
+ break;
+
+ case CommandCode::ROTINP:
+ if (consume(1, parameters))
+ {
+ uint8_t const count = parameters[0];
+
+ if (count <= m_rotary_input_channels)
+ {
+ if (produce((count * 2) + 1, response))
+ {
+ response[0] = ReportCode::Normal;
+
+ for (int i = 0; i < count; i++)
+ {
+ uint16_t const rotary_input = rotary_input_r(i);
+ response[(i * 2) + 1] = rotary_input >> 8;
+ response[(i * 2) + 2] = rotary_input;
+ }
+ }
+ }
+ else if (produce(1, response))
+ response[0] = ReportCode::InvalidParameter;
+ }
+ break;
+
+ case CommandCode::SCRPOSINP:
+ if (consume(1, parameters))
+ {
+ uint8_t const index = parameters[0] - 1;
+ if (index < m_screen_position_input_channels)
+ {
+ if (produce(5, response))
+ {
+ uint16_t const enable = screen_position_enable_r(index);
+ uint16_t const x = enable ? screen_position_x_r(index) : 0xffff;
+ uint16_t const y = enable ? screen_position_y_r(index) : 0xffff;
+ response[0] = ReportCode::Normal;
+ response[1] = x >> 8;
+ response[2] = x;
+ response[3] = y >> 8;
+ response[4] = y;
+ }
+ }
+ else if (produce(1, response))
+ response[0] = ReportCode::InvalidParameter;
+ }
+ break;
+
+ case CommandCode::RETRANSMIT:
+ std::copy_n(m_retransmit_buffer.begin(), m_retransmit_length, m_tx_buffer.begin());
+ m_tx_length = m_retransmit_length;
+ break;
+
+ case CommandCode::COINDEC:
+ if (consume(3, parameters))
+ {
+ uint8_t const index = parameters[0] - m_coin_offset;
+ uint16_t const amount = (parameters[1] << 8) | parameters[2];
+
+ if (index < m_coin_slots)
+ {
+ if (produce(1, response))
+ {
+ m_coin_counter[index] = (m_coin_counter[index] < amount) ? 0 : m_coin_counter[index] - amount;
+ response[0] = ReportCode::Normal;
+ }
+ }
+ else if (produce(1, response))
+ response[0] = ReportCode::InvalidParameter;
+ }
+ break;
+
+ case CommandCode::OUTPUT1:
+ if (consume(1, parameters))
+ {
+ uint8_t const count = parameters[0];
+
+ if (consume(count, parameters))
+ {
+ if (count <= (m_output_slots + 7) / 8)
+ {
+ if (produce(1, response))
+ {
+ uint64_t output = m_output & ~jvs_bitmask<uint64_t>(count * 8);
+ for (int i = 0; i < count; i++)
+ output |= (uint64_t)parameters[i] << (i * 8);
+
+ update_output(output);
+ response[0] = ReportCode::Normal;
+ }
+ }
+ else if (produce(1, response))
+ response[0] = ReportCode::InvalidParameter;
+ }
+ }
+ break;
+
+ case CommandCode::ANLOUT:
+ if (consume(1, parameters))
+ {
+ uint8_t const count = parameters[0];
+
+ if (consume(count * 2, parameters))
+ {
+ if (count <= m_analog_output_channels)
+ {
+ if (produce(1, response))
+ {
+ for (int i = 0; i < count; i++)
+ update_analog_output(i, (parameters[i * 2] << 8) | parameters[(i * 2) + 1]);
+
+ response[0] = ReportCode::Normal;
+ }
+ }
+ else if (produce(1, response))
+ response[0] = ReportCode::InvalidParameter;
+ }
+ }
+ break;
+
+ case CommandCode::COININC:
+ if (consume(3, parameters))
+ {
+ uint8_t const index = parameters[0] - m_coin_offset;
+ uint16_t const amount = (parameters[1] << 8) | parameters[2];
+
+ if (index < m_coin_slots)
+ {
+ if (produce(1, response))
+ {
+ m_coin_counter[index] = (m_coin_counter[index] + amount) & 0x3fff;
+ response[0] = ReportCode::Normal;
+ }
+ }
+ else if (produce(1, response))
+ response[0] = ReportCode::InvalidParameter;
+ }
+ break;
+
+ case CommandCode::OUTPUT2:
+ if (consume(2, parameters))
+ {
+ uint8_t const index = parameters[0] - 1;
+ uint8_t const output = parameters[1];
+
+ if (index < (m_output_slots + 7) / 8)
+ {
+ if (produce(1, response))
+ {
+ update_output((m_output & ~(0xffULL << (index * 8))) | ((uint64_t)output << (index * 8)));
+ response[0] = ReportCode::Normal;
+ }
+ }
+ else if (produce(1, response))
+ response[0] = ReportCode::InvalidParameter;
+ }
+ break;
+
+ case CommandCode::OUTPUT3:
+ if (consume(2, parameters))
+ {
+ uint8_t const index = parameters[0];
+ uint8_t const output = parameters[1];
+
+ if (index < m_output_slots && output <= 2)
+ {
+ if (produce(1, response))
+ {
+ if (output == 2 || BIT(m_output, index ^ 7) != output)
+ update_output(m_output ^ (1ULL << (index ^ 7)));
+
+ response[0] = ReportCode::Normal;
+ }
+ }
+ else if (produce(1, response))
+ response[0] = ReportCode::InvalidParameter;
+ }
+ break;
+
+ default:
+ LOGERROR("unknown JVS command % 02x\n", command);
+ status_code(StatusCode::UnknownCommand);
+ break;
+ }
+}
+
+void jvs_hle_device::status_code(uint8_t status_code)
+{
+ m_tx_buffer[2] = status_code;
+}
+
+bool jvs_hle_device::consume(int size, uint8_t const *&parameters)
+{
+ if (m_rx_index + size < m_rx_length)
+ {
+ parameters = &m_rx_buffer[m_rx_index];
+ m_rx_index += size;
+ return true;
+ }
+
+ uint8_t *response;
+ if (produce(1, response))
+ response[0] = ReportCode::IncorrectNumberOfParameters;
+
+ m_rx_index = m_rx_length - 1;
+ parameters = nullptr;
+ return false;
+}
+
+bool jvs_hle_device::produce(int size, uint8_t *&response)
+{
+ if (m_tx_length + size >= std::size(m_tx_buffer))
+ {
+ status_code(StatusCode::AcknowledgeOverflow);
+ m_tx_length = m_tx_safe_length;
+ }
+
+ if (m_tx_buffer[2] == StatusCode::Normal)
+ {
+ response = &m_tx_buffer[m_tx_length];
+ m_tx_length += size;
+ return true;
+ }
+
+ response = nullptr;
+ return false;
+}
+
+void jvs_hle_device::packet_received()
+{
+ m_tx_bit = -1;
+ std::fill_n(m_tx_buffer.begin(), m_tx_length, 0);
+ m_tx_index = 0;
+ m_tx_length = 0;
+
+ if (m_rx_length >= 4 && (m_rx_buffer[0] == 0xff || m_rx_buffer[0] == m_address))
+ {
+ m_tx_buffer[0] = 0x00; // destination
+
+ uint8_t checksum = std::accumulate(m_rx_buffer.begin(), m_rx_buffer.begin() + m_rx_length - 1, 0);
+ if (m_rx_buffer[m_rx_length - 1] != checksum)
+ {
+ LOGERROR("jvs checksum %02x expected %02x\n", checksum, m_rx_buffer[m_rx_length - 1]);
+
+ if (m_rx_buffer[0] != 0xff)
+ {
+ status_code(StatusCode::ChecksumError);
+ m_tx_length = 3;
+ }
+ }
+ else
+ {
+ if (VERBOSE & LOG_COMMAND)
+ {
+ std::string jvsin;
+ for (int i = 0; i < m_rx_length; i++)
+ jvsin += util::string_format(" %02x", m_rx_buffer[i]);
+
+ LOGCOMMAND("jvs in %s\n", jvsin);
+ }
+
+ status_code(StatusCode::Normal);
+
+ m_rx_index = 2;
+ m_tx_length = 3;
+
+ while (m_tx_buffer[2] == StatusCode::Normal && m_rx_index < m_rx_length - 1)
+ {
+ m_tx_safe_length = m_tx_length;
+ execute(m_rx_buffer[m_rx_index++]);
+ }
+
+ if (m_tx_length == 3 && m_tx_buffer[2] == StatusCode::Normal)
+ m_tx_length = 0;
+ else
+ {
+ std::copy_n(m_tx_buffer.begin(), m_tx_length, m_retransmit_buffer.begin());
+ m_retransmit_length = m_tx_length;
+ }
+ }
+
+ if (m_tx_length)
+ {
+ m_tx_buffer[1] = m_tx_length - 1;
+ uint8_t checksum = std::accumulate(m_tx_buffer.begin(), m_tx_buffer.begin() + m_tx_length, 0);
+ m_tx_buffer[m_tx_length++] = checksum;
+
+ if (VERBOSE & LOG_COMMAND)
+ {
+ std::string jvsout;
+ for (int i = 0; i < m_tx_length; i++)
+ jvsout += util::string_format(" %02x", m_tx_buffer[i]);
+
+ LOGCOMMAND("jvs out %s\n", jvsout);
+ }
+
+ m_tx_timer->adjust(attotime::from_hz(115200) * 10, 0, attotime::from_hz(115200));
+ }
+ }
+
+ rx_clear();
+}
+
+void jvs_hle_device::rxd(int state)
+{
+ if (m_rxd && !state && m_rx_timer && m_rx_timer->expire().is_never())
+ m_rx_timer->adjust(attotime::from_hz(115200) / 2, 0, attotime::from_hz(115200));
+
+ m_rxd = state;
+}
+
+TIMER_CALLBACK_MEMBER(jvs_hle_device::rx_timer_callback)
+{
+ if (m_rx_bit < 0)
+ {
+ if (m_rxd)
+ rx_stop();
+ else
+ m_rx_bit = 0;
+ }
+ else if (m_rx_bit < 8)
+ {
+ if (m_rxd)
+ m_rx_buffer[m_rx_length] |= 1 << m_rx_bit;
+
+ m_rx_bit++;
+ }
+ else
+ {
+ m_rx_length++;
+
+ if (!m_rxd)
+ rx_clear(); // frame error
+ else if (m_rx_buffer[m_rx_length - 1] == Sync)
+ {
+ rx_clear();
+ m_rx_state = State::Data;
+ }
+ else if (m_rx_state == State::Sync)
+ rx_discard();
+ else if (m_rx_buffer[m_rx_length - 1] == Escape)
+ {
+ rx_discard();
+ m_rx_state = State::EscapedData;
+ }
+ else
+ {
+ if (m_rx_state == State::EscapedData)
+ {
+ m_rx_buffer[m_rx_length - 1]++;
+ m_rx_state = State::Data;
+ }
+
+ if (m_rx_length >= 2 && m_rx_length == m_rx_buffer[1] + 2)
+ packet_received();
+ else if (m_rx_length == m_rx_buffer.size())
+ rx_clear();
+ }
+
+ rx_stop();
+ }
+}
+
+TIMER_CALLBACK_MEMBER(jvs_hle_device::tx_timer_callback)
+{
+ if (m_tx_bit < 0)
+ {
+ if (m_tx_index >= m_tx_length)
+ {
+ m_tx_timer->adjust(attotime::never);
+ m_tx_state = State::Sync;
+ rts(0);
+ sense(jvs_port_device::sense::Initialized);
+ }
+ else
+ {
+ if (m_tx_index == 0)
+ rts(1);
+ txd(0);
+ m_tx_bit = 0;
+ }
+ }
+ else if (m_tx_bit < 8)
+ {
+ uint8_t data = (m_tx_state == State::Sync) ? Sync :
+ (m_tx_state == State::Escape) ? Escape :
+ (m_tx_state == State::EscapedData) ? m_tx_buffer[m_tx_index] - 1 :
+ m_tx_buffer[m_tx_index];
+
+ txd(BIT(data, m_tx_bit));
+ m_tx_bit++;
+ }
+ else
+ {
+ txd(1);
+ m_tx_bit = -1;
+
+ if (m_tx_state == State::Escape)
+ m_tx_state = State::EscapedData;
+ else
+ {
+ if (m_tx_state != State::Sync)
+ m_tx_index++;
+
+ if (m_tx_index < m_tx_length && (m_tx_buffer[m_tx_index] == Sync || m_tx_buffer[m_tx_index] == Escape))
+ m_tx_state = State::Escape;
+ else
+ m_tx_state = State::Data;
+ }
+ }
+}
+
+TIMER_CALLBACK_MEMBER(jvs_hle_device::coin_timer_callback)
+{
+ for (int i = 0; i < m_coin_slots; i++)
+ {
+ uint8_t coin = coin_r(i, 0x01);
+ if (BIT(coin & ~m_coin_prev[i], 0))
+ m_coin_counter[i] = (m_coin_counter[i] + 1) & 0x3fff;
+
+ m_coin_prev[i] = coin;
+ }
+}
+
+void jvs_hle_device::rx_clear()
+{
+ std::fill_n(m_rx_buffer.begin(), m_rx_length, 0);
+ m_rx_length = 0;
+ m_rx_state = State::Sync;
+}
+
+void jvs_hle_device::rx_discard()
+{
+ m_rx_buffer[--m_rx_length] = 0;
+}
+
+void jvs_hle_device::rx_stop()
+{
+ m_rx_timer->adjust(attotime::never);
+ m_rx_bit = -1;
+}
+
+uint32_t jvs_hle_device::switch_mask()
+{
+ return jvs_bitmask<uint32_t>(switch_count());
+}
+
+void jvs_hle_device::update_output(uint64_t output)
+{
+ output &= m_output_mask;
+
+ if (m_output != output)
+ {
+ LOGOUTPUT("update_output %0*llx\n", (m_output_slots + 3) / 4, output);
+ m_output_cb(0, output, output ^ m_output);
+ m_output = output;
+ }
+}
+
+void jvs_hle_device::update_analog_output(int offset, uint16_t output)
+{
+ if (m_analog_output[offset] != output)
+ {
+ LOGOUTPUT("update_fanalog_output %d %04x\n", offset, output);
+ m_analog_output_cb[offset](0, output, 0xffff);
+ m_analog_output[offset] = output;
+ }
+}
diff --git a/src/devices/bus/jvs/jvshle.h b/src/devices/bus/jvs/jvshle.h
new file mode 100644
index 00000000000..1d3abfbd461
--- /dev/null
+++ b/src/devices/bus/jvs/jvshle.h
@@ -0,0 +1,175 @@
+// license:BSD-3-Clause
+// copyright-holders:smf
+#ifndef MAME_BUS_JVS_JVSHLE_H
+#define MAME_BUS_JVS_JVSHLE_H
+
+#pragma once
+
+#include "jvs.h"
+
+class jvs_hle_device :
+ public device_t,
+ public device_jvs_interface
+{
+protected:
+ jvs_hle_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock = 0);
+
+ // device_t
+ virtual void device_start() override ATTR_COLD;
+ virtual void device_reset() override ATTR_COLD;
+
+ // device_jvs_interface
+ virtual void rxd(int state) override;
+
+ virtual const char *device_id();
+ virtual uint8_t command_revision();
+ virtual uint8_t jvs_revision();
+ virtual uint8_t communication_revision();
+ virtual uint8_t player_count() { return 0; }
+ virtual uint8_t switch_count() { return 0; }
+ virtual uint32_t switch_mask();
+ virtual uint8_t coin_slots() { return 0; }
+ virtual uint8_t coin_offset() { return 1; }
+ virtual uint8_t analog_input_channels() { return 0; }
+ virtual uint8_t analog_input_bits() { return 0; }
+ virtual uint8_t rotary_input_channels() { return 0; }
+ virtual uint8_t screen_position_input_channels() { return 0; }
+ virtual uint8_t screen_position_input_xbits() { return 0; }
+ virtual uint8_t screen_position_input_ybits() { return 0; }
+ virtual uint8_t output_slots() { return 0; }
+ virtual uint8_t analog_output_channels() { return 0; }
+ virtual void feature_check();
+ virtual void execute(uint8_t command);
+ void status_code(uint8_t status_code);
+ bool consume(int size, const uint8_t *&parameters);
+ bool produce(int size, uint8_t *&response);
+
+ template<typename T, typename U> constexpr T jvs_bitmask(U n)
+ {
+ return make_bitmask<T>((n + 7) & ~7) ^ (make_bitmask<T>((-n) & 7) << (n & ~7));
+ }
+
+ struct CommandCode { enum : uint8_t
+ {
+ Reset = 0xf0,
+ SetAddress = 0xf1,
+ CommMethodChange = 0xf2,
+
+ IOIDENT = 0x10,
+ CMDREV = 0x11,
+ JVSREV = 0x12,
+ COMMVER = 0x13,
+ FEATCHK = 0x14,
+ MAINID = 0x15,
+
+ SWINP = 0x20,
+ COININP = 0x21,
+ ANLINP = 0x22,
+ ROTINP = 0x23,
+ KEYINP = 0x24,
+ SCRPOSINP = 0x25,
+ MISCSWINP = 0x26,
+
+ PAYCNT = 0x2e,
+ RETRANSMIT = 0x2f,
+ COINDEC = 0x30,
+ PAYINC = 0x31,
+ OUTPUT1 = 0x32,
+ ANLOUT = 0x33,
+ CHAROUT = 0x34,
+ COININC = 0x35,
+ PAYDEC = 0x36,
+ OUTPUT2 = 0x37,
+ OUTPUT3 = 0x38,
+ }; };
+
+ struct StatusCode { enum : uint8_t
+ {
+ Normal = 0x01,
+ UnknownCommand = 0x02,
+ ChecksumError = 0x03,
+ AcknowledgeOverflow = 0x04,
+ }; };
+
+ struct ReportCode { enum : uint8_t
+ {
+ Normal = 0x01,
+ IncorrectNumberOfParameters = 0x02,
+ InvalidParameter = 0x03,
+ Busy = 0x04,
+ }; };
+
+ struct FunctionCode { enum : uint8_t
+ {
+ End = 0x00,
+
+ SwitchInput = 0x01,
+ CoinInput = 0x02,
+ AnalogInput = 0x03,
+ RotaryInput = 0x04,
+ KeycodeInput = 0x05,
+ ScreenPositionInput = 0x06,
+ MiscSwitchInput = 0x07,
+
+ CardSystem = 0x10,
+ MedalHopper = 0x11,
+ GeneralPurposeOutput = 0x12,
+ AnalogOutput = 0x13,
+ CharacterOutput = 0x14,
+ Backup = 0x15,
+ }; };
+
+private:
+ void packet_received();
+ TIMER_CALLBACK_MEMBER(rx_timer_callback);
+ TIMER_CALLBACK_MEMBER(tx_timer_callback);
+ TIMER_CALLBACK_MEMBER(coin_timer_callback);
+ void rx_clear();
+ void rx_discard();
+ void rx_stop();
+ void update_output(uint64_t output);
+ void update_analog_output(int offset, uint16_t output);
+
+ emu_timer *m_tx_timer;
+ emu_timer *m_rx_timer;
+ emu_timer *m_coin_timer;
+
+ uint8_t m_address;
+ std::vector<uint8_t> m_mainid;
+ uint8_t m_mainid_length;
+ std::vector<uint8_t> m_retransmit_buffer;
+ uint16_t m_retransmit_length;
+ uint16_t m_rx_index;
+ int32_t m_rx_bit;
+ std::vector<uint8_t> m_rx_buffer;
+ int32_t m_rx_length;
+ uint8_t m_rx_state;
+ int32_t m_rxd;
+ int32_t m_tx_bit;
+ std::vector<uint8_t> m_tx_buffer;
+ int32_t m_tx_index;
+ uint32_t m_tx_length;
+ uint32_t m_tx_safe_length;
+ uint8_t m_tx_state;
+
+ uint8_t m_player_count;
+ uint8_t m_switch_count;
+ uint32_t m_switch_mask;
+ uint8_t m_coin_slots;
+ std::array<uint16_t, 8> m_coin_counter;
+ uint8_t m_coin_offset;
+ std::array<uint8_t, 8> m_coin_prev;
+ uint8_t m_analog_input_channels;
+ uint8_t m_analog_input_bits;
+ uint8_t m_rotary_input_channels;
+ uint8_t m_screen_position_input_channels;
+ uint8_t m_screen_position_input_xbits;
+ uint8_t m_screen_position_input_ybits;
+ uint64_t m_output;
+ uint64_t m_output_mask;
+ uint8_t m_output_slots;
+ std::array<uint16_t, 8> m_analog_output;
+ uint8_t m_analog_output_channels;
+};
+
+#endif // MAME_BUS_JVS_JVSHLE_H
diff --git a/src/devices/bus/jvs/namcoio.cpp b/src/devices/bus/jvs/namcoio.cpp
new file mode 100644
index 00000000000..2081658c4be
--- /dev/null
+++ b/src/devices/bus/jvs/namcoio.cpp
@@ -0,0 +1,1611 @@
+// license:BSD-3-Clause
+// copyright-holders:smf
+/*
+Namco I/O PCBs
+--------------
+
+ASCA-1A PCB
+8662968202 (8662978202)
+|--------------------------------------------------------|
+|J105 J104 J103 J102 J101 |
+| NJM2904 |-------| |
+| ADM485 |ALTERA | |
+| NJM2904 |EPM7064| |
+| | | |
+| |-------| |-------| |
+| |---| | | |
+| IC13| | C78 | SW2 LB1235 LB1233 |
+| |---| | | 14.7460MHz LB1235 |
+| JP1|-------| |
+| 62256 PST592D |
+| MB87078 J106 |
+|--------------------------------------------------------|
+Notes:
+ IC13 - Atmel AT29C020 2MBit EEPROM labelled 'ASC1IO-A' (PLCC32)
+ C78 - Namco Custom MCU, positively identified as a Hitachi H8/3334 (PLCC84)
+ Clock input 14.7460MHz
+ EPM7064 - Altera EPM7064LC68-15 CPLD, labelled 'ASCA DR0' (PLCC68)
+ PST592D - System Reset IC (SOIC4)
+ 62256 - Hitachi HM62256 32kB x8-bit SRAM
+ ADM485 - Analog Devices +ADM485 5V Low Power EIA RS-485 Transceiver (SOIC8)
+ MB87078 - Fujitsu MB87078 Electronic Volume Control IC (SOIC24)
+ NJM2904 - New Japan Radio Co. NJM2904 Dual Operational Amplifier
+ LB1235 - Sanyo LB1235 65V 1.5A 4-channel Darlington Driver
+ LB1233 - Sanyo LB1233 Darlington Transistor Array with Built-in Current Limiting Resistors
+ J101 - 64 pin connector joining to ?
+ J102 - USB-A connector \ both tied together with common connections
+ J103 - USB-B connector /
+ J104 - Dual Red/White RCA Jacks (Twin Stereo Audio)
+ J105 - 9 pin connector
+ J106 - 12 pin connector
+ JP1 - 3 pin jumper labelled 'WE' and 'NC'. Default position is NC. This is used to write enable
+ the EEPROM for factory programming.
+ SW2 - DIP switch with 4 switches (default all off)
+
+This board is used with Final Furlong. This board connects to GORgON AV PCB
+
+
+V187 ASCA-2A PCB
+2477960102 (2477970102)
+|--------------------------------------------------------|
+| J105 |
+| |-------| 14.7456MHz |
+| J104 |ALTERA | ADM485 PST592D|
+| |EPM7064| |-------| |
+| | | | | |
+| |-------| | C78 | |
+| LC78815 | | |
+| |-------| |
+| MB87078 |---| |
+| LA4705 LB1233 |IC1| 62256 |
+| LB1235 |---| |
+| J101 J102 |
+|--------------------------------------------------------|
+Notes:
+ IC1 - Atmel AT29C020 2MBit EEPROM labelled 'ASCA1 I/O-A' (PLCC32)
+ C78 - Namco Custom MCU, positively identified as a Hitachi H8/3334 (PLCC84)
+ Clock input 14.7456MHz
+ EPM7064 - Altera EPM7064LC68-15 CPLD, labelled 'ASCA DR0' (PLCC68)
+ PST592D - System Reset IC (SOIC4)
+ ADM485 - Analog Devices +ADM485 5V Low Power EIA RS-485 Transceiver (SOIC8)
+ 62256 - Hitachi HM62256 32kB x8-bit SRAM
+ LB1235 - Sanyo LB1235 65V 1.5A 4-channel Darlington Driver
+ LB1233 - Sanyo LB1233 Darlington Transistor Array with Built-in Current Limiting Resistors
+ MB87078 - Fujitsu MB87078 Electronic Volume Control IC (SOIC24)
+ LC78815 - Sanyo LC78815 2-Channel 16-Bit D/A Converter (SOIC20)
+ LA4705 - Sanyo LA4705 15W 2-channel Power Amplifier
+ J101 - 34 pin flat cable connector for filter board
+ J102 - 50 pin flat cable connector for filter board
+ J104 - 8 pin JVS power connector (+5V, +12V, +3.3V)
+ J105 - 64 pin connector for connection of Main PCB
+
+This board is used with Rapid River but also works with Final Furlong.
+
+
+ASCA-3A PCB 8662968301 (8662978301)
+This is used with Motocross Go!
+It's identical to the one shown below (ASCA-4A) but the ROM is a surface mounted
+PLCC32 instead of a socketed DIP32 chip. Everything else is identical.
+
+ASCA-4A PCB 8662968401 (8662978401)
+(Used with most games and [for testing purposes] is able to boot all S23/SS23/Evolution2 games)
+Sticker for Gunmen Wars: ASCA5 PCB 86629615
+|---------------------------------------------------|
+| PST592 62256 |
+| 14.7460MHz |-------| |
+| | C78 | |
+| LB1235 DSW(4) | | 27C1001 |
+| LB1233 LB1235 |-------| |
+| |
+| |------| ADM485 |
+| |ALTERA| |
+| |EPM7096 |
+| J101 |------| J102 J103 |
+|---------------------------------------------------|
+Notes:
+ J101 - 64 pin connector for power + inputs. This joins to another PCB at 90 degrees containing
+ a bunch of connectors named 'ASCA 4B PCB 8662968702 (8662978702)'. This is where ALL of the
+ inputs/outputs for game control and inter-PCB communication are connected
+ PST592 - System Reset IC (SOIC4)
+ C78 - Hitachi HD643334 H8/3334 Microcontroller rebadged as 'C78'. Clock input 14.746MHz (PLCC84)
+ 27C1001 - 128k x8 EPROM (DIP32)
+ - For Downhill Bikers labelled 'ASC3 IO-C'
+ - For Panic Park labelled 'ASC3 IO-C'
+ - For Race On! labelled 'ASC5 IO-A'
+ - For Gunmen Wars labelled 'ASC5 IO-A'
+ 62256 - 32k x8 SRAM (SOP28)
+ EPM7096 - Altera EPM7096 CPLD with sticker 'ASCA,DR1' (PLCC68)
+ ADM485 - Analog Devices ADM485 +5V Low Power EIA RS-485 Transceiver (SOIC8)
+ J102/J103- Standard USB A and B connectors. These are not populated on most games, but are populated for
+ use with Motocross Go! on the ASCA-3A PCB.
+
+
+FCA PCB 8662969102 (8662979102)
+(Used with 500GP and Angler King. Another identical board is used with Ridge Racer V on System 246)
+|---------------------------------------------------|
+| J101 J106 |
+| 4.9152MHz |
+| DSW(6) |
+| LED2 |-----| |
+| | MCU | |
+| LEDS3-10 | | |
+| PIC16F84 |-----| |
+| JP1 LED1 ADM485 |
+| |
+| J102 J104 |
+|---------------------------------------------------|
+Notes:
+ J101 - 6 pin connector for power input
+ J102 - 60 pin flat cable connector
+ J104 - 5 pin connector
+ J106 - 30 pin flat cable connector
+ JP1 - 3 pin jumper, set to 'NORM'. Alt setting 'WR'
+ 3771 - Fujitsu MB3771 System Reset IC (SOIC8)
+ PIC16F84 - Microchip PIC16F84 PIC (SOIC20)
+ - For 500GP and Angler King stamped 'CAP10'
+ - For Ridge Racer V (on System 246) stamped 'CAP11'
+ MCU - Fujitsu MB90F574 F2MC-16LX Family Microcontroller (QFP120)
+ - For 500 GP and Angler King stamped 'FCAF10'
+ - For Ridge Racer V (on System 246) stamped 'FCAF11'
+ ADM485 - Analog Devices ADM485 +5V Low Power EIA RS-485 Transceiver (SOIC8)
+
+
+Drive/Feedback PCB
+------------------
+
+V183 AMC PCB 2473966102 (2473970102)
+|---------------------------------------------------|
+| |
+| |
+| 4.9152MHz J2|
+| |-----| |
+| | MCU | |
+| | | |
+| SS22 FFB |-----| |
+| |------| |
+| |ALTERA| DSW(4) |
+| |EPM7096 |
+| |------| |
+| J4|
+| ADM485 |
+| 27C1024 62256x2 J5|
+| |
+|---------------------------------------------------|
+Notes:
+ This board is used only with Motocross Go! to control the steering feedback motor. It communicates as a slave JVS
+ I/O board to both the game board and the ASCA I/O board. Another signal labelled as 'FREEZE/RELAY' connects between
+ this board to its ASCA I/O board.
+
+ MCU - Fujitsu MB90611A F2MC-16F Family Microcontroller. Clock input 4.9152MHz (QFP100)
+ 62256 - 32k x2 SRAM (SOP28)
+ EPM7096 - Altera EPM7064 CPLD labelled 'MG1,P LD0A' (PLCC44)
+ 27C1001 - 128k x8 EPROM labelled 'MG1-PRG0' (DIP40)
+ ADM485 - Analog Devices ADM485 +5V Low Power EIA RS-485 Transceiver (SOIC8)
+ J4/J5 - Standard USB A and B connectors.
+ J2 - Ribbon cable connector.
+ SS22 FFB - The recycled System 22 v147 motor drive board portion.
+
+ From testing on an actual Motocross Go! cabinet, the game doesn't like it if this board is disconnected in any way.
+ It needs both an ASCA and AMC I/O board chained in order to fully boot with properly working I/O. The following happens
+ if any portion of an AMC pcb is disconnected (only applies to Motocross Go!).
+
+ AMC board powered off: Board doesn't properly initialize its subcpu giving a 'subcpu timeout'.
+ AMC board powered on, JVS comms disconnected, freeze/relay connected: Board initializes the subcpu properly but
+ intentionally disables inputs.
+ AMC board powered on, JVS comms connected, freeze/relay disconnected: Board initializes the subcpu properly.
+ Main inputs work. Motor doesn't respond (if freeze/relay is reconnected, the motor will respond again).
+
+ In RS232 mode, the data should be sent at 9600 8n1 in the following format:
+ byte 0: 0xff
+ byte 1: 0x00-0x7f Analog output 0
+ byte 2: 0x00-0x0f/0x80-0x8f digital output
+ byte 3: 0x00-0xff Analog output 1
+
+
+I/O Boards for gun games
+------------------------
+
+Type 1:
+
+V185 I/O PCB
+2479961102 (2479971102)
+|-----------------------------------------|
+| J601 LED1 LED2 |-------| |
+| DSW(4)JP1 |-------| |TSSIO | |
+| |-----| | C78 |14.746MHz|PLD | |
+| |TSSIO| | |PST592 |-------| |
+| |PROG | |-------| |
+| |-----| |
+| |
+| 62256 |
+|ADM485 |
+|J1 SLA4060 J5|
+| J3 J4 |
+|-----------------------------------------|
+Notes:
+ TSSIOPROG - Atmel AT29C020 EEPROM stamped 'TSSIOP8' (PLCC32)
+ C78 - Namco Custom C78, actually a rebadged Hitachi HD643334 MCU, clock input 14.746MHz (PLCC84)
+ TSSIOPLD - Altera MAX EPM7128ELC84 CPLD with label 'TSSIOPLD' (PLCC84)
+ SLA4060 - Sanken Electric SLA4060 NPN general purpose darlington transistor (used to drive the kick-back solenoid in the gun)
+ PST592 - System Reset IC (SOIC4)
+ J1 - 12 position connector for power and I/O communication
+ J3 - 12 position connector for gun connection (trigger/buttons/optical signal/power)
+ J4 - not used?
+ J5 - 6 position connector for network
+ J601 - not used?
+ JP1 - jumper set to 1-2 (lower position), labelled 'WR'
+ DSW - 4 position dipswitch block, all off
+
+This board is used only on Time Crisis II.
+Note the gun is a standard light gun.
+
+
+Type 2:
+
+V221 MIU PCB
+2512960101 (2512970101)
+additional sticker for Time Crisis 3 says '2591961001 V291 XMIU PCB'
+|---------------------------------------------|
+|J10 J9 29C020 LC35256 DSW(4) |
+| M0105 PRG.8F LED |
+|2267 6393 LED |
+| T082 T082 |------| |
+| |--------| | C78 | J8 |
+| |ALTERA | | | |
+|J11 |MAX | |------| J7|
+| LM1881 |EPM7128 | 3771 |
+|R305526 |--------| |
+| ZUW1R51212 14.746MHz |
+| ADM485 J6|
+| |
+| J1 J2 J3 J4 J5 |
+|---------------------------------------------|
+Notes:
+ 2267 - JRC2267 Current limiting diode array? (SOIC8)
+ R305526 - Some kind of mini transformer or regulator?
+ LC35256 - Sanyo LC35256 32k x8 SRAM (SOP28)
+ LM1881 - National Semiconductor LM1881 Video Sync Separator (SOIC8)
+ M0105 - Matsushita Panasonic 0105 = ? (SOIC16)
+ T082 - Texas Instruments T082 (=TL082) JFET-Input operational amplifier (SOIC8)
+ 6393 - Sanyo 6393 (LA6393) High Performance Dual Comparator (SOIC8)
+ ADM485 - Analog Devices ADM485 5V Low Power EIA RS-485 Transceiver (SOIC8)
+ 3771 - Fujitsu MB3771 Power Supply Monitor and Master Reset IC (SOIC8)
+ EPM7128 - Altera MAX EPM7128SLC84-15 PLD labelled 'TMIU1/PLD0' (Time Crisis 3)
+ 29C020 - location for 29C020 PLCC32 Flash/EP ROM (not populated)
+ ZUW1R51212 - Cosel ZUW1R51212 DC to DC Power Supply Module (input 9-18VDC, output +-12VDC or +24VDC)
+ DSW - 4 position dipswitch block, all off
+ J1 - 6-pin power input connector
+ J2 - 12-pin connector (cabinet buttons UP/DOWN/ENTER plus TEST/SERVICE/COIN etc)
+ J3 - 4 pin connector (not used)
+ J4 - 9 pin Namco female plug connector for gun (solenoid +24V/trigger/pedal/sensor)
+ J5 - 5 pin connector used for I/O --> S246 communications (connects to USB link connection on main unit)
+ J6 - 7-pin connector (not used)
+ J9 - 6-pin connector (not used)
+ J10 - 2-pin Namco female plug connector (not used)
+ J11 - 6-pin Namco female plug connector (video input from CCD camera)
+ PRG.8F - 27C1001 EPROM with label
+ 'XMIU1 PRG0' (I/O program for Time Crisis 3)
+ 'CSZ1 PRG0A' (I/O program for Crisis Zone)
+
+This board is used on Crisis Zone (System 23 Evolution2) and Time Crisis 3 (System 246)
+Note both games use a CCD camera for the gun sensor.
+
+*/
+
+#include "emu.h"
+#include "namcoio.h"
+#include "jvshle.h"
+#include "cpu/f2mc16/mb90570.h"
+
+#define LOG_OUTPUT (1U << 1)
+
+//#define VERBOSE (LOG_OUTPUT)
+//#define LOG_OUTPUT_FUNC osd_printf_info
+#include "logmacro.h"
+
+#define LOGOUTPUT(...) LOGMASKED(LOG_OUTPUT, __VA_ARGS__)
+
+namco_amc_device::namco_amc_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) :
+ device_t(mconfig, NAMCO_AMC, tag, owner, clock),
+ device_jvs_interface(mconfig, *this),
+ device_rs232_port_interface(mconfig, *this),
+ m_iocpu(*this, "iocpu"),
+ m_analog_output{},
+ m_clear_output(1),
+ m_output(0),
+ m_ppg_duty(0),
+ m_ppg_flags(0),
+ m_sense_latch(0),
+ m_unknown_output(0)
+{
+}
+
+void namco_amc_device::device_add_mconfig(machine_config &config)
+{
+ MB90611A(config, m_iocpu, 4.9152_MHz_XTAL);
+ m_iocpu->set_addrmap(AS_PROGRAM, &namco_amc_device::iocpu_program_map);
+ m_iocpu->ppg().output<1>().set([this](offs_t offset, uint32_t data, uint32_t mem_mask)
+ {
+ m_ppg_duty = mem_mask >> 26;
+ update_analog_output0();
+ });
+ m_iocpu->adc().channel<0>().set(FUNC(namco_amc_device::adc_r<0>));
+ m_iocpu->adc().channel<1>().set(FUNC(namco_amc_device::adc_r<1>));
+ m_iocpu->adc().channel<2>().set(FUNC(namco_amc_device::adc_r<2>));
+ m_iocpu->adc().channel<3>().set(FUNC(namco_amc_device::adc_r<3>));
+ m_iocpu->port<0x2>().read().set([this]()
+ {
+ return (BIT(m_clear_output, 0) << 7) |
+ ((m_jvs_sense != jvs_port_device::sense::Initialized) << 6) |
+ ((m_jvs_sense != jvs_port_device::sense::None) << 5) |
+ (1 << 4) | // sense
+ (15 << 0); // output
+ });
+ m_iocpu->port<0x2>().write().set([this](uint8_t data)
+ {
+ m_sense_latch = BIT(data, 4); // HACK: improve compatibility by delaying sense::Initialized
+ if (!m_sense_latch)
+ sense(jvs_port_device::sense::Uninitialized);
+
+ uint8_t output = bitswap<4>(data, 0, 1, 2, 3) << 4;
+ if (m_output != output)
+ {
+ LOGOUTPUT("output_w %02x\n", output);
+ m_output_cb(0, output, output ^ m_output);
+ m_output = output;
+ }
+ });
+ m_iocpu->port<0x3>().read().set([this](uint8_t data)
+ {
+ return ~bitswap<8>(player_r(0, 0xfc03), 10, 11, 12, 13, 14, 15, 0, 1);
+ });
+ m_iocpu->port<0x7>().read().set_ioport("DSW");
+ m_iocpu->port<0x8>().write().set([this](uint8_t data)
+ {
+ m_ppg_flags = BIT(data, 0, 2);
+ update_analog_output0();
+
+ m_unknown_output = BIT(data, 2); // RS232 bit 7 of digital data, JVS unknown?
+ // BIT(data, 5); // set at startup
+ });
+ m_iocpu->port<0x9>().write().set([this](uint8_t data)
+ {
+ if (m_sense_latch)
+ sense(jvs_port_device::sense::Initialized); // HACK: improve compatibility by delaying sense::Initialized
+
+ // BIT(data, 1); // set at startup
+ rts(BIT(data, 2));
+ // BIT(data, 3); // toggles to indicate activity/error?
+ // BIT(data, 4); // ""
+ });
+
+ m_iocpu->uart<1>().sot().set(FUNC(namco_amc_device::txd));
+
+ config.set_maximum_quantum(attotime::from_hz(2 * 115200));
+
+ add_jvs_port(config);
+}
+
+namespace {
+
+struct DSW { enum : uint8_t
+{
+ Interface = 0x08,
+}; };
+
+static INPUT_PORTS_START(namco_amc)
+ PORT_START("DSW")
+ PORT_DIPNAME(0x08, 0x08, "Interface") PORT_DIPLOCATION("SW1:4")
+ PORT_DIPSETTING(0x08, "JVS")
+ PORT_DIPSETTING(0x00, "RS232")
+ PORT_DIPNAME(0x04, 0x04, "Output Test") PORT_DIPLOCATION("SW1:3")
+ PORT_DIPSETTING(0x04, DEF_STR(Off))
+ PORT_DIPSETTING(0x00, DEF_STR(On)) // interface must be set to JVS
+ PORT_DIPNAME(0x02, 0x00, "JVS Timeout") PORT_DIPLOCATION("SW1:2") // HACK: improve compatibility by setting default to Continue
+ PORT_DIPSETTING(0x02, "Stop") // outputs are cleared and board requires power cycling
+ PORT_DIPSETTING(0x00, "Continue") // outputs are cleared, but board still responds
+ PORT_DIPUNKNOWN_DIPLOC(0x01, 0x01, "SW1:1")
+INPUT_PORTS_END
+
+static INPUT_PORTS_START(namco_amc_default)
+ PORT_INCLUDE(namco_amc)
+
+ PORT_START("PLAYER1")
+ PORT_BIT(0x00000002, IP_ACTIVE_HIGH, IPT_BUTTON1)
+ PORT_BIT(0x00000001, IP_ACTIVE_HIGH, IPT_BUTTON2)
+ PORT_BIT(0x00008000, IP_ACTIVE_HIGH, IPT_BUTTON3)
+ PORT_BIT(0x00004000, IP_ACTIVE_HIGH, IPT_BUTTON4)
+ PORT_BIT(0x00002000, IP_ACTIVE_HIGH, IPT_BUTTON5)
+ PORT_BIT(0x00001000, IP_ACTIVE_HIGH, IPT_BUTTON6)
+ PORT_BIT(0x00000800, IP_ACTIVE_HIGH, IPT_BUTTON7)
+ PORT_BIT(0x00000400, IP_ACTIVE_HIGH, IPT_BUTTON8)
+
+ PORT_START("ANALOG_INPUT1")
+ PORT_BIT(0xffff, 0x8000, IPT_PADDLE) PORT_MINMAX(0x0000, 0xffff) PORT_SENSITIVITY(100) PORT_KEYDELTA(2560) PORT_NAME("Analog Input 1")
+
+ PORT_START("ANALOG_INPUT2")
+ PORT_BIT(0xffff, 0x8000, IPT_PADDLE) PORT_MINMAX(0x0000, 0xffff) PORT_SENSITIVITY(100) PORT_KEYDELTA(2560) PORT_NAME("Analog Input 2")
+
+ PORT_START("ANALOG_INPUT3")
+ PORT_BIT(0xffff, 0x8000, IPT_PADDLE) PORT_MINMAX(0x0000, 0xffff) PORT_SENSITIVITY(100) PORT_KEYDELTA(2560) PORT_NAME("Analog Input 3")
+
+ PORT_START("ANALOG_INPUT4")
+ PORT_BIT(0xffff, 0x8000, IPT_PADDLE) PORT_MINMAX(0x0000, 0xffff) PORT_SENSITIVITY(100) PORT_KEYDELTA(2560) PORT_NAME("Analog Input 4")
+
+ PORT_START("CLEAR")
+ PORT_BIT(0x0001, IP_ACTIVE_LOW, IPT_BUTTON9) PORT_NAME("Clear Output") PORT_WRITE_LINE_MEMBER(FUNC(namco_amc_device::clear_output))
+INPUT_PORTS_END
+
+ROM_START( namco_amc )
+ ROM_REGION( 0x020000, "iocpu", 0 )
+ ROM_LOAD( "mg1prog0a.3a", 0x000000, 0x020000, CRC(b2b5be8f) SHA1(803652b7b8fde2196b7fb742ba8b9843e4fcd2de) )
+ROM_END
+
+} // anonymous namespace
+
+ioport_constructor namco_amc_device::device_input_ports() const
+{
+ return m_default_inputs ? INPUT_PORTS_NAME(namco_amc_default) : INPUT_PORTS_NAME(namco_amc);
+}
+
+const tiny_rom_entry *namco_amc_device::device_rom_region() const
+{
+ return ROM_NAME(namco_amc);
+}
+
+void namco_amc_device::device_start()
+{
+ save_item(NAME(m_analog_output));
+ save_item(NAME(m_clear_output));
+ save_item(NAME(m_output));
+ save_item(NAME(m_ppg_duty));
+ save_item(NAME(m_ppg_flags));
+ save_item(NAME(m_sense_latch));
+ save_item(NAME(m_unknown_output));
+}
+
+void namco_amc_device::rxd(int state)
+{
+ m_iocpu->uart<1>().sin(state);
+}
+
+void namco_amc_device::input_txd(int state)
+{
+ m_iocpu->uart<0>().sin(state);
+}
+
+void namco_amc_device::iocpu_program_map(address_map &map)
+{
+ map(0x0000c8, 0x0000c8).w(FUNC(namco_amc_device::analog_output_w<1>));
+ map(0xfc0000, 0xfcffff).ram();
+ map(0xfe0000, 0xffffff).rom().region("iocpu", 0);
+}
+
+void namco_amc_device::update_analog_output0()
+{
+ analog_output_w<0>((BIT(m_ppg_flags, 0) ? 0 : m_ppg_duty) | (!BIT(m_ppg_flags, 1) << 6));
+}
+
+template<unsigned N>
+void namco_amc_device::analog_output_w(uint8_t data)
+{
+ if (m_analog_output[N] != data)
+ {
+ m_analog_output[N] = data;
+ LOGOUTPUT("analog_output_w %04x %04x\n", m_analog_output[0] * 0x101, m_analog_output[1] * 0x101);
+ m_analog_output_cb[N](data * 0x101);
+ }
+}
+
+template<int N>
+uint16_t namco_amc_device::adc_r()
+{
+ return analog_input_r(N, 0xffc0) >> 6;
+}
+
+void namco_amc_device::clear_output(int state)
+{
+ m_clear_output = state;
+}
+
+int namco_amc_device::unknown_output()
+{
+ return m_unknown_output;
+}
+
+
+namespace {
+
+static INPUT_PORTS_START(namco_c78_io)
+ PORT_START("DSW")
+ PORT_DIPUNKNOWN_DIPLOC(0x08, 0x08, "DIP SW2:1")
+ PORT_DIPUNKNOWN_DIPLOC(0x04, 0x04, "DIP SW2:2")
+ PORT_DIPUNKNOWN_DIPLOC(0x02, 0x02, "DIP SW2:3")
+ PORT_DIPUNKNOWN_DIPLOC(0x01, 0x01, "DIP SW2:4")
+INPUT_PORTS_END
+
+class namco_c78_jvs_io_device :
+ public device_t,
+ public device_jvs_interface
+{
+protected:
+ namco_c78_jvs_io_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_jvs_interface(mconfig, *this),
+ m_iocpu(*this, "iocpu"),
+ m_dsw(*this, "DSW")
+ {
+ }
+
+ // device_t
+ virtual void device_add_mconfig(machine_config &config) override ATTR_COLD
+ {
+ H83334(config, m_iocpu, 14.7456_MHz_XTAL);
+ m_iocpu->set_addrmap(AS_PROGRAM, &namco_c78_jvs_io_device::iocpu_program_map);
+ m_iocpu->write_port1().set_nop(); // unused
+ m_iocpu->write_port2().set_nop(); // unused
+ m_iocpu->write_port3().set_nop(); // unused
+ m_iocpu->read_port4().set(FUNC(namco_c78_jvs_io_device::iocpu_port_4_r));
+ m_iocpu->write_port4().set(FUNC(namco_c78_jvs_io_device::iocpu_port_4_w));
+ m_iocpu->read_port5().set(FUNC(namco_c78_jvs_io_device::iocpu_port_5_r));
+ m_iocpu->write_port5().set(FUNC(namco_c78_jvs_io_device::iocpu_port_5_w));
+ m_iocpu->read_port6().set(FUNC(namco_c78_jvs_io_device::iocpu_port_6_r));
+ m_iocpu->write_port6().set(FUNC(namco_c78_jvs_io_device::iocpu_port_6_w));
+ m_iocpu->read_port9().set(FUNC(namco_c78_jvs_io_device::iocpu_port_9_r));
+
+ m_iocpu->write_sci_tx<0>().set(FUNC(namco_c78_jvs_io_device::txd));
+
+ config.set_maximum_quantum(attotime::from_hz(2 * 115200));
+
+ add_jvs_port(config);
+ }
+
+ virtual ioport_constructor device_input_ports() const override ATTR_COLD
+ {
+ return INPUT_PORTS_NAME(namco_c78_io);
+ }
+
+ virtual void device_start() override ATTR_COLD
+ {
+ }
+
+ // device_jvs_interface
+ virtual void rxd(int state) override
+ {
+ m_iocpu->sci_rx_w<0>(state);
+ }
+
+ virtual void iocpu_program_map(address_map &map) ATTR_COLD
+ {
+ map(0x0000, 0x3fff).rom().region("iocpu", 0);
+ map(0xc000, 0xfb7f).ram();
+ }
+
+ uint8_t iocpu_port_4_r()
+ {
+ return (1 << 7) | // J6:4 (unknown input)
+ (BIT(m_dsw->read(), 0, 2) << 5) | // SW2:3/SW2:4
+ ((m_jvs_sense != jvs_port_device::sense::None) << 4) |
+ ((m_jvs_sense != jvs_port_device::sense::Initialized) << 3) |
+ (1 << 2) | // TR1 collector, emitter J1:1 & base J1:2 (sense)
+ (1 << 1) | // J6:10 (output high at startup)
+ (1 << 0); // NC (output)
+ }
+
+ void iocpu_port_4_w(uint8_t data)
+ {
+ sense(BIT(data, 2) ? jvs_port_device::sense::Initialized : jvs_port_device::sense::Uninitialized);
+ // BIT(data, 1)
+ }
+
+ uint8_t iocpu_port_5_r()
+ {
+ return (31 << 3) | // pins not bonded
+ (1 << 2) | // ADM485:2 (rts)
+ (1 << 1) | // ADM485:1 (configured as RxD)
+ (1 << 0); // ADM485:4 (configured as TxD)
+ }
+
+ void iocpu_port_5_w(uint8_t data)
+ {
+ rts(BIT(data, 2));
+ }
+
+ virtual uint8_t iocpu_port_6_r()
+ {
+ return (1 << 7) | // unknown input
+ (3 << 5) | // coin counter output
+ (BIT(~player_r(0, 0x40), 6) << 4) |
+ (3 << 2) | // unknown output
+ (BIT(m_dsw->read(), 2) << 1) | // SW2:2
+ (1 << 0); // unused input
+ }
+
+ void iocpu_port_6_w(uint8_t data)
+ {
+ machine().bookkeeping().coin_counter_w(0, BIT(data, 6));
+ machine().bookkeeping().coin_counter_w(1, BIT(data, 5)); // except tssio/csz1/xmiu1
+ // BIT(data, 3); // toggles (except asca1)
+ // BIT(data, 2); // toggles (except asca1)
+ }
+
+ virtual uint8_t iocpu_port_9_r() = 0;
+
+ required_device<h83334_device> m_iocpu;
+ required_ioport m_dsw;
+};
+
+
+static INPUT_PORTS_START(namco_asca1)
+ PORT_INCLUDE(namco_c78_io)
+
+ PORT_MODIFY("DSW")
+ PORT_DIPNAME(0x04, 0x04, "Output Test") PORT_DIPLOCATION("SW2:2")
+ PORT_DIPSETTING(0x04, DEF_STR(Off))
+ PORT_DIPSETTING(0x00, DEF_STR(On))
+INPUT_PORTS_END
+
+static INPUT_PORTS_START(namco_asca1_default)
+ PORT_INCLUDE(namco_asca1)
+
+ PORT_START("SYSTEM")
+ PORT_SERVICE(0x80, IP_ACTIVE_HIGH)
+
+ PORT_START("PLAYER1")
+ PORT_BIT(0x00000040, IP_ACTIVE_HIGH, IPT_SERVICE1)
+ PORT_BIT(0x00000020, IP_ACTIVE_HIGH, IPT_JOYSTICK_UP)
+ PORT_BIT(0x00000010, IP_ACTIVE_HIGH, IPT_JOYSTICK_DOWN)
+ PORT_BIT(0x00000002, IP_ACTIVE_HIGH, IPT_BUTTON1)
+ PORT_BIT(0x00000001, IP_ACTIVE_HIGH, IPT_BUTTON2)
+ PORT_BIT(0x00008000, IP_ACTIVE_HIGH, IPT_BUTTON3)
+ PORT_BIT(0x00004000, IP_ACTIVE_HIGH, IPT_BUTTON4)
+ PORT_BIT(0x00002000, IP_ACTIVE_HIGH, IPT_BUTTON5)
+ PORT_BIT(0x00001000, IP_ACTIVE_HIGH, IPT_BUTTON6)
+ PORT_BIT(0x00000800, IP_ACTIVE_HIGH, IPT_BUTTON7)
+ PORT_BIT(0x00000400, IP_ACTIVE_HIGH, IPT_BUTTON8)
+ PORT_BIT(0x00000200, IP_ACTIVE_HIGH, IPT_BUTTON9)
+ PORT_BIT(0x00000100, IP_ACTIVE_HIGH, IPT_BUTTON10)
+ PORT_BIT(0x00800000, IP_ACTIVE_HIGH, IPT_BUTTON11)
+ PORT_BIT(0x00400000, IP_ACTIVE_HIGH, IPT_BUTTON12)
+ PORT_BIT(0x00200000, IP_ACTIVE_HIGH, IPT_BUTTON13)
+
+ PORT_START("COIN1")
+ PORT_BIT(0x01, IP_ACTIVE_HIGH, IPT_COIN1)
+
+ PORT_START("COIN2")
+ PORT_BIT(0x01, IP_ACTIVE_HIGH, IPT_COIN2)
+
+ PORT_START("ANALOG_INPUT1")
+ PORT_BIT(0xffff, 0x8000, IPT_PADDLE) PORT_MINMAX(0x0000, 0xffff) PORT_SENSITIVITY(100) PORT_KEYDELTA(2560) PORT_NAME("Analog Input 1")
+
+ PORT_START("ANALOG_INPUT2")
+ PORT_BIT(0xffff, 0x8000, IPT_PADDLE) PORT_MINMAX(0x0000, 0xffff) PORT_SENSITIVITY(100) PORT_KEYDELTA(2560) PORT_NAME("Analog Input 2")
+
+ PORT_START("ANALOG_INPUT3")
+ PORT_BIT(0xffff, 0x8000, IPT_PADDLE) PORT_MINMAX(0x0000, 0xffff) PORT_SENSITIVITY(100) PORT_KEYDELTA(2560) PORT_NAME("Analog Input 3")
+
+ PORT_START("ANALOG_INPUT4")
+ PORT_BIT(0xffff, 0x8000, IPT_PADDLE) PORT_MINMAX(0x0000, 0xffff) PORT_SENSITIVITY(100) PORT_KEYDELTA(2560) PORT_NAME("Analog Input 4")
+
+ PORT_START("ANALOG_INPUT5")
+ PORT_BIT(0xffff, 0x8000, IPT_PADDLE) PORT_MINMAX(0x0000, 0xffff) PORT_SENSITIVITY(100) PORT_KEYDELTA(2560) PORT_NAME("Analog Input 5")
+
+ PORT_START("ANALOG_INPUT6")
+ PORT_BIT(0xffff, 0x8000, IPT_PADDLE) PORT_MINMAX(0x0000, 0xffff) PORT_SENSITIVITY(100) PORT_KEYDELTA(2560) PORT_NAME("Analog Input 6")
+
+ PORT_START("ANALOG_INPUT7")
+ PORT_BIT(0xffff, 0x8000, IPT_PADDLE) PORT_MINMAX(0x0000, 0xffff) PORT_SENSITIVITY(100) PORT_KEYDELTA(2560) PORT_NAME("Analog Input 7")
+
+ PORT_START("ANALOG_INPUT8")
+ PORT_BIT(0xffff, 0x8000, IPT_PADDLE) PORT_MINMAX(0x0000, 0xffff) PORT_SENSITIVITY(100) PORT_KEYDELTA(2560) PORT_NAME("Analog Input 8")
+INPUT_PORTS_END
+
+ROM_START( namco_asca1 )
+ ROM_REGION( 0x040000, "iocpu", 0 )
+ ROM_LOAD( "asc1_io-a.ic13", 0x000000, 0x040000, CRC(77cdf69a) SHA1(497af1059f85c07bea2dd0d303481623f6019dcf) )
+ROM_END
+
+class namco_asca_1_device :
+ public namco_c78_jvs_io_device
+{
+public:
+ namco_asca_1_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock = 0) :
+ namco_asca_1_device(mconfig, NAMCO_ASCA1, tag, owner, clock)
+ {
+ }
+
+protected:
+ namco_asca_1_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock) :
+ namco_c78_jvs_io_device(mconfig, type, tag, owner, clock),
+ m_output(0)
+ {
+ }
+
+ // device_t
+ virtual ioport_constructor device_input_ports() const override ATTR_COLD
+ {
+ return m_default_inputs ? INPUT_PORTS_NAME(namco_asca1_default) : INPUT_PORTS_NAME(namco_asca1);
+ }
+
+ virtual void device_add_mconfig(machine_config &config) override ATTR_COLD
+ {
+ namco_c78_jvs_io_device::device_add_mconfig(config);
+
+ m_iocpu->read_port8().set(FUNC(namco_asca_1_device::iocpu_port_8_r));
+ m_iocpu->write_port8().set(FUNC(namco_asca_1_device::iocpu_port_8_w));
+ m_iocpu->write_port9().set(FUNC(namco_asca_1_device::iocpu_port_9_w));
+
+ m_iocpu->read_adc<0>().set(FUNC(namco_asca_1_device::adc_r<0>));
+ m_iocpu->read_adc<1>().set(FUNC(namco_asca_1_device::adc_r<1>));
+ m_iocpu->read_adc<2>().set(FUNC(namco_asca_1_device::adc_r<2>));
+ m_iocpu->read_adc<3>().set(FUNC(namco_asca_1_device::adc_r<3>));
+ m_iocpu->read_adc<4>().set(FUNC(namco_asca_1_device::adc_r<4>));
+ m_iocpu->read_adc<5>().set(FUNC(namco_asca_1_device::adc_r<5>));
+ m_iocpu->read_adc<6>().set(FUNC(namco_asca_1_device::adc_r<6>));
+ m_iocpu->read_adc<7>().set(FUNC(namco_asca_1_device::adc_r<7>));
+ }
+
+ virtual const tiny_rom_entry *device_rom_region() const override ATTR_COLD
+ {
+ return ROM_NAME(namco_asca1);
+ }
+
+ virtual void device_start() override ATTR_COLD
+ {
+ namco_c78_jvs_io_device::device_start();
+
+ save_item(NAME(m_output));
+ }
+
+ // namco_c78_jvs_io_device
+ virtual void iocpu_program_map(address_map &map) override
+ {
+ namco_c78_jvs_io_device::iocpu_program_map(map);
+
+ map(0x6000, 0x6003).r(FUNC(namco_asca_1_device::in_r));
+ map(0x6004, 0x6005).w(FUNC(namco_asca_1_device::output_w));
+ }
+
+ uint8_t iocpu_port_8_r()
+ {
+ return (1 << 7) | // pin not bonded
+ (3 << 5) | // unknown input
+ (31 << 0); // unknown output
+ }
+
+ void iocpu_port_8_w(uint8_t data)
+ {
+ // BIT(data, 6) // set at startup, is set to input?
+ }
+
+ virtual uint8_t iocpu_port_9_r() override
+ {
+ return (3 << 6) | // unknown input
+ (31 << 1) | // unknown output
+ (BIT(m_dsw->read(), 3) << 0); // SW2:1 TODO: confirm
+ }
+
+ void iocpu_port_9_w(uint8_t data)
+ {
+ }
+
+ uint8_t in_r(offs_t offset)
+ {
+ if (offset == 0)
+ {
+ const auto system = system_r(0x80);
+ const auto p1 = player_r(0, 0xe033);
+
+ return ~((BIT(p1, 13) << 7) |
+ (BIT(p1, 14) << 6) |
+ (BIT(p1, 15) << 5) |
+ (BIT(p1, 0) << 4) |
+ (BIT(p1, 1) << 3) |
+ (BIT(p1, 4) << 2) |
+ (BIT(p1, 5) << 1) |
+ (BIT(system, 7) << 0));
+ }
+ else if (offset == 1)
+ {
+ const auto p1 = player_r(0, 0xe00300);
+
+ return ~((BIT(p1, 21) << 4) |
+ (BIT(p1, 22) << 3) |
+ (BIT(p1, 23) << 2) |
+ (BIT(p1, 8) << 1) |
+ (BIT(p1, 9) << 0));
+ }
+ else if (offset == 2)
+ {
+ const auto p1 = player_r(0, 0x1c00);
+ const auto c1 = coin_r(0, 0x01);
+
+ return ~((BIT(c1, 0) << 3) |
+ (BIT(p1, 10) << 2) |
+ (BIT(p1, 11) << 1) |
+ (BIT(p1, 12) << 0));
+ }
+ else if (offset == 3)
+ {
+ const auto c1 = coin_r(0, 0x80);
+ const auto c2 = coin_r(1, 0x81);
+
+ return ~((BIT(c2, 0) << 3) |
+ (BIT(~c2, 7) << 1) | // not asca1
+ (BIT(~c1, 7) << 0)); // not asca1
+ }
+ return 0xff;
+ }
+
+ template<int N> uint16_t adc_r()
+ {
+ return analog_input_r(N, 0xffc0) >> 6;
+ }
+
+ virtual void output_w(offs_t offset, uint8_t data)
+ {
+ uint16_t output = ((m_output & ~(0xff << (offset * 8))) | bitswap<8>(data, 0, 1, 2, 3, 4, 5, 6, 7) << (offset * 8)) & 0xf8ff;
+
+ if (m_output != output)
+ {
+ LOGOUTPUT("output_w %04x\n", output);
+ m_output_cb(0, output, output ^ m_output);
+ m_output = output;
+ }
+ }
+
+ uint64_t m_output;
+};
+
+
+static INPUT_PORTS_START(namco_asca3_default)
+ PORT_INCLUDE(namco_asca1_default)
+
+ PORT_MODIFY("DSW")
+ PORT_DIPUNKNOWN_DIPLOC(0x04, 0x04, "DIP SW2:2")
+
+ PORT_MODIFY("COIN1")
+ PORT_BIT(0x80, IP_ACTIVE_HIGH, IPT_TILT2) PORT_NAME("Counter 1 disconnected")
+
+ PORT_MODIFY("COIN2")
+ PORT_BIT(0x80, IP_ACTIVE_HIGH, IPT_TILT3) PORT_NAME("Counter 2 disconnected")
+
+ PORT_START("ROTARY_INPUT1")
+ PORT_BIT(0xff, 0, IPT_MOUSE_X) PORT_SENSITIVITY(15) PORT_KEYDELTA(8) PORT_NAME("Rotary Input 1")
+
+ PORT_START("ROTARY_INPUT2")
+ PORT_BIT(0xff, 0, IPT_MOUSE_Y) PORT_SENSITIVITY(15) PORT_KEYDELTA(8) PORT_REVERSE PORT_NAME("Rotary Input 2")
+INPUT_PORTS_END
+
+ROM_START( namco_asca3 )
+ ROM_REGION( 0x040000, "iocpu", 0 )
+ ROM_LOAD( "asc3_io-c.ic14", 0x000000, 0x020000, CRC(2f272a7b) SHA1(9d7ebe274c0d26f5f38747224d42d0375e2ed14c) )
+ROM_END
+
+class namco_asca_3_device :
+ public namco_asca_1_device
+{
+public:
+ namco_asca_3_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock = 0) :
+ namco_asca_3_device(mconfig, NAMCO_ASCA3, tag, owner, clock)
+ {
+ }
+
+protected:
+ namco_asca_3_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock) :
+ namco_asca_1_device(mconfig, type, tag, owner, clock),
+ m_rotary_prev{}
+ {
+ }
+
+ // device_t
+ virtual ioport_constructor device_input_ports() const override ATTR_COLD
+ {
+ return m_default_inputs ? INPUT_PORTS_NAME(namco_asca3_default) : namco_c78_jvs_io_device::device_input_ports();
+ }
+
+ virtual const tiny_rom_entry *device_rom_region() const override ATTR_COLD
+ {
+ return ROM_NAME(namco_asca3);
+ }
+
+ virtual void device_start() override ATTR_COLD
+ {
+ m_analog_output_timer = timer_alloc(FUNC(namco_asca_3_device::analog_output_timer_callback), this);
+
+ namco_asca_1_device::device_start();
+
+ save_item(NAME(m_analog_output));
+ save_item(NAME(m_analog_output_cycles));
+ save_item(NAME(m_analog_output_state));
+ save_item(NAME(m_rotary_prev));
+ }
+
+ // namco_c78_jvs_io_device
+ virtual void iocpu_program_map(address_map &map) override
+ {
+ namco_asca_1_device::iocpu_program_map(map);
+
+ map(0x6006, 0x6007).r(FUNC(namco_asca_3_device::rotary_diff_r));
+ }
+
+ virtual void output_w(offs_t offset, uint8_t data) override
+ {
+ if (offset == 1)
+ {
+ namco_asca_1_device::output_w(offset, data & ~(1 << 4));
+
+ int analog_output_state = BIT(data, 4);
+ if (analog_output_state != m_analog_output_state)
+ {
+ if (analog_output_state)
+ {
+ uint64_t high = m_analog_output_cycles[0] - m_analog_output_cycles[1];
+ uint64_t low = m_iocpu->total_cycles() - m_analog_output_cycles[0];
+ update_analog_output((high ? (0xff * high) / (high + low) : 0x0000) * 0x101);
+ }
+
+ m_analog_output_cycles[analog_output_state] = m_iocpu->total_cycles();
+ m_analog_output_timer->adjust(attotime::from_hz(18));
+ m_analog_output_state = analog_output_state;
+ }
+ }
+ else
+ namco_asca_1_device::output_w(offset, data);
+ }
+
+ TIMER_CALLBACK_MEMBER(analog_output_timer_callback)
+ {
+ update_analog_output(m_analog_output_state ? 0xffff : 0x0000);
+ }
+
+ void update_analog_output(uint16_t data)
+ {
+ if (m_analog_output != data)
+ {
+ m_analog_output = data;
+ LOGOUTPUT("analog_output_w %04x\n", data);
+ m_analog_output_cb[0](data);
+ }
+ }
+
+ virtual uint8_t rotary_diff_r(offs_t offset)
+ {
+ uint8_t data = rotary_input_r(offset) - m_rotary_prev[offset];
+ m_rotary_prev[offset] += data;
+ return data;
+ }
+
+ emu_timer *m_analog_output_timer;
+ uint16_t m_analog_output;
+ uint64_t m_analog_output_cycles[2];
+ uint8_t m_analog_output_state;
+ uint8_t m_rotary_prev[2];
+};
+
+
+ROM_START( namco_asca3a )
+ ROM_REGION( 0x040000, "iocpu", 0 )
+ ROM_LOAD( "asca-3a.ic14", 0x000000, 0x040000, CRC(8e9266e5) SHA1(ffa8782ca641d71d57df23ed1c5911db05d3df97) )
+ROM_END
+
+class namco_asca_3a_device :
+ public namco_asca_3_device
+{
+public:
+ namco_asca_3a_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock = 0) :
+ namco_asca_3_device(mconfig, NAMCO_ASCA3A, tag, owner, clock)
+ {
+ }
+
+protected:
+ // device_t
+ virtual const tiny_rom_entry *device_rom_region() const override ATTR_COLD
+ {
+ return ROM_NAME(namco_asca3a);
+ }
+};
+
+
+ROM_START( namco_asca5 )
+ ROM_REGION( 0x040000, "iocpu", 0 )
+ ROM_LOAD( "asc5_io-a.ic14", 0x000000, 0x020000, CRC(5964767f) SHA1(320db5e78ae23c5f94e368432d51573b409995db) )
+ROM_END
+
+class namco_asca_5_device :
+ public namco_asca_3_device
+{
+public:
+ namco_asca_5_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock = 0) :
+ namco_asca_3_device(mconfig, NAMCO_ASCA5, tag, owner, clock)
+ {
+ }
+
+protected:
+ // device_t
+ virtual const tiny_rom_entry *device_rom_region() const override ATTR_COLD
+ {
+ return ROM_NAME(namco_asca5);
+ }
+};
+
+
+ROM_START( namco_emio102 )
+ ROM_REGION( 0x040000, "iocpu", 0 )
+ ROM_LOAD( "th1io-a.4f", 0x000000, 0x040000, CRC(1cbbce27) SHA1(71d61d9218543e1b0b2a6c550a8ff2b7c6267257) )
+ROM_END
+
+class namco_em_io1_02_device :
+ public namco_asca_1_device
+{
+public:
+ namco_em_io1_02_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock = 0) :
+ namco_asca_1_device(mconfig, NAMCO_EMIO102, tag, owner, clock)
+ {
+ }
+
+protected:
+ // device_t
+ virtual const tiny_rom_entry *device_rom_region() const override ATTR_COLD
+ {
+ return ROM_NAME(namco_emio102);
+ }
+
+ virtual void device_start() override ATTR_COLD
+ {
+ namco_c78_jvs_io_device::device_start();
+
+ save_item(NAME(m_multiplexed_output));
+ }
+
+ virtual void output_w(offs_t offset, uint8_t data) override
+ {
+ if (m_multiplexed_output[offset] != data)
+ {
+ m_multiplexed_output[offset] = data;
+
+ if (m_multiplexed_output[1] < 3)
+ {
+ int shift = m_multiplexed_output[1] == 2 ? 16 :
+ m_multiplexed_output[1] == 0 ? 8 : 0;
+
+ uint64_t output = (m_output & ~(0xff << shift)) | (m_multiplexed_output[0] << shift);
+
+ if (m_output != output)
+ {
+ LOGOUTPUT("output_w %06x\n", output);
+ m_output_cb(0, output, output ^ m_output);
+ m_output = output;
+ }
+ }
+ }
+ }
+
+ uint8_t m_multiplexed_output[2];
+};
+
+
+static INPUT_PORTS_START(namco_tssio)
+ PORT_INCLUDE(namco_c78_io)
+
+ PORT_START("SW")
+ PORT_BIT(0x01, IP_ACTIVE_LOW, IPT_BUTTON7) PORT_NAME("Unknown (SW2:unpopulated)")
+ PORT_BIT(0x02, IP_ACTIVE_LOW, IPT_BUTTON8) PORT_NAME("Service (SW3:unpopulated)")
+INPUT_PORTS_END
+
+static INPUT_PORTS_START(namco_tssio_default)
+ PORT_INCLUDE(namco_tssio)
+
+ PORT_START("SYSTEM")
+ PORT_SERVICE(0x80, IP_ACTIVE_HIGH)
+
+ PORT_START("PLAYER1")
+ PORT_BIT(0x00000040, IP_ACTIVE_HIGH, IPT_SERVICE1)
+ PORT_BIT(0x00000020, IP_ACTIVE_HIGH, IPT_JOYSTICK_UP)
+ PORT_BIT(0x00000010, IP_ACTIVE_HIGH, IPT_JOYSTICK_DOWN)
+ PORT_BIT(0x00000002, IP_ACTIVE_HIGH, IPT_BUTTON1)
+ PORT_BIT(0x00000001, IP_ACTIVE_HIGH, IPT_BUTTON2)
+ PORT_BIT(0x00008000, IP_ACTIVE_HIGH, IPT_BUTTON3)
+ PORT_BIT(0x00004000, IP_ACTIVE_HIGH, IPT_BUTTON4)
+ PORT_BIT(0x00002000, IP_ACTIVE_HIGH, IPT_BUTTON5)
+ PORT_BIT(0x00001000, IP_ACTIVE_HIGH, IPT_BUTTON6)
+
+ PORT_START("COIN1")
+ PORT_BIT(0x01, IP_ACTIVE_HIGH, IPT_COIN1)
+ PORT_BIT(0x80, IP_ACTIVE_HIGH, IPT_TILT2) PORT_NAME("Counter disconnected")
+
+ PORT_START("SCREEN_POSITION_INPUT_X1") // tuned for CRT
+ PORT_BIT(0xfff, 91 + 733 / 2, IPT_LIGHTGUN_X) PORT_CROSSHAIR(X, 1.0, 0.0, 0) PORT_MINMAX(91, 91 + 733) PORT_SENSITIVITY(100) PORT_KEYDELTA(12)
+
+ PORT_START("SCREEN_POSITION_INPUT_Y1") // tuned for CRT - can't shoot below the statusbar?
+ PORT_BIT(0xfff, 38 + 247 / 2, IPT_LIGHTGUN_Y) PORT_CROSSHAIR(Y, 1.0, 0.0, 0) PORT_MINMAX(38, 38 + 247) PORT_SENSITIVITY(100) PORT_KEYDELTA(4)
+INPUT_PORTS_END
+
+ROM_START( namco_tssio )
+ ROM_REGION( 0x040000, "iocpu", 0 )
+ ROM_LOAD( "tssioprog.ic3", 0x000000, 0x040000, CRC(edad4538) SHA1(1330189184a636328d956c0e435f8d9ad2e96a80) )
+ROM_END
+
+class namco_tss_io_device :
+ public namco_c78_jvs_io_device
+{
+public:
+ namco_tss_io_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock = 0) :
+ namco_tss_io_device(mconfig, NAMCO_TSSIO, tag, owner, clock)
+ {
+ }
+
+protected:
+ namco_tss_io_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock = 0) :
+ namco_c78_jvs_io_device(mconfig, type, tag, owner, clock),
+ m_sw(*this, "SW"),
+ m_output(0)
+ {
+ }
+
+ // device_t
+ virtual void device_add_mconfig(machine_config &config) override ATTR_COLD
+ {
+ namco_c78_jvs_io_device::device_add_mconfig(config);
+
+ m_iocpu->read_port8().set(FUNC(namco_tss_io_device::iocpu_port_8_r));
+ m_iocpu->write_port8().set(FUNC(namco_tss_io_device::iocpu_port_8_w));
+ m_iocpu->write_port9().set(FUNC(namco_tss_io_device::iocpu_port_9_w));
+ }
+
+ virtual ioport_constructor device_input_ports() const override ATTR_COLD
+ {
+ return m_default_inputs ? INPUT_PORTS_NAME(namco_tssio_default) : INPUT_PORTS_NAME(namco_tssio);
+ }
+
+ virtual const tiny_rom_entry *device_rom_region() const override ATTR_COLD
+ {
+ return ROM_NAME(namco_tssio);
+ }
+
+ virtual void device_start() override ATTR_COLD
+ {
+ namco_c78_jvs_io_device::device_start();
+
+ save_item(NAME(m_output));
+ }
+
+ // namco_c78_jvs_io_device
+ virtual void iocpu_program_map(address_map &map) override
+ {
+ namco_c78_jvs_io_device::iocpu_program_map(map);
+
+ map(0x6000, 0x6001).r(FUNC(namco_tss_io_device::in_r));
+ map(0x6002, 0x6002).w(FUNC(namco_tss_io_device::output_w));
+ map(0x7000, 0x7005).r(FUNC(namco_tss_io_device::gun_r));
+ map(0x7007, 0x7007).r(FUNC(namco_tss_io_device::gun_ack_r)); // guessed, result ignored
+ }
+
+ virtual uint8_t iocpu_port_6_r() override
+ {
+ return (1 << 7) | // Altera:75 (unknown input)
+ (3 << 5) | // coin counter output
+ ((BIT(~player_r(0, 0x40), 6) & BIT(m_sw->read(), 1)) << 4) | // SW3
+ (3 << 2) | // LED (unemulated)
+ (BIT(m_dsw->read(), 2) << 1) | // SW1:2
+ (BIT(m_sw->read(), 0) << 0); // SW2
+ }
+
+ uint8_t iocpu_port_8_r()
+ {
+ return (1 << 7) | // pin not bonded
+ (1 << 6) | // pullup VCC (maybe in case IRQ5 becomes enabled?)
+ (1 << 5) | // J6:2 (configured for RxD1)
+ (1 << 4) | // J6:3 (configured for TxD1)
+ (15 << 0); // A13/A12/A11/A10 (unemulated input)
+ }
+
+ void iocpu_port_8_w(uint8_t data)
+ {
+ }
+
+ virtual uint8_t iocpu_port_9_r() override
+ {
+ return (1 << 7) | // Altera:74 (unknown input)
+ (1 << 6) | // NC (system clock output)
+ (7 << 3) | // Altera (unknown output)
+ (3 << 1) | // Altera (unknown input)
+ (BIT(m_dsw->read(), 3) << 0); // SW1:1/J6:11/Altera
+ }
+
+ void iocpu_port_9_w(uint8_t data)
+ {
+ }
+
+ uint8_t gun_r(offs_t offset)
+ {
+ uint16_t data = (offset % 3) == 0 ? screen_position_x_r(0) :
+ (offset % 3) == 1 ? screen_position_y_r(0) : // ystart
+ screen_position_y_r(0) + 1;// yend
+ return (offset < 3) ? data & 0xff : data >> 8;
+ }
+
+ uint8_t gun_ack_r()
+ {
+ return 0x00;
+ }
+
+ uint8_t in_r(offs_t offset)
+ {
+ if (offset == 0)
+ {
+ const auto system = system_r(0x80);
+ const auto p1 = player_r(0, 0x32);
+ const auto c1 = coin_r(0, 0x81);
+
+ return ~((BIT(p1, 1) << 7) | // BUTTON1
+ (BIT(p1, 4) << 6) | // DOWN
+ (BIT(p1, 5) << 5) | // UP
+ (BIT(system, 7) << 4) | // TEST
+ (0 << 3) | // unknown input
+ (BIT(~c1, 7) << 2) | // counter disconnected
+ (0 << 1) | // unknown input
+ (BIT(c1, 0) << 0)); // COIN
+ }
+ else if (offset == 1)
+ {
+ const auto p1 = player_r(0, 0xf001);
+
+ return ~((BIT(p1, 12) << 4) | // BUTTON6
+ (BIT(p1, 13) << 3) | // BUTTON5
+ (BIT(p1, 14) << 2) | // BUTTON4
+ (BIT(p1, 15) << 1) | // BUTTON3
+ (BIT(p1, 0) << 0)); // BUTTON2
+ }
+
+ return 0xff;
+ }
+
+ void output_w(uint8_t data)
+ {
+ data = bitswap<3>(data, 0, 1, 2) << 5;
+ if (m_output != data)
+ {
+ LOGOUTPUT("output_w %02x\n", data);
+ m_output_cb(0, data, data ^ m_output);
+ m_output = data;
+ }
+ }
+
+ required_ioport m_sw;
+ uint8_t m_output;
+};
+
+
+static INPUT_PORTS_START(namco_csz1_default)
+ PORT_INCLUDE(namco_tssio_default)
+
+ PORT_MODIFY("SCREEN_POSITION_INPUT_X1")
+ PORT_BIT(0xfff, 0x1bf, IPT_LIGHTGUN_X) PORT_CROSSHAIR(X, 1.0, 0.0, 0) PORT_MINMAX(0x040, 0x33f) PORT_SENSITIVITY(100) PORT_KEYDELTA(12)
+
+ PORT_MODIFY("SCREEN_POSITION_INPUT_Y1")
+ PORT_BIT(0xfff, 0x08f, IPT_LIGHTGUN_Y) PORT_CROSSHAIR(Y, 1.0, 0.0, 0) PORT_MINMAX(0x020, 0x0ff) PORT_SENSITIVITY(100) PORT_KEYDELTA(4)
+INPUT_PORTS_END
+
+ROM_START( namco_csz1 )
+ ROM_REGION( 0x040000, "iocpu", 0 )
+ ROM_LOAD( "csz1prg0a.8f", 0x000000, 0x020000, CRC(8edc36b3) SHA1(b5df211988d856572fcc313480e693c8561784e4) )
+ ROM_FILL( 0x04ed, 1, 0x05 ) // HACK: Increase timeout from 4
+ROM_END
+
+class namco_csz1_device :
+ public namco_tss_io_device
+{
+public:
+ namco_csz1_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock = 0) :
+ namco_tss_io_device(mconfig, NAMCO_CSZ1, tag, owner, clock)
+ {
+ }
+
+protected:
+ // device_t
+ virtual ioport_constructor device_input_ports() const override ATTR_COLD
+ {
+ return m_default_inputs ? INPUT_PORTS_NAME(namco_csz1_default) : namco_tss_io_device::device_input_ports();
+ }
+
+ virtual const tiny_rom_entry *device_rom_region() const override ATTR_COLD
+ {
+ return ROM_NAME(namco_csz1);
+ }
+
+ virtual void device_start() override ATTR_COLD
+ {
+ namco_tss_io_device::device_start();
+
+ m_analog_output = 0;
+
+ save_item(NAME(m_analog_output));
+ }
+
+ // namco_c78_jvs_io_device
+ virtual void iocpu_program_map(address_map &map) override
+ {
+ namco_tss_io_device::iocpu_program_map(map);
+
+ map(0x6003, 0x6003).w(FUNC(namco_csz1_device::analog_output_w));
+ }
+
+ void analog_output_w(uint8_t data)
+ {
+ if (m_analog_output != data)
+ {
+ m_analog_output = data;
+ LOGOUTPUT("analog_output_w %04x\n", data * 0x101);
+ m_analog_output_cb[0](data * 0x101);
+ }
+ }
+
+ uint8_t m_analog_output;
+};
+
+
+ROM_START( namco_xmiu1 )
+ ROM_REGION( 0x040000, "iocpu", 0 )
+ ROM_LOAD( "csz1prg0a.8f", 0x000000, 0x040000, CRC(bb112fe0) SHA1(6fa5dc81d258137c1b1ad427d49d136d0bbf53fa) )
+ROM_END
+
+class namco_xmiu1_device :
+ public namco_tss_io_device
+{
+public:
+ namco_xmiu1_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock = 0) :
+ namco_tss_io_device(mconfig, NAMCO_XMIU1, tag, owner, clock)
+ {
+ }
+
+protected:
+ // device_t
+ virtual const tiny_rom_entry *device_rom_region() const override ATTR_COLD
+ {
+ return ROM_NAME(namco_xmiu1);
+ }
+};
+
+
+ROM_START( namco_fca11 )
+ ROM_REGION( 0x040000, "iocpu2", 0 ) // 256KB internal flash ROM
+ ROM_LOAD( "fcaf11.ic4", 0x030000, 0x010000, CRC(13d936df) SHA1(fbb2191263b2b326f1f49729767ee6fae2db21f7) ) // almost good dump, all JVS related code and data is in place
+ ROM_FILL( 0x000000, 0x034000, 0x67 ) // dump was made from $0000 to $ffff, not $fc0000. The ROM only appears in memory from $4000-$ffff
+
+ ROM_REGION( 0x040000, "iocpu", 0 )
+ ROM_LOAD( "asc3_io-c.ic14", 0x000000, 0x020000, CRC(2f272a7b) SHA1(9d7ebe274c0d26f5f38747224d42d0375e2ed14c) )
+ ROM_COPY( "iocpu2", 0x039040, 0x001082, 0x00003b ) // patch ASCA3 ROM to report FCA11 description
+
+ ROM_REGION( 0x10000, "pic", 0 ) // I/O board PIC16F84 code
+ ROM_LOAD( "fcap11.ic2", 0x000000, 0x004010, CRC(1b2592ce) SHA1(a1a487361053af564f6ec67e545413e370a3b38c) )
+ROM_END
+
+class namco_fca_11_device :
+ public namco_asca_3_device
+{
+public:
+ namco_fca_11_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock = 0) :
+ namco_fca_11_device(mconfig, NAMCO_FCA11, tag, owner, clock)
+ {
+ }
+
+protected:
+ namco_fca_11_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock) :
+ namco_asca_3_device(mconfig, type, tag, owner, clock),
+ m_iocpu2(*this, "iocpu2")
+ {
+ }
+
+ // device_t
+ virtual void device_add_mconfig(machine_config &config) override ATTR_COLD
+ {
+ namco_asca_3_device::device_add_mconfig(config);
+
+ MB90F574(config, m_iocpu2, 4.9152_MHz_XTAL);
+ m_iocpu2->set_addrmap(AS_PROGRAM, &namco_fca_11_device::iocpu2_program_map);
+ }
+
+ virtual const tiny_rom_entry *device_rom_region() const override ATTR_COLD
+ {
+ return ROM_NAME(namco_fca11);
+ }
+
+ virtual void device_reset() override ATTR_COLD
+ {
+ namco_asca_3_device::device_reset();
+
+ m_iocpu2->set_input_line(INPUT_LINE_RESET, ASSERT_LINE);
+ }
+
+ // device_jvs_interface
+ virtual void rxd(int state) override
+ {
+ namco_asca_3_device::rxd(state);
+
+ m_iocpu2->uart<1>().sin(state);
+ }
+
+ void iocpu2_program_map(address_map &map)
+ {
+ map(0x004000, 0x00ffff).rom().region("iocpu2", 0x034000);
+ map(0xfc0000, 0xffffff).rom().region("iocpu2", 0);
+ }
+
+ required_device<mb90f574_device> m_iocpu2;
+};
+
+
+ROM_START( namco_fca10 )
+ ROM_REGION( 0x040000, "iocpu2", ROMREGION_ERASE00 ) // 256KB internal flash ROM
+ ROM_LOAD( "fcaf10.bin", 0x000000, 0x040000, NO_DUMP )
+
+ ROM_REGION( 0x040000, "iocpu", 0 )
+ ROM_LOAD( "asc3_io-c.ic14", 0x000000, 0x020000, CRC(2f272a7b) SHA1(9d7ebe274c0d26f5f38747224d42d0375e2ed14c) )
+
+ ROM_REGION( 0x10000, "pic", 0 ) // I/O board PIC16F84 code
+ ROM_LOAD( "fcap10.ic2", 0x000000, 0x004010, NO_DUMP )
+ROM_END
+
+class namco_fca_10_device :
+ public namco_fca_11_device
+{
+public:
+ namco_fca_10_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock = 0) :
+ namco_fca_11_device(mconfig, NAMCO_FCA10, tag, owner, clock)
+ {
+ }
+
+protected:
+ // device_t
+ virtual const tiny_rom_entry *device_rom_region() const override ATTR_COLD
+ {
+ return ROM_NAME(namco_fca10);
+ }
+
+ virtual void device_start() override ATTR_COLD
+ {
+ namco_fca_11_device::device_start();
+
+ // patch ASCA3 ROM to report FCA10 description
+ auto iocpu = memregion("iocpu")->base();
+ for (int i = 0; i < 0x30; i++)
+ iocpu[BYTE_XOR_BE(i + 0x108d)] = "FCA-1;Ver1.00;JPN,Multipurpose + Rotary Encoder"[i];
+ }
+};
+
+
+ROM_START( namco_fcb )
+ ROM_REGION( 0x040000, "iocpu2", 0 ) // 256KB internal flash ROM
+ ROM_LOAD( "fcb1_io-0b.ic4", 0x034000, 0x00c000, BAD_DUMP CRC(5e25b73f) SHA1(fa805a422ff8793989b0ce901cc868ec1a87c7ac) ) // most JVS handling code is in undumped area
+ ROM_FILL( 0x000000, 0x034000, 0x67 ) // dump was made from $0000 to $ffff, not $fc0000. The ROM only appears in memory from $4000-$ffff
+
+ ROM_REGION( 0x040000, "iocpu", 0 )
+ ROM_LOAD( "asc3_io-c.ic14", 0x000000, 0x020000, CRC(2f272a7b) SHA1(9d7ebe274c0d26f5f38747224d42d0375e2ed14c) )
+ ROM_COPY( "iocpu2", 0x03436a, 0x001082, 0x00003b ) // patch ASCA3 ROM to report FCB description
+
+ ROM_REGION( 0x10000, "pic", 0 ) // I/O board PIC16F84 code
+ ROM_LOAD( "fcb_pic", 0x000000, 0x004010, NO_DUMP )
+ROM_END
+
+class namco_fcb_device :
+ public namco_fca_11_device
+{
+public:
+ namco_fcb_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock = 0) :
+ namco_fca_11_device(mconfig, NAMCO_FCB, tag, owner, clock)
+ {
+ }
+
+protected:
+ // device_t
+ virtual const tiny_rom_entry *device_rom_region() const override ATTR_COLD
+ {
+ return ROM_NAME(namco_fcb);
+ }
+};
+
+
+class namco_em_pri1_01_device :
+ public jvs_hle_device
+{
+public:
+ namco_em_pri1_01_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock = 0) :
+ jvs_hle_device(mconfig, NAMCO_EMPRI101, tag, owner, clock)
+ {
+ }
+
+ // device_t
+ static constexpr feature_type imperfect_features() { return feature::PRINTER; }
+
+ virtual void device_add_mconfig(machine_config &config) override ATTR_COLD
+ {
+ add_jvs_port(config);
+ }
+
+ // jvs_hle_device
+ virtual const char *device_id() override
+ {
+ return "namco ltd.;EM Pri1-01;Ver2.00;JPN&EXP,Techno-Drive PRN";
+ }
+
+ virtual void execute(uint8_t command) override
+ {
+ const uint8_t *parameters;
+ uint8_t *response;
+
+ switch (command)
+ {
+ case 0x72:
+ if (consume(1, parameters))
+ {
+ switch (parameters[0])
+ {
+ case 0x01: // initialise?
+ if (produce(1, response))
+ response[0] = ReportCode::Normal;
+ break;
+
+ case 0x02: // end transmit?
+ if (produce(1, response))
+ response[0] = ReportCode::Normal;
+ break;
+
+ case 0x03: // get status
+ if (produce(2, response))
+ {
+ response[0] = ReportCode::Normal;
+ response[1] = 0x01; // 1=ok/2=busy/4=paper empty
+ }
+ break;
+
+ case 0x04: // begin transmit?
+ if (produce(1, response))
+ response[0] = ReportCode::Normal;
+ break;
+
+ case 0x05: // end of print job?
+ if (consume(1, parameters) && produce(1, response))
+ response[0] = (parameters[0] == 1) ? ReportCode::Normal : ReportCode::InvalidParameter;
+ break;
+
+ case 0x07: // transmit data
+ if (consume(1, parameters))
+ {
+ uint8_t length = parameters[0];
+
+ if (consume(length, parameters) && produce(1, response))
+ response[0] = ReportCode::Normal;
+ }
+ break;
+
+ default:
+ status_code(StatusCode::UnknownCommand);
+ break;
+ }
+ }
+ break;
+
+ default:
+ jvs_hle_device::execute(command);
+ break;
+ }
+ }
+};
+
+} // anonymous namespace
+
+
+DEFINE_DEVICE_TYPE(NAMCO_AMC, namco_amc_device, "namco_amc", "Namco AMC PCB (Extra I/O,JPN,Ver1.10)")
+DEFINE_DEVICE_TYPE_PRIVATE(NAMCO_ASCA1, device_jvs_interface, namco_asca_1_device, "namco_asca1", "Namco ASCA-1 (Multipurpose I/O,JPN,Ver2.00)")
+DEFINE_DEVICE_TYPE_PRIVATE(NAMCO_ASCA3, device_jvs_interface, namco_asca_3_device, "namco_asca3", "Namco ASCA-3 (Multipurpose + Rotary Encoder,JPN,Ver2.04)")
+DEFINE_DEVICE_TYPE_PRIVATE(NAMCO_ASCA3A, device_jvs_interface, namco_asca_3a_device, "namco_asca3a", "Namco ASCA-3 (Multipurpose + Rotary Encoder,JPN,Ver2.02)")
+DEFINE_DEVICE_TYPE_PRIVATE(NAMCO_ASCA5, device_jvs_interface, namco_asca_5_device, "namco_asca5", "Namco ASCA-5 (Multipurpose,JPN,Ver2.09)")
+DEFINE_DEVICE_TYPE_PRIVATE(NAMCO_CSZ1, device_jvs_interface, namco_csz1_device, "namco_csz1", "Namco CSZ1 MIU-I/O (GUN-EXTENTION,JPN,Ver2.05)")
+DEFINE_DEVICE_TYPE_PRIVATE(NAMCO_EMIO102, device_jvs_interface, namco_em_io1_02_device, "namco_emio102", "Namco EM I/O1-02 (Techno-Drive I/O,JPN&EXP,Ver2.00)")
+DEFINE_DEVICE_TYPE_PRIVATE(NAMCO_EMPRI101, device_jvs_interface, namco_em_pri1_01_device, "namco_empri101", "Namco EM Pri1-01")
+DEFINE_DEVICE_TYPE_PRIVATE(NAMCO_FCA10, device_jvs_interface, namco_fca_10_device, "namco_fca10", "Namco FCA-1 (Multipurpose + Rotary Encoder,JPN,Ver1.00)")
+DEFINE_DEVICE_TYPE_PRIVATE(NAMCO_FCA11, device_jvs_interface, namco_fca_11_device, "namco_fca11", "Namco FCA-1 (Multipurpose + Rotary Encoder,JPN,Ver1.01)")
+DEFINE_DEVICE_TYPE_PRIVATE(NAMCO_FCB, device_jvs_interface, namco_fcb_device, "namco_fcb", "Namco FCB (TouchPanel&Multipurpose,JPN,Ver1.02)")
+DEFINE_DEVICE_TYPE_PRIVATE(NAMCO_TSSIO, device_jvs_interface, namco_tss_io_device, "namco_tssio", "Namco TSS-I/O (GUN-EXTENTION,JPN,Ver2.02)")
+DEFINE_DEVICE_TYPE_PRIVATE(NAMCO_XMIU1, device_jvs_interface, namco_xmiu1_device, "namco_xmiu1", "Namco XMIU1 TSS-I/O (GUN-EXTENTION,JPN,Ver2.11,Ver2.12)")
diff --git a/src/devices/bus/jvs/namcoio.h b/src/devices/bus/jvs/namcoio.h
new file mode 100644
index 00000000000..c3d38ff8bb1
--- /dev/null
+++ b/src/devices/bus/jvs/namcoio.h
@@ -0,0 +1,73 @@
+// license:BSD-3-Clause
+// copyright-holders:smf
+
+#ifndef MAME_BUS_JVS_NAMCOIO_H
+#define MAME_BUS_JVS_NAMCOIO_H
+
+#pragma once
+
+#include "jvs.h"
+#include "bus/rs232/rs232.h"
+#include "cpu/f2mc16/mb90610a.h"
+#include "cpu/h8/h83337.h"
+
+class namco_amc_device :
+ public device_t,
+ public device_jvs_interface,
+ public device_rs232_port_interface
+{
+public:
+ namco_amc_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock = 0);
+
+ void clear_output(int state);
+ int unknown_output();
+
+ static constexpr DEVICE_INPUT_DEFAULTS_START(dsw_rs232)
+ DEVICE_INPUT_DEFAULTS("DSW", 0x08, 0x00)
+ DEVICE_INPUT_DEFAULTS_END
+
+protected:
+ // device_t
+ virtual void device_add_mconfig(machine_config &config) override ATTR_COLD;
+ virtual ioport_constructor device_input_ports() const override ATTR_COLD;
+ virtual const tiny_rom_entry *device_rom_region() const override ATTR_COLD;
+ virtual void device_start() override ATTR_COLD;
+
+ // device_jvs_interface
+ virtual void rxd(int state) override;
+
+ // device_rs232_port_interface
+ virtual void input_txd(int state) override;
+
+ virtual void iocpu_program_map(address_map &map);
+
+ template<int N> uint16_t adc_r();
+ void update_analog_output0();
+ template<unsigned N> void analog_output_w(uint8_t data);
+
+ required_device<mb90611a_device> m_iocpu;
+ std::array<uint8_t, 2> m_analog_output;
+ uint8_t m_clear_output;
+ uint8_t m_output;
+ uint8_t m_ppg_duty;
+ uint8_t m_ppg_flags;
+ uint8_t m_sense_latch;
+ uint8_t m_unknown_output;
+};
+
+
+DECLARE_DEVICE_TYPE(NAMCO_AMC, namco_amc_device)
+DECLARE_DEVICE_TYPE(NAMCO_ASCA1, device_jvs_interface)
+DECLARE_DEVICE_TYPE(NAMCO_ASCA3, device_jvs_interface)
+DECLARE_DEVICE_TYPE(NAMCO_ASCA3A, device_jvs_interface)
+DECLARE_DEVICE_TYPE(NAMCO_ASCA5, device_jvs_interface)
+DECLARE_DEVICE_TYPE(NAMCO_CSZ1, device_jvs_interface)
+DECLARE_DEVICE_TYPE(NAMCO_EMIO102, device_jvs_interface)
+DECLARE_DEVICE_TYPE(NAMCO_EMPRI101, device_jvs_interface)
+DECLARE_DEVICE_TYPE(NAMCO_FCA10, device_jvs_interface)
+DECLARE_DEVICE_TYPE(NAMCO_FCA11, device_jvs_interface)
+DECLARE_DEVICE_TYPE(NAMCO_FCB, device_jvs_interface)
+DECLARE_DEVICE_TYPE(NAMCO_TSSIO, device_jvs_interface)
+DECLARE_DEVICE_TYPE(NAMCO_XMIU1, device_jvs_interface)
+
+#endif
diff --git a/src/devices/bus/kc/d002.cpp b/src/devices/bus/kc/d002.cpp
index 03dc9fb8f3b..f11dfe327c5 100644
--- a/src/devices/bus/kc/d002.cpp
+++ b/src/devices/bus/kc/d002.cpp
@@ -11,6 +11,8 @@
#include "emu.h"
#include "d002.h"
+#include "machine/input_merger.h"
+
#include "ram.h"
#include "rom.h"
#include "d004.h"
@@ -50,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);
}
@@ -111,33 +113,39 @@ void kc_d002_device::device_reset()
void kc_d002_device::device_add_mconfig(machine_config &config)
{
+ INPUT_MERGER_ANY_HIGH(config, "irq").output_handler().set(FUNC(kc_d002_device::out_irq_w));
+ INPUT_MERGER_ANY_HIGH(config, "nmi").output_handler().set(FUNC(kc_d002_device::out_nmi_w));
+ INPUT_MERGER_ANY_HIGH(config, "halt").output_handler().set(FUNC(kc_d002_device::out_halt_w));
+
KCCART_SLOT(config, m_expansions[0], kc85_cart, nullptr);
- m_expansions[0]->set_next_slot("m4");
- m_expansions[0]->irq().set(FUNC(kc_d002_device::out_irq_w));
- m_expansions[0]->nmi().set(FUNC(kc_d002_device::out_nmi_w));
- m_expansions[0]->halt().set(FUNC(kc_d002_device::out_halt_w));
+ m_expansions[0]->set_next_slot(m_expansions[1]);
+ m_expansions[0]->irq().set("irq", FUNC(input_merger_device::in_w<0>));
+ m_expansions[0]->nmi().set("nmi", FUNC(input_merger_device::in_w<0>));
+ m_expansions[0]->halt().set("halt", FUNC(input_merger_device::in_w<0>));
+
KCCART_SLOT(config, m_expansions[1], kc85_cart, nullptr);
- m_expansions[1]->set_next_slot("m8");
- m_expansions[1]->irq().set(FUNC(kc_d002_device::out_irq_w));
- m_expansions[1]->nmi().set(FUNC(kc_d002_device::out_nmi_w));
- m_expansions[1]->halt().set(FUNC(kc_d002_device::out_halt_w));
+ m_expansions[1]->set_next_slot(m_expansions[2]);
+ m_expansions[1]->irq().set("irq", FUNC(input_merger_device::in_w<1>));
+ m_expansions[1]->nmi().set("nmi", FUNC(input_merger_device::in_w<1>));
+ m_expansions[1]->halt().set("halt", FUNC(input_merger_device::in_w<1>));
+
KCCART_SLOT(config, m_expansions[2], kc85_cart, nullptr);
- m_expansions[2]->set_next_slot("mc");
- m_expansions[2]->irq().set(FUNC(kc_d002_device::out_irq_w));
- m_expansions[2]->nmi().set(FUNC(kc_d002_device::out_nmi_w));
- m_expansions[2]->halt().set(FUNC(kc_d002_device::out_halt_w));
+ m_expansions[2]->set_next_slot(m_expansions[3]);
+ m_expansions[2]->irq().set("irq", FUNC(input_merger_device::in_w<2>));
+ m_expansions[2]->nmi().set("nmi", FUNC(input_merger_device::in_w<2>));
+ m_expansions[2]->halt().set("halt", FUNC(input_merger_device::in_w<2>));
+
KCCART_SLOT(config, m_expansions[3], kc85_cart, nullptr);
- m_expansions[3]->set_next_slot("exp");
- m_expansions[3]->irq().set(FUNC(kc_d002_device::out_irq_w));
- m_expansions[3]->nmi().set(FUNC(kc_d002_device::out_nmi_w));
- m_expansions[3]->halt().set(FUNC(kc_d002_device::out_halt_w));
+ m_expansions[3]->set_next_slot(m_expansions[4]);
+ m_expansions[3]->irq().set("irq", FUNC(input_merger_device::in_w<3>));
+ m_expansions[3]->nmi().set("nmi", FUNC(input_merger_device::in_w<3>));
+ m_expansions[3]->halt().set("halt", FUNC(input_merger_device::in_w<3>));
// expansion interface
KCCART_SLOT(config, m_expansions[4], kc85_exp, nullptr);
- m_expansions[4]->set_next_slot(nullptr);
- m_expansions[4]->irq().set(FUNC(kc_d002_device::out_irq_w));
- m_expansions[4]->nmi().set(FUNC(kc_d002_device::out_nmi_w));
- m_expansions[4]->halt().set(FUNC(kc_d002_device::out_halt_w));
+ m_expansions[4]->irq().set("irq", FUNC(input_merger_device::in_w<4>));
+ m_expansions[4]->nmi().set("nmi", FUNC(input_merger_device::in_w<4>));
+ m_expansions[4]->halt().set("halt", FUNC(input_merger_device::in_w<4>));
}
//-------------------------------------------------
@@ -218,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..08685641c1f 100644
--- a/src/devices/bus/kc/d002.h
+++ b/src/devices/bus/kc/d002.h
@@ -23,25 +23,25 @@ public:
protected:
// device-level overrides
- virtual void device_start() override;
- virtual void device_reset() override;
+ virtual void device_start() override ATTR_COLD;
+ virtual void device_reset() override ATTR_COLD;
// optional information overrides
- virtual void device_add_mconfig(machine_config &config) override;
- virtual ioport_constructor device_input_ports() const override;
+ virtual void device_add_mconfig(machine_config &config) override ATTR_COLD;
+ virtual ioport_constructor device_input_ports() const override ATTR_COLD;
// kcexp_interface overrides
virtual void read(offs_t offset, uint8_t &data) override;
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 f07b6de1695..3d129baaf3e 100644
--- a/src/devices/bus/kc/d004.cpp
+++ b/src/devices/bus/kc/d004.cpp
@@ -52,9 +52,11 @@ void kc_d004_gide_device::kc_d004_gide_io(address_map &map)
map(0x00fc, 0x00ff).mirror(0xff00).rw(Z80CTC_TAG, FUNC(z80ctc_device::read), FUNC(z80ctc_device::write));
}
-FLOPPY_FORMATS_MEMBER( kc_d004_device::floppy_formats )
- FLOPPY_KC85_FORMAT
-FLOPPY_FORMATS_END
+void kc_d004_device::floppy_formats(format_registration &fr)
+{
+ fr.add_mfm_containers();
+ fr.add(FLOPPY_KC85_FORMAT);
+}
static void kc_d004_floppies(device_slot_interface &device)
{
@@ -129,7 +131,7 @@ void kc_d004_device::device_start()
{
m_rom = memregion(Z80_TAG)->base();
- m_reset_timer = timer_alloc(TIMER_RESET);
+ m_reset_timer = timer_alloc(FUNC(kc_d004_device::reset_tick), this);
}
//-------------------------------------------------
@@ -183,17 +185,12 @@ const tiny_rom_entry *kc_d004_device::device_rom_region() const
}
//-------------------------------------------------
-// device_timer - handler timer events
+// reset_tick - reset the main CPU when needed
//-------------------------------------------------
-void kc_d004_device::device_timer(emu_timer &timer, device_timer_id id, int param, void *ptr)
+TIMER_CALLBACK_MEMBER(kc_d004_device::reset_tick)
{
- switch(id)
- {
- case TIMER_RESET:
- m_cpu->set_input_line(INPUT_LINE_RESET, ASSERT_LINE);
- break;
- }
+ m_cpu->set_input_line(INPUT_LINE_RESET, ASSERT_LINE);
}
/*-------------------------------------------------
@@ -301,7 +298,7 @@ void kc_d004_device::io_write(offs_t offset, uint8_t data)
// FDC emulation
//**************************************************************************
-READ8_MEMBER(kc_d004_device::hw_input_gate_r)
+uint8_t kc_d004_device::hw_input_gate_r()
{
/*
bit 7: DMA Request (DRQ from FDC)
@@ -327,7 +324,7 @@ READ8_MEMBER(kc_d004_device::hw_input_gate_r)
return hw_input_gate;
}
-WRITE8_MEMBER(kc_d004_device::fdd_select_w)
+void kc_d004_device::fdd_select_w(uint8_t data)
{
if (data & 0x01)
m_floppy = m_floppy0->get_device();
@@ -346,12 +343,12 @@ WRITE8_MEMBER(kc_d004_device::fdd_select_w)
m_fdc->set_floppy(m_floppy);
}
-WRITE8_MEMBER(kc_d004_device::hw_terminal_count_w)
+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);
@@ -412,7 +409,7 @@ void kc_d004_gide_device::device_reset()
// GIDE read
//-------------------------------------------------
-READ8_MEMBER(kc_d004_gide_device::gide_r)
+uint8_t kc_d004_gide_device::gide_r(offs_t offset)
{
uint8_t data = 0xff;
uint8_t io_addr = offset & 0x0f;
@@ -440,11 +437,11 @@ READ8_MEMBER(kc_d004_gide_device::gide_r)
{
if (ide_cs == 0 )
{
- m_ata_data = m_ata->read_cs0(io_addr & 0x07);
+ m_ata_data = m_ata->cs0_r(io_addr & 0x07);
}
else
{
- m_ata_data = m_ata->read_cs1(io_addr & 0x07);
+ m_ata_data = m_ata->cs1_r(io_addr & 0x07);
}
}
@@ -461,7 +458,7 @@ READ8_MEMBER(kc_d004_gide_device::gide_r)
// GIDE write
//-------------------------------------------------
-WRITE8_MEMBER(kc_d004_gide_device::gide_w)
+void kc_d004_gide_device::gide_w(offs_t offset, uint8_t data)
{
uint8_t io_addr = offset & 0x0f;
@@ -489,11 +486,11 @@ WRITE8_MEMBER(kc_d004_gide_device::gide_w)
{
if (ide_cs == 0)
{
- m_ata->write_cs0(io_addr & 0x07, m_ata_data);
+ m_ata->cs0_w(io_addr & 0x07, m_ata_data);
}
else
{
- m_ata->write_cs1(io_addr & 0x07, m_ata_data);
+ m_ata->cs1_w(io_addr & 0x07, m_ata_data);
}
}
}
diff --git a/src/devices/bus/kc/d004.h b/src/devices/bus/kc/d004.h
index 2d4c49d2ebc..037becfb757 100644
--- a/src/devices/bus/kc/d004.h
+++ b/src/devices/bus/kc/d004.h
@@ -9,7 +9,7 @@
#include "machine/z80ctc.h"
#include "cpu/z80/z80.h"
#include "machine/upd765.h"
-#include "machine/ataintf.h"
+#include "bus/ata/ataintf.h"
#include "imagedev/floppy.h"
#include "imagedev/harddriv.h"
@@ -32,13 +32,12 @@ protected:
kc_d004_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_timer(emu_timer &timer, device_timer_id id, int param, void *ptr) override;
+ virtual void device_start() override ATTR_COLD;
+ virtual void device_reset() override ATTR_COLD;
// optional information overrides
- virtual void device_add_mconfig(machine_config &config) override;
- virtual const tiny_rom_entry *device_rom_region() const override;
+ virtual void device_add_mconfig(machine_config &config) override ATTR_COLD;
+ virtual const tiny_rom_entry *device_rom_region() const override ATTR_COLD;
// kcexp_interface overrides
virtual uint8_t module_id_r() override { return 0xa7; }
@@ -47,21 +46,21 @@ protected:
virtual void io_read(offs_t offset, uint8_t &data) override;
virtual void io_write(offs_t offset, uint8_t data) override;
- DECLARE_READ8_MEMBER(hw_input_gate_r);
- DECLARE_WRITE8_MEMBER(fdd_select_w);
- DECLARE_WRITE8_MEMBER(hw_terminal_count_w);
+ TIMER_CALLBACK_MEMBER(reset_tick);
+
+ uint8_t hw_input_gate_r();
+ void fdd_select_w(uint8_t data);
+ void hw_terminal_count_w(uint8_t data);
required_device<z80_device> m_cpu;
private:
- DECLARE_FLOPPY_FORMATS( floppy_formats );
-
- DECLARE_WRITE_LINE_MEMBER( fdc_irq );
+ static void floppy_formats(format_registration &fr);
- void kc_d004_io(address_map &map);
- void kc_d004_mem(address_map &map);
+ void fdc_irq(int state);
- static const device_timer_id TIMER_RESET = 0;
+ void kc_d004_io(address_map &map) ATTR_COLD;
+ void kc_d004_mem(address_map &map) ATTR_COLD;
required_device<upd765a_device> m_fdc;
required_device<floppy_connector> m_floppy0;
@@ -94,11 +93,11 @@ public:
protected:
// device-level overrides
- virtual void device_reset() override;
+ virtual void device_reset() override ATTR_COLD;
// optional information overrides
- virtual void device_add_mconfig(machine_config &config) override;
- virtual const tiny_rom_entry *device_rom_region() const override;
+ virtual void device_add_mconfig(machine_config &config) override ATTR_COLD;
+ virtual const tiny_rom_entry *device_rom_region() const override ATTR_COLD;
private:
required_device<ata_interface_device> m_ata;
@@ -106,10 +105,10 @@ private:
uint16_t m_ata_data;
int m_lh;
- DECLARE_READ8_MEMBER(gide_r);
- DECLARE_WRITE8_MEMBER(gide_w);
+ uint8_t gide_r(offs_t offset);
+ void gide_w(offs_t offset, uint8_t data);
- void kc_d004_gide_io(address_map &map);
+ void kc_d004_gide_io(address_map &map) ATTR_COLD;
};
// device type definition
diff --git a/src/devices/bus/kc/kc.cpp b/src/devices/bus/kc/kc.cpp
index aa9e75e1951..feed0c8995e 100644
--- a/src/devices/bus/kc/kc.cpp
+++ b/src/devices/bus/kc/kc.cpp
@@ -38,7 +38,7 @@
VCC 28 57 NC
NC 29 58 NC
- Slots are organized into a chain (MEI -> MEO) , the first module that
+ Slots are organized into a chain (MEI -> MEO), the first module that
decode the address on bus, clear the MEO line for disable other modules
with less priority.
@@ -107,7 +107,8 @@
#include "emu.h"
#include "kc.h"
-#define LOG 0
+//#define VERBOSE 1
+#include "logmacro.h"
/***************************************************************************
@@ -131,7 +132,7 @@ DEFINE_DEVICE_TYPE(KCCART_SLOT, kccart_slot_device, "kccart_slot", "KC85 Cartrid
//-------------------------------------------------
device_kcexp_interface::device_kcexp_interface(const machine_config &mconfig, device_t &device)
- : device_slot_card_interface(mconfig, device)
+ : device_interface(device, "kcexp")
{
}
@@ -159,11 +160,12 @@ kcexp_slot_device::kcexp_slot_device(const machine_config &mconfig, const char *
kcexp_slot_device::kcexp_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),
+ device_single_card_slot_interface<device_kcexp_interface>(mconfig, *this),
m_out_irq_cb(*this),
m_out_nmi_cb(*this),
m_out_halt_cb(*this),
- m_cart(nullptr), m_next_slot_tag(nullptr), m_next_slot(nullptr)
+ m_cart(nullptr),
+ m_next_slot(*this, finder_base::DUMMY_TAG)
{
}
@@ -175,19 +177,22 @@ kcexp_slot_device::~kcexp_slot_device()
{
}
+
+void kcexp_slot_device::device_validity_check(validity_checker &valid) const
+{
+ std::pair<device_t &, char const *> const next_target(m_next_slot.finder_target());
+ if ((next_target.second != finder_base::DUMMY_TAG) && !m_next_slot)
+ osd_printf_error("Next slot device %s relative to %s not found", next_target.second, next_target.first.tag());
+}
+
+
//-------------------------------------------------
// device_start - device-specific startup
//-------------------------------------------------
void kcexp_slot_device::device_start()
{
- m_cart = dynamic_cast<device_kcexp_interface *>(get_card_device());
- m_next_slot = m_next_slot_tag ? owner()->subdevice<kcexp_slot_device>(m_next_slot_tag) : nullptr;
-
- // resolve callbacks
- m_out_irq_cb.resolve_safe();
- m_out_nmi_cb.resolve_safe();
- m_out_halt_cb.resolve_safe();
+ m_cart = get_card_device();
}
@@ -260,9 +265,9 @@ 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)
{
- if (LOG) logerror("KCEXP '%s': %s MEI line\n", tag(), state != CLEAR_LINE ? "ASSERT": "CLEAR");
+ LOG("KCEXP: %s MEI line\n", state != CLEAR_LINE ? "ASSERT": "CLEAR");
if (m_cart)
m_cart->mei_w(state);
@@ -272,9 +277,9 @@ 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)
{
- if (LOG) logerror("KCEXP '%s': %s MEO line\n", tag(), state != CLEAR_LINE ? "ASSERT": "CLEAR");
+ LOG("KCEXP: %s MEO line\n", state != CLEAR_LINE ? "ASSERT": "CLEAR");
if (m_next_slot)
m_next_slot->mei_w(state);
@@ -290,7 +295,7 @@ WRITE_LINE_MEMBER( kcexp_slot_device::meo_w )
//-------------------------------------------------
kccart_slot_device::kccart_slot_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) :
kcexp_slot_device(mconfig, KCCART_SLOT, tag, owner, clock),
- device_image_interface(mconfig, *this)
+ device_cartrom_image_interface(mconfig, *this)
{
}
@@ -306,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();
@@ -327,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 0c14a8ef5d3..37cb6ee8f2a 100644
--- a/src/devices/bus/kc/kc.h
+++ b/src/devices/bus/kc/kc.h
@@ -13,7 +13,7 @@
#pragma once
-#include "softlist_dev.h"
+#include "imagedev/cartrom.h"
/***************************************************************************
TYPE DEFINITIONS
@@ -21,7 +21,7 @@
// ======================> device_kcexp_interface
-class device_kcexp_interface : public device_slot_card_interface
+class device_kcexp_interface : public device_interface
{
public:
// construction/destruction
@@ -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);
@@ -43,8 +43,7 @@ protected:
// ======================> kcexp_slot_device
-class kcexp_slot_device : public device_t,
- public device_slot_interface
+class kcexp_slot_device : public device_t, public device_single_card_slot_interface<device_kcexp_interface>
{
public:
// construction/destruction
@@ -65,7 +64,7 @@ public:
auto halt() { return m_out_halt_cb.bind(); }
// inline configuration
- void set_next_slot(const char *next_module_tag) { m_next_slot_tag = next_module_tag; }
+ template <typename T> void set_next_slot(T &&next_module_tag) { m_next_slot.set_tag(std::forward<T>(next_module_tag)); }
// reading and writing
virtual uint8_t module_id_r();
@@ -74,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;
@@ -85,18 +84,17 @@ protected:
kcexp_slot_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_validity_check(validity_checker &valid) const override;
+ virtual void device_start() override ATTR_COLD;
device_kcexp_interface* m_cart;
- const char* m_next_slot_tag;
- kcexp_slot_device* m_next_slot;
+ optional_device<kcexp_slot_device> m_next_slot;
};
// ======================> kccart_slot_device
-class kccart_slot_device : public kcexp_slot_device,
- public device_image_interface
+class kccart_slot_device : public kcexp_slot_device, public device_cartrom_image_interface
{
public:
// construction/destruction
@@ -112,20 +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;
- virtual const software_list_loader &get_software_list_loader() const override { return rom_software_list_loader::instance(); }
+ // device_image_interface implementation
+ virtual std::pair<std::error_condition, std::string> call_load() override;
- virtual iodevice_t image_type() const override { return IO_CARTSLOT; }
- virtual bool is_readable() const override { return 1; }
- virtual bool is_writeable() const override { return 0; }
- virtual bool is_creatable() const override { return 0; }
- virtual bool must_be_loaded() const override { return 0; }
- virtual bool is_reset_on_load() const override { return 1; }
- virtual const char *image_interface() const override { return "kc_cart"; }
- virtual const char *file_extensions() const override { return "bin"; }
+ 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..6ef138a477e 100644
--- a/src/devices/bus/kc/ram.h
+++ b/src/devices/bus/kc/ram.h
@@ -25,15 +25,15 @@ protected:
kc_m011_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_start() override ATTR_COLD;
+ virtual void device_reset() override ATTR_COLD;
// kcexp_interface overrides
virtual uint8_t module_id_r() override { return 0xf6; }
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;
@@ -84,7 +84,7 @@ public:
protected:
// device-level overrides
- virtual void device_reset() override;
+ virtual void device_reset() override ATTR_COLD;
// kcexp_interface overrides
virtual uint8_t module_id_r() override { return 0x79; }
@@ -109,7 +109,7 @@ public:
protected:
// device-level overrides
- virtual void device_reset() override;
+ virtual void device_reset() override ATTR_COLD;
// kcexp_interface overrides
virtual uint8_t module_id_r() override { return 0x7a; }
@@ -156,7 +156,7 @@ public:
protected:
// device-level overrides
- virtual void device_reset() override;
+ virtual void device_reset() override ATTR_COLD;
// kcexp_interface overrides
virtual uint8_t module_id_r() override { return 0x78; }
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..bc7fe31cff7 100644
--- a/src/devices/bus/kc/rom.h
+++ b/src/devices/bus/kc/rom.h
@@ -25,16 +25,16 @@ protected:
kc_8k_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 const tiny_rom_entry *device_rom_region() const override;
+ virtual void device_start() override ATTR_COLD;
+ virtual void device_reset() override ATTR_COLD;
+ virtual const tiny_rom_entry *device_rom_region() const override ATTR_COLD;
// kcexp_interface overrides
virtual uint8_t module_id_r() override { return 0xfb; }
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;
@@ -75,7 +75,7 @@ public:
protected:
// device-level overrides
- virtual void device_reset() override;
+ virtual void device_reset() override ATTR_COLD;
// kcexp_interface overrides
virtual uint8_t module_id_r() override { return 0x01; }
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..e487e193f80
--- /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 ATTR_COLD;
+ virtual void device_reset() override ATTR_COLD;
+ virtual void device_add_mconfig(machine_config &config) override ATTR_COLD;
+ virtual ioport_constructor device_input_ports() const override ATTR_COLD;
+
+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..c1ec6051d31
--- /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 ATTR_COLD;
+
+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..78ca273cc47
--- /dev/null
+++ b/src/devices/bus/kim1/kim1bus.h
@@ -0,0 +1,208 @@
+// license:BSD-3-Clause
+// copyright-holders:R. Belmont
+/***************************************************************************
+
+ kim1bus.h - KIM-1 expansion bus
+
+ Basically 6502 bus brought out to a connector.
+
+ 44-pin edge connector, 1-22 on top, A-Z on bottom
+
+ SYNC 1 A AB0
+ /RDY 2 B AB1
+ clock phase 1 3 C AB2
+ /IRQ 4 D AB3
+ RO 5 E AB4
+ /NMI 6 F AB5
+ /RES 7 H AB6
+ DB7 8 J AB7
+ DB6 9 K AB8
+ DB5 10 L AB9
+ DB4 11 M AB10
+ DB3 12 N AB11
+ DB2 13 P AB12
+ DB1 14 R AB13
+ DB0 15 S AB14
+ K6 16 T AB15
+ SST out 17 U clock phase 2
+ N/C 18 V R/W
+ N/C 19 W inverted R/W
+ N/C 20 X PLL test
+ VCC 21 Y inverted clock phase 2
+ GND 22 Z RAM R/W
+
+ * RO is connected to 6502 SO pin
+ * K6 is asserted (low) when accessing 0x1800-0x1bff (mirror 0xe000)
+
+ Rockwell AIM65 expansion only differs in five pins:
+
+ -12V 16
+ +12V 17
+ /CS8 18
+ /CS9 19
+ /CSA 20
+
+ Comelta DRAC-1 expansion modules use a 96-pin Eurocard connector with row
+ b unused. Has an external manual reset input and more power rails, but
+ omits some control signals:
+
+ +25V a 1 c +25V
+ external manual reset a 2 c reserved
+ reserved a 3 c +5V battery
+ +12V a 4 c +15V
+ -5V a 5 c -15V/-12V
+ +5V a 6 c +5V
+ GND a 7 c GND
+ GND a 8 c GND
+ N/C a 9 c N/C
+ N/C a 10 c N/C
+ N/C a 11 c N/C
+ N/C a 12 c N/C
+ reserved a 13 c SYNC
+ reserved a 14 c reserved
+ R/W a 15 c /RDY
+ clock phase 2 a 16 c clock phase 1
+ /IRQ a 17 c reserved
+ /NMI a 18 c /RES
+ reserved a 19 c reserved
+ DB7 a 20 c DB6
+ DB5 a 21 c DB4
+ DB3 a 22 c DB2
+ DB1 a 23 c DB0
+ reserved a 24 c reserved
+ AB15 a 25 c AB14
+ AB13 a 26 c AB12
+ AB11 a 27 c AB10
+ AB9 a 28 c AB8
+ AB7 a 29 c AB6
+ AB5 a 30 c AB4
+ AB3 a 31 c AB2
+ AB1 a 32 c AB0
+
+ * No RO, RAM R/W, inverted clock phase 2 and R/W, K6 or SST out
+
+***************************************************************************/
+
+#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 ATTR_COLD;
+ virtual void device_start() override ATTR_COLD;
+
+ // 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 ATTR_COLD;
+ virtual void device_reset() override ATTR_COLD;
+
+ // 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 ddfe9d81330..b14c79f81bb 100644
--- a/src/devices/bus/lpci/cirrus.cpp
+++ b/src/devices/bus/lpci/cirrus.cpp
@@ -64,10 +64,11 @@
***************************************************************************/
#include "emu.h"
-#include "cirrus.h"
#include "video/pc_vga.h"
+#include "cirrus.h"
-#define LOG_PCIACCESS 0
+#define VERBOSE (0)
+#include "logmacro.h"
//**************************************************************************
// DEVICE DEFINITIONS
@@ -85,7 +86,8 @@ DEFINE_DEVICE_TYPE(PCI_CIRRUS_SVGA, pci_cirrus_svga_device, "pci_cirrus_svga", "
pci_cirrus_svga_device::pci_cirrus_svga_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
: device_t(mconfig, PCI_CIRRUS_SVGA, tag, owner, clock)
- , pci_device_interface( mconfig, *this )
+ , pci_device_interface(mconfig, *this)
+ , m_vga(*this, "vga")
{
}
@@ -135,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;
}
@@ -147,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);
}
/*************************************
@@ -157,8 +157,8 @@ void pci_cirrus_svga_device::pci_write(pci_bus_device *pcibus, int function, int
*
*************************************/
-WRITE8_MEMBER( pci_cirrus_svga_device::cirrus_42E8_w )
+void pci_cirrus_svga_device::cirrus_42E8_w(uint8_t data)
{
if (data & 0x80)
- machine().device("vga")->reset();
+ m_vga->reset();
}
diff --git a/src/devices/bus/lpci/cirrus.h b/src/devices/bus/lpci/cirrus.h
index 22eabaff906..409a6fcfa8b 100644
--- a/src/devices/bus/lpci/cirrus.h
+++ b/src/devices/bus/lpci/cirrus.h
@@ -20,18 +20,22 @@
class pci_cirrus_svga_device : public device_t, public pci_device_interface
{
public:
- // construction/destruction
+ // construction/destruction
pci_cirrus_svga_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
+ template <typename T>
+ void set_vga(T &&tag) { m_vga.set_tag(std::forward<T>(tag)); }
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_WRITE8_MEMBER( cirrus_42E8_w );
+ void cirrus_42E8_w(uint8_t data);
protected:
// device-level overrides
- virtual void device_start() override;
- virtual void device_reset() override;
+ virtual void device_start() override ATTR_COLD;
+ virtual void device_reset() override ATTR_COLD;
+
+ required_device<vga_device> m_vga;
};
diff --git a/src/devices/bus/lpci/i82371ab.cpp b/src/devices/bus/lpci/i82371ab.cpp
index ef32506481a..102cd6b8b56 100644
--- a/src/devices/bus/lpci/i82371ab.cpp
+++ b/src/devices/bus/lpci/i82371ab.cpp
@@ -19,6 +19,20 @@
#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 VERBOSE (LOG_GENERAL | LOG_ISA | LOG_IDE | LOG_USB | LOG_ACPI)
+//#define LOG_OUTPUT_FUNC osd_printf_info
+#include "logmacro.h"
+
+#define LOGISA(...) LOGMASKED(LOG_ISA, __VA_ARGS__)
+#define LOGIDE(...) LOGMASKED(LOG_IDE, __VA_ARGS__)
+#define LOGUSB(...) LOGMASKED(LOG_USB, __VA_ARGS__)
+#define LOGACPI(...) LOGMASKED(LOG_ACPI, __VA_ARGS__)
+
DEFINE_DEVICE_TYPE(I82371AB, i82371ab_device, "i82371ab", "Intel 82371AB")
@@ -28,6 +42,8 @@ i82371ab_device::i82371ab_device(const machine_config &mconfig, const char *tag,
{
}
+
+
uint32_t i82371ab_device::pci_isa_r(device_t *busdevice, int offset, uint32_t mem_mask)
{
uint32_t result = m_regs[0][offset] |
@@ -35,7 +51,7 @@ uint32_t i82371ab_device::pci_isa_r(device_t *busdevice, int offset, uint32_t me
m_regs[0][offset+2] << 16|
m_regs[0][offset+3] << 24;
- logerror("i82371ab_pci_isa_r, offset = %02x, mem_mask = %08x\n", offset, mem_mask);
+ LOGISA("ISA read: [%02x] -> %08x & %08x\n", offset, result, mem_mask);
return result;
}
@@ -46,7 +62,7 @@ void i82371ab_device::pci_isa_w(device_t *busdevice, int offset, uint32_t data,
int i;
COMBINE_DATA(&cdata);
- logerror("i82371ab_pci_isa_w, offset = %02x, data = %08x, mem_mask = %08x\n", offset, data, mem_mask);
+ LOGISA("ISA write: [%02x] <- %08x & %08x\n", offset, data, mem_mask);
for(i = 0; i < 4; i++, offset++, cdata >>= 8)
{
@@ -74,7 +90,7 @@ uint32_t i82371ab_device::pci_ide_r(device_t *busdevice, int offset, uint32_t me
m_regs[1][offset+2] << 16|
m_regs[1][offset+3] << 24;
- logerror("i82371ab_pci_ide_r, offset = %02x, mem_mask = %08x\n", offset, mem_mask);
+ LOGIDE("IDE read: [%02x] -> %08x & %08x\n", offset, result, mem_mask);
return result;
}
@@ -85,7 +101,7 @@ void i82371ab_device::pci_ide_w(device_t *busdevice, int offset, uint32_t data,
int i;
COMBINE_DATA(&cdata);
- logerror("i82371ab_pci_isa_w, offset = %02x, data = %08x, mem_mask = %08x\n", offset, data, mem_mask);
+ LOGIDE("IDE write: [%02x] <- %08x & %08x\n", offset, data, mem_mask);
for(i = 0; i < 4; i++, offset++, cdata >>= 8)
{
@@ -113,7 +129,7 @@ uint32_t i82371ab_device::pci_usb_r(device_t *busdevice, int offset, uint32_t me
m_regs[2][offset+2] << 16|
m_regs[2][offset+3] << 24;
- logerror("i82371ab_pci_usb_r, offset = %02x, mem_mask = %08x\n", offset, mem_mask);
+ LOGUSB("USB read: [%02x] -> %08x & %08x\n", offset, result, mem_mask);
return result;
}
@@ -124,7 +140,7 @@ void i82371ab_device::pci_usb_w(device_t *busdevice, int offset, uint32_t data,
int i;
COMBINE_DATA(&cdata);
- logerror("i82371ab_pci_isa_w, offset = %02x, data = %08x, mem_mask = %08x\n", offset, data, mem_mask);
+ LOGUSB("USB write: [%02x] <- %08x & %08x\n", offset, data, mem_mask);
for(i = 0; i < 4; i++, offset++, cdata >>= 8)
{
@@ -152,7 +168,7 @@ uint32_t i82371ab_device::pci_acpi_r(device_t *busdevice, int offset, uint32_t m
m_regs[3][offset+2] << 16|
m_regs[3][offset+3] << 24;
- logerror("i82371ab_pci_acpi_r, offset = %02x, mem_mask = %08x\n", offset, mem_mask);
+ LOGACPI("ACPI read: [%02x] -> %08x & %08x\n", offset, result, mem_mask);
return result;
}
@@ -163,7 +179,7 @@ void i82371ab_device::pci_acpi_w(device_t *busdevice, int offset, uint32_t data,
int i;
COMBINE_DATA(&cdata);
- logerror("i82371ab_pci_isa_w, offset = %02x, data = %08x, mem_mask = %08x\n", offset, data, mem_mask);
+ LOGACPI("ACPI write: [%02x] <- %08x & %08x\n", offset, data, mem_mask);
for(i = 0; i < 4; i++, offset++, cdata >>= 8)
{
@@ -194,7 +210,7 @@ uint32_t i82371ab_device::pci_read(pci_bus_device *pcibus, int function, int off
case 3: return pci_acpi_r(pcibus, offset, mem_mask);
}
- logerror("i82371ab_pci_read: read from undefined function %d\n", function);
+ LOG("read from undefined function %d\n", function);
return 0;
}
diff --git a/src/devices/bus/lpci/i82371ab.h b/src/devices/bus/lpci/i82371ab.h
index 5080c135145..f3fdd626f70 100644
--- a/src/devices/bus/lpci/i82371ab.h
+++ b/src/devices/bus/lpci/i82371ab.h
@@ -32,8 +32,8 @@ public:
protected:
// device-level overrides
- virtual void device_start() override;
- virtual void device_reset() override;
+ virtual void device_start() override ATTR_COLD;
+ virtual void device_reset() override ATTR_COLD;
uint32_t pci_isa_r(device_t *busdevice, int offset, uint32_t mem_mask);
void pci_isa_w(device_t *busdevice, int offset, uint32_t data, uint32_t mem_mask);
diff --git a/src/devices/bus/lpci/i82371sb.cpp b/src/devices/bus/lpci/i82371sb.cpp
index 738c725f530..16917043332 100644
--- a/src/devices/bus/lpci/i82371sb.cpp
+++ b/src/devices/bus/lpci/i82371sb.cpp
@@ -38,6 +38,7 @@ i82371sb_device::i82371sb_device(const machine_config &mconfig, const char *tag,
, m_apmc(0)
, m_apms(0)
, m_base(0)
+ , m_cpu(*this, finder_base::DUMMY_TAG)
{
}
@@ -163,8 +164,8 @@ void i82371sb_device::map_busmaster_dma()
{
if (m_base != 0)
{
- spaceio->install_readwrite_handler(m_base, m_base + 0x7, read32_delegate(FUNC(bus_master_ide_controller_device::bmdma_r), &(*m_ide)), write32_delegate(FUNC(bus_master_ide_controller_device::bmdma_w), &(*m_ide)), 0xffffffff);
- spaceio->install_readwrite_handler(m_base + 0x8, m_base + 0xf, read32_delegate(FUNC(bus_master_ide_controller_device::bmdma_r), &(*m_ide2)), write32_delegate(FUNC(bus_master_ide_controller_device::bmdma_w), &(*m_ide2)), 0xffffffff);
+ spaceio->install_readwrite_handler(m_base, m_base + 0x7, read32s_delegate(*m_ide, FUNC(bus_master_ide_controller_device::bmdma_r)), write32s_delegate(*m_ide, FUNC(bus_master_ide_controller_device::bmdma_w)), 0xffffffff);
+ spaceio->install_readwrite_handler(m_base + 0x8, m_base + 0xf, read32s_delegate(*m_ide2, FUNC(bus_master_ide_controller_device::bmdma_r)), write32s_delegate(*m_ide2, FUNC(bus_master_ide_controller_device::bmdma_w)), 0xffffffff);
}
}
@@ -249,13 +250,12 @@ void i82371sb_device::remap(int space_id, offs_t start, offs_t end)
void i82371sb_device::device_start()
{
- address_space& spaceio = machine().device(":maincpu")->memory().space(AS_IO);
+ address_space& spaceio = m_cpu->space(AS_IO);
southbridge_device::device_start();
m_ide_io_ports_enabled = false;
- spaceio.install_readwrite_handler(0x00b0, 0x00b3, read8_delegate(FUNC(i82371sb_device::read_apmcapms), this), write8_delegate(FUNC(i82371sb_device::write_apmcapms), this), 0xffff0000);
- m_smi_callback.resolve_safe();
- m_boot_state_hook.resolve_safe();
+ spaceio.install_readwrite_handler(0x00b0, 0x00b3, read8sm_delegate(*this, FUNC(i82371sb_device::read_apmcapms)), write8sm_delegate(*this, FUNC(i82371sb_device::write_apmcapms)), 0xffff0000);
+
// setup save states
save_item(NAME(m_regs));
}
@@ -300,7 +300,7 @@ void i82371sb_device::port80_debug_write(uint8_t value)
m_boot_state_hook((offs_t)0, value);
}
-READ8_MEMBER(i82371sb_device::read_apmcapms)
+uint8_t i82371sb_device::read_apmcapms(offs_t offset)
{
if (offset == 0)
return m_apmc;
@@ -308,7 +308,7 @@ READ8_MEMBER(i82371sb_device::read_apmcapms)
return m_apms;
}
-WRITE8_MEMBER(i82371sb_device::write_apmcapms)
+void i82371sb_device::write_apmcapms(offs_t offset, uint8_t data)
{
if (offset == 0)
{
diff --git a/src/devices/bus/lpci/i82371sb.h b/src/devices/bus/lpci/i82371sb.h
index 7411a6ebea2..e0e9fadfe88 100644
--- a/src/devices/bus/lpci/i82371sb.h
+++ b/src/devices/bus/lpci/i82371sb.h
@@ -24,6 +24,9 @@ public:
// construction/destruction
i82371sb_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
+ template <typename T>
+ void set_cpu(T &&tag) { m_cpu.set_tag(std::forward<T>(tag)); }
+
auto smi() { return m_smi_callback.bind(); }
auto boot_state_hook() { return m_boot_state_hook.bind(); }
@@ -34,8 +37,8 @@ public:
protected:
// device-level overrides
- virtual void device_start() override;
- virtual void device_reset() override;
+ virtual void device_start() override ATTR_COLD;
+ virtual void device_reset() override ATTR_COLD;
virtual void port80_debug_write(uint8_t value) override;
uint32_t pci_isa_r(device_t *busdevice, int offset, uint32_t mem_mask);
@@ -47,8 +50,8 @@ protected:
uint32_t pci_usb_r(device_t *busdevice, int offset, uint32_t mem_mask);
void pci_usb_w(device_t *busdevice, int offset, uint32_t data, uint32_t mem_mask);
private:
- DECLARE_READ8_MEMBER(read_apmcapms);
- DECLARE_WRITE8_MEMBER(write_apmcapms);
+ uint8_t read_apmcapms(offs_t offset);
+ void write_apmcapms(offs_t offset, uint8_t data);
void map_busmaster_dma();
void update_smireq_line();
@@ -61,6 +64,7 @@ private:
int m_apmc;
int m_apms;
uint32_t m_base;
+ required_device<cpu_device> m_cpu;
};
// device type definition
diff --git a/src/devices/bus/lpci/i82439tx.cpp b/src/devices/bus/lpci/i82439tx.cpp
index 1fe0e22717f..1c36412eac1 100644
--- a/src/devices/bus/lpci/i82439tx.cpp
+++ b/src/devices/bus/lpci/i82439tx.cpp
@@ -21,12 +21,15 @@ DEFINE_DEVICE_TYPE(I82439TX_LEGACY, i82439tx_device, "i82439tx_legacy", "Intel 8
i82439tx_device::i82439tx_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) :
northbridge_device(mconfig, I82439TX_LEGACY, tag, owner, clock),
pci_device_interface(mconfig, *this),
- m_cpu_tag(nullptr),
m_region_tag(nullptr),
m_space(nullptr),
m_rom(nullptr)
{
m_smram.smiact_n = 1;
+ m_smram.tseg_size = 0;
+ m_smram.mapping = 0;
+ m_smram.tseg_en = 0;
+ m_smram.h_smrame = 0;
}
void i82439tx_device::i82439tx_configure_memory(uint8_t val, offs_t begin, offs_t end)
@@ -142,7 +145,7 @@ uint32_t i82439tx_device::pci_read(pci_bus_device *pcibus, int function, int off
case 0xF4:
case 0xF8:
case 0xFC:
- assert(((offset - 0x50) / 4) >= 0 && ((offset - 0x50) / 4) < ARRAY_LENGTH(m_regs));
+ assert(((offset - 0x50) / 4) >= 0 && ((offset - 0x50) / 4) < std::size(m_regs));
result = m_regs[(offset - 0x50) / 4];
break;
@@ -291,7 +294,7 @@ void i82439tx_device::pci_write(pci_bus_device *pcibus, int function, int offset
case 0xF4:
case 0xF8:
case 0xFC:
- assert(((offset - 0x50) / 4) >= 0 && ((offset - 0x50) / 4) < ARRAY_LENGTH(m_regs));
+ assert(((offset - 0x50) / 4) >= 0 && ((offset - 0x50) / 4) < std::size(m_regs));
COMBINE_DATA(&m_regs[(offset - 0x50) / 4]);
break;
@@ -423,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
@@ -442,10 +445,7 @@ void i82439tx_device::device_start()
{
northbridge_device::device_start();
// get address space we are working on
- device_t *cpu = machine().device(m_cpu_tag);
- assert(cpu != nullptr);
-
- m_space = &cpu->memory().space(AS_PROGRAM);
+ m_space = &m_cpu->space(AS_PROGRAM);
// get rom region
m_rom = machine().root_device().memregion(m_region_tag)->base();
diff --git a/src/devices/bus/lpci/i82439tx.h b/src/devices/bus/lpci/i82439tx.h
index 3bb2671ecb7..3918730d571 100644
--- a/src/devices/bus/lpci/i82439tx.h
+++ b/src/devices/bus/lpci/i82439tx.h
@@ -24,24 +24,22 @@ public:
// construction/destruction
i82439tx_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
- void set_cpu(const char *tag) { m_cpu_tag = tag; }
void set_region(const char *tag) { m_region_tag = tag; }
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
- virtual void device_start() override;
- virtual void device_reset() override;
+ virtual void device_start() override ATTR_COLD;
+ virtual void device_reset() override ATTR_COLD;
void i82439tx_configure_memory(uint8_t val, offs_t begin, offs_t end);
void update_smram_mappings();
private:
- const char *m_cpu_tag;
const char *m_region_tag;
address_space *m_space;
diff --git a/src/devices/bus/lpci/mpc105.cpp b/src/devices/bus/lpci/mpc105.cpp
index 5816153f134..8853f3eb047 100644
--- a/src/devices/bus/lpci/mpc105.cpp
+++ b/src/devices/bus/lpci/mpc105.cpp
@@ -10,9 +10,9 @@
#include "emu.h"
#include "mpc105.h"
-#include "machine/ram.h"
-#define LOG_MPC105 0
+#define VERBOSE (0)
+#include "logmacro.h"
//**************************************************************************
// DEVICE DEFINITIONS
@@ -35,7 +35,8 @@ mpc105_device::mpc105_device(const machine_config &mconfig, const char *tag, dev
m_bank_base_default(0),
m_bank_base(0),
m_bank_enable(0),
- m_maincpu(*this, finder_base::DUMMY_TAG)
+ m_maincpu(*this, finder_base::DUMMY_TAG),
+ m_ram(*this, ":" RAM_TAG)
{
}
@@ -67,9 +68,9 @@ void mpc105_device::update_memory()
int bank;
offs_t begin, end;
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)
{
@@ -91,17 +92,16 @@ void mpc105_device::update_memory()
| (((m_bank_registers[(bank / 4) + 6] >> (bank % 4) * 8)) & 0x03) << 28
| 0x000FFFFF;
- end = std::min(end, begin + machine().device<ram_device>(RAM_TAG)->size() - 1);
+ end = std::min(end, begin + ram_size - 1);
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, machine().device<ram_device>(RAM_TAG)->pointer(), machine().device<ram_device>(RAM_TAG)->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)
{
sprintf(bank_str,"bank%d",uint8_t(bank + m_bank_base));
- membank(bank_str)->set_base(machine().device<ram_device>(RAM_TAG)->pointer());
+ membank(bank_str)->set_base(m_ram->pointer());
}
}
}
diff --git a/src/devices/bus/lpci/mpc105.h b/src/devices/bus/lpci/mpc105.h
index 94f9181a2d7..f14316e3ce2 100644
--- a/src/devices/bus/lpci/mpc105.h
+++ b/src/devices/bus/lpci/mpc105.h
@@ -14,6 +14,7 @@
#pragma once
#include "pci.h"
+#include "machine/ram.h"
#define MPC105_MEMORYBANK_COUNT 8
@@ -35,8 +36,8 @@ public:
protected:
// device-level overrides
- virtual void device_start() override;
- virtual void device_reset() override;
+ virtual void device_start() override ATTR_COLD;
+ virtual void device_reset() override ATTR_COLD;
void update_memory();
@@ -47,6 +48,7 @@ private:
uint32_t m_bank_registers[8];
required_device<cpu_device> m_maincpu;
+ required_device<ram_device> m_ram;
};
diff --git a/src/devices/bus/lpci/northbridge.cpp b/src/devices/bus/lpci/northbridge.cpp
index e07220bb005..0384a9637e4 100644
--- a/src/devices/bus/lpci/northbridge.cpp
+++ b/src/devices/bus/lpci/northbridge.cpp
@@ -13,9 +13,9 @@
// GLOBAL VARIABLES
//**************************************************************************
-northbridge_device::northbridge_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock)
+northbridge_device::northbridge_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_maincpu(*this, ":maincpu"),
+ m_cpu(*this, finder_base::DUMMY_TAG),
m_ram(*this, ":" RAM_TAG)
{
}
@@ -26,16 +26,14 @@ northbridge_device::northbridge_device(const machine_config &mconfig, device_typ
void northbridge_device::device_start()
{
- address_space& space = machine().device(":maincpu")->memory().space(AS_PROGRAM);
+ address_space &space = m_cpu->space(AS_PROGRAM);
machine().root_device().membank("bank10")->set_base(m_ram->pointer());
if (m_ram->size() > 0x100000)
{
offs_t ram_limit = 0x100000 + m_ram->size() - 0x100000;
- space.install_read_bank (0x100000, ram_limit - 1, "bank1");
- space.install_write_bank(0x100000, ram_limit - 1, "bank1");
- machine().root_device().membank("bank1")->set_base(m_ram->pointer() + 0x100000);
+ space.install_ram(0x100000, ram_limit - 1, m_ram->pointer() + 0x100000);
}
}
diff --git a/src/devices/bus/lpci/northbridge.h b/src/devices/bus/lpci/northbridge.h
index dd557427f16..bdd4d2840bf 100644
--- a/src/devices/bus/lpci/northbridge.h
+++ b/src/devices/bus/lpci/northbridge.h
@@ -16,15 +16,19 @@
class northbridge_device : public device_t
{
+public:
+ template <typename T>
+ void set_cpu(T &&tag) { m_cpu.set_tag(std::forward<T>(tag)); }
+
protected:
// construction/destruction
northbridge_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_start() override ATTR_COLD;
+ virtual void device_reset() override ATTR_COLD;
- required_device<cpu_device> m_maincpu;
+ required_device<cpu_device> m_cpu;
required_device<ram_device> m_ram;
};
diff --git a/src/devices/bus/lpci/pci.cpp b/src/devices/bus/lpci/pci.cpp
index 1a772f3bef6..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
@@ -91,7 +92,8 @@ DEFINE_DEVICE_TYPE(PCI_BUS, pci_bus_device, "pci_bus", "PCI Bus")
//-------------------------------------------------
pci_bus_device::pci_bus_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) :
device_t(mconfig, PCI_BUS, tag, owner, clock), m_busnum(0),
- m_father(nullptr), m_address(0), m_devicenum(0), m_busnumber(0), m_busnumaddr(nullptr)
+ m_address(0), m_devicenum(0), m_busnumber(0), m_busnumaddr(nullptr),
+ m_father(*this, finder_base::DUMMY_TAG)
{
for (auto & elem : m_devtag) {
elem= nullptr;
@@ -103,7 +105,7 @@ pci_bus_device::pci_bus_device(const machine_config &mconfig, const char *tag, d
INLINE FUNCTIONS
***************************************************************************/
-READ32_MEMBER( pci_bus_device::read )
+uint32_t pci_bus_device::read(offs_t offset, uint32_t mem_mask)
{
uint32_t result = 0xffffffff;
int function, reg;
@@ -129,8 +131,7 @@ READ32_MEMBER( pci_bus_device::read )
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;
}
@@ -157,12 +158,11 @@ pci_bus_device *pci_bus_device::pci_search_bustree(int busnum, int devicenum, pc
-WRITE32_MEMBER( pci_bus_device::write )
+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)
{
@@ -182,8 +182,7 @@ WRITE32_MEMBER( pci_bus_device::write )
}
else
m_devicenum = -1;
- if (LOG_PCI)
- logerror(" bus:%d device:%d\n", busnum, devicenum);
+ LOG(" bus:%d device:%d\n", busnum, devicenum);
}
break;
@@ -196,8 +195,7 @@ WRITE32_MEMBER( pci_bus_device::write )
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;
}
@@ -205,25 +203,25 @@ WRITE32_MEMBER( pci_bus_device::write )
-READ64_MEMBER(pci_bus_device::read_64be)
+uint64_t pci_bus_device::read_64be(offs_t offset, uint64_t mem_mask)
{
uint64_t result = 0;
mem_mask = swapendian_int64(mem_mask);
if (ACCESSING_BITS_0_31)
- result |= (uint64_t)read(space, offset * 2 + 0, mem_mask >> 0) << 0;
+ result |= (uint64_t)read(offset * 2 + 0, mem_mask >> 0) << 0;
if (ACCESSING_BITS_32_63)
- result |= (uint64_t)read(space, offset * 2 + 1, mem_mask >> 32) << 32;
+ result |= (uint64_t)read(offset * 2 + 1, mem_mask >> 32) << 32;
return swapendian_int64(result);
}
-WRITE64_MEMBER(pci_bus_device::write_64be)
+void pci_bus_device::write_64be(offs_t offset, uint64_t data, uint64_t mem_mask)
{
data = swapendian_int64(data);
mem_mask = swapendian_int64(mem_mask);
if (ACCESSING_BITS_0_31)
- write(space, offset * 2 + 0, data >> 0, mem_mask >> 0);
+ write(offset * 2 + 0, data >> 0, mem_mask >> 0);
if (ACCESSING_BITS_32_63)
- write(space, offset * 2 + 1, data >> 32, mem_mask >> 32);
+ write(offset * 2 + 1, data >> 32, mem_mask >> 32);
}
@@ -236,7 +234,7 @@ void pci_bus_device::add_sibling(pci_bus_device *sibling, int busnum)
void pci_bus_device::remap(int space_id, offs_t start, offs_t end)
{
- for (int i = 0; i < ARRAY_LENGTH(m_devtag); i++)
+ for (int i = 0; i < std::size(m_devtag); i++)
{
if (m_device[i] != nullptr)
m_device[i]->remap(space_id, start, end);
@@ -271,7 +269,7 @@ void pci_bus_device::device_start()
char id[3];
/* find all our devices */
- for (int i = 0; i < ARRAY_LENGTH(m_devtag); i++)
+ for (int i = 0; i < std::size(m_devtag); i++)
{
sprintf(id, "%d", i);
pci_connector_device *conn = downcast<pci_connector_device *>(subdevice(id));
@@ -284,11 +282,8 @@ void pci_bus_device::device_start()
m_device[i] = nullptr;
}
- if (m_father != nullptr) {
- pci_bus_device *father = machine().device<pci_bus_device>(m_father);
- if (father)
- father->add_sibling(this, m_busnum);
- }
+ if (m_father.found())
+ m_father->add_sibling(this, m_busnum);
/* register pci states */
save_item(NAME(m_address));
@@ -312,8 +307,8 @@ void pci_bus_device::device_reset()
// pci_device_interface - constructor
//-------------------------------------------------
-pci_device_interface::pci_device_interface(const machine_config &mconfig, device_t &device)
- : device_slot_card_interface(mconfig, device),
+pci_device_interface::pci_device_interface(const machine_config &mconfig, device_t &device) :
+ device_interface(device, "lpci"),
m_pci_bus(nullptr)
{
}
@@ -332,7 +327,7 @@ DEFINE_DEVICE_TYPE(PCI_CONNECTOR, pci_connector_device, "pci_connector", "PCI de
pci_connector_device::pci_connector_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) :
device_t(mconfig, PCI_CONNECTOR, tag, owner, clock),
- device_slot_interface(mconfig, *this)
+ device_single_card_slot_interface<pci_device_interface>(mconfig, *this)
{
}
@@ -346,5 +341,5 @@ void pci_connector_device::device_start()
pci_device_interface *pci_connector_device::get_device()
{
- return dynamic_cast<pci_device_interface *>(get_card_device());
+ return get_card_device();
}
diff --git a/src/devices/bus/lpci/pci.h b/src/devices/bus/lpci/pci.h
index 7f93875fcfb..ab96eb3de74 100644
--- a/src/devices/bus/lpci/pci.h
+++ b/src/devices/bus/lpci/pci.h
@@ -12,7 +12,6 @@
#define MAME_BUS_LPCI_PCI_H
#pragma once
-#include <forward_list>
//**************************************************************************
// TYPE DEFINITIONS
@@ -21,7 +20,7 @@ class pci_bus_device;
// ======================> pci_device_interface
-class pci_device_interface : public device_slot_card_interface
+class pci_device_interface : public device_interface
{
public:
// construction/destruction
@@ -41,7 +40,7 @@ protected:
};
class pci_connector_device : public device_t,
- public device_slot_interface
+ public device_single_card_slot_interface<pci_device_interface>
{
public:
template <typename T>
@@ -59,7 +58,7 @@ public:
pci_device_interface *get_device();
protected:
- virtual void device_start() override;
+ virtual void device_start() override ATTR_COLD;
};
DECLARE_DEVICE_TYPE(PCI_CONNECTOR, pci_connector_device)
@@ -72,16 +71,16 @@ public:
// construction/destruction
pci_bus_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
- DECLARE_READ32_MEMBER( read );
- DECLARE_WRITE32_MEMBER( write );
+ uint32_t read(offs_t offset, uint32_t mem_mask = ~0);
+ void write(offs_t offset, uint32_t data, uint32_t mem_mask = ~0);
- DECLARE_READ64_MEMBER( read_64be );
- DECLARE_WRITE64_MEMBER( write_64be );
+ uint64_t read_64be(offs_t offset, uint64_t mem_mask = ~0);
+ void write_64be(offs_t offset, uint64_t data, uint64_t mem_mask = ~0);
void set_busnum(int busnum) { m_busnum = busnum; }
- void set_father(const char *father) { m_father = father; }
- void set_device(int num, const char *tag) {
- m_devtag[num] = tag; }
+ template <typename T>
+ void set_father(T &&tag) { m_father.set_tag(std::forward<T>(tag)); }
+ void set_device(int num, const char *tag) { m_devtag[num] = tag; }
pci_bus_device *pci_search_bustree(int busnum, int devicenum, pci_bus_device *pcibus);
void add_sibling(pci_bus_device *sibling, int busnum);
@@ -90,8 +89,8 @@ public:
protected:
// device-level overrides
- virtual void device_start() override;
- virtual void device_reset() override;
+ virtual void device_start() override ATTR_COLD;
+ virtual void device_reset() override ATTR_COLD;
virtual void device_post_load() override;
private:
@@ -100,7 +99,6 @@ private:
const char * m_devtag[32];
pci_device_interface *m_device[32];
- const char * m_father;
pci_bus_device * m_siblings[8];
uint8_t m_siblings_busnum[8];
int m_siblings_count;
@@ -109,6 +107,8 @@ private:
int8_t m_devicenum; // device number we are addressing
int8_t m_busnumber; // pci bus number we are addressing
pci_bus_device * m_busnumaddr; // pci bus we are addressing
+
+ optional_device<pci_bus_device> m_father;
};
// device type definition
diff --git a/src/devices/bus/lpci/southbridge.cpp b/src/devices/bus/lpci/southbridge.cpp
index c4ce2257ed1..4a9b8641857 100644
--- a/src/devices/bus/lpci/southbridge.cpp
+++ b/src/devices/bus/lpci/southbridge.cpp
@@ -135,56 +135,56 @@ southbridge_device::southbridge_device(const machine_config &mconfig, device_typ
*
**********************************************************/
-READ32_MEMBER(southbridge_device::ide1_read32_cs0_r)
+uint32_t southbridge_device::ide1_read32_cs0_r(offs_t offset, uint32_t mem_mask)
{
if (!m_ide_io_ports_enabled)
return 0xffffffff;
return m_ide->read_cs0(offset, mem_mask);
}
-WRITE32_MEMBER(southbridge_device::ide1_write32_cs0_w)
+void southbridge_device::ide1_write32_cs0_w(offs_t offset, uint32_t data, uint32_t mem_mask)
{
if (!m_ide_io_ports_enabled)
return;
m_ide->write_cs0(offset, data, mem_mask);
}
-READ32_MEMBER(southbridge_device::ide2_read32_cs0_r)
+uint32_t southbridge_device::ide2_read32_cs0_r(offs_t offset, uint32_t mem_mask)
{
if (!m_ide_io_ports_enabled)
return 0xffffffff;
return m_ide2->read_cs0(offset, mem_mask);
}
-WRITE32_MEMBER(southbridge_device::ide2_write32_cs0_w)
+void southbridge_device::ide2_write32_cs0_w(offs_t offset, uint32_t data, uint32_t mem_mask)
{
if (!m_ide_io_ports_enabled)
return;
m_ide2->write_cs0(offset, data, mem_mask);
}
-READ8_MEMBER(southbridge_device::ide1_read_cs1_r)
+uint8_t southbridge_device::ide1_read_cs1_r()
{
if (!m_ide_io_ports_enabled)
return 0xff;
return m_ide->read_cs1(1, 0xff0000) >> 16;
}
-WRITE8_MEMBER(southbridge_device::ide1_write_cs1_w)
+void southbridge_device::ide1_write_cs1_w(uint8_t data)
{
if (!m_ide_io_ports_enabled)
return;
m_ide->write_cs1(1, data << 16, 0xff0000);
}
-READ8_MEMBER(southbridge_device::ide2_read_cs1_r)
+uint8_t southbridge_device::ide2_read_cs1_r()
{
if (!m_ide_io_ports_enabled)
return 0xff;
return m_ide2->read_cs1(1, 0xff0000) >> 16;
}
-WRITE8_MEMBER(southbridge_device::ide2_write_cs1_w)
+void southbridge_device::ide2_write_cs1_w(uint8_t data)
{
if (!m_ide_io_ports_enabled)
return;
@@ -194,7 +194,7 @@ WRITE8_MEMBER(southbridge_device::ide2_write_cs1_w)
// With EISA it is possible to select whether each IRQ line is edge sensitive or level sensitive
// Each bit corresponds to an IRQ, 0 for edge triggered 1 for level sensitive
// IRQs 0 1 2 8 13 are always edge triggered
-READ8_MEMBER(southbridge_device::eisa_irq_read)
+uint8_t southbridge_device::eisa_irq_read(offs_t offset)
{
if (offset == 0)
return m_eisa_irq_mode & 0xff;
@@ -202,7 +202,7 @@ READ8_MEMBER(southbridge_device::eisa_irq_read)
return m_eisa_irq_mode >> 8;
}
-WRITE8_MEMBER(southbridge_device::eisa_irq_write)
+void southbridge_device::eisa_irq_write(offs_t offset, uint8_t data)
{
if (offset == 0)
m_eisa_irq_mode = (m_eisa_irq_mode & 0xff00) | data;
@@ -219,18 +219,18 @@ void southbridge_device::device_start()
{
spaceio = &m_maincpu->space(AS_IO);
- spaceio->install_readwrite_handler(0x0000, 0x001f, read8sm_delegate(FUNC(am9517a_device::read), &(*m_dma8237_1)), write8sm_delegate(FUNC(am9517a_device::write), &(*m_dma8237_1)), 0xffffffff);
- spaceio->install_readwrite_handler(0x0020, 0x003f, read8sm_delegate(FUNC(pic8259_device::read), &(*m_pic8259_master)), write8sm_delegate(FUNC(pic8259_device::write), &(*m_pic8259_master)), 0xffffffff);
- spaceio->install_readwrite_handler(0x0040, 0x005f, read8sm_delegate(FUNC(pit8254_device::read), &(*m_pit8254)), write8sm_delegate(FUNC(pit8254_device::write), &(*m_pit8254)), 0xffffffff);
- spaceio->install_readwrite_handler(0x0060, 0x0063, read8_delegate(FUNC(southbridge_device::at_portb_r), this), write8_delegate(FUNC(southbridge_device::at_portb_w), this), 0x0000ff00);
- spaceio->install_readwrite_handler(0x0080, 0x009f, read8_delegate(FUNC(southbridge_device::at_page8_r), this), write8_delegate(FUNC(southbridge_device::at_page8_w), this), 0xffffffff);
- spaceio->install_readwrite_handler(0x00a0, 0x00bf, read8sm_delegate(FUNC(pic8259_device::read), &(*m_pic8259_slave)), write8sm_delegate(FUNC(pic8259_device::write), &(*m_pic8259_slave)), 0xffffffff);
- spaceio->install_readwrite_handler(0x00c0, 0x00df, read8_delegate(FUNC(southbridge_device::at_dma8237_2_r), this), write8_delegate(FUNC(southbridge_device::at_dma8237_2_w), this), 0xffffffff);
- spaceio->install_readwrite_handler(0x0170, 0x0177, read32_delegate(FUNC(southbridge_device::ide2_read32_cs0_r), this), write32_delegate(FUNC(southbridge_device::ide2_write32_cs0_w), this), 0xffffffff);
- spaceio->install_readwrite_handler(0x01f0, 0x01f7, read32_delegate(FUNC(southbridge_device::ide1_read32_cs0_r), this), write32_delegate(FUNC(southbridge_device::ide1_write32_cs0_w), this), 0xffffffff);
- spaceio->install_readwrite_handler(0x0374, 0x0377, read8_delegate(FUNC(southbridge_device::ide2_read_cs1_r), this), write8_delegate(FUNC(southbridge_device::ide2_write_cs1_w), this), 0xff0000);
- spaceio->install_readwrite_handler(0x03f4, 0x03f7, read8_delegate(FUNC(southbridge_device::ide1_read_cs1_r), this), write8_delegate(FUNC(southbridge_device::ide1_write_cs1_w), this), 0xff0000);
- spaceio->install_readwrite_handler(0x04d0, 0x04d3, read8_delegate(FUNC(southbridge_device::eisa_irq_read), this), write8_delegate(FUNC(southbridge_device::eisa_irq_write), this), 0x0000ffff);
+ spaceio->install_readwrite_handler(0x0000, 0x001f, read8sm_delegate(*m_dma8237_1, FUNC(am9517a_device::read)), write8sm_delegate(*m_dma8237_1, FUNC(am9517a_device::write)), 0xffffffff);
+ spaceio->install_readwrite_handler(0x0020, 0x003f, read8sm_delegate(*m_pic8259_master, FUNC(pic8259_device::read)), write8sm_delegate(*m_pic8259_master, FUNC(pic8259_device::write)), 0xffffffff);
+ spaceio->install_readwrite_handler(0x0040, 0x005f, read8sm_delegate(*m_pit8254, FUNC(pit8254_device::read)), write8sm_delegate(*m_pit8254, FUNC(pit8254_device::write)), 0xffffffff);
+ spaceio->install_readwrite_handler(0x0060, 0x0063, read8smo_delegate(*this, FUNC(southbridge_device::at_portb_r)), write8smo_delegate(*this, FUNC(southbridge_device::at_portb_w)), 0x0000ff00);
+ spaceio->install_readwrite_handler(0x0080, 0x009f, read8sm_delegate(*this, FUNC(southbridge_device::at_page8_r)), write8sm_delegate(*this, FUNC(southbridge_device::at_page8_w)), 0xffffffff);
+ spaceio->install_readwrite_handler(0x00a0, 0x00bf, read8sm_delegate(*m_pic8259_slave, FUNC(pic8259_device::read)), write8sm_delegate(*m_pic8259_slave, FUNC(pic8259_device::write)), 0xffffffff);
+ spaceio->install_readwrite_handler(0x00c0, 0x00df, read8sm_delegate(*this, FUNC(southbridge_device::at_dma8237_2_r)), write8sm_delegate(*this, FUNC(southbridge_device::at_dma8237_2_w)), 0xffffffff);
+ spaceio->install_readwrite_handler(0x0170, 0x0177, read32s_delegate(*this, FUNC(southbridge_device::ide2_read32_cs0_r)), write32s_delegate(*this, FUNC(southbridge_device::ide2_write32_cs0_w)), 0xffffffff);
+ spaceio->install_readwrite_handler(0x01f0, 0x01f7, read32s_delegate(*this, FUNC(southbridge_device::ide1_read32_cs0_r)), write32s_delegate(*this, FUNC(southbridge_device::ide1_write32_cs0_w)), 0xffffffff);
+ spaceio->install_readwrite_handler(0x0374, 0x0377, read8smo_delegate(*this, FUNC(southbridge_device::ide2_read_cs1_r)), write8smo_delegate(*this, FUNC(southbridge_device::ide2_write_cs1_w)), 0xff0000);
+ spaceio->install_readwrite_handler(0x03f4, 0x03f7, read8smo_delegate(*this, FUNC(southbridge_device::ide1_read_cs1_r)), write8smo_delegate(*this, FUNC(southbridge_device::ide1_write_cs1_w)), 0xff0000);
+ spaceio->install_readwrite_handler(0x04d0, 0x04d3, read8sm_delegate(*this, FUNC(southbridge_device::eisa_irq_read)), write8sm_delegate(*this, FUNC(southbridge_device::eisa_irq_write)), 0x0000ffff);
spaceio->nop_readwrite(0x00e0, 0x00ef);
}
@@ -254,7 +254,7 @@ void southbridge_device::device_reset()
* pic8259 configuration
*
*************************************************************/
-READ8_MEMBER( southbridge_device::get_slave_ack )
+uint8_t southbridge_device::get_slave_ack(offs_t offset)
{
if (offset==2) // IRQ = 2
return m_pic8259_slave->acknowledge();
@@ -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);
@@ -306,7 +306,7 @@ WRITE_LINE_MEMBER( southbridge_device::at_pit8254_out2_changed )
*
*************************************************************************/
-READ8_MEMBER( southbridge_device::at_page8_r )
+uint8_t southbridge_device::at_page8_r(offs_t offset)
{
uint8_t data = m_at_pages[offset % 0x10];
@@ -329,7 +329,7 @@ READ8_MEMBER( southbridge_device::at_page8_r )
}
-WRITE8_MEMBER( southbridge_device::at_page8_w )
+void southbridge_device::at_page8_w(offs_t offset, uint8_t data)
{
m_at_pages[offset % 0x10] = data;
@@ -353,7 +353,7 @@ WRITE8_MEMBER( southbridge_device::at_page8_w )
}
-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);
@@ -361,7 +361,7 @@ WRITE_LINE_MEMBER( southbridge_device::pc_dma_hrq_changed )
m_dma8237_2->hack_w( state );
}
-READ8_MEMBER(southbridge_device::pc_dma_read_byte)
+uint8_t southbridge_device::pc_dma_read_byte(offs_t offset)
{
address_space& prog_space = m_maincpu->space(AS_PROGRAM); // get the right address space
if(m_dma_channel == -1)
@@ -374,7 +374,7 @@ READ8_MEMBER(southbridge_device::pc_dma_read_byte)
}
-WRITE8_MEMBER(southbridge_device::pc_dma_write_byte)
+void southbridge_device::pc_dma_write_byte(offs_t offset, uint8_t data)
{
address_space& prog_space = m_maincpu->space(AS_PROGRAM); // get the right address space
if(m_dma_channel == -1)
@@ -385,7 +385,7 @@ WRITE8_MEMBER(southbridge_device::pc_dma_write_byte)
}
-READ8_MEMBER(southbridge_device::pc_dma_read_word)
+uint8_t southbridge_device::pc_dma_read_word(offs_t offset)
{
address_space& prog_space = m_maincpu->space(AS_PROGRAM); // get the right address space
if(m_dma_channel == -1)
@@ -400,7 +400,7 @@ READ8_MEMBER(southbridge_device::pc_dma_read_word)
}
-WRITE8_MEMBER(southbridge_device::pc_dma_write_word)
+void southbridge_device::pc_dma_write_word(offs_t offset, uint8_t data)
{
address_space& prog_space = m_maincpu->space(AS_PROGRAM); // get the right address space
if(m_dma_channel == -1)
@@ -411,24 +411,24 @@ WRITE8_MEMBER(southbridge_device::pc_dma_write_word)
}
-READ8_MEMBER( southbridge_device::pc_dma8237_0_dack_r ) { return m_isabus->dack_r(0); }
-READ8_MEMBER( southbridge_device::pc_dma8237_1_dack_r ) { return m_isabus->dack_r(1); }
-READ8_MEMBER( southbridge_device::pc_dma8237_2_dack_r ) { return m_isabus->dack_r(2); }
-READ8_MEMBER( southbridge_device::pc_dma8237_3_dack_r ) { return m_isabus->dack_r(3); }
-READ8_MEMBER( southbridge_device::pc_dma8237_5_dack_r ) { return m_isabus->dack_r(5); }
-READ8_MEMBER( southbridge_device::pc_dma8237_6_dack_r ) { return m_isabus->dack_r(6); }
-READ8_MEMBER( southbridge_device::pc_dma8237_7_dack_r ) { return m_isabus->dack_r(7); }
+uint8_t southbridge_device::pc_dma8237_0_dack_r() { return m_isabus->dack_r(0); }
+uint8_t southbridge_device::pc_dma8237_1_dack_r() { return m_isabus->dack_r(1); }
+uint8_t southbridge_device::pc_dma8237_2_dack_r() { return m_isabus->dack_r(2); }
+uint8_t southbridge_device::pc_dma8237_3_dack_r() { return m_isabus->dack_r(3); }
+uint8_t southbridge_device::pc_dma8237_5_dack_r() { return m_isabus->dack_r(5); }
+uint8_t southbridge_device::pc_dma8237_6_dack_r() { return m_isabus->dack_r(6); }
+uint8_t southbridge_device::pc_dma8237_7_dack_r() { return m_isabus->dack_r(7); }
-WRITE8_MEMBER( southbridge_device::pc_dma8237_0_dack_w ){ m_isabus->dack_w(0, data); }
-WRITE8_MEMBER( southbridge_device::pc_dma8237_1_dack_w ){ m_isabus->dack_w(1, data); }
-WRITE8_MEMBER( southbridge_device::pc_dma8237_2_dack_w ){ m_isabus->dack_w(2, data); }
-WRITE8_MEMBER( southbridge_device::pc_dma8237_3_dack_w ){ m_isabus->dack_w(3, data); }
-WRITE8_MEMBER( southbridge_device::pc_dma8237_5_dack_w ){ m_isabus->dack_w(5, data); }
-WRITE8_MEMBER( southbridge_device::pc_dma8237_6_dack_w ){ m_isabus->dack_w(6, data); }
-WRITE8_MEMBER( southbridge_device::pc_dma8237_7_dack_w ){ m_isabus->dack_w(7, data); }
+void southbridge_device::pc_dma8237_0_dack_w(uint8_t data) { m_isabus->dack_w(0, data); }
+void southbridge_device::pc_dma8237_1_dack_w(uint8_t data) { m_isabus->dack_w(1, data); }
+void southbridge_device::pc_dma8237_2_dack_w(uint8_t data) { m_isabus->dack_w(2, data); }
+void southbridge_device::pc_dma8237_3_dack_w(uint8_t data) { m_isabus->dack_w(3, data); }
+void southbridge_device::pc_dma8237_5_dack_w(uint8_t data) { m_isabus->dack_w(5, data); }
+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,16 +450,16 @@ 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); }
-READ8_MEMBER( southbridge_device::at_portb_r )
+uint8_t southbridge_device::at_portb_r()
{
uint8_t data = m_at_speaker;
data &= ~0xd0; // AT BIOS don't likes this being set
@@ -475,7 +475,7 @@ READ8_MEMBER( southbridge_device::at_portb_r )
return data;
}
-WRITE8_MEMBER( southbridge_device::at_portb_w )
+void southbridge_device::at_portb_w(uint8_t data)
{
m_at_speaker = data;
m_pit8254->write_gate2(BIT(data, 0));
@@ -485,18 +485,18 @@ WRITE8_MEMBER( southbridge_device::at_portb_w )
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);
}
-READ8_MEMBER( southbridge_device::at_dma8237_2_r )
+uint8_t southbridge_device::at_dma8237_2_r(offs_t offset)
{
return m_dma8237_2->read(offset / 2);
}
-WRITE8_MEMBER( southbridge_device::at_dma8237_2_w )
+void southbridge_device::at_dma8237_2_w(offs_t offset, uint8_t data)
{
m_dma8237_2->write(offset / 2, data);
}
@@ -524,13 +524,12 @@ void southbridge_extended_device::device_add_mconfig(machine_config &config)
keybc.hot_res().set_inputline(":maincpu", INPUT_LINE_RESET);
keybc.gate_a20().set_inputline(":maincpu", INPUT_LINE_A20);
keybc.kbd_irq().set("pic8259_master", FUNC(pic8259_device::ir1_w));
- keybc.kbd_clk().set("pc_kbdc", FUNC(pc_kbdc_device::clock_write_from_mb));
- keybc.kbd_data().set("pc_kbdc", FUNC(pc_kbdc_device::data_write_from_mb));
+ keybc.kbd_clk().set(m_pc_kbdc, FUNC(pc_kbdc_device::clock_write_from_mb));
+ keybc.kbd_data().set(m_pc_kbdc, FUNC(pc_kbdc_device::data_write_from_mb));
- PC_KBDC(config, m_pc_kbdc, 0);
+ PC_KBDC(config, m_pc_kbdc, pc_at_keyboards, STR_KBD_MICROSOFT_NATURAL);
m_pc_kbdc->out_clock_cb().set(m_keybc, FUNC(at_keyboard_controller_device::kbd_clk_w));
m_pc_kbdc->out_data_cb().set(m_keybc, FUNC(at_keyboard_controller_device::kbd_data_w));
- PC_KBDC_SLOT(config, "kbd", pc_at_keyboards, STR_KBD_MICROSOFT_NATURAL).set_pc_kbdc_slot(m_pc_kbdc);
ds12885_device &rtc(DS12885(config, "rtc"));
rtc.irq().set("pic8259_slave", FUNC(pic8259_device::ir0_w));
@@ -546,7 +545,7 @@ southbridge_extended_device::southbridge_extended_device(const machine_config &m
: southbridge_device(mconfig, type, tag, owner, clock),
m_keybc(*this, "keybc"),
m_ds12885(*this, "rtc"),
- m_pc_kbdc(*this, "pc_kbdc")
+ m_pc_kbdc(*this, "kbd")
{
}
@@ -560,9 +559,10 @@ void southbridge_extended_device::device_start()
southbridge_device::device_start();
- spaceio.install_readwrite_handler(0x0060, 0x0063, read8smo_delegate(FUNC(at_keyboard_controller_device::data_r), &(*m_keybc)), write8smo_delegate(FUNC(at_keyboard_controller_device::data_w), &(*m_keybc)), 0x000000ff);
- spaceio.install_readwrite_handler(0x0064, 0x0067, read8smo_delegate(FUNC(at_keyboard_controller_device::status_r), &(*m_keybc)), write8smo_delegate(FUNC(at_keyboard_controller_device::command_w), &(*m_keybc)), 0xffffffff);
- spaceio.install_readwrite_handler(0x0070, 0x007f, read8sm_delegate(FUNC(ds12885_device::read), &(*m_ds12885)), write8sm_delegate(FUNC(ds12885_device::write), &(*m_ds12885)), 0xffffffff);
+ 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_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);
}
//-------------------------------------------------
@@ -574,15 +574,10 @@ void southbridge_extended_device::device_reset()
southbridge_device::device_reset();
}
-WRITE8_MEMBER( southbridge_extended_device::write_rtc )
+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 7c2c8f3760f..aa0273283e3 100644
--- a/src/devices/bus/lpci/southbridge.h
+++ b/src/devices/bus/lpci/southbridge.h
@@ -12,7 +12,7 @@
#include "machine/pic8259.h"
#include "machine/pit8253.h"
-#include "machine/ataintf.h"
+#include "bus/ata/ataintf.h"
#include "machine/at_keybc.h"
#include "machine/idectrl.h"
@@ -45,11 +45,11 @@ protected:
southbridge_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;
+ virtual void device_add_mconfig(machine_config &config) override ATTR_COLD;
// device-level overrides
- virtual void device_start() override;
- virtual void device_reset() override;
+ virtual void device_start() override ATTR_COLD;
+ virtual void device_reset() override ATTR_COLD;
virtual void port80_debug_write(uint8_t value) {}
required_device<cpu_device> m_maincpu;
@@ -83,57 +83,57 @@ protected:
void pc_select_dma_channel(int channel, bool state);
private:
- DECLARE_READ8_MEMBER(at_page8_r);
- DECLARE_WRITE8_MEMBER(at_page8_w);
- DECLARE_READ8_MEMBER(at_portb_r);
- DECLARE_WRITE8_MEMBER(at_portb_w);
- DECLARE_WRITE_LINE_MEMBER(iochck_w);
- DECLARE_READ8_MEMBER(get_slave_ack);
- 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);
- DECLARE_READ8_MEMBER(pc_dma8237_0_dack_r);
- DECLARE_READ8_MEMBER(pc_dma8237_1_dack_r);
- DECLARE_READ8_MEMBER(pc_dma8237_2_dack_r);
- DECLARE_READ8_MEMBER(pc_dma8237_3_dack_r);
- DECLARE_READ8_MEMBER(pc_dma8237_5_dack_r);
- DECLARE_READ8_MEMBER(pc_dma8237_6_dack_r);
- DECLARE_READ8_MEMBER(pc_dma8237_7_dack_r);
- DECLARE_WRITE8_MEMBER(pc_dma8237_0_dack_w);
- DECLARE_WRITE8_MEMBER(pc_dma8237_1_dack_w);
- DECLARE_WRITE8_MEMBER(pc_dma8237_2_dack_w);
- DECLARE_WRITE8_MEMBER(pc_dma8237_3_dack_w);
- DECLARE_WRITE8_MEMBER(pc_dma8237_5_dack_w);
- DECLARE_WRITE8_MEMBER(pc_dma8237_6_dack_w);
- DECLARE_WRITE8_MEMBER(pc_dma8237_7_dack_w);
- 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);
-
- DECLARE_READ32_MEMBER(ide1_read32_cs0_r);
- DECLARE_WRITE32_MEMBER(ide1_write32_cs0_w);
- DECLARE_READ32_MEMBER(ide2_read32_cs0_r);
- DECLARE_WRITE32_MEMBER(ide2_write32_cs0_w);
- DECLARE_READ8_MEMBER(ide1_read_cs1_r);
- DECLARE_WRITE8_MEMBER(ide1_write_cs1_w);
- DECLARE_READ8_MEMBER(ide2_read_cs1_r);
- DECLARE_WRITE8_MEMBER(ide2_write_cs1_w);
-
- DECLARE_READ8_MEMBER(at_dma8237_2_r);
- DECLARE_WRITE8_MEMBER(at_dma8237_2_w);
- DECLARE_READ8_MEMBER(pc_dma_read_byte);
- DECLARE_WRITE8_MEMBER(pc_dma_write_byte);
- DECLARE_READ8_MEMBER(pc_dma_read_word);
- DECLARE_WRITE8_MEMBER(pc_dma_write_word);
- DECLARE_READ8_MEMBER(eisa_irq_read);
- DECLARE_WRITE8_MEMBER(eisa_irq_write);
+ uint8_t at_page8_r(offs_t offset);
+ void at_page8_w(offs_t offset, uint8_t data);
+ uint8_t at_portb_r();
+ void at_portb_w(uint8_t data);
+ void iochck_w(int state);
+ uint8_t get_slave_ack(offs_t offset);
+ 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();
+ uint8_t pc_dma8237_3_dack_r();
+ uint8_t pc_dma8237_5_dack_r();
+ uint8_t pc_dma8237_6_dack_r();
+ uint8_t pc_dma8237_7_dack_r();
+ void pc_dma8237_0_dack_w(uint8_t data);
+ void pc_dma8237_1_dack_w(uint8_t data);
+ void pc_dma8237_2_dack_w(uint8_t data);
+ void pc_dma8237_3_dack_w(uint8_t data);
+ 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);
+ 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);
+ 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);
+
+ uint8_t at_dma8237_2_r(offs_t offset);
+ void at_dma8237_2_w(offs_t offset, uint8_t data);
+ uint8_t pc_dma_read_byte(offs_t offset);
+ void pc_dma_write_byte(offs_t offset, uint8_t data);
+ uint8_t pc_dma_read_word(offs_t offset);
+ void pc_dma_write_word(offs_t offset, uint8_t data);
+ uint8_t eisa_irq_read(offs_t offset);
+ void eisa_irq_write(offs_t offset, uint8_t data);
};
// ======================> southbridge_extended_device
@@ -149,17 +149,17 @@ protected:
southbridge_extended_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;
+ virtual void device_add_mconfig(machine_config &config) override ATTR_COLD;
// device-level overrides
- virtual void device_start() override;
- virtual void device_reset() override;
+ virtual void device_start() override ATTR_COLD;
+ virtual void device_reset() override ATTR_COLD;
required_device<at_keyboard_controller_device> m_keybc;
required_device<ds12885_device> m_ds12885;
required_device<pc_kbdc_device> m_pc_kbdc;
private:
- DECLARE_WRITE8_MEMBER(write_rtc);
+ void rtc_nmi_w(uint8_t data);
};
#endif // MAME_BUS_LPCI_SOUTHBRIDGE_H
diff --git a/src/devices/bus/lpci/vt82c505.h b/src/devices/bus/lpci/vt82c505.h
index bbe790781d2..0450d29eced 100644
--- a/src/devices/bus/lpci/vt82c505.h
+++ b/src/devices/bus/lpci/vt82c505.h
@@ -22,8 +22,8 @@ public:
protected:
// device-level overrides
- virtual void device_start() override;
- virtual void device_reset() override;
+ virtual void device_start() override ATTR_COLD;
+ virtual void device_reset() override ATTR_COLD;
private:
uint16_t m_window_addr[3];
diff --git a/src/devices/bus/m5/rom.cpp b/src/devices/bus/m5/rom.cpp
index 5bb1ee371cc..fbf80f5ce29 100644
--- a/src/devices/bus/m5/rom.cpp
+++ b/src/devices/bus/m5/rom.cpp
@@ -43,7 +43,7 @@ m5_ram_device::m5_ram_device(const machine_config &mconfig, const char *tag, dev
mapper specific handlers
-------------------------------------------------*/
-READ8_MEMBER(m5_rom_device::read_rom)
+uint8_t m5_rom_device::read_rom(offs_t offset)
{
if (offset < m_rom_size)
return m_rom[offset];
@@ -51,12 +51,12 @@ READ8_MEMBER(m5_rom_device::read_rom)
return 0xff;
}
-READ8_MEMBER(m5_ram_device::read_ram)
+uint8_t m5_ram_device::read_ram(offs_t offset)
{
return m_ram[offset];
}
-WRITE8_MEMBER(m5_ram_device::write_ram)
+void m5_ram_device::write_ram(offs_t offset, uint8_t data)
{
m_ram[offset] = data;
}
diff --git a/src/devices/bus/m5/rom.h b/src/devices/bus/m5/rom.h
index 6050920c153..890f111cca8 100644
--- a/src/devices/bus/m5/rom.h
+++ b/src/devices/bus/m5/rom.h
@@ -22,7 +22,7 @@ public:
virtual void device_reset() override {}
// reading and writing
- virtual DECLARE_READ8_MEMBER(read_rom) override;
+ virtual uint8_t read_rom(offs_t offset) override;
protected:
m5_rom_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock);
@@ -37,8 +37,8 @@ public:
m5_ram_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
// reading and writing
- virtual DECLARE_READ8_MEMBER(read_ram) override;
- virtual DECLARE_WRITE8_MEMBER(write_ram) 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
diff --git a/src/devices/bus/m5/slot.cpp b/src/devices/bus/m5/slot.cpp
index cdfb88466e1..1be35e6d997 100644
--- a/src/devices/bus/m5/slot.cpp
+++ b/src/devices/bus/m5/slot.cpp
@@ -7,7 +7,6 @@
***********************************************************************************************************/
-
#include "emu.h"
#include "slot.h"
@@ -25,10 +24,10 @@ DEFINE_DEVICE_TYPE(M5_CART_SLOT, m5_cart_slot_device, "m5_cart_slot", "M5 Cartri
// device_m5_cart_interface - constructor
//-------------------------------------------------
-device_m5_cart_interface::device_m5_cart_interface(const machine_config &mconfig, device_t &device)
- : device_slot_card_interface(mconfig, device),
- m_rom(nullptr),
- m_rom_size(0)
+device_m5_cart_interface::device_m5_cart_interface(const machine_config &mconfig, device_t &device) :
+ device_interface(device, "m5cart"),
+ m_rom(nullptr),
+ m_rom_size(0)
{
}
@@ -49,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;
}
}
@@ -74,9 +73,10 @@ void device_m5_cart_interface::ram_alloc(uint32_t size)
//-------------------------------------------------
m5_cart_slot_device::m5_cart_slot_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) :
device_t(mconfig, M5_CART_SLOT, tag, owner, clock),
- device_image_interface(mconfig, *this),
- device_slot_interface(mconfig, *this),
- m_type(M5_STD), m_cart(nullptr)
+ device_cartrom_image_interface(mconfig, *this),
+ device_single_card_slot_interface(mconfig, *this),
+ m_type(M5_STD),
+ m_cart(nullptr)
{
}
@@ -95,7 +95,7 @@ m5_cart_slot_device::~m5_cart_slot_device()
void m5_cart_slot_device::device_start()
{
- m_cart = dynamic_cast<device_m5_cart_interface *>(get_card_device());
+ m_cart = get_card_device();
}
@@ -120,9 +120,9 @@ static const m5_slot slot_list[] =
static int m5_get_pcb_id(const char *slot)
{
- for (int i = 0; i < ARRAY_LENGTH(slot_list); i++)
+ for (int i = 0; i < std::size(slot_list); i++)
{
- if (!core_stricmp(slot_list[i].slot_option, slot))
+ if (!strcmp(slot_list[i].slot_option, slot))
return slot_list[i].pcb_id;
}
@@ -131,7 +131,7 @@ static int m5_get_pcb_id(const char *slot)
static const char *m5_get_slot(int type)
{
- for (int i = 0; i < ARRAY_LENGTH(slot_list); i++)
+ for (int i = 0; i < std::size(slot_list); i++)
{
if (slot_list[i].pcb_id == type)
return slot_list[i].slot_option;
@@ -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_UNSPECIFIED, "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());
}
@@ -219,10 +215,10 @@ std::string m5_cart_slot_device::get_default_card_software(get_default_card_soft
read
-------------------------------------------------*/
-READ8_MEMBER(m5_cart_slot_device::read_rom)
+uint8_t m5_cart_slot_device::read_rom(offs_t offset)
{
if (m_cart)
- return m_cart->read_rom(space, offset);
+ return m_cart->read_rom(offset);
else
return 0xff;
}
@@ -231,10 +227,10 @@ READ8_MEMBER(m5_cart_slot_device::read_rom)
read
-------------------------------------------------*/
-READ8_MEMBER(m5_cart_slot_device::read_ram)
+uint8_t m5_cart_slot_device::read_ram(offs_t offset)
{
if (m_cart)
- return m_cart->read_ram(space, offset);
+ return m_cart->read_ram(offset);
else
return 0xff;
}
@@ -243,8 +239,8 @@ READ8_MEMBER(m5_cart_slot_device::read_ram)
write
-------------------------------------------------*/
-WRITE8_MEMBER(m5_cart_slot_device::write_ram)
+void m5_cart_slot_device::write_ram(offs_t offset, uint8_t data)
{
if (m_cart)
- m_cart->write_ram(space, offset, data);
+ m_cart->write_ram(offset, data);
}
diff --git a/src/devices/bus/m5/slot.h b/src/devices/bus/m5/slot.h
index e2a835238b9..8beacec422e 100644
--- a/src/devices/bus/m5/slot.h
+++ b/src/devices/bus/m5/slot.h
@@ -5,7 +5,7 @@
#pragma once
-#include "softlist_dev.h"
+#include "imagedev/cartrom.h"
/***************************************************************************
@@ -28,16 +28,16 @@ enum
// ======================> device_m5_cart_interface
-class device_m5_cart_interface : public device_slot_card_interface
+class device_m5_cart_interface : public device_interface
{
public:
// construction/destruction
virtual ~device_m5_cart_interface();
// reading and writing
- virtual DECLARE_READ8_MEMBER(read_rom) { return 0xff; }
- virtual DECLARE_READ8_MEMBER(read_ram) { return 0xff; }
- virtual DECLARE_WRITE8_MEMBER(write_ram) {}
+ virtual uint8_t read_rom(offs_t offset) { return 0xff; }
+ 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);
@@ -61,8 +61,8 @@ protected:
// ======================> m5_cart_slot_device
class m5_cart_slot_device : public device_t,
- public device_image_interface,
- public device_slot_interface
+ public device_cartrom_image_interface,
+ public device_single_card_slot_interface<device_m5_cart_interface>
{
public:
// construction/destruction
@@ -79,39 +79,32 @@ public:
m5_cart_slot_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock = 0);
virtual ~m5_cart_slot_device();
- // device-level overrides
- virtual void device_start() override;
+ // device_image_interface implementation
+ virtual std::pair<std::error_condition, std::string> call_load() override;
+ virtual void call_unload() override { }
- // image-level overrides
- virtual image_init_result call_load() override;
- virtual void call_unload() override {}
- virtual const software_list_loader &get_software_list_loader() const override { return rom_software_list_loader::instance(); }
+ 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"; }
+
+ // 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; }
void save_ram() { if (m_cart && m_cart->get_ram_size()) m_cart->save_ram(); }
- virtual iodevice_t image_type() const override { return IO_CARTSLOT; }
- virtual bool is_readable() const override { return 1; }
- virtual bool is_writeable() const override { return 0; }
- virtual bool is_creatable() const override { return 0; }
- virtual bool must_be_loaded() const override { return 0; }
- virtual bool is_reset_on_load() const override { return 1; }
- virtual const char *image_interface() const override { return "m5_cart"; }
- virtual const char *file_extensions() const override { return "bin,rom"; }
-
- // slot interface overrides
- virtual std::string get_default_card_software(get_default_card_software_hook &hook) const override;
-
// reading and writing
- virtual DECLARE_READ8_MEMBER(read_rom);
- virtual DECLARE_READ8_MEMBER(read_ram);
- virtual DECLARE_WRITE8_MEMBER(write_ram);
+ uint8_t read_rom(offs_t offset);
+ uint8_t read_ram(offs_t offset);
+ void write_ram(offs_t offset, uint8_t data);
protected:
+ // device_t implementation
+ virtual void device_start() override ATTR_COLD;
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
new file mode 100644
index 00000000000..fc1b6450824
--- /dev/null
+++ b/src/devices/bus/mackbd/keyboard.cpp
@@ -0,0 +1,974 @@
+// license: BSD-3-Clause
+// copyright-holders: Vas Crabb
+/***************************************************************************
+
+ Apple M0110/M0120 keyboard/keypad
+
+ These peripherals have a lot in common:
+ * Based on Intel or Philips mask-programmed 8021 microcontroller
+ * 100µH inductor as timing element (gives approximately 3MHz)
+ * Identical microcontroller programs
+ * Identical external watchdog circuits based on 74LS123
+ * Identical power-on/brownout reset circuits
+ * Identical host communication interface via P07 and P20
+ * Keys read with a mixture of matrix and dedicated inputs
+ * Neither has diodes to prevent ghosting
+
+ The program chooses keyboard or keypad mode based on whether P05
+ reads low with no outputs driven low.
+
+ The keyboard has dedicated inputs for the four modifiers (Shift,
+ Command, Option, and mechanically toggling Caps Lock - no Control
+ keys and no distinction between left/right Shift and Option). The
+ rest of the keys (52 for ANSI or 53 for ISO) are read via a
+ nine-by-six matrix.
+
+ The keypad has dedicated inputs for the digits and (rather
+ ineffciently) reads the other eight keys via a three-by-three
+ matrix.
+
+ Known MPU silkscreens (date code from real example):
+
+ P8021H 1273
+ 8409
+ ©INTEL '81
+
+ MAB8021P
+ R044
+ DND418V3 S
+ 341-0222B
+
+ +-----------+---------------+-------------------+
+ | Pin | Keyboard | Keypad |
+ +-----------+---------------+-------------------+
+ | P00 (4) | column read | row drive |
+ | P01 (5) | column read | row drive |
+ | P02 (6) | column read | row drive |
+ | P03 (7) | column read | 8 |
+ | P04 (8) | column read | 9 |
+ | P05 (9) | column read | sense |
+ | P06 (10) | Caps Lock | keyboard clock |
+ | P07 (11) | host clock | host clock |
+ +-----------+---------------+-------------------+
+ | P10 (18) | row drive | 0 |
+ | P11 (19) | row drive | 1 |
+ | P12 (20) | row drive | 2 |
+ | P13 (21) | row drive | 3 |
+ | P14 (22) | row drive | 4 |
+ | P15 (23) | row drive | 5 |
+ | P16 (24) | row drive | 6 |
+ | P17 (25) | row drive | 7 |
+ +-----------+---------------+-------------------+
+ | P20 (26) | host data | host data |
+ | P21 (27) | row drive* | keyboard data |
+ | P22 (1) | Shift | column read |
+ | P23 (2) | Command | column read |
+ +-----------+---------------+-------------------+
+ | T1 (13) | Option | column read |
+ +-----------+---------------+-------------------+
+ * falling edge starts/resets watchdog timer
+
+ +------+-----------------------------------------------------+
+ | ANSI | P21 P10 P11 P12 P13 P14 P15 P16 P17 |
+ +------+-----------------------------------------------------+
+ | P00 | A Z Q 1 = ] Rtn \ Tab |
+ | P01 | S X W 2 9 O L , Spc |
+ | P02 | D C E 3 7 U J / ` |
+ | P03 | F V R 4 - [ ' N Bsp |
+ | P04 | H Y 6 8 I K M Ent |
+ | P05 | G B T 5 0 P ; . |
+ +------+-----------------------------------------------------+
+
+ +------+-----------------------------------------------------+
+ | ISO | P21 P10 P11 P12 P13 P14 P15 P16 P17 |
+ +------+-----------------------------------------------------+
+ | P00 | A ` Q 1 = ] \ Rtn Tab |
+ | P01 | S Z W 2 9 O L M Ent |
+ | P02 | D X E 3 7 U J . § |
+ | P03 | F C R 4 - [ ' B Bsp |
+ | P04 | H / Y 6 8 I K N Spc |
+ | P05 | G V T 5 0 P ; , |
+ +------+-----------------------------------------------------+
+
+ +------+-----------------+
+ | Pad | P00 P01 P02 |
+ +------+-----------------+
+ | P22 | / Clr . |
+ | P23 | - , * |
+ | T1 | Ent + |
+ +------+-----------------+
+
+ +------+-------+-------+-------+
+ | Code | ANSI | ISO | Pad |
+ +------+-------+-------+-------+
+ | 0x01 | A | A | |
+ | 0x03 | S | S | . |
+ | 0x05 | D | D | * |
+ | 0x07 | F | F | |
+ | 0x09 | H | H | |
+ | 0x0b | G | G | |
+ | 0x0d | Z | § | + |
+ | 0x0f | X | Z | Clr |
+ | 0x11 | C | X | , |
+ | 0x13 | V | C | |
+ | 0x15 | | / | |
+ | 0x17 | B | V | |
+ | 0x19 | Q | Q | Ent |
+ | 0x1b | W | W | / |
+ | 0x1d | E | E | - |
+ | 0x1f | R | R | |
+ | 0x21 | Y | Y | |
+ | 0x23 | T | T | |
+ | 0x25 | 1 | 1 | 0 |
+ | 0x27 | 2 | 2 | 1 |
+ | 0x29 | 3 | 3 | 2 |
+ | 0x2b | 4 | 4 | 3 |
+ | 0x2d | 6 | 6 | 4 |
+ | 0x2f | 5 | 5 | 5 |
+ | 0x31 | = | = | 6 |
+ | 0x33 | 9 | 9 | 7 |
+ | 0x35 | 7 | 7 | |
+ | 0x37 | - | - | 8 |
+ | 0x39 | 8 | 8 | 9 |
+ | 0x3b | 0 | 0 | |
+ | 0x3d | ] | ] | |
+ | 0x3f | O | O | |
+ | 0x41 | U | U | |
+ | 0x43 | [ | [ | |
+ | 0x45 | I | I | |
+ | 0x47 | P | P | |
+ | 0x49 | Rtn | \ | |
+ | 0x4b | L | L | |
+ | 0x4d | J | J | |
+ | 0x4f | ' | ' | |
+ | 0x51 | K | K | |
+ | 0x53 | ; | ; | |
+ | 0x55 | \ | Rtn | |
+ | 0x57 | , | M | |
+ | 0x59 | / | . | |
+ | 0x5b | N | B | |
+ | 0x5d | M | N | |
+ | 0x5f | . | , | |
+ | 0x61 | Tab | Tab | |
+ | 0x63 | Spc | Ent | |
+ | 0x65 | ` | ` | |
+ | 0x67 | Bsp | Bsp | |
+ | 0x69 | Ent | Spc | |
+ | 0x6b | | | |
+ | 0x6d | | | |
+ | 0x6f | Cmd | Cmd | |
+ | 0x71 | Shift | Shift | |
+ | 0x73 | Caps | Caps | |
+ | 0x75 | Opt | Opt | |
+ | 0x77 | error | error | error |
+ | 0x79 | | | pad |
+ | 0x7b | idle | idle | idle |
+ | 0x7d | pass | pass | pass |
+ | 0x7f | | | |
+ +------+-------+-------+-------+
+
+ 65 25 27 29 2b 2f 2d 35 39 33 3b 37 31 67
+ 61 19 1b 1d 1f 23 13 41 45 3f 47 43 3d 55
+ 73 01 03 05 07 0b 09 4d 51 4b 53 4f 49
+ 71 0d 0f 11 13 17 5b 5d 57 5f 59 71
+ 75 6f 63 69 75
+
+ 65 25 27 29 2b 2f 2d 35 39 33 3b 37 31 67
+ 61 19 1b 1d 1f 23 21 41 45 3f 47 43 3d 55
+ 73 01 03 05 07 0b 09 4d 51 4b 53 4f 49
+ 71 0d 0f 11 13 17 5b 5d 57 5f 59 15 71
+ 75 6f 69 63 75
+
+ 0f 1d 0d 05
+ 33 37 39 1b
+ 2d 2f 31 11
+ 27 29 2b
+ 25 03 19
+
+ Known part numbers:
+ * M0110 (U.S. - ANSI)
+ * M0110B (British - ISO)
+ * M0110F (French - ISO)
+ * M0110J (Japanese - ANSI)
+ * M0110T (Italian - ISO)
+ * M0120 (keypad - English)
+ * M0120P (keypad - European)
+
+ ISO keyboards and the European keypad use icons rather than English
+ text for Backspace, Tab, Caps Lock, Shift, Return, Shift, Option,
+ Enter and Clear (all variants use icons for command and the cursor
+ arrows).
+
+ TODO:
+ * Determine whether P00 or P01 actually feeds the keypad watchdog
+ * Find more model numbers and implement more layouts
+
+***************************************************************************/
+
+#include "emu.h"
+#include "keyboard.h"
+
+#include "cpu/mcs48/mcs48.h"
+
+#define LOG_WATCHDOG (1U << 1)
+#define LOG_MATRIX (1U << 2)
+#define LOG_COMM (1U << 3)
+
+//#define VERBOSE (LOG_GENERAL | LOG_WATCHDOG | LOG_MATRIX | LOG_COMM)
+//#define LOG_OUTPUT_STREAM std::cerr
+#include "logmacro.h"
+
+#define LOGWATCHDOG(...) LOGMASKED(LOG_WATCHDOG, __VA_ARGS__)
+#define LOGMATRIX(...) LOGMASKED(LOG_MATRIX, __VA_ARGS__)
+#define LOGCOMM(...) LOGMASKED(LOG_COMM, __VA_ARGS__)
+
+
+namespace {
+
+ROM_START(keyboard)
+ ROM_REGION(0x0400, "mpu", 0)
+ ROM_LOAD("ip8021h_2173.bin", 0x000000, 0x000400, CRC(5fbd9a94) SHA1(32a3b58afb445a8675b12a4de3aec2fa00c99222))
+ROM_END
+
+
+template <unsigned Rows>
+class peripheral_base : public device_t, public device_mac_keyboard_interface
+{
+public:
+ ioport_value columns_r()
+ {
+ ioport_value result(make_bitmask<ioport_value>(Rows));
+ for (unsigned i = 0U; Rows > i; ++i)
+ {
+ if (!BIT(m_row_drive, i))
+ result &= m_rows[i]->read();
+ }
+ LOGMATRIX("read matrix: row drive = %X, result = %X\n", m_row_drive, result);
+ return result ^ make_bitmask<ioport_value>(Rows);
+ }
+
+ ioport_value host_data_r()
+ {
+ return m_host_data_in ^ 0x01;
+ }
+
+protected:
+ peripheral_base(machine_config const &mconfig, device_type type, char const *tag, device_t *owner, u32 clock)
+ : device_t(mconfig, type, tag, owner, clock)
+ , device_mac_keyboard_interface(mconfig, *this)
+ , m_mpu{ *this, "mpu" }
+ , m_rows{ *this, "ROW%u", 0U }
+ {
+ }
+
+ virtual tiny_rom_entry const *device_rom_region() const override
+ {
+ return ROM_NAME(keyboard);
+ }
+
+ virtual void device_add_mconfig(machine_config &config) override
+ {
+ I8021(config, m_mpu, 3'000'000); // 100µH inductor gives approximately 3MHz
+ m_mpu->p0_out_cb().set(FUNC(peripheral_base::host_clock_w)).bit(7);
+ m_mpu->p2_out_cb().set(FUNC(peripheral_base::host_data_w)).bit(0);
+ }
+
+ virtual void device_start() override
+ {
+ m_watchdog_timeout = timer_alloc(FUNC(peripheral_base::watchdog_timeout), this);
+ m_watchdog_output = timer_alloc(FUNC(peripheral_base::watchdog_output), this);
+
+ m_row_drive = make_bitmask<u16>(Rows);
+ m_host_clock_out = 1U;
+ m_host_data_out = 1U;
+ m_host_data_in = 0x01U;
+ m_watchdog_in = 1U;
+
+ save_item(NAME(m_row_drive));
+ save_item(NAME(m_host_clock_out));
+ save_item(NAME(m_host_data_out));
+ save_item(NAME(m_host_data_in));
+ save_item(NAME(m_watchdog_in));
+ }
+
+ virtual void data_w(int state) override
+ {
+ machine().scheduler().synchronize(timer_expired_delegate(FUNC(peripheral_base::update_host_data), this), state);
+ }
+
+ void watchdog_w(int state)
+ {
+ if (bool(state) != bool(m_watchdog_in))
+ {
+ m_watchdog_in = state ? 1U : 0U;
+ if (!state)
+ {
+ // 74LS123 with Rt = 200kΩ and Cext = 1µF
+ // t = K * Rt * Cext * (1 + (0.7 / Rt)) = 0.28 * 200k * 1µ * (1 + (0.7 / 200k)) ≈ 56ms
+ m_watchdog_timeout->adjust(attotime::from_msec(56));
+ LOGWATCHDOG("%s: watchdog reset\n", machine().describe_context());
+ }
+ }
+ }
+
+ template <u16 Mask> void set_row_drive(u16 value)
+ {
+ m_row_drive = ((m_row_drive & ~Mask) | (value & Mask)) & make_bitmask<u16>(Rows);
+ }
+
+ required_device<i8021_device> m_mpu;
+
+private:
+ void host_clock_w(int state)
+ {
+ if (bool(state) != bool(m_host_clock_out))
+ {
+ if (state)
+ LOGCOMM("%s: host clock out 0 -> 1 data=%u\n", machine().describe_context(), (m_host_data_out && m_host_data_in) ? 1U : 0U);
+ else
+ LOGCOMM("%s: host clock out 1 -> 0\n", machine().describe_context());
+ write_clock(m_host_clock_out = state ? 1U : 0U);
+ }
+ }
+
+ void host_data_w(int state)
+ {
+ if (bool(state) != bool(m_host_data_out))
+ {
+ LOGCOMM("%s: host data out %u -> %u\n", machine().describe_context(), m_host_data_out, state ? 1U : 0U);
+ write_data(m_host_data_out = state ? 1U : 0U);
+ }
+ }
+
+ TIMER_CALLBACK_MEMBER(update_host_data)
+ {
+ if (bool(param) != bool(m_host_data_in))
+ {
+ LOGCOMM("host data in %u -> %u\n", m_host_data_in, param ? 1U : 0U);
+ m_host_data_in = param ? 0x01U : 0x00U;
+ }
+ }
+
+ TIMER_CALLBACK_MEMBER(watchdog_timeout)
+ {
+ // 74LS123 with Rt = 200kΩ and Cext = 100nF
+ // t = K * Rt * Cext * (1 + (0.7 / Rt)) = 0.28 * 200k * 100n * (1 + (0.7 / 200k)) ≈ 5.6ms
+ m_watchdog_output->adjust(attotime::from_usec(5600));
+ LOG("watchdog timeout\n");
+ m_mpu->set_input_line(INPUT_LINE_RESET, ASSERT_LINE);
+ }
+
+ TIMER_CALLBACK_MEMBER(watchdog_output)
+ {
+ LOGWATCHDOG("watchdog release\n");
+ m_mpu->set_input_line(INPUT_LINE_RESET, CLEAR_LINE);
+ }
+
+ required_ioport_array<Rows> m_rows;
+
+ emu_timer *m_watchdog_timeout = nullptr;
+ emu_timer *m_watchdog_output = nullptr;
+
+ u16 m_row_drive = make_bitmask<u16>(Rows); // current bit pattern driving rows (active low)
+ u8 m_host_clock_out = 1U; // clock line drive to host (idle high)
+ u8 m_host_data_out = 1U; // data line drive to host (idle high)
+ u8 m_host_data_in = 0x01U; // data line drive from host (idle high)
+ u8 m_watchdog_in = 1U; // watchdog start/reset (falling edge trigger)
+};
+
+
+class keyboard_base : public peripheral_base<9>
+{
+protected:
+ keyboard_base(machine_config const &mconfig, device_type type, char const *tag, device_t *owner, u32 clock)
+ : peripheral_base<9>(mconfig, type, tag, owner, clock)
+ {
+ }
+
+ virtual void device_add_mconfig(machine_config &config) override
+ {
+ peripheral_base<9>::device_add_mconfig(config);
+
+ m_mpu->p0_in_cb().set_ioport("P0");
+ m_mpu->p1_out_cb().set([this] (u8 data) { set_row_drive<0x01feU>(u16(data) << 1); });
+ m_mpu->p2_in_cb().set_ioport("P2");
+ m_mpu->p2_out_cb().append([this] (u8 data) { set_row_drive<0x0001U>((data >> 1) & 0x01U); });
+ m_mpu->p2_out_cb().append(FUNC(keyboard_base::watchdog_w)).bit(1);
+ m_mpu->t1_in_cb().set_ioport("T1");
+ }
+};
+
+
+class keypad_base : public peripheral_base<3>
+{
+public:
+ ioport_value keyboard_clock_r()
+ {
+ return m_keyboard_clock_in ^ 0x01;
+ }
+
+ ioport_value keyboard_data_r()
+ {
+ return m_keyboard_data_in ^ 0x01;
+ }
+
+protected:
+ keypad_base(machine_config const &mconfig, device_type type, char const *tag, device_t *owner, u32 clock)
+ : peripheral_base<3>(mconfig, type, tag, owner, clock)
+ , m_keyboard_port(*this, "kbd")
+ {
+ }
+
+ virtual void device_add_mconfig(machine_config &config) override
+ {
+ peripheral_base<3>::device_add_mconfig(config);
+
+ m_mpu->p0_in_cb().set_ioport("P0");
+ m_mpu->p0_out_cb().append(FUNC(keypad_base::set_row_drive<0x07U>));
+ m_mpu->p0_out_cb().append(FUNC(keypad_base::watchdog_w)).bit(1); // TODO: confirm whether P0 or P1 resets watchdog
+ m_mpu->p1_in_cb().set_ioport("P1");
+ m_mpu->p2_in_cb().set_ioport("P2");
+ m_mpu->p2_out_cb().append(FUNC(keypad_base::keyboard_data_out_w)).bit(1);
+ m_mpu->t1_in_cb().set([this] () { return int((~columns_r() >> 2) & 0x01U); });
+
+ MAC_KEYBOARD_PORT(config, m_keyboard_port, mac_keyboard_devices, "us");
+ m_keyboard_port->clock_cb().set(FUNC(keypad_base::keyboard_clock_in_w));
+ m_keyboard_port->data_cb().set(FUNC(keypad_base::keyboard_data_in_w));
+ }
+
+ virtual void device_start() override
+ {
+ peripheral_base<3>::device_start();
+
+ m_keyboard_data_out = 0x01U;
+ m_keyboard_clock_in = 0x01U;
+ m_keyboard_data_in = 0x01U;
+
+ save_item(NAME(m_keyboard_data_out));
+ save_item(NAME(m_keyboard_clock_in));
+ save_item(NAME(m_keyboard_data_in));
+ }
+
+ required_device<mac_keyboard_port_device> m_keyboard_port;
+
+private:
+ void keyboard_data_out_w(int state)
+ {
+ if (bool(state) != bool(m_keyboard_data_out))
+ {
+ LOGCOMM("%s: keyboard data out %u -> %u\n", machine().describe_context(), m_keyboard_data_out, state ? 1U : 0U);
+ m_keyboard_port->data_w(m_keyboard_data_out = state ? 0x01U : 0x00U);
+ }
+ }
+
+ void keyboard_clock_in_w(int state)
+ {
+ machine().scheduler().synchronize(timer_expired_delegate(FUNC(keypad_base::update_keyboard_clock), this), state);
+ }
+
+ void keyboard_data_in_w(int state)
+ {
+ machine().scheduler().synchronize(timer_expired_delegate(FUNC(keypad_base::update_keyboard_data), this), state);
+ }
+
+ TIMER_CALLBACK_MEMBER(update_keyboard_clock)
+ {
+ m_keyboard_clock_in = param ? 0x01U : 0x00U;
+ }
+
+ TIMER_CALLBACK_MEMBER(update_keyboard_data)
+ {
+ m_keyboard_data_in = param ? 0x01U : 0x00U;
+ }
+
+ u8 m_keyboard_data_out = 0x01U; // data line drive to keyboard (idle high)
+ u8 m_keyboard_clock_in = 0x01U; // clock line driver from keyboard (idle high)
+ u8 m_keyboard_data_in = 0x01U; // data line drive from keyboard (idle high)
+};
+
+
+INPUT_PORTS_START(keyboard_us)
+ PORT_START("ROW0")
+ PORT_BIT(0x01, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_A) PORT_CHAR('a') PORT_CHAR('A')
+ PORT_BIT(0x02, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_S) PORT_CHAR('s') PORT_CHAR('S')
+ 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_F) PORT_CHAR('f') PORT_CHAR('F')
+ PORT_BIT(0x10, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_H) PORT_CHAR('h') PORT_CHAR('H')
+ PORT_BIT(0x20, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_G) PORT_CHAR('g') PORT_CHAR('G')
+
+ PORT_START("ROW1")
+ PORT_BIT(0x01, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_Z) PORT_CHAR('z') PORT_CHAR('Z')
+ PORT_BIT(0x02, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_X) PORT_CHAR('x') PORT_CHAR('X')
+ PORT_BIT(0x04, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_C) PORT_CHAR('c') PORT_CHAR('C')
+ 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_UNUSED)
+ PORT_BIT(0x20, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_B) PORT_CHAR('b') PORT_CHAR('B')
+
+ PORT_START("ROW2")
+ PORT_BIT(0x01, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_Q) PORT_CHAR('q') PORT_CHAR('Q')
+ PORT_BIT(0x02, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_W) PORT_CHAR('w') PORT_CHAR('W')
+ 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')
+ PORT_BIT(0x10, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_Y) PORT_CHAR('y') PORT_CHAR('Y')
+ PORT_BIT(0x20, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_T) PORT_CHAR('t') PORT_CHAR('T')
+
+ PORT_START("ROW3")
+ PORT_BIT(0x01, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_1) PORT_CHAR('1') PORT_CHAR('!')
+ PORT_BIT(0x02, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_2) PORT_CHAR('2') PORT_CHAR('@')
+ PORT_BIT(0x04, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_3) PORT_CHAR('3') PORT_CHAR('#')
+ PORT_BIT(0x08, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_4) PORT_CHAR('4') PORT_CHAR('$')
+ PORT_BIT(0x10, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_6) PORT_CHAR('6') PORT_CHAR('^')
+ PORT_BIT(0x20, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_5) PORT_CHAR('5') PORT_CHAR('%')
+
+ PORT_START("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('9') PORT_CHAR('(')
+ PORT_BIT(0x04, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_7) PORT_CHAR('7') PORT_CHAR('&')
+ PORT_BIT(0x08, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_MINUS) PORT_CHAR('-') PORT_CHAR('_')
+ PORT_BIT(0x10, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_8) PORT_CHAR('8') PORT_CHAR('*')
+ PORT_BIT(0x20, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_0) PORT_CHAR('0') PORT_CHAR(')')
+
+ PORT_START("ROW5")
+ PORT_BIT(0x01, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_CLOSEBRACE) PORT_CHAR(']') 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_U) PORT_CHAR('u') PORT_CHAR('U')
+ PORT_BIT(0x08, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_OPENBRACE) PORT_CHAR('[') PORT_CHAR('{')
+ PORT_BIT(0x10, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_I) PORT_CHAR('i') PORT_CHAR('I')
+ PORT_BIT(0x20, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_P) PORT_CHAR('p') PORT_CHAR('P')
+
+ PORT_START("ROW6")
+ PORT_BIT(0x01, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_ENTER) PORT_CHAR(0x0d) PORT_NAME("Return")
+ PORT_BIT(0x02, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_L) PORT_CHAR('l') PORT_CHAR('L')
+ 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_QUOTE) PORT_CHAR('\'') PORT_CHAR('"')
+ PORT_BIT(0x10, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_K) PORT_CHAR('k') PORT_CHAR('K')
+ PORT_BIT(0x20, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_COLON) PORT_CHAR(';') PORT_CHAR(':')
+
+ PORT_START("ROW7")
+ 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_CODE(KEYCODE_COMMA) PORT_CHAR(',') PORT_CHAR('<')
+ PORT_BIT(0x04, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_SLASH) PORT_CHAR('/') PORT_CHAR('?')
+ 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_KEYBOARD) PORT_CODE(KEYCODE_M) PORT_CHAR('m') PORT_CHAR('M')
+ PORT_BIT(0x20, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_STOP) PORT_CHAR('.') PORT_CHAR('>')
+
+ PORT_START("ROW8")
+ PORT_BIT(0x01, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_TAB) PORT_CHAR(0x09) PORT_NAME("Tab")
+ PORT_BIT(0x02, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_SPACE) PORT_CHAR(' ')
+ PORT_BIT(0x04, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_TILDE) PORT_CHAR('`') PORT_CHAR('~')
+ PORT_BIT(0x08, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_BACKSPACE) PORT_CHAR(0x08) PORT_NAME("Backspace")
+ PORT_BIT(0x10, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_RCONTROL) PORT_NAME("Enter")
+ PORT_BIT(0x20, IP_ACTIVE_LOW, IPT_UNUSED)
+
+ PORT_START("P0")
+ PORT_BIT(0x3f, IP_ACTIVE_LOW, IPT_CUSTOM) PORT_CUSTOM_MEMBER(FUNC(keyboard_base::columns_r))
+ PORT_BIT(0x40, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_CAPSLOCK) PORT_CHAR(UCHAR_MAMEKEY(CAPSLOCK)) PORT_NAME("Caps Lock") PORT_TOGGLE
+ PORT_BIT(0x80, IP_ACTIVE_LOW, IPT_UNUSED)
+
+ PORT_START("P2")
+ PORT_BIT(0x01, IP_ACTIVE_LOW, IPT_CUSTOM) PORT_CUSTOM_MEMBER(FUNC(keyboard_base::host_data_r))
+ PORT_BIT(0x02, IP_ACTIVE_LOW, IPT_UNUSED)
+ PORT_BIT(0x04, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_LSHIFT) PORT_CODE(KEYCODE_RSHIFT) PORT_CHAR(UCHAR_SHIFT_1) PORT_NAME("Shift")
+ PORT_BIT(0x08, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_LCONTROL) PORT_NAME("Command")
+ PORT_BIT(0xf0, IP_ACTIVE_LOW, IPT_UNUSED)
+
+ PORT_START("T1")
+ PORT_BIT(0x01, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_LALT) PORT_CODE(KEYCODE_RALT) PORT_CHAR(UCHAR_SHIFT_2) PORT_NAME("Option")
+INPUT_PORTS_END
+
+INPUT_PORTS_START(keyboard_gb)
+ PORT_INCLUDE(keyboard_us)
+
+ PORT_MODIFY("ROW1")
+ PORT_BIT(0x01, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_BACKSLASH2) PORT_CHAR('\\') PORT_CHAR('|')
+ PORT_BIT(0x02, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_Z) PORT_CHAR('z') PORT_CHAR('Z')
+ 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('/') PORT_CHAR('?')
+ 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(U'£')
+
+ PORT_MODIFY("ROW6")
+ PORT_BIT(0x01, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_BACKSLASH) PORT_CHAR('`') PORT_CHAR('~')
+
+ PORT_MODIFY("ROW7")
+ PORT_BIT(0x01, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_ENTER) PORT_CHAR(0x0d) PORT_NAME("Return")
+ PORT_BIT(0x02, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_M) PORT_CHAR('m') PORT_CHAR('M')
+ PORT_BIT(0x04, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_STOP) PORT_CHAR('.') PORT_CHAR('>')
+ 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_N) PORT_CHAR('n') PORT_CHAR('N')
+ PORT_BIT(0x20, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_COMMA) PORT_CHAR(',') PORT_CHAR('<')
+
+ 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(U'§') PORT_CHAR('#')
+ PORT_BIT(0x10, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_SPACE) PORT_CHAR(' ')
+INPUT_PORTS_END
+
+INPUT_PORTS_START(keyboard_fr)
+ PORT_INCLUDE(keyboard_us)
+
+ PORT_MODIFY("ROW0")
+ PORT_BIT(0x01, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_A) PORT_CHAR('q') PORT_CHAR('Q')
+
+ PORT_MODIFY("ROW1")
+ PORT_BIT(0x01, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_BACKSLASH2) PORT_CHAR('<') PORT_CHAR('>')
+ 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('=') PORT_CHAR('+')
+ PORT_BIT(0x20, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_V) PORT_CHAR('v') PORT_CHAR('V')
+
+ PORT_MODIFY("ROW2")
+ PORT_BIT(0x01, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_Q) PORT_CHAR('a') PORT_CHAR('A')
+ PORT_BIT(0x02, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_W) PORT_CHAR('z') PORT_CHAR('Z')
+
+ 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(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(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(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(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(U'ˆ') PORT_CHAR(U'¨')
+
+ PORT_MODIFY("ROW6")
+ 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")
+ PORT_BIT(0x01, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_ENTER) PORT_CHAR(0x0d) PORT_NAME("Return")
+ PORT_BIT(0x02, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_M) PORT_CHAR(',') PORT_CHAR('?')
+ PORT_BIT(0x04, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_STOP) PORT_CHAR(':') PORT_CHAR('/')
+ 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_N) PORT_CHAR('n') PORT_CHAR('N')
+ PORT_BIT(0x20, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_COMMA) PORT_CHAR(';') PORT_CHAR('.')
+
+ 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('@') PORT_CHAR('#')
+ PORT_BIT(0x10, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_SPACE) PORT_CHAR(' ')
+INPUT_PORTS_END
+
+INPUT_PORTS_START(keyboard_it)
+ PORT_INCLUDE(keyboard_us)
+
+ PORT_MODIFY("ROW1")
+ PORT_BIT(0x01, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_BACKSLASH2) PORT_CHAR('<') PORT_CHAR('>')
+ 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(U'ò') PORT_CHAR('!')
+ PORT_BIT(0x20, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_V) PORT_CHAR('v') PORT_CHAR('V')
+
+ PORT_MODIFY("ROW2")
+ PORT_BIT(0x02, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_W) PORT_CHAR('z') PORT_CHAR('Z')
+
+ 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('"') 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(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(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(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(U'ì') PORT_CHAR(U'ˆ')
+
+ PORT_MODIFY("ROW6")
+ 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")
+ PORT_BIT(0x01, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_ENTER) PORT_CHAR(0x0d) PORT_NAME("Return")
+ PORT_BIT(0x02, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_M) PORT_CHAR(',') PORT_CHAR('?')
+ PORT_BIT(0x04, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_STOP) PORT_CHAR(':') PORT_CHAR('/')
+ 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_N) PORT_CHAR('n') PORT_CHAR('N')
+ PORT_BIT(0x20, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_COMMA) PORT_CHAR(';') PORT_CHAR('.')
+
+ 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('@') PORT_CHAR('#')
+ PORT_BIT(0x10, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_SPACE) PORT_CHAR(' ')
+INPUT_PORTS_END
+
+INPUT_PORTS_START(keyboard_jp)
+ PORT_INCLUDE(keyboard_us)
+
+ PORT_MODIFY("ROW0")
+ PORT_BIT(0x01, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_A) PORT_CHAR('a') PORT_CHAR('A') PORT_NAME(u8"A \u30c1") // チ
+ PORT_BIT(0x02, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_S) PORT_CHAR('s') PORT_CHAR('S') PORT_NAME(u8"S \u30c8") // ト
+ PORT_BIT(0x04, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_D) PORT_CHAR('d') PORT_CHAR('D') PORT_NAME(u8"D \u30b7") // シ
+ PORT_BIT(0x08, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_F) PORT_CHAR('f') PORT_CHAR('F') PORT_NAME(u8"F \u30cf") // ハ
+ PORT_BIT(0x10, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_H) PORT_CHAR('h') PORT_CHAR('H') PORT_NAME(u8"H \u30af") // ク
+ PORT_BIT(0x20, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_G) PORT_CHAR('g') PORT_CHAR('G') PORT_NAME(u8"G \u30ad") // キ
+
+ PORT_MODIFY("ROW1")
+ PORT_BIT(0x01, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_Z) PORT_CHAR('z') PORT_CHAR('Z') PORT_NAME(u8"Z \u30c4 \u30c3") // ツ ッ
+ PORT_BIT(0x02, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_X) PORT_CHAR('x') PORT_CHAR('X') PORT_NAME(u8"X \u30b5") // サ
+ PORT_BIT(0x04, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_C) PORT_CHAR('c') PORT_CHAR('C') PORT_NAME(u8"C \u30bd") // ソ
+ PORT_BIT(0x08, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_V) PORT_CHAR('v') PORT_CHAR('V') PORT_NAME(u8"V \u30d2") // ヒ
+ PORT_BIT(0x20, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_B) PORT_CHAR('b') PORT_CHAR('B') PORT_NAME(u8"B \u30b3") // コ
+
+ PORT_MODIFY("ROW2")
+ PORT_BIT(0x01, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_Q) PORT_CHAR('q') PORT_CHAR('Q') PORT_NAME(u8"Q \u30bf") // タ
+ PORT_BIT(0x02, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_W) PORT_CHAR('w') PORT_CHAR('W') PORT_NAME(u8"W \u30c6") // テ
+ PORT_BIT(0x04, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_E) PORT_CHAR('e') PORT_CHAR('E') PORT_NAME(u8"E \u30a4 \u30a3") // イ ィ
+ PORT_BIT(0x08, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_R) PORT_CHAR('r') PORT_CHAR('R') PORT_NAME(u8"R \u30b9") // ス
+ PORT_BIT(0x10, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_Y) PORT_CHAR('y') PORT_CHAR('Y') PORT_NAME(u8"Y \u30f3") // ン
+ PORT_BIT(0x20, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_T) PORT_CHAR('t') PORT_CHAR('T') PORT_NAME(u8"T \u30ab") // カ
+
+ PORT_MODIFY("ROW3")
+ PORT_BIT(0x01, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_1) PORT_CHAR('1') PORT_CHAR('!') PORT_NAME(u8"1 ! \u30cc") // ヌ
+ PORT_BIT(0x02, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_2) PORT_CHAR('2') PORT_CHAR('@') PORT_NAME(u8"2 @ \u30d5") // フ
+ PORT_BIT(0x04, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_3) PORT_CHAR('3') PORT_CHAR('#') PORT_NAME(u8"3 # \u30a2 \u30a1") // ア ァ
+ PORT_BIT(0x08, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_4) PORT_CHAR('4') PORT_CHAR('$') PORT_NAME(u8"4 $ \u30a6 \u30a5") // ウ ゥ
+ PORT_BIT(0x10, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_6) PORT_CHAR('6') PORT_CHAR('^') PORT_NAME(u8"6 ^ \u30aa \u30a9") // オ ォ
+ PORT_BIT(0x20, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_5) PORT_CHAR('5') PORT_CHAR('%') PORT_NAME(u8"5 % \u30a8 \u30a7") // エ ェ
+
+ PORT_MODIFY("ROW4")
+ PORT_BIT(0x01, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_EQUALS) PORT_CHAR('=') PORT_CHAR('+') PORT_NAME(u8"= + \u309c \u300c") // ゜ 「
+ PORT_BIT(0x02, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_9) PORT_CHAR('9') PORT_CHAR('(') PORT_NAME(u8"9 ( \u30e8 \u30e7") // ヨ ョ
+ PORT_BIT(0x04, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_7) PORT_CHAR('7') PORT_CHAR('&') PORT_NAME(u8"7 & \u30e4 \u30e3") // ヤ ャ
+ PORT_BIT(0x08, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_MINUS) PORT_CHAR('-') PORT_CHAR('_') PORT_NAME(u8"- _ \u30db") // ホ
+ PORT_BIT(0x10, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_8) PORT_CHAR('8') PORT_CHAR('*') PORT_NAME(u8"8 * \u30e6 \u30e5") // ユ ュ
+ PORT_BIT(0x20, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_0) PORT_CHAR('0') PORT_CHAR(')') PORT_NAME(u8"0 ) \u30ef \u30f2") // ワ ヲ
+
+ PORT_MODIFY("ROW5")
+ PORT_BIT(0x01, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_CLOSEBRACE) PORT_CHAR(']') PORT_CHAR('}') PORT_NAME(u8"] } \u30e0 \u30fc") // ム ー
+ PORT_BIT(0x02, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_O) PORT_CHAR('o') PORT_CHAR('O') PORT_NAME(u8"O \u30e9") // ラ
+ PORT_BIT(0x04, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_U) PORT_CHAR('u') PORT_CHAR('U') PORT_NAME(u8"U \u30ca") // ナ
+ 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_I) PORT_CHAR('i') PORT_CHAR('I') PORT_NAME(u8"I \u30cb") // ニ
+ PORT_BIT(0x20, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_P) PORT_CHAR('p') PORT_CHAR('P') PORT_NAME(u8"P \u30bb") // セ
+
+ PORT_MODIFY("ROW6")
+ PORT_BIT(0x02, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_L) PORT_CHAR('l') PORT_CHAR('L') PORT_NAME(u8"L \u30ea") // リ
+ PORT_BIT(0x04, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_J) PORT_CHAR('j') PORT_CHAR('J') PORT_NAME(u8"J \u30de") // マ
+ PORT_BIT(0x08, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_QUOTE) PORT_CHAR('\'') PORT_CHAR('"') PORT_NAME(u8"' \" \u30b1 \u30ed") // ケ ロ
+ PORT_BIT(0x10, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_K) PORT_CHAR('k') PORT_CHAR('K') PORT_NAME(u8"K \u30ce") // ノ
+ PORT_BIT(0x20, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_COLON) PORT_CHAR(';') PORT_CHAR(':') PORT_NAME(u8"; : \u30ec") // レ
+
+ PORT_MODIFY("ROW7")
+ PORT_BIT(0x01, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_BACKSLASH) PORT_CHAR(U'¥') PORT_CHAR('|') PORT_NAME(u8"¥ | \u30d8") // ヘ
+ PORT_BIT(0x02, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_COMMA) PORT_CHAR(',') PORT_CHAR('<') PORT_NAME(u8", < \u30cd \u3001") // ネ 、
+ PORT_BIT(0x04, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_SLASH) PORT_CHAR('/') PORT_CHAR('?') PORT_NAME(u8"/ ? \u30e1 \u30fb") // メ ・
+ PORT_BIT(0x08, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_N) PORT_CHAR('n') PORT_CHAR('N') PORT_NAME(u8"N \u30df") // ミ
+ PORT_BIT(0x10, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_M) PORT_CHAR('m') PORT_CHAR('M') PORT_NAME(u8"M \u30e2") // モ
+ PORT_BIT(0x20, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_STOP) PORT_CHAR('.') PORT_CHAR('>') PORT_NAME(u8". > \u30eb \u3002") // ル 。
+
+ PORT_MODIFY("P0")
+ PORT_BIT(0x40, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_CAPSLOCK) PORT_CHAR(UCHAR_MAMEKEY(CAPSLOCK)) PORT_NAME(u8"\u30ab\u30ca (Kana)") PORT_TOGGLE // カナ
+INPUT_PORTS_END
+
+
+class m0110_device : public keyboard_base
+{
+public:
+ m0110_device(machine_config const &mconfig, char const *tag, device_t *owner, u32 clock)
+ : keyboard_base(mconfig, MACKBD_M0110, tag, owner, clock)
+ {
+ }
+
+protected:
+ virtual ioport_constructor device_input_ports() const override
+ {
+ return INPUT_PORTS_NAME(keyboard_us);
+ }
+};
+
+class m0110b_device : public keyboard_base
+{
+public:
+ m0110b_device(machine_config const &mconfig, char const *tag, device_t *owner, u32 clock)
+ : keyboard_base(mconfig, MACKBD_M0110B, tag, owner, clock)
+ {
+ }
+
+ static auto parent_rom_device_type() { return &MACKBD_M0110; }
+
+protected:
+ virtual ioport_constructor device_input_ports() const override
+ {
+ return INPUT_PORTS_NAME(keyboard_gb);
+ }
+};
+
+class m0110f_device : public keyboard_base
+{
+public:
+ m0110f_device(machine_config const &mconfig, char const *tag, device_t *owner, u32 clock)
+ : keyboard_base(mconfig, MACKBD_M0110F, tag, owner, clock)
+ {
+ }
+
+ static auto parent_rom_device_type() { return &MACKBD_M0110; }
+
+protected:
+ virtual ioport_constructor device_input_ports() const override
+ {
+ return INPUT_PORTS_NAME(keyboard_fr);
+ }
+};
+
+class m0110t_device : public keyboard_base
+{
+public:
+ m0110t_device(machine_config const &mconfig, char const *tag, device_t *owner, u32 clock)
+ : keyboard_base(mconfig, MACKBD_M0110T, tag, owner, clock)
+ {
+ }
+
+ static auto parent_rom_device_type() { return &MACKBD_M0110; }
+
+protected:
+ virtual ioport_constructor device_input_ports() const override
+ {
+ return INPUT_PORTS_NAME(keyboard_it);
+ }
+};
+
+class m0110j_device : public keyboard_base
+{
+public:
+ m0110j_device(machine_config const &mconfig, char const *tag, device_t *owner, u32 clock)
+ : keyboard_base(mconfig, MACKBD_M0110J, tag, owner, clock)
+ {
+ }
+
+ static auto parent_rom_device_type() { return &MACKBD_M0110; }
+
+protected:
+ virtual ioport_constructor device_input_ports() const override
+ {
+ return INPUT_PORTS_NAME(keyboard_jp);
+ }
+};
+
+
+INPUT_PORTS_START(keypad)
+ PORT_START("ROW0")
+ PORT_BIT(0x01, IP_ACTIVE_LOW, IPT_KEYPAD) PORT_CODE(KEYCODE_MINUS_PAD) PORT_CHAR(UCHAR_MAMEKEY(SLASH_PAD)) PORT_NAME("Keypad / (Up)")
+ PORT_BIT(0x02, IP_ACTIVE_LOW, IPT_KEYPAD) PORT_CODE(KEYCODE_EQUALS_PAD) PORT_CHAR(UCHAR_MAMEKEY(MINUS_PAD)) PORT_NAME("Keypad -")
+ PORT_BIT(0x04, IP_ACTIVE_LOW, IPT_KEYPAD) PORT_CODE(KEYCODE_ENTER_PAD) PORT_CHAR(UCHAR_MAMEKEY(ENTER_PAD)) PORT_NAME("Keypad Enter")
+
+ PORT_START("ROW1")
+ PORT_BIT(0x01, IP_ACTIVE_LOW, IPT_KEYPAD) PORT_CODE(KEYCODE_NUMLOCK) PORT_CHAR(UCHAR_MAMEKEY(NUMLOCK)) PORT_NAME("Keypad Clear")
+ PORT_BIT(0x02, IP_ACTIVE_LOW, IPT_KEYPAD) PORT_CODE(KEYCODE_PLUS_PAD) PORT_CHAR(UCHAR_MAMEKEY(COMMA_PAD)) PORT_NAME("Keypad , (Down)")
+ PORT_BIT(0x04, IP_ACTIVE_LOW, IPT_KEYPAD) PORT_CODE(KEYCODE_SLASH_PAD) PORT_CHAR(UCHAR_MAMEKEY(PLUS_PAD)) PORT_NAME("Keypad + (Left)")
+
+ PORT_START("ROW2")
+ PORT_BIT(0x01, IP_ACTIVE_LOW, IPT_KEYPAD) PORT_CODE(KEYCODE_DEL_PAD) PORT_CHAR(UCHAR_MAMEKEY(DEL_PAD)) PORT_NAME("Keypad .")
+ PORT_BIT(0x02, IP_ACTIVE_LOW, IPT_KEYPAD) PORT_CODE(KEYCODE_ASTERISK) PORT_CHAR(UCHAR_MAMEKEY(ASTERISK)) PORT_NAME("Keypad * (Right)")
+ PORT_BIT(0x04, IP_ACTIVE_LOW, IPT_UNUSED)
+
+ PORT_START("P0")
+ PORT_BIT(0x07, IP_ACTIVE_LOW, IPT_UNUSED)
+ PORT_BIT(0x08, IP_ACTIVE_LOW, IPT_KEYPAD) PORT_CODE(KEYCODE_8_PAD) PORT_CHAR(UCHAR_MAMEKEY(8_PAD)) PORT_NAME("Keypad 8")
+ PORT_BIT(0x10, IP_ACTIVE_LOW, IPT_KEYPAD) PORT_CODE(KEYCODE_9_PAD) PORT_CHAR(UCHAR_MAMEKEY(9_PAD)) PORT_NAME("Keypad 9")
+ PORT_BIT(0x20, IP_ACTIVE_HIGH, IPT_CUSTOM)
+ PORT_BIT(0x40, IP_ACTIVE_LOW, IPT_CUSTOM) PORT_CUSTOM_MEMBER(FUNC(keypad_base::keyboard_clock_r))
+ PORT_BIT(0x80, IP_ACTIVE_LOW, IPT_UNUSED)
+
+ PORT_START("P1")
+ PORT_BIT(0x01, IP_ACTIVE_LOW, IPT_KEYPAD) PORT_CODE(KEYCODE_0_PAD) PORT_CHAR(UCHAR_MAMEKEY(0_PAD)) PORT_NAME("Keypad 0")
+ PORT_BIT(0x02, IP_ACTIVE_LOW, IPT_KEYPAD) PORT_CODE(KEYCODE_1_PAD) PORT_CHAR(UCHAR_MAMEKEY(1_PAD)) PORT_NAME("Keypad 1")
+ PORT_BIT(0x04, IP_ACTIVE_LOW, IPT_KEYPAD) PORT_CODE(KEYCODE_2_PAD) PORT_CHAR(UCHAR_MAMEKEY(2_PAD)) PORT_NAME("Keypad 2")
+ PORT_BIT(0x08, IP_ACTIVE_LOW, IPT_KEYPAD) PORT_CODE(KEYCODE_3_PAD) PORT_CHAR(UCHAR_MAMEKEY(3_PAD)) PORT_NAME("Keypad 3")
+ PORT_BIT(0x10, IP_ACTIVE_LOW, IPT_KEYPAD) PORT_CODE(KEYCODE_4_PAD) PORT_CHAR(UCHAR_MAMEKEY(4_PAD)) PORT_NAME("Keypad 4")
+ PORT_BIT(0x20, IP_ACTIVE_LOW, IPT_KEYPAD) PORT_CODE(KEYCODE_5_PAD) PORT_CHAR(UCHAR_MAMEKEY(5_PAD)) PORT_NAME("Keypad 5")
+ PORT_BIT(0x40, IP_ACTIVE_LOW, IPT_KEYPAD) PORT_CODE(KEYCODE_6_PAD) PORT_CHAR(UCHAR_MAMEKEY(6_PAD)) PORT_NAME("Keypad 6")
+ PORT_BIT(0x80, IP_ACTIVE_LOW, IPT_KEYPAD) PORT_CODE(KEYCODE_7_PAD) PORT_CHAR(UCHAR_MAMEKEY(7_PAD)) PORT_NAME("Keypad 7")
+
+ PORT_START("P2")
+ PORT_BIT(0x01, IP_ACTIVE_LOW, IPT_CUSTOM) PORT_CUSTOM_MEMBER(FUNC(keypad_base::host_data_r))
+ PORT_BIT(0x02, IP_ACTIVE_LOW, IPT_CUSTOM) PORT_CUSTOM_MEMBER(FUNC(keypad_base::keyboard_data_r))
+ PORT_BIT(0x0c, IP_ACTIVE_LOW, IPT_CUSTOM) PORT_CUSTOM_MEMBER(FUNC(keypad_base::columns_r))
+INPUT_PORTS_END
+
+INPUT_PORTS_START(keypad_eu)
+ PORT_INCLUDE(keypad)
+
+ PORT_MODIFY("ROW1")
+ PORT_BIT(0x02, IP_ACTIVE_LOW, IPT_KEYPAD) PORT_CODE(KEYCODE_PLUS_PAD) PORT_CHAR(UCHAR_MAMEKEY(COMMA_PAD)) PORT_NAME("Keypad . (Down)")
+
+ PORT_MODIFY("ROW2")
+ PORT_BIT(0x01, IP_ACTIVE_LOW, IPT_KEYPAD) PORT_CODE(KEYCODE_DEL_PAD) PORT_CHAR(UCHAR_MAMEKEY(DEL_PAD)) PORT_NAME("Keypad ,")
+INPUT_PORTS_END
+
+
+class m0120_device : public keypad_base
+{
+public:
+ m0120_device(machine_config const &mconfig, char const *tag, device_t *owner, u32 clock)
+ : keypad_base(mconfig, MACKBD_M0120, tag, owner, clock)
+ {
+ }
+
+ static auto parent_rom_device_type() { return &MACKBD_M0110; }
+
+protected:
+ virtual ioport_constructor device_input_ports() const override
+ {
+ return INPUT_PORTS_NAME(keypad);
+ }
+};
+
+class m0120p_device : public keypad_base
+{
+public:
+ m0120p_device(machine_config const &mconfig, char const *tag, device_t *owner, u32 clock)
+ : keypad_base(mconfig, MACKBD_M0120P, tag, owner, clock)
+ {
+ }
+
+ static auto parent_rom_device_type() { return &MACKBD_M0110; }
+
+protected:
+ virtual void device_add_mconfig(machine_config &config) override
+ {
+ keypad_base::device_add_mconfig(config);
+
+ m_keyboard_port->set_default_option("fr");
+ }
+
+ virtual ioport_constructor device_input_ports() const override
+ {
+ return INPUT_PORTS_NAME(keypad_eu);
+ }
+};
+
+} // anonymous namespace
+
+
+DEFINE_DEVICE_TYPE_PRIVATE(MACKBD_M0110, device_mac_keyboard_interface, m0110_device, "mackbd_m0110", "Macintosh Keyboard (U.S. - M0110)")
+DEFINE_DEVICE_TYPE_PRIVATE(MACKBD_M0110B, device_mac_keyboard_interface, m0110b_device, "mackbd_m0110b", "Macintosh Keyboard (British - M0110B)")
+DEFINE_DEVICE_TYPE_PRIVATE(MACKBD_M0110F, device_mac_keyboard_interface, m0110f_device, "mackbd_m0110f", "Macintosh Keyboard (French - M0110F)")
+DEFINE_DEVICE_TYPE_PRIVATE(MACKBD_M0110T, device_mac_keyboard_interface, m0110t_device, "mackbd_m0110t", "Macintosh Keyboard (Italian - M0110T)")
+DEFINE_DEVICE_TYPE_PRIVATE(MACKBD_M0110J, device_mac_keyboard_interface, m0110j_device, "mackbd_m0110j", "Macintosh Keyboard (Japanese - M0110J)")
+
+DEFINE_DEVICE_TYPE_PRIVATE(MACKBD_M0120, device_mac_keyboard_interface, m0120_device, "mackbd_m0120", "Macintosh Numeric Keypad (English - M0120)")
+DEFINE_DEVICE_TYPE_PRIVATE(MACKBD_M0120P, device_mac_keyboard_interface, m0120p_device, "mackbd_m0120p", "Macintosh Numeric Keypad (European - M0120P)")
diff --git a/src/devices/bus/mackbd/keyboard.h b/src/devices/bus/mackbd/keyboard.h
new file mode 100644
index 00000000000..a4a51848bc6
--- /dev/null
+++ b/src/devices/bus/mackbd/keyboard.h
@@ -0,0 +1,24 @@
+// license: BSD-3-Clause
+// copyright-holders: Vas Crabb
+/***************************************************************************
+
+ Apple M0110/M0120 keyboard/keypad
+
+***************************************************************************/
+#ifndef MAME_BUS_MACKBD_KEYBOARD_H
+#define MAME_BUS_MACKBD_KEYBOARD_H
+
+#pragma once
+
+#include "mackbd.h"
+
+DECLARE_DEVICE_TYPE(MACKBD_M0110, device_mac_keyboard_interface)
+DECLARE_DEVICE_TYPE(MACKBD_M0110B, device_mac_keyboard_interface)
+DECLARE_DEVICE_TYPE(MACKBD_M0110F, device_mac_keyboard_interface)
+DECLARE_DEVICE_TYPE(MACKBD_M0110T, device_mac_keyboard_interface)
+DECLARE_DEVICE_TYPE(MACKBD_M0110J, device_mac_keyboard_interface)
+
+DECLARE_DEVICE_TYPE(MACKBD_M0120, device_mac_keyboard_interface)
+DECLARE_DEVICE_TYPE(MACKBD_M0120P, device_mac_keyboard_interface)
+
+#endif // MAME_BUS_MACKBD_KEYBOARD_H
diff --git a/src/devices/bus/mackbd/mackbd.cpp b/src/devices/bus/mackbd/mackbd.cpp
new file mode 100644
index 00000000000..458e7772800
--- /dev/null
+++ b/src/devices/bus/mackbd/mackbd.cpp
@@ -0,0 +1,176 @@
+// license: BSD-3-Clause
+// copyright-holders: Vas Crabb
+/***************************************************************************
+
+ Mac 128k/512k/Plus keyboard interface (pre-ADB)
+
+ Two-wire protocol designed to avoid the need for an accurate/stable
+ clock source in the keyboard. This is not a multi-drop bus. In
+ cases where peripherals are daisy-chained, the upstream peripheral
+ acts as a host for the downstream peripheral.
+
+ In the idle state, both signal lines are high, pulled up using
+ resistors. All transactions are initiated by the host, but the
+ timing is controlled entirely by the peripheral. The data signal
+ must be valid on the rising edge of the clock signal. The data is
+ not inverted.
+
+ Transaction steps (ignoring mandatory delays):
+ * Host pulls down data line to initiate transfer
+ * Peripheral reads one octet (eight bits) from host, MSB first:
+ - Peripheral pulls clock line low
+ - Host sets bit on data line
+ - Peripheral releases clock line
+ - Peripheral samples data line
+ - Repeat for remaining bits of octet
+ * Host releases data line
+ * Peripheral sends one octet (eight bits) to host, MSB first:
+ - Peripheral places bit on data line
+ - Peripheral pulls clock line low
+ - Peripheral releases clock line
+ - Host samples data line
+ - Repeat for remaining bits of octet
+ * Peripheral releases data line
+
+ The last bit (LSB) of the octet transferred from the host to the
+ peripheral is always zero. This allows the host to hold the data
+ line low until it's ready to receive the response from the
+ peripheral. The last bit of the octet transferred from the
+ peripheral to the host is always high.
+
+ Some transactions expect an immediate response while others allow
+ the peripheral to delay the response if it has no data to send
+ immediately. The host polls the peripheral continuously. If no
+ response is received in about 500ms, the host assumes the
+ peripheral has crashed/reset or has been unplugged, and will
+ attempt to re-establish communication.
+
+ Transactions:
+ * 0x10: Permission to send
+ Peripheral responds immediately with data if avaiblable. If no
+ data is available, peripheral waits for data and responds when it
+ becomes available. If no data is available after 250ms, the
+ peripheral responds with 0x7b to hand control back to the host.
+ * 0x14: Request to send
+ Peripheral responds immediately with data, or 0x7b if no data is
+ available.
+ * 0x16: Reset and identify
+ Peripheral responds with identification code.
+ - 0x03: M0110 compact keyboard
+ - 0x0b: M0110A Mac Plus keyboard
+ - 0x11: M0120 numeric keypad
+ - 0x13: M0120 numeric keypad with M0110 compact keyboard
+ - 0x1b: M0120 numeric keypad with M0110A Mac Plus keyboard
+ - 0x27: Assimilation Process keypad with M0110 keyboard???
+ * 0x36: Perform self test
+ Peripheral responds with 0x7d (pass) or 0x77 (failure).
+
+ Responses to polling commands 0x10 and 0x14 have the first bit clear
+ for key down events or set for key up events.
+
+ The keypad passes polling commands 0x10 and 0x14 on to the keyboard
+ if it has no response to send. If the keypad has a key transition
+ to report, it responds with the octet 0x79. After receiving this
+ response, the host should send command 0x10 to receive the key
+ transition event from the keypad.
+
+ Additionally, if bit 5 of the octet sent to the peripheral is set
+ (0x40), the octet is passed on to a daisy-chained peripheral with
+ this bit cleared. The response from the daisy-chained peripheral is
+ passed back to the host. If the transaction to the daisy-chained
+ peripheral times out, the peripheral sends the response 0x77 to the
+ host.
+
+ TODO:
+ * Dump/emulate newer versions of Apple keyboards (GI PIC1657 based)
+ * Emulate Music Publisher music notation input pad
+ * Emulate Assimilation Process keypad (and trackball)
+
+***************************************************************************/
+
+#include "emu.h"
+#include "mackbd.h"
+
+
+DEFINE_DEVICE_TYPE(MAC_KEYBOARD_PORT, mac_keyboard_port_device, "mackbd_port", "Macintosh 128k/512k/Plus Keyboard Port")
+
+
+//**************************************************************************
+// HOST PORT
+//**************************************************************************
+
+mac_keyboard_port_device::mac_keyboard_port_device(machine_config const &mconfig, char const *tag, device_t *owner, u32 clock)
+ : device_t(mconfig, MAC_KEYBOARD_PORT, tag, owner, clock)
+ , device_single_card_slot_interface<device_mac_keyboard_interface>(mconfig, *this)
+ , m_clock_cb{ *this }
+ , m_data_cb{ *this }
+ , m_peripheral{ nullptr }
+{
+}
+
+mac_keyboard_port_device::~mac_keyboard_port_device()
+{
+}
+
+void mac_keyboard_port_device::data_w(int state)
+{
+ if (m_peripheral)
+ m_peripheral->data_w(state);
+}
+
+void mac_keyboard_port_device::device_start()
+{
+ m_peripheral = dynamic_cast<device_mac_keyboard_interface *>(get_card_device());
+}
+
+
+//**************************************************************************
+// PERIPHERAL INTERFACE
+//**************************************************************************
+
+device_mac_keyboard_interface::device_mac_keyboard_interface(machine_config const &mconfig, device_t &device)
+ : device_interface(device, "mackbd")
+ , m_host{ dynamic_cast<mac_keyboard_port_device *>(device.owner()) }
+{
+}
+
+device_mac_keyboard_interface::~device_mac_keyboard_interface()
+{
+}
+
+void device_mac_keyboard_interface::interface_validity_check(validity_checker &valid) const
+{
+ device_t *const owner(device().owner());
+ if (owner && dynamic_cast<device_slot_interface *>(owner) && !dynamic_cast<mac_keyboard_port_device *>(owner))
+ osd_printf_error("Device %s (%s) is not a Macintosh keyboard port\n", owner->tag(), owner->name());
+}
+
+
+//**************************************************************************
+// SUPPORTED DEVICES
+//**************************************************************************
+
+#include "keyboard.h"
+#include "pluskbd.h"
+
+
+// must come after including the headers that declare these extern
+template class device_finder<device_mac_keyboard_interface, false>;
+template class device_finder<device_mac_keyboard_interface, true>;
+
+
+void mac_keyboard_devices(device_slot_interface &device)
+{
+ device.option_add("us", MACKBD_M0110);
+ device.option_add("gb", MACKBD_M0110B);
+ device.option_add("fr", MACKBD_M0110F);
+ device.option_add("it", MACKBD_M0110T);
+ device.option_add("jp", MACKBD_M0110J);
+
+ device.option_add("pad", MACKBD_M0120);
+ device.option_add("eupad", MACKBD_M0120P);
+
+ device.option_add("usp", MACKBD_M0110A);
+ device.option_add("frp", MACKBD_M0110A_F);
+ device.option_add("jpp", MACKBD_M0110A_J);
+}
diff --git a/src/devices/bus/mackbd/mackbd.h b/src/devices/bus/mackbd/mackbd.h
new file mode 100644
index 00000000000..bfdd8397640
--- /dev/null
+++ b/src/devices/bus/mackbd/mackbd.h
@@ -0,0 +1,90 @@
+// license: BSD-3-Clause
+// copyright-holders: Vas Crabb
+/***************************************************************************
+
+ Mac 128k/512k/Plus keyboard interface (pre-ADB)
+
+ 4p4c RJ11 connector (cables wired straight through):
+ 1: power/signal ground (black)
+ 2: clock (red, peripheral to host)
+ 3: data (green, bidirectional)
+ 4: +5V power (yellow, maximum 200mA for all peripherals)
+
+***************************************************************************/
+#ifndef MAME_BUS_MACKBD_MACKBD_H
+#define MAME_BUS_MACKBD_MACKBD_H
+
+#pragma once
+
+
+class device_mac_keyboard_interface;
+
+DECLARE_DEVICE_TYPE(MAC_KEYBOARD_PORT, mac_keyboard_port_device)
+
+void mac_keyboard_devices(device_slot_interface &device);
+
+
+//**************************************************************************
+// HOST PORT
+//**************************************************************************
+
+class mac_keyboard_port_device : public device_t, public device_single_card_slot_interface<device_mac_keyboard_interface>
+{
+public:
+ template <typename T>
+ mac_keyboard_port_device(machine_config const &mconfig, char const *tag, device_t *owner, T &&opts, char const *dflt)
+ : mac_keyboard_port_device(mconfig, tag, owner, 0U)
+ {
+ option_reset();
+ opts(*this);
+ set_default_option(dflt);
+ set_fixed(false);
+ }
+ mac_keyboard_port_device(machine_config const &mconfig, char const *tag, device_t *owner, u32 clock = 0U);
+ virtual ~mac_keyboard_port_device() override;
+
+ auto clock_cb() { return m_clock_cb.bind(); }
+ auto data_cb() { return m_data_cb.bind(); }
+
+ void data_w(int state);
+
+protected:
+ virtual void device_start() override ATTR_COLD;
+
+private:
+ devcb_write_line m_clock_cb;
+ devcb_write_line m_data_cb;
+
+ device_mac_keyboard_interface *m_peripheral;
+
+ friend class device_mac_keyboard_interface;
+};
+
+
+//**************************************************************************
+// PERIPHERAL INTERFACE
+//**************************************************************************
+
+class device_mac_keyboard_interface : public device_interface
+{
+public:
+ virtual ~device_mac_keyboard_interface() override;
+
+protected:
+ device_mac_keyboard_interface(machine_config const &mconfig, device_t &device);
+
+ virtual void interface_validity_check(validity_checker &valid) const override;
+
+ 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 void data_w(int state) = 0;
+
+private:
+ mac_keyboard_port_device *const m_host;
+
+ friend class mac_keyboard_port_device;
+};
+
+
+#endif // MAME_BUS_MACKBD_MACKBD_H
diff --git a/src/devices/bus/mackbd/pluskbd.cpp b/src/devices/bus/mackbd/pluskbd.cpp
new file mode 100644
index 00000000000..ec024264df9
--- /dev/null
+++ b/src/devices/bus/mackbd/pluskbd.cpp
@@ -0,0 +1,508 @@
+// license: BSD-3-Clause
+// copyright-holders: Vas Crabb
+/***************************************************************************
+
+ Apple M0110A keyboard with integrated keypad
+
+ This keyboard emulates an M0120 keypad with an M0110 keyboard
+ plugged in to it. Keypad keys and arrow keys produce scan codes
+ with the 0x79 prefix. The keyboard simulates holding shift when
+ pressing the = / * + keys on the keypad.
+
+ This keyboard was only available in ANSI layout, no ISO layout
+ variants were made. International markets continued to receive the
+ M0110/M0120 keyboard/keypad. International variants of the M0110A
+ were eventually produced, differing only in key cap labels. All
+ keys have the same shapes, sizes, positions and scan codes as they
+ do on the U.S. version.
+
+ Emulation based entirely on examining the MPU program and observing
+ behaviour. There may be additional hardware in the keyboard that is
+ not emulated (e.g. a watchdog timer).
+
+ +-----------+---------------+
+ | Pin | Keyboard |
+ +-----------+---------------+
+ | P10 (27) | row drive |
+ | P11 (28) | row drive |
+ | P12 (29) | row drive |
+ | P13 (30) | row drive |
+ | P14 (31) | row drive |
+ | P15 (32) | row drive |
+ | P16 (33) | row drive |
+ | P17 (34) | row drive |
+ +-----------+---------------+
+ | P20 (21) | row drive |
+ | P21 (22) | row drive |
+ | P22 (23) | Shift |
+ | P23 (24) | Caps Lock |
+ | P24 (35) | Option |
+ | P25 (36) | Command |
+ | P26 (37) | host clock |
+ | P27 (38) | host data |
+ +-----------+---------------+
+ | DB0 (12) | column read |
+ | DB1 (13) | column read |
+ | DB2 (14) | column read |
+ | DB3 (15) | column read |
+ | DB4 (16) | column read |
+ | DB5 (17) | column read |
+ | DB6 (18) | column read |
+ | DB6 (19) | column read |
+ +-----------+---------------+
+
+ +-----+-----------------------------------------------------------+
+ | | P10 P11 P12 P13 P14 P15 P16 P17 P20 P21 |
+ +-----+-----------------------------------------------------------+
+ | DB0 | \ Left Right Down KP0 KP. Ent |
+ | DB1 | KP* KP/ KP= Clear Bsp = - 0 Z |
+ | DB2 | KP8 KP9 KP- Up KP1 KP2 KP3 KP+ KP7 |
+ | DB3 | P [ ] ' Rtn KP4 KP5 KP6 Spc |
+ | DB4 | D F G H J K L ; A S |
+ | DB5 | W E R T Y U I O Tab Q |
+ | DB6 | 2 3 4 5 6 7 8 9 ` 1 |
+ | DB7 | V B N M , . / X C |
+ +-----+-----------------------------------------------------------+
+
+ Known part numbers:
+ * M0110A (U.S.)
+ * M0110A F (French)
+ * M0110A J (Japanese)
+
+ The French version has icons rather than English text for Backspace,
+ Tab, Caps Lock, Return, Shift, Option, Clear and Enter.
+
+ 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 still has the ANSI "typewriter
+ shift" arrangement for Latin characters and ASCII punctuation (it
+ doesn't use the JIS "bit shift" arrangement).
+
+***************************************************************************/
+
+#include "emu.h"
+#include "pluskbd.h"
+
+#include "cpu/mcs48/mcs48.h"
+
+#define LOG_MATRIX (1U << 1)
+#define LOG_COMM (1U << 2)
+
+//#define VERBOSE (LOG_GENERAL | LOG_MATRIX | LOG_COMM)
+//#define LOG_OUTPUT_STREAM std::cerr
+#include "logmacro.h"
+
+#define LOGMATRIX(...) LOGMASKED(LOG_MATRIX, __VA_ARGS__)
+#define LOGCOMM(...) LOGMASKED(LOG_COMM, __VA_ARGS__)
+
+
+namespace {
+
+ROM_START(keyboard)
+ ROM_REGION(0x0400, "mpu", 0)
+ ROM_LOAD("341-0332-a.bin", 0x000000, 0x000400, CRC(6554f5b6) SHA1(a80404a122d74721cda13b285c412057c2c78bd7))
+ROM_END
+
+
+class keyboard_base : public device_t, public device_mac_keyboard_interface
+{
+public:
+ ioport_value host_data_r()
+ {
+ return m_host_data_in ^ 0x01;
+ }
+
+protected:
+ keyboard_base(machine_config const &mconfig, device_type type, char const *tag, device_t *owner, u32 clock)
+ : device_t(mconfig, type, tag, owner, clock)
+ , device_mac_keyboard_interface(mconfig, *this)
+ , m_mpu{ *this, "mpu" }
+ , m_rows{ *this, "ROW%u", 0U }
+ {
+ }
+
+ virtual tiny_rom_entry const *device_rom_region() const override
+ {
+ return ROM_NAME(keyboard);
+ }
+
+ virtual void device_add_mconfig(machine_config &config) override
+ {
+ I8048(config, m_mpu, 6_MHz_XTAL); // NEC 8048HC517 341-0332-A with ceramic resonator
+ m_mpu->set_addrmap(AS_IO, &keyboard_base::mpu_io);
+ m_mpu->p1_out_cb().set(FUNC(keyboard_base::p1_w));
+ m_mpu->p2_in_cb().set_ioport("P2");
+ m_mpu->p2_out_cb().set(FUNC(keyboard_base::p2_w));
+ m_mpu->bus_in_cb().set(FUNC(keyboard_base::bus_r));
+ }
+
+ virtual void device_start() override
+ {
+ m_row_drive = 0x03ffU;
+ m_host_clock_out = 1U;
+ m_host_data_out = 1U;
+ m_host_data_in = 0x01U;
+
+ save_item(NAME(m_row_drive));
+ save_item(NAME(m_host_clock_out));
+ save_item(NAME(m_host_data_out));
+ save_item(NAME(m_host_data_in));
+ }
+
+ virtual void data_w(int state) override
+ {
+ machine().scheduler().synchronize(timer_expired_delegate(FUNC(keyboard_base::update_host_data), this), state);
+ }
+
+private:
+ void p1_w(u8 data)
+ {
+ m_row_drive = (m_row_drive & 0x0300) | u16(data);
+ }
+
+ void p2_w(u8 data)
+ {
+ m_row_drive = (m_row_drive & 0x00ff) | (u16(data & 0x03) << 8);
+
+ if (BIT(data, 6) != m_host_clock_out)
+ {
+ if (BIT(data, 6))
+ LOGCOMM("%s: host clock out 0 -> 1 data=%u\n", machine().describe_context(), (m_host_data_out && m_host_data_in) ? 1U : 0U);
+ else
+ LOGCOMM("%s: host clock out 1 -> 0\n", machine().describe_context());
+ write_clock(m_host_clock_out = BIT(data, 6));
+ }
+
+ if (BIT(data, 7) != m_host_data_out)
+ {
+ LOGCOMM("%s: host data out %u -> %u\n", machine().describe_context(), m_host_data_out, BIT(data, 7));
+ write_data(m_host_data_out = BIT(data, 7));
+ }
+ }
+
+ u8 bus_r()
+ {
+ u8 result(0xffU);
+ for (unsigned i = 0U; m_rows.size() > i; ++i)
+ {
+ if (!BIT(m_row_drive, i))
+ result &= m_rows[i]->read();
+ }
+ LOGMATRIX("read matrix: row drive = %X, result = %X\n", m_row_drive, result);
+ return result;
+ }
+
+ void mpu_io(address_map &map)
+ {
+ // MPU writes 0xff to these addresses before reading columns to ensure the bus pins aren't pulled down
+ map(0x2a, 0x33).nopw();
+ }
+
+ TIMER_CALLBACK_MEMBER(update_host_data)
+ {
+ if (bool(param) != bool(m_host_data_in))
+ {
+ LOGCOMM("host data in %u -> %u\n", m_host_data_in, param ? 1U : 0U);
+ m_host_data_in = param ? 0x01U : 0x00U;
+ }
+ }
+
+ required_device<mcs48_cpu_device> m_mpu;
+ required_ioport_array<10> m_rows;
+
+ u16 m_row_drive = 0x03ffU; // current bit pattern driving rows (active low)
+ u8 m_host_clock_out = 1U; // clock line drive to host (idle high)
+ u8 m_host_data_out = 1U; // data line drive to host (idle high)
+ u8 m_host_data_in = 0x01U; // data line drive from host (idle high)
+};
+
+
+INPUT_PORTS_START(keyboard_us)
+ PORT_START("ROW0")
+ PORT_BIT(0x01, IP_ACTIVE_LOW, IPT_UNUSED)
+ PORT_BIT(0x02, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_ASTERISK) PORT_CHAR(UCHAR_MAMEKEY(ASTERISK)) PORT_NAME("Keypad *")
+ PORT_BIT(0x04, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_8_PAD) PORT_CHAR(UCHAR_MAMEKEY(8_PAD)) PORT_NAME("Keypad 8")
+ 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_D) PORT_CHAR('d') PORT_CHAR('D')
+ PORT_BIT(0x20, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_W) PORT_CHAR('w') PORT_CHAR('W')
+ PORT_BIT(0x40, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_2) PORT_CHAR('2') PORT_CHAR('@')
+ PORT_BIT(0x80, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_V) PORT_CHAR('v') PORT_CHAR('V')
+
+ PORT_START("ROW1")
+ 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_CODE(KEYCODE_SLASH_PAD) PORT_CHAR(UCHAR_MAMEKEY(SLASH_PAD)) PORT_NAME("Keypad /")
+ PORT_BIT(0x04, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_9_PAD) PORT_CHAR(UCHAR_MAMEKEY(9_PAD)) PORT_NAME("Keypad 9")
+ PORT_BIT(0x08, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_OPENBRACE) PORT_CHAR('[') PORT_CHAR('{')
+ PORT_BIT(0x10, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_F) PORT_CHAR('f') PORT_CHAR('F')
+ PORT_BIT(0x20, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_E) PORT_CHAR('e') PORT_CHAR('E')
+ PORT_BIT(0x40, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_3) PORT_CHAR('3') PORT_CHAR('#')
+ PORT_BIT(0x80, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_B) PORT_CHAR('b') PORT_CHAR('B')
+
+ PORT_START("ROW2")
+ PORT_BIT(0x01, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_LEFT) PORT_CHAR(UCHAR_MAMEKEY(LEFT))
+ PORT_BIT(0x02, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_EQUALS_PAD) PORT_CHAR(UCHAR_MAMEKEY(EQUALS_PAD)) PORT_NAME("Keypad =")
+ PORT_BIT(0x04, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_MINUS_PAD) PORT_CHAR(UCHAR_MAMEKEY(MINUS_PAD)) PORT_NAME("Keypad -")
+ PORT_BIT(0x08, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_CLOSEBRACE) PORT_CHAR(']') PORT_CHAR('}')
+ PORT_BIT(0x10, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_G) PORT_CHAR('g') PORT_CHAR('G')
+ PORT_BIT(0x20, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_R) PORT_CHAR('r') PORT_CHAR('R')
+ PORT_BIT(0x40, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_4) PORT_CHAR('4') PORT_CHAR('$')
+ PORT_BIT(0x80, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_N) PORT_CHAR('n') PORT_CHAR('N')
+
+ PORT_START("ROW3")
+ PORT_BIT(0x01, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_RIGHT) PORT_CHAR(UCHAR_MAMEKEY(RIGHT))
+ PORT_BIT(0x02, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_NUMLOCK) PORT_CHAR(UCHAR_MAMEKEY(NUMLOCK)) PORT_NAME("Keypad Clear")
+ PORT_BIT(0x04, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_UP) PORT_CHAR(UCHAR_MAMEKEY(UP))
+ PORT_BIT(0x08, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_QUOTE) PORT_CHAR('\'') PORT_CHAR('"')
+ PORT_BIT(0x10, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_H) PORT_CHAR('h') PORT_CHAR('H')
+ PORT_BIT(0x20, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_T) PORT_CHAR('t') PORT_CHAR('T')
+ PORT_BIT(0x40, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_5) PORT_CHAR('5') PORT_CHAR('%')
+ PORT_BIT(0x80, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_M) PORT_CHAR('m') PORT_CHAR('M')
+
+ PORT_START("ROW4")
+ PORT_BIT(0x01, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_DOWN) PORT_CHAR(UCHAR_MAMEKEY(DOWN))
+ PORT_BIT(0x02, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_BACKSPACE) PORT_CHAR(0x08) PORT_NAME("Backspace")
+ PORT_BIT(0x04, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_1_PAD) PORT_CHAR(UCHAR_MAMEKEY(1_PAD)) PORT_NAME("Keypad 1")
+ PORT_BIT(0x08, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_ENTER) PORT_CHAR(0x0d) PORT_NAME("Return")
+ PORT_BIT(0x10, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_J) PORT_CHAR('j') PORT_CHAR('J')
+ PORT_BIT(0x20, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_Y) PORT_CHAR('y') PORT_CHAR('Y')
+ PORT_BIT(0x40, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_6) PORT_CHAR('6') PORT_CHAR('^')
+ PORT_BIT(0x80, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_COMMA) PORT_CHAR(',') PORT_CHAR('<')
+
+ PORT_START("ROW5")
+ PORT_BIT(0x01, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_0_PAD) PORT_CHAR(UCHAR_MAMEKEY(0_PAD)) PORT_NAME("Keypad 0")
+ PORT_BIT(0x02, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_EQUALS) PORT_CHAR('=') PORT_CHAR('+')
+ PORT_BIT(0x04, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_2_PAD) PORT_CHAR(UCHAR_MAMEKEY(2_PAD)) PORT_NAME("Keypad 2")
+ PORT_BIT(0x08, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_4_PAD) PORT_CHAR(UCHAR_MAMEKEY(4_PAD)) PORT_NAME("Keypad 4")
+ PORT_BIT(0x10, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_K) PORT_CHAR('k') PORT_CHAR('K')
+ PORT_BIT(0x20, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_U) PORT_CHAR('u') PORT_CHAR('U')
+ PORT_BIT(0x40, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_7) PORT_CHAR('7') PORT_CHAR('&')
+ PORT_BIT(0x80, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_STOP) PORT_CHAR('.') PORT_CHAR('>')
+
+ PORT_START("ROW6")
+ PORT_BIT(0x01, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_DEL_PAD) PORT_CHAR(UCHAR_MAMEKEY(DEL_PAD)) PORT_NAME("Keypad .")
+ 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_3_PAD) PORT_CHAR(UCHAR_MAMEKEY(3_PAD)) PORT_NAME("Keypad 3")
+ PORT_BIT(0x08, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_5_PAD) PORT_CHAR(UCHAR_MAMEKEY(5_PAD)) PORT_NAME("Keypad 5")
+ 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_I) PORT_CHAR('i') PORT_CHAR('I')
+ PORT_BIT(0x40, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_8) PORT_CHAR('8') PORT_CHAR('*')
+ PORT_BIT(0x80, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_SLASH) PORT_CHAR('/') PORT_CHAR('?')
+
+ PORT_START("ROW7")
+ PORT_BIT(0x01, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_ENTER_PAD) PORT_CHAR(UCHAR_MAMEKEY(ENTER_PAD)) PORT_NAME("Keypad Enter")
+ PORT_BIT(0x02, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_0) PORT_CHAR('0') PORT_CHAR(')')
+ PORT_BIT(0x04, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_PLUS_PAD) PORT_CHAR(UCHAR_MAMEKEY(PLUS_PAD)) PORT_NAME("Keypad +")
+ PORT_BIT(0x08, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_6_PAD) PORT_CHAR(UCHAR_MAMEKEY(6_PAD)) PORT_NAME("Keypad 6")
+ PORT_BIT(0x10, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_COLON) PORT_CHAR(';') PORT_CHAR(':')
+ PORT_BIT(0x20, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_O) PORT_CHAR('o') PORT_CHAR('O')
+ PORT_BIT(0x40, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_9) PORT_CHAR('9') PORT_CHAR('(')
+ PORT_BIT(0x80, IP_ACTIVE_LOW, IPT_UNUSED)
+
+ PORT_START("ROW8")
+ PORT_BIT(0x01, IP_ACTIVE_LOW, IPT_UNUSED)
+ PORT_BIT(0x02, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_Z) PORT_CHAR('z') PORT_CHAR('Z')
+ PORT_BIT(0x04, IP_ACTIVE_LOW, IPT_UNUSED)
+ PORT_BIT(0x08, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_SPACE) PORT_CHAR(' ')
+ PORT_BIT(0x10, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_A) PORT_CHAR('a') PORT_CHAR('A')
+ PORT_BIT(0x20, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_TAB) PORT_CHAR(0x09) PORT_NAME("Tab")
+ PORT_BIT(0x40, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_TILDE) PORT_CHAR('`') PORT_CHAR('~')
+ PORT_BIT(0x80, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_X) PORT_CHAR('x') PORT_CHAR('X')
+
+ PORT_START("ROW9")
+ PORT_BIT(0x03, IP_ACTIVE_LOW, IPT_UNUSED)
+ PORT_BIT(0x04, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_7_PAD) PORT_CHAR(UCHAR_MAMEKEY(7_PAD)) PORT_NAME("Keypad 7")
+ PORT_BIT(0x08, IP_ACTIVE_LOW, IPT_UNUSED)
+ PORT_BIT(0x10, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_S) PORT_CHAR('s') PORT_CHAR('S')
+ PORT_BIT(0x20, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_Q) PORT_CHAR('q') PORT_CHAR('Q')
+ PORT_BIT(0x40, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_1) PORT_CHAR('1') PORT_CHAR('!')
+ PORT_BIT(0x80, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_C) PORT_CHAR('c') PORT_CHAR('C')
+
+ PORT_START("P2")
+ PORT_BIT(0x43, IP_ACTIVE_LOW, IPT_UNUSED)
+ PORT_BIT(0x04, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_LSHIFT) PORT_CODE(KEYCODE_RSHIFT) PORT_CHAR(UCHAR_SHIFT_1) PORT_NAME("Shift")
+ PORT_BIT(0x08, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_CAPSLOCK) PORT_CHAR(UCHAR_MAMEKEY(CAPSLOCK)) PORT_NAME("Caps Lock") PORT_TOGGLE
+ PORT_BIT(0x10, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_LALT) PORT_CODE(KEYCODE_RALT) PORT_CHAR(UCHAR_SHIFT_2) PORT_NAME("Option")
+ PORT_BIT(0x20, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_LCONTROL) PORT_NAME("Command")
+ PORT_BIT(0x80, IP_ACTIVE_LOW, IPT_CUSTOM) PORT_CUSTOM_MEMBER(FUNC(keyboard_base::host_data_r))
+INPUT_PORTS_END
+
+INPUT_PORTS_START(keyboard_fr)
+ PORT_INCLUDE(keyboard_us)
+
+ 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(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(U'ˆ') PORT_CHAR(U'¨')
+ PORT_BIT(0x40, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_3) PORT_CHAR('"') PORT_CHAR('3')
+
+ PORT_MODIFY("ROW2")
+ PORT_BIT(0x08, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_CLOSEBRACE) PORT_CHAR('$') PORT_CHAR('*')
+ 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(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(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(U'è') PORT_CHAR('7')
+ PORT_BIT(0x80, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_STOP) PORT_CHAR(':') PORT_CHAR('/')
+
+ PORT_MODIFY("ROW6")
+ PORT_BIT(0x01, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_DEL_PAD) PORT_CHAR(UCHAR_MAMEKEY(DEL_PAD)) PORT_NAME("Keypad ,")
+ PORT_BIT(0x02, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_MINUS) PORT_CHAR(')') PORT_CHAR(0xb0) // °
+ PORT_BIT(0x40, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_8) PORT_CHAR('!') PORT_CHAR('8')
+ 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(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(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(U'£')
+
+ PORT_MODIFY("ROW9")
+ PORT_BIT(0x20, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_Q) PORT_CHAR('a') PORT_CHAR('A')
+ PORT_BIT(0x40, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_1) PORT_CHAR('&') PORT_CHAR('1')
+INPUT_PORTS_END
+
+INPUT_PORTS_START(keyboard_jp)
+ PORT_INCLUDE(keyboard_us)
+
+ PORT_MODIFY("ROW0")
+ PORT_BIT(0x08, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_P) PORT_CHAR('p') PORT_CHAR('P') PORT_NAME(u8"P \u30bb") // セ
+ PORT_BIT(0x10, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_D) PORT_CHAR('d') PORT_CHAR('D') PORT_NAME(u8"D \u30b7") // シ
+ PORT_BIT(0x20, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_W) PORT_CHAR('w') PORT_CHAR('W') PORT_NAME(u8"W \u30c6") // テ
+ PORT_BIT(0x40, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_2) PORT_CHAR('2') PORT_CHAR('@') PORT_NAME(u8"2 @ \u30d5") // フ
+ 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(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") // イ ィ
+ PORT_BIT(0x40, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_3) PORT_CHAR('3') PORT_CHAR('#') PORT_NAME(u8"3 # \u30a2 \u30a1") // ア ァ
+ PORT_BIT(0x80, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_B) PORT_CHAR('b') PORT_CHAR('B') PORT_NAME(u8"B \u30b3") // コ
+
+ PORT_MODIFY("ROW2")
+ PORT_BIT(0x08, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_CLOSEBRACE) PORT_CHAR(']') PORT_CHAR('}') PORT_NAME(u8"] } \u30e0 \u30fc") // ム ー
+ PORT_BIT(0x10, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_G) PORT_CHAR('g') PORT_CHAR('G') PORT_NAME(u8"G \u30ad") // キ
+ PORT_BIT(0x20, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_R) PORT_CHAR('r') PORT_CHAR('R') PORT_NAME(u8"R \u30b9") // ス
+ PORT_BIT(0x40, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_4) PORT_CHAR('4') PORT_CHAR('$') PORT_NAME(u8"4 $ \u30a6 \u30a5") // ウ ゥ
+ PORT_BIT(0x80, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_N) PORT_CHAR('n') PORT_CHAR('N') PORT_NAME(u8"N \u30df") // ミ
+
+ PORT_MODIFY("ROW3")
+ PORT_BIT(0x08, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_QUOTE) PORT_CHAR('\'') PORT_CHAR('"') PORT_NAME(u8"' \" \u30b1 \u30ed") // ケ ロ
+ PORT_BIT(0x10, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_H) PORT_CHAR('h') PORT_CHAR('H') PORT_NAME(u8"H \u30af") // ク
+ PORT_BIT(0x20, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_T) PORT_CHAR('t') PORT_CHAR('T') PORT_NAME(u8"T \u30ab") // カ
+ PORT_BIT(0x40, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_5) PORT_CHAR('5') PORT_CHAR('%') PORT_NAME(u8"5 % \u30a8 \u30a7") // エ
+ PORT_BIT(0x80, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_M) PORT_CHAR('m') PORT_CHAR('M') PORT_NAME(u8"M \u30e2") // モ
+
+ PORT_MODIFY("ROW4")
+ PORT_BIT(0x10, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_J) PORT_CHAR('j') PORT_CHAR('J') PORT_NAME(u8"J \u30de") // マ
+ PORT_BIT(0x20, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_Y) PORT_CHAR('y') PORT_CHAR('Y') PORT_NAME(u8"Y \u30f3") // ン
+ PORT_BIT(0x40, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_6) PORT_CHAR('6') PORT_CHAR('^') PORT_NAME(u8"6 ^ \u30aa \u30a9") // オ ォ
+ PORT_BIT(0x80, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_COMMA) PORT_CHAR(',') PORT_CHAR('<') PORT_NAME(u8", < \u30cd \u3001") // ネ 、
+
+ PORT_MODIFY("ROW5")
+ PORT_BIT(0x02, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_EQUALS) PORT_CHAR('=') PORT_CHAR('+') PORT_NAME(u8"= + \u309c \u300c") // ゜ 「
+ PORT_BIT(0x10, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_K) PORT_CHAR('k') PORT_CHAR('K') PORT_NAME(u8"K \u30ce") // ノ
+ PORT_BIT(0x20, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_U) PORT_CHAR('u') PORT_CHAR('U') PORT_NAME(u8"U \u30ca") // ナ
+ PORT_BIT(0x40, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_7) PORT_CHAR('7') PORT_CHAR('&') PORT_NAME(u8"7 & \u30e4 \u30e3") // ヤ ャ
+ PORT_BIT(0x80, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_STOP) PORT_CHAR('.') PORT_CHAR('>') PORT_NAME(u8". > \u30eb \u3002") // ル 。
+
+ PORT_MODIFY("ROW6")
+ PORT_BIT(0x02, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_MINUS) PORT_CHAR('-') PORT_CHAR('_') PORT_NAME(u8"- _ \u30db") // ホ
+ PORT_BIT(0x10, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_L) PORT_CHAR('l') PORT_CHAR('L') PORT_NAME(u8"L \u30ea") // リ
+ PORT_BIT(0x20, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_I) PORT_CHAR('i') PORT_CHAR('I') PORT_NAME(u8"I \u30cb") // ニ
+ PORT_BIT(0x40, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_8) PORT_CHAR('8') PORT_CHAR('*') PORT_NAME(u8"8 * \u30e6 \u30e5") // ユ ュ
+ PORT_BIT(0x80, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_SLASH) PORT_CHAR('/') PORT_CHAR('?') PORT_NAME(u8"/ ? \u30e1 \u30fb") // メ ・
+
+ PORT_MODIFY("ROW7")
+ PORT_BIT(0x02, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_0) PORT_CHAR('0') PORT_CHAR(')') PORT_NAME(u8"0 ) \u30ef \u30f2") // ワ ヲ
+ PORT_BIT(0x10, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_COLON) PORT_CHAR(';') PORT_CHAR(':') PORT_NAME(u8"; : \u30ec") // レ
+ PORT_BIT(0x20, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_O) PORT_CHAR('o') PORT_CHAR('O') PORT_NAME(u8"O \u30e9") // ラ
+ PORT_BIT(0x40, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_9) PORT_CHAR('9') PORT_CHAR('(') PORT_NAME(u8"9 ( \u30e8 \u30e7") // ヨ ョ
+
+ PORT_MODIFY("ROW8")
+ PORT_BIT(0x02, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_Z) PORT_CHAR('z') PORT_CHAR('Z') PORT_NAME(u8"Z \u30c4 \u30c3") // ツ ッ
+ PORT_BIT(0x10, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_A) PORT_CHAR('a') PORT_CHAR('A') PORT_NAME(u8"A \u30c1") // チ
+ PORT_BIT(0x80, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_X) PORT_CHAR('x') PORT_CHAR('X') PORT_NAME(u8"X \u30b5") // サ
+
+ PORT_MODIFY("ROW9")
+ PORT_BIT(0x10, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_S) PORT_CHAR('s') PORT_CHAR('S') PORT_NAME(u8"S \u30c8") // ト
+ PORT_BIT(0x20, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_Q) PORT_CHAR('q') PORT_CHAR('Q') PORT_NAME(u8"Q \u30bf") // タ
+ PORT_BIT(0x40, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_1) PORT_CHAR('1') PORT_CHAR('!') PORT_NAME(u8"1 ! \u30cc") // ヌ
+ PORT_BIT(0x80, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_C) PORT_CHAR('c') PORT_CHAR('C') PORT_NAME(u8"C \u30bd") // ソ
+
+ PORT_MODIFY("P2")
+ PORT_BIT(0x08, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_CAPSLOCK) PORT_CHAR(UCHAR_MAMEKEY(CAPSLOCK)) PORT_NAME(u8"\u30ab\u30ca (Kana)") PORT_TOGGLE // カナ
+INPUT_PORTS_END
+
+
+class m0110a_device : public keyboard_base
+{
+public:
+ m0110a_device(machine_config const &mconfig, char const *tag, device_t *owner, u32 clock)
+ : keyboard_base(mconfig, MACKBD_M0110A, tag, owner, clock)
+ {
+ }
+
+protected:
+ virtual ioport_constructor device_input_ports() const override
+ {
+ return INPUT_PORTS_NAME(keyboard_us);
+ }
+};
+
+class m0110a_f_device : public keyboard_base
+{
+public:
+ m0110a_f_device(machine_config const &mconfig, char const *tag, device_t *owner, u32 clock)
+ : keyboard_base(mconfig, MACKBD_M0110A_F, tag, owner, clock)
+ {
+ }
+
+ static auto parent_rom_device_type() { return &MACKBD_M0110A; }
+
+protected:
+ virtual ioport_constructor device_input_ports() const override
+ {
+ return INPUT_PORTS_NAME(keyboard_fr);
+ }
+};
+
+class m0110a_j_device : public keyboard_base
+{
+public:
+ m0110a_j_device(machine_config const &mconfig, char const *tag, device_t *owner, u32 clock)
+ : keyboard_base(mconfig, MACKBD_M0110A_J, tag, owner, clock)
+ {
+ }
+
+ static auto parent_rom_device_type() { return &MACKBD_M0110A; }
+
+protected:
+ virtual ioport_constructor device_input_ports() const override
+ {
+ return INPUT_PORTS_NAME(keyboard_jp);
+ }
+};
+
+} // anonymous namespace
+
+
+DEFINE_DEVICE_TYPE_PRIVATE(MACKBD_M0110A , device_mac_keyboard_interface, m0110a_device, "mackbd_m0110a", "Macintosh Plus Keyboard (U.S. - M0110A)")
+DEFINE_DEVICE_TYPE_PRIVATE(MACKBD_M0110A_F, device_mac_keyboard_interface, m0110a_f_device, "mackbd_m0110a_f", "Macintosh Plus Keyboard (French - M0110A F)")
+DEFINE_DEVICE_TYPE_PRIVATE(MACKBD_M0110A_J, device_mac_keyboard_interface, m0110a_j_device, "mackbd_m0110a_j", "Macintosh Plus Keyboard (Japanese - M0110A J)")
diff --git a/src/devices/bus/mackbd/pluskbd.h b/src/devices/bus/mackbd/pluskbd.h
new file mode 100644
index 00000000000..3fbe4fe8288
--- /dev/null
+++ b/src/devices/bus/mackbd/pluskbd.h
@@ -0,0 +1,19 @@
+// license: BSD-3-Clause
+// copyright-holders: Vas Crabb
+/***************************************************************************
+
+ Apple M0110A keyboard with integrated keypad
+
+***************************************************************************/
+#ifndef MAME_BUS_MACKBD_PLUSKBD_H
+#define MAME_BUS_MACKBD_PLUSKBD_H
+
+#pragma once
+
+#include "mackbd.h"
+
+DECLARE_DEVICE_TYPE(MACKBD_M0110A, device_mac_keyboard_interface)
+DECLARE_DEVICE_TYPE(MACKBD_M0110A_F, device_mac_keyboard_interface)
+DECLARE_DEVICE_TYPE(MACKBD_M0110A_J, device_mac_keyboard_interface)
+
+#endif // MAME_BUS_MACKBD_PLUSKBD_H
diff --git a/src/devices/bus/macpds/hyperdrive.cpp b/src/devices/bus/macpds/hyperdrive.cpp
index 0c64d077765..ac688a1a620 100644
--- a/src/devices/bus/macpds/hyperdrive.cpp
+++ b/src/devices/bus/macpds/hyperdrive.cpp
@@ -159,7 +159,7 @@ void macpds_hyperdrive_device::device_start()
install_rom(this, HYPERDRIVE_ROM_REGION, 0xf80000);
// WD200x registers
- m_macpds->install_device(0xfc0000, 0xfc000f, read16_delegate(FUNC(macpds_hyperdrive_device::hyperdrive_r), this), write16_delegate(FUNC(macpds_hyperdrive_device::hyperdrive_w), this));
+ m_macpds->install_device(0xfc0000, 0xfc000f, read16sm_delegate(*this, FUNC(macpds_hyperdrive_device::hyperdrive_r)), write16sm_delegate(*this, FUNC(macpds_hyperdrive_device::hyperdrive_w)));
}
//-------------------------------------------------
@@ -170,22 +170,22 @@ void macpds_hyperdrive_device::device_reset()
{
}
-WRITE16_MEMBER( macpds_hyperdrive_device::hyperdrive_w )
+void macpds_hyperdrive_device::hyperdrive_w(offs_t offset, uint16_t data)
{
m_hdc->write(offset, data & 0xff);
}
-READ16_MEMBER( macpds_hyperdrive_device::hyperdrive_r )
+uint16_t macpds_hyperdrive_device::hyperdrive_r(offs_t offset)
{
return m_hdc->read(offset);
}
-WRITE8_MEMBER( macpds_hyperdrive_device::hdd_w )
+void macpds_hyperdrive_device::hdd_w(offs_t offset, uint8_t data)
{
// printf("hdd_w: %02x @ %x\n", data, offset);
}
-READ8_MEMBER( macpds_hyperdrive_device::hdd_r )
+uint8_t macpds_hyperdrive_device::hdd_r(offs_t offset)
{
// printf("hdd_r: @ %x\n", offset);
return 0;
diff --git a/src/devices/bus/macpds/hyperdrive.h b/src/devices/bus/macpds/hyperdrive.h
index 9d8000b1c88..13580c73ced 100644
--- a/src/devices/bus/macpds/hyperdrive.h
+++ b/src/devices/bus/macpds/hyperdrive.h
@@ -1,7 +1,7 @@
// license:BSD-3-Clause
// copyright-holders:R. Belmont
-#ifndef MAME_BUS_PDS_HYPERDRIVE_H
-#define MAME_BUS_PDS_HYPERDRIVE_H
+#ifndef MAME_BUS_MACPDS_HYPERDRIVE_H
+#define MAME_BUS_MACPDS_HYPERDRIVE_H
#pragma once
@@ -29,25 +29,25 @@ protected:
macpds_hyperdrive_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_start() override ATTR_COLD;
+ virtual void device_reset() override ATTR_COLD;
// optional information overrides
- virtual void device_add_mconfig(machine_config &config) override;
- virtual const tiny_rom_entry *device_rom_region() const override;
+ virtual void device_add_mconfig(machine_config &config) override ATTR_COLD;
+ virtual const tiny_rom_entry *device_rom_region() const override ATTR_COLD;
required_device<wd2010_device> m_hdc;
private:
- DECLARE_READ16_MEMBER(hyperdrive_r);
- DECLARE_WRITE16_MEMBER(hyperdrive_w);
+ uint16_t hyperdrive_r(offs_t offset);
+ void hyperdrive_w(offs_t offset, uint16_t data);
- DECLARE_READ8_MEMBER(hdd_r);
- DECLARE_WRITE8_MEMBER(hdd_w);
+ uint8_t hdd_r(offs_t offset);
+ void hdd_w(offs_t offset, uint8_t data);
};
// device type definition
DECLARE_DEVICE_TYPE(PDS_HYPERDRIVE, macpds_hyperdrive_device)
-#endif // MAME_BUS_PDS_TPDFPD_H
+#endif // MAME_BUS_MACPDS_HYPERDRIVE_H
diff --git a/src/devices/bus/macpds/macpds.cpp b/src/devices/bus/macpds/macpds.cpp
index 8773f453093..4fa3eae6d6e 100644
--- a/src/devices/bus/macpds/macpds.cpp
+++ b/src/devices/bus/macpds/macpds.cpp
@@ -33,8 +33,7 @@ macpds_slot_device::macpds_slot_device(const machine_config &mconfig, const char
macpds_slot_device::macpds_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_macpds_tag(nullptr),
- m_macpds_slottag(nullptr)
+ m_macpds(*this, finder_base::DUMMY_TAG)
{
}
@@ -46,7 +45,7 @@ void macpds_slot_device::device_start()
{
device_macpds_card_interface *dev = dynamic_cast<device_macpds_card_interface *>(get_card_device());
- if (dev) dev->set_macpds_tag(m_macpds_tag, m_macpds_slottag);
+ if (dev) dev->set_macpds_and_slot(m_macpds, this);
}
//**************************************************************************
@@ -70,17 +69,21 @@ macpds_device::macpds_device(const machine_config &mconfig, const char *tag, dev
macpds_device::macpds_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_maincpu(nullptr),
- m_cputag(nullptr)
+ m_maincpu(*this, finder_base::DUMMY_TAG)
{
}
+
+macpds_device::~macpds_device()
+{
+}
+
+
//-------------------------------------------------
// device_start - device-specific startup
//-------------------------------------------------
void macpds_device::device_start()
{
- m_maincpu = machine().device<cpu_device>(m_cputag);
}
//-------------------------------------------------
@@ -91,30 +94,30 @@ 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);
}
-void macpds_device::install_device(offs_t start, offs_t end, read8_delegate rhandler, write8_delegate whandler, uint32_t mask)
+template<typename R, typename W> void macpds_device::install_device(offs_t start, offs_t end, R rhandler, W whandler, uint32_t mask)
{
- m_maincpu = machine().device<cpu_device>(m_cputag);
m_maincpu->space(AS_PROGRAM).install_readwrite_handler(start, end, rhandler, whandler, mask);
}
-void macpds_device::install_device(offs_t start, offs_t end, read16_delegate rhandler, write16_delegate whandler, uint32_t mask)
-{
- m_maincpu = machine().device<cpu_device>(m_cputag);
- m_maincpu->space(AS_PROGRAM).install_readwrite_handler(start, end, rhandler, whandler, mask);
-}
+template void macpds_device::install_device<read8_delegate, write8_delegate >(offs_t start, offs_t end, read8_delegate rhandler, write8_delegate whandler, uint32_t mask);
+template void macpds_device::install_device<read8s_delegate, write8s_delegate >(offs_t start, offs_t end, read8s_delegate rhandler, write8s_delegate whandler, uint32_t mask);
+template void macpds_device::install_device<read8sm_delegate, write8sm_delegate >(offs_t start, offs_t end, read8sm_delegate rhandler, write8sm_delegate whandler, uint32_t mask);
+template void macpds_device::install_device<read8smo_delegate, write8smo_delegate >(offs_t start, offs_t end, read8smo_delegate rhandler, write8smo_delegate whandler, uint32_t mask);
+template void macpds_device::install_device<read16_delegate, write16_delegate >(offs_t start, offs_t end, read16_delegate rhandler, write16_delegate whandler, uint32_t mask);
+template void macpds_device::install_device<read16s_delegate, write16s_delegate >(offs_t start, offs_t end, read16s_delegate rhandler, write16s_delegate whandler, uint32_t mask);
+template void macpds_device::install_device<read16sm_delegate, write16sm_delegate >(offs_t start, offs_t end, read16sm_delegate rhandler, write16sm_delegate whandler, uint32_t mask);
+template void macpds_device::install_device<read16smo_delegate, write16smo_delegate>(offs_t start, offs_t end, read16smo_delegate rhandler, write16smo_delegate whandler, uint32_t mask);
-void macpds_device::install_bank(offs_t start, offs_t end, const char *tag, uint8_t *data)
+void macpds_device::install_bank(offs_t start, offs_t end, uint8_t *data)
{
// printf("install_bank: %s @ %x->%x\n", tag, start, end);
- m_maincpu = machine().device<cpu_device>(m_cputag);
address_space &space = m_maincpu->space(AS_PROGRAM);
- space.install_readwrite_bank(start, end, 0, tag );
- machine().root_device().membank(siblingtag(tag).c_str())->set_base(data);
+ space.install_ram(start, end, data);
}
void macpds_device::set_irq_line(int line, int state)
@@ -135,10 +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_slot_card_interface(mconfig, device),
- m_macpds(nullptr),
- m_macpds_tag(nullptr), m_macpds_slottag(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)
{
}
@@ -153,26 +156,18 @@ device_macpds_card_interface::~device_macpds_card_interface()
void device_macpds_card_interface::set_macpds_device()
{
- m_macpds = dynamic_cast<macpds_device *>(device().machine().device(m_macpds_tag));
- 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, const char *tag, uint8_t *data)
+void device_macpds_card_interface::install_bank(offs_t start, offs_t end, uint8_t *data)
{
- char bank[256];
-
- // append an underscore and the slot name to the bank so it's guaranteed unique
- snprintf(bank, sizeof(bank), "%s_%s", tag, m_macpds_slottag);
-
- m_macpds->install_bank(start, end, bank, data);
+ m_macpds->install_bank(start, end, data);
}
void device_macpds_card_interface::install_rom(device_t *dev, const char *romregion, uint32_t addr)
{
uint8_t *rom = device().machine().root_device().memregion(dev->subtag(romregion).c_str())->base();
uint32_t romlen = device().machine().root_device().memregion(dev->subtag(romregion).c_str())->bytes();
- char bankname[128];
- sprintf(bankname, "rom_%x", addr);
- m_macpds->install_bank(addr, addr+romlen-1, bankname, rom);
+ m_macpds->install_bank(addr, addr+romlen-1, rom);
}
diff --git a/src/devices/bus/macpds/macpds.h b/src/devices/bus/macpds/macpds.h
index 2354549afd5..3a2979d3f35 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
@@ -20,8 +24,7 @@
class macpds_device;
-class macpds_slot_device : public device_t,
- public device_slot_interface
+class macpds_slot_device : public device_t, public device_slot_interface
{
public:
// construction/destruction
@@ -32,22 +35,23 @@ public:
option_reset();
opts(*this);
set_default_option(dflt);
- set_macpds_slot(nbtag, tag);
+ set_macpds_slot(nbtag);
}
macpds_slot_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
// inline configuration
- void set_macpds_slot(const char *tag, const char *slottag) { m_macpds_tag = tag; m_macpds_slottag = slottag; }
+ template <typename T>
+ void set_macpds_slot(T &&tag) { m_macpds.set_tag(std::forward<T>(tag));}
protected:
macpds_slot_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_start() override ATTR_COLD;
// configuration
- const char *m_macpds_tag, *m_macpds_slottag;
+ required_device<macpds_device> m_macpds;
};
// device type definition
@@ -68,29 +72,29 @@ 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
- void set_cputag(const char *tag) { m_cputag = tag; }
+ 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 install_device(offs_t start, offs_t end, read8_delegate rhandler, write8_delegate whandler, uint32_t mask=0xffffffff);
- void install_device(offs_t start, offs_t end, read16_delegate rhandler, write16_delegate whandler, uint32_t mask=0xffffffff);
- void install_bank(offs_t start, offs_t end, const char *tag, uint8_t *data);
+
+ 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);
protected:
macpds_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_start() override ATTR_COLD;
+ virtual void device_reset() override ATTR_COLD;
// internal state
- cpu_device *m_maincpu;
+ required_device<cpu_device> m_maincpu;
- simple_list<device_macpds_card_interface> m_device_list;
- const char *m_cputag;
+ std::vector<std::reference_wrapper<device_macpds_card_interface> > m_device_list;
};
@@ -100,33 +104,27 @@ DECLARE_DEVICE_TYPE(MACPDS, macpds_device)
// ======================> device_macpds_card_interface
// class representing interface-specific live macpds card
-class device_macpds_card_interface : public device_slot_card_interface
+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
- void install_bank(offs_t start, offs_t end, const char *tag, uint8_t *data);
+ void install_bank(offs_t start, offs_t end, uint8_t *data);
void install_rom(device_t *dev, const char *romregion, uint32_t addr);
// inline configuration
- void set_macpds_tag(const char *tag, const char *slottag) { m_macpds_tag = tag; m_macpds_slottag = slottag; }
+ void set_macpds_and_slot(macpds_device *macpds, macpds_slot_device *macpds_slot) { m_macpds = macpds; m_macpds_slot = macpds_slot; }
protected:
device_macpds_card_interface(const machine_config &mconfig, device_t &device);
- macpds_device *m_macpds;
- const char *m_macpds_tag, *m_macpds_slottag;
-
-private:
- device_macpds_card_interface *m_next;
+ macpds_device *m_macpds;
+ macpds_slot_device *m_macpds_slot;
};
#endif // MAME_BUS_MACPDS_MACPDS_H
diff --git a/src/devices/bus/macpds/pds_tpdfpd.cpp b/src/devices/bus/macpds/pds_tpdfpd.cpp
index 1a3f2671e5c..c6eeb68c466 100644
--- a/src/devices/bus/macpds/pds_tpdfpd.cpp
+++ b/src/devices/bus/macpds/pds_tpdfpd.cpp
@@ -109,13 +109,12 @@ void macpds_sedisplay_device::device_start()
m_vram = std::make_unique<uint8_t[]>(VRAM_SIZE);
- static const char bankname[] = { "radpds_ram" };
- m_macpds->install_bank(0xc40000, 0xc40000+VRAM_SIZE-1, bankname, m_vram.get());
+ m_macpds->install_bank(0xc40000, 0xc40000+VRAM_SIZE-1, m_vram.get());
- m_macpds->install_device(0x770000, 0x77000f, read16_delegate(FUNC(macpds_sedisplay_device::ramdac_r), this), write16_delegate(FUNC(macpds_sedisplay_device::ramdac_w), this));
- m_macpds->install_device(0xc10000, 0xc2ffff, read16_delegate(FUNC(macpds_sedisplay_device::sedisplay_r), this), write16_delegate(FUNC(macpds_sedisplay_device::sedisplay_w), this));
+ m_macpds->install_device(0x770000, 0x77000f, read16s_delegate(*this, FUNC(macpds_sedisplay_device::ramdac_r)), write16s_delegate(*this, FUNC(macpds_sedisplay_device::ramdac_w)));
+ m_macpds->install_device(0xc10000, 0xc2ffff, read16sm_delegate(*this, FUNC(macpds_sedisplay_device::sedisplay_r)), write16sm_delegate(*this, FUNC(macpds_sedisplay_device::sedisplay_w)));
- m_timer = timer_alloc(0, nullptr);
+ m_timer = timer_alloc(FUNC(macpds_sedisplay_device::vbl_tick), this);
m_timer->adjust(screen().time_until_pos(879, 0), 0);
}
@@ -136,7 +135,7 @@ void macpds_sedisplay_device::device_reset()
}
-void macpds_sedisplay_device::device_timer(emu_timer &timer, device_timer_id tid, int param, void *ptr)
+TIMER_CALLBACK_MEMBER(macpds_sedisplay_device::vbl_tick)
{
if (!m_vbl_disable)
{
@@ -154,38 +153,34 @@ void macpds_sedisplay_device::device_timer(emu_timer &timer, device_timer_id tid
uint32_t macpds_sedisplay_device::screen_update(screen_device &screen, bitmap_rgb32 &bitmap, const rectangle &cliprect)
{
- uint32_t *scanline;
- int x, y;
- uint8_t pixels, *vram;
+ uint8_t const *const vram = m_vram.get();
- vram = m_vram.get();
-
- for (y = 0; y < 870; y++)
+ for (int y = 0; y < 870; y++)
{
- scanline = &bitmap.pix32(y);
- for (x = 0; x < 640/8; x++)
+ uint32_t *scanline = &bitmap.pix(y);
+ for (int x = 0; x < 640/8; x++)
{
- pixels = vram[(y * (1024/8)) + (x^1)];
-
- *scanline++ = m_palette[((pixels>>7)&0x1)^1];
- *scanline++ = m_palette[((pixels>>6)&0x1)^1];
- *scanline++ = m_palette[((pixels>>5)&0x1)^1];
- *scanline++ = m_palette[((pixels>>4)&0x1)^1];
- *scanline++ = m_palette[((pixels>>3)&0x1)^1];
- *scanline++ = m_palette[((pixels>>2)&0x1)^1];
- *scanline++ = m_palette[((pixels>>1)&0x1)^1];
- *scanline++ = m_palette[(pixels&1)^1];
+ uint8_t const pixels = vram[(y * (1024/8)) + (x^1)];
+
+ *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)];
}
}
return 0;
}
-WRITE16_MEMBER( macpds_sedisplay_device::sedisplay_w )
+void macpds_sedisplay_device::sedisplay_w(offs_t offset, uint16_t data)
{
}
-READ16_MEMBER( macpds_sedisplay_device::sedisplay_r )
+uint16_t macpds_sedisplay_device::sedisplay_r(offs_t offset)
{
if (offset == 0) // ack vbl
{
@@ -199,7 +194,7 @@ READ16_MEMBER( macpds_sedisplay_device::sedisplay_r )
return 0;
}
-WRITE16_MEMBER( macpds_sedisplay_device::ramdac_w )
+void macpds_sedisplay_device::ramdac_w(offs_t offset, uint16_t data, uint16_t mem_mask)
{
switch (offset)
{
@@ -224,7 +219,7 @@ WRITE16_MEMBER( macpds_sedisplay_device::ramdac_w )
}
}
-READ16_MEMBER( macpds_sedisplay_device::ramdac_r )
+uint16_t macpds_sedisplay_device::ramdac_r(offs_t offset, uint16_t mem_mask)
{
return 0;
}
diff --git a/src/devices/bus/macpds/pds_tpdfpd.h b/src/devices/bus/macpds/pds_tpdfpd.h
index 21f53e63d7c..26fef74fb3a 100644
--- a/src/devices/bus/macpds/pds_tpdfpd.h
+++ b/src/devices/bus/macpds/pds_tpdfpd.h
@@ -1,7 +1,7 @@
// license:BSD-3-Clause
// copyright-holders:R. Belmont
-#ifndef MAME_BUS_PDS_TPDFPD_H
-#define MAME_BUS_PDS_TPDFPD_H
+#ifndef MAME_BUS_MACPDS_PDS_TPDFPD_H
+#define MAME_BUS_MACPDS_PDS_TPDFPD_H
#pragma once
@@ -26,22 +26,23 @@ protected:
macpds_sedisplay_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_timer(emu_timer &timer, device_timer_id id, int param, void *ptr) override;
+ virtual void device_start() override ATTR_COLD;
+ virtual void device_reset() override ATTR_COLD;
// optional information overrides
- virtual void device_add_mconfig(machine_config &config) override;
- virtual const tiny_rom_entry *device_rom_region() const override;
+ virtual void device_add_mconfig(machine_config &config) override ATTR_COLD;
+ virtual const tiny_rom_entry *device_rom_region() const override ATTR_COLD;
private:
- DECLARE_READ16_MEMBER(sedisplay_r);
- DECLARE_WRITE16_MEMBER(sedisplay_w);
- DECLARE_READ16_MEMBER(ramdac_r);
- DECLARE_WRITE16_MEMBER(ramdac_w);
+ uint16_t sedisplay_r(offs_t offset);
+ void sedisplay_w(offs_t offset, uint16_t data);
+ uint16_t ramdac_r(offs_t offset, uint16_t mem_mask = ~0);
+ void ramdac_w(offs_t offset, uint16_t data, uint16_t mem_mask = ~0);
uint32_t screen_update(screen_device &screen, bitmap_rgb32 &bitmap, const rectangle &cliprect);
+ TIMER_CALLBACK_MEMBER(vbl_tick);
+
std::unique_ptr<uint8_t[]> m_vram;
uint32_t m_vbl_disable;
uint32_t m_palette[256], m_colors[3], m_count, m_clutoffs;
@@ -52,4 +53,4 @@ private:
// device type definition
DECLARE_DEVICE_TYPE(PDS_SEDISPLAY, macpds_sedisplay_device)
-#endif // MAME_BUS_PDS_TPDFPD_H
+#endif // MAME_BUS_MACPDS_PDS_TPDFPD_H
diff --git a/src/devices/bus/mc10/mc10_cart.cpp b/src/devices/bus/mc10/mc10_cart.cpp
new file mode 100644
index 00000000000..d87f34dcea2
--- /dev/null
+++ b/src/devices/bus/mc10/mc10_cart.cpp
@@ -0,0 +1,232 @@
+// license:BSD-3-Clause
+// copyright-holders:tim lindner
+/*********************************************************************
+
+ mc10cart.cpp
+
+ MC-10 / Alice expansion slot - typically used for the 16K external
+ RAM expansion.
+
+ MC-10 and Alice pinout listing
+ --- ------- --- -------
+ 1 GND 18 A6
+ 2 GND 19 A7
+ 3 D0 20 A8
+ 4 D1 21 A9
+ 5 D2 22 A10
+ 6 D3 23 A11
+ 7 D4 24 A12
+ 8 D5 25 A13
+ 9 D6 26 A14
+ 10 D7 27 A15
+ 11 R/!W 28 E
+ 12 A0 29 SEL
+ 13 A1 30 RESET
+ 14 A2 31 !NMI
+ 15 A3 32 +5V
+ 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.
+
+*********************************************************************/
+
+#include "emu.h"
+#include "mc10_cart.h"
+
+#include "mcx128.h"
+#include "multiports_ext.h"
+#include "pak.h"
+#include "ram.h"
+
+//#define VERBOSE 1
+#include "logmacro.h"
+
+//**************************************************************************
+// GLOBAL VARIABLES
+//**************************************************************************
+
+DEFINE_DEVICE_TYPE(MC10CART_SLOT, mc10cart_slot_device, "mc10cart_slot", "MC-10 Cartridge Slot")
+
+//**************************************************************************
+// LIVE DEVICE
+//**************************************************************************
+
+//-------------------------------------------------
+// mc10cart_slot_device - constructor
+//-------------------------------------------------
+mc10cart_slot_device::mc10cart_slot_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock) :
+ device_t(mconfig, MC10CART_SLOT, tag, owner, clock),
+ device_single_card_slot_interface<device_mc10cart_interface>(mconfig, *this),
+ device_cartrom_image_interface(mconfig, *this),
+ m_nmi_callback(*this),
+ m_memspace(*this, finder_base::DUMMY_TAG, -1),
+ m_cart(nullptr)
+{
+}
+
+//-------------------------------------------------
+// device_start - device-specific startup
+//-------------------------------------------------
+
+void mc10cart_slot_device::device_start()
+{
+ m_cart = get_card_device();
+}
+
+//-------------------------------------------------
+// set_nmi_line
+//-------------------------------------------------
+
+void mc10cart_slot_device::set_nmi_line(int state)
+{
+ m_nmi_callback(state);
+}
+
+//-------------------------------------------------
+// call_load
+//-------------------------------------------------
+
+std::pair<std::error_condition, std::string> mc10cart_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::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())
+ {
+ 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"), len, 1, ENDIANNESS_BIG);
+ u32 const cnt(fread(romregion->base(), len));
+ if (cnt != len)
+ return std::make_pair(image_error::UNSPECIFIED, "Error reading cartridge file");
+ }
+
+ return m_cart->load();
+}
+
+//-------------------------------------------------
+// get_default_card_software
+//-------------------------------------------------
+
+std::string mc10cart_slot_device::get_default_card_software(get_default_card_software_hook &hook) const
+{
+ return software_get_default_slot("pak");
+}
+
+//**************************************************************************
+// DEVICE MC-10 CART INTERFACE - Implemented by devices that plug into
+// MC-10 cartridge slots
+//**************************************************************************
+
+template class device_finder<device_mc10cart_interface, false>;
+template class device_finder<device_mc10cart_interface, true>;
+
+//-------------------------------------------------
+// device_mc10cart_interface - constructor
+//-------------------------------------------------
+
+device_mc10cart_interface::device_mc10cart_interface(const machine_config &mconfig, device_t &device)
+ : device_interface(device, "mc10cart")
+ , m_owning_slot(nullptr)
+{
+}
+
+//-------------------------------------------------
+// ~device_mc10cart_interface - destructor
+//-------------------------------------------------
+
+device_mc10cart_interface::~device_mc10cart_interface()
+{
+}
+
+//-------------------------------------------------
+// interface_config_complete
+//-------------------------------------------------
+
+void device_mc10cart_interface::interface_config_complete()
+{
+ m_owning_slot = dynamic_cast<mc10cart_slot_device *>(device().owner());
+}
+
+//-------------------------------------------------
+// interface_pre_start
+//-------------------------------------------------
+
+void device_mc10cart_interface::interface_pre_start()
+{
+ if (!m_owning_slot)
+ throw emu_fatalerror("Expected device().owner() to be of type mc10cart_slot_device");
+}
+
+/*-------------------------------------------------
+ rom size constraints
+-------------------------------------------------*/
+
+int device_mc10cart_interface::max_rom_length() const
+{
+ return 0;
+}
+
+/*-------------------------------------------------
+ load
+-------------------------------------------------*/
+
+std::pair<std::error_condition, std::string> device_mc10cart_interface::load()
+{
+ return std::make_pair(image_error::UNSUPPORTED, std::string());
+}
+
+//-------------------------------------------------
+// mc10_cart_add_basic_devices
+//-------------------------------------------------
+
+void mc10_cart_add_basic_devices(device_slot_interface &device)
+{
+ // basic devices
+ device.option_add("mcx128", MC10_PAK_MCX128).default_bios("mc10");
+ device.option_add("pak", MC10_PAK);
+ device.option_add("ram", MC10_PAK_RAM);
+ device.option_add("multi", ALICE_MULTIPORTS_EXT);
+}
+
+//-------------------------------------------------
+// alice_cart_add_basic_devices
+//-------------------------------------------------
+
+void alice_cart_add_basic_devices(device_slot_interface &device)
+{
+ // basic devices
+ device.option_add("mcx128", MC10_PAK_MCX128).default_bios("alice");
+ device.option_add("pak", MC10_PAK);
+ device.option_add("ram", MC10_PAK_RAM);
+ device.option_add("multi", ALICE_MULTIPORTS_EXT);
+}
+
+//-------------------------------------------------
+// alice32_cart_add_basic_devices
+//-------------------------------------------------
+
+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
new file mode 100644
index 00000000000..9f9116e3a9e
--- /dev/null
+++ b/src/devices/bus/mc10/mc10_cart.h
@@ -0,0 +1,110 @@
+// license:BSD-3-Clause
+// copyright-holders:tim lindner
+/*********************************************************************
+
+ mc10_cart.h
+
+ MC-10 / Alice cartridge management
+
+*********************************************************************/
+
+#ifndef MAME_BUS_MC10_MC10_CART_H
+#define MAME_BUS_MC10_MC10_CART_H
+
+#pragma once
+
+#include "imagedev/cartrom.h"
+
+/***************************************************************************
+ TYPE DEFINITIONS
+***************************************************************************/
+
+
+// ======================> mc10cart_slot_device
+class device_mc10cart_interface;
+
+class mc10cart_slot_device final : public device_t,
+ public device_single_card_slot_interface<device_mc10cart_interface>,
+ 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)
+ : mc10cart_slot_device(mconfig, tag, owner, clock)
+ {
+ option_reset();
+ opts(*this);
+ set_default_option(dflt);
+ set_fixed(false);
+ }
+
+ mc10cart_slot_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock);
+
+ // inline configuration
+ template <typename T> void set_memspace(T &&tag, int spacenum) { m_memspace.set_tag(std::forward<T>(tag), spacenum); }
+ auto nmi_callback() { return m_nmi_callback.bind(); }
+
+ // address map manipulations
+ address_space &memspace() const { return *m_memspace; }
+
+ // 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"; }
+ virtual const char *file_extensions() const noexcept override { return "mcc,rom"; }
+
+ // manipulation of nmi line
+ void set_nmi_line(int state);
+ devcb_write_line m_nmi_callback;
+
+ // device_slot_interface implementation
+ virtual std::string get_default_card_software(get_default_card_software_hook &hook) const override;
+
+protected:
+ // device_t implementation
+ virtual void device_start() override ATTR_COLD;
+
+ required_address_space m_memspace;
+
+private:
+ // cartridge
+ device_mc10cart_interface *m_cart;
+};
+
+// device type definition
+DECLARE_DEVICE_TYPE(MC10CART_SLOT, mc10cart_slot_device)
+
+class device_mc10cart_interface : public device_interface
+{
+public:
+ // construction/destruction
+ virtual ~device_mc10cart_interface();
+
+ virtual int max_rom_length() const;
+
+ virtual std::pair<std::error_condition, std::string> load();
+
+protected:
+ void raise_cart_nmi() { m_owning_slot->set_nmi_line(ASSERT_LINE); }
+ void lower_cart_nmi() { m_owning_slot->set_nmi_line(CLEAR_LINE); }
+
+ virtual void interface_config_complete() override;
+ virtual void interface_pre_start() override;
+
+ device_mc10cart_interface(const machine_config &mconfig, device_t &device);
+
+ // accessors for containers
+ mc10cart_slot_device &owning_slot() const { assert(m_owning_slot); return *m_owning_slot; }
+
+private:
+ mc10cart_slot_device * m_owning_slot;
+};
+
+// methods for configuring MC-10 slot devices
+void mc10_cart_add_basic_devices(device_slot_interface &device);
+void alice_cart_add_basic_devices(device_slot_interface &device);
+void alice32_cart_add_basic_devices(device_slot_interface &device);
+
+#endif // MAME_BUS_MC10_MC10_CART_H
diff --git a/src/devices/bus/mc10/mcx128.cpp b/src/devices/bus/mc10/mcx128.cpp
new file mode 100644
index 00000000000..58c3e5c4543
--- /dev/null
+++ b/src/devices/bus/mc10/mcx128.cpp
@@ -0,0 +1,339 @@
+// license:BSD-3-Clause
+// copyright-holders:tim lindner
+/***************************************************************************
+
+ mcx128.cpp
+
+ Code for emulating Darren Atkinson's MCX-128 cartridge
+
+ Features:
+ 128K of RAM expansion
+ 16K of ROM expansion
+
+ New MC-10 memory map defined by this cartridge:
+
+ 0000 - 0003 6803 Ports
+ 0004 - 0007 Expansion RAM
+ 0008 - 000E 6803 Status / Control
+ 000F Expansion RAM
+ 0010 - 0013 6803 UART
+ 0014 6803 RAM Control Reg
+ 0015 - 001F Unused
+ 0020 - 007F Expansion RAM
+ 0080 - 00FF On-chip CPU RAM / Expansion RAM
+ 0100 - 3FFF Expansion RAM
+ 4000 - 5FFF Built-In RAM / Expansion RAM
+ 6000 - BEFF Expansion RAM
+ BF00 RAM Bank Control Reg
+ BF01 ROM Map Control Reg
+ BF80 - BFFF Keyboard / VDG / Sound
+ C000 - DFFF EPROM or Expansion RAM
+ E000 - FFFF Built-in ROM, EPROM or Expansion RAM
+
+ Deficiency:
+
+ * Writing to 6803 chip RAM at $80 to $ff should be mirrored
+ to external RAM.
+
+***************************************************************************/
+
+#include "emu.h"
+#include "mcx128.h"
+
+//#define VERBOSE (LOG_GENERAL)
+#include "logmacro.h"
+
+namespace {
+
+ROM_START(mcx128)
+ ROM_REGION(0x4000, "eprom", ROMREGION_ERASE00)
+ ROM_DEFAULT_BIOS("mc10")
+
+ ROM_SYSTEM_BIOS(0, "mc10", "Darren Atkinson's MCX-128 cartridge")
+ ROMX_LOAD("mcx128bas.rom", 0x0000, 0x4000, CRC(11202e4b) SHA1(36c30d0f198a1bffee88ef29d92f2401447a91f4), ROM_BIOS(0))
+
+ ROM_SYSTEM_BIOS(1, "alice", "Darren Atkinson's MCX-128 cartridge for Alice")
+ ROMX_LOAD("alice128bas.rom", 0x0000, 0x4000, CRC(a737544a) SHA1(c8fd92705fc42deb6a0ffac6274e27fd61ecd4cc), ROM_BIOS(1))
+ROM_END
+
+//**************************************************************************
+// TYPE DECLARATIONS
+//**************************************************************************
+
+// ======================> mc10_pak_device
+
+class mc10_pak_mcx128_device :
+ public device_t,
+ public device_mc10cart_interface
+{
+public:
+ // construction/destruction
+ mc10_pak_mcx128_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock);
+
+protected:
+ // device_t implementation
+ virtual void device_start() override ATTR_COLD;
+ virtual void device_reset() override ATTR_COLD;
+
+ virtual const tiny_rom_entry *device_rom_region() const override ATTR_COLD;
+
+ u8 control_register_read(offs_t offset);
+ void control_register_write(offs_t offset, u8 data);
+
+ void write_ram_mirror(address_space &space, offs_t offset, u8 data);
+
+ void view_map0(address_map &map) ATTR_COLD;
+ void view_map1(address_map &map) ATTR_COLD;
+ void view_map2(address_map &map) ATTR_COLD;
+ void view_map3(address_map &map) ATTR_COLD;
+ void view_map4(address_map &map) ATTR_COLD;
+ void view_map5(address_map &map) ATTR_COLD;
+ void view_map6(address_map &map) ATTR_COLD;
+ void view_map7(address_map &map) ATTR_COLD;
+
+
+private:
+ memory_share_creator<u8> m_share;
+ memory_view m_view;
+ memory_bank_array_creator<8> m_bank;
+ uint8_t ram_bank_cr;
+ uint8_t rom_map_cr;
+
+ void update_banks();
+
+};
+
+//-------------------------------------------------
+// mc10_pak_device - constructor
+//-------------------------------------------------
+
+mc10_pak_mcx128_device::mc10_pak_mcx128_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock)
+ : device_t(mconfig, MC10_PAK_MCX128, tag, owner, clock)
+ , device_mc10cart_interface(mconfig, *this)
+ , m_share(*this, "ext_ram", 1024*128, ENDIANNESS_BIG)
+ , m_view(*this, "mcx_view")
+ , m_bank(*this, "bank%u", 0U)
+{
+}
+
+const tiny_rom_entry * mc10_pak_mcx128_device::device_rom_region() const
+{
+ return ROM_NAME(mcx128);
+}
+
+
+void mc10_pak_mcx128_device::view_map0(address_map &map)
+{
+ map(0x0004, 0x0007).bankrw("bank0");
+ map(0x000f, 0x000f).bankrw("bank1");
+ map(0x0020, 0x3fff).bankrw("bank2");
+ map(0x4000, 0x5fff).bankr("bank3").w(FUNC(mc10_pak_mcx128_device::write_ram_mirror));
+ map(0x6000, 0xbeff).bankrw("bank4");
+ map(0xbf00, 0xbf01).rw(FUNC(mc10_pak_mcx128_device::control_register_read), FUNC(mc10_pak_mcx128_device::control_register_write));
+ map(0xc000, 0xfeff).rom().region("eprom",0x0000).bankw("bank5");
+ map(0xff00, 0xffff).rom().region("eprom",0x3f00).bankw("bank7");
+}
+
+void mc10_pak_mcx128_device::view_map1(address_map &map)
+{
+ map(0x0004, 0x0007).bankrw("bank0");
+ map(0x000f, 0x000f).bankrw("bank1");
+ map(0x0020, 0x3fff).bankrw("bank2");
+ map(0x4000, 0x5fff).bankr("bank3").w(FUNC(mc10_pak_mcx128_device::write_ram_mirror));
+ map(0x6000, 0xbeff).bankrw("bank4");
+ map(0xbf00, 0xbf01).rw(FUNC(mc10_pak_mcx128_device::control_register_read), FUNC(mc10_pak_mcx128_device::control_register_write));
+ map(0xc000, 0xdfff).bankrw("bank5");
+ map(0xe000, 0xfeff).rom().region("eprom",0x2000).bankw("bank6");
+ map(0xff00, 0xffff).rom().region("eprom",0x3f00).bankw("bank7");
+}
+
+void mc10_pak_mcx128_device::view_map2(address_map &map)
+{
+ map(0x0004, 0x0007).bankrw("bank0");
+ map(0x000f, 0x000f).bankrw("bank1");
+ map(0x0020, 0x3fff).bankrw("bank2");
+ map(0x4000, 0x5fff).bankr("bank3").w(FUNC(mc10_pak_mcx128_device::write_ram_mirror));
+ map(0x6000, 0xbeff).bankrw("bank4");
+ map(0xbf00, 0xbf01).rw(FUNC(mc10_pak_mcx128_device::control_register_read), FUNC(mc10_pak_mcx128_device::control_register_write));
+ map(0xc000, 0xdfff).bankrw("bank5");
+ map(0xe000, 0xfeff).bankw("bank6");
+ map(0xff00, 0xffff).bankw("bank7");
+// 0xe000, 0xffff: read internal ROM
+}
+
+void mc10_pak_mcx128_device::view_map3(address_map &map)
+{
+ map(0x0004, 0x0007).bankrw("bank0");
+ map(0x000f, 0x000f).bankrw("bank1");
+ map(0x0020, 0x3fff).bankrw("bank2");
+ map(0x4000, 0x5fff).bankr("bank3").w(FUNC(mc10_pak_mcx128_device::write_ram_mirror));
+ map(0x6000, 0xbeff).bankrw("bank4");
+ map(0xbf00, 0xbf01).rw(FUNC(mc10_pak_mcx128_device::control_register_read), FUNC(mc10_pak_mcx128_device::control_register_write));
+ map(0xc000, 0xfeff).bankrw("bank5");
+ map(0xff00, 0xffff).bankrw("bank7");
+}
+
+void mc10_pak_mcx128_device::view_map4(address_map &map)
+{
+ map(0x0004, 0x0007).bankrw("bank0");
+ map(0x000f, 0x000f).bankrw("bank1");
+ map(0x0020, 0x3fff).bankrw("bank2");
+ map(0x4000, 0xbeff).bankrw("bank3");
+ map(0xbf00, 0xbf01).rw(FUNC(mc10_pak_mcx128_device::control_register_read), FUNC(mc10_pak_mcx128_device::control_register_write));
+ map(0xc000, 0xfeff).rom().region("eprom",0x0000).bankw("bank5");
+ map(0xff00, 0xffff).rom().region("eprom",0x3f00).bankw("bank7");
+}
+
+void mc10_pak_mcx128_device::view_map5(address_map &map)
+{
+ map(0x0004, 0x0007).bankrw("bank0");
+ map(0x000f, 0x000f).bankrw("bank1");
+ map(0x0020, 0x3fff).bankrw("bank2");
+ map(0x4000, 0xbeff).bankrw("bank3");
+ map(0xbf00, 0xbf01).rw(FUNC(mc10_pak_mcx128_device::control_register_read), FUNC(mc10_pak_mcx128_device::control_register_write));
+ map(0xc000, 0xdfff).bankrw("bank5");
+ map(0xe000, 0xfeff).rom().region("eprom",0x2000).bankw("bank6");
+ map(0xff00, 0xffff).rom().region("eprom",0x3f00).bankw("bank7");
+}
+
+void mc10_pak_mcx128_device::view_map6(address_map &map)
+{
+ map(0x0004, 0x0007).bankrw("bank0");
+ map(0x000f, 0x000f).bankrw("bank1");
+ map(0x0020, 0x3fff).bankrw("bank2");
+ map(0x4000, 0xbeff).bankrw("bank3");
+ map(0xbf00, 0xbf01).rw(FUNC(mc10_pak_mcx128_device::control_register_read), FUNC(mc10_pak_mcx128_device::control_register_write));
+ map(0xc000, 0xdfff).bankrw("bank5");
+ map(0xe000, 0xfeff).bankw("bank6");
+ map(0xff00, 0xffff).bankw("bank7");
+// 0xe000, 0xffff: read internal ROM
+}
+
+void mc10_pak_mcx128_device::view_map7(address_map &map)
+{
+ map(0x0004, 0x0007).bankrw("bank0");
+ map(0x000f, 0x000f).bankrw("bank1");
+ map(0x0020, 0x3fff).bankrw("bank2");
+ map(0x4000, 0xbeff).bankrw("bank3");
+ map(0xbf00, 0xbf01).rw(FUNC(mc10_pak_mcx128_device::control_register_read), FUNC(mc10_pak_mcx128_device::control_register_write));
+ map(0xc000, 0xfeff).bankrw("bank5");
+ map(0xff00, 0xffff).bankrw("bank7");
+}
+
+//-------------------------------------------------
+// device_start - device-specific startup
+//-------------------------------------------------
+
+void mc10_pak_mcx128_device::device_start()
+{
+ save_item(NAME(ram_bank_cr));
+ save_item(NAME(rom_map_cr));
+
+ // 0x0004 - 0x0007
+ m_bank[0]->configure_entry(0, &m_share[0x00004]);
+ m_bank[0]->configure_entry(1, &m_share[0x10004]);
+
+ // 0x000f - 0x000f
+ m_bank[1]->configure_entry(0, &m_share[0x0000f]);
+ m_bank[1]->configure_entry(1, &m_share[0x1000f]);
+
+ // 0x0000 - 0x3fff
+ m_bank[2]->configure_entry(0, &m_share[0x00020]);
+ m_bank[2]->configure_entry(1, &m_share[0x10020]);
+
+ // 0x4000 - 0x5fff
+ m_bank[3]->configure_entry(0, &m_share[0x08000]);
+ m_bank[3]->configure_entry(1, &m_share[0x18000]);
+
+ // 0x6000 - 0xbeff
+ m_bank[4]->configure_entry(0, &m_share[0x0a000]);
+ m_bank[4]->configure_entry(1, &m_share[0x1a000]);
+
+ // 0xc000 - 0xdfff
+ m_bank[5]->configure_entry(0, &m_share[0x04000]);
+ m_bank[5]->configure_entry(1, &m_share[0x14000]);
+
+ // 0xe000 - 0xffff
+ m_bank[6]->configure_entry(0, &m_share[0x06000]);
+ m_bank[6]->configure_entry(1, &m_share[0x16000]);
+
+ // 0xff00 - 0xffff
+ m_bank[7]->configure_entry(0, &m_share[0x07f00]);
+ m_bank[7]->configure_entry(1, &m_share[0x07f00]);
+
+ owning_slot().memspace().install_view(0x0000, 0xffff, m_view);
+
+ m_view[0].install_device(0x0000, 0xffff, *this, &mc10_pak_mcx128_device::view_map0);
+ m_view[1].install_device(0x0000, 0xffff, *this, &mc10_pak_mcx128_device::view_map1);
+ m_view[2].install_device(0x0000, 0xffff, *this, &mc10_pak_mcx128_device::view_map2);
+ m_view[3].install_device(0x0000, 0xffff, *this, &mc10_pak_mcx128_device::view_map3);
+ m_view[4].install_device(0x0000, 0xffff, *this, &mc10_pak_mcx128_device::view_map4);
+ m_view[5].install_device(0x0000, 0xffff, *this, &mc10_pak_mcx128_device::view_map5);
+ m_view[6].install_device(0x0000, 0xffff, *this, &mc10_pak_mcx128_device::view_map6);
+ m_view[7].install_device(0x0000, 0xffff, *this, &mc10_pak_mcx128_device::view_map7);
+}
+
+//-------------------------------------------------
+// device_reset - device-specific startup
+//-------------------------------------------------
+
+void mc10_pak_mcx128_device::device_reset()
+{
+ ram_bank_cr = 0;
+ rom_map_cr = 0;
+ update_banks();
+}
+
+void mc10_pak_mcx128_device::write_ram_mirror(address_space &space, offs_t offset, u8 data)
+{
+ std::optional<int> cur_slot = m_view.entry();
+ m_share[0x08000+offset] = data;
+
+ if (cur_slot.has_value())
+ {
+ int cur_slot_int = *cur_slot;
+ m_view.disable();
+ space.write_byte(0x4000+offset, data);
+ m_view.select(cur_slot_int);
+ }
+}
+
+u8 mc10_pak_mcx128_device::control_register_read(offs_t offset)
+{
+ if (offset==0)
+ return ram_bank_cr & 0x03;
+
+ return rom_map_cr & 0x03;
+}
+
+void mc10_pak_mcx128_device::control_register_write(offs_t offset, u8 data)
+{
+ if (offset==0)
+ ram_bank_cr = data;
+ else
+ rom_map_cr = data;
+
+ update_banks();
+}
+
+void mc10_pak_mcx128_device::update_banks()
+{
+ int bank0 = ram_bank_cr & 0x01;
+ int bank1 = (ram_bank_cr & 0x02) >> 1;
+
+ m_bank[0]->set_entry(bank0);
+ m_bank[1]->set_entry(bank0);
+ m_bank[2]->set_entry(bank0);
+ m_bank[3]->set_entry(bank1);
+ m_bank[4]->set_entry(bank1);
+ m_bank[5]->set_entry(bank0);
+ m_bank[6]->set_entry(bank0);
+ m_bank[7]->set_entry(bank0);
+
+ m_view.select((bank1 << 2) | (rom_map_cr & 0x03));
+ LOG("view select: %d, bank cr: %d\n", (bank1 << 2) | (rom_map_cr & 0x03), ram_bank_cr & 0x03 );
+}
+
+} // anonymous namespace
+
+DEFINE_DEVICE_TYPE_PRIVATE(MC10_PAK_MCX128, device_mc10cart_interface, mc10_pak_mcx128_device, "mcx128", "Darren Atkinson's MCX-128 cartridge")
diff --git a/src/devices/bus/mc10/mcx128.h b/src/devices/bus/mc10/mcx128.h
new file mode 100644
index 00000000000..a4c936a3d78
--- /dev/null
+++ b/src/devices/bus/mc10/mcx128.h
@@ -0,0 +1,14 @@
+// license:BSD-3-Clause
+// copyright-holders:tim lindner
+#ifndef MAME_BUS_MC10_MCX128_H
+#define MAME_BUS_MC10_MCX128_H
+
+#pragma once
+
+#include "mc10_cart.h"
+
+// device type definition
+DECLARE_DEVICE_TYPE(MC10_PAK_MCX128, device_mc10cart_interface)
+
+#endif // MAME_BUS_MC10_MCX128_H
+
diff --git a/src/devices/bus/mc10/multiports_ext.cpp b/src/devices/bus/mc10/multiports_ext.cpp
new file mode 100644
index 00000000000..f5f94c466ee
--- /dev/null
+++ b/src/devices/bus/mc10/multiports_ext.cpp
@@ -0,0 +1,141 @@
+// license:BSD-3-Clause
+// copyright-holders:S. Glaize
+
+/***************************************************************************
+
+ 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 ATTR_COLD;
+ virtual void device_reset() override ATTR_COLD;
+
+ void control_register_write(offs_t offset, u8 data);
+
+ void multiports_mem(address_map &map) ATTR_COLD;
+
+private:
+ memory_bank_creator m_bank;
+ 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")
+ , 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"));
+ assert(romregion != nullptr);
+
+ const u32 min_rom_length = 8 * 1024;
+ const u32 block_rom_length = 8 * 1024;
+ const u32 len = romregion->bytes();
+
+ if (len < min_rom_length)
+ {
+ return std::make_pair(
+ image_error::INVALIDLENGTH,
+ util::string_format("Unsupported cartridge size (must be at least %u bytes)", min_rom_length));
+ }
+ else if (len % block_rom_length != 0)
+ {
+ return std::make_pair(
+ image_error::INVALIDLENGTH,
+ util::string_format("Unsupported cartridge size (must be a multiple of %u bytes)", block_rom_length));
+ }
+
+ 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..d67194ffd98
--- /dev/null
+++ b/src/devices/bus/mc10/multiports_ext.h
@@ -0,0 +1,11 @@
+#ifndef MAME_BUS_MC10_MULTIPORTS_EXT_H
+#define MAME_BUS_MC10_MULTIPORTS_EXT_H
+
+#pragma once
+
+#include "mc10_cart.h"
+
+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
new file mode 100644
index 00000000000..aa41f9079b2
--- /dev/null
+++ b/src/devices/bus/mc10/pak.cpp
@@ -0,0 +1,94 @@
+// license:BSD-3-Clause
+// copyright-holders:tim lindner
+/***************************************************************************
+
+ pak.cpp
+
+ Code for emulating standard MC-10 cartridges with only ROM
+
+***************************************************************************/
+
+#include "emu.h"
+#include "pak.h"
+
+
+namespace {
+
+//**************************************************************************
+// TYPE DEFINITIONS
+//**************************************************************************
+
+// ======================> mc10_pak_device
+
+class mc10_pak_device :
+ public device_t,
+ public device_mc10cart_interface
+{
+public:
+ // construction/destruction
+ mc10_pak_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_pak_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, u32 clock);
+
+ // device_t implementation
+ virtual void device_start() override ATTR_COLD;
+};
+
+//**************************************************************************
+// LIVE DEVICE
+//**************************************************************************
+
+//-------------------------------------------------
+// mc10_pak_device - constructor
+//-------------------------------------------------
+mc10_pak_device::mc10_pak_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)
+{
+}
+
+mc10_pak_device::mc10_pak_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock)
+ : mc10_pak_device(mconfig, MC10_PAK, tag, owner, clock)
+{
+}
+
+//-------------------------------------------------
+// rom constraints
+//-------------------------------------------------
+
+int mc10_pak_device::max_rom_length() const
+{
+ return 1024 * 16;
+}
+
+//-------------------------------------------------
+// device_start - device-specific startup
+//-------------------------------------------------
+
+void mc10_pak_device::device_start()
+{
+}
+
+//-------------------------------------------------
+// load - install ROM region
+//-------------------------------------------------
+
+std::pair<std::error_condition, std::string> mc10_pak_device::load()
+{
+ memory_region *const romregion(memregion("^rom"));
+ assert(romregion != nullptr);
+
+ // if the host has supplied a ROM space, install it
+ owning_slot().memspace().install_rom(0x5000, 0x5000 + romregion->bytes(), romregion->base());
+
+ return std::make_pair(std::error_condition(), std::string());
+}
+
+} // anonymous namespace
+
+DEFINE_DEVICE_TYPE_PRIVATE(MC10_PAK, device_mc10cart_interface, mc10_pak_device, "mc10pak", "MC-10 Program PAK")
diff --git a/src/devices/bus/mc10/pak.h b/src/devices/bus/mc10/pak.h
new file mode 100644
index 00000000000..073e7ec6b85
--- /dev/null
+++ b/src/devices/bus/mc10/pak.h
@@ -0,0 +1,12 @@
+// license:BSD-3-Clause
+// copyright-holders:tim lindner
+#ifndef MAME_BUS_MC10_PAK_H
+#define MAME_BUS_MC10_PAK_H
+
+#pragma once
+
+#include "mc10_cart.h"
+
+DECLARE_DEVICE_TYPE(MC10_PAK, device_mc10cart_interface)
+
+#endif // MAME_BUS_MC10_PAK_H
diff --git a/src/devices/bus/mc10/ram.cpp b/src/devices/bus/mc10/ram.cpp
new file mode 100644
index 00000000000..e98657f75f9
--- /dev/null
+++ b/src/devices/bus/mc10/ram.cpp
@@ -0,0 +1,78 @@
+// license:BSD-3-Clause
+// copyright-holders:tim lindner
+/***************************************************************************
+
+ ram.cpp
+
+ Code for emulating the Radio Shack 16K RAM Cartridge
+
+***************************************************************************/
+
+#include "emu.h"
+#include "ram.h"
+
+// #include "machine/ram.h"
+
+// #define VERBOSE (LOG_GENERAL )
+#include "logmacro.h"
+
+
+//**************************************************************************
+// TYPE DECLARATIONS
+//**************************************************************************
+
+namespace
+{
+ // ======================> mc10_pak_device
+
+ class mc10_pak_ram_device :
+ public device_t,
+ public device_mc10cart_interface
+ {
+ public:
+ // construction/destruction
+ mc10_pak_ram_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock);
+
+ protected:
+ // device_t implementation
+ virtual void device_start() override ATTR_COLD;
+ private:
+ memory_share_creator<u8> m_share;
+ };
+};
+
+
+
+//**************************************************************************
+// GLOBAL VARIABLES
+//**************************************************************************
+
+DEFINE_DEVICE_TYPE_PRIVATE(MC10_PAK_RAM, device_mc10cart_interface, mc10_pak_ram_device, "mc10pakram", "Radio Shack 16K RAM Cartridge")
+
+
+
+//-------------------------------------------------
+// mc10_pak_device - constructor
+//-------------------------------------------------
+
+mc10_pak_ram_device::mc10_pak_ram_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock)
+ : device_t(mconfig, MC10_PAK_RAM, tag, owner, clock)
+ , device_mc10cart_interface(mconfig, *this)
+ , m_share(*this, "ext_ram", 1024*16, ENDIANNESS_BIG)
+{
+}
+
+
+
+//**************************************************************************
+// MACHINE FRAGMENTS AND ADDRESS MAPS
+//**************************************************************************
+
+//-------------------------------------------------
+// device_start - device-specific startup
+//-------------------------------------------------
+
+void mc10_pak_ram_device::device_start()
+{
+ owning_slot().memspace().install_ram(0x5000, 0x8fff, &m_share[0]);
+}
diff --git a/src/devices/bus/mc10/ram.h b/src/devices/bus/mc10/ram.h
new file mode 100644
index 00000000000..efe89fd3370
--- /dev/null
+++ b/src/devices/bus/mc10/ram.h
@@ -0,0 +1,14 @@
+// license:BSD-3-Clause
+// copyright-holders:tim lindner
+#ifndef MAME_BUS_MC10_RAM_H
+#define MAME_BUS_MC10_RAM_H
+
+#pragma once
+
+#include "mc10_cart.h"
+
+// device type definition
+DECLARE_DEVICE_TYPE(MC10_PAK_RAM, device_mc10cart_interface)
+
+#endif // MAME_BUS_MC10_RAM_H
+
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..1ca97aa90e2
--- /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 ATTR_COLD;
+ virtual void device_start() override ATTR_COLD;
+ virtual void device_reset() override ATTR_COLD;
+
+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..8b4ed5729e4
--- /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 ATTR_COLD;
+ virtual void device_reset() override ATTR_COLD;
+
+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..ad8cea51776
--- /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 ATTR_COLD;
+
+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 ATTR_COLD;
+ virtual void device_start() override ATTR_COLD;
+};
+
+// 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/eeprom.cpp b/src/devices/bus/megadrive/eeprom.cpp
index 32787dec152..533d5d540fa 100644
--- a/src/devices/bus/megadrive/eeprom.cpp
+++ b/src/devices/bus/megadrive/eeprom.cpp
@@ -3,39 +3,40 @@
/***********************************************************************************************************
- MegaDrive / Genesis cart+EEPROM emulation
-
-
- TODO: proper EEPROM emulation, still not worked on (just hooked up the I2C device)
-
-
- i2c games mapping table:
-
- game name | SDA_IN | SDA_OUT | SCL | SIZE_MASK | PAGE_MASK |
- ----------------------------------|------------|------------|------------|----------------|-----------|
- NBA Jam | 0x200001-0 | 0x200001-0 | 0x200001-1 | 0x00ff (24C02) | 0x03 | xx
- NBA Jam TE | 0x200001-0 | 0x200001-0 | 0x200000-0 | 0x00ff (24C02) | 0x03 | xx
- NBA Jam TE (32x) | 0x200001-0 | 0x200001-0 | 0x200000-0 | 0x00ff (24C02) | 0x03 |
- NFL Quarterback Club | 0x200001-0 | 0x200001-0 | 0x200000-0 | 0x00ff (24C02) | 0x03 | xx
- NFL Quarterback Club 96 | 0x200001-0 | 0x200001-0 | 0x200000-0 | 0x07ff (24C16) | 0x07 | xx
- College Slam | 0x200001-0 | 0x200001-0 | 0x200000-0 | 0x1fff (24C64) | 0x07 | xx
- Frank Thomas Big Hurt Baseball | 0x200001-0 | 0x200001-0 | 0x200000-0 | 0x1fff (24C64) | 0x07 | xx
- NHLPA Hockey 93 | 0x200001-7 | 0x200001-7 | 0x200001-6 | 0x007f (24C01) | 0x03 | xx
- Rings of Power | 0x200001-7 | 0x200001-7 | 0x200001-6 | 0x007f (24C01) | 0x03 | xx
- Evander Holyfield's Boxing | 0x200001-0 | 0x200001-0 | 0x200001-1 | 0x007f (24C01) | 0x03 | xx
- Greatest Heavyweights of the Ring | 0x200001-0 | 0x200001-0 | 0x200001-1 | 0x007f (24C01) | 0x03 | xx
- Wonder Boy V | 0x200001-0 | 0x200001-0 | 0x200001-1 | 0x007f (24C01) | 0x03 | xx
- Sports Talk Baseball | 0x200001-0 | 0x200001-0 | 0x200001-1 | 0x007f (24C01) | 0x03 | xx
- Megaman - the Wily Wars | 0x200001-0 | 0x200001-0 | 0x200001-1 | 0x007f (24C01) | 0x03 | xx **
- Micro Machines 2 | 0x380001-7 | 0x300000-0*| 0x300000-1*| 0x03ff (24C08) | 0x0f |
- Micro Machines Military | 0x380001-7 | 0x300000-0*| 0x300000-1*| 0x03ff (24C08) | 0x0f |
- Micro Machines 96 | 0x380001-7 | 0x300000-0*| 0x300000-1*| 0x07ff (24C16) | 0x0f |
- Brian Lara Cricket 96 | 0x380001-7 | 0x300000-0*| 0x300000-1*| 0x1fff (24C64) | 0x??* |
- ----------------------------------|------------|------------|------------|----------------|-----------|
-
- * Notes: check these
- ** original Rockman Mega World (J) set uses normal backup RAM
-
+ MegaDrive / Genesis cart + I2C EEPROM emulation
+
+
+ TODO: EEPROM hookup verification in most games.
+
+
+ I2C games mapping table:
+
+ Game Name | SDA_IN | SDA_OUT | SCL | SIZE_MASK | PAGE_MASK | WORKS |
+ ----------------------------------|------------|------------|------------|----------------|-----------|-------|
+ NBA Jam | 0x200001-0 | 0x200001-0 | 0x200001-1 | 0x00ff (24C02) | 0x03 | |
+ NBA Jam TE | 0x200001-0 | 0x200001-0 | 0x200000-0 | 0x00ff (24C02) | 0x03 | |
+ NBA Jam TE (32x) | 0x200001-0 | 0x200001-0 | 0x200000-0 | 0x00ff (24C02) | 0x03 | |
+ NFL Quarterback Club | 0x200001-0 | 0x200001-0 | 0x200000-0 | 0x00ff (24C02) | 0x03 | |
+ NFL Quarterback Club 96 | 0x200001-0 | 0x200001-0 | 0x200000-0 | 0x07ff (24C16) | 0x07 | |
+ College Slam | 0x200001-0 | 0x200001-0 | 0x200000-0 | 0x1fff (24C64) | 0x07 | |
+ Frank Thomas Big Hurt Baseball | 0x200001-0 | 0x200001-0 | 0x200000-0 | 0x1fff (24C64) | 0x07 | |
+ NHLPA Hockey 93 | 0x200001-7 | 0x200001-7 | 0x200001-6 | 0x007f (24C01) | 0x03 | |
+ Rings of Power | 0x200001-7 | 0x200001-7 | 0x200001-6 | 0x007f (24C01) | 0x03 | |
+ Honoo no Toukyuuji - Dodge Danpei | 0x200001-0 | 0x200001-0 | 0x200001-1 | 0x007f (24C01) | 0x03 | Unk. |
+ Evander Holyfield's Boxing | 0x200001-0 | 0x200001-0 | 0x200001-1 | 0x007f (24C01) | 0x03 | Yes |
+ Greatest Heavyweights of the Ring | 0x200001-0 | 0x200001-0 | 0x200001-1 | 0x007f (24C01) | 0x03 | Yes |
+ Wonder Boy V | 0x200001-0 | 0x200001-0 | 0x200001-1 | 0x007f (24C01) | 0x03 | Yes |
+ Sports Talk Baseball | 0x200001-0 | 0x200001-0 | 0x200001-1 | 0x007f (24C01) | 0x03 | Yes |
+ Megaman - The Wily Wars | 0x200001-0 | 0x200001-0 | 0x200001-1 | 0x007f (24C01) | 0x03 | Yes | **
+ Micro Machines 2 | 0x380001-7 | 0x300000-0*| 0x300000-1*| 0x03ff (24C08) | 0x0f | Yes |
+ Micro Machines Military | 0x380001-7 | 0x300000-0*| 0x300000-1*| 0x03ff (24C08) | 0x0f | Yes |
+ Micro Machines 96 | 0x380001-7 | 0x300000-0*| 0x300000-1*| 0x07ff (24C16) | 0x0f | Yes |
+ Brian Lara Cricket 96 | 0x380001-7 | 0x300000-0*| 0x300000-1*| 0x1fff (24C64) | 0x??* | |
+ Shame Warne Cricket | 0x380001-7 | 0x300000-0*| 0x300000-1*| 0x1fff (24C64) | 0x??* | |
+ ----------------------------------|------------|------------|------------|----------------|-----------|-------|
+
+ * Not specified in Eke-Eke's document
+ ** Original Rockman Mega World (J) set uses normal backup RAM
Micro Machines 2, Micro Machines Military, Micro Machines 96 are emulated in md_jcart
@@ -58,6 +59,7 @@ DEFINE_DEVICE_TYPE(MD_EEPROM_NFLQB, md_eeprom_nflqb_device, "md_eeprom_nfl
DEFINE_DEVICE_TYPE(MD_EEPROM_CSLAM, md_eeprom_cslam_device, "md_eeprom_cslam", "MD College Slam")
DEFINE_DEVICE_TYPE(MD_EEPROM_NHLPA, md_eeprom_nhlpa_device, "md_eeprom_nhlpa", "MD NHLPA 93")
DEFINE_DEVICE_TYPE(MD_EEPROM_BLARA, md_eeprom_blara_device, "md_eeprom_blara", "MD Brian Lara")
+DEFINE_DEVICE_TYPE(MD_EEPROM_MODE1, md_eeprom_mode1_device, "md_eeprom_mode1", "MD Serial EEPROM Mode 1")
md_std_eeprom_device::md_std_eeprom_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock)
@@ -102,6 +104,11 @@ md_eeprom_blara_device::md_eeprom_blara_device(const machine_config &mconfig, co
{
}
+md_eeprom_mode1_device::md_eeprom_mode1_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
+ : md_std_eeprom_device(mconfig, MD_EEPROM_MODE1, tag, owner, clock)
+{
+}
+
//-------------------------------------------------
// device_add_mconfig - add device configuration
@@ -142,6 +149,11 @@ void md_eeprom_blara_device::device_add_mconfig(machine_config &config)
I2C_24C64(config, m_i2cmem);
}
+void md_eeprom_mode1_device::device_add_mconfig(machine_config &config)
+{
+ I2C_X24C01(config, m_i2cmem);
+}
+
void md_std_eeprom_device::device_start()
{
save_item(NAME(m_i2c_mem));
@@ -162,11 +174,12 @@ void md_std_eeprom_device::device_reset()
CART + EEPROM
-------------------------------------------------*/
-READ16_MEMBER(md_std_eeprom_device::read)
+uint16_t md_std_eeprom_device::read(offs_t offset)
{
if (offset == 0x200000/2)
{
- return m_i2cmem->read_sda();
+ const uint8_t data = m_i2cmem->read_sda();
+ return ((uint16_t)data << 8) | data;
}
if (offset < 0x400000/2)
return m_rom[MD_ADDR(offset)];
@@ -174,7 +187,7 @@ READ16_MEMBER(md_std_eeprom_device::read)
return 0xffff;
}
-WRITE16_MEMBER(md_std_eeprom_device::write)
+void md_std_eeprom_device::write(offs_t offset, uint16_t data, uint16_t mem_mask)
{
if (offset == 0x200000/2)
{
@@ -185,7 +198,7 @@ WRITE16_MEMBER(md_std_eeprom_device::write)
}
}
-READ16_MEMBER(md_eeprom_nbajam_device::read)
+uint16_t md_eeprom_nbajam_device::read(offs_t offset)
{
if (offset == 0x200000/2)
{
@@ -198,7 +211,7 @@ READ16_MEMBER(md_eeprom_nbajam_device::read)
return 0xffff;
}
-WRITE16_MEMBER(md_eeprom_nbajam_device::write)
+void md_eeprom_nbajam_device::write(offs_t offset, uint16_t data, uint16_t mem_mask)
{
if (offset == 0x200000/2)
{
@@ -209,7 +222,7 @@ WRITE16_MEMBER(md_eeprom_nbajam_device::write)
}
}
-READ16_MEMBER(md_eeprom_nbajamte_device::read)
+uint16_t md_eeprom_nbajamte_device::read(offs_t offset)
{
if (offset == 0x200000/2)
{
@@ -222,7 +235,7 @@ READ16_MEMBER(md_eeprom_nbajamte_device::read)
return 0xffff;
}
-WRITE16_MEMBER(md_eeprom_nbajamte_device::write)
+void md_eeprom_nbajamte_device::write(offs_t offset, uint16_t data, uint16_t mem_mask)
{
if (offset == 0x200000/2)
{
@@ -241,7 +254,7 @@ WRITE16_MEMBER(md_eeprom_nbajamte_device::write)
}
// same as NBAJAMTE above... derived class?
-READ16_MEMBER(md_eeprom_cslam_device::read)
+uint16_t md_eeprom_cslam_device::read(offs_t offset)
{
if (offset == 0x200000/2)
{
@@ -254,7 +267,7 @@ READ16_MEMBER(md_eeprom_cslam_device::read)
return 0xffff;
}
-WRITE16_MEMBER(md_eeprom_cslam_device::write)
+void md_eeprom_cslam_device::write(offs_t offset, uint16_t data, uint16_t mem_mask)
{
if (offset == 0x200000/2)
{
@@ -273,7 +286,7 @@ WRITE16_MEMBER(md_eeprom_cslam_device::write)
}
// same as NBAJAMTE above... derived class?
-READ16_MEMBER(md_eeprom_nflqb_device::read)
+uint16_t md_eeprom_nflqb_device::read(offs_t offset)
{
if (offset == 0x200000/2)
{
@@ -286,7 +299,7 @@ READ16_MEMBER(md_eeprom_nflqb_device::read)
return 0xffff;
}
-WRITE16_MEMBER(md_eeprom_nflqb_device::write)
+void md_eeprom_nflqb_device::write(offs_t offset, uint16_t data, uint16_t mem_mask)
{
if (offset == 0x200000/2)
{
@@ -297,7 +310,7 @@ WRITE16_MEMBER(md_eeprom_nflqb_device::write)
}
}
-READ16_MEMBER(md_eeprom_nhlpa_device::read)
+uint16_t md_eeprom_nhlpa_device::read(offs_t offset)
{
if (offset == 0x200000/2)
{
@@ -310,7 +323,7 @@ READ16_MEMBER(md_eeprom_nhlpa_device::read)
return 0xffff;
}
-WRITE16_MEMBER(md_eeprom_nhlpa_device::write)
+void md_eeprom_nhlpa_device::write(offs_t offset, uint16_t data, uint16_t mem_mask)
{
if (offset == 0x200000/2)
{
@@ -321,7 +334,7 @@ WRITE16_MEMBER(md_eeprom_nhlpa_device::write)
}
}
-READ16_MEMBER(md_eeprom_blara_device::read)
+uint16_t md_eeprom_blara_device::read(offs_t offset)
{
if (offset == 0x380000/2)
{
@@ -334,7 +347,7 @@ READ16_MEMBER(md_eeprom_blara_device::read)
return 0xffff;
}
-WRITE16_MEMBER(md_eeprom_blara_device::write)
+void md_eeprom_blara_device::write(offs_t offset, uint16_t data, uint16_t mem_mask)
{
if (offset == 0x380000/2)
{
@@ -584,7 +597,7 @@ uint8_t md_eeprom_nbajam_alt_device::eeprom_i2c_out()
}
-READ16_MEMBER(md_eeprom_nbajam_alt_device::read)
+uint16_t md_eeprom_nbajam_alt_device::read(offs_t offset)
{
if (offset == 0x200000/2)
{
@@ -596,7 +609,7 @@ READ16_MEMBER(md_eeprom_nbajam_alt_device::read)
return 0xffff;
}
-WRITE16_MEMBER(md_eeprom_nbajam_alt_device::write)
+void md_eeprom_nbajam_alt_device::write(offs_t offset, uint16_t data, uint16_t mem_mask)
{
if (offset == 0x200000/2)
{
diff --git a/src/devices/bus/megadrive/eeprom.h b/src/devices/bus/megadrive/eeprom.h
index de60b413c27..729f9c338db 100644
--- a/src/devices/bus/megadrive/eeprom.h
+++ b/src/devices/bus/megadrive/eeprom.h
@@ -26,13 +26,13 @@ protected:
md_std_eeprom_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 device_start() override ATTR_COLD;
+ virtual void device_reset() override ATTR_COLD;
+ virtual void device_add_mconfig(machine_config &config) override ATTR_COLD;
// reading and writing
- virtual DECLARE_READ16_MEMBER(read) override;
- virtual DECLARE_WRITE16_MEMBER(write) override;
+ virtual uint16_t read(offs_t offset) override;
+ virtual void write(offs_t offset, uint16_t data, uint16_t mem_mask = ~0) override;
required_device<i2cmem_device> m_i2cmem;
uint8_t m_i2c_mem, m_i2c_clk;
@@ -48,11 +48,11 @@ public:
protected:
// device-level overrides
- virtual void device_add_mconfig(machine_config &config) override;
+ virtual void device_add_mconfig(machine_config &config) override ATTR_COLD;
// reading and writing
- virtual DECLARE_READ16_MEMBER(read) override;
- virtual DECLARE_WRITE16_MEMBER(write) override;
+ virtual uint16_t read(offs_t offset) override;
+ virtual void write(offs_t offset, uint16_t data, uint16_t mem_mask = ~0) override;
};
// ======================> md_eeprom_nbajamte_device
@@ -65,11 +65,11 @@ public:
protected:
// device-level overrides
- virtual void device_add_mconfig(machine_config &config) override;
+ virtual void device_add_mconfig(machine_config &config) override ATTR_COLD;
// reading and writing
- virtual DECLARE_READ16_MEMBER(read) override;
- virtual DECLARE_WRITE16_MEMBER(write) override;
+ virtual uint16_t read(offs_t offset) override;
+ virtual void write(offs_t offset, uint16_t data, uint16_t mem_mask = ~0) override;
};
// ======================> md_eeprom_cslam_device (same read/write as nbajamte, but different I2C type)
@@ -82,11 +82,11 @@ public:
protected:
// device-level overrides
- virtual void device_add_mconfig(machine_config &config) override;
+ virtual void device_add_mconfig(machine_config &config) override ATTR_COLD;
// reading and writing
- virtual DECLARE_READ16_MEMBER(read) override;
- virtual DECLARE_WRITE16_MEMBER(write) override;
+ virtual uint16_t read(offs_t offset) override;
+ virtual void write(offs_t offset, uint16_t data, uint16_t mem_mask = ~0) override;
};
// ======================> md_eeprom_nflqb_device (same read/write as nbajamte, but different I2C type)
@@ -99,11 +99,11 @@ public:
protected:
// device-level overrides
- virtual void device_add_mconfig(machine_config &config) override;
+ virtual void device_add_mconfig(machine_config &config) override ATTR_COLD;
// reading and writing
- virtual DECLARE_READ16_MEMBER(read) override;
- virtual DECLARE_WRITE16_MEMBER(write) override;
+ virtual uint16_t read(offs_t offset) override;
+ virtual void write(offs_t offset, uint16_t data, uint16_t mem_mask = ~0) override;
};
// ======================> md_eeprom_nhlpa_device
@@ -116,11 +116,11 @@ public:
protected:
// device-level overrides
- virtual void device_add_mconfig(machine_config &config) override;
+ virtual void device_add_mconfig(machine_config &config) override ATTR_COLD;
// reading and writing
- virtual DECLARE_READ16_MEMBER(read) override;
- virtual DECLARE_WRITE16_MEMBER(write) override;
+ virtual uint16_t read(offs_t offset) override;
+ virtual void write(offs_t offset, uint16_t data, uint16_t mem_mask = ~0) override;
};
// ======================> md_eeprom_blara_device (same read/write as codemast, but different I2C type)
@@ -133,11 +133,24 @@ public:
protected:
// device-level overrides
- virtual void device_add_mconfig(machine_config &config) override;
+ virtual void device_add_mconfig(machine_config &config) override ATTR_COLD;
// reading and writing
- virtual DECLARE_READ16_MEMBER(read) override;
- virtual DECLARE_WRITE16_MEMBER(write) override;
+ virtual uint16_t read(offs_t offset) override;
+ virtual void write(offs_t offset, uint16_t data, uint16_t mem_mask = ~0) override;
+};
+
+// ======================> md_eeprom_mode1_device
+
+class md_eeprom_mode1_device : public md_std_eeprom_device
+{
+public:
+ // construction/destruction
+ md_eeprom_mode1_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
+
+protected:
+ // device-level overrides
+ virtual void device_add_mconfig(machine_config &config) override ATTR_COLD;
};
@@ -149,6 +162,7 @@ DECLARE_DEVICE_TYPE(MD_EEPROM_CSLAM, md_eeprom_cslam_device)
DECLARE_DEVICE_TYPE(MD_EEPROM_NFLQB, md_eeprom_nflqb_device)
DECLARE_DEVICE_TYPE(MD_EEPROM_NHLPA, md_eeprom_nhlpa_device)
DECLARE_DEVICE_TYPE(MD_EEPROM_BLARA, md_eeprom_blara_device)
+DECLARE_DEVICE_TYPE(MD_EEPROM_MODE1, md_eeprom_mode1_device)
@@ -174,12 +188,12 @@ public:
md_eeprom_nbajam_alt_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
// reading and writing
- virtual DECLARE_READ16_MEMBER(read) override;
- virtual DECLARE_WRITE16_MEMBER(write) override;
+ virtual uint16_t read(offs_t offset) override;
+ virtual void write(offs_t offset, uint16_t data, uint16_t mem_mask = ~0) override;
protected:
// device-level overrides
- virtual void device_start() override;
+ virtual void device_start() override ATTR_COLD;
private:
void eeprom_i2c_init();
diff --git a/src/devices/bus/megadrive/ggenie.cpp b/src/devices/bus/megadrive/ggenie.cpp
index 17dbb78fc1d..e4df6f8ef29 100644
--- a/src/devices/bus/megadrive/ggenie.cpp
+++ b/src/devices/bus/megadrive/ggenie.cpp
@@ -63,7 +63,7 @@ void md_rom_ggenie_device::device_reset()
mapper specific handlers
-------------------------------------------------*/
-READ16_MEMBER(md_rom_ggenie_device::read)
+uint16_t md_rom_ggenie_device::read(offs_t offset)
{
if (!m_gg_bypass || !m_exp->m_cart)
{
@@ -88,13 +88,13 @@ READ16_MEMBER(md_rom_ggenie_device::read)
else if (offset == m_gg_addr[5]/2 && BIT(m_gg_regs[0], 5))
return m_gg_data[5];
else
- return m_exp->m_cart->read(space, offset);
+ return m_exp->m_cart->read(offset);
}
else
return 0xffff;
}
-WRITE16_MEMBER(md_rom_ggenie_device::write)
+void md_rom_ggenie_device::write(offs_t offset, uint16_t data, uint16_t mem_mask)
{
if (offset >= 0x40/2)
return;
diff --git a/src/devices/bus/megadrive/ggenie.h b/src/devices/bus/megadrive/ggenie.h
index 38e282ac747..e72df698cc8 100644
--- a/src/devices/bus/megadrive/ggenie.h
+++ b/src/devices/bus/megadrive/ggenie.h
@@ -18,15 +18,15 @@ public:
md_rom_ggenie_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_start() override ATTR_COLD;
+ virtual void device_reset() override ATTR_COLD;
// device-level overrides
- virtual void device_add_mconfig(machine_config &config) override;
+ virtual void device_add_mconfig(machine_config &config) override ATTR_COLD;
// reading and writing
- virtual DECLARE_READ16_MEMBER(read) override;
- virtual DECLARE_WRITE16_MEMBER(write) override;
+ virtual uint16_t read(offs_t offset) override;
+ virtual void write(offs_t offset, uint16_t data, uint16_t mem_mask = ~0) override;
private:
required_device<md_cart_slot_device> m_exp;
diff --git a/src/devices/bus/megadrive/jcart.cpp b/src/devices/bus/megadrive/jcart.cpp
index 76f38ff0dd3..d8cad677e52 100644
--- a/src/devices/bus/megadrive/jcart.cpp
+++ b/src/devices/bus/megadrive/jcart.cpp
@@ -3,25 +3,20 @@
/***********************************************************************************************************
- MegaDrive / Genesis J-Cart (+SEPROM) emulation
+ MegaDrive / Genesis J-Cart + I2C EEPROM emulation
- Emulation based on earlier researches by ElBarto
+ Emulation based on earlier research by ElBarto and Eke-Eke
- i2c games mapping table:
+ I2C games mapping table:
- game name | SDA_IN | SDA_OUT | SCL | SIZE_MASK | PAGE_MASK |
- ----------------------------------|------------|------------|------------|----------------|-----------|
- Micro Machines 2 | 0x380001-7 | 0x300000-0*| 0x300000-1*| 0x03ff (24C08) | 0x0f |
- Micro Machines Military | 0x380001-7 | 0x300000-0*| 0x300000-1*| 0x03ff (24C08) | 0x0f |
- Micro Machines 96 | 0x380001-7 | 0x300000-0*| 0x300000-1*| 0x07ff (24C16) | 0x0f |
- ----------------------------------|------------|------------|------------|----------------|-----------|
-
- * Notes: check these
-
-
- TODO: proper SEPROM emulation, still not worked on (just hooked up the I2C device)
+ Game Name | SDA_IN | SDA_OUT | SCL | SIZE_MASK | PAGE_MASK | WORKS |
+ ----------------------------------|------------|------------|------------|----------------|-----------|-------|
+ Micro Machines 2 | 0x380001-7 | 0x300000-0*| 0x300000-1*| 0x03ff (24C08) | 0x0f | Yes |
+ Micro Machines Military | 0x380001-7 | 0x300000-0*| 0x300000-1*| 0x03ff (24C08) | 0x0f | Yes |
+ Micro Machines 96 | 0x380001-7 | 0x300000-0*| 0x300000-1*| 0x07ff (24C16) | 0x0f | Yes |
+ ----------------------------------|------------|------------|------------|----------------|-----------|-------|
***********************************************************************************************************/
@@ -30,6 +25,8 @@
#include "emu.h"
#include "jcart.h"
+#include "bus/sms_ctrl/controllers.h"
+
//-------------------------------------------------
// md_rom_device - constructor
@@ -43,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)
{
}
@@ -81,60 +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)
{
- I2C_24C16A(config, m_i2cmem);
-}
-
-
-static INPUT_PORTS_START( jcart_ipt )
+ md_jcart_device::device_add_mconfig(config);
- PORT_START("JCART3") /* Joypad 3 on J-Cart (3 button + start) */
- PORT_BIT( 0x0001, IP_ACTIVE_LOW, IPT_JOYSTICK_UP ) PORT_8WAY PORT_PLAYER(3)
- PORT_BIT( 0x0002, IP_ACTIVE_LOW, IPT_JOYSTICK_DOWN ) PORT_8WAY PORT_PLAYER(3)
- PORT_BIT( 0x0004, IP_ACTIVE_LOW, IPT_JOYSTICK_LEFT ) PORT_8WAY PORT_PLAYER(3)
- PORT_BIT( 0x0008, IP_ACTIVE_LOW, IPT_JOYSTICK_RIGHT ) PORT_8WAY PORT_PLAYER(3)
- PORT_BIT( 0x0010, IP_ACTIVE_LOW, IPT_BUTTON2 ) PORT_PLAYER(3) PORT_NAME("P3 B")
- PORT_BIT( 0x0020, IP_ACTIVE_LOW, IPT_BUTTON3 ) PORT_PLAYER(3) PORT_NAME("P3 C")
- PORT_BIT( 0x0040, IP_ACTIVE_LOW, IPT_BUTTON1 ) PORT_PLAYER(3) PORT_NAME("P3 A")
- PORT_BIT( 0x0080, IP_ACTIVE_LOW, IPT_START ) PORT_PLAYER(3)
-
- PORT_START("JCART4") /* Joypad 4 on J-Cart (3 button + start) */
- PORT_BIT( 0x0001, IP_ACTIVE_LOW, IPT_JOYSTICK_UP ) PORT_8WAY PORT_PLAYER(4)
- PORT_BIT( 0x0002, IP_ACTIVE_LOW, IPT_JOYSTICK_DOWN ) PORT_8WAY PORT_PLAYER(4)
- PORT_BIT( 0x0004, IP_ACTIVE_LOW, IPT_JOYSTICK_LEFT ) PORT_8WAY PORT_PLAYER(4)
- PORT_BIT( 0x0008, IP_ACTIVE_LOW, IPT_JOYSTICK_RIGHT ) PORT_8WAY PORT_PLAYER(4)
- PORT_BIT( 0x0010, IP_ACTIVE_LOW, IPT_BUTTON2 ) PORT_PLAYER(4) PORT_NAME("P4 B")
- PORT_BIT( 0x0020, IP_ACTIVE_LOW, IPT_BUTTON3 ) PORT_PLAYER(4) PORT_NAME("P4 C")
- PORT_BIT( 0x0040, IP_ACTIVE_LOW, IPT_BUTTON1 ) PORT_PLAYER(4) PORT_NAME("P4 A")
- PORT_BIT( 0x0080, IP_ACTIVE_LOW, IPT_START ) PORT_PLAYER(4)
+ I2C_24C16(config, m_i2cmem); // 24C16A
+}
-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));
@@ -142,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;
@@ -157,24 +147,13 @@ void md_seprom_codemast_device::device_reset()
J-CART ONLY (Pete Sampras Tennis)
-------------------------------------------------*/
-READ16_MEMBER(md_jcart_device::read)
+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_safe(0);
- joy[1] = m_jcart4.read_safe(0);
- return (m_jcart_io_data[0] & 0x40) | joy[0] | (joy[1] << 8);
- }
- else
- {
- joy[0] = ((m_jcart3.read_safe(0) & 0xc0) >> 2) | (m_jcart3.read_safe(0) & 0x03);
- joy[1] = ((m_jcart4.read_safe(0) & 0xc0) >> 2) | (m_jcart4.read_safe(0) & 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)];
@@ -182,61 +161,52 @@ READ16_MEMBER(md_jcart_device::read)
return 0xffff;
}
-WRITE16_MEMBER(md_jcart_device::write)
+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
-------------------------------------------------*/
-READ16_MEMBER(md_seprom_codemast_device::read)
+uint16_t md_seprom_codemast_device::read(offs_t offset)
{
if (offset == 0x380000/2)
{
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_safe(0);
- joy[1] = m_jcart4.read_safe(0);
- return (m_jcart_io_data[0] & 0x40) | joy[0] | (joy[1] << 8);
- }
- else
- {
- joy[0] = ((m_jcart3.read_safe(0) & 0xc0) >> 2) | (m_jcart3.read_safe(0) & 0x03);
- joy[1] = ((m_jcart4.read_safe(0) & 0xc0) >> 2) | (m_jcart4.read_safe(0) & 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;
}
-WRITE16_MEMBER(md_seprom_codemast_device::write)
+void md_seprom_codemast_device::write(offs_t offset, uint16_t data, uint16_t mem_mask)
{
- if (offset == 0x380000/2)
+ if (offset == 0x300000/2)
{
m_i2c_clk = BIT(data, 9);
m_i2c_mem = BIT(data, 8);
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 510a91a5d37..768abf8c7bc 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,27 +20,26 @@ 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 DECLARE_READ16_MEMBER(read) override;
- virtual DECLARE_WRITE16_MEMBER(write) override;
+ virtual uint16_t read(offs_t offset) override;
+ virtual void write(offs_t offset, uint16_t data, uint16_t mem_mask = ~0) override;
protected:
md_jcart_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;
-
- required_ioport m_jcart3;
- required_ioport m_jcart4;
+ virtual void device_add_mconfig(machine_config &config) override ATTR_COLD;
+ virtual void device_resolve_objects() override ATTR_COLD;
+ virtual void device_start() override ATTR_COLD;
+ virtual void device_reset() override ATTR_COLD;
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
{
@@ -51,15 +50,15 @@ public:
protected:
md_seprom_codemast_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_start() override ATTR_COLD;
+ virtual void device_reset() override ATTR_COLD;
// device-level overrides
- virtual void device_add_mconfig(machine_config &config) override;
+ virtual void device_add_mconfig(machine_config &config) override ATTR_COLD;
// reading and writing
- virtual DECLARE_READ16_MEMBER(read) override;
- virtual DECLARE_WRITE16_MEMBER(write) override;
+ virtual uint16_t read(offs_t offset) override;
+ virtual void write(offs_t offset, uint16_t data, uint16_t mem_mask = ~0) override;
required_device<i2cmem_device> m_i2cmem;
@@ -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
{
@@ -78,7 +76,7 @@ public:
protected:
// device-level overrides
- virtual void device_add_mconfig(machine_config &config) override;
+ virtual void device_add_mconfig(machine_config &config) override ATTR_COLD;
};
@@ -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_carts.cpp b/src/devices/bus/megadrive/md_carts.cpp
index 7b2e8fa333d..c5be97a54f4 100644
--- a/src/devices/bus/megadrive/md_carts.cpp
+++ b/src/devices/bus/megadrive/md_carts.cpp
@@ -32,7 +32,7 @@ void md_cart(device_slot_interface &device)
device.option_add_internal("rom_sf001", MD_ROM_BEGGARP);
device.option_add_internal("rom_sf002", MD_ROM_WUKONG);
device.option_add_internal("rom_sf004", MD_ROM_STARODYS);
-// EEPROM handling (not supported fully yet)
+// EEPROM handling (most not supported fully yet)
device.option_add_internal("rom_eeprom", MD_STD_EEPROM);
device.option_add_internal("rom_nbajam", MD_EEPROM_NBAJAM);
device.option_add_internal("rom_nbajamte", MD_EEPROM_NBAJAMTE);
@@ -40,6 +40,7 @@ void md_cart(device_slot_interface &device)
device.option_add_internal("rom_cslam", MD_EEPROM_CSLAM);
device.option_add_internal("rom_nhlpa", MD_EEPROM_NHLPA);
device.option_add_internal("rom_blara", MD_EEPROM_BLARA);
+ device.option_add_internal("rom_eeprom_mode1", MD_EEPROM_MODE1);
// J-Cart controller (Sampras Tennis)
device.option_add_internal("rom_jcart", MD_JCART);
// J-Cart controller + EEPROM handling (not supported fully yet)
@@ -79,6 +80,8 @@ void md_cart(device_slot_interface &device)
device.option_add_internal("rom_smouse", MD_ROM_SMOUSE);
device.option_add_internal("rom_soulb", MD_ROM_SOULB);
device.option_add_internal("rom_squir", MD_ROM_SQUIR);
+ device.option_add_internal("rom_sram_arg96", MD_ROM_SRAM_ARG96);
+ device.option_add_internal("rom_tc2000", MD_ROM_TC2000);
device.option_add_internal("rom_tekkensp", MD_ROM_TEKKENSP);
device.option_add_internal("rom_topf", MD_ROM_TOPF);
diff --git a/src/devices/bus/megadrive/md_slot.cpp b/src/devices/bus/megadrive/md_slot.cpp
index 26afaf888cc..a7b4d2a20ac 100644
--- a/src/devices/bus/megadrive/md_slot.cpp
+++ b/src/devices/bus/megadrive/md_slot.cpp
@@ -43,7 +43,6 @@
***********************************************************************************************************/
-
#include "emu.h"
#include "md_slot.h"
@@ -64,7 +63,7 @@ DEFINE_DEVICE_TYPE(COPERA_CART_SLOT, copera_cart_slot_device, "copera_cart_slot"
//-------------------------------------------------
device_md_cart_interface::device_md_cart_interface(const machine_config &mconfig, device_t &device)
- : device_slot_card_interface(mconfig, device), m_nvram_start(0), m_nvram_end(0), m_nvram_active(0), m_nvram_readonly(0), m_nvram_handlers_installed(0),
+ : device_interface(device, "mdcart"), m_nvram_start(0), m_nvram_end(0), m_nvram_active(0), m_nvram_readonly(0), m_nvram_handlers_installed(0),
m_rom(nullptr),
m_rom_size(0)
{
@@ -83,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;
}
}
@@ -162,10 +161,9 @@ uint32_t device_md_cart_interface::get_padded_size(uint32_t size)
//-------------------------------------------------
base_md_cart_slot_device::base_md_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_image_interface(mconfig, *this),
- device_slot_interface(mconfig, *this),
- m_type(SEGA_STD), m_cart(nullptr),
- m_must_be_loaded(1)
+ device_cartrom_image_interface(mconfig, *this),
+ device_single_card_slot_interface<device_md_cart_interface>(mconfig, *this),
+ m_type(SEGA_STD), m_cart(nullptr)
{
}
@@ -198,7 +196,7 @@ base_md_cart_slot_device::~base_md_cart_slot_device()
void base_md_cart_slot_device::device_start()
{
- m_cart = dynamic_cast<device_md_cart_interface *>(get_card_device());
+ m_cart = get_card_device();
}
@@ -271,6 +269,7 @@ static const md_slot slot_list[] =
{ SMOUSE, "rom_smouse" },
{ SOULBLAD, "rom_soulblad" },
{ SQUIRRELK, "rom_squir" },
+ { SRAM_ARG96, "rom_sram_arg96" },
{ TEKKENSP, "rom_tekkesp" },
{ TOPFIGHTER, "rom_topf" },
@@ -282,7 +281,7 @@ static int md_get_pcb_id(const char *slot)
{
for (auto & elem : slot_list)
{
- if (!core_stricmp(elem.slot_option, slot))
+ if (!strcmp(elem.slot_option, slot))
return elem.pcb_id;
}
@@ -310,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
@@ -327,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)
@@ -345,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");
@@ -361,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"));
@@ -378,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();
}
@@ -454,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;
@@ -473,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();
@@ -534,7 +533,7 @@ image_init_result base_md_cart_slot_device::load_nonlist()
}
#endif
- return image_init_result::PASS;
+ return std::error_condition();
}
/*-------------------------------------------------
@@ -615,6 +614,7 @@ void base_md_cart_slot_device::setup_nvram()
// These types only come from softlist loading
case SEGA_SRAM:
+ case SRAM_ARG96:
m_cart->m_nvram_start = 0x200000;
m_cart->m_nvram_end = m_cart->m_nvram_start + get_software_region_length("sram") - 1;
m_cart->nvram_alloc(m_cart->m_nvram_end - m_cart->m_nvram_start + 1);
@@ -905,23 +905,23 @@ std::string base_md_cart_slot_device::get_default_card_software(get_default_card
{
if (hook.image_file())
{
- const char *slot_string;
- uint32_t len = hook.image_file()->size(), offset = 0;
+ uint64_t len;
+ hook.image_file()->length(len); // FIXME: check error return, guard against excessively large files
std::vector<uint8_t> rom(len);
- int type;
- hook.image_file()->read(&rom[0], len);
+ util::read(*hook.image_file(), &rom[0], len); // FIXME: check error return or read returning short
- if (genesis_is_SMD(&rom[0x200], len - 0x200))
- offset = 0x200;
+ uint32_t const offset = genesis_is_SMD(&rom[0x200], len - 0x200) ? 0x200 : 0;
- type = get_cart_type(&rom[offset], len - offset);
- slot_string = md_get_slot(type);
+ int const type = get_cart_type(&rom[offset], len - offset);
+ char const *const slot_string = md_get_slot(type);
return std::string(slot_string);
}
else
+ {
return software_get_default_slot("rom");
+ }
}
@@ -930,26 +930,26 @@ std::string base_md_cart_slot_device::get_default_card_software(get_default_card
read
-------------------------------------------------*/
-READ16_MEMBER(base_md_cart_slot_device::read)
+uint16_t base_md_cart_slot_device::read(offs_t offset)
{
if (m_cart)
- return m_cart->read(space, offset, mem_mask);
+ return m_cart->read(offset);
else
return 0xffff;
}
-READ16_MEMBER(base_md_cart_slot_device::read_a13)
+uint16_t base_md_cart_slot_device::read_a13(offs_t offset)
{
if (m_cart)
- return m_cart->read_a13(space, offset, mem_mask);
+ return m_cart->read_a13(offset);
else
return 0xffff;
}
-READ16_MEMBER(base_md_cart_slot_device::read_a15)
+uint16_t base_md_cart_slot_device::read_a15(offs_t offset)
{
if (m_cart)
- return m_cart->read_a15(space, offset, mem_mask);
+ return m_cart->read_a15(offset);
else
return 0xffff;
}
@@ -959,22 +959,22 @@ READ16_MEMBER(base_md_cart_slot_device::read_a15)
write
-------------------------------------------------*/
-WRITE16_MEMBER(base_md_cart_slot_device::write)
+void base_md_cart_slot_device::write(offs_t offset, uint16_t data, uint16_t mem_mask)
{
if (m_cart)
- m_cart->write(space, offset, data, mem_mask);
+ m_cart->write(offset, data, mem_mask);
}
-WRITE16_MEMBER(base_md_cart_slot_device::write_a13)
+void base_md_cart_slot_device::write_a13(offs_t offset, uint16_t data)
{
if (m_cart)
- m_cart->write_a13(space, offset, data, mem_mask);
+ m_cart->write_a13(offset, data);
}
-WRITE16_MEMBER(base_md_cart_slot_device::write_a15)
+void base_md_cart_slot_device::write_a15(offs_t offset, uint16_t data)
{
if (m_cart)
- m_cart->write_a15(space, offset, data, mem_mask);
+ m_cart->write_a15(offset, data);
}
/*-------------------------------------------------
@@ -1033,8 +1033,8 @@ void base_md_cart_slot_device::file_logging(uint8_t *ROM8, uint32_t rom_len, uin
rom_start = (ROM8[0x1a1] << 24 | ROM8[0x1a0] << 16 | ROM8[0x1a3] << 8 | ROM8[0x1a2]);
rom_end = (ROM8[0x1a5] << 24 | ROM8[0x1a4] << 16 | ROM8[0x1a7] << 8 | ROM8[0x1a6]);
- ram_start = (ROM8[0x1a9] << 24 | ROM8[0x1a8] << 16 | ROM8[0x1ab] << 8 | ROM8[0x1aa]);;
- ram_end = (ROM8[0x1ad] << 24 | ROM8[0x1ac] << 16 | ROM8[0x1af] << 8 | ROM8[0x1ae]);;
+ ram_start = (ROM8[0x1a9] << 24 | ROM8[0x1a8] << 16 | ROM8[0x1ab] << 8 | ROM8[0x1aa]);
+ ram_end = (ROM8[0x1ad] << 24 | ROM8[0x1ac] << 16 | ROM8[0x1af] << 8 | ROM8[0x1ae]);
if (ROM8[0x1b1] == 'R' && ROM8[0x1b0] == 'A')
{
valid_sram = true;
@@ -1081,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 42fd2503f76..82c8b09e8af 100644
--- a/src/devices/bus/megadrive/md_slot.h
+++ b/src/devices/bus/megadrive/md_slot.h
@@ -5,7 +5,7 @@
#pragma once
-#include "softlist_dev.h"
+#include "imagedev/cartrom.h"
/***************************************************************************
TYPE DEFINITIONS
@@ -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 */
@@ -78,6 +78,8 @@ enum
SMOUSE, /* Smart Mouse */
SOULBLAD, /* Soul Blade */
SQUIRRELK, /* Squirrel King */
+ SRAM_ARG96, /* Futbol Argentino 96 (Argentina) (hack of J. League Pro Striker 2) */
+ TC2000, /* TC 2000 (Argentina, protected) */
TEKKENSP, /* Tekken Special */
TOPFIGHTER, /* Top Fighter 2000 MK VIII */
@@ -89,7 +91,7 @@ enum
// ======================> device_md_cart_interface
-class device_md_cart_interface : public device_slot_card_interface
+class device_md_cart_interface : public device_interface
{
friend class base_md_cart_slot_device;
public:
@@ -97,25 +99,25 @@ public:
virtual ~device_md_cart_interface();
// reading and writing
- virtual DECLARE_READ16_MEMBER(read) { return 0xffff; }
- virtual DECLARE_WRITE16_MEMBER(write) {}
- virtual DECLARE_READ16_MEMBER(read_a13) { return 0xffff; }
- virtual DECLARE_WRITE16_MEMBER(write_a13) {}
- virtual DECLARE_READ16_MEMBER(read_a15) { return 0xffff; }
- virtual DECLARE_WRITE16_MEMBER(write_a15) {}
+ virtual uint16_t read(offs_t offset) { return 0xffff; }
+ virtual void write(offs_t offset, uint16_t data, uint16_t mem_mask = ~0) {}
+ virtual uint16_t read_a13(offs_t offset) { return 0xffff; }
+ virtual void write_a13(offs_t offset, uint16_t data) {}
+ virtual uint16_t read_a15(offs_t offset) { return 0xffff; }
+ virtual void write_a15(offs_t offset, uint16_t data) {}
virtual int read_test() { return 0; } // used by Virtua Racing test
- /* this probably should do more, like make Genesis V2 'die' if the SEGA string is not written promptly */
- virtual DECLARE_WRITE16_MEMBER(write_tmss_bank) { m_device.logerror("Write to TMSS bank: offset %x data %x\n", 0xa14000 + (offset << 1), data); };
+ // 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]; };
- virtual uint32_t get_rom_size() { return m_rom_size; };
- virtual uint32_t get_nvram_size() { return m_nvram.size()*sizeof(uint16_t); };
- virtual void set_bank_to_rom(const char *banktag, uint32_t offset) {};
+ virtual uint16_t* get_rom_base() { return m_rom; }
+ virtual uint16_t* get_nvram_base() { return &m_nvram[0]; }
+ virtual uint32_t get_rom_size() { return m_rom_size; }
+ virtual uint32_t get_nvram_size() { return m_nvram.size()*sizeof(uint16_t); }
+ virtual void set_bank_to_rom(const char *banktag, uint32_t offset) {}
void save_nvram() { device().save_item(NAME(m_nvram)); }
@@ -134,7 +136,7 @@ protected:
int m_nvram_handlers_installed;
// internal state
-public: // FIXME: this needs to be public becuase the S&K "lock-on" cart is implemented in a really dodgy way
+public: // FIXME: this needs to be public because the S&K "lock-on" cart is implemented in a really dodgy way
uint16_t *m_rom;
protected:
uint32_t m_rom_size;
@@ -147,62 +149,56 @@ protected:
// ======================> base_md_cart_slot_device
class base_md_cart_slot_device : public device_t,
- public device_image_interface,
- public device_slot_interface
+ public device_cartrom_image_interface,
+ public device_single_card_slot_interface<device_md_cart_interface>
{
public:
// construction/destruction
- base_md_cart_slot_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock);
virtual ~base_md_cart_slot_device();
- // 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 void call_unload() override;
- virtual const software_list_loader &get_software_list_loader() const override { return rom_software_list_loader::instance(); }
- virtual iodevice_t image_type() const override { return IO_CARTSLOT; }
- virtual bool is_readable() const override { return 1; }
- virtual bool is_writeable() const override { return 0; }
- virtual bool is_creatable() const override { return 0; }
- virtual bool must_be_loaded() const override { return m_must_be_loaded; }
- virtual bool is_reset_on_load() const override { return 1; }
+ 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();
void setup_nvram();
- void set_must_be_loaded(bool _must_be_loaded) { m_must_be_loaded = _must_be_loaded; }
void file_logging(uint8_t *ROM, uint32_t rom_len, uint32_t nvram_len);
void save_nvram() { if (m_cart && m_cart->get_nvram_size()) m_cart->save_nvram(); }
// reading and writing
- virtual DECLARE_READ16_MEMBER(read);
- virtual DECLARE_WRITE16_MEMBER(write);
- virtual DECLARE_READ16_MEMBER(read_a13);
- virtual DECLARE_WRITE16_MEMBER(write_a13);
- virtual DECLARE_READ16_MEMBER(read_a15);
- virtual DECLARE_WRITE16_MEMBER(write_a15);
- virtual DECLARE_WRITE16_MEMBER(write_tmss_bank) { if (m_cart) m_cart->write_tmss_bank(space, offset, data, mem_mask); };
+ virtual uint16_t read(offs_t offset);
+ virtual void write(offs_t offset, uint16_t data, uint16_t mem_mask = ~0);
+ virtual uint16_t read_a13(offs_t offset);
+ virtual void write_a13(offs_t offset, uint16_t data);
+ virtual uint16_t read_a15(offs_t offset);
+ virtual void write_a15(offs_t offset, uint16_t data);
+ virtual void write_tmss_bank(offs_t offset, uint16_t data) { if (m_cart) m_cart->write_tmss_bank(offset, data); }
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;
device_md_cart_interface* m_cart;
- bool m_must_be_loaded;
+
+protected:
+ base_md_cart_slot_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 ATTR_COLD;
};
// ======================> md_cart_slot_device
@@ -222,8 +218,10 @@ public:
}
md_cart_slot_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
- virtual const char *image_interface() const override { return "megadriv_cart"; }
- virtual const char *file_extensions() const override { return "smd,bin,md,gen"; }
+
+ // 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"; }
};
// ======================> pico_cart_slot_device
@@ -242,8 +240,10 @@ public:
set_fixed(false);
}
pico_cart_slot_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
- virtual const char *image_interface() const override { return "pico_cart"; }
- virtual const char *file_extensions() const override { return "bin,md"; }
+
+ // 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"; }
};
// ======================> copera_cart_slot_device
@@ -262,8 +262,10 @@ public:
set_fixed(false);
}
copera_cart_slot_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
- virtual const char *image_interface() const override { return "copera_cart"; }
- virtual const char *file_extensions() const override { return "bin,md"; }
+
+ // 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"; }
};
@@ -272,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/megadrive/rom.cpp b/src/devices/bus/megadrive/rom.cpp
index ac54cfcc8fd..6c624f2b515 100644
--- a/src/devices/bus/megadrive/rom.cpp
+++ b/src/devices/bus/megadrive/rom.cpp
@@ -57,12 +57,14 @@ DEFINE_DEVICE_TYPE(MD_ROM_POKESTAD, md_rom_pokestad_device, "md_rom_pokestad", "
DEFINE_DEVICE_TYPE(MD_ROM_REALTEC, md_rom_realtec_device, "md_rom_realtec", "MD Realtec")
DEFINE_DEVICE_TYPE(MD_ROM_REDCL, md_rom_redcl_device, "md_rom_redcl", "MD Redcliff")
DEFINE_DEVICE_TYPE(MD_ROM_SQUIR, md_rom_squir_device, "md_rom_squir", "MD Squirrel King")
+DEFINE_DEVICE_TYPE(MD_ROM_TC2000, md_rom_tc2000_device, "md_rom_tc2000", "MD TC2000")
DEFINE_DEVICE_TYPE(MD_ROM_TEKKENSP, md_rom_tekkensp_device, "md_rom_tekkensp", "MD Tekken Special")
DEFINE_DEVICE_TYPE(MD_ROM_TOPF, md_rom_topf_device, "md_rom_topf", "MD Top Fighter")
DEFINE_DEVICE_TYPE(MD_ROM_RADICA, md_rom_radica_device, "md_rom_radica", "MD Radica TV games")
DEFINE_DEVICE_TYPE(MD_ROM_BEGGARP, md_rom_beggarp_device, "md_rom_beggarp", "MD Beggar Prince")
DEFINE_DEVICE_TYPE(MD_ROM_WUKONG, md_rom_wukong_device, "md_rom_wukong", "MD Legend of Wukong")
DEFINE_DEVICE_TYPE(MD_ROM_STARODYS, md_rom_starodys_device, "md_rom_starodys", "MD Star Odyssey")
+DEFINE_DEVICE_TYPE(MD_ROM_SRAM_ARG96, md_rom_sram_arg96_device, "md_rom_sram_arg96", "MD Futbol Argentino 96")
md_std_rom_device::md_std_rom_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock)
@@ -76,10 +78,22 @@ md_std_rom_device::md_std_rom_device(const machine_config &mconfig, const char *
}
md_rom_sram_device::md_rom_sram_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
- : md_std_rom_device(mconfig, MD_ROM_SRAM, tag, owner, clock)
+ : md_rom_sram_device(mconfig, MD_ROM_SRAM, tag, owner, clock)
{
}
+md_rom_sram_device::md_rom_sram_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock)
+ : md_std_rom_device(mconfig, type, tag, owner, clock)
+{
+}
+
+
+md_rom_sram_arg96_device::md_rom_sram_arg96_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
+ : md_rom_sram_device(mconfig, MD_ROM_SRAM_ARG96, tag, owner, clock)
+{
+}
+
+
md_rom_fram_device::md_rom_fram_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
: md_std_rom_device(mconfig, MD_ROM_FRAM, tag, owner, clock)
{
@@ -215,6 +229,11 @@ md_rom_squir_device::md_rom_squir_device(const machine_config &mconfig, const ch
{
}
+md_rom_tc2000_device::md_rom_tc2000_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
+ : md_std_rom_device(mconfig, MD_ROM_TC2000, tag, owner, clock)
+{
+}
+
md_rom_tekkensp_device::md_rom_tekkensp_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
: md_std_rom_device(mconfig, MD_ROM_TEKKENSP, tag, owner, clock), m_reg(0)
{
@@ -450,7 +469,7 @@ void md_rom_starodys_device::device_reset()
CART + SRAM
-------------------------------------------------*/
-READ16_MEMBER(md_rom_sram_device::read)
+uint16_t md_rom_sram_device::read(offs_t offset)
{
// since a lot of generic carts ends up here if loaded from fullpath
// we access nvram only if m_nvram_handlers_installed has been turned on
@@ -465,7 +484,7 @@ READ16_MEMBER(md_rom_sram_device::read)
return 0xffff;
}
-WRITE16_MEMBER(md_rom_sram_device::write)
+void md_rom_sram_device::write(offs_t offset, uint16_t data, uint16_t mem_mask)
{
// since a lot of generic carts ends up here if loaded from fullpath
// we access nvram only if m_nvram_handlers_installed has been turned on
@@ -476,7 +495,7 @@ WRITE16_MEMBER(md_rom_sram_device::write)
}
}
-WRITE16_MEMBER(md_rom_sram_device::write_a13)
+void md_rom_sram_device::write_a13(offs_t offset, uint16_t data)
{
if (offset == 0xf0/2)
{
@@ -495,7 +514,7 @@ WRITE16_MEMBER(md_rom_sram_device::write_a13)
CART + FRAM [almost same as SRAM... merge common parts?]
-------------------------------------------------*/
-READ16_MEMBER(md_rom_fram_device::read)
+uint16_t md_rom_fram_device::read(offs_t offset)
{
if (offset >= m_nvram_start/2 && offset <= m_nvram_end/2 && m_nvram_active)
return m_nvram[offset - m_nvram_start/2];
@@ -505,20 +524,20 @@ READ16_MEMBER(md_rom_fram_device::read)
return 0xffff;
}
-WRITE16_MEMBER(md_rom_fram_device::write)
+void md_rom_fram_device::write(offs_t offset, uint16_t data, uint16_t mem_mask)
{
if (offset >= m_nvram_start/2 && offset <= m_nvram_end/2 && m_nvram_active)
m_nvram[offset - m_nvram_start/2] = data;
}
-WRITE16_MEMBER(md_rom_fram_device::write_a13)
+void md_rom_fram_device::write_a13(offs_t offset, uint16_t data)
{
if (offset == 0xf0/2)
m_nvram_active = BIT(data, 0);
}
-READ16_MEMBER(md_rom_fram_device::read_a13)
+uint16_t md_rom_fram_device::read_a13(offs_t offset)
{
if (offset == 0xf0/2)
return m_nvram_active;
@@ -530,7 +549,7 @@ READ16_MEMBER(md_rom_fram_device::read_a13)
SUPER STREET FIGHTERS 2
-------------------------------------------------*/
-READ16_MEMBER(md_rom_ssf2_device::read)
+uint16_t md_rom_ssf2_device::read(offs_t offset)
{
if (offset < 0x400000/2)
return m_rom[offset];
@@ -539,7 +558,7 @@ READ16_MEMBER(md_rom_ssf2_device::read)
}
// I'm not very fond of the code below...
-WRITE16_MEMBER(md_rom_ssf2_device::write_a13)
+void md_rom_ssf2_device::write_a13(offs_t offset, uint16_t data)
{
if (offset >= 0xf0/2)
{
@@ -564,7 +583,7 @@ WRITE16_MEMBER(md_rom_ssf2_device::write_a13)
#define MD_ADDR_CM2IN1(a) (m_base == 0 ? ((a << 1) & 0x1fffff)/2 : (((a << 1) & 0x1fffff) + 0x200000)/2)
-READ16_MEMBER(md_rom_cm2in1_device::read)
+uint16_t md_rom_cm2in1_device::read(offs_t offset)
{
if (offset < 0x400000/2)
return m_rom[MD_ADDR_CM2IN1(offset)];
@@ -577,15 +596,15 @@ READ16_MEMBER(md_rom_cm2in1_device::read)
PIRATE MULTICARTS
-------------------------------------------------*/
-READ16_MEMBER(md_rom_mcpirate_device::read)
+uint16_t md_rom_mcpirate_device::read(offs_t offset)
{
if (offset < 0x400000/2)
return m_rom[(((m_bank * 0x10000) + (offset << 1)) & (m_rom_size - 1))/2];
else
- return read(space, offset - 0x400000/2, 0xffff);
+ return read(offset - 0x400000/2);
}
-WRITE16_MEMBER(md_rom_mcpirate_device::write_a13)
+void md_rom_mcpirate_device::write_a13(offs_t offset, uint16_t data)
{
offset <<= 1;
if (offset < 0x40)
@@ -596,7 +615,7 @@ WRITE16_MEMBER(md_rom_mcpirate_device::write_a13)
A BUG'S LIFE
-------------------------------------------------*/
-READ16_MEMBER(md_rom_bugslife_device::read_a13)
+uint16_t md_rom_bugslife_device::read_a13(offs_t offset)
{
if (offset == 0x00/2) return 0x28;
if (offset == 0x02/2) return 0x01;
@@ -608,7 +627,7 @@ READ16_MEMBER(md_rom_bugslife_device::read_a13)
CHINESE FIGHTER 3
-------------------------------------------------*/
-READ16_MEMBER(md_rom_chinf3_device::read)
+uint16_t md_rom_chinf3_device::read(offs_t offset)
{
if (offset < 0x100000/2)
{
@@ -680,7 +699,7 @@ READ16_MEMBER(md_rom_chinf3_device::read)
return 0xffff;
}
-WRITE16_MEMBER(md_rom_chinf3_device::write)
+void md_rom_chinf3_device::write(offs_t offset, uint16_t data, uint16_t mem_mask)
{
if (offset >= 0x600000/2 && offset < 0x700000/2)
{
@@ -701,7 +720,7 @@ WRITE16_MEMBER(md_rom_chinf3_device::write)
16 MAHJONG II
-------------------------------------------------*/
-READ16_MEMBER(md_rom_16mj2_device::read)
+uint16_t md_rom_16mj2_device::read(offs_t offset)
{
if (offset == 0x400004/2) return 0xc900;
@@ -716,7 +735,7 @@ READ16_MEMBER(md_rom_16mj2_device::read)
LINGHUAN DAOSHI SUPER MAGICIAN / ELF WOR
-------------------------------------------------*/
-READ16_MEMBER(md_rom_elfwor_device::read)
+uint16_t md_rom_elfwor_device::read(offs_t offset)
{
// It returns (0x55 @ 0x400000 OR 0xc9 @ 0x400004) AND (0x0f @ 0x400002 OR 0x18 @ 0x400006).
// It is probably best to add handlers for all 4 addresses
@@ -736,7 +755,7 @@ READ16_MEMBER(md_rom_elfwor_device::read)
HUAN LE TAO QI SHU / SMART MOUSE
-------------------------------------------------*/
-READ16_MEMBER(md_rom_smouse_device::read)
+uint16_t md_rom_smouse_device::read(offs_t offset)
{
if (offset == 0x400000/2) return 0x5500;
if (offset == 0x400002/2) return 0x0f00;
@@ -754,7 +773,7 @@ READ16_MEMBER(md_rom_smouse_device::read)
YA SE CHUAN SHUO
-------------------------------------------------*/
-READ16_MEMBER(md_rom_yasech_device::read)
+uint16_t md_rom_yasech_device::read(offs_t offset)
{
if (offset == 0x400000/2) return 0x6300;
if (offset == 0x400002/2) return 0x9800;
@@ -772,7 +791,7 @@ READ16_MEMBER(md_rom_yasech_device::read)
KOF98
-------------------------------------------------*/
-READ16_MEMBER(md_rom_kof98_device::read)
+uint16_t md_rom_kof98_device::read(offs_t offset)
{
if (offset == 0x480000/2) return 0xaa00;
if (offset == 0x4800e0/2) return 0xaa00;
@@ -792,7 +811,7 @@ READ16_MEMBER(md_rom_kof98_device::read)
KOF 99
-------------------------------------------------*/
-READ16_MEMBER(md_rom_kof99_device::read_a13)
+uint16_t md_rom_kof99_device::read_a13(offs_t offset)
{
if (offset == 0x00/2) return 0x00; // startup protection check, chinese message if != 0
if (offset == 0x02/2) return 0x01; // write 02 to a13002.. shift right 1?
@@ -804,7 +823,7 @@ READ16_MEMBER(md_rom_kof99_device::read_a13)
LION KING 2
-------------------------------------------------*/
-READ16_MEMBER(md_rom_lion2_device::read)
+uint16_t md_rom_lion2_device::read(offs_t offset)
{
if (offset == 0x400002/2) return m_prot1_data;
if (offset == 0x400006/2) return m_prot2_data;
@@ -816,7 +835,7 @@ READ16_MEMBER(md_rom_lion2_device::read)
return 0xffff;
}
-WRITE16_MEMBER(md_rom_lion2_device::write)
+void md_rom_lion2_device::write(offs_t offset, uint16_t data, uint16_t mem_mask)
{
if (offset == 0x400000/2) m_prot1_data = data;
if (offset == 0x400004/2) m_prot2_data = data;
@@ -828,7 +847,7 @@ WRITE16_MEMBER(md_rom_lion2_device::write)
#define MD_LION3_ADDR(a) (((offset << 1) | (m_bank << 15)) & (m_rom_size - 1))/2
-READ16_MEMBER(md_rom_lion3_device::read)
+uint16_t md_rom_lion3_device::read(offs_t offset)
{
if (offset < 0x100000/2)
return m_rom[MD_LION3_ADDR(offset)];
@@ -855,7 +874,7 @@ READ16_MEMBER(md_rom_lion3_device::read)
return 0xffff;
}
-WRITE16_MEMBER(md_rom_lion3_device::write)
+void md_rom_lion3_device::write(offs_t offset, uint16_t data, uint16_t mem_mask)
{
if (offset >= 0x600000/2 && offset < 0x700000/2)
{
@@ -907,7 +926,7 @@ WRITE16_MEMBER(md_rom_lion3_device::write)
MA JIANG QING REN / MAHJONG LOVER
-------------------------------------------------*/
-READ16_MEMBER(md_rom_mjlov_device::read)
+uint16_t md_rom_mjlov_device::read(offs_t offset)
{
if (offset == 0x400000/2) return 0x9000;
if (offset == 0x401000/2) return 0xd300;
@@ -924,7 +943,7 @@ READ16_MEMBER(md_rom_mjlov_device::read)
CHAOJI MAJIANG CLUB
-------------------------------------------------*/
-READ16_MEMBER(md_rom_cjmjclub_device::read)
+uint16_t md_rom_cjmjclub_device::read(offs_t offset)
{
if (offset == 0x400000/2) return 0x9000;
if (offset == 0x400002/2) return 0xd300;
@@ -941,7 +960,7 @@ READ16_MEMBER(md_rom_cjmjclub_device::read)
SUPER BUBBLE BOBBLE MD
-------------------------------------------------*/
-READ16_MEMBER(md_rom_sbubl_device::read)
+uint16_t md_rom_sbubl_device::read(offs_t offset)
{
if (offset == 0x400000/2) return 0x5500;
if (offset == 0x400002/2) return 0x0f00;
@@ -957,7 +976,7 @@ READ16_MEMBER(md_rom_sbubl_device::read)
SOUL BLADE
-------------------------------------------------*/
-READ16_MEMBER(md_rom_soulb_device::read)
+uint16_t md_rom_soulb_device::read(offs_t offset)
{
if (offset == 0x400002/2) return 0x9800;
if (offset == 0x400004/2) return 0xc900;
@@ -976,7 +995,7 @@ READ16_MEMBER(md_rom_soulb_device::read)
#define MD_POKESTAD_ADDR(a) (((offset << 1) | (m_bank << 15)) & (m_rom_size - 1))/2
-READ16_MEMBER(md_rom_pokestad_device::read)
+uint16_t md_rom_pokestad_device::read(offs_t offset)
{
if (offset < 0x100000/2)
return m_rom[MD_POKESTAD_ADDR(offset)];
@@ -988,7 +1007,7 @@ READ16_MEMBER(md_rom_pokestad_device::read)
return 0xffff;
}
-WRITE16_MEMBER(md_rom_pokestad_device::write)
+void md_rom_pokestad_device::write(offs_t offset, uint16_t data, uint16_t mem_mask)
{
if (offset >= 0x700000/2 && offset < 0x800000/2)
m_bank = data & 0x7f;
@@ -998,7 +1017,7 @@ WRITE16_MEMBER(md_rom_pokestad_device::write)
POKEMON ALT
-------------------------------------------------*/
-READ16_MEMBER(md_rom_pokea_device::read_a13)
+uint16_t md_rom_pokea_device::read_a13(offs_t offset)
{
if (offset == 0x00/2) return 0x14;
if (offset == 0x02/2) return 0x01;
@@ -1010,14 +1029,14 @@ READ16_MEMBER(md_rom_pokea_device::read_a13)
REALTEC
-------------------------------------------------*/
-READ16_MEMBER(md_rom_realtec_device::read)
+uint16_t md_rom_realtec_device::read(offs_t offset)
{
if (offset < (m_bank_size * 0x20000)) // two banks of same (variable) size at the bottom of the rom
return m_rom[MD_ADDR((offset + (m_bank_addr * 0x20000)/2))];
return m_rom[MD_ADDR(((offset & 0x1fff/2) + 0x7e000/2))]; // otherwise it accesses the final 8k of the image
}
-WRITE16_MEMBER(md_rom_realtec_device::write)
+void md_rom_realtec_device::write(offs_t offset, uint16_t data, uint16_t mem_mask)
{
if (offset == 0x400000/2)
{
@@ -1040,7 +1059,7 @@ WRITE16_MEMBER(md_rom_realtec_device::write)
RED CLIFF
-------------------------------------------------*/
-READ16_MEMBER(md_rom_redcl_device::read)
+uint16_t md_rom_redcl_device::read(offs_t offset)
{
if (offset == 0x400000/2) return 0x55 << 8;
if (offset == 0x400004/2) return 0xaa << 8;
@@ -1056,7 +1075,7 @@ READ16_MEMBER(md_rom_redcl_device::read)
ROCKMAN X3
-------------------------------------------------*/
-READ16_MEMBER(md_rom_rx3_device::read_a13)
+uint16_t md_rom_rx3_device::read_a13(offs_t offset)
{
if (offset == 0)
return 0x0c;
@@ -1068,7 +1087,7 @@ READ16_MEMBER(md_rom_rx3_device::read_a13)
SQUIRREL KING
-------------------------------------------------*/
-READ16_MEMBER(md_rom_squir_device::read)
+uint16_t md_rom_squir_device::read(offs_t offset)
{
if ((offset >= 0x400000/2) && (offset < 0x400008/2))
return m_latch;
@@ -1080,7 +1099,7 @@ READ16_MEMBER(md_rom_squir_device::read)
return 0xffff;
}
-WRITE16_MEMBER(md_rom_squir_device::write)
+void md_rom_squir_device::write(offs_t offset, uint16_t data, uint16_t mem_mask)
{
if (offset >= 0x400000/2 && offset < 0x400008/2)
m_latch = data;
@@ -1090,7 +1109,7 @@ WRITE16_MEMBER(md_rom_squir_device::write)
SUPER MARIO BROS
-------------------------------------------------*/
-READ16_MEMBER(md_rom_smb_device::read_a13)
+uint16_t md_rom_smb_device::read_a13(offs_t offset)
{
if (offset == 0)
return 0x0c;
@@ -1102,7 +1121,7 @@ READ16_MEMBER(md_rom_smb_device::read_a13)
SUPER MARIO BROS 2
-------------------------------------------------*/
-READ16_MEMBER(md_rom_smb2_device::read_a13)
+uint16_t md_rom_smb2_device::read_a13(offs_t offset)
{
if (offset == 0)
return 0x0a;
@@ -1114,7 +1133,7 @@ READ16_MEMBER(md_rom_smb2_device::read_a13)
SUPER MARIO WORLD 64
-------------------------------------------------*/
-READ16_MEMBER(md_rom_smw64_device::read)
+uint16_t md_rom_smw64_device::read(offs_t offset)
{
// 0x000000-0x0fffff: lower 512KB ROM (up to 0x07ffff) + mirror
// 0x600000-0x6fffff: internal hardware (up to 0x67ffff) + mirror
@@ -1179,7 +1198,7 @@ READ16_MEMBER(md_rom_smw64_device::read)
return 0xffff;
}
-WRITE16_MEMBER(md_rom_smw64_device::write)
+void md_rom_smw64_device::write(offs_t offset, uint16_t data, uint16_t mem_mask)
{
// 0x600000-0x6fffff: internal hardware (up to 0x67ffff) + mirror
// Namely,
@@ -1225,10 +1244,65 @@ WRITE16_MEMBER(md_rom_smw64_device::write)
}
/*-------------------------------------------------
+ TC2000 / TRUCO 96
+ -------------------------------------------------*/
+
+void md_rom_tc2000_device::device_start()
+{
+ save_item(NAME(m_retvalue));
+}
+
+void md_rom_tc2000_device::device_reset()
+{
+ m_retvalue = 0;
+}
+
+uint16_t md_rom_tc2000_device::read(offs_t offset)
+{
+ if (offset < 0x100000 / 2)
+ {
+ return md_std_rom_device::read(offset);
+ }
+ else
+ {
+ // this works for game boot and starting a game, are there any further checks?
+ logerror("protection read at offset %08x returning %04x\n", offset*2, m_retvalue);
+
+ return m_retvalue;
+ }
+}
+
+void md_rom_tc2000_device::write(offs_t offset, uint16_t data, uint16_t mem_mask)
+{
+ if (offset < 0x100000/2)
+ {
+ md_std_rom_device::write(offset, data, mem_mask);
+ }
+ else
+ {
+ if (((offset * 2) & 0xf) == 0x0) // truco96a uses this case
+ {
+ m_retvalue = 0x0000;
+ }
+ else if (((offset * 2) & 0xf) == 0x8)
+ {
+ m_retvalue = 0x5000;
+ }
+ else if (((offset * 2) & 0xf) == 0xc)
+ {
+ m_retvalue = 0xa000;
+ }
+
+ logerror("protection write at offset %08x %04x %04x\n", offset*2, data, mem_mask);
+ }
+}
+
+
+/*-------------------------------------------------
TEKKEN SPECIAL
-------------------------------------------------*/
-READ16_MEMBER(md_rom_tekkensp_device::read)
+uint16_t md_rom_tekkensp_device::read(offs_t offset)
{
if (offset < 0x400000/2)
return m_rom[MD_ADDR(offset)];
@@ -1238,7 +1312,7 @@ READ16_MEMBER(md_rom_tekkensp_device::read)
return 0xffff;
}
-WRITE16_MEMBER(md_rom_tekkensp_device::write)
+void md_rom_tekkensp_device::write(offs_t offset, uint16_t data, uint16_t mem_mask)
{
if (offset < 0x400000/2)
return;
@@ -1274,7 +1348,7 @@ WRITE16_MEMBER(md_rom_tekkensp_device::write)
TOP FIGHTER
-------------------------------------------------*/
-READ16_MEMBER(md_rom_topf_device::read)
+uint16_t md_rom_topf_device::read(offs_t offset)
{
//cpu #0 (PC=0004CBAE): unmapped program memory word read from 006A35D4 & 00FF -- wants regD7
if (offset == 0x645b44/2)
@@ -1329,7 +1403,7 @@ READ16_MEMBER(md_rom_topf_device::read)
return 0xffff;
}
-WRITE16_MEMBER(md_rom_topf_device::write)
+void md_rom_topf_device::write(offs_t offset, uint16_t data, uint16_t mem_mask)
{
if (offset >= 0x700000/2 && offset < 0x800000/2)
{
@@ -1354,12 +1428,12 @@ WRITE16_MEMBER(md_rom_topf_device::write)
RADICA TV GAMES [to be split...]
-------------------------------------------------*/
-READ16_MEMBER(md_rom_radica_device::read)
+uint16_t md_rom_radica_device::read(offs_t offset)
{
return m_rom[(((m_bank * 0x10000) + (offset << 1)) & (m_rom_size - 1))/2];
}
-READ16_MEMBER(md_rom_radica_device::read_a13)
+uint16_t md_rom_radica_device::read_a13(offs_t offset)
{
if (offset < 0x80)
m_bank = offset & 0x3f;
@@ -1377,7 +1451,7 @@ READ16_MEMBER(md_rom_radica_device::read_a13)
the end of ROM.
-------------------------------------------------*/
-READ16_MEMBER(md_rom_beggarp_device::read)
+uint16_t md_rom_beggarp_device::read(offs_t offset)
{
if (offset >= m_nvram_start/2 && offset <= m_nvram_end/2 && m_nvram_active)
return m_nvram[offset & 0x3fff];
@@ -1390,7 +1464,7 @@ READ16_MEMBER(md_rom_beggarp_device::read)
return 0xffff;
}
-WRITE16_MEMBER(md_rom_beggarp_device::write)
+void md_rom_beggarp_device::write(offs_t offset, uint16_t data, uint16_t mem_mask)
{
if (offset >= 0x0e00/2 && offset < 0x0f00/2)
m_mode = BIT(data, 7);
@@ -1400,7 +1474,7 @@ WRITE16_MEMBER(md_rom_beggarp_device::write)
}
// this works the same as in standard SRAM carts
-WRITE16_MEMBER(md_rom_beggarp_device::write_a13)
+void md_rom_beggarp_device::write_a13(offs_t offset, uint16_t data)
{
if (offset == 0xf0/2)
{
@@ -1424,7 +1498,7 @@ WRITE16_MEMBER(md_rom_beggarp_device::write_a13)
(i.e. mirror of first 128K)
-------------------------------------------------*/
-READ16_MEMBER(md_rom_wukong_device::read)
+uint16_t md_rom_wukong_device::read(offs_t offset)
{
if (offset >= m_nvram_start/2 && offset <= m_nvram_end/2 && m_nvram_active)
return m_nvram[offset - m_nvram_start/2];
@@ -1438,7 +1512,7 @@ READ16_MEMBER(md_rom_wukong_device::read)
return 0xffff;
}
-WRITE16_MEMBER(md_rom_wukong_device::write)
+void md_rom_wukong_device::write(offs_t offset, uint16_t data, uint16_t mem_mask)
{
if (offset < 0x100000/2) // it actually writes to 0xe00/2
m_mode = BIT(data, 7);
@@ -1448,7 +1522,7 @@ WRITE16_MEMBER(md_rom_wukong_device::write)
}
// this works the same as in standard SRAM carts
-WRITE16_MEMBER(md_rom_wukong_device::write_a13)
+void md_rom_wukong_device::write_a13(offs_t offset, uint16_t data)
{
if (offset == 0xf0/2)
{
@@ -1474,7 +1548,7 @@ WRITE16_MEMBER(md_rom_wukong_device::write_a13)
gives open bus
-------------------------------------------------*/
-READ16_MEMBER(md_rom_starodys_device::read)
+uint16_t md_rom_starodys_device::read(offs_t offset)
{
if (offset >= m_nvram_start/2 && offset <= m_nvram_end/2 && m_nvram_active && m_ram_enable)
return m_nvram[offset & 0x3fff];
@@ -1494,7 +1568,7 @@ READ16_MEMBER(md_rom_starodys_device::read)
return 0xffff;
}
-WRITE16_MEMBER(md_rom_starodys_device::write)
+void md_rom_starodys_device::write(offs_t offset, uint16_t data, uint16_t mem_mask)
{
if (offset >= m_nvram_start/2 && offset <= m_nvram_end/2 && m_nvram_active && !m_nvram_readonly && m_ram_enable)
m_nvram[offset & 0x3fff] = data;
@@ -1536,13 +1610,13 @@ WRITE16_MEMBER(md_rom_starodys_device::write)
}
-READ16_MEMBER(md_rom_starodys_device::read_a13)
+uint16_t md_rom_starodys_device::read_a13(offs_t offset)
{
return m_base << 4;
}
// this works the same as in standard SRAM carts
-WRITE16_MEMBER(md_rom_starodys_device::write_a13)
+void md_rom_starodys_device::write_a13(offs_t offset, uint16_t data)
{
if (offset == 0xf0/2)
{
@@ -1553,3 +1627,43 @@ WRITE16_MEMBER(md_rom_starodys_device::write_a13)
m_nvram_handlers_installed = 1;
}
}
+
+
+/*-------------------------------------------------
+ Futbol Argentino 96 (Argentina)
+ -------------------------------------------------*/
+
+uint16_t md_rom_sram_arg96_device::read(offs_t offset)
+{
+ if (offset < 0x400000 / 2)
+ {
+ return md_rom_sram_device::read(offset);
+ }
+ else
+ {
+ // these return values are probably connected somehow with the writes
+ // but the game only ever looks for these results before doing DMA operations
+ if ((offset * 2) == 0x4c6200)
+ return 0xa;
+ else if ((offset * 2) == 0x4c6600)
+ return 0x9;
+ else if ((offset * 2) == 0x4c6a00)
+ return 0x7;
+ else
+ logerror("unhandled read at offset %08x\n", offset);
+
+ return 0x0000;
+ }
+}
+
+void md_rom_sram_arg96_device::write(offs_t offset, uint16_t data, uint16_t mem_mask)
+{
+ if (offset < 0x400000/2)
+ {
+ md_rom_sram_device::write(offset, data, mem_mask);
+ }
+ else
+ {
+ logerror("unhandled write at offset %08x %04x %04x\n", offset, data, mem_mask);
+ }
+}
diff --git a/src/devices/bus/megadrive/rom.h b/src/devices/bus/megadrive/rom.h
index 8077ad7e0c6..b98469d3155 100644
--- a/src/devices/bus/megadrive/rom.h
+++ b/src/devices/bus/megadrive/rom.h
@@ -21,8 +21,8 @@ public:
md_std_rom_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
// reading and writing
- virtual DECLARE_READ16_MEMBER(read) override { if (offset < 0x400000/2) return m_rom[MD_ADDR(offset)]; else return 0xffff; }
- virtual DECLARE_WRITE16_MEMBER(write) override { }
+ virtual uint16_t read(offs_t offset) override { if (offset < 0x400000/2) return m_rom[MD_ADDR(offset)]; else return 0xffff; }
+ virtual void write(offs_t offset, uint16_t data, uint16_t mem_mask = ~0) override { }
protected:
md_std_rom_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock);
@@ -39,10 +39,25 @@ public:
// construction/destruction
md_rom_sram_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
+protected:
+ md_rom_sram_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock);
+
+public:
// reading and writing
- virtual DECLARE_READ16_MEMBER(read) override;
- virtual DECLARE_WRITE16_MEMBER(write) override;
- virtual DECLARE_WRITE16_MEMBER(write_a13) override;
+ virtual uint16_t read(offs_t offset) override;
+ virtual void write(offs_t offset, uint16_t data, uint16_t mem_mask = ~0) override;
+ virtual void write_a13(offs_t offset, uint16_t data) override;
+};
+
+// ======================> md_rom_sram_arg96_device
+
+class md_rom_sram_arg96_device : public md_rom_sram_device
+{
+public:
+ md_rom_sram_arg96_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
+
+ virtual uint16_t read(offs_t offset) override;
+ virtual void write(offs_t offset, uint16_t data, uint16_t mem_mask = ~0) override;
};
// ======================> md_rom_fram_device
@@ -54,10 +69,10 @@ public:
md_rom_fram_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
// reading and writing
- virtual DECLARE_READ16_MEMBER(read) override;
- virtual DECLARE_WRITE16_MEMBER(write) override;
- virtual DECLARE_READ16_MEMBER(read_a13) override;
- virtual DECLARE_WRITE16_MEMBER(write_a13) override;
+ virtual uint16_t read(offs_t offset) override;
+ virtual void write(offs_t offset, uint16_t data, uint16_t mem_mask = ~0) override;
+ virtual uint16_t read_a13(offs_t offset) override;
+ virtual void write_a13(offs_t offset, uint16_t data) override;
};
// ======================> md_rom_ssf2_device
@@ -69,13 +84,13 @@ public:
md_rom_ssf2_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
// reading and writing
- virtual DECLARE_READ16_MEMBER(read) override;
- virtual DECLARE_WRITE16_MEMBER(write_a13) override;
+ virtual uint16_t read(offs_t offset) override;
+ virtual void write_a13(offs_t offset, uint16_t data) override;
protected:
// device-level overrides
- virtual void device_start() override;
- virtual void device_reset() override;
+ virtual void device_start() override ATTR_COLD;
+ virtual void device_reset() override ATTR_COLD;
private:
uint8_t m_bank[16];
@@ -91,12 +106,12 @@ public:
md_rom_cm2in1_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
// reading and writing
- virtual DECLARE_READ16_MEMBER(read) override;
+ virtual uint16_t read(offs_t offset) override;
protected:
// device-level overrides
- virtual void device_start() override;
- virtual void device_reset() override;
+ virtual void device_start() override ATTR_COLD;
+ virtual void device_reset() override ATTR_COLD;
private:
int m_base;
@@ -112,13 +127,13 @@ public:
md_rom_mcpirate_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
// reading and writing
- virtual DECLARE_READ16_MEMBER(read) override;
- virtual DECLARE_WRITE16_MEMBER(write_a13) override;
+ virtual uint16_t read(offs_t offset) override;
+ virtual void write_a13(offs_t offset, uint16_t data) override;
protected:
// device-level overrides
- virtual void device_start() override;
- virtual void device_reset() override;
+ virtual void device_start() override ATTR_COLD;
+ virtual void device_reset() override ATTR_COLD;
private:
uint8_t m_bank;
@@ -134,7 +149,7 @@ public:
md_rom_bugslife_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
// reading and writing
- virtual DECLARE_READ16_MEMBER(read_a13) override;
+ virtual uint16_t read_a13(offs_t offset) override;
};
// ======================> md_rom_chinf3_device
@@ -146,13 +161,13 @@ public:
md_rom_chinf3_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
// reading and writing
- virtual DECLARE_READ16_MEMBER(read) override;
- virtual DECLARE_WRITE16_MEMBER(write) override;
+ virtual uint16_t read(offs_t offset) override;
+ virtual void write(offs_t offset, uint16_t data, uint16_t mem_mask = ~0) override;
protected:
// device-level overrides
- virtual void device_start() override;
- virtual void device_reset() override;
+ virtual void device_start() override ATTR_COLD;
+ virtual void device_reset() override ATTR_COLD;
private:
int m_bank;
@@ -167,7 +182,7 @@ public:
md_rom_16mj2_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
// reading and writing
- virtual DECLARE_READ16_MEMBER(read) override;
+ virtual uint16_t read(offs_t offset) override;
};
// ======================> md_rom_elfwor_device
@@ -179,7 +194,7 @@ public:
md_rom_elfwor_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
// reading and writing
- virtual DECLARE_READ16_MEMBER(read) override;
+ virtual uint16_t read(offs_t offset) override;
};
// ======================> md_rom_yasech_device
@@ -191,7 +206,7 @@ public:
md_rom_yasech_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
// reading and writing
- virtual DECLARE_READ16_MEMBER(read) override;
+ virtual uint16_t read(offs_t offset) override;
};
// ======================> md_rom_kof98_device
@@ -203,7 +218,7 @@ public:
md_rom_kof98_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
// reading and writing
- virtual DECLARE_READ16_MEMBER(read) override;
+ virtual uint16_t read(offs_t offset) override;
};
// ======================> md_rom_kof99_device
@@ -215,7 +230,7 @@ public:
md_rom_kof99_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
// reading and writing
- virtual DECLARE_READ16_MEMBER(read_a13) override;
+ virtual uint16_t read_a13(offs_t offset) override;
};
// ======================> md_rom_lion2_device
@@ -227,13 +242,13 @@ public:
md_rom_lion2_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
// reading and writing
- virtual DECLARE_READ16_MEMBER(read) override;
- virtual DECLARE_WRITE16_MEMBER(write) override;
+ virtual uint16_t read(offs_t offset) override;
+ virtual void write(offs_t offset, uint16_t data, uint16_t mem_mask = ~0) override;
protected:
// device-level overrides
- virtual void device_start() override;
- virtual void device_reset() override;
+ virtual void device_start() override ATTR_COLD;
+ virtual void device_reset() override ATTR_COLD;
private:
uint16_t m_prot1_data, m_prot2_data;
@@ -248,13 +263,13 @@ public:
md_rom_lion3_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
// reading and writing
- virtual DECLARE_READ16_MEMBER(read) override;
- virtual DECLARE_WRITE16_MEMBER(write) override;
+ virtual uint16_t read(offs_t offset) override;
+ virtual void write(offs_t offset, uint16_t data, uint16_t mem_mask = ~0) override;
protected:
// device-level overrides
- virtual void device_start() override;
- virtual void device_reset() override;
+ virtual void device_start() override ATTR_COLD;
+ virtual void device_reset() override ATTR_COLD;
private:
uint8_t m_reg[3];
@@ -270,7 +285,7 @@ public:
md_rom_mjlov_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
// reading and writing
- virtual DECLARE_READ16_MEMBER(read) override;
+ virtual uint16_t read(offs_t offset) override;
};
// ======================> md_rom_cjmjclub_device
@@ -282,7 +297,7 @@ public:
md_rom_cjmjclub_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
// reading and writing
- virtual DECLARE_READ16_MEMBER(read) override;
+ virtual uint16_t read(offs_t offset) override;
};
// ======================> md_rom_pokea_device
@@ -294,7 +309,7 @@ public:
md_rom_pokea_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
// reading and writing
- virtual DECLARE_READ16_MEMBER(read_a13) override;
+ virtual uint16_t read_a13(offs_t offset) override;
};
// ======================> md_rom_pokestad_device
@@ -306,13 +321,13 @@ public:
md_rom_pokestad_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
// reading and writing
- virtual DECLARE_READ16_MEMBER(read) override;
- virtual DECLARE_WRITE16_MEMBER(write) override;
+ virtual uint16_t read(offs_t offset) override;
+ virtual void write(offs_t offset, uint16_t data, uint16_t mem_mask = ~0) override;
protected:
// device-level overrides
- virtual void device_start() override;
- virtual void device_reset() override;
+ virtual void device_start() override ATTR_COLD;
+ virtual void device_reset() override ATTR_COLD;
private:
uint8_t m_bank;
@@ -327,13 +342,13 @@ public:
md_rom_realtec_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
// reading and writing
- virtual DECLARE_READ16_MEMBER(read) override;
- virtual DECLARE_WRITE16_MEMBER(write) override;
+ virtual uint16_t read(offs_t offset) override;
+ virtual void write(offs_t offset, uint16_t data, uint16_t mem_mask = ~0) override;
protected:
// device-level overrides
- virtual void device_start() override;
- virtual void device_reset() override;
+ virtual void device_start() override ATTR_COLD;
+ virtual void device_reset() override ATTR_COLD;
private:
uint16_t m_bank_addr, m_bank_size, m_old_bank_addr;
@@ -348,7 +363,7 @@ public:
md_rom_redcl_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
// reading and writing
- virtual DECLARE_READ16_MEMBER(read) override;
+ virtual uint16_t read(offs_t offset) override;
};
// ======================> md_rom_rx3_device
@@ -360,7 +375,7 @@ public:
md_rom_rx3_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
// reading and writing
- virtual DECLARE_READ16_MEMBER(read_a13) override;
+ virtual uint16_t read_a13(offs_t offset) override;
};
// ======================> md_rom_sbubl_device
@@ -372,7 +387,7 @@ public:
md_rom_sbubl_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
// reading and writing
- virtual DECLARE_READ16_MEMBER(read) override;
+ virtual uint16_t read(offs_t offset) override;
};
// ======================> md_rom_smb_device
@@ -384,7 +399,7 @@ public:
md_rom_smb_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
// reading and writing
- virtual DECLARE_READ16_MEMBER(read_a13) override;
+ virtual uint16_t read_a13(offs_t offset) override;
};
// ======================> md_rom_smb2_device
@@ -396,7 +411,7 @@ public:
md_rom_smb2_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
// reading and writing
- virtual DECLARE_READ16_MEMBER(read_a13) override;
+ virtual uint16_t read_a13(offs_t offset) override;
};
// ======================> md_rom_smw64_device
@@ -408,13 +423,13 @@ public:
md_rom_smw64_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
// reading and writing
- virtual DECLARE_READ16_MEMBER(read) override;
- virtual DECLARE_WRITE16_MEMBER(write) override;
+ virtual uint16_t read(offs_t offset) override;
+ virtual void write(offs_t offset, uint16_t data, uint16_t mem_mask = ~0) override;
protected:
// device-level overrides
- virtual void device_start() override;
- virtual void device_reset() override;
+ virtual void device_start() override ATTR_COLD;
+ virtual void device_reset() override ATTR_COLD;
private:
uint32_t m_latch0, m_latch1;
@@ -431,7 +446,7 @@ public:
md_rom_smouse_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
// reading and writing
- virtual DECLARE_READ16_MEMBER(read) override;
+ virtual uint16_t read(offs_t offset) override;
};
@@ -444,7 +459,7 @@ public:
md_rom_soulb_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
// reading and writing
- virtual DECLARE_READ16_MEMBER(read) override;
+ virtual uint16_t read(offs_t offset) override;
};
// ======================> md_rom_squir_device
@@ -456,18 +471,40 @@ public:
md_rom_squir_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
// reading and writing
- virtual DECLARE_READ16_MEMBER(read) override;
- virtual DECLARE_WRITE16_MEMBER(write) override;
+ virtual uint16_t read(offs_t offset) override;
+ virtual void write(offs_t offset, uint16_t data, uint16_t mem_mask = ~0) override;
protected:
// device-level overrides
- virtual void device_start() override;
- virtual void device_reset() override;
+ virtual void device_start() override ATTR_COLD;
+ virtual void device_reset() override ATTR_COLD;
private:
uint16_t m_latch;
};
+// ======================> md_rom_tc2000_device
+
+class md_rom_tc2000_device : public md_std_rom_device
+{
+public:
+ // construction/destruction
+ md_rom_tc2000_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
+
+ // 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;
+
+protected:
+ // device-level overrides
+ virtual void device_start() override ATTR_COLD;
+ virtual void device_reset() override ATTR_COLD;
+
+private:
+ uint16_t m_retvalue;
+};
+
+
// ======================> md_rom_tekkensp_device
class md_rom_tekkensp_device : public md_std_rom_device
@@ -477,13 +514,13 @@ public:
md_rom_tekkensp_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
// reading and writing
- virtual DECLARE_READ16_MEMBER(read) override;
- virtual DECLARE_WRITE16_MEMBER(write) override;
+ virtual uint16_t read(offs_t offset) override;
+ virtual void write(offs_t offset, uint16_t data, uint16_t mem_mask = ~0) override;
protected:
// device-level overrides
- virtual void device_start() override;
- virtual void device_reset() override;
+ virtual void device_start() override ATTR_COLD;
+ virtual void device_reset() override ATTR_COLD;
private:
uint16_t m_reg;
@@ -498,13 +535,13 @@ public:
md_rom_topf_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
// reading and writing
- virtual DECLARE_READ16_MEMBER(read) override;
- virtual DECLARE_WRITE16_MEMBER(write) override;
+ virtual uint16_t read(offs_t offset) override;
+ virtual void write(offs_t offset, uint16_t data, uint16_t mem_mask = ~0) override;
protected:
// device-level overrides
- virtual void device_start() override;
- virtual void device_reset() override;
+ virtual void device_start() override ATTR_COLD;
+ virtual void device_reset() override ATTR_COLD;
private:
uint16_t m_latch;
@@ -520,13 +557,13 @@ public:
md_rom_radica_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
// reading and writing
- virtual DECLARE_READ16_MEMBER(read) override;
- virtual DECLARE_READ16_MEMBER(read_a13) override;
+ virtual uint16_t read(offs_t offset) override;
+ virtual uint16_t read_a13(offs_t offset) override;
protected:
// device-level overrides
- virtual void device_start() override;
- virtual void device_reset() override;
+ virtual void device_start() override ATTR_COLD;
+ virtual void device_reset() override ATTR_COLD;
private:
uint8_t m_bank;
@@ -541,14 +578,14 @@ public:
md_rom_beggarp_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
// reading and writing
- virtual DECLARE_READ16_MEMBER(read) override;
- virtual DECLARE_WRITE16_MEMBER(write) override;
- virtual DECLARE_WRITE16_MEMBER(write_a13) override;
+ virtual uint16_t read(offs_t offset) override;
+ virtual void write(offs_t offset, uint16_t data, uint16_t mem_mask = ~0) override;
+ virtual void write_a13(offs_t offset, uint16_t data) override;
protected:
// device-level overrides
- virtual void device_start() override;
- virtual void device_reset() override;
+ virtual void device_start() override ATTR_COLD;
+ virtual void device_reset() override ATTR_COLD;
private:
uint8_t m_mode, m_lock;
@@ -563,14 +600,14 @@ public:
md_rom_wukong_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
// reading and writing
- virtual DECLARE_READ16_MEMBER(read) override;
- virtual DECLARE_WRITE16_MEMBER(write) override;
- virtual DECLARE_WRITE16_MEMBER(write_a13) override;
+ virtual uint16_t read(offs_t offset) override;
+ virtual void write(offs_t offset, uint16_t data, uint16_t mem_mask = ~0) override;
+ virtual void write_a13(offs_t offset, uint16_t data) override;
protected:
// device-level overrides
- virtual void device_start() override;
- virtual void device_reset() override;
+ virtual void device_start() override ATTR_COLD;
+ virtual void device_reset() override ATTR_COLD;
private:
uint8_t m_mode;
@@ -585,15 +622,15 @@ public:
md_rom_starodys_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
// reading and writing
- virtual DECLARE_READ16_MEMBER(read) override;
- virtual DECLARE_WRITE16_MEMBER(write) override;
- virtual DECLARE_READ16_MEMBER(read_a13) override;
- virtual DECLARE_WRITE16_MEMBER(write_a13) override;
+ virtual uint16_t read(offs_t offset) override;
+ virtual void write(offs_t offset, uint16_t data, uint16_t mem_mask = ~0) override;
+ virtual uint16_t read_a13(offs_t offset) override;
+ virtual void write_a13(offs_t offset, uint16_t data) override;
protected:
// device-level overrides
- virtual void device_start() override;
- virtual void device_reset() override;
+ virtual void device_start() override ATTR_COLD;
+ virtual void device_reset() override ATTR_COLD;
private:
uint8_t m_mode, m_lock, m_ram_enable, m_base;
@@ -631,6 +668,8 @@ DECLARE_DEVICE_TYPE(MD_ROM_POKESTAD, md_rom_pokestad_device)
DECLARE_DEVICE_TYPE(MD_ROM_REALTEC, md_rom_realtec_device)
DECLARE_DEVICE_TYPE(MD_ROM_REDCL, md_rom_redcl_device)
DECLARE_DEVICE_TYPE(MD_ROM_SQUIR, md_rom_squir_device)
+DECLARE_DEVICE_TYPE(MD_ROM_SRAM_ARG96, md_rom_sram_arg96_device)
+DECLARE_DEVICE_TYPE(MD_ROM_TC2000, md_rom_tc2000_device)
DECLARE_DEVICE_TYPE(MD_ROM_TEKKENSP, md_rom_tekkensp_device)
DECLARE_DEVICE_TYPE(MD_ROM_TOPF, md_rom_topf_device)
DECLARE_DEVICE_TYPE(MD_ROM_RADICA, md_rom_radica_device)
diff --git a/src/devices/bus/megadrive/sk.cpp b/src/devices/bus/megadrive/sk.cpp
index c45574ff1a3..5e0a970c320 100644
--- a/src/devices/bus/megadrive/sk.cpp
+++ b/src/devices/bus/megadrive/sk.cpp
@@ -5,19 +5,15 @@
Sonic & Knuckles pass-thorugh cart emulation
-
- TODO: currently we only support loading of base carts with no bankswitch or protection...
- shall we support other as well?
+ TODO: This could potentially make use of memory views. Investigate.
***********************************************************************************************************/
-
-
-
#include "emu.h"
#include "sk.h"
#include "rom.h"
+#include "md_carts.h"
//-------------------------------------------------
@@ -31,6 +27,7 @@ md_rom_sk_device::md_rom_sk_device(const machine_config &mconfig, device_type ty
: device_t(mconfig, type, tag, owner, clock)
, device_md_cart_interface(mconfig, *this)
, m_exp(*this, "subslot")
+ , m_map_upper(false)
{
}
@@ -42,36 +39,69 @@ md_rom_sk_device::md_rom_sk_device(const machine_config &mconfig, const char *ta
void md_rom_sk_device::device_start()
{
+ save_item(NAME(m_map_upper));
}
+
+void md_rom_sk_device::device_reset()
+{
+ m_map_upper = false;
+}
+
+
/*-------------------------------------------------
mapper specific handlers
-------------------------------------------------*/
-READ16_MEMBER(md_rom_sk_device::read)
+uint16_t md_rom_sk_device::read(offs_t offset)
{
- if (m_exp->m_cart != nullptr && m_exp->m_cart->get_rom_base() != nullptr && offset >= 0x200000/2 && offset < (0x200000 + m_exp->m_cart->get_rom_size())/2)
- return m_exp->m_cart->m_rom[offset - 0x200000/2];
+ if (m_map_upper)
+ {
+ if (offset >= 0x300000/2)
+ return m_rom[MD_ADDR(offset)]; // Sonic 2 patch ROM
+ else if (m_exp->m_cart != nullptr && m_exp->m_cart->get_rom_base() != nullptr && offset >= 0x200000/2)
+ return m_exp->m_cart->read(offset); // Sonic 3 ROM pass-through or FRAM
+ }
+
+ if (m_exp->m_cart != nullptr && m_exp->m_cart->get_rom_base() != nullptr && offset >= 0x200000/2)
+ return m_exp->m_cart->read(offset - 0x200000/2);
+
if (offset < 0x400000/2)
return m_rom[MD_ADDR(offset)];
else
return 0xffff;
}
-WRITE16_MEMBER(md_rom_sk_device::write)
+void md_rom_sk_device::write(offs_t offset, uint16_t data, uint16_t mem_mask)
+{
+ if (m_exp->m_cart == nullptr || m_exp->m_cart->get_rom_base() == nullptr)
+ return;
+
+ if (m_map_upper)
+ m_exp->m_cart->write(offset, data, mem_mask);
+ else if (offset >= 0x200000/2)
+ m_exp->m_cart->write(offset - 0x200000/2, data, mem_mask);
+}
+
+uint16_t md_rom_sk_device::read_a13(offs_t offset)
{
-// should there be anything here?
+ if (m_exp->m_cart != nullptr && m_exp->m_cart->get_rom_base() != nullptr)
+ return m_exp->m_cart->read_a13(offset);
+ return 0xffff;
}
+void md_rom_sk_device::write_a13(offs_t offset, uint16_t data)
+{
+ if (m_exp->m_cart != nullptr && m_exp->m_cart->get_rom_base() != nullptr)
+ m_exp->m_cart->write_a13(offset, data);
+ if (offset == 0xf0/2)
+ m_map_upper = BIT(data, 0);
+}
static void sk_sub_cart(device_slot_interface &device)
{
- device.option_add_internal("rom", MD_STD_ROM);
- device.option_add_internal("rom_svp", MD_STD_ROM);
- device.option_add_internal("rom_sram", MD_ROM_SRAM);
- device.option_add_internal("rom_sramsafe", MD_ROM_SRAM);
- device.option_add_internal("rom_fram", MD_ROM_FRAM);
-// add all types??
+ // Inherit all cartridge types; cartridges <= 2 megabytes in size are mirrored into the upper 2 megabytes by the Sonic & Knuckles cartridge.
+ md_cart(device);
}
diff --git a/src/devices/bus/megadrive/sk.h b/src/devices/bus/megadrive/sk.h
index 2e115f7674c..5f56c6c00a7 100644
--- a/src/devices/bus/megadrive/sk.h
+++ b/src/devices/bus/megadrive/sk.h
@@ -20,17 +20,21 @@ public:
protected:
md_rom_sk_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_start() override ATTR_COLD;
+ virtual void device_reset() override ATTR_COLD;
// device-level overrides
- virtual void device_add_mconfig(machine_config &config) override;
+ virtual void device_add_mconfig(machine_config &config) override ATTR_COLD;
// reading and writing
- virtual DECLARE_READ16_MEMBER(read) override;
- virtual DECLARE_WRITE16_MEMBER(write) override;
+ virtual uint16_t read(offs_t offset) override;
+ virtual void write(offs_t offset, uint16_t data, uint16_t mem_mask = ~0) override;
+ virtual uint16_t read_a13(offs_t offset) override;
+ virtual void write_a13(offs_t offset, uint16_t data) override;
private:
required_device<md_cart_slot_device> m_exp;
+ bool m_map_upper;
};
diff --git a/src/devices/bus/megadrive/stm95.cpp b/src/devices/bus/megadrive/stm95.cpp
index 4f536766b01..e3fca0bbffe 100644
--- a/src/devices/bus/megadrive/stm95.cpp
+++ b/src/devices/bus/megadrive/stm95.cpp
@@ -209,7 +209,7 @@ void md_eeprom_stm95_device::device_reset()
mapper specific handlers
-------------------------------------------------*/
-READ16_MEMBER(md_eeprom_stm95_device::read)
+uint16_t md_eeprom_stm95_device::read(offs_t offset)
{
if (offset == 0x0015e6/2 || offset == 0x0015e8/2)
{
@@ -236,7 +236,7 @@ READ16_MEMBER(md_eeprom_stm95_device::read)
}
}
-READ16_MEMBER(md_eeprom_stm95_device::read_a13)
+uint16_t md_eeprom_stm95_device::read_a13(offs_t offset)
{
if (offset == 0x0a/2)
{
@@ -245,7 +245,7 @@ READ16_MEMBER(md_eeprom_stm95_device::read_a13)
return 0xffff;
}
-WRITE16_MEMBER(md_eeprom_stm95_device::write_a13)
+void md_eeprom_stm95_device::write_a13(offs_t offset, uint16_t data)
{
if (offset == 0x00/2)
{
diff --git a/src/devices/bus/megadrive/stm95.h b/src/devices/bus/megadrive/stm95.h
index c1291e1f12f..fd944bb13f8 100644
--- a/src/devices/bus/megadrive/stm95.h
+++ b/src/devices/bus/megadrive/stm95.h
@@ -64,16 +64,16 @@ public:
md_eeprom_stm95_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
// reading and writing
- virtual DECLARE_READ16_MEMBER(read) override;
- virtual DECLARE_READ16_MEMBER(read_a13) override;
- virtual DECLARE_WRITE16_MEMBER(write_a13) override;
+ virtual uint16_t read(offs_t offset) override;
+ virtual uint16_t read_a13(offs_t offset) override;
+ virtual void write_a13(offs_t offset, uint16_t data) override;
protected:
md_eeprom_stm95_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_start() override ATTR_COLD;
+ virtual void device_reset() override ATTR_COLD;
private:
uint8_t m_bank[3];
diff --git a/src/devices/bus/megadrive/svp.cpp b/src/devices/bus/megadrive/svp.cpp
index fe4ae33536e..7850f9d3a80 100644
--- a/src/devices/bus/megadrive/svp.cpp
+++ b/src/devices/bus/megadrive/svp.cpp
@@ -23,8 +23,30 @@
* Depending on GPO bits in status register, PM0, PM1, PM2 and XST can act as
* external status registers, os as programmable memory registers. PM4 always
* acts as PM register (independent on GPO bits).
+ *
+ * TODO: internal ROM has been dumped but isn't used yet
*/
+/*
+ * Regarding `svp.bin`:
+ *
+ * There's an internal ROM inside the SVP chip which it's accessible by the DSP's
+ * "internal view" (i.e.: not using the external registers) from 0xFC00 to 0xFFFF
+ * (in word space, byte space addresses would be 0x1F800 - 0x1FFFE).
+ *
+ * Most of what's in that ROM (dumped as `svp.bin`) are routines not used by
+ * Virtua Racing. But part of it is actually used by the game:
+ *
+ * - Reset int. vector at 0xFFFC/0x1FFF8, specifying 0xFC08 as the entry point address.
+ * - Boot-up process: register initialization, checks for "security" string in ROM header
+ * and reading game entry point address (from 0x1C8 to 0x1CF in ROM - byte addresses).
+ *
+ * At some point it might be interesting to emulate this behavior, reading the reset
+ * interrupt vector handler address in the internal ROM, and letting the boot-up process
+ * to do its thing. This would also allow for the SVP emulation to be always active
+ * (as ROMs that don't contain the "security string" lead the SVP to enter an infinite
+ * loop to avoid bus clashes, etc...) now that SVP homebrew is "a thing".
+*/
#include "emu.h"
#include "svp.h"
@@ -50,6 +72,16 @@ md_rom_svp_device::md_rom_svp_device(const machine_config &mconfig, const char *
{
}
+ROM_START( svp )
+ ROM_REGION(0x800, "internal_rom", 0)
+ ROM_LOAD("svp.bin", 0x000, 0x800, CRC(2421ec7e) SHA1(0b951ea9c6094b3c34e4f0b64d031c75c237564f))
+ROM_END
+
+tiny_rom_entry const *md_rom_svp_device::device_rom_region() const
+{
+ return ROM_NAME(svp);
+}
+
#define SSP_PMC_HAVE_ADDR 1 // address written to PMAC, waiting for mode
#define SSP_PMC_SET 2 // PMAC is set, PMx can be programmed
@@ -170,7 +202,7 @@ uint32_t md_rom_svp_device::pm_io(int reg, int write, uint32_t d)
return (uint32_t)-1;
}
-READ16_MEMBER( md_rom_svp_device::read_pm0 )
+uint16_t md_rom_svp_device::read_pm0()
{
uint32_t d = pm_io(0, 0, 0);
if (d != (uint32_t)-1)
@@ -180,7 +212,7 @@ READ16_MEMBER( md_rom_svp_device::read_pm0 )
return d;
}
-WRITE16_MEMBER( md_rom_svp_device::write_pm0 )
+void md_rom_svp_device::write_pm0(uint16_t data)
{
uint32_t r = pm_io(0, 1, data);
if (r != (uint32_t)-1)
@@ -188,7 +220,7 @@ WRITE16_MEMBER( md_rom_svp_device::write_pm0 )
m_xst2 = data; // ?
}
-READ16_MEMBER( md_rom_svp_device::read_pm1 )
+uint16_t md_rom_svp_device::read_pm1()
{
uint32_t r = pm_io(1, 0, 0);
if (r != (uint32_t)-1)
@@ -197,7 +229,7 @@ READ16_MEMBER( md_rom_svp_device::read_pm1 )
return 0;
}
-WRITE16_MEMBER( md_rom_svp_device::write_pm1 )
+void md_rom_svp_device::write_pm1(uint16_t data)
{
uint32_t r = pm_io(1, 1, data);
if (r != (uint32_t)-1)
@@ -205,7 +237,7 @@ WRITE16_MEMBER( md_rom_svp_device::write_pm1 )
logerror("svp: PM1 acces in non PM mode?\n");
}
-READ16_MEMBER( md_rom_svp_device::read_pm2 )
+uint16_t md_rom_svp_device::read_pm2()
{
uint32_t r = pm_io(2, 0, 0);
if (r != (uint32_t)-1)
@@ -214,7 +246,7 @@ READ16_MEMBER( md_rom_svp_device::read_pm2 )
return 0;
}
-WRITE16_MEMBER( md_rom_svp_device::write_pm2 )
+void md_rom_svp_device::write_pm2(uint16_t data)
{
uint32_t r = pm_io(2, 1, data);
if (r != (uint32_t)-1)
@@ -222,7 +254,7 @@ WRITE16_MEMBER( md_rom_svp_device::write_pm2 )
logerror("svp: PM2 acces in non PM mode?\n");
}
-READ16_MEMBER( md_rom_svp_device::read_xst )
+uint16_t md_rom_svp_device::read_xst()
{
uint32_t d = pm_io(3, 0, 0);
if (d != (uint32_t)-1)
@@ -230,7 +262,7 @@ READ16_MEMBER( md_rom_svp_device::read_xst )
return m_xst;
}
-WRITE16_MEMBER( md_rom_svp_device::write_xst )
+void md_rom_svp_device::write_xst(uint16_t data)
{
uint32_t r = pm_io(3, 1, data);
if (r != (uint32_t)-1)
@@ -239,17 +271,17 @@ WRITE16_MEMBER( md_rom_svp_device::write_xst )
m_xst = data;
}
-READ16_MEMBER( md_rom_svp_device::read_pm4 )
+uint16_t md_rom_svp_device::read_pm4()
{
return pm_io(4, 0, 0);
}
-WRITE16_MEMBER( md_rom_svp_device::write_pm4 )
+void md_rom_svp_device::write_pm4(uint16_t data)
{
pm_io(4, 1, data);
}
-READ16_MEMBER( md_rom_svp_device::read_pmc )
+uint16_t md_rom_svp_device::read_pmc()
{
if (m_emu_status & SSP_PMC_HAVE_ADDR)
{
@@ -264,7 +296,7 @@ READ16_MEMBER( md_rom_svp_device::read_pmc )
}
}
-WRITE16_MEMBER( md_rom_svp_device::write_pmc )
+void md_rom_svp_device::write_pmc(uint16_t data)
{
if (m_emu_status & SSP_PMC_HAVE_ADDR)
{
@@ -279,24 +311,24 @@ WRITE16_MEMBER( md_rom_svp_device::write_pmc )
}
}
-READ16_MEMBER( md_rom_svp_device::read_al )
+uint16_t md_rom_svp_device::read_al()
{
m_emu_status &= ~(SSP_PMC_SET | SSP_PMC_HAVE_ADDR);
return 0;
}
-WRITE16_MEMBER( md_rom_svp_device::write_al )
+void md_rom_svp_device::write_al(uint16_t data)
{
}
-READ16_MEMBER( md_rom_svp_device::rom_read1 )
+uint16_t md_rom_svp_device::rom_read1(offs_t offset)
{
uint16_t *IRAM = (uint16_t *)m_iram;
return IRAM[offset];
}
-READ16_MEMBER( md_rom_svp_device::rom_read2 )
+uint16_t md_rom_svp_device::rom_read2(offs_t offset)
{
return m_rom[offset + 0x800/2];
}
@@ -320,8 +352,8 @@ INPUT_PORTS_END
void md_rom_svp_device::md_svp_ssp_map(address_map &map)
{
-// AM_RANGE(0x0000, 0x03ff) AM_READ(rom_read1)
-// AM_RANGE(0x0400, 0xffff) AM_READ(rom_read2)
+// map(0x0000, 0x03ff).r(FUNC(md_rom_svp_device::rom_read1));
+// map(0x0400, 0xffff).r(FUNC(md_rom_svp_device::rom_read2));
map(0x0000, 0x03ff).bankr("iram_svp");
map(0x0400, 0xffff).bankr("cart_svp");
}
@@ -369,8 +401,8 @@ void md_rom_svp_device::set_bank_to_rom(const char *banktag, uint32_t offset)
void md_rom_svp_device::device_start()
{
- memset(m_pmac_read, 0, ARRAY_LENGTH(m_pmac_read));
- memset(m_pmac_write, 0, ARRAY_LENGTH(m_pmac_write));
+ std::fill(std::begin(m_pmac_read), std::end(m_pmac_read), 0);
+ std::fill(std::begin(m_pmac_write), std::end(m_pmac_write), 0);
m_pmc.d = 0;
m_pmc.w.l = 0;
m_pmc.w.h = 0;
@@ -394,7 +426,7 @@ void md_rom_svp_device::device_start()
save_item(NAME(m_iram));
}
-READ16_MEMBER(md_rom_svp_device::read)
+uint16_t md_rom_svp_device::read(offs_t offset)
{
uint16_t *DRAM = (uint16_t *)m_dram;
@@ -425,7 +457,7 @@ READ16_MEMBER(md_rom_svp_device::read)
}
}
-WRITE16_MEMBER(md_rom_svp_device::write)
+void md_rom_svp_device::write(offs_t offset, uint16_t data, uint16_t mem_mask)
{
if (offset >= 0x300000/2 && offset < 0x320000/2)
{
@@ -435,7 +467,7 @@ WRITE16_MEMBER(md_rom_svp_device::write)
}
}
-READ16_MEMBER(md_rom_svp_device::read_a15)
+uint16_t md_rom_svp_device::read_a15(offs_t offset)
{
uint32_t d;
switch (offset)
@@ -450,7 +482,7 @@ READ16_MEMBER(md_rom_svp_device::read_a15)
return 0;
}
-WRITE16_MEMBER(md_rom_svp_device::write_a15)
+void md_rom_svp_device::write_a15(offs_t offset, uint16_t data)
{
switch (offset)
{
diff --git a/src/devices/bus/megadrive/svp.h b/src/devices/bus/megadrive/svp.h
index 40d7e9aab2c..ed562dfed68 100644
--- a/src/devices/bus/megadrive/svp.h
+++ b/src/devices/bus/megadrive/svp.h
@@ -22,38 +22,40 @@ public:
protected:
md_rom_svp_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_start() override ATTR_COLD;
// device-level overrides
- virtual void device_add_mconfig(machine_config &config) override;
- virtual ioport_constructor device_input_ports() const override;
+ virtual void device_add_mconfig(machine_config &config) override ATTR_COLD;
+ virtual ioport_constructor device_input_ports() const override ATTR_COLD;
+ virtual tiny_rom_entry const *device_rom_region() const override ATTR_COLD;
+
virtual void set_bank_to_rom(const char *banktag, uint32_t offset) override;
// reading and writing
- virtual DECLARE_READ16_MEMBER(read) override;
- virtual DECLARE_WRITE16_MEMBER(write) override;
- virtual DECLARE_READ16_MEMBER(read_a15) override;
- virtual DECLARE_WRITE16_MEMBER(write_a15) override;
+ virtual uint16_t read(offs_t offset) override;
+ virtual void write(offs_t offset, uint16_t data, uint16_t mem_mask = ~0) override;
+ virtual uint16_t read_a15(offs_t offset) override;
+ virtual void write_a15(offs_t offset, uint16_t data) override;
virtual int read_test() override;
- virtual DECLARE_READ16_MEMBER(rom_read1);
- virtual DECLARE_READ16_MEMBER(rom_read2);
-
- virtual DECLARE_READ16_MEMBER(read_pm0);
- virtual DECLARE_READ16_MEMBER(read_pm1);
- virtual DECLARE_READ16_MEMBER(read_pm2);
- virtual DECLARE_READ16_MEMBER(read_pm4);
- virtual DECLARE_READ16_MEMBER(read_xst);
- virtual DECLARE_READ16_MEMBER(read_pmc);
- virtual DECLARE_READ16_MEMBER(read_al);
- virtual DECLARE_WRITE16_MEMBER(write_pm0);
- virtual DECLARE_WRITE16_MEMBER(write_pm1);
- virtual DECLARE_WRITE16_MEMBER(write_pm2);
- virtual DECLARE_WRITE16_MEMBER(write_pm4);
- virtual DECLARE_WRITE16_MEMBER(write_xst);
- virtual DECLARE_WRITE16_MEMBER(write_pmc);
- virtual DECLARE_WRITE16_MEMBER(write_al);
+ virtual uint16_t rom_read1(offs_t offset);
+ virtual uint16_t rom_read2(offs_t offset);
+
+ virtual uint16_t read_pm0();
+ virtual uint16_t read_pm1();
+ virtual uint16_t read_pm2();
+ virtual uint16_t read_pm4();
+ virtual uint16_t read_xst();
+ virtual uint16_t read_pmc();
+ virtual uint16_t read_al();
+ virtual void write_pm0(uint16_t data);
+ virtual void write_pm1(uint16_t data);
+ virtual void write_pm2(uint16_t data);
+ virtual void write_pm4(uint16_t data);
+ virtual void write_xst(uint16_t data);
+ virtual void write_pmc(uint16_t data);
+ virtual void write_al(uint16_t data);
private:
required_device<cpu_device> m_svp;
@@ -70,8 +72,8 @@ private:
uint8_t m_iram[0x800]; // IRAM (0-0x7ff)
uint8_t m_dram[0x20000]; // [0x20000];
- void md_svp_ext_map(address_map &map);
- void md_svp_ssp_map(address_map &map);
+ void md_svp_ext_map(address_map &map) ATTR_COLD;
+ void md_svp_ssp_map(address_map &map) ATTR_COLD;
};
diff --git a/src/devices/bus/midi/midi.cpp b/src/devices/bus/midi/midi.cpp
index ca87636e6e6..4fb56b1e24f 100644
--- a/src/devices/bus/midi/midi.cpp
+++ b/src/devices/bus/midi/midi.cpp
@@ -5,9 +5,9 @@
DEFINE_DEVICE_TYPE(MIDI_PORT, midi_port_device, "midi_port", "MIDI port")
-midi_port_device::midi_port_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
- : device_t(mconfig, MIDI_PORT, tag, owner, clock),
- device_slot_interface(mconfig, *this),
+midi_port_device::midi_port_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) :
+ device_t(mconfig, MIDI_PORT, tag, owner, clock),
+ device_single_card_slot_interface<device_midi_port_interface>(mconfig, *this),
m_rxd(0),
m_rxd_handler(*this),
m_dev(nullptr)
@@ -20,22 +20,21 @@ midi_port_device::~midi_port_device()
void midi_port_device::device_config_complete()
{
- m_dev = dynamic_cast<device_midi_port_interface *>(get_card_device());
+ m_dev = get_card_device();
}
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);
}
-device_midi_port_interface::device_midi_port_interface(const machine_config &mconfig, device_t &device)
- : device_slot_card_interface(mconfig, device)
+device_midi_port_interface::device_midi_port_interface(const machine_config &mconfig, device_t &device) :
+ device_interface(device, "midi")
{
m_port = dynamic_cast<midi_port_device *>(device.owner());
}
diff --git a/src/devices/bus/midi/midi.h b/src/devices/bus/midi/midi.h
index 162d2d7545e..03673ce8a4d 100644
--- a/src/devices/bus/midi/midi.h
+++ b/src/devices/bus/midi/midi.h
@@ -8,8 +8,7 @@
class device_midi_port_interface;
-class midi_port_device : public device_t,
- public device_slot_interface
+class midi_port_device : public device_t, public device_single_card_slot_interface<device_midi_port_interface>
{
friend class device_midi_port_interface;
@@ -29,12 +28,12 @@ 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;
+ virtual void device_start() override ATTR_COLD;
virtual void device_config_complete() override;
void common(machine_config &config);
@@ -47,15 +46,15 @@ private:
device_midi_port_interface *m_dev;
};
-class device_midi_port_interface : public device_slot_card_interface
+class device_midi_port_interface : public device_interface
{
friend class midi_port_device;
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..c54396b925c 100644
--- a/src/devices/bus/midi/midiinport.h
+++ b/src/devices/bus/midi/midiinport.h
@@ -23,12 +23,12 @@ public:
midiin_port_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_add_mconfig(machine_config &config) override ATTR_COLD;
virtual void device_start() override { m_owner = dynamic_cast<midi_port_device *>(owner()); }
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..e0560c0e36c 100644
--- a/src/devices/bus/midi/midioutport.h
+++ b/src/devices/bus/midi/midioutport.h
@@ -22,12 +22,12 @@ 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 { }
virtual void device_reset() override { }
- virtual void device_add_mconfig(machine_config &config) override;
+ virtual void device_add_mconfig(machine_config &config) override ATTR_COLD;
private:
required_device<midiout_device> m_midiout;
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..7a0230e334c
--- /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 ATTR_COLD;
+ virtual void device_start() override ATTR_COLD;
+
+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/mpf1/epb.cpp b/src/devices/bus/mpf1/epb.cpp
new file mode 100644
index 00000000000..718f904965d
--- /dev/null
+++ b/src/devices/bus/mpf1/epb.cpp
@@ -0,0 +1,131 @@
+// license:BSD-3-Clause
+// copyright-holders:Nigel Barnes
+/***************************************************************************
+
+ Multitech Eprom Programmer Board
+
+ EPB-MPF :
+ MPF-1B : ADDR 9000 GO
+
+ EPB-MPF-IBP :
+ MPF-1P : G 9000
+ MPF-1B : ADDR 9800 GO
+
+***************************************************************************/
+
+#include "emu.h"
+#include "epb.h"
+#include "machine/i8255.h"
+
+
+namespace {
+
+//-------------------------------------------------
+// rom_region - device-specific ROM region
+//-------------------------------------------------
+
+ROM_START( mpf_epb )
+ ROM_REGION(0x0800, "rom", 0)
+ ROM_LOAD("epb-ib.u8", 0x0000, 0x0800, CRC(bbd854f5) SHA1(489e597c12a14a1cf9568d18b299e4f4ae656f71))
+ROM_END
+
+ROM_START( mpf_epb_ibp )
+ ROM_REGION(0x1000, "rom", 0)
+ ROM_LOAD("ebp-ibp.u8", 0x0000, 0x1000, CRC(0156387a) SHA1(296842ee5bac23f41f46534663d4f0bfc04075cf))
+ROM_END
+
+
+//-------------------------------------------------
+// mpf_epb_device - constructor
+//-------------------------------------------------
+
+class mpf_epb_device : public device_t, public device_mpf1_exp_interface
+{
+public:
+ static constexpr feature_type unemulated_features() { return feature::ROM; }
+
+ mpf_epb_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
+ : mpf_epb_device(mconfig, MPF_EPB, tag, owner, clock)
+ {
+ }
+
+protected:
+ mpf_epb_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_mpf1_exp_interface(mconfig, *this)
+ , m_rom(*this, "rom")
+ , m_ppi(*this, "ppi")
+ {
+ }
+
+ virtual void device_add_mconfig(machine_config &config) override
+ {
+ I8255(config, m_ppi);
+ }
+
+ virtual const tiny_rom_entry *device_rom_region() const override
+ {
+ return ROM_NAME( mpf_epb );
+ }
+
+ virtual void device_start() override
+ {
+ m_ram = make_unique_clear<uint8_t[]>(0x1000);
+
+ // register for save states
+ save_pointer(NAME(m_ram), 0x1000);
+ }
+
+ virtual void device_reset() override
+ {
+ program_space().install_ram(0x8000, 0x8fff, m_ram.get());
+ program_space().install_rom(0x9000, 0x97ff, m_rom->base());
+
+ io_space().install_readwrite_handler(0xcc, 0xcf, emu::rw_delegate(*m_ppi, FUNC(i8255_device::read)), emu::rw_delegate(*m_ppi, FUNC(i8255_device::write)));
+ }
+
+ required_memory_region m_rom;
+ required_device<i8255_device> m_ppi;
+
+ std::unique_ptr<uint8_t[]> m_ram;
+};
+
+
+// ======================> mpf_epb_ibp_device
+
+class mpf_epb_ibp_device : public mpf_epb_device
+{
+public:
+ mpf_epb_ibp_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
+ : mpf_epb_device(mconfig, MPF_EPB_IBP, tag, owner, clock)
+ {
+ }
+
+protected:
+ virtual const tiny_rom_entry *device_rom_region() const override
+ {
+ return ROM_NAME( mpf_epb_ibp );
+ }
+
+ virtual void device_start() override
+ {
+ m_ram = make_unique_clear<uint8_t[]>(0x1800);
+
+ // register for save states
+ save_pointer(NAME(m_ram), 0x1800);
+ }
+
+ virtual void device_reset() override
+ {
+ program_space().install_rom(0x9000, 0x9fff, m_rom->base());
+ program_space().install_ram(0xd800, 0xefff, m_ram.get());
+
+ io_space().install_readwrite_handler(0x70, 0x7f, emu::rw_delegate(*m_ppi, FUNC(i8255_device::read)), emu::rw_delegate(*m_ppi, FUNC(i8255_device::write)));
+ }
+};
+
+} // anonymous namespace
+
+
+DEFINE_DEVICE_TYPE_PRIVATE(MPF_EPB, device_mpf1_exp_interface, mpf_epb_device, "mpf1_epb", "Multitech EPB-MPF (Eprom Programmer Board)")
+DEFINE_DEVICE_TYPE_PRIVATE(MPF_EPB_IBP, device_mpf1_exp_interface, mpf_epb_ibp_device, "mpf1_epb_ibp", "Multitech EPB-MPF-IBP (Eprom Programmer Board)")
diff --git a/src/devices/bus/mpf1/epb.h b/src/devices/bus/mpf1/epb.h
new file mode 100644
index 00000000000..d52d52099e3
--- /dev/null
+++ b/src/devices/bus/mpf1/epb.h
@@ -0,0 +1,14 @@
+// license:BSD-3-Clause
+// copyright-holders:Nigel Barnes
+#ifndef MAME_BUS_MPF1_EPB_H
+#define MAME_BUS_MPF1_EPB_H
+
+#pragma once
+
+#include "slot.h"
+
+
+DECLARE_DEVICE_TYPE(MPF_EPB, device_mpf1_exp_interface)
+DECLARE_DEVICE_TYPE(MPF_EPB_IBP, device_mpf1_exp_interface)
+
+#endif // MAME_BUS_MPF1_EPB_H
diff --git a/src/devices/bus/mpf1/iom.cpp b/src/devices/bus/mpf1/iom.cpp
new file mode 100644
index 00000000000..e7b2df0213f
--- /dev/null
+++ b/src/devices/bus/mpf1/iom.cpp
@@ -0,0 +1,145 @@
+// license:BSD-3-Clause
+// copyright-holders:Nigel Barnes
+/***************************************************************************
+
+ Multitech I/O and Memory Board
+
+ PIO Application Example : G B000
+ CTC Application Example : G B100
+ 8251 Application Example : G B300
+
+***************************************************************************/
+
+#include "emu.h"
+#include "iom.h"
+#include "machine/i8251.h"
+#include "machine/z80ctc.h"
+#include "machine/z80pio.h"
+#include "bus/rs232/rs232.h"
+
+
+namespace {
+
+//-------------------------------------------------
+// rom_region - device-specific ROM region
+//-------------------------------------------------
+
+ROM_START(mpf_iom_ip)
+ ROM_REGION(0x1000, "rom", 0)
+ ROM_LOAD("ip-iom.bin", 0x0000, 0x1000, CRC(bf789c58) SHA1(2c3c26290e041e913d00d7e0d65d53480e27187c))
+ROM_END
+
+
+//-------------------------------------------------
+// input_ports - device-specific input ports
+//-------------------------------------------------
+
+static INPUT_PORTS_START(mpf_iom_ip)
+ PORT_START("DIPSW")
+ PORT_DIPNAME(0xf, 0xa, "Baud Rate")
+ PORT_DIPSETTING(0x0, "50")
+ PORT_DIPSETTING(0x1, "75")
+ PORT_DIPSETTING(0x2, "110")
+ PORT_DIPSETTING(0x3, "150")
+ PORT_DIPSETTING(0x4, "200")
+ PORT_DIPSETTING(0x5, "300")
+ PORT_DIPSETTING(0x6, "600")
+ PORT_DIPSETTING(0x7, "1200")
+ PORT_DIPSETTING(0x8, "2400")
+ PORT_DIPSETTING(0x9, "4800")
+ PORT_DIPSETTING(0xa, "9600")
+INPUT_PORTS_END
+
+
+static DEVICE_INPUT_DEFAULTS_START( terminal )
+ DEVICE_INPUT_DEFAULTS( "RS232_TXBAUD", 0xff, RS232_BAUD_9600 )
+ DEVICE_INPUT_DEFAULTS( "RS232_RXBAUD", 0xff, RS232_BAUD_9600 )
+ DEVICE_INPUT_DEFAULTS( "RS232_DATABITS", 0xff, RS232_DATABITS_7 )
+ DEVICE_INPUT_DEFAULTS( "RS232_PARITY", 0xff, RS232_PARITY_EVEN )
+ DEVICE_INPUT_DEFAULTS( "RS232_STOPBITS", 0xff, RS232_STOPBITS_1 )
+DEVICE_INPUT_DEFAULTS_END
+
+
+//-------------------------------------------------
+// mpf_iom_device - constructor
+//-------------------------------------------------
+
+class mpf_iom_device : public device_t, public device_mpf1_exp_interface
+{
+public:
+ mpf_iom_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
+ : device_t(mconfig, MPF_IOM_IP, tag, owner, clock)
+ , device_mpf1_exp_interface(mconfig, *this)
+ , m_rom(*this, "rom")
+ , m_ctc(*this, "ctc")
+ , m_pio(*this, "pio")
+ , m_usart(*this, "uart")
+ {
+ }
+
+protected:
+ virtual void device_add_mconfig(machine_config &config) override
+ {
+ Z80PIO(config, m_pio, DERIVED_CLOCK(1, 1));
+ m_pio->out_int_callback().set(DEVICE_SELF_OWNER, FUNC(mpf1_exp_device::int_w));
+
+ Z80CTC(config, m_ctc, DERIVED_CLOCK(1, 1));
+ m_ctc->set_clk<2>(DERIVED_CLOCK(1, 1));
+ m_ctc->zc_callback<2>().set(m_usart, FUNC(i8251_device::write_txc));
+ m_ctc->zc_callback<2>().append(m_usart, FUNC(i8251_device::write_rxc));
+ m_ctc->intr_callback().set(DEVICE_SELF_OWNER, FUNC(mpf1_exp_device::int_w));
+
+ I8251(config, m_usart, DERIVED_CLOCK(1, 1));
+ m_usart->rxrdy_handler().set(m_ctc, FUNC(z80ctc_device::trg3));
+ m_usart->txd_handler().set("rs232", FUNC(rs232_port_device::write_txd));
+ m_usart->dtr_handler().set("rs232", FUNC(rs232_port_device::write_dtr));
+ m_usart->rts_handler().set("rs232", FUNC(rs232_port_device::write_rts));
+
+ rs232_port_device &rs232(RS232_PORT(config, "rs232", default_rs232_devices, nullptr));
+ rs232.rxd_handler().set(m_usart, FUNC(i8251_device::write_rxd));
+ rs232.cts_handler().set(m_usart, FUNC(i8251_device::write_cts));
+ rs232.dsr_handler().set(m_usart, FUNC(i8251_device::write_dsr));
+ rs232.set_option_device_input_defaults("terminal", DEVICE_INPUT_DEFAULTS_NAME(terminal));
+ }
+
+ virtual const tiny_rom_entry *device_rom_region() const override
+ {
+ return ROM_NAME(mpf_iom_ip);
+ }
+
+ virtual ioport_constructor device_input_ports() const override
+ {
+ return INPUT_PORTS_NAME(mpf_iom_ip);
+ }
+
+ virtual void device_start() override
+ {
+ m_ram = make_unique_clear<uint8_t[]>(0x1800);
+
+ save_pointer(NAME(m_ram), 0x1800);
+ }
+
+ virtual void device_reset() override
+ {
+ program_space().install_rom(0xb000, 0xbfff, m_rom->base());
+ program_space().install_ram(0xd800, 0xefff, m_ram.get());
+
+ io_space().install_readwrite_handler(0x60, 0x61, emu::rw_delegate(*m_usart, FUNC(i8251_device::read)), emu::rw_delegate(*m_usart, FUNC(i8251_device::write)));
+ io_space().install_readwrite_handler(0x64, 0x67, emu::rw_delegate(*m_ctc, FUNC(z80ctc_device::read)), emu::rw_delegate(*m_ctc, FUNC(z80ctc_device::write)));
+ io_space().install_readwrite_handler(0x68, 0x6b, emu::rw_delegate(*m_pio, FUNC(z80pio_device::read)), emu::rw_delegate(*m_pio, FUNC(z80pio_device::write)));
+ io_space().install_read_port(0x6c, 0x6c, "DIPSW");
+ }
+
+private:
+ required_memory_region m_rom;
+ required_device<z80ctc_device> m_ctc;
+ required_device<z80pio_device> m_pio;
+ required_device<i8251_device> m_usart;
+
+ std::unique_ptr<uint8_t[]> m_ram;
+};
+
+} // anonymous namespace
+
+
+DEFINE_DEVICE_TYPE_PRIVATE(MPF_IOM_IP, device_mpf1_exp_interface, mpf_iom_device, "mpf1_iom_ip", "Multitech IOM-MPF-IP (I/O and Memory Board)")
diff --git a/src/devices/bus/mpf1/iom.h b/src/devices/bus/mpf1/iom.h
new file mode 100644
index 00000000000..02fb9ff496d
--- /dev/null
+++ b/src/devices/bus/mpf1/iom.h
@@ -0,0 +1,13 @@
+// license:BSD-3-Clause
+// copyright-holders:Nigel Barnes
+#ifndef MAME_BUS_MPF1_IOM_H
+#define MAME_BUS_MPF1_IOM_H
+
+#pragma once
+
+#include "slot.h"
+
+
+DECLARE_DEVICE_TYPE(MPF_IOM_IP, device_mpf1_exp_interface)
+
+#endif // MAME_BUS_MPF1_IOM_H
diff --git a/src/devices/bus/mpf1/prt.cpp b/src/devices/bus/mpf1/prt.cpp
new file mode 100644
index 00000000000..1962d2dcad9
--- /dev/null
+++ b/src/devices/bus/mpf1/prt.cpp
@@ -0,0 +1,138 @@
+// license:BSD-3-Clause
+// copyright-holders:Nigel Barnes
+/***************************************************************************
+
+ Multitech Printer
+
+ PRT-MPF :
+ Printer driver utility : ADDR 65AC GO
+ Z80-Disassembler listing utility : ADDR 6000 GO
+ Memory dump utility : ADDR 6300 GO
+ BASIC program listing utility : ADDR 6400 GO
+ Printer line feed : ADDR 6500 GO
+
+ PRT-MPF-IP : Address Mnemonic Function
+ 6A00 SHIFT Drive the thermal head shift right
+ 6A10 PLINEFD Line feed
+ 6A30 PLINE Drive the paper vertically by two lines
+ 6A40 MTPPRT Print out the contents of the line buffer
+
+***************************************************************************/
+
+#include "emu.h"
+#include "prt.h"
+#include "bus/generic/carts.h"
+#include "bus/generic/slot.h"
+
+
+namespace {
+
+//-------------------------------------------------
+// rom_region - device-specific ROM region
+//-------------------------------------------------
+
+ROM_START( mpf_prt )
+ ROM_REGION(0x1000, "u5", 0)
+ ROM_LOAD("prt-ib.u5", 0x0000, 0x1000, CRC(730f2fb0) SHA1(f31536ee9dbb9babb9ce16a7490db654ca0b5749))
+ROM_END
+
+ROM_START( mpf_prt_ip )
+ ROM_REGION(0x1000, "u5", 0)
+ ROM_LOAD("prt-ip_v1.1.u5", 0x0000, 0x1000, CRC(4dd2a4eb) SHA1(6a3e7daa7834d67fd572261ed4a9a62c4594fe3f))
+ROM_END
+
+
+//-------------------------------------------------
+// mpf_prt_device - constructor
+//-------------------------------------------------
+
+class mpf_prt_device : public device_t, public device_mpf1_exp_interface
+{
+public:
+ static constexpr feature_type unemulated_features() { return feature::PRINTER; }
+
+ mpf_prt_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
+ : mpf_prt_device(mconfig, MPF_PRT, tag, owner, clock)
+ {
+ }
+
+protected:
+ mpf_prt_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_mpf1_exp_interface(mconfig, *this)
+ , m_rom_u5(*this, "u5")
+ , m_rom_u6(*this, "u6")
+ {
+ }
+
+ virtual void device_add_mconfig(machine_config &config) override
+ {
+ // TODO: Seikosha MTP201A thermal printer
+
+ GENERIC_SOCKET(config, "u6", generic_linear_slot, nullptr, "bin,rom");
+ }
+
+ virtual const tiny_rom_entry *device_rom_region() const override
+ {
+ return ROM_NAME( mpf_prt );
+ }
+
+ virtual void device_start() override { }
+ virtual void device_reset() override
+ {
+ program_space().install_rom(0x6000, 0x6fff, m_rom_u5->base());
+ program_space().install_read_handler(0x7000, 0x7fff, emu::rw_delegate(*m_rom_u6, FUNC(generic_slot_device::read_rom)));
+
+ io_space().install_write_handler(0xca, 0xca, emu::rw_delegate(*this, FUNC(mpf_prt_device::prt_w)));
+ io_space().install_read_handler(0xcb, 0xcb, emu::rw_delegate(*this, FUNC(mpf_prt_device::prt_r)));
+ }
+
+private:
+ required_memory_region m_rom_u5;
+ required_device<generic_slot_device> m_rom_u6;
+
+ uint8_t prt_r()
+ {
+ uint8_t data = 0x00;
+
+ // bit 0 TGP
+ // bit 1 HP
+
+ return data;
+ }
+
+ void prt_w(uint8_t data)
+ {
+ // bit 0 TH7
+ // bit 1 TH6
+ // bit 2 TH5
+ // bit 3 TH4
+ // bit 4 TH3
+ // bit 5 TH2
+ // bit 6 TH1
+ // bit 7 MOTOR
+ }
+};
+
+
+class mpf_prt_ip_device : public mpf_prt_device
+{
+public:
+ mpf_prt_ip_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
+ : mpf_prt_device(mconfig, MPF_PRT_IP, tag, owner, clock)
+ {
+ }
+
+protected:
+ virtual const tiny_rom_entry *device_rom_region() const override
+ {
+ return ROM_NAME( mpf_prt_ip );
+ }
+
+};
+
+} // anonymous namespace
+
+
+DEFINE_DEVICE_TYPE_PRIVATE(MPF_PRT, device_mpf1_exp_interface, mpf_prt_device, "mpf1_prt", "Multitech PRT-MPF (Printer)")
+DEFINE_DEVICE_TYPE_PRIVATE(MPF_PRT_IP, device_mpf1_exp_interface, mpf_prt_ip_device, "mpf1_prt_ip", "Multitech PRT-MPF-IP (Printer)")
diff --git a/src/devices/bus/mpf1/prt.h b/src/devices/bus/mpf1/prt.h
new file mode 100644
index 00000000000..fb465fe356f
--- /dev/null
+++ b/src/devices/bus/mpf1/prt.h
@@ -0,0 +1,14 @@
+// license:BSD-3-Clause
+// copyright-holders:Nigel Barnes
+#ifndef MAME_BUS_MPF1_PRT_H
+#define MAME_BUS_MPF1_PRT_H
+
+#pragma once
+
+#include "slot.h"
+
+
+DECLARE_DEVICE_TYPE(MPF_PRT, device_mpf1_exp_interface)
+DECLARE_DEVICE_TYPE(MPF_PRT_IP, device_mpf1_exp_interface)
+
+#endif // MAME_BUS_MPF1_PRT_H
diff --git a/src/devices/bus/mpf1/sgb.cpp b/src/devices/bus/mpf1/sgb.cpp
new file mode 100644
index 00000000000..9866c05844d
--- /dev/null
+++ b/src/devices/bus/mpf1/sgb.cpp
@@ -0,0 +1,73 @@
+// license:BSD-3-Clause
+// copyright-holders:Nigel Barnes
+/***************************************************************************
+
+ Multitech Sound Generation Board
+
+ Piano : ADDR C200 GO
+
+***************************************************************************/
+
+#include "emu.h"
+#include "sgb.h"
+#include "sound/ay8910.h"
+#include "speaker.h"
+
+
+namespace {
+
+//-------------------------------------------------
+// rom_region - device-specific ROM region
+//-------------------------------------------------
+
+ROM_START( mpf_sgb )
+ ROM_REGION(0x1000, "rom", 0)
+ ROM_LOAD("sgb-mpf.bin", 0x0000, 0x1000, CRC(2d51d964) SHA1(13f3c7243d691b66ad5f0dcbbc16488c8905a394))
+ROM_END
+
+
+//-------------------------------------------------
+// mpf_sgb_device - constructor
+//-------------------------------------------------
+
+class mpf_sgb_device : public device_t, public device_mpf1_exp_interface
+{
+public:
+ mpf_sgb_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
+ : device_t(mconfig, MPF_SGB, tag, owner, clock)
+ , device_mpf1_exp_interface(mconfig, *this)
+ , m_rom(*this, "rom")
+ , m_ay(*this, "ay8910")
+ {
+ }
+
+protected:
+ virtual void device_add_mconfig(machine_config &config) override
+ {
+ SPEAKER(config, "mono").front_center();
+ AY8910(config, m_ay, DERIVED_CLOCK(1, 1)).add_route(ALL_OUTPUTS, "mono", 1.0);
+ }
+
+ virtual const tiny_rom_entry *device_rom_region() const override
+ {
+ return ROM_NAME( mpf_sgb );
+ }
+
+ virtual void device_start() override { }
+ virtual void device_reset() override
+ {
+ program_space().install_rom(0xc000, 0xcfff, m_rom->base());
+
+ io_space().install_read_handler(0xc1, 0xc1, emu::rw_delegate(*m_ay, FUNC(ay8910_device::data_r)));
+ io_space().install_write_handler(0xc2, 0xc3, emu::rw_delegate(*m_ay, FUNC(ay8910_device::data_address_w)));
+ }
+
+private:
+ required_memory_region m_rom;
+ required_device<ay8910_device> m_ay;
+};
+
+} // anonymous namespace
+
+
+DEFINE_DEVICE_TYPE_PRIVATE(MPF_SGB, device_mpf1_exp_interface, mpf_sgb_device, "mpf1_sgb", "Multitech SGB-MPF (Sound Generation Board)")
diff --git a/src/devices/bus/mpf1/sgb.h b/src/devices/bus/mpf1/sgb.h
new file mode 100644
index 00000000000..4ae172a62cf
--- /dev/null
+++ b/src/devices/bus/mpf1/sgb.h
@@ -0,0 +1,13 @@
+// license:BSD-3-Clause
+// copyright-holders:Nigel Barnes
+#ifndef MAME_BUS_MPF1_SGB_H
+#define MAME_BUS_MPF1_SGB_H
+
+#pragma once
+
+#include "slot.h"
+
+
+DECLARE_DEVICE_TYPE(MPF_SGB, device_mpf1_exp_interface)
+
+#endif // MAME_BUS_MPF1_SGB_H
diff --git a/src/devices/bus/mpf1/slot.cpp b/src/devices/bus/mpf1/slot.cpp
new file mode 100644
index 00000000000..d1470beb862
--- /dev/null
+++ b/src/devices/bus/mpf1/slot.cpp
@@ -0,0 +1,126 @@
+// license:BSD-3-Clause
+// copyright-holders:Nigel Barnes
+/***************************************************************************
+
+ Micro-Professor Expansion Slot
+
+***************************************************************************/
+
+#include "emu.h"
+#include "slot.h"
+
+// supported devices
+#include "epb.h"
+#include "iom.h"
+#include "prt.h"
+#include "sgb.h"
+#include "ssb.h"
+#include "tva.h"
+#include "vid.h"
+
+
+//**************************************************************************
+// DEVICE DEFINITIONS
+//**************************************************************************
+
+DEFINE_DEVICE_TYPE(MPF1_EXP, mpf1_exp_device, "mpf_exp", "Micro-Professor Expansion Slot")
+
+
+//**************************************************************************
+// SLOT DEVICE
+//**************************************************************************
+
+//-------------------------------------------------
+// mpf1_exp_device - constructor
+//-------------------------------------------------
+
+mpf1_exp_device::mpf1_exp_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
+ : device_t(mconfig, MPF1_EXP, tag, owner, clock)
+ , device_single_card_slot_interface<device_mpf1_exp_interface>(mconfig, *this)
+ , m_program(*this, finder_base::DUMMY_TAG, -1)
+ , m_io(*this, finder_base::DUMMY_TAG, -1)
+ , m_card(nullptr)
+ , m_int_handler(*this)
+ , m_nmi_handler(*this)
+ , m_wait_handler(*this)
+{
+}
+
+//-------------------------------------------------
+// device_config_complete - perform any
+// operations now that the configuration is
+// complete
+//-------------------------------------------------
+
+void mpf1_exp_device::device_config_complete()
+{
+ // for pass-through connectors, use the parent slot's spaces
+ if (dynamic_cast<device_mpf1_exp_interface *>(owner()) != nullptr)
+ {
+ auto parent = dynamic_cast<mpf1_exp_device *>(owner()->owner());
+ if (parent != nullptr)
+ {
+ if (m_program.finder_tag() == finder_base::DUMMY_TAG)
+ m_program.set_tag(parent->m_program, parent->m_program.spacenum());
+ if (m_io.finder_tag() == finder_base::DUMMY_TAG)
+ m_io.set_tag(parent->m_io, parent->m_io.spacenum());
+ }
+ }
+}
+
+//-------------------------------------------------
+// device_start - device-specific startup
+//-------------------------------------------------
+
+void mpf1_exp_device::device_start()
+{
+ m_card = get_card_device();
+}
+
+
+//**************************************************************************
+// CARD INTERFACE
+//**************************************************************************
+
+//-------------------------------------------------
+// device_mpf1_exp_interface - constructor
+//-------------------------------------------------
+
+device_mpf1_exp_interface::device_mpf1_exp_interface(const machine_config &mconfig, device_t &device)
+ : device_interface(device, "mpf1exp")
+ , m_slot(dynamic_cast<mpf1_exp_device *>(device.owner()))
+{
+}
+
+
+//**************************************************************************
+// SLOT INTERFACE
+//**************************************************************************
+
+void mpf1_exp_devices(device_slot_interface &device)
+{
+ device.option_add("epb", MPF_EPB);
+ device.option_add("epb_ibp", MPF_EPB_IBP);
+ device.option_add("prt", MPF_PRT);
+ device.option_add("sgb", MPF_SGB);
+ device.option_add("ssb", MPF_SSB);
+ //device.option_add("vid", MPF_VID);
+}
+
+void mpf1p_exp_devices(device_slot_interface &device)
+{
+ device.option_add("epb_ibp", MPF_EPB_IBP);
+ //device.option_add("epb_ip", MPF_EPB_IP);
+ device.option_add("iom_ip", MPF_IOM_IP);
+ device.option_add("prt_ip", MPF_PRT_IP);
+ //device.option_add("sgb_ip", MPF_SGB_IP);
+ //device.option_add("ssb_ip", MPF_SSB_IP);
+ device.option_add("tva", MPF_TVA_IP);
+ device.option_add("vid", MPF_VID);
+}
+
+void mpf1_88_exp_devices(device_slot_interface &device)
+{
+ //device.option_add("epb_i88", MPF_EPB_I88);
+ //device.option_add("prt_i88", MPF_PRT_I88);
+}
diff --git a/src/devices/bus/mpf1/slot.h b/src/devices/bus/mpf1/slot.h
new file mode 100644
index 00000000000..28e6cc08ff4
--- /dev/null
+++ b/src/devices/bus/mpf1/slot.h
@@ -0,0 +1,122 @@
+// license:BSD-3-Clause
+// copyright-holders:Nigel Barnes
+/***************************************************************************
+
+ Micro-Professor Expansion Slot
+
+ 60-pin slot
+
+ +5V 1 2 D7
+ +5V 3 4 D6
+ GND 5 6 D5
+ GND 7 8 D4
+ GND 9 10 D3
+ GND 11 12 D2
+ GND 13 14 D1
+ GND 15 16 D0
+ GND 17 18 A15
+ A14 19 20 A13
+ A12 21 22 A11
+ A10 23 24 A9
+ A8 25 26 A7
+ A6 27 28 A5
+ A4 29 30 A3
+ A2 31 32 A1
+ A0 33 34 /RESET
+ GND 35 36 /RFSH
+ GND 37 38 /M1
+ GND 39 40 /BUSACK
+ GND 41 42 /WR
+ GND 43 44 /RD
+ GND 45 46 /IORQ
+ GND 47 48 /MREQ
+ GND 49 50 /HALT
+ GND 51 52 /NMI
+ GND 53 54 /INT
+ GND 55 56 /WAIT
+ GND 57 58 /BUSREQ
+ GND 59 60 SYSCLK
+
+***************************************************************************/
+
+#ifndef MAME_BUS_MPF1_SLOT_H
+#define MAME_BUS_MPF1_SLOT_H
+
+#pragma once
+
+
+//**************************************************************************
+// TYPE DEFINITIONS
+//**************************************************************************
+
+class device_mpf1_exp_interface;
+
+class mpf1_exp_device : public device_t, public device_single_card_slot_interface<device_mpf1_exp_interface>
+{
+ friend class device_mpf1_exp_interface;
+public:
+ // construction/destruction
+ template <typename T>
+ mpf1_exp_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock, T &&opts, const char *dflt)
+ : mpf1_exp_device(mconfig, tag, owner, clock)
+ {
+ option_reset();
+ opts(*this);
+ set_default_option(dflt);
+ set_fixed(false);
+ }
+
+ mpf1_exp_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
+
+ 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(); }
+ auto wait_handler() { return m_wait_handler.bind(); }
+
+ // called from card device
+ void int_w(int state) { m_int_handler(state); }
+ void nmi_w(int state) { m_nmi_handler(state); }
+ void wait_w(int state) { m_wait_handler(state); }
+
+protected:
+ // device-level overrides
+ virtual void device_config_complete() override;
+ virtual void device_start() override ATTR_COLD;
+
+ required_address_space m_program;
+ required_address_space m_io;
+
+ device_mpf1_exp_interface *m_card;
+
+private:
+ devcb_write_line m_int_handler;
+ devcb_write_line m_nmi_handler;
+ devcb_write_line m_wait_handler;
+};
+
+
+class device_mpf1_exp_interface : public device_interface
+{
+public:
+ // construction/destruction
+ device_mpf1_exp_interface(const machine_config &mconfig, device_t &device);
+
+protected:
+ address_space &program_space() { return *m_slot->m_program; }
+ address_space &io_space() { return *m_slot->m_io; }
+
+ mpf1_exp_device *m_slot;
+};
+
+// device type definition
+DECLARE_DEVICE_TYPE(MPF1_EXP, mpf1_exp_device)
+
+// supported devices
+void mpf1_exp_devices(device_slot_interface &device);
+void mpf1p_exp_devices(device_slot_interface &device);
+void mpf1_88_exp_devices(device_slot_interface &device);
+
+#endif // MAME_BUS_MPF1_SLOT_H
diff --git a/src/devices/bus/mpf1/ssb.cpp b/src/devices/bus/mpf1/ssb.cpp
new file mode 100644
index 00000000000..ef3188e6f64
--- /dev/null
+++ b/src/devices/bus/mpf1/ssb.cpp
@@ -0,0 +1,92 @@
+// license:BSD-3-Clause
+// copyright-holders:Nigel Barnes
+/***************************************************************************
+
+ Multitech Speech Synthesizer Board
+
+ PROG 1 : Time-clock program ADDR 5000 GO
+ CHECK-CODE : Self-test, speak all vocabulary ADDR 51DC GO
+ PROG 2 : Speech program utility ADDR 5200 GO
+
+ TODO: improve VSP READY callback to Z80 WAIT, currently VSP FIFO overflows.
+
+***************************************************************************/
+
+#include "emu.h"
+#include "ssb.h"
+#include "sound/tms5220.h"
+#include "bus/generic/carts.h"
+#include "bus/generic/slot.h"
+#include "speaker.h"
+
+
+namespace {
+
+//-------------------------------------------------
+// rom_region - device-specific ROM region
+//-------------------------------------------------
+
+ROM_START( mpf_ssb )
+ ROM_REGION(0x1000, "u5", 0)
+ ROM_LOAD("ssb-mpf.bin", 0x0000, 0x1000, CRC(f926334f) SHA1(35847f8164eed4c0794a8b74e5d7fa972b10eb90))
+ROM_END
+
+
+//-------------------------------------------------
+// mpf_ssb_device - constructor
+//-------------------------------------------------
+
+class mpf_ssb_device : public device_t, public device_mpf1_exp_interface
+{
+public:
+ static constexpr feature_type imperfect_features() { return feature::SOUND; }
+
+ mpf_ssb_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
+ : device_t(mconfig, MPF_SSB, tag, owner, clock)
+ , device_mpf1_exp_interface(mconfig, *this)
+ , m_rom_u5(*this, "u5")
+ , m_rom_u4(*this, "u4")
+ , m_rom_u3(*this, "u3")
+ , m_vsp(*this, "vsp")
+ {
+ }
+
+protected:
+ virtual void device_add_mconfig(machine_config &config) override
+ {
+ SPEAKER(config, "mono").front_center();
+
+ TMS5200(config, m_vsp, 640000);
+ m_vsp->ready_cb().set(DEVICE_SELF_OWNER, FUNC(mpf1_exp_device::wait_w));
+ m_vsp->add_route(ALL_OUTPUTS, "mono", 0.5);
+
+ GENERIC_SOCKET(config, "u4", generic_linear_slot, nullptr, "bin,rom");
+ GENERIC_SOCKET(config, "u3", generic_linear_slot, nullptr, "bin,rom");
+ }
+
+ virtual const tiny_rom_entry *device_rom_region() const override
+ {
+ return ROM_NAME( mpf_ssb );
+ }
+
+ virtual void device_start() override { }
+ virtual void device_reset() override
+ {
+ program_space().install_rom(0x5000, 0x5fff, m_rom_u5->base());
+ program_space().install_read_handler(0x6000, 0x6fff, emu::rw_delegate(*m_rom_u4, FUNC(generic_slot_device::read_rom)));
+ program_space().install_read_handler(0x7000, 0x7fff, emu::rw_delegate(*m_rom_u3, FUNC(generic_slot_device::read_rom)));
+
+ io_space().install_readwrite_handler(0xfe, 0xfe, emu::rw_delegate(*m_vsp, FUNC(tms5200_device::status_r)), emu::rw_delegate(*m_vsp, FUNC(tms5200_device::data_w)));
+ }
+
+private:
+ required_memory_region m_rom_u5;
+ required_device<generic_slot_device> m_rom_u4;
+ required_device<generic_slot_device> m_rom_u3;
+ required_device<tms5200_device> m_vsp;
+};
+
+} // anonymous namespace
+
+
+DEFINE_DEVICE_TYPE_PRIVATE(MPF_SSB, device_mpf1_exp_interface, mpf_ssb_device, "mpf1_ssb", "Multitech SSB-MPF (Speech Synthesizer Board)")
diff --git a/src/devices/bus/mpf1/ssb.h b/src/devices/bus/mpf1/ssb.h
new file mode 100644
index 00000000000..00a618f842a
--- /dev/null
+++ b/src/devices/bus/mpf1/ssb.h
@@ -0,0 +1,13 @@
+// license:BSD-3-Clause
+// copyright-holders:Nigel Barnes
+#ifndef MAME_BUS_MPF1_SSB_H
+#define MAME_BUS_MPF1_SSB_H
+
+#pragma once
+
+#include "slot.h"
+
+
+DECLARE_DEVICE_TYPE(MPF_SSB, device_mpf1_exp_interface)
+
+#endif // MAME_BUS_MPF1_SSB_H
diff --git a/src/devices/bus/mpf1/tva.cpp b/src/devices/bus/mpf1/tva.cpp
new file mode 100644
index 00000000000..206ff6cea6f
--- /dev/null
+++ b/src/devices/bus/mpf1/tva.cpp
@@ -0,0 +1,85 @@
+// license:BSD-3-Clause
+// copyright-holders:Nigel Barnes
+/***************************************************************************
+
+ Multitech TVA-MPF-IP
+
+ TODO:
+ - no known documentation so emulation not verified.
+
+***************************************************************************/
+
+#include "emu.h"
+#include "tva.h"
+#include "screen.h"
+#include "video/ef9365.h"
+
+
+namespace {
+
+//-------------------------------------------------
+// rom_region - device-specific ROM region
+//-------------------------------------------------
+
+ROM_START( mpf_tva )
+ ROM_REGION(0x1000, "rom", 0)
+ ROM_LOAD("tva.bin", 0x0000, 0x1000, CRC(a9d4f261) SHA1(3a5b0dba5d1e2edda8563b55010c86efd1548d0b))
+ROM_END
+
+
+//-------------------------------------------------
+// mpf_tva_ip_device - constructor
+//-------------------------------------------------
+
+class mpf_tva_ip_device : public device_t, public device_mpf1_exp_interface
+{
+public:
+ static constexpr feature_type imperfect_features() { return feature::GRAPHICS; }
+
+ mpf_tva_ip_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
+ : device_t(mconfig, MPF_TVA_IP, tag, owner, clock)
+ , device_mpf1_exp_interface(mconfig, *this)
+ , m_rom(*this, "rom")
+ , m_gdp(*this, "ef9367")
+ {
+ }
+
+protected:
+ virtual void device_add_mconfig(machine_config &config) override
+ {
+ screen_device &screen(SCREEN(config, "screen", SCREEN_TYPE_RASTER));
+ screen.set_size(512, 312);
+ screen.set_visarea(0, 512 - 1, 0, 256 - 1);
+ screen.set_refresh_hz(50);
+ screen.set_screen_update("ef9367", FUNC(ef9365_device::screen_update));
+ PALETTE(config, "palette", palette_device::MONOCHROME);
+
+ EF9365(config, m_gdp, 1750000); // EF9367
+ m_gdp->set_screen("screen");
+ m_gdp->set_palette_tag("palette");
+ m_gdp->set_nb_bitplanes(1);
+ m_gdp->set_display_mode(ef9365_device::DISPLAY_MODE_512x256);
+ m_gdp->irq_handler().set(DEVICE_SELF_OWNER, FUNC(mpf1_exp_device::int_w));
+ }
+
+ virtual const tiny_rom_entry *device_rom_region() const override
+ {
+ return ROM_NAME( mpf_tva );
+ }
+
+ virtual void device_start() override { }
+ virtual void device_reset() override
+ {
+ program_space().install_rom(0xa000, 0xafff, m_rom->base());
+ program_space().install_readwrite_handler(0xafe0, 0xafef, emu::rw_delegate(*m_gdp, FUNC(ef9365_device::data_r)), emu::rw_delegate(*m_gdp, FUNC(ef9365_device::data_w)));
+ }
+
+private:
+ required_memory_region m_rom;
+ required_device<ef9365_device> m_gdp;
+};
+
+} // anonymous namespace
+
+
+DEFINE_DEVICE_TYPE_PRIVATE(MPF_TVA_IP, device_mpf1_exp_interface, mpf_tva_ip_device, "mpf1_tva_ip", "Multitech TVA-MPF-IP (Video Board)")
diff --git a/src/devices/bus/mpf1/tva.h b/src/devices/bus/mpf1/tva.h
new file mode 100644
index 00000000000..9810d876923
--- /dev/null
+++ b/src/devices/bus/mpf1/tva.h
@@ -0,0 +1,13 @@
+// license:BSD-3-Clause
+// copyright-holders:Nigel Barnes
+#ifndef MAME_BUS_MPF1_TVA_H
+#define MAME_BUS_MPF1_TVA_H
+
+#pragma once
+
+#include "slot.h"
+
+
+DECLARE_DEVICE_TYPE(MPF_TVA_IP, device_mpf1_exp_interface)
+
+#endif // MAME_BUS_MPF1_TVA_H
diff --git a/src/devices/bus/mpf1/vid.cpp b/src/devices/bus/mpf1/vid.cpp
new file mode 100644
index 00000000000..4ef0634a51c
--- /dev/null
+++ b/src/devices/bus/mpf1/vid.cpp
@@ -0,0 +1,158 @@
+// license:BSD-3-Clause
+// copyright-holders:Nigel Barnes
+/***************************************************************************
+
+ Bardehle Electronics VIDEO-MPF-I
+
+***************************************************************************/
+
+#include "emu.h"
+#include "vid.h"
+#include "video/mc6845.h"
+#include "emupal.h"
+#include "screen.h"
+
+
+namespace {
+
+//-------------------------------------------------
+// rom_region - device-specific ROM region
+//-------------------------------------------------
+
+ROM_START( mpf_vid )
+ ROM_REGION(0x0800, "rom", 0)
+ ROM_SYSTEM_BIOS(0, "20", "2.0")
+ ROMX_LOAD("vidmon_v20.bin", 0x0000, 0x0800, CRC(3a2293a0) SHA1(281092d82a272383b584b31064421296add20c46), ROM_BIOS(0))
+
+ ROM_REGION(0x0800, "chargen", 0)
+ ROM_LOAD("vidchar.bin", 0x0000, 0x0800, CRC(d56211f9) SHA1(9cf717de353b86c38f94b805d31a16d8079896af))
+ROM_END
+
+
+//-------------------------------------------------
+// gfx_layout mpf_vid_charlayout
+//-------------------------------------------------
+
+static const gfx_layout mpf_vid_charlayout =
+{
+ 8, 12, /* 8 x 12 characters */
+ 128, /* 128 characters */
+ 1, /* 1 bits per pixel */
+ { 0 }, /* no bitplanes */
+ /* x offsets */
+ { 0, 1, 2, 3, 4, 5, 6, 7 },
+ /* 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 */
+};
+
+//-------------------------------------------------
+// GFXDECODE( gfx_mpf_vid )
+//-------------------------------------------------
+
+static GFXDECODE_START(gfx_mpf_vid)
+ GFXDECODE_ENTRY("chargen", 0, mpf_vid_charlayout, 0, 1)
+GFXDECODE_END
+
+
+//-------------------------------------------------
+// mpf_vid_device - constructor
+//-------------------------------------------------
+
+class mpf_vid_device : public device_t, public device_mpf1_exp_interface
+{
+public:
+ static constexpr feature_type imperfect_features() { return feature::GRAPHICS; }
+
+ mpf_vid_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
+ : device_t(mconfig, MPF_VID, tag, owner, clock)
+ , device_mpf1_exp_interface(mconfig, *this)
+ , m_rom(*this, "rom")
+ , m_chargen(*this, "chargen")
+ , m_crtc(*this, "mc6845")
+ , m_palette(*this, "palette")
+ {
+ }
+
+protected:
+ virtual void device_add_mconfig(machine_config &config) override
+ {
+ screen_device &screen(SCREEN(config, "screen", SCREEN_TYPE_RASTER));
+ screen.set_raw(8_MHz_XTAL, 512, 0, 320, 326, 0, 240);
+ screen.set_screen_update("mc6845", FUNC(mc6845_device::screen_update));
+
+ GFXDECODE(config, "gfxdecode", m_palette, gfx_mpf_vid);
+ PALETTE(config, m_palette, palette_device::MONOCHROME);
+
+ MC6845(config, m_crtc, 8_MHz_XTAL / 8); // UM6845
+ m_crtc->set_screen("screen");
+ m_crtc->set_show_border_area(false);
+ m_crtc->set_char_width(8);
+ m_crtc->set_update_row_callback(FUNC(mpf_vid_device::crtc_update_row));
+ }
+
+ virtual const tiny_rom_entry *device_rom_region() const override
+ {
+ return ROM_NAME( mpf_vid );
+ }
+
+ virtual void device_start() override
+ {
+ m_videoram = make_unique_clear<uint8_t[]>(0x0800);
+
+ save_pointer(NAME(m_videoram), 0x0800);
+ }
+
+ virtual void device_reset() override
+ {
+ program_space().install_ram(0x4000, 0x47ff, 0x800, m_videoram.get());
+ program_space().install_rom(0xa000, 0xa7ff, m_rom->base());
+
+ io_space().nop_read(0xf0, 0xf0); // TODO: UM6845 Status Register (b7 must be high)
+ io_space().install_write_handler(0xf0, 0xf0, emu::rw_delegate(*m_crtc, FUNC(mc6845_device::address_w)));
+ io_space().install_readwrite_handler(0xf1, 0xf1, emu::rw_delegate(*m_crtc, FUNC(mc6845_device::register_r)), emu::rw_delegate(*m_crtc, FUNC(mc6845_device::register_w)));
+ }
+
+private:
+ required_memory_region m_rom;
+ required_memory_region m_chargen;
+ required_device<mc6845_device> m_crtc;
+ required_device<palette_device> m_palette;
+
+ MC6845_UPDATE_ROW(crtc_update_row);
+
+ std::unique_ptr<uint8_t[]> m_videoram;
+};
+
+
+//**************************************************************************
+// IMPLEMENTATION
+//**************************************************************************
+
+MC6845_UPDATE_ROW(mpf_vid_device::crtc_update_row)
+{
+ uint32_t *p = &bitmap.pix(y);
+
+ for (int column = 0; column < x_count; column++)
+ {
+ uint8_t code = m_videoram[(ma + column) & 0x7ff];
+ uint16_t addr = (code << 4) | (ra & 0x0f);
+ uint8_t data = m_chargen->base()[addr & 0x7ff];
+
+ if (column == cursor_x)
+ {
+ data = 0xff;
+ }
+
+ for (int bit = 0; bit < 8; bit++)
+ {
+ *p++ = m_palette->pen(BIT(code, 7) ? !BIT(data, 7) : BIT(data, 7));
+ data <<= 1;
+ }
+ }
+}
+
+} // anonymous namespace
+
+
+DEFINE_DEVICE_TYPE_PRIVATE(MPF_VID, device_mpf1_exp_interface, mpf_vid_device, "mpf1_vid", "Bardehle VIDEO-MPF-I (Video Board)")
diff --git a/src/devices/bus/mpf1/vid.h b/src/devices/bus/mpf1/vid.h
new file mode 100644
index 00000000000..83573004514
--- /dev/null
+++ b/src/devices/bus/mpf1/vid.h
@@ -0,0 +1,13 @@
+// license:BSD-3-Clause
+// copyright-holders:Nigel Barnes
+#ifndef MAME_BUS_MPF1_VID_H
+#define MAME_BUS_MPF1_VID_H
+
+#pragma once
+
+#include "slot.h"
+
+
+DECLARE_DEVICE_TYPE(MPF_VID, device_mpf1_exp_interface)
+
+#endif // MAME_BUS_MPF1_VID_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..89508f853a9
--- /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 ATTR_COLD;
+ virtual void device_reset() override ATTR_COLD;
+
+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..9beb17197fc
--- /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 ATTR_COLD;
+
+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 ATTR_COLD;
+
+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 ATTR_COLD;
+
+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 ATTR_COLD;
+
+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..1681ea92aea
--- /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 ATTR_COLD;
+ virtual void device_start() override { }
+ virtual void device_add_mconfig(machine_config &config) override ATTR_COLD;
+ 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 158de522e4d..a035f9bee2a 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 ATTR_COLD;
+ virtual void device_add_mconfig(machine_config &config) override ATTR_COLD;
+ virtual const tiny_rom_entry *device_rom_region() const override ATTR_COLD;
-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) ATTR_COLD;
+
+ 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(FUNC(z80pio_device::write_alt), m_bm012_pio.target()));
- io_space().install_read_handler(0x70, 0x73, read8sm_delegate(FUNC(z80pio_device::read_alt), m_bm012_pio.target()));
+ 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..f452bd45ac2
--- /dev/null
+++ b/src/devices/bus/msx/cart/cartridge.cpp
@@ -0,0 +1,247 @@
+// 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 "franky.h"
+#include "fs_sr021.h"
+#include "fs_sr022.h"
+#include "halnote.h"
+#include "hbi55.h"
+#include "hfox.h"
+#include "holy_quran.h"
+#include "ide.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 "video80.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_internal(slotoptions::VIDEO80, MSX_CART_VIDEO80);
+ device.option_add(slotoptions::BEEPACK, MSX_CART_BEEPACK);
+ device.option_add(slotoptions::BM_012, MSX_CART_BM_012);
+ device.option_add(slotoptions::FRANKY, MSX_CART_FRANKY);
+ 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::SUNRISE_ATAIDE, MSX_CART_SUNRISE_ATAIDE);
+ 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..50cdbc3b74d
--- /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 ATTR_COLD;
+ 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 ATTR_COLD;
+ 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 ATTR_COLD;
+ 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 ATTR_COLD;
+ virtual void device_start() override ATTR_COLD;
+ 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 ATTR_COLD;
+ virtual void device_start() override ATTR_COLD;
+ 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 ATTR_COLD;
+ virtual void device_start() override ATTR_COLD;
+ 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 ATTR_COLD;
+ virtual void device_start() override ATTR_COLD;
+ 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..d034ba8a891
--- /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 ATTR_COLD;
+
+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..ff753a39e9d
--- /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 ATTR_COLD;
+ virtual const tiny_rom_entry *device_rom_region() const override ATTR_COLD;
+
+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..ddb959e04bb
--- /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_EASI_SPEECH_H
+#define MAME_BUS_MSX_CART_EASI_SPEECH_H
+
+#pragma once
+
+#include "bus/msx/slot/cartridge.h"
+
+
+DECLARE_DEVICE_TYPE(MSX_CART_EASISPEECH, msx_cart_interface)
+
+#endif // MAME_BUS_MSX_CART_EASI_SPEECH_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..ae5d67825c2
--- /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 ATTR_COLD;
+ virtual void device_reset() override ATTR_COLD;
+
+ // device_t implementation
+ virtual void device_add_mconfig(machine_config &config) override ATTR_COLD;
+
+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/franky.cpp b/src/devices/bus/msx/cart/franky.cpp
new file mode 100644
index 00000000000..525bebafda4
--- /dev/null
+++ b/src/devices/bus/msx/cart/franky.cpp
@@ -0,0 +1,86 @@
+// license:BSD-3-Clause
+// copyright-holders:Wilbert Pol
+/**********************************************************************************
+
+Emulation of SuperSoniqs' Franky cartridge, the predecessor of SuperSoniqs'
+PlaySonic cartridge.
+
+**********************************************************************************/
+
+#include "emu.h"
+#include "franky.h"
+
+#include "video/315_5124.h"
+
+#include "speaker.h"
+
+namespace {
+
+class msx_cart_franky_device : public device_t, public msx_cart_interface
+{
+public:
+ msx_cart_franky_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock)
+ : device_t(mconfig, MSX_CART_FRANKY, tag, owner, clock)
+ , msx_cart_interface(mconfig, *this)
+ , m_vdp(*this, "vdp")
+ , m_screen(*this, "screen")
+ { }
+
+protected:
+ virtual void device_start() override ATTR_COLD;
+
+ // device_t implementation
+ virtual void device_add_mconfig(machine_config &config) override ATTR_COLD;
+
+private:
+ uint32_t screen_update(screen_device &screen, bitmap_rgb32 &bitmap, const rectangle &cliprect);
+
+ required_device<sega315_5124_device> m_vdp;
+ required_device<screen_device> m_screen;
+};
+
+
+void msx_cart_franky_device::device_add_mconfig(machine_config &config)
+{
+ SPEAKER(config, "franky").front_center();
+
+ SCREEN(config, m_screen, SCREEN_TYPE_RASTER);
+
+ m_screen->set_raw(XTAL(10'738'635)/2,
+ sega315_5124_device::WIDTH,
+ sega315_5124_device::LBORDER_START + sega315_5124_device::LBORDER_WIDTH - 2,
+ sega315_5124_device::LBORDER_START + sega315_5124_device::LBORDER_WIDTH + 256 + 10,
+ sega315_5124_device::HEIGHT_NTSC,
+ sega315_5124_device::TBORDER_START + sega315_5124_device::NTSC_224_TBORDER_HEIGHT,
+ sega315_5124_device::TBORDER_START + sega315_5124_device::NTSC_224_TBORDER_HEIGHT + 224);
+ m_screen->set_refresh_hz(XTAL(10'738'635)/2 / (sega315_5124_device::WIDTH * sega315_5124_device::HEIGHT_NTSC));
+ m_screen->set_screen_update(FUNC(msx_cart_franky_device::screen_update));
+
+ SEGA315_5246(config, m_vdp, XTAL(10'738'635));
+ m_vdp->set_screen(m_screen);
+ m_vdp->set_is_pal(false);
+ m_vdp->n_int().set(*this, FUNC(msx_cart_franky_device::irq_out));
+ // There is no NMI signal on the cartridge slot, so no way to hook this up
+ //m_vdp->n_nmi().set_inputline(maincpu, INPUT_LINE_NMI);
+ m_vdp->add_route(ALL_OUTPUTS, "franky", 1.00);
+}
+
+
+void msx_cart_franky_device::device_start()
+{
+ io_space().install_write_handler(0x48, 0x49, emu::rw_delegate(*m_vdp, FUNC(sega315_5124_device::psg_w)));
+ io_space().install_read_handler(0x48, 0x48, emu::rw_delegate(*m_vdp, FUNC(sega315_5124_device::vcount_read)));
+ io_space().install_read_handler(0x49, 0x49, emu::rw_delegate(*m_vdp, FUNC(sega315_5124_device::hcount_read)));
+ io_space().install_readwrite_handler(0x88, 0x88, emu::rw_delegate(*m_vdp, FUNC(sega315_5124_device::data_read)), emu::rw_delegate(*m_vdp, FUNC(sega315_5124_device::data_write)));
+ io_space().install_readwrite_handler(0x89, 0x89, emu::rw_delegate(*m_vdp, FUNC(sega315_5124_device::control_read)), emu::rw_delegate(*m_vdp, FUNC(sega315_5124_device::control_write)));
+}
+
+
+uint32_t msx_cart_franky_device::screen_update(screen_device &screen, bitmap_rgb32 &bitmap, const rectangle &cliprect)
+{
+ return m_vdp->screen_update(screen, bitmap, cliprect);
+}
+
+} // anonymous namespace
+
+DEFINE_DEVICE_TYPE_PRIVATE(MSX_CART_FRANKY, msx_cart_interface, msx_cart_franky_device, "msx_cart_franky", "MSX Cartridge - Franky")
diff --git a/src/devices/bus/msx/cart/franky.h b/src/devices/bus/msx/cart/franky.h
new file mode 100644
index 00000000000..ea30405a4da
--- /dev/null
+++ b/src/devices/bus/msx/cart/franky.h
@@ -0,0 +1,13 @@
+// license:BSD-3-Clause
+// copyright-holders:Wilbert Pol
+#ifndef MAME_BUS_MSX_CART_FRANKY_H
+#define MAME_BUS_MSX_CART_FRANKY_H
+
+#pragma once
+
+#include "bus/msx/slot/cartridge.h"
+
+
+DECLARE_DEVICE_TYPE(MSX_CART_FRANKY, msx_cart_interface)
+
+#endif // MAME_BUS_MSX_CART_FRANKY_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..016b8cd1993
--- /dev/null
+++ b/src/devices/bus/msx/cart/fs_sr021.cpp
@@ -0,0 +1,191 @@
+// 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 ATTR_COLD;
+ virtual void device_reset() override ATTR_COLD;
+
+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)));
+
+ io_space().install_write_tap(0xd8, 0xd9, "kanji_w", [this] (offs_t ofs, u8 &data, u8) { this->kanji_w(ofs, data); });
+ io_space().install_read_tap(0xd9, 0xd9, "kanji_r", [this] (offs_t ofs, u8 &data, u8) { data &= this->kanji_r(ofs); });
+
+ 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 (BIT(offset, 0))
+ 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..2bce81db442
--- /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 ATTR_COLD;
+ virtual void device_reset() override ATTR_COLD;
+
+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..ffe6d883b16
--- /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 ATTR_COLD;
+
+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..22ee16d92f9
--- /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 ATTR_COLD;
+ virtual void device_start() override ATTR_COLD;
+ virtual void device_reset() override ATTR_COLD;
+ 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..7963df4cdbc
--- /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 ATTR_COLD;
+
+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..b04edb3a6b0
--- /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 ATTR_COLD;
+
+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/ide.cpp b/src/devices/bus/msx/cart/ide.cpp
new file mode 100644
index 00000000000..8aafb248dba
--- /dev/null
+++ b/src/devices/bus/msx/cart/ide.cpp
@@ -0,0 +1,199 @@
+// license:BSD-3-Clause
+// copyright-holders:Wilbert Pol
+/******************************************************************************
+
+Sunrise ATA-IDE and CF ATA-IDE cartridges.
+
+The difference between these two interface cartridges is in the connectors. The
+ATA-IDE cartridge has a connector for an IDE cable. The CF ATA-IDE cartridge
+has 2 slots for CF cards. The rest of the hardware and firmware on these
+cartridges is the same.
+
+******************************************************************************/
+#include "emu.h"
+#include "ide.h"
+
+#include "bus/ata/ataintf.h"
+#include "bus/ata/hdd.h"
+#include "machine/intelfsh.h"
+
+
+namespace
+{
+
+class msx_cart_sunrise_ataide_device : public device_t, public msx_cart_interface
+{
+public:
+ msx_cart_sunrise_ataide_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock)
+ : device_t(mconfig, MSX_CART_SUNRISE_ATAIDE, tag, owner, clock)
+ , msx_cart_interface(mconfig, *this)
+ , m_flash(*this, "flash")
+ , m_ata(*this, "ata")
+ , m_view(*this, "view")
+ , m_activity_led(*this, "activity_led")
+ , m_control(0)
+ , m_data(0)
+ { }
+
+protected:
+ 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;
+ virtual const tiny_rom_entry *device_rom_region() const override ATTR_COLD;
+
+private:
+ required_device<amd_29f010_device> m_flash;
+ required_device<ata_interface_device> m_ata;
+ memory_view m_view;
+ output_finder<> m_activity_led;
+ u8 m_control;
+ u32 m_bank_base;
+ u16 m_data;
+};
+
+
+void msx_cart_sunrise_ataide_device::device_add_mconfig(machine_config &config)
+{
+ AMD_29F010(config, m_flash);
+
+ ATA_INTERFACE(config, m_ata).options(ata_devices, "hdd", nullptr, false);
+ m_ata->dasp_handler().set_output("activity_led");
+}
+
+
+ROM_START(sunrise_ataide)
+ ROM_REGION(0x20000, "flash", ROMREGION_ERASEFF)
+ // These are not dumped from a real unit but the result of flashing the firmware.
+ // Since the full flash contents are written, the contents are expected to be the same.
+ ROM_DEFAULT_BIOS("v2.50")
+ ROM_SYSTEM_BIOS(0, "v2.50", "v2.50 - 29.01.2013")
+ ROMX_LOAD("v2.50.u3", 0, 0x20000, CRC(1944bca9) SHA1(b4bd26c0caee3bdb4e2e2dd1ca6e5ed1e9a7d57e), ROM_BIOS(0))
+
+ ROM_SYSTEM_BIOS(1, "v2.40", "v2.40 - 23.03.2005")
+ ROMX_LOAD("v2.40.u3", 0, 0x20000, CRC(c73f525b) SHA1(b43e709d62ce4c88072eec4369b4910e89b3fe7b), ROM_BIOS(1))
+
+ // Reverse-patched from a patched variant
+ ROM_SYSTEM_BIOS(2, "v2.21", "v2.21 - 26.03.2003")
+ ROMX_LOAD("v2.21.u3", 0, 0x20000, BAD_DUMP CRC(fb99f89b) SHA1(a650f51310c2a02c893993e683b54850c278d60b), ROM_BIOS(2))
+
+ ROM_SYSTEM_BIOS(3, "v2.10", "v2.10 - 14.06.2002")
+ ROMX_LOAD("v2.10.u3", 0, 0x20000, NO_DUMP, ROM_BIOS(3))
+
+ // Reverse-patched from a patched variant
+ ROM_SYSTEM_BIOS(4, "v2.01", "v2.01 - 18.09.2000")
+ ROMX_LOAD("v2.01.u3", 0, 0x20000, BAD_DUMP CRC(7fd06ee2) SHA1(bced64ee970e0d66be2634914e4aa58530202f7e), ROM_BIOS(4))
+
+ ROM_SYSTEM_BIOS(5, "v1.99", "v1.99 - 27.02.2000")
+ ROMX_LOAD("v1.99.u3", 0, 0x20000, NO_DUMP, ROM_BIOS(5))
+
+ ROM_SYSTEM_BIOS(6, "v1.97", "v1.97 - 20.10.1999")
+ ROMX_LOAD("v1.97.u3", 0, 0x20000, NO_DUMP, ROM_BIOS(6))
+
+ ROM_SYSTEM_BIOS(7, "v1.96", "v1.96 - 22.09.1999")
+ ROMX_LOAD("v1.96.u3", 0, 0x20000, NO_DUMP, ROM_BIOS(7))
+
+ ROM_REGION(0x1000, "gals", ROMREGION_ERASE00)
+ ROM_LOAD("gal16v8d.gal1.jed.u1", 0x0000, 1452, CRC(db625e66) SHA1(5e0718066eea14b89d3801e5464b9a3db41baa2e))
+ ROM_LOAD("gal16v8d.gal2.jed.u2", 0x0800, 1494, CRC(22e34ff1) SHA1(cbeb5830ee740747aa61ef5b896e2eb6d7acd7ab))
+ROM_END
+
+
+const tiny_rom_entry *msx_cart_sunrise_ataide_device::device_rom_region() const
+{
+ return ROM_NAME(sunrise_ataide);
+}
+
+
+void msx_cart_sunrise_ataide_device::device_start()
+{
+ m_activity_led.resolve();
+
+ save_item(NAME(m_control));
+ save_item(NAME(m_bank_base));
+ save_item(NAME(m_data));
+
+ page(1)->install_read_handler(0x4000, 0x7fff, read8sm_delegate(*this, [this] (offs_t offset)
+ {
+ u8 data = m_flash->read(m_bank_base | offset);
+ return bitswap(data, 0, 1, 2, 3, 4, 5, 6, 7);
+ }, "read")
+ );
+ page(1)->install_write_handler(0x4104, 0x4104, write8smo_delegate(*this, [this] (u8 data)
+ {
+ m_control = data;
+ m_bank_base = bitswap(m_control, 5, 6, 7) * 0x4000;
+ m_view.select(BIT(m_control, 0));
+ }, "control")
+ );
+ page(1)->install_view(0x7c00, 0x7e0f, m_view);
+ m_view[0];
+ m_view[1].install_read_handler(0x7c00, 0x7dff, read8sm_delegate(*this, [this] (offs_t offset)
+ {
+ if (!machine().side_effects_disabled())
+ {
+ if (!BIT(offset, 0))
+ {
+ m_ata->write_dmack(1);
+ m_data = m_ata->read_dma();
+ m_ata->write_dmack(0);
+ return m_data & 0xff;
+ }
+ }
+ return m_data >> 8;
+ }, "read_ide_data")
+ );
+ m_view[1].install_write_handler(0x7c00, 0x7dff, write8sm_delegate(*this, [this] (offs_t offset, u8 data)
+ {
+ if (BIT(offset, 0))
+ {
+ m_data = (m_data & 0x00ff) | (data << 8);
+ m_ata->write_dmack(1);
+ m_ata->write_dma(m_data);
+ m_ata->write_dmack(0);
+ }
+ else
+ {
+ m_data = (m_data & 0xff00) | data;
+ }
+ }, "write_ide_data")
+ );
+ m_view[1].install_write_handler(0x7e00, 0x7e0f, write8sm_delegate(*this, [this] (offs_t offset, u8 data)
+ {
+ if (BIT(offset, 3))
+ m_ata->cs1_w(offset & 0x07, data, 0xff);
+ else
+ m_ata->cs0_w(offset & 0x07, data, 0xff);
+ }, "write_ide")
+ );
+ m_view[1].install_read_handler(0x7e00, 0x7e0f, read8sm_delegate(*this, [this] (offs_t offset)
+ {
+ if (BIT(offset, 3))
+ return m_ata->cs1_r(offset & 0x07, 0xff);
+ else
+ return m_ata->cs0_r(offset & 0x07, 0xff);
+ }, "read_ide")
+ );
+
+ page(2)->install_write_handler(0x8000, 0xbfff, write8sm_delegate(*this, [this] (offs_t offset, u8 data)
+ {
+ data = bitswap(data, 0, 1, 2, 3, 4, 5, 6, 7);
+ m_flash->write(m_bank_base | (offset & 0x3fff), data);
+ }, "write_flash")
+ );
+}
+
+
+void msx_cart_sunrise_ataide_device::device_reset()
+{
+ m_control = 0;
+ m_bank_base = 0;
+ m_data = 0;
+ m_view.select(0);
+ m_activity_led = 0;
+ // Pulling high breaks status reads
+ //m_ata->write_dmack(1);
+}
+
+} // anonymous namespace
+
+DEFINE_DEVICE_TYPE_PRIVATE(MSX_CART_SUNRISE_ATAIDE, msx_cart_interface, msx_cart_sunrise_ataide_device, "msx_cart_sunrise_ataide", "Sunrise ATA-IDE/CF ATA-IDE Interface")
diff --git a/src/devices/bus/msx/cart/ide.h b/src/devices/bus/msx/cart/ide.h
new file mode 100644
index 00000000000..1b958ffda59
--- /dev/null
+++ b/src/devices/bus/msx/cart/ide.h
@@ -0,0 +1,12 @@
+// license:BSD-3-Clause
+// copyright-holders:Wilbert Pol
+#ifndef MAME_BUS_MSX_CART_IDE_H
+#define MAME_BUS_MSX_CART_IDE_H
+
+#pragma once
+
+#include "bus/msx/slot/cartridge.h"
+
+DECLARE_DEVICE_TYPE(MSX_CART_SUNRISE_ATAIDE, msx_cart_interface)
+
+#endif // MAME_BUS_MSX_CART_IDE_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..69088d4c3db
--- /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 ATTR_COLD;
+ virtual const tiny_rom_entry *device_rom_region() const override ATTR_COLD;
+
+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..a50fa236e18
--- /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 ATTR_COLD;
+ virtual void device_reset() override ATTR_COLD;
+
+ 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_tap(0xd8, 0xd9, "kanji_w", [this] (offs_t ofs, u8 &data, u8) { this->kanji_w(ofs, data); });
+ io_space().install_read_tap(0xd9, 0xd9, "kanji_r", [this] (offs_t ofs, u8 &data, u8) { data &= this->kanji_r(ofs); });
+}
+
+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 (BIT(offset, 0))
+ 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 ATTR_COLD;
+ virtual ioport_constructor device_input_ports() const override ATTR_COLD;
+
+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..6e0cb011326
--- /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 ATTR_COLD;
+
+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 ATTR_COLD;
+
+ virtual void device_add_mconfig(machine_config &config) override ATTR_COLD;
+
+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 ATTR_COLD;
+
+ virtual const tiny_rom_entry *device_rom_region() const override ATTR_COLD;
+ virtual void device_add_mconfig(machine_config &config) override ATTR_COLD;
+
+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 ATTR_COLD;
+
+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 ATTR_COLD;
+
+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 ATTR_COLD;
+ virtual void device_reset() override ATTR_COLD;
+
+ virtual void device_add_mconfig(machine_config &config) override ATTR_COLD;
+
+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 ATTR_COLD;
+
+ virtual void device_add_mconfig(machine_config &config) override ATTR_COLD;
+
+ 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) ATTR_COLD;
+};
+
+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 ATTR_COLD;
+
+ 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..73d71ec2006
--- /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 ATTR_COLD;
+
+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 ATTR_COLD;
+
+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 ATTR_COLD;
+ virtual void device_reset() override ATTR_COLD;
+
+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 ATTR_COLD;
+
+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 ATTR_COLD;
+
+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..135d28e2cdd
--- /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 ATTR_COLD;
+ virtual void device_reset() override ATTR_COLD;
+
+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..654b185f75a
--- /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 ATTR_COLD;
+
+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..199a02462c2
--- /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 ATTR_COLD;
+ virtual void device_reset() override ATTR_COLD;
+
+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
new file mode 100644
index 00000000000..ba03a17d4d3
--- /dev/null
+++ b/src/devices/bus/msx/cart/moonsound.cpp
@@ -0,0 +1,122 @@
+// license:BSD-3-Clause
+// copyright-holders:Wilbert Pol
+/**********************************************************************************
+
+TODO:
+- Properly hook up correct SRAM sizes for different moonsound compatible
+ cartridges. (Original moonsound has 128KB SRAM)
+
+**********************************************************************************/
+
+#include "emu.h"
+#include "moonsound.h"
+
+#include "sound/ymopl.h"
+
+#include "speaker.h"
+
+
+#define VERBOSE 0
+#include "logmacro.h"
+
+namespace {
+
+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 ATTR_COLD;
+ virtual void device_reset() override ATTR_COLD;
+
+ virtual void device_add_mconfig(machine_config &config) override ATTR_COLD;
+ virtual const tiny_rom_entry *device_rom_region() const override ATTR_COLD;
+
+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) ATTR_COLD;
+
+ required_device<ymf278b_device> m_ymf278b;
+};
+
+void msx_cart_moonsound_device::ymf278b_map(address_map &map)
+{
+ map(0x000000, 0x1fffff).rom();
+ 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.
+ SPEAKER(config, "speaker", 2).front();
+
+ YMF278B(config, m_ymf278b, 33.8688_MHz_XTAL);
+ m_ymf278b->set_addrmap(0, &msx_cart_moonsound_device::ymf278b_map);
+ m_ymf278b->irq_handler().set(FUNC(msx_cart_moonsound_device::irq_w));
+ m_ymf278b->add_route(0, "speaker", 0.50, 0);
+ m_ymf278b->add_route(1, "speaker", 0.50, 1);
+ m_ymf278b->add_route(2, "speaker", 0.40, 0);
+ m_ymf278b->add_route(3, "speaker", 0.40, 1);
+ m_ymf278b->add_route(4, "speaker", 0.50, 0);
+ m_ymf278b->add_route(5, "speaker", 0.50, 1);
+}
+
+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);
+}
+
+void msx_cart_moonsound_device::device_start()
+{
+ // Install IO read/write handlers
+ 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()
+{
+}
+
+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_pcm(offs_t offset, u8 data)
+{
+ LOG("moonsound: write 0x%02x, data 0x%02x\n", 0x7e + offset, data);
+ m_ymf278b->write(4 + offset, data);
+}
+
+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
+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..06231a40e07
--- /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 ATTR_COLD;
+ virtual void device_add_mconfig(machine_config &config) override ATTR_COLD;
+ virtual const tiny_rom_entry *device_rom_region() const override ATTR_COLD;
+
+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 ATTR_COLD;
+ virtual void device_add_mconfig(machine_config &config) override ATTR_COLD;
+ virtual const tiny_rom_entry *device_rom_region() const override ATTR_COLD;
+
+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 ATTR_COLD;
+ virtual void device_reset() override ATTR_COLD;
+ virtual void device_add_mconfig(machine_config &config) override ATTR_COLD;
+ virtual ioport_constructor device_input_ports() const override ATTR_COLD;
+ virtual const tiny_rom_entry *device_rom_region() const override ATTR_COLD;
+
+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 68303c56667..b1cbc65378b 100644
--- a/src/devices/bus/msx_cart/msx_audio_kb.cpp
+++ b/src/devices/bus/msx/cart/msx_audio_kb.cpp
@@ -7,9 +7,15 @@
DEFINE_DEVICE_TYPE(MSX_AUDIO_KBDC_PORT, msx_audio_kbdc_port_device, "msx_audio_kbdc_port", "MSX Audio keyboard connector port")
-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_kb_port_interface::msx_audio_kb_port_interface(machine_config const &mconfig, device_t &device)
+ : device_interface(device, "msxaudiokb")
+{
+}
+
+
+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_slot_interface(mconfig, *this)
+ , device_single_card_slot_interface<msx_audio_kb_port_interface>(mconfig, *this)
, m_keyboard(nullptr)
{
}
@@ -17,26 +23,23 @@ msx_audio_kbdc_port_device::msx_audio_kbdc_port_device(const machine_config &mco
void msx_audio_kbdc_port_device::device_start()
{
- m_keyboard = dynamic_cast<msx_audio_kb_port_interface *>(get_card_device());
+ m_keyboard = get_card_device();
}
-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();
- }
- return 0xff;
+ else
+ return 0xff;
}
@@ -47,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)
@@ -55,11 +58,11 @@ public:
{
}
- virtual ioport_constructor device_input_ports() const override;
+ virtual ioport_constructor device_input_ports() const override ATTR_COLD;
- virtual uint8_t read() override
+ virtual u8 read() override
{
- uint8_t result = 0xff;
+ u8 result = 0xff;
for (int i = 0; i < 8; i++)
{
@@ -71,7 +74,7 @@ public:
return result;
}
- virtual void write(uint8_t data) override
+ virtual void write(u8 data) override
{
m_row = data;
}
@@ -85,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")
@@ -170,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)
@@ -185,11 +188,11 @@ public:
{
}
- virtual ioport_constructor device_input_ports() const override;
+ virtual ioport_constructor device_input_ports() const override ATTR_COLD;
- virtual uint8_t read() override
+ virtual u8 read() override
{
- uint8_t result = 0xff;
+ u8 result = 0xff;
for (int i = 0; i < 8; i++)
{
@@ -201,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;
@@ -216,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")
@@ -299,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 93a2d026214..a5d93a8d67b 100644
--- a/src/devices/bus/msx_cart/msx_audio_kb.h
+++ b/src/devices/bus/msx/cart/msx_audio_kb.h
@@ -7,7 +7,7 @@
DECLARE_DEVICE_TYPE(MSX_AUDIO_KBDC_PORT, msx_audio_kbdc_port_device)
-class msx_audio_kb_port_interface : public device_slot_card_interface
+class msx_audio_kb_port_interface : public device_interface
{
public:
virtual uint8_t read() { return 0xff; }
@@ -15,39 +15,37 @@ public:
protected:
// construction/destruction
- using device_slot_card_interface::device_slot_card_interface;
+ msx_audio_kb_port_interface(machine_config const &mconfig, device_t &device);
};
-class msx_audio_kbdc_port_device : public device_t, public device_slot_interface
+class msx_audio_kbdc_port_device : public device_t, public device_single_card_slot_interface<msx_audio_kb_port_interface>
{
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);
-
- // device-level overrides
- virtual void device_start() override;
+ 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_t implementation
+ virtual void device_start() override ATTR_COLD;
+
msx_audio_kb_port_interface *m_keyboard;
};
void msx_audio_keyboards(device_slot_interface &device);
-
#endif // MAME_BUS_MSX_CART_MSX_AUDIO_KB_H
diff --git a/src/devices/bus/msx/cart/msxdos2.cpp b/src/devices/bus/msx/cart/msxdos2.cpp
new file mode 100644
index 00000000000..2dc969fe091
--- /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 ATTR_COLD;
+ 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 ATTR_COLD;
+
+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..11ce70ac2a2
--- /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 ATTR_COLD;
+
+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..cd94d9f41b6
--- /dev/null
+++ b/src/devices/bus/msx/cart/ram.cpp
@@ -0,0 +1,544 @@
+// 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
+
+Known issues/problems:
+- Switching Tecnobytes Double RAM from Memory Mapper to MegaRAM mode will cause
+ the emulation to look up when the system is using the Double RAM as main
+ memory. It is unknown if this also happens on a real system.
+
+TODO:
+- Unknown which parts of memory are used for the MegaRAM 8KB pages.
+
+
+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
+- 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"
+#include "sound/sn76496.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)
+DECLARE_DEVICE_TYPE(MSX_CART_DOUBLE_RAM, msx_cart_interface)
+DECLARE_DEVICE_TYPE(MSX_CART_MMM, 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);
+ device.option_add(slotoptions::DOUBLE_RAM, MSX_CART_DOUBLE_RAM);
+ device.option_add(slotoptions::MMM, MSX_CART_MMM);
+}
+
+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 ATTR_COLD;
+
+ template <int Bank> void bank_w(u8 data);
+
+ 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)
+ { }
+};
+
+
+class msx_cart_mmm_device : public msx_cart_base_mm_ram_device
+{
+public:
+ msx_cart_mmm_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock)
+ : msx_cart_base_mm_ram_device(mconfig, MSX_CART_MMM, tag, owner, clock, 1024 * 1024)
+ , m_sn76489a(*this, "sn76489a")
+ , m_access_enabled(false)
+ , m_sn76489_enabled(false)
+ { }
+
+protected:
+ virtual void device_start() override ATTR_COLD;
+ virtual void device_add_mconfig(machine_config &config) override ATTR_COLD;
+
+private:
+ required_device<sn76496_base_device> m_sn76489a;
+ bool m_access_enabled;
+ bool m_sn76489_enabled;
+};
+
+void msx_cart_mmm_device::device_start()
+{
+ msx_cart_base_mm_ram_device::device_start();
+
+ m_access_enabled = false;
+ m_sn76489_enabled = false;
+
+ io_space().install_write_tap(0x3c, 0x3c, "ena_access", [this] (offs_t, u8& data, u8){ this->m_access_enabled = BIT(data, 7); });
+ io_space().install_write_tap(0x3f, 0x3f, "sn76489w", [this] (offs_t, u8& data, u8){ if (m_sn76489_enabled) this->m_sn76489a->write(data); });
+
+ page(2)->install_write_tap(0x803c, 0x803c, "ena_sn76489", [this] (offs_t, u8& data, u8){ if (m_access_enabled) this->m_sn76489_enabled |= BIT(data, 6); });
+ page(2)->install_read_tap(0x80fc, 0x80fc, "map00r", [this] (offs_t, u8& data, u8){ if (m_access_enabled) data = 0xc0 | this->m_rambank[0]->entry(); });
+ page(2)->install_read_tap(0x80fd, 0x80fd, "map40r", [this] (offs_t, u8& data, u8){ if (m_access_enabled) data = 0xc0 | this->m_rambank[1]->entry(); });
+ page(2)->install_read_tap(0x80fe, 0x80fe, "map80r", [this] (offs_t, u8& data, u8){ if (m_access_enabled) data = 0xc0 | this->m_rambank[2]->entry(); });
+ page(2)->install_read_tap(0x80ff, 0x80ff, "mapc0r", [this] (offs_t, u8& data, u8){ if (m_access_enabled) data = 0xc0 | this->m_rambank[3]->entry(); });
+ page(2)->install_write_tap(0x80fc, 0x80fc, "map00w", [this] (offs_t, u8& data, u8){ if (m_access_enabled) this->bank_w<0>(data); });
+ page(2)->install_write_tap(0x80fd, 0x80fd, "map40w", [this] (offs_t, u8& data, u8){ if (m_access_enabled) this->bank_w<1>(data); });
+ page(2)->install_write_tap(0x80fe, 0x80fe, "map80w", [this] (offs_t, u8& data, u8){ if (m_access_enabled) this->bank_w<2>(data); });
+ page(2)->install_write_tap(0x80ff, 0x80ff, "mapc0w", [this] (offs_t, u8& data, u8){ if (m_access_enabled) this->bank_w<3>(data); });
+
+ save_item(NAME(m_access_enabled));
+ save_item(NAME(m_sn76489_enabled));
+}
+
+void msx_cart_mmm_device::device_add_mconfig(machine_config &config)
+{
+ SN76489A(config, m_sn76489a, DERIVED_CLOCK(1, 3));
+ if (parent_slot())
+ m_sn76489a->add_route(ALL_OUTPUTS, soundin(), 0.8);
+}
+
+
+
+class msx_cart_double_ram_device : public msx_cart_base_mm_ram_device
+{
+public:
+ msx_cart_double_ram_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock)
+ : msx_cart_base_mm_ram_device(mconfig, MSX_CART_DOUBLE_RAM, tag, owner, clock, 4 * 1024 * 1024)
+ , m_mode_switch(*this, "MODE")
+ , m_view{ {*this, "view0"}, {*this, "view1"}, {*this, "view2"}, {*this, "view3"} }
+ , m_mrview{ {*this, "mrview0"}, {*this, "mrview1"}, {*this, "mrview2"}, {*this, "mrview3"} }
+ , m_megaram(false)
+ { }
+
+ DECLARE_INPUT_CHANGED_MEMBER(mode_callback);
+
+protected:
+ virtual void device_start() override ATTR_COLD;
+ virtual void device_reset() override ATTR_COLD;
+ virtual ioport_constructor device_input_ports() const override ATTR_COLD;
+
+private:
+ static constexpr u8 MODE_RO = 0;
+ static constexpr u8 MODE_RW = 1;
+ static constexpr u8 MODE_MM = 0;
+ static constexpr u8 MODE_MR = 1;
+
+ required_ioport m_mode_switch;
+ memory_view m_view[4];
+ memory_view m_mrview[4];
+ bool m_megaram;
+
+ void set_page_views();
+};
+
+static INPUT_PORTS_START(double_ram_mode_switch)
+ PORT_START("MODE")
+ PORT_CONFNAME(0x01, 0x01, "Mode") PORT_CHANGED_MEMBER(DEVICE_SELF, FUNC(msx_cart_double_ram_device::mode_callback), 0)
+ PORT_CONFSETTING(0x00, "Memory Mapper")
+ PORT_CONFSETTING(0x01, "MegaRAM")
+INPUT_PORTS_END
+
+ioport_constructor msx_cart_double_ram_device::device_input_ports() const
+{
+ return INPUT_PORTS_NAME(double_ram_mode_switch);
+}
+
+void msx_cart_double_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);
+ }
+ );
+
+ page(0)->install_view(0x0000, 0x3fff, m_view[0]);
+ page(1)->install_view(0x4000, 0x7fff, m_view[1]);
+ page(2)->install_view(0x8000, 0xbfff, m_view[2]);
+ page(3)->install_view(0xc000, 0xffff, m_view[3]);
+
+ m_view[0][MODE_MM].install_readwrite_bank(0x0000, 0x3fff, m_rambank[0]);
+ m_view[0][MODE_MR];
+
+ m_view[1][MODE_MM].install_readwrite_bank(0x4000, 0x7fff, m_rambank[1]);
+ m_view[1][MODE_MR].install_view(0x4000, 0x5fff, m_mrview[0]);
+ m_view[1][MODE_MR].install_view(0x6000, 0x7fff, m_mrview[1]);
+
+ m_view[2][MODE_MM].install_readwrite_bank(0x8000, 0xbfff, m_rambank[2]);
+ m_view[2][MODE_MR].install_view(0x8000, 0x9fff, m_mrview[2]);
+ m_view[2][MODE_MR].install_view(0xa000, 0xbfff, m_mrview[3]);
+
+ m_view[3][MODE_MM].install_readwrite_bank(0xc000, 0xffff, m_rambank[3]);
+ m_view[3][MODE_MR];
+
+ m_mrview[0][MODE_RO].install_read_bank(0x4000, 0x5fff, m_rambank[0]);
+ m_mrview[0][MODE_RO].install_write_handler(0x4000, 0x4000, write8smo_delegate(*this, [this] (u8 data) { this->m_rambank[0]->set_entry(data); }, "bank_4000"));
+ m_mrview[0][MODE_RW].install_readwrite_bank(0x4000, 0x5fff, m_rambank[0]);
+
+ m_mrview[1][MODE_RO].install_read_bank(0x6000, 0x7fff, m_rambank[1]);
+ m_mrview[1][MODE_RO].install_write_handler(0x6000, 0x6000, write8smo_delegate(*this, [this] (u8 data) { this->m_rambank[1]->set_entry(data); }, "bank_6000"));
+ m_mrview[1][MODE_RW].install_readwrite_bank(0x6000, 0x7fff, m_rambank[1]);
+
+ m_mrview[2][MODE_RO].install_read_bank(0x8000, 0x9fff, m_rambank[2]);
+ m_mrview[2][MODE_RO].install_write_handler(0x8000, 0x8000, write8smo_delegate(*this, [this] (u8 data) { this->m_rambank[2]->set_entry(data); }, "bank_8000"));
+ m_mrview[2][MODE_RW].install_readwrite_bank(0x8000, 0x9fff, m_rambank[2]);
+
+ m_mrview[3][MODE_RO].install_read_bank(0xa000, 0xbfff, m_rambank[3]);
+ m_mrview[3][MODE_RO].install_write_handler(0xa000, 0xa000, write8smo_delegate(*this, [this] (u8 data) { this->m_rambank[3]->set_entry(data); }, "bank_a000"));
+ m_mrview[3][MODE_RW].install_readwrite_bank(0xa000, 0xbfff, m_rambank[3]);
+
+ io_space().install_read_tap(0x8e, 0x8e, "megaram_w", [this] (offs_t, u8&, u8) { if (m_megaram) for (int i = 0; i < 4; i++) m_mrview[i].select(MODE_RW); } );
+ io_space().install_write_tap(0x8e, 0x8e, "megaram_r", [this] (offs_t, u8&, u8) { if (m_megaram) for (int i = 0; i < 4; i++) m_mrview[i].select(MODE_RO); } );
+
+ // 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){ if (!m_megaram) this->bank_w<0>(data); });
+ io_space().install_write_tap(0xfd, 0xfd, "bank1", [this] (offs_t, u8& data, u8){ if (!m_megaram) this->bank_w<1>(data); });
+ io_space().install_write_tap(0xfe, 0xfe, "bank2", [this] (offs_t, u8& data, u8){ if (!m_megaram) this->bank_w<2>(data); });
+ io_space().install_write_tap(0xff, 0xff, "bank3", [this] (offs_t, u8& data, u8){ if (!m_megaram) this->bank_w<3>(data); });
+
+ save_item(NAME(m_megaram));
+
+ for (int i = 0; i < 4; i++)
+ {
+ m_mrview[i].select(MODE_RO);
+ m_rambank[i]->set_entry(i);
+ }
+}
+
+void msx_cart_double_ram_device::device_reset()
+{
+ m_megaram = BIT(m_mode_switch->read(), 0);
+ set_page_views();
+}
+
+INPUT_CHANGED_MEMBER(msx_cart_double_ram_device::mode_callback)
+{
+ m_megaram = BIT(newval, 0);
+ set_page_views();
+}
+
+void msx_cart_double_ram_device::set_page_views()
+{
+ for (int i = 0; i < 4; i++)
+ m_view[i].select(m_megaram ? MODE_MR : MODE_MM);
+}
+
+} // 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")
+DEFINE_DEVICE_TYPE_PRIVATE(MSX_CART_DOUBLE_RAM, msx_cart_interface, msx_cart_double_ram_device, "msx_cart_double_ram", "Tecnobytes Double RAM")
+DEFINE_DEVICE_TYPE_PRIVATE(MSX_CART_MMM, msx_cart_interface, msx_cart_mmm_device, "msx_cart_mmm", "Popolon Musical Memory Mapper")
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..4949fb908fd
--- /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 ATTR_COLD;
+
+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 ATTR_COLD;
+ virtual void device_add_mconfig(machine_config &config) override ATTR_COLD;
+
+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..b2eefe5ee80
--- /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 ATTR_COLD;
+ virtual void device_add_mconfig(machine_config &config) override ATTR_COLD;
+ virtual void device_resolve_objects() override ATTR_COLD;
+ 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..61e44463cb4
--- /dev/null
+++ b/src/devices/bus/msx/cart/slotoptions.cpp
@@ -0,0 +1,94 @@
+// 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 DOUBLE_RAM = "double_ram";
+char const *const EASISPEECH = "easispeech";
+char const *const EC701 = "ec701";
+char const *const FMPAC = "fmpac";
+char const *const FRANKY = "franky";
+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 MMM = "mmm";
+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_ATAIDE = "sunrise_ataide";
+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";
+char const *const VIDEO80 = "video80";
+} // 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..d5bf0586de3
--- /dev/null
+++ b/src/devices/bus/msx/cart/slotoptions.h
@@ -0,0 +1,98 @@
+// 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 DOUBLE_RAM;
+extern char const *const DOOLY;
+extern char const *const EASISPEECH;
+extern char const *const EC701;
+extern char const *const FMPAC;
+extern char const *const FRANKY;
+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 MMM;
+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_ATAIDE;
+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;
+extern char const *const VIDEO80;
+} // 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..51a3e53ebb0
--- /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 ATTR_COLD;
+ virtual void device_start() override { }
+ virtual void device_add_mconfig(machine_config &config) override ATTR_COLD;
+ 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..30523be115a
--- /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 ATTR_COLD;
+
+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/video80.cpp b/src/devices/bus/msx/cart/video80.cpp
new file mode 100644
index 00000000000..2bdfff855da
--- /dev/null
+++ b/src/devices/bus/msx/cart/video80.cpp
@@ -0,0 +1,212 @@
+// license:BSD-3-Clause
+// copyright-holders:F. Ulivi
+
+/*********************************************************************
+
+ VIDEO80 homebrew 80-column video card
+
+ This is a 80-column video card that I designed and built in 1988.
+ Here's a summary of its features:
+ - 80 columns by 24 rows of text video
+ - 8x8 character cell
+ - 16 MHz dot clock, 50 Hz frame rate
+ - Based on MC6845 CRT controller
+ - 4k of SRAM: half for the framebuffer & half for the character
+ generator.
+ - 4k of EPROM: it contains the firmware and the compressed font.
+ FW supports seamless operation in both BASIC and MSXDOS
+ environments. No driver or additional sw is needed.
+
+*********************************************************************/
+
+#include "emu.h"
+#include "video80.h"
+#include "cpu/z80/z80.h"
+#include "video/mc6845.h"
+
+#include "emupal.h"
+#include "screen.h"
+
+// Debugging
+#define VERBOSE 0
+#include "logmacro.h"
+
+namespace {
+
+// Dot clock
+constexpr auto DOT_CLOCK = 16_MHz_XTAL;
+
+class msx_cart_video80_device : public device_t, public msx_cart_interface
+{
+public:
+ msx_cart_video80_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
+ : device_t(mconfig, MSX_CART_VIDEO80, tag, owner, clock)
+ , msx_cart_interface(mconfig, *this)
+ , m_palette(*this, "palette")
+ , m_crtc(*this, "crtc")
+ , m_screen(*this, "screen1")
+ , m_cpu_waiting(false)
+ {
+ }
+
+ virtual std::error_condition initialize_cartridge(std::string &message) override;
+
+protected:
+ virtual void device_start() override ATTR_COLD;
+ virtual void device_add_mconfig(machine_config &config) override ATTR_COLD;
+
+ void de_w(int state);
+ uint8_t vram_r(offs_t addr);
+ void vram_w(offs_t addr, uint8_t data);
+ uint8_t crtc_r(offs_t addr);
+ void crtc_w(offs_t addr, uint8_t data);
+
+private:
+ static inline constexpr unsigned VRAM_SIZE = 4096;
+
+ required_device<palette_device> m_palette;
+ required_device<mc6845_device> m_crtc;
+ required_device<screen_device> m_screen;
+
+ uint8_t m_vram[VRAM_SIZE];
+ bool m_cpu_waiting;
+
+ MC6845_UPDATE_ROW(crtc_update_row);
+};
+
+std::error_condition msx_cart_video80_device::initialize_cartridge(std::string &message)
+{
+ if (!cart_rom_region())
+ {
+ message = "msx_cart_video80_device: Required region 'rom' was not found.";
+ return image_error::INTERNAL;
+ }
+
+ if (cart_rom_region()->bytes() != 0x1000)
+ {
+ message = "msx_cart_video80_device: Region 'rom' has invalid size.";
+ return image_error::INVALIDLENGTH;
+ }
+
+ page(1)->install_rom(0x4000, 0x4fff, cart_rom_region()->base());
+ page(1)->install_read_handler(0x5000, 0x5fff, emu::rw_delegate(*this, FUNC(msx_cart_video80_device::vram_r)));
+ page(1)->install_write_handler(0x5000, 0x5fff, emu::rw_delegate(*this, FUNC(msx_cart_video80_device::vram_w)));
+ page(1)->install_read_handler(0x6000, 0x6fff, emu::rw_delegate(*this, FUNC(msx_cart_video80_device::crtc_r)));
+ page(1)->install_write_handler(0x6000, 0x6fff, emu::rw_delegate(*this, FUNC(msx_cart_video80_device::crtc_w)));
+
+ return std::error_condition();
+}
+
+void msx_cart_video80_device::device_start()
+{
+ save_item(NAME(m_vram));
+ save_item(NAME(m_cpu_waiting));
+}
+
+void msx_cart_video80_device::device_add_mconfig(machine_config &config)
+{
+ PALETTE(config, m_palette, palette_device::MONOCHROME);
+
+ SCREEN(config, m_screen, SCREEN_TYPE_RASTER, rgb_t::green());
+ m_screen->set_raw(DOT_CLOCK, 1024, 0, 640, 312, 0, 192);
+ m_screen->set_screen_update(m_crtc, FUNC(mc6845_device::screen_update));
+
+ MC6845(config, m_crtc, DOT_CLOCK / 8);
+ m_crtc->set_char_width(8);
+ m_crtc->set_show_border_area(false);
+ m_crtc->set_screen(m_screen);
+ m_crtc->set_update_row_callback(FUNC(msx_cart_video80_device::crtc_update_row));
+ m_crtc->out_de_callback().set(FUNC(msx_cart_video80_device::de_w));
+}
+
+void msx_cart_video80_device::de_w(int state)
+{
+ if (m_cpu_waiting && !state)
+ {
+ maincpu().set_input_line(Z80_INPUT_LINE_WAIT, CLEAR_LINE);
+ m_cpu_waiting = false;
+ }
+}
+
+uint8_t msx_cart_video80_device::vram_r(offs_t addr)
+{
+ if (!machine().side_effects_disabled() && m_crtc->de_r())
+ {
+ maincpu().set_input_line(Z80_INPUT_LINE_WAIT, ASSERT_LINE);
+ maincpu().defer_access();
+ m_cpu_waiting = true;
+ return 0;
+ }
+ else
+ {
+ return m_vram[addr];
+ }
+}
+
+void msx_cart_video80_device::vram_w(offs_t addr, uint8_t data)
+{
+ if (!machine().side_effects_disabled() && m_crtc->de_r())
+ {
+ maincpu().set_input_line(Z80_INPUT_LINE_WAIT, ASSERT_LINE);
+ maincpu().defer_access();
+ m_cpu_waiting = true;
+ }
+ else
+ {
+ m_vram[addr] = data;
+ }
+}
+
+uint8_t msx_cart_video80_device::crtc_r(offs_t addr)
+{
+ uint8_t res = 0;
+
+ if (BIT(addr, 1))
+ {
+ if (BIT(addr, 0))
+ res = m_crtc->register_r();
+ else
+ LOG("Reading from non-existing reg!\n");
+ }
+ else
+ {
+ LOG("Reading from a write-only address!\n");
+ }
+
+ return res;
+}
+
+void msx_cart_video80_device::crtc_w(offs_t addr, uint8_t data)
+{
+ if (BIT(addr, 1))
+ {
+ LOG("Writing to a read-only address!\n");
+ }
+ else
+ {
+ if (BIT(addr, 0))
+ m_crtc->register_w(data);
+ else
+ m_crtc->address_w(data);
+ }
+}
+
+MC6845_UPDATE_ROW(msx_cart_video80_device::crtc_update_row)
+{
+ pen_t const *const pen = m_palette->pens();
+ for (int i = 0; i < x_count; i++)
+ {
+ uint8_t const char_code = m_vram[(ma + i) & 0x7ff];
+ uint8_t pixels = m_vram[(unsigned(char_code) << 3) | 0x800 | (ra & 7)];
+ bool const cursor = cursor_x == i;
+ if (cursor)
+ pixels = ~pixels;
+
+ for (unsigned col = 0; col < 8; col++)
+ bitmap.pix(y, i * 8 + col) = pen[BIT(pixels, 7 - col)];
+ }
+}
+
+} // anonymous namespace
+
+DEFINE_DEVICE_TYPE_PRIVATE(MSX_CART_VIDEO80, msx_cart_interface, msx_cart_video80_device, "msx_cart_video80", "MSX Cartridge - VIDEO80")
diff --git a/src/devices/bus/msx/cart/video80.h b/src/devices/bus/msx/cart/video80.h
new file mode 100644
index 00000000000..ee7a8d522ef
--- /dev/null
+++ b/src/devices/bus/msx/cart/video80.h
@@ -0,0 +1,19 @@
+// license:BSD-3-Clause
+// copyright-holders:F. Ulivi
+
+/*********************************************************************
+
+ VIDEO80 homebrew 80-column video card
+
+*********************************************************************/
+
+#ifndef MAME_BUS_MSX_CART_VIDEO80_H
+#define MAME_BUS_MSX_CART_VIDEO80_H
+
+#pragma once
+
+#include "bus/msx/slot/cartridge.h"
+
+DECLARE_DEVICE_TYPE(MSX_CART_VIDEO80, msx_cart_interface)
+
+#endif // MAME_BUS_MSX_CART_VIDEO80_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..2d9000390dc
--- /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 ATTR_COLD;
+ virtual void device_resolve_objects() override ATTR_COLD;
+ 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..075c00ae3af
--- /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 ATTR_COLD;
+
+ 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..1a7f7152018
--- /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 ATTR_COLD;
+ 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..03861b5b0a9
--- /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 ATTR_COLD;
+ 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..04cf6204372
--- /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 ATTR_COLD;
+
+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..95155e7f421
--- /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 ATTR_COLD;
+ virtual void device_reset() override ATTR_COLD;
+
+ 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..1f22b3dc900
--- /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 ATTR_COLD;
+ virtual void device_add_mconfig(machine_config &config) override ATTR_COLD;
+
+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..9f6a662d5d5
--- /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 ATTR_COLD;
+ 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..466ececd4c7
--- /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 ATTR_COLD;
+ virtual void device_reset() override ATTR_COLD;
+
+ 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..168104b7bb4
--- /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", FUNC(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", FUNC(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..bb315802c8d
--- /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 ATTR_COLD;
+};
+
+#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..31e863d5c8a
--- /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 ATTR_COLD;
+};
+
+#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..a9ba98068a5
--- /dev/null
+++ b/src/devices/bus/msx/module/sfg.cpp
@@ -0,0 +1,211 @@
+// 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 ATTR_COLD;
+ virtual void device_add_mconfig(machine_config &config) override ATTR_COLD;
+
+ 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, "speaker", 2).front();
+ 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, "speaker", 0.80, 0);
+ ym2151.add_route(1, "speaker", 0.80, 1);
+
+ 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 ATTR_COLD;
+};
+
+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 ATTR_COLD;
+ virtual const tiny_rom_entry *device_rom_region() const override ATTR_COLD;
+};
+
+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, "speaker", 0.80, 0);
+ ym2164.add_route(1, "speaker", 0.80, 1);
+}
+
+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..cd7bf3d7f1c
--- /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 ATTR_COLD;
+
+protected:
+ virtual void device_start() override ATTR_COLD;
+
+ virtual void device_add_mconfig(machine_config &config) override ATTR_COLD;
+
+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..d120cc520da
--- /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 ATTR_COLD;
+ virtual void device_reset() override ATTR_COLD;
+
+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..206f835cc49
--- /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 ATTR_COLD;
+ virtual void device_reset() override ATTR_COLD;
+
+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 79a07b2e53a..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, 0x20000)
+ , 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..5dfc4a81e9d 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_reset() override;
+ virtual void device_start() override ATTR_COLD;
+ virtual void device_reset() override ATTR_COLD;
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..8438d4a8f8d
--- /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 ATTR_COLD;
+ virtual void device_start() override ATTR_COLD;
+
+ 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..0ce715c2263
--- /dev/null
+++ b/src/devices/bus/msx/slot/disk.cpp
@@ -0,0 +1,1435 @@
+// 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);
+ m_fdc->set_ready_line_connected(false);
+}
+
+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..c5819b29aee
--- /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 ATTR_COLD;
+ virtual void device_reset() override ATTR_COLD;
+ 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 ATTR_COLD;
+ 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 ATTR_COLD;
+ virtual void device_reset() override ATTR_COLD;
+ 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 ATTR_COLD;
+};
+
+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 ATTR_COLD;
+};
+
+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 ATTR_COLD;
+};
+
+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 ATTR_COLD;
+};
+
+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 ATTR_COLD;
+};
+
+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 ATTR_COLD;
+};
+
+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 ATTR_COLD;
+};
+
+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 ATTR_COLD;
+};
+
+
+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 ATTR_COLD;
+ virtual void device_reset() override ATTR_COLD;
+ 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 ATTR_COLD;
+};
+
+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 ATTR_COLD;
+};
+
+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 ATTR_COLD;
+};
+
+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 ATTR_COLD;
+};
+
+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 ATTR_COLD;
+};
+
+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 ATTR_COLD;
+};
+
+
+
+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 ATTR_COLD;
+ virtual void device_start() override ATTR_COLD;
+};
+
+
+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 ATTR_COLD;
+};
+
+
+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 ATTR_COLD;
+ virtual void device_start() override ATTR_COLD;
+
+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 ATTR_COLD;
+ virtual void device_reset() override ATTR_COLD;
+ virtual void device_post_load() override;
+ virtual void device_add_mconfig(machine_config &config) override ATTR_COLD;
+
+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 ATTR_COLD;
+ virtual void device_reset() override ATTR_COLD;
+ virtual void device_post_load() override;
+ virtual void device_add_mconfig(machine_config &config) override ATTR_COLD;
+
+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 ATTR_COLD;
+ virtual void device_reset() override ATTR_COLD;
+ virtual void device_post_load() override;
+ virtual void device_add_mconfig(machine_config &config) override ATTR_COLD;
+
+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 ATTR_COLD;
+ virtual void device_reset() override ATTR_COLD;
+ virtual void device_post_load() override;
+ virtual void device_add_mconfig(machine_config &config) override ATTR_COLD;
+
+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 ATTR_COLD;
+};
+
+
+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 ATTR_COLD;
+ virtual void device_reset() override ATTR_COLD;
+ virtual void device_post_load() override;
+ virtual void device_add_mconfig(machine_config &config) override ATTR_COLD;
+
+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 ATTR_COLD;
+ virtual void device_reset() override ATTR_COLD;
+ virtual void device_post_load() override;
+ virtual void device_add_mconfig(machine_config &config) override ATTR_COLD;
+
+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 ATTR_COLD;
+};
+
+
+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 ATTR_COLD;
+ virtual void device_reset() override ATTR_COLD;
+ virtual void device_post_load() override;
+ virtual void device_add_mconfig(machine_config &config) override ATTR_COLD;
+
+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..abb599d4c42
--- /dev/null
+++ b/src/devices/bus/msx/slot/fs4600.cpp
@@ -0,0 +1,136 @@
+// 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 = std::make_unique<u8[]>(SRAM_SIZE);
+ m_nvram->set_base(&m_sram[0], SRAM_SIZE);
+
+ save_item(NAME(m_sram_address));
+ save_pointer(NAME(m_sram), SRAM_SIZE);
+
+ 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..2db6c18b4a9 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_add_mconfig(machine_config &config) override;
+ virtual void device_start() override ATTR_COLD;
+ virtual void device_reset() override ATTR_COLD;
- void restore_banks();
+ virtual void device_add_mconfig(machine_config &config) override ATTR_COLD;
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::unique_ptr<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..6b59c516bbe
--- /dev/null
+++ b/src/devices/bus/msx/slot/fsa1fm.cpp
@@ -0,0 +1,223 @@
+// 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 = std::make_unique<u8[]>(RAM_SIZE);
+ m_empty_bank = std::make_unique<u8[]>(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(NAME(m_ram), m_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[0]); // 0x80-0x83 empty
+ m_bank[i]->configure_entry(0x84 + j, &m_ram[0]); // 0x84-0x87 ram
+ m_bank[i]->configure_entry(0x88 + j, &m_empty_bank[0]); // 0x88-0x8b empty
+ m_bank[i]->configure_entry(0x8c + j, &m_ram[0]); // 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 = std::make_unique<u8[]>(SRAM_SIZE);
+ m_nvram->set_base(&m_sram[0], SRAM_SIZE);
+
+ save_pointer(NAME(m_sram), 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[0]);
+ 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..3553a799860
--- /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 ATTR_COLD;
+ virtual void device_reset() override ATTR_COLD;
+
+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::unique_ptr<u8[]> m_ram;
+ std::unique_ptr<u8[]> 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 ATTR_COLD;
+ virtual void device_reset() override ATTR_COLD;
+ virtual void device_add_mconfig(machine_config &config) override ATTR_COLD;
+ virtual ioport_constructor device_input_ports() const override ATTR_COLD;
+
+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::unique_ptr<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..3848b8e5ff4
--- /dev/null
+++ b/src/devices/bus/msx/slot/msx_rs232.cpp
@@ -0,0 +1,527 @@
+// 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 = std::make_unique<u8[]>(RAM_SIZE);
+ save_pointer(NAME(m_ram), RAM_SIZE);
+
+ // TODO unmap rom from page 0
+ page(0)->install_ram(0x2000, 0x27ff, &m_ram[0]);
+ page(1)->install_rom(0x4000, 0x5fff, m_rom_region->base() + m_region_offset);
+ page(1)->install_ram(0x6000, 0x67ff, &m_ram[0]);
+ page(2)->install_ram(0xa000, 0xa7ff, &m_ram[0]);
+ 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[0]);
+}
+
+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 = std::make_unique<u8[]>(SRAM_SIZE);
+ m_nvram->set_base(&m_sram[0], SRAM_SIZE);
+
+ save_item(NAME(m_bank_reg));
+ save_pointer(NAME(m_sram), SRAM_SIZE);
+
+ 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[0]);
+}
+
+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..2bd93072953
--- /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 ATTR_COLD;
+ virtual void device_reset() override ATTR_COLD;
+ virtual void device_add_mconfig(machine_config &config) override ATTR_COLD;
+
+ 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 ATTR_COLD;
+
+ 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 ATTR_COLD;
+ virtual ioport_constructor device_input_ports() const override ATTR_COLD;
+
+ 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 ATTR_COLD;
+ virtual ioport_constructor device_input_ports() const override ATTR_COLD;
+
+ 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::unique_ptr<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 ATTR_COLD;
+
+ 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 ATTR_COLD;
+ virtual ioport_constructor device_input_ports() const override ATTR_COLD;
+
+ 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 ATTR_COLD;
+ virtual void device_reset() override ATTR_COLD;
+ virtual ioport_constructor device_input_ports() const override ATTR_COLD;
+ virtual void device_add_mconfig(machine_config &config) override ATTR_COLD;
+
+ 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::unique_ptr<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..e7474b6630f
--- /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 ATTR_COLD;
+ virtual void device_reset() override ATTR_COLD;
+ virtual ioport_constructor device_input_ports() const override ATTR_COLD;
+
+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
new file mode 100644
index 00000000000..489f9eaaaaa
--- /dev/null
+++ b/src/devices/bus/msx/slot/music.h
@@ -0,0 +1,35 @@
+// license:BSD-3-Clause
+// copyright-holders:Wilbert Pol
+#ifndef MAME_BUS_MSX_SLOT_MUSIC_H
+#define MAME_BUS_MSX_SLOT_MUSIC_H
+
+#pragma once
+
+#include "rom.h"
+#include "slot.h"
+
+#include "sound/ymopl.h"
+
+#include <utility>
+
+
+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, u32 clock);
+
+ // configuration
+ template <typename T> void set_ym2413_tag(T &&tag) { m_ym2413.set_tag(std::forward<T>(tag)); }
+
+protected:
+ virtual void device_start() override ATTR_COLD;
+
+private:
+ required_device<ym2413_device> m_ym2413;
+};
+
+
+#endif // MAME_BUS_MSX_SLOT_MUSIC_H
diff --git a/src/devices/bus/msx/slot/panasonic08.cpp b/src/devices/bus/msx/slot/panasonic08.cpp
new file mode 100644
index 00000000000..a0a644c46a9
--- /dev/null
+++ b/src/devices/bus/msx/slot/panasonic08.cpp
@@ -0,0 +1,133 @@
+// 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 = std::make_unique<u8[]>(SRAM_SIZE);
+
+ m_nvram->set_base(&m_sram[0], SRAM_SIZE);
+
+ save_item(NAME(m_selected_bank));
+ save_item(NAME(m_control));
+ save_pointer(NAME(m_sram), SRAM_SIZE);
+
+ 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[0]);
+ m_bank[i]->configure_entry(0x81, &m_sram[0x2000]);
+ m_bank[i]->configure_entry(0x82, &m_sram[0]);
+ m_bank[i]->configure_entry(0x83, &m_sram[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..c94fa981597 100644
--- a/src/devices/bus/msx_slot/panasonic08.h
+++ b/src/devices/bus/msx/slot/panasonic08.h
@@ -15,32 +15,33 @@ 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_start() override ATTR_COLD;
+ virtual void device_reset() override ATTR_COLD;
- virtual void device_add_mconfig(machine_config &config) override;
+ virtual void device_add_mconfig(machine_config &config) override ATTR_COLD;
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;
- std::vector<uint8_t> m_sram;
+ 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::unique_ptr<u8[]> m_sram;
};
diff --git a/src/devices/bus/msx/slot/panasonic08r.cpp b/src/devices/bus/msx/slot/panasonic08r.cpp
new file mode 100644
index 00000000000..c274cf951f4
--- /dev/null
+++ b/src/devices/bus/msx/slot/panasonic08r.cpp
@@ -0,0 +1,166 @@
+// license:BSD-3-Clause
+// copyright-holders:Wilbert Pol
+/*
+
+ Emulation of the firmware mapper as found in Panasonic FS-A1ST and FS-A1GT Turbo-R machines.
+
+
+*/
+
+#include "emu.h"
+#include "panasonic08r.h"
+
+
+DEFINE_DEVICE_TYPE(MSX_SLOT_PANASONIC08R, msx_slot_panasonic08r_device, "msx_slot_panasonic08r", "MSX Internal Panasonic08r")
+
+
+msx_slot_panasonic08r_device::msx_slot_panasonic08r_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock)
+ : device_t(mconfig, MSX_SLOT_PANASONIC08R, tag, owner, clock)
+ , msx_internal_slot_interface(mconfig, *this)
+ , m_sram_size(0)
+ , 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"}, {*this, "view6"}, {*this, "view7"}
+ }
+ , m_mm(*this, finder_base::DUMMY_TAG)
+ , m_region_offset(0)
+ , m_control(0)
+{
+}
+
+
+void msx_slot_panasonic08r_device::device_add_mconfig(machine_config &config)
+{
+ NVRAM(config, m_nvram, nvram_device::DEFAULT_ALL_0);
+}
+
+
+void msx_slot_panasonic08r_device::device_start()
+{
+ // Sanity checks
+ if (m_rom_region->bytes() < m_region_offset + 0x400000)
+ fatalerror("Memory region '%s' is too small for the panasonic08r firmware\n", m_rom_region.finder_tag());
+ if (m_sram_size != 0x4000 && m_sram_size != 0x8000)
+ fatalerror("Invalid SRAM size for the panasonic08r firmware\n");
+
+ m_sram = std::make_unique<u8[]>(m_sram_size);
+ m_nvram->set_base(&m_sram[0], m_sram_size);
+
+ save_item(NAME(m_selected_bank));
+ save_item(NAME(m_control));
+ save_item(NAME(m_bank9));
+ save_pointer(NAME(m_sram), m_sram_size);
+
+ for (int i = 0; i < 8; i++)
+ {
+ m_bank[i]->configure_entries(0, 0x200, m_rom_region->base() + m_region_offset, 0x2000);
+ m_bank[i]->configure_entry(0x80, &m_sram[0]);
+ m_bank[i]->configure_entry(0x81, &m_sram[0x2000]);
+ if (m_sram_size >= 0x8000)
+ {
+ m_bank[i]->configure_entry(0x82, &m_sram[0x4000]);
+ m_bank[i]->configure_entry(0x83, &m_sram[0x6000]);
+ }
+
+ // Assuming smaller internal RAM is mirrored.
+ int internal_ram_banks = m_mm->get_ram_size() / 0x2000;
+ int start_bank = 0x180;
+ do {
+ int nr_banks = internal_ram_banks;
+ if (start_bank + nr_banks > 0x200)
+ nr_banks = 0x200 - start_bank;
+ m_bank[i]->configure_entries(start_bank, nr_banks, m_mm->get_ram_base(), 0x2000);
+ start_bank += internal_ram_banks;
+ }
+ while (start_bank < 0x200);
+ }
+
+ for (int i = 0; i < 8; i++)
+ {
+ const u16 start = 0x2000 * i;
+ const u16 end = start + 0x1fff;
+
+ page(i/2)->install_view(start, end, m_view[i]);
+ m_view[i][0].install_read_bank(start, end, m_bank[i]);
+ m_view[i][1].install_readwrite_bank(start, end, m_bank[i]);
+ }
+
+ m_view[3][2].install_read_bank(0x6000, 0x7fff, m_bank[3]);
+ m_view[3][2].install_read_handler(0x7ff0, 0x7ff7, read8sm_delegate(*this, [this] (offs_t offset) { return m_selected_bank[offset] & 0xff; }, "bank_r"));
+ m_view[3][3].install_readwrite_bank(0x6000, 0x7fff, m_bank[3]);
+ m_view[3][3].install_read_handler(0x7ff0, 0x7ff7, read8sm_delegate(*this, [this] (offs_t offset) { return m_selected_bank[offset] & 0xff; }, "bank_r"));
+ page(1)->install_write_handler(0x6000, 0x6000, emu::rw_delegate(*this, FUNC(msx_slot_panasonic08r_device::bank_w<0>)));
+ page(1)->install_write_handler(0x6400, 0x6400, emu::rw_delegate(*this, FUNC(msx_slot_panasonic08r_device::bank_w<1>)));
+ page(1)->install_write_handler(0x6800, 0x6800, emu::rw_delegate(*this, FUNC(msx_slot_panasonic08r_device::bank_w<2>)));
+ page(1)->install_write_handler(0x6c00, 0x6c00, emu::rw_delegate(*this, FUNC(msx_slot_panasonic08r_device::bank_w<3>)));
+ page(1)->install_write_handler(0x7000, 0x7000, emu::rw_delegate(*this, FUNC(msx_slot_panasonic08r_device::bank_w<4>)));
+ page(1)->install_write_handler(0x7400, 0x7400, emu::rw_delegate(*this, FUNC(msx_slot_panasonic08r_device::bank_w<6>)));
+ page(1)->install_write_handler(0x7800, 0x7800, emu::rw_delegate(*this, FUNC(msx_slot_panasonic08r_device::bank_w<5>)));
+ page(1)->install_write_handler(0x7c00, 0x7c00, emu::rw_delegate(*this, FUNC(msx_slot_panasonic08r_device::bank_w<7>)));
+ page(1)->install_readwrite_handler(0x7ff8, 0x7ff8,
+ read8smo_delegate(*this, [this] () { return m_bank9; }, "bank9_r"),
+ write8smo_delegate(*this, [this] (u8 data)
+ {
+ m_bank9 = data;
+ select_banks();
+ }, "bank9_w"));
+ page(1)->install_write_handler(0x7ff9, 0x7ff9, write8smo_delegate(*this, [this] (u8 data)
+ {
+ m_control = data;
+ select_banks();
+ }, "control_w"
+ ));
+}
+
+
+void msx_slot_panasonic08r_device::device_reset()
+{
+ m_control = 0;
+ m_bank9 = 0;
+ for (int i = 0 ; i < 8; i++)
+ {
+ m_selected_bank[i] = 0;
+ m_bank[i]->set_entry(0);
+ m_view[i].select(0);
+ }
+}
+
+
+template <int Bank>
+void msx_slot_panasonic08r_device::set_view()
+{
+ const bool sram_active = (m_selected_bank[Bank] >= 0x80 && m_selected_bank[Bank] < 0x84);
+ const bool ram_active = (m_selected_bank[Bank] >= 0x180);
+ const int view = ((sram_active || ram_active) ? 1 : 0) | ((Bank == 3 && BIT(m_control, 2)) ? 2 : 0);
+
+ m_view[Bank].select(view);
+}
+
+
+template <int Bank>
+void msx_slot_panasonic08r_device::bank_w(u8 data)
+{
+ u16 bank = data;
+
+ if (BIT(m_control, 4))
+ bank |= (BIT(m_bank9, Bank) << 8);
+ m_selected_bank[Bank] = bank;
+ m_bank[Bank]->set_entry(bank);
+ set_view<Bank>();
+}
+
+
+void msx_slot_panasonic08r_device::select_banks()
+{
+ bank_w<0>(m_selected_bank[0]);
+ bank_w<1>(m_selected_bank[1]);
+ bank_w<2>(m_selected_bank[2]);
+ bank_w<3>(m_selected_bank[3]);
+ bank_w<4>(m_selected_bank[4]);
+ bank_w<5>(m_selected_bank[5]);
+ bank_w<6>(m_selected_bank[6]);
+ bank_w<7>(m_selected_bank[7]);
+}
diff --git a/src/devices/bus/msx/slot/panasonic08r.h b/src/devices/bus/msx/slot/panasonic08r.h
new file mode 100644
index 00000000000..9e16d9f5501
--- /dev/null
+++ b/src/devices/bus/msx/slot/panasonic08r.h
@@ -0,0 +1,52 @@
+// license:BSD-3-Clause
+// copyright-holders:Wilbert Pol
+#ifndef MAME_BUS_MSX_SLOT_PANASONIC08R_H
+#define MAME_BUS_MSX_SLOT_PANASONIC08R_H
+
+#pragma once
+
+#include "ram_mm.h"
+#include "slot.h"
+#include "machine/nvram.h"
+
+
+DECLARE_DEVICE_TYPE(MSX_SLOT_PANASONIC08R, msx_slot_panasonic08r_device)
+
+
+class msx_slot_panasonic08r_device : public device_t, public msx_internal_slot_interface
+{
+public:
+ msx_slot_panasonic08r_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock);
+
+ // configuration helpers
+ template <typename T> msx_slot_panasonic08r_device &set_mm_tag(T &&tag) { m_mm.set_tag(std::forward<T>(tag)); return *this; }
+ void set_rom_start(const char *region, u32 offset) { m_rom_region.set_tag(region); m_region_offset = offset; }
+ msx_slot_panasonic08r_device &set_sram_size(u16 size) { m_sram_size = size; return *this; }
+
+protected:
+ 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;
+
+private:
+ template <int Bank> void set_view();
+ template <int Bank> void bank_w(u8 data);
+
+ void select_banks();
+
+ u16 m_sram_size;
+ required_device<nvram_device> m_nvram;
+ required_memory_region m_rom_region;
+ memory_bank_array_creator<8> m_bank;
+ memory_view m_view[8];
+ required_device<msx_slot_ram_mm_device> m_mm;
+ u32 m_region_offset;
+ u16 m_selected_bank[8];
+ u8 m_control;
+ u8 m_bank9;
+ std::unique_ptr<u8[]> m_sram;
+};
+
+
+#endif // MAME_BUS_MSX_SLOT_PANASONIC08R_H
diff --git a/src/devices/bus/msx/slot/ram.cpp b/src/devices/bus/msx/slot/ram.cpp
new file mode 100644
index 00000000000..03219dbf824
--- /dev/null
+++ b/src/devices/bus/msx/slot/ram.cpp
@@ -0,0 +1,31 @@
+// license:BSD-3-Clause
+// copyright-holders:Wilbert Pol
+
+#include "emu.h"
+#include "ram.h"
+
+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, u32 clock)
+ : device_t(mconfig, MSX_SLOT_RAM, tag, owner, clock)
+ , msx_internal_slot_interface(mconfig, *this)
+{
+}
+
+void msx_slot_ram_device::device_start()
+{
+ if (m_size < m_end_address - m_start_address)
+ fatalerror("Invalid size %04x for address range %004x - %04x\n", m_start_address, m_end_address);
+
+ m_ram = std::make_unique<u8[]>(m_size);
+ save_pointer(NAME(m_ram), m_size);
+
+ u8 *ram = &m_ram[0];
+ u32 start_address = m_start_address;
+ for (int i = m_start_address >> 14; i < 4 && i * 0x4000 < m_end_address; i++)
+ {
+ 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..faf428c71a7 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;
+ virtual void device_start() override ATTR_COLD;
private:
- std::vector<uint8_t> m_ram;
+ std::unique_ptr<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..bd0de812474
--- /dev/null
+++ b/src/devices/bus/msx/slot/ram_mm.cpp
@@ -0,0 +1,59 @@
+// 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 = std::make_unique<u8[]>(m_total_size);
+ save_pointer(NAME(m_ram), m_total_size);
+
+ // 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[0], 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..4002e6928ea
--- /dev/null
+++ b/src/devices/bus/msx/slot/ram_mm.h
@@ -0,0 +1,38 @@
+// 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; }
+
+ // Backdoor for the Turbo-R firmware/internal mapper to access internal RAM.
+ u32 get_ram_size() { return m_total_size; }
+ u8 *get_ram_base() { return &m_ram[0]; }
+
+protected:
+ virtual void device_start() override ATTR_COLD;
+
+private:
+ u8 read_mapper_bank(offs_t offset);
+ void write_mapper_bank(offs_t offset, u8 data);
+
+ std::unique_ptr<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..95fff321424 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;
+ virtual void device_start() override ATTR_COLD;
+ 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..29fd07cca93
--- /dev/null
+++ b/src/devices/bus/msx/slot/sony08.cpp
@@ -0,0 +1,89 @@
+// 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= std::make_unique<u8[]>(SRAM_SIZE);
+ m_nvram->set_base(&m_sram[0], SRAM_SIZE);
+
+ save_pointer(NAME(m_sram), 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[0]);
+
+ 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..279783db929 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_add_mconfig(machine_config &config) override;
+ virtual void device_start() override ATTR_COLD;
+ virtual void device_reset() override ATTR_COLD;
- void restore_banks();
+ virtual void device_add_mconfig(machine_config &config) override ATTR_COLD;
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::unique_ptr<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 406ec8f4de3..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(FUNC(msx_cart_arc_device::io_7f_w), this));
- io_space().install_read_handler(0x7f, 0x7f, read8smo_delegate(FUNC(msx_cart_arc_device::io_7f_r), this));
-}
-
-
-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 3a3af30d191..00000000000
--- a/src/devices/bus/msx_cart/cartridge.cpp
+++ /dev/null
@@ -1,128 +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 "fmpac.h"
-#include "fs_sr022.h"
-#include "halnote.h"
-#include "hfox.h"
-#include "holy_quran.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("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("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_slot_card_interface(mconfig, device)
- , 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 529d2f0a081..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_slot_card_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 7bbbdd292c0..00000000000
--- a/src/devices/bus/msx_cart/disk.cpp
+++ /dev/null
@@ -1,611 +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.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")
-
-
-FLOPPY_FORMATS_MEMBER( msx_cart_disk_device::floppy_formats )
- FLOPPY_MSX_FORMAT
-FLOPPY_FORMATS_END
-
-
-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 ce238992349..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;
-
- DECLARE_FLOPPY_FORMATS(floppy_formats);
-};
-
-
-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/fmpac.cpp b/src/devices/bus/msx_cart/fmpac.cpp
deleted file mode 100644
index a5229a6c61e..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(FUNC(msx_cart_fmpac_device::write_ym2413), this));
-}
-
-
-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 a0f660b1620..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/ym2413.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 181d9710fcc..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 - Harry 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("rtype: 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/konami.cpp b/src/devices/bus/msx_cart/konami.cpp
deleted file mode 100644
index f5ac42be362..00000000000
--- a/src/devices/bus/msx_cart/konami.cpp
+++ /dev/null
@@ -1,948 +0,0 @@
-// license:BSD-3-Clause
-// copyright-holders:Wilbert Pol
-#include "emu.h"
-#include "konami.h"
-
-#include "sound/volt_reg.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/2).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
- voltage_regulator_device &vref(VOLTAGE_REGULATOR(config, "vref"));
- vref.add_route(0, "dac", 1.0, DAC_VREF_POS_INPUT);
- vref.add_route(0, "dac", -1.0, DAC_VREF_NEG_INPUT);
-}
-
-
-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/2).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(FUNC(vlm5030_device::data_w), m_vlm5030.target()));
- io_space().install_write_handler(0x20, 0x20, write8smo_delegate(FUNC(msx_cart_keyboard_master_device::io_20_w), this));
- io_space().install_read_handler(0x00, 0x00, read8smo_delegate(FUNC(msx_cart_keyboard_master_device::io_00_r), this));
-}
-
-
-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 1906a5eb51b..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(FUNC(msx_cart_korean_90in1_device::banking), this));
-}
-
-
-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 66efee9188f..00000000000
--- a/src/devices/bus/msx_cart/majutsushi.cpp
+++ /dev/null
@@ -1,120 +0,0 @@
-// license:BSD-3-Clause
-// copyright-holders:Wilbert Pol
-#include "emu.h"
-#include "majutsushi.h"
-
-#include "sound/volt_reg.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
- voltage_regulator_device &vref(VOLTAGE_REGULATOR(config, "vref"));
- vref.add_route(0, "dac", 1.0, DAC_VREF_POS_INPUT);
- vref.add_route(0, "dac", -1.0, DAC_VREF_NEG_INPUT);
-}
-
-
-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.cpp b/src/devices/bus/msx_cart/moonsound.cpp
deleted file mode 100644
index afdb3c039eb..00000000000
--- a/src/devices/bus/msx_cart/moonsound.cpp
+++ /dev/null
@@ -1,125 +0,0 @@
-// license:BSD-3-Clause
-// copyright-holders:Wilbert Pol
-/**********************************************************************************
-
-TODO:
-- Properly hook up correct SRAM sizes for different moonsound compatible
- cartridges. (Original moonsound has 128KB SRAM)
-
-**********************************************************************************/
-
-#include "emu.h"
-#include "moonsound.h"
-
-#include "speaker.h"
-
-
-#define VERBOSE 0
-#include "logmacro.h"
-
-
-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")
-{
-}
-
-
-void msx_cart_moonsound_device::ymf278b_map(address_map &map)
-{
- map(0x000000, 0x1fffff).rom();
- 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.
- SPEAKER(config, "lspeaker").front_left();
- SPEAKER(config, "rspeaker").front_right();
-
- YMF278B(config, m_ymf278b, 33.8688_MHz_XTAL);
- m_ymf278b->set_addrmap(0, &msx_cart_moonsound_device::ymf278b_map);
- m_ymf278b->irq_handler().set(FUNC(msx_cart_moonsound_device::irq_w));
- m_ymf278b->add_route(0, "lspeaker", 0.50);
- m_ymf278b->add_route(1, "rspeaker", 0.50);
- m_ymf278b->add_route(2, "lspeaker", 0.50);
- m_ymf278b->add_route(3, "rspeaker", 0.50);
- m_ymf278b->add_route(4, "lspeaker", 0.40);
- m_ymf278b->add_route(5, "rspeaker", 0.40);
- m_ymf278b->add_route(6, "lspeaker", 0.40);
- m_ymf278b->add_route(7, "rspeaker", 0.40);
-}
-
-
-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 );
-}
-
-
-void msx_cart_moonsound_device::device_start()
-{
- // Install IO read/write handlers
- io_space().install_readwrite_handler(0x7e, 0x7f, read8sm_delegate(FUNC(msx_cart_moonsound_device::read_ymf278b_pcm), this), write8sm_delegate(FUNC(msx_cart_moonsound_device::write_ymf278b_pcm), this));
- io_space().install_readwrite_handler(0xc4, 0xc7, read8sm_delegate(FUNC(msx_cart_moonsound_device::read_ymf278b_fm), this), write8sm_delegate(FUNC(msx_cart_moonsound_device::write_ymf278b_fm), this));
- io_space().install_read_handler(0xc0, 0xc0, read8smo_delegate(FUNC(msx_cart_moonsound_device::read_c0), this));
-}
-
-
-void msx_cart_moonsound_device::device_reset()
-{
-}
-
-
-WRITE_LINE_MEMBER(msx_cart_moonsound_device::irq_w)
-{
- 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)
-{
- 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)
-{
- 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()
-{
- LOG("moonsound: read 0xc0\n");
- return 0x00;
-}
diff --git a/src/devices/bus/msx_cart/moonsound.h b/src/devices/bus/msx_cart/moonsound.h
deleted file mode 100644
index ca30dfb5c35..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/ymf278b.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 679c035b014..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(FUNC(y8950_device::write), m_y8950.target()));
- io_space().install_read_handler(0xc0, 0xc1, read8sm_delegate(FUNC(y8950_device::read), m_y8950.target()));
-}
-
-
-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().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(FUNC(y8950_device::write), m_y8950.target()));
- io_space().install_read_handler(0xc0, 0xc1, read8sm_delegate(FUNC(y8950_device::read), m_y8950.target()));
- io_space().install_write_handler(0x00, 0x01, write8sm_delegate(FUNC(acia6850_device::write), m_acia6850.target()));
- io_space().install_read_handler(0x04, 0x05, read8sm_delegate(FUNC(acia6850_device::read), m_acia6850.target()));
-}
-
-
-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(FUNC(msx_cart_msx_audio_fsca1_device::write_y8950), this));
- io_space().install_read_handler(0xc0, 0xc3, read8sm_delegate(FUNC(msx_cart_msx_audio_fsca1_device::read_y8950), this));
-}
-
-
-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 3aeee7cddf1..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/8950intf.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 a64b0648195..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("rtype: 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 b846a935953..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(FUNC(msx_cart_superloderunner_device::banking), this));
-}
-
-
-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 c7a33a7e4c7..00000000000
--- a/src/devices/bus/msx_cart/yamaha.cpp
+++ /dev/null
@@ -1,204 +0,0 @@
-// license:BSD-3-Clause
-// copyright-holders:Wilbert Pol
-/**************************************************************************
-
-Yamaha SFG01/SFG05 emulation
-
-TODO:
-- Use a real YM2164 implementation for SFG05
-
-**************************************************************************/
-
-#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(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
- m_ym2151->irq_handler().set(FUNC(msx_cart_sfg_device::ym2151_irq_w));
- m_ym2151->add_route(0, "lspeaker", 0.80);
- m_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));
-}
-
-
-ROM_START( msx_sfg01 )
- ROM_REGION(0x4000, "sfg", 0)
- ROM_LOAD("sfg01.rom", 0x0, 0x4000, CRC(0995fb36) SHA1(434651305f92aa770a89e40b81125fb22d91603d))
-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) )
- 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) )
-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(device_irq_acknowledge_delegate(FUNC(msx_cart_sfg_device::irq_callback),this));
-}
-
-
-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->status_r();
-
- 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
- m_ym2151->register_w(data);
- break;
-
- case 0x3ff1: // YM-2151 data
- m_ym2151->data_w(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 e5072dc5dcf..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/ym2151.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);
-
-private:
- DECLARE_WRITE_LINE_MEMBER(ym2151_irq_w);
- DECLARE_WRITE_LINE_MEMBER(ym2148_irq_w);
-
- required_memory_region m_region_sfg;
- required_device<ym2151_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 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 87b89f93c78..00000000000
--- a/src/devices/bus/msx_slot/cartridge.cpp
+++ /dev/null
@@ -1,370 +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_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";
- uint32_t length = hook.image_file()->size();
- std::vector<uint8_t> rom(length);
- 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
- hook.image_file()->read(&rom[0], length);
- 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 faabf394042..00000000000
--- a/src/devices/bus/msx_slot/cartridge.h
+++ /dev/null
@@ -1,82 +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 "softlist_dev.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_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 const software_list_loader &get_software_list_loader() const override { return rom_software_list_loader::instance(); }
- virtual iodevice_t image_type() const override { return IO_CARTSLOT; }
- virtual bool is_readable() const override { return true; }
- virtual bool is_writeable() const override { return false; }
- virtual bool is_creatable() const override { return false; }
- virtual bool must_be_loaded() const override { return false; }
- virtual bool is_reset_on_load() const override { return true; }
- virtual const char *image_interface() const override { return "msx_cart"; }
- virtual const char *file_extensions() const override { return "mx1,bin,rom"; }
- virtual const char *custom_instance_name() const override { return "cartridge"; }
- virtual const char *custom_brief_instance_name() const override { return "cart"; }
-
- // 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 override { return "msx_yamaha_60pin"; }
- virtual const char *custom_instance_name() const override { return "cartridge60pin"; }
- virtual const char *custom_brief_instance_name() const 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 309b7f2d80f..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(FUNC(msx_slot_disk5_device::io_write), this));
- io_space().install_read_handler(0xd0, 0xd4, read8sm_delegate(FUNC(msx_slot_disk5_device::io_read), this));
-}
-
-
-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 a7470fc2a78..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 0e3ae00b0f3..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(FUNC(msx_slot_music_device::write_ym2413), this));
-}
-
-
-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/music.h b/src/devices/bus/msx_slot/music.h
deleted file mode 100644
index 385e568c4e5..00000000000
--- a/src/devices/bus/msx_slot/music.h
+++ /dev/null
@@ -1,37 +0,0 @@
-// license:BSD-3-Clause
-// copyright-holders:Wilbert Pol
-#ifndef MAME_BUS_MSX_SLOT_MUSIC_H
-#define MAME_BUS_MSX_SLOT_MUSIC_H
-
-#pragma once
-
-#include "bus/msx_slot/slot.h"
-#include "bus/msx_slot/rom.h"
-#include "sound/ym2413.h"
-
-
-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);
-
- // configuration helpers
- void set_ym2413_tag(const char *tag) { m_ym2413_tag = tag; }
-
- virtual uint8_t read(offs_t offset) override;
-
-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;
-};
-
-
-#endif // MAME_BUS_MSX_SLOT_MUSIC_H
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.cpp b/src/devices/bus/msx_slot/ram.cpp
deleted file mode 100644
index 835a5551b92..00000000000
--- a/src/devices/bus/msx_slot/ram.cpp
+++ /dev/null
@@ -1,36 +0,0 @@
-// license:BSD-3-Clause
-// copyright-holders:Wilbert Pol
-
-#include "emu.h"
-#include "ram.h"
-
-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)
- : device_t(mconfig, MSX_SLOT_RAM, tag, owner, clock)
- , msx_internal_slot_interface(mconfig, *this)
-{
-}
-
-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 )
- {
- m_ram[offset - m_start_address] = data;
- }
-}
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 ade67f6eb66..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(FUNC(msx_slot_ram_mm_device::read_mapper_bank), this));
- io_space().install_write_handler(0xFC, 0xFF, write8sm_delegate(FUNC(msx_slot_ram_mm_device::write_mapper_bank), this));
-}
-
-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..a7b09bebeeb
--- /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_BOARD_H
+#define MAME_BUS_MTU130_BOARD_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 ATTR_COLD;
+};
+
+DECLARE_DEVICE_TYPE(MTU130_EXTENSION, mtu130_extension_device)
+
+#endif // MAME_BUS_MTU130_BOARD_H
diff --git a/src/devices/bus/mtu130/datamover.cpp b/src/devices/bus/mtu130/datamover.cpp
new file mode 100644
index 00000000000..f8ae08da903
--- /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_line_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..eaf64402d1f
--- /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 ATTR_COLD;
+ virtual void device_reset() override ATTR_COLD;
+
+protected:
+ virtual void device_add_mconfig(machine_config &config) override ATTR_COLD;
+
+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) ATTR_COLD;
+ void m68k_map(address_map &map) ATTR_COLD;
+ void m68k_cs_map(address_map &map) ATTR_COLD;
+
+ 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
new file mode 100644
index 00000000000..a0c75ec89ca
--- /dev/null
+++ b/src/devices/bus/mtx/cfx.cpp
@@ -0,0 +1,152 @@
+// license:BSD-3-Clause
+// copyright-holders:Nigel Barnes
+/**********************************************************************
+
+ Memotech Compact Flash System
+
+**********************************************************************/
+
+
+#include "emu.h"
+#include "cfx.h"
+
+
+//**************************************************************************
+// DEVICE DEFINITIONS
+//**************************************************************************
+
+DEFINE_DEVICE_TYPE(MTX_CFX, mtx_cfx_device, "mtx_cfx", "MTX CFX System")
+
+
+//-------------------------------------------------
+// ROM( cfx )
+//-------------------------------------------------
+
+ROM_START( cfx )
+ ROM_REGION(0x4000, "flash", ROMREGION_ERASE00) // SST39SF010
+ ROM_SYSTEM_BIOS(0, "153", "CFX Duo 15 (Build 153, 02 April 2018)")
+ ROMX_LOAD("cfx015-b153,280.bin", 0x0000, 0x3afc, CRC(77b31543) SHA1(3973016bbbd36ac958915e187f26816ec431ef87), ROM_BIOS(0))
+ ROM_SYSTEM_BIOS(1, "151", "CFX Duo 15 (Build 151, 03 December 2017)")
+ ROMX_LOAD("cfx015-b151.bin", 0x0000, 0x3afc, CRC(4c7366c7) SHA1(33a7f503a84602aaf93ba61f55a3e4d5dbb223ce), ROM_BIOS(1))
+ ROM_SYSTEM_BIOS(2, "147", "CFX Duo 14 (Build 147, 28 December 2016)")
+ ROMX_LOAD("cfx014-b147,512.bin", 0x0000, 0x3afc, CRC(ef9d0e1f) SHA1(b6e5ba79f804f509f0d028f00d5972e07e2cb9cf), ROM_BIOS(2))
+ ROM_SYSTEM_BIOS(3, "144", "CFX Duo 14 (Build 144, 17 October 2015)")
+ ROMX_LOAD("cfx0014,512.bin", 0x0000, 0x3a3f, CRC(23ab4f0e) SHA1(e01874ba5392518be2313fb3161bcef6a72c9662), ROM_BIOS(3))
+ ROM_SYSTEM_BIOS(4, "132", "CFX Duo 13 (Build 132, 11 October 2015)")
+ ROMX_LOAD("cfx013,512.bin", 0x0000, 0x3c31, CRC(2d1c4ebc) SHA1(5f894bdc9fc20d37d11a2771b8e8fbcacd3f938e), ROM_BIOS(4))
+ ROM_SYSTEM_BIOS(5, "103", "CFX Duo 12 (Build 103, 21 August 2015)")
+ ROMX_LOAD("cfx_duo12.bin", 0x0000, 0x4000, CRC(4fbe5ab7) SHA1(3e8dcc3d88158e0dc30d7d9ecec7e427883f7171), ROM_BIOS(5))
+ROM_END
+
+
+//-------------------------------------------------
+// device_add_mconfig - add device configuration
+//-------------------------------------------------
+
+void mtx_cfx_device::device_add_mconfig(machine_config &config)
+{
+ I8255(config, m_pia);
+ m_pia->in_pa_callback().set([this]() { return m_ide_data & 0xff; });
+ m_pia->out_pa_callback().set([this](uint8_t data) { m_ide_data = (m_ide_data & 0xff00) | data; });
+ m_pia->in_pb_callback().set([this]() { return m_ide_data >> 8; });
+ 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, "cf", nullptr, false);
+}
+
+
+const tiny_rom_entry *mtx_cfx_device::device_rom_region() const
+{
+ return ROM_NAME( cfx );
+}
+
+
+//**************************************************************************
+// LIVE DEVICE
+//**************************************************************************
+
+//-------------------------------------------------
+// mtx_cfx_device - constructor
+//-------------------------------------------------
+
+mtx_cfx_device::mtx_cfx_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
+ : device_t(mconfig, MTX_CFX, tag, owner, clock)
+ , device_mtx_exp_interface(mconfig, *this)
+ , m_flash(*this, "flash")
+ , m_pia(*this, "pia")
+ , m_ide(*this, "ide")
+ , m_ide_data(0)
+{
+}
+
+
+//-------------------------------------------------
+// device_start - device-specific startup
+//-------------------------------------------------
+
+void mtx_cfx_device::device_start()
+{
+ save_item(NAME(m_ide_data));
+}
+
+
+//-------------------------------------------------
+// device_reset - device-specific reset
+//-------------------------------------------------
+
+void mtx_cfx_device::device_reset()
+{
+ machine().root_device().membank("rommap_bank1")->configure_entries(4, 2, m_flash->base(), 0x2000);
+
+ io_space().install_readwrite_handler(0x6c, 0x6f, read8sm_delegate(*m_pia, FUNC(i8255_device::read)), write8sm_delegate(*m_pia, FUNC(i8255_device::write)));
+}
+
+
+//**************************************************************************
+// IMPLEMENTATION
+//**************************************************************************
+
+void mtx_cfx_device::portc_w(uint8_t data)
+{
+ /*
+ b0 A0
+ b1 A1
+ b2 A2
+ b3 CS0
+ b4 CS1
+ b5 WRITE
+ b6 READ
+ b7 RESET
+ */
+
+ if (BIT(data, 7))
+ m_ide->reset();
+
+ switch (BIT(data, 3, 2))
+ {
+ case 0x01: // CS0
+ switch (BIT(data, 5, 2))
+ {
+ case 0x01: // WRITE
+ m_ide->cs0_w(data & 0x07, m_ide_data);
+ break;
+ case 0x02: // READ
+ m_ide_data = m_ide->cs0_r(data & 0x07);
+ break;
+ }
+ break;
+
+ case 0x02: // CS1
+ switch (BIT(data, 5, 2))
+ {
+ case 0x01: // WRITE
+ m_ide->cs1_w(data & 0x07, m_ide_data);
+ break;
+ case 0x02: // READ
+ m_ide_data = m_ide->cs1_r(data & 0x07);
+ break;
+ }
+ break;
+ }
+}
diff --git a/src/devices/bus/mtx/cfx.h b/src/devices/bus/mtx/cfx.h
new file mode 100644
index 00000000000..cf7562ed1f2
--- /dev/null
+++ b/src/devices/bus/mtx/cfx.h
@@ -0,0 +1,51 @@
+// license:BSD-3-Clause
+// copyright-holders:Nigel Barnes
+/**********************************************************************
+
+ Memotech Compact Flash System
+
+**********************************************************************/
+
+
+#ifndef MAME_BUS_MTX_CFX_H
+#define MAME_BUS_MTX_CFX_H
+
+#include "exp.h"
+#include "machine/i8255.h"
+#include "bus/ata/ataintf.h"
+
+
+//**************************************************************************
+// TYPE DEFINITIONS
+//**************************************************************************
+
+class mtx_cfx_device : public device_t, public device_mtx_exp_interface
+{
+public:
+ // construction/destruction
+ mtx_cfx_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 ATTR_COLD;
+ virtual const tiny_rom_entry *device_rom_region() const override ATTR_COLD;
+
+ // device-level overrides
+ virtual void device_start() override ATTR_COLD;
+ virtual void device_reset() override ATTR_COLD;
+
+private:
+ required_memory_region m_flash;
+ required_device<i8255_device> m_pia;
+ required_device<ata_interface_device> m_ide;
+
+ uint16_t m_ide_data;
+
+ void portc_w(uint8_t data);
+};
+
+
+// device type definition
+DECLARE_DEVICE_TYPE(MTX_CFX, mtx_cfx_device)
+
+#endif // MAME_BUS_MTX_CFX_H
diff --git a/src/devices/bus/mtx/exp.cpp b/src/devices/bus/mtx/exp.cpp
index 1bfd5068679..3a8a5f64801 100644
--- a/src/devices/bus/mtx/exp.cpp
+++ b/src/devices/bus/mtx/exp.cpp
@@ -26,12 +26,28 @@ DEFINE_DEVICE_TYPE(MTX_EXP_SLOT, mtx_exp_slot_device, "mtx_exp_slot", "MTX expan
//-------------------------------------------------
device_mtx_exp_interface::device_mtx_exp_interface(const machine_config &mconfig, device_t &device)
- : device_slot_card_interface(mconfig, device)
+ : device_interface(device, "mtxexp")
+ , m_rom(nullptr)
+ , m_rom_size(0)
{
m_slot = dynamic_cast<mtx_exp_slot_device *>(device.owner());
}
+//-------------------------------------------------
+// rom_alloc - alloc the space for the ROM
+//-------------------------------------------------
+
+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"), size, 1, ENDIANNESS_LITTLE)->base();
+ m_rom_size = size;
+ }
+}
+
+
//**************************************************************************
// LIVE DEVICE
//**************************************************************************
@@ -42,52 +58,76 @@ device_mtx_exp_interface::device_mtx_exp_interface(const machine_config &mconfig
mtx_exp_slot_device::mtx_exp_slot_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
: device_t(mconfig, MTX_EXP_SLOT, tag, owner, clock)
- , device_slot_interface(mconfig, *this)
+ , device_single_card_slot_interface<device_mtx_exp_interface>(mconfig, *this)
+ , device_cartrom_image_interface(mconfig, *this)
, m_program(*this, finder_base::DUMMY_TAG, -1)
, m_io(*this, finder_base::DUMMY_TAG, -1)
- , m_card(nullptr)
, m_busreq_handler(*this)
, m_int_handler(*this)
, m_nmi_handler(*this)
+ , m_card(nullptr)
{
}
//-------------------------------------------------
-// device_validity_check -
+// device_start - device-specific startup
//-------------------------------------------------
-void mtx_exp_slot_device::device_validity_check(validity_checker &valid) const
+void mtx_exp_slot_device::device_start()
{
- device_t *const carddev = get_card_device();
- if (carddev && !dynamic_cast<device_mtx_exp_interface *>(carddev))
- osd_printf_error("Card device %s (%s) does not implement device_mtx_exp_interface\n", carddev->tag(), carddev->name());
+ m_card = get_card_device();
}
//-------------------------------------------------
-// device_start - device-specific startup
+// call_load
//-------------------------------------------------
-void mtx_exp_slot_device::device_start()
+std::pair<std::error_condition, std::string> mtx_exp_slot_device::call_load()
{
- device_t *const carddev = get_card_device();
- if (carddev && !dynamic_cast<device_mtx_exp_interface *>(carddev))
- osd_printf_error("Card device %s (%s) does not implement device_mtx_exp_interface\n", carddev->tag(), carddev->name());
-
- // resolve callbacks
- m_busreq_handler.resolve_safe();
- m_int_handler.resolve_safe();
- m_nmi_handler.resolve_safe();
+ if (m_card)
+ {
+ uint32_t const size = !loaded_through_softlist() ? length() : get_software_region_length("rom");
+
+ if (size % 0x2000)
+ return std::make_pair(image_error::INVALIDLENGTH, "Unsupported cartridge size (must be a multiple of 8K)");
+
+ m_card->rom_alloc(size, tag());
+
+ if (!loaded_through_softlist())
+ fread(m_card->get_rom_base(), size);
+ else
+ memcpy(m_card->get_rom_base(), get_software_region("rom"), size);
+ }
+
+ return std::make_pair(std::error_condition(), std::string());
}
//-------------------------------------------------
-// device_reset - device-specific reset
+// get_default_card_software -
//-------------------------------------------------
-void mtx_exp_slot_device::device_reset()
+std::string mtx_exp_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
+
+ if (len == 0x80000)
+ return software_get_default_slot("magrom");
+ }
+
+ return software_get_default_slot("rompak");
+}
+
+
+void mtx_exp_slot_device::bankswitch(uint8_t data)
{
+ if (m_card)
+ m_card->bankswitch(data);
}
@@ -97,13 +137,25 @@ void mtx_exp_slot_device::device_reset()
// slot devices
+#include "cfx.h"
//#include "fdx.h"
+#include "magrom.h"
+#include "rompak.h"
#include "sdx.h"
-void mtx_expansion_devices(device_slot_interface &device)
+void mtx_int_expansion_devices(device_slot_interface &device)
{
+ device.option_add("cfx", MTX_CFX);
//device.option_add("fdx", MTX_FDX); /* FDX Floppy Disc System */
- device.option_add("sdxbas", MTX_SDXBAS); /* SDX Floppy Disc System (SDX ROM)*/
+ device.option_add_internal("magrom", MTX_MAGROM);
device.option_add("sdxcpm", MTX_SDXCPM); /* SDX Floppy Disc System (CP/M ROM and 80 column card) */
}
+
+void mtx_ext_expansion_devices(device_slot_interface &device)
+{
+ device.option_add("cfx", MTX_CFX);
+ device.option_add_internal("magrom", MTX_MAGROM);
+ device.option_add_internal("rompak", MTX_ROMPAK);
+ device.option_add("sdxbas", MTX_SDXBAS); /* SDX Floppy Disc System (SDX ROM)*/
+}
diff --git a/src/devices/bus/mtx/exp.h b/src/devices/bus/mtx/exp.h
index d4e05f2f9c9..0f180d16f4a 100644
--- a/src/devices/bus/mtx/exp.h
+++ b/src/devices/bus/mtx/exp.h
@@ -12,6 +12,8 @@
#pragma once
+#include "imagedev/cartrom.h"
+
//**************************************************************************
// TYPE DEFINITIONS
@@ -21,8 +23,9 @@
class device_mtx_exp_interface;
-class mtx_exp_slot_device : public device_t, public device_slot_interface
+class mtx_exp_slot_device : public device_t, public device_single_card_slot_interface<device_mtx_exp_interface>, public device_cartrom_image_interface
{
+ friend class device_mtx_exp_interface;
public:
// construction/destruction
template <typename T>
@@ -45,49 +48,72 @@ public:
auto int_handler() { return m_int_handler.bind(); }
auto nmi_handler() { return m_nmi_handler.bind(); }
- 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); }
+ // for the card to use
+ 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); }
- // address spaces we are attached to
- required_address_space m_program;
- required_address_space m_io;
+ virtual void bankswitch(uint8_t data);
protected:
- // device-level overrides
- virtual void device_validity_check(validity_checker &valid) const override;
- virtual void device_start() override;
- virtual void device_reset() override;
+ // device_t implementation
+ virtual void device_start() override ATTR_COLD;
- device_mtx_exp_interface *m_card;
+ // 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"; }
+
+ // device_slot_interface implementation
+ virtual std::string get_default_card_software(get_default_card_software_hook &hook) const override;
private:
+ // address spaces we are attached to
+ required_address_space m_program;
+ required_address_space m_io;
+
devcb_write_line m_busreq_handler;
devcb_write_line m_int_handler;
devcb_write_line m_nmi_handler;
+
+ device_mtx_exp_interface *m_card;
};
// ======================> device_mtx_exp_interface
-class device_mtx_exp_interface : public device_slot_card_interface
+class device_mtx_exp_interface : public device_interface
{
public:
+ virtual void bankswitch(uint8_t data) { }
+
+ void rom_alloc(uint32_t size, const char *tag);
+ uint8_t* get_rom_base() { return m_rom; }
+ uint32_t get_rom_size() { return m_rom_size; }
+
+protected:
// construction/destruction
device_mtx_exp_interface(const machine_config &mconfig, device_t &device);
-protected:
address_space &program_space() { return *m_slot->m_program; }
address_space &io_space() { return *m_slot->m_io; }
mtx_exp_slot_device *m_slot;
+
+private:
+ // internal state
+ uint8_t *m_rom;
+ uint32_t m_rom_size;
};
// device type definition
DECLARE_DEVICE_TYPE(MTX_EXP_SLOT, mtx_exp_slot_device)
-void mtx_expansion_devices(device_slot_interface &device);
+void mtx_int_expansion_devices(device_slot_interface &device);
+void mtx_ext_expansion_devices(device_slot_interface &device);
#endif // MAME_BUS_MTX_EXP_H
diff --git a/src/devices/bus/mtx/magrom.cpp b/src/devices/bus/mtx/magrom.cpp
new file mode 100644
index 00000000000..5b75a9d4f1e
--- /dev/null
+++ b/src/devices/bus/mtx/magrom.cpp
@@ -0,0 +1,103 @@
+// license:BSD-3-Clause
+// copyright-holders:Nigel Barnes
+/**********************************************************************
+
+ Martin Allcorn's Games ROM
+
+**********************************************************************/
+
+
+#include "emu.h"
+#include "magrom.h"
+
+
+//**************************************************************************
+// DEVICE DEFINITIONS
+//**************************************************************************
+
+DEFINE_DEVICE_TYPE(MTX_MAGROM, mtx_magrom_device, "mtx_magrom", "MTX MAGROM")
+
+
+//-------------------------------------------------
+// INPUT_PORTS( magrom )
+//-------------------------------------------------
+
+INPUT_PORTS_START(magrom)
+ PORT_START("JUMPERS")
+ PORT_CONFNAME(0x03, 0x01, "System")
+ PORT_CONFSETTING(0x00, "MTX500")
+ PORT_CONFSETTING(0x01, "MTX512")
+ PORT_CONFSETTING(0x03, "RS128")
+ PORT_CONFNAME(0x04, 0x00, "ROM ID")
+ PORT_CONFSETTING(0x00, "GROM")
+ PORT_CONFSETTING(0x04, "ROM 6")
+INPUT_PORTS_END
+
+
+//-------------------------------------------------
+// input_ports - device-specific input ports
+//-------------------------------------------------
+
+ioport_constructor mtx_magrom_device::device_input_ports() const
+{
+ return INPUT_PORTS_NAME(magrom);
+}
+
+
+//**************************************************************************
+// LIVE DEVICE
+//**************************************************************************
+
+//-------------------------------------------------
+// mtx_magrom_device - constructor
+//-------------------------------------------------
+
+mtx_magrom_device::mtx_magrom_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
+ : device_t(mconfig, MTX_MAGROM, tag, owner, clock)
+ , device_mtx_exp_interface(mconfig, *this)
+ , m_bank(*this, "bank")
+ , m_jumpers(*this, "JUMPERS")
+{
+}
+
+
+//-------------------------------------------------
+// device_start - device-specific startup
+//-------------------------------------------------
+
+void mtx_magrom_device::device_start()
+{
+}
+
+
+//-------------------------------------------------
+// device_reset - device-specific reset
+//-------------------------------------------------
+
+void mtx_magrom_device::device_reset()
+{
+ m_bank->configure_entries(0, 32, get_rom_base(), 0x4000);
+
+ int rom_id = (m_jumpers->read() & 0x04) ? 6 : 7;
+ machine().root_device().membank("rommap_bank1")->configure_entry(rom_id, get_rom_base() + 0x2000);
+
+ io_space().install_write_handler(0xfb, 0xfb, write8smo_delegate(*this, FUNC(mtx_magrom_device::page_w)));
+}
+
+
+//**************************************************************************
+// IMPLEMENTATION
+//**************************************************************************
+
+void mtx_magrom_device::bankswitch(uint8_t data)
+{
+ int page = m_jumpers->read() & 0x03;
+ if (!BIT(data, 7) && BIT(data, 0, 4) == page)
+ program_space().install_read_bank(0x4000, 0x7fff, m_bank);
+}
+
+
+void mtx_magrom_device::page_w(uint8_t data)
+{
+ m_bank->set_entry(data & 0x1f);
+}
diff --git a/src/devices/bus/mtx/magrom.h b/src/devices/bus/mtx/magrom.h
new file mode 100644
index 00000000000..3569865cf53
--- /dev/null
+++ b/src/devices/bus/mtx/magrom.h
@@ -0,0 +1,50 @@
+// license:BSD-3-Clause
+// copyright-holders:Nigel Barnes
+/**********************************************************************
+
+ Martin Allcorn's Games ROM
+
+**********************************************************************/
+
+
+#ifndef MAME_BUS_MTX_MAGROM_H
+#define MAME_BUS_MTX_MAGROM_H
+
+#include "exp.h"
+
+
+//**************************************************************************
+// TYPE DEFINITIONS
+//**************************************************************************
+
+// ======================> mtx_magrom_device
+
+class mtx_magrom_device : public device_t, public device_mtx_exp_interface
+{
+public:
+ // construction/destruction
+ mtx_magrom_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
+
+protected:
+ // optional information overrides
+ virtual ioport_constructor device_input_ports() const override ATTR_COLD;
+
+ // device-level overrides
+ virtual void device_start() override ATTR_COLD;
+ virtual void device_reset() override ATTR_COLD;
+
+ virtual void bankswitch(uint8_t data) override;
+
+private:
+ memory_bank_creator m_bank;
+ required_ioport m_jumpers;
+
+ void page_w(uint8_t data);
+};
+
+
+// device type definition
+DECLARE_DEVICE_TYPE(MTX_MAGROM, mtx_magrom_device)
+
+
+#endif // MAME_BUS_MTX_MAGROM_H
diff --git a/src/devices/bus/mtx/rompak.cpp b/src/devices/bus/mtx/rompak.cpp
new file mode 100644
index 00000000000..6f870c540ce
--- /dev/null
+++ b/src/devices/bus/mtx/rompak.cpp
@@ -0,0 +1,51 @@
+// license:BSD-3-Clause
+// copyright-holders:Nigel Barnes
+/**********************************************************************
+
+ Memotech ROMPAK
+
+**********************************************************************/
+
+#include "emu.h"
+#include "rompak.h"
+
+
+//**************************************************************************
+// DEVICE DEFINITIONS
+//**************************************************************************
+
+DEFINE_DEVICE_TYPE(MTX_ROMPAK, mtx_rompak_device, "rompak", "MTX ROMPAK")
+
+
+//**************************************************************************
+// LIVE DEVICE
+//**************************************************************************
+
+//-------------------------------------------------
+// mtx_rompak_device - constructor
+//-------------------------------------------------
+
+mtx_rompak_device::mtx_rompak_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock)
+ : device_t(mconfig, MTX_ROMPAK, tag, owner, clock)
+ , device_mtx_exp_interface(mconfig, *this)
+{
+}
+
+
+//-------------------------------------------------
+// device_start - device-specific startup
+//-------------------------------------------------
+
+void mtx_rompak_device::device_start()
+{
+}
+
+
+//-------------------------------------------------
+// device_reset - device-specific reset
+//-------------------------------------------------
+
+void mtx_rompak_device::device_reset()
+{
+ machine().root_device().membank("rommap_bank1")->configure_entry(7, get_rom_base());
+}
diff --git a/src/devices/bus/mtx/rompak.h b/src/devices/bus/mtx/rompak.h
new file mode 100644
index 00000000000..8ade842c73f
--- /dev/null
+++ b/src/devices/bus/mtx/rompak.h
@@ -0,0 +1,40 @@
+// license:BSD-3-Clause
+// copyright-holders:Nigel Barnes
+/**********************************************************************
+
+ Memotech ROMPAK
+
+**********************************************************************/
+
+
+#ifndef MAME_BUS_MTX_ROMPAK_H
+#define MAME_BUS_MTX_ROMPAK_H
+
+#pragma once
+
+#include "exp.h"
+
+//**************************************************************************
+// TYPE DEFINITIONS
+//**************************************************************************
+
+// ======================> mtx_rompak_device
+
+class mtx_rompak_device : public device_t, public device_mtx_exp_interface
+{
+public:
+ // construction/destruction
+ mtx_rompak_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock);
+
+protected:
+ // device-level overrides
+ virtual void device_start() override ATTR_COLD;
+ virtual void device_reset() override ATTR_COLD;
+};
+
+
+// device type definitions
+DECLARE_DEVICE_TYPE(MTX_ROMPAK, mtx_rompak_device)
+
+
+#endif // MAME_BUS_MTX_ROMPAK_H
diff --git a/src/devices/bus/mtx/sdx.cpp b/src/devices/bus/mtx/sdx.cpp
index d34e73e7605..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
@@ -29,9 +30,11 @@ static void sdx_floppies(device_slot_interface &device)
device.option_add("525qd", FLOPPY_525_QD);
}
-FLOPPY_FORMATS_MEMBER(mtx_sdx_device::floppy_formats)
- FLOPPY_MTX_FORMAT
-FLOPPY_FORMATS_END
+void mtx_sdx_device::floppy_formats(format_registration &fr)
+{
+ fr.add_mfm_containers();
+ fr.add(FLOPPY_MTX_FORMAT);
+}
//-------------------------------------------------
// ROM( sdx )
@@ -135,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)
@@ -145,25 +148,22 @@ 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);
- m_screen->set_vblank_time(ATTOSECONDS_IN_USEC(2500)); /* not accurate */
- m_screen->set_refresh_hz(50);
- m_screen->set_size(960, 313);
- m_screen->set_visarea(00, 640 - 1, 0, 240 - 1);
- m_screen->set_screen_update("crtc", FUNC(mc6845_device::screen_update));
+ m_screen->set_raw(15_MHz_XTAL, 960, 0, 640, 313, 0, 240);
+ m_screen->set_screen_update("crtc", FUNC(hd6845s_device::screen_update));
GFXDECODE(config, "gfxdecode", "palette", gfx_mtx_sdx);
PALETTE(config, "palette", palette_device::RGB_3BIT);
- MC6845(config, m_crtc, 15_MHz_XTAL / 8);
+ HD6845S(config, m_crtc, 15_MHz_XTAL / 8);
m_crtc->set_screen("screen");
m_crtc->set_show_border_area(false);
m_crtc->set_char_width(8);
- m_crtc->set_update_row_callback(FUNC(mtx_sdxcpm_device::crtc_update_row), this);
+ m_crtc->set_update_row_callback(FUNC(mtx_sdxcpm_device::crtc_update_row));
}
@@ -190,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)
{
}
@@ -239,8 +238,8 @@ void mtx_sdxbas_device::device_reset()
machine().root_device().membank("rommap_bank1")->configure_entry(3, m_sdx_rom->base());
/* SDX FDC */
- io_space().install_readwrite_handler(0x10, 0x13, read8sm_delegate(FUNC(mb8877_device::read), m_fdc.target()), write8sm_delegate(FUNC(mb8877_device::write), m_fdc.target()));
- io_space().install_readwrite_handler(0x14, 0x14, read8_delegate(FUNC(mtx_sdx_device::sdx_status_r), this), write8_delegate(FUNC(mtx_sdx_device::sdx_control_w), this));
+ io_space().install_readwrite_handler(0x10, 0x13, read8sm_delegate(*m_fdc, FUNC(mb8877_device::read)), write8sm_delegate(*m_fdc, FUNC(mb8877_device::write)));
+ io_space().install_readwrite_handler(0x14, 0x14, read8smo_delegate(*this, FUNC(mtx_sdx_device::sdx_status_r)), write8smo_delegate(*this, FUNC(mtx_sdx_device::sdx_control_w)));
}
void mtx_sdxcpm_device::device_reset()
@@ -248,13 +247,13 @@ void mtx_sdxcpm_device::device_reset()
machine().root_device().membank("rommap_bank1")->configure_entry(3, m_sdx_rom->base());
/* SDX FDC */
- io_space().install_readwrite_handler(0x10, 0x13, read8sm_delegate(FUNC(mb8877_device::read), m_fdc.target()), write8sm_delegate(FUNC(mb8877_device::write), m_fdc.target()));
- io_space().install_readwrite_handler(0x14, 0x14, read8_delegate(FUNC(mtx_sdx_device::sdx_status_r), this), write8_delegate(FUNC(mtx_sdx_device::sdx_control_w), this));
+ io_space().install_readwrite_handler(0x10, 0x13, read8sm_delegate(*m_fdc, FUNC(mb8877_device::read)), write8sm_delegate(*m_fdc, FUNC(mb8877_device::write)));
+ io_space().install_readwrite_handler(0x14, 0x14, read8smo_delegate(*this, FUNC(mtx_sdx_device::sdx_status_r)), write8smo_delegate(*this, FUNC(mtx_sdx_device::sdx_control_w)));
/* 80 column */
- io_space().install_readwrite_handler(0x30, 0x33, read8_delegate(FUNC(mtx_sdxcpm_device::mtx_80col_r), this), write8_delegate(FUNC(mtx_sdxcpm_device::mtx_80col_w), this));
- io_space().install_readwrite_handler(0x38, 0x38, read8smo_delegate(FUNC(mc6845_device::status_r), m_crtc.target()), write8smo_delegate(FUNC(mc6845_device::address_w), m_crtc.target()));
- io_space().install_readwrite_handler(0x39, 0x39, read8smo_delegate(FUNC(mc6845_device::register_r), m_crtc.target()), write8smo_delegate(FUNC(mc6845_device::register_w), m_crtc.target()));
+ io_space().install_readwrite_handler(0x30, 0x33, read8sm_delegate(*this, FUNC(mtx_sdxcpm_device::mtx_80col_r)), write8sm_delegate(*this, FUNC(mtx_sdxcpm_device::mtx_80col_w)));
+ io_space().install_readwrite_handler(0x38, 0x38, read8smo_delegate(*m_crtc, FUNC(hd6845s_device::status_r)), write8smo_delegate(*m_crtc, FUNC(mc6845_device::address_w)));
+ io_space().install_readwrite_handler(0x39, 0x39, read8smo_delegate(*m_crtc, FUNC(hd6845s_device::register_r)), write8smo_delegate(*m_crtc, FUNC(mc6845_device::register_w)));
memset(m_80col_char_ram, 0, sizeof(m_80col_char_ram));
memset(m_80col_attr_ram, 0, sizeof(m_80col_attr_ram));
@@ -265,7 +264,7 @@ void mtx_sdxcpm_device::device_reset()
// IMPLEMENTATION
//**************************************************************************
-READ8_MEMBER(mtx_sdx_device::sdx_status_r)
+uint8_t mtx_sdx_device::sdx_status_r()
{
/*
bit description
@@ -281,12 +280,13 @@ READ8_MEMBER(mtx_sdx_device::sdx_status_r)
uint8_t data = 0x00;
- data |= m_dsw[BIT(m_control, 0)].read_safe(0x0f) & 0x0f;
+ 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;
@@ -294,7 +294,7 @@ READ8_MEMBER(mtx_sdx_device::sdx_status_r)
return data;
}
-WRITE8_MEMBER(mtx_sdx_device::sdx_control_w)
+void mtx_sdx_device::sdx_control_w(uint8_t data)
{
/*
bit description
@@ -308,22 +308,22 @@ WRITE8_MEMBER(mtx_sdx_device::sdx_control_w)
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));
}
@@ -331,17 +331,17 @@ WRITE8_MEMBER(mtx_sdx_device::sdx_control_w)
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);
}
//-------------------------------------------------
// 80 column video board
//-------------------------------------------------
-READ8_MEMBER(mtx_sdxcpm_device::mtx_80col_r)
+uint8_t mtx_sdxcpm_device::mtx_80col_r(offs_t offset)
{
uint8_t data = 0xff;
@@ -362,7 +362,7 @@ READ8_MEMBER(mtx_sdxcpm_device::mtx_80col_r)
return data;
}
-WRITE8_MEMBER(mtx_sdxcpm_device::mtx_80col_w)
+void mtx_sdxcpm_device::mtx_80col_w(offs_t offset, uint8_t data)
{
switch (offset)
{
@@ -417,7 +417,7 @@ MC6845_UPDATE_ROW(mtx_sdxcpm_device::crtc_update_row)
int color = BIT(data, 7) ? fg : bg;
- bitmap.pix32(y, x) = pen[de ? color : 0];
+ bitmap.pix(y, x) = pen[de ? color : 0];
data <<= 1;
}
diff --git a/src/devices/bus/mtx/sdx.h b/src/devices/bus/mtx/sdx.h
index dff83358dd4..4e7183d9565 100644
--- a/src/devices/bus/mtx/sdx.h
+++ b/src/devices/bus/mtx/sdx.h
@@ -6,15 +6,13 @@
**********************************************************************/
-
-#ifndef MAME_BUS_MTX_EXP_SDX_H
-#define MAME_BUS_MTX_EXP_SDX_H
+#ifndef MAME_BUS_MTX_SDX_H
+#define MAME_BUS_MTX_SDX_H
#include "exp.h"
#include "imagedev/floppy.h"
#include "machine/wd_fdc.h"
#include "video/mc6845.h"
-#include "formats/mtx_dsk.h"
#include "emupal.h"
#include "screen.h"
@@ -27,14 +25,14 @@ class mtx_sdx_device :
public device_mtx_exp_interface
{
public:
- DECLARE_FLOPPY_FORMATS(floppy_formats);
+ static void floppy_formats(format_registration &fr);
// optional information overrides
- virtual ioport_constructor device_input_ports() const override;
+ virtual ioport_constructor device_input_ports() const override ATTR_COLD;
- DECLARE_READ8_MEMBER(sdx_status_r);
- DECLARE_WRITE8_MEMBER(sdx_control_w);
- DECLARE_WRITE_LINE_MEMBER(motor_w);
+ uint8_t sdx_status_r();
+ void sdx_control_w(uint8_t data);
+ 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;
};
@@ -57,12 +53,12 @@ public:
protected:
// optional information overrides
- virtual void device_add_mconfig(machine_config &config) override;
- virtual const tiny_rom_entry *device_rom_region() const override;
+ virtual void device_add_mconfig(machine_config &config) override ATTR_COLD;
+ virtual const tiny_rom_entry *device_rom_region() const override ATTR_COLD;
// device-level overrides
- virtual void device_start() override;
- virtual void device_reset() override;
+ virtual void device_start() override ATTR_COLD;
+ virtual void device_reset() override ATTR_COLD;
};
class mtx_sdxcpm_device : public mtx_sdx_device
@@ -73,21 +69,21 @@ public:
protected:
// optional information overrides
- virtual void device_add_mconfig(machine_config &config) override;
- virtual const tiny_rom_entry *device_rom_region() const override;
+ virtual void device_add_mconfig(machine_config &config) override ATTR_COLD;
+ virtual const tiny_rom_entry *device_rom_region() const override ATTR_COLD;
// device-level overrides
- virtual void device_start() override;
- virtual void device_reset() override;
+ virtual void device_start() override ATTR_COLD;
+ virtual void device_reset() override ATTR_COLD;
private:
- DECLARE_READ8_MEMBER(mtx_80col_r);
- DECLARE_WRITE8_MEMBER(mtx_80col_w);
+ uint8_t mtx_80col_r(offs_t offset);
+ void mtx_80col_w(offs_t offset, uint8_t data);
MC6845_UPDATE_ROW(crtc_update_row);
required_device<screen_device> m_screen;
required_device<palette_device> m_palette;
- required_device<mc6845_device> m_crtc;
+ required_device<hd6845s_device> m_crtc;
required_memory_region m_char_rom;
uint8_t m_80col_char_ram[0x800];
uint8_t m_80col_attr_ram[0x800];
@@ -101,5 +97,4 @@ private:
DECLARE_DEVICE_TYPE(MTX_SDXBAS, mtx_sdxbas_device)
DECLARE_DEVICE_TYPE(MTX_SDXCPM, mtx_sdxcpm_device)
-
-#endif // MAME_BUS_MTX_EXP_SDX_H
+#endif // MAME_BUS_MTX_SDX_H
diff --git a/src/devices/bus/multibus/cpuap.cpp b/src/devices/bus/multibus/cpuap.cpp
new file mode 100644
index 00000000000..415b9e7e94d
--- /dev/null
+++ b/src/devices/bus/multibus/cpuap.cpp
@@ -0,0 +1,214 @@
+// license:BSD-3-Clause
+// copyright-holders:Patrick Mackinlay
+
+/*
+ * Siemens S26361-D333 CPUAP processor board.
+ *
+ * This Multibus card was in Siemens PC-MX2 systems. It has a 10MHz NS32016
+ * CPU with the complete set of NS32000 support chips and 1MiB of on-board RAM.
+ * The board connects to optional memory expansion boards through a dedicated
+ * connector (not the Multibus). It has no on-board UART, so depends on a SERAD
+ * or DUEAI board installed in the system to communicate with a console.
+ *
+ * Sources:
+ * - https://oldcomputers-ddns.org/public/pub/rechner/siemens/mx-rm/pc-mx2/manuals/pc-mx2_pc2000_9780_logik.pdf
+ * - https://mx300i.narten.de/view_board.cfm?5EF287A1ABC3F4DCAFEA2BC2FAB8C4000E50392BD499
+ *
+ * TODO:
+ * - led output
+ * - nmi generation
+ * - figure out how to pass-through multibus addresses
+ */
+
+#include "emu.h"
+#include "cpuap.h"
+
+#define VERBOSE 0
+#include "logmacro.h"
+
+DEFINE_DEVICE_TYPE(CPUAP, cpuap_device, "cpuap", "Siemens S26361-D333 CPUAP")
+
+cpuap_device::cpuap_device(machine_config const &mconfig, char const *tag, device_t *owner, u32 clock)
+ : device_t(mconfig, CPUAP, tag, owner, clock)
+ , device_multibus_interface(mconfig, *this)
+ , m_cpu(*this, "cpu")
+ , m_fpu(*this, "fpu")
+ , m_mmu(*this, "mmu")
+ , m_icu(*this, "icu")
+ , m_rtc(*this, "rtc")
+ , m_s7(*this, "S7")
+ , m_s8(*this, "S8")
+ , m_boot(*this, "boot")
+{
+}
+
+// processor diagnostic register
+enum prdia_mask : u8
+{
+ LED1 = 0x01,
+ LED2 = 0x02,
+ LED3 = 0x04,
+ LED4 = 0x08,
+ LED5 = 0x10,
+ LED6 = 0x20,
+ ERRORLED = 0x40,
+ ENNMI = 0x80,
+};
+
+enum nmi_mask : u8
+{
+ PAR2 = 0x01,
+ DEBUGI = 0x02,
+ ACF = 0x04,
+ PERLO = 0x08, // parity error lo
+ PERHI = 0x10, // parity error hi
+ BTIMOUT = 0x20, // bus timeout
+ INT7 = 0x40,
+};
+
+ROM_START(cpuap)
+ ROM_REGION16_LE(0x10000, "eprom", 0)
+ ROM_SYSTEM_BIOS(0, "rev9", "D333 Monitor Rev 9.0 16.06.1988")
+ ROMX_LOAD("361d0333d053__e01735_ine.d53", 0x0000, 0x4000, CRC(b5eefb64) SHA1(a71a7daf9a8f0481d564bfc4d7ed5eb955f8665f), ROM_SKIP(1) | ROM_BIOS(0))
+ ROMX_LOAD("361d0333d054__e01725_ine.d54", 0x0001, 0x4000, CRC(3a3c6b6e) SHA1(5302fd79c89e0b4d164c639e2d73f4b9a279ddcb), ROM_SKIP(1) | ROM_BIOS(0))
+ ROMX_FILL(0x8000, 0x8000, 0xff, ROM_BIOS(0))
+
+ ROM_SYSTEM_BIOS(1, "rev3", "D333 Monitor Rev 3 09.12.1985")
+ ROMX_LOAD("d333__d56_g53__lb.d56", 0x0000, 0x2000, CRC(0892ff90) SHA1(e84ceb8eb3c13de3692297c46632dbfafaad675f), ROM_SKIP(1) | ROM_BIOS(1))
+ ROMX_LOAD("d333__d55_g53__hb.d55", 0x0001, 0x2000, CRC(821e1e41) SHA1(0800249eab8db490c1fb6fea6d65bc7e874c9a0c), ROM_SKIP(1) | ROM_BIOS(1))
+ ROMX_FILL(0x4000, 0xc000, 0xff, ROM_BIOS(1))
+ROM_END
+
+static INPUT_PORTS_START(cpuap)
+ PORT_START("S7")
+
+ // Offen: Ausgabe des Urladers über Diagnose-Stecker, keine SERAD/G Baugruppe gesteckt
+ // Open: boot loader output via diagnostic plug, no SERAD/G module plugged in
+ PORT_DIPNAME(0x80, 0x00, "Diagnostic") PORT_DIPLOCATION("S7:8")
+ PORT_DIPSETTING(0x00, DEF_STR(Off))
+ PORT_DIPSETTING(0x80, DEF_STR(On))
+
+ // Offen: Monitor-Programm nach Testende
+ // Open: enter monitor after test
+ PORT_DIPNAME(0x40, 0x00, "Boot Option") PORT_DIPLOCATION("S7:7")
+ PORT_DIPSETTING(0x00, "Disk")
+ PORT_DIPSETTING(0x40, "Monitor")
+
+ PORT_DIPNAME(0x20, 0x00, "S7:5") PORT_DIPLOCATION("S7:6")
+ PORT_DIPSETTING(0x00, DEF_STR(Off))
+ PORT_DIPSETTING(0x20, DEF_STR(On))
+ PORT_DIPNAME(0x10, 0x00, "S7:4") PORT_DIPLOCATION("S7:5")
+ PORT_DIPSETTING(0x00, DEF_STR(Off))
+ PORT_DIPSETTING(0x10, DEF_STR(On))
+ PORT_DIPNAME(0x08, 0x00, "S7:3") PORT_DIPLOCATION("S7:4")
+ PORT_DIPSETTING(0x00, DEF_STR(Off))
+ PORT_DIPSETTING(0x08, DEF_STR(On))
+ PORT_DIPNAME(0x04, 0x00, "S7:2") PORT_DIPLOCATION("S7:3")
+ PORT_DIPSETTING(0x00, DEF_STR(Off))
+ PORT_DIPSETTING(0x04, DEF_STR(On))
+ PORT_DIPNAME(0x02, 0x00, "S7:1") PORT_DIPLOCATION("S7:2")
+ PORT_DIPSETTING(0x00, DEF_STR(Off))
+ PORT_DIPSETTING(0x02, DEF_STR(On))
+
+ // Offen: kein Reboot nach Systemabsturz
+ // Open: no reboot after system crash
+ PORT_DIPNAME(0x01, 0x00, "S7:0") PORT_DIPLOCATION("S7:1") // S7:0 not allowed, causes crash in the dips menu
+ PORT_DIPSETTING(0x00, DEF_STR(Off))
+ PORT_DIPSETTING(0x01, DEF_STR(On))
+
+ PORT_START("S8")
+ PORT_DIPNAME(0x01, 0x00, "IRQ 7")
+ PORT_DIPSETTING(0x00, "ICU IR11")
+ PORT_DIPSETTING(0x01, "NMI")
+INPUT_PORTS_END
+
+const tiny_rom_entry *cpuap_device::device_rom_region() const
+{
+ return ROM_NAME(cpuap);
+}
+
+ioport_constructor cpuap_device::device_input_ports() const
+{
+ return INPUT_PORTS_NAME(cpuap);
+}
+
+void cpuap_device::device_start()
+{
+}
+
+void cpuap_device::device_reset()
+{
+ m_boot.select(0);
+ m_nmi = 0xff;
+}
+
+void cpuap_device::bus_timeout(u8 data)
+{
+ m_nmi &= ~BTIMOUT;
+
+ if (m_prdia & ENNMI)
+ m_cpu->set_input_line(INPUT_LINE_NMI, 1);
+}
+
+void cpuap_device::device_add_mconfig(machine_config &config)
+{
+ NS32016(config, m_cpu, 20_MHz_XTAL / 2);
+ m_cpu->set_addrmap(0, &cpuap_device::cpu_map<0>);
+ m_cpu->set_addrmap(4, &cpuap_device::cpu_map<4>);
+
+ NS32081(config, m_fpu, 20_MHz_XTAL / 2);
+ m_cpu->set_fpu(m_fpu);
+
+ NS32082(config, m_mmu, 20_MHz_XTAL / 2);
+ m_cpu->set_mmu(m_mmu);
+
+ NS32202(config, m_icu, 20_MHz_XTAL / 2);
+ m_icu->out_int().set_inputline(m_cpu, INPUT_LINE_IRQ0).invert();
+
+ int_callback<0>().set(m_icu, FUNC(ns32202_device::ir_w<0>));
+ int_callback<1>().set(m_icu, FUNC(ns32202_device::ir_w<1>));
+ int_callback<2>().set(m_icu, FUNC(ns32202_device::ir_w<3>));
+ int_callback<3>().set(m_icu, FUNC(ns32202_device::ir_w<4>));
+ int_callback<4>().set(m_icu, FUNC(ns32202_device::ir_w<6>));
+ int_callback<5>().set(m_icu, FUNC(ns32202_device::ir_w<7>));
+ int_callback<6>().set(m_icu, FUNC(ns32202_device::ir_w<8>));
+ int_callback<7>().set([this](int state) { m_s8->read() ? m_cpu->set_input_line(INPUT_LINE_NMI, !state) : m_icu->ir_w<11>(state); });
+
+ MC146818(config, m_rtc, 32.768_kHz_XTAL);
+}
+
+template <unsigned ST> void cpuap_device::cpu_map(address_map &map)
+{
+ if (ST == 0)
+ {
+ map(0x000000, 0x0fffff).view(m_boot);
+
+ m_boot[0](0x000000, 0x00ffff).rom().region("eprom", 0);
+ m_boot[1](0x000000, 0x0fffff).ram();
+
+ //map(0x100000, 0x3fffff); // first memory expansion
+ //map(0x400000, 0x6fffff); // second memory expansion
+
+ map(0x700000, 0xdfffff).w(FUNC(cpuap_device::bus_timeout));
+
+ map(0xe00000, 0xefffff).rw(FUNC(cpuap_device::bus_mem_r), FUNC(cpuap_device::bus_mem_w)); // multibus mem
+ map(0xf00000, 0xf0ffff).rw(FUNC(cpuap_device::bus_pio_r), FUNC(cpuap_device::bus_pio_w)); // multibus i/o
+
+ //map(0xf10000, 0xfdffff); // unused
+ map(0xfe0000, 0xfeffff).rom().region("eprom", 0);
+
+ //map(0xff0000, 0xf7ffff); // unused
+ map(0xff8000, 0xff803f).rw(m_rtc, FUNC(mc146818_device::read_direct), FUNC(mc146818_device::write_direct));
+ map(0xff8100, 0xff8100).lr8([this]() { return m_s7->read(); }, "s7_r");
+ map(0xff8200, 0xff8200).lw8([this](u8 data) { LOG("prdia_w 0x%02x led 0x%x (%s)\n", data, ~data & 0x3f, machine().describe_context()); m_prdia = data; }, "prdia_w");
+ map(0xff8300, 0xff8300).lrw8([this]() { return m_poff; }, "poff_r", [this](u8 data) { m_poff = data & 3; }, "poff_w"); // 3 pohopofi - power off interrupt?
+ //map(0xff8400, 0xff840f); // 4 csuart
+ map(0xff8500, 0xff8500).lw8([this](u8 data) { m_boot.select(BIT(data, 0)); }, "mapprom_w");
+ map(0xff8600, 0xff863f).m(m_icu, FUNC(ns32202_device::map<0>)).umask16(0x00ff);
+ map(0xff8700, 0xff8700).lrw8(
+ [this]() { return m_nmi; }, "nmi_r",
+ [this](u8 data) { LOG("nmi_w 0x%02x (%s)\n", data, machine().describe_context()); m_nmi = 0xff; }, "nmi_w");
+ }
+
+ map(0xfffe00, 0xfffeff).m(m_icu, FUNC(ns32202_device::map<BIT(ST, 1)>)).umask16(0x00ff);
+}
diff --git a/src/devices/bus/multibus/cpuap.h b/src/devices/bus/multibus/cpuap.h
new file mode 100644
index 00000000000..340d7a94c42
--- /dev/null
+++ b/src/devices/bus/multibus/cpuap.h
@@ -0,0 +1,58 @@
+// license:BSD-3-Clause
+// copyright-holders:Patrick Mackinlay
+
+#ifndef MAME_BUS_MULTIBUS_CPUAP_H
+#define MAME_BUS_MULTIBUS_CPUAP_H
+
+#pragma once
+
+#include "multibus.h"
+
+#include "cpu/ns32000/ns32000.h"
+#include "machine/ns32081.h"
+#include "machine/ns32082.h"
+#include "machine/ns32202.h"
+#include "machine/mc146818.h"
+
+
+class cpuap_device
+ : public device_t
+ , public device_multibus_interface
+{
+public:
+ cpuap_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 ATTR_COLD;
+ virtual void device_add_mconfig(machine_config &config) override ATTR_COLD;
+ virtual ioport_constructor device_input_ports() const override ATTR_COLD;
+ virtual void device_start() override ATTR_COLD;
+ virtual void device_reset() override ATTR_COLD;
+
+private:
+ template <unsigned ST> void cpu_map(address_map &map) ATTR_COLD;
+
+ void bus_timeout(u8 data);
+ void bus_mem_w(offs_t offset, u16 data, u16 mem_mask) { m_bus->space(AS_PROGRAM).write_word(0xe00000 | offset << 1, data, mem_mask); }
+ u16 bus_mem_r(offs_t offset, u16 mem_mask) { return m_bus->space(AS_PROGRAM).read_word(0xe00000 | offset << 1, mem_mask); }
+ void bus_pio_w(offs_t offset, u16 data, u16 mem_mask) { m_bus->space(AS_IO).write_word(offset << 1, data, mem_mask); }
+ u16 bus_pio_r(offs_t offset, u16 mem_mask) { return m_bus->space(AS_IO).read_word(offset << 1, mem_mask); }
+
+ required_device<ns32016_device> m_cpu;
+ required_device<ns32081_device> m_fpu;
+ required_device<ns32082_device> m_mmu;
+ required_device<ns32202_device> m_icu;
+ required_device<mc146818_device> m_rtc;
+ required_ioport m_s7;
+ required_ioport m_s8;
+ memory_view m_boot;
+
+ u8 m_prdia;
+ u8 m_poff;
+ u8 m_nmi;
+};
+
+DECLARE_DEVICE_TYPE(CPUAP, cpuap_device)
+
+#endif // MAME_BUS_MULTIBUS_CPUAP_H
diff --git a/src/devices/bus/multibus/isbc202.cpp b/src/devices/bus/multibus/isbc202.cpp
new file mode 100644
index 00000000000..97b7bca71ae
--- /dev/null
+++ b/src/devices/bus/multibus/isbc202.cpp
@@ -0,0 +1,1164 @@
+// license:BSD-3-Clause
+// copyright-holders: F. Ulivi
+/*********************************************************************
+
+ isbc202.cpp
+
+ Intel iSBC-202 SSDD 8" floppy disk controller
+
+ This controller interfaces a standard 8/16-bit Multibus system
+ with up to 4 8" SSDD floppy drives. It was typically used to
+ expand a MDS-II system with double-density drives.
+ The ISIS-II OS identifies the drives as :F0: :F1: :F2: :F3:
+ The iSBC-202 controller is based on two boards: a "channel"
+ board with the actual controller and an "interface" board.
+ The latter handles the low-level aspects of the disks, especially
+ the encoding and decoding of MMFM modulated bits. This board
+ interfaces directly with standard Shugart SA-800-1 drives.
+ The drives are housed, two at time, in a (big) external box
+ that also holds their power supply.
+ The channel board is implemented with a 3000-series bit slice
+ processor. Microcode is stored on 4 512x8 bipolar PROMs.
+ The channel board is bus mastering, i.e. it can issue memory
+ read/write cycles to the main processor RAM.
+ Format of data on disk is entirely Intel proprietary.
+ Intel also designed a similar controller (iSBC-201) for FM
+ IBM-standard disks. AFAIK, this board shares the channel board
+ with iSBC-202 (but not the microcode) and has a different
+ interface board.
+ This table summarizes the main characteristics of the disks.
+
+ | Bit cell size | 2 µs |
+ | Modulation | MMFM |
+ | Bit order | MS first |
+ | Sides | 1 |
+ | Tracks | 77 |
+ | Sectors/track | 52 |
+ | Sector size | 128 bytes|
+ | Formatted size | 500.5 kB |
+ | Rotation speed | 360 RPM |
+
+ Special thanks to Eric Smith for dumping the microcode PROMs.
+ Without his work this driver wouldn't exist at all.
+
+ Reference manuals.
+ - Intellec series II MDS double-density diskette subsystem
+ (schematic drawings) - Intel 1980 - 9800425-02 Rev. B
+ - Intellec double-density diskette operating system hardware
+ reference manual - Intel 1977 - 9800422A
+ - SBC 202 double-density diskette controller hardware reference
+ manual - Intel 1977 - 9800420A
+
+ What follows is a list of things that I left out. They could be
+ implemented at a later time just for completeness sake as ISIS-II
+ doesn't rely on them at all.
+ - The STOP signal (it seems to be used in iSBC-201 only)
+ - Interrupt to CPU
+ - Head load/unload commands (MAME doesn't emulate head loading)
+
+*********************************************************************/
+
+#include "emu.h"
+#include "isbc202.h"
+#include "formats/img_dsk.h"
+#include "formats/fs_isis.h"
+
+// Debugging
+#include "logmacro.h"
+#define LOG_BUS_MASK (LOG_GENERAL << 1)
+#define LOG_BUS(...) LOGMASKED(LOG_BUS_MASK, __VA_ARGS__)
+#define LOG_RD_MASK (LOG_BUS_MASK << 1)
+#define LOG_RD(...) LOGMASKED(LOG_RD_MASK, __VA_ARGS__)
+#define LOG_WR_MASK (LOG_RD_MASK << 1)
+#define LOG_WR(...) LOGMASKED(LOG_WR_MASK, __VA_ARGS__)
+#define LOG_DR_MASK (LOG_WR_MASK << 1)
+#define LOG_DR(...) LOGMASKED(LOG_DR_MASK, __VA_ARGS__)
+#undef VERBOSE
+//#define VERBOSE (LOG_GENERAL|LOG_BUS_MASK|LOG_RD_MASK|LOG_WR_MASK|LOG_DR_MASK)
+#define VERBOSE LOG_GENERAL
+
+// Bit manipulation
+namespace {
+ template<typename T> constexpr T BIT_MASK(unsigned n)
+ {
+ return (T)1U << n;
+ }
+
+ template<typename T> void BIT_CLR(T& w , unsigned n)
+ {
+ w &= ~BIT_MASK<T>(n);
+ }
+
+ template<typename T> void BIT_SET(T& w , unsigned n)
+ {
+ w |= BIT_MASK<T>(n);
+ }
+}
+
+// Constants
+constexpr unsigned TIMEOUT_MS = 10; // "timeout" timer: 10 ms
+constexpr unsigned HALF_BIT_CELL_US = 1;// Half bit cell duration in µs
+constexpr unsigned BIT_FREQUENCY = 500000; // Frequency of bit cells in Hz
+constexpr uint16_t CRC_POLY = 0x1021; // CRC-CCITT
+
+// device type definition
+DEFINE_DEVICE_TYPE(ISBC202, isbc202_device, "isbc202", "iSBC-202 floppy controller")
+
+// Microcode disassembler
+class isbc202_disassembler : public util::disasm_interface
+{
+public:
+ isbc202_disassembler();
+ virtual ~isbc202_disassembler() = default;
+
+ virtual u32 opcode_alignment() const override;
+ virtual offs_t disassemble(std::ostream &stream, offs_t pc, const data_buffer &opcodes, const data_buffer &params) override;
+};
+
+isbc202_disassembler::isbc202_disassembler()
+{
+}
+
+u32 isbc202_disassembler::opcode_alignment() const
+{
+ return 1;
+}
+
+offs_t isbc202_disassembler::disassemble(std::ostream &stream, offs_t pc, const data_buffer &opcodes, const data_buffer &params)
+{
+ uint32_t microcode = opcodes.r32(pc);
+
+ // Decode address control instruction
+ uint8_t ac = uint8_t(microcode >> 25);
+
+ if ((ac & 0b1100000) == 0b0000000) {
+ // JCC
+ util::stream_format(stream , "JCC $%03x" , ((uint16_t(ac) & 0b11111) << 4) | (pc & 0xf));
+ } else if ((ac & 0b1110000) == 0b0100000) {
+ // JZR
+ util::stream_format(stream , "JZR $00%x" , ac & 0b1111);
+ } else if ((ac & 0b1110000) == 0b0110000) {
+ // JCR
+ util::stream_format(stream , "JCR $%03x" , (pc & 0b111110000) | (ac & 0b1111));
+ } else if ((ac & 0b1111000) == 0b1110000) {
+ // JCE
+ util::stream_format(stream , "JCE $%03x" , (pc & 0b110001111) | ((ac & 0b111) << 4));
+ } else if ((ac & 0b1110000) == 0b1000000) {
+ // JFL
+ util::stream_format(stream , "JFL $%03x" , (pc & 0b100001000) | ((ac & 0b1111) << 4) | 0b10);
+ } else if ((ac & 0b1111000) == 0b1010000) {
+ // JCF
+ util::stream_format(stream , "JCF $%03x" , (pc & 0b110001000) | ((ac & 0b111) << 4) | 0b10);
+ } else if ((ac & 0b1111000) == 0b1011000) {
+ // JZF
+ util::stream_format(stream , "JZF $%03x" , (pc & 0b110001000) | ((ac & 0b111) << 4) | 0b10);
+ } else if ((ac & 0b1111000) == 0b1100000) {
+ // JPR
+ util::stream_format(stream , "JPR $%02xx" , ((pc >> 4) & 0b11000) | (ac & 0b111));
+ } else if ((ac & 0b1111000) == 0b1101000) {
+ // JLL
+ util::stream_format(stream , "JLL $%03x" , (pc & 0b110000000) | ((ac & 0b111) << 4) | 0b100);
+ } else if ((ac & 0b1111100) == 0b1111100) {
+ // JRL
+ util::stream_format(stream , "JRL $%03x" , (pc & 0b110000000) | ((ac & 0b11) << 4) | 0b001001100);
+ } else {
+ // JPX
+ util::stream_format(stream , "JPX $%02xx" , ((pc >> 4) & 0b11100) | (ac & 0b11));
+ }
+
+ // Decode input multiplexer
+ uint8_t in = uint8_t((microcode >> 13) & 7);
+ util::stream_format(stream , " I=%u" , in);
+
+ // Decode function code
+ uint8_t fc = uint8_t((microcode >> 18) & 0x7f);
+ uint8_t fg;
+ uint8_t rg;
+ unsigned reg;
+ i3002_device::decode_fc(fc , fg , rg , reg);
+ util::stream_format(stream , " CPE=%u%u/%2s" , fg , rg + 1 , i3002_device::reg_name(reg));
+
+ // Decode flag control
+ stream << (BIT(microcode , 17) ? " FF1" : " FF0");
+ stream << (BIT(microcode , 16) ? " HCZ" : " SCZ");
+
+ // Decode K
+ uint8_t slk = uint8_t((microcode >> 8) & 3);
+ uint8_t mask = uint8_t(microcode);
+ uint8_t kbus;
+ if (!BIT(slk , 0)) {
+ kbus = mask;
+ } else if (slk == 1) {
+ kbus = 0xff;
+ } else {
+ kbus = 0;
+ }
+ util::stream_format(stream , " K=$%02x" , kbus);
+
+ // Decode OUT
+ util::stream_format(stream , " S=%u M=$%02x" , slk , mask);
+ if (BIT(slk , 0) && !BIT(mask , 7)) {
+ uint8_t out = uint8_t((microcode >> 10) & 7);
+ util::stream_format(stream , " O=%u" , out);
+ }
+
+ return 1 | SUPPORTED;
+}
+
+// isbc202_device
+isbc202_device::isbc202_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock)
+ : cpu_device(mconfig , ISBC202 , tag , owner , DERIVED_CLOCK(1, 4))
+ , device_multibus_interface(mconfig , *this)
+ , m_mcu(*this , "mcu")
+ , m_cpes(*this , "cpe%u" , 0)
+ , m_drives(*this , "floppy%u" , 0)
+ , m_program_config("microprogram" , ENDIANNESS_BIG , 32 , 9 , -2)
+ , m_mem_space(nullptr)
+{
+}
+
+isbc202_device::~isbc202_device()
+{
+}
+
+uint8_t isbc202_device::io_r(address_space &space, offs_t offset)
+{
+ uint8_t res = 0;
+
+ switch (offset) {
+ case 0:
+ // Read drive status & INT (auto XACK)
+ // Bit What
+ // 7 0
+ // 6 Drive 3 ready
+ // 5 Drive 2 ready
+ // 4 1
+ // 3 1
+ // 2 Int pending
+ // 1 Drive 1 ready
+ // 0 Drive 0 ready
+ {
+ uint8_t ready = m_ready_in & m_ready_ff;
+ if (BIT(ready , 3)) {
+ BIT_SET(res , 6);
+ }
+ if (BIT(ready , 2)) {
+ BIT_SET(res , 5);
+ }
+ BIT_SET(res , 4);
+ BIT_SET(res , 3);
+ if (m_irq) {
+ BIT_SET(res , 2);
+ }
+ if (BIT(ready , 1)) {
+ BIT_SET(res , 1);
+ }
+ if (BIT(ready , 0)) {
+ BIT_SET(res , 0);
+ }
+ }
+ break;
+
+ case 1:
+ // Read result type (auto XACK)
+ m_irq = false;
+ res = m_data_low_out;
+ break;
+
+ case 3:
+ // Read result byte (no auto XACK)
+ if (!m_2nd_pass) {
+ set_start(3 , true);
+ } else {
+ m_2nd_pass = false;
+ res = m_data_low_out;
+ }
+ break;
+
+ default:
+ LOG("RD from unknown reg!\n");
+ break;
+ }
+
+ LOG_BUS("IO R @%u=%02x\n" , offset , res);
+ return res;
+}
+
+void isbc202_device::io_w(address_space &space, offs_t offset, uint8_t data)
+{
+ LOG_BUS("IO W @%u=%02x\n" , offset , data);
+
+ switch (offset) {
+ case 0:
+ case 1:
+ // Write LSB address
+ case 2:
+ // Write MSB address & start op
+ case 4:
+ case 5:
+ case 6:
+ if (!m_2nd_pass) {
+ m_cpu_data = data;
+ set_start(offset , false);
+ } else {
+ m_2nd_pass = false;
+ }
+ break;
+
+ case 7:
+ // Reset
+ pulse_input_line(INPUT_LINE_RESET , attotime::zero);
+ break;
+
+ default:
+ LOG("WR to unknown reg!\n");
+ break;
+ }
+}
+
+void isbc202_device::co_w(int state)
+{
+ m_inputs[ IN_SEL_CO ] = state;
+ m_mcu->fi_w(state);
+ m_cpes[ 3 ]->li_w(state);
+}
+
+uint8_t isbc202_device::px_r()
+{
+ if (BIT(m_px_s1s0 , 0)) {
+ return m_cmd & 7;
+ } else if (BIT(m_px_s1s0 , 1)) {
+ return (m_op_us & 7) | 8;
+ } else {
+ return 0;
+ }
+}
+
+void isbc202_device::device_start()
+{
+ state_add(STATE_GENPC , "GENPC" , m_microcode_addr).noshow();
+ state_add(STATE_GENPCBASE , "CURPC" , m_microcode_addr).noshow();
+ state_add(STATE_GENFLAGS , "FLAGS" , m_flags).noshow().callimport().callexport().formatstr("%9s");
+
+ for (int i = 0; i < i3002_device::REG_COUNT; ++i) {
+ state_add(i , i3002_device::reg_name(i) , m_regs[ i ]).callimport().callexport();
+ }
+
+ save_item(NAME(m_flags));
+ save_item(NAME(m_regs));
+ save_item(NAME(m_microcode_addr));
+ save_item(NAME(m_code_word));
+ save_item(NAME(m_ac));
+ save_item(NAME(m_fc));
+ save_item(NAME(m_fc32));
+ save_item(NAME(m_fc10));
+ save_item(NAME(m_in_sel));
+ save_item(NAME(m_out_sel));
+ save_item(NAME(m_slk));
+ save_item(NAME(m_mask));
+ save_item(NAME(m_kbus));
+ save_item(NAME(m_inputs));
+ save_item(NAME(m_op_us));
+ save_item(NAME(m_px_s1s0));
+ save_item(NAME(m_cmd));
+ save_item(NAME(m_2nd_pass));
+ save_item(NAME(m_ready_in));
+ save_item(NAME(m_ready_ff));
+ save_item(NAME(m_gate_lower));
+ save_item(NAME(m_irq));
+ save_item(NAME(m_data_low_out));
+ save_item(NAME(m_data_low_in));
+ save_item(NAME(m_cpu_data));
+ save_item(NAME(m_addr_low_out));
+ save_item(NAME(m_mem_wrt));
+ save_item(NAME(m_wrt_inh));
+ save_item(NAME(m_direction));
+ save_item(NAME(m_ibus_cached));
+ save_item(NAME(m_ibus));
+ save_item(NAME(m_crc));
+ save_item(NAME(m_crc_enabled));
+ save_item(NAME(m_crc_out));
+ save_item(NAME(m_reading));
+ save_item(NAME(m_writing));
+ save_item(NAME(m_data_sr));
+ save_item(NAME(m_last_data_bit));
+ save_item(NAME(m_clock_sr));
+ save_item(NAME(m_last_f_time));
+ save_item(NAME(m_clock_gate));
+ save_item(NAME(m_amwrt));
+ save_item(NAME(m_dlyd_amwrt));
+
+ space(AS_PROGRAM).cache(m_cache);
+ set_icountptr(m_icount);
+ space(AS_PROGRAM).install_rom(0 , 0x1ff , memregion("microcode")->base());
+
+ for (auto& d : m_drives) {
+ d->get_device()->setup_ready_cb(floppy_image_device::ready_cb(&isbc202_device::floppy_ready_cb , this));
+ d->get_device()->setup_index_pulse_cb(floppy_image_device::index_pulse_cb(&isbc202_device::floppy_index_cb , this));
+ }
+
+ m_timeout_timer = timer_alloc(FUNC(isbc202_device::timeout_tick), this);
+ m_byte_timer = timer_alloc(FUNC(isbc202_device::byte_tick), this);
+ m_f_timer = timer_alloc(FUNC(isbc202_device::f_tick), this);
+
+ m_mem_space = &m_bus->space(AS_PROGRAM);
+ m_bus->space(AS_IO).install_readwrite_handler(0x78, 0x7f, read8m_delegate(*this, FUNC(isbc202_device::io_r)), write8m_delegate(*this, FUNC(isbc202_device::io_w)));
+}
+
+void isbc202_device::device_reset()
+{
+ // Set start address
+ m_mcu->addr_w(0);
+ // Select drive #0
+ m_op_us = 0;
+ m_current_drive = m_drives[ 0 ]->get_device();
+
+ // XFERREQ is always 1 because R/W in CPU memory is instantaneous
+ m_inputs[ IN_SEL_XFERQ ] = true;
+
+ m_inputs[ IN_SEL_TIMEOUT ] = true;
+ m_inputs[ IN_SEL_F ] = false;
+
+ m_2nd_pass = false;
+
+ m_irq = false;
+
+ m_reading = false;
+ m_writing = false;
+
+ m_timeout_timer->reset();
+ m_byte_timer->reset();
+ m_f_timer->reset();
+}
+
+TIMER_CALLBACK_MEMBER(isbc202_device::timeout_tick)
+{
+ m_inputs[ IN_SEL_TIMEOUT ] = true;
+}
+
+TIMER_CALLBACK_MEMBER(isbc202_device::byte_tick)
+{
+ m_inputs[ IN_SEL_F ] = true;
+ m_f_timer->adjust(attotime::from_usec(HALF_BIT_CELL_US * 2));
+ m_dlyd_amwrt = m_amwrt;
+ if (m_reading) {
+ m_last_f_time = machine().time();
+ rd_bits(8);
+ m_byte_timer->adjust(m_pll.ctime - machine().time());
+ // Updating of AZ flag actually happens when F goes low
+ m_inputs[ IN_SEL_AZ ] = m_crc == 0;
+ }
+}
+
+TIMER_CALLBACK_MEMBER(isbc202_device::f_tick)
+{
+ m_inputs[ IN_SEL_F ] = false;
+ if (m_writing) {
+ write_byte();
+ m_data_sr = dbus_r();
+ m_byte_timer->adjust(attotime::from_usec(HALF_BIT_CELL_US * 14));
+ }
+}
+
+ROM_START(isbc202)
+ ROM_REGION(0x800 , "microcode" , ROMREGION_32BIT | ROMREGION_BE)
+ ROM_LOAD32_BYTE("sbc202-a10-0230.bin" , 0x000 , 0x200 , CRC(e8fa3893) SHA1(88fab74b0466e8aac36eee46cd7536ed1b32a2c9))
+ ROM_LOAD32_BYTE("sbc202-a11-0261.bin" , 0x001 , 0x200 , CRC(3ad01769) SHA1(4c22b8fc3ea599dd49684ff4dcafc29ec3425c4c))
+ ROM_LOAD32_BYTE("sbc202-a12-0233.bin" , 0x002 , 0x200 , CRC(61496232) SHA1(b0473217944b2f6e966d97e97cf5ad8d883a09e4))
+ ROM_LOAD32_BYTE("sbc202-a13-0232.bin" , 0x003 , 0x200 , CRC(c369ab86) SHA1(fc3b7f9c3e71ea1442827c51247a9944c6d40b37))
+ROM_END
+
+const tiny_rom_entry *isbc202_device::device_rom_region() const
+{
+ return ROM_NAME(isbc202);
+}
+
+static void isbc202_floppies(device_slot_interface &device)
+{
+ device.option_add("8ssdd" , FLOPPY_8_SSDD);
+}
+
+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)
+{
+ I3001(config , m_mcu , 0);
+
+ // Allocation of the bit-slices:
+ // m_cpes[ 0 ] Bits 0..1
+ // m_cpes[ 1 ] Bits 2..3
+ // m_cpes[ 2 ] Bits 4..5
+ // m_cpes[ 3 ] Bits 6..7
+ for (auto& finder : m_cpes) {
+ I3002(config , finder , 0);
+ }
+
+ // Connect CO/CI signals
+ m_mcu->set_fo_w_cb(m_cpes[ 0 ] , FUNC(i3002_device::ci_w));
+ m_cpes[ 0 ]->set_co_w_cb(m_cpes[ 1 ] , FUNC(i3002_device::ci_w));
+ m_cpes[ 1 ]->set_co_w_cb(m_cpes[ 2 ] , FUNC(i3002_device::ci_w));
+ m_cpes[ 2 ]->set_co_w_cb(m_cpes[ 3 ] , FUNC(i3002_device::ci_w));
+ m_cpes[ 3 ]->set_co_w_cb(FUNC(isbc202_device::co_w));
+
+ // Connect RO/LI signals
+ m_cpes[ 0 ]->set_ro_w_cb(FUNC(isbc202_device::co_w));
+ m_cpes[ 1 ]->set_ro_w_cb(m_cpes[ 0 ] , FUNC(i3002_device::li_w));
+ m_cpes[ 2 ]->set_ro_w_cb(m_cpes[ 1 ] , FUNC(i3002_device::li_w));
+ m_cpes[ 3 ]->set_ro_w_cb(m_cpes[ 2 ] , FUNC(i3002_device::li_w));
+
+ // Connect M-bus
+ m_cpes[ 0 ]->set_mbus_r_cb(NAME([this]() { return mbus_r(); }));
+ m_cpes[ 1 ]->set_mbus_r_cb(NAME([this]() { return mbus_r() >> 2; }));
+ m_cpes[ 2 ]->set_mbus_r_cb(NAME([this]() { return mbus_r() >> 4; }));
+ m_cpes[ 3 ]->set_mbus_r_cb(NAME([this]() { return mbus_r() >> 6; }));
+
+ // Connect I-bus
+ m_cpes[ 0 ]->set_ibus_r_cb(NAME([this]() { return ibus_r(); }));
+ m_cpes[ 1 ]->set_ibus_r_cb(NAME([this]() { return ibus_r() >> 2; }));
+ m_cpes[ 2 ]->set_ibus_r_cb(NAME([this]() { return ibus_r() >> 4; }));
+ m_cpes[ 3 ]->set_ibus_r_cb(NAME([this]() { return ibus_r() >> 6; }));
+
+ // Connect SX input
+ m_mcu->set_sx_r_cb(NAME([this]() { return m_microcode_addr & 0xf; }));
+ // Connect PX input
+ m_mcu->set_px_r_cb(FUNC(isbc202_device::px_r));
+
+ // Drives
+ for (auto& finder : m_drives) {
+ FLOPPY_CONNECTOR(config , finder , isbc202_floppies , "8ssdd" , isbc202_floppy_formats).set_fixed(true);
+ }
+}
+
+void isbc202_device::execute_run()
+{
+ do {
+ m_microcode_addr = m_mcu->addr_r();
+ debugger_instruction_hook(m_microcode_addr);
+ m_code_word = m_cache.read_dword(m_microcode_addr);
+
+ // Unpack microcode into fields
+ // Bits Field
+ //================
+ // 31..25 Address Control
+ // 24..18 Function Code
+ // 17 Flag Control bits 3 & 2
+ // 16 Flag Control bits 1 & 0
+ // 15..13 Input multiplexer selection
+ // 12..10 Output control
+ // 9..8 SLK field
+ // 7..0 Mask field
+ m_ac = uint8_t(m_code_word >> 25);
+ m_fc = uint8_t((m_code_word >> 18) & 0x7f);
+ m_fc32 = BIT(m_code_word , 17);
+ m_fc10 = BIT(m_code_word , 16);
+ m_in_sel = uint8_t((m_code_word >> 13) & 7);
+ m_out_sel = uint8_t((m_code_word >> 10) & 7);
+ m_slk = uint8_t((m_code_word >> 8) & 3);
+ m_mask = uint8_t(m_code_word);
+
+ m_mcu->fc_w((m_fc32 ? 0b1100 : 0b0000) | (m_fc10 ? 0b0011 : 0b0000));
+
+ // Set outputs
+ if (BIT(m_slk , 0) && !BIT(m_mask , 7)) {
+ set_output();
+ }
+
+ // Compute K-bus
+ if (!BIT(m_slk , 0)) {
+ m_kbus = m_mask;
+ } else if (m_slk == 1) {
+ m_kbus = 0xff;
+ } else {
+ m_kbus = 0;
+ }
+
+ m_ibus_cached = false;
+
+ // Update CPEs
+ m_cpes[ 0 ]->fc_kbus_w(m_fc , m_kbus);
+ m_cpes[ 1 ]->fc_kbus_w(m_fc , m_kbus >> 2);
+ m_cpes[ 2 ]->fc_kbus_w(m_fc , m_kbus >> 4);
+ m_cpes[ 3 ]->fc_kbus_w(m_fc , m_kbus >> 6);
+ if (m_cpes[ 0 ]->update_ro()) {
+ // Data propagate to right (right-shift op)
+ m_cpes[ 3 ]->clk_w(1);
+ m_cpes[ 2 ]->clk_w(1);
+ m_cpes[ 1 ]->clk_w(1);
+ m_cpes[ 0 ]->clk_w(1);
+ } else {
+ // Data propagate to left (every op but right-shift)
+ m_cpes[ 0 ]->clk_w(1);
+ m_cpes[ 1 ]->clk_w(1);
+ m_cpes[ 2 ]->clk_w(1);
+ m_cpes[ 3 ]->clk_w(1);
+ }
+
+ // Update MCU
+ if (m_in_sel == IN_SEL_AC0) {
+ m_mcu->ac_w(m_ac);
+ } else {
+ m_mcu->ac_w((m_ac & 0b1111110) | m_inputs[ m_in_sel ]);
+ }
+ m_mcu->clk_w(1);
+
+ m_icount--;
+ } while (m_icount > 0);
+}
+
+device_memory_interface::space_config_vector isbc202_device::memory_space_config() const
+{
+ return space_config_vector{
+ std::make_pair(AS_PROGRAM , &m_program_config)
+ };
+}
+
+std::unique_ptr<util::disasm_interface> isbc202_device::create_disassembler()
+{
+ return std::make_unique<isbc202_disassembler>();
+}
+
+void isbc202_device::state_import(const device_state_entry &entry)
+{
+ switch (entry.index()) {
+ case i3002_device::REG_R0:
+ case i3002_device::REG_R1:
+ case i3002_device::REG_R2:
+ case i3002_device::REG_R3:
+ case i3002_device::REG_R4:
+ case i3002_device::REG_R5:
+ case i3002_device::REG_R6:
+ case i3002_device::REG_R7:
+ case i3002_device::REG_R8:
+ case i3002_device::REG_R9:
+ case i3002_device::REG_T:
+ case i3002_device::REG_AC:
+ case i3002_device::REG_MAR:
+ m_cpes[ 0 ]->get_reg(entry.index()) = m_regs[ entry.index() ] & i3002_device::WORD_MASK;
+ m_cpes[ 1 ]->get_reg(entry.index()) = (m_regs[ entry.index() ] >> 2) & i3002_device::WORD_MASK;
+ m_cpes[ 2 ]->get_reg(entry.index()) = (m_regs[ entry.index() ] >> 4) & i3002_device::WORD_MASK;
+ m_cpes[ 3 ]->get_reg(entry.index()) = (m_regs[ entry.index() ] >> 6) & i3002_device::WORD_MASK;
+ break;
+
+ default:
+ break;
+ }
+}
+
+void isbc202_device::state_export(const device_state_entry &entry)
+{
+ switch (entry.index()) {
+ case STATE_GENFLAGS:
+ m_flags = 0;
+ if (m_inputs[ IN_SEL_CO ]) {
+ BIT_SET(m_flags , 0);
+ }
+ if (m_mcu->fo_r()) {
+ BIT_SET(m_flags , 1);
+ }
+ if (m_mcu->carry_r()) {
+ BIT_SET(m_flags , 2);
+ }
+ if (m_mcu->zero_r()) {
+ BIT_SET(m_flags , 3);
+ }
+ break;
+
+ case i3002_device::REG_R0:
+ case i3002_device::REG_R1:
+ case i3002_device::REG_R2:
+ case i3002_device::REG_R3:
+ case i3002_device::REG_R4:
+ case i3002_device::REG_R5:
+ case i3002_device::REG_R6:
+ case i3002_device::REG_R7:
+ case i3002_device::REG_R8:
+ case i3002_device::REG_R9:
+ case i3002_device::REG_T:
+ case i3002_device::REG_AC:
+ case i3002_device::REG_MAR:
+ m_regs[ entry.index() ] = m_cpes[ 3 ]->get_reg(entry.index());
+ m_regs[ entry.index() ] <<= 2;
+ m_regs[ entry.index() ] |= m_cpes[ 2 ]->get_reg(entry.index());
+ m_regs[ entry.index() ] <<= 2;
+ m_regs[ entry.index() ] |= m_cpes[ 1 ]->get_reg(entry.index());
+ m_regs[ entry.index() ] <<= 2;
+ m_regs[ entry.index() ] |= m_cpes[ 0 ]->get_reg(entry.index());
+ break;
+
+ default:
+ break;
+ }
+}
+
+void isbc202_device::state_string_export(const device_state_entry &entry, std::string &str) const
+{
+ switch (entry.index()) {
+ case STATE_GENFLAGS:
+ str = string_format("%c %c %s %s" ,
+ BIT(m_flags , 3) ? 'Z' : '-' ,
+ BIT(m_flags , 2) ? 'C' : '-' ,
+ BIT(m_flags , 1) ? "FO" : "--" ,
+ BIT(m_flags , 0) ? "FI" : "--");
+ break;
+
+ default:
+ break;
+ }
+}
+
+void isbc202_device::set_output()
+{
+ switch (m_out_sel) {
+ case 0:
+ // Bit What
+ // 6..3 -
+ // 2 Head load
+ // 1 Start timeout
+ // 0 Step pulse
+ if (BIT(m_mask , 1)) {
+ m_inputs[ IN_SEL_TIMEOUT ] = false;
+ m_timeout_timer->adjust(attotime::from_msec(TIMEOUT_MS));
+ }
+ if (BIT(m_mask , 0) && (!m_direction || m_current_drive->trk00_r())) {
+ LOG_DR("Step %s\n" , m_direction ? "OUT" : "IN");
+ m_current_drive->dir_w(m_direction);
+ m_current_drive->stp_w(0);
+ m_current_drive->stp_w(1);
+ }
+ break;
+
+ case 1:
+ // Bit What
+ // 6 Reset data overrun
+ // 5 Set XACK
+ // 4 Set write inhibit
+ // 3 Clear write inhibit
+ // 2 -
+ // 1 Reset RDY latches (0)
+ // 0 -
+ if (BIT(m_mask , 5)) {
+ // Release CPU from wait state
+ LOG_BUS("CPU out of wait state\n");
+ xack_w(0);
+ // Ensure the MCU executes a few instruction before the CPU
+ machine().scheduler().add_quantum(attotime::from_usec(1) , attotime::from_usec(5));
+ m_inputs[ IN_SEL_START ] = false;
+ }
+ if (BIT(m_mask , 4)) {
+ m_wrt_inh = true;
+ }
+ if (BIT(m_mask , 3)) {
+ m_wrt_inh = false;
+ }
+ if (!BIT(m_mask , 1)) {
+ m_ready_ff = 0xf;
+ }
+ break;
+
+ case 2:
+ // Bit What
+ // 6..2 -
+ // 1..0 s1:s0 for PX input selection
+ m_px_s1s0 = m_mask & 3;
+ break;
+
+ case 3:
+ // Bit What
+ // 6 Z2
+ // 5 SR OUT (0 = DATA, 1 = CRC)
+ // 4 Write gate (0)
+ // 3 -
+ // 2 Z1
+ // 1..0 -
+ m_crc_out = BIT(m_mask , 5);
+ set_rd_wr(m_reading, !BIT(m_mask , 4));
+ break;
+
+ case 4:
+ // Bit What
+ // 6 Stepping direction (1 = out, 0 = in)
+ // 5 CRC enable (0)
+ // 4..0 -
+ m_direction = BIT(m_mask , 6);
+ m_crc_enabled = !BIT(m_mask , 5);
+ break;
+
+ case 5:
+ // Bit What
+ // 6..5 -
+ // 4 Mem write (0)
+ // 3 GATE LOWER (0)
+ // 2 -
+ // 1 INOP RESET (0)
+ // 0 AMWRT
+ m_mem_wrt = !BIT(m_mask , 4);
+ m_gate_lower = BIT(m_mask , 3);
+ m_amwrt = BIT(m_mask , 0);
+ break;
+
+ case 6:
+ // Bit What
+ // 6 Latch data bus into A24/A25
+ // 5 Set INT FF
+ // 4 Set Track > 43
+ // 3 Latch D into A[7..0]
+ // 2 Latch D into D[7..0]
+ // 1 Latch D into D[F..8]
+ // 0 Set XFER REQ
+ if (BIT(m_mask , 6)) {
+ m_data_low_in = m_cpu_data;
+ }
+ if (BIT(m_mask , 5)) {
+ m_irq = true;
+ }
+ if (BIT(m_mask , 3)) {
+ m_addr_low_out = dbus_r();
+ }
+ if (BIT(m_mask , 2)) {
+ m_data_low_out = dbus_r();
+ }
+ if (BIT(m_mask , 0)) {
+ if (m_mem_wrt) {
+ if (!m_wrt_inh) {
+ // CPU memory write
+ uint16_t addr = m_addr_low_out | (uint16_t(abus_r()) << 8);
+ if (m_mem_space) {
+ LOG_BUS("MEM W %04x=%02x\n" , addr , m_data_low_out);
+ m_mem_space->write_byte(addr , m_data_low_out);
+ } else {
+ LOG("CPU AS not set!\n");
+ }
+ }
+ } else {
+ // CPU memory read
+ uint16_t addr = m_addr_low_out | (uint16_t(abus_r()) << 8);
+ if (m_mem_space) {
+ m_data_low_in = m_mem_space->read_byte(addr);
+ LOG_BUS("MEM R %04x=%02x\n" , addr , m_data_low_in);
+ } else {
+ LOG("CPU AS not set!\n");
+ }
+ }
+ }
+ break;
+
+ case 7:
+ // Bit What
+ // 6 Latch OP & US
+ // 5 Reset INDEX
+ // 4 Set Track <= 43
+ // 3 Clear START/STOP
+ // 2 Unload head
+ // 1 Set RESET READ
+ // 0 Clear RESET READ
+ if (BIT(m_mask , 6)) {
+ m_op_us = dbus_r() & 0x3f;
+ m_current_drive = m_drives[ selected_drive() ]->get_device();
+ }
+ if (BIT(m_mask , 5)) {
+ m_inputs[ IN_SEL_INDEX ] = false;
+ }
+ if (BIT(m_mask , 3)) {
+ m_cmd = 0;
+ LOG_BUS("CLR ST\n");
+ // TODO: more
+ }
+ if (BIT(m_mask , 1)) {
+ set_rd_wr(false, m_writing);
+ }
+ if (BIT(m_mask , 0)) {
+ set_rd_wr(true, m_writing);
+ }
+ break;
+ }
+}
+
+unsigned isbc202_device::selected_drive() const
+{
+ return (m_op_us >> 4) & 3;
+}
+
+unsigned isbc202_device::drive_idx(floppy_image_device *drive)
+{
+ for (unsigned i = 0; i < 4; ++i) {
+ if (drive == m_drives[ i ]->get_device()) {
+ return i;
+ }
+ }
+ LOG("Unknown drive!\n");
+ return 0;
+}
+
+void isbc202_device::floppy_ready_cb(floppy_image_device *floppy , int state)
+{
+ unsigned idx = drive_idx(floppy);
+
+ uint8_t old_state = m_ready_in;
+
+ if (!state) {
+ BIT_SET(m_ready_in , idx);
+ } else {
+ BIT_CLR(m_ready_in , idx);
+ }
+
+ uint8_t gone_not_ready = ~m_ready_in & old_state;
+
+ BIT_CLR(gone_not_ready, selected_drive());
+
+ m_ready_ff &= ~gone_not_ready;
+}
+
+void isbc202_device::floppy_index_cb(floppy_image_device *floppy , int state)
+{
+ if (state && floppy == m_current_drive) {
+ LOG_DR("Index @%.6f\n" , machine().time().as_double());
+ m_inputs[ IN_SEL_INDEX ] = true;
+ }
+}
+
+uint8_t isbc202_device::dbus_r() const
+{
+ return m_cpes[ 0 ]->dbus_r() |
+ (m_cpes[ 1 ]->dbus_r() << 2) |
+ (m_cpes[ 2 ]->dbus_r() << 4) |
+ (m_cpes[ 3 ]->dbus_r() << 6);
+}
+
+uint8_t isbc202_device::mbus_r() const
+{
+ return m_gate_lower ? 0 : m_data_low_in;
+}
+
+uint8_t isbc202_device::ibus_r()
+{
+ if (!m_ibus_cached) {
+ m_ibus_cached = true;
+ m_ibus = 0xff;
+ if (BIT(m_slk , 0) && BIT(m_mask , 7)) {
+ if (BIT(m_mask , 5)) {
+ // Bit What
+ // 7 Drive 3/1 ready
+ // 6 Drive 2/0 ready
+ // 5 Track 0
+ // 4 STOP
+ // 3..0 1
+ m_ibus = 0x0f;
+ uint8_t ready = m_ready_in & m_ready_ff;
+ if (m_gate_lower) {
+ ready >>= 2;
+ }
+ if (BIT(ready , 1)) {
+ BIT_SET(m_ibus, 7);
+ }
+ if (BIT(ready , 0)) {
+ BIT_SET(m_ibus, 6);
+ }
+ if (!m_current_drive->trk00_r()) {
+ BIT_SET(m_ibus, 5);
+ }
+ // TODO: STOP bit
+ } else if (BIT(m_mask , 6)) {
+ // Bit What
+ // 7 Selected drive not ready
+ // 6 Write fault
+ // 5 Write protection
+ // 4 Data overrun
+ // 3..0 1
+ m_ibus = 0x0f;
+ if (!BIT(m_ready_in , selected_drive())) {
+ BIT_SET(m_ibus, 7);
+ }
+ if (m_current_drive->wpt_r()) {
+ BIT_SET(m_ibus, 5);
+ }
+ } else if (BIT(m_mask , 3)) {
+ // Read clock SR
+ m_ibus = aligned_rd_data(m_clock_sr);
+ } else if (BIT(m_mask , 4)) {
+ // Read data SR
+ m_ibus = aligned_rd_data(m_data_sr);
+ }
+ }
+ }
+
+ return m_ibus;
+}
+
+uint8_t isbc202_device::abus_r() const
+{
+ return m_cpes[ 0 ]->abus_r() |
+ (m_cpes[ 1 ]->abus_r() << 2) |
+ (m_cpes[ 2 ]->abus_r() << 4) |
+ (m_cpes[ 3 ]->abus_r() << 6);
+}
+
+void isbc202_device::set_start(uint8_t off , bool read)
+{
+ m_cmd = off;
+ m_inputs[ IN_SEL_START ] = true;
+ // Put CPU in wait state
+ xack_w(1);
+ m_cpu_rd = read;
+ m_2nd_pass = true;
+ LOG_BUS("CPU in wait state (rd=%d)\n" , read);
+}
+
+void isbc202_device::set_rd_wr(bool new_rd , bool new_wr)
+{
+ if (!m_reading && new_rd) {
+ // Start reading
+ LOG_RD("Start RD @%.6f\n" , machine().time().as_double());
+ m_pll.set_clock(attotime::from_usec(HALF_BIT_CELL_US));
+ m_pll.read_reset(machine().time());
+
+ // Search for next SYNC (16x 1 and a 0)
+ m_byte_timer->reset();
+ m_f_timer->reset();
+ unsigned cnt_trans = 0;
+ attotime rot_period = attotime::from_hz(6);
+ while ((m_pll.ctime - machine().time()) < rot_period) {
+ attotime edge = m_current_drive->get_next_transition(m_pll.ctime);
+ if (edge.is_never()) {
+ break;
+ }
+ attotime tm;
+ bool bit = m_pll.feed_read_data(tm , edge , attotime::never);
+ if (cnt_trans < 32) {
+ if (!(BIT(cnt_trans , 0) ^ bit)) {
+ cnt_trans++;
+ } else {
+ cnt_trans = 0;
+ }
+ } else if (cnt_trans == 32) {
+ if (!bit) {
+ cnt_trans++;
+ } else {
+ cnt_trans = 0;
+ }
+ } else {
+ if (!bit) {
+ LOG_RD("SYNC found @%.6f\n" , m_pll.ctime.as_double());
+ // GOT SYNC!
+ if (m_crc_enabled) {
+ // CRC shouldn't be enabled here or register won't get cleared
+ LOG("Huh? CRC enabled during SYNC scan?\n");
+ }
+ m_crc = 0;
+ // Load the "0" bit into data/clock SR
+ m_data_sr = 0;
+ m_clock_sr = 0;
+ // Read 7 more bits to make a full byte
+ rd_bits(7);
+ // Timer to go off at end of 8th bit of AM byte (when F signal goes high)
+ m_byte_timer->adjust(m_pll.ctime - machine().time());
+ break;
+ } else {
+ cnt_trans = 32;
+ }
+ }
+ }
+ } else if (m_reading && !new_rd) {
+ // Stop reading
+ LOG_RD("Stop RD\n");
+ m_byte_timer->reset();
+ m_f_timer->reset();
+ m_inputs[ IN_SEL_F ] = false;
+ }
+ m_reading = new_rd;
+
+ if (!m_writing && new_wr) {
+ // Start writing
+ LOG_WR("Start WR\n");
+ m_pll.set_clock(attotime::from_usec(HALF_BIT_CELL_US));
+ m_pll.start_writing(machine().time());
+ m_pll.ctime = machine().time();
+ m_last_data_bit = false;
+ m_byte_timer->adjust(attotime::from_usec(HALF_BIT_CELL_US * 14));
+ } else if (m_writing && !new_wr) {
+ // Stop writing
+ LOG_WR("Stop WR\n");
+ m_pll.stop_writing(m_current_drive , machine().time());
+ m_byte_timer->reset();
+ m_f_timer->reset();
+ m_inputs[ IN_SEL_F ] = false;
+ }
+ m_writing = new_wr;
+}
+
+uint8_t isbc202_device::aligned_rd_data(uint16_t sr)
+{
+ attotime tmp{ machine().time() - m_last_f_time };
+
+ // Compute how many bit cells have gone by since the last time F went high
+ unsigned bits = tmp.as_ticks(BIT_FREQUENCY);
+ if (bits) {
+ LOG_RD("Aligning by %u bits\n" , bits);
+ sr <<= bits;
+ }
+ return uint8_t(sr >> 8);
+}
+
+void isbc202_device::rd_bits(unsigned n)
+{
+ while (n--) {
+ attotime edge = m_current_drive->get_next_transition(m_pll.ctime);
+ if (edge.is_never()) {
+ break;
+ }
+ attotime tm;
+ bool clock_bit = m_pll.feed_read_data(tm , edge , attotime::never);
+ edge = m_current_drive->get_next_transition(m_pll.ctime);
+ if (edge.is_never()) {
+ break;
+ }
+ bool data_bit = m_pll.feed_read_data(tm , edge , attotime::never);
+
+ m_clock_sr = (m_clock_sr << 1) | clock_bit;
+ bool crc_bit = BIT(m_data_sr , 15);
+ m_data_sr = (m_data_sr << 1) | data_bit;
+ update_crc(crc_bit);
+ }
+ LOG_RD("CLK %04x DT %04x CRC %04x\n" , m_clock_sr , m_data_sr , m_crc);
+}
+
+void isbc202_device::write_byte()
+{
+ LOG_WR("WR DT %02x CRC %04x CE %d CO %d AW %d @%.6f\n" , m_data_sr & 0xff , m_crc , m_crc_enabled , m_crc_out , m_dlyd_amwrt , machine().time().as_double());
+
+ for (unsigned i = 0; i < 8; i++) {
+ bool sr_bit = BIT(m_data_sr , 7);
+ bool crc_bit = update_crc(sr_bit);
+ bool data_bit = m_crc_out ? crc_bit : sr_bit;
+ bool clock_bit = m_clock_gate && !data_bit && !m_last_data_bit;
+ if (i <= 3 && m_dlyd_amwrt) {
+ m_clock_gate = true;
+ } else {
+ m_clock_gate = !data_bit && !clock_bit;
+ }
+ attotime dummy;
+
+ m_pll.write_next_bit(clock_bit , dummy , nullptr , attotime::never);
+ m_pll.write_next_bit(data_bit , dummy , nullptr , attotime::never);
+ m_data_sr <<= 1;
+ m_last_data_bit = data_bit;
+ }
+ m_pll.commit(m_current_drive , machine().time());
+ m_pll.ctime = machine().time();
+}
+
+bool isbc202_device::update_crc(bool bit)
+{
+ bool out = BIT(m_crc , 15);
+
+ if (m_crc_enabled && (out ^ bit)) {
+ m_crc = (m_crc << 1) ^ CRC_POLY;
+ } else {
+ m_crc <<= 1;
+ }
+
+ return out;
+}
diff --git a/src/devices/bus/multibus/isbc202.h b/src/devices/bus/multibus/isbc202.h
new file mode 100644
index 00000000000..cde1589993f
--- /dev/null
+++ b/src/devices/bus/multibus/isbc202.h
@@ -0,0 +1,163 @@
+// license:BSD-3-Clause
+// copyright-holders: F. Ulivi
+/*********************************************************************
+
+ isbc202.h
+
+ Intel iSBC-202 SSDD 8" floppy disk controller
+
+*********************************************************************/
+
+#ifndef MAME_BUS_MULTIBUS_ISBC202_H
+#define MAME_BUS_MULTIBUS_ISBC202_H
+
+#pragma once
+
+#include "multibus.h"
+#include "machine/i3001.h"
+#include "machine/i3002.h"
+#include "machine/fdc_pll.h"
+#include "imagedev/floppy.h"
+
+class isbc202_device : public cpu_device,
+ public device_multibus_interface
+{
+public:
+ // Construction/destruction
+ isbc202_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock);
+ virtual ~isbc202_device();
+
+ // Access to I/O space by CPU
+ uint8_t io_r(address_space &space, offs_t offset);
+ void io_w(address_space &space, offs_t offset, uint8_t data);
+
+ void co_w(int state);
+
+ uint8_t px_r();
+
+protected:
+ // device_t overrides
+ virtual void device_start() override ATTR_COLD;
+ virtual void device_reset() override ATTR_COLD;
+ virtual const tiny_rom_entry *device_rom_region() const override ATTR_COLD;
+ virtual void device_add_mconfig(machine_config &config) override ATTR_COLD;
+
+ // device_execute_interface overrides
+ virtual uint32_t execute_min_cycles() const noexcept override { return 1; }
+ virtual void execute_run() override;
+
+ // device_memory_interface overrides
+ virtual space_config_vector memory_space_config() const override;
+
+ // device_disasm_interface overrides
+ virtual std::unique_ptr<util::disasm_interface> create_disassembler() override;
+
+ // device_state_interface overrides
+ virtual void state_import(const device_state_entry &entry) override;
+ virtual void state_export(const device_state_entry &entry) override;
+ virtual void state_string_export(const device_state_entry &entry, std::string &str) const override;
+
+private:
+ required_device<i3001_device> m_mcu;
+ required_device_array<i3002_device , 4> m_cpes;
+ required_device_array<floppy_connector , 4> m_drives;
+
+ address_space_config m_program_config;
+ memory_access<9, 2 , -2 , ENDIANNESS_BIG>::cache m_cache;
+
+ address_space *m_mem_space;
+
+ int m_icount;
+ uint8_t m_flags;
+ uint8_t m_regs[ i3002_device::REG_COUNT ];
+ uint16_t m_microcode_addr;
+ uint32_t m_code_word;
+ uint8_t m_ac;
+ uint8_t m_fc;
+ bool m_fc32;
+ bool m_fc10;
+ enum { // m_in_sel Input on AC[0]
+ IN_SEL_AC0, // 0 AC[0]
+ IN_SEL_CO, // 1 CO
+ IN_SEL_START, // 2 START
+ IN_SEL_F, // 3 F
+ IN_SEL_AZ, // 4 AZ
+ IN_SEL_INDEX, // 5 INDEX
+ IN_SEL_XFERQ, // 6 XFERREQ
+ IN_SEL_TIMEOUT,//7 TIMEOUT
+ IN_SEL_COUNT
+ };
+ uint8_t m_in_sel;
+ uint8_t m_out_sel;
+ uint8_t m_slk;
+ uint8_t m_mask;
+ uint8_t m_kbus;
+ bool m_inputs[ IN_SEL_COUNT ];
+ // IC identifiers have this form: x-Ayy
+ // where x is either C (for channel board) or I (for interface board)
+ // and yy is the numeric IC ID.
+ uint8_t m_op_us; // C-A44
+ floppy_image_device *m_current_drive;
+ uint8_t m_px_s1s0; // C-A16-11 & C-A16-13
+ uint8_t m_cmd; // C-A8
+ bool m_2nd_pass;
+ bool m_cpu_rd;
+ uint8_t m_ready_in;
+ uint8_t m_ready_ff; // I-A44 & I-A43
+ bool m_gate_lower; // I-A58-9
+ bool m_irq; // C-A37-9
+ uint8_t m_data_low_out; // C-A43
+ uint8_t m_data_low_in; // C-A25
+ uint8_t m_cpu_data;
+ uint8_t m_addr_low_out; // C-A41
+ bool m_mem_wrt; // I-A58-4
+ bool m_wrt_inh; // I-A46-13
+ bool m_direction; // I-A58-11
+ bool m_ibus_cached;
+ uint8_t m_ibus;
+ uint16_t m_crc; // I-A62
+ bool m_crc_enabled; // I-A58-13
+ bool m_crc_out; // C-A16-2
+ bool m_reading; // I-A46-9
+ bool m_writing; // C-A16-4
+ uint16_t m_data_sr; // C-A36 & C-A29 (MSB), next byte in LSB
+ bool m_last_data_bit; // I-A48-6
+ uint16_t m_clock_sr; // C-A34 & C-A27 (MSB), next byte in LSB
+ attotime m_last_f_time;
+ bool m_clock_gate; // I-A10-8
+ bool m_amwrt; // I-A58-6
+ bool m_dlyd_amwrt;
+
+ // PLL
+ fdc_pll_t m_pll;
+
+ // Timers
+ emu_timer *m_timeout_timer;
+ emu_timer *m_byte_timer;
+ emu_timer *m_f_timer;
+
+ TIMER_CALLBACK_MEMBER(timeout_tick);
+ TIMER_CALLBACK_MEMBER(byte_tick);
+ TIMER_CALLBACK_MEMBER(f_tick);
+
+ void set_output();
+ unsigned selected_drive() const;
+ unsigned drive_idx(floppy_image_device *drive);
+ void floppy_ready_cb(floppy_image_device *floppy , int state);
+ void floppy_index_cb(floppy_image_device *floppy , int state);
+ uint8_t dbus_r() const;
+ uint8_t mbus_r() const;
+ uint8_t abus_r() const;
+ uint8_t ibus_r();
+ void set_start(uint8_t off , bool read);
+ void set_rd_wr(bool new_rd , bool new_wr);
+ uint8_t aligned_rd_data(uint16_t sr);
+ void rd_bits(unsigned n);
+ void write_byte();
+ bool update_crc(bool bit);
+};
+
+// device type declaration
+DECLARE_DEVICE_TYPE(ISBC202, isbc202_device)
+
+#endif /* MAME_BUS_MULTIBUS_ISBC202_H */
diff --git a/src/devices/bus/multibus/isbc8024.cpp b/src/devices/bus/multibus/isbc8024.cpp
new file mode 100644
index 00000000000..df6dbbe8390
--- /dev/null
+++ b/src/devices/bus/multibus/isbc8024.cpp
@@ -0,0 +1,156 @@
+// license:BSD-3-Clause
+// copyright-holders:Patrick Mackinlay
+
+/*
+ * Intel iSBC 80/24 Single Board Computer
+ *
+ * Sources:
+ * - http://www.bitsavers.org/pdf/intel/iSBC/148437-001_iSBC_80_24A_Hardware_Reference_Manual_Nov85.pdf
+ *
+ * TODO:
+ * - configurable eprom quantity/size
+ * - configurable irq, clock and I/O
+ * - reverse engineer unknown firmware
+ * - led output
+ */
+
+#include "emu.h"
+#include "isbc8024.h"
+
+#define VERBOSE 0
+#include "logmacro.h"
+
+DEFINE_DEVICE_TYPE(ISBC8024, isbc8024_device, "isbc8024", "Intel iSBC 80/24 Single Board Computer")
+
+isbc8024_device::isbc8024_device(machine_config const &mconfig, char const *tag, device_t *owner, u32 clock)
+ : device_t(mconfig, ISBC8024, tag, owner, clock)
+ , device_multibus_interface(mconfig, *this)
+ , m_cpu(*this, "cpu")
+ , m_pit(*this, "pit")
+ , m_pci(*this, "pci")
+ , m_ppi(*this, "ppi%u", 0U)
+ , m_pic(*this, "pic")
+ , m_j3(*this, "j3")
+ , m_conf(*this, "CONF")
+ , m_installed(false)
+{
+}
+
+ROM_START(isbc8024)
+ ROM_REGION(0x1000, "eprom", 0)
+ ROM_SYSTEM_BIOS(0, "unknown", "unknown")
+ ROMX_LOAD("unknown.u50", 0x000, 0x800, CRC(28b18721) SHA1(37526ed0a4f1e910fc0a8f6af0708c77a7358f69), ROM_BIOS(0))
+ ROMX_LOAD("unknown.u51", 0x800, 0x800, CRC(9e49f6ad) SHA1(565ab4740d3151eb4d8ef9ff3e02570cf7804be1), ROM_BIOS(0))
+ROM_END
+
+static INPUT_PORTS_START(isbc8024)
+ PORT_START("CONF")
+ PORT_CONFNAME(0x0003, 0x0003, "Size")
+ PORT_CONFSETTING( 0x0000, "None")
+ PORT_CONFSETTING( 0x0001, "2048")
+ PORT_CONFSETTING( 0x0002, "4096")
+ PORT_CONFSETTING( 0x0003, "8192")
+
+ PORT_CONFNAME(0xf000, 0xf000, "End")
+ PORT_CONFSETTING( 0x3000, "3FFF")
+ PORT_CONFSETTING( 0x7000, "7FFF")
+ PORT_CONFSETTING( 0xb000, "BFFF")
+ PORT_CONFSETTING( 0xf000, "FFFF")
+INPUT_PORTS_END
+
+const tiny_rom_entry *isbc8024_device::device_rom_region() const
+{
+ return ROM_NAME(isbc8024);
+}
+
+ioport_constructor isbc8024_device::device_input_ports() const
+{
+ return INPUT_PORTS_NAME(isbc8024);
+}
+
+void isbc8024_device::device_start()
+{
+}
+
+void isbc8024_device::device_reset()
+{
+ if (!m_installed)
+ {
+ ioport_value const conf = m_conf->read();
+ if (conf & 3)
+ {
+ size_t const ram_size = 1024 << (conf & 3);
+ offs_t ram_end = (conf & 0xf000) | 0x0fff;
+
+ std::unique_ptr<u8[]> const ram = std::make_unique<u8[]>(ram_size);
+ m_cpu->space(AS_PROGRAM).install_ram(ram_end - ram_size + 1, ram_end, ram.get());
+ }
+
+ // TODO: what's exposed to the Multibus?
+
+ m_installed = true;
+ }
+}
+
+void isbc8024_device::device_add_mconfig(machine_config &config)
+{
+ I8085A(config, m_cpu, 19'354'000 / 2);
+ m_cpu->set_addrmap(AS_PROGRAM, &isbc8024_device::cpu_mem_map);
+ m_cpu->set_addrmap(AS_IO, &isbc8024_device::cpu_pio_map);
+
+ PIT8254(config, m_pit);
+ m_pit->set_clk<0>(19'354'000 / 18);
+ m_pit->set_clk<1>(19'354'000 / 18);
+ m_pit->set_clk<2>(19'354'000 / 18);
+ m_pit->out_handler<0>().set(m_pic, FUNC(pic8259_device::ir2_w));
+ //m_pit->out_handler<1>().set(m_pic, FUNC(pic8259_device::ir?));
+ m_pit->out_handler<2>().append(m_pci, FUNC(i8251_device::write_rxc));
+ m_pit->out_handler<2>().append(m_pci, FUNC(i8251_device::write_txc));
+
+ I8251(config, m_pci, 0);
+
+ I8255(config, m_ppi[0], 0); // j1
+ I8255(config, m_ppi[1], 0); // j2
+
+ PIC8259(config, m_pic);
+ m_pic->out_int_callback().set_inputline(m_cpu, I8085_INTR_LINE);
+ int_callback<2>().set(m_pic, FUNC(pic8259_device::ir1_w));
+
+ RS232_PORT(config, m_j3, default_rs232_devices, nullptr);
+
+ m_pci->txd_handler().set(m_j3, FUNC(rs232_port_device::write_txd));
+ m_pci->dtr_handler().set(m_j3, FUNC(rs232_port_device::write_dtr));
+ m_pci->rts_handler().set(m_j3, FUNC(rs232_port_device::write_rts));
+ m_j3->rxd_handler().set(m_pci, FUNC(i8251_device::write_rxd));
+ m_j3->dsr_handler().set(m_pci, FUNC(i8251_device::write_dsr));
+ m_j3->cts_handler().set(m_pci, FUNC(i8251_device::write_cts));
+}
+
+void isbc8024_device::cpu_mem_map(address_map &map)
+{
+ // default off-board mem access to multibus
+ map(0x0000, 0xffff).rw(FUNC(isbc8024_device::bus_mem_r), FUNC(isbc8024_device::bus_mem_w));
+
+ // TODO: variable number and size of EPROMs
+ map(0x0000, 0x0fff).rom().region("eprom", 0);
+}
+
+void isbc8024_device::cpu_pio_map(address_map &map)
+{
+ // default off-board pio access to multibus
+ map(0x00, 0xff).rw(FUNC(isbc8024_device::bus_pio_r), FUNC(isbc8024_device::bus_pio_w));
+
+ map(0xd4, 0xd4).noprw(); // TODO: power fail
+ //map(0xd5, 0xd5); // system bus override
+ map(0xd6, 0xd6).lw8([this](u8 data) { popmessage("LED"); }, "led_w"); // led diagnostic indicator
+ map(0xd7, 0xd7).noprw(); // reserved
+ map(0xd8, 0xd9).rw(m_pic, FUNC(pic8259_device::read), FUNC(pic8259_device::write)).mirror(0x02);
+ map(0xdc, 0xdf).rw(m_pit, FUNC(pit8254_device::read), FUNC(pit8254_device::write));
+ map(0xe4, 0xe7).rw(m_ppi[0], FUNC(i8255_device::read), FUNC(i8255_device::write));
+ map(0xe8, 0xeb).rw(m_ppi[1], FUNC(i8255_device::read), FUNC(i8255_device::write));
+ map(0xec, 0xed).rw(m_pci, FUNC(i8251_device::read), FUNC(i8251_device::write)).mirror(0x02);
+ //map(0xc0, 0xc7); // mutimodule 1 mcs0/ j5
+ //map(0xc8, 0xcf); // mutimodule 1 mcs1/ j5
+ //map(0xf0, 0xf7); // mutimodule 2 mcs0/ j6
+ //map(0xf8, 0xff); // mutimodule 2 mcs1/ j6
+}
diff --git a/src/devices/bus/multibus/isbc8024.h b/src/devices/bus/multibus/isbc8024.h
new file mode 100644
index 00000000000..ece5d98b78b
--- /dev/null
+++ b/src/devices/bus/multibus/isbc8024.h
@@ -0,0 +1,57 @@
+// license:BSD-3-Clause
+// copyright-holders:Patrick Mackinlay
+
+#ifndef MAME_BUS_MULTIBUS_ISBC8024_H
+#define MAME_BUS_MULTIBUS_ISBC8024_H
+
+#pragma once
+
+#include "multibus.h"
+
+#include "cpu/i8085/i8085.h"
+#include "machine/pit8253.h"
+#include "machine/i8251.h"
+#include "machine/i8255.h"
+#include "machine/pic8259.h"
+
+#include "bus/rs232/rs232.h"
+
+class isbc8024_device
+ : public device_t
+ , public device_multibus_interface
+{
+public:
+ isbc8024_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 ATTR_COLD;
+ virtual void device_add_mconfig(machine_config &config) override ATTR_COLD;
+ virtual ioport_constructor device_input_ports() const override ATTR_COLD;
+ virtual void device_start() override ATTR_COLD;
+ virtual void device_reset() override ATTR_COLD;
+
+private:
+ void cpu_mem_map(address_map &map) ATTR_COLD;
+ void cpu_pio_map(address_map &map) ATTR_COLD;
+
+ void bus_mem_w(offs_t offset, u8 data) { m_bus->space(AS_PROGRAM).write_byte(offset, data); }
+ u8 bus_mem_r(offs_t offset) { return m_bus->space(AS_PROGRAM).read_byte(offset); }
+ void bus_pio_w(offs_t offset, u8 data) { m_bus->space(AS_IO).write_byte(offset, data); }
+ u8 bus_pio_r(offs_t offset) { return m_bus->space(AS_IO).read_byte(offset); }
+
+ required_device<i8085a_cpu_device> m_cpu;
+ required_device<pit8254_device> m_pit;
+ required_device<i8251_device> m_pci;
+ required_device_array<i8255_device, 2> m_ppi;
+ required_device<pic8259_device> m_pic;
+ required_device<rs232_port_device> m_j3;
+
+ required_ioport m_conf;
+
+ bool m_installed;
+};
+
+DECLARE_DEVICE_TYPE(ISBC8024, isbc8024_device)
+
+#endif // MAME_BUS_MULTIBUS_ISBC8024_H
diff --git a/src/devices/bus/multibus/labtam_3232.cpp b/src/devices/bus/multibus/labtam_3232.cpp
new file mode 100644
index 00000000000..11eab51a107
--- /dev/null
+++ b/src/devices/bus/multibus/labtam_3232.cpp
@@ -0,0 +1,123 @@
+// license:BSD-3-Clause
+// copyright-holders:Patrick Mackinlay
+
+/*
+ * Labtam 3000 3232 (V32?) processor board.
+ *
+ * Sources:
+ * - http://www.cpu-ns32k.net/Multi.html
+ * - https://arvutimuuseum.ut.ee/index.php?m=eksponaadid&id=223
+ *
+ * TODO:
+ * - skeleton only
+ */
+
+#include "emu.h"
+#include "labtam_3232.h"
+
+#define VERBOSE 0
+#include "logmacro.h"
+
+DEFINE_DEVICE_TYPE(LABTAM_3232, labtam_3232_device, "labtam_3232", "Labtam 3232")
+
+labtam_3232_device::labtam_3232_device(machine_config const &mconfig, char const *tag, device_t *owner, u32 clock)
+ : device_t(mconfig, LABTAM_3232, tag, owner, clock)
+ , device_multibus_interface(mconfig, *this)
+ , m_cpu(*this, "cpu")
+ , m_fpu(*this, "fpu")
+ , m_mmu(*this, "mmu")
+ , m_icu(*this, "icu")
+ , m_boot(*this, "boot")
+ , m_installed(false)
+{
+}
+
+ROM_START(labtam_3232)
+ ROM_REGION32_LE(0x10000, "eprom", 0)
+ 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)
+INPUT_PORTS_END
+
+const tiny_rom_entry *labtam_3232_device::device_rom_region() const
+{
+ return ROM_NAME(labtam_3232);
+}
+
+ioport_constructor labtam_3232_device::device_input_ports() const
+{
+ return INPUT_PORTS_NAME(labtam_3232);
+}
+
+void labtam_3232_device::device_start()
+{
+}
+
+void labtam_3232_device::device_reset()
+{
+ if (!m_installed)
+ {
+ // TODO: what's exposed to the Multibus?
+#if 0
+ m_bus->int_callback<0>().set(m_icu, FUNC(ns32202_device::ir_w<0>));
+ m_bus->int_callback<1>().set(m_icu, FUNC(ns32202_device::ir_w<1>));
+ m_bus->int_callback<2>().set(m_icu, FUNC(ns32202_device::ir_w<3>));
+ m_bus->int_callback<3>().set(m_icu, FUNC(ns32202_device::ir_w<4>));
+ m_bus->int_callback<4>().set(m_icu, FUNC(ns32202_device::ir_w<6>));
+ m_bus->int_callback<5>().set(m_icu, FUNC(ns32202_device::ir_w<7>));
+ m_bus->int_callback<6>().set(m_icu, FUNC(ns32202_device::ir_w<8>));
+ m_bus->int_callback<7>().set([this](int state) { m_s8->read() ? m_cpu->set_input_line(INPUT_LINE_NMI, !state) : m_icu->ir_w<11>(state); });
+#endif
+ m_installed = true;
+ }
+
+ m_boot.select(0);
+}
+
+void labtam_3232_device::device_add_mconfig(machine_config &config)
+{
+ NS32032(config, m_cpu, 20_MHz_XTAL / 2);
+ m_cpu->set_addrmap(0, &labtam_3232_device::cpu_map<0>);
+ m_cpu->set_addrmap(4, &labtam_3232_device::cpu_map<4>);
+
+ NS32081(config, m_fpu, 20_MHz_XTAL / 2);
+ m_cpu->set_fpu(m_fpu);
+
+ NS32082(config, m_mmu, 20_MHz_XTAL / 2);
+ m_cpu->set_mmu(m_mmu);
+
+ NS32202(config, m_icu, 20_MHz_XTAL / 2);
+ m_icu->out_int().set_inputline(m_cpu, INPUT_LINE_IRQ0).invert();
+}
+
+template <unsigned ST> void labtam_3232_device::cpu_map(address_map &map)
+{
+ if (ST == 0)
+ {
+ map(0x00000000, 0x007fffff).view(m_boot);
+
+ m_boot[0](0x00000000, 0x0000ffff).rom().region("eprom", 0);
+ m_boot[1](0x00000000, 0x001fffff).ram(); // 2M on-board RAM with parity (up to 8M possible?)
+
+ // 0xd00000 - maybe multibus memory or i/o?
+ map(0x00d00413, 0x00d00413).lr8([]() { return 0x18; }, "unknown_r8");
+ map(0x00d00500, 0x00d00503).lr16([]() { return 0x0003; }, "unknown_r16");
+
+ map(0x00f80000, 0x00f8ffff).rom().region("eprom", 0);
+
+ map(0x00fff914, 0x00fff914).lw8([this](u8 data) { m_boot.select(1); }, "men_w"); // ram enable?
+ }
+
+ map(0xfffe00, 0xfffeff).m(m_icu, FUNC(ns32202_device::map<BIT(ST, 1)>)).umask32(0x000000ff);
+}
diff --git a/src/devices/bus/multibus/labtam_3232.h b/src/devices/bus/multibus/labtam_3232.h
new file mode 100644
index 00000000000..8511428eba0
--- /dev/null
+++ b/src/devices/bus/multibus/labtam_3232.h
@@ -0,0 +1,51 @@
+// license:BSD-3-Clause
+// copyright-holders:Patrick Mackinlay
+
+#ifndef MAME_BUS_MULTIBUS_LABTAM_3232_H
+#define MAME_BUS_MULTIBUS_LABTAM_3232_H
+
+#pragma once
+
+#include "multibus.h"
+
+#include "cpu/ns32000/ns32000.h"
+#include "machine/ns32081.h"
+#include "machine/ns32082.h"
+#include "machine/ns32202.h"
+
+class labtam_3232_device
+ : public device_t
+ , public device_multibus_interface
+{
+public:
+ labtam_3232_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 ATTR_COLD;
+ virtual void device_add_mconfig(machine_config &config) override ATTR_COLD;
+ virtual ioport_constructor device_input_ports() const override ATTR_COLD;
+ virtual void device_start() override ATTR_COLD;
+ virtual void device_reset() override ATTR_COLD;
+
+private:
+ template <unsigned ST> void cpu_map(address_map &map) ATTR_COLD;
+
+ //void bus_mem_w(offs_t offset, u16 data, u16 mem_mask) { m_bus->space(AS_PROGRAM).write_word(0xe00000 | offset << 1, data, mem_mask); }
+ //u16 bus_mem_r(offs_t offset, u16 mem_mask) { return m_bus->space(AS_PROGRAM).read_word(0xe00000 | offset << 1, mem_mask); }
+ //void bus_pio_w(offs_t offset, u16 data, u16 mem_mask) { m_bus->space(AS_IO).write_word(offset << 1, data, mem_mask); }
+ //u16 bus_pio_r(offs_t offset, u16 mem_mask) { return m_bus->space(AS_IO).read_word(offset << 1, mem_mask); }
+
+ required_device<ns32032_device> m_cpu;
+ required_device<ns32081_device> m_fpu;
+ required_device<ns32082_device> m_mmu;
+ required_device<ns32202_device> m_icu;
+
+ memory_view m_boot;
+
+ bool m_installed;
+};
+
+DECLARE_DEVICE_TYPE(LABTAM_3232, labtam_3232_device)
+
+#endif // MAME_BUS_MULTIBUS_LABTAM_3232_H
diff --git a/src/devices/bus/multibus/labtam_vducom.cpp b/src/devices/bus/multibus/labtam_vducom.cpp
new file mode 100644
index 00000000000..456ce36f8e6
--- /dev/null
+++ b/src/devices/bus/multibus/labtam_vducom.cpp
@@ -0,0 +1,455 @@
+// license:BSD-3-Clause
+// copyright-holders:Patrick Mackinlay
+
+/*
+ * Labtam 3000 8086 VDU COMM card.
+ *
+ * Sources:
+ * - https://arvutimuuseum.ut.ee/index.php?m=eksponaadid&id=223
+ *
+ * TODO:
+ * - 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"
+
+enum u7_mask : u8
+{
+ U7_PWRFAIL = 0x01, // enable multibus access
+ U7_WINDOW = 0x02, // 0=lower 512k, 1=upper 512k
+ U7_SWAP = 0x04, // swap data & display segments
+ U7_VDOUBLE = 0x08, // enable double vertical resolution
+ U7_HALF = 0x10, // enable half intensity
+ U7_CLICK = 0x20, // disable key click
+ U7_BLANK = 0x80, // disable blanked screen
+};
+
+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_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)
+{
+}
+
+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_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(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, "Disable Graphics") PORT_DIPLOCATION("E4:2")
+ PORT_DIPSETTING(0x00, DEF_STR(Yes))
+ 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(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, 0x00, "Disable Graphics") PORT_DIPLOCATION("E4:2")
+ PORT_DIPSETTING(0x00, DEF_STR(Yes))
+ 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(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 const gfx_layout vducom_char_set_1 =
+{
+ 8, 12, 64, 1,
+ { 0 },
+ { 7, 6, 5, 4, 3, 2, 1, 0 },
+ { 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 * 12
+};
+
+static const gfx_layout vducom_char_set_2 =
+{
+ 8, 12, 96, 1,
+ { 0 },
+ { 7, 6, 5, 4, 3, 2, 1, 0 },
+ { 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 * 12
+};
+
+static GFXDECODE_START(labtam_vducom)
+ GFXDECODE_ENTRY("eprom", 0xbc80, vducom_char_set_1, 0, 1)
+ GFXDECODE_ENTRY("eprom", 0xc100, vducom_char_set_2, 0, 1)
+GFXDECODE_END
+
+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);
+}
+
+ioport_constructor labtam_8086cpu_device::device_input_ports() const
+{
+ return INPUT_PORTS_NAME(labtam_8086cpu);
+}
+
+void labtam_vducom_device_base::device_start()
+{
+ save_item(NAME(m_start));
+ save_item(NAME(m_u7));
+}
+
+void labtam_vducom_device_base::device_reset()
+{
+ if (!m_installed)
+ m_installed = true;
+
+ m_u7 = 0;
+ m_start = 0;
+
+ m_nvram[0]->recall(1);
+ 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_base::device_add_mconfig(machine_config &config)
+{
+ I8086(config, m_cpu, 16_MHz_XTAL / 2);
+ 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[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[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);
+ int_callback<3>().set(m_pic, FUNC(pic8259_device::ir6_w));
+
+ UPD7201(config, m_com[0], 16_MHz_XTAL / 4);
+ m_com[0]->out_int_callback().set(m_pic, FUNC(pic8259_device::ir3_w));
+
+ 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, 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);
+ PALETTE(config, m_palette, FUNC(labtam_vducom_device::palette_init), 4);
+
+ SCREEN(config, m_screen, SCREEN_TYPE_RASTER);
+ 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_base::cpu_mem(address_map &map)
+{
+ map(0x00000, 0x0ffff).ram().share("ram1");
+ map(0x10000, 0x1ffff).ram().share("ram0");
+ map(0x20000, 0x2ffff).rom().region("eprom", 0).mirror(0x50000);
+
+ 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_base::bus_mem_r), FUNC(labtam_vducom_device_base::bus_mem_w));
+}
+
+void labtam_vducom_device_base::cpu_pio(address_map &map)
+{
+ map(0x0000, 0x7fff).rw(FUNC(labtam_vducom_device_base::bus_pio_r), FUNC(labtam_vducom_device_base::bus_pio_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_base::nvram_r), FUNC(labtam_vducom_device_base::nvram_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(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)
+{
+ // 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());
+}
+
+// non-interlace: two planes 800x300, each 32k, 2bpp -> 4 levels (black, dim, normal, bold)
+// interlace: one plane 800x600, 64k, (black, normal)
+MC6845_UPDATE_ROW(labtam_vducom_device::update_row)
+{
+ 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++)
+ {
+ u16 const data0 = ram[(offset + x)];
+ u16 const data1 = ram[(offset + x) ^ 0x4000];
+
+ for (unsigned b = 0; b < 16; b++)
+ {
+ unsigned c = BIT(data0, b) << 1;
+ if (u7() & U7_HALF)
+ c |= BIT(data1, b);
+
+ bitmap.pix(y, x * 16 + b) = m_palette->pen_color(c);
+ }
+ }
+}
+
+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());
+
+ if (BIT(data, 0))
+ m_u7 |= 1U << offset;
+ else
+ m_u7 &= ~(1U << offset);
+
+ m_mbus.select(BIT(m_u7, 0));
+}
+
+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_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
new file mode 100644
index 00000000000..fa017d372ea
--- /dev/null
+++ b/src/devices/bus/multibus/labtam_vducom.h
@@ -0,0 +1,109 @@
+// license:BSD-3-Clause
+// copyright-holders:Patrick Mackinlay
+
+#ifndef MAME_BUS_MULTIBUS_LABTAM_VDUCOM_H
+#define MAME_BUS_MULTIBUS_LABTAM_VDUCOM_H
+
+#pragma once
+
+#include "multibus.h"
+
+#include "cpu/i86/i86.h"
+#include "machine/am9513.h"
+#include "machine/pic8259.h"
+#include "machine/x2212.h"
+#include "machine/z80sio.h"
+#include "video/mc6845.h"
+
+#include "bus/rs232/rs232.h"
+
+#include "emupal.h"
+#include "screen.h"
+
+
+class labtam_vducom_device_base
+ : public device_t
+ , public device_multibus_interface
+{
+protected:
+ 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 ATTR_COLD;
+ virtual void device_start() override ATTR_COLD;
+ virtual void device_reset() override ATTR_COLD;
+
+ void cpu_mem(address_map &map) ATTR_COLD;
+ virtual void cpu_pio(address_map &map) ATTR_COLD;
+
+ void bus_mem_w(offs_t offset, u16 data, u16 mem_mask);
+ u16 bus_mem_r(offs_t offset, u16 mem_mask);
+ void bus_pio_w(offs_t offset, u16 data, u16 mem_mask) { m_bus->space(AS_IO).write_word(offset << 1, data, mem_mask); }
+ u16 bus_pio_r(offs_t offset, u16 mem_mask) { return m_bus->space(AS_IO).read_word(offset << 1, mem_mask); }
+
+ u8 nvram_r(address_space &space, offs_t offset) { return m_nvram[1]->read(space, offset) << 4 | m_nvram[0]->read(space, offset); }
+ void nvram_w(offs_t offset, u8 data) { m_nvram[0]->write(offset, data & 0x0f); m_nvram[1]->write(offset, data >> 4); }
+
+ u8 u15_r(offs_t offset) { return BIT(m_e4->read(), offset); }
+ void u7_w(offs_t offset, u8 data);
+
+ 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_array<rs232_port_device, 4> m_serial;
+
+private:
+ required_ioport m_e4;
+ memory_view m_mbus;
+
+ u16 m_start;
+ u8 m_u7;
+
+ bool m_installed;
+};
+
+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 ATTR_COLD;
+ virtual const tiny_rom_entry *device_rom_region() const override ATTR_COLD;
+};
+
+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 ATTR_COLD;
+ virtual const tiny_rom_entry *device_rom_region() const override ATTR_COLD;
+ virtual void device_add_mconfig(machine_config &config) override ATTR_COLD;
+
+ virtual void cpu_pio(address_map &map) override ATTR_COLD;
+
+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
new file mode 100644
index 00000000000..db60e831c95
--- /dev/null
+++ b/src/devices/bus/multibus/labtam_z80sbc.cpp
@@ -0,0 +1,603 @@
+// license:BSD-3-Clause
+// copyright-holders:Patrick Mackinlay
+
+/*
+ * Labtam 3000 Z80 SBC card.
+ *
+ * Sources:
+ * - https://arvutimuuseum.ut.ee/index.php?m=eksponaadid&id=223
+ *
+ * TODO:
+ * - serial
+ */
+/*
+ * Part Type Function
+ * ---- ---- --------
+ * MCM93422PC * 3 256x4 RAM memory mapper (8 maps of 32, 12-bit entries)
+ * M5K4164ANP * 16 64x1 DRAM 128KiB main memory
+ * M58725P 2048x8 SRAM resident bus RAM
+ * WD2793A-PL02 floppy disk formatter/controller
+ * Z80A CPU
+ * Z80A DMA * 2 fdc and sio dma
+ * Z80A SIO/2
+ * AM9513PC system timing controller
+ * MM58167AN real time clock
+ * AM9519APC universal interrupt controller
+ *
+ * D8203-1 DRAM controller
+ * AM2946PC * 4
+ * DP8304BN
+ *
+ * 25MHz
+ * 20MHz
+ * 8MHz
+ */
+
+#include "emu.h"
+#include "labtam_z80sbc.h"
+
+#define VERBOSE 0
+#include "logmacro.h"
+
+enum map_mux_mask : u8
+{
+ MM_ENB = 0x01, // mapper enabled
+ MM_INT = 0x02, // interrupt map mode selected (mapnum=0)
+ MM_PND = 0x04, // map mode change pending next non-instruction memory read
+};
+
+enum mapwr1_mask : u8
+{
+ MAPWR1_MA19 = 0x10, // multibus address bit 19
+ MAPWR1_WP = 0x20, // write protect
+ MAPWR1_MEM = 0x40, // memory access
+ MAPWR1_RESB = 0x80, // resident bus select
+};
+
+enum drvstatus_mask : u8
+{
+ DRVSTATUS_A = 0x01, // FD0 is mini floppy
+ DRVSTATUS_C = 0x02, // FD1 is mini floppy
+ DRVSTATUS_E = 0x04, // FD2 is mini floppy
+ DRVSTATUS_G = 0x08, // FD3 is mini floppy
+ DRVSTATUS_B = 0x10, // not used
+ DRVSTATUS_D = 0x20, // not used
+ DRVSTATUS_F = 0x40, // ?
+ DRVSTATUS_DS = 0x80, // floppy is double-sided
+};
+
+DEFINE_DEVICE_TYPE(LABTAM_Z80SBC, labtam_z80sbc_device, "labtam_z80sbc", "Labtam Z80 SBC")
+
+labtam_z80sbc_device::labtam_z80sbc_device(machine_config const &mconfig, char const *tag, device_t *owner, u32 clock)
+ : device_t(mconfig, LABTAM_Z80SBC, tag, owner, clock)
+ , device_multibus_interface(mconfig, *this)
+ , m_cpu(*this, "cpu")
+ , m_stc(*this, "stc")
+ , m_uic(*this, "uic")
+ , m_rtc(*this, "rtc")
+ , m_fdc(*this, "fdc")
+ , m_dma(*this, "dma%u", 0U)
+ , m_sio(*this, "sio")
+ , m_int(*this, "int")
+ , m_fdd(*this, "fdd%u", 0U)
+ , m_eprom(*this, "eprom%u", 0U)
+ , m_e15(*this, "E15%c", 'A')
+ , m_e21(*this, "E21")
+ , m_installed(false)
+{
+}
+
+ROM_START(labtam_z80sbc)
+ ROM_SYSTEM_BIOS(0, "c85", "Version C85")
+ ROM_SYSTEM_BIOS(1, "a85", "Version A85")
+
+ ROM_REGION(0x2000, "eprom0", 0)
+ 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)
+ 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)
+ PORT_START("E15A")
+ PORT_DIPNAME(0x00f0, 0x00f0, "I/O Low")
+ PORT_DIPSETTING(0x0000, "0000h")
+ PORT_DIPSETTING(0x0010, "0010h")
+ PORT_DIPSETTING(0x0020, "0020h")
+ PORT_DIPSETTING(0x0030, "0030h")
+ PORT_DIPSETTING(0x0040, "0040h")
+ PORT_DIPSETTING(0x0050, "0050h")
+ PORT_DIPSETTING(0x0060, "0060h")
+ PORT_DIPSETTING(0x0070, "0070h")
+ PORT_DIPSETTING(0x0080, "0080h")
+ PORT_DIPSETTING(0x0090, "0090h")
+ PORT_DIPSETTING(0x00a0, "00a0h")
+ PORT_DIPSETTING(0x00b0, "00b0h")
+ PORT_DIPSETTING(0x00c0, "00c0h")
+ PORT_DIPSETTING(0x00d0, "00d0h")
+ PORT_DIPSETTING(0x00e0, "00e0h")
+ PORT_DIPSETTING(0x00f0, "00f0h")
+
+ PORT_START("E15B")
+ PORT_DIPNAME(0x0f00, 0x0000, "I/O Middle")
+ PORT_DIPSETTING(0x0000, "0000h")
+ PORT_DIPSETTING(0x0100, "0100h")
+ PORT_DIPSETTING(0x0200, "0200h")
+ PORT_DIPSETTING(0x0300, "0300h")
+ PORT_DIPSETTING(0x0400, "0400h")
+ PORT_DIPSETTING(0x0500, "0500h")
+ PORT_DIPSETTING(0x0600, "0600h")
+ PORT_DIPSETTING(0x0700, "0700h")
+ PORT_DIPSETTING(0x0800, "0800h")
+ PORT_DIPSETTING(0x0900, "0900h")
+ PORT_DIPSETTING(0x0a00, "0a00h")
+ PORT_DIPSETTING(0x0b00, "0b00h")
+ PORT_DIPSETTING(0x0c00, "0c00h")
+ PORT_DIPSETTING(0x0d00, "0d00h")
+ PORT_DIPSETTING(0x0e00, "0e00h")
+ PORT_DIPSETTING(0x0f00, "0f00h")
+
+ PORT_START("E15C")
+ PORT_DIPNAME(0xf000, 0x0000, "I/O High")
+ PORT_DIPSETTING(0x0000, "0000h")
+ PORT_DIPSETTING(0x1000, "1000h")
+ PORT_DIPSETTING(0x2000, "2000h")
+ PORT_DIPSETTING(0x3000, "3000h")
+ PORT_DIPSETTING(0x4000, "4000h")
+ PORT_DIPSETTING(0x5000, "5000h")
+ PORT_DIPSETTING(0x6000, "6000h")
+ PORT_DIPSETTING(0x7000, "7000h")
+ PORT_DIPSETTING(0x8000, "8000h")
+ PORT_DIPSETTING(0x9000, "9000h")
+ PORT_DIPSETTING(0xa000, "a000h")
+ PORT_DIPSETTING(0xb000, "b000h")
+ PORT_DIPSETTING(0xc000, "c000h")
+ PORT_DIPSETTING(0xd000, "d000h")
+ PORT_DIPSETTING(0xe000, "e000h")
+ PORT_DIPSETTING(0xf000, "f000h")
+
+ PORT_START("E15D")
+ PORT_DIPNAME(0xf0000, 0xf0000, "Memory Bank 1")
+ PORT_DIPSETTING(0x00000, "00000h")
+ PORT_DIPSETTING(0x10000, "10000h")
+ PORT_DIPSETTING(0x20000, "20000h")
+ PORT_DIPSETTING(0x30000, "30000h")
+ PORT_DIPSETTING(0x40000, "40000h")
+ PORT_DIPSETTING(0x50000, "50000h")
+ PORT_DIPSETTING(0x60000, "60000h")
+ PORT_DIPSETTING(0x70000, "70000h")
+ PORT_DIPSETTING(0x80000, "80000h")
+ PORT_DIPSETTING(0x90000, "90000h")
+ PORT_DIPSETTING(0xa0000, "a0000h")
+ PORT_DIPSETTING(0xb0000, "b0000h")
+ PORT_DIPSETTING(0xc0000, "c0000h")
+ PORT_DIPSETTING(0xd0000, "d0000h")
+ PORT_DIPSETTING(0xe0000, "e0000h")
+ PORT_DIPSETTING(0xf0000, "f0000h")
+
+ PORT_START("E15E")
+ PORT_DIPNAME(0xf0000, 0xe0000, "Memory Bank 0")
+ PORT_DIPSETTING(0x00000, "00000h")
+ PORT_DIPSETTING(0x10000, "10000h")
+ PORT_DIPSETTING(0x20000, "20000h")
+ PORT_DIPSETTING(0x30000, "30000h")
+ PORT_DIPSETTING(0x40000, "40000h")
+ PORT_DIPSETTING(0x50000, "50000h")
+ PORT_DIPSETTING(0x60000, "60000h")
+ PORT_DIPSETTING(0x70000, "70000h")
+ PORT_DIPSETTING(0x80000, "80000h")
+ PORT_DIPSETTING(0x90000, "90000h")
+ PORT_DIPSETTING(0xa0000, "a0000h")
+ PORT_DIPSETTING(0xb0000, "b0000h")
+ PORT_DIPSETTING(0xc0000, "c0000h")
+ PORT_DIPSETTING(0xd0000, "d0000h")
+ PORT_DIPSETTING(0xe0000, "e0000h")
+ PORT_DIPSETTING(0xf0000, "f0000h")
+
+ PORT_START("E21")
+ PORT_DIPNAME(0x01, 0x01, "FD0 is 5.25\"") PORT_DIPLOCATION("E21:1")
+ PORT_DIPSETTING(0x00, DEF_STR(Yes))
+ PORT_DIPSETTING(0x01, DEF_STR(No))
+ PORT_DIPNAME(0x02, 0x00, "FD1 is 5.25\"") PORT_DIPLOCATION("E21:3")
+ PORT_DIPSETTING(0x00, DEF_STR(Yes))
+ PORT_DIPSETTING(0x02, DEF_STR(No))
+ PORT_DIPNAME(0x04, 0x00, "FD2 is 5.25\"") PORT_DIPLOCATION("E21:5")
+ PORT_DIPSETTING(0x00, DEF_STR(Yes))
+ PORT_DIPSETTING(0x04, DEF_STR(No))
+ PORT_DIPNAME(0x08, 0x08, "FD3 is 5.25\"") PORT_DIPLOCATION("E21:7")
+ PORT_DIPSETTING(0x00, DEF_STR(Yes))
+ PORT_DIPSETTING(0x08, DEF_STR(No))
+ PORT_DIPUNUSED_DIPLOC(0x70, 0x70, "E21:2,4,6")
+INPUT_PORTS_END
+
+const tiny_rom_entry *labtam_z80sbc_device::device_rom_region() const
+{
+ return ROM_NAME(labtam_z80sbc);
+}
+
+ioport_constructor labtam_z80sbc_device::device_input_ports() const
+{
+ return INPUT_PORTS_NAME(labtam_z80sbc);
+}
+
+void labtam_z80sbc_device::device_resolve_objects()
+{
+ // TODO: Multibus interrupt lines may optionally be wire-wrapped to
+ // Am9517 interrupt request inputs 0, 1, 3 or 7.
+}
+
+void labtam_z80sbc_device::device_start()
+{
+ m_ram0 = std::make_unique<u8[]>(0x10000);
+ m_ram1 = std::make_unique<u8[]>(0x10000);
+ m_sram = std::make_unique<u8[]>(0x800);
+
+ m_map_lo = std::make_unique<u8[]>(256);
+ m_map_hi = std::make_unique<u8[]>(256);
+
+ save_pointer(NAME(m_ram0), 0x10000);
+ save_pointer(NAME(m_ram1), 0x10000);
+ save_pointer(NAME(m_sram), 0x800);
+
+ save_pointer(NAME(m_map_lo), 256);
+ save_pointer(NAME(m_map_hi), 256);
+
+ save_item(NAME(m_map_mux));
+ save_item(NAME(m_map_num));
+ save_item(NAME(m_map_cnt));
+}
+
+void labtam_z80sbc_device::device_reset()
+{
+ if (!m_installed)
+ {
+ u32 const ram0_select = m_e15[4]->read();
+ 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_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::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;
+ }
+
+ m_map_mux = 0;
+ m_map_num = 0;
+ m_map_cnt = 0;
+ m_fdcstatus = 0x3c;
+
+ m_dma[0]->iei_w(1);
+}
+
+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);
+}
+
+static const z80_daisy_config daisy_chain[] = { { "dma0" }, { "dma1" }, { "sio" }, { nullptr } };
+
+void labtam_z80sbc_device::device_add_mconfig(machine_config &config)
+{
+ Z80(config, m_cpu, 20_MHz_XTAL / 4);
+ m_cpu->set_addrmap(AS_PROGRAM, &labtam_z80sbc_device::cpu_mem);
+ m_cpu->set_addrmap(AS_IO, &labtam_z80sbc_device::cpu_pio);
+ m_cpu->irqack_cb().set([this](int state) { m_map_mux |= MM_PND; });
+ m_cpu->set_daisy_config(daisy_chain);
+ m_cpu->set_irq_acknowledge_callback(m_uic, FUNC(am9519_device::iack_cb));
+
+ INPUT_MERGER_ANY_HIGH(config, m_int);
+ m_int->output_handler().set_inputline(m_cpu, INPUT_LINE_IRQ0);
+
+ /*
+ * The Z80DMAs, Z80SIO and Am9519 are all connected to the Z80 /INT line,
+ * with EI/EO lines used to control request priority. The Am9519 does not
+ * support the full Z80 IM2 interrupt protocol and the RETI instruction is
+ * not used by the system firmware.
+ *
+ * This logic is emulated using an input merger for the interrupt line, a
+ * Z80 daisy-chain for the DMA and SIO devices and a regular interrupt
+ * acknowledge callback handler for the UIC. This has the side-effect of
+ * making the UIC the lowest-priority device despite not emulating and
+ * connecting its EI/EO lines.
+ */
+
+ Z80DMA(config, m_dma[0], 20_MHz_XTAL / 4);
+ m_dma[0]->out_int_callback().set(m_int, FUNC(input_merger_any_high_device::in_w<0>));
+ m_dma[0]->out_ieo_callback().set(m_dma[1], FUNC(z80dma_device::iei_w));
+ m_dma[0]->out_busreq_callback().set(m_dma[0], FUNC(z80dma_device::bai_w));
+ m_dma[0]->in_mreq_callback().set(FUNC(labtam_z80sbc_device::map_r<7>));
+ m_dma[0]->out_mreq_callback().set(FUNC(labtam_z80sbc_device::map_w<7>));
+ m_dma[0]->in_iorq_callback().set(m_fdc, FUNC(wd2793_device::data_r));
+ m_dma[0]->out_iorq_callback().set(m_fdc, FUNC(wd2793_device::data_w));
+
+ Z80DMA(config, m_dma[1], 20_MHz_XTAL / 4);
+ m_dma[1]->out_int_callback().set(m_int, FUNC(input_merger_any_high_device::in_w<1>));
+ //m_dma[1]->out_ieo_callback().set(m_sio, FUNC(z80sio_device::iei_w));
+ m_dma[1]->out_busreq_callback().set(m_dma[1], FUNC(z80dma_device::bai_w));
+ m_dma[1]->in_mreq_callback().set(FUNC(labtam_z80sbc_device::map_r<7>));
+ m_dma[1]->out_mreq_callback().set(FUNC(labtam_z80sbc_device::map_w<7>));
+
+ // TODO: implement iei/ieo on z80sio
+ Z80SIO(config, m_sio, 20_MHz_XTAL / 4);
+ m_sio->out_int_callback().set(m_int, FUNC(input_merger_any_high_device::in_w<2>));
+ //m_sio->out_ieo_callback().set(m_uic, FUNC(am9519_device::iei_w));
+
+ // TODO: implement iei/ieo on am9519
+ AM9519(config, m_uic);
+ 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(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
+
+ AM9513(config, m_stc, 4'000'000);
+ m_stc->out4_cb().set(m_uic, FUNC(am9519_device::ireq5_w));
+
+ MM58167(config, m_rtc, 32.768_kHz_XTAL);
+ m_rtc->irq().set(m_uic, FUNC(am9519_device::ireq6_w));
+
+ FLOPPY_CONNECTOR(config, m_fdd[0], z80sbc_floppies, "dsdd8", floppy_image_device::default_mfm_floppy_formats).enable_sound(true);
+ FLOPPY_CONNECTOR(config, m_fdd[1], z80sbc_floppies, nullptr, floppy_image_device::default_mfm_floppy_formats).enable_sound(true);
+ FLOPPY_CONNECTOR(config, m_fdd[2], z80sbc_floppies, nullptr, floppy_image_device::default_mfm_floppy_formats).enable_sound(true);
+ FLOPPY_CONNECTOR(config, m_fdd[3], z80sbc_floppies, nullptr, floppy_image_device::default_mfm_floppy_formats).enable_sound(true);
+}
+
+void labtam_z80sbc_device::cpu_mem(address_map &map)
+{
+ /*
+ * Resident Bus Decoding
+ * 2000..27ff sram
+ * 4000..5fff eprom 1
+ * e000..ffff eprom 0
+ */
+ map(0x0000, 0xffff).rw(FUNC(labtam_z80sbc_device::mem_r), FUNC(labtam_z80sbc_device::mem_w));
+}
+
+void labtam_z80sbc_device::cpu_pio(address_map &map)
+{
+ 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");
+ map(0x0020, 0x0020).mirror(0xff00).w(FUNC(labtam_z80sbc_device::intswt_w));
+ map(0x0028, 0x0028).mirror(0xff00).w(FUNC(labtam_z80sbc_device::mapnum_w));
+
+ map(0x0030, 0x0037).mirror(0xff00).w(FUNC(labtam_z80sbc_device::drive_w));
+ map(0x0038, 0x0038).mirror(0xff00).lw8([this](u8 data) { LOG("reset drive fault\n"); }, "fltrest");
+ map(0x0040, 0x0043).mirror(0xff00).rw(m_fdc, FUNC(wd2793_device::read), FUNC(wd2793_device::write));
+ map(0x0048, 0x004b).mirror(0xff00).rw(m_sio, FUNC(z80sio_device::ba_cd_r), FUNC(z80sio_device::ba_cd_w));
+ map(0x0050, 0x0051).mirror(0xff00).rw(m_stc, FUNC(am9513_device::read8), FUNC(am9513_device::write8));
+ map(0x0058, 0x0058).mirror(0xff00).rw(m_uic, FUNC(am9519_device::data_r), FUNC(am9519_device::data_w));
+ map(0x0059, 0x0059).mirror(0xff00).rw(m_uic, FUNC(am9519_device::stat_r), FUNC(am9519_device::cmd_w));
+
+ //map(0x0060, 0x0067); // TODO: wd1001
+
+ map(0x0068, 0x0068).mirror(0xff00).r(FUNC(labtam_z80sbc_device::drvstatus_r));
+
+ map(0x0070, 0x0070).select(0xff00).lr8([this](offs_t offset) { return m_map_lo[offset >> 8]; }, "maprd0");
+ map(0x0078, 0x0078).select(0xff00).lr8([this](offs_t offset) { return m_map_hi[offset >> 8] | m_map_num; }, "maprd1");
+
+ map(0x0080, 0x0080).mirror(0xff00).rw(m_dma[0], FUNC(z80dma_device::read), FUNC(z80dma_device::write));
+ map(0x00a0, 0x00a0).mirror(0xff00).rw(m_dma[1], FUNC(z80dma_device::read), FUNC(z80dma_device::write));
+ map(0x00e0, 0x00ff).mirror(0xff00).rw(m_rtc, FUNC(mm58167_device::read), FUNC(mm58167_device::write));
+}
+
+u8 labtam_z80sbc_device::mem_r(offs_t offset)
+{
+ // check for and complete pending map number change
+ if ((m_map_mux & MM_PND) && !machine().side_effects_disabled())
+ {
+ if (m_map_cnt == 0)
+ {
+ m_map_mux &= ~MM_PND;
+ m_map_mux ^= MM_INT;
+ }
+ else
+ m_map_cnt--;
+ }
+
+ if (m_map_mux & MM_ENB)
+ {
+ if (m_map_mux & MM_INT)
+ return map_r(0, offset);
+ else
+ return map_r(m_map_num, offset);
+ }
+ else
+ // Theory: when mapper is deactivated, its outputs are all forced high, resulting
+ // in set RESB|MEM|WP flags and resident bus address |= 0xf800.
+ return m_eprom[0][0x1800 | (offset & 0x7ff)];
+}
+
+void labtam_z80sbc_device::mem_w(offs_t offset, u8 data)
+{
+ if (m_map_mux & MM_ENB)
+ {
+ if (m_map_mux & MM_INT)
+ map_w(0, offset, data);
+ else
+ map_w(m_map_num, offset, data);
+ }
+ else
+ LOG("mem_w unmapped offset 0x%04x data 0x%02x (%s)\n", offset, data, machine().describe_context());
+}
+
+u8 labtam_z80sbc_device::map_r(unsigned map_num, offs_t offset)
+{
+ u8 const entry = ((offset >> 8) & 0xf8) | (map_num & 0x07);
+ u8 const lo = m_map_lo[entry];
+ u8 const hi = m_map_hi[entry];
+
+ u32 const address = u32(hi & MAPWR1_MA19) << 15 | u32(lo) << 11 | (offset & 0x7ff);
+
+ if (hi & MAPWR1_RESB)
+ {
+ // TODO: use address space to decode resident bus
+ switch (address & 0xf000)
+ {
+ case 0x2000:
+ return m_sram[address & 0x7ff];
+ case 0x4000:
+ case 0x5000:
+ return m_eprom[1][address & 0x1fff];
+ case 0xe000:
+ case 0xf000:
+ return m_eprom[0][address & 0x1fff];
+ default:
+ LOG("map_r hi 0x%02x lo 0x%02x address 0x%05x (%s)\n", hi, lo, address, machine().describe_context());
+ return 0;
+ }
+ }
+ else
+ return m_bus->space((hi & MAPWR1_MEM) ? AS_PROGRAM : AS_IO).read_byte(address);
+}
+
+void labtam_z80sbc_device::map_w(unsigned map_num, offs_t offset, u8 data)
+{
+ u8 const entry = ((offset >> 8) & 0xf8) | (map_num & 0x07);
+ u8 const lo = m_map_lo[entry];
+ u8 const hi = m_map_hi[entry];
+
+ u32 const address = u32(hi & MAPWR1_MA19) << 15 | u32(lo) << 11 | (offset & 0x7ff);
+
+ if (!(hi & MAPWR1_WP))
+ {
+ if (hi & MAPWR1_RESB)
+ {
+ // TODO: use address space to decode resident bus
+ switch (address & 0xf000)
+ {
+ case 0x2000:
+ m_sram[address & 0x7ff] = data;
+ break;
+ default:
+ LOG("map_w hi 0x%02x lo 0x%02x address 0x%05x data 0x%02x (%s)\n", hi, lo, address, data, machine().describe_context());
+ break;
+ }
+ }
+ else
+ m_bus->space((hi & MAPWR1_MEM) ? AS_PROGRAM : AS_IO).write_byte(address, data);
+ }
+}
+
+void labtam_z80sbc_device::intswt_w(u8 data)
+{
+ /*
+ * Writing to this port deactivates the interrupt map after the next three
+ * Z80 memory read cycles. This delay supports interrupt return, allowing
+ * the standard epilogue of NOP, EI, and RET to be fetched and executed
+ * from map 0, before the return address is fetched from the non-interrupt
+ * memory map.
+ */
+
+ LOG("intswt map 0x%02x mux 0x%02x (%s)\n", m_map_num, m_map_mux, machine().describe_context());
+
+ m_map_mux |= MM_PND;
+ m_map_cnt = 3;
+}
+
+void labtam_z80sbc_device::mapnum_w(u8 data)
+{
+ LOG("mapnum 0x%02x (%s)\n", data, machine().describe_context());
+
+ m_map_mux |= MM_ENB;
+
+ // TODO: what are bits 3, 4 and 5 used for?
+ m_map_num = data & 0x07;
+}
+
+void labtam_z80sbc_device::drive_w(offs_t offset, u8 data)
+{
+ switch (offset)
+ {
+ case 0:
+ case 1:
+ case 2:
+ case 3:
+ if (BIT(data, 0))
+ {
+ LOG("drive_w select drive %d (%s)\n", offset, machine().describe_context());
+ m_drive = offset;
+ m_fdc->set_floppy(m_fdd[*m_drive]->get_device());
+ }
+ else
+ {
+ m_drive.reset();
+ m_fdc->set_floppy(nullptr);
+ }
+ break;
+ case 4:
+ m_fdc->dden_w(BIT(data, 0));
+ break;
+ case 5:
+ // FIXME: make side select persistent
+ if (m_drive)
+ {
+ LOG("drive_w select side %d (%s)\n", BIT(data, 0), machine().describe_context());
+ m_fdd[*m_drive]->get_device()->ss_w(BIT(data, 0));
+ }
+ break;
+ case 6:
+ // TODO: precomp
+ break;
+ case 7:
+ LOG("drive_w mini-floppy %s (%s)\n", BIT(data, 0) ? "disable" : "enable", machine().describe_context());
+ m_fdc->enmf_w(BIT(data, 0));
+ break;
+ }
+}
+
+void labtam_z80sbc_device::fdcclr_w(u8 data)
+{
+ 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 0x%02x (%s)\n", data, machine().describe_context());
+ m_fdcstatus &= ~0x02;
+}
+
+void labtam_z80sbc_device::fdcatn_w(u8 data)
+{
+ 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 (%s)\n", machine().describe_context());
+ return m_fdcstatus;
+}
+
+u8 labtam_z80sbc_device::drvstatus_r()
+{
+ u8 data = m_e21->read();
+
+ if (m_drive)
+ {
+ floppy_image_device *fid = m_fdd[*m_drive]->get_device();
+ if (fid && !fid->twosid_r())
+ data |= DRVSTATUS_DS;
+ }
+
+ return data;
+}
diff --git a/src/devices/bus/multibus/labtam_z80sbc.h b/src/devices/bus/multibus/labtam_z80sbc.h
new file mode 100644
index 00000000000..f8e9d2c7127
--- /dev/null
+++ b/src/devices/bus/multibus/labtam_z80sbc.h
@@ -0,0 +1,97 @@
+// license:BSD-3-Clause
+// copyright-holders:Patrick Mackinlay
+
+#ifndef MAME_BUS_MULTIBUS_LABTAM_Z80SBC_H
+#define MAME_BUS_MULTIBUS_LABTAM_Z80SBC_H
+
+#pragma once
+
+#include "multibus.h"
+
+#include "cpu/z80/z80.h"
+#include "machine/am9513.h"
+#include "machine/am9519.h"
+#include "machine/mm58167.h"
+#include "machine/wd_fdc.h"
+#include "machine/z80dma.h"
+#include "machine/z80sio.h"
+
+#include "machine/input_merger.h"
+
+#include "imagedev/floppy.h"
+
+class labtam_z80sbc_device
+ : public device_t
+ , public device_multibus_interface
+{
+public:
+ labtam_z80sbc_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 ATTR_COLD;
+ virtual void device_add_mconfig(machine_config &config) override ATTR_COLD;
+ virtual ioport_constructor device_input_ports() const override ATTR_COLD;
+ virtual void device_resolve_objects() override ATTR_COLD;
+ virtual void device_start() override ATTR_COLD;
+ virtual void device_reset() override ATTR_COLD;
+
+private:
+ void cpu_mem(address_map &map) ATTR_COLD;
+ void cpu_pio(address_map &map) ATTR_COLD;
+
+ // cpu memory handlers
+ u8 mem_r(offs_t offset);
+ void mem_w(offs_t offset, u8 data);
+
+ // memory mapping handlers
+ u8 map_r(unsigned map_num, offs_t offset);
+ void map_w(unsigned map_num, offs_t offset, u8 data);
+ template <unsigned M> u8 map_r(offs_t offset) { return map_r(M, offset); }
+ template <unsigned M> void map_w(offs_t offset, u8 data) { map_w(M, offset, data); }
+
+ void intswt_w(u8 data);
+ void mapnum_w(u8 data);
+ void drive_w(offs_t offset, u8 data);
+ void fdcclr_w(u8 data);
+ void netclr_w(u8 data);
+ void fdcatn_w(u8 data);
+ u8 fdcstatus_r();
+ u8 drvstatus_r();
+
+ required_device<z80_device> m_cpu;
+ required_device<am9513_device> m_stc;
+ required_device<am9519_device> m_uic;
+ required_device<mm58167_device> m_rtc;
+ required_device<wd2793_device> m_fdc;
+ required_device_array<z80dma_device, 2> m_dma;
+ required_device<z80sio_device> m_sio;
+ required_device<input_merger_any_high_device> m_int;
+
+ required_device_array<floppy_connector, 4> m_fdd;
+
+ optional_region_ptr_array<u8, 2> m_eprom;
+
+ required_ioport_array<5> m_e15; // multibus address assignments
+ required_ioport m_e21; // floppy drive option selection
+
+ std::unique_ptr<u8[]> m_ram0;
+ std::unique_ptr<u8[]> m_ram1;
+ std::unique_ptr<u8[]> m_sram;
+
+ std::unique_ptr<u8[]> m_map_lo;
+ std::unique_ptr<u8[]> m_map_hi;
+
+ u8 m_map_mux;
+ u8 m_map_num;
+ u8 m_map_cnt;
+
+ u8 m_fdcstatus;
+ std::optional<u8> m_drive;
+
+ bool m_installed;
+};
+
+DECLARE_DEVICE_TYPE(LABTAM_Z80SBC, labtam_z80sbc_device)
+
+#endif // MAME_BUS_MULTIBUS_LABTAM_Z80SBC_H
diff --git a/src/devices/bus/multibus/multibus.cpp b/src/devices/bus/multibus/multibus.cpp
new file mode 100644
index 00000000000..b0365b6e7fe
--- /dev/null
+++ b/src/devices/bus/multibus/multibus.cpp
@@ -0,0 +1,112 @@
+// license:BSD-3-Clause
+// copyright-holders: F. Ulivi
+/*********************************************************************
+
+ multibus.cpp
+
+ Intel Multibus
+
+*********************************************************************/
+
+/*
+ * TODO:
+ * - shared interrupts
+ * - vectored and non-vectored irq acknowledge
+ * - inhibit lines
+ * - lock/unlock
+ * - bus arbitration/priority
+ */
+
+#include "emu.h"
+#include "multibus.h"
+
+// device type definition
+DEFINE_DEVICE_TYPE(MULTIBUS, multibus_device, "multibus", "Intel Multibus")
+DEFINE_DEVICE_TYPE(MULTIBUS_SLOT, multibus_slot_device, "multibus_slot", "Intel Multibus slot")
+
+multibus_device::multibus_device(machine_config const &mconfig, char const *tag, device_t *owner, u32 clock)
+ : device_t(mconfig, MULTIBUS, tag, owner, clock)
+ , device_memory_interface(mconfig, *this)
+ , m_mem_config("mem", ENDIANNESS_LITTLE, 16, 24, 0, address_map_constructor(FUNC(multibus_device::mem_map), this))
+ , m_pio_config("pio", ENDIANNESS_LITTLE, 16, 16, 0, address_map_constructor(FUNC(multibus_device::pio_map), this))
+ , m_int_cb(*this)
+ , m_xack_cb(*this)
+{
+}
+
+device_memory_interface::space_config_vector multibus_device::memory_space_config() const
+{
+ return space_config_vector { std::make_pair(AS_PROGRAM, &m_mem_config), std::make_pair(AS_IO, &m_pio_config) };
+}
+
+void multibus_device::device_start()
+{
+}
+
+void multibus_device::mem_map(address_map &map)
+{
+ map(0x00'0000, 0xff'ffff).unmaprw().flags(FLAG_UNMAPPED);
+}
+
+void multibus_device::pio_map(address_map &map)
+{
+ map(0x0000, 0xffff).unmaprw().flags(FLAG_UNMAPPED);
+}
+
+multibus_slot_device::multibus_slot_device(machine_config const &mconfig, char const *tag, device_t *owner, u32 clock)
+ : device_t(mconfig, MULTIBUS_SLOT, tag, owner, clock)
+ , device_slot_interface(mconfig, *this)
+ , m_bus(*this, finder_base::DUMMY_TAG)
+{
+}
+
+void multibus_slot_device::device_start()
+{
+}
+
+device_multibus_interface::device_multibus_interface(machine_config const &mconfig, device_t &device)
+ : device_interface(device, "multibus")
+ , m_bus(*this, finder_base::DUMMY_TAG)
+ , m_int(*this)
+{
+}
+
+void device_multibus_interface::interface_config_complete()
+{
+ // FIXME: avoid listxml crash caused by owner device not being a slot
+ if (device().owner() && device().owner()->owner())
+ {
+ m_bus.set_tag(downcast<multibus_slot_device &>(*device().owner()).bus());
+ multibus_device &bus(*m_bus.lookup());
+
+ // route incoming interrupt requests to all cards
+ bus.int_callback<0>().append([this](int state) { m_int[0](state); });
+ bus.int_callback<1>().append([this](int state) { m_int[1](state); });
+ bus.int_callback<2>().append([this](int state) { m_int[2](state); });
+ bus.int_callback<3>().append([this](int state) { m_int[3](state); });
+ bus.int_callback<4>().append([this](int state) { m_int[4](state); });
+ bus.int_callback<5>().append([this](int state) { m_int[5](state); });
+ bus.int_callback<6>().append([this](int state) { m_int[6](state); });
+ bus.int_callback<7>().append([this](int state) { m_int[7](state); });
+ }
+}
+
+void device_multibus_interface::int_w(unsigned number, int state)
+{
+ switch (number)
+ {
+ case 0: int_w<0>(state); break;
+ case 1: int_w<1>(state); break;
+ case 2: int_w<2>(state); break;
+ case 3: int_w<3>(state); break;
+ case 4: int_w<4>(state); break;
+ case 5: int_w<5>(state); break;
+ case 6: int_w<6>(state); break;
+ case 7: int_w<7>(state); break;
+ }
+}
+
+void device_multibus_interface::unmap(int spacenum, offs_t addrstart, offs_t addrend, offs_t addrmirror)
+{
+ m_bus->space(spacenum).unmap_readwrite(addrstart, addrend, addrmirror, multibus_device::FLAG_UNMAPPED);
+}
diff --git a/src/devices/bus/multibus/multibus.h b/src/devices/bus/multibus/multibus.h
new file mode 100644
index 00000000000..3260ebac5ea
--- /dev/null
+++ b/src/devices/bus/multibus/multibus.h
@@ -0,0 +1,175 @@
+// license:BSD-3-Clause
+// copyright-holders: F. Ulivi
+/*********************************************************************
+
+ multibus.h
+
+ Intel Multibus
+
+ P1 Multibus connector:
+
+ Power supplies
+ 1 GND 2 GND
+ 3 +5Vdc 4 +5Vdc
+ 5 +5Vdc 6 +5Vdc
+ 7 +12Vdc 8 +12Vdc
+ 9 -5Vdc 10 -5Vdc
+ 11 GND 12 GND
+ Bus controls
+ 13 BCLK/ 14 INIT/
+ 15 BPRN/ 16 BPRO/
+ 17 BUSY/ 18 BREQ/
+ 19 MRDC/ 20 MWTC/
+ 21 IORC/ 22 IOWC/
+ 23 XACK/ 24 INH1/
+ Bus controls and address
+ 25 LOCK/ 26 INH2/
+ 27 BHEN/ 28 ADR10/
+ 29 CBRQ/ 30 ADR11/
+ 31 CCLK/ 32 ADR12/
+ 33 INTA/ 34 ADR13/
+ Interrupts
+ 35 INT6/ 36 INT7/
+ 37 INT4/ 38 INT5/
+ 39 INT2/ 40 INT3/
+ 41 INT0/ 42 INT1/
+ Address
+ 43 ADRE/ 44 ADRF/
+ 45 ADRC/ 46 ADRD/
+ 47 ADRA/ 48 ADRB/
+ 49 ADR8/ 50 ADR9/
+ 51 ADR6/ 52 ADR7/
+ 53 ADR4/ 54 ADR5/
+ 55 ADR2/ 56 ADR3/
+ 57 ADR0/ 58 ADR1/
+ Data
+ 59 DATE/ 60 DATF/
+ 61 DATC/ 62 DATD/
+ 63 DATA/ 64 DATB/
+ 65 DAT8/ 66 DAT9/
+ 67 DAT6/ 68 DAT7/
+ 69 DAT4/ 70 DAT5/
+ 71 DAT2/ 72 DAT3/
+ 73 DAT0/ 74 DAT1/
+ Power supplies
+ 75 GND 76 GND
+ 77 reserved 78 reserved
+ 79 -12Vdc 80 -12Vdc
+ 81 +5Vdc 82 +5Vdc
+ 83 +5Vdc 84 +5Vdc
+ 85 GND 86 GND
+
+ P2 Multibus connector:
+
+ 1-54 reserved for iLBX bus
+
+ Address
+ 55 ADR16/ 56 ADR17/
+ 57 ADR14/ 58 ADR15/
+
+ 59-60 reserved for iLBx bus
+
+*********************************************************************/
+
+#ifndef MAME_BUS_MULTIBUS_MULTIBUS_H
+#define MAME_BUS_MULTIBUS_MULTIBUS_H
+
+#pragma once
+
+class multibus_device
+ : public device_t
+ , public device_memory_interface
+{
+public:
+ multibus_device(machine_config const &mconfig, char const *tag, device_t *owner, u32 clock);
+
+ enum flags : u16
+ {
+ FLAG_UNMAPPED = 0x0001,
+ };
+
+ // interrupt interface
+ template <unsigned I> auto int_callback() { return m_int_cb[I].bind(); }
+ template <unsigned I> void int_w(int state) { m_int_cb[I](state); }
+
+ // XACK/
+ auto xack_cb() { return m_xack_cb.bind(); }
+
+ // Set XACK/ signal (this is meant for "device_multibus_interface" devices)
+ void xack_w(int state) { m_xack_cb(state); }
+
+protected:
+ // device_t overrides
+ virtual void device_start() override ATTR_COLD;
+
+ // device_memory_interface overrides
+ virtual space_config_vector memory_space_config() const override;
+
+ void mem_map(address_map &map);
+ void pio_map(address_map &map);
+
+private:
+ address_space_config const m_mem_config;
+ address_space_config const m_pio_config;
+
+ devcb_write_line::array<8> m_int_cb;
+ devcb_write_line m_xack_cb;
+};
+
+class multibus_slot_device
+ : public device_t
+ , public device_slot_interface
+{
+public:
+ multibus_slot_device(machine_config const &mconfig, char const *tag, device_t *owner, u32 clock = DERIVED_CLOCK(1, 1));
+
+ template <typename T, typename U>
+ multibus_slot_device(machine_config const &mconfig, char const *tag, device_t *owner, T &&bus_tag, U &&slot_options, char const *default_option, bool const fixed)
+ : multibus_slot_device(mconfig, tag, owner, DERIVED_CLOCK(1,1))
+ {
+ m_bus.set_tag(std::forward<T>(bus_tag));
+
+ option_reset();
+ slot_options(*this);
+ set_default_option(default_option);
+ set_fixed(fixed);
+ }
+
+ auto bus() const { return m_bus; }
+
+protected:
+ virtual void device_start() override ATTR_COLD;
+
+private:
+ required_device<multibus_device> m_bus;
+};
+
+class device_multibus_interface : public device_interface
+{
+protected:
+ device_multibus_interface(machine_config const &mconfig, device_t &device);
+
+ // configuration
+ template <unsigned I> auto int_callback() { return m_int[I].bind(); }
+
+ // device_interface implementation
+ virtual void interface_config_complete() override ATTR_COLD;
+
+ // runtime
+ template <unsigned I> void int_w(int state) { m_bus->int_w<I>(state); }
+ void int_w(unsigned number, int state);
+
+ void xack_w(int state) { m_bus->xack_w(state); }
+ void unmap(int spacenum, offs_t addrstart, offs_t addrend, offs_t addrmirror = 0U);
+
+ required_device<multibus_device> m_bus;
+
+private:
+ devcb_write_line::array<8> m_int;
+};
+
+// device type declaration
+DECLARE_DEVICE_TYPE(MULTIBUS, multibus_device)
+DECLARE_DEVICE_TYPE(MULTIBUS_SLOT, multibus_slot_device)
+
+#endif // MAME_BUS_MULTIBUS_MULTIBUS_H
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..3e1b9c1ca9c
--- /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 ATTR_COLD;
+ virtual void device_start() override ATTR_COLD;
+ virtual void device_reset() override ATTR_COLD;
+ virtual ioport_constructor device_input_ports() const override ATTR_COLD;
+ virtual const tiny_rom_entry *device_rom_region() const override ATTR_COLD;
+
+ void cpu_mem(address_map &map) ATTR_COLD;
+ virtual void cpu_pio(address_map &map) ATTR_COLD;
+
+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) ATTR_COLD;
+ void k7070_cpu_mem(address_map &map) ATTR_COLD;
+};
+
+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..0071ce106ec
--- /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 ATTR_COLD;
+ virtual void device_start() override ATTR_COLD;
+ virtual void device_reset() override ATTR_COLD;
+ virtual const tiny_rom_entry *device_rom_region() const override ATTR_COLD;
+
+ void cpu_mem(address_map &map) ATTR_COLD;
+ virtual void cpu_pio(address_map &map) ATTR_COLD;
+
+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/multibus/serad.cpp b/src/devices/bus/multibus/serad.cpp
new file mode 100644
index 00000000000..f4fa2346a6c
--- /dev/null
+++ b/src/devices/bus/multibus/serad.cpp
@@ -0,0 +1,204 @@
+// license:BSD-3-Clause
+// copyright-holders:Patrick Mackinlay
+
+/*
+ * Siemens S26361-D279 SERAD serial interface board.
+ *
+ * This Multibus card was used with several Multibus-based computers from
+ * Siemens, including the PC-MX2, MX300 and MX500. It has 3 SCN2681 DUARTs,
+ * giving a total of two V24 and four SS97 serial ports. These are controlled
+ * by an on-board 8085A microcontroller, with a dual-port RAM mailbox used to
+ * communicate with the host.
+ *
+ * Sources:
+ * - https://oldcomputers-ddns.org/public/pub/rechner/siemens/mx-rm/pc-mx2/manuals/pc-mx2_pc2000_9780_logik.pdf
+ * - https://mx300i.narten.de/view_board.cfm?5EF287A1ABC3F4DCAFEA2BC2FAB8C504041A
+ *
+ * TODO:
+ * - multibus lock/unlock/interrupt
+ * - SS97 ports with power on/reset signals
+ */
+
+#include "emu.h"
+#include "serad.h"
+
+#define VERBOSE 0
+#include "logmacro.h"
+
+DEFINE_DEVICE_TYPE(SERAD, serad_device, "serad", "Siemens S26361-D279 SERAD")
+
+serad_device::serad_device(machine_config const &mconfig, char const *tag, device_t *owner, u32 clock)
+ : device_t(mconfig, SERAD, tag, owner, clock)
+ , device_multibus_interface(mconfig, *this)
+ , m_cpu(*this, "cpu")
+ , m_mbx(*this, "mbx")
+ , m_rst65(*this, "rst65")
+ , m_duart(*this, "duart%u", 0U)
+ , m_port(*this, "port%u", 0U)
+ , m_installed(false)
+{
+}
+
+ROM_START(serad)
+ ROM_REGION(0x2000, "cpu", 0)
+ ROM_LOAD("361d0279d031__e00422_tex.d31", 0x0000, 0x2000, CRC(369f5fd1) SHA1(6a1c2d351d5552d54d835b7726b3f9b921605d0e))
+ROM_END
+
+static INPUT_PORTS_START(serad)
+ PORT_START("MEM")
+ PORT_DIPNAME(0xfff, 0xef7, "Base Address")
+ PORT_DIPSETTING(0xef7, "EF7000")
+ PORT_DIPSETTING(0xef6, "EF6000")
+ PORT_DIPSETTING(0xef5, "EF5000")
+ PORT_DIPSETTING(0xef4, "EF4000")
+ PORT_DIPSETTING(0xef3, "EF3000")
+
+ PORT_START("PIO")
+ PORT_DIPNAME(0xff, 0x10, "I/O Address")
+ PORT_DIPSETTING(0x0f, "0F00")
+ PORT_DIPSETTING(0x10, "1000")
+ PORT_DIPSETTING(0x11, "1100")
+ PORT_DIPSETTING(0x12, "1200")
+ PORT_DIPSETTING(0x13, "1300")
+
+ PORT_START("IRQ")
+ PORT_DIPNAME(0xff, 0x00, "Interrupt")
+ PORT_DIPSETTING(0x00, "None")
+ PORT_DIPSETTING(0x01, "0")
+ PORT_DIPSETTING(0x02, "1")
+ PORT_DIPSETTING(0x04, "2")
+ PORT_DIPSETTING(0x08, "3")
+ PORT_DIPSETTING(0x10, "4")
+ PORT_DIPSETTING(0x20, "5")
+ PORT_DIPSETTING(0x40, "6")
+ PORT_DIPSETTING(0x80, "7")
+INPUT_PORTS_END
+
+const tiny_rom_entry *serad_device::device_rom_region() const
+{
+ return ROM_NAME(serad);
+}
+
+ioport_constructor serad_device::device_input_ports() const
+{
+ return INPUT_PORTS_NAME(serad);
+}
+
+void serad_device::device_start()
+{
+}
+
+void serad_device::device_reset()
+{
+ if (!m_installed)
+ {
+ u32 const mem = ioport("MEM")->read() << 12;
+ u32 const pio = ioport("PIO")->read() << 8;
+
+ m_bus->space(AS_PROGRAM).install_ram(mem, mem | 0xfff, m_mbx.target());
+ m_bus->space(AS_IO).install_write_handler(pio, pio | 0xff, write8smo_delegate(*this, &serad_device::rst55_w<1>, "serad_device::rst55_w"));
+
+ m_installed = true;
+ }
+}
+
+void serad_device::device_add_mconfig(machine_config &config)
+{
+ I8085A(config, m_cpu, 20_MHz_XTAL / 2); // P8085AH-2
+ m_cpu->set_addrmap(AS_PROGRAM, &serad_device::mem_map);
+ m_cpu->set_addrmap(AS_IO, &serad_device::pio_map);
+
+ INPUT_MERGER_ANY_HIGH(config, m_rst65);
+ m_rst65->output_handler().set_inputline(m_cpu, I8085_RST65_LINE);
+
+ SCN2681(config, m_duart[0], 7.3728_MHz_XTAL / 2);
+ SCN2681(config, m_duart[1], 7.3728_MHz_XTAL / 2);
+ SCN2681(config, m_duart[2], 7.3728_MHz_XTAL / 2);
+
+ m_duart[0]->irq_cb().set(m_rst65, FUNC(input_merger_any_high_device::in_w<0>));
+ m_duart[1]->irq_cb().set(m_rst65, FUNC(input_merger_any_high_device::in_w<1>));
+ m_duart[2]->irq_cb().set(m_rst65, FUNC(input_merger_any_high_device::in_w<2>));
+
+ RS232_PORT(config, m_port[0], default_rs232_devices, nullptr); // SS97
+ RS232_PORT(config, m_port[1], default_rs232_devices, nullptr); // SS97
+ RS232_PORT(config, m_port[2], default_rs232_devices, nullptr); // V24
+ RS232_PORT(config, m_port[3], default_rs232_devices, nullptr); // SS97
+ RS232_PORT(config, m_port[4], default_rs232_devices, nullptr); // SS97
+ RS232_PORT(config, m_port[5], default_rs232_devices, nullptr); // V24
+
+ m_duart[0]->a_tx_cb().set(m_port[0], FUNC(rs232_port_device::write_txd));
+ m_duart[0]->b_tx_cb().set(m_port[1], FUNC(rs232_port_device::write_txd));
+ m_duart[0]->outport_cb().set(
+ [this](u8 data)
+ {
+ // clear 0
+ // clear 1
+ // -
+ // -
+ m_duart[1]->ip0_w(BIT(data, 4)); // rxrdy0
+ m_duart[1]->ip1_w(BIT(data, 5)); // rxrdy1
+ m_duart[0]->ip0_w(BIT(data, 6)); // txrdy0
+ m_duart[0]->ip1_w(BIT(data, 7)); // txrdy1
+ }
+ );
+
+ m_duart[1]->a_tx_cb().set(m_port[2], FUNC(rs232_port_device::write_txd));
+ m_duart[1]->b_tx_cb().set(m_port[3], FUNC(rs232_port_device::write_txd));
+ m_duart[1]->outport_cb().set(
+ [this](u8 data)
+ {
+ m_port[2]->write_rts(BIT(data, 0)); // s2.k2 (rts)
+ // clear 3
+ // -
+ m_port[2]->write_dtr(BIT(data, 3)); // s1.k2 (dtr)
+ m_duart[1]->ip2_w(BIT(data, 4)); // rxrdy2
+ m_duart[1]->ip3_w(BIT(data, 5)); // rxrdy3
+ m_duart[0]->ip2_w(BIT(data, 6)); // txrdy2
+ m_duart[0]->ip3_w(BIT(data, 7)); // txrdy3
+ }
+ );
+
+ m_duart[2]->a_tx_cb().set(m_port[4], FUNC(rs232_port_device::write_txd));
+ m_duart[2]->b_tx_cb().set(m_port[5], FUNC(rs232_port_device::write_txd));
+ m_duart[2]->outport_cb().set(
+ [this](u8 data)
+ {
+ // clear 4
+ m_port[5]->write_rts(BIT(data, 1)); // s2.k5 (rts)
+ // resled
+ m_port[5]->write_dtr(BIT(data, 3)); // s1.k5 (dtr)
+ m_duart[1]->ip4_w(BIT(data, 4)); // rxrdy4
+ m_duart[1]->ip5_w(BIT(data, 5)); // rxrdy5
+ m_duart[0]->ip4_w(BIT(data, 6)); // txrdy4
+ m_duart[0]->ip5_w(BIT(data, 7)); // txrdy5
+ }
+ );
+
+ m_port[0]->rxd_handler().set(m_duart[0], FUNC(scn2681_device::rx_a_w));
+ m_port[1]->rxd_handler().set(m_duart[0], FUNC(scn2681_device::rx_b_w));
+ m_port[2]->rxd_handler().set(m_duart[1], FUNC(scn2681_device::rx_a_w));
+ m_port[2]->cts_handler().set(m_duart[2], FUNC(scn2681_device::ip0_w));
+ m_port[3]->rxd_handler().set(m_duart[1], FUNC(scn2681_device::rx_b_w));
+ m_port[4]->rxd_handler().set(m_duart[2], FUNC(scn2681_device::rx_a_w));
+ m_port[5]->rxd_handler().set(m_duart[2], FUNC(scn2681_device::rx_b_w));
+ m_port[5]->cts_handler().set(m_duart[2], FUNC(scn2681_device::ip1_w));
+}
+
+void serad_device::mem_map(address_map &map)
+{
+ map(0x0000, 0x1fff).rom().region("cpu", 0).mirror(0x2000);
+ map(0x4000, 0x4fff).ram().share("mbx").mirror(0x3000);
+ map(0x8000, 0x87ff).ram();
+}
+
+void serad_device::pio_map(address_map &map)
+{
+ map(0x00, 0x0f).rw(m_duart[0], FUNC(scn2681_device::read), FUNC(scn2681_device::write)); // duart 0
+ map(0x10, 0x1f).rw(m_duart[1], FUNC(scn2681_device::read), FUNC(scn2681_device::write)); // duart 2
+ map(0x20, 0x2f).rw(m_duart[2], FUNC(scn2681_device::read), FUNC(scn2681_device::write)); // duart 4
+ //map(0x30, 0x3f); // TODO: multibus interrupt
+ map(0x40, 0x4f).nopw(); // TODO: multibus lock
+ map(0x50, 0x5f).nopw(); // TODO: multibus unlock
+ map(0x60, 0x6f).w(FUNC(serad_device::rst55_w<0>));
+ //map(0x70, 0x7f); // TODO: power
+}
diff --git a/src/devices/bus/multibus/serad.h b/src/devices/bus/multibus/serad.h
new file mode 100644
index 00000000000..6df233dda34
--- /dev/null
+++ b/src/devices/bus/multibus/serad.h
@@ -0,0 +1,49 @@
+// license:BSD-3-Clause
+// copyright-holders:Patrick Mackinlay
+
+#ifndef MAME_BUS_MULTIBUS_SERAD_H
+#define MAME_BUS_MULTIBUS_SERAD_H
+
+#pragma once
+
+#include "multibus.h"
+
+#include "cpu/i8085/i8085.h"
+#include "machine/mc68681.h"
+#include "machine/input_merger.h"
+#include "bus/rs232/rs232.h"
+
+class serad_device
+ : public device_t
+ , public device_multibus_interface
+{
+public:
+ serad_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 ATTR_COLD;
+ virtual void device_add_mconfig(machine_config &config) override ATTR_COLD;
+ virtual ioport_constructor device_input_ports() const override ATTR_COLD;
+ virtual void device_start() override ATTR_COLD;
+ virtual void device_reset() override ATTR_COLD;
+
+private:
+ void mem_map(address_map &map) ATTR_COLD;
+ void pio_map(address_map &map) ATTR_COLD;
+
+ template <unsigned S> void rst55_w(u8 data) { m_cpu->set_input_line(I8085_RST55_LINE, S); }
+ void apzint_w(u8 data) { int_w(2, 0); }
+
+ required_device<i8085a_cpu_device> m_cpu;
+ required_shared_ptr<u8> m_mbx;
+ required_device<input_merger_any_high_device> m_rst65;
+ required_device_array<scn2681_device, 3> m_duart;
+ required_device_array<rs232_port_device, 6> m_port;
+
+ bool m_installed;
+};
+
+DECLARE_DEVICE_TYPE(SERAD, serad_device)
+
+#endif // MAME_BUS_MULTIBUS_SERAD_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..1272f4f04ee
--- /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 ATTR_COLD;
+ virtual void device_start() override ATTR_COLD;
+ virtual void device_reset() override ATTR_COLD;
+
+ // 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..7c7b1740e2d
--- /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 ATTR_COLD;
+ virtual void device_reset() override ATTR_COLD;
+
+ // optional information overrides
+ virtual void device_add_mconfig(machine_config &config) override ATTR_COLD;
+
+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..311f97ac298
--- /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 ATTR_COLD;
+ virtual void device_start() override ATTR_COLD;
+
+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..0fb28351d5c
--- /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 ATTR_COLD;
+
+ // 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 ATTR_COLD;
+ virtual void device_reset() override ATTR_COLD;
+
+ 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..2d1e8fc3b1d
--- /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 ATTR_COLD;
+ virtual void device_start() override ATTR_COLD;
+
+ 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/avc.cpp b/src/devices/bus/nasbus/avc.cpp
index 4aacc354567..f4590b2ac3f 100644
--- a/src/devices/bus/nasbus/avc.cpp
+++ b/src/devices/bus/nasbus/avc.cpp
@@ -34,7 +34,7 @@ void nascom_avc_device::device_add_mconfig(machine_config &config)
m_crtc->set_screen("screen");
m_crtc->set_show_border_area(false);
m_crtc->set_char_width(6);
- m_crtc->set_update_row_callback(FUNC(nascom_avc_device::crtc_update_row), this);
+ m_crtc->set_update_row_callback(FUNC(nascom_avc_device::crtc_update_row));
}
@@ -78,9 +78,9 @@ void nascom_avc_device::device_start()
void nascom_avc_device::device_reset()
{
- io_space().install_write_handler(0xb0, 0xb0, write8smo_delegate(FUNC(mc6845_device::address_w), m_crtc.target()));
- io_space().install_readwrite_handler(0xb1, 0xb1, read8smo_delegate(FUNC(mc6845_device::register_r), m_crtc.target()), write8smo_delegate(FUNC(mc6845_device::register_w), m_crtc.target()));
- io_space().install_write_handler(0xb2, 0xb2, write8_delegate(FUNC(nascom_avc_device::control_w), this));
+ io_space().install_write_handler(0xb0, 0xb0, write8smo_delegate(*m_crtc, FUNC(mc6845_device::address_w)));
+ io_space().install_readwrite_handler(0xb1, 0xb1, read8smo_delegate(*m_crtc, FUNC(mc6845_device::register_r)), write8smo_delegate(*m_crtc, FUNC(mc6845_device::register_w)));
+ io_space().install_write_handler(0xb2, 0xb2, write8smo_delegate(*this, FUNC(nascom_avc_device::control_w)));
}
@@ -120,30 +120,30 @@ MC6845_UPDATE_ROW( nascom_avc_device::crtc_update_row )
}
// plot the pixel
- bitmap.pix32(y, x) = m_palette->pen_color((b << 2) | (g << 1) | (r << 0));
+ bitmap.pix(y, x) = m_palette->pen_color((b << 2) | (g << 1) | (r << 0));
}
}
-WRITE8_MEMBER( nascom_avc_device::control_w )
+void nascom_avc_device::control_w(uint8_t data)
{
logerror("nascom_avc_device::control_w: 0x%02x\n", data);
// page video ram in?
if (((m_control & 0x07) == 0) && (data & 0x07))
{
- m_nasbus->ram_disable_w(0);
- program_space().install_readwrite_handler(0x8000, 0xbfff, read8_delegate(FUNC(nascom_avc_device::vram_r), this), write8_delegate(FUNC(nascom_avc_device::vram_w), this));
+ ram_disable_w(0);
+ program_space().install_readwrite_handler(0x8000, 0xbfff, read8sm_delegate(*this, FUNC(nascom_avc_device::vram_r)), write8sm_delegate(*this, FUNC(nascom_avc_device::vram_w)));
}
else if ((data & 0x07) == 0)
{
program_space().unmap_readwrite(0x8000, 0xbfff);
- m_nasbus->ram_disable_w(1);
+ ram_disable_w(1);
}
m_control = data;
}
-READ8_MEMBER( nascom_avc_device::vram_r )
+uint8_t nascom_avc_device::vram_r(offs_t offset)
{
// manual says only one plane can be read, i assume this is the order
if (BIT(m_control, 0)) return m_r_ram[offset];
@@ -154,7 +154,7 @@ READ8_MEMBER( nascom_avc_device::vram_r )
return 0xff;
}
-WRITE8_MEMBER( nascom_avc_device::vram_w )
+void nascom_avc_device::vram_w(offs_t offset, uint8_t data)
{
// all planes can be written at the same time
if (BIT(m_control, 0)) m_r_ram[offset] = data;
diff --git a/src/devices/bus/nasbus/avc.h b/src/devices/bus/nasbus/avc.h
index defa2a916c5..8be07b6223a 100644
--- a/src/devices/bus/nasbus/avc.h
+++ b/src/devices/bus/nasbus/avc.h
@@ -27,15 +27,15 @@ class nascom_avc_device : public device_t, public device_nasbus_card_interface
public:
// construction/destruction
nascom_avc_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
- DECLARE_WRITE8_MEMBER(control_w);
+ void control_w(uint8_t data);
- READ8_MEMBER(vram_r);
- WRITE8_MEMBER(vram_w);
+ uint8_t vram_r(offs_t offset);
+ void vram_w(offs_t offset, uint8_t data);
protected:
- virtual void device_add_mconfig(machine_config &config) override;
- virtual void device_start() override;
- virtual void device_reset() override;
+ 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:
MC6845_UPDATE_ROW(crtc_update_row);
diff --git a/src/devices/bus/nasbus/floppy.cpp b/src/devices/bus/nasbus/floppy.cpp
index 0f19c846bd0..905f5eef087 100644
--- a/src/devices/bus/nasbus/floppy.cpp
+++ b/src/devices/bus/nasbus/floppy.cpp
@@ -24,9 +24,11 @@
DEFINE_DEVICE_TYPE(NASCOM_FDC, nascom_fdc_device, "nascom_fdc", "Nascom Floppy Disc Controller")
-FLOPPY_FORMATS_MEMBER( nascom_fdc_device::floppy_formats )
- FLOPPY_NASCOM_FORMAT
-FLOPPY_FORMATS_END
+void nascom_fdc_device::floppy_formats(format_registration &fr)
+{
+ fr.add_mfm_containers();
+ fr.add(FLOPPY_NASCOM_FORMAT);
+}
static void nascom_floppies(device_slot_interface &device)
{
@@ -78,7 +80,7 @@ nascom_fdc_device::nascom_fdc_device(const machine_config &mconfig, const char *
void nascom_fdc_device::device_start()
{
// timer to turn off the drive motor line
- m_motor = machine().scheduler().timer_alloc(timer_expired_delegate(FUNC(nascom_fdc_device::motor_off), this));
+ m_motor = timer_alloc(FUNC(nascom_fdc_device::motor_off), this);
save_item(NAME(m_select));
}
@@ -89,9 +91,9 @@ void nascom_fdc_device::device_start()
void nascom_fdc_device::device_reset()
{
- io_space().install_readwrite_handler(0xe0, 0xe3, read8sm_delegate(FUNC(fd1793_device::read), m_fdc.target()), write8sm_delegate(FUNC(fd1793_device::write), m_fdc.target()));
- io_space().install_readwrite_handler(0xe4, 0xe4, read8_delegate(FUNC(nascom_fdc_device::select_r), this), write8_delegate(FUNC(nascom_fdc_device::select_w), this));
- io_space().install_read_handler(0xe5, 0xe5, read8_delegate(FUNC(nascom_fdc_device::status_r), this));
+ io_space().install_readwrite_handler(0xe0, 0xe3, read8sm_delegate(*m_fdc, FUNC(fd1793_device::read)), write8sm_delegate(*m_fdc, FUNC(fd1793_device::write)));
+ io_space().install_readwrite_handler(0xe4, 0xe4, read8smo_delegate(*this, FUNC(nascom_fdc_device::select_r)), write8smo_delegate(*this, FUNC(nascom_fdc_device::select_w)));
+ io_space().install_read_handler(0xe5, 0xe5, read8smo_delegate(*this, FUNC(nascom_fdc_device::status_r)));
}
//-------------------------------------------------
@@ -130,7 +132,7 @@ TIMER_CALLBACK_MEMBER( nascom_fdc_device::motor_off )
m_floppy3->get_device()->mon_w(1);
}
-READ8_MEMBER( nascom_fdc_device::select_r )
+uint8_t nascom_fdc_device::select_r()
{
m_select |= (0x80 | 0x20);
@@ -154,7 +156,7 @@ READ8_MEMBER( nascom_fdc_device::select_r )
return m_select;
}
-WRITE8_MEMBER( nascom_fdc_device::select_w )
+void nascom_fdc_device::select_w(uint8_t data)
{
if (VERBOSE)
logerror("nascom_fdc_device::select_w: 0x%02x\n", data);
@@ -182,7 +184,7 @@ WRITE8_MEMBER( nascom_fdc_device::select_w )
m_select = data;
}
-READ8_MEMBER( nascom_fdc_device::status_r )
+uint8_t nascom_fdc_device::status_r()
{
uint8_t data = 0;
diff --git a/src/devices/bus/nasbus/floppy.h b/src/devices/bus/nasbus/floppy.h
index a5bb188a270..16738b44fbf 100644
--- a/src/devices/bus/nasbus/floppy.h
+++ b/src/devices/bus/nasbus/floppy.h
@@ -28,20 +28,20 @@ public:
// construction/destruction
nascom_fdc_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
- DECLARE_READ8_MEMBER(select_r);
- DECLARE_WRITE8_MEMBER(select_w);
- DECLARE_READ8_MEMBER(status_r);
+ uint8_t select_r();
+ void select_w(uint8_t data);
+ uint8_t status_r();
protected:
- virtual void device_add_mconfig(machine_config &config) override;
- virtual void device_start() override;
- virtual void device_reset() override;
+ 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;
virtual void device_reset_after_children() override;
private:
TIMER_CALLBACK_MEMBER(motor_off);
- DECLARE_FLOPPY_FORMATS(floppy_formats);
+ static void floppy_formats(format_registration &fr);
required_device<fd1793_device> m_fdc;
required_device<floppy_connector> m_floppy0;
diff --git a/src/devices/bus/nasbus/nasbus.cpp b/src/devices/bus/nasbus/nasbus.cpp
index ed6cf27bc7a..2f9ef67b811 100644
--- a/src/devices/bus/nasbus/nasbus.cpp
+++ b/src/devices/bus/nasbus/nasbus.cpp
@@ -29,7 +29,8 @@ nasbus_slot_device::nasbus_slot_device(const machine_config &mconfig, const char
nasbus_slot_device::nasbus_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)
+ , device_single_card_slot_interface<device_nasbus_card_interface>(mconfig, *this)
+ , m_bus(*this, finder_base::DUMMY_TAG)
{
}
@@ -39,13 +40,9 @@ nasbus_slot_device::nasbus_slot_device(const machine_config &mconfig, device_typ
void nasbus_slot_device::device_start()
{
- device_nasbus_card_interface *dev = dynamic_cast<device_nasbus_card_interface *>(get_card_device());
-
+ device_nasbus_card_interface *const dev = get_card_device();
if (dev)
- {
- nasbus_device *m_nasbus = downcast<nasbus_device *>(owner()->subdevice(NASBUS_TAG));
- m_nasbus->add_card(dev);
- }
+ m_bus->add_card(*dev);
}
@@ -73,7 +70,6 @@ nasbus_device::nasbus_device(const machine_config &mconfig, const char *tag, dev
nasbus_device::~nasbus_device()
{
- m_dev.detach_all();
}
//-------------------------------------------------
@@ -82,8 +78,6 @@ nasbus_device::~nasbus_device()
void nasbus_device::device_start()
{
- // resolve callbacks
- m_ram_disable_handler.resolve_safe();
}
//-------------------------------------------------
@@ -98,14 +92,14 @@ void nasbus_device::device_reset()
// add_card - add new card to our bus
//-------------------------------------------------
-void nasbus_device::add_card(device_nasbus_card_interface *card)
+void nasbus_device::add_card(device_nasbus_card_interface &card)
{
- card->set_nasbus_device(this);
- m_dev.append(*card);
+ card.set_nasbus_device(*this);
+ 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); }
//**************************************************************************
@@ -117,9 +111,8 @@ 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_slot_card_interface(mconfig, device),
- m_nasbus(nullptr),
- m_next(nullptr)
+ device_interface(device, "nasbus"),
+ m_nasbus(nullptr)
{
}
@@ -131,7 +124,15 @@ device_nasbus_card_interface::~device_nasbus_card_interface()
{
}
-void device_nasbus_card_interface::set_nasbus_device(nasbus_device *nasbus)
+void device_nasbus_card_interface::set_nasbus_device(nasbus_device &nasbus)
+{
+ assert(!device().started());
+ m_nasbus = &nasbus;
+}
+
+
+void device_nasbus_card_interface::interface_pre_start()
{
- m_nasbus = nasbus;
+ if (!m_nasbus)
+ throw device_missing_dependencies();
}
diff --git a/src/devices/bus/nasbus/nasbus.h b/src/devices/bus/nasbus/nasbus.h
index c2c11e2db9a..708f4d4621b 100644
--- a/src/devices/bus/nasbus/nasbus.h
+++ b/src/devices/bus/nasbus/nasbus.h
@@ -92,14 +92,10 @@
#pragma once
+#include <functional>
+#include <vector>
-//**************************************************************************
-// CONSTANTS / MACROS
-//**************************************************************************
-
-#define NASBUS_TAG "nasbus"
-
//**************************************************************************
// TYPE DEFINITIONS
@@ -107,29 +103,36 @@
// forward declaration
class device_nasbus_card_interface;
+class nasbus_device;
// ======================> nasbus_slot_device
-class nasbus_slot_device : public device_t, public device_slot_interface
+class nasbus_slot_device : public device_t, public device_single_card_slot_interface<device_nasbus_card_interface>
{
public:
// construction/destruction
- template <typename T>
- nasbus_slot_device(machine_config const &mconfig, char const *tag, device_t *owner, T &&opts, char const *dflt)
+ template <typename T, typename U>
+ nasbus_slot_device(machine_config const &mconfig, char const *tag, device_t *owner, T &&bus, U &&opts, char const *dflt)
: nasbus_slot_device(mconfig, tag, owner, (uint32_t)0)
{
option_reset();
opts(*this);
set_default_option(dflt);
set_fixed(false);
+ set_bus(std::forward<T>(bus));
}
nasbus_slot_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
+ template <typename T> void set_bus(T &&tag) { m_bus.set_tag(std::forward<T>(tag)); }
+
protected:
nasbus_slot_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_t implementation
+ virtual void device_start() override ATTR_COLD;
+
+private:
+ required_device<nasbus_device> m_bus;
};
// device type definition
@@ -147,26 +150,28 @@ public:
auto ram_disable() { return m_ram_disable_handler.bind(); }
- void add_card(device_nasbus_card_interface *card);
+ void add_card(device_nasbus_card_interface &card);
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); }
// from cards
- DECLARE_WRITE_LINE_MEMBER( ram_disable_w );
+ void ram_disable_w(int state);
protected:
- // device-level overrides
- virtual void device_start() override;
- virtual void device_reset() override;
+ // device_t implementation
+ virtual void device_start() override ATTR_COLD;
+ virtual void device_reset() override ATTR_COLD;
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
@@ -174,27 +179,26 @@ DECLARE_DEVICE_TYPE(NASBUS, nasbus_device)
// ======================> device_nasbus_interface
-class device_nasbus_card_interface : public device_slot_card_interface
+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; }
+ void set_nasbus_device(nasbus_device &nasbus);
protected:
device_nasbus_card_interface(const machine_config &mconfig, device_t &device);
+ virtual void interface_pre_start() override;
+
+ 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; }
- nasbus_device *m_nasbus;
-
private:
- device_nasbus_card_interface *m_next;
+ nasbus_device *m_nasbus;
};
// include here so drivers don't need to
diff --git a/src/devices/bus/neogeo/boot_cthd.h b/src/devices/bus/neogeo/boot_cthd.h
index d99eeaea941..c98abd38790 100644
--- a/src/devices/bus/neogeo/boot_cthd.h
+++ b/src/devices/bus/neogeo/boot_cthd.h
@@ -29,10 +29,10 @@ protected:
neogeo_cthd2k3_cart_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint16_t clock);
// device-level overrides
- virtual void device_start() override;
- virtual void device_reset() override;
+ virtual void device_start() override ATTR_COLD;
+ virtual void device_reset() override ATTR_COLD;
- virtual void device_add_mconfig(machine_config &config) override;
+ virtual void device_add_mconfig(machine_config &config) override ATTR_COLD;
required_device<cthd_prot_device> m_prot;
};
@@ -84,7 +84,7 @@ public:
virtual int get_fixed_bank_type() override { return 2; }
protected:
- virtual void device_add_mconfig(machine_config &config) override;
+ virtual void device_add_mconfig(machine_config &config) override ATTR_COLD;
private:
required_device<cmc_prot_device> m_cmc_prot;
diff --git a/src/devices/bus/neogeo/boot_kof10th.cpp b/src/devices/bus/neogeo/boot_kof10th.cpp
index d1dd9c925f5..a93b0e55af6 100644
--- a/src/devices/bus/neogeo/boot_kof10th.cpp
+++ b/src/devices/bus/neogeo/boot_kof10th.cpp
@@ -85,18 +85,18 @@ uint32_t neogeo_kof10th_cart_device::get_special_bank()
return m_special_bank;
}
-READ16_MEMBER(neogeo_kof10th_cart_device::protection_r)
+uint16_t neogeo_kof10th_cart_device::protection_r(address_space &space, offs_t offset)
{
return m_cart_ram[offset];
}
-READ16_MEMBER(neogeo_kof10th_cart_device::addon_r)
+uint16_t neogeo_kof10th_cart_device::addon_r(offs_t offset)
{
// printf("kof10th_RAM2_r\n");
return m_cart_ram2[offset];
}
-WRITE16_MEMBER(neogeo_kof10th_cart_device::protection_w)
+void neogeo_kof10th_cart_device::protection_w(offs_t offset, uint16_t data, uint16_t mem_mask)
{
if (offset < 0x40000/2)
{
diff --git a/src/devices/bus/neogeo/boot_kof10th.h b/src/devices/bus/neogeo/boot_kof10th.h
index 9c5cf2a2e5d..a82b61304e7 100644
--- a/src/devices/bus/neogeo/boot_kof10th.h
+++ b/src/devices/bus/neogeo/boot_kof10th.h
@@ -21,19 +21,19 @@ public:
virtual uint16_t get_helper() override;
virtual uint32_t get_bank_base(uint16_t sel) override;
virtual uint32_t get_special_bank() override;
- virtual DECLARE_READ16_MEMBER(addon_r) override;
- virtual DECLARE_READ16_MEMBER(protection_r) override;
- virtual DECLARE_WRITE16_MEMBER(protection_w) override;
+ virtual uint16_t addon_r(offs_t offset) override;
+ virtual uint16_t protection_r(address_space &space, offs_t offset) override;
+ virtual void protection_w(offs_t offset, uint16_t data, uint16_t mem_mask = ~0) override;
virtual void decrypt_all(DECRYPT_ALL_PARAMS) override;
virtual int get_fixed_bank_type() override { return 0; }
protected:
// device-level overrides
- virtual void device_start() override;
- virtual void device_reset() override;
+ virtual void device_start() override ATTR_COLD;
+ virtual void device_reset() override ATTR_COLD;
- virtual void device_add_mconfig(machine_config &config) override;
+ virtual void device_add_mconfig(machine_config &config) override ATTR_COLD;
private:
uint8_t* m_fixed;
diff --git a/src/devices/bus/neogeo/boot_kof2k2.h b/src/devices/bus/neogeo/boot_kof2k2.h
index f7b926a4a2a..36b07f6bc3c 100644
--- a/src/devices/bus/neogeo/boot_kof2k2.h
+++ b/src/devices/bus/neogeo/boot_kof2k2.h
@@ -26,7 +26,7 @@ public:
virtual int get_fixed_bank_type() override { return 0; }
protected:
- virtual void device_add_mconfig(machine_config &config) override;
+ virtual void device_add_mconfig(machine_config &config) override ATTR_COLD;
private:
required_device<cmc_prot_device> m_cmc_prot;
@@ -50,7 +50,7 @@ public:
virtual int get_fixed_bank_type() override { return 0; }
protected:
- virtual void device_add_mconfig(machine_config &config) override;
+ virtual void device_add_mconfig(machine_config &config) override ATTR_COLD;
private:
required_device<cmc_prot_device> m_cmc_prot;
@@ -73,7 +73,7 @@ public:
virtual int get_fixed_bank_type() override { return 0; }
protected:
- virtual void device_add_mconfig(machine_config &config) override;
+ virtual void device_add_mconfig(machine_config &config) override ATTR_COLD;
private:
required_device<cmc_prot_device> m_cmc_prot;
diff --git a/src/devices/bus/neogeo/boot_kof2k3.h b/src/devices/bus/neogeo/boot_kof2k3.h
index a5deb9bc378..272f189872f 100644
--- a/src/devices/bus/neogeo/boot_kof2k3.h
+++ b/src/devices/bus/neogeo/boot_kof2k3.h
@@ -22,12 +22,12 @@ public:
virtual int get_fixed_bank_type() override { return 0; }
virtual uint32_t get_bank_base(uint16_t sel) override { return m_kof2k3bl_prot->get_bank_base(); }
- virtual DECLARE_READ16_MEMBER(protection_r) override { return m_kof2k3bl_prot->protection_r(space, offset, mem_mask); }
- virtual DECLARE_WRITE16_MEMBER(protection_w) override { m_kof2k3bl_prot->kof2003_w(space, offset, data, mem_mask); }
- virtual DECLARE_READ16_MEMBER(addon_r) override { return m_kof2k3bl_prot->overlay_r(space, offset, mem_mask); }
+ virtual uint16_t protection_r(address_space &space, offs_t offset) override { return m_kof2k3bl_prot->protection_r(offset); }
+ virtual void protection_w(offs_t offset, uint16_t data, uint16_t mem_mask = ~0) override { m_kof2k3bl_prot->kof2003_w(offset, data, mem_mask); }
+ virtual uint16_t addon_r(offs_t offset) override { return m_kof2k3bl_prot->overlay_r(); }
protected:
- virtual void device_add_mconfig(machine_config &config) override;
+ virtual void device_add_mconfig(machine_config &config) override ATTR_COLD;
private:
required_device<cmc_prot_device> m_cmc_prot;
@@ -50,11 +50,11 @@ public:
virtual int get_fixed_bank_type() override { return 0; }
virtual uint32_t get_bank_base(uint16_t sel) override { return m_kof2k3bl_prot->get_bank_base(); }
- virtual DECLARE_READ16_MEMBER(protection_r) override { return m_kof2k3bl_prot->protection_r(space, offset, mem_mask); }
- virtual DECLARE_WRITE16_MEMBER(protection_w) override { m_kof2k3bl_prot->kof2003p_w(space, offset, data, mem_mask); }
+ virtual uint16_t protection_r(address_space &space, offs_t offset) override { return m_kof2k3bl_prot->protection_r(offset); }
+ virtual void protection_w(offs_t offset, uint16_t data, uint16_t mem_mask = ~0) override { m_kof2k3bl_prot->kof2003p_w(offset, data, mem_mask); }
protected:
- virtual void device_add_mconfig(machine_config &config) override;
+ virtual void device_add_mconfig(machine_config &config) override ATTR_COLD;
private:
required_device<cmc_prot_device> m_cmc_prot;
@@ -77,12 +77,12 @@ public:
virtual int get_fixed_bank_type() override { return 0; }
virtual uint32_t get_bank_base(uint16_t sel) override { return m_kof2k3bl_prot->get_bank_base(); }
- virtual DECLARE_READ16_MEMBER(protection_r) override { return m_kof2k3bl_prot->protection_r(space, offset, mem_mask); }
- virtual DECLARE_WRITE16_MEMBER(protection_w) override { m_kof2k3bl_prot->kof2003_w(space, offset, data, mem_mask); }
- virtual DECLARE_READ16_MEMBER(addon_r) override { return m_kof2k3bl_prot->overlay_r(space, offset, mem_mask); }
+ virtual uint16_t protection_r(address_space &space, offs_t offset) override { return m_kof2k3bl_prot->protection_r(offset); }
+ virtual void protection_w(offs_t offset, uint16_t data, uint16_t mem_mask = ~0) override { m_kof2k3bl_prot->kof2003_w(offset, data, mem_mask); }
+ virtual uint16_t addon_r(offs_t offset) override { return m_kof2k3bl_prot->overlay_r(); }
protected:
- virtual void device_add_mconfig(machine_config &config) override;
+ virtual void device_add_mconfig(machine_config &config) override ATTR_COLD;
private:
required_device<cmc_prot_device> m_cmc_prot;
diff --git a/src/devices/bus/neogeo/boot_misc.cpp b/src/devices/bus/neogeo/boot_misc.cpp
index b544fa93976..8476123fbc7 100644
--- a/src/devices/bus/neogeo/boot_misc.cpp
+++ b/src/devices/bus/neogeo/boot_misc.cpp
@@ -245,6 +245,25 @@ void neogeo_ms5plus_cart_device::device_add_mconfig(machine_config &config)
/*************************************************
+ mslug5b
+ **************************************************/
+
+DEFINE_DEVICE_TYPE(NEOGEO_MSLUG5B_CART, neogeo_mslug5b_cart_device, "neocart_mslug5b", "Neo Geo Metal Slug 5 Bootleg Cart")
+
+neogeo_mslug5b_cart_device::neogeo_mslug5b_cart_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) :
+ neogeo_bootleg_cart_device(mconfig, NEOGEO_MSLUG5B_CART, tag, owner, clock)
+{
+}
+
+void neogeo_mslug5b_cart_device::decrypt_all(DECRYPT_ALL_PARAMS)
+{
+ m_prot->mslug5b_vx_decrypt(ym_region, ym_region_size);
+ m_prot->sx_decrypt(fix_region, fix_region_size, 2);
+ m_prot->mslug5b_cx_decrypt(spr_region, spr_region_size);
+}
+
+
+/*************************************************
kog
**************************************************/
@@ -273,7 +292,7 @@ ioport_constructor neogeo_kog_cart_device::device_input_ports() const
}
-READ16_MEMBER(neogeo_kog_cart_device::protection_r)
+uint16_t neogeo_kog_cart_device::protection_r(address_space &space, offs_t offset)
{
return m_jumper->read();
}
diff --git a/src/devices/bus/neogeo/boot_misc.h b/src/devices/bus/neogeo/boot_misc.h
index 4943f64583b..6abf1dd5c6d 100644
--- a/src/devices/bus/neogeo/boot_misc.h
+++ b/src/devices/bus/neogeo/boot_misc.h
@@ -25,10 +25,10 @@ protected:
neogeo_bootleg_cart_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint16_t clock);
// device-level overrides
- virtual void device_start() override;
- virtual void device_reset() override;
+ virtual void device_start() override ATTR_COLD;
+ virtual void device_reset() override ATTR_COLD;
- virtual void device_add_mconfig(machine_config &config) override;
+ virtual void device_add_mconfig(machine_config &config) override ATTR_COLD;
required_device<neoboot_prot_device> m_prot;
};
@@ -153,7 +153,7 @@ public:
virtual int get_fixed_bank_type() override { return 0; }
protected:
- virtual void device_add_mconfig(machine_config &config) override;
+ virtual void device_add_mconfig(machine_config &config) override ATTR_COLD;
private:
required_device<cmc_prot_device> m_cmc_prot;
@@ -161,6 +161,7 @@ private:
DECLARE_DEVICE_TYPE(NEOGEO_MSLUG3B6_CART, neogeo_mslug3b6_cart_device)
+
/*************************************************
ms5plus
**************************************************/
@@ -172,11 +173,11 @@ public:
virtual void decrypt_all(DECRYPT_ALL_PARAMS) override;
virtual int get_fixed_bank_type() override { return 1; }
- virtual DECLARE_READ16_MEMBER(protection_r) override { return m_prot->mslug5p_prot_r(space, offset, mem_mask); }
+ virtual uint16_t protection_r(address_space &space, offs_t offset) override { return m_prot->mslug5p_prot_r(); }
virtual uint32_t get_bank_base(uint16_t sel) override { return m_prot->mslug5p_bank_base(sel); }
protected:
- virtual void device_add_mconfig(machine_config &config) override;
+ virtual void device_add_mconfig(machine_config &config) override ATTR_COLD;
private:
required_device<cmc_prot_device> m_cmc_prot;
@@ -187,6 +188,21 @@ DECLARE_DEVICE_TYPE(NEOGEO_MS5PLUS_CART, neogeo_ms5plus_cart_device)
/*************************************************
+ mslug5b
+ **************************************************/
+
+class neogeo_mslug5b_cart_device : public neogeo_bootleg_cart_device
+{
+public:
+ neogeo_mslug5b_cart_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
+ virtual void decrypt_all(DECRYPT_ALL_PARAMS) override;
+ virtual int get_fixed_bank_type() override { return 0; }
+};
+
+DECLARE_DEVICE_TYPE(NEOGEO_MSLUG5B_CART, neogeo_mslug5b_cart_device)
+
+
+/*************************************************
kog
**************************************************/
@@ -195,9 +211,9 @@ class neogeo_kog_cart_device : public neogeo_bootleg_cart_device
public:
neogeo_kog_cart_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
- virtual ioport_constructor device_input_ports() const override;
+ virtual ioport_constructor device_input_ports() const override ATTR_COLD;
- virtual DECLARE_READ16_MEMBER(protection_r) override;
+ virtual uint16_t protection_r(address_space &space, offs_t offset) override;
virtual void decrypt_all(DECRYPT_ALL_PARAMS) override;
virtual int get_fixed_bank_type() override { return 0; }
diff --git a/src/devices/bus/neogeo/boot_svc.h b/src/devices/bus/neogeo/boot_svc.h
index 57c68c29afd..33970d2c170 100644
--- a/src/devices/bus/neogeo/boot_svc.h
+++ b/src/devices/bus/neogeo/boot_svc.h
@@ -20,13 +20,13 @@ public:
neogeo_svcboot_cart_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
virtual uint32_t get_bank_base(uint16_t sel) override { return m_pvc_prot->get_bank_base(); }
- virtual DECLARE_READ16_MEMBER(protection_r) override { return m_pvc_prot->protection_r(space, offset, mem_mask); }
- virtual DECLARE_WRITE16_MEMBER(protection_w) override { m_pvc_prot->protection_w(space, offset, data, mem_mask); }
+ virtual uint16_t protection_r(address_space &space, offs_t offset) override { return m_pvc_prot->protection_r(offset); }
+ virtual void protection_w(offs_t offset, uint16_t data, uint16_t mem_mask = ~0) override { m_pvc_prot->protection_w(offset, data, mem_mask); }
virtual void decrypt_all(DECRYPT_ALL_PARAMS) override;
virtual int get_fixed_bank_type() override { return 0; }
protected:
- virtual void device_add_mconfig(machine_config &config) override;
+ virtual void device_add_mconfig(machine_config &config) override ATTR_COLD;
private:
required_device<pvc_prot_device> m_pvc_prot;
@@ -74,13 +74,13 @@ public:
neogeo_svcsplus_cart_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
virtual uint32_t get_bank_base(uint16_t sel) override { return m_pvc_prot->get_bank_base(); }
- virtual DECLARE_READ16_MEMBER(protection_r) override { return m_pvc_prot->protection_r(space, offset, mem_mask); }
- virtual DECLARE_WRITE16_MEMBER(protection_w) override { m_pvc_prot->protection_w(space, offset, data, mem_mask); }
+ virtual uint16_t protection_r(address_space &space, offs_t offset) override { return m_pvc_prot->protection_r(offset); }
+ virtual void protection_w(offs_t offset, uint16_t data, uint16_t mem_mask = ~0) override { m_pvc_prot->protection_w(offset, data, mem_mask); }
virtual void decrypt_all(DECRYPT_ALL_PARAMS) override;
virtual int get_fixed_bank_type() override { return 0; }
protected:
- virtual void device_add_mconfig(machine_config &config) override;
+ virtual void device_add_mconfig(machine_config &config) override ATTR_COLD;
private:
required_device<pvc_prot_device> m_pvc_prot;
diff --git a/src/devices/bus/neogeo/carts.cpp b/src/devices/bus/neogeo/carts.cpp
index 94fbb70c34e..854a2248ae8 100644
--- a/src/devices/bus/neogeo/carts.cpp
+++ b/src/devices/bus/neogeo/carts.cpp
@@ -109,6 +109,7 @@ void neogeo_cart(device_slot_interface &device)
device.option_add_internal("boot_samsho5b", NEOGEO_SAMSHO5B_CART);
device.option_add_internal("boot_mslug3b6", NEOGEO_MSLUG3B6_CART); // this also uses a CMC42 for gfx
device.option_add_internal("boot_ms5plus", NEOGEO_MS5PLUS_CART); // this also uses a CMC50 for gfx + audiocpu & NEOPCM2 for YM scramble
+ device.option_add_internal("boot_mslug5b", NEOGEO_MSLUG5B_CART);
device.option_add_internal("boot_kog", NEOGEO_KOG_CART);
device.option_add_internal("boot_kf10th", NEOGEO_KOF10TH_CART);
diff --git a/src/devices/bus/neogeo/cmc.h b/src/devices/bus/neogeo/cmc.h
index bba8251d2e5..72cf6b6431d 100644
--- a/src/devices/bus/neogeo/cmc.h
+++ b/src/devices/bus/neogeo/cmc.h
@@ -26,10 +26,10 @@ protected:
neogeo_cmc_cart_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint16_t clock);
// device-level overrides
- virtual void device_start() override;
- virtual void device_reset() override;
+ virtual void device_start() override ATTR_COLD;
+ virtual void device_reset() override ATTR_COLD;
- virtual void device_add_mconfig(machine_config &config) override;
+ virtual void device_add_mconfig(machine_config &config) override ATTR_COLD;
required_device<cmc_prot_device> m_prot;
};
@@ -214,13 +214,13 @@ public:
virtual void decrypt_all(DECRYPT_ALL_PARAMS) override;
virtual int get_fixed_bank_type() override { return 1; }
- virtual DECLARE_READ16_MEMBER(ram_r) override { return m_ram[offset]; }
- virtual DECLARE_WRITE16_MEMBER(ram_w) override { COMBINE_DATA(&m_ram[offset]); }
+ virtual uint16_t ram_r(offs_t offset) override { return m_ram[offset]; }
+ virtual void ram_w(offs_t offset, uint16_t data, uint16_t mem_mask = ~0) override { COMBINE_DATA(&m_ram[offset]); }
protected:
- virtual void device_start() override;
+ virtual void device_start() override ATTR_COLD;
- virtual void device_add_mconfig(machine_config &config) override;
+ virtual void device_add_mconfig(machine_config &config) override ATTR_COLD;
private:
std::unique_ptr<uint16_t[]> m_ram;
diff --git a/src/devices/bus/neogeo/fatfury2.h b/src/devices/bus/neogeo/fatfury2.h
index 804049e4ff0..375034f5cf3 100644
--- a/src/devices/bus/neogeo/fatfury2.h
+++ b/src/devices/bus/neogeo/fatfury2.h
@@ -18,15 +18,15 @@ public:
neogeo_fatfury2_cart_device(const machine_config &mconfig, const char *tag, device_t *owner, uint16_t clock);
// reading and writing
- virtual DECLARE_READ16_MEMBER(protection_r) override { return m_prot->protection_r(space, offset, mem_mask); }
- virtual DECLARE_WRITE16_MEMBER(protection_w) override { m_prot->protection_w(space, offset, data, mem_mask); }
+ virtual uint16_t protection_r(address_space &space, offs_t offset) override { return m_prot->protection_r(offset); }
+ virtual void protection_w(offs_t offset, uint16_t data, uint16_t mem_mask = ~0) override { m_prot->protection_w(offset, data); }
protected:
// device-level overrides
- virtual void device_start() override;
- virtual void device_reset() override;
+ virtual void device_start() override ATTR_COLD;
+ virtual void device_reset() override ATTR_COLD;
- virtual void device_add_mconfig(machine_config &config) override;
+ virtual void device_add_mconfig(machine_config &config) override ATTR_COLD;
required_device<fatfury2_prot_device> m_prot;
};
diff --git a/src/devices/bus/neogeo/kof2k2.h b/src/devices/bus/neogeo/kof2k2.h
index f5ade4c4444..476ce79361c 100644
--- a/src/devices/bus/neogeo/kof2k2.h
+++ b/src/devices/bus/neogeo/kof2k2.h
@@ -27,10 +27,10 @@ protected:
neogeo_kof2k2type_cart_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint16_t clock);
// device-level overrides
- virtual void device_start() override;
- virtual void device_reset() override;
+ virtual void device_start() override ATTR_COLD;
+ virtual void device_reset() override ATTR_COLD;
- virtual void device_add_mconfig(machine_config &config) override;
+ virtual void device_add_mconfig(machine_config &config) override ATTR_COLD;
required_device<cmc_prot_device> m_cmc_prot;
required_device<pcm2_prot_device> m_pcm2_prot;
diff --git a/src/devices/bus/neogeo/kof98.h b/src/devices/bus/neogeo/kof98.h
index 9cb1ddbf59e..fe3f0fa5de0 100644
--- a/src/devices/bus/neogeo/kof98.h
+++ b/src/devices/bus/neogeo/kof98.h
@@ -18,17 +18,17 @@ public:
neogeo_kof98_cart_device(const machine_config &mconfig, const char *tag, device_t *owner, uint16_t clock);
// reading and writing
- virtual DECLARE_READ16_MEMBER(protection_r) override { return m_prot->protection_r(space, offset, mem_mask); }
- virtual DECLARE_WRITE16_MEMBER(protection_w) override { m_prot->protection_w(space, offset, data, mem_mask); }
+ virtual uint16_t protection_r(address_space &space, offs_t offset) override { return m_prot->protection_r(offset); }
+ virtual void protection_w(offs_t offset, uint16_t data, uint16_t mem_mask = ~0) override { m_prot->protection_w(data); }
virtual void decrypt_all(DECRYPT_ALL_PARAMS) override;
protected:
// device-level overrides
- virtual void device_start() override;
- virtual void device_reset() override;
+ virtual void device_start() override ATTR_COLD;
+ virtual void device_reset() override ATTR_COLD;
- virtual void device_add_mconfig(machine_config &config) override;
+ virtual void device_add_mconfig(machine_config &config) override ATTR_COLD;
required_device<kof98_prot_device> m_prot;
};
diff --git a/src/devices/bus/neogeo/mslugx.h b/src/devices/bus/neogeo/mslugx.h
index cb542fb7530..6a8d1f80648 100644
--- a/src/devices/bus/neogeo/mslugx.h
+++ b/src/devices/bus/neogeo/mslugx.h
@@ -18,15 +18,15 @@ public:
neogeo_mslugx_cart_device(const machine_config &mconfig, const char *tag, device_t *owner, uint16_t clock);
// reading and writing
- virtual DECLARE_READ16_MEMBER(protection_r) override { return m_prot->protection_r(space, offset, mem_mask); }
- virtual DECLARE_WRITE16_MEMBER(protection_w) override { m_prot->protection_w(space, offset, data, mem_mask); }
+ virtual uint16_t protection_r(address_space &space, offs_t offset) override { return m_prot->protection_r(space, offset); }
+ virtual void protection_w(offs_t offset, uint16_t data, uint16_t mem_mask = ~0) override { m_prot->protection_w(offset, data); }
protected:
// device-level overrides
- virtual void device_start() override;
- virtual void device_reset() override;
+ virtual void device_start() override ATTR_COLD;
+ virtual void device_reset() override ATTR_COLD;
- virtual void device_add_mconfig(machine_config &config) override;
+ virtual void device_add_mconfig(machine_config &config) override ATTR_COLD;
required_device<mslugx_prot_device> m_prot;
};
diff --git a/src/devices/bus/neogeo/pcm2.h b/src/devices/bus/neogeo/pcm2.h
index a088d9b0172..a1ccb59f468 100644
--- a/src/devices/bus/neogeo/pcm2.h
+++ b/src/devices/bus/neogeo/pcm2.h
@@ -23,10 +23,10 @@ protected:
neogeo_pcm2_cart_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint16_t clock);
// device-level overrides
- virtual void device_start() override;
- virtual void device_reset() override;
+ virtual void device_start() override ATTR_COLD;
+ virtual void device_reset() override ATTR_COLD;
- virtual void device_add_mconfig(machine_config &config) override;
+ virtual void device_add_mconfig(machine_config &config) override ATTR_COLD;
required_device<cmc_prot_device> m_cmc_prot;
required_device<pcm2_prot_device> m_pcm2_prot;
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..be6deb783f4 100644
--- a/src/devices/bus/neogeo/prot_cmc.h
+++ b/src/devices/bus/neogeo/prot_cmc.h
@@ -59,13 +59,12 @@ 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);
protected:
- virtual void device_start() override;
- virtual void device_reset() override;
+ virtual void device_start() override ATTR_COLD;
+ virtual void device_reset() override ATTR_COLD;
const uint8_t *type0_t03;
const uint8_t *type0_t12;
diff --git a/src/devices/bus/neogeo/prot_cthd.cpp b/src/devices/bus/neogeo/prot_cthd.cpp
index d2c427d6ac7..d4cbc5c2a79 100644
--- a/src/devices/bus/neogeo/prot_cthd.cpp
+++ b/src/devices/bus/neogeo/prot_cthd.cpp
@@ -118,7 +118,7 @@ void cthd_prot_device::decrypt_cthd2003(uint8_t* sprrom, uint32_t sprrom_size, u
// temporarily replaced by the get_bank_base functions below, until we clean up bankswitch implementation
/*
-WRITE16_MEMBER( ngbootleg_prot_device::cthd2003_bankswitch_w )
+void ngbootleg_prot_device::cthd2003_bankswitch_w(offs_t offset, uint16_t data)
{
int bankaddress;
static const int cthd2003_banks[8] =
diff --git a/src/devices/bus/neogeo/prot_cthd.h b/src/devices/bus/neogeo/prot_cthd.h
index 95ae38289b3..aa60cd70b00 100644
--- a/src/devices/bus/neogeo/prot_cthd.h
+++ b/src/devices/bus/neogeo/prot_cthd.h
@@ -20,7 +20,7 @@ public:
void decrypt_cthd2003(uint8_t* sprrom, uint32_t sprrom_size, uint8_t* audiorom, uint32_t audiorom_size, uint8_t* fixedrom, uint32_t fixedrom_size);
void patch_cthd2003(uint8_t* cpurom, uint32_t cpurom_size);
- //DECLARE_WRITE16_MEMBER(cthd2003_bankswitch_w);
+ //void cthd2003_bankswitch_w(offs_t offset, uint16_t data);
uint32_t get_bank_base(uint16_t sel);
void ct2k3sp_sx_decrypt(uint8_t* fixedrom, uint32_t fixedrom_size);
@@ -32,8 +32,8 @@ public:
void matrimbl_decrypt(uint8_t* sprrom, uint32_t sprrom_size, uint8_t* audiorom, uint32_t audiorom_size);
protected:
- virtual void device_start() override;
- virtual void device_reset() override;
+ virtual void device_start() override ATTR_COLD;
+ virtual void device_reset() override ATTR_COLD;
};
#endif // MAME_BUS_NEOGEO_PROT_CTHD_H
diff --git a/src/devices/bus/neogeo/prot_fatfury2.cpp b/src/devices/bus/neogeo/prot_fatfury2.cpp
index 418c49ff4cd..d28b417b33d 100644
--- a/src/devices/bus/neogeo/prot_fatfury2.cpp
+++ b/src/devices/bus/neogeo/prot_fatfury2.cpp
@@ -11,14 +11,18 @@ DEFINE_DEVICE_TYPE(NG_FATFURY2_PROT, fatfury2_prot_device, "ng_fatfury_prot", "N
fatfury2_prot_device::fatfury2_prot_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) :
device_t(mconfig, NG_FATFURY2_PROT, tag, owner, clock),
- m_prot_data(0)
+ m_pro_ct0(*this, "pro_ct0")
{
}
+void fatfury2_prot_device::device_add_mconfig(machine_config &config)
+{
+ ALPHA_8921(config, m_pro_ct0, 0); // PRO-CT0 or SNK-9201
+}
+
void fatfury2_prot_device::device_start()
{
- save_item(NAME(m_prot_data));
}
void fatfury2_prot_device::device_reset()
@@ -31,71 +35,39 @@ void fatfury2_prot_device::device_reset()
/* the protection involves reading and writing addresses in the */
/* 0x2xxxxx range. There are several checks all around the code. */
-READ16_MEMBER( fatfury2_prot_device::protection_r )
+uint16_t fatfury2_prot_device::protection_r(offs_t offset)
{
- uint16_t res = m_prot_data >> 24;
-
- switch (offset)
- {
- case 0x55550/2:
- case 0xffff0/2:
- case 0x00000/2:
- case 0xff000/2:
- case 0x36000/2:
- case 0x36008/2:
- return res;
-
- case 0x36004/2:
- case 0x3600c/2:
- return ((res & 0xf0) >> 4) | ((res & 0x0f) << 4);
-
- default:
- logerror("unknown protection read at %s, offset %08x\n", machine().describe_context(), offset << 1);
- return 0;
- }
+ m_pro_ct0->even_w(BIT(offset, 1));
+ m_pro_ct0->h_w(BIT(offset, 2));
+ u8 gad = m_pro_ct0->gad_r();
+ u8 gbd = m_pro_ct0->gbd_r();
+ /*
+ Data pin from PRO-CT0
+ D0 D1 D2 D3 D4 D5 D6 D7
+ GAD2 GAD3 GAD0 GAD1 GBD2 GBD3 GBD0 GBD1
+ */
+ return (BIT(gbd, 0, 2) << 6) | (BIT(gbd, 2, 2) << 4) | (BIT(gad, 0, 2) << 2) | (BIT(gad, 2, 2) << 0);
}
-WRITE16_MEMBER( fatfury2_prot_device::protection_w )
+void fatfury2_prot_device::protection_w(offs_t offset, uint16_t data)
{
- switch (offset)
- {
- case 0x11112/2: /* data == 0x1111; expects 0xff000000 back */
- m_prot_data = 0xff000000;
- break;
-
- case 0x33332/2: /* data == 0x3333; expects 0x0000ffff back */
- m_prot_data = 0x0000ffff;
- break;
-
- case 0x44442/2: /* data == 0x4444; expects 0x00ff0000 back */
- m_prot_data = 0x00ff0000;
- break;
-
- case 0x55552/2: /* data == 0x5555; read back from 55550, ffff0, 00000, ff000 */
- m_prot_data = 0xff00ff00;
- break;
-
- case 0x56782/2: /* data == 0x1234; read back from 36000 *or* 36004 */
- m_prot_data = 0xf05a3601;
- break;
-
- case 0x42812/2: /* data == 0x1824; read back from 36008 *or* 3600c */
- m_prot_data = 0x81422418;
- break;
-
- case 0x55550/2:
- case 0xffff0/2:
- case 0xff000/2:
- case 0x36000/2:
- case 0x36004/2:
- case 0x36008/2:
- case 0x3600c/2:
- m_prot_data <<= 8;
- break;
-
- default:
- logerror("unknown protection write at %s, offset %08x, data %02x\n", machine().describe_context(), offset, data);
- break;
- }
+ // /PORTOEL connected into PRO-CT0 CLK pin
+ m_pro_ct0->clk_w(true);
+
+ m_pro_ct0->load_w(BIT(offset, 0)); // A1
+ m_pro_ct0->even_w(BIT(offset, 1)); // A2
+ m_pro_ct0->h_w(BIT(offset, 2)); // A3
+
+ // C16-31 = A4-A19, C0-C15 = D0-D15
+ /*
+ Address/Data pin mapping into PRO-CT0
+ C0 C1 C2 C3 C4 C5 C6 C7 C8 C9 C10 C11 C12 C13 C14 C15 C16 C17 C18 C19 C20 C21 C22 C23 C24 C25 C26 C27 C28 C29 C30 C31 LOAD EVEN H
+ D0 D4 D1 D5 D2 D6 D3 D7 D8 D12 D9 D13 D10 D14 D11 D15 A4 A8 A5 A9 A6 A10 A7 A11 A12 A16 A13 A17 A14 A18 A15 A19 A1 A2 A3
+ */
+ m_pro_ct0->c_w((u32(bitswap<16>(BIT(offset, 3, 16), 15, 11, 14, 10, 13, 9, 12, 8, 7, 3, 6, 2, 5, 1, 4, 0)) << 16) |
+ u32(bitswap<16>(data, 15, 11, 14, 10, 13, 9, 12, 8, 7, 3, 6, 2, 5, 1, 4, 0)));
+
+ // release /PORTOEL
+ m_pro_ct0->clk_w(false);
}
diff --git a/src/devices/bus/neogeo/prot_fatfury2.h b/src/devices/bus/neogeo/prot_fatfury2.h
index bb33d1c10c1..6cf08a09654 100644
--- a/src/devices/bus/neogeo/prot_fatfury2.h
+++ b/src/devices/bus/neogeo/prot_fatfury2.h
@@ -6,6 +6,8 @@
#pragma once
+#include "machine/alpha_8921.h"
+
DECLARE_DEVICE_TYPE(NG_FATFURY2_PROT, fatfury2_prot_device)
@@ -15,14 +17,16 @@ public:
// construction/destruction
fatfury2_prot_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock = 0);
- DECLARE_READ16_MEMBER( protection_r );
- DECLARE_WRITE16_MEMBER( protection_w );
+ uint16_t protection_r(offs_t offset);
+ void protection_w(offs_t offset, uint16_t data);
protected:
- virtual void device_start() override;
- virtual void device_reset() override;
+ 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;
- uint32_t m_prot_data;
+private:
+ required_device<alpha_8921_device> m_pro_ct0; // PRO-CT0 or SNK-9201
};
#endif // MAME_BUS_NEOGEO_PROT_FATFURY2_H
diff --git a/src/devices/bus/neogeo/prot_kof2k2.h b/src/devices/bus/neogeo/prot_kof2k2.h
index 324da5a8918..a509e0fa273 100644
--- a/src/devices/bus/neogeo/prot_kof2k2.h
+++ b/src/devices/bus/neogeo/prot_kof2k2.h
@@ -22,8 +22,8 @@ public:
void samsh5sp_decrypt_68k(uint8_t* cpurom, uint32_t cpurom_size);
protected:
- virtual void device_start() override;
- virtual void device_reset() override;
+ virtual void device_start() override ATTR_COLD;
+ virtual void device_reset() override ATTR_COLD;
};
#endif // MAME_BUS_NEOGEO_PROT_KOF2K2_H
diff --git a/src/devices/bus/neogeo/prot_kof2k3bl.cpp b/src/devices/bus/neogeo/prot_kof2k3bl.cpp
index 456f164c042..67262d15bc8 100644
--- a/src/devices/bus/neogeo/prot_kof2k3bl.cpp
+++ b/src/devices/bus/neogeo/prot_kof2k3bl.cpp
@@ -31,17 +31,17 @@ void kof2k3bl_prot_device::device_reset()
/* The King of Fighters 2003 (bootleg set 1) */
-READ16_MEMBER( kof2k3bl_prot_device::protection_r)
+uint16_t kof2k3bl_prot_device::protection_r(offs_t offset)
{
return m_cartridge_ram[offset];
}
-READ16_MEMBER(kof2k3bl_prot_device::overlay_r) // hack?
+uint16_t kof2k3bl_prot_device::overlay_r() // hack?
{
return m_overlay;
}
-WRITE16_MEMBER(kof2k3bl_prot_device::kof2003_w)
+void kof2k3bl_prot_device::kof2003_w(offs_t offset, uint16_t data, uint16_t mem_mask)
{
data = COMBINE_DATA(&m_cartridge_ram[offset]);
if (offset == 0x1ff0/2 || offset == 0x1ff2/2)
@@ -60,7 +60,7 @@ WRITE16_MEMBER(kof2k3bl_prot_device::kof2003_w)
}
}
-WRITE16_MEMBER(kof2k3bl_prot_device::kof2003p_w)
+void kof2k3bl_prot_device::kof2003p_w(offs_t offset, uint16_t data, uint16_t mem_mask)
{
data = COMBINE_DATA(&m_cartridge_ram[offset]);
if (offset == 0x1ff0/2 || offset == 0x1ff2/2)
diff --git a/src/devices/bus/neogeo/prot_kof2k3bl.h b/src/devices/bus/neogeo/prot_kof2k3bl.h
index 52d87e87bfe..f0867e22dd7 100644
--- a/src/devices/bus/neogeo/prot_kof2k3bl.h
+++ b/src/devices/bus/neogeo/prot_kof2k3bl.h
@@ -15,18 +15,18 @@ public:
// construction/destruction
kof2k3bl_prot_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock = 0);
- DECLARE_READ16_MEMBER(protection_r);
- DECLARE_WRITE16_MEMBER(kof2003_w);
- DECLARE_WRITE16_MEMBER(kof2003p_w);
- DECLARE_READ16_MEMBER(overlay_r);
+ uint16_t protection_r(offs_t offset);
+ void kof2003_w(offs_t offset, uint16_t data, uint16_t mem_mask = ~0);
+ void kof2003p_w(offs_t offset, uint16_t data, uint16_t mem_mask = ~0);
+ uint16_t overlay_r();
void bl_px_decrypt(uint8_t* cpurom, uint32_t cpurom_size);
void pl_px_decrypt(uint8_t* cpurom, uint32_t cpurom_size);
void upl_px_decrypt(uint8_t* cpurom, uint32_t cpurom_size);
uint32_t get_bank_base() {return m_bank_base; }
protected:
- virtual void device_start() override;
- virtual void device_reset() override;
+ virtual void device_start() override ATTR_COLD;
+ virtual void device_reset() override ATTR_COLD;
private:
uint16_t m_overlay;
diff --git a/src/devices/bus/neogeo/prot_kof98.cpp b/src/devices/bus/neogeo/prot_kof98.cpp
index 5f76d935e1a..528bb2bf691 100644
--- a/src/devices/bus/neogeo/prot_kof98.cpp
+++ b/src/devices/bus/neogeo/prot_kof98.cpp
@@ -81,7 +81,7 @@ void kof98_prot_device::decrypt_68k(uint8_t* cpurom, uint32_t cpurom_size)
The boards have an ALTERA chip (EPM7128SQC100-15) which is tied to 242-P1
***************************************************************/
-READ16_MEMBER(kof98_prot_device::protection_r)
+uint16_t kof98_prot_device::protection_r(offs_t offset)
{
if (m_prot_state == 1)
{
@@ -106,7 +106,7 @@ READ16_MEMBER(kof98_prot_device::protection_r)
/* when 0x20aaaa contains 0x0090 (word) then 0x100 (normally the neogeo header) should return 0x00c200fd worked out using real hw */
-WRITE16_MEMBER( kof98_prot_device::protection_w )
+void kof98_prot_device::protection_w(uint16_t data)
{
/* info from razoola */
switch (data)
diff --git a/src/devices/bus/neogeo/prot_kof98.h b/src/devices/bus/neogeo/prot_kof98.h
index 652e098898a..f67b0dd8eb5 100644
--- a/src/devices/bus/neogeo/prot_kof98.h
+++ b/src/devices/bus/neogeo/prot_kof98.h
@@ -17,14 +17,14 @@ public:
kof98_prot_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock = 0);
void decrypt_68k(uint8_t* cpurom, uint32_t cpurom_size);
- DECLARE_WRITE16_MEMBER(protection_w);
- DECLARE_READ16_MEMBER(protection_r);
+ void protection_w(uint16_t data);
+ uint16_t protection_r(offs_t offset);
int m_prot_state;
uint16_t m_default_rom[2];
protected:
- virtual void device_start() override;
- virtual void device_reset() override;
+ virtual void device_start() override ATTR_COLD;
+ virtual void device_reset() override ATTR_COLD;
};
#endif // MAME_BUS_NEOGEO_PROT_KOF98_H
diff --git a/src/devices/bus/neogeo/prot_misc.cpp b/src/devices/bus/neogeo/prot_misc.cpp
index d145b78cdfb..3cd4b6db75c 100644
--- a/src/devices/bus/neogeo/prot_misc.cpp
+++ b/src/devices/bus/neogeo/prot_misc.cpp
@@ -267,7 +267,7 @@ void neoboot_prot_device::samsho5b_vx_decrypt(uint8_t* ymsndrom, uint32_t ymsndr
/* Metal Slug 5 Plus (bootleg) */
-READ16_MEMBER( neoboot_prot_device::mslug5p_prot_r )
+uint16_t neoboot_prot_device::mslug5p_prot_r()
{
logerror("%s access protected\n", machine().describe_context());
return 0xa0;
@@ -275,7 +275,7 @@ READ16_MEMBER( neoboot_prot_device::mslug5p_prot_r )
// FIXME: temporarily moved to the driver, through mslug5p_bank_base() below
/*
-WRITE16_MEMBER( neoboot_prot_device::ms5plus_bankswitch_w )
+void neoboot_prot_device::ms5plus_bankswitch_w(offs_t offset, uint16_t data)
{
int bankaddress;
logerror("offset: %06x %s set banking %04x\n",offset,machine().describe_context(),data);
@@ -304,6 +304,34 @@ uint32_t neoboot_prot_device::mslug5p_bank_base(uint16_t sel)
}
+/* Metal Slug 5 (bootleg) */
+
+void neoboot_prot_device::mslug5b_vx_decrypt(uint8_t* ymsndrom, uint32_t ymsndrom_size)
+{
+ // only odd bytes are scrambled
+ int ym_size = ymsndrom_size;
+ uint8_t *rom = ymsndrom;
+ for (int i = 1; i < ym_size; i += 2)
+ rom[i] = bitswap<8>(rom[i], 3, 2, 4, 1, 5, 0, 6, 7);
+}
+
+void neoboot_prot_device::mslug5b_cx_decrypt(uint8_t* sprrom, uint32_t sprrom_size)
+{
+ // rom a18/a19 lines are swapped
+ int cx_size = sprrom_size;
+ uint8_t *rom = sprrom;
+ std::vector<uint8_t> buf(cx_size);
+
+ memcpy(&buf[0], rom, cx_size);
+
+ for (int i = 1; i < 128; i += 4)
+ {
+ memcpy(&rom[i * 0x80000], &buf[(i + 1) * 0x80000], 0x80000);
+ memcpy(&rom[(i + 1) * 0x80000], &buf[i * 0x80000], 0x80000);
+ }
+}
+
+
/* The King of Gladiator (The King of Fighters '97 bootleg) */
// The protection patching here may be incomplete - Thanks to Razoola for the info
diff --git a/src/devices/bus/neogeo/prot_misc.h b/src/devices/bus/neogeo/prot_misc.h
index e1525fc44f6..a5e746c74ab 100644
--- a/src/devices/bus/neogeo/prot_misc.h
+++ b/src/devices/bus/neogeo/prot_misc.h
@@ -34,14 +34,17 @@ public:
void samsho5b_px_decrypt(uint8_t* cpurom, uint32_t cpurom_size);
void samsho5b_vx_decrypt(uint8_t* ymsndrom, uint32_t ymsndrom_size);
- DECLARE_READ16_MEMBER(mslug5p_prot_r);
- //DECLARE_WRITE16_MEMBER(ms5plus_bankswitch_w);
+ uint16_t mslug5p_prot_r();
+ //void ms5plus_bankswitch_w(offs_t offset, uint16_t data);
uint32_t mslug5p_bank_base(uint16_t sel);
+ void mslug5b_vx_decrypt(uint8_t* ymsndrom, uint32_t ymsndrom_size);
+ void mslug5b_cx_decrypt(uint8_t* sprrom, uint32_t sprrom_size);
+
void kog_px_decrypt(uint8_t* cpurom, uint32_t cpurom_size);
void svcboot_px_decrypt(uint8_t* cpurom, uint32_t cpurom_size);
- void svcboot_cx_decrypt(uint8_t*sprrom, uint32_t sprrom_size);
+ void svcboot_cx_decrypt(uint8_t* sprrom, uint32_t sprrom_size);
void svcplus_px_decrypt(uint8_t* cpurom, uint32_t cpurom_size);
void svcplus_px_hack(uint8_t* cpurom, uint32_t cpurom_size);
void svcplusa_px_decrypt(uint8_t* cpurom, uint32_t cpurom_size);
@@ -55,8 +58,8 @@ public:
void kof10th_decrypt(uint8_t* cpurom, uint32_t cpurom_size);
protected:
- virtual void device_start() override;
- virtual void device_reset() override;
+ virtual void device_start() override ATTR_COLD;
+ virtual void device_reset() override ATTR_COLD;
};
#endif // MAME_BUS_NEOGEO_PROT_MISC_H
diff --git a/src/devices/bus/neogeo/prot_mslugx.cpp b/src/devices/bus/neogeo/prot_mslugx.cpp
index 650d595bf87..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"
@@ -32,7 +32,7 @@ void mslugx_prot_device::device_reset()
Also found is a QFP144 chip labeled with 0103 - function unknown
***************************************************************/
-WRITE16_MEMBER( mslugx_prot_device::protection_w )
+void mslugx_prot_device::protection_w(offs_t offset, uint16_t data)
{
switch (offset)
{
@@ -60,7 +60,7 @@ WRITE16_MEMBER( mslugx_prot_device::protection_w )
}
-READ16_MEMBER( mslugx_prot_device::protection_r )
+uint16_t mslugx_prot_device::protection_r(address_space &space, offs_t offset)
{
uint16_t res = 0;
diff --git a/src/devices/bus/neogeo/prot_mslugx.h b/src/devices/bus/neogeo/prot_mslugx.h
index 106bce3ad84..93c8ebdb912 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
@@ -16,12 +16,12 @@ public:
// construction/destruction
mslugx_prot_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock = 0);
- DECLARE_WRITE16_MEMBER( protection_w );
- DECLARE_READ16_MEMBER( protection_r );
+ void protection_w(offs_t offset, uint16_t data);
+ uint16_t protection_r(address_space &space, offs_t offset);
protected:
- virtual void device_start() override;
- virtual void device_reset() override;
+ virtual void device_start() override ATTR_COLD;
+ virtual void device_reset() override ATTR_COLD;
private:
uint16_t m_counter;
diff --git a/src/devices/bus/neogeo/prot_pcm2.h b/src/devices/bus/neogeo/prot_pcm2.h
index 707e9ab94b4..823b1849468 100644
--- a/src/devices/bus/neogeo/prot_pcm2.h
+++ b/src/devices/bus/neogeo/prot_pcm2.h
@@ -20,8 +20,8 @@ public:
void swap(uint8_t* ymrom, uint32_t ymsize, int value);
protected:
- virtual void device_start() override;
- virtual void device_reset() override;
+ virtual void device_start() override ATTR_COLD;
+ virtual void device_reset() override ATTR_COLD;
};
#endif // MAME_BUS_NEOGEO_PROT_PCM2_H
diff --git a/src/devices/bus/neogeo/prot_pvc.cpp b/src/devices/bus/neogeo/prot_pvc.cpp
index 8e290596576..1f0d734e732 100644
--- a/src/devices/bus/neogeo/prot_pvc.cpp
+++ b/src/devices/bus/neogeo/prot_pvc.cpp
@@ -75,12 +75,12 @@ uint32_t pvc_prot_device::get_bank_base()
return bankaddress + 0x100000;
}
-READ16_MEMBER( pvc_prot_device::protection_r )
+uint16_t pvc_prot_device::protection_r(offs_t offset)
{
return m_cart_ram[offset];
}
-WRITE16_MEMBER( pvc_prot_device::protection_w )
+void pvc_prot_device::protection_w(offs_t offset, uint16_t data, uint16_t mem_mask)
{
COMBINE_DATA(&m_cart_ram[offset]);
if (offset == 0xff0)
diff --git a/src/devices/bus/neogeo/prot_pvc.h b/src/devices/bus/neogeo/prot_pvc.h
index d2855808331..a6cd628a17d 100644
--- a/src/devices/bus/neogeo/prot_pvc.h
+++ b/src/devices/bus/neogeo/prot_pvc.h
@@ -19,8 +19,8 @@ public:
void pvc_write_pack_color();
// void pvc_write_bankswitch(address_space &space);
uint32_t get_bank_base();
- DECLARE_READ16_MEMBER(protection_r);
- DECLARE_WRITE16_MEMBER(protection_w);
+ uint16_t protection_r(offs_t offset);
+ void protection_w(offs_t offset, uint16_t data, uint16_t mem_mask = ~0);
uint16_t m_cart_ram[0x1000];
@@ -31,8 +31,8 @@ public:
void kof2003h_decrypt_68k(uint8_t* rom, uint32_t size);
protected:
- virtual void device_start() override;
- virtual void device_reset() override;
+ virtual void device_start() override ATTR_COLD;
+ virtual void device_reset() override ATTR_COLD;
};
#endif // MAME_BUS_NEOGEO_PROT_PVC_H
diff --git a/src/devices/bus/neogeo/prot_sma.cpp b/src/devices/bus/neogeo/prot_sma.cpp
index 99ed2269d2a..ccb569fec6e 100644
--- a/src/devices/bus/neogeo/prot_sma.cpp
+++ b/src/devices/bus/neogeo/prot_sma.cpp
@@ -33,7 +33,7 @@ void sma_prot_device::device_reset()
// temporarily replaced by the get_bank_base functions below, until we clean up bankswitch implementation
#if 0
-WRITE16_MEMBER( sma_prot_device::kof99_bankswitch_w )
+void sma_prot_device::kof99_bankswitch_w(uint16_t data)
{
int bankaddress;
static const int bankoffset[64] =
@@ -50,20 +50,14 @@ WRITE16_MEMBER( sma_prot_device::kof99_bankswitch_w )
};
// unscramble bank number
- data =
- (BIT(data, 14) << 0)+
- (BIT(data, 6) << 1)+
- (BIT(data, 8) << 2)+
- (BIT(data, 10) << 3)+
- (BIT(data, 12) << 4)+
- (BIT(data, 5) << 5);
+ data = bitswap<6>(data, 5, 12, 10, 8, 6, 14);
bankaddress = 0x100000 + bankoffset[data];
m_bankdev->neogeo_set_main_cpu_bank_address(bankaddress);
}
-WRITE16_MEMBER( sma_prot_device::garou_bankswitch_w )
+void sma_prot_device::garou_bankswitch_w(uint16_t data)
{
int bankaddress;
static const int bankoffset[64] =
@@ -85,20 +79,14 @@ WRITE16_MEMBER( sma_prot_device::garou_bankswitch_w )
};
// unscramble bank number
- data =
- (BIT(data, 5) << 0)+
- (BIT(data, 9) << 1)+
- (BIT(data, 7) << 2)+
- (BIT(data, 6) << 3)+
- (BIT(data, 14) << 4)+
- (BIT(data, 12) << 5);
+ data = bitswap<6>(data, 12, 14, 6, 7, 9, 5);
bankaddress = 0x100000 + bankoffset[data];
m_bankdev->neogeo_set_main_cpu_bank_address(bankaddress);
}
-WRITE16_MEMBER( sma_prot_device::garouh_bankswitch_w )
+void sma_prot_device::garouh_bankswitch_w(uint16_t data)
{
int bankaddress;
static const int bankoffset[64] =
@@ -122,20 +110,14 @@ WRITE16_MEMBER( sma_prot_device::garouh_bankswitch_w )
};
// unscramble bank number
- data =
- (BIT(data, 4) << 0)+
- (BIT(data, 8) << 1)+
- (BIT(data, 14) << 2)+
- (BIT(data, 2) << 3)+
- (BIT(data, 11) << 4)+
- (BIT(data, 13) << 5);
+ data = bitswap<6>(data, 13, 11, 2, 14, 8, 4);
bankaddress = 0x100000 + bankoffset[data];
m_bankdev->neogeo_set_main_cpu_bank_address(bankaddress);
}
-WRITE16_MEMBER( sma_prot_device::mslug3_bankswitch_w )
+void sma_prot_device::mslug3_bankswitch_w(uint16_t data)
{
int bankaddress;
static const int bankoffset[64] =
@@ -156,20 +138,14 @@ WRITE16_MEMBER( sma_prot_device::mslug3_bankswitch_w )
};
// unscramble bank number
- data =
- (BIT(data, 14) << 0)+
- (BIT(data, 12) << 1)+
- (BIT(data, 15) << 2)+
- (BIT(data, 6) << 3)+
- (BIT(data, 3) << 4)+
- (BIT(data, 9) << 5);
+ data = bitswap<6>(data, 9, 3, 6, 15, 12, 14);
bankaddress = 0x100000 + bankoffset[data];
m_bankdev->neogeo_set_main_cpu_bank_address(bankaddress);
}
-WRITE16_MEMBER( sma_prot_device::kof2000_bankswitch_w )
+void sma_prot_device::kof2000_bankswitch_w(uint16_t data)
{
int bankaddress;
static const int bankoffset[64] =
@@ -186,13 +162,7 @@ WRITE16_MEMBER( sma_prot_device::kof2000_bankswitch_w )
};
// unscramble bank number
- data =
- (BIT(data, 15) << 0)+
- (BIT(data, 14) << 1)+
- (BIT(data, 7) << 2)+
- (BIT(data, 3) << 3)+
- (BIT(data, 10) << 4)+
- (BIT(data, 5) << 5);
+ data = bitswap<6>(data, 5, 10, 3, 7, 14, 15);
bankaddress = 0x100000 + bankoffset[data];
m_bankdev->neogeo_set_main_cpu_bank_address(bankaddress);
@@ -215,13 +185,7 @@ uint32_t sma_prot_device::kof99_bank_base(uint16_t sel)
};
/* unscramble bank number */
- int data =
- (BIT(sel, 14) << 0)+
- (BIT(sel, 6) << 1)+
- (BIT(sel, 8) << 2)+
- (BIT(sel, 10) << 3)+
- (BIT(sel, 12) << 4)+
- (BIT(sel, 5) << 5);
+ int data = bitswap<6>(sel, 5, 12, 10, 8, 6, 14);
int bankaddress = 0x100000 + bankoffset[data];
return bankaddress;
@@ -248,13 +212,7 @@ uint32_t sma_prot_device::garou_bank_base(uint16_t sel)
};
// unscramble bank number
- int data =
- (BIT(sel, 5) << 0)+
- (BIT(sel, 9) << 1)+
- (BIT(sel, 7) << 2)+
- (BIT(sel, 6) << 3)+
- (BIT(sel, 14) << 4)+
- (BIT(sel, 12) << 5);
+ int data = bitswap<6>(sel, 12, 14, 6, 7, 9, 5);
int bankaddress = 0x100000 + bankoffset[data];
return bankaddress;
@@ -283,13 +241,7 @@ uint32_t sma_prot_device::garouh_bank_base(uint16_t sel)
};
// unscramble bank number
- int data =
- (BIT(sel, 4) << 0)+
- (BIT(sel, 8) << 1)+
- (BIT(sel, 14) << 2)+
- (BIT(sel, 2) << 3)+
- (BIT(sel, 11) << 4)+
- (BIT(sel, 13) << 5);
+ int data = bitswap<6>(sel, 13, 11, 2, 14, 8, 4);
int bankaddress = 0x100000 + bankoffset[data];
return bankaddress;
@@ -315,13 +267,7 @@ uint32_t sma_prot_device::mslug3_bank_base(uint16_t sel)
};
// unscramble bank number
- int data =
- (BIT(sel, 14) << 0)+
- (BIT(sel, 12) << 1)+
- (BIT(sel, 15) << 2)+
- (BIT(sel, 6) << 3)+
- (BIT(sel, 3) << 4)+
- (BIT(sel, 9) << 5);
+ int data = bitswap<6>(sel, 9, 3, 6, 15, 12, 14);
int bankaddress = 0x100000 + bankoffset[data];
return bankaddress;
@@ -347,13 +293,7 @@ uint32_t sma_prot_device::mslug3a_bank_base(uint16_t sel)
};
// unscramble bank number
- int data =
- (BIT(sel, 15) << 0)+
- (BIT(sel, 3) << 1)+
- (BIT(sel, 1) << 2)+
- (BIT(sel, 6) << 3)+
- (BIT(sel, 12) << 4)+
- (BIT(sel, 11) << 5);
+ int data = bitswap<6>(sel, 11, 12, 6, 1, 3, 15);
int bankaddress = 0x100000 + bankoffset[data];
return bankaddress;
@@ -375,13 +315,7 @@ uint32_t sma_prot_device::kof2000_bank_base(uint16_t sel)
};
// unscramble bank number
- int data =
- (BIT(sel, 15) << 0)+
- (BIT(sel, 14) << 1)+
- (BIT(sel, 7) << 2)+
- (BIT(sel, 3) << 3)+
- (BIT(sel, 10) << 4)+
- (BIT(sel, 5) << 5);
+ int data = bitswap<6>(sel, 5, 10, 3, 7, 14, 15);
int bankaddress = 0x100000 + bankoffset[data];
return bankaddress;
@@ -389,7 +323,7 @@ uint32_t sma_prot_device::kof2000_bank_base(uint16_t sel)
-READ16_MEMBER( sma_prot_device::prot_9a37_r )
+uint16_t sma_prot_device::prot_9a37_r()
{
return 0x9a37;
}
@@ -398,7 +332,7 @@ READ16_MEMBER( sma_prot_device::prot_9a37_r )
/* information about the sma random number generator provided by razoola */
/* this RNG is correct for KOF99, other games might be different */
-READ16_MEMBER( sma_prot_device::random_r )
+uint16_t sma_prot_device::random_r()
{
uint16_t old = m_sma_rng;
uint16_t newbit = ((m_sma_rng >> 2) ^
@@ -431,13 +365,13 @@ void sma_prot_device::kof99_decrypt_68k(uint8_t* base)
uint16_t buffer[0x800/2];
memcpy(buffer, &rom[i], 0x800);
for (int j = 0; j < 0x800/2; j++)
- rom[i+j] = buffer[bitswap<24>(j,23,22,21,20,19,18,17,16,15,14,13,12,11,10,6,2,4,9,8,3,1,7,0,5)];
+ rom[i+j] = buffer[bitswap<10>(j,6,2,4,9,8,3,1,7,0,5)];
}
// swap address lines & relocate fixed part
rom = (uint16_t *)base;
for (int i = 0; i < 0x0c0000/2; i++)
- rom[i] = rom[0x700000/2 + bitswap<24>(i,23,22,21,20,19,18,11,6,14,17,16,5,8,10,12,0,4,3,2,7,9,15,13,1)];
+ rom[i] = rom[0x700000/2 + bitswap<19>(i,18,11,6,14,17,16,5,8,10,12,0,4,3,2,7,9,15,13,1)];
}
@@ -452,7 +386,7 @@ void sma_prot_device::garou_decrypt_68k(uint8_t* base)
// swap address lines & relocate fixed part
rom = (uint16_t *)base;
for (int i = 0; i < 0x0c0000/2; i++)
- rom[i] = rom[0x710000/2 + bitswap<24>(i,23,22,21,20,19,18,4,5,16,14,7,9,6,13,17,15,3,1,2,12,11,8,10,0)];
+ rom[i] = rom[0x710000/2 + bitswap<19>(i,18,4,5,16,14,7,9,6,13,17,15,3,1,2,12,11,8,10,0)];
// swap address lines for the banked part
rom = (uint16_t *)(base + 0x100000);
@@ -461,7 +395,7 @@ void sma_prot_device::garou_decrypt_68k(uint8_t* base)
uint16_t buffer[0x8000/2];
memcpy(buffer, &rom[i], 0x8000);
for (int j = 0; j < 0x8000/2; j++)
- rom[i+j] = buffer[bitswap<24>(j,23,22,21,20,19,18,17,16,15,14,9,4,8,3,13,6,2,7,0,12,1,11,10,5)];
+ rom[i+j] = buffer[bitswap<14>(j,9,4,8,3,13,6,2,7,0,12,1,11,10,5)];
}
}
@@ -477,7 +411,7 @@ void sma_prot_device::garouh_decrypt_68k(uint8_t* base)
// swap address lines & relocate fixed part
rom = (uint16_t *)base;
for (int i = 0; i < 0x0c0000/2; i++)
- rom[i] = rom[0x7f8000/2 + bitswap<24>(i,23,22,21,20,19,18,5,16,11,2,6,7,17,3,12,8,14,4,0,9,1,10,15,13)];
+ rom[i] = rom[0x7f8000/2 + bitswap<19>(i,18,5,16,11,2,6,7,17,3,12,8,14,4,0,9,1,10,15,13)];
// swap address lines for the banked part
rom = (uint16_t *)(base + 0x100000);
@@ -486,7 +420,7 @@ void sma_prot_device::garouh_decrypt_68k(uint8_t* base)
uint16_t buffer[0x8000/2];
memcpy(buffer, &rom[i], 0x8000);
for (int j = 0; j < 0x8000/2; j++)
- rom[i+j] = buffer[bitswap<24>(j,23,22,21,20,19,18,17,16,15,14,12,8,1,7,11,3,13,10,6,9,5,4,0,2)];
+ rom[i+j] = buffer[bitswap<14>(j,12,8,1,7,11,3,13,10,6,9,5,4,0,2)];
}
}
@@ -502,7 +436,7 @@ void sma_prot_device::mslug3_decrypt_68k(uint8_t* base)
// swap address lines & relocate fixed part
rom = (uint16_t *)base;
for (int i = 0; i < 0x0c0000/2; i++)
- rom[i] = rom[0x5d0000/2 + bitswap<24>(i,23,22,21,20,19,18,15,2,1,13,3,0,9,6,16,4,11,5,7,12,17,14,10,8)];
+ rom[i] = rom[0x5d0000/2 + bitswap<19>(i,18,15,2,1,13,3,0,9,6,16,4,11,5,7,12,17,14,10,8)];
// swap address lines for the banked part
rom = (uint16_t *)(base + 0x100000);
@@ -511,7 +445,7 @@ void sma_prot_device::mslug3_decrypt_68k(uint8_t* base)
uint16_t buffer[0x10000/2];
memcpy(buffer, &rom[i], 0x10000);
for (int j = 0; j < 0x10000/2; j++)
- rom[i+j] = buffer[bitswap<24>(j,23,22,21,20,19,18,17,16,15,2,11,0,14,6,4,13,8,9,3,10,7,5,12,1)];
+ rom[i+j] = buffer[bitswap<15>(j,2,11,0,14,6,4,13,8,9,3,10,7,5,12,1)];
}
}
@@ -526,7 +460,7 @@ void sma_prot_device::mslug3a_decrypt_68k(uint8_t* base)
/* swap address lines & relocate fixed part */
rom = (uint16_t *)base;
for (int i = 0; i < 0x0c0000/2; i++)
- rom[i] = rom[0x5d0000/2 + bitswap<24>(i,23,22,21,20,19,18,1,16,14,7,17,5,8,4,15,6,3,2,0,13,10,12,9,11)];
+ rom[i] = rom[0x5d0000/2 + bitswap<19>(i,18,1,16,14,7,17,5,8,4,15,6,3,2,0,13,10,12,9,11)];
rom = (uint16_t *)(base + 0x100000);
/* swap address lines for the banked part */
@@ -535,7 +469,7 @@ void sma_prot_device::mslug3a_decrypt_68k(uint8_t* base)
uint16_t buffer[0x10000/2];
memcpy(buffer,&rom[i],0x10000);
for (int j = 0;j < 0x10000/2;j++)
- rom[i+j] = buffer[bitswap<24>(j,23,22,21,20,19,18,17,16,15,12,0,11,3,4,13,6,8,14,7,5,2,10,9,1)];
+ rom[i+j] = buffer[bitswap<15>(j,12,0,11,3,4,13,6,8,14,7,5,2,10,9,1)];
}
}
@@ -554,11 +488,11 @@ void sma_prot_device::kof2000_decrypt_68k(uint8_t* base)
uint16_t buffer[0x800/2];
memcpy(buffer, &rom[i], 0x800);
for (int j = 0; j < 0x800/2; j++)
- rom[i+j] = buffer[bitswap<24>(j,23,22,21,20,19,18,17,16,15,14,13,12,11,10,4,1,3,8,6,2,7,0,9,5)];
+ rom[i+j] = buffer[bitswap<10>(j,4,1,3,8,6,2,7,0,9,5)];
}
// swap address lines & relocate fixed part
rom = (uint16_t *)base;
for (int i = 0; i < 0x0c0000/2; i++)
- rom[i] = rom[0x73a000/2 + bitswap<24>(i,23,22,21,20,19,18,8,4,15,13,3,14,16,2,6,17,7,12,10,0,5,11,1,9)];
+ rom[i] = rom[0x73a000/2 + bitswap<19>(i,18,8,4,15,13,3,14,16,2,6,17,7,12,10,0,5,11,1,9)];
}
diff --git a/src/devices/bus/neogeo/prot_sma.h b/src/devices/bus/neogeo/prot_sma.h
index c36af941132..9dcfb3e2d63 100644
--- a/src/devices/bus/neogeo/prot_sma.h
+++ b/src/devices/bus/neogeo/prot_sma.h
@@ -16,13 +16,13 @@ public:
// construction/destruction
sma_prot_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock = 0);
- //DECLARE_WRITE16_MEMBER( kof99_bankswitch_w );
- //DECLARE_WRITE16_MEMBER( garou_bankswitch_w );
- //DECLARE_WRITE16_MEMBER( garouh_bankswitch_w );
- //DECLARE_WRITE16_MEMBER( mslug3_bankswitch_w );
- //DECLARE_WRITE16_MEMBER( kof2000_bankswitch_w );
- DECLARE_READ16_MEMBER( prot_9a37_r );
- DECLARE_READ16_MEMBER( random_r );
+ //void kof99_bankswitch_w(uint16_t data);
+ //void garou_bankswitch_w(uint16_t data);
+ //void garouh_bankswitch_w(uint16_t data);
+ //void mslug3_bankswitch_w(uint16_t data);
+ //void kof2000_bankswitch_w(uint16_t data);
+ uint16_t prot_9a37_r();
+ uint16_t random_r();
uint32_t kof99_bank_base(uint16_t sel);
uint32_t garou_bank_base(uint16_t sel);
uint32_t garouh_bank_base(uint16_t sel);
@@ -37,8 +37,8 @@ public:
void kof2000_decrypt_68k(uint8_t* base);
protected:
- virtual void device_start() override;
- virtual void device_reset() override;
+ virtual void device_start() override ATTR_COLD;
+ virtual void device_reset() override ATTR_COLD;
private:
uint16_t m_sma_rng;
diff --git a/src/devices/bus/neogeo/pvc.h b/src/devices/bus/neogeo/pvc.h
index 0b3f9c6ce75..e1fc3265c94 100644
--- a/src/devices/bus/neogeo/pvc.h
+++ b/src/devices/bus/neogeo/pvc.h
@@ -21,8 +21,8 @@ public:
// reading and writing
virtual uint32_t get_bank_base(uint16_t sel) override { return m_pvc_prot->get_bank_base(); }
- virtual DECLARE_READ16_MEMBER(protection_r) override { return m_pvc_prot->protection_r(space, offset, mem_mask); }
- virtual DECLARE_WRITE16_MEMBER(protection_w) override { m_pvc_prot->protection_w(space, offset, data, mem_mask); }
+ virtual uint16_t protection_r(address_space &space, offs_t offset) override { return m_pvc_prot->protection_r(offset); }
+ virtual void protection_w(offs_t offset, uint16_t data, uint16_t mem_mask = ~0) override { m_pvc_prot->protection_w(offset, data, mem_mask); }
virtual void decrypt_all(DECRYPT_ALL_PARAMS) override { }
virtual int get_fixed_bank_type() override { return 0; }
@@ -31,10 +31,10 @@ protected:
neogeo_pvc_cart_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint16_t clock);
// device-level overrides
- virtual void device_start() override;
- virtual void device_reset() override;
+ virtual void device_start() override ATTR_COLD;
+ virtual void device_reset() override ATTR_COLD;
- virtual void device_add_mconfig(machine_config &config) override;
+ virtual void device_add_mconfig(machine_config &config) override ATTR_COLD;
required_device<cmc_prot_device> m_cmc_prot;
required_device<pcm2_prot_device> m_pcm2_prot;
diff --git a/src/devices/bus/neogeo/rom.cpp b/src/devices/bus/neogeo/rom.cpp
index 0f54a808cef..290ea9f3a5d 100644
--- a/src/devices/bus/neogeo/rom.cpp
+++ b/src/devices/bus/neogeo/rom.cpp
@@ -49,7 +49,7 @@ void neogeo_rom_device::device_reset()
mapper specific handlers
-------------------------------------------------*/
-READ16_MEMBER(neogeo_rom_device::rom_r)
+uint16_t neogeo_rom_device::rom_r(offs_t offset)
{
// to speed up access to ROM, the access to ROM are actually replaced in the driver
// by accesses to the maincpu rom region, where we have anyway copied the rom content
@@ -58,7 +58,7 @@ READ16_MEMBER(neogeo_rom_device::rom_r)
}
-WRITE16_MEMBER(neogeo_rom_device::banksel_w)
+void neogeo_rom_device::banksel_w(uint16_t data)
{
// to speed up access to ROM, the banking is taken care of at driver level
// by mapping higher banks to the corresponding offset in maincpu rom region
diff --git a/src/devices/bus/neogeo/rom.h b/src/devices/bus/neogeo/rom.h
index 1f62a890859..136c9f2e2ce 100644
--- a/src/devices/bus/neogeo/rom.h
+++ b/src/devices/bus/neogeo/rom.h
@@ -17,15 +17,15 @@ public:
neogeo_rom_device(const machine_config &mconfig, const char *tag, device_t *owner, uint16_t clock);
// reading and writing
- virtual DECLARE_READ16_MEMBER(rom_r) override;
- virtual DECLARE_WRITE16_MEMBER(banksel_w) override;
+ virtual uint16_t rom_r(offs_t offset) override;
+ virtual void banksel_w(uint16_t data) override;
protected:
neogeo_rom_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint16_t clock);
// device-level overrides
- virtual void device_start() override;
- virtual void device_reset() override;
+ virtual void device_start() override ATTR_COLD;
+ virtual void device_reset() override ATTR_COLD;
};
@@ -44,15 +44,15 @@ class neogeo_vliner_cart_device : public neogeo_rom_device
public:
neogeo_vliner_cart_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
- virtual DECLARE_READ16_MEMBER(ram_r) override { return m_cart_ram[offset]; }
- virtual DECLARE_WRITE16_MEMBER(ram_w) override { COMBINE_DATA(&m_cart_ram[offset]); }
+ virtual uint16_t ram_r(offs_t offset) override { return m_cart_ram[offset]; }
+ virtual void ram_w(offs_t offset, uint16_t data, uint16_t mem_mask = ~0) override { COMBINE_DATA(&m_cart_ram[offset]); }
virtual int get_fixed_bank_type() override { return 0; }
protected:
- virtual void device_start() override;
+ virtual void device_start() override ATTR_COLD;
- virtual void device_add_mconfig(machine_config &config) override;
+ virtual void device_add_mconfig(machine_config &config) override ATTR_COLD;
private:
std::unique_ptr<uint16_t[]> m_cart_ram;
diff --git a/src/devices/bus/neogeo/sbp.cpp b/src/devices/bus/neogeo/sbp.cpp
index 6b6920cb5e8..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
+//-------------------------------------------------
-READ16_MEMBER( neogeo_sbp_cart_device::protection_r )
+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);
@@ -49,13 +61,12 @@ READ16_MEMBER( neogeo_sbp_cart_device::protection_r )
}
-WRITE16_MEMBER( neogeo_sbp_cart_device::protection_w )
+void neogeo_sbp_cart_device::protection_w(offs_t offset, uint16_t data, uint16_t mem_mask)
{
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 @@ WRITE16_MEMBER( neogeo_sbp_cart_device::protection_w )
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/sbp.h b/src/devices/bus/neogeo/sbp.h
index 455c7892399..f9d91e972f7 100644
--- a/src/devices/bus/neogeo/sbp.h
+++ b/src/devices/bus/neogeo/sbp.h
@@ -17,15 +17,15 @@ class neogeo_sbp_cart_device : public neogeo_rom_device
public:
neogeo_sbp_cart_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
- virtual DECLARE_WRITE16_MEMBER(protection_w) override;
- virtual DECLARE_READ16_MEMBER(protection_r) override;
+ virtual void protection_w(offs_t offset, uint16_t data, uint16_t mem_mask = ~0) override;
+ virtual uint16_t protection_r(address_space &space, offs_t offset) override;
virtual void decrypt_all(DECRYPT_ALL_PARAMS) override;
virtual int get_fixed_bank_type() override { return 0; }
protected:
- virtual void device_start() override;
- virtual void device_reset() override;
+ virtual void device_start() override ATTR_COLD;
+ virtual void device_reset() override ATTR_COLD;
void patch(uint8_t* cpurom, uint32_t cpurom_size);
};
diff --git a/src/devices/bus/neogeo/slot.cpp b/src/devices/bus/neogeo/slot.cpp
index 9a01c1b1196..ce8fd3acf6e 100644
--- a/src/devices/bus/neogeo/slot.cpp
+++ b/src/devices/bus/neogeo/slot.cpp
@@ -20,15 +20,15 @@ DEFINE_DEVICE_TYPE(NEOGEO_CART_SLOT, neogeo_cart_slot_device, "neogeo_cart_slot"
// device_neogeo_cart_interface - constructor
//-------------------------------------------------
-device_neogeo_cart_interface::device_neogeo_cart_interface(const machine_config &mconfig, device_t &device)
- : device_slot_card_interface(mconfig, device),
+device_neogeo_cart_interface::device_neogeo_cart_interface(const machine_config &mconfig, device_t &device) :
+ device_interface(device, "neogeocart"),
m_region_rom(*this, "^maincpu"),
m_region_fixed(*this, "^fixed"),
m_region_audio(*this, "^audiocpu"),
m_region_audiocrypt(*this, "^audiocrypt"),
m_region_spr(*this, "^sprites"),
- m_region_ym(*this, "^ymsnd"),
- m_region_ymd(*this, "^ymsnd.deltat")
+ m_region_ym(*this, "^ymsnd:adpcma"),
+ m_region_ymd(*this, "^ymsnd:adpcmb")
{
}
@@ -99,8 +99,8 @@ void device_neogeo_cart_interface::optimize_sprites(uint8_t* region_sprites, uin
//-------------------------------------------------
neogeo_cart_slot_device::neogeo_cart_slot_device(const machine_config &mconfig, const char *tag, device_t *owner, uint16_t clock) :
device_t(mconfig, NEOGEO_CART_SLOT, tag, owner, clock),
- device_image_interface(mconfig, *this),
- device_slot_interface(mconfig, *this),
+ device_cartrom_image_interface(mconfig, *this),
+ device_single_card_slot_interface<device_neogeo_cart_interface>(mconfig, *this),
m_cart(nullptr)
{
}
@@ -196,6 +196,7 @@ static const neogeo_slot slot_list[] =
{ NEOGEO_SAMSHO5B, "boot_samsho5b" },
{ NEOGEO_MSLUG3B6, "boot_mslug3b6" },
{ NEOGEO_MSLUG5P, "boot_ms5plus" },
+ { NEOGEO_MSLUG5B, "boot_mslug5b" },
{ NEOGEO_KOG, "boot_kog" },
{ NEOGEO_SBP, "boot_sbp" },
{ NEOGEO_KOF10TH, "boot_kf10th" },
@@ -206,7 +207,7 @@ static int neogeo_get_pcb_id(const char *slot)
{
for (auto & elem : slot_list)
{
- if (!core_stricmp(elem.slot_option, slot))
+ if (!strcmp(elem.slot_option, slot))
return elem.pcb_id;
}
@@ -223,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)
{
@@ -258,17 +258,17 @@ image_init_result neogeo_cart_slot_device::call_load()
memcpy(ROM8 + 0x10000, get_software_region("audiocpu"), len); // avoid reloading in XML, should just improve banking instead tho?
}
- len = get_software_region_length("ymsnd");
+ len = get_software_region_length("ymsnd:adpcma");
m_cart->ym_alloc(len);
ROM8 = m_cart->get_ym_base();
- memcpy(ROM8, get_software_region("ymsnd"), len);
+ memcpy(ROM8, get_software_region("ymsnd:adpcma"), len);
- if (get_software_region("ymsnd.deltat") != nullptr)
+ if (get_software_region("ymsnd:adpcmb") != nullptr)
{
- len = get_software_region_length("ymsnd.deltat");
+ len = get_software_region_length("ymsnd:adpcmb");
m_cart->ymdelta_alloc(len);
ROM8 = m_cart->get_ymdelta_base();
- memcpy(ROM8, get_software_region("ymsnd.deltat"), len);
+ memcpy(ROM8, get_software_region("ymsnd:adpcmb"), len);
}
else
{
@@ -303,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());
}
@@ -333,10 +331,10 @@ std::string neogeo_cart_slot_device::get_default_card_software(get_default_card_
rom_r
-------------------------------------------------*/
-READ16_MEMBER(neogeo_cart_slot_device::rom_r)
+uint16_t neogeo_cart_slot_device::rom_r(offs_t offset)
{
if (m_cart)
- return m_cart->rom_r(space, offset, mem_mask);
+ return m_cart->rom_r(offset);
else
return 0xffff;
}
@@ -345,20 +343,20 @@ READ16_MEMBER(neogeo_cart_slot_device::rom_r)
write_banksel
-------------------------------------------------*/
-WRITE16_MEMBER(neogeo_cart_slot_device::banksel_w)
+void neogeo_cart_slot_device::banksel_w(uint16_t data)
{
if (m_cart)
- m_cart->banksel_w(space, offset, data, mem_mask);
+ m_cart->banksel_w(data);
}
/*-------------------------------------------------
ram_r
-------------------------------------------------*/
-READ16_MEMBER(neogeo_cart_slot_device::ram_r)
+uint16_t neogeo_cart_slot_device::ram_r(offs_t offset)
{
if (m_cart)
- return m_cart->ram_r(space, offset, mem_mask);
+ return m_cart->ram_r(offset);
else
return 0xffff;
}
@@ -367,20 +365,20 @@ READ16_MEMBER(neogeo_cart_slot_device::ram_r)
ram_w
-------------------------------------------------*/
-WRITE16_MEMBER(neogeo_cart_slot_device::ram_w)
+void neogeo_cart_slot_device::ram_w(offs_t offset, uint16_t data, uint16_t mem_mask)
{
if (m_cart)
- m_cart->ram_w(space, offset, data, mem_mask);
+ m_cart->ram_w(offset, data, mem_mask);
}
/*-------------------------------------------------
addon_r
-------------------------------------------------*/
-READ16_MEMBER(neogeo_cart_slot_device::addon_r)
+uint16_t neogeo_cart_slot_device::addon_r(offs_t offset)
{
if (m_cart)
- return m_cart->addon_r(space, offset, mem_mask);
+ return m_cart->addon_r(offset);
else
return 0xffff;
}
@@ -389,10 +387,10 @@ READ16_MEMBER(neogeo_cart_slot_device::addon_r)
protection_r
-------------------------------------------------*/
-READ16_MEMBER(neogeo_cart_slot_device::protection_r)
+uint16_t neogeo_cart_slot_device::protection_r(address_space &space, offs_t offset)
{
if (m_cart)
- return m_cart->protection_r(space, offset, mem_mask);
+ return m_cart->protection_r(space, offset);
else
return 0xffff;
}
@@ -401,8 +399,8 @@ READ16_MEMBER(neogeo_cart_slot_device::protection_r)
protection_w
-------------------------------------------------*/
-WRITE16_MEMBER(neogeo_cart_slot_device::protection_w)
+void neogeo_cart_slot_device::protection_w(offs_t offset, uint16_t data, uint16_t mem_mask)
{
if (m_cart)
- m_cart->protection_w(space, offset, data, mem_mask);
+ m_cart->protection_w(offset, data, mem_mask);
}
diff --git a/src/devices/bus/neogeo/slot.h b/src/devices/bus/neogeo/slot.h
index b5be4c5e901..300a9243b0f 100644
--- a/src/devices/bus/neogeo/slot.h
+++ b/src/devices/bus/neogeo/slot.h
@@ -5,7 +5,7 @@
#pragma once
-#include "softlist_dev.h"
+#include "imagedev/cartrom.h"
/* PCB */
@@ -68,6 +68,7 @@ enum
NEOGEO_SAMSHO5B,
NEOGEO_MSLUG3B6,
NEOGEO_MSLUG5P,
+ NEOGEO_MSLUG5B,
NEOGEO_KOG,
NEOGEO_SBP,
NEOGEO_KOF10TH,
@@ -85,25 +86,25 @@ enum
#define DECRYPT_ALL_PARAMS \
uint8_t* cpuregion, uint32_t cpuregion_size,uint8_t* spr_region, uint32_t spr_region_size,uint8_t* fix_region, uint32_t fix_region_size,uint8_t* ym_region, uint32_t ym_region_size,uint8_t* ymdelta_region, uint32_t ymdelta_region_size,uint8_t* audiocpu_region, uint32_t audio_region_size, uint8_t* audiocrypt_region, uint32_t audiocrypt_region_size
-class device_neogeo_cart_interface : public device_slot_card_interface
+class device_neogeo_cart_interface : public device_interface
{
public:
// construction/destruction
virtual ~device_neogeo_cart_interface();
// reading from ROM
- virtual DECLARE_READ16_MEMBER(rom_r) { return 0xffff; }
- virtual DECLARE_WRITE16_MEMBER(banksel_w) { };
- virtual DECLARE_READ16_MEMBER(ram_r) { return 0xffff; }
- virtual DECLARE_WRITE16_MEMBER(ram_w) { };
- virtual DECLARE_READ16_MEMBER(protection_r) { return 0xffff; }
- virtual DECLARE_WRITE16_MEMBER(protection_w) { };
- virtual DECLARE_READ16_MEMBER(addon_r) { return 0xffff; }
+ virtual uint16_t rom_r(offs_t offset) { return 0xffff; }
+ virtual void banksel_w(uint16_t data) { }
+ virtual uint16_t ram_r(offs_t offset) { return 0xffff; }
+ virtual void ram_w(offs_t offset, uint16_t data, uint16_t mem_mask = ~0) { }
+ virtual uint16_t protection_r(address_space &space, offs_t offset) { return 0xffff; }
+ virtual void protection_w(offs_t offset, uint16_t data, uint16_t mem_mask = ~0) { }
+ virtual uint16_t addon_r(offs_t offset) { return 0xffff; }
virtual uint32_t get_bank_base(uint16_t sel) { return 0; }
virtual uint32_t get_special_bank() { return 0; }
virtual uint16_t get_helper() { return 0; }
- virtual void decrypt_all(DECRYPT_ALL_PARAMS) { };
+ virtual void decrypt_all(DECRYPT_ALL_PARAMS) { }
virtual int get_fixed_bank_type() { return 0; }
void rom_alloc(uint32_t size) { m_rom.resize(size/sizeof(uint16_t)); }
@@ -185,8 +186,8 @@ protected:
// ======================> neogeo_cart_slot_device
class neogeo_cart_slot_device : public device_t,
- public device_image_interface,
- public device_slot_interface
+ public device_cartrom_image_interface,
+ public device_single_card_slot_interface<device_neogeo_cart_interface>
{
public:
// construction/destruction
@@ -202,31 +203,25 @@ 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 const software_list_loader &get_software_list_loader() const override { return rom_software_list_loader::instance(); }
-
- virtual iodevice_t image_type() const override { return IO_CARTSLOT; }
- virtual bool is_readable() const override { return 1; }
- virtual bool is_writeable() const override { return 0; }
- virtual bool is_creatable() const override { return 0; }
- virtual bool must_be_loaded() const override { return 0; }
- virtual bool is_reset_on_load() const override { return 1; }
- virtual const char *image_interface() const override { return "neo_cart"; }
- virtual const char *file_extensions() const override { return "bin"; }
-
- // slot interface overrides
+
+ 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"; }
+
+ // device_slot_interface implementation
virtual std::string get_default_card_software(get_default_card_software_hook &hook) const override;
// reading and writing
- DECLARE_READ16_MEMBER(rom_r);
- DECLARE_WRITE16_MEMBER(banksel_w);
- DECLARE_READ16_MEMBER(ram_r);
- DECLARE_WRITE16_MEMBER(ram_w);
- DECLARE_READ16_MEMBER(protection_r);
- DECLARE_WRITE16_MEMBER(protection_w);
- DECLARE_READ16_MEMBER(addon_r);
+ uint16_t rom_r(offs_t offset);
+ void banksel_w(uint16_t data);
+ uint16_t ram_r(offs_t offset);
+ void ram_w(offs_t offset, uint16_t data, uint16_t mem_mask = ~0);
+ uint16_t protection_r(address_space &space, offs_t offset);
+ void protection_w(offs_t offset, uint16_t data, uint16_t mem_mask = ~0);
+ uint16_t addon_r(offs_t offset);
void set_cart_type(const char *slot);
int get_type() { return m_type; }
@@ -333,10 +328,9 @@ public:
get_audio_base(), get_audio_size(),
get_audiocrypt_base(), get_audiocrypt_size()); }
-
protected:
- // device-level overrides
- virtual void device_start() override;
+ // device_t implementation
+ virtual void device_start() override ATTR_COLD;
private:
int m_type;
diff --git a/src/devices/bus/neogeo/sma.h b/src/devices/bus/neogeo/sma.h
index b4b72b3b5b5..5cbde9893b8 100644
--- a/src/devices/bus/neogeo/sma.h
+++ b/src/devices/bus/neogeo/sma.h
@@ -17,8 +17,8 @@ public:
neogeo_sma_cart_device(const machine_config &mconfig, const char *tag, device_t *owner, uint16_t clock);
// reading and writing
- virtual DECLARE_READ16_MEMBER(protection_r) override { return m_sma_prot->prot_9a37_r(space, offset, mem_mask); }
- virtual DECLARE_READ16_MEMBER(addon_r) override { return m_sma_prot->random_r(space, offset, mem_mask); }
+ virtual uint16_t protection_r(address_space &space, offs_t offset) override { return m_sma_prot->prot_9a37_r(); }
+ virtual uint16_t addon_r(offs_t offset) override { return m_sma_prot->random_r(); }
virtual uint32_t get_bank_base(uint16_t sel) override { return 0; }
virtual void decrypt_all(DECRYPT_ALL_PARAMS) override {}
@@ -28,10 +28,10 @@ protected:
neogeo_sma_cart_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint16_t clock);
// device-level overrides
- virtual void device_start() override;
- virtual void device_reset() override;
+ virtual void device_start() override ATTR_COLD;
+ virtual void device_reset() override ATTR_COLD;
- virtual void device_add_mconfig(machine_config &config) override;
+ virtual void device_add_mconfig(machine_config &config) override ATTR_COLD;
required_device<sma_prot_device> m_sma_prot;
required_device<cmc_prot_device> m_cmc_prot;
diff --git a/src/devices/bus/neogeo_ctrl/ctrl.cpp b/src/devices/bus/neogeo_ctrl/ctrl.cpp
index 023d28adaf8..93ff26640f8 100644
--- a/src/devices/bus/neogeo_ctrl/ctrl.cpp
+++ b/src/devices/bus/neogeo_ctrl/ctrl.cpp
@@ -43,8 +43,8 @@ DEFINE_DEVICE_TYPE(NEOGEO_CTRL_EDGE_CONNECTOR, neogeo_ctrl_edge_port_device, "ne
// device_neogeo_control_port_interface - constructor
//-------------------------------------------------
-device_neogeo_control_port_interface::device_neogeo_control_port_interface(const machine_config &mconfig, device_t &device)
- : device_slot_card_interface(mconfig,device)
+device_neogeo_control_port_interface::device_neogeo_control_port_interface(const machine_config &mconfig, device_t &device) :
+ device_interface(device, "neogeoctrl")
{
m_port = dynamic_cast<neogeo_control_port_device *>(device.owner());
}
@@ -62,8 +62,8 @@ device_neogeo_control_port_interface::~device_neogeo_control_port_interface()
// device_neogeo_ctrl_edge_interface - constructor
//-------------------------------------------------
-device_neogeo_ctrl_edge_interface::device_neogeo_ctrl_edge_interface(const machine_config &mconfig, device_t &device)
- : device_slot_card_interface(mconfig,device)
+device_neogeo_ctrl_edge_interface::device_neogeo_ctrl_edge_interface(const machine_config &mconfig, device_t &device) :
+ device_interface(device, "neogeoedge")
{
m_port = dynamic_cast<neogeo_ctrl_edge_port_device *>(device.owner());
}
@@ -88,7 +88,7 @@ device_neogeo_ctrl_edge_interface::~device_neogeo_ctrl_edge_interface()
neogeo_control_port_device::neogeo_control_port_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) :
device_t(mconfig, NEOGEO_CONTROL_PORT, tag, owner, clock),
- device_slot_interface(mconfig, *this),
+ device_single_card_slot_interface<device_neogeo_control_port_interface>(mconfig, *this),
m_device(nullptr)
{
}
@@ -109,7 +109,7 @@ neogeo_control_port_device::~neogeo_control_port_device()
void neogeo_control_port_device::device_start()
{
- m_device = dynamic_cast<device_neogeo_control_port_interface *>(get_card_device());
+ m_device = get_card_device();
}
@@ -137,7 +137,7 @@ void neogeo_control_port_device::write_ctrlsel(uint8_t data)
neogeo_ctrl_edge_port_device::neogeo_ctrl_edge_port_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) :
device_t(mconfig, NEOGEO_CTRL_EDGE_CONNECTOR, tag, owner, clock),
- device_slot_interface(mconfig, *this),
+ device_single_card_slot_interface<device_neogeo_ctrl_edge_interface>(mconfig, *this),
m_device(nullptr)
{
}
@@ -158,18 +158,18 @@ neogeo_ctrl_edge_port_device::~neogeo_ctrl_edge_port_device()
void neogeo_ctrl_edge_port_device::device_start()
{
- m_device = dynamic_cast<device_neogeo_ctrl_edge_interface *>(get_card_device());
+ m_device = get_card_device();
}
-READ8_MEMBER(neogeo_ctrl_edge_port_device::in0_r)
+uint8_t neogeo_ctrl_edge_port_device::in0_r()
{
- return m_device ? m_device->in0_r(space, offset, mem_mask) : 0xff;
+ return m_device ? m_device->in0_r() : 0xff;
}
-READ8_MEMBER(neogeo_ctrl_edge_port_device::in1_r)
+uint8_t neogeo_ctrl_edge_port_device::in1_r()
{
- return m_device ? m_device->in1_r(space, offset, mem_mask) : 0xff;
+ return m_device ? m_device->in1_r() : 0xff;
}
uint8_t neogeo_ctrl_edge_port_device::read_start_sel()
@@ -200,6 +200,12 @@ void neogeo_arc_edge(device_slot_interface &device)
device.option_add("joy", NEOGEO_JOY_AC);
}
+void neogeo_arc_edge_irrmaze(device_slot_interface &device)
+{
+ device.option_add("joy", NEOGEO_JOY_AC);
+ device.option_add("irrmaze", NEOGEO_IRRMAZE);
+}
+
void neogeo_arc_edge_fixed(device_slot_interface &device)
{
device.option_add("joy", NEOGEO_JOY_AC);
diff --git a/src/devices/bus/neogeo_ctrl/ctrl.h b/src/devices/bus/neogeo_ctrl/ctrl.h
index bfe568d9b7e..2a410c42cac 100644
--- a/src/devices/bus/neogeo_ctrl/ctrl.h
+++ b/src/devices/bus/neogeo_ctrl/ctrl.h
@@ -18,9 +18,8 @@
class neogeo_control_port_device;
class neogeo_ctrl_edge_port_device;
-// ======================> device_neogeo_control_port_interface
-class device_neogeo_control_port_interface : public device_slot_card_interface
+class device_neogeo_control_port_interface : public device_interface
{
public:
// construction/destruction
@@ -36,9 +35,8 @@ protected:
neogeo_control_port_device *m_port;
};
-// ======================> neogeo_control_port_device
-class neogeo_control_port_device : public device_t, public device_slot_interface
+class neogeo_control_port_device : public device_t, public device_single_card_slot_interface<device_neogeo_control_port_interface>
{
public:
// construction/destruction
@@ -57,27 +55,24 @@ public:
uint8_t read_ctrl();
uint8_t read_start_sel();
void write_ctrlsel(uint8_t data);
- DECLARE_READ8_MEMBER( ctrl_r ) { return read_ctrl(); }
protected:
// device-level overrides
- virtual void device_start() override;
+ virtual void device_start() override ATTR_COLD;
device_neogeo_control_port_interface *m_device;
};
-// ======================> device_neogeo_ctrl_edge_interface
-
-class device_neogeo_ctrl_edge_interface : public device_slot_card_interface
+class device_neogeo_ctrl_edge_interface : public device_interface
{
public:
// construction/destruction
virtual ~device_neogeo_ctrl_edge_interface();
virtual uint8_t read_start_sel() { return 0xff; }
- virtual DECLARE_READ8_MEMBER( in0_r ) { return 0xff; }
- virtual DECLARE_READ8_MEMBER( in1_r ) { return 0xff; }
+ virtual uint8_t in0_r() { return 0xff; }
+ virtual uint8_t in1_r() { return 0xff; }
virtual void write_ctrlsel(uint8_t data) { }
protected:
@@ -86,9 +81,8 @@ protected:
neogeo_ctrl_edge_port_device *m_port;
};
-// ======================> neogeo_ctrl_edge_port_device
-class neogeo_ctrl_edge_port_device : public device_t, public device_slot_interface
+class neogeo_ctrl_edge_port_device : public device_t, public device_single_card_slot_interface<device_neogeo_ctrl_edge_interface>
{
public:
// construction/destruction
@@ -105,27 +99,26 @@ public:
virtual ~neogeo_ctrl_edge_port_device();
uint8_t read_start_sel();
- DECLARE_READ8_MEMBER( in0_r );
- DECLARE_READ8_MEMBER( in1_r );
+ uint8_t in0_r();
+ uint8_t in1_r();
void write_ctrlsel(uint8_t data);
protected:
// device-level overrides
- virtual void device_start() override;
+ virtual void device_start() override ATTR_COLD;
device_neogeo_ctrl_edge_interface *m_device;
};
-// device type definition
DECLARE_DEVICE_TYPE(NEOGEO_CONTROL_PORT, neogeo_control_port_device)
DECLARE_DEVICE_TYPE(NEOGEO_CTRL_EDGE_CONNECTOR, neogeo_ctrl_edge_port_device)
void neogeo_controls(device_slot_interface &device);
void neogeo_arc_edge(device_slot_interface &device);
+void neogeo_arc_edge_irrmaze(device_slot_interface &device);
void neogeo_arc_edge_fixed(device_slot_interface &device);
void neogeo_arc_pin15(device_slot_interface &device);
-
#endif // MAME_BUS_NEOGEO_CTRL_CTRL_H
diff --git a/src/devices/bus/neogeo_ctrl/dial.cpp b/src/devices/bus/neogeo_ctrl/dial.cpp
index 9f4bd75066d..6ee2a75840c 100644
--- a/src/devices/bus/neogeo_ctrl/dial.cpp
+++ b/src/devices/bus/neogeo_ctrl/dial.cpp
@@ -22,7 +22,7 @@ static INPUT_PORTS_START( neogeo_dial )
PORT_BIT( 0x02, IP_ACTIVE_LOW, IPT_JOYSTICK_DOWN ) PORT_PLAYER(1)
PORT_BIT( 0x04, IP_ACTIVE_LOW, IPT_JOYSTICK_LEFT ) PORT_PLAYER(1)
PORT_BIT( 0x08, IP_ACTIVE_LOW, IPT_JOYSTICK_RIGHT ) PORT_PLAYER(1)
- PORT_BIT( 0x90, IP_ACTIVE_LOW, IPT_BUTTON1 ) PORT_PLAYER(1) /* note it needs it from 0x80 when using paddle */
+ PORT_BIT( 0x90, IP_ACTIVE_LOW, IPT_BUTTON1 ) PORT_PLAYER(1) // note it needs it from 0x80 when using paddle
PORT_BIT( 0x20, IP_ACTIVE_LOW, IPT_BUTTON2 ) PORT_PLAYER(1)
PORT_BIT( 0x40, IP_ACTIVE_LOW, IPT_BUTTON3 ) PORT_PLAYER(1)
@@ -31,7 +31,7 @@ static INPUT_PORTS_START( neogeo_dial )
PORT_BIT( 0x02, IP_ACTIVE_LOW, IPT_JOYSTICK_DOWN ) PORT_PLAYER(2)
PORT_BIT( 0x04, IP_ACTIVE_LOW, IPT_JOYSTICK_LEFT ) PORT_PLAYER(2)
PORT_BIT( 0x08, IP_ACTIVE_LOW, IPT_JOYSTICK_RIGHT ) PORT_PLAYER(2)
- PORT_BIT( 0x90, IP_ACTIVE_LOW, IPT_BUTTON1 ) PORT_PLAYER(2) /* note it needs it from 0x80 when using paddle */
+ PORT_BIT( 0x90, IP_ACTIVE_LOW, IPT_BUTTON1 ) PORT_PLAYER(2) // note it needs it from 0x80 when using paddle
PORT_BIT( 0x20, IP_ACTIVE_LOW, IPT_BUTTON2 ) PORT_PLAYER(2)
PORT_BIT( 0x40, IP_ACTIVE_LOW, IPT_BUTTON3 ) PORT_PLAYER(2)
@@ -84,17 +84,8 @@ neogeo_dial_device::neogeo_dial_device(const machine_config &mconfig, const char
void neogeo_dial_device::device_start()
{
- save_item(NAME(m_ctrl_sel));
-}
-
-
-//-------------------------------------------------
-// device_reset - device-specific reset
-//-------------------------------------------------
-
-void neogeo_dial_device::device_reset()
-{
m_ctrl_sel = 0;
+ save_item(NAME(m_ctrl_sel));
}
@@ -102,30 +93,18 @@ void neogeo_dial_device::device_reset()
// in0_r
//-------------------------------------------------
-READ8_MEMBER(neogeo_dial_device::in0_r)
+uint8_t neogeo_dial_device::in0_r()
{
- uint8_t res = 0;
- if (m_ctrl_sel & 0x01)
- res = m_joy1->read();
- else
- res = m_dial1->read();
-
- return res;
+ return BIT(m_ctrl_sel, 0) ? m_joy1->read() : m_dial1->read();
}
//-------------------------------------------------
// in1_r
//-------------------------------------------------
-READ8_MEMBER(neogeo_dial_device::in1_r)
+uint8_t neogeo_dial_device::in1_r()
{
- uint8_t res = 0;
- if (m_ctrl_sel & 0x01)
- res = m_joy2->read();
- else
- res = m_dial2->read();
-
- return res;
+ return BIT(m_ctrl_sel, 0) ? m_joy2->read() : m_dial2->read();
}
//-------------------------------------------------
diff --git a/src/devices/bus/neogeo_ctrl/dial.h b/src/devices/bus/neogeo_ctrl/dial.h
index e532d11d195..ebdae3b7958 100644
--- a/src/devices/bus/neogeo_ctrl/dial.h
+++ b/src/devices/bus/neogeo_ctrl/dial.h
@@ -27,16 +27,15 @@ public:
neogeo_dial_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;
+ virtual ioport_constructor device_input_ports() const override ATTR_COLD;
protected:
// device-level overrides
- virtual void device_start() override;
- virtual void device_reset() override;
+ virtual void device_start() override ATTR_COLD;
// device_neogeo_control_port_interface overrides
- virtual DECLARE_READ8_MEMBER( in0_r ) override;
- virtual DECLARE_READ8_MEMBER( in1_r ) override;
+ virtual uint8_t in0_r() override;
+ virtual uint8_t in1_r() override;
virtual void write_ctrlsel(uint8_t data) override;
virtual uint8_t read_start_sel() override;
diff --git a/src/devices/bus/neogeo_ctrl/irrmaze.cpp b/src/devices/bus/neogeo_ctrl/irrmaze.cpp
index d6020244ca7..59374e6f99a 100644
--- a/src/devices/bus/neogeo_ctrl/irrmaze.cpp
+++ b/src/devices/bus/neogeo_ctrl/irrmaze.cpp
@@ -86,22 +86,16 @@ void neogeo_irrmaze_device::device_start()
// in0_r
//-------------------------------------------------
-READ8_MEMBER(neogeo_irrmaze_device::in0_r)
+uint8_t neogeo_irrmaze_device::in0_r()
{
- uint8_t res = 0;
- if (m_ctrl_sel & 0x01)
- res = m_ty->read();
- else
- res = m_tx->read();
-
- return res;
+ return BIT(m_ctrl_sel, 0) ? m_ty->read() : m_tx->read();
}
//-------------------------------------------------
// in1_r
//-------------------------------------------------
-READ8_MEMBER(neogeo_irrmaze_device::in1_r)
+uint8_t neogeo_irrmaze_device::in1_r()
{
return m_buttons->read();
}
diff --git a/src/devices/bus/neogeo_ctrl/irrmaze.h b/src/devices/bus/neogeo_ctrl/irrmaze.h
index bc00b4eeb2e..b4e539cef72 100644
--- a/src/devices/bus/neogeo_ctrl/irrmaze.h
+++ b/src/devices/bus/neogeo_ctrl/irrmaze.h
@@ -27,12 +27,12 @@ public:
protected:
// device-level overrides
- virtual ioport_constructor device_input_ports() const override;
- virtual void device_start() override;
+ virtual ioport_constructor device_input_ports() const override ATTR_COLD;
+ virtual void device_start() override ATTR_COLD;
// device_neogeo_control_port_interface overrides
- virtual DECLARE_READ8_MEMBER( in0_r ) override;
- virtual DECLARE_READ8_MEMBER( in1_r ) override;
+ virtual uint8_t in0_r() override;
+ virtual uint8_t in1_r() override;
virtual uint8_t read_start_sel() override;
virtual void write_ctrlsel(uint8_t data) override;
diff --git a/src/devices/bus/neogeo_ctrl/joystick.cpp b/src/devices/bus/neogeo_ctrl/joystick.cpp
index 045e593895c..fe2712d00a8 100644
--- a/src/devices/bus/neogeo_ctrl/joystick.cpp
+++ b/src/devices/bus/neogeo_ctrl/joystick.cpp
@@ -31,10 +31,10 @@ static INPUT_PORTS_START( neogeo_joy )
PORT_BIT( 0x02, IP_ACTIVE_LOW, IPT_JOYSTICK_DOWN )
PORT_BIT( 0x04, IP_ACTIVE_LOW, IPT_JOYSTICK_LEFT )
PORT_BIT( 0x08, IP_ACTIVE_LOW, IPT_JOYSTICK_RIGHT )
- PORT_BIT( 0x10, IP_ACTIVE_LOW, IPT_BUTTON1 ) PORT_NAME("A")
- PORT_BIT( 0x20, IP_ACTIVE_LOW, IPT_BUTTON2 ) PORT_NAME("B")
- PORT_BIT( 0x40, IP_ACTIVE_LOW, IPT_BUTTON3 ) PORT_NAME("C")
- PORT_BIT( 0x80, IP_ACTIVE_LOW, IPT_BUTTON4 ) PORT_NAME("D")
+ 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( 0x40, IP_ACTIVE_LOW, IPT_BUTTON3 ) PORT_NAME("%p C")
+ PORT_BIT( 0x80, IP_ACTIVE_LOW, IPT_BUTTON4 ) PORT_NAME("%p D")
PORT_START("START_SELECT")
PORT_BIT( 0x01, IP_ACTIVE_LOW, IPT_START )
@@ -130,20 +130,20 @@ static INPUT_PORTS_START( neogeo_joy_ac )
PORT_BIT( 0x02, IP_ACTIVE_LOW, IPT_JOYSTICK_DOWN ) PORT_PLAYER(1)
PORT_BIT( 0x04, IP_ACTIVE_LOW, IPT_JOYSTICK_LEFT ) PORT_PLAYER(1)
PORT_BIT( 0x08, IP_ACTIVE_LOW, IPT_JOYSTICK_RIGHT ) PORT_PLAYER(1)
- PORT_BIT( 0x10, IP_ACTIVE_LOW, IPT_BUTTON1 ) PORT_PLAYER(1)
- PORT_BIT( 0x20, IP_ACTIVE_LOW, IPT_BUTTON2 ) PORT_PLAYER(1)
- PORT_BIT( 0x40, IP_ACTIVE_LOW, IPT_BUTTON3 ) PORT_PLAYER(1)
- PORT_BIT( 0x80, IP_ACTIVE_LOW, IPT_BUTTON4 ) PORT_PLAYER(1)
+ PORT_BIT( 0x10, IP_ACTIVE_LOW, IPT_BUTTON1 ) PORT_PLAYER(1) PORT_NAME("%p A")
+ PORT_BIT( 0x20, IP_ACTIVE_LOW, IPT_BUTTON2 ) PORT_PLAYER(1) PORT_NAME("%p B")
+ PORT_BIT( 0x40, IP_ACTIVE_LOW, IPT_BUTTON3 ) PORT_PLAYER(1) PORT_NAME("%p C")
+ PORT_BIT( 0x80, IP_ACTIVE_LOW, IPT_BUTTON4 ) PORT_PLAYER(1) PORT_NAME("%p D")
PORT_START("JOY2")
PORT_BIT( 0x01, IP_ACTIVE_LOW, IPT_JOYSTICK_UP ) PORT_PLAYER(2)
PORT_BIT( 0x02, IP_ACTIVE_LOW, IPT_JOYSTICK_DOWN ) PORT_PLAYER(2)
PORT_BIT( 0x04, IP_ACTIVE_LOW, IPT_JOYSTICK_LEFT ) PORT_PLAYER(2)
PORT_BIT( 0x08, IP_ACTIVE_LOW, IPT_JOYSTICK_RIGHT ) PORT_PLAYER(2)
- PORT_BIT( 0x10, IP_ACTIVE_LOW, IPT_BUTTON1 ) PORT_PLAYER(2)
- PORT_BIT( 0x20, IP_ACTIVE_LOW, IPT_BUTTON2 ) PORT_PLAYER(2)
- PORT_BIT( 0x40, IP_ACTIVE_LOW, IPT_BUTTON3 ) PORT_PLAYER(2)
- PORT_BIT( 0x80, IP_ACTIVE_LOW, IPT_BUTTON4 ) PORT_PLAYER(2)
+ PORT_BIT( 0x10, IP_ACTIVE_LOW, IPT_BUTTON1 ) PORT_PLAYER(2) PORT_NAME("%p A")
+ PORT_BIT( 0x20, IP_ACTIVE_LOW, IPT_BUTTON2 ) PORT_PLAYER(2) PORT_NAME("%p B")
+ PORT_BIT( 0x40, IP_ACTIVE_LOW, IPT_BUTTON3 ) PORT_PLAYER(2) PORT_NAME("%p C")
+ PORT_BIT( 0x80, IP_ACTIVE_LOW, IPT_BUTTON4 ) PORT_PLAYER(2) PORT_NAME("%p D")
PORT_START("START")
PORT_BIT( 0xfa, IP_ACTIVE_LOW, IPT_UNUSED )
@@ -190,7 +190,7 @@ void neogeo_joy_ac_device::device_start()
// in0_r
//-------------------------------------------------
-READ8_MEMBER(neogeo_joy_ac_device::in0_r)
+uint8_t neogeo_joy_ac_device::in0_r()
{
return m_joy[0]->read();
}
@@ -199,7 +199,7 @@ READ8_MEMBER(neogeo_joy_ac_device::in0_r)
// in1_r
//-------------------------------------------------
-READ8_MEMBER(neogeo_joy_ac_device::in1_r)
+uint8_t neogeo_joy_ac_device::in1_r()
{
return m_joy[1]->read();
}
diff --git a/src/devices/bus/neogeo_ctrl/joystick.h b/src/devices/bus/neogeo_ctrl/joystick.h
index bf07ec90b9b..68f1eb2a55e 100644
--- a/src/devices/bus/neogeo_ctrl/joystick.h
+++ b/src/devices/bus/neogeo_ctrl/joystick.h
@@ -27,8 +27,8 @@ public:
protected:
// device-level overrides
- virtual ioport_constructor device_input_ports() const override;
- virtual void device_start() override;
+ virtual ioport_constructor device_input_ports() const override ATTR_COLD;
+ virtual void device_start() override ATTR_COLD;
// device_neogeo_control_port_interface overrides
virtual uint8_t read_ctrl() override;
@@ -52,12 +52,12 @@ public:
protected:
// device-level overrides
- virtual ioport_constructor device_input_ports() const override;
- virtual void device_start() override;
+ virtual ioport_constructor device_input_ports() const override ATTR_COLD;
+ virtual void device_start() override ATTR_COLD;
// device_neogeo_ctrl_edge_interface overrides
- virtual DECLARE_READ8_MEMBER( in0_r ) override;
- virtual DECLARE_READ8_MEMBER( in1_r ) override;
+ virtual uint8_t in0_r() override;
+ virtual uint8_t in1_r() override;
virtual uint8_t read_start_sel() override;
private:
diff --git a/src/devices/bus/neogeo_ctrl/kizuna4p.cpp b/src/devices/bus/neogeo_ctrl/kizuna4p.cpp
index 4ef3e3d78fe..ccc08ef61ed 100644
--- a/src/devices/bus/neogeo_ctrl/kizuna4p.cpp
+++ b/src/devices/bus/neogeo_ctrl/kizuna4p.cpp
@@ -119,7 +119,7 @@ void neogeo_kizuna4p_device::device_start()
// in0_r
//-------------------------------------------------
-READ8_MEMBER(neogeo_kizuna4p_device::in0_r)
+uint8_t neogeo_kizuna4p_device::in0_r()
{
return m_joy[BIT(m_ctrl_sel, 0) << 1]->read() & ~(BIT(m_ctrl_sel, 2) << (BIT(m_ctrl_sel, 0) | 4));
}
@@ -128,7 +128,7 @@ READ8_MEMBER(neogeo_kizuna4p_device::in0_r)
// in1_r
//-------------------------------------------------
-READ8_MEMBER(neogeo_kizuna4p_device::in1_r)
+uint8_t neogeo_kizuna4p_device::in1_r()
{
return m_joy[(BIT(m_ctrl_sel, 0) << 1) | 1]->read() & ~(BIT(m_ctrl_sel, 2) << (BIT(m_ctrl_sel, 0) | 4));
}
diff --git a/src/devices/bus/neogeo_ctrl/kizuna4p.h b/src/devices/bus/neogeo_ctrl/kizuna4p.h
index c48f0078a81..b9575b690fc 100644
--- a/src/devices/bus/neogeo_ctrl/kizuna4p.h
+++ b/src/devices/bus/neogeo_ctrl/kizuna4p.h
@@ -28,12 +28,12 @@ public:
protected:
// device-level overrides
- virtual ioport_constructor device_input_ports() const override;
- virtual void device_start() override;
+ virtual ioport_constructor device_input_ports() const override ATTR_COLD;
+ virtual void device_start() override ATTR_COLD;
// device_neogeo_control_port_interface overrides
- virtual DECLARE_READ8_MEMBER( in0_r ) override;
- virtual DECLARE_READ8_MEMBER( in1_r ) override;
+ virtual uint8_t in0_r() override;
+ virtual uint8_t in1_r() override;
virtual uint8_t read_start_sel() override;
virtual void write_ctrlsel(uint8_t data) override;
diff --git a/src/devices/bus/neogeo_ctrl/mahjong.h b/src/devices/bus/neogeo_ctrl/mahjong.h
index d4fd1646ece..36987565c3c 100644
--- a/src/devices/bus/neogeo_ctrl/mahjong.h
+++ b/src/devices/bus/neogeo_ctrl/mahjong.h
@@ -29,9 +29,9 @@ protected:
neogeo_mjctrl_ac_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock);
// device-level overrides
- virtual ioport_constructor device_input_ports() const override;
+ virtual ioport_constructor device_input_ports() const override ATTR_COLD;
virtual uint8_t read_start_sel() override;
- virtual void device_start() override;
+ virtual void device_start() override ATTR_COLD;
// device_neogeo_control_port_interface overrides
virtual uint8_t read_ctrl() override;
@@ -54,7 +54,7 @@ public:
protected:
// optional information overrides
- virtual ioport_constructor device_input_ports() const override;
+ virtual ioport_constructor device_input_ports() const override ATTR_COLD;
// device_neogeo_control_port_interface overrides
virtual uint8_t read_start_sel() override;
diff --git a/src/devices/bus/nes/2a03pur.cpp b/src/devices/bus/nes/2a03pur.cpp
index 87e364b1638..9425cfdadcf 100644
--- a/src/devices/bus/nes/2a03pur.cpp
+++ b/src/devices/bus/nes/2a03pur.cpp
@@ -7,7 +7,7 @@
Here we emulate the PCB designed by infiniteneslives and
- rainwarrior for this homebew multicart [mapper 31]
+ rainwarrior for this homebrew multicart [mapper 31]
The main difference of this PCB compared to others is that it
uses 4k PRG banks!
@@ -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"
//-------------------------------------------------
@@ -34,7 +33,7 @@
DEFINE_DEVICE_TYPE(NES_2A03PURITANS, nes_2a03pur_device, "nes_2a03pur", "NES Cart 2A03 Puritans Album PCB")
-nes_2a03pur_device::nes_2a03pur_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
+nes_2a03pur_device::nes_2a03pur_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock)
: nes_nrom_device(mconfig, NES_2A03PURITANS, tag, owner, clock)
{
}
@@ -45,14 +44,12 @@ void nes_2a03pur_device::device_start()
{
common_start();
save_item(NAME(m_reg));
- memset(m_reg, 0x00, sizeof(m_reg));
- m_reg[7] = 0xff & ((m_prg_chunks << 2) - 1);
+ std::fill(std::begin(m_reg), std::end(m_reg), 0x00);
+ m_reg[7] = 0xff;
}
void nes_2a03pur_device::pcb_reset()
{
- m_chr_source = m_vrom_chunks ? CHRROM : CHRRAM;
- chr8(0, m_chr_source);
// register content is not touched by reset
}
@@ -65,7 +62,9 @@ void nes_2a03pur_device::pcb_reset()
Board 2A03 Puritans Album
- In MESS: supported.
+ iNES: mapper 31
+
+ In MAME: Supported.
This mapper supports up to 1MB of PRG-ROM, in 4k
banks located at $8000, $9000, $A000, $B000, $C000,
@@ -91,17 +90,17 @@ void nes_2a03pur_device::pcb_reset()
This has been assigned to iNES mapper 31.
-------------------------------------------------*/
-void nes_2a03pur_device::write_l(offs_t offset, uint8_t data)
+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 & ((m_prg_chunks << 2) - 1);
+ m_reg[offset & 7] = data;
}
-uint8_t nes_2a03pur_device::read_h(offs_t offset)
+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[(offset >> 12) & 7] * 0x1000) + (offset & 0x0fff)];
+ return m_prg[((m_reg[BIT(offset, 12, 3)] * 0x1000) + (offset & 0x0fff)) & (m_prg_size - 1)];
}
diff --git a/src/devices/bus/nes/2a03pur.h b/src/devices/bus/nes/2a03pur.h
index 970898ff128..01bd0a80a45 100644
--- a/src/devices/bus/nes/2a03pur.h
+++ b/src/devices/bus/nes/2a03pur.h
@@ -8,25 +8,25 @@
#include "nxrom.h"
-// ======================> nes_racermate_device
+// ======================> nes_2a03pur_device
class nes_2a03pur_device : public nes_nrom_device
{
public:
// construction/destruction
- nes_2a03pur_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
+ nes_2a03pur_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock);
- virtual uint8_t read_h(offs_t offset) override;
- virtual void write_l(offs_t offset, uint8_t data) override;
+ virtual u8 read_h(offs_t offset) override;
+ virtual void write_l(offs_t offset, u8 data) override;
virtual void pcb_reset() override;
protected:
// device-level overrides
- virtual void device_start() override;
+ virtual void device_start() override ATTR_COLD;
private:
- uint8_t m_reg[8];
+ u8 m_reg[8];
};
diff --git a/src/devices/bus/nes/act53.cpp b/src/devices/bus/nes/act53.cpp
index 2a441c36153..59955eb74fc 100644
--- a/src/devices/bus/nes/act53.cpp
+++ b/src/devices/bus/nes/act53.cpp
@@ -7,7 +7,7 @@
Here we emulate the Multi-Discrete PCB designed by Tepples for
- this homebew multicart [mapper 28]
+ this homebrew multicart [mapper 28]
***********************************************************************************************************/
@@ -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"
//-------------------------------------------------
@@ -32,7 +31,7 @@
DEFINE_DEVICE_TYPE(NES_ACTION53, nes_action53_device, "nes_action53", "NES Cart Action 53 PCB")
-nes_action53_device::nes_action53_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
+nes_action53_device::nes_action53_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock)
: nes_nrom_device(mconfig, NES_ACTION53, tag, owner, clock)
, m_sel(0)
{
@@ -45,17 +44,20 @@ void nes_action53_device::device_start()
common_start();
save_item(NAME(m_sel));
save_item(NAME(m_reg));
- m_reg[0] = 0x00;
- m_reg[1] = 0x0f;
- m_reg[2] = 0x00;
- m_reg[3] = 0x3f;
+}
+
+void nes_action53_device::pcb_start(running_machine &machine, u8 *ciram_ptr, bool cart_mounted)
+{
+ device_nes_cart_interface::pcb_start(machine, ciram_ptr, cart_mounted);
+ // at power on last 16K of ROM is mapped to $C000-$FFFF
+ m_reg[0] = m_reg[1] = m_reg[2] = 0;
+ m_reg[3] = (m_prg_chunks - 1) >> 1;
+ update_prg();
}
void nes_action53_device::pcb_reset()
{
- m_chr_source = m_vrom_chunks ? CHRROM : CHRRAM;
// register content is not touched by reset
- update_prg();
}
@@ -67,7 +69,9 @@ void nes_action53_device::pcb_reset()
Board ACTION 53
- In MESS: *VERY* preliminary support.
+ iNES: mapper 28
+
+ In MAME: Preliminary supported.
This board uses 4 registers (reg is selected by writes to 0x5xxx)
Info from nesdev wiki
@@ -79,7 +83,7 @@ void nes_action53_device::pcb_reset()
R:$80 is clear
R:$01: [...M PPPP]
- P = PRG Reg
+ P = Inner PRG Reg
M = Mirroring
This bit overwrites bit 0 of R:$80, but only if bit 1 of
R:$80 is clear
@@ -97,7 +101,7 @@ void nes_action53_device::pcb_reset()
%10 = Vert
%11 = Horz
- R:$81: [..BB BBBB]
+ R:$81: [BBBB BBBB]
Outer PRG Reg
@@ -105,34 +109,20 @@ void nes_action53_device::pcb_reset()
void nes_action53_device::update_prg()
{
- uint8_t prg_lo, prg_hi, helper;
- uint8_t out = (m_reg[3] & 0x3f) << 1; // Outer PRG reg
- uint8_t size = (m_reg[2] & 0x30) >> 4; // Game size
- uint8_t mask = (1 << (size + 1)) - 1; // Bits to be taken from PRG reg
-
- if (!BIT(m_reg[2], 3))
- {
- helper = (out & ~mask) | ((m_reg[1] << 1) & mask);
- //32K mode
- prg_lo = (helper & 0xfe);
- prg_hi = (helper | 0x01);
- }
- else
- {
- helper = (out & ~mask) | (m_reg[1] & mask);
- if (BIT(m_reg[2], 2))
- {
- //16K mode with fixed HI
- prg_lo = helper;
- prg_hi = (out | 0x01);
- }
- else
- {
- //16K mode with fixed LO
- prg_lo = (out & 0xfe);
- prg_hi = helper;
- }
- }
+ u16 prg_lo, prg_hi;
+ u8 size = BIT(m_reg[2], 4, 2); // Game size
+ u16 mask = ~0 << (size + 1); // Bits to be taken from PRG regs
+ u8 b32k = !BIT(m_reg[2], 3); // 32K mode bit
+ u16 outer = m_reg[3] << 1; // Outer PRG reg bits
+ u8 inner = (m_reg[1] << b32k) & ~mask; // Inner PRG reg bits
+
+ prg_hi = prg_lo = (outer & mask) | inner;
+ if (b32k) // 32K mode
+ prg_hi++;
+ else if (BIT(m_reg[2], 2)) // 16K mode with fixed HI
+ prg_hi = ++outer;
+ else // 16K mode with fixed LO
+ prg_lo = outer;
// printf("banks : 0x%2X - 0x%2X\n", prg_lo, prg_hi);
prg16_89ab(prg_lo);
@@ -158,18 +148,18 @@ void nes_action53_device::update_mirr()
}
}
-void nes_action53_device::write_l(offs_t offset, uint8_t data)
+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 = BIT(data, 0) | (BIT(data, 7) << 1);
+ m_sel = bitswap<2>(data, 7, 0);
}
-void nes_action53_device::write_h(offs_t offset, uint8_t 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/act53.h b/src/devices/bus/nes/act53.h
index 8e4b1c3b073..629abdd537f 100644
--- a/src/devices/bus/nes/act53.h
+++ b/src/devices/bus/nes/act53.h
@@ -12,22 +12,23 @@ class nes_action53_device : public nes_nrom_device
{
public:
// construction/destruction
- nes_action53_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
+ nes_action53_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock);
- virtual void write_l(offs_t offset, uint8_t data) override;
- virtual void write_h(offs_t offset, uint8_t data) override;
+ virtual void write_l(offs_t offset, u8 data) override;
+ virtual void write_h(offs_t offset, u8 data) override;
virtual void pcb_reset() override;
+ virtual void pcb_start(running_machine &machine, u8 *ciram_ptr, bool cart_mounted) override;
protected:
// device-level overrides
- virtual void device_start() override;
+ virtual void device_start() override ATTR_COLD;
private:
void update_prg();
void update_mirr();
- uint8_t m_sel;
- uint8_t m_reg[4];
+ u8 m_sel;
+ u8 m_reg[4];
};
// device type definition
diff --git a/src/devices/bus/nes/aladdin.cpp b/src/devices/bus/nes/aladdin.cpp
index db57b61ff00..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"
@@ -39,7 +38,7 @@
//-------------------------------------------------
aladdin_cart_interface::aladdin_cart_interface(const machine_config &mconfig, device_t &device)
- : device_slot_card_interface(mconfig, device)
+ : device_interface(device, "aladdincart")
, m_rom(nullptr)
, m_rom_size(0)
, m_lobank(0)
@@ -68,8 +67,8 @@ DEFINE_DEVICE_TYPE(NES_ALADDIN_SLOT, nes_aladdin_slot_device, "nes_ade_slot", "N
nes_aladdin_slot_device::nes_aladdin_slot_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
: device_t(mconfig, NES_ALADDIN_SLOT, tag, owner, clock)
- , device_image_interface(mconfig, *this)
- , device_slot_interface(mconfig, *this)
+ , device_cartrom_image_interface(mconfig, *this)
+ , device_single_card_slot_interface<aladdin_cart_interface>(mconfig, *this)
, m_cart(nullptr)
{
}
@@ -81,7 +80,7 @@ nes_aladdin_slot_device::~nes_aladdin_slot_device()
void nes_aladdin_slot_device::device_start()
{
- m_cart = dynamic_cast<aladdin_cart_interface *>(get_card_device());
+ m_cart = get_card_device();
}
uint8_t nes_aladdin_slot_device::read(offs_t offset)
@@ -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());
}
@@ -141,16 +141,15 @@ std::string nes_aladdin_slot_device::get_default_card_software(get_default_card_
{
if (hook.image_file())
{
- const char *slot_string = "algn";
- uint32_t len = hook.image_file()->size();
+ uint64_t len;
+ hook.image_file()->length(len); // FIXME: check error return, guard against excessively large files
std::vector<uint8_t> rom(len);
- uint8_t mapper;
- hook.image_file()->read(&rom[0], len);
+ util::read(*hook.image_file(), &rom[0], len); // FIXME: check error return or read returning short
- mapper = (rom[6] & 0xf0) >> 4;
- mapper |= rom[7] & 0xf0;
+ uint8_t const mapper = ((rom[6] & 0xf0) >> 4) | (rom[7] & 0xf0);
+ const char *slot_string = "algn";
// if (mapper == 71)
// slot_string = "algn";
if (mapper == 232)
@@ -158,8 +157,8 @@ std::string nes_aladdin_slot_device::get_default_card_software(get_default_card_
return std::string(slot_string);
}
- else
- return software_get_default_slot("algn");
+
+ return software_get_default_slot("algn");
}
@@ -245,7 +244,7 @@ void nes_algq_rom_device::write_prg(uint32_t offset, uint8_t data)
// m_hibank = 3rd page inside the block
if (offset < 0x4000)
{
- m_bank_base = ((data >> 3) & 3) << 2;
+ m_bank_base = (data & 0x18) >> 1;
m_lobank = m_bank_base | (m_lobank & 3);
m_hibank = m_bank_base | 3;
}
@@ -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 9014bf6969a..b97be914218 100644
--- a/src/devices/bus/nes/aladdin.h
+++ b/src/devices/bus/nes/aladdin.h
@@ -6,7 +6,7 @@
#pragma once
#include "nxrom.h"
-#include "softlist_dev.h"
+#include "imagedev/cartrom.h"
//----------------------------------
@@ -17,7 +17,7 @@
// ======================> aladdin_cart_interface
-class aladdin_cart_interface : public device_slot_card_interface
+class aladdin_cart_interface : public device_interface
{
public:
// construction/destruction
@@ -44,8 +44,8 @@ protected:
class nes_aladdin_device;
class nes_aladdin_slot_device : public device_t,
- public device_image_interface,
- public device_slot_interface
+ public device_cartrom_image_interface,
+ public device_single_card_slot_interface<aladdin_cart_interface>
{
friend class nes_aladdin_device;
public:
@@ -63,30 +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();
- // device-level overrides
- virtual void device_start() override;
-
- // image-level overrides
- virtual image_init_result call_load() override;
- virtual const software_list_loader &get_software_list_loader() const override { return rom_software_list_loader::instance(); }
-
- virtual iodevice_t image_type() const override { return IO_CARTSLOT; }
- virtual bool is_readable() const override { return 1; }
- virtual bool is_writeable() const override { return 0; }
- virtual bool is_creatable() const override { return 0; }
- virtual bool must_be_loaded() const override { return 0; }
- virtual bool is_reset_on_load() const override { return 1; }
- virtual const char *image_interface() const override { return "ade_cart"; }
- virtual const char *file_extensions() const override { return "nes,bin"; }
-
- // slot interface overrides
+ // 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"; }
+
+ // 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:
- aladdin_cart_interface* m_cart;
+ // device_t implementation
+ virtual void device_start() override ATTR_COLD;
+
+ aladdin_cart_interface *m_cart;
};
// device type definition
@@ -109,7 +103,7 @@ public:
nes_algn_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 const tiny_rom_entry *device_rom_region() const override ATTR_COLD;
virtual uint8_t* get_cart_base();
virtual void write_prg(uint32_t offset, uint8_t data) override;
@@ -117,8 +111,8 @@ protected:
nes_algn_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 void device_start() override ATTR_COLD;
+ virtual void device_reset() override ATTR_COLD;
};
@@ -135,8 +129,8 @@ public:
protected:
// device-level overrides
- virtual void device_start() override;
- virtual void device_reset() override;
+ virtual void device_start() override ATTR_COLD;
+ virtual void device_reset() override ATTR_COLD;
uint8_t m_bank_base;
};
@@ -166,10 +160,9 @@ public:
virtual void pcb_reset() override;
protected:
- // device-level overrides
- virtual void device_start() override;
-
- virtual void device_add_mconfig(machine_config &config) override;
+ // device_t implementation
+ virtual void device_start() override ATTR_COLD;
+ virtual void device_add_mconfig(machine_config &config) override ATTR_COLD;
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 2e93ea17501..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"
//-------------------------------------------------
@@ -38,71 +37,41 @@ DEFINE_DEVICE_TYPE(NES_NINA006, nes_nina006_device, "nes_nina006", "NES Cart AVE
DEFINE_DEVICE_TYPE(NES_MAXI15, nes_maxi15_device, "nes_maxi15", "NES Cart AVE Maxi 15 PCB")
-nes_nina001_device::nes_nina001_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
+nes_nina001_device::nes_nina001_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock)
: nes_nrom_device(mconfig, NES_NINA001, tag, owner, clock)
{
}
-nes_nina006_device::nes_nina006_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
+nes_nina006_device::nes_nina006_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock)
: nes_nrom_device(mconfig, NES_NINA006, tag, owner, clock)
{
}
-nes_maxi15_device::nes_maxi15_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
- : nes_nrom_device(mconfig, NES_MAXI15, tag, owner, clock), m_reg(0), m_bank(0)
+nes_maxi15_device::nes_maxi15_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock)
+ : nes_nrom_device(mconfig, NES_MAXI15, tag, owner, clock)
{
}
-void nes_nina001_device::device_start()
-{
- common_start();
-}
-
-void nes_nina001_device::pcb_reset()
-{
- m_chr_source = m_vrom_chunks ? CHRROM : CHRRAM;
- prg32(0);
- chr8(0, m_chr_source);
-}
-
-void nes_nina006_device::device_start()
-{
- common_start();
-}
-
-void nes_nina006_device::pcb_reset()
-{
- m_chr_source = m_vrom_chunks ? CHRROM : CHRRAM;
- prg32(0);
- chr8(0, m_chr_source);
-}
-
-
void nes_maxi15_device::device_start()
{
common_start();
- save_item(NAME(m_bank));
save_item(NAME(m_reg));
}
void nes_maxi15_device::pcb_reset()
{
- m_chr_source = m_vrom_chunks ? CHRROM : CHRRAM;
prg32(0);
- chr8(0, m_chr_source);
- set_nt_mirroring(PPU_MIRROR_VERT);
+ chr8(0, CHRROM);
- m_reg = 0;
- m_bank = 0;
+ m_reg[0] = m_reg[1] = 0;
}
-
/*-------------------------------------------------
mapper specific handlers
-------------------------------------------------*/
@@ -118,13 +87,15 @@ void nes_maxi15_device::pcb_reset()
then readable back in WRAM (WRAM is tested by
Impossible Mission II at start)
- In MESS: Supported.
+ In MAME: Supported.
-------------------------------------------------*/
-void nes_nina001_device::write_m(offs_t offset, uint8_t data)
+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
switch (offset)
{
@@ -138,8 +109,6 @@ void nes_nina001_device::write_m(offs_t offset, uint8_t data)
chr4_4(data, CHRROM);
break;
}
-
- m_prgram[offset] = data;
}
/*-------------------------------------------------
@@ -151,15 +120,16 @@ void nes_nina001_device::write_m(offs_t offset, uint8_t data)
iNES: mapper 79
- In MESS: Supported.
+ In MAME: Supported.
-------------------------------------------------*/
-void nes_nina006_device::write_l(offs_t offset, uint8_t 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);
- if (!(offset & 0x0100))
+ offset += 0x100;
+ if (BIT(offset, 8)) // $41xx, $43xx, ... $5fxx
{
prg32(data >> 3);
chr8(data & 7, CHRROM);
@@ -174,41 +144,30 @@ void nes_nina006_device::write_l(offs_t offset, uint8_t data)
iNES: mapper 234
- In MESS: Partially Supported.
+ In MAME: Supported.
-------------------------------------------------*/
-void nes_maxi15_device::update_banks()
+u8 nes_maxi15_device::read_h(offs_t offset)
{
- if (m_bank & 0x40)
- {
- prg32((m_bank & 0x0e) | (m_reg & 1));
- chr8(((m_bank & 0x0e) << 2) | ((m_reg >> 4) & 7), m_chr_source);
- }
- else
- {
- prg32(m_bank & 0x0f);
- chr8(((m_bank & 0x0f) << 2) | ((m_reg >> 4) & 3), m_chr_source);
- }
-}
+ LOG("Maxi 15 read_h, offset: %04x\n", offset);
-uint8_t nes_maxi15_device::read_h(offs_t offset)
-{
- LOG_MMC(("Maxi 15 read_h, offset: %04x\n", offset));
+ u8 temp = hi_access_rom(offset);
- if (offset >= 0x7f80 && offset < 0x7fa0)
- {
- m_bank = hi_access_rom(offset);
- set_nt_mirroring(BIT(m_bank, 7) ? PPU_MIRROR_HORZ : PPU_MIRROR_VERT);
- update_banks();
- return m_bank;
- }
- if (offset >= 0x7fe8 && offset < 0x7ff8)
+ if ((offset >= 0x7f80 && offset < 0x7fa0) || (offset >= 0x7fe8 && offset < 0x7ff8))
{
- m_reg = hi_access_rom(offset);
- update_banks();
- return m_reg;
+ int reg = BIT(offset, 6);
+ if (reg || !(m_reg[0] & 0x3f)) // inner banks always modifiable, outer banks locked once set
+ {
+ m_reg[reg] = temp;
+
+ u8 mode = !BIT(m_reg[0], 6);
+ u8 outer = m_reg[0] & (0x0e | mode);
+ prg32(outer | (m_reg[1] & !mode));
+ chr8(outer << 2 | ((m_reg[1] >> 4) & (7 >> mode)), CHRROM);
+ set_nt_mirroring(BIT(m_reg[0], 7) ? PPU_MIRROR_HORZ : PPU_MIRROR_VERT);
+ }
}
- return hi_access_rom(offset);
+ return temp;
}
diff --git a/src/devices/bus/nes/ave.h b/src/devices/bus/nes/ave.h
index b40d2ed6d9d..60e196f9522 100644
--- a/src/devices/bus/nes/ave.h
+++ b/src/devices/bus/nes/ave.h
@@ -14,15 +14,9 @@ class nes_nina001_device : public nes_nrom_device
{
public:
// construction/destruction
- nes_nina001_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
+ nes_nina001_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock);
- virtual void write_m(offs_t offset, uint8_t data) override;
-
- virtual void pcb_reset() override;
-
-protected:
- // device-level overrides
- virtual void device_start() override;
+ virtual void write_m(offs_t offset, u8 data) override;
};
@@ -32,15 +26,9 @@ class nes_nina006_device : public nes_nrom_device
{
public:
// construction/destruction
- nes_nina006_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
-
- virtual void write_l(offs_t offset, uint8_t data) override;
+ nes_nina006_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock);
- virtual void pcb_reset() override;
-
-protected:
- // device-level overrides
- virtual void device_start() override;
+ virtual void write_l(offs_t offset, u8 data) override;
};
@@ -50,20 +38,18 @@ class nes_maxi15_device : public nes_nrom_device
{
public:
// construction/destruction
- nes_maxi15_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
+ nes_maxi15_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock);
- virtual uint8_t read_h(offs_t offset) override;
+ virtual u8 read_h(offs_t offset) override;
virtual void pcb_reset() override;
protected:
// device-level overrides
- virtual void device_start() override;
+ virtual void device_start() override ATTR_COLD;
private:
- void update_banks();
-
- uint8_t m_reg, m_bank;
+ u8 m_reg[2];
};
diff --git a/src/devices/bus/nes/bandai.cpp b/src/devices/bus/nes/bandai.cpp
index 1dd82f1747d..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"
@@ -115,7 +116,6 @@ void nes_oekakids_device::pcb_reset()
prg32(0);
chr4_0(0, CHRRAM);
chr4_4(3, CHRRAM);
- set_nt_mirroring(PPU_MIRROR_LOW);
m_latch = 0;
m_reg = 0;
}
@@ -123,7 +123,7 @@ void nes_oekakids_device::pcb_reset()
void nes_fcg_device::device_start()
{
common_start();
- irq_timer = timer_alloc(TIMER_IRQ);
+ irq_timer = timer_alloc(FUNC(nes_fcg_device::irq_timer_tick), this);
irq_timer->adjust(attotime::zero, 0, clocks_to_attotime(1));
save_item(NAME(m_irq_enable));
@@ -132,7 +132,6 @@ void nes_fcg_device::device_start()
void nes_fcg_device::pcb_reset()
{
- m_chr_source = m_vrom_chunks ? CHRROM : CHRRAM;
prg16_89ab(0);
prg16_cdef(m_prg_chunks - 1);
chr8(0, m_chr_source);
@@ -144,7 +143,7 @@ void nes_fcg_device::pcb_reset()
void nes_lz93d50_24c01_device::device_start()
{
common_start();
- irq_timer = timer_alloc(TIMER_IRQ);
+ irq_timer = timer_alloc(FUNC(nes_lz93d50_24c01_device::irq_timer_tick), this);
irq_timer->adjust(attotime::zero, 0, clocks_to_attotime(1));
save_item(NAME(m_irq_enable));
@@ -154,7 +153,6 @@ void nes_lz93d50_24c01_device::device_start()
void nes_lz93d50_24c01_device::pcb_reset()
{
- m_chr_source = m_vrom_chunks ? CHRROM : CHRRAM;
prg16_89ab(0);
prg16_cdef(m_prg_chunks - 1);
chr8(0, m_chr_source);
@@ -167,7 +165,7 @@ void nes_lz93d50_24c01_device::pcb_reset()
void nes_fjump2_device::device_start()
{
common_start();
- irq_timer = timer_alloc(TIMER_IRQ);
+ irq_timer = timer_alloc(FUNC(nes_fjump2_device::irq_timer_tick), this);
irq_timer->adjust(attotime::zero, 0, clocks_to_attotime(1));
save_item(NAME(m_reg));
@@ -200,39 +198,35 @@ void nes_fjump2_device::pcb_reset()
iNES: mapper 96
- In MESS: Preliminary Support.
+ In MAME: Preliminary Support.
-------------------------------------------------*/
void nes_oekakids_device::nt_w(offs_t offset, uint8_t data)
{
- int page = ((offset & 0xc00) >> 10);
-
#if 0
if (!(offset & 0x1000) && (offset & 0x3ff) < 0x3c0)
{
- m_latch = (offset & 0x300) >> 8;
+ m_latch = BIT(offset, 8, 2);
chr4_0(m_reg | m_latch, CHRRAM);
}
#endif
- m_nt_access[page][offset & 0x3ff] = data;
+ device_nes_cart_interface::nt_w(offset, data);
}
uint8_t nes_oekakids_device::nt_r(offs_t offset)
{
- int page = ((offset & 0xc00) >> 10);
-
#if 0
if (!(offset & 0x1000) && (offset & 0x3ff) < 0x3c0)
{
- m_latch = (offset & 0x300) >> 8;
+ m_latch = BIT(offset, 8, 2);
chr4_0(m_reg | m_latch, CHRRAM);
}
#endif
- return m_nt_access[page][offset & 0x3ff];
+ return device_nes_cart_interface::nt_r(offset);
}
void nes_oekakids_device::update_chr()
@@ -247,7 +241,7 @@ void nes_oekakids_device::ppu_latch(offs_t offset)
#if 0
if ((offset & 0x3000) == 0x2000)
{
- m_latch = (offset & 0x300) >> 8;
+ m_latch = BIT(offset, 8, 2);
update_chr();
}
#endif
@@ -255,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;
@@ -281,36 +275,33 @@ 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
-------------------------------------------------*/
-void nes_fcg_device::device_timer(emu_timer &timer, device_timer_id id, int param, void *ptr)
+TIMER_CALLBACK_MEMBER(nes_fcg_device::irq_timer_tick)
{
- if (id == TIMER_IRQ)
+ if (m_irq_enable)
{
- if (m_irq_enable)
+ // 16bit counter, IRQ fired when the counter goes from 1 to 0
+ // after firing, the counter is *not* reloaded, but next clock
+ // counter wraps around from 0 to 0xffff
+ if (!m_irq_count)
+ m_irq_count = 0xffff;
+ else
+ m_irq_count--;
+
+ if (!m_irq_count)
{
- // 16bit counter, IRQ fired when the counter goes from 1 to 0
- // after firing, the counter is *not* reloaded, but next clock
- // counter wraps around from 0 to 0xffff
- if (!m_irq_count)
- m_irq_count = 0xffff;
- else
- m_irq_count--;
-
- if (!m_irq_count)
- {
- set_irq_line(ASSERT_LINE);
- m_irq_enable = 0;
- }
+ set_irq_line(ASSERT_LINE);
+ m_irq_enable = 0;
}
}
}
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)
{
@@ -341,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);
@@ -363,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)
{
@@ -380,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
@@ -393,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)
@@ -415,7 +406,7 @@ void nes_lz93d50_24c02_device::device_add_mconfig(machine_config &config)
iNES: mappers 153
- In MESS: Supported
+ In MAME: Supported
-------------------------------------------------*/
@@ -432,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/bandai.h b/src/devices/bus/nes/bandai.h
index e7cb0a1d0cd..ea3951b78a6 100644
--- a/src/devices/bus/nes/bandai.h
+++ b/src/devices/bus/nes/bandai.h
@@ -29,7 +29,7 @@ public:
protected:
// device-level overrides
- virtual void device_start() override;
+ virtual void device_start() override ATTR_COLD;
void update_chr();
@@ -45,19 +45,18 @@ public:
// construction/destruction
nes_fcg_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
- virtual void device_timer(emu_timer &timer, device_timer_id id, int param, void *ptr) override;
void fcg_write(offs_t offset, uint8_t data);
virtual void write_m(offs_t offset, uint8_t data) override;
virtual void pcb_reset() override;
protected:
- static constexpr device_timer_id TIMER_IRQ = 0;
-
nes_fcg_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_start() override ATTR_COLD;
+
+ TIMER_CALLBACK_MEMBER(irq_timer_tick);
uint16_t m_irq_count;
int m_irq_enable;
@@ -74,7 +73,6 @@ public:
// construction/destruction
nes_lz93d50_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
- // device-level overrides
virtual void write_h(offs_t offset, uint8_t data) override { fcg_write(offset, data); }
protected:
@@ -99,9 +97,9 @@ protected:
nes_lz93d50_24c01_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_start() override ATTR_COLD;
- virtual void device_add_mconfig(machine_config &config) override;
+ virtual void device_add_mconfig(machine_config &config) override ATTR_COLD;
// TODO: fix EEPROM I/O emulation
required_device<i2cmem_device> m_i2cmem;
@@ -119,7 +117,7 @@ public:
protected:
// device-level overrides
- virtual void device_add_mconfig(machine_config &config) override;
+ virtual void device_add_mconfig(machine_config &config) override ATTR_COLD;
};
@@ -139,7 +137,7 @@ public:
protected:
// device-level overrides
- virtual void device_start() override;
+ virtual void device_start() override ATTR_COLD;
void set_prg();
uint8_t m_reg[5];
diff --git a/src/devices/bus/nes/batlab.cpp b/src/devices/bus/nes/batlab.cpp
new file mode 100644
index 00000000000..3a9df33a3cf
--- /dev/null
+++ b/src/devices/bus/nes/batlab.cpp
@@ -0,0 +1,256 @@
+// license:BSD-3-Clause
+// copyright-holders:kmg
+/***********************************************************************************************************
+
+
+ NES/Famicom cartridge emulation for Batlab Electronics and related PCBs
+
+
+ Here we emulate the following homebrew PCBs
+
+ * Batlab BATMAP-000 [mapper 399]
+ * Batlab BATMAP-SRR-X [mapper 413]
+
+ ***********************************************************************************************************/
+
+
+#include "emu.h"
+#include "batlab.h"
+
+#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 (LOG_GENERAL)
+#else
+#define VERBOSE (0)
+#endif
+#include "logmacro.h"
+
+
+//-------------------------------------------------
+// constructor
+//-------------------------------------------------
+
+DEFINE_DEVICE_TYPE(NES_BATMAP_000, nes_batmap_000_device, "nes_batmap_000", "NES Cart Batlab BATMAP-000 PCB")
+DEFINE_DEVICE_TYPE(NES_BATMAP_SRRX, nes_batmap_srrx_device, "nes_batmap_srrx", "NES Cart Batlab BATMAP-SRR-X PCB")
+
+
+nes_batmap_000_device::nes_batmap_000_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock)
+ : nes_txrom_device(mconfig, NES_BATMAP_000, tag, owner, clock)
+{
+}
+
+nes_batmap_srrx_device::nes_batmap_srrx_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock)
+ : nes_nrom_device(mconfig, NES_BATMAP_SRRX, tag, owner, clock), m_reg(0), m_dpcm_addr(0), m_dpcm_ctrl(0), m_irq_count(0), m_irq_count_latch(0), m_irq_enable(0)
+{
+}
+
+
+
+void nes_batmap_000_device::pcb_reset()
+{
+ mmc3_common_initialize(0x0f, 0xff, 0);
+
+ prg16_89ab(0);
+ prg16_cdef(m_prg_chunks - 1);
+ chr8(0, CHRRAM);
+}
+
+void nes_batmap_srrx_device::device_start()
+{
+ common_start();
+ save_item(NAME(m_reg));
+ save_item(NAME(m_dpcm_addr));
+ save_item(NAME(m_dpcm_ctrl));
+ save_item(NAME(m_irq_enable));
+ save_item(NAME(m_irq_count));
+ save_item(NAME(m_irq_count_latch));
+}
+
+void nes_batmap_srrx_device::pcb_reset()
+{
+ prg8_89(0);
+ prg8_ab(0);
+ prg8_cd(3); // 0xd000-0xffff fixed PRG bank
+ prg8_ef(4);
+ chr4_0(0, CHRROM);
+ chr4_4(0x3d, CHRROM); // fixed CHR bank
+
+ m_reg = 0;
+ m_dpcm_addr = 0;
+ m_dpcm_ctrl = 0;
+
+ m_irq_enable = 0;
+ m_irq_count = m_irq_count_latch = 0;
+}
+
+
+/*-------------------------------------------------
+ mapper specific handlers
+ -------------------------------------------------*/
+
+/*-------------------------------------------------
+
+ Batlab BATMAP-000 board
+
+ Games: Star Versus, Anamanaguchi carts? (not dumped?)
+
+ These boards have been seen using a Xilinx XC9572XL CPLD.
+ This provides a clone of MMC3-style IRQ and mirroring
+ (not sure how it may differ) with simpler PRG/CHR banking.
+ Boards are marked as having 1MB PRG, swappable in 8K banks
+ at 0xa000 and 0xc000, and 32KB CHR, swappable in 4K banks.
+
+ NES 2.0: mapper 399
+
+ In MAME: Supported.
+
+ -------------------------------------------------*/
+
+void nes_batmap_000_device::write_h(offs_t offset, u8 data)
+{
+ LOG("batmap_000 write_h, offset: %04x, data: %02x\n", offset, data);
+
+ switch (offset & 0x6001)
+ {
+ case 0x0000:
+ chr4_x(BIT(data, 7) << 2, data & 0x07, CHRRAM);
+ break;
+ case 0x0001:
+ prg8_x(BIT(data, 7) + 1, data & 0x7f);
+ break;
+ default:
+ txrom_write(offset, data);
+ break;
+ }
+}
+
+/*-------------------------------------------------
+
+ Batlab BATMAP-SRR-X board
+
+ Games: Super Russian Roulette
+
+ According to dumper it uses a CPLD. This provides PRG
+ and CHR banking, MMC3-like scanline IRQ, and access
+ to an 8MB ROM of DPCM for streaming digitized speech.
+
+ The memory map for reads is as follows:
+
+ 0x4800~ read DPCM data byte (and data pointer++)
+ 0x5000~ 4K fixed to PRG 0x1000
+ 0x6000~ 8K, reg 0
+ 0x8000~ 8K, reg 1
+ 0xA000~ 8K, reg 2
+ 0xC000~ Same as 0x4800
+ 0xD000~ 12K fixed to PRG 0x7000-0xffff
+
+ The DPCM ROM data pointer is at least 23-bits wide
+ and is written serially, by bit, at 0xc000 using
+ the MSB of each write. There is a control register (?)
+ at 0xd000. It's not clear what it does since for each
+ complete sound played it is always written with the
+ sequence 0x01, 0x00, 0x02. Other sources say bit 1 is
+ a flag that turns on/off incrementing of the pointer.
+
+ NES 2.0: mapper 413
+
+ In MAME: Supported.
+
+ -------------------------------------------------*/
+
+// IRQ based on our MMC3 implementation, details for SRR are unclear
+void nes_batmap_srrx_device::hblank_irq(int scanline, bool vblank, bool blanked)
+{
+ if (scanline < ppu2c0x_device::BOTTOM_VISIBLE_SCANLINE)
+ {
+ if (!m_irq_count)
+ m_irq_count = m_irq_count_latch;
+ else
+ m_irq_count--;
+
+ if (m_irq_enable && !blanked && !m_irq_count)
+ {
+ LOG("irq fired, scanline: %d\n", scanline);
+ set_irq_line(ASSERT_LINE);
+ }
+ }
+}
+
+u8 nes_batmap_srrx_device::read_dpcm()
+{
+ m_dpcm_addr &= m_misc_rom_size - 1;
+ return m_misc_rom[m_dpcm_addr++];
+}
+
+u8 nes_batmap_srrx_device::read_l(offs_t offset)
+{
+ LOGMASKED(LOG_HIFREQ, "batmap_srrx read_l, offset: %04x", offset);
+
+ offset += 0x100;
+ switch (offset & 0x1800)
+ {
+ case 0x0000:
+ return get_open_bus();
+ case 0x0800:
+ return read_dpcm();
+ default:
+ return m_prg[offset]; // fixed to second 4K
+ }
+}
+
+u8 nes_batmap_srrx_device::read_m(offs_t 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("batmap_srrx read_h, offset: %04x", offset);
+
+ if ((offset & 0x7000) == 0x4000)
+ return read_dpcm();
+ else
+ return hi_access_rom(offset);
+}
+
+void nes_batmap_srrx_device::write_h(offs_t offset, u8 data)
+{
+ LOG("batmap_srrx write_h, offset: %04x, data: %02x\n", offset, data);
+
+ switch (offset & 0x7000)
+ {
+ case 0x0000:
+ m_irq_count_latch = data;
+ break;
+ case 0x1000:
+ m_irq_count = 0;
+ break;
+ case 0x2000:
+ case 0x3000:
+ m_irq_enable = BIT(offset, 12);
+ if (!m_irq_enable)
+ set_irq_line(CLEAR_LINE);
+ break;
+ case 0x4000:
+ m_dpcm_addr = m_dpcm_addr << 1 | data >> 7;
+ break;
+ case 0x5000:
+ m_dpcm_ctrl = data;
+ break;
+ case 0x6000:
+ case 0x7000:
+ switch (data >> 6)
+ {
+ case 0: m_reg = data & 0x3f; break;
+ case 1: prg8_89(data & 0x3f); break;
+ case 2: prg8_ab(data & 0x3f); break;
+ case 3: chr4_0(data & 0x3f, CHRROM); break;
+ }
+ break;
+ }
+}
diff --git a/src/devices/bus/nes/batlab.h b/src/devices/bus/nes/batlab.h
new file mode 100644
index 00000000000..905fe1ab3d9
--- /dev/null
+++ b/src/devices/bus/nes/batlab.h
@@ -0,0 +1,60 @@
+// license:BSD-3-Clause
+// copyright-holders:kmg
+#ifndef MAME_BUS_NES_BATLAB_H
+#define MAME_BUS_NES_BATLAB_H
+
+#pragma once
+
+#include "mmc3.h"
+
+
+// ======================> nes_batmap_000_device
+
+class nes_batmap_000_device : public nes_txrom_device
+{
+public:
+ // construction/destruction
+ nes_batmap_000_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock);
+
+ virtual void write_h(offs_t offset, u8 data) override;
+
+ virtual void pcb_reset() override;
+};
+
+
+// ======================> nes_batmap_srrx_device
+
+class nes_batmap_srrx_device : public nes_nrom_device
+{
+public:
+ // construction/destruction
+ nes_batmap_srrx_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock);
+
+ virtual u8 read_l(offs_t offset) override;
+ virtual u8 read_m(offs_t offset) override;
+ virtual u8 read_h(offs_t offset) override;
+ virtual void write_h(offs_t offset, u8 data) override;
+
+ virtual void hblank_irq(int scanline, bool vblank, bool blanked) override;
+ virtual void pcb_reset() override;
+
+protected:
+ // device-level overrides
+ virtual void device_start() override ATTR_COLD;
+
+private:
+ u8 read_dpcm();
+ u8 m_reg;
+ u32 m_dpcm_addr;
+ u8 m_dpcm_ctrl;
+
+ u16 m_irq_count, m_irq_count_latch;
+ int m_irq_enable;
+};
+
+
+// device type definition
+DECLARE_DEVICE_TYPE(NES_BATMAP_000, nes_batmap_000_device)
+DECLARE_DEVICE_TYPE(NES_BATMAP_SRRX, nes_batmap_srrx_device)
+
+#endif // MAME_BUS_NES_BATLAB_H
diff --git a/src/devices/bus/nes/benshieng.cpp b/src/devices/bus/nes/benshieng.cpp
index 2b3c7818f58..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"
//-------------------------------------------------
@@ -31,9 +30,8 @@
DEFINE_DEVICE_TYPE(NES_BENSHIENG, nes_benshieng_device, "nes_benshieng", "NES Cart Benshieng PCB")
-nes_benshieng_device::nes_benshieng_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
- : nes_nrom_device(mconfig, NES_BENSHIENG, tag, owner, clock)
- , m_dipsetting(0)
+nes_benshieng_device::nes_benshieng_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock)
+ : nes_nrom_device(mconfig, NES_BENSHIENG, tag, owner, clock), m_dipsetting(0)
{
}
@@ -44,20 +42,17 @@ void nes_benshieng_device::device_start()
{
common_start();
save_item(NAME(m_dipsetting));
- save_item(NAME(m_mmc_prg_bank));
- save_item(NAME(m_mmc_vrom_bank));
}
void nes_benshieng_device::pcb_reset()
{
- m_dipsetting = 0;
+ for (int i = 0; i < 4; i++)
+ {
+ prg8_x(i, 0x0f);
+ chr2_x(2 * i, 0x00, CHRROM);
+ }
- m_mmc_prg_bank[0] = 0xff;
- m_mmc_prg_bank[1] = 0xff;
- m_mmc_prg_bank[2] = 0xff;
- m_mmc_prg_bank[3] = 0xff;
- memset(m_mmc_vrom_bank, 0, sizeof(m_mmc_vrom_bank));
- update_banks();
+ m_dipsetting = 0;
}
@@ -72,35 +67,27 @@ void nes_benshieng_device::pcb_reset()
Games: a few 4 in 1 multicarts
- -------------------------------------------------*/
+ NES 2.0: mapper 286
-void nes_benshieng_device::update_banks()
-{
- prg8_89(m_mmc_prg_bank[0]);
- prg8_ab(m_mmc_prg_bank[1]);
- prg8_cd(m_mmc_prg_bank[2]);
- prg8_ef(m_mmc_prg_bank[3]);
- chr2_0(m_mmc_vrom_bank[0], CHRROM);
- chr2_2(m_mmc_vrom_bank[1], CHRROM);
- chr2_4(m_mmc_vrom_bank[2], CHRROM);
- chr2_6(m_mmc_vrom_bank[3], CHRROM);
-}
+ -------------------------------------------------*/
-void nes_benshieng_device::write_h(offs_t offset, uint8_t data)
+void nes_benshieng_device::write_h(offs_t offset, u8 data)
{
- uint8_t helper = (offset & 0xc00) >> 10;
- 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);
+
switch (offset & 0x7000)
{
case 0x0000:
- m_mmc_vrom_bank[helper] = offset & 0x1f;
+ case 0x1000:
+ chr2_x(2 * bank, offset & 0x1f, CHRROM);
break;
case 0x2000:
- if (BIT(offset, m_dipsetting + 4)) // mmc_dipsetting is always zero atm, given we have no way to add cart-based DIPs
- m_mmc_prg_bank[helper] = offset & 0x0f;
+ case 0x3000:
+ if (BIT(offset, m_dipsetting + 4)) // m_dipsetting is always zero atm, given we have no way to add cart-based DIPs
+ prg8_x(bank, offset & 0x0f);
break;
}
- update_banks();
}
diff --git a/src/devices/bus/nes/benshieng.h b/src/devices/bus/nes/benshieng.h
index 599de5a6e9c..17598c6a3d2 100644
--- a/src/devices/bus/nes/benshieng.h
+++ b/src/devices/bus/nes/benshieng.h
@@ -14,21 +14,18 @@ class nes_benshieng_device : public nes_nrom_device
{
public:
// construction/destruction
- nes_benshieng_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
+ nes_benshieng_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock);
- virtual void write_h(offs_t offset, uint8_t data) override;
+ virtual void write_h(offs_t offset, u8 data) override;
virtual void pcb_reset() override;
protected:
// device-level overrides
- virtual void device_start() override;
+ virtual void device_start() override ATTR_COLD;
private:
- void update_banks();
- uint8_t m_dipsetting;
- uint8_t m_mmc_prg_bank[4];
- uint8_t m_mmc_vrom_bank[4];
+ u8 m_dipsetting;
};
diff --git a/src/devices/bus/nes/bootleg.cpp b/src/devices/bus/nes/bootleg.cpp
index d585a8df9de..4ce050033d5 100644
--- a/src/devices/bus/nes/bootleg.cpp
+++ b/src/devices/bus/nes/bootleg.cpp
@@ -13,7 +13,9 @@
TODO:
- review all PCBs and fix the starting banks (which are often the main problem of not working games)
- - investigate pcbs listed in FCEUmm but with apparently no dumps available (LE05 and LH53)
+ - SMB2 bootlegs all seem to have timing issues. This is apparent on worlds A-D as the bottom of the
+ world letter scrolls. Hardware footage of the mapper 50 version shows the letter bottoms flickering
+ (though it could be a video/compression artifact).
***********************************************************************************************************/
@@ -22,57 +24,61 @@
#include "bootleg.h"
#include "video/ppu2c0x.h" // this has to be included so that IRQ functions can access ppu2c0x_device::BOTTOM_VISIBLE_SCANLINE
-#include "screen.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"
//-------------------------------------------------
// constructor
//-------------------------------------------------
-DEFINE_DEVICE_TYPE(NES_AX5705, nes_ax5705_device, "nes_ax5705", "NES Cart AX5705 PCB")
DEFINE_DEVICE_TYPE(NES_SC127, nes_sc127_device, "nes_sc127", "NES Cart SC-127 PCB")
DEFINE_DEVICE_TYPE(NES_MARIOBABY, nes_mbaby_device, "nes_mbaby", "NES Cart Mario Baby Bootleg PCB")
DEFINE_DEVICE_TYPE(NES_ASN, nes_asn_device, "nes_asn", "NES Cart Ai Senshi Nicol Bootleg PCB")
DEFINE_DEVICE_TYPE(NES_SMB3PIRATE, nes_smb3p_device, "nes_smb3p", "NES Cart Super Mario Bros. 3 Pirate PCB")
+DEFINE_DEVICE_TYPE(NES_BTL_CONTRAJ, nes_btl_cj_device, "nes_btl_cj", "NES Cart Contra Japan Pirate PCB")
DEFINE_DEVICE_TYPE(NES_BTL_DNINJA, nes_btl_dn_device, "nes_btl_dn", "NES Cart DragonNinja Pirate PCB")
-DEFINE_DEVICE_TYPE(NES_WHIRLWIND_2706, nes_whirl2706_device, "nes_whirl2706", "NES Cart Whilwind 2706 PCB")
DEFINE_DEVICE_TYPE(NES_SMB2J, nes_smb2j_device, "nes_smb2j", "NES Cart Super Mario Bros. 2 Jpn PCB")
DEFINE_DEVICE_TYPE(NES_SMB2JA, nes_smb2ja_device, "nes_smb2ja", "NES Cart Super Mario Bros. 2 Jpn (Alt) PCB")
DEFINE_DEVICE_TYPE(NES_SMB2JB, nes_smb2jb_device, "nes_smb2jb", "NES Cart Super Mario Bros. 2 Jpn (Alt 2) PCB")
+DEFINE_DEVICE_TYPE(NES_N32_4IN1, nes_n32_4in1_device, "nes_n32_4in1", "NES Cart N-32 4 in 1 PCB")
+DEFINE_DEVICE_TYPE(NES_0353, nes_0353_device, "nes_0353", "NES Cart 0353 PCB")
DEFINE_DEVICE_TYPE(NES_09034A, nes_09034a_device, "nes_09034a", "NES Cart 09-034A PCB")
+DEFINE_DEVICE_TYPE(NES_L001, nes_l001_device, "nes_l001", "NES Cart L-001 PCB")
+DEFINE_DEVICE_TYPE(NES_BATMANFS, nes_batmanfs_device, "nes_batmanfs", "NES Cart Batman Pirate PCB")
+DEFINE_DEVICE_TYPE(NES_PALTHENA, nes_palthena_device, "nes_palthena", "NES Cart Palthena no Kagami Pirate PCB")
DEFINE_DEVICE_TYPE(NES_TOBIDASE, nes_tobidase_device, "nes_tobidase", "NES Cart Tobidase Daisakusen Pirate PCB")
-DEFINE_DEVICE_TYPE(NES_LH32, nes_lh32_device, "nes_lh32", "NES Cart LH-32 Pirate PCB")
-DEFINE_DEVICE_TYPE(NES_LH10, nes_lh10_device, "nes_lh10", "NES Cart LH-10 Pirate PCB")
-DEFINE_DEVICE_TYPE(NES_LH53, nes_lh53_device, "nes_lh53", "NES Cart LH-53 Pirate PCB")
+DEFINE_DEVICE_TYPE(NES_DH08, nes_dh08_device, "nes_dh08", "NES Cart DH-08 Pirate PCB")
+DEFINE_DEVICE_TYPE(NES_LE05, nes_le05_device, "nes_le05", "NES Cart LE05 Pirate PCB")
+DEFINE_DEVICE_TYPE(NES_LG25, nes_lg25_device, "nes_lg25", "NES Cart LG25 Pirate PCB")
+DEFINE_DEVICE_TYPE(NES_LH10, nes_lh10_device, "nes_lh10", "NES Cart LH10 Pirate PCB")
+DEFINE_DEVICE_TYPE(NES_LH28_LH54, nes_lh28_lh54_device, "nes_lh28_lh54", "NES Cart LH28/LH54 Pirate PCBs")
+DEFINE_DEVICE_TYPE(NES_LH31, nes_lh31_device, "nes_lh31", "NES Cart LH31 Pirate PCB")
+DEFINE_DEVICE_TYPE(NES_LH32, nes_lh32_device, "nes_lh32", "NES Cart LH32 Pirate PCB")
+DEFINE_DEVICE_TYPE(NES_LH42, nes_lh42_device, "nes_lh42", "NES Cart LH42 Pirate PCB")
+DEFINE_DEVICE_TYPE(NES_LH51, nes_lh51_device, "nes_lh51", "NES Cart LH51 Pirate PCB")
+DEFINE_DEVICE_TYPE(NES_LH53, nes_lh53_device, "nes_lh53", "NES Cart LH53 Pirate PCB")
DEFINE_DEVICE_TYPE(NES_2708, nes_2708_device, "nes_2708", "NES Cart BTL-2708 Pirate PCB")
DEFINE_DEVICE_TYPE(NES_AC08, nes_ac08_device, "nes_ac08", "NES Cart AC08 Pirate PCB")
-DEFINE_DEVICE_TYPE(NES_UNL_BB, nes_unl_bb_device, "nes_unl_bb", "NES Cart FDS+CHR Pirate PCB")
DEFINE_DEVICE_TYPE(NES_MMALEE, nes_mmalee_device, "nes_mmalee", "NES Cart Super Mario Bros. Malee 2 Pirate PCB")
-DEFINE_DEVICE_TYPE(NES_SHUIGUAN, nes_shuiguan_device, "nes_shuiguan", "NES Cart Shui Guan Pipe Pirate PCB")
DEFINE_DEVICE_TYPE(NES_RT01, nes_rt01_device, "nes_rt01", "NES Cart RT-01 PCB")
+DEFINE_DEVICE_TYPE(NES_YUNG08, nes_yung08_device, "nes_yung08", "NES Cart Super Mario Bros. 2 YUNG-08 PCB")
-nes_ax5705_device::nes_ax5705_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
- : nes_nrom_device(mconfig, NES_AX5705, tag, owner, clock)
-{
-}
-
nes_sc127_device::nes_sc127_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
: nes_nrom_device(mconfig, NES_SC127, tag, owner, clock), m_irq_count(0), m_irq_enable(0)
{
}
-nes_mbaby_device::nes_mbaby_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
- : nes_nrom_device(mconfig, NES_MARIOBABY, tag, owner, clock), m_latch(0), m_irq_enable(0), irq_timer(nullptr)
+nes_mbaby_device::nes_mbaby_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock)
+ : nes_nrom_device(mconfig, NES_MARIOBABY, tag, owner, clock), m_irq_count(0), m_irq_enable(0), m_latch(0), irq_timer(nullptr)
{
}
@@ -81,38 +87,68 @@ nes_asn_device::nes_asn_device(const machine_config &mconfig, const char *tag, d
{
}
-nes_smb3p_device::nes_smb3p_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
+nes_smb3p_device::nes_smb3p_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock)
: nes_nrom_device(mconfig, NES_SMB3PIRATE, tag, owner, clock), m_irq_count(0), m_irq_enable(0), irq_timer(nullptr)
{
}
-nes_btl_dn_device::nes_btl_dn_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
- : nes_nrom_device(mconfig, NES_BTL_DNINJA, tag, owner, clock), m_irq_count(0)
+nes_btl_cj_device::nes_btl_cj_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock)
+ : nes_nrom_device(mconfig, NES_BTL_CONTRAJ, tag, owner, clock)
{
}
-nes_whirl2706_device::nes_whirl2706_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
- : nes_nrom_device(mconfig, NES_WHIRLWIND_2706, tag, owner, clock), m_latch(0)
+nes_btl_dn_device::nes_btl_dn_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
+ : nes_nrom_device(mconfig, NES_BTL_DNINJA, tag, owner, clock), m_irq_count(0)
{
}
-nes_smb2j_device::nes_smb2j_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
+nes_smb2j_device::nes_smb2j_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock)
: nes_nrom_device(mconfig, NES_SMB2J, tag, owner, clock), m_irq_count(0), m_irq_enable(0), irq_timer(nullptr)
{
}
-nes_smb2ja_device::nes_smb2ja_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
+nes_smb2ja_device::nes_smb2ja_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock)
: nes_nrom_device(mconfig, NES_SMB2JA, tag, owner, clock), m_irq_count(0), m_irq_enable(0), irq_timer(nullptr)
{
}
-nes_smb2jb_device::nes_smb2jb_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
- : nes_nrom_device(mconfig, NES_SMB2JB, tag, owner, clock), m_irq_count(0), m_irq_enable(0), irq_timer(nullptr)
+nes_smb2jb_device::nes_smb2jb_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, u32 clock, u8 bank67)
+ : nes_nrom_device(mconfig, type, tag, owner, clock), m_irq_count(0), m_irq_enable(0), m_reg(0), m_bank67(bank67), irq_timer(nullptr)
+{
+}
+
+nes_smb2jb_device::nes_smb2jb_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock)
+ : nes_smb2jb_device(mconfig, NES_SMB2JB, tag, owner, clock, 0x0f)
+{
+}
+
+nes_n32_4in1_device::nes_n32_4in1_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock)
+ : nes_smb2jb_device(mconfig, NES_N32_4IN1, tag, owner, clock, 0x07)
+{
+}
+
+nes_0353_device::nes_0353_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock)
+ : nes_nrom_device(mconfig, NES_0353, tag, owner, clock), m_reg(0)
+{
+}
+
+nes_09034a_device::nes_09034a_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock)
+ : nes_nrom_device(mconfig, NES_09034A, tag, owner, clock), m_irq_count(0), m_irq_enable(0), m_reg(0), irq_timer(nullptr)
+{
+}
+
+nes_l001_device::nes_l001_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock)
+ : nes_nrom_device(mconfig, NES_L001, tag, owner, clock), m_irq_count(0), irq_timer(nullptr)
+{
+}
+
+nes_batmanfs_device::nes_batmanfs_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock)
+ : nes_nrom_device(mconfig, NES_BATMANFS, tag, owner, clock), m_irq_count(0), m_irq_enable(0), irq_timer(nullptr)
{
}
-nes_09034a_device::nes_09034a_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
- : nes_nrom_device(mconfig, NES_09034A, tag, owner, clock), m_reg(0)
+nes_palthena_device::nes_palthena_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock)
+ : nes_nrom_device(mconfig, NES_PALTHENA, tag, owner, clock), m_reg(0)
{
}
@@ -121,16 +157,56 @@ nes_tobidase_device::nes_tobidase_device(const machine_config &mconfig, const ch
{
}
+nes_whirlwind_device::nes_whirlwind_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, u32 clock)
+ : nes_nrom_device(mconfig, type, tag, owner, clock), m_reg(0)
+{
+}
+
+nes_dh08_device::nes_dh08_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock)
+ : nes_whirlwind_device(mconfig, NES_DH08, tag, owner, clock)
+{
+}
+
+nes_le05_device::nes_le05_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock)
+ : nes_whirlwind_device(mconfig, NES_LE05, tag, owner, clock)
+{
+}
+
+nes_lh28_lh54_device::nes_lh28_lh54_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock)
+ : nes_whirlwind_device(mconfig, NES_LH28_LH54, tag, owner, clock)
+{
+}
+
+nes_lh31_device::nes_lh31_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock)
+ : nes_whirlwind_device(mconfig, NES_LH31, tag, owner, clock)
+{
+}
+
nes_lh32_device::nes_lh32_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
: nes_nrom_device(mconfig, NES_LH32, tag, owner, clock), m_latch(0)
{
}
-nes_lh10_device::nes_lh10_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
+nes_lh42_device::nes_lh42_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock)
+ : nes_nrom_device(mconfig, NES_LH42, tag, owner, clock), m_latch(0)
+{
+}
+
+nes_lg25_device::nes_lg25_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock)
+ : nes_nrom_device(mconfig, NES_LG25, tag, owner, clock), m_latch(0)
+{
+}
+
+nes_lh10_device::nes_lh10_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock)
: nes_nrom_device(mconfig, NES_LH10, tag, owner, clock), m_latch(0)
{
}
+nes_lh51_device::nes_lh51_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock)
+ : nes_nrom_device(mconfig, NES_LH51, tag, owner, clock)
+{
+}
+
nes_lh53_device::nes_lh53_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
: nes_nrom_device(mconfig, NES_LH53, tag, owner, clock), m_irq_count(0), m_irq_enable(0), m_reg(0), irq_timer(nullptr)
{
@@ -146,50 +222,23 @@ nes_ac08_device::nes_ac08_device(const machine_config &mconfig, const char *tag,
{
}
-nes_unl_bb_device::nes_unl_bb_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
- : nes_nrom_device(mconfig, NES_UNL_BB, tag, owner, clock)
-{
-}
-
nes_mmalee_device::nes_mmalee_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
: nes_nrom_device(mconfig, NES_MMALEE, tag, owner, clock)
{
}
-nes_shuiguan_device::nes_shuiguan_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
- : nes_nrom_device(mconfig, NES_SHUIGUAN, tag, owner, clock), m_irq_count(0), m_irq_enable(0), irq_timer(nullptr)
-{
-}
-
nes_rt01_device::nes_rt01_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
: nes_nrom_device(mconfig, NES_RT01, tag, owner, clock)
{
}
-
-
-
-void nes_ax5705_device::device_start()
+nes_yung08_device::nes_yung08_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock)
+ : nes_nrom_device(mconfig, NES_YUNG08, tag, owner, clock), m_irq_count(0), m_irq_latch(0), irq_timer(nullptr)
{
- common_start();
- save_item(NAME(m_mmc_prg_bank));
- save_item(NAME(m_mmc_vrom_bank));
}
-void nes_ax5705_device::pcb_reset()
-{
- m_chr_source = m_vrom_chunks ? CHRROM : CHRRAM;
- chr8(0, m_chr_source);
- m_mmc_prg_bank[0] = 0;
- m_mmc_prg_bank[1] = 1;
- prg8_89(m_mmc_prg_bank[0]);
- prg8_ab(m_mmc_prg_bank[1]);
- prg8_cd(0xfe);
- prg8_ef(0xff);
- memset(m_mmc_vrom_bank, 0, sizeof(m_mmc_vrom_bank));
-}
void nes_sc127_device::device_start()
{
@@ -200,7 +249,6 @@ void nes_sc127_device::device_start()
void nes_sc127_device::pcb_reset()
{
- m_chr_source = m_vrom_chunks ? CHRROM : CHRRAM;
prg32(0xff);
chr8(0, m_chr_source);
@@ -211,21 +259,20 @@ void nes_sc127_device::pcb_reset()
void nes_mbaby_device::device_start()
{
common_start();
- irq_timer = timer_alloc(TIMER_IRQ);
- irq_timer->reset();
- timer_freq = clocks_to_attotime(24576);
+ irq_timer = timer_alloc(FUNC(nes_mbaby_device::irq_timer_tick), this);
+ irq_timer->adjust(attotime::zero, 0, clocks_to_attotime(1));
save_item(NAME(m_irq_enable));
+ save_item(NAME(m_irq_count));
save_item(NAME(m_latch));
}
void nes_mbaby_device::pcb_reset()
{
- m_chr_source = m_vrom_chunks ? CHRROM : CHRRAM;
prg32((m_prg_chunks - 1) >> 1);
- chr8(0, m_chr_source);
m_irq_enable = 0;
+ m_irq_count = 0;
m_latch = 0;
}
@@ -237,7 +284,6 @@ void nes_asn_device::device_start()
void nes_asn_device::pcb_reset()
{
- m_chr_source = m_vrom_chunks ? CHRROM : CHRRAM;
prg32((m_prg_chunks - 1) >> 1);
chr8(0, m_chr_source);
@@ -247,61 +293,70 @@ void nes_asn_device::pcb_reset()
void nes_smb3p_device::device_start()
{
common_start();
- irq_timer = timer_alloc(TIMER_IRQ);
+ irq_timer = timer_alloc(FUNC(nes_smb3p_device::irq_timer_tick), this);
irq_timer->adjust(attotime::zero, 0, clocks_to_attotime(1));
save_item(NAME(m_irq_enable));
save_item(NAME(m_irq_count));
}
-void nes_smb3p_device::pcb_reset()
+void nes_smb3p_device::pcb_start(running_machine &machine, u8 *ciram_ptr, bool cart_mounted)
{
- m_chr_source = m_vrom_chunks ? CHRROM : CHRRAM;
- prg8_89((m_prg_chunks << 1) - 1);
- prg8_ab(0);
- prg8_cd(0);
- prg8_ef((m_prg_chunks << 1) - 1);
- chr8(0, m_chr_source);
+ device_nes_cart_interface::pcb_start(machine, ciram_ptr, cart_mounted);
+ // registers reliably boot up with all 1s according to hardware tests
+ for (int i = 0; i < 4; i++)
+ prg8_x(i, 0x1f);
+}
- m_irq_enable = 0;
- m_irq_count = 0;
+void nes_smb3p_device::pcb_reset()
+{
+ // registers not cleared or initialized at reset
}
-void nes_btl_dn_device::device_start()
+void nes_batmanfs_device::device_start()
{
common_start();
+ irq_timer = timer_alloc(FUNC(nes_batmanfs_device::irq_timer_tick), this);
+ irq_timer->adjust(attotime::zero, 0, clocks_to_attotime(1));
+
+ save_item(NAME(m_irq_enable));
save_item(NAME(m_irq_count));
}
-void nes_btl_dn_device::pcb_reset()
+void nes_batmanfs_device::pcb_reset()
{
- m_chr_source = m_vrom_chunks ? CHRROM : CHRRAM;
- prg16_89ab(0);
- prg16_cdef(m_prg_chunks - 1);
- chr8(0, m_chr_source);
+ prg32((m_prg_chunks >> 1) - 1); // Last 8K bank is fixed, the rest are swappable
+ chr8(0, CHRROM);
+ m_irq_enable = 0;
m_irq_count = 0;
}
-void nes_whirl2706_device::device_start()
+void nes_btl_cj_device::pcb_reset()
+{
+ prg32((m_prg_chunks >> 1) - 1); // Last 8K bank is fixed, the rest are swappable
+ chr8(0, CHRROM);
+}
+
+void nes_btl_dn_device::device_start()
{
common_start();
- save_item(NAME(m_latch));
+ save_item(NAME(m_irq_count));
}
-void nes_whirl2706_device::pcb_reset()
+void nes_btl_dn_device::pcb_reset()
{
- m_chr_source = m_vrom_chunks ? CHRROM : CHRRAM;
- prg32(0xff);
+ prg16_89ab(0);
+ prg16_cdef(m_prg_chunks - 1);
chr8(0, m_chr_source);
- m_latch = 0;
+ m_irq_count = 0;
}
void nes_smb2j_device::device_start()
{
common_start();
- irq_timer = timer_alloc(TIMER_IRQ);
+ irq_timer = timer_alloc(FUNC(nes_smb2j_device::irq_timer_tick), this);
irq_timer->adjust(attotime::zero, 0, clocks_to_attotime(1));
save_item(NAME(m_irq_enable));
@@ -310,12 +365,11 @@ void nes_smb2j_device::device_start()
void nes_smb2j_device::pcb_reset()
{
- m_chr_source = m_vrom_chunks ? CHRROM : CHRRAM;
- chr8(0, m_chr_source);
prg8_89(1);
prg8_ab(0);
- prg8_cd(0);
+ prg8_cd(4); // switchable bank
prg8_ef(9);
+ chr8(0, CHRROM);
m_irq_enable = 0;
m_irq_count = 0;
@@ -324,7 +378,7 @@ void nes_smb2j_device::pcb_reset()
void nes_smb2ja_device::device_start()
{
common_start();
- irq_timer = timer_alloc(TIMER_IRQ);
+ irq_timer = timer_alloc(FUNC(nes_smb2ja_device::irq_timer_tick), this);
irq_timer->adjust(attotime::zero, 0, clocks_to_attotime(1));
save_item(NAME(m_irq_enable));
@@ -333,12 +387,11 @@ void nes_smb2ja_device::device_start()
void nes_smb2ja_device::pcb_reset()
{
- m_chr_source = m_vrom_chunks ? CHRROM : CHRRAM;
- prg8_89(0xfc);
- prg8_ab(0xfd);
- prg8_cd(0xfe);
- prg8_ef(0xff);
- chr8(0, m_chr_source);
+ prg8_89(4);
+ prg8_ab(5);
+ prg8_cd(0); // switchable bank
+ prg8_ef(7);
+ chr8(0, CHRROM);
m_irq_enable = 0;
m_irq_count = 0;
@@ -347,37 +400,98 @@ void nes_smb2ja_device::pcb_reset()
void nes_smb2jb_device::device_start()
{
common_start();
- irq_timer = timer_alloc(TIMER_IRQ);
+ irq_timer = timer_alloc(FUNC(nes_smb2jb_device::irq_timer_tick), this);
irq_timer->adjust(attotime::zero, 0, clocks_to_attotime(1));
save_item(NAME(m_irq_enable));
save_item(NAME(m_irq_count));
+ save_item(NAME(m_reg));
}
void nes_smb2jb_device::pcb_reset()
{
- m_chr_source = m_vrom_chunks ? CHRROM : CHRRAM;
prg8_89(0x08);
prg8_ab(0x09);
- prg8_cd(0);
+ prg8_cd(0); // switchable bank
prg8_ef(0x0b);
- chr8(0, m_chr_source);
m_irq_enable = 0;
m_irq_count = 0;
+ m_reg = 0;
+}
+
+void nes_n32_4in1_device::pcb_reset()
+{
+ // Powers up in menu, but soft reset does not touch banks (so each game returns to its own title). Is this correct?
+
+ m_irq_enable = 0;
+ m_irq_count = 0;
+ m_reg = 0;
+}
+
+void nes_0353_device::device_start()
+{
+ common_start();
+ save_item(NAME(m_reg));
+}
+
+void nes_0353_device::pcb_reset()
+{
+ prg32((m_prg_chunks >> 1) - 1); // fixed 32K bank
+
+ m_reg = 0;
}
void nes_09034a_device::device_start()
{
common_start();
+ irq_timer = timer_alloc(FUNC(nes_09034a_device::irq_timer_tick), this);
+ irq_timer->adjust(attotime::zero, 0, clocks_to_attotime(1));
+
+ save_item(NAME(m_irq_enable));
+ save_item(NAME(m_irq_count));
save_item(NAME(m_reg));
}
void nes_09034a_device::pcb_reset()
{
- m_chr_source = m_vrom_chunks ? CHRROM : CHRRAM;
prg32(0);
chr8(0, m_chr_source);
+
+ m_irq_enable = 0;
+ m_irq_count = 0;
+ m_reg = 0;
+}
+
+void nes_l001_device::device_start()
+{
+ common_start();
+ irq_timer = timer_alloc(FUNC(nes_l001_device::irq_timer_tick), this);
+ irq_timer->adjust(attotime::zero, 0, clocks_to_attotime(1));
+
+ save_item(NAME(m_irq_count));
+}
+
+void nes_l001_device::pcb_reset()
+{
+ prg32((m_prg_chunks >> 1) - 1);
+ chr8(0, CHRROM);
+
+ m_irq_count = 0;
+}
+
+void nes_palthena_device::device_start()
+{
+ common_start();
+ save_item(NAME(m_reg));
+}
+
+void nes_palthena_device::pcb_reset()
+{
+ prg8_89(0x0c);
+ // 0xa000-0xbfff switchable bank
+ prg16_cdef(m_prg_chunks - 1);
+
m_reg = 0;
}
@@ -389,13 +503,25 @@ void nes_tobidase_device::device_start()
void nes_tobidase_device::pcb_reset()
{
- m_chr_source = m_vrom_chunks ? CHRROM : CHRRAM;
prg32(2);
- chr8(0, m_chr_source);
m_latch = 0;
}
+void nes_whirlwind_device::device_start()
+{
+ common_start();
+ save_item(NAME(m_reg));
+}
+
+void nes_whirlwind_device::pcb_reset()
+{
+ prg32((m_prg_chunks >> 1) - 1); // upper PRG: banks are always fixed
+ chr8(0, m_chr_source);
+
+ m_reg = (m_prg_chunks << 1) - 1; // lower PRG: ProWres needs this fixed, others modify it
+}
+
void nes_lh32_device::device_start()
{
common_start();
@@ -404,36 +530,64 @@ void nes_lh32_device::device_start()
void nes_lh32_device::pcb_reset()
{
- chr8(0, CHRRAM);
-
prg32((m_prg_chunks - 1) >> 1);
// 0xc000-0xdfff reads/writes WRAM
m_latch = 0xf;
}
+void nes_lh42_device::device_start()
+{
+ common_start();
+ save_item(NAME(m_latch));
+}
+
+void nes_lh42_device::pcb_reset()
+{
+ prg16_89ab(0);
+ prg16_cdef(m_prg_chunks - 1); // Last 16K is fixed
+
+ m_latch = 0;
+}
+
+void nes_lg25_device::device_start()
+{
+ common_start();
+ save_item(NAME(m_latch));
+}
+
+void nes_lg25_device::pcb_reset()
+{
+ prg16_89ab(0);
+ prg16_cdef(m_prg_chunks - 1); // Last 16K is fixed
+
+ m_latch = 0;
+}
+
void nes_lh10_device::device_start()
{
common_start();
save_item(NAME(m_latch));
- save_item(NAME(m_reg));
}
void nes_lh10_device::pcb_reset()
{
- chr8(0, CHRRAM);
-
prg8_89(0);
prg8_ab(0);
// 0xc000-0xdfff reads/writes WRAM
- prg8_ef(0xff);
- memset(m_reg, 0, sizeof(m_reg));
+ prg8_ef((m_prg_chunks << 1) - 1);
+
m_latch = 0;
}
+void nes_lh51_device::pcb_reset()
+{
+ prg32((m_prg_chunks >> 1) - 1); // first 8K is switchable, the rest fixed
+}
+
void nes_lh53_device::device_start()
{
common_start();
- irq_timer = timer_alloc(TIMER_IRQ);
+ irq_timer = timer_alloc(FUNC(nes_lh53_device::irq_timer_tick), this);
irq_timer->adjust(attotime::zero, 0, clocks_to_attotime(1));
save_item(NAME(m_irq_enable));
@@ -443,11 +597,9 @@ void nes_lh53_device::device_start()
void nes_lh53_device::pcb_reset()
{
- chr8(0, CHRRAM);
-
prg8_89(0xc);
- prg8_ab(0xd); // last 2K are overlayed by WRAM
- prg8_cd(0xe); // first 6K are overlayed by WRAM
+ prg8_ab(0xd); // last 2K are overlaid by WRAM
+ prg8_cd(0xe); // first 6K are overlaid by WRAM
prg8_ef(0xf);
m_reg = 0;
m_irq_count = 0;
@@ -462,10 +614,8 @@ void nes_2708_device::device_start()
void nes_2708_device::pcb_reset()
{
- chr8(0, CHRRAM);
-
prg32(7);
- // the upper PRG banks never change, but there are 8K of WRAM overlayed to the ROM area based on reg1
+ // the upper PRG banks never change, but there are 8K of WRAM overlaid to the ROM area based on reg1
m_reg[0] = 0;
m_reg[1] = 0;
}
@@ -478,75 +628,40 @@ void nes_ac08_device::device_start()
void nes_ac08_device::pcb_reset()
{
- m_chr_source = m_vrom_chunks ? CHRROM : CHRRAM;
- chr8(0, m_chr_source);
prg32(0xff);
m_latch = 0xff;
}
-void nes_unl_bb_device::device_start()
-{
- common_start();
- save_item(NAME(m_reg));
-}
-
-void nes_unl_bb_device::pcb_reset()
-{
- chr8(0, CHRROM);
- prg32(0xff);
- // the upper PRG banks never change, but there are 8K of WRAM overlayed to the ROM area based on reg1
- m_reg[0] = 0xff;
- m_reg[1] = 0;
-}
-
-void nes_mmalee_device::device_start()
-{
- common_start();
-}
-
-void nes_mmalee_device::pcb_reset()
+void nes_rt01_device::pcb_reset()
{
- chr8(0, CHRROM);
- prg32(0);
+ chr2_0(0, CHRROM);
+ chr2_2(0, CHRROM);
+ chr2_4(0, CHRROM);
+ chr2_6(0, CHRROM);
+ prg16_89ab(0);
+ prg16_cdef(0);
}
-void nes_shuiguan_device::device_start()
+void nes_yung08_device::device_start()
{
common_start();
- irq_timer = timer_alloc(TIMER_IRQ);
- // always running and checking for IRQ every 114 cycles? or resetting every frame?
- irq_timer->adjust(attotime::zero, 0, clocks_to_attotime(114));
+ irq_timer = timer_alloc(FUNC(nes_yung08_device::irq_timer_tick), this);
+ irq_timer->adjust(attotime::zero, 0, clocks_to_attotime(1));
- save_item(NAME(m_irq_enable));
save_item(NAME(m_irq_count));
- save_item(NAME(m_mmc_vrom_bank));
+ save_item(NAME(m_irq_latch));
}
-void nes_shuiguan_device::pcb_reset()
+void nes_yung08_device::pcb_reset()
{
- m_chr_source = m_vrom_chunks ? CHRROM : CHRRAM;
- prg32((m_prg_chunks << 1) - 1);
- chr8(0, m_chr_source);
+ prg8_89(1);
+ prg8_ab(0);
+ prg8_cd(0); // switchable bank
+ prg8_ef(8);
+ chr8(0, CHRROM);
- m_irq_enable = 0;
m_irq_count = 0;
- memset(m_mmc_vrom_bank, 0, sizeof(m_mmc_vrom_bank));
-}
-
-
-void nes_rt01_device::device_start()
-{
- common_start();
-}
-
-void nes_rt01_device::pcb_reset()
-{
- chr2_0(0, CHRROM);
- chr2_2(0, CHRROM);
- chr2_4(0, CHRROM);
- chr2_6(0, CHRROM);
- prg16_89ab(0);
- prg16_cdef(0);
+ m_irq_latch = 0;
}
@@ -556,88 +671,17 @@ void nes_rt01_device::pcb_reset()
/*-------------------------------------------------
- Board UNL-AX5705
-
- Games: Super Mario Bros. Pocker Mali (Crayon Shin-chan pirate hack)
-
- In MESS: Supported
-
- -------------------------------------------------*/
-
-void nes_ax5705_device::set_prg()
-{
- prg8_89(m_mmc_prg_bank[0]);
- prg8_ab(m_mmc_prg_bank[1]);
-}
-
-void nes_ax5705_device::write_h(offs_t offset, uint8_t data)
-{
- uint8_t bank;
- LOG_MMC(("ax5705 write_h, offset: %04x, data: %02x\n", offset, data));
-
- switch (offset & 0x700f)
- {
- case 0x0000:
- m_mmc_prg_bank[0] = (data & 0x05) | ((data & 0x08) >> 2) | ((data & 0x02) << 2);
- set_prg();
- break;
- case 0x0008:
- set_nt_mirroring(BIT(data, 0) ? PPU_MIRROR_HORZ : PPU_MIRROR_VERT);
- break;
- case 0x2000:
- m_mmc_prg_bank[1] = (data & 0x05) | ((data & 0x08) >> 2) | ((data & 0x02) << 2);
- set_prg();
- break;
- /* CHR banks 0, 1, 4, 5 */
- case 0x2008:
- case 0x200a:
- case 0x4008:
- case 0x400a:
- bank = ((offset & 0x4000) ? 4 : 0) + ((offset & 0x0002) ? 1 : 0);
- m_mmc_vrom_bank[bank] = (m_mmc_vrom_bank[bank] & 0xf0) | (data & 0x0f);
- chr1_x(bank, m_mmc_vrom_bank[bank], CHRROM);
- break;
- case 0x2009:
- case 0x200b:
- case 0x4009:
- case 0x400b:
- bank = ((offset & 0x4000) ? 4 : 0) + ((offset & 0x0002) ? 1 : 0);
- m_mmc_vrom_bank[bank] = (m_mmc_vrom_bank[bank] & 0x0f) | ((data & 0x04) << 3) | ((data & 0x02) << 5) | ((data & 0x09) << 4);
- chr1_x(bank, m_mmc_vrom_bank[bank], CHRROM);
- break;
- /* CHR banks 2, 3, 6, 7 */
- case 0x4000:
- case 0x4002:
- case 0x6000:
- case 0x6002:
- bank = 2 + ((offset & 0x2000) ? 4 : 0) + ((offset & 0x0002) ? 1 : 0);
- m_mmc_vrom_bank[bank] = (m_mmc_vrom_bank[bank] & 0xf0) | (data & 0x0f);
- chr1_x(bank, m_mmc_vrom_bank[bank], CHRROM);
- break;
- case 0x4001:
- case 0x4003:
- case 0x6001:
- case 0x6003:
- bank = 2 + ((offset & 0x2000) ? 4 : 0) + ((offset & 0x0002) ? 1 : 0);
- m_mmc_vrom_bank[bank] = (m_mmc_vrom_bank[bank] & 0x0f) | ((data & 0x04) << 3) | ((data & 0x02) << 5) | ((data & 0x09) << 4);
- chr1_x(bank, m_mmc_vrom_bank[bank], CHRROM);
- break;
- }
-}
-
-/*-------------------------------------------------
-
SC-127 Board
Games: Wario World II (Kirby Hack)
iNES: mapper 35
- In MESS: Supported
+ In MAME: Supported.
-------------------------------------------------*/
-void nes_sc127_device::hblank_irq(int scanline, int vblank, int blanked)
+void nes_sc127_device::hblank_irq(int scanline, bool vblank, bool blanked)
{
if (scanline < ppu2c0x_device::BOTTOM_VISIBLE_SCANLINE && m_irq_enable)
{
@@ -645,8 +689,8 @@ void nes_sc127_device::hblank_irq(int scanline, int vblank, int blanked)
if (!blanked && (m_irq_count == 0))
{
- LOG_MMC(("irq fired, scanline: %d\n", scanline));
- hold_irq_line();
+ LOG("irq fired, scanline: %d\n", scanline);
+ set_irq_line(ASSERT_LINE);
m_irq_enable = 0;
}
}
@@ -654,7 +698,7 @@ void nes_sc127_device::hblank_irq(int scanline, int vblank, int 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)
{
@@ -681,6 +725,7 @@ void nes_sc127_device::write_h(offs_t offset, uint8_t data)
break;
case 0x4002:
m_irq_enable = 0;
+ set_irq_line(CLEAR_LINE);
break;
case 0x4003:
m_irq_enable = 1;
@@ -702,22 +747,24 @@ void nes_sc127_device::write_h(offs_t offset, uint8_t data)
iNES: mapper 42
- In MESS: Supported.
+ In MAME: Supported.
-------------------------------------------------*/
-void nes_mbaby_device::device_timer(emu_timer &timer, device_timer_id id, int param, void *ptr)
+TIMER_CALLBACK_MEMBER(nes_mbaby_device::irq_timer_tick)
{
- if (id == TIMER_IRQ)
+ if (m_irq_enable)
{
- hold_irq_line();
- irq_timer->adjust(attotime::never);
+ m_irq_count = (m_irq_count + 1) & 0x7fff; // unverified 15-bit counter based on FCEUX
+
+ if (m_irq_count >= 0x6000)
+ set_irq_line(ASSERT_LINE);
}
}
-void nes_mbaby_device::write_h(offs_t offset, uint8_t data)
+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)
{
@@ -730,25 +777,20 @@ void nes_mbaby_device::write_h(offs_t offset, uint8_t data)
set_nt_mirroring(BIT(data, 3) ? PPU_MIRROR_HORZ : PPU_MIRROR_VERT);
break;
case 0x02:
- /* Check if IRQ is being enabled */
- if (!m_irq_enable && (data & 0x02))
- {
- m_irq_enable = 1;
- irq_timer->adjust(timer_freq);
- }
- if (!(data & 0x02))
+ m_irq_enable = BIT(data, 1);
+ if (!m_irq_enable)
{
- m_irq_enable = 0;
- irq_timer->adjust(attotime::never);
+ m_irq_count = 0;
+ set_irq_line(CLEAR_LINE);
}
break;
}
}
}
-uint8_t nes_mbaby_device::read_m(offs_t offset)
+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)];
}
@@ -760,13 +802,13 @@ uint8_t nes_mbaby_device::read_m(offs_t offset)
iNES: mapper 42 with no IRQ and no NT, but CHR switch
- In MESS: Partially Supported.
+ In MAME: Partially supported.
-------------------------------------------------*/
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);
@@ -777,11 +819,10 @@ 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)];
}
-
/*-------------------------------------------------
BTL-SMB3
@@ -790,62 +831,46 @@ uint8_t nes_asn_device::read_m(offs_t offset)
iNES: mapper 106
- In MESS: Supported.
+ In MAME: Supported.
-------------------------------------------------*/
-void nes_smb3p_device::device_timer(emu_timer &timer, device_timer_id id, int param, void *ptr)
+TIMER_CALLBACK_MEMBER(nes_smb3p_device::irq_timer_tick)
{
- if (id == TIMER_IRQ)
- {
- if (m_irq_enable)
- {
- if (m_irq_count == 0xffff)
- {
- hold_irq_line();
- m_irq_enable = 0;
- }
- else
- m_irq_count++;
- }
- }
+ // counter does not stop when interrupts are disabled
+ if (m_irq_count != 0xffff)
+ m_irq_count++;
+ if (m_irq_enable && m_irq_count == 0xffff)
+ set_irq_line(ASSERT_LINE);
}
-void nes_smb3p_device::write_h(offs_t offset, uint8_t data)
+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)
{
- case 0x00:
- case 0x02:
- chr1_x(offset & 0x07, data & 0xfe, CHRROM);
- break;
- case 0x01:
- case 0x03:
- chr1_x(offset & 0x07, data | 0x01, CHRROM);
+ case 0x00: case 0x01: case 0x02: case 0x03:
+ chr1_x(offset & 0x07, (data & 0x7e) | BIT(offset, 0), CHRROM);
break;
- case 0x04: case 0x05:
- case 0x06: case 0x07:
- chr1_x(offset & 0x07, data, CHRROM);
+ case 0x04: case 0x05: case 0x06: case 0x07:
+ chr1_x(offset & 0x07, data & 0x7f, CHRROM);
break;
case 0x08:
- prg8_89(data | 0x10);
+ case 0x0b:
+ prg8_x(offset & 0x03, (data | 0x10) & 0x1f);
break;
case 0x09:
- prg8_ab(data);
- break;
case 0x0a:
- prg8_cd(data);
- break;
- case 0x0b:
- prg8_ef(data | 0x10);
+ prg8_x(offset & 0x03, data & 0x1f);
break;
case 0x0c:
- set_nt_mirroring(BIT(data, 0) ? PPU_MIRROR_HORZ : PPU_MIRROR_VERT);
+ set_nt_mirroring(BIT(data, 0) ? PPU_MIRROR_HORZ : PPU_MIRROR_VERT);
break;
case 0x0d:
m_irq_count = 0;
m_irq_enable = 0;
+ set_irq_line(CLEAR_LINE);
break;
case 0x0e:
m_irq_count = (m_irq_count & 0xff00) | data;
@@ -859,30 +884,72 @@ void nes_smb3p_device::write_h(offs_t offset, uint8_t data)
/*-------------------------------------------------
+ BTL-CONTRAJ
+
+ Games: Contra (J) pirate
+
+ NES 2.0: mapper 326
+
+ This PCB has swappable 8K banks at 0x8000-0x9fff,
+ 0xa000-0xbfff, and 0xc000-0xdfff and associated
+ registers in those ranges. Selectable 1K banks for
+ both CHRROM and CIRAM are also in registers across
+ upper memory, 0x8000-0xffff, with mask 0x8010.
+
+ In MAME: Supported.
+
+ TODO: Find out why this crashes in the intro story.
+ Bootleggers missed the bug? Bad dump? This differs
+ only in a couple hundred bytes from contraj, so there
+ aren't that many places for the problem to hide.
+
+ -------------------------------------------------*/
+
+void nes_btl_cj_device::write_h(offs_t offset, u8 data)
+{
+ LOG("btl_cj write_h, offset: %04x, data: %02x\n", offset, data);
+
+ if (BIT(offset, 4))
+ {
+ if (BIT(offset, 3))
+ set_nt_page(offset & 0x03, CIRAM, data & 1, 1);
+ else
+ chr1_x(offset & 0x07, data, CHRROM);
+ }
+ else
+ {
+ offset = BIT(offset, 13, 2);
+ if (offset != 3)
+ prg8_x(offset, data & 0x0f);
+ }
+}
+
+/*-------------------------------------------------
+
BTL-DRAGONNINJA
Games: Dragon Ninja (Bootleg), Super Mario Bros. 8
iNES: mapper 222
- In MESS: Unsupported.
+ In MAME: Unsupported.
-------------------------------------------------*/
/* Scanline based IRQ ? */
-void nes_btl_dn_device::hblank_irq(int scanline, int vblank, int blanked )
+void nes_btl_dn_device::hblank_irq(int scanline, bool vblank, bool blanked)
{
if (!m_irq_count || ++m_irq_count < 240)
return;
m_irq_count = 0;
- hold_irq_line();
+ set_irq_line(ASSERT_LINE);
}
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)
{
@@ -903,11 +970,12 @@ void nes_btl_dn_device::write_h(offs_t offset, uint8_t data)
case 0x5002:
case 0x6000:
case 0x6002:
- bank = ((offset & 0x7000) - 0x3000) / 0x0800 + ((offset & 0x0002) >> 1);
+ bank = 2 * (BIT(offset, 12, 3) - 3) + BIT(offset, 1);
chr1_x(bank, data, CHRROM);
break;
case 0x7000:
m_irq_count = data;
+ set_irq_line(CLEAR_LINE);
break;
}
}
@@ -920,152 +988,174 @@ void nes_btl_dn_device::write_h(offs_t offset, uint8_t data)
/*-------------------------------------------------
- WHIRLWIND-2706
+ Boards DH-08, LE05, LH28, LH31, LH54 (same as LH28)
- Games: Meikyuu Jiin Dababa (FDS conversion) and a few
- others
+ Games: Bubble Bobble alt 1, ProWres, Meikyuu Jiin Dababa,
+ Bubble Bobble alt 2, Falsion
- This PCB maps PRG in 0x6000-0x7fff
+ Similar PCB variants for FDS conversions by Whirlwind Manu. They
+ map PRG in 0x6000-0x7fff. They vary slightly in the use/nonuse
+ of CHR RAM, switchable banks, and valid register locations.
- iNES: mapper 108
+ iNES: mapper 108, 4 submappers
- In MESS: Supported.
+ In MAME: Supported.
-------------------------------------------------*/
-void nes_whirl2706_device::write_h(offs_t offset, uint8_t data)
+u8 nes_whirlwind_device::read_m(offs_t offset)
{
- LOG_MMC(("whirl2706 write_h, offset: %04x, data: %02x\n", offset, data));
- m_latch = data;
+ LOG("whirlwind read_m, offset: %04x\n", offset);
+ return m_prg[((m_reg & m_prg_mask) * 0x2000) + offset];
}
-uint8_t nes_whirl2706_device::read_m(offs_t offset)
+void nes_dh08_device::write_h(offs_t offset, u8 data) // submapper 1
{
- LOG_MMC(("whirl2706 read_m, offset: %04x\n", offset));
- return m_prg[(m_latch * 0x2000 + (offset & 0x1fff)) & (m_prg_size - 1)];
+ 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("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("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("lh31 write_h, offset: %04x, data: %02x\n", offset, data);
+ if (offset >= 0x6000)
+ {
+ m_reg = data;
+ chr8(data, m_chr_source);
+ }
}
/*-------------------------------------------------
Bootleg Board SMB2J
- Games: Super Mario Bros. 2 Pirate (LF36)
+ Games: Super Mario Bros. 2 Pirates (TONY-I, YS-612)
iNES: mapper 43
- In MESS: Supported.
+ In MAME: Supported.
-------------------------------------------------*/
-void nes_smb2j_device::device_timer(emu_timer &timer, device_timer_id id, int param, void *ptr)
+TIMER_CALLBACK_MEMBER(nes_smb2j_device::irq_timer_tick)
{
- if (id == TIMER_IRQ)
+ if (m_irq_enable)
{
- if (m_irq_enable)
- {
- if (m_irq_count == 0xfff)
- {
- hold_irq_line();
- m_irq_enable = 0;
- m_irq_count = 0;
- }
- else
- m_irq_count++;
- }
+ m_irq_count = (m_irq_count + 1) & 0xfff;
+ if (!m_irq_count)
+ set_irq_line(ASSERT_LINE);
}
}
-void nes_smb2j_device::write_l(offs_t offset, uint8_t data)
+void nes_smb2j_device::update_irq(u8 data)
{
- LOG_MMC(("smb2j write_l, offset: %04x, data: %02x\n", offset, data));
- offset += 0x100;
-
- if (offset == 0x122) // $4122
- m_irq_enable = data & 3; // maybe also m_irq_count = 0?!?
+ m_irq_enable = BIT(data, 0);
+ if (!m_irq_enable)
+ {
+ set_irq_line(CLEAR_LINE);
+ m_irq_count = 0;
+ }
}
-void nes_smb2j_device::write_h(offs_t offset, uint8_t data)
+void nes_smb2j_device::write_45(offs_t offset, u8 data)
{
- LOG_MMC(("smb2j write_h, offset: %04x, data: %02x\n", offset, data));
+ static const u8 bank[8] = {4, 3, 4, 4, 4, 7, 5, 6};
- if (offset == 0x122) // $8122 too?
- m_irq_enable = data & 3;
+ switch (offset & 0x71ff)
+ {
+ case 0x4022:
+ prg8_cd(bank[data & 0x07]);
+ break;
+ case 0x4122:
+ nes_smb2j_device::update_irq(data);
+ break;
+ }
}
-void nes_smb2j_device::write_ex(offs_t offset, uint8_t 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);
+}
- if (offset == 2)
- {
- int temp;
+void nes_smb2j_device::write_l(offs_t offset, u8 data)
+{
+ LOG("smb2j write_l, offset: %04x, data: %02x\n", offset, data);
+ nes_smb2j_device::write_45(offset + 0x4100, data);
+}
- // According to hardware tests
- if (data & 1)
- temp = 3;
- else
- temp = 4 + ((data & 7) >> 1);
+void nes_smb2j_device::write_h(offs_t offset, u8 data)
+{
+ LOG("smb2j write_h, offset: %04x, data: %02x\n", offset, data);
- prg8_cd(temp);
- }
+ if (offset == 0x122) // $8122 is also IRQ for YS-612, mask unknown
+ nes_smb2j_device::update_irq(data);
}
-uint8_t nes_smb2j_device::read_l(offs_t offset)
+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)
return m_prg[0x10000 + (offset & 0x0fff)];
- return get_open_bus(); // open bus
+ return get_open_bus();
}
-uint8_t nes_smb2j_device::read_m(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];
}
/*-------------------------------------------------
- BTL-SMB2A
+ BTL-SMB2JA
- Games: Super Mario Bros. 2 Pirate (Jpn version of SMB2)
+ Games: Super Mario Bros. 2 Pirates (LF36, Hey Sung, 1990 SMB4)
iNES: mapper 40
- In MESS: Supported.
+ In MAME: Supported.
-------------------------------------------------*/
-void nes_smb2ja_device::device_timer(emu_timer &timer, device_timer_id id, int param, void *ptr)
+TIMER_CALLBACK_MEMBER(nes_smb2ja_device::irq_timer_tick)
{
- if (id == TIMER_IRQ)
+ if (m_irq_enable)
{
- if (m_irq_enable)
- {
- if (m_irq_count == 0xfff)
- {
- hold_irq_line();
- m_irq_enable = 0;
- m_irq_count = 0;
- }
- else
- m_irq_count++;
- }
+ m_irq_count = (m_irq_count + 1) & 0x1fff; // 13-bit counter
+ if (BIT(m_irq_count, 12))
+ set_irq_line(ASSERT_LINE);
+ else if (!m_irq_count)
+ set_irq_line(CLEAR_LINE); // CD4020 acknowledges on overflow
}
}
-void nes_smb2ja_device::write_h(offs_t offset, uint8_t data)
+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)
{
case 0x0000:
m_irq_enable = 0;
m_irq_count = 0;
+ set_irq_line(CLEAR_LINE);
break;
case 0x2000:
m_irq_enable = 1;
@@ -1076,112 +1166,407 @@ void nes_smb2ja_device::write_h(offs_t offset, uint8_t data)
}
}
-uint8_t nes_smb2ja_device::read_m(offs_t offset)
+u8 nes_smb2ja_device::read_m(offs_t offset)
{
- LOG_MMC(("smb2ja read_m, offset: %04x\n", offset));
- return m_prg[(0xfe * 0x2000 + (offset & 0x1fff)) & (m_prg_size - 1)];
+ LOG("smb2ja read_m, offset: %04x\n", offset);
+ return m_prg[0x06 * 0x2000 + offset]; // fixed 8K bank
}
/*-------------------------------------------------
- BTL-SMB2B
+ BTL-SMB2JB (PCB 761214)
- Games: Super Mario Bros. 2 Pirate (Jpn version of SMB2)
+ Games: Super Mario Bros. 2 Pirate (N-32)
This was marked as Alt. Levels. is it true?
iNES: mapper 50
- In MESS: Partially Supported.
+ In MAME: Supported.
-------------------------------------------------*/
-void nes_smb2jb_device::device_timer(emu_timer &timer, device_timer_id id, int param, void *ptr)
+TIMER_CALLBACK_MEMBER(nes_smb2jb_device::irq_timer_tick)
{
- if (id == TIMER_IRQ)
+ if (m_irq_enable)
{
- if (m_irq_enable)
- {
- if (m_irq_count == 0xfff)
+ if (BIT(++m_irq_count, 12))
+ set_irq_line(ASSERT_LINE);
+ }
+}
+
+void nes_smb2jb_device::write_45(offs_t offset, u8 data)
+{
+ switch (offset & 0x4120)
+ {
+ case 0x4020:
+ m_reg = bitswap<4>(data, 3, 0, 2, 1);
+ prg8_cd(m_reg);
+ break;
+ case 0x4120:
+ m_irq_enable = BIT(data, 0);
+ if (!m_irq_enable)
{
- hold_irq_line();
- m_irq_enable = 0;
+ set_irq_line(CLEAR_LINE);
m_irq_count = 0;
}
+ break;
+ }
+}
+
+void nes_smb2jb_device::write_ex(offs_t offset, u8 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("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("smb2jb read_m, offset: %04x\n", offset);
+ return m_prg[(m_bank67 * 0x2000 + offset) & (m_prg_size - 1)];
+}
+
+/*-------------------------------------------------
+
+ BMC-N32-4IN1
+
+ Unknown Bootleg Multigame Board
+ Games: 4 in 1
+
+ This multicart contains the mapper 50 version of SMB2.
+ There are changes to bank locations compared to that
+ game, but otherwise we rely on the existing SMB2JB
+ emulation (unless other differences are discovered?)
+
+ NES 2.0: mapper 416
+
+ In MAME: Supported.
+
+ -------------------------------------------------*/
+
+void nes_n32_4in1_device::write_h(offs_t offset, u8 data)
+{
+ LOG("n32_4in1 write_h, offset: %04x, data: %02x\n", offset, data);
+
+ if (offset < 0x2000)
+ {
+ if (BIT(data, 3)) // NROM games
+ {
+ u8 bank = bitswap<3>(data, 3, 7, 5);
+ u8 mode = BIT(data, 7);
+ if (data & 0xc0)
+ {
+ prg16_89ab(bank & ~mode);
+ prg16_cdef(bank | mode);
+ }
else
- m_irq_count++;
+ for (int i = 0; i < 4; i++)
+ prg8_x(i, bank << 1);
}
+ else // SMB2 only
+ {
+ prg8_89(0);
+ prg8_ab(1);
+ prg8_cd(m_reg);
+ prg8_ef(3);
+ }
+
+ chr8(BIT(data, 1, 2), CHRROM);
+ set_nt_mirroring(BIT(data, 2) ? PPU_MIRROR_HORZ : PPU_MIRROR_VERT);
}
}
-void nes_smb2jb_device::write_l(offs_t offset, uint8_t data)
+/*-------------------------------------------------
+
+ (BTL-)0353
+
+ Games: Lucky Rabbit (Roger Rabbit conversion)
+
+ NES 2.0: mapper 415
+
+ In MAME: Supported.
+
+ -------------------------------------------------*/
+
+u8 nes_0353_device::read_m(offs_t 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)
{
- uint8_t prg;
- LOG_MMC(("smb2jb write_l, offset: %04x, data: %02x\n", offset, data));
- offset += 0x100;
+ 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;
+}
+
+/*-------------------------------------------------
+
+ (UNL-)09-034A
+
+ Games: Zanac FDS conversion with two PRG chips and
+ no CHRROM, and SMB2 and Volleyball FDS conversions
+ with two PRG chips and CHRROM. Originally dumps
+ were marked as UNL-SMB2J PCB.
+
+ Only SMB2 uses the IRQ and it has been documented as
+ being broken on real hardware. Most notably the status
+ bar scrolls with the rest of the screen and the game
+ completely crashes between the "our princess" scene of
+ world 4-4 and the beginning of world 5-1. How the IRQ
+ functions is to be confirmed but it likely uses a 12-bit
+ counter just like the other SMB2 bootlegs. That is how
+ we presently emulate it here.
+
+ NES 2.0: mapper 304
+
+ In MAME: Supported.
+
+ -------------------------------------------------*/
- switch (offset & 0x1e0)
+TIMER_CALLBACK_MEMBER(nes_09034a_device::irq_timer_tick)
+{
+ if (m_irq_enable)
{
- case 0x020:
- case 0x0a0:
- prg = (data & 0x08) | ((data & 0x06) >> 1) | ((data & 0x01) << 2);
- prg8_cd(prg);
+ m_irq_count = (m_irq_count + 1) & 0x0fff;
+ if (!m_irq_count)
+ set_irq_line(ASSERT_LINE);
+ }
+}
+
+void nes_09034a_device::write_ex(offs_t offset, u8 data)
+{
+ LOG("09-034a write_ex, offset: %04x, data: %02x\n", offset, data);
+
+ offset += 0x20;
+ switch (offset)
+ {
+ case 0x0027:
+ m_reg = data & 1;
break;
- case 0x120:
- case 0x1a0:
- m_irq_enable = data & 0x01;
+ case 0x0068:
+ m_irq_enable = BIT(data, 0);
+ if (!m_irq_enable)
+ {
+ m_irq_count = 0;
+ set_irq_line(CLEAR_LINE);
+ }
break;
}
}
-uint8_t nes_smb2jb_device::read_m(offs_t offset)
+u8 nes_09034a_device::read_ex(offs_t 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
+ if (offset >= 0x42 && offset <= 0x55)
+ return 0xff;
+ else
+ return get_open_bus();
+}
+
+u8 nes_09034a_device::read_m(offs_t 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)];
+}
+
+/*-------------------------------------------------
+
+ Board L-001
+
+ Games: Sangokushi III (Sangokushi II bootleg)
+
+ This board has swappable 8K PRG banks at 0x8000, 0xa000,
+ and 0xc000, while 0xe000 is fixed to the final bank.
+ CHRROM and CIRAM are also swappable in 1K banks.
+ The board has a 16-bit IRQ counter with the enable bit
+ acting as the MSB. The enhanced audio of the original
+ Namco 163 board is not retained.
+
+ NES 2.0: mapper 330
+
+ In MAME: Supported.
+
+ -------------------------------------------------*/
+
+TIMER_CALLBACK_MEMBER(nes_l001_device::irq_timer_tick)
{
- LOG_MMC(("smb2jb read_m, offset: %04x\n", offset));
- return m_prg[((0x0f * 0x2000) + (offset & 0x1fff)) & (m_prg_size - 1)];
+ if (BIT(m_irq_count, 15))
+ {
+ if (++m_irq_count == 0)
+ set_irq_line(ASSERT_LINE);
+ }
}
-/* This goes to 0x4020-0x403f & 0x40a0-0x40bf */
-void nes_smb2jb_device::write_ex(offs_t offset, uint8_t data)
+void nes_l001_device::write_h(offs_t offset, u8 data)
{
- uint8_t prg;
- LOG_MMC(("smb2jb write_ex, offset: %04x, data: %02x\n", offset, data));
+ LOG("l-001 write_h, offset: %04x, data: %02x\n", offset, data);
- if ((offset < 0x20) || (offset >= 0x80 && offset < 0xa0))
+ switch (offset & 0x6400)
{
- prg = (data & 0x08) | ((data & 0x06) >> 1) | ((data & 0x01) << 2);
- prg8_cd(prg);
+ case 0x0000:
+ case 0x2000:
+ chr1_x(BIT(offset, 11, 3), data, CHRROM);
+ break;
+ case 0x0400:
+ m_irq_count = (m_irq_count & 0xff00) | data;
+ break;
+ case 0x2400:
+ m_irq_count = (m_irq_count & 0x00ff) | data << 8;
+ set_irq_line(CLEAR_LINE);
+ break;
+ case 0x4000:
+ set_nt_page(BIT(offset, 11, 2), CIRAM, data & 1, 1);
+ break;
+ case 0x6000:
+ if (offset < 0x7800)
+ prg8_x(BIT(offset, 11, 2), data & 0x1f);
+ break;
}
}
/*-------------------------------------------------
- (UNL-)09-034A
+ BTL-BATMANFS
- Games: Zanac FDS conversion with two PRG chips and
- no CHRROM and Volleyball FDS conversion with two PRG
- chips and CHRROM.
- Originally dumps were marked as UNL-SMB2J pcb
+ Games: Batman "Fine Studio" pirate
- iNES:
+ NES 2.0: mapper 417
- In MESS: Partially Supported. Need to emulate IRQ
- (needed by smb2 conversion?)
+ In MAME: Supported.
-------------------------------------------------*/
-void nes_09034a_device::write_ex(offs_t offset, uint8_t data)
+TIMER_CALLBACK_MEMBER(nes_batmanfs_device::irq_timer_tick)
{
- LOG_MMC(("09-034a write_ex, offset: %04x, data: %02x\n", offset, data));
+ // 10-bit counter does not stop when interrupts are disabled
+ m_irq_count = (m_irq_count + 1) & 0x3ff;
+ if (m_irq_enable && !m_irq_count)
+ set_irq_line(ASSERT_LINE);
+}
- if (offset == 7) // $4027
- m_reg = data & 1;
+void nes_batmanfs_device::write_h(offs_t offset, u8 data)
+{
+ LOG("batmanfs write_h, offset: %04x, data: %02x\n", offset, data);
+ switch (offset & 0x70)
+ {
+ case 0x00:
+ if ((offset & 0x03) != 0x03)
+ prg8_x(offset & 0x03, data & 0x0f);
+ break;
+ case 0x10:
+ case 0x20:
+ chr1_x((offset & 0x03) + 4 * BIT(offset, 5), data, CHRROM);
+ break;
+ case 0x30:
+ m_irq_enable = 1;
+ m_irq_count = 0;
+ break;
+ case 0x40:
+ m_irq_enable = 0;
+ set_irq_line(CLEAR_LINE);
+ break;
+ case 0x50:
+ set_nt_page(offset & 0x03, CIRAM, data & 1, 1);
+ break;
+ }
}
-uint8_t nes_09034a_device::read_m(offs_t offset)
+/*-------------------------------------------------
+
+ BTL-PALTHENA
+
+ Games: Palthena no Kagami (FDS conversion)
+
+ This board has fixed 8K PRG banks at 0x6000, 0x8000,
+ 0xc000, and 0xe000. The PRG bank at 0xa000 is switchable
+ by writing to the register in the same 0xa000-0xbfff
+ range. What makes the board interesting is the overlaid
+ 8K of RAM with only 6K addressable:
+
+ 8K WRAM: Addr:
+ 0x0000-0x11ff 0xc000-0xd1ff
+ 0x1200-0x12ff 0x8200-0x82ff
+ 0x1300-0x17ff N/A
+ 0x1800-0x18ff 0x6000-0x60ff
+ 0x1900-0x19ff N/A
+ 0x1a00-0x1aff 0x6200-0x62ff
+ 0x1b00-0x1bff N/A
+ 0x1c00-0x1dff 0x6400-0x65ff
+ 0x1e00-0x1eff N/A
+ 0x1f00-0x1fff 0xdf00-0xdfff
+
+ NES 2.0: mapper 539
+
+ In MAME: Supported.
+
+-------------------------------------------------*/
+
+u8 nes_palthena_device::read_m(offs_t offset)
{
- LOG_MMC(("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];
+ LOGMASKED(LOG_HIFREQ, "palthena read_m, offset: %04x\n", offset);
+ switch (offset & 0x1f00)
+ {
+ case 0x0000:
+ case 0x0200:
+ case 0x0400:
+ case 0x0500:
+ return m_prgram[offset | 0x1800];
+ default:
+ return m_prg[0x0d * 0x2000 + offset]; // fixed PRG bank
+ }
+}
+
+void nes_palthena_device::write_m(offs_t offset, u8 data)
+{
+ LOG("palthena write_m, offset: %04x, data: %02x\n", offset, data);
+ switch (offset & 0x1f00)
+ {
+ case 0x0000:
+ case 0x0200:
+ case 0x0400:
+ case 0x0500:
+ m_prgram[offset | 0x1800] = data;
+ break;
+ }
+}
+
+u8 nes_palthena_device::read_h(offs_t 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];
+ else if (page == 0x02)
+ return m_prgram[offset | 0x1000];
+
+ return hi_access_rom(offset);
+}
+
+void nes_palthena_device::write_h(offs_t offset, u8 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;
+ else if (page == 0x02)
+ m_prgram[offset | 0x1000] = data;
+ else if (page >= 0x20 && page < 0x40)
+ prg8_ab(data & 0x0f);
+ else if (offset == 0x7fff)
+ set_nt_mirroring(BIT(data, 3) ? PPU_MIRROR_HORZ : PPU_MIRROR_VERT);
}
/*-------------------------------------------------
@@ -1194,13 +1579,13 @@ uint8_t nes_09034a_device::read_m(offs_t offset)
iNES: mapper 120
- In MESS: Partially Supported.
+ In MAME: Partially supported.
-------------------------------------------------*/
void nes_tobidase_device::write_l(offs_t offset, uint8_t data)
{
- LOG_MMC(("tobidase write_h, offset: %04x, data: %02x\n", offset, data));
+ LOG("tobidase write_l, offset: %04x, data: %02x\n", offset, data);
offset += 0x4100;
if ((offset & 0x63c0) == 0x41c0)
@@ -1209,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)];
@@ -1223,21 +1608,21 @@ uint8_t nes_tobidase_device::read_m(offs_t offset)
This PCB maps WRAM in 0xc000-0xdfff and PRG in 0x6000-0x7fff
- iNES:
+ iNES: mapper 125
- In MESS: Supported.
+ In MAME: Supported.
-------------------------------------------------*/
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];
@@ -1247,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;
@@ -1266,6 +1650,81 @@ void nes_lh32_device::write_h(offs_t offset, uint8_t data)
/*-------------------------------------------------
+ UNL-LH42
+
+ Games: Highway Star (Whirlwind Manu bootleg)
+
+ NES 2.0: mapper 418
+
+ In MAME: Supported.
+
+ -------------------------------------------------*/
+
+void nes_lh42_device::write_h(offs_t offset, u8 data)
+{
+ LOG("lh42 write_h, offset: %04x, data: %02x\n", offset, data);
+
+ switch (offset & 0x6001)
+ {
+ case 0x0000:
+ m_latch = data & 0x07;
+ break;
+ case 0x0001:
+ switch (m_latch)
+ {
+ case 5:
+ set_nt_mirroring(BIT(data, 0) ? PPU_MIRROR_HORZ : PPU_MIRROR_VERT);
+ break;
+ case 6:
+ case 7:
+ prg8_x(m_latch & 1, data & 0x0f);
+ break;
+ }
+ break;
+ }
+}
+
+/*-------------------------------------------------
+
+ UNL-LG25
+
+ Games: Moero TwinBee Cinnamon Hakase o Sukue! (FDS conversion)
+
+ In addition to the two swappable 8K PRG banks at
+ 0x8000 and 0xa000, this board has 8K WRAM at 0x6000.
+
+ NES 2.0: mapper 557
+
+ In MAME: Supported.
+
+ -------------------------------------------------*/
+
+void nes_lg25_device::write_h(offs_t offset, u8 data)
+{
+ LOG("lg25 write_h, offset: %04x, data: %02x\n", offset, data);
+
+ switch (offset & 0x6001)
+ {
+ case 0x0000:
+ m_latch = data & 0x07;
+ break;
+ case 0x0001:
+ switch (m_latch)
+ {
+ case 5:
+ set_nt_mirroring(BIT(data, 5) ? PPU_MIRROR_HORZ : PPU_MIRROR_VERT);
+ break;
+ case 6:
+ case 7:
+ prg8_x(m_latch & 1, data & 0x0f);
+ break;
+ }
+ break;
+ }
+}
+
+/*-------------------------------------------------
+
UNL-LH10
Games: Fuuun Shaolin Kyo (FDS conversion)
@@ -1273,27 +1732,21 @@ void nes_lh32_device::write_h(offs_t offset, uint8_t data)
This PCB maps WRAM in 0xc000-0xdfff and PRG in 0x6000-0x7fff
This is very similar to KS7037 (see kaiser.cpp)
- iNES:
+ NES 2.0: mapper 522
- In MESS: Supported.
+ In MAME: Supported.
-------------------------------------------------*/
-void nes_lh10_device::update_prg()
-{
- prg8_89(m_reg[6]);
- prg8_ab(m_reg[7]);
-}
-
-uint8_t nes_lh10_device::read_m(offs_t offset)
+u8 nes_lh10_device::read_m(offs_t offset)
{
- LOG_MMC(("lh10 read_m, offset: %04x\n", offset));
- return m_prg[(0x0e * 0x2000) + (offset & 0x1fff)];
+ LOG("lh10 read_m, offset: %04x\n", offset);
+ return m_prg[(0x0e * 0x2000 + offset) & (m_prg_size - 1)];
}
-uint8_t nes_lh10_device::read_h(offs_t offset)
+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];
@@ -1301,25 +1754,60 @@ uint8_t nes_lh10_device::read_h(offs_t offset)
return hi_access_rom(offset);
}
-void nes_lh10_device::write_h(offs_t offset, uint8_t data)
+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);
- if (offset >= 0x4000 && offset < 0x6000)
- m_prgram[offset & 0x1fff] = data;
+ switch (offset & 0x6001)
+ {
+ case 0x0000:
+ m_latch = data & 7;
+ break;
+ case 0x0001:
+ switch (m_latch)
+ {
+ case 6:
+ case 7:
+ prg8_x(m_latch & 1, data & 0x0f);
+ break;
+ }
+ break;
+ case 0x4000:
+ case 0x4001:
+ m_prgram[offset & 0x1fff] = data;
+ break;
+ }
+}
- else
+/*-------------------------------------------------
+
+ UNL-LH51
+
+ Games: Ai Senshi Nicol (Whirlwind Manu FDS conversion)
+
+ A simple board with swappable 8K PRG at 0x8000-0x9fff,
+ fixed PRG above that, and 8K WRAM at 0x6000-0x7fff.
+ The game's sound code is broken and does not work on
+ real hardware.
+
+ NES 2.0: mapper 309
+
+ In MAME: Supported.
+
+ -------------------------------------------------*/
+
+void nes_lh51_device::write_h(offs_t offset, u8 data)
+{
+ LOG("lh51 write_h, offset: %04x, data: %02x\n", offset, data);
+
+ switch (offset & 0x6000)
{
- switch (offset & 0x6001)
- {
- case 0x0000:
- m_latch = data & 7;
- break;
- case 0x0001:
- m_reg[m_latch] = data;
- update_prg();
- break;
- }
+ case 0x0000:
+ prg8_89(data & 0x0f);
+ break;
+ case 0x6000:
+ set_nt_mirroring(BIT(data, 3) ? PPU_MIRROR_HORZ : PPU_MIRROR_VERT);
+ break;
}
}
@@ -1329,54 +1817,49 @@ void nes_lh10_device::write_h(offs_t offset, uint8_t data)
Games: Nazo no Murasamejou (FDS conversion)
- This PCB maps WRAM (w/battery) in 0xb800-0xd7ff and
- PRG in 0x6000-0x7fff
+ This PCB maps WRAM in 0xb800-0xd7ff and PRG in 0x6000-0x7fff
- iNES:
+ NES 2.0: mapper 535
- In MESS: Preliminar Support only.
+ In MAME: Preliminary support only.
-------------------------------------------------*/
-void nes_lh53_device::device_timer(emu_timer &timer, device_timer_id id, int param, void *ptr)
+TIMER_CALLBACK_MEMBER(nes_lh53_device::irq_timer_tick)
{
- if (id == TIMER_IRQ)
+ if (m_irq_enable)
{
- if (m_irq_enable)
+ m_irq_count++;
+ if (m_irq_count > 7560)//value from FCEUMM...
{
- m_irq_count++;
- if (m_irq_count > 7560)//value from FCEUMM...
- {
- m_irq_count = 0;
- set_irq_line(ASSERT_LINE);
- }
+ m_irq_count = 0;
+ set_irq_line(ASSERT_LINE);
}
}
}
uint8_t nes_lh53_device::read_m(offs_t offset)
{
- LOG_MMC(("lh53 read_m, offset: %04x\n", offset));
- return m_prg[(m_reg * 0x2000) + (offset & 0x1fff)];
+ 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_battery[offset & 0x1fff];
+ return m_prgram[offset - 0x3800];
return hi_access_rom(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_battery[offset & 0x1fff] = data;
-
+ m_prgram[offset - 0x3800] = data;
else
{
switch (offset & 0x7000)
@@ -1400,21 +1883,21 @@ void nes_lh53_device::write_h(offs_t offset, uint8_t data)
Games: Doki Doki Panic (FDS conversion)
- iNES: mapper 103?
-
This board has a very unique setup, with 8KB of WRAM
in 0x6000-0x7fff and other 8KB of WRAM in 0xb800-0xd7ff
which can be switched in 2KB chunks (we attempt to
emulate this by intercepting reads in that area before
they get to the PRG banks...)
- In MESS: Supported.
+ iNES: mapper 103
+
+ In MAME: Supported.
-------------------------------------------------*/
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
@@ -1423,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
@@ -1440,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
@@ -1465,93 +1948,59 @@ void nes_2708_device::write_h(offs_t offset, uint8_t data)
Games: Green Beret (FDS conversions)
- iNES:
-
This board has two PRG chips. The first (128K) is
connected to 0x6000-0x7fff and switches among the
16x8K banks; the second (32K) is fixed in 0x8000-0xffff
- In MESS: Supported.
+ iNES: ???
+
+ In MAME: Supported.
-------------------------------------------------*/
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 = (data >> 1) & 0x0f;
+ m_latch = BIT(data, 1, 4);
else
m_latch = data & 0x0f; // apparently there also is a Castlevania FDS conversion using same board with different banking lines
}
/*-------------------------------------------------
- UNL-BB
-
- Games: Bubble Bobble and other FDS conversions with CHRROM!
-
- iNES:
-
-
- In MESS: Supported.
-
- -------------------------------------------------*/
-
-uint8_t nes_unl_bb_device::read_m(offs_t offset)
-{
- LOG_MMC(("unl-bb read_m, offset: %04x\n", offset));
- return m_prg[(((m_reg[0] & 3 & m_prg_mask) * 0x2000) + (offset & 0x1fff))];
-}
-
-void nes_unl_bb_device::write_h(offs_t offset, uint8_t data)
-{
- LOG_MMC(("unl-bb write_h, offset: %04x, data: %02x\n", offset, data));
-
- if (!(offset & 0x1000))
- {
- m_reg[0] = data;
- m_reg[1] = data;
- }
- else
- m_reg[1] = data & 1; // Pro Wrestling uses this
-
- chr8(m_reg[1] & 3, m_chr_source);
-}
-
-/*-------------------------------------------------
-
BTL-MARIO1-MALEE2 (aka Genius Merio Bros)
Games: Super Mario Bros Malee 2
- iNES:
-
This PCB has two PRG chips (32K+2K) + one CHR chip (8K)
+ 2KB of WRAM
The second PRG chip (2K) is connected at 0x6000-0x6800
while WRAM is at 0x7000-0x7800
- In MESS: Supported.
+ iNES: mapper 55
+
+ In MAME: Supported.
-------------------------------------------------*/
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];
@@ -1563,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;
@@ -1571,113 +2020,95 @@ void nes_mmalee_device::write_m(offs_t offset, uint8_t data)
/*-------------------------------------------------
- BTL-SHUIGUANPIPE
+ RT-01
+
+ Games: Russian test cart
+
+ The PRG EPROM has copy protected areas with
+ "weak bits", which is tested at some points (info
+ from Cah4e3).
+
+ NES 2.0: mapper 328
+
+ In MAME: Partially supported?
+
+ -------------------------------------------------*/
+
+uint8_t nes_rt01_device::read_h(offs_t offset)
+{
+ LOGMASKED(LOG_HIFREQ, "rt01 read_h, offset: %04x\n", offset);
+
+ if ((offset >= 0x4e80) && (offset < 0x4f00))
+ return 0xf2 | (machine().rand() & 0x0d);
+ if ((offset >= 0x7e80) && (offset < 0x7f00))
+ return 0xf2 | (machine().rand() & 0x0d);
+
+ return hi_access_rom(offset);
+}
+
+/*-------------------------------------------------
+
+ YUNG-08
- Games: Shui Guan Pipe (Gimmick Pirate)
+ Games: Super Mario Bros. 2 Pirate (YUNG-08)
- iNES:
+ NES 2.0: mapper 368
- In MESS: Supported, but there are glitches (PPU or IRQ?)
+ In MAME: Supported.
-------------------------------------------------*/
-// timer always running and checking IRQ every 114 CPU cycles?
-void nes_shuiguan_device::device_timer(emu_timer &timer, device_timer_id id, int param, void *ptr)
+TIMER_CALLBACK_MEMBER(nes_yung08_device::irq_timer_tick)
{
- if (id == TIMER_IRQ)
+ if (BIT(m_irq_latch, 0))
{
- m_irq_count++;
- m_irq_count &= 0xff;
-
- if (m_irq_enable && !m_irq_count)
- hold_irq_line();
+ m_irq_count = (m_irq_count + 1) & 0x0fff;
+ if (!m_irq_count)
+ set_irq_line(ASSERT_LINE);
}
}
-void nes_shuiguan_device::write_h(offs_t offset, uint8_t data)
+void nes_yung08_device::write_45(offs_t offset, u8 data)
{
- int bank;
- LOG_MMC(("shuiguan write_h, offset: %04x, data: %02x\n", offset, data));
-
- switch (offset & 0x7000)
+ switch (offset & 0x51ff)
{
- case 0x0000:
- if (offset & 0x800 && !(offset & 0x0c)) // 0x8800-0x8803 + N*0x10
- prg8_89(data);
- break;
- case 0x1000:
- if (offset & 0x800 && !(offset & 0x0c)) // 0x9800-0x9803 + N*0x10
- {
- switch (data & 0x03)
- {
- case 0: set_nt_mirroring(PPU_MIRROR_VERT); break;
- case 1: set_nt_mirroring(PPU_MIRROR_HORZ); break;
- case 2: set_nt_mirroring(PPU_MIRROR_LOW); break;
- case 3: set_nt_mirroring(PPU_MIRROR_HIGH); break;
- }
- }
- break;
- case 0x2000:
- if (!(offset & 0x800) && !(offset & 0x0c)) // 0xa000-0xa003 + N*0x10
- prg8_cd(data);
- if (offset & 0x800 && !(offset & 0x0c)) // 0xa800-0xa803 + N*0x10
- prg8_ab(data);
- break;
- case 0x3000:
- case 0x4000:
- case 0x5000:
- case 0x6000:
- bank = (((offset + 0x1000) >> 11) | (offset >> 3)) & 0x07;
- if (offset & 4)
- m_mmc_vrom_bank[bank] = (m_mmc_vrom_bank[bank] & 0x0f) | ((data & 0x0f) << 4);
- else
- m_mmc_vrom_bank[bank] = (m_mmc_vrom_bank[bank] & 0xf0) | ((data & 0x0f) << 0);
- chr1_x(bank, m_mmc_vrom_bank[bank], m_chr_source);
+ case 0x4022:
+ prg8_cd(data & 1 ? 3 : 4 + BIT(data, 1, 2));
break;
- case 0x7000:
- switch (offset & 0x0c)
+ case 0x4122:
+ m_irq_latch = data & 0x35;
+ if (!BIT(m_irq_latch, 0))
{
- case 0x00: m_irq_count = (m_irq_count & 0xf0) | ((data & 0x0f) << 0); break;
- case 0x04: m_irq_count = (m_irq_count & 0x0f) | ((data & 0x0f) << 4); break;
- case 0x08: m_irq_enable= data; break;
- case 0x0c: break;
+ set_irq_line(CLEAR_LINE);
+ m_irq_count = 0;
}
break;
}
}
-uint8_t nes_shuiguan_device::read_m(offs_t offset)
+void nes_yung08_device::write_ex(offs_t offset, u8 data)
{
- // always first bank??
- LOG_MMC(("shuiguan read_m, offset: %04x\n", offset));
- return m_prg[offset & 0x1fff];
+ LOG("yung08 write_ex, offset: %04x, data: %02x\n", offset, data);
+ write_45(offset + 0x4020, data);
}
-
-/*-------------------------------------------------
-
- RT-01
-
- Games: Russian test cart
-
- The PRG EPROM has copy protected areas with
- "weak bits", which is tested at some points (info
- from Cah4e3).
-
- iNES:
-
- In MESS:
-
- -------------------------------------------------*/
-
-uint8_t nes_rt01_device::read_h(offs_t offset)
+void nes_yung08_device::write_l(offs_t offset, u8 data)
{
-// LOG_MMC(("rt01 read_h, offset: %04x\n", offset));
+ LOG("yung08 write_l, offset: %04x, data: %02x\n", offset, data);
+ write_45(offset + 0x4100, data);
+}
- if ((offset >= 0x4e80) && (offset < 0x4f00))
- return 0xf2 | (machine().rand() & 0x0d);
- if ((offset >= 0x7e80) && (offset < 0x7f00))
- return 0xf2 | (machine().rand() & 0x0d);
+u8 nes_yung08_device::read_l(offs_t offset)
+{
+ LOG("yung08 read_l, offset: %04x\n", offset);
+ offset += 0x100;
+ if ((offset & 0x11ff) == 0x0122) // 0x4122
+ return m_irq_latch | 0x8a;
+ return get_open_bus();
+}
- return hi_access_rom(offset);
+u8 nes_yung08_device::read_m(offs_t 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/bootleg.h b/src/devices/bus/nes/bootleg.h
index 42213b131b8..06f10d8b06e 100644
--- a/src/devices/bus/nes/bootleg.h
+++ b/src/devices/bus/nes/bootleg.h
@@ -6,29 +6,6 @@
#include "nxrom.h"
-// ======================> nes_ax5705_device
-
-class nes_ax5705_device : public nes_nrom_device
-{
-public:
- // construction/destruction
- nes_ax5705_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
-
- virtual void write_h(offs_t offset, uint8_t data) override;
-
- virtual void pcb_reset() override;
-
-protected:
- // device-level overrides
- virtual void device_start() override;
-
-private:
- void set_prg();
- uint8_t m_mmc_prg_bank[2];
- uint8_t m_mmc_vrom_bank[8];
-};
-
-
// ======================> nes_sc127_device
class nes_sc127_device : public nes_nrom_device
@@ -38,12 +15,12 @@ public:
nes_sc127_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
virtual void write_h(offs_t offset, uint8_t data) override;
- virtual void hblank_irq(int scanline, int vblank, int blanked) override;
+ virtual void hblank_irq(int scanline, bool vblank, bool blanked) override;
virtual void pcb_reset() override;
protected:
// device-level overrides
- virtual void device_start() override;
+ virtual void device_start() override ATTR_COLD;
private:
uint16_t m_irq_count;
@@ -57,25 +34,25 @@ class nes_mbaby_device : public nes_nrom_device
{
public:
// construction/destruction
- nes_mbaby_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
- virtual uint8_t read_m(offs_t offset) override;
- virtual void write_h(offs_t offset, uint8_t data) override;
+ nes_mbaby_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock);
+
+ virtual u8 read_m(offs_t offset) override;
+ virtual void write_h(offs_t offset, u8 data) override;
virtual void pcb_reset() override;
protected:
// device-level overrides
- virtual void device_start() override;
- virtual void device_timer(emu_timer &timer, device_timer_id id, int param, void *ptr) override;
+ virtual void device_start() override ATTR_COLD;
-private:
- static constexpr device_timer_id TIMER_IRQ = 0;
+ TIMER_CALLBACK_MEMBER(irq_timer_tick);
- uint8_t m_latch;
+private:
+ u16 m_irq_count;
int m_irq_enable;
+ u8 m_latch;
emu_timer *irq_timer;
- attotime timer_freq;
};
@@ -94,7 +71,7 @@ public:
protected:
// device-level overrides
- virtual void device_start() override;
+ virtual void device_start() override ATTR_COLD;
private:
uint8_t m_latch;
@@ -107,26 +84,40 @@ class nes_smb3p_device : public nes_nrom_device
{
public:
// construction/destruction
- nes_smb3p_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
+ nes_smb3p_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock);
- virtual void write_h(offs_t offset, uint8_t data) override;
+ virtual void write_h(offs_t offset, u8 data) override;
virtual void pcb_reset() override;
+ virtual void pcb_start(running_machine &machine, u8 *ciram_ptr, bool cart_mounted) override;
protected:
// device-level overrides
- virtual void device_start() override;
- virtual void device_timer(emu_timer &timer, device_timer_id id, int param, void *ptr) override;
+ virtual void device_start() override ATTR_COLD;
+
+ TIMER_CALLBACK_MEMBER(irq_timer_tick);
private:
- uint16_t m_irq_count;
+ u16 m_irq_count;
int m_irq_enable;
- static const device_timer_id TIMER_IRQ = 0;
emu_timer *irq_timer;
};
+// ======================> nes_btl_cj_device
+
+class nes_btl_cj_device : public nes_nrom_device
+{
+public:
+ // construction/destruction
+ nes_btl_cj_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock);
+ virtual void write_h(offs_t offset, u8 data) override;
+
+ virtual void pcb_reset() override;
+};
+
+
// ======================> nes_btl_dn_device
class nes_btl_dn_device : public nes_nrom_device
@@ -136,142 +127,248 @@ public:
nes_btl_dn_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
virtual void write_h(offs_t offset, uint8_t data) override;
- virtual void hblank_irq(int scanline, int vblank, int blanked) override;
+ virtual void hblank_irq(int scanline, bool vblank, bool blanked) override;
virtual void pcb_reset() override;
protected:
// device-level overrides
- virtual void device_start() override;
+ virtual void device_start() override ATTR_COLD;
private:
uint16_t m_irq_count;
};
-// ======================> nes_whirl2706_device
+// ======================> nes_smb2j_device
-class nes_whirl2706_device : public nes_nrom_device
+class nes_smb2j_device : public nes_nrom_device
{
public:
// construction/destruction
- nes_whirl2706_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
+ nes_smb2j_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock);
- virtual uint8_t read_m(offs_t offset) override;
- virtual void write_h(offs_t offset, uint8_t data) override;
+ virtual u8 read_l(offs_t offset) override;
+ virtual u8 read_m(offs_t offset) override;
+ virtual void write_ex(offs_t offset, u8 data) override;
+ virtual void write_l(offs_t offset, u8 data) override;
+ virtual void write_h(offs_t offset, u8 data) override;
virtual void pcb_reset() override;
protected:
// device-level overrides
- virtual void device_start() override;
+ virtual void device_start() override ATTR_COLD;
+
+ TIMER_CALLBACK_MEMBER(irq_timer_tick);
private:
- uint8_t m_latch;
+ void update_irq(u8 data);
+ void write_45(offs_t offset, u8 data);
+ u16 m_irq_count;
+ int m_irq_enable;
+
+ emu_timer *irq_timer;
};
-// ======================> nes_smb2j_device
+// ======================> nes_smb2ja_device
-class nes_smb2j_device : public nes_nrom_device
+class nes_smb2ja_device : public nes_nrom_device
{
public:
// construction/destruction
- nes_smb2j_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
+ nes_smb2ja_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock);
- virtual uint8_t read_l(offs_t offset) override;
- virtual uint8_t read_m(offs_t offset) override;
- virtual void write_ex(offs_t offset, uint8_t data) override;
- virtual void write_l(offs_t offset, uint8_t data) override;
- virtual void write_h(offs_t offset, uint8_t data) override;
+ virtual u8 read_m(offs_t offset) override;
+ virtual void write_h(offs_t offset, u8 data) override;
virtual void pcb_reset() override;
protected:
// device-level overrides
- virtual void device_start() override;
- virtual void device_timer(emu_timer &timer, device_timer_id id, int param, void *ptr) override;
+ virtual void device_start() override ATTR_COLD;
+
+ TIMER_CALLBACK_MEMBER(irq_timer_tick);
private:
- uint16_t m_irq_count;
+ u16 m_irq_count;
int m_irq_enable;
- static const device_timer_id TIMER_IRQ = 0;
emu_timer *irq_timer;
};
-// ======================> nes_smb2ja_device
+// ======================> nes_smb2jb_device
-class nes_smb2ja_device : public nes_nrom_device
+class nes_smb2jb_device : public nes_nrom_device
{
public:
// construction/destruction
- nes_smb2ja_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
- virtual uint8_t read_m(offs_t offset) override;
- virtual void write_h(offs_t offset, uint8_t data) override;
+ nes_smb2jb_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock);
+
+ virtual u8 read_m(offs_t offset) override;
+ virtual void write_l(offs_t offset, u8 data) override;
+ virtual void write_ex(offs_t offset, u8 data) override;
virtual void pcb_reset() override;
protected:
+ nes_smb2jb_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, u32 clock, u8 bank67);
+
// device-level overrides
- virtual void device_start() override;
- virtual void device_timer(emu_timer &timer, device_timer_id id, int param, void *ptr) override;
+ virtual void device_start() override ATTR_COLD;
+
+ TIMER_CALLBACK_MEMBER(irq_timer_tick);
+
+ u16 m_irq_count;
+ int m_irq_enable;
+ u8 m_reg;
private:
- uint16_t m_irq_count;
+ void write_45(offs_t offset, u8 data);
+ const u8 m_bank67;
+
+ emu_timer *irq_timer;
+};
+
+
+// ======================> nes_n32_4in1_device
+
+class nes_n32_4in1_device : public nes_smb2jb_device
+{
+public:
+ // construction/destruction
+ nes_n32_4in1_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock);
+
+ virtual void write_h(offs_t offset, u8 data) override;
+
+ virtual void pcb_reset() override;
+};
+
+
+// ======================> nes_0353_device
+
+class nes_0353_device : public nes_nrom_device
+{
+public:
+ // construction/destruction
+ nes_0353_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock);
+
+ virtual u8 read_m(offs_t offset) override;
+ virtual void write_h(offs_t offset, u8 data) override;
+
+ virtual void pcb_reset() override;
+
+protected:
+ // device-level overrides
+ virtual void device_start() override ATTR_COLD;
+
+private:
+ u8 m_reg;
+};
+
+
+// ======================> nes_09034a_device
+
+class nes_09034a_device : public nes_nrom_device
+{
+public:
+ // construction/destruction
+ nes_09034a_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock);
+
+ virtual void write_ex(offs_t offset, u8 data) override;
+ virtual u8 read_ex(offs_t offset) override;
+ virtual u8 read_m(offs_t offset) override;
+
+ virtual void pcb_reset() override;
+
+protected:
+ // device-level overrides
+ virtual void device_start() override ATTR_COLD;
+
+ TIMER_CALLBACK_MEMBER(irq_timer_tick);
+
+private:
+ u16 m_irq_count;
int m_irq_enable;
+ u8 m_reg;
- static const device_timer_id TIMER_IRQ = 0;
emu_timer *irq_timer;
};
-// ======================> nes_smb2jb_device
+// ======================> nes_l001_device
-class nes_smb2jb_device : public nes_nrom_device
+class nes_l001_device : public nes_nrom_device
{
public:
// construction/destruction
- nes_smb2jb_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
- virtual uint8_t read_m(offs_t offset) override;
- virtual void write_l(offs_t offset, uint8_t data) override;
- virtual void write_ex(offs_t offset, uint8_t data) override;
+ nes_l001_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock);
+
+ virtual void write_h(offs_t offset, u8 data) override;
virtual void pcb_reset() override;
protected:
// device-level overrides
- virtual void device_start() override;
- virtual void device_timer(emu_timer &timer, device_timer_id id, int param, void *ptr) override;
+ virtual void device_start() override ATTR_COLD;
+
+ TIMER_CALLBACK_MEMBER(irq_timer_tick);
private:
- uint16_t m_irq_count;
+ u16 m_irq_count;
+
+ emu_timer *irq_timer;
+};
+
+
+// ======================> nes_batmanfs_device
+
+class nes_batmanfs_device : public nes_nrom_device
+{
+public:
+ // construction/destruction
+ nes_batmanfs_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock);
+
+ virtual void write_h(offs_t offset, u8 data) override;
+
+ virtual void pcb_reset() override;
+
+protected:
+ // device-level overrides
+ virtual void device_start() override ATTR_COLD;
+
+ TIMER_CALLBACK_MEMBER(irq_timer_tick);
+
+private:
+ u16 m_irq_count;
int m_irq_enable;
- static const device_timer_id TIMER_IRQ = 0;
emu_timer *irq_timer;
};
-// ======================> nes_09034a_device
+// ======================> nes_palthena_device
-class nes_09034a_device : public nes_nrom_device
+class nes_palthena_device : public nes_nrom_device
{
public:
// construction/destruction
- nes_09034a_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
+ nes_palthena_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock);
- virtual void write_ex(offs_t offset, uint8_t data) override;
- virtual uint8_t read_m(offs_t offset) override;
+ virtual u8 read_m(offs_t offset) override;
+ virtual u8 read_h(offs_t offset) override;
+ virtual void write_m(offs_t offset, u8 data) override;
+ virtual void write_h(offs_t offset, u8 data) override;
virtual void pcb_reset() override;
protected:
// device-level overrides
- virtual void device_start() override;
+ virtual void device_start() override ATTR_COLD;
private:
- uint8_t m_reg;
+ u8 m_reg;
};
@@ -290,13 +387,81 @@ public:
protected:
// device-level overrides
- virtual void device_start() override;
+ virtual void device_start() override ATTR_COLD;
private:
uint8_t m_latch;
};
+// ======================> nes_whirlwind_device
+
+class nes_whirlwind_device : public nes_nrom_device
+{
+public:
+ virtual u8 read_m(offs_t offset) override;
+
+ virtual void pcb_reset() override;
+
+protected:
+ // construction/destruction
+ nes_whirlwind_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, u32 clock);
+
+ // device-level overrides
+ virtual void device_start() override ATTR_COLD;
+
+ u8 m_reg;
+};
+
+
+// ======================> nes_dh08_device
+
+class nes_dh08_device : public nes_whirlwind_device
+{
+public:
+ // construction/destruction
+ nes_dh08_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock);
+
+ virtual void write_h(offs_t offset, u8 data) override;
+};
+
+
+// ======================> nes_le05_device
+
+class nes_le05_device : public nes_whirlwind_device
+{
+public:
+ // construction/destruction
+ nes_le05_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock);
+
+ virtual void write_h(offs_t offset, u8 data) override;
+};
+
+
+// ======================> nes_lh28_lh54_device
+
+class nes_lh28_lh54_device : public nes_whirlwind_device
+{
+public:
+ // construction/destruction
+ nes_lh28_lh54_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock);
+
+ virtual void write_h(offs_t offset, u8 data) override;
+};
+
+
+// ======================> nes_lh31_device
+
+class nes_lh31_device : public nes_whirlwind_device
+{
+public:
+ // construction/destruction
+ nes_lh31_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock);
+
+ virtual void write_h(offs_t offset, u8 data) override;
+};
+
+
// ======================> nes_lh32_device
class nes_lh32_device : public nes_nrom_device
@@ -314,35 +479,89 @@ public:
protected:
// device-level overrides
- virtual void device_start() override;
+ virtual void device_start() override ATTR_COLD;
private:
uint8_t m_latch;
};
+// ======================> nes_lh42_device
+
+class nes_lh42_device : public nes_nrom_device
+{
+public:
+ // construction/destruction
+ nes_lh42_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock);
+
+ virtual void write_h(offs_t offset, u8 data) override;
+
+ virtual void pcb_reset() override;
+
+protected:
+ // device-level overrides
+ virtual void device_start() override ATTR_COLD;
+
+private:
+ u8 m_latch;
+};
+
+
+// ======================> nes_lg25_device
+
+class nes_lg25_device : public nes_nrom_device
+{
+public:
+ // construction/destruction
+ nes_lg25_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock);
+
+ virtual void write_h(offs_t offset, u8 data) override;
+
+ virtual void pcb_reset() override;
+
+protected:
+ // device-level overrides
+ virtual void device_start() override ATTR_COLD;
+
+private:
+ u8 m_latch;
+};
+
+
// ======================> nes_lh10_device
class nes_lh10_device : public nes_nrom_device
{
public:
// construction/destruction
- nes_lh10_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
+ nes_lh10_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock);
- virtual uint8_t read_h(offs_t offset) override;
- virtual uint8_t read_m(offs_t offset) override;
- virtual void write_h(offs_t offset, uint8_t data) override;
+ virtual u8 read_h(offs_t offset) override;
+ virtual u8 read_m(offs_t offset) override;
+ virtual void write_h(offs_t offset, u8 data) override;
virtual void pcb_reset() override;
protected:
// device-level overrides
- virtual void device_start() override;
+ virtual void device_start() override ATTR_COLD;
private:
- void update_prg();
- uint8_t m_latch;
- uint8_t m_reg[8];
+ u8 m_latch;
+};
+
+
+// ======================> nes_lh51_device
+
+class nes_lh51_device : public nes_nrom_device
+{
+public:
+ // construction/destruction
+ nes_lh51_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock);
+
+ virtual void write_h(offs_t offset, u8 data) override;
+
+ virtual void pcb_reset() override;
};
@@ -363,15 +582,15 @@ public:
protected:
// device-level overrides
- virtual void device_start() override;
- virtual void device_timer(emu_timer &timer, device_timer_id id, int param, void *ptr) override;
+ virtual void device_start() override ATTR_COLD;
+
+ TIMER_CALLBACK_MEMBER(irq_timer_tick);
private:
uint16_t m_irq_count;
int m_irq_enable;
uint8_t m_reg;
- static const device_timer_id TIMER_IRQ = 0;
emu_timer *irq_timer;
attotime timer_freq;
};
@@ -394,12 +613,13 @@ public:
protected:
// device-level overrides
- virtual void device_start() override;
+ virtual void device_start() override ATTR_COLD;
private:
uint8_t m_reg[2];
};
+
// ======================> nes_ac08_device
class nes_ac08_device : public nes_nrom_device
@@ -416,31 +636,12 @@ public:
protected:
// device-level overrides
- virtual void device_start() override;
+ virtual void device_start() override ATTR_COLD;
private:
uint8_t m_latch;
};
-// ======================> nes_unl_bb_device
-
-class nes_unl_bb_device : public nes_nrom_device
-{
-public:
- // construction/destruction
- nes_unl_bb_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
- virtual uint8_t read_m(offs_t offset) override;
- virtual void write_h(offs_t offset, uint8_t data) override;
-
- virtual void pcb_reset() override;
-
-protected:
- // device-level overrides
- virtual void device_start() override;
-
-private:
- uint8_t m_reg[2];
-};
// ======================> nes_mmalee_device
@@ -452,83 +653,85 @@ public:
virtual uint8_t read_m(offs_t offset) override;
virtual void write_m(offs_t offset, uint8_t data) override;
-
- virtual void pcb_reset() override;
-
-protected:
- // device-level overrides
- virtual void device_start() override;
};
-// ======================> nes_shuiguan_device
-class nes_shuiguan_device : public nes_nrom_device
+// ======================> nes_rt01_device
+
+class nes_rt01_device : public nes_nrom_device
{
public:
// construction/destruction
- nes_shuiguan_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
+ nes_rt01_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
- virtual uint8_t read_m(offs_t offset) override;
- virtual void write_h(offs_t offset, uint8_t data) override;
+ virtual uint8_t read_h(offs_t offset) override;
virtual void pcb_reset() override;
-
-protected:
- // device-level overrides
- virtual void device_start() override;
- virtual void device_timer(emu_timer &timer, device_timer_id id, int param, void *ptr) override;
-
-private:
- uint16_t m_irq_count;
- int m_irq_enable;
- uint8_t m_mmc_vrom_bank[8];
-
- static const device_timer_id TIMER_IRQ = 0;
- emu_timer *irq_timer;
};
-// ======================> nes_rt01_device
+// ======================> nes_yung08_device
-class nes_rt01_device : public nes_nrom_device
+class nes_yung08_device : public nes_nrom_device
{
public:
// construction/destruction
- nes_rt01_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
+ nes_yung08_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock);
- virtual uint8_t read_h(offs_t offset) override;
+ virtual u8 read_l(offs_t offset) override;
+ virtual u8 read_m(offs_t offset) override;
+ virtual void write_ex(offs_t offset, u8 data) override;
+ virtual void write_l(offs_t offset, u8 data) override;
virtual void pcb_reset() override;
protected:
// device-level overrides
- virtual void device_start() override;
+ virtual void device_start() override ATTR_COLD;
+
+ TIMER_CALLBACK_MEMBER(irq_timer_tick);
+
+private:
+ void write_45(offs_t offset, u8 data);
+ u16 m_irq_count;
+ int m_irq_latch;
+
+ emu_timer *irq_timer;
};
// device type definition
-DECLARE_DEVICE_TYPE(NES_AX5705, nes_ax5705_device)
DECLARE_DEVICE_TYPE(NES_SC127, nes_sc127_device)
DECLARE_DEVICE_TYPE(NES_MARIOBABY, nes_mbaby_device)
DECLARE_DEVICE_TYPE(NES_ASN, nes_asn_device)
DECLARE_DEVICE_TYPE(NES_SMB3PIRATE, nes_smb3p_device)
+DECLARE_DEVICE_TYPE(NES_BTL_CONTRAJ, nes_btl_cj_device)
DECLARE_DEVICE_TYPE(NES_BTL_DNINJA, nes_btl_dn_device)
-DECLARE_DEVICE_TYPE(NES_WHIRLWIND_2706, nes_whirl2706_device)
DECLARE_DEVICE_TYPE(NES_SMB2J, nes_smb2j_device)
DECLARE_DEVICE_TYPE(NES_SMB2JA, nes_smb2ja_device)
DECLARE_DEVICE_TYPE(NES_SMB2JB, nes_smb2jb_device)
+DECLARE_DEVICE_TYPE(NES_N32_4IN1, nes_n32_4in1_device)
+DECLARE_DEVICE_TYPE(NES_0353, nes_0353_device)
DECLARE_DEVICE_TYPE(NES_09034A, nes_09034a_device)
+DECLARE_DEVICE_TYPE(NES_L001, nes_l001_device)
+DECLARE_DEVICE_TYPE(NES_BATMANFS, nes_batmanfs_device)
+DECLARE_DEVICE_TYPE(NES_PALTHENA, nes_palthena_device)
DECLARE_DEVICE_TYPE(NES_TOBIDASE, nes_tobidase_device)
-DECLARE_DEVICE_TYPE(NES_LH32, nes_lh32_device)
+DECLARE_DEVICE_TYPE(NES_DH08, nes_dh08_device)
+DECLARE_DEVICE_TYPE(NES_LE05, nes_le05_device)
+DECLARE_DEVICE_TYPE(NES_LG25, nes_lg25_device)
DECLARE_DEVICE_TYPE(NES_LH10, nes_lh10_device)
+DECLARE_DEVICE_TYPE(NES_LH28_LH54, nes_lh28_lh54_device)
+DECLARE_DEVICE_TYPE(NES_LH31, nes_lh31_device)
+DECLARE_DEVICE_TYPE(NES_LH32, nes_lh32_device)
+DECLARE_DEVICE_TYPE(NES_LH42, nes_lh42_device)
+DECLARE_DEVICE_TYPE(NES_LH51, nes_lh51_device)
DECLARE_DEVICE_TYPE(NES_LH53, nes_lh53_device)
DECLARE_DEVICE_TYPE(NES_2708, nes_2708_device)
DECLARE_DEVICE_TYPE(NES_AC08, nes_ac08_device)
-DECLARE_DEVICE_TYPE(NES_UNL_BB, nes_unl_bb_device)
DECLARE_DEVICE_TYPE(NES_MMALEE, nes_mmalee_device)
-DECLARE_DEVICE_TYPE(NES_SHUIGUAN, nes_shuiguan_device)
DECLARE_DEVICE_TYPE(NES_RT01, nes_rt01_device)
-
+DECLARE_DEVICE_TYPE(NES_YUNG08, nes_yung08_device)
#endif // MAME_BUS_NES_BOOTLEG_H
diff --git a/src/devices/bus/nes/camerica.cpp b/src/devices/bus/nes/camerica.cpp
index 5870b2911ab..658add539b8 100644
--- a/src/devices/bus/nes/camerica.cpp
+++ b/src/devices/bus/nes/camerica.cpp
@@ -17,9 +17,8 @@
TODO:
- - check what causes flickering from PPU in Fire Hawk, Poogie and Big Nose (same PPU issue as Back to
- Future 2&3?)
- - not all the Golden Five games work. investigate!
+ - check what causes flickering from PPU in Fire Hawk, Pogie and Big Nose Freaks Out (same PPU issue as Back to Future 2&3?)
+ - mapper 232 games need properly dumped to determine if the "alt" BF9096 board really exists.
***********************************************************************************************************/
@@ -29,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"
//-------------------------------------------------
@@ -43,78 +41,80 @@
DEFINE_DEVICE_TYPE(NES_BF9093, nes_bf9093_device, "nes_bf9093", "NES Cart Camerica BF9093 PCB")
DEFINE_DEVICE_TYPE(NES_BF9096, nes_bf9096_device, "nes_bf9096", "NES Cart Camerica BF9096 PCB")
+DEFINE_DEVICE_TYPE(NES_BF9096A, nes_bf9096a_device, "nes_bf9096a", "NES Cart Camerica BF9096 Alt PCB")
DEFINE_DEVICE_TYPE(NES_GOLDEN5, nes_golden5_device, "nes_golden5", "NES Cart Camerica Golden 5 PCB")
-nes_bf9093_device::nes_bf9093_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
+nes_bf9093_device::nes_bf9093_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock)
: nes_nrom_device(mconfig, NES_BF9093, tag, owner, clock)
{
}
-nes_bf9096_device::nes_bf9096_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
- : nes_nrom_device(mconfig, NES_BF9096, tag, owner, clock), m_bank_base(0), m_latch(0)
+nes_bf9096_device::nes_bf9096_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, u32 clock, bool page_swap)
+ : nes_nrom_device(mconfig, type, tag, owner, clock), m_reg(0), m_page_swap(page_swap)
{
}
-nes_golden5_device::nes_golden5_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
- : nes_nrom_device(mconfig, NES_GOLDEN5, tag, owner, clock), m_bank_base(0), m_latch(0)
+nes_bf9096_device::nes_bf9096_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock)
+ : nes_bf9096_device(mconfig, NES_BF9096, tag, owner, clock, false)
{
}
+nes_bf9096a_device::nes_bf9096a_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock)
+ : nes_bf9096_device(mconfig, NES_BF9096A, tag, owner, clock, true)
+{
+}
-
-
-void nes_bf9093_device::device_start()
+nes_golden5_device::nes_golden5_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock)
+ : nes_nrom_device(mconfig, NES_GOLDEN5, tag, owner, clock), m_lock(0), m_reg(0)
{
- common_start();
}
+
+
+
void nes_bf9093_device::pcb_reset()
{
- m_chr_source = m_vrom_chunks ? CHRROM : CHRRAM;
- prg32(0xff);
- chr8(0, m_chr_source);
+ prg16_89ab(0);
+ prg16_cdef(m_prg_chunks - 1);
+ if (m_pcb_ctrl_mirror)
+ set_nt_mirroring(PPU_MIRROR_LOW);
}
void nes_bf9096_device::device_start()
{
common_start();
- save_item(NAME(m_latch));
- save_item(NAME(m_bank_base));
+ save_item(NAME(m_reg));
}
void nes_bf9096_device::pcb_reset()
{
- m_chr_source = m_vrom_chunks ? CHRROM : CHRRAM;
- chr8(0, m_chr_source);
+ prg16_89ab(0);
+ prg16_cdef(3);
- m_latch = 0x00;
- m_bank_base = 0x0c;
- prg16_89ab(m_bank_base | m_latch);
- prg16_cdef(m_bank_base | 3);
+ m_reg = 0;
}
void nes_golden5_device::device_start()
{
common_start();
- save_item(NAME(m_latch));
+ save_item(NAME(m_lock));
+ save_item(NAME(m_reg));
+
+ // these are not cleared on reset
+ m_lock = 0;
+ m_reg = 0;
}
void nes_golden5_device::pcb_reset()
{
- m_chr_source = m_vrom_chunks ? CHRROM : CHRRAM;
- chr8(0, m_chr_source);
-
- m_latch = 0x00;
- m_bank_base = 0x00;
- prg16_89ab(m_bank_base | m_latch);
- prg16_cdef(m_bank_base | 0x0f);
+ prg16_89ab(m_reg);
+ prg16_cdef(m_reg | 0x0f);
}
-
/*-------------------------------------------------
mapper specific handlers
-------------------------------------------------*/
@@ -132,25 +132,22 @@ void nes_golden5_device::pcb_reset()
iNES: mapper 71
- In MESS: Partially Supported.
+ In MAME: Partially supported.
-------------------------------------------------*/
-void nes_bf9093_device::write_h(offs_t offset, uint8_t data)
+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 & 0x7000)
+ switch (offset & 0x6000)
{
case 0x0000:
- case 0x1000:
if (m_pcb_ctrl_mirror)
set_nt_mirroring(BIT(data, 4) ? PPU_MIRROR_HIGH : PPU_MIRROR_LOW);
break;
case 0x4000:
- case 0x5000:
case 0x6000:
- case 0x7000:
prg16_89ab(data);
break;
}
@@ -170,24 +167,26 @@ void nes_bf9093_device::write_h(offs_t offset, uint8_t data)
iNES: mapper 232
- In MESS: Supported.
+ In MAME: Supported.
-------------------------------------------------*/
-void nes_bf9096_device::write_h(offs_t offset, uint8_t 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)
{
- m_bank_base = ((data >> 3) & 3) << 2;
- prg16_89ab(m_bank_base | m_latch);
- prg16_cdef(m_bank_base | 3);
+ m_reg = (m_reg & 0x03) | (data & 0x18) >> 1;
+ if (m_page_swap)
+ m_reg = bitswap<4>(m_reg, 2, 3, 1, 0);
+ prg16_89ab(m_reg);
+ prg16_cdef(m_reg | 0x03);
}
else
{
- m_latch = data & 3;
- prg16_89ab(m_bank_base | m_latch);
+ m_reg = (m_reg & 0x0c) | (data & 0x03);
+ prg16_89ab(m_reg);
}
}
@@ -199,27 +198,24 @@ void nes_bf9096_device::write_h(offs_t offset, uint8_t data)
iNES: mapper 104
- In MESS: Supported.
+ In MAME: Supported.
-------------------------------------------------*/
-void nes_golden5_device::write_h(offs_t offset, uint8_t 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)
+ if (offset >= 0x4000)
{
- if (data & 0x08)
- {
- m_bank_base = (data & 0x07) << 4;
- prg16_89ab(m_bank_base | m_latch);
- prg16_cdef(m_bank_base | 0x0f);
- }
-
+ m_reg = (m_reg & 0x70) | (data & 0x0f);
+ prg16_89ab(m_reg);
}
- else
+ else if (!m_lock)
{
- m_latch = data & 0x0f;
- prg16_89ab(m_bank_base | m_latch);
+ m_lock = BIT(data, 3);
+ m_reg = (m_reg & 0x0f) | (data & 0x07) << 4;
+ prg16_89ab(m_reg);
+ prg16_cdef(m_reg | 0x0f);
}
}
diff --git a/src/devices/bus/nes/camerica.h b/src/devices/bus/nes/camerica.h
index 7688249a64c..6dcd3fd79a6 100644
--- a/src/devices/bus/nes/camerica.h
+++ b/src/devices/bus/nes/camerica.h
@@ -14,15 +14,11 @@ class nes_bf9093_device : public nes_nrom_device
{
public:
// construction/destruction
- nes_bf9093_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
+ nes_bf9093_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock);
- virtual void write_h(offs_t offset, uint8_t data) override;
+ virtual void write_h(offs_t offset, u8 data) override;
virtual void pcb_reset() override;
-
-protected:
- // device-level overrides
- virtual void device_start() override;
};
@@ -32,19 +28,31 @@ class nes_bf9096_device : public nes_nrom_device
{
public:
// construction/destruction
- nes_bf9096_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
+ nes_bf9096_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock);
- virtual void write_h(offs_t offset, uint8_t data) override;
- virtual void write_m(offs_t offset, uint8_t data) override { write_h(offset, data); }
+ virtual void write_h(offs_t offset, u8 data) override;
virtual void pcb_reset() override;
protected:
+ nes_bf9096_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, u32 clock, bool page_swap);
+
// device-level overrides
- virtual void device_start() override;
+ virtual void device_start() override ATTR_COLD;
private:
- uint8_t m_bank_base, m_latch;
+ u8 m_reg;
+ const bool m_page_swap;
+};
+
+
+// ======================> nes_bf9096a_device
+
+class nes_bf9096a_device : public nes_bf9096_device
+{
+public:
+ // construction/destruction
+ nes_bf9096a_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock);
};
@@ -54,24 +62,25 @@ class nes_golden5_device : public nes_nrom_device
{
public:
// construction/destruction
- nes_golden5_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
+ nes_golden5_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock);
- virtual void write_h(offs_t offset, uint8_t data) override;
+ virtual void write_h(offs_t offset, u8 data) override;
virtual void pcb_reset() override;
protected:
// device-level overrides
- virtual void device_start() override;
+ virtual void device_start() override ATTR_COLD;
private:
- uint8_t m_bank_base, m_latch;
+ u8 m_lock, m_reg;
};
// device type definition
DECLARE_DEVICE_TYPE(NES_BF9093, nes_bf9093_device)
DECLARE_DEVICE_TYPE(NES_BF9096, nes_bf9096_device)
+DECLARE_DEVICE_TYPE(NES_BF9096A, nes_bf9096a_device)
DECLARE_DEVICE_TYPE(NES_GOLDEN5, nes_golden5_device)
#endif // MAME_BUS_NES_CAMERICA_H
diff --git a/src/devices/bus/nes/cne.cpp b/src/devices/bus/nes/cne.cpp
index c81e7a2bdc8..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"
//-------------------------------------------------
@@ -37,59 +36,29 @@ DEFINE_DEVICE_TYPE(NES_CNE_FSB, nes_cne_fsb_device, "nes_cne_fsb", "NES
DEFINE_DEVICE_TYPE(NES_CNE_SHLZ, nes_cne_shlz_device, "nes_cne_shlz", "NES Cart C&E Sheng Huo Lie Zhuan PCB")
-nes_cne_decathl_device::nes_cne_decathl_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
+nes_cne_decathl_device::nes_cne_decathl_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock)
: nes_nrom_device(mconfig, NES_CNE_DECATHL, tag, owner, clock)
{
}
-nes_cne_fsb_device::nes_cne_fsb_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
+nes_cne_fsb_device::nes_cne_fsb_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock)
: nes_nrom_device(mconfig, NES_CNE_FSB, tag, owner, clock)
{
}
-nes_cne_shlz_device::nes_cne_shlz_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
+nes_cne_shlz_device::nes_cne_shlz_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock)
: nes_nrom_device(mconfig, NES_CNE_SHLZ, tag, owner, clock)
{
}
-void nes_cne_decathl_device::device_start()
-{
- common_start();
-}
-
-void nes_cne_decathl_device::pcb_reset()
-{
- m_chr_source = m_vrom_chunks ? CHRROM : CHRRAM;
- prg32(0);
- chr8(0, m_chr_source);
-}
-
-void nes_cne_fsb_device::device_start()
-{
- common_start();
-}
-
void nes_cne_fsb_device::pcb_reset()
{
- m_chr_source = m_vrom_chunks ? CHRROM : CHRRAM;
prg32(0xff);
chr8(0, m_chr_source);
}
-void nes_cne_shlz_device::device_start()
-{
- common_start();
-}
-
-void nes_cne_shlz_device::pcb_reset()
-{
- m_chr_source = m_vrom_chunks ? CHRROM : CHRRAM;
- prg32(0);
- chr8(0, m_chr_source);
-}
-
@@ -108,24 +77,20 @@ void nes_cne_shlz_device::pcb_reset()
iNES: mapper 244
- In MESS: Supported.
+ In MAME: Supported.
-------------------------------------------------*/
-void nes_cne_decathl_device::write_h(offs_t offset, uint8_t data)
+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)
- return;
- if (offset < 0x00a5)
- {
- prg32((offset - 0x0065) & 0x03);
- return;
- }
- if (offset < 0x00e5)
+ if (offset >= 0x0065)
{
- chr8((offset - 0x00a5) & 0x07, CHRROM);
+ if (offset < 0x00a5)
+ prg32((offset - 0x0065) & 0x03);
+ else if (offset < 0x00e5)
+ chr8((offset - 0x00a5) & 0x07, CHRROM);
}
}
@@ -142,56 +107,44 @@ void nes_cne_decathl_device::write_h(offs_t offset, uint8_t data)
iNES: mapper 246
- In MESS: Supported.
+ In MAME: Supported.
-------------------------------------------------*/
-void nes_cne_fsb_device::write_m(offs_t offset, uint8_t 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)
{
switch (offset & 0x0007)
{
case 0x0000:
- prg8_89(data);
- break;
case 0x0001:
- prg8_ab(data);
- break;
case 0x0002:
- prg8_cd(data);
- break;
case 0x0003:
- prg8_ef(data);
+ prg8_x(offset & 0x03, data);
break;
case 0x0004:
- chr2_0(data, CHRROM);
- break;
case 0x0005:
- chr2_2(data, CHRROM);
- break;
case 0x0006:
- chr2_4(data, CHRROM);
- break;
case 0x0007:
- chr2_6(data, CHRROM);
+ chr2_x((offset & 0x03) << 1, data, CHRROM);
break;
}
}
else
- m_battery[offset] = data;
+ device_nes_cart_interface::write_m(offset, data);
}
-uint8_t nes_cne_fsb_device::read_m(offs_t offset)
+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 m_battery[offset];
+ return device_nes_cart_interface::read_m(offset);
- return 0xff;
+ return get_open_bus();
}
/*-------------------------------------------------
@@ -207,13 +160,13 @@ uint8_t nes_cne_fsb_device::read_m(offs_t offset)
iNES: mapper 240
- In MESS: Supported.
+ In MAME: Supported.
-------------------------------------------------*/
-void nes_cne_shlz_device::write_l(offs_t offset, uint8_t data)
+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/cne.h b/src/devices/bus/nes/cne.h
index da0623cbde3..9e704443503 100644
--- a/src/devices/bus/nes/cne.h
+++ b/src/devices/bus/nes/cne.h
@@ -14,15 +14,9 @@ class nes_cne_decathl_device : public nes_nrom_device
{
public:
// construction/destruction
- nes_cne_decathl_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
+ nes_cne_decathl_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock);
- virtual void write_h(offs_t offset, uint8_t data) override;
-
- virtual void pcb_reset() override;
-
-protected:
- // device-level overrides
- virtual void device_start() override;
+ virtual void write_h(offs_t offset, u8 data) override;
};
@@ -32,16 +26,12 @@ class nes_cne_fsb_device : public nes_nrom_device
{
public:
// construction/destruction
- nes_cne_fsb_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
+ nes_cne_fsb_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock);
- virtual uint8_t read_m(offs_t offset) override;
- virtual void write_m(offs_t offset, uint8_t data) override;
+ virtual u8 read_m(offs_t offset) override;
+ virtual void write_m(offs_t offset, u8 data) override;
virtual void pcb_reset() override;
-
-protected:
- // device-level overrides
- virtual void device_start() override;
};
@@ -51,15 +41,9 @@ class nes_cne_shlz_device : public nes_nrom_device
{
public:
// construction/destruction
- nes_cne_shlz_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
-
- virtual void write_l(offs_t offset, uint8_t data) override;
-
- virtual void pcb_reset() override;
+ nes_cne_shlz_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock);
-protected:
- // device-level overrides
- virtual void device_start() override;
+ virtual void write_l(offs_t offset, u8 data) override;
};
diff --git a/src/devices/bus/nes/cony.cpp b/src/devices/bus/nes/cony.cpp
index e42ae833f82..1b56fa36ce2 100644
--- a/src/devices/bus/nes/cony.cpp
+++ b/src/devices/bus/nes/cony.cpp
@@ -9,9 +9,7 @@
Here we emulate the following PCBs
* UNL-CONY [mapper 83]
- * UNL-YOKO
-
- TODO: fix glitches and emulate properly the variants
+ * UNL-YOKO [mapper 264]
***********************************************************************************************************/
@@ -21,124 +19,81 @@
#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"
//-------------------------------------------------
// constructor
//-------------------------------------------------
-DEFINE_DEVICE_TYPE(NES_CONY, nes_cony_device, "nes_cony", "NES Cart Cony PCB")
-DEFINE_DEVICE_TYPE(NES_YOKO, nes_yoko_device, "nes_yoko", "NES Cart Yoko PCB")
+DEFINE_DEVICE_TYPE(NES_CONY, nes_cony_device, "nes_cony", "NES Cart Cony PCB")
+DEFINE_DEVICE_TYPE(NES_CONY1K, nes_cony1k_device, "nes_cony1k", "NES Cart Cony 1K PCB")
+DEFINE_DEVICE_TYPE(NES_YOKO, nes_yoko_device, "nes_yoko", "NES Cart Yoko PCB")
-nes_cony_device::nes_cony_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock)
- : nes_nrom_device(mconfig, type, tag, owner, clock)
- , m_irq_count(0)
- , m_irq_enable(0)
- , irq_timer(nullptr)
- , m_latch1(0)
- , m_latch2(0)
- , m_extra1(0)
+nes_cony_device::nes_cony_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, u32 clock, u16 extra_addr, u8 mask)
+ : nes_nrom_device(mconfig, type, tag, owner, clock), m_irq_count(0), m_irq_enable(0), irq_timer(nullptr), m_extra_addr(extra_addr), m_mask(mask), m_mode_reg(0), m_outer_reg(0)
{
}
-nes_cony_device::nes_cony_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
- : nes_cony_device(mconfig, NES_CONY, tag, owner, clock)
+nes_cony_device::nes_cony_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock)
+ : nes_cony_device(mconfig, NES_CONY, tag, owner, clock, 0x1100, 0x1f)
{
}
-nes_yoko_device::nes_yoko_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
- : nes_cony_device(mconfig, NES_YOKO, tag, owner, clock), m_extra2(0)
+nes_cony1k_device::nes_cony1k_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock)
+ : nes_cony_device(mconfig, NES_CONY1K, tag, owner, clock, 0x1100, 0x1f)
{
}
-
-
-
-void nes_cony_device::device_start()
+nes_yoko_device::nes_yoko_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock)
+ : nes_cony_device(mconfig, NES_YOKO, tag, owner, clock, 0x1400, 0x0f)
{
- common_start();
- irq_timer = timer_alloc(TIMER_IRQ);
- irq_timer->adjust(attotime::zero, 0, clocks_to_attotime(1));
-
- save_item(NAME(m_irq_enable));
- save_item(NAME(m_irq_count));
-
- save_item(NAME(m_low_reg));
- save_item(NAME(m_reg));
- save_item(NAME(m_extra1));
- save_item(NAME(m_latch1));
- save_item(NAME(m_latch2));
}
-void nes_cony_device::pcb_reset()
-{
- m_chr_source = m_vrom_chunks ? CHRROM : CHRRAM;
- prg16_89ab(0);
- prg8_cd(0x1e);
- prg8_ef(0x1f);
- chr8(0, m_chr_source);
- m_irq_enable = 0;
- m_irq_count = 0;
- m_latch1 = 0;
- m_latch2 = 0;
- m_extra1 = 0;
- memset(m_low_reg, 0, sizeof(m_low_reg));
- memset(m_reg, 0, sizeof(m_reg));
- m_reg[9] = 0x0f;
-}
-
-void nes_yoko_device::device_start()
+void nes_cony_device::device_start()
{
common_start();
- irq_timer = timer_alloc(TIMER_IRQ);
+ irq_timer = timer_alloc(FUNC(nes_cony_device::irq_timer_tick), this);
irq_timer->adjust(attotime::zero, 0, clocks_to_attotime(1));
save_item(NAME(m_irq_enable));
save_item(NAME(m_irq_count));
- save_item(NAME(m_low_reg));
- save_item(NAME(m_reg));
- save_item(NAME(m_extra1));
- save_item(NAME(m_extra2));
- save_item(NAME(m_latch1));
- save_item(NAME(m_latch2));
+ save_item(NAME(m_mmc_prg_bank));
+ save_item(NAME(m_mmc_vrom_bank));
+ save_item(NAME(m_extra_ram));
+ save_item(NAME(m_mode_reg));
+ save_item(NAME(m_outer_reg));
}
-void nes_yoko_device::pcb_reset()
+void nes_cony_device::pcb_reset()
{
- m_chr_source = m_vrom_chunks ? CHRROM : CHRRAM;
prg16_89ab(0);
- prg8_cd(0x1e);
- prg8_ef(0x1f);
- chr8(0, m_chr_source);
+ prg16_cdef(m_prg_chunks - 1);
+ chr8(0, CHRROM);
m_irq_enable = 0;
m_irq_count = 0;
- m_latch1 = 0;
- m_latch2 = 0;
- m_extra1 = 0;
- m_extra2 = 0;
+ m_mode_reg = 0;
+ m_outer_reg = 0;
- memset(m_low_reg, 0, sizeof(m_low_reg));
- memset(m_reg, 0, sizeof(m_reg));
- m_reg[9] = 0x0f;
+ std::fill(std::begin(m_extra_ram), std::end(m_extra_ram), 0x00);
+ std::fill(std::begin(m_mmc_prg_bank), std::end(m_mmc_prg_bank), 0x00);
+ std::fill(std::begin(m_mmc_vrom_bank), std::end(m_mmc_vrom_bank), 0x00);
}
-
/*-------------------------------------------------
mapper specific handlers
-------------------------------------------------*/
@@ -152,250 +107,180 @@ void nes_yoko_device::pcb_reset()
iNES: mapper 83
- In MESS: Supported.
+ In MAME: Supported.
-------------------------------------------------*/
-void nes_cony_device::device_timer(emu_timer &timer, device_timer_id id, int param, void *ptr)
+TIMER_CALLBACK_MEMBER(nes_cony_device::irq_timer_tick)
{
- if (id == TIMER_IRQ)
+ if (m_irq_enable)
{
- if (m_irq_enable)
+ m_irq_count += BIT(m_mode_reg, 6) ? -1 : 1;
+ if (!m_irq_count)
{
- if (!m_irq_count)
- {
- hold_irq_line();
- m_irq_enable = 0;
- m_irq_count = 0xffff;
- }
- else
- m_irq_count--;
+ set_irq_line(ASSERT_LINE);
+ m_irq_enable = 0;
}
}
}
-void nes_cony_device::write_l(offs_t offset, uint8_t data)
+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);
- if (offset >= 0x1000 && offset < 0x1103) // from 0x5100-0x51ff
- m_low_reg[offset & 0x03] = data;
+ offset += 0x100;
+ if (offset >= m_extra_addr) // scratch ram from 0x5100 or 0x5400
+ m_extra_ram[offset & 0x03] = data;
}
-uint8_t nes_cony_device::read_l(offs_t offset)
+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);
- if (offset == 0x0f00) // 0x5000
- {
- // read dipswitch bit! - currently unimplemented
- }
- if (offset >= 0x1000 && offset < 0x1103) // from 0x5100-0x51ff
- return m_low_reg[offset & 0x03];
+ offset += 0x100;
+ if (offset >= m_extra_addr) // scratch ram from 0x5100 or 0x5400
+ return m_extra_ram[offset & 0x03];
+ else if (offset >= 0x1000) // 0x5000
+ return m_extra_addr >> 10; // FIXME: this should be 2-bit jumper settings; certain games glitch with certain values here
else
- return 0x00;
+ return get_open_bus();
}
-void nes_cony_device::set_prg()
+void nes_cony_device::write_m(offs_t offset, u8 data)
{
- prg16_89ab(m_reg[8] & 0x3f);
- prg16_cdef((m_reg[8] & 0x30) | 0x0f);
+ 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;
}
-void nes_cony_device::set_chr()
+u8 nes_cony_device::read_m(offs_t offset)
{
- // FIXME: here we emulate at least 3 different boards!!!
- // one board switches 1k VROM banks only
- // one writes to 0x8000 and then switches 2k VROM banks only
- // one writes to 0x831n (n=2,3,4,5) and then switches 2k VROM banks only
- // we should split them and possibly document the proper behavior of each variant
- if (m_latch1 && !m_latch2)
- {
- chr2_0(m_reg[0], CHRROM);
- chr2_2(m_reg[1], CHRROM);
- chr2_4(m_reg[6], CHRROM);
- chr2_6(m_reg[7], CHRROM);
- }
+ 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)];
+ else if (BIT(m_mode_reg, 5))
+ return m_prg[(m_mmc_prg_bank[3] * 0x2000 + offset) & (m_prg_size - 1)];
else
+ return get_open_bus();
+}
+
+void nes_cony_device::set_prg()
+{
+ switch (m_mode_reg & 0x18)
{
- chr1_0(m_reg[0] | ((m_reg[8] & 0x30) << 4), CHRROM);
- chr1_1(m_reg[1] | ((m_reg[8] & 0x30) << 4), CHRROM);
- chr1_2(m_reg[2] | ((m_reg[8] & 0x30) << 4), CHRROM);
- chr1_3(m_reg[3] | ((m_reg[8] & 0x30) << 4), CHRROM);
- chr1_4(m_reg[4] | ((m_reg[8] & 0x30) << 4), CHRROM);
- chr1_5(m_reg[5] | ((m_reg[8] & 0x30) << 4), CHRROM);
- chr1_6(m_reg[6] | ((m_reg[8] & 0x30) << 4), CHRROM);
- chr1_7(m_reg[7] | ((m_reg[8] & 0x30) << 4), CHRROM);
+ case 0x00:
+ prg16_89ab(m_outer_reg);
+ prg16_cdef(m_outer_reg | m_mask >> 1);
+ break;
+ case 0x08:
+ prg32(m_outer_reg >> 1);
+ break;
+ case 0x10:
+ case 0x18:
+ {
+ int base = (m_outer_reg << 1) & ~m_mask;
+ prg8_89(base | (m_mmc_prg_bank[0] & m_mask));
+ prg8_ab(base | (m_mmc_prg_bank[1] & m_mask));
+ prg8_cd(base | (m_mmc_prg_bank[2] & m_mask));
+ prg8_ef(base | m_mask);
+ break;
+ }
}
}
-void nes_cony_device::write_h(offs_t offset, uint8_t data)
+void nes_cony_device::set_chr()
{
- LOG_MMC(("cony write_h, offset: %04x, data: %02x\n", offset, data));
+ chr2_0(m_mmc_vrom_bank[0], CHRROM);
+ chr2_2(m_mmc_vrom_bank[1], CHRROM);
+ chr2_4(m_mmc_vrom_bank[6], CHRROM);
+ chr2_6(m_mmc_vrom_bank[7], CHRROM);
+}
- switch (offset)
+void nes_cony_device::write_h(offs_t offset, u8 data)
+{
+ LOG("cony write_h, offset: %04x, data: %02x\n", offset, data);
+
+ switch (offset & 0x0300)
{
case 0x0000:
- m_latch1 = 1;
- case 0x3000:
- case 0x30ff:
- case 0x31ff:
- m_reg[8] = data;
+ m_outer_reg = data;
set_prg();
set_chr();
break;
case 0x0100:
- m_extra1 = data & 0x80;
+ m_mode_reg = data;
+ set_prg();
switch (data & 0x03)
{
- case 0:
- set_nt_mirroring(PPU_MIRROR_VERT);
- break;
- case 1:
- set_nt_mirroring(PPU_MIRROR_HORZ);
- break;
- case 2:
- set_nt_mirroring(PPU_MIRROR_LOW);
- break;
- case 3:
- set_nt_mirroring(PPU_MIRROR_HIGH);
- break;
+ case 0: set_nt_mirroring(PPU_MIRROR_VERT); break;
+ case 1: set_nt_mirroring(PPU_MIRROR_HORZ); break;
+ case 2: set_nt_mirroring(PPU_MIRROR_LOW); break;
+ case 3: set_nt_mirroring(PPU_MIRROR_HIGH); break;
}
break;
case 0x0200:
- m_irq_count = (m_irq_count & 0xff00) | data;
- break;
- case 0x0201:
- m_irq_enable = m_extra1;
- m_irq_count = (data << 8) | (m_irq_count & 0xff);
+ if (offset & 1)
+ {
+ m_irq_enable = BIT(m_mode_reg, 7);
+ m_irq_count = data << 8 | (m_irq_count & 0x00ff);
+ }
+ else
+ {
+ m_irq_count = (m_irq_count & 0xff00) | data;
+ set_irq_line(CLEAR_LINE);
+ }
break;
case 0x0300:
- prg8_89(data);
- break;
- case 0x0301:
- prg8_ab(data);
- break;
- case 0x0302:
- prg8_cd(data);
- break;
- case 0x0312:
- case 0x0313:
- case 0x0314:
- case 0x0315:
- m_latch2 = 1;
- case 0x0310:
- case 0x0311:
- case 0x0316:
- case 0x0317:
- m_reg[offset - 0x0310] = data;
- set_chr();
- break;
- case 0x0318:
- m_reg[9] = data; // unused?
- set_prg();
+ switch (offset & 0x18)
+ {
+ case 0x00:
+ case 0x08:
+ m_mmc_prg_bank[offset & 3] = data;
+ set_prg();
+ break;
+ case 0x10:
+ m_mmc_vrom_bank[offset & 7] = data;
+ set_chr();
+ break;
+ }
break;
}
}
/*-------------------------------------------------
- Yoko Bootleg Board
-
- Games: Mortal Kombat II, Master Figther VI'
-
-
- Very similar to Cony board
-
- In MESS: Supported.
+ Cony Bootleg Board alternate 1K CHR banking
-------------------------------------------------*/
-void nes_yoko_device::write_l(offs_t offset, uint8_t data)
+void nes_cony1k_device::set_chr()
{
- LOG_MMC(("yoko write_l, offset: %04x, data: %02x\n", offset, data));
-
- if (offset >= 0x1300) // from 0x5400
- m_low_reg[offset & 0x03] = data;
+ for (int i = 0; i < 8; i++)
+ chr1_x(i, m_mmc_vrom_bank[i] | (m_outer_reg & 0x30) << 4, CHRROM);
}
-uint8_t nes_yoko_device::read_l(offs_t offset)
-{
- LOG_MMC(("yoko read_l, offset: %04x\n", offset));
+/*-------------------------------------------------
- if (offset >= 0x0f00 && offset < 0x1300) // 0x5000
- {
- // read dipswitch bit! - currently unimplemented
- }
- if (offset >= 0x1300) // from 0x5400
- return m_low_reg[offset & 0x03];
- else
- return 0x00;
-}
+ Yoko Bootleg Board
-void nes_yoko_device::set_prg()
-{
- if (m_extra1 & 0x10)
- {
- int base = (m_extra2 & 0x08) << 1;
- prg8_89(base | (m_reg[0] & 0x0f));
- prg8_ab(base | (m_reg[1] & 0x0f));
- prg8_cd(base | (m_reg[2] & 0x0f));
- prg8_ef(base | 0x0f);
- }
- else if (m_extra1 & 0x08)
- prg32(m_extra2 >> 1);
- else
- {
- prg16_89ab(m_extra2);
- prg16_cdef(0xff);
- }
-}
+ Games: Mortal Kombat II, Master Fighter VI'
-void nes_yoko_device::set_chr()
-{
- chr2_0(m_reg[4], CHRROM);
- chr2_2(m_reg[5], CHRROM);
- chr2_4(m_reg[6], CHRROM);
- chr2_6(m_reg[7], CHRROM);
-}
+ Seems to be the same as the Cony board (2K CHR
+ banking version) but with address lines A10/A11
+ swapped in for Cony address lines A8/A9.
+
+ NES 2.0: mapper 264
+
+ In MAME: Supported.
-void nes_yoko_device::write_h(offs_t offset, uint8_t data)
+ -------------------------------------------------*/
+
+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);
- switch (offset & 0x0c17)
- {
- case 0x0000:
- m_extra2 = data;
- set_prg();
- break;
- case 0x400:
- m_extra1 = data;
- if (data & 1)
- set_nt_mirroring(PPU_MIRROR_HORZ);
- else
- set_nt_mirroring(PPU_MIRROR_VERT);
- set_prg();
- break;
- case 0x0800:
- m_irq_count = (m_irq_count & 0xff00) | data;
- break;
- case 0x0801:
- m_irq_enable = m_extra1 & 0x80;
- m_irq_count = (data << 8) | (m_irq_count & 0xff);
- break;
- case 0x0c00:
- case 0x0c01:
- case 0x0c02:
- m_reg[offset & 3] = data;
- set_prg();
- break;
- case 0x0c10:
- case 0x0c11:
- case 0x0c16:
- case 0x0c17:
- m_reg[4 + (offset & 3)] = data;
- set_chr();
- break;
- }
+ offset = (offset & 0xf0ff) | (offset & 0x0c00) >> 2;
+ nes_cony_device::write_h(offset, data);
}
diff --git a/src/devices/bus/nes/cony.h b/src/devices/bus/nes/cony.h
index aa767a88c13..0d25e08e94c 100644
--- a/src/devices/bus/nes/cony.h
+++ b/src/devices/bus/nes/cony.h
@@ -14,66 +14,70 @@ class nes_cony_device : public nes_nrom_device
{
public:
// construction/destruction
- nes_cony_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
+ nes_cony_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock);
- virtual uint8_t read_l(offs_t offset) override;
- virtual void write_l(offs_t offset, uint8_t data) override;
- virtual void write_h(offs_t offset, uint8_t data) override;
+ virtual u8 read_l(offs_t offset) override;
+ virtual u8 read_m(offs_t offset) override;
+ virtual void write_l(offs_t offset, u8 data) override;
+ virtual void write_m(offs_t offset, u8 data) override;
+ virtual void write_h(offs_t offset, u8 data) override;
virtual void pcb_reset() override;
protected:
- static constexpr device_timer_id TIMER_IRQ = 0;
-
- nes_cony_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock);
+ // construction/destruction
+ nes_cony_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, u32 clock, u16 extra_addr, u8 mask);
// device-level overrides
- virtual void device_start() override;
- virtual void device_timer(emu_timer &timer, device_timer_id id, int param, void *ptr) override;
+ virtual void device_start() override ATTR_COLD;
virtual void set_prg();
virtual void set_chr();
- uint16_t m_irq_count;
+ TIMER_CALLBACK_MEMBER(irq_timer_tick);
+
+ u16 m_irq_count;
int m_irq_enable;
emu_timer *irq_timer;
- uint8_t m_latch1, m_latch2;
- uint8_t m_low_reg[4];
- uint8_t m_reg[10];
- uint8_t m_extra1;
+ u8 m_mmc_prg_bank[4];
+ u8 m_mmc_vrom_bank[8];
+ u8 m_extra_ram[4];
+ const u16 m_extra_addr;
+ const u8 m_mask;
+ u8 m_mode_reg;
+ u8 m_outer_reg;
};
-// ======================> nes_yoko_device
+// ======================> nes_cony1k_device
-class nes_yoko_device : public nes_cony_device
+class nes_cony1k_device : public nes_cony_device
{
public:
// construction/destruction
- nes_yoko_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
+ nes_cony1k_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock);
- virtual uint8_t read_l(offs_t offset) override;
- virtual void write_l(offs_t offset, uint8_t data) override;
- virtual void write_h(offs_t offset, uint8_t data) override;
+ virtual void set_chr() override;
+};
- virtual void pcb_reset() override;
-protected:
- // device-level overrides
- virtual void device_start() override;
+// ======================> nes_yoko_device
-private:
- virtual void set_prg() override;
- virtual void set_chr() override;
+class nes_yoko_device : public nes_cony_device
+{
+public:
+ // construction/destruction
+ nes_yoko_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock);
- uint8_t m_extra2;
+ virtual void write_h(offs_t offset, u8 data) override;
};
// device type definition
-DECLARE_DEVICE_TYPE(NES_CONY, nes_cony_device)
-DECLARE_DEVICE_TYPE(NES_YOKO, nes_yoko_device)
+DECLARE_DEVICE_TYPE(NES_CONY, nes_cony_device)
+DECLARE_DEVICE_TYPE(NES_CONY1K, nes_cony1k_device)
+DECLARE_DEVICE_TYPE(NES_YOKO, nes_yoko_device)
#endif // MAME_BUS_NES_CONY_H
diff --git a/src/devices/bus/nes/datach.cpp b/src/devices/bus/nes/datach.cpp
index 5262b6d927a..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
//--------------------------------
@@ -42,7 +40,7 @@
//-------------------------------------------------
datach_cart_interface::datach_cart_interface(const machine_config &mconfig, device_t &device)
- : device_slot_card_interface(mconfig, device)
+ : device_interface(device, "datachcart")
, m_i2cmem(*this, "i2cmem")
, m_rom(nullptr), m_bank(0)
{
@@ -68,8 +66,8 @@ DEFINE_DEVICE_TYPE(NES_DATACH_SLOT, nes_datach_slot_device, "nes_datach_slot", "
nes_datach_slot_device::nes_datach_slot_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
: device_t(mconfig, NES_DATACH_SLOT, tag, owner, clock)
- , device_image_interface(mconfig, *this)
- , device_slot_interface(mconfig, *this)
+ , device_cartrom_image_interface(mconfig, *this)
+ , device_single_card_slot_interface<datach_cart_interface>(mconfig, *this)
, m_cart(nullptr)
{
}
@@ -81,31 +79,30 @@ nes_datach_slot_device::~nes_datach_slot_device()
void nes_datach_slot_device::device_start()
{
- m_cart = dynamic_cast<datach_cart_interface *>(get_card_device());
+ m_cart = get_card_device();
}
uint8_t nes_datach_slot_device::read(offs_t offset)
{
if (m_cart)
return m_cart->read(offset);
-
- return 0xff;
+ else
+ 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());
}
@@ -231,8 +230,8 @@ nes_datach_device::nes_datach_device(const machine_config &mconfig, const char *
void nes_datach_device::device_start()
{
common_start();
- irq_timer = timer_alloc(TIMER_IRQ);
- serial_timer = timer_alloc(TIMER_SERIAL);
+ irq_timer = timer_alloc(FUNC(nes_datach_device::irq_timer_tick), this);
+ serial_timer = timer_alloc(FUNC(nes_datach_device::serial_tick), this);
irq_timer->adjust(attotime::zero, 0, clocks_to_attotime(1));
serial_timer->adjust(attotime::zero, 0, clocks_to_attotime(1000));
@@ -243,7 +242,6 @@ void nes_datach_device::device_start()
void nes_datach_device::pcb_reset()
{
- m_chr_source = m_vrom_chunks ? CHRROM : CHRRAM;
prg16_89ab(0);
prg16_cdef(m_prg_chunks - 1);
chr8(0, m_chr_source);
@@ -267,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
@@ -286,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)
@@ -303,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)
@@ -315,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)
{
@@ -378,32 +376,34 @@ void nes_datach_device::device_add_mconfig(machine_config &config)
//-------------------------------------------------
-// device_timer - handler timer events
+// irq_timer_tick - handle IRQ timer
//-------------------------------------------------
-void nes_datach_device::device_timer(emu_timer &timer, device_timer_id id, int param, void *ptr)
+TIMER_CALLBACK_MEMBER(nes_datach_device::irq_timer_tick)
{
- if (id == TIMER_IRQ)
+ if (m_irq_enable)
{
- if (m_irq_enable)
+ // 16bit counter, IRQ fired when the counter goes from 1 to 0
+ // after firing, the counter is *not* reloaded, but next clock
+ // counter wraps around from 0 to 0xffff
+ if (!m_irq_count)
+ m_irq_count = 0xffff;
+ else
+ m_irq_count--;
+
+ if (!m_irq_count)
{
- // 16bit counter, IRQ fired when the counter goes from 1 to 0
- // after firing, the counter is *not* reloaded, but next clock
- // counter wraps around from 0 to 0xffff
- if (!m_irq_count)
- m_irq_count = 0xffff;
- else
- m_irq_count--;
-
- if (!m_irq_count)
- {
- set_irq_line(ASSERT_LINE);
- m_irq_enable = 0;
- }
+ set_irq_line(ASSERT_LINE);
+ m_irq_enable = 0;
}
}
- if (id == TIMER_SERIAL)
- {
- m_datach_latch = (m_reader->read_pixel() << 3);
- }
+}
+
+//-------------------------------------------------
+// serial_tick - tick in a serial bit
+//-------------------------------------------------
+
+TIMER_CALLBACK_MEMBER(nes_datach_device::serial_tick)
+{
+ m_datach_latch = (m_reader->read_pixel() << 3);
}
diff --git a/src/devices/bus/nes/datach.h b/src/devices/bus/nes/datach.h
index 81865baa69f..8059d234564 100644
--- a/src/devices/bus/nes/datach.h
+++ b/src/devices/bus/nes/datach.h
@@ -6,7 +6,7 @@
#pragma once
#include "bandai.h"
-#include "softlist_dev.h"
+#include "imagedev/cartrom.h"
#include "machine/i2cmem.h"
#include "machine/bcreader.h"
@@ -18,7 +18,7 @@
// ======================> datach_cart_interface
-class datach_cart_interface : public device_slot_card_interface
+class datach_cart_interface : public device_interface
{
public:
// construction/destruction
@@ -46,8 +46,8 @@ protected:
class nes_datach_device;
class nes_datach_slot_device : public device_t,
- public device_image_interface,
- public device_slot_interface
+ public device_cartrom_image_interface,
+ public device_single_card_slot_interface<datach_cart_interface>
{
friend class nes_datach_device;
public:
@@ -64,30 +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();
- // device-level overrides
- virtual void device_start() override;
+ // device_image_interface implementation
+ virtual std::pair<std::error_condition, std::string> call_load() override;
- // image-level overrides
- virtual image_init_result call_load() override;
- virtual const software_list_loader &get_software_list_loader() const override { return rom_software_list_loader::instance(); }
+ 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"; }
- virtual iodevice_t image_type() const override { return IO_CARTSLOT; }
- virtual bool is_readable() const override { return 1; }
- virtual bool is_writeable() const override { return 0; }
- virtual bool is_creatable() const override { return 0; }
- virtual bool must_be_loaded() const override { return 0; }
- virtual bool is_reset_on_load() const override { return 1; }
- virtual const char *image_interface() const override { return "datach_cart"; }
- virtual const char *file_extensions() const 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:
- datach_cart_interface* m_cart;
+ // device_t implementation
+ virtual void device_start() override ATTR_COLD;
+
+ datach_cart_interface *m_cart;
};
// device type definition
@@ -108,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
- virtual void device_start() override;
- virtual void device_reset() override;
+ // device_t implementation
+ virtual void device_start() override ATTR_COLD;
+ virtual void device_reset() override ATTR_COLD;
+ virtual const tiny_rom_entry *device_rom_region() const override ATTR_COLD;
};
// ======================> nes_datach_24c01_device
@@ -129,8 +122,8 @@ public:
nes_datach_24c01_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;
+ // device_t implementation
+ virtual void device_add_mconfig(machine_config &config) override ATTR_COLD;
};
// device type definition
@@ -159,10 +152,12 @@ public:
virtual void pcb_reset() override;
protected:
- // device-level overrides
- virtual void device_start() override;
- virtual void device_timer(emu_timer &timer, device_timer_id id, int param, void *ptr) override;
- virtual void device_add_mconfig(machine_config &config) override;
+ // device_t implementation
+ virtual void device_start() override ATTR_COLD;
+ virtual void device_add_mconfig(machine_config &config) override ATTR_COLD;
+
+ TIMER_CALLBACK_MEMBER(irq_timer_tick);
+ TIMER_CALLBACK_MEMBER(serial_tick);
uint8_t m_datach_latch;
required_device<i2cmem_device> m_i2cmem;
@@ -171,7 +166,6 @@ protected:
uint8_t m_i2c_dir;
uint8_t m_i2c_in_use;
- static const device_timer_id TIMER_SERIAL = 1;
emu_timer *serial_timer;
};
diff --git a/src/devices/bus/nes/discrete.cpp b/src/devices/bus/nes/discrete.cpp
index 2fb7883d063..7705c4ba1bc 100644
--- a/src/devices/bus/nes/discrete.cpp
+++ b/src/devices/bus/nes/discrete.cpp
@@ -12,9 +12,6 @@
* PCB with IC 74x377 [mapper 11]
* PCB with IC 74x161x138 [mapper 38]
- TODO:
- - Investigating missing inputs in Crime Busters
-
***********************************************************************************************************/
@@ -23,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"
//-------------------------------------------------
@@ -41,22 +37,22 @@ DEFINE_DEVICE_TYPE(NES_74X377, nes_74x377_device, "nes_74x377",
DEFINE_DEVICE_TYPE(NES_74X161X138, nes_74x161x138_device, "nes_bitcorp_dis", "NES Cart Discrete Logic (74*161/138) PCB")
-nes_74x161x161x32_device::nes_74x161x161x32_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
+nes_74x161x161x32_device::nes_74x161x161x32_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock)
: nes_nrom_device(mconfig, NES_74X161X161X32, tag, owner, clock)
{
}
-nes_74x139x74_device::nes_74x139x74_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
+nes_74x139x74_device::nes_74x139x74_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock)
: nes_nrom_device(mconfig, NES_74X139X74, tag, owner, clock)
{
}
-nes_74x377_device::nes_74x377_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
+nes_74x377_device::nes_74x377_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock)
: nes_nrom_device(mconfig, NES_74X377, tag, owner, clock)
{
}
-nes_74x161x138_device::nes_74x161x138_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
+nes_74x161x138_device::nes_74x161x138_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock)
: nes_nrom_device(mconfig, NES_74X161X138, tag, owner, clock)
{
}
@@ -64,54 +60,13 @@ nes_74x161x138_device::nes_74x161x138_device(const machine_config &mconfig, cons
-void nes_74x161x161x32_device::device_start()
-{
- common_start();
-}
-
void nes_74x161x161x32_device::pcb_reset()
{
- m_chr_source = m_vrom_chunks ? CHRROM : CHRRAM;
prg16_89ab(0);
prg16_cdef(m_prg_chunks - 1);
chr8(0, m_chr_source);
-}
-
-void nes_74x139x74_device::device_start()
-{
- common_start();
-}
-
-void nes_74x139x74_device::pcb_reset()
-{
- m_chr_source = m_vrom_chunks ? CHRROM : CHRRAM;
- prg16_89ab(0);
- prg16_cdef(m_prg_chunks - 1);
- chr8(0, m_chr_source);
-}
-
-void nes_74x377_device::device_start()
-{
- common_start();
-}
-
-void nes_74x377_device::pcb_reset()
-{
- m_chr_source = m_vrom_chunks ? CHRROM : CHRRAM;
- prg32(0);
- chr8(0, m_chr_source);
-}
-
-void nes_74x161x138_device::device_start()
-{
- common_start();
-}
-
-void nes_74x161x138_device::pcb_reset()
-{
- m_chr_source = m_vrom_chunks ? CHRROM : CHRRAM;
- prg32(0);
- chr8(0, m_chr_source);
+ if (m_pcb_ctrl_mirror)
+ set_nt_mirroring(PPU_MIRROR_LOW);
}
@@ -134,9 +89,9 @@ void nes_74x161x138_device::pcb_reset()
-------------------------------------------------*/
// there are two 'variants' depending on hardwired or mapper ctrl mirroring
-void nes_74x161x161x32_device::write_h(offs_t offset, uint8_t data)
+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);
@@ -155,11 +110,11 @@ void nes_74x161x161x32_device::write_h(offs_t offset, uint8_t data)
-------------------------------------------------*/
-void nes_74x139x74_device::write_m(offs_t offset, uint8_t 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(((data & 0x02) >> 1) | ((data & 0x01) << 1), CHRROM);
+ chr8(bitswap<2>(data, 0, 1), CHRROM);
}
/*-------------------------------------------------
@@ -170,7 +125,7 @@ void nes_74x139x74_device::write_m(offs_t offset, uint8_t data)
iNES: mapper 11
- In MESS: Supported
+ In MAME: Supported
Note: bit2 & bit3 are actually related to CIC lockout
defeating, and real Color Dreams titles use only
@@ -179,9 +134,9 @@ void nes_74x139x74_device::write_m(offs_t offset, uint8_t data)
-------------------------------------------------*/
-void nes_74x377_device::write_h(offs_t offset, uint8_t 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);
@@ -200,9 +155,9 @@ void nes_74x377_device::write_h(offs_t offset, uint8_t data)
-------------------------------------------------*/
-void nes_74x161x138_device::write_m(offs_t offset, uint8_t 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/discrete.h b/src/devices/bus/nes/discrete.h
index 861b8b643bf..ec3ad88d824 100644
--- a/src/devices/bus/nes/discrete.h
+++ b/src/devices/bus/nes/discrete.h
@@ -14,15 +14,11 @@ class nes_74x161x161x32_device : public nes_nrom_device
{
public:
// construction/destruction
- nes_74x161x161x32_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
+ nes_74x161x161x32_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock);
- virtual void write_h(offs_t offset, uint8_t data) override;
+ virtual void write_h(offs_t offset, u8 data) override;
virtual void pcb_reset() override;
-
-protected:
- // device-level overrides
- virtual void device_start() override;
};
@@ -32,15 +28,9 @@ class nes_74x139x74_device : public nes_nrom_device
{
public:
// construction/destruction
- nes_74x139x74_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
-
- virtual void write_m(offs_t offset, uint8_t data) override;
+ nes_74x139x74_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock);
- virtual void pcb_reset() override;
-
-protected:
- // device-level overrides
- virtual void device_start() override;
+ virtual void write_m(offs_t offset, u8 data) override;
};
@@ -50,15 +40,9 @@ class nes_74x377_device : public nes_nrom_device
{
public:
// construction/destruction
- nes_74x377_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
-
- virtual void write_h(offs_t offset, uint8_t data) override;
+ nes_74x377_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock);
- virtual void pcb_reset() override;
-
-protected:
- // device-level overrides
- virtual void device_start() override;
+ virtual void write_h(offs_t offset, u8 data) override;
};
@@ -68,15 +52,9 @@ class nes_74x161x138_device : public nes_nrom_device
{
public:
// construction/destruction
- nes_74x161x138_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
-
- virtual void write_m(offs_t offset, uint8_t data) override;
-
- virtual void pcb_reset() override;
+ nes_74x161x138_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock);
-protected:
- // device-level overrides
- virtual void device_start() override;
+ virtual void write_m(offs_t offset, u8 data) override;
};
diff --git a/src/devices/bus/nes/disksys.cpp b/src/devices/bus/nes/disksys.cpp
index 71101492822..9512ef036e8 100644
--- a/src/devices/bus/nes/disksys.cpp
+++ b/src/devices/bus/nes/disksys.cpp
@@ -9,12 +9,10 @@
Here we emulate the RAM expansion + Disk Drive which form the
Famicom Disk System.
- Based on info from NESDev wiki ( http://wiki.nesdev.com/w/index.php/Family_Computer_Disk_System )
+ Based on info from NESDev wiki ( https://www.nesdev.org/wiki/Family_Computer_Disk_System )
TODO:
- convert floppy drive + fds format to modern code!
- - add sound bits
- - stop IRQ from using HOLD_LINE
***********************************************************************************************************/
@@ -23,14 +21,14 @@
#include "disksys.h"
#include "imagedev/flopdrv.h"
#include "formats/nes_dsk.h"
+#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"
//-----------------------------------------------
@@ -53,15 +51,20 @@ static const floppy_interface nes_floppy_interface =
void nes_disksys_device::device_add_mconfig(machine_config &config)
{
- LEGACY_FLOPPY(config, FLOPPY_0, 0, &nes_floppy_interface);
+ LEGACY_FLOPPY(config, m_disk, 0, &nes_floppy_interface);
+
+ SPEAKER(config, "addon").front_center(); // connected to motherboard
+
+ RP2C33_SOUND(config, m_sound, XTAL(21'477'272)/12); // clock driven from motherboard?
+ m_sound->add_route(0, "addon", 0.2);
}
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
@@ -101,9 +104,11 @@ nes_disksys_device::nes_disksys_device(const machine_config &mconfig, const char
: nes_nrom_device(mconfig, NES_DISKSYS, tag, owner, clock)
, m_2c33_rom(*this, "drive")
, m_fds_data(nullptr)
- , m_disk(*this, FLOPPY_0)
+ , m_disk(*this, "floppy0")
+ , m_sound(*this, "rp2c33snd")
, irq_timer(nullptr)
- , m_irq_count(0), m_irq_count_latch(0), m_irq_enable(0), m_irq_transfer(0), m_fds_motor_on(0), m_fds_door_closed(0), m_fds_current_side(0), m_fds_head_position(0), m_fds_status0(0), m_read_mode(0), m_drive_ready(0)
+ , m_irq_count(0), m_irq_count_latch(0), m_irq_enable(false), m_irq_repeat(false), m_irq_transfer(false), m_disk_reg_enable(false), m_sound_en(false)
+ , m_fds_motor_on(0), m_fds_door_closed(0), m_fds_current_side(0), m_fds_head_position(0), m_fds_status0(0), m_read_mode(0), m_drive_ready(0)
, m_fds_sides(0), m_fds_last_side(0), m_fds_count(0)
{
}
@@ -116,7 +121,7 @@ void nes_disksys_device::device_start()
m_disk->floppy_install_load_proc(nes_disksys_device::load_proc);
m_disk->floppy_install_unload_proc(nes_disksys_device::unload_proc);
- irq_timer = timer_alloc(TIMER_IRQ);
+ irq_timer = timer_alloc(FUNC(nes_disksys_device::irq_timer_tick), this);
irq_timer->adjust(attotime::zero, 0, clocks_to_attotime(1));
save_item(NAME(m_fds_motor_on));
@@ -127,9 +132,12 @@ void nes_disksys_device::device_start()
save_item(NAME(m_read_mode));
save_item(NAME(m_drive_ready));
save_item(NAME(m_irq_enable));
+ save_item(NAME(m_irq_repeat));
save_item(NAME(m_irq_transfer));
save_item(NAME(m_irq_count));
save_item(NAME(m_irq_count_latch));
+ save_item(NAME(m_disk_reg_enable));
+ save_item(NAME(m_sound_en));
save_item(NAME(m_fds_last_side));
save_item(NAME(m_fds_count));
@@ -151,8 +159,11 @@ void nes_disksys_device::pcb_reset()
m_drive_ready = 0;
m_irq_count = 0;
m_irq_count_latch = 0;
- m_irq_enable = 0;
- m_irq_transfer = 0;
+ m_irq_enable = false;
+ m_irq_repeat = false;
+ m_irq_transfer = false;
+ m_disk_reg_enable = false;
+ m_sound_en = false;
m_fds_count = 0;
m_fds_last_side = 0;
@@ -175,7 +186,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;
@@ -183,7 +194,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];
@@ -193,29 +204,35 @@ 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];
}
-void nes_disksys_device::hblank_irq(int scanline, int vblank, int blanked)
+void nes_disksys_device::hblank_irq(int scanline, bool vblank, bool blanked)
{
+ // FIXME: This looks like a gross hack that ties the disk byte transfer IRQ to the PPU. Seriously?
if (m_irq_transfer)
- hold_irq_line();
+ {
+ set_irq_line(ASSERT_LINE);
+ m_fds_status0 |= 0x02;
+ }
}
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)
{
// wavetable
+ if (m_sound_en)
+ m_sound->wave_w(offset - 0x20, data);
}
switch (offset)
@@ -227,18 +244,35 @@ void nes_disksys_device::write_ex(offs_t offset, uint8_t data)
m_irq_count_latch = (m_irq_count_latch & 0x00ff) | (data << 8);
break;
case 0x02:
- m_irq_count = m_irq_count_latch;
- m_irq_enable = BIT(data, 1);
+ if (m_disk_reg_enable)
+ {
+ m_irq_repeat = BIT(data, 0);
+ m_irq_enable = BIT(data, 1);
+ if (m_irq_enable)
+ m_irq_count = m_irq_count_latch;
+ else
+ set_irq_line(CLEAR_LINE);
+ }
break;
case 0x03:
// bit0 - Enable disk I/O registers
// bit1 - Enable sound I/O registers
+ m_disk_reg_enable = BIT(data, 0);
+ if (!m_disk_reg_enable)
+ {
+ m_irq_enable = 0;
+ set_irq_line(CLEAR_LINE);
+ }
+ m_sound_en = BIT(data, 1);
break;
case 0x04:
// write data out to disk
// TEST!
if (m_fds_data && m_fds_current_side && !m_read_mode)
m_fds_data[(m_fds_current_side - 1) * 65500 + m_fds_head_position++] = data;
+ // clear the byte transfer flag
+ m_fds_status0 &= ~0x02;
+ set_irq_line(CLEAR_LINE);
break;
case 0x05:
// $4025 - FDS Control
@@ -260,7 +294,11 @@ void nes_disksys_device::write_ex(offs_t offset, uint8_t data)
m_fds_head_position -= 2; // ??? is this some sort of compensation??
m_read_mode = BIT(data, 2);
- set_nt_mirroring(BIT(data, 3) ? PPU_MIRROR_HORZ : PPU_MIRROR_VERT);
+ if (BIT(data, 3))
+ m_fds_status0 |= 0x08;
+ else
+ m_fds_status0 &= ~0x08;
+ set_nt_mirroring(BIT(m_fds_status0, 3) ? PPU_MIRROR_HORZ : PPU_MIRROR_VERT);
m_drive_ready = data & 0x40;
m_irq_transfer = BIT(data, 7);
break;
@@ -277,18 +315,22 @@ void nes_disksys_device::write_ex(offs_t offset, uint8_t data)
case 0x68: // $4088 - Mod table write
case 0x69: // $4089 - Wave write / master volume
case 0x6a: // $408a - Envelope speed
+ if (m_sound_en)
+ m_sound->write(offset - 0x60, data);
break;
}
}
uint8_t nes_disksys_device::read_ex(offs_t offset)
{
- LOG_MMC(("Famicom Disk System read_ex, offset: %04x\n", offset));
- uint8_t ret;
+ LOG("Famicom Disk System read_ex, offset: %04x\n", offset);
+ uint8_t ret = 0x00;
if (offset >= 0x20 && offset < 0x60)
{
// wavetable
+ if (m_sound_en)
+ ret = m_sound->wave_r(offset - 0x20);
}
switch (offset)
@@ -299,12 +341,14 @@ uint8_t nes_disksys_device::read_ex(offs_t offset)
// bit1 - Byte transfer flag (Set to 1 every time 8 bits have been transferred between
// the RAM adaptor & disk drive through $4024/$4031; Reset to 0 when $4024,
// $4031, or $4030 has been serviced)
+ // bit3 = Nametable mirroring flag (0: Vertical, 1: Horizontal)
// bit4 - CRC control (0: CRC passed; 1: CRC error)
// bit6 - End of Head (1 when disk head is on the most inner track)
// bit7 - Disk Data Read/Write Enable (1 when disk is readable/writable)
ret = m_fds_status0 | 0x80;
- // clear the disk IRQ detect flag
- m_fds_status0 &= ~0x01;
+ // clear the disk IRQ detect and byte transfer flags
+ m_fds_status0 &= ~0x03;
+ set_irq_line(CLEAR_LINE);
break;
case 0x11:
// $4031 - data latch
@@ -323,6 +367,9 @@ uint8_t nes_disksys_device::read_ex(offs_t offset)
}
else
ret = 0;
+ // clear the byte transfer flag
+ m_fds_status0 &= ~0x02;
+ set_irq_line(CLEAR_LINE);
break;
case 0x12:
// $4032 - disk status 1:
@@ -351,6 +398,9 @@ uint8_t nes_disksys_device::read_ex(offs_t offset)
break;
case 0x70: // $4090 - Volume gain - write through $4080
case 0x72: // $4092 - Mod gain - read through $4084
+ if (m_sound_en)
+ ret = m_sound->read(offset - 0x60);
+ break;
default:
ret = 0x00;
break;
@@ -360,23 +410,22 @@ uint8_t nes_disksys_device::read_ex(offs_t offset)
}
//-------------------------------------------------
-// device_timer - handler timer events
+// irq_timer_tick - handle IRQ timer
//-------------------------------------------------
-void nes_disksys_device::device_timer(emu_timer &timer, device_timer_id id, int param, void *ptr)
+TIMER_CALLBACK_MEMBER(nes_disksys_device::irq_timer_tick)
{
- if (id == TIMER_IRQ)
+ if (m_irq_enable)
{
- if (m_irq_enable && m_irq_count)
- {
+ if (m_irq_count)
m_irq_count--;
- if (!m_irq_count)
- {
- hold_irq_line();
+ else
+ {
+ set_irq_line(ASSERT_LINE);
+ m_irq_count = m_irq_count_latch;
+ if (!m_irq_repeat)
m_irq_enable = 0;
- m_fds_status0 |= 0x01;
- m_irq_count_latch = 0; // used in Kaettekita Mario Bros
- }
+ m_fds_status0 |= 0x01;
}
}
}
@@ -393,7 +442,7 @@ void nes_disksys_device::disk_flip_side()
if (m_fds_current_side == 0)
popmessage("No disk inserted.");
else
- popmessage("Disk set to side %d", m_fds_current_side);
+ popmessage("Disk set to side %c", m_fds_current_side+0x40);
}
@@ -416,7 +465,6 @@ void nes_disksys_device::load_disk(device_image_interface &image)
// if there is an header, skip it
image.fseek(header, SEEK_SET);
image.fread(m_fds_data.get(), 65500 * m_fds_sides);
- return;
}
void nes_disksys_device::unload_disk(device_image_interface &image)
diff --git a/src/devices/bus/nes/disksys.h b/src/devices/bus/nes/disksys.h
index 1e3e45afb1e..e8e06f8f326 100644
--- a/src/devices/bus/nes/disksys.h
+++ b/src/devices/bus/nes/disksys.h
@@ -7,6 +7,7 @@
#include "nxrom.h"
#include "imagedev/flopdrv.h"
+#include "sound/rp2c33_snd.h"
// ======================> nes_disksys_device
@@ -26,16 +27,15 @@ public:
virtual void disk_flip_side() override;
- virtual void hblank_irq(int scanline, int vblank, int blanked) override;
+ virtual void hblank_irq(int scanline, bool vblank, bool blanked) override;
virtual void pcb_reset() override;
protected:
// device-level overrides
- virtual void device_start() override;
- virtual void device_timer(emu_timer &timer, device_timer_id id, int param, void *ptr) override;
+ virtual void device_start() override ATTR_COLD;
- virtual void device_add_mconfig(machine_config &config) override;
- virtual const tiny_rom_entry *device_rom_region() const override;
+ virtual void device_add_mconfig(machine_config &config) override ATTR_COLD;
+ virtual const tiny_rom_entry *device_rom_region() const override ATTR_COLD;
required_region_ptr<uint8_t> m_2c33_rom;
@@ -43,17 +43,21 @@ private:
static void load_proc(device_image_interface &image, bool is_created);
static void unload_proc(device_image_interface &image);
+ TIMER_CALLBACK_MEMBER(irq_timer_tick);
+
std::unique_ptr<uint8_t[]> m_fds_data; // here, we store a copy of the disk
required_device<legacy_floppy_image_device> m_disk;
+ required_device<rp2c33_sound_device> m_sound;
- static const device_timer_id TIMER_IRQ = 0;
emu_timer *irq_timer;
void load_disk(device_image_interface &image);
void unload_disk(device_image_interface &image);
uint16_t m_irq_count, m_irq_count_latch;
- int m_irq_enable, m_irq_transfer;
+ bool m_irq_enable, m_irq_repeat, m_irq_transfer;
+ bool m_disk_reg_enable;
+ bool m_sound_en;
uint8_t m_fds_motor_on;
uint8_t m_fds_door_closed;
@@ -64,8 +68,8 @@ private:
uint8_t m_drive_ready;
uint8_t m_fds_sides;
- int m_fds_last_side;
- int m_fds_count;
+ int32_t m_fds_last_side;
+ int32_t m_fds_count;
};
diff --git a/src/devices/bus/nes/event.cpp b/src/devices/bus/nes/event.cpp
index 41ebc976308..46be863f5ac 100644
--- a/src/devices/bus/nes/event.cpp
+++ b/src/devices/bus/nes/event.cpp
@@ -1,14 +1,15 @@
// license:BSD-3-Clause
-// copyright-holders:Fabio Priuli
+// copyright-holders:Fabio Priuli,kmg
/***********************************************************************************************************
- NES/Famicom cartridge emulation for Nintendo NES-EVENT PCB
+ NES/Famicom cartridge emulation for Nintendo NES-EVENT PCBs
Here we emulate the following PCBs
* Nintendo NES-EVENT [mapper 105]
+ * Nintendo NES-EVENT2 [mapper 555]
***********************************************************************************************************/
@@ -16,24 +17,25 @@
#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"
//-------------------------------------------------
// constructor
//-------------------------------------------------
-DEFINE_DEVICE_TYPE(NES_EVENT, nes_event_device, "nes_event", "NES Cart Event PCB")
+DEFINE_DEVICE_TYPE(NES_EVENT, nes_event_device, "nes_event", "NES Cart EVENT PCB")
+DEFINE_DEVICE_TYPE(NES_EVENT2, nes_event2_device, "nes_event2", "NES Cart EVENT2 PCB")
-nes_event_device::nes_event_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
+nes_event_device::nes_event_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock)
: nes_sxrom_device(mconfig, NES_EVENT, tag, owner, clock)
, m_dsw(*this, "DIPSW")
, m_nwc_init(0)
@@ -44,18 +46,24 @@ nes_event_device::nes_event_device(const machine_config &mconfig, const char *ta
{
}
+nes_event2_device::nes_event2_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock)
+ : nes_tqrom_device(mconfig, NES_EVENT2, tag, owner, clock)
+ , m_dsw(*this, "DIPSW")
+ , m_tqrom_mode(false)
+ , event_timer(nullptr)
+ , m_timer_count(0)
+ , m_timer_enabled(0)
+{
+}
+
void nes_event_device::device_start()
{
- common_start();
- event_timer = timer_alloc(TIMER_EVENT);
+ nes_sxrom_device::device_start();
+
+ event_timer = timer_alloc(FUNC(nes_event_device::event_tick), this);
event_timer->adjust(attotime::never);
- timer_freq = clocks_to_attotime(1);
- save_item(NAME(m_latch));
- save_item(NAME(m_count));
- save_item(NAME(m_reg));
- save_item(NAME(m_reg_write_enable));
save_item(NAME(m_nwc_init));
save_item(NAME(m_timer_count));
@@ -65,21 +73,38 @@ void nes_event_device::device_start()
void nes_event_device::pcb_reset()
{
- m_latch = 0;
- m_count = 0;
- m_reg[0] = 0x0f;
- m_reg[1] = m_reg[2] = m_reg[3] = 0;
- m_reg_write_enable = 1;
+ nes_sxrom_device::pcb_reset();
+ prg32(0);
+
m_nwc_init = 2;
- set_nt_mirroring(PPU_MIRROR_HORZ);
- chr8(0, CHRRAM);
- prg32(0);
m_timer_count = 0;
m_timer_enabled = 0;
m_timer_on = 0;
}
+void nes_event2_device::device_start()
+{
+ mmc3_start();
+
+ event_timer = timer_alloc(FUNC(nes_event2_device::event_tick), this);
+ event_timer->adjust(attotime::zero, 0, clocks_to_attotime(1));
+
+ save_item(NAME(m_tqrom_mode));
+
+ save_item(NAME(m_timer_count));
+ save_item(NAME(m_timer_enabled));
+}
+
+void nes_event2_device::pcb_reset()
+{
+ m_tqrom_mode = false;
+ mmc3_common_initialize(0x07, 0x7f, 0);
+
+ m_timer_count = 0;
+ m_timer_enabled = 0;
+}
+
/*-------------------------------------------------
@@ -88,16 +113,16 @@ void nes_event_device::pcb_reset()
/*-------------------------------------------------
- Event PCB
+ EVENT PCB
- Games: Nintento World Championships
+ Games: Nintento World Championships 1990
- MMC-1 variant with repurposed register at $a000 and a
+ MMC1 variant with repurposed register at $a000 and a
lot of discrete components
iNES: mapper 105
- In MESS: Supported.
+ In MAME: Supported.
-------------------------------------------------*/
@@ -109,88 +134,129 @@ void nes_event_device::set_chr()
void nes_event_device::set_prg()
{
// printf("enter with %d and reg1 0x%x - reg3 0x%x\n", m_nwc_init, m_reg[1], m_reg[3]);
- // reg[1] is different from base MMC-1!
+ // reg[1] is different from base MMC1!
// bit 0 is ignored, bit1/bit3 are used for PRG switch, bit4 is used for the timer
- uint8_t temp = (m_reg[1] >> 1) & 7;
-
// initially PRG is fixed, until bit4 of reg1 is set to 1 and then to 0
switch (m_nwc_init)
{
case 2:
- if (m_reg[1] & 0x10) m_nwc_init--;
+ if (BIT(m_reg[1], 4)) m_nwc_init--;
return;
case 1:
- if (~m_reg[1] & 0x10) m_nwc_init--;
+ if (!BIT(m_reg[1], 4)) m_nwc_init--;
return;
}
- if (temp < 4)
- prg32(temp);
+ // PRG mode 1 works similarly to base MMC1, but only acts on the higher 128KB (2nd PRG ROM)
+ if (BIT(m_reg[1], 3))
+ nes_sxrom_device::set_prg(0x08, 0x07);
else
- {
- // else PRG works similarly to base MMC-1, but only acts on the higher 128KB (2nd PRG ROM)
- switch (m_reg[0] & 0x0c)
- {
- case 0x00:
- case 0x04:
- prg32(0x04 | ((m_reg[3] >> 1) & 0x03));
- break;
- case 0x08:
- prg16_89ab(0x08 | 0x00);
- prg16_cdef(0x08 | (m_reg[3] & 0x07));
- break;
- case 0x0c:
- prg16_89ab(0x08 | (m_reg[3] & 0x07));
- prg16_cdef(0x08 | 0x07);
- break;
- }
- }
+ prg32(BIT(m_reg[1], 1, 2));
// after the init procedure above, bit4 of m_reg[1] is used to init IRQ, by setting and then clearing the bit
// however, there are (bankswitch related?) writes with bit4 cleared before the one 'enabling' the timer, so
// we need the additional m_timer_enabled variable, to avoid starting the timer before its time...
- if (m_reg[1] & 0x10)
+ if (BIT(m_reg[1], 4))
{
+ m_timer_count = 0;
m_timer_enabled = 1;
set_irq_line(CLEAR_LINE);
}
- else
+ else if (!m_timer_on && m_timer_enabled)
{
- if (!m_timer_on && m_timer_enabled)
- {
- m_timer_count = 0x20000000 | ((m_dsw->read() & 0x0f) << 25);
- event_timer->adjust(attotime::zero, 0, timer_freq);
- m_timer_on = 1;
- }
+ event_timer->adjust(attotime::zero, 0, clocks_to_attotime(1));
+ m_timer_on = 1;
}
}
-void nes_event_device::update_regs(int reg)
+/*-------------------------------------------------
+
+ EVENT2 PCB
+
+ Games: Nintento Campus Challenge 1991
+
+ Similar to the previous EVENT PCB, but based around
+ the MMC3. Onboard 8K VRAM and 8K WRAM support Pinbot
+ and SMB3, respectively, and an additional 2K WRAM at
+ $5000 is used by the control routine. The board also
+ featured an RJ11, used to transmit player names and
+ scores to a display at the staged events.
+
+ The present emulation is based on what is known via
+ the reproduction board by RetroZone. That board is
+ missing the RJ11, two DIP switches, and...?
+
+ NES 2.0: mapper 555
+
+ In MAME: Supported.
+
+ -------------------------------------------------*/
+
+u8 nes_event2_device::read_l(offs_t 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;
+ else if (offset < 0x1000 || m_prgram.empty())
+ return get_open_bus();
+ else
+ return m_prgram[(0x2000 + (offset & 0x7ff)) % m_prgram.size()];
+}
+
+u8 nes_event2_device::read_m(offs_t offset)
{
- switch (reg)
+ LOGMASKED(LOG_HIFREQ, "event2 read_m, offset: %04x\n", offset);
+ if (m_prgram.empty())
+ return get_open_bus();
+ else
+ return m_prgram[offset % m_prgram.size()];
+}
+
+void nes_event2_device::write_l(offs_t offset, u8 data)
+{
+ LOG("event2 write_l, offset: %04x, data: %02x\n", offset, data);
+
+ offset += 0x100;
+ switch (offset & 0x1c00)
{
- case 0:
- switch (m_reg[0] & 0x03)
- {
- case 0: set_nt_mirroring(PPU_MIRROR_LOW); break;
- case 1: set_nt_mirroring(PPU_MIRROR_HIGH); break;
- case 2: set_nt_mirroring(PPU_MIRROR_VERT); break;
- case 3: set_nt_mirroring(PPU_MIRROR_HORZ); break;
- }
- set_prg();
- break;
- case 1:
- set_prg();
- break;
- case 2:
- set_chr();
+ case 0x1000:
+ case 0x1400:
+ m_prgram[(0x2000 + (offset & 0x7ff)) % m_prgram.size()] = data;
break;
- case 3:
- set_prg();
+ case 0x1800:
+ m_tqrom_mode = (data & 0x06) == 0x02;
+
+ m_prg_base = (data & 0x04) << 3;
+ m_prg_mask = (data & 0x03) << 3 | 0x07;
+ set_prg(m_prg_base, m_prg_mask);
+
+ m_chr_base = m_prg_base << 2;
+ set_chr(m_chr_source, m_chr_base, m_chr_mask);
+
+ m_timer_enabled = BIT(data, 3);
+ if (!m_timer_enabled)
+ m_timer_count = 0;
break;
}
}
+void nes_event2_device::write_m(offs_t offset, u8 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;
+}
+
+void nes_event2_device::chr_cb(int start, int bank, int source)
+{
+ if (m_tqrom_mode)
+ nes_tqrom_device::chr_cb(start, bank, source);
+ else
+ nes_txrom_device::chr_cb(start, bank, source);
+}
+
+
//-------------------------------------------------
// Dipswitch
//-------------------------------------------------
@@ -223,20 +289,30 @@ ioport_constructor nes_event_device::device_input_ports() const
return INPUT_PORTS_NAME( nwc_dsw );
}
+ioport_constructor nes_event2_device::device_input_ports() const
+{
+ return INPUT_PORTS_NAME( nwc_dsw );
+}
+
//-------------------------------------------------
-// device_timer - handler timer events
+// event_tick - tick the event timer
//-------------------------------------------------
-void nes_event_device::device_timer(emu_timer &timer, device_timer_id id, int param, void *ptr)
+TIMER_CALLBACK_MEMBER(nes_event_device::event_tick)
{
- if (id == TIMER_EVENT)
+ if (m_timer_on)
{
- m_timer_count--;
- if (!m_timer_count)
+ if (++m_timer_count >= (0x10 | m_dsw->read()) << 25)
{
- hold_irq_line();
+ set_irq_line(ASSERT_LINE);
event_timer->reset();
}
}
}
+
+TIMER_CALLBACK_MEMBER(nes_event2_device::event_tick)
+{
+ if (m_timer_enabled)
+ m_timer_count++;
+}
diff --git a/src/devices/bus/nes/event.h b/src/devices/bus/nes/event.h
index b4b67614b50..8a0de36a199 100644
--- a/src/devices/bus/nes/event.h
+++ b/src/devices/bus/nes/event.h
@@ -1,11 +1,12 @@
// license:BSD-3-Clause
-// copyright-holders:Fabio Priuli
-#ifndef MAEM_BUS_NES_EVENT_H
-#define MAEM_BUS_NES_EVENT_H
+// copyright-holders:Fabio Priuli,kmg
+#ifndef MAME_BUS_NES_EVENT_H
+#define MAME_BUS_NES_EVENT_H
#pragma once
#include "mmc1.h"
+#include "mmc3.h"
// ======================> nes_event_device
@@ -14,36 +15,66 @@ class nes_event_device : public nes_sxrom_device
{
public:
// construction/destruction
- nes_event_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
-
- virtual ioport_constructor device_input_ports() const override;
+ nes_event_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock);
virtual void pcb_reset() override;
protected:
- static constexpr device_timer_id TIMER_EVENT = 0;
-
// device-level overrides
- virtual void device_start() override;
- virtual void device_timer(emu_timer &timer, device_timer_id id, int param, void *ptr) override;
+ virtual void device_start() override ATTR_COLD;
+ virtual ioport_constructor device_input_ports() const override ATTR_COLD;
- virtual void update_regs(int reg) override;
virtual void set_prg() override;
virtual void set_chr() override;
+ TIMER_CALLBACK_MEMBER(event_tick);
+
required_ioport m_dsw;
int m_nwc_init;
emu_timer *event_timer;
- attotime timer_freq;
- uint32_t m_timer_count;
+ u32 m_timer_count;
int m_timer_on, m_timer_enabled;
};
+// ======================> nes_event2_device
+
+class nes_event2_device : public nes_tqrom_device
+{
+public:
+ // construction/destruction
+ nes_event2_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock);
+
+ virtual u8 read_l(offs_t offset) override;
+ virtual void write_l(offs_t offset, u8 data) override;
+ virtual u8 read_m(offs_t offset) override;
+ virtual void write_m(offs_t offset, u8 data) override;
+ virtual void chr_cb(int start, int bank, int source) override;
+
+ virtual void pcb_reset() override;
+
+protected:
+ // device-level overrides
+ virtual void device_start() override ATTR_COLD;
+ virtual ioport_constructor device_input_ports() const override ATTR_COLD;
+
+ TIMER_CALLBACK_MEMBER(event_tick);
+
+ required_ioport m_dsw;
+
+ bool m_tqrom_mode;
+
+ emu_timer *event_timer;
+
+ u32 m_timer_count;
+ int m_timer_enabled;
+};
+
// device type definition
-DECLARE_DEVICE_TYPE(NES_EVENT, nes_event_device)
+DECLARE_DEVICE_TYPE(NES_EVENT, nes_event_device)
+DECLARE_DEVICE_TYPE(NES_EVENT2, nes_event2_device)
-#endif // MAEM_BUS_NES_EVENT_H
+#endif // MAME_BUS_NES_EVENT_H
diff --git a/src/devices/bus/nes/ggenie.cpp b/src/devices/bus/nes/ggenie.cpp
index bb5866feac7..58cb2655e89 100644
--- a/src/devices/bus/nes/ggenie.cpp
+++ b/src/devices/bus/nes/ggenie.cpp
@@ -10,6 +10,8 @@
* Galoob Game Genie, passthrough hacking cart
+ TODO: emulate bugs/quirks/bus conflicts. See NesDev wiki.
+
***********************************************************************************************************/
@@ -17,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"
//-------------------------------------------------
@@ -33,10 +37,10 @@
DEFINE_DEVICE_TYPE(NES_GGENIE, nes_ggenie_device, "nes_ggenie", "NES Cart Game Genie PCB")
-nes_ggenie_device::nes_ggenie_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
+nes_ggenie_device::nes_ggenie_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock)
: nes_nrom_device(mconfig, NES_GGENIE, tag, owner, clock)
, m_ggslot(*this, "gg_slot")
- , m_gg_bypass(0)
+ , m_gg_bypass(false)
{
}
@@ -45,26 +49,35 @@ void nes_ggenie_device::device_start()
{
common_start();
save_item(NAME(m_gg_bypass));
+ save_item(NAME(m_gg_addr));
+ save_item(NAME(m_gg_repl));
+ save_item(NAME(m_gg_comp));
+ save_item(NAME(m_gg_enable));
+ save_item(NAME(m_gg_is_comp));
}
-void nes_ggenie_device::pcb_start(running_machine &machine, uint8_t *ciram_ptr, bool cart_mounted)
+void nes_ggenie_device::pcb_start(running_machine &machine, u8 *ciram_ptr, bool cart_mounted)
{
device_nes_cart_interface::pcb_start(machine, ciram_ptr, cart_mounted);
- if (m_ggslot->m_cart)
- m_ggslot->pcb_start(m_ciram);
-}
+ m_ggslot->pcb_start(m_ciram);
-void nes_ggenie_device::pcb_reset()
-{
- m_chr_source = m_vrom_chunks ? CHRROM : CHRRAM;
prg32(0);
- chr8(0, m_chr_source);
+ m_gg_bypass = false;
- set_nt_mirroring(PPU_MIRROR_LOW);
- m_gg_bypass = 0;
+ for (int i = 0; i < 3; i++)
+ {
+ m_gg_addr[i] = 0;
+ m_gg_repl[i] = 0;
+ m_gg_comp[i] = 0;
+ m_gg_enable[i] = false;
+ m_gg_is_comp[i] = false;
+ }
+}
- if (m_ggslot->m_cart)
- m_ggslot->m_cart->pcb_reset();
+void nes_ggenie_device::pcb_reset()
+{
+ // Game Genie does NOT reset to its interface once in game mode
+ m_ggslot->pcb_reset();
}
@@ -80,177 +93,154 @@ void nes_ggenie_device::pcb_reset()
-------------------------------------------------*/
-void nes_ggenie_device::write_h(offs_t offset, uint8_t data)
+void nes_ggenie_device::write_h(offs_t offset, u8 data)
{
-// LOG_MMC(("axrom write_h, offset: %04x, data: %02x\n", offset, data));
- if (!m_gg_bypass)
+ LOGMASKED(LOG_HIFREQ, "ggenie write_h, offset: %04x, data: %02x\n", offset, data);
+
+ if (m_gg_bypass)
{
- // From blargg: Codes are written to $8001-800C, starting at $800C and going down to $8001.
- // Next, two values are written to $8000. The first specify the kind of codes which have
- // been inserted, the second write to $8000 is always zero (all 8 bits).
- // This probably disables the boot ROM (the code is executing from RAM at this point).
- // Once done, the code jumps to ($FFFC) to begin the game.
- // All 12 bytes from $8001-800C are written regardless of how many codes are inserted.
- // The value written to $8000 is the only clue as to what codes are actually valid and which
- // ones have compare values.
- if (offset)
- {
- int code;
- offset -= 1;
- code = (offset & 0xc) >> 2;
- if (code == 3)
- return; // how did we end up here? the GG is not expected to write to $800d-800f!
+ m_ggslot->write_h(offset, data);
+ return;
+ }
- switch (offset & 3)
- {
- case 0:
- m_gg_addr[code] |= (data & 0x7f) << 8;
- break;
- case 1:
- m_gg_addr[code] = data;
- break;
- case 2:
- m_gg_comp[code] = data;
- break;
- case 3:
- m_gg_repl[code] = data;
- break;
- }
- return;
- }
+ // From blargg: Codes are written to $8001-800C, starting at $800C and going down to $8001.
+ // Next, two values are written to $8000. The first specify the kind of codes which have
+ // been inserted, and disables the boot ROM. The second write to $8000 is always 0x00, and
+ // goes to the slave cart for unknown reasons.
+ // Once done, the code jumps to ($FFFC) to begin the game.
+ // All 12 bytes from $8001-800C are written regardless of how many codes are inserted.
+ // The value written to $8000 is the only clue as to what codes are actually valid and which
+ // ones have compare values.
+ if (offset)
+ {
+ offset -= 1;
+ int code = BIT(offset, 2, 2);
+ if (code == 3)
+ return; // how did we end up here? the GG is not expected to write to $800d-800f!
- if (offset == 0 && data == 0)
+ switch (offset & 3)
{
- m_gg_bypass = 1;
- reset_cpu();
+ case 0:
+ m_gg_addr[code] |= (data & 0x7f) << 8;
+ break;
+ case 1:
+ m_gg_addr[code] = data;
+ break;
+ case 2:
+ m_gg_comp[code] = data;
+ break;
+ case 3:
+ m_gg_repl[code] = data;
+ break;
}
- else
+ }
+ else // 0x8000
+ {
+ m_gg_bypass = BIT(data, 0);
+ for (int i = 0; i < 3; i++)
+ {
+ m_gg_is_comp[i] = BIT(data, i + 1);
+ m_gg_enable[i] = !BIT(data, i + 4);
+ }
+ // bit 7 is unused and always zero
+
+ LOGMASKED(LOG_INFO, "Game Genie Summary:\n");
+ for (int i = 0; i < 3; i++)
{
- // bit 0 is always set (GG enable?)
- m_gg_is_comp[0] = BIT(data, 1);
- m_gg_is_comp[1] = BIT(data, 2);
- m_gg_is_comp[2] = BIT(data, 3);
- m_gg_disable[0] = BIT(data, 4);
- m_gg_disable[1] = BIT(data, 5);
- m_gg_disable[2] = BIT(data, 6);
- // bit 7 is always clear
- logerror("Game Genie Summary:\n");
- for (int i = 0; i < 3; i++)
+ LOGMASKED(LOG_INFO, "Code %d: %s\n", i, m_gg_enable[i] ? "Yes" : "No");
+ if (m_gg_enable[i])
{
- logerror("Code %d: %s\n", i, m_gg_disable[i] ? "No" : "Yes");
- if (!m_gg_disable[i])
- {
- logerror("\tAddr: 0x%X\n", m_gg_addr[i]);
- logerror("\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, "\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])
+ LOGMASKED(LOG_INFO, "\t if equals: 0x%X\n", m_gg_comp[i]);
}
}
}
- else
- m_ggslot->write_h(offset, data);
}
-void nes_ggenie_device::write_m(offs_t offset, uint8_t data)
+void nes_ggenie_device::write_m(offs_t offset, u8 data)
{
- if (m_gg_bypass && m_ggslot)
+ if (m_gg_bypass)
m_ggslot->write_m(offset, data);
}
-void nes_ggenie_device::write_l(offs_t offset, uint8_t data)
+void nes_ggenie_device::write_l(offs_t offset, u8 data)
{
- if (m_gg_bypass && m_ggslot)
+ if (m_gg_bypass)
m_ggslot->write_l(offset, data);
}
-uint8_t nes_ggenie_device::read_h(offs_t offset)
+u8 nes_ggenie_device::read_h(offs_t offset)
{
if (m_gg_bypass && m_ggslot->m_cart)
{
- uint8_t rom_value = m_ggslot->m_cart->hi_access_rom(offset);
+ u8 rom_value = m_ggslot->m_cart->hi_access_rom(offset);
// check if GG code has to act on this address
for (int i = 0; i < 3; i++)
{
- if (!m_gg_disable[i] && offset == m_gg_addr[i])
+ if (m_gg_enable[i] && offset == m_gg_addr[i])
{
- if (!m_gg_is_comp[i] || (m_gg_is_comp[i] && m_gg_comp[i] == rom_value))
+ if (!m_gg_is_comp[i] || m_gg_comp[i] == rom_value)
return m_gg_repl[i];
}
}
- return rom_value;
+ return rom_value;
}
- return hi_access_rom(offset);
+ return m_prg[offset & 0xfff]; // ROM is only 4K
}
-uint8_t nes_ggenie_device::read_m(offs_t offset)
+u8 nes_ggenie_device::read_m(offs_t offset)
{
- if (m_gg_bypass && m_ggslot->m_cart)
- return m_ggslot->m_cart->read_m(offset);
+ if (m_gg_bypass)
+ return m_ggslot->read_m(offset);
return 0xff;
}
-uint8_t nes_ggenie_device::read_l(offs_t offset)
+u8 nes_ggenie_device::read_l(offs_t offset)
{
- if (m_gg_bypass && m_ggslot->m_cart)
- return m_ggslot->m_cart->read_l(offset);
+ if (m_gg_bypass)
+ return m_ggslot->read_l(offset);
return 0xff;
}
-void nes_ggenie_device::chr_w(offs_t offset, uint8_t data)
+void nes_ggenie_device::chr_w(offs_t offset, u8 data)
{
- int bank = offset >> 10;
-
if (m_gg_bypass && m_ggslot->m_cart)
- {
m_ggslot->m_cart->chr_w(offset, data);
- return;
- }
-
- if (m_chr_src[bank] == CHRRAM)
- m_chr_access[bank][offset & 0x3ff] = data;
}
-uint8_t nes_ggenie_device::chr_r(offs_t offset)
+u8 nes_ggenie_device::chr_r(offs_t offset)
{
- int bank = offset >> 10;
-
if (m_gg_bypass && m_ggslot->m_cart)
- return m_ggslot->m_cart->chr_r(offset);
-
- return m_chr_access[bank][offset & 0x3ff];
+ return m_ggslot->m_cart->chr_r(offset);
+ else
+ {
+ // there is no on-board CHRROM, 1 of 4 values are generated based on PPU A2, A4, A5, A6, A7, resulting in 16 tiles
+ static constexpr u8 chr_lut[4] = { 0x00, 0xf0, 0x0f, 0xff };
+ return chr_lut[BIT(offset, BIT(offset, 2) ? 4 : 6, 2)];
+ }
}
-void nes_ggenie_device::nt_w(offs_t offset, uint8_t data)
+void nes_ggenie_device::nt_w(offs_t offset, u8 data)
{
- int page = ((offset & 0xc00) >> 10);
-
if (m_gg_bypass && m_ggslot->m_cart)
- {
m_ggslot->m_cart->nt_w(offset, data);
- return;
- }
-
- if (!m_nt_writable[page])
- return;
-
- m_nt_access[page][offset & 0x3ff] = data;
+ else
+ device_nes_cart_interface::nt_w(offset, data);
}
-uint8_t nes_ggenie_device::nt_r(offs_t offset)
+u8 nes_ggenie_device::nt_r(offs_t offset)
{
- int page = ((offset & 0xc00) >> 10);
-
if (m_gg_bypass && m_ggslot->m_cart)
return m_ggslot->m_cart->nt_r(offset);
-
- return m_nt_access[page][offset & 0x3ff];
+ else
+ return device_nes_cart_interface::nt_r(offset);
}
diff --git a/src/devices/bus/nes/ggenie.h b/src/devices/bus/nes/ggenie.h
index 2d6974be849..baca7c4dc15 100644
--- a/src/devices/bus/nes/ggenie.h
+++ b/src/devices/bus/nes/ggenie.h
@@ -14,44 +14,44 @@ class nes_ggenie_device : public nes_nrom_device
{
public:
// construction/destruction
- nes_ggenie_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
-
- virtual uint8_t read_l(offs_t offset) override;
- virtual uint8_t read_m(offs_t offset) override;
- virtual uint8_t read_h(offs_t offset) override;
- virtual void write_l(offs_t offset, uint8_t data) override;
- virtual void write_m(offs_t offset, uint8_t data) override;
- virtual void write_h(offs_t offset, uint8_t data) override;
-
- virtual uint8_t chr_r(offs_t offset) override;
- virtual void chr_w(offs_t offset, uint8_t data) override;
- virtual uint8_t nt_r(offs_t offset) override;
- virtual void nt_w(offs_t offset, uint8_t data) override;
-
- void hblank_irq(int scanline, int vblank, int blanked) override { if (m_gg_bypass && m_ggslot->m_cart) m_ggslot->m_cart->hblank_irq(scanline, vblank, blanked); }
- void scanline_irq(int scanline, int vblank, int blanked) override { if (m_gg_bypass && m_ggslot->m_cart) m_ggslot->m_cart->scanline_irq(scanline, vblank, blanked); }
+ nes_ggenie_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock);
+
+ virtual u8 read_l(offs_t offset) override;
+ virtual u8 read_m(offs_t offset) override;
+ virtual u8 read_h(offs_t offset) override;
+ virtual void write_l(offs_t offset, u8 data) override;
+ virtual void write_m(offs_t offset, u8 data) override;
+ virtual void write_h(offs_t offset, u8 data) override;
+
+ virtual u8 chr_r(offs_t offset) override;
+ virtual void chr_w(offs_t offset, u8 data) override;
+ virtual u8 nt_r(offs_t offset) override;
+ virtual void nt_w(offs_t offset, u8 data) override;
+
+ void hblank_irq(int scanline, bool vblank, bool blanked) override { if (m_gg_bypass && m_ggslot->m_cart) m_ggslot->m_cart->hblank_irq(scanline, vblank, blanked); }
+ void scanline_irq(int scanline, bool vblank, bool blanked) override { if (m_gg_bypass && m_ggslot->m_cart) m_ggslot->m_cart->scanline_irq(scanline, vblank, blanked); }
void ppu_latch(offs_t offset) override { if (m_gg_bypass && m_ggslot->m_cart) m_ggslot->m_cart->ppu_latch(offset); }
virtual void pcb_reset() override;
- virtual void pcb_start(running_machine &machine, uint8_t *ciram_ptr, bool cart_mounted) override;
+ virtual void pcb_start(running_machine &machine, u8 *ciram_ptr, bool cart_mounted) override;
protected:
// device-level overrides
- virtual void device_start() override;
+ virtual void device_start() override ATTR_COLD;
- virtual void device_add_mconfig(machine_config &config) override;
+ virtual void device_add_mconfig(machine_config &config) override ATTR_COLD;
private:
- // emulate the Game Genie!
+ // passthrough cart slot
required_device<nes_cart_slot_device> m_ggslot;
- int m_gg_bypass;
+ bool m_gg_bypass;
// GG codes
- uint16_t m_gg_addr[3];
- uint8_t m_gg_repl[3];
- uint8_t m_gg_comp[3];
- int m_gg_disable[3];
- int m_gg_is_comp[3];
+ u16 m_gg_addr[3];
+ u8 m_gg_repl[3];
+ u8 m_gg_comp[3];
+ bool m_gg_enable[3];
+ bool m_gg_is_comp[3];
};
diff --git a/src/devices/bus/nes/henggedianzi.cpp b/src/devices/bus/nes/henggedianzi.cpp
index 0f9acd05d45..46af837c524 100644
--- a/src/devices/bus/nes/henggedianzi.cpp
+++ b/src/devices/bus/nes/henggedianzi.cpp
@@ -10,7 +10,6 @@
* Henggedianzi Super Rich [mapper 177]
* Henggedianzi Xing He Zhan Shi [mapper 179]
- * Henggedianzi Shen Hua Jian Yun III
TODO:
@@ -24,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"
//-------------------------------------------------
@@ -38,7 +36,6 @@
DEFINE_DEVICE_TYPE(NES_HENGG_SRICH, nes_hengg_srich_device, "nes_hengg_srich", "NES Cart Henggedianzi Super Rich PCB")
DEFINE_DEVICE_TYPE(NES_HENGG_XHZS, nes_hengg_xhzs_device, "nes_hengg_xhzs", "NES Cart Henggedianzi Xing He Zhan Shi PCB")
-DEFINE_DEVICE_TYPE(NES_HENGG_SHJY3, nes_hengg_shjy3_device, "nes_hengg_shjy3", "NES Cart Henggedianzi Shen Hua Jian Yun III PCB")
nes_hengg_srich_device::nes_hengg_srich_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
@@ -51,67 +48,6 @@ nes_hengg_xhzs_device::nes_hengg_xhzs_device(const machine_config &mconfig, cons
{
}
-nes_hengg_shjy3_device::nes_hengg_shjy3_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
- : nes_nrom_device(mconfig, NES_HENGG_SHJY3, tag, owner, clock), m_irq_count(0), m_irq_count_latch(0), m_irq_enable(0), m_chr_mode(0)
-{
-}
-
-
-
-
-void nes_hengg_srich_device::device_start()
-{
- common_start();
-}
-
-void nes_hengg_srich_device::pcb_reset()
-{
- m_chr_source = m_vrom_chunks ? CHRROM : CHRRAM;
- prg32(0);
- chr8(0, m_chr_source);
-}
-
-void nes_hengg_xhzs_device::device_start()
-{
- common_start();
-}
-
-void nes_hengg_xhzs_device::pcb_reset()
-{
- m_chr_source = m_vrom_chunks ? CHRROM : CHRRAM;
- prg32(0);
- chr8(0, m_chr_source);
-}
-
-void nes_hengg_shjy3_device::device_start()
-{
- common_start();
- save_item(NAME(m_irq_count));
- save_item(NAME(m_irq_count_latch));
- save_item(NAME(m_irq_enable));
- save_item(NAME(m_chr_mode));
- save_item(NAME(m_mmc_prg_bank));
- save_item(NAME(m_mmc_vrom_bank));
- save_item(NAME(m_mmc_extra_bank));
-}
-
-void nes_hengg_shjy3_device::pcb_reset()
-{
- m_chr_source = m_vrom_chunks ? CHRROM : CHRRAM;
- prg16_89ab(0);
- prg16_cdef(m_prg_chunks - 1);
- chr8(0, m_chr_source);
-
- m_irq_enable = 0;
- m_irq_count = m_irq_count_latch = 0;
-
- m_chr_mode = 0;
- memset(m_mmc_prg_bank, 0, sizeof(m_mmc_prg_bank));
- memset(m_mmc_vrom_bank, 0, sizeof(m_mmc_vrom_bank));
- memset(m_mmc_extra_bank, 0, sizeof(m_mmc_extra_bank));
-}
-
-
@@ -131,13 +67,13 @@ void nes_hengg_shjy3_device::pcb_reset()
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);
@@ -158,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)
@@ -173,104 +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);
}
-
-/*-------------------------------------------------
-
- UNL-SHJY3
-
- -------------------------------------------------*/
-
-/* I think the IRQ should only get fired if enough CPU cycles have passed, but we don't implement (yet) this part */
-void nes_hengg_shjy3_device::hblank_irq(int scanline, int vblank, int blanked)
-{
- if (m_irq_enable & 0x02)
- {
- if (m_irq_count == 0xff)
- {
- m_irq_count = m_irq_count_latch;
- m_irq_enable = m_irq_enable | ((m_irq_enable & 0x01) << 1);
- hold_irq_line();
- }
- else
- m_irq_count++;
- }
-}
-
-void nes_hengg_shjy3_device::update_banks()
-{
- prg8_89(m_mmc_prg_bank[0]);
- prg8_ab(m_mmc_prg_bank[1]);
-
- for (int i = 0; i < 8; i++)
- {
- uint8_t chr_bank = m_mmc_vrom_bank[i] | (m_mmc_extra_bank[i] << 4);
- if (m_mmc_vrom_bank[i] == 0xc8)
- {
- m_chr_mode = 0;
- continue;
- }
- else if (m_mmc_vrom_bank[i] == 0x88)
- {
- m_chr_mode = 1;
- continue;
- }
- if ((m_mmc_vrom_bank[i] == 4 || m_mmc_vrom_bank[i] == 5) && !m_chr_mode)
- chr1_x(i, chr_bank & 1, CHRRAM);
- else
- chr1_x(i, chr_bank, CHRROM);
- }
-}
-
-void nes_hengg_shjy3_device::write_h(offs_t offset, uint8_t data)
-{
- LOG_MMC(("shjy3 write_h, offset: %04x, data: %02x\n", offset, data));
-
- if (offset >= 0x3000 && offset <= 0x600c)
- {
- uint8_t shift = offset & 4;
- uint8_t mmc_helper = ((offset & 8) | (offset >> 8)) >> 3;
- mmc_helper += 2;
- mmc_helper &= 7;
-
- m_mmc_vrom_bank[mmc_helper] = (m_mmc_vrom_bank[mmc_helper] & (0xf0 >> shift)) | ((data & 0x0f) << shift);
- if (shift)
- m_mmc_extra_bank[mmc_helper] = data >> 4;
- }
- else
- {
- switch (offset)
- {
- case 0x0010:
- m_mmc_prg_bank[0] = data;
- break;
- case 0x2010:
- m_mmc_prg_bank[1] = data;
- break;
- case 0x1400:
- switch (data & 0x03)
- {
- case 0: set_nt_mirroring(PPU_MIRROR_VERT); break;
- case 1: set_nt_mirroring(PPU_MIRROR_HORZ); break;
- case 2: set_nt_mirroring(PPU_MIRROR_LOW); break;
- case 3: set_nt_mirroring(PPU_MIRROR_HIGH); break;
- }
- break;
- case 0x7000:
- m_irq_count_latch = (m_irq_count_latch & 0xf0) | (data & 0x0f);
- break;
- case 0x7004:
- m_irq_count_latch = (m_irq_count_latch & 0x0f) | ((data & 0x0f) << 4);
- break;
- case 0x7008:
- m_irq_enable = data & 0x03;
- if (m_irq_enable & 0x02)
- m_irq_count = m_irq_count_latch;
- break;
- }
- }
- update_banks();
-}
diff --git a/src/devices/bus/nes/henggedianzi.h b/src/devices/bus/nes/henggedianzi.h
index 0bf0b2faebc..fc5922a1c4e 100644
--- a/src/devices/bus/nes/henggedianzi.h
+++ b/src/devices/bus/nes/henggedianzi.h
@@ -17,12 +17,6 @@ public:
nes_hengg_srich_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
virtual void write_h(offs_t offset, uint8_t data) override;
-
- virtual void pcb_reset() override;
-
-protected:
- // device-level overrides
- virtual void device_start() override;
};
@@ -36,47 +30,11 @@ public:
virtual void write_l(offs_t offset, uint8_t data) override;
virtual void write_h(offs_t offset, uint8_t data) override;
-
- virtual void pcb_reset() override;
-
-protected:
- // device-level overrides
- virtual void device_start() override;
};
-// ======================> nes_hengg_shjy3_device
-
-class nes_hengg_shjy3_device : public nes_nrom_device
-{
-public:
- // construction/destruction
- nes_hengg_shjy3_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
-
- virtual void write_h(offs_t offset, uint8_t data) override;
-
- virtual void hblank_irq(int scanline, int vblank, int blanked) override;
- virtual void pcb_reset() override;
-
-protected:
- // device-level overrides
- virtual void device_start() override;
-
-private:
- void update_banks();
-
- uint16_t m_irq_count, m_irq_count_latch;
- int m_irq_enable;
-
- int m_chr_mode;
- uint8_t m_mmc_prg_bank[2];
- uint8_t m_mmc_vrom_bank[8];
- uint8_t m_mmc_extra_bank[8];
-};
-
// device type definition
DECLARE_DEVICE_TYPE(NES_HENGG_SRICH, nes_hengg_srich_device)
DECLARE_DEVICE_TYPE(NES_HENGG_XHZS, nes_hengg_xhzs_device)
-DECLARE_DEVICE_TYPE(NES_HENGG_SHJY3, nes_hengg_shjy3_device)
#endif // MAME_BUS_NES_HENGGEDIANZI_H
diff --git a/src/devices/bus/nes/hes.cpp b/src/devices/bus/nes/hes.cpp
index 946ea1f9585..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"
//-------------------------------------------------
@@ -33,26 +32,12 @@
DEFINE_DEVICE_TYPE(NES_HES, nes_hes_device, "nes_hes", "NES Cart HES PCB")
-nes_hes_device::nes_hes_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
+nes_hes_device::nes_hes_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock)
: nes_nrom_device(mconfig, NES_HES, tag, owner, clock)
{
}
-void nes_hes_device::device_start()
-{
- common_start();
-}
-
-void nes_hes_device::pcb_reset()
-{
- m_chr_source = m_vrom_chunks ? CHRROM : CHRRAM;
- prg32(0);
- chr8(0, m_chr_source);
-}
-
-
-
/*-------------------------------------------------
mapper specific handlers
-------------------------------------------------*/
@@ -69,19 +54,19 @@ void nes_hes_device::pcb_reset()
iNES: mapper 113
- In MESS: Supported.
+ In MAME: Supported.
-------------------------------------------------*/
-void nes_hes_device::write_l(offs_t offset, uint8_t data)
+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);
- if (!(offset & 0x100))
+ offset += 0x100;
+ if (BIT(offset, 8)) // $41xx, $43xx, ... $5fxx
{
- prg32((data & 0x38) >> 3);
- chr8((data & 0x07) | ((data & 0x40) >> 3), CHRROM);
- if (m_pcb_ctrl_mirror)
- set_nt_mirroring(BIT(data, 7) ? PPU_MIRROR_VERT : PPU_MIRROR_HORZ);
+ prg32(BIT(data, 3, 3));
+ chr8(bitswap<4>(data, 6, 2, 1, 0), CHRROM);
+ set_nt_mirroring(BIT(data, 7) ? PPU_MIRROR_VERT : PPU_MIRROR_HORZ);
}
}
diff --git a/src/devices/bus/nes/hes.h b/src/devices/bus/nes/hes.h
index ea72578ad98..24577f416cb 100644
--- a/src/devices/bus/nes/hes.h
+++ b/src/devices/bus/nes/hes.h
@@ -14,15 +14,9 @@ class nes_hes_device : public nes_nrom_device
{
public:
// construction/destruction
- nes_hes_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
+ nes_hes_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock);
- virtual void write_l(offs_t offset, uint8_t data) override;
-
- virtual void pcb_reset() override;
-
-protected:
- // device-level overrides
- virtual void device_start() override;
+ virtual void write_l(offs_t offset, u8 data) override;
};
diff --git a/src/devices/bus/nes/hosenkan.cpp b/src/devices/bus/nes/hosenkan.cpp
deleted file mode 100644
index ae7749b7e9a..00000000000
--- a/src/devices/bus/nes/hosenkan.cpp
+++ /dev/null
@@ -1,159 +0,0 @@
-// license:BSD-3-Clause
-// copyright-holders:Fabio Priuli
-/***********************************************************************************************************
-
-
- NES/Famicom cartridge emulation for Hosenkan PCBs
-
-
- ***********************************************************************************************************/
-
-
-#include "emu.h"
-#include "hosenkan.h"
-
-#include "video/ppu2c0x.h" // this has to be included so that IRQ functions can access ppu2c0x_device::BOTTOM_VISIBLE_SCANLINE
-#include "screen.h"
-
-
-#ifdef NES_PCB_DEBUG
-#define VERBOSE 1
-#else
-#define VERBOSE 0
-#endif
-
-#define LOG_MMC(x) do { if (VERBOSE) logerror x; } while (0)
-
-
-//-------------------------------------------------
-// constructor
-//-------------------------------------------------
-
-DEFINE_DEVICE_TYPE(NES_HOSENKAN, nes_hosenkan_device, "nes_hosenkan", "NES Cart HOSENKAN PCB")
-
-
-nes_hosenkan_device::nes_hosenkan_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
- : nes_nrom_device(mconfig, NES_HOSENKAN, tag, owner, clock)
- , m_irq_count(0)
- , m_irq_count_latch(0)
- , m_irq_clear(0)
- , m_irq_enable(0)
- , m_latch(0)
-{
-}
-
-
-
-
-void nes_hosenkan_device::device_start()
-{
- common_start();
- save_item(NAME(m_irq_enable));
- save_item(NAME(m_irq_count));
- save_item(NAME(m_irq_count_latch));
- save_item(NAME(m_irq_clear));
- save_item(NAME(m_latch));
-}
-
-void nes_hosenkan_device::pcb_reset()
-{
- m_chr_source = m_vrom_chunks ? CHRROM : CHRRAM;
- prg32((m_prg_chunks - 1) >> 1);
- chr8(0, m_chr_source);
-
- m_latch = 0;
- m_irq_enable = 0;
- m_irq_count = m_irq_count_latch = 0;
- m_irq_clear = 0;
-}
-
-
-
-/*-------------------------------------------------
- mapper specific handlers
- -------------------------------------------------*/
-
-/*-------------------------------------------------
-
- Bootleg Board by Hosenkan
-
- Games: Pocahontas, Super Donkey Kong
-
- iNES: mapper 182
-
- In MESS: Supported.
-
- -------------------------------------------------*/
-
-// same as MMC3!
-void nes_hosenkan_device::hblank_irq( int scanline, int vblank, int blanked )
-{
- if (scanline < ppu2c0x_device::BOTTOM_VISIBLE_SCANLINE)
- {
- int prior_count = m_irq_count;
- if ((m_irq_count == 0) || m_irq_clear)
- m_irq_count = m_irq_count_latch;
- else
- m_irq_count--;
-
- if (m_irq_enable && !blanked && (m_irq_count == 0) && (prior_count || m_irq_clear))
- {
- LOG_MMC(("irq fired, scanline: %d\n", scanline));
- hold_irq_line();
- }
- }
- m_irq_clear = 0;
-}
-
-void nes_hosenkan_device::write_h(offs_t offset, uint8_t data)
-{
- LOG_MMC(("hosenkan write_h, offset: %04x, data: %02x\n", offset, data));
-
- switch (offset & 0x7003)
- {
- case 0x0001:
- set_nt_mirroring(BIT(data, 0) ? PPU_MIRROR_HORZ : PPU_MIRROR_VERT);
- break;
- case 0x2000:
- m_latch = data;
- break;
- case 0x4000:
- switch (m_latch)
- {
- case 0:
- chr2_0(data >> 1, CHRROM);
- break;
- case 1:
- chr1_5(data, CHRROM);
- break;
- case 2:
- chr2_2(data >> 1, CHRROM);
- break;
- case 3:
- chr1_7(data, CHRROM);
- break;
- case 4:
- prg8_89(data);
- break;
- case 5:
- prg8_ab(data);
- break;
- case 6:
- chr1_4(data, CHRROM);
- break;
- case 7:
- chr1_6(data, CHRROM);
- break;
- }
- break;
- case 0x6003:
- if (data)
- {
- m_irq_count = data;
- m_irq_enable = 1;
- }
- else
- m_irq_enable = 0;
- break;
- }
-}
diff --git a/src/devices/bus/nes/hosenkan.h b/src/devices/bus/nes/hosenkan.h
deleted file mode 100644
index 163aef76edc..00000000000
--- a/src/devices/bus/nes/hosenkan.h
+++ /dev/null
@@ -1,39 +0,0 @@
-// license:BSD-3-Clause
-// copyright-holders:Fabio Priuli
-#ifndef MAME_BUS_NES_HOSENKAN_H
-#define MAME_BUS_NES_HOSENKAN_H
-
-#pragma once
-
-#include "nxrom.h"
-
-
-// ======================> nes_hosenkan_device
-
-class nes_hosenkan_device : public nes_nrom_device
-{
-public:
- // construction/destruction
- nes_hosenkan_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
-
- virtual void write_h(offs_t offset, uint8_t data) override;
-
- virtual void hblank_irq(int scanline, int vblank, int blanked) override;
- virtual void pcb_reset() override;
-
-protected:
- // device-level overrides
- virtual void device_start() override;
-
-private:
- uint16_t m_irq_count, m_irq_count_latch;
- uint8_t m_irq_clear;
- int m_irq_enable;
-
- uint8_t m_latch;
-};
-
-// device type definition
-DECLARE_DEVICE_TYPE(NES_HOSENKAN, nes_hosenkan_device)
-
-#endif // MAME_BUS_NES_HOSENKAN_H
diff --git a/src/devices/bus/nes/irem.cpp b/src/devices/bus/nes/irem.cpp
index c55cb588506..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"
//-------------------------------------------------
@@ -40,38 +39,38 @@ DEFINE_DEVICE_TYPE(NES_G101, nes_g101_device, "nes_g101", "NES Cart
DEFINE_DEVICE_TYPE(NES_H3001, nes_h3001_device, "ns_h3001", "NES Cart Irem H-3001 PCB")
-nes_lrog017_device::nes_lrog017_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
+nes_lrog017_device::nes_lrog017_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock)
: nes_nrom_device(mconfig, NES_LROG017, tag, owner, clock)
{
}
-nes_holydivr_device::nes_holydivr_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
+nes_holydivr_device::nes_holydivr_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock)
: nes_nrom_device(mconfig, NES_HOLYDIVR, tag, owner, clock)
{
}
-nes_tam_s1_device::nes_tam_s1_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
+nes_tam_s1_device::nes_tam_s1_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock)
: nes_nrom_device(mconfig, NES_TAM_S1, tag, owner, clock)
{
}
-nes_g101_device::nes_g101_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
- : nes_nrom_device(mconfig, NES_G101, tag, owner, clock), m_latch(0)
+nes_g101_device::nes_g101_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, u32 clock, u8 prg_mask)
+ : nes_nrom_device(mconfig, type, tag, owner, clock), m_latch(0), m_reg(0), m_prg_mask(prg_mask)
{
}
-nes_h3001_device::nes_h3001_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
- : nes_nrom_device(mconfig, NES_H3001, tag, owner, clock), m_irq_count(0), m_irq_count_latch(0), m_irq_enable(0), irq_timer(nullptr)
+nes_g101_device::nes_g101_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock)
+ : nes_g101_device(mconfig, NES_G101, tag, owner, clock, 0x1f)
{
}
+nes_h3001_device::nes_h3001_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock)
+ : nes_g101_device(mconfig, NES_H3001, tag, owner, clock, 0x3f), m_irq_count(0), m_irq_count_latch(0), m_irq_enable(0), irq_timer(nullptr)
+{
+}
-void nes_lrog017_device::device_start()
-{
- common_start();
-}
void nes_lrog017_device::pcb_reset()
{
@@ -82,52 +81,40 @@ void nes_lrog017_device::pcb_reset()
chr2_6(2, CHRRAM);
}
-void nes_holydivr_device::device_start()
-{
- common_start();
-}
-
void nes_holydivr_device::pcb_reset()
{
- m_chr_source = m_vrom_chunks ? CHRROM : CHRRAM;
prg16_89ab(0);
prg16_cdef(m_prg_chunks - 1);
chr8(0, m_chr_source);
}
-void nes_tam_s1_device::device_start()
-{
- common_start();
-}
-
void nes_tam_s1_device::pcb_reset()
{
- m_chr_source = m_vrom_chunks ? CHRROM : CHRRAM;
prg16_89ab(m_prg_chunks - 1);
prg16_cdef(0);
- chr8(0, m_chr_source);
}
void nes_g101_device::device_start()
{
common_start();
save_item(NAME(m_latch));
+ save_item(NAME(m_reg));
}
void nes_g101_device::pcb_reset()
{
- m_chr_source = m_vrom_chunks ? CHRROM : CHRRAM;
prg16_89ab(0);
prg16_cdef(m_prg_chunks - 1);
chr8(0, m_chr_source);
m_latch = 0;
+ m_reg = 0;
}
void nes_h3001_device::device_start()
{
- common_start();
- irq_timer = timer_alloc(TIMER_IRQ);
+ nes_g101_device::device_start();
+ irq_timer = timer_alloc(FUNC(nes_h3001_device::irq_timer_tick), this);
irq_timer->adjust(attotime::zero, 0, clocks_to_attotime(1));
save_item(NAME(m_irq_enable));
@@ -137,11 +124,7 @@ void nes_h3001_device::device_start()
void nes_h3001_device::pcb_reset()
{
- m_chr_source = m_vrom_chunks ? CHRROM : CHRRAM;
- prg16_89ab(0);
- prg16_cdef(m_prg_chunks - 1);
- chr8(0, m_chr_source);
-
+ nes_g101_device::pcb_reset();
m_irq_enable = 0;
m_irq_count = 0;
m_irq_count_latch = 0;
@@ -166,15 +149,15 @@ void nes_h3001_device::pcb_reset()
-------------------------------------------------*/
-void nes_lrog017_device::write_h(offs_t offset, uint8_t data)
+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);
prg32(data);
- chr2_0((data >> 4), CHRROM);
+ chr2_0(data >> 4, CHRROM);
}
/*-------------------------------------------------
@@ -185,9 +168,9 @@ void nes_lrog017_device::write_h(offs_t offset, uint8_t data)
-------------------------------------------------*/
-void nes_holydivr_device::write_h(offs_t offset, uint8_t 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);
@@ -205,19 +188,16 @@ void nes_holydivr_device::write_h(offs_t offset, uint8_t data)
iNES: mapper 97
- In MESS: Supported.
+ In MAME: Supported.
-------------------------------------------------*/
-void nes_tam_s1_device::write_h(offs_t offset, uint8_t 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)
{
- // this pcb is subject to bus conflict
- data = account_bus_conflict(offset, data);
-
set_nt_mirroring(BIT(data, 7) ? PPU_MIRROR_VERT : PPU_MIRROR_HORZ);
prg16_cdef(data);
}
@@ -227,40 +207,41 @@ void nes_tam_s1_device::write_h(offs_t offset, uint8_t data)
Irem G-101 board emulation
- Major League uses hardwired mirroring
+ Major League has hardwired mirroring and PRG mode latch
iNES: mapper 32
-------------------------------------------------*/
-void nes_g101_device::write_h(offs_t offset, uint8_t data)
+void nes_g101_device::set_prg()
{
- LOG_MMC(("g101 write_h, offset: %04x, data: %02x\n", offset, data));
+ prg8_x(0 ^ m_latch, m_reg);
+ prg8_x(2 ^ m_latch, m_prg_mask - 1);
+}
+
+void nes_g101_device::write_h(offs_t offset, u8 data)
+{
+ LOG("g101 write_h, offset: %04x, data: %02x\n", offset, data);
switch (offset & 0x7000)
{
case 0x0000:
- if (m_latch)
- {
- prg8_89(0xfe);
- prg8_cd(data & 0x1f);
- }
- else
- {
- prg8_89(data & 0x1f);
- prg8_cd(0xfe);
- }
+ m_reg = data & m_prg_mask;
+ set_prg();
break;
case 0x1000:
- m_latch = BIT(data, 1);
if (m_pcb_ctrl_mirror)
+ {
+ m_latch = data & 0x02;
+ set_prg();
set_nt_mirroring(BIT(data, 0) ? PPU_MIRROR_HORZ : PPU_MIRROR_VERT);
+ }
break;
case 0x2000:
- prg8_ab(data & 0x1f);
+ prg8_ab(data & m_prg_mask);
break;
case 0x3000:
- chr1_x(offset & 0x07, data & 0x7f, CHRROM);
+ chr1_x(offset & 0x07, data, CHRROM);
break;
}
}
@@ -274,77 +255,60 @@ void nes_g101_device::write_h(offs_t offset, uint8_t data)
iNES: mapper 65
- In MESS: Supported.
+ In MAME: Supported.
-------------------------------------------------*/
-
-void nes_h3001_device::device_timer(emu_timer &timer, device_timer_id id, int param, void *ptr)
+TIMER_CALLBACK_MEMBER(nes_h3001_device::irq_timer_tick)
{
- if (id == TIMER_IRQ)
+ if (m_irq_enable)
{
- if (m_irq_enable)
- {
- // 16bit counter, IRQ fired when the counter reaches 0
- // after firing, the counter is *not* reloaded and does not wrap
- if (m_irq_count > 0)
- m_irq_count--;
+ // 16bit counter, IRQ fired when the counter reaches 0
+ // after firing, the counter is *not* reloaded and does not wrap
+ if (m_irq_count)
+ m_irq_count--;
- if (!m_irq_count)
- {
- set_irq_line(ASSERT_LINE);
- m_irq_enable = 0;
- }
+ if (!m_irq_count)
+ {
+ set_irq_line(ASSERT_LINE);
+ m_irq_enable = 0;
}
}
}
-void nes_h3001_device::write_h(offs_t offset, uint8_t data)
+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 & 0x7fff)
+ switch (offset & 0x7007)
{
- case 0x0000:
- prg8_89(data);
+ default:
+ nes_g101_device::write_h(offset, data);
+ break;
+ case 0x1000:
+ m_latch = (data & 0x80) >> 6;
+ set_prg();
break;
-
case 0x1001:
- set_nt_mirroring(BIT(data, 7) ? PPU_MIRROR_HORZ : PPU_MIRROR_VERT);
+ set_nt_mirroring(BIT(data, 6) ? PPU_MIRROR_LOW : (BIT(data, 7) ? PPU_MIRROR_HORZ : PPU_MIRROR_VERT));
+ break;
+ case 0x1002:
break;
-
case 0x1003:
m_irq_enable = data & 0x80;
set_irq_line(CLEAR_LINE);
break;
-
case 0x1004:
m_irq_count = m_irq_count_latch;
set_irq_line(CLEAR_LINE);
break;
-
case 0x1005:
m_irq_count_latch = (m_irq_count_latch & 0x00ff) | (data << 8);
break;
-
case 0x1006:
m_irq_count_latch = (m_irq_count_latch & 0xff00) | data;
break;
-
- case 0x2000:
- prg8_ab(data);
- break;
-
- case 0x3000: case 0x3001: case 0x3002: case 0x3003:
- case 0x3004: case 0x3005: case 0x3006: case 0x3007:
- chr1_x(offset & 0x07, data, CHRROM);
- break;
-
- case 0x4000:
- prg8_cd(data);
- break;
-
- default:
+ case 0x1007:
break;
}
}
diff --git a/src/devices/bus/nes/irem.h b/src/devices/bus/nes/irem.h
index 82fd0815c38..1996b8f7455 100644
--- a/src/devices/bus/nes/irem.h
+++ b/src/devices/bus/nes/irem.h
@@ -14,15 +14,11 @@ class nes_lrog017_device : public nes_nrom_device
{
public:
// construction/destruction
- nes_lrog017_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
+ nes_lrog017_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock);
- virtual void write_h(offs_t offset, uint8_t data) override;
+ virtual void write_h(offs_t offset, u8 data) override;
virtual void pcb_reset() override;
-
-protected:
- // device-level overrides
- virtual void device_start() override;
};
@@ -32,15 +28,11 @@ class nes_holydivr_device : public nes_nrom_device
{
public:
// construction/destruction
- nes_holydivr_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
+ nes_holydivr_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock);
- virtual void write_h(offs_t offset, uint8_t data) override;
+ virtual void write_h(offs_t offset, u8 data) override;
virtual void pcb_reset() override;
-
-protected:
- // device-level overrides
- virtual void device_start() override;
};
@@ -50,15 +42,11 @@ class nes_tam_s1_device : public nes_nrom_device
{
public:
// construction/destruction
- nes_tam_s1_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
+ nes_tam_s1_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock);
- virtual void write_h(offs_t offset, uint8_t data) override;
+ virtual void write_h(offs_t offset, u8 data) override;
virtual void pcb_reset() override;
-
-protected:
- // device-level overrides
- virtual void device_start() override;
};
@@ -68,44 +56,54 @@ class nes_g101_device : public nes_nrom_device
{
public:
// construction/destruction
- nes_g101_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
+ nes_g101_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock);
- virtual void write_h(offs_t offset, uint8_t data) override;
+ virtual void write_h(offs_t offset, u8 data) override;
virtual void pcb_reset() override;
protected:
+ // construction/destruction
+ nes_g101_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, u32 clock, u8 prg_mask);
+
// device-level overrides
- virtual void device_start() override;
+ virtual void device_start() override ATTR_COLD;
- uint8_t m_latch;
+ void set_prg();
+ u8 m_latch;
+
+private:
+ u8 m_reg;
+ const u8 m_prg_mask;
};
// ======================> nes_h3001_device
-class nes_h3001_device : public nes_nrom_device
+class nes_h3001_device : public nes_g101_device
{
public:
// construction/destruction
- nes_h3001_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
+ nes_h3001_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock);
- virtual void write_h(offs_t offset, uint8_t data) override;
+ virtual void write_h(offs_t offset, u8 data) override;
virtual void pcb_reset() override;
protected:
// device-level overrides
- virtual void device_start() override;
- virtual void device_timer(emu_timer &timer, device_timer_id id, int param, void *ptr) override;
+ virtual void device_start() override ATTR_COLD;
+
+ TIMER_CALLBACK_MEMBER(irq_timer_tick);
- uint16_t m_irq_count, m_irq_count_latch;
- int m_irq_enable;
+private:
+ u16 m_irq_count, m_irq_count_latch;
+ u8 m_irq_enable;
- static const device_timer_id TIMER_IRQ = 0;
emu_timer *irq_timer;
};
+
// device type definition
DECLARE_DEVICE_TYPE(NES_LROG017, nes_lrog017_device)
DECLARE_DEVICE_TYPE(NES_HOLYDIVR, nes_holydivr_device)
diff --git a/src/devices/bus/nes/jaleco.cpp b/src/devices/bus/nes/jaleco.cpp
index 740c3c799b8..2ce809a4eea 100644
--- a/src/devices/bus/nes/jaleco.cpp
+++ b/src/devices/bus/nes/jaleco.cpp
@@ -21,17 +21,16 @@
#include "emu.h"
#include "jaleco.h"
-#include "sound/samples.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"
//-------------------------------------------------
@@ -52,130 +51,95 @@ DEFINE_DEVICE_TYPE(NES_JF29, nes_jf29_device, "nes_jf29", "NES C
DEFINE_DEVICE_TYPE(NES_JF33, nes_jf33_device, "nes_jf33", "NES Cart Jaleco JF-33 (Moe Pro! Saikyou-hen) PCB")
-nes_jf11_device::nes_jf11_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
+nes_jf11_device::nes_jf11_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock)
: nes_nrom_device(mconfig, NES_JF11, tag, owner, clock)
{
}
-nes_jf13_device::nes_jf13_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
+nes_jf13_device::nes_jf13_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock)
: nes_nrom_device(mconfig, NES_JF13, tag, owner, clock)
, m_samples(*this, "samples")
{
}
-nes_jf16_device::nes_jf16_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
+nes_jf16_device::nes_jf16_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock)
: nes_nrom_device(mconfig, NES_JF16, tag, owner, clock)
{
}
-nes_jf17_device::nes_jf17_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock)
- : nes_nrom_device(mconfig, type, tag, owner, clock), m_latch(0)
-{
-}
-
-nes_jf17_device::nes_jf17_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
- : nes_jf17_device(mconfig, NES_JF17, tag, owner, clock)
-{
-}
-
-nes_jf17_adpcm_device::nes_jf17_adpcm_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
- : nes_jf17_device(mconfig, NES_JF17_ADPCM, tag, owner, clock)
- , m_samples(*this, "samples")
-{
-}
-
-nes_jf19_device::nes_jf19_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock)
+nes_jf17_device::nes_jf17_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, u32 clock, bool prg_flip)
: nes_nrom_device(mconfig, type, tag, owner, clock)
-{
-}
-
-nes_jf19_device::nes_jf19_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
- : nes_jf19_device(mconfig, NES_JF19, tag, owner, clock)
-{
-}
-
-nes_jf19_adpcm_device::nes_jf19_adpcm_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
- : nes_jf19_device(mconfig, NES_JF19_ADPCM, tag, owner, clock)
, m_samples(*this, "samples")
+ , m_latch(0)
+ , m_prg_flip(prg_flip)
{
}
-nes_ss88006_device::nes_ss88006_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock)
- : nes_nrom_device(mconfig, type, tag, owner, clock), m_irq_count(0), m_irq_count_latch(0), m_irq_mode(0), m_irq_enable(0), irq_timer(nullptr), m_latch(0)
+nes_jf17_device::nes_jf17_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock)
+ : nes_jf17_device(mconfig, NES_JF17, tag, owner, clock, false)
{
}
-nes_ss88006_device::nes_ss88006_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
- : nes_ss88006_device(mconfig, NES_SS88006, tag, owner, clock)
+nes_jf17_adpcm_device::nes_jf17_adpcm_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock)
+ : nes_jf17_device(mconfig, NES_JF17_ADPCM, tag, owner, clock, false)
{
}
-nes_ss88006_adpcm_device::nes_ss88006_adpcm_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock)
- : nes_ss88006_device(mconfig, type, tag, owner, clock)
+nes_jf19_device::nes_jf19_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock)
+ : nes_jf17_device(mconfig, NES_JF19, tag, owner, clock, true)
{
}
-nes_jf23_device::nes_jf23_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
- : nes_ss88006_adpcm_device(mconfig, NES_JF23, tag, owner, clock)
- , m_samples(*this, "samples")
+nes_jf19_adpcm_device::nes_jf19_adpcm_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock)
+ : nes_jf17_device(mconfig, NES_JF19_ADPCM, tag, owner, clock, true)
{
}
-nes_jf24_device::nes_jf24_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
- : nes_ss88006_adpcm_device(mconfig, NES_JF24, tag, owner, clock)
+nes_ss88006_device::nes_ss88006_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, u32 clock)
+ : nes_nrom_device(mconfig, type, tag, owner, clock)
, m_samples(*this, "samples")
+ , m_irq_count(0)
+ , m_irq_count_latch(0)
+ , m_irq_mode(0)
+ , m_irq_enable(0)
+ , irq_timer(nullptr)
+ , m_wram_protect(0)
{
}
-nes_jf29_device::nes_jf29_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
- : nes_ss88006_adpcm_device(mconfig, NES_JF29, tag, owner, clock)
- , m_samples(*this, "samples")
+nes_ss88006_device::nes_ss88006_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock)
+ : nes_ss88006_device(mconfig, NES_SS88006, tag, owner, clock)
{
}
-nes_jf33_device::nes_jf33_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
- : nes_ss88006_adpcm_device(mconfig, NES_JF33, tag, owner, clock)
- , m_samples(*this, "samples")
+nes_jf23_device::nes_jf23_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock)
+ : nes_ss88006_device(mconfig, NES_JF23, tag, owner, clock)
{
}
-
-
-void nes_jf11_device::device_start()
+nes_jf24_device::nes_jf24_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock)
+ : nes_ss88006_device(mconfig, NES_JF24, tag, owner, clock)
{
- common_start();
}
-void nes_jf11_device::pcb_reset()
+nes_jf29_device::nes_jf29_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock)
+ : nes_ss88006_device(mconfig, NES_JF29, tag, owner, clock)
{
- m_chr_source = m_vrom_chunks ? CHRROM : CHRRAM;
- prg32(0);
- chr8(0, m_chr_source);
}
-void nes_jf13_device::device_start()
+nes_jf33_device::nes_jf33_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock)
+ : nes_ss88006_device(mconfig, NES_JF33, tag, owner, clock)
{
- common_start();
}
-void nes_jf13_device::pcb_reset()
-{
- m_chr_source = m_vrom_chunks ? CHRROM : CHRRAM;
- prg32(0);
- chr8(0, m_chr_source);
-}
-void nes_jf16_device::device_start()
-{
- common_start();
-}
void nes_jf16_device::pcb_reset()
{
- m_chr_source = m_vrom_chunks ? CHRROM : CHRRAM;
prg16_89ab(0);
prg16_cdef(m_prg_chunks - 1);
chr8(0, m_chr_source);
+ set_nt_mirroring(PPU_MIRROR_LOW);
}
void nes_jf17_device::device_start()
@@ -186,29 +150,16 @@ void nes_jf17_device::device_start()
void nes_jf17_device::pcb_reset()
{
- m_chr_source = m_vrom_chunks ? CHRROM : CHRRAM;
prg16_89ab(0);
- prg16_cdef(m_prg_chunks - 1);
+ prg16_cdef(m_prg_flip ? 0 : m_prg_chunks - 1);
chr8(0, m_chr_source);
m_latch = 0;
}
-void nes_jf19_device::device_start()
-{
- common_start();
-}
-
-void nes_jf19_device::pcb_reset()
-{
- m_chr_source = m_vrom_chunks ? CHRROM : CHRRAM;
- prg32(0);
- chr8(0, m_chr_source);
-}
-
void nes_ss88006_device::device_start()
{
common_start();
- irq_timer = timer_alloc(TIMER_IRQ);
+ irq_timer = timer_alloc(FUNC(nes_ss88006_device::irq_timer_tick), this);
irq_timer->adjust(attotime::zero, 0, clocks_to_attotime(1));
save_item(NAME(m_mmc_prg_bank));
@@ -217,23 +168,22 @@ void nes_ss88006_device::device_start()
save_item(NAME(m_irq_count));
save_item(NAME(m_irq_count_latch));
save_item(NAME(m_irq_mode));
- save_item(NAME(m_latch));
+ save_item(NAME(m_wram_protect));
}
void nes_ss88006_device::pcb_reset()
{
- m_chr_source = m_vrom_chunks ? CHRROM : CHRRAM;
prg16_89ab(0);
prg16_cdef(m_prg_chunks - 1);
chr8(0, m_chr_source);
- memset(m_mmc_prg_bank, 0, sizeof(m_mmc_prg_bank));
- memset(m_mmc_vrom_bank, 0, sizeof(m_mmc_vrom_bank));
+ std::fill(std::begin(m_mmc_prg_bank), std::end(m_mmc_prg_bank), 0x00);
+ std::fill(std::begin(m_mmc_vrom_bank), std::end(m_mmc_vrom_bank), 0x00);
m_irq_enable = 0;
m_irq_mode = 0;
m_irq_count = 0;
m_irq_count_latch = 0;
- m_latch = 0;
+ m_wram_protect = 0;
}
@@ -245,17 +195,18 @@ void nes_ss88006_device::pcb_reset()
Jaleco JF-11, JF-12 & JF-14 boards emulation
- Games: Bio Senshi Dan, Mississippi Satsujin Jiken
+ Games: Bio Senshi Dan, Mississippi Satsujin Jiken,
+ Yousai Club
iNES: mapper 140
- In MESS: Supported.
+ In MAME: Supported.
-------------------------------------------------*/
-void nes_jf11_device::write_m(offs_t offset, uint8_t data)
+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);
}
@@ -270,40 +221,36 @@ void nes_jf11_device::write_m(offs_t offset, uint8_t data)
iNES: mapper 86
- In MESS: Supported.
+ In MAME: Supported.
-------------------------------------------------*/
-void nes_jf13_device::write_m(offs_t offset, uint8_t 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)
{
- prg32((data >> 4) & 0x03);
- chr8(((data >> 4) & 0x04) | (data & 0x03), CHRROM);
- }
- else
- {
-// printf("sample write: offset: %04x, data: %02x\n", offset, data);
- if (data & 0x20)
- m_samples->start(data & 0x0f, data & 0x0f);
- else
- m_samples->stop_all();
+ prg32(BIT(data, 4, 2));
+ chr8(bitswap<3>(data, 6, 1, 0), CHRROM);
}
+ else if ((data & 0x30) == 0x20)
+ m_samples->start(data & 0x0f, data & 0x0f);
}
/*-------------------------------------------------
Jaleco JF-16 board emulation
+ Games: Uchuusen Cosmo Carrier
+
iNES: mapper 78 (shared with a diff Irem board)
-------------------------------------------------*/
-void nes_jf16_device::write_h(offs_t offset, uint8_t 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);
@@ -316,224 +263,141 @@ void nes_jf16_device::write_h(offs_t offset, uint8_t data)
/*-------------------------------------------------
- Jaleco JF-17 boards emulation
+ Jaleco JF-17 & JF-19 boards emulation
Note: we don't emulate the additional sound hardware
for Moero!! Pro Tennis
Games: Moero!! Juudou Warriors, Moero!! Pro Tennis, Pinball
- Quest Jpn
+ Quest Jpn, Moero Pro Soccer, Moero Pro Yakyuu '88
- iNES: mapper 72
+ iNES: mapper 72 & 92
- In MESS: Supported, see below for the Moero Pro Tennis
+ In MAME: Supported, see below for the games with samples
-------------------------------------------------*/
-void nes_jf17_device::write_h(offs_t offset, uint8_t data)
-{
- LOG_MMC(("jf17 write_h, offset: %04x, data: %02x\n", offset, data));
-
- // this pcb is subject to bus conflict
- data = account_bus_conflict(offset, data);
-
- if (BIT(m_latch, 7) && !BIT(data, 7))
- prg16_89ab(m_latch & 0x07);
- if (BIT(m_latch, 6) && !BIT(data, 6))
- chr8(m_latch & 0x0f, CHRROM);
-
- m_latch = data;
-}
-
-void nes_jf17_adpcm_device::write_h(offs_t offset, uint8_t data)
+void nes_jf17_device::write_h(offs_t offset, u8 data)
{
- LOG_MMC(("jf17 + ADPCM 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);
- if (BIT(m_latch, 7) && !BIT(data, 7))
- prg16_89ab(m_latch & 0x07);
- if (BIT(m_latch, 6) && !BIT(data, 6))
- chr8(m_latch & 0x0f, CHRROM);
- if (BIT(data, 5) && !BIT(data,4))
+ if (BIT(data, 7) && !BIT(m_latch, 7)) // 74174 clocks on 0 -> 1
{
-// printf("sample write: offset: %04x, data: %02x\n", offset, data);
- m_samples->start(offset & 0x1f, offset & 0x1f);
+ if (m_prg_flip)
+ prg16_cdef(data & 0x0f);
+ else
+ prg16_89ab(data & 0x07);
}
+ if (BIT(data, 6) && !BIT(m_latch, 6)) // 74174 clocks on 0 -> 1
+ chr8(data & 0x0f, CHRROM);
m_latch = data;
+
+ if (m_samples)
+ if ((data & 0x30) == 0x20)
+ m_samples->start(offset & 0x1f, offset & 0x1f);
}
/*-------------------------------------------------
- Jaleco JF-19 boards emulation
-
- Note: we don't emulate the additional sound hardware.
+ Jaleco SS88006 board emulation, aka JF-27, JF-29, JF-30, ...,
+ JF-38, JF-40, JF-41
- Games: Moero Pro Soccer, Moero Pro Yakyuu '88
+ Games: Lord of King, Magic John, Moe Pro '90, Ninja Jajamaru,
+ Pizza Pop, Plasma Ball
- iNES: mapper 92
+ iNES: mapper 18
- In MESS: Supported, see below for the Moero Pro Yakyuu '88
+ In MAME: Supported, see below for the games with samples
-------------------------------------------------*/
-void nes_jf19_device::write_h(offs_t offset, uint8_t data)
+TIMER_CALLBACK_MEMBER(nes_ss88006_device::irq_timer_tick)
{
- LOG_MMC(("jf19 write_h, offset: %04x, data: %02x\n", offset, data));
-
- // this pcb is subject to bus conflict
- data = account_bus_conflict(offset, data);
-
- if (BIT(data, 7))
- prg16_cdef(data & 0x0f);
- if (BIT(data, 6))
- chr8(data & 0x0f, CHRROM);
-}
+ if (m_irq_enable)
+ {
+ u16 mask = 0xffff; // 16-bit counter (default)
-void nes_jf19_adpcm_device::write_h(offs_t offset, uint8_t data)
-{
- LOG_MMC(("jf19 + ADPCM write_h, offset: %04x, data: %02x\n", offset, data));
+ if (BIT(m_irq_mode, 3)) // 4-bit counter
+ mask = 0x000f;
+ else if (BIT(m_irq_mode, 2)) // 8-bit counter
+ mask = 0x00ff;
+ else if (BIT(m_irq_mode, 1)) // 12-bit counter
+ mask = 0x0fff;
- // this pcb is subject to bus conflict
- data = account_bus_conflict(offset, data);
+ m_irq_count = (m_irq_count & ~mask) | ((m_irq_count - 1) & mask);
- if (BIT(data, 7))
- prg16_cdef(data & 0x0f);
- if (BIT(data, 6))
- chr8(data & 0x0f, CHRROM);
- if (BIT(data, 5) && !BIT(data,4))
- {
-// printf("sample write: offset: %04x, data: %02x\n", offset, data);
- m_samples->start(offset & 0x1f, offset & 0x1f);
+ if ((m_irq_count & mask) == mask)
+ set_irq_line(ASSERT_LINE);
}
}
-/*-------------------------------------------------
-
- Jaleco SS88006 board emulation, aka JF-27, JF-29, JF-30, ...,
- JF-38, JF-40, JF-41
-
- Games: Lord of King, Magic John, Moe Pro '90, Ninja Jajamaru,
- Pizza Pop, Plasma Ball
-
- iNES: mapper 18
+u8 nes_ss88006_device::read_m(offs_t offset)
+{
+ LOG("ss88006 read_m, offset: %04x\n", offset);
- In MESS: Supported, see below for the games with samples
+ if (m_wram_protect & 1) // RAM enabled
+ return device_nes_cart_interface::read_m(offset);
- -------------------------------------------------*/
+ return get_open_bus();
+}
-void nes_ss88006_device::device_timer(emu_timer &timer, device_timer_id id, int param, void *ptr)
+void nes_ss88006_device::write_m(offs_t offset, u8 data)
{
- if (id == TIMER_IRQ)
- {
- if (m_irq_enable)
- {
- if (m_irq_mode & 0x08) // 4bits counter
- {
- if (!(m_irq_count & 0x000f))
- {
- set_irq_line(ASSERT_LINE);
- m_irq_count = (m_irq_count & 0xfff0) | 0x000f;
- }
- else
- m_irq_count = (m_irq_count & 0xfff0) | ((m_irq_count & 0x000f) - 1);
- }
- else if (m_irq_mode & 0x04) // 8bits counter
- {
- if (!(m_irq_count & 0x00ff))
- {
- set_irq_line(ASSERT_LINE);
- m_irq_count = (m_irq_count & 0xff00) | 0x00ff;
- }
- else
- m_irq_count = (m_irq_count & 0xff00) | ((m_irq_count & 0x00ff) - 1);
- }
- else if (m_irq_mode & 0x02) // 12bits counter
- {
- if (!(m_irq_count & 0x0fff))
- {
- set_irq_line(ASSERT_LINE);
- m_irq_count = (m_irq_count & 0xf000) | 0x0fff;
- }
- else
- m_irq_count = (m_irq_count & 0xf000) | ((m_irq_count & 0x0fff) - 1);
- }
- else // 16bits counter
- {
- if (!m_irq_count)
- {
- set_irq_line(ASSERT_LINE);
- m_irq_count = 0xffff;
- }
- else
- m_irq_count = m_irq_count - 1;
- }
- }
- }
+ 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);
}
-void nes_ss88006_device::ss88006_write(offs_t offset, uint8_t data)
+void nes_ss88006_device::write_h(offs_t offset, u8 data)
{
- uint8_t bank;
- 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;
switch (offset & 0x7003)
{
case 0x0000:
- m_mmc_prg_bank[0] = (m_mmc_prg_bank[0] & 0xf0) | (data & 0x0f);
- prg8_89(m_mmc_prg_bank[0]);
- break;
case 0x0001:
- m_mmc_prg_bank[0] = (m_mmc_prg_bank[0] & 0x0f) | (data << 4);
- prg8_89(m_mmc_prg_bank[0]);
- break;
case 0x0002:
- m_mmc_prg_bank[1] = (m_mmc_prg_bank[1] & 0xf0) | (data & 0x0f);
- prg8_ab(m_mmc_prg_bank[1]);
- break;
case 0x0003:
- m_mmc_prg_bank[1] = (m_mmc_prg_bank[1] & 0x0f) | (data << 4);
- prg8_ab(m_mmc_prg_bank[1]);
- break;
case 0x1000:
- m_mmc_prg_bank[2] = (m_mmc_prg_bank[2] & 0xf0) | (data & 0x0f);
- prg8_cd(m_mmc_prg_bank[2]);
- break;
case 0x1001:
- m_mmc_prg_bank[2] = (m_mmc_prg_bank[2] & 0x0f) | (data << 4);
- prg8_cd(m_mmc_prg_bank[2]);
+ bank = bitswap<2>(offset, 12, 1);
+ shift = (offset & 1) << 2;
+ m_mmc_prg_bank[bank] &= ~(0x0f << shift);
+ m_mmc_prg_bank[bank] |= (data & 0x0f) << shift;
+ prg8_x(bank, m_mmc_prg_bank[bank]);
break;
- /* $9002, 3 (1002, 3) uncaught = Jaleco Baseball writes 0 */
- /* believe it's related to battery-backed ram enable/disable */
+ case 0x1002:
+ m_wram_protect = data & 0x03;
+ break;
case 0x2000: case 0x2001: case 0x2002: case 0x2003:
case 0x3000: case 0x3001: case 0x3002: case 0x3003:
case 0x4000: case 0x4001: case 0x4002: case 0x4003:
case 0x5000: case 0x5001: case 0x5002: case 0x5003:
- bank = ((offset & 0x7000) - 0x2000) / 0x0800 + ((offset & 0x0002) >> 1);
- if (offset & 0x0001)
- m_mmc_vrom_bank[bank] = (m_mmc_vrom_bank[bank] & 0x0f) | ((data & 0x0f)<< 4);
- else
- m_mmc_vrom_bank[bank] = (m_mmc_vrom_bank[bank] & 0xf0) | (data & 0x0f);
-
+ bank = 2 * (BIT(offset, 12, 3) - 2) + BIT(offset, 1);
+ shift = (offset & 1) << 2;
+ m_mmc_vrom_bank[bank] &= ~(0x0f << shift);
+ m_mmc_vrom_bank[bank] |= (data & 0x0f) << shift;
chr1_x(bank, m_mmc_vrom_bank[bank], CHRROM);
break;
case 0x6000:
- m_irq_count_latch = (m_irq_count_latch & 0xfff0) | (data & 0x0f);
- break;
case 0x6001:
- m_irq_count_latch = (m_irq_count_latch & 0xff0f) | ((data & 0x0f) << 4);
- break;
case 0x6002:
- m_irq_count_latch = (m_irq_count_latch & 0xf0ff) | ((data & 0x0f) << 8);
- break;
case 0x6003:
- m_irq_count_latch = (m_irq_count_latch & 0x0fff) | ((data & 0x0f) << 12);
+ shift = 4 * (offset & 0x03);
+ m_irq_count_latch &= ~(0x000f << shift);
+ m_irq_count_latch |= (data & 0x0f) << shift;
break;
+
case 0x7000:
m_irq_count = m_irq_count_latch;
set_irq_line(CLEAR_LINE);
@@ -554,34 +418,14 @@ void nes_ss88006_device::ss88006_write(offs_t offset, uint8_t data)
}
break;
- default:
- logerror("Jaleco SS88006 uncaught write, addr: %04x, value: %02x\n", offset + 0x8000, data);
- break;
- }
-}
-
-
-// bits2-bits6 are sample number, bit1 is setup/enable/disable
-// program first write sample # + bit1 set to 'init' the sample
-// then it writes sample # + bit1 clear to 'start' the sample
-void nes_ss88006_adpcm_device::ss88006_adpcm_write(offs_t offset, uint8_t data, samples_device &dev)
-{
- LOG_MMC(("ss88006 write_h, offset: %04x, data: %02x\n", offset, data));
-
- switch (offset & 0x7003)
- {
case 0x7003:
- if ((m_latch & 0x7c) == (data & 0x7c))
- {
-// printf("sample write: data: %02x\n", data);
- if ((m_latch & 2) && !(data & 2))
- dev.start((data >> 2) & 0x1f, (data >> 2) & 0x1f);
- }
- m_latch = data;
+ if (m_samples)
+ if ((data & 0x03) == 0x02)
+ m_samples->start(BIT(data, 2, 5), BIT(data, 2, 5));
break;
default:
- ss88006_write(offset, data);
+ LOGMASKED(LOG_UNHANDLED, "Jaleco SS88006 uncaught write, addr: %04x, value: %02x\n", offset + 0x8000, data);
break;
}
}
@@ -612,13 +456,13 @@ static const char *const jf13_sample_names[] =
"04", // safe
"05", // foul
"06", // (catcher obtains the ball)
- "07", // you're out
+ "07", // batter out
"08", // play ball
"09", // ball four
"10", // home run
"11", // new pitcher
"12", // ouch (pitcher hits batter)
- "13", // ??
+ "13", // aho (idiot)
"14", // (bat hits the ball)
"15", // (crowd)
nullptr
diff --git a/src/devices/bus/nes/jaleco.h b/src/devices/bus/nes/jaleco.h
index 53cc5716ce3..96c235f77f5 100644
--- a/src/devices/bus/nes/jaleco.h
+++ b/src/devices/bus/nes/jaleco.h
@@ -15,15 +15,9 @@ class nes_jf11_device : public nes_nrom_device
{
public:
// construction/destruction
- nes_jf11_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
+ nes_jf11_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock);
- virtual void write_m(offs_t offset, uint8_t data) override;
-
- virtual void pcb_reset() override;
-
-protected:
- // device-level overrides
- virtual void device_start() override;
+ virtual void write_m(offs_t offset, u8 data) override;
};
@@ -33,17 +27,13 @@ class nes_jf13_device : public nes_nrom_device
{
public:
// construction/destruction
- nes_jf13_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
-
- virtual void write_m(offs_t offset, uint8_t data) override;
+ nes_jf13_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock);
- virtual void pcb_reset() override;
+ virtual void write_m(offs_t offset, u8 data) override;
protected:
// device-level overrides
- virtual void device_start() override;
-
- virtual void device_add_mconfig(machine_config &config) override;
+ virtual void device_add_mconfig(machine_config &config) override ATTR_COLD;
private:
required_device<samples_device> m_samples;
@@ -56,15 +46,11 @@ class nes_jf16_device : public nes_nrom_device
{
public:
// construction/destruction
- nes_jf16_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
+ nes_jf16_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock);
- virtual void write_h(offs_t offset, uint8_t data) override;
+ virtual void write_h(offs_t offset, u8 data) override;
virtual void pcb_reset() override;
-
-protected:
- // device-level overrides
- virtual void device_start() override;
};
@@ -74,19 +60,23 @@ class nes_jf17_device : public nes_nrom_device
{
public:
// construction/destruction
- nes_jf17_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
+ nes_jf17_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock);
- virtual void write_h(offs_t offset, uint8_t data) override;
+ virtual void write_h(offs_t offset, u8 data) override;
virtual void pcb_reset() override;
protected:
- nes_jf17_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock);
+ nes_jf17_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, u32 clock, bool m_prg_flip);
// device-level overrides
- virtual void device_start() override;
+ virtual void device_start() override ATTR_COLD;
- uint8_t m_latch;
+ optional_device<samples_device> m_samples;
+
+private:
+ u8 m_latch;
+ const bool m_prg_flip;
};
@@ -96,53 +86,33 @@ class nes_jf17_adpcm_device : public nes_jf17_device
{
public:
// construction/destruction
- nes_jf17_adpcm_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
-
- virtual void write_h(offs_t offset, uint8_t data) override;
+ nes_jf17_adpcm_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock);
protected:
- virtual void device_add_mconfig(machine_config &config) override;
-
-private:
- required_device<samples_device> m_samples;
+ virtual void device_add_mconfig(machine_config &config) override ATTR_COLD;
};
// ======================> nes_jf19_device
-class nes_jf19_device : public nes_nrom_device
+class nes_jf19_device : public nes_jf17_device
{
public:
// construction/destruction
- nes_jf19_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
-
- virtual void write_h(offs_t offset, uint8_t data) override;
-
- virtual void pcb_reset() override;
-
-protected:
- nes_jf19_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;
+ nes_jf19_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock);
};
// ======================> nes_jf19_adpcm_device
-class nes_jf19_adpcm_device : public nes_jf19_device
+class nes_jf19_adpcm_device : public nes_jf17_device
{
public:
// construction/destruction
- nes_jf19_adpcm_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
-
- virtual void write_h(offs_t offset, uint8_t data) override;
+ nes_jf19_adpcm_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock);
protected:
- virtual void device_add_mconfig(machine_config &config) override;
-
-private:
- required_device<samples_device> m_samples;
+ virtual void device_add_mconfig(machine_config &config) override ATTR_COLD;
};
@@ -152,115 +122,86 @@ class nes_ss88006_device : public nes_nrom_device
{
public:
// construction/destruction
- nes_ss88006_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
+ nes_ss88006_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock);
- void ss88006_write(offs_t offset, uint8_t data);
- virtual void write_h(offs_t offset, uint8_t data) override { ss88006_write(offset, data); }
+ virtual u8 read_m(offs_t offset) override;
+ virtual void write_m(offs_t offset, u8 data) override;
+ virtual void write_h(offs_t offset, u8 data) override;
virtual void pcb_reset() override;
protected:
- nes_ss88006_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock);
+ nes_ss88006_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_timer(emu_timer &timer, device_timer_id id, int param, void *ptr) override;
-
- uint16_t m_irq_count, m_irq_count_latch;
- uint8_t m_irq_mode;
- int m_irq_enable;
+ virtual void device_start() override ATTR_COLD;
- static const device_timer_id TIMER_IRQ = 0;
- emu_timer *irq_timer;
+ TIMER_CALLBACK_MEMBER(irq_timer_tick);
- uint8_t m_mmc_prg_bank[3];
- uint8_t m_mmc_vrom_bank[8];
+ optional_device<samples_device> m_samples;
- uint8_t m_latch; // used for samples, in derived classes
-};
-
-
-// ======================> nes_ss88006_adpcm_device
+private:
+ u16 m_irq_count, m_irq_count_latch;
+ u8 m_irq_mode;
+ u8 m_irq_enable;
-class nes_ss88006_adpcm_device : public nes_ss88006_device
-{
-protected:
- // construction/destruction
- nes_ss88006_adpcm_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock);
+ emu_timer *irq_timer;
- void ss88006_adpcm_write(offs_t offset, uint8_t data, samples_device &dev);
+ u8 m_mmc_prg_bank[3];
+ u8 m_mmc_vrom_bank[8];
+ u8 m_wram_protect;
};
// ======================> nes_jf23_device
-class nes_jf23_device : public nes_ss88006_adpcm_device
+class nes_jf23_device : public nes_ss88006_device
{
public:
// construction/destruction
- nes_jf23_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
+ nes_jf23_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock);
protected:
- virtual void device_add_mconfig(machine_config &config) override;
-
-private:
- virtual void write_h(offs_t offset, uint8_t data) override { ss88006_adpcm_write(offset, data, *m_samples); }
-
- required_device<samples_device> m_samples;
+ virtual void device_add_mconfig(machine_config &config) override ATTR_COLD;
};
// ======================> nes_jf24_device
-class nes_jf24_device : public nes_ss88006_adpcm_device
+class nes_jf24_device : public nes_ss88006_device
{
public:
// construction/destruction
- nes_jf24_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
+ nes_jf24_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock);
protected:
- virtual void device_add_mconfig(machine_config &config) override;
-
-private:
- virtual void write_h(offs_t offset, uint8_t data) override { ss88006_adpcm_write(offset, data, *m_samples); }
-
- required_device<samples_device> m_samples;
+ virtual void device_add_mconfig(machine_config &config) override ATTR_COLD;
};
// ======================> nes_jf29_device
-class nes_jf29_device : public nes_ss88006_adpcm_device
+class nes_jf29_device : public nes_ss88006_device
{
public:
// construction/destruction
- nes_jf29_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
+ nes_jf29_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock);
protected:
- virtual void device_add_mconfig(machine_config &config) override;
-
-private:
- virtual void write_h(offs_t offset, uint8_t data) override { ss88006_adpcm_write(offset, data, *m_samples); }
-
- required_device<samples_device> m_samples;
+ virtual void device_add_mconfig(machine_config &config) override ATTR_COLD;
};
// ======================> nes_jf33_device
-class nes_jf33_device : public nes_ss88006_adpcm_device
+class nes_jf33_device : public nes_ss88006_device
{
public:
// construction/destruction
- nes_jf33_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
+ nes_jf33_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock);
protected:
- virtual void device_add_mconfig(machine_config &config) override;
-
-private:
- virtual void write_h(offs_t offset, uint8_t data) override { ss88006_adpcm_write(offset, data, *m_samples); }
-
- required_device<samples_device> m_samples;
+ virtual void device_add_mconfig(machine_config &config) override ATTR_COLD;
};
diff --git a/src/devices/bus/nes/jncota.cpp b/src/devices/bus/nes/jncota.cpp
new file mode 100644
index 00000000000..613acd8e3f3
--- /dev/null
+++ b/src/devices/bus/nes/jncota.cpp
@@ -0,0 +1,108 @@
+// license:BSD-3-Clause
+// copyright-holders:kmg
+/***********************************************************************************************************
+
+
+ NES/Famicom cartridge emulation for Shenzhen Jncota PCBs
+
+
+ Here we emulate the following PCBs
+
+ * Jncota KT-1001 [mapper 551]
+
+ ***********************************************************************************************************/
+
+
+#include "emu.h"
+#include "jncota.h"
+
+
+#ifdef NES_PCB_DEBUG
+#define VERBOSE (LOG_GENERAL)
+#else
+#define VERBOSE (0)
+#endif
+#include "logmacro.h"
+
+
+//-------------------------------------------------
+// constructor
+//-------------------------------------------------
+
+DEFINE_DEVICE_TYPE(NES_JNCOTA_KT1001, nes_jncota_kt1001_device, "nes_jncota_kt1001", "NES Cart Shenzhen Jncota KT-1001 PCB")
+
+
+nes_jncota_kt1001_device::nes_jncota_kt1001_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock)
+ : nes_nrom_device(mconfig, NES_JNCOTA_KT1001, tag, owner, clock)
+{
+}
+
+
+
+void nes_jncota_kt1001_device::device_start()
+{
+ common_start();
+ save_item(NAME(m_reg));
+}
+
+void nes_jncota_kt1001_device::pcb_reset()
+{
+ prg32(0);
+ chr8(0, CHRROM);
+
+ m_reg[0] = m_reg[1] = m_reg[2] = 0;
+}
+
+
+/*-------------------------------------------------
+ mapper specific handlers
+ -------------------------------------------------*/
+
+/*-------------------------------------------------
+
+ Shenzhen Jncota board KT-1001 (this is the serial
+ on the cart, PCB is likely KT-00X for some X)
+
+ Games: Jing Ke Xin Zhuan, Sheng Huo Lie Zhuan,
+ Zhan Guo Feng Yun, Xia Ke Chuan Qi
+
+ This board is very similar to mapper 178 but with
+ bankable CHRROM instead of PRGRAM and without
+ selectable mirroring.
+
+ NES 2.0: mapper 551
+
+ In MAME: Supported.
+
+ -------------------------------------------------*/
+
+void nes_jncota_kt1001_device::write_l(offs_t offset, u8 data)
+{
+ LOG("jncota_kt1001 write_h, offset: %04x, data: %02x\n", offset, data);
+
+ offset += 0x100;
+ switch (offset & 0x1803)
+ {
+ case 0x0800: case 0x0801: case 0x0802:
+ {
+ m_reg[offset & 3] = data;
+
+ u16 bank = m_reg[2] << 3 | (m_reg[1] & 0x7);
+ u16 mode = !BIT(m_reg[0], 2);
+ if (BIT(m_reg[0], 1)) // UNROM mode
+ {
+ prg16_89ab(bank);
+ prg16_cdef(bank | mode | 0x06);
+ }
+ else // NROM mode
+ {
+ prg16_89ab(bank & ~mode);
+ prg16_cdef(bank | mode);
+ }
+ break;
+ }
+ case 0x0803:
+ chr8(data, CHRROM);
+ break;
+ }
+}
diff --git a/src/devices/bus/nes/jncota.h b/src/devices/bus/nes/jncota.h
new file mode 100644
index 00000000000..586d797c262
--- /dev/null
+++ b/src/devices/bus/nes/jncota.h
@@ -0,0 +1,35 @@
+// license:BSD-3-Clause
+// copyright-holders:kmg
+#ifndef MAME_BUS_NES_JNCOTA_H
+#define MAME_BUS_NES_JNCOTA_H
+
+#pragma once
+
+#include "nxrom.h"
+
+
+// ======================> nes_jncota_kt1001_device
+
+class nes_jncota_kt1001_device : public nes_nrom_device
+{
+public:
+ // construction/destruction
+ nes_jncota_kt1001_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock);
+
+ virtual void write_l(offs_t offset, u8 data) override;
+
+ virtual void pcb_reset() override;
+
+protected:
+ // device-level overrides
+ virtual void device_start() override ATTR_COLD;
+
+private:
+ u8 m_reg[3];
+};
+
+
+// device type definition
+DECLARE_DEVICE_TYPE(NES_JNCOTA_KT1001, nes_jncota_kt1001_device)
+
+#endif // MAME_BUS_NES_JNCOTA_H
diff --git a/src/devices/bus/nes/jy.cpp b/src/devices/bus/nes/jy.cpp
index 8a54624cd5a..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"
//-------------------------------------------------
@@ -73,7 +72,7 @@ nes_jy_typec_device::nes_jy_typec_device(const machine_config &mconfig, const ch
void nes_jy_typea_device::device_start()
{
common_start();
- irq_timer = timer_alloc(TIMER_IRQ);
+ irq_timer = timer_alloc(FUNC(nes_jy_typea_device::irq_timer_tick), this);
irq_timer->reset();
timer_freq = clocks_to_attotime(1);
@@ -98,7 +97,6 @@ void nes_jy_typea_device::device_start()
void nes_jy_typea_device::pcb_reset()
{
- m_chr_source = m_vrom_chunks ? CHRROM : CHRRAM;
prg32(0);
chr8(0, m_chr_source);
@@ -147,18 +145,18 @@ void nes_jy_typea_device::pcb_reset()
uint8_t nes_jy_typea_device::nt_r(offs_t offset)
{
int page = ((offset & 0xc00) >> 10);
- irq_clock(0, 2);
+ irq_clock(false, 2);
return m_nt_access[page][offset & 0x3ff];
}
uint8_t nes_jy_typea_device::chr_r(offs_t offset)
{
int bank = offset >> 10;
- irq_clock(0, 2);
+ irq_clock(false, 2);
return m_chr_access[bank][offset & 0x3ff];
}
-void nes_jy_typea_device::irq_clock(int mode, int blanked)
+void nes_jy_typea_device::irq_clock(bool blanked, int mode)
{
bool clock = false, fire = false;
@@ -225,15 +223,12 @@ void nes_jy_typea_device::irq_clock(int mode, int blanked)
}
}
-void nes_jy_typea_device::device_timer(emu_timer &timer, device_timer_id id, int param, void *ptr)
+TIMER_CALLBACK_MEMBER(nes_jy_typea_device::irq_timer_tick)
{
- if (id == TIMER_IRQ)
- {
- irq_clock(0, 0);
- }
+ irq_clock(false, 0);
}
-void nes_jy_typea_device::scanline_irq(int scanline, int vblank, int blanked)
+void nes_jy_typea_device::scanline_irq(int scanline, bool vblank, bool blanked)
{
if (scanline < ppu2c0x_device::BOTTOM_VISIBLE_SCANLINE)
irq_clock(blanked, 1);
@@ -243,7 +238,7 @@ void nes_jy_typea_device::scanline_irq(int scanline, int vblank, int 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)
@@ -262,12 +257,12 @@ uint8_t nes_jy_typea_device::read_l(offs_t offset)
return m_latch;
}
- return get_open_bus(); // open bus
+ return get_open_bus();
}
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)
@@ -284,12 +279,12 @@ 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)];
- return get_open_bus(); // open bus
+ return get_open_bus();
}
@@ -427,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)
{
@@ -573,7 +568,7 @@ uint8_t nes_jy_typec_device::chr_r(offs_t offset)
{
int bank = offset >> 10;
- irq_clock(0, 2);
+ irq_clock(false, 2);
switch (offset & 0xff0)
{
case 0xfd0:
diff --git a/src/devices/bus/nes/jy.h b/src/devices/bus/nes/jy.h
index d318bfae60a..4f36fd68b4c 100644
--- a/src/devices/bus/nes/jy.h
+++ b/src/devices/bus/nes/jy.h
@@ -24,17 +24,18 @@ public:
virtual uint8_t chr_r(offs_t offset) override;
virtual uint8_t nt_r(offs_t offset) override;
- virtual void scanline_irq(int scanline, int vblank, int blanked) override;
+ virtual void scanline_irq(int scanline, bool vblank, bool blanked) override;
virtual void pcb_reset() override;
protected:
nes_jy_typea_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_timer(emu_timer &timer, device_timer_id id, int param, void *ptr) override;
+ virtual void device_start() override ATTR_COLD;
- void irq_clock(int blanked, int mode);
+ TIMER_CALLBACK_MEMBER(irq_timer_tick);
+
+ void irq_clock(bool blanked, int mode);
void update_banks(int reg);
void update_prg();
void update_chr();
@@ -61,7 +62,6 @@ protected:
int m_irq_enable;
int m_irq_up, m_irq_down;
- static const device_timer_id TIMER_IRQ = 0;
emu_timer *irq_timer;
attotime timer_freq;
};
diff --git a/src/devices/bus/nes/kaiser.cpp b/src/devices/bus/nes/kaiser.cpp
index 52690376e4b..aaa5a247341 100644
--- a/src/devices/bus/nes/kaiser.cpp
+++ b/src/devices/bus/nes/kaiser.cpp
@@ -8,23 +8,22 @@
Here we emulate the following Kaiser bootleg PCBs
+ * Kaiser KS106C
* Kaiser KS202
+ * Kaiser KS7010
* Kaiser KS7012
* Kaiser KS7013B
+ * Kaiser KS7016
+ * Kaiser KS7016B
* Kaiser KS7017
+ * Kaiser KS7021A
* Kaiser KS7022
+ * Kaiser KS7030
+ * Kaiser KS7031
* Kaiser KS7032
- * Kaiser KS7058
- * Kaiser KS7016
* Kaiser KS7037
-
- The Kaiser KS7057 bootleg board is emulated in nes_mmc3_clones.cpp
-
-
- TODO:
- - FCEUmm lists more Kaiser PCBs:
- * KS7030 (for Yume Koujou Doki Doki Panic by Kaiser?)
- but there seem to be no available dumps...
+ * Kaiser KS7057
+ * Kaiser KS7058
***********************************************************************************************************/
@@ -32,100 +31,143 @@
#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"
//-------------------------------------------------
// constructor
//-------------------------------------------------
-DEFINE_DEVICE_TYPE(NES_KS7058, nes_ks7058_device, "nes_ks7058", "NES Cart Kaiser KS-7058 PCB")
-DEFINE_DEVICE_TYPE(NES_KS7022, nes_ks7022_device, "nes_ks7022", "NES Cart Kaiser KS-7022 PCB")
-DEFINE_DEVICE_TYPE(NES_KS7032, nes_ks7032_device, "nes_ks7032", "NES Cart Kaiser KS-7032 PCB")
+DEFINE_DEVICE_TYPE(NES_KS106C, nes_ks106c_device, "nes_ks106c", "NES Cart Kaiser KS-106C PCB")
DEFINE_DEVICE_TYPE(NES_KS202, nes_ks202_device, "nes_ks202", "NES Cart Kaiser KS-202 PCB")
-DEFINE_DEVICE_TYPE(NES_KS7017, nes_ks7017_device, "nes_ks7017", "NES Cart Kaiser KS-7017 PCB")
+DEFINE_DEVICE_TYPE(NES_KS7010, nes_ks7010_device, "nes_ks7010", "NES Cart Kaiser KS-7010 PCB")
DEFINE_DEVICE_TYPE(NES_KS7012, nes_ks7012_device, "nes_ks7012", "NES Cart Kaiser KS-7012 PCB")
DEFINE_DEVICE_TYPE(NES_KS7013B, nes_ks7013b_device, "nes_ks7013b", "NES Cart Kaiser KS-7013B PCB")
-DEFINE_DEVICE_TYPE(NES_KS7031, nes_ks7031_device, "nes_ks7031", "NES Cart Kaiser KS-7031 PCB")
DEFINE_DEVICE_TYPE(NES_KS7016, nes_ks7016_device, "nes_ks7016", "NES Cart Kaiser KS-7016 PCB")
+DEFINE_DEVICE_TYPE(NES_KS7016B, nes_ks7016b_device, "nes_ks7016b", "NES Cart Kaiser KS-7016B PCB")
+DEFINE_DEVICE_TYPE(NES_KS7017, nes_ks7017_device, "nes_ks7017", "NES Cart Kaiser KS-7017 PCB")
+DEFINE_DEVICE_TYPE(NES_KS7021A, nes_ks7021a_device, "nes_ks7021a", "NES Cart Kaiser KS-7021A PCB")
+DEFINE_DEVICE_TYPE(NES_KS7022, nes_ks7022_device, "nes_ks7022", "NES Cart Kaiser KS-7022 PCB")
+DEFINE_DEVICE_TYPE(NES_KS7030, nes_ks7030_device, "nes_ks7030", "NES Cart Kaiser KS-7030 PCB")
+DEFINE_DEVICE_TYPE(NES_KS7031, nes_ks7031_device, "nes_ks7031", "NES Cart Kaiser KS-7031 PCB")
+DEFINE_DEVICE_TYPE(NES_KS7032, nes_ks7032_device, "nes_ks7032", "NES Cart Kaiser KS-7032 PCB")
DEFINE_DEVICE_TYPE(NES_KS7037, nes_ks7037_device, "nes_ks7037", "NES Cart Kaiser KS-7037 PCB")
+DEFINE_DEVICE_TYPE(NES_KS7057, nes_ks7057_device, "nes_ks7057", "NES Cart Kaiser KS-7057 PCB")
+DEFINE_DEVICE_TYPE(NES_KS7058, nes_ks7058_device, "nes_ks7058", "NES Cart Kaiser KS-7058 PCB")
+
+nes_ks106c_device::nes_ks106c_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock)
+ : nes_nrom_device(mconfig, NES_KS106C, tag, owner, clock), m_latch(0)
+{
+}
-nes_ks7058_device::nes_ks7058_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
+nes_ks7058_device::nes_ks7058_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock)
: nes_nrom_device(mconfig, NES_KS7058, tag, owner, clock)
{
}
-nes_ks7022_device::nes_ks7022_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
+nes_ks7022_device::nes_ks7022_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock)
: nes_nrom_device(mconfig, NES_KS7022, tag, owner, clock), m_latch(0)
{
}
-nes_ks7032_device::nes_ks7032_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock)
- : nes_nrom_device(mconfig, type, tag, owner, clock), m_latch(0), m_irq_count(0), m_irq_enable(0), irq_timer(nullptr)
+nes_ks7032_device::nes_ks7032_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, u32 clock)
+ : nes_nrom_device(mconfig, type, tag, owner, clock), m_latch(0), m_irq_count(0), m_irq_count_latch(0), m_irq_enable(0), irq_timer(nullptr)
{
}
-nes_ks7032_device::nes_ks7032_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
+nes_ks7032_device::nes_ks7032_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock)
: nes_ks7032_device(mconfig, NES_KS7032, tag, owner, clock)
{
}
-nes_ks202_device::nes_ks202_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
+nes_ks202_device::nes_ks202_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock)
: nes_ks7032_device(mconfig, NES_KS202, tag, owner, clock)
{
}
-nes_ks7017_device::nes_ks7017_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
+nes_ks7016_device::nes_ks7016_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, u32 clock, u8 a15_flip)
+ : nes_nrom_device(mconfig, type, tag, owner, clock), m_latch(0), m_a15_flip(a15_flip)
+{
+}
+
+nes_ks7016_device::nes_ks7016_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock)
+ : nes_ks7016_device(mconfig, NES_KS7016, tag, owner, clock, 0x00)
+{
+}
+
+nes_ks7016b_device::nes_ks7016b_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock)
+ : nes_ks7016_device(mconfig, NES_KS7016B, tag, owner, clock, 0x04)
+{
+}
+
+nes_ks7017_device::nes_ks7017_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock)
: nes_nrom_device(mconfig, NES_KS7017, tag, owner, clock), m_latch(0), m_irq_count(0), m_irq_status(0), m_irq_enable(0), irq_timer(nullptr)
{
}
-nes_ks7012_device::nes_ks7012_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
+nes_ks7021a_device::nes_ks7021a_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock)
+ : nes_nrom_device(mconfig, NES_KS7021A, tag, owner, clock)
+{
+}
+
+nes_ks7010_device::nes_ks7010_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock)
+ : nes_nrom_device(mconfig, NES_KS7010, tag, owner, clock), m_latch(0)
+{
+}
+
+nes_ks7012_device::nes_ks7012_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock)
: nes_nrom_device(mconfig, NES_KS7012, tag, owner, clock)
{
}
-nes_ks7013b_device::nes_ks7013b_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
+nes_ks7013b_device::nes_ks7013b_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock)
: nes_nrom_device(mconfig, NES_KS7013B, tag, owner, clock)
{
}
-nes_ks7031_device::nes_ks7031_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
+nes_ks7030_device::nes_ks7030_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock)
+ : nes_nrom_device(mconfig, NES_KS7030, tag, owner, clock)
+{
+}
+
+nes_ks7031_device::nes_ks7031_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock)
: nes_nrom_device(mconfig, NES_KS7031, tag, owner, clock)
{
}
-nes_ks7016_device::nes_ks7016_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
- : nes_nrom_device(mconfig, NES_KS7016, tag, owner, clock)
+nes_ks7037_device::nes_ks7037_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock)
+ : nes_nrom_device(mconfig, NES_KS7037, tag, owner, clock), m_reg(0)
{
}
-nes_ks7037_device::nes_ks7037_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
- : nes_nrom_device(mconfig, NES_KS7037, tag, owner, clock)
+nes_ks7057_device::nes_ks7057_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock)
+ : nes_nrom_device(mconfig, NES_KS7057, tag, owner, clock)
{
}
-void nes_ks7058_device::device_start()
+void nes_ks106c_device::device_start()
{
common_start();
+ save_item(NAME(m_latch));
}
-void nes_ks7058_device::pcb_reset()
+void nes_ks106c_device::pcb_reset()
{
- m_chr_source = m_vrom_chunks ? CHRROM : CHRRAM;
- prg32(0);
- chr8(0, m_chr_source);
+ prg32(m_latch);
+ chr8(m_latch, CHRROM);
+ set_nt_mirroring(BIT(m_latch, 0) ? PPU_MIRROR_VERT : PPU_MIRROR_HORZ);
+ m_latch = (m_latch + 1) & 0x03;
}
void nes_ks7022_device::device_start()
@@ -136,7 +178,6 @@ void nes_ks7022_device::device_start()
void nes_ks7022_device::pcb_reset()
{
- m_chr_source = m_vrom_chunks ? CHRROM : CHRRAM;
prg16_89ab(0);
prg16_cdef(m_prg_chunks - 1);
chr8(0, m_chr_source);
@@ -147,33 +188,49 @@ void nes_ks7022_device::pcb_reset()
void nes_ks7032_device::device_start()
{
common_start();
- irq_timer = timer_alloc(TIMER_IRQ);
+ irq_timer = timer_alloc(FUNC(nes_ks7032_device::irq_timer_tick), this);
irq_timer->adjust(attotime::zero, 0, clocks_to_attotime(1));
save_item(NAME(m_latch));
save_item(NAME(m_irq_enable));
save_item(NAME(m_irq_count));
+ save_item(NAME(m_irq_count_latch));
save_item(NAME(m_reg));
}
void nes_ks7032_device::pcb_reset()
{
- m_chr_source = m_vrom_chunks ? CHRROM : CHRRAM;
- prg16_89ab(0);
- prg16_cdef(m_prg_chunks - 1);
- chr8(0, m_chr_source);
-
m_latch = 0;
m_irq_enable = 0;
m_irq_count = 0;
- memset(m_reg, 0, sizeof(m_reg));
+ m_irq_count_latch = 0;
+ std::fill(std::begin(m_reg), std::end(m_reg), 0x00);
+
prg_update();
+ prg8_ef((m_prg_chunks << 1) - 1);
+ chr8(0, m_chr_source);
+}
+
+void nes_ks7016_device::device_start()
+{
+ common_start();
+ save_item(NAME(m_latch));
+}
+
+void nes_ks7016_device::pcb_reset()
+{
+ prg8_89(0x0c ^ m_a15_flip);
+ prg8_ab(0x0d ^ m_a15_flip);
+ prg8_cd(0x0e ^ m_a15_flip);
+ prg8_ef(0x0f ^ m_a15_flip);
+
+ m_latch = 0;
}
void nes_ks7017_device::device_start()
{
common_start();
- irq_timer = timer_alloc(TIMER_IRQ);
+ irq_timer = timer_alloc(FUNC(nes_ks7017_device::irq_timer_tick), this);
irq_timer->adjust(attotime::zero, 0, clocks_to_attotime(1));
save_item(NAME(m_latch));
@@ -184,10 +241,8 @@ void nes_ks7017_device::device_start()
void nes_ks7017_device::pcb_reset()
{
- m_chr_source = m_vrom_chunks ? CHRROM : CHRRAM;
prg16_89ab(0);
prg16_cdef(2);
- chr8(0, m_chr_source);
m_latch = 0;
m_irq_enable = 0;
@@ -195,82 +250,93 @@ void nes_ks7017_device::pcb_reset()
m_irq_status = 0;
}
-void nes_ks7012_device::device_start()
+void nes_ks7021a_device::pcb_reset()
+{
+ prg16_89ab(0);
+ prg16_cdef(m_prg_chunks - 1);
+ chr8(0, CHRROM);
+}
+
+void nes_ks7010_device::device_start()
{
common_start();
+ save_item(NAME(m_latch));
}
-void nes_ks7012_device::pcb_reset()
+void nes_ks7010_device::pcb_reset()
{
- m_chr_source = m_vrom_chunks ? CHRROM : CHRRAM;
- prg32(0xff);
- chr8(0, m_chr_source);
+ prg16_89ab(0x05); // all upper banks are fixed
+ prg16_cdef(0x03);
+ chr8(0, CHRROM);
+
+ m_latch = 0;
}
-void nes_ks7013b_device::device_start()
+void nes_ks7012_device::pcb_reset()
{
- common_start();
+ prg32((m_prg_chunks >> 1) - 1);
}
void nes_ks7013b_device::pcb_reset()
{
- m_chr_source = m_vrom_chunks ? CHRROM : CHRRAM;
prg16_89ab(0);
prg16_cdef(m_prg_chunks - 1);
- chr8(0, m_chr_source);
}
-void nes_ks7031_device::device_start()
+void nes_ks7030_device::device_start()
{
common_start();
save_item(NAME(m_reg));
}
-void nes_ks7031_device::pcb_reset()
+void nes_ks7030_device::pcb_reset()
{
- prg32(0); // not really used...
- chr8(0, CHRRAM);
+ prg32((m_prg_chunks >> 1) - 1); // not really used...
- m_reg[0] = 0;
- m_reg[1] = 0;
- m_reg[2] = 0;
- m_reg[3] = 0;
+ m_reg[0] = m_reg[1] = 0;
}
-void nes_ks7016_device::device_start()
+void nes_ks7031_device::device_start()
{
common_start();
save_item(NAME(m_reg));
}
-void nes_ks7016_device::pcb_reset()
+void nes_ks7031_device::pcb_reset()
{
- prg8_89(0xc);
- prg8_ab(0xd);
- prg8_cd(0xe);
- prg8_ef(0xf);
- chr8(0, CHRRAM);
+ prg32(0); // not really used...
- m_reg = 4;
+ std::fill(std::begin(m_reg), std::end(m_reg), 0x00);
}
void nes_ks7037_device::device_start()
{
common_start();
- save_item(NAME(m_latch));
save_item(NAME(m_reg));
}
void nes_ks7037_device::pcb_reset()
{
prg8_89(0);
- prg8_ab(0x1e);
+ prg8_ab(0x0e);
prg8_cd(0);
- prg8_ef(0x1f);
- chr8(0, CHRRAM);
+ prg8_ef(0x0f);
- memset(m_reg, 0, sizeof(m_reg));
- m_latch = 0;
+ m_reg = 0;
+}
+
+void nes_ks7057_device::device_start()
+{
+ common_start();
+ save_item(NAME(m_reg));
+}
+
+void nes_ks7057_device::pcb_reset()
+{
+ prg8_ab(0x0d);
+ prg16_cdef(0x07);
+
+ std::fill(std::begin(m_reg), std::end(m_reg), 0x00);
}
@@ -281,6 +347,21 @@ void nes_ks7037_device::pcb_reset()
/*-------------------------------------------------
+ Kaiser Board KS106C
+
+ Games: 4 in 1
+
+ No need to use handlers. At reset the banks change
+ and so does the game.
+
+ NES 2.0: mapper 352
+
+ In MAME: Supported.
+
+ -------------------------------------------------*/
+
+/*-------------------------------------------------
+
Kaiser Board KS7058
Games: Tui Do Woo Ma Jeung
@@ -291,13 +372,13 @@ void nes_ks7037_device::pcb_reset()
iNES: mapper 171
- In MESS: Supported.
+ In MAME: Supported.
-------------------------------------------------*/
-void nes_ks7058_device::write_h(offs_t offset, uint8_t data)
+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)
{
@@ -318,24 +399,23 @@ void nes_ks7058_device::write_h(offs_t offset, uint8_t data)
iNES: mapper 175
- In MESS: Supported?
+ In MAME: Supported?
-------------------------------------------------*/
-void nes_ks7022_device::write_h(offs_t offset, uint8_t 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);
-
- if (offset == 0x2000)
+ else if (offset == 0x2000)
m_latch = data & 0x0f;
}
-uint8_t nes_ks7022_device::read_h(offs_t offset)
+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)
{
@@ -351,32 +431,27 @@ uint8_t nes_ks7022_device::read_h(offs_t offset)
Kaiser Board KS7032
- Games: A few FDS conversions like Bubble Bobble
- or SMB2
+ Games: FDS conversions of Bubble Bobble, SMB2,
+ and Exciting Soccer
- iNES:
+ These boards have a KS202 ASIC that provide both
+ banking and a cycle-based IRQ similar to the VRC3.
- TODO: available dumps do not seem to use WRAM...
- yet m_reg[4] should switch WRAM bank... investigate!
+ iNES: mapper 142
- In MESS: Supported?
+ In MAME: Supported.
-------------------------------------------------*/
-void nes_ks7032_device::device_timer(emu_timer &timer, device_timer_id id, int param, void *ptr)
+TIMER_CALLBACK_MEMBER(nes_ks7032_device::irq_timer_tick)
{
- if (id == TIMER_IRQ)
+ if (m_irq_enable)
{
- if (m_irq_enable)
+ if (++m_irq_count == 0)
{
- if (m_irq_count == 0xffff)
- {
- m_irq_enable = 0;
- m_irq_count = 0;
- hold_irq_line();
- }
- else
- m_irq_count++;
+ set_irq_line(ASSERT_LINE);
+ m_irq_enable = 0;
+ m_irq_count = m_irq_count_latch;
}
}
}
@@ -388,85 +463,137 @@ void nes_ks7032_device::prg_update()
prg8_cd(m_reg[3]);
}
-void nes_ks7032_device::ks7032_write(offs_t offset, uint8_t data)
+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)
{
case 0x0000:
- m_irq_count = (m_irq_count & 0xfff0) | (data & 0x0f);
- break;
case 0x1000:
- m_irq_count = (m_irq_count & 0xff0f) | ((data & 0x0f) << 4);
- break;
case 0x2000:
- m_irq_count = (m_irq_count & 0xf0ff) | ((data & 0x0f) << 8);
- break;
case 0x3000:
- m_irq_count = (m_irq_count & 0x0fff) | ((data & 0x0f) << 12);
+ {
+ int shift = 4 * BIT(offset, 12, 2);
+ m_irq_count_latch &= ~(0x000f << shift);
+ m_irq_count_latch |= (data & 0x0f) << shift;
break;
+ }
case 0x4000:
- m_irq_enable = 1;
+ m_irq_enable = BIT(data, 1);
+ if (m_irq_enable)
+ m_irq_count = m_irq_count_latch;
+ set_irq_line(CLEAR_LINE);
+ break;
+ case 0x5000:
+ set_irq_line(CLEAR_LINE);
break;
case 0x6000:
m_latch = data & 0x07;
break;
case 0x7000:
- m_reg[m_latch] = data;
+ m_reg[m_latch] = (m_reg[m_latch] & 0xf0) | (data & 0x0f);
prg_update();
break;
}
}
-uint8_t nes_ks7032_device::read_m(offs_t offset)
+u8 nes_ks7032_device::read_m(offs_t offset)
{
- LOG_MMC(("ks7032 read_m, offset: %04x\n", offset));
- return m_prg[((m_reg[4] * 0x2000) + (offset & 0x1fff)) & (m_prg_size - 1)];
+ LOG("ks7032 read_m, offset: %04x\n", offset);
+ return m_prg[(m_reg[4] * 0x2000 + offset) & (m_prg_size - 1)];
}
/*-------------------------------------------------
- Kaiser Board KS202
+ Kaiser SMB3 Board with KS202
Games: Super Mario Bros. 3 (Pirate, Alt)
- iNES:
+ A chip, PAL16L8ANC, provides the extra bits overlaid
+ at 0xf000-0xffff. Writes go to both it and the KS202.
- In MESS: Supported?
+ iNES: mapper 56
- -------------------------------------------------*/
+ In MAME: Supported.
+
+ TODO: This device needs renaming of some sort. KS202
+ is a chip found on some Kaiser PCBs that actually
+ provides the functionality implemented above in the
+ KS7032 PCB. It's not clear what SMB3's PCB is.
+ -------------------------------------------------*/
-void nes_ks202_device::write_h(offs_t offset, uint8_t data)
+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);
- switch (offset & 0x7000)
+ if (offset >= 0x7000)
{
- case 0x7000:
- m_reg[m_latch] = data;
- prg_update();
- switch (offset & 0xc00)
- {
- case 0x800:
- set_nt_mirroring(BIT(data, 0) ? PPU_MIRROR_VERT : PPU_MIRROR_HORZ);
- break;
- case 0xc00:
- chr1_x(offset & 0x07, data, CHRROM);
- break;
- }
- break;
- default:
- ks7032_write(offset, data);
- break;
+ switch (offset & 0xc00)
+ {
+ case 0x000:
+ if ((offset & 3) == 3)
+ prg8_ef((data & 0x10) | 0x0f);
+ else
+ {
+ int reg = (offset & 3) + 1;
+ m_reg[reg] = (m_reg[reg] & 0x0f) | (data & 0x10);
+ }
+ break;
+ case 0x800:
+ set_nt_mirroring(BIT(data, 0) ? PPU_MIRROR_VERT : PPU_MIRROR_HORZ);
+ break;
+ case 0xc00:
+ chr1_x(offset & 0x07, data & 0x7f, CHRROM);
+ break;
+ }
}
+
+ nes_ks7032_device::write_h(offset, data);
}
-uint8_t nes_ks202_device::read_m(offs_t offset)
+u8 nes_ks202_device::read_m(offs_t offset)
{
- LOG_MMC(("ks202 read_m, offset: %04x\n", offset));
- return m_prgram[offset & 0x1fff];
+ return device_nes_cart_interface::read_m(offset);
+}
+
+/*-------------------------------------------------
+
+ Kaiser Boards KS7016, KS7016B
+
+ Games: Exciting Basket, Meikyuu Jiin Dababa FDS Conversions
+
+ These two variants have fixed upper 32K PRG and switchable
+ 8K PRG at 0x6000-0x7fff. The only difference appears to be
+ a flipped bit in the bank numbers. KS7016 puts banks 0x0c
+ through 0x0f in the upper PRG; KS7016B uses 0x08 to 0x0b.
+ For the switchable 8K PRG the latched bank # patterns are:
+
+ KS7016: 0 1 2 3 4 5 6 7 8 9 A B 8 9 A B
+ KS7016B: 0 1 2 3 4 5 6 7 C D E F C D E F
+
+ (NB: only KS7016B has been verified against PCB, KS7016 is a surmise.)
+
+ NES 2.0: mapper 306, mapper 549
+
+ In MAME: Supported.
+
+ -------------------------------------------------*/
+
+u8 nes_ks7016_device::read_m(offs_t 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("ks7016 write_h, offset: %04x, data: %02x\n", offset, data);
+
+ m_latch = BIT(offset, 2, 4);
+ if (m_latch & 0x08)
+ m_latch = (m_latch & 0x0b) | m_a15_flip;
}
/*-------------------------------------------------
@@ -475,74 +602,147 @@ uint8_t nes_ks202_device::read_m(offs_t offset)
Games: Almana no Kiseki FDS conversion
- iNES:
+ NES 2.0: mapper 303
- In MESS: Supported.
+ In MAME: Supported.
-------------------------------------------------*/
-void nes_ks7017_device::device_timer(emu_timer &timer, device_timer_id id, int param, void *ptr)
+TIMER_CALLBACK_MEMBER(nes_ks7017_device::irq_timer_tick)
{
- if (id == TIMER_IRQ)
+ if (m_irq_enable)
{
- if (m_irq_enable)
+ if (--m_irq_count == 0)
{
- if (!m_irq_count)
- {
- hold_irq_line();
- m_irq_enable = 0;
- m_irq_status |= 0x01;
- }
- else
- m_irq_count--;
+ set_irq_line(ASSERT_LINE);
+ m_irq_enable = 0;
+ m_irq_status |= 0x01;
}
}
}
-void nes_ks7017_device::write_l(offs_t offset, uint8_t data)
+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;
-
- if (offset >= 0xa00 && offset < 0xb00)
- m_latch = ((offset >> 2) & 0x03) | ((offset >> 4) & 0x04);
-
- if (offset >= 0x1100 && offset < 0x1200)
- prg16_89ab(m_latch);
+ switch (offset & 0x1f00)
+ {
+ case 0x0a00:
+ m_latch = bitswap<3>(offset, 6, 3, 2);
+ break;
+ case 0x1100:
+ prg16_89ab(m_latch);
+ break;
+ }
}
-void nes_ks7017_device::write_ex(offs_t offset, uint8_t data)
+void nes_ks7017_device::write_ex(offs_t offset, u8 data)
{
- LOG_MMC(("ks7017 write_ex, offset: %04x, data: %02x\n", offset, data));
- offset += 0x20;
+ LOG("ks7017 write_ex, offset: %04x, data: %02x\n", offset, data);
- if (offset == 0x0020) // 0x4020
- m_irq_count = (m_irq_count & 0xff00) | data;
-
- if (offset == 0x0021) // 0x4021
+ offset += 0x4020;
+ switch (offset)
{
- m_irq_count = (m_irq_count & 0x00ff) | (data << 8);
- m_irq_enable = 1;
+ case 0x4020:
+ m_irq_count = (m_irq_count & 0xff00) | data;
+ break;
+ case 0x4021:
+ m_irq_count = (m_irq_count & 0x00ff) | (data << 8);
+ m_irq_enable = 1;
+ break;
+ case 0x4025:
+ set_nt_mirroring(BIT(data, 3) ? PPU_MIRROR_HORZ : PPU_MIRROR_VERT);
+ break;
}
-
- if (offset == 0x0025) // 0x4025
- set_nt_mirroring(BIT(data, 3) ? PPU_MIRROR_HORZ : PPU_MIRROR_VERT);
}
-uint8_t nes_ks7017_device::read_ex(offs_t offset)
+u8 nes_ks7017_device::read_ex(offs_t offset)
{
- LOG_MMC(("ks7017 read_ex, offset: %04x\n", offset));
- offset += 0x20;
+ LOG("ks7017 read_ex, offset: %04x\n", offset);
- if (offset == 0x0030) // 0x4030
+ offset += 0x4020;
+ if (offset == 0x4030)
{
int temp = m_irq_status;
m_irq_status &= ~0x01;
+ set_irq_line(CLEAR_LINE);
return temp;
}
- return get_open_bus(); // open bus
+ return get_open_bus();
+}
+
+/*-------------------------------------------------
+
+ Kaiser Board KS7021A
+
+ Games: GetsuFumaDen
+
+ This board has a 16K fixed PRG bank at 0xc000 and
+ a swappable 16K PRG bank at 0x8000. CHR banks are
+ selectable by 1K page.
+
+ NES 2.0: mapper 525
+
+ In MAME: Supported.
+
+ -------------------------------------------------*/
+
+void nes_ks7021a_device::write_h(offs_t offset, u8 data)
+{
+ LOG("ks7021a write_h, offset: %04x, data: %02x\n", offset, data);
+
+ switch (offset & 0x7000)
+ {
+ case 0x0000:
+ prg16_89ab(BIT(data, 1, 3));
+ break;
+ case 0x1000:
+ set_nt_mirroring(BIT(data, 0) ? PPU_MIRROR_HORZ : PPU_MIRROR_VERT);
+ break;
+ case 0x3000:
+ chr1_x(offset & 0x07, data & 0x7f, CHRROM);
+ break;
+ }
+}
+
+/*-------------------------------------------------
+
+ Kaiser Board KS7010
+
+ Games: Akumajo Dracula FDS Conversion
+
+ This board has fixed PRG banks in 0x8000-0xffff.
+ 0x6000-0x7fff is an 8K swappable PRG bank. This bank
+ and the CHR bank are BOTH set by the same latch.
+ Moreover, the latch is set by READING certain
+ addresses and the exact mask is still unknown...
+
+ NES 2.0: mapper 554
+
+ In MAME: Supported.
+
+ -------------------------------------------------*/
+
+u8 nes_ks7010_device::read_m(offs_t offset)
+{
+ 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)
+{
+ 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);
+ }
+
+ u8 data = hi_access_rom(offset);
+ LOGMASKED(LOG_HIFREQ, "ks7010 read_h, offset: %04x, data: %02x\n", offset, data);
+ return data;
}
/*-------------------------------------------------
@@ -551,15 +751,15 @@ uint8_t nes_ks7017_device::read_ex(offs_t offset)
Games: Zanac FDS Conversion
- iNES:
+ NES 2.0: mapper 346
- In MESS: Not working
+ In MAME: Supported.
-------------------------------------------------*/
-void nes_ks7012_device::write_h(offs_t offset, uint8_t data)
+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);
@@ -567,101 +767,138 @@ void nes_ks7012_device::write_h(offs_t offset, uint8_t data)
prg32(1);
}
-
/*-------------------------------------------------
Kaiser Board KS7013B
- Games: Highway Star FDS Conversion
+ Games: Highway Star bootleg
- iNES:
+ NES 2.0: mapper 312
- In MESS: Supported.
+ In MAME: Supported.
-------------------------------------------------*/
-void nes_ks7013b_device::write_m(offs_t offset, uint8_t 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, uint8_t 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);
}
-
/*-------------------------------------------------
- Kaiser Board KS7031
+ Kaiser Board KS7030
- Games: Dracula II FDS Conversion
+ Games: Doki Doki Panic (FDS conversion)
- This board is quite weird. It handles 2K PRG chunks
- and the chip contains chunks in reverse order, so
- that the first 2K are actually loaded at the top
- of the 0x8000-0xffff region. Main bank is fixed, while
- the 8K mapped at 0x6000-0x7fff varies with reg writes.
+ This board has a complicated memory layout. The last
+ 32k of the mask ROM is fixed into 0x8000-0xffff, but
+ 8k of WRAM and 8k of bankable PRG (in two 4k banks)
+ are adjacent and overlaid. The ranges are as follows.
+
+ WRAM: PRG:
+ - 3k, 0x6000-0x6bff - 1k, 0x6c00-0x6fff (reg 1, last 1k)
+ - 2k, 0xb800-0xbfff - 4k, 0x7000-0x7fff (reg 0)
+ - 3k, 0xcc00-0xd7ff - 3k, 0xc000-0xcc00 (reg 1, initial 3k)
- TODO: understand how SRAM is handled...
+ The two registers latch part of the address in writes
+ to 0x8000-0x8fff and 0x9000-0x9fff respectively.
- iNES:
+ NES 2.0: mapper 347
- In MESS: Supported.
+ In MAME: Supported.
-------------------------------------------------*/
-uint8_t nes_ks7031_device::read_m(offs_t offset)
+u8 nes_ks7030_device::read_m(offs_t offset)
{
-// LOG_MMC(("ks7031 read_m, offset: %04x\n", offset));
- return m_prg[(m_reg[(offset >> 11) & 3] * 0x0800) + (offset & 0x7ff)];
+ 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
+ return m_prg[m_reg[1] * 0x1000 + offset];
+ else // 4k PRG
+ return m_prg[0x10000 + m_reg[0] * 0x1000 + (offset & 0x0fff)];
}
-uint8_t nes_ks7031_device::read_h(offs_t offset)
+void nes_ks7030_device::write_m(offs_t offset, u8 data)
{
- // here the first 32K are accessed, but in 16x2K blocks loaded in reverse order
- int accessed_2k = (offset >> 11) & 0x0f;
- return m_prg[((0x0f - accessed_2k) * 0x0800) + (offset & 0x7ff)];
+ LOG("ks7030 write_m, offset: %04x\n", offset);
+ if (offset < 0x0c00) // first 3k of WRAM
+ m_prgram[offset] = data;
}
-void nes_ks7031_device::write_h(offs_t offset, uint8_t data)
+u8 nes_ks7030_device::read_h(offs_t offset)
{
- LOG_MMC(("ks7031 write_h, offset: %04x, data: %02x\n", offset, data));
- m_reg[(offset >> 11) & 3] = data & 0x3f;
+ 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
+ return m_prgram[offset - 0x2c00];
+ else if (offset < 0x4c00) // first 3k of 4k PRG bank
+ return m_prg[m_reg[1] * 0x1000 + (offset & 0x0fff)];
+ else // last 3k of WRAM
+ return m_prgram[offset - 0x3800];
}
-
+void nes_ks7030_device::write_h(offs_t offset, u8 data)
+{
+ LOG("ks7030 write_h, offset: %04x\n", offset);
+ if (offset < 0x1000)
+ {
+ set_nt_mirroring(BIT(offset, 3) ? PPU_MIRROR_HORZ : PPU_MIRROR_VERT);
+ m_reg[0] = offset & 0x07;
+ }
+ else if (offset < 0x2000)
+ m_reg[1] = offset & 0x0f;
+ else if (offset >= 0x3800 && offset < 0x4000) // middle 2k of WRAM
+ m_prgram[offset - 0x2c00] = data;
+ else if (offset >= 0x4c00 && offset < 0x5800) // last 3k of WRAM
+ m_prgram[offset - 0x3800] = data;
+}
/*-------------------------------------------------
- Kaiser Board KS7016
+ Kaiser Board KS7031
- Games: Exciting Basket FDS Conversion
+ Games: Dracula II FDS Conversion
+
+ This board is quite weird. It handles 2K PRG chunks
+ and the chip contains chunks in reverse order, so
+ that the first 2K are actually loaded at the top
+ of the 0x8000-0xffff region. Main bank is fixed, while
+ the 8K mapped at 0x6000-0x7fff varies with reg writes.
- iNES:
+ NES 2.0: mapper 305
- In MESS: Unsupported.
+ In MAME: Supported.
-------------------------------------------------*/
-uint8_t nes_ks7016_device::read_m(offs_t offset)
+u8 nes_ks7031_device::read_m(offs_t offset)
{
-// LOG_MMC(("ks7016 read_m, offset: %04x\n", offset));
- return m_prg[((m_reg * 0x2000) + (offset & 0x1fff)) & (m_prg_size - 1)];
+ LOGMASKED(LOG_HIFREQ, "ks7031 read_m, offset: %04x\n", offset);
+ return m_prg[(m_reg[BIT(offset, 11, 2)] * 0x0800) + (offset & 0x7ff)];
}
-void nes_ks7016_device::write_h(offs_t offset, uint8_t data)
+u8 nes_ks7031_device::read_h(offs_t offset)
{
- LOG_MMC(("ks7016 write_h, offset: %04x, data: %02x\n", offset, data));
- uint8_t mask = offset & 0x30;
- if ((offset & 0x5943) == 0x5943)
- m_reg = (mask == 0x30) ? 0xb : (((offset >> 2) & 0x0f) << 1);
- if ((offset & 0x5943) == 0x5903)
- m_reg = (mask != 0x30) ? 0xb : (((offset >> 2) & 0x0f) << 1);
+ // here the first 32K are accessed, but in 16x2K blocks loaded in reverse order
+ int accessed_2k = BIT(~offset, 11, 4);
+ return m_prg[accessed_2k * 0x0800 + (offset & 0x7ff)];
}
+void nes_ks7031_device::write_h(offs_t offset, u8 data)
+{
+ LOG("ks7031 write_h, offset: %04x, data: %02x\n", offset, data);
+ m_reg[BIT(offset, 11, 2)] = data & 0x3f;
+}
/*-------------------------------------------------
@@ -674,43 +911,31 @@ void nes_ks7016_device::write_h(offs_t offset, uint8_t data)
but with WRAM split between 0x6000-0x6fff
and 0xb000-0xbfff.
- iNES:
+ NES 2.0: mapper 307
- In MESS: Unsupported.
+ In MAME: Supported.
-------------------------------------------------*/
-void nes_ks7037_device::update_prg()
-{
- prg8_89(m_reg[6]);
- prg8_ab(0xfe);
- prg8_cd(m_reg[7]);
- prg8_ef(0xff);
- set_nt_page(0, CIRAM, m_reg[2] & 1, 1);
- set_nt_page(1, CIRAM, m_reg[3] & 1, 1);
- set_nt_page(2, CIRAM, m_reg[4] & 1, 1);
- set_nt_page(3, CIRAM, m_reg[5] & 1, 1);
-}
-
-uint8_t nes_ks7037_device::read_m(offs_t offset)
+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 & 0x0fff];
+ return m_prgram[offset];
else
- return m_prg[(0x1e * 0x1000) + (offset & 0x0fff)];
+ return m_prg[0x0f * 0x1000 + (offset & 0x0fff)]; // 4k PRG bank 15 is fixed
}
-void nes_ks7037_device::write_m(offs_t offset, uint8_t data)
+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 & 0x0fff] = data;
+ m_prgram[offset] = data;
}
-uint8_t nes_ks7037_device::read_h(offs_t offset)
+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)];
@@ -718,23 +943,74 @@ uint8_t nes_ks7037_device::read_h(offs_t offset)
return hi_access_rom(offset);
}
-void nes_ks7037_device::write_h(offs_t offset, uint8_t data)
+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);
- if (offset >= 0x3000 && offset < 0x4000)
- m_prgram[0x1000 + (offset & 0x0fff)] = data;
- else
+ switch (offset & 0x7000)
{
- switch (offset & 0x6001)
- {
- case 0x0000:
- m_latch = data & 7;
- break;
- case 0x0001:
- m_reg[m_latch] = data;
- update_prg();
- break;
- }
+ case 0x0000:
+ case 0x1000:
+ if (!(offset & 1))
+ m_reg = data & 7;
+ else if (m_reg >= 6)
+ prg8_x((m_reg & 1) << 1, data);
+ else if (m_reg >= 2)
+ set_nt_page(bitswap<2>(m_reg, 0, 2), CIRAM, data & 1, 1);
+ break;
+ case 0x3000:
+ m_prgram[0x1000 + (offset & 0x0fff)] = data;
+ break;
+ }
+}
+
+/*-------------------------------------------------
+
+ Kaiser Board KS7057
+
+ Games: Gyruss
+
+ This PCB has fixed banks after 0xa000 and 8x2K
+ swappable banks in 0x6000-0x9fff. Pairs of nibble
+ registers (we store joined as bytes) control the banks,
+ with $B000/$B001, $B002/$B003, $C000/$C001, $C002/$C003
+ selecting 4 banks in 0x8000-0x9fff, and $D000/$D001,
+ $D002/$D003, $E000/$E001, $E002/$E003 selecting the
+ remaining 4 banks in 0x6000-0x7fff.
+
+ NES 2.0: mapper 302
+
+ In MAME: Supported.
+
+ -------------------------------------------------*/
+
+u8 nes_ks7057_device::read_m(offs_t 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)
+{
+ 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)];
+
+ return hi_access_rom(offset);
+}
+
+void nes_ks7057_device::write_h(offs_t offset, u8 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);
+ else if (offset >= 0x3000 && offset < 0x6004)
+ {
+ u8 reg = bitswap<4>(offset, 14, 13, 12, 1) - 6;
+ if (BIT(offset, 0))
+ m_reg[reg] = (m_reg[reg] & 0x0f) | ((data & 0x03) << 4);
+ else
+ m_reg[reg] = (m_reg[reg] & 0xf0) | (data & 0x0f);
}
}
diff --git a/src/devices/bus/nes/kaiser.h b/src/devices/bus/nes/kaiser.h
index e0e31658cdb..6eb8d90161f 100644
--- a/src/devices/bus/nes/kaiser.h
+++ b/src/devices/bus/nes/kaiser.h
@@ -8,21 +8,34 @@
#include "nxrom.h"
-// ======================> nes_ks7058_device
+// ======================> nes_ks106c_device
-class nes_ks7058_device : public nes_nrom_device
+class nes_ks106c_device : public nes_nrom_device
{
public:
// construction/destruction
- nes_ks7058_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
-
- virtual void write_h(offs_t offset, uint8_t data) override;
+ nes_ks106c_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock);
virtual void pcb_reset() override;
protected:
// device-level overrides
- virtual void device_start() override;
+ virtual void device_start() override ATTR_COLD;
+
+private:
+ u8 m_latch;
+};
+
+
+// ======================> nes_ks7058_device
+
+class nes_ks7058_device : public nes_nrom_device
+{
+public:
+ // construction/destruction
+ nes_ks7058_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock);
+
+ virtual void write_h(offs_t offset, u8 data) override;
};
@@ -32,19 +45,19 @@ class nes_ks7022_device : public nes_nrom_device
{
public:
// construction/destruction
- nes_ks7022_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
+ nes_ks7022_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock);
- virtual uint8_t read_h(offs_t offset) override;
- virtual void write_h(offs_t offset, uint8_t data) override;
+ virtual u8 read_h(offs_t offset) override;
+ virtual void write_h(offs_t offset, u8 data) override;
virtual void pcb_reset() override;
protected:
// device-level overrides
- virtual void device_start() override;
+ virtual void device_start() override ATTR_COLD;
private:
- uint8_t m_latch;
+ u8 m_latch;
};
@@ -54,30 +67,31 @@ class nes_ks7032_device : public nes_nrom_device
{
public:
// construction/destruction
- nes_ks7032_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
+ nes_ks7032_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock);
- virtual uint8_t read_m(offs_t offset) override;
- void ks7032_write(offs_t offset, uint8_t data);
- virtual void write_h(offs_t offset, uint8_t data) override { ks7032_write(offset, data); }
+ virtual u8 read_m(offs_t offset) override;
+ virtual void write_h(offs_t offset, u8 data) override;
virtual void pcb_reset() override;
protected:
- nes_ks7032_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock);
+ // construction/destruction
+ nes_ks7032_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_timer(emu_timer &timer, device_timer_id id, int param, void *ptr) override;
+ virtual void device_start() override ATTR_COLD;
- void prg_update();
+ TIMER_CALLBACK_MEMBER(irq_timer_tick);
- uint8_t m_latch;
- uint8_t m_reg[8];
+ u8 m_reg[8];
+
+private:
+ void prg_update();
+ u8 m_latch;
- uint16_t m_irq_count;
- int m_irq_enable;
+ u16 m_irq_count, m_irq_count_latch;
+ u8 m_irq_enable;
- static const device_timer_id TIMER_IRQ = 0;
emu_timer *irq_timer;
};
@@ -88,11 +102,46 @@ class nes_ks202_device : public nes_ks7032_device
{
public:
// construction/destruction
- nes_ks202_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
+ nes_ks202_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock);
+
+ virtual u8 read_m(offs_t offset) override;
+ virtual void write_h(offs_t offset, u8 data) override;
+};
+
+
+// ======================> nes_ks7016_device
+
+class nes_ks7016_device : public nes_nrom_device
+{
+public:
+ // construction/destruction
+ nes_ks7016_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock);
+
+ virtual u8 read_m(offs_t offset) override;
+ virtual void write_h(offs_t offset, u8 data) override;
+
+ virtual void pcb_reset() override;
+
+protected:
+ // construction/destruction
+ nes_ks7016_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, u32 clock, u8 a15_flip);
// device-level overrides
- virtual uint8_t read_m(offs_t offset) override;
- virtual void write_h(offs_t offset, uint8_t data) override;
+ virtual void device_start() override ATTR_COLD;
+
+private:
+ u8 m_latch;
+ const u8 m_a15_flip;
+};
+
+
+// ======================> nes_ks7016b_device
+
+class nes_ks7016b_device : public nes_ks7016_device
+{
+public:
+ // construction/destruction
+ nes_ks7016b_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock);
};
@@ -102,64 +151,117 @@ class nes_ks7017_device : public nes_nrom_device
{
public:
// construction/destruction
- nes_ks7017_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
+ nes_ks7017_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock);
- virtual uint8_t read_ex(offs_t offset) override;
- virtual void write_ex(offs_t offset, uint8_t data) override;
- virtual void write_l(offs_t offset, uint8_t data) override;
+ virtual u8 read_ex(offs_t offset) override;
+ virtual void write_ex(offs_t offset, u8 data) override;
+ virtual void write_l(offs_t offset, u8 data) override;
virtual void pcb_reset() override;
protected:
// device-level overrides
- virtual void device_start() override;
- virtual void device_timer(emu_timer &timer, device_timer_id id, int param, void *ptr) override;
+ virtual void device_start() override ATTR_COLD;
+
+ TIMER_CALLBACK_MEMBER(irq_timer_tick);
private:
- uint8_t m_latch;
+ u8 m_latch;
- uint16_t m_irq_count;
- uint8_t m_irq_status;
- int m_irq_enable;
+ u16 m_irq_count;
+ u8 m_irq_status;
+ u8 m_irq_enable;
- static const device_timer_id TIMER_IRQ = 0;
emu_timer *irq_timer;
};
-// ======================> nes_ks7012_device
+// ======================> nes_ks7021a_device
-class nes_ks7012_device : public nes_nrom_device
+class nes_ks7021a_device : public nes_nrom_device
+{
+public:
+ // construction/destruction
+ nes_ks7021a_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock);
+
+ virtual void write_h(offs_t offset, u8 data) override;
+
+ virtual void pcb_reset() override;
+};
+
+
+// ======================> nes_ks7010_device
+
+class nes_ks7010_device : public nes_nrom_device
{
public:
// construction/destruction
- nes_ks7012_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
+ nes_ks7010_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock);
- virtual void write_h(offs_t offset, uint8_t data) override;
+ virtual u8 read_m(offs_t offset) override;
+ virtual u8 read_h(offs_t offset) override;
virtual void pcb_reset() override;
protected:
// device-level overrides
- virtual void device_start() override;
+ virtual void device_start() override ATTR_COLD;
+
+private:
+ u8 m_latch;
+};
+
+
+// ======================> nes_ks7012_device
+
+class nes_ks7012_device : public nes_nrom_device
+{
+public:
+ // construction/destruction
+ nes_ks7012_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock);
+
+ virtual void write_h(offs_t offset, u8 data) override;
+
+ virtual void pcb_reset() override;
};
+
// ======================> nes_ks7013b_device
class nes_ks7013b_device : public nes_nrom_device
{
public:
// construction/destruction
- nes_ks7013b_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
+ nes_ks7013b_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock);
- virtual void write_m(offs_t offset, uint8_t data) override;
- virtual void write_h(offs_t offset, uint8_t data) override;
+ virtual void write_m(offs_t offset, u8 data) override;
+ virtual void write_h(offs_t offset, u8 data) override;
+
+ virtual void pcb_reset() override;
+};
+
+
+// ======================> nes_ks7030_device
+
+class nes_ks7030_device : public nes_nrom_device
+{
+public:
+ // construction/destruction
+ nes_ks7030_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock);
+
+ virtual u8 read_m(offs_t offset) override;
+ virtual u8 read_h(offs_t offset) override;
+ virtual void write_m(offs_t offset, u8 data) override;
+ virtual void write_h(offs_t offset, u8 data) override;
virtual void pcb_reset() override;
protected:
// device-level overrides
- virtual void device_start() override;
+ virtual void device_start() override ATTR_COLD;
+
+private:
+ u8 m_reg[2];
};
@@ -169,80 +271,86 @@ class nes_ks7031_device : public nes_nrom_device
{
public:
// construction/destruction
- nes_ks7031_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
+ nes_ks7031_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock);
- virtual uint8_t read_m(offs_t offset) override;
- virtual uint8_t read_h(offs_t offset) override;
- virtual void write_h(offs_t offset, uint8_t data) override;
+ virtual u8 read_m(offs_t offset) override;
+ virtual u8 read_h(offs_t offset) override;
+ virtual void write_h(offs_t offset, u8 data) override;
virtual void pcb_reset() override;
protected:
// device-level overrides
- virtual void device_start() override;
+ virtual void device_start() override ATTR_COLD;
private:
- uint8_t m_reg[4];
+ u8 m_reg[4];
};
-// ======================> nes_ks7016_device
+// ======================> nes_ks7037_device
-class nes_ks7016_device : public nes_nrom_device
+class nes_ks7037_device : public nes_nrom_device
{
public:
// construction/destruction
- nes_ks7016_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
+ nes_ks7037_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock);
- virtual uint8_t read_m(offs_t offset) override;
- virtual void write_h(offs_t offset, uint8_t data) override;
+ virtual u8 read_m(offs_t offset) override;
+ virtual u8 read_h(offs_t offset) override;
+ virtual void write_m(offs_t offset, u8 data) override;
+ virtual void write_h(offs_t offset, u8 data) override;
virtual void pcb_reset() override;
protected:
// device-level overrides
- virtual void device_start() override;
+ virtual void device_start() override ATTR_COLD;
private:
- uint8_t m_reg;
+ u8 m_reg;
};
-// ======================> nes_ks7037_device
-class nes_ks7037_device : public nes_nrom_device
+// ======================> nes_ks7057_device
+
+class nes_ks7057_device : public nes_nrom_device
{
public:
// construction/destruction
- nes_ks7037_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
+ nes_ks7057_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock);
- virtual uint8_t read_m(offs_t offset) override;
- virtual uint8_t read_h(offs_t offset) override;
- virtual void write_m(offs_t offset, uint8_t data) override;
- virtual void write_h(offs_t offset, uint8_t data) override;
+ virtual u8 read_m(offs_t offset) override;
+ virtual u8 read_h(offs_t offset) override;
+ virtual void write_h(offs_t offset, u8 data) override;
virtual void pcb_reset() override;
protected:
// device-level overrides
- virtual void device_start() override;
+ virtual void device_start() override ATTR_COLD;
private:
- void update_prg();
- uint8_t m_latch;
- uint8_t m_reg[8];
+ u8 m_reg[8];
};
// device type definition
-DECLARE_DEVICE_TYPE(NES_KS7058, nes_ks7058_device)
-DECLARE_DEVICE_TYPE(NES_KS7022, nes_ks7022_device)
-DECLARE_DEVICE_TYPE(NES_KS7032, nes_ks7032_device)
+DECLARE_DEVICE_TYPE(NES_KS106C, nes_ks106c_device)
DECLARE_DEVICE_TYPE(NES_KS202, nes_ks202_device)
-DECLARE_DEVICE_TYPE(NES_KS7017, nes_ks7017_device)
+DECLARE_DEVICE_TYPE(NES_KS7010, nes_ks7010_device)
DECLARE_DEVICE_TYPE(NES_KS7012, nes_ks7012_device)
DECLARE_DEVICE_TYPE(NES_KS7013B, nes_ks7013b_device)
-DECLARE_DEVICE_TYPE(NES_KS7031, nes_ks7031_device)
DECLARE_DEVICE_TYPE(NES_KS7016, nes_ks7016_device)
+DECLARE_DEVICE_TYPE(NES_KS7016B, nes_ks7016b_device)
+DECLARE_DEVICE_TYPE(NES_KS7017, nes_ks7017_device)
+DECLARE_DEVICE_TYPE(NES_KS7021A, nes_ks7021a_device)
+DECLARE_DEVICE_TYPE(NES_KS7022, nes_ks7022_device)
+DECLARE_DEVICE_TYPE(NES_KS7030, nes_ks7030_device)
+DECLARE_DEVICE_TYPE(NES_KS7031, nes_ks7031_device)
+DECLARE_DEVICE_TYPE(NES_KS7032, nes_ks7032_device)
DECLARE_DEVICE_TYPE(NES_KS7037, nes_ks7037_device)
+DECLARE_DEVICE_TYPE(NES_KS7057, nes_ks7057_device)
+DECLARE_DEVICE_TYPE(NES_KS7058, nes_ks7058_device)
#endif // MAME_BUS_NES_KAISER_H
diff --git a/src/devices/bus/nes/karastudio.cpp b/src/devices/bus/nes/karastudio.cpp
index fc98a658213..0cca5acbe11 100644
--- a/src/devices/bus/nes/karastudio.cpp
+++ b/src/devices/bus/nes/karastudio.cpp
@@ -32,12 +32,11 @@
#include "karastudio.h"
#ifdef NES_PCB_DEBUG
-#define VERBOSE 1
+#define VERBOSE (LOG_GENERAL)
#else
#define VERBOSE 0
#endif
-
-#define LOG_MMC(x) do { if (VERBOSE) logerror x; } while (0)
+#include "logmacro.h"
//-----------------------------------------
@@ -51,7 +50,7 @@
//-------------------------------------------------
kstudio_cart_interface::kstudio_cart_interface(const machine_config &mconfig, device_t &device)
- : device_slot_card_interface(mconfig, device)
+ : device_interface(device, "kstudiocart")
, m_rom(nullptr), m_bank(0)
{
}
@@ -73,8 +72,8 @@ DEFINE_DEVICE_TYPE(NES_KSEXPANSION_SLOT, nes_kstudio_slot_device, "nes_ks_slot",
nes_kstudio_slot_device::nes_kstudio_slot_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
: device_t(mconfig, NES_KSEXPANSION_SLOT, tag, owner, clock)
- , device_image_interface(mconfig, *this)
- , device_slot_interface(mconfig, *this)
+ , device_cartrom_image_interface(mconfig, *this)
+ , device_single_card_slot_interface<kstudio_cart_interface>(mconfig, *this)
, m_cart(nullptr)
{
}
@@ -86,44 +85,43 @@ nes_kstudio_slot_device::~nes_kstudio_slot_device()
void nes_kstudio_slot_device::device_start()
{
- m_cart = dynamic_cast<kstudio_cart_interface *>(get_card_device());
+ m_cart = get_card_device();
}
uint8_t nes_kstudio_slot_device::read(offs_t offset)
{
if (m_cart)
return m_cart->read(offset);
-
- return 0xff;
+ else
+ 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());
}
@@ -199,7 +197,6 @@ void nes_karaokestudio_device::device_start()
void nes_karaokestudio_device::pcb_reset()
{
- m_chr_source = m_vrom_chunks ? CHRROM : CHRRAM;
prg16_89ab(0);
prg16_cdef((m_prg_chunks - 1) ^ 0x08);
chr8(0, m_chr_source);
@@ -227,13 +224,13 @@ void nes_karaokestudio_device::pcb_reset()
uint8_t nes_karaokestudio_device::read_m(offs_t offset)
{
- LOG_MMC(("karaoke studio read_m, offset: %04x\n", offset));
+ LOG("karaoke studio read_m, offset: %04x\n", offset);
return m_mic_ipt->read();
}
uint8_t nes_karaokestudio_device::read_h(offs_t offset)
{
- LOG_MMC(("karaoke studio read_h, offset: %04x\n", offset));
+ LOG("karaoke studio 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);
@@ -249,7 +246,7 @@ uint8_t nes_karaokestudio_device::read_h(offs_t offset)
void nes_karaokestudio_device::write_h(offs_t offset, uint8_t data)
{
- LOG_MMC(("karaoke studio write_h, offset: %04x, data: %02x\n", offset, data));
+ LOG("karaoke studio write_h, offset: %04x, data: %02x\n", offset, data);
// bit3 1 = M ROM (main unit), 0=E ROM (expansion)
// HACK(?): currently it is not clear how the unit acknowledges the presence of the expansion
// cart (when expansion is present, code keeps switching both from the expansion rom and from
diff --git a/src/devices/bus/nes/karastudio.h b/src/devices/bus/nes/karastudio.h
index fcb481f046e..b76f8b7f035 100644
--- a/src/devices/bus/nes/karastudio.h
+++ b/src/devices/bus/nes/karastudio.h
@@ -6,7 +6,7 @@
#pragma once
#include "nxrom.h"
-#include "softlist_dev.h"
+#include "imagedev/cartrom.h"
//-----------------------------------------
@@ -17,7 +17,7 @@
// ======================> kstudio_cart_interface
-class kstudio_cart_interface : public device_slot_card_interface
+class kstudio_cart_interface : public device_interface
{
public:
// construction/destruction
@@ -43,8 +43,8 @@ protected:
class nes_karaokestudio_device;
class nes_kstudio_slot_device : public device_t,
- public device_image_interface,
- public device_slot_interface
+ public device_cartrom_image_interface,
+ public device_single_card_slot_interface<kstudio_cart_interface>
{
friend class nes_karaokestudio_device;
public:
@@ -62,30 +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;
- virtual const software_list_loader &get_software_list_loader() const override { return rom_software_list_loader::instance(); }
+ // device_image_interface implementation
+ virtual std::pair<std::error_condition, std::string> call_load() override;
- virtual iodevice_t image_type() const override { return IO_CARTSLOT; }
- virtual bool is_readable() const override { return 1; }
- virtual bool is_writeable() const override { return 0; }
- virtual bool is_creatable() const override { return 0; }
- virtual bool must_be_loaded() const override { return 0; }
- virtual bool is_reset_on_load() const override { return 1; }
- virtual const char *image_interface() const override { return "ks_cart"; }
- virtual const char *file_extensions() const override { return "bin"; }
+ 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
- virtual void device_start() override;
+ // device_t implementation
+ virtual void device_start() override ATTR_COLD;
- kstudio_cart_interface* m_cart;
+ kstudio_cart_interface *m_cart;
};
// device type definition
@@ -107,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
- virtual void device_start() override;
- virtual void device_reset() override;
+ // device_t implementation
+ virtual void device_start() override ATTR_COLD;
+ virtual void device_reset() override ATTR_COLD;
+ virtual const tiny_rom_entry *device_rom_region() const override ATTR_COLD;
};
// device type definition
@@ -143,10 +136,10 @@ public:
protected:
// device-level overrides
- virtual void device_start() override;
+ virtual void device_start() override ATTR_COLD;
- virtual ioport_constructor device_input_ports() const override;
- virtual void device_add_mconfig(machine_config &config) override;
+ virtual ioport_constructor device_input_ports() const override ATTR_COLD;
+ virtual void device_add_mconfig(machine_config &config) override ATTR_COLD;
private:
int m_exp_active;
diff --git a/src/devices/bus/nes/konami.cpp b/src/devices/bus/nes/konami.cpp
index b936b06b48a..27362d28c8c 100644
--- a/src/devices/bus/nes/konami.cpp
+++ b/src/devices/bus/nes/konami.cpp
@@ -16,11 +16,6 @@
* Konami VRC-6 [mapper 24,26]
* Konami VRC-7 [mapper 85]
-
- TODO:
- - improve IRQ (CPU mode not currently emulated)
- - add VRC-6 sound features
-
***********************************************************************************************************/
@@ -29,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
@@ -50,37 +46,42 @@ DEFINE_DEVICE_TYPE(NES_VRC6, nes_konami_vrc6_device, "nes_vrc6", "NES Cart Konam
DEFINE_DEVICE_TYPE(NES_VRC7, nes_konami_vrc7_device, "nes_vrc7", "NES Cart Konami VRC-7 PCB")
-nes_konami_vrc1_device::nes_konami_vrc1_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
+nes_konami_vrc1_device::nes_konami_vrc1_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock)
: nes_nrom_device(mconfig, NES_VRC1, tag, owner, clock)
{
}
-nes_konami_vrc2_device::nes_konami_vrc2_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
- : nes_nrom_device(mconfig, NES_VRC2, tag, owner, clock), m_latch(0)
+nes_konami_vrc2_device::nes_konami_vrc2_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, u32 clock)
+ : nes_nrom_device(mconfig, type, tag, owner, clock), m_latch(0)
+{
+}
+
+nes_konami_vrc2_device::nes_konami_vrc2_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock)
+ : nes_konami_vrc2_device(mconfig, NES_VRC2, tag, owner, clock)
{
}
-nes_konami_vrc3_device::nes_konami_vrc3_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
+nes_konami_vrc3_device::nes_konami_vrc3_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock)
: nes_nrom_device(mconfig, NES_VRC3, tag, owner, clock), m_irq_count(0), m_irq_count_latch(0), m_irq_enable(0), m_irq_enable_latch(0), m_irq_mode(0), irq_timer(nullptr)
{
}
-nes_konami_vrc4_device::nes_konami_vrc4_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock)
- : nes_nrom_device(mconfig, type, tag, owner, clock), m_latch(0), m_mmc_prg_bank(0), m_irq_count(0), m_irq_count_latch(0), m_irq_enable(0), m_irq_enable_latch(0), m_irq_mode(0), m_irq_prescale(0), irq_timer(nullptr)
+nes_konami_vrc4_device::nes_konami_vrc4_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, u32 clock)
+ : nes_nrom_device(mconfig, type, tag, owner, clock), m_prg_flip(0), m_wram_enable(0), m_irq_count(0), m_irq_count_latch(0), m_irq_enable(0), m_irq_enable_latch(0), m_irq_mode(0), m_irq_prescale(0), irq_timer(nullptr)
{
}
-nes_konami_vrc4_device::nes_konami_vrc4_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
+nes_konami_vrc4_device::nes_konami_vrc4_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock)
: nes_konami_vrc4_device(mconfig, NES_VRC4, tag, owner, clock)
{
}
-nes_konami_vrc6_device::nes_konami_vrc6_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
+nes_konami_vrc6_device::nes_konami_vrc6_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock)
: nes_konami_vrc4_device(mconfig, NES_VRC6, tag, owner, clock), m_vrc6snd(*this, "vrc6snd")
{
}
-nes_konami_vrc7_device::nes_konami_vrc7_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
+nes_konami_vrc7_device::nes_konami_vrc7_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock)
: nes_konami_vrc4_device(mconfig, NES_VRC7, tag, owner, clock), m_vrc7snd(*this, "vrc7snd")
{
}
@@ -95,12 +96,11 @@ void nes_konami_vrc1_device::device_start()
void nes_konami_vrc1_device::pcb_reset()
{
- m_chr_source = m_vrom_chunks ? CHRROM : CHRRAM;
prg16_89ab(0);
prg16_cdef(m_prg_chunks - 1);
chr8(0, m_chr_source);
- memset(m_mmc_vrom_bank, 0, sizeof(m_mmc_vrom_bank));
+ m_mmc_vrom_bank[0] = m_mmc_vrom_bank[1] = 0;
}
void nes_konami_vrc2_device::device_start()
@@ -112,19 +112,18 @@ void nes_konami_vrc2_device::device_start()
void nes_konami_vrc2_device::pcb_reset()
{
- m_chr_source = m_vrom_chunks ? CHRROM : CHRRAM;
prg16_89ab(0);
prg16_cdef(m_prg_chunks - 1);
chr8(0, m_chr_source);
m_latch = 0;
- memset(m_mmc_vrom_bank, 0, sizeof(m_mmc_vrom_bank));
+ std::fill(std::begin(m_mmc_vrom_bank), std::end(m_mmc_vrom_bank), 0x00);
}
void nes_konami_vrc3_device::device_start()
{
common_start();
- irq_timer = timer_alloc(TIMER_IRQ);
+ irq_timer = timer_alloc(FUNC(nes_konami_vrc3_device::irq_timer_tick), this);
irq_timer->adjust(attotime::zero, 0, clocks_to_attotime(1));
save_item(NAME(m_irq_mode));
@@ -136,7 +135,6 @@ void nes_konami_vrc3_device::device_start()
void nes_konami_vrc3_device::pcb_reset()
{
- m_chr_source = m_vrom_chunks ? CHRROM : CHRRAM;
prg16_89ab(0);
prg16_cdef(m_prg_chunks - 1);
chr8(0, m_chr_source);
@@ -148,11 +146,10 @@ void nes_konami_vrc3_device::pcb_reset()
m_irq_count_latch = 0;
}
-
void nes_konami_vrc4_device::device_start()
{
common_start();
- irq_timer = timer_alloc(TIMER_IRQ);
+ irq_timer = timer_alloc(FUNC(nes_konami_vrc4_device::irq_timer_tick), this);
irq_timer->adjust(attotime::zero, 0, clocks_to_attotime(1));
save_item(NAME(m_irq_mode));
@@ -161,64 +158,36 @@ void nes_konami_vrc4_device::device_start()
save_item(NAME(m_irq_enable_latch));
save_item(NAME(m_irq_count));
save_item(NAME(m_irq_count_latch));
- save_item(NAME(m_latch));
+ save_item(NAME(m_prg_flip));
+ save_item(NAME(m_wram_enable));
save_item(NAME(m_mmc_prg_bank));
save_item(NAME(m_mmc_vrom_bank));
}
void nes_konami_vrc4_device::pcb_reset()
{
- m_chr_source = m_vrom_chunks ? CHRROM : CHRRAM;
- prg16_89ab(0);
- prg16_cdef(m_prg_chunks - 1);
- chr8(0, m_chr_source);
-
m_irq_mode = 0;
- m_irq_prescale = 341;
+ m_irq_prescale = 0;
m_irq_enable = 0;
m_irq_enable_latch = 0;
m_irq_count = 0;
m_irq_count_latch = 0;
- m_latch = 0;
- m_mmc_prg_bank = 0;
- memset(m_mmc_vrom_bank, 0, sizeof(m_mmc_vrom_bank));
-}
+ m_prg_flip = 0;
+ m_wram_enable = 0;
+ m_mmc_prg_bank[0] = 0;
+ m_mmc_prg_bank[1] = 0;
+ set_prg();
-void nes_konami_vrc6_device::device_start()
-{
- nes_konami_vrc4_device::device_start();
-}
-
-void nes_konami_vrc7_device::device_start()
-{
- common_start();
- irq_timer = timer_alloc(TIMER_IRQ);
- irq_timer->adjust(attotime::zero, 0, clocks_to_attotime(1));
-
- save_item(NAME(m_irq_mode));
- save_item(NAME(m_irq_prescale));
- save_item(NAME(m_irq_enable));
- save_item(NAME(m_irq_enable_latch));
- save_item(NAME(m_irq_count));
- save_item(NAME(m_irq_count_latch));
+ for (int i = 0; i < 8; i++)
+ m_mmc_vrom_bank[i] = i;
+ set_chr();
}
void nes_konami_vrc7_device::pcb_reset()
{
- m_chr_source = m_vrom_chunks ? CHRROM : CHRRAM;
- prg8_89(0);
- prg8_ab(0);
- prg8_cd(0);
- prg8_ef(0xff);
- chr8(0, m_chr_source);
-
- m_irq_mode = 0;
- m_irq_prescale = 341;
- m_irq_enable = 0;
- m_irq_enable_latch = 0;
- m_irq_count = 0;
- m_irq_count_latch = 0;
+ nes_konami_vrc4_device::pcb_reset();
+ prg32((m_prg_chunks >> 1) - 1);
}
@@ -235,29 +204,25 @@ void nes_konami_vrc7_device::pcb_reset()
iNES: mapper 75
- In MESS: Supported.
+ In MAME: Supported.
-------------------------------------------------*/
-void nes_konami_vrc1_device::write_h(offs_t offset, uint8_t data)
+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)
{
case 0x0000:
- prg8_89(data);
- break;
case 0x2000:
- prg8_ab(data);
- break;
case 0x4000:
- prg8_cd(data);
+ prg8_x(BIT(offset, 13, 2), data & 0x0f);
break;
case 0x1000:
- set_nt_mirroring((data & 0x01) ? PPU_MIRROR_HORZ : PPU_MIRROR_VERT);
- m_mmc_vrom_bank[0] = (m_mmc_vrom_bank[0] & 0x0f) | ((data & 0x02) << 3);
- m_mmc_vrom_bank[1] = (m_mmc_vrom_bank[1] & 0x0f) | ((data & 0x04) << 2);
+ set_nt_mirroring(data & 1 ? PPU_MIRROR_HORZ : PPU_MIRROR_VERT);
+ m_mmc_vrom_bank[0] = (m_mmc_vrom_bank[0] & 0x0f) | BIT(data, 1) << 4;
+ m_mmc_vrom_bank[1] = (m_mmc_vrom_bank[1] & 0x0f) | BIT(data, 2) << 4;
chr4_0(m_mmc_vrom_bank[0], CHRROM);
chr4_4(m_mmc_vrom_bank[1], CHRROM);
break;
@@ -276,69 +241,59 @@ void nes_konami_vrc1_device::write_h(offs_t offset, uint8_t data)
Konami VRC-2
- In MESS: Supported.
+ In MAME: Supported.
-------------------------------------------------*/
-uint8_t nes_konami_vrc2_device::read_m(offs_t offset)
+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())
- return m_battery[offset & (m_battery.size() - 1)];
- else if (!m_prgram.empty())
- return m_prgram[offset & (m_prgram.size() - 1)];
- else // sort of protection? it returns open bus in $7000-$7fff and (open bus & 0xfe) | m_latch in $6000-$6fff
- return (offset < 0x1000) ? ((get_open_bus() & 0xfe) | (m_latch & 1)) : get_open_bus();
+ if (!m_battery.empty() || !m_prgram.empty())
+ return device_nes_cart_interface::read_m(offset);
+ else // VRC2 was planned with EEPROM support; the non-working feature behaves as a vestigial 1-bit latch in $6000-$6fff on certain boards (contraj, ggoemon2 depend on this)
+ return (offset < 0x1000) ? (get_open_bus() & 0xfe) | (m_latch & 1) : get_open_bus();
}
-void nes_konami_vrc2_device::write_m(offs_t offset, uint8_t data)
+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_battery[offset & (m_battery.size() - 1)] = data;
- else if (!m_prgram.empty())
- m_prgram[offset & (m_prgram.size() - 1)] = data;
+ if (!m_battery.empty() || !m_prgram.empty())
+ device_nes_cart_interface::write_m(offset, data);
else if (offset < 0x1000)
m_latch = data;
}
-void nes_konami_vrc2_device::write_h(offs_t offset, uint8_t data)
+void nes_konami_vrc2_device::write_h(offs_t offset, u8 data)
{
- uint8_t bank, shift, mask;
- uint16_t add_lines = ((offset << (9 - m_vrc_ls_prg_a)) & 0x200) | ((offset << (8 - m_vrc_ls_prg_b)) & 0x100);
- 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);
switch (offset & 0x7000)
{
case 0x0000:
- prg8_89(data);
- break;
case 0x2000:
- prg8_ab(data);
+ prg8_x(BIT(offset, 13), data);
break;
case 0x1000:
- switch (data & 0x03)
- {
- case 0x00: set_nt_mirroring(PPU_MIRROR_VERT); break;
- case 0x01: set_nt_mirroring(PPU_MIRROR_HORZ); break;
- case 0x02: set_nt_mirroring(PPU_MIRROR_LOW); break;
- case 0x03: set_nt_mirroring(PPU_MIRROR_HIGH); break;
- }
+ set_nt_mirroring(data & 1 ? PPU_MIRROR_HORZ : PPU_MIRROR_VERT);
break;
case 0x3000:
case 0x4000:
case 0x5000:
case 0x6000:
- bank = ((offset & 0x7000) - 0x3000) / 0x0800 + BIT(add_lines, 9);
- shift = BIT(add_lines, 8) * 4;
- mask = (0xf0 >> shift);
- m_mmc_vrom_bank[bank] = (m_mmc_vrom_bank[bank] & mask) | (((data >> m_vrc_ls_chr) & 0x0f) << shift);
- chr1_x(bank, m_mmc_vrom_bank[bank], CHRROM);
+ {
+ int bank = 2 * (BIT(offset, 12, 3) - 3) + BIT(addr_lines, 1);
+ int shift = BIT(addr_lines, 0) * 4;
+ int mask = 0x0f << shift;
+ m_mmc_vrom_bank[bank] = (m_mmc_vrom_bank[bank] & ~mask) | (((data >> m_vrc_ls_chr) << shift) & mask);
+ chr1_x(bank, m_mmc_vrom_bank[bank], m_chr_source);
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;
}
}
@@ -351,63 +306,47 @@ void nes_konami_vrc2_device::write_h(offs_t offset, uint8_t data)
iNES: mapper 73
- In MESS: Supported.
+ In MAME: Supported.
-------------------------------------------------*/
-void nes_konami_vrc3_device::device_timer(emu_timer &timer, device_timer_id id, int param, void *ptr)
+TIMER_CALLBACK_MEMBER(nes_konami_vrc3_device::irq_timer_tick)
{
- if (id == TIMER_IRQ)
+ if (m_irq_enable)
{
- if (m_irq_enable)
+ u16 mask = m_irq_mode ? 0x00ff : 0xffff; // 8 or 16 bit mode?
+
+ // upper byte only incremented and reloaded in 16-bit mode
+ m_irq_count = (m_irq_count & ~mask) | ((m_irq_count + 1) & mask);
+ if (!(m_irq_count & mask))
{
- if (m_irq_mode) // 8bits mode
- {
- if ((m_irq_count & 0x00ff) == 0xff)
- {
- set_irq_line(ASSERT_LINE);
- m_irq_count = m_irq_count_latch;
- }
- else
- m_irq_count = (m_irq_count & 0xff00) | ((m_irq_count & 0x00ff) + 1);
- }
- else // 16bits mode
- {
- if (m_irq_count == 0xffff)
- {
- set_irq_line(ASSERT_LINE);
- m_irq_count = m_irq_count_latch;
- }
- else
- m_irq_count++;
- }
+ set_irq_line(ASSERT_LINE);
+ m_irq_count = (m_irq_count & ~mask) | (m_irq_count_latch & mask);
}
}
}
-void nes_konami_vrc3_device::write_h(offs_t offset, uint8_t data)
+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)
{
case 0x0000:
- m_irq_count_latch = (m_irq_count_latch & 0xfff0) | ((data & 0x0f) << 0);
- break;
case 0x1000:
- m_irq_count_latch = (m_irq_count_latch & 0xff0f) | ((data & 0x0f) << 4);
- break;
case 0x2000:
- m_irq_count_latch = (m_irq_count_latch & 0xf0ff) | ((data & 0x0f) << 8);
- break;
case 0x3000:
- m_irq_count_latch = (m_irq_count_latch & 0x0fff) | ((data & 0x0f) << 12);
+ {
+ int shift = 4 * BIT(offset, 12, 2);
+ m_irq_count_latch &= ~(0x000f << shift);
+ m_irq_count_latch |= (data & 0x0f) << shift;
break;
+ }
case 0x4000:
m_irq_mode = data & 0x04;
m_irq_enable = data & 0x02;
m_irq_enable_latch = data & 0x01;
- if (data & 0x02)
+ if (m_irq_enable)
m_irq_count = m_irq_count_latch;
set_irq_line(CLEAR_LINE);
break;
@@ -416,10 +355,10 @@ void nes_konami_vrc3_device::write_h(offs_t offset, uint8_t data)
set_irq_line(CLEAR_LINE);
break;
case 0x7000:
- prg16_89ab(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;
}
}
@@ -428,7 +367,7 @@ void nes_konami_vrc3_device::write_h(offs_t offset, uint8_t data)
Konami VRC-4
- In MESS: Supported
+ In MAME: Supported
-------------------------------------------------*/
@@ -443,113 +382,142 @@ void nes_konami_vrc4_device::irq_tick()
m_irq_count++;
}
-void nes_konami_vrc4_device::device_timer(emu_timer &timer, device_timer_id id, int param, void *ptr)
+TIMER_CALLBACK_MEMBER(nes_konami_vrc4_device::irq_timer_tick)
{
- if (id == TIMER_IRQ)
+ if (m_irq_enable)
{
- if (m_irq_enable)
+ if (m_irq_mode) // cycle mode
+ irq_tick();
+ else // scanline mode
{
- if (m_irq_mode) // cycle mode
- irq_tick();
- else // scanline mode
+ // A prescaler divides the passing CPU cycles by 114, 114, then 113 (and repeats that order).
+ // This approximates 113+2/3 CPU cycles, which is one NTSC scanline.
+ // Since this is a CPU-based IRQ, though, it is triggered also during non visible scanlines...
+ m_irq_prescale -= 3;
+
+ if (m_irq_prescale <= 0)
{
- // A prescaler divides the passing CPU cycles by 114, 114, then 113 (and repeats that order).
- // This approximates 113+2/3 CPU cycles, which is one NTSC scanline.
- // Since this is a CPU-based IRQ, though, it is triggered also during non visible scanlines...
- if (m_irq_prescale < 3)
- {
- m_irq_prescale += 341;
- irq_tick();
- }
-
- m_irq_prescale -= 3;
+ m_irq_prescale += 341;
+ irq_tick();
}
}
}
}
-void nes_konami_vrc4_device::set_prg()
+void nes_konami_vrc4_device::irq_ack_w()
{
- if (m_latch & 0x02)
+ m_irq_enable = m_irq_enable_latch;
+ set_irq_line(CLEAR_LINE);
+}
+
+void nes_konami_vrc4_device::irq_ctrl_w(u8 data)
+{
+ m_irq_mode = data & 0x04;
+ m_irq_enable = data & 0x02;
+ m_irq_enable_latch = data & 0x01;
+ if (m_irq_enable)
{
- prg8_89(0xfe);
- prg8_cd(m_mmc_prg_bank);
+ m_irq_count = m_irq_count_latch;
+ m_irq_prescale = 341;
}
- else
+ set_irq_line(CLEAR_LINE);
+}
+
+void nes_konami_vrc4_device::set_mirror(u8 data)
+{
+ switch (data & 0x03)
{
- prg8_89(m_mmc_prg_bank);
- prg8_cd(0xfe);
+ case 0x00: set_nt_mirroring(PPU_MIRROR_VERT); break;
+ case 0x01: set_nt_mirroring(PPU_MIRROR_HORZ); break;
+ case 0x02: set_nt_mirroring(PPU_MIRROR_LOW); break;
+ case 0x03: set_nt_mirroring(PPU_MIRROR_HIGH); break;
}
}
-void nes_konami_vrc4_device::write_h(offs_t offset, uint8_t data)
+void nes_konami_vrc4_device::set_prg(int prg_base, int prg_mask)
{
- uint8_t bank, shift, mask;
- uint16_t add_lines = ((offset << (9 - m_vrc_ls_prg_a)) & 0x200) | ((offset << (8 - m_vrc_ls_prg_b)) & 0x100);
- LOG_MMC(("VRC-4 write_h, offset: %04x, data: %02x\n", offset, data));
+ prg8_x(0 ^ m_prg_flip, prg_base | (m_mmc_prg_bank[0] & prg_mask));
+ prg8_x(1, prg_base | (m_mmc_prg_bank[1] & prg_mask));
+ prg8_x(2 ^ m_prg_flip, prg_base | (prg_mask & ~1));
+ prg8_x(3, prg_base | prg_mask);
+}
+
+void nes_konami_vrc4_device::set_chr(int chr_base, int chr_mask)
+{
+ for (int i = 0; i < 8; i++)
+ chr1_x(i, chr_base | (m_mmc_vrom_bank[i] & chr_mask), m_chr_source);
+}
+
+u8 nes_konami_vrc4_device::read_m(offs_t offset)
+{
+ LOG("VRC-4 read_m, offset: %04x\n", offset);
+
+ if (m_wram_enable)
+ return device_nes_cart_interface::read_m(offset);
+ else
+ return get_open_bus();
+}
+
+void nes_konami_vrc4_device::write_m(offs_t offset, u8 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);
+}
+
+void nes_konami_vrc4_device::write_h(offs_t offset, u8 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);
switch (offset & 0x7000)
{
case 0x0000:
- m_mmc_prg_bank = data;
- set_prg();
- break;
case 0x2000:
- prg8_ab(data);
+ m_mmc_prg_bank[BIT(offset, 13)] = data;
+ set_prg();
break;
case 0x1000:
- if (add_lines & 0x200)
+ if (BIT(addr_lines, 1))
{
- m_latch = data & 0x02;
+ m_wram_enable = data & 0x01;
+ m_prg_flip = data & 0x02;
set_prg();
}
else
- {
- switch (data & 0x03)
- {
- case 0x00: set_nt_mirroring(PPU_MIRROR_VERT); break;
- case 0x01: set_nt_mirroring(PPU_MIRROR_HORZ); break;
- case 0x02: set_nt_mirroring(PPU_MIRROR_LOW); break;
- case 0x03: set_nt_mirroring(PPU_MIRROR_HIGH); break;
- }
- }
+ set_mirror(data);
break;
case 0x3000:
case 0x4000:
case 0x5000:
case 0x6000:
- bank = ((offset & 0x7000) - 0x3000) / 0x0800 + BIT(add_lines, 9);
- shift = BIT(add_lines, 8) * 4;
- mask = (0xf0 >> shift);
- m_mmc_vrom_bank[bank] = (m_mmc_vrom_bank[bank] & mask) | ((data & 0x0f) << shift);
- chr1_x(bank, m_mmc_vrom_bank[bank], CHRROM);
+ {
+ int bank = 2 * (BIT(offset, 12, 3) - 3) + BIT(addr_lines, 1);
+ int shift = BIT(addr_lines, 0) * 4;
+ int mask = shift ? 0x1f0 : 0x0f;
+ m_mmc_vrom_bank[bank] = (m_mmc_vrom_bank[bank] & ~mask) | ((data << shift) & mask);
+ set_chr();
break;
+ }
case 0x7000:
- switch (add_lines)
+ switch (addr_lines)
{
- case 0x000:
+ case 0:
m_irq_count_latch = (m_irq_count_latch & 0xf0) | (data & 0x0f);
break;
- case 0x100:
- m_irq_count_latch = (m_irq_count_latch & 0x0f) | ((data & 0x0f) << 4);
+ case 1:
+ m_irq_count_latch = (m_irq_count_latch & 0x0f) | (data & 0x0f) << 4;
break;
- case 0x200:
- m_irq_mode = data & 0x04;
- m_irq_enable = data & 0x02;
- m_irq_enable_latch = data & 0x01;
- if (data & 0x02)
- m_irq_count = m_irq_count_latch;
- set_irq_line(CLEAR_LINE);
+ case 2:
+ irq_ctrl_w(data);
break;
- case 0x300:
- m_irq_enable = m_irq_enable_latch;
- set_irq_line(CLEAR_LINE);
+ case 3:
+ irq_ack_w();
break;
}
break;
- default:
- logerror("VRC-4 write_h uncaught write, addr: %04x value: %02x\n", ((offset & 0x7000) | add_lines) + 0x8000, data);
- break;
}
}
@@ -557,76 +525,64 @@ void nes_konami_vrc4_device::write_h(offs_t offset, uint8_t data)
Konami VRC-6
- In MESS: Supported. It also uses konami_irq (there are IRQ
+ In MAME: Supported. It also uses konami_irq (there are IRQ
issues though: see Akumajou Densetsu intro).
+ TODO: Implement other CHR modes not used by any of
+ the three released VRC6 games?
+
-------------------------------------------------*/
-void nes_konami_vrc6_device::write_h(offs_t offset, uint8_t data)
+void nes_konami_vrc6_device::write_h(offs_t offset, u8 data)
{
- uint8_t bank;
- uint16_t add_lines = ((offset << (9 - m_vrc_ls_prg_a)) & 0x200) | ((offset << (8 - m_vrc_ls_prg_b)) & 0x100);
- 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);
switch (offset & 0x7000)
{
case 0x0000:
- prg16_89ab(data);
+ prg16_89ab(data & 0x0f);
break;
case 0x4000:
- prg8_cd(data);
+ prg8_cd(data & 0x1f);
break;
case 0x1000: // pulse 1 & global control
- m_vrc6snd->write(add_lines>>8, data);
+ m_vrc6snd->write(addr_lines, data);
break;
case 0x2000: // pulse 2
- m_vrc6snd->write((add_lines>>8) | 0x100, data);
+ m_vrc6snd->write(addr_lines | 0x100, data);
break;
case 0x3000:
- if (add_lines == 0x300)
+ if (addr_lines == 3)
{
- switch (data & 0x0c)
- {
- case 0x00: set_nt_mirroring(PPU_MIRROR_VERT); break;
- case 0x04: set_nt_mirroring(PPU_MIRROR_HORZ); break;
- case 0x08: set_nt_mirroring(PPU_MIRROR_LOW); break;
- case 0x0c: set_nt_mirroring(PPU_MIRROR_HIGH); break;
- }
+ set_mirror(data >> 2);
+ m_wram_enable = BIT(data, 7);
}
else // saw
- m_vrc6snd->write((add_lines>>8) | 0x200, data);
+ m_vrc6snd->write(addr_lines | 0x200, data);
break;
case 0x5000:
case 0x6000:
- bank = ((offset & 0x7000) - 0x5000) / 0x0400 + ((add_lines & 0x0300) >> 8);
- chr1_x(bank, data, CHRROM);
+ chr1_x(4 * BIT(offset, 13) + addr_lines, data, CHRROM);
break;
case 0x7000:
- switch (add_lines)
+ switch (addr_lines)
{
- case 0x000:
+ case 0:
m_irq_count_latch = data;
break;
- case 0x100:
- m_irq_mode = data & 0x04;
- m_irq_enable = data & 0x02;
- m_irq_enable_latch = data & 0x01;
- if (data & 0x02)
- m_irq_count = m_irq_count_latch;
- set_irq_line(CLEAR_LINE);
+ case 1:
+ irq_ctrl_w(data);
break;
- case 0x200:
- m_irq_enable = m_irq_enable_latch;
- set_irq_line(CLEAR_LINE);
+ case 2:
+ irq_ack_w();
break;
default:
- logerror("VRC-6 write_h uncaught write, addr: %04x value: %02x\n", ((offset & 0x7000) | add_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;
- default:
- logerror("VRC-6 write_h uncaught write, addr: %04x value: %02x\n", ((offset & 0x7000) | add_lines) + 0x8000, data);
- break;
}
}
@@ -653,86 +609,51 @@ void nes_konami_vrc6_device::device_add_mconfig(machine_config &config)
iNES: mapper 85
- In MESS: Supported. It also uses konami_irq.
+ In MAME: Supported. It also uses konami_irq.
-------------------------------------------------*/
-void nes_konami_vrc7_device::write_h(offs_t offset, uint8_t data)
+void nes_konami_vrc7_device::write_h(offs_t offset, u8 data)
{
- uint8_t bank;
- LOG_MMC(("VRC-7 write_h, offset: %04x, data: %02x\n", offset, data));
-
- switch (offset & 0x7038)
- {
- case 0x0000:
- prg8_89(data);
- break;
- case 0x0008:
- case 0x0010:
- case 0x0018:
- prg8_ab(data);
- break;
-
- case 0x1000:
- prg8_cd(data);
- break;
-
- case 0x1010:
- case 0x1018:
- m_vrc7snd->register_port_w(data);
- break;
- case 0x1030:
- case 0x1038:
- m_vrc7snd->data_port_w(data);
- break;
+ LOG("VRC-7 write_h, offset: %04x, data: %02x\n", offset, data);
- case 0x2000:
- case 0x2008:
- case 0x2010:
- case 0x2018:
- case 0x3000:
- case 0x3008:
- case 0x3010:
- case 0x3018:
- case 0x4000:
- case 0x4008:
- case 0x4010:
- case 0x4018:
- case 0x5000:
- case 0x5008:
- case 0x5010:
- case 0x5018:
- bank = ((offset & 0x7000) - 0x2000) / 0x0800 + ((offset & 0x0018) ? 1 : 0);
- chr1_x(bank, data, m_chr_source);
- break;
+ u8 reg = bitswap<4>(offset, 14, 13, 12, m_vrc_ls_prg_a);
- case 0x6000:
- switch (data & 0x03)
- {
- case 0x00: set_nt_mirroring(PPU_MIRROR_VERT); break;
- case 0x01: set_nt_mirroring(PPU_MIRROR_HORZ); break;
- case 0x02: set_nt_mirroring(PPU_MIRROR_LOW); break;
- case 0x03: set_nt_mirroring(PPU_MIRROR_HIGH); break;
- }
- break;
- case 0x6008: case 0x6010: case 0x6018:
+ switch (reg)
+ {
+ case 0x0:
+ case 0x1:
+ case 0x2:
+ prg8_x(reg, data & 0x3f);
+ break;
+ case 0x3:
+ if (BIT(offset, 5))
+ m_vrc7snd->data_w(data);
+ else
+ m_vrc7snd->address_w(data);
+ break;
+ case 0x4:
+ case 0x5:
+ case 0x6:
+ case 0x7:
+ case 0x8:
+ case 0x9:
+ case 0xa:
+ case 0xb:
+ chr1_x(reg - 4, data, m_chr_source);
+ break;
+ case 0xc:
+ set_mirror(data);
+ m_wram_enable = BIT(data, 7);
+ break;
+ case 0xd:
m_irq_count_latch = data;
break;
- case 0x7000:
- m_irq_mode = data & 0x04;
- m_irq_enable = data & 0x02;
- m_irq_enable_latch = data & 0x01;
- if (data & 0x02)
- m_irq_count = m_irq_count_latch;
- set_irq_line(CLEAR_LINE);
+ case 0xe:
+ irq_ctrl_w(data);
break;
- case 0x7008: case 0x7010: case 0x7018:
- m_irq_enable = m_irq_enable_latch;
- set_irq_line(CLEAR_LINE);
- break;
-
- default:
- logerror("VRC-7 write_h uncaught write, addr: %04x value: %02x\n", offset + 0x8000, data);
+ case 0xf:
+ irq_ack_w();
break;
}
}
@@ -763,5 +684,5 @@ void nes_konami_vrc7_device::device_add_mconfig(machine_config &config)
// TODO: this is not how VRC7 clock signaling works!
// The board uses the CLK pin in reality, not hardcoded NTSC values!
- VRC7(config, m_vrc7snd, XTAL(21'477'272)/6).add_route(0, "addon", 1.0).add_route(1, "addon", 0.0);
+ DS1001(config, m_vrc7snd, XTAL(21'477'272)/6).add_route(0, "addon", 1.0).add_route(1, "addon", 0.0);
}
diff --git a/src/devices/bus/nes/konami.h b/src/devices/bus/nes/konami.h
index 86afa1832e1..67aa4e6f4be 100644
--- a/src/devices/bus/nes/konami.h
+++ b/src/devices/bus/nes/konami.h
@@ -7,7 +7,7 @@
#include "nxrom.h"
#include "sound/vrc6.h"
-#include "sound/ym2413.h"
+#include "sound/ymopl.h"
// ======================> nes_konami_vrc1_device
@@ -16,18 +16,18 @@ class nes_konami_vrc1_device : public nes_nrom_device
{
public:
// construction/destruction
- nes_konami_vrc1_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
+ nes_konami_vrc1_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock);
- virtual void write_h(offs_t offset, uint8_t data) override;
+ virtual void write_h(offs_t offset, u8 data) override;
virtual void pcb_reset() override;
protected:
// device-level overrides
- virtual void device_start() override;
+ virtual void device_start() override ATTR_COLD;
private:
- uint8_t m_mmc_vrom_bank[2];
+ u8 m_mmc_vrom_bank[2];
};
@@ -37,21 +37,24 @@ class nes_konami_vrc2_device : public nes_nrom_device
{
public:
// construction/destruction
- nes_konami_vrc2_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
+ nes_konami_vrc2_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock);
- virtual uint8_t read_m(offs_t offset) override;
- virtual void write_m(offs_t offset, uint8_t data) override;
- virtual void write_h(offs_t offset, uint8_t data) override;
+ virtual u8 read_m(offs_t offset) override;
+ virtual void write_m(offs_t offset, u8 data) override;
+ virtual void write_h(offs_t offset, u8 data) override;
virtual void pcb_reset() override;
protected:
+ // construction/destruction
+ nes_konami_vrc2_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_start() override ATTR_COLD;
private:
- uint8_t m_mmc_vrom_bank[8];
- uint8_t m_latch;
+ u8 m_mmc_vrom_bank[8];
+ u8 m_latch;
};
@@ -61,21 +64,20 @@ class nes_konami_vrc3_device : public nes_nrom_device
{
public:
// construction/destruction
- nes_konami_vrc3_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
+ nes_konami_vrc3_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock);
- virtual void write_h(offs_t offset, uint8_t data) override;
+ virtual void write_h(offs_t offset, u8 data) override;
virtual void pcb_reset() override;
protected:
// device-level overrides
- virtual void device_start() override;
- virtual void device_timer(emu_timer &timer, device_timer_id id, int param, void *ptr) override;
+ virtual void device_start() override ATTR_COLD;
-private:
- static constexpr device_timer_id TIMER_IRQ = 0;
+ TIMER_CALLBACK_MEMBER(irq_timer_tick);
- uint16_t m_irq_count, m_irq_count_latch;
+private:
+ u16 m_irq_count, m_irq_count_latch;
int m_irq_enable, m_irq_enable_latch;
int m_irq_mode;
@@ -89,27 +91,38 @@ class nes_konami_vrc4_device : public nes_nrom_device
{
public:
// construction/destruction
- nes_konami_vrc4_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
+ nes_konami_vrc4_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock);
- virtual void write_h(offs_t offset, uint8_t data) override;
+ virtual u8 read_m(offs_t offset) override;
+ virtual void write_m(offs_t offset, u8 data) override;
+ virtual void write_h(offs_t offset, u8 data) override;
virtual void pcb_reset() override;
protected:
- static constexpr device_timer_id TIMER_IRQ = 0;
-
- nes_konami_vrc4_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock);
+ // construction/destruction
+ nes_konami_vrc4_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_start() override ATTR_COLD;
- virtual void device_timer(emu_timer &timer, device_timer_id id, int param, void *ptr) override;
- void set_prg();
- uint8_t m_mmc_vrom_bank[8];
- uint8_t m_latch, m_mmc_prg_bank;
+ TIMER_CALLBACK_MEMBER(irq_timer_tick);
+
+ void set_mirror(u8 data);
+ void set_prg(int prg_base, int prg_mask);
+ void set_chr(int chr_base, int chr_mask);
+ virtual void set_prg() { set_prg(0x00, 0x1f); }
+ virtual void set_chr() { set_chr(0x00, 0x1ff); }
+
+ u16 m_mmc_vrom_bank[8];
+ u8 m_mmc_prg_bank[2];
+ u8 m_prg_flip;
+ u8 m_wram_enable;
void irq_tick();
- uint16_t m_irq_count, m_irq_count_latch;
+ virtual void irq_ack_w();
+ void irq_ctrl_w(u8 data);
+ u8 m_irq_count, m_irq_count_latch;
int m_irq_enable, m_irq_enable_latch;
int m_irq_mode;
int m_irq_prescale;
@@ -124,16 +137,15 @@ class nes_konami_vrc6_device : public nes_konami_vrc4_device
{
public:
// construction/destruction
- nes_konami_vrc6_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
+ nes_konami_vrc6_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock);
- virtual void write_h(offs_t offset, uint8_t data) override;
+ virtual void write_h(offs_t offset, u8 data) override;
protected:
// device-level overrides
- virtual void device_start() override;
-
- virtual void device_add_mconfig(machine_config &config) override;
+ virtual void device_add_mconfig(machine_config &config) override ATTR_COLD;
+private:
required_device<vrc6snd_device> m_vrc6snd;
};
@@ -144,20 +156,18 @@ class nes_konami_vrc7_device : public nes_konami_vrc4_device
{
public:
// construction/destruction
- nes_konami_vrc7_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
+ nes_konami_vrc7_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock);
- virtual void write_h(offs_t offset, uint8_t data) override;
+ virtual void write_h(offs_t offset, u8 data) override;
virtual void pcb_reset() override;
protected:
// device-level overrides
- virtual void device_start() override;
-
- virtual void device_add_mconfig(machine_config &config) override;
+ virtual void device_add_mconfig(machine_config &config) override ATTR_COLD;
private:
- required_device<vrc7snd_device> m_vrc7snd;
+ required_device<ds1001_device> m_vrc7snd;
};
diff --git a/src/devices/bus/nes/legacy.cpp b/src/devices/bus/nes/legacy.cpp
index a3ab9377082..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"
//-------------------------------------------------
@@ -59,23 +58,10 @@ nes_ffe8_device::nes_ffe8_device(const machine_config &mconfig, const char *tag,
-void nes_ffe3_device::device_start()
-{
- common_start();
-}
-
-void nes_ffe3_device::pcb_reset()
-{
- m_chr_source = m_vrom_chunks ? CHRROM : CHRRAM;
- prg32(0);
- chr8(0, m_chr_source);
-}
-
-
void nes_ffe4_device::device_start()
{
common_start();
- irq_timer = timer_alloc(TIMER_IRQ);
+ irq_timer = timer_alloc(FUNC(nes_ffe4_device::irq_timer_tick), this);
irq_timer->adjust(attotime::zero, 0, clocks_to_attotime(1));
save_item(NAME(m_exram));
@@ -89,7 +75,6 @@ void nes_ffe4_device::device_start()
void nes_ffe4_device::pcb_reset()
{
- m_chr_source = m_vrom_chunks ? CHRROM : CHRRAM;
prg16_89ab(0);
prg16_cdef(7);
chr8(0, m_chr_source);
@@ -105,7 +90,6 @@ void nes_ffe4_device::pcb_reset()
void nes_ffe8_device::pcb_reset()
{
- m_chr_source = m_vrom_chunks ? CHRROM : CHRRAM;
prg16_89ab(0);
prg16_cdef(0xff);
chr8(0, m_chr_source);
@@ -132,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);
@@ -151,32 +135,29 @@ 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.
-------------------------------------------------*/
-void nes_ffe4_device::device_timer(emu_timer &timer, device_timer_id id, int param, void *ptr)
+TIMER_CALLBACK_MEMBER(nes_ffe4_device::irq_timer_tick)
{
- if (id == TIMER_IRQ)
+ if (m_irq_enable)
{
- if (m_irq_enable)
+ if (m_irq_count == 0xffff)
{
- if (m_irq_count == 0xffff)
- {
- set_irq_line(ASSERT_LINE);
- m_irq_count = 0;
- m_irq_enable = 0;
- }
- else
- m_irq_count++;
+ set_irq_line(ASSERT_LINE);
+ m_irq_count = 0;
+ m_irq_enable = 0;
}
+ else
+ m_irq_count++;
}
}
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)
{
@@ -224,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?
{
@@ -253,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/legacy.h b/src/devices/bus/nes/legacy.h
index 92722c0591c..4721856abfe 100644
--- a/src/devices/bus/nes/legacy.h
+++ b/src/devices/bus/nes/legacy.h
@@ -17,12 +17,6 @@ public:
nes_ffe3_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
virtual void write_h(offs_t offset, uint8_t data) override;
-
- virtual void pcb_reset() override;
-
-protected:
- // device-level overrides
- virtual void device_start() override;
};
@@ -42,13 +36,12 @@ public:
virtual void pcb_reset() override;
protected:
- static constexpr device_timer_id TIMER_IRQ = 0;
-
nes_ffe4_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_timer(emu_timer &timer, device_timer_id id, int param, void *ptr) override;
+ virtual void device_start() override ATTR_COLD;
+
+ TIMER_CALLBACK_MEMBER(irq_timer_tick);
uint16_t m_irq_count;
int m_irq_enable;
@@ -70,7 +63,6 @@ public:
// construction/destruction
nes_ffe8_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
- // device-level overrides
virtual void write_l(offs_t offset, uint8_t data) override;
virtual void write_h(offs_t offset, uint8_t data) override {}
diff --git a/src/devices/bus/nes/mmc1.cpp b/src/devices/bus/nes/mmc1.cpp
index 9a27c601b4c..c2cbccf77e9 100644
--- a/src/devices/bus/nes/mmc1.cpp
+++ b/src/devices/bus/nes/mmc1.cpp
@@ -13,6 +13,13 @@
* 001 Yoshi flashes in-game.
* 001 Back to the Future have heavily corrupted graphics (since forever).
+ TODO:
+ - Combine 2 versions of set_prg in SxROM base class. This means dealing with
+ variant boards SNROM, SUROM, etc which repurpose bits in the MMC1 regs.
+ - Determine if "MMC1" marked chips, the earliest version, ignores WRAM
+ enable/disable bit like its first revision, MMC1A. Also determine if MMC1C
+ really exists. It's described by kevtris, but it's not in BootGod's DB.
+
***********************************************************************************************************/
@@ -20,47 +27,40 @@
#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"
//-------------------------------------------------
// constructor
//-------------------------------------------------
-DEFINE_DEVICE_TYPE(NES_SXROM, nes_sxrom_device, "nes_sxrom", "NES Cart SxROM (MMC-1) PCB")
-DEFINE_DEVICE_TYPE(NES_SOROM, nes_sorom_device, "nes_sorom", "NES Cart SOROM (MMC-1) PCB")
-DEFINE_DEVICE_TYPE(NES_SXROM_A, nes_sxrom_a_device, "nes_sxrom_a", "NES Cart SxROM (MMC-1A) PCB")
-DEFINE_DEVICE_TYPE(NES_SOROM_A, nes_sorom_a_device, "nes_sorom_a", "NES Cart SOROM (MMC-1A) PCB")
+DEFINE_DEVICE_TYPE(NES_SXROM, nes_sxrom_device, "nes_sxrom", "NES Cart SxROM (MMC-1) PCB")
+DEFINE_DEVICE_TYPE(NES_SOROM, nes_sorom_device, "nes_sorom", "NES Cart SOROM (MMC-1) PCB")
+DEFINE_DEVICE_TYPE(NES_SZROM, nes_szrom_device, "nes_szrom", "NES Cart SZROM (MMC-1) PCB")
-nes_sxrom_device::nes_sxrom_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock)
+nes_sxrom_device::nes_sxrom_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, u32 clock)
: nes_nrom_device(mconfig, type, tag, owner, clock), m_reg_write_enable(0), m_latch(0), m_count(0)
{
}
-nes_sxrom_device::nes_sxrom_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
+nes_sxrom_device::nes_sxrom_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock)
: nes_sxrom_device(mconfig, NES_SXROM, tag, owner, clock)
{
}
-nes_sorom_device::nes_sorom_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
+nes_sorom_device::nes_sorom_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock)
: nes_sxrom_device(mconfig, NES_SOROM, tag, owner, clock)
{
}
-nes_sxrom_a_device::nes_sxrom_a_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
- : nes_sxrom_device(mconfig, NES_SXROM_A, tag, owner, clock)
-{
-}
-
-nes_sorom_a_device::nes_sorom_a_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
- : nes_sxrom_device(mconfig, NES_SOROM_A, tag, owner, clock)
+nes_szrom_device::nes_szrom_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock)
+ : nes_sxrom_device(mconfig, NES_SZROM, tag, owner, clock)
{
}
@@ -77,48 +77,19 @@ void nes_sxrom_device::device_start()
void nes_sxrom_device::pcb_reset()
{
- m_chr_source = m_vrom_chunks ? CHRROM : CHRRAM;
-
- m_latch = 0;
- m_count = 0;
- m_reg[0] = 0x0f;
- m_reg[1] = m_reg[2] = m_reg[3] = 0;
- m_reg_write_enable = 1;
-
- set_nt_mirroring(PPU_MIRROR_HORZ);
- set_chr();
- set_prg();
-}
-
-void nes_sorom_device::pcb_reset()
-{
- m_chr_source = m_vrom_chunks ? CHRROM : CHRRAM;
-
m_latch = 0;
m_count = 0;
m_reg[0] = 0x0f;
- m_reg[1] = m_reg[2] = m_reg[3] = 0;
+ m_reg[1] = 0;
+ m_reg[2] = 0;
+ m_reg[3] = 0;
m_reg_write_enable = 1;
- set_nt_mirroring(PPU_MIRROR_HORZ);
set_chr();
set_prg();
+ set_mirror();
}
-void nes_sorom_a_device::pcb_reset()
-{
- m_chr_source = m_vrom_chunks ? CHRROM : CHRRAM;
-
- m_latch = 0;
- m_count = 0;
- m_reg[0] = 0x0f;
- m_reg[1] = m_reg[2] = m_reg[3] = 0;
- m_reg_write_enable = 1;
-
- set_nt_mirroring(PPU_MIRROR_HORZ);
- set_chr();
- set_prg();
-}
@@ -142,9 +113,31 @@ TIMER_CALLBACK_MEMBER( nes_sxrom_device::resync_callback )
}
+// Standard MMC1 PRG banking with base and mask (to support multicarts, etc)
+void nes_sxrom_device::set_prg(int prg_base, int prg_mask)
+{
+ u8 bank = prg_base | (m_reg[3] & prg_mask);
+
+ switch (BIT(m_reg[0], 2, 2))
+ {
+ case 0:
+ case 1:
+ prg32(bank >> 1);
+ break;
+ case 2:
+ prg16_89ab(prg_base);
+ prg16_cdef(bank);
+ break;
+ case 3:
+ prg16_89ab(bank);
+ prg16_cdef(prg_base | prg_mask);
+ break;
+ }
+}
+
void nes_sxrom_device::set_prg()
{
- uint8_t prg_mode, prg_offset;
+ u8 prg_mode, prg_offset;
prg_mode = m_reg[0] & 0x0c;
/* prg_mode&0x8 determines bank size: 32k (if 0) or 16k (if 1)? when in 16k mode,
@@ -177,34 +170,34 @@ void nes_sxrom_device::set_prg()
}
}
-void nes_sxrom_device::set_chr()
+// Standard MMC1 CHR banking with base and mask (to support multicarts, etc)
+void nes_sxrom_device::set_chr(int chr_base, int chr_mask)
{
- uint8_t chr_mode = BIT(m_reg[0], 4);
-
- if (chr_mode)
+ if (BIT(m_reg[0], 4))
{
- chr4_0(m_reg[1] & 0x1f, m_chr_source);
- chr4_4(m_reg[2] & 0x1f, m_chr_source);
+ chr4_0(chr_base | (m_reg[1] & chr_mask), m_chr_source);
+ chr4_4(chr_base | (m_reg[2] & chr_mask), m_chr_source);
}
else
- chr8((m_reg[1] & 0x1f) >> 1, m_chr_source);
+ chr8((chr_base | (m_reg[1] & chr_mask)) >> 1, m_chr_source);
}
-// this allows for easier implementation of the NES-EVENT board used for Nintento World Championships
+void nes_sxrom_device::set_mirror()
+{
+ static constexpr u8 mirr[4] = { PPU_MIRROR_LOW, PPU_MIRROR_HIGH, PPU_MIRROR_VERT, PPU_MIRROR_HORZ };
+
+ set_nt_mirroring(mirr[m_reg[0] & 0x03]);
+}
+
+// this allows for easier implementation of MMC1 subclasses
void nes_sxrom_device::update_regs(int reg)
{
switch (reg)
{
case 0:
- switch (m_reg[0] & 0x03)
- {
- case 0: set_nt_mirroring(PPU_MIRROR_LOW); break;
- case 1: set_nt_mirroring(PPU_MIRROR_HIGH); break;
- case 2: set_nt_mirroring(PPU_MIRROR_VERT); break;
- case 3: set_nt_mirroring(PPU_MIRROR_HORZ); break;
- }
set_chr();
set_prg();
+ set_mirror();
break;
case 1:
set_chr();
@@ -219,9 +212,9 @@ void nes_sxrom_device::update_regs(int reg)
}
}
-void nes_sxrom_device::write_h(offs_t offset, uint8_t data)
+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)
@@ -241,7 +234,6 @@ void nes_sxrom_device::write_h(offs_t offset, uint8_t data)
if (data & 0x80)
{
m_count = 0;
- m_latch = 0;
// Set reg at 0x8000 to size 16k and lower half swap - needed for Robocop 3, Dynowars
m_reg[0] |= 0x0c;
@@ -249,28 +241,24 @@ void nes_sxrom_device::write_h(offs_t offset, uint8_t data)
return;
}
- if (m_count < 5)
- {
- if (m_count == 0) m_latch = 0;
- m_latch >>= 1;
- m_latch |= (data & 0x01) ? 0x10 : 0x00;
- m_count++;
- }
+ m_latch >>= 1;
+ m_latch |= (data & 1) << 4;
+ m_count = (m_count + 1) % 5;
- if (m_count == 5)
+ if (!m_count)
{
- m_reg[(offset & 0x6000) >> 13] = m_latch;
- update_regs((offset & 0x6000) >> 13);
- m_count = 0;
+ int reg = BIT(offset, 13, 2);
+ m_reg[reg] = m_latch;
+ update_regs(reg);
}
}
-void nes_sxrom_device::write_m(offs_t offset, uint8_t data)
+void nes_sxrom_device::write_m(offs_t offset, u8 data)
{
- uint8_t bank = (m_reg[1] >> 2) & 3;
- LOG_MMC(("sxrom write_m, offset: %04x, data: %02x\n", offset, data));
+ u8 bank = BIT(m_reg[1], 2, 2);
+ LOG("sxrom write_m, offset: %04x, data: %02x\n", offset, data);
- if (!BIT(m_reg[3], 4)) // WRAM enabled
+ if (!BIT(m_reg[3], 4) || m_mmc1_type == mmc1_type::MMC1A) // WRAM enabled
{
if (!m_battery.empty())
m_battery[((bank * 0x2000) + offset) & (m_battery.size() - 1)] = data;
@@ -279,12 +267,12 @@ void nes_sxrom_device::write_m(offs_t offset, uint8_t data)
}
}
-uint8_t nes_sxrom_device::read_m(offs_t offset)
+u8 nes_sxrom_device::read_m(offs_t offset)
{
- uint8_t bank = (m_reg[1] >> 2) & 3;
- LOG_MMC(("sxrom read_m, offset: %04x\n", offset));
+ u8 bank = BIT(m_reg[1], 2, 2);
+ LOG("sxrom read_m, offset: %04x\n", offset);
- if (!BIT(m_reg[3], 4)) // WRAM enabled
+ if (!BIT(m_reg[3], 4) || m_mmc1_type == mmc1_type::MMC1A) // WRAM enabled
{
if (!m_battery.empty())
return m_battery[((bank * 0x2000) + offset) & (m_battery.size() - 1)];
@@ -292,16 +280,16 @@ uint8_t nes_sxrom_device::read_m(offs_t offset)
return m_prgram[((bank * 0x2000) + offset) & (m_prgram.size() - 1)];
}
- return get_open_bus(); // open bus
+ return get_open_bus();
}
// SOROM has two RAM banks, the first is not battery backed up, the second is.
-void nes_sorom_device::write_m(offs_t offset, uint8_t data)
+void nes_sorom_device::write_m(offs_t offset, u8 data)
{
- uint8_t 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));
+ u8 type = BIT(m_reg[0], 4) ? BIT(m_reg[1], 4) : BIT(m_reg[1], 3);
+ LOG("sorom write_m, offset: %04x, data: %02x\n", offset, data);
- if (!BIT(m_reg[3], 4)) // WRAM enabled
+ if (!BIT(m_reg[3], 4) || m_mmc1_type == mmc1_type::MMC1A) // WRAM enabled
{
if (type)
m_battery[offset & (m_battery.size() - 1)] = data;
@@ -310,12 +298,12 @@ void nes_sorom_device::write_m(offs_t offset, uint8_t data)
}
}
-uint8_t nes_sorom_device::read_m(offs_t offset)
+u8 nes_sorom_device::read_m(offs_t offset)
{
- uint8_t 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));
+ u8 type = BIT(m_reg[0], 4) ? BIT(m_reg[1], 4) : BIT(m_reg[1], 3);
+ LOG("sorom read_m, offset: %04x\n", offset);
- if (!BIT(m_reg[3], 4)) // WRAM enabled
+ if (!BIT(m_reg[3], 4) || m_mmc1_type == mmc1_type::MMC1A) // WRAM enabled
{
if (type)
return m_battery[offset & (m_battery.size() - 1)];
@@ -323,52 +311,34 @@ uint8_t nes_sorom_device::read_m(offs_t offset)
return m_prgram[offset & (m_prgram.size() - 1)];
}
- return get_open_bus(); // open bus
-}
-
-// MMC1A boards have no wram enable/disable bit
-void nes_sxrom_a_device::write_m(offs_t offset, uint8_t data)
-{
- uint8_t bank = (m_reg[1] >> 2) & 3;
- LOG_MMC(("sxrom_a write_m, offset: %04x, data: %02x\n", offset, data));
-
- if (!m_battery.empty())
- m_battery[((bank * 0x2000) + offset) & (m_battery.size() - 1)] = data;
- if (!m_prgram.empty())
- m_prgram[((bank * 0x2000) + offset) & (m_prgram.size() - 1)] = data;
+ return get_open_bus();
}
-uint8_t nes_sxrom_a_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)
{
- uint8_t bank = (m_reg[1] >> 2) & 3;
- LOG_MMC(("sxrom_a read_m, offset: %04x\n", offset));
-
- if (!m_battery.empty())
- return m_battery[((bank * 0x2000) + offset) & (m_battery.size() - 1)];
- if (!m_prgram.empty())
- return m_prgram[((bank * 0x2000) + offset) & (m_prgram.size() - 1)];
+ LOG("szrom write_m, offset: %04x, data: %02x\n", offset, data);
- return get_open_bus(); // open bus
+ if (!BIT(m_reg[3], 4) || m_mmc1_type == mmc1_type::MMC1A) // WRAM enabled
+ {
+ if (BIT(m_reg[BIT(m_reg[0], 4) + 1], 4))
+ m_battery[offset & (m_battery.size() - 1)] = data;
+ else
+ m_prgram[offset & (m_prgram.size() - 1)] = data;
+ }
}
-void nes_sorom_a_device::write_m(offs_t offset, uint8_t data)
+u8 nes_szrom_device::read_m(offs_t offset)
{
- uint8_t type = BIT(m_reg[0], 4) ? BIT(m_reg[1], 4) : BIT(m_reg[1], 3);
- LOG_MMC(("sorom_a write_m, offset: %04x, data: %02x\n", offset, data));
+ LOG("szrom read_m, offset: %04x\n", offset);
- if (type)
- m_battery[offset & (m_battery.size() - 1)] = data;
- else
- m_prgram[offset & (m_prgram.size() - 1)] = data;
-}
-
-uint8_t nes_sorom_a_device::read_m(offs_t offset)
-{
- uint8_t type = BIT(m_reg[0], 4) ? BIT(m_reg[1], 4) : BIT(m_reg[1], 3);
- LOG_MMC(("sorom_a read_m, offset: %04x\n", offset));
+ if (!BIT(m_reg[3], 4) || m_mmc1_type == mmc1_type::MMC1A) // WRAM enabled
+ {
+ if (BIT(m_reg[BIT(m_reg[0], 4) + 1], 4))
+ return m_battery[offset & (m_battery.size() - 1)];
+ else
+ return m_prgram[offset & (m_prgram.size() - 1)];
+ }
- if (type)
- return m_battery[offset & (m_battery.size() - 1)];
- else
- return m_prgram[offset & (m_prgram.size() - 1)];
+ return get_open_bus();
}
diff --git a/src/devices/bus/nes/mmc1.h b/src/devices/bus/nes/mmc1.h
index c8ccb835d76..64c508976ac 100644
--- a/src/devices/bus/nes/mmc1.h
+++ b/src/devices/bus/nes/mmc1.h
@@ -14,71 +14,68 @@ class nes_sxrom_device : public nes_nrom_device
{
public:
// construction/destruction
- nes_sxrom_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
+ nes_sxrom_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock);
- virtual uint8_t read_m(offs_t offset) override;
- virtual void write_m(offs_t offset, uint8_t data) override;
- virtual void write_h(offs_t offset, uint8_t data) override;
+ virtual u8 read_m(offs_t offset) override;
+ virtual void write_m(offs_t offset, u8 data) override;
+ virtual void write_h(offs_t offset, u8 data) override;
virtual void pcb_reset() override;
protected:
- nes_sxrom_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock);
+ nes_sxrom_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_start() override ATTR_COLD;
TIMER_CALLBACK_MEMBER(resync_callback);
- virtual void update_regs(int reg); // this is needed to simplify NES-EVENT pcb implementation, which handle differently some regs!
+ virtual void update_regs(int reg);
+ void set_prg(int prg_base, int prg_mask);
+ void set_chr(int chr_base, int chr_mask);
virtual void set_prg();
- virtual void set_chr();
+// virtual void set_prg() { set_prg(0x00, 0x0f); }
+ virtual void set_chr() { set_chr(0x00, 0x1f); }
+ virtual void set_mirror();
- uint8_t m_reg[4];
- int m_reg_write_enable;
- int m_latch;
- int m_count;
+ u8 m_reg[4];
+
+private:
+ u8 m_reg_write_enable;
+ u8 m_latch;
+ u8 m_count;
};
+
+// ======================> nes_sorom_device
+
class nes_sorom_device : public nes_sxrom_device
{
public:
// construction/destruction
- nes_sorom_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
+ nes_sorom_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock);
- virtual uint8_t read_m(offs_t offset) override;
- virtual void write_m(offs_t offset, uint8_t data) override;
-
- virtual void pcb_reset() override;
+ virtual u8 read_m(offs_t offset) override;
+ virtual void write_m(offs_t offset, u8 data) override;
};
-class nes_sxrom_a_device : public nes_sxrom_device
-{
-public:
- // construction/destruction
- nes_sxrom_a_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
- virtual uint8_t read_m(offs_t offset) override;
- virtual void write_m(offs_t offset, uint8_t data) override;
-};
+// ======================> nes_szrom_device
-class nes_sorom_a_device : public nes_sxrom_device
+class nes_szrom_device : public nes_sxrom_device
{
public:
// construction/destruction
- nes_sorom_a_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
+ nes_szrom_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock);
- virtual uint8_t read_m(offs_t offset) override;
- virtual void write_m(offs_t offset, uint8_t data) override;
-
- virtual void pcb_reset() override;
+ virtual u8 read_m(offs_t offset) override;
+ virtual void write_m(offs_t offset, u8 data) override;
};
// device type definition
-DECLARE_DEVICE_TYPE(NES_SXROM, nes_sxrom_device)
-DECLARE_DEVICE_TYPE(NES_SOROM, nes_sorom_device)
-DECLARE_DEVICE_TYPE(NES_SXROM_A, nes_sxrom_a_device)
-DECLARE_DEVICE_TYPE(NES_SOROM_A, nes_sorom_a_device)
+DECLARE_DEVICE_TYPE(NES_SXROM, nes_sxrom_device)
+DECLARE_DEVICE_TYPE(NES_SOROM, nes_sorom_device)
+DECLARE_DEVICE_TYPE(NES_SZROM, nes_szrom_device)
#endif // MAME_BUS_NES_MMC1_H
diff --git a/src/devices/bus/nes/mmc1_clones.cpp b/src/devices/bus/nes/mmc1_clones.cpp
new file mode 100644
index 00000000000..8c318c4b96c
--- /dev/null
+++ b/src/devices/bus/nes/mmc1_clones.cpp
@@ -0,0 +1,432 @@
+// license:BSD-3-Clause
+// copyright-holders:kmg
+/***********************************************************************************************************
+
+
+ NES/Famicom cartridge emulation for MMC-1 clone PCBs
+
+
+ Here we emulate several pirate PCBs based on MMC-1 boards
+
+ ***********************************************************************************************************/
+
+
+#include "emu.h"
+#include "mmc1_clones.h"
+
+
+#ifdef NES_PCB_DEBUG
+#define VERBOSE (LOG_GENERAL)
+#else
+#define VERBOSE (0)
+#endif
+#include "logmacro.h"
+
+
+//-------------------------------------------------
+// constructor
+//-------------------------------------------------
+
+DEFINE_DEVICE_TYPE(NES_BMC_JY012005, nes_bmc_jy012005_device, "nes_bmc_jy012005", "NES Cart BMC JY012005 PCB")
+DEFINE_DEVICE_TYPE(NES_BMC_JY820845C, nes_bmc_jy820845c_device, "nes_bmc_jy820845c", "NES Cart BMC JY820845C PCB")
+DEFINE_DEVICE_TYPE(NES_FARID_SLROM, nes_farid_slrom_device, "nes_farid_slrom", "NES Cart Farid SLROM 8 in 1 PCB")
+DEFINE_DEVICE_TYPE(NES_NINJARYU, nes_ninjaryu_device, "nes_ninjaryu", "NES Cart Ninja Ryukenden Chinese PCB")
+DEFINE_DEVICE_TYPE(NES_RESETSXROM, nes_resetsxrom_device, "nes_resetsxrom", "NES Cart BMC RESET-SXROM PCB")
+DEFINE_DEVICE_TYPE(NES_SRPG_5IN1, nes_srpg5in1_device, "nes_srpg5in1", "NES Cart Super RPG 5 in 1 PCB")
+DEFINE_DEVICE_TYPE(NES_TXC_22110, nes_txc_22110_device, "nes_txc_22110", "NES Cart TXC 01-22110-000 PCB")
+
+
+nes_bmc_jy012005_device::nes_bmc_jy012005_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock)
+ : nes_sxrom_device(mconfig, NES_BMC_JY012005, tag, owner, clock), m_latch0(0)
+{
+}
+
+nes_bmc_jy820845c_device::nes_bmc_jy820845c_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock)
+ : nes_sxrom_device(mconfig, NES_BMC_JY820845C, tag, owner, clock), m_latch0(0), m_mode(0)
+{
+}
+
+nes_farid_slrom_device::nes_farid_slrom_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock)
+ : nes_sxrom_device(mconfig, NES_FARID_SLROM, tag, owner, clock), m_outer(0)
+{
+}
+
+nes_ninjaryu_device::nes_ninjaryu_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock)
+ : nes_sxrom_device(mconfig, NES_NINJARYU, tag, owner, clock)
+{
+}
+
+nes_resetsxrom_device::nes_resetsxrom_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock)
+ : nes_sxrom_device(mconfig, NES_RESETSXROM, tag, owner, clock), m_reset_count(-1)
+{
+}
+
+nes_srpg5in1_device::nes_srpg5in1_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock)
+ : nes_sxrom_device(mconfig, NES_SRPG_5IN1, tag, owner, clock), m_outer(0), m_outer_count(0), m_outer_latch(0)
+{
+}
+
+nes_txc_22110_device::nes_txc_22110_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock)
+ : nes_sxrom_device(mconfig, NES_TXC_22110, tag, owner, clock), m_latch0(0), m_mode(0)
+{
+}
+
+
+
+void nes_bmc_jy012005_device::device_start()
+{
+ nes_sxrom_device::device_start();
+ save_item(NAME(m_latch0));
+}
+
+void nes_bmc_jy012005_device::pcb_reset()
+{
+ m_latch0 = 0;
+ nes_sxrom_device::pcb_reset();
+}
+
+void nes_bmc_jy820845c_device::device_start()
+{
+ nes_sxrom_device::device_start();
+ save_item(NAME(m_latch0));
+ save_item(NAME(m_mode));
+}
+
+void nes_bmc_jy820845c_device::pcb_reset()
+{
+ nes_sxrom_device::pcb_reset();
+
+ m_latch0 = 0;
+ m_mode = 0;
+ update_banks();
+}
+
+void nes_farid_slrom_device::device_start()
+{
+ nes_sxrom_device::device_start();
+ save_item(NAME(m_outer));
+}
+
+void nes_farid_slrom_device::pcb_reset()
+{
+ m_outer = 0;
+ nes_sxrom_device::pcb_reset();
+}
+
+void nes_resetsxrom_device::device_start()
+{
+ nes_sxrom_device::device_start();
+ save_item(NAME(m_reset_count));
+}
+
+void nes_resetsxrom_device::pcb_reset()
+{
+ m_reset_count = (m_reset_count + 1) & 3;
+ nes_sxrom_device::pcb_reset();
+}
+
+void nes_srpg5in1_device::device_start()
+{
+ nes_sxrom_device::device_start();
+ save_item(NAME(m_outer));
+ save_item(NAME(m_outer_count));
+ save_item(NAME(m_outer_latch));
+}
+
+void nes_srpg5in1_device::pcb_reset()
+{
+ m_outer = 0;
+ m_outer_count = 0;
+ m_outer_latch = 0;
+ nes_sxrom_device::pcb_reset();
+}
+
+void nes_txc_22110_device::device_start()
+{
+ nes_sxrom_device::device_start();
+ save_item(NAME(m_latch0));
+ save_item(NAME(m_mode));
+}
+
+void nes_txc_22110_device::pcb_reset()
+{
+ nes_sxrom_device::pcb_reset();
+
+ m_latch0 = 0;
+ m_mode = 0;
+ update_banks();
+}
+
+
+
+/*-------------------------------------------------
+ mapper specific handlers
+ -------------------------------------------------*/
+
+/*-------------------------------------------------
+
+ UNL-NINJARYU
+
+ Games: Ninja Ryukenden Chinese
+
+ This board was previously assigned to mapper 111. It has
+ registers akin to MMC1 but without the need to write to
+ them serially. The one existing game has 256K CHR, so this
+ must have at least 1 more bit for CHR banking. Other differences?
+
+ In MAME: Preliminary supported.
+
+ -------------------------------------------------*/
+
+void nes_ninjaryu_device::write_h(offs_t offset, u8 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);
+}
+
+
+/*-------------------------------------------------
+
+ MULTIGAME CARTS BASED ON MMC1
+
+ -------------------------------------------------*/
+
+/*-------------------------------------------------
+
+ BMC-JY012005
+
+ Games: 1998 Super HiK 8 in 1 (JY-021B)
+
+ MMC1 clone with banking for multigame menu.
+
+ NES 2.0: mapper 404
+
+ In MAME: Supported.
+
+ -------------------------------------------------*/
+
+void nes_bmc_jy012005_device::set_prg()
+{
+ u8 mode = !BIT(m_latch0, 6);
+ nes_sxrom_device::set_prg((m_latch0 & 0x07 & ~mode) << 3, mode << 3 | 0x07);
+}
+
+void nes_bmc_jy012005_device::set_chr()
+{
+ nes_sxrom_device::set_chr((m_latch0 & 0x07) << 5, 0x1f);
+}
+
+void nes_bmc_jy012005_device::write_m(offs_t offset, u8 data)
+{
+ LOG("bmc_jy012005 write_m, offset: %04x, data: %02x\n", offset, data);
+
+ if (!BIT(m_latch0, 7)) // outer bank lock
+ {
+ m_latch0 = data;
+ set_prg();
+ set_chr();
+ }
+}
+
+/*-------------------------------------------------
+
+ BMC-JY820845C
+
+ Games: 7 in 1 1993 Chess Series (JY-015)
+
+ MMC1 clone with banking for multigame menu.
+
+ NES 2.0: mapper 550
+
+ In MAME: Supported.
+
+ -------------------------------------------------*/
+
+void nes_bmc_jy820845c_device::update_banks() // used by menu and MHROM games
+{
+ prg32((m_mode & 0x07) << 1 | BIT(m_latch0, 4));
+ chr8((m_mode & 0x06) << 1 | (m_latch0 & 0x03), CHRROM);
+}
+
+void nes_bmc_jy820845c_device::write_m(offs_t offset, u8 data)
+{
+ LOG("bmc_jy820845c write_m, offset: %04x, data: %02x\n", offset, data);
+
+ nes_sxrom_device::write_m(offset, data); // register overlaid on WRAM
+
+ if (offset >= 0x1000 && !BIT(m_mode, 3))
+ {
+ m_mode = offset & 0x0f;
+ if ((m_mode & 0x06) == 0x06) // MMC1 mode
+ {
+ set_prg();
+ set_chr();
+ }
+ else
+ update_banks();
+ }
+}
+
+void nes_bmc_jy820845c_device::write_h(offs_t offset, u8 data)
+{
+ LOG("bmc_jy820845c write_h, offset: %04x, data: %02x\n", offset, data);
+
+ m_latch0 = data;
+
+ if ((m_mode & 0x06) == 0x06)
+ nes_sxrom_device::write_h(offset, data);
+ else
+ update_banks();
+}
+
+/*-------------------------------------------------
+
+ FARID_SLROM_8-IN-1
+
+ Games: 8 in 1
+
+ MMC1 clone with banking for multigame menu.
+
+ NES 2.0: mapper 323
+
+ In MAME: Supported.
+
+ -------------------------------------------------*/
+
+void nes_farid_slrom_device::write_m(offs_t offset, u8 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;
+}
+
+/*-------------------------------------------------
+
+ BMC-RESET-SXROM
+
+ Games: 4 in 1 (JY-021, JY-022, JY-051)
+
+ MMC1 clone with outer banks switched by resetting.
+
+ NES 2.0: mapper 374
+
+ In MAME: Supported.
+
+ -------------------------------------------------*/
+
+/*-------------------------------------------------
+
+ BMC-SRPG-5IN1 (PCB has no distinguishing label)
+
+ Games: Super RPG 5 in 1 CH501
+
+ MMC1 clone with banking for multigame menu. Note: This
+ game does not soft reset properly on real hardware.
+
+ The interesting feature of this board is that it has a
+ serially written 4-bit shift register that selects the
+ outer game bank (meaning it has two shift registers,
+ since it also clones the MMC1's). The MSB (bit 3) seems
+ to indicate menu mode (0) or game mode (1), but it's not
+ clear if/how this is used. Is it a lock? We currently
+ don't use the MSB nor allow it to be read back.
+
+ NES 2.0: mapper 543
+
+ In MAME: Supported.
+
+ -------------------------------------------------*/
+
+void nes_srpg5in1_device::write_l(offs_t offset, u8 data)
+{
+ LOG("srpg5in1 write_l, offset: %04x, data: %02x\n", offset, data);
+
+ offset += 0x100;
+ if (offset >= 0x1000)
+ {
+ m_outer_latch = (data & 0x08) | m_outer_latch >> 1;
+ m_outer_count = (m_outer_count + 1) & 0x03;
+ if (!m_outer_count)
+ {
+ m_outer = m_outer_latch;
+ set_prg();
+ }
+ }
+}
+
+void nes_srpg5in1_device::write_m(offs_t offset, u8 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);
+
+ if (!BIT(m_reg[3], 4)) // WRAM enabled
+ m_battery[((bank * 0x2000) + offset) & (m_battery.size() - 1)] = data;
+}
+
+u8 nes_srpg5in1_device::read_m(offs_t 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);
+
+ if (!BIT(m_reg[3], 4)) // WRAM enabled
+ return m_battery[((bank * 0x2000) + offset) & (m_battery.size() - 1)];
+
+ return get_open_bus();
+}
+
+/*-------------------------------------------------
+
+ TXC 01-22110-000 Board
+
+ Games: 2 in 1 Uzi Lightgun (MGC-002)
+
+ This board has an MMC1 clone for Operation Wolf and
+ otherwise is mostly compatible with mapper 70 for
+ Bandai's Space Shadow.
+
+ NES 2.0: mapper 297
+
+ In MAME: Supported.
+
+ -------------------------------------------------*/
+
+void nes_txc_22110_device::update_banks() // used by menu and Space Shadow
+{
+ u8 outer = (m_mode & 0x02) << 1;
+ prg16_89ab(outer | BIT(m_latch0, 4, 2));
+ prg16_cdef(outer | 3);
+ chr8(m_latch0 & 0x0f, CHRROM);
+}
+
+void nes_txc_22110_device::write_l(offs_t offset, u8 data)
+{
+ LOG("TXC 22110 write_l, offset: %04x, data: %02x\n", offset, data);
+ if (offset < 0x100) // $4100 - $41ff
+ {
+ m_mode = data;
+ if (m_mode & 1) // MMC1 mode
+ {
+ set_prg();
+ set_chr();
+ }
+ else
+ update_banks();
+ }
+}
+
+void nes_txc_22110_device::write_h(offs_t offset, u8 data)
+{
+ LOG("TXC 22110 write_h, offset: %04x, data: %02x\n", offset, data);
+
+ if (m_mode & 1)
+ nes_sxrom_device::write_h(offset, data);
+ else
+ {
+ m_latch0 = data;
+ update_banks();
+ }
+}
diff --git a/src/devices/bus/nes/mmc1_clones.h b/src/devices/bus/nes/mmc1_clones.h
new file mode 100644
index 00000000000..dbb2ef93061
--- /dev/null
+++ b/src/devices/bus/nes/mmc1_clones.h
@@ -0,0 +1,185 @@
+// license:BSD-3-Clause
+// copyright-holders:kmg
+#ifndef MAME_BUS_NES_MMC1_CLONES_H
+#define MAME_BUS_NES_MMC1_CLONES_H
+
+#pragma once
+
+#include "mmc1.h"
+
+
+// ======================> nes_bmc_jy012005_device
+
+class nes_bmc_jy012005_device : public nes_sxrom_device
+{
+public:
+ // construction/destruction
+ nes_bmc_jy012005_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock);
+
+ virtual void write_m(offs_t offset, u8 data) override;
+
+ virtual void pcb_reset() override;
+
+protected:
+ // device-level overrides
+ virtual void device_start() override ATTR_COLD;
+
+ virtual void set_prg() override;
+ virtual void set_chr() override;
+
+private:
+ u8 m_latch0;
+};
+
+
+// ======================> nes_bmc_jy820845c_device
+
+class nes_bmc_jy820845c_device : public nes_sxrom_device
+{
+public:
+ // construction/destruction
+ nes_bmc_jy820845c_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock);
+
+ virtual void write_m(offs_t offset, u8 data) override;
+ virtual void write_h(offs_t offset, u8 data) override;
+
+ virtual void pcb_reset() override;
+
+protected:
+ // device-level overrides
+ virtual void device_start() override ATTR_COLD;
+
+ virtual void set_prg() override { nes_sxrom_device::set_prg(0x18, 0x07); }
+ virtual void set_chr() override { nes_sxrom_device::set_chr(0x18, 0x07); }
+
+private:
+ void update_banks();
+ u8 m_latch0, m_mode;
+};
+
+
+// ======================> nes_farid_slrom_device
+
+class nes_farid_slrom_device : public nes_sxrom_device
+{
+public:
+ // construction/destruction
+ nes_farid_slrom_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock);
+
+ virtual void write_m(offs_t offset, u8 data) override;
+
+ virtual void pcb_reset() override;
+
+protected:
+ // device-level overrides
+ virtual void device_start() override ATTR_COLD;
+
+ virtual void set_prg() override { nes_sxrom_device::set_prg((m_outer & 0x70) >> 1, 0x07); }
+ virtual void set_chr() override { nes_sxrom_device::set_chr((m_outer & 0x70) << 1, 0x1f); }
+
+private:
+ u8 m_outer;
+};
+
+
+// ======================> nes_ninjaryu_device
+
+class nes_ninjaryu_device : public nes_sxrom_device
+{
+public:
+ // construction/destruction
+ nes_ninjaryu_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock);
+
+ virtual void write_h(offs_t offset, u8 data) override;
+
+protected:
+ virtual void set_prg() override { nes_sxrom_device::set_prg(0x00, 0x0f); }
+ virtual void set_chr() override { nes_sxrom_device::set_chr(0x00, 0x3f); }
+};
+
+
+// ======================> nes_resetsxrom_device
+
+class nes_resetsxrom_device : public nes_sxrom_device
+{
+public:
+ // construction/destruction
+ nes_resetsxrom_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock);
+
+ virtual void pcb_reset() override;
+
+protected:
+ // device-level overrides
+ virtual void device_start() override ATTR_COLD;
+
+ virtual void set_prg() override { nes_sxrom_device::set_prg(m_reset_count << 3, 0x07); }
+ virtual void set_chr() override { nes_sxrom_device::set_chr(m_reset_count << 5, 0x1f); }
+
+private:
+ int m_reset_count;
+};
+
+
+// ======================> nes_srpg5in1_device
+
+class nes_srpg5in1_device : public nes_sxrom_device
+{
+public:
+ // construction/destruction
+ nes_srpg5in1_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock);
+
+ virtual u8 read_m(offs_t offset) override;
+ virtual void write_l(offs_t offset, u8 data) override;
+ virtual void write_m(offs_t offset, u8 data) override;
+
+ virtual void pcb_reset() override;
+
+protected:
+ // device-level overrides
+ virtual void device_start() override ATTR_COLD;
+
+ virtual void set_prg() override { nes_sxrom_device::set_prg((m_outer & 0x07) << 4, 0x0f); }
+ virtual void set_chr() override { nes_sxrom_device::set_chr(0x00, 0x01); }
+
+private:
+ u8 m_outer, m_outer_count, m_outer_latch;
+};
+
+
+// ======================> nes_txc_22110_device
+
+class nes_txc_22110_device : public nes_sxrom_device
+{
+public:
+ // construction/destruction
+ nes_txc_22110_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock);
+
+ virtual void write_l(offs_t offset, u8 data) override;
+ virtual void write_h(offs_t offset, u8 data) override;
+
+ virtual void pcb_reset() override;
+
+protected:
+ // device-level overrides
+ virtual void device_start() override ATTR_COLD;
+
+ virtual void set_prg() override { nes_sxrom_device::set_prg(0x08, 0x07); }
+ virtual void set_chr() override { nes_sxrom_device::set_chr(0x20, 0x1f); }
+ virtual void set_mirror() override {} // hardwired to vertical mirroring
+
+private:
+ void update_banks();
+ u8 m_latch0, m_mode;
+};
+
+
+// device type definition
+DECLARE_DEVICE_TYPE(NES_BMC_JY012005, nes_bmc_jy012005_device)
+DECLARE_DEVICE_TYPE(NES_BMC_JY820845C, nes_bmc_jy820845c_device)
+DECLARE_DEVICE_TYPE(NES_FARID_SLROM, nes_farid_slrom_device)
+DECLARE_DEVICE_TYPE(NES_NINJARYU, nes_ninjaryu_device)
+DECLARE_DEVICE_TYPE(NES_RESETSXROM, nes_resetsxrom_device)
+DECLARE_DEVICE_TYPE(NES_SRPG_5IN1, nes_srpg5in1_device)
+DECLARE_DEVICE_TYPE(NES_TXC_22110, nes_txc_22110_device)
+
+#endif // MAME_BUS_NES_MMC1_CLONES_H
diff --git a/src/devices/bus/nes/mmc2.cpp b/src/devices/bus/nes/mmc2.cpp
index 8be7b04d2d7..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"
//-------------------------------------------------
@@ -59,7 +58,6 @@ void nes_pxrom_device::device_start()
void nes_pxrom_device::pcb_reset()
{
- m_chr_source = m_vrom_chunks ? CHRROM : CHRRAM;
prg8_89(0);
prg8_ab((m_prg_chunks << 1) - 3);
prg8_cd((m_prg_chunks << 1) - 2);
@@ -73,7 +71,6 @@ void nes_pxrom_device::pcb_reset()
void nes_fxrom_device::pcb_reset()
{
- m_chr_source = m_vrom_chunks ? CHRROM : CHRRAM;
prg16_89ab(0);
prg16_cdef(m_prg_chunks - 1);
chr8(0, m_chr_source);
@@ -98,7 +95,7 @@ void nes_fxrom_device::pcb_reset()
iNES: mapper 9
- In MESS: Supported
+ In MAME: Supported
-------------------------------------------------*/
@@ -106,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);
}
@@ -132,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:
@@ -162,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;
}
}
@@ -178,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/mmc2.h b/src/devices/bus/nes/mmc2.h
index 9f4d100d2f6..0a83cdb721b 100644
--- a/src/devices/bus/nes/mmc2.h
+++ b/src/devices/bus/nes/mmc2.h
@@ -26,7 +26,7 @@ protected:
nes_pxrom_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_start() override ATTR_COLD;
uint8_t m_reg[4];
int m_latch1, m_latch2;
@@ -41,7 +41,6 @@ public:
// construction/destruction
nes_fxrom_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
- // device-level overrides
virtual void write_h(offs_t offset, uint8_t data) override;
virtual void pcb_reset() override;
diff --git a/src/devices/bus/nes/mmc3.cpp b/src/devices/bus/nes/mmc3.cpp
index d6f7f37dc4a..79b6c7deefa 100644
--- a/src/devices/bus/nes/mmc3.cpp
+++ b/src/devices/bus/nes/mmc3.cpp
@@ -20,7 +20,6 @@
* 004 Mendel Palace has never worked properly
* 004 Ninja Gaiden 2 has flashing bg graphics in the second level
- * 119 Pin Bot has glitches when the ball is in the upper half of the screen
***********************************************************************************************************/
@@ -29,16 +28,15 @@
#include "mmc3.h"
#include "video/ppu2c0x.h" // this has to be included so that IRQ functions can access ppu2c0x_device::BOTTOM_VISIBLE_SCANLINE
-#include "screen.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"
//-------------------------------------------------
@@ -54,7 +52,7 @@ DEFINE_DEVICE_TYPE(NES_ZZ_PCB, nes_zz_device, "nes_zz", "NES Cart PAL-ZZ
nes_txrom_device::nes_txrom_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock)
- : nes_nrom_device(mconfig, type, tag, owner, clock), m_prg_base(0), m_prg_mask(0), m_chr_base(0), m_chr_mask(0)
+ : nes_nrom_device(mconfig, type, tag, owner, clock), m_mmc_mirror(0), m_prg_base(0), m_prg_mask(0), m_chr_base(0), m_chr_mask(0)
, m_latch(0), m_wram_protect(0), m_alt_irq(0), m_irq_count(0), m_irq_count_latch(0), m_irq_clear(0), m_irq_enable(0)
{
}
@@ -69,22 +67,32 @@ nes_hkrom_device::nes_hkrom_device(const machine_config &mconfig, const char *ta
{
}
-nes_txsrom_device::nes_txsrom_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
- : nes_txrom_device(mconfig, NES_TXSROM, tag, owner, clock)
+nes_txsrom_device::nes_txsrom_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, u32 clock)
+ : nes_txrom_device(mconfig, type, tag, owner, clock)
+{
+}
+
+nes_txsrom_device::nes_txsrom_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock)
+ : nes_txsrom_device(mconfig, NES_TXSROM, tag, owner, clock)
+{
+}
+
+nes_tqrom_device::nes_tqrom_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, u32 clock)
+ : nes_txrom_device(mconfig, type, tag, owner, clock)
{
}
-nes_tqrom_device::nes_tqrom_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
- : nes_txrom_device(mconfig, NES_TQROM, tag, owner, clock)
+nes_tqrom_device::nes_tqrom_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock)
+ : nes_tqrom_device(mconfig, NES_TQROM, tag, owner, clock)
{
}
-nes_qj_device::nes_qj_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
+nes_qj_device::nes_qj_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock)
: nes_txrom_device(mconfig, NES_QJ_PCB, tag, owner, clock)
{
}
-nes_zz_device::nes_zz_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
+nes_zz_device::nes_zz_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock)
: nes_txrom_device(mconfig, NES_ZZ_PCB, tag, owner, clock)
{
}
@@ -96,6 +104,7 @@ void nes_txrom_device::mmc3_start()
common_start();
save_item(NAME(m_mmc_prg_bank));
save_item(NAME(m_mmc_vrom_bank));
+ save_item(NAME(m_mmc_mirror));
save_item(NAME(m_latch));
save_item(NAME(m_wram_protect));
save_item(NAME(m_prg_base));
@@ -113,8 +122,19 @@ void nes_txrom_device::mmc3_common_initialize( int prg_mask, int chr_mask, int i
{
m_mmc_prg_bank[0] = m_mmc_prg_bank[2] = 0xffe; // m_mmc_prg_bank[2] & m_mmc_prg_bank[3] remain always the same in most MMC3 variants
m_mmc_prg_bank[1] = m_mmc_prg_bank[3] = 0xfff; // but some pirate clone mappers change them after writing certain registers
- memset(m_mmc_vrom_bank, 0, sizeof(m_mmc_vrom_bank));
+ // Point CHR banks to the first 8K of memory. This is needed for a few unlicensed carts that use VRAM and don't init banks properly.
+ // This includes at least some Waixing games, EverQuest and Sanguozhi, and some multicarts, New Star 6 in 1 and Famicom Yarou Vol 1.
+ m_mmc_vrom_bank[0] = 0;
+ m_mmc_vrom_bank[1] = 2;
+ m_mmc_vrom_bank[2] = 4;
+ m_mmc_vrom_bank[3] = 5;
+ m_mmc_vrom_bank[4] = 6;
+ m_mmc_vrom_bank[5] = 7;
+ m_mmc_vrom_bank[6] = 0; // extension reg used by clone boards
+ m_mmc_vrom_bank[7] = 0; // extension reg used by clone boards
+
+ m_mmc_mirror = 0;
m_latch = 0;
m_wram_protect = 0x80;
@@ -134,7 +154,6 @@ void nes_txrom_device::mmc3_common_initialize( int prg_mask, int chr_mask, int i
void nes_txrom_device::pcb_reset()
{
- m_chr_source = m_vrom_chunks ? CHRROM : CHRRAM;
// 4-screen mirroring is taken care in pcb_start, if needed...
mmc3_common_initialize(0xff, 0xff, 0);
}
@@ -154,7 +173,6 @@ void nes_hkrom_device::device_start()
void nes_hkrom_device::pcb_reset()
{
- m_chr_source = m_vrom_chunks ? CHRROM : CHRRAM;
mmc3_common_initialize(0xff, 0xff, 1);
m_mmc6_reg = 0xf0;
m_wram_enable = 0;
@@ -163,14 +181,12 @@ void nes_hkrom_device::pcb_reset()
void nes_qj_device::pcb_reset()
{
- m_chr_source = m_vrom_chunks ? CHRROM : CHRRAM;
mmc3_common_initialize(0x0f, 0x7f, 0);
}
void nes_zz_device::pcb_reset()
{
- m_chr_source = m_vrom_chunks ? CHRROM : CHRRAM;
mmc3_common_initialize(0x07, 0x7f, 0);
}
@@ -188,7 +204,7 @@ void nes_zz_device::pcb_reset()
-------------------------------------------------*/
/* Here, IRQ counter decrements every scanline. */
-void nes_txrom_device::hblank_irq(int scanline, int vblank, int blanked)
+void nes_txrom_device::hblank_irq(int scanline, bool vblank, bool blanked)
{
if (scanline < ppu2c0x_device::BOTTOM_VISIBLE_SCANLINE)
{
@@ -200,7 +216,7 @@ void nes_txrom_device::hblank_irq(int scanline, int vblank, int 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);
}
}
@@ -248,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)
{
@@ -283,7 +299,9 @@ void nes_txrom_device::txrom_write(offs_t offset, uint8_t data)
break;
case 0x2000:
- set_nt_mirroring(BIT(data, 0) ? PPU_MIRROR_HORZ : PPU_MIRROR_VERT);
+ m_mmc_mirror = data;
+ if (m_mirroring != PPU_MIRROR_4SCREEN)
+ set_nt_mirroring(BIT(data, 0) ? PPU_MIRROR_HORZ : PPU_MIRROR_VERT);
break;
case 0x2001:
@@ -308,27 +326,27 @@ 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))
{
if (!m_battery.empty())
m_battery[offset & (m_battery.size() - 1)] = data;
- if (!m_prgram.empty())
+ else if (!m_prgram.empty())
m_prgram[offset & (m_prgram.size() - 1)] = 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))
{
@@ -338,7 +356,7 @@ uint8_t nes_txrom_device::read_m(offs_t offset)
return m_prgram[offset & (m_prgram.size() - 1)];
}
- return get_open_bus(); // open bus
+ return get_open_bus();
}
@@ -353,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;
@@ -371,13 +389,13 @@ 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(); // open bus
+ return get_open_bus();
if (!(m_mmc6_reg & 0xa0))
- return get_open_bus(); // open bus
+ return get_open_bus();
if (BIT(offset, 9) && BIT(m_mmc6_reg, 7)) // access to upper half of 1k when upper read is enabled
return m_mmc6_ram[offset & 0x3ff];
@@ -392,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)
{
@@ -437,43 +455,30 @@ void nes_hkrom_device::write_h(offs_t offset, uint8_t data)
iNES: mapper 118
- In MESS: Supported. It also uses mmc3_irq.
+ In MAME: Supported. It also uses mmc3_irq.
-------------------------------------------------*/
-void nes_txsrom_device::set_mirror()
+void nes_txsrom_device::set_chr(u8 chr, int chr_base, int chr_mask)
{
- if (m_latch & 0x80)
- {
- set_nt_page(0, CIRAM, BIT(m_mmc_vrom_bank[2],7), 1);
- set_nt_page(1, CIRAM, BIT(m_mmc_vrom_bank[3],7), 1);
- set_nt_page(2, CIRAM, BIT(m_mmc_vrom_bank[4],7), 1);
- set_nt_page(3, CIRAM, BIT(m_mmc_vrom_bank[5],7), 1);
- }
- else
- {
- set_nt_page(0, CIRAM, BIT(m_mmc_vrom_bank[0],7), 1);
- set_nt_page(1, CIRAM, BIT(m_mmc_vrom_bank[0],7), 1);
- set_nt_page(2, CIRAM, BIT(m_mmc_vrom_bank[1],7), 1);
- set_nt_page(3, CIRAM, BIT(m_mmc_vrom_bank[1],7), 1);
- }
-}
+ nes_txrom_device::set_chr(chr, chr_base, chr_mask);
-void nes_txsrom_device::chr_cb( int start, int bank, int source )
-{
- set_mirror(); // we could probably update only for one (e.g. the first) call, to slightly optimize the code
- chr1_x(start, bank, source);
+ // do nametables
+ static constexpr u8 bank[8] = { 0, 0, 1, 1, 2, 3, 4, 5 };
+ int start = (m_latch & 0x80) >> 5;
+
+ for (int i = 0; i < 4; i++)
+ set_nt_page(i, CIRAM, BIT(m_mmc_vrom_bank[bank[start + i]], 7), 1);
}
-void nes_txsrom_device::write_h(offs_t offset, uint8_t data)
+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)
{
case 0x2000:
break;
-
default:
txrom_write(offset, data);
break;
@@ -488,33 +493,18 @@ void nes_txsrom_device::write_h(offs_t offset, uint8_t data)
iNES: mapper 119
- In MESS: Supported. It also uses mmc3_irq.
+ In MAME: Supported. It also uses mmc3_irq.
-------------------------------------------------*/
-void nes_tqrom_device::set_chr( uint8_t chr, int chr_base, int chr_mask )
+void nes_tqrom_device::chr_cb(int start, int bank, int source)
{
- uint8_t chr_page = (m_latch & 0x80) >> 5;
- uint8_t src[6], mask[6];
-
- // TQROM ignores the source, base and mask set by the MMC3 and determines them based on vrom bank bits
- for (int i = 0; i < 6; i++)
- {
- src[i] = (m_mmc_vrom_bank[i] & 0x40) ? CHRRAM : CHRROM;
- mask[i] = (m_mmc_vrom_bank[i] & 0x40) ? 0x07 : 0x3f;
- }
-
- chr1_x(chr_page ^ 0, ((m_mmc_vrom_bank[0] & ~0x01) & mask[0]), src[0]);
- chr1_x(chr_page ^ 1, ((m_mmc_vrom_bank[0] | 0x01) & mask[0]), src[0]);
- chr1_x(chr_page ^ 2, ((m_mmc_vrom_bank[1] & ~0x01) & mask[1]), src[1]);
- chr1_x(chr_page ^ 3, ((m_mmc_vrom_bank[1] | 0x01) & mask[1]), src[1]);
- chr1_x(chr_page ^ 4, (m_mmc_vrom_bank[2] & mask[2]), src[2]);
- chr1_x(chr_page ^ 5, (m_mmc_vrom_bank[3] & mask[3]), src[3]);
- chr1_x(chr_page ^ 6, (m_mmc_vrom_bank[4] & mask[4]), src[4]);
- chr1_x(chr_page ^ 7, (m_mmc_vrom_bank[5] & mask[5]), src[5]);
+ if (BIT(bank, 6))
+ chr1_x(start, bank & 0x07, CHRRAM);
+ else
+ chr1_x(start, bank & 0x3f, CHRROM);
}
-
/*-------------------------------------------------
NES-QJ board (MMC3 variant for US 2-in-1 Nintendo cart
@@ -524,19 +514,19 @@ void nes_tqrom_device::set_chr( uint8_t chr, int chr_base, int chr_mask )
-------------------------------------------------*/
-void nes_qj_device::write_m(offs_t offset, uint8_t data)
+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);
- m_prg_base = BIT(data, 0) << 4;
- m_prg_mask = 0x0f;
- m_chr_base = BIT(data, 0) << 7;
- m_chr_mask = 0x7f;
- set_prg(m_prg_base, m_prg_mask);
- set_chr(m_chr_source, m_chr_base, m_chr_mask);
+ if (BIT(m_wram_protect, 7) && !BIT(m_wram_protect, 6))
+ {
+ m_prg_base = BIT(data, 0) << 4;
+ m_chr_base = BIT(data, 0) << 7;
+ set_prg(m_prg_base, m_prg_mask);
+ set_chr(m_chr_source, m_chr_base, m_chr_mask);
+ }
}
-
/*-------------------------------------------------
PAL-ZZ board (MMC3 variant for European 3-in-1 Nintendo cart
@@ -544,17 +534,22 @@ void nes_qj_device::write_m(offs_t offset, uint8_t data)
iNES: mapper 37
+ TODO: this board apparently only resets to the menu
+ screen on systems with a CIC (the outer PRG lines
+ are somehow tied to the CIC's reset line).
+
-------------------------------------------------*/
-void nes_zz_device::write_m(offs_t offset, uint8_t data)
+void nes_zz_device::write_m(offs_t offset, u8 data)
{
- uint8_t mmc_helper = data & 0x07;
- LOG_MMC(("zz write_m, offset: %04x, data: %02x\n", offset, data));
+ LOG("zz write_m, offset: %04x, data: %02x\n", offset, data);
- m_prg_base = (BIT(mmc_helper, 2) << 4) | (((mmc_helper & 0x03) == 0x03) ? 0x08 : 0);
- m_prg_mask = (mmc_helper << 1) | 0x07;
- m_chr_base = BIT(mmc_helper, 2) << 7;
- m_chr_mask = 0x7f;
- set_prg(m_prg_base, m_prg_mask);
- set_chr(m_chr_source, m_chr_base, m_chr_mask);
+ if (BIT(m_wram_protect, 7) && !BIT(m_wram_protect, 6))
+ {
+ m_prg_base = ((data & 0x04) | (data & (data << 1) & 0x02)) << 2;
+ m_prg_mask = (m_prg_mask == 0x10) ? 0x0f : 0x07;
+ m_chr_base = BIT(data, 2) << 7;
+ set_prg(m_prg_base, m_prg_mask);
+ set_chr(m_chr_source, m_chr_base, m_chr_mask);
+ }
}
diff --git a/src/devices/bus/nes/mmc3.h b/src/devices/bus/nes/mmc3.h
index 5ef9e8dbdaa..5e231787d71 100644
--- a/src/devices/bus/nes/mmc3.h
+++ b/src/devices/bus/nes/mmc3.h
@@ -23,7 +23,7 @@ public:
virtual void prg_cb(int start, int bank);
virtual void chr_cb(int start, int bank, int source);
- virtual void hblank_irq(int scanline, int vblank, int blanked) override;
+ virtual void hblank_irq(int scanline, bool vblank, bool blanked) override;
virtual void pcb_reset() override;
protected:
@@ -40,6 +40,7 @@ protected:
// are there MMC3 clones which need more regs?
uint16_t m_mmc_prg_bank[4];
uint16_t m_mmc_vrom_bank[8]; // a few clones need more than the 6 banks used by base MMC3 (e.g. waixing_g)
+ uint8_t m_mmc_mirror;
int m_prg_base, m_prg_mask; // MMC3 based multigame carts select a block of banks by using these (and then act like normal MMC3),
int m_chr_base, m_chr_mask; // while MMC3 and clones (mapper 118 & 119) simply set them as 0 and 0xff resp.
@@ -70,7 +71,7 @@ public:
protected:
// device-level overrides
- virtual void device_start() override;
+ virtual void device_start() override ATTR_COLD;
int m_wram_enable;
uint8_t m_mmc6_reg;
@@ -86,14 +87,15 @@ class nes_txsrom_device : public nes_txrom_device
{
public:
// construction/destruction
- nes_txsrom_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
+ nes_txsrom_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock);
- // device-level overrides
- virtual void write_h(offs_t offset, uint8_t data) override;
- virtual void chr_cb(int start, int bank, int source) override;
+ virtual void write_h(offs_t offset, u8 data) override;
protected:
- void set_mirror();
+ // construction/destruction
+ nes_txsrom_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, u32 clock);
+
+ virtual void set_chr(u8 chr, int chr_base, int chr_mask) override;
};
@@ -103,10 +105,13 @@ class nes_tqrom_device : public nes_txrom_device
{
public:
// construction/destruction
- nes_tqrom_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
+ nes_tqrom_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock);
+
+ virtual void chr_cb(int start, int bank, int source) override;
protected:
- virtual void set_chr( uint8_t chr, int chr_base, int chr_mask ) override;
+ // construction/destruction
+ nes_tqrom_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, u32 clock);
};
@@ -116,10 +121,10 @@ class nes_qj_device : public nes_txrom_device
{
public:
// construction/destruction
- nes_qj_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
+ nes_qj_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock);
+
+ virtual void write_m(offs_t offset, u8 data) override;
- // device-level overrides
- virtual void write_m(offs_t offset, uint8_t data) override;
virtual void pcb_reset() override;
};
@@ -130,10 +135,10 @@ class nes_zz_device : public nes_txrom_device
{
public:
// construction/destruction
- nes_zz_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
+ nes_zz_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock);
+
+ virtual void write_m(offs_t offset, u8 data) override;
- // device-level overrides
- virtual void write_m(offs_t offset, uint8_t data) override;
virtual void pcb_reset() override;
};
diff --git a/src/devices/bus/nes/mmc3_clones.cpp b/src/devices/bus/nes/mmc3_clones.cpp
index 9be591c7d9f..0fc9b3c1c93 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"
//-------------------------------------------------
@@ -29,12 +29,15 @@
//-------------------------------------------------
DEFINE_DEVICE_TYPE(NES_NITRA, nes_nitra_device, "nes_nitra", "NES Cart Nitra PCB")
-DEFINE_DEVICE_TYPE(NES_KS7057, nes_ks7057_device, "nes_ks7057", "NES Cart KS-7057 PCB")
+DEFINE_DEVICE_TYPE(NES_BMW8544, nes_bmw8544_device, "nes_bmw8544", "NES Cart BMW8544 PCB")
+DEFINE_DEVICE_TYPE(NES_FS6, nes_fs6_device, "nes_fs6", "NES Cart Fight Street VI PCB")
DEFINE_DEVICE_TYPE(NES_SBROS11, nes_sbros11_device, "nes_smb11", "NES Cart SMB 11 PCB")
-DEFINE_DEVICE_TYPE(NES_MALISB, nes_malisb_device, "nes_malisb", "NES Cart Mali Spash Bomb PCB")
-DEFINE_DEVICE_TYPE(NES_FAMILY4646, nes_family4646_device, "nes_family4646", "NES Cart BMC-FAMILY04646 PCB")
+DEFINE_DEVICE_TYPE(NES_MALISB, nes_malisb_device, "nes_malisb", "NES Cart Mali Splash Bomb PCB")
+DEFINE_DEVICE_TYPE(NES_FAMILY4646, nes_family4646_device, "nes_family4646", "NES Cart BMC-FAMILY4646 PCB")
DEFINE_DEVICE_TYPE(NES_PIKAY2K, nes_pikay2k_device, "nes_pikay2k", "NES Cart PIKACHU Y2K PCB")
DEFINE_DEVICE_TYPE(NES_8237, nes_8237_device, "nes_8237", "NES Cart UNL-8237 PCB")
+DEFINE_DEVICE_TYPE(NES_8237A, nes_8237a_device, "nes_8237a", "NES Cart UNL-8237A PCB")
+DEFINE_DEVICE_TYPE(NES_158B, nes_158b_device, "nes_158b", "NES Cart UNL-158B PCB")
DEFINE_DEVICE_TYPE(NES_SG_LIONK, nes_sglionk_device, "nes_sglionk", "NES Cart SuperGame Lion King PCB")
DEFINE_DEVICE_TYPE(NES_SG_BOOG, nes_sgboog_device, "nes_sgbooger", "NES Cart SuperGame BoogerMan PCB")
DEFINE_DEVICE_TYPE(NES_KASING, nes_kasing_device, "nes_kasing", "NES Cart Kasing PCB")
@@ -45,48 +48,141 @@ DEFINE_DEVICE_TYPE(NES_TXC_TW, nes_txc_tw_device, "nes_txc_tw",
DEFINE_DEVICE_TYPE(NES_KOF97, nes_kof97_device, "nes_kof97", "NES Cart KoF 97 PCB")
DEFINE_DEVICE_TYPE(NES_KOF96, nes_kof96_device, "nes_kof96", "NES Cart KoF 96 PCB")
DEFINE_DEVICE_TYPE(NES_SF3, nes_sf3_device, "nes_sf3", "NES Cart Super Fighter III PCB")
+DEFINE_DEVICE_TYPE(NES_COCOMA, nes_cocoma_device, "nes_cocoma", "NES Cart Cocoma Core Pro PCB")
DEFINE_DEVICE_TYPE(NES_GOUDER, nes_gouder_device, "nes_gouder", "NES Cart Gouder PCB")
DEFINE_DEVICE_TYPE(NES_SA9602B, nes_sa9602b_device, "nes_sa9602b", "NES Cart SA-9602B PCB")
DEFINE_DEVICE_TYPE(NES_SACHEN_SHERO, nes_sachen_shero_device, "nes_shero", "NES Cart Street Hero PCB")
-//DEFINE_DEVICE_TYPE(NES_A9746, nes_a9746_device, "nes_bmc_a9746", "NES Cart A-9746 PCB")
-
-DEFINE_DEVICE_TYPE(NES_FK23C, nes_fk23c_device, "nes_kf23c", "NES Cart KF23C PCB")
-DEFINE_DEVICE_TYPE(NES_FK23CA, nes_fk23ca_device, "nes_kf23ca", "NES Cart KF23CA PCB")
+DEFINE_DEVICE_TYPE(NES_SACHEN_ZGDH, nes_sachen_zgdh_device, "nes_zgdh", "NES Cart Zhongguo Daheng PCB")
+DEFINE_DEVICE_TYPE(NES_A9746, nes_a9746_device, "nes_bmc_a9746", "NES Cart A-9746 PCB")
+
+DEFINE_DEVICE_TYPE(NES_A88S1, nes_a88s1_device, "nes_a88s1", "NES Cart BMC A88S-1 PCB")
+DEFINE_DEVICE_TYPE(NES_BMC_EL86XC, nes_bmc_el86xc_device, "nes_bmc_el86xc", "NES Cart BMC EL860947C/EL861121C PCB")
+DEFINE_DEVICE_TYPE(NES_FK23C, nes_fk23c_device, "nes_fk23c", "NES Cart FK23C PCB")
+DEFINE_DEVICE_TYPE(NES_FK23CA, nes_fk23ca_device, "nes_fk23ca", "NES Cart FK23CA PCB")
+DEFINE_DEVICE_TYPE(NES_NT639, nes_nt639_device, "nes_nt639", "NES Cart NT-639 PCB")
+DEFINE_DEVICE_TYPE(NES_RESETTXROM, nes_resettxrom_device, "nes_resettxrom", "NES Cart BMC RESET-TXROM PCB")
DEFINE_DEVICE_TYPE(NES_S24IN1SC03, nes_s24in1sc03_device, "nes_s24in1c03", "NES Cart Super 24 in 1 SC-03 PCB")
+DEFINE_DEVICE_TYPE(NES_TECHLINE9IN1, nes_tech9in1_device, "nes_tech9in1", "NES Cart Techline 9 in 1 PCB")
+DEFINE_DEVICE_TYPE(NES_BMC_5IN1, nes_bmc_5in1_device, "nes_bmc_5in1", "NES Cart BMC 5 in 1 1993 Copyright PCB")
+DEFINE_DEVICE_TYPE(NES_BMC_8IN1, nes_bmc_8in1_device, "nes_bmc_8in1", "NES Cart BMC GRM070 8 in 1 PCB")
DEFINE_DEVICE_TYPE(NES_BMC_15IN1, nes_bmc_15in1_device, "nes_bmc_15in1", "NES Cart BMC 15 in 1 PCB")
DEFINE_DEVICE_TYPE(NES_BMC_SBIG7, nes_bmc_sbig7_device, "nes_bmc_sbig7", "NES Cart BMC Super BIG 7 in 1 PCB")
DEFINE_DEVICE_TYPE(NES_BMC_HIK8, nes_bmc_hik8_device, "nes_bmc_hik8", "NES Cart BMC HIK 8 in 1 PCB")
+DEFINE_DEVICE_TYPE(NES_BMC_JY208, nes_bmc_jy208_device, "nes_bmc_jy208", "NES Cart BMC JY-208 PCB")
+DEFINE_DEVICE_TYPE(NES_BMC_JY302, nes_bmc_jy302_device, "nes_bmc_jy302", "NES Cart BMC JY-302 PCB")
+DEFINE_DEVICE_TYPE(NES_BMC_KC885, nes_bmc_kc885_device, "nes_bmc_kc885", "NES Cart BMC KC885 PCB")
+DEFINE_DEVICE_TYPE(NES_BMC_SFC12, nes_bmc_sfc12_device, "nes_bmc_sfc12", "NES Cart BMC SFC-12 PCB")
DEFINE_DEVICE_TYPE(NES_BMC_HIK4, nes_bmc_hik4_device, "nes_bmc_hik4", "NES Cart BMC HIK 4 in 1 PCB")
-DEFINE_DEVICE_TYPE(NES_BMC_MARIO7IN1, nes_bmc_mario7in1_device, "nes_bmc_mario7in1", "NES Cart BMC Mario 7 in 1 PCB")
+DEFINE_DEVICE_TYPE(NES_BMC_F15, nes_bmc_f15_device, "nes_bmc_f15", "NES Cart BMC F-15 PCB")
+DEFINE_DEVICE_TYPE(NES_BMC_F600, nes_bmc_f600_device, "nes_bmc_f600", "NES Cart BMC F600 PCB")
+DEFINE_DEVICE_TYPE(NES_BMC_GN45, nes_bmc_gn45_device, "nes_bmc_gn45", "NES Cart BMC GN-45 PCB")
DEFINE_DEVICE_TYPE(NES_BMC_GOLD7IN1, nes_bmc_gold7in1_device, "nes_bmc_gold7in1", "NES Cart BMC Golden 7 in 1 PCB")
-DEFINE_DEVICE_TYPE(NES_BMC_GC6IN1, nes_bmc_gc6in1_device, "nes_bmc_gc6in1", "NES Cart BMC Golden Card 6 in 1 PCB")
+DEFINE_DEVICE_TYPE(NES_BMC_K3006, nes_bmc_k3006_device, "nes_bmc_k3006", "NES Cart BMC K-3006 PCB")
+DEFINE_DEVICE_TYPE(NES_BMC_K3033, nes_bmc_k3033_device, "nes_bmc_k3033", "NES Cart BMC K-3033 PCB")
+DEFINE_DEVICE_TYPE(NES_BMC_L6IN1, nes_bmc_l6in1_device, "nes_bmc_l6in1", "NES Cart BMC L6IN1 PCB")
+DEFINE_DEVICE_TYPE(NES_BMC_00202650, nes_bmc_00202650_device, "nes_bmc_00202650", "NES Cart BMC 00202650 PCB")
DEFINE_DEVICE_TYPE(NES_BMC_411120C, nes_bmc_411120c_device, "nes_bmc_411120c", "NES Cart BMC 411120C PCB")
+DEFINE_DEVICE_TYPE(NES_BMC_810305C, nes_bmc_810305c_device, "nes_bmc_810305c", "NES Cart BMC 81-03-05-C PCB")
+DEFINE_DEVICE_TYPE(NES_BMC_820720C, nes_bmc_820720c_device, "nes_bmc_820720c", "NES Cart BMC 820720C PCB")
DEFINE_DEVICE_TYPE(NES_BMC_830118C, nes_bmc_830118c_device, "nes_bmc_830118c", "NES Cart BMC 830118C PCB")
+DEFINE_DEVICE_TYPE(NES_BMC_830832C, nes_bmc_830832c_device, "nes_bmc_830832c", "NES Cart BMC 830832C PCB")
+DEFINE_DEVICE_TYPE(NES_BMC_YY841101C, nes_bmc_yy841101c_device, "nes_bmc_yy841101c", "NES Cart BMC YY841101C PCB")
+DEFINE_DEVICE_TYPE(NES_BMC_YY841155C, nes_bmc_yy841155c_device, "nes_bmc_yy841155c", "NES Cart BMC YY841155C PCB")
DEFINE_DEVICE_TYPE(NES_PJOY84, nes_pjoy84_device, "nes_pjoy84", "NES Cart Powerjoy 84 PCB")
-DEFINE_DEVICE_TYPE(NES_COOLBOY, nes_coolboy_device, "nes_coolboy", "NES Cart CoolBoy PCB")
+DEFINE_DEVICE_TYPE(NES_SMD133, nes_smd133_device, "nes_smd133", "NES Cart SMD133 PCB")
+
+
+INPUT_PORTS_START( sachen_shero )
+ PORT_START("JUMPER")
+ PORT_CONFNAME( 0x80, 0x00, "Title Screen" )
+ PORT_CONFSETTING( 0x00, "Street Heroes" )
+ PORT_CONFSETTING( 0x80, u8"\u4f8d\u9b42 (Shìhún)" ) // 侍魂
+INPUT_PORTS_END
+
+INPUT_PORTS_START( bmc_5in1 )
+ PORT_START("JUMPER")
+ PORT_CONFNAME( 0x01, 0x01, "Menu Type" )
+ PORT_CONFSETTING( 0x00, "20 in 1" )
+ PORT_CONFSETTING( 0x01, "5 in 1" )
+INPUT_PORTS_END
+
+INPUT_PORTS_START( bmc_f600 )
+ PORT_START("JUMPER")
+ PORT_CONFNAME( 0x80, 0x80, "Menu Type" )
+ PORT_CONFSETTING( 0x00, "Mario 67 in 1" )
+ PORT_CONFSETTING( 0x80, "Mario Party II (6 in 1)" )
+INPUT_PORTS_END
+
+INPUT_PORTS_START( bmc_kc885 )
+ PORT_START("JUMPER")
+ PORT_CONFNAME( 0x07, 0x07, "Menu Type" )
+ PORT_CONFSETTING( 0x00, "6000 in 1" )
+ PORT_CONFSETTING( 0x01, "400 in 1" )
+ PORT_CONFSETTING( 0x02, "800 in 1" )
+ PORT_CONFSETTING( 0x03, "5000 in 1" )
+ PORT_CONFSETTING( 0x04, "190 in 1" )
+ PORT_CONFSETTING( 0x05, "1000 in 1" )
+ PORT_CONFSETTING( 0x06, "2000 in 1" )
+ PORT_CONFSETTING( 0x07, "19 in 1" )
+INPUT_PORTS_END
+
+
+//-------------------------------------------------
+// input_ports - device-specific input ports
+//-------------------------------------------------
+ioport_constructor nes_sachen_shero_device::device_input_ports() const
+{
+ return INPUT_PORTS_NAME( sachen_shero );
+}
+
+ioport_constructor nes_bmc_5in1_device::device_input_ports() const
+{
+ return INPUT_PORTS_NAME( bmc_5in1 );
+}
-nes_nitra_device::nes_nitra_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
+ioport_constructor nes_bmc_f600_device::device_input_ports() const
+{
+ return INPUT_PORTS_NAME( bmc_f600 );
+}
+
+ioport_constructor nes_bmc_kc885_device::device_input_ports() const
+{
+ return INPUT_PORTS_NAME( bmc_kc885 );
+}
+
+
+
+//**************************************************************************
+// LIVE DEVICE
+//**************************************************************************
+
+nes_nitra_device::nes_nitra_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock)
: nes_txrom_device(mconfig, NES_NITRA, tag, owner, clock)
{
}
-nes_ks7057_device::nes_ks7057_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
- : nes_txrom_device(mconfig, NES_KS7057, tag, owner, clock)
+nes_bmw8544_device::nes_bmw8544_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock)
+ : nes_txrom_device(mconfig, NES_BMW8544, tag, owner, clock), m_reg(0)
+{
+}
+
+nes_fs6_device::nes_fs6_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock)
+ : nes_txrom_device(mconfig, NES_FS6, tag, owner, clock)
{
}
-nes_sbros11_device::nes_sbros11_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
+nes_sbros11_device::nes_sbros11_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock)
: nes_txrom_device(mconfig, NES_SBROS11, tag, owner, clock)
{
}
-nes_malisb_device::nes_malisb_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
+nes_malisb_device::nes_malisb_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock)
: nes_txrom_device(mconfig, NES_MALISB, tag, owner, clock)
{
}
-nes_family4646_device::nes_family4646_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
+nes_family4646_device::nes_family4646_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock)
: nes_txrom_device(mconfig, NES_FAMILY4646, tag, owner, clock)
{
}
@@ -96,33 +192,58 @@ nes_pikay2k_device::nes_pikay2k_device(const machine_config &mconfig, const char
{
}
-nes_8237_device::nes_8237_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
- : nes_txrom_device(mconfig, NES_8237, tag, owner, clock), m_cd_enable(0)
+nes_8237_device::nes_8237_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, u32 clock, u8 board)
+ : nes_txrom_device(mconfig, type, tag, owner, clock), m_board(board)
{
}
-nes_sglionk_device::nes_sglionk_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
- : nes_txrom_device(mconfig, NES_SG_LIONK, tag, owner, clock), m_reg(0), m_reg_enabled(0)
+nes_8237_device::nes_8237_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock)
+ : nes_8237_device(mconfig, NES_8237, tag, owner, clock, 0)
{
}
-nes_sgboog_device::nes_sgboog_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
- : nes_txrom_device(mconfig, NES_SG_BOOG, tag, owner, clock), m_mode(0)
+nes_8237a_device::nes_8237a_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock)
+ : nes_8237_device(mconfig, NES_8237A, tag, owner, clock, 1)
{
}
-nes_kasing_device::nes_kasing_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
- : nes_txrom_device(mconfig, NES_KASING, tag, owner, clock), m_reg(0)
+nes_158b_device::nes_158b_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock)
+ : nes_8237_device(mconfig, NES_158B, tag, owner, clock, 0)
{
}
-nes_kay_device::nes_kay_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
+nes_kasing_device::nes_kasing_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, u32 clock)
+ : nes_txrom_device(mconfig, type, tag, owner, clock), m_mmc3_mode(true)
+{
+}
+
+nes_kasing_device::nes_kasing_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock)
+ : nes_kasing_device(mconfig, NES_KASING, tag, owner, clock)
+{
+}
+
+nes_sglionk_device::nes_sglionk_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, u32 clock, u8 board)
+ : nes_kasing_device(mconfig, type, tag, owner, clock), m_board(board)
+{
+}
+
+nes_sglionk_device::nes_sglionk_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock)
+ : nes_sglionk_device(mconfig, NES_SG_LIONK, tag, owner, clock, 0)
+{
+}
+
+nes_sgboog_device::nes_sgboog_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock)
+ : nes_sglionk_device(mconfig, NES_SG_BOOG, tag, owner, clock, 1)
+{
+}
+
+nes_kay_device::nes_kay_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock)
: nes_txrom_device(mconfig, NES_KAY, tag, owner, clock), m_low_reg(0)
{
}
-nes_h2288_device::nes_h2288_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
- : nes_txrom_device(mconfig, NES_H2288, tag, owner, clock)
+nes_h2288_device::nes_h2288_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock)
+ : nes_txrom_device(mconfig, NES_H2288, tag, owner, clock), m_mmc3_mode(true)
{
}
@@ -141,8 +262,8 @@ nes_kof97_device::nes_kof97_device(const machine_config &mconfig, const char *ta
{
}
-nes_kof96_device::nes_kof96_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
- : nes_txrom_device(mconfig, NES_KOF96, tag, owner, clock)
+nes_kof96_device::nes_kof96_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock)
+ : nes_txrom_device(mconfig, NES_KOF96, tag, owner, clock), m_mmc3_mode(true)
{
}
@@ -151,6 +272,11 @@ nes_sf3_device::nes_sf3_device(const machine_config &mconfig, const char *tag, d
{
}
+nes_cocoma_device::nes_cocoma_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock)
+ : nes_txrom_device(mconfig, NES_COCOMA, tag, owner, clock)
+{
+}
+
nes_gouder_device::nes_gouder_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
: nes_txrom_device(mconfig, NES_GOUDER, tag, owner, clock)
{
@@ -161,15 +287,32 @@ nes_sa9602b_device::nes_sa9602b_device(const machine_config &mconfig, const char
{
}
-nes_sachen_shero_device::nes_sachen_shero_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
- : nes_txrom_device(mconfig, NES_SACHEN_SHERO, tag, owner, clock), m_reg(0)
+nes_sachen_shero_device::nes_sachen_shero_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock)
+ : nes_txrom_device(mconfig, NES_SACHEN_SHERO, tag, owner, clock)
+ , m_jumper(*this, "JUMPER")
+ , m_reg(0)
+{
+}
+
+nes_sachen_zgdh_device::nes_sachen_zgdh_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock)
+ : nes_txrom_device(mconfig, NES_SACHEN_ZGDH, tag, owner, clock), m_reg(0)
+{
+}
+
+nes_a9746_device::nes_a9746_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
+ : nes_txrom_device(mconfig, NES_A9746, tag, owner, clock)
+{
+}
+
+nes_a88s1_device::nes_a88s1_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock)
+ : nes_txrom_device(mconfig, NES_A88S1, tag, owner, clock)
{
}
-//nes_a9746_device::nes_a9746_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
-// : nes_txrom_device(mconfig, NES_A9746, tag, owner, clock)
-//{
-//}
+nes_bmc_el86xc_device::nes_bmc_el86xc_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock)
+ : nes_txrom_device(mconfig, NES_BMC_EL86XC, tag, owner, clock)
+{
+}
nes_fk23c_device::nes_fk23c_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock)
: nes_txrom_device(mconfig, type, tag, owner, clock), m_mmc_cmd1(0)
@@ -186,13 +329,39 @@ nes_fk23ca_device::nes_fk23ca_device(const machine_config &mconfig, const char *
{
}
+nes_nt639_device::nes_nt639_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock)
+ : nes_txrom_device(mconfig, NES_NT639, tag, owner, clock)
+{
+}
+
+nes_resettxrom_device::nes_resettxrom_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock)
+ : nes_txrom_device(mconfig, NES_RESETTXROM, tag, owner, clock), m_count(-1)
+{
+}
+
nes_s24in1sc03_device::nes_s24in1sc03_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
: nes_txrom_device(mconfig, NES_S24IN1SC03, tag, owner, clock)
{
}
-nes_bmc_15in1_device::nes_bmc_15in1_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
- : nes_txrom_device(mconfig, NES_BMC_15IN1, tag, owner, clock)
+nes_tech9in1_device::nes_tech9in1_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock)
+ : nes_txrom_device(mconfig, NES_TECHLINE9IN1, tag, owner, clock)
+{
+}
+
+nes_bmc_5in1_device::nes_bmc_5in1_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock)
+ : nes_txrom_device(mconfig, NES_BMC_5IN1, tag, owner, clock)
+ , m_jumper(*this, "JUMPER")
+{
+}
+
+nes_bmc_8in1_device::nes_bmc_8in1_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock)
+ : nes_txrom_device(mconfig, NES_BMC_8IN1, tag, owner, clock)
+{
+}
+
+nes_bmc_15in1_device::nes_bmc_15in1_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock)
+ : nes_txrom_device(mconfig, NES_BMC_15IN1, tag, owner, clock), m_jumper(0)
{
}
@@ -201,38 +370,116 @@ nes_bmc_sbig7_device::nes_bmc_sbig7_device(const machine_config &mconfig, const
{
}
-nes_bmc_hik8_device::nes_bmc_hik8_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
- : nes_txrom_device(mconfig, NES_BMC_HIK8, tag, owner, clock), m_count(0)
+nes_bmc_hik8_device::nes_bmc_hik8_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, u32 clock)
+ : nes_txrom_device(mconfig, type, tag, owner, clock), m_count(0)
+{
+}
+
+nes_bmc_hik8_device::nes_bmc_hik8_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock)
+ : nes_bmc_hik8_device(mconfig, NES_BMC_HIK8, tag, owner, clock)
+{
+}
+
+nes_bmc_jy208_device::nes_bmc_jy208_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock)
+ : nes_bmc_hik8_device(mconfig, NES_BMC_JY208, tag, owner, clock)
+{
+}
+
+nes_bmc_jy302_device::nes_bmc_jy302_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock)
+ : nes_bmc_hik8_device(mconfig, NES_BMC_JY302, tag, owner, clock)
+{
+}
+
+nes_bmc_kc885_device::nes_bmc_kc885_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock)
+ : nes_bmc_hik8_device(mconfig, NES_BMC_KC885, tag, owner, clock)
+ , m_jumper(*this, "JUMPER")
+{
+}
+
+nes_bmc_sfc12_device::nes_bmc_sfc12_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock)
+ : nes_bmc_hik8_device(mconfig, NES_BMC_SFC12, tag, owner, clock)
+{
+}
+
+nes_bmc_hik4_device::nes_bmc_hik4_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock)
+ : nes_txrom_device(mconfig, NES_BMC_HIK4, tag, owner, clock), m_mmc3_mode(true)
+{
+}
+
+nes_bmc_f15_device::nes_bmc_f15_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock)
+ : nes_txrom_device(mconfig, NES_BMC_F15, tag, owner, clock)
+{
+}
+
+nes_bmc_f600_device::nes_bmc_f600_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock)
+ : nes_txsrom_device(mconfig, NES_BMC_F600, tag, owner, clock)
+ , m_jumper(*this, "JUMPER")
+ , m_reg(0)
+{
+}
+
+nes_bmc_gn45_device::nes_bmc_gn45_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock)
+ : nes_txrom_device(mconfig, NES_BMC_GN45, tag, owner, clock), m_lock(false)
+{
+}
+
+nes_bmc_gold7in1_device::nes_bmc_gold7in1_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock)
+ : nes_txrom_device(mconfig, NES_BMC_GOLD7IN1, tag, owner, clock), m_lock(false)
{
}
-nes_bmc_hik4_device::nes_bmc_hik4_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
- : nes_txrom_device(mconfig, NES_BMC_HIK4, tag, owner, clock)
+nes_bmc_k3006_device::nes_bmc_k3006_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock)
+ : nes_txrom_device(mconfig, NES_BMC_K3006, tag, owner, clock)
{
}
-nes_bmc_mario7in1_device::nes_bmc_mario7in1_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
- : nes_txrom_device(mconfig, NES_BMC_MARIO7IN1, tag, owner, clock), m_reg_written(0)
+nes_bmc_k3033_device::nes_bmc_k3033_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock)
+ : nes_txrom_device(mconfig, NES_BMC_K3033, tag, owner, clock), m_mmc3_mode(false)
{
}
-nes_bmc_gold7in1_device::nes_bmc_gold7in1_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
- : nes_txrom_device(mconfig, NES_BMC_GOLD7IN1, tag, owner, clock), m_reg_written(0)
+nes_bmc_l6in1_device::nes_bmc_l6in1_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock)
+ : nes_txrom_device(mconfig, NES_BMC_L6IN1, tag, owner, clock), m_reg(0)
{
}
-nes_bmc_gc6in1_device::nes_bmc_gc6in1_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
- : nes_txrom_device(mconfig, NES_BMC_GC6IN1, tag, owner, clock)
+nes_bmc_00202650_device::nes_bmc_00202650_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock)
+ : nes_txrom_device(mconfig, NES_BMC_00202650, tag, owner, clock), m_mmc3_mode(false)
{
}
-nes_bmc_411120c_device::nes_bmc_411120c_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
+nes_bmc_411120c_device::nes_bmc_411120c_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock)
: nes_txrom_device(mconfig, NES_BMC_411120C, tag, owner, clock), m_reg(0)
{
}
-nes_bmc_830118c_device::nes_bmc_830118c_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
- : nes_txrom_device(mconfig, NES_BMC_830118C, tag, owner, clock), m_reg(0)
+nes_bmc_810305c_device::nes_bmc_810305c_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock)
+ : nes_txsrom_device(mconfig, NES_BMC_810305C, tag, owner, clock), m_outer(0)
+{
+}
+
+nes_bmc_820720c_device::nes_bmc_820720c_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock)
+ : nes_txrom_device(mconfig, NES_BMC_820720C, tag, owner, clock), m_reg(0)
+{
+}
+
+nes_bmc_830118c_device::nes_bmc_830118c_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock)
+ : nes_txrom_device(mconfig, NES_BMC_830118C, tag, owner, clock)
+{
+}
+
+nes_bmc_830832c_device::nes_bmc_830832c_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock)
+ : nes_txrom_device(mconfig, NES_BMC_830832C, tag, owner, clock)
+{
+}
+
+nes_bmc_yy841101c_device::nes_bmc_yy841101c_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock)
+ : nes_txrom_device(mconfig, NES_BMC_YY841101C, tag, owner, clock)
+{
+}
+
+nes_bmc_yy841155c_device::nes_bmc_yy841155c_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock)
+ : nes_txrom_device(mconfig, NES_BMC_YY841155C, tag, owner, clock)
{
}
@@ -241,17 +488,37 @@ nes_pjoy84_device::nes_pjoy84_device(const machine_config &mconfig, const char *
{
}
-nes_coolboy_device::nes_coolboy_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
- : nes_txrom_device(mconfig, NES_COOLBOY, tag, owner, clock)
+nes_smd133_device::nes_smd133_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock)
+ : nes_txrom_device(mconfig, NES_SMD133, tag, owner, clock)
{
}
+
+void nes_bmw8544_device::device_start()
+{
+ mmc3_start();
+ save_item(NAME(m_reg));
+}
+
+void nes_bmw8544_device::pcb_reset()
+{
+ m_reg = 0;
+ mmc3_common_initialize(0x0f, 0xff, 0);
+}
+
+void nes_family4646_device::device_start()
+{
+ mmc3_start();
+ save_item(NAME(m_reg));
+}
+
void nes_family4646_device::pcb_reset()
{
- m_chr_source = m_vrom_chunks ? CHRROM : CHRRAM;
+ std::fill(std::begin(m_reg), std::end(m_reg), 0x00);
mmc3_common_initialize(0x1f, 0xff, 0);
+ set_nt_mirroring(PPU_MIRROR_HORZ); // Space Shuttle on CB-4035 doesn't set mirroring bit. Whether this cart is hard-wired to reset correctly to horizontal mirroring is not clear.
}
void nes_pikay2k_device::device_start()
@@ -262,8 +529,6 @@ void nes_pikay2k_device::device_start()
void nes_pikay2k_device::pcb_reset()
{
- m_chr_source = m_vrom_chunks ? CHRROM : CHRRAM;
-
m_reg[0] = 0xff;
m_reg[1] = 0;
mmc3_common_initialize(0xff, 0xff, 0);
@@ -273,70 +538,42 @@ void nes_8237_device::device_start()
{
mmc3_start();
save_item(NAME(m_reg));
- save_item(NAME(m_cd_enable));
}
void nes_8237_device::pcb_reset()
{
- m_chr_source = m_vrom_chunks ? CHRROM : CHRRAM;
+ mmc3_common_initialize(0x1f, 0xff, 0);
m_reg[0] = 0;
- m_reg[1] = 0;
+ m_reg[1] = 0x0f;
m_reg[2] = 0;
- m_cd_enable = 0;
- mmc3_common_initialize(0xff, 0xff, 0);
-}
-
-void nes_sglionk_device::device_start()
-{
- mmc3_start();
- save_item(NAME(m_reg));
- save_item(NAME(m_reg_enabled));
+ update_banks();
}
-void nes_sglionk_device::pcb_reset()
+void nes_158b_device::device_start()
{
- m_chr_source = m_vrom_chunks ? CHRROM : CHRRAM;
-
- m_reg = m_reg_enabled = 0;
- mmc3_common_initialize(0xff, 0xff, 0);
+ nes_8237_device::device_start();
+ save_item(NAME(m_prot));
}
-void nes_sgboog_device::device_start()
+void nes_158b_device::pcb_reset()
{
- mmc3_start();
- save_item(NAME(m_reg));
- save_item(NAME(m_mode));
-}
-
-void nes_sgboog_device::pcb_reset()
-{
- m_chr_source = m_vrom_chunks ? CHRROM : CHRRAM;
-
- m_mode = 0x04;
- m_reg[0] = 0x00;
- m_reg[1] = 0xff;
- m_reg[2] = 0;
- mmc3_common_initialize(0x1f, 0xff, 0);
- set_prg(m_prg_base, m_prg_mask);
- set_chr(m_chr_source, m_chr_base, m_chr_mask);
+ nes_8237_device::pcb_reset();
+ m_prot = 7; // Blood of Jurassic needs this row of prot_table
}
void nes_kasing_device::device_start()
{
mmc3_start();
- save_item(NAME(m_reg));
+ save_item(NAME(m_mmc3_mode));
}
void nes_kasing_device::pcb_reset()
{
- m_chr_source = m_vrom_chunks ? CHRROM : CHRRAM;
-
- m_reg = 0;
+ m_mmc3_mode = true;
mmc3_common_initialize(0xff, 0xff, 0);
}
-
void nes_kay_device::device_start()
{
mmc3_start();
@@ -346,27 +583,22 @@ void nes_kay_device::device_start()
void nes_kay_device::pcb_reset()
{
- m_chr_source = m_vrom_chunks ? CHRROM : CHRRAM;
-
- memset(m_reg, 0, sizeof(m_reg));
+ std::fill(std::begin(m_reg), std::end(m_reg), 0x00);
m_low_reg = 0;
- mmc3_common_initialize(0xff, 0xff, 0);
+ mmc3_common_initialize(0x1f, 0xff, 0);
}
void nes_h2288_device::device_start()
{
mmc3_start();
- save_item(NAME(m_reg));
+ save_item(NAME(m_mmc3_mode));
}
void nes_h2288_device::pcb_reset()
{
- m_chr_source = m_vrom_chunks ? CHRROM : CHRRAM;
-
- m_reg[0] = 0;
- m_reg[1] = 0;
- mmc3_common_initialize(0xff, 0xff, 0);
+ m_mmc3_mode = true;
+ mmc3_common_initialize(0x3f, 0xff, 0);
}
void nes_6035052_device::device_start()
@@ -377,25 +609,27 @@ void nes_6035052_device::device_start()
void nes_6035052_device::pcb_reset()
{
- m_chr_source = m_vrom_chunks ? CHRROM : CHRRAM;
mmc3_common_initialize(0xff, 0xff, 0);
-
m_prot = 0;
}
void nes_kof96_device::device_start()
{
mmc3_start();
- save_item(NAME(m_reg));
+ save_item(NAME(m_mmc3_mode));
}
void nes_kof96_device::pcb_reset()
{
- m_chr_source = m_vrom_chunks ? CHRROM : CHRRAM;
- memset(m_reg, 0, sizeof(m_reg));
+ m_mmc3_mode = true;
mmc3_common_initialize(0xff, 0xff, 0);
}
+void nes_cocoma_device::pcb_reset()
+{
+ mmc3_common_initialize(0x0f, 0x7f, 0);
+}
+
void nes_gouder_device::device_start()
{
mmc3_start();
@@ -404,8 +638,7 @@ void nes_gouder_device::device_start()
void nes_gouder_device::pcb_reset()
{
- m_chr_source = m_vrom_chunks ? CHRROM : CHRRAM;
- memset(m_reg, 0, sizeof(m_reg));
+ std::fill(std::begin(m_reg), std::end(m_reg), 0x00);
mmc3_common_initialize(0xff, 0xff, 0);
}
@@ -418,8 +651,6 @@ void nes_sa9602b_device::device_start()
void nes_sa9602b_device::pcb_reset()
{
- m_chr_source = m_vrom_chunks ? CHRROM : CHRRAM;
-
m_reg = 0;
m_prg_chip = 0;
mmc3_common_initialize(0x1ff, 0xff, 0); // 1.5MB of PRG-ROM, no CHR-ROM but 32K CHR-RAM
@@ -433,10 +664,57 @@ void nes_sachen_shero_device::device_start()
void nes_sachen_shero_device::pcb_reset()
{
- m_chr_source = m_vrom_chunks ? CHRROM : CHRRAM;
+ m_reg = 0;
+ mmc3_common_initialize(0xff, 0xff, 0);
+}
+
+void nes_sachen_zgdh_device::device_start()
+{
+ mmc3_start();
+ save_item(NAME(m_reg));
+}
+
+void nes_sachen_zgdh_device::pcb_reset()
+{
+ assert(m_vram.size() >= 0x2000);
m_reg = 0;
- mmc3_common_initialize(0xff, 0x1ff, 0);
+ mmc3_common_initialize(0x1f, 0x7f, 0);
+}
+
+void nes_a9746_device::device_start()
+{
+ mmc3_start();
+ save_item(NAME(m_reg));
+}
+
+void nes_a9746_device::pcb_reset()
+{
+ m_reg[0] = 0;
+ m_reg[1] = 0;
+ m_reg[2] = 0;
+ mmc3_common_initialize(0x7f, 0xff, 0);
+}
+
+void nes_a88s1_device::device_start()
+{
+ mmc3_start();
+ save_item(NAME(m_reg));
+
+ // power-on values for registers; they don't seem to change with soft reset
+ m_reg[0] = 0x80;
+ m_reg[1] = 0x82;
+}
+
+void nes_a88s1_device::pcb_reset()
+{
+ mmc3_common_initialize(0x1f, 0xff, 0);
+ update_banks();
+}
+
+void nes_bmc_el86xc_device::pcb_reset()
+{
+ mmc3_common_initialize((m_outer_prg_size >> 3) - 1, 0x7f, 0);
}
void nes_fk23c_device::device_start()
@@ -448,8 +726,6 @@ void nes_fk23c_device::device_start()
void nes_fk23c_device::pcb_reset()
{
- m_chr_source = m_vrom_chunks ? CHRROM : CHRRAM;
-
m_mmc_cmd1 = 0;
m_reg[0] = 4;
m_reg[1] = 0xff;
@@ -458,13 +734,10 @@ void nes_fk23c_device::pcb_reset()
mmc3_common_initialize(0xff, 0xff, 0);
fk23c_set_prg();
fk23c_set_chr();
-
}
void nes_fk23ca_device::pcb_reset()
{
- m_chr_source = m_vrom_chunks ? CHRROM : CHRRAM;
-
m_mmc_cmd1 = 0;
m_reg[0] = m_reg[1] = m_reg[2] = m_reg[3] = 0;
m_reg[4] = m_reg[5] = m_reg[6] = m_reg[7] = 0xff;
@@ -473,6 +746,29 @@ void nes_fk23ca_device::pcb_reset()
fk23c_set_chr();
}
+void nes_nt639_device::pcb_reset()
+{
+ mmc3_common_initialize(0x0f, 0xff, 0);
+}
+
+// These reset-based PCBs are emulated here with no additional handlers
+void nes_resettxrom_device::device_start()
+{
+ mmc3_start();
+ save_item(NAME(m_count));
+}
+
+void nes_resettxrom_device::pcb_reset()
+{
+ mmc3_common_initialize((m_outer_prg_size >> 3) - 1, m_outer_chr_size - 1, 0);
+
+ m_count = (m_count + 1) & 3;
+ m_prg_base = m_count << (31 - count_leading_zeros_32(m_outer_prg_size) - 3); // << std::countr_zero(m_outer_prg_size) - 3; in C++20
+ m_chr_base = m_count << (31 - count_leading_zeros_32(m_outer_chr_size)); // << std::countr_zero(m_outer_chr_size); in C++20
+ set_prg(m_prg_base, m_prg_mask);
+ set_chr(m_chr_source, m_chr_base, m_chr_mask);
+}
+
void nes_s24in1sc03_device::device_start()
{
mmc3_start();
@@ -481,26 +777,43 @@ void nes_s24in1sc03_device::device_start()
void nes_s24in1sc03_device::pcb_reset()
{
- m_chr_source = m_vrom_chunks ? CHRROM : CHRRAM;
-
m_reg[0] = 0x24;
m_reg[1] = 0x9f;
m_reg[2] = 0;
mmc3_common_initialize(0xff, 0xff, 0);
}
-void nes_bmc_15in1_device::pcb_reset()
+void nes_tech9in1_device::device_start()
{
- m_chr_source = m_vrom_chunks ? CHRROM : CHRRAM;
+ mmc3_start();
+ save_item(NAME(m_reg));
+}
+void nes_tech9in1_device::pcb_reset()
+{
+ m_reg[0] = m_reg[1] = m_reg[2] = 0;
+ mmc3_common_initialize(0x1f, 0xff, 0);
+}
+
+void nes_bmc_5in1_device::pcb_reset()
+{
+ mmc3_common_initialize(0x0f, 0x7f, 0);
+ prg32(0);
+}
+
+void nes_bmc_8in1_device::pcb_reset()
+{
+ mmc3_common_initialize(0x0f, 0x7f, 0);
+ prg32(0);
+}
+
+void nes_bmc_15in1_device::pcb_reset()
+{
mmc3_common_initialize(0x1f, 0xff, 0);
- m_prg_base = 0x10; // this board has a diff prg_base
- set_prg(m_prg_base, m_prg_mask);
}
void nes_bmc_sbig7_device::pcb_reset()
{
- m_chr_source = m_vrom_chunks ? CHRROM : CHRRAM;
mmc3_common_initialize(0x0f, 0x7f, 0);
}
@@ -513,64 +826,122 @@ void nes_bmc_hik8_device::device_start()
void nes_bmc_hik8_device::pcb_reset()
{
- m_chr_source = m_vrom_chunks ? CHRROM : CHRRAM;
+ set_nt_mirroring(PPU_MIRROR_VERT); // necessary since some boards/games don't reliably set mirroring (Rockman 1 on mc_s13 at least)
m_count = 0;
- memset(m_reg, 0, sizeof(m_reg));
+ std::fill(std::begin(m_reg), std::end(m_reg), 0x00);
mmc3_common_initialize(0x3f, 0xff, 0);
}
+void nes_bmc_kc885_device::pcb_reset()
+{
+ nes_bmc_hik8_device::pcb_reset();
+ m_prg_mask = 0x1f;
+ set_prg(m_prg_base, m_prg_mask);
+}
+
+void nes_bmc_hik4_device::device_start()
+{
+ mmc3_start();
+ save_item(NAME(m_mmc3_mode));
+}
+
void nes_bmc_hik4_device::pcb_reset()
{
- m_chr_source = m_vrom_chunks ? CHRROM : CHRRAM;
+ m_mmc3_mode = true;
mmc3_common_initialize(0x0f, 0x7f, 0);
}
-void nes_bmc_mario7in1_device::device_start()
+void nes_bmc_f15_device::pcb_reset()
+{
+ mmc3_common_initialize(0x1f, 0xff, 0);
+ prg16_89ab(0);
+ prg16_cdef(0);
+}
+
+void nes_bmc_f600_device::device_start()
{
mmc3_start();
- save_item(NAME(m_reg_written));
+ save_item(NAME(m_reg));
+}
+
+void nes_bmc_f600_device::pcb_reset()
+{
+ m_reg = 0;
+ mmc3_common_initialize(0x1f, 0x7f, 0);
}
-void nes_bmc_mario7in1_device::pcb_reset()
+void nes_bmc_gn45_device::device_start()
{
- m_chr_source = m_vrom_chunks ? CHRROM : CHRRAM;
+ mmc3_start();
+ save_item(NAME(m_lock));
+}
- m_reg_written = 0;
- mmc3_common_initialize(0x1f, 0xff, 0);
+void nes_bmc_gn45_device::pcb_reset()
+{
+ m_lock = false;
+ mmc3_common_initialize(0x0f, 0x7f, 0);
}
void nes_bmc_gold7in1_device::device_start()
{
mmc3_start();
- save_item(NAME(m_reg_written));
+ save_item(NAME(m_lock));
}
void nes_bmc_gold7in1_device::pcb_reset()
{
- m_chr_source = m_vrom_chunks ? CHRROM : CHRRAM;
-
- m_reg_written = 0;
+ m_lock = false;
mmc3_common_initialize(0x1f, 0xff, 0);
}
-void nes_bmc_gc6in1_device::device_start()
+void nes_bmc_k3006_device::pcb_reset()
+{
+ mmc3_common_initialize(0x0f, 0x7f, 0);
+ prg16_89ab(0);
+ prg16_cdef(0);
+}
+
+void nes_bmc_k3033_device::device_start()
+{
+ mmc3_start();
+ save_item(NAME(m_mmc3_mode));
+}
+
+void nes_bmc_k3033_device::pcb_reset()
+{
+ m_mmc3_mode = false;
+ mmc3_common_initialize(0x0f, 0x7f, 0);
+ prg16_89ab(0);
+ prg16_cdef(0);
+}
+
+void nes_bmc_l6in1_device::device_start()
{
mmc3_start();
save_item(NAME(m_reg));
}
-void nes_bmc_gc6in1_device::pcb_reset()
+void nes_bmc_l6in1_device::pcb_reset()
{
- m_chr_source = m_vrom_chunks ? CHRROM : CHRRAM;
+ m_reg = 0;
+ mmc3_common_initialize(0x0f, 0x07, 0);
+}
- m_reg[0] = 0x00;
- m_reg[1] = 0xff;
- m_reg[2] = 0x03;
- m_reg[3] = 0;
- mmc3_common_initialize(0xff, 0xff, 0);
- set_prg(m_prg_base, m_prg_mask);
- set_chr(m_chr_source, m_chr_base, m_chr_mask);
+void nes_bmc_00202650_device::device_start()
+{
+ mmc3_start();
+ save_item(NAME(m_mmc3_mode));
+}
+
+void nes_bmc_00202650_device::pcb_reset()
+{
+ m_mmc3_mode = false;
+ mmc3_common_initialize(0x0f, 0x7f, 0);
+
+ // PCB has an extra 32KB boot menu chip, only the menu uses the CHRRAM
+ prg32((m_prg_chunks >> 1) - 1);
+ chr8(0, CHRRAM);
}
void nes_bmc_411120c_device::device_start()
@@ -581,24 +952,59 @@ void nes_bmc_411120c_device::device_start()
void nes_bmc_411120c_device::pcb_reset()
{
- m_chr_source = m_vrom_chunks ? CHRROM : CHRRAM;
-
m_reg = 0;
- mmc3_common_initialize(0x7f, 0x7f, 0);
+ mmc3_common_initialize(0x0f, 0x7f, 0);
}
-void nes_bmc_830118c_device::device_start()
+void nes_bmc_810305c_device::device_start()
+{
+ mmc3_start();
+ save_item(NAME(m_outer));
+}
+
+void nes_bmc_810305c_device::pcb_reset()
+{
+ m_outer = 0;
+ mmc3_common_initialize(0x1f, 0x7f, 0);
+}
+
+void nes_bmc_820720c_device::device_start()
{
mmc3_start();
save_item(NAME(m_reg));
}
+void nes_bmc_820720c_device::pcb_reset()
+{
+ m_reg = 0;
+ mmc3_common_initialize(0x0f, 0xff, 0);
+}
+
void nes_bmc_830118c_device::pcb_reset()
{
- m_chr_source = m_vrom_chunks ? CHRROM : CHRRAM;
+ mmc3_common_initialize(0x0f, 0x7f, 0);
+}
- m_reg = 0;
- mmc3_common_initialize(0x7f, 0x7f, 0);
+void nes_bmc_830832c_device::pcb_reset()
+{
+ mmc3_common_initialize(0x1f, 0xff, 0);
+}
+
+void nes_bmc_yy841101c_device::pcb_reset()
+{
+ mmc3_common_initialize(0x0f, 0x7f, 0);
+}
+
+void nes_bmc_yy841155c_device::device_start()
+{
+ mmc3_start();
+ save_item(NAME(m_reg));
+}
+
+void nes_bmc_yy841155c_device::pcb_reset()
+{
+ m_reg[0] = m_reg[1];
+ mmc3_common_initialize(0x0f, 0x7f, 0);
}
void nes_pjoy84_device::device_start()
@@ -609,13 +1015,23 @@ void nes_pjoy84_device::device_start()
void nes_pjoy84_device::pcb_reset()
{
- m_chr_source = m_vrom_chunks ? CHRROM : CHRRAM;
-
- memset(m_reg, 0, sizeof(m_reg));
+ std::fill(std::begin(m_reg), std::end(m_reg), 0x00);
set_base_mask();
mmc3_common_initialize(m_prg_mask, m_chr_mask, 0);
}
+void nes_smd133_device::device_start()
+{
+ mmc3_start();
+ save_item(NAME(m_reg));
+}
+
+void nes_smd133_device::pcb_reset()
+{
+ std::fill(std::begin(m_reg), std::end(m_reg), 0x00);
+ mmc3_common_initialize(0x3f, 0xff, 0);
+}
+
/*-------------------------------------------------
@@ -626,42 +1042,79 @@ void nes_pjoy84_device::pcb_reset()
Bootleg Board by Nitra
- Games: Time Diver Avenger
+ Games: Queen Bee, Time Diver Avenger
- This acts basically like a MMC3 with different use of write
- address.
+ MMC3 clone with A10 tied to what is normally A0 and
+ data instead coming from the lower address lines.
iNES: mapper 250
- In MESS: Supported.
+ In MAME: Supported.
+
+ -------------------------------------------------*/
+
+void nes_nitra_device::write_h(offs_t offset, u8 data)
+{
+ LOG("nitra write_h, offset: %04x, data: %02x\n", offset, data);
+
+ txrom_write((offset & 0x6000) | BIT(offset, 10), offset);
+}
+
+/*-------------------------------------------------
+
+ Board BMW8544
+
+ Games: Dragon Fighter (Flying Star)
+
+ MMC3 clone with poorly understood PRG/CHR banking.
+
+ NES 2.0: mapper 292
+
+ In MAME: Not supported.
-------------------------------------------------*/
-void nes_nitra_device::write_h(offs_t offset, uint8_t data)
+void nes_bmw8544_device::set_prg(int prg_base, int prg_mask)
{
- LOG_MMC(("nitra write_h, offset: %04x, data: %02x\n", offset, data));
+ nes_txrom_device::set_prg(prg_base, prg_mask);
+ prg8_89(m_reg);
+}
+
+u8 nes_bmw8544_device::read_m(offs_t offset)
+{
+ LOGMASKED(LOG_HIFREQ, "bmw8544 read_m, offset: %04x\n", offset);
- txrom_write((offset & 0x6000) | ((offset & 0x400) >> 10), offset & 0xff);
+ // CHR banking may be done by reads in this address range
+
+ return nes_txrom_device::read_m(offset);
+}
+
+void nes_bmw8544_device::write_m(offs_t offset, u8 data)
+{
+ LOG("bmw8544 write_m, offset: %04x, data: %02x\n", offset, data);
+ m_reg = data;
+ prg8_89(data);
}
/*-------------------------------------------------
- Board UNL-KS7057
+ Board UNL-FS6
Games: Street Fighter VI / Fight Street VI
MMC3 clone (identical, but for switched address lines)
- In MESS: Supported
+ iNES: mapper 196 alt?
+
+ In MAME: Supported.
-------------------------------------------------*/
-void nes_ks7057_device::write_h(offs_t offset, uint8_t data)
+void nes_fs6_device::write_h(offs_t offset, u8 data)
{
- LOG_MMC(("ks7057 write_h, offset: %04x, data: %02x\n", offset, data));
+ LOG("fs6 write_h, offset: %04x, data: %02x\n", offset, data);
- offset = (BIT(offset, 0) << 1) | BIT(offset, 1) | (offset & ~0x03);
- txrom_write(offset, data);
+ txrom_write(bitswap<2>(offset, 0, 1) | (offset & ~0x03), data);
}
/*-------------------------------------------------
@@ -675,15 +1128,15 @@ void nes_ks7057_device::write_h(offs_t offset, uint8_t data)
iNES: mapper 196
- In MESS: Supported.
+ In MAME: Supported.
-------------------------------------------------*/
-void nes_sbros11_device::write_h(offs_t offset, uint8_t 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) | ((offset & 0x04) >> 2), data);
+ txrom_write((offset & 0x6000) | BIT(offset, 2), data);
}
/*-------------------------------------------------
@@ -695,30 +1148,30 @@ void nes_sbros11_device::write_h(offs_t offset, uint8_t data)
This is very similar to mapper 196, but with additional
data bit swap.
- In MESS: Supported.
+ NES 2.0: mapper 325
+
+ In MAME: Supported.
-------------------------------------------------*/
void nes_malisb_device::prg_cb(int start, int bank)
{
- bank = (bank & 3) | ((bank & 8) >> 1) | ((bank & 4) << 1);
+ bank = bitswap<4>(bank, 2, 3, 1, 0);
prg8_x(start, bank);
}
void nes_malisb_device::chr_cb(int start, int bank, int source)
{
- bank = (bank & 0xdd) | ((bank & 0x20) >> 4) | ((bank & 2) << 4);
+ bank = bitswap<8>(bank, 7, 6, 1, 4, 3, 2, 5, 0);
chr1_x(start, bank, source);
}
-void nes_malisb_device::write_h(offs_t offset, uint8_t data)
+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);
- if (offset > 0x4000)
- txrom_write((offset & 0xfffe) | ((offset & 0x04) >> 2) | ((offset & 0x08) >> 3), data);
- else
- txrom_write((offset & 0xfffe) | ((offset & 0x08) >> 3), data);
+ offset = (offset & 0x6000) | BIT(offset, 3) | (BIT(offset, 14) & BIT(offset, 2));
+ txrom_write(offset, data);
}
/*-------------------------------------------------
@@ -726,31 +1179,62 @@ void nes_malisb_device::write_h(offs_t offset, uint8_t data)
BMC-FAMILY-4646B
Known Boards: Unknown Multigame Bootleg Board (4646B)
- Games: 2 in 1 - Family Kid & Aladdin 4
+ Games: 2 in 1 - Family Kid & Aladdin 4, various multicarts.
- MMC3 clone
+ MMC3 clone with banking for multigame menu.
iNES: mapper 134
- In MESS: Supported.
+ In MAME: Preliminary supported.
+
+ TODO: There are unknown writes to the unused reg 3,
+ though it seems only 0x00 is written. Next, some
+ carts have solder pad setting readable at 0x8000.
+ Lastly, YH-4103 doesn't soft reset cleanly like
+ the other carts, but does this happen on hardware?
-------------------------------------------------*/
-void nes_family4646_device::write_m(offs_t offset, uint8_t data)
+void nes_family4646_device::prg_cb(int start, int bank)
{
- LOG_MMC(("family4646 write_m, offset: %04x, data: %02x\n", offset, data));
-
- if (offset == 0x01)
+ if (!BIT(m_reg[1], 7)) // MMC3 mode
+ nes_txrom_device::prg_cb(start, bank);
+ else if (start == 0) // NROM mode, only uses MMC3's $8000 bank
{
- m_prg_base = (data & 0x02) << 4;
- m_prg_mask = 0x1f;
- m_chr_base = (data & 0x20) << 3;
- m_chr_mask = 0xff;
- set_prg(m_prg_base, m_prg_mask);
- set_chr(m_chr_source, m_chr_base, m_chr_mask);
+ if (BIT(m_reg[1], 3))
+ {
+ prg16_89ab(bank & ~0x01);
+ prg16_cdef(bank & ~0x01);
+ }
+ else
+ prg32(bank & ~0x03);
}
}
+void nes_family4646_device::write_m(offs_t offset, u8 data)
+{
+ LOG("family4646 write_m, offset: %04x, data: %02x\n", offset, data);
+
+ int reg = offset & 0x03;
+ if (!BIT(m_reg[0], 7)) // lock bit
+ m_reg[reg] = data;
+ else if (reg == 2) // final two bits of reg 2 respond regardless
+ m_reg[reg] = (m_reg[reg] & ~0x03) | (data & 0x03);
+ else
+ return;
+
+ m_prg_base = (m_reg[1] & 0x03) << 4;
+ m_prg_mask = 0x1f >> BIT(m_reg[1], 2);
+ set_prg(m_prg_base, m_prg_mask);
+
+ m_chr_base = (m_reg[1] & 0x30) << 3;
+ m_chr_mask = 0xff >> BIT(m_reg[1], 6);
+ if (BIT(m_reg[0], 3)) // CNROM-like mode
+ chr8(m_chr_base >> 3 | (m_reg[2] & (m_chr_mask >> 3)), m_chr_source);
+ else // MMC3 mode
+ set_chr(m_chr_source, m_chr_base, m_chr_mask);
+}
+
/*-------------------------------------------------
BTL-PIKACHUY2K
@@ -759,13 +1243,13 @@ void nes_family4646_device::write_m(offs_t offset, uint8_t 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)
{
@@ -775,6 +1259,7 @@ void nes_pikay2k_device::write_h(offs_t offset, uint8_t data)
case 0x2000:
m_reg[0] = 0;
+ [[fallthrough]];
default:
txrom_write(offset, data);
break;
@@ -784,382 +1269,265 @@ 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]);
}
/*-------------------------------------------------
- Board UNL-8237
+ Board UNL-8237, UNL-8237A
- Games: Pocahontas 2
+ Games: Pocahontas 2, MK3, various multicarts
- MMC3 clone
+ MMC3 clone with register and address scrambling and
+ a few extra banking modes by writing 0x5000-0x5fff.
- In MESS: Supported
+ iNES: mapper 215
- -------------------------------------------------*/
+ In MAME: Preliminary supported.
-void nes_8237_device::prg_cb(int start, int bank)
-{
- if (!(m_reg[0] & 0x80))
- prg8_x(start, bank);
-}
+ TODO: Lion King crashes after the first level in mc_9king.
+ Also in mc_9king Lion King, Somari and Aladdin all reset
+ to Aladdin instead of the menu.
-void nes_8237_device::chr_cb(int start, int bank, int source)
-{
- bank |= ((m_reg[1] << 6) & 0x100);
- chr1_x(start, bank, source);
-}
+ -------------------------------------------------*/
-void nes_8237_device::write_l(offs_t offset, uint8_t data)
+void nes_8237_device::update_banks()
{
- LOG_MMC(("unl_8237 write_l, offset: %04x, data: %02x\n", offset, data));
- offset += 0x100;
+ int a17 = BIT(m_reg[0], 6);
+ m_chr_base = m_board ? (m_reg[1] & 0x0e) << 7 : (m_reg[1] & 0x0c) << 6;
+ m_chr_base |= (BIT(m_reg[1], 5) & a17) << 7;
+ m_chr_mask = 0xff >> a17;
+ set_chr(m_chr_source, m_chr_base, m_chr_mask);
- if (offset == 0x1000)
- {
- m_reg[0] = data;
- if (m_reg[0] & 0x80)
- {
- if (m_reg[0] & 0x20)
- prg32((m_reg[0] & 0x0f) >> 1);
- else
- {
- prg16_89ab(m_reg[0] & 0x1f);
- prg16_cdef(m_reg[0] & 0x1f);
- }
- }
- else
- set_prg(m_prg_base, m_prg_mask);
- }
+ m_prg_base = m_board ? bitswap<3>(m_reg[1], 3, 1, 0) : m_reg[1] & 0x03;
+ m_prg_base = m_prg_base << 5 | (m_reg[1] & (a17 << 4));
+ m_prg_mask = 0x1f >> a17;
- if (offset == 0x1001)
+ if (BIT(m_reg[0], 7))
{
- m_reg[1] = data;
- set_chr(m_chr_source, m_chr_base, m_chr_mask);
+ u8 bank = m_prg_base >> 1 | (m_reg[0] & (m_prg_mask >> 1));
+ u8 mode = BIT(m_reg[0], 5);
+ prg16_89ab(bank & ~mode);
+ prg16_cdef(bank | mode);
}
+ set_prg(m_prg_base, m_prg_mask);
+}
- if (offset == 0x1007)
- {
- m_reg[2] = data & 0x07; // this selects different permutations for addresses and regs (to be implemented)
- }
+void nes_8237_device::prg_cb(int start, int bank)
+{
+ if (!BIT(m_reg[0], 7))
+ nes_txrom_device::prg_cb(start, bank);
}
-void nes_8237_device::write_h(offs_t offset, uint8_t data)
+void nes_8237_device::write_l(offs_t offset, u8 data)
{
- static const uint8_t conv_table[8] = {0, 2, 6, 1, 7, 3, 4, 5};
- LOG_MMC(("unl_8237 write_h, offset: %04x, data: %02x\n", offset, data));
+ LOG("unl_8237 write_l, offset: %04x, data: %02x\n", offset, data);
+ offset += 0x100;
- switch (offset & 0x7000)
+ switch (offset & 0x1007)
{
- case 0x0000:
case 0x1000:
- set_nt_mirroring((data | (data >> 7)) & 0x01 ? PPU_MIRROR_HORZ : PPU_MIRROR_VERT);
+ case 0x1001:
+ m_reg[offset & 1] = data;
+ update_banks();
break;
-
- case 0x2000:
- case 0x3000:
- m_cd_enable = 1;
- data = (data & 0xc0) | conv_table[data & 0x07];
- txrom_write(0x0000, data);
+ case 0x1007:
+ m_reg[2] = data & 0x07;
break;
+ }
+}
- case 0x4000:
- case 0x5000:
- if (m_cd_enable)
- {
- m_cd_enable = 0;
- txrom_write(0x0001, data);
- }
- break;
+void nes_8237_device::write_h(offs_t offset, u8 data)
+{
+ LOG("unl_8237 write_h, offset: %04x, data: %02x\n", offset, data);
- case 0x6000:
- break;
+ static constexpr u8 reg_table[8][8] =
+ {
+ {0, 1, 2, 3, 4, 5, 6, 7},
+ {0, 2, 6, 1, 7, 3, 4, 5},
+ {0, 5, 4, 1, 7, 2, 6, 3},
+ {0, 6, 3, 7, 5, 2, 4, 1},
+ {0, 2, 5, 3, 6, 1, 7, 4},
+ {0, 1, 2, 3, 4, 5, 6, 7},
+ {0, 1, 2, 3, 4, 5, 6, 7},
+ {0, 1, 2, 3, 4, 5, 6, 7}
+ };
- case 0x7000:
- txrom_write(0x6001, data);
- txrom_write(0x4000, data);
- txrom_write(0x4001, data);
- break;
- }
+ static constexpr u16 addr_table[8][8] =
+ {
+ {0x8000, 0x8001, 0xa000, 0xa001, 0xc000, 0xc001, 0xe000, 0xe001},
+ {0xa001, 0xa000, 0x8000, 0xc000, 0x8001, 0xc001, 0xe000, 0xe001},
+ {0x8000, 0x8001, 0xa000, 0xa001, 0xc000, 0xc001, 0xe000, 0xe001},
+ {0xc001, 0x8000, 0x8001, 0xa000, 0xa001, 0xe001, 0xe000, 0xc000},
+ {0xa001, 0x8001, 0x8000, 0xc000, 0xa000, 0xc001, 0xe000, 0xe001},
+ {0x8000, 0x8001, 0xa000, 0xa001, 0xc000, 0xc001, 0xe000, 0xe001},
+ {0x8000, 0x8001, 0xa000, 0xa001, 0xc000, 0xc001, 0xe000, 0xe001},
+ {0x8000, 0x8001, 0xa000, 0xa001, 0xc000, 0xc001, 0xe000, 0xe001},
+ };
+
+ u16 addr = addr_table[m_reg[2]][bitswap<3>(offset, 14, 13, 0)];
+ if (addr == 0x8000)
+ data = (data & 0xc0) | reg_table[m_reg[2]][data & 0x07];
+ txrom_write(addr & 0x6001, data);
}
/*-------------------------------------------------
- Bootleg Board by Super Game
+ Board UNL-158B
- Games: The Lion King
+ Games: Blood of Jurassic, Super Hang-On
- MMC3 clone.
+ MMC3 clone that appears to be the same as the 8237
+ boards above with added protection reads at 0x5000.
- iNES: mapper 114
+ NES 2.0: mapper 258
- In MESS: Supported.
+ In MAME: Preliminary supported.
+
+ TODO: Sprites in BoJ can sometimes become a garbled
+ mess. Not sure if zapper hit detection is ok either,
+ or why it seems you can't shoot at times (reload?).
+ Super Hang-On is a hack of Rad Racer/Highway Star so
+ it has all the graphics issues those games have.
-------------------------------------------------*/
-void nes_sglionk_device::write_m(offs_t offset, uint8_t data)
+u8 nes_158b_device::read_l(offs_t offset)
{
- LOG_MMC(("sglionk write_m, offset: %04x, data: %02x\n", offset, data));
-
- m_reg = data;
+ LOG("unl_158b read_l, offset: %04x\n", offset);
- if (m_reg & 0x80)
+ static constexpr u8 prot_table[8][8] =
{
- prg16_89ab(data & 0x1f);
- prg16_cdef(data & 0x1f);
- }
- else
- set_prg(m_prg_base, m_prg_mask);
+ {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
+ {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x00},
+ {0x00, 0x00, 0x00, 0x00, 0x03, 0x04, 0x00, 0x00},
+ {0x00, 0x00, 0x00, 0x01, 0x00, 0x04, 0x05, 0x00},
+ {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
+ {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
+ {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
+ {0x00, 0x00, 0x00, 0x01, 0x02, 0x04, 0x0f, 0x00}
+ };
+
+ u8 temp = get_open_bus();
+
+ offset += 0x100;
+ if (offset >= 0x1000)
+ temp = (temp & 0xf0) | prot_table[m_prot][offset & 0x07];
+ return temp;
}
-void nes_sglionk_device::write_h(offs_t offset, uint8_t data)
+void nes_158b_device::write_l(offs_t offset, u8 data)
{
- static const uint8_t conv_table[8] = {0, 3, 1, 5, 6, 7, 2, 4};
- LOG_MMC(("sglionk write_h, offset: %04x, data: %02x\n", offset, data));
+ LOG("unl_158b write_l, offset: %04x, data: %02x\n", offset, data);
- if (offset < 0x6000)
- {
- switch (offset & 0x6000)
- {
- case 0x0000:
- set_nt_mirroring(BIT(data, 0) ? PPU_MIRROR_HORZ : PPU_MIRROR_VERT);
- break;
- case 0x2000:
- m_reg_enabled = 1;
- data = (data & 0xc0) | conv_table[data & 0x07];
- txrom_write(0x0000, data);
- break;
- case 0x4000:
- if (m_reg_enabled && (m_reg & 0x80) == 0)
- {
- m_reg_enabled = 0;
- txrom_write(0x0001, data);
- }
- break;
- }
- }
- else
+ switch ((offset + 0x100) & 0x1003)
{
- switch (offset & 0x03)
- {
- case 0x02:
- txrom_write(0x6000, data);
- break;
- case 0x03:
- txrom_write(0x6001, data);
- txrom_write(0x4000, data);
- txrom_write(0x4001, data);
- break;
- }
+ case 0x1002:
+ m_prot = data & 0x07;
+ break;
+ default:
+ nes_8237_device::write_l(offset, data);
+ break;
}
}
/*-------------------------------------------------
- Bootleg Board by Super Game
+ Bootleg Board by Kasing
- Games: Boogerman, Mortal Kombat III
+ Games: AV Jiu Ji Mahjong, Bao Qing Tian, Thunderbolt 2,
+ Shisen Mahjong 2, Garou Densetsu Special
- MMC3 clone. Also, it probably needs a hack to support both
- variants (Boogerman & MK3).
+ MMC3 clone with extra banking modes at 0x6000-0x7fff.
- iNES: mapper 215
+ iNES: mapper 115
- In MESS: Preliminary support.
+ In MAME: Supported.
-------------------------------------------------*/
-void nes_sgboog_device::prg_cb(int start, int bank)
-{
- if (!(m_reg[0] & 0x80)) // if this is != 0 we should never even arrive here
- {
- if (m_reg[1] & 0x08)
- bank = (bank & 0x1f) | 0x20;
- else
- bank = (bank & 0x0f) | (m_reg[1] & 0x10);
-
- prg8_x(start, bank);
- }
-}
-
-void nes_sgboog_device::chr_cb(int start, int bank, int source)
-{
- if ((m_reg[1] & 0x04))
- bank |= 0x100;
- else
- bank = (bank & 0x7f) | ((m_reg[1] & 0x10) << 3);
-
- chr1_x(start, bank, source);
-}
-
-void nes_sgboog_device::set_prg(int prg_base, int prg_mask)
+void nes_kasing_device::prg_cb(int start, int bank)
{
- if (m_reg[0] & 0x80)
- {
- prg16_89ab((m_reg[0] & 0xf0) | (m_reg[1] & 0x10));
- prg16_cdef((m_reg[0] & 0xf0) | (m_reg[1] & 0x10));
- }
- else
- {
- // here standard MMC3 bankswitch
- uint8_t prg_flip = (m_latch & 0x40) ? 2 : 0;
-
- prg_cb(0, prg_base | (m_mmc_prg_bank[0 ^ prg_flip] & prg_mask));
- prg_cb(1, prg_base | (m_mmc_prg_bank[1] & prg_mask));
- prg_cb(2, prg_base | (m_mmc_prg_bank[2 ^ prg_flip] & prg_mask));
- prg_cb(3, prg_base | (m_mmc_prg_bank[3] & prg_mask));
- }
+ if (m_mmc3_mode)
+ nes_txrom_device::prg_cb(start, bank);
}
-void nes_sgboog_device::write_l(offs_t offset, uint8_t data)
+void nes_kasing_device::write_m(offs_t offset, u8 data)
{
- LOG_MMC(("sgboog write_l, offset: %04x, data: %02x\n", offset, data));
- offset += 0x100;
+ LOG("kasing write_m, offset: %04x, data: %02x\n", offset, data);
- if (offset == 0x1000)
- {
- m_reg[0] = data;
- set_prg(m_prg_base, m_prg_mask);
- }
- else if (offset == 0x1001)
+ if (BIT(offset, 0))
{
- m_reg[1] = data;
+ m_chr_base = BIT(data, 0) << 8;
set_chr(m_chr_source, m_chr_base, m_chr_mask);
}
- else if (offset == 0x1007)
- {
- m_latch = 0;
- m_mode = data;
- set_prg(m_prg_base, m_prg_mask);
- set_chr(m_chr_source, m_chr_base, m_chr_mask);
- }
-}
-
-void nes_sgboog_device::write_m(offs_t offset, uint8_t data)
-{
- LOG_MMC(("sgboog write_m, offset: %04x, data: %02x\n", offset, data));
-
- if (offset == 0x0000)
- {
- m_reg[0] = data;
- set_prg(m_prg_base, m_prg_mask);
- }
- else if (offset == 0x0001)
- {
- m_reg[1] = data;
- set_chr(m_chr_source, m_chr_base, m_chr_mask);
- }
- else if (offset == 0x0007)
- {
- m_latch = 0;
- m_mode = data;
- set_prg(m_prg_base, m_prg_mask);
- set_chr(m_chr_source, m_chr_base, m_chr_mask);
- }
-}
-
-void nes_sgboog_device::write_h(offs_t offset, uint8_t data)
-{
- static const uint8_t conv_table[8] = {0,2,5,3,6,1,7,4};
- LOG_MMC(("sgboog write_h, offset: %04x, data: %02x\n", offset, data));
-
- if (m_mode)
+ else
{
- switch (offset & 0x6001)
+ m_mmc3_mode = !BIT(data, 7);
+ if (m_mmc3_mode)
+ set_prg(m_prg_base, m_prg_mask);
+ else
{
- case 0x0000:
- break;
-
- case 0x0001:
- if (m_reg[2] && ((m_reg[0] & 0x80) == 0 || (m_latch & 0x07) < 6)) // if we use the prg16 banks and cmd=6,7 DON'T enter!
- {
- m_reg[2] = 0;
- txrom_write(0x0001, data);
- }
- break;
-
- case 0x2000:
- data = (data & 0xc0) | conv_table[data & 0x07];
- m_reg[2] = 1;
- txrom_write(0x0000, data);
- break;
-
- case 0x4000:
- set_nt_mirroring(((data >> 7) | data) & 0x01 ? PPU_MIRROR_HORZ : PPU_MIRROR_VERT);
- break;
-
- case 0x4001:
- txrom_write(0x6001, data);
- break;
-
- case 0x6001:
- txrom_write(0x4000, data);
- txrom_write(0x4001, data);
- break;
-
- default:
- txrom_write(offset, data);
- break;
+ u8 bank = data & 0x0f;
+ u8 mode = BIT(data, 5);
+ prg16_89ab(bank & ~mode);
+ prg16_cdef(bank | mode);
}
}
- else
- txrom_write(offset, data);
}
/*-------------------------------------------------
- Bootleg Board by Kasing
+ Bootleg Boards by Super Game and Hosenkan
- Games: AV Jiu Ji Mahjong, Bao Qing Tian, Thunderbolt 2,
- Shisen Mahjong 2
+ Games: The Lion King, Aladdin, Boogerman, Pocohon,
+ Super Donkey Kong
- MMC3 clone
+ MMC3 clone with register and address scrambling and
+ a few extra banking modes by writing 0x6000-0x7fff.
+ This is the same as mapper 115 with scrambling.
- iNES: mapper 115
+ iNES: mapper 114 (and 182)
- In MESS: Supported
+ In MAME: Supported.
-------------------------------------------------*/
-void nes_kasing_device::prg_cb(int start, int bank)
+void nes_sglionk_device::write_h(offs_t offset, u8 data)
{
- if (BIT(m_reg, 7))
- prg32(m_reg >> 1);
- else
- prg8_x(start, bank);
-}
+ LOG("sglionk write_h, offset: %04x, data: %02x\n", offset, data);
-void nes_kasing_device::write_m(offs_t offset, uint8_t data)
-{
- LOG_MMC(("kasing write_m, offset: %04x, data: %02x\n", offset, data));
+ static constexpr u8 reg_table[2][8] =
+ {
+ {0, 3, 1, 5, 6, 7, 2, 4},
+ {0, 2, 5, 3, 6, 1, 7, 4}
+ };
- switch (offset & 0x01)
+ static constexpr u16 addr_table[2][8] =
{
- case 0x00:
- m_reg = data;
- set_prg(m_prg_base, m_prg_mask);
- break;
- case 0x01:
- m_chr_base = (data & 0x01) ? 0x100 : 0x000;
- set_chr(m_chr_source, m_chr_base, m_chr_mask);
- break;
- }
+ {0xa001, 0xa000, 0x8000, 0xc000, 0x8001, 0xc001, 0xe000, 0xe001},
+ {0xa001, 0x8001, 0x8000, 0xc001, 0xa000, 0xc000, 0xe000, 0xe001}
+ };
+
+ u16 addr = addr_table[m_board][bitswap<3>(offset, 14, 13, 0)];
+ if (addr == 0x8000)
+ data = (data & 0xc0) | reg_table[m_board][data & 0x07];
+ txrom_write(addr & 0x6001, data);
}
/*-------------------------------------------------
- Bootleg Board by Kay (for Panda Prince)
+ A9711/A9713 Bootleg Boards by Kay (for Panda Prince)
Games: The Panda Prince, Sonic 3d Blast 6, SFZ2 '97, YuYu '97
(and its title hack MK6), UMK3, Super Lion King 2
@@ -1168,137 +1536,89 @@ void nes_kasing_device::write_m(offs_t offset, uint8_t data)
iNES: mapper 121
- In MESS: Most game works, with some graphical issues.
+ In MAME: Supported.
+
+ TODO: Most of the fighting games have graphical issues
+ with backgrounds on some stages. Due to common timing
+ issue with PPU/MMC3? Super Lion King 2's title screen
+ is also inexplicably broken.
-------------------------------------------------*/
-void nes_kay_device::write_l(offs_t offset, uint8_t data)
+void nes_kay_device::write_l(offs_t offset, u8 data)
{
- LOG_MMC(("kay write_l, offset: %04x, data: %02x\n", offset, data));
- offset += 0x100;
+ LOG("kay write_l, offset: %04x, data: %02x\n", offset, data);
+ offset += 0x100;
if (offset >= 0x1000)
+ m_low_reg = data & 0x03;
+
+ if ((offset & 0x1180) == 0x1180) // only written by Super 3-in-1
{
- switch (data & 0x03)
- {
- case 0x00:
- case 0x01:
- m_low_reg = 0x83;
- break;
- case 0x02:
- m_low_reg = 0x42;
- break;
- case 0x03:
- m_low_reg = 0x00;
- break;
- }
+ m_prg_base = (data & 0x80) >> 2;
+ set_prg(m_prg_base, m_prg_mask);
+ m_chr_base = m_prg_base << 3;
+ set_chr(m_chr_source, m_chr_base, m_chr_mask);
}
}
-uint8_t nes_kay_device::read_l(offs_t offset)
+u8 nes_kay_device::read_l(offs_t offset)
{
- LOG_MMC(("kay read_l, offset: %04x\n", offset));
- offset += 0x100;
+ LOG("kay read_l, offset: %04x\n", offset);
+
+ static constexpr u8 prot_table[4] = {0x83, 0x83, 0x42, 0x00};
+ offset += 0x100;
if (offset >= 0x1000)
- return m_low_reg;
+ return prot_table[m_low_reg];
else
- return 0xff;
+ return get_open_bus();
}
-void nes_kay_device::update_regs()
+void nes_kay_device::chr_cb(int start, int bank, int source)
{
- switch (m_reg[5] & 0x3f)
- {
- case 0x20:
- case 0x29:
- case 0x2b:
- case 0x3f:
- m_reg[7] = 1;
- m_reg[1] = m_reg[6];
- break;
- case 0x26:
- m_reg[7] = 0;
- m_reg[1] = m_reg[6];
- break;
- case 0x2c:
- m_reg[7] = 1;
- if (m_reg[6])
- m_reg[1] = m_reg[6];
- break;
-
- case 0x28:
- m_reg[7] = 0;
- m_reg[2] = m_reg[6];
- break;
-
- case 0x2a:
- m_reg[7] = 0;
- m_reg[3] = m_reg[6];
- break;
-
- case 0x2f:
- break;
-
- default:
- m_reg[5] = 0;
- break;
- }
+ bank |= (m_latch << 1) & (start << 6) & 0x100;
+ chr1_x(start, bank, source);
}
-void nes_kay_device::prg_cb(int start, int bank)
+void nes_kay_device::set_prg(int prg_base, int prg_mask)
{
- if (m_reg[5] & 0x3f)
+ nes_txrom_device::set_prg(prg_base, prg_mask);
+
+ if (BIT(m_reg[4], 5))
{
- prg8_x(start, bank & 0x3f);
- prg8_ef(m_reg[1]);
- prg8_cd(m_reg[2]);
- prg8_ab(m_reg[3]);
+ prg8_ab(prg_base | m_reg[0]);
+ prg8_cd(prg_base | m_reg[1]);
+ prg8_ef(prg_base | m_reg[2]);
}
- else
- prg8_x(start, bank & 0x3f);
}
-void nes_kay_device::chr_cb(int start, int bank, int source)
+void nes_kay_device::write_h(offs_t offset, u8 data)
{
- uint8_t chr_page = (m_latch & 0x80) >> 5;
-
- if ((start & 0x04) == chr_page)
- bank |= 0x100;
-
- chr1_x(start, bank, source);
-}
+ LOG("kay write_h, offset: %04x, data: %02x\n", offset, data);
-void nes_kay_device::write_h(offs_t offset, uint8_t data)
-{
- LOG_MMC(("kay write_h, offset: %04x, data: %02x\n", offset, data));
+ txrom_write(offset, data);
switch (offset & 0x6003)
{
- case 0x0000:
- txrom_write(offset, data);
- set_prg(m_prg_base, m_prg_mask);
- break;
-
case 0x0001:
- m_reg[6] = (BIT(data, 0) << 5) | (BIT(data, 1) << 4) | (BIT(data, 2) << 3)
- | (BIT(data, 3) << 2) | (BIT(data, 4) << 1) | BIT(data, 5);
- if (!m_reg[7])
- update_regs();
- txrom_write(offset, data);
- set_prg(m_prg_base, m_prg_mask);
+ m_reg[3] = bitswap<6>(data, 0, 1, 2, 3, 4, 5);
+ switch (m_reg[4])
+ {
+ case 0x26:
+ case 0x28:
+ case 0x2a:
+ m_reg[(0x2a - m_reg[4]) / 2] = m_reg[3];
+ set_prg(m_prg_base, m_prg_mask);
+ break;
+ }
break;
-
case 0x0003:
- m_reg[5] = data;
- update_regs();
- txrom_write(0x0000, data);
+ m_reg[4] = data & 0x3f;
+ if (BIT(m_reg[4], 5) && m_reg[3])
+ m_reg[2] = m_reg[3];
set_prg(m_prg_base, m_prg_mask);
break;
-
- default:
- txrom_write(offset, data);
- break;
}
}
@@ -1306,66 +1626,49 @@ void nes_kay_device::write_h(offs_t offset, uint8_t data)
UNL-H2288
+ Games: Earthworm Jim 2, Ultimate Mortal Kombat 3
+
+ iNES: mapper 123
+
+ In MAME: Supported.
+
-------------------------------------------------*/
void nes_h2288_device::prg_cb(int start, int bank)
{
- if (!(m_reg[0] & 0x40))
- prg8_x(start, bank);
+ if (m_mmc3_mode)
+ nes_txrom_device::prg_cb(start, bank);
}
-void nes_h2288_device::write_l(offs_t offset, uint8_t data)
+void nes_h2288_device::write_l(offs_t offset, u8 data)
{
- LOG_MMC(("h2288 write_l, offset: %04x, data: %02x\n", offset, data));
- offset += 0x100;
+ LOG("h2288 write_l, offset: %04x, data: %02x\n", offset, data);
+ offset += 0x100;
if (offset >= 0x1800)
{
- m_reg[offset & 1] = data;
- if (m_reg[0] & 0x40)
- {
- uint8_t helper1 = (m_reg[0] & 0x05) | ((m_reg[0] >> 2) & 0x0a);
- uint8_t helper2 = BIT(m_reg[0], 1);
- prg16_89ab(helper1 & ~helper2);
- prg16_cdef(helper1 | helper2);
- }
- else
+ m_mmc3_mode = !BIT(data, 6);
+ if (m_mmc3_mode)
set_prg(m_prg_base, m_prg_mask);
- }
-}
-
-uint8_t nes_h2288_device::read_l(offs_t offset)
-{
- LOG_MMC(("h2288 read_l, offset: %04x\n", offset));
- offset += 0x100;
-
- if (offset >= 0x1000)
- {
- int helper = offset >> 8;
- if (offset & 1)
- return helper | 0x01;
else
- return helper ^ 0x01;
+ {
+ u8 bank = bitswap<4>(data, 5, 2, 3, 0);
+ u8 mode = BIT(data, 1);
+ prg16_89ab(bank & ~mode);
+ prg16_cdef(bank | mode);
+ }
}
-
- return 0;
}
-void nes_h2288_device::write_h(offs_t offset, uint8_t data)
+void nes_h2288_device::write_h(offs_t offset, u8 data)
{
- static const uint8_t conv_table[8] = {0, 3, 1, 5, 6, 7, 2, 4};
- LOG_MMC(("h2288 write_h, offset: %04x, data: %02x\n", offset, data));
+ LOG("h2288 write_h, offset: %04x, data: %02x\n", offset, data);
- switch (offset & 0x6001)
- {
- case 0x0000:
- txrom_write(0x0000, (data & 0xc0) | conv_table[data & 0x07]);
- break;
+ static constexpr u8 reg_table[8] = {0, 3, 1, 5, 6, 7, 2, 4};
- default:
- txrom_write(offset, data);
- break;
- }
+ if (!(offset & 0x6001))
+ data = (data & 0xc0) | reg_table[data & 0x07];
+ txrom_write(offset, data);
}
/*-------------------------------------------------
@@ -1374,13 +1677,13 @@ void nes_h2288_device::write_h(offs_t offset, uint8_t 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;
@@ -1388,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;
}
@@ -1402,185 +1705,102 @@ 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);
}
-/* writes to 0x8000-0xffff are like MMC3 but no PRG bankswitch (beacuse it is handled by low writes) */
+// writes to 0x8000-0xffff are like MMC3 but no PRG bankswitch (because it is handled by low writes)
void nes_txc_tw_device::prg_cb(int start, int bank)
{
- return;
}
/*-------------------------------------------------
Board UNL-KOF97
- Games: King of Fighters 97 (Rex Soft)
+ Games: King of Fighters 97 (Rex Soft), Boogerman II
MMC3 clone
- In MESS: Not working
+ In MAME: Supported.
-------------------------------------------------*/
-inline uint8_t kof97_unscramble( uint8_t data )
+void nes_kof97_device::write_h(offs_t offset, u8 data)
{
- return ((data >> 1) & 0x01) | ((data >> 4) & 0x02) | ((data << 2) & 0x04) | ((data >> 0) & 0xd8) | ((data << 3) & 0x20);
-}
+ LOG("kof97 write_h, offset: %04x, data: %02x\n", offset, data);
-void nes_kof97_device::write_h(offs_t offset, uint8_t data)
-{
- LOG_MMC(("kof97 write_h, offset: %04x, data: %02x\n", offset, data));
+ // unscramble address and data
+ offset = (offset & 0x6000) | BIT(offset, 12);
+ data = bitswap<8>(data, 7, 6, 2, 4, 3, 0, 5, 1);
- /* Addresses 0x9000, 0xa000, 0xd000 & 0xf000 behaves differently than MMC3 */
- if (offset == 0x1000)
- txrom_write(0x0001, kof97_unscramble(data));
- else if (offset == 0x2000)
- txrom_write(0x0000, kof97_unscramble(data));
- else if (offset == 0x5000)
- txrom_write(0x4001, kof97_unscramble(data));
- else if (offset == 0x7000)
- txrom_write(0x6001, kof97_unscramble(data));
- /* Other addresses behaves like MMC3, up to unscrambling data */
- else
- txrom_write(offset, kof97_unscramble(data));
+ txrom_write(offset, data);
}
/*-------------------------------------------------
Bootleg Board for KOF96
- Games: The King of Fighters 96, Sonic 3D Blast 6, Street
- Fighter Zero 2
+ Games: The King of Fighters 96, Street Fighter Zero 2
MMC3 clone
iNES: mapper 187
- In MESS: Preliminary Support.
+ In MAME: Supported.
-------------------------------------------------*/
void nes_kof96_device::prg_cb(int start, int bank)
{
- if (!(m_reg[0] & 0x80))
- prg8_x(start, bank);
+ if (m_mmc3_mode)
+ nes_txrom_device::prg_cb(start, bank);
}
void nes_kof96_device::chr_cb(int start, int bank, int source)
{
- uint8_t chr_page = (m_latch & 0x80) >> 5;
-
- if ((start & 0x04) == chr_page)
- bank |= 0x100;
-
+ bank |= (m_latch << 1) & (start << 6) & 0x100;
chr1_x(start, bank, source);
}
-void nes_kof96_device::write_l(offs_t offset, uint8_t data)
+void nes_kof96_device::write_l(offs_t offset, u8 data)
{
- uint8_t new_bank;
- LOG_MMC(("kof96 write_l, offset: %04x, data: %02x\n", offset, data));
- offset += 0x100;
+ LOG("kof96 write_l, offset: %04x, data: %02x\n", offset, data);
- if (offset == 0x1000)
+ offset += 0x100;
+ if ((offset & 0x1001) == 0x1000)
{
- m_reg[0] = data;
-
- if (m_reg[0] & 0x80)
- {
- new_bank = (m_reg[0] & 0x1f);
-
- if (m_reg[0] & 0x20)
- prg32(new_bank >> 2);
- else
- {
- prg16_89ab(new_bank);
- prg16_cdef(new_bank);
- }
- }
- else
+ m_mmc3_mode = !BIT(data, 7);
+ if (m_mmc3_mode)
set_prg(m_prg_base, m_prg_mask);
- }
-
- if (offset >= 0x1000)
- {
- switch (data & 0x03)
+ else
{
- case 0x00:
- case 0x01:
- m_reg[1] = 0x83;
- break;
- case 0x02:
- m_reg[1] = 0x42;
- break;
- case 0x03:
- m_reg[1] = 0x00;
- break;
+ u8 bank = BIT(data, 1, 4);
+ u8 mode = BIT(data, 5);
+ prg16_89ab(bank & ~mode);
+ prg16_cdef(bank | mode);
}
-
- }
-
- if (!m_reg[3] && offset > 0x1000)
- {
- m_reg[3] = 1;
- poke(0x4017, 0x40); // FIXME
}
}
-uint8_t nes_kof96_device::read_l(offs_t offset)
+u8 nes_kof96_device::read_l(offs_t offset)
{
- LOG_MMC(("kof96 read_l, offset: %04x\n", offset));
- offset += 0x100;
+ LOG("kof96 read_l, offset: %04x\n", offset);
- if (!(offset < 0x1000))
- return m_reg[1];
+ offset += 0x100;
+ if (offset >= 0x1000)
+ return 0x80; // unknown protection read, kof96 expects that MSB is set
else
return 0;
}
-void nes_kof96_device::write_h(offs_t offset, uint8_t data)
-{
- LOG_MMC(("kof96 write_h, offset: %04x, data: %02x\n", offset, data));
-
- switch (offset & 0x6003)
- {
- case 0x0000:
- m_reg[2] = 1;
- txrom_write(0x0000, data);
- break;
-
- case 0x0001:
- if (m_reg[2])
- txrom_write(0x0001, data);
- break;
-
- case 0x0002:
- break;
-
- case 0x0003:
- m_reg[2] = 0;
-
- if (data == 0x28)
- prg8_cd(0x17);
- else if (data == 0x2a)
- prg8_ab(0x0f);
- break;
-
- default:
- txrom_write(offset, data);
- break;
- }
-}
-
/*-------------------------------------------------
Bootleg Board for Super Fighter III
@@ -1589,7 +1809,7 @@ void nes_kof96_device::write_h(offs_t offset, uint8_t data)
iNES: mapper 197
- In MESS: Supported.
+ In MAME: Supported.
-------------------------------------------------*/
@@ -1603,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)
{
@@ -1631,6 +1851,35 @@ void nes_sf3_device::write_h(offs_t offset, uint8_t data)
/*-------------------------------------------------
+ Cocoma Core Pro Board
+
+ Games: BrilliantCom Cocoma Pack 1 and 2
+
+ MMC3 clone with an extra outer bank latch.
+
+ NES 2.0: mapper 516
+
+ In MAME: Supported.
+
+ -------------------------------------------------*/
+
+void nes_cocoma_device::write_h(offs_t offset, u8 data)
+{
+ LOG("cocoma write_h, offset: %04x, data: %02x\n", offset, data);
+
+ if (BIT(offset, 4))
+ {
+ m_prg_base = (offset & 0x03) << 4;
+ set_prg(m_prg_base, m_prg_mask);
+ m_chr_base = (offset & 0x0c) << 5;
+ set_chr(m_chr_source, m_chr_base, m_chr_mask);
+ }
+ else
+ txrom_write(offset, data);
+}
+
+/*-------------------------------------------------
+
Bootleg Board 37017 (?) by Gouder
Games: Street Fighter IV
@@ -1639,13 +1888,13 @@ void nes_sf3_device::write_h(offs_t offset, uint8_t data)
iNES: mapper 208
- In MESS: Preliminary Support.
+ In MAME: Preliminary Support.
-------------------------------------------------*/
-void nes_gouder_device::write_l(offs_t offset, uint8_t data)
+void nes_gouder_device::write_l(offs_t offset, u8 data)
{
- static const uint8_t conv_table[256] =
+ static constexpr u8 conv_table[256] =
{
0x59,0x59,0x59,0x59,0x59,0x59,0x59,0x59,0x59,0x49,0x19,0x09,0x59,0x49,0x19,0x09,
0x59,0x59,0x59,0x59,0x59,0x59,0x59,0x59,0x51,0x41,0x11,0x01,0x51,0x41,0x11,0x01,
@@ -1665,30 +1914,38 @@ void nes_gouder_device::write_l(offs_t offset, uint8_t 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);
- if (!(offset < 0x1700))
- m_reg[offset & 0x03] = data ^ conv_table[m_reg[4]];
- else if (!(offset < 0xf00))
- m_reg[4] = data;
- else if (!(offset < 0x700))
- prg32(((data >> 3) & 0x02) | (data & 0x01));
+ offset += 0x100;
+ switch (offset & 0x1800)
+ {
+ case 0x0800:
+ prg32(bitswap<2>(data, 4, 0));
+ set_nt_mirroring(BIT(data, 5) ? PPU_MIRROR_HORZ : PPU_MIRROR_VERT);
+ break;
+ case 0x1000:
+ m_reg[4] = data;
+ break;
+ case 0x1800:
+ m_reg[offset & 0x03] = data ^ conv_table[m_reg[4]];
+ break;
+ }
}
-uint8_t nes_gouder_device::read_l(offs_t offset)
+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);
- if (!(offset < 0x1700))
+ offset += 0x100;
+ if (offset >= 0x1800)
return m_reg[offset & 0x03];
- return 0x00;
+ return get_open_bus();
}
-/* writes to 0x8000-0xffff are like MMC3 but no PRG bankswitch (beacuse it is handled by low writes) */
+// writes to 0x8000-0xffff are like MMC3 but no PRG bankswitch (because it is handled by low writes)
void nes_gouder_device::prg_cb(int start, int bank)
{
- return;
}
@@ -1698,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
-------------------------------------------------*/
@@ -1724,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)
{
@@ -1733,7 +1990,7 @@ void nes_sa9602b_device::write_h(offs_t offset, uint8_t data)
break;
case 0x0001:
if ((m_reg & 7) < 6)
- m_prg_chip = (data & 0xc0) >> 6;
+ m_prg_chip = BIT(data, 6, 2);
set_prg(0, m_prg_mask);
break;
}
@@ -1747,24 +2004,23 @@ void nes_sa9602b_device::write_h(offs_t offset, uint8_t data)
Sachen boards used for Street Heroes
- in MESS: Very Preliminary support
+ NES 2.0: mapper 262
- -------------------------------------------------*/
+ In MAME: Supported.
+ -------------------------------------------------*/
-void nes_sachen_shero_device::chr_cb( int start, int bank, int source )
+void nes_sachen_shero_device::chr_cb(int start, int bank, int source)
{
- int shift = start < 2 ? 5 :
- start < 4 ? 6 :
- start < 6 ? 8 : 7;
+ static constexpr u8 shift[4] = {5, 6, 8, 7};
+
if (!BIT(m_reg, 6))
- chr1_x(start, ((m_reg << shift) & 0x100) | bank, source);
+ chr1_x(start, ((m_reg << shift[start >> 1]) & 0x100) | bank, source);
}
-
-void nes_sachen_shero_device::write_l(offs_t offset, uint8_t data)
+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)
@@ -1777,16 +2033,145 @@ void nes_sachen_shero_device::write_l(offs_t offset, uint8_t data)
}
}
-uint8_t nes_sachen_shero_device::read_l(offs_t offset)
+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)
+ return m_jumper->read();
+ else
+ return get_open_bus();
+}
+
+/*-------------------------------------------------
+
+ SACHEN-ZGDH
+
+ Sachen board used for Zhongguo Daheng
+
+ NES 2.0: mapper 512
+
+ In MAME: Supported.
+
+ -------------------------------------------------*/
+
+u8 nes_sachen_zgdh_device::nt_r(offs_t offset)
+{
+ if (m_reg == 1)
+ return m_vram[0x1000 + (offset & 0x0fff)];
+ else
+ return device_nes_cart_interface::nt_r(offset);
+}
+
+void nes_sachen_zgdh_device::nt_w(offs_t offset, u8 data)
+{
+ if (m_reg == 1)
+ m_vram[0x1000 + (offset & 0x0fff)] = data;
+ else
+ device_nes_cart_interface::nt_w(offset, data);
+}
+
+void nes_sachen_zgdh_device::set_chr(u8 chr, int chr_base, int chr_mask)
+{
+ if (m_reg <= 1)
+ {
+ chr = CHRROM;
+ m_chr_mask = 0x7f;
+ }
+ else
{
- // DSW read!
+ chr = CHRRAM;
+ m_chr_mask = 0x03;
+ }
+ nes_txrom_device::set_chr(chr, chr_base, m_chr_mask);
+}
+
+void nes_sachen_zgdh_device::write_l(offs_t offset, u8 data)
+{
+ LOG("zgdh write_l, offset: %04x, data: %02x\n", offset, data);
+
+ offset += 0x100;
+ if ((offset & 0x1100) == 0x0100)
+ {
+ m_reg = data & 0x03;
+ set_chr(m_chr_source, m_chr_base, m_chr_mask);
+ }
+}
+
+/*-------------------------------------------------
+
+ UNL-A9746
+
+ Games: Toy Story, Super 1997 4 in 1 (NT-8029)
+
+ MMC3 clone
+
+ iNES: mapper 219
+
+ Preliminary emulation based on Cah4e3's code
+
+ -------------------------------------------------*/
+
+void nes_a9746_device::update_banks(uint8_t value)
+{
+ uint8_t bank = bitswap<8>(value & 0x3c,7,6,0,1,2,3,4,5);
+
+ switch (m_reg[0])
+ {
+ case 0x26: prg8_89(bank); break;
+ case 0x25: prg8_ab(bank); break;
+ case 0x24: prg8_cd(bank); break;
+ case 0x23: prg8_ef(bank); break;
+ }
+
+ switch (m_reg[1])
+ {
+ case 0x08: case 0x0a: case 0x0c: case 0x0e:
+ case 0x10: case 0x12: case 0x14: case 0x16:
+ case 0x18: case 0x1a: case 0x1c: case 0x1e:
+ m_reg[2] = value << 4;
+ break;
+ case 0x09: chr1_0(m_reg[2] | (value >> 1), m_chr_source); break;
+ case 0x0b: chr1_1(m_reg[2] | (value >> 1) | 1, m_chr_source); break;
+ case 0x0d: chr1_2(m_reg[2] | (value >> 1), m_chr_source); break;
+ case 0x0f: chr1_3(m_reg[2] | (value >> 1) | 1, m_chr_source); break;
+ case 0x11: chr1_4(m_reg[2] | (value >> 1), m_chr_source); break;
+ case 0x15: chr1_5(m_reg[2] | (value >> 1), m_chr_source); break;
+ case 0x19: chr1_6(m_reg[2] | (value >> 1), m_chr_source); break;
+ case 0x1d: chr1_7(m_reg[2] | (value >> 1), m_chr_source); break;
+ }
+}
+
+void nes_a9746_device::write_h(offs_t offset, uint8_t data)
+{
+ LOG("unl_a9746 write_h, offset: %04x, data: %02x\n", offset, data);
+
+ switch (offset & 0x6003)
+ {
+ case 0x0000:
+ m_reg[1] = data;
+ m_reg[0] = 0;
+ break;
+ case 0x0001:
+ update_banks(data);
+ break;
+ case 0x0002:
+ m_reg[0] = data;
+ m_reg[1] = 0;
+ break;
+
+ case 0x0003:
+ case 0x2000:
+ case 0x2001:
+ case 0x2002:
+ case 0x2003:
+ break;
+
+ default:
+ txrom_write(offset, data);
+ break;
}
- return get_open_bus(); // open bus
}
@@ -1797,16 +2182,16 @@ uint8_t nes_sachen_shero_device::read_l(offs_t offset)
-------------------------------------------------*/
- /*-------------------------------------------------
+/*-------------------------------------------------
- Board BMC-FK23C
+ Board BMC-FK23C
- MMC3 clone
+ MMC3 clone
- In MESS: partially supported (still to sort initial banking
- for many games)
+ In MAME: partially supported (still to sort initial banking
+ for many games)
- -------------------------------------------------*/
+ -------------------------------------------------*/
#if 0
// alt version...
@@ -1851,7 +2236,7 @@ void nes_fk23c_device::chr_cb(int start, int bank, int source)
void nes_fk23c_device::fk23c_set_prg()
{
if ((m_reg[0] & 0x07) == 4)
- prg32((m_reg[1] & 0x7f) >> 1);
+ prg32(BIT(m_reg[1], 1, 6));
else if ((m_reg[0] & 0x07) == 3)
{
prg16_89ab(m_reg[1] & 0x7f);
@@ -1888,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)
@@ -1905,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)
{
@@ -1945,11 +2330,40 @@ void nes_fk23c_device::write_h(offs_t offset, uint8_t data)
/*-------------------------------------------------
+ BMC-NT-639
+
+ Unknown Bootleg Multigame Board
+ Games: 2 in 1 Mortal Kombat VI/VII
+
+ NES 2.0: mapper 291
+
+ In MAME: Supported.
+
+ -------------------------------------------------*/
+
+void nes_nt639_device::write_m(offs_t offset, u8 data)
+{
+ LOG("nt639 write_m, offset: %04x, data: %02x\n", offset, data);
+
+ if (BIT(data, 5))
+ prg32(bitswap<3>(data, 6, 2, 1));
+ else
+ {
+ m_prg_base = (data & 0x40) >> 2;
+ set_prg(m_prg_base, m_prg_mask);
+ }
+
+ m_chr_base = (data & 0x40) << 2;
+ set_chr(m_chr_source, m_chr_base, m_chr_mask);
+}
+
+/*-------------------------------------------------
+
Board BMC-SUPER24IN1SC03
Games: Super 24-in-1
- In MESS: Partially Supported
+ In MAME: Partially Supported
-------------------------------------------------*/
@@ -1973,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)
@@ -1998,30 +2412,147 @@ void nes_s24in1sc03_device::write_l(offs_t offset, uint8_t data)
/*-------------------------------------------------
- BMC-15IN1
+ BMC-TECHLINE9IN1
Unknown Bootleg Multigame Board
- Games: 3 in 1, 15 in 1
+ Games: 9 in 1
- iNES: mapper 205, MMC3 clone
+ NES 2.0: mapper 351
- In MESS: Supported.
+ In MAME: Supported.
-------------------------------------------------*/
-void nes_bmc_15in1_device::write_m(offs_t offset, uint8_t data)
+void nes_tech9in1_device::update_banks()
{
- LOG_MMC(("bmc_15in1 write_m, offset: %04x, data: %02x\n", offset, data));
-
- if (offset & 0x0800)
+ if (BIT(m_reg[2], 7)) // NROM mode
{
- m_prg_base = (data & 0x03) << 4;
- m_prg_mask = (data & 0x02) ? 0x0f : 0x1f;
- m_chr_base = (data & 0x03) << 7;
- m_chr_mask = (data & 0x02) ? 0x7f : 0xff;
+ u8 bank = m_reg[1] >> 2;
+ u8 mode = !BIT(m_reg[2], 6);
+ prg16_89ab(bank & ~mode);
+ prg16_cdef(bank | mode);
+ }
+ else // MMC3 mode
+ {
+ m_prg_base = (m_reg[1] & 0xfc) >> 1;
+ m_prg_mask = 0x1f >> BIT(m_reg[2], 5);
set_prg(m_prg_base, m_prg_mask);
- set_chr(m_chr_source, m_chr_base, m_chr_mask);
}
+
+ m_chr_base = (m_reg[0] & 0xfc) << 1;
+ m_chr_mask = BIT(m_reg[2], 7) ? 0x1f : 0xff >> BIT(m_reg[2], 5);
+ set_chr(m_chr_source, m_chr_base, m_chr_mask);
+}
+
+void nes_tech9in1_device::write_l(offs_t offset, u8 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
+ {
+ case 0x1000: case 0x1001: case 0x1002:
+ m_reg[offset & 3] = data;
+ update_banks();
+ break;
+ }
+}
+
+/*-------------------------------------------------
+
+ BMC-5IN1
+
+ Unknown Bootleg Multigame Board
+ Games: 5 in 1 1993 Copyright
+
+ NES 2.0: mapper 334
+
+ In MAME: Supported.
+
+ -------------------------------------------------*/
+
+u8 nes_bmc_5in1_device::read_m(offs_t offset)
+{
+ LOG("bmc_5in1 read_m, offset: %04x\n", offset);
+
+ if ((offset & 0x03) == 0x02)
+ return (get_open_bus() & 0xfe) | m_jumper->read();
+ else
+ return get_open_bus();
+}
+
+void nes_bmc_5in1_device::write_m(offs_t offset, u8 data)
+{
+ LOG("bmc_5in1 write_m, offset: %04x, data: %02x\n", offset, data);
+
+ if ((m_wram_protect & 0xc0) == 0x80)
+ {
+ if (!(offset & 0x03))
+ prg32(BIT(data, 1, 2));
+ }
+}
+
+/*-------------------------------------------------
+
+ BMC-NEWSTAR-GRM070-8IN1
+
+ Unknown Bootleg Multigame Board
+ Games: New Star Super 8 in 1
+
+ NES 2.0: mapper 333
+
+ In MAME: Supported.
+
+ -------------------------------------------------*/
+
+void nes_bmc_8in1_device::write_h(offs_t offset, u8 data)
+{
+ LOG("bmc_8in1 write_h, offset: %04x, data: %02x\n", offset, data);
+
+ if (BIT(offset, 12))
+ {
+ if (BIT(data, 4))
+ {
+ m_prg_base = (data & 0x0c) << 2;
+ set_prg(m_prg_base, m_prg_mask);
+ m_chr_base = m_prg_base << 3;
+ set_chr(m_chr_source, m_chr_base, m_chr_mask);
+ }
+ else
+ prg32(data & 0x0f);
+ }
+ else
+ txrom_write(offset, data);
+}
+
+/*-------------------------------------------------
+
+ BMC-15IN1 (PCB JC-016-2?)
+
+ Games: 3 in 1, 15 in 1
+
+ MMC3 clone with banking for multigame menu.
+
+ iNES: mapper 205
+
+ In MAME: Supported.
+
+ -------------------------------------------------*/
+
+void nes_bmc_15in1_device::write_m(offs_t offset, u8 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
+
+ m_prg_base = (data & 0x03) << 4;
+ m_prg_mask = 0x1f >> BIT(data, 1);
+ set_prg(m_prg_base, m_prg_mask);
+
+ m_chr_base = m_prg_base << 3;
+ m_chr_mask = 0xff >> BIT(data, 1);
+ set_chr(m_chr_source, m_chr_base, m_chr_mask);
}
/*-------------------------------------------------
@@ -2033,18 +2564,18 @@ void nes_bmc_15in1_device::write_m(offs_t offset, uint8_t 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)
{
- case 0x2001: /* $a001 - Select 128K ROM/VROM base (0..5) or last 256K ROM/VRAM base (6) */
+ case 0x2001: // $a001 - Select 128K ROM/VROM base (0..5) or last 256K ROM/VRAM base (6)
page = (data & 0x07);
if (page > 6)
page = 6;
@@ -2068,50 +2599,169 @@ void nes_bmc_sbig7_device::write_h(offs_t offset, uint8_t data)
BMC-HIK8IN1
Known Boards: Unknown Multigame Bootleg Board
- Games: Street Fighter V, various multigame carts
+ Games: Many, many multigame carts
iNES: mapper 45
- In MESS: Supported. It also uses mmc3_irq.
+ In MAME: Supported. It also uses mmc3_irq.
+
+ -------------------------------------------------*/
+
+void nes_bmc_hik8_device::write_m(offs_t offset, u8 data)
+{
+ LOG("bmc_hik8 write_m, offset: %04x, data: %02x\n", offset, data);
+
+ nes_txrom_device::write_m(offset, data); // registers overlay WRAM
+
+ if (!BIT(m_reg[3], 6)) // outer register lock bit
+ {
+ m_reg[m_count] = data;
+ m_count = (m_count + 1) & 0x03;
+
+ m_prg_base = (m_reg[2] & 0xc0) << 2 | m_reg[1];
+ m_prg_mask = ~m_reg[3] & 0x3f;
+ set_prg(m_prg_base, m_prg_mask);
+
+ m_chr_base = (m_reg[2] & 0xf0) << 4 | m_reg[0];
+ m_chr_mask = 0xff >> (~m_reg[2] & 0x0f);
+ set_chr(m_chr_source, m_chr_base, m_chr_mask);
+ }
+}
+
+/*-------------------------------------------------
+
+ BMC-JY-208
+
+ Games: Rockman 7 in 1
+
+ Variant of the HIK8IN1 boards that adds 8K of VRAM
+ to be used presumably by Rockman 4/6 and a 4 screen
+ mirroring mode for Sachen's Rocman X.
+
+ NES 2.0: mapper 356
+
+ In MAME: Supported.
-------------------------------------------------*/
-void nes_bmc_hik8_device::write_m(offs_t offset, uint8_t data)
+void nes_bmc_jy208_device::set_chr(u8 chr, int chr_base, int chr_mask)
{
- LOG_MMC(("bmc_hik8 write_m, offset: %04x, data: %02x\n", offset, data));
+ if (BIT(m_reg[2], 5))
+ nes_txrom_device::set_chr(chr, chr_base, chr_mask);
+ else
+ chr8(0, CHRRAM);
+}
+
+void nes_bmc_jy208_device::write_m(offs_t offset, u8 data)
+{
+ nes_bmc_hik8_device::write_m(offset, data);
- /* This bit is the "register lock". Once register are locked, writes go to WRAM
- and there is no way to unlock them (except by resetting the machine) */
- if ((m_reg[3] & 0x40) && !m_prgram.empty())
- m_prgram[offset] = data;
+ if (BIT(m_reg[2], 6))
+ m_mirroring = PPU_MIRROR_4SCREEN; // prevent MMC3 mirror switching
else
+ m_mirroring = BIT(m_mmc_mirror, 0) ? PPU_MIRROR_HORZ : PPU_MIRROR_VERT; // allow MMC3 mirror switching and get its current setting
+
+ set_nt_mirroring(m_mirroring); // actually change nametable pointers
+}
+
+/*-------------------------------------------------
+
+ BMC-JY-302
+
+ Games: Super 8 in 1
+
+ Variant of the HIK8IN1 boards that adds 8K of VRAM
+ which seems the same as the SFC-12 board below,
+ other than the line which selects VRAM/VROM.
+
+ NES 2.0: mapper 410
+
+ In MAME: Supported.
+
+ -------------------------------------------------*/
+
+void nes_bmc_jy302_device::set_chr(u8 chr, int chr_base, int chr_mask)
+{
+ if (BIT(m_reg[2], 6))
+ chr8(0, CHRRAM);
+ else
+ nes_txrom_device::set_chr(chr, chr_base, chr_mask);
+}
+
+/*-------------------------------------------------
+
+ BMC-KC885
+
+ Games: Super 8 in 1 VIP19
+
+ Variant of the HIK8IN1 boards that has different
+ upper address lines for PRG banking. Exactly how
+ these lines are selected is determined by three
+ jumper/solder pads.
+
+ NES 2.0: mapper 401
+
+ In MAME: Supported.
+
+ -------------------------------------------------*/
+
+u8 nes_bmc_kc885_device::read_h(offs_t 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();
+ else
+ return hi_access_rom(offset);
+}
+
+void nes_bmc_kc885_device::write_m(offs_t offset, u8 data)
+{
+ LOG("bmc_kc885 write_m, offset: %04x, data: %02x\n", offset, data);
+
+ if (!BIT(m_reg[3], 6)) // outer register lock bit
{
+ if (m_count == 1)
+ data = (data & ~0x60) | bitswap<2>(data, 5, 6) << 5;
m_reg[m_count] = data;
m_count = (m_count + 1) & 0x03;
- if (!m_count)
- {
- LOG_MMC(("bmc_hik8 write_m, command completed %02x %02x %02x %02x\n", m_reg[3],
- m_reg[2], m_reg[1], m_reg[0]));
-
- m_prg_base = m_reg[1];
- m_prg_mask = 0x3f ^ (m_reg[3] & 0x3f);
- m_chr_base = ((m_reg[2] & 0xf0) << 4) | m_reg[0];
- if (BIT(m_reg[2], 3))
- m_chr_mask = (1 << ((m_reg[2] & 7) + 1)) - 1;
- else if (m_reg[2])
- m_chr_mask = 0;
- else
- m_chr_mask = 0xff; // i.e. we use the vrom_bank with no masking
+ u8 mask = 0x80 | (m_jumper->read() & 0x03) << 5;
+ m_prg_base = (m_reg[2] & mask) | (m_reg[1] & ~mask);
+ m_prg_mask = ~m_reg[3] & 0x1f;
+ set_prg(m_prg_base, m_prg_mask);
- set_prg(m_prg_base, m_prg_mask);
- set_chr(m_chr_source, m_chr_base, m_chr_mask);
- }
+ m_chr_base = (m_reg[2] & 0xf0) << 4 | m_reg[0];
+ m_chr_mask = 0xff >> (~m_reg[2] & 0x0f);
+ set_chr(m_chr_source, m_chr_base, m_chr_mask);
}
}
/*-------------------------------------------------
+ BMC-SFC-12
+
+ Games: Rockman 6 in 1 (alt 2)
+
+ Variant of the HIK8IN1 boards that adds 8K of VRAM
+ to be used presumably by Rockman 4/6.
+
+ NES 2.0: mapper 372
+
+ In MAME: Supported.
+
+ -------------------------------------------------*/
+
+void nes_bmc_sfc12_device::set_chr(u8 chr, int chr_base, int chr_mask)
+{
+ if (BIT(m_reg[2], 5))
+ chr8(0, CHRRAM);
+ else
+ nes_txrom_device::set_chr(chr, chr_base, chr_mask);
+}
+
+/*-------------------------------------------------
+
BMC-SUPERHIK-4IN1
Known Boards: Unknown Multigame Bootleg Board
@@ -2119,73 +2769,253 @@ void nes_bmc_hik8_device::write_m(offs_t offset, uint8_t data)
iNES: mapper 49
- In MESS: Supported. It also uses mmc3_irq.
+ In MAME: Supported. It also uses mmc3_irq.
-------------------------------------------------*/
-void nes_bmc_hik4_device::write_m(offs_t offset, uint8_t data)
+void nes_bmc_hik4_device::prg_cb(int start, int bank)
{
- LOG_MMC(("bmc_hik4 write_m, offset: %04x, data: %02x\n", offset, data));
+ if (m_mmc3_mode) // all games use MMC3 PRG banking except Master Fighter III
+ nes_txrom_device::prg_cb(start, bank);
+}
- /* mid writes only work when WRAM is enabled. not sure if I should
- change the condition to m_mmc_latch2==0x80 (i.e. what is the effect of
- the read-only bit?) */
- if (m_wram_protect & 0x80)
+void nes_bmc_hik4_device::write_m(offs_t offset, u8 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)
{
- if (data & 0x01) /* if this is 0, then we have 32k PRG blocks */
+ m_mmc3_mode = data & 0x01;
+ if (m_mmc3_mode)
{
m_prg_base = (data & 0xc0) >> 2;
- m_prg_mask = 0x0f;
set_prg(m_prg_base, m_prg_mask);
}
- else
- prg32((data & 0x30) >> 4);
+ else // Master Fighter III only
+ prg32(BIT(data, 4, 2));
m_chr_base = (data & 0xc0) << 1;
- m_chr_mask = 0x7f;
set_chr(m_chr_source, m_chr_base, m_chr_mask);
}
}
/*-------------------------------------------------
- BMC-MARIOPARTY-7IN1
+ BMC-A88S-1
- Known Boards: Unknown Multigame Bootleg Board
- Games: Mario 7 in 1
+ Games: 1997 Super 7 in 1, 6 in 1 (JY-201 to JY-206)
- MMC3 clone
+ MMC3 clone with banking for multigame menu.
- iNES: mapper 52
+ NES 2.0: mapper 411
+
+ In MAME: Preliminary supported.
- In MESS: Supported.
+ TODO: Investigate...
+ - Hokuto no Ken has broken sound on each cart it's on.
+ - Bird Fighter boss fights have corrupt graphics.
+ - whether not being able to reset from within certain
+ games is correct. Examples are Samurai (title scroll
+ only) and Bomber Man (in game only) on JY-202, or
+ SD Gunman in JY-204.
-------------------------------------------------*/
-void nes_bmc_mario7in1_device::write_m(offs_t offset, uint8_t data)
+void nes_a88s1_device::update_banks()
+{
+ u8 outer = bitswap<2>(m_reg[1], 6, 3);
+ u8 size_128k = !BIT(m_reg[1], 1);
+
+ if (BIT(m_reg[0], 6)) // NROM mode
+ {
+ u8 bank = outer << 3 | bitswap<3>(m_reg[0], 2, 3, 0);
+ u8 mode = BIT(m_reg[0], 1);
+ prg16_89ab(bank & ~mode);
+ prg16_cdef(bank | mode);
+ }
+ else // MMC3 mode
+ {
+ m_prg_base = (outer & (0xfe | size_128k)) << 4;
+ m_prg_mask = 0x1f >> size_128k;
+ set_prg(m_prg_base, m_prg_mask);
+ }
+
+ m_chr_base = (m_reg[0] & 0x10) << 4 | (BIT(m_reg[1], 2) & size_128k) << 7;
+ m_chr_mask = 0xff >> size_128k;
+ set_chr(m_chr_source, m_chr_base, m_chr_mask);
+}
+
+void nes_a88s1_device::prg_cb(int start, int bank)
+{
+ if (!BIT(m_reg[0], 6))
+ nes_txrom_device::prg_cb(start, bank);
+}
+
+void nes_a88s1_device::write_l(offs_t offset, u8 data)
+{
+ LOG("a88s1 write_l, offset: %04x, data: %02x\n", offset, data);
+
+ offset += 0x100;
+ if (offset >= 0x1000)
+ {
+ m_reg[offset & 1] = data;
+ update_banks();
+ }
+}
+
+/*-------------------------------------------------
+
+ BMC-F-15
+
+ Unknown Multigame Bootleg Board
+ Games: 150 in 1 Unchained Melody
+
+ MMC3 clone with banking for multigame menu.
+
+ NES 2.0: mapper 259
+
+ In MAME: Supported.
+
+ -------------------------------------------------*/
+
+void nes_bmc_f15_device::write_m(offs_t offset, u8 data)
+{
+ LOG("bmc_f15 write_m, offset: %04x, data: %02x\n", offset, data);
+
+ if (BIT(m_wram_protect, 7))
+ {
+ u8 bank = data & 0x0f;
+ u8 mode = BIT(data, 3);
+ prg16_89ab(bank & ~mode);
+ prg16_cdef(bank | mode);
+ }
+}
+
+void nes_bmc_f15_device::prg_cb(int start, int bank)
+{
+ // Ignore MMC3 PRG bank switching. Master Fighter II (game #150) uses the bank switching above.
+}
+
+/*-------------------------------------------------
+
+ BMC-F600
+
+ Games: Golden Mario Party II 6 in 1
+
+ MMC3 clone with banking for multigame menu. Note,
+ this cart has one TxSROM game (SMB4) and so it uses
+ the nonstandard MMC3 mirroring of those boards.
+
+ NES 2.0: mapper 370
+
+ In MAME: Supported.
+
+ -------------------------------------------------*/
+
+u8 nes_bmc_f600_device::read_l(offs_t offset)
+{
+ LOG("bmc_f600 read_l, offset: %04x\n", offset);
+
+ offset += 0x100;
+ if (offset >= 0x1000)
+ return (get_open_bus() & 0x7f) | m_jumper->read();
+ else
+ return get_open_bus();
+}
+
+void nes_bmc_f600_device::write_l(offs_t offset, u8 data)
+{
+ LOG("bmc_f600 write_l, offset: %04x, data: %02x\n", offset, data);
+
+ offset += 0x100;
+ if (offset >= 0x1000)
+ {
+ m_reg = offset;
+
+ m_prg_base = (m_reg & 0x38) << 1;
+ m_prg_mask = 0x1f >> BIT(m_reg, 5);
+ set_prg(m_prg_base, m_prg_mask);
+
+ m_chr_base = (m_reg & 0x07) << 7;
+ m_chr_mask = 0xff >> BIT(~m_reg, 2);
+ set_chr(m_chr_source, m_chr_base, m_chr_mask);
+ }
+}
+
+void nes_bmc_f600_device::write_h(offs_t offset, u8 data)
{
- uint8_t helper1, helper2;
- LOG_MMC(("bmc_mario7in1 write_m, 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
+ nes_txrom_device::write_h(offset, data);
+}
+
+void nes_bmc_f600_device::set_chr(u8 chr, int chr_base, int chr_mask)
+{
+ if ((m_reg & 0x07) == 1)
+ nes_txsrom_device::set_chr(chr, chr_base, chr_mask);
+ else
+ nes_txrom_device::set_chr(chr, chr_base, chr_mask);
+}
+
+/*-------------------------------------------------
+
+ BMC EL860947C and EL861121C boards
+
+ Games: 8 in 1 (JY-111, JY-112, and JY-119)
+
+ MMC3 clone with banking for multigame menu.
+
+ NES 2.0: mapper 267 and mapper 377
- /* mid writes only work when WRAM is enabled. not sure if I should
- change the condition to m_map52_reg_written == 0x80 (i.e. what is the effect of
- the read-only bit?) and it only can happen once! */
- if ((m_wram_protect & 0x80) && !m_reg_written)
+ In MAME: Supported.
+
+ -------------------------------------------------*/
+
+void nes_bmc_el86xc_device::write_m(offs_t offset, u8 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
{
- helper1 = (data & 0x08);
- helper2 = (data & 0x40);
+ int outer = bitswap<3>(data, 5, 2, 1);
+ m_prg_base = outer << (31 - count_leading_zeros_32(m_outer_prg_size) - 3); // << std::countr_zero(m_outer_prg_size) - 3; in C++20
+ set_prg(m_prg_base, m_prg_mask);
+ m_chr_base = outer << 7;
+ set_chr(m_chr_source, m_chr_base, m_chr_mask);
+ }
+}
+
+/*-------------------------------------------------
+
+ BMC-GN-45
- m_prg_base = helper1 ? ((data & 0x07) << 4) : ((data & 0x06) << 4);
- m_prg_mask = helper1 ? 0x0f : 0x1f;
- m_chr_base = ((data & 0x20) << 4) | ((data & 0x04) << 6) | (helper2 ? ((data & 0x10) << 3) : 0);
- m_chr_mask = helper2 ? 0x7f : 0xff;
+ Games: 4 in 1 (K-3131GS and K-3131SS)
+
+ MMC3 clone with banking for multigame menu.
+
+ NES 2.0: mapper 366
+
+ In MAME: Supported.
+
+ -------------------------------------------------*/
+
+void nes_bmc_gn45_device::write_m(offs_t offset, u8 data)
+{
+ LOG("bmc_gn45 write_m, offset: %04x, data: %02x\n", offset, data);
+
+ nes_txrom_device::write_m(offset, data); // registers overlay WRAM
+
+ if (!m_lock)
+ {
+ m_prg_base = offset & 0x70;
set_prg(m_prg_base, m_prg_mask);
+ m_chr_base = m_prg_base << 3;
set_chr(m_chr_source, m_chr_base, m_chr_mask);
- m_reg_written = 1;
+ m_lock = BIT(offset, 7);
}
- else
- m_prgram[offset] = data;
}
/*-------------------------------------------------
@@ -2195,241 +3025,529 @@ void nes_bmc_mario7in1_device::write_m(offs_t offset, uint8_t data)
Known Boards: Unknown Multigame Bootleg Board
Games: Super HIK Gold 7 in 1, Golden 7 in 1 and many more
- MMC3 clone, same as BMC-MARIOPARTY-7IN1 but with switched CHR
- bank lines
+ MMC3 clone with banking for multigame menu.
iNES: mapper 52
- In MESS: Supported.
+ In MAME: Supported.
-------------------------------------------------*/
-void nes_bmc_gold7in1_device::write_m(offs_t offset, uint8_t data)
+void nes_bmc_gold7in1_device::write_m(offs_t offset, u8 data)
{
- uint8_t helper1, helper2;
- 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 & 0x80) && !m_reg_written)
+ if ((m_wram_protect & 0xc0) == 0x80 && !m_lock)
{
- helper1 = (data & 0x08);
- helper2 = (data & 0x40);
+ u8 prg128k = BIT(data, 3);
+ u8 chr128k = BIT(data, 6);
- m_prg_base = helper1 ? ((data & 0x07) << 4) : ((data & 0x06) << 4);
- m_prg_mask = helper1 ? 0x0f : 0x1f;
- m_chr_base = ((data & 0x20) << 3) | ((data & 0x04) << 7) | (helper2 ? ((data & 0x10) << 3) : 0);
- m_chr_mask = helper2 ? 0x7f : 0xff;
+ m_prg_base = (data & (0x06 | prg128k)) << 4;
+ m_prg_mask = 0x1f >> prg128k;
+ m_chr_base = (bitswap<3>(data, 2, 5, 4) & (0x06 | chr128k)) << 7;
+ m_chr_mask = 0xff >> chr128k;
set_prg(m_prg_base, m_prg_mask);
set_chr(m_chr_source, m_chr_base, m_chr_mask);
- m_reg_written = BIT(data, 7); // mc_2hikg & mc_s3nt3 write here multiple time
+ m_lock = BIT(data, 7); // mc_2hikg & mc_s3nt3 write here multiple time
}
else
- m_prgram[offset] = data;
+ nes_txrom_device::write_m(offset, data); // write WRAM
}
/*-------------------------------------------------
- BMC-GOLDENCARD-6IN1
+ BMC-K-3006
- Known Boards: Unknown Bootleg Multigame Board
- Games: Golden Card 6 in 1
+ Games: 21 in 1
- MMC3 clone
+ MMC3 clone with banking for multigame menu.
- iNES: mapper 217
+ NES 2.0: mapper 339
- In MESS: Supported.
+ In MAME: Supported.
-------------------------------------------------*/
-void nes_bmc_gc6in1_device::prg_cb(int start, int bank)
+void nes_bmc_k3006_device::write_m(offs_t offset, u8 data)
{
- if (m_reg[1] & 0x08)
- bank &= 0x1f;
- else
+ LOG("bmc_k3006 write_m, offset: %04x, data: %02x\n", offset, data);
+ if ((m_wram_protect & 0xc0) == 0x80)
{
- bank &= 0x0f;
- bank |= m_reg[1] & 0x10;
+ if (BIT(offset, 5)) // MMC3 mode
+ {
+ m_prg_base = (offset & 0x18) << 1;
+ set_prg(m_prg_base, m_prg_mask);
+ m_chr_base = m_prg_base << 3;
+ set_chr(m_chr_source, m_chr_base, m_chr_mask);
+ }
+ else // NROM mode
+ {
+ u8 bank = offset & 0x1f;
+ u8 mode = (offset & 0x06) == 0x06;
+ prg16_89ab(bank & ~mode);
+ prg16_cdef(bank | mode);
+ }
}
-
- prg8_x(start, bank | ((m_reg[1] & 0x03) << 5));
}
-void nes_bmc_gc6in1_device::chr_cb(int start, int bank, int source)
-{
- if (!(m_reg[1] & 0x08))
- bank = ((m_reg[1] & 0x10) << 3) | (bank & 0x7f);
+/*-------------------------------------------------
+
+ BMC-K-3033
+ Games: 35 in 1
- bank |= ((m_reg[1] << 6) & 0x100);
- chr1_x(start, ((m_reg[1] & 0x03) << 8) | bank, source);
+ MMC3 clone with banking for multigame menu.
+
+ NES 2.0: mapper 322
+
+ In MAME: Supported.
+
+ -------------------------------------------------*/
+
+void nes_bmc_k3033_device::prg_cb(int start, int bank)
+{
+ if (m_mmc3_mode)
+ nes_txrom_device::prg_cb(start, bank);
}
-void nes_bmc_gc6in1_device::write_l(offs_t offset, uint8_t data)
+void nes_bmc_k3033_device::write_m(offs_t offset, u8 data)
{
- uint8_t bank;
- LOG_MMC(("bmc_gc6in1 write_l, offset: %04x, data: %02x\n", offset, data));
- offset += 0x100;
+ LOG("bmc_k3033 write_m, offset: %04x, data: %02x\n", offset, data);
- if (offset == 0x1000)
+ if ((m_wram_protect & 0xc0) == 0x80)
{
- m_reg[0] = data;
- if (data & 0x80)
+ m_mmc3_mode = BIT(offset, 5);
+
+ u8 mode_128k = !(BIT(offset, 7) && m_mmc3_mode);
+ m_chr_base = bitswap<3>(offset, 6, 4, 3) << (8 - mode_128k);
+ m_chr_mask = 0xff >> mode_128k;
+ set_chr(m_chr_source, m_chr_base, m_chr_mask);
+
+ if (m_mmc3_mode)
{
- bank = (data & 0x0f) | ((m_reg[1] & 0x03) << 4);
- prg16_89ab(bank);
- prg16_cdef(bank);
- }
- else
+ m_prg_base = m_chr_base >> 3;
+ m_prg_mask = m_chr_mask >> 3;
set_prg(m_prg_base, m_prg_mask);
+ }
+ else // NROM mode
+ {
+ u8 bank = (offset & 0x40) >> 1 | (offset & 0x1f);
+ u8 mode = !!(offset & 0x03);
+ prg16_89ab(bank & ~mode);
+ prg16_cdef(bank | mode);
+ }
}
- else if (offset == 0x1001)
+}
+
+/*-------------------------------------------------
+
+ BMC-L6IN1
+
+ Games: New Star 6 in 1
+
+ MMC3 clone with banking for multigame menu.
+
+ NES 2.0: mapper 345
+
+ Note: Cabal leaves the APU in a bad state so that
+ after soft resetting and loading Track & Field there
+ is a constant drone pitch. This is likely a game bug.
+
+ -------------------------------------------------*/
+
+void nes_bmc_l6in1_device::set_prg(int prg_base, int prg_mask)
+{
+ if (m_reg & 0x0c) // MMC3 mode
+ nes_txrom_device::set_prg(prg_base, prg_mask);
+ else // AxROM mode
+ prg32(prg_base >> 2 | (m_reg & 0x03));
+}
+
+void nes_bmc_l6in1_device::set_mirror()
+{
+ if (BIT(m_reg, 5))
+ set_nt_mirroring(BIT(m_reg, 4) ? PPU_MIRROR_HIGH : PPU_MIRROR_LOW);
+ else
+ set_nt_mirroring(m_mmc_mirror ? PPU_MIRROR_HORZ : PPU_MIRROR_VERT);
+}
+
+void nes_bmc_l6in1_device::write_m(offs_t offset, u8 data)
+{
+ LOG("bmc_l6in1 write_m, offset: %04x, data: %02x\n", offset, data);
+
+ if ((m_wram_protect & 0xc0) == 0x80)
{
- m_reg[1] = data;
+ m_reg = data;
+ m_prg_base = (m_reg & 0xc0) >> 2;
set_prg(m_prg_base, m_prg_mask);
+ set_mirror();
}
- else if (offset == 0x1007)
+}
+
+void nes_bmc_l6in1_device::write_h(offs_t offset, u8 data)
+{
+ LOG("bmc_l6in1 write_h, offset: %04x, data: %02x\n", offset, data);
+
+ txrom_write(offset, data);
+ if ((offset & 0x6001) == 0x2000)
+ set_mirror();
+}
+
+/*-------------------------------------------------
+
+ BMC-00202650
+
+ Games: 8 in 1
+
+ MMC3 clone with banking for multigame menu.
+
+ NES 2.0: mapper 392
+
+ In MAME: Supported.
+
+ TODO: Soft reset doesn't work for some games some of
+ the time. Seems to be caused by main RAM contents.
+ Does this happen on hardware?
+
+ -------------------------------------------------*/
+
+void nes_bmc_00202650_device::set_prg(int prg_base, int prg_mask)
+{
+ if (m_mmc3_mode)
+ nes_txrom_device::set_prg(prg_base, prg_mask);
+}
+
+void nes_bmc_00202650_device::set_chr(u8 chr, int chr_base, int chr_mask)
+{
+ if (m_mmc3_mode)
+ nes_txrom_device::set_chr(chr, chr_base, chr_mask);
+}
+
+void nes_bmc_00202650_device::write_m(offs_t offset, u8 data)
+{
+ LOG("bmc_00202650 write_m, offset: %04x, data: %02x\n", offset, data);
+
+ if (!m_mmc3_mode)
{
- m_reg[2] = data;
+ m_mmc3_mode = BIT(data, 4);
+
+ m_prg_base = (data & 0x07) << 4;
+ set_prg(m_prg_base, m_prg_mask);
+
+ m_chr_base = m_prg_base << 3;
+ set_chr(m_chr_source, m_chr_base, m_chr_mask);
}
}
-void nes_bmc_gc6in1_device::write_h(offs_t offset, uint8_t data)
+/*-------------------------------------------------
+
+ BMC-411120C, BMC-810849-C
+
+ Games: 4 in 1, 19 in 1
+
+ MMC3 clone with banking for multigame menu.
+
+ NES 2.0: mapper 287
+
+ In MAME: Supported.
+
+ -------------------------------------------------*/
+
+void nes_bmc_411120c_device::prg_cb(int start, int bank)
{
- uint8_t cmd;
- static const uint8_t conv_table[8] = {0, 6, 3, 7, 5, 2, 4, 1};
- LOG_MMC(("bmc_gc6in1 write_h, offset: %04x, data: %02x\n", offset, data));
+ if (!BIT(m_reg, 3)) // all games use MMC3 PRG banking except Master Fighter II
+ nes_txrom_device::prg_cb(start, bank);
+}
+
+void nes_bmc_411120c_device::write_m(offs_t offset, u8 data)
+{
+ LOG("bmc_411120c write_m, offset: %04x, data: %02x\n", offset, data);
- if (!m_reg[2])
+ if (BIT(m_wram_protect, 7))
{
- // in this case we act like MMC3, only with alt prg/chr handlers
- txrom_write(offset, data);
+ m_reg = offset;
+ if (BIT(m_reg, 3))
+ prg32(bitswap<5>(m_reg, 2, 1, 0, 5, 4));
+ else
+ {
+ m_prg_base = (m_reg & 0x07) << 4;
+ set_prg(m_prg_base, m_prg_mask);
+ }
+ m_chr_base = (m_reg & 0x07) << 7;
+ set_chr(m_chr_source, m_chr_base, m_chr_mask);
}
- else
+}
+
+/*-------------------------------------------------
+
+ BMC-81-03-05-C
+
+ Games: 92' Super Mario Family
+
+ MMC3 clone with banking for multigame menu. Note,
+ this cart has one TxSROM game (SMB4) and so it uses
+ the nonstandard MMC3 mirroring of those boards.
+
+ NES 2.0: mapper 353
+
+ In MAME: Partially supported.
+
+ TODO: Banking isn't quite right. Golden Mario, the
+ 4th game, should be SMB2J but loads as plain old
+ Mario Bros with garbled graphics. Golden Mario
+ should be on the last outer bank #3.
+
+ -------------------------------------------------*/
+
+void nes_bmc_810305c_device::set_prg(int prg_base, int prg_mask)
+{
+ u8 a17 = BIT(m_mmc_vrom_bank[0], 7);
+
+ nes_txrom_device::set_prg(prg_base | (m_outer == 2 && a17) << 4, prg_mask);
+
+ if (m_outer == 3 && !a17)
{
- switch (offset & 0x6001)
- {
- case 0x0000:
- txrom_write(0x4000, data);
- break;
+ prg8_cd(m_mmc_prg_bank[0] | 0x70);
+ prg8_ef(m_mmc_prg_bank[1] | 0x70);
+ }
+}
- case 0x0001:
- data = (data & 0xc0) | conv_table[data & 0x07];
- m_reg[3] = 1;
- txrom_write(0x0000, data);
- break;
+void nes_bmc_810305c_device::set_chr(u8 chr, int chr_base, int chr_mask)
+{
+ if (m_outer == 2 && BIT(m_mmc_vrom_bank[0], 7))
+ chr8(0, CHRRAM);
+ else if (m_outer)
+ nes_txrom_device::set_chr(chr, chr_base, chr_mask);
+ else
+ nes_txsrom_device::set_chr(chr, chr_base, chr_mask);
+}
- case 0x2000:
- cmd = m_latch & 0x07;
- if (m_reg[3])
- {
- m_reg[3] = 0;
- switch (cmd)
- {
- case 0: case 1: // these do not need to be separated: we take care of them in set_chr!
- case 2: case 3: case 4: case 5:
- m_mmc_vrom_bank[cmd] = data;
- set_chr(m_chr_source, m_chr_base, m_chr_mask);
- break;
- case 6:
- case 7:
- m_mmc_prg_bank[cmd - 6] = data;
- set_prg(m_prg_base, m_prg_mask);
- break;
- }
- }
- break;
+void nes_bmc_810305c_device::write_h(offs_t offset, u8 data)
+{
+ LOG("bmc_810305c write_h, offset: %04x, data: %02x\n", offset, data);
+ if (BIT(offset, 7)) // outer register
+ {
+ m_outer = BIT(offset, 13, 2);
- case 0x2001:
- set_nt_mirroring(BIT(data, 0) ? PPU_MIRROR_HORZ : PPU_MIRROR_VERT);
- break;
+ m_prg_base = m_outer << 5;
+ m_prg_mask = 0x1f >> ((m_outer == 2) ? 1 : 0);
+ set_prg(m_prg_base, m_prg_mask);
- default:
- txrom_write(offset, data);
- break;
- }
+ m_chr_base = m_outer << 7;
+ set_chr(m_chr_source, m_chr_base, m_chr_mask);
}
+ else if (m_outer) // standard MMC3 registers
+ nes_txrom_device::write_h(offset, data);
+ else // TxSROM MMC3 registers without mirroring bit
+ nes_txsrom_device::write_h(offset, data);
}
/*-------------------------------------------------
- BMC-411120C
+ BMC-820720C
+ Games: 1993 Super HiK 8 in 1 (G-002)
- MMC3 clone
+ MMC3 clone with banking for multigame menu.
+ NES 2.0: mapper 393
- In MESS: Very Preliminary Support
+ In MAME: Supported.
-------------------------------------------------*/
-void nes_bmc_411120c_device::prg_cb(int start, int bank)
+void nes_bmc_820720c_device::set_prg(int prg_base, int prg_mask)
{
- if (m_reg & 8) // & 0xc when DSW change (diff menu?)
- prg32(((m_reg >> 4) & 3) | 0x0c);
+ switch (m_reg >> 4)
+ {
+ case 0: // MMC3 mode
+ case 1:
+ nes_txrom_device::set_prg(prg_base, prg_mask);
+ break;
+ case 2: // BNROM mode
+ prg32((prg_base | (m_mmc_prg_bank[BIT(m_latch, 6) << 1] & prg_mask)) >> 2);
+ break;
+ case 3: // UNROM mode
+ prg16_89ab(m_prg_base >> 1);
+ prg16_cdef(m_prg_base >> 1 | 0x07);
+ break;
+ }
+}
+
+void nes_bmc_820720c_device::set_chr(u8 chr, int chr_base, int chr_mask)
+{
+ if (BIT(m_reg, 3))
+ chr8(0, CHRRAM);
else
- prg8_x(start, (bank & 0x0f) | ((m_reg & 0x03) << 4));
+ nes_txrom_device::set_chr(chr, chr_base, chr_mask);
}
-void nes_bmc_411120c_device::chr_cb(int start, int bank, int source)
+void nes_bmc_820720c_device::write_m(offs_t offset, u8 data)
{
- chr1_x(start, bank | ((m_reg & 3) << 7), source);
+ LOG("bmc_820720c write_m, offset: %04x, data: %02x\n", offset, data);
+
+ if ((m_wram_protect & 0xc0) == 0x80)
+ {
+ m_reg = offset & 0x3f;
+
+ m_prg_base = (m_reg & 0x07) << 4;
+ set_prg(m_prg_base, m_prg_mask);
+
+ m_chr_base = (m_reg & 0x01) << 8;
+ set_chr(m_chr_source, m_chr_base, m_chr_mask);
+ }
}
-void nes_bmc_411120c_device::write_m(offs_t offset, uint8_t data)
+void nes_bmc_820720c_device::write_h(offs_t offset, u8 data)
{
- LOG_MMC(("bmc_411120c write_m, offset: %04x, data: %02x\n", offset, data));
+ LOG("bmc_820720c write_h, offset: %04x, data: %02x\n", offset, data);
- m_reg = data;
- set_prg(m_prg_base, m_prg_mask);
- set_chr(m_chr_source, m_chr_base, m_chr_mask);
+ txrom_write(offset, data); // MMC3 regs always written (for mirroring in non-MMC3 modes)
+
+ if ((m_reg & 0x30) == 0x30) // UNROM mode
+ {
+ prg16_89ab(m_prg_base >> 1 | (data & 0x07));
+ prg16_cdef(m_prg_base >> 1 | 0x07);
+ }
}
/*-------------------------------------------------
BMC-830118C
+ Games: 7 in 1 (EW-002, M-022, M-026, M-027)
- MMC3 clone
+ MMC3 clone with banking for multigame menu.
+ NES 2.0: mapper 348
- In MESS: Very Preliminary Support
+ In MAME: Preliminary supported.
+
+ TODO: Only M-022 seems to reliably soft reset to the
+ menu for all games. The other three carts are hit or
+ miss. MMC3 games in particular are not likely to
+ reset to the menu. Investigate further...
-------------------------------------------------*/
void nes_bmc_830118c_device::prg_cb(int start, int bank)
{
- if ((m_reg & 0x0c) != 0x0c)
- prg8_x(start, (bank & 0x0f) | ((m_reg & 0x0c) << 2));
- else
+ if (m_prg_base == 0x30)
{
- if (start == 0)
+ if (start <= 1)
{
- prg8_89((bank & 0x0f) | ((m_reg & 0x0c) << 2));
- prg8_ab((bank & 0x0f) | 0x20);
- }
- else if (start == 2)
- {
- prg8_cd((bank & 0x0f) | ((m_reg & 0x0c) << 2));
- prg8_ef((bank & 0x0f) | 0x20);
+ prg8_x(start, bank & ~2);
+ prg8_x(start + 2, bank | 2);
}
}
+ else
+ nes_txrom_device::prg_cb(start, bank);
}
-void nes_bmc_830118c_device::chr_cb(int start, int bank, int source)
+void nes_bmc_830118c_device::write_m(offs_t offset, u8 data)
{
- chr1_x(start, (bank & 0x7f) | ((m_reg & 0x0c) << 5), source);
+ LOG("bmc_830118c write_m, offset: %04x, data: %02x\n", offset, data);
+
+ if ((m_wram_protect & 0xc0) == 0x80)
+ {
+ m_prg_base = (data & 0x0c) << 2;
+ set_prg(m_prg_base, m_prg_mask);
+ m_chr_base = m_prg_base << 3;
+ set_chr(m_chr_source, m_chr_base, m_chr_mask);
+ }
}
-void nes_bmc_830118c_device::write_m(offs_t offset, uint8_t data)
+/*-------------------------------------------------
+
+ BMC-830832C
+
+ Games: 1994 Super HiK 3 in 1 (JY-007)
+
+ MMC3 clone with banking for multigame menu.
+
+ NES 2.0: mapper 364
+
+ In MAME: Supported.
+
+ -------------------------------------------------*/
+
+void nes_bmc_830832c_device::write_m(offs_t offset, u8 data)
{
- LOG_MMC(("bmc_830118c 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;
+ m_prg_mask = 0x1f >> BIT(data, 5);
+ set_prg(m_prg_base, m_prg_mask);
+
+ m_chr_base = (data & 0x10) << 4;
+ m_chr_mask = 0xff >> BIT(data, 5);
+ set_chr(m_chr_source, m_chr_base, m_chr_mask);
+ }
+}
+
+/*-------------------------------------------------
+
+ BMC-YY841101C
- if (offset >= 0x800 && offset < 0x900)
+ Games: 4 in 1 (OK-411, JY-009, JY-018, JY-019, JY-020)
+
+ MMC3 clone with banking for multigame menu.
+
+ NES 2.0: mapper 361
+
+ In MAME: Supported.
+
+ -------------------------------------------------*/
+
+void nes_bmc_yy841101c_device::write_m(offs_t offset, u8 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_reg = data;
+ m_prg_base = data & 0xf0;
set_prg(m_prg_base, m_prg_mask);
+ m_chr_base = (data & 0xf0) << 3;
+ set_chr(m_chr_source, m_chr_base, m_chr_mask);
+ }
+}
+
+/*-------------------------------------------------
+
+ BMC-YY841155C
+
+ Games: Donkey Kong 8 in 1 (JY-041)
+
+ MMC3 clone with banking for multigame menu.
+
+ NES 2.0: mapper 376
+
+ In MAME: Supported.
+
+ -------------------------------------------------*/
+
+void nes_bmc_yy841155c_device::write_m(offs_t offset, u8 data)
+{
+ LOG("bmc_yy841155c write_m, offset: %04x, data: %02x\n", offset, data);
+
+ if (offset >= 0x1000)
+ {
+ m_reg[offset & 1] = data;
+
+ m_prg_base = (m_reg[1] & 0x01) << 5 | (m_reg[0] & 0x40) >> 2;
+ if (BIT(m_reg[0], 7)) // NROM mode
+ {
+ u8 bank = m_prg_base >> 1 | (m_reg[0] & 0x07);
+ u8 mode = BIT(m_reg[0], 5);
+ prg16_89ab(bank & ~mode);
+ prg16_cdef(bank | mode);
+ }
+ else // MMC3 mode
+ set_prg(m_prg_base, m_prg_mask);
+
+ m_chr_base = m_prg_base << 3;
set_chr(m_chr_source, m_chr_base, m_chr_mask);
}
}
@@ -2480,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)
{
@@ -2488,6 +3606,7 @@ void nes_pjoy84_device::write_m(offs_t offset, uint8_t data)
case 0x03:
if (m_reg[3] & 0x80)
return; // else we act as if offset & 3 = 1,2
+ [[fallthrough]];
case 0x01:
case 0x02:
m_reg[offset & 0x03] = data;
@@ -2503,124 +3622,78 @@ void nes_pjoy84_device::write_m(offs_t offset, uint8_t data)
/*-------------------------------------------------
- COOLBOY
+ COOLBOY, MINDKIDS, and others with SMD132/133 chips
+
+ Games: many multicarts, Chinese games, and some
+ modern re-releases such as Metal Storm and Holy Diver
+
+ NES 2.0: mapper 268
- Games: several multigame carts
+ In MAME: Partially supported.
- In MESS: Not Supported.
+ TODO: There are many unimplemented features, though
+ there may be no carts that use them. Some of the
+ unemulated stuff: regs 4 and 5 not used, more GNROM
+ bits in reg 2, "weird" modes, WRAM at 0x5000, etc.
-------------------------------------------------*/
-void nes_coolboy_device::prg_cb(int start, int bank)
+void nes_smd133_device::prg_cb(int start, int bank)
{
- bank = (bank & 3) | ((bank & 8) >> 1) | ((bank & 4) << 1);
+ if (BIT(m_reg[3], 4)) // GNROM mode
+ {
+ u8 mask = (m_reg[1] & 0x02) | 0x01;
+ bank &= ~0x0f;
+ bank |= (m_reg[3] & ~mask & 0x0f) | (start & mask);
+ }
+
prg8_x(start, bank);
}
-void nes_coolboy_device::chr_cb(int start, int bank, int source)
+void nes_smd133_device::chr_cb(int start, int bank, int source)
{
- bank = (bank & 0xdd) | ((bank & 0x20) >> 4) | ((bank & 2) << 4);
+ if (BIT(m_reg[3], 4)) // GNROM mode
+ {
+ bank &= ~m_chr_mask;
+ bank |= (m_reg[2] & 0x0f) << 3 | start;
+ }
+
chr1_x(start, bank, source);
}
-void nes_coolboy_device::write_m(offs_t offset, uint8_t data)
+void nes_smd133_device::smd133_write(offs_t offset, u8 data)
{
- LOG_MMC(("coolboy write_m, offset: %04x, data: %02x\n", offset, data));
-
- m_reg[offset & 0x03] = data;
- //set_base_mask();
- set_chr(m_chr_source, m_chr_base, m_chr_mask);
- set_prg(m_prg_base, m_prg_mask);
-}
-
-#ifdef UNUSED_FUNCTION
-/*-------------------------------------------------
+ int reg = offset & 0x07;
- UNL-A9746
-
-
- MMC3 clone
-
-
- Preliminary emulation based on Cah4e3's code
- No dump is available (yet) for this.
-
- -------------------------------------------------*/
-
-void nes_a9746_device::device_start()
-{
- mmc3_start();
- save_item(NAME(m_reg));
-}
+ if (reg < 6 && (BIT(m_reg[3], 4) || !BIT(m_reg[3], 7)))
+ {
+ m_reg[reg] = data;
-void nes_a9746_device::pcb_reset()
-{
- m_chr_source = m_vrom_chunks ? CHRROM : CHRRAM;
+ m_prg_base = (m_reg[0] & 0x30) << 6 | (m_reg[1] & 0x0c) << 6 | (m_reg[1] & 0x10) << 3 | (m_reg[0] & 0x07) << 4;
+ m_prg_mask = (bitswap<3>(m_reg[1], 5, 6, 7) << 5 | (m_reg[0] & 0x40) >> 2 | 0x0f) ^ 0x30;
+ set_prg(m_prg_base, m_prg_mask);
- m_reg[0] = 0;
- m_reg[1] = 0;
- m_reg[2] = 0;
- mmc3_common_initialize(0x7f, 0xff, 0);
+ m_chr_base = (m_reg[0] & 0x80) & ((m_reg[0] & 0x08) << 4);
+ m_chr_mask = 0xff >> BIT(m_reg[0], 7);
+ set_chr(m_chr_source, m_chr_base, m_chr_mask);
+ }
}
-void nes_a9746_device::update_banks(uint8_t value)
+void nes_smd133_device::write_l(offs_t offset, u8 data)
{
- uint8_t bank = bitswap<8>(value & 0x3c,7,6,0,1,2,3,4,5);
+ LOG("smd133 write_l, offset: %04x, data: %02x\n", offset, data);
- switch (m_reg[0])
- {
- case 0x26: prg8_89(bank); break;
- case 0x25: prg8_ab(bank); break;
- case 0x24: prg8_cd(bank); break;
- case 0x23: prg8_ef(bank); break;
- }
-
- switch (m_reg[1])
- {
- case 0x08: case 0x0a: case 0x0c: case 0x0e:
- case 0x10: case 0x12: case 0x14: case 0x16:
- case 0x18: case 0x1a: case 0x1c: case 0x1e:
- m_reg[2] = (value << 4);
- break;
- case 0x09: chr1_0(m_reg[2] | (value >> 1), m_chr_source); break;
- case 0x0b: chr1_1(m_reg[2] | (value >> 1) | 1, m_chr_source); break;
- case 0x0d: chr1_2(m_reg[2] | (value >> 1), m_chr_source); break;
- case 0x0f: chr1_3(m_reg[2] | (value >> 1) | 1, m_chr_source); break;
- case 0x11: chr1_4(m_reg[2] | (value >> 1), m_chr_source); break;
- case 0x15: chr1_5(m_reg[2] | (value >> 1), m_chr_source); break;
- case 0x19: chr1_6(m_reg[2] | (value >> 1), m_chr_source); break;
- case 0x1d: chr1_7(m_reg[2] | (value >> 1), m_chr_source); break;
- }
+ offset += 0x100;
+ if (offset >= 0x1000 && m_smd133_addr == 0x5000)
+ smd133_write(offset, data);
}
-void nes_a9746_device::write_h(offs_t offset, uint8_t data)
+void nes_smd133_device::write_m(offs_t offset, u8 data)
{
- LOG_MMC(("unl_a9746 write_h, offset: %04x, data: %02x\n", offset, data));
-
- switch (offset & 0x6003)
- {
- case 0x0000:
- m_reg[1] = data;
- m_reg[0] = 0;
- break;
- case 0x0001:
- update_banks(data);
- break;
- case 0x0002:
- m_reg[0] = data;
- m_reg[1] = 0;
- break;
+ LOG("smd133 write_m, offset: %04x, data: %02x\n", offset, data);
- case 0x0003:
- case 0x2000:
- case 0x2001:
- case 0x2002:
- case 0x2003:
- break;
+ nes_txrom_device::write_m(offset, data); // registers overlay WRAM
- default:
- txrom_write(offset, data);
- break;
- }
+ if (offset < 0x1000 && m_smd133_addr == 0x6000)
+ smd133_write(offset, data);
}
-#endif
diff --git a/src/devices/bus/nes/mmc3_clones.h b/src/devices/bus/nes/mmc3_clones.h
index 680e86b4c9c..e114748cc66 100644
--- a/src/devices/bus/nes/mmc3_clones.h
+++ b/src/devices/bus/nes/mmc3_clones.h
@@ -14,23 +14,45 @@ class nes_nitra_device : public nes_txrom_device
{
public:
// construction/destruction
- nes_nitra_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
+ nes_nitra_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock);
- // device-level overrides
- virtual void write_h(offs_t offset, uint8_t data) override;
+ virtual void write_h(offs_t offset, u8 data) override;
};
-// ======================> nes_ks7057_device
+// ======================> nes_bmw8544_device
-class nes_ks7057_device : public nes_txrom_device
+class nes_bmw8544_device : public nes_txrom_device
{
public:
// construction/destruction
- nes_ks7057_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
+ nes_bmw8544_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock);
+ virtual u8 read_m(offs_t offset) override;
+ virtual void write_m(offs_t offset, u8 data) override;
+
+ virtual void pcb_reset() override;
+
+protected:
// device-level overrides
- virtual void write_h(offs_t offset, uint8_t data) override;
+ virtual void device_start() override ATTR_COLD;
+
+ virtual void set_prg(int prg_base, int prg_mask) override;
+
+private:
+ u8 m_reg;
+};
+
+
+// ======================> nes_fs6_device
+
+class nes_fs6_device : public nes_txrom_device
+{
+public:
+ // construction/destruction
+ nes_fs6_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock);
+
+ virtual void write_h(offs_t offset, u8 data) override;
};
@@ -40,10 +62,9 @@ class nes_sbros11_device : public nes_txrom_device
{
public:
// construction/destruction
- nes_sbros11_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
+ nes_sbros11_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock);
- // device-level overrides
- virtual void write_h(offs_t offset, uint8_t data) override;
+ virtual void write_h(offs_t offset, u8 data) override;
};
@@ -53,10 +74,9 @@ class nes_malisb_device : public nes_txrom_device
{
public:
// construction/destruction
- nes_malisb_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
+ nes_malisb_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock);
- // device-level overrides
- virtual void write_h(offs_t offset, uint8_t data) override;
+ virtual void write_h(offs_t offset, u8 data) override;
virtual void prg_cb(int start, int bank) override;
virtual void chr_cb(int start, int bank, int source) override;
};
@@ -68,12 +88,19 @@ class nes_family4646_device : public nes_txrom_device
{
public:
// construction/destruction
- nes_family4646_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
+ nes_family4646_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock);
- // device-level overrides
- virtual void write_m(offs_t offset, uint8_t data) override;
+ virtual void write_m(offs_t offset, u8 data) override;
+ virtual void prg_cb(int start, int bank) override;
virtual void pcb_reset() override;
+
+protected:
+ // device-level overrides
+ virtual void device_start() override ATTR_COLD;
+
+private:
+ u8 m_reg[4];
};
@@ -93,7 +120,7 @@ public:
protected:
// device-level overrides
- virtual void device_start() override;
+ virtual void device_start() override ATTR_COLD;
private:
uint8_t m_reg[2];
@@ -106,92 +133,111 @@ class nes_8237_device : public nes_txrom_device
{
public:
// construction/destruction
- nes_8237_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
+ nes_8237_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock);
- // device-level overrides
- virtual void device_start() override;
- virtual void write_l(offs_t offset, uint8_t data) override;
- virtual void write_h(offs_t offset, uint8_t data) override;
+ virtual void write_l(offs_t offset, u8 data) override;
+ virtual void write_h(offs_t offset, u8 data) override;
virtual void prg_cb(int start, int bank) override;
- virtual void chr_cb(int start, int bank, int source) override;
virtual void pcb_reset() override;
+protected:
+ // construction/destruction
+ nes_8237_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, u32 clock, u8 board);
+
+ // device-level overrides
+ virtual void device_start() override ATTR_COLD;
+
private:
- uint8_t m_reg[3];
- int m_cd_enable;
+ void update_banks();
+ u8 m_reg[3];
+ const u8 m_board;
};
-// ======================> nes_sglionk_device
+// ======================> nes_8237a_device
-class nes_sglionk_device : public nes_txrom_device
+class nes_8237a_device : public nes_8237_device
{
public:
// construction/destruction
- nes_sglionk_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
+ nes_8237a_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock);
+};
- virtual void write_m(offs_t offset, uint8_t data) override;
- virtual void write_h(offs_t offset, uint8_t data) override;
+
+// ======================> nes_158b_device
+
+class nes_158b_device : public nes_8237_device
+{
+public:
+ // construction/destruction
+ nes_158b_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock);
+
+ virtual u8 read_l(offs_t offset) override;
+ virtual void write_l(offs_t offset, u8 data) override;
virtual void pcb_reset() override;
protected:
// device-level overrides
- virtual void device_start() override;
+ virtual void device_start() override ATTR_COLD;
private:
- uint8_t m_reg;
- int m_reg_enabled;
+ int m_prot;
};
-// ======================> nes_sgboog_device
+// ======================> nes_kasing_device
-class nes_sgboog_device : public nes_txrom_device
+class nes_kasing_device : public nes_txrom_device
{
public:
// construction/destruction
- nes_sgboog_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
+ nes_kasing_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock);
- virtual void write_l(offs_t offset, uint8_t data) override;
- virtual void write_m(offs_t offset, uint8_t data) override;
- virtual void write_h(offs_t offset, uint8_t data) override;
+ virtual void write_m(offs_t offset, u8 data) override;
virtual void prg_cb(int start, int bank) override;
- virtual void chr_cb(int start, int bank, int source) override;
virtual void pcb_reset() override;
protected:
+ // construction/destruction
+ nes_kasing_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_start() override ATTR_COLD;
private:
- virtual void set_prg(int prg_base, int prg_mask) override;
- uint8_t m_reg[3];
- uint8_t m_mode;
+ bool m_mmc3_mode;
};
-// ======================> nes_kasing_device
+// ======================> nes_sglionk_device
-class nes_kasing_device : public nes_txrom_device
+class nes_sglionk_device : public nes_kasing_device
{
public:
// construction/destruction
- nes_kasing_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
+ nes_sglionk_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock);
- virtual void write_m(offs_t offset, uint8_t data) override;
- virtual void prg_cb(int start, int bank) override;
-
- virtual void pcb_reset() override;
+ virtual void write_h(offs_t offset, u8 data) override;
protected:
- // device-level overrides
- virtual void device_start() override;
+ // construction/destruction
+ nes_sglionk_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, u32 clock, u8 board);
private:
- uint8_t m_reg;
+ const u8 m_board;
+};
+
+
+// ======================> nes_sgboog_device
+
+class nes_sgboog_device : public nes_sglionk_device
+{
+public:
+ // construction/destruction
+ nes_sgboog_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock);
};
@@ -201,24 +247,24 @@ class nes_kay_device : public nes_txrom_device
{
public:
// construction/destruction
- nes_kay_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
+ nes_kay_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock);
- virtual uint8_t read_l(offs_t offset) override;
- virtual void write_l(offs_t offset, uint8_t data) override;
- virtual void write_h(offs_t offset, uint8_t data) override;
- virtual void prg_cb(int start, int bank) override;
+ virtual u8 read_l(offs_t offset) override;
+ virtual void write_l(offs_t offset, u8 data) override;
+ virtual void write_h(offs_t offset, u8 data) override;
virtual void chr_cb(int start, int bank, int source) override;
virtual void pcb_reset() override;
protected:
// device-level overrides
- virtual void device_start() override;
+ virtual void device_start() override ATTR_COLD;
+
+ virtual void set_prg(int prg_base, int prg_mask) override;
private:
- void update_regs();
- uint8_t m_reg[8];
- uint8_t m_low_reg;
+ u8 m_reg[5];
+ u8 m_low_reg;
};
@@ -228,21 +274,23 @@ class nes_h2288_device : public nes_txrom_device
{
public:
// construction/destruction
- nes_h2288_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
+ nes_h2288_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock);
- virtual uint8_t read_l(offs_t offset) override;
- virtual void write_l(offs_t offset, uint8_t data) override;
- virtual void write_h(offs_t offset, uint8_t data) override;
+// FIXME: This is a hack and should be removed once open bus behavior is properly working. UMK3 depends on an open bus read (F51F: lda $5f74) at bootup.
+ virtual u8 read_l(offs_t offset) override { return 0x5f; }
+
+ virtual void write_l(offs_t offset, u8 data) override;
+ virtual void write_h(offs_t offset, u8 data) override;
virtual void prg_cb(int start, int bank) override;
virtual void pcb_reset() override;
protected:
// device-level overrides
- virtual void device_start() override;
+ virtual void device_start() override ATTR_COLD;
private:
- uint8_t m_reg[2]; // reg 1 is unused?
+ bool m_mmc3_mode;
};
@@ -265,7 +313,7 @@ public:
protected:
// device-level overrides
- virtual void device_start() override;
+ virtual void device_start() override ATTR_COLD;
private:
uint8_t m_prot;
@@ -280,7 +328,6 @@ public:
// construction/destruction
nes_txc_tw_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
- // device-level overrides
virtual void write_l(offs_t offset, uint8_t data) override;
virtual void write_m(offs_t offset, uint8_t data) override { write_l(offset & 0xff, data); } // offset does not really count for this mapper }
virtual void prg_cb(int start, int bank) override;
@@ -295,7 +342,6 @@ public:
// construction/destruction
nes_kof97_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
- // device-level overrides
virtual void write_h(offs_t offset, uint8_t data) override;
};
@@ -306,11 +352,10 @@ class nes_kof96_device : public nes_txrom_device
{
public:
// construction/destruction
- nes_kof96_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
+ nes_kof96_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock);
- virtual uint8_t read_l(offs_t offset) override;
- virtual void write_l(offs_t offset, uint8_t data) override;
- virtual void write_h(offs_t offset, uint8_t data) override; // offset does not really count for this mapper
+ virtual u8 read_l(offs_t offset) override;
+ virtual void write_l(offs_t offset, u8 data) override;
virtual void prg_cb(int start, int bank) override;
virtual void chr_cb(int start, int bank, int source) override;
@@ -318,10 +363,10 @@ public:
protected:
// device-level overrides
- virtual void device_start() override;
+ virtual void device_start() override ATTR_COLD;
private:
- uint8_t m_reg[4];
+ bool m_mmc3_mode;
};
@@ -333,7 +378,6 @@ public:
// construction/destruction
nes_sf3_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
- // device-level overrides
virtual void write_h(offs_t offset, uint8_t data) override;
protected:
@@ -341,6 +385,20 @@ protected:
};
+// ======================> nes_cocoma_device
+
+class nes_cocoma_device : public nes_txrom_device
+{
+public:
+ // construction/destruction
+ nes_cocoma_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock);
+
+ virtual void write_h(offs_t offset, u8 data) override;
+
+ virtual void pcb_reset() override;
+};
+
+
// ======================> nes_gouder_device
class nes_gouder_device : public nes_txrom_device
@@ -357,7 +415,7 @@ public:
protected:
// device-level overrides
- virtual void device_start() override;
+ virtual void device_start() override ATTR_COLD;
private:
uint8_t m_reg[5];
@@ -379,7 +437,7 @@ public:
protected:
// device-level overrides
- virtual void device_start() override;
+ virtual void device_start() override ATTR_COLD;
private:
uint8_t m_reg;
@@ -393,23 +451,48 @@ class nes_sachen_shero_device : public nes_txrom_device
{
public:
// construction/destruction
- nes_sachen_shero_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
+ nes_sachen_shero_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock);
- virtual uint8_t read_l(offs_t offset) override;
- virtual void write_l(offs_t offset, uint8_t data) override;
+ virtual u8 read_l(offs_t offset) override;
+ virtual void write_l(offs_t offset, u8 data) override;
virtual void chr_cb(int start, int bank, int source) override;
virtual void pcb_reset() override;
protected:
// device-level overrides
- virtual void device_start() override;
+ virtual ioport_constructor device_input_ports() const override ATTR_COLD;
+ virtual void device_start() override ATTR_COLD;
private:
- uint8_t m_reg;
+ required_ioport m_jumper;
+ u8 m_reg;
+};
+
+// ======================> nes_sachen_zgdh_device
+
+class nes_sachen_zgdh_device : public nes_txrom_device
+{
+public:
+ // construction/destruction
+ nes_sachen_zgdh_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock);
+
+ virtual void write_l(offs_t offset, u8 data) override;
+ virtual u8 nt_r(offs_t offset) override;
+ virtual void nt_w(offs_t offset, u8 data) override;
+
+ virtual void pcb_reset() override;
+
+protected:
+ // device-level overrides
+ virtual void device_start() override ATTR_COLD;
+
+ virtual void set_chr(u8 chr, int chr_base, int chr_mask) override;
+
+private:
+ u8 m_reg;
};
-#ifdef UNUSED_FUNCTION
// ======================> nes_a9746_device
class nes_a9746_device : public nes_txrom_device
@@ -420,17 +503,53 @@ public:
virtual void write_h(offs_t offset, uint8_t data) override;
- virtual void pcb_reset();
+ virtual void pcb_reset() override;
protected:
// device-level overrides
- virtual void device_start() override;
+ virtual void device_start() override ATTR_COLD;
private:
void update_banks(uint8_t value);
uint8_t m_reg[3];
};
-#endif
+
+
+// ======================> nes_a88s1_device
+
+class nes_a88s1_device : public nes_txrom_device
+{
+public:
+ // construction/destruction
+ nes_a88s1_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock);
+
+ virtual void write_l(offs_t offset, u8 data) override;
+ virtual void prg_cb(int start, int bank) override;
+
+ virtual void pcb_reset() override;
+
+protected:
+ // device-level overrides
+ virtual void device_start() override ATTR_COLD;
+
+private:
+ void update_banks();
+ u8 m_reg[2];
+};
+
+
+// ======================> nes_bmc_el86xc_device
+
+class nes_bmc_el86xc_device : public nes_txrom_device
+{
+public:
+ // construction/destruction
+ nes_bmc_el86xc_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock);
+
+ virtual void write_m(offs_t offset, u8 data) override;
+
+ virtual void pcb_reset() override;
+};
// ======================> nes_fk23c_device
@@ -452,7 +571,7 @@ protected:
nes_fk23c_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_start() override ATTR_COLD;
void fk23c_set_prg();
void fk23c_set_chr();
@@ -473,6 +592,39 @@ public:
};
+// ======================> nes_nt639_device
+
+class nes_nt639_device : public nes_txrom_device
+{
+public:
+ // construction/destruction
+ nes_nt639_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock);
+
+ virtual void write_m(offs_t offset, u8 data) override;
+
+ virtual void pcb_reset() override;
+};
+
+
+// ======================> nes_resettxrom_device
+
+class nes_resettxrom_device : public nes_txrom_device
+{
+public:
+ // construction/destruction
+ nes_resettxrom_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock);
+
+ virtual void pcb_reset() override;
+
+protected:
+ // device-level overrides
+ virtual void device_start() override ATTR_COLD;
+
+private:
+ int m_count;
+};
+
+
// ======================> nes_s24in1sc03_device
class nes_s24in1sc03_device : public nes_txrom_device
@@ -489,25 +641,85 @@ public:
protected:
// device-level overrides
- virtual void device_start() override;
+ virtual void device_start() override ATTR_COLD;
private:
uint8_t m_reg[3];
};
+// ======================> nes_tech9in1_device
+
+class nes_tech9in1_device : public nes_txrom_device
+{
+public:
+ // construction/destruction
+ nes_tech9in1_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock);
+
+ virtual void write_l(offs_t offset, u8 data) override;
+
+ virtual void pcb_reset() override;
+
+protected:
+ // device-level overrides
+ virtual void device_start() override ATTR_COLD;
+
+private:
+ void update_banks();
+ u8 m_reg[3];
+};
+
+
+// ======================> nes_bmc_5in1_device
+
+class nes_bmc_5in1_device : public nes_txrom_device
+{
+public:
+ // construction/destruction
+ nes_bmc_5in1_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock);
+
+ virtual u8 read_m(offs_t offset) override;
+ virtual void write_m(offs_t offset, u8 data) override;
+
+ virtual void pcb_reset() override;
+
+protected:
+ // device-level overrides
+ virtual ioport_constructor device_input_ports() const override ATTR_COLD;
+
+private:
+ required_ioport m_jumper;
+};
+
+
+// ======================> nes_bmc_8in1_device
+
+class nes_bmc_8in1_device : public nes_txrom_device
+{
+public:
+ // construction/destruction
+ nes_bmc_8in1_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock);
+
+ virtual void write_h(offs_t offset, u8 data) override;
+
+ virtual void pcb_reset() override;
+};
+
+
// ======================> nes_bmc_15in1_device
class nes_bmc_15in1_device : public nes_txrom_device
{
public:
// construction/destruction
- nes_bmc_15in1_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
+ nes_bmc_15in1_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock);
- // device-level overrides
- virtual void write_m(offs_t offset, uint8_t data) override;
+ virtual void write_m(offs_t offset, u8 data) override;
virtual void pcb_reset() override;
+
+private:
+ u8 m_jumper;
};
@@ -519,7 +731,6 @@ public:
// construction/destruction
nes_bmc_sbig7_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
- // device-level overrides
virtual void write_h(offs_t offset, uint8_t data) override;
virtual void pcb_reset() override;
@@ -532,19 +743,84 @@ class nes_bmc_hik8_device : public nes_txrom_device
{
public:
// construction/destruction
- nes_bmc_hik8_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
+ nes_bmc_hik8_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock);
- virtual void write_m(offs_t offset, uint8_t data) override;
+ virtual void write_m(offs_t offset, u8 data) override;
+
+ virtual void pcb_reset() override;
+
+protected:
+ // construction/destruction
+ nes_bmc_hik8_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, u32 clock);
+
+ // device-level overrides
+ virtual void device_start() override ATTR_COLD;
+
+ u8 m_reg[4];
+ u8 m_count;
+};
+
+
+// ======================> nes_bmc_jy208_device
+
+class nes_bmc_jy208_device : public nes_bmc_hik8_device
+{
+public:
+ // construction/destruction
+ nes_bmc_jy208_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock);
+
+ virtual void write_m(offs_t offset, u8 data) override;
+
+protected:
+ virtual void set_chr(u8 chr, int chr_base, int chr_mask) override;
+};
+
+
+// ======================> nes_bmc_jy302_device
+
+class nes_bmc_jy302_device : public nes_bmc_hik8_device
+{
+public:
+ // construction/destruction
+ nes_bmc_jy302_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock);
+
+protected:
+ virtual void set_chr(u8 chr, int chr_base, int chr_mask) override;
+};
+
+
+// ======================> nes_bmc_kc885_device
+
+class nes_bmc_kc885_device : public nes_bmc_hik8_device
+{
+public:
+ // construction/destruction
+ nes_bmc_kc885_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock);
+
+ virtual u8 read_h(offs_t offset) override;
+ virtual void write_m(offs_t offset, u8 data) override;
virtual void pcb_reset() override;
protected:
// device-level overrides
- virtual void device_start() override;
+ virtual ioport_constructor device_input_ports() const override ATTR_COLD;
private:
- uint8_t m_reg[4];
- uint8_t m_count;
+ required_ioport m_jumper;
+};
+
+
+// ======================> nes_bmc_sfc12_device
+
+class nes_bmc_sfc12_device : public nes_bmc_hik8_device
+{
+public:
+ // construction/destruction
+ nes_bmc_sfc12_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock);
+
+protected:
+ virtual void set_chr(u8 chr, int chr_base, int chr_mask) override;
};
@@ -554,33 +830,82 @@ class nes_bmc_hik4_device : public nes_txrom_device
{
public:
// construction/destruction
- nes_bmc_hik4_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
+ nes_bmc_hik4_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock);
+
+ virtual void write_m(offs_t offset, u8 data) override;
+ virtual void prg_cb(int start, int bank) override;
+
+ virtual void pcb_reset() override;
+protected:
// device-level overrides
- virtual void write_m(offs_t offset, uint8_t data) override;
+ virtual void device_start() override ATTR_COLD;
+
+private:
+ bool m_mmc3_mode;
+};
+
+
+// ======================> nes_bmc_f15_device
+
+class nes_bmc_f15_device : public nes_txrom_device
+{
+public:
+ // construction/destruction
+ nes_bmc_f15_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock);
+
+ virtual void write_m(offs_t offset, u8 data) override;
+ virtual void prg_cb(int start, int bank) override;
virtual void pcb_reset() override;
};
-// ======================> nes_bmc_mario7in1_device
+// ======================> nes_bmc_f600_device
-class nes_bmc_mario7in1_device : public nes_txrom_device
+class nes_bmc_f600_device : public nes_txsrom_device
{
public:
// construction/destruction
- nes_bmc_mario7in1_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
+ nes_bmc_f600_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock);
+
+ virtual u8 read_l(offs_t offset) override;
+ virtual void write_l(offs_t offset, u8 data) override;
+ virtual void write_h(offs_t offset, u8 data) override;
+
+ virtual void pcb_reset() override;
+
+protected:
+ // device-level overrides
+ virtual ioport_constructor device_input_ports() const override ATTR_COLD;
+ virtual void device_start() override ATTR_COLD;
+
+ virtual void set_chr(u8 chr, int chr_base, int chr_mask) override;
+
+private:
+ required_ioport m_jumper;
+ u8 m_reg;
+};
- virtual void write_m(offs_t offset, uint8_t data) override;
+
+// ======================> nes_bmc_gn45_device
+
+class nes_bmc_gn45_device : public nes_txrom_device
+{
+public:
+ // construction/destruction
+ nes_bmc_gn45_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock);
+
+ virtual void write_m(offs_t offset, u8 data) override;
virtual void pcb_reset() override;
protected:
// device-level overrides
- virtual void device_start() override;
+ virtual void device_start() override ATTR_COLD;
private:
- uint8_t m_reg_written;
+ bool m_lock;
};
@@ -590,42 +915,103 @@ class nes_bmc_gold7in1_device : public nes_txrom_device
{
public:
// construction/destruction
- nes_bmc_gold7in1_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
+ nes_bmc_gold7in1_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock);
- virtual void write_m(offs_t offset, uint8_t data) override;
+ virtual void write_m(offs_t offset, u8 data) override;
virtual void pcb_reset() override;
protected:
// device-level overrides
- virtual void device_start() override;
+ virtual void device_start() override ATTR_COLD;
private:
- uint8_t m_reg_written;
+ bool m_lock;
};
-// ======================> nes_bmc_gc6in1_device
+// ======================> nes_bmc_k3006_device
-class nes_bmc_gc6in1_device : public nes_txrom_device
+class nes_bmc_k3006_device : public nes_txrom_device
{
public:
// construction/destruction
- nes_bmc_gc6in1_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
+ nes_bmc_k3006_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock);
- virtual void write_l(offs_t offset, uint8_t data) override;
- virtual void write_h(offs_t offset, uint8_t data) override;
+ virtual void write_m(offs_t offset, u8 data) override;
+
+ virtual void pcb_reset() override;
+};
+
+
+// ======================> nes_bmc_k3033_device
+
+class nes_bmc_k3033_device : public nes_txrom_device
+{
+public:
+ // construction/destruction
+ nes_bmc_k3033_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock);
+
+ virtual void write_m(offs_t offset, u8 data) override;
virtual void prg_cb(int start, int bank) override;
- virtual void chr_cb(int start, int bank, int source) override;
virtual void pcb_reset() override;
protected:
// device-level overrides
- virtual void device_start() override;
+ virtual void device_start() override ATTR_COLD;
private:
- uint8_t m_reg[4];
+ bool m_mmc3_mode;
+};
+
+
+// ======================> nes_bmc_l6in1_device
+
+class nes_bmc_l6in1_device : public nes_txrom_device
+{
+public:
+ // construction/destruction
+ nes_bmc_l6in1_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock);
+
+ virtual void write_m(offs_t offset, u8 data) override;
+ virtual void write_h(offs_t offset, u8 data) override;
+
+ virtual void pcb_reset() override;
+
+protected:
+ // device-level overrides
+ virtual void device_start() override ATTR_COLD;
+
+ virtual void set_prg(int prg_base, int prg_mask) override;
+
+private:
+ void set_mirror();
+ u8 m_reg;
+};
+
+
+// ======================> nes_bmc_00202650_device
+
+class nes_bmc_00202650_device : public nes_txrom_device
+{
+public:
+ // construction/destruction
+ nes_bmc_00202650_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock);
+
+ virtual void write_m(offs_t offset, u8 data) override;
+
+ virtual void pcb_reset() override;
+
+protected:
+ // device-level overrides
+ virtual void device_start() override ATTR_COLD;
+
+ virtual void set_prg(int prg_base, int prg_mask) override;
+ virtual void set_chr(u8 chr, int chr_base, int chr_mask) override;
+
+private:
+ bool m_mmc3_mode;
};
@@ -635,20 +1021,68 @@ class nes_bmc_411120c_device : public nes_txrom_device
{
public:
// construction/destruction
- nes_bmc_411120c_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
+ nes_bmc_411120c_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock);
- virtual void write_m(offs_t offset, uint8_t data) override;
+ virtual void write_m(offs_t offset, u8 data) override;
virtual void prg_cb(int start, int bank) override;
- virtual void chr_cb(int start, int bank, int source) override;
virtual void pcb_reset() override;
protected:
// device-level overrides
- virtual void device_start() override;
+ virtual void device_start() override ATTR_COLD;
private:
- uint8_t m_reg;
+ u8 m_reg;
+};
+
+
+// ======================> nes_bmc_810305c_device
+
+class nes_bmc_810305c_device : public nes_txsrom_device
+{
+public:
+ // construction/destruction
+ nes_bmc_810305c_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock);
+
+ virtual void write_h(offs_t offset, u8 data) override;
+
+ virtual void pcb_reset() override;
+
+protected:
+ // device-level overrides
+ virtual void device_start() override ATTR_COLD;
+
+ virtual void set_prg(int prg_base, int prg_mask) override;
+ virtual void set_chr(u8 chr, int chr_base, int chr_mask) override;
+
+private:
+ u8 m_outer;
+};
+
+
+// ======================> nes_bmc_820720c_device
+
+class nes_bmc_820720c_device : public nes_txrom_device
+{
+public:
+ // construction/destruction
+ nes_bmc_820720c_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock);
+
+ virtual void write_m(offs_t offset, u8 data) override;
+ virtual void write_h(offs_t offset, u8 data) override;
+
+ virtual void pcb_reset() override;
+
+protected:
+ // device-level overrides
+ virtual void device_start() override ATTR_COLD;
+
+ virtual void set_prg(int prg_base, int prg_mask) override;
+ virtual void set_chr(u8 chr, int chr_base, int chr_mask) override;
+
+private:
+ u8 m_reg;
};
@@ -658,20 +1092,61 @@ class nes_bmc_830118c_device : public nes_txrom_device
{
public:
// construction/destruction
- nes_bmc_830118c_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
+ nes_bmc_830118c_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock);
- virtual void write_m(offs_t offset, uint8_t data) override;
+ virtual void write_m(offs_t offset, u8 data) override;
virtual void prg_cb(int start, int bank) override;
- virtual void chr_cb(int start, int bank, int source) override;
+
+ virtual void pcb_reset() override;
+};
+
+
+// ======================> nes_bmc_830832c_device
+
+class nes_bmc_830832c_device : public nes_txrom_device
+{
+public:
+ // construction/destruction
+ nes_bmc_830832c_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock);
+
+ virtual void write_m(offs_t offset, u8 data) override;
+
+ virtual void pcb_reset() override;
+};
+
+
+// ======================> nes_bmc_yy841101c_device
+
+class nes_bmc_yy841101c_device : public nes_txrom_device
+{
+public:
+ // construction/destruction
+ nes_bmc_yy841101c_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock);
+
+ virtual void write_m(offs_t offset, u8 data) override;
+
+ virtual void pcb_reset() override;
+};
+
+
+// ======================> nes_bmc_yy841155c_device
+
+class nes_bmc_yy841155c_device : public nes_txrom_device
+{
+public:
+ // construction/destruction
+ nes_bmc_yy841155c_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock);
+
+ virtual void write_m(offs_t offset, u8 data) override;
virtual void pcb_reset() override;
protected:
// device-level overrides
- virtual void device_start() override;
+ virtual void device_start() override ATTR_COLD;
private:
- uint8_t m_reg;
+ u8 m_reg[2];
};
@@ -691,39 +1166,50 @@ public:
protected:
// device-level overrides
- virtual void device_start() override;
+ virtual void device_start() override ATTR_COLD;
private:
inline void set_base_mask();
uint8_t m_reg[4];
};
-// ======================> nes_coolboy_device
-class nes_coolboy_device : public nes_txrom_device
+// ======================> nes_smd133_device
+
+class nes_smd133_device : public nes_txrom_device
{
public:
// construction/destruction
- nes_coolboy_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
+ nes_smd133_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock);
- // device-level overrides
- virtual void write_m(offs_t offset, uint8_t data) override;
+ virtual void write_l(offs_t offset, u8 data) override;
+ virtual void write_m(offs_t offset, u8 data) override;
virtual void prg_cb(int start, int bank) override;
virtual void chr_cb(int start, int bank, int source) override;
+ virtual void pcb_reset() override;
+
+protected:
+ // device-level overrides
+ virtual void device_start() override ATTR_COLD;
+
private:
- uint8_t m_reg[4];
+ void smd133_write(offs_t offset, u8 data);
+ u8 m_reg[6];
};
// device type definition
DECLARE_DEVICE_TYPE(NES_NITRA, nes_nitra_device)
-DECLARE_DEVICE_TYPE(NES_KS7057, nes_ks7057_device)
+DECLARE_DEVICE_TYPE(NES_BMW8544, nes_bmw8544_device)
+DECLARE_DEVICE_TYPE(NES_FS6, nes_fs6_device)
DECLARE_DEVICE_TYPE(NES_SBROS11, nes_sbros11_device)
DECLARE_DEVICE_TYPE(NES_MALISB, nes_malisb_device)
DECLARE_DEVICE_TYPE(NES_FAMILY4646, nes_family4646_device)
DECLARE_DEVICE_TYPE(NES_PIKAY2K, nes_pikay2k_device)
DECLARE_DEVICE_TYPE(NES_8237, nes_8237_device)
+DECLARE_DEVICE_TYPE(NES_8237A, nes_8237a_device)
+DECLARE_DEVICE_TYPE(NES_158B, nes_158b_device)
DECLARE_DEVICE_TYPE(NES_SG_LIONK, nes_sglionk_device)
DECLARE_DEVICE_TYPE(NES_SG_BOOG, nes_sgboog_device)
DECLARE_DEVICE_TYPE(NES_KASING, nes_kasing_device)
@@ -734,26 +1220,47 @@ DECLARE_DEVICE_TYPE(NES_TXC_TW, nes_txc_tw_device)
DECLARE_DEVICE_TYPE(NES_KOF97, nes_kof97_device)
DECLARE_DEVICE_TYPE(NES_KOF96, nes_kof96_device)
DECLARE_DEVICE_TYPE(NES_SF3, nes_sf3_device)
+DECLARE_DEVICE_TYPE(NES_COCOMA, nes_cocoma_device)
DECLARE_DEVICE_TYPE(NES_GOUDER, nes_gouder_device)
DECLARE_DEVICE_TYPE(NES_SA9602B, nes_sa9602b_device)
DECLARE_DEVICE_TYPE(NES_SACHEN_SHERO, nes_sachen_shero_device)
-#ifdef UNUSED_FUNCTION
+DECLARE_DEVICE_TYPE(NES_SACHEN_ZGDH, nes_sachen_zgdh_device)
DECLARE_DEVICE_TYPE(NES_A9746, nes_a9746_device)
-#endif
+DECLARE_DEVICE_TYPE(NES_A88S1, nes_a88s1_device)
+DECLARE_DEVICE_TYPE(NES_BMC_EL86XC, nes_bmc_el86xc_device)
DECLARE_DEVICE_TYPE(NES_FK23C, nes_fk23c_device)
DECLARE_DEVICE_TYPE(NES_FK23CA, nes_fk23ca_device)
+DECLARE_DEVICE_TYPE(NES_NT639, nes_nt639_device)
+DECLARE_DEVICE_TYPE(NES_RESETTXROM, nes_resettxrom_device)
DECLARE_DEVICE_TYPE(NES_S24IN1SC03, nes_s24in1sc03_device)
+DECLARE_DEVICE_TYPE(NES_TECHLINE9IN1, nes_tech9in1_device)
+DECLARE_DEVICE_TYPE(NES_BMC_5IN1, nes_bmc_5in1_device)
+DECLARE_DEVICE_TYPE(NES_BMC_8IN1, nes_bmc_8in1_device)
DECLARE_DEVICE_TYPE(NES_BMC_15IN1, nes_bmc_15in1_device)
DECLARE_DEVICE_TYPE(NES_BMC_SBIG7, nes_bmc_sbig7_device)
DECLARE_DEVICE_TYPE(NES_BMC_HIK8, nes_bmc_hik8_device)
+DECLARE_DEVICE_TYPE(NES_BMC_JY208, nes_bmc_jy208_device)
+DECLARE_DEVICE_TYPE(NES_BMC_JY302, nes_bmc_jy302_device)
+DECLARE_DEVICE_TYPE(NES_BMC_KC885, nes_bmc_kc885_device)
+DECLARE_DEVICE_TYPE(NES_BMC_SFC12, nes_bmc_sfc12_device)
DECLARE_DEVICE_TYPE(NES_BMC_HIK4, nes_bmc_hik4_device)
-DECLARE_DEVICE_TYPE(NES_BMC_MARIO7IN1, nes_bmc_mario7in1_device)
+DECLARE_DEVICE_TYPE(NES_BMC_F15, nes_bmc_f15_device)
+DECLARE_DEVICE_TYPE(NES_BMC_F600, nes_bmc_f600_device)
+DECLARE_DEVICE_TYPE(NES_BMC_GN45, nes_bmc_gn45_device)
DECLARE_DEVICE_TYPE(NES_BMC_GOLD7IN1, nes_bmc_gold7in1_device)
-DECLARE_DEVICE_TYPE(NES_BMC_GC6IN1, nes_bmc_gc6in1_device)
+DECLARE_DEVICE_TYPE(NES_BMC_K3006, nes_bmc_k3006_device)
+DECLARE_DEVICE_TYPE(NES_BMC_K3033, nes_bmc_k3033_device)
+DECLARE_DEVICE_TYPE(NES_BMC_L6IN1, nes_bmc_l6in1_device)
+DECLARE_DEVICE_TYPE(NES_BMC_00202650, nes_bmc_00202650_device)
DECLARE_DEVICE_TYPE(NES_BMC_411120C, nes_bmc_411120c_device)
+DECLARE_DEVICE_TYPE(NES_BMC_810305C, nes_bmc_810305c_device)
+DECLARE_DEVICE_TYPE(NES_BMC_820720C, nes_bmc_820720c_device)
DECLARE_DEVICE_TYPE(NES_BMC_830118C, nes_bmc_830118c_device)
+DECLARE_DEVICE_TYPE(NES_BMC_830832C, nes_bmc_830832c_device)
+DECLARE_DEVICE_TYPE(NES_BMC_YY841101C, nes_bmc_yy841101c_device)
+DECLARE_DEVICE_TYPE(NES_BMC_YY841155C, nes_bmc_yy841155c_device)
DECLARE_DEVICE_TYPE(NES_PJOY84, nes_pjoy84_device)
-DECLARE_DEVICE_TYPE(NES_COOLBOY, nes_coolboy_device)
+DECLARE_DEVICE_TYPE(NES_SMD133, nes_smd133_device)
#endif // MAME_BUS_NES_MMC3_CLONES_H
diff --git a/src/devices/bus/nes/mmc5.cpp b/src/devices/bus/nes/mmc5.cpp
index 171af3c86e9..1b0bf30caf3 100644
--- a/src/devices/bus/nes/mmc5.cpp
+++ b/src/devices/bus/nes/mmc5.cpp
@@ -20,19 +20,21 @@
#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
#define LAST_CHR_REG_B 1
-static const int m_mmc5_attrib[4] = {0x00, 0x55, 0xaa, 0xff};
+static const uint8_t m_mmc5_attrib[4] = {0x00, 0x55, 0xaa, 0xff};
//-------------------------------------------------
// constructor
@@ -43,11 +45,11 @@ DEFINE_DEVICE_TYPE(NES_EXROM, nes_exrom_device, "nes_exrom", "NES Cart ExROM (MM
nes_exrom_device::nes_exrom_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
: nes_nrom_device(mconfig, NES_EXROM, tag, owner, clock), m_irq_count(0)
- , m_irq_status(0), m_irq_enable(0), m_mult1(0), m_mult2(0), m_mmc5_scanline(0), m_vrom_page_a(0), m_vrom_page_b(0), m_floodtile(0), m_floodattr(0)
+ , m_irq_status(0), m_irq_enable(false), m_pcm_irq(false), m_mult1(0), m_mult2(0), m_mmc5_scanline(0), m_vrom_page_a(0), m_vrom_page_b(0), m_floodtile(0), m_floodattr(0)
, m_prg_mode(0), m_chr_mode(0), m_wram_protect_1(0), m_wram_protect_2(0), m_exram_control(0), m_wram_base(0), m_last_chr(0), m_ex1_chr(0)
, m_split_chr(0), m_ex1_bank(0), m_ex1_attrib(0), m_high_chr(0), m_split_scr(0), m_split_rev(0), m_split_ctrl(0), m_split_yst(0), m_split_bank(0), m_vcount(0)
, m_ppu(*this, ":ppu") // FIXME: this dependency should not exist
- , m_sound(*this, "mmc5snd") // FIXME: this is a hack, it should be separated device, similar not same as NES APU!!!
+ , m_sound(*this, "mmc5snd")
{
}
@@ -62,6 +64,7 @@ void nes_exrom_device::device_start()
save_item(NAME(m_irq_count));
save_item(NAME(m_irq_status));
save_item(NAME(m_irq_enable));
+ save_item(NAME(m_pcm_irq));
save_item(NAME(m_mult1));
save_item(NAME(m_mult2));
save_item(NAME(m_vrom_page_a));
@@ -96,14 +99,14 @@ void nes_exrom_device::device_start()
void nes_exrom_device::pcb_reset()
{
- m_chr_source = m_vrom_chunks ? CHRROM : CHRRAM;
prg16_89ab(m_prg_chunks - 2);
prg16_cdef(m_prg_chunks - 1);
chr8(0, m_chr_source);
m_irq_count = 0;
m_irq_status = 0;
- m_irq_enable = 0;
+ m_irq_enable = false;
+ m_pcm_irq = false;
m_mult1 = m_mult2 = 0;
m_vrom_page_a = m_vrom_page_b = 0;
@@ -159,7 +162,7 @@ void nes_exrom_device::pcb_reset()
iNES: mapper 5
- MESS status: Partially supported
+ MAME status: Partially supported
-------------------------------------------------*/
@@ -236,16 +239,20 @@ void nes_exrom_device::update_prg()
}
}
-void nes_exrom_device::hblank_irq(int scanline, int vblank, int blanked )
+void nes_exrom_device::update_irq()
+{
+ set_irq_line(((BIT(m_irq_status, 7) && m_irq_enable) || m_pcm_irq) ? ASSERT_LINE : CLEAR_LINE);
+}
+
+
+void nes_exrom_device::hblank_irq(int scanline, bool vblank, bool blanked)
{
m_vcount = scanline;
if (scanline == m_irq_count)
{
- if (m_irq_enable)
- set_irq_line(ASSERT_LINE);
-
m_irq_status = 0xff;
+ update_irq();
}
// "In Frame" flag
@@ -256,6 +263,13 @@ void nes_exrom_device::hblank_irq(int scanline, int vblank, int blanked )
}
+void nes_exrom_device::pcm_irq(int state)
+{
+ m_pcm_irq = state;
+ update_irq();
+}
+
+
void nes_exrom_device::set_mirror(int page, int src)
{
switch (src)
@@ -279,7 +293,7 @@ void nes_exrom_device::set_mirror(int page, int src)
inline bool nes_exrom_device::in_split()
{
- int tile = m_ppu->get_tilenum();
+ int const tile = m_ppu->get_tilenum();
if (tile < 34)
{
@@ -293,7 +307,7 @@ inline bool nes_exrom_device::in_split()
uint8_t nes_exrom_device::nt_r(offs_t offset)
{
- int page = ((offset & 0xc00) >> 10);
+ int const page = ((offset & 0xc00) >> 10);
switch (m_nt_src[page])
{
@@ -315,16 +329,16 @@ uint8_t nes_exrom_device::nt_r(offs_t offset)
// but it does not work yet
if (m_split_scr && !(m_exram_control & 0x02) && in_split())
{
- int tile = m_ppu->get_tilenum();
+ int const tile = m_ppu->get_tilenum();
if ((offset & 0x3ff) >= 0x3c0)
{
- int pos = (((m_split_yst + m_vcount) & ~0x1f) | (tile & 0x1f)) >> 2;
+ int const pos = (((m_split_yst + m_vcount) & ~0x1f) | (tile & 0x1f)) >> 2;
return m_exram[0x3c0 | pos];
}
else
{
- int pos = (((m_split_yst + m_vcount) & 0xf8) << 2) | (tile & 0x1f);
+ int const pos = (((m_split_yst + m_vcount) & 0xf8) << 2) | (tile & 0x1f);
return m_exram[pos];
}
}
@@ -346,7 +360,7 @@ uint8_t nes_exrom_device::nt_r(offs_t offset)
void nes_exrom_device::nt_w(offs_t offset, uint8_t data)
{
- int page = ((offset & 0xc00) >> 10);
+ int const page = ((offset & 0xc00) >> 10);
if (!m_nt_writable[page])
return;
@@ -392,19 +406,19 @@ inline uint8_t nes_exrom_device::base_chr_r(int bank, uint32_t offset)
inline uint8_t nes_exrom_device::split_chr_r(uint32_t offset)
{
- uint32_t helper = (m_split_bank * 0x1000) + (offset & 0x3f8) + (m_split_yst & 7);
+ uint32_t const helper = (m_split_bank * 0x1000) + (offset & 0x3f8) + (m_split_yst & 7);
return m_vrom[helper & (m_vrom_size - 1)];
}
inline uint8_t nes_exrom_device::bg_ex1_chr_r(uint32_t offset)
{
- uint32_t helper = (m_ex1_bank * 0x1000) + (offset & 0xfff);
+ uint32_t const helper = (m_ex1_bank * 0x1000) + (offset & 0xfff);
return m_vrom[helper & (m_vrom_size - 1)];
}
uint8_t nes_exrom_device::chr_r(offs_t offset)
{
- int bank = offset >> 10;
+ int const bank = offset >> 10;
// Extended Attribute Mode (Ex1) does affect BG drawing even for 8x16 sprites (JustBreed uses it extensively!)
// However, if a game enables Ex1 but does not write a new m_ex1_bank, I'm not sure here we get the correct behavior
@@ -433,9 +447,12 @@ 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 >= 0x1000) && (offset <= 0x1015))
+ return m_sound->read(offset & 0x1f);
+
if ((offset >= 0x1c00) && (offset <= 0x1fff))
{
// EXRAM
@@ -452,7 +469,7 @@ uint8_t nes_exrom_device::read_l(offs_t offset)
if (!machine().side_effects_disabled())
{
m_irq_status &= ~0x80;
- set_irq_line(CLEAR_LINE);
+ update_irq();
}
return value;
@@ -464,7 +481,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();
}
}
@@ -472,7 +489,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))
@@ -488,7 +505,7 @@ void nes_exrom_device::write_l(offs_t offset, uint8_t data)
m_exram[offset - 0x1c00] = data;
else if (m_exram_control != 0x03) // Modes 0,1 = write data in frame / write 0 otherwise
{
- if (m_irq_status & 0x40)
+ if (BIT(m_irq_status, 6))
m_exram[offset - 0x1c00] = data;
else
m_exram[offset - 0x1c00] = 0x00;
@@ -502,29 +519,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:
@@ -543,7 +560,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;
@@ -604,12 +621,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));
+ m_irq_enable = BIT(data, 7);
+ LOG("MMC5 irq enable: %02x\n", data);
break;
case 0x1205:
@@ -621,7 +638,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;
}
}
@@ -632,10 +649,10 @@ 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)
+ if (BIT(m_wram_base, 2))
return m_prgram[(offset + (m_wram_base & 0x03) * 0x2000) & (m_prgram.size() - 1)];
else
return m_battery[(offset + (m_wram_base & 0x03) * 0x2000) & (m_battery.size() - 1)];
@@ -650,7 +667,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;
@@ -663,24 +680,31 @@ 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));
- int bank = offset / 0x2000;
+ LOG("exrom read_h, offset: %04x\n", offset);
+ int const bank = offset / 0x2000;
+ uint8_t ret = 0;
if (bank < 3 && offset >= bank * 0x2000 && offset < (bank + 1) * 0x2000 && m_prg_ram_mapped[bank])
{
if (!m_battery.empty() && m_ram_hi_banks[bank] < 4)
- return m_battery[((m_ram_hi_banks[bank] * 0x2000) + (offset & 0x1fff)) & (m_battery.size() - 1)];
+ ret = m_battery[((m_ram_hi_banks[bank] * 0x2000) + (offset & 0x1fff)) & (m_battery.size() - 1)];
else if (!m_prgram.empty())
- return m_prgram[(((m_ram_hi_banks[bank] & 3) * 0x2000) + (offset & 0x1fff)) & (m_prgram.size() - 1)];
+ ret = m_prgram[(((m_ram_hi_banks[bank] & 3) * 0x2000) + (offset & 0x1fff)) & (m_prgram.size() - 1)];
}
-
- return hi_access_rom(offset);
+ else
+ ret = hi_access_rom(offset);
+ if (!machine().side_effects_disabled())
+ {
+ if (BIT(~offset, 14))
+ m_sound->pcm_w(ret);
+ }
+ return ret;
}
void nes_exrom_device::write_h(offs_t offset, uint8_t data)
{
- LOG_MMC(("exrom write_h, offset: %04x, data: %02x\n", offset, data));
- int bank = offset / 0x2000;
+ LOG("exrom write_h, offset: %04x, data: %02x\n", offset, data);
+ int const bank = offset / 0x2000;
if (m_wram_protect_1 != 0x02 || m_wram_protect_2 != 0x01 || bank == 3 || !m_prg_ram_mapped[bank])
return;
@@ -699,6 +723,7 @@ void nes_exrom_device::device_add_mconfig(machine_config &config)
// additional sound hardware
SPEAKER(config, "addon").front_center();
- // TODO: temporary; will be separated device
- NES_APU(config, m_sound, XTAL(21'477'272)/12).add_route(ALL_OUTPUTS, "addon", 0.90);
+ MMC5_SOUND(config, m_sound, XTAL(21'477'272)/12);
+ m_sound->irq().set(FUNC(nes_exrom_device::pcm_irq));
+ m_sound->add_route(ALL_OUTPUTS, "addon", 0.90);
}
diff --git a/src/devices/bus/nes/mmc5.h b/src/devices/bus/nes/mmc5.h
index 27a9709cafd..98be5dcfcd6 100644
--- a/src/devices/bus/nes/mmc5.h
+++ b/src/devices/bus/nes/mmc5.h
@@ -7,7 +7,7 @@
#include "nxrom.h"
-#include "sound/nes_apu.h" // temp hack to pass the additional sound regs to APU...
+#include "sound/mmc5.h"
#include "video/ppu2c0x.h" // this has to be included so that IRQ functions can access ppu2c0x_device::BOTTOM_VISIBLE_SCANLINE
@@ -31,17 +31,20 @@ public:
virtual uint8_t nt_r(offs_t offset) override;
virtual void nt_w(offs_t offset, uint8_t data) override;
- virtual void hblank_irq(int scanline, int vblank, int blanked) override;
+ virtual void hblank_irq(int scanline, bool vblank, bool blanked) override;
virtual void pcb_reset() override;
protected:
// device-level overrides
- virtual void device_add_mconfig(machine_config &config) override;
- virtual void device_start() override;
+ virtual void device_add_mconfig(machine_config &config) override ATTR_COLD;
+ virtual void device_start() override ATTR_COLD;
void set_mirror(int page, int src);
void update_prg();
+ void update_irq();
+ void pcm_irq(int state);
+
inline uint8_t base_chr_r(int bank, uint32_t offset);
inline uint8_t split_chr_r(uint32_t offset);
inline uint8_t bg_ex1_chr_r(uint32_t offset);
@@ -49,24 +52,25 @@ protected:
uint16_t m_irq_count;
uint8_t m_irq_status;
- int m_irq_enable;
+ bool m_irq_enable;
+ bool m_pcm_irq;
- int m_mult1, m_mult2;
+ int32_t m_mult1, m_mult2;
- int m_mmc5_scanline;
- int m_vrom_page_a;
- int m_vrom_page_b;
+ int32_t m_mmc5_scanline;
+ int32_t m_vrom_page_a;
+ int32_t m_vrom_page_b;
uint16_t m_vrom_bank[12]; // MMC5 has 10bit wide VROM regs!
- int m_floodtile;
- int m_floodattr;
+ uint8_t m_floodtile;
+ uint8_t m_floodattr;
- int m_prg_mode; // $5100
- int m_chr_mode; // $5101
- int m_wram_protect_1; // $5102
- int m_wram_protect_2; // $5103
- int m_exram_control; // $5104
- int m_wram_base; // $5113
+ uint8_t m_prg_mode; // $5100
+ uint8_t m_chr_mode; // $5101
+ uint8_t m_wram_protect_1; // $5102
+ uint8_t m_wram_protect_2; // $5103
+ uint8_t m_exram_control; // $5104
+ uint8_t m_wram_base; // $5113
uint8_t m_last_chr;
uint8_t m_ex1_chr;
@@ -84,7 +88,7 @@ protected:
uint8_t m_split_ctrl; // $5200
uint8_t m_split_yst; // $5201
uint8_t m_split_bank; // $5202
- int m_vcount;
+ int32_t m_vcount;
// MMC-5 contains 1K of internal ram
uint8_t m_exram[0x400];
@@ -94,7 +98,7 @@ protected:
// int m_nes_vram_sprite[8];
required_device<ppu2c0x_device> m_ppu;
- required_device<nesapu_device> m_sound;
+ required_device<mmc5_sound_device> m_sound;
};
diff --git a/src/devices/bus/nes/multigame.cpp b/src/devices/bus/nes/multigame.cpp
index c117520afe5..33e377fc6eb 100644
--- a/src/devices/bus/nes/multigame.cpp
+++ b/src/devices/bus/nes/multigame.cpp
@@ -8,6 +8,10 @@
Here we emulate several PCBs used in multigame pirate carts (not MMC-3 based)
+ TODO: Investigate further Gunsmoke on mc_8et40, mc_2gn91, mc_8x801. All have
+ the same bug where enemies/barrels don't appear until they are halfway down
+ the screeen. They all seem to be a minor hack of the US release.
+
***********************************************************************************************************/
@@ -15,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"
//-------------------------------------------------
@@ -29,31 +34,56 @@
//-------------------------------------------------
DEFINE_DEVICE_TYPE(NES_ACTION52, nes_action52_device, "nes_action52", "NES Cart Action 52 PCB")
-DEFINE_DEVICE_TYPE(NES_CALTRON6IN1, nes_caltron_device, "nes_caltron", "NES Cart Caltron 6 in 1 PCB")
+DEFINE_DEVICE_TYPE(NES_CALTRON6IN1, nes_caltron6in1_device, "nes_caltron6in1", "NES Cart Caltron 6 in 1 PCB")
+DEFINE_DEVICE_TYPE(NES_CALTRON9IN1, nes_caltron9in1_device, "nes_caltron9in1", "NES Cart Caltron 9 in 1 PCB")
DEFINE_DEVICE_TYPE(NES_RUMBLESTATION, nes_rumblestat_device, "nes_rumblestat", "NES Cart Rumblestation PCB")
DEFINE_DEVICE_TYPE(NES_SVISION16, nes_svision16_device, "nes_svision16", "NES Cart Supervision 16 in 1 PCB")
+DEFINE_DEVICE_TYPE(NES_FARID_UNROM, nes_farid_unrom_device, "nes_farid_unrom", "NES Cart Farid UNROM 8 in 1 PCB")
+DEFINE_DEVICE_TYPE(NES_KN42, nes_kn42_device, "nes_kn42", "NES Cart KN-42 PCB")
DEFINE_DEVICE_TYPE(NES_N625092, nes_n625092_device, "nes_n625092", "NES Cart N625092 PCB")
DEFINE_DEVICE_TYPE(NES_A65AS, nes_a65as_device, "nes_a65as", "NES Cart A65AS PCB")
DEFINE_DEVICE_TYPE(NES_T262, nes_t262_device, "nes_t262", "NES Cart T-262 PCB")
-DEFINE_DEVICE_TYPE(NES_NOVEL1, nes_novel1_device, "nes_novel1", "NES Cart Novel Diamond Type 1 PCB")
-DEFINE_DEVICE_TYPE(NES_NOVEL2, nes_novel2_device, "nes_novel2", "NES Cart Novel Diamond Type 2 PCB")
DEFINE_DEVICE_TYPE(NES_STUDYNGAME, nes_studyngame_device, "nes_studyngame", "NES Cart Study n Game PCB")
DEFINE_DEVICE_TYPE(NES_SUPERGUN20IN1, nes_sgun20in1_device, "nes_sgun20in1", "NES Cart Supergun 20 in 1 PCB")
DEFINE_DEVICE_TYPE(NES_VT5201, nes_vt5201_device, "nes_vt5201", "NES Cart VT5201 PCB")
-DEFINE_DEVICE_TYPE(NES_810544C, nes_810544c_device, "nes_810544c", "NES Cart 810544-C-A1 PCB")
+DEFINE_DEVICE_TYPE(NES_BMC_60311C, nes_bmc_60311c_device, "nes_bmc_60311c", "NES Cart BMC 60311C PCB")
+DEFINE_DEVICE_TYPE(NES_BMC_80013B, nes_bmc_80013b_device, "nes_bmc_80013b", "NES Cart BMC 80013-B PCB")
+DEFINE_DEVICE_TYPE(NES_BMC_810544C, nes_bmc_810544c_device, "nes_bmc_810544c", "NES Cart BMC 810544-C-A1 PCB")
+DEFINE_DEVICE_TYPE(NES_BMC_830425C, nes_bmc_830425c_device, "nes_bmc_830425c", "NES Cart BMC 830425C-4391T PCB")
+DEFINE_DEVICE_TYPE(NES_BMC_830928C, nes_bmc_830928c_device, "nes_bmc_830928c", "NES Cart BMC 830928C PCB")
+DEFINE_DEVICE_TYPE(NES_BMC_850437C, nes_bmc_850437c_device, "nes_bmc_850437c", "NES Cart BMC 850437C PCB")
+DEFINE_DEVICE_TYPE(NES_BMC_891227, nes_bmc_891227_device, "nes_bmc_891227", "NES Cart BMC 891227 PCB")
+DEFINE_DEVICE_TYPE(NES_BMC_970630C, nes_bmc_970630c_device, "nes_bmc_970630c", "NES Cart BMC 970630C PCB")
DEFINE_DEVICE_TYPE(NES_NTD03, nes_ntd03_device, "nes_ntd03", "NES Cart NTD-03 PCB")
-DEFINE_DEVICE_TYPE(NES_BMC_GB63, nes_bmc_gb63_device, "nes_bmc_gb63", "NES Cart BMC Ghostbusters 63 in 1 PCB")
+DEFINE_DEVICE_TYPE(NES_BMC_CTC09, nes_bmc_ctc09_device, "nes_bmc_ctc09", "NES Cart BMC CTC-09 PCB")
+DEFINE_DEVICE_TYPE(NES_BMC_CTC12IN1, nes_bmc_ctc12in1_device, "nes_bmc_ctc12in1", "NES Cart BMC CTC-12IN1 PCB")
+DEFINE_DEVICE_TYPE(NES_BMC_DS927, nes_bmc_ds927_device, "nes_bmc_ds927", "NES Cart BMC DS-9-27 PCB")
+DEFINE_DEVICE_TYPE(NES_BMC_FAM250, nes_bmc_fam250_device, "nes_bmc_fam250", "NES Cart BMC FAM250 PCB")
DEFINE_DEVICE_TYPE(NES_BMC_GKA, nes_bmc_gka_device, "nes_bmc_gka", "NES Cart BMC GK-A PCB")
DEFINE_DEVICE_TYPE(NES_BMC_GKB, nes_bmc_gkb_device, "nes_bmc_gkb", "NES Cart BMC GK-B PCB")
+DEFINE_DEVICE_TYPE(NES_BMC_GKCXIN1, nes_bmc_gkcxin1_device, "nes_bmc_gkcxin1", "NES Cart BMC GKCXIN1 PCB")
+DEFINE_DEVICE_TYPE(NES_BMC_GN91B, nes_bmc_gn91b_device, "nes_bmc_gn91b", "NES Cart BMC GN-91B PCB")
+DEFINE_DEVICE_TYPE(NES_BMC_HP898F, nes_bmc_hp898f_device, "nes_bmc_hp898f", "NES Cart BMC HP-898F PCB")
+DEFINE_DEVICE_TYPE(NES_BMC_K1029, nes_bmc_k1029_device, "nes_bmc_k1029", "NES Cart BMC K-1029 PCB")
+DEFINE_DEVICE_TYPE(NES_BMC_K3036, nes_bmc_k3036_device, "nes_bmc_k3036", "NES Cart BMC K-3036 PCB")
+DEFINE_DEVICE_TYPE(NES_BMC_K3046, nes_bmc_k3046_device, "nes_bmc_k3046", "NES Cart BMC K-3046 PCB")
+DEFINE_DEVICE_TYPE(NES_BMC_K3071, nes_bmc_k3071_device, "nes_bmc_k3071", "NES Cart BMC K-3071 PCB")
+DEFINE_DEVICE_TYPE(NES_BMC_S009, nes_bmc_s009_device, "nes_bmc_s009", "NES Cart BMC S-009 PCB")
+DEFINE_DEVICE_TYPE(NES_BMC_SA005A, nes_bmc_sa005a_device, "nes_bmc_sa005a", "NES Cart BMC SA005-A PCB")
+DEFINE_DEVICE_TYPE(NES_BMC_TF2740, nes_bmc_tf2740_device, "nes_bmc_tf2740", "NES Cart BMC TF2740 PCB")
+DEFINE_DEVICE_TYPE(NES_BMC_TH2348, nes_bmc_th2348_device, "nes_bmc_th2348", "NES Cart BMC TH2348 PCB")
+DEFINE_DEVICE_TYPE(NES_BMC_TJ03, nes_bmc_tj03_device, "nes_bmc_tj03", "NES Cart BMC TJ-03 PCB")
DEFINE_DEVICE_TYPE(NES_BMC_WS, nes_bmc_ws_device, "nes_bmc_ws", "NES Cart BMC WS PCB")
DEFINE_DEVICE_TYPE(NES_BMC_11160, nes_bmc_11160_device, "nes_bmc_1160", "NES Cart BMC-1160 PCB")
DEFINE_DEVICE_TYPE(NES_BMC_G146, nes_bmc_g146_device, "nes_bmc_g146", "NES Cart BMC-G-146 PCB")
+DEFINE_DEVICE_TYPE(NES_BMC_2751, nes_bmc_2751_device, "nes_bmc_2751", "NES Cart BMC-2751 PCB")
DEFINE_DEVICE_TYPE(NES_BMC_8157, nes_bmc_8157_device, "nes_bmc_8157", "NES Cart BMC-8157 PCB")
DEFINE_DEVICE_TYPE(NES_BMC_HIK300, nes_bmc_hik300_device, "nes_bmc_hik300", "NES Cart BMC HIK 300 in 1 PCB")
DEFINE_DEVICE_TYPE(NES_BMC_S700, nes_bmc_s700_device, "nes_bmc_s700", "NES Cart BMC Super 700 in 1 PCB")
DEFINE_DEVICE_TYPE(NES_BMC_BALL11, nes_bmc_ball11_device, "nes_bmc_ball11", "NES Cart BMC Ball 11 in 1 PCB")
DEFINE_DEVICE_TYPE(NES_BMC_22GAMES, nes_bmc_22games_device, "nes_bmc_22games", "NES Cart BMC 22 Games PCB")
-DEFINE_DEVICE_TYPE(NES_BMC_64Y2K, nes_bmc_64y2k_device, "nes_bmc_64y2k", "NES Cart BMC 64 in 1 Y2K PCB")
+DEFINE_DEVICE_TYPE(NES_BMC_64Y2K, nes_bmc_64y2k_device, "nes_bmc_64y2k", "NES Cart BMC Y2K 64 in 1 PCB")
+DEFINE_DEVICE_TYPE(NES_BMC_420Y2K, nes_bmc_420y2k_device, "nes_bmc_420y2k", "NES Cart BMC Y2K 420 in 1 PCB")
DEFINE_DEVICE_TYPE(NES_BMC_12IN1, nes_bmc_12in1_device, "nes_bmc_12in1", "NES Cart BMC 12 in 1 PCB")
DEFINE_DEVICE_TYPE(NES_BMC_20IN1, nes_bmc_20in1_device, "nes_bmc_20in1", "NES Cart BMC 20 in 1 PCB")
DEFINE_DEVICE_TYPE(NES_BMC_21IN1, nes_bmc_21in1_device, "nes_bmc_21in1", "NES Cart BMC 21 in 1 PCB")
@@ -64,26 +94,55 @@ DEFINE_DEVICE_TYPE(NES_BMC_64IN1, nes_bmc_64in1_device, "nes_bmc_64in1
DEFINE_DEVICE_TYPE(NES_BMC_70IN1, nes_bmc_70in1_device, "nes_bmc_70in1", "NES Cart BMC 70 in 1 PCB")
DEFINE_DEVICE_TYPE(NES_BMC_72IN1, nes_bmc_72in1_device, "nes_bmc_72in1", "NES Cart BMC 72 in 1 PCB")
DEFINE_DEVICE_TYPE(NES_BMC_76IN1, nes_bmc_76in1_device, "nes_bmc_76in1", "NES Cart BMC 76 in 1 PCB")
-DEFINE_DEVICE_TYPE(NES_BMC_110IN1, nes_bmc_110in1_device, "nes_bmc_110in1", "NES Cart BMC 110 in 1 PCB")
DEFINE_DEVICE_TYPE(NES_BMC_150IN1, nes_bmc_150in1_device, "nes_bmc_150in1", "NES Cart BMC 150 in 1 PCB")
DEFINE_DEVICE_TYPE(NES_BMC_190IN1, nes_bmc_190in1_device, "nes_bmc_190in1", "NES Cart BMC 190 in 1 PCB")
+DEFINE_DEVICE_TYPE(NES_BMC_500IN1, nes_bmc_500in1_device, "nes_bmc_500in1", "NES Cart BMC 500 in 1 PCB")
DEFINE_DEVICE_TYPE(NES_BMC_800IN1, nes_bmc_800in1_device, "nes_bmc_800in1", "NES Cart BMC 800 in 1 PCB")
DEFINE_DEVICE_TYPE(NES_BMC_1200IN1, nes_bmc_1200in1_device, "nes_bmc_1200in1", "NES Cart BMC 1200 in 1 PCB")
-DEFINE_DEVICE_TYPE(NES_BMC_GOLD150, nes_bmc_gold150_device, "nes_bmc_gold150", "NES Cart BMC Golden 150 in 1 PCB")
-DEFINE_DEVICE_TYPE(NES_BMC_GOLD260, nes_bmc_gold260_device, "nes_bmc_gold260", "NES Cart BMC Golden 260 in 1 PCB")
-DEFINE_DEVICE_TYPE(NES_BMC_CH001, nes_bmc_ch001_device, "nes_bmc_ch001", "NES Cart BMC CH-001 PCB")
-DEFINE_DEVICE_TYPE(NES_BMC_SUPER22, nes_bmc_super22_device, "nes_bmc_super22", "NES Cart BMC Super 22 Games PCB")
+DEFINE_DEVICE_TYPE(NES_BMC_GOLD260, nes_bmc_gold260_device, "nes_bmc_gold260", "NES Cart BMC Golden Game X in 1 PCB")
+DEFINE_DEVICE_TYPE(NES_BMC_TH22913, nes_bmc_th22913_device, "nes_bmc_th22913", "NES Cart BMC TH2291-3 PCB")
+DEFINE_DEVICE_TYPE(NES_BMC_82AB, nes_bmc_82ab_device, "nes_bmc_82ab", "NES Cart BMC 82AB PCB")
DEFINE_DEVICE_TYPE(NES_BMC_4IN1RESET, nes_bmc_4in1reset_device, "nes_bmc_4in1reset", "NES Cart BMC 4 in 1 (Reset Based) PCB")
DEFINE_DEVICE_TYPE(NES_BMC_42IN1RESET, nes_bmc_42in1reset_device, "nes_bmc_42in1reset", "NES Cart BMC 42 in 1 (Reset Based) PCB")
+DEFINE_DEVICE_TYPE(NES_BMC_NC20MB, nes_bmc_nc20mb_device, "nes_bmc_nc20mb", "NES Cart BMC NC-20MB PCB")
+DEFINE_DEVICE_TYPE(NES_BMC_LC160, nes_bmc_lc160_device, "nes_bmc_lc160", "NES Cart BMC Little Com 160 PCB")
+
+
+INPUT_PORTS_START( bmc_8157 )
+ PORT_START("JUMPER")
+ PORT_CONFNAME( 0x01, 0x01, "Menu Type" )
+ PORT_CONFSETTING( 0x00, "20-in-1" )
+ PORT_CONFSETTING( 0x01, "4-in-1" )
+INPUT_PORTS_END
+
+//-------------------------------------------------
+// input_ports - device-specific input ports
+//-------------------------------------------------
+
+ioport_constructor nes_bmc_8157_device::device_input_ports() const
+{
+ return INPUT_PORTS_NAME( bmc_8157 );
+}
-nes_action52_device::nes_action52_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
+
+
+//**************************************************************************
+// LIVE DEVICE
+//**************************************************************************
+
+nes_action52_device::nes_action52_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock)
: nes_nrom_device(mconfig, NES_ACTION52, tag, owner, clock)
{
}
-nes_caltron_device::nes_caltron_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
- : nes_nrom_device(mconfig, NES_CALTRON6IN1, tag, owner, clock), m_latch(0)
+nes_caltron6in1_device::nes_caltron6in1_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock)
+ : nes_nrom_device(mconfig, NES_CALTRON6IN1, tag, owner, clock), m_latch(0), m_reg(0)
+{
+}
+
+nes_caltron9in1_device::nes_caltron9in1_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock)
+ : nes_nrom_device(mconfig, NES_CALTRON9IN1, tag, owner, clock)
{
}
@@ -92,13 +151,18 @@ nes_rumblestat_device::nes_rumblestat_device(const machine_config &mconfig, cons
{
}
-nes_svision16_device::nes_svision16_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
+nes_svision16_device::nes_svision16_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock)
: nes_nrom_device(mconfig, NES_SVISION16, tag, owner, clock), m_latch1(0), m_latch2(0)
{
}
-nes_n625092_device::nes_n625092_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
- : nes_nrom_device(mconfig, NES_N625092, tag, owner, clock), m_latch1(0), m_latch2(0)
+nes_farid_unrom_device::nes_farid_unrom_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock)
+ : nes_nrom_device(mconfig, NES_FARID_UNROM, tag, owner, clock), m_reg(0)
+{
+}
+
+nes_kn42_device::nes_kn42_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock)
+ : nes_nrom_device(mconfig, NES_KN42, tag, owner, clock), m_latch(0)
{
}
@@ -107,122 +171,219 @@ nes_a65as_device::nes_a65as_device(const machine_config &mconfig, const char *ta
{
}
-nes_t262_device::nes_t262_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
- : nes_nrom_device(mconfig, NES_T262, tag, owner, clock), m_latch1(0), m_latch2(0)
+nes_t262_device::nes_t262_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock)
+ : nes_nrom_device(mconfig, NES_T262, tag, owner, clock), m_latch(0)
{
}
-nes_novel1_device::nes_novel1_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
- : nes_nrom_device(mconfig, NES_NOVEL1, tag, owner, clock)
+nes_studyngame_device::nes_studyngame_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
+ : nes_nrom_device(mconfig, NES_STUDYNGAME, tag, owner, clock)
{
}
-nes_novel2_device::nes_novel2_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
- : nes_nrom_device(mconfig, NES_NOVEL2, tag, owner, clock)
+nes_sgun20in1_device::nes_sgun20in1_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, u32 clock)
+ : nes_nrom_device(mconfig, type, tag, owner, clock)
{
}
-nes_studyngame_device::nes_studyngame_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
- : nes_nrom_device(mconfig, NES_STUDYNGAME, tag, owner, clock)
+nes_sgun20in1_device::nes_sgun20in1_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock)
+ : nes_sgun20in1_device(mconfig, NES_SUPERGUN20IN1, tag, owner, clock)
+{
+}
+
+nes_bmc_190in1_device::nes_bmc_190in1_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock)
+ : nes_sgun20in1_device(mconfig, NES_BMC_190IN1, tag, owner, clock)
+{
+}
+
+nes_vt5201_device::nes_vt5201_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock)
+ : nes_nrom_device(mconfig, NES_VT5201, tag, owner, clock), m_latch(0), m_jumper(0)
+{
+}
+
+nes_bmc_80013b_device::nes_bmc_80013b_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock)
+ : nes_nrom_device(mconfig, NES_BMC_80013B, tag, owner, clock), m_latch(0)
+{
+}
+
+nes_bmc_810544c_device::nes_bmc_810544c_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock)
+ : nes_nrom_device(mconfig, NES_BMC_810544C, tag, owner, clock)
{
}
-nes_sgun20in1_device::nes_sgun20in1_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
- : nes_nrom_device(mconfig, NES_SUPERGUN20IN1, tag, owner, clock)
+nes_bmc_830425c_device::nes_bmc_830425c_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock)
+ : nes_nrom_device(mconfig, NES_BMC_830425C, tag, owner, clock), m_latch(0)
{
}
-nes_vt5201_device::nes_vt5201_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
- : nes_nrom_device(mconfig, NES_VT5201, tag, owner, clock), m_latch(0), m_dipsetting(0)
+nes_bmc_830928c_device::nes_bmc_830928c_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock)
+ : nes_nrom_device(mconfig, NES_BMC_830928C, tag, owner, clock), m_latch(0)
{
}
-nes_810544c_device::nes_810544c_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
- : nes_nrom_device(mconfig, NES_810544C, tag, owner, clock)
+nes_bmc_850437c_device::nes_bmc_850437c_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock)
+ : nes_nrom_device(mconfig, NES_BMC_850437C, tag, owner, clock)
{
}
-nes_ntd03_device::nes_ntd03_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
+nes_bmc_970630c_device::nes_bmc_970630c_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock)
+ : nes_nrom_device(mconfig, NES_BMC_970630C, tag, owner, clock), m_latch(0)
+{
+}
+
+nes_ntd03_device::nes_ntd03_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock)
: nes_nrom_device(mconfig, NES_NTD03, tag, owner, clock)
{
}
-nes_bmc_gb63_device::nes_bmc_gb63_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
- : nes_nrom_device(mconfig, NES_BMC_GB63, tag, owner, clock), m_latch(0), m_dipsetting(0), m_vram_disable(0)
+nes_bmc_ctc09_device::nes_bmc_ctc09_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock)
+ : nes_nrom_device(mconfig, NES_BMC_CTC09, tag, owner, clock)
{
}
-nes_bmc_gka_device::nes_bmc_gka_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
- : nes_nrom_device(mconfig, NES_BMC_GKA, tag, owner, clock), m_latch1(0), m_latch2(0)
+nes_bmc_ds927_device::nes_bmc_ds927_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock)
+ : nes_nrom_device(mconfig, NES_BMC_DS927, tag, owner, clock), m_latch(0), m_mode(0)
{
}
-nes_bmc_gkb_device::nes_bmc_gkb_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
+nes_bmc_gka_device::nes_bmc_gka_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock)
+ : nes_nrom_device(mconfig, NES_BMC_GKA, tag, owner, clock)
+{
+}
+
+nes_bmc_gkb_device::nes_bmc_gkb_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock)
: nes_nrom_device(mconfig, NES_BMC_GKB, tag, owner, clock)
{
}
+nes_bmc_gkcxin1_device::nes_bmc_gkcxin1_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock)
+ : nes_nrom_device(mconfig, NES_BMC_GKCXIN1, tag, owner, clock)
+{
+}
+
+nes_bmc_gn91b_device::nes_bmc_gn91b_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock)
+ : nes_nrom_device(mconfig, NES_BMC_GN91B, tag, owner, clock), m_latch(0)
+{
+}
+
+nes_bmc_hp898f_device::nes_bmc_hp898f_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock)
+ : nes_nrom_device(mconfig, NES_BMC_HP898F, tag, owner, clock)
+{
+}
+
+nes_bmc_k3036_device::nes_bmc_k3036_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock)
+ : nes_nrom_device(mconfig, NES_BMC_K3036, tag, owner, clock)
+{
+}
+
+nes_bmc_k3046_device::nes_bmc_k3046_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock)
+ : nes_nrom_device(mconfig, NES_BMC_K3046, tag, owner, clock)
+{
+}
+
+nes_bmc_k3071_device::nes_bmc_k3071_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock)
+ : nes_nrom_device(mconfig, NES_BMC_K3071, tag, owner, clock)
+{
+}
+
+nes_bmc_s009_device::nes_bmc_s009_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock)
+ : nes_nrom_device(mconfig, NES_BMC_S009, tag, owner, clock), m_reg(0)
+{
+}
+
+nes_bmc_sa005a_device::nes_bmc_sa005a_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock)
+ : nes_nrom_device(mconfig, NES_BMC_SA005A, tag, owner, clock)
+{
+}
+
+nes_bmc_tf2740_device::nes_bmc_tf2740_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock)
+ : nes_nrom_device(mconfig, NES_BMC_TF2740, tag, owner, clock), m_jumper(0)
+{
+}
+
+nes_bmc_th2348_device::nes_bmc_th2348_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock)
+ : nes_nrom_device(mconfig, NES_BMC_TH2348, tag, owner, clock), m_latch(0)
+{
+}
+
+nes_bmc_tj03_device::nes_bmc_tj03_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock)
+ : nes_nrom_device(mconfig, NES_BMC_TJ03, tag, owner, clock)
+{
+}
+
nes_bmc_ws_device::nes_bmc_ws_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
: nes_nrom_device(mconfig, NES_BMC_WS, tag, owner, clock), m_latch(0)
{
}
-nes_bmc_11160_device::nes_bmc_11160_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
+nes_bmc_11160_device::nes_bmc_11160_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock)
: nes_nrom_device(mconfig, NES_BMC_11160, tag, owner, clock)
{
}
-nes_bmc_g146_device::nes_bmc_g146_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
+nes_bmc_g146_device::nes_bmc_g146_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock)
: nes_nrom_device(mconfig, NES_BMC_G146, tag, owner, clock)
{
}
-nes_bmc_8157_device::nes_bmc_8157_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
+nes_bmc_2751_device::nes_bmc_2751_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock)
+ : nes_nrom_device(mconfig, NES_BMC_2751, tag, owner, clock)
+{
+}
+
+nes_bmc_8157_device::nes_bmc_8157_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock)
: nes_nrom_device(mconfig, NES_BMC_8157, tag, owner, clock)
+ , m_jumper(*this, "JUMPER")
+ , m_latch(0)
{
}
-nes_bmc_hik300_device::nes_bmc_hik300_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
+nes_bmc_hik300_device::nes_bmc_hik300_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock)
: nes_nrom_device(mconfig, NES_BMC_HIK300, tag, owner, clock)
{
}
-nes_bmc_s700_device::nes_bmc_s700_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
+nes_bmc_s700_device::nes_bmc_s700_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock)
: nes_nrom_device(mconfig, NES_BMC_S700, tag, owner, clock)
{
}
-nes_bmc_ball11_device::nes_bmc_ball11_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
+nes_bmc_ball11_device::nes_bmc_ball11_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock)
: nes_nrom_device(mconfig, NES_BMC_BALL11, tag, owner, clock)
{
}
-nes_bmc_22games_device::nes_bmc_22games_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
- : nes_nrom_device(mconfig, NES_BMC_22GAMES, tag, owner, clock)
+nes_bmc_22games_device::nes_bmc_22games_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock)
+ : nes_nrom_device(mconfig, NES_BMC_22GAMES, tag, owner, clock), m_latch(0), m_reset(0)
+{
+}
+
+nes_bmc_64y2k_device::nes_bmc_64y2k_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock)
+ : nes_nrom_device(mconfig, NES_BMC_64Y2K, tag, owner, clock), m_reg_mask(0)
{
}
-nes_bmc_64y2k_device::nes_bmc_64y2k_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
- : nes_nrom_device(mconfig, NES_BMC_64Y2K, tag, owner, clock)
+nes_bmc_420y2k_device::nes_bmc_420y2k_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock)
+ : nes_nrom_device(mconfig, NES_BMC_420Y2K, tag, owner, clock), m_latch(0), m_reg(0)
{
}
-nes_bmc_12in1_device::nes_bmc_12in1_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
+nes_bmc_12in1_device::nes_bmc_12in1_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock)
: nes_nrom_device(mconfig, NES_BMC_12IN1, tag, owner, clock)
{
}
-nes_bmc_20in1_device::nes_bmc_20in1_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
+nes_bmc_20in1_device::nes_bmc_20in1_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock)
: nes_nrom_device(mconfig, NES_BMC_20IN1, tag, owner, clock)
{
}
-nes_bmc_21in1_device::nes_bmc_21in1_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
+nes_bmc_21in1_device::nes_bmc_21in1_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock)
: nes_nrom_device(mconfig, NES_BMC_21IN1, tag, owner, clock)
{
}
-nes_bmc_31in1_device::nes_bmc_31in1_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
+nes_bmc_31in1_device::nes_bmc_31in1_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock)
: nes_nrom_device(mconfig, NES_BMC_31IN1, tag, owner, clock)
{
}
@@ -242,38 +403,38 @@ nes_bmc_64in1_device::nes_bmc_64in1_device(const machine_config &mconfig, const
{
}
-nes_bmc_70in1_device::nes_bmc_70in1_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
- : nes_nrom_device(mconfig, NES_BMC_70IN1, tag, owner, clock), m_mode(0)
+nes_bmc_70in1_device::nes_bmc_70in1_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, u32 clock)
+ : nes_nrom_device(mconfig, type, tag, owner, clock), m_jumper(type == NES_BMC_70IN1 ? 0x0d : 0x06)
{
}
-nes_bmc_72in1_device::nes_bmc_72in1_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
- : nes_nrom_device(mconfig, NES_BMC_72IN1, tag, owner, clock)
+nes_bmc_70in1_device::nes_bmc_70in1_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock)
+ : nes_bmc_70in1_device(mconfig, NES_BMC_70IN1, tag, owner, clock)
{
}
-nes_bmc_76in1_device::nes_bmc_76in1_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
- : nes_nrom_device(mconfig, NES_BMC_76IN1, tag, owner, clock), m_latch1(0), m_latch2(0)
+nes_bmc_800in1_device::nes_bmc_800in1_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock)
+ : nes_bmc_70in1_device(mconfig, NES_BMC_800IN1, tag, owner, clock)
{
}
-nes_bmc_110in1_device::nes_bmc_110in1_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
- : nes_nrom_device(mconfig, NES_BMC_110IN1, tag, owner, clock)
+nes_bmc_72in1_device::nes_bmc_72in1_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock)
+ : nes_nrom_device(mconfig, NES_BMC_72IN1, tag, owner, clock)
{
}
-nes_bmc_150in1_device::nes_bmc_150in1_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
- : nes_nrom_device(mconfig, NES_BMC_150IN1, tag, owner, clock)
+nes_bmc_76in1_device::nes_bmc_76in1_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock)
+ : nes_nrom_device(mconfig, NES_BMC_76IN1, tag, owner, clock)
{
}
-nes_bmc_190in1_device::nes_bmc_190in1_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
- : nes_nrom_device(mconfig, NES_BMC_190IN1, tag, owner, clock)
+nes_bmc_150in1_device::nes_bmc_150in1_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock)
+ : nes_nrom_device(mconfig, NES_BMC_150IN1, tag, owner, clock)
{
}
-nes_bmc_800in1_device::nes_bmc_800in1_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
- : nes_nrom_device(mconfig, NES_BMC_800IN1, tag, owner, clock), m_mode(0)
+nes_bmc_500in1_device::nes_bmc_500in1_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock)
+ : nes_nrom_device(mconfig, NES_BMC_500IN1, tag, owner, clock)
{
}
@@ -282,64 +443,127 @@ nes_bmc_1200in1_device::nes_bmc_1200in1_device(const machine_config &mconfig, co
{
}
-nes_bmc_gold150_device::nes_bmc_gold150_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
- : nes_nrom_device(mconfig, NES_BMC_GOLD150, tag, owner, clock), m_latch(0)
+nes_bmc_gold260_device::nes_bmc_gold260_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock)
+ : nes_nrom_device(mconfig, NES_BMC_GOLD260, tag, owner, clock)
{
}
-nes_bmc_gold260_device::nes_bmc_gold260_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
- : nes_nrom_device(mconfig, NES_BMC_GOLD260, tag, owner, clock)
+nes_bmc_4in1reset_device::nes_bmc_4in1reset_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock)
+ : nes_nrom_device(mconfig, NES_BMC_4IN1RESET, tag, owner, clock), m_latch(0)
{
}
-nes_bmc_ch001_device::nes_bmc_ch001_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
- : nes_nrom_device(mconfig, NES_BMC_CH001, tag, owner, clock), m_latch(0)
+nes_bmc_42in1reset_device::nes_bmc_42in1reset_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, u32 clock, u8 mirror_flip)
+ : nes_nrom_device(mconfig, type, tag, owner, clock), m_latch(0), m_mirror_flip(mirror_flip)
{
}
-nes_bmc_super22_device::nes_bmc_super22_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
- : nes_nrom_device(mconfig, NES_BMC_SUPER22, tag, owner, clock)
+nes_bmc_42in1reset_device::nes_bmc_42in1reset_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock)
+ : nes_bmc_42in1reset_device(mconfig, NES_BMC_42IN1RESET, tag, owner, clock, 0)
{
}
-nes_bmc_4in1reset_device::nes_bmc_4in1reset_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
- : nes_nrom_device(mconfig, NES_BMC_4IN1RESET, tag, owner, clock), m_latch(0)
+nes_bmc_nc20mb_device::nes_bmc_nc20mb_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock)
+ : nes_bmc_42in1reset_device(mconfig, NES_BMC_NC20MB, tag, owner, clock, 1)
+{
+}
+
+nes_bmc_lc160_device::nes_bmc_lc160_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock)
+ : nes_nrom_device(mconfig, NES_BMC_LC160, tag, owner, clock)
+{
+}
+
+nes_vram_protect_device::nes_vram_protect_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, u32 clock)
+ : nes_nrom_device(mconfig, type, tag, owner, clock), m_vram_protect(false)
+{
+}
+
+nes_bmc_60311c_device::nes_bmc_60311c_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock)
+ : nes_vram_protect_device(mconfig, NES_BMC_60311C, tag, owner, clock)
+{
+}
+
+nes_bmc_ctc12in1_device::nes_bmc_ctc12in1_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, u32 clock)
+ : nes_vram_protect_device(mconfig, type, tag, owner, clock)
+{
+}
+
+nes_bmc_ctc12in1_device::nes_bmc_ctc12in1_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock)
+ : nes_bmc_ctc12in1_device(mconfig, NES_BMC_CTC12IN1, tag, owner, clock)
+{
+}
+
+nes_bmc_891227_device::nes_bmc_891227_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock)
+ : nes_bmc_ctc12in1_device(mconfig, NES_BMC_891227, tag, owner, clock)
+{
+}
+
+nes_bmc_k1029_device::nes_bmc_k1029_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, u32 clock)
+ : nes_vram_protect_device(mconfig, type, tag, owner, clock)
+{
+}
+
+nes_bmc_k1029_device::nes_bmc_k1029_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock)
+ : nes_bmc_k1029_device(mconfig, NES_BMC_K1029, tag, owner, clock)
+{
+}
+
+nes_bmc_fam250_device::nes_bmc_fam250_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock)
+ : nes_bmc_k1029_device(mconfig, NES_BMC_FAM250, tag, owner, clock), m_latch(0), m_reg(0)
+{
+}
+
+nes_n625092_device::nes_n625092_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock)
+ : nes_vram_protect_device(mconfig, NES_N625092, tag, owner, clock)
+{
+}
+
+nes_bmc_th22913_device::nes_bmc_th22913_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, u32 clock, u8 vram_prot_bit)
+ : nes_vram_protect_device(mconfig, type, tag, owner, clock), m_vram_prot_bit(vram_prot_bit)
{
}
-nes_bmc_42in1reset_device::nes_bmc_42in1reset_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
- : nes_nrom_device(mconfig, NES_BMC_42IN1RESET, tag, owner, clock), m_latch(0)
+nes_bmc_th22913_device::nes_bmc_th22913_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock)
+ : nes_bmc_th22913_device(mconfig, NES_BMC_TH22913, tag, owner, clock, 10)
{
}
+nes_bmc_82ab_device::nes_bmc_82ab_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock)
+ : nes_bmc_th22913_device(mconfig, NES_BMC_82AB, tag, owner, clock, 9)
+{
+}
-void nes_action52_device::device_start()
+
+void nes_caltron6in1_device::device_start()
{
common_start();
+ save_item(NAME(m_latch));
+ save_item(NAME(m_reg));
}
-void nes_action52_device::pcb_reset()
+void nes_caltron6in1_device::pcb_reset()
{
- m_chr_source = m_vrom_chunks ? CHRROM : CHRRAM;
prg32(0);
- chr8(0, m_chr_source);
+ chr8(0, CHRROM);
+
+ m_latch = 0;
+ m_reg = 0;
}
-void nes_caltron_device::device_start()
+void nes_caltron9in1_device::device_start()
{
common_start();
save_item(NAME(m_latch));
}
-void nes_caltron_device::pcb_reset()
+void nes_caltron9in1_device::pcb_reset()
{
- m_chr_source = m_vrom_chunks ? CHRROM : CHRRAM;
prg32(0);
- chr8(0, m_chr_source);
+ chr8(0, CHRROM);
- m_latch = 0;
+ m_latch[0] = m_latch[1] = m_latch[2] = 0;
}
void nes_rumblestat_device::device_start()
@@ -351,7 +575,6 @@ void nes_rumblestat_device::device_start()
void nes_rumblestat_device::pcb_reset()
{
- m_chr_source = m_vrom_chunks ? CHRROM : CHRRAM;
prg32(0);
chr8(0, m_chr_source);
@@ -368,423 +591,428 @@ void nes_svision16_device::device_start()
void nes_svision16_device::pcb_reset()
{
- m_chr_source = m_vrom_chunks ? CHRROM : CHRRAM;
prg32(0);
- chr8(0, m_chr_source);
m_latch1 = 0;
m_latch2 = 0;
}
-void nes_n625092_device::device_start()
+void nes_farid_unrom_device::device_start()
{
common_start();
- save_item(NAME(m_latch1));
- save_item(NAME(m_latch2));
+ save_item(NAME(m_reg));
}
-void nes_n625092_device::pcb_reset()
+void nes_farid_unrom_device::pcb_reset()
{
- m_chr_source = m_vrom_chunks ? CHRROM : CHRRAM;
prg16_89ab(0);
- prg16_cdef(0);
- chr8(0, m_chr_source);
+ prg16_cdef(7);
- m_latch1 = 0;
- m_latch2 = 0;
+ m_reg &= 0x87; // only middle four bits cleared on soft reset
}
-void nes_a65as_device::device_start()
+void nes_kn42_device::device_start()
{
common_start();
+ save_item(NAME(m_latch));
+}
+
+void nes_kn42_device::pcb_reset()
+{
+ m_latch ^= 0x10;
+ prg16_89ab(m_latch);
+ prg16_cdef(m_latch | 0x0f); // fixed to last bank for either game
}
void nes_a65as_device::pcb_reset()
{
- m_chr_source = m_vrom_chunks ? CHRROM : CHRRAM;
prg16_89ab(0);
prg16_cdef(7);
- set_nt_mirroring(PPU_MIRROR_VERT);
- chr8(0, m_chr_source);
}
void nes_t262_device::device_start()
{
common_start();
- save_item(NAME(m_latch1));
- save_item(NAME(m_latch2));
+ save_item(NAME(m_latch));
}
void nes_t262_device::pcb_reset()
{
- m_chr_source = m_vrom_chunks ? CHRROM : CHRRAM;
prg16_89ab(0);
prg16_cdef(7);
- chr8(0, m_chr_source);
-
- m_latch1 = 0;
- m_latch2 = 0;
-}
-void nes_novel1_device::device_start()
-{
- common_start();
+ m_latch = 0;
}
-void nes_novel1_device::pcb_reset()
+void nes_sgun20in1_device::pcb_reset()
{
- m_chr_source = m_vrom_chunks ? CHRROM : CHRRAM;
- prg32(0);
- chr8(0, m_chr_source);
- set_nt_mirroring(PPU_MIRROR_VERT);
+ prg16_89ab(0);
+ prg16_cdef(0);
+ chr8(0, CHRROM);
}
-void nes_novel2_device::device_start()
+void nes_vt5201_device::device_start()
{
common_start();
+ save_item(NAME(m_latch));
+ save_item(NAME(m_jumper));
}
-void nes_novel2_device::pcb_reset()
+void nes_vt5201_device::pcb_reset()
{
- m_chr_source = m_vrom_chunks ? CHRROM : CHRRAM;
prg32(0);
- chr8(0, m_chr_source);
-}
+ chr8(0, CHRROM);
-void nes_studyngame_device::device_start()
-{
- common_start();
+ m_latch = 0;
+ m_jumper = 0;
}
-void nes_studyngame_device::pcb_reset()
+void nes_bmc_80013b_device::device_start()
{
- m_chr_source = m_vrom_chunks ? CHRROM : CHRRAM;
- prg32(0);
- chr8(0, m_chr_source);
+ common_start();
+ save_item(NAME(m_latch));
+ save_item(NAME(m_reg));
}
-void nes_sgun20in1_device::device_start()
+void nes_bmc_80013b_device::pcb_reset()
{
- common_start();
+ m_latch = 0x80;
+ m_reg[0] = m_reg[1] = 0;
+ update_prg();
}
-void nes_sgun20in1_device::pcb_reset()
+void nes_bmc_810544c_device::pcb_reset()
{
- m_chr_source = m_vrom_chunks ? CHRROM : CHRRAM;
prg16_89ab(0);
prg16_cdef(0);
- chr8(0, m_chr_source);
+ chr8(0, CHRROM);
}
-void nes_vt5201_device::device_start()
+void nes_bmc_830425c_device::device_start()
{
common_start();
save_item(NAME(m_latch));
- save_item(NAME(m_dipsetting));
}
-void nes_vt5201_device::pcb_reset()
+void nes_bmc_830425c_device::pcb_reset()
{
- m_chr_source = m_vrom_chunks ? CHRROM : CHRRAM;
- prg32(0);
- chr8(0, m_chr_source);
+ prg16_89ab(0);
+ prg16_cdef(0x0f);
m_latch = 0;
- m_dipsetting = 0;
}
-void nes_810544c_device::device_start()
+void nes_bmc_830928c_device::device_start()
{
common_start();
+ save_item(NAME(m_latch));
}
-void nes_810544c_device::pcb_reset()
+void nes_bmc_830928c_device::pcb_reset()
{
- m_chr_source = m_vrom_chunks ? CHRROM : CHRRAM;
prg16_89ab(0);
- prg16_cdef(0);
- chr8(0, m_chr_source);
- set_nt_mirroring(PPU_MIRROR_VERT);
+ prg16_cdef(7);
+
+ m_latch = 0;
}
-void nes_ntd03_device::device_start()
+void nes_bmc_850437c_device::device_start()
{
common_start();
+ save_item(NAME(m_reg));
}
-void nes_ntd03_device::pcb_reset()
+void nes_bmc_850437c_device::pcb_reset()
{
- m_chr_source = m_vrom_chunks ? CHRROM : CHRRAM;
- prg32(0);
- chr8(0, m_chr_source);
+ prg16_89ab(0);
+ prg16_cdef(7);
+
+ m_reg[0] = m_reg[1] = 0;
}
-void nes_bmc_gb63_device::device_start()
+void nes_bmc_970630c_device::device_start()
{
common_start();
save_item(NAME(m_latch));
- save_item(NAME(m_dipsetting));
- save_item(NAME(m_reg));
- save_item(NAME(m_vram_disable));
}
-void nes_bmc_gb63_device::pcb_reset()
+void nes_bmc_970630c_device::pcb_reset()
{
prg16_89ab(0);
- prg16_cdef(0xfff);
- chr8(0, CHRRAM);
+ prg16_cdef(7);
m_latch = 0;
- m_dipsetting = 0;
- m_reg[0] = 0;
- m_reg[1] = 0;
- update_banks();
- m_vram_disable = 0;
}
-void nes_bmc_gka_device::device_start()
+void nes_bmc_ctc09_device::pcb_reset()
+{
+// nes_slot's pcb_start sets us up in the main menu. Soft reset is empty so
+// that games reset to their own title screens. This seems to be this cart's
+// intended behavior as trying to reset to the menu here crashes (due to RAM
+// contents?). Soft reset can similarly crash the main menu (BTANB?).
+}
+
+void nes_bmc_ds927_device::device_start()
{
common_start();
- save_item(NAME(m_latch1));
- save_item(NAME(m_latch2));
+ save_item(NAME(m_latch));
+ save_item(NAME(m_mode));
}
-void nes_bmc_gka_device::pcb_reset()
+void nes_bmc_ds927_device::pcb_reset()
{
- m_chr_source = m_vrom_chunks ? CHRROM : CHRRAM;
+ assert(m_prgram.size() >= 0x2000);
+
prg16_89ab(0);
prg16_cdef(0);
- chr8(0, m_chr_source);
- m_latch1 = 0;
- m_latch2 = 0;
+ m_latch = 0;
+ m_mode = 0;
}
-void nes_bmc_gkb_device::device_start()
+void nes_bmc_gka_device::device_start()
{
common_start();
+ save_item(NAME(m_reg));
}
-void nes_bmc_gkb_device::pcb_reset()
+void nes_bmc_gka_device::pcb_reset()
{
- m_chr_source = m_vrom_chunks ? CHRROM : CHRRAM;
- prg32(0);
- chr8(0, m_chr_source);
+ prg16_89ab(0);
+ prg16_cdef(0);
+ chr8(0, CHRROM);
+
+ m_reg[0] = m_reg[1] = 0;
}
-void nes_bmc_ws_device::device_start()
+void nes_bmc_gn91b_device::device_start()
{
common_start();
save_item(NAME(m_latch));
}
-void nes_bmc_ws_device::pcb_reset()
+void nes_bmc_gn91b_device::pcb_reset()
{
- m_chr_source = m_vrom_chunks ? CHRROM : CHRRAM;
- prg32(0);
- chr8(0, m_chr_source);
+ prg16_89ab(0);
+ prg16_cdef(7);
m_latch = 0;
}
-void nes_bmc_11160_device::device_start()
+void nes_bmc_k3036_device::pcb_reset()
{
- common_start();
+ prg16_89ab(0);
+ prg16_cdef(7);
}
-void nes_bmc_11160_device::pcb_reset()
+void nes_bmc_k3046_device::pcb_reset()
{
- m_chr_source = m_vrom_chunks ? CHRROM : CHRRAM;
- prg32(0);
- chr8(0, m_chr_source);
+ prg16_89ab(0);
+ prg16_cdef(7);
}
-void nes_bmc_g146_device::device_start()
+void nes_bmc_k3071_device::pcb_reset()
{
- common_start();
+ prg16_89ab(0);
+ prg16_cdef(0);
+ chr8(0, CHRROM);
}
-void nes_bmc_g146_device::pcb_reset()
+void nes_bmc_s009_device::device_start()
{
- m_chr_source = m_vrom_chunks ? CHRROM : CHRRAM;
- prg32(0);
- chr8(0, m_chr_source);
+ common_start();
+ save_item(NAME(m_reg));
}
-void nes_bmc_8157_device::device_start()
+void nes_bmc_s009_device::pcb_reset()
{
- common_start();
+ prg16_89ab(0);
+ prg16_cdef(7);
+
+ m_reg = 0;
}
-void nes_bmc_8157_device::pcb_reset()
+void nes_bmc_sa005a_device::pcb_reset()
{
- m_chr_source = m_vrom_chunks ? CHRROM : CHRRAM;
- prg32(0);
- chr8(0, m_chr_source);
+ prg16_89ab(0);
+ prg16_cdef(0);
+ chr8(0, CHRROM);
}
-void nes_bmc_hik300_device::device_start()
+void nes_bmc_tf2740_device::device_start()
{
common_start();
+ save_item(NAME(m_reg));
+ save_item(NAME(m_jumper));
}
-void nes_bmc_hik300_device::pcb_reset()
+void nes_bmc_tf2740_device::pcb_reset()
{
- m_chr_source = m_vrom_chunks ? CHRROM : CHRRAM;
- prg32(0xff);
- chr8(0xff, CHRROM);
+ prg16_89ab(0);
+ prg16_cdef(0);
+ chr8(0, CHRROM);
+
+ m_reg[0] = m_reg[1] = m_reg[2] = 0;
}
-void nes_bmc_s700_device::device_start()
+void nes_bmc_th2348_device::device_start()
{
common_start();
+ save_item(NAME(m_latch));
}
-void nes_bmc_s700_device::pcb_reset()
+void nes_bmc_th2348_device::pcb_reset()
{
- m_chr_source = m_vrom_chunks ? CHRROM : CHRRAM;
- prg32(0);
- chr8(0, m_chr_source);
+ prg16_89ab(0);
+ prg16_cdef(7);
+
+ m_latch = 0;
}
-void nes_bmc_ball11_device::device_start()
+void nes_bmc_ws_device::device_start()
{
common_start();
- save_item(NAME(m_reg));
+ save_item(NAME(m_latch));
}
-void nes_bmc_ball11_device::pcb_reset()
+void nes_bmc_ws_device::pcb_reset()
{
- m_chr_source = m_vrom_chunks ? CHRROM : CHRRAM;
prg32(0);
chr8(0, m_chr_source);
- m_reg[0] = 1;
- m_reg[1] = 0;
- set_banks();
+ m_latch = 0;
}
-void nes_bmc_22games_device::device_start()
+void nes_bmc_2751_device::pcb_start(running_machine &machine, u8 *ciram_ptr, bool cart_mounted)
{
- common_start();
+ device_nes_cart_interface::pcb_start(machine, ciram_ptr, cart_mounted);
+ prg16_89ab(0);
+ prg16_cdef(0);
+ chr8(0, CHRROM);
}
-void nes_bmc_22games_device::pcb_reset()
+void nes_bmc_2751_device::pcb_reset()
{
- m_chr_source = m_vrom_chunks ? CHRROM : CHRRAM;
- prg16_89ab(0);
- prg16_cdef(7);
- chr8(0, m_chr_source);
+ // this board does not reset to menu on soft reset
}
-void nes_bmc_64y2k_device::device_start()
+void nes_bmc_8157_device::device_start()
{
common_start();
- save_item(NAME(m_reg));
+ save_item(NAME(m_latch));
}
-void nes_bmc_64y2k_device::pcb_reset()
+void nes_bmc_8157_device::pcb_reset()
{
- m_chr_source = m_vrom_chunks ? CHRROM : CHRRAM;
- chr8(0, m_chr_source);
+ prg16_89ab(0);
+ prg16_cdef(0);
- m_reg[0] = 0x80;
- m_reg[1] = 0x43;
- m_reg[2] = m_reg[3] = 0;
- set_prg();
- set_nt_mirroring(PPU_MIRROR_VERT);
+ m_latch = 0;
}
-void nes_bmc_12in1_device::device_start()
+void nes_bmc_hik300_device::pcb_reset()
+{
+ prg16_89ab(0);
+ prg16_cdef(0);
+ chr8(0, CHRROM);
+}
+
+void nes_bmc_ball11_device::device_start()
{
common_start();
save_item(NAME(m_reg));
}
-void nes_bmc_12in1_device::pcb_reset()
+void nes_bmc_ball11_device::pcb_reset()
{
- m_chr_source = m_vrom_chunks ? CHRROM : CHRRAM;
prg32(0);
- chr8(0, m_chr_source);
- m_reg[0] = 0;
+
+ m_reg[0] = 2;
m_reg[1] = 0;
- m_reg[2] = 0;
- update_banks();
}
-void nes_bmc_20in1_device::device_start()
+void nes_bmc_22games_device::device_start()
{
common_start();
+ save_item(NAME(m_latch));
+ save_item(NAME(m_reset));
}
-void nes_bmc_20in1_device::pcb_reset()
+void nes_bmc_22games_device::pcb_reset()
{
- m_chr_source = m_vrom_chunks ? CHRROM : CHRRAM;
- prg16_89ab(0);
- prg16_cdef(m_prg_chunks - 1);
- chr8(0, m_chr_source);
- set_nt_mirroring(PPU_MIRROR_VERT);
+ if (m_reset)
+ {
+ prg32(4);
+ m_latch = 1;
+ }
+ else
+ {
+ prg16_89ab(0);
+ prg16_cdef(7);
+ set_nt_mirroring(PPU_MIRROR_VERT);
+ m_reset = 1;
+ }
}
-void nes_bmc_21in1_device::device_start()
+void nes_bmc_64y2k_device::device_start()
{
common_start();
+ save_item(NAME(m_reg));
}
-void nes_bmc_21in1_device::pcb_reset()
+void nes_bmc_64y2k_device::pcb_reset()
{
- m_chr_source = m_vrom_chunks ? CHRROM : CHRRAM;
- prg32(0);
- chr8(0, m_chr_source);
+ m_reg_mask = m_chr_source == CHRROM ? 0x03 : 0x01;
+ m_reg[0] = 0x80;
+ m_reg[1] = 0x43;
+ m_reg[2] = m_reg[3] = 0;
+ update_banks();
}
-void nes_bmc_31in1_device::device_start()
+void nes_bmc_420y2k_device::device_start()
{
common_start();
+ save_item(NAME(m_latch));
+ save_item(NAME(m_reg));
}
-void nes_bmc_31in1_device::pcb_reset()
+void nes_bmc_420y2k_device::pcb_reset()
{
- m_chr_source = m_vrom_chunks ? CHRROM : CHRRAM;
prg16_89ab(0);
- prg16_cdef(1);
- chr8(0, m_chr_source);
+ prg16_cdef(7);
+
+ m_latch = 0;
+ m_reg = 0;
}
-void nes_bmc_35in1_device::device_start()
+void nes_bmc_12in1_device::device_start()
{
common_start();
+ save_item(NAME(m_reg));
+}
+
+void nes_bmc_12in1_device::pcb_reset()
+{
+ std::fill(std::begin(m_reg), std::end(m_reg), 0x00);
+ update_banks();
}
void nes_bmc_35in1_device::pcb_reset()
{
- m_chr_source = m_vrom_chunks ? CHRROM : CHRRAM;
prg16_89ab(0);
prg16_cdef(0);
chr8(0, m_chr_source);
}
-void nes_bmc_36in1_device::device_start()
-{
- common_start();
-}
-
void nes_bmc_36in1_device::pcb_reset()
{
- m_chr_source = m_vrom_chunks ? CHRROM : CHRRAM;
prg16_89ab(m_prg_chunks - 1);
prg16_cdef(m_prg_chunks - 1);
chr8(0, m_chr_source);
}
-void nes_bmc_64in1_device::device_start()
-{
- common_start();
-}
-
void nes_bmc_64in1_device::pcb_reset()
{
- m_chr_source = m_vrom_chunks ? CHRROM : CHRRAM;
prg16_89ab(0);
prg16_cdef(0);
chr8(0, m_chr_source);
@@ -793,212 +1021,163 @@ void nes_bmc_64in1_device::pcb_reset()
void nes_bmc_70in1_device::device_start()
{
common_start();
- save_item(NAME(m_reg));
- save_item(NAME(m_mode));
+ save_item(NAME(m_latch));
}
void nes_bmc_70in1_device::pcb_reset()
{
- prg16_89ab(m_prg_chunks - 1);
- prg16_cdef(m_prg_chunks - 1);
- chr8(0, CHRROM);
- m_reg[0] = 0;
- m_reg[1] = 0;
- m_mode = 0;
+ chr8(0, m_chr_source);
+
+ m_latch[0] = m_latch[1] = 0;
+ update_banks();
}
void nes_bmc_72in1_device::device_start()
{
common_start();
-}
-
-void nes_bmc_72in1_device::pcb_reset()
-{
- m_chr_source = m_vrom_chunks ? CHRROM : CHRRAM;
- prg32(0);
- chr8(0, m_chr_source);
+ save_item(NAME(m_extra_ram));
}
void nes_bmc_76in1_device::device_start()
{
common_start();
- save_item(NAME(m_latch1));
- save_item(NAME(m_latch2));
+ save_item(NAME(m_reg));
}
void nes_bmc_76in1_device::pcb_reset()
{
- m_chr_source = m_vrom_chunks ? CHRROM : CHRRAM;
prg32(0);
- chr8(0, m_chr_source);
-
- m_latch1 = 0;
- m_latch2 = 0;
-}
-void nes_bmc_110in1_device::device_start()
-{
- common_start();
+ m_reg[0] = m_reg[1] = 0;
}
-void nes_bmc_110in1_device::pcb_reset()
+void nes_bmc_150in1_device::pcb_reset()
{
- m_chr_source = m_vrom_chunks ? CHRROM : CHRRAM;
prg16_89ab(0);
- prg16_cdef(1);
- chr8(0, m_chr_source);
- set_nt_mirroring(PPU_MIRROR_VERT);
+ prg16_cdef(0);
+ chr8(0, CHRROM);
}
-void nes_bmc_150in1_device::device_start()
+void nes_bmc_1200in1_device::device_start()
{
common_start();
+ save_item(NAME(m_vram_protect));
}
-void nes_bmc_150in1_device::pcb_reset()
+void nes_bmc_1200in1_device::pcb_reset()
{
- m_chr_source = m_vrom_chunks ? CHRROM : CHRRAM;
prg16_89ab(0);
prg16_cdef(0);
chr8(0, m_chr_source);
+ m_vram_protect = 0;
}
-void nes_bmc_190in1_device::device_start()
+// This PCB is fully emulated here :)
+void nes_bmc_4in1reset_device::device_start()
{
common_start();
+ m_latch = 3;
+ save_item(NAME(m_latch));
}
-void nes_bmc_190in1_device::pcb_reset()
+void nes_bmc_4in1reset_device::pcb_reset()
{
- m_chr_source = m_vrom_chunks ? CHRROM : CHRRAM;
- prg16_89ab(0);
- prg16_cdef(0);
- chr8(0, m_chr_source);
+ m_latch = (m_latch + 1) & 3;
+ prg16_89ab(m_latch);
+ prg16_cdef(m_latch);
+ chr8(m_latch, CHRROM);
}
-void nes_bmc_800in1_device::device_start()
+
+void nes_bmc_42in1reset_device::device_start()
{
common_start();
- save_item(NAME(m_reg));
- save_item(NAME(m_mode));
+ m_latch = 0x20;
+ save_item(NAME(m_latch));
}
-void nes_bmc_800in1_device::pcb_reset()
+void nes_bmc_42in1reset_device::pcb_reset()
{
- m_chr_source = m_vrom_chunks ? CHRROM : CHRRAM;
- prg16_89ab(m_prg_chunks - 1);
- prg16_cdef(m_prg_chunks - 1);
- chr8(0, m_chr_source);
- m_reg[0] = 0;
- m_reg[1] = 0;
- m_mode = 0;
+ m_latch ^= 0x20;
+ prg32(m_latch >> 1);
}
-void nes_bmc_1200in1_device::device_start()
+void nes_vram_protect_device::device_start()
{
common_start();
save_item(NAME(m_vram_protect));
}
-void nes_bmc_1200in1_device::pcb_reset()
+void nes_vram_protect_device::pcb_reset()
{
- m_chr_source = m_vrom_chunks ? CHRROM : CHRRAM;
- prg16_89ab(0);
- prg16_cdef(0);
- chr8(0, m_chr_source);
- m_vram_protect = 0;
+ prg32(0);
+ m_vram_protect = false;
}
-void nes_bmc_gold150_device::device_start()
+void nes_bmc_60311c_device::device_start()
{
- common_start();
- save_item(NAME(m_latch));
+ nes_vram_protect_device::device_start();
+ save_item(NAME(m_reg));
}
-void nes_bmc_gold150_device::pcb_reset()
+void nes_bmc_60311c_device::pcb_reset()
{
- m_chr_source = m_vrom_chunks ? CHRROM : CHRRAM;
- prg32(0);
- chr8(0, m_chr_source);
+ nes_vram_protect_device::pcb_reset();
- m_latch = 0;
+ m_reg[0] = m_reg[1] = m_reg[2] = 0;
+ update_banks();
}
-void nes_bmc_gold260_device::device_start()
+void nes_bmc_ctc12in1_device::device_start()
{
- common_start();
+ nes_vram_protect_device::device_start();
+ save_item(NAME(m_reg));
}
-void nes_bmc_gold260_device::pcb_reset()
+void nes_bmc_ctc12in1_device::pcb_reset()
{
- m_chr_source = m_vrom_chunks ? CHRROM : CHRRAM;
- prg32(0);
- chr8(0, m_chr_source);
+ nes_vram_protect_device::pcb_reset();
+ prg16_89ab(0);
+ prg16_cdef(0);
+
+ m_reg[0] = m_reg[1] = 0;
}
-void nes_bmc_ch001_device::device_start()
+void nes_bmc_fam250_device::device_start()
{
- common_start();
+ nes_bmc_k1029_device::device_start();
save_item(NAME(m_latch));
+ save_item(NAME(m_reg));
}
-void nes_bmc_ch001_device::pcb_reset()
+void nes_bmc_fam250_device::pcb_reset()
{
- m_chr_source = m_vrom_chunks ? CHRROM : CHRRAM;
- prg32(0);
- chr8(0, m_chr_source);
+ nes_bmc_k1029_device::pcb_reset();
m_latch = 0;
+ m_reg = 0;
}
-void nes_bmc_super22_device::device_start()
-{
- common_start();
-}
-
-void nes_bmc_super22_device::pcb_reset()
-{
- m_chr_source = m_vrom_chunks ? CHRROM : CHRRAM;
- prg32(0);
- chr8(0, m_chr_source);
-}
-
-
-// This PCB is fully emulated here :)
-void nes_bmc_4in1reset_device::device_start()
+void nes_n625092_device::device_start()
{
- common_start();
- m_latch = -1;
+ nes_vram_protect_device::device_start();
save_item(NAME(m_latch));
}
-void nes_bmc_4in1reset_device::pcb_reset()
+void nes_n625092_device::pcb_reset()
{
- m_latch++;
- m_latch &= 3;
- chr8(m_latch, CHRROM);
- prg16_89ab(m_latch);
- prg16_cdef(m_latch);
-}
-
+ nes_vram_protect_device::pcb_reset();
+ prg16_89ab(0);
+ prg16_cdef(0);
-void nes_bmc_42in1reset_device::device_start()
-{
- common_start();
- m_latch = -1;
- save_item(NAME(m_reg));
+ m_latch[0] = m_latch[1] = 0;
}
-void nes_bmc_42in1reset_device::pcb_reset()
+void nes_bmc_th22913_device::pcb_reset()
{
- m_chr_source = m_vrom_chunks ? CHRROM : CHRRAM;
- m_latch++;
- m_latch &= 1;
- chr8(0, m_chr_source);
- prg32(m_latch << 4);
-
- m_reg[0] = 0;
- m_reg[1] = 0;
+ nes_vram_protect_device::pcb_reset();
+ prg16_89ab(0);
+ prg16_cdef(0);
}
@@ -1016,24 +1195,17 @@ void nes_bmc_42in1reset_device::pcb_reset()
-------------------------------------------------*/
-void nes_action52_device::write_h(offs_t offset, uint8_t data)
+void nes_action52_device::write_h(offs_t offset, u8 data)
{
- uint8_t pmode = offset & 0x20;
- int pbank = (offset & 0x1fc0) >> 6;
- int cbank = (data & 0x03) | ((offset & 0x0f) << 2);
- LOG_MMC(("ae_act52_w, offset: %04x, data: %02x\n", offset, data));
-
- set_nt_mirroring(BIT(offset, 13) ? PPU_MIRROR_HORZ : PPU_MIRROR_VERT);
+ LOG("ae_act52_w, offset: %04x, data: %02x\n", offset, data);
- chr8(cbank, CHRROM);
+ u8 bank = BIT(offset, 6, 7);
+ u8 mode = !BIT(offset, 5);
+ prg16_89ab(bank & ~mode);
+ prg16_cdef(bank | mode);
- if (pmode)
- {
- prg16_89ab(pbank);
- prg16_cdef(pbank);
- }
- else
- prg32(pbank >> 1);
+ chr8((data & 0x03) | (offset & 0x0f) << 2, CHRROM);
+ set_nt_mirroring(BIT(offset, 13) ? PPU_MIRROR_HORZ : PPU_MIRROR_VERT);
}
/*-------------------------------------------------
@@ -1044,25 +1216,77 @@ void nes_action52_device::write_h(offs_t offset, uint8_t data)
iNES: mapper 41
- In MESS: Supported.
+ In MAME: Supported.
-------------------------------------------------*/
-void nes_caltron_device::write_m(offs_t offset, uint8_t data)
+void nes_caltron6in1_device::update_chr()
+{
+ chr8(((m_latch >> 1) & 0x0c) | m_reg, CHRROM);
+}
+
+void nes_caltron6in1_device::write_m(offs_t offset, u8 data)
+{
+ LOG("caltron6in1 write_m, offset: %04x, data: %02x\n", offset, data);
+
+ switch (offset & 0x1800)
+ {
+ case 0x0000:
+ m_latch = offset & 0x3f;
+ prg32(offset & 0x07);
+ update_chr();
+ set_nt_mirroring(BIT(offset, 5) ? PPU_MIRROR_HORZ : PPU_MIRROR_VERT);
+ break;
+ }
+}
+
+void nes_caltron6in1_device::write_h(offs_t offset, u8 data)
{
- LOG_MMC(("caltron write_m, 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);
- m_latch = offset & 0xff;
- set_nt_mirroring(BIT(data, 5) ? PPU_MIRROR_HORZ : PPU_MIRROR_VERT);
- prg32(offset & 0x07);
+ if (BIT(m_latch, 2))
+ {
+ m_reg = data & 0x03;
+ update_chr();
+ }
}
-void nes_caltron_device::write_h(offs_t offset, uint8_t data)
+/*-------------------------------------------------
+
+ Caltron 9 in 1 Board
+
+ Games: 9 in 1 by Caltron
+
+ NES 2.0: mapper 389
+
+ In MAME: Supported.
+
+ -------------------------------------------------*/
+
+void nes_caltron9in1_device::write_h(offs_t offset, u8 data)
{
- LOG_MMC(("caltron 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;
+
+ if (BIT(m_latch[1], 1))
+ {
+ u8 outer = (m_latch[0] >> 2) & ~0x03;
+ u8 inner = (m_latch[2] >> 2) & 0x03;
+ prg16_89ab(outer | inner);
+ prg16_cdef(outer | 0x03);
+ }
+ else
+ prg32(m_latch[0] >> 3);
+
+ if (nibble)
+ chr8(((m_latch[1] >> 1) & 0x1c) | (m_latch[2] & 0x03), CHRROM);
+ else
+ set_nt_mirroring(BIT(m_latch[0], 0) ? PPU_MIRROR_HORZ : PPU_MIRROR_VERT);
- if (m_latch & 0x04)
- chr8(((m_latch & 0x18) >> 1) | (data & 0x03), CHRROM);
}
/*-------------------------------------------------
@@ -1073,13 +1297,13 @@ void nes_caltron_device::write_h(offs_t offset, uint8_t 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);
@@ -1089,13 +1313,13 @@ 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);
- m_prg = (m_prg & ~0x01) | (data & 0x01);
- m_chr = (m_chr & ~0x07) | ((data & 0x70) >> 4);
+ m_prg = (m_prg & ~0x01) | BIT(data, 0);
+ m_chr = (m_chr & ~0x07) | BIT(data, 4, 3);
prg32(m_prg);
chr8(m_chr, CHRROM);
}
@@ -1106,102 +1330,111 @@ void nes_rumblestat_device::write_h(offs_t offset, uint8_t data)
Games: Supervision 16 in 1
+ This cart contains a 32KB boot menu that selects
+ games from a separate 2MB of ROM. The common iNES
+ file arbitrarily puts this first before the 2MB ROM.
+ A simpler alternate approach would be to place the
+ 32KB menu at the end of contiguous PRG. In that case
+ pcb_reset should be changed to point to the last
+ part of PRG and the +2s and +4 below can be removed.
+
iNES: mapper 53
- In MESS: Partially Supported. (the dump contains 32KB of
- EEPROM which is not currently handled well)
+ In MAME: Supported.
-------------------------------------------------*/
void nes_svision16_device::update_prg()
{
- int base = (m_latch1 & 0x0f) << 3;
- if (m_latch1 & 0x10)
- {
- prg16_89ab((base | (m_latch2 & 7)) + 2); // +2 due to the eeprom
- prg16_cdef((base | 0x07) + 2); // +2 due to the eeprom
- }
- else
+ if (BIT(m_latch1, 4))
{
- prg16_89ab(0);
- prg16_cdef(1);
+ u8 bank = (m_latch1 & 0x0f) << 3 | (m_latch2 & 0x07);
+ prg16_89ab(bank + 2); // +2 due to the 32KB menu
+ prg16_cdef((bank | 0x07) + 2); // +2 due to the 32KB menu
}
-
}
-uint8_t nes_svision16_device::read_m(offs_t offset)
+void nes_svision16_device::write_m(offs_t offset, u8 data)
{
- int bank = (((m_latch1 & 0x0f) << 4) | 0x0f) + 4 ; // +4 due to the eeprom
- LOG_MMC(("svision16 read_m, offset: %04x\n", offset));
- return m_prg[((bank * 0x2000) + (offset & 0x1fff)) & m_prg_mask];
+ LOG("svision16 write_m, offset: %04x, data: %02x\n", offset, data);
+
+ if (!BIT(m_latch1, 4))
+ {
+ m_latch1 = data;
+ update_prg();
+ set_nt_mirroring(BIT(m_latch1, 5) ? PPU_MIRROR_HORZ : PPU_MIRROR_VERT);
+ }
}
-void nes_svision16_device::write_m(offs_t offset, uint8_t data)
+void nes_svision16_device::write_h(offs_t offset, u8 data)
{
- LOG_MMC(("svision16 write_m, offset: %04x, data: %02x\n", offset, data));
-
- m_latch1 = data;
+ LOG("svision16 write_h, offset: %04x, data: %02x\n", offset, data);
+ m_latch2 = data;
update_prg();
- set_nt_mirroring(BIT(data, 5) ? PPU_MIRROR_HORZ : PPU_MIRROR_VERT);
}
-void nes_svision16_device::write_h(offs_t offset, uint8_t data)
+u8 nes_svision16_device::read_m(offs_t offset)
{
- LOG_MMC(("svision16 write_h, offset: %04x, data: %02x\n", offset, data));
- m_latch2 = data;
- update_prg();
+ 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
}
/*-------------------------------------------------
- Bootleg Board N625092
+ FARID_UNROM_8-IN-1
- Games: 400 in 1, 700 in 1, 1000 in 1
+ Games: 8 in 1
- iNES: mapper 221
+ NES 2.0: mapper 324
- In MESS: Supported.
+ In MAME: Supported.
-------------------------------------------------*/
-void nes_n625092_device::set_prg(uint8_t reg1, uint8_t reg2)
+void nes_farid_unrom_device::write_h(offs_t offset, u8 data)
{
- uint8_t helper1, helper2;
+ 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);
- helper1 = !(reg1 & 0x01) ? reg2 : (reg1 & 0x80) ? reg2 : (reg2 & 0x06) | 0x00;
- helper2 = !(reg1 & 0x01) ? reg2 : (reg1 & 0x80) ? 0x07 : (reg2 & 0x06) | 0x01;
+ if (BIT(data, 7) && !(m_reg & 0x88))
+ m_reg = data;
+ else
+ m_reg = (m_reg & 0x78) | (data & 0x87);
- prg16_89ab(helper1 | ((reg1 & 0x70) >> 1));
- prg16_cdef(helper2 | ((reg1 & 0x70) >> 1));
+ u8 bank = (m_reg & 0x70) >> 1 | (m_reg & 0x07);
+ prg16_89ab(bank);
+ prg16_cdef(bank | 0x07);
}
-void nes_n625092_device::write_h(offs_t offset, uint8_t data)
-{
- LOG_MMC(("n625092 write_h, offset: %04x, data: %02x\n", offset, data));
+/*-------------------------------------------------
- if (offset < 0x4000)
- {
- set_nt_mirroring(BIT(data, 0) ? PPU_MIRROR_HORZ : PPU_MIRROR_VERT);
- offset = (offset >> 1) & 0xff;
+ Bootleg Board KN-42
- if (m_latch1 != offset)
- {
- m_latch1 = offset;
- set_prg(m_latch1, m_latch2);
- }
- }
- else
- {
- offset &= 0x07;
+ Games: 2 in 1 - Big Nose & Big Nose Freaks Out
- if (m_latch2 != offset)
- {
- m_latch2 = offset;
- set_prg(m_latch1, m_latch2);
- }
- }
-}
+ NES 2.0: mapper 381
+
+ In MAME: Supported.
+
+ TODO: Big Nose Freaks Out has timing issues like
+ many Camerica games. It happens with the singleton
+ dump and is unrelated to the bootleg board here.
+
+ -------------------------------------------------*/
+
+void nes_kn42_device::write_h(offs_t offset, u8 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);
+ prg16_89ab(m_latch | (data & 0x07) << 1 | BIT(data, 4));
+}
/*-------------------------------------------------
@@ -1209,14 +1442,14 @@ void nes_n625092_device::write_h(offs_t offset, uint8_t 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);
@@ -1236,308 +1469,844 @@ void nes_a65as_device::write_h(offs_t offset, uint8_t data)
Board BMC-T-262
- Games: 4-in-1 (D-010), 8-in-1 (A-020)
+ Games: 4-in-1 (D-010), 8-in-1 (A-020), and others
+
+ NES 2.0: mapper 265
- In MESS: Supported
+ In MAME: Supported.
-------------------------------------------------*/
-void nes_t262_device::write_h(offs_t offset, uint8_t data)
+void nes_t262_device::write_h(offs_t offset, u8 data)
{
- uint8_t mmc_helper;
- LOG_MMC(("t262 write_h, offset: %04x, data: %02x\n", offset, data));
+ LOG("t262 write_h, offset: %04x, data: %02x\n", offset, data);
- if (m_latch2 || offset == 0)
+ if (!BIT(m_latch, 13))
{
- m_latch1 = (m_latch1 & 0x38) | (data & 0x07);
- prg16_89ab(m_latch1);
+ m_latch = offset;
+ set_nt_mirroring(BIT(m_latch, 1) ? PPU_MIRROR_HORZ : PPU_MIRROR_VERT);
}
- else
+
+ u8 bank = bitswap<4>(m_latch, 9, 8, 6, 5) << 3 | (data & 0x07); // NesDev shows the high bit here, but is it correct? So far no cart is large enough to use this.
+ u8 mode = BIT(m_latch, 0);
+ if (BIT(m_latch, 7)) // NROM mode
{
- m_latch2 = 1;
- set_nt_mirroring(BIT(data, 1) ? PPU_MIRROR_HORZ : PPU_MIRROR_VERT);
- mmc_helper = ((offset >> 3) & 0x20) | ((offset >> 2) & 0x18);
- m_latch1 = mmc_helper | (m_latch1 & 0x07);
- prg16_89ab(m_latch1);
- prg16_cdef(mmc_helper | 0x07);
+ prg16_89ab(bank & ~mode);
+ prg16_cdef(bank | mode);
+ }
+ else // UNROM mode
+ {
+ prg16_89ab(bank);
+ prg16_cdef(bank | 0x07);
}
}
+/*-------------------------------------------------
+
+ Board UNL-STUDYNGAME
+
+ Games: Study n Game 32 in 1
+
+ iNES: mapper 39
+
+ 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("studyngame write_h, offset: %04x, data: %02x\n", offset, data);
+ prg32(data);
+}
/*-------------------------------------------------
- BMC-NOVELDIAMOND and BMC-999999in1
+ Boards BMC-SUPERGUN-20IN1, BMC-190IN1
- Unknown Bootleg Multigame Board
- Games: I only found 'Novel Diamond 999999-in-1.unf' using
- this mapper (hence the code is used for BMC_NOVELDIAMOND
- board). The code is included here in case a mapper 54
- dump arises.
+ Unknown Bootleg Multigame Boards
+ Games: Super Gun 20 in 1, Golden 190 in 1
- iNES: mappers 54 and 213
+ iNES: mapper 214
+ NES 2.0: mapper 300
- In MESS: Partial Support.
+ In MAME: Supported.
-------------------------------------------------*/
-// Are this correct or should they work the same?
-void nes_novel1_device::write_h(offs_t offset, uint8_t data)
+void nes_sgun20in1_device::write_h(offs_t offset, u8 data)
{
- LOG_MMC(("novel1 write_h, offset: %04x, data: %02x\n", offset, data));
+ LOG("supergun20in1 write_h, offset: %04x, data: %02x\n", offset, data);
- prg32(offset & 0x03);
- chr8(offset & 0x07, CHRROM);
+// 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.
+ switch (offset & 0x7000)
+ {
+ case 0x0000:
+ case 0x7000:
+ offset >>= 2;
+ prg16_89ab(offset);
+ prg16_cdef(offset);
+ chr8(offset, CHRROM);
+ }
+}
+
+void nes_bmc_190in1_device::write_h(offs_t offset, u8 data)
+{
+ nes_sgun20in1_device::write_h(offset, data);
+ set_nt_mirroring(BIT(data, 0) ? PPU_MIRROR_HORZ : PPU_MIRROR_VERT);
}
-void nes_novel2_device::write_h(offs_t offset, uint8_t data)
+/*-------------------------------------------------
+
+ BMC-VT5201, BMC-T3H53, BMC-D1038
+
+ Games: Super 35 in 1, TN 95 in 1, 46 in 1, 65 in 1,
+ 74 in 1, 77 in 1
+
+ iNES: mapper 59
+
+ In MAME: Supported.
+
+ -------------------------------------------------*/
+
+void nes_vt5201_device::write_h(offs_t offset, u8 data)
{
- LOG_MMC(("novel2 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
+ {
+ m_latch = offset >> 8;
- prg32(offset >> 1);
- chr8(offset >> 3, CHRROM);
+ u8 bank = BIT(offset, 4, 3);
+ u8 mode = !BIT(offset, 7);
+ prg16_89ab(bank & ~mode);
+ prg16_cdef(bank | mode);
+
+ chr8(offset & 0x07, CHRROM);
+ set_nt_mirroring(BIT(offset, 3) ? PPU_MIRROR_HORZ : PPU_MIRROR_VERT);
+ }
}
+u8 nes_vt5201_device::read_h(offs_t 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
+ else
+ return hi_access_rom(offset);
+}
/*-------------------------------------------------
- Board UNL-STUDYNGAME
+ BMC-80013-B
- Games: Study n Game 32 in 1
+ Games: Cartridge Story I, II, and III
- iNES: mapper 39
+ NES 2.0: mapper 274
- In MESS: Partially Supported (problems with PRG bankswitch,
- only keyboard exercise work).
+ In MAME: Supported.
-------------------------------------------------*/
-void nes_studyngame_device::write_h(offs_t offset, uint8_t data)
+void nes_bmc_80013b_device::update_prg()
{
- LOG_MMC(("studyngame write_h, offset: %04x, data: %02x\n", offset, data));
- prg32(data);
+ prg16_89ab(m_latch | (m_reg[1] & 0x70) | m_reg[0]);
+ prg16_cdef(m_reg[1]);
+}
+
+void nes_bmc_80013b_device::write_h(offs_t offset, u8 data)
+{
+ LOG("bmc_80013b write_h, offset: %04x, data: %02x\n", offset, data);
+ if (offset & 0x6000)
+ {
+ m_reg[1] = data & 0x7f;
+ m_latch = !BIT(offset, 14) << 7;
+ }
+ else
+ {
+ m_reg[0] = data & 0x0f;
+ set_nt_mirroring(BIT(data, 4) ? PPU_MIRROR_HORZ : PPU_MIRROR_VERT);
+ }
+ update_prg();
}
/*-------------------------------------------------
- BMC-SUPERGUN-20IN1
+ BMC-810544-C-A1, NTDEC 2746
- Unknown Bootleg Multigame Board
- Games: Super Gun 20 in 1
+ Games: 200-in-1 Elfland, 14 in 1
- iNES: mapper 214
+ NES 2.0: mapper 261
- In MESS: Supported.
+ In MAME: Supported.
-------------------------------------------------*/
-void nes_sgun20in1_device::write_h(offs_t offset, uint8_t data)
+void nes_bmc_810544c_device::write_h(offs_t offset, u8 data)
{
- LOG_MMC(("supergun20in1 write_h, offset: %04x, data: %02x\n", offset, data));
+ LOG("bmc_810544c write_h, offset: %04x, data: %02x\n", offset, data);
- prg16_89ab(offset >> 2);
- prg16_cdef(offset >> 2);
- chr8(offset, CHRROM);
+ u8 bank = bitswap<4>(offset, 9, 8, 7, 5);
+ u8 mode = BIT(offset, 6);
+ prg16_89ab(bank & ~mode);
+ prg16_cdef(bank | mode);
+
+ chr8(offset & 0x0f, CHRROM);
+ set_nt_mirroring(BIT(offset, 4) ? PPU_MIRROR_HORZ : PPU_MIRROR_VERT);
}
/*-------------------------------------------------
- BMC-VT5201
+ BMC-830425C-4391T
+
+ Games: Super HiK 6-in-1 (A-030)
+
+ NES 2.0: mapper 320
+
+ In MAME: Supported.
-------------------------------------------------*/
-void nes_vt5201_device::write_h(offs_t offset, uint8_t data)
+void nes_bmc_830425c_device::write_h(offs_t offset, u8 data)
{
- LOG_MMC(("vt5201 wirte_h, offset: %04x, data: %02x\n", offset, data));
+ LOG("bmc_830425c write_h, offset: %04x, data: %02x\n", offset, data);
- m_latch = BIT(offset, 8);
+ if ((offset & 0x7fe0) == 0x70e0)
+ m_latch = offset & 0x1f;
- // not sure about this mirroring bit!!
- // without it TN 95 in 1 has glitches in Lunar Ball; with it TN 95 in 1 has glitches in Galaxian!
- set_nt_mirroring(BIT(data, 3) ? PPU_MIRROR_HORZ : PPU_MIRROR_VERT);
- if (BIT(offset, 7))
+ u8 outer = (m_latch & 0x0f) << 3;
+ u8 mode = !BIT(m_latch, 4) << 3 | 0x07;
+ prg16_89ab(outer | (data & mode));
+ prg16_cdef(outer | mode);
+}
+
+/*-------------------------------------------------
+
+ BMC-830928C
+
+ Games: 9 in 1
+
+ NES 2.0: mapper 382
+
+ In MAME: Supported.
+
+ -------------------------------------------------*/
+
+void nes_bmc_830928c_device::write_h(offs_t offset, u8 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);
+
+ if (!BIT(m_latch, 5))
{
- prg16_89ab((offset >> 4) & 0x07);
- prg16_cdef((offset >> 4) & 0x07);
+ m_latch = offset & 0x3f;
+ set_nt_mirroring(BIT(m_latch, 4) ? PPU_MIRROR_HORZ : PPU_MIRROR_VERT);
+ }
+
+ u8 outer = (m_latch & 0x07) << 3;
+ if (BIT(m_latch, 3)) // BNROM mode
+ prg32(outer >> 1 | (data & 0x03));
+ else // UNROM mode
+ {
+ prg16_89ab(outer | (data & 0x07));
+ prg16_cdef(outer | 7);
}
- else
- prg32((offset >> 5) & 0x03);
- chr8(offset, CHRROM);
}
-uint8_t nes_vt5201_device::read_h(offs_t offset)
+/*-------------------------------------------------
+
+ BMC-850437C
+
+ Games: Super 8-in-1 (JY-050 rev0, JY-085, JY-086)
+
+ NES 2.0: mapper 396
+
+ In MAME: Supported.
+
+ -------------------------------------------------*/
+
+void nes_bmc_850437c_device::write_h(offs_t offset, u8 data)
{
- LOG_MMC(("bmc_vt5201 read_h, offset: %04x\n", offset));
- // m_dipsetting = ioport("CARTDIPS")->read();
+ LOG("bmc_850437c write_h, offset: %04x, data: %02x\n", offset, data);
- if (m_latch)
- return m_dipsetting; // cart mode, depending on the Dip Switches (always zero atm, given we have no way to add cart-based DIPs)
- else
- return hi_access_rom(offset);
+ m_reg[(offset & 0x6000) == 0x2000] = data; // outer banking is always at 0xa000, mask is a guess
+
+ u8 bank = (m_reg[1] & 0x07) << 3 | (m_reg[0] & 0x07);
+ prg16_89ab(bank);
+ prg16_cdef(bank | 0x07);
+
+ set_nt_mirroring(BIT(m_reg[1], 6) ? PPU_MIRROR_HORZ : PPU_MIRROR_VERT);
}
/*-------------------------------------------------
- BMC-810544-C-A1
+ BMC-970630C
+
+ Games: 2 in 1 (NT-811), 4 in 1 1999
+
+ NES 2.0: mapper 380
- Games: 200-in-1 Elfland
+ In MAME: Supported.
+
+ TODO: Contra has the same graphics glitches as in
+ BMC-8157. These are marked as partially supported
+ in the softlist, but maybe this is just a BTANB?
-------------------------------------------------*/
-void nes_810544c_device::write_h(offs_t offset, uint8_t data)
+void nes_bmc_970630c_device::write_h(offs_t offset, u8 data)
{
- uint8_t bank = (offset >> 7);
- LOG_MMC(("810544 write_h, offset: %04x, data: %02x\n", offset, data));
+ LOG("bmc_970630c write_h, offset: %04x, data: %02x\n", offset, data);
- if (!BIT(offset, 6))
+ u8 bank = BIT(offset, 2, 5);
+ if (BIT(offset, 9)) // NROM mode
{
- prg16_89ab((bank << 1) | BIT(offset, 5));
- prg16_cdef((bank << 1) | BIT(offset, 5));
+ u8 mode = !BIT(offset, 0);
+ prg16_89ab(bank & ~mode);
+ prg16_cdef(bank | mode);
+ }
+ else // UNROM-esque mode
+ {
+ prg16_89ab(bank);
+ prg16_cdef(bank | 0x07);
}
- else
- prg32(bank);
- set_nt_mirroring(BIT(offset, 4) ? PPU_MIRROR_HORZ : PPU_MIRROR_VERT);
+ set_nt_mirroring(BIT(offset, 1) ? PPU_MIRROR_HORZ : PPU_MIRROR_VERT);
+ m_latch = BIT(offset, 8);
+}
- chr8(offset & 0x0f, CHRROM);
+u8 nes_bmc_970630c_device::read_h(offs_t 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...
+ else
+ return hi_access_rom(offset);
}
/*-------------------------------------------------
BMC-NTD-03
+ Games: ASDER 20 in 1
+
+ NES 2.0: mapper 290
+
+ In MAME: Supported.
+
+ -------------------------------------------------*/
+
+void nes_ntd03_device::write_h(offs_t offset, u8 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);
+ prg16_89ab(bank & ~mode);
+ prg16_cdef(bank | mode);
+
+ chr8(bitswap<5>(offset, 9, 8, 2, 1, 0), CHRROM);
+ set_nt_mirroring(BIT(offset, 10) ? PPU_MIRROR_HORZ : PPU_MIRROR_VERT);
+}
+
+/*-------------------------------------------------
+
+ BMC-CTC-09
+
+ Games: 10 in 1
+
+ NES 2.0: mapper 335
+
+ In MAME: Supported.
+
-------------------------------------------------*/
-void nes_ntd03_device::write_h(offs_t offset, uint8_t data)
+void nes_bmc_ctc09_device::write_h(offs_t offset, u8 data)
{
- uint8_t pbank = (offset >> 10) & 0x1e;
- uint8_t cbank = ((offset & 0x300) >> 5) | (offset & 0x07);
- LOG_MMC(("ntd03 write_h, offset: %04x, data: %02x\n", offset, data));
+ LOG("bmc_ctc09 write_h, offset: %04x, data: %02x\n", offset, data);
- if (BIT(offset, 7))
+ if (BIT(offset, 14))
{
- prg16_89ab(pbank | BIT(offset, 6));
- prg16_cdef(pbank | BIT(offset, 6));
+ if (BIT(data, 4))
+ {
+ u8 bank = ((data & 0x07) << 1) | BIT(data, 3);
+ prg16_89ab(bank);
+ prg16_cdef(bank);
+ }
+ else
+ prg32(data & 0x07);
+ set_nt_mirroring(BIT(data, 5) ? PPU_MIRROR_HORZ : PPU_MIRROR_VERT);
}
else
- prg32(pbank >> 1);
+ chr8(data & 0x0f, CHRROM);
+}
- set_nt_mirroring(BIT(offset, 10) ? PPU_MIRROR_HORZ : PPU_MIRROR_VERT);
+/*-------------------------------------------------
+
+ Board DS-9-27
+
+ Games: 190 in 1
+
+ Bizarro board of mostly simple games that has
+ 8K of WRAM that is mappable, with mirroring in
+ NROM128 mode, to anywhere in upper memory.
+
+ NES 2.0: mapper 452
+
+ In MAME: Supported.
+
+ -------------------------------------------------*/
+
+u8 nes_bmc_ds927_device::read_h(offs_t offset)
+{
+ LOGMASKED(LOG_HIFREQ, "bmc_ds927 read_h, offset: %04x\n", offset);
+
+ int bits = m_mode == 1 ? 1 : 2;
+
+ if (BIT(offset, 13, bits) == BIT(m_latch, 4, bits))
+ return m_prgram[offset & 0x1fff];
- chr8(cbank, CHRROM);
+ return hi_access_rom(offset);
+}
+
+void nes_bmc_ds927_device::write_h(offs_t offset, u8 data)
+{
+ LOG("bmc_ds927 write_h, offset: %04x, data: %02x\n", offset, data);
+
+ if (offset < 0x6000)
+ {
+ m_latch = data;
+ m_mode = bitswap<2>(data, 3, 1);
+
+ int bank = BIT(offset, 1, 7);
+
+ switch (m_mode)
+ {
+ case 0:
+ prg16_89ab(bank >> 1);
+ prg16_cdef(0);
+ break;
+ case 1:
+ for (int i = 0; i < 4; i++)
+ prg8_x(i, bank);
+ break;
+ case 2:
+ case 3:
+ prg8_89(bank);
+ prg8_ab(bank | 1);
+ prg8_cd(bank | 2);
+ prg8_ef(bank | 3 | (data & 0x04));
+ break;
+ }
+ }
+
+ set_nt_mirroring(BIT(data, 0) ? PPU_MIRROR_HORZ : PPU_MIRROR_VERT);
+
+ int bits = m_mode == 1 ? 1 : 2;
+
+ if (BIT(offset, 13, bits) == BIT(m_latch, 4, bits))
+ m_prgram[offset & 0x1fff] = data;
}
/*-------------------------------------------------
- BMC-GHOSTBUSTERS63IN1
+ Board BMC-GKA
+
+ Unknown Bootleg Multigame Board
+ Games: 6 in 1, 54 in 1, 106 in 1
+
+ iNES: mapper 57
- in MESS: only preliminar support
+ In MAME: Supported.
-------------------------------------------------*/
-void nes_bmc_gb63_device::chr_w(offs_t offset, uint8_t data)
+u8 nes_bmc_gka_device::read_m(offs_t offset)
{
- int bank = offset >> 10;
+ LOG("bmc_gka read_m, offset: %04x\n", offset);
+ return 0; // TODO: menus differ by jumper/DIP settings readable at 0x6000.
+}
- if (!m_vram_disable)
- m_chr_access[bank][offset & 0x3ff] = data;
+void nes_bmc_gka_device::write_h(offs_t offset, u8 data)
+{
+ LOG("bmc_gka write_h, offset: %04x, data: %02x\n", offset, data);
+
+ m_reg[BIT(offset, 11)] = data;
+
+ u8 bank = m_reg[1] >> 5;
+ u8 mode = BIT(m_reg[1], 4);
+ prg16_89ab(bank & ~mode);
+ prg16_cdef(bank | mode);
+
+ chr8((m_reg[0] & 0x40) >> 3 | (m_reg[1] & 0x04) | (m_reg[BIT(m_reg[0], 7)] & 0x03), CHRROM);
+ set_nt_mirroring(BIT(m_reg[1], 3) ? PPU_MIRROR_HORZ : PPU_MIRROR_VERT);
+}
+
+/*-------------------------------------------------
+
+ Board BMC-GKB
+
+ Unknown Bootleg Multigame Board
+ Games: 68 in 1, 73 in 1, 98 in 1, and many others
+
+ iNES: mapper 58
+
+ In MAME: Supported.
+
+ TODO: Investigate why Jewel on mc_wq55 crashes after
+ its title screen. It further invokes write_h, causing
+ bank switching (and these games are all NROM/CNROM so
+ they should never switch PRG once the menu loads them),
+ but ignoring those writes doesn't fix the problem. Is
+ the game non-working on hardware? A bad dump?
+
+ -------------------------------------------------*/
+
+void nes_bmc_gkb_device::write_h(offs_t offset, u8 data)
+{
+ LOG("bmc_gkb write_h, offset: %04x, data: %02x\n", offset, data);
+
+ u8 bank = offset & 0x07;
+ u8 mode = !BIT(offset, 6);
+ prg16_89ab(bank & ~mode);
+ prg16_cdef(bank | mode);
+
+ chr8(BIT(offset, 3, 3), CHRROM);
+ set_nt_mirroring(BIT(offset, 7) ? PPU_MIRROR_HORZ : PPU_MIRROR_VERT);
+}
+
+/*-------------------------------------------------
+
+ Board BMC-GKCXIN1
+
+ Unknown Bootleg Multigame Board
+ Games: 21 in 1, 64 in 1
+
+ NES 2.0: mapper 288
+
+ In MAME: Supported.
+
+ TODO: This has some sort of solder pad settings.
+
+ -------------------------------------------------*/
+
+void nes_bmc_gkcxin1_device::write_h(offs_t offset, u8 data)
+{
+ LOG("bmc_gkcxin1 write_h, offset: %04x, data: %02x\n", offset, data);
+
+ prg32(BIT(offset, 3, 2));
+ chr8(offset & 0x07, CHRROM);
}
-void nes_bmc_gb63_device::update_banks()
+/*-------------------------------------------------
+
+ Board BMC-GN-91B
+
+ Unknown Bootleg Multigame Board
+ Games: 2 in 1
+
+ NES 2.0: mapper 431
+
+ In MAME: Supported.
+
+ -------------------------------------------------*/
+
+void nes_bmc_gn91b_device::write_h(offs_t offset, u8 data)
{
- set_nt_mirroring(BIT(m_reg[0], 6) ? PPU_MIRROR_VERT : PPU_MIRROR_HORZ);
+ LOG("bmc_gn91b write_h, offset: %04x, data: %02x\n", offset, data);
+
+ if (offset < 0x4000)
+ {
+ m_latch = (offset & 0x10) >> 1;
+ prg16_cdef(m_latch | 0x07);
+ set_nt_mirroring(m_latch ? PPU_MIRROR_HORZ : PPU_MIRROR_VERT);
+ }
+ prg16_89ab(m_latch | (data & 0x07));
+}
- if (BIT(m_reg[0], 5))
+/*-------------------------------------------------
+
+ Board HP-898F
+
+ Games: Prima soft 9999999 in 1 and others
+
+ NES 2.0: mapper 319
+
+ In MAME: Supported.
+
+ TODO: Mirroring is clearly incorrect for Ninja-kun
+ on 4 in 1 (0207). Is this an error on the original
+ cart or should there really be a variant device?
+
+ -------------------------------------------------*/
+
+u8 nes_bmc_hp898f_device::read_l(offs_t offset)
+{
+ LOG("bmc_hp898f read_l, offset: %04x\n", offset);
+
+ offset += 0x100;
+ if (offset & 0x1000)
+ return 0; // FIXME: some carts read jumpers that change menu
+
+ return get_open_bus();
+}
+
+void nes_bmc_hp898f_device::write_m(offs_t offset, u8 data)
+{
+ LOG("bmc_hp898f write_m, offset: %04x, data: %02x\n", offset, data);
+
+ if (offset & 0x04)
{
- prg16_89ab(m_reg[0] & 0x1f);
- prg16_cdef(m_reg[0] & 0x1f);
+ u8 bank = bitswap<3>(data, 4, 3, 5);
+ u8 mode = BIT(data, 6);
+ prg16_89ab(bank & ~mode);
+ prg16_cdef(bank | mode);
+ set_nt_mirroring(BIT(data, 7) ? PPU_MIRROR_VERT : PPU_MIRROR_HORZ);
}
else
- prg32((m_reg[0] & 0x1f) >> 1);
+ chr8(data >> 4, CHRROM);
+}
+
+/*-------------------------------------------------
-// according to FCEUMM source, the game should be able to disable the VRAM, but this stops the game from working
-// maybe the VRAM disable does not work at start?
-// m_vram_disable = BIT(m_reg[1], 1) ? 0 : 1;
+ BMC-K-3036
+
+ Games: 35 in 1
+
+ NES 2.0: mapper 340
+
+ In MAME: Supported.
+
+ -------------------------------------------------*/
+
+void nes_bmc_k3036_device::write_h(offs_t offset, u8 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));
+ set_nt_mirroring((offset & 0x25) == 0x25 ? PPU_MIRROR_HORZ : PPU_MIRROR_VERT);
}
-void nes_bmc_gb63_device::write_h(offs_t offset, uint8_t data)
+/*-------------------------------------------------
+
+ BMC-K-3046
+
+ Games: 11 in 1
+
+ NES 2.0: mapper 336
+
+ In MAME: Supported.
+
+ -------------------------------------------------*/
+
+void nes_bmc_k3046_device::write_h(offs_t offset, u8 data)
{
- LOG_MMC(("bmc_gb63 write_h, offset: %04x, data: %02x\n", offset, data));
+ LOG("bmc_k3046 write_h, offset: %04x, data: %02x\n", offset, data);
- m_reg[offset & 1] = data;
- m_latch = BIT(m_reg[0], 7) | (BIT(m_reg[1], 0) << 1);
- update_banks();
+ // this pcb is subject to bus conflict
+ data = account_bus_conflict(offset, data);
+
+ data &= 0x1f;
+ prg16_89ab(data);
+ prg16_cdef(data | 0x07);
}
-uint8_t nes_bmc_gb63_device::read_h(offs_t offset)
+/*-------------------------------------------------
+
+ BMC-K-3071
+
+ Games: 110 in 1
+
+ NES 2.0: mapper 438
+
+ In MAME: Supported.
+
+ -------------------------------------------------*/
+
+void nes_bmc_k3071_device::write_h(offs_t offset, u8 data)
{
- LOG_MMC(("bmc_gb63 read_h, offset: %04x\n", offset));
- // m_dipsetting = ioport("CARTDIPS")->read();
+ LOG("bmc_k3071 write_h, offset: %04x, data: %02x\n", offset, data);
- if (m_latch == 1)
- return get_open_bus(); // open bus
- else
- return hi_access_rom(offset);
+ u8 bank = BIT(offset, 1, 5);
+ u8 mode = BIT(offset, 0);
+ prg16_89ab(bank & ~mode);
+ prg16_cdef(bank | mode);
+
+ chr8(BIT(data, 1, 5), CHRROM);
+ set_nt_mirroring(BIT(data, 0) ? PPU_MIRROR_HORZ : PPU_MIRROR_VERT);
+}
+
+/*-------------------------------------------------
+
+ BMC-S-009
+
+ Games: 8 in 1
+
+ NES 2.0: mapper 434
+
+ In MAME: Supported.
+
+ -------------------------------------------------*/
+
+void nes_bmc_s009_device::write_m(offs_t offset, u8 data)
+{
+ LOG("bmc_s009 write_m, offset: %04x, data: %02x\n", offset, data);
+
+ m_reg = (data & 0x07) << 3;
+ prg16_89ab(m_reg);
+ prg16_cdef(m_reg | 0x07);
+
+ set_nt_mirroring(BIT(data, 5) ? PPU_MIRROR_VERT : PPU_MIRROR_HORZ);
}
+void nes_bmc_s009_device::write_h(offs_t offset, u8 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);
+
+ prg16_89ab(m_reg | (data & 0x07));
+}
/*-------------------------------------------------
- Board BMC-GKA
+ BMC-SA005-A
- Unknown Bootleg Multigame Board
- Games: 6 in 1, 54 in 1, 106 in 1
+ Games: 16 in 1
- iNES: mapper 57
+ NES 2.0: mapper 338
+
+ In MAME: Supported.
+
+ -------------------------------------------------*/
- In MESS: Supported.
+void nes_bmc_sa005a_device::write_h(offs_t offset, u8 data)
+{
+ LOG("bmc_sa005a write_h, offset: %04x, data: %02x\n", offset, data);
+ u8 bank = offset & 0x0f;
+ prg16_89ab(bank);
+ prg16_cdef(bank);
+ chr8(bank, CHRROM);
+ set_nt_mirroring(BIT(offset, 3) ? PPU_MIRROR_VERT : PPU_MIRROR_HORZ);
+}
+
+/*-------------------------------------------------
+
+ BMC-TF2740
+
+ Games: 14 in 1, 40 in 1, 158 in 1, 9999 in 1,
+ 10000000 in 1
+
+ NES 2.0: mapper 428
+
+ In MAME: Supported.
-------------------------------------------------*/
-void nes_bmc_gka_device::write_h(offs_t offset, uint8_t data)
+void nes_bmc_tf2740_device::update_chr()
{
- LOG_MMC(("bmc_gka write_h, offset: %04x, data: %02x\n", offset, data));
+ chr8(m_reg[2] & 0xc0 ? (m_reg[1] & 0x04) | (m_reg[0] & 0x03) : m_reg[1] & 0x07, CHRROM);
+}
- if (offset & 0x0800)
- m_latch2 = data;
- else
- m_latch1 = data;
+void nes_bmc_tf2740_device::write_m(offs_t offset, u8 data)
+{
+ LOG("bmc_tf2740 write_m, offset: %04x, data: %02x\n", offset, data);
- if (m_latch2 & 0x80)
- prg32(2 | (m_latch2 >> 6));
- else
+ switch (offset & 0x03)
{
- prg16_89ab((m_latch2 >> 5) & 0x03);
- prg16_cdef((m_latch2 >> 5) & 0x03);
- }
+ case 0x01:
+ {
+ u8 bank = data >> 5;
+ u8 mode = BIT(data, 4);
+ prg16_89ab(bank & ~mode);
+ prg16_cdef(bank | mode);
- set_nt_mirroring((m_latch2 & 0x08) ? PPU_MIRROR_HORZ : PPU_MIRROR_VERT);
+ set_nt_mirroring(BIT(data, 3) ? PPU_MIRROR_HORZ : PPU_MIRROR_VERT);
+ [[fallthrough]];
+ }
+ case 0x02:
+ m_reg[offset & 0x03] = data;
+ update_chr();
+ break;
+ }
+}
- chr8((m_latch1 & 0x03) | (m_latch2 & 0x07) | ((m_latch2 & 0x10) >> 1), CHRROM);
+void nes_bmc_tf2740_device::write_h(offs_t offset, u8 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("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
+}
/*-------------------------------------------------
- Board BMC-GKB
+ BMC-TH2348
- Unknown Bootleg Multigame Board
- Games: 68 in 1, 73 in 1, 98 in 1
+ Games: Golden 8 in 1
- iNES: mapper 58
+ NES 2.0: mapper 437
- In MESS: Supported.
+ In MAME: Supported.
-------------------------------------------------*/
-void nes_bmc_gkb_device::write_h(offs_t offset, uint8_t data)
+void nes_bmc_th2348_device::write_l(offs_t offset, u8 data)
{
- uint8_t bank = (offset & 0x40) ? 0 : 1;
- LOG_MMC(("bmc_gkb write_h, offset: %04x, data: %02x\n", offset, data));
+ LOG("bmc_th2348 write_l, offset: %04x, data: %02x\n", offset, data);
- prg16_89ab(offset & ~bank);
- prg16_cdef(offset | bank);
- chr8(offset >> 3, m_chr_source);
- set_nt_mirroring(BIT(data, 7) ? PPU_MIRROR_HORZ : PPU_MIRROR_VERT);
+ offset += 0x100;
+ if (offset >= 0x1000)
+ {
+ m_latch = (offset & 0x07) << 3;
+ prg16_89ab(m_latch);
+ prg16_cdef(m_latch | 0x07);
+
+ set_nt_mirroring(BIT(offset, 3) ? PPU_MIRROR_HORZ : PPU_MIRROR_VERT);
+ }
+}
+
+void nes_bmc_th2348_device::write_h(offs_t offset, u8 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);
+
+ prg16_89ab(m_latch | (data & 0x07));
+}
+
+/*-------------------------------------------------
+
+ BMC-TJ-03
+
+ Games: 4 in 1
+
+ NES 2.0: mapper 341
+
+ In MAME: Supported.
+
+ -------------------------------------------------*/
+
+void nes_bmc_tj03_device::write_h(offs_t offset, u8 data)
+{
+ LOG("bmc_tj03 write_h, offset: %04x, data: %02x\n", offset, data);
+ u8 bank = BIT(offset, 8, 2);
+ prg32(bank);
+ chr8(bank, CHRROM);
+ set_nt_mirroring(BIT(offset, 9) ? PPU_MIRROR_HORZ : PPU_MIRROR_VERT);
}
/*-------------------------------------------------
@@ -1546,15 +2315,14 @@ void nes_bmc_gkb_device::write_h(offs_t offset, uint8_t data)
Games: Super 40-in-1
- In MESS: Partially Supported (some games, like Galaxian, have
+ In MAME: Partially Supported (some games, like Galaxian, have
issues)
-------------------------------------------------*/
void nes_bmc_ws_device::write_m(offs_t offset, uint8_t data)
{
- uint8_t mmc_helper;
- 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)
{
@@ -1565,9 +2333,9 @@ void nes_bmc_ws_device::write_m(offs_t offset, uint8_t data)
{
m_latch = data & 0x20;
set_nt_mirroring(BIT(data, 4) ? PPU_MIRROR_HORZ : PPU_MIRROR_VERT);
- mmc_helper = (~data & 0x08) >> 3;
- prg16_89ab(data & ~mmc_helper);
- prg16_cdef(data | mmc_helper);
+ u8 mode = !BIT(data, 3);
+ prg16_89ab(data & ~mode);
+ prg16_cdef(data | mode);
}
break;
case 1:
@@ -1580,21 +2348,23 @@ void nes_bmc_ws_device::write_m(offs_t offset, uint8_t data)
/*-------------------------------------------------
- Board BMC-11160 (by TXC?)
+ Board BMC-11160 by TXC
Games: 6 in 1 (MGC-023)
- In MESS: Partially Supported
+ NES 2.0: mapper 299
+
+ In MAME: Partially supported. (Light gun hit detection is broken)
-------------------------------------------------*/
-void nes_bmc_11160_device::write_h(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((data & 0x70) >> 4);
- chr8(((data & 0x70) >> 2) | (data & 3), m_chr_source);
- set_nt_mirroring(BIT(data, 7) ? PPU_MIRROR_HORZ : PPU_MIRROR_VERT);
+ prg32(BIT(data, 4, 2));
+ chr8(bitswap<4>(data, 5, 4, 1, 0), CHRROM);
+ set_nt_mirroring(BIT(data, 7) ? PPU_MIRROR_VERT : PPU_MIRROR_HORZ);
}
/*-------------------------------------------------
@@ -1603,31 +2373,53 @@ void nes_bmc_11160_device::write_h(offs_t offset, uint8_t data)
Games: 1994 Super HIK 14 in 1 (G-136)
- In MESS: Partially Supported
+ NES 2.0: mapper 349
+
+ In MAME: Supported.
-------------------------------------------------*/
-void nes_bmc_g146_device::write_h(offs_t offset, uint8_t 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);
- if (offset & 0x800)
+ u8 prg_lo = offset & 0x1f;
+ u8 prg_hi = prg_lo; // default: NROM-128 mode
+ if (BIT(offset, 11))
+ prg_hi |= 0x07; // UNROM mode
+ else if (!BIT(offset, 6))
{
- // UNROM mode
- int helper = offset & BIT(offset, 6);
- prg16_89ab((offset & 0x1f) | helper);
- prg16_cdef((offset & 0x18) | 7);
+ prg_lo &= ~0x01; // NROM-256 mode
+ prg_hi |= 0x01;
}
- else if (offset & 0x40)
- {
- // 16KB mode
- prg16_89ab(offset & 0x1f);
- prg16_cdef(offset & 0x1f);
- }
- else
- prg32((offset & 0x1f) >> 4);
+ prg16_89ab(prg_lo);
+ prg16_cdef(prg_hi);
+
+ set_nt_mirroring(BIT(offset, 7) ? PPU_MIRROR_HORZ : PPU_MIRROR_VERT);
+}
- set_nt_mirroring(!BIT(offset, 7) ? PPU_MIRROR_HORZ : PPU_MIRROR_VERT);
+/*-------------------------------------------------
+
+ Board BMC-2751
+
+ Games: 5 in 1
+
+ iNES: mapper 174
+
+ In MAME: Supported.
+
+ -------------------------------------------------*/
+
+void nes_bmc_2751_device::write_h(offs_t offset, u8 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);
+ prg16_cdef(bank | mode);
+
+ chr8(BIT(offset, 1, 3), CHRROM);
+ set_nt_mirroring(BIT(offset, 0) ? PPU_MIRROR_HORZ : PPU_MIRROR_VERT);
}
/*-------------------------------------------------
@@ -1636,35 +2428,41 @@ void nes_bmc_g146_device::write_h(offs_t offset, uint8_t data)
Games: 4 in 1 1993 (CK-001)
- In MESS: Partially Supported
+ NES 2.0: mapper 301
+
+ In MAME: Preliminary supported.
+
+ TODO: Determine the cause of Contra graphics glitches.
+ Is NesDev description of board wrong? It seems b9 = 1
+ and b7 = 0 always? Also couldn't see evidence of the
+ mirroring bit being used.
-------------------------------------------------*/
-void nes_bmc_8157_device::write_h(offs_t offset, uint8_t 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);
- prg16_89ab((offset >> 2) & 0x1f);
- if (offset & 0x200)
- prg16_cdef(offset & 0x1f);
- else
- prg16_cdef((offset & 0x18) | 7);
+ u8 bank = BIT(offset, 2, 5);
+ prg16_89ab(bank);
+ if (BIT(offset, 9))
+ bank |= 0x07;
+ else if (BIT(offset, 7))
+ bank &= ~0x07;
+ prg16_cdef(bank);
- set_nt_mirroring(!BIT(offset, 1) ? PPU_MIRROR_HORZ : PPU_MIRROR_VERT);
+ m_latch = BIT(offset, 8);
+ set_nt_mirroring(BIT(offset, 1) ? PPU_MIRROR_HORZ : PPU_MIRROR_VERT);
}
-uint8_t nes_bmc_8157_device::read_h(offs_t offset)
+u8 nes_bmc_8157_device::read_h(offs_t offset)
{
- LOG_MMC(("bmc_8157 read_h, offset: %04x\n", offset));
- // m_dipsetting = ioport("CARTDIPS")->read();
-
-// uint8_t val = hi_access_rom(offset);
-// return val | m_noise; // the first write_h sets m_noise=0xff or 0 depending on dsw
-
+ LOG("bmc_8157 read_h, offset: %04x\n", offset);
+ if (m_latch)
+ offset = (offset & ~0x01) | m_jumper->read();
return hi_access_rom(offset);
}
-
/*-------------------------------------------------
BMC-SUPERHIK_300IN1
@@ -1674,24 +2472,27 @@ uint8_t nes_bmc_8157_device::read_h(offs_t offset)
iNES: mapper 212
- In MESS: Supported.
+ In MAME: Supported.
-------------------------------------------------*/
-void nes_bmc_hik300_device::write_h(offs_t offset, uint8_t data)
+u8 nes_bmc_hik300_device::read_m(offs_t offset)
{
- LOG_MMC(("bmc_hik300 write_h, offset: %04x, data: %02x\n", offset, data));
+ 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
+}
- set_nt_mirroring(BIT(data, 3) ? PPU_MIRROR_HORZ : PPU_MIRROR_VERT);
- chr8(offset, CHRROM);
+void nes_bmc_hik300_device::write_h(offs_t offset, u8 data)
+{
+ LOG("bmc_hik300 write_h, offset: %04x, data: %02x\n", offset, data);
- if (offset < 0x4000)
- {
- prg16_89ab(offset);
- prg16_cdef(offset);
- }
- else
- prg32(offset >> 1);
+ u8 bank = offset & 0x07;
+ u8 mode = BIT(offset, 14);
+ prg16_89ab(bank & ~mode);
+ prg16_cdef(bank | mode);
+
+ chr8(bank, CHRROM);
+ set_nt_mirroring(BIT(offset, 3) ? PPU_MIRROR_HORZ : PPU_MIRROR_VERT);
}
/*-------------------------------------------------
@@ -1699,31 +2500,33 @@ void nes_bmc_hik300_device::write_h(offs_t offset, uint8_t data)
BMC-SUPER-700IN1
Unknown Bootleg Multigame Board
- Games: Super 700 in 1
+ Games: Super 700 in 1, Super 190 in 1
iNES: mapper 62
- In MESS: Supported.
+ In MAME: Supported.
+
+ TODO:
+ - Investigate why Gradius menu items 643-649 crash
+ 700-in-1 after pressing start at title screen.
+ Gradius works from other menu numbers fine.
+ - Slalom and Star Force have the wrong mirroring
+ on 190-in-1. Bug on cart, bad dump, or is there
+ another bit that affects mirroring?
-------------------------------------------------*/
-void nes_bmc_s700_device::write_h(offs_t offset, uint8_t 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));
-
- chr8(((offset & 0x1f) << 2) | (data & 0x03), CHRROM);
+ LOG("bmc_s700 write_h, offset: %04x, data: %02x\n", offset, data);
- if (offset & 0x20)
- {
- prg16_89ab((offset & 0x40) | ((offset >> 8) & 0x3f));
- prg16_cdef((offset & 0x40) | ((offset >> 8) & 0x3f));
- }
- else
- {
- prg32(((offset & 0x40) | ((offset >> 8) & 0x3f)) >> 1);
- }
+ u8 bank = (offset & 0x40) | BIT(offset, 8, 6);
+ u8 mode = !BIT(offset, 5);
+ prg16_89ab(bank & ~mode);
+ prg16_cdef(bank | mode);
- set_nt_mirroring(BIT(data, 7) ? PPU_MIRROR_HORZ : PPU_MIRROR_VERT);
+ chr8((offset & 0x1f) << 2 | (data & 0x03), CHRROM);
+ set_nt_mirroring(BIT(offset, 7) ? PPU_MIRROR_HORZ : PPU_MIRROR_VERT);
}
/*-------------------------------------------------
@@ -1731,52 +2534,46 @@ void nes_bmc_s700_device::write_h(offs_t offset, uint8_t data)
BMC-BALLGAMES-11IN1
Known Boards: Unknown Multigame Bootleg Board
- Games: 11 in 1 Ball Games
+ Games: 11 in 1 Ball Series
iNES: mapper 51
- In MESS: Partially Supported.
+ In MAME: Supported.
-------------------------------------------------*/
-void nes_bmc_ball11_device::set_banks()
+u8 nes_bmc_ball11_device::read_m(offs_t offset)
{
- set_nt_mirroring((m_reg[0] == 3) ? PPU_MIRROR_HORZ : PPU_MIRROR_VERT);
+ LOG("bmc_ball11 read_m, offset: %04x, data: %02x\n", offset);
- if (m_reg[0] & 0x01)
- {
+ u8 bank = m_reg[1] << 2 | (m_reg[0] ? 0x23 : 0x2f);
+ return m_prg[(bank * 0x2000 + offset) & (m_prg_size - 1)];
+}
+
+void nes_bmc_ball11_device::update_prg()
+{
+ if (m_reg[0])
prg32(m_reg[1]);
- }
else
{
- prg16_89ab((m_reg[1] << 1) | (m_reg[0] >> 1));
- prg16_cdef((m_reg[1] << 1) | 0x07);
+ prg16_89ab(m_reg[1] << 1 | BIT(m_reg[1], 4));
+ prg16_cdef(m_reg[1] << 1 | 0x07);
}
}
-void nes_bmc_ball11_device::write_m(offs_t offset, uint8_t data)
+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));
-
- m_reg[0] = ((data >> 1) & 0x01) | ((data >> 3) & 0x02);
- set_banks();
+ 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();
}
-void nes_bmc_ball11_device::write_h(offs_t offset, uint8_t 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));
-
- switch (offset & 0x6000)
- {
- case 0x4000: // here we also update reg[0] upper bit
- m_reg[0] = (m_reg[0] & 0x01) | ((data >> 3) & 0x02);
- case 0x0000:
- case 0x2000:
- case 0x6000:
- m_reg[1] = data & 0x0f;
- set_banks();
- break;
- }
+ LOG("bmc_ball11 write_h, offset: %04x, data: %02x\n", offset, data);
+ m_reg[1] = data & 0x1f;
+ update_prg();
}
/*-------------------------------------------------
@@ -1784,37 +2581,33 @@ void nes_bmc_ball11_device::write_h(offs_t offset, uint8_t data)
BMC-22GAMES
Unknown Bootleg Multigame Board
- Games: 22 in 1
+ Games: Contra/22 in 1 combo
iNES: mapper 230
- In MESS: Partially Supported. It would need a reset
- to work (not possible yet)
+ In MAME: Supported.
+
+ TODO: Determine whether reset works as written or
+ whether it toggles between Contra and the game menu.
+ Reset to Contra from the menu or other games often
+ fails due to RAM contents it seems.
-------------------------------------------------*/
-void nes_bmc_22games_device::write_h(offs_t offset, uint8_t 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 (1) // this should flip at reset
- {
- prg16_89ab(data & 0x07);
- }
- else
+ if (m_latch)
{
- if (data & 0x20)
- {
- prg16_89ab((data & 0x1f) + 8);
- prg16_cdef((data & 0x1f) + 8);
- }
- else
- {
- prg16_89ab((data & 0x1f) + 8);
- prg16_cdef((data & 0x1f) + 9);
- }
+ u8 bank = (data & 0x1f) + 8;
+ u8 mode = !BIT(data, 5);
+ prg16_89ab(bank & ~mode);
+ prg16_cdef(bank | mode);
set_nt_mirroring(BIT(data, 6) ? PPU_MIRROR_VERT : PPU_MIRROR_HORZ);
}
+ else
+ prg16_89ab(data & 0x07);
}
/*-------------------------------------------------
@@ -1823,97 +2616,125 @@ void nes_bmc_22games_device::write_h(offs_t offset, uint8_t data)
Games: 64-in-1 Y2K
- In MESS: Supported
+ NES 2.0: mapper 314
+
+ In MAME: Supported.
-------------------------------------------------*/
-void nes_bmc_64y2k_device::set_prg()
+void nes_bmc_64y2k_device::update_banks()
{
- uint8_t helper1 = (m_reg[1] & 0x1f);
- uint8_t helper2 = (helper1 << 1) | ((m_reg[1] & 0x40) >> 6);
-
- if (m_reg[0] & 0x80)
+ if (BIT(m_reg[0] & m_reg[1], 7))
+ prg32(m_reg[1]);
+ else
{
- if (m_reg[1] & 0x80)
- prg32(helper1);
- else
- {
- prg16_89ab(helper2);
- prg16_cdef(helper2);
- }
+ u8 bank = m_reg[1] << 1 | BIT(m_reg[1], 6);
+ prg16_89ab(bank);
+ prg16_cdef(bank | (BIT(m_reg[0], 7) ? 0 : 7));
}
- else
- prg16_cdef(helper2);
+
+ chr8(BIT(m_reg[0], 1, 2) | (m_reg[2] << 2), m_chr_source);
+ set_nt_mirroring(BIT(m_reg[0], 5) ? PPU_MIRROR_HORZ : PPU_MIRROR_VERT);
}
-void nes_bmc_64y2k_device::write_l(offs_t offset, uint8_t data)
+void nes_bmc_64y2k_device::write_l(offs_t offset, u8 data)
{
- LOG_MMC(("bmc64y2k write_l, offset: %04x, data: %02x\n", offset, data));
- offset += 0x100;
+ LOG("bmc_64y2k write_l, offset: %04x, data: %02x\n", offset, data);
- switch (offset)
+ offset += 0x100;
+ if (offset >= 0x1000)
{
- case 0x1000:
- case 0x1001:
- case 0x1002:
- case 0x1003:
- m_reg[offset & 0x03] = data;
- set_prg();
- chr8(((m_reg[0] >> 1) & 0x03) | (m_reg[2] << 2), CHRROM);
- break;
+ m_reg[offset & m_reg_mask] = data;
+ update_banks();
}
- if (offset == 0x1000) /* write to reg[0] also sets mirroring */
- set_nt_mirroring(BIT(data, 5) ? PPU_MIRROR_HORZ : PPU_MIRROR_VERT);
}
-void nes_bmc_64y2k_device::write_h(offs_t offset, uint8_t data)
+void nes_bmc_64y2k_device::write_h(offs_t offset, u8 data)
{
- LOG_MMC(("bmc64y2k write_h, offset: %04x, data: %02x\n", offset, data));
+ LOG("bmc_64y2k write_h, offset: %04x, data: %02x\n", offset, data);
- m_reg[3] = data; // reg[3] is currently unused?!?
+ if (!BIT(m_reg[0], 7))
+ prg16_89ab(((m_reg[1] << 1) & ~0x07) | (data & 0x07));
}
/*-------------------------------------------------
- BMC-12IN1
+ Board BMC-TELETUBBIES
+ (name assigned by BootGod who said the board has
+ no markings, a glop top, and an 8K VRAM chip)
- Unknown Bootleg Multigame Board
- Games:
+ Games: Y2K 420 in 1
- iNES:
+ iNES: mapper 237
- In MESS: Supported.
+ In MAME: Supported.
-------------------------------------------------*/
-void nes_bmc_12in1_device::update_banks()
+void nes_bmc_420y2k_device::write_h(offs_t offset, u8 data)
{
- int bank = (m_reg[2] & 3) << 3;
-
- chr4_0((m_reg[0] >> 3) | (bank << 2), m_chr_source);
- chr4_4((m_reg[1] >> 3) | (bank << 2), m_chr_source);
+ LOG("bmc_420y2k write_h, offset: %04x, data: %02x\n", offset, data);
- if (m_reg[2] & 8)
- prg32(((m_reg[0] & 7) >> 1) | bank);
+ if (BIT(m_latch, 1)) // lock bit
+ m_reg = (m_reg & ~0x07) | (data & 0x07);
else
{
- prg16_89ab((m_reg[0] & 7) | bank);
- prg16_cdef(7 | bank);
+ m_latch = offset;
+ m_reg = data;
}
- set_nt_mirroring(BIT(m_reg[2], 2) ? PPU_MIRROR_HORZ : PPU_MIRROR_VERT);
+ u8 bank = BIT(m_latch, 2) << 5 | (m_reg & 0x1f);
+ u8 mode = BIT(m_reg, 6);
+ prg16_89ab(bank & ~mode); // strangely for UNROM games it DOESN'T ignore the NROM mode bit
+ prg16_cdef(bank | (BIT(m_reg, 7) ? mode : 0x07));
+
+ set_nt_mirroring(BIT(m_reg, 5) ? PPU_MIRROR_HORZ : PPU_MIRROR_VERT);
}
-void nes_bmc_12in1_device::write_h(offs_t offset, uint8_t data)
+u8 nes_bmc_420y2k_device::read_h(offs_t offset)
{
- LOG_MMC(("bmc_12in1 write_h, offset: %04x, data: %02x\n", offset, data));
+ 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);
+}
- switch (offset & 0x6000)
- {
- case 0x2000: m_reg[0] = data; break;
- case 0x4000: m_reg[1] = data; break;
- case 0x6000: m_reg[2] = data; break;
- }
+/*-------------------------------------------------
+
+ BMC-12IN1
+
+ Unknown Bootleg Multigame Board
+ Games: 7 in 1
+
+ NES 2.0: mapper 331
+
+ In MAME: Supported.
+
+ TODO: Supposedly PRG banks change depending on what
+ CHR page the PPU is rendering from. This is not
+ emulated but the cart still works since both inner
+ PRG registers are always set to the same value.
+
+ -------------------------------------------------*/
+
+void nes_bmc_12in1_device::update_banks()
+{
+ u8 outer = (m_reg[3] & 0x03) << 3;
+ u8 mode = BIT(m_reg[3], 3) ? 0x01 : 0x07; // NROM256 or UNROM-like mode
+ prg16_89ab(outer | (m_reg[1] & 0x07));
+ prg16_cdef(outer | (m_reg[2] & 0x07) | mode);
+
+ chr4_0(outer | (m_reg[1] >> 3), m_chr_source);
+ chr4_4(outer | (m_reg[2] >> 3), m_chr_source);
+
+ set_nt_mirroring(BIT(m_reg[3], 2) ? PPU_MIRROR_HORZ : PPU_MIRROR_VERT);
+}
+
+void nes_bmc_12in1_device::write_h(offs_t offset, u8 data)
+{
+ LOG("bmc_12in1 write_h, offset: %04x, data: %02x\n", offset, data);
+
+ m_reg[BIT(offset, 13, 2)] = data;
update_banks();
}
@@ -1926,39 +2747,38 @@ void nes_bmc_12in1_device::write_h(offs_t offset, uint8_t data)
iNES: mapper 231
- In MESS: Supported.
+ In MAME: Supported.
-------------------------------------------------*/
-void nes_bmc_20in1_device::write_h(offs_t offset, uint8_t 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);
- set_nt_mirroring(BIT(data, 7) ? PPU_MIRROR_HORZ : PPU_MIRROR_VERT);
-
- prg16_89ab((offset & 0x1e));
- prg16_cdef((offset & 0x1e) | ((offset & 0x20) ? 1 : 0));
+ prg16_89ab(offset & 0x1e);
+ prg16_cdef((offset & 0x1e) | BIT(offset, 5));
+ set_nt_mirroring(BIT(offset, 7) ? PPU_MIRROR_HORZ : PPU_MIRROR_VERT);
}
/*-------------------------------------------------
- BMC-21IN1
+ BMC-21IN1, BMC-NOVELDIAMOND
Unknown Bootleg Multigame Board
- Games: 8 in 1, 21 in 1
+ Games: 8 in 1, 21 in 1, 9999999 in 1
iNES: mapper 201
- In MESS: Supported.
+ In MAME: Supported.
-------------------------------------------------*/
-void nes_bmc_21in1_device::write_h(offs_t offset, uint8_t 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 & 0x03, CHRROM);
+ chr8(offset & 0x07, CHRROM);
}
/*-------------------------------------------------
@@ -1970,27 +2790,25 @@ void nes_bmc_21in1_device::write_h(offs_t offset, uint8_t data)
iNES: mapper 229
- In MESS: Supported.
+ In MAME: Supported.
-------------------------------------------------*/
-void nes_bmc_31in1_device::write_h(offs_t offset, uint8_t 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);
- set_nt_mirroring(BIT(data, 5) ? PPU_MIRROR_HORZ : PPU_MIRROR_VERT);
- chr8(offset, CHRROM);
-
- if ((offset & 0x1e) == 0)
+ offset &= 0x1f;
+ if (offset & 0x1e)
{
- prg16_89ab(0);
- prg16_89ab(1);
+ prg16_89ab(offset);
+ prg16_cdef(offset);
}
else
- {
- prg16_89ab(offset & 0x1f);
- prg16_89ab(offset & 0x1f);
- }
+ prg32(0);
+
+ chr8(offset, CHRROM);
}
/*-------------------------------------------------
@@ -2002,16 +2820,17 @@ void nes_bmc_31in1_device::write_h(offs_t offset, uint8_t data)
iNES: mapper 203
- In MESS: Supported.
+ In MAME: Supported.
-------------------------------------------------*/
-void nes_bmc_35in1_device::write_h(offs_t offset, uint8_t 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);
- prg16_89ab((data >> 2) & 0x03);
- prg16_cdef((data >> 2) & 0x03);
+ u8 bank = BIT(data, 2, 2);
+ prg16_89ab(bank);
+ prg16_cdef(bank);
chr8(data & 0x03, CHRROM);
}
@@ -2024,13 +2843,13 @@ void nes_bmc_35in1_device::write_h(offs_t offset, uint8_t 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);
@@ -2048,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.
-------------------------------------------------*/
@@ -2056,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);
@@ -2067,163 +2886,165 @@ void nes_bmc_64in1_device::write_h(offs_t offset, uint8_t data)
/*-------------------------------------------------
- BMC-70IN1
+ BMC-70IN1 (FIXME: according to NesDev the boards for this
+ and BMC-800IN1 are Realtec 8031 and 8155. Which is which?)
- Unknown Bootleg Multigame Board
- Games:
+ Games: 35 in 1, 68 in 1, 70 in 1
+
+ iNES: mapper 236
- iNES: mapper
+ This is the same hardware as BMC-800IN1 below, but
+ these carts have CHRROM and lack the extended PRG
+ bank switching. Solder pads/jumpers not emulated yet.
- This is same hardware as BMC-800IN1 below, but this
- cart has CHR and slightly diff bankswitch.
- DSW not emulated yet.
+ In MAME: Supported.
- In MESS: Preliminary Supported.
+ TODO: Determine if Excitebike on 68 in 1 is actually
+ bugged on the real cartridge. It sets mirroring bit
+ to horizontal when it should be vertical.
-------------------------------------------------*/
-void nes_bmc_70in1_device::write_h(offs_t offset, uint8_t data)
+void nes_bmc_70in1_device::update_banks()
{
- LOG_MMC(("bmc70in1 write_h, offset: %04x, data: %02x\n", offset, data));
+ update_prg(m_latch[1] & 0x07);
+ chr8(m_latch[0] & 0x07, CHRROM);
+}
- if (offset < 0x4000)
+void nes_bmc_70in1_device::update_prg(u8 bank)
+{
+ if (BIT(m_latch[1], 5)) // NROM mode
{
- set_nt_mirroring(BIT(offset, 5) ? PPU_MIRROR_HORZ: PPU_MIRROR_VERT);
- chr8(offset & 7, CHRROM);
+ u8 mode = !BIT(m_latch[1], 4);
+ prg16_89ab(bank & ~mode);
+ prg16_cdef(bank | mode);
}
- else
+ else // UNROM mode
{
- switch (offset & 0x30)
- {
- case 0x00: m_mode = 0x0; m_reg[0] = (m_reg[0] & 0x38) | (offset & 0x7); m_reg[1] = m_reg[0] | 0x7; break;
- case 0x10: m_mode = 0x1; m_reg[0] = (m_reg[0] & 0x38) | (offset & 0x7); m_reg[1] = m_reg[0] | 0x7; break;
- case 0x20: m_mode = 0x0; m_reg[0] = (m_reg[0] & 0x38) | (offset & 0x6); m_reg[1] = m_reg[0] | 0x1; break;
- case 0x30: m_mode = 0x0; m_reg[0] = (m_reg[0] & 0x38) | (offset & 0x7); m_reg[1] = m_reg[0] | 0x0; break;
- }
- prg16_89ab(m_reg[0]);
- prg16_cdef(m_reg[1]);
+ prg16_89ab(bank);
+ prg16_cdef(bank | 0x07);
}
}
+void nes_bmc_70in1_device::write_h(offs_t offset, u8 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);
+}
+
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_mode)
- offset = (offset & 0x7ff0) | m_mode;
+ if ((m_latch[1] & 0x30) == 0x10)
+ offset = (offset & ~0x0f) | m_jumper; // TODO: make jumper selectable
return hi_access_rom(offset);
}
/*-------------------------------------------------
- BMC-72IN1
+ BMC-800IN1
- Unknown Bootleg Multigame Board
- Games: 72 in 1, 115 in 1 and other multigame carts
+ Games: 800 in 1
+
+ iNES: mapper 236
- iNES: mapper 225
+ This is the same hardware as BMC-70IN1, but this
+ cart supports larger PRG and has unbanked CHRRAM.
- In MESS: Supported.
+ In MAME: Supported.
-------------------------------------------------*/
-void nes_bmc_72in1_device::write_h(offs_t offset, uint8_t data)
+void nes_bmc_800in1_device::update_banks()
{
- int hi_bank = offset & 0x40;
- int size_16 = offset & 0x1000;
- int bank = (offset & 0xf80) >> 7;
-
- LOG_MMC(("bmc_72in1 write_h, offset: %04x, data: %02x\n", offset, data));
-
- chr8(offset, CHRROM);
- set_nt_mirroring((offset & 0x2000) ? PPU_MIRROR_HORZ : PPU_MIRROR_VERT);
- if (size_16)
- {
- bank <<= 1;
- if (hi_bank)
- bank ++;
-
- prg16_89ab(bank);
- prg16_cdef(bank);
- }
- else
- prg32(bank);
+ update_prg((m_latch[0] & 0x07) << 3 | (m_latch[1] & 0x07));
}
/*-------------------------------------------------
- BMC-76IN1
+ BMC-72IN1, BMC-110IN1
Unknown Bootleg Multigame Board
- Games: 76 in 1, Super 42 in 1
+ Games: 72 in 1, 115 in 1 and other multigame carts
- iNES: mapper 226
+ iNES: mappers 225, 255
- In MESS: Supported.
+ In MAME: Supported.
-------------------------------------------------*/
-// does this work for super42in1 as well?!?
-void nes_bmc_76in1_device::write_h(offs_t offset, uint8_t data)
+u8 nes_bmc_72in1_device::read_l(offs_t offset)
{
- int hi_bank;
- int size_16;
- int bank;
+ LOG("bmc_72in1 read_l, offset: %04x\n", offset);
- LOG_MMC(("bmc_76in1 write_h, offset: %04x, data: %02x\n", offset, data));
+ offset += 0x100;
+ if (offset >= 0x1800) // 4 nibbles of RAM mirrored above 0x5800
+ return m_extra_ram[offset & 0x03];
- if (offset & 0x01)
- m_latch2 = data;
- else
- m_latch1 = data;
+ return get_open_bus();
+}
- set_nt_mirroring(BIT(m_latch1, 6) ? PPU_MIRROR_HORZ : PPU_MIRROR_VERT);
+void nes_bmc_72in1_device::write_l(offs_t offset, u8 data)
+{
+ LOG("bmc_72in1 write_l, offset: %04x, data: %02x\n", offset, data);
- hi_bank = m_latch1 & 0x01;
- size_16 = m_latch1 & 0x20;
- bank = ((m_latch1 & 0x1e) >> 1) | ((m_latch1 & 0x80) >> 3) | ((m_latch2 & 0x01) << 5);
+ offset += 0x100;
+ if (offset >= 0x1800) // 4 nibbles of RAM mirrored above 0x5800
+ m_extra_ram[offset & 0x03] = data & 0x0f;
+}
- if (size_16)
- {
- bank <<= 1;
- if (hi_bank)
- bank ++;
+void nes_bmc_72in1_device::write_h(offs_t offset, u8 data)
+{
+ LOG("bmc_72in1 write_h, offset: %04x, data: %02x\n", offset, data);
- prg16_89ab(bank);
- prg16_cdef(bank);
- }
- else
- prg32(bank);
+ u8 high = (offset >> 8) & 0x40;
+ u8 bank = high | BIT(offset, 6, 6);
+ u8 mode = !BIT(offset, 12);
+ prg16_89ab(bank & ~mode);
+ prg16_cdef(bank | mode);
+
+ chr8(high | (offset & 0x3f), CHRROM);
+ set_nt_mirroring(BIT(offset, 13) ? PPU_MIRROR_HORZ : PPU_MIRROR_VERT);
}
/*-------------------------------------------------
- BMC-110IN1
+ BMC-76IN1, BMC-SUPER42IN1, BMC-GHOSTBUSTERS63IN1
- Known Boards: Unknown Bootleg Board
- Games: 110 in 1
+ Unknown Bootleg Multigame Board
+ Games: 76 in 1, Super 42 in 1, Ghostbusters 63 in 1
+
+ iNES: mapper 226
- iNES: mapper 255
+ In MAME: Supported.
- In MESS: Preliminary support.
+ TODO: Investigate nature of GB63's PCB. It likely has
+ three 512KB chips and it seems the two high-order bits
+ here select between them. However, 0,1 select the first
+ chip and 2,3 correspond to the other two respectively.
+ Does the PCB have an empty socket for a fourth chip in
+ position 1? We mirror the first chip by reloading in
+ the softlist, but should this really be open bus?
-------------------------------------------------*/
-void nes_bmc_110in1_device::write_h(offs_t offset, uint8_t data)
+void nes_bmc_76in1_device::write_h(offs_t offset, u8 data)
{
- uint8_t helper1 = (offset >> 12) ? 0 : 1;
- uint8_t helper2 = ((offset >> 8) & 0x40) | ((offset >> 6) & 0x3f);
+ LOG("bmc_76in1 write_h, offset: %04x, data: %02x\n", offset, data);
+ m_reg[offset & 0x01] = data;
- LOG_MMC(("bmc_110in1 write_h, offset: %04x, data: %02x\n", offset, data));
+ u8 bank = m_reg[1] << 6 | (m_reg[0] & 0x80) >> 2 | (m_reg[0] & 0x1f);
+ u8 mode = !BIT(m_reg[0], 5);
+ prg16_89ab(bank & ~mode);
+ prg16_cdef(bank | mode);
- set_nt_mirroring((offset & 0x2000) ? PPU_MIRROR_HORZ : PPU_MIRROR_VERT);
- prg16_89ab(helper1 & ~helper2);
- prg16_cdef(helper1 | helper2);
- chr8(((offset >> 8) & 0x40) | (offset & 0x3f), CHRROM);
+ set_nt_mirroring(BIT(m_reg[0], 6) ? PPU_MIRROR_VERT : PPU_MIRROR_HORZ);
}
-
/*-------------------------------------------------
BMC-150IN1
@@ -2233,93 +3054,41 @@ void nes_bmc_110in1_device::write_h(offs_t offset, uint8_t data)
iNES: mapper 202
- In MESS: Supported.
+ In MAME: Supported.
-------------------------------------------------*/
-void nes_bmc_150in1_device::write_h(offs_t offset, uint8_t data)
+void nes_bmc_150in1_device::write_h(offs_t offset, u8 data)
{
- int bank = (offset >> 1) & 0x07;
+ LOG("bmc_150in1 write_h, offset: %04x, data: %02x\n", offset, data);
- LOG_MMC(("bmc_150in1 write_h, offset: %04x, data: %02x\n", offset, data));
+ u8 bank = BIT(offset, 1, 3);
+ u8 mode = (bank & 0x06) == 0x06;
+ prg16_89ab(bank & ~mode);
+ prg16_cdef(bank | mode);
- prg16_89ab(bank);
- prg16_cdef(bank + (((bank & 0x06) == 0x06) ? 1 : 0));
chr8(bank, CHRROM);
-
- set_nt_mirroring(BIT(data, 0) ? PPU_MIRROR_HORZ: PPU_MIRROR_VERT);
-}
-
-
-/*-------------------------------------------------
-
- Board BMC-190IN1
-
- Games: 190-in-1
-
- In MESS: Supported
-
- -------------------------------------------------*/
-
-void nes_bmc_190in1_device::write_h(offs_t offset, uint8_t data)
-{
- LOG_MMC(("bmc190in1 write_h, offset: %04x, data: %02x\n", offset, data));
-
- set_nt_mirroring(BIT(data, 0) ? PPU_MIRROR_HORZ : PPU_MIRROR_VERT);
- offset >>= 2;
- prg16_89ab(offset);
- prg16_cdef(offset);
- chr8(offset, CHRROM);
+ set_nt_mirroring(BIT(offset, 0) ? PPU_MIRROR_HORZ: PPU_MIRROR_VERT);
}
/*-------------------------------------------------
- BMC-800IN1
+ BMC-500IN1
Unknown Bootleg Multigame Board
- Games:
-
- iNES: mapper
+ Games: 500 in 1, 2000 in 1 Unchained Melody, etc
- DSW not emulated yet.
+ iNES: mapper 217
- In MESS: Preliminary Supported.
+ In MAME: Supported.
-------------------------------------------------*/
-void nes_bmc_800in1_device::write_h(offs_t offset, uint8_t data)
-{
- LOG_MMC(("bmc800in1 write_h, offset: %04x, data: %02x\n", offset, data));
-
- if (offset < 0x4000)
- {
- set_nt_mirroring(BIT(offset, 5) ? PPU_MIRROR_HORZ: PPU_MIRROR_VERT);
-
- m_reg[0] = (m_reg[0]) | ((offset << 3) & 0x38);
- m_reg[1] = (m_reg[1]) | ((offset << 3) & 0x38);
- }
- else
- {
- switch (offset & 0x30)
- {
- case 0x00: m_mode = 0x0; m_reg[0] = (m_reg[0] & 0x38) | (offset & 0x7); m_reg[1] = m_reg[0] | 0x7; break;
- case 0x10: m_mode = 0x1; m_reg[0] = (m_reg[0] & 0x38) | (offset & 0x7); m_reg[1] = m_reg[0] | 0x7; break;
- case 0x20: m_mode = 0x0; m_reg[0] = (m_reg[0] & 0x38) | (offset & 0x6); m_reg[1] = m_reg[0] | 0x1; break;
- case 0x30: m_mode = 0x0; m_reg[0] = (m_reg[0] & 0x38) | (offset & 0x7); m_reg[1] = m_reg[0] | 0x0; break;
- }
- }
- prg16_89ab(m_reg[0]);
- prg16_cdef(m_reg[1]);
-}
-
-uint8_t nes_bmc_800in1_device::read_h(offs_t offset)
+void nes_bmc_500in1_device::write_h(offs_t offset, u8 data)
{
- LOG_MMC(("bmc800in1 read_h, offset: %04x\n", offset));
-
- if (m_mode)
- offset = (offset & 0x7ff0) | m_mode;
-
- return hi_access_rom(offset);
+ LOG("bmc500in1 write_h, offset: %04x, data: %02x\n", offset, data);
+ prg32(BIT(offset, 2, 3));
+ chr8(offset & 0x07, CHRROM);
}
/*-------------------------------------------------
@@ -2331,7 +3100,7 @@ uint8_t nes_bmc_800in1_device::read_h(offs_t offset)
iNES: mapper 227
- In MESS: Preliminary Supported.
+ In MAME: Preliminary Supported.
-------------------------------------------------*/
@@ -2348,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)
{
@@ -2376,227 +3145,396 @@ void nes_bmc_1200in1_device::write_h(offs_t offset, uint8_t data)
set_nt_mirroring(BIT(offset, 1) ? PPU_MIRROR_HORZ : PPU_MIRROR_VERT);
}
-
/*-------------------------------------------------
BMC-GOLDEN260IN1
Unknown Bootleg Multigame Board
- Games:
+ Games: Golden Game 150 in 1, Golden Game 210 in 1,
+ Golden Game 260 in 1, 1500 in 1
iNES: mapper 235
- In MESS: Preliminary Supported.
+ In MAME: Supported.
+
+ TODO: Return open bus when ROM sockets are empty?
-------------------------------------------------*/
-void nes_bmc_gold260_device::write_h(offs_t offset, uint8_t data)
+void nes_bmc_gold260_device::write_h(offs_t offset, u8 data)
{
- int bank = (offset & 0x1f) | ((offset & 0x0300) >> 3);
- 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);
- if (offset & 0x400)
- set_nt_mirroring(PPU_MIRROR_LOW);
- else
- set_nt_mirroring(BIT(offset, 13) ? PPU_MIRROR_HORZ : PPU_MIRROR_VERT);
+ u8 bank = bitswap<8>(offset, 9, 8, 4, 3, 2, 1, 0, 12);
+ u8 mode = !BIT(offset, 11);
+ prg16_89ab(bank & ~mode);
+ prg16_cdef(bank | mode);
- if (offset & 0x800)
- {
- bank = (bank << 1) | BIT(offset, 12);
- prg16_89ab(bank);
- prg16_cdef(bank);
- }
- else
- prg32(bank);
+ set_nt_mirroring(BIT(offset, 10) ? PPU_MIRROR_LOW : BIT(offset, 13) ? PPU_MIRROR_HORZ : PPU_MIRROR_VERT);
}
-
/*-------------------------------------------------
- BMC-GOLDEN150IN1
+ BMC-RESETBASED4IN1
Unknown Bootleg Multigame Board
- Games:
- iNES: mapper 235
+ Games: 4 in 1 (several of them)
- Same as the above + open bus in 0x8000-0xffff when
- enabled
+ iNES: mapper 60
+
+ No need to use handlers. At reset the banks change
+ and so does the game.
- In MESS: Preliminary Supported.
+ In MAME: Supported.
-------------------------------------------------*/
+/*-------------------------------------------------
-void nes_bmc_gold150_device::write_h(offs_t offset, uint8_t data)
-{
- int bank = (offset & 0x1f) | ((offset & 0x0200) >> 4);
- LOG_MMC(("bmc_gold150 write_h, offset: %04x, data: %02x\n", offset, data));
+ BMC-42IN1RESETBASED, BMC-NC-20MB
- m_latch = (offset & 0x0100);
+ Games: 42 (22 + 20) in 1, 20 in 1 (CA-006)
- if (offset & 0x400)
- set_nt_mirroring(PPU_MIRROR_LOW);
- else
- set_nt_mirroring(BIT(offset, 13) ? PPU_MIRROR_HORZ : PPU_MIRROR_VERT);
+ Here we implement two nearly identical mappers. The
+ NC-20MB board does not have the reset latch and its
+ mirroring bit is inverted from the 42 in 1.
- if (offset & 0x800)
- {
- bank = (bank << 1) | BIT(offset, 12);
- prg16_89ab(bank);
- prg16_cdef(bank);
- }
- else
- prg32(bank);
-}
+ There is an identical dump of the 42 in 1 identified
+ as SUPER22GAMES that supposedly selected between the
+ two menus via dip switch. It's not clear which, if
+ any, variants of this cart exist, nor if this is
+ really reset-based.
+
+ iNES: mapper 233
+ NES 2.0: mapper 433
-uint8_t nes_bmc_gold150_device::read_h(offs_t offset)
+ In MAME: Supported.
+
+ -------------------------------------------------*/
+
+void nes_bmc_42in1reset_device::write_h(offs_t offset, u8 data)
{
- LOG_MMC(("bmc_gold150 read_h, offset: %04x\n", offset));
+ LOG("bmc_42in1reset write_h, offset: %04x, data: %02x\n", offset, data);
- if (m_latch) // open bus
- return get_open_bus();
- else
- return hi_access_rom(offset);
-}
+ u8 bank = m_latch | (data & 0x1f);
+ u8 mode = !BIT(data, 5);
+ prg16_89ab(bank & ~mode);
+ prg16_cdef(bank | mode);
+ // some sources say there are 1-screen modes for 42-in-1, but this works as is
+ set_nt_mirroring(BIT(data, 6) ^ m_mirror_flip ? PPU_MIRROR_VERT : PPU_MIRROR_HORZ);
+}
/*-------------------------------------------------
- BMC-POWERFUL-255
+ BMC-LITTLECOM-160
Unknown Bootleg Multigame Board
- Games:
- iNES: mapper 63
+ Games: Little Com 160
+ NES 2.0: mapper 541
- In MESS: Preliminary Supported.
+ In MAME: Supported.
-------------------------------------------------*/
-void nes_bmc_ch001_device::write_h(offs_t offset, uint8_t data)
+void nes_bmc_lc160_device::write_h(offs_t offset, u8 data)
{
- int bank = ((offset >> 1) & 0x1fc);
- LOG_MMC(("bmc_ch001 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);
+ u8 mode = !BIT(offset, 1);
+ prg16_89ab(bank & ~mode);
+ prg16_cdef(bank | mode);
+ set_nt_mirroring(BIT(offset, 0) ? PPU_MIRROR_VERT : PPU_MIRROR_HORZ);
+ }
+}
- m_latch = ((offset & 0x300) == 0x300);
- set_nt_mirroring(BIT(offset, 0) ? PPU_MIRROR_HORZ : PPU_MIRROR_VERT);
+/*-------------------------------------------------
+
+ BMC-60311C
- if (offset & 2)
+ Games: 17 in 1
+
+ NES 2.0: mapper 289
+
+ In MAME: Preliminary supported.
+
+ TODO: All the Capcom games and Konami's Hyper Soccer
+ sound horrible here. BTANB? Also Journey to the West
+ doesn't work as an individual rom (jwest) or here.
+
+ -------------------------------------------------*/
+
+void nes_bmc_60311c_device::update_banks()
+{
+ if (BIT(m_reg[0], 1)) // UNROM mode
{
- prg8_89(bank + 0);
- prg8_ab(bank + 1);
- prg8_cd(bank + 2);
- prg8_ef(bank + 3);
+ prg16_89ab((m_reg[1] & ~0x07) | (BIT(m_reg[0], 0) ? 0x07 : m_reg[2]));
+ prg16_cdef(m_reg[1] | 0x07);
}
- else
+ else // NROM mode
{
- bank |= (offset & 4) >> 1;
- prg8_89(bank + 0);
- prg8_ab(bank + 1);
- prg8_cd(bank + 0);
- prg8_ef(bank + 1);
+ prg16_89ab(m_reg[1] & ~BIT(m_reg[0], 0));
+ prg16_cdef(m_reg[1] | BIT(m_reg[0], 0));
}
- if (offset & 0x800) // in this case, the last 8KB bank is switched differently...
- prg8_ef((offset & 0x07c ) | ((offset & 0x6) ? 0x3 : 0x1));
+ set_nt_mirroring(BIT(m_reg[0], 3) ? PPU_MIRROR_HORZ : PPU_MIRROR_VERT);
+ m_vram_protect = BIT(m_reg[0], 2);
}
-uint8_t nes_bmc_ch001_device::read_h(offs_t offset)
+void nes_bmc_60311c_device::write_m(offs_t offset, u8 data)
{
- LOG_MMC(("bmc_ch001 read_h, offset: %04x\n", offset));
+ LOG("bmc_60311c write_m, offset: %04x, data: %02x\n", offset, data);
+ m_reg[offset & 1] = data & 0x7f;
+ update_banks();
+}
- if (m_latch && offset < 0x4000) // open bus
- return get_open_bus();
- else
- return hi_access_rom(offset);
+void nes_bmc_60311c_device::write_h(offs_t offset, u8 data)
+{
+ LOG("bmc_60311c write_h, offset: %04x, data: %02x\n", offset, data);
+ m_reg[2] = data & 0x07;
+ update_banks();
}
/*-------------------------------------------------
- BMC-SUPER22GAMES
+ BMC-CTC-12IN1
- Unknown Bootleg Multigame Board
- Games:
+ Games: 12 in 1 Game Card
+
+ NES 2.0: mapper 337
+
+ In MAME: Supported.
+
+ -------------------------------------------------*/
- iNES:
+u8 nes_bmc_ctc12in1_device::read_m(offs_t 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("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);
+ switch (m_reg[0] >> 6)
+ {
+ case 0:
+ prg16_89ab(bank);
+ prg16_cdef(bank);
+ break;
+ case 1:
+ prg32(bank >> 1);
+ break;
+ case 2:
+ case 3:
+ prg16_89ab(bank);
+ prg16_cdef(bank | 0x07);
+ break;
+ }
+
+ m_vram_protect = !BIT(m_reg[0], 7) || (offset & 0x6000) == 0x6000;
+ set_nt_mirroring(BIT(m_reg[0], 5) ? PPU_MIRROR_HORZ : PPU_MIRROR_VERT);
+}
+
+/*-------------------------------------------------
- is there a dsw to access the higher banks above 0x20?
+ BMC-891227
- In MESS: Preliminary Supported.
+ Games: Super 15 in 1 Game Card
+
+ NES 2.0: mapper 350
+
+ This board is similar to CTC-12IN1 above but with
+ the mirroring and banking mode bits moved and with
+ support for Contra on a separate 128K chip.
+
+ In MAME: Supported.
+
+ TODO: Contra bugs: Without input character sprite
+ is always in the UP position. Cannot pickup weapons.
-------------------------------------------------*/
-void nes_bmc_super22_device::write_h(offs_t offset, uint8_t data)
+void nes_bmc_891227_device::write_h(offs_t offset, u8 data)
{
- LOG_MMC(("bmc_super22 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);
+
+ nes_bmc_ctc12in1_device::write_h(offset, data);
- if (data & 0x20)
+ if ((m_reg[0] & 0xc0) == 0xc0) // Contra only mode
{
- prg16_89ab(data & 0x1f);
- prg16_cdef(data & 0x1f);
+ prg16_89ab(0x20 | (m_reg[1] & 0x07));
+ prg16_cdef(0x27);
}
+}
+
+/*-------------------------------------------------
+
+ BMC-FAM250
+
+ Games: 250 in 1
+
+ This board is very close to the K-1029 board of the
+ famous Contra 100 and 168 multicarts. It sports an
+ extra mode to support a Bubble Bobble FDS bootleg.
+
+ NES 2.0: mapper 354
+
+ In MAME: Supported.
+
+ TODO: Circus Charlie's mirroring is incorrectly set
+ to horizontal. Is this a BTANB?
+
+ -------------------------------------------------*/
+
+u8 nes_bmc_fam250_device::read_m(offs_t 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)];
else
- prg32((data & 0x1f) >> 1);
+ return get_open_bus();
+}
+
+void nes_bmc_fam250_device::write_h(offs_t offset, u8 data)
+{
+ LOG("fam250 write_h, offset: %04x, data: %02x\n", offset, data);
- switch (data & 0xc0)
+ if (offset >= 0x7000)
{
- case 0x00: set_nt_mirroring(PPU_MIRROR_LOW); break;
- case 0x40: set_nt_mirroring(PPU_MIRROR_VERT); break;
- case 0x80: set_nt_mirroring(PPU_MIRROR_HORZ); break;
- case 0xc0: set_nt_mirroring(PPU_MIRROR_HIGH); break;
+ nes_bmc_k1029_device::write_h(offset, data);
+
+ m_latch = offset & 0x07;
+ m_reg = data;
+ if (m_latch == 5)
+ prg32((m_reg & 0x18) >> 1 | 0x03);
+
+ m_vram_protect = BIT(offset, 3);
}
}
-
/*-------------------------------------------------
- BMC-RESETBASED4IN1
-
- Unknown Bootleg Multigame Board
+ BMC-K-1029
- Games:
+ Games: 100 in 1 Contra Function 16, 168 in 1
- iNES:
+ iNES: mapper 15
- No need to use handlers. At reset the banks change
- and so does the game.
+ In MAME: Supported.
- In MESS: Preliminary Supported.
+ TODO: Contra games in 100-in-1 endlessly loop the
+ second level played regardless of starting level.
+ BTANB? Bad dump? FCEUX exhibits the same behavior.
-------------------------------------------------*/
+void nes_bmc_k1029_device::write_h(offs_t offset, u8 data)
+{
+ LOG("bmc_k1029 write_h, offset: %04x, data: %02x\n", offset, data);
+
+ u8 bank = data & 0x3f;
+ switch (offset & 3)
+ {
+ case 0:
+ prg32(bank >> 1);
+ break;
+ case 1:
+ prg16_89ab(bank);
+ prg16_cdef(bank | 0x07);
+ break;
+ case 2:
+ bank = bank << 1 | BIT(data, 7);
+ prg8_89(bank);
+ prg8_ab(bank);
+ prg8_cd(bank);
+ prg8_ef(bank);
+ break;
+ case 3:
+ prg16_89ab(bank);
+ prg16_cdef(bank);
+ break;
+ }
+
+ set_nt_mirroring(BIT(data, 6) ? PPU_MIRROR_HORZ : PPU_MIRROR_VERT);
+ m_vram_protect = BIT(offset, 0) == BIT(offset, 1);
+}
+
/*-------------------------------------------------
- BMC-42IN1RESETBASED
+ Bootleg Board N625092
- Unknown Bootleg Multigame Board
+ Games: 320 in 1, 400 in 1, 700 in 1, 800 in 1,
+ 1000 in 1, 2000 in 1, 5000000 in 1
- Games:
+ iNES: mapper 221
- iNES:
+ In MAME: Supported.
- In MESS: Preliminary Supported.
+ TODO: Several games have incorrect mirroring bits
+ on all carts they appear on. It's subtle so it's
+ likely a BTANB? Noticeable in Flappy, Pacman, and
+ Warpman title scrolls and at bottom of screen in
+ Zippy Race in-game.
-------------------------------------------------*/
-void nes_bmc_42in1reset_device::write_h(offs_t offset, uint8_t data)
+void nes_n625092_device::write_h(offs_t offset, u8 data)
{
- int bank;
- LOG_MMC(("bmc_42in1reset write_h, offset: %04x, data: %02x\n", offset, data));
+ LOG("n625092 write_h, offset: %04x, data: %02x\n", offset, data);
- m_reg[offset & 1] = data;
- bank = (m_reg[0] & 0x1f) | (m_latch << 5) | ((m_reg[1] & 1) << 6);
+ m_latch[BIT(offset, 14)] = offset;
- if (!(m_reg[0] & 0x20))
- prg32(bank >> 1);
- else
+ u8 bank = bitswap<4>(m_latch[0], 9, 7, 6, 5) << 3 | (m_latch[1] & 0x07);
+ u8 mode = BIT(m_latch[0], 1);
+ if (mode && BIT(m_latch[0], 8)) // UNROM mode
{
prg16_89ab(bank);
- prg16_cdef(bank);
+ prg16_cdef(bank | 7);
+ }
+ else // NROM mode
+ {
+ prg16_89ab(bank & ~mode);
+ prg16_cdef(bank | mode);
}
- set_nt_mirroring(BIT(offset, 6) ? PPU_MIRROR_HORZ : PPU_MIRROR_VERT);
+ set_nt_mirroring(BIT(m_latch[0], 0) ? PPU_MIRROR_HORZ : PPU_MIRROR_VERT);
+ m_vram_protect = BIT(m_latch[1], 3);
+}
+
+/*-------------------------------------------------
+
+ BMC-TH2291-3, BMC-CH-011, BMC-82AB
+ Games: Powerful 250 in 1, Powerful 255 in 1, 82 in 1
+
+ iNES: mapper 63
+
+ In MAME: Supported.
+
+ -------------------------------------------------*/
+
+void nes_bmc_th22913_device::write_h(offs_t offset, u8 data)
+{
+ LOG("bmc_th22913 write_h, offset: %04x, data: %02x\n", offset, data);
+
+ u8 bank = offset >> 2;
+ u8 mode = BIT(offset, 1);
+ prg16_89ab(bank & ~mode);
+ prg16_cdef(bank | mode);
+
+ set_nt_mirroring(BIT(offset, 0) ? PPU_MIRROR_HORZ : PPU_MIRROR_VERT);
+ m_vram_protect = BIT(offset, m_vram_prot_bit);
}
diff --git a/src/devices/bus/nes/multigame.h b/src/devices/bus/nes/multigame.h
index 51db3e9f821..f7cf1508458 100644
--- a/src/devices/bus/nes/multigame.h
+++ b/src/devices/bus/nes/multigame.h
@@ -14,37 +14,53 @@ class nes_action52_device : public nes_nrom_device
{
public:
// construction/destruction
- nes_action52_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
+ nes_action52_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock);
- virtual void write_h(offs_t offset, uint8_t data) override;
+ virtual void write_h(offs_t offset, u8 data) override;
+};
+
+
+// ======================> nes_caltron6in1_device
+
+class nes_caltron6in1_device : public nes_nrom_device
+{
+public:
+ // construction/destruction
+ nes_caltron6in1_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock);
+
+ virtual void write_m(offs_t offset, u8 data) override;
+ virtual void write_h(offs_t offset, u8 data) override;
virtual void pcb_reset() override;
protected:
// device-level overrides
- virtual void device_start() override;
+ virtual void device_start() override ATTR_COLD;
+
+private:
+ void update_chr();
+ u8 m_latch, m_reg;
};
-// ======================> nes_caltron_device
+// ======================> nes_caltron9in1_device
-class nes_caltron_device : public nes_nrom_device
+class nes_caltron9in1_device : public nes_nrom_device
{
public:
// construction/destruction
- nes_caltron_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
+ nes_caltron9in1_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock);
- virtual void write_m(offs_t offset, uint8_t data) override;
- virtual void write_h(offs_t offset, uint8_t data) override;
+ virtual void write_h(offs_t offset, u8 data) override;
virtual void pcb_reset() override;
protected:
// device-level overrides
- virtual void device_start() override;
+ virtual void device_start() override ATTR_COLD;
private:
- uint8_t m_latch;
+ u8 m_latch[3];
};
@@ -63,7 +79,7 @@ public:
protected:
// device-level overrides
- virtual void device_start() override;
+ virtual void device_start() override ATTR_COLD;
private:
uint8_t m_prg, m_chr;
@@ -76,43 +92,63 @@ class nes_svision16_device : public nes_nrom_device
{
public:
// construction/destruction
- nes_svision16_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
+ nes_svision16_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock);
- virtual uint8_t read_m(offs_t offset) override;
- virtual void write_m(offs_t offset, uint8_t data) override;
- virtual void write_h(offs_t offset, uint8_t data) override;
+ virtual u8 read_m(offs_t offset) override;
+ virtual void write_m(offs_t offset, u8 data) override;
+ virtual void write_h(offs_t offset, u8 data) override;
virtual void pcb_reset() override;
protected:
// device-level overrides
- virtual void device_start() override;
+ virtual void device_start() override ATTR_COLD;
private:
void update_prg();
- uint8_t m_latch1, m_latch2;
+ u8 m_latch1, m_latch2;
};
-// ======================> nes_n625092_device
+// ======================> nes_farid_unrom_device
-class nes_n625092_device : public nes_nrom_device
+class nes_farid_unrom_device : public nes_nrom_device
{
public:
// construction/destruction
- nes_n625092_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
+ nes_farid_unrom_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock);
- virtual void write_h(offs_t offset, uint8_t data) override;
+ virtual void write_h(offs_t offset, u8 data) override;
virtual void pcb_reset() override;
protected:
// device-level overrides
- virtual void device_start() override;
+ virtual void device_start() override ATTR_COLD;
private:
- void set_prg(uint8_t reg1, uint8_t reg2);
- uint8_t m_latch1, m_latch2;
+ u8 m_reg;
+};
+
+
+// ======================> nes_kn42_device
+
+class nes_kn42_device : public nes_nrom_device
+{
+public:
+ // construction/destruction
+ nes_kn42_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock);
+
+ virtual void write_h(offs_t offset, u8 data) override;
+
+ virtual void pcb_reset() override;
+
+protected:
+ // device-level overrides
+ virtual void device_start() override ATTR_COLD;
+
+private:
+ u8 m_latch;
};
@@ -127,10 +163,6 @@ public:
virtual void write_h(offs_t offset, uint8_t data) override;
virtual void pcb_reset() override;
-
-protected:
- // device-level overrides
- virtual void device_start() override;
};
@@ -140,64 +172,91 @@ class nes_t262_device : public nes_nrom_device
{
public:
// construction/destruction
- nes_t262_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
+ nes_t262_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock);
- virtual void write_h(offs_t offset, uint8_t data) override;
+ virtual void write_h(offs_t offset, u8 data) override;
virtual void pcb_reset() override;
protected:
// device-level overrides
- virtual void device_start() override;
+ virtual void device_start() override ATTR_COLD;
private:
- uint8_t m_latch1, m_latch2;
+ u16 m_latch;
};
-// ======================> nes_novel1_device
+// ======================> nes_studyngame_device
-class nes_novel1_device : public nes_nrom_device
+class nes_studyngame_device : public nes_nrom_device
{
public:
// construction/destruction
- nes_novel1_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
+ nes_studyngame_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
virtual void write_h(offs_t offset, uint8_t data) override;
+};
+
+
+// ======================> nes_sgun20in1_device
+
+class nes_sgun20in1_device : public nes_nrom_device
+{
+public:
+ // construction/destruction
+ nes_sgun20in1_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock);
+
+ virtual void write_h(offs_t offset, u8 data) override;
virtual void pcb_reset() override;
protected:
- // device-level overrides
- virtual void device_start() override;
+ nes_sgun20in1_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, u32 clock);
};
-// ======================> nes_novel2_device
+// ======================> nes_bmc_190in1_device
-class nes_novel2_device : public nes_nrom_device
+class nes_bmc_190in1_device : public nes_sgun20in1_device
{
public:
// construction/destruction
- nes_novel2_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
+ nes_bmc_190in1_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock);
- virtual void write_h(offs_t offset, uint8_t data) override;
+ virtual void write_h(offs_t offset, u8 data) override;
+};
+
+
+// ======================> nes_vt5201_device
+
+class nes_vt5201_device : public nes_nrom_device
+{
+public:
+ // construction/destruction
+ nes_vt5201_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock);
+
+ virtual u8 read_h(offs_t offset) override;
+ virtual void write_h(offs_t offset, u8 data) override;
virtual void pcb_reset() override;
protected:
// device-level overrides
- virtual void device_start() override;
+ virtual void device_start() override ATTR_COLD;
+
+private:
+ u8 m_latch, m_jumper;
};
-// ======================> nes_studyngame_device
+// ======================> nes_bmc_80013b_device
-class nes_studyngame_device : public nes_nrom_device
+class nes_bmc_80013b_device : public nes_nrom_device
{
public:
// construction/destruction
- nes_studyngame_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
+ nes_bmc_80013b_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock);
virtual void write_h(offs_t offset, uint8_t data) override;
@@ -205,129 +264,180 @@ public:
protected:
// device-level overrides
- virtual void device_start() override;
+ virtual void device_start() override ATTR_COLD;
+
+private:
+ void update_prg();
+ u8 m_latch, m_reg[2];
};
-// ======================> nes_sgun20in1_device
+// ======================> nes_bmc_810544c_device
-class nes_sgun20in1_device : public nes_nrom_device
+class nes_bmc_810544c_device : public nes_nrom_device
{
public:
// construction/destruction
- nes_sgun20in1_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
+ nes_bmc_810544c_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock);
+
+ virtual void write_h(offs_t offset, u8 data) override;
+
+ virtual void pcb_reset() override;
+};
- virtual void write_h(offs_t offset, uint8_t data) override;
+
+// ======================> nes_bmc_830425c_device
+
+class nes_bmc_830425c_device : public nes_nrom_device
+{
+public:
+ // construction/destruction
+ nes_bmc_830425c_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock);
+
+ virtual void write_h(offs_t offset, u8 data) override;
virtual void pcb_reset() override;
protected:
// device-level overrides
- virtual void device_start() override;
+ virtual void device_start() override ATTR_COLD;
+
+private:
+ u8 m_latch;
};
-// ======================> nes_vt5201_device
+// ======================> nes_bmc_830928c_device
-class nes_vt5201_device : public nes_nrom_device
+class nes_bmc_830928c_device : public nes_nrom_device
{
public:
// construction/destruction
- nes_vt5201_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
+ nes_bmc_830928c_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock);
- virtual uint8_t read_h(offs_t offset) override;
- virtual void write_h(offs_t offset, uint8_t data) override;
+ virtual void write_h(offs_t offset, u8 data) override;
virtual void pcb_reset() override;
protected:
// device-level overrides
- virtual void device_start() override;
+ virtual void device_start() override ATTR_COLD;
private:
- uint8_t m_latch, m_dipsetting;
+ u8 m_latch;
};
-// ======================> nes_810544c_device
+// ======================> nes_bmc_850437c_device
-class nes_810544c_device : public nes_nrom_device
+class nes_bmc_850437c_device : public nes_nrom_device
{
public:
// construction/destruction
- nes_810544c_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
+ nes_bmc_850437c_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock);
- virtual void write_h(offs_t offset, uint8_t data) override;
+ virtual void write_h(offs_t offset, u8 data) override;
virtual void pcb_reset() override;
protected:
// device-level overrides
- virtual void device_start() override;
+ virtual void device_start() override ATTR_COLD;
+
+private:
+ u8 m_reg[2];
};
-// ======================> nes_ntd03_device
+// ======================> nes_bmc_970630c_device
-class nes_ntd03_device : public nes_nrom_device
+class nes_bmc_970630c_device : public nes_nrom_device
{
public:
// construction/destruction
- nes_ntd03_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
+ nes_bmc_970630c_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock);
- virtual void write_h(offs_t offset, uint8_t data) override;
+ virtual u8 read_h(offs_t offset) override;
+ virtual void write_h(offs_t offset, u8 data) override;
virtual void pcb_reset() override;
protected:
// device-level overrides
- virtual void device_start() override;
+ virtual void device_start() override ATTR_COLD;
+
+private:
+ u8 m_latch;
+};
+
+
+// ======================> nes_ntd03_device
+
+class nes_ntd03_device : public nes_nrom_device
+{
+public:
+ // construction/destruction
+ nes_ntd03_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock);
+
+ virtual void write_h(offs_t offset, u8 data) override;
};
-// ======================> nes_bmc_gb63_device
+// ======================> nes_bmc_ctc09_device
-class nes_bmc_gb63_device : public nes_nrom_device
+class nes_bmc_ctc09_device : public nes_nrom_device
{
public:
// construction/destruction
- nes_bmc_gb63_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
+ nes_bmc_ctc09_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock);
+
+ virtual void write_h(offs_t offset, u8 data) override;
+
+ virtual void pcb_reset() override;
+};
- virtual uint8_t read_h(offs_t offset) override;
- virtual void write_h(offs_t offset, uint8_t data) override;
- virtual void chr_w(offs_t offset, uint8_t data) override;
+
+// ======================> nes_bmc_ds927_device
+
+class nes_bmc_ds927_device : public nes_nrom_device
+{
+public:
+ // construction/destruction
+ nes_bmc_ds927_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock);
+
+ virtual u8 read_h(offs_t offset) override;
+ virtual void write_h(offs_t offset, u8 data) override;
virtual void pcb_reset() override;
protected:
// device-level overrides
- virtual void device_start() override;
+ virtual void device_start() override ATTR_COLD;
private:
- void update_banks();
- uint8_t m_latch, m_dipsetting;
- uint8_t m_reg[2];
- int m_vram_disable;
+ u8 m_latch, m_mode;
};
+
// ======================> nes_bmc_gka_device
class nes_bmc_gka_device : public nes_nrom_device
{
public:
// construction/destruction
- nes_bmc_gka_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
+ nes_bmc_gka_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock);
- virtual void write_h(offs_t offset, uint8_t data) override;
+ virtual u8 read_m(offs_t offset) override;
+ virtual void write_h(offs_t offset, u8 data) override;
virtual void pcb_reset() override;
protected:
// device-level overrides
- virtual void device_start() override;
+ virtual void device_start() override ATTR_COLD;
private:
- uint8_t m_latch1, m_latch2;
+ u8 m_reg[2];
};
@@ -337,15 +447,192 @@ class nes_bmc_gkb_device : public nes_nrom_device
{
public:
// construction/destruction
- nes_bmc_gkb_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
+ nes_bmc_gkb_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock);
+
+ virtual void write_h(offs_t offset, u8 data) override;
+};
- virtual void write_h(offs_t offset, uint8_t data) override;
+
+// ======================> nes_bmc_gkcxin1_device
+
+class nes_bmc_gkcxin1_device : public nes_nrom_device
+{
+public:
+ // construction/destruction
+ nes_bmc_gkcxin1_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock);
+
+ virtual void write_h(offs_t offset, u8 data) override;
+};
+
+
+// ======================> nes_bmc_gn91b_device
+
+class nes_bmc_gn91b_device : public nes_nrom_device
+{
+public:
+ // construction/destruction
+ nes_bmc_gn91b_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock);
+
+ virtual void write_h(offs_t offset, u8 data) override;
virtual void pcb_reset() override;
protected:
// device-level overrides
- virtual void device_start() override;
+ virtual void device_start() override ATTR_COLD;
+
+private:
+ u8 m_latch;
+};
+
+
+// ======================> nes_bmc_hp898f_device
+
+class nes_bmc_hp898f_device : public nes_nrom_device
+{
+public:
+ // construction/destruction
+ nes_bmc_hp898f_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock);
+
+ virtual u8 read_l(offs_t offset) override;
+ virtual void write_m(offs_t offset, u8 data) override;
+};
+
+
+// ======================> nes_bmc_k3036_device
+
+class nes_bmc_k3036_device : public nes_nrom_device
+{
+public:
+ // construction/destruction
+ nes_bmc_k3036_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock);
+
+ virtual void write_h(offs_t offset, u8 data) override;
+
+ virtual void pcb_reset() override;
+};
+
+
+// ======================> nes_bmc_k3046_device
+
+class nes_bmc_k3046_device : public nes_nrom_device
+{
+public:
+ // construction/destruction
+ nes_bmc_k3046_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock);
+
+ virtual void write_h(offs_t offset, u8 data) override;
+
+ virtual void pcb_reset() override;
+};
+
+
+// ======================> nes_bmc_k3071_device
+
+class nes_bmc_k3071_device : public nes_nrom_device
+{
+public:
+ // construction/destruction
+ nes_bmc_k3071_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock);
+
+ virtual void write_h(offs_t offset, u8 data) override;
+
+ virtual void pcb_reset() override;
+};
+
+
+// ======================> nes_bmc_s009_device
+
+class nes_bmc_s009_device : public nes_nrom_device
+{
+public:
+ // construction/destruction
+ nes_bmc_s009_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock);
+
+ virtual void write_m(offs_t offset, u8 data) override;
+ virtual void write_h(offs_t offset, u8 data) override;
+
+ virtual void pcb_reset() override;
+
+protected:
+ // device-level overrides
+ virtual void device_start() override ATTR_COLD;
+
+private:
+ u8 m_reg;
+};
+
+
+// ======================> nes_bmc_sa005a_device
+
+class nes_bmc_sa005a_device : public nes_nrom_device
+{
+public:
+ // construction/destruction
+ nes_bmc_sa005a_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock);
+
+ virtual void write_h(offs_t offset, u8 data) override;
+
+ virtual void pcb_reset() override;
+};
+
+
+// ======================> nes_bmc_tf2740_device
+
+class nes_bmc_tf2740_device : public nes_nrom_device
+{
+public:
+ // construction/destruction
+ nes_bmc_tf2740_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock);
+
+ virtual u8 read_m(offs_t offset) override;
+ virtual void write_m(offs_t offset, u8 data) override;
+ virtual void write_h(offs_t offset, u8 data) override;
+
+ virtual void pcb_reset() override;
+
+protected:
+ // device-level overrides
+ virtual void device_start() override ATTR_COLD;
+
+private:
+ void update_chr();
+ u8 m_reg[3];
+ u8 m_jumper;
+};
+
+
+// ======================> nes_bmc_th2348_device
+
+class nes_bmc_th2348_device : public nes_nrom_device
+{
+public:
+ // construction/destruction
+ nes_bmc_th2348_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock);
+
+ virtual void write_l(offs_t offset, u8 data) override;
+ virtual void write_h(offs_t offset, u8 data) override;
+
+ virtual void pcb_reset() override;
+
+protected:
+ // device-level overrides
+ virtual void device_start() override ATTR_COLD;
+
+private:
+ u8 m_latch;
+};
+
+
+// ======================> nes_bmc_tj03_device
+
+class nes_bmc_tj03_device : public nes_nrom_device
+{
+public:
+ // construction/destruction
+ nes_bmc_tj03_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock);
+
+ virtual void write_h(offs_t offset, u8 data) override;
};
@@ -363,7 +650,7 @@ public:
protected:
// device-level overrides
- virtual void device_start() override;
+ virtual void device_start() override ATTR_COLD;
private:
uint8_t m_latch;
@@ -376,15 +663,9 @@ class nes_bmc_11160_device : public nes_nrom_device
{
public:
// construction/destruction
- nes_bmc_11160_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
-
- virtual void write_h(offs_t offset, uint8_t data) override;
+ nes_bmc_11160_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock);
- virtual void pcb_reset() override;
-
-protected:
- // device-level overrides
- virtual void device_start() override;
+ virtual void write_h(offs_t offset, u8 data) override;
};
@@ -394,15 +675,24 @@ class nes_bmc_g146_device : public nes_nrom_device
{
public:
// construction/destruction
- nes_bmc_g146_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
+ nes_bmc_g146_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock);
- virtual void write_h(offs_t offset, uint8_t data) override;
+ virtual void write_h(offs_t offset, u8 data) override;
+};
- virtual void pcb_reset() override;
-protected:
- // device-level overrides
- virtual void device_start() override;
+// ======================> nes_bmc_2751_device
+
+class nes_bmc_2751_device : public nes_nrom_device
+{
+public:
+ // construction/destruction
+ nes_bmc_2751_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock);
+
+ virtual void write_h(offs_t offset, u8 data) override;
+
+ virtual void pcb_reset() override;
+ virtual void pcb_start(running_machine &machine, u8 *ciram_ptr, bool cart_mounted) override;
};
@@ -412,16 +702,21 @@ class nes_bmc_8157_device : public nes_nrom_device
{
public:
// construction/destruction
- nes_bmc_8157_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
+ nes_bmc_8157_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock);
- virtual uint8_t read_h(offs_t offset) override;
- virtual void write_h(offs_t offset, uint8_t data) override;
+ virtual u8 read_h(offs_t offset) override;
+ virtual void write_h(offs_t offset, u8 data) override;
virtual void pcb_reset() override;
protected:
// device-level overrides
- virtual void device_start() override;
+ virtual ioport_constructor device_input_ports() const override ATTR_COLD;
+ virtual void device_start() override ATTR_COLD;
+
+private:
+ required_ioport m_jumper;
+ u8 m_latch;
};
@@ -431,15 +726,12 @@ class nes_bmc_hik300_device : public nes_nrom_device
{
public:
// construction/destruction
- nes_bmc_hik300_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
+ nes_bmc_hik300_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock);
- virtual void write_h(offs_t offset, uint8_t data) override;
+ virtual u8 read_m(offs_t offset) override;
+ virtual void write_h(offs_t offset, u8 data) override;
virtual void pcb_reset() override;
-
-protected:
- // device-level overrides
- virtual void device_start() override;
};
@@ -449,15 +741,9 @@ class nes_bmc_s700_device : public nes_nrom_device
{
public:
// construction/destruction
- nes_bmc_s700_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
-
- virtual void write_h(offs_t offset, uint8_t data) override;
+ nes_bmc_s700_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock);
- virtual void pcb_reset() override;
-
-protected:
- // device-level overrides
- virtual void device_start() override;
+ virtual void write_h(offs_t offset, u8 data) override;
};
@@ -467,20 +753,21 @@ class nes_bmc_ball11_device : public nes_nrom_device
{
public:
// construction/destruction
- nes_bmc_ball11_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
+ nes_bmc_ball11_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock);
- virtual void write_m(offs_t offset, uint8_t data) override;
- virtual void write_h(offs_t offset, uint8_t data) override;
+ virtual u8 read_m(offs_t offset) override;
+ virtual void write_m(offs_t offset, u8 data) override;
+ virtual void write_h(offs_t offset, u8 data) override;
virtual void pcb_reset() override;
protected:
// device-level overrides
- virtual void device_start() override;
+ virtual void device_start() override ATTR_COLD;
private:
- void set_banks();
- uint8_t m_reg[2];
+ void update_prg();
+ u8 m_reg[2];
};
@@ -490,15 +777,18 @@ class nes_bmc_22games_device : public nes_nrom_device
{
public:
// construction/destruction
- nes_bmc_22games_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
+ nes_bmc_22games_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock);
- virtual void write_h(offs_t offset, uint8_t data) override;
+ virtual void write_h(offs_t offset, u8 data) override;
virtual void pcb_reset() override;
protected:
// device-level overrides
- virtual void device_start() override;
+ virtual void device_start() override ATTR_COLD;
+
+private:
+ int m_latch, m_reset;
};
@@ -508,78 +798,89 @@ class nes_bmc_64y2k_device : public nes_nrom_device
{
public:
// construction/destruction
- nes_bmc_64y2k_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
+ nes_bmc_64y2k_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock);
- virtual void write_l(offs_t offset, uint8_t data) override;
- virtual void write_h(offs_t offset, uint8_t data) override;
+ virtual void write_l(offs_t offset, u8 data) override;
+ virtual void write_h(offs_t offset, u8 data) override;
virtual void pcb_reset() override;
protected:
// device-level overrides
- virtual void device_start() override;
+ virtual void device_start() override ATTR_COLD;
private:
- void set_prg();
- uint8_t m_reg[4];
+ void update_banks();
+ u8 m_reg[4];
+ u8 m_reg_mask;
};
-// ======================> nes_bmc_12in1_device
+// ======================> nes_bmc_420y2k_device
-class nes_bmc_12in1_device : public nes_nrom_device
+class nes_bmc_420y2k_device : public nes_nrom_device
{
public:
// construction/destruction
- nes_bmc_12in1_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
+ nes_bmc_420y2k_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock);
- virtual void write_h(offs_t offset, uint8_t data) override;
+ virtual u8 read_h(offs_t offset) override;
+ virtual void write_h(offs_t offset, u8 data) override;
virtual void pcb_reset() override;
protected:
// device-level overrides
- virtual void device_start() override;
+ virtual void device_start() override ATTR_COLD;
private:
- void update_banks();
- uint8_t m_reg[3];
+ u8 m_latch, m_reg;
};
-// ======================> nes_bmc_20in1_device
+// ======================> nes_bmc_12in1_device
-class nes_bmc_20in1_device : public nes_nrom_device
+class nes_bmc_12in1_device : public nes_nrom_device
{
public:
// construction/destruction
- nes_bmc_20in1_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
+ nes_bmc_12in1_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock);
- virtual void write_h(offs_t offset, uint8_t data) override;
+ virtual void write_h(offs_t offset, u8 data) override;
virtual void pcb_reset() override;
protected:
// device-level overrides
- virtual void device_start() override;
+ virtual void device_start() override ATTR_COLD;
+
+private:
+ void update_banks();
+ u8 m_reg[4];
};
-// ======================> nes_bmc_21in1_device
+// ======================> nes_bmc_20in1_device
-class nes_bmc_21in1_device : public nes_nrom_device
+class nes_bmc_20in1_device : public nes_nrom_device
{
public:
// construction/destruction
- nes_bmc_21in1_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
+ nes_bmc_20in1_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock);
- virtual void write_h(offs_t offset, uint8_t data) override;
+ virtual void write_h(offs_t offset, u8 data) override;
+};
- virtual void pcb_reset() override;
-protected:
- // device-level overrides
- virtual void device_start() override;
+// ======================> nes_bmc_21in1_device
+
+class nes_bmc_21in1_device : public nes_nrom_device
+{
+public:
+ // construction/destruction
+ nes_bmc_21in1_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock);
+
+ virtual void write_h(offs_t offset, u8 data) override;
};
@@ -589,15 +890,9 @@ class nes_bmc_31in1_device : public nes_nrom_device
{
public:
// construction/destruction
- nes_bmc_31in1_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
-
- virtual void write_h(offs_t offset, uint8_t data) override;
+ nes_bmc_31in1_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock);
- virtual void pcb_reset() override;
-
-protected:
- // device-level overrides
- virtual void device_start() override;
+ virtual void write_h(offs_t offset, u8 data) override;
};
@@ -612,10 +907,6 @@ public:
virtual void write_h(offs_t offset, uint8_t data) override;
virtual void pcb_reset() override;
-
-protected:
- // device-level overrides
- virtual void device_start() override;
};
@@ -630,10 +921,6 @@ public:
virtual void write_h(offs_t offset, uint8_t data) override;
virtual void pcb_reset() override;
-
-protected:
- // device-level overrides
- virtual void device_start() override;
};
@@ -648,10 +935,6 @@ public:
virtual void write_h(offs_t offset, uint8_t data) override;
virtual void pcb_reset() override;
-
-protected:
- // device-level overrides
- virtual void device_start() override;
};
@@ -661,20 +944,40 @@ class nes_bmc_70in1_device : public nes_nrom_device
{
public:
// construction/destruction
- nes_bmc_70in1_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
+ nes_bmc_70in1_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock);
- virtual uint8_t read_h(offs_t offset) override;
- virtual void write_h(offs_t offset, uint8_t data) override;
+ virtual u8 read_h(offs_t offset) override;
+ virtual void write_h(offs_t offset, u8 data) override;
virtual void pcb_reset() override;
protected:
+ // construction/destruction
+ nes_bmc_70in1_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_start() override ATTR_COLD;
+
+ virtual void update_banks();
+ void update_prg(u8 bank);
+
+ u8 m_latch[2];
private:
- uint8_t m_mode;
- uint8_t m_reg[2];
+ u8 m_jumper;
+};
+
+
+// ======================> nes_bmc_800in1_device
+
+class nes_bmc_800in1_device : public nes_bmc_70in1_device
+{
+public:
+ // construction/destruction
+ nes_bmc_800in1_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock);
+
+protected:
+ virtual void update_banks() override;
};
@@ -684,15 +987,20 @@ class nes_bmc_72in1_device : public nes_nrom_device
{
public:
// construction/destruction
- nes_bmc_72in1_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
+ nes_bmc_72in1_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock);
- virtual void write_h(offs_t offset, uint8_t data) override;
+ virtual u8 read_l(offs_t offset) override;
+ virtual void write_l(offs_t offset, u8 data) override;
+ virtual void write_h(offs_t offset, u8 data) override;
- virtual void pcb_reset() override;
+// virtual void pcb_reset() override;
protected:
// device-level overrides
- virtual void device_start() override;
+ virtual void device_start() override ATTR_COLD;
+
+private:
+ u8 m_extra_ram[4];
};
@@ -702,267 +1010,368 @@ class nes_bmc_76in1_device : public nes_nrom_device
{
public:
// construction/destruction
- nes_bmc_76in1_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
+ nes_bmc_76in1_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock);
- virtual void write_h(offs_t offset, uint8_t data) override;
+ virtual void write_h(offs_t offset, u8 data) override;
virtual void pcb_reset() override;
protected:
// device-level overrides
- virtual void device_start() override;
+ virtual void device_start() override ATTR_COLD;
private:
- uint8_t m_latch1, m_latch2;
+ u8 m_reg[2];
};
-// ======================> nes_bmc_110in1_device
+// ======================> nes_bmc_150in1_device
-class nes_bmc_110in1_device : public nes_nrom_device
+class nes_bmc_150in1_device : public nes_nrom_device
{
public:
// construction/destruction
- nes_bmc_110in1_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
+ nes_bmc_150in1_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock);
- virtual void write_h(offs_t offset, uint8_t data) override;
+ virtual void write_h(offs_t offset, u8 data) override;
virtual void pcb_reset() override;
+};
-protected:
- // device-level overrides
- virtual void device_start() override;
+
+// ======================> nes_bmc_500in1_device
+
+class nes_bmc_500in1_device : public nes_nrom_device
+{
+public:
+ // construction/destruction
+ nes_bmc_500in1_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock);
+
+ virtual void write_h(offs_t offset, u8 data) override;
};
-// ======================> nes_bmc_150in1_device
+// ======================> nes_bmc_1200in1_device
-class nes_bmc_150in1_device : public nes_nrom_device
+class nes_bmc_1200in1_device : public nes_nrom_device
{
public:
// construction/destruction
- nes_bmc_150in1_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
+ nes_bmc_1200in1_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
virtual void write_h(offs_t offset, uint8_t data) override;
+ virtual void chr_w(offs_t offset, uint8_t data) override;
virtual void pcb_reset() override;
protected:
// device-level overrides
- virtual void device_start() override;
+ virtual void device_start() override ATTR_COLD;
+
+private:
+ uint8_t m_vram_protect;
};
-// ======================> nes_bmc_190in1_device
+// ======================> nes_bmc_gold260_device
-class nes_bmc_190in1_device : public nes_nrom_device
+class nes_bmc_gold260_device : public nes_nrom_device
{
public:
// construction/destruction
- nes_bmc_190in1_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
+ nes_bmc_gold260_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock);
- virtual void write_h(offs_t offset, uint8_t data) override;
+ virtual void write_h(offs_t offset, u8 data) override;
+};
+
+
+// ======================> nes_bmc_4in1reset_device
+
+class nes_bmc_4in1reset_device : public nes_nrom_device
+{
+public:
+ // construction/destruction
+ nes_bmc_4in1reset_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock);
virtual void pcb_reset() override;
protected:
// device-level overrides
- virtual void device_start() override;
+ virtual void device_start() override ATTR_COLD;
+
+private:
+ u8 m_latch;
};
-// ======================> nes_bmc_800in1_device
+// ======================> nes_bmc_42in1reset_device
-class nes_bmc_800in1_device : public nes_nrom_device
+class nes_bmc_42in1reset_device : public nes_nrom_device
{
public:
// construction/destruction
- nes_bmc_800in1_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
+ nes_bmc_42in1reset_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock);
- virtual uint8_t read_h(offs_t offset) override;
- virtual void write_h(offs_t offset, uint8_t data) override;
+ virtual void write_h(offs_t offset, u8 data) override;
virtual void pcb_reset() override;
protected:
+ // construction/destruction
+ nes_bmc_42in1reset_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, u32 clock, u8 mirror_flip);
+
// device-level overrides
- virtual void device_start() override;
+ virtual void device_start() override ATTR_COLD;
private:
- uint8_t m_mode;
- uint8_t m_reg[2];
+ u8 m_latch;
+ const u8 m_mirror_flip;
};
-// ======================> nes_bmc_1200in1_device
+// ======================> nes_bmc_nc20mb_device
-class nes_bmc_1200in1_device : public nes_nrom_device
+class nes_bmc_nc20mb_device : public nes_bmc_42in1reset_device
{
public:
// construction/destruction
- nes_bmc_1200in1_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
+ nes_bmc_nc20mb_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock);
+};
- virtual void write_h(offs_t offset, uint8_t data) override;
- virtual void chr_w(offs_t offset, uint8_t data) override;
+
+// ======================> nes_bmc_lc160_device
+
+class nes_bmc_lc160_device : public nes_nrom_device
+{
+public:
+ // construction/destruction
+ nes_bmc_lc160_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock);
+
+ virtual void write_h(offs_t offset, u8 data) override;
+};
+
+
+// ======================> nes_vram_protect_device
+
+class nes_vram_protect_device : public nes_nrom_device
+{
+public:
+ virtual void chr_w(offs_t offset, u8 data) override { if (!m_vram_protect) device_nes_cart_interface::chr_w(offset, data); }
virtual void pcb_reset() override;
protected:
+ // construction/destruction
+ nes_vram_protect_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_start() override ATTR_COLD;
-private:
- uint8_t m_vram_protect;
+ bool m_vram_protect;
};
-// ======================> nes_bmc_gold150_device
+// ======================> nes_bmc_60311c_device
-class nes_bmc_gold150_device : public nes_nrom_device
+class nes_bmc_60311c_device : public nes_vram_protect_device
{
public:
// construction/destruction
- nes_bmc_gold150_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
+ nes_bmc_60311c_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock);
- virtual uint8_t read_h(offs_t offset) override;
- virtual void write_h(offs_t offset, uint8_t data) override;
+ virtual void write_m(offs_t offset, u8 data) override;
+ virtual void write_h(offs_t offset, u8 data) override;
virtual void pcb_reset() override;
protected:
// device-level overrides
- virtual void device_start() override;
+ virtual void device_start() override ATTR_COLD;
private:
- uint8_t m_latch;
+ void update_banks();
+ u8 m_reg[3];
};
-// ======================> nes_bmc_gold260_device
+// ======================> nes_bmc_ctc12in1_device
-class nes_bmc_gold260_device : public nes_nrom_device
+class nes_bmc_ctc12in1_device : public nes_vram_protect_device
{
public:
// construction/destruction
- nes_bmc_gold260_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
+ nes_bmc_ctc12in1_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock);
- virtual void write_h(offs_t offset, uint8_t data) override;
+ virtual u8 read_m(offs_t offset) override;
+ virtual void write_h(offs_t offset, u8 data) override;
virtual void pcb_reset() override;
protected:
+ // construction/destruction
+ nes_bmc_ctc12in1_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_start() override ATTR_COLD;
+
+ u8 m_reg[2];
};
-// ======================> nes_bmc_ch001_device
+// ======================> nes_bmc_891227_device
-class nes_bmc_ch001_device : public nes_nrom_device
+class nes_bmc_891227_device : public nes_bmc_ctc12in1_device
{
public:
// construction/destruction
- nes_bmc_ch001_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
+ nes_bmc_891227_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock);
- virtual uint8_t read_h(offs_t offset) override;
- virtual void write_h(offs_t offset, uint8_t data) override;
+ virtual void write_h(offs_t offset, u8 data) override;
+};
- virtual void pcb_reset() override;
-protected:
- // device-level overrides
- virtual void device_start() override;
+// ======================> nes_bmc_k1029_device
-private:
- uint8_t m_latch;
+class nes_bmc_k1029_device : public nes_vram_protect_device
+{
+public:
+ // construction/destruction
+ nes_bmc_k1029_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock);
+
+ virtual void write_h(offs_t offset, u8 data) override;
+
+protected:
+ // construction/destruction
+ nes_bmc_k1029_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, u32 clock);
};
-// ======================> nes_bmc_super22_device
+// ======================> nes_bmc_fam250_device
-class nes_bmc_super22_device : public nes_nrom_device
+class nes_bmc_fam250_device : public nes_bmc_k1029_device
{
public:
// construction/destruction
- nes_bmc_super22_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
+ nes_bmc_fam250_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock);
- virtual void write_h(offs_t offset, uint8_t data) override;
+ virtual u8 read_m(offs_t offset) override;
+ virtual void write_h(offs_t offset, u8 data) override;
virtual void pcb_reset() override;
protected:
// device-level overrides
- virtual void device_start() override;
+ virtual void device_start() override ATTR_COLD;
+
+private:
+ u8 m_latch, m_reg;
};
-// ======================> nes_bmc_4in1reset_device
+// ======================> nes_n625092_device
-class nes_bmc_4in1reset_device : public nes_nrom_device
+class nes_n625092_device : public nes_vram_protect_device
{
public:
// construction/destruction
- nes_bmc_4in1reset_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
+ nes_n625092_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock);
+
+ virtual void write_h(offs_t offset, u8 data) override;
virtual void pcb_reset() override;
protected:
// device-level overrides
- virtual void device_start() override;
+ virtual void device_start() override ATTR_COLD;
private:
- int m_latch;
+ u16 m_latch[2];
};
-// ======================> nes_bmc_42in1reset_device
-class nes_bmc_42in1reset_device : public nes_nrom_device
+// ======================> nes_bmc_th22913_device
+
+class nes_bmc_th22913_device : public nes_vram_protect_device
{
public:
// construction/destruction
- nes_bmc_42in1reset_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
+ nes_bmc_th22913_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock);
- virtual void write_h(offs_t offset, uint8_t data) override;
+ virtual void write_h(offs_t offset, u8 data) override;
virtual void pcb_reset() override;
protected:
- // device-level overrides
- virtual void device_start() override;
+ // construction/destruction
+ nes_bmc_th22913_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, u32 clock, u8 vram_prot_bit);
private:
- int m_latch;
- uint8_t m_reg[2];
+ const u8 m_vram_prot_bit;
+};
+
+
+// ======================> nes_bmc_82ab_device
+
+class nes_bmc_82ab_device : public nes_bmc_th22913_device
+{
+public:
+ // construction/destruction
+ nes_bmc_82ab_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock);
};
// device type definition
DECLARE_DEVICE_TYPE(NES_ACTION52, nes_action52_device)
-DECLARE_DEVICE_TYPE(NES_CALTRON6IN1, nes_caltron_device)
+DECLARE_DEVICE_TYPE(NES_CALTRON6IN1, nes_caltron6in1_device)
+DECLARE_DEVICE_TYPE(NES_CALTRON9IN1, nes_caltron9in1_device)
DECLARE_DEVICE_TYPE(NES_RUMBLESTATION, nes_rumblestat_device)
DECLARE_DEVICE_TYPE(NES_SVISION16, nes_svision16_device)
+DECLARE_DEVICE_TYPE(NES_FARID_UNROM, nes_farid_unrom_device)
+DECLARE_DEVICE_TYPE(NES_KN42, nes_kn42_device)
DECLARE_DEVICE_TYPE(NES_N625092, nes_n625092_device)
DECLARE_DEVICE_TYPE(NES_A65AS, nes_a65as_device)
DECLARE_DEVICE_TYPE(NES_T262, nes_t262_device)
-DECLARE_DEVICE_TYPE(NES_NOVEL1, nes_novel1_device)
-DECLARE_DEVICE_TYPE(NES_NOVEL2, nes_novel2_device)
DECLARE_DEVICE_TYPE(NES_STUDYNGAME, nes_studyngame_device)
DECLARE_DEVICE_TYPE(NES_SUPERGUN20IN1, nes_sgun20in1_device)
DECLARE_DEVICE_TYPE(NES_VT5201, nes_vt5201_device)
-DECLARE_DEVICE_TYPE(NES_810544C, nes_810544c_device)
+DECLARE_DEVICE_TYPE(NES_BMC_60311C, nes_bmc_60311c_device)
+DECLARE_DEVICE_TYPE(NES_BMC_80013B, nes_bmc_80013b_device)
+DECLARE_DEVICE_TYPE(NES_BMC_810544C, nes_bmc_810544c_device)
+DECLARE_DEVICE_TYPE(NES_BMC_830425C, nes_bmc_830425c_device)
+DECLARE_DEVICE_TYPE(NES_BMC_830928C, nes_bmc_830928c_device)
+DECLARE_DEVICE_TYPE(NES_BMC_850437C, nes_bmc_850437c_device)
+DECLARE_DEVICE_TYPE(NES_BMC_891227, nes_bmc_891227_device)
+DECLARE_DEVICE_TYPE(NES_BMC_970630C, nes_bmc_970630c_device)
DECLARE_DEVICE_TYPE(NES_NTD03, nes_ntd03_device)
-DECLARE_DEVICE_TYPE(NES_BMC_GB63, nes_bmc_gb63_device)
+DECLARE_DEVICE_TYPE(NES_BMC_CTC09, nes_bmc_ctc09_device)
+DECLARE_DEVICE_TYPE(NES_BMC_CTC12IN1, nes_bmc_ctc12in1_device)
+DECLARE_DEVICE_TYPE(NES_BMC_DS927, nes_bmc_ds927_device)
+DECLARE_DEVICE_TYPE(NES_BMC_FAM250, nes_bmc_fam250_device)
DECLARE_DEVICE_TYPE(NES_BMC_GKA, nes_bmc_gka_device)
DECLARE_DEVICE_TYPE(NES_BMC_GKB, nes_bmc_gkb_device)
+DECLARE_DEVICE_TYPE(NES_BMC_GKCXIN1, nes_bmc_gkcxin1_device)
+DECLARE_DEVICE_TYPE(NES_BMC_GN91B, nes_bmc_gn91b_device)
+DECLARE_DEVICE_TYPE(NES_BMC_HP898F, nes_bmc_hp898f_device)
+DECLARE_DEVICE_TYPE(NES_BMC_K1029, nes_bmc_k1029_device)
+DECLARE_DEVICE_TYPE(NES_BMC_K3036, nes_bmc_k3036_device)
+DECLARE_DEVICE_TYPE(NES_BMC_K3046, nes_bmc_k3046_device)
+DECLARE_DEVICE_TYPE(NES_BMC_K3071, nes_bmc_k3071_device)
+DECLARE_DEVICE_TYPE(NES_BMC_S009, nes_bmc_s009_device)
+DECLARE_DEVICE_TYPE(NES_BMC_SA005A, nes_bmc_sa005a_device)
+DECLARE_DEVICE_TYPE(NES_BMC_TF2740, nes_bmc_tf2740_device)
+DECLARE_DEVICE_TYPE(NES_BMC_TH2348, nes_bmc_th2348_device)
+DECLARE_DEVICE_TYPE(NES_BMC_TJ03, nes_bmc_tj03_device)
DECLARE_DEVICE_TYPE(NES_BMC_WS, nes_bmc_ws_device)
DECLARE_DEVICE_TYPE(NES_BMC_11160, nes_bmc_11160_device)
DECLARE_DEVICE_TYPE(NES_BMC_G146, nes_bmc_g146_device)
+DECLARE_DEVICE_TYPE(NES_BMC_2751, nes_bmc_2751_device)
DECLARE_DEVICE_TYPE(NES_BMC_8157, nes_bmc_8157_device)
DECLARE_DEVICE_TYPE(NES_BMC_HIK300, nes_bmc_hik300_device)
DECLARE_DEVICE_TYPE(NES_BMC_S700, nes_bmc_s700_device)
DECLARE_DEVICE_TYPE(NES_BMC_BALL11, nes_bmc_ball11_device)
DECLARE_DEVICE_TYPE(NES_BMC_22GAMES, nes_bmc_22games_device)
DECLARE_DEVICE_TYPE(NES_BMC_64Y2K, nes_bmc_64y2k_device)
+DECLARE_DEVICE_TYPE(NES_BMC_420Y2K, nes_bmc_420y2k_device)
DECLARE_DEVICE_TYPE(NES_BMC_12IN1, nes_bmc_12in1_device)
DECLARE_DEVICE_TYPE(NES_BMC_20IN1, nes_bmc_20in1_device)
DECLARE_DEVICE_TYPE(NES_BMC_21IN1, nes_bmc_21in1_device)
@@ -973,16 +1382,17 @@ DECLARE_DEVICE_TYPE(NES_BMC_64IN1, nes_bmc_64in1_device)
DECLARE_DEVICE_TYPE(NES_BMC_70IN1, nes_bmc_70in1_device)
DECLARE_DEVICE_TYPE(NES_BMC_72IN1, nes_bmc_72in1_device)
DECLARE_DEVICE_TYPE(NES_BMC_76IN1, nes_bmc_76in1_device)
-DECLARE_DEVICE_TYPE(NES_BMC_110IN1, nes_bmc_110in1_device)
DECLARE_DEVICE_TYPE(NES_BMC_150IN1, nes_bmc_150in1_device)
DECLARE_DEVICE_TYPE(NES_BMC_190IN1, nes_bmc_190in1_device)
+DECLARE_DEVICE_TYPE(NES_BMC_500IN1, nes_bmc_500in1_device)
DECLARE_DEVICE_TYPE(NES_BMC_800IN1, nes_bmc_800in1_device)
DECLARE_DEVICE_TYPE(NES_BMC_1200IN1, nes_bmc_1200in1_device)
-DECLARE_DEVICE_TYPE(NES_BMC_GOLD150, nes_bmc_gold150_device)
DECLARE_DEVICE_TYPE(NES_BMC_GOLD260, nes_bmc_gold260_device)
-DECLARE_DEVICE_TYPE(NES_BMC_CH001, nes_bmc_ch001_device)
-DECLARE_DEVICE_TYPE(NES_BMC_SUPER22, nes_bmc_super22_device)
DECLARE_DEVICE_TYPE(NES_BMC_4IN1RESET, nes_bmc_4in1reset_device)
DECLARE_DEVICE_TYPE(NES_BMC_42IN1RESET, nes_bmc_42in1reset_device)
+DECLARE_DEVICE_TYPE(NES_BMC_NC20MB, nes_bmc_nc20mb_device)
+DECLARE_DEVICE_TYPE(NES_BMC_LC160, nes_bmc_lc160_device)
+DECLARE_DEVICE_TYPE(NES_BMC_TH22913, nes_bmc_th22913_device)
+DECLARE_DEVICE_TYPE(NES_BMC_82AB, nes_bmc_82ab_device)
#endif // MAME_BUS_NES_MULTIGAME_H
diff --git a/src/devices/bus/nes/namcot.cpp b/src/devices/bus/nes/namcot.cpp
index 4e0951bf92a..67d321fc137 100644
--- a/src/devices/bus/nes/namcot.cpp
+++ b/src/devices/bus/nes/namcot.cpp
@@ -8,7 +8,7 @@
Here we emulate the following PCBs
- * Namcot 3433 & 3443 (aka DxROM) [mapper 88, 204, 154]
+ * Namcot 3433 & 3443 (aka DxROM) [mapper 88, 206, 154]
* Namcot 3446 [mapper 76]
* Namcot 3425 [mapper 95]
* Namcot 163 [mapper 19]
@@ -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"
//-------------------------------------------------
@@ -98,7 +97,6 @@ void nes_namcot3433_device::device_start()
void nes_namcot3433_device::pcb_reset()
{
- m_chr_source = m_vrom_chunks ? CHRROM : CHRRAM;
prg16_89ab(m_prg_chunks - 2);
prg16_cdef(m_prg_chunks - 1);
chr8(0, m_chr_source);
@@ -114,7 +112,6 @@ void nes_namcot3446_device::device_start()
void nes_namcot3446_device::pcb_reset()
{
- m_chr_source = m_vrom_chunks ? CHRROM : CHRRAM;
prg16_89ab(0);
prg16_cdef(m_prg_chunks - 1);
chr8(0, m_chr_source);
@@ -131,7 +128,6 @@ void nes_namcot3425_device::device_start()
void nes_namcot3425_device::pcb_reset()
{
- m_chr_source = m_vrom_chunks ? CHRROM : CHRRAM;
prg16_89ab(0);
prg16_cdef(m_prg_chunks - 1);
chr8(0, m_chr_source);
@@ -143,7 +139,7 @@ void nes_namcot3425_device::pcb_reset()
void nes_namcot340_device::device_start()
{
common_start();
- irq_timer = timer_alloc(TIMER_IRQ);
+ irq_timer = timer_alloc(FUNC(nes_namcot340_device::irq_timer_tick), this);
irq_timer->adjust(attotime::zero, 0, clocks_to_attotime(1));
save_item(NAME(m_irq_enable));
@@ -156,7 +152,6 @@ void nes_namcot340_device::device_start()
void nes_namcot340_device::pcb_reset()
{
- m_chr_source = m_vrom_chunks ? CHRROM : CHRRAM;
prg16_89ab(0);
prg16_cdef(m_prg_chunks - 1);
chr8(0, m_chr_source);
@@ -169,7 +164,7 @@ void nes_namcot340_device::pcb_reset()
void nes_namcot175_device::device_start()
{
common_start();
- irq_timer = timer_alloc(TIMER_IRQ);
+ irq_timer = timer_alloc(FUNC(nes_namcot175_device::irq_timer_tick), this);
irq_timer->adjust(attotime::zero, 0, clocks_to_attotime(1));
save_item(NAME(m_irq_enable));
@@ -183,7 +178,6 @@ void nes_namcot175_device::device_start()
void nes_namcot175_device::pcb_reset()
{
- m_chr_source = m_vrom_chunks ? CHRROM : CHRRAM;
prg16_89ab(0);
prg16_cdef(m_prg_chunks - 1);
chr8(0, m_chr_source);
@@ -197,7 +191,7 @@ void nes_namcot175_device::pcb_reset()
void nes_namcot163_device::device_start()
{
common_start();
- irq_timer = timer_alloc(TIMER_IRQ);
+ irq_timer = timer_alloc(FUNC(nes_namcot163_device::irq_timer_tick), this);
irq_timer->adjust(attotime::zero, 0, clocks_to_attotime(1));
save_item(NAME(m_irq_enable));
@@ -231,7 +225,6 @@ void nes_namcot163_device::device_start()
void nes_namcot163_device::pcb_reset()
{
- m_chr_source = m_vrom_chunks ? CHRROM : CHRRAM;
prg16_89ab(0);
prg16_cdef(m_prg_chunks - 1);
chr8(0, m_chr_source);
@@ -267,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);
@@ -296,7 +289,6 @@ void nes_namcot3433_device::dxrom_write(offs_t offset, uint8_t data)
}
}
-
/*-------------------------------------------------
Namcot 3446 board emulation
@@ -311,33 +303,25 @@ 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);
- // NEStopia does not have this!
if (offset >= 0x2000)
- {
- if (!(offset & 1))
- set_nt_mirroring(BIT(data, 0) ? PPU_MIRROR_HORZ : PPU_MIRROR_VERT);
return;
- }
- switch (offset & 1)
+ if (offset & 1)
{
- case 1:
- switch (m_latch & 0x07)
+ switch (m_latch & 0x07)
{
case 2: chr2_0(data, CHRROM); break;
case 3: chr2_2(data, CHRROM); break;
case 4: chr2_4(data, CHRROM); break;
case 5: chr2_6(data, CHRROM); break;
- case 6: BIT(m_latch, 6) ? prg8_cd(data) : prg8_89(data); break;
+ case 6: prg8_89(data); break;
case 7: prg8_ab(data); break;
}
- break;
- case 0:
- m_latch = data;
- break;
}
+ else
+ m_latch = data;
}
/*-------------------------------------------------
@@ -356,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;
@@ -408,27 +392,24 @@ void nes_namcot3425_device::write_h(offs_t offset, uint8_t data)
iNES: mapper 210
- In MESS: Supported
+ In MAME: Supported
-------------------------------------------------*/
-void nes_namcot340_device::device_timer(emu_timer &timer, device_timer_id id, int param, void *ptr)
+TIMER_CALLBACK_MEMBER(nes_namcot340_device::irq_timer_tick)
{
- if (id == TIMER_IRQ)
+ if (m_irq_enable)
{
- if (m_irq_enable)
- {
- if (m_irq_count == 0x7fff) // counter does not wrap to 0!
- set_irq_line(ASSERT_LINE);
- else
- m_irq_count++;
- }
+ if (m_irq_count == 0x7fff) // counter does not wrap to 0!
+ set_irq_line(ASSERT_LINE);
+ else
+ m_irq_count++;
}
}
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)
@@ -447,17 +428,19 @@ 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)
{
case 0x1000:
return m_irq_count & 0xff;
- set_irq_line(CLEAR_LINE);
+ set_irq_line(CLEAR_LINE); // FIXME: unreachable
+ [[fallthrough]];
case 0x1800:
- return (m_irq_count >> 8) & 0xff;
- set_irq_line(CLEAR_LINE);
+ return m_irq_count >> 8;
+ set_irq_line(CLEAR_LINE); // FIXME: unreachable
+ [[fallthrough]];
default:
return 0x00;
}
@@ -465,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)
{
@@ -473,7 +456,7 @@ void nes_namcot340_device::n340_hiwrite(offs_t offset, uint8_t data)
case 0x1000: case 0x1800:
case 0x2000: case 0x2800:
case 0x3000: case 0x3800:
- chr1_x(offset / 0x800, data, CHRROM);
+ chr1_x(offset >> 11, data, CHRROM);
break;
case 0x4000:
// no cart found with wram, so it is not clear if this could work as in Namcot-175...
@@ -520,7 +503,7 @@ void nes_namcot340_device::n340_hiwrite(offs_t offset, uint8_t data)
iNES: mapper 210
- In MESS: Supported
+ In MAME: Supported
-------------------------------------------------*/
@@ -531,7 +514,7 @@ uint8_t nes_namcot175_device::read_m(offs_t offset)
if (!m_battery.empty() && !m_wram_protect)
return m_battery[offset & (m_battery.size() - 1)];
- return get_open_bus(); // open bus
+ return get_open_bus();
}
void nes_namcot175_device::write_m(offs_t offset, uint8_t data)
@@ -544,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)
{
@@ -573,7 +556,7 @@ void nes_namcot175_device::write_h(offs_t offset, uint8_t data)
iNES: mapper 19
- In MESS: Supported
+ In MAME: Supported
-------------------------------------------------*/
@@ -612,20 +595,20 @@ uint8_t nes_namcot163_device::read_m(offs_t offset)
if (!m_battery.empty() && offset < m_battery.size())
return m_battery[offset & (m_battery.size() - 1)];
- return get_open_bus(); // open bus
+ return get_open_bus();
}
void nes_namcot163_device::write_m(offs_t offset, uint8_t data)
{
// the pcb can separately protect each 2KB chunk of the external wram from writes
- int bank = (offset & 0x1800) >> 11;
+ int bank = BIT(offset, 11, 2);
if (!m_battery.empty() && !BIT(m_wram_protect, bank))
m_battery[offset & (m_battery.size() - 1)] = 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)
@@ -641,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)
@@ -663,8 +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)
{
- int page;
- 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)
{
@@ -673,14 +655,13 @@ void nes_namcot163_device::write_h(offs_t offset, uint8_t data)
case 0x2000: case 0x2800:
case 0x3000: case 0x3800:
m_chr_bank = data;
- chr1_x(offset / 0x800, m_chr_bank, CHRROM);
+ chr1_x(offset >> 11, m_chr_bank, CHRROM);
break;
case 0x4000:
case 0x4800:
case 0x5000:
case 0x5800:
- page = (offset & 0x1800) >> 11;
- set_mirror(page, data);
+ set_mirror(BIT(offset, 11, 2), data);
break;
case 0x6000:
m_namco163snd->disable_w((data & 0x40) ? ASSERT_LINE : CLEAR_LINE);
diff --git a/src/devices/bus/nes/namcot.h b/src/devices/bus/nes/namcot.h
index 1dcf237fa90..d78bf509454 100644
--- a/src/devices/bus/nes/namcot.h
+++ b/src/devices/bus/nes/namcot.h
@@ -26,7 +26,7 @@ protected:
nes_namcot3433_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_start() override ATTR_COLD;
private:
uint8_t m_latch;
@@ -47,7 +47,7 @@ public:
protected:
// device-level overrides
- virtual void device_start() override;
+ virtual void device_start() override ATTR_COLD;
private:
uint8_t m_latch;
@@ -68,7 +68,7 @@ public:
protected:
// device-level overrides
- virtual void device_start() override;
+ virtual void device_start() override ATTR_COLD;
private:
uint8_t m_latch;
@@ -94,13 +94,12 @@ public:
virtual void pcb_reset() override;
protected:
- static constexpr device_timer_id TIMER_IRQ = 0;
-
nes_namcot340_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_timer(emu_timer &timer, device_timer_id id, int param, void *ptr) override;
+ virtual void device_start() override ATTR_COLD;
+
+ TIMER_CALLBACK_MEMBER(irq_timer_tick);
uint16_t m_irq_count;
int m_irq_enable;
@@ -122,7 +121,7 @@ public:
nes_namcot175_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
// device-level overrides
- virtual void device_start() override;
+ virtual void device_start() override ATTR_COLD;
virtual uint8_t read_m(offs_t offset) override;
virtual void write_m(offs_t offset, uint8_t data) override;
virtual void write_h(offs_t offset, uint8_t data) override;
@@ -156,9 +155,9 @@ public:
protected:
// device-level overrides
- virtual void device_start() override;
+ virtual void device_start() override ATTR_COLD;
- virtual void device_add_mconfig(machine_config &config) override;
+ virtual void device_add_mconfig(machine_config &config) override ATTR_COLD;
private:
void set_mirror(uint8_t page, uint8_t data);
diff --git a/src/devices/bus/nes/nanjing.cpp b/src/devices/bus/nes/nanjing.cpp
index 9719816beb2..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"
//-------------------------------------------------
@@ -60,7 +59,6 @@ void nes_nanjing_device::device_start()
void nes_nanjing_device::pcb_reset()
{
- m_chr_source = m_vrom_chunks ? CHRROM : CHRRAM;
prg16_89ab(m_prg_chunks - 2);
prg16_cdef(m_prg_chunks - 1);
chr8(0, m_chr_source);
@@ -88,11 +86,11 @@ void nes_nanjing_device::pcb_reset()
iNES: mapper 163
- In MESS: Unsupported.
+ In MAME: Unsupported.
-------------------------------------------------*/
-void nes_nanjing_device::hblank_irq(int scanline, int vblank, int blanked)
+void nes_nanjing_device::hblank_irq(int scanline, bool vblank, bool blanked)
{
if (BIT(m_reg[0], 7))
{
@@ -113,7 +111,7 @@ void nes_nanjing_device::hblank_irq(int scanline, int vblank, int 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;
@@ -157,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/nanjing.h b/src/devices/bus/nes/nanjing.h
index c5a71032573..9741da6e6cd 100644
--- a/src/devices/bus/nes/nanjing.h
+++ b/src/devices/bus/nes/nanjing.h
@@ -22,12 +22,12 @@ public:
virtual uint8_t read_l(offs_t offset) override;
virtual void write_l(offs_t offset, uint8_t data) override;
- virtual void hblank_irq(int scanline, int vblank, int blanked) override;
+ virtual void hblank_irq(int scanline, bool vblank, bool blanked) override;
virtual void pcb_reset() override;
protected:
// device-level overrides
- virtual void device_start() override;
+ virtual void device_start() override ATTR_COLD;
private:
uint8_t m_count;
diff --git a/src/devices/bus/nes/nes_carts.cpp b/src/devices/bus/nes/nes_carts.cpp
index a4a3950b98d..1b04e56d5e2 100644
--- a/src/devices/bus/nes/nes_carts.cpp
+++ b/src/devices/bus/nes/nes_carts.cpp
@@ -34,6 +34,7 @@
#include "act53.h"
#include "aladdin.h"
#include "ave.h"
+#include "batlab.h"
#include "benshieng.h"
#include "camerica.h"
#include "cne.h"
@@ -41,7 +42,7 @@
#include "ggenie.h"
#include "hes.h"
#include "henggedianzi.h"
-#include "hosenkan.h"
+#include "jncota.h"
#include "jy.h"
#include "kaiser.h"
#include "legacy.h"
@@ -51,6 +52,7 @@
#include "rcm.h"
#include "rexsoft.h"
#include "sachen.h"
+#include "sealie.h"
#include "somari.h"
#include "subor.h"
#include "tengen.h"
@@ -61,7 +63,9 @@
#include "bootleg.h"
#include "multigame.h"
#include "pirate.h"
+#include "mmc1_clones.h"
#include "mmc3_clones.h"
+#include "vrc_clones.h"
void nes_cart(device_slot_interface &device)
@@ -98,8 +102,7 @@ void nes_cart(device_slot_interface &device)
// SxROM
device.option_add_internal("sxrom", NES_SXROM);
device.option_add_internal("sorom", NES_SOROM);
- device.option_add_internal("sxrom_a", NES_SXROM_A); // in MMC1-A PRG RAM is always enabled
- device.option_add_internal("sorom_a", NES_SOROM_A); // in MMC1-A PRG RAM is always enabled
+ device.option_add_internal("szrom", NES_SZROM);
// TxROM
device.option_add_internal("txrom", NES_TXROM);
// HKROM
@@ -116,6 +119,7 @@ void nes_cart(device_slot_interface &device)
device.option_add_internal("pal_zz", NES_ZZ_PCB);
device.option_add_internal("nes_qj", NES_QJ_PCB);
device.option_add_internal("nes_event", NES_EVENT);
+ device.option_add_internal("nes_event2", NES_EVENT2);
// Discrete Components boards
// IC_74x139x74
device.option_add_internal("discrete_74x139", NES_74X139X74);
@@ -187,14 +191,18 @@ void nes_cart(device_slot_interface &device)
device.option_add_internal("nina006", NES_NINA006);
device.option_add_internal("bf9093", NES_BF9093);
device.option_add_internal("bf9096", NES_BF9096);
+ device.option_add_internal("bf9096a", NES_BF9096A);
device.option_add_internal("goldenfive", NES_GOLDEN5);
device.option_add_internal("ade", NES_ALADDIN);
device.option_add_internal("cne_decathl", NES_CNE_DECATHL);
device.option_add_internal("cne_fsb", NES_CNE_FSB);
device.option_add_internal("cne_shlz", NES_CNE_SHLZ);
+ device.option_add_internal("cocoma", NES_COCOMA);
device.option_add_internal("nanjing", NES_NANJING); // mapper 163
device.option_add_internal("ntdec_asder", NES_NTDEC_ASDER); // mapper 112
device.option_add_internal("ntdec_fh", NES_NTDEC_FH); // mapper 193
+ device.option_add_internal("ntdec_n715021", NES_NTDEC_N715021); // mapper 81
+ device.option_add_internal("jncota_kt1001", NES_JNCOTA_KT1001); // mapper 551
device.option_add_internal("jyc_a", NES_JY_TYPEA); // mapper 90
device.option_add_internal("jyc_b", NES_JY_TYPEB); // mapper 211
device.option_add_internal("jyc_c", NES_JY_TYPEC); // mapper 209
@@ -204,6 +212,8 @@ void nes_cart(device_slot_interface &device)
device.option_add_internal("sa72007", NES_SACHEN_SA72007);
device.option_add_internal("sa72008", NES_SACHEN_SA72008);
device.option_add_internal("tca01", NES_SACHEN_TCA01);
+ device.option_add_internal("s3013", NES_SACHEN_3013);
+ device.option_add_internal("s3014", NES_SACHEN_3014);
device.option_add_internal("s8259a", NES_SACHEN_8259A);
device.option_add_internal("s8259b", NES_SACHEN_8259B);
device.option_add_internal("s8259c", NES_SACHEN_8259C);
@@ -212,9 +222,9 @@ void nes_cart(device_slot_interface &device)
device.option_add_internal("s74x374a", NES_SACHEN_74X374_ALT); // FIXME: Made up boards some different handling
device.option_add_internal("tcu01", NES_SACHEN_TCU01);
device.option_add_internal("tcu02", NES_SACHEN_TCU02);
- device.option_add_internal("tengen_800008", NES_TENGEN_800008); // FIXME: Is this the same as CNROM?
device.option_add_internal("tengen_800032", NES_TENGEN_800032);
device.option_add_internal("tengen_800037", NES_TENGEN_800037);
+ device.option_add_internal("txc_22110", NES_TXC_22110);
device.option_add_internal("txc_22211", NES_TXC_22211);
device.option_add_internal("txc_dumarc", NES_TXC_DUMARACING);
device.option_add_internal("txc_mjblock", NES_TXC_MJBLOCK);
@@ -227,12 +237,12 @@ void nes_cart(device_slot_interface &device)
device.option_add_internal("waixing_d", NES_WAIXING_D);
device.option_add_internal("waixing_e", NES_WAIXING_E);
device.option_add_internal("waixing_f", NES_WAIXING_F);
+ device.option_add_internal("waixing_f1", NES_WAIXING_F1);
device.option_add_internal("waixing_g", NES_WAIXING_G);
device.option_add_internal("waixing_h", NES_WAIXING_H);
device.option_add_internal("waixing_h1", NES_WAIXING_H1); // FIXME: Made up boards the different WRAM protect banks (see Shen Mi Jin San Jiao)
device.option_add_internal("waixing_i", NES_WAIXING_I);
device.option_add_internal("waixing_j", NES_WAIXING_J);
- device.option_add_internal("waixing_sgz", NES_WAIXING_SGZ);
device.option_add_internal("waixing_sgzlz", NES_WAIXING_SGZLZ);
device.option_add_internal("waixing_sec", NES_WAIXING_SEC);
device.option_add_internal("waixing_ffv", NES_WAIXING_FFV);
@@ -242,22 +252,27 @@ void nes_cart(device_slot_interface &device)
device.option_add_internal("waixing_sh2", NES_WAIXING_SH2);
device.option_add_internal("fs304", NES_WAIXING_FS304); // used in Zelda 3 by Waixing
device.option_add_internal("cony", NES_CONY);
+ device.option_add_internal("cony1k", NES_CONY1K);
device.option_add_internal("yoko", NES_YOKO);
device.option_add_internal("hengg_srich", NES_HENGG_SRICH);
device.option_add_internal("hengg_xhzs", NES_HENGG_XHZS);
- device.option_add_internal("hengg_shjy3", NES_HENGG_SHJY3); // mapper 253
device.option_add_internal("hes", NES_HES);
- device.option_add_internal("hosenkan", NES_HOSENKAN);
- device.option_add_internal("ks7058", NES_KS7058);
+ device.option_add_internal("ks106c", NES_KS106C); // mapper 352
device.option_add_internal("ks202", NES_KS202); // mapper 56
- device.option_add_internal("ks7022", NES_KS7022); // mapper 175
+ device.option_add_internal("ks7010", NES_KS7010); // used in Akumajo Dracula (FDS Conversion)
+ device.option_add_internal("ks7012", NES_KS7012); // used in Zanac (FDS Conversion)
+ device.option_add_internal("ks7013b", NES_KS7013B); // used in Highway Star Kaiser bootleg
+ device.option_add_internal("ks7016", NES_KS7016); // used in Exciting Basket (FDS Conversion)
+ device.option_add_internal("ks7016b", NES_KS7016B); // used in Meikyu Jiin Dababa alt (FDS Conversion)
device.option_add_internal("ks7017", NES_KS7017);
- device.option_add_internal("ks7032", NES_KS7032); // mapper 142
- device.option_add_internal("ks7012", NES_KS7012); // used in Zanac (FDS Conversion);
- device.option_add_internal("ks7013b", NES_KS7013B); // used in Highway Star (FDS Conversion);
- device.option_add_internal("ks7031", NES_KS7031); // used in Dracula II (FDS Conversion);
- device.option_add_internal("ks7016", NES_KS7016); // used in Exciting Basket (FDS Conversion);
- device.option_add_internal("ks7037", NES_KS7037); // used in Metroid (FDS Conversion);
+ device.option_add_internal("ks7021a", NES_KS7021A); // GetsuFumaDen pirate cart
+ device.option_add_internal("ks7022", NES_KS7022); // mapper 175
+ device.option_add_internal("ks7030", NES_KS7030); // used in Doki Doki Panic alt (FDS Conversion)
+ device.option_add_internal("ks7031", NES_KS7031); // used in Dracula II (FDS Conversion)
+ device.option_add_internal("ks7032", NES_KS7032); // mapper 142
+ device.option_add_internal("ks7037", NES_KS7037); // used in Metroid (FDS Conversion)
+ device.option_add_internal("ks7057", NES_KS7057); // used in Gyruss (FDS Conversion)
+ device.option_add_internal("ks7058", NES_KS7058);
device.option_add_internal("gs2015", NES_GS2015);
device.option_add_internal("gs2004", NES_GS2004);
device.option_add_internal("gs2013", NES_GS2013);
@@ -273,93 +288,150 @@ void nes_cart(device_slot_interface &device)
device.option_add_internal("subor0", NES_SUBOR0);
device.option_add_internal("subor1", NES_SUBOR1);
device.option_add_internal("subor2", NES_SUBOR2);
+ device.option_add_internal("unl_158b", NES_158B);
device.option_add_internal("cc21", NES_CC21);
device.option_add_internal("xiaozy", NES_XIAOZY);
device.option_add_internal("edu2k", NES_EDU2K);
- device.option_add_internal("t230", NES_T230);
- device.option_add_internal("mk2", NES_MK2);
- device.option_add_internal("unl_whero", NES_WHERO); // mapper 27
+ device.option_add_internal("jy830623c", NES_JY830623C);
device.option_add_internal("unl_43272", NES_43272); // used in Gaau Hok Gwong Cheung
- device.option_add_internal("tf1201", NES_TF1201);
- device.option_add_internal("unl_cfight", NES_CITYFIGHT); // used by City Fighter IV
+ device.option_add_internal("ninjaryu", NES_NINJARYU); // used by Ninja Ryukenden Chinese
+ device.option_add_internal("unl_eh8813a", NES_EH8813A); // used by Dr. Mario II
device.option_add_internal("zemina", NES_ZEMINA); // mapper 190 - Magic Kid GooGoo
// misc bootleg boards
- device.option_add_internal("ax5705", NES_AX5705);
device.option_add_internal("sc127", NES_SC127);
device.option_add_internal("mariobaby", NES_MARIOBABY);
device.option_add_internal("asnicol", NES_ASN);
device.option_add_internal("smb3pirate", NES_SMB3PIRATE);
+ device.option_add_internal("btl_contraj", NES_BTL_CONTRAJ);
device.option_add_internal("btl_dninja", NES_BTL_DNINJA);
- device.option_add_internal("whirl2706", NES_WHIRLWIND_2706);
device.option_add_internal("smb2j", NES_SMB2J);
device.option_add_internal("smb2ja", NES_SMB2JA);
device.option_add_internal("smb2jb", NES_SMB2JB);
+ device.option_add_internal("yung08", NES_YUNG08);
+ device.option_add_internal("btl_0353", NES_0353); // used by Lucky (Roger) Rabbit FDS conversion
device.option_add_internal("09034a", NES_09034A);
+ device.option_add_internal("l001", NES_L001);
+ device.option_add_internal("batmanfs", NES_BATMANFS);
+ device.option_add_internal("palthena", NES_PALTHENA); // used by Palthena no Kagami FDS conversion
device.option_add_internal("tobidase", NES_TOBIDASE); // mapper 120
- device.option_add_internal("mmalee2", NES_MMALEE); // mapper 55?
+ device.option_add_internal("mmalee2", NES_MMALEE); // mapper 55
device.option_add_internal("unl_2708", NES_2708); // mapper 103
+ device.option_add_internal("unl_dh08", NES_DH08); // used in Bubble Bobble alt (FDS Conversion)
+ device.option_add_internal("unl_le05", NES_LE05); // used in ProWres (FDS Conversion)
+ device.option_add_internal("unl_lg25", NES_LG25); // used in Moero TwinBee (FDS Conversion)
+ device.option_add_internal("unl_lh10", NES_LH10); // used in Fuuun Shaolin Kyo (FDS Conversion)
+ device.option_add_internal("unl_lh28_lh54", NES_LH28_LH54); // used in Falsion, Meikyuu Jiin Dababa FDS conversions
+ device.option_add_internal("unl_lh31", NES_LH31); // used in Bubble Bobble alt FDS conversion
device.option_add_internal("unl_lh32", NES_LH32); // used by Monty no Doki Doki Daidassou FDS conversion
- device.option_add_internal("unl_lh10", NES_LH10); // used in Fuuun Shaolin Kyo (FDS Conversion);
- device.option_add_internal("unl_lh53", NES_LH53); // used in Nazo no Murasamejou (FDS Conversion);
+ device.option_add_internal("unl_lh42", NES_LH42); // used by Highway Star Whirlwind Manu bootleg
+ device.option_add_internal("unl_lh51", NES_LH51); // used in Ai Senshi Nicol alt FDS conversion
+ device.option_add_internal("unl_lh53", NES_LH53); // used in Nazo no Murasamejou (FDS Conversion)
device.option_add_internal("unl_ac08", NES_AC08); // used by Green Beret FDS conversion
- device.option_add_internal("unl_bb", NES_UNL_BB); // used by a few FDS conversions
- device.option_add_internal("sgpipe", NES_SHUIGUAN); // mapper 183
device.option_add_internal("rt01", NES_RT01);
// misc MMC3 clone boards
device.option_add_internal("dbz5", NES_REX_DBZ5);
device.option_add_internal("sl1632", NES_REX_SL1632);
device.option_add_internal("somari", NES_SOMARI); // mapper 116
+ device.option_add_internal("huang2", NES_HUANG2); // mapper 116 also
device.option_add_internal("nitra", NES_NITRA);
- device.option_add_internal("ks7057", NES_KS7057); // mapper 196 alt (for Street Fighter VI / Fight Street VI);
+ device.option_add_internal("bmw8544", NES_BMW8544);
+ device.option_add_internal("fs6", NES_FS6); // mapper 196 alt? (for Street Fighter VI / Fight Street VI);
device.option_add_internal("sbros11", NES_SBROS11);
device.option_add_internal("unl_malisb", NES_MALISB); // used by Super Mali Splash Bomb
device.option_add_internal("family4646", NES_FAMILY4646);
device.option_add_internal("pikay2k", NES_PIKAY2K); // mapper 254
device.option_add_internal("8237", NES_8237);
- device.option_add_internal("8237a", NES_NROM); // UNSUPPORTED
+ device.option_add_internal("8237a", NES_8237A);
device.option_add_internal("sg_lionk", NES_SG_LIONK);
device.option_add_internal("sg_boog", NES_SG_BOOG);
device.option_add_internal("kasing", NES_KASING);
device.option_add_internal("kay", NES_KAY);
device.option_add_internal("h2288", NES_H2288);
- device.option_add_internal("unl_6035052", NES_6035052); // mapper 238?
+ device.option_add_internal("unl_6035052", NES_6035052); // mapper 238
device.option_add_internal("txc_tw", NES_TXC_TW);
device.option_add_internal("kof97", NES_KOF97);
device.option_add_internal("kof96", NES_KOF96);
device.option_add_internal("sfight3", NES_SF3);
device.option_add_internal("gouder", NES_GOUDER);
device.option_add_internal("sa9602b", NES_SA9602B);
- device.option_add_internal("unl_shero", NES_SACHEN_SHERO);
+ device.option_add_internal("sachen_shero", NES_SACHEN_SHERO);
+ device.option_add_internal("sachen_zgdh", NES_SACHEN_ZGDH);
+ device.option_add_internal("a9746", NES_A9746); // mapper 219
+// misc VRC clone boards
+ device.option_add_internal("btl_2yudb", NES_2YUDB);
+ device.option_add_internal("btl_900218", NES_900218);
+ device.option_add_internal("ax40g", NES_AX40G);
+ device.option_add_internal("ax5705", NES_AX5705);
+ device.option_add_internal("bmc_830506c", NES_BMC_830506C);
+ device.option_add_internal("bmc_831128c", NES_BMC_831128C);
+ device.option_add_internal("bmc_kl06", NES_BMC_KL06);
+ device.option_add_internal("unl_cfight", NES_CITYFIGHT); // used by City Fighter IV
+ device.option_add_internal("hengg_shjy3", NES_HENGG_SHJY3); // mapper 253
+ device.option_add_internal("sgpipe", NES_SHUIGUAN); // mapper 183
+ device.option_add_internal("t230", NES_T230);
+ device.option_add_internal("tf1201", NES_TF1201);
+ device.option_add_internal("th21311", NES_TH21311);
+ device.option_add_internal("waixing_sgz", NES_WAIXING_SGZ);
// misc multigame cart boards
device.option_add_internal("benshieng", NES_BENSHIENG);
device.option_add_internal("action52", NES_ACTION52);
device.option_add_internal("caltron6in1", NES_CALTRON6IN1);
+ device.option_add_internal("caltron9in1", NES_CALTRON9IN1);
device.option_add_internal("maxi15", NES_MAXI15); // mapper 234
device.option_add_internal("rumblestation", NES_RUMBLESTATION); // mapper 46
device.option_add_internal("svision16", NES_SVISION16); // mapper 53
+ device.option_add_internal("kn42", NES_KN42);
device.option_add_internal("n625092", NES_N625092);
device.option_add_internal("a65as", NES_A65AS);
device.option_add_internal("t262", NES_T262);
- device.option_add_internal("novel1", NES_NOVEL1);
- device.option_add_internal("novel2", NES_NOVEL2); // mapper 213... same as BMC-NOVELDIAMOND9999999IN1 board?
device.option_add_internal("studyngame", NES_STUDYNGAME); // mapper 39
device.option_add_internal("sgun20in1", NES_SUPERGUN20IN1);
- device.option_add_internal("bmc_vt5201", NES_VT5201); // mapper 60 otherwise
- device.option_add_internal("bmc_d1038", NES_VT5201); // mapper 60?
- device.option_add_internal("810544c", NES_810544C);
+ device.option_add_internal("bmc_vt5201", NES_VT5201); // mapper 59
+ device.option_add_internal("bmc_60311c", NES_BMC_60311C);
+ device.option_add_internal("bmc_80013b", NES_BMC_80013B);
+ device.option_add_internal("bmc_810544c", NES_BMC_810544C);
+ device.option_add_internal("bmc_82ab", NES_BMC_82AB);
+ device.option_add_internal("bmc_830425c", NES_BMC_830425C);
+ device.option_add_internal("bmc_830928c", NES_BMC_830928C);
+ device.option_add_internal("bmc_850437c", NES_BMC_850437C);
+ device.option_add_internal("bmc_891227", NES_BMC_891227);
+ device.option_add_internal("bmc_970630c", NES_BMC_970630C);
+ device.option_add_internal("bmc_jy012005", NES_BMC_JY012005);
+ device.option_add_internal("bmc_jy820845c", NES_BMC_JY820845C);
+ device.option_add_internal("srpg_5in1", NES_SRPG_5IN1);
+ device.option_add_internal("n32_4in1", NES_N32_4IN1);
device.option_add_internal("ntd03", NES_NTD03);
- device.option_add_internal("bmc_gb63", NES_BMC_GB63);
+ device.option_add_internal("bmc_ctc09", NES_BMC_CTC09);
+ device.option_add_internal("bmc_ctc12in1", NES_BMC_CTC12IN1);
+ device.option_add_internal("bmc_ds927", NES_BMC_DS927);
+ device.option_add_internal("bmc_fam250", NES_BMC_FAM250);
device.option_add_internal("bmc_gka", NES_BMC_GKA);
device.option_add_internal("bmc_gkb", NES_BMC_GKB);
+ device.option_add_internal("bmc_gkcxin1", NES_BMC_GKCXIN1);
+ device.option_add_internal("bmc_gn91b", NES_BMC_GN91B);
+ device.option_add_internal("bmc_hp898f", NES_BMC_HP898F);
+ device.option_add_internal("bmc_k1029", NES_BMC_K1029);
+ device.option_add_internal("bmc_k3006", NES_BMC_K3006);
+ device.option_add_internal("bmc_k3033", NES_BMC_K3033);
+ device.option_add_internal("bmc_k3036", NES_BMC_K3036);
+ device.option_add_internal("bmc_k3046", NES_BMC_K3046);
+ device.option_add_internal("bmc_k3071", NES_BMC_K3071);
+ device.option_add_internal("bmc_s009", NES_BMC_S009);
+ device.option_add_internal("bmc_sa005a", NES_BMC_SA005A);
+ device.option_add_internal("bmc_tf2740", NES_BMC_TF2740);
+ device.option_add_internal("bmc_th2348", NES_BMC_TH2348);
+ device.option_add_internal("bmc_tj03", NES_BMC_TJ03);
device.option_add_internal("bmc_ws", NES_BMC_WS);
device.option_add_internal("bmc_g146", NES_BMC_G146);
device.option_add_internal("bmc_11160", NES_BMC_11160);
+ device.option_add_internal("bmc_2751", NES_BMC_2751);
device.option_add_internal("bmc_8157", NES_BMC_8157);
device.option_add_internal("bmc_hik300", NES_BMC_HIK300);
device.option_add_internal("bmc_s700", NES_BMC_S700);
device.option_add_internal("bmc_ball11", NES_BMC_BALL11);
device.option_add_internal("bmc_22games", NES_BMC_22GAMES);
device.option_add_internal("bmc_64y2k", NES_BMC_64Y2K);
+ device.option_add_internal("bmc_420y2k", NES_BMC_420Y2K);
device.option_add_internal("bmc_12in1", NES_BMC_12IN1);
device.option_add_internal("bmc_20in1", NES_BMC_20IN1);
device.option_add_internal("bmc_21in1", NES_BMC_21IN1);
@@ -367,58 +439,76 @@ void nes_cart(device_slot_interface &device)
device.option_add_internal("bmc_35in1", NES_BMC_35IN1);
device.option_add_internal("bmc_36in1", NES_BMC_36IN1);
device.option_add_internal("bmc_64in1", NES_BMC_64IN1);
- device.option_add_internal("bmc_70in1", NES_BMC_70IN1); // mapper 236?
+ device.option_add_internal("bmc_70in1", NES_BMC_70IN1); // mapper 236
device.option_add_internal("bmc_72in1", NES_BMC_72IN1);
device.option_add_internal("bmc_76in1", NES_BMC_76IN1);
- device.option_add_internal("bmc_s42in1", NES_BMC_76IN1);
- device.option_add_internal("bmc_110in1", NES_BMC_110IN1);
device.option_add_internal("bmc_150in1", NES_BMC_150IN1);
device.option_add_internal("bmc_190in1", NES_BMC_190IN1);
- device.option_add_internal("bmc_800in1", NES_BMC_800IN1); // mapper 236?
+ device.option_add_internal("bmc_500in1", NES_BMC_500IN1);
+ device.option_add_internal("bmc_800in1", NES_BMC_800IN1); // mapper 236
device.option_add_internal("bmc_1200in1", NES_BMC_1200IN1);
- device.option_add_internal("bmc_gold150", NES_BMC_GOLD150); // mapper 235 with 2M PRG
- device.option_add_internal("bmc_gold260", NES_BMC_GOLD260); // mapper 235 with 4M PRG
- device.option_add_internal("bmc_power255", NES_BMC_CH001); // mapper 63?
- device.option_add_internal("bmc_s22games", NES_BMC_SUPER22); // mapper 233
+ device.option_add_internal("bmc_gold260", NES_BMC_GOLD260); // mapper 235
+ device.option_add_internal("bmc_th22913", NES_BMC_TH22913); // mapper 63
device.option_add_internal("bmc_reset4", NES_BMC_4IN1RESET); // mapper 60 with 64k prg and 32k chr
- device.option_add_internal("bmc_reset42", NES_BMC_42IN1RESET); // mapper 60? or 226? or 233?
+ device.option_add_internal("bmc_reset42", NES_BMC_42IN1RESET); // mapper 233
+ device.option_add_internal("bmc_nc20mb", NES_BMC_NC20MB);
+ device.option_add_internal("bmc_lc160", NES_BMC_LC160);
+ device.option_add_internal("resetsxrom", NES_RESETSXROM);
// misc multigame cart MMC3 clone boards
+ device.option_add_internal("a88s1", NES_A88S1);
+ device.option_add_internal("bmc_el86xc", NES_BMC_EL86XC);
device.option_add_internal("fk23c", NES_FK23C);
device.option_add_internal("fk23ca", NES_FK23CA);
+ device.option_add_internal("nt639", NES_NT639);
+ device.option_add_internal("resettxrom", NES_RESETTXROM);
device.option_add_internal("s24in1c03", NES_S24IN1SC03);
+ device.option_add_internal("smd133", NES_SMD133);
+ device.option_add_internal("tech9in1", NES_TECHLINE9IN1);
+ device.option_add_internal("bmc_5in1", NES_BMC_5IN1);
+ device.option_add_internal("bmc_8in1", NES_BMC_8IN1);
device.option_add_internal("bmc_15in1", NES_BMC_15IN1);
device.option_add_internal("bmc_sbig7in1", NES_BMC_SBIG7);
device.option_add_internal("bmc_hik8in1", NES_BMC_HIK8);
+ device.option_add_internal("bmc_jy208", NES_BMC_JY208);
+ device.option_add_internal("bmc_jy302", NES_BMC_JY302);
+ device.option_add_internal("bmc_kc885", NES_BMC_KC885);
+ device.option_add_internal("bmc_sfc12", NES_BMC_SFC12);
device.option_add_internal("bmc_hik4in1", NES_BMC_HIK4);
- device.option_add_internal("bmc_mario7in1", NES_BMC_MARIO7IN1);
+ device.option_add_internal("bmc_f15", NES_BMC_F15);
+ device.option_add_internal("bmc_f600", NES_BMC_F600);
+ device.option_add_internal("bmc_gn45", NES_BMC_GN45);
device.option_add_internal("bmc_gold7in1", NES_BMC_GOLD7IN1);
- device.option_add_internal("bmc_gc6in1", NES_BMC_GC6IN1);
+ device.option_add_internal("bmc_l6in1", NES_BMC_L6IN1);
+ device.option_add_internal("bmc_00202650", NES_BMC_00202650);
device.option_add_internal("bmc_411120c", NES_BMC_411120C);
+ device.option_add_internal("bmc_810305c", NES_BMC_810305C);
+ device.option_add_internal("bmc_820720c", NES_BMC_820720C);
device.option_add_internal("bmc_830118c", NES_BMC_830118C);
+ device.option_add_internal("bmc_830832c", NES_BMC_830832C);
+ device.option_add_internal("bmc_yy841101c", NES_BMC_YY841101C);
+ device.option_add_internal("bmc_yy841155c", NES_BMC_YY841155C);
device.option_add_internal("pjoy84", NES_PJOY84);
device.option_add_internal("nocash_nochr", NES_NOCHR);
- device.option_add_internal("nes_action53", NES_ACTION53);
- device.option_add_internal("nes_2a03pur", NES_2A03PURITANS);
+ device.option_add_internal("action53", NES_ACTION53);
+ device.option_add_internal("batmap_000", NES_BATMAP_000);
+ device.option_add_internal("batmap_srrx", NES_BATMAP_SRRX);
+ device.option_add_internal("8bitxmas", NES_8BITXMAS);
+ device.option_add_internal("cufrom", NES_CUFROM);
+ device.option_add_internal("dpcmcart", NES_DPCMCART);
+ device.option_add_internal("unrom512", NES_UNROM512);
+ device.option_add_internal("2a03pur", NES_2A03PURITANS);
+ device.option_add_internal("farid_slrom8in1", NES_FARID_SLROM);
+ device.option_add_internal("farid_unrom8in1", NES_FARID_UNROM);
// other unsupported...
- device.option_add_internal("ninjaryu", NES_NROM); // mapper 111 - UNSUPPORTED
device.option_add_internal("unl_dance", NES_NROM); // UNSUPPORTED
device.option_add_internal("onebus", NES_NROM); // UNSUPPORTED
device.option_add_internal("pec586", NES_NROM); // UNSUPPORTED
- device.option_add_internal("coolboy", NES_NROM); // UNSUPPORTED
- device.option_add_internal("bmc_f15", NES_NROM); // UNSUPPORTED
- device.option_add_internal("bmc_hp898f", NES_NROM); // UNSUPPORTED
- device.option_add_internal("bmc_8in1", NES_NROM); // UNSUPPORTED
- device.option_add_internal("unl_eh8813a", NES_NROM); // UNSUPPORTED
- device.option_add_internal("unl_158b", NES_NROM); // UNSUPPORTED
- device.option_add_internal("unl_drgnfgt", NES_NROM); // UNSUPPORTED
// are there dumps of games with these boards?
- device.option_add_internal("bmc_hik_kof", NES_NROM); // mapper 251 - UNSUPPORTED
device.option_add_internal("bmc_13in1jy110", NES_NROM); // [mentioned in FCEUMM source - we need more info] - UNSUPPORTED
device.option_add_internal("bmc_gk_192", NES_NROM); // [mentioned in FCEUMM source - we need more info] - UNSUPPORTED
device.option_add_internal("konami_qtai", NES_NROM); // [mentioned in FCEUMM source - we need more info] - UNSUPPORTED
device.option_add_internal("unl_3d_block", NES_NROM); // [mentioned in FCEUMM source - we need more info] - UNSUPPORTED
device.option_add_internal("unl_c_n22m", NES_NROM); // [mentioned in FCEUMM source - we need more info] - UNSUPPORTED
- device.option_add_internal("a9746", NES_NROM); // mapper 219 - UNSUPPORTED (no dump available);
// legacy boards for FFE copier mappers (are there images available to fix/improve emulation?)
device.option_add_internal("ffe3", NES_FFE3);
device.option_add_internal("ffe4", NES_FFE4);
diff --git a/src/devices/bus/nes/nes_ines.hxx b/src/devices/bus/nes/nes_ines.hxx
index 6887256fc59..95f35e14735 100644
--- a/src/devices/bus/nes/nes_ines.hxx
+++ b/src/devices/bus/nes/nes_ines.hxx
@@ -47,22 +47,23 @@ static const nes_mmc mmc_list[] =
{ 12, REXSOFT_DBZ5 },
{ 13, STD_CPROM },
{ 14, REXSOFT_SL1632 },
- { 15, WAIXING_WXZS2 },
+ { 15, BMC_K1029 },
{ 16, BANDAI_LZ93EX2 }, // with 24c02
{ 17, FFE8_BOARD },
{ 18, JALECO_SS88006 },
{ 19, NAMCOT_163 },
+ // 20 Reserved for emulator use for FDS emulation.
{ 21, KONAMI_VRC4 },
{ 22, KONAMI_VRC2 },
{ 23, KONAMI_VRC2 },
{ 24, KONAMI_VRC6 },
{ 25, KONAMI_VRC4 },
{ 26, KONAMI_VRC6 },
- { 27, UNL_WORLDHERO }, // 27 World Hero board - Unsupported
- { 28, BTL_ACTION53 }, // 28 - Multi-discrete PCB designed by Tepples for Action 53
- // 29 Unused
- // 30 UNROM 512 + Flash, currently unsupported
- { 31, BTL_2A03_PURITANS }, // 31 - PCB designed by infinitelives & rainwarrior for 2A03 Puritans Album
+ { 27, UNL_CC21 }, // Mihunche, but previously used for World Hero
+ { 28, UNL_ACTION53 }, // Multi-discrete PCB designed by Tepples for Action 53
+ { 29, SEALIE_CUFROM }, // homebrew PCB used by Glider
+ { 30, SEALIE_UNROM512 }, // UNROM 512 + Flash
+ { 31, UNL_2A03PURITANS }, // PCB designed by infinitelives & rainwarrior for 2A03 Puritans Album
{ 32, IREM_G101 },
{ 33, TAITO_TC0190FMC },
{ 34, STD_BXROM },
@@ -85,16 +86,16 @@ static const nes_mmc mmc_list[] =
{ 51, BMC_BALLGAMES_11IN1 },
{ 52, BMC_GOLD_7IN1 },
{ 53, SVISION16_BOARD },
- { 54, BMC_NOVEL1 },
- // 55 Genius SMB - No info (nor images) available
+ { 54, BMC_21IN1 }, // duplicate of mapper 201, though possibly should be "Unused"
+ { 55, UNL_MMALEE }, // Genius SMB
{ 56, KAISER_KS202 },
{ 57, BMC_GKA },
{ 58, BMC_GKB },
- // 59 Unused
- // 60 4-in-1, 35-in-1 Reset based
+ { 59, BMC_VT5201 }, // and BMC-T3H53, BMC-D1038
+ { 60, BMC_4IN1RESET },
{ 61, RCM_TF9IN1 },
{ 62, BMC_SUPER_700IN1 },
- { 63, BMC_CH001 }, // Powerful 255
+ { 63, BMC_TH22913 }, // Powerful 250/255
{ 64, TENGEN_800032 },
{ 65, IREM_H3001 },
{ 66, STD_GXROM },
@@ -112,8 +113,8 @@ static const nes_mmc mmc_list[] =
{ 78, IREM_HOLYDIVR },
{ 79, AVE_NINA06 },
{ 80, TAITO_X1_005 },
- // 81 Unused
- { 82, TAITO_X1_017 },
+ { 81, NTDEC_N715021 }, // 81 Super Gun
+ // 82 Taito X1-017 mapper for old mis-ordered PRG dumps
{ 83, CONY_BOARD },
// 84 Pasofami hacked images?
{ 85, KONAMI_VRC7 },
@@ -122,7 +123,7 @@ static const nes_mmc mmc_list[] =
{ 88, NAMCOT_34X3 },
{ 89, SUNSOFT_2 },
{ 90, JYCOMPANY_A },
- { 91, UNL_MK2 },
+ { 91, UNL_JY830623C },
{ 92, JALECO_JF19 },
{ 93, SUNSOFT_2 },
{ 94, STD_UN1ROM },
@@ -134,15 +135,16 @@ static const nes_mmc mmc_list[] =
// 100 images hacked to work with nesticle?
// 101 Unused (Urusei Yatsura had been assigned to this mapper, but it's Mapper 87)
// 102 Unused
- { 103, UNL_2708 }, // 103 Bootleg cart 2708 (Doki Doki Panic - FDS Conversion) - Unsupported
+ { 103, UNL_2708 }, // 103 Bootleg cart 2708 (Doki Doki Panic - FDS Conversion)
{ 104, CAMERICA_GOLDENFIVE },
{ 105, STD_EVENT },
{ 106, BTL_SMB3 },
{ 107, MAGICSERIES_MD },
- { 108, WHIRLWIND_2706 },
+ { 108, UNL_LH28_LH54 }, // 108 has 4 variant boards
// 109 Unused
// 110 Unused
- // 111 Ninja Ryuukenden Chinese? - Unsupported
+ // 111 GTROM 512 + Flash, currently unsupported
+ // Old mapper 111: Ninja Ryukenden Chinese - currently supported in software list only
{ 112, NTDEC_ASDER },
{ 113, HES_BOARD },
{ 114, SUPERGAME_LIONKING },
@@ -155,11 +157,11 @@ static const nes_mmc mmc_list[] =
{ 121, KAY_BOARD },
// 122 Unused
{ 123, UNL_H2288 },
- // 124 Unused
- // 125 Unused
+ // 124 Super Game Mega Type III bootleg arcade board. Emulated in MAME as supergm3.
+ { 125, UNL_LH32 }, // Monty no Doki Doki Daidassou - FDS Conversion
{ 126, BMC_PJOY84 },
- // 127 Unused
- // 128 Unused
+ // 127 Double Dragon II Japan pirate. Dump available?
+ // 128 1994 Super HiK 4-in-1 pirate. Dump available?
// 129 Unused
// 130 Unused
// 131 Unused
@@ -173,7 +175,7 @@ static const nes_mmc mmc_list[] =
{ 139, SACHEN_8259C },
{ 140, JALECO_JF11 },
{ 141, SACHEN_8259A },
- { 142, KAISER_KS7032},
+ { 142, KAISER_KS7032 },
{ 143, SACHEN_TCA01 },
{ 144, AGCI_50282 },
{ 145, SACHEN_SA72007 },
@@ -186,15 +188,15 @@ static const nes_mmc mmc_list[] =
{ 152, DIS_74X161X161X32 },
{ 153, BANDAI_LZ93 },
{ 154, NAMCOT_34X3 },
- { 155, STD_SXROM_A }, // diff compared to MMC1 concern WRAM
+ { 155, STD_SXROM }, // same as mapper 1 but forces the use of MMC1A
{ 156, OPENCORP_DAOU306 },
{ 157, BANDAI_DATACH }, // Datach Reader games -> must go in the Datach subslot
{ 158, TENGEN_800037 },
{ 159, BANDAI_LZ93EX1 }, // with 24c01
{ 160, SACHEN_SA009 },
// 161 Unused
- { 162, WAIXING_FS304}, // not confirmed, but a lot of chinese releases use it like this...
- { 163, NANJING_BOARD},
+ { 162, WAIXING_FS304 }, // not confirmed, but a lot of chinese releases use it like this...
+ { 163, NANJING_BOARD },
{ 164, WAIXING_FFV },
{ 165, WAIXING_SH2 },
{ 166, SUBOR_TYPE1 },
@@ -205,15 +207,15 @@ static const nes_mmc mmc_list[] =
{ 171, KAISER_KS7058 },
{ 172, TXC_DUMARACING },
{ 173, TXC_MJBLOCK },
- // 174 Unused
- { 175, KAISER_KS7022},
+ { 174, BMC_2751 },
+ { 175, KAISER_KS7022 },
{ 176, UNL_XIAOZY },
{ 177, HENGG_SRICH },
{ 178, WAIXING_SGZLZ },
{ 179, HENGG_XHZS },
{ 180, UXROM_CC },
// 181 Unused
- { 182, HOSENKAN_BOARD },
+ { 182, SUPERGAME_LIONKING }, // duplicate of mapper 114
{ 183, BTL_SHUIGUAN },
{ 184, SUNSOFT_1 },
{ 185, STD_CNROM },
@@ -230,7 +232,7 @@ static const nes_mmc mmc_list[] =
{ 196, BTL_SBROS11 },
{ 197, UNL_SF3 },
{ 198, WAIXING_TYPE_F },
- { 199, WAIXING_TYPE_G },
+ { 199, WAIXING_TYPE_F1 },
{ 200, BMC_36IN1 },
{ 201, BMC_21IN1 },
{ 202, BMC_150IN1 },
@@ -244,14 +246,14 @@ static const nes_mmc mmc_list[] =
{ 210, NAMCOT_175 },
{ 211, JYCOMPANY_B },
{ 212, BMC_SUPERHIK_300IN1 },
- { 213, BMC_NOVEL2 },
+ { 213, BMC_GKB }, // duplicate of mapper 58
{ 214, BMC_SUPERGUN_20IN1 },
- { 215, SUPERGAME_BOOGERMAN },
+ { 215, UNL_8237 }, // and UNL_8237A
{ 216, RCM_GS2015 },
- { 217, BMC_GOLDENCARD_6IN1 },
+ { 217, BMC_500IN1 },
{ 218, NOCASH_NOCHR },
- // 219 UNL-A9746 (according to Cah4e3's code, no dump available (yet)
- // 220 Unused
+ { 219, UNL_A9746 },
+ // 220 Unused - reserved for emulator debugging
{ 221, UNL_N625092 },
{ 222, BTL_DRAGONNINJA },
{ 223, WAIXING_TYPE_I }, // (according to NEStopia source, it's MMC3 with more WRAM)
@@ -264,11 +266,11 @@ static const nes_mmc mmc_list[] =
{ 230, BMC_22GAMES },
{ 231, BMC_20IN1 },
{ 232, CAMERICA_BF9096 },
- { 233, BMC_SUPER22 },
+ { 233, BMC_42IN1RESET },
{ 234, AVE_MAXI15 },
- { 235, BMC_GOLD150 }, // 235 Golden Game x-in-1 - Unsupported
- // 236 Game 800-in-1 - Unsupported
- // 237 Unused
+ { 235, BMC_GOLD260 }, // 235 Golden Game x-in-1 games
+ { 236, BMC_70IN1 },
+ { 237, BMC_TELETUBBIES },
{ 238, UNL_603_5052 },
// 239 Unused
{ 240, CNE_SHLZ },
@@ -282,18 +284,264 @@ static const nes_mmc mmc_list[] =
// 248 Unused
{ 249, WAIXING_SECURITY },
{ 250, NITRA_TDA },
- // 251 Shen Hua Jian Yun III?? - Unsupported
+ // 251 Unused
{ 252, WAIXING_SGZ },
- // 253 Super 8-in-1 99 King Fighter?? - Unsupported
+ { 253, HENGG_SHJY3 },
{ 254, BTL_PIKACHUY2K },
- { 255, BMC_110IN1 },
+ { 255, BMC_72IN1 }, // duplicate of mapper 225
+
+ // NES 2.0
+ // 256 OneBus Famiclones
+ // 257 UNIF MAPR PEC-586?
+ { 258, UNL_158B },
+ { 259, BMC_F15 },
+ // 260 HP10xx/HP20xx multicarts?
+ { 261, BMC_810544C },
+ { 262, SACHEN_SHERO },
+ { 263, UNL_KOF97 },
+ { 264, YOKO_BOARD },
+ { 265, BMC_T262 },
+ { 266, UNL_CITYFIGHT },
+ { 267, BMC_EL861121C },
+ { 268, SMD133_BOARD },
+ // 269 mc_gx121 seems to be a PnP, but there are two actual multicarts for this mapper?
+ // 270 multicarts on OneBus Famiclones
+ // 271 TXC 4 in 1 MGC-026, not in nes.xml?
+ // 272 Akumajo Special bootleg not in nes.xml
+ // 273 Gremlins 2 bootleg, related to pirate gremlin2h or unk2?
+ { 274, BMC_80013B },
+ // 275 Unused
+ // 276 Unused
+ // 277 Unused
+ // 278 Unused
+ // 279 Unused
+ // 280 Unused
+ // 281 seems to be mc_sh4b and many other JY multicarts not in nes.xml?
+ // 282 more JY multicarts not in nes.xml?
+ { 283, RCM_GS2004 }, // and RCM_GS2013
+ // 284 UNL_DRIPGAME, not in nes.xml
+ { 285, BMC_A65AS },
+ { 286, BMC_BENSHIENG },
+ { 287, BMC_411120C },
+ { 288, BMC_GKCXIN1 },
+ { 289, BMC_60311C },
+ { 290, BMC_NTD_03 },
+ { 291, BMC_NT639 },
+ { 292, UNL_BMW8544 }, // Dragon Fighter by Flying Star
+ // 293 NewStar multicarts, do we have these in nes.xml?
+ { 294, BMC_FAMILY_4646 }, // FIXME: is this really exactly the same as mapper 134?
+ // 295 JY multicarts not yet in nes.xml
+ // 296 VT3x handhelds
+ { 297, TXC_22110 }, // 2-in-1 Uzi Lightgun
+ { 298, UNL_TF1201 }, // Lethal Weapon (Enforcers) pirate
+ { 299, BMC_11160 },
+ { 300, BMC_190IN1 },
+ { 301, BMC_8157 },
+ { 302, KAISER_KS7057 }, // Gyruss FDS conversion
+ { 303, KAISER_KS7017 }, // Almana no Kiseki FDS conversion
+ { 304, BTL_09034A }, // various FDS conversions
+ { 305, KAISER_KS7031 }, // Dracula II FDS conversion
+ { 306, KAISER_KS7016 }, // Exciting Basket FDS conversion
+ { 307, KAISER_KS7037 }, // Metroid FDS conversion
+ { 308, UNL_TH21311 }, // Batman (Sunsoft) pirate on VRC2 clone hardware
+ { 309, UNL_LH51 }, // Ai Senshi Nicol alt FDS conversion
+ // 310 variant of mapper 125?
+ // 311 Unused (previously assigned in error to a bad SMB2 pirate dump)
+ { 312, KAISER_KS7013B }, // Highway Star Kaiser bootleg
+ { 313, BMC_RESETTXROM },
+ { 314, BMC_64IN1NR },
+ // 315 820732C and 830134C multicarts, not in nes.xml?
+ // 316 Unused
+ // 317 Unused
+ // 318 Unused
+ { 319, BMC_HP898F },
+ { 320, BMC_830425C },
+ // 321 duplicate of 287?
+ { 322, BMC_K3033 },
+ { 323, FARID_SLROM8IN1 }, // homebrew 8-in-1
+ { 324, FARID_UNROM8IN1 }, // homebrew 8-in-1
+ { 325, UNL_MALISB }, // Super Mali Splash Bomb pirate hack
+ { 326, BTL_CONTRAJ },
+ // 327 BMC-10-24-C-A1 6-in-1
+ { 328, UNL_RT01 }, // test cart (Russia)
+ { 329, UNL_EDU2K },
+ { 330, BTL_L001 }, // Sangokushi II bootleg (retitled part III)
+ { 331, BMC_12IN1 },
+ { 332, BMC_WS },
+ { 333, BMC_8IN1 },
+ { 334, BMC_5IN1_1993 },
+ { 335, BMC_CTC09 },
+ { 336, BMC_K3046 },
+ { 337, BMC_CTC_12IN1 },
+ { 338, BMC_SA005A },
+ { 339, BMC_K3006 },
+ { 340, BMC_K3036 },
+ { 341, BMC_TJ03 },
+ // 342 COOLGIRL homebrew
+ // 343 reset-based 4-in-1 pirate?
+ // 344 3/6-in-1 GN-26 multicart, not in nes.xml
+ { 345, BMC_L6IN1 },
+ { 346, KAISER_KS7012 }, // Zanac alt FDS conversion
+ { 347, KAISER_KS7030 }, // Doki Doki Panic alt FDS conversion
+ { 348, BMC_830118C },
+ { 349, BMC_G146 },
+ { 350, BMC_891227 },
+ { 351, BMC_TECHLINE9IN1 },
+ { 352, KAISER_KS106C }, // 4-in-1
+ { 353, BMC_810305C }, // Super Mario Family multicart
+ { 354, BMC_FAM250 },
+ // 355 Hwang Shinwei 3-D Block etc, currently has unemulated PIC16C54
+ { 356, BMC_JY208 },
+ // 357 Bit Corp 4-in-1 (ID 4602)
+ // 358 JY multicarts, variant of mapper 282
+ // 359 BMC-SB-5013 multicarts
+ // 360 Bit Corp 31-in-1 (ID 3150) (has five accessible DIP switches!)
+ { 361, BMC_YY841101C },
+ { 362, BMC_830506C },
+ // 363 variant of mapper 358?
+ { 364, BMC_830832C },
+ // 365 is this asderp95 in nes.xml?
+ { 366, BMC_GN45 },
+ // 367 7-in-1 cart that is a close variant of mapper 205
+ { 368, BTL_YUNG08 }, // SMB2 FDS conversion
+ // 369 Super Mario Bros Party multicart
+ { 370, BMC_F600 }, // Golden Mario Party II multicart
+ // 371 Spanish PEC-586 computer main cart
+ { 372, BMC_SFC12 },
+ // 373 Super 4-in-1, not in nes.xml?
+ { 374, BMC_RESETSXROM },
+ // 375 135-in-1 2MB multicart
+ { 376, BMC_YY841155C },
+ { 377, BMC_EL860947C },
+ // 378 8-in-1 multicart, which one?
+ // 379 35-in-1 multicart, similar to mapper 38
+ { 380, BMC_970630C },
+ { 381, UNL_KN42 }, // 2-in-1 Big Nose games
+ { 382, BMC_830928C },
+ // 383 JY-014 multicart
+ // 384 4-in-1 VRC4 clone with Crisis Force
+ // 385 NTDEC 2779 5-in-1, not in nes.xml?
+ // 386 JY-090 multicart
+ // 387 various JY multicarts
+ // 388 various JY multicarts
+ { 389, CALTRON_9IN1 },
+ // 390 variant of mapper 236?
+ // 391 BS-110 MMC3 clone
+ { 392, BMC_00202650 },
+ { 393, BMC_820720C },
+ // 394 Realtec HSK007 multicart
+ // 395 Realtec 8210 multicarts
+ { 396, BMC_850437C },
+ // 397 JY-082 multicart, not in nes.xml?
+ // 398 JY-048 multicart, not in nes.xml?
+ { 399, BATMAP_000 }, // homebrew game Star Versus
+ // 400 retroUSB (Sealie?) 8-bit XMAS 2017
+ { 401, BMC_KC885 },
+ // 402 22-in-1 Olympic Games, not in nes.xml?
+ // 403 Tetris Family 19-in-1 that only works on Famiclones with 6502's BCD mode
+ { 404, BMC_JY012005 },
+ // 405 UMC UM6578 NES-on-a-chip games...PnPs?
+ // 406 homebrew game Haradius Zero
+ // 407 VT03 PnP
+ // 408 Konami PnP
+ { 409, SEALIE_DPCMCART }, // A Winner is You homebrew music cart
+ { 410, BMC_JY302 },
+ { 411, BMC_A88S1 },
+ // 412 INTV 10-in-1 PnP 2nd edition
+ { 413, BATMAP_SRRX }, // homebrew game Super Russian Roulette
+ // 414 9999999-in-1 multicart
+ { 415, BTL_0353 }, // Lucky (Roger) Rabbit FDS conversion
+ { 416, BMC_N32_4IN1 },
+ { 417, BTL_BATMANFS }, // "Fine Studio" Batman bootleg
+ { 418, UNL_LH42 }, // Highway Star Whirlwind Manu bootleg
+ // 419 VT03 PnPs
+ // 420 Kasheng A971210 board
+ // 421 JY SC871115C board
+ // 422 BS-300 etc multicarts related to mappers 126 and 534
+ // 423 Lexibook PnP
+ // 424 Lexibook PnP
+ // 425 Cube Tech PnP
+ // 426 PnP
+ // 427 PnP
+ { 428, BMC_TF2740 },
+ // 429 Milowork FCFC1 flash cartridge
+ // 430 MMC3-based 831031C/T-308 multicart
+ { 431, BMC_GN91B },
+ // 432 Realtec 8090
+ { 433, BMC_NC20MB },
+ { 434, BMC_S009 },
+ // 435 F-1002 multicart
+ // 436 VT02 PnP
+ { 437, BMC_TH2348 },
+ { 438, BMC_K3071 },
+ // 439 YS2309 multicart
+ // 440 Dongda Sonic REC-9388 educational computer
+ // 441 841026C and 850335C multicarts
+ // 442 "Golden Key" educational computer
+ // 443 NC3000M multicart
+ // 444 NC7000M multicart
+ // 445 DG574B MMC3-compatible multicart
+ // 446 Mindkids SMD172B_FPGA board
+ { 447, BMC_KL06 },
+ // 448 VRC4-based 830768C multicart
+ // 449 Super Games King multicart
+ // 450 VRC2-based YY841157C multicart
+ // 451 homebrew Haratyler HP/MP
+ { 452, BMC_DS927 },
+ // 453 Realtec 8042
+ // 454...511 Unused
+ { 512, SACHEN_ZGDH },
+ { 513, SACHEN_SA9602B },
+ // 514 seems to be for skaraok, currently set to UNKNOWN in nes.xml
+ // 515 Korean Family Noraebang karaoke cart with expansion cart, mic, and YM2413!
+ { 516, COCOMA_BOARD },
+ // 517 another Korean karaoke cart with mic
+ // 518 Subor UNL-DANCE2000 and a few others
+ { 519, UNL_EH8813A }, // Dr Mario II Chinese pirate
+ { 520, BTL_2YUDB },
+ { 521, DREAMTECH_BOARD }, // Korean Igo
+ { 522, UNL_LH10 }, // Fuuun Shaolin Kyo FDS conversion
+ // { 523, UNKNOWN }, likely fengshnb or a clone not yet in nes.xml
+ { 524, BTL_900218 }, // Lord of King pirate
+ { 525, KAISER_KS7021A }, // GetsuFumaDen pirate (and maybe a Contra?)
+ // 526 sangochu clone not yet in nes.xml?
+ { 527, UNL_AX40G }, // Fudou Myouou Den pirate
+ { 528, BMC_831128C }, // 1995 New Series Super 2-in-1
+ { 529, UNL_T230 }, // Datach Dragon Ball Z IV bootleg
+ { 530, UNL_AX5705 }, // Super Mario Bros Pocker Mali
+ // 531 Used by Asder PC-95 Famicom clone built into a keyboard
+ // 532 Emulator only mapper for Chinese version of sangoht2?
+ { 533, SACHEN_3014 }, // Dong Dong Nao II
+ // 534 Are these all PnPs? Is one mc_101 or a clone not in nes.xml?
+ { 535, UNL_LH53 }, // Nazo no Murasamejo FDS conversion
+ // 536 and 537 Waixing FS303, mapper 195 variants?
+ // { 538, BTL_60106416L }, Exciting Soccer bootleg, not in nes.xml (available baddump needs banks rearranged?)
+ { 539, BTL_PALTHENA }, // Hikari Shinwa (Kid Icarus) FDS conversion
+ // 540 for mstrfgt6 in nes.xml or a variant of it not in nes.xml?
+ { 541, BMC_LITTLECOM160 },
+ // 542 Chairman Mao's 100th anniversary cart? You've got to be kidding me.
+ { 543, BMC_SRPG_5IN1 },
+ // 544 another alt of sango2ht/sanguo2a?
+ // 545 4 in 1 (ST-80) multicart, not in nes.xml?
+ // 546 10 in 1 Tenchi wo Kurau multicart, not in nes.xml?
+ // 547 Konami QTa adapter games
+ // { 548, BTL_CTC15 }, // Almana no Kiseki alt FDS conversion (dump available?)
+ { 549, KAISER_KS7016B }, // Meikyuu Jiin Dababa alt FDS conversion
+ { 550, BMC_JY820845C },
+ { 551, JNCOTA_KT1001 },
+ { 552, TAITO_X1_017 },
+ { 553, SACHEN_3013 }, // Dong Dong Nao 1
+ { 554, KAISER_KS7010 }, // Akumajo Dracula FDS conversion
+ { 555, STD_EVENT2 },
+ // 556 JY-215 multicart
+ { 557, UNL_LG25 }, // Moero TwinBee FDS conversion
+ // 558 some games on YC-03-09 board (related to mappers 162-164)
+ // 559...4095 Unused
};
const nes_mmc *nes_mapper_lookup( int mapper )
{
- int i;
-
- for (i = 0; i < ARRAY_LENGTH(mmc_list); i++)
+ for (int i = 0; i < std::size(mmc_list); i++)
{
if (mmc_list[i].iNesMapper == mapper)
return &mmc_list[i];
@@ -342,7 +590,8 @@ void nes_cart_slot_device::call_load_ines()
uint32_t vram_size = 0, prgram_size = 0, battery_size = 0, mapper_sram_size = 0;
uint32_t prg_size, vrom_size;
uint8_t header[0x10];
- uint8_t mapper, submapper = 0, local_options;
+ uint16_t mapper;
+ uint8_t submapper = 0, local_options;
bool ines20 = false, prg16k;
std::string mapinfo;
int pcb_id = 0, mapint1 = 0, mapint2 = 0, mapint3 = 0, mapint4 = 0;
@@ -370,8 +619,9 @@ void nes_cart_slot_device::call_load_ines()
// probably the header got corrupted: don't trust upper bits for mapper
break;
- case 0x8: // it's iNES 2.0 format
+ case 0x8: // it's NES 2.0 format
ines20 = true;
+ [[fallthrough]];
case 0x0:
default:
mapper |= header[7] & 0xf0;
@@ -402,25 +652,42 @@ void nes_cart_slot_device::call_load_ines()
logerror("NES: No extrainfo found\n");
}
- // use extended iNES2.0 info if available!
+ // use extended NES 2.0 info if available!
if (ines20)
{
mapper |= (header[8] & 0x0f) << 8;
// read submappers (based on 20140116 specs)
- submapper = (header[8] & 0xf0 >> 8);
- prg_size += ((header[9] & 0x0f) << 8) * 0x4000;
- vrom_size += ((header[9] & 0xf0) << 4) * 0x2000;
+ submapper = (header[8] & 0xf0) >> 4;
+
+ // NES 2.0's extended exponential sizes, needed for loading PRG >= 64MB, CHR >= 32MB. These bizarrely go up to 7 * 2^63!
+ auto expsize = [] (u8 byte) { return (2*(byte & 0x03) + 1) << (byte >> 2); };
+
+ if ((header[9] & 0x0f) == 0x0f)
+ {
+ prg_size = expsize(header[4]);
+ if (prg_size == 0) // 0 only on overflow
+ fatalerror("NES 2.0 PRG size >= 4GB is unsupported.\n");
+ }
+ else
+ prg_size += ((header[9] & 0x0f) << 8) * 0x4000;
+
+ if ((header[9] & 0xf0) == 0xf0)
+ {
+ vrom_size = expsize(header[5]);
+ if (vrom_size == 0) // 0 only on overflow
+ fatalerror("NES 2.0 CHR size >= 4GB is unsupported.\n");
+ }
+ else
+ vrom_size += ((header[9] & 0xf0) << 4) * 0x2000;
}
ines_mapr_setup(mapper, &pcb_id);
// handle submappers
if (submapper)
{
- // 001: MMC1
- if (mapper == 1 && submapper == 3)
- pcb_id = STD_SXROM_A;
- else if (mapper == 1 && submapper == 5)
- logerror("Unimplemented iNES2.0 submapper: SEROM/SHROM/SH1ROM.\n");
+ // 001: MMC1 (other submappers are deprecated)
+ if (mapper == 1 && submapper == 5)
+ logerror("Unimplemented NES 2.0 submapper: SEROM/SHROM/SH1ROM.\n");
// 002, 003, 007: UxROM, CNROM, AxROM
else if (mapper == 2 && submapper == 2)
bus_conflict = true;
@@ -469,7 +736,7 @@ void nes_cart_slot_device::call_load_ines()
else if (mapper == 68 && submapper == 1)
{
submapper = 0;
- logerror("Unimplemented iNES2.0 submapper: SUNSOFT-DCS.\n");
+ logerror("Unimplemented NES 2.0 submapper: SUNSOFT-DCS.\n");
}
// iNES Mapper 071
else if (mapper == 71 && submapper == 1)
@@ -484,6 +751,11 @@ void nes_cart_slot_device::call_load_ines()
else if (submapper == 3)
pcb_id = IREM_HOLYDIVR;
}
+ // iNES Mapper 116
+ else if (mapper == 116 && submapper == 2)
+ {
+ pcb_id = SOMARI_HUANG2; // Mapper 116 is used for 2 diff boards
+ }
// iNES Mapper 185
else if (mapper == 185)
{
@@ -491,15 +763,50 @@ void nes_cart_slot_device::call_load_ines()
m_cart->set_ce(0x03, ce_state);
}
// iNES Mapper 232
- else if (mapper == 210 && submapper == 1)
+ else if (mapper == 232 && submapper == 1)
{
- submapper = 0;
- logerror("Unimplemented iNES2.0 submapper: CAMERICA-BF9096.\n");
+ pcb_id = CAMERICA_BF9096_ALT;
+ }
+ // 268: SMD133 boards
+ else if (mapper == 268)
+ {
+ if (submapper == 0)
+ m_cart->set_smd133_addr(0x6000);
+ else if (submapper == 1)
+ m_cart->set_smd133_addr(0x5000);
+ else
+ logerror("Unimplemented NES 2.0 submapper: %d\n", submapper);
+ }
+ // 313: BMC RESET-TXROM
+ else if (mapper == 313)
+ {
+ if (submapper == 0)
+ {
+ m_cart->set_outer_prg_size(128);
+ m_cart->set_outer_chr_size(128);
+ }
+ else if (submapper == 1)
+ {
+ m_cart->set_outer_prg_size(256);
+ m_cart->set_outer_chr_size(128);
+ }
+ else if (submapper == 2)
+ {
+ m_cart->set_outer_prg_size(128);
+ m_cart->set_outer_chr_size(256);
+ }
+ else if (submapper == 3)
+ {
+ m_cart->set_outer_prg_size(256);
+ m_cart->set_outer_chr_size(256);
+ }
+ else
+ logerror("Unimplemented NES 2.0 submapper: %d\n", submapper);
}
else if (submapper)
{
submapper = 0;
- logerror("Undocumented iNES2.0 submapper, please report it to the MESS boards!\n");
+ logerror("Undocumented NES 2.0 submapper, please report it to the MAME boards!\n");
}
}
@@ -509,7 +816,13 @@ void nes_cart_slot_device::call_load_ines()
if (BIT(local_options, 1))
battery_size = NES_BATTERY_SIZE; // with original iNES format we can only support 8K WRAM battery
m_cart->set_trainer(BIT(local_options, 2) ? true : false);
- m_cart->set_four_screen_vram(BIT(local_options, 3) ? true : false);
+
+ // A select few boards or their variants have on-cart RAM to support 4-screen mirroring
+ if ((BIT(local_options, 3) && (m_pcb_id == STD_TXROM || m_pcb_id == NAMCOT_34X3)) || m_pcb_id == IREM_LROG017 || m_pcb_id == SACHEN_SHERO)
+ {
+ m_cart->set_four_screen_vram(true);
+ m_cart->set_mirroring(PPU_MIRROR_4SCREEN);
+ }
if (ines20)
{
@@ -545,6 +858,13 @@ void nes_cart_slot_device::call_load_ines()
}
break;
+ case STD_SXROM:
+ if (mapper == 1 && ines20 && prgram_size == 0x2000 && battery_size == 0x2000 && vrom_size == 0x4000)
+ m_pcb_id = STD_SZROM;
+ if (mapper == 155)
+ m_cart->set_mmc1_type(device_nes_cart_interface::mmc1_type::MMC1A);
+ break;
+
case NOCASH_NOCHR:
// this mapper uses mirroring flags differently
m_cart->set_four_screen_vram(false);
@@ -565,6 +885,28 @@ void nes_cart_slot_device::call_load_ines()
}
break;
+ case SEALIE_UNROM512:
+ // this mapper also uses mirroring flags differently
+ m_cart->set_four_screen_vram(false);
+ switch (local_options & 0x09)
+ {
+ case 0x00:
+ m_cart->set_mirroring(PPU_MIRROR_HORZ);
+ break;
+ case 0x01:
+ m_cart->set_mirroring(PPU_MIRROR_VERT);
+ break;
+ case 0x08:
+ m_cart->set_mirroring(PPU_MIRROR_LOW);
+ m_cart->set_pcb_ctrl_mirror(true);
+ break;
+ case 0x09:
+ m_cart->set_mirroring(PPU_MIRROR_4SCREEN);
+ m_cart->set_four_screen_vram(true);
+ break;
+ }
+ break;
+
case STD_CNROM:
if (mapper == 185 && !submapper)
{
@@ -613,6 +955,10 @@ void nes_cart_slot_device::call_load_ines()
m_cart->set_vrc_lines(0, 1, 0);
break;
+ case KONAMI_VRC7:
+ m_cart->set_vrc_lines((crc_hack || submapper == 2) ? 4 : 3, 0, 0);
+ break;
+
case IREM_G101:
if (crc_hack && !submapper)
m_cart->set_mirroring(PPU_MIRROR_HIGH); // Major League has hardwired mirroring
@@ -634,6 +980,33 @@ void nes_cart_slot_device::call_load_ines()
m_cart->set_pcb_ctrl_mirror(true);
break;
+ case CONY_BOARD:
+ if (submapper == 0 || submapper == 2)
+ pcb_id = CONY1K_BOARD;
+ break;
+
+ case UNL_LH28_LH54:
+ if (vrom_size)
+ m_pcb_id = (vrom_size == 0x4000) ? UNL_LE05 : UNL_LH31;
+ else if (!BIT(local_options, 0))
+ m_pcb_id = UNL_DH08;
+ break;
+
+ case UNL_8237:
+ if (submapper == 1)
+ m_pcb_id = UNL_8237A;
+ break;
+
+ case BMC_70IN1:
+ if (vrom_size == 0)
+ m_pcb_id = BMC_800IN1;
+ break;
+
+ case RCM_GS2004:
+ if (prg_size >= 0x50000)
+ m_pcb_id = RCM_GS2013;
+ break;
+
case HES_BOARD:
if (crc_hack)
m_cart->set_pcb_ctrl_mirror(true); // Mapper 113 is used for 2 diff boards
@@ -664,11 +1037,6 @@ void nes_cart_slot_device::call_load_ines()
m_pcb_id = WAIXING_DQ8; // Mapper 242 is used for 2 diff boards
break;
- case BMC_GOLD_7IN1:
- if (crc_hack)
- m_pcb_id = BMC_MARIOPARTY_7IN1; // Mapper 52 is used for 2 diff boards
- break;
-
case BTL_MARIOBABY:
if (crc_hack)
m_pcb_id = BTL_AISENSHINICOL; // Mapper 42 is used for 2 diff boards
@@ -687,7 +1055,16 @@ void nes_cart_slot_device::call_load_ines()
case NAMCOT_163:
mapper_sram_size = m_cart->get_mapper_sram_size();
break;
- //FIXME: we also have to fix Action 52 PRG loading somewhere...
+
+ case BMC_EL860947C:
+ m_cart->set_outer_prg_size(128);
+ break;
+
+ case BMC_EL861121C:
+ m_cart->set_outer_prg_size(256);
+ break;
+
+ //FIXME: we also have to fix Action 52 PRG loading somewhere...
case BANDAI_DATACH:
fatalerror("Bandai Datach games have to be mounted in the Datach subslot!\n");
@@ -698,42 +1075,38 @@ void nes_cart_slot_device::call_load_ines()
m_cart->set_bus_conflict(bus_conflict);
// SETUP step 4: logging what we have found
- if (!ines20)
- {
- logerror("Loaded game in iNES format:\n");
- logerror("-- Mapper %u\n", mapper);
- logerror("-- PRG 0x%x (%d x 16k chunks)\n", prg_size, prg_size / 0x4000);
- logerror("-- VROM 0x%x (%d x 8k chunks)\n", vrom_size, vrom_size / 0x2000);
- logerror("-- VRAM 0x%x (%d x 8k chunks)\n", vram_size, vram_size / 0x2000);
- logerror("-- Mirroring %s\n", BIT(header[6], 0) ? "Vertical" : "Horizontal");
- if (battery_size)
- logerror("-- Battery found\n");
- if (m_cart->get_trainer())
- logerror("-- Trainer found\n");
- if (m_cart->get_four_screen_vram())
- logerror("-- 4-screen VRAM\n");
- logerror("-- TV System: %s\n", ((header[10] & 3) == 0) ? "NTSC" : (header[10] & 1) ? "Both NTSC and PAL" : "PAL");
- }
- else
+ logerror("Loaded game in %s format:\n", ines20 ? "NES 2.0" : "iNES");
+ logerror("-- Mapper: %u\n", mapper);
+ if (ines20)
+ logerror("-- Submapper: %u\n", header[8] >> 4);
+ logerror("-- PRG 0x%x (%d x 16k chunks)\n", prg_size, prg_size / 0x4000);
+ logerror("-- VROM 0x%x (%d x 8k chunks)\n", vrom_size, vrom_size / 0x2000);
+ logerror("-- VRAM 0x%x (%d x 8k chunks)\n", vram_size, vram_size / 0x2000);
+ logerror("-- Mirroring: %s\n", BIT(header[6], 0) ? "Vertical" : "Horizontal");
+ if (battery_size)
+ logerror("-- Battery found\n");
+ if (m_cart->get_trainer())
+ logerror("-- Trainer found\n");
+ if (m_cart->get_four_screen_vram())
+ logerror("-- 4-screen VRAM\n");
+ if (ines20)
{
- logerror("Loaded game in Extended iNES format:\n");
- logerror("-- Mapper: %u\n", mapper);
- logerror("-- Submapper: %u\n", (header[8] & 0xf0) >> 4);
- logerror("-- PRG 0x%x (%d x 16k chunks)\n", prg_size, prg_size / 0x4000);
- logerror("-- VROM 0x%x (%d x 8k chunks)\n", vrom_size, vrom_size / 0x2000);
- logerror("-- VRAM 0x%x (%d x 8k chunks)\n", vram_size, vram_size / 0x2000);
- logerror("-- PRG NVWRAM: %d\n", (header[10] & 0xf0) >> 4);
+ logerror("-- PRG NVWRAM: %d\n", header[10] >> 4);
logerror("-- PRG WRAM: %d\n", header[10] & 0x0f);
- logerror("-- CHR NVWRAM: %d\n", (header[11] & 0xf0) >> 4);
+ logerror("-- CHR NVWRAM: %d\n", header[11] >> 4);
logerror("-- CHR WRAM: %d\n", header[11] & 0x0f);
- logerror("-- TV System: %s\n", (header[12] & 2) ? "Both NTSC and PAL" : (header[12] & 1) ? "PAL" : "NTSC");
+
+ static const char *timing[] = { "NTSC", "PAL", "Multi-region", "Dendy" };
+ logerror("-- CPU/PPU Timing: %s\n", timing[header[12] & 3]);
}
+ else
+ logerror("-- TV System: %s\n", ((header[10] & 3) == 0) ? "NTSC" : (header[10] & 1) ? "Both NTSC and PAL" : "PAL");
// 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())
@@ -823,7 +1196,8 @@ void nes_cart_slot_device::call_load_ines()
const char * nes_cart_slot_device::get_default_card_ines(get_default_card_software_hook &hook, const uint8_t *ROM, uint32_t len) const
{
- uint8_t mapper, submapper = 0;
+ uint16_t mapper;
+ uint8_t submapper = 0;
bool ines20 = false;
std::string mapinfo;
int pcb_id = 0, mapint1 = 0, mapint2 = 0, mapint3 = 0, mapint4 = 0;
@@ -838,8 +1212,9 @@ const char * nes_cart_slot_device::get_default_card_ines(get_default_card_softwa
// probably the header got corrupted: don't trust upper bits for mapper
break;
- case 0x8: // it's iNES 2.0 format
+ case 0x8: // it's NES 2.0 format
ines20 = true;
+ [[fallthrough]];
case 0x0:
default:
mapper |= ROM[7] & 0xf0;
@@ -857,12 +1232,12 @@ const char * nes_cart_slot_device::get_default_card_ines(get_default_card_softwa
}
}
- // use extended iNES2.0 info if available!
+ // use extended NES 2.0 info if available!
if (ines20)
{
mapper |= (ROM[8] & 0x0f) << 8;
// read submappers (based on 20140116 specs)
- submapper = (ROM[8] & 0xf0 >> 8);
+ submapper = (ROM[8] & 0xf0) >> 4;
}
ines_mapr_setup(mapper, &pcb_id);
@@ -870,11 +1245,9 @@ const char * nes_cart_slot_device::get_default_card_ines(get_default_card_softwa
// handle submappers
if (submapper)
{
- // 001: MMC1
- if (mapper == 1 && submapper == 3)
- pcb_id = STD_SXROM_A;
- else if (mapper == 1 && submapper == 5)
- logerror("Unimplemented iNES2.0 submapper: SEROM/SHROM/SH1ROM.\n");
+ // 001: MMC1 (other submappers are deprecated)
+ if (mapper == 1 && submapper == 5)
+ logerror("Unimplemented NES 2.0 submapper: SEROM/SHROM/SH1ROM.\n");
// 021, 023, 025: VRC4 / VRC2
else if (mapper == 21 || mapper == 23 || mapper == 25)
{
@@ -899,6 +1272,16 @@ const char * nes_cart_slot_device::get_default_card_ines(get_default_card_softwa
else if (submapper == 3)
pcb_id = IREM_HOLYDIVR;
}
+ // iNES Mapper 116
+ else if (mapper == 116 && submapper == 2)
+ {
+ pcb_id = SOMARI_HUANG2; // Mapper 116 is used for 2 diff boards
+ }
+ // iNES Mapper 232
+ else if (mapper == 232 && submapper == 1)
+ {
+ pcb_id = CAMERICA_BF9096_ALT;
+ }
}
// solve mapper conflicts
@@ -909,6 +1292,12 @@ const char * nes_cart_slot_device::get_default_card_ines(get_default_card_softwa
pcb_id = STD_NROM368;
break;
+ case STD_SXROM:
+ // only A Ressha de Ikou uses SZROM and it can be detected by its profile: 8K WRAM, 8K BWRAM, 16K CHR ROM
+ if (mapper == 1 && ines20 && ROM[10] == 0x77 && ROM[5] == 2)
+ pcb_id = STD_SZROM;
+ break;
+
case KONAMI_VRC2:
if (mapper == 23 && crc_hack && !submapper)
pcb_id = KONAMI_VRC4; // this allows for konami_irq to be installed at reset
@@ -934,15 +1323,37 @@ const char * nes_cart_slot_device::get_default_card_ines(get_default_card_softwa
pcb_id = WAIXING_DQ8; // Mapper 242 is used for 2 diff boards
break;
- case BMC_GOLD_7IN1:
- if (crc_hack)
- pcb_id = BMC_MARIOPARTY_7IN1; // Mapper 52 is used for 2 diff boards
- break;
-
case BTL_MARIOBABY:
if (crc_hack)
pcb_id = BTL_AISENSHINICOL; // Mapper 42 is used for 2 diff boards
break;
+
+ case CONY_BOARD:
+ if (submapper == 0 || submapper == 2)
+ pcb_id = CONY1K_BOARD; // Mapper 83 is used for 3 diff boards
+ break;
+
+ case UNL_LH28_LH54: // Mapper 108 is used for 4 diff boards
+ if (ROM[5])
+ pcb_id = (ROM[5] == 2) ? UNL_LE05 : UNL_LH31;
+ else if (!BIT(ROM[6], 0))
+ pcb_id = UNL_DH08;
+ break;
+
+ case UNL_8237: // Mapper 215 is used for 2 diff boards
+ if (submapper == 1)
+ pcb_id = UNL_8237A;
+ break;
+
+ case BMC_70IN1: // Mapper 236 is used for 2 diff boards
+ if (ROM[5] == 0)
+ pcb_id = BMC_800IN1;
+ break;
+
+ case RCM_GS2004: // Mapper 283 is used for 2 diff boards
+ if (ROM[4] >= 20)
+ pcb_id = RCM_GS2013;
+ break;
}
return nes_get_slot(pcb_id);
diff --git a/src/devices/bus/nes/nes_pcb.hxx b/src/devices/bus/nes/nes_pcb.hxx
index e26bd71dfd2..d9b63863b04 100644
--- a/src/devices/bus/nes/nes_pcb.hxx
+++ b/src/devices/bus/nes/nes_pcb.hxx
@@ -32,8 +32,7 @@ static const nes_pcb pcb_list[] =
{ "un1rom", STD_UN1ROM },
{ "sxrom", STD_SXROM },
{ "sorom", STD_SOROM },
- { "sxrom_a", STD_SXROM_A },
- { "sorom_a", STD_SOROM_A },
+ { "szrom", STD_SZROM },
{ "txrom", STD_TXROM },
{ "hkrom", STD_HKROM },
{ "tqrom", STD_TQROM },
@@ -43,6 +42,7 @@ static const nes_pcb pcb_list[] =
{ "pal_zz", PAL_ZZ },
{ "nes_qj", NES_QJ },
{ "nes_event", STD_EVENT },
+ { "nes_event2", STD_EVENT2 },
{ "discrete_74x139", DIS_74X139X74 },
{ "discrete_74x377", DIS_74X377 },
{ "discrete_74x161", DIS_74X161X161X32 },
@@ -102,20 +102,25 @@ static const nes_pcb pcb_list[] =
{ "maxi15", AVE_MAXI15 },
{ "bf9093", CAMERICA_BF9093 },
{ "bf9096", CAMERICA_BF9096 },
+ { "bf9096a", CAMERICA_BF9096_ALT },
{ "goldenfive", CAMERICA_GOLDENFIVE },
{ "ade" , CAMERICA_ALADDIN },
{ "cne_decathl", CNE_DECATHLON },
{ "cne_fsb", CNE_FSB },
{ "cne_shlz", CNE_SHLZ },
+ { "cocoma", COCOMA_BOARD },
{ "nanjing", NANJING_BOARD }, // mapper 163
{ "ntdec_asder", NTDEC_ASDER }, // mapper 112
{ "ntdec_fh", NTDEC_FIGHTINGHERO }, // mapper 193
+ { "ntdec_n715021", NTDEC_N715021 }, // mapper 81
{ "sa009", SACHEN_SA009 },
{ "sa0036", SACHEN_SA0036 },
{ "sa0037", SACHEN_SA0037 },
{ "sa72007", SACHEN_SA72007 },
{ "sa72008", SACHEN_SA72008 },
{ "tca01", SACHEN_TCA01 },
+ { "s3013", SACHEN_3013 },
+ { "s3014", SACHEN_3014 },
{ "s8259a", SACHEN_8259A },
{ "s8259b", SACHEN_8259B },
{ "s8259c", SACHEN_8259C },
@@ -125,9 +130,9 @@ static const nes_pcb pcb_list[] =
{ "tcu01", SACHEN_TCU01 },
{ "tcu02", SACHEN_TCU02 },
{ "sa9602b", SACHEN_SA9602B },
- { "tengen_800008", TENGEN_800008 }, /* FIXME: Is this the same as mapper 3? */
{ "tengen_800032", TENGEN_800032 },
{ "tengen_800037", TENGEN_800037 },
+ { "txc_22110", TXC_22110 },
{ "txc_22211", TXC_22211 },
{ "txc_dumarc", TXC_DUMARACING },
{ "txc_mjblock", TXC_MJBLOCK },
@@ -140,12 +145,12 @@ static const nes_pcb pcb_list[] =
{ "waixing_d", WAIXING_TYPE_D },
{ "waixing_e", WAIXING_TYPE_E },
{ "waixing_f", WAIXING_TYPE_F },
+ { "waixing_f1", WAIXING_TYPE_F1 },
{ "waixing_g", WAIXING_TYPE_G },
{ "waixing_h", WAIXING_TYPE_H },
{ "waixing_h1", WAIXING_TYPE_H1 },
{ "waixing_i", WAIXING_TYPE_I },
{ "waixing_j", WAIXING_TYPE_J },
- { "waixing_sgz", WAIXING_SGZ },
{ "waixing_sgzlz", WAIXING_SGZLZ },
{ "waixing_sec", WAIXING_SECURITY },
{ "waixing_ffv", WAIXING_FFV },
@@ -155,22 +160,27 @@ static const nes_pcb pcb_list[] =
{ "waixing_sh2", WAIXING_SH2 },
{ "fs304", WAIXING_FS304 }, // used in Zelda 3 by Waixing
{ "cony", CONY_BOARD },
+ { "cony1k", CONY1K_BOARD },
{ "yoko", YOKO_BOARD },
{ "hengg_srich", HENGG_SRICH },
{ "hengg_xhzs", HENGG_XHZS },
- { "hengg_shjy3", HENGG_SHJY3 }, // mapper 253
{ "hes", HES_BOARD },
- { "hosenkan", HOSENKAN_BOARD },
- { "ks7058", KAISER_KS7058 },
+ { "ks106c", KAISER_KS106C }, // mapper 352
{ "ks202", KAISER_KS202 }, // mapper 56
- { "ks7022", KAISER_KS7022 }, // mapper 175
- { "ks7017", KAISER_KS7017 },
- { "ks7032", KAISER_KS7032 }, // mapper 142
- { "ks7031", KAISER_KS7031 }, // used in Dracula II (FDS Conversion)
- { "ks7012", KAISER_KS7012 }, // used in Zanac (FDS Conversion)
- { "ks7013b", KAISER_KS7013B }, // used in Highway Star (FDS Conversion)
+ { "ks7010", KAISER_KS7010 }, // used in Akumajo Dracula (FDS Conversion)
+ { "ks7012", KAISER_KS7012 }, // used in Zanac (FDS Conversion)
+ { "ks7013b", KAISER_KS7013B }, // used in Highway Star Kaiser bootleg
{ "ks7016", KAISER_KS7016 }, // used in Exciting Basketball (FDS Conversion)
- { "ks7037", KAISER_KS7037 }, // Metroid FDS Chinese
+ { "ks7016b", KAISER_KS7016B }, // used in Meikyuu Jiin Dababa alt (FDS Conversion)
+ { "ks7017", KAISER_KS7017 },
+ { "ks7021a", KAISER_KS7021A }, // GetsuFumaDen pirate cart
+ { "ks7022", KAISER_KS7022 }, // mapper 175
+ { "ks7030", KAISER_KS7030 }, // used in Doki Doki Panic alt (FDS Conversion)
+ { "ks7031", KAISER_KS7031 }, // used in Dracula II (FDS Conversion)
+ { "ks7032", KAISER_KS7032 }, // mapper 142
+ { "ks7037", KAISER_KS7037 }, // Metroid (FDS Conversion)
+ { "ks7057", KAISER_KS7057 }, // Gyruss (FDS Conversion)
+ { "ks7058", KAISER_KS7058 },
{ "gs2015", RCM_GS2015 },
{ "gs2004", RCM_GS2004 },
{ "gs2013", RCM_GS2013 },
@@ -186,40 +196,62 @@ static const nes_pcb pcb_list[] =
{ "subor0", SUBOR_TYPE0 },
{ "subor1", SUBOR_TYPE1 },
{ "subor2", SUBOR_TYPE2 },
+ { "unl_158b", UNL_158B }, // Blood of Jurassic
{ "cc21", UNL_CC21 },
{ "xiaozy", UNL_XIAOZY },
{ "edu2k", UNL_EDU2K },
- { "t230", UNL_T230 },
- { "mk2", UNL_MK2 },
+ { "jy830623c", UNL_JY830623C },
{ "zemina", ZEMINA_BOARD },
- // misc bootleg boards
+ // misc VRC clone boards
+ { "btl_2yudb", BTL_2YUDB },
+ { "btl_900218", BTL_900218 }, // pirate The Lord of King
+ { "ax40g", UNL_AX40G },
{ "ax5705", UNL_AX5705 },
+ { "bmc_830506c", BMC_830506C },
+ { "bmc_831128c", BMC_831128C },
+ { "bmc_kl06", BMC_KL06 },
+ { "unl_cfight", UNL_CITYFIGHT },
+ { "hengg_shjy3", HENGG_SHJY3 }, // mapper 253
+ { "sgpipe", BTL_SHUIGUAN },
+ { "t230", UNL_T230 },
+ { "tf1201", UNL_TF1201 },
+ { "th21311", UNL_TH21311 },
+ { "waixing_sgz", WAIXING_SGZ },
+ // misc bootleg boards
{ "sc127", UNL_SC127 },
{ "mariobaby", BTL_MARIOBABY },
{ "asnicol", BTL_AISENSHINICOL },
{ "smb3pirate", BTL_SMB3 },
+ { "btl_contraj", BTL_CONTRAJ },
{ "btl_dninja", BTL_DRAGONNINJA },
- { "whirl2706", WHIRLWIND_2706 },
{ "smb2j", UNL_SMB2J },
{ "smb2ja", BTL_SMB2JA },
{ "smb2jb", BTL_SMB2JB },
+ { "yung08", BTL_YUNG08 },
+ { "btl_0353", BTL_0353 },
{ "09034a", BTL_09034A },
+ { "l001", BTL_L001 },
+ { "batmanfs", BTL_BATMANFS },
+ { "palthena", BTL_PALTHENA },
{ "tobidase", BTL_TOBIDASE }, // mapper 120
{ "dbz5", REXSOFT_DBZ5 },
{ "sl1632", REXSOFT_SL1632 },
{ "somari", SOMARI_SL12 }, // mapper 116
+ { "huang2", SOMARI_HUANG2 }, // mapper 116 also
{ "nitra", NITRA_TDA },
- { "ks7057", UNL_KS7057 }, // mapper 196 alt (for Street Fighter VI / Fight Street VI },
+ { "bmw8544", UNL_BMW8544 },
+ { "fs6", UNL_FS6 }, // mapper 196 alt? (for Street Fighter VI / Fight Street VI },
{ "sbros11", BTL_SBROS11 },
{ "family4646", BMC_FAMILY_4646 },
{ "pikay2k", BTL_PIKACHUY2K }, // mapper 254
{ "8237", UNL_8237 },
+ { "8237a", UNL_8237A },
{ "sg_lionk", SUPERGAME_LIONKING },
{ "sg_boog", SUPERGAME_BOOGERMAN },
{ "kasing", KASING_BOARD },
{ "kay", KAY_BOARD },
{ "h2288", UNL_H2288 },
- { "unl_6035052", UNL_603_5052 }, // mapper 238?
+ { "unl_6035052", UNL_603_5052 }, // mapper 238
{ "txc_tw", TXC_TW },
{ "kof97", UNL_KOF97 },
{ "kof96", UNL_KOF96 },
@@ -228,28 +260,57 @@ static const nes_pcb pcb_list[] =
{ "benshieng", BMC_BENSHIENG },
{ "action52", ACTENT_ACT52 },
{ "caltron6in1", CALTRON_6IN1 },
+ { "caltron9in1", CALTRON_9IN1 },
{ "rumblestation", RUMBLESTATION_BOARD }, // mapper 46
{ "svision16", SVISION16_BOARD },
+ { "kn42", UNL_KN42 },
{ "n625092", UNL_N625092 },
{ "a65as", BMC_A65AS },
{ "t262", BMC_T262 },
- { "novel1", BMC_NOVEL1 },
- { "novel2", BMC_NOVEL2 }, // mapper 213... same as BMC-NOVELDIAMOND9999999IN1 board?
{ "studyngame", UNL_STUDYNGAME }, // mapper 39
{ "sgun20in1", BMC_SUPERGUN_20IN1 },
- { "bmc_vt5201", BMC_VT5201 }, // mapper 60 otherwise
- { "bmc_d1038", BMC_VT5201 }, // mapper 60?
- { "810544c", BMC_810544 },
+ { "bmc_vt5201", BMC_VT5201 }, // mapper 59
+ { "bmc_60311c", BMC_60311C },
+ { "bmc_80013b", BMC_80013B },
+ { "bmc_810544c", BMC_810544C },
+ { "bmc_82ab", BMC_82AB },
+ { "bmc_830425c", BMC_830425C },
+ { "bmc_830928c", BMC_830928C },
+ { "bmc_850437c", BMC_850437C },
+ { "bmc_891227", BMC_891227 },
+ { "bmc_970630c", BMC_970630C },
+ { "bmc_jy012005", BMC_JY012005 },
+ { "bmc_jy820845c", BMC_JY820845C },
+ { "srpg_5in1", BMC_SRPG_5IN1 },
+ { "n32_4in1", BMC_N32_4IN1 },
{ "ntd03", BMC_NTD_03 },
- { "bmc_gb63", BMC_G63IN1 },
+ { "bmc_ctc09", BMC_CTC09 },
+ { "bmc_ctc12in1", BMC_CTC_12IN1 },
+ { "bmc_ds927", BMC_DS927 },
+ { "bmc_fam250", BMC_FAM250 },
{ "bmc_gka", BMC_GKA },
{ "bmc_gkb", BMC_GKB },
+ { "bmc_gkcxin1", BMC_GKCXIN1 },
+ { "bmc_gn91b", BMC_GN91B },
+ { "bmc_hp898f", BMC_HP898F },
+ { "bmc_k1029", BMC_K1029 },
+ { "bmc_k3006", BMC_K3006 },
+ { "bmc_k3033", BMC_K3033 },
+ { "bmc_k3036", BMC_K3036 },
+ { "bmc_k3046", BMC_K3046 },
+ { "bmc_k3071", BMC_K3071 },
+ { "bmc_s009", BMC_S009 },
+ { "bmc_sa005a", BMC_SA005A },
+ { "bmc_tf2740", BMC_TF2740 },
+ { "bmc_th2348", BMC_TH2348 },
+ { "bmc_tj03", BMC_TJ03 },
{ "bmc_ws", BMC_WS },
{ "bmc_hik300", BMC_SUPERHIK_300IN1 },
{ "bmc_s700", BMC_SUPER_700IN1 },
{ "bmc_ball11", BMC_BALLGAMES_11IN1 },
{ "bmc_22games", BMC_22GAMES },
{ "bmc_64y2k", BMC_64IN1NR },
+ { "bmc_420y2k", BMC_TELETUBBIES },
{ "bmc_12in1", BMC_12IN1 },
{ "bmc_20in1", BMC_20IN1 },
{ "bmc_21in1", BMC_21IN1 },
@@ -260,75 +321,99 @@ static const nes_pcb pcb_list[] =
{ "bmc_70in1", BMC_70IN1 },
{ "bmc_72in1", BMC_72IN1 },
{ "bmc_76in1", BMC_76IN1 },
- { "bmc_s42in1", BMC_76IN1 },
- { "bmc_110in1", BMC_110IN1 },
{ "bmc_150in1", BMC_150IN1 },
{ "bmc_190in1", BMC_190IN1 },
+ { "bmc_500in1", BMC_500IN1 },
{ "bmc_800in1", BMC_800IN1 },
{ "bmc_1200in1", BMC_1200IN1 },
+ { "bmc_2751", BMC_2751 },
{ "bmc_8157", BMC_8157 },
{ "bmc_g146", BMC_G146 },
{ "bmc_11160", BMC_11160 },
+ { "a88s1", BMC_A88S1 },
+ { "bmc_el86xc", BMC_EL860947C },
{ "fk23c", BMC_FK23C },
{ "fk23ca", BMC_FK23CA },
+ { "nt639", BMC_NT639 },
+ { "resetsxrom", BMC_RESETSXROM },
+ { "resettxrom", BMC_RESETTXROM },
{ "s24in1c03", BMC_S24IN1SC03 },
+ { "smd133", SMD133_BOARD },
+ { "tech9in1", BMC_TECHLINE9IN1 },
+ { "bmc_5in1", BMC_5IN1_1993 },
+ { "bmc_8in1", BMC_8IN1 },
{ "bmc_15in1", BMC_15IN1 },
{ "bmc_sbig7in1", BMC_SUPERBIG_7IN1 },
{ "bmc_hik8in1", BMC_HIK8IN1 },
+ { "bmc_jy208", BMC_JY208 },
+ { "bmc_jy302", BMC_JY302 },
+ { "bmc_kc885", BMC_KC885 },
+ { "bmc_sfc12", BMC_SFC12 },
{ "bmc_hik4in1", BMC_SUPERHIK_4IN1 },
- { "bmc_mario7in1", BMC_MARIOPARTY_7IN1 },
+ { "bmc_f15", BMC_F15 },
+ { "bmc_f600", BMC_F600 },
+ { "bmc_gn45", BMC_GN45 },
{ "bmc_gold7in1", BMC_GOLD_7IN1 },
- { "bmc_gc6in1", BMC_GOLDENCARD_6IN1 },
+ { "bmc_l6in1", BMC_L6IN1 },
+ { "bmc_00202650", BMC_00202650 },
{ "bmc_411120c", BMC_411120C },
+ { "bmc_810305c", BMC_810305C },
+ { "bmc_820720c", BMC_820720C },
{ "bmc_830118c", BMC_830118C },
+ { "bmc_830832c", BMC_830832C },
+ { "bmc_yy841101c", BMC_YY841101C },
+ { "bmc_yy841155c", BMC_YY841155C },
{ "pjoy84", BMC_PJOY84 },
- { "bmc_gold150", BMC_GOLD150 },
{ "bmc_gold260", BMC_GOLD260 },
- { "bmc_power255", BMC_CH001 },
- { "bmc_s22games", BMC_SUPER22 },
+ { "bmc_th22913", BMC_TH22913 },
{ "bmc_reset4", BMC_4IN1RESET },
{ "bmc_reset42", BMC_42IN1RESET },
+ { "bmc_nc20mb", BMC_NC20MB },
+ { "bmc_lc160", BMC_LITTLECOM160 },
+ { "jncota_kt1001", JNCOTA_KT1001 },
{ "jyc_a", JYCOMPANY_A },
{ "jyc_b", JYCOMPANY_B },
{ "jyc_c", JYCOMPANY_C },
{ "tek90", JYCOMPANY_A },
{ "sa9602b", SACHEN_SA9602B },
- { "unl_shero", SACHEN_SHERO },
+ { "sachen_shero", SACHEN_SHERO },
+ { "sachen_zgdh", SACHEN_ZGDH },
+ { "a9746", UNL_A9746 },
{ "mmalee2", UNL_MMALEE },
{ "unl_2708", UNL_2708 },
+ { "unl_dh08", UNL_DH08 },
+ { "unl_le05", UNL_LE05 },
+ { "unl_lg25", UNL_LG25 },
{ "unl_lh10", UNL_LH10 },
+ { "unl_lh28_lh54", UNL_LH28_LH54 },
+ { "unl_lh31", UNL_LH31 },
{ "unl_lh32", UNL_LH32 },
+ { "unl_lh42", UNL_LH42 },
+ { "unl_lh51", UNL_LH51 },
{ "unl_lh53", UNL_LH53 },
{ "unl_ac08", UNL_AC08 },
- { "unl_bb", UNL_BB },
{ "unl_malisb", UNL_MALISB },
- { "sgpipe", BTL_SHUIGUAN },
{ "rt01", UNL_RT01 }, // Russian Test Cart
- { "unl_whero", UNL_WORLDHERO },
{ "unl_43272", UNL_43272 },
- { "tf1201", UNL_TF1201 },
- { "unl_cfight", UNL_CITYFIGHT },
+ { "ninjaryu", UNL_NINJARYU },
+ { "unl_eh8813a", UNL_EH8813A }, // Dr. Mario II
{ "nocash_nochr", NOCASH_NOCHR },
- { "nes_action53", BTL_ACTION53 },
- { "nes_2a03pur", BTL_2A03_PURITANS },
+ { "action53", UNL_ACTION53 },
+ { "batmap_000", BATMAP_000 },
+ { "batmap_srrx", BATMAP_SRRX },
+ { "8bitxmas", SEALIE_8BITXMAS },
+ { "cufrom", SEALIE_CUFROM },
+ { "dpcmcart", SEALIE_DPCMCART },
+ { "unrom512", SEALIE_UNROM512 },
+ { "2a03pur", UNL_2A03PURITANS },
+ { "farid_slrom8in1", FARID_SLROM8IN1 },
+ { "farid_unrom8in1", FARID_UNROM8IN1 },
{ "ffe3", FFE3_BOARD },
{ "ffe4", FFE4_BOARD },
{ "ffe8", FFE8_BOARD },
- { "8237a", UNSUPPORTED_BOARD },
- { "ninjaryu", UNSUPPORTED_BOARD },
{ "unl_dance", UNSUPPORTED_BOARD },
- { "bmc_hik_kof", UNSUPPORTED_BOARD },
{ "onebus", UNSUPPORTED_BOARD },
- { "coolboy", UNSUPPORTED_BOARD },
- { "btl_900218", UNSUPPORTED_BOARD }, // pirate The Lord of King, to be emulated soon
- { "a9746", UNSUPPORTED_BOARD },
{ "pec586", UNSUPPORTED_BOARD },
- { "bmc_f15", UNSUPPORTED_BOARD }, // 150-in-1 Unchained Melody
- { "bmc_hp898f", UNSUPPORTED_BOARD }, // Primasoft 9999999-in-1
- { "bmc_8in1", UNSUPPORTED_BOARD }, // Super 8-in-1 (Incl. Rockin' Kats)
- { "unl_eh8813a", UNSUPPORTED_BOARD }, // Dr. Mario II
- { "unl_158b", UNSUPPORTED_BOARD }, // Blood of Jurassic
- { "unl_drgnfgt", UNSUPPORTED_BOARD }, // Dragon Fighter by Flying Star
{ "test", TEST_BOARD },
{ "unknown", UNKNOWN_BOARD } // a few pirate dumps uses the wrong mapper...
};
@@ -337,7 +422,7 @@ static const nes_pcb *nes_pcb_lookup( const char *slot )
{
for (auto & elem : pcb_list)
{
- if (!core_stricmp(elem.slot_opt, slot))
+ if (!strcmp(elem.slot_opt, slot))
return &elem;
}
return nullptr;
@@ -577,6 +662,25 @@ void nes_cart_slot_device::call_load_pcb()
// osd_printf_error("VRC-6, pin9: A%d, pin10: A%d\n", nes_cart_get_line(get_feature("vrc6-pin9"), nes_cart_get_line(get_feature("vrc6-pin10"));
}
+ if (m_pcb_id == KONAMI_VRC7)
+ m_cart->set_vrc_lines(nes_cart_get_line(get_feature("vrc7-pin19")), 0, 0);
+
+ if (m_pcb_id == STD_SXROM || m_pcb_id == STD_SOROM)
+ {
+ if (get_feature("mmc1_type") != nullptr)
+ {
+ using mmc1_type = device_nes_cart_interface::mmc1_type;
+
+ const char *type = get_feature("mmc1_type");
+ if (!strcmp(type, "MMC1"))
+ m_cart->set_mmc1_type(mmc1_type::MMC1);
+ else if (!strcmp(type, "MMC1A"))
+ m_cart->set_mmc1_type(mmc1_type::MMC1A);
+ else if (!strncmp(type, "MMC1B", 5)) // common prefix of several variants
+ m_cart->set_mmc1_type(mmc1_type::MMC1B);
+ }
+ }
+
if (m_pcb_id == STD_HKROM || m_pcb_id == TAITO_X1_017)
mapper_sram_size = m_cart->get_mapper_sram_size();
@@ -592,6 +696,39 @@ void nes_cart_slot_device::call_load_pcb()
m_cart->set_n163_vol(n163_get_submapper_num(get_feature("n163-vol")));
}
+ // get address of SMD133 chip on boards that use it
+ if (m_pcb_id == SMD133_BOARD)
+ {
+ const char *addr = get_feature("smd133-addr");
+ int val = 6;
+
+ if (addr == nullptr || sscanf(addr, "%u%*c", &val) != 1 || val < 5 || val > 6)
+ logerror("Unexpected smd133-addr: %s\n", addr ? addr : "(nullptr)");
+ m_cart->set_smd133_addr(val * 0x1000);
+ }
+
+ // get outer PRG bank size for multicart boards that use this feature
+ if (m_pcb_id == BMC_EL860947C || m_pcb_id == BMC_RESETTXROM)
+ {
+ const char *size = get_feature("outer-prg-size");
+ int kbyte = 128;
+
+ if (size == nullptr || sscanf(size, "%u%*c", &kbyte) != 1 || kbyte & (kbyte - 1) || kbyte <= 0)
+ logerror("Unexpected outer-prg-size: %s\n", size ? size : "(nullptr)");
+ m_cart->set_outer_prg_size(kbyte);
+ }
+
+ // get outer CHR bank size for multicart boards that use this feature
+ if (m_pcb_id == BMC_RESETTXROM)
+ {
+ const char *size = get_feature("outer-chr-size");
+ int kbyte = 128;
+
+ if (size == nullptr || sscanf(size, "%u%*c", &kbyte) != 1 || kbyte & (kbyte - 1) || kbyte <= 0)
+ logerror("Unexpected outer-chr-size: %s\n", size ? size : "(nullptr)");
+ m_cart->set_outer_chr_size(kbyte);
+ }
+
// pirate variants of boards with bus conflict are often not suffering from it
// and actually games glitch if bus conflict is emulated...
@@ -605,7 +742,7 @@ void nes_cart_slot_device::call_load_pcb()
{
logerror("-- PCB: %s", get_feature("pcb"));
if (m_pcb_id == UNSUPPORTED_BOARD)
- logerror(" (currently not supported by MESS)");
+ logerror(" (currently not supported by MAME)");
logerror("\n");
}
logerror("-- PRG 0x%x (%d x 16k chunks)\n", prg_size, prg_size / 0x4000);
@@ -615,24 +752,31 @@ 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);
}
- // SETUP steps 7: allocate the remaining pointer, when needed
+ // SETUP steps 7: allocate pointers for any extra chip data, when needed
+ if (m_pcb_id == BATMAP_SRRX)
+ {
+ uint32_t dpcm_size = get_software_region_length("dpcm");
+ if (dpcm_size)
+ {
+ m_cart->misc_rom_alloc(dpcm_size);
+ memcpy(m_cart->get_misc_rom_base(), get_software_region("dpcm"), dpcm_size);
+ }
+ }
+
+ // SETUP steps 8: allocate the remaining pointers, when needed
if (vram_size)
m_cart->vram_alloc(vram_size);
if (prgram_size)
m_cart->prgram_alloc(prgram_size);
- // also nes_smb2j_device needs WRAM initialized to 0xff? check!
- if (m_pcb_id == UNL_SMB2J)
- memset(m_cart->get_prgram_base(), 0xff, prgram_size);
-
// Attempt to load a battery file for this ROM
// A few boards have internal RAM with a battery (MMC6, Taito X1-005 & X1-017, etc.)
if (battery_size || mapper_sram_size)
diff --git a/src/devices/bus/nes/nes_slot.cpp b/src/devices/bus/nes/nes_slot.cpp
index ab8235ccc55..d7df07d7693 100644
--- a/src/devices/bus/nes/nes_slot.cpp
+++ b/src/devices/bus/nes/nes_slot.cpp
@@ -107,7 +107,7 @@ DEFINE_DEVICE_TYPE(NES_CART_SLOT, nes_cart_slot_device, "nes_cart_slot", "NES Ca
//-------------------------------------------------
device_nes_cart_interface::device_nes_cart_interface(const machine_config &mconfig, device_t &device)
- : device_slot_card_interface(mconfig, device)
+ : device_interface(device, "nescart")
, m_prg(nullptr)
, m_vrom(nullptr)
, m_ciram(nullptr)
@@ -117,13 +117,20 @@ device_nes_cart_interface::device_nes_cart_interface(const machine_config &mconf
// main NES CPU here, even if it does not belong to this device.
, m_maincpu(*this, ":maincpu")
, m_mapper_sram(nullptr)
+ , m_misc_rom(nullptr)
, m_mapper_sram_size(0)
+ , m_misc_rom_size(0)
, m_ce_mask(0)
, m_ce_state(0)
+ , m_mmc1_type(mmc1_type::MMC1B)
, m_vrc_ls_prg_a(0)
, m_vrc_ls_prg_b(0)
, m_vrc_ls_chr(0)
- , m_mirroring(PPU_MIRROR_NONE)
+ , m_n163_vol(0)
+ , m_outer_prg_size(0)
+ , m_outer_chr_size(0)
+ , m_smd133_addr(0x6000)
+ , m_mirroring(PPU_MIRROR_HORZ)
, m_pcb_ctrl_mirror(false)
, m_four_screen_vram(false)
, m_has_trainer(false)
@@ -151,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)
@@ -167,26 +174,24 @@ void device_nes_cart_interface::prg_alloc(size_t size, const char *tag)
m_prg_chunks--;
}
- m_prg_mask = ((m_prg_chunks << 1) - 1);
+ m_prg_mask = (m_prg_chunks << 1) - 1;
// printf("first mask %x!\n", m_prg_mask);
if ((m_prg_chunks << 1) & m_prg_mask)
{
- int mask_bits = 0, temp = (m_prg_chunks << 1), mapsize;
+ int mask_bits = 0;
// contrary to what happens with later systems, like e.g. SNES or MD,
// only half a dozen of NES carts have PRG which is not a power of 2
// so we use this bank_map only as an exception
// printf("uneven rom!\n");
// 1. redefine mask as (next power of 2)-1
- for (; temp; )
- {
+ for (int temp = m_prg_chunks << 1; temp; temp >>= 1)
mask_bits++;
- temp >>= 1;
- }
+
m_prg_mask = (1 << mask_bits) - 1;
// printf("new mask %x!\n", m_prg_mask);
- mapsize = (1 << mask_bits)/2;
+ int mapsize = (1 << mask_bits) / 2;
// 2. create a bank_map for banks in the range mask/2 -> mask
m_prg_bank_map.resize(mapsize);
@@ -199,7 +204,7 @@ void device_nes_cart_interface::prg_alloc(size_t size, const char *tag)
while (j % mapsize)
{
int k = 0, repeat_banks;
- while ((j % (mapsize >> k)) && k < mask_bits)
+ while (j % (mapsize >> k) && k < mask_bits)
k++;
repeat_banks = j % (mapsize >> (k - 1));
for (int l = 0; l < repeat_banks; l++)
@@ -218,18 +223,25 @@ 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)
+{
+ if (m_misc_rom == nullptr)
+ {
+ m_misc_rom = device().machine().memory().region_alloc(device().subtag("^cart:misc_rom"), size, 1, ENDIANNESS_LITTLE)->base();
+ m_misc_rom_size = size;
+ }
+}
+
void device_nes_cart_interface::prgram_alloc(size_t size)
{
m_prgram.resize(size);
@@ -253,20 +265,20 @@ void device_nes_cart_interface::battery_alloc(size_t size)
inline int device_nes_cart_interface::prg_8k_bank_num(int bank_8k)
{
- if (m_prg_mask == ((m_prg_chunks << 1) - 1))
+ if (m_prg_mask == (m_prg_chunks << 1) - 1)
return bank_8k & m_prg_mask;
// only a few pirate games (less than a dozen) have PRG which is not power of 2
// so we treat it here separately, rather than forcing all games to use m_prg_bank_map
// case 1: if we are accessing a bank before the end of the image, just return that bank
- if (bank_8k < ((m_prg_chunks << 1) - 1))
+ if (bank_8k < (m_prg_chunks << 1) - 1)
return bank_8k;
// case 2: otherwise return a mirror using the bank_map!
// uint8_t temp = bank_8k;
bank_8k &= m_prg_mask;
- bank_8k -= (m_prg_mask/2 + 1);
+ bank_8k -= m_prg_mask / 2 + 1;
// printf("bank: accessed %x (top: %x), returned %x\n", temp, (m_prg_chunks << 1) - 1, m_prg_bank_map[bank_8k]);
return m_prg_bank_map[bank_8k];
}
@@ -276,8 +288,8 @@ inline void device_nes_cart_interface::update_prg_banks(int prg_bank_start, int
for (int prg_bank = prg_bank_start; prg_bank <= prg_bank_end; prg_bank++)
{
assert(prg_bank >= 0);
- assert(prg_bank < ARRAY_LENGTH(m_prg_bank));
- assert(prg_bank < ARRAY_LENGTH(m_prg_bank_mem));
+ assert(prg_bank < std::size(m_prg_bank));
+ assert(prg_bank < std::size(m_prg_bank_mem));
m_prg_bank_mem[prg_bank]->set_entry(m_prg_bank[prg_bank]);
}
@@ -285,11 +297,11 @@ inline void device_nes_cart_interface::update_prg_banks(int prg_bank_start, int
void device_nes_cart_interface::prg32(int bank)
{
- /* if there is only 16k PRG, return */
+ // if there is only 16k PRG, return
if (!(m_prg_chunks >> 1))
return;
- /* assumes that bank references a 32k chunk */
+ // assumes that bank references a 32k chunk
bank = prg_8k_bank_num(bank * 4);
m_prg_bank[0] = bank + 0;
@@ -301,7 +313,7 @@ void device_nes_cart_interface::prg32(int bank)
void device_nes_cart_interface::prg16_89ab(int bank)
{
- /* assumes that bank references a 16k chunk */
+ // assumes that bank references a 16k chunk
bank = prg_8k_bank_num(bank * 2);
m_prg_bank[0] = bank + 0;
@@ -311,7 +323,7 @@ void device_nes_cart_interface::prg16_89ab(int bank)
void device_nes_cart_interface::prg16_cdef(int bank)
{
- /* assumes that bank references a 16k chunk */
+ // assumes that bank references a 16k chunk
bank = prg_8k_bank_num(bank * 2);
m_prg_bank[2] = bank + 0;
@@ -319,48 +331,12 @@ void device_nes_cart_interface::prg16_cdef(int bank)
update_prg_banks(2, 3);
}
-void device_nes_cart_interface::prg8_89(int bank)
-{
- /* assumes that bank references an 8k chunk */
- bank = prg_8k_bank_num(bank);
-
- m_prg_bank[0] = bank;
- update_prg_banks(0, 0);
-}
-
-void device_nes_cart_interface::prg8_ab(int bank)
-{
- /* assumes that bank references an 8k chunk */
- bank = prg_8k_bank_num(bank);
-
- m_prg_bank[1] = bank;
- update_prg_banks(1, 1);
-}
-
-void device_nes_cart_interface::prg8_cd(int bank)
-{
- /* assumes that bank references an 8k chunk */
- bank = prg_8k_bank_num(bank);
-
- m_prg_bank[2] = bank;
- update_prg_banks(2, 2);
-}
-
-void device_nes_cart_interface::prg8_ef(int bank)
-{
- /* assumes that bank references an 8k chunk */
- bank = prg_8k_bank_num(bank);
-
- m_prg_bank[3] = bank;
- update_prg_banks(3, 3);
-}
-
-/* We also define an additional helper to map 8k PRG-ROM to one of the banks (passed as parameter) */
+// We define a parameterized helper to map 8k PRG-ROM to one of the banks
void device_nes_cart_interface::prg8_x(int start, int bank)
{
assert(start < 4);
- /* assumes that bank references an 8k chunk */
+ // assumes that bank references an 8k chunk
bank = prg_8k_bank_num(bank);
m_prg_bank[start] = bank;
@@ -371,110 +347,36 @@ void device_nes_cart_interface::prg8_x(int start, int bank)
// CHR helpers
//-------------------------------------------------
-inline void device_nes_cart_interface::chr_sanity_check( int source )
+void device_nes_cart_interface::bank_chr(int shift, int start, int bank, int source)
{
- if (source == CHRRAM && m_vram.empty())
- fatalerror("CHRRAM bankswitch with no VRAM\n");
-
- if (source == CHRROM && m_vrom == nullptr)
- fatalerror("CHRROM bankswitch with no VROM\n");
-}
-
-void device_nes_cart_interface::chr8(int bank, int source)
-{
- chr_sanity_check(source);
+ uint8_t *base_ptr;
+ uint32_t chr_chunks;
if (source == CHRRAM)
{
- bank &= (m_vram_chunks - 1);
- for (int i = 0; i < 8; i++)
- {
- m_chr_src[i] = source;
- m_chr_orig[i] = (bank * 0x2000) + (i * 0x400); // for save state uses!
- m_chr_access[i] = &m_vram[m_chr_orig[i]];
- }
- }
- else
- {
- bank &= (m_vrom_chunks - 1);
- for (int i = 0; i < 8; i++)
- {
- m_chr_src[i] = source;
- m_chr_orig[i] = (bank * 0x2000) + (i * 0x400); // for save state uses!
- m_chr_access[i] = &m_vrom[m_chr_orig[i]];
- }
- }
-}
-
-void device_nes_cart_interface::chr4_x(int start, int bank, int source)
-{
- chr_sanity_check(source);
+ assert(!m_vram.empty());
- if (source == CHRRAM)
- {
- bank &= ((m_vram_chunks << 1) - 1);
- for (int i = 0; i < 4; i++)
- {
- m_chr_src[i + start] = source;
- m_chr_orig[i + start] = (bank * 0x1000) + (i * 0x400); // for save state uses!
- m_chr_access[i + start] = &m_vram[m_chr_orig[i + start]];
- }
+ base_ptr = &m_vram[0];
+ chr_chunks = m_vram_chunks;
}
- else
+ else // source == CHRROM
{
- bank &= ((m_vrom_chunks << 1) - 1);
- for (int i = 0; i < 4; i++)
- {
- m_chr_src[i + start] = source;
- m_chr_orig[i + start] = (bank * 0x1000) + (i * 0x400); // for save state uses!
- m_chr_access[i + start] = &m_vrom[m_chr_orig[i + start]];
- }
- }
-}
-
-void device_nes_cart_interface::chr2_x(int start, int bank, int source)
-{
- chr_sanity_check(source);
+ assert(m_vrom != nullptr);
- if (source == CHRRAM)
- {
- bank &= ((m_vram_chunks << 2) - 1);
- for (int i = 0; i < 2; i++)
- {
- m_chr_src[i + start] = source;
- m_chr_orig[i + start] = (bank * 0x800) + (i * 0x400); // for save state uses!
- m_chr_access[i + start] = &m_vram[m_chr_orig[i + start]];
- }
+ base_ptr = m_vrom;
+ chr_chunks = m_vrom_chunks;
}
- else
- {
- bank &= ((m_vrom_chunks << 2) - 1);
- for (int i = 0; i < 2; i++)
- {
- m_chr_src[i + start] = source;
- m_chr_orig[i + start] = (bank * 0x800) + (i * 0x400); // for save state uses!
- m_chr_access[i + start] = &m_vrom[m_chr_orig[i + start]];
- }
- }
-}
-void device_nes_cart_interface::chr1_x(int start, int bank, int source)
-{
- chr_sanity_check(source);
+ bank &= (chr_chunks << (3 - shift)) - 1;
+ int size = 0x400 << shift;
+ int bank_start = bank * size;
+ int kbyte = 1 << shift;
- if (source == CHRRAM)
+ for (int i = 0; i < kbyte; i++)
{
- bank &= ((m_vram_chunks << 3) - 1);
- m_chr_src[start] = source;
- m_chr_orig[start] = (bank * 0x400); // for save state uses!
- m_chr_access[start] = &m_vram[m_chr_orig[start]];
- }
- else
- {
- bank &= ((m_vrom_chunks << 3) - 1);
- m_chr_src[start] = source;
- m_chr_orig[start] = (bank * 0x400); // for save state uses!
- m_chr_access[start] = &m_vrom[m_chr_orig[start]];
+ m_chr_src[i + start] = source;
+ m_chr_orig[i + start] = bank_start + i * 0x400; // for save state uses!
+ m_chr_access[i + start] = &base_ptr[m_chr_orig[i + start]];
}
}
@@ -484,7 +386,7 @@ void device_nes_cart_interface::chr1_x(int start, int bank, int source)
void device_nes_cart_interface::set_nt_page(int page, int source, int bank, int writable)
{
- uint8_t* base_ptr;
+ uint8_t *base_ptr;
switch (source)
{
@@ -492,7 +394,7 @@ void device_nes_cart_interface::set_nt_page(int page, int source, int bank, int
base_ptr = &m_ext_ntram[0];
break;
case VROM:
- bank &= ((m_vrom_chunks << 3) - 1);
+ bank &= (m_vrom_chunks << 3) - 1;
base_ptr = m_vrom;
break;
case EXRAM:
@@ -505,7 +407,7 @@ void device_nes_cart_interface::set_nt_page(int page, int source, int bank, int
break;
}
- page &= 3; /* mask down to the 4 logical pages */
+ page &= 3; // mask down to the 4 logical pages
m_nt_src[page] = source;
if (base_ptr)
@@ -519,20 +421,21 @@ void device_nes_cart_interface::set_nt_page(int page, int source, int bank, int
void device_nes_cart_interface::set_nt_mirroring(int mirroring)
{
- /* setup our videomem handlers based on mirroring */
+ // setup our videomem handlers based on mirroring
switch (mirroring)
{
- case PPU_MIRROR_VERT:
+ default:
+ case PPU_MIRROR_HORZ:
set_nt_page(0, CIRAM, 0, 1);
- set_nt_page(1, CIRAM, 1, 1);
- set_nt_page(2, CIRAM, 0, 1);
+ set_nt_page(1, CIRAM, 0, 1);
+ set_nt_page(2, CIRAM, 1, 1);
set_nt_page(3, CIRAM, 1, 1);
break;
- case PPU_MIRROR_HORZ:
+ case PPU_MIRROR_VERT:
set_nt_page(0, CIRAM, 0, 1);
- set_nt_page(1, CIRAM, 0, 1);
- set_nt_page(2, CIRAM, 1, 1);
+ set_nt_page(1, CIRAM, 1, 1);
+ set_nt_page(2, CIRAM, 0, 1);
set_nt_page(3, CIRAM, 1, 1);
break;
@@ -557,14 +460,6 @@ void device_nes_cart_interface::set_nt_mirroring(int mirroring)
set_nt_page(2, CART_NTRAM, 2, 1);
set_nt_page(3, CART_NTRAM, 3, 1);
break;
-
- case PPU_MIRROR_NONE:
- default:
- set_nt_page(0, CIRAM, 0, 1);
- set_nt_page(1, CIRAM, 0, 1);
- set_nt_page(2, CIRAM, 1, 1);
- set_nt_page(3, CIRAM, 1, 1);
- break;
}
}
@@ -572,32 +467,13 @@ 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)
{
- // use hold_irq_line for HOLD_LINE semantics (not recommended)
assert(state == ASSERT_LINE || state == CLEAR_LINE);
m_maincpu->set_input_line(m6502_device::IRQ_LINE, state);
}
-void device_nes_cart_interface::hold_irq_line()
-{
- // hack which requires the CPU object
- m_maincpu->set_input_line(m6502_device::IRQ_LINE, HOLD_LINE);
-}
-
-void device_nes_cart_interface::reset_cpu()
-{
- // another hack
- m_maincpu->set_pc(0xfffc);
-}
-
-void device_nes_cart_interface::poke(offs_t offset, uint8_t data)
-{
- // even worse hack
- m_maincpu->space(AS_PROGRAM).write_byte(offset, data);
-}
-
//-------------------------------------------------
// Other helpers
//-------------------------------------------------
@@ -607,7 +483,7 @@ void device_nes_cart_interface::poke(offs_t offset, uint8_t data)
// the memory banks)
uint8_t device_nes_cart_interface::hi_access_rom(uint32_t offset)
{
- int bank = (offset & 0x6000) >> 13;
+ int bank = BIT(offset, 13, 2);
return m_prg[m_prg_bank[bank] * 0x2000 + (offset & 0x1fff)];
}
@@ -632,7 +508,7 @@ uint8_t device_nes_cart_interface::account_bus_conflict(uint32_t offset, uint8_t
void device_nes_cart_interface::chr_w(offs_t offset, uint8_t data)
{
- int bank = offset >> 10;
+ int bank = BIT(offset, 10, 3);
if (m_chr_src[bank] == CHRRAM)
m_chr_access[bank][offset & 0x3ff] = data;
@@ -640,24 +516,22 @@ void device_nes_cart_interface::chr_w(offs_t offset, uint8_t data)
uint8_t device_nes_cart_interface::chr_r(offs_t offset)
{
- int bank = offset >> 10;
+ int bank = BIT(offset, 10, 3);
return m_chr_access[bank][offset & 0x3ff];
}
void device_nes_cart_interface::nt_w(offs_t offset, uint8_t data)
{
- int page = ((offset & 0xc00) >> 10);
-
- if (!m_nt_writable[page])
- return;
+ int page = BIT(offset, 10, 2);
- m_nt_access[page][offset & 0x3ff] = data;
+ if (m_nt_writable[page])
+ m_nt_access[page][offset & 0x3ff] = data;
}
uint8_t device_nes_cart_interface::nt_r(offs_t offset)
{
- int page = ((offset & 0xc00) >> 10);
+ int page = BIT(offset, 10, 2);
return m_nt_access[page][offset & 0x3ff];
}
@@ -732,7 +606,7 @@ void device_nes_cart_interface::pcb_start(running_machine &machine, uint8_t *cir
if (m_four_screen_vram)
{
- m_ext_ntram.resize(0x2000);
+ m_ext_ntram.resize(0x1000);
device().save_item(NAME(m_ext_ntram));
}
@@ -778,12 +652,11 @@ void device_nes_cart_interface::nes_banks_restore()
//-------------------------------------------------
nes_cart_slot_device::nes_cart_slot_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
: device_t(mconfig, NES_CART_SLOT, tag, owner, clock)
- , device_image_interface(mconfig, *this)
- , device_slot_interface(mconfig, *this)
+ , device_cartrom_image_interface(mconfig, *this)
+ , device_single_card_slot_interface<device_nes_cart_interface>(mconfig, *this)
, m_crc_hack(0)
, m_cart(nullptr)
, m_pcb_id(NO_BOARD)
- , m_must_be_loaded(1)
{
}
@@ -801,7 +674,7 @@ nes_cart_slot_device::~nes_cart_slot_device()
void nes_cart_slot_device::device_start()
{
- m_cart = dynamic_cast<device_nes_cart_interface *>(get_card_device());
+ m_cart = get_card_device();
}
@@ -828,7 +701,7 @@ void nes_cart_slot_device::pcb_reset()
-------------------------------------------------*/
-/* Include emulation of NES PCBs for softlist */
+// Include emulation of NES PCBs for softlist
#include "nes_pcb.hxx"
@@ -838,7 +711,7 @@ void nes_cart_slot_device::pcb_reset()
-------------------------------------------------*/
-/* Include emulation of UNIF Boards for .unf files */
+// Include emulation of UNIF Boards for .unf files
#include "nes_unif.hxx"
@@ -848,11 +721,11 @@ void nes_cart_slot_device::pcb_reset()
-------------------------------------------------*/
-/* Include emulation of iNES Mappers for .nes files */
+// Include emulation of iNES Mappers for .nes files
#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)
{
@@ -860,41 +733,34 @@ image_init_result nes_cart_slot_device::call_load()
{
char magic[4];
- /* Check first 4 bytes of the image to decide if it is UNIF or iNES */
- /* Unfortunately, many .unf files have been released as .nes, so we cannot rely on extensions only */
+ // Check first 4 bytes of the image to decide if it is UNIF or iNES
+ // Unfortunately, many .unf files have been released as .nes, so we cannot rely on extensions only
fread(magic, 4);
- if ((magic[0] == 'N') && (magic[1] == 'E') && (magic[2] == 'S')) /* If header starts with 'NES' it is iNES */
+ 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 */
+ 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());
- 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());
}
@@ -929,16 +795,16 @@ std::string nes_cart_slot_device::get_default_card_software(get_default_card_sof
{
if (hook.image_file())
{
- const char *slot_string = "nrom";
- uint32_t len = hook.image_file()->size();
+ uint64_t len;
+ hook.image_file()->length(len); // FIXME: check error return, guard against excessively large files
std::vector<uint8_t> rom(len);
- hook.image_file()->read(&rom[0], len);
+ 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'))
slot_string = get_default_card_ines(hook, &rom[0], len);
-
- if ((rom[0] == 'U') && (rom[1] == 'N') && (rom[2] == 'I') && (rom[3] == 'F'))
+ else if ((rom[0] == 'U') && (rom[1] == 'N') && (rom[2] == 'I') && (rom[3] == 'F'))
slot_string = get_default_card_unif(&rom[0], len);
return std::string(slot_string);
diff --git a/src/devices/bus/nes/nes_slot.h b/src/devices/bus/nes/nes_slot.h
index f26c526b360..61ba5d0e78c 100644
--- a/src/devices/bus/nes/nes_slot.h
+++ b/src/devices/bus/nes/nes_slot.h
@@ -5,7 +5,7 @@
#pragma once
-#include "softlist_dev.h"
+#include "imagedev/cartrom.h"
/***************************************************************************
@@ -15,7 +15,7 @@
// uncomment this for *very* verbose logging of most cart accesses
//#define NES_PCB_DEBUG
-/* Boards */
+// Boards
enum
{
STD_NROM = 0,
@@ -23,117 +23,138 @@ enum
STD_CNROM, STD_CPROM,
STD_EXROM, STD_FXROM, STD_GXROM,
STD_HKROM, STD_PXROM,
- STD_SXROM, STD_TXROM, STD_TXSROM,
- STD_TKROM, STD_TQROM,
+ STD_SXROM, STD_SOROM, STD_SZROM,
+ STD_TXROM, STD_TXSROM, STD_TKROM, STD_TQROM,
STD_UXROM, STD_UN1ROM, UXROM_CC,
- HVC_FAMBASIC, NES_QJ, PAL_ZZ, STD_EVENT,
- STD_SXROM_A, STD_SOROM, STD_SOROM_A,
+ HVC_FAMBASIC, NES_QJ, PAL_ZZ, STD_EVENT, STD_EVENT2,
STD_DISKSYS,
STD_NROM368,//homebrew extension of NROM!
- /* Discrete components boards (by various manufacturer) */
+ // Discrete components boards (by various manufacturer)
DIS_74X161X138, DIS_74X139X74,
DIS_74X377, DIS_74X161X161X32,
- /* Active Enterprises */
+ // Active Enterprises
ACTENT_ACT52,
- /* AGCI */
+ // AGCI
AGCI_50282,
- /* AVE */
+ // AVE
AVE_NINA01, AVE_NINA06, AVE_MAXI15,
- /* Bandai */
+ // Bandai
BANDAI_FJUMP2, BANDAI_PT554,
BANDAI_DATACH, BANDAI_KARAOKE, BANDAI_OEKAKIDS,
BANDAI_FCG, BANDAI_LZ93, BANDAI_LZ93EX1, BANDAI_LZ93EX2,
- /* Caltron */
- CALTRON_6IN1,
- /* Camerica */
- CAMERICA_BF9093, CAMERICA_BF9096, CAMERICA_ALADDIN,
- CAMERICA_GOLDENFIVE, GG_NROM,
- /* Dreamtech */
+ // Caltron
+ CALTRON_6IN1, CALTRON_9IN1,
+ // Camerica
+ CAMERICA_BF9093, CAMERICA_BF9096, CAMERICA_BF9096_ALT,
+ CAMERICA_ALADDIN, CAMERICA_GOLDENFIVE, GG_NROM,
+ // Dreamtech
DREAMTECH_BOARD,
- /* Irem */
+ // Irem
IREM_G101, IREM_H3001, IREM_LROG017,
IREM_TAM_S1, IREM_HOLYDIVR,
- /* Jaleco */
+ // Jaleco
JALECO_SS88006, JALECO_JF11, JALECO_JF13,
JALECO_JF16, JALECO_JF17, JALECO_JF17_ADPCM,
JALECO_JF19, JALECO_JF19_ADPCM, JALECO_JF23,
JALECO_JF24, JALECO_JF29, JALECO_JF33,
- /* Konami */
+ // Konami
KONAMI_VRC1, KONAMI_VRC2, KONAMI_VRC3,
KONAMI_VRC4, KONAMI_VRC6, KONAMI_VRC7,
- /* Namcot */
+ // Namcot
NAMCOT_163, NAMCOT_175, NAMCOT_340,
NAMCOT_3425, NAMCOT_34X3, NAMCOT_3446,
- /* NTDEC */
- NTDEC_ASDER, NTDEC_FIGHTINGHERO,
- /* Rex Soft */
+ // NTDEC
+ NTDEC_ASDER, NTDEC_FIGHTINGHERO, NTDEC_N715021,
+ // Rex Soft
REXSOFT_SL1632, REXSOFT_DBZ5,
- /* Sachen */
+ // Sachen
SACHEN_8259A, SACHEN_8259B, SACHEN_8259C, SACHEN_8259D,
SACHEN_SA009, SACHEN_SA0036, SACHEN_SA0037,
- SACHEN_SA72007, SACHEN_SA72008, SACHEN_TCA01,
- SACHEN_TCU01, SACHEN_TCU02, SACHEN_SA9602B,
- SACHEN_74LS374, SACHEN_74LS374_ALT, SACHEN_SHERO,
- /* Sunsoft */
+ SACHEN_SA72007, SACHEN_SA72008, SACHEN_SA9602B,
+ SACHEN_TCA01, SACHEN_TCU01, SACHEN_TCU02, SACHEN_3013, SACHEN_3014,
+ SACHEN_74LS374, SACHEN_74LS374_ALT, SACHEN_SHERO, SACHEN_ZGDH,
+ // Sunsoft
SUNSOFT_1, SUNSOFT_2, SUNSOFT_3, SUNSOFT_4,
SUNSOFT_DCS, SUNSOFT_5, SUNSOFT_FME7,
- /* Taito */
+ // Taito
TAITO_TC0190FMC, TAITO_TC0190FMCP,
TAITO_X1_005, TAITO_X1_017,
- /* Tengen */
- TENGEN_800008, TENGEN_800032, TENGEN_800037,
- /* TXC */
- TXC_22211, TXC_DUMARACING, TXC_MJBLOCK,
- TXC_COMMANDOS, TXC_TW, TXC_STRIKEW,
- /* Multigame Carts */
- BMC_64IN1NR, BMC_190IN1, BMC_A65AS,
- BMC_HIK8IN1, BMC_NOVEL1, BMC_NOVEL2, BMC_S24IN1SC03, BMC_T262,
+ // Tengen
+ TENGEN_800032, TENGEN_800037,
+ // TXC
+ TXC_22110, TXC_22211, TXC_COMMANDOS, TXC_DUMARACING,
+ TXC_MJBLOCK, TXC_STRIKEW, TXC_TW,
+ // Multigame Carts
+ BMC_64IN1NR, BMC_190IN1, BMC_A65AS, BMC_A88S1, BMC_F15, BMC_F600, BMC_L6IN1,
+ BMC_GN45, BMC_HIK8IN1, BMC_SFC12, BMC_JY208, BMC_JY302, BMC_KC885, BMC_KL06,
+ BMC_S24IN1SC03, BMC_T262, BMC_TELETUBBIES,
BMC_WS, BMC_SUPERBIG_7IN1, BMC_SUPERHIK_4IN1, BMC_BALLGAMES_11IN1,
- BMC_MARIOPARTY_7IN1, BMC_GOLD_7IN1, BMC_SUPER_700IN1, BMC_FAMILY_4646,
+ BMC_GOLD_7IN1, BMC_SUPER_700IN1, BMC_FAMILY_4646,
BMC_36IN1, BMC_21IN1, BMC_150IN1, BMC_35IN1, BMC_64IN1,
- BMC_15IN1, BMC_SUPERHIK_300IN1, BMC_SUPERGUN_20IN1,
- BMC_GOLDENCARD_6IN1, BMC_72IN1, BMC_SUPER_42IN1, BMC_76IN1,
- BMC_31IN1, BMC_22GAMES, BMC_20IN1, BMC_110IN1,
- BMC_70IN1, BMC_800IN1, BMC_1200IN1,
- BMC_GKA, BMC_GKB, BMC_VT5201, BMC_BENSHIENG, BMC_810544,
- BMC_NTD_03, BMC_G63IN1, BMC_FK23C, BMC_FK23CA, BMC_PJOY84,
- BMC_POWERFUL_255, BMC_11160, BMC_G146, BMC_8157, BMC_830118C,
- BMC_411120C, BMC_GOLD150, BMC_GOLD260, BMC_CH001, BMC_SUPER22,
- BMC_12IN1, BMC_4IN1RESET, BMC_42IN1RESET,
- /* Unlicensed */
- UNL_8237, UNL_CC21, UNL_AX5705, UNL_KOF97, UNL_KS7057,
- UNL_N625092, UNL_SC127, UNL_SMB2J, UNL_T230, UNL_MMALEE,
- UNL_UXROM, UNL_MK2, UNL_XIAOZY, UNL_KOF96,
- UNL_SF3, UNL_RACERMATE, UNL_EDU2K, UNL_LH53, UNL_LH32, UNL_LH10,
- UNL_STUDYNGAME, UNL_603_5052, UNL_H2288, UNL_2708,
- UNL_MALISB, UNL_BB, UNL_AC08, UNL_A9746, UNL_WORLDHERO,
- UNL_43272, UNL_TF1201, UNL_CITYFIGHT, UNL_RT01,
- /* Bootleg boards */
- BTL_SMB2JA, BTL_MARIOBABY, BTL_AISENSHINICOL, BTL_TOBIDASE,
- BTL_SMB2JB, BTL_09034A, BTL_SMB3, BTL_SBROS11, BTL_DRAGONNINJA,
- BTL_PIKACHUY2K, BTL_SHUIGUAN,
- /* Misc: these are needed to convert mappers to boards, I will sort them later */
+ BMC_8IN1, BMC_15IN1, BMC_SUPERHIK_300IN1, BMC_SUPERGUN_20IN1,
+ BMC_72IN1, BMC_SUPER_42IN1, BMC_76IN1,
+ BMC_31IN1, BMC_22GAMES, BMC_20IN1, BMC_5IN1_1993,
+ BMC_70IN1, BMC_500IN1, BMC_800IN1, BMC_1200IN1,
+ BMC_DS927, BMC_GKA, BMC_GKB, BMC_GKCXIN1, BMC_GN91B, BMC_GOLD260,
+ BMC_HP898F, BMC_VT5201, BMC_BENSHIENG,
+ BMC_CTC09, BMC_CTC_12IN1, BMC_60311C, BMC_80013B, BMC_810544C, BMC_82AB,
+ BMC_830425C, BMC_830506C, BMC_830928C, BMC_850437C, BMC_891227, BMC_970630C,
+ BMC_N32_4IN1, BMC_NC20MB, BMC_NT639, BMC_NTD_03, BMC_SRPG_5IN1,
+ BMC_EL860947C, BMC_EL861121C, BMC_FAM250, BMC_FK23C, BMC_FK23CA,
+ BMC_JY012005, BMC_JY820845C, BMC_PJOY84,
+ BMC_S009, BMC_TH22913, BMC_TH2348, BMC_11160, BMC_G146,
+ BMC_2751, BMC_8157, BMC_00202650,
+ BMC_411120C, BMC_810305C, BMC_820720C, BMC_830118C,
+ BMC_830832C, BMC_831128C, BMC_YY841101C, BMC_YY841155C,
+ BMC_12IN1, BMC_4IN1RESET, BMC_42IN1RESET, BMC_LITTLECOM160,
+ BMC_K1029, BMC_K3006, BMC_K3033, BMC_K3036, BMC_K3046, BMC_K3071, BMC_SA005A,
+ BMC_TF2740, BMC_TJ03, BMC_RESETSXROM, BMC_RESETTXROM, BMC_TECHLINE9IN1,
+ // Unlicensed
+ UNL_8237, UNL_8237A, UNL_CC21, UNL_AX40G, UNL_AX5705, UNL_KN42,
+ UNL_KOF97, UNL_N625092, UNL_SC127, UNL_SMB2J, UNL_T230, UNL_MMALEE,
+ UNL_JY830623C, UNL_XIAOZY, UNL_KOF96, UNL_FS6,
+ UNL_SF3, UNL_RACERMATE, UNL_EDU2K,
+ UNL_STUDYNGAME, UNL_603_5052, UNL_H2288, UNL_158B, UNL_2708,
+ UNL_MALISB, UNL_AC08, UNL_A9746, UNL_43272, UNL_TF1201, UNL_TH21311,
+ UNL_BMW8544, UNL_CITYFIGHT, UNL_NINJARYU, UNL_EH8813A, UNL_RT01,
+ // Bootleg boards
+ BTL_0353, BTL_09034A, BTL_2YUDB, BTL_900218, BTL_AISENSHINICOL,
+ BTL_BATMANFS, BTL_CONTRAJ, BTL_DRAGONNINJA, BTL_L001, BTL_MARIOBABY,
+ BTL_PALTHENA, BTL_PIKACHUY2K, BTL_SBROS11, BTL_SHUIGUAN,
+ BTL_SMB2JA, BTL_SMB2JB, BTL_SMB3, BTL_TOBIDASE, BTL_YUNG08,
+ // Shenzhen Jncota
+ JNCOTA_KT1001,
+ // Kaiser
+ KAISER_KS106C, KAISER_KS202, KAISER_KS7010, KAISER_KS7012,
+ KAISER_KS7013B, KAISER_KS7016, KAISER_KS7016B, KAISER_KS7017,
+ KAISER_KS7021A, KAISER_KS7022, KAISER_KS7030, KAISER_KS7031,
+ KAISER_KS7032, KAISER_KS7037, KAISER_KS7057, KAISER_KS7058,
+ // Whirlwind Manu
+ UNL_DH08, UNL_LE05, UNL_LG25, UNL_LH10, UNL_LH28_LH54,
+ UNL_LH31, UNL_LH32, UNL_LH42, UNL_LH51, UNL_LH53,
+ // Misc: these are needed to convert mappers to boards, I will sort them later
OPENCORP_DAOU306, HES_BOARD, SVISION16_BOARD, RUMBLESTATION_BOARD, JYCOMPANY_A, JYCOMPANY_B, JYCOMPANY_C,
- MAGICSERIES_MD, KASING_BOARD, FUTUREMEDIA_BOARD, FUKUTAKE_BOARD, SOMARI_SL12,
+ MAGICSERIES_MD, KASING_BOARD, FUTUREMEDIA_BOARD, FUKUTAKE_BOARD, SOMARI_SL12, SOMARI_HUANG2,
HENGG_SRICH, HENGG_XHZS, HENGG_SHJY3, SUBOR_TYPE0, SUBOR_TYPE1, SUBOR_TYPE2,
- KAISER_KS7058, KAISER_KS7032, KAISER_KS7022, KAISER_KS7017,
- KAISER_KS7012, KAISER_KS7013B, KAISER_KS202, KAISER_KS7031,
- KAISER_KS7016, KAISER_KS7037,
- CNE_DECATHLON, CNE_FSB, CNE_SHLZ, CONY_BOARD, YOKO_BOARD,
+ CNE_DECATHLON, CNE_FSB, CNE_SHLZ, COCOMA_BOARD, CONY_BOARD, CONY1K_BOARD, SMD133_BOARD, YOKO_BOARD,
RCM_GS2015, RCM_GS2004, RCM_GS2013, RCM_TF9IN1, RCM_3DBLOCK,
WAIXING_TYPE_A, WAIXING_TYPE_A1, WAIXING_TYPE_B, WAIXING_TYPE_C, WAIXING_TYPE_D,
- WAIXING_TYPE_E, WAIXING_TYPE_F, WAIXING_TYPE_G, WAIXING_TYPE_H, WAIXING_TYPE_H1,
+ WAIXING_TYPE_E, WAIXING_TYPE_F, WAIXING_TYPE_F1, WAIXING_TYPE_G, WAIXING_TYPE_H, WAIXING_TYPE_H1,
WAIXING_TYPE_I, WAIXING_TYPE_J, WAIXING_FS304,
WAIXING_SGZLZ, WAIXING_SGZ, WAIXING_WXZS, WAIXING_SECURITY, WAIXING_SH2,
WAIXING_DQ8, WAIXING_FFV, WAIXING_WXZS2, SUPERGAME_LIONKING, SUPERGAME_BOOGERMAN,
- KAY_BOARD, HOSENKAN_BOARD, NITRA_TDA, GOUDER_37017, NANJING_BOARD,
- WHIRLWIND_2706, ZEMINA_BOARD,
+ KAY_BOARD, NITRA_TDA, GOUDER_37017, NANJING_BOARD, ZEMINA_BOARD,
+ // homebrew PCBs
NOCASH_NOCHR, // homebrew PCB design which uses NTRAM for CHRRAM
- BTL_ACTION53, // homebrew PCB for homebrew multicarts
- BTL_2A03_PURITANS, // homebrew PCB
- /* FFE boards, for mappers 6, 8, 17 */
+ UNL_ACTION53, // homebrew PCB for homebrew multicarts
+ UNL_2A03PURITANS, FARID_SLROM8IN1, FARID_UNROM8IN1,
+ // Batlab Electronics
+ BATMAP_000, BATMAP_SRRX,
+ // Sealie
+ SEALIE_8BITXMAS, SEALIE_CUFROM, SEALIE_DPCMCART, SEALIE_UNROM512,
+ // FFE boards, for mappers 6, 8, 17
FFE3_BOARD, FFE4_BOARD, FFE8_BOARD, TEST_BOARD,
- /* Unsupported (for place-holder boards, with no working emulation) & no-board (at init) */
+ // Unsupported (for place-holder boards, with no working emulation) & no-board (at init)
UNSUPPORTED_BOARD, UNKNOWN_BOARD, NO_BOARD
};
@@ -149,7 +170,6 @@ enum
#define CART_NTRAM 4
-#define PPU_MIRROR_NONE 0
#define PPU_MIRROR_VERT 1
#define PPU_MIRROR_HORZ 2
#define PPU_MIRROR_HIGH 3
@@ -159,9 +179,11 @@ enum
// ======================> device_nes_cart_interface
-class device_nes_cart_interface : public device_slot_card_interface
+class device_nes_cart_interface : public device_interface
{
public:
+ enum class mmc1_type : u8 { MMC1, MMC1A, MMC1B };
+
// construction/destruction
virtual ~device_nes_cart_interface();
@@ -183,8 +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 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);
@@ -199,8 +222,12 @@ public:
void set_trainer(bool val) { m_has_trainer = val; }
void set_ce(int mask, int state) { m_ce_mask = mask; m_ce_state = state; }
+ void set_mmc1_type(mmc1_type val) { m_mmc1_type = val; }
void set_vrc_lines(int PRG_A, int PRG_B, int CHR) { m_vrc_ls_prg_a = PRG_A; m_vrc_ls_prg_b = PRG_B; m_vrc_ls_chr = CHR; }
void set_n163_vol(int vol) { m_n163_vol = vol; }
+ void set_outer_prg_size(int val) { m_outer_prg_size = val; }
+ void set_outer_chr_size(int val) { m_outer_chr_size = val; }
+ void set_smd133_addr(int val) { m_smd133_addr = val; }
void set_x1_005_alt(bool val) { m_x1_005_alt_mirroring = val; }
void set_bus_conflict(bool val) { m_bus_conflict = val; }
uint8_t get_open_bus() { return m_open_bus; }
@@ -213,6 +240,7 @@ public:
uint8_t *get_ciram_base() { return m_ciram; }
uint8_t *get_battery_base() { return &m_battery[0]; }
uint8_t *get_mapper_sram_base() { return m_mapper_sram; }
+ uint8_t *get_misc_rom_base() { return m_misc_rom; }
uint32_t get_prg_size() const { return m_prg_size; }
uint32_t get_prgram_size() const { return m_prgram.size(); }
@@ -220,10 +248,11 @@ public:
uint32_t get_vram_size() const { return m_vram.size(); }
uint32_t get_battery_size() const { return m_battery.size(); }
uint32_t get_mapper_sram_size() const { return m_mapper_sram_size; }
+ uint32_t get_misc_rom_size() const { return m_misc_rom_size; }
virtual void ppu_latch(offs_t offset) {}
- virtual void hblank_irq(int scanline, int vblank, int blanked) {}
- virtual void scanline_irq(int scanline, int vblank, int blanked) {}
+ virtual void hblank_irq(int scanline, bool vblank, bool blanked) {}
+ virtual void scanline_irq(int scanline, bool vblank, bool blanked) {}
virtual void pcb_reset() {} // many pcb expect specific PRG/CHR banking at start
virtual void pcb_start(running_machine &machine, uint8_t *ciram_ptr, bool cart_mounted);
@@ -236,10 +265,7 @@ public:
protected:
device_nes_cart_interface(const machine_config &mconfig, device_t &device);
- DECLARE_WRITE_LINE_MEMBER(set_irq_line);
- void hold_irq_line();
- void reset_cpu();
- void poke(offs_t offset, uint8_t data);
+ void set_irq_line(int state);
// internal state
uint8_t *m_prg;
@@ -260,17 +286,23 @@ protected:
// these are specific of some boards but must be accessible from the driver
// E.g. additional save ram for HKROM, X1-005 & X1-017 boards, or ExRAM for MMC5
uint8_t *m_mapper_sram;
+ uint8_t *m_misc_rom;
std::vector<uint8_t> m_ext_ntram;
uint32_t m_mapper_sram_size;
+ uint32_t m_misc_rom_size;
int m_ce_mask;
int m_ce_state;
+ mmc1_type m_mmc1_type;
int m_vrc_ls_prg_a;
int m_vrc_ls_prg_b;
int m_vrc_ls_chr;
int m_n163_vol;
+ int m_outer_prg_size;
+ int m_outer_chr_size;
+ int m_smd133_addr;
- int m_mirroring;
+ int32_t m_mirroring;
bool m_pcb_ctrl_mirror, m_four_screen_vram, m_has_trainer;
bool m_x1_005_alt_mirroring; // temp hack for two kind of mirroring in Taito X1-005 boards (to be replaced with pin checking)
bool m_bus_conflict;
@@ -282,7 +314,7 @@ public:
inline int prg_8k_bank_num(int bank);
inline void update_prg_banks(int prg_bank_start, int prg_bank_end);
memory_bank *m_prg_bank_mem[4];
- int m_prg_bank[4];
+ int32_t m_prg_bank[4];
uint32_t m_prg_chunks;
uint32_t m_prg_mask;
@@ -290,52 +322,54 @@ public:
void prg32(int bank);
void prg16_89ab(int bank);
void prg16_cdef(int bank);
- void prg8_89(int bank);
- void prg8_ab(int bank);
- void prg8_cd(int bank);
- void prg8_ef(int bank);
void prg8_x(int start, int bank);
+ void prg8_89(int bank) { prg8_x(0, bank); }
+ void prg8_ab(int bank) { prg8_x(1, bank); }
+ void prg8_cd(int bank) { prg8_x(2, bank); }
+ void prg8_ef(int bank) { prg8_x(3, bank); }
// CHR
- int m_chr_source; // global source for the 8 VROM banks
- inline void chr_sanity_check(int source);
+ int32_t m_chr_source; // global source for the 8 VROM banks
//these were previously called chr_map. they are a quick banking structure,
//because some of these change multiple times per scanline!
- int m_chr_src[8]; //defines source of base pointer
- int m_chr_orig[8]; //defines offset of 0x400 byte segment at base pointer
+ int32_t m_chr_src[8]; //defines source of base pointer
+ int32_t m_chr_orig[8]; //defines offset of 0x400 byte segment at base pointer
uint8_t *m_chr_access[8]; //source translated + origin -> valid pointer!
uint32_t m_vrom_chunks;
uint32_t m_vram_chunks;
// CHR helpers
- void chr8(int bank, int source);
- void chr4_x(int start, int bank, int source);
- void chr4_0(int bank, int source){ chr4_x(0, bank, source); };
- void chr4_4(int bank, int source){ chr4_x(4, bank, source); };
- void chr2_x(int start, int bank, int source);
- void chr2_0(int bank, int source) { chr2_x(0, bank, source); };
- void chr2_2(int bank, int source) { chr2_x(2, bank, source); };
- void chr2_4(int bank, int source) { chr2_x(4, bank, source); };
- void chr2_6(int bank, int source) { chr2_x(6, bank, source); };
- void chr1_x(int start, int bank, int source);
- void chr1_0(int bank, int source) { chr1_x(0, bank, source); };
- void chr1_1(int bank, int source) { chr1_x(1, bank, source); };
- void chr1_2(int bank, int source) { chr1_x(2, bank, source); };
- void chr1_3(int bank, int source) { chr1_x(3, bank, source); };
- void chr1_4(int bank, int source) { chr1_x(4, bank, source); };
- void chr1_5(int bank, int source) { chr1_x(5, bank, source); };
- void chr1_6(int bank, int source) { chr1_x(6, bank, source); };
- void chr1_7(int bank, int source) { chr1_x(7, bank, source); };
+private:
+ void bank_chr(int shift, int start, int bank, int source);
+public:
+ void chr8(int bank, int source) { bank_chr(3, 0, bank, source); }
+ void chr4_x(int start, int bank, int source) { bank_chr(2, start, bank, source); }
+ void chr4_0(int bank, int source) { bank_chr(2, 0, bank, source); }
+ void chr4_4(int bank, int source) { bank_chr(2, 4, bank, source); }
+ void chr2_x(int start, int bank, int source) { bank_chr(1, start, bank, source); }
+ void chr2_0(int bank, int source) { bank_chr(1, 0, bank, source); }
+ void chr2_2(int bank, int source) { bank_chr(1, 2, bank, source); }
+ void chr2_4(int bank, int source) { bank_chr(1, 4, bank, source); }
+ void chr2_6(int bank, int source) { bank_chr(1, 6, bank, source); }
+ void chr1_x(int start, int bank, int source) { bank_chr(0, start, bank, source); }
+ void chr1_0(int bank, int source) { bank_chr(0, 0, bank, source); }
+ void chr1_1(int bank, int source) { bank_chr(0, 1, bank, source); }
+ void chr1_2(int bank, int source) { bank_chr(0, 2, bank, source); }
+ void chr1_3(int bank, int source) { bank_chr(0, 3, bank, source); }
+ void chr1_4(int bank, int source) { bank_chr(0, 4, bank, source); }
+ void chr1_5(int bank, int source) { bank_chr(0, 5, bank, source); }
+ void chr1_6(int bank, int source) { bank_chr(0, 6, bank, source); }
+ void chr1_7(int bank, int source) { bank_chr(0, 7, bank, source); }
// NameTable & Mirroring
//these were previously called nt_page. they are a quick banking structure for a maximum of 4K of RAM/ROM/ExRAM
- int m_nt_src[4];
- int m_nt_orig[4];
- int m_nt_writable[4];
+ int32_t m_nt_src[4];
+ int32_t m_nt_orig[4];
+ int32_t m_nt_writable[4];
uint8_t *m_nt_access[4]; //quick banking structure for a maximum of 4K of RAM/ROM/ExRAM
void set_nt_page(int page, int source, int bank, int writable);
@@ -347,8 +381,8 @@ public:
// ======================> nes_cart_slot_device
class nes_cart_slot_device : public device_t,
- public device_image_interface,
- public device_slot_interface
+ public device_cartrom_image_interface,
+ public device_single_card_slot_interface<device_nes_cart_interface>
{
public:
// construction/destruction
@@ -364,34 +398,17 @@ public:
nes_cart_slot_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
virtual ~nes_cart_slot_device();
- // 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 void call_unload() override;
- virtual const software_list_loader &get_software_list_loader() const override { return rom_software_list_loader::instance(); }
- void call_load_ines();
- void call_load_unif();
- void call_load_pcb();
+ virtual bool is_reset_on_load() const noexcept override { return true; }
+ virtual const char *image_interface() const noexcept override { return "nes_cart"; }
+ virtual const char *file_extensions() const noexcept override { return "nes,unf,unif"; }
+ virtual u32 unhashed_header_length() const noexcept override { return 16; }
- virtual iodevice_t image_type() const override { return IO_CARTSLOT; }
- virtual bool is_readable() const override { return 1; }
- virtual bool is_writeable() const override { return 0; }
- virtual bool is_creatable() const override { return 0; }
- virtual bool must_be_loaded() const override { return m_must_be_loaded; }
- virtual bool is_reset_on_load() const override { return 1; }
- virtual const char *image_interface() const override { return "nes_cart"; }
- virtual const char *file_extensions() const override { return "nes,unf,unif"; }
- virtual u32 unhashed_header_length() const 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;
- const char * get_default_card_ines(get_default_card_software_hook &hook, const uint8_t *ROM, uint32_t len) const;
- static const char * get_default_card_unif(const uint8_t *ROM, uint32_t len);
- static const char * nes_get_slot(int pcb_id);
- int nes_get_pcb_id(const char *slot);
// reading and writing
virtual uint8_t read_l(offs_t offset);
@@ -406,7 +423,7 @@ public:
// hack until disk system is made modern!
virtual void disk_flip_side() { if (m_cart) m_cart->disk_flip_side(); }
- int get_pcb_id() { return m_pcb_id; };
+ int get_pcb_id() { return m_pcb_id; }
void pcb_start(uint8_t *ciram_ptr);
void pcb_reset();
@@ -414,25 +431,27 @@ public:
// temporarily here
int m_crc_hack;
- int get_crc_hack() { return m_crc_hack; };
-
- void set_must_be_loaded(bool _must_be_loaded) { m_must_be_loaded = _must_be_loaded; }
+ int get_crc_hack() { return m_crc_hack; }
//private:
device_nes_cart_interface* m_cart;
int m_pcb_id;
- bool m_must_be_loaded;
-};
-// device type definition
-DECLARE_DEVICE_TYPE(NES_CART_SLOT, nes_cart_slot_device)
+protected:
+ // device_t implementation
+ virtual void device_start() override ATTR_COLD;
+ const char * get_default_card_ines(get_default_card_software_hook &hook, const uint8_t *ROM, uint32_t len) const;
+ static const char * get_default_card_unif(const uint8_t *ROM, uint32_t len);
+ static const char * nes_get_slot(int pcb_id);
+ int nes_get_pcb_id(const char *slot);
-/***************************************************************************
- DEVICE CONFIGURATION MACROS
- ***************************************************************************/
+ void call_load_ines();
+ void call_load_unif();
+ void call_load_pcb();
+};
-#define NESSLOT_PRGROM_REGION_TAG ":cart:prg_rom"
-#define NESSLOT_CHRROM_REGION_TAG ":cart:chr_rom"
+// device type definition
+DECLARE_DEVICE_TYPE(NES_CART_SLOT, nes_cart_slot_device)
#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 51843f60c2e..b4955cd9b8d 100644
--- a/src/devices/bus/nes/nes_unif.hxx
+++ b/src/devices/bus/nes/nes_unif.hxx
@@ -11,6 +11,8 @@
****************************************************************************************/
+#include "corestr.h"
+#include "multibyte.h"
/* Set to generate prg & chr files when the cart is loaded */
#define SPLIT_PRG 0
@@ -53,7 +55,7 @@ enum
static const unif unif_list[] =
{
/* UNIF NVW WRAM CRAM IDX*/
- { "DREAMTECH01", 0, 0, CHRRAM_8, DREAMTECH_BOARD}, //UNIF only!
+ { "DREAMTECH01", 0, 0, CHRRAM_8, DREAMTECH_BOARD},
{ "NES-ANROM", 0, 0, CHRRAM_8, STD_AXROM},
{ "NES-AOROM", 0, 0, CHRRAM_8, STD_AXROM},
{ "NES-CNROM", 0, 0, CHRRAM_0, STD_CNROM},
@@ -92,41 +94,40 @@ static const unif unif_list[] =
{ "UNL-SACHEN-8259A", 0, 0, CHRRAM_0, SACHEN_8259A},
{ "UNL-SACHEN-8259B", 0, 0, CHRRAM_0, SACHEN_8259B},
{ "BMC-190IN1", 0, 0, CHRRAM_0, BMC_190IN1},
- { "BMC-64IN1NOREPEAT", 0, 0, CHRRAM_0, BMC_64IN1NR}, //UNIF only!
- { "BMC-A65AS", 0, 0, CHRRAM_8, BMC_A65AS}, //UNIF only!
- { "BMC-GS-2004", 0, 0, CHRRAM_8, RCM_GS2004}, //UNIF only!
- { "BMC-GS-2013", 0, 0, CHRRAM_8, RCM_GS2013}, //UNIF only!
- { "BMC-NOVELDIAMOND9999999IN1", 0, 0, CHRRAM_0, BMC_NOVEL1},
+ { "BMC-64IN1NOREPEAT", 0, 0, CHRRAM_0, BMC_64IN1NR},
+ { "BMC-A65AS", 0, 0, CHRRAM_8, BMC_A65AS},
+ { "BMC-GS-2004", 0, 0, CHRRAM_8, RCM_GS2004},
+ { "BMC-GS-2013", 0, 0, CHRRAM_8, RCM_GS2013},
+ { "BMC-NOVELDIAMOND9999999IN1", 0, 0, CHRRAM_0, BMC_21IN1},
{ "BMC-SUPER24IN1SC03", 8, 0, CHRRAM_8, BMC_S24IN1SC03},
{ "BMC-SUPERHIK8IN1", 8, 0, CHRRAM_0, BMC_HIK8IN1},
- { "BMC-T-262", 0, 0, CHRRAM_8, BMC_T262}, //UNIF only!
- { "BMC-WS", 0, 0, CHRRAM_0, BMC_WS}, //UNIF only!
+ { "BMC-T-262", 0, 0, CHRRAM_8, BMC_T262},
+ { "BMC-WS", 0, 0, CHRRAM_0, BMC_WS},
{ "BMC-N625092", 0, 0, CHRRAM_0, UNL_N625092},
// below are boards which are not yet supported, but are used by some UNIF files. they are here as a reminder to what is missing to be added
{ "UNL-TEK90", 0, 0, CHRRAM_0, JYCOMPANY_A}, // JY Company A (is TEK90 the real PCB name?)
{ "UNL-KS7017", 0, 0, CHRRAM_0, KAISER_KS7017},
{ "UNL-KS7032", 0, 0, CHRRAM_0, KAISER_KS7032}, // mapper 142
- { "UNL-603-5052", 0, 0, CHRRAM_0, UNL_603_5052}, // mapper 238?
+ { "UNL-603-5052", 0, 0, CHRRAM_0, UNL_603_5052}, // mapper 238
{ "UNL-EDU2000", 0, 32, CHRRAM_8, UNL_EDU2K},
{ "UNL-H2288", 0, 0, CHRRAM_0, UNL_H2288}, // mapper 123
{ "UNL-SHERO", 0, 0, CHRRAM_8, SACHEN_SHERO},
{ "UNL-YOKO", 0, 0, CHRRAM_0, YOKO_BOARD}, // similar to mapper 83, but not the same
{ "UNL-FS304", 0, 8, CHRRAM_8, WAIXING_FS304}, // used in Zelda 3 by Waixing
{ "UNL-43272", 0, 0, CHRRAM_0, UNL_43272}, // used in Gaau Hok Gwong Cheung
- { "BTL-MARIO1-MALEE2", 0, 0, CHRRAM_0, UNL_MMALEE}, // mapper 55?
+ { "BTL-MARIO1-MALEE2", 0, 0, CHRRAM_0, UNL_MMALEE}, // mapper 55
{ "BMC-FK23C", 0, 0, CHRRAM_0, BMC_FK23C},
{ "BMC-FK23CA", 0, 0, CHRRAM_0, BMC_FK23CA},
- { "BMC-GHOSTBUSTERS63IN1", 0, 0, CHRRAM_8, BMC_G63IN1 },
+ { "BMC-GHOSTBUSTERS63IN1", 0, 0, CHRRAM_8, BMC_76IN1 },
{ "BMC-BS-5", 0, 0, CHRRAM_0, BMC_BENSHIENG},
- { "BMC-810544-C-A1", 0, 0, CHRRAM_0, BMC_810544},
+ { "BMC-810544-C-A1", 0, 0, CHRRAM_0, BMC_810544C},
{ "BMC-411120-C", 0, 0, CHRRAM_0, BMC_411120C},
{ "BMC-8157", 0, 0, CHRRAM_8, BMC_8157},
{ "BMC-830118C", 0, 0, CHRRAM_0, BMC_830118C},
- { "BMC-D1038", 0, 0, CHRRAM_0, BMC_VT5201}, // mapper 60?
+ { "BMC-D1038", 0, 0, CHRRAM_0, BMC_VT5201}, // mapper 59
{ "BMC-SUPERVISION16IN1", 0, 0, CHRRAM_0, SVISION16_BOARD}, // mapper 53
{ "BMC-NTD-03", 0, 0, CHRRAM_0, BMC_NTD_03},
{ "UNL-AC08", 0, 0, CHRRAM_0, UNL_AC08},
- { "UNL-BB", 0, 0, CHRRAM_0, UNL_BB},
{ "UNL-LH32", 0, 0, CHRRAM_0, UNL_LH32},
{ "UNL-LH53", 0, 0, CHRRAM_0, UNL_LH53},
{ "BMC-G-146", 0, 0, CHRRAM_0, BMC_G146},
@@ -134,9 +135,11 @@ static const unif unif_list[] =
{ "UNL-MALISB", 0, 0, CHRRAM_0, UNL_MALISB},
{ "UNL-TF1201", 0, 0, CHRRAM_0, UNL_TF1201},
{ "UNL-DANCE2000", 0, 8, CHRRAM_8, SUBOR_TYPE2}, // similar to some Subor carts
+ { "FARID_SLROM_8-IN-1", 0, 0, CHRRAM_0, FARID_SLROM8IN1},
+ { "FARID_UNROM_8-IN-1", 0, 0, CHRRAM_8, FARID_UNROM8IN1},
{ "BMC-12-IN-1", 0, 0, CHRRAM_0, UNSUPPORTED_BOARD},
- { "BMC-70IN1", 0, 0, CHRRAM_0, UNSUPPORTED_BOARD}, // mapper 236?
- { "BMC-70IN1B", 0, 0, CHRRAM_0, UNSUPPORTED_BOARD}, // mapper 236?
+ { "BMC-70IN1", 0, 0, CHRRAM_0, UNSUPPORTED_BOARD}, // mapper 236
+ { "BMC-70IN1B", 0, 0, CHRRAM_0, UNSUPPORTED_BOARD}, // mapper 236
{ "BMC-42IN1RESETSWITCH", 0, 0, CHRRAM_0, UNSUPPORTED_BOARD}, // mapper 60?
{ "BMC-F-15", 0, 0, CHRRAM_0, UNSUPPORTED_BOARD}, // 150-in-1 Unchained Melody
{ "BMC-HP898F", 0, 0, CHRRAM_0, UNSUPPORTED_BOARD}, // Primasoft 9999999-in-1
@@ -157,8 +160,7 @@ static const unif unif_list[] =
const unif *nes_unif_lookup( const char *board )
{
- int i;
- for (i = 0; i < ARRAY_LENGTH(unif_list); i++)
+ for (int i = 0; i < std::size(unif_list); i++)
{
if (!core_stricmp(unif_list[i].board, board))
return &unif_list[i];
@@ -219,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
@@ -240,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);
@@ -254,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);
}
@@ -268,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);
}
@@ -276,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);
}
@@ -284,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);
}
@@ -292,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);
}
@@ -300,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");
@@ -311,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);
}
@@ -319,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);
}
@@ -327,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);
}
@@ -335,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);
}
@@ -343,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);
}
@@ -351,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);
@@ -361,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);
}
@@ -369,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);
}
@@ -377,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)
@@ -385,7 +387,7 @@ void nes_cart_slot_device::call_load_unif()
else
{
small_prg = true;
- logerror("This chunk is smaller than 16K: the emulation might have issues. Please report this file to the MESS forums.\n");
+ logerror("This chunk is smaller than 16K: the emulation might have issues. Please report this file to the MAME forums.\n");
}
/* Read in the program chunks */
@@ -398,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);
@@ -411,7 +413,7 @@ void nes_cart_slot_device::call_load_unif()
}
else
{
- logerror("Unsupported UNIF chunk or corrupted header. Please report the problem at MESS Board.\n");
+ logerror("Unsupported UNIF chunk or corrupted header. Please report the problem at MAME Board.\n");
read_length = size;
}
}
@@ -424,7 +426,7 @@ void nes_cart_slot_device::call_load_unif()
if (!prg_start)
{
- fatalerror("No PRG found. Please report the problem at MESS Board.\n");
+ fatalerror("No PRG found. Please report the problem at MAME Board.\n");
}
// SETUP step 2: getting PCB and other settings
@@ -478,35 +480,32 @@ 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);
}
if (small_prg) // This is not supported yet, so warn users about this
- osd_printf_error("Loaded UNIF file with non-16k PRG chunk. This is not supported in MESS yet.");
+ osd_printf_error("Loaded UNIF file with non-16k PRG chunk. This is not supported in MAME yet.");
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");
}
@@ -517,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);
@@ -565,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);
@@ -574,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 6fbcd6f31ef..5e95c380ffb 100644
--- a/src/devices/bus/nes/ntdec.cpp
+++ b/src/devices/bus/nes/ntdec.cpp
@@ -10,9 +10,10 @@
* NTDEC ASDER [mapper 112]
* NTDEC Fighting Hero [mapper 193]
+ * NTDEC N715021 [mapper 81]
TODO:
- - why is Master Shooter not working?
+ - why is Master Shooter not working? (correctly aimed shots score as a hit on random targets)
***********************************************************************************************************/
@@ -22,33 +23,37 @@
#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"
//-------------------------------------------------
// constructor
//-------------------------------------------------
-DEFINE_DEVICE_TYPE(NES_NTDEC_ASDER, nes_ntdec_asder_device, "nes_ntdec_asder", "NES Cart NTDEC Asder PCB")
-DEFINE_DEVICE_TYPE(NES_NTDEC_FH, nes_ntdec_fh_device, "nes_fh_asder", "NES Cart NTDEC Fighting Hero PCB")
+DEFINE_DEVICE_TYPE(NES_NTDEC_ASDER, nes_ntdec_asder_device, "nes_ntdec_asder", "NES Cart NTDEC Asder PCB")
+DEFINE_DEVICE_TYPE(NES_NTDEC_FH, nes_ntdec_fh_device, "nes_ntdec_fh", "NES Cart NTDEC Fighting Hero PCB")
+DEFINE_DEVICE_TYPE(NES_NTDEC_N715021, nes_ntdec_n715021_device, "nes_ntdec_n715021", "NES Cart NTDEC N715021 PCB")
-nes_ntdec_asder_device::nes_ntdec_asder_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
- : nes_nrom_device(mconfig, NES_NTDEC_ASDER, tag, owner, clock)
- , m_latch(0)
+nes_ntdec_asder_device::nes_ntdec_asder_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock)
+ : nes_nrom_device(mconfig, NES_NTDEC_ASDER, tag, owner, clock), m_latch(0), m_chr_outer(0)
{
}
-nes_ntdec_fh_device::nes_ntdec_fh_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
+nes_ntdec_fh_device::nes_ntdec_fh_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock)
: nes_nrom_device(mconfig, NES_NTDEC_FH, tag, owner, clock)
{
}
+nes_ntdec_n715021_device::nes_ntdec_n715021_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock)
+ : nes_nrom_device(mconfig, NES_NTDEC_N715021, tag, owner, clock)
+{
+}
+
@@ -56,32 +61,31 @@ void nes_ntdec_asder_device::device_start()
{
common_start();
save_item(NAME(m_latch));
+ save_item(NAME(m_chr_outer));
}
void nes_ntdec_asder_device::pcb_reset()
{
- m_chr_source = m_vrom_chunks ? CHRROM : CHRRAM;
prg16_89ab(0);
prg16_cdef(m_prg_chunks - 1);
- chr8(0, m_chr_source);
+ chr8(0, CHRROM);
m_latch = 0;
-}
-
-void nes_ntdec_fh_device::device_start()
-{
- common_start();
+ m_chr_outer = 0;
}
void nes_ntdec_fh_device::pcb_reset()
{
- m_chr_source = m_vrom_chunks ? CHRROM : CHRRAM;
prg32((m_prg_chunks - 1) >> 1);
- chr8(0, m_chr_source);
- set_nt_mirroring(PPU_MIRROR_VERT);
+ chr8(0, CHRROM);
}
-
+void nes_ntdec_n715021_device::pcb_reset()
+{
+ prg16_89ab(0);
+ prg16_cdef(m_prg_chunks - 1);
+ chr8(0, CHRROM);
+}
@@ -96,17 +100,25 @@ void nes_ntdec_fh_device::pcb_reset()
Games: Cobra Mission, Fighting Hero III, Huang Di, Master
Shooter
+ This board supports swappable 8K PRG banks at 0x8000 and
+ 0xa000 via 2 registers. 16K above is fixed. CHR ROM is
+ selected by 6 registers: 2x2K for the first two, and 4x1K
+ for the remaining 4. The former can only address 256K of
+ CHR while the latter combines with latch at 0xc000 to
+ span 512K. Registers are not directly written to but
+ selected at 0x8000.
+
iNES: mapper 112
- In MESS: Supported.
+ In MAME: Supported.
-------------------------------------------------*/
-void nes_ntdec_asder_device::write_h(offs_t offset, uint8_t data)
+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)
+ switch (offset & 0x6001) // writes only at even addresses?
{
case 0x0000:
m_latch = data & 0x07;
@@ -114,36 +126,21 @@ void nes_ntdec_asder_device::write_h(offs_t offset, uint8_t data)
case 0x2000:
switch (m_latch)
{
- case 0:
- prg8_89(data);
- break;
- case 1:
- prg8_ab(data);
- break;
- case 2:
- data &= 0xfe;
- chr1_0(data, CHRROM);
- chr1_1(data + 1, CHRROM);
- break;
- case 3:
- data &= 0xfe;
- chr1_2(data, CHRROM);
- chr1_3(data + 1, CHRROM);
+ case 0: case 1:
+ prg8_x(m_latch, data);
break;
- case 4:
- chr1_4(data, CHRROM);
+ case 2: case 3:
+ chr2_x((m_latch & 0x01) << 1, data >> 1, CHRROM);
break;
- case 5:
- chr1_5(data, CHRROM);
- break;
- case 6:
- chr1_6(data, CHRROM);
- break;
- case 7:
- chr1_7(data, CHRROM);
+ case 4: case 5: case 6: case 7:
+ u16 high = BIT(m_chr_outer, m_latch) << 8;
+ chr1_x(m_latch, high | data, CHRROM);
break;
}
break;
+ case 0x4000:
+ m_chr_outer = data;
+ break;
case 0x6000:
set_nt_mirroring(BIT(data, 0) ? PPU_MIRROR_HORZ : PPU_MIRROR_VERT);
break;
@@ -154,22 +151,23 @@ void nes_ntdec_asder_device::write_h(offs_t offset, uint8_t data)
Bootleg Board by NTDEC for Fighting Hero
- Games: Fighting Hero
+ Games: Fighting Hero, War in the Gulf
Very simple mapper: writes to 0x6000-0x7fff swap PRG and
- CHR banks.
+ CHR banks. The mirroring register at 0x6004 appears to
+ not be used by any known software?
iNES: mapper 193
- In MESS: Supported.
+ In MAME: Supported.
-------------------------------------------------*/
-void nes_ntdec_fh_device::write_m(offs_t offset, uint8_t 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 & 0x03)
+ switch (offset & 0x07)
{
case 0:
chr4_0(data >> 2, CHRROM);
@@ -181,7 +179,32 @@ void nes_ntdec_fh_device::write_m(offs_t offset, uint8_t data)
chr2_6(data >> 1 , CHRROM);
break;
case 3:
- prg8_89(data);
+ prg8_89(data & 0x0f);
+ break;
+ case 4:
+ set_nt_mirroring(BIT(data, 0) ? PPU_MIRROR_HORZ : PPU_MIRROR_VERT);
break;
}
}
+
+/*-------------------------------------------------
+
+ NTDEC Board N715021
+
+ Games: Super Gun
+
+ Very simple mapper: writes to 0x8000-0xffff swap PRG and
+ CHR banks. PCB also has a latch at 0x6000 but it is not used.
+
+ iNES: mapper 81
+
+ In MAME: Supported.
+
+ -------------------------------------------------*/
+
+void nes_ntdec_n715021_device::write_h(offs_t offset, u8 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/ntdec.h b/src/devices/bus/nes/ntdec.h
index 062c5d7dcec..ad0c12aeef6 100644
--- a/src/devices/bus/nes/ntdec.h
+++ b/src/devices/bus/nes/ntdec.h
@@ -14,18 +14,18 @@ class nes_ntdec_asder_device : public nes_nrom_device
{
public:
// construction/destruction
- nes_ntdec_asder_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
+ nes_ntdec_asder_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock);
- virtual void write_h(offs_t offset, uint8_t data) override;
+ virtual void write_h(offs_t offset, u8 data) override;
virtual void pcb_reset() override;
protected:
// device-level overrides
- virtual void device_start() override;
+ virtual void device_start() override ATTR_COLD;
private:
- uint8_t m_latch;
+ u8 m_latch, m_chr_outer;
};
@@ -35,20 +35,31 @@ class nes_ntdec_fh_device : public nes_nrom_device
{
public:
// construction/destruction
- nes_ntdec_fh_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
+ nes_ntdec_fh_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock);
- virtual void write_m(offs_t offset, uint8_t data) override;
+ virtual void write_m(offs_t offset, u8 data) override;
virtual void pcb_reset() override;
+};
-protected:
- // device-level overrides
- virtual void device_start() override;
+
+// ======================> nes_ntdec_n715021_device
+
+class nes_ntdec_n715021_device : public nes_nrom_device
+{
+public:
+ // construction/destruction
+ nes_ntdec_n715021_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock);
+
+ virtual void write_h(offs_t offset, u8 data) override;
+
+ virtual void pcb_reset() override;
};
// device type definition
-DECLARE_DEVICE_TYPE(NES_NTDEC_ASDER, nes_ntdec_asder_device)
-DECLARE_DEVICE_TYPE(NES_NTDEC_FH, nes_ntdec_fh_device)
+DECLARE_DEVICE_TYPE(NES_NTDEC_ASDER, nes_ntdec_asder_device)
+DECLARE_DEVICE_TYPE(NES_NTDEC_FH, nes_ntdec_fh_device)
+DECLARE_DEVICE_TYPE(NES_NTDEC_N715021, nes_ntdec_n715021_device)
#endif // MAME_BUS_NES_NTDEC_H
diff --git a/src/devices/bus/nes/nxrom.cpp b/src/devices/bus/nes/nxrom.cpp
index 352b7534250..ae377894131 100644
--- a/src/devices/bus/nes/nxrom.cpp
+++ b/src/devices/bus/nes/nxrom.cpp
@@ -30,15 +30,12 @@
#include "emu.h"
#include "nxrom.h"
-#include "sound/samples.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"
//-------------------------------------------------
@@ -149,37 +146,18 @@ void nes_nrom_device::common_start()
void nes_nrom_device::pcb_reset()
{
- m_chr_source = m_vrom_chunks ? CHRROM : CHRRAM;
prg32(0);
chr8(0, m_chr_source);
}
-void nes_axrom_device::device_start()
-{
- common_start();
-}
-
void nes_axrom_device::pcb_reset()
{
- m_chr_source = m_vrom_chunks ? CHRROM : CHRRAM;
prg32(0);
chr8(0, m_chr_source);
set_nt_mirroring(PPU_MIRROR_LOW);
}
-void nes_bxrom_device::device_start()
-{
- common_start();
-}
-
-void nes_bxrom_device::pcb_reset()
-{
- m_chr_source = m_vrom_chunks ? CHRROM : CHRRAM;
- prg32(0);
- chr8(0, m_chr_source);
-}
-
void nes_cnrom_device::device_start()
{
common_start();
@@ -188,74 +166,44 @@ void nes_cnrom_device::device_start()
void nes_cnrom_device::pcb_reset()
{
- m_chr_source = m_vrom_chunks ? CHRROM : CHRRAM;
prg32(0);
chr8(0, m_chr_source);
m_chr_open_bus = 0;
}
-void nes_cprom_device::device_start()
-{
- common_start();
-}
-
void nes_cprom_device::pcb_reset()
{
- m_chr_source = CHRRAM;
prg32(0);
chr4_0(0, m_chr_source);
chr4_4(0, m_chr_source);
}
-void nes_gxrom_device::device_start()
-{
- common_start();
-}
-
-void nes_gxrom_device::pcb_reset()
-{
- m_chr_source = m_vrom_chunks ? CHRROM : CHRRAM;
- prg32(0);
- chr8(0, m_chr_source);
-}
-
-void nes_uxrom_device::device_start()
-{
- common_start();
-}
-
void nes_uxrom_device::pcb_reset()
{
- m_chr_source = m_vrom_chunks ? CHRROM : CHRRAM;
prg16_89ab(0);
prg16_cdef(m_prg_chunks - 1);
chr8(0, m_chr_source);
}
-void nes_uxrom_cc_device::device_start()
-{
- common_start();
-}
-
-void nes_uxrom_cc_device::pcb_reset()
+void nes_un1rom_device::pcb_reset()
{
- m_chr_source = m_vrom_chunks ? CHRROM : CHRRAM;
- prg32(0);
+ prg16_89ab(0);
+ prg16_cdef(m_prg_chunks - 1);
chr8(0, m_chr_source);
}
-void nes_un1rom_device::device_start()
+void nes_nochr_device::pcb_reset()
{
- common_start();
-}
+ prg32(0);
-void nes_un1rom_device::pcb_reset()
-{
- m_chr_source = m_vrom_chunks ? CHRROM : CHRRAM;
- prg16_89ab(0);
- prg16_cdef(m_prg_chunks - 1);
- chr8(0, m_chr_source);
+ switch (m_mirroring)
+ {
+ case PPU_MIRROR_VERT: m_ciram_a10 = 10; break;
+ case PPU_MIRROR_HORZ: m_ciram_a10 = 11; break;
+ case PPU_MIRROR_LOW: m_ciram_a10 = 12; break;
+ case PPU_MIRROR_HIGH: m_ciram_a10 = 13; break;
+ }
}
@@ -272,7 +220,7 @@ void nes_un1rom_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
-------------------------------------------------*/
@@ -284,13 +232,13 @@ void nes_un1rom_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];
@@ -300,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)];
}
@@ -327,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);
@@ -356,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);
@@ -382,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);
@@ -411,8 +359,6 @@ void nes_cnrom_device::write_h(offs_t offset, uint8_t data)
uint8_t nes_cnrom_device::chr_r(offs_t offset)
{
- int bank = offset >> 10;
-
// a few CNROM boards contained copy protection schemes through
// suitably configured diodes, so that subsequent CHR reads can
// give actual VROM content or open bus values.
@@ -420,7 +366,7 @@ uint8_t nes_cnrom_device::chr_r(offs_t offset)
if (m_chr_open_bus)
return get_open_bus();
- return m_chr_access[bank][offset & 0x3ff];
+ return device_nes_cart_interface::chr_r(offset);
}
@@ -434,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);
@@ -461,12 +407,12 @@ 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);
- prg32((data & 0xf0) >> 4);
+ prg32(data >> 4);
chr8(data & 0x0f, CHRROM);
}
@@ -481,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);
@@ -507,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);
}
@@ -528,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);
@@ -546,33 +492,39 @@ void nes_un1rom_device::write_h(offs_t offset, uint8_t data)
NoCash NOCHR board emulation
- This is an homebrew PCB design on a single chip
- (+possibly CIC) which uses the NTRAM as CHRRAM!
+ This is a homebrew PCB design on a single chip
+ (+optional CIC) which uses the NTRAM as CHRRAM!
+ One of PPU A10-A13 is tied directly to CIRAM A10,
+ meaning the 16K PPU address space (save for the
+ palette RAM at 0x3f00-0x3fff) appears as the first
+ 1K page of CIRAM 1, 2, 4, or 8 times followed by
+ the second 1K page of CIRAM 1, 2, 4, or 8 times,
+ and then mirrored as many times as necessary.
iNES: mapper 218
- In MESS: Supported.
+ In MAME: Supported.
-------------------------------------------------*/
-void nes_nochr_device::chr_w(offs_t offset, uint8_t data)
+void nes_nochr_device::chr_w(offs_t offset, u8 data)
{
- int mirr = get_mirroring();
- if (mirr == PPU_MIRROR_HIGH)
- m_ciram[(offset & 0x3ff) + 0x000] = data;
- else if (mirr == PPU_MIRROR_LOW)
- m_ciram[(offset & 0x3ff) + 0x400] = data;
- else
- m_ciram[offset & 0x7ff] = data; // not sure here, since there is no software to test...
+ offset = (offset & 0x3ff) | BIT(offset, m_ciram_a10) << 10;
+ m_ciram[offset] = data;
}
-uint8_t nes_nochr_device::chr_r(offs_t offset)
+u8 nes_nochr_device::chr_r(offs_t offset)
{
- int mirr = get_mirroring();
- if (mirr == PPU_MIRROR_HIGH)
- return m_ciram[(offset & 0x3ff) + 0x000];
- else if (mirr == PPU_MIRROR_LOW)
- return m_ciram[(offset & 0x3ff) + 0x400];
- else
- return m_ciram[offset & 0x7ff]; // not sure here, since there is no software to test...
+ offset = (offset & 0x3ff) | BIT(offset, m_ciram_a10) << 10;
+ return m_ciram[offset];
+}
+
+void nes_nochr_device::nt_w(offs_t offset, u8 data)
+{
+ chr_w(offset + 0x2000, data);
+}
+
+u8 nes_nochr_device::nt_r(offs_t offset)
+{
+ return chr_r(offset + 0x2000);
}
diff --git a/src/devices/bus/nes/nxrom.h b/src/devices/bus/nes/nxrom.h
index 382abf05390..01d0a25aa0c 100644
--- a/src/devices/bus/nes/nxrom.h
+++ b/src/devices/bus/nes/nxrom.h
@@ -6,7 +6,6 @@
#pragma once
#include "nes_slot.h"
-#include "sound/samples.h"
// ======================> nes_nrom_device
@@ -65,10 +64,6 @@ public:
virtual void write_h(offs_t offset, uint8_t data) override;
virtual void pcb_reset() override;
-
-protected:
- // device-level overrides
- virtual void device_start() override;
};
@@ -81,12 +76,6 @@ public:
nes_bxrom_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
virtual void write_h(offs_t offset, uint8_t data) override;
-
- virtual void pcb_reset() override;
-
-protected:
- // device-level overrides
- virtual void device_start() override;
};
@@ -107,7 +96,7 @@ protected:
nes_cnrom_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_start() override ATTR_COLD;
private:
uint8_t m_chr_open_bus;
@@ -125,10 +114,6 @@ public:
virtual void write_h(offs_t offset, uint8_t data) override;
virtual void pcb_reset() override;
-
-protected:
- // device-level overrides
- virtual void device_start() override;
};
@@ -141,12 +126,6 @@ public:
nes_gxrom_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
virtual void write_h(offs_t offset, uint8_t data) override;
-
- virtual void pcb_reset() override;
-
-protected:
- // device-level overrides
- virtual void device_start() override;
};
@@ -161,10 +140,6 @@ public:
virtual void write_h(offs_t offset, uint8_t data) override;
virtual void pcb_reset() override;
-
-protected:
- // device-level overrides
- virtual void device_start() override;
};
@@ -177,12 +152,6 @@ public:
nes_uxrom_cc_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
virtual void write_h(offs_t offset, uint8_t data) override;
-
- virtual void pcb_reset() override;
-
-protected:
- // device-level overrides
- virtual void device_start() override;
};
@@ -197,10 +166,6 @@ public:
virtual void write_h(offs_t offset, uint8_t data) override;
virtual void pcb_reset() override;
-
-protected:
- // device-level overrides
- virtual void device_start() override;
};
@@ -210,13 +175,18 @@ class nes_nochr_device : public nes_nrom_device
{
public:
// construction/destruction
- nes_nochr_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
+ nes_nochr_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock);
- // device-level overrides
- virtual uint8_t chr_r(offs_t offset) override;
- virtual void chr_w(offs_t offset, uint8_t data) override;
-};
+ virtual u8 chr_r(offs_t offset) override;
+ virtual void chr_w(offs_t offset, u8 data) override;
+ virtual u8 nt_r(offs_t offset) override;
+ virtual void nt_w(offs_t offset, u8 data) override;
+ virtual void pcb_reset() override;
+
+private:
+ u8 m_ciram_a10;
+};
// device type definition
diff --git a/src/devices/bus/nes/pirate.cpp b/src/devices/bus/nes/pirate.cpp
index acda901ecca..44b7c8acf8d 100644
--- a/src/devices/bus/nes/pirate.cpp
+++ b/src/devices/bus/nes/pirate.cpp
@@ -18,16 +18,14 @@
#include "pirate.h"
#include "video/ppu2c0x.h" // this has to be included so that IRQ functions can access ppu2c0x_device::BOTTOM_VISIBLE_SCANLINE
-#include "screen.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"
//-------------------------------------------------
@@ -36,27 +34,24 @@
DEFINE_DEVICE_TYPE(NES_AGCI_50282, nes_agci_device, "nes_agci50282", "NES Cart AGCI 50282 PCB")
DEFINE_DEVICE_TYPE(NES_DREAMTECH01, nes_dreamtech_device, "nes_dreamtech", "NES Cart Dreamtech01 PCB")
-DEFINE_DEVICE_TYPE(NES_FUKUTAKE, nes_fukutake_device, "nes_futuremedia", "NES Cart Fukutake Study Box PCB")
-DEFINE_DEVICE_TYPE(NES_FUTUREMEDIA, nes_futuremedia_device, "nes_fukutake", "NES Cart FutureMedia PCB")
+DEFINE_DEVICE_TYPE(NES_FUKUTAKE, nes_fukutake_device, "nes_fukutake", "NES Cart Fukutake Study Box PCB")
+DEFINE_DEVICE_TYPE(NES_FUTUREMEDIA, nes_futuremedia_device, "nes_futuremedia", "NES Cart FutureMedia PCB")
DEFINE_DEVICE_TYPE(NES_MAGSERIES, nes_magseries_device, "nes_magseries", "NES Cart Magical Series PCB")
DEFINE_DEVICE_TYPE(NES_DAOU306, nes_daou306_device, "nes_daou306", "NES Cart Daou 306 PCB")
DEFINE_DEVICE_TYPE(NES_CC21, nes_cc21_device, "nes_cc21", "NES Cart CC-21 PCB")
DEFINE_DEVICE_TYPE(NES_XIAOZY, nes_xiaozy_device, "nes_xiaozy", "NES Cart Xiao Zhuan Yuan PCB")
DEFINE_DEVICE_TYPE(NES_EDU2K, nes_edu2k_device, "nes_edu2k", "NES Cart Educational Computer 2000 PCB")
-DEFINE_DEVICE_TYPE(NES_T230, nes_t230_device, "nes_t230", "NES Cart T-230 PCB")
-DEFINE_DEVICE_TYPE(NES_MK2, nes_mk2_device, "nes_mk2", "NES Cart Mortal Kombat 2 PCB")
-DEFINE_DEVICE_TYPE(NES_WHERO, nes_whero_device, "nes_whero", "NES Cart World Heroes PCB")
+DEFINE_DEVICE_TYPE(NES_JY830623C, nes_jy830623c_device, "nes_jy830623c", "NES Cart JY830623C PCB")
DEFINE_DEVICE_TYPE(NES_43272, nes_43272_device, "nes_43272", "NES Cart UNL-43272 PCB")
-DEFINE_DEVICE_TYPE(NES_TF1201, nes_tf1201_device, "nes_tf1201", "NES Cart UNL-TF1201 PCB")
-DEFINE_DEVICE_TYPE(NES_CITYFIGHT, nes_cityfight_device, "nes_cityfight", "NES Cart City Fighter PCB")
+DEFINE_DEVICE_TYPE(NES_EH8813A, nes_eh8813a_device, "nes_eh8813a", "NES Cart UNL-EH8813A PCB")
-nes_agci_device::nes_agci_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
+nes_agci_device::nes_agci_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock)
: nes_nrom_device(mconfig, NES_AGCI_50282, tag, owner, clock)
{
}
-nes_dreamtech_device::nes_dreamtech_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
+nes_dreamtech_device::nes_dreamtech_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock)
: nes_nrom_device(mconfig, NES_DREAMTECH01, tag, owner, clock)
{
}
@@ -66,22 +61,22 @@ nes_fukutake_device::nes_fukutake_device(const machine_config &mconfig, const ch
{
}
-nes_futuremedia_device::nes_futuremedia_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
- : nes_nrom_device(mconfig, NES_FUTUREMEDIA, tag, owner, clock), m_irq_count(0), m_irq_count_latch(0), m_irq_clear(0), m_irq_enable(0)
+nes_futuremedia_device::nes_futuremedia_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock)
+ : nes_nrom_device(mconfig, NES_FUTUREMEDIA, tag, owner, clock), m_irq_count(0), m_irq_count_latch(0), m_irq_enable(0)
{
}
-nes_magseries_device::nes_magseries_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
+nes_magseries_device::nes_magseries_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock)
: nes_nrom_device(mconfig, NES_MAGSERIES, tag, owner, clock)
{
}
-nes_daou306_device::nes_daou306_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
+nes_daou306_device::nes_daou306_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock)
: nes_nrom_device(mconfig, NES_DAOU306, tag, owner, clock)
{
}
-nes_cc21_device::nes_cc21_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
+nes_cc21_device::nes_cc21_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock)
: nes_nrom_device(mconfig, NES_CC21, tag, owner, clock)
{
}
@@ -96,18 +91,8 @@ nes_edu2k_device::nes_edu2k_device(const machine_config &mconfig, const char *ta
{
}
-nes_t230_device::nes_t230_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
- : nes_nrom_device(mconfig, NES_T230, tag, owner, clock), m_irq_count(0), m_irq_count_latch(0), m_irq_mode(0), m_irq_enable(0), m_irq_enable_latch(0)
-{
-}
-
-nes_mk2_device::nes_mk2_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
- : nes_nrom_device(mconfig, NES_MK2, tag, owner, clock), m_irq_count(0), m_irq_count_latch(0), m_irq_clear(0), m_irq_enable(0)
-{
-}
-
-nes_whero_device::nes_whero_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
- : nes_nrom_device(mconfig, NES_WHERO, tag, owner, clock), m_reg(0), m_irq_count(0), m_irq_count_latch(0), m_irq_enable(0), m_irq_enable_latch(0)
+nes_jy830623c_device::nes_jy830623c_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock)
+ : nes_nrom_device(mconfig, NES_JY830623C, tag, owner, clock), m_latch(0), m_irq_count(0), m_irq_count_latch(0), m_irq_enable(0)
{
}
@@ -116,42 +101,18 @@ nes_43272_device::nes_43272_device(const machine_config &mconfig, const char *ta
{
}
-nes_tf1201_device::nes_tf1201_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
- : nes_nrom_device(mconfig, NES_TF1201, tag, owner, clock), m_prg(0), m_swap(0), m_irq_count(0), m_irq_enable(0), m_irq_enable_latch(0)
-{
-}
-
-nes_cityfight_device::nes_cityfight_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
- : nes_nrom_device(mconfig, NES_CITYFIGHT, tag, owner, clock), m_prg_reg(0), m_prg_mode(0), m_irq_count(0), m_irq_enable(0), irq_timer(nullptr)
+nes_eh8813a_device::nes_eh8813a_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock)
+ : nes_nrom_device(mconfig, NES_EH8813A, tag, owner, clock), m_jumper(0), m_latch(0), m_reg(0)
{
}
-void nes_agci_device::device_start()
-{
- common_start();
-}
-
-void nes_agci_device::pcb_reset()
-{
- m_chr_source = m_vrom_chunks ? CHRROM : CHRRAM;
- prg32(0);
- chr8(0, m_chr_source);
-}
-
-void nes_dreamtech_device::device_start()
-{
- common_start();
-}
-
void nes_dreamtech_device::pcb_reset()
{
- m_chr_source = m_vrom_chunks ? CHRROM : CHRRAM;
prg16_89ab(0);
prg16_cdef(8);
- chr8(0, m_chr_source);
}
void nes_fukutake_device::device_start()
@@ -165,7 +126,6 @@ void nes_fukutake_device::device_start()
void nes_fukutake_device::pcb_reset()
{
- m_chr_source = m_vrom_chunks ? CHRROM : CHRRAM;
prg16_89ab(0);
prg16_cdef(0);
chr8(0, m_chr_source);
@@ -176,7 +136,6 @@ void nes_fukutake_device::pcb_reset()
void nes_futuremedia_device::device_start()
{
common_start();
- save_item(NAME(m_irq_clear));
save_item(NAME(m_irq_enable));
save_item(NAME(m_irq_count));
save_item(NAME(m_irq_count_latch));
@@ -184,28 +143,14 @@ void nes_futuremedia_device::device_start()
void nes_futuremedia_device::pcb_reset()
{
- m_chr_source = m_vrom_chunks ? CHRROM : CHRRAM;
prg16_89ab(0);
prg16_cdef(m_prg_chunks - 1);
- chr8(0, m_chr_source);
+ chr8(0, CHRROM);
- m_irq_clear = 0;
m_irq_enable = 0;
m_irq_count = m_irq_count_latch = 0;
}
-void nes_magseries_device::device_start()
-{
- common_start();
-}
-
-void nes_magseries_device::pcb_reset()
-{
- m_chr_source = m_vrom_chunks ? CHRROM : CHRRAM;
- prg32(0);
- chr8(0, m_chr_source);
-}
-
void nes_daou306_device::device_start()
{
common_start();
@@ -214,35 +159,24 @@ void nes_daou306_device::device_start()
void nes_daou306_device::pcb_reset()
{
- m_chr_source = m_vrom_chunks ? CHRROM : CHRRAM;
prg16_89ab(m_prg_chunks - 2);
prg16_cdef(m_prg_chunks - 1);
chr8(0, m_chr_source);
set_nt_mirroring(PPU_MIRROR_LOW);
- memset(m_reg, 0, sizeof(m_reg));
-}
-
-void nes_cc21_device::device_start()
-{
- common_start();
+ std::fill(std::begin(m_reg), std::end(m_reg), 0x00);
}
void nes_cc21_device::pcb_reset()
{
- m_chr_source = m_vrom_chunks ? CHRROM : CHRRAM;
prg32(0);
- chr8(0, m_chr_source);
-}
-
-void nes_xiaozy_device::device_start()
-{
- common_start();
+ chr4_0(0, CHRROM);
+ chr4_4(0, CHRROM);
+ set_nt_mirroring(PPU_MIRROR_LOW);
}
void nes_xiaozy_device::pcb_reset()
{
- m_chr_source = m_vrom_chunks ? CHRROM : CHRRAM;
prg32((m_prg_chunks - 1) >> 1);
chr8(0, m_chr_source);
}
@@ -255,88 +189,33 @@ void nes_edu2k_device::device_start()
void nes_edu2k_device::pcb_reset()
{
- m_chr_source = m_vrom_chunks ? CHRROM : CHRRAM;
prg32(0);
chr8(0, m_chr_source);
m_latch = 0;
}
-void nes_t230_device::device_start()
-{
- common_start();
- save_item(NAME(m_irq_mode));
- save_item(NAME(m_irq_enable));
- save_item(NAME(m_irq_enable_latch));
- save_item(NAME(m_irq_count));
- save_item(NAME(m_irq_count_latch));
- save_item(NAME(m_mmc_vrom_bank));
-}
-
-void nes_t230_device::pcb_reset()
-{
- m_chr_source = m_vrom_chunks ? CHRROM : CHRRAM;
- prg16_89ab(0);
- prg16_cdef(m_prg_chunks - 1);
- chr8(0, m_chr_source);
-
- m_irq_mode = 0;
- m_irq_enable = m_irq_enable_latch = 0;
- m_irq_count = m_irq_count_latch = 0;
-
- memset(m_mmc_vrom_bank, 0, sizeof(m_mmc_vrom_bank));
-}
-
-void nes_mk2_device::device_start()
+void nes_jy830623c_device::device_start()
{
common_start();
- save_item(NAME(m_irq_clear));
+ save_item(NAME(m_latch));
+ save_item(NAME(m_reg));
save_item(NAME(m_irq_enable));
save_item(NAME(m_irq_count));
save_item(NAME(m_irq_count_latch));
}
-void nes_mk2_device::pcb_reset()
+void nes_jy830623c_device::pcb_reset()
{
- m_chr_source = m_vrom_chunks ? CHRROM : CHRRAM;
- prg16_89ab(m_prg_chunks - 1);
- prg16_cdef(m_prg_chunks - 1);
- chr8(0, m_chr_source);
+ m_latch = 0;
+ std::fill(std::begin(m_reg), std::end(m_reg), 0x00);
+ update_banks();
set_nt_mirroring(PPU_MIRROR_VERT);
- m_irq_clear = 0;
m_irq_enable = 0;
m_irq_count = m_irq_count_latch = 0;
}
-
-void nes_whero_device::device_start()
-{
- common_start();
- save_item(NAME(m_irq_enable));
- save_item(NAME(m_irq_enable_latch));
- save_item(NAME(m_irq_count));
- save_item(NAME(m_irq_count_latch));
- save_item(NAME(m_reg));
- save_item(NAME(m_mmc_vrom_bank));
-}
-
-void nes_whero_device::pcb_reset()
-{
- m_chr_source = m_vrom_chunks ? CHRROM : CHRRAM;
- prg16_89ab(0);
- prg16_cdef(m_prg_chunks - 1);
- chr8(0x100, m_chr_source);
-
- m_irq_enable = 0;
- m_irq_enable_latch = 0;
- m_irq_count = 0;
- m_irq_count_latch = 0;
-
- m_reg = 0;
- memset(m_mmc_vrom_bank, 0, sizeof(m_mmc_vrom_bank));
-}
-
void nes_43272_device::device_start()
{
common_start();
@@ -345,64 +224,28 @@ void nes_43272_device::device_start()
void nes_43272_device::pcb_reset()
{
- m_chr_source = m_vrom_chunks ? CHRROM : CHRRAM;
prg32((m_prg_chunks - 1) >> 1);
chr8(0, m_chr_source);
m_latch = 0x81;
}
-void nes_tf1201_device::device_start()
+void nes_eh8813a_device::device_start()
{
common_start();
- save_item(NAME(m_prg));
- save_item(NAME(m_swap));
- save_item(NAME(m_irq_enable));
- save_item(NAME(m_irq_enable_latch));
- save_item(NAME(m_irq_count));
- save_item(NAME(m_mmc_vrom_bank));
-}
-
-void nes_tf1201_device::pcb_reset()
-{
- m_chr_source = m_vrom_chunks ? CHRROM : CHRRAM;
- prg16_89ab(0);
- prg16_cdef(m_prg_chunks - 1);
- chr8(0, m_chr_source);
-
- memset(m_mmc_vrom_bank, 0, sizeof(m_mmc_vrom_bank));
- m_prg = 0;
- m_swap = 0;
- m_irq_enable = 0;
- m_irq_enable_latch = 0;
- m_irq_count = 0;
-}
-
-void nes_cityfight_device::device_start()
-{
- common_start();
- irq_timer = timer_alloc(TIMER_IRQ);
- irq_timer->adjust(attotime::zero, 0, clocks_to_attotime(1));
-
- save_item(NAME(m_prg_reg));
- save_item(NAME(m_prg_mode));
- save_item(NAME(m_irq_enable));
- save_item(NAME(m_irq_count));
- save_item(NAME(m_mmc_vrom_bank));
+ save_item(NAME(m_jumper));
+ save_item(NAME(m_latch));
+ save_item(NAME(m_reg));
}
-void nes_cityfight_device::pcb_reset()
+void nes_eh8813a_device::pcb_reset()
{
- m_chr_source = m_vrom_chunks ? CHRROM : CHRRAM;
- prg16_89ab(0);
- prg16_cdef(m_prg_chunks - 1);
- chr8(0, m_chr_source);
+ prg32(0);
+ chr8(0, CHRROM);
- memset(m_mmc_vrom_bank, 0, sizeof(m_mmc_vrom_bank));
- m_prg_reg = 0;
- m_prg_mode = 0;
- m_irq_enable = 0;
- m_irq_count = 0;
+ m_jumper = 0;
+ m_latch = 0;
+ m_reg = 0;
}
@@ -419,17 +262,17 @@ void nes_cityfight_device::pcb_reset()
iNES: mapper 144
- In MESS: Supported.
+ In MAME: Supported.
-------------------------------------------------*/
-void nes_agci_device::write_h(offs_t offset, uint8_t data)
+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
- uint8_t temp = account_bus_conflict(offset, 0xff);
- data = (data & temp) | (temp & 1);
+ // bit 0 is always determined by the ROM value at the offset due to a resistor on the board
+ data = account_bus_conflict(offset, data | 1);
chr8(data >> 4, CHRROM);
prg32(data);
@@ -441,16 +284,18 @@ void nes_agci_device::write_h(offs_t offset, uint8_t data)
Games: Korean Igo
- In MESS: Supported
+ NES 2.0: mapper 521
+
+ In MAME: Supported.
-------------------------------------------------*/
-void nes_dreamtech_device::write_l(offs_t offset, uint8_t data)
+void nes_dreamtech_device::write_l(offs_t offset, u8 data)
{
- LOG_MMC(("dreamtech write_l, offset: %04x, data: %02x\n", offset, data));
- offset += 0x100;
+ LOG("dreamtech write_l, offset: %04x, data: %02x\n", offset, data);
- if (offset == 0x1020) /* 0x5020 */
+ offset += 0x100;
+ if (offset >= 0x1000)
prg16_89ab(data);
}
@@ -462,14 +307,13 @@ void nes_dreamtech_device::write_l(offs_t offset, uint8_t data)
iNES: mapper 186
- In MESS: Unsupported.
-
+ In MAME: Unsupported.
-------------------------------------------------*/
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)
@@ -485,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)
@@ -505,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)];
}
@@ -523,11 +367,11 @@ uint8_t nes_fukutake_device::read_m(offs_t offset)
iNES: mapper 117
- In MESS: Unsupported.
+ In MAME: Partially supported.
-------------------------------------------------*/
-void nes_futuremedia_device::hblank_irq(int scanline, int vblank, int blanked)
+void nes_futuremedia_device::hblank_irq(int scanline, bool vblank, bool blanked)
{
// if (scanline < ppu2c0x_device::BOTTOM_VISIBLE_SCANLINE)
{
@@ -535,28 +379,22 @@ void nes_futuremedia_device::hblank_irq(int scanline, int vblank, int blanked)
{
m_irq_count--;
if (!m_irq_count)
- hold_irq_line();
+ set_irq_line(ASSERT_LINE);
}
}
}
-void nes_futuremedia_device::write_h(offs_t offset, uint8_t data)
+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)
{
case 0x0000:
- prg8_89(data);
- break;
case 0x0001:
- prg8_ab(data);
- break;
case 0x0002:
- prg8_cd(data);
- break;
case 0x0003:
- prg8_ef(data);
+ prg8_x(offset & 0x03, data);
break;
case 0x2000:
case 0x2001:
@@ -568,22 +406,21 @@ void nes_futuremedia_device::write_h(offs_t offset, uint8_t data)
case 0x2007:
chr1_x(offset & 0x07, data, CHRROM);
break;
-
- case 0x5000:
- set_nt_mirroring(BIT(data, 0) ? PPU_MIRROR_HORZ : PPU_MIRROR_VERT);
- break;
-
case 0x4001:
m_irq_count_latch = data;
break;
case 0x4002:
- // IRQ cleared
+ set_irq_line(CLEAR_LINE);
break;
case 0x4003:
m_irq_count = m_irq_count_latch;
break;
+ case 0x5000:
+ set_nt_mirroring(BIT(data, 0) ? PPU_MIRROR_HORZ : PPU_MIRROR_VERT);
+ break;
case 0x6000:
m_irq_enable = data & 0x01;
+ set_irq_line(CLEAR_LINE);
break;
}
}
@@ -599,13 +436,13 @@ void nes_futuremedia_device::write_h(offs_t offset, uint8_t data)
iNES: mapper 107
- In MESS: Supported.
+ In MAME: Supported.
-------------------------------------------------*/
-void nes_magseries_device::write_h(offs_t offset, uint8_t 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);
@@ -619,70 +456,28 @@ void nes_magseries_device::write_h(offs_t offset, uint8_t data)
iNES: mapper 156
- In MESS: Supported.
+ In MAME: Supported.
Notes: Metal Force and Buzz & Waldog only use the first 4
regs and no mirroring. Janggun ui Adeul uses all features
-------------------------------------------------*/
-void nes_daou306_device::write_h(offs_t offset, uint8_t data)
+void nes_daou306_device::write_h(offs_t offset, u8 data)
{
- LOG_MMC(("daou306 write_h, offset: %04x, data: %02x\n", offset, data));
- int reg = BIT(offset, 2) ? 8 : 0;
+ LOG("daou306 write_h, offset: %04x, data: %02x\n", offset, data);
- switch (offset)
+ if (offset >= 0x4000 && offset < 0x4010)
{
- case 0x4000:
- case 0x4004:
- m_reg[reg + 0] = data;
- chr1_0(m_reg[0] | (m_reg[8] << 8), CHRROM);
- break;
- case 0x4001:
- case 0x4005:
- m_reg[reg + 1] = data;
- chr1_1(m_reg[1] | (m_reg[9] << 8), CHRROM);
- break;
- case 0x4002:
- case 0x4006:
- m_reg[reg + 2] = data;
- chr1_2(m_reg[2] | (m_reg[10] << 8), CHRROM);
- break;
- case 0x4003:
- case 0x4007:
- m_reg[reg + 3] = data;
- chr1_3(m_reg[3] | (m_reg[11] << 8), CHRROM);
- break;
- case 0x4008:
- case 0x400c:
- m_reg[reg + 4] = data;
- chr1_4(m_reg[4] | (m_reg[12] << 8), CHRROM);
- break;
- case 0x4009:
- case 0x400d:
- m_reg[reg + 5] = data;
- chr1_5(m_reg[5] | (m_reg[13] << 8), CHRROM);
- break;
- case 0x400a:
- case 0x400e:
- m_reg[reg + 6] = data;
- chr1_6(m_reg[6] | (m_reg[14] << 8), CHRROM);
- break;
- case 0x400b:
- case 0x400f:
- m_reg[reg + 7] = data;
- chr1_7(m_reg[7] | (m_reg[15] << 8), CHRROM);
- break;
- case 0x4010:
- prg16_89ab(data);
- break;
- case 0x4014:
- if (data & 1)
- set_nt_mirroring(PPU_MIRROR_HORZ);
- else
- set_nt_mirroring(PPU_MIRROR_VERT);
- break;
+ int reg = bitswap<4>(offset, 2, 3, 1, 0);
+ m_reg[reg] = data;
+ reg &= 0x07;
+ chr1_x(reg, m_reg[reg] | (m_reg[reg | 8] << 8), CHRROM);
}
+ else if (offset == 0x4010)
+ prg16_89ab(data);
+ else if (offset == 0x4014)
+ set_nt_mirroring(data & 1 ? PPU_MIRROR_HORZ : PPU_MIRROR_VERT);
}
/*-------------------------------------------------
@@ -691,16 +486,19 @@ void nes_daou306_device::write_h(offs_t offset, uint8_t data)
Games: Mi Hun Che
- In MESS: Supported
+ iNES: mapper 27 (overlaps with incompatible World Hero)
+
+ In MAME: Supported.
-------------------------------------------------*/
-void nes_cc21_device::write_h(offs_t offset, uint8_t 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, 1) ? PPU_MIRROR_HIGH : PPU_MIRROR_LOW);
- chr8((offset & 0x01), CHRROM);
+ set_nt_mirroring(BIT(offset, 0) ? PPU_MIRROR_HIGH : PPU_MIRROR_LOW);
+ chr4_0(BIT(offset, 0), CHRROM);
+ chr4_4(BIT(offset, 0), CHRROM);
}
/*-------------------------------------------------
@@ -714,13 +512,13 @@ void nes_cc21_device::write_h(offs_t offset, uint8_t 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)
{
@@ -741,276 +539,125 @@ 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 = (data & 0xc0) >> 6;
+ m_latch = BIT(data, 6, 2);
}
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)];
}
/*-------------------------------------------------
- Board UNL-T-230
-
- Games: Dragon Ball Z IV (Unl)
-
- This mapper appears to be similar to Konami VRC-2
- but the game has no VROM and only 1 VRAM bank, so we
- completely skip the chr bankswitch. If other games
- using the same board and using CHR should surface,
- we need to investigate this...
-
- In MESS: Supported
-
- -------------------------------------------------*/
-
-// Identical to Konami IRQ
-void nes_t230_device::hblank_irq(int scanline, int vblank, int blanked)
-{
- /* Increment & check the IRQ scanline counter */
- if (m_irq_enable && (++m_irq_count == 0x100))
- {
- m_irq_count = m_irq_count_latch;
- m_irq_enable = m_irq_enable_latch;
- hold_irq_line();
- }
-}
-
-void nes_t230_device::write_h(offs_t offset, uint8_t data)
-{
- LOG_MMC(("t230 write_h, offset: %04x, data: %02x\n", offset, data));
-
- switch (offset & 0x700c)
- {
- case 0x0000:
- break;
- case 0x2000:
- prg16_89ab(data);
- break;
- case 0x1000:
- case 0x1004:
- case 0x1008:
- case 0x100c:
- switch (data & 0x03)
- {
- case 0x00: set_nt_mirroring(PPU_MIRROR_VERT); break;
- case 0x01: set_nt_mirroring(PPU_MIRROR_HORZ); break;
- case 0x02: set_nt_mirroring(PPU_MIRROR_LOW); break;
- case 0x03: set_nt_mirroring(PPU_MIRROR_HIGH); break;
- }
- break;
-
- case 0x7000:
- m_irq_count_latch &= ~0x0f;
- m_irq_count_latch |= data & 0x0f;
- break;
- case 0x7004:
- m_irq_count_latch &= ~0xf0;
- m_irq_count_latch |= (data << 4) & 0xf0;
- break;
- case 0x7008:
- m_irq_mode = data & 0x04; // currently not implemented: 0 = prescaler mode / 1 = CPU mode
- m_irq_enable = data & 0x02;
- m_irq_enable_latch = data & 0x01;
- if (data & 0x02)
- m_irq_count = m_irq_count_latch;
- break;
-
- default:
- logerror("unl_t230_w uncaught offset: %04x value: %02x\n", offset, data);
- break;
- }
-}
-
-/*-------------------------------------------------
-
- Bootleg Board for MK2
+ Bootleg Board JY830623C
Games: Mortal Kombat II, Street Fighter III, Super Mario
Kart Rider
- This board uses an IRQ system very similar to MMC3. We indeed
- use mapper4_irq, but there is some small glitch!
-
iNES: mapper 91
- In MESS: Supported.
+ In MAME: Partially supported.
+
+ FIXME: IRQ is fixed length but not every 7 scanlines
+ as done here. Rather it triggers once every 64 rises
+ of PPU A12. Various games have very obvious raster-
+ split issues from this bug. Also note there is
+ another submapper with cycle-based IRQ.
-------------------------------------------------*/
-// Same IRQ as MMC3
-void nes_mk2_device::hblank_irq( int scanline, int vblank, int blanked )
+void nes_jy830623c_device::hblank_irq(int scanline, bool vblank, bool blanked)
{
if (scanline < ppu2c0x_device::BOTTOM_VISIBLE_SCANLINE)
{
int prior_count = m_irq_count;
- if ((m_irq_count == 0) || m_irq_clear)
- m_irq_count = m_irq_count_latch;
- else
+ if (m_irq_count)
m_irq_count--;
+ else
+ m_irq_count = m_irq_count_latch;
- if (m_irq_enable && !blanked && (m_irq_count == 0) && (prior_count || m_irq_clear))
+ if (m_irq_enable && !blanked && !m_irq_count && prior_count)
{
- LOG_MMC(("irq fired, scanline: %d\n", scanline));
- hold_irq_line();
+ LOG("irq fired, scanline: %d\n", scanline);
+ set_irq_line(ASSERT_LINE);
}
}
- m_irq_clear = 0;
}
-void nes_mk2_device::write_m(offs_t offset, uint8_t data)
+void nes_jy830623c_device::update_banks()
{
- LOG_MMC(("mk2 write_m, offset: %04x, data: %02x\n", offset, data));
-
- switch (offset & 0x1000)
- {
- case 0x0000:
- switch (offset & 0x03)
- {
- case 0x00: chr2_0(data, CHRROM); break;
- case 0x01: chr2_2(data, CHRROM); break;
- case 0x02: chr2_4(data, CHRROM); break;
- case 0x03: chr2_6(data, CHRROM); break;
- }
- break;
- case 0x1000:
- switch (offset & 0x03)
- {
- case 0x00: prg8_89(data); break;
- case 0x01: prg8_ab(data); break;
- case 0x02: m_irq_enable = 0; m_irq_count = 0; break;
- case 0x03: m_irq_enable = 1; m_irq_count = 7; break;
- }
- break;
- default:
- logerror("mk2 write_m, uncaught addr: %04x value: %02x\n", offset + 0x6000, data);
- break;
- }
-}
-
-
-/*-------------------------------------------------
-
- UNL-WOLRDHERO board emulation
+ prg8_89((m_latch & 0x06) << 3 | m_reg[4]);
+ prg8_ab((m_latch & 0x06) << 3 | m_reg[5]);
+ prg16_cdef((m_latch & 0x06) << 2 | 0x07);
-
- iNES:
-
- -------------------------------------------------*/
-
-// Same as Konami VRC IRQ...
-void nes_whero_device::hblank_irq(int scanline, int vblank, int blanked)
-{
- /* Increment & check the IRQ scanline counter */
- if (m_irq_enable && (++m_irq_count == 0x100))
- {
- m_irq_count = m_irq_count_latch;
- m_irq_enable = m_irq_enable_latch;
- hold_irq_line();
- }
+ for (int i = 0; i < 4; i++)
+ chr2_x(2 * i, (m_latch & 1) << 8 | m_reg[i], CHRROM);
}
-void nes_whero_device::write_h(offs_t offset, uint8_t data)
+void nes_jy830623c_device::write_m(offs_t offset, u8 data)
{
- int bank, shift, mask1, mask2;
- LOG_MMC(("World Hero write_h, offset: %04x, data: %02x\n", offset, data));
+ LOG("jy830623c write_m, offset: %04x, data: %02x\n", offset, data);
- switch (offset & 0x70c3)
+ switch (offset & 0x1003)
{
case 0x0000:
- if (!m_reg)
- prg8_89(data);
- else
- prg8_cd(data);
- break;
-
+ case 0x0001:
+ case 0x0002:
+ case 0x0003:
case 0x1000:
- switch (data & 0x03)
- {
- case 0x00: set_nt_mirroring(PPU_MIRROR_VERT); break;
- case 0x01: set_nt_mirroring(PPU_MIRROR_HORZ); break;
- case 0x02: set_nt_mirroring(PPU_MIRROR_LOW); break;
- case 0x03: set_nt_mirroring(PPU_MIRROR_HIGH); break;
- }
+ case 0x1001:
+ m_reg[bitswap<3>(offset, 12, 1, 0)] = data;
+ update_banks();
break;
-
case 0x1002:
- case 0x1080:
- if (m_reg != (data & 2))
- {
- m_reg = data & 2;
- // swap banks!
- prg8_89(m_prg_bank[2]);
- prg8_cd(m_prg_bank[0]);
- }
- break;
-
- case 0x2000:
- prg8_ab(data);
+ m_irq_enable = 0;
+ m_irq_count = 0;
+ set_irq_line(CLEAR_LINE);
break;
-
- case 0x3000: case 0x3001: case 0x3002: case 0x3003:
- case 0x4000: case 0x4001: case 0x4002: case 0x4003:
- case 0x5000: case 0x5001: case 0x5002: case 0x5003:
- case 0x6000: case 0x6001: case 0x6002: case 0x6003:
- bank = ((offset & 0x7000) - 0x3000) / 0x0800 + BIT(offset, 1);
- shift = (offset & 1) << 2;
- mask1 = shift ? 0x00f : 0xff0;
- mask2 = shift ? 0xff0 : 0x00f;
- m_mmc_vrom_bank[bank] = (m_mmc_vrom_bank[bank] & mask1) | ((data << shift) & mask2);
- chr1_x(bank, m_mmc_vrom_bank[bank], CHRROM);
- break;
-
- case 0x7000:
- m_irq_count_latch = (m_irq_count_latch & 0xf0) | (data & 0x0f);
- break;
-
- case 0x7001:
- m_irq_count_latch = (m_irq_count_latch & 0x0f) | ((data & 0x0f) << 4);
+ case 0x1003:
+ m_irq_enable = 1;
+ m_irq_count = 7;
break;
+ }
+}
- case 0x7002:
- // m_irq_mode = data & 0x04; // currently not implemented: 0 = prescaler mode / 1 = CPU mode
- m_irq_enable = data & 0x02;
- m_irq_enable_latch = data & 0x01;
- if (data & 0x02)
- m_irq_count = m_irq_count_latch;
- break;
+void nes_jy830623c_device::write_h(offs_t offset, u8 data)
+{
+ LOG("jy830623c write_h, offset: %04x, data: %02x\n", offset, data);
- case 0x7003:
- m_irq_enable = m_irq_enable_latch;
- break;
+ if (offset < 0x2000)
+ {
+ m_latch = offset;
+ update_banks();
}
}
-
/*-------------------------------------------------
UNL-43272
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((m_latch & 0x38) >> 3);
+ prg32(BIT(m_latch, 3, 3));
m_latch = offset & 0xffff;
}
@@ -1019,202 +666,51 @@ 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);
}
-
/*-------------------------------------------------
- UNL-TF1201
+ UNL-EH8813A
+
+ Games: Dr. Mario II, 1996 English CAI 3 in 1,
+ Elementary School Math CAI
- Games:
+ NES 2.0: mapper 519
- In MESS: Preliminary Supported
+ In MAME: Supported.
-------------------------------------------------*/
-void nes_tf1201_device::hblank_irq(int scanline, int vblank, int blanked)
+void nes_eh8813a_device::write_h(offs_t offset, u8 data)
{
- if (m_irq_enable_latch != m_irq_enable && scanline < 240)
- m_irq_count -= 8;
+ LOG("unl_eh8813a write_h, offset: %04x, data: %02x\n", offset, data);
- if (m_irq_enable)
+ if (!BIT(m_latch, 8))
{
- m_irq_count++;
- if ((m_irq_count & 0xff) == 238)
- hold_irq_line();
- }
-}
+ m_latch = offset;
+ m_reg = data;
-void nes_tf1201_device::update_prg()
-{
- prg8_89(m_swap ? 0xff : m_prg);
- prg8_cd(m_swap ? m_prg : 0xff );
-}
+ u8 bank = m_latch & 0x3f;
+ u8 mode = !BIT(m_latch, 7);
+ prg16_89ab(bank & ~mode);
+ prg16_cdef(bank | mode);
-void nes_tf1201_device::write_h(offs_t offset, uint8_t data)
-{
- int bank;
- LOG_MMC(("unl_tf1201 write_h, offset: %04x, data: %02x\n", offset, data));
-
- offset = (offset & 0x7003) | ((offset & 0x0c) >> 2); // nestopia does not OR here...
-
- switch (offset & 0x7003)
- {
- case 0x0000:
- m_prg = data;
- update_prg();
- break;
- case 0x1000:
- set_nt_mirroring(BIT(data, 0) ? PPU_MIRROR_HORZ : PPU_MIRROR_VERT);
- break;
- case 0x1001:
- m_swap = data & 0x03;
- update_prg();
- break;
- case 0x2000:
- prg8_ab(data);
- break;
- case 0x3000: case 0x3001: case 0x3002: case 0x3003:
- case 0x4000: case 0x4001: case 0x4002: case 0x4003:
- case 0x5000: case 0x5001: case 0x5002: case 0x5003:
- case 0x6000: case 0x6001: case 0x6002: case 0x6003:
- bank = (((offset - 0x3000) >> 11) | (offset & 0x1)) & 0x7;
- if (offset & 2)
- m_mmc_vrom_bank[bank] = (m_mmc_vrom_bank[bank] & 0x0f) | ((data & 0x0f) << 4);
- else
- m_mmc_vrom_bank[bank] = (m_mmc_vrom_bank[bank] & 0xf0) | ((data & 0x0f) << 0);
- chr1_x(bank, m_mmc_vrom_bank[bank], m_chr_source);
- break;
- case 0x7000:
- m_irq_count = (m_irq_count & 0xf0) | (data & 0x0f);
- break;
- case 0x7001:
- case 0x7003:
- m_irq_enable_latch = m_irq_enable;
- m_irq_enable = BIT(data, 1);
- break;
- case 0x7002:
- m_irq_count = (m_irq_count & 0x0f) | ((data & 0x0f) << 4);
- break;
+ set_nt_mirroring(BIT(m_reg, 7) ? PPU_MIRROR_HORZ : PPU_MIRROR_VERT);
}
-}
-
-/*-------------------------------------------------
-
- UNL-CITYFIGHT
-
- Games:
-
- Additional audio register not emulated yet!
-
- In MESS: Preliminary Supported
-
- -------------------------------------------------*/
-
-void nes_cityfight_device::device_timer(emu_timer &timer, device_timer_id id, int param, void *ptr)
-{
- if (id == TIMER_IRQ)
- {
- if (m_irq_enable)
- {
- if (!m_irq_count)
- {
- hold_irq_line();
- m_irq_count = 0xffff;
- }
- else
- m_irq_count--;
- }
- }
-}
-
-void nes_cityfight_device::update_prg()
-{
- prg32(m_prg_reg >> 2);
- if (!m_prg_mode)
- prg8_cd(m_prg_reg);
+ chr8((m_reg & 0x7c) | (data & 0x03), CHRROM);
}
-void nes_cityfight_device::write_h(offs_t offset, uint8_t data)
+u8 nes_eh8813a_device::read_h(offs_t offset)
{
- int bank;
- LOG_MMC(("unl_cityfight write_h, offset: %04x, data: %02x\n", offset, data));
+ LOG("unl_eh8813a read_h, offset: %04x\n", offset);
- switch (offset & 0x700c)
- {
- case 0x1000:
- switch (data & 0x03)
- {
- case 0x00: set_nt_mirroring(PPU_MIRROR_VERT); break;
- case 0x01: set_nt_mirroring(PPU_MIRROR_HORZ); break;
- case 0x02: set_nt_mirroring(PPU_MIRROR_LOW); break;
- case 0x03: set_nt_mirroring(PPU_MIRROR_HIGH); break;
- }
- m_prg_reg = data & 0xc;
- break;
- case 0x1004:
- case 0x1008:
- case 0x100c:
- if (offset & 0x800)
- LOG_MMC(("Extended Audio write, data %x!", data & 0x0f));//pcmwrite(0x4011, (V & 0xf) << 3);
- else
- m_prg_reg = data & 0xc;
- break;
-
-
- case 0x2000: case 0x2004: case 0x2008: case 0x200c:
- bank = 2 + BIT(offset, 3);
- if (offset & 4)
- m_mmc_vrom_bank[bank] = (m_mmc_vrom_bank[bank] & 0x0f) | ((data & 0x0f) << 4);
- else
- m_mmc_vrom_bank[bank] = (m_mmc_vrom_bank[bank] & 0xf0) | ((data & 0x0f) << 0);
- chr1_x(bank, m_mmc_vrom_bank[bank], m_chr_source);
- break;
- case 0x3000: case 0x3004: case 0x3008: case 0x300c:
- bank = 4 + BIT(offset, 3);
- if (offset & 4)
- m_mmc_vrom_bank[bank] = (m_mmc_vrom_bank[bank] & 0x0f) | ((data & 0x0f) << 4);
- else
- m_mmc_vrom_bank[bank] = (m_mmc_vrom_bank[bank] & 0xf0) | ((data & 0x0f) << 0);
- chr1_x(bank, m_mmc_vrom_bank[bank], m_chr_source);
- break;
- case 0x5000: case 0x5004: case 0x5008: case 0x500c:
- bank = 0 + BIT(offset, 3);
- if (offset & 4)
- m_mmc_vrom_bank[bank] = (m_mmc_vrom_bank[bank] & 0x0f) | ((data & 0x0f) << 4);
- else
- m_mmc_vrom_bank[bank] = (m_mmc_vrom_bank[bank] & 0xf0) | ((data & 0x0f) << 0);
- chr1_x(bank, m_mmc_vrom_bank[bank], m_chr_source);
- break;
- case 0x6000: case 0x6004: case 0x6008: case 0x600c:
- bank = 6 + BIT(offset, 3);
- if (offset & 4)
- m_mmc_vrom_bank[bank] = (m_mmc_vrom_bank[bank] & 0x0f) | ((data & 0x0f) << 4);
- else
- m_mmc_vrom_bank[bank] = (m_mmc_vrom_bank[bank] & 0xf0) | ((data & 0x0f) << 0);
- chr1_x(bank, m_mmc_vrom_bank[bank], m_chr_source);
- break;
-
- case 0x4000:
- case 0x4004:
- case 0x4008:
- case 0x400c:
- m_prg_mode = data & 1;
-
- case 0x7000:
- m_irq_count = (m_irq_count & 0x1e0) | ((data & 0x0f) << 1);
- break;
- case 0x7004:
- m_irq_count = (m_irq_count & 0x1e) | ((data & 0x0f) << 5);
- break;
- case 0x7008:
- m_irq_enable = BIT(data, 1);
- break;
- }
+ if (BIT(m_latch, 6))
+ offset = (offset & ~0x0f) | m_jumper; // TODO: jumper setting that controls which menu appears is 0 for now
+ return hi_access_rom(offset);
}
@@ -1236,7 +732,6 @@ void nes_fujiya_device::device_start()
void nes_fujiya_device::pcb_reset()
{
- m_chr_source = m_vrom_chunks ? CHRROM : CHRRAM;
prg16_89ab(0);
prg16_cdef(0);
chr8(0, m_chr_source);
@@ -1246,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)
@@ -1255,12 +750,12 @@ 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)
- return m_latch | ((offset >> 8) & 0x7f);
+ return m_latch | (BIT(offset, 8, 7));
- return get_open_bus(); // open bus
+ return get_open_bus();
}
#endif
diff --git a/src/devices/bus/nes/pirate.h b/src/devices/bus/nes/pirate.h
index e99bd703aec..5ddfd26a0b4 100644
--- a/src/devices/bus/nes/pirate.h
+++ b/src/devices/bus/nes/pirate.h
@@ -14,15 +14,9 @@ class nes_agci_device : public nes_nrom_device
{
public:
// construction/destruction
- nes_agci_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
+ nes_agci_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock);
- virtual void write_h(offs_t offset, uint8_t data) override;
-
- virtual void pcb_reset() override;
-
-protected:
- // device-level overrides
- virtual void device_start() override;
+ virtual void write_h(offs_t offset, u8 data) override;
};
@@ -32,15 +26,11 @@ class nes_dreamtech_device : public nes_nrom_device
{
public:
// construction/destruction
- nes_dreamtech_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
+ nes_dreamtech_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock);
- virtual void write_l(offs_t offset, uint8_t data) override;
+ virtual void write_l(offs_t offset, u8 data) override;
virtual void pcb_reset() override;
-
-protected:
- // device-level overrides
- virtual void device_start() override;
};
@@ -61,7 +51,7 @@ public:
protected:
// device-level overrides
- virtual void device_start() override;
+ virtual void device_start() override ATTR_COLD;
private:
uint8_t m_latch;
@@ -75,20 +65,19 @@ class nes_futuremedia_device : public nes_nrom_device
{
public:
// construction/destruction
- nes_futuremedia_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
+ nes_futuremedia_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock);
- virtual void write_h(offs_t offset, uint8_t data) override;
+ virtual void write_h(offs_t offset, u8 data) override;
- virtual void hblank_irq(int scanline, int vblank, int blanked) override;
+ virtual void hblank_irq(int scanline, bool vblank, bool blanked) override;
virtual void pcb_reset() override;
protected:
// device-level overrides
- virtual void device_start() override;
+ virtual void device_start() override ATTR_COLD;
private:
- uint16_t m_irq_count, m_irq_count_latch;
- uint8_t m_irq_clear;
+ u8 m_irq_count, m_irq_count_latch;
int m_irq_enable;
};
@@ -99,15 +88,9 @@ class nes_magseries_device : public nes_nrom_device
{
public:
// construction/destruction
- nes_magseries_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
+ nes_magseries_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock);
- virtual void write_h(offs_t offset, uint8_t data) override;
-
- virtual void pcb_reset() override;
-
-protected:
- // device-level overrides
- virtual void device_start() override;
+ virtual void write_h(offs_t offset, u8 data) override;
};
@@ -117,18 +100,18 @@ class nes_daou306_device : public nes_nrom_device
{
public:
// construction/destruction
- nes_daou306_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
+ nes_daou306_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock);
- virtual void write_h(offs_t offset, uint8_t data) override;
+ virtual void write_h(offs_t offset, u8 data) override;
virtual void pcb_reset() override;
protected:
// device-level overrides
- virtual void device_start() override;
+ virtual void device_start() override ATTR_COLD;
private:
- uint8_t m_reg[16];
+ u8 m_reg[16];
};
@@ -138,15 +121,11 @@ class nes_cc21_device : public nes_nrom_device
{
public:
// construction/destruction
- nes_cc21_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
+ nes_cc21_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock);
- virtual void write_h(offs_t offset, uint8_t data) override;
+ virtual void write_h(offs_t offset, u8 data) override;
virtual void pcb_reset() override;
-
-protected:
- // device-level overrides
- virtual void device_start() override;
};
@@ -161,10 +140,6 @@ public:
virtual void write_l(offs_t offset, uint8_t data) override;
virtual void pcb_reset() override;
-
-protected:
- // device-level overrides
- virtual void device_start() override;
};
@@ -184,90 +159,41 @@ public:
protected:
// device-level overrides
- virtual void device_start() override;
+ virtual void device_start() override ATTR_COLD;
private:
uint8_t m_latch;
};
-// ======================> nes_t230_device
+// ======================> nes_jy830623c_device
-class nes_t230_device : public nes_nrom_device
+class nes_jy830623c_device : public nes_nrom_device
{
public:
// construction/destruction
- nes_t230_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
+ nes_jy830623c_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock);
- virtual void write_h(offs_t offset, uint8_t data) override;
+ virtual void write_m(offs_t offset, u8 data) override;
+ virtual void write_h(offs_t offset, u8 data) override;
- virtual void hblank_irq(int scanline, int vblank, int blanked) override;
+ virtual void hblank_irq(int scanline, bool vblank, bool blanked) override;
virtual void pcb_reset() override;
protected:
// device-level overrides
- virtual void device_start() override;
+ virtual void device_start() override ATTR_COLD;
private:
- uint16_t m_irq_count, m_irq_count_latch;
- uint8_t m_irq_mode;
- int m_irq_enable, m_irq_enable_latch;
-
- uint8_t m_mmc_vrom_bank[8];
-};
-
-
-// ======================> nes_mk2_device
-
-class nes_mk2_device : public nes_nrom_device
-{
-public:
- // construction/destruction
- nes_mk2_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
-
- virtual void write_m(offs_t offset, uint8_t data) override;
-
- virtual void hblank_irq(int scanline, int vblank, int blanked) override;
- virtual void pcb_reset() override;
-
-protected:
- // device-level overrides
- virtual void device_start() override;
+ void update_banks();
+ u8 m_latch;
+ u8 m_reg[6];
-private:
- uint16_t m_irq_count, m_irq_count_latch;
- uint8_t m_irq_clear;
+ u16 m_irq_count, m_irq_count_latch;
int m_irq_enable;
};
-// ======================> nes_whero_device
-
-class nes_whero_device : public nes_nrom_device
-{
-public:
- // construction/destruction
- nes_whero_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
-
- virtual void write_h(offs_t offset, uint8_t data) override;
-
- virtual void hblank_irq(int scanline, int vblank, int blanked) override;
- virtual void pcb_reset() override;
-
-protected:
- // device-level overrides
- virtual void device_start() override;
-
-private:
- uint8_t m_reg;
- uint8_t m_mmc_vrom_bank[8];
-
- uint16_t m_irq_count, m_irq_count_latch;
- int m_irq_enable, m_irq_enable_latch;
-// int m_irq_mode;
-};
-
-
// ======================> nes_43272_device
class nes_43272_device : public nes_nrom_device
@@ -283,69 +209,34 @@ public:
protected:
// device-level overrides
- virtual void device_start() override;
+ virtual void device_start() override ATTR_COLD;
private:
uint16_t m_latch;
};
-// ======================> nes_tf1201_device
+// ======================> nes_eh8813a_device
-class nes_tf1201_device : public nes_nrom_device
+class nes_eh8813a_device : public nes_nrom_device
{
public:
// construction/destruction
- nes_tf1201_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
+ nes_eh8813a_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock);
- virtual void write_h(offs_t offset, uint8_t data) override;
+ virtual u8 read_h(offs_t offset) override;
+ virtual void write_h(offs_t offset, u8 data) override;
- virtual void hblank_irq(int scanline, int vblank, int blanked) override;
virtual void pcb_reset() override;
protected:
// device-level overrides
- virtual void device_start() override;
+ virtual void device_start() override ATTR_COLD;
private:
- void update_prg();
- uint8_t m_prg, m_swap;
- uint16_t m_irq_count;
- int m_irq_enable, m_irq_enable_latch;
-
- uint8_t m_mmc_vrom_bank[8];
-};
-
-
-// ======================> nes_cityfight_device
-
-class nes_cityfight_device : public nes_nrom_device
-{
-public:
- // construction/destruction
- nes_cityfight_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
-
- virtual void write_h(offs_t offset, uint8_t data) override;
-
- virtual void pcb_reset() override;
-
-protected:
- // device-level overrides
- virtual void device_start() override;
- virtual void device_timer(emu_timer &timer, device_timer_id id, int param, void *ptr) override;
-
-private:
- static constexpr device_timer_id TIMER_IRQ = 0;
-
- void update_prg();
-
- uint8_t m_prg_reg, m_prg_mode;
- uint16_t m_irq_count;
- int m_irq_enable;
-
- emu_timer *irq_timer;
-
- uint8_t m_mmc_vrom_bank[8];
+ u8 m_jumper;
+ u16 m_latch;
+ u8 m_reg;
};
@@ -366,7 +257,7 @@ public:
protected:
// device-level overrides
- virtual void device_start() override;
+ virtual void device_start() override ATTR_COLD;
private:
uint8_t m_latch;
@@ -384,12 +275,9 @@ DECLARE_DEVICE_TYPE(NES_DAOU306, nes_daou306_device)
DECLARE_DEVICE_TYPE(NES_CC21, nes_cc21_device)
DECLARE_DEVICE_TYPE(NES_XIAOZY, nes_xiaozy_device)
DECLARE_DEVICE_TYPE(NES_EDU2K, nes_edu2k_device)
-DECLARE_DEVICE_TYPE(NES_T230, nes_t230_device)
-DECLARE_DEVICE_TYPE(NES_MK2, nes_mk2_device)
-DECLARE_DEVICE_TYPE(NES_WHERO, nes_whero_device)
+DECLARE_DEVICE_TYPE(NES_JY830623C, nes_jy830623c_device)
DECLARE_DEVICE_TYPE(NES_43272, nes_43272_device)
-DECLARE_DEVICE_TYPE(NES_TF1201, nes_tf1201_device)
-DECLARE_DEVICE_TYPE(NES_CITYFIGHT, nes_cityfight_device)
+DECLARE_DEVICE_TYPE(NES_EH8813A, nes_eh8813a_device)
//DECLARE_DEVICE_TYPE(NES_FUJIYA, nes_fujiya_device)
#endif // MAME_BUS_NES_PIRATE_H
diff --git a/src/devices/bus/nes/pt554.cpp b/src/devices/bus/nes/pt554.cpp
index db16ca42e37..fee133f6add 100644
--- a/src/devices/bus/nes/pt554.cpp
+++ b/src/devices/bus/nes/pt554.cpp
@@ -8,9 +8,6 @@
Here we emulate the following Bandai PT-554 PCB (a CNROM PCB + LPC / PARCOR speech synthesis chip)
- TODO:
- - emulate the mat controller
-
***********************************************************************************************************/
@@ -20,22 +17,21 @@
#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"
//-------------------------------------------------
// constructor
//-------------------------------------------------
-DEFINE_DEVICE_TYPE(NES_BANDAI_PT554, nes_bandai_pt554_device, "nes_bandai_pt554", "NES Cart Bandai BT-554 PCB")
+DEFINE_DEVICE_TYPE(NES_BANDAI_PT554, nes_bandai_pt554_device, "nes_bandai_pt554", "NES Cart Bandai PT-554 PCB")
-nes_bandai_pt554_device::nes_bandai_pt554_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
+nes_bandai_pt554_device::nes_bandai_pt554_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock)
: nes_cnrom_device(mconfig, NES_BANDAI_PT554, tag, owner, clock)
, m_samples(*this, "samples")
{
@@ -55,31 +51,30 @@ nes_bandai_pt554_device::nes_bandai_pt554_device(const machine_config &mconfig,
with an Mitsubishi M50805 LPC / PARCOR speech synthesis chip
with internal tables stored in ROM which have not yet been dumped.
- iNES: mapper 3?
+ iNES: mapper 3
-------------------------------------------------*/
-void nes_bandai_pt554_device::write_m(offs_t offset, uint8_t data)
+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))
m_samples->start(data & 0x07, data & 0x07);
- else
- m_samples->stop(data & 0x07);
}
static const char *const pt554_sample_names[] =
{
"*ftaerobi",
- "00",
- "01",
- "02",
- "03",
- "04",
- "05",
- "06",
- "07",
+ "00", // hello, let's go
+ "01", // rest
+ "02", // good
+ "03", // hai
+ "04", // four
+ "05", // three
+ "06", // two
+ "07", // one
nullptr
};
diff --git a/src/devices/bus/nes/pt554.h b/src/devices/bus/nes/pt554.h
index 746750c52ed..db0765e84c5 100644
--- a/src/devices/bus/nes/pt554.h
+++ b/src/devices/bus/nes/pt554.h
@@ -6,6 +6,7 @@
#pragma once
#include "nxrom.h"
+#include "sound/samples.h"
// ======================> nes_bandai_pt554_device
@@ -14,13 +15,13 @@ class nes_bandai_pt554_device : public nes_cnrom_device
{
public:
// construction/destruction
- nes_bandai_pt554_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
+ nes_bandai_pt554_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock);
- virtual void write_m(offs_t offset, uint8_t data) override;
+ virtual void write_m(offs_t offset, u8 data) override;
protected:
// device-level overrides
- virtual void device_add_mconfig(machine_config &config) override;
+ virtual void device_add_mconfig(machine_config &config) override ATTR_COLD;
private:
required_device<samples_device> m_samples;
diff --git a/src/devices/bus/nes/racermate.cpp b/src/devices/bus/nes/racermate.cpp
index 111cb997dd0..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"
//-------------------------------------------------
@@ -51,7 +50,6 @@ void nes_racermate_device::device_start()
void nes_racermate_device::pcb_reset()
{
-// m_chr_source = m_vrom_chunks ? CHRROM : CHRRAM;
prg16_89ab(0);
prg16_cdef(m_prg_chunks - 1);
chr4_0(0, CHRRAM);
@@ -70,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!!!
-------------------------------------------------*/
@@ -83,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/racermate.h b/src/devices/bus/nes/racermate.h
index cb74a06a6b0..abd8de946e8 100644
--- a/src/devices/bus/nes/racermate.h
+++ b/src/devices/bus/nes/racermate.h
@@ -15,7 +15,7 @@ public:
nes_racermate_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
// device-level overrides
- virtual void device_start() override;
+ virtual void device_start() override ATTR_COLD;
virtual void write_h(offs_t offset, uint8_t data) override;
virtual void pcb_reset() override;
diff --git a/src/devices/bus/nes/rcm.cpp b/src/devices/bus/nes/rcm.cpp
index fdd07830381..73b78644170 100644
--- a/src/devices/bus/nes/rcm.cpp
+++ b/src/devices/bus/nes/rcm.cpp
@@ -8,14 +8,11 @@
Here we emulate the following PCBs
+ * RCM GS2004 [mapper 283]
+ * RCM GS2013 [mapper 283 also]
* RCM GS2015 [mapper 216]
- * RCM GS2004
- * RCM GS2013
* RCM Tetris Family 9in1 [mapper 61]
- * RCM 3D Block
-
- TODO:
- - investigate why 3D Block does not work
+ * RCM 3D Block [mapper 355]
***********************************************************************************************************/
@@ -24,23 +21,21 @@
#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"
//-------------------------------------------------
// constructor
//-------------------------------------------------
-DEFINE_DEVICE_TYPE(NES_GS2015, nes_gs2015_device, "nes_g2015", "NES Cart RCM GS-2015 PCB")
-DEFINE_DEVICE_TYPE(NES_GS2004, nes_gs2004_device, "nes_g2004", "NES Cart RCM GS-2004 PCB")
-DEFINE_DEVICE_TYPE(NES_GS2013, nes_gs2013_device, "nes_g2013", "NES Cart RCM GS-2013 PCB")
+DEFINE_DEVICE_TYPE(NES_GS2004, nes_gs2004_device, "nes_gs2004", "NES Cart RCM GS-2004 PCB")
+DEFINE_DEVICE_TYPE(NES_GS2013, nes_gs2013_device, "nes_gs2013", "NES Cart RCM GS-2013 PCB")
+DEFINE_DEVICE_TYPE(NES_GS2015, nes_gs2015_device, "nes_gs2015", "NES Cart RCM GS-2015 PCB")
DEFINE_DEVICE_TYPE(NES_TF9IN1, nes_tf9_device, "nes_tetrisfam", "NES Cart RCM Tetris Family 9 in 1 PCB")
DEFINE_DEVICE_TYPE(NES_3DBLOCK, nes_3dblock_device, "nes_3dblock", "NES Cart RCM 3D Block PCB")
@@ -50,93 +45,29 @@ nes_gs2015_device::nes_gs2015_device(const machine_config &mconfig, const char *
{
}
-nes_gs2004_device::nes_gs2004_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
- : nes_nrom_device(mconfig, NES_GS2004, tag, owner, clock)
-{
-}
-
-nes_gs2013_device::nes_gs2013_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
- : nes_nrom_device(mconfig, NES_GS2013, tag, owner, clock)
-{
-}
-
-nes_tf9_device::nes_tf9_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
- : nes_nrom_device(mconfig, NES_TF9IN1, tag, owner, clock)
-{
-}
-
-nes_3dblock_device::nes_3dblock_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
- : nes_nrom_device(mconfig, NES_3DBLOCK, tag, owner, clock), m_irq_count(0)
-{
-}
-
-
-
-
-void nes_gs2015_device::device_start()
-{
- common_start();
-}
-
-void nes_gs2015_device::pcb_reset()
-{
- m_chr_source = m_vrom_chunks ? CHRROM : CHRRAM;
- prg32(0);
- chr8(0, m_chr_source);
-}
-
-void nes_gs2004_device::device_start()
-{
- common_start();
-}
-
-void nes_gs2004_device::pcb_reset()
+nes_gs2004_device::nes_gs2004_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, u32 clock, int bank)
+ : nes_nrom_device(mconfig, type, tag, owner, clock), m_base(bank * 0x2000)
{
- m_chr_source = m_vrom_chunks ? CHRROM : CHRRAM;
- prg32(0xff);
- chr8(0, m_chr_source);
}
-void nes_gs2013_device::device_start()
+nes_gs2004_device::nes_gs2004_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock)
+ : nes_gs2004_device(mconfig, NES_GS2004, tag, owner, clock, 0x20)
{
- common_start();
}
-void nes_gs2013_device::pcb_reset()
+nes_gs2013_device::nes_gs2013_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock)
+ : nes_gs2004_device(mconfig, NES_GS2013, tag, owner, clock, 0x1f)
{
- m_chr_source = m_vrom_chunks ? CHRROM : CHRRAM;
- prg32(0xff);
- chr8(0, m_chr_source);
}
-void nes_tf9_device::device_start()
-{
- common_start();
-}
-
-void nes_tf9_device::pcb_reset()
-{
- m_chr_source = m_vrom_chunks ? CHRROM : CHRRAM;
- prg32(0);
- chr8(0, m_chr_source);
-}
-
-void nes_3dblock_device::device_start()
+nes_tf9_device::nes_tf9_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock)
+ : nes_nrom_device(mconfig, NES_TF9IN1, tag, owner, clock)
{
- common_start();
- save_item(NAME(m_reg));
- save_item(NAME(m_irq_count));
}
-void nes_3dblock_device::pcb_reset()
+nes_3dblock_device::nes_3dblock_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock)
+ : nes_nrom_device(mconfig, NES_3DBLOCK, tag, owner, clock)
{
- prg32(0);
- chr8(0, CHRRAM);
- m_reg[0] = 0;
- m_reg[1] = 0;
- m_reg[2] = 0;
- m_reg[3] = 0;
- m_irq_count = 0;
}
@@ -157,13 +88,14 @@ void nes_3dblock_device::pcb_reset()
iNES: mapper 216
- In MESS: Supported.
+ In MAME: Partially supported. Bonza games have some
+ sort of card inputs for gambling purposes.
-------------------------------------------------*/
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);
@@ -171,47 +103,32 @@ 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?)
}
/*-------------------------------------------------
- Board BMC-GS2004
+ Boards BMC-GS2004, BMC-GS2013
- Games: Tetris Family 6-in-1
+ Games: Tetris Family 6-in-1, 5-in-1, 12-in-1
- In MESS: Preliminary Support. It also misses WRAM handling
- (we need reads from 0x6000-0x7fff)
+ NES 2.0: mapper 283
+
+ In MAME: Supported.
-------------------------------------------------*/
-void nes_gs2004_device::write_h(offs_t offset, uint8_t data)
+u8 nes_gs2004_device::read_m(offs_t offset)
{
- LOG_MMC(("gs2004 write_h, offset: %04x, data: %02x\n", offset, data));
-
- prg32(data);
+ LOG("gs2004 read_m, offset: %04x\n", offset);
+ return m_prg[m_base + offset]; // fixed base differs per device
}
-/*-------------------------------------------------
-
- Board BMC-GS2013
-
- Games: Tetris Family 12-in-1
-
- In MESS: Preliminary Support. It also misses WRAM handling
- (we need reads from 0x6000-0x7fff)
-
- -------------------------------------------------*/
-
-void nes_gs2013_device::write_h(offs_t offset, uint8_t data)
+void nes_gs2004_device::write_h(offs_t offset, u8 data)
{
- LOG_MMC(("gs2013 write_h, offset: %04x, data: %02x\n", offset, data));
-
- if (data & 0x08)
- prg32(data & 0x09);
- else
- prg32(data & 0x07);
+ LOG("gs2004 write_h, offset: %04x, data: %02x\n", offset, data);
+ prg32(data);
}
/*-------------------------------------------------
@@ -220,35 +137,22 @@ void nes_gs2013_device::write_h(offs_t offset, uint8_t data)
Games: Tetris Family 9 in 1, 20 in 1
- Simple Mapper: prg/chr/nt are swapped depending on the offset
- of writes in 0x8000-0xffff. offset&0x80 set NT mirroring,
- when (offset&0x30) is 0,3 prg32 is set; when it is 1,2
- two 16k prg banks are set. See below for the values used in
- these banks.
-
iNES: mapper 61
- In MESS: Supported.
+ In MAME: Supported.
-------------------------------------------------*/
-void nes_tf9_device::write_h(offs_t offset, uint8_t data)
+void nes_tf9_device::write_h(offs_t offset, u8 data)
{
- LOG_MMC(("tetrisfam write_h, offset: %04x, data: %02x\n", offset, data));
-
- switch (offset & 0x30)
- {
- case 0x00:
- case 0x30:
- prg32(offset & 0x0f);
- break;
- case 0x10:
- case 0x20:
- prg16_89ab(((offset & 0x0f) << 1) | ((offset & 0x20) >> 4));
- prg16_cdef(((offset & 0x0f) << 1) | ((offset & 0x20) >> 4));
- break;
- }
- set_nt_mirroring(BIT(data, 7) ? PPU_MIRROR_HORZ : PPU_MIRROR_VERT);
+ LOG("tetrisfam write_h, offset: %04x, data: %02x\n", offset, data);
+
+ u8 bank = (offset & 0x0f) << 1 | BIT(offset, 5);
+ u8 mode = !BIT(offset, 4);
+ prg16_89ab(bank & ~mode);
+ prg16_cdef(bank | mode);
+
+ set_nt_mirroring(BIT(offset, 7) ? PPU_MIRROR_HORZ : PPU_MIRROR_VERT);
}
/*-------------------------------------------------
@@ -257,46 +161,10 @@ void nes_tf9_device::write_h(offs_t offset, uint8_t data)
Games: 3-D Block Hwang Shinwei version
- iNES:
+ NES 2.0: mapper 355
- In MESS: Very Preliminary Support. What is the purpose
- of the writes to $4800-$4900-$4a00? These writes
- also happens on the RCM version, which however works
- (probably an unused leftover code in that version)
+ In MAME: Not supported.
- FCEUmm suggests it might be IRQ related, but
- it does not seem to help much...
+ TODO: implement PIC16C54 protection
-------------------------------------------------*/
-
-void nes_3dblock_device::hblank_irq(int scanline, int vblank, int blanked)
-{
- if (m_irq_count)
- {
- m_irq_count--;
- if (!m_irq_count)
- hold_irq_line();
- }
-}
-
-void nes_3dblock_device::write_l(offs_t offset, uint8_t data)
-{
- LOG_MMC(("3dblock write_l, offset: %04x, data: %02x\n", offset, data));
- offset += 0x100;
-
- switch (offset)
- {
- case 0x800: // $4800
- m_reg[0] = data;
- break;
- case 0x900: // $4900
- m_reg[1] = data;
- break;
- case 0xa00: // $4a00
- m_reg[2] = data;
- break;
- case 0xe00: // $4e00
- m_reg[3] = data; m_irq_count = 0x10;
- break;
- }
-}
diff --git a/src/devices/bus/nes/rcm.h b/src/devices/bus/nes/rcm.h
index 005869fe09c..2f60fafef42 100644
--- a/src/devices/bus/nes/rcm.h
+++ b/src/devices/bus/nes/rcm.h
@@ -19,12 +19,6 @@ public:
virtual uint8_t read_l(offs_t offset) override { return read_m(offset); }
virtual uint8_t read_m(offs_t offset) override;
virtual void write_h(offs_t offset, uint8_t data) override;
-
- virtual void pcb_reset() override;
-
-protected:
- // device-level overrides
- virtual void device_start() override;
};
@@ -34,33 +28,27 @@ class nes_gs2004_device : public nes_nrom_device
{
public:
// construction/destruction
- nes_gs2004_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
+ nes_gs2004_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock);
- virtual void write_h(offs_t offset, uint8_t data) override;
-
- virtual void pcb_reset() override;
+ virtual u8 read_m(offs_t offset) override;
+ virtual void write_h(offs_t offset, u8 data) override;
protected:
- // device-level overrides
- virtual void device_start() override;
+ // construction/destruction
+ nes_gs2004_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, u32 clock, int bank);
+
+private:
+ const u32 m_base;
};
// ======================> nes_gs2013_device
-class nes_gs2013_device : public nes_nrom_device
+class nes_gs2013_device : public nes_gs2004_device
{
public:
// construction/destruction
- nes_gs2013_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
-
- virtual void write_h(offs_t offset, uint8_t data) override;
-
- virtual void pcb_reset() override;
-
-protected:
- // device-level overrides
- virtual void device_start() override;
+ nes_gs2013_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock);
};
@@ -70,15 +58,9 @@ class nes_tf9_device : public nes_nrom_device
{
public:
// construction/destruction
- nes_tf9_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
+ nes_tf9_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock);
- virtual void write_h(offs_t offset, uint8_t data) override;
-
- virtual void pcb_reset() override;
-
-protected:
- // device-level overrides
- virtual void device_start() override;
+ virtual void write_h(offs_t offset, u8 data) override;
};
@@ -88,27 +70,14 @@ class nes_3dblock_device : public nes_nrom_device
{
public:
// construction/destruction
- nes_3dblock_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
-
- virtual void write_l(offs_t offset, uint8_t data) override;
-
- virtual void hblank_irq(int scanline, int vblank, int blanked) override;
- virtual void pcb_reset() override;
-
-protected:
- // device-level overrides
- virtual void device_start() override;
-
-private:
- uint8_t m_reg[4];
- uint8_t m_irq_count;
+ nes_3dblock_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock);
};
// device type definition
-DECLARE_DEVICE_TYPE(NES_GS2015, nes_gs2015_device)
DECLARE_DEVICE_TYPE(NES_GS2004, nes_gs2004_device)
DECLARE_DEVICE_TYPE(NES_GS2013, nes_gs2013_device)
+DECLARE_DEVICE_TYPE(NES_GS2015, nes_gs2015_device)
DECLARE_DEVICE_TYPE(NES_TF9IN1, nes_tf9_device)
DECLARE_DEVICE_TYPE(NES_3DBLOCK, nes_3dblock_device)
diff --git a/src/devices/bus/nes/rexsoft.cpp b/src/devices/bus/nes/rexsoft.cpp
index c10b88afe01..76eeb7c8036 100644
--- a/src/devices/bus/nes/rexsoft.cpp
+++ b/src/devices/bus/nes/rexsoft.cpp
@@ -13,7 +13,6 @@
TODO:
- fix 0x6000-0x7fff accesses, write_m/read_m
- - check glitches in SL-1632
***********************************************************************************************************/
@@ -23,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"
//-------------------------------------------------
@@ -39,14 +37,13 @@ DEFINE_DEVICE_TYPE(NES_REX_DBZ5, nes_rex_dbz5_device, "nes_rex_dbz5", "NES
DEFINE_DEVICE_TYPE(NES_REX_SL1632, nes_rex_sl1632_device, "nes_rex_sl1632", "NES Cart Rex Soft SL-1632 PCB")
-nes_rex_dbz5_device::nes_rex_dbz5_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
- : nes_txrom_device(mconfig, NES_REX_DBZ5, tag, owner, clock)
- , m_extra(0)
+nes_rex_dbz5_device::nes_rex_dbz5_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock)
+ : nes_txrom_device(mconfig, NES_REX_DBZ5, tag, owner, clock), m_extra(0)
{
}
-nes_rex_sl1632_device::nes_rex_sl1632_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
- : nes_txrom_device(mconfig, NES_REX_SL1632, tag, owner, clock), m_mode(0), m_mirror(0)
+nes_rex_sl1632_device::nes_rex_sl1632_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock)
+ : nes_txrom_device(mconfig, NES_REX_SL1632, tag, owner, clock), m_mode(0)
{
}
@@ -61,7 +58,6 @@ void nes_rex_dbz5_device::device_start()
void nes_rex_dbz5_device::pcb_reset()
{
- m_chr_source = m_vrom_chunks ? CHRROM : CHRRAM;
m_extra = 0;
mmc3_common_initialize(0xff, 0xff, 0);
}
@@ -71,18 +67,16 @@ void nes_rex_sl1632_device::device_start()
mmc3_start();
save_item(NAME(m_mode));
save_item(NAME(m_mirror));
- save_item(NAME(m_extra_bank));
+ save_item(NAME(m_vrc2_prg_bank));
+ save_item(NAME(m_vrc2_vrom_bank));
}
void nes_rex_sl1632_device::pcb_reset()
{
- m_chr_source = m_vrom_chunks ? CHRROM : CHRRAM;
-
m_mode = 0;
- m_mirror = 0;
- memset(m_extra_bank, 0, sizeof(m_extra_bank));
- m_extra_bank[2] = 0xfe;
- m_extra_bank[3] = 0xff;
+ m_mirror[0] = m_mirror[1] = 0;
+ m_vrc2_prg_bank[0] = m_vrc2_prg_bank[1] = 0;
+ std::fill(std::begin(m_vrc2_vrom_bank), std::end(m_vrc2_vrom_bank), 0x00);
mmc3_common_initialize(0xff, 0xff, 0);
}
@@ -108,13 +102,13 @@ void nes_rex_sl1632_device::pcb_reset()
iNES: mapper 12
- In MESS: Supported
+ In MAME: Supported.
-------------------------------------------------*/
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);
@@ -123,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;
}
@@ -141,123 +135,81 @@ void nes_rex_dbz5_device::chr_cb(int start, int bank, int source)
Games: Samurai Spirits
- MMC3 clone
+ This board uses a Huang-1 chip, which can simulate the
+ behavior of MMC1, MMC3, and VRC2. A PAL controls which
+ mode is active and limits it to the latter two here.
iNES: mapper 14
- In MESS: Supported
+ In MAME: Supported.
-------------------------------------------------*/
void nes_rex_sl1632_device::set_prg(int prg_base, int prg_mask)
{
- if (m_mode & 0x02)
+ if (BIT(m_mode, 1)) // MMC3 mode
+ nes_txrom_device::set_prg(prg_base, prg_mask);
+ else // VRC2 mode
{
- // here standard MMC3 bankswitch
- uint8_t prg_flip = (m_latch & 0x40) ? 2 : 0;
-
- prg_cb(0, prg_base | (m_mmc_prg_bank[0 ^ prg_flip] & prg_mask));
- prg_cb(1, prg_base | (m_mmc_prg_bank[1] & prg_mask));
- prg_cb(2, prg_base | (m_mmc_prg_bank[2 ^ prg_flip] & prg_mask));
- prg_cb(3, prg_base | (m_mmc_prg_bank[3] & prg_mask));
- }
- else
- {
- prg8_89(m_extra_bank[0]);
- prg8_ab(m_extra_bank[1]);
- prg8_cd(m_extra_bank[2]);
- prg8_ef(m_extra_bank[3]);
+ prg8_89(m_vrc2_prg_bank[0]);
+ prg8_ab(m_vrc2_prg_bank[1]);
+ prg16_cdef(m_prg_chunks - 1);
}
}
-void nes_rex_sl1632_device::set_chr(uint8_t chr, int chr_base, int chr_mask)
+void nes_rex_sl1632_device::chr_cb(int start, int bank, int source)
{
- static const uint8_t conv_table[8] = {5, 5, 5, 5, 3, 3, 1, 1};
- uint8_t chr_page = (m_latch & 0x80) >> 5;
- uint8_t bank[8];
- uint8_t chr_base2[8];
-
- if (m_mode & 0x02)
- {
- for (int i = 0; i < 8; i++)
- {
- // since the mapper acts on 1K CHR chunks, we have 8 banks which use the 6 m_mmc_vrom_bank from MMC3 base class
- if (i < 4)
- bank[i] = ((m_mmc_vrom_bank[i / 2] & 0xfe) | (i & 1));
- else
- bank[i] = m_mmc_vrom_bank[i - 2];
- chr_base2[i] = chr_base | ((m_mode << conv_table[i]) & 0x100);
- }
- }
- else
- {
- for (int i = 0; i < 8; i++)
- {
- bank[i] = m_extra_bank[i + 4]; // first 4 m_extra_banks are PRG
- chr_base2[i] = chr_base;
- }
- }
+ u16 hi = BIT(m_mode, std::max(start | 1, 3)) << 8;
- chr1_x(chr_page ^ 0, chr_base2[0] | (bank[0] & chr_mask), chr);
- chr1_x(chr_page ^ 1, chr_base2[1] | (bank[1] & chr_mask), chr);
- chr1_x(chr_page ^ 2, chr_base2[2] | (bank[2] & chr_mask), chr);
- chr1_x(chr_page ^ 3, chr_base2[3] | (bank[3] & chr_mask), chr);
- chr1_x(chr_page ^ 4, chr_base2[4] | (bank[4] & chr_mask), chr);
- chr1_x(chr_page ^ 5, chr_base2[5] | (bank[5] & chr_mask), chr);
- chr1_x(chr_page ^ 6, chr_base2[6] | (bank[6] & chr_mask), chr);
- chr1_x(chr_page ^ 7, chr_base2[7] | (bank[7] & chr_mask), chr);
+ if (BIT(m_mode, 1)) // MMC3 mode
+ chr1_x(start, hi | bank, source);
+ else // VRC2 mode
+ chr1_x(start, hi | m_vrc2_vrom_bank[start], source);
}
-void nes_rex_sl1632_device::write_h(offs_t offset, uint8_t data)
+void nes_rex_sl1632_device::write_h(offs_t offset, u8 data)
{
- uint8_t helper1, helper2;
- 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)
+ if (offset == 0x2131) // Mode control register at $A131
{
m_mode = data;
set_prg(m_prg_base, m_prg_mask);
set_chr(m_chr_source, m_chr_base, m_chr_mask);
- if (!(m_mode & 0x02))
- set_nt_mirroring(BIT(m_mirror, 0) ? PPU_MIRROR_HORZ : PPU_MIRROR_VERT);
+ set_nt_mirroring(m_mirror[BIT(m_mode, 1)] ? PPU_MIRROR_HORZ : PPU_MIRROR_VERT);
+ if (!BIT(m_mode, 1))
+ set_irq_line(CLEAR_LINE);
}
-
- if (m_mode & 0x02)
- {
- switch (offset & 0x6001)
- {
- case 0x2000:
- set_nt_mirroring(BIT(m_mirror, 0) ? PPU_MIRROR_VERT : PPU_MIRROR_HORZ);
- break;
-
- default:
- txrom_write(offset, data);
- break;
- }
- }
- else if (offset >= 0x3000 && offset <= 0x6003)
+ else if (BIT(m_mode, 1)) // MMC3 mode
{
- helper1 = (offset & 0x01) << 2;
- offset = ((offset & 0x02) | (offset >> 10)) >> 1;
- helper2 = ((offset + 2) & 0x07) + 4; // '+4' because first 4 m_extra_banks are for PRG!
- m_extra_bank[helper2] = (m_extra_bank[helper2] & (0xf0 >> helper1)) | ((data & 0x0f) << helper1);
- set_chr(m_chr_source, m_chr_base, m_chr_mask);
+ txrom_write(offset, data);
+ if ((offset & 0x6001) == 0x2000)
+ m_mirror[1] = data & 1;
}
- else
- {
- switch (offset & 0x7003)
+ else // VRC2 mode
+ switch (offset & 0x7000)
{
case 0x0000:
case 0x2000:
- m_extra_bank[offset >> 13] = data;
- set_prg(m_prg_base, m_prg_mask);
+ m_vrc2_prg_bank[BIT(offset, 13)] = data;
+ prg8_x(BIT(offset, 13), data);
break;
-
case 0x1000:
- m_mirror = data;
- set_nt_mirroring(BIT(m_mirror, 0) ? PPU_MIRROR_HORZ : PPU_MIRROR_VERT);
+ m_mirror[0] = data & 1;
+ set_nt_mirroring(m_mirror[0] ? PPU_MIRROR_HORZ : PPU_MIRROR_VERT);
+ break;
+ case 0x3000:
+ case 0x4000:
+ case 0x5000:
+ case 0x6000:
+ {
+ u8 bank = ((offset >> 12) - 3) * 2 + BIT(offset, 1);
+ u8 shift = (offset & 1) << 2;
+ u8 mask = 0x0f << shift;
+ m_vrc2_vrom_bank[bank] = (m_vrc2_vrom_bank[bank] & ~mask) | ((data << shift) & mask);
+ chr_cb(bank, 0, CHRROM);
break;
+ }
}
- }
}
diff --git a/src/devices/bus/nes/rexsoft.h b/src/devices/bus/nes/rexsoft.h
index 0c44c73139d..7bfd0e28f9e 100644
--- a/src/devices/bus/nes/rexsoft.h
+++ b/src/devices/bus/nes/rexsoft.h
@@ -25,7 +25,7 @@ public:
protected:
// device-level overrides
- virtual void device_start() override;
+ virtual void device_start() override ATTR_COLD;
private:
uint8_t m_extra;
@@ -38,21 +38,23 @@ class nes_rex_sl1632_device : public nes_txrom_device
{
public:
// construction/destruction
- nes_rex_sl1632_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
+ nes_rex_sl1632_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock);
- virtual void write_h(offs_t offset, uint8_t data) override;
+ virtual void write_h(offs_t offset, u8 data) override;
+ virtual void chr_cb(int start, int bank, int source) override;
virtual void pcb_reset() override;
protected:
// device-level overrides
- virtual void device_start() override;
+ virtual void device_start() override ATTR_COLD;
virtual void set_prg(int prg_base, int prg_mask) override;
- virtual void set_chr(uint8_t chr, int chr_base, int chr_mask) override;
- uint8_t m_mode, m_mirror;
- uint8_t m_extra_bank[12];
+ u8 m_mode;
+ u8 m_mirror[2];
+ u8 m_vrc2_prg_bank[2];
+ u8 m_vrc2_vrom_bank[8];
};
diff --git a/src/devices/bus/nes/sachen.cpp b/src/devices/bus/nes/sachen.cpp
index 0622bfec8d4..69934c2b0cd 100644
--- a/src/devices/bus/nes/sachen.cpp
+++ b/src/devices/bus/nes/sachen.cpp
@@ -9,20 +9,18 @@
Here we emulate the following PCBs
* Sachen SA-009 [mapper 160]
- * Sachen SA-0036 [mapper 148]
- * Sachen SA-0037 [mapper 149]
+ * Sachen SA-0036 [mapper 149]
+ * Sachen SA-0037 [mapper 148]
* Sachen SA-72007 [mapper 145]
* Sachen SA-72008 [mapper 133]
* Sachen TCA-01 [mapper 143]
* Sachen TCU-01 [mapper 147]
* Sachen TCU-02 [mapper 136]
+ * Sachen 3013 [mapper 553]
+ * Sachen 3014 [mapper 533]
* Sachen Discrete PCBs [mapper 150 & 243]
* Sachen 8259 [mapper 141 (A), 138 (B), 139 (C), 137 (D)]
- Known issues on specific mappers:
-
- * 133 Qi Wang starts with corrupted graphics (ingame seems better)
-
***********************************************************************************************************/
@@ -30,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"
//-------------------------------------------------
@@ -52,6 +50,8 @@ DEFINE_DEVICE_TYPE(NES_SACHEN_SA72008, nes_sachen_sa72008_device, "nes_sa7
DEFINE_DEVICE_TYPE(NES_SACHEN_TCA01, nes_sachen_tca01_device, "nes_tca01", "NES Cart Sachen TCA-01 PCB")
DEFINE_DEVICE_TYPE(NES_SACHEN_TCU01, nes_sachen_tcu01_device, "nes_tcu01", "NES Cart Sachen TCU-01 PCB")
DEFINE_DEVICE_TYPE(NES_SACHEN_TCU02, nes_sachen_tcu02_device, "nes_tcu02", "NES Cart Sachen TCU-02 PCB")
+DEFINE_DEVICE_TYPE(NES_SACHEN_3013, nes_sachen_3013_device, "nes_3013", "NES Cart Sachen 3013 PCB")
+DEFINE_DEVICE_TYPE(NES_SACHEN_3014, nes_sachen_3014_device, "nes_3014", "NES Cart Sachen 3014 PCB")
DEFINE_DEVICE_TYPE(NES_SACHEN_74X374, nes_sachen_74x374_device, "nes_s74x374", "NES Cart Sachen 74*374 PCB")
DEFINE_DEVICE_TYPE(NES_SACHEN_74X374_ALT, nes_sachen_74x374_alt_device, "nes_s74x374a", "NES Cart Sachen 74*374 Alt PCB")
DEFINE_DEVICE_TYPE(NES_SACHEN_8259A, nes_sachen_8259a_device, "nes_s8259a", "NES Cart Sachen 8259A PCB")
@@ -65,7 +65,7 @@ nes_sachen_sa009_device::nes_sachen_sa009_device(const machine_config &mconfig,
{
}
-nes_sachen_sa0036_device::nes_sachen_sa0036_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
+nes_sachen_sa0036_device::nes_sachen_sa0036_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock)
: nes_nrom_device(mconfig, NES_SACHEN_SA0036, tag, owner, clock)
{
}
@@ -100,6 +100,16 @@ nes_sachen_tcu02_device::nes_sachen_tcu02_device(const machine_config &mconfig,
{
}
+nes_sachen_3013_device::nes_sachen_3013_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock)
+ : nes_nrom_device(mconfig, NES_SACHEN_3013, tag, owner, clock)
+{
+}
+
+nes_sachen_3014_device::nes_sachen_3014_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock)
+ : nes_nrom_device(mconfig, NES_SACHEN_3014, tag, owner, clock), m_latch(0)
+{
+}
+
nes_sachen_74x374_device::nes_sachen_74x374_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock)
: nes_nrom_device(mconfig, type, tag, owner, clock), m_latch(0), m_mmc_vrom_bank(0)
{
@@ -143,102 +153,37 @@ nes_sachen_8259d_device::nes_sachen_8259d_device(const machine_config &mconfig,
-void nes_sachen_sa009_device::device_start()
-{
- common_start();
-}
-
-void nes_sachen_sa009_device::pcb_reset()
-{
- m_chr_source = m_vrom_chunks ? CHRROM : CHRRAM;
- prg32(0);
- chr8(0, m_chr_source);
-}
-
-void nes_sachen_sa0036_device::device_start()
-{
- common_start();
-}
-
-void nes_sachen_sa0036_device::pcb_reset()
-{
- m_chr_source = m_vrom_chunks ? CHRROM : CHRRAM;
- prg32(0);
- chr8(0, m_chr_source);
-}
-
-void nes_sachen_sa0037_device::device_start()
-{
- common_start();
-}
-
-void nes_sachen_sa0037_device::pcb_reset()
-{
- m_chr_source = m_vrom_chunks ? CHRROM : CHRRAM;
- prg32(0);
- chr8(0, m_chr_source);
-}
-
-void nes_sachen_sa72007_device::device_start()
-{
- common_start();
-}
-
-void nes_sachen_sa72007_device::pcb_reset()
-{
- m_chr_source = m_vrom_chunks ? CHRROM : CHRRAM;
- prg32(0);
- chr8(0, m_chr_source);
-}
-
-void nes_sachen_sa72008_device::device_start()
-{
- common_start();
-}
-
-void nes_sachen_sa72008_device::pcb_reset()
-{
- m_chr_source = m_vrom_chunks ? CHRROM : CHRRAM;
- prg32(0);
- chr8(0, m_chr_source);
-}
-
-void nes_sachen_tca01_device::device_start()
-{
- common_start();
-}
-
void nes_sachen_tca01_device::pcb_reset()
{
- m_chr_source = m_vrom_chunks ? CHRROM : CHRRAM;
prg16_89ab(0);
prg16_cdef(1);
chr8(0, m_chr_source);
}
-void nes_sachen_tcu01_device::device_start()
+void nes_sachen_tcu02_device::device_start()
{
common_start();
+ save_item(NAME(m_latch));
}
-void nes_sachen_tcu01_device::pcb_reset()
+void nes_sachen_tcu02_device::pcb_reset()
{
- m_chr_source = m_vrom_chunks ? CHRROM : CHRRAM;
prg32(0);
chr8(0, m_chr_source);
+
+ m_latch = 0;
}
-void nes_sachen_tcu02_device::device_start()
+void nes_sachen_3014_device::device_start()
{
common_start();
save_item(NAME(m_latch));
}
-void nes_sachen_tcu02_device::pcb_reset()
+void nes_sachen_3014_device::pcb_reset()
{
- m_chr_source = m_vrom_chunks ? CHRROM : CHRRAM;
prg32(0);
- chr8(0, m_chr_source);
+ chr8(0, CHRROM);
m_latch = 0;
}
@@ -252,7 +197,6 @@ void nes_sachen_74x374_device::device_start()
void nes_sachen_74x374_device::pcb_reset()
{
- m_chr_source = m_vrom_chunks ? CHRROM : CHRRAM;
prg32(0);
chr8(0, m_chr_source);
@@ -269,7 +213,6 @@ void nes_sachen_8259a_device::device_start()
void nes_sachen_8259a_device::pcb_reset()
{
- m_chr_source = m_vrom_chunks ? CHRROM : CHRRAM;
prg32(0);
chr8(0, m_chr_source);
set_nt_mirroring(PPU_MIRROR_VERT);
@@ -280,7 +223,6 @@ void nes_sachen_8259a_device::pcb_reset()
void nes_sachen_8259d_device::pcb_reset()
{
- m_chr_source = m_vrom_chunks ? CHRROM : CHRRAM;
prg32(0);
chr8(m_vrom_chunks - 1, CHRROM);
set_nt_mirroring(PPU_MIRROR_VERT);
@@ -304,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);
}
@@ -323,13 +265,16 @@ void nes_sachen_sa009_device::write_l(offs_t offset, uint8_t data)
iNES: mapper 149
- In MESS: Supported.
+ In MAME: Supported.
-------------------------------------------------*/
-void nes_sachen_sa0036_device::write_h(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);
chr8(data >> 7, CHRROM);
}
@@ -337,18 +282,19 @@ void nes_sachen_sa0036_device::write_h(offs_t offset, uint8_t data)
/*-------------------------------------------------
Sachen SA0037 bootleg boards
+ Tengen 800008 board
- Games: Mahjong World, Shisen Mahjong
+ Games: Mahjong World, Shisen Mahjong, Tengen Tetris
iNES: mapper 148
- In MESS: Supported.
+ In MAME: Supported.
-------------------------------------------------*/
-void nes_sachen_sa0037_device::write_h(offs_t offset, uint8_t 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);
@@ -365,13 +311,13 @@ void nes_sachen_sa0037_device::write_h(offs_t offset, uint8_t 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))
@@ -386,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);
@@ -402,17 +348,17 @@ void nes_sachen_sa72008_device::write_l(offs_t offset, uint8_t data)
Sachen TCA-01 bootleg boards
- iNES: mapper 143
-
Games: Dancing Blocks, Magic Mathematic
- In MESS: Supported.
+ iNES: mapper 143
+
+ In MAME: Supported.
-------------------------------------------------*/
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))
@@ -429,17 +375,17 @@ 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)
{
- prg32(((data >> 6) & 0x02) | ((data >> 2) & 0x01));
+ prg32(bitswap<2>(data, 7, 2));
chr8(data >> 3, CHRROM);
}
}
@@ -452,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)
{
@@ -469,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;
@@ -479,6 +425,65 @@ uint8_t nes_sachen_tcu02_device::read_l(offs_t offset)
/*-------------------------------------------------
+ Sachen 3013 board
+
+ Games: Dong Dong Nao 1
+
+ This discrete board basically behaves like standard
+ NROM-128 (mapper 0) but has circuitry so that the
+ lower half of PRG reads as a constant instead of as
+ a mirror of the upper half.
+
+ NES 2.0: mapper 553
+
+ In MAME: Supported.
+
+ -------------------------------------------------*/
+
+u8 nes_sachen_3013_device::read_h(offs_t offset)
+{
+ return (offset < 0x4000) ? 0x3a : hi_access_rom(offset);
+}
+
+/*-------------------------------------------------
+
+ Sachen 3014 board (also marked with serial SA-003)
+
+ Games: Dong Dong Nao 2
+
+ This board is a CNROM variant with simple protection.
+ The upper nibble of high address writes is latched
+ and read back in the lower nibble at 0xe000-0xefff.
+
+ NES 2.0: mapper 533
+
+ In MAME: Supported.
+
+ -------------------------------------------------*/
+
+void nes_sachen_3014_device::write_h(offs_t offset, u8 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);
+
+ m_latch = data >> 4;
+ chr8(m_latch & 1, CHRROM);
+}
+
+u8 nes_sachen_3014_device::read_h(offs_t offset)
+{
+ LOGMASKED(LOG_HIFREQ, "Sachen 3014 read_h, offset: %04x\n", offset);
+ u8 temp = hi_access_rom(offset);
+
+ if ((offset & 0x7000) == 0x6000)
+ temp = (temp & 0xf0) | m_latch;
+ return temp;
+}
+
+/*-------------------------------------------------
+
Sachen 74x374 bootleg boards
Games: Chess Academy, Chinese Checkers Jpn, Mahjong Academy,
@@ -506,15 +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))
@@ -542,7 +546,7 @@ void nes_sachen_74x374_device::write_l(offs_t offset, uint8_t data)
chr8(m_mmc_vrom_bank, CHRROM);
break;
case 0x07:
- set_mirror((data >> 1) & 0x03);
+ set_mirror(BIT(data, 1, 2));
break;
default:
break;
@@ -553,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))
@@ -564,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))
@@ -628,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/sachen.h b/src/devices/bus/nes/sachen.h
index b23599345b3..a7bda355a5d 100644
--- a/src/devices/bus/nes/sachen.h
+++ b/src/devices/bus/nes/sachen.h
@@ -17,12 +17,6 @@ public:
nes_sachen_sa009_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
virtual void write_l(offs_t offset, uint8_t data) override;
-
- virtual void pcb_reset() override;
-
-protected:
- // device-level overrides
- virtual void device_start() override;
};
@@ -32,15 +26,9 @@ class nes_sachen_sa0036_device : public nes_nrom_device
{
public:
// construction/destruction
- nes_sachen_sa0036_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
-
- virtual void write_h(offs_t offset, uint8_t data) override;
-
- virtual void pcb_reset() override;
+ nes_sachen_sa0036_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock);
-protected:
- // device-level overrides
- virtual void device_start() override;
+ virtual void write_h(offs_t offset, u8 data) override;
};
@@ -50,15 +38,9 @@ class nes_sachen_sa0037_device : public nes_nrom_device
{
public:
// construction/destruction
- nes_sachen_sa0037_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
+ nes_sachen_sa0037_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock);
- virtual void write_h(offs_t offset, uint8_t data) override;
-
- virtual void pcb_reset() override;
-
-protected:
- // device-level overrides
- virtual void device_start() override;
+ virtual void write_h(offs_t offset, u8 data) override;
};
@@ -71,12 +53,6 @@ public:
nes_sachen_sa72007_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
virtual void write_l(offs_t offset, uint8_t data) override;
-
- virtual void pcb_reset() override;
-
-protected:
- // device-level overrides
- virtual void device_start() override;
};
@@ -89,12 +65,6 @@ public:
nes_sachen_sa72008_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
virtual void write_l(offs_t offset, uint8_t data) override;
-
- virtual void pcb_reset() override;
-
-protected:
- // device-level overrides
- virtual void device_start() override;
};
@@ -109,10 +79,6 @@ public:
virtual uint8_t read_l(offs_t offset) override;
virtual void pcb_reset() override;
-
-protected:
- // device-level overrides
- virtual void device_start() override;
};
@@ -127,12 +93,6 @@ public:
virtual void write_l(offs_t offset, uint8_t data) override;
virtual void write_m(offs_t offset, uint8_t data) override { write_l((offset + 0x100) & 0xfff, data); }
virtual void write_h(offs_t offset, uint8_t data) override { write_l((offset + 0x100) & 0xfff, data); }
-
- virtual void pcb_reset() override;
-
-protected:
- // device-level overrides
- virtual void device_start() override;
};
@@ -151,13 +111,47 @@ public:
protected:
// device-level overrides
- virtual void device_start() override;
+ virtual void device_start() override ATTR_COLD;
private:
uint8_t m_latch;
};
+// ======================> nes_sachen_3013_device
+
+class nes_sachen_3013_device : public nes_nrom_device
+{
+public:
+ // construction/destruction
+ nes_sachen_3013_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock);
+
+ virtual u8 read_h(offs_t offset) override;
+};
+
+
+// ======================> nes_sachen_3014_device
+
+class nes_sachen_3014_device : public nes_nrom_device
+{
+public:
+ // construction/destruction
+ nes_sachen_3014_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock);
+
+ virtual u8 read_h(offs_t offset) override;
+ virtual void write_h(offs_t offset, u8 data) override;
+
+ virtual void pcb_reset() override;
+
+protected:
+ // device-level overrides
+ virtual void device_start() override ATTR_COLD;
+
+private:
+ u8 m_latch;
+};
+
+
// ======================> nes_sachen_74x374_device
class nes_sachen_74x374_device : public nes_nrom_device
@@ -175,7 +169,7 @@ protected:
nes_sachen_74x374_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_start() override ATTR_COLD;
void set_mirror(uint8_t nt);
uint8_t m_latch, m_mmc_vrom_bank;
@@ -190,7 +184,6 @@ public:
// construction/destruction
nes_sachen_74x374_alt_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
- // device-level overrides
virtual uint8_t read_l(offs_t offset) override { return 0xff; } // no read_l here
virtual void write_l(offs_t offset, uint8_t data) override;
};
@@ -213,7 +206,7 @@ protected:
nes_sachen_8259a_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_start() override ATTR_COLD;
virtual void chr_update();
uint8_t m_reg[8];
@@ -270,6 +263,8 @@ DECLARE_DEVICE_TYPE(NES_SACHEN_SA72008, nes_sachen_sa72008_device)
DECLARE_DEVICE_TYPE(NES_SACHEN_TCA01, nes_sachen_tca01_device)
DECLARE_DEVICE_TYPE(NES_SACHEN_TCU01, nes_sachen_tcu01_device)
DECLARE_DEVICE_TYPE(NES_SACHEN_TCU02, nes_sachen_tcu02_device)
+DECLARE_DEVICE_TYPE(NES_SACHEN_3013, nes_sachen_3013_device)
+DECLARE_DEVICE_TYPE(NES_SACHEN_3014, nes_sachen_3014_device)
DECLARE_DEVICE_TYPE(NES_SACHEN_74X374, nes_sachen_74x374_device)
DECLARE_DEVICE_TYPE(NES_SACHEN_74X374_ALT, nes_sachen_74x374_alt_device)
DECLARE_DEVICE_TYPE(NES_SACHEN_8259A, nes_sachen_8259a_device)
diff --git a/src/devices/bus/nes/sealie.cpp b/src/devices/bus/nes/sealie.cpp
new file mode 100644
index 00000000000..5c7b42cfe4e
--- /dev/null
+++ b/src/devices/bus/nes/sealie.cpp
@@ -0,0 +1,241 @@
+// license:BSD-3-Clause
+// copyright-holders:kmg
+/***********************************************************************************************************
+
+
+ NES/Famicom cartridge emulation for Sealie Computing and related PCBs
+
+
+ Here we emulate the following homebrew PCBs
+
+ * SEALIE RET-CUFROM [mapper 29]
+ * SEALIE DPCMcart [mapper 409]
+ * SEALIE UNROM 512 [mapper 30]
+ * SEALIE 8BIT XMAS [mapper 30]
+
+ ***********************************************************************************************************/
+
+
+#include "emu.h"
+#include "sealie.h"
+
+
+#ifdef NES_PCB_DEBUG
+#define VERBOSE (LOG_GENERAL)
+#else
+#define VERBOSE (0)
+#endif
+#include "logmacro.h"
+
+
+//-------------------------------------------------
+// constructor
+//-------------------------------------------------
+
+DEFINE_DEVICE_TYPE(NES_8BITXMAS, nes_8bitxmas_device, "nes_8bitxmas", "NES Cart Sealie 8BIT XMAS PCB")
+DEFINE_DEVICE_TYPE(NES_CUFROM, nes_cufrom_device, "nes_cufrom", "NES Cart Sealie RET-CUFROM PCB")
+DEFINE_DEVICE_TYPE(NES_DPCMCART, nes_dpcmcart_device, "nes_dpcmcart", "NES Cart Sealie DPCMcart PCB")
+DEFINE_DEVICE_TYPE(NES_UNROM512, nes_unrom512_device, "nes_unrom512", "NES Cart Sealie UNROM 512 PCB")
+
+
+nes_cufrom_device::nes_cufrom_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock)
+ : nes_nrom_device(mconfig, NES_CUFROM, tag, owner, clock)
+{
+}
+
+nes_dpcmcart_device::nes_dpcmcart_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock)
+ : nes_nrom_device(mconfig, NES_DPCMCART, tag, owner, clock)
+{
+}
+
+nes_unrom512_device::nes_unrom512_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, u32 clock)
+ : nes_nrom_device(mconfig, type, tag, owner, clock)
+{
+}
+
+nes_unrom512_device::nes_unrom512_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock)
+ : nes_unrom512_device(mconfig, NES_UNROM512, tag, owner, clock)
+{
+}
+
+nes_8bitxmas_device::nes_8bitxmas_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock)
+ : nes_unrom512_device(mconfig, NES_8BITXMAS, tag, owner, clock), m_led(0)
+{
+}
+
+
+
+void nes_cufrom_device::pcb_reset()
+{
+ prg16_89ab(0);
+ prg16_cdef(m_prg_chunks - 1);
+ chr8(0, CHRRAM);
+}
+
+void nes_dpcmcart_device::pcb_reset()
+{
+ prg16_89ab(0);
+ prg16_cdef(m_prg_chunks - 1);
+}
+
+void nes_unrom512_device::pcb_reset()
+{
+ prg16_89ab(0);
+ prg16_cdef(m_prg_chunks - 1);
+ chr8(0, CHRRAM);
+ if (m_pcb_ctrl_mirror)
+ set_nt_mirroring(PPU_MIRROR_LOW);
+}
+
+void nes_8bitxmas_device::device_start()
+{
+ nes_unrom512_device::device_start();
+ save_item(NAME(m_led));
+
+ m_bus_conflict = false;
+}
+
+void nes_8bitxmas_device::pcb_reset()
+{
+ nes_unrom512_device::pcb_reset();
+
+ m_led = 0;
+ update_led();
+}
+
+
+
+/*-------------------------------------------------
+ mapper specific handlers
+ -------------------------------------------------*/
+
+/*-------------------------------------------------
+
+ Sealie RET-CUFROM board
+
+ Games: Glider (only?)
+
+ This homebrew mapper supports 8x16k PRG banks at 0x8000,
+ 8k WRAM at 0x6000, and 4x8k VRAM banks. PRG is stored on
+ flash ROM, though unlike mapper 30 it doesn't appear to
+ be self-flashable, only through an external tool.
+
+ iNES: mapper 29
+
+ In MAME: Supported.
+
+ -------------------------------------------------*/
+
+void nes_cufrom_device::write_h(offs_t offset, u8 data)
+{
+ LOG("cufrom write_h, offset: %04x, data: %02x\n", offset, data);
+
+ prg16_89ab(BIT(data, 2, 3));
+ chr8(data & 0x03, CHRRAM);
+}
+
+/*-------------------------------------------------
+
+ Sealie DPCMcart board
+
+ Games: A Winner is You
+
+ This homebrew mapper supports a whopping 64MB which
+ is paged in 16K chucks at 0x8000. 0xc000 is fixed.
+
+ NES 2.0: mapper 409
+
+ In MAME: Partially supported.
+
+ TODO: Controls other than 'next track' don't work.
+
+ -------------------------------------------------*/
+
+void nes_dpcmcart_device::write_h(offs_t offset, u8 data)
+{
+ LOG("dpcmcart write_h, offset: %04x, data: %02x\n", offset, data);
+ prg16_89ab(offset & 0x0fff);
+}
+
+/*-------------------------------------------------
+
+ Sealie UNROM 512 board
+
+ Games: Battle Kid 1 & 2, E.T., many more
+
+ This board has several variations and jumper configurations.
+ Currently we only support the Sealie nonflashable config
+ with 32x16k PRG banks at 0x8000, 4x8k VRAM, and three
+ mirroring configs (H, V, or PCB selected 1-screen modes).
+
+ iNES: mapper 30
+
+ In MAME: Preliminary partial support.
+
+ -------------------------------------------------*/
+
+void nes_unrom512_device::write_h(offs_t offset, u8 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);
+
+ if (m_pcb_ctrl_mirror)
+ set_nt_mirroring(BIT(data, 7) ? PPU_MIRROR_HIGH : PPU_MIRROR_LOW);
+ prg16_89ab(data & 0x1f);
+ chr8(BIT(data, 5, 2), CHRRAM);
+}
+
+/*-------------------------------------------------
+
+ Sealie 8BIT XMAS revD board
+
+ Games: 8-bit Xmas 2012-2016 and 2018-2021?
+
+ This board is a variant of UNROM512 with 16 LEDs
+ in 4 colors, blue, yellow, green, red, which are
+ controlled in pairs by each byte written to
+ 0x8000-0xbfff. Bits are [BYGR bygr] where bygr
+ control LEDs 1,2 and BYGR control LEDs 3,4. On
+ the 8BIT XMAS revD 2012 board LEDS are arranged:
+
+ _______________________________
+ | RED2 GRN3 |
+ | |
+ | YEL2 BLU3 |
+ | |
+ | BLU1 YEL4 |
+ | |
+ | GRN1 RED4 |
+ | |
+ | RED1 GRN4 |
+ | |
+ | YEL1 BLU4 |
+ -- --
+ | GRN2 BLU2 YEL3 RED3 |
+ | |
+
+ iNES: mapper 30
+
+ In MAME: Preliminary partial support.
+
+ -------------------------------------------------*/
+
+void nes_8bitxmas_device::update_led()
+{
+ // TODO: add artwork
+}
+
+void nes_8bitxmas_device::write_h(offs_t offset, u8 data)
+{
+ LOG("8bitxmas write_h, offset: %04x, data: %02x\n", offset, data);
+
+ if (BIT(offset, 14))
+ nes_unrom512_device::write_h(offset, data);
+ else if (m_led != data)
+ {
+ m_led = data;
+ update_led();
+ }
+}
diff --git a/src/devices/bus/nes/sealie.h b/src/devices/bus/nes/sealie.h
new file mode 100644
index 00000000000..0b7a9a3b5a9
--- /dev/null
+++ b/src/devices/bus/nes/sealie.h
@@ -0,0 +1,85 @@
+// license:BSD-3-Clause
+// copyright-holders:kmg
+#ifndef MAME_BUS_NES_SEALIE_H
+#define MAME_BUS_NES_SEALIE_H
+
+#pragma once
+
+#include "nxrom.h"
+
+
+// ======================> nes_cufrom_device
+
+class nes_cufrom_device : public nes_nrom_device
+{
+public:
+ // construction/destruction
+ nes_cufrom_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock);
+
+ virtual void write_h(offs_t offset, u8 data) override;
+
+ virtual void pcb_reset() override;
+};
+
+
+// ======================> nes_dpcmcart_device
+
+class nes_dpcmcart_device : public nes_nrom_device
+{
+public:
+ // construction/destruction
+ nes_dpcmcart_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock);
+
+ virtual void write_h(offs_t offset, u8 data) override;
+
+ virtual void pcb_reset() override;
+};
+
+
+// ======================> nes_unrom512_device
+
+class nes_unrom512_device : public nes_nrom_device
+{
+public:
+ // construction/destruction
+ nes_unrom512_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock);
+
+ virtual void write_h(offs_t offset, u8 data) override;
+
+ virtual void pcb_reset() override;
+
+protected:
+ // construction/destruction
+ nes_unrom512_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, u32 clock);
+};
+
+
+// ======================> nes_8bitxmas_device
+
+class nes_8bitxmas_device : public nes_unrom512_device
+{
+public:
+ // construction/destruction
+ nes_8bitxmas_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock);
+
+ virtual void write_h(offs_t offset, u8 data) override;
+
+ virtual void pcb_reset() override;
+
+protected:
+ // device-level overrides
+ virtual void device_start() override ATTR_COLD;
+
+private:
+ void update_led();
+ u8 m_led;
+};
+
+
+// device type definition
+DECLARE_DEVICE_TYPE(NES_8BITXMAS, nes_8bitxmas_device)
+DECLARE_DEVICE_TYPE(NES_CUFROM, nes_cufrom_device)
+DECLARE_DEVICE_TYPE(NES_DPCMCART, nes_dpcmcart_device)
+DECLARE_DEVICE_TYPE(NES_UNROM512, nes_unrom512_device)
+
+#endif // MAME_BUS_NES_SEALIE_H
diff --git a/src/devices/bus/nes/somari.cpp b/src/devices/bus/nes/somari.cpp
index c517a4fae16..15382d01111 100644
--- a/src/devices/bus/nes/somari.cpp
+++ b/src/devices/bus/nes/somari.cpp
@@ -17,17 +17,15 @@
#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
#define SOMARI_MMC1_MODE 2
-#define SOMARI_MMC1_MODE_AGAIN 3
//-------------------------------------------------
@@ -35,15 +33,21 @@
//-------------------------------------------------
DEFINE_DEVICE_TYPE(NES_SOMARI, nes_somari_device, "nes_somari", "NES Cart Team Somari PCB")
+DEFINE_DEVICE_TYPE(NES_HUANG2, nes_huang2_device, "nes_huang2", "NES Cart Huang-2 PCB")
-nes_somari_device::nes_somari_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
- : nes_txrom_device(mconfig, NES_SOMARI, tag, owner, clock)
- , m_board_mode(0)
- , m_mmc3_mirror_reg(0)
- , m_count(0)
- , m_mmc1_latch(0)
- , m_vrc_mirror_reg(0)
+nes_somari_device::nes_somari_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, u32 clock, u8 mmc1_prg_shift)
+ : nes_txrom_device(mconfig, type, tag, owner, clock), m_board_mode(0), m_mmc1_count(0), m_mmc1_latch(0), m_mmc1_prg_shift(mmc1_prg_shift), m_vrc_mirror(0)
+{
+}
+
+nes_somari_device::nes_somari_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock)
+ : nes_somari_device(mconfig, NES_SOMARI, tag, owner, clock, 0)
+{
+}
+
+nes_huang2_device::nes_huang2_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock)
+ : nes_somari_device(mconfig, NES_HUANG2, tag, owner, clock, 1)
{
}
@@ -51,67 +55,27 @@ nes_somari_device::nes_somari_device(const machine_config &mconfig, const char *
void nes_somari_device::device_start()
{
- common_start();
+ mmc3_start();
save_item(NAME(m_board_mode));
- // MMC3
- save_item(NAME(m_mmc_prg_bank));
- save_item(NAME(m_mmc_vrom_bank));
- save_item(NAME(m_latch));
- save_item(NAME(m_prg_base));
- save_item(NAME(m_prg_mask));
- save_item(NAME(m_chr_base));
- save_item(NAME(m_chr_mask));
- save_item(NAME(m_mmc3_mirror_reg));
-
- save_item(NAME(m_irq_enable));
- save_item(NAME(m_irq_count));
- save_item(NAME(m_irq_count_latch));
- save_item(NAME(m_irq_clear));
-
// MMC1
- save_item(NAME(m_count));
+ save_item(NAME(m_mmc1_count));
save_item(NAME(m_mmc1_latch));
save_item(NAME(m_mmc1_reg));
// VRC2
save_item(NAME(m_vrc_prg_bank));
save_item(NAME(m_vrc_vrom_bank));
- save_item(NAME(m_vrc_mirror_reg));
+ save_item(NAME(m_vrc_mirror));
}
void nes_somari_device::pcb_reset()
{
- m_chr_source = m_vrom_chunks ? CHRROM : CHRRAM;
- prg32(0);
- chr8(0, m_chr_source);
-
- m_board_mode = 2; // mode
-
- // MMC3
- m_prg_base = m_chr_base = 0;
- m_prg_mask = 0xff;
- m_chr_mask = 0xff;
- m_latch = 0;
- m_mmc_prg_bank[0] = 0x3c;
- m_mmc_prg_bank[1] = 0x3d;
- m_mmc_prg_bank[2] = 0x3e;
- m_mmc_prg_bank[3] = 0x3f;
- m_mmc_vrom_bank[0] = 0x00;
- m_mmc_vrom_bank[1] = 0x01;
- m_mmc_vrom_bank[2] = 0x04;
- m_mmc_vrom_bank[3] = 0x05;
- m_mmc_vrom_bank[4] = 0x06;
- m_mmc_vrom_bank[5] = 0x07;
- m_mmc3_mirror_reg = 0;
-
- m_alt_irq = 0;
- m_irq_enable = 0;
- m_irq_count = m_irq_count_latch = 0;
- m_irq_clear = 0;
+ m_board_mode = SOMARI_MMC3_MODE;
+ mmc3_common_initialize(0xff, 0xff, 0);
// MMC1 regs
- m_count = 0;
+ m_mmc1_count = 0;
m_mmc1_latch = 0;
m_mmc1_reg[0] = 0x0c;
m_mmc1_reg[1] = 0x00;
@@ -119,12 +83,9 @@ void nes_somari_device::pcb_reset()
m_mmc1_reg[3] = 0x00;
// VRC2 regs
- m_vrc_prg_bank[0] = 0x00;
- m_vrc_prg_bank[1] = 0x01;
- for (int i = 0; i < 8; ++i)
- m_vrc_vrom_bank[i] = i;
- bank_update_switchmode();
- m_vrc_mirror_reg = 0;
+ m_vrc_prg_bank[0] = m_vrc_prg_bank[1] = 0;
+ m_vrc_mirror = 0;
+ std::fill(std::begin(m_vrc_vrom_bank), std::end(m_vrc_vrom_bank), 0xff); // Somari (original release) glitches on "Somari Team Presents" screen without this
}
@@ -138,147 +99,87 @@ void nes_somari_device::pcb_reset()
SOMERI TEAM
+ Games: Somari, Kart Fighter, Garou Densetsu Special,
+ AV Bishoujo Senshi, AV Kyuukyoku Mahjong 2
+
+ Like Rex Soft's SL-1632 these boards use Huang chips
+ which simulate the behavior of MMC1, MMC3, and VRC2.
+ There is a second revision, Huang-2, that appears to
+ only have been used for AV Kyuukyoku Mahjong 2. Its
+ MMC1 mode has nonstandard PRG banking.
+
iNES: mapper 116
- Emulation note about regs in MESS: currently,
+ Emulation note about regs in MAME: currently,
- m_mmc_prg_bank[n] for n=0,...,3 represent the MMC3 PRG banks (inherited from base class)
- m_mmc_vrom_bank[n] for n=0,...,5 represent the MMC3 CHR banks (inherited from base class)
- m_mmc1_reg[n] for n=0,1,2,3 represent the MMC1 regs
- - m_count and m_mmc1_latch are additional variables for MMC1 (notice that MMC3 uses a diff m_latch!)
+ - m_mmc1_count and m_mmc1_latch are additional variables for MMC1 (notice that MMC3 uses a diff m_latch!)
- m_vrc_prg_bank[n] for n=0,1 represent the VRC2 PRG banks
- m_vrc_vrom_bank[n] for n=0,...,7 represent the VRC2 CHR banks
- In MESS: Preliminary support
+ In MAME: Supported.
-------------------------------------------------*/
// MMC1 Mode emulation
-void nes_somari_device::mmc1_w(offs_t offset, uint8_t data)
+void nes_somari_device::mmc1_reset_latch()
{
- assert(m_board_mode == 2);
-
- if (data & 0x80)
- {
- m_count = 0;
- m_mmc1_latch = 0;
-
- m_mmc1_reg[0] |= 0x0c;
- update_prg();
- return;
- }
-
- if (m_count < 5)
- {
- if (m_count == 0) m_mmc1_latch = 0;
- m_mmc1_latch >>= 1;
- m_mmc1_latch |= (data & 0x01) ? 0x10 : 0x00;
- m_count++;
- }
-
- if (m_count == 5)
- {
- m_mmc1_reg[(offset & 0x6000) >> 13] = m_mmc1_latch;
- update_mirror();
- update_prg();
- update_chr();
-
- m_count = 0;
- }
+ m_mmc1_count = 0;
+ m_mmc1_reg[0] |= 0x0c;
+ update_prg();
}
-// MMC3 Mode emulation
-void nes_somari_device::mmc3_w(offs_t offset, uint8_t data)
+void nes_somari_device::mmc1_w(offs_t offset, u8 data)
{
- uint8_t mmc_helper, cmd;
-
- assert(m_board_mode == 1);
-
- switch (offset & 0x6001)
+ if (BIT(data, 7))
+ mmc1_reset_latch();
+ else
{
- case 0x0000:
- mmc_helper = m_latch ^ data;
- m_latch = data;
-
- if (mmc_helper & 0x40)
- update_prg();
-
- if (mmc_helper & 0x80)
- update_chr();
- break;
-
- case 0x0001:
- cmd = m_latch & 0x07;
- switch (cmd)
- {
- case 0: case 1:
- case 2: case 3: case 4: case 5:
- m_mmc_vrom_bank[cmd] = data;
- update_chr();
- break;
- case 6:
- case 7:
- m_mmc_prg_bank[cmd - 6] = data & 0x3f;
- update_prg();
- break;
- }
- break;
-
- case 0x2000:
- m_mmc3_mirror_reg = data & 1;
- update_mirror();
- break;
- case 0x2001: break;
- case 0x4000: m_irq_count_latch = data; break;
- case 0x4001: m_irq_count = 0; break;
- case 0x6000: m_irq_enable = 0; set_irq_line(CLEAR_LINE); break;
- case 0x6001: m_irq_enable = 1; break;
+ m_mmc1_latch = (data & 1) << 4 | m_mmc1_latch >> 1;
+
+ m_mmc1_count = (m_mmc1_count + 1) % 5;
+ if (!m_mmc1_count)
+ {
+ m_mmc1_reg[BIT(offset, 13, 2)] = m_mmc1_latch;
+ update_all_banks();
+ }
}
}
// VRC2 Mode emulation
-void nes_somari_device::vrc2_w(offs_t offset, uint8_t data)
+void nes_somari_device::vrc2_w(offs_t offset, u8 data)
{
- uint8_t bank, shift;
-
- assert(m_board_mode == 0);
-
switch (offset & 0x7000)
{
case 0x0000:
- m_vrc_prg_bank[0] = data & 0x1f;
+ case 0x2000:
+ m_vrc_prg_bank[BIT(offset, 13)] = data & 0x1f;
update_prg();
break;
-
case 0x1000:
- m_vrc_mirror_reg = data & 1;
+ m_vrc_mirror = data;
update_mirror();
break;
-
- case 0x2000:
- m_vrc_prg_bank[1] = data & 0x1f;
- update_prg();
- break;
-
case 0x3000:
case 0x4000:
case 0x5000:
case 0x6000:
- // this makes no sense for vrc2 and breaks somari, but it's ok for garousp!!
- bank = ((offset & 0x7000) - 0x3000) / 0x0800 + BIT(offset, 1);
- shift = BIT(offset, 2) * 4;
- data = (data & 0x0f) << shift;
- m_vrc_vrom_bank[bank] = data;
-
+ {
+ u8 bank = ((offset >> 12) - 3) * 2 + BIT(offset, 1);
+ u8 shift = (offset & 1) << 2;
+ u8 mask = 0x0f << shift;
+ m_vrc_vrom_bank[bank] = (m_vrc_vrom_bank[bank] & ~mask) | ((data << shift) & mask);
update_chr();
break;
+ }
}
}
-
void nes_somari_device::update_prg()
{
switch (m_board_mode)
@@ -286,38 +187,26 @@ void nes_somari_device::update_prg()
case SOMARI_VRC2_MODE:
prg8_89(m_vrc_prg_bank[0]);
prg8_ab(m_vrc_prg_bank[1]);
- prg8_cd(0x3e);
- prg8_ef(0x3f);
+ prg16_cdef(m_prg_chunks - 1);
break;
case SOMARI_MMC3_MODE:
- {
- uint8_t prg_flip = (m_latch & 0x40) ? 2 : 0;
- prg8_x(0, m_mmc_prg_bank[0 ^ prg_flip]);
- prg8_x(1, m_mmc_prg_bank[1]);
- prg8_x(2, m_mmc_prg_bank[2 ^ prg_flip]);
- prg8_x(3, m_mmc_prg_bank[3]);
- }
+ set_prg(m_prg_base, m_prg_mask);
break;
case SOMARI_MMC1_MODE:
-// case SOMARI_MMC1_MODE_AGAIN:
+ switch (BIT(m_mmc1_reg[0], 2, 2))
{
- uint8_t prg_offset = m_mmc1_reg[1] & 0x10;
-
- switch (m_mmc1_reg[0] & 0x0c)
- {
- case 0x00:
- case 0x04:
- prg32((prg_offset + m_mmc1_reg[3]) >> 1);
- break;
- case 0x08:
- prg16_89ab(prg_offset + 0);
- prg16_cdef(prg_offset + m_mmc1_reg[3]);
- break;
- case 0x0c:
- prg16_89ab(prg_offset + m_mmc1_reg[3]);
- prg16_cdef(prg_offset + 0x0f);
- break;
- }
+ case 0:
+ case 1:
+ prg32(m_mmc1_reg[3] >> 1);
+ break;
+ case 2:
+ prg16_89ab(0);
+ prg16_cdef(m_mmc1_reg[3] >> m_mmc1_prg_shift);
+ break;
+ case 3:
+ prg16_89ab(m_mmc1_reg[3] >> m_mmc1_prg_shift);
+ prg16_cdef(0x0f >> m_mmc1_prg_shift);
+ break;
}
break;
}
@@ -332,27 +221,16 @@ void nes_somari_device::update_chr()
chr1_x(i, m_chr_base | m_vrc_vrom_bank[i], CHRROM);
break;
case SOMARI_MMC3_MODE:
- {
- uint8_t chr_page = (m_latch & 0x80) >> 5;
- chr1_x(chr_page ^ 0, m_chr_base | ((m_mmc_vrom_bank[0] & ~0x01)), CHRROM);
- chr1_x(chr_page ^ 1, m_chr_base | ((m_mmc_vrom_bank[0] | 0x01)), CHRROM);
- chr1_x(chr_page ^ 2, m_chr_base | ((m_mmc_vrom_bank[1] & ~0x01)), CHRROM);
- chr1_x(chr_page ^ 3, m_chr_base | ((m_mmc_vrom_bank[1] | 0x01)), CHRROM);
- chr1_x(chr_page ^ 4, m_chr_base | (m_mmc_vrom_bank[2]), CHRROM);
- chr1_x(chr_page ^ 5, m_chr_base | (m_mmc_vrom_bank[3]), CHRROM);
- chr1_x(chr_page ^ 6, m_chr_base | (m_mmc_vrom_bank[4]), CHRROM);
- chr1_x(chr_page ^ 7, m_chr_base | (m_mmc_vrom_bank[5]), CHRROM);
- }
+ set_chr(m_chr_source, m_chr_base, m_chr_mask);
break;
case SOMARI_MMC1_MODE:
-// case SOMARI_MMC1_MODE_AGAIN:
if (BIT(m_mmc1_reg[0], 4))
{
chr4_0(m_mmc1_reg[1] & 0x1f, CHRROM);
chr4_4(m_mmc1_reg[2] & 0x1f, CHRROM);
}
else
- chr8((m_mmc1_reg[1] & 0x1f) >> 1, CHRROM);
+ chr8(BIT(m_mmc1_reg[1], 1, 4), CHRROM);
break;
}
}
@@ -362,13 +240,12 @@ void nes_somari_device::update_mirror()
switch (m_board_mode)
{
case SOMARI_VRC2_MODE:
- set_nt_mirroring(m_vrc_mirror_reg ? PPU_MIRROR_HORZ : PPU_MIRROR_VERT);
+ set_nt_mirroring(m_vrc_mirror & 1 ? PPU_MIRROR_HORZ : PPU_MIRROR_VERT);
break;
case SOMARI_MMC3_MODE:
- set_nt_mirroring(m_mmc3_mirror_reg ? PPU_MIRROR_HORZ : PPU_MIRROR_VERT);
+ set_nt_mirroring(m_mmc_mirror & 1 ? PPU_MIRROR_HORZ : PPU_MIRROR_VERT);
break;
case SOMARI_MMC1_MODE:
-// case SOMARI_MMC1_MODE_AGAIN:
switch (m_mmc1_reg[0] & 0x03)
{
case 0x00: set_nt_mirroring(PPU_MIRROR_LOW); break;
@@ -380,45 +257,43 @@ void nes_somari_device::update_mirror()
}
}
-
-void nes_somari_device::write_h(offs_t offset, uint8_t data)
+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)
{
case SOMARI_VRC2_MODE: vrc2_w(offset, data); break;
- case SOMARI_MMC3_MODE: mmc3_w(offset, data); break;
+ case SOMARI_MMC3_MODE: txrom_write(offset, data); break;
case SOMARI_MMC1_MODE: mmc1_w(offset, data); break;
}
}
-void nes_somari_device::bank_update_switchmode()
+void nes_somari_device::update_all_banks()
{
- switch (m_board_mode)
- {
- case SOMARI_VRC2_MODE:
- break;
- case SOMARI_MMC3_MODE:
- break;
- case SOMARI_MMC1_MODE:
- break;
- }
update_mirror();
update_prg();
update_chr();
}
-void nes_somari_device::write_m(offs_t offset, uint8_t data)
+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)
{
- m_board_mode = data & 0x03;
- m_chr_base = ((m_board_mode & 0x04) << 6);
- if (m_board_mode != 1)
+ m_board_mode = std::min(data & 0x03, SOMARI_MMC1_MODE);
+ if (m_board_mode == SOMARI_MMC1_MODE)
+ mmc1_reset_latch(); // Garou crashes between fights without this
+
+ m_chr_base = (data & 0x04) << 6;
+
+ if (m_board_mode != SOMARI_MMC3_MODE)
+ {
m_irq_enable = 0;
- bank_update_switchmode();
+ set_irq_line(CLEAR_LINE);
+ }
+
+ update_all_banks();
}
}
diff --git a/src/devices/bus/nes/somari.h b/src/devices/bus/nes/somari.h
index dda299b3a99..e284e5a78d3 100644
--- a/src/devices/bus/nes/somari.h
+++ b/src/devices/bus/nes/somari.h
@@ -14,45 +14,57 @@ class nes_somari_device : public nes_txrom_device
{
public:
// construction/destruction
- nes_somari_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
+ nes_somari_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock);
- virtual void write_l(offs_t offset, uint8_t data) override { write_m(offset + 0x100, data); }
- virtual void write_m(offs_t offset, uint8_t data) override;
- void mmc1_w(offs_t offset, uint8_t data);
- void mmc3_w(offs_t offset, uint8_t data);
- void vrc2_w(offs_t offset, uint8_t data);
- virtual void write_h(offs_t offset, uint8_t data) override;
+ virtual void write_l(offs_t offset, u8 data) override { write_m(offset + 0x100, data); }
+ virtual void write_m(offs_t offset, u8 data) override;
+ virtual void write_h(offs_t offset, u8 data) override;
virtual void pcb_reset() override;
protected:
+ // construction/destruction
+ nes_somari_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, u32 clock, u8 mmc1_prg_shift);
+
// device-level overrides
- virtual void device_start() override;
+ virtual void device_start() override ATTR_COLD;
private:
+ void mmc1_reset_latch();
+ void mmc1_w(offs_t offset, u8 data);
+ void vrc2_w(offs_t offset, u8 data);
void update_prg();
void update_chr();
void update_mirror();
- void bank_update_switchmode();
-
- uint8_t m_board_mode;
+ void update_all_banks();
- // MMC3 - inherited from txrom
- uint8_t m_mmc3_mirror_reg;
+ u8 m_board_mode;
// MMC1
- uint8_t m_count;
- uint8_t m_mmc1_latch;
- uint8_t m_mmc1_reg[4];
+ u8 m_mmc1_count;
+ u8 m_mmc1_latch;
+ u8 m_mmc1_reg[4];
+ const u8 m_mmc1_prg_shift;
// VRC2
- uint8_t m_vrc_prg_bank[2];
- uint8_t m_vrc_vrom_bank[8];
- uint8_t m_vrc_mirror_reg;
+ u8 m_vrc_prg_bank[2];
+ u8 m_vrc_vrom_bank[8];
+ u8 m_vrc_mirror;
+};
+
+
+// ======================> nes_huang2_device
+
+class nes_huang2_device : public nes_somari_device
+{
+public:
+ // construction/destruction
+ nes_huang2_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock);
};
// device type definition
DECLARE_DEVICE_TYPE(NES_SOMARI, nes_somari_device)
+DECLARE_DEVICE_TYPE(NES_HUANG2, nes_huang2_device)
#endif // MAME_BUS_NES_SOMARI_H
diff --git a/src/devices/bus/nes/subor.cpp b/src/devices/bus/nes/subor.cpp
index 0fa25b2b5bb..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
@@ -98,7 +97,6 @@ void nes_subor2_device::device_start()
void nes_subor0_device::pcb_reset()
{
- m_chr_source = m_vrom_chunks ? CHRROM : CHRRAM;
prg16_89ab(0);
prg16_cdef(0x20);
chr8(0, m_chr_source);
@@ -108,7 +106,6 @@ void nes_subor0_device::pcb_reset()
void nes_subor1_device::pcb_reset()
{
- m_chr_source = m_vrom_chunks ? CHRROM : CHRRAM;
prg16_89ab(0);
prg16_cdef(0x07);
chr8(0, m_chr_source);
@@ -185,12 +182,10 @@ void nes_subor2_device::ppu_latch(offs_t offset)
uint8_t nes_subor2_device::nt_r(offs_t offset)
{
- int page = ((offset & 0xc00) >> 10);
-
- /* Nametable reads report the current page; this seems to work without issues */
- m_page = page;
+ // Nametable reads report the current page; this seems to work without issues
+ m_page = BIT(offset, 10, 2);
- return m_nt_access[page][offset & 0x3ff];
+ return device_nes_cart_interface::nt_r(offset);
}
/*-------------------------------------------------
@@ -236,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)
{
@@ -252,9 +247,9 @@ 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[(offset >> 13) & 0x03] = data;
+ m_reg[BIT(offset, 13, 2)] = data;
subor_helper1 = ((m_reg[0] ^ m_reg[1]) << 1) & 0x20;
subor_helper2 = ((m_reg[2] ^ m_reg[3]) << 0) & 0x1f;
@@ -282,9 +277,9 @@ 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[(offset >> 13) & 0x03] = data;
+ m_reg[BIT(offset, 13, 2)] = data;
subor_helper1 = ((m_reg[0] ^ m_reg[1]) << 1) & 0x20;
subor_helper2 = ((m_reg[2] ^ m_reg[3]) << 0) & 0x1f;
@@ -311,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/subor.h b/src/devices/bus/nes/subor.h
index a4ffc13a553..2fb12136852 100644
--- a/src/devices/bus/nes/subor.h
+++ b/src/devices/bus/nes/subor.h
@@ -26,7 +26,7 @@ public:
protected:
// device-level overrides
- virtual void device_start() override;
+ virtual void device_start() override ATTR_COLD;
private:
uint8_t m_reg[4];
@@ -47,7 +47,7 @@ public:
protected:
// device-level overrides
- virtual void device_start() override;
+ virtual void device_start() override ATTR_COLD;
private:
uint8_t m_reg[4];
@@ -71,7 +71,7 @@ public:
protected:
// device-level overrides
- virtual void device_start() override;
+ virtual void device_start() override ATTR_COLD;
private:
void update_banks();
diff --git a/src/devices/bus/nes/sunsoft.cpp b/src/devices/bus/nes/sunsoft.cpp
index be90e36e535..14ea2ea83c2 100644
--- a/src/devices/bus/nes/sunsoft.cpp
+++ b/src/devices/bus/nes/sunsoft.cpp
@@ -16,7 +16,7 @@
* Sunsoft-5B [mapper 69]
TODO:
- - check 1-line glitches due to IRQ in Sunsoft-3
+ - 1-line glitches in Fantasy Zone II (Sunsoft-3) seem to be PPU timing related. The cycle-based IRQ timer below "should" be ok.
***********************************************************************************************************/
@@ -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"
//-------------------------------------------------
@@ -64,12 +64,12 @@ nes_sunsoft_3_device::nes_sunsoft_3_device(const machine_config &mconfig, const
{
}
-nes_sunsoft_4_device::nes_sunsoft_4_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock)
- : nes_nrom_device(mconfig, type, tag, owner, clock), m_reg(0), m_latch1(0), m_latch2(0), m_wram_enable(0)
+nes_sunsoft_4_device::nes_sunsoft_4_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, u32 clock)
+ : nes_nrom_device(mconfig, type, tag, owner, clock), m_wram_enable(0)
{
}
-nes_sunsoft_4_device::nes_sunsoft_4_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
+nes_sunsoft_4_device::nes_sunsoft_4_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock)
: nes_sunsoft_4_device(mconfig, NES_SUNSOFT_4, tag, owner, clock)
{
}
@@ -91,27 +91,15 @@ nes_sunsoft_5_device::nes_sunsoft_5_device(const machine_config &mconfig, const
}
-void nes_sunsoft_1_device::device_start()
-{
- common_start();
-}
-
void nes_sunsoft_1_device::pcb_reset()
{
- m_chr_source = m_vrom_chunks ? CHRROM : CHRRAM;
prg16_89ab(0);
prg16_cdef(m_prg_chunks - 1);
chr8(0, m_chr_source);
}
-void nes_sunsoft_2_device::device_start()
-{
- common_start();
-}
-
void nes_sunsoft_2_device::pcb_reset()
{
- m_chr_source = m_vrom_chunks ? CHRROM : CHRRAM;
prg16_89ab(0);
prg16_cdef(m_prg_chunks - 1);
chr8(0, m_chr_source);
@@ -122,7 +110,7 @@ void nes_sunsoft_2_device::pcb_reset()
void nes_sunsoft_3_device::device_start()
{
common_start();
- irq_timer = timer_alloc(TIMER_IRQ);
+ irq_timer = timer_alloc(FUNC(nes_sunsoft_3_device::irq_timer_tick), this);
irq_timer->adjust(attotime::zero, 0, clocks_to_attotime(1));
save_item(NAME(m_irq_enable));
@@ -132,10 +120,10 @@ void nes_sunsoft_3_device::device_start()
void nes_sunsoft_3_device::pcb_reset()
{
- m_chr_source = m_vrom_chunks ? CHRROM : CHRRAM;
prg16_89ab(0);
prg16_cdef(m_prg_chunks - 1);
chr8(0, m_chr_source);
+
m_irq_toggle = 0;
m_irq_count = 0;
m_irq_enable = 0;
@@ -144,32 +132,25 @@ void nes_sunsoft_3_device::pcb_reset()
void nes_sunsoft_4_device::device_start()
{
common_start();
- save_item(NAME(m_latch1));
- save_item(NAME(m_latch2));
save_item(NAME(m_reg));
save_item(NAME(m_wram_enable));
}
void nes_sunsoft_4_device::pcb_reset()
{
- m_chr_source = m_vrom_chunks ? CHRROM : CHRRAM;
prg16_89ab(0);
prg16_cdef(m_prg_chunks - 1);
chr8(0, m_chr_source);
- m_reg = 0;
- m_latch1 = 0;
- m_latch2 = 0;
+ m_reg[0] = m_reg[1] = m_reg[2] = 0;
m_wram_enable = 0;
}
void nes_sunsoft_fme7_device::device_start()
{
common_start();
- irq_timer = timer_alloc(TIMER_IRQ);
- // this has to be hardcoded because some some scanline code only suits NTSC... it will be fixed with PPU rewrite
- irq_timer->adjust(attotime::zero, 0, attotime::from_hz((21477272.724 / 12)));
-// irq_timer->adjust(attotime::zero, 0, clocks_to_attotime(1));
+ irq_timer = timer_alloc(FUNC(nes_sunsoft_fme7_device::irq_timer_tick), this);
+ irq_timer->adjust(attotime::zero, 0, clocks_to_attotime(1));
save_item(NAME(m_wram_bank));
save_item(NAME(m_latch));
@@ -179,7 +160,6 @@ void nes_sunsoft_fme7_device::device_start()
void nes_sunsoft_fme7_device::pcb_reset()
{
- m_chr_source = m_vrom_chunks ? CHRROM : CHRRAM;
prg16_89ab(0);
prg16_cdef(m_prg_chunks - 1);
chr8(0, m_chr_source);
@@ -211,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)
{
@@ -238,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);
@@ -256,51 +236,33 @@ void nes_sunsoft_2_device::write_h(offs_t offset, uint8_t data)
Sunsoft-3 board emulation
- The two games using this board have incompatible mirroring
- wiring, making necessary two distinct mappers & pcb_id
+ Games: Fantasy Zone II, Mito Koumon II - Sekai Manyuki
iNES: mapper 67
-------------------------------------------------*/
-
-void nes_sunsoft_3_device::device_timer(emu_timer &timer, device_timer_id id, int param, void *ptr)
+TIMER_CALLBACK_MEMBER(nes_sunsoft_3_device::irq_timer_tick)
{
- if (id == TIMER_IRQ)
+ if (m_irq_enable && --m_irq_count == 0xffff)
{
- if (m_irq_enable)
- {
- if (!m_irq_count)
- {
- set_irq_line(ASSERT_LINE);
- m_irq_count = 0xffff;
- m_irq_enable = 0;
- }
- else
- m_irq_count--;
- }
+ set_irq_line(ASSERT_LINE);
+ m_irq_enable = 0;
}
}
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)
{
case 0x0800:
- chr2_0(data, CHRROM);
- break;
case 0x1800:
- chr2_2(data, CHRROM);
- break;
case 0x2800:
- chr2_4(data, CHRROM);
- break;
case 0x3800:
- chr2_6(data, CHRROM);
+ chr2_x((offset >> 11) & 0x06, data & 0x3f, CHRROM);
break;
- case 0x4000:
case 0x4800:
m_irq_toggle ^= 1;
if (m_irq_toggle)
@@ -311,7 +273,6 @@ void nes_sunsoft_3_device::write_h(offs_t offset, uint8_t data)
case 0x5800:
m_irq_enable = BIT(data, 4);
m_irq_toggle = 0;
- set_irq_line(CLEAR_LINE);
break;
case 0x6800:
switch (data & 3)
@@ -323,10 +284,10 @@ void nes_sunsoft_3_device::write_h(offs_t offset, uint8_t data)
}
break;
case 0x7800:
- prg16_89ab(data);
+ prg16_89ab(data & 0x0f);
break;
default:
- LOG_MMC(("Sunsoft 3 write_h uncaught write, offset: %04x, data: %02x\n", offset, data));
+ set_irq_line(CLEAR_LINE);
break;
}
}
@@ -341,143 +302,98 @@ void nes_sunsoft_3_device::write_h(offs_t offset, uint8_t data)
-------------------------------------------------*/
-void nes_sunsoft_4_device::sun4_mirror( int mirror, int mirr0, int mirr1 )
+void nes_sunsoft_4_device::sun4_mirror()
{
- switch (mirror)
+ static constexpr u8 ciram_lut[4] =
{
- case 0x00:
- set_nt_mirroring(PPU_MIRROR_VERT);
- break;
- case 0x01:
- set_nt_mirroring(PPU_MIRROR_HORZ);
- break;
- case 0x02:
- set_nt_mirroring(PPU_MIRROR_LOW);
- break;
- case 0x03:
- set_nt_mirroring(PPU_MIRROR_HIGH);
- break;
- case 0x10:
- set_nt_page(0, VROM, mirr0 | 0x80, 0);
- set_nt_page(1, VROM, mirr1 | 0x80, 0);
- set_nt_page(2, VROM, mirr0 | 0x80, 0);
- set_nt_page(3, VROM, mirr1 | 0x80, 0);
- break;
- case 0x11:
- set_nt_page(0, VROM, mirr0 | 0x80, 0);
- set_nt_page(1, VROM, mirr0 | 0x80, 0);
- set_nt_page(2, VROM, mirr1 | 0x80, 0);
- set_nt_page(3, VROM, mirr1 | 0x80, 0);
- break;
- case 0x12:
- set_nt_page(0, VROM, mirr0 | 0x80, 0);
- set_nt_page(1, VROM, mirr0 | 0x80, 0);
- set_nt_page(2, VROM, mirr0 | 0x80, 0);
- set_nt_page(3, VROM, mirr0 | 0x80, 0);
- break;
- case 0x13:
- set_nt_page(0, VROM, mirr1 | 0x80, 0);
- set_nt_page(1, VROM, mirr1 | 0x80, 0);
- set_nt_page(2, VROM, mirr1 | 0x80, 0);
- set_nt_page(3, VROM, mirr1 | 0x80, 0);
- break;
- }
+ PPU_MIRROR_VERT, PPU_MIRROR_HORZ, PPU_MIRROR_LOW, PPU_MIRROR_HIGH
+ };
+
+ static constexpr u8 vrom_lut[4][4] =
+ {
+ { 0, 1, 0, 1 }, // vert
+ { 0, 0, 1, 1 }, // horz
+ { 0, 0, 0, 0 }, // low
+ { 1, 1, 1, 1 } // high
+ };
+
+ int mirr = m_reg[2] & 0x03;
+
+ if (BIT(m_reg[2], 4))
+ for (int i = 0; i < 4; i++)
+ set_nt_page(i, VROM, m_reg[vrom_lut[mirr][i]], 0);
+ else
+ set_nt_mirroring(ciram_lut[mirr]);
}
-void nes_sunsoft_4_device::sun4_write(offs_t offset, uint8_t data)
+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)
{
case 0x0000:
- chr2_0(data, CHRROM);
- break;
case 0x1000:
- chr2_2(data, CHRROM);
- break;
case 0x2000:
- chr2_4(data, CHRROM);
- break;
case 0x3000:
- chr2_6(data, CHRROM);
+ chr2_x((offset >> 11) & 0x06, data, CHRROM);
break;
case 0x4000:
- m_latch1 = data & 0x7f;
- sun4_mirror(m_reg, m_latch1, m_latch2);
- break;
case 0x5000:
- m_latch2 = data & 0x7f;
- sun4_mirror(m_reg, m_latch1, m_latch2);
- break;
case 0x6000:
- m_reg = data & 0x13;
- sun4_mirror(m_reg, m_latch1, m_latch2);
+ m_reg[(offset >> 12) - 4] = data | 0x80;
+ sun4_mirror();
break;
case 0x7000:
prg16_89ab(data & 0x0f);
m_wram_enable = BIT(data, 4);
break;
- default:
- LOG_MMC(("Sunsoft 4 write_h uncaught write, offset: %04x, data: %02x\n", offset, data));
- break;
}
}
-void nes_sunsoft_4_device::write_m(offs_t offset, uint8_t 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_battery.empty() && m_wram_enable)
- m_battery[offset & (m_battery.size() - 1)] = data;
- if (!m_prgram.empty() && m_wram_enable)
- m_prgram[offset & (m_prgram.size() - 1)] = data;
+ if (m_wram_enable)
+ device_nes_cart_interface::write_m(offset, data);
}
-uint8_t nes_sunsoft_4_device::read_m(offs_t offset)
+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_battery.empty() && m_wram_enable)
- return m_battery[offset & (m_battery.size() - 1)];
- if (!m_prgram.empty() && m_wram_enable)
- return m_prgram[offset & (m_prgram.size() - 1)];
+ if (m_wram_enable)
+ return device_nes_cart_interface::read_m(offset);
- return get_open_bus(); // open bus
+ return get_open_bus();
}
/*-------------------------------------------------
JxROM & Sunsoft 5A / 5B / FME7 board emulation
- Notice that Sunsoft-5B = FME7 + sound chip (the latter being
- currently unemulated in MESS)
+ Notice that Sunsoft-5B = FME7 + sound chip
iNES: mapper 69
-------------------------------------------------*/
-void nes_sunsoft_fme7_device::device_timer(emu_timer &timer, device_timer_id id, int param, void *ptr)
+TIMER_CALLBACK_MEMBER(nes_sunsoft_fme7_device::irq_timer_tick)
{
- if (id == TIMER_IRQ)
+ if (BIT(m_irq_enable, 7)) // counter decrement enabled
{
- if ((m_irq_enable & 0x80)) // bit7, counter decrement
+ if (--m_irq_count == 0xffff)
{
- if (!m_irq_count)
- {
- m_irq_count = 0xffff;
- if (m_irq_enable & 0x01) // bit0, trigger enable
- set_irq_line(ASSERT_LINE);
- }
- else
- m_irq_count--;
+ if (BIT(m_irq_enable, 0)) // IRQs enabled
+ set_irq_line(ASSERT_LINE);
}
}
}
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)
{
@@ -515,8 +431,7 @@ void nes_sunsoft_fme7_device::fme7_write(offs_t offset, uint8_t data)
break;
case 0x0d:
m_irq_enable = data;
- if (!(m_irq_enable & 1))
- set_irq_line(CLEAR_LINE);
+ set_irq_line(CLEAR_LINE);
break;
case 0x0e:
m_irq_count = (m_irq_count & 0xff00) | data;
@@ -528,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;
}
}
@@ -536,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;
@@ -552,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)];
@@ -564,7 +479,7 @@ uint8_t nes_sunsoft_fme7_device::read_m(offs_t offset)
return m_prgram[((bank * 0x2000) + offset) & (m_prgram.size() - 1)];
}
- return get_open_bus(); // open bus
+ return get_open_bus();
}
@@ -580,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)
{
@@ -616,5 +531,5 @@ void nes_sunsoft_5_device::device_add_mconfig(machine_config &config)
// TODO: this is not how Sunsoft 5B clock signaling works!
// The board uses the CLK pin in reality, not hardcoded NTSC values!
- YM2149(config, m_ym2149, (XTAL(21'477'272)/12)/2).add_route(ALL_OUTPUTS, "addon", 0.50); // divide by 2 for the internal divider
+ SUNSOFT_5B_SOUND(config, m_ym2149, XTAL(21'477'272)/12).add_route(ALL_OUTPUTS, "addon", 0.50);
}
diff --git a/src/devices/bus/nes/sunsoft.h b/src/devices/bus/nes/sunsoft.h
index c02b94647cf..05c82759d86 100644
--- a/src/devices/bus/nes/sunsoft.h
+++ b/src/devices/bus/nes/sunsoft.h
@@ -20,10 +20,6 @@ public:
virtual void write_m(offs_t offset, uint8_t data) override;
virtual void pcb_reset() override;
-
-protected:
- // device-level overrides
- virtual void device_start() override;
};
@@ -38,10 +34,6 @@ public:
virtual void write_h(offs_t offset, uint8_t data) override;
virtual void pcb_reset() override;
-
-protected:
- // device-level overrides
- virtual void device_start() override;
};
@@ -59,13 +51,14 @@ public:
protected:
// device-level overrides
- virtual void device_start() override;
- virtual void device_timer(emu_timer &timer, device_timer_id id, int param, void *ptr) override;
+ virtual void device_start() override ATTR_COLD;
+
+ TIMER_CALLBACK_MEMBER(irq_timer_tick);
+
private:
uint16_t m_irq_count;
int m_irq_enable, m_irq_toggle;
- static const device_timer_id TIMER_IRQ = 0;
emu_timer *irq_timer;
};
@@ -76,26 +69,30 @@ class nes_sunsoft_4_device : public nes_nrom_device
{
public:
// construction/destruction
- nes_sunsoft_4_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
+ nes_sunsoft_4_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock);
- virtual uint8_t read_m(offs_t offset) override;
- virtual void write_m(offs_t offset, uint8_t data) override;
- void sun4_write(offs_t offset, uint8_t data);
- virtual void write_h(offs_t offset, uint8_t data) override { sun4_write(offset, data); }
+ virtual u8 read_m(offs_t offset) override;
+ virtual void write_m(offs_t offset, u8 data) override;
+ void sun4_write(offs_t offset, u8 data);
+ virtual void write_h(offs_t offset, u8 data) override { sun4_write(offset, data); }
virtual void pcb_reset() override;
protected:
- nes_sunsoft_4_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock);
+ nes_sunsoft_4_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_start() override ATTR_COLD;
- void sun4_mirror(int mirror, int mirr0, int mirr1);
+ u8 m_wram_enable;
- int m_reg, m_latch1, m_latch2, m_wram_enable;
+private:
+ void sun4_mirror();
+
+ u8 m_reg[3];
};
+
// ======================> nes_sunsoft_fme7_device
class nes_sunsoft_fme7_device : public nes_nrom_device
@@ -115,14 +112,14 @@ protected:
nes_sunsoft_fme7_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_timer(emu_timer &timer, device_timer_id id, int param, void *ptr) override;
+ virtual void device_start() override ATTR_COLD;
+
+ TIMER_CALLBACK_MEMBER(irq_timer_tick);
private:
uint16_t m_irq_count;
int m_irq_enable;
- static const device_timer_id TIMER_IRQ = 0;
emu_timer *irq_timer;
uint8_t m_latch;
@@ -141,7 +138,7 @@ public:
virtual void write_h(offs_t offset, uint8_t data) override;
protected:
- virtual void device_add_mconfig(machine_config &config) override;
+ virtual void device_add_mconfig(machine_config &config) override ATTR_COLD;
private:
required_device<ay8910_device> m_ym2149;
diff --git a/src/devices/bus/nes/sunsoft_dcs.cpp b/src/devices/bus/nes/sunsoft_dcs.cpp
index 23c81894666..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"
//-----------------------------------------------
@@ -35,7 +34,7 @@
//-------------------------------------------------
ntb_cart_interface::ntb_cart_interface(const machine_config &mconfig, device_t &device)
- : device_slot_card_interface(mconfig, device)
+ : device_interface(device, "ntbcart")
, m_rom(nullptr)
{
}
@@ -52,8 +51,8 @@ DEFINE_DEVICE_TYPE(NES_NTB_SLOT, nes_ntb_slot_device, "nes_ntb_slot", "NES NTB C
nes_ntb_slot_device::nes_ntb_slot_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
: device_t(mconfig, NES_NTB_SLOT, tag, owner, clock)
- , device_image_interface(mconfig, *this)
- , device_slot_interface(mconfig, *this)
+ , device_cartrom_image_interface(mconfig, *this)
+ , device_single_card_slot_interface<ntb_cart_interface>(mconfig, *this)
, m_cart(nullptr)
{
}
@@ -65,44 +64,43 @@ nes_ntb_slot_device::~nes_ntb_slot_device()
void nes_ntb_slot_device::device_start()
{
- m_cart = dynamic_cast<ntb_cart_interface *>(get_card_device());
+ m_cart = get_card_device();
}
uint8_t nes_ntb_slot_device::read(offs_t offset)
{
if (m_cart)
return m_cart->read(offset);
-
- return 0xff;
+ else
+ return 0xff;
}
-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());
}
@@ -166,30 +164,19 @@ nes_sunsoft_dcs_device::nes_sunsoft_dcs_device(const machine_config &mconfig, co
void nes_sunsoft_dcs_device::device_start()
{
- common_start();
- ntb_enable_timer = timer_alloc(TIMER_PROTECT);
+ nes_sunsoft_4_device::device_start();
+
+ ntb_enable_timer = timer_alloc(FUNC(nes_sunsoft_dcs_device::protect_tick), this);
ntb_enable_timer->reset();
timer_freq = clocks_to_attotime(107520);
- save_item(NAME(m_latch1));
- save_item(NAME(m_latch2));
- save_item(NAME(m_reg));
- save_item(NAME(m_wram_enable));
save_item(NAME(m_exrom_enable));
save_item(NAME(m_timer_on));
}
void nes_sunsoft_dcs_device::pcb_reset()
{
- m_chr_source = m_vrom_chunks ? CHRROM : CHRRAM;
- prg16_89ab(0);
- prg16_cdef(m_prg_chunks - 1);
- chr8(0, m_chr_source);
-
- m_reg = 0;
- m_latch1 = 0;
- m_latch2 = 0;
- m_wram_enable = 0;
+ nes_sunsoft_4_device::pcb_reset();
m_exrom_enable = 0;
m_timer_on = 0;
}
@@ -214,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)
{
@@ -231,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)
{
@@ -246,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;
@@ -262,14 +249,14 @@ 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)];
if (!m_prgram.empty() && m_wram_enable)
return m_prgram[offset & (m_prgram.size() - 1)];
- return get_open_bus(); // open bus
+ return get_open_bus();
}
@@ -292,14 +279,11 @@ void nes_sunsoft_dcs_device::device_add_mconfig(machine_config &config)
//-------------------------------------------------
-// device_timer - handler timer events
+// protect_tick - handler NTB-ROM timer elapsing
//-------------------------------------------------
-void nes_sunsoft_dcs_device::device_timer(emu_timer &timer, device_timer_id id, int param, void *ptr)
+TIMER_CALLBACK_MEMBER(nes_sunsoft_dcs_device::protect_tick)
{
- if (id == TIMER_PROTECT)
- {
- m_timer_on = 0;
- ntb_enable_timer->reset();
- }
+ m_timer_on = 0;
+ ntb_enable_timer->reset();
}
diff --git a/src/devices/bus/nes/sunsoft_dcs.h b/src/devices/bus/nes/sunsoft_dcs.h
index 51a11b22ae4..8fb49a81bd8 100644
--- a/src/devices/bus/nes/sunsoft_dcs.h
+++ b/src/devices/bus/nes/sunsoft_dcs.h
@@ -6,7 +6,7 @@
#pragma once
#include "sunsoft.h"
-#include "softlist_dev.h"
+#include "imagedev/cartrom.h"
//-----------------------------------------------
@@ -17,7 +17,7 @@
// ======================> ntb_cart_interface
-class ntb_cart_interface : public device_slot_card_interface
+class ntb_cart_interface : public device_interface
{
public:
// construction/destruction
@@ -40,8 +40,8 @@ protected:
class nes_sunsoft_dcs_device;
class nes_ntb_slot_device : public device_t,
- public device_image_interface,
- public device_slot_interface
+ public device_cartrom_image_interface,
+ public device_single_card_slot_interface<ntb_cart_interface>
{
friend class nes_sunsoft_dcs_device;
public:
@@ -59,29 +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();
- // device-level overrides
- virtual void device_start() override;
-
- // image-level overrides
- virtual image_init_result call_load() override;
- virtual const software_list_loader &get_software_list_loader() const override { return rom_software_list_loader::instance(); }
-
- virtual iodevice_t image_type() const override { return IO_CARTSLOT; }
- virtual bool is_readable() const override { return 1; }
- virtual bool is_writeable() const override { return 0; }
- virtual bool is_creatable() const override { return 0; }
- virtual bool must_be_loaded() const override { return 0; }
- virtual bool is_reset_on_load() const override { return 1; }
- virtual const char *image_interface() const override { return "ntb_cart"; }
- virtual const char *file_extensions() const override { return "bin"; }
-
- // slot interface overrides
+ // 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"; }
+
+ // 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:
- ntb_cart_interface* m_cart;
+ // device_t implementation
+ virtual void device_start() override ATTR_COLD;
+
+ ntb_cart_interface *m_cart;
};
// device type definition
@@ -103,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
- virtual void device_start() override;
+ // device_t implementation
+ virtual void device_start() override ATTR_COLD;
+ virtual const tiny_rom_entry *device_rom_region() const override ATTR_COLD;
};
// device type definition
@@ -142,14 +135,12 @@ public:
protected:
// device-level overrides
- virtual void device_start() override;
- virtual void device_timer(emu_timer &timer, device_timer_id id, int param, void *ptr) override;
+ virtual void device_start() override ATTR_COLD;
+ virtual void device_add_mconfig(machine_config &config) override ATTR_COLD;
- virtual void device_add_mconfig(machine_config &config) override;
+ TIMER_CALLBACK_MEMBER(protect_tick);
private:
- static constexpr device_timer_id TIMER_PROTECT = 0;
-
int m_timer_on, m_exrom_enable;
required_device<nes_ntb_slot_device> m_subslot;
diff --git a/src/devices/bus/nes/taito.cpp b/src/devices/bus/nes/taito.cpp
index 28c37b6109c..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"
//-------------------------------------------------
@@ -46,41 +45,35 @@ DEFINE_DEVICE_TYPE(NES_X1_005, nes_x1_005_device, "nes_x1_
DEFINE_DEVICE_TYPE(NES_X1_017, nes_x1_017_device, "nes_x1_017", "NES Cart Taito X1-017 PCB")
-nes_tc0190fmc_device::nes_tc0190fmc_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock)
+nes_tc0190fmc_device::nes_tc0190fmc_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, u32 clock)
: nes_nrom_device(mconfig, type, tag, owner, clock)
{
}
-nes_tc0190fmc_device::nes_tc0190fmc_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
+nes_tc0190fmc_device::nes_tc0190fmc_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock)
: nes_tc0190fmc_device(mconfig, NES_TC0190FMC, tag, owner, clock)
{
}
-nes_tc0190fmc_pal16r4_device::nes_tc0190fmc_pal16r4_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
+nes_tc0190fmc_pal16r4_device::nes_tc0190fmc_pal16r4_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock)
: nes_tc0190fmc_device(mconfig, NES_TC0190FMC_PAL16R4, tag, owner, clock), m_irq_count(0), m_irq_count_latch(0), m_irq_enable(0)
{
}
-nes_x1_005_device::nes_x1_005_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
+nes_x1_005_device::nes_x1_005_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock)
: nes_nrom_device(mconfig, NES_X1_005, tag, owner, clock), m_latch(0)
{
}
-nes_x1_017_device::nes_x1_017_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
- : nes_nrom_device(mconfig, NES_X1_017, tag, owner, clock), m_latch(0)
+nes_x1_017_device::nes_x1_017_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock)
+ : nes_nrom_device(mconfig, NES_X1_017, tag, owner, clock), m_latch(0), m_irq_count(0), m_irq_count_latch(0), m_irq_enable(0), irq_timer(nullptr)
{
}
-void nes_tc0190fmc_device::device_start()
-{
- common_start();
-}
-
void nes_tc0190fmc_device::pcb_reset()
{
- m_chr_source = m_vrom_chunks ? CHRROM : CHRRAM;
prg16_89ab(0);
prg16_cdef(m_prg_chunks - 1);
chr8(0, m_chr_source);
@@ -88,7 +81,7 @@ void nes_tc0190fmc_device::pcb_reset()
void nes_tc0190fmc_pal16r4_device::device_start()
{
- common_start();
+ nes_tc0190fmc_device::device_start();
save_item(NAME(m_irq_enable));
save_item(NAME(m_irq_count));
save_item(NAME(m_irq_count_latch));
@@ -96,10 +89,7 @@ void nes_tc0190fmc_pal16r4_device::device_start()
void nes_tc0190fmc_pal16r4_device::pcb_reset()
{
- m_chr_source = m_vrom_chunks ? CHRROM : CHRRAM;
- prg16_89ab(0);
- prg16_cdef(m_prg_chunks - 1);
- chr8(0, m_chr_source);
+ nes_tc0190fmc_device::pcb_reset();
m_irq_enable = 0;
m_irq_count = 0;
@@ -119,7 +109,6 @@ void nes_x1_005_device::device_start()
void nes_x1_005_device::pcb_reset()
{
- m_chr_source = m_vrom_chunks ? CHRROM : CHRRAM;
prg16_89ab(0);
prg16_cdef(m_prg_chunks - 1);
chr8(0, m_chr_source);
@@ -130,6 +119,13 @@ void nes_x1_005_device::pcb_reset()
void nes_x1_017_device::device_start()
{
common_start();
+ irq_timer = timer_alloc(FUNC(nes_x1_017_device::irq_timer_tick), this);
+ irq_timer->adjust(attotime::zero, 0, clocks_to_attotime(1));
+
+ save_item(NAME(m_irq_enable));
+ save_item(NAME(m_irq_count));
+ save_item(NAME(m_irq_count_latch));
+
save_item(NAME(m_latch));
save_item(NAME(m_reg));
save_item(NAME(m_mmc_vrom_bank));
@@ -142,14 +138,17 @@ void nes_x1_017_device::device_start()
void nes_x1_017_device::pcb_reset()
{
- m_chr_source = m_vrom_chunks ? CHRROM : CHRRAM;
prg16_89ab(0);
prg16_cdef(m_prg_chunks - 1);
chr8(0, m_chr_source);
+ m_irq_enable = 0;
+ m_irq_count = 0;
+ m_irq_count_latch = 0;
+
m_latch = 0;
- memset(m_reg, 0, sizeof(m_reg));
- memset(m_mmc_vrom_bank, 0, sizeof(m_mmc_vrom_bank));
+ m_reg[0] = m_reg[1] = m_reg[2] = 0;
+ std::fill(std::begin(m_mmc_vrom_bank), std::end(m_mmc_vrom_bank), 0x00);
}
@@ -168,15 +167,15 @@ void nes_x1_017_device::pcb_reset()
iNES: mapper 33
- In MESS: Supported.
+ In MAME: Supported.
-------------------------------------------------*/
-void nes_tc0190fmc_device::tc0190fmc_write(offs_t offset, uint8_t data)
+void nes_tc0190fmc_device::write_h(offs_t offset, u8 data)
{
- LOG_MMC(("tc0190fmc_write, offset: %04x, data: %02x\n", offset, data));
+ LOG("tc0190fmc write_h, offset: %04x, data: %02x\n", offset, data);
- switch (offset & 0x7003)
+ switch (offset & 0x6003)
{
case 0x0000:
set_nt_mirroring(BIT(data, 6) ? PPU_MIRROR_HORZ : PPU_MIRROR_VERT);
@@ -186,22 +185,14 @@ void nes_tc0190fmc_device::tc0190fmc_write(offs_t offset, uint8_t data)
prg8_ab(data);
break;
case 0x0002:
- chr2_0(data, CHRROM);
- break;
case 0x0003:
- chr2_2(data, CHRROM);
+ chr2_x((offset & 1) << 1, data, CHRROM);
break;
case 0x2000:
- chr1_4(data, CHRROM);
- break;
case 0x2001:
- chr1_5(data, CHRROM);
- break;
case 0x2002:
- chr1_6(data, CHRROM);
- break;
case 0x2003:
- chr1_7(data, CHRROM);
+ chr1_x((offset & 0x03) | 4, data, CHRROM);
break;
}
}
@@ -221,30 +212,30 @@ void nes_tc0190fmc_device::tc0190fmc_write(offs_t offset, uint8_t data)
iNES: mapper 48
- In MESS: Supported.
+ In MAME: Supported.
-------------------------------------------------*/
-void nes_tc0190fmc_pal16r4_device::hblank_irq( int scanline, int vblank, int blanked )
+void nes_tc0190fmc_pal16r4_device::hblank_irq(int scanline, bool vblank, bool blanked)
{
if (scanline < ppu2c0x_device::BOTTOM_VISIBLE_SCANLINE)
{
- int prior_count = m_irq_count;
- if (m_irq_count == 0)
- m_irq_count = m_irq_count_latch;
- else
+ if (m_irq_count)
+ {
m_irq_count--;
-
- if (m_irq_enable && !blanked && (m_irq_count == 0) && prior_count)
- set_irq_line(ASSERT_LINE);
+ if (m_irq_enable && !blanked && !m_irq_count)
+ set_irq_line(ASSERT_LINE);
+ }
+ else
+ m_irq_count = m_irq_count_latch;
}
}
-void nes_tc0190fmc_pal16r4_device::write_h(offs_t offset, uint8_t data)
+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 & 0x7003)
+ switch (offset & 0x6003)
{
case 0x0000:
prg8_89(data);
@@ -256,10 +247,10 @@ void nes_tc0190fmc_pal16r4_device::write_h(offs_t offset, uint8_t data)
case 0x2001:
case 0x2002:
case 0x2003:
- tc0190fmc_write(offset, data);
+ nes_tc0190fmc_device::write_h(offset, data);
break;
case 0x4000:
- m_irq_count_latch = (0x100 - data) & 0xff;
+ m_irq_count_latch = ~data;
break;
case 0x4001:
m_irq_count = m_irq_count_latch;
@@ -284,124 +275,110 @@ void nes_tc0190fmc_pal16r4_device::write_h(offs_t offset, uint8_t data)
Actually, Fudou Myouou Den uses a variant of the board with
CIRAM, making necessary two distinct mappers & pcb_id.
- Also, we miss to emulate the security check at 0x7ef8 / 0x7ef9
- and the 0x80 ram!
-
iNES: mappers 80 & 207
-------------------------------------------------*/
-void nes_x1_005_device::write_m(offs_t offset, uint8_t 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);
- switch (offset)
+ if ((offset & 0x1f70) == 0x1e70) // A7 is not connected
{
- case 0x1ef0:
- chr2_0((data & 0x7f) >> 1, CHRROM);
- if (m_x1_005_alt_mirroring)
- {
- set_nt_page(0, CIRAM, (data & 0x80) ? 1 : 0, 1);
- set_nt_page(1, CIRAM, (data & 0x80) ? 1 : 0, 1);
- }
- break;
- case 0x1ef1:
- chr2_2((data & 0x7f) >> 1, CHRROM);
- if (m_x1_005_alt_mirroring)
- {
- set_nt_page(2, CIRAM, (data & 0x80) ? 1 : 0, 1);
- set_nt_page(3, CIRAM, (data & 0x80) ? 1 : 0, 1);
- }
- break;
- case 0x1ef2:
- chr1_4(data, CHRROM);
- break;
- case 0x1ef3:
- chr1_5(data, CHRROM);
- break;
- case 0x1ef4:
- chr1_6(data, CHRROM);
- break;
- case 0x1ef5:
- chr1_7(data, CHRROM);
- break;
- case 0x1ef6:
- case 0x1ef7:
- if (!m_x1_005_alt_mirroring)
- set_nt_mirroring(BIT(data, 0) ? PPU_MIRROR_VERT : PPU_MIRROR_HORZ);
- break;
- case 0x1ef8:
- case 0x1ef9:
- m_latch = data;
- break;
- case 0x1efa:
- case 0x1efb:
- prg8_89(data);
- break;
- case 0x1efc:
- case 0x1efd:
- prg8_ab(data);
- break;
- case 0x1efe:
- case 0x1eff:
- prg8_cd(data);
- break;
- default:
- logerror("mapper80_m_w uncaught addr: %04x, value: %02x\n", offset + 0x6000, data);
- break;
+ u8 reg = offset & 0x0f;
+
+ switch (reg)
+ {
+ case 0x0:
+ case 0x1:
+ reg <<= 1;
+ chr2_x(reg, BIT(data, 1, 6), CHRROM);
+ if (m_x1_005_alt_mirroring)
+ {
+ set_nt_page(reg + 0, CIRAM, BIT(data, 7), 1);
+ set_nt_page(reg + 1, CIRAM, BIT(data, 7), 1);
+ }
+ break;
+ case 0x2:
+ case 0x3:
+ case 0x4:
+ case 0x5:
+ chr1_x(reg + 2, data, CHRROM);
+ break;
+ case 0x6:
+ case 0x7:
+ if (!m_x1_005_alt_mirroring)
+ set_nt_mirroring(BIT(data, 0) ? PPU_MIRROR_VERT : PPU_MIRROR_HORZ);
+ break;
+ case 0x8:
+ case 0x9:
+ m_latch = data;
+ break;
+ case 0xa:
+ case 0xb:
+ case 0xc:
+ case 0xd:
+ case 0xe:
+ case 0xf:
+ prg8_x((reg - 0x0a) >> 1, data);
+ break;
+ }
}
-
- if (offset >= 0x1f00 && m_latch == 0xa3)
+ else if (offset >= 0x1f00 && m_latch == 0xa3)
m_x1_005_ram[offset & 0x7f] = data;
+ else
+ LOGMASKED(LOG_UNHANDLED, "Taito X1-005 uncaught addr: %04x, value: %02x\n", offset + 0x6000, data);
}
-uint8_t nes_x1_005_device::read_m(offs_t offset)
+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];
- return get_open_bus(); // open bus
+ return get_open_bus();
}
/*-------------------------------------------------
Taito X1-017 board emulation
- We miss to emulate the security check at 0x6000-0x73ff
- and the ram!
-
Games: Kyuukyoku Harikiri Koushien, Kyuukyoku Harikiri
- Stadium, SD Keiji - Blader
+ Stadium 3, Kyuukyoku Harikiri - Heisei Gannenban,
+ SD Keiji - Blader
+
+ NES 2.0: mapper 552 (old mapper 82 are mis-ordered bad dumps)
- iNES: mapper 82
+ In MAME: Supported.
- In MESS: Supported.
+ TODO: KH Koushien seems to be working except it needs to
+ be reset once with a new NVRAM file. KH Heisei won't
+ load "Single Game" menu option but other game modes work.
-------------------------------------------------*/
+TIMER_CALLBACK_MEMBER(nes_x1_017_device::irq_timer_tick)
+{
+ if ((m_irq_enable & 0x05) == 1 && m_irq_count) // counting enabled?
+ m_irq_count--;
+ if (!m_irq_count && BIT(m_irq_enable, 1))
+ set_irq_line(ASSERT_LINE);
+}
+
void nes_x1_017_device::set_chr()
{
- if (m_latch)
- {
- chr2_4(m_mmc_vrom_bank[0] >> 1, CHRROM);
- chr2_6(m_mmc_vrom_bank[1] >> 1, CHRROM);
- }
- else
- {
- chr2_0(m_mmc_vrom_bank[0] >> 1, CHRROM);
- chr2_2(m_mmc_vrom_bank[1] >> 1, CHRROM);
- }
+ chr2_x(0 ^ m_latch, m_mmc_vrom_bank[0] >> 1, CHRROM);
+ chr2_x(2 ^ m_latch, m_mmc_vrom_bank[1] >> 1, CHRROM);
chr1_x(4 ^ m_latch, m_mmc_vrom_bank[2], CHRROM);
chr1_x(5 ^ m_latch, m_mmc_vrom_bank[3], CHRROM);
chr1_x(6 ^ m_latch, m_mmc_vrom_bank[4], CHRROM);
chr1_x(7 ^ m_latch, m_mmc_vrom_bank[5], CHRROM);
}
-void nes_x1_017_device::write_m(offs_t offset, uint8_t data)
+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)
{
@@ -411,19 +388,13 @@ void nes_x1_017_device::write_m(offs_t offset, uint8_t data)
case 0x1ef3:
case 0x1ef4:
case 0x1ef5:
- if (m_mmc_vrom_bank[offset & 0x07] != data)
- {
- m_mmc_vrom_bank[offset & 0x07] = data;
- set_chr();
- }
+ m_mmc_vrom_bank[offset & 0x07] = data;
+ set_chr();
break;
case 0x1ef6:
set_nt_mirroring(BIT(data, 0) ? PPU_MIRROR_VERT : PPU_MIRROR_HORZ);
- if (m_latch != ((data & 0x02) << 1))
- {
- m_latch = ((data & 0x02) << 1);
- set_chr();
- }
+ m_latch = (data & 0x02) << 1;
+ set_chr();
break;
case 0x1ef7:
case 0x1ef8:
@@ -431,39 +402,54 @@ void nes_x1_017_device::write_m(offs_t offset, uint8_t data)
m_reg[(offset & 0x0f) - 7] = data;
break;
case 0x1efa:
- prg8_89(data >> 2);
- break;
case 0x1efb:
- prg8_ab(data >> 2);
- break;
case 0x1efc:
- prg8_cd(data >> 2);
+ prg8_x((offset & 0x0f) - 0x0a, bitswap<6>(data, 0, 1, 2, 3, 4, 5));
+ break;
+ case 0x1efd:
+ m_irq_count_latch = data;
+ break;
+ case 0x1efe:
+ m_irq_enable = data;
+ if (!BIT(m_irq_enable, 0))
+ m_irq_count = m_irq_count_latch ? (m_irq_count_latch + 2) * 16 : 17;
+ if (!BIT(m_irq_enable, 1))
+ set_irq_line(CLEAR_LINE);
break;
- default:
- logerror("x1017_m_w uncaught write, addr: %04x, value: %02x\n", offset + 0x6000, data);
+ case 0x1eff:
+ set_irq_line(CLEAR_LINE);
+ m_irq_count = m_irq_count_latch ? (m_irq_count_latch + 1) * 16 : 1;
break;
}
// 2+2+1 KB of Internal RAM can be independently enabled/disabled!
- if (offset < 0x0800 && m_reg[0] == 0xca)
- m_x1_017_ram[0x0000 + (offset & 0x7ff)] = data;
- if (offset < 0x1000 && m_reg[1] == 0x69)
- m_x1_017_ram[0x0800 + (offset & 0x7ff)] = data;
- if (offset < 0x1400 && m_reg[2] == 0x84)
- m_x1_017_ram[0x1000 + (offset & 0x3ff)] = data;
+ if ((offset < 0x0800 && m_reg[0] == 0xca) ||
+ (offset < 0x1000 && m_reg[1] == 0x69) ||
+ (offset < 0x1400 && m_reg[2] == 0x84))
+ {
+ m_x1_017_ram[offset] = data;
+
+ // 1st byte in each 1K page latches most recent read/write from that page
+ m_x1_017_ram[offset & 0x1c00] = data;
+ }
}
-uint8_t nes_x1_017_device::read_m(offs_t offset)
+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)
- return m_x1_017_ram[0x0000 + (offset & 0x7ff)];
- if (offset < 0x1000 && m_reg[1] == 0x69)
- return m_x1_017_ram[0x0800 + (offset & 0x7ff)];
- if (offset < 0x1400 && m_reg[2] == 0x84)
- return m_x1_017_ram[0x1000 + (offset & 0x3ff)];
-
- return get_open_bus(); // open bus
+ if ((offset < 0x0800 && m_reg[0] == 0xca) ||
+ (offset < 0x1000 && m_reg[1] == 0x69) ||
+ (offset < 0x1400 && m_reg[2] == 0x84))
+ {
+ u8 ret = m_x1_017_ram[offset];
+
+ // 1st byte in each 1K page latches most recent read/write from that page
+ m_x1_017_ram[offset & 0x1c00] = ret;
+
+ return ret;
+ }
+
+ return 0; // no open bus behavior due to pull-down resistors
}
diff --git a/src/devices/bus/nes/taito.h b/src/devices/bus/nes/taito.h
index b4efa553c86..791ed08ffe9 100644
--- a/src/devices/bus/nes/taito.h
+++ b/src/devices/bus/nes/taito.h
@@ -14,18 +14,14 @@ class nes_tc0190fmc_device : public nes_nrom_device
{
public:
// construction/destruction
- nes_tc0190fmc_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
+ nes_tc0190fmc_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock);
- void tc0190fmc_write(offs_t offset, uint8_t data);
- virtual void write_h(offs_t offset, uint8_t data) override { tc0190fmc_write(offset, data); }
+ virtual void write_h(offs_t offset, u8 data) override;
virtual void pcb_reset() override;
protected:
- nes_tc0190fmc_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;
+ nes_tc0190fmc_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, u32 clock);
};
@@ -35,20 +31,20 @@ class nes_tc0190fmc_pal16r4_device : public nes_tc0190fmc_device
{
public:
// construction/destruction
- nes_tc0190fmc_pal16r4_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
+ nes_tc0190fmc_pal16r4_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock);
- virtual void write_h(offs_t offset, uint8_t data) override;
+ virtual void write_h(offs_t offset, u8 data) override;
- virtual void hblank_irq(int scanline, int vblank, int blanked) override;
+ virtual void hblank_irq(int scanline, bool vblank, bool blanked) override;
virtual void pcb_reset() override;
protected:
// device-level overrides
- virtual void device_start() override;
+ virtual void device_start() override ATTR_COLD;
private:
- uint16_t m_irq_count, m_irq_count_latch;
- int m_irq_enable;
+ u8 m_irq_count, m_irq_count_latch;
+ u8 m_irq_enable;
};
@@ -58,21 +54,21 @@ class nes_x1_005_device : public nes_nrom_device
{
public:
// construction/destruction
- nes_x1_005_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
+ nes_x1_005_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock);
- virtual uint8_t read_m(offs_t offset) override;
- virtual void write_m(offs_t offset, uint8_t data) override;
+ virtual u8 read_m(offs_t offset) override;
+ virtual void write_m(offs_t offset, u8 data) override;
virtual void pcb_reset() override;
protected:
// device-level overrides
- virtual void device_start() override;
+ virtual void device_start() override ATTR_COLD;
private:
- uint8_t m_latch;
+ u8 m_latch;
// Taito X1-005 chip contains 80 bytes of internal ram, possibly battery backed up
- uint8_t m_x1_005_ram[0x80];
+ u8 m_x1_005_ram[0x80];
};
@@ -82,24 +78,34 @@ class nes_x1_017_device : public nes_nrom_device
{
public:
// construction/destruction
- nes_x1_017_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
+ nes_x1_017_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock);
- virtual uint8_t read_m(offs_t offset) override;
- virtual void write_m(offs_t offset, uint8_t data) override;
+ virtual u8 read_ex(offs_t offset) override { return 0; } // no open bus
+ virtual u8 read_l(offs_t offset) override { return 0; } // no open bus
+ virtual u8 read_m(offs_t offset) override;
+ virtual void write_m(offs_t offset, u8 data) override;
virtual void pcb_reset() override;
protected:
// device-level overrides
- virtual void device_start() override;
+ virtual void device_start() override ATTR_COLD;
+
+ TIMER_CALLBACK_MEMBER(irq_timer_tick);
private:
void set_chr();
- uint8_t m_latch;
- uint8_t m_reg[3]; //mapper ram protect
- uint8_t m_mmc_vrom_bank[6];
+ u8 m_latch;
+ u8 m_reg[3]; // mapper ram enable
+ u8 m_mmc_vrom_bank[6];
// Taito X1-017 chip contains 5K of internal ram, battery backed up
- uint8_t m_x1_017_ram[0x1400];
+ u8 m_x1_017_ram[0x1400];
+
+ u16 m_irq_count;
+ u8 m_irq_count_latch;
+ u8 m_irq_enable;
+
+ emu_timer *irq_timer;
};
@@ -109,5 +115,4 @@ DECLARE_DEVICE_TYPE(NES_TC0190FMC_PAL16R4, nes_tc0190fmc_pal16r4_device)
DECLARE_DEVICE_TYPE(NES_X1_005, nes_x1_005_device)
DECLARE_DEVICE_TYPE(NES_X1_017, nes_x1_017_device)
-
#endif // MAME_BUS_NES_TAITO_H
diff --git a/src/devices/bus/nes/tengen.cpp b/src/devices/bus/nes/tengen.cpp
index f6228685796..2304ee9a201 100644
--- a/src/devices/bus/nes/tengen.cpp
+++ b/src/devices/bus/nes/tengen.cpp
@@ -8,12 +8,10 @@
Here we emulate the following PCBs
- * Tengen 800008
* Tengen 800032 [mapper 64]
* Tengen 800037 [mapper 158]
- TODO:
- - emulated the IRQ delay in 800032 (possibly reason of Skull & Crossbones not working?)
+ Note, Tetris' Tengen 800008 [mapper 148] is implemented in sachen.cpp.
***********************************************************************************************************/
@@ -25,39 +23,32 @@
#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"
//-------------------------------------------------
// constructor
//-------------------------------------------------
-DEFINE_DEVICE_TYPE(NES_TENGEN_800008, nes_tengen008_device, "nes_tengen008", "NES Cart Tengen 800008 PCB")
DEFINE_DEVICE_TYPE(NES_TENGEN_800032, nes_tengen032_device, "nes_tengen032", "NES Cart Tengen 800032 PCB")
DEFINE_DEVICE_TYPE(NES_TENGEN_800037, nes_tengen037_device, "nes_tengen037", "NES Cart Tengen 800037 PCB")
-nes_tengen008_device::nes_tengen008_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
- : nes_nrom_device(mconfig, NES_TENGEN_800008, tag, owner, clock)
-{
-}
-
-nes_tengen032_device::nes_tengen032_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock)
- : nes_nrom_device(mconfig, type, tag, owner, clock), m_irq_count(0), m_irq_count_latch(0), m_irq_mode(0), m_irq_reset(0), m_irq_enable(0), m_latch(0), irq_timer(nullptr)
+nes_tengen032_device::nes_tengen032_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, u32 clock)
+ : nes_nrom_device(mconfig, type, tag, owner, clock), m_latch(0), m_irq_count(0), m_irq_count_latch(0), m_irq_mode(0), m_irq_reset(0), m_irq_enable(0), m_irq_pending(0), irq_timer(nullptr)
{
}
-nes_tengen032_device::nes_tengen032_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
+nes_tengen032_device::nes_tengen032_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock)
: nes_tengen032_device(mconfig, NES_TENGEN_800032, tag, owner, clock)
{
}
-nes_tengen037_device::nes_tengen037_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
+nes_tengen037_device::nes_tengen037_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock)
: nes_tengen032_device(mconfig, NES_TENGEN_800037, tag, owner, clock)
{
}
@@ -65,24 +56,12 @@ nes_tengen037_device::nes_tengen037_device(const machine_config &mconfig, const
-void nes_tengen008_device::device_start()
-{
- common_start();
-}
-
-void nes_tengen008_device::pcb_reset()
-{
- m_chr_source = m_vrom_chunks ? CHRROM : CHRRAM;
- prg32(0);
- chr8(0, m_chr_source);
-}
-
void nes_tengen032_device::device_start()
{
common_start();
- irq_timer = timer_alloc(TIMER_IRQ);
- irq_timer->reset();
+ irq_timer = timer_alloc(FUNC(nes_tengen032_device::irq_timer_tick), this);
timer_freq = clocks_to_attotime(4);
+ irq_timer->adjust(attotime::zero, 0, timer_freq);
save_item(NAME(m_mmc_prg_bank));
save_item(NAME(m_mmc_vrom_bank));
@@ -91,24 +70,27 @@ void nes_tengen032_device::device_start()
save_item(NAME(m_irq_mode));
save_item(NAME(m_irq_reset));
save_item(NAME(m_irq_enable));
+ save_item(NAME(m_irq_pending));
save_item(NAME(m_irq_count));
save_item(NAME(m_irq_count_latch));
}
void nes_tengen032_device::pcb_reset()
{
- m_chr_source = m_vrom_chunks ? CHRROM : CHRRAM;
- prg16_89ab(m_prg_chunks - 1);
+ prg16_89ab(0);
prg16_cdef(m_prg_chunks - 1);
chr8(0, m_chr_source);
- memset(m_mmc_prg_bank, 0, sizeof(m_mmc_prg_bank));
- memset(m_mmc_vrom_bank, 0, sizeof(m_mmc_vrom_bank));
+
+ std::fill(std::begin(m_mmc_prg_bank), std::end(m_mmc_prg_bank), 0x00);
+ std::fill(std::begin(m_mmc_vrom_bank), std::end(m_mmc_vrom_bank), 0x00);
m_latch = 0;
m_irq_mode = 0;
m_irq_reset = 0;
m_irq_enable = 0;
- m_irq_count = m_irq_count_latch = 0;
+ m_irq_pending = 0;
+ m_irq_count = 0;
+ m_irq_count_latch = 0xff;
}
@@ -118,27 +100,6 @@ void nes_tengen032_device::pcb_reset()
/*-------------------------------------------------
- Tengen 800008 Board
-
- iNES: mapper 3?
-
- In MESS: Supported.
-
- -------------------------------------------------*/
-
-void nes_tengen008_device::write_h(offs_t offset, uint8_t data)
-{
- LOG_MMC(("tengen008 write_h, offset: %04x, data: %02x\n", offset, data));
-
- // this pcb is subject to bus conflict
- data = account_bus_conflict(offset, data);
-
- prg32(data >> 3);
- chr8(data, CHRROM);
-}
-
-/*-------------------------------------------------
-
Tengen 800032 Board
Games: Klax, Road Runner, Rolling Thunder, Shinobi, Skulls
@@ -150,10 +111,12 @@ void nes_tengen008_device::write_h(offs_t offset, uint8_t data)
iNES: mapper 64
- In MESS: Partially Supported (there should be a small
- delay between the IRQ and its execution, but that is not
- emulated yet: this is possibly the problem with Skulls
- & Crossbones)
+ In MAME: Partially supported.
+
+ TODO: There are issues with IRQ. Skull & Crossbones
+ probably doesn't work because of this? It alone uses
+ the cycle-based IRQ (and it constantly switches
+ between IRQ modes).
-------------------------------------------------*/
@@ -168,33 +131,38 @@ inline void nes_tengen032_device::irq_clock(int blanked)
if (m_irq_reset)
{
m_irq_reset = 0;
- m_irq_count = m_irq_count_latch + 1;
+ m_irq_count = m_irq_count_latch | (m_irq_count_latch ? 1 : 0);
}
else if (!m_irq_count)
m_irq_count = m_irq_count_latch;
+ else
+ m_irq_count--;
- m_irq_count--;
if (m_irq_enable && !blanked && !m_irq_count)
- set_irq_line(ASSERT_LINE);
+ m_irq_pending = 1;
}
// we use the HBLANK IRQ latch from PPU for the scanline based IRQ mode
// and a timer for the cycle based IRQ mode, which both call irq_clock
-void nes_tengen032_device::device_timer(emu_timer &timer, device_timer_id id, int param, void *ptr)
+TIMER_CALLBACK_MEMBER(nes_tengen032_device::irq_timer_tick)
{
- if (id == TIMER_IRQ)
+ if (m_irq_pending)
{
- irq_clock(0);
+ set_irq_line(ASSERT_LINE);
+ m_irq_pending = 0;
}
+
+ if (m_irq_mode)
+ irq_clock(0);
}
-void nes_tengen032_device::hblank_irq(int scanline, int vblank, int blanked)
+void nes_tengen032_device::hblank_irq(int scanline, bool vblank, bool blanked)
{
if (!m_irq_mode) // we are in scanline mode!
{
- if (scanline < ppu2c0x_device::BOTTOM_VISIBLE_SCANLINE)
+ if (scanline <= ppu2c0x_device::BOTTOM_VISIBLE_SCANLINE)
{
irq_clock(blanked);
}
@@ -203,47 +171,40 @@ void nes_tengen032_device::hblank_irq(int scanline, int vblank, int blanked)
void nes_tengen032_device::set_prg()
{
- uint8_t prg_mode = m_latch & 0x40;
-
- prg8_89(m_mmc_prg_bank[prg_mode ? 2: 0]);
- prg8_ab(m_mmc_prg_bank[prg_mode ? 0: 1]);
- prg8_cd(m_mmc_prg_bank[prg_mode ? 1: 2]);
-}
+ u8 prg_flip = (m_latch & 0x40) >> 5;
-void nes_tengen032_device::chr_cb(int start, int bank, int source)
-{
- chr1_x(start, bank, source);
+ prg8_89(m_mmc_prg_bank[0 ^ prg_flip]);
+ prg8_ab(m_mmc_prg_bank[1]);
+ prg8_cd(m_mmc_prg_bank[2 ^ prg_flip]);
}
void nes_tengen032_device::set_chr()
{
- uint8_t chr_page = (m_latch & 0x80) >> 5;
+ u8 chr_flip = (m_latch & 0x80) >> 5;
if (m_latch & 0x20)
{
- chr_cb(0 ^ chr_page, m_mmc_vrom_bank[0], CHRROM);
- chr_cb(1 ^ chr_page, m_mmc_vrom_bank[6], CHRROM);
- chr_cb(2 ^ chr_page, m_mmc_vrom_bank[1], CHRROM);
- chr_cb(3 ^ chr_page, m_mmc_vrom_bank[7], CHRROM);
+ chr1_x(0 ^ chr_flip, m_mmc_vrom_bank[0], CHRROM);
+ chr1_x(1 ^ chr_flip, m_mmc_vrom_bank[6], CHRROM);
+ chr1_x(2 ^ chr_flip, m_mmc_vrom_bank[1], CHRROM);
+ chr1_x(3 ^ chr_flip, m_mmc_vrom_bank[7], CHRROM);
}
else
{
- chr_cb(0 ^ chr_page, m_mmc_vrom_bank[0] & ~0x01, CHRROM);
- chr_cb(1 ^ chr_page, m_mmc_vrom_bank[0] | 0x01, CHRROM);
- chr_cb(2 ^ chr_page, m_mmc_vrom_bank[1] & ~0x01, CHRROM);
- chr_cb(3 ^ chr_page, m_mmc_vrom_bank[1] | 0x01, CHRROM);
+ chr2_x(0 ^ chr_flip, m_mmc_vrom_bank[0] >> 1, CHRROM);
+ chr2_x(2 ^ chr_flip, m_mmc_vrom_bank[1] >> 1, CHRROM);
}
- chr_cb(4 ^ chr_page, m_mmc_vrom_bank[2], CHRROM);
- chr_cb(5 ^ chr_page, m_mmc_vrom_bank[3], CHRROM);
- chr_cb(6 ^ chr_page, m_mmc_vrom_bank[4], CHRROM);
- chr_cb(7 ^ chr_page, m_mmc_vrom_bank[5], CHRROM);
+ chr1_x(4 ^ chr_flip, m_mmc_vrom_bank[2], CHRROM);
+ chr1_x(5 ^ chr_flip, m_mmc_vrom_bank[3], CHRROM);
+ chr1_x(6 ^ chr_flip, m_mmc_vrom_bank[4], CHRROM);
+ chr1_x(7 ^ chr_flip, m_mmc_vrom_bank[5], CHRROM);
}
-void nes_tengen032_device::tengen032_write(offs_t offset, uint8_t data)
+void nes_tengen032_device::write_h(offs_t offset, u8 data)
{
- uint8_t helper, cmd;
- LOG_MMC(("tengen032_write, offset: %04x, data: %02x\n", offset, data));
+ u8 helper, cmd;
+ LOG("tengen032 write_h, offset: %04x, data: %02x\n", offset, data);
switch (offset & 0x6001)
{
@@ -293,17 +254,16 @@ void nes_tengen032_device::tengen032_write(offs_t offset, uint8_t data)
m_irq_count_latch = data;
break;
- case 0x4001: /* $c001 - IRQ scanline latch */
+ case 0x4001: // $c001 - IRQ scanline latch
m_irq_mode = data & 0x01;
if (m_irq_mode)
irq_timer->adjust(attotime::zero, 0, timer_freq);
- else
- irq_timer->adjust(attotime::never);
m_irq_reset = 1;
break;
case 0x6000:
m_irq_enable = 0;
+ m_irq_pending = 0;
set_irq_line(CLEAR_LINE);
break;
@@ -312,7 +272,7 @@ void nes_tengen032_device::tengen032_write(offs_t offset, uint8_t 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;
}
}
@@ -330,46 +290,32 @@ void nes_tengen032_device::tengen032_write(offs_t offset, uint8_t data)
iNES: mapper 158
- In MESS: Supported.
+ In MAME: Supported.
-------------------------------------------------*/
-void nes_tengen037_device::set_mirror()
+void nes_tengen037_device::set_chr()
{
- if (m_latch & 0x80)
- {
- set_nt_page(0, CIRAM, BIT(m_mmc_vrom_bank[2],7), 1);
- set_nt_page(1, CIRAM, BIT(m_mmc_vrom_bank[3],7), 1);
- set_nt_page(2, CIRAM, BIT(m_mmc_vrom_bank[4],7), 1);
- set_nt_page(3, CIRAM, BIT(m_mmc_vrom_bank[5],7), 1);
- }
- else
- {
- set_nt_page(0, CIRAM, BIT(m_mmc_vrom_bank[0],7), 1);
- set_nt_page(1, CIRAM, BIT(m_mmc_vrom_bank[0],7), 1);
- set_nt_page(2, CIRAM, BIT(m_mmc_vrom_bank[1],7), 1);
- set_nt_page(3, CIRAM, BIT(m_mmc_vrom_bank[1],7), 1);
- }
-}
+ nes_tengen032_device::set_chr();
-void nes_tengen037_device::chr_cb( int start, int bank, int source )
-{
- set_mirror(); // we could probably update only for one (e.g. the first) call, to slightly optimize the code
- chr1_x(start, bank, source);
-}
+ // do nametables
+ static constexpr u8 bank[8] = { 0, 0, 1, 1, 2, 3, 4, 5 };
+ int start = (m_latch & 0x80) >> 5;
+ for (int i = 0; i < 4; i++)
+ set_nt_page(i, CIRAM, BIT(m_mmc_vrom_bank[bank[start + i]], 7), 1);
+}
-void nes_tengen037_device::write_h(offs_t offset, uint8_t data)
+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)
{
case 0x2000:
break;
-
default:
- tengen032_write(offset, data);
+ nes_tengen032_device::write_h(offset, data);
break;
}
}
diff --git a/src/devices/bus/nes/tengen.h b/src/devices/bus/nes/tengen.h
index 6d651339f86..f753e5f67bb 100644
--- a/src/devices/bus/nes/tengen.h
+++ b/src/devices/bus/nes/tengen.h
@@ -6,60 +6,42 @@
#include "nxrom.h"
-// ======================> nes_tengen008_device
-
-class nes_tengen008_device : public nes_nrom_device
-{
-public:
- // construction/destruction
- nes_tengen008_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
-
- virtual void write_h(offs_t offset, uint8_t data) override;
-
- virtual void pcb_reset() override;
-
-protected:
- // device-level overrides
- virtual void device_start() override;
-};
-
-
// ======================> nes_tengen032_device
class nes_tengen032_device : public nes_nrom_device
{
public:
// construction/destruction
- nes_tengen032_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
+ nes_tengen032_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock);
- void tengen032_write(offs_t offset, uint8_t data);
- virtual void write_h(offs_t offset, uint8_t data) override { tengen032_write(offset, data); }
+ virtual void write_h(offs_t offset, u8 data) override;
- virtual void hblank_irq(int scanline, int vblank, int blanked) override;
+ virtual void hblank_irq(int scanline, bool vblank, bool blanked) override;
virtual void pcb_reset() override;
protected:
- nes_tengen032_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock);
+ nes_tengen032_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_timer(emu_timer &timer, device_timer_id id, int param, void *ptr) override;
+ virtual void device_start() override ATTR_COLD;
+
+ virtual void set_chr();
+
+ TIMER_CALLBACK_MEMBER(irq_timer_tick);
- virtual void chr_cb(int start, int bank, int source);
+ u8 m_latch;
+ u8 m_mmc_vrom_bank[8];
+private:
void set_prg();
- void set_chr();
void irq_clock(int blanked);
- uint16_t m_irq_count, m_irq_count_latch;
- uint8_t m_irq_mode, m_irq_reset;
- int m_irq_enable;
+ u16 m_irq_count, m_irq_count_latch;
+ u8 m_irq_mode, m_irq_reset;
+ u8 m_irq_enable, m_irq_pending;
- uint8_t m_latch;
- uint8_t m_mmc_prg_bank[3];
- uint8_t m_mmc_vrom_bank[8];
+ u8 m_mmc_prg_bank[3];
- static const device_timer_id TIMER_IRQ = 0;
emu_timer *irq_timer;
attotime timer_freq;
};
@@ -71,19 +53,17 @@ class nes_tengen037_device : public nes_tengen032_device
{
public:
// construction/destruction
- nes_tengen037_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
+ nes_tengen037_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock);
// device-level overrides
- virtual void write_h(offs_t offset, uint8_t data) override;
- virtual void chr_cb(int start, int bank, int source) override;
+ virtual void write_h(offs_t offset, u8 data) override;
protected:
- void set_mirror();
+ virtual void set_chr() override;
};
// device type definition
-DECLARE_DEVICE_TYPE(NES_TENGEN_800008, nes_tengen008_device)
DECLARE_DEVICE_TYPE(NES_TENGEN_800032, nes_tengen032_device)
DECLARE_DEVICE_TYPE(NES_TENGEN_800037, nes_tengen037_device)
diff --git a/src/devices/bus/nes/txc.cpp b/src/devices/bus/nes/txc.cpp
index 4149c6262a3..0fbab1a8f12 100644
--- a/src/devices/bus/nes/txc.cpp
+++ b/src/devices/bus/nes/txc.cpp
@@ -7,10 +7,10 @@
Here we emulate the following PCBs
+ * TXC 01-22000-400 [mapper 36]
* TXC 22111 [mapper 132]
* TXC Du Ma Racing [mapper 172]
* TXC Mahjong Block [mapper 172]
- * TXC Strike Wolf [mapper 36]
* TXC Commandos (and many more) [mapper 241]
TODO:
@@ -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"
//-------------------------------------------------
@@ -40,7 +39,7 @@
DEFINE_DEVICE_TYPE(NES_TXC_22211, nes_txc_22211_device, "nes_txc_22211", "NES Cart TXC 22211 PCB")
DEFINE_DEVICE_TYPE(NES_TXC_DUMARACING, nes_txc_dumarc_device, "nes_txc_dumarc", "NES Cart TXC Du Ma Racing PCB")
DEFINE_DEVICE_TYPE(NES_TXC_MJBLOCK, nes_txc_mjblock_device, "nes_txc_mjblock", "NES Cart TXC Mahjong Block PCB")
-DEFINE_DEVICE_TYPE(NES_TXC_STRIKEW, nes_txc_strikew_device, "nes_txc_strikew", "NES Cart TXC Strike Wolf PCB")
+DEFINE_DEVICE_TYPE(NES_TXC_STRIKEW, nes_txc_strikew_device, "nes_txc_strikew", "NES Cart TXC 01-22000-400 PCB")
DEFINE_DEVICE_TYPE(NES_TXC_COMMANDOS, nes_txc_commandos_device, "nes_txc_comm", "NES Cart TXC Cart Commandos PCB") // and others
@@ -64,7 +63,7 @@ nes_txc_mjblock_device::nes_txc_mjblock_device(const machine_config &mconfig, co
{
}
-nes_txc_strikew_device::nes_txc_strikew_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
+nes_txc_strikew_device::nes_txc_strikew_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock)
: nes_nrom_device(mconfig, NES_TXC_STRIKEW, tag, owner, clock)
{
}
@@ -85,7 +84,6 @@ void nes_txc_22211_device::device_start()
void nes_txc_22211_device::pcb_reset()
{
- m_chr_source = m_vrom_chunks ? CHRROM : CHRRAM;
prg32(0);
chr8(0, m_chr_source);
m_reg[0] = m_reg[1] = m_reg[2] = m_reg[3] = 0;
@@ -94,31 +92,19 @@ void nes_txc_22211_device::pcb_reset()
void nes_txc_strikew_device::device_start()
{
common_start();
+ save_item(NAME(m_reg));
}
void nes_txc_strikew_device::pcb_reset()
{
- m_chr_source = m_vrom_chunks ? CHRROM : CHRRAM;
- prg32(0);
- chr8(0, m_chr_source);
-}
-
-void nes_txc_commandos_device::device_start()
-{
- common_start();
-}
-
-void nes_txc_commandos_device::pcb_reset()
-{
- m_chr_source = m_vrom_chunks ? CHRROM : CHRRAM;
prg32(0);
chr8(0, m_chr_source);
+ m_reg[0] = m_reg[1] = m_reg[2] = m_reg[3] = 0;
}
-
/*-------------------------------------------------
mapper specific handlers
-------------------------------------------------*/
@@ -135,13 +121,13 @@ void nes_txc_commandos_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;
@@ -149,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;
@@ -159,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);
@@ -176,16 +162,16 @@ 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((((data ^ m_reg[2]) >> 3) & 0x02) | (((data ^ m_reg[2]) >> 5) & 0x01), CHRROM);
+ chr8(bitswap<2>(data ^ m_reg[2], 4, 5), CHRROM);
}
/*-------------------------------------------------
@@ -199,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,29 +201,59 @@ uint8_t nes_txc_mjblock_device::read_l(offs_t offset)
/*-------------------------------------------------
- Bootleg Board 'Strike Wolf' by TXC
+ TXC 01-22000-400 Board
- Games: Strike Wolf and Policeman
+ Games: F-15 City War, Policeman, Puzzle, Strike Wolf,
+ Venice Beach Volley
iNES: mapper 36
- In MESS: Supported (Policeman requires no bus conflict
- though, or it has glitches)
+ In MAME: Supported.
-------------------------------------------------*/
-void nes_txc_strikew_device::write_h(offs_t offset, uint8_t data)
+u8 nes_txc_strikew_device::read_l(offs_t offset)
{
- LOG_MMC(("TXC Strike Wolf write_h, offset: %04x, data: %02x\n", offset, data));
+ LOG("TXC 01-22000-400 read_l, offset: %04x\n", offset);
+
+ offset += 0x100;
+ if (offset & 0x100)
+ return (get_open_bus() & 0xcf) | m_reg[0] << 4;
- // this pcb is subject to bus conflict
- data = account_bus_conflict(offset, data);
+ return get_open_bus();
+}
+
+void nes_txc_strikew_device::write_l(offs_t offset, u8 data)
+{
+ LOG("TXC 01-22000-400 write_l, offset: %04x, data: %02x\n", offset, data);
- if ((offset >= 0x400) && (offset < 0x7fff))
+ offset += 0x100;
+ switch (offset & 0x103)
{
- prg32(data >> 4);
- chr8(data & 0x0f, CHRROM);
+ case 0x100:
+ if (m_reg[3] & 1)
+ m_reg[0] = (m_reg[0] + 1) & 0x03;
+ else if (m_reg[1] & 1)
+ m_reg[0] = m_reg[2] ^ 0x03;
+ else
+ m_reg[0] = m_reg[2];
+ break;
+ case 0x101:
+ case 0x102:
+ case 0x103:
+ m_reg[offset & 0x03] = BIT(data, 4, 2);
+ break;
}
+
+ if (offset & 0x200)
+ chr8(data, CHRROM);
+}
+
+void nes_txc_strikew_device::write_h(offs_t offset, u8 data)
+{
+ LOG("TXC 01-22000-400 write_h, offset: %04x, data: %02x\n", offset, data);
+
+ prg32(m_reg[0]);
}
/*-------------------------------------------------
@@ -252,7 +268,7 @@ void nes_txc_strikew_device::write_h(offs_t offset, uint8_t data)
iNES: mapper 241
- In MESS: Supported.
+ In MAME: Supported.
-------------------------------------------------*/
@@ -263,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/txc.h b/src/devices/bus/nes/txc.h
index 9ad5e2807dc..a250dadcb30 100644
--- a/src/devices/bus/nes/txc.h
+++ b/src/devices/bus/nes/txc.h
@@ -26,7 +26,7 @@ protected:
nes_txc_22211_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_start() override ATTR_COLD;
uint8_t m_reg[4];
};
@@ -40,7 +40,6 @@ public:
// construction/destruction
nes_txc_dumarc_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
- // device-level overrides
virtual void write_h(offs_t offset, uint8_t data) override;
};
@@ -53,7 +52,6 @@ public:
// construction/destruction
nes_txc_mjblock_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
- // device-level overrides
virtual uint8_t read_l(offs_t offset) override;
};
@@ -64,15 +62,19 @@ class nes_txc_strikew_device : public nes_nrom_device
{
public:
// construction/destruction
- nes_txc_strikew_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
+ nes_txc_strikew_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock);
- virtual void write_h(offs_t offset, uint8_t data) override;
+ virtual u8 read_l(offs_t offset) override;
+ virtual void write_l(offs_t offset, u8 data) override;
+ virtual void write_h(offs_t offset, u8 data) override;
virtual void pcb_reset() override;
protected:
// device-level overrides
- virtual void device_start() override;
+ virtual void device_start() override ATTR_COLD;
+
+ u8 m_reg[4];
};
@@ -86,12 +88,6 @@ public:
virtual uint8_t read_l(offs_t offset) override;
virtual void write_h(offs_t offset, uint8_t data) override;
-
- virtual void pcb_reset() override;
-
-protected:
- // device-level overrides
- virtual void device_start() override;
};
diff --git a/src/devices/bus/nes/vrc_clones.cpp b/src/devices/bus/nes/vrc_clones.cpp
new file mode 100644
index 00000000000..ba358cb164f
--- /dev/null
+++ b/src/devices/bus/nes/vrc_clones.cpp
@@ -0,0 +1,861 @@
+// license:BSD-3-Clause
+// copyright-holders:kmg
+/***********************************************************************************************************
+
+
+ NES/Famicom cartridge emulation for Konami VRC clone PCBs
+
+
+ Here we emulate several pirate PCBs based on VRC2/4 boards
+
+ ***********************************************************************************************************/
+
+
+#include "emu.h"
+#include "vrc_clones.h"
+
+#define LOG_HIFREQ (1U << 1)
+
+#ifdef NES_PCB_DEBUG
+#define VERBOSE (LOG_GENERAL)
+#else
+#define VERBOSE (0)
+#endif
+#include "logmacro.h"
+
+
+//-------------------------------------------------
+// constructor
+//-------------------------------------------------
+
+DEFINE_DEVICE_TYPE(NES_2YUDB, nes_2yudb_device, "nes_2yudb", "NES Cart Yu Yu Hakusho - Dragon Ball Z 2 in 1 PCB")
+DEFINE_DEVICE_TYPE(NES_900218, nes_900218_device, "nes_900218", "NES Cart 900218 PCB")
+DEFINE_DEVICE_TYPE(NES_AX40G, nes_ax40g_device, "nes_ax40g", "NES Cart UNL-AX-40G PCB")
+DEFINE_DEVICE_TYPE(NES_AX5705, nes_ax5705_device, "nes_ax5705", "NES Cart AX5705 PCB")
+DEFINE_DEVICE_TYPE(NES_BMC_830506C, nes_bmc_830506c_device, "nes_bmc_830506c", "NES Cart BMC 830506C PCB")
+DEFINE_DEVICE_TYPE(NES_BMC_831128C, nes_bmc_831128c_device, "nes_bmc_831128c", "NES Cart BMC 831128C PCB")
+DEFINE_DEVICE_TYPE(NES_BMC_KL06, nes_bmc_kl06_device, "nes_bmc_kl06", "NES Cart BMC KL-06 PCB")
+DEFINE_DEVICE_TYPE(NES_CITYFIGHT, nes_cityfight_device, "nes_cityfight", "NES Cart City Fighter PCB")
+DEFINE_DEVICE_TYPE(NES_SHUIGUAN, nes_shuiguan_device, "nes_shuiguan", "NES Cart Shui Guan Pipe Pirate PCB")
+DEFINE_DEVICE_TYPE(NES_T230, nes_t230_device, "nes_t230", "NES Cart T-230 PCB")
+DEFINE_DEVICE_TYPE(NES_TF1201, nes_tf1201_device, "nes_tf1201", "NES Cart UNL-TF1201 PCB")
+DEFINE_DEVICE_TYPE(NES_TH21311, nes_th21311_device, "nes_th21311", "NES Cart UNL-TH2131-1 PCB")
+DEFINE_DEVICE_TYPE(NES_WAIXING_SGZ, nes_waixing_sgz_device, "nes_waixing_sgz", "NES Cart Waixing San Guo Zhi PCB")
+DEFINE_DEVICE_TYPE(NES_HENGG_SHJY3, nes_hengg_shjy3_device, "nes_hengg_shjy3", "NES Cart Henggedianzi Shen Hua Jian Yun III PCB")
+
+
+nes_2yudb_device::nes_2yudb_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock)
+ : nes_konami_vrc4_device(mconfig, NES_2YUDB, tag, owner, clock), m_outer(0)
+{
+}
+
+nes_900218_device::nes_900218_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock)
+ : nes_konami_vrc2_device(mconfig, NES_900218, tag, owner, clock), m_irq_count(0), m_irq_enable(0), irq_timer(nullptr)
+{
+}
+
+nes_ax40g_device::nes_ax40g_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock)
+ : nes_konami_vrc2_device(mconfig, NES_AX40G, tag, owner, clock)
+{
+}
+
+nes_ax5705_device::nes_ax5705_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock)
+ : nes_konami_vrc4_device(mconfig, NES_AX5705, tag, owner, clock)
+{
+}
+
+nes_bmc_830506c_device::nes_bmc_830506c_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock)
+ : nes_konami_vrc4_device(mconfig, NES_BMC_830506C, tag, owner, clock), m_outer(0)
+{
+}
+
+nes_bmc_831128c_device::nes_bmc_831128c_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock)
+ : nes_konami_vrc4_device(mconfig, NES_BMC_831128C, tag, owner, clock), m_reg(0)
+{
+}
+
+nes_bmc_kl06_device::nes_bmc_kl06_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock)
+ : nes_konami_vrc4_device(mconfig, NES_BMC_KL06, tag, owner, clock), m_reg(0)
+{
+}
+
+nes_cityfight_device::nes_cityfight_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock)
+ : nes_konami_vrc4_device(mconfig, NES_CITYFIGHT, tag, owner, clock)
+{
+}
+
+nes_shuiguan_device::nes_shuiguan_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock)
+ : nes_konami_vrc4_device(mconfig, NES_SHUIGUAN, tag, owner, clock)
+{
+}
+
+nes_t230_device::nes_t230_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock)
+ : nes_konami_vrc4_device(mconfig, NES_T230, tag, owner, clock)
+{
+}
+
+nes_tf1201_device::nes_tf1201_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock)
+ : nes_konami_vrc4_device(mconfig, NES_TF1201, tag, owner, clock)
+{
+}
+
+nes_th21311_device::nes_th21311_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock)
+ : nes_konami_vrc2_device(mconfig, NES_TH21311, tag, owner, clock), m_irq_count(0), m_irq_enable(0), irq_timer(nullptr)
+{
+}
+
+nes_waixing_sgz_device::nes_waixing_sgz_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, u32 clock, u8 chr_match)
+ : nes_konami_vrc4_device(mconfig, type, tag, owner, clock), m_chr_match(chr_match)
+{
+}
+
+nes_waixing_sgz_device::nes_waixing_sgz_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock)
+ : nes_waixing_sgz_device(mconfig, NES_WAIXING_SGZ, tag, owner, clock, 0x06)
+{
+}
+
+nes_hengg_shjy3_device::nes_hengg_shjy3_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock)
+ : nes_waixing_sgz_device(mconfig, NES_HENGG_SHJY3, tag, owner, clock, 0x04)
+{
+}
+
+
+
+void nes_2yudb_device::device_start()
+{
+ nes_konami_vrc4_device::device_start();
+ save_item(NAME(m_outer));
+
+ // VRC4 pins 3 and 4
+ m_vrc_ls_prg_a = 3; // A3
+ m_vrc_ls_prg_b = 2; // A2
+}
+
+void nes_2yudb_device::pcb_reset()
+{
+ m_outer = 0;
+ nes_konami_vrc4_device::pcb_reset();
+}
+
+void nes_900218_device::device_start()
+{
+ nes_konami_vrc2_device::device_start();
+ irq_timer = timer_alloc(FUNC(nes_900218_device::irq_timer_tick), this);
+ irq_timer->adjust(attotime::zero, 0, clocks_to_attotime(1));
+
+ save_item(NAME(m_irq_enable));
+ save_item(NAME(m_irq_count));
+
+ // VRC2 pins 3 and 4
+ m_vrc_ls_prg_a = 1; // A1
+ m_vrc_ls_prg_b = 0; // A0
+}
+
+void nes_900218_device::pcb_reset()
+{
+ nes_konami_vrc2_device::pcb_reset();
+ m_irq_enable = 0;
+ m_irq_count = 0;
+}
+
+void nes_ax40g_device::device_start()
+{
+ nes_konami_vrc2_device::device_start();
+
+ // VRC2 pins 3 and 4
+ m_vrc_ls_prg_a = 1; // A1
+ m_vrc_ls_prg_b = 0; // A0
+}
+
+void nes_ax5705_device::device_start()
+{
+ nes_konami_vrc4_device::device_start();
+
+ // VRC4 pins 3 and 4
+ m_vrc_ls_prg_a = 1; // A1
+ m_vrc_ls_prg_b = 0; // A0
+}
+
+void nes_bmc_830506c_device::device_start()
+{
+ nes_konami_vrc4_device::device_start();
+ save_item(NAME(m_outer));
+
+ // VRC4 pins 3 and 4
+ m_vrc_ls_prg_a = 1; // A1
+ m_vrc_ls_prg_b = 0; // A0
+}
+
+void nes_bmc_830506c_device::pcb_reset()
+{
+ m_outer = 0;
+ nes_konami_vrc4_device::pcb_reset();
+}
+
+void nes_bmc_831128c_device::device_start()
+{
+ nes_konami_vrc4_device::device_start();
+ save_item(NAME(m_reg));
+}
+
+void nes_bmc_831128c_device::pcb_reset()
+{
+ nes_konami_vrc4_device::pcb_reset();
+
+ m_reg = 0;
+ prg32((m_prg_chunks >> 1) - 1);
+}
+
+void nes_bmc_kl06_device::device_start()
+{
+ nes_konami_vrc4_device::device_start();
+ save_item(NAME(m_reg));
+
+ // VRC4 pins 3 and 4
+ m_vrc_ls_prg_a = 3; // A1
+ m_vrc_ls_prg_b = 2; // A0
+}
+
+void nes_bmc_kl06_device::pcb_reset()
+{
+ m_reg = 0;
+ nes_konami_vrc4_device::pcb_reset();
+}
+
+void nes_cityfight_device::device_start()
+{
+ nes_konami_vrc4_device::device_start();
+
+ // VRC4 pins 3 and 4
+ m_vrc_ls_prg_a = 3; // A3
+ m_vrc_ls_prg_b = 2; // A2
+}
+
+void nes_shuiguan_device::device_start()
+{
+ nes_konami_vrc4_device::device_start();
+ save_item(NAME(m_reg));
+
+ // VRC4 pins 3 and 4
+ m_vrc_ls_prg_a = 3; // A3
+ m_vrc_ls_prg_b = 2; // A2
+}
+
+void nes_shuiguan_device::pcb_reset()
+{
+ nes_konami_vrc4_device::pcb_reset();
+ m_reg = 0;
+}
+
+void nes_t230_device::device_start()
+{
+ nes_konami_vrc4_device::device_start();
+
+ // VRC4 pins 3 and 4
+ m_vrc_ls_prg_a = 3; // A3
+ m_vrc_ls_prg_b = 2; // A2
+}
+
+void nes_tf1201_device::device_start()
+{
+ nes_konami_vrc4_device::device_start();
+
+ // VRC4 pins 3 and 4
+ m_vrc_ls_prg_a = 0; // A0
+ m_vrc_ls_prg_b = 1; // A1
+}
+
+void nes_th21311_device::device_start()
+{
+ nes_konami_vrc2_device::device_start();
+ irq_timer = timer_alloc(FUNC(nes_th21311_device::irq_timer_tick), this);
+ irq_timer->adjust(attotime::zero, 0, clocks_to_attotime(1));
+
+ save_item(NAME(m_irq_enable));
+ save_item(NAME(m_irq_count));
+ save_item(NAME(m_irq_latch));
+
+ // VRC2 pins 3 and 4
+ m_vrc_ls_prg_a = 1; // A1
+ m_vrc_ls_prg_b = 0; // A0
+}
+
+void nes_th21311_device::pcb_reset()
+{
+ nes_konami_vrc2_device::pcb_reset();
+ m_irq_enable = 0;
+ m_irq_count = 0;
+ m_irq_latch = 0;
+}
+
+void nes_waixing_sgz_device::device_start()
+{
+ nes_konami_vrc4_device::device_start();
+ save_item(NAME(m_chr_mask));
+ save_item(NAME(m_chr_match));
+
+ m_chr_mask = 0xfe;
+
+ // VRC4 pins 3 and 4
+ m_vrc_ls_prg_a = 3; // A3
+ m_vrc_ls_prg_b = 2; // A2
+}
+
+
+
+/*-------------------------------------------------
+ mapper specific handlers
+ -------------------------------------------------*/
+
+/*-------------------------------------------------
+
+ Board BTL-900218
+
+ Games: Lord of King (Astyanax pirate)
+
+ This board has a VRC2 clone that has been altered to
+ add a simple IRQ counter fixed to 1024 CPU cycles.
+
+ NES 2.0: mapper 524
+
+ In MAME: Supported.
+
+ -------------------------------------------------*/
+
+TIMER_CALLBACK_MEMBER(nes_900218_device::irq_timer_tick)
+{
+ if (m_irq_enable)
+ {
+ m_irq_count++;
+ set_irq_line(BIT(m_irq_count, 10) ? ASSERT_LINE : CLEAR_LINE);
+ }
+}
+
+void nes_900218_device::write_h(offs_t offset, u8 data)
+{
+ LOG("900218 write_h, offset: %04x, data: %02x\n", offset, data);
+
+ if ((offset & 0x7000) == 0x7000)
+ {
+ switch (offset & 0xc)
+ {
+ case 0x8:
+ m_irq_enable = 1;
+ break;
+ case 0xc:
+ m_irq_enable = 0;
+ m_irq_count = 0;
+ set_irq_line(CLEAR_LINE);
+ break;
+ }
+ }
+ else
+ nes_konami_vrc2_device::write_h(offset, data);
+}
+
+/*-------------------------------------------------
+
+ Board UNL-AX-40G
+
+ Games: Fudou Myouou Den pirate
+
+ VRC2 clone that supports extra single screen mirroring
+ modes seen in the original Taito X1-005 board.
+
+ NES 2.0: mapper 527
+
+ In MAME: Supported.
+
+ -------------------------------------------------*/
+
+void nes_ax40g_device::write_h(offs_t offset, u8 data)
+{
+ LOG("ax40g write_h, offset: %04x, data: %02x\n", offset, data);
+
+ nes_konami_vrc2_device::write_h(offset, data);
+
+ if ((offset & 0x7001) == 0x3001)
+ {
+ set_nt_page(offset & 0x02, CIRAM, BIT(data, 3), 1);
+ set_nt_page((offset & 0x02) + 1, CIRAM, BIT(data, 3), 1);
+ }
+}
+
+/*-------------------------------------------------
+
+ Board UNL-AX5705
+
+ Games: Super Mario Bros. Pocker Mali (Crayon Shin-chan pirate hack)
+
+ VRC4 clone with a few PRG/CHR address lines swapped.
+
+ NES 2.0: mapper 530
+
+ In MAME: Supported.
+
+ -------------------------------------------------*/
+
+void nes_ax5705_device::write_h(offs_t offset, u8 data)
+{
+ LOG("ax5705 write_h, offset: %04x, data: %02x\n", offset, data);
+
+ offset = (offset & ~0x1000) | BIT(offset, 3) << 12;
+ switch (offset & 0x7001)
+ {
+ case 0x0000: case 0x0001: case 0x2000: case 0x2001:
+ data = bitswap<4>(data, 1, 2, 3, 0);
+ break;
+ case 0x3001: case 0x4001: case 0x5001: case 0x6001:
+ data = bitswap<3>(data, 1, 2, 0);
+ break;
+ }
+ nes_konami_vrc4_device::write_h(offset, data);
+}
+
+/*-------------------------------------------------
+
+ UNL-CITYFIGHT
+
+ Games: City Fighter IV
+
+ VRC4 clone with simple 32K PRG banking (it's a minimal
+ hack of Master Fighter II banking). More interestingly
+ it adds a 4-bit PCM audio register, not emulated yet.
+
+ NES 2.0: mapper 266
+
+ In MAME: Partially supported.
+
+ -------------------------------------------------*/
+
+void nes_cityfight_device::write_h(offs_t offset, u8 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)
+ {
+ case 0x0000:
+ case 0x0800:
+ break; // PRG banking at $8000 ignored
+ case 0x1000:
+ prg32(BIT(data, 2, 2));
+ if (!(offset & 3)) // $9000 is also VRC4 mirroring
+ nes_konami_vrc4_device::write_h(offset, data);
+ break;
+ case 0x1800:
+ 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);
+ break;
+ }
+}
+
+/*-------------------------------------------------
+
+ BTL-SHUIGUANPIPE
+
+ Games: Shui Guan Pipe (Gimmick Pirate)
+
+ VRC4 clone that differs in its PRG banking only.
+
+ iNES: mapper 183
+
+ In MAME: Supported.
+
+ -------------------------------------------------*/
+
+u8 nes_shuiguan_device::read_m(offs_t 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("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("shuiguan write_h, offset: %04x, data: %02x\n", offset, data);
+
+ switch (offset & 0x7800)
+ {
+ case 0x0000:
+ case 0x1000:
+ break; // writes to $8000 and $9000 ignored
+ case 0x0800:
+ prg8_89(data);
+ break;
+ case 0x2000:
+ prg8_cd(data);
+ break;
+ case 0x2800:
+ prg8_ab(data);
+ break;
+ default:
+ nes_konami_vrc4_device::write_h(offset, data);
+ break;
+ }
+}
+
+/*-------------------------------------------------
+
+ Board UNL-T-230
+
+ Games: Dragon Ball Z IV (Unl)
+
+ VRC4 clone that uses CHRRAM instead of CHRROM and
+ has nonstandard PRG banking.
+
+ NES 2.0: mapper 529
+
+ In MAME: Supported.
+
+ TODO: This cart and its appearance on the 2yudb set
+ have IRQ timing issues that cause a bouncing status
+ bar in fights. Other emulators also have issues
+ on the split line so perhaps some noise is expected?
+
+ -------------------------------------------------*/
+
+void nes_t230_device::write_h(offs_t offset, u8 data)
+{
+ LOG("t230 write_h, offset: %04x, data: %02x\n", offset, data);
+
+ switch (offset & 0x7000)
+ {
+ case 0x0000:
+ break; // PRG banking at $8000 ignored
+ case 0x2000:
+ prg16_89ab(data);
+ break;
+ default:
+ nes_konami_vrc4_device::write_h(offset, data);
+ break;
+ }
+}
+
+/*-------------------------------------------------
+
+ UNL-TF1201
+
+ Games: Leathal Weapon (Leathal Enforcers clone)
+
+ VRC4 clone where the only known difference is in the
+ IRQ behavior. This clone does not copy the IRQ reload
+ bit to the enable bit on writes to IRQ acknowledge.
+
+ NES 2.0: mapper 298
+
+ In MAME: Supported.
+
+ -------------------------------------------------*/
+
+void nes_tf1201_device::irq_ack_w()
+{
+ set_irq_line(CLEAR_LINE);
+}
+
+/*-------------------------------------------------
+
+ Board UNL-TH2131-1
+
+ Games: Batman pirate (Dynacon)
+
+ VRC2 clone with an added IRQ timer. A selectable 4-bit
+ latch controls the duration as it is decremented
+ relative to another internal 12-bit counter.
+
+ NES 2.0: mapper 308
+
+ In MAME: Supported.
+
+ -------------------------------------------------*/
+
+TIMER_CALLBACK_MEMBER(nes_th21311_device::irq_timer_tick)
+{
+ if (m_irq_enable)
+ {
+ m_irq_count = (m_irq_count + 1) & 0xfff; // 12-bit counter
+ if (m_irq_count == 0x800)
+ m_irq_latch--;
+ if (!m_irq_latch && m_irq_count < 0x800)
+ set_irq_line(ASSERT_LINE);
+ }
+}
+
+void nes_th21311_device::write_h(offs_t offset, u8 data)
+{
+ LOG("th21311 write_h, offset: %04x, data: %02x\n", offset, data);
+
+ if ((offset & 0x7000) == 0x7000)
+ {
+ switch (offset & 3)
+ {
+ case 0:
+ m_irq_enable = 0;
+ m_irq_count = 0;
+ set_irq_line(CLEAR_LINE);
+ break;
+ case 1:
+ m_irq_enable = 1;
+ break;
+ case 3:
+ m_irq_latch = data >> 4;
+ break;
+ }
+ }
+ else
+ nes_konami_vrc2_device::write_h(offset, data);
+}
+
+/*-------------------------------------------------
+
+ Waixing San Guo Zhi Board, Henggedianzi UNL-SHJY3
+
+ Games: San Guo Zhi (mapper 252), several Chinese
+ hacks of Dragon Ball games (mapper 253)
+
+ VRC4 clones that substitute 2K of CHRRAM in place for
+ two of the standard 1K CHRROM pages. Unusually this is
+ done by a GAL looking at certain address bits of the
+ PPU's address space, as the PPU writes pattern tables.
+
+ iNES: mapper 252 and mapper 253
+
+ In MAME: Supported.
+
+ TODO: Why does Sanguozhi flicker every second or two?
+
+ -------------------------------------------------*/
+
+void nes_waixing_sgz_device::write_h(offs_t offset, u8 data)
+{
+ LOG("waixing_sgz write_h, offset: %04x, data: %02x\n", offset, data);
+
+ nes_konami_vrc4_device::write_h(offset, data);
+
+ for (int bank = 0; bank < 8; bank++)
+ if ((m_mmc_vrom_bank[bank] & m_chr_mask) == m_chr_match)
+ chr1_x(bank, m_mmc_vrom_bank[bank] & 1, CHRRAM);
+}
+
+void nes_waixing_sgz_device::chr_w(offs_t offset, u8 data)
+{
+ device_nes_cart_interface::chr_w(offset, data);
+
+ switch (m_mmc_vrom_bank[BIT(offset, 10, 3)])
+ {
+ case 0x88:
+ m_chr_mask = 0xfc;
+ m_chr_match = 0x4c;
+ break;
+ case 0xc2:
+ m_chr_mask = 0xfe;
+ m_chr_match = 0x7c;
+ break;
+ case 0xc8:
+ m_chr_mask = 0xfe;
+ m_chr_match = 0x04;
+ break;
+ }
+}
+
+/*-------------------------------------------------
+
+ MULTIGAME CARTS BASED ON VRC
+
+ -------------------------------------------------*/
+
+/*-------------------------------------------------
+
+ Board BTL-2YUDB
+
+ Games: 2 in 1 Datach Yu Yu Hakusho + Dragon Ball Z
+
+ VRC4 clone that uses CHRRAM instead of the usual
+ CHRROM and has a bit for selecting the outer PRG bank.
+
+ NES 2.0: mapper 520
+
+ In MAME: Supported.
+
+ -------------------------------------------------*/
+
+void nes_2yudb_device::write_h(offs_t offset, u8 data)
+{
+ LOG("2yudb write_h, offset: %04x, data: %02x\n", offset, data);
+
+ nes_konami_vrc4_device::write_h(offset, data);
+
+ if (offset >= 0x3000 && offset < 0x7000 && !BIT(offset, m_vrc_ls_prg_b))
+ {
+ u8 bank = ((offset >> 12) - 3) * 2 + BIT(offset, m_vrc_ls_prg_a);
+ m_outer = (m_mmc_vrom_bank[bank] & 0x08) << 2;
+ set_prg();
+ }
+}
+
+/*-------------------------------------------------
+
+ Board BMC-830506C
+
+ Games: 1995 Super HiK 4 in 1 (JY-005)
+
+ VRC4 clone with banking for multicart menu.
+
+ NES 2.0: mapper 362
+
+ In MAME: Supported.
+
+ -------------------------------------------------*/
+
+void nes_bmc_830506c_device::irq_ack_w()
+{
+ set_irq_line(CLEAR_LINE);
+}
+
+void nes_bmc_830506c_device::write_h(offs_t offset, u8 data)
+{
+ LOG("bmc_830506c write_h, offset: %04x, data: %02x\n", offset, data);
+
+ nes_konami_vrc4_device::write_h(offset, data);
+
+ if (offset >= 0x3000 && offset < 0x7000 && BIT(offset, m_vrc_ls_prg_b))
+ {
+ u8 bank = ((offset >> 12) - 3) * 2 + BIT(offset, m_vrc_ls_prg_a);
+ m_outer = (m_mmc_vrom_bank[bank] & 0x180) >> 3;
+ set_prg();
+ }
+}
+
+/*-------------------------------------------------
+
+ Board BMC-831128C
+
+ Games: 1995 New Series Super 2 in 1
+
+ Weird clone that seems to be part Konami VRC4 (IRQ),
+ and part Sunsoft FME-7 (banking/mirroring).
+
+ NES 2.0: mapper 528
+
+ In MAME: Supported.
+
+ -------------------------------------------------*/
+
+
+u8 nes_bmc_831128c_device::read_m(offs_t offset)
+{
+ u8 data = 0;
+ if (m_reg == 1)
+ data = device_nes_cart_interface::read_m(offset);
+ else
+ 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)
+{
+ 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);
+}
+
+void nes_bmc_831128c_device::write_h(offs_t offset, u8 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
+ return;
+
+ int outer = BIT(offset, 14) << 4;
+ prg16_cdef(outer ? m_prg_chunks - 1 : 7);
+
+ u8 reg = offset & 0x0f;
+ switch (reg)
+ {
+ case 0x0: case 0x1: case 0x2: case 0x3:
+ case 0x4: case 0x5: case 0x6: case 0x7:
+ chr1_x(reg, (outer << 4) | data, m_chr_source);
+ break;
+ case 0x8:
+ m_reg = data;
+ break;
+ case 0x9:
+ case 0xa:
+ prg8_x(reg - 9, outer + (data & (outer | 0x0f)));
+ break;
+ // case 0xb: do nothing
+ case 0xc:
+ set_mirror(data);
+ break;
+ case 0xd:
+ irq_ctrl_w(data);
+ break;
+ case 0xe:
+ irq_ack_w();
+ break;
+ case 0xf:
+ m_irq_count_latch = data;
+ break;
+ }
+}
+
+/*-------------------------------------------------
+
+ Board BMC-KL-06
+
+ Games: 1993 New 860 in 1 Over-Valued Golden Version Games
+
+ VRC4 clone with banking for multicart menu.
+
+ NES 2.0: mapper 447
+
+ In MAME: Supported.
+
+ TODO: There must be jumper settings since this is
+ showing up as a 1650 in 1.
+
+ -------------------------------------------------*/
+
+void nes_bmc_kl06_device::set_prg()
+{
+ u8 outer = (m_reg & 0x03) << 4;
+
+ if (BIT(m_reg, 2))
+ {
+ u8 bank_lo = outer | m_mmc_prg_bank[0];
+ u8 bank_hi = outer | m_mmc_prg_bank[1];
+ u8 mode = ~m_reg & 0x02;
+ prg8_89(bank_lo & ~mode);
+ prg8_ab(bank_hi & ~mode);
+ prg8_cd(bank_lo | mode);
+ prg8_ef(bank_hi | mode);
+ }
+ else
+ nes_konami_vrc4_device::set_prg(outer, 0x0f);
+}
+
+void nes_bmc_kl06_device::write_m(offs_t offset, u8 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);
+
+ if (!(m_reg & 1)) // lock bit
+ {
+ m_reg = offset;
+ set_prg();
+ set_chr();
+ }
+}
diff --git a/src/devices/bus/nes/vrc_clones.h b/src/devices/bus/nes/vrc_clones.h
new file mode 100644
index 00000000000..438ab5ef51a
--- /dev/null
+++ b/src/devices/bus/nes/vrc_clones.h
@@ -0,0 +1,309 @@
+// license:BSD-3-Clause
+// copyright-holders:kmg
+#ifndef MAME_BUS_NES_VRC_CLONES_H
+#define MAME_BUS_NES_VRC_CLONES_H
+
+#pragma once
+
+#include "konami.h"
+
+
+// ======================> nes_2yudb_device
+
+class nes_2yudb_device : public nes_konami_vrc4_device
+{
+public:
+ // construction/destruction
+ nes_2yudb_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock);
+
+ virtual void write_h(offs_t offset, u8 data) override;
+
+ virtual void pcb_reset() override;
+
+protected:
+ // device-level overrides
+ virtual void device_start() override ATTR_COLD;
+
+ virtual void set_prg() override { nes_konami_vrc4_device::set_prg(m_outer, 0x1f); }
+
+private:
+ u8 m_outer;
+};
+
+
+// ======================> nes_900218_device
+
+class nes_900218_device : public nes_konami_vrc2_device
+{
+public:
+ // construction/destruction
+ nes_900218_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock);
+
+ virtual void write_h(offs_t offset, u8 data) override;
+
+ virtual void pcb_reset() override;
+
+protected:
+ // device-level overrides
+ virtual void device_start() override ATTR_COLD;
+
+ TIMER_CALLBACK_MEMBER(irq_timer_tick);
+
+private:
+ u16 m_irq_count;
+ int m_irq_enable;
+
+ emu_timer *irq_timer;
+};
+
+
+// ======================> nes_ax40g_device
+
+class nes_ax40g_device : public nes_konami_vrc2_device
+{
+public:
+ // construction/destruction
+ nes_ax40g_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock);
+
+ virtual void write_h(offs_t offset, u8 data) override;
+
+protected:
+ // device-level overrides
+ virtual void device_start() override ATTR_COLD;
+};
+
+
+// ======================> nes_ax5705_device
+
+class nes_ax5705_device : public nes_konami_vrc4_device
+{
+public:
+ // construction/destruction
+ nes_ax5705_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock);
+
+ virtual void write_h(offs_t offset, u8 data) override;
+
+protected:
+ // device-level overrides
+ virtual void device_start() override ATTR_COLD;
+};
+
+
+// ======================> nes_bmc_830506c_device
+
+class nes_bmc_830506c_device : public nes_konami_vrc4_device
+{
+public:
+ // construction/destruction
+ nes_bmc_830506c_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock);
+
+ virtual void write_h(offs_t offset, u8 data) override;
+
+ virtual void pcb_reset() override;
+
+protected:
+ // device-level overrides
+ virtual void device_start() override ATTR_COLD;
+
+ virtual void irq_ack_w() override;
+ virtual void set_prg() override { nes_konami_vrc4_device::set_prg(m_outer, 0x0f); }
+
+private:
+ u8 m_outer;
+};
+
+
+// ======================> nes_bmc_831128c_device
+
+class nes_bmc_831128c_device : public nes_konami_vrc4_device
+{
+public:
+ // construction/destruction
+ nes_bmc_831128c_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock);
+
+ virtual u8 read_m(offs_t offset) override;
+ virtual void write_m(offs_t offset, u8 data) override;
+ virtual void write_h(offs_t offset, u8 data) override;
+
+ virtual void pcb_reset() override;
+
+protected:
+ // device-level overrides
+ virtual void device_start() override ATTR_COLD;
+
+private:
+ u8 m_reg;
+};
+
+
+// ======================> nes_bmc_kl06_device
+
+class nes_bmc_kl06_device : public nes_konami_vrc4_device
+{
+public:
+ // construction/destruction
+ nes_bmc_kl06_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock);
+
+ virtual void write_m(offs_t offset, u8 data) override;
+
+ virtual void pcb_reset() override;
+
+protected:
+ // device-level overrides
+ virtual void device_start() override ATTR_COLD;
+
+ virtual void set_prg() override;
+ virtual void set_chr() override { nes_konami_vrc4_device::set_chr((m_reg & 0x03) << 7, 0x7f); }
+
+private:
+ u8 m_reg;
+};
+
+
+// ======================> nes_cityfight_device
+
+class nes_cityfight_device : public nes_konami_vrc4_device
+{
+public:
+ // construction/destruction
+ nes_cityfight_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock);
+
+ virtual void write_h(offs_t offset, u8 data) override;
+
+protected:
+ // device-level overrides
+ virtual void device_start() override ATTR_COLD;
+};
+
+
+// ======================> nes_shuiguan_device
+
+class nes_shuiguan_device : public nes_konami_vrc4_device
+{
+public:
+ // construction/destruction
+ nes_shuiguan_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock);
+
+ virtual u8 read_m(offs_t offset) override;
+ virtual void write_m(offs_t offset, u8 data) override;
+ virtual void write_h(offs_t offset, u8 data) override;
+
+ virtual void pcb_reset() override;
+
+protected:
+ // device-level overrides
+ virtual void device_start() override ATTR_COLD;
+
+private:
+ u8 m_reg;
+};
+
+
+// ======================> nes_t230_device
+
+class nes_t230_device : public nes_konami_vrc4_device
+{
+public:
+ // construction/destruction
+ nes_t230_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock);
+
+ virtual void write_h(offs_t offset, u8 data) override;
+
+protected:
+ // device-level overrides
+ virtual void device_start() override ATTR_COLD;
+};
+
+
+// ======================> nes_tf1201_device
+
+class nes_tf1201_device : public nes_konami_vrc4_device
+{
+public:
+ // construction/destruction
+ nes_tf1201_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock);
+
+protected:
+ // device-level overrides
+ virtual void device_start() override ATTR_COLD;
+
+ virtual void irq_ack_w() override;
+};
+
+
+// ======================> nes_th21311_device
+
+class nes_th21311_device : public nes_konami_vrc2_device
+{
+public:
+ // construction/destruction
+ nes_th21311_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock);
+
+ virtual void write_h(offs_t offset, u8 data) override;
+
+ virtual void pcb_reset() override;
+
+protected:
+ // device-level overrides
+ virtual void device_start() override ATTR_COLD;
+
+ TIMER_CALLBACK_MEMBER(irq_timer_tick);
+
+private:
+ u16 m_irq_count;
+ u8 m_irq_latch;
+ int m_irq_enable;
+
+ emu_timer *irq_timer;
+};
+
+
+// ======================> nes_waixing_sgz_device
+
+class nes_waixing_sgz_device : public nes_konami_vrc4_device
+{
+public:
+ // construction/destruction
+ nes_waixing_sgz_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock);
+
+ virtual void write_h(offs_t offset, u8 data) override;
+ virtual void chr_w(offs_t offset, u8 data) override;
+
+protected:
+ // construction/destruction
+ nes_waixing_sgz_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, u32 clock, u8 chr_match);
+
+ // device-level overrides
+ virtual void device_start() override ATTR_COLD;
+
+private:
+ u8 m_chr_mask, m_chr_match;
+};
+
+// ======================> nes_hengg_shjy3_device
+
+class nes_hengg_shjy3_device : public nes_waixing_sgz_device
+{
+public:
+ // construction/destruction
+ nes_hengg_shjy3_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock);
+};
+
+
+// device type definition
+DECLARE_DEVICE_TYPE(NES_2YUDB, nes_2yudb_device)
+DECLARE_DEVICE_TYPE(NES_900218, nes_900218_device)
+DECLARE_DEVICE_TYPE(NES_AX40G, nes_ax40g_device)
+DECLARE_DEVICE_TYPE(NES_AX5705, nes_ax5705_device)
+DECLARE_DEVICE_TYPE(NES_BMC_830506C, nes_bmc_830506c_device)
+DECLARE_DEVICE_TYPE(NES_BMC_831128C, nes_bmc_831128c_device)
+DECLARE_DEVICE_TYPE(NES_BMC_KL06, nes_bmc_kl06_device)
+DECLARE_DEVICE_TYPE(NES_CITYFIGHT, nes_cityfight_device)
+DECLARE_DEVICE_TYPE(NES_HENGG_SHJY3, nes_hengg_shjy3_device)
+DECLARE_DEVICE_TYPE(NES_SHUIGUAN, nes_shuiguan_device)
+DECLARE_DEVICE_TYPE(NES_T230, nes_t230_device)
+DECLARE_DEVICE_TYPE(NES_TF1201, nes_tf1201_device)
+DECLARE_DEVICE_TYPE(NES_TH21311, nes_th21311_device)
+DECLARE_DEVICE_TYPE(NES_WAIXING_SGZ, nes_waixing_sgz_device)
+
+#endif // MAME_BUS_NES_VRC_CLONES_H
diff --git a/src/devices/bus/nes/waixing.cpp b/src/devices/bus/nes/waixing.cpp
index 3706d64b26e..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"
//-------------------------------------------------
@@ -38,6 +38,7 @@ DEFINE_DEVICE_TYPE(NES_WAIXING_C, nes_waixing_c_device, "nes_waixing_c",
DEFINE_DEVICE_TYPE(NES_WAIXING_D, nes_waixing_d_device, "nes_waixing_d", "NES Cart Waixing Type D PCB")
DEFINE_DEVICE_TYPE(NES_WAIXING_E, nes_waixing_e_device, "nes_waixing_e", "NES Cart Waixing Type E PCB")
DEFINE_DEVICE_TYPE(NES_WAIXING_F, nes_waixing_f_device, "nes_waixing_f", "NES Cart Waixing Type F PCB")
+DEFINE_DEVICE_TYPE(NES_WAIXING_F1, nes_waixing_f1_device, "nes_waixing_f1", "NES Cart Waixing Type F1 PCB")
DEFINE_DEVICE_TYPE(NES_WAIXING_G, nes_waixing_g_device, "nes_waixing_g", "NES Cart Waixing Type G PCB")
DEFINE_DEVICE_TYPE(NES_WAIXING_H, nes_waixing_h_device, "nes_waixing_h", "NES Cart Waixing Type H PCB")
DEFINE_DEVICE_TYPE(NES_WAIXING_H1, nes_waixing_h1_device, "nes_waixing_h1", "NES Cart Waixing Type H (Alt) PCB")
@@ -45,7 +46,6 @@ DEFINE_DEVICE_TYPE(NES_WAIXING_I, nes_waixing_i_device, "nes_waixing_i",
DEFINE_DEVICE_TYPE(NES_WAIXING_J, nes_waixing_j_device, "nes_waixing_j", "NES Cart Waixing Type J PCB")
DEFINE_DEVICE_TYPE(NES_WAIXING_SH2, nes_waixing_sh2_device, "nes_waixing_sh2", "NES Cart Waixing SH2 PCB")
DEFINE_DEVICE_TYPE(NES_WAIXING_SEC, nes_waixing_sec_device, "nes_waixing_sec", "NES Cart Waixing Security Chip PCB")
-DEFINE_DEVICE_TYPE(NES_WAIXING_SGZ, nes_waixing_sgz_device, "nes_waixing_sgz", "NES Cart Waixing San Guo Zhi PCB")
DEFINE_DEVICE_TYPE(NES_WAIXING_SGZLZ, nes_waixing_sgzlz_device, "nes_waixing_sgzlz", "NES Cart Waixing San Guo Zhong Lie Zhuan PCB")
DEFINE_DEVICE_TYPE(NES_WAIXING_FFV, nes_waixing_ffv_device, "nes_waixing_ffv", "NES Cart Waixing Final Fantasy V PCB")
DEFINE_DEVICE_TYPE(NES_WAIXING_WXZS, nes_waixing_wxzs_device, "nes_waixing_wxzs", "NES Cart Waixing Wai Xing Zhan Shi PCB")
@@ -89,8 +89,18 @@ nes_waixing_e_device::nes_waixing_e_device(const machine_config &mconfig, const
{
}
-nes_waixing_f_device::nes_waixing_f_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
- : nes_waixing_a_device(mconfig, NES_WAIXING_F, tag, owner, clock)
+nes_waixing_f_device::nes_waixing_f_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, u32 clock)
+ : nes_txrom_device(mconfig, type, tag, owner, clock)
+{
+}
+
+nes_waixing_f_device::nes_waixing_f_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock)
+ : nes_waixing_f_device(mconfig, NES_WAIXING_F, tag, owner, clock)
+{
+}
+
+nes_waixing_f1_device::nes_waixing_f1_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock)
+ : nes_waixing_f_device(mconfig, NES_WAIXING_F1, tag, owner, clock)
{
}
@@ -124,7 +134,7 @@ nes_waixing_j_device::nes_waixing_j_device(const machine_config &mconfig, const
{
}
-nes_waixing_sh2_device::nes_waixing_sh2_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
+nes_waixing_sh2_device::nes_waixing_sh2_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock)
: nes_txrom_device(mconfig, NES_WAIXING_SH2, tag, owner, clock)
{
}
@@ -134,11 +144,6 @@ nes_waixing_sec_device::nes_waixing_sec_device(const machine_config &mconfig, co
{
}
-nes_waixing_sgz_device::nes_waixing_sgz_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
- : nes_nrom_device(mconfig, NES_WAIXING_SGZ, tag, owner, clock), m_irq_count(0), m_irq_count_latch(0), m_irq_enable(0), m_irq_enable_latch(0)
-{
-}
-
nes_waixing_sgzlz_device::nes_waixing_sgzlz_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
: nes_nrom_device(mconfig, NES_WAIXING_SGZLZ, tag, owner, clock), m_reg{ 0, 0, 0, 0 }
{
@@ -178,28 +183,13 @@ void nes_waixing_a_device::device_start()
void nes_waixing_a_device::pcb_reset()
{
- m_chr_source = m_vrom_chunks ? CHRROM : CHRRAM;
mmc3_common_initialize(0xff, 0xff, 0);
std::fill(std::begin(mapper_ram), std::end(mapper_ram), 0x00);
}
-void nes_waixing_f_device::pcb_reset()
-{
- m_chr_source = m_vrom_chunks ? CHRROM : CHRRAM;
- mmc3_common_initialize(0xff, 0xff, 0);
-
- std::fill(std::begin(mapper_ram), std::end(mapper_ram), 0x00);
- m_mmc_prg_bank[0] = 0x00;
- m_mmc_prg_bank[1] = 0x01;
- m_mmc_prg_bank[2] = 0x4e;
- m_mmc_prg_bank[3] = 0x4f;
- set_prg(m_prg_base, m_prg_mask);
-}
-
void nes_waixing_g_device::pcb_reset()
{
- m_chr_source = m_vrom_chunks ? CHRROM : CHRRAM;
mmc3_common_initialize(0xff, 0xff, 0);
std::fill(std::begin(mapper_ram), std::end(mapper_ram), 0x00);
@@ -227,8 +217,6 @@ void nes_waixing_j_device::device_start()
void nes_waixing_j_device::pcb_reset()
{
- m_chr_source = m_vrom_chunks ? CHRROM : CHRRAM;
-
m_reg[0] = 0x01;
m_reg[1] = 0x02;
m_reg[2] = 0x7e;
@@ -245,10 +233,9 @@ void nes_waixing_sh2_device::device_start()
void nes_waixing_sh2_device::pcb_reset()
{
- m_chr_source = m_vrom_chunks ? CHRROM : CHRRAM;
-
m_reg[0] = m_reg[1] = 0;
mmc3_common_initialize(0xff, 0xff, 0);
+ set_nt_mirroring(PPU_MIRROR_VERT); // first Fire Emblem doesn't properly set mirroring like the other games do
}
void nes_waixing_sec_device::device_start()
@@ -259,37 +246,10 @@ void nes_waixing_sec_device::device_start()
void nes_waixing_sec_device::pcb_reset()
{
- m_chr_source = m_vrom_chunks ? CHRROM : CHRRAM;
-
m_reg = 0;
mmc3_common_initialize(0xff, 0xff, 0);
}
-void nes_waixing_sgz_device::device_start()
-{
- common_start();
- save_item(NAME(m_irq_enable));
- save_item(NAME(m_irq_enable_latch));
- save_item(NAME(m_irq_count));
- save_item(NAME(m_irq_count_latch));
- save_item(NAME(m_mmc_vrom_bank));
-}
-
-void nes_waixing_sgz_device::pcb_reset()
-{
- m_chr_source = m_vrom_chunks ? CHRROM : CHRRAM;
- prg16_89ab(0);
- prg16_cdef(m_prg_chunks - 1);
- chr8(0, m_chr_source);
-
- m_irq_enable = 0;
- m_irq_enable_latch = 0;
- m_irq_count = 0;
- m_irq_count_latch = 0;
-
- std::fill(std::begin(m_mmc_vrom_bank), std::end(m_mmc_vrom_bank), 0x00);
-}
-
void nes_waixing_sgzlz_device::device_start()
{
common_start();
@@ -298,7 +258,6 @@ void nes_waixing_sgzlz_device::device_start()
void nes_waixing_sgzlz_device::pcb_reset()
{
- m_chr_source = m_vrom_chunks ? CHRROM : CHRRAM;
prg32(0);
chr8(0, m_chr_source);
@@ -313,7 +272,6 @@ void nes_waixing_ffv_device::device_start()
void nes_waixing_ffv_device::pcb_reset()
{
- m_chr_source = m_vrom_chunks ? CHRROM : CHRRAM;
prg16_89ab(0);
prg16_cdef(0x1f);
chr8(0, m_chr_source);
@@ -321,43 +279,6 @@ void nes_waixing_ffv_device::pcb_reset()
m_reg[0] = m_reg[1] = 0;
}
-void nes_waixing_wxzs_device::device_start()
-{
- common_start();
-}
-
-void nes_waixing_wxzs_device::pcb_reset()
-{
- m_chr_source = m_vrom_chunks ? CHRROM : CHRRAM;
- prg32(0);
- chr8(0, m_chr_source);
-}
-
-void nes_waixing_dq8_device::device_start()
-{
- common_start();
-}
-
-void nes_waixing_dq8_device::pcb_reset()
-{
- m_chr_source = m_vrom_chunks ? CHRROM : CHRRAM;
- prg32(0);
- chr8(0, m_chr_source);
-}
-
-void nes_waixing_wxzs2_device::device_start()
-{
- common_start();
-}
-
-void nes_waixing_wxzs2_device::pcb_reset()
-{
- m_chr_source = m_vrom_chunks ? CHRROM : CHRRAM;
- prg32(0);
- chr8(0, m_chr_source);
- set_nt_mirroring(PPU_MIRROR_VERT);
-}
-
void nes_waixing_fs304_device::device_start()
{
common_start();
@@ -366,7 +287,6 @@ void nes_waixing_fs304_device::device_start()
void nes_waixing_fs304_device::pcb_reset()
{
- m_chr_source = m_vrom_chunks ? CHRROM : CHRRAM;
prg32(0);
chr8(0, m_chr_source);
@@ -394,7 +314,7 @@ void nes_waixing_fs304_device::pcb_reset()
iNES: mapper 74
- In MESS: Supported
+ In MAME: Supported
-------------------------------------------------*/
@@ -414,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;
}
}
@@ -435,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)
{
@@ -454,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];
@@ -464,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;
@@ -483,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.
-------------------------------------------------*/
@@ -505,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.
-------------------------------------------------*/
@@ -527,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.
-------------------------------------------------*/
@@ -550,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.
-------------------------------------------------*/
@@ -560,77 +480,49 @@ void nes_waixing_e_device::chr_cb(int start, int bank, int source)
chr1_x(start, bank, chr_src);
}
-
/*-------------------------------------------------
- Waixing Board Type F
+ Waixing Board Type F, F1
- Games: Tenchi wo Kurau II (C)
+ Games: Tenchi wo Kurau II translations (mapper 198),
+ and (mapper 199) Chengjisihan, Tangmu Lixian Ji,
+ Fengse Huanxiang, Datang Fengyun VI Dai
- MMC3 clone.
+ MMC3 clone with an extra 4K WRAM at 0x5000-0x5fff.
+ Mapper 198 banks its 8K CHR RAM and 199 does not.
- iNES: mapper 198
+ iNES: mappers 198, 199
- In MESS: Preliminary support.
+ In MAME: Supported.
+
+ TODO: Sort out G board games which were assigned
+ to mapper 199 previously.
-------------------------------------------------*/
-void nes_waixing_f_device::chr_cb(int start, int bank, int source)
+u8 nes_waixing_f_device::read_l(offs_t offset)
{
- chr1_x(start, bank, CHRRAM);
-}
+ LOGMASKED(LOG_HIFREQ, "waixing_f read_l, offset: %04x\n", offset);
-void nes_waixing_f_device::prg_cb(int start, int bank)
-{
-// if (bank > 0x3f)
-// bank = 0x40 | (bank & 0xf);
- prg8_x(start, bank);
+ offset += 0x100;
+ if (!m_prgram.empty() && offset >= 0x1000)
+ return m_prgram[offset & 0x0fff & (m_prgram.size() - 1)];
+
+ return get_open_bus();
}
-void nes_waixing_f_device::set_prg( int prg_base, int prg_mask )
+void nes_waixing_f_device::write_l(offs_t offset, u8 data)
{
- uint8_t prg_flip = (m_latch & 0x40) ? 2 : 0;
+ LOGMASKED(LOG_HIFREQ, "waixing_f write_l, offset: %04x, data: %02x\n", offset, data);
- prg_cb(0, m_mmc_prg_bank[0 ^ prg_flip]);
- prg_cb(1, m_mmc_prg_bank[1]);
- prg_cb(2, m_mmc_prg_bank[2 ^ prg_flip]);
- prg_cb(3, m_mmc_prg_bank[3]);
+ offset += 0x100;
+ if (!m_prgram.empty() && offset >= 0x1000)
+ m_prgram[offset & 0x0fff & (m_prgram.size() - 1)] = data;
}
-void nes_waixing_f_device::write_h(offs_t offset, uint8_t data)
+void nes_waixing_f1_device::set_chr(u8 chr, int chr_base, int chr_mask)
{
- uint8_t cmd;
- LOG_MMC(("waixing_f write_h, offset: %04x, data: %02x\n", offset, data));
-
- switch (offset & 0x6001)
- {
- case 0x0001:
- cmd = m_latch & 0x07;
- switch (cmd)
- {
- case 0: case 1: // these do not need to be separated: we take care of them in set_chr!
- case 2: case 3: case 4: case 5:
- m_mmc_vrom_bank[cmd] = data;
- set_chr(m_chr_source, m_chr_base, m_chr_mask);
- break;
- case 6:
- case 7:
- case 8:
- case 9:
- m_mmc_prg_bank[cmd - 6] = data;
- //printf("prg bank %d value %x\n", cmd - 6, data);
- set_prg(m_prg_base, m_prg_mask);
- break;
- }
- break;
-
- case 0x2001:
- break;
-
- default:
- waixing_write(offset, data);
- break;
- }
+// ignore CHR banking as all F1 games use 8K unbanked CHR RAM
}
/*-------------------------------------------------
@@ -644,7 +536,7 @@ void nes_waixing_f_device::write_h(offs_t offset, uint8_t data)
iNES: mapper 199
- In MESS: Supported.
+ In MAME: Supported.
-------------------------------------------------*/
@@ -671,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)
{
@@ -721,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.
-------------------------------------------------*/
@@ -734,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)
{
@@ -746,6 +638,7 @@ void nes_waixing_h_device::write_h(offs_t offset, uint8_t data)
m_prg_base = (data << 5) & 0x40;
m_prg_mask = 0x3f;
set_prg(m_prg_base, m_prg_mask);
+ [[fallthrough]];
case 1:
case 2: case 3: case 4: case 5:
m_mmc_vrom_bank[cmd] = data;
@@ -775,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)
{
@@ -787,6 +680,7 @@ void nes_waixing_h1_device::write_h(offs_t offset, uint8_t data)
m_prg_base = (data << 5) & 0x40;
m_prg_mask = 0x3f;
set_prg(m_prg_base, m_prg_mask);
+ [[fallthrough]];
case 1:
case 2: case 3: case 4: case 5:
m_mmc_vrom_bank[cmd] = data;
@@ -818,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.
-------------------------------------------------*/
@@ -835,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)
{
@@ -871,41 +765,39 @@ void nes_waixing_j_device::write_h(offs_t offset, uint8_t data)
Waixing SH2 Board
- Games: Fire Emblem (C) and Fire Emblem Gaiden (C)
+ Games: Fire Emblem (C), Fire Emblem Gaiden (C),
+ Zhentian Shi Yongshi
- MMC3 clone with different access to CHR
+ MMC3 clone with MMC2-like CHR banking.
iNES: mapper 165
- In MESS: Partially Supported.
+ In MAME: Supported.
-------------------------------------------------*/
-void nes_waixing_sh2_device::chr_cb(int start, int bank, int source)
+void nes_waixing_sh2_device::set_chr(u8 chr, int chr_base, int chr_mask)
{
- chr4_0(m_reg[0], m_reg[0] ? CHRRAM : CHRROM);
- chr4_4(m_reg[1], m_reg[1] ? CHRRAM : CHRROM);
+ int bank1 = m_mmc_vrom_bank[m_reg[0] ? 1 : 0] >> 2;
+ int bank2 = m_mmc_vrom_bank[m_reg[1] ? 4 : 2] >> 2;
+
+ chr4_0(bank1, bank1 ? CHRROM : CHRRAM);
+ chr4_4(bank2, bank2 ? CHRROM : CHRRAM);
}
-uint8_t nes_waixing_sh2_device::chr_r(offs_t offset)
+u8 nes_waixing_sh2_device::chr_r(offs_t offset)
{
- int bank = offset >> 10;
- uint8_t val = m_chr_access[bank][offset & 0x3ff]; // this would be usual return value
- int chr_helper;
+ int val = device_nes_cart_interface::chr_r(offset);
switch (offset & 0xff8)
{
- case 0xfd0: chr_helper = (bank & 0x4) | 0x0; break;
- case 0xfe8: chr_helper = (bank & 0x4) | 0x2; break;
- default: return val;
+ case 0xfd0:
+ case 0xfe8:
+ m_reg[BIT(offset, 12)] = BIT(offset, 3);
+ set_chr(m_chr_source, m_chr_base, m_chr_mask);
+ break;
}
- m_reg[offset >> 12] = chr_helper;
- if (offset & 0x1000)
- chr4_4(m_reg[1], m_reg[1] ? CHRRAM : CHRROM);
- else
- chr4_0(m_reg[0], m_reg[0] ? CHRRAM : CHRROM);
-
return val;
}
@@ -920,7 +812,7 @@ uint8_t nes_waixing_sh2_device::chr_r(offs_t offset)
iNES: mapper 249
- In MESS: Partially Supported.
+ In MAME: Partially Supported.
-------------------------------------------------*/
@@ -942,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)
@@ -955,81 +847,6 @@ void nes_waixing_sec_device::write_l(offs_t offset, uint8_t data)
/*-------------------------------------------------
- Waixing San Guo Zhi Board
-
- Games: San Guo Zhi
-
- This board uses Konami IRQ
-
- iNES: mapper 252
-
- In MESS: Unsupported.
-
- -------------------------------------------------*/
-
-// same as Konami IRQ
-void nes_waixing_sgz_device::hblank_irq(int scanline, int vblank, int blanked)
-{
- /* Increment & check the IRQ scanline counter */
- if (m_irq_enable && (++m_irq_count == 0x100))
- {
- m_irq_count = m_irq_count_latch;
- m_irq_enable = m_irq_enable_latch;
- hold_irq_line();
- }
-}
-
-void nes_waixing_sgz_device::write_h(offs_t offset, uint8_t data)
-{
- uint8_t helper, bank;
- LOG_MMC(("waixing_sgz write_h, offset: %04x, data: %02x\n", offset, data));
-
- switch (offset & 0x7000)
- {
- case 0x0000:
- prg8_89(data);
- break;
- case 0x2000:
- prg8_ab(data);
- break;
- case 0x3000:
- case 0x4000:
- case 0x5000:
- case 0x6000:
- bank = ((offset & 0x7000) - 0x3000) / 0x0800 + ((offset & 0x0008) >> 3);
- helper = offset & 0x04;
- if (helper)
- m_mmc_vrom_bank[bank] = (m_mmc_vrom_bank[bank] & 0x0f) | ((data & 0x0f) << 4);
- else
- m_mmc_vrom_bank[bank] = (m_mmc_vrom_bank[bank] & 0xf0) | (data & 0x0f);
- chr1_x(bank, m_mmc_vrom_bank[bank], CHRROM);
- break;
- case 0x7000:
- switch (offset & 0x0c)
- {
- case 0x00:
- m_irq_count_latch = (m_irq_count_latch & 0xf0) | (data & 0x0f);
- break;
- case 0x04:
- m_irq_count_latch = (m_irq_count_latch & 0x0f) | ((data & 0x0f) << 4);
- break;
- case 0x08:
- m_irq_enable = data & 0x02;
- m_irq_count_latch = data & 0x01;
- if (data & 0x02)
- m_irq_count = m_irq_count_latch;
- break;
- case 0x0c:
- m_irq_enable = m_irq_enable_latch;
- break;
- }
- break;
- }
-}
-
-
-/*-------------------------------------------------
-
Waixing San Guo Zhong Lie Zhuan Board
Games: Fan Kong Jing Ying, San Guo Zhong Lie Zhuan, Xing
@@ -1037,7 +854,7 @@ void nes_waixing_sgz_device::write_h(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
@@ -1049,7 +866,7 @@ void nes_waixing_sgz_device::write_h(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;
@@ -1108,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)
@@ -1157,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);
@@ -1187,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);
}
@@ -1206,18 +1023,21 @@ void nes_waixing_dq8_device::write_h(offs_t offset, uint8_t data)
Games: Wai Xing Zhan Shi 2 (aka Phantasy Star 2),
Bao Xiao Tien Guo, Bio Hazard, Pokemon Gold, Subor (R)
- iNES: mapper 15
-
- In MESS: Supported
+ FIXME: This used to be mapper 15. NesDev research says the
+ only two games found on board K-1029 (now in multigame.cpp)
+ are the two Contra multicarts. All other Waixing games
+ appear to be ROM hacks to work with mapper 15. Games on
+ this device need to be reassigned to correct device and/or
+ replaced with original dumps that match the original boards.
-------------------------------------------------*/
void nes_waixing_wxzs2_device::write_h(offs_t offset, uint8_t data)
{
- uint8_t flip = (data & 0x80) >> 7;
- uint8_t helper = (data & 0x7f) << 1;
+ 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);
@@ -1261,20 +1081,19 @@ 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));
- int bank;
- offset += 0x100;
+ LOG("fs304 write_l, offset: %04x, data: %02x\n", offset, data);
+ offset += 0x100;
if (offset >= 0x1000)
{
- m_reg[(offset >> 8) & 3] = data;
- bank = ((m_reg[2] & 0x0f) << 4) | BIT(m_reg[1], 1) | (m_reg[0] & 0x0e);
+ m_reg[BIT(offset, 8, 2)] = data;
+ int bank = ((m_reg[2] & 0x0f) << 4) | BIT(m_reg[1], 1) | (m_reg[0] & 0x0e);
prg32(bank);
chr8(0, CHRRAM);
}
diff --git a/src/devices/bus/nes/waixing.h b/src/devices/bus/nes/waixing.h
index bb6fcaf831a..91a06eef3ac 100644
--- a/src/devices/bus/nes/waixing.h
+++ b/src/devices/bus/nes/waixing.h
@@ -28,7 +28,7 @@ protected:
nes_waixing_a_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_start() override ATTR_COLD;
void set_mirror(uint8_t nt);
@@ -56,7 +56,6 @@ public:
// construction/destruction
nes_waixing_b_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
- // device-level overrides
virtual void chr_cb(int start, int bank, int source) override;
};
@@ -69,7 +68,6 @@ public:
// construction/destruction
nes_waixing_c_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
- // device-level overrides
virtual void chr_cb(int start, int bank, int source) override;
};
@@ -82,7 +80,6 @@ public:
// construction/destruction
nes_waixing_d_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
- // device-level overrides
virtual void chr_cb(int start, int bank, int source) override;
};
@@ -95,28 +92,37 @@ public:
// construction/destruction
nes_waixing_e_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
- // device-level overrides
virtual void chr_cb(int start, int bank, int source) override;
};
// ======================> nes_waixing_f_device
-class nes_waixing_f_device : public nes_waixing_a_device
+class nes_waixing_f_device : public nes_txrom_device
{
public:
// construction/destruction
- nes_waixing_f_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
+ nes_waixing_f_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock);
- // device-level overrides
- virtual void write_h(offs_t offset, uint8_t data) override;
- virtual void prg_cb(int start, int bank) override;
- virtual void chr_cb(int start, int bank, int source) override;
+ virtual u8 read_l(offs_t offset) override;
+ virtual void write_l(offs_t offset, u8 data) override;
- virtual void pcb_reset() override;
+protected:
+ // construction/destruction
+ nes_waixing_f_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, u32 clock);
+};
-private:
- virtual void set_prg(int prg_base, int prg_mask) override;
+
+// ======================> nes_waixing_f1_device
+
+class nes_waixing_f1_device : public nes_waixing_f_device
+{
+public:
+ // construction/destruction
+ nes_waixing_f1_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock);
+
+protected:
+ virtual void set_chr(uint8_t chr, int chr_base, int chr_mask) override;
};
@@ -128,7 +134,6 @@ public:
// construction/destruction
nes_waixing_g_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
- // device-level overrides
virtual void write_h(offs_t offset, uint8_t data) override;
virtual void chr_cb(int start, int bank, int source) override;
@@ -147,15 +152,13 @@ public:
// construction/destruction
nes_waixing_h_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
+ virtual void write_h(offs_t offset, uint8_t data) override;
virtual void chr_cb(int start, int bank, int source) override;
// This PCB does not have 1K of internal RAM, so it's not derived from nes_waixing_a_device!!
protected:
nes_waixing_h_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock);
-
- // device-level overrides
- virtual void write_h(offs_t offset, uint8_t data) override;
};
@@ -167,7 +170,6 @@ public:
// construction/destruction
nes_waixing_h1_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
- // device-level overrides
virtual void write_h(offs_t offset, uint8_t data) override;
// This variant does not ignore the wram protect!
@@ -200,7 +202,7 @@ public:
protected:
// device-level overrides
- virtual void device_start() override;
+ virtual void device_start() override ATTR_COLD;
virtual void set_prg(int prg_base, int prg_mask) override;
uint8_t m_reg[4];
@@ -213,17 +215,20 @@ class nes_waixing_sh2_device : public nes_txrom_device
{
public:
// construction/destruction
- nes_waixing_sh2_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
+ nes_waixing_sh2_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock);
- // device-level overrides
- virtual void device_start() override;
- virtual uint8_t chr_r(offs_t offset) override;
- virtual void chr_cb(int start, int bank, int source) override;
+ virtual u8 chr_r(offs_t offset) override;
virtual void pcb_reset() override;
protected:
- uint8_t m_reg[2];
+ // device-level overrides
+ virtual void device_start() override ATTR_COLD;
+
+ virtual void set_chr(u8 chr, int chr_base, int chr_mask) override;
+
+private:
+ u8 m_reg[2];
};
@@ -243,36 +248,12 @@ public:
protected:
// device-level overrides
- virtual void device_start() override;
+ virtual void device_start() override ATTR_COLD;
uint8_t m_reg;
};
-// ======================> nes_waixing_sgz_device
-
-class nes_waixing_sgz_device : public nes_nrom_device
-{
-public:
- // construction/destruction
- nes_waixing_sgz_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
-
- virtual void write_h(offs_t offset, uint8_t data) override;
-
- virtual void hblank_irq(int scanline, int vblank, int blanked) override;
- virtual void pcb_reset() override;
-
-protected:
- // device-level overrides
- virtual void device_start() override;
-
- uint16_t m_irq_count, m_irq_count_latch;
- int m_irq_enable, m_irq_enable_latch;
-
- uint8_t m_mmc_vrom_bank[8];
-};
-
-
// ======================> nes_waixing_sgzlz_device
class nes_waixing_sgzlz_device : public nes_nrom_device
@@ -287,7 +268,7 @@ public:
protected:
// device-level overrides
- virtual void device_start() override;
+ virtual void device_start() override ATTR_COLD;
uint8_t m_reg[4];
};
@@ -307,7 +288,7 @@ public:
protected:
// device-level overrides
- virtual void device_start() override;
+ virtual void device_start() override ATTR_COLD;
uint8_t m_reg[2];
};
@@ -322,12 +303,6 @@ public:
nes_waixing_wxzs_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
virtual void write_h(offs_t offset, uint8_t data) override;
-
- virtual void pcb_reset() override;
-
-protected:
- // device-level overrides
- virtual void device_start() override;
};
@@ -340,12 +315,6 @@ public:
nes_waixing_dq8_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
virtual void write_h(offs_t offset, uint8_t data) override;
-
- virtual void pcb_reset() override;
-
-protected:
- // device-level overrides
- virtual void device_start() override;
};
@@ -358,12 +327,6 @@ public:
nes_waixing_wxzs2_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
virtual void write_h(offs_t offset, uint8_t data) override;
-
- virtual void pcb_reset() override;
-
-protected:
- // device-level overrides
- virtual void device_start() override;
};
@@ -381,7 +344,7 @@ public:
protected:
// device-level overrides
- virtual void device_start() override;
+ virtual void device_start() override ATTR_COLD;
uint8_t m_reg[4];
};
@@ -395,6 +358,7 @@ DECLARE_DEVICE_TYPE(NES_WAIXING_C, nes_waixing_c_device)
DECLARE_DEVICE_TYPE(NES_WAIXING_D, nes_waixing_d_device)
DECLARE_DEVICE_TYPE(NES_WAIXING_E, nes_waixing_e_device)
DECLARE_DEVICE_TYPE(NES_WAIXING_F, nes_waixing_f_device)
+DECLARE_DEVICE_TYPE(NES_WAIXING_F1, nes_waixing_f1_device)
DECLARE_DEVICE_TYPE(NES_WAIXING_G, nes_waixing_g_device)
DECLARE_DEVICE_TYPE(NES_WAIXING_H, nes_waixing_h_device)
DECLARE_DEVICE_TYPE(NES_WAIXING_H1, nes_waixing_h1_device)
@@ -402,7 +366,6 @@ DECLARE_DEVICE_TYPE(NES_WAIXING_I, nes_waixing_i_device)
DECLARE_DEVICE_TYPE(NES_WAIXING_J, nes_waixing_j_device)
DECLARE_DEVICE_TYPE(NES_WAIXING_SH2, nes_waixing_sh2_device)
DECLARE_DEVICE_TYPE(NES_WAIXING_SEC, nes_waixing_sec_device)
-DECLARE_DEVICE_TYPE(NES_WAIXING_SGZ, nes_waixing_sgz_device)
DECLARE_DEVICE_TYPE(NES_WAIXING_SGZLZ, nes_waixing_sgzlz_device)
DECLARE_DEVICE_TYPE(NES_WAIXING_FFV, nes_waixing_ffv_device)
DECLARE_DEVICE_TYPE(NES_WAIXING_WXZS, nes_waixing_wxzs_device)
diff --git a/src/devices/bus/nes/zemina.cpp b/src/devices/bus/nes/zemina.cpp
index 22741967572..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
@@ -28,38 +27,28 @@ DEFINE_DEVICE_TYPE(NES_ZEMINA, nes_zemina_device, "nes_zemina", "NES Cart Zemina
//**************************************************************************
//-------------------------------------------------
-// nes_zemina_device - constructor
+// constructor
//-------------------------------------------------
-nes_zemina_device::nes_zemina_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
+nes_zemina_device::nes_zemina_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock)
: nes_nrom_device(mconfig, NES_ZEMINA, tag, owner, clock)
{
}
-/*-------------------------------------------------
- device_start
--------------------------------------------------*/
-void nes_zemina_device::device_start()
-{
- common_start();
-}
-/*-------------------------------------------------
- pcb_reset
--------------------------------------------------*/
void nes_zemina_device::pcb_reset()
{
- set_nt_mirroring(PPU_MIRROR_VERT);
- chr2_0(0, CHRROM);
- chr2_2(0, CHRROM);
- chr2_4(0, CHRROM);
- chr2_6(0, CHRROM);
prg16_89ab(0);
- prg16_cdef(0);
+ prg16_cdef(0); // fixed bank
+
+ for (int i = 0; i < 4; i++)
+ chr2_x(i << 1, 0, CHRROM);
}
+
+
/*-------------------------------------------------
mapper specific handlers
-------------------------------------------------*/
@@ -68,46 +57,26 @@ void nes_zemina_device::pcb_reset()
Zemina board emulation
- Currently, this board is only known to be used
- by one game: Magic Kid GooGoo.
+ Games: Magic Kid GooGoo
- Info from kevtris at NESDev, who dumped the game:
- wiki.nesdev.com/w/index.php/INES_Mapper_190
+ iNES: mapper 190
--------------------------------------------------*/
+ In MAME: Supported.
-/*-------------------------------------------------
- write
-------------------------------------------------*/
-void nes_zemina_device::write_h(offs_t offset, uint8_t data)
+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);
- if (offset >= 0x0000 && offset <= 0x1FFF)
- {
- prg16_89ab(data & 0x07);
- }
- else if (offset >= 0x4000 && offset <= 0x5FFF)
- {
- prg16_89ab((data & 0x07) | 0x08);
- }
- else if ((offset & 0x2000) == 0x2000) // 2K CHR banks
+ switch (offset & 0x6000)
{
- switch (offset & 0x03) // only A0, A1, A13, A14, and A15 are used to select the CHR bank
- {
- case 0x00:
- chr2_0(data, CHRROM);
- break;
- case 0x01:
- chr2_2(data, CHRROM);
- break;
- case 0x02:
- chr2_4(data, CHRROM);
- break;
- case 0x03:
- chr2_6(data, CHRROM);
- break;
- }
+ case 0x0000:
+ case 0x4000:
+ prg16_89ab(BIT(offset, 14) << 3 | (data & 0x07));
+ break;
+ case 0x2000:
+ chr2_x((offset & 0x03) << 1, data, CHRROM);
+ break;
}
}
diff --git a/src/devices/bus/nes/zemina.h b/src/devices/bus/nes/zemina.h
index 752c7f1382d..992ecdb2c13 100644
--- a/src/devices/bus/nes/zemina.h
+++ b/src/devices/bus/nes/zemina.h
@@ -11,16 +11,13 @@
// ======================> nes_zemina_device
-class nes_zemina_device :
- public nes_nrom_device
+class nes_zemina_device : public nes_nrom_device
{
public:
// construction/destruction
- nes_zemina_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
+ nes_zemina_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock);
- // device-level overrides
- virtual void device_start() override;
- virtual void write_h(offs_t offset, uint8_t data) override;
+ virtual void write_h(offs_t offset, u8 data) override;
virtual void pcb_reset() override;
};
diff --git a/src/devices/bus/nes_ctrl/4score.h b/src/devices/bus/nes_ctrl/4score.h
index c69249b5511..51dec907297 100644
--- a/src/devices/bus/nes_ctrl/4score.h
+++ b/src/devices/bus/nes_ctrl/4score.h
@@ -23,15 +23,16 @@
class nes_4score_device : public device_t,
public device_nes_control_port_interface
{
+public:
+ virtual uint8_t read_bit0() override;
+
protected:
// construction/destruction
nes_4score_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_bit0() override;
+ virtual void device_start() override ATTR_COLD;
+ virtual void device_reset() override ATTR_COLD;
uint32_t m_latch;
};
@@ -44,10 +45,11 @@ public:
// construction/destruction
nes_4score_p1p3_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
- virtual ioport_constructor device_input_ports() const override;
+ virtual void write(uint8_t data) override;
protected:
- virtual void write(uint8_t data) override;
+ // device-level overrides
+ virtual ioport_constructor device_input_ports() const override ATTR_COLD;
private:
required_ioport m_joypad1;
@@ -62,10 +64,11 @@ public:
// construction/destruction
nes_4score_p2p4_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
- virtual ioport_constructor device_input_ports() const override;
+ virtual void write(uint8_t data) override;
protected:
- virtual void write(uint8_t data) override;
+ // device-level overrides
+ virtual ioport_constructor device_input_ports() const override ATTR_COLD;
private:
required_ioport m_joypad2;
@@ -77,5 +80,4 @@ private:
DECLARE_DEVICE_TYPE(NES_4SCORE_P1P3, nes_4score_p1p3_device)
DECLARE_DEVICE_TYPE(NES_4SCORE_P2P4, nes_4score_p2p4_device)
-
#endif // MAME_BUS_NES_CTRL_4SCORE_H
diff --git a/src/devices/bus/nes_ctrl/arkpaddle.cpp b/src/devices/bus/nes_ctrl/arkpaddle.cpp
index 8cd2cfea3c4..48be8990b47 100644
--- a/src/devices/bus/nes_ctrl/arkpaddle.cpp
+++ b/src/devices/bus/nes_ctrl/arkpaddle.cpp
@@ -5,6 +5,25 @@
Nintendo Family Computer & Entertainment System -
Arkanoid Paddle input device
+ TODO: Investigate the differences between the 3 paddles released with
+ Arkanoid (US), Arkanoid (JP), Arkanoid II (JP). At the moment we only
+ emulate the US and daisy-chainable Famicom (Ark2) paddles.
+
+ 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.
+
**********************************************************************/
#include "emu.h"
@@ -14,15 +33,18 @@
// 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 )
PORT_START("PADDLE")
- PORT_BIT( 0xff, 0x7f, IPT_PADDLE) PORT_SENSITIVITY(25) PORT_KEYDELTA(25) PORT_CENTERDELTA(0) PORT_MINMAX(0x62,0xf2)
+ // MINMAX range large enough to encompass what Taito games expect, Ark1 will glitch if MIN is too low
+ // This may be too wide compared with real paddles, even accounting for those with adjustment screws
+ PORT_BIT( 0x1ff, 0x130, IPT_PADDLE ) PORT_SENSITIVITY(50) PORT_KEYDELTA(35) PORT_CENTERDELTA(0) PORT_MINMAX(0x78, 0x1f8)
+
PORT_START("BUTTON")
- PORT_BIT( 0x01, IP_ACTIVE_HIGH, IPT_BUTTON1) PORT_NAME("Paddle button")
+ PORT_BIT( 0x01, IP_ACTIVE_HIGH, IPT_BUTTON1 ) PORT_NAME("Paddle button")
INPUT_PORTS_END
@@ -35,6 +57,23 @@ ioport_constructor nes_vaus_device::device_input_ports() const
return INPUT_PORTS_NAME( arkanoid_paddle );
}
+static void vausfc_daisy(device_slot_interface &device)
+{
+ device.option_add("vaus", NES_ARKPADDLE_FC);
+}
+
+
+//-------------------------------------------------
+// device_add_mconfig - add device configuration
+//-------------------------------------------------
+
+void nes_vausfc_device::device_add_mconfig(machine_config &config)
+{
+ // expansion port to allow daisy chaining
+ NES_CONTROL_PORT(config, m_daisychain, vausfc_daisy, nullptr);
+ if (m_port != nullptr)
+ m_daisychain->set_screen_tag(m_port->m_screen);
+}
//**************************************************************************
@@ -45,22 +84,23 @@ ioport_constructor nes_vaus_device::device_input_ports() const
// nes_vaus_device - constructor
//-------------------------------------------------
-nes_vaus_device::nes_vaus_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock)
+nes_vaus_device::nes_vaus_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, u32 clock)
: device_t(mconfig, type, tag, owner, clock)
, device_nes_control_port_interface(mconfig, *this)
, m_paddle(*this, "PADDLE")
, m_button(*this, "BUTTON")
- , m_start_conv(0), m_latch(0)
+ , m_latch(0)
{
}
-nes_vaus_device::nes_vaus_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
+nes_vaus_device::nes_vaus_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock)
: nes_vaus_device(mconfig, NES_ARKPADDLE, tag, owner, clock)
{
}
-nes_vausfc_device::nes_vausfc_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
+nes_vausfc_device::nes_vausfc_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock)
: nes_vaus_device(mconfig, NES_ARKPADDLE_FC, tag, owner, clock)
+ , m_daisychain(*this, "subexp")
{
}
@@ -72,18 +112,7 @@ nes_vausfc_device::nes_vausfc_device(const machine_config &mconfig, const char *
void nes_vaus_device::device_start()
{
save_item(NAME(m_latch));
- save_item(NAME(m_start_conv));
-}
-
-
-//-------------------------------------------------
-// device_reset
-//-------------------------------------------------
-
-void nes_vaus_device::device_reset()
-{
- m_latch = 0;
- m_start_conv = 0;
+ save_item(NAME(m_strobe));
}
@@ -91,25 +120,25 @@ void nes_vaus_device::device_reset()
// read
//-------------------------------------------------
-uint8_t nes_vaus_device::read_bit34()
+u8 nes_vaus_device::read_bit34()
{
- uint8_t ret = (m_button->read() << 3);
- ret |= (m_latch & 0x80) >> 3;
+ u8 ret = m_button->read() << 3;
+ ret |= (m_latch & 0x100) >> 4;
m_latch <<= 1;
- m_latch &= 0xff;
return ret;
}
-uint8_t nes_vausfc_device::read_exp(offs_t offset)
+u8 nes_vausfc_device::read_exp(offs_t offset)
{
- uint8_t ret;
+ u8 ret;
if (offset == 0) //$4016
ret = m_button->read() << 1;
else //$4017
{
- ret = (m_latch & 0x80) >> 6;
+ ret = (m_latch & 0x100) >> 7;
m_latch <<= 1;
- m_latch &= 0xff;
+ ret |= (m_daisychain->read_exp(0) & 0x02) << 2;
+ ret |= (m_daisychain->read_exp(1) & 0x02) << 3;
}
return ret;
}
@@ -118,12 +147,14 @@ uint8_t nes_vausfc_device::read_exp(offs_t offset)
// write
//-------------------------------------------------
-void nes_vaus_device::write(uint8_t data)
+void nes_vaus_device::write(u8 data)
{
- int old = m_start_conv;
-
- if (data == 0 && old == 1)
- m_latch = (uint8_t) (m_paddle->read() ^ 0xff);
+ if (write_strobe(data))
+ m_latch = ~m_paddle->read();
+}
- m_start_conv = data;
+void nes_vausfc_device::write(u8 data)
+{
+ m_daisychain->write(data & 1);
+ nes_vaus_device::write(data);
}
diff --git a/src/devices/bus/nes_ctrl/arkpaddle.h b/src/devices/bus/nes_ctrl/arkpaddle.h
index cdd6255792b..2dc20d63b92 100644
--- a/src/devices/bus/nes_ctrl/arkpaddle.h
+++ b/src/devices/bus/nes_ctrl/arkpaddle.h
@@ -25,39 +25,42 @@ class nes_vaus_device : public device_t, public device_nes_control_port_interfac
{
public:
// construction/destruction
- nes_vaus_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
+ nes_vaus_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock);
- // optional information overrides
- virtual ioport_constructor device_input_ports() const override;
+ virtual u8 read_bit34() override;
+ virtual void write(u8 data) override;
protected:
- nes_vaus_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock);
+ nes_vaus_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;
-
- virtual uint8_t read_bit34() override;
- virtual void write(uint8_t data) override;
+ virtual void device_start() override ATTR_COLD;
+ virtual ioport_constructor device_input_ports() const override ATTR_COLD;
required_ioport m_paddle;
required_ioport m_button;
- uint8_t m_start_conv;
- uint32_t m_latch;
+ u16 m_latch;
};
-// ======================> nes_vaus_device
+// ======================> nes_vausfc_device
class nes_vausfc_device : public nes_vaus_device
{
public:
// construction/destruction
- nes_vausfc_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
+ nes_vausfc_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock);
+
+ virtual u8 read_bit34() override { return 0; }
+ virtual u8 read_exp(offs_t offset) override;
+ virtual void write(u8 data) override;
protected:
- virtual uint8_t read_bit34() override { return 0; }
- virtual uint8_t read_exp(offs_t offset) override;
+ // device-level overrides
+ virtual void device_add_mconfig(machine_config &config) override ATTR_COLD;
+
+private:
+ required_device<nes_control_port_device> m_daisychain;
};
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..ebe5615292d
--- /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_H
+#define MAME_BUS_NES_CTRL_BANDAIHS_H
+
+#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 ATTR_COLD;
+ virtual void device_add_mconfig(machine_config &config) override ATTR_COLD;
+ virtual ioport_constructor device_input_ports() const override ATTR_COLD;
+
+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_H
diff --git a/src/devices/bus/nes_ctrl/bcbattle.cpp b/src/devices/bus/nes_ctrl/bcbattle.cpp
index a60e3cd158c..26973cfc51c 100644
--- a/src/devices/bus/nes_ctrl/bcbattle.cpp
+++ b/src/devices/bus/nes_ctrl/bcbattle.cpp
@@ -27,47 +27,44 @@ void nes_bcbattle_device::device_add_mconfig(machine_config &config)
//-------------------------------------------------
-// device_timer - handler timer events
+// scan_tick - periodic scan kludge
//-------------------------------------------------
// This part is the hacky replacement for the real Barcode unit [shared with SNES implementation]:
// code periodically checks whether a new code has been scanned and it moves it to the
// m_current_barcode array
-void nes_bcbattle_device::device_timer(emu_timer &timer, device_timer_id id, int param, void *ptr)
+TIMER_CALLBACK_MEMBER(nes_bcbattle_device::scan_tick)
{
- if (id == TIMER_BATTLER)
+ int old = m_new_code;
+ // has something new been scanned?
+ if (old < m_reader->get_pending_code())
{
- int old = m_new_code;
- // has something new been scanned?
- if (old < m_reader->get_pending_code())
+ if (m_reader->get_byte_length() == 13)
{
- if (m_reader->get_byte_length() == 13)
- {
- for (int i = 0; i < 13; i++)
- m_current_barcode[i] = m_reader->read_code() + '0';
- }
- else if (m_reader->get_byte_length() == 8)
- {
- for (int i = 0; i < 5; i++)
- m_current_barcode[i] = 0x20;
- for (int i = 5; i < 13; i++)
- m_current_barcode[i] = m_reader->read_code() + '0';
- }
- // read one more, to reset the internal byte counter
- m_reader->read_code();
-
- // the string "SUNSOFT" is accepted as well by Barcode World
- m_current_barcode[13] = 'E';
- m_current_barcode[14] = 'P';
- m_current_barcode[15] = 'O';
- m_current_barcode[16] = 'C';
- m_current_barcode[17] = 'H';
- m_current_barcode[18] = 0x0d;
- m_current_barcode[19] = 0x0a;
- m_pending_code = 1;
+ for (int i = 0; i < 13; i++)
+ m_current_barcode[i] = m_reader->read_code() + '0';
+ }
+ else if (m_reader->get_byte_length() == 8)
+ {
+ for (int i = 0; i < 5; i++)
+ m_current_barcode[i] = 0x20;
+ for (int i = 5; i < 13; i++)
+ m_current_barcode[i] = m_reader->read_code() + '0';
}
- m_new_code = m_reader->get_pending_code();
+ // read one more, to reset the internal byte counter
+ m_reader->read_code();
+
+ // the string "SUNSOFT" is accepted as well by Barcode World
+ m_current_barcode[13] = 'E';
+ m_current_barcode[14] = 'P';
+ m_current_barcode[15] = 'O';
+ m_current_barcode[16] = 'C';
+ m_current_barcode[17] = 'H';
+ m_current_barcode[18] = 0x0d;
+ m_current_barcode[19] = 0x0a;
+ m_pending_code = 1;
}
+ m_new_code = m_reader->get_pending_code();
}
//**************************************************************************
@@ -96,7 +93,7 @@ void nes_bcbattle_device::device_start()
// lacking emulation of the standalone Barcode Battler, we refresh periodically the input from the reader
// proper emulation would have the standalone unit acknowledging that a new barcode has been scanned
// and sending the proper serial bits, instead of our read_current_bit() function!
- battler_timer = timer_alloc(TIMER_BATTLER);
+ battler_timer = timer_alloc(FUNC(nes_bcbattle_device::scan_tick), this);
battler_timer->adjust(attotime::zero, 0, machine().device<cpu_device>("maincpu")->cycles_to_attotime(1000));
save_item(NAME(m_current_barcode));
@@ -119,7 +116,7 @@ void nes_bcbattle_device::device_reset()
m_transmitting = 0;
m_cur_bit = 0;
m_cur_byte = 0;
- memset(m_current_barcode, 0, ARRAY_LENGTH(m_current_barcode));
+ std::fill(std::begin(m_current_barcode), std::end(m_current_barcode), 0);
}
diff --git a/src/devices/bus/nes_ctrl/bcbattle.h b/src/devices/bus/nes_ctrl/bcbattle.h
index 9fc75b0f9fc..907a0c550f8 100644
--- a/src/devices/bus/nes_ctrl/bcbattle.h
+++ b/src/devices/bus/nes_ctrl/bcbattle.h
@@ -28,19 +28,19 @@ public:
// construction/destruction
nes_bcbattle_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
-protected:
- static constexpr device_timer_id TIMER_BATTLER = 1;
+ virtual uint8_t read_exp(offs_t offset) override;
+protected:
// device-level overrides
- virtual void device_start() override;
- virtual void device_reset() override;
- virtual void device_timer(emu_timer &timer, device_timer_id id, int param, void *ptr) override;
+ virtual void device_start() override ATTR_COLD;
+ virtual void device_reset() override ATTR_COLD;
- virtual void device_add_mconfig(machine_config &config) override;
+ virtual void device_add_mconfig(machine_config &config) override ATTR_COLD;
- virtual uint8_t read_exp(offs_t offset) override;
int read_current_bit();
+ TIMER_CALLBACK_MEMBER(scan_tick);
+
required_device<barcode_reader_device> m_reader;
uint8_t m_current_barcode[20];
int m_pending_code, m_new_code, m_transmitting, m_cur_bit, m_cur_byte;
diff --git a/src/devices/bus/nes_ctrl/ctrl.cpp b/src/devices/bus/nes_ctrl/ctrl.cpp
index a946eeb80fb..4f508cac556 100644
--- a/src/devices/bus/nes_ctrl/ctrl.cpp
+++ b/src/devices/bus/nes_ctrl/ctrl.cpp
@@ -6,18 +6,18 @@
and Family Computer expansion port emulation
Here we emulate in fact 3 different kind of ports, which are
- connected to different bis of memory locations $4016 and $4017:
+ connected to different bits of memory locations $4016 and $4017:
- NES controller ports: these are hooked to bit 0,3,4 of the
corresponding address ($4016 for port1, $4017 for port2)
- FC controller ports: these are only hooked to bit 0 of the
corresponding address (so that e.g. a NES Zapper could not
be connected to a later FC AV model, because its inputs
would not be detected)
- - FC expansion port: this is hooked to bits 0-4 of both addresses
- To make things a little bit more complex, old FC models have the
- controller hardwired to the unit, and the P2 controllers are
- directly hooked also to one of the expansion port lines (namely,
- microphone inputs from P2 go to $4016 bit 2)
+ - FC expansion port: this is hooked to bit 1 of memory location
+ $4016 and bits 0-4 of $4017
+ To make things a little bit more complex, old FC models have
+ controllers hardwired to the unit, and the P2 controllers are
+ directly hooked to bit 2 of $4016 (for microphone inputs).
Even if the controller port and the expansion port are
physically different (the FC expansion is a 15pin port, while
@@ -35,29 +35,36 @@
handlers they have hooks for: Basic usage is that the expansion
port calls read_exp, FC ctrl ports call read_bit0, and NES ctrl
ports call both read_bit0 and read_bit34. However, to cope with
- the original FC microphone, we will have the second controller
- port calling read_exp too.
+ the original FC microphone, we have a one-off read_bit2 handler
+ called by the second controller.
**********************************************************************/
#include "emu.h"
-#include "screen.h"
#include "ctrl.h"
+
// slot devices
#include "4score.h"
#include "arkpaddle.h"
+#include "bandaihs.h"
#include "bcbattle.h"
-#include "ftrainer.h"
+#include "dorepiano.h"
#include "fckeybrd.h"
+#include "fcmat.h"
#include "hori.h"
#include "joypad.h"
+#include "konamibag.h"
#include "konamihs.h"
#include "miracle.h"
#include "mjpanel.h"
#include "pachinko.h"
#include "partytap.h"
#include "powerpad.h"
+#include "rob.h"
+#include "sharpcass.h"
+#include "snesadapter.h"
#include "suborkey.h"
+#include "turbofile.h"
#include "zapper.h"
@@ -77,8 +84,9 @@ DEFINE_DEVICE_TYPE(NES_CONTROL_PORT, nes_control_port_device, "nes_control_port"
// device_nes_control_port_interface - constructor
//-------------------------------------------------
-device_nes_control_port_interface::device_nes_control_port_interface(const machine_config &mconfig, device_t &device) :
- device_slot_card_interface(mconfig, device)
+device_nes_control_port_interface::device_nes_control_port_interface(const machine_config &mconfig, device_t &device)
+ : device_interface(device, "nesctrl")
+ , m_strobe(0)
{
m_port = dynamic_cast<nes_control_port_device *>(device.owner());
}
@@ -102,9 +110,9 @@ device_nes_control_port_interface::~device_nes_control_port_interface()
// nes_control_port_device - constructor
//-------------------------------------------------
-nes_control_port_device::nes_control_port_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) :
+nes_control_port_device::nes_control_port_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock) :
device_t(mconfig, NES_CONTROL_PORT, tag, owner, clock),
- device_slot_interface(mconfig, *this),
+ device_single_card_slot_interface<device_nes_control_port_interface>(mconfig, *this),
m_screen(*this, finder_base::DUMMY_TAG),
m_device(nullptr)
{
@@ -126,35 +134,43 @@ nes_control_port_device::~nes_control_port_device()
void nes_control_port_device::device_start()
{
- m_device = dynamic_cast<device_nes_control_port_interface *>(get_card_device());
+ m_device = get_card_device();
}
-uint8_t nes_control_port_device::read_bit0()
+u8 nes_control_port_device::read_bit0()
{
- uint8_t data = 0;
+ u8 data = 0;
if (m_device)
data = m_device->read_bit0();
return data;
}
-uint8_t nes_control_port_device::read_bit34()
+u8 nes_control_port_device::read_bit2()
{
- uint8_t data = 0;
+ u8 data = 0;
+ if (m_device)
+ data = m_device->read_bit2();
+ return data;
+}
+
+u8 nes_control_port_device::read_bit34()
+{
+ u8 data = 0;
if (m_device)
data = m_device->read_bit34();
return data;
}
-uint8_t nes_control_port_device::read_exp(offs_t offset)
+u8 nes_control_port_device::read_exp(offs_t offset)
{
- uint8_t data = 0;
+ u8 data = 0;
if (m_device)
data = m_device->read_exp(offset);
return data;
}
-void nes_control_port_device::write(uint8_t data)
+void nes_control_port_device::write(u8 data)
{
if (m_device)
m_device->write(data);
@@ -172,6 +188,8 @@ void nes_control_port1_devices(device_slot_interface &device)
device.option_add("zapper", NES_ZAPPER);
device.option_add("4score_p1p3", NES_4SCORE_P1P3);
device.option_add("miracle_piano", NES_MIRACLE);
+ device.option_add("snes_adapter", NES_SNESADAPTER);
+ device.option_add("vboy", NES_VBOYCTRL);
}
void nes_control_port2_devices(device_slot_interface &device)
@@ -181,6 +199,13 @@ void nes_control_port2_devices(device_slot_interface &device)
device.option_add("vaus", NES_ARKPADDLE);
device.option_add("powerpad", NES_POWERPAD);
device.option_add("4score_p2p4", NES_4SCORE_P2P4);
+ device.option_add("snes_adapter", NES_SNESADAPTER);
+ device.option_add("vboy", NES_VBOYCTRL);
+}
+
+void nes_control_special_devices(device_slot_interface &device)
+{
+ device.option_add("rob", NES_ROB);
}
void fc_control_port1_devices(device_slot_interface &device)
@@ -198,28 +223,35 @@ void fc_control_port2_devices(device_slot_interface &device)
void fc_expansion_devices(device_slot_interface &device)
{
- device.option_add("joypad", NES_JOYPAD);
+ 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);
device.option_add("family_trainer", NES_FTRAINER);
+ device.option_add("konamibag", NES_KONAMIBAG);
device.option_add("konamihs", NES_KONAMIHS);
- device.option_add("mj_panel", NES_MJPANEL);
+ device.option_add("konami_piano", NES_DOREPIANO);
+ device.option_add("mahjong", NES_MJPANEL);
device.option_add("pachinko", NES_PACHINKO);
device.option_add("partytap", NES_PARTYTAP);
device.option_add("hori_twin", NES_HORITWIN);
device.option_add("hori_4p", NES_HORI4P);
device.option_add("barcode_battler", NES_BARCODE_BATTLER);
device.option_add("subor_keyboard", NES_SUBORKEYBOARD);
+ device.option_add("taptapmat", NES_TAPTAPMAT);
+ device.option_add("turbofile", NES_TURBOFILE);
}
-void majesco_control_port1_devices(device_slot_interface &device)
+void famibox_control_port12_devices(device_slot_interface &device)
{
- device.option_add("ddr", NES_VT_MAJESCO_DDR);
+ device.option_add("joypad", NES_JOYPAD);
+ device.option_add("zapper", NES_ZAPPER);
}
-void majesco_control_port2_devices(device_slot_interface &device)
+void famibox_control_port3_devices(device_slot_interface &device)
{
- // nothing?
+ device.option_add("zapper", NES_ZAPPER);
}
diff --git a/src/devices/bus/nes_ctrl/ctrl.h b/src/devices/bus/nes_ctrl/ctrl.h
index 0acefbf4654..3fb22995b3c 100644
--- a/src/devices/bus/nes_ctrl/ctrl.h
+++ b/src/devices/bus/nes_ctrl/ctrl.h
@@ -17,6 +17,8 @@
#pragma once
+#include "screen.h"
+
//**************************************************************************
// TYPE DEFINITIONS
@@ -26,47 +28,53 @@ class nes_control_port_device;
// ======================> device_nes_control_port_interface
-class device_nes_control_port_interface : public device_slot_card_interface
+class device_nes_control_port_interface : public device_interface
{
public:
// construction/destruction
virtual ~device_nes_control_port_interface();
- virtual uint8_t read_bit0() { return 0; }
- virtual uint8_t read_bit34() { return 0; }
- virtual uint8_t read_exp(offs_t offset) { return 0; }
- virtual void write(uint8_t data) { }
+ virtual u8 read_bit0() { return 0; }
+ virtual u8 read_bit2() { return 0; } // intended only for P2 microphone
+ virtual u8 read_bit34() { return 0; }
+ virtual u8 read_exp(offs_t offset) { return 0; }
+ virtual void write(u8 data) { }
protected:
device_nes_control_port_interface(const machine_config &mconfig, device_t &device);
+ // helper to keep track of strobe bit, returns true on 1 to 0 transitions
+ bool write_strobe(u8 data) { u8 prev = m_strobe; m_strobe = data & 1; return prev && !m_strobe; }
+
nes_control_port_device *m_port;
+ u8 m_strobe;
};
// ======================> nes_control_port_device
class nes_control_port_device : public device_t,
- public device_slot_interface
+ public device_single_card_slot_interface<device_nes_control_port_interface>
{
public:
// construction/destruction
template <typename T>
nes_control_port_device(machine_config const &mconfig, char const *tag, device_t *owner, T &&opts, char const *dflt)
- : nes_control_port_device(mconfig, tag, owner, (uint32_t)0)
+ : nes_control_port_device(mconfig, tag, owner, (u32)0)
{
option_reset();
opts(*this);
set_default_option(dflt);
set_fixed(false);
}
- nes_control_port_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
+ nes_control_port_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock);
virtual ~nes_control_port_device();
- uint8_t read_bit0();
- uint8_t read_bit34();
- uint8_t read_exp(offs_t offset);
- void write(uint8_t data);
+ u8 read_bit0();
+ u8 read_bit2();
+ u8 read_bit34();
+ u8 read_exp(offs_t offset);
+ void write(u8 data);
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
@@ -74,7 +82,7 @@ public:
protected:
// device-level overrides
- virtual void device_start() override;
+ virtual void device_start() override ATTR_COLD;
// devices
device_nes_control_port_interface *m_device;
@@ -86,11 +94,11 @@ DECLARE_DEVICE_TYPE(NES_CONTROL_PORT, nes_control_port_device)
void nes_control_port1_devices(device_slot_interface &device);
void nes_control_port2_devices(device_slot_interface &device);
+void nes_control_special_devices(device_slot_interface &device);
void fc_control_port1_devices(device_slot_interface &device);
void fc_control_port2_devices(device_slot_interface &device);
void fc_expansion_devices(device_slot_interface &device);
-void majesco_control_port1_devices(device_slot_interface &device);
-void majesco_control_port2_devices(device_slot_interface &device);
-
+void famibox_control_port12_devices(device_slot_interface &device);
+void famibox_control_port3_devices(device_slot_interface &device);
#endif // MAME_BUS_NES_CTRL_CTRL_H
diff --git a/src/devices/bus/nes_ctrl/dorepiano.cpp b/src/devices/bus/nes_ctrl/dorepiano.cpp
new file mode 100644
index 00000000000..6fd4179d2f0
--- /dev/null
+++ b/src/devices/bus/nes_ctrl/dorepiano.cpp
@@ -0,0 +1,158 @@
+// license:BSD-3-Clause
+// copyright-holders:kmg
+/**********************************************************************
+
+ Nintendo Family Computer Konami 'Doremikko' RJ250 Piano Keyboard
+
+**********************************************************************/
+
+#include "emu.h"
+#include "dorepiano.h"
+
+//**************************************************************************
+// DEVICE DEFINITIONS
+//**************************************************************************
+
+DEFINE_DEVICE_TYPE(NES_DOREPIANO, nes_dorepiano_device, "nes_dorepiano", "Konami 'Doremikko' Piano Keyboard")
+
+
+static INPUT_PORTS_START( nes_dorepiano )
+ PORT_START("PIANO.0")
+ PORT_BIT( 0x3f, IP_ACTIVE_HIGH, IPT_UNUSED )
+
+ PORT_START("PIANO.1")
+ PORT_BIT( 0x0f, IP_ACTIVE_HIGH, IPT_UNUSED )
+ PORT_BIT( 0x10, IP_ACTIVE_HIGH, IPT_KEYPAD ) PORT_NAME("Octave 0 F") PORT_CODE(KEYCODE_Z)
+ PORT_BIT( 0x20, IP_ACTIVE_HIGH, IPT_KEYPAD ) PORT_NAME("Octave 0 F#") PORT_CODE(KEYCODE_S)
+
+ PORT_START("PIANO.2")
+ PORT_BIT( 0x01, IP_ACTIVE_HIGH, IPT_KEYPAD ) PORT_NAME("Octave 0 G") PORT_CODE(KEYCODE_X)
+ PORT_BIT( 0x02, IP_ACTIVE_HIGH, IPT_KEYPAD ) PORT_NAME("Octave 0 G#") PORT_CODE(KEYCODE_D)
+ PORT_BIT( 0x04, IP_ACTIVE_HIGH, IPT_KEYPAD ) PORT_NAME("Octave 0 A") PORT_CODE(KEYCODE_C)
+ PORT_BIT( 0x08, IP_ACTIVE_HIGH, IPT_KEYPAD ) PORT_NAME("Octave 0 A#") PORT_CODE(KEYCODE_F)
+ PORT_BIT( 0x10, IP_ACTIVE_HIGH, IPT_KEYPAD ) PORT_NAME("Octave 0 B") PORT_CODE(KEYCODE_V)
+ PORT_BIT( 0x20, IP_ACTIVE_HIGH, IPT_KEYPAD ) PORT_NAME("Octave 0 C") PORT_CODE(KEYCODE_B)
+
+ PORT_START("PIANO.3")
+ PORT_BIT( 0x01, IP_ACTIVE_HIGH, IPT_KEYPAD ) PORT_NAME("Octave 0 C#") PORT_CODE(KEYCODE_H)
+ PORT_BIT( 0x02, IP_ACTIVE_HIGH, IPT_KEYPAD ) PORT_NAME("Octave 0 D") PORT_CODE(KEYCODE_N)
+ PORT_BIT( 0x04, IP_ACTIVE_HIGH, IPT_KEYPAD ) PORT_NAME("Octave 0 D#") PORT_CODE(KEYCODE_J)
+ PORT_BIT( 0x08, IP_ACTIVE_HIGH, IPT_KEYPAD ) PORT_NAME("Octave 0 E") PORT_CODE(KEYCODE_M)
+ PORT_BIT( 0x10, IP_ACTIVE_HIGH, IPT_KEYPAD ) PORT_NAME("Octave 1 F") PORT_CODE(KEYCODE_COMMA)
+ PORT_BIT( 0x20, IP_ACTIVE_HIGH, IPT_KEYPAD ) PORT_NAME("Octave 1 F#") PORT_CODE(KEYCODE_L)
+
+ PORT_START("PIANO.4")
+ PORT_BIT( 0x01, IP_ACTIVE_HIGH, IPT_KEYPAD ) PORT_NAME("Octave 1 G") PORT_CODE(KEYCODE_STOP)
+ PORT_BIT( 0x02, IP_ACTIVE_HIGH, IPT_KEYPAD ) PORT_NAME("Octave 1 G#") PORT_CODE(KEYCODE_COLON)
+ PORT_BIT( 0x04, IP_ACTIVE_HIGH, IPT_KEYPAD ) PORT_NAME("Octave 1 A") PORT_CODE(KEYCODE_SLASH)
+ PORT_BIT( 0x08, IP_ACTIVE_HIGH, IPT_KEYPAD ) PORT_NAME("Octave 1 A#") PORT_CODE(KEYCODE_QUOTE)
+ PORT_BIT( 0x10, IP_ACTIVE_HIGH, IPT_KEYPAD ) PORT_NAME("Octave 1 B") PORT_CODE(KEYCODE_Q)
+ PORT_BIT( 0x20, IP_ACTIVE_HIGH, IPT_KEYPAD ) PORT_NAME("Octave 1 C") PORT_CODE(KEYCODE_W)
+
+ PORT_START("PIANO.5")
+ PORT_BIT( 0x01, IP_ACTIVE_HIGH, IPT_KEYPAD ) PORT_NAME("Octave 1 C#") PORT_CODE(KEYCODE_3)
+ PORT_BIT( 0x02, IP_ACTIVE_HIGH, IPT_KEYPAD ) PORT_NAME("Octave 1 D") PORT_CODE(KEYCODE_E)
+ PORT_BIT( 0x04, IP_ACTIVE_HIGH, IPT_KEYPAD ) PORT_NAME("Octave 1 D#") PORT_CODE(KEYCODE_4)
+ PORT_BIT( 0x08, IP_ACTIVE_HIGH, IPT_KEYPAD ) PORT_NAME("Octave 1 E") PORT_CODE(KEYCODE_R)
+ PORT_BIT( 0x10, IP_ACTIVE_HIGH, IPT_KEYPAD ) PORT_NAME("Octave 2 F") PORT_CODE(KEYCODE_T)
+ PORT_BIT( 0x20, IP_ACTIVE_HIGH, IPT_KEYPAD ) PORT_NAME("Octave 2 F#") PORT_CODE(KEYCODE_6)
+
+ PORT_START("PIANO.6")
+ PORT_BIT( 0x01, IP_ACTIVE_HIGH, IPT_KEYPAD ) PORT_NAME("Octave 2 G") PORT_CODE(KEYCODE_Y)
+ PORT_BIT( 0x02, IP_ACTIVE_HIGH, IPT_KEYPAD ) PORT_NAME("Octave 2 G#") PORT_CODE(KEYCODE_7)
+ PORT_BIT( 0x04, IP_ACTIVE_HIGH, IPT_KEYPAD ) PORT_NAME("Octave 2 A") PORT_CODE(KEYCODE_U)
+ PORT_BIT( 0x08, IP_ACTIVE_HIGH, IPT_KEYPAD ) PORT_NAME("Octave 2 A#") PORT_CODE(KEYCODE_8)
+ PORT_BIT( 0x10, IP_ACTIVE_HIGH, IPT_KEYPAD ) PORT_NAME("Octave 2 B") PORT_CODE(KEYCODE_I)
+ PORT_BIT( 0x20, IP_ACTIVE_HIGH, IPT_KEYPAD ) PORT_NAME("Octave 2 C") PORT_CODE(KEYCODE_O)
+
+ PORT_START("PIANO.7")
+ PORT_BIT( 0x01, IP_ACTIVE_HIGH, IPT_KEYPAD ) PORT_NAME("Octave 2 C#") PORT_CODE(KEYCODE_0)
+ PORT_BIT( 0x02, IP_ACTIVE_HIGH, IPT_KEYPAD ) PORT_NAME("Octave 2 D") PORT_CODE(KEYCODE_OPENBRACE)
+ PORT_BIT( 0x04, IP_ACTIVE_HIGH, IPT_KEYPAD ) PORT_NAME("Octave 2 D#") PORT_CODE(KEYCODE_EQUALS)
+ PORT_BIT( 0x08, IP_ACTIVE_HIGH, IPT_KEYPAD ) PORT_NAME("Octave 2 E") PORT_CODE(KEYCODE_CLOSEBRACE)
+ PORT_BIT( 0x30, IP_ACTIVE_HIGH, IPT_UNUSED )
+INPUT_PORTS_END
+
+
+//-------------------------------------------------
+// input_ports - device-specific input ports
+//-------------------------------------------------
+
+ioport_constructor nes_dorepiano_device::device_input_ports() const
+{
+ return INPUT_PORTS_NAME( nes_dorepiano );
+}
+
+
+
+//**************************************************************************
+// LIVE DEVICE
+//**************************************************************************
+
+//-------------------------------------------------
+// nes_dorepiano_device - constructor
+//-------------------------------------------------
+
+nes_dorepiano_device::nes_dorepiano_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock)
+ : device_t(mconfig, NES_DOREPIANO, tag, owner, clock)
+ , device_nes_control_port_interface(mconfig, *this)
+ , m_port(*this, "PIANO.%u", 0)
+ , m_cur_port(0)
+ , m_latch(0)
+ , m_mask(0)
+{
+}
+
+
+//-------------------------------------------------
+// device_start
+//-------------------------------------------------
+
+void nes_dorepiano_device::device_start()
+{
+ save_item(NAME(m_cur_port));
+ save_item(NAME(m_latch));
+ save_item(NAME(m_mask));
+
+ m_mask = 0x0f;
+}
+
+
+//-------------------------------------------------
+// read
+//-------------------------------------------------
+
+u8 nes_dorepiano_device::read_exp(offs_t offset)
+{
+ u8 ret = 0;
+
+ if (offset == 1) // $4017
+ {
+ ret = m_port[m_cur_port]->read() & m_mask;
+ m_mask = ~m_mask;
+ ret >>= m_mask & 0x04;
+ ret <<= 1;
+ }
+
+ return ret;
+}
+
+//-------------------------------------------------
+// write
+//-------------------------------------------------
+
+void nes_dorepiano_device::write(u8 data)
+{
+ if (BIT(data, 1))
+ {
+ m_cur_port = 0;
+ m_mask = 0x0f;
+ }
+ else if (BIT(data, 0) && !BIT(m_latch, 0))
+ {
+ m_cur_port = (m_cur_port + 1) & 0x07;
+ m_mask = 0x0f;
+ }
+
+ m_latch = data;
+}
diff --git a/src/devices/bus/nes_ctrl/dorepiano.h b/src/devices/bus/nes_ctrl/dorepiano.h
new file mode 100644
index 00000000000..41d2ef2860d
--- /dev/null
+++ b/src/devices/bus/nes_ctrl/dorepiano.h
@@ -0,0 +1,50 @@
+// license:BSD-3-Clause
+// copyright-holders:kmg
+/**********************************************************************
+
+ Nintendo Family Computer Konami 'Doremikko' RJ250 Piano Keyboard
+
+**********************************************************************/
+
+#ifndef MAME_BUS_NES_CTRL_DOREPIANO_H
+#define MAME_BUS_NES_CTRL_DOREPIANO_H
+
+#pragma once
+
+#include "ctrl.h"
+
+
+//**************************************************************************
+// TYPE DEFINITIONS
+//**************************************************************************
+
+// ======================> nes_dorepiano_device
+
+class nes_dorepiano_device :
+ public device_t,
+ public device_nes_control_port_interface
+{
+public:
+ // construction/destruction
+ nes_dorepiano_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 ATTR_COLD;
+ virtual ioport_constructor device_input_ports() const override ATTR_COLD;
+
+private:
+ required_ioport_array<8> m_port;
+ u8 m_cur_port;
+ u8 m_latch;
+ u8 m_mask;
+};
+
+
+// device type definition
+DECLARE_DEVICE_TYPE(NES_DOREPIANO, nes_dorepiano_device)
+
+#endif // MAME_BUS_NES_CTRL_DOREPIANO_H
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 85bf0c2f83f..623c7022d09 100644
--- a/src/devices/bus/nes_ctrl/fckeybrd.h
+++ b/src/devices/bus/nes_ctrl/fckeybrd.h
@@ -2,12 +2,12 @@
// copyright-holders:Fabio Priuli
/**********************************************************************
- Nintendo Family Computer Keyboard Component
+ Nintendo Family Computer Keyboard HVC-007 and Data Recorder HVC-008
**********************************************************************/
-#ifndef MAME_BUS_NES_CTRL_FCKEYBOARD_H
-#define MAME_BUS_NES_CTRL_FCKEYBOARD_H
+#ifndef MAME_BUS_NES_CTRL_FCKEYBRD_H
+#define MAME_BUS_NES_CTRL_FCKEYBRD_H
#pragma once
@@ -26,28 +26,26 @@ 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 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;
+ virtual void device_start() override ATTR_COLD;
- virtual uint8_t read_exp(offs_t offset) override;
- virtual void write(uint8_t data) override;
+ virtual ioport_constructor device_input_ports() const override ATTR_COLD;
+ virtual void device_add_mconfig(machine_config &config) override ATTR_COLD;
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;
};
// device type definition
DECLARE_DEVICE_TYPE(NES_FCKEYBOARD, nes_fckeybrd_device)
-
-#endif // MAME_BUS_NES_CTRL_FCKEYBOARD_H
+#endif // MAME_BUS_NES_CTRL_FCKEYBRD_H
diff --git a/src/devices/bus/nes_ctrl/fcmat.cpp b/src/devices/bus/nes_ctrl/fcmat.cpp
new file mode 100644
index 00000000000..f40bb9df48a
--- /dev/null
+++ b/src/devices/bus/nes_ctrl/fcmat.cpp
@@ -0,0 +1,177 @@
+// license:BSD-3-Clause
+// copyright-holders:kmg, Fabio Priuli
+/**********************************************************************
+
+ Here we emulate two distinct mat controllers which share a common
+ read/write interface with the hardware:
+
+ Nintendo Family Computer - Bandai Family Trainer Mat
+ Nintendo Family Computer - IGS Tap-tap Mat
+
+**********************************************************************/
+
+#include "emu.h"
+#include "fcmat.h"
+
+//**************************************************************************
+// DEVICE DEFINITIONS
+//**************************************************************************
+
+DEFINE_DEVICE_TYPE(NES_FTRAINER, nes_ftrainer_device, "nes_famtrain", "Bandai Family Trainer")
+DEFINE_DEVICE_TYPE(NES_TAPTAPMAT, nes_taptapmat_device, "nes_taptapmat", "IGS Tap-tap Mat")
+
+
+static INPUT_PORTS_START( nes_ftrainer )
+ PORT_START("LAYOUT")
+ PORT_CONFNAME( 0x01, 0x00, "Family Trainer Button Layout")
+ PORT_CONFSETTING( 0x00, "Side A" )
+ PORT_CONFSETTING( 0x01, "Side B" )
+
+ // difference between the two sides is that we mirror the key mapping to match the real pad layout!
+ PORT_START("MAT_COL.0")
+ // side A layout
+ PORT_BIT( 0x01, IP_ACTIVE_HIGH, IPT_UNUSED ) PORT_CONDITION("LAYOUT", 0x01, EQUALS, 0x00)
+ PORT_BIT( 0x02, IP_ACTIVE_HIGH, IPT_BUTTON8 ) PORT_NAME("Family Trainer Mid1") PORT_CODE(KEYCODE_F) PORT_CONDITION("LAYOUT", 0x01, EQUALS, 0x00)
+ PORT_BIT( 0x04, IP_ACTIVE_HIGH, IPT_UNUSED ) PORT_CONDITION("LAYOUT", 0x01, EQUALS, 0x00)
+ // side B layout
+ PORT_BIT( 0x01, IP_ACTIVE_HIGH, IPT_BUTTON12 ) PORT_NAME("Family Trainer 12") PORT_CODE(KEYCODE_M) PORT_CONDITION("LAYOUT", 0x01, EQUALS, 0x01)
+ PORT_BIT( 0x02, IP_ACTIVE_HIGH, IPT_BUTTON8 ) PORT_NAME("Family Trainer 8") PORT_CODE(KEYCODE_J) PORT_CONDITION("LAYOUT", 0x01, EQUALS, 0x01)
+ PORT_BIT( 0x04, IP_ACTIVE_HIGH, IPT_BUTTON4 ) PORT_NAME("Family Trainer 4") PORT_CODE(KEYCODE_U) PORT_CONDITION("LAYOUT", 0x01, EQUALS, 0x01)
+
+ PORT_START("MAT_COL.1")
+ // side A layout
+ PORT_BIT( 0x01, IP_ACTIVE_HIGH, IPT_BUTTON11 ) PORT_NAME("Family Trainer Low1") PORT_CODE(KEYCODE_B) PORT_CONDITION("LAYOUT", 0x01, EQUALS, 0x00)
+ PORT_BIT( 0x02, IP_ACTIVE_HIGH, IPT_BUTTON7 ) PORT_NAME("Family Trainer Mid2") PORT_CODE(KEYCODE_G) PORT_CONDITION("LAYOUT", 0x01, EQUALS, 0x00)
+ PORT_BIT( 0x04, IP_ACTIVE_HIGH, IPT_BUTTON3 ) PORT_NAME("Family Trainer Top1") PORT_CODE(KEYCODE_T) PORT_CONDITION("LAYOUT", 0x01, EQUALS, 0x00)
+ // side B layout
+ PORT_BIT( 0x01, IP_ACTIVE_HIGH, IPT_BUTTON11 ) PORT_NAME("Family Trainer 11") PORT_CODE(KEYCODE_N) PORT_CONDITION("LAYOUT", 0x01, EQUALS, 0x01)
+ PORT_BIT( 0x02, IP_ACTIVE_HIGH, IPT_BUTTON7 ) PORT_NAME("Family Trainer 7") PORT_CODE(KEYCODE_H) PORT_CONDITION("LAYOUT", 0x01, EQUALS, 0x01)
+ PORT_BIT( 0x04, IP_ACTIVE_HIGH, IPT_BUTTON3 ) PORT_NAME("Family Trainer 3") PORT_CODE(KEYCODE_Y) PORT_CONDITION("LAYOUT", 0x01, EQUALS, 0x01)
+
+ PORT_START("MAT_COL.2")
+ // side A layout
+ PORT_BIT( 0x01, IP_ACTIVE_HIGH, IPT_BUTTON10 ) PORT_NAME("Family Trainer Low2") PORT_CODE(KEYCODE_N) PORT_CONDITION("LAYOUT", 0x01, EQUALS, 0x00)
+ PORT_BIT( 0x02, IP_ACTIVE_HIGH, IPT_BUTTON6 ) PORT_NAME("Family Trainer Mid3") PORT_CODE(KEYCODE_H) PORT_CONDITION("LAYOUT", 0x01, EQUALS, 0x00)
+ PORT_BIT( 0x04, IP_ACTIVE_HIGH, IPT_BUTTON2 ) PORT_NAME("Family Trainer Top2") PORT_CODE(KEYCODE_Y) PORT_CONDITION("LAYOUT", 0x01, EQUALS, 0x00)
+ // side B layout
+ PORT_BIT( 0x01, IP_ACTIVE_HIGH, IPT_BUTTON10 ) PORT_NAME("Family Trainer 10") PORT_CODE(KEYCODE_B) PORT_CONDITION("LAYOUT", 0x01, EQUALS, 0x01)
+ PORT_BIT( 0x02, IP_ACTIVE_HIGH, IPT_BUTTON6 ) PORT_NAME("Family Trainer 6") PORT_CODE(KEYCODE_G) PORT_CONDITION("LAYOUT", 0x01, EQUALS, 0x01)
+ PORT_BIT( 0x04, IP_ACTIVE_HIGH, IPT_BUTTON2 ) PORT_NAME("Family Trainer 2") PORT_CODE(KEYCODE_T) PORT_CONDITION("LAYOUT", 0x01, EQUALS, 0x01)
+
+ PORT_START("MAT_COL.3")
+ // side A layout
+ PORT_BIT( 0x01, IP_ACTIVE_HIGH, IPT_UNUSED ) PORT_CONDITION("LAYOUT", 0x01, EQUALS, 0x00)
+ PORT_BIT( 0x02, IP_ACTIVE_HIGH, IPT_BUTTON5 ) PORT_NAME("Family Trainer Mid4") PORT_CODE(KEYCODE_J) PORT_CONDITION("LAYOUT", 0x01, EQUALS, 0x00)
+ PORT_BIT( 0x04, IP_ACTIVE_HIGH, IPT_UNUSED ) PORT_CONDITION("LAYOUT", 0x01, EQUALS, 0x00)
+ // side B layout
+ PORT_BIT( 0x01, IP_ACTIVE_HIGH, IPT_BUTTON9 ) PORT_NAME("Family Trainer 9") PORT_CODE(KEYCODE_V) PORT_CONDITION("LAYOUT", 0x01, EQUALS, 0x01)
+ PORT_BIT( 0x02, IP_ACTIVE_HIGH, IPT_BUTTON5 ) PORT_NAME("Family Trainer 5") PORT_CODE(KEYCODE_F) PORT_CONDITION("LAYOUT", 0x01, EQUALS, 0x01)
+ PORT_BIT( 0x04, IP_ACTIVE_HIGH, IPT_BUTTON1 ) PORT_NAME("Family Trainer 1") PORT_CODE(KEYCODE_R) PORT_CONDITION("LAYOUT", 0x01, EQUALS, 0x01)
+INPUT_PORTS_END
+
+
+static INPUT_PORTS_START( nes_taptapmat )
+ PORT_START("MAT_COL.0")
+ PORT_BIT( 0x01, IP_ACTIVE_HIGH, IPT_BUTTON12 ) PORT_NAME("Bottom Left (Frankenstein)") PORT_CODE(KEYCODE_V)
+ PORT_BIT( 0x02, IP_ACTIVE_HIGH, IPT_BUTTON8 ) PORT_NAME("Middle Left (Bang!)") PORT_CODE(KEYCODE_F)
+ PORT_BIT( 0x04, IP_ACTIVE_HIGH, IPT_BUTTON4 ) PORT_NAME("Top Left (Antlion)") PORT_CODE(KEYCODE_R)
+
+ PORT_START("MAT_COL.1")
+ PORT_BIT( 0x01, IP_ACTIVE_HIGH, IPT_BUTTON11 ) PORT_NAME("Bottom Mid-Left (Bang!)") PORT_CODE(KEYCODE_B)
+ PORT_BIT( 0x02, IP_ACTIVE_HIGH, IPT_BUTTON7 ) PORT_NAME("Middle Mid-Left (Caveman)") PORT_CODE(KEYCODE_G)
+ PORT_BIT( 0x04, IP_ACTIVE_HIGH, IPT_BUTTON3 ) PORT_NAME("Top Mid-Left (Bang!)") PORT_CODE(KEYCODE_T)
+
+ PORT_START("MAT_COL.2")
+ PORT_BIT( 0x01, IP_ACTIVE_HIGH, IPT_BUTTON10 ) PORT_NAME("Bottom Mid-Right (Shark)") PORT_CODE(KEYCODE_N)
+ PORT_BIT( 0x02, IP_ACTIVE_HIGH, IPT_BUTTON6 ) PORT_NAME("Middle Mid-Right (Bang!)") PORT_CODE(KEYCODE_H)
+ PORT_BIT( 0x04, IP_ACTIVE_HIGH, IPT_BUTTON2 ) PORT_NAME("Top Mid-Right (Dinosaur)") PORT_CODE(KEYCODE_Y)
+
+ PORT_START("MAT_COL.3")
+ PORT_BIT( 0x01, IP_ACTIVE_HIGH, IPT_BUTTON9 ) PORT_NAME("Bottom Right (Bang!)") PORT_CODE(KEYCODE_M)
+ PORT_BIT( 0x02, IP_ACTIVE_HIGH, IPT_BUTTON5 ) PORT_NAME("Middle Right (Mole)") PORT_CODE(KEYCODE_J)
+ PORT_BIT( 0x04, IP_ACTIVE_HIGH, IPT_BUTTON1 ) PORT_NAME("Top Right (Bang!)") PORT_CODE(KEYCODE_U)
+INPUT_PORTS_END
+
+
+//-------------------------------------------------
+// input_ports - device-specific input ports
+//-------------------------------------------------
+
+ioport_constructor nes_ftrainer_device::device_input_ports() const
+{
+ return INPUT_PORTS_NAME( nes_ftrainer );
+}
+
+ioport_constructor nes_taptapmat_device::device_input_ports() const
+{
+ return INPUT_PORTS_NAME( nes_taptapmat );
+}
+
+
+
+//**************************************************************************
+// LIVE DEVICE
+//**************************************************************************
+
+//-------------------------------------------------
+// constructor
+//-------------------------------------------------
+
+nes_fcmat_device::nes_fcmat_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, u32 clock)
+ : device_t(mconfig, type, tag, owner, clock)
+ , device_nes_control_port_interface(mconfig, *this)
+ , m_mat(*this, "MAT_COL.%u", 0)
+ , m_row_scan(0)
+{
+}
+
+nes_ftrainer_device::nes_ftrainer_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock)
+ : nes_fcmat_device(mconfig, NES_FTRAINER, tag, owner, clock)
+{
+}
+
+nes_taptapmat_device::nes_taptapmat_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock)
+ : nes_fcmat_device(mconfig, NES_TAPTAPMAT, tag, owner, clock)
+{
+}
+
+
+//-------------------------------------------------
+// device_start
+//-------------------------------------------------
+
+void nes_fcmat_device::device_start()
+{
+ save_item(NAME(m_row_scan));
+}
+
+
+//-------------------------------------------------
+// read
+//-------------------------------------------------
+
+u8 nes_fcmat_device::read_exp(offs_t offset)
+{
+ u8 ret = 0;
+
+ if (offset == 1) // $4017
+ {
+ for (int row = 0; row < 3; row++) // bottom row first (buttons 9,10,11,12 on Family Trainer)
+ if (!BIT(m_row_scan, row))
+ for (int col = 0; col < 4; col++) // left column first (Family Trainer side A and Tap-tap Mat)
+ ret |= BIT(m_mat[col]->read(), row) << (col + 1);
+ ret = ~ret & 0x1e; // 0: pressed, 1: not pressed
+ }
+
+ return ret;
+}
+
+//-------------------------------------------------
+// write
+//-------------------------------------------------
+
+void nes_fcmat_device::write(u8 data)
+{
+ // select row to scan
+ m_row_scan = data & 0x07;
+}
diff --git a/src/devices/bus/nes_ctrl/fcmat.h b/src/devices/bus/nes_ctrl/fcmat.h
new file mode 100644
index 00000000000..70e65a3318f
--- /dev/null
+++ b/src/devices/bus/nes_ctrl/fcmat.h
@@ -0,0 +1,77 @@
+// license:BSD-3-Clause
+// copyright-holders:kmg, Fabio Priuli
+/**********************************************************************
+
+ Nintendo Family Computer - Bandai Family Trainer Mat
+ Nintendo Family Computer - IGS Tap-tap Mat
+
+**********************************************************************/
+
+#ifndef MAME_BUS_NES_CTRL_FCMAT_H
+#define MAME_BUS_NES_CTRL_FCMAT_H
+
+#pragma once
+
+#include "ctrl.h"
+
+
+//**************************************************************************
+// TYPE DEFINITIONS
+//**************************************************************************
+
+// ======================> nes_fcmat_device
+
+class nes_fcmat_device :
+ public device_t,
+ public device_nes_control_port_interface
+{
+public:
+ virtual u8 read_exp(offs_t offset) override;
+ virtual void write(u8 data) override;
+
+protected:
+ // construction/destruction
+ nes_fcmat_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, u32 clock);
+
+ // device-level overrides
+ virtual void device_start() override ATTR_COLD;
+
+private:
+ required_ioport_array<4> m_mat;
+ u8 m_row_scan;
+};
+
+
+// ======================> nes_ftrainer_device
+
+class nes_ftrainer_device : public nes_fcmat_device
+{
+public:
+ // construction/destruction
+ nes_ftrainer_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock);
+
+protected:
+ // device-level overrides
+ virtual ioport_constructor device_input_ports() const override ATTR_COLD;
+};
+
+
+// ======================> nes_taptapmat_device
+
+class nes_taptapmat_device : public nes_fcmat_device
+{
+public:
+ // construction/destruction
+ nes_taptapmat_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock);
+
+protected:
+ // device-level overrides
+ virtual ioport_constructor device_input_ports() const override ATTR_COLD;
+};
+
+
+// device type definition
+DECLARE_DEVICE_TYPE(NES_FTRAINER, nes_ftrainer_device)
+DECLARE_DEVICE_TYPE(NES_TAPTAPMAT, nes_taptapmat_device)
+
+#endif // MAME_BUS_NES_CTRL_FCMAT_H
diff --git a/src/devices/bus/nes_ctrl/ftrainer.cpp b/src/devices/bus/nes_ctrl/ftrainer.cpp
deleted file mode 100644
index 06f4aaf4f3c..00000000000
--- a/src/devices/bus/nes_ctrl/ftrainer.cpp
+++ /dev/null
@@ -1,155 +0,0 @@
-// license:BSD-3-Clause
-// copyright-holders:Fabio Priuli
-/**********************************************************************
-
- Nintendo Family Computer - Bandai Family Trainer Mat
-
-**********************************************************************/
-
-#include "emu.h"
-#include "ftrainer.h"
-
-//**************************************************************************
-// DEVICE DEFINITIONS
-//**************************************************************************
-
-DEFINE_DEVICE_TYPE(NES_FTRAINER, nes_ftrainer_device, "nes_famtrain", "Bandai Family Trainer")
-
-
-static INPUT_PORTS_START( nes_joypad )
- PORT_START("LAYOUT")
- PORT_CONFNAME( 0x01, 0x00, "Family Trainer Button Layout")
- PORT_CONFSETTING( 0x00, "Side A" )
- PORT_CONFSETTING( 0x01, "Side B" )
-
- // difference between the two sides is that we mirror the key mapping to match the real pad layout!
- PORT_START("FT_COL.0")
- // side A layout
- PORT_BIT( 0x01, IP_ACTIVE_HIGH, IPT_UNUSED ) PORT_CONDITION("LAYOUT", 0x01, EQUALS, 0x00)
- PORT_BIT( 0x02, IP_ACTIVE_HIGH, IPT_KEYPAD ) PORT_NAME("Family Trainer Mid1") PORT_CODE(KEYCODE_J) PORT_CONDITION("LAYOUT", 0x01, EQUALS, 0x00)
- PORT_BIT( 0x04, IP_ACTIVE_HIGH, IPT_UNUSED ) PORT_CONDITION("LAYOUT", 0x01, EQUALS, 0x00)
- // side B layout
- PORT_BIT( 0x01, IP_ACTIVE_HIGH, IPT_KEYPAD ) PORT_NAME("Family Trainer 12") PORT_CODE(KEYCODE_M) PORT_CONDITION("LAYOUT", 0x01, EQUALS, 0x01)
- PORT_BIT( 0x02, IP_ACTIVE_HIGH, IPT_KEYPAD ) PORT_NAME("Family Trainer 8") PORT_CODE(KEYCODE_J) PORT_CONDITION("LAYOUT", 0x01, EQUALS, 0x01)
- PORT_BIT( 0x04, IP_ACTIVE_HIGH, IPT_KEYPAD ) PORT_NAME("Family Trainer 4") PORT_CODE(KEYCODE_U) PORT_CONDITION("LAYOUT", 0x01, EQUALS, 0x01)
-
- PORT_START("FT_COL.1")
- // side A layout
- PORT_BIT( 0x01, IP_ACTIVE_HIGH, IPT_KEYPAD ) PORT_NAME("Family Trainer Low1") PORT_CODE(KEYCODE_N) PORT_CONDITION("LAYOUT", 0x01, EQUALS, 0x00)
- PORT_BIT( 0x02, IP_ACTIVE_HIGH, IPT_KEYPAD ) PORT_NAME("Family Trainer Mid2") PORT_CODE(KEYCODE_H) PORT_CONDITION("LAYOUT", 0x01, EQUALS, 0x00)
- PORT_BIT( 0x04, IP_ACTIVE_HIGH, IPT_KEYPAD ) PORT_NAME("Family Trainer Top1") PORT_CODE(KEYCODE_Y) PORT_CONDITION("LAYOUT", 0x01, EQUALS, 0x00)
- // side B layout
- PORT_BIT( 0x01, IP_ACTIVE_HIGH, IPT_KEYPAD ) PORT_NAME("Family Trainer 11") PORT_CODE(KEYCODE_N) PORT_CONDITION("LAYOUT", 0x01, EQUALS, 0x01)
- PORT_BIT( 0x02, IP_ACTIVE_HIGH, IPT_KEYPAD ) PORT_NAME("Family Trainer 7") PORT_CODE(KEYCODE_H) PORT_CONDITION("LAYOUT", 0x01, EQUALS, 0x01)
- PORT_BIT( 0x04, IP_ACTIVE_HIGH, IPT_KEYPAD ) PORT_NAME("Family Trainer 3") PORT_CODE(KEYCODE_Y) PORT_CONDITION("LAYOUT", 0x01, EQUALS, 0x01)
-
- PORT_START("FT_COL.2")
- // side A layout
- PORT_BIT( 0x01, IP_ACTIVE_HIGH, IPT_KEYPAD ) PORT_NAME("Family Trainer Low2") PORT_CODE(KEYCODE_B) PORT_CONDITION("LAYOUT", 0x01, EQUALS, 0x00)
- PORT_BIT( 0x02, IP_ACTIVE_HIGH, IPT_KEYPAD ) PORT_NAME("Family Trainer Mid3") PORT_CODE(KEYCODE_G) PORT_CONDITION("LAYOUT", 0x01, EQUALS, 0x00)
- PORT_BIT( 0x04, IP_ACTIVE_HIGH, IPT_KEYPAD ) PORT_NAME("Family Trainer Top2") PORT_CODE(KEYCODE_T) PORT_CONDITION("LAYOUT", 0x01, EQUALS, 0x00)
- // side B layout
- PORT_BIT( 0x01, IP_ACTIVE_HIGH, IPT_KEYPAD ) PORT_NAME("Family Trainer 10") PORT_CODE(KEYCODE_B) PORT_CONDITION("LAYOUT", 0x01, EQUALS, 0x01)
- PORT_BIT( 0x02, IP_ACTIVE_HIGH, IPT_KEYPAD ) PORT_NAME("Family Trainer 6") PORT_CODE(KEYCODE_G) PORT_CONDITION("LAYOUT", 0x01, EQUALS, 0x01)
- PORT_BIT( 0x04, IP_ACTIVE_HIGH, IPT_KEYPAD ) PORT_NAME("Family Trainer 2") PORT_CODE(KEYCODE_T) PORT_CONDITION("LAYOUT", 0x01, EQUALS, 0x01)
-
- PORT_START("FT_COL.3")
- // side A layout
- PORT_BIT( 0x01, IP_ACTIVE_HIGH, IPT_UNUSED ) PORT_CONDITION("LAYOUT", 0x01, EQUALS, 0x00)
- PORT_BIT( 0x02, IP_ACTIVE_HIGH, IPT_KEYPAD ) PORT_NAME("Family Trainer Mid4") PORT_CODE(KEYCODE_F) PORT_CONDITION("LAYOUT", 0x01, EQUALS, 0x00)
- PORT_BIT( 0x04, IP_ACTIVE_HIGH, IPT_UNUSED ) PORT_CONDITION("LAYOUT", 0x01, EQUALS, 0x00)
- // side B layout
- PORT_BIT( 0x01, IP_ACTIVE_HIGH, IPT_KEYPAD ) PORT_NAME("Family Trainer 9") PORT_CODE(KEYCODE_V) PORT_CONDITION("LAYOUT", 0x01, EQUALS, 0x01)
- PORT_BIT( 0x02, IP_ACTIVE_HIGH, IPT_KEYPAD ) PORT_NAME("Family Trainer 5") PORT_CODE(KEYCODE_F) PORT_CONDITION("LAYOUT", 0x01, EQUALS, 0x01)
- PORT_BIT( 0x04, IP_ACTIVE_HIGH, IPT_KEYPAD ) PORT_NAME("Family Trainer 1") PORT_CODE(KEYCODE_R) PORT_CONDITION("LAYOUT", 0x01, EQUALS, 0x01)
-INPUT_PORTS_END
-
-
-//-------------------------------------------------
-// input_ports - device-specific input ports
-//-------------------------------------------------
-
-ioport_constructor nes_ftrainer_device::device_input_ports() const
-{
- return INPUT_PORTS_NAME( nes_joypad );
-}
-
-
-
-//**************************************************************************
-// LIVE DEVICE
-//**************************************************************************
-
-//-------------------------------------------------
-// nes_ftrainer_device - constructor
-//-------------------------------------------------
-
-nes_ftrainer_device::nes_ftrainer_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
- : device_t(mconfig, NES_FTRAINER, tag, owner, clock)
- , device_nes_control_port_interface(mconfig, *this)
- , m_trainer(*this, "FT_COL.%u", 0)
- , m_row_scan(0)
-{
-}
-
-
-//-------------------------------------------------
-// device_start
-//-------------------------------------------------
-
-void nes_ftrainer_device::device_start()
-{
- save_item(NAME(m_row_scan));
-}
-
-
-//-------------------------------------------------
-// device_reset
-//-------------------------------------------------
-
-void nes_ftrainer_device::device_reset()
-{
- m_row_scan = 0;
-}
-
-
-//-------------------------------------------------
-// read
-//-------------------------------------------------
-
-uint8_t nes_ftrainer_device::read_exp(offs_t offset)
-{
- uint8_t ret = 0;
- if (offset == 1) //$4017
- {
- if (!BIT(m_row_scan, 0))
- {
- // read low line: buttons 9,10,11,12
- for (int i = 0; i < 4; i++)
- ret |= ((m_trainer[i]->read() & 0x01) << (1 + i));
- }
- else if (!BIT(m_row_scan, 1))
- {
- // read mid line: buttons 5,6,7,8
- for (int i = 0; i < 4; i++)
- ret |= ((m_trainer[i]->read() & 0x02) << (1 + i));
- }
- else if (!BIT(m_row_scan, 2))
- {
- // read high line: buttons 1,2,3,4
- for (int i = 0; i < 4; i++)
- ret |= ((m_trainer[i]->read() & 0x04) << (1 + i));
- }
- }
- return ret;
-}
-
-//-------------------------------------------------
-// write
-//-------------------------------------------------
-
-void nes_ftrainer_device::write(uint8_t data)
-{
- // select row to scan
- m_row_scan = data & 0x07;
-}
diff --git a/src/devices/bus/nes_ctrl/ftrainer.h b/src/devices/bus/nes_ctrl/ftrainer.h
deleted file mode 100644
index d72077c93a2..00000000000
--- a/src/devices/bus/nes_ctrl/ftrainer.h
+++ /dev/null
@@ -1,50 +0,0 @@
-// license:BSD-3-Clause
-// copyright-holders:Fabio Priuli
-/**********************************************************************
-
- Nintendo Family Computer - Bandai Family Trainer Mat
-
-**********************************************************************/
-
-#ifndef MAME_BUS_NES_CTRL_FTRAINER_H
-#define MAME_BUS_NES_CTRL_FTRAINER_H
-
-#pragma once
-
-#include "ctrl.h"
-
-
-//**************************************************************************
-// TYPE DEFINITIONS
-//**************************************************************************
-
-// ======================> nes_ftrainer_device
-
-class nes_ftrainer_device : public device_t,
- public device_nes_control_port_interface
-{
-public:
- // construction/destruction
- nes_ftrainer_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
-
- virtual ioport_constructor device_input_ports() const override;
-
-protected:
- // device-level overrides
- virtual void device_start() override;
- virtual void device_reset() override;
-
- virtual uint8_t read_exp(offs_t offset) override;
- virtual void write(uint8_t data) override;
-
-private:
- required_ioport_array<4> m_trainer;
- uint8_t m_row_scan;
-};
-
-
-// device type definition
-DECLARE_DEVICE_TYPE(NES_FTRAINER, nes_ftrainer_device)
-
-
-#endif // MAME_BUS_NES_CTRL_FTRAINER_H
diff --git a/src/devices/bus/nes_ctrl/hori.cpp b/src/devices/bus/nes_ctrl/hori.cpp
index 5c4f33c8ca9..7b1351af3fd 100644
--- a/src/devices/bus/nes_ctrl/hori.cpp
+++ b/src/devices/bus/nes_ctrl/hori.cpp
@@ -2,20 +2,25 @@
// copyright-holders:Fabio Priuli
/**********************************************************************
- Nintendo Family Computer Hori Twin (and 4P?) adapters
-
- Emulation of the 4Players adapter is quite pointless: if 2P mode
- (default mode) it behaves like a Hori Twin adapter, in 4P mode
- it has P1 and P2 inputs overwriting the inputs coming from the
- main controllers (possibly creating a bit of confusion, since
- you get 6 sets of inputs with only 4 acknowledged by the running
- system).
- For the moment we keep it available for documentation purposes.
-
- TODO: find out confirmation whether in 2P mode, inputs from joypads
- connected to the 4players adapter are really seen as P3 and P4 inputs.
- it seems the most reasonable setup (so that users with only 2
- external pads can use the adapter in 4P games), but one never knows...
+ Nintendo Family Computer Hori Twin and 4 Players adapters
+
+ In general these adapters work by reading pin 13 (the Famicom sees
+ this in memory location $4016, bit 1) of their subports. Other
+ input pins are not connected so various specialty controllers are
+ incompatible with these adapters.
+
+ The Hori Twin passes subport 1's input directly through to $4016
+ bit 1. It reroutes subport 2's to $4017 bit 1. Incidentally, HAL
+ released a device, Joypair, that should be functionally equivalent
+ to the Hori Twin.
+
+ The Hori 4 Players adapter has a 2/4 switch. In 2P mode it works
+ just like the Hori Twin. In 4P mode it still passes through joypad
+ reads to bit 1 of $4016 and $4017, but it operates like the NES Four
+ Score (which in fact uses a Hori PCB). Subport 1 then subport 3
+ inputs are passed serially to $4016 bit 1. Likewise subport 2 and 4
+ go to $4017 bit 1. A signature byte can be read from both locations
+ following this.
**********************************************************************/
@@ -28,7 +33,7 @@
//**************************************************************************
DEFINE_DEVICE_TYPE(NES_HORITWIN, nes_horitwin_device, "nes_horitwin", "FC Hori Twin Adapter")
-DEFINE_DEVICE_TYPE(NES_HORI4P, nes_hori4p_device, "nes_hori4p", "FC Hori 4P Adapter")
+DEFINE_DEVICE_TYPE(NES_HORI4P, nes_hori4p_device, "nes_hori4p", "FC Hori 4 Players Adaptor")
static INPUT_PORTS_START( nes_hori4p )
@@ -51,7 +56,7 @@ ioport_constructor nes_hori4p_device::device_input_ports() const
static void hori_adapter(device_slot_interface &device)
{
- device.option_add("joypad", NES_JOYPAD);
+ device.option_add("joypad", NES_FCPAD_EXP);
}
@@ -61,27 +66,21 @@ static void hori_adapter(device_slot_interface &device)
void nes_horitwin_device::device_add_mconfig(machine_config &config)
{
- NES_CONTROL_PORT(config, m_port1, hori_adapter, "joypad");
- NES_CONTROL_PORT(config, m_port2, hori_adapter, "joypad");
- if (m_port != nullptr)
+ for (int i = 0; i < 2; i++)
{
- m_port1->set_screen_tag(m_port->m_screen);
- m_port2->set_screen_tag(m_port->m_screen);
+ NES_CONTROL_PORT(config, m_subexp[i], hori_adapter, "joypad");
+ if (m_port != nullptr)
+ m_subexp[i]->set_screen_tag(m_port->m_screen);
}
}
void nes_hori4p_device::device_add_mconfig(machine_config &config)
{
- NES_CONTROL_PORT(config, m_port1, hori_adapter, "joypad");
- NES_CONTROL_PORT(config, m_port2, hori_adapter, "joypad");
- NES_CONTROL_PORT(config, m_port3, hori_adapter, "joypad");
- NES_CONTROL_PORT(config, m_port4, hori_adapter, "joypad");
- if (m_port != nullptr)
+ for (int i = 0; i < 4; i++)
{
- m_port1->set_screen_tag(m_port->m_screen);
- m_port2->set_screen_tag(m_port->m_screen);
- m_port3->set_screen_tag(m_port->m_screen);
- m_port4->set_screen_tag(m_port->m_screen);
+ NES_CONTROL_PORT(config, m_subexp[i], hori_adapter, "joypad");
+ if (m_port != nullptr)
+ m_subexp[i]->set_screen_tag(m_port->m_screen);
}
}
@@ -94,23 +93,33 @@ void nes_hori4p_device::device_add_mconfig(machine_config &config)
// nes_horitwin_device - constructor
//-------------------------------------------------
-nes_horitwin_device::nes_horitwin_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) :
- device_t(mconfig, NES_HORITWIN, tag, owner, clock),
- device_nes_control_port_interface(mconfig, *this),
- m_port1(*this, "port1"),
- m_port2(*this, "port2")
+nes_horitwin_device::nes_horitwin_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock)
+ : device_t(mconfig, NES_HORITWIN, tag, owner, clock)
+ , device_nes_control_port_interface(mconfig, *this)
+ , m_subexp(*this, "subexp%u", 0)
+{
+}
+
+nes_hori4p_device::nes_hori4p_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock)
+ : device_t(mconfig, NES_HORI4P, tag, owner, clock)
+ , device_nes_control_port_interface(mconfig, *this)
+ , m_subexp(*this, "subexp%u", 0)
+ , m_cfg(*this, "CONFIG")
{
}
-nes_hori4p_device::nes_hori4p_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) :
- device_t(mconfig, NES_HORI4P, tag, owner, clock),
- device_nes_control_port_interface(mconfig, *this),
- m_port1(*this, "port1"),
- m_port2(*this, "port2"),
- m_port3(*this, "port3"),
- m_port4(*this, "port4"),
- m_cfg(*this, "CONFIG")
+
+//-------------------------------------------------
+// device_start
+//-------------------------------------------------
+
+void nes_hori4p_device::device_start()
{
+ save_item(NAME(m_count));
+ save_item(NAME(m_sig));
+ save_item(NAME(m_strobe));
+
+ reset_regs();
}
@@ -118,39 +127,32 @@ nes_hori4p_device::nes_hori4p_device(const machine_config &mconfig, const char *
// read
//-------------------------------------------------
-uint8_t nes_horitwin_device::read_exp(offs_t offset)
+u8 nes_horitwin_device::read_exp(offs_t offset)
{
- uint8_t ret = 0;
- if (offset == 0) //$4016
- ret |= (m_port1->read_bit0() << 1);
- else //$4017
- ret |= (m_port2->read_bit0() << 1);
- return ret;
+ return m_subexp[offset]->read_exp(0);
}
-uint8_t nes_hori4p_device::read_exp(offs_t offset)
+u8 nes_hori4p_device::read_exp(offs_t offset)
{
- uint8_t ret = 0;
- if (m_cfg->read() == 0) // 2P
+ u8 ret = 0;
+ int mode4p = m_cfg->read();
+
+ if (m_strobe)
+ reset_regs();
+
+ if (m_count[offset] < 16 || !mode4p) // read from P1/P2 for first byte, P3/P4 for second byte if in 4P mode
{
- if (offset == 0) //$4016
- ret |= (m_port1->read_bit0() << 1);
- else //$4017
- ret |= (m_port2->read_bit0() << 1);
+ int port = 2 * (BIT(m_count[offset], 3) & mode4p) + offset;
+ ret = m_subexp[port]->read_exp(0);
}
- else // 4P
+ else // excess reads return a distinct signature byte on both $4016 and $4017
{
- if (offset == 0) //$4016
- {
- ret |= (m_port1->read_bit0() << 0);
- ret |= (m_port3->read_bit0() << 1);
- }
- else //$4017
- {
- ret |= (m_port2->read_bit0() << 0);
- ret |= (m_port4->read_bit0() << 1);
- }
+ ret = (m_sig[offset] & 1) << 1;
+ m_sig[offset] >>= 1;
+ m_sig[offset] |= 0x80; // reads beyond signature are always 1
}
+ m_count[offset]++;
+
return ret;
}
@@ -158,16 +160,27 @@ uint8_t nes_hori4p_device::read_exp(offs_t offset)
// write
//-------------------------------------------------
-void nes_horitwin_device::write(uint8_t data)
+void nes_horitwin_device::write(u8 data)
{
- m_port1->write(data);
- m_port2->write(data);
+ m_subexp[0]->write(data);
+ m_subexp[1]->write(data);
}
-void nes_hori4p_device::write(uint8_t data)
+void nes_hori4p_device::write(u8 data)
{
- m_port1->write(data);
- m_port2->write(data);
- m_port3->write(data);
- m_port4->write(data);
+ for (int i = 0; i < 4; i++)
+ m_subexp[i]->write(data);
+
+ if (write_strobe(data))
+ reset_regs();
+}
+
+void nes_hori4p_device::reset_regs()
+{
+ m_count[0] = 0;
+ m_count[1] = 0;
+
+ // signature third bytes returned in 4P mode, pair is flipped from what Four Score returns
+ m_sig[0] = 0x04;
+ m_sig[1] = 0x08;
}
diff --git a/src/devices/bus/nes_ctrl/hori.h b/src/devices/bus/nes_ctrl/hori.h
index c5ba00ffbeb..f8bd7f7c692 100644
--- a/src/devices/bus/nes_ctrl/hori.h
+++ b/src/devices/bus/nes_ctrl/hori.h
@@ -2,7 +2,7 @@
// copyright-holders:Fabio Priuli
/**********************************************************************
- Nintendo Family Computer Hori Twin (and 4P?) adapters
+ Nintendo Family Computer Hori Twin and 4 Players adapters
**********************************************************************/
@@ -25,21 +25,21 @@ class nes_horitwin_device : public device_t,
{
public:
// construction/destruction
- nes_horitwin_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
+ nes_horitwin_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 uint8_t read_exp(offs_t offset) override;
- virtual void write(uint8_t data) override;
+ virtual void device_add_mconfig(machine_config &config) override ATTR_COLD;
private:
- required_device<nes_control_port_device> m_port1;
- required_device<nes_control_port_device> m_port2;
+ required_device_array<nes_control_port_device, 2> m_subexp;
};
+
// ======================> nes_hori4p_device
class nes_hori4p_device : public device_t,
@@ -47,23 +47,24 @@ class nes_hori4p_device : public device_t,
{
public:
// construction/destruction
- nes_hori4p_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
+ nes_hori4p_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;
-
- virtual uint8_t read_exp(offs_t offset) override;
- virtual void write(uint8_t data) override;
+ virtual void device_start() override ATTR_COLD;
+ virtual void device_add_mconfig(machine_config &config) override ATTR_COLD;
+ virtual ioport_constructor device_input_ports() const override ATTR_COLD;
private:
- required_device<nes_control_port_device> m_port1;
- required_device<nes_control_port_device> m_port2;
- required_device<nes_control_port_device> m_port3;
- required_device<nes_control_port_device> m_port4;
+ void reset_regs();
+
+ required_device_array<nes_control_port_device, 4> m_subexp;
required_ioport m_cfg;
+ u8 m_count[2];
+ u8 m_sig[2];
};
@@ -71,5 +72,4 @@ private:
DECLARE_DEVICE_TYPE(NES_HORITWIN, nes_horitwin_device)
DECLARE_DEVICE_TYPE(NES_HORI4P, nes_hori4p_device)
-
#endif // MAME_BUS_NES_CTRL_HORI_H
diff --git a/src/devices/bus/nes_ctrl/joypad.cpp b/src/devices/bus/nes_ctrl/joypad.cpp
index 1027340cf63..c4972912d78 100644
--- a/src/devices/bus/nes_ctrl/joypad.cpp
+++ b/src/devices/bus/nes_ctrl/joypad.cpp
@@ -25,6 +25,14 @@
game (an image of such connection is shown e.g. in Nekketsu Koukou
Dodgeball Bu manual)
+ FIXME: The official Nintendo stick mentioned above by Hori has the
+ P1/P2 and 4/8-way switches but it DOESN'T have a daisy chain port.
+ ASCII made at least two sticks, AS-2088-FC and AS-3399-FC, that may
+ be the only two that exist with a daisy chain port. The former has
+ no additional switches at all, so its port may be a pass-thru. The
+ latter has many features: P1/P2 and 4/8-way switches, turbo, jacks
+ for data recorder, etc.
+
**********************************************************************/
#include "emu.h"
@@ -35,17 +43,17 @@
//**************************************************************************
DEFINE_DEVICE_TYPE(NES_JOYPAD, nes_joypad_device, "nes_joypad", "Nintendo NES / FC Control Pad")
+DEFINE_DEVICE_TYPE(NES_FCPAD_EXP, nes_fcpadexp_device, "nes_fcpadexp", "Nintendo Family Computer Expansion Port Pad")
DEFINE_DEVICE_TYPE(NES_FCPAD_P2, nes_fcpad2_device, "nes_fcpad2", "Nintendo Family Computer P2 Pad")
DEFINE_DEVICE_TYPE(NES_CCPAD_LEFT, nes_ccpadl_device, "nes_ccpadl", "FC Crazy Climber Left Pad")
DEFINE_DEVICE_TYPE(NES_CCPAD_RIGHT, nes_ccpadr_device, "nes_ccpadr", "FC Crazy Climber Right Pad")
DEFINE_DEVICE_TYPE(NES_ARCSTICK, nes_arcstick_device, "nes_arcstick", "Nintendo Family Computer Arcade Stick")
-// for the standalone TV Plug and Play
-DEFINE_DEVICE_TYPE(NES_VT_MAJESCO_DDR, nes_vt_majesco_ddr_device, "nes_ddr", "Majesco DDR Pad")
+DEFINE_DEVICE_TYPE(NES_VBOYCTRL, nes_vboyctrl_device, "nes_vboyctrl", "Nintendo Virtual Boy Controller")
-static INPUT_PORTS_START( nes_joypad )
+INPUT_PORTS_START( nes_joypad )
PORT_START("JOYPAD")
- PORT_BIT( 0x01, IP_ACTIVE_HIGH, IPT_BUTTON2 ) PORT_NAME("A")
- PORT_BIT( 0x02, IP_ACTIVE_HIGH, IPT_BUTTON1 ) PORT_NAME("B")
+ PORT_BIT( 0x01, IP_ACTIVE_HIGH, IPT_BUTTON2 ) PORT_NAME("%p A")
+ PORT_BIT( 0x02, IP_ACTIVE_HIGH, IPT_BUTTON1 ) 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
@@ -55,15 +63,15 @@ static INPUT_PORTS_START( nes_joypad )
INPUT_PORTS_END
static INPUT_PORTS_START( nes_fcpad_p2 )
- PORT_START("JOYPAD")
- PORT_BIT( 0x01, IP_ACTIVE_HIGH, IPT_BUTTON2 ) PORT_NAME("A")
- PORT_BIT( 0x02, IP_ACTIVE_HIGH, IPT_BUTTON1 ) PORT_NAME("B")
- PORT_BIT( 0x04, IP_ACTIVE_HIGH, IPT_SELECT ) PORT_NAME("Microphone")
- PORT_BIT( 0x08, IP_ACTIVE_HIGH, IPT_UNUSED )
- 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_INCLUDE( nes_joypad )
+
+ PORT_MODIFY("JOYPAD")
+ PORT_BIT( 0x04, IP_ACTIVE_HIGH, IPT_UNUSED ) // no select button
+ PORT_BIT( 0x08, IP_ACTIVE_HIGH, IPT_UNUSED ) // or start button on controller 2
+
+ PORT_START("MIC")
+ PORT_BIT( 0x03, IP_ACTIVE_HIGH, IPT_UNUSED )
+ PORT_BIT( 0x04, IP_ACTIVE_HIGH, IPT_BUTTON3 ) PORT_NAME("%p Microphone")
INPUT_PORTS_END
static INPUT_PORTS_START( nes_ccpad_left )
@@ -78,18 +86,6 @@ static INPUT_PORTS_START( nes_ccpad_left )
PORT_BIT( 0x80, IP_ACTIVE_HIGH, IPT_JOYSTICKLEFT_DOWN ) PORT_8WAY
INPUT_PORTS_END
-static INPUT_PORTS_START( nes_ddr )
- PORT_START("JOYPAD")
- PORT_BIT( 0x01, IP_ACTIVE_HIGH, IPT_UNUSED )
- PORT_BIT( 0x02, IP_ACTIVE_HIGH, IPT_UNUSED )
- PORT_BIT( 0x04, IP_ACTIVE_HIGH, IPT_UNUSED )
- PORT_BIT( 0x08, IP_ACTIVE_HIGH, IPT_START )
- PORT_BIT( 0x10, IP_ACTIVE_HIGH, IPT_BUTTON1 ) PORT_NAME("Up Arrow") // these can't be treated as a joystick as opposing directions are often required
- PORT_BIT( 0x20, IP_ACTIVE_HIGH, IPT_BUTTON2 ) PORT_NAME("Down Arrow")
- PORT_BIT( 0x40, IP_ACTIVE_HIGH, IPT_BUTTON3 ) PORT_NAME("Left Arrow")
- PORT_BIT( 0x80, IP_ACTIVE_HIGH, IPT_BUTTON4 ) PORT_NAME("Right Arrow")
-INPUT_PORTS_END
-
static INPUT_PORTS_START( nes_ccpad_right )
PORT_START("JOYPAD")
PORT_BIT( 0x01, IP_ACTIVE_HIGH, IPT_UNUSED )
@@ -112,8 +108,8 @@ static INPUT_PORTS_START( nes_arcstick )
PORT_CONFSETTING( 0x02, "Player II" )
PORT_START("JOYPAD")
- PORT_BIT( 0x01, IP_ACTIVE_HIGH, IPT_BUTTON2 ) PORT_NAME("A")
- PORT_BIT( 0x02, IP_ACTIVE_HIGH, IPT_BUTTON1 ) PORT_NAME("B")
+ PORT_BIT( 0x01, IP_ACTIVE_HIGH, IPT_BUTTON2 ) PORT_NAME("%p A")
+ PORT_BIT( 0x02, IP_ACTIVE_HIGH, IPT_BUTTON1 ) 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_CONDITION("CONFIG", 0x01, EQUALS, 0x01)
@@ -126,6 +122,26 @@ static INPUT_PORTS_START( nes_arcstick )
PORT_BIT( 0x80, IP_ACTIVE_HIGH, IPT_JOYSTICK_RIGHT ) PORT_4WAY PORT_CONDITION("CONFIG", 0x01, EQUALS, 0x00)
INPUT_PORTS_END
+static INPUT_PORTS_START( nes_vboyctrl )
+ PORT_START("JOYPAD")
+ PORT_BIT( 0x0001, IP_ACTIVE_HIGH, IPT_JOYSTICKRIGHT_DOWN ) PORT_8WAY
+ PORT_BIT( 0x0002, IP_ACTIVE_HIGH, IPT_JOYSTICKRIGHT_LEFT ) PORT_8WAY
+ PORT_BIT( 0x0004, IP_ACTIVE_HIGH, IPT_SELECT )
+ PORT_BIT( 0x0008, IP_ACTIVE_HIGH, IPT_START )
+ PORT_BIT( 0x0010, IP_ACTIVE_HIGH, IPT_JOYSTICKLEFT_UP ) PORT_8WAY
+ PORT_BIT( 0x0020, IP_ACTIVE_HIGH, IPT_JOYSTICKLEFT_DOWN ) PORT_8WAY
+ PORT_BIT( 0x0040, IP_ACTIVE_HIGH, IPT_JOYSTICKLEFT_LEFT ) PORT_8WAY
+ PORT_BIT( 0x0080, IP_ACTIVE_HIGH, IPT_JOYSTICKLEFT_RIGHT ) PORT_8WAY
+ PORT_BIT( 0x0100, IP_ACTIVE_HIGH, IPT_JOYSTICKRIGHT_RIGHT ) PORT_8WAY
+ PORT_BIT( 0x0200, IP_ACTIVE_HIGH, IPT_JOYSTICKRIGHT_UP ) PORT_8WAY
+ PORT_BIT( 0x0400, IP_ACTIVE_HIGH, IPT_BUTTON3 ) PORT_NAME("%p L") // Left button on back
+ PORT_BIT( 0x0800, IP_ACTIVE_HIGH, IPT_BUTTON4 ) PORT_NAME("%p R") // Right button on back
+ PORT_BIT( 0x1000, IP_ACTIVE_HIGH, IPT_BUTTON1 ) PORT_NAME("%p B")
+ PORT_BIT( 0x2000, IP_ACTIVE_HIGH, IPT_BUTTON2 ) PORT_NAME("%p A")
+ PORT_BIT( 0x4000, IP_ACTIVE_LOW, IPT_UNUSED ) // Always 1
+ PORT_BIT( 0x8000, IP_ACTIVE_HIGH, IPT_UNUSED ) // Battery low
+INPUT_PORTS_END
+
//-------------------------------------------------
// input_ports - device-specific input ports
//-------------------------------------------------
@@ -155,12 +171,11 @@ ioport_constructor nes_arcstick_device::device_input_ports() const
return INPUT_PORTS_NAME( nes_arcstick );
}
-ioport_constructor nes_vt_majesco_ddr_device::device_input_ports() const
+ioport_constructor nes_vboyctrl_device::device_input_ports() const
{
- return INPUT_PORTS_NAME( nes_ddr );
+ return INPUT_PORTS_NAME( nes_vboyctrl );
}
-
static void arcstick_daisy(device_slot_interface &device)
{
device.option_add("arcstick", NES_ARCSTICK);
@@ -188,63 +203,67 @@ void nes_arcstick_device::device_add_mconfig(machine_config &config)
// nes_joypad_device - constructor
//-------------------------------------------------
-nes_joypad_device::nes_joypad_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_nes_control_port_interface(mconfig, *this),
- m_joypad(*this, "JOYPAD"), m_latch(0)
+nes_joypad_device::nes_joypad_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, u32 clock, u32 latch_fill)
+ : device_t(mconfig, type, tag, owner, clock)
+ , device_nes_control_port_interface(mconfig, *this)
+ , m_joypad(*this, "JOYPAD")
+ , m_latch(0)
+ , m_latch_fill(latch_fill)
{
}
-nes_joypad_device::nes_joypad_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) :
- nes_joypad_device(mconfig, NES_JOYPAD, tag, owner, clock)
+nes_joypad_device::nes_joypad_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock)
+ : nes_joypad_device(mconfig, NES_JOYPAD, tag, owner, clock)
{
}
-nes_fcpad2_device::nes_fcpad2_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) :
- nes_joypad_device(mconfig, NES_FCPAD_P2, tag, owner, clock)
+nes_fcpadexp_device::nes_fcpadexp_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, u32 clock, u32 latch_fill)
+ : nes_joypad_device(mconfig, type, tag, owner, clock, latch_fill)
{
}
-nes_ccpadl_device::nes_ccpadl_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) :
- nes_joypad_device(mconfig, NES_CCPAD_LEFT, tag, owner, clock)
+nes_fcpadexp_device::nes_fcpadexp_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock)
+ : nes_fcpadexp_device(mconfig, NES_FCPAD_EXP, tag, owner, clock)
{
}
-nes_ccpadr_device::nes_ccpadr_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) :
- nes_joypad_device(mconfig, NES_CCPAD_RIGHT, tag, owner, clock)
+nes_fcpad2_device::nes_fcpad2_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock)
+ : nes_joypad_device(mconfig, NES_FCPAD_P2, tag, owner, clock)
+ , m_mic(*this, "MIC")
{
}
-nes_vt_majesco_ddr_device::nes_vt_majesco_ddr_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) :
- nes_joypad_device(mconfig, NES_VT_MAJESCO_DDR, tag, owner, clock)
+nes_ccpadl_device::nes_ccpadl_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock)
+ : nes_joypad_device(mconfig, NES_CCPAD_LEFT, tag, owner, clock)
{
}
-nes_arcstick_device::nes_arcstick_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) :
- nes_joypad_device(mconfig, NES_ARCSTICK, tag, owner, clock),
- m_daisychain(*this, "subexp"),
- m_cfg(*this, "CONFIG")
+nes_ccpadr_device::nes_ccpadr_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock)
+ : nes_joypad_device(mconfig, NES_CCPAD_RIGHT, tag, owner, clock)
{
}
+nes_arcstick_device::nes_arcstick_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock)
+ : nes_fcpadexp_device(mconfig, NES_ARCSTICK, tag, owner, clock)
+ , m_daisychain(*this, "subexp")
+ , m_cfg(*this, "CONFIG")
+{
+}
-//-------------------------------------------------
-// device_start
-//-------------------------------------------------
-
-void nes_joypad_device::device_start()
+nes_vboyctrl_device::nes_vboyctrl_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock)
+ : nes_joypad_device(mconfig, NES_VBOYCTRL, tag, owner, clock, 0x8000)
{
- save_item(NAME(m_latch));
}
//-------------------------------------------------
-// device_reset
+// device_start
//-------------------------------------------------
-void nes_joypad_device::device_reset()
+void nes_joypad_device::device_start()
{
- m_latch = 0;
+ save_item(NAME(m_latch));
+ save_item(NAME(m_strobe));
}
@@ -252,20 +271,26 @@ void nes_joypad_device::device_reset()
// read
//-------------------------------------------------
-uint8_t nes_joypad_device::read_bit0()
+u8 nes_joypad_device::read_bit0()
{
- uint8_t ret = m_latch & 1;
+ if (m_strobe)
+ set_latch();
+
+ u8 ret = m_latch & 1;
m_latch >>= 1;
+ m_latch |= m_latch_fill;
+
return ret;
}
-uint8_t nes_fcpad2_device::read_exp(offs_t offset)
+u8 nes_fcpadexp_device::read_exp(offs_t offset)
{
- uint8_t ret = 0;
- if (!offset) // microphone input
- ret |= m_joypad->read() & 0x04;
+ return offset ? 0 : nes_joypad_device::read_bit0() << 1;
+}
- return ret;
+u8 nes_fcpad2_device::read_bit2()
+{
+ return m_mic->read();
}
// NOTE: I haven't found any documentation about what happens when
@@ -274,29 +299,14 @@ uint8_t nes_fcpad2_device::read_exp(offs_t offset)
// with each other? currently, we only support the following setup:
// if the first pad is set as P1, the daisy chained pad is checked
// for P2 only, and vice versa.
-uint8_t nes_arcstick_device::read_exp(offs_t offset)
+u8 nes_arcstick_device::read_exp(offs_t offset)
{
- uint8_t ret = 0;
- if (offset == 0) //$4016
- {
- if ((m_cfg->read() & 2) == 0) // we are P1 input
- {
- ret |= (m_latch & 1) << 1;
- m_latch >>= 1;
- }
- else
- ret |= m_daisychain->read_exp(0);
- }
- else //$4017
- {
- if ((m_cfg->read() & 2) == 2) // we are P2 input
- {
- ret |= (m_latch & 1) << 1;
- m_latch >>= 1;
- }
- else
- ret |= m_daisychain->read_exp(1);
- }
+ u8 ret = 0;
+
+ if (BIT(m_cfg->read(), 1) == offset) // P# matches the port? That's us!
+ ret = nes_fcpadexp_device::read_exp(0);
+ else // otherwise it's possibly the other controller
+ ret = m_daisychain->read_exp(offset);
return ret;
}
@@ -305,29 +315,14 @@ uint8_t nes_arcstick_device::read_exp(offs_t offset)
// write
//-------------------------------------------------
-void nes_joypad_device::write(uint8_t data)
+void nes_joypad_device::write(u8 data)
{
- if (data & 0x01)
- return;
-
- m_latch = m_joypad->read();
+ if (write_strobe(data))
+ set_latch();
}
-void nes_fcpad2_device::write(uint8_t data)
-{
- if (data & 0x01)
- return;
-
- // microphone is hooked to expansion bits, not to the controller bit
- m_latch = m_joypad->read() & ~0x04;
-}
-
-void nes_arcstick_device::write(uint8_t data)
+void nes_arcstick_device::write(u8 data)
{
m_daisychain->write(data);
-
- if (data & 0x01)
- return;
-
- m_latch = m_joypad->read();
+ nes_fcpadexp_device::write(data);
}
diff --git a/src/devices/bus/nes_ctrl/joypad.h b/src/devices/bus/nes_ctrl/joypad.h
index 46cfd854756..d1911111976 100644
--- a/src/devices/bus/nes_ctrl/joypad.h
+++ b/src/devices/bus/nes_ctrl/joypad.h
@@ -13,6 +13,7 @@
#include "ctrl.h"
+INPUT_PORTS_EXTERN( nes_joypad );
//**************************************************************************
// TYPE DEFINITIONS
@@ -25,99 +26,132 @@ class nes_joypad_device : public device_t,
{
public:
// construction/destruction
- nes_joypad_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
+ nes_joypad_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock);
- virtual ioport_constructor device_input_ports() const override;
+ virtual u8 read_bit0() override;
+ virtual void write(u8 data) override;
protected:
- nes_joypad_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock);
+ nes_joypad_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, u32 clock, u32 latch_fill = 0x80);
// device-level overrides
- virtual void device_start() override;
- virtual void device_reset() override;
+ virtual void device_start() override ATTR_COLD;
+ virtual ioport_constructor device_input_ports() const override ATTR_COLD;
- virtual uint8_t read_bit0() override;
- virtual void write(uint8_t data) override;
+ virtual void set_latch() { m_latch = m_joypad->read(); }
required_ioport m_joypad;
- uint32_t m_latch;
+ u32 m_latch; // wider than standard joypad's 8-bit latch to accomodate subclass devices
+ const u32 m_latch_fill; // the new MSB as a joypad's shift register shifts
};
+
+// ======================> nes_fcpadexp_device
+
+class nes_fcpadexp_device : public nes_joypad_device
+{
+public:
+ // construction/destruction
+ nes_fcpadexp_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock);
+
+ virtual u8 read_bit0() override { return 0; }
+ virtual u8 read_exp(offs_t offset) override;
+
+protected:
+ nes_fcpadexp_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, u32 clock, u32 latch_fill = 0x80);
+};
+
+
// ======================> nes_fcpad2_device
class nes_fcpad2_device : public nes_joypad_device
{
public:
// construction/destruction
- nes_fcpad2_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
+ nes_fcpad2_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock);
- virtual ioport_constructor device_input_ports() const override;
+ virtual u8 read_bit2() override;
protected:
- virtual uint8_t read_exp(offs_t offset) override;
- virtual void write(uint8_t data) override;
+ // device-level overrides
+ virtual ioport_constructor device_input_ports() const override ATTR_COLD;
+
+private:
+ required_ioport m_mic;
};
+
// ======================> nes_ccpadl_device
class nes_ccpadl_device : public nes_joypad_device
{
public:
// construction/destruction
- nes_ccpadl_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
+ nes_ccpadl_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock);
- virtual ioport_constructor device_input_ports() const override;
+protected:
+ // device-level overrides
+ virtual ioport_constructor device_input_ports() const override ATTR_COLD;
};
+
// ======================> nes_ccpadr_device
class nes_ccpadr_device : public nes_joypad_device
{
public:
// construction/destruction
- nes_ccpadr_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
+ nes_ccpadr_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock);
- virtual ioport_constructor device_input_ports() const override;
+protected:
+ // device-level overrides
+ virtual ioport_constructor device_input_ports() const override ATTR_COLD;
};
-// ======================> nes_vt_majesco_ddr_device
-class nes_vt_majesco_ddr_device : public nes_joypad_device
+// ======================> nes_arcstick_device
+
+class nes_arcstick_device : public nes_fcpadexp_device
{
public:
// construction/destruction
- nes_vt_majesco_ddr_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
+ nes_arcstick_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;
- virtual ioport_constructor device_input_ports() const override;
+protected:
+ // device-level overrides
+ virtual ioport_constructor device_input_ports() const override ATTR_COLD;
+ virtual void device_add_mconfig(machine_config &config) override ATTR_COLD;
+
+private:
+ required_device<nes_control_port_device> m_daisychain;
+ required_ioport m_cfg;
};
-// ======================> nes_arcstick_device
-class nes_arcstick_device : public nes_joypad_device
+// ======================> nes_vboyctrl_device
+
+class nes_vboyctrl_device : public nes_joypad_device
{
public:
// construction/destruction
- nes_arcstick_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
+ nes_vboyctrl_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock);
protected:
- virtual ioport_constructor device_input_ports() const override;
- virtual void device_add_mconfig(machine_config &config) override;
-
- virtual uint8_t read_bit0() override { return 0; }
- virtual uint8_t read_exp(offs_t offset) override;
- virtual void write(uint8_t data) override;
-
- required_device<nes_control_port_device> m_daisychain;
- required_ioport m_cfg;
+ // device-level overrides
+ virtual ioport_constructor device_input_ports() const override ATTR_COLD;
};
// device type definition
DECLARE_DEVICE_TYPE(NES_JOYPAD, nes_joypad_device)
+DECLARE_DEVICE_TYPE(NES_FCPAD_EXP, nes_fcpadexp_device)
DECLARE_DEVICE_TYPE(NES_FCPAD_P2, nes_fcpad2_device)
DECLARE_DEVICE_TYPE(NES_CCPAD_LEFT, nes_ccpadl_device)
DECLARE_DEVICE_TYPE(NES_CCPAD_RIGHT, nes_ccpadr_device)
DECLARE_DEVICE_TYPE(NES_ARCSTICK, nes_arcstick_device)
-DECLARE_DEVICE_TYPE(NES_VT_MAJESCO_DDR, nes_vt_majesco_ddr_device)
+DECLARE_DEVICE_TYPE(NES_VBOYCTRL, nes_vboyctrl_device)
#endif // MAME_BUS_NES_CTRL_JOYPAD_H
diff --git a/src/devices/bus/nes_ctrl/konamibag.cpp b/src/devices/bus/nes_ctrl/konamibag.cpp
new file mode 100644
index 00000000000..bef79cfde60
--- /dev/null
+++ b/src/devices/bus/nes_ctrl/konamibag.cpp
@@ -0,0 +1,88 @@
+// license:BSD-3-Clause
+// copyright-holders:kmg
+/**********************************************************************
+
+ Nintendo Family Computer - Konami Exciting Boxing Air Bag
+
+**********************************************************************/
+
+#include "emu.h"
+#include "konamibag.h"
+
+//**************************************************************************
+// DEVICE DEFINITIONS
+//**************************************************************************
+
+DEFINE_DEVICE_TYPE(NES_KONAMIBAG, nes_konamibag_device, "nes_konamibag", "Konami Exciting Boxing Air Bag")
+
+
+static INPUT_PORTS_START( nes_konamibag )
+ PORT_START("BAG.0")
+ PORT_BIT( 0x01, IP_ACTIVE_LOW, IPT_BUTTON1 ) PORT_CODE(KEYCODE_7_PAD) PORT_NAME("Left Hook")
+ PORT_BIT( 0x02, IP_ACTIVE_LOW, IPT_UNKNOWN ) // opponent dodges right, unclear how this is triggered
+ PORT_BIT( 0x04, IP_ACTIVE_LOW, IPT_UNKNOWN ) // opponent dodges left, unclear how this is triggered
+ PORT_BIT( 0x08, IP_ACTIVE_LOW, IPT_BUTTON4 ) PORT_CODE(KEYCODE_9_PAD) PORT_NAME("Right Hook")
+
+ PORT_START("BAG.1")
+ PORT_BIT( 0x01, IP_ACTIVE_LOW, IPT_BUTTON5 ) PORT_CODE(KEYCODE_4_PAD) PORT_NAME("Left Jab")
+ PORT_BIT( 0x02, IP_ACTIVE_LOW, IPT_BUTTON6 ) PORT_CODE(KEYCODE_2_PAD) PORT_NAME("Body")
+ PORT_BIT( 0x04, IP_ACTIVE_LOW, IPT_BUTTON7 ) PORT_CODE(KEYCODE_6_PAD) PORT_NAME("Right Jab")
+ PORT_BIT( 0x08, IP_ACTIVE_LOW, IPT_BUTTON8 ) PORT_CODE(KEYCODE_5_PAD) PORT_NAME("Straight")
+INPUT_PORTS_END
+
+
+//-------------------------------------------------
+// input_ports - device-specific input ports
+//-------------------------------------------------
+
+ioport_constructor nes_konamibag_device::device_input_ports() const
+{
+ return INPUT_PORTS_NAME( nes_konamibag );
+}
+
+
+
+//**************************************************************************
+// LIVE DEVICE
+//**************************************************************************
+
+//-------------------------------------------------
+// nes_konamibag_device - constructor
+//-------------------------------------------------
+
+nes_konamibag_device::nes_konamibag_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock)
+ : device_t(mconfig, NES_KONAMIBAG, tag, owner, clock)
+ , device_nes_control_port_interface(mconfig, *this)
+ , m_sensor(*this, "BAG.%u", 0)
+ , m_cur_sensor(0)
+{
+}
+
+
+//-------------------------------------------------
+// device_start
+//-------------------------------------------------
+
+void nes_konamibag_device::device_start()
+{
+ save_item(NAME(m_cur_sensor));
+}
+
+
+//-------------------------------------------------
+// read
+//-------------------------------------------------
+
+u8 nes_konamibag_device::read_exp(offs_t offset)
+{
+ return (offset == 1) ? m_sensor[m_cur_sensor]->read() << 1 : 0;
+}
+
+//-------------------------------------------------
+// write
+//-------------------------------------------------
+
+void nes_konamibag_device::write(u8 data)
+{
+ m_cur_sensor = BIT(data, 1);
+}
diff --git a/src/devices/bus/nes_ctrl/konamibag.h b/src/devices/bus/nes_ctrl/konamibag.h
new file mode 100644
index 00000000000..e7179763c38
--- /dev/null
+++ b/src/devices/bus/nes_ctrl/konamibag.h
@@ -0,0 +1,50 @@
+// license:BSD-3-Clause
+// copyright-holders:kmg
+/**********************************************************************
+
+ Nintendo Family Computer - Konami Exciting Boxing Air Bag
+
+**********************************************************************/
+
+#ifndef MAME_BUS_NES_CTRL_KONAMIBAG_H
+#define MAME_BUS_NES_CTRL_KONAMIBAG_H
+
+#pragma once
+
+#include "ctrl.h"
+
+
+//**************************************************************************
+// TYPE DEFINITIONS
+//**************************************************************************
+
+// ======================> nes_konamibag_device
+
+class nes_konamibag_device :
+ public device_t,
+ public device_nes_control_port_interface
+{
+public:
+ static constexpr feature_type imperfect_features() { return feature::CONTROLS; }
+
+ // construction/destruction
+ nes_konamibag_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 ATTR_COLD;
+ virtual ioport_constructor device_input_ports() const override ATTR_COLD;
+
+private:
+ required_ioport_array<2> m_sensor;
+ u8 m_cur_sensor;
+};
+
+
+// device type definition
+DECLARE_DEVICE_TYPE(NES_KONAMIBAG, nes_konamibag_device)
+
+#endif // MAME_BUS_NES_CTRL_KONAMIBAG_H
diff --git a/src/devices/bus/nes_ctrl/konamihs.cpp b/src/devices/bus/nes_ctrl/konamihs.cpp
index 9522f5e3c2b..d8d95c9bbd6 100644
--- a/src/devices/bus/nes_ctrl/konamihs.cpp
+++ b/src/devices/bus/nes_ctrl/konamihs.cpp
@@ -18,12 +18,12 @@ DEFINE_DEVICE_TYPE(NES_KONAMIHS, nes_konamihs_device, "nes_konamihs", "Konami Hy
static INPUT_PORTS_START( nes_konamihs )
PORT_START("P1")
- PORT_BIT( 0x01, IP_ACTIVE_HIGH, IPT_BUTTON2 ) PORT_NAME("PI Run")
- PORT_BIT( 0x02, IP_ACTIVE_HIGH, IPT_BUTTON1 ) PORT_NAME("PI Jump")
+ PORT_BIT( 0x01, IP_ACTIVE_HIGH, IPT_BUTTON2 ) PORT_NAME("I Run")
+ PORT_BIT( 0x02, IP_ACTIVE_HIGH, IPT_BUTTON1 ) PORT_NAME("I Jump")
PORT_START("P2")
- PORT_BIT( 0x01, IP_ACTIVE_HIGH, IPT_BUTTON2 ) PORT_NAME("PII Run")
- PORT_BIT( 0x02, IP_ACTIVE_HIGH, IPT_BUTTON1 ) PORT_NAME("PII Jump")
+ PORT_BIT( 0x01, IP_ACTIVE_HIGH, IPT_BUTTON4 ) PORT_NAME("II Run")
+ PORT_BIT( 0x02, IP_ACTIVE_HIGH, IPT_BUTTON3 ) PORT_NAME("II Jump")
INPUT_PORTS_END
//-------------------------------------------------
@@ -43,13 +43,11 @@ ioport_constructor nes_konamihs_device::device_input_ports() const
// nes_konamihs_device - constructor
//-------------------------------------------------
-nes_konamihs_device::nes_konamihs_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) :
- device_t(mconfig, NES_KONAMIHS, tag, owner, clock),
- device_nes_control_port_interface(mconfig, *this),
- m_ipt_p1(*this, "P1"),
- m_ipt_p2(*this, "P2"),
- m_latch_p1(0),
- m_latch_p2(0)
+nes_konamihs_device::nes_konamihs_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock)
+ : device_t(mconfig, NES_KONAMIHS, tag, owner, clock)
+ , device_nes_control_port_interface(mconfig, *this)
+ , m_ipt(*this, "P%u", 1)
+ , m_latch(0)
{
}
@@ -60,19 +58,7 @@ nes_konamihs_device::nes_konamihs_device(const machine_config &mconfig, const ch
void nes_konamihs_device::device_start()
{
- save_item(NAME(m_latch_p1));
- save_item(NAME(m_latch_p2));
-}
-
-
-//-------------------------------------------------
-// device_reset
-//-------------------------------------------------
-
-void nes_konamihs_device::device_reset()
-{
- m_latch_p1 = 0;
- m_latch_p2 = 0;
+ save_item(NAME(m_latch));
}
@@ -80,14 +66,13 @@ void nes_konamihs_device::device_reset()
// read
//-------------------------------------------------
-uint8_t nes_konamihs_device::read_exp(offs_t offset)
+u8 nes_konamihs_device::read_exp(offs_t offset)
{
- uint8_t ret = 0;
+ u8 ret = 0;
if (offset == 1) //$4017
- {
- ret |= m_latch_p1 << 1;
- ret |= m_latch_p2 << 3;
- }
+ for (int i = 0; i < 2; i++)
+ if (BIT(m_latch, i))
+ ret |= m_ipt[i]->read() << (2 * i + 1);
return ret;
}
@@ -95,10 +80,7 @@ uint8_t nes_konamihs_device::read_exp(offs_t offset)
// write
//-------------------------------------------------
-void nes_konamihs_device::write(uint8_t data)
+void nes_konamihs_device::write(u8 data)
{
- if ((data & 0x02) == 0)
- m_latch_p1 = m_ipt_p1->read();
- if ((data & 0x04) == 0)
- m_latch_p2 = m_ipt_p2->read();
+ m_latch = ~data >> 1;
}
diff --git a/src/devices/bus/nes_ctrl/konamihs.h b/src/devices/bus/nes_ctrl/konamihs.h
index 4d8b480968b..0e960594387 100644
--- a/src/devices/bus/nes_ctrl/konamihs.h
+++ b/src/devices/bus/nes_ctrl/konamihs.h
@@ -25,23 +25,22 @@ class nes_konamihs_device : public device_t,
{
public:
// construction/destruction
- nes_konamihs_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
+ nes_konamihs_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock);
- virtual ioport_constructor device_input_ports() const 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 void device_start() override ATTR_COLD;
+ virtual ioport_constructor device_input_ports() const override ATTR_COLD;
- virtual uint8_t read_exp(offs_t offset) override;
- virtual void write(uint8_t data) override;
-
- required_ioport m_ipt_p1;
- required_ioport m_ipt_p2;
- uint32_t m_latch_p1, m_latch_p2;
+private:
+ required_ioport_array<2> m_ipt;
+ u8 m_latch;
};
+
// device type definition
DECLARE_DEVICE_TYPE(NES_KONAMIHS, nes_konamihs_device)
diff --git a/src/devices/bus/nes_ctrl/miracle.cpp b/src/devices/bus/nes_ctrl/miracle.cpp
index d9f445f58ef..4945358c028 100644
--- a/src/devices/bus/nes_ctrl/miracle.cpp
+++ b/src/devices/bus/nes_ctrl/miracle.cpp
@@ -31,15 +31,12 @@ void nes_miracle_device::device_add_mconfig(machine_config &config)
//-------------------------------------------------
-// device_timer - handler timer events
+// strobe_tick - increment strobe counter
//-------------------------------------------------
-void nes_miracle_device::device_timer(emu_timer &timer, device_timer_id id, int param, void *ptr)
+TIMER_CALLBACK_MEMBER(nes_miracle_device::strobe_tick)
{
- if (id == TIMER_STROBE_ON)
- {
- m_strobe_clock++;
- }
+ m_strobe_clock++;
}
//**************************************************************************
@@ -67,7 +64,7 @@ nes_miracle_device::nes_miracle_device(const machine_config &mconfig, const char
void nes_miracle_device::device_start()
{
- strobe_timer = timer_alloc(TIMER_STROBE_ON);
+ strobe_timer = timer_alloc(FUNC(nes_miracle_device::strobe_tick), this);
strobe_timer->adjust(attotime::never);
save_item(NAME(m_strobe_on));
save_item(NAME(m_sent_bits));
diff --git a/src/devices/bus/nes_ctrl/miracle.h b/src/devices/bus/nes_ctrl/miracle.h
index 16cc1c57cd1..2e584c8664d 100644
--- a/src/devices/bus/nes_ctrl/miracle.h
+++ b/src/devices/bus/nes_ctrl/miracle.h
@@ -30,19 +30,21 @@ public:
// construction/destruction
nes_miracle_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
+ virtual uint8_t read_bit0() override;
+ virtual void write(uint8_t data) override;
+
required_device<midi_port_device> m_midiin, m_midiout;
protected:
static constexpr int XMIT_RING_SIZE = 64;
static constexpr int RECV_RING_SIZE = 64;
- static constexpr device_timer_id TIMER_STROBE_ON = 0;
// device-level overrides
- virtual void device_start() override;
- virtual void device_reset() override;
+ 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;
- virtual void device_timer(emu_timer &timer, device_timer_id id, int param, void *ptr) override;
- virtual void device_add_mconfig(machine_config &config) override;
+ TIMER_CALLBACK_MEMBER(strobe_tick);
private:
// serial overrides
@@ -52,9 +54,6 @@ private:
void xmit_char(uint8_t data);
- virtual uint8_t read_bit0() override;
- virtual void write(uint8_t data) override;
-
emu_timer *strobe_timer;
int m_strobe_on, m_midi_mode, m_sent_bits;
diff --git a/src/devices/bus/nes_ctrl/mjpanel.cpp b/src/devices/bus/nes_ctrl/mjpanel.cpp
index e667487dac5..9624ff95226 100644
--- a/src/devices/bus/nes_ctrl/mjpanel.cpp
+++ b/src/devices/bus/nes_ctrl/mjpanel.cpp
@@ -2,7 +2,14 @@
// copyright-holders:Fabio Priuli
/**********************************************************************
- Nintendo Family Computer Mahjong Panel
+ Nintendo Family Computer Capcom Mahjong Controller
+
+ There are two versions of this controller, one packed with the 1st
+ and 2nd Ide Yousoku Meijin no Jissen Mahjong, respectively. Both
+ have the original game's serial "CAP-IM" on back. Controller serials
+ HC-01 or HC-02 appear on revisions of the 1st game's controller.
+ HC-01 also appears on the 2nd game's controller. At least one
+ version of the original controller has a PCB marked 0827-06 HORI.
**********************************************************************/
@@ -13,7 +20,7 @@
// DEVICE DEFINITIONS
//**************************************************************************
-DEFINE_DEVICE_TYPE(NES_MJPANEL, nes_mjpanel_device, "nes_mjpanel", "Famicom Mahjong Panel")
+DEFINE_DEVICE_TYPE(NES_MJPANEL, nes_mjpanel_device, "nes_mjpanel", "Capcom Mahjong Controller")
static INPUT_PORTS_START( nes_mjpanel )
@@ -22,17 +29,17 @@ static INPUT_PORTS_START( nes_mjpanel )
PORT_START("MJPANEL.1")
PORT_BIT( 0x03, IP_ACTIVE_HIGH, IPT_UNUSED )
- PORT_BIT( 0x04, IP_ACTIVE_HIGH, IPT_MAHJONG_N )
- PORT_BIT( 0x08, IP_ACTIVE_HIGH, IPT_MAHJONG_M )
+ PORT_BIT( 0x04, IP_ACTIVE_HIGH, IPT_MAHJONG_N ) PORT_NAME("%p Mahjong N / Circle")
+ PORT_BIT( 0x08, IP_ACTIVE_HIGH, IPT_MAHJONG_M ) PORT_NAME("%p Mahjong M / Square")
PORT_BIT( 0x10, IP_ACTIVE_HIGH, IPT_MAHJONG_L )
PORT_BIT( 0x20, IP_ACTIVE_HIGH, IPT_MAHJONG_K )
PORT_BIT( 0x40, IP_ACTIVE_HIGH, IPT_MAHJONG_J )
PORT_BIT( 0x80, IP_ACTIVE_HIGH, IPT_MAHJONG_I )
PORT_START("MJPANEL.2")
- PORT_BIT( 0x01, IP_ACTIVE_HIGH, IPT_MAHJONG_H )
- PORT_BIT( 0x02, IP_ACTIVE_HIGH, IPT_MAHJONG_G )
- PORT_BIT( 0x04, IP_ACTIVE_HIGH, IPT_MAHJONG_F )
+ PORT_BIT( 0x01, IP_ACTIVE_HIGH, IPT_MAHJONG_H ) PORT_NAME("%p Mahjong H / Right")
+ PORT_BIT( 0x02, IP_ACTIVE_HIGH, IPT_MAHJONG_G ) PORT_NAME("%p Mahjong G / Up")
+ PORT_BIT( 0x04, IP_ACTIVE_HIGH, IPT_MAHJONG_F ) PORT_NAME("%p Mahjong F / Left")
PORT_BIT( 0x08, IP_ACTIVE_HIGH, IPT_MAHJONG_E )
PORT_BIT( 0x10, IP_ACTIVE_HIGH, IPT_MAHJONG_D )
PORT_BIT( 0x20, IP_ACTIVE_HIGH, IPT_MAHJONG_C )
@@ -45,9 +52,9 @@ static INPUT_PORTS_START( nes_mjpanel )
PORT_BIT( 0x04, IP_ACTIVE_HIGH, IPT_MAHJONG_REACH )
PORT_BIT( 0x08, IP_ACTIVE_HIGH, IPT_MAHJONG_CHI )
PORT_BIT( 0x10, IP_ACTIVE_HIGH, IPT_MAHJONG_PON )
- PORT_BIT( 0x20, IP_ACTIVE_HIGH, IPT_MAHJONG_KAN )
- PORT_BIT( 0x40, IP_ACTIVE_HIGH, IPT_SELECT ) PORT_NAME("Mahjong Select")
- PORT_BIT( 0x80, IP_ACTIVE_HIGH, IPT_START ) PORT_NAME("Mahjong Start")
+ PORT_BIT( 0x20, IP_ACTIVE_HIGH, IPT_MAHJONG_KAN ) PORT_NAME("%p Mahjong Kan / Right")
+ PORT_BIT( 0x40, IP_ACTIVE_HIGH, IPT_START ) PORT_NAME("%p Start / Down")
+ PORT_BIT( 0x80, IP_ACTIVE_HIGH, IPT_SELECT ) PORT_NAME("%p Select / Left")
INPUT_PORTS_END
@@ -70,11 +77,12 @@ ioport_constructor nes_mjpanel_device::device_input_ports() const
// nes_mjpanel_device - constructor
//-------------------------------------------------
-nes_mjpanel_device::nes_mjpanel_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
+nes_mjpanel_device::nes_mjpanel_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock)
: device_t(mconfig, NES_MJPANEL, tag, owner, clock)
, device_nes_control_port_interface(mconfig, *this)
, m_panel(*this, "MJPANEL.%u", 0)
, m_latch(0)
+ , m_row(0)
{
}
@@ -86,16 +94,8 @@ nes_mjpanel_device::nes_mjpanel_device(const machine_config &mconfig, const char
void nes_mjpanel_device::device_start()
{
save_item(NAME(m_latch));
-}
-
-
-//-------------------------------------------------
-// device_reset
-//-------------------------------------------------
-
-void nes_mjpanel_device::device_reset()
-{
- m_latch = 0;
+ save_item(NAME(m_row));
+ save_item(NAME(m_strobe));
}
@@ -103,17 +103,16 @@ void nes_mjpanel_device::device_reset()
// read
//-------------------------------------------------
-uint8_t nes_mjpanel_device::read_exp(offs_t offset)
+u8 nes_mjpanel_device::read_exp(offs_t offset)
{
- uint8_t ret = 0;
- if (offset)
+ u8 ret = 0;
+ if (offset == 1) // $4017
{
+ if (m_strobe)
+ set_latch();
ret = (m_latch & 1) << 1;
m_latch >>= 1;
}
- else
- logerror("Error: Mahjong panel read from $4016\n");
-
return ret;
}
@@ -121,13 +120,17 @@ uint8_t nes_mjpanel_device::read_exp(offs_t offset)
// write
//-------------------------------------------------
-void nes_mjpanel_device::write(uint8_t data)
+void nes_mjpanel_device::write(u8 data)
{
- if (data & 0x01)
- return;
+ m_row = (data >> 1) & 0x03;
+ if (write_strobe(data))
+ set_latch();
+}
- if (data & 0xf8)
- logerror("Error: Mahjong panel read with mux data %02x\n", (data & 0xfe));
- else
- m_latch = m_panel[(data & 0xfe) >> 1]->read();
+void nes_mjpanel_device::set_latch()
+{
+ if (m_row)
+ m_latch = m_panel[m_row]->read();
+ else // hardware behavior of the apparently unused input row
+ m_latch = m_panel[1]->read() | m_panel[2]->read();
}
diff --git a/src/devices/bus/nes_ctrl/mjpanel.h b/src/devices/bus/nes_ctrl/mjpanel.h
index 1a18bf0b19c..a14c0c75d46 100644
--- a/src/devices/bus/nes_ctrl/mjpanel.h
+++ b/src/devices/bus/nes_ctrl/mjpanel.h
@@ -2,7 +2,7 @@
// copyright-holders:Fabio Priuli
/**********************************************************************
- Nintendo Family Computer Mahjong Panel
+ Nintendo Family Computer Capcom Mahjong Controller
**********************************************************************/
@@ -25,26 +25,26 @@ class nes_mjpanel_device : public device_t,
{
public:
// construction/destruction
- nes_mjpanel_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
+ nes_mjpanel_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock);
- virtual ioport_constructor device_input_ports() const 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 uint8_t read_exp(offs_t offset) override;
- virtual void write(uint8_t data) override;
+ virtual void device_start() override ATTR_COLD;
+ virtual ioport_constructor device_input_ports() const override ATTR_COLD;
private:
+ void set_latch();
+
required_ioport_array<4> m_panel;
- uint32_t m_latch;
+ u8 m_latch;
+ u8 m_row;
};
// device type definition
DECLARE_DEVICE_TYPE(NES_MJPANEL, nes_mjpanel_device)
-
#endif // MAME_BUS_NES_CTRL_MJPANEL_H
diff --git a/src/devices/bus/nes_ctrl/pachinko.cpp b/src/devices/bus/nes_ctrl/pachinko.cpp
index d8aa81e3091..e5b7dd5a6ac 100644
--- a/src/devices/bus/nes_ctrl/pachinko.cpp
+++ b/src/devices/bus/nes_ctrl/pachinko.cpp
@@ -2,7 +2,7 @@
// copyright-holders:Fabio Priuli
/**********************************************************************
- Nintendo Family Computer Pachinko Controller
+ Nintendo Family Computer Coconuts Japan CJPC-102 Pachinko Controller
**********************************************************************/
@@ -13,19 +13,11 @@
// DEVICE DEFINITIONS
//**************************************************************************
-DEFINE_DEVICE_TYPE(NES_PACHINKO, nes_pachinko_device, "nes_pachinko", "Famicom Pachinko Controller")
+DEFINE_DEVICE_TYPE(NES_PACHINKO, nes_pachinko_device, "nes_pachinko", "Coconuts Japan Pachinko Controller CJPC-102")
static INPUT_PORTS_START( nes_pachinko )
- PORT_START("JOYPAD")
- PORT_BIT( 0x01, IP_ACTIVE_HIGH, IPT_BUTTON2 ) PORT_NAME("A")
- PORT_BIT( 0x02, IP_ACTIVE_HIGH, IPT_BUTTON1 ) PORT_NAME("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_INCLUDE( nes_joypad )
PORT_START("TRIGGER")
PORT_BIT( 0xff, 0, IPT_PEDAL ) PORT_MINMAX(0, 0x63) PORT_SENSITIVITY(25) PORT_KEYDELTA(20)
@@ -48,62 +40,15 @@ ioport_constructor nes_pachinko_device::device_input_ports() const
// nes_pachinko_device - constructor
//-------------------------------------------------
-nes_pachinko_device::nes_pachinko_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) :
- device_t(mconfig, NES_PACHINKO, tag, owner, clock),
- device_nes_control_port_interface(mconfig, *this),
- m_joypad(*this, "JOYPAD"),
- m_trigger(*this, "TRIGGER"),
- m_latch(0)
+nes_pachinko_device::nes_pachinko_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock)
+ : nes_fcpadexp_device(mconfig, NES_PACHINKO, tag, owner, clock, 0)
+ , m_trigger(*this, "TRIGGER")
{
}
-//-------------------------------------------------
-// device_start
-//-------------------------------------------------
-
-void nes_pachinko_device::device_start()
-{
- save_item(NAME(m_latch));
-}
-
-
-//-------------------------------------------------
-// device_reset
-//-------------------------------------------------
-
-void nes_pachinko_device::device_reset()
-{
- m_latch = 0;
-}
-
-
-//-------------------------------------------------
-// read
-//-------------------------------------------------
-
-uint8_t nes_pachinko_device::read_exp(offs_t offset)
-{
- uint8_t ret = 0;
- // this controller behaves like a standard P3 joypad, with longer stream of inputs
- if (offset == 0) //$4016
- {
- ret |= (m_latch & 1) << 1;
- m_latch >>= 1;
- }
- return ret;
-}
-
-//-------------------------------------------------
-// write
-//-------------------------------------------------
-
-void nes_pachinko_device::write(uint8_t data)
+void nes_pachinko_device::set_latch()
{
- if (data & 0x01)
- return;
-
m_latch = m_joypad->read();
- m_latch |= ((m_trigger->read() ^ 0xff) & 0xff) << 8;
- m_latch |= 0xff0000;
+ m_latch |= ~bitswap<8>(m_trigger->read(), 0, 1, 2, 3, 4, 5, 6, 7) << 8;
}
diff --git a/src/devices/bus/nes_ctrl/pachinko.h b/src/devices/bus/nes_ctrl/pachinko.h
index f4f7feae596..709a589080d 100644
--- a/src/devices/bus/nes_ctrl/pachinko.h
+++ b/src/devices/bus/nes_ctrl/pachinko.h
@@ -2,7 +2,7 @@
// copyright-holders:Fabio Priuli
/**********************************************************************
- Nintendo Family Computer Pachinko Controller
+ Nintendo Family Computer Coconuts Japan CJPC-102 Pachinko Controller
**********************************************************************/
@@ -11,7 +11,7 @@
#pragma once
-#include "ctrl.h"
+#include "joypad.h"
//**************************************************************************
@@ -20,28 +20,23 @@
// ======================> nes_pachinko_device
-class nes_pachinko_device : public device_t,
- public device_nes_control_port_interface
+class nes_pachinko_device : public nes_fcpadexp_device
{
public:
// construction/destruction
- nes_pachinko_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
-
- virtual ioport_constructor device_input_ports() const override;
+ nes_pachinko_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 ioport_constructor device_input_ports() const override ATTR_COLD;
- virtual uint8_t read_exp(offs_t offset) override;
- virtual void write(uint8_t data) override;
+ virtual void set_latch() override;
- required_ioport m_joypad;
+private:
required_ioport m_trigger;
- uint32_t m_latch;
};
+
// device type definition
DECLARE_DEVICE_TYPE(NES_PACHINKO, nes_pachinko_device)
diff --git a/src/devices/bus/nes_ctrl/partytap.cpp b/src/devices/bus/nes_ctrl/partytap.cpp
index b9029ab2f3a..b06be261e49 100644
--- a/src/devices/bus/nes_ctrl/partytap.cpp
+++ b/src/devices/bus/nes_ctrl/partytap.cpp
@@ -2,7 +2,7 @@
// copyright-holders:Fabio Priuli
/**********************************************************************
- Nintendo Family Computer Yonezawa / PartyRoom 21 Party Tap Controller
+ Nintendo Family Computer Yonezawa / Party Room 21 Partytap Controller
**********************************************************************/
@@ -13,7 +13,7 @@
// DEVICE DEFINITIONS
//**************************************************************************
-DEFINE_DEVICE_TYPE(NES_PARTYTAP, nes_partytap_device, "nes_partytap", "Yonezawa Party Tap Controller")
+DEFINE_DEVICE_TYPE(NES_PARTYTAP, nes_partytap_device, "nes_partytap", "Yonezawa Partytap Controller")
static INPUT_PORTS_START( nes_partytap )
@@ -44,12 +44,11 @@ ioport_constructor nes_partytap_device::device_input_ports() const
// nes_partytap_device - constructor
//-------------------------------------------------
-nes_partytap_device::nes_partytap_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) :
- device_t(mconfig, NES_PARTYTAP, tag, owner, clock),
- device_nes_control_port_interface(mconfig, *this),
- m_inputs(*this, "INPUTS"),
- m_mode(0),
- m_latch(0)
+nes_partytap_device::nes_partytap_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock)
+ : device_t(mconfig, NES_PARTYTAP, tag, owner, clock)
+ , device_nes_control_port_interface(mconfig, *this)
+ , m_inputs(*this, "INPUTS")
+ , m_latch(0)
{
}
@@ -61,18 +60,7 @@ nes_partytap_device::nes_partytap_device(const machine_config &mconfig, const ch
void nes_partytap_device::device_start()
{
save_item(NAME(m_latch));
- save_item(NAME(m_mode));
-}
-
-
-//-------------------------------------------------
-// device_reset
-//-------------------------------------------------
-
-void nes_partytap_device::device_reset()
-{
- m_mode = 0xe0;
- m_latch = 0;
+ save_item(NAME(m_strobe));
}
@@ -80,15 +68,16 @@ void nes_partytap_device::device_reset()
// read
//-------------------------------------------------
-uint8_t nes_partytap_device::read_exp(offs_t offset)
+u8 nes_partytap_device::read_exp(offs_t offset)
{
- uint8_t ret = 0;
+ u8 ret = 0;
if (offset == 1) //$4017
{
- ret |= m_latch & 0x1c;
+ if (m_strobe)
+ m_latch = m_inputs->read();
+ ret = m_latch & 0x1c;
m_latch >>= 3;
- // append mode bits
- m_latch |= m_mode;
+ m_latch |= 0xa0; // after first two reads, 0x14 will be returned
}
return ret;
}
@@ -97,14 +86,8 @@ uint8_t nes_partytap_device::read_exp(offs_t offset)
// write
//-------------------------------------------------
-void nes_partytap_device::write(uint8_t data)
+void nes_partytap_device::write(u8 data)
{
- // inputs are read in two chunks of 3 bits, before the second one is read bit2 is written here
- // probably a mechanism for the game to detect which group of inputs is being read
- m_mode = BIT(data, 2) ? 0xa0 : 0xe0;
-
- if (data & 0x01)
- return;
-
- m_latch = m_inputs->read();
+ if (write_strobe(data))
+ m_latch = m_inputs->read();
}
diff --git a/src/devices/bus/nes_ctrl/partytap.h b/src/devices/bus/nes_ctrl/partytap.h
index c3da2278aed..4568665749a 100644
--- a/src/devices/bus/nes_ctrl/partytap.h
+++ b/src/devices/bus/nes_ctrl/partytap.h
@@ -2,7 +2,7 @@
// copyright-holders:Fabio Priuli
/**********************************************************************
- Nintendo Family Computer Yonezawa / PartyRoom 21 Party Tap Controller
+ Nintendo Family Computer Yonezawa / Party Room 21 Partytap Controller
**********************************************************************/
@@ -25,23 +25,22 @@ class nes_partytap_device : public device_t,
{
public:
// construction/destruction
- nes_partytap_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
+ nes_partytap_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock);
- virtual ioport_constructor device_input_ports() const 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 uint8_t read_exp(offs_t offset) override;
- virtual void write(uint8_t data) override;
+ virtual void device_start() override ATTR_COLD;
+ virtual ioport_constructor device_input_ports() const override ATTR_COLD;
+private:
required_ioport m_inputs;
- uint8_t m_mode;
- uint32_t m_latch;
+ u8 m_latch;
};
+
// device type definition
DECLARE_DEVICE_TYPE(NES_PARTYTAP, nes_partytap_device)
diff --git a/src/devices/bus/nes_ctrl/powerpad.cpp b/src/devices/bus/nes_ctrl/powerpad.cpp
index 40a31ba89bc..688e73e3b12 100644
--- a/src/devices/bus/nes_ctrl/powerpad.cpp
+++ b/src/devices/bus/nes_ctrl/powerpad.cpp
@@ -19,43 +19,43 @@ DEFINE_DEVICE_TYPE(NES_POWERPAD, nes_powerpad_device, "nes_powerpad", "Bandai Po
static INPUT_PORTS_START( nes_powerpad )
PORT_START("LAYOUT")
PORT_CONFNAME( 0x01, 0x00, "Power Pad Button Layout")
- PORT_CONFSETTING( 0x00, "Side A" )
- PORT_CONFSETTING( 0x01, "Side B" )
+ PORT_CONFSETTING( 0x00, "Side A" )
+ PORT_CONFSETTING( 0x01, "Side B" )
// difference between the two sides is that we mirror the key mapping to match the real pad layout!
- PORT_START("POWERPAD1")
+ PORT_START("POWERPAD.0")
// side A layout
- PORT_BIT( 0x01, IP_ACTIVE_HIGH, IPT_KEYPAD ) PORT_NAME("PowerPad Top1") PORT_CODE(KEYCODE_Y) PORT_CONDITION("LAYOUT", 0x01, EQUALS, 0x00)
- PORT_BIT( 0x02, IP_ACTIVE_HIGH, IPT_UNUSED ) PORT_CONDITION("LAYOUT", 0x01, EQUALS, 0x00)
- PORT_BIT( 0x04, IP_ACTIVE_HIGH, IPT_KEYPAD ) PORT_NAME("PowerPad Mid1") PORT_CODE(KEYCODE_J) PORT_CONDITION("LAYOUT", 0x01, EQUALS, 0x00)
- PORT_BIT( 0x08, IP_ACTIVE_HIGH, IPT_UNUSED ) PORT_CONDITION("LAYOUT", 0x01, EQUALS, 0x00)
- PORT_BIT( 0x10, IP_ACTIVE_HIGH, IPT_KEYPAD ) PORT_NAME("PowerPad Mid2") PORT_CODE(KEYCODE_H) PORT_CONDITION("LAYOUT", 0x01, EQUALS, 0x00)
- PORT_BIT( 0x20, IP_ACTIVE_HIGH, IPT_KEYPAD ) PORT_NAME("PowerPad Low1") PORT_CODE(KEYCODE_N) PORT_CONDITION("LAYOUT", 0x01, EQUALS, 0x00)
- PORT_BIT( 0x40, IP_ACTIVE_HIGH, IPT_KEYPAD ) PORT_NAME("PowerPad Low2") PORT_CODE(KEYCODE_B) PORT_CONDITION("LAYOUT", 0x01, EQUALS, 0x00)
- PORT_BIT( 0x80, IP_ACTIVE_HIGH, IPT_KEYPAD ) PORT_NAME("PowerPad Mid3") PORT_CODE(KEYCODE_G) PORT_CONDITION("LAYOUT", 0x01, EQUALS, 0x00)
+ PORT_BIT( 0x01, IP_ACTIVE_HIGH, IPT_BUTTON2 ) PORT_NAME("PowerPad Top2") PORT_CODE(KEYCODE_Y) PORT_CONDITION("LAYOUT", 0x01, EQUALS, 0x00)
+ PORT_BIT( 0x02, IP_ACTIVE_HIGH, IPT_UNUSED ) PORT_CONDITION("LAYOUT", 0x01, EQUALS, 0x00)
+ PORT_BIT( 0x04, IP_ACTIVE_HIGH, IPT_BUTTON5 ) PORT_NAME("PowerPad Mid4") PORT_CODE(KEYCODE_J) PORT_CONDITION("LAYOUT", 0x01, EQUALS, 0x00)
+ PORT_BIT( 0x08, IP_ACTIVE_HIGH, IPT_UNUSED ) PORT_CONDITION("LAYOUT", 0x01, EQUALS, 0x00)
+ PORT_BIT( 0x10, IP_ACTIVE_HIGH, IPT_BUTTON6 ) PORT_NAME("PowerPad Mid3") PORT_CODE(KEYCODE_H) PORT_CONDITION("LAYOUT", 0x01, EQUALS, 0x00)
+ PORT_BIT( 0x20, IP_ACTIVE_HIGH, IPT_BUTTON10 ) PORT_NAME("PowerPad Low2") PORT_CODE(KEYCODE_N) PORT_CONDITION("LAYOUT", 0x01, EQUALS, 0x00)
+ PORT_BIT( 0x40, IP_ACTIVE_HIGH, IPT_BUTTON11 ) PORT_NAME("PowerPad Low1") PORT_CODE(KEYCODE_B) PORT_CONDITION("LAYOUT", 0x01, EQUALS, 0x00)
+ PORT_BIT( 0x80, IP_ACTIVE_HIGH, IPT_BUTTON7 ) PORT_NAME("PowerPad Mid2") PORT_CODE(KEYCODE_G) PORT_CONDITION("LAYOUT", 0x01, EQUALS, 0x00)
// side B layout
- PORT_BIT( 0x01, IP_ACTIVE_HIGH, IPT_KEYPAD ) PORT_NAME("PowerPad 2") PORT_CODE(KEYCODE_T) PORT_CONDITION("LAYOUT", 0x01, EQUALS, 0x01)
- PORT_BIT( 0x02, IP_ACTIVE_HIGH, IPT_KEYPAD ) PORT_NAME("PowerPad 1") PORT_CODE(KEYCODE_R) PORT_CONDITION("LAYOUT", 0x01, EQUALS, 0x01)
- PORT_BIT( 0x04, IP_ACTIVE_HIGH, IPT_KEYPAD ) PORT_NAME("PowerPad 5") PORT_CODE(KEYCODE_F) PORT_CONDITION("LAYOUT", 0x01, EQUALS, 0x01)
- PORT_BIT( 0x08, IP_ACTIVE_HIGH, IPT_KEYPAD ) PORT_NAME("PowerPad 9") PORT_CODE(KEYCODE_V) PORT_CONDITION("LAYOUT", 0x01, EQUALS, 0x01)
- PORT_BIT( 0x10, IP_ACTIVE_HIGH, IPT_KEYPAD ) PORT_NAME("PowerPad 6") PORT_CODE(KEYCODE_G) PORT_CONDITION("LAYOUT", 0x01, EQUALS, 0x01)
- PORT_BIT( 0x20, IP_ACTIVE_HIGH, IPT_KEYPAD ) PORT_NAME("PowerPad 10") PORT_CODE(KEYCODE_B) PORT_CONDITION("LAYOUT", 0x01, EQUALS, 0x01)
- PORT_BIT( 0x40, IP_ACTIVE_HIGH, IPT_KEYPAD ) PORT_NAME("PowerPad 11") PORT_CODE(KEYCODE_N) PORT_CONDITION("LAYOUT", 0x01, EQUALS, 0x01)
- PORT_BIT( 0x80, IP_ACTIVE_HIGH, IPT_KEYPAD ) PORT_NAME("PowerPad 7") PORT_CODE(KEYCODE_H) PORT_CONDITION("LAYOUT", 0x01, EQUALS, 0x01)
-
- PORT_START("POWERPAD2")
+ PORT_BIT( 0x01, IP_ACTIVE_HIGH, IPT_BUTTON2 ) PORT_NAME("PowerPad 2") PORT_CODE(KEYCODE_T) PORT_CONDITION("LAYOUT", 0x01, EQUALS, 0x01)
+ PORT_BIT( 0x02, IP_ACTIVE_HIGH, IPT_BUTTON1 ) PORT_NAME("PowerPad 1") PORT_CODE(KEYCODE_R) PORT_CONDITION("LAYOUT", 0x01, EQUALS, 0x01)
+ PORT_BIT( 0x04, IP_ACTIVE_HIGH, IPT_BUTTON5 ) PORT_NAME("PowerPad 5") PORT_CODE(KEYCODE_F) PORT_CONDITION("LAYOUT", 0x01, EQUALS, 0x01)
+ PORT_BIT( 0x08, IP_ACTIVE_HIGH, IPT_BUTTON9 ) PORT_NAME("PowerPad 9") PORT_CODE(KEYCODE_V) PORT_CONDITION("LAYOUT", 0x01, EQUALS, 0x01)
+ PORT_BIT( 0x10, IP_ACTIVE_HIGH, IPT_BUTTON6 ) PORT_NAME("PowerPad 6") PORT_CODE(KEYCODE_G) PORT_CONDITION("LAYOUT", 0x01, EQUALS, 0x01)
+ PORT_BIT( 0x20, IP_ACTIVE_HIGH, IPT_BUTTON10 ) PORT_NAME("PowerPad 10") PORT_CODE(KEYCODE_B) PORT_CONDITION("LAYOUT", 0x01, EQUALS, 0x01)
+ PORT_BIT( 0x40, IP_ACTIVE_HIGH, IPT_BUTTON11 ) PORT_NAME("PowerPad 11") PORT_CODE(KEYCODE_N) PORT_CONDITION("LAYOUT", 0x01, EQUALS, 0x01)
+ PORT_BIT( 0x80, IP_ACTIVE_HIGH, IPT_BUTTON7 ) PORT_NAME("PowerPad 7") PORT_CODE(KEYCODE_H) PORT_CONDITION("LAYOUT", 0x01, EQUALS, 0x01)
+
+ PORT_START("POWERPAD.1")
// side A layout
- PORT_BIT( 0x01, IP_ACTIVE_HIGH, IPT_UNUSED ) PORT_CONDITION("LAYOUT", 0x01, EQUALS, 0x00)
- PORT_BIT( 0x02, IP_ACTIVE_HIGH, IPT_KEYPAD ) PORT_NAME("PowerPad Top2") PORT_CODE(KEYCODE_T) PORT_CONDITION("LAYOUT", 0x01, EQUALS, 0x00)
- PORT_BIT( 0x04, IP_ACTIVE_HIGH, IPT_UNUSED ) PORT_CONDITION("LAYOUT", 0x01, EQUALS, 0x00)
- PORT_BIT( 0x08, IP_ACTIVE_HIGH, IPT_KEYPAD ) PORT_NAME("PowerPad Mid4") PORT_CODE(KEYCODE_F) PORT_CONDITION("LAYOUT", 0x01, EQUALS, 0x00)
- PORT_BIT( 0xf0, IP_ACTIVE_HIGH, IPT_UNUSED ) PORT_CONDITION("LAYOUT", 0x01, EQUALS, 0x00)
+ PORT_BIT( 0x01, IP_ACTIVE_HIGH, IPT_UNUSED ) PORT_CONDITION("LAYOUT", 0x01, EQUALS, 0x00)
+ PORT_BIT( 0x02, IP_ACTIVE_HIGH, IPT_BUTTON3 ) PORT_NAME("PowerPad Top1") PORT_CODE(KEYCODE_T) PORT_CONDITION("LAYOUT", 0x01, EQUALS, 0x00)
+ PORT_BIT( 0x04, IP_ACTIVE_HIGH, IPT_UNUSED ) PORT_CONDITION("LAYOUT", 0x01, EQUALS, 0x00)
+ PORT_BIT( 0x08, IP_ACTIVE_HIGH, IPT_BUTTON8 ) PORT_NAME("PowerPad Mid1") PORT_CODE(KEYCODE_F) PORT_CONDITION("LAYOUT", 0x01, EQUALS, 0x00)
+ PORT_BIT( 0xf0, IP_ACTIVE_LOW, IPT_UNUSED ) PORT_CONDITION("LAYOUT", 0x01, EQUALS, 0x00)
// side B layout
- PORT_BIT( 0x01, IP_ACTIVE_HIGH, IPT_KEYPAD ) PORT_NAME("PowerPad 4") PORT_CODE(KEYCODE_U) PORT_CONDITION("LAYOUT", 0x01, EQUALS, 0x01)
- PORT_BIT( 0x02, IP_ACTIVE_HIGH, IPT_KEYPAD ) PORT_NAME("PowerPad 3") PORT_CODE(KEYCODE_Y) PORT_CONDITION("LAYOUT", 0x01, EQUALS, 0x01)
- PORT_BIT( 0x04, IP_ACTIVE_HIGH, IPT_KEYPAD ) PORT_NAME("PowerPad 12") PORT_CODE(KEYCODE_M) PORT_CONDITION("LAYOUT", 0x01, EQUALS, 0x01)
- PORT_BIT( 0x08, IP_ACTIVE_HIGH, IPT_KEYPAD ) PORT_NAME("PowerPad 8") PORT_CODE(KEYCODE_J) PORT_CONDITION("LAYOUT", 0x01, EQUALS, 0x01)
- PORT_BIT( 0xf0, IP_ACTIVE_HIGH, IPT_UNUSED ) PORT_CONDITION("LAYOUT", 0x01, EQUALS, 0x01)
+ PORT_BIT( 0x01, IP_ACTIVE_HIGH, IPT_BUTTON4 ) PORT_NAME("PowerPad 4") PORT_CODE(KEYCODE_U) PORT_CONDITION("LAYOUT", 0x01, EQUALS, 0x01)
+ PORT_BIT( 0x02, IP_ACTIVE_HIGH, IPT_BUTTON3 ) PORT_NAME("PowerPad 3") PORT_CODE(KEYCODE_Y) PORT_CONDITION("LAYOUT", 0x01, EQUALS, 0x01)
+ PORT_BIT( 0x04, IP_ACTIVE_HIGH, IPT_BUTTON12 ) PORT_NAME("PowerPad 12") PORT_CODE(KEYCODE_M) PORT_CONDITION("LAYOUT", 0x01, EQUALS, 0x01)
+ PORT_BIT( 0x08, IP_ACTIVE_HIGH, IPT_BUTTON8 ) PORT_NAME("PowerPad 8") PORT_CODE(KEYCODE_J) PORT_CONDITION("LAYOUT", 0x01, EQUALS, 0x01)
+ PORT_BIT( 0xf0, IP_ACTIVE_LOW, IPT_UNUSED ) PORT_CONDITION("LAYOUT", 0x01, EQUALS, 0x01)
INPUT_PORTS_END
@@ -78,11 +78,10 @@ ioport_constructor nes_powerpad_device::device_input_ports() const
// nes_powerpad_device - constructor
//-------------------------------------------------
-nes_powerpad_device::nes_powerpad_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) :
- device_t(mconfig, NES_POWERPAD, tag, owner, clock),
- device_nes_control_port_interface(mconfig, *this),
- m_ipt1(*this, "POWERPAD1"),
- m_ipt2(*this, "POWERPAD2")
+nes_powerpad_device::nes_powerpad_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock)
+ : device_t(mconfig, NES_POWERPAD, tag, owner, clock)
+ , device_nes_control_port_interface(mconfig, *this)
+ , m_ipt(*this, "POWERPAD.%u", 0)
{
}
@@ -94,31 +93,26 @@ nes_powerpad_device::nes_powerpad_device(const machine_config &mconfig, const ch
void nes_powerpad_device::device_start()
{
save_item(NAME(m_latch));
+ save_item(NAME(m_strobe));
}
//-------------------------------------------------
-// device_reset
+// read
//-------------------------------------------------
-void nes_powerpad_device::device_reset()
+u8 nes_powerpad_device::read_bit34()
{
- m_latch[0] = 0;
- m_latch[1] = 0;
-}
+ u8 ret = 0;
+ for (int i = 0; i < 2; i++)
+ {
+ if (m_strobe)
+ m_latch[i] = m_ipt[i]->read();
+ ret |= (m_latch[i] & 1) << (i + 3);
+ m_latch[i] = (m_latch[i] >> 1) | 0x80;
+ }
-//-------------------------------------------------
-// read
-//-------------------------------------------------
-
-uint8_t nes_powerpad_device::read_bit34()
-{
- uint8_t ret = 0;
- ret |= (m_latch[0] & 0x01) << 3;
- ret |= (m_latch[1] & 0x01) << 4;
- m_latch[0] >>= 1;
- m_latch[1] >>= 1;
return ret;
}
@@ -126,11 +120,9 @@ uint8_t nes_powerpad_device::read_bit34()
// write
//-------------------------------------------------
-void nes_powerpad_device::write(uint8_t data)
+void nes_powerpad_device::write(u8 data)
{
- if (data & 0x01)
- return;
-
- m_latch[0] = m_ipt1->read();
- m_latch[1] = m_ipt2->read() | 0xf0;
+ if (write_strobe(data))
+ for (int i = 0; i < 2; i++)
+ m_latch[i] = m_ipt[i]->read();
}
diff --git a/src/devices/bus/nes_ctrl/powerpad.h b/src/devices/bus/nes_ctrl/powerpad.h
index 1e46f8402dc..8fa8565ad26 100644
--- a/src/devices/bus/nes_ctrl/powerpad.h
+++ b/src/devices/bus/nes_ctrl/powerpad.h
@@ -25,22 +25,19 @@ class nes_powerpad_device : public device_t,
{
public:
// construction/destruction
- nes_powerpad_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
+ nes_powerpad_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock);
- virtual ioport_constructor device_input_ports() const override;
+ virtual u8 read_bit34() override;
+ virtual void write(u8 data) override;
protected:
// device-level overrides
- virtual void device_start() override;
- virtual void device_reset() override;
-
- virtual uint8_t read_bit34() override;
- virtual void write(uint8_t data) override;
+ virtual void device_start() override ATTR_COLD;
+ virtual ioport_constructor device_input_ports() const override ATTR_COLD;
private:
- required_ioport m_ipt1;
- required_ioport m_ipt2;
- uint32_t m_latch[2];
+ required_ioport_array<2> m_ipt;
+ u8 m_latch[2];
};
diff --git a/src/devices/bus/nes_ctrl/rob.cpp b/src/devices/bus/nes_ctrl/rob.cpp
new file mode 100644
index 00000000000..5e101d55042
--- /dev/null
+++ b/src/devices/bus/nes_ctrl/rob.cpp
@@ -0,0 +1,139 @@
+// license:BSD-3-Clause
+// copyright-holders:hap
+/**********************************************************************
+
+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)
+
+**********************************************************************/
+
+#include "emu.h"
+#include "rob.h"
+
+#include "nes_rob.lh"
+
+//**************************************************************************
+// DEVICE DEFINITIONS
+//**************************************************************************
+
+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)
+ PORT_START("EYE_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)
+INPUT_PORTS_END
+
+ioport_constructor nes_rob_device::device_input_ports() const
+{
+ return INPUT_PORTS_NAME( nes_rob );
+}
+
+
+//**************************************************************************
+// LIVE DEVICE
+//**************************************************************************
+
+//-------------------------------------------------
+// constructor
+//-------------------------------------------------
+
+nes_rob_device::nes_rob_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock)
+ : device_t(mconfig, NES_ROB, tag, owner, clock)
+ , device_nes_control_port_interface(mconfig, *this)
+ , m_maincpu(*this, "maincpu")
+ , m_sensor(*this, "sensor")
+ , m_eye_x(*this, "EYE_X")
+ , m_eye_y(*this, "EYE_Y")
+ , m_motor_out(*this, "rob_motor.%u", 0U)
+ , m_led_out(*this, "rob_led")
+{
+}
+
+
+//-------------------------------------------------
+// device_start
+//-------------------------------------------------
+
+void nes_rob_device::device_start()
+{
+ // resolve handlers
+ m_motor_out.resolve();
+ m_led_out.resolve();
+}
+
+
+//-------------------------------------------------
+// R.O.B. specific handlers
+//-------------------------------------------------
+
+u8 nes_rob_device::input_r()
+{
+ // R00: lightsensor
+ 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)
+{
+ switch (offset & 3)
+ {
+ case 0:
+ // R03: led
+ m_led_out = BIT(data, 3);
+ break;
+
+ case 1:
+ // R10-R13: motors: down, up, close, open
+ for (int i = 0; i < 4; i++)
+ m_motor_out[i] = BIT(data, i);
+ break;
+
+ case 2:
+ // R20,R21: motors: right, left
+ for (int i = 0; i < 2; i++)
+ m_motor_out[i + 4] = BIT(data, i);
+ break;
+
+ default:
+ break;
+ }
+}
+
+void nes_rob_device::device_add_mconfig(machine_config &config)
+{
+ SM590(config, m_maincpu, 455_kHz_XTAL);
+ m_maincpu->read_r<0>().set(FUNC(nes_rob_device::input_r));
+ m_maincpu->write_r<0>().set(FUNC(nes_rob_device::output_w));
+ m_maincpu->write_r<1>().set(FUNC(nes_rob_device::output_w));
+ m_maincpu->write_r<2>().set(FUNC(nes_rob_device::output_w));
+ m_maincpu->write_r<3>().set(FUNC(nes_rob_device::output_w));
+
+ NES_ZAPPER_SENSOR(config, m_sensor, 0);
+ if (m_port != nullptr)
+ m_sensor->set_screen_tag(m_port->m_screen);
+
+ // must use -numscreens 2 to see the output status
+ config.set_default_layout(layout_nes_rob);
+}
+
+ROM_START( nes_rob )
+ ROM_REGION( 0x200, "maincpu", 0 )
+ ROM_LOAD( "rfc-cpu10.ic1", 0x000, 0x200, CRC(f9c96b9c) SHA1(a87e2f0f5e454c093d1352ac368aa9e82e9f6790) )
+ROM_END
+
+const tiny_rom_entry *nes_rob_device::device_rom_region() const
+{
+ return ROM_NAME(nes_rob);
+}
diff --git a/src/devices/bus/nes_ctrl/rob.h b/src/devices/bus/nes_ctrl/rob.h
new file mode 100644
index 00000000000..445cb5292e2
--- /dev/null
+++ b/src/devices/bus/nes_ctrl/rob.h
@@ -0,0 +1,54 @@
+// license:BSD-3-Clause
+// copyright-holders:hap
+/**********************************************************************
+
+ Nintendo HVC-012 Family Computer Robot / Nintendo NES-012 R.O.B.
+
+**********************************************************************/
+
+#ifndef MAME_BUS_NES_CTRL_ROB_H
+#define MAME_BUS_NES_CTRL_ROB_H
+
+#pragma once
+
+#include "ctrl.h"
+#include "cpu/sm510/sm590.h"
+#include "zapper_sensor.h"
+
+
+//**************************************************************************
+// TYPE DEFINITIONS
+//**************************************************************************
+
+// ======================> nes_rob_device
+
+class nes_rob_device : public device_t,
+ public device_nes_control_port_interface
+{
+public:
+ // construction/destruction
+ nes_rob_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock);
+
+protected:
+ // device-level overrides
+ virtual void device_start() override ATTR_COLD;
+ virtual void device_add_mconfig(machine_config &config) override ATTR_COLD;
+ virtual const tiny_rom_entry *device_rom_region() const override ATTR_COLD;
+ virtual ioport_constructor device_input_ports() const override ATTR_COLD;
+
+private:
+ required_device<sm590_device> m_maincpu;
+ required_device<nes_zapper_sensor_device> m_sensor;
+ required_ioport m_eye_x;
+ required_ioport m_eye_y;
+ output_finder<6> m_motor_out;
+ output_finder<> m_led_out;
+
+ u8 input_r();
+ void output_w(offs_t offset, u8 data);
+};
+
+// device type definition
+DECLARE_DEVICE_TYPE(NES_ROB, nes_rob_device)
+
+#endif // MAME_BUS_NES_CTRL_ROB_H
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..5d43c9be597
--- /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 ATTR_COLD;
+
+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/snesadapter.cpp b/src/devices/bus/nes_ctrl/snesadapter.cpp
new file mode 100644
index 00000000000..8b26824a80d
--- /dev/null
+++ b/src/devices/bus/nes_ctrl/snesadapter.cpp
@@ -0,0 +1,72 @@
+// license:BSD-3-Clause
+// copyright-holders:kmg
+/**********************************************************************
+
+ Nintendo Family Computer & Entertainment System SNES controller port adapter
+
+**********************************************************************/
+
+#include "emu.h"
+#include "snesadapter.h"
+// slot devices
+#include "bus/snes_ctrl/joypad.h"
+#include "bus/snes_ctrl/mouse.h"
+
+
+//**************************************************************************
+// DEVICE DEFINITIONS
+//**************************************************************************
+
+DEFINE_DEVICE_TYPE(NES_SNESADAPTER, nes_snesadapter_device, "nes_snesadapter", "SNES Controller Port Adapter")
+
+
+static void snes_controllers(device_slot_interface &device)
+{
+ device.option_add("snes_joypad", SNES_JOYPAD);
+ device.option_add("snes_mouse", SNES_MOUSE);
+}
+
+
+//-------------------------------------------------
+// device_add_mconfig - add device configuration
+//-------------------------------------------------
+
+void nes_snesadapter_device::device_add_mconfig(machine_config &config)
+{
+ SNES_CONTROL_PORT(config, m_snesctrl, snes_controllers, nullptr);
+}
+
+
+//**************************************************************************
+// LIVE DEVICE
+//**************************************************************************
+
+//-------------------------------------------------
+// nes_snesadapter_device - constructor
+//-------------------------------------------------
+
+nes_snesadapter_device::nes_snesadapter_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock)
+ : device_t(mconfig, NES_SNESADAPTER, tag, owner, clock)
+ , device_nes_control_port_interface(mconfig, *this)
+ , m_snesctrl(*this, "port")
+{
+}
+
+
+//-------------------------------------------------
+// read
+//-------------------------------------------------
+
+u8 nes_snesadapter_device::read_bit0()
+{
+ return m_snesctrl->read_pin4();
+}
+
+//-------------------------------------------------
+// write
+//-------------------------------------------------
+
+void nes_snesadapter_device::write(u8 data)
+{
+ m_snesctrl->write_strobe(data);
+}
diff --git a/src/devices/bus/nes_ctrl/snesadapter.h b/src/devices/bus/nes_ctrl/snesadapter.h
new file mode 100644
index 00000000000..dab91783a2a
--- /dev/null
+++ b/src/devices/bus/nes_ctrl/snesadapter.h
@@ -0,0 +1,46 @@
+// license:BSD-3-Clause
+// copyright-holders:kmg
+/**********************************************************************
+
+ Nintendo Family Computer & Entertainment System SNES controller port adapter
+
+**********************************************************************/
+
+#ifndef MAME_BUS_NES_CTRL_SNESADAPTER_H
+#define MAME_BUS_NES_CTRL_SNESADAPTER_H
+
+#pragma once
+
+#include "ctrl.h"
+#include "bus/snes_ctrl/ctrl.h"
+
+
+//**************************************************************************
+// TYPE DEFINITIONS
+//**************************************************************************
+
+// ======================> nes_snesadapter_device
+
+class nes_snesadapter_device : public device_t, public device_nes_control_port_interface
+{
+public:
+ // construction/destruction
+ nes_snesadapter_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock);
+
+ virtual u8 read_bit0() 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 ATTR_COLD;
+
+private:
+ required_device<snes_control_port_device> m_snesctrl;
+};
+
+
+// device type definition
+DECLARE_DEVICE_TYPE(NES_SNESADAPTER, nes_snesadapter_device)
+
+#endif // MAME_BUS_NES_CTRL_SNESADAPTER_H
diff --git a/src/devices/bus/nes_ctrl/suborkey.h b/src/devices/bus/nes_ctrl/suborkey.h
index a25324142d6..5d99ce14de8 100644
--- a/src/devices/bus/nes_ctrl/suborkey.h
+++ b/src/devices/bus/nes_ctrl/suborkey.h
@@ -27,15 +27,14 @@ public:
// construction/destruction
nes_suborkey_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
- virtual ioport_constructor device_input_ports() const override;
+ virtual uint8_t read_exp(offs_t offset) override;
+ virtual void write(uint8_t data) override;
protected:
// device-level overrides
- virtual void device_start() override;
- virtual void device_reset() override;
-
- virtual uint8_t read_exp(offs_t offset) override;
- virtual void write(uint8_t data) override;
+ virtual void device_start() override ATTR_COLD;
+ virtual void device_reset() override ATTR_COLD;
+ virtual ioport_constructor device_input_ports() const override ATTR_COLD;
private:
required_ioport_array<13> m_kbd;
diff --git a/src/devices/bus/nes_ctrl/turbofile.cpp b/src/devices/bus/nes_ctrl/turbofile.cpp
new file mode 100644
index 00000000000..fff73bef7b3
--- /dev/null
+++ b/src/devices/bus/nes_ctrl/turbofile.cpp
@@ -0,0 +1,140 @@
+// license:BSD-3-Clause
+// copyright-holders:kmg
+/**********************************************************************
+
+ Nintendo Family Computer ASCII Turbofile SRAM external storage device
+
+ The original 8K Turbofile, emulated here, has been seen with serials
+ AS-TF02 through AS-TF04, differences unknown. We do not support the
+ Turbo File II (yet?), but it appears to simply be a 32K version with
+ a manual switch to select between four 8K banks. Both devices also
+ sport a write protect switch.
+
+**********************************************************************/
+
+#include "emu.h"
+#include "turbofile.h"
+
+//**************************************************************************
+// DEVICE DEFINITIONS
+//**************************************************************************
+
+DEFINE_DEVICE_TYPE(NES_TURBOFILE, nes_turbofile_device, "nes_turbofile", "ASCII Turbofile Backup RAM")
+
+
+INPUT_CHANGED_MEMBER( nes_turbofile_device::lock_changed )
+{
+ m_locked = newval;
+ popmessage("Turbofile Protect Switch %s\n", m_locked ? "ON" : "OFF");
+}
+
+
+static INPUT_PORTS_START( nes_turbofile )
+ PORT_START("LOCK")
+ PORT_BIT( 0x01, IP_ACTIVE_HIGH, IPT_BUTTON1 ) PORT_NAME("Protect Switch") PORT_TOGGLE PORT_CHANGED_MEMBER(DEVICE_SELF, FUNC(nes_turbofile_device::lock_changed), 0)
+INPUT_PORTS_END
+
+//-------------------------------------------------
+// input_ports - device-specific input ports
+//-------------------------------------------------
+
+ioport_constructor nes_turbofile_device::device_input_ports() const
+{
+ return INPUT_PORTS_NAME( nes_turbofile );
+}
+
+
+//-------------------------------------------------
+// device_add_mconfig - add device configuration
+//-------------------------------------------------
+
+void nes_turbofile_device::device_add_mconfig(machine_config &config)
+{
+ NVRAM(config, "nvram", nvram_device::DEFAULT_NONE);
+}
+
+
+//**************************************************************************
+// LIVE DEVICE
+//**************************************************************************
+
+//-------------------------------------------------
+// nes_turbofile_device - constructor
+//-------------------------------------------------
+
+nes_turbofile_device::nes_turbofile_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock)
+ : device_t(mconfig, NES_TURBOFILE, tag, owner, clock)
+ , device_nes_control_port_interface(mconfig, *this)
+ , m_nvram(*this, "nvram")
+ , m_lock(*this, "LOCK")
+ , m_addr(0)
+ , m_bit(0)
+ , m_latch(0)
+ , m_locked(0)
+{
+}
+
+
+//-------------------------------------------------
+// device_start
+//-------------------------------------------------
+
+void nes_turbofile_device::device_start()
+{
+ // 8K RAM
+ m_ram = std::make_unique<u8[]>(0x2000);
+ m_nvram->set_base(m_ram.get(), 0x2000);
+
+ save_pointer(NAME(m_ram), 0x2000);
+ save_item(NAME(m_addr));
+ save_item(NAME(m_bit));
+ save_item(NAME(m_latch));
+ save_item(NAME(m_locked));
+}
+
+
+//-------------------------------------------------
+// device_reset
+//-------------------------------------------------
+
+void nes_turbofile_device::device_reset()
+{
+ m_locked = m_lock->read();
+}
+
+
+//-------------------------------------------------
+// read
+//-------------------------------------------------
+
+u8 nes_turbofile_device::read_exp(offs_t offset)
+{
+ return (offset == 1) ? BIT(m_ram[m_addr], m_bit) << 2 : 0;
+}
+
+//-------------------------------------------------
+// write
+//-------------------------------------------------
+
+void nes_turbofile_device::write(u8 data)
+{
+ if (!BIT(data, 1)) // reset position to start of RAM
+ {
+ m_addr = 0;
+ m_bit = 0;
+ }
+
+ if (!BIT(data, 2) && BIT(m_latch, 2))
+ {
+ if (!m_locked)
+ {
+ m_ram[m_addr] &= ~(1 << m_bit);
+ m_ram[m_addr] |= (data & 1) << m_bit;
+ }
+ m_bit = (m_bit + 1) & 0x07;
+ if (!m_bit)
+ m_addr = (m_addr + 1) & 0x1fff;
+ }
+
+ m_latch = data;
+}
diff --git a/src/devices/bus/nes_ctrl/turbofile.h b/src/devices/bus/nes_ctrl/turbofile.h
new file mode 100644
index 00000000000..b95a28c6024
--- /dev/null
+++ b/src/devices/bus/nes_ctrl/turbofile.h
@@ -0,0 +1,59 @@
+// license:BSD-3-Clause
+// copyright-holders:kmg
+/**********************************************************************
+
+ Nintendo Family Computer ASCII Turbofile SRAM external storage device
+
+**********************************************************************/
+
+#ifndef MAME_BUS_NES_CTRL_TURBOFILE_H
+#define MAME_BUS_NES_CTRL_TURBOFILE_H
+
+#pragma once
+
+#include "ctrl.h"
+#include "machine/nvram.h"
+
+
+//**************************************************************************
+// TYPE DEFINITIONS
+//**************************************************************************
+
+// ======================> nes_turbofile_device
+
+class nes_turbofile_device : public device_t,
+ public device_nes_control_port_interface
+{
+public:
+ // construction/destruction
+ nes_turbofile_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;
+
+ DECLARE_INPUT_CHANGED_MEMBER(lock_changed);
+
+protected:
+ // device-level overrides
+ virtual void device_start() override ATTR_COLD;
+ virtual void device_reset() override ATTR_COLD;
+
+ virtual ioport_constructor device_input_ports() const override ATTR_COLD;
+ virtual void device_add_mconfig(machine_config &config) override ATTR_COLD;
+
+private:
+ required_device<nvram_device> m_nvram;
+ required_ioport m_lock;
+
+ std::unique_ptr<u8[]> m_ram;
+ u16 m_addr;
+ u8 m_bit;
+ u8 m_latch;
+ u8 m_locked;
+};
+
+
+// device type definition
+DECLARE_DEVICE_TYPE(NES_TURBOFILE, nes_turbofile_device)
+
+#endif // MAME_BUS_NES_CTRL_TURBOFILE_H
diff --git a/src/devices/bus/nes_ctrl/zapper.cpp b/src/devices/bus/nes_ctrl/zapper.cpp
index da3df413a40..4a2b42d136a 100644
--- a/src/devices/bus/nes_ctrl/zapper.cpp
+++ b/src/devices/bus/nes_ctrl/zapper.cpp
@@ -7,7 +7,6 @@
**********************************************************************/
#include "emu.h"
-#include "screen.h"
#include "zapper.h"
//**************************************************************************
@@ -17,60 +16,69 @@
DEFINE_DEVICE_TYPE(NES_ZAPPER, nes_zapper_device, "nes_zapper", "Nintendo Zapper Lightgun")
-static INPUT_PORTS_START( nes_zapper )
- PORT_START("ZAPPER_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_BIT( 0xff, 0x80, IPT_LIGHTGUN_Y) PORT_CROSSHAIR(Y, 1.0, 0.0, 0) PORT_SENSITIVITY(50) PORT_KEYDELTA(30) PORT_MINMAX(0,255)
- PORT_START("ZAPPER_T")
- PORT_BIT( 0x10, IP_ACTIVE_HIGH, IPT_BUTTON1) PORT_NAME("Lightgun Trigger")
-INPUT_PORTS_END
-
-
//-------------------------------------------------
// input_ports - device-specific input ports
//-------------------------------------------------
+static INPUT_PORTS_START( nes_zapper )
+ 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( 0x01, IP_ACTIVE_HIGH, IPT_BUTTON1 ) PORT_NAME("Lightgun Trigger") PORT_CHANGED_MEMBER(DEVICE_SELF, FUNC(nes_zapper_device::trigger), 0)
+INPUT_PORTS_END
+
ioport_constructor nes_zapper_device::device_input_ports() const
{
return INPUT_PORTS_NAME( nes_zapper );
}
+INPUT_CHANGED_MEMBER(nes_zapper_device::trigger)
+{
+ // a trigger pull is active for around 3-4 frames
+ if (newval)
+ m_trigger->adjust(attotime::from_msec(50));
+}
-//**************************************************************************
-// LIVE DEVICE
-//**************************************************************************
-
//-------------------------------------------------
-// nes_zapper_device - constructor
+// device_add_mconfig - add device configuration
//-------------------------------------------------
-nes_zapper_device::nes_zapper_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) :
- device_t(mconfig, NES_ZAPPER, tag, owner, clock),
- device_nes_control_port_interface(mconfig, *this),
- m_lightx(*this, "ZAPPER_X"),
- m_lighty(*this, "ZAPPER_Y"),
- m_trigger(*this, "ZAPPER_T")
+void nes_zapper_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
+//**************************************************************************
+
//-------------------------------------------------
-// device_start
+// constructor
//-------------------------------------------------
-void nes_zapper_device::device_start()
+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, "GUN_X")
+ , m_lighty(*this, "GUN_Y")
{
}
//-------------------------------------------------
-// device_reset
+// device_start
//-------------------------------------------------
-void nes_zapper_device::device_reset()
+void nes_zapper_device::device_start()
{
+ m_trigger = timer_alloc(timer_expired_delegate());
}
@@ -78,39 +86,20 @@ void nes_zapper_device::device_reset()
// read
//-------------------------------------------------
-uint8_t nes_zapper_device::read_bit34()
+u8 nes_zapper_device::read_bit34()
{
- uint8_t ret = m_trigger->read();
- int x = m_lightx->read();
- int y = m_lighty->read();
-
- // update the screen if necessary
- if (!m_port->m_screen->vblank())
- {
- int vpos = m_port->m_screen->vpos();
- int hpos = m_port->m_screen->hpos();
-
- if (vpos > y || (vpos == y && hpos >= x))
- m_port->m_screen->update_now();
- }
-
- // get the pixel at the gun position
- rgb_t pix = m_port->m_screen->pixel(x, y);
-
- // check if the cursor is over a bright pixel
- // FIXME: still a gross hack
- if (pix.r() == 0xff && pix.b() == 0xff && pix.g() > 0x90)
- ret &= ~0x08; // sprite hit
- else
- ret |= 0x08; // no sprite hit
+ u8 ret = m_trigger->enabled() ? 0x10 : 0;
+
+ if (!m_sensor->detect_light(m_lightx->read(), m_lighty->read()))
+ ret |= 0x08;
return ret;
}
-uint8_t nes_zapper_device::read_exp(offs_t offset)
+u8 nes_zapper_device::read_exp(offs_t offset)
{
- uint8_t ret = 0;
+ u8 ret = 0;
if (offset == 1) // $4017
- ret |= nes_zapper_device::read_bit34();
+ ret = nes_zapper_device::read_bit34();
return ret;
}
diff --git a/src/devices/bus/nes_ctrl/zapper.h b/src/devices/bus/nes_ctrl/zapper.h
index 5ae68fd0a6e..f7ec17b7401 100644
--- a/src/devices/bus/nes_ctrl/zapper.h
+++ b/src/devices/bus/nes_ctrl/zapper.h
@@ -6,13 +6,14 @@
**********************************************************************/
-#ifndef MAME_BUS_NES_CTRL_ZAPPER
-#define MAME_BUS_NES_CTRL_ZAPPER
+#ifndef MAME_BUS_NES_CTRL_ZAPPER_H
+#define MAME_BUS_NES_CTRL_ZAPPER_H
#pragma once
-
#include "ctrl.h"
+#include "zapper_sensor.h"
+
//**************************************************************************
// TYPE DEFINITIONS
@@ -25,26 +26,28 @@ class nes_zapper_device : public device_t,
{
public:
// construction/destruction
- nes_zapper_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
+ nes_zapper_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock);
- virtual ioport_constructor device_input_ports() const override;
+ virtual u8 read_bit34() override;
+ virtual u8 read_exp(offs_t offset) override;
+
+ DECLARE_INPUT_CHANGED_MEMBER(trigger);
protected:
// device-level overrides
- virtual void device_start() override;
- virtual void device_reset() override;
-
- virtual uint8_t read_bit34() override;
- virtual uint8_t read_exp(offs_t offset) override;
+ virtual void device_start() override ATTR_COLD;
+ virtual void device_add_mconfig(machine_config &config) override ATTR_COLD;
+ virtual ioport_constructor device_input_ports() const override ATTR_COLD;
private:
+ required_device<nes_zapper_sensor_device> m_sensor;
required_ioport m_lightx;
required_ioport m_lighty;
- required_ioport m_trigger;
+ emu_timer *m_trigger;
};
// device type definition
DECLARE_DEVICE_TYPE(NES_ZAPPER, nes_zapper_device)
-#endif // MAME_BUS_NES_CTRL_ZAPPER
+#endif // MAME_BUS_NES_CTRL_ZAPPER_H
diff --git a/src/devices/bus/nes_ctrl/zapper_sensor.cpp b/src/devices/bus/nes_ctrl/zapper_sensor.cpp
new file mode 100644
index 00000000000..6d0bf53fc6d
--- /dev/null
+++ b/src/devices/bus/nes_ctrl/zapper_sensor.cpp
@@ -0,0 +1,72 @@
+// license:BSD-3-Clause
+// copyright-holders:kmg
+/**********************************************************************
+
+ HLE of the common photodiode reading routine used in the NES,
+ Vs. System, and PlayChoice-10 light guns, and R.O.B.
+
+ These all use a Sharp IR3T07, though the NES zapper is (always?)
+ seen with the IR3T07A revision.
+
+**********************************************************************/
+
+#include "emu.h"
+#include "zapper_sensor.h"
+
+//**************************************************************************
+// DEVICE DEFINITIONS
+//**************************************************************************
+
+DEFINE_DEVICE_TYPE(NES_ZAPPER_SENSOR, nes_zapper_sensor_device, "nes_zapper_sensor", "Nintendo Zapper Lightgun Photodiode")
+
+
+//**************************************************************************
+// LIVE DEVICE
+//**************************************************************************
+
+//-------------------------------------------------
+// constructor
+//-------------------------------------------------
+
+nes_zapper_sensor_device::nes_zapper_sensor_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock)
+ : device_t(mconfig, NES_ZAPPER_SENSOR, tag, owner, clock)
+ , m_screen(*this, finder_base::DUMMY_TAG)
+{
+}
+
+
+//-------------------------------------------------
+// detect_light
+//-------------------------------------------------
+
+bool nes_zapper_sensor_device::detect_light(int x, int y)
+{
+ int vpos = m_screen->vpos();
+ int hpos = m_screen->hpos();
+
+ // update the screen if necessary
+ if (!m_screen->vblank())
+ if (vpos > y - radius || (vpos == y - radius && hpos >= x - radius))
+ m_screen->update_now();
+
+ int sum = 0;
+ int scanned = 0;
+
+ // sum brightness of pixels nearby the gun position
+ for (int i = x - radius; i <= x + radius; i++)
+ for (int j = y - radius; j <= y + radius; j++)
+ // look at pixels within circular sensor
+ if ((x - i) * (x - i) + (y - j) * (y - j) <= radius * radius)
+ {
+ rgb_t pix = m_screen->pixel(i, j);
+
+ // only detect light if gun position is near, and behind, where the PPU is drawing on the CRT, from NesDev wiki:
+ // "Zap Ruder test ROM show that the photodiode stays on for about 26 scanlines with pure white, 24 scanlines with light gray, or 19 lines with dark gray."
+ if (j <= vpos && j > vpos - sustain && (j != vpos || i <= hpos))
+ sum += pix.r() + pix.g() + pix.b();
+ scanned++;
+ }
+
+ // light detected if average brightness is above threshold
+ return sum >= bright * scanned;
+}
diff --git a/src/devices/bus/nes_ctrl/zapper_sensor.h b/src/devices/bus/nes_ctrl/zapper_sensor.h
new file mode 100644
index 00000000000..0f556e27a34
--- /dev/null
+++ b/src/devices/bus/nes_ctrl/zapper_sensor.h
@@ -0,0 +1,53 @@
+// license:BSD-3-Clause
+// copyright-holders:kmg
+/**********************************************************************
+
+ HLE of the common photodiode reading routine used in the NES,
+ Vs. System, and PlayChoice-10 light guns, and R.O.B.
+
+**********************************************************************/
+
+#ifndef MAME_BUS_NES_CTRL_ZAPPER_SENSOR_H
+#define MAME_BUS_NES_CTRL_ZAPPER_SENSOR_H
+
+#pragma once
+
+#include "screen.h"
+
+
+//**************************************************************************
+// TYPE DEFINITIONS
+//**************************************************************************
+
+// ======================> nes_zapper_sensor_device
+
+class nes_zapper_sensor_device : public device_t
+{
+public:
+ // construction/destruction
+ nes_zapper_sensor_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock);
+
+ template <typename T> void set_screen_tag(T &&tag) { m_screen.set_tag(std::forward<T>(tag)); }
+
+ bool detect_light(int x, int y);
+
+protected:
+ // device-level overrides
+ virtual void device_start() override { }
+
+private:
+ // radius of circle picked up by the gun's photodiode
+ static constexpr int radius = 5;
+ // brightness threshold
+ static constexpr int bright = 0xc0;
+ // # of CRT scanlines that sustain brightness
+ static constexpr int sustain = 22;
+
+ required_device<screen_device> m_screen;
+};
+
+
+// device type definition
+DECLARE_DEVICE_TYPE(NES_ZAPPER_SENSOR, nes_zapper_sensor_device)
+
+#endif // MAME_BUS_NES_CTRL_ZAPPER_SENSOR_H
diff --git a/src/devices/bus/newbrain/eim.cpp b/src/devices/bus/newbrain/eim.cpp
index 3f0b7a19ee0..9b44f80b55f 100644
--- a/src/devices/bus/newbrain/eim.cpp
+++ b/src/devices/bus/newbrain/eim.cpp
@@ -113,7 +113,7 @@ newbrain_eim_device::newbrain_eim_device(const machine_config &mconfig, const ch
device_newbrain_expansion_slot_interface(mconfig, *this),
m_ctc(*this, Z80CTC_TAG),
m_acia(*this, MC6850_TAG),
- m_exp(*this, NEWBRAIN_EXPANSION_SLOT_TAG),
+ m_exp(*this, "exp"),
m_rom(*this, "eim"),
m_ram(*this, RAM_TAG)
{
@@ -185,7 +185,7 @@ void newbrain_eim_device::iorq_w(offs_t offset, uint8_t data, bool &prtov)
// anout_r -
//-------------------------------------------------
-READ8_MEMBER( newbrain_eim_device::anout_r )
+uint8_t newbrain_eim_device::anout_r()
{
return 0xff;
}
@@ -195,7 +195,7 @@ READ8_MEMBER( newbrain_eim_device::anout_r )
// anout_w -
//-------------------------------------------------
-WRITE8_MEMBER( newbrain_eim_device::anout_w )
+void newbrain_eim_device::anout_w(uint8_t data)
{
}
@@ -204,7 +204,7 @@ WRITE8_MEMBER( newbrain_eim_device::anout_w )
// anin_r -
//-------------------------------------------------
-READ8_MEMBER( newbrain_eim_device::anin_r )
+uint8_t newbrain_eim_device::anin_r()
{
return 0;
}
@@ -214,7 +214,7 @@ READ8_MEMBER( newbrain_eim_device::anin_r )
// anio_w -
//-------------------------------------------------
-WRITE8_MEMBER( newbrain_eim_device::anio_w )
+void newbrain_eim_device::anio_w(uint8_t data)
{
}
@@ -223,7 +223,7 @@ WRITE8_MEMBER( newbrain_eim_device::anio_w )
// 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 19b456338fd..bac4ff72ac7 100644
--- a/src/devices/bus/newbrain/eim.h
+++ b/src/devices/bus/newbrain/eim.h
@@ -33,19 +33,19 @@ public:
// construction/destruction
newbrain_eim_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
- DECLARE_READ8_MEMBER( anout_r );
- DECLARE_WRITE8_MEMBER( anout_w );
- DECLARE_READ8_MEMBER( anin_r );
- DECLARE_WRITE8_MEMBER( anio_w );
+ uint8_t anout_r();
+ void anout_w(uint8_t data);
+ uint8_t anin_r();
+ void anio_w(uint8_t data);
protected:
// device-level overrides
- virtual void device_start() override;
- virtual void device_reset() override;
+ virtual void device_start() override ATTR_COLD;
+ virtual void device_reset() override ATTR_COLD;
// optional information overrides
- virtual const tiny_rom_entry *device_rom_region() const override;
- virtual void device_add_mconfig(machine_config &config) override;
+ virtual const tiny_rom_entry *device_rom_region() const override ATTR_COLD;
+ virtual void device_add_mconfig(machine_config &config) override ATTR_COLD;
// device_newbrain_expansion_slot_interface overrides
virtual uint8_t mreq_r(offs_t offset, uint8_t data, bool &romov, int &exrm, bool &raminh) override;
@@ -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/exp.cpp b/src/devices/bus/newbrain/exp.cpp
index a1a9e2210ed..66f7d9d302a 100644
--- a/src/devices/bus/newbrain/exp.cpp
+++ b/src/devices/bus/newbrain/exp.cpp
@@ -28,7 +28,7 @@ DEFINE_DEVICE_TYPE(NEWBRAIN_EXPANSION_SLOT, newbrain_expansion_slot_device, "new
//-------------------------------------------------
device_newbrain_expansion_slot_interface::device_newbrain_expansion_slot_interface(const machine_config &mconfig, device_t &device) :
- device_slot_card_interface(mconfig,device)
+ device_interface(device, "newbrainexp")
{
m_slot = dynamic_cast<newbrain_expansion_slot_device *>(device.owner());
}
@@ -45,7 +45,8 @@ device_newbrain_expansion_slot_interface::device_newbrain_expansion_slot_interfa
newbrain_expansion_slot_device::newbrain_expansion_slot_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) :
device_t(mconfig, NEWBRAIN_EXPANSION_SLOT, tag, owner, clock),
- device_slot_interface(mconfig, *this), m_card(nullptr)
+ device_single_card_slot_interface<device_newbrain_expansion_slot_interface>(mconfig, *this),
+ m_card(nullptr)
{
}
@@ -56,7 +57,7 @@ newbrain_expansion_slot_device::newbrain_expansion_slot_device(const machine_con
void newbrain_expansion_slot_device::device_start()
{
- m_card = dynamic_cast<device_newbrain_expansion_slot_interface *>(get_card_device());
+ m_card = get_card_device();
}
diff --git a/src/devices/bus/newbrain/exp.h b/src/devices/bus/newbrain/exp.h
index e9e56c1bd66..cd250652428 100644
--- a/src/devices/bus/newbrain/exp.h
+++ b/src/devices/bus/newbrain/exp.h
@@ -43,13 +43,6 @@
//**************************************************************************
-// CONSTANTS
-//**************************************************************************
-
-#define NEWBRAIN_EXPANSION_SLOT_TAG "exp"
-
-
-//**************************************************************************
// TYPE DEFINITIONS
//**************************************************************************
@@ -58,7 +51,7 @@
class device_newbrain_expansion_slot_interface;
class newbrain_expansion_slot_device : public device_t,
- public device_slot_interface
+ public device_single_card_slot_interface<device_newbrain_expansion_slot_interface>
{
public:
// construction/destruction
@@ -83,8 +76,8 @@ public:
protected:
// device-level overrides
- virtual void device_start() override;
- virtual void device_reset() override;
+ virtual void device_start() override ATTR_COLD;
+ virtual void device_reset() override ATTR_COLD;
device_newbrain_expansion_slot_interface *m_card;
};
@@ -93,7 +86,7 @@ protected:
// ======================> device_newbrain_expansion_slot_interface
// class representing interface-specific live newbrain_expansion card
-class device_newbrain_expansion_slot_interface : public device_slot_card_interface
+class device_newbrain_expansion_slot_interface : public device_interface
{
public:
// memory access
diff --git a/src/devices/bus/newbrain/fdc.cpp b/src/devices/bus/newbrain/fdc.cpp
index 7cadbd0bddd..c726a36f020 100644
--- a/src/devices/bus/newbrain/fdc.cpp
+++ b/src/devices/bus/newbrain/fdc.cpp
@@ -113,10 +113,10 @@ void newbrain_fdc_device::device_add_mconfig(machine_config &config)
UPD765A(config, m_fdc, 8'000'000, false, true);
m_fdc->intrq_wr_callback().set(FUNC(newbrain_fdc_device::fdc_int_w));
- FLOPPY_CONNECTOR(config, UPD765_TAG ":0", newbrain_floppies, "525dd", floppy_image_device::default_floppy_formats);
- FLOPPY_CONNECTOR(config, UPD765_TAG ":1", newbrain_floppies, "525dd", floppy_image_device::default_floppy_formats);
- FLOPPY_CONNECTOR(config, UPD765_TAG ":2", newbrain_floppies, nullptr, floppy_image_device::default_floppy_formats);
- FLOPPY_CONNECTOR(config, UPD765_TAG ":3", newbrain_floppies, nullptr, floppy_image_device::default_floppy_formats);
+ FLOPPY_CONNECTOR(config, UPD765_TAG ":0", newbrain_floppies, "525dd", floppy_image_device::default_mfm_floppy_formats);
+ FLOPPY_CONNECTOR(config, UPD765_TAG ":1", newbrain_floppies, "525dd", floppy_image_device::default_mfm_floppy_formats);
+ FLOPPY_CONNECTOR(config, UPD765_TAG ":2", newbrain_floppies, nullptr, floppy_image_device::default_mfm_floppy_formats);
+ FLOPPY_CONNECTOR(config, UPD765_TAG ":3", newbrain_floppies, nullptr, floppy_image_device::default_mfm_floppy_formats);
NEWBRAIN_EXPANSION_SLOT(config, m_exp, XTAL(16'000'000)/8, newbrain_expansion_cards, nullptr);
}
@@ -135,11 +135,8 @@ newbrain_fdc_device::newbrain_fdc_device(const machine_config &mconfig, const ch
device_newbrain_expansion_slot_interface(mconfig, *this),
m_maincpu(*this, Z80_TAG),
m_fdc(*this, UPD765_TAG),
- m_floppy0(*this, UPD765_TAG ":0"),
- m_floppy1(*this, UPD765_TAG ":1"),
- m_floppy2(*this, UPD765_TAG ":2"),
- m_floppy3(*this, UPD765_TAG ":3"),
- m_exp(*this, NEWBRAIN_EXPANSION_SLOT_TAG)
+ m_floppy(*this, UPD765_TAG ":%u", 0U),
+ m_exp(*this, "exp")
{
}
@@ -224,10 +221,9 @@ void newbrain_fdc_device::iorq_w(offs_t offset, uint8_t data, bool &prtov)
void newbrain_fdc_device::moton(int state)
{
- if (m_floppy0->get_device()) m_floppy0->get_device()->mon_w(!state);
- if (m_floppy1->get_device()) m_floppy1->get_device()->mon_w(!state);
- if (m_floppy2->get_device()) m_floppy2->get_device()->mon_w(!state);
- if (m_floppy3->get_device()) m_floppy3->get_device()->mon_w(!state);
+ for (auto &floppy : m_floppy)
+ if (floppy->get_device())
+ floppy->get_device()->mon_w(!state);
}
@@ -235,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 e5d6665a078..4fc9340b9c0 100644
--- a/src/devices/bus/newbrain/fdc.h
+++ b/src/devices/bus/newbrain/fdc.h
@@ -32,12 +32,12 @@ public:
protected:
// device-level overrides
- virtual void device_start() override;
- virtual void device_reset() override;
+ virtual void device_start() override ATTR_COLD;
+ virtual void device_reset() override ATTR_COLD;
// optional information overrides
- virtual const tiny_rom_entry *device_rom_region() const override;
- virtual void device_add_mconfig(machine_config &config) override;
+ virtual const tiny_rom_entry *device_rom_region() const override ATTR_COLD;
+ virtual void device_add_mconfig(machine_config &config) override ATTR_COLD;
// device_newbrain_expansion_slot_interface overrides
virtual uint8_t mreq_r(offs_t offset, uint8_t data, bool &romov, int &exrm, bool &raminh) override;
@@ -46,21 +46,18 @@ 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();
void io_dec_w(uint8_t data);
- void newbrain_fdc_io(address_map &map);
- void newbrain_fdc_mem(address_map &map);
+ void newbrain_fdc_io(address_map &map) ATTR_COLD;
+ void newbrain_fdc_mem(address_map &map) ATTR_COLD;
required_device<z80_device> m_maincpu;
required_device<upd765a_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<newbrain_expansion_slot_device> m_exp;
void moton(int state);
diff --git a/src/devices/bus/nscsi/applecd.cpp b/src/devices/bus/nscsi/applecd.cpp
new file mode 100644
index 00000000000..aec8a154c7a
--- /dev/null
+++ b/src/devices/bus/nscsi/applecd.cpp
@@ -0,0 +1,92 @@
+// license:BSD-3-Clause
+// copyright-holders:AJR
+/*******************************************************************************
+
+ Skeleton device for Apple external CD-ROM drives.
+
+ PCB: 1-631-957-15
+
+ Microcontrollers:
+ - Intel S80C31-1
+ - Mitsubishi M37450M8-452FP © SONY '91
+
+ Memories:
+ - National NMC27C256Q (or BQ) 32,768x8 EEPROM (for 80C31)
+ - Sony CXK5864BM-12L 8,192x8 Static RAM (x2)
+ (one near EEPROM, one between LC8951 and M37450M8)
+ - Fujitsu MB81464-12 65,536x4 Dynamic RAM (x2: for CXD1184)
+ - Fujitsu MB81C79A-45 8,192x9 Static RAM (for LC8951)
+ - Sony CXK5816MS-12L 2,048x8 Static RAM (near CXD1135)
+
+ Other major digital ICs:
+ - Sony CXD1180AQ SCSI Controller
+ - Sony CXD1184Q
+ - Sanyo LC8951 CD-ROM Error Correction & Host Interface Processor
+ - Sony CXD1135Q
+
+ Linear ICs:
+ - Toshiba TC9154AP Dual Volume Control
+ - Burr-Brown PCM67U Dual Audio DAC
+ - Sony CXA1182Q-Z CD Servo Signal Processor
+ - Sony CXA1081M
+ - Toshiba TA8406P Dual Power Operational Amplifier (x3)
+
+ XTALs: 12A KSS2A (80C31?), 20A KSS2A (CXD1184), D167 (LC8951?)
+
+*******************************************************************************/
+
+#include "emu.h"
+#include "applecd.h"
+
+#include "cpu/mcs51/mcs51.h"
+#include "cpu/m6502/m3745x.h"
+#include "machine/ncr5380.h"
+
+DEFINE_DEVICE_TYPE(APPLECD150, applecd150_device, "aplcd150", "AppleCD 150")
+
+applecd150_device::applecd150_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock)
+ : device_t(mconfig, APPLECD150, tag, owner, clock)
+ , nscsi_slot_card_interface(mconfig, *this, "scsic")
+{
+}
+
+void applecd150_device::device_start()
+{
+}
+
+void applecd150_device::prog_map(address_map &map)
+{
+ map(0x0000, 0x7fff).rom().region("eeprom", 0);
+}
+
+void applecd150_device::ext_map(address_map &map)
+{
+ map(0xc020, 0xc027).m("scsic", FUNC(cxd1180_device::map));
+}
+
+void applecd150_device::device_add_mconfig(machine_config &config)
+{
+ i80c31_device &mcu1(I80C31(config, "mcu1", 12_MHz_XTAL));
+ mcu1.set_addrmap(AS_PROGRAM, &applecd150_device::prog_map);
+ mcu1.set_addrmap(AS_IO, &applecd150_device::ext_map);
+
+ M37450(config, "mcu2", 16.9344_MHz_XTAL / 2).set_disable();
+
+ CXD1180(config, "scsic").irq_handler().set_inputline("mcu1", MCS51_INT1_LINE);
+
+ //LC8951(config, "cdintf", 16.9344_MHz_XTAL);
+}
+
+ROM_START(aplcd150)
+ ROM_REGION(0x8000, "eeprom", 0)
+ ROM_LOAD("apl_1.8g_1289.ic303", 0x0000, 0x8000, CRC(54ebf81f) SHA1(e4cd656e2a433229543e874a29f1567758170fc6))
+
+ ROM_REGION(0x4000, "mcu2", 0)
+ ROM_LOAD("m37450m8-452fp.ic201", 0x0000, 0x4000, NO_DUMP)
+ROM_END
+
+const tiny_rom_entry *applecd150_device::device_rom_region() const
+{
+ return ROM_NAME(aplcd150);
+}
+
diff --git a/src/devices/bus/nscsi/applecd.h b/src/devices/bus/nscsi/applecd.h
new file mode 100644
index 00000000000..fa2d0fe3387
--- /dev/null
+++ b/src/devices/bus/nscsi/applecd.h
@@ -0,0 +1,30 @@
+// license:BSD-3-Clause
+// copyright-holders:AJR
+
+#ifndef MAME_BUS_NSCSI_APPLECD_H
+#define MAME_BUS_NSCSI_APPLECD_H
+
+#pragma once
+
+#include "machine/nscsi_bus.h"
+
+class applecd150_device : public device_t, public nscsi_slot_card_interface
+{
+public:
+ applecd150_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 ATTR_COLD;
+ virtual void device_add_mconfig(machine_config &config) override ATTR_COLD;
+ virtual const tiny_rom_entry *device_rom_region() const override ATTR_COLD;
+
+private:
+ void prog_map(address_map &map) ATTR_COLD;
+ void ext_map(address_map &map) ATTR_COLD;
+};
+
+DECLARE_DEVICE_TYPE(APPLECD150, applecd150_device)
+
+#endif // MAME_BUS_NSCSI_APPLECD_H
diff --git a/src/devices/bus/nscsi/cd.cpp b/src/devices/bus/nscsi/cd.cpp
index 93424f493fa..5bad79ed8c4 100644
--- a/src/devices/bus/nscsi/cd.cpp
+++ b/src/devices/bus/nscsi/cd.cpp
@@ -1,21 +1,41 @@
// license:BSD-3-Clause
// copyright-holders:Olivier Galibert
#include "emu.h"
+#include "emuopts.h"
+
#include "bus/nscsi/cd.h"
-#define VERBOSE 0
+#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)")
DEFINE_DEVICE_TYPE(NSCSI_CDROM_APPLE, nscsi_cdrom_apple_device, "scsi_cdrom_apple", "Apple SCSI CD-ROM")
+// ZuluSCSI/BlueSCSI toolbox commands. All are 10 bytes as of protocol version 0.
+static constexpr uint8_t TOOLBOX_LIST_FILES = 0xd0;
+static constexpr uint8_t TOOLBOX_GET_FILE = 0xd1;
+static constexpr uint8_t TOOLBOX_COUNT_FILES = 0xd2;
+static constexpr uint8_t TOOLBOX_SEND_FILE_PREP = 0xd3;
+static constexpr uint8_t TOOLBOX_SEND_FILE_10 = 0xd4;
+static constexpr uint8_t TOOLBOX_SEND_FILE_END = 0xd5;
+static constexpr uint8_t TOOLBOX_TOGGLE_DEBUG = 0xd6;
+static constexpr uint8_t TOOLBOX_LIST_CDS = 0xd7;
+static constexpr uint8_t TOOLBOX_SET_NEXT_CD = 0xd8;
+static constexpr uint8_t TOOLBOX_LIST_DEVICES = 0xd9;
+static constexpr uint8_t TOOLBOX_COUNT_CDS = 0xda;
+
nscsi_cdrom_device::nscsi_cdrom_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) :
nscsi_cdrom_device(mconfig, NSCSI_CDROM, tag, owner, "Sony", "CDU-76S", "1.0", 0x00, 0x05)
{
@@ -26,6 +46,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 +66,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)
{
@@ -56,41 +86,56 @@ 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", "CDU-76S", "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")
+ , m_removal_prevented(false)
, 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();
+
+ m_xfer_buffer.resize(8192);
+
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));
+ save_item(NAME(m_xfer_position));
+ save_item(NAME(m_write_length));
+ save_item(NAME(m_write_offset));
+ save_item(NAME(m_write_is_setup));
}
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)
@@ -105,21 +150,39 @@ int nscsi_cdrom_device::to_msf(int frame)
void nscsi_cdrom_device::set_block_size(u32 block_size)
{
if (bytes_per_sector % block_size)
- throw emu_fatalerror("nscsi_cdrom_device(%s): block size must be a factor of sector size", tag());
+ {
+ logerror("nscsi_cdrom_device(%s): block size %d must be a factor of sector size %d", tag(), block_size, bytes_per_sector);
+ return;
+ }
bytes_per_block = block_size;
};
+bool nscsi_cdrom_device::scsi_command_done(uint8_t command, uint8_t length)
+{
+ switch (command & 0xd0)
+ {
+ case 0xd0: // ZuluSCSI/BlueSCSI toolbox commands
+ return length == 10;
+
+ default:
+ return nscsi_full_device::scsi_command_done(command, length);
+ }
+}
uint8_t nscsi_cdrom_device::scsi_get_data(int id, int pos)
{
+ if (id == 4)
+ return m_xfer_buffer[m_xfer_position++];
+
if(id != 2)
return nscsi_full_device::scsi_get_data(id, pos);
+
const int sector = (lba * bytes_per_block + pos) / bytes_per_sector;
const int extra_pos = (lba * bytes_per_block) % bytes_per_sector;
if(sector != cur_sector) {
cur_sector = sector;
- if(!cdrom_read_data(cdrom, sector, sector_buffer, 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);
}
@@ -129,20 +192,101 @@ uint8_t nscsi_cdrom_device::scsi_get_data(int id, int pos)
void nscsi_cdrom_device::scsi_put_data(int id, int pos, uint8_t data)
{
+ if (id == 4) {
+ m_xfer_buffer[m_xfer_position] = data;
+ m_xfer_position++;
+ if (m_write_is_setup) {
+ if (m_xfer_position == 33) {
+ osd_file::ptr file;
+ uint64_t filesize;
+ m_write_path.clear();
+ m_write_path = machine().options().share_directory();
+ m_write_path.append(PATH_SEPARATOR);
+ m_write_path.append((char *)&m_xfer_buffer[0]);
+ if (osd_file::open(m_write_path, OPEN_FLAG_CREATE | OPEN_FLAG_WRITE, file, filesize)) {
+ LOG("Open for write/creation failed for [%s]\n", m_write_path.c_str());
+ scsi_status_complete(SS_CHECK_CONDITION);
+ sense(false, SK_ILLEGAL_REQUEST, SK_ASC_INVALID_FIELD_IN_CDB);
+ return;
+ }
+ }
+ }
+ else
+ {
+ if (m_xfer_position == m_write_length) {
+ uint32_t actualWritten;
+ osd_file::ptr file;
+ uint64_t filesize;
+
+ LOG("flushing [%s] to disk at %08x\n", m_write_path.c_str(), m_write_offset * 512);
+ osd_file::open(m_write_path, OPEN_FLAG_WRITE, file, filesize);
+ file->write(&m_xfer_buffer[0], m_write_offset * 512, m_write_length, actualWritten);
+
+ if (actualWritten != m_write_length) {
+ scsi_status_complete(SS_CHECK_CONDITION);
+ sense(false, SK_ILLEGAL_REQUEST, SK_ASC_INVALID_FIELD_IN_CDB);
+ }
+ }
+ }
+ return;
+ }
+
if(id != 2) {
nscsi_full_device::scsi_put_data(id, pos, data);
return;
}
// 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;
+ }
+ }
+ }
+}
+
+void nscsi_cdrom_device::update_directory()
+{
+ std::string tmpPath(machine().options().share_directory());
+ osd::directory::ptr directory = osd::directory::open(tmpPath);
+
+ m_directory.clear();
+
+ if (directory != nullptr)
+ {
+ const osd::directory::entry *ourEntry;
+
+ while ((ourEntry = directory->read()) != nullptr)
+ {
+ m_directory.push_back(*ourEntry);
+
+ // API version 0 has a hard cap of 100 files
+ if (m_directory.size() >= 99)
+ {
+ break;
+ }
+ }
+
+ directory.reset();
}
}
@@ -157,11 +301,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);
@@ -172,19 +316,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;
@@ -219,7 +363,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;
@@ -239,8 +383,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;
}
@@ -252,8 +394,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;
@@ -264,9 +407,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;
@@ -282,9 +425,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);
@@ -307,24 +450,20 @@ void nscsi_cdrom_device::scsi_command()
}
case SC_READ_CAPACITY: {
- if(!cdrom) {
+ LOG("command READ CAPACITY\n");
+
+ if(!image->exists()) {
return_no_cd();
break;
}
- LOG("command READ CAPACITY\n");
-
// get the last used block on the disc
- const u32 temp = cdrom_get_track_start(cdrom, 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);
@@ -332,11 +471,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;
}
@@ -354,24 +493,27 @@ void nscsi_cdrom_device::scsi_command()
return;
}
- int page = scsi_cmdbuf[2] & 0x3f;
- int size = scsi_cmdbuf[4];
+ const int page = scsi_cmdbuf[2] & 0x3f;
+ const int size = scsi_cmdbuf[4];
+ const bool noBlockDesc = BIT(scsi_cmdbuf[1], 3);
int pos = 1;
scsi_cmdbuf[pos++] = 0x00; // medium type
scsi_cmdbuf[pos++] = 0x80; // WP, cache
// get the last used block on the disc
- const u32 temp = cdrom_get_track_start(cdrom, 0xaa) * (bytes_per_sector / bytes_per_block) - 1;
- scsi_cmdbuf[pos++] = 0x08; // Block descriptor length
+ const u32 temp = image->exists() ? image->get_track_start(0xaa) * (bytes_per_sector / bytes_per_block) - 1 : 0;
+ scsi_cmdbuf[pos++] = noBlockDesc ? 0x00 : 0x08; // 0 or 8 bytes of block descriptor
- scsi_cmdbuf[pos++] = 0x00; // density code
- scsi_cmdbuf[pos++] = (temp>>16) & 0xff;
- scsi_cmdbuf[pos++] = (temp>>8) & 0xff;
- scsi_cmdbuf[pos++] = (temp & 0xff);
- scsi_cmdbuf[pos++] = 0;
- scsi_cmdbuf[pos++] = 0;
- scsi_cmdbuf[pos++] = (bytes_per_block>>8)&0xff;
- scsi_cmdbuf[pos++] = (bytes_per_block & 0xff);
+ if (!noBlockDesc)
+ {
+ scsi_cmdbuf[pos++] = 0x00; // density code
+ put_u24be(&scsi_cmdbuf[pos], temp);
+ pos += 3;
+ scsi_cmdbuf[pos++] = 0;
+ scsi_cmdbuf[pos++] = 0;
+ put_u16be(&scsi_cmdbuf[pos], bytes_per_block);
+ pos += 2;
+ }
bool fail = false;
int pmax = page == 0x3f ? 0x3e : page;
@@ -420,20 +562,72 @@ void nscsi_cdrom_device::scsi_command()
scsi_cmdbuf[pos++] = 0x00; // Reserved
break;
- default:
- if (page != 0x3f) {
- LOG("mode sense page %02x unhandled\n", p);
- fail = true;
+ 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] =
+ {
+ 0x00, 0x41, 0x50, 0x50, 0x4C, 0x45, 0x20, 0x43, 0x4F, 0x4D, 0x50, 0x55,
+ 0x54, 0x45, 0x52, 0x2C, 0x20, 0x49, 0x4E, 0x43, 0x20, 0x20, 0x20
+ };
+
+ LOG("Apple special MODE SENSE page\n");
+ scsi_cmdbuf[pos++] = 0x30; // PS, page id
+ memcpy(&scsi_cmdbuf[pos], apple_magic, 0x17);
+ pos += 0x17;
+ }
+ break;
+
+ case 0x31: // magic BlueSCSI page; official clients require this to recognize a toolbox-capable device
+ {
+ // Yes this is lame for a GPLv3 project.
+ static const u8 bluescsi_magic[] =
+ {
+ "BlueSCSI is the BEST STOLEN FROM BLUESCSI\0"
+ };
+
+ scsi_cmdbuf[pos++] = 0x31; // page ID
+ scsi_cmdbuf[pos++] = 42; // page length
+ memcpy(&scsi_cmdbuf[pos], bluescsi_magic, 42);
+ pos += 42;
}
break;
+
+ default:
+ if (page != 0x3f)
+ {
+ LOG("mode sense page %02x unhandled\n", p);
+ fail = true;
+ }
+ break;
}
}
- scsi_cmdbuf[0] = pos;
- if(pos > size)
- pos = size;
+ scsi_cmdbuf[0] = pos - 1; // return -1 for mode sense 6
if (!fail) {
- scsi_data_in(0, pos);
+ if (size < pos)
+ scsi_data_in(0, size);
+ else
+ scsi_data_in(0, pos);
+
scsi_status_complete(SS_GOOD);
} else {
scsi_status_complete(SS_CHECK_CONDITION);
@@ -442,11 +636,117 @@ void nscsi_cdrom_device::scsi_command()
break;
}
+ case SC_READ_DISC_INFORMATION:
+ LOG("command READ DISC INFORMATION\n");
+ if(!image->exists()) {
+ return_no_cd();
+ break;
+ }
+
+ std::fill_n(scsi_cmdbuf, 34, 0);
+ scsi_cmdbuf[1] = 32;
+ scsi_cmdbuf[2] = 2; // disc is complete
+ 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] = 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 = image->get_track_start(0);
+ tstart = to_msf(tstart + 150);
+
+ put_u32be(&scsi_cmdbuf[16], tstart);
+
+ // lead-out start time in MSF
+ tstart = image->get_track_start(0xaa);
+ tstart = to_msf(tstart + 150);
+
+ put_u32be(&scsi_cmdbuf[20], tstart);
+ }
+
+ scsi_data_in(0, 34);
+ scsi_status_complete(SS_GOOD);
+ break;
+
case SC_PREVENT_ALLOW_MEDIUM_REMOVAL:
// TODO: support eject prevention
LOG("command %s MEDIUM REMOVAL\n", (scsi_cmdbuf[4] & 0x1) ? "PREVENT" : "ALLOW");
+ m_removal_prevented = BIT(scsi_cmdbuf[4], 0);
+ 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: {
/*
@@ -460,7 +760,7 @@ void nscsi_cdrom_device::scsi_command()
"Session info",
"Full TOC",
"PMA",
- "ATIP"
+ "ATIP",
"Reserved 5",
"Reserved 6",
"Reserved 7",
@@ -475,7 +775,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)
@@ -484,11 +784,16 @@ 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(!image->exists()) {
+ return_no_cd();
+ break;
+ }
+
int pos = 0;
switch (format) {
case 0: {
int start_track = scsi_cmdbuf[6];
- int end_track = cdrom_get_last_track(cdrom);
+ int end_track = image->get_last_track();
int tracks;
if(start_track == 0)
@@ -504,10 +809,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(cdrom);
+ scsi_cmdbuf[pos++] = image->get_last_track();
if (start_track == 0)
start_track = 1;
@@ -521,19 +826,17 @@ void nscsi_cdrom_device::scsi_command()
}
scsi_cmdbuf[pos++] = 0;
- scsi_cmdbuf[pos++] = cdrom_get_adr_control(cdrom, 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, 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;
}
@@ -541,25 +844,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(cdrom, 0);
+ scsi_cmdbuf[pos++] = image->get_adr_control(0);
scsi_cmdbuf[pos++] = 1;
scsi_cmdbuf[pos++] = 0;
- u32 tstart = cdrom_get_track_start(cdrom, 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;
}
@@ -583,6 +884,162 @@ 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;
+
+ case TOOLBOX_COUNT_FILES:
+ LOG("TOOLBOX_COUNT_FILES\n");
+
+ update_directory();
+
+ scsi_cmdbuf[0] = m_directory.size();
+ scsi_data_in(0, 1);
+ scsi_status_complete(SS_GOOD);
+ break;
+
+ case TOOLBOX_LIST_FILES:
+ {
+ LOG("TOOLBOX_LIST_FILES\n");
+
+ // it's assumed clients will always do COUNT_FILES before LIST_FILES, because otherwise
+ // they'll have no idea how much data is coming.
+ int pos = 0;
+ int index = 0;
+
+ if (m_directory.size() > 0)
+ {
+ while (index < m_directory.size())
+ {
+ scsi_cmdbuf[pos] = index;
+ scsi_cmdbuf[pos + 1] = m_directory[index].type != osd::directory::entry::entry_type::DIR;
+ // There's a guaranteed null terminator one byte after the name field
+ strncpy(reinterpret_cast<char *>(&scsi_cmdbuf[pos + 2]), m_directory[index].name, 31);
+ scsi_cmdbuf[pos + 36] = (m_directory[index].size >> 24) & 0xff;
+ scsi_cmdbuf[pos + 37] = (m_directory[index].size >> 16) & 0xff;
+ scsi_cmdbuf[pos + 38] = (m_directory[index].size >> 8) & 0xff;
+ scsi_cmdbuf[pos + 39] = m_directory[index].size & 0xff;
+
+ LOG("%02d: %s %08x\n", index, m_directory[index].name, (uint32_t)m_directory[index].size);
+
+ index++;
+ pos += 40;
+ }
+ }
+
+ scsi_data_in(0, pos);
+ scsi_status_complete(SS_GOOD);
+ break;
+ }
+
+ case TOOLBOX_GET_FILE:
+ {
+ update_directory();
+
+ if (scsi_cmdbuf[1] >= m_directory.size())
+ {
+ LOG("TOOLBOX_GET_FILE: out of range file %d, %d available\n", scsi_cmdbuf[1], (int)m_directory.size());
+ scsi_status_complete(SS_CHECK_CONDITION);
+ sense(false, SK_ILLEGAL_REQUEST, SK_ASC_INVALID_FIELD_IN_CDB);
+ return;
+ }
+
+ uint32_t offset = scsi_cmdbuf[2] << 24 | scsi_cmdbuf[3] << 16 | scsi_cmdbuf[4] << 8 | scsi_cmdbuf[5];
+ LOG("TOOLBOX_GET_FILE: file # %d (%s), offset %08x\n", scsi_cmdbuf[1], m_directory[scsi_cmdbuf[1]].name, offset);
+
+ std::string tmpPath(machine().options().share_directory());
+ tmpPath.append(PATH_SEPARATOR);
+ tmpPath.append(m_directory[scsi_cmdbuf[1]].name);
+
+ osd_file::ptr file;
+ u64 size;
+ if (osd_file::open(tmpPath, OPEN_FLAG_READ, file, size))
+ {
+ LOG("Open failed for [%s]\n", tmpPath.c_str());
+ scsi_status_complete(SS_CHECK_CONDITION);
+ sense(false, SK_ILLEGAL_REQUEST, SK_ASC_INVALID_FIELD_IN_CDB);
+ return;
+ }
+ u32 actualRead;
+ file->read(&m_xfer_buffer[0], offset * 4096, 4096, actualRead);
+
+ if (actualRead == 0)
+ {
+ scsi_status_complete(SS_CHECK_CONDITION);
+ sense(false, SK_ILLEGAL_REQUEST, SK_ASC_INVALID_FIELD_IN_CDB);
+ return;
+ }
+
+ m_xfer_position = 0;
+ scsi_data_in(4, actualRead);
+ scsi_status_complete(SS_GOOD);
+ break;
+ }
+
+ case TOOLBOX_SEND_FILE_PREP:
+ LOG("TOOLBOX_SEND_FILE_PREP\n");
+ m_xfer_position = 0;
+ m_write_is_setup = true;
+ scsi_data_out(4, 33);
+ scsi_status_complete(SS_GOOD);
+ break;
+
+ case TOOLBOX_SEND_FILE_10:
+ m_xfer_position = 0;
+ m_write_is_setup = false;
+ m_write_length = scsi_cmdbuf[1] << 8 | scsi_cmdbuf[2];
+ m_write_offset = scsi_cmdbuf[3] << 16 | scsi_cmdbuf[4] << 8 | scsi_cmdbuf[5];
+ LOG("TOOLBOX_SEND_FILE_10 offset %08x len %04x\n", m_write_offset, m_write_length);
+ scsi_data_out(4, m_write_length);
+ scsi_status_complete(SS_GOOD);
+ break;
+
+ case TOOLBOX_SEND_FILE_END:
+ LOG("TOOLBOX_SEND_FILE_END\n");
+ scsi_status_complete(SS_GOOD);
+ break;
+
+ case TOOLBOX_COUNT_CDS:
+ LOG("TOOLBOX_COUNT_CDS\n");
+ scsi_cmdbuf[0] = 0;
+ scsi_data_in(0, 1);
+ scsi_status_complete(SS_GOOD);
+ break;
+
default:
nscsi_full_device::scsi_command();
break;
@@ -604,13 +1061,23 @@ enum sgi_scsi_command_e : uint8_t {
* in the kernel runs, if there are SCSI problems.
*/
SGI_HD2CDROM = 0xc9,
+ /*
+ * IRIX 5.3 sends this command when it wants to eject the drive
+ */
+ SGI_EJECT = 0xc4,
};
void nscsi_cdrom_sgi_device::scsi_command()
{
switch (scsi_cmdbuf[0]) {
case SGI_HD2CDROM:
- LOG("command SGI_HD2CDROM");
+ LOG("command SGI_HD2CDROM\n");
+ // No need to do anything (yet). Just acknowledge the command.
+ scsi_status_complete(SS_GOOD);
+ break;
+
+ case SGI_EJECT:
+ LOG("command SGI_EJECT\n");
// No need to do anything (yet). Just acknowledge the command.
scsi_status_complete(SS_GOOD);
break;
@@ -627,34 +1094,653 @@ bool nscsi_cdrom_sgi_device::scsi_command_done(uint8_t command, uint8_t length)
case SGI_HD2CDROM:
return length == 10;
+ case SGI_EJECT:
+ return length == 10;
+
default:
- return nscsi_full_device::scsi_command_done(command, length);
+ return nscsi_cdrom_device::scsi_command_done(command, length);
}
}
+
+// Apple CDSC commands, from "Apple CD-ROM SCSI Command Set", version 1.4, February 15, 1988.
+// These are related to the Sony CDU-541 commands but customized by Apple.
+enum apple_scsi_command_e : uint8_t {
+ APPLE_EJECT = 0xc0, // EJECT DISC
+ APPLE_READ_TOC = 0xc1, // READ TOC
+ APPLE_READ_Q_SUBCODE = 0xc2, // READ Q SUBCODE
+ APPLE_READ_HEADER = 0xc3, // READ HEADER
+ APPLE_AUDIO_TRK_SEARCH = 0xc8, // AUDIO TRACK SEARCH
+ APPLE_AUDIO_PLAY = 0xc9, // AUDIO PLAY
+ APPLE_AUDIO_PAUSE = 0xca, // AUDIO PAUSE
+ APPLE_AUDIO_STOP = 0xcb, // AUDIO STOP
+ APPLE_AUDIO_STATUS = 0xcc, // AUDIO STATUS
+ APPLE_AUDIO_SCAN = 0xcd, // AUDIO SCAN
+ 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,
+ 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,
the firmware assumes the drive is broken and retries the TEST_UNIT_READY for 60 seconds before giving up
and booting the machine.
+
+ MacOS will see the normal 0x3A disc-not-present and simply disbelieve it and hammer on the drive while
+ asking the user to format it because it's unreadable. 0xB0 makes it behave as expected.
*/
+
+void nscsi_cdrom_apple_device::return_no_cd()
+{
+ sense(false, SK_NOT_READY, 0xb0);
+ scsi_status_complete(SS_CHECK_CONDITION);
+}
+
void nscsi_cdrom_apple_device::scsi_command()
{
+ #if 1
+ 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]);
+ }
+ #endif
switch (scsi_cmdbuf[0]) {
case SC_TEST_UNIT_READY:
- LOG("command TEST UNIT READY (AppleCD)\n");
- if(cdrom)
+ //LOG("command TEST UNIT READY (AppleCD)\n");
+ if(image->exists())
{
scsi_status_complete(SS_GOOD);
}
else
{
- sense(false, SK_NOT_READY, 0xb0);
+ return_no_cd();
+ }
+ 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]);
+
+ // cmdbuf 9 bits 6 & 7:
+ // 00 = first and last track # in BCD
+ // 01 = starting address of the lead-out in M/S/F
+ // 10 = starting address of a range of tracks from a starting track
+ // 11 = reserved
+ const uint8_t operation = scsi_cmdbuf[9] & 0xc0;
+ if (operation == 0x80)
+ {
+ // get TOC info for 1 or more tracks from a specified starting track
+ assert(scsi_cmdbuf[5] > 0);
+
+ const int start_track = bcd_2_dec(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 (operation == 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 if (operation == 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 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 Sony 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
+ 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
+
+ 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
+ }
+ }
+ scsi_data_in(SBUF_MAIN, 6);
+ scsi_status_complete(SS_GOOD);
+ break;
+
+ case APPLE_READ_Q_SUBCODE:
+ {
+ 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
+
+ const 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;
+
+ // This command does not change the play or pause status.
+ case APPLE_AUDIO_TRK_SEARCH:
+ {
+ const uint8_t val = scsi_cmdbuf[5];
+ const uint8_t start_track = (((val & 0xf0) >> 4) * 10) + (val & 0x0f);
+
+ cdda->cancel_scan();
+ if (cdda->audio_paused())
+ {
+ cdda->pause_audio(0);
+ }
+
+ uint32_t start_lba = 0;
+
+ // cmdbuf[9] bits 6 & 7:
+ // 00 = search address is LBA
+ // 01 = search address is M/S/F
+ // 10 = search address is track number
+ if (scsi_cmdbuf[9] == 0x40)
+ {
+ LOG("command APPLE AUDIO TRACK SEARCH 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 TRACK SEARCH 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);
+ m_stop_position = image->get_track_start(start_track); // does this actually update the stop position?
+ }
+ }
+ else if (scsi_cmdbuf[9] == 0x00) // LBA
+ {
+ start_lba = (scsi_cmdbuf[5] << 24) | (scsi_cmdbuf[4] << 16) | (scsi_cmdbuf[3] << 8) || scsi_cmdbuf[2];
+ }
+ else
+ {
+ logerror("nscsi_cdrom_apple_device: Unknown APPLE AUDIO PLAY address mode %02x\n", scsi_cmdbuf[9]);
+ }
+
+ // PLAY / PAUSE bit
+ if ((scsi_cmdbuf[1] & 0x10) == 0x10)
+ {
+ cdda->start_audio(start_lba, m_stop_position - start_lba);
+ }
+ else
+ {
+ cdda->start_audio(start_lba, m_stop_position - start_lba);
+ cdda->pause_audio(true);
+ }
+ m_stopped = false;
+
+ scsi_status_complete(SS_GOOD);
+ }
+ break;
+
+ case APPLE_AUDIO_PLAY:
+ {
+ const uint8_t val = scsi_cmdbuf[5];
+ const uint8_t start_track = (((val & 0xf0) >> 4) * 10) + (val & 0x0f);
+
+ cdda->cancel_scan();
+ if (cdda->audio_paused())
+ {
+ cdda->pause_audio(0);
+ }
+
+ // cmdbuf[9] bits 6 & 7:
+ // 00 = address is LBA
+ // 01 = address is M/S/F
+ // 10 = address is track number
+ uint32_t address = 0;
+ if (scsi_cmdbuf[9] == 0x80)
+ {
+ LOG("command APPLE AUDIO PLAY 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
+ {
+ address = image->get_track_start(start_track - 1);
+ }
+ }
+ else if (scsi_cmdbuf[9] == 0x40)
+ {
+ LOG("command APPLE AUDIO PLAY TRACK MSF = %02x:%02x:%02x\n", scsi_cmdbuf[3], scsi_cmdbuf[4], scsi_cmdbuf[5]);
+
+ const uint32_t msf = (bcd_2_dec(scsi_cmdbuf[3]) << 16) | (bcd_2_dec(scsi_cmdbuf[4]) << 8) | bcd_2_dec(scsi_cmdbuf[5]);
+ address = cdrom_file::msf_to_lba(msf);
+ }
+ else if (scsi_cmdbuf[9] == 0x00)
+ {
+ address = (scsi_cmdbuf[5] << 24) | (scsi_cmdbuf[4] << 16) | (scsi_cmdbuf[3] << 8) || scsi_cmdbuf[2];
+ LOG("command APPLE AUDIO PLAY lba = %d\n", address);
+ }
+ else
+ {
+ fatalerror("nscsi_cdrom_apple_device: unknown mode for APPLE AUDIO PLAY %02x\n", scsi_cmdbuf[9]);
+ }
+
+ // cmdbuf[1] & 0x10:
+ // 0 = address is the starting address, stop address was set by a STOP command
+ // 1 = address is the stop address, start address was set by a TRACK SEARCH command
+ if (scsi_cmdbuf[1] & 0x10)
+ {
+ const auto start = cdda->get_audio_lba();
+ cdda->start_audio(start, address - start);
+ }
+ else
+ {
+ cdda->start_audio(address, m_stop_position - address);
+ m_stopped = false;
+ }
+ scsi_status_complete(SS_GOOD);
+ }
+ break;
+
+ case APPLE_AUDIO_SCAN:
+ /*
+ 3/4/5 = MSF of starting position
+ 1 = 00 for forward scan, 0x10 for reverse
+ Scan ends with a PAUSE OFF command.
+ */
+ 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]);
+
+ if (!m_stopped)
+ {
+ uint32_t start_lba = 0;
+ switch (scsi_cmdbuf[9] & 0xc0)
+ {
+ case 0x00: // stop at LBA
+ start_lba = (scsi_cmdbuf[5] << 24) | (scsi_cmdbuf[4] << 16) | (scsi_cmdbuf[3] << 8) || scsi_cmdbuf[2];
+ LOG("command APPLE AUDIO SCAN at LBA %d\n", m_stop_position);
+ 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]);
+ start_lba = cdrom_file::msf_to_lba(msf);
+ LOG("command APPLE AUDIO SCAN at MSF %02x:%02x:%02x\n", scsi_cmdbuf[5], scsi_cmdbuf[6], scsi_cmdbuf[7]);
+ }
+ break;
+
+ case 0x80: // stop at track number
+ {
+ const uint8_t start_track = bcd_2_dec(scsi_cmdbuf[5]);
+ if (start_track >= image->get_last_track())
+ {
+ start_lba = image->get_track_start(0xaa);
+ }
+ else
+ {
+ start_lba = image->get_track_start(start_track + 1);
+ }
+ start_lba--;
+ LOG("command APPLE AUDIO SCAN at end of track %d (LBA %d)\n", start_track, m_stop_position);
+ }
+ break;
+
+ default:
+ logerror("nscsi_cdrom_apple_device: Unknown APPLE AUDIO SCAN address mode %02x\n", scsi_cmdbuf[9]);
+ break;
+ }
+
+ // begin seeking from the specified address
+ cdda->set_audio_lba(start_lba);
+
+ if ((scsi_cmdbuf[1] & 0x10) == 0)
+ {
+ cdda->scan_forward();
+ }
+ else
+ {
+ cdda->scan_reverse();
+ }
+ }
+ 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 and stop scanning
+ cdda->cancel_scan();
+ if (cdda->audio_paused())
+ {
+ cdda->pause_audio(0);
+ }
+ }
+ scsi_status_complete(SS_GOOD);
+ break;
+
+ case APPLE_AUDIO_STOP:
+ switch (scsi_cmdbuf[9] & 0xc0)
+ {
+ case 0x00: // stop at LBA
+ m_stop_position = (scsi_cmdbuf[5] << 24) | (scsi_cmdbuf[4] << 16) | (scsi_cmdbuf[3] << 8) || scsi_cmdbuf[2];
+ LOG("command APPLE AUDIO STOP at LBA %d\n", m_stop_position);
+ 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);
+ LOG("command APPLE AUDIO STOP at MSF %02x:%02x:%02x\n", scsi_cmdbuf[5], scsi_cmdbuf[6], scsi_cmdbuf[7]);
+ }
+ break;
+
+ case 0x80: // stop at track number
+ {
+ const uint8_t start_track = bcd_2_dec(scsi_cmdbuf[5]);
+ if (start_track >= image->get_last_track())
+ {
+ m_stop_position = image->get_track_start(0xaa);
+ }
+ else
+ {
+ m_stop_position = image->get_track_start(start_track + 1);
+ }
+ m_stop_position--;
+ LOG("command APPLE AUDIO STOP at end of track %d (LBA %d)\n", start_track, m_stop_position);
+ }
+ break;
+
+ default:
+ logerror("nscsi_cdrom_apple_device: Unknown APPLE AUDIO STOP address mode %02x\n", scsi_cmdbuf[9]);
+ break;
+ }
+
+ if ((!m_stopped) && (cdda->get_audio_lba() >= m_stop_position))
+ {
+ m_stopped = true;
+ cdda->stop_audio();
+ }
+
+ scsi_status_complete(SS_GOOD);
+ break;
+
+ case APPLE_AUDIO_CONTROL:
+ LOG("command APPLE AUDIO CONTROL, size %d\n", scsi_cmdbuf[8]);
+
+ if (image->exists())
+ {
+ scsi_data_out(3, scsi_cmdbuf[8]);
+ scsi_status_complete(SS_GOOD);
+ }
+ else
+ {
+ return_no_cd();
+ }
+ break;
+
+ case APPLE_EJECT:
+ LOG("command APPLE EJECT\n");
+ if (!m_removal_prevented)
+ {
+ cdda->stop_audio();
+ m_stopped = true;
+ image->unload();
+ sense(false, SK_NOT_READY, SK_ASC_MEDIUM_NOT_PRESENT);
+ scsi_status_complete(SS_GOOD);
+ }
+ else
+ {
+ LOG("Eject not allowed by PREVENT_ALLOW_MEDIA_REMOVAL\n");
+ sense(false, SK_ILLEGAL_REQUEST, 0x80); // "Prevent bit is set"
scsi_status_complete(SS_CHECK_CONDITION);
}
break;
+ case SC_READ_6:
+ case SC_READ_10:
+ case SC_READ_12:
+ cdda->stop_audio();
+ m_stopped = true;
+ [[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_cdrom_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..3c4fda34862 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)
@@ -29,24 +35,31 @@ protected:
this->compliance = compliance;
}
- virtual void device_start() override;
- virtual void device_reset() override;
- virtual void device_add_mconfig(machine_config &config) override;
+ 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;
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 bool scsi_command_done(uint8_t command, uint8_t length) override;
+
+ virtual void return_no_cd();
+ static int to_msf(int frame);
+
+ void update_directory();
- cdrom_file *cdrom;
+ bool m_removal_prevented;
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 +67,15 @@ private:
uint8_t inquiry_data;
uint8_t compliance;
- void return_no_cd();
- static int to_msf(int frame);
+ uint8_t cdda_sotc;
+
+ uint32_t m_xfer_position;
+ uint16_t m_write_length;
+ uint32_t m_write_offset;
+ bool m_write_is_setup;
+ std::string m_write_path;
+ std::vector<osd::directory::entry> m_directory;
+ std::vector<uint8_t> m_xfer_buffer;
};
class nscsi_cdrom_sgi_device : public nscsi_cdrom_device
@@ -68,6 +88,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 +112,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 +140,26 @@ 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 ATTR_COLD;
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;
+ virtual void return_no_cd() 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 a4fb163f446..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,27 +17,37 @@ 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();
}
void cdd2000_device::device_add_mconfig(machine_config &config)
{
- MC68HC11A1(config, m_cdcpu, 8'000'000); // type and clock are total guesses
- m_cdcpu->set_addrmap(AS_PROGRAM, &cdd2000_device::mem_map);
+ 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..e08a187794f 100644
--- a/src/devices/bus/nscsi/cdd2000.h
+++ b/src/devices/bus/nscsi/cdd2000.h
@@ -16,14 +16,16 @@ public:
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 void device_start() override ATTR_COLD;
+ virtual void device_reset() override ATTR_COLD;
+ virtual void device_add_mconfig(machine_config &config) override ATTR_COLD;
+ virtual const tiny_rom_entry *device_rom_region() const override ATTR_COLD;
private:
- void mem_map(address_map &map);
+ void mem_map(address_map &map) ATTR_COLD;
required_device<cpu_device> m_cdcpu;
+ required_memory_bank m_rombank;
};
DECLARE_DEVICE_TYPE(CDD2000, cdd2000_device)
diff --git a/src/devices/bus/nscsi/cdrn820s.cpp b/src/devices/bus/nscsi/cdrn820s.cpp
index 5b3b1b87dbb..9c74b8a31d4 100644
--- a/src/devices/bus/nscsi/cdrn820s.cpp
+++ b/src/devices/bus/nscsi/cdrn820s.cpp
@@ -2,7 +2,7 @@
// copyright-holders:AJR
/*******************************************************************************
- Skeleton device for Sanyo/Caravalle CDR-N820s.
+ Skeleton device for Sanyo/Caravelle CDR-N820s.
*******************************************************************************/
@@ -10,7 +10,7 @@
#include "bus/nscsi/cdrn820s.h"
#include "machine/wd33c9x.h"
-DEFINE_DEVICE_TYPE(CDRN820S, cdrn820s_device, "cdrn820s", "Caravalle CDR-N820s")
+DEFINE_DEVICE_TYPE(CDRN820S, cdrn820s_device, "cdrn820s", "Caravelle CDR-N820s")
cdrn820s_device::cdrn820s_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, u32 clock)
: device_t(mconfig, type, tag, owner, clock)
@@ -43,8 +43,8 @@ void cdrn820s_device::device_add_mconfig(machine_config &config)
}
ROM_START(cdrn820s)
- ROM_REGION(0x40000, "program", 0)
- ROM_LOAD16_WORD_SWAP("cdr_120.bin", 0x00000, 0x20000, CRC(8cac6862) SHA1(e498dcd9006d257ced6cd0b50c76608e9a8023f7)) // Caravelle CDR-N820S 1.20
+ ROM_REGION16_BE(0x40000, "program", 0)
+ ROM_LOAD("cdr_120.bin", 0x00000, 0x20000, CRC(8cac6862) SHA1(e498dcd9006d257ced6cd0b50c76608e9a8023f7)) // Caravelle CDR-N820S 1.20
ROM_END
const tiny_rom_entry *cdrn820s_device::device_rom_region() const
diff --git a/src/devices/bus/nscsi/cdrn820s.h b/src/devices/bus/nscsi/cdrn820s.h
index c76fb007bbd..4d6a2df53e8 100644
--- a/src/devices/bus/nscsi/cdrn820s.h
+++ b/src/devices/bus/nscsi/cdrn820s.h
@@ -19,12 +19,12 @@ public:
protected:
cdrn820s_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, u32 clock);
- 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 device_start() override ATTR_COLD;
+ virtual void device_add_mconfig(machine_config &config) override ATTR_COLD;
+ virtual const tiny_rom_entry *device_rom_region() const override ATTR_COLD;
private:
- void mem_map(address_map &map);
+ void mem_map(address_map &map) ATTR_COLD;
required_device<h83048_device> m_h8;
};
diff --git a/src/devices/bus/nscsi/cdu415.cpp b/src/devices/bus/nscsi/cdu415.cpp
new file mode 100644
index 00000000000..5b69a7d3c46
--- /dev/null
+++ b/src/devices/bus/nscsi/cdu415.cpp
@@ -0,0 +1,67 @@
+// license:BSD-3-Clause
+// copyright-holders:Olivier Galibert
+/*******************************************************************************
+
+ Skeleton device for Sony CDU415 cdrom reader
+
+*******************************************************************************/
+
+// Chips:
+// - IC201: H8/3032 - main mcu, 64k internal rom
+// - IC202: CXD1804AR - cdrom decoder and scsi interface
+// - IC203: V53C16126HK40 - DRAM 128k*16
+// - IC205: BU6243K - ?
+// - IC207: AM28F512 - Firmware
+
+#include "emu.h"
+#include "cdu415.h"
+
+DEFINE_DEVICE_TYPE(CDU415, cdu415_device, "cdu415", "Sony CDU415 CD-R")
+
+cdu415_device::cdu415_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock)
+ : device_t(mconfig, CDU415, tag, owner, clock)
+ , nscsi_slot_card_interface(mconfig, *this, "cxd1804ar")
+ , m_mcu(*this, "mcu")
+ , m_scsi(*this, "cxd1804ar")
+ , m_rom(*this, "mcu")
+{
+}
+
+void cdu415_device::device_start()
+{
+ // The reset vector is the only obvious one there.
+ m_rom[0] = m_rom[0x8000];
+ m_rom[1] = m_rom[0x8001];
+}
+
+void cdu415_device::mem_map(address_map &map)
+{
+ map(0x00000, 0x0ffff).rom().region("mcu", 0);
+ map(0x20000, 0x2ffff).rom().region("mcu", 0x10000);
+}
+
+void cdu415_device::device_add_mconfig(machine_config &config)
+{
+ H83032(config, m_mcu, 10000000);
+ m_mcu->set_addrmap(AS_PROGRAM, &cdu415_device::mem_map);
+
+ NCR53C94(config, m_scsi, 25'000'000); // Temporary placeholder
+}
+
+ROM_START(cdu415)
+ ROM_REGION(0x20000, "mcu", 0)
+ ROM_FILL(0x00000, 0x10000, 0x00) // Internal rom not yet dumped
+ ROM_LOAD("cdu415.bin", 0x10000, 0x10000, CRC(9873b898) SHA1(72d0b192efc32f7c8985dd96df3e346c57a236e7))
+ROM_END
+
+const tiny_rom_entry *cdu415_device::device_rom_region() const
+{
+ return ROM_NAME(cdu415);
+}
+
+u8 cdu415_device::jumpers_r()
+{
+ u32 jumpers_id = strtol(owner()->basetag(), nullptr, 16);
+ return (jumpers_id ^ 7) << 1;
+}
+
diff --git a/src/devices/bus/nscsi/cdu415.h b/src/devices/bus/nscsi/cdu415.h
new file mode 100644
index 00000000000..807eb774668
--- /dev/null
+++ b/src/devices/bus/nscsi/cdu415.h
@@ -0,0 +1,37 @@
+// license:BSD-3-Clause
+// copyright-holders:O. Galibert
+
+#ifndef MAME_BUS_NSCSI_CDU415_H
+#define MAME_BUS_NSCSI_CDU415_H
+
+#pragma once
+
+#include "machine/nscsi_bus.h"
+#include "cpu/h8/h83032.h"
+#include "machine/ncr53c90.h"
+
+class cdu415_device : public device_t, public nscsi_slot_card_interface
+{
+public:
+ cdu415_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 ATTR_COLD;
+ virtual void device_add_mconfig(machine_config &config) override ATTR_COLD;
+ virtual const tiny_rom_entry *device_rom_region() const override ATTR_COLD;
+
+private:
+ void mem_map(address_map &map) ATTR_COLD;
+
+ required_device<h83032_device> m_mcu;
+ required_device<ncr53c94_device> m_scsi;
+ required_region_ptr<u16> m_rom;
+
+ u8 jumpers_r();
+};
+
+DECLARE_DEVICE_TYPE(CDU415, cdu415_device)
+
+#endif // MAME_BUS_NSCSI_CDU415_H
diff --git a/src/devices/bus/nscsi/cdu561.cpp b/src/devices/bus/nscsi/cdu561.cpp
new file mode 100644
index 00000000000..2382ab23382
--- /dev/null
+++ b/src/devices/bus/nscsi/cdu561.cpp
@@ -0,0 +1,87 @@
+// license:BSD-3-Clause
+// copyright-holders:AJR
+/*******************************************************************************
+
+ Skeleton device for Sony CDU561-25 CD-ROM drive.
+
+ PCB: MAIN 1-644-812-13
+
+ Microcontroller:
+ - Mitsubishi M37732S4AFP
+
+ Memories:
+ - TI TMS27C010A-12 EPROM or equivalent
+ - Mosel MS62256CLL-10FC or Sony CXK58257AM-10L 32,768x8 Static RAM
+ - Mosel MS514256A-70VC 262,144x4 Fast Page Mode DRAM (x2; near CXD1198)
+ - Fujitsu MB81C79A-45 or Sony CXK5971AM-35 8,192x9 Static RAM (near CXD1186)
+
+ Other major digital ICs:
+ - Sony CXD1185CQ SCSI Controller
+ - Sony CXD1186Q CD-ROM Decoder
+ - Sony CXD1198AQ CD-ROM Subcode Decoder
+ - Sony CXD2500BQ CD Digital Signal Processor
+ - Sony CXD8416Q
+
+ Linear ICs:
+ - Sony CXA1372AQ RF Signal Processing Servo Amplifier for CD Player
+ - Sony CXA1571M RF Amplifier for CD Player
+ - Sony CXD2568M (apparently a RF amplifier, similar to CXA1821M but with
+ hold and AGC controls)
+ - Toshiba TA8406P Dual Power Operational Amplifier (x3)
+
+ XTALs:
+ - D169 (near CXD2500B)
+ - 24.00MX (near CXD1198)
+
+*******************************************************************************/
+
+#include "emu.h"
+#include "cdu561.h"
+
+#include "cpu/m37710/m37710.h"
+#include "machine/cxd1185.h"
+
+DEFINE_DEVICE_TYPE(CDU561_25, cdu561_25_device, "cdu561_25", "Sony CDU561-25")
+
+cdu561_25_device::cdu561_25_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock)
+ : device_t(mconfig, CDU561_25, tag, owner, clock)
+ , nscsi_slot_card_interface(mconfig, *this, "scsic")
+{
+}
+
+void cdu561_25_device::device_start()
+{
+}
+
+void cdu561_25_device::mem_map(address_map &map)
+{
+ map(0x000880, 0x007fff).ram();
+ map(0x008000, 0x01ffff).rom().region("eprom", 0x8000);
+ map(0x020000, 0x02ffff).rom().region("eprom", 0);
+ map(0x030000, 0x03000f).noprw(); // CXD1186?
+ map(0x050000, 0x05000f).m("scsic", FUNC(cxd1185_device::map));
+ map(0x070000, 0x070001).nopr(); // ?
+}
+
+void cdu561_25_device::device_add_mconfig(machine_config &config)
+{
+ m37732s4_device &mcu(M37732S4(config, "mcu", 24_MHz_XTAL / 2));
+ mcu.set_addrmap(AS_PROGRAM, &cdu561_25_device::mem_map);
+
+ CXD1185(config, "scsic", 24_MHz_XTAL / 2);
+}
+
+ROM_START(cdu561_25)
+ ROM_REGION16_LE(0x20000, "eprom", 0)
+ ROM_SYSTEM_BIOS(0, "19a", "apl1.9a")
+ ROMX_LOAD("apl1.9a_83fb.ic302", 0x00000, 0x20000, CRC(0efc50eb) SHA1(8bfd6ebc0863017914808e8282a5914cdc828f56), ROM_BIOS(0))
+ ROM_SYSTEM_BIOS(1, "18f", "apl1.8F")
+ ROMX_LOAD("apl1.8f_d905.ic302", 0x00000, 0x20000, CRC(3ea92e48) SHA1(2f409fd59c5f09d22e00b39f4b0b57e16316090d), ROM_BIOS(1))
+ ROM_SYSTEM_BIOS(2, "17w", "apl1.7w")
+ ROMX_LOAD("apl_1.7w.bin", 0x00000, 0x20000, CRC(12ba5843) SHA1(70aa550693020431ccbd374ff85e4de8809431df), ROM_BIOS(2))
+ROM_END
+
+const tiny_rom_entry *cdu561_25_device::device_rom_region() const
+{
+ return ROM_NAME(cdu561_25);
+}
diff --git a/src/devices/bus/nscsi/cdu561.h b/src/devices/bus/nscsi/cdu561.h
new file mode 100644
index 00000000000..74a0c29aef2
--- /dev/null
+++ b/src/devices/bus/nscsi/cdu561.h
@@ -0,0 +1,29 @@
+// license:BSD-3-Clause
+// copyright-holders:AJR
+
+#ifndef MAME_BUS_NSCSI_CDU561_H
+#define MAME_BUS_NSCSI_CDU561_H
+
+#pragma once
+
+#include "machine/nscsi_bus.h"
+
+class cdu561_25_device : public device_t, public nscsi_slot_card_interface
+{
+public:
+ cdu561_25_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 ATTR_COLD;
+ virtual void device_add_mconfig(machine_config &config) override ATTR_COLD;
+ virtual const tiny_rom_entry *device_rom_region() const override ATTR_COLD;
+
+private:
+ void mem_map(address_map &map) ATTR_COLD;
+};
+
+DECLARE_DEVICE_TYPE(CDU561_25, cdu561_25_device)
+
+#endif // MAME_BUS_NSCSI_CDU561_25_H
diff --git a/src/devices/bus/nscsi/cdu75s.cpp b/src/devices/bus/nscsi/cdu75s.cpp
new file mode 100644
index 00000000000..601b849f36a
--- /dev/null
+++ b/src/devices/bus/nscsi/cdu75s.cpp
@@ -0,0 +1,78 @@
+// license:BSD-3-Clause
+// copyright-holders:Olivier Galibert
+/*******************************************************************************
+
+ Skeleton device for Sony/Apple CDU75S 4x cdrom reader
+
+*******************************************************************************/
+
+// Chips:
+// - IC101: CXA1841Q - RF signal analog amplifier
+// - IC102: CXA1182Q-Z - servo control
+// - IC103: CXD2510Q - CD DSP
+// - IC105: BU4053BCF - analog mux/demux
+// - IC201: H8/3032 - main mcu, 64k internal rom
+// - IC202: CXD1808AQ - cdrom decoder
+// - IC203: LH62800K-60 - DRAM 256k*8
+// - IC204: FAS204 2405027 - Fast Architecture SCSI 204, ncr 53c94 compatible
+// - IC205: CXD8532Q - ? probable logic/processing, suspect it handles the jumpers, some dma, that kind of stuff
+// - IC301: pcm-1715u - DAC
+// - IC401: BA6295AFP - 2 channel motor driver
+
+// irq1 on CXD1808AQ
+// irq3 on FAS204
+
+#include "emu.h"
+#include "cdu75s.h"
+
+DEFINE_DEVICE_TYPE(CDU75S, cdu75s_device, "cdu75s", "Sony/Apple CDU75S CD-R")
+
+cdu75s_device::cdu75s_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock)
+ : device_t(mconfig, CDU75S, tag, owner, clock)
+ , nscsi_slot_card_interface(mconfig, *this, "fas204")
+ , m_mcu(*this, "mcu")
+ , m_scsi(*this, "fas204")
+ , m_rom(*this, "mcu")
+{
+}
+
+void cdu75s_device::device_start()
+{
+}
+
+void cdu75s_device::mem_map(address_map &map)
+{
+ map(0x00000, 0x1ffff).rom().region("mcu", 0);
+ map(0x40000, 0x4000f).m(m_scsi, FUNC(ncr53c94_device::map));
+
+ map(0x60000, 0x60007); // CXD8532Q
+ map(0x60005, 0x60005).r(FUNC(cdu75s_device::jumpers_r));
+
+ map(0xc0000, 0xc003f); // CXD1808AQ
+}
+
+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);
+
+ NCR53C94(config, m_scsi, 25'000'000); // FAS204, compatible
+}
+
+ROM_START(cdu75s)
+ ROM_REGION(0x20000, "mcu", 0)
+ ROM_LOAD("ic201.bin", 0x00000, 0x10000, CRC(8781ad49) SHA1(abdfb2561f2420a7f462e3bd5c8bd4d6eb0a9dfb))
+ ROM_LOAD("cdu-75s_1.0j_95.03.14_apple.bin", 0x10000, 0x10000, CRC(f4ad4d48) SHA1(7d674116304bc6948fe4a52d9859b4eb5d40b914))
+ROM_END
+
+const tiny_rom_entry *cdu75s_device::device_rom_region() const
+{
+ return ROM_NAME(cdu75s);
+}
+
+u8 cdu75s_device::jumpers_r()
+{
+ u32 jumpers_id = strtol(owner()->basetag(), nullptr, 16);
+ return (jumpers_id ^ 7) << 1;
+}
+
diff --git a/src/devices/bus/nscsi/cdu75s.h b/src/devices/bus/nscsi/cdu75s.h
new file mode 100644
index 00000000000..518060322c7
--- /dev/null
+++ b/src/devices/bus/nscsi/cdu75s.h
@@ -0,0 +1,37 @@
+// license:BSD-3-Clause
+// copyright-holders:O. Galibert
+
+#ifndef MAME_BUS_NSCSI_CDU75S_H
+#define MAME_BUS_NSCSI_CDU75S_H
+
+#pragma once
+
+#include "machine/nscsi_bus.h"
+#include "cpu/h8/h83032.h"
+#include "machine/ncr53c90.h"
+
+class cdu75s_device : public device_t, public nscsi_slot_card_interface
+{
+public:
+ cdu75s_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 ATTR_COLD;
+ virtual void device_add_mconfig(machine_config &config) override ATTR_COLD;
+ virtual const tiny_rom_entry *device_rom_region() const override ATTR_COLD;
+
+private:
+ void mem_map(address_map &map) ATTR_COLD;
+
+ required_device<h83032_device> m_mcu;
+ required_device<ncr53c94_device> m_scsi;
+ required_region_ptr<u16> m_rom;
+
+ u8 jumpers_r();
+};
+
+DECLARE_DEVICE_TYPE(CDU75S, cdu75s_device)
+
+#endif // MAME_BUS_NSCSI_CDU75S_H
diff --git a/src/devices/bus/nscsi/cfp1080s.cpp b/src/devices/bus/nscsi/cfp1080s.cpp
new file mode 100644
index 00000000000..8425348d78c
--- /dev/null
+++ b/src/devices/bus/nscsi/cfp1080s.cpp
@@ -0,0 +1,95 @@
+// license:BSD-3-Clause
+// copyright-holders:AJR
+/*******************************************************************************
+
+ Skeleton device for Conner CFP1080S SCSI hard drive.
+
+ Hardware includes "INDY" and "OCEANVIEW" QFP128 ICs by NCR. The MCU is a
+ QFP144 type labeled SC415902BFV.
+
+
+ Model - Conner CFP1080S
+ Interface - Fast SCSI-2
+ Capacity 1080MB
+ C/H/S - 2794/8/72-114
+ Total Blocks - 2,177,184
+
+*******************************************************************************/
+
+#include "emu.h"
+#include "bus/nscsi/cfp1080s.h"
+#include "cpu/m68hc16/m68hc16z.h"
+
+DEFINE_DEVICE_TYPE(CFP1080S, cfp1080s_device, "cfp1080s", "Conner CFP1080S")
+
+cfp1080s_device::cfp1080s_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock)
+ : nscsi_device(mconfig, CFP1080S, tag, owner, clock)
+ , nscsi_slot_card_interface(mconfig, *this, DEVICE_SELF)
+ , m_hdcpu(*this, "hdcpu")
+ , m_addrptr(0)
+{
+}
+
+void cfp1080s_device::device_start()
+{
+ save_item(NAME(m_addrptr));
+}
+
+u8 cfp1080s_device::ff081_r()
+{
+ return 0x80; // code often loops until bit 7 of this status register is set
+}
+
+u8 cfp1080s_device::ff082_r()
+{
+ return 0; // bit 6 tested
+}
+
+void cfp1080s_device::data_port_w(u8 data)
+{
+ logerror("Writing $%02X to data port (address pointer = $%06X)\n", data, m_addrptr);
+}
+
+void cfp1080s_device::addrptrl_w(u8 data)
+{
+ m_addrptr = (m_addrptr & 0xffff00) | data;
+}
+
+void cfp1080s_device::addrptrm_w(u8 data)
+{
+ m_addrptr = (m_addrptr & 0xff00ff) | u32(data) << 8;
+}
+
+void cfp1080s_device::addrptrh_w(u8 data)
+{
+ m_addrptr = (m_addrptr & 0x00ffff) | u32(data) << 16;
+}
+
+void cfp1080s_device::mem_map(address_map &map)
+{
+ map(0x00000, 0x1ffff).rom().region("firmware", 0);
+ map(0x20000, 0x21fff).ram();
+ map(0xff081, 0xff081).r(FUNC(cfp1080s_device::ff081_r));
+ map(0xff082, 0xff082).r(FUNC(cfp1080s_device::ff082_r));
+ map(0xff090, 0xff090).w(FUNC(cfp1080s_device::data_port_w));
+ map(0xff098, 0xff098).w(FUNC(cfp1080s_device::addrptrl_w));
+ map(0xff099, 0xff099).w(FUNC(cfp1080s_device::addrptrm_w));
+ map(0xff09a, 0xff09a).w(FUNC(cfp1080s_device::addrptrh_w));
+ map(0xff8c6, 0xff8c7).noprw(); // ?
+}
+
+void cfp1080s_device::device_add_mconfig(machine_config &config)
+{
+ MC68HC16Z1(config, m_hdcpu, 20'000'000); // exact type and clock unknown
+ m_hdcpu->set_addrmap(AS_PROGRAM, &cfp1080s_device::mem_map);
+}
+
+ROM_START(cfp1080s)
+ ROM_REGION16_BE(0x20000, "firmware", 0)
+ ROM_LOAD16_WORD_SWAP("conner_cfp1080s.bin", 0x00000, 0x20000, CRC(3254150a) SHA1(605be871e75ff775554fc8ce4e09bc2e35a6db09))
+ROM_END
+
+const tiny_rom_entry *cfp1080s_device::device_rom_region() const
+{
+ return ROM_NAME(cfp1080s);
+}
diff --git a/src/devices/bus/nscsi/cfp1080s.h b/src/devices/bus/nscsi/cfp1080s.h
new file mode 100644
index 00000000000..8a9e4efb0ed
--- /dev/null
+++ b/src/devices/bus/nscsi/cfp1080s.h
@@ -0,0 +1,40 @@
+// license:BSD-3-Clause
+// copyright-holders:AJR
+
+#ifndef MAME_BUS_NSCSI_CFP1080S_H
+#define MAME_BUS_NSCSI_CFP1080S_H
+
+#pragma once
+
+#include "machine/nscsi_bus.h"
+
+class cfp1080s_device : public nscsi_device, public nscsi_slot_card_interface
+{
+public:
+ cfp1080s_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 ATTR_COLD;
+ virtual void device_add_mconfig(machine_config &config) override ATTR_COLD;
+ virtual const tiny_rom_entry *device_rom_region() const override ATTR_COLD;
+
+private:
+ u8 ff081_r();
+ u8 ff082_r();
+ void data_port_w(u8 data);
+ void addrptrl_w(u8 data);
+ void addrptrm_w(u8 data);
+ void addrptrh_w(u8 data);
+
+ void mem_map(address_map &map) ATTR_COLD;
+
+ required_device<cpu_device> m_hdcpu;
+
+ u32 m_addrptr;
+};
+
+DECLARE_DEVICE_TYPE(CFP1080S, cfp1080s_device)
+
+#endif // MAME_BUS_NSCSI_CFP1080S_H
diff --git a/src/devices/bus/nscsi/crd254sh.cpp b/src/devices/bus/nscsi/crd254sh.cpp
new file mode 100644
index 00000000000..7561f94cb6e
--- /dev/null
+++ b/src/devices/bus/nscsi/crd254sh.cpp
@@ -0,0 +1,63 @@
+// license:BSD-3-Clause
+// copyright-holders:Olivier Galibert
+/*******************************************************************************
+
+ Skeleton device for Sony/Apple CRD-254SH 4x cdrom reader
+
+*******************************************************************************/
+
+// Chips:
+// - Hitachi H8/3040 : CPU, external rom mode
+// - Sanyo LC89512W : CD-ROM error correction + SCSI
+// - Sanyo LC7868K : DSP for CD players
+// - Sanyo LC98200 : ?
+// - Sanyo LA9220 : Analog signal processing and servo control
+// - Sanyo LC78816W : ?
+// - Sanyo LA6531 : 2-Channel BTL-USE driver
+// - 2x NPN NN514256J-45 : 256Kx4 DRAM
+//
+// The LC89512W combines a LC89517 (cdrom) upgraded for 4x and a LC8945 (scsi)
+// The LC89517 is a LC89515 upgraded for x2 capability
+// The LC89515 is an enhanced LC8951, and is documented
+
+
+#include "emu.h"
+#include "crd254sh.h"
+
+DEFINE_DEVICE_TYPE(CRD254SH, crd254sh_device, "crd254sh", "Sanyo CRD-254SH CD-ROM")
+
+crd254sh_device::crd254sh_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock)
+ : device_t(mconfig, CRD254SH, tag, owner, clock)
+ , nscsi_slot_card_interface(mconfig, *this, "dummy_scsi")
+ , m_mcu(*this, "mcu")
+ , m_scsi(*this, "dummy_scsi")
+ , m_rom(*this, "mcu")
+{
+}
+
+void crd254sh_device::device_start()
+{
+}
+
+void crd254sh_device::mem_map(address_map &map)
+{
+ map(0x00000, 0x0ffff).rom().region("mcu", 0);
+}
+
+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);
+
+ NCR53C94(config, m_scsi, 25_MHz_XTAL); // Placeholder until we implement the real chip
+}
+
+ROM_START(crd254sh)
+ ROM_REGION(0x10000, "mcu", 0)
+ ROM_LOAD("crd-254s_1.02.bin", 0x00000, 0x10000, CRC(539df5f0) SHA1(edb1f7d96f351ef70b8ade03449fb63e0e0a652b))
+ROM_END
+
+const tiny_rom_entry *crd254sh_device::device_rom_region() const
+{
+ return ROM_NAME(crd254sh);
+}
diff --git a/src/devices/bus/nscsi/crd254sh.h b/src/devices/bus/nscsi/crd254sh.h
new file mode 100644
index 00000000000..d3409d945b4
--- /dev/null
+++ b/src/devices/bus/nscsi/crd254sh.h
@@ -0,0 +1,35 @@
+// license:BSD-3-Clause
+// copyright-holders:O. Galibert
+
+#ifndef MAME_BUS_NSCSI_CRD254SH_H
+#define MAME_BUS_NSCSI_CRD254SH_H
+
+#pragma once
+
+#include "machine/nscsi_bus.h"
+#include "cpu/h8/h83042.h"
+#include "machine/ncr53c90.h"
+
+class crd254sh_device : public device_t, public nscsi_slot_card_interface
+{
+public:
+ crd254sh_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 ATTR_COLD;
+ virtual void device_add_mconfig(machine_config &config) override ATTR_COLD;
+ virtual const tiny_rom_entry *device_rom_region() const override ATTR_COLD;
+
+private:
+ void mem_map(address_map &map) ATTR_COLD;
+
+ required_device<h83040_device> m_mcu;
+ required_device<ncr53c94_device> m_scsi;
+ required_region_ptr<u16> m_rom;
+};
+
+DECLARE_DEVICE_TYPE(CRD254SH, crd254sh_device)
+
+#endif // MAME_BUS_NSCSI_CRD254SH_H
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/cw7501.h b/src/devices/bus/nscsi/cw7501.h
index 0b785c4d3ba..db1d3f42c69 100644
--- a/src/devices/bus/nscsi/cw7501.h
+++ b/src/devices/bus/nscsi/cw7501.h
@@ -1,8 +1,8 @@
// license:BSD-3-Clause
// copyright-holders:AJR
-#ifndef MAME_BUS_NSCSI_CW7501
-#define MAME_BUS_NSCSI_CW7501 1
+#ifndef MAME_BUS_NSCSI_CW7501_H
+#define MAME_BUS_NSCSI_CW7501_H
#pragma once
@@ -19,16 +19,16 @@ public:
protected:
cw7501_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, u32 clock);
- 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 device_start() override ATTR_COLD;
+ virtual void device_add_mconfig(machine_config &config) override ATTR_COLD;
+ virtual const tiny_rom_entry *device_rom_region() const override ATTR_COLD;
private:
u8 mystery_data_r();
void mystery_data_w(u8 data);
void mystery_address_w(u8 data);
- void mem_map(address_map &map);
+ void mem_map(address_map &map) ATTR_COLD;
required_device<m37710s4_device> m_cdcpu;
@@ -43,10 +43,10 @@ public:
static constexpr feature_type unemulated_features() { return feature::DISK; }
protected:
- virtual const tiny_rom_entry *device_rom_region() const override;
+ virtual const tiny_rom_entry *device_rom_region() const override ATTR_COLD;
};
DECLARE_DEVICE_TYPE(CW7501, cw7501_device)
DECLARE_DEVICE_TYPE(CDR4210, cdr4210_device)
-#endif // MAME_BUS_NSCSI_CW7501
+#endif // MAME_BUS_NSCSI_CW7501_H
diff --git a/src/devices/bus/nscsi/devices.cpp b/src/devices/bus/nscsi/devices.cpp
index c8f45a0d84a..0ff4b192467 100644
--- a/src/devices/bus/nscsi/devices.cpp
+++ b/src/devices/bus/nscsi/devices.cpp
@@ -3,20 +3,43 @@
#include "emu.h"
+#include "bus/nscsi/applecd.h"
#include "bus/nscsi/cd.h"
#include "bus/nscsi/cdd2000.h"
#include "bus/nscsi/cdrn820s.h"
+#include "bus/nscsi/cdu75s.h"
+#include "bus/nscsi/cdu415.h"
+#include "bus/nscsi/cdu561.h"
+#include "bus/nscsi/cfp1080s.h"
+#include "bus/nscsi/crd254sh.h"
#include "bus/nscsi/cw7501.h"
#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);
device.option_add("cdrn820s", CDRN820S);
device.option_add("cdd2000", CDD2000);
-};
+ device.option_add("cdu75s", CDU75S);
+ device.option_add("cdu415", CDU415);
+ device.option_add("cdu561_25", CDU561_25);
+ device.option_add("crd254sh", CRD254SH);
+ device.option_add("smoc501", SMOC501);
+ device.option_add("aplcd150", APPLECD150);
+ device.option_add("aplcdsc", NSCSI_CDROM_APPLE);
+ device.option_add("cfp1080s", CFP1080S);
+}
+
+void mac_scsi_devices(device_slot_interface &device)
+{
+ default_scsi_devices(device);
+ device.option_replace("cdrom", NSCSI_CDROM_APPLE);
+}
diff --git a/src/devices/bus/nscsi/devices.h b/src/devices/bus/nscsi/devices.h
index 9958577517a..996fbd1b77e 100644
--- a/src/devices/bus/nscsi/devices.h
+++ b/src/devices/bus/nscsi/devices.h
@@ -7,5 +7,6 @@
#pragma once
extern void default_scsi_devices(device_slot_interface &device);
+extern void mac_scsi_devices(device_slot_interface &device);
#endif // MAME_BUS_NSCSI_DEVICES_H
diff --git a/src/devices/bus/nscsi/hd.cpp b/src/devices/bus/nscsi/hd.cpp
index 6c6543b409c..fe5fc45127b 100644
--- a/src/devices/bus/nscsi/hd.cpp
+++ b/src/devices/bus/nscsi/hd.cpp
@@ -4,9 +4,11 @@
#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
@@ -20,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)
{
}
@@ -37,24 +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 hard_disk_info *hdinfo = hard_disk_get_info(harddisk);
- bytes_per_sector = hdinfo->sectorbytes;
-
- chd_file *chd = image->get_chd_file();
- if(chd != nullptr)
- chd->read_metadata(HARD_DISK_IDENT_METADATA_TAG, 0, m_inquiry_data);
+ const auto &hdinfo = image->get_info();
+ bytes_per_sector = hdinfo.sectorbytes;
+ 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)
@@ -69,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(!hard_disk_read(harddisk, cur_lba, block)) {
+ if(!image->read(cur_lba, block)) {
LOG("HD READ ERROR !\n");
memset(block, 0, sizeof(block));
}
@@ -92,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(!hard_disk_write(harddisk, cur_lba, block))
+ if(!image->write(cur_lba, block))
LOG("HD WRITE ERROR !\n");
}
}
@@ -112,19 +110,26 @@ 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);
- scsi_data_in(2, blocks*bytes_per_sector);
- scsi_status_complete(SS_GOOD);
+ if(image->read(lba, block)) {
+ scsi_data_in(2, blocks*bytes_per_sector);
+ scsi_status_complete(SS_GOOD);
+ }
+ else
+ {
+ scsi_status_complete(SS_CHECK_CONDITION);
+ sense(false, SK_ILLEGAL_REQUEST, SK_ASC_INVALID_FIELD_IN_CDB);
+ }
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;
@@ -214,17 +219,15 @@ void nscsi_harddisk_device::scsi_command()
scsi_cmdbuf[pos++] = 0x00; // medium type
scsi_cmdbuf[pos++] = 0x00; // WP, cache
- hard_disk_info *info = hard_disk_get_info(harddisk);
- uint32_t dsize = info->cylinders * info->heads * info->sectors - 1;
+ 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;
@@ -242,7 +245,7 @@ void nscsi_harddisk_device::scsi_command()
case 0x01: // read-write error recovery page
scsi_cmdbuf[pos++] = 0x01; // !PS, page id
scsi_cmdbuf[pos++] = 0x0a; // page length
- scsi_cmdbuf[pos++] = 0; // various bits
+ scsi_cmdbuf[pos++] = 0x26; // various bits
scsi_cmdbuf[pos++] = 0; // read retry count
scsi_cmdbuf[pos++] = 0; // correction span
scsi_cmdbuf[pos++] = 0; // head offset count
@@ -276,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
@@ -304,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;
}
@@ -382,7 +384,7 @@ void nscsi_harddisk_device::scsi_command()
}
if (!fail) {
- scsi_cmdbuf[0] = pos;
+ scsi_cmdbuf[0] = pos - 1;
if (pos > size)
pos = size;
@@ -400,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;
@@ -418,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);
@@ -442,20 +444,19 @@ void nscsi_harddisk_device::scsi_command()
break;
}
+ case SC_SYNCHRONIZE_CACHE:
+ LOG("command SYNCHRONIZE CACHE (10)\n");
+ scsi_status_complete(SS_GOOD);
+ break;
+
case SC_READ_CAPACITY: {
LOG("command READ CAPACITY\n");
- hard_disk_info *info = hard_disk_get_info(harddisk);
- uint32_t size = info->cylinders * info->heads * info->sectors - 1;
+ 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);
@@ -463,18 +464,25 @@ 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);
- scsi_data_in(2, blocks*bytes_per_sector);
- scsi_status_complete(SS_GOOD);
+ if(image->read(lba, block)) {
+ scsi_data_in(2, blocks*bytes_per_sector);
+ scsi_status_complete(SS_GOOD);
+ }
+ else
+ {
+ scsi_status_complete(SS_CHECK_CONDITION);
+ sense(false, SK_ILLEGAL_REQUEST, SK_ASC_INVALID_FIELD_IN_CDB);
+ }
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);
@@ -490,12 +498,12 @@ void nscsi_harddisk_device::scsi_command()
(scsi_cmdbuf[1] & 0x10) ? " FMTDATA" : "",
(scsi_cmdbuf[1] & 0x08) ? " CMPLIST" : "");
{
- hard_disk_info *info = hard_disk_get_info(harddisk);
- 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++) {
- hard_disk_write(harddisk, cyl * head * sector, block.get());
+ 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++) {
+ image->write(cyl * head * sector, block.get());
}
}
}
@@ -504,11 +512,16 @@ void nscsi_harddisk_device::scsi_command()
break;
case SC_MODE_SELECT_6:
- LOG("command MODE SELECT\n");
+ 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]);
+
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);
@@ -517,7 +530,8 @@ void nscsi_harddisk_device::scsi_command()
break;
default:
- LOG("command %02x ***UNKNOWN***\n", scsi_cmdbuf[0]);
+ LOGMASKED(LOG_UNSUPPORTED, "command %02x ***UNKNOWN***\n", scsi_cmdbuf[0]);
+ // Parent may handle this
nscsi_full_device::scsi_command();
break;
}
diff --git a/src/devices/bus/nscsi/hd.h b/src/devices/bus/nscsi/hd.h
index 7ee1f851d26..07c32689589 100644
--- a/src/devices/bus/nscsi/hd.h
+++ b/src/devices/bus/nscsi/hd.h
@@ -16,9 +16,9 @@ public:
protected:
nscsi_harddisk_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 device_start() override ATTR_COLD;
+ virtual void device_reset() override ATTR_COLD;
+ virtual void device_add_mconfig(machine_config &config) override ATTR_COLD;
virtual void scsi_command() override;
virtual uint8_t scsi_get_data(int id, int pos) override;
@@ -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 5ecf65ef693..52358d7e851 100644
--- a/src/devices/bus/nscsi/s1410.cpp
+++ b/src/devices/bus/nscsi/s1410.cpp
@@ -3,7 +3,16 @@
#include "emu.h"
#include "bus/nscsi/s1410.h"
-DEFINE_DEVICE_TYPE(NSCSI_S1410, nscsi_s1410_device, "scsi_s1410", "S1410 Hard Disk")
+#include "multibyte.h"
+
+#define LOG_COMMAND (1U << 1)
+#define LOG_DATA (1U << 2)
+
+#define VERBOSE 0
+
+#include "logmacro.h"
+
+DEFINE_DEVICE_TYPE(NSCSI_S1410, nscsi_s1410_device, "scsi_s1410", "Xebec S1410 5.25 Inch Winchester Disk Controller")
nscsi_s1410_device::nscsi_s1410_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) :
nscsi_harddisk_device(mconfig, NSCSI_S1410, tag, owner, clock)
@@ -25,48 +34,87 @@ 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_REQUEST_SENSE:
+ 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_FORMAT_UNIT:
+ case SC_SEEK:
if (scsi_cmdbuf[1] >> 5) {
scsi_status_complete(SS_NOT_READY);
- return;
+ 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);
+ break;
+
+ case SC_FORMAT_UNIT:
+ LOG("command FORMAT UNIT\n");
+ {
+ const auto &info = image->get_info();
+ auto block = std::make_unique<uint8_t[]>(info.sectorbytes);
+ memset(&block[0], 0x6c, info.sectorbytes);
+ lba = get_u24be(&scsi_cmdbuf[1]) & 0x1fffff;
+ for(; lba < (info.cylinders * info.heads * info.sectors); lba++) {
+ image->write(lba, block.get());
+ }
+ }
scsi_status_complete(SS_GOOD);
break;
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;
- std::vector<uint8_t> data(track_length);
- memset(&data[0], 0xc6, track_length);
+ auto block = std::make_unique<uint8_t[]>(track_length);
+ memset(&block[0], 0x6c, track_length);
- if(!hard_disk_write(harddisk, lba, &data[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);
}
@@ -76,31 +124,33 @@ 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;
}
- scsi_data_in(2, 3);
+ scsi_data_out(2, 3);
scsi_status_complete(SS_GOOD);
break;
case SC_INIT_DRIVE_PARAMS:
- scsi_data_in(2, 8);
+ scsi_data_out(2, 8);
scsi_status_complete(SS_GOOD);
break;
case SC_WRITE_SECTOR_BUFFER:
- scsi_data_in(2, 512);
+ scsi_data_out(2, bytes_per_sector);
scsi_status_complete(SS_GOOD);
break;
case SC_READ_SECTOR_BUFFER:
- scsi_data_out(2, 512);
+ scsi_data_in(2, bytes_per_sector);
scsi_status_complete(SS_GOOD);
break;
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);
@@ -134,15 +184,22 @@ uint8_t nscsi_s1410_device::scsi_get_data(int id, int pos)
void nscsi_s1410_device::scsi_put_data(int id, int pos, uint8_t data)
{
+ if(id != 2 && !pos) {
+ return nscsi_harddisk_device::scsi_put_data(id, pos, data);
+ }
+
switch(scsi_cmdbuf[0]) {
case SC_FORMAT_ALT_TRACK:
+ LOGMASKED(LOG_DATA, "s1410: scsi_put_data, id:%d pos:%d data:%02x %c\n", id, pos, data, data >= 0x20 && data < 0x7f ? (char)data : ' ');
break;
case SC_INIT_DRIVE_PARAMS:
+ LOGMASKED(LOG_DATA, "s1410: scsi_put_data, id:%d pos:%d data:%02x %c\n", id, pos, data, data >= 0x20 && data < 0x7f ? (char)data : ' ');
params[pos] = data;
break;
case SC_WRITE_SECTOR_BUFFER:
+ LOGMASKED(LOG_DATA, "s1410: scsi_put_data, id:%d pos:%d data:%02x %c\n", id, pos, data, data >= 0x20 && data < 0x7f ? (char)data : ' ');
block[pos] = data;
break;
@@ -150,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..a7f69e9cd94 100644
--- a/src/devices/bus/nscsi/s1410.h
+++ b/src/devices/bus/nscsi/s1410.h
@@ -1,7 +1,7 @@
// license:BSD-3-Clause
// copyright-holders:Olivier Galibert
-#ifndef MAME_MACHINE_NSCSI_S1410_H
-#define MAME_MACHINE_NSCSI_S1410_H
+#ifndef MAME_BUS_NSCSI_S1410_H
+#define MAME_BUS_NSCSI_S1410_H
#pragma once
@@ -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
};
- virtual void device_reset() override;
+ // SCSI sense keys
+ enum {
+ SK_NO_ERROR = 0x00,
+ SK_DRIVE_NOT_READY = 0x04,
+ SK_FORMAT_ERROR = 0x1a
+ };
+
+ virtual void device_reset() override ATTR_COLD;
+ 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/smoc501.cpp b/src/devices/bus/nscsi/smoc501.cpp
new file mode 100644
index 00000000000..48ede8a888c
--- /dev/null
+++ b/src/devices/bus/nscsi/smoc501.cpp
@@ -0,0 +1,91 @@
+// license:BSD-3-Clause
+// copyright-holders:AJR
+/**********************************************************************
+
+ Sony SMO-C501 Magneto Optical Disk Controller
+
+ This is the SCSI/M-ESDI bridge controller for the SMO-D501 and
+ SMO-E501 MO disk drives.
+
+ The PCB features some ASICs by ADSI.
+
+**********************************************************************/
+
+#include "emu.h"
+#include "smoc501.h"
+
+#include "cpu/nec/v5x.h"
+#include "machine/wd33c9x.h"
+
+DEFINE_DEVICE_TYPE(SMOC501, smoc501_device, "smoc501", "Sony SMO-C501 MO Disk Controller")
+
+smoc501_device::smoc501_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock)
+ : device_t(mconfig, SMOC501, tag, owner, clock)
+ , nscsi_slot_card_interface(mconfig, *this, "scsic")
+{
+}
+
+void smoc501_device::device_start()
+{
+}
+
+
+void smoc501_device::mem_map(address_map &map)
+{
+ map(0x00000, 0x07fff).ram();
+ map(0x0a000, 0x0a01f).rw("scsic", FUNC(wd33c93_device::dir_r), FUNC(wd33c93_device::dir_w));
+ map(0xf0000, 0xfffff).rom().region("microcode", 0);
+}
+
+
+static INPUT_PORTS_START(smoc501)
+ PORT_START("DSW")
+ PORT_DIPNAME(0x80, 0x80, "Loading Control") PORT_DIPLOCATION("DSW:1")
+ PORT_DIPSETTING(0x80, DEF_STR(Off))
+ PORT_DIPSETTING(0x00, DEF_STR(On))
+ PORT_DIPNAME(0x40, 0x40, "Eject Mode") PORT_DIPLOCATION("DSW:2")
+ PORT_DIPSETTING(0x40, "Eject Button")
+ PORT_DIPSETTING(0x00, "Controller")
+ PORT_DIPNAME(0x20, 0x20, "Temporary Mode") PORT_DIPLOCATION("DSW:3")
+ PORT_DIPSETTING(0x00, "512 Bytes/Sector")
+ PORT_DIPSETTING(0x20, "1024 Bytes/Sector")
+ PORT_DIPNAME(0x10, 0x00, "Terminator") PORT_DIPLOCATION("DSW:4")
+ PORT_DIPSETTING(0x10, DEF_STR(Off))
+ PORT_DIPSETTING(0x00, "On (Last Drive)")
+ PORT_DIPNAME(0x08, 0x00, "Auto Spin Up") PORT_DIPLOCATION("DSW:5")
+ PORT_DIPSETTING(0x08, "By Drive Unit")
+ PORT_DIPSETTING(0x00, "By Controller")
+ PORT_DIPNAME(0x07, 0x06, "Drive Number") PORT_DIPLOCATION("DSW:8,7,6")
+ PORT_DIPSETTING(0x07, "0")
+ PORT_DIPSETTING(0x06, "1")
+ PORT_DIPSETTING(0x05, "2")
+ PORT_DIPSETTING(0x04, "3")
+ PORT_DIPSETTING(0x03, "4")
+ PORT_DIPSETTING(0x02, "5")
+ PORT_DIPSETTING(0x01, "6")
+ PORT_DIPSETTING(0x00, "7")
+INPUT_PORTS_END
+
+ioport_constructor smoc501_device::device_input_ports() const
+{
+ return INPUT_PORTS_NAME(smoc501);
+}
+
+void smoc501_device::device_add_mconfig(machine_config &config)
+{
+ v40_device &mpu(V40(config, "mpu", 16'000'000)); // clock is guessed
+ mpu.set_addrmap(AS_PROGRAM, &smoc501_device::mem_map);
+
+ wd33c93_device &scsic(WD33C93(config, "scsic", 10'000'000)); // clock is guessed
+ scsic.irq_cb().set_inputline("mpu", INPUT_LINE_IRQ5);
+}
+
+ROM_START(smoc501)
+ ROM_REGION(0x10000, "microcode", 0)
+ ROM_LOAD("c501-00.rom", 0x00000, 0x10000, CRC(0ae04500) SHA1(96c73a3a2ecdc8c903e920f2afba5b4edd5cdba6))
+ROM_END
+
+const tiny_rom_entry *smoc501_device::device_rom_region() const
+{
+ return ROM_NAME(smoc501);
+}
diff --git a/src/devices/bus/nscsi/smoc501.h b/src/devices/bus/nscsi/smoc501.h
new file mode 100644
index 00000000000..1069e30fbd8
--- /dev/null
+++ b/src/devices/bus/nscsi/smoc501.h
@@ -0,0 +1,30 @@
+// license:BSD-3-Clause
+// copyright-holders:AJR
+
+#ifndef MAME_BUS_NSCSI_SMOC501_H
+#define MAME_BUS_NSCSI_SMOC501_H
+
+#pragma once
+
+#include "machine/nscsi_bus.h"
+
+class smoc501_device : public device_t, public nscsi_slot_card_interface
+{
+public:
+ smoc501_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 ATTR_COLD;
+ virtual ioport_constructor device_input_ports() const override ATTR_COLD;
+ virtual void device_add_mconfig(machine_config &config) override ATTR_COLD;
+ virtual const tiny_rom_entry *device_rom_region() const override ATTR_COLD;
+
+private:
+ void mem_map(address_map &map) ATTR_COLD;
+};
+
+DECLARE_DEVICE_TYPE(SMOC501, smoc501_device)
+
+#endif // MAME_BUS_NSCSI_SMOC501_H
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..6f3dc1d67e6
--- /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 ATTR_COLD;
+
+ // nscsi_full_device implementation
+ virtual void device_start() override ATTR_COLD;
+ virtual void device_reset() override ATTR_COLD;
+ 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..f358c3b22f8
--- /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 ATTR_COLD;
+ virtual void device_reset() override ATTR_COLD;
+
+ // optional information overrides
+ virtual void device_add_mconfig(machine_config &config) override ATTR_COLD;
+ virtual const tiny_rom_entry *device_rom_region() const override ATTR_COLD;
+ virtual ioport_constructor device_input_ports() const override ATTR_COLD;
+
+ 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, u32 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, u32 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;
+}
+
+u32 lcpds_cv8lc_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();
+
+ 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..b43bc4e7583
--- /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_8LC_H
+#define MAME_BUS_NUBUS_8LC_H
+
+#pragma once
+
+#include "nubus.h"
+
+DECLARE_DEVICE_TYPE(PDSLC_COLORVUE8LC, device_nubus_card_interface)
+
+#endif // MAME_BUS_NUBUS_8LC_H
diff --git a/src/devices/bus/nubus/bootbug.cpp b/src/devices/bus/nubus/bootbug.cpp
index 24763b64dc2..4d7b568b19c 100644
--- a/src/devices/bus/nubus/bootbug.cpp
+++ b/src/devices/bus/nubus/bootbug.cpp
@@ -5,18 +5,42 @@
Brigent BootBug card
Debugger support card for creators of NuBus slot firmware and other
- early-boot/low-level software.
+ early-boot/low-level software. Actually has many of the features
+ of MacsBug including A6 stack tracing. Absolutely not PowerMac compatible
+ though, unlike MacsBug.
- Basically a serial card with an overachieving declaration ROM.
+ Basically an 8250 serial card with an overachieving declaration ROM.
***************************************************************************/
#include "emu.h"
#include "bootbug.h"
+
#include "bus/rs232/rs232.h"
#include "bus/rs232/terminal.h"
#include "bus/rs232/null_modem.h"
-#include "screen.h"
+#include "machine/ins8250.h"
+
+namespace {
+class nubus_bootbug_device : public device_t,
+ public device_nubus_card_interface
+{
+public:
+ nubus_bootbug_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock);
+
+protected:
+ required_device<ns16450_device> m_uart;
+
+ // device-level overrides
+ virtual void device_start() override ATTR_COLD;
+
+ // optional information overrides
+ virtual void device_add_mconfig(machine_config &config) override ATTR_COLD;
+ virtual const tiny_rom_entry *device_rom_region() const override ATTR_COLD;
+
+private:
+ void card_map(address_map &map);
+};
static void isa_com(device_slot_interface &device)
{
@@ -24,10 +48,8 @@ static void isa_com(device_slot_interface &device)
device.option_add("null_modem", NULL_MODEM);
}
-#define BOOTBUG_ROM_REGION "btbug_rom"
-
ROM_START( bootbug )
- ROM_REGION(0x10000, BOOTBUG_ROM_REGION, 0)
+ ROM_REGION(0x10000, "declrom", 0)
ROM_DEFAULT_BIOS("bb15")
ROM_SYSTEM_BIOS(0, "bb15", "BootBug v1.5")
ROMX_LOAD( "bootbug1.5.bin", 0x000000, 0x010000, CRC(432badf0) SHA1(914ad4bb28946cac732cf8b178508b69e4c1aae2), ROM_BIOS(0))
@@ -35,17 +57,6 @@ ROM_START( bootbug )
ROMX_LOAD( "bootbug1.3.bin", 0x000000, 0x010000, CRC(2902a234) SHA1(c783d19a5e4c536e58e1e7e201ec47e8fb78d435), ROM_BIOS(1))
ROM_END
-//**************************************************************************
-// GLOBAL VARIABLES
-//**************************************************************************
-
-DEFINE_DEVICE_TYPE(NUBUS_BOOTBUG, nubus_bootbug_device, "nb_btbug", "Brigent BootBug debugger card")
-
-
-//-------------------------------------------------
-// device_add_mconfig - add device configuration
-//-------------------------------------------------
-
void nubus_bootbug_device::device_add_mconfig(machine_config &config)
{
NS16450(config, m_uart, XTAL(1'843'200));
@@ -61,64 +72,29 @@ void nubus_bootbug_device::device_add_mconfig(machine_config &config)
serport0.cts_handler().set(m_uart, FUNC(ins8250_uart_device::cts_w));
}
-//-------------------------------------------------
-// rom_region - device-specific ROM region
-//-------------------------------------------------
-
const tiny_rom_entry *nubus_bootbug_device::device_rom_region() const
{
return ROM_NAME( bootbug );
}
-//**************************************************************************
-// LIVE DEVICE
-//**************************************************************************
-
-//-------------------------------------------------
-// nubus_bootbug_device - constructor
-//-------------------------------------------------
-
-nubus_bootbug_device::nubus_bootbug_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) :
- nubus_bootbug_device(mconfig, NUBUS_BOOTBUG, tag, owner, clock)
-{
-}
-
-nubus_bootbug_device::nubus_bootbug_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_bootbug_device::nubus_bootbug_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock) :
+ device_t(mconfig, NUBUS_BOOTBUG, tag, owner, clock),
device_nubus_card_interface(mconfig, *this),
m_uart(*this, "uart_0")
{
}
-//-------------------------------------------------
-// device_start - device-specific startup
-//-------------------------------------------------
-
-void nubus_bootbug_device::device_start()
+void nubus_bootbug_device::card_map(address_map &map)
{
- uint32_t slotspace;
-
- install_declaration_rom(this, BOOTBUG_ROM_REGION);
-
- slotspace = get_slotspace();
-
- nubus().install_device(slotspace, slotspace+0xff, read32_delegate(FUNC(nubus_bootbug_device::dev_r), this), write32_delegate(FUNC(nubus_bootbug_device::dev_w), this));
+ map(0x00'0000, 0x00'00ff).rw(m_uart, FUNC(ns16450_device::ins8250_r), FUNC(ns16450_device::ins8250_w)).umask32(0x000000ff);
}
-//-------------------------------------------------
-// device_reset - device-specific reset
-//-------------------------------------------------
-
-void nubus_bootbug_device::device_reset()
+void nubus_bootbug_device::device_start()
{
+ install_declaration_rom("declrom");
+ nubus().install_map(*this, &nubus_bootbug_device::card_map);
}
-WRITE32_MEMBER( nubus_bootbug_device::dev_w )
-{
- m_uart->ins8250_w(offset, data & 0xff);
-}
+} // anonymous namespace
-READ32_MEMBER( nubus_bootbug_device::dev_r )
-{
- return m_uart->ins8250_r(offset);
-}
+DEFINE_DEVICE_TYPE_PRIVATE(NUBUS_BOOTBUG, device_nubus_card_interface, nubus_bootbug_device, "nb_btbug", "Brigent BootBug debugger card")
diff --git a/src/devices/bus/nubus/bootbug.h b/src/devices/bus/nubus/bootbug.h
index 5dced2d119c..8593b041078 100644
--- a/src/devices/bus/nubus/bootbug.h
+++ b/src/devices/bus/nubus/bootbug.h
@@ -6,41 +6,7 @@
#pragma once
#include "nubus.h"
-#include "machine/ins8250.h"
-//**************************************************************************
-// TYPE DEFINITIONS
-//**************************************************************************
-
-// ======================> nubus_bootbug_device
-
-class nubus_bootbug_device :
- public device_t,
- public device_nubus_card_interface
-{
-public:
- // construction/destruction
- nubus_bootbug_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
-
-protected:
- nubus_bootbug_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock);
-
- required_device<ns16450_device> m_uart;
-
- // 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:
- DECLARE_READ32_MEMBER(dev_r);
- DECLARE_WRITE32_MEMBER(dev_w);
-};
-
-// device type definition
-DECLARE_DEVICE_TYPE(NUBUS_BOOTBUG, nubus_bootbug_device)
+DECLARE_DEVICE_TYPE(NUBUS_BOOTBUG, device_nubus_card_interface)
#endif // MAME_BUS_NUBUS_BOOTBUG_H
diff --git a/src/devices/bus/nubus/cards.cpp b/src/devices/bus/nubus/cards.cpp
new file mode 100644
index 00000000000..b47a690ea65
--- /dev/null
+++ b/src/devices/bus/nubus/cards.cpp
@@ -0,0 +1,120 @@
+// license:BSD-3-Clause
+// copyright-holders:R. Belmont
+/***************************************************************************
+
+ 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"
+#include "nubus_asntmc3b.h"
+#include "nubus_cb264.h"
+#include "nubus_image.h"
+#include "nubus_m2hires.h"
+#include "nubus_m2video.h"
+#include "nubus_radiustpd.h"
+#include "nubus_spec8.h"
+#include "nubus_specpdq.h"
+#include "nubus_vikbw.h"
+#include "pds30_30hr.h"
+#include "pds30_cb264.h"
+#include "pds30_procolor816.h"
+#include "pds30_sigmalview.h"
+#include "quadralink.h"
+#include "thunder4gx.h"
+
+void mac_nubus_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("workstation",NUBUS_WORKSTATION); // Apple Macintosh II Workstation 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("pc8", NUBUS_PROCOLOR8); // Lapis ProColor Server 8 video card
+}
+
+void powermac_nubus_cards(device_slot_interface &device)
+{
+ 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("asmc3nb", NUBUS_ASNTMC3NB); // Asante MC3NB Ethernet card
+ device.option_add("enetnb", NUBUS_APPLEENET); // Apple NuBus Ethernet
+ device.option_add("quadralink", NUBUS_QUADRALINK); // AE Quadralink serial card
+ device.option_add("thunder4gx", NUBUS_THUNDERIVGX); // Radius Thunder IV GX video card
+}
+
+void mac_pds030_cards(device_slot_interface &device)
+{
+ device.option_add("cb264se30", PDS030_CB264SE30); // RasterOps Colorboard 264/SE30
+ device.option_add("pc8", PDS030_PROCOLOR8); // Lapis ProColor Server 8 PDS
+ 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("30hrint", PDS030_XCEED30HRINT); // Micron/XCEED Technology Color 30HR (take over SE/30 internal monitor)
+ device.option_add("mc30", PDS030_XCEEDMC30); // Micron/XCEED Technology MacroColor 30
+ device.option_add("mc30int", PDS030_XCEEDMC30INT); // Micron/XCEED Technology MacroColor 30 (take over SE/30 internal monitor)
+ 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("workstation", NUBUS_WORKSTATION); // Apple Macintosh II Workstation 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("pc8", NUBUS_PROCOLOR8); // Lapis ProColor Server 8 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
new file mode 100644
index 00000000000..67c8f853022
--- /dev/null
+++ b/src/devices/bus/nubus/cards.h
@@ -0,0 +1,21 @@
+// license:BSD-3-Clause
+// copyright-holders:R. Belmont
+/***************************************************************************
+
+ NuBus, SE/30 PDS, and LC PDS slot cards
+
+***************************************************************************/
+
+#ifndef MAME_BUS_NUBUS_CARDS_H
+#define MAME_BUS_NUBUS_CARDS_H
+
+#pragma once
+
+void mac_nubus_cards(device_slot_interface &device) ATTR_COLD;
+void powermac_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
new file mode 100644
index 00000000000..4ced40e7935
--- /dev/null
+++ b/src/devices/bus/nubus/laserview.cpp
@@ -0,0 +1,273 @@
+// license:BSD-3-Clause
+// copyright-holders:R. Belmont
+/***************************************************************************
+
+ Sigma Designs fixed-resolution monochrome video card
+ 1664x1200 or 832x600 according to the ad, but more modes exist
+ in the dumped v3.0 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
+
+ Modes in the declaration ROM shown by SlotsParse are:
+ 832x600
+ 1664x1200
+ 640x480
+ 1280x960
+ 512x384
+ 1024x768
+
+ TODO: Figure out how to set the other modes. A software driver, possibly?
+
+***************************************************************************/
+
+#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 {
+
+ 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);
+
+ protected:
+ // device-level overrides
+ virtual void device_start() override ATTR_COLD;
+ virtual void device_reset() override ATTR_COLD;
+
+ // optional information overrides
+ virtual void device_add_mconfig(machine_config &config) override ATTR_COLD;
+ virtual const tiny_rom_entry *device_rom_region() const override ATTR_COLD;
+
+ private:
+ u8 regs_r(offs_t offset);
+ void regs_w(offs_t offset, u8 data);
+
+ u32 screen_update(screen_device &screen, bitmap_ind16 &bitmap, const rectangle &cliprect);
+
+ void vbl_w(int state);
+
+ required_device<screen_device> m_screen;
+
+ std::unique_ptr<u32[]> m_vram;
+ u16 m_htotal, m_hvis, m_vtotal, m_vvis, m_stride;
+ 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(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);
+}
+
+//-------------------------------------------------
+// rom_region - device-specific ROM region
+//-------------------------------------------------
+
+const tiny_rom_entry *nubus_laserview_device::device_rom_region() const
+{
+ return ROM_NAME( laserview );
+}
+
+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_screen(*this, "screen"),
+ m_htotal(0), m_hvis(0), m_vtotal(0), m_vvis(0),
+ m_vbl_disable(1), m_prot_latch(0)
+{
+}
+
+void nubus_laserview_device::device_start()
+{
+ const u32 slotspace = get_slotspace();
+
+ install_declaration_rom("declrom", true);
+
+ 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, emu::rw_delegate(*this, FUNC(nubus_laserview_device::regs_r)), emu::rw_delegate(*this, FUNC(nubus_laserview_device::regs_w)));
+
+ 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;
+ std::fill_n(&m_vram[0], VRAM_SIZE / sizeof(u32), 0);
+}
+
+u32 nubus_laserview_device::screen_update(screen_device &screen, bitmap_ind16 &bitmap, const rectangle &cliprect)
+{
+ auto const vram8 = util::big_endian_cast<u8 const>(&m_vram[0]);
+ for (int y = 0; y < m_vvis; y++)
+ {
+ u16 *scanline = &bitmap.pix(y);
+ for (int x = 0; x < m_hvis/8; x++)
+ {
+ u8 const pixels = vram8[(y * (m_stride >> 4)) + 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::vbl_w(int state)
+{
+ if ((state) && (!m_vbl_disable))
+ {
+ raise_slot_irq();
+ }
+}
+
+void nubus_laserview_device::regs_w(offs_t offset, u8 data)
+{
+ switch (offset)
+ {
+ case 0x00f9:
+ m_prot_latch = data ^ 0xff;
+ 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;
+ break;
+
+ case 0xffef:
+ if ((data & 0xff) == 0x04)
+ {
+ m_vbl_disable = 0;
+ }
+ else if ((data & 0xff) == 1)
+ {
+ lower_slot_irq();
+ }
+ else
+ {
+ m_vbl_disable = 1;
+ lower_slot_irq();
+ }
+ break;
+
+ default:
+ // the code to set the CRTC params dirties up bits 8-15 of the address, so ignore it
+ switch (offset & 0xff)
+ {
+ case 0x81:
+ m_htotal = (m_htotal & 0xff00) | data;
+ break;
+
+ case 0x83:
+ m_htotal = (m_htotal & 0xff) | (data << 8);
+ break;
+
+ case 0x85:
+ m_hvis = (m_hvis & 0xff00) | data;
+ break;
+
+ case 0x87:
+ m_hvis = (m_hvis & 0xff) | (data << 8);
+ break;
+
+ case 0x89:
+ m_stride = (m_stride & 0xff00) | data;
+ break;
+
+ case 0x8b:
+ m_stride = (m_stride & 0xff) | (data << 8);
+ break;
+
+ case 0x91:
+ m_vtotal = (m_vtotal & 0xff00) | data;
+ break;
+
+ case 0x93:
+ m_vtotal = (m_vtotal & 0xff) | (data << 8);
+ break;
+
+ case 0x95:
+ m_vvis = (m_vvis & 0xff00) | data;
+ break;
+
+ case 0x97:
+ m_vvis = (m_vvis & 0xff) | (data << 8);
+ break;
+ }
+ break;
+ }
+}
+
+u8 nubus_laserview_device::regs_r(offs_t offset)
+{
+ switch (offset)
+ {
+ case 0xff04: // vblank status
+ return m_screen->vblank();
+
+ case 0xff08:
+ return m_prot_latch;
+
+ // monitor sense? DIP switches?
+ case 0xfffc:
+ return 0xe4;
+ }
+
+ 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
new file mode 100644
index 00000000000..22e283c2391
--- /dev/null
+++ b/src/devices/bus/nubus/laserview.h
@@ -0,0 +1,12 @@
+// license:BSD-3-Clause
+// copyright-holders:R. Belmont
+#ifndef MAME_BUS_NUBUS_LASERVIEW_H
+#define MAME_BUS_NUBUS_LASERVIEW_H
+
+#pragma once
+
+#include "nubus.h"
+
+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 9aac443a2c2..bc65103c7e5 100644
--- a/src/devices/bus/nubus/nubus.cpp
+++ b/src/devices/bus/nubus/nubus.cpp
@@ -2,7 +2,7 @@
// copyright-holders:R. Belmont
/***************************************************************************
- nubus.c - NuBus bus and card emulation
+ nubus.cpp - NuBus bus and card emulation
by R. Belmont, based heavily on Miodrag Milanovic's ISA8/16 implementation
@@ -11,6 +11,8 @@
#include "emu.h"
#include "nubus.h"
+#include <algorithm>
+
//**************************************************************************
// GLOBAL VARIABLES
@@ -25,176 +27,218 @@ DEFINE_DEVICE_TYPE(NUBUS_SLOT, nubus_slot_device, "nubus_slot", "NuBus slot")
//-------------------------------------------------
// nubus_slot_device - constructor
//-------------------------------------------------
-nubus_slot_device::nubus_slot_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) :
+nubus_slot_device::nubus_slot_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock) :
nubus_slot_device(mconfig, NUBUS_SLOT, tag, owner, clock)
{
}
-nubus_slot_device::nubus_slot_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock) :
+nubus_slot_device::nubus_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_slot_interface(mconfig, *this),
- m_nubus_tag(nullptr),
+ device_single_card_slot_interface(mconfig, *this),
+ m_nubus(*this, finder_base::DUMMY_TAG),
m_nubus_slottag(nullptr)
{
}
//-------------------------------------------------
-// device_start - device-specific startup
+// device_resolve_objects - resolve objects that
+// may be needed for other devices to set
+// initial conditions at start time
//-------------------------------------------------
-void nubus_slot_device::device_start()
+void nubus_slot_device::device_resolve_objects()
{
- device_nubus_card_interface *dev = dynamic_cast<device_nubus_card_interface *>(get_card_device());
+ device_nubus_card_interface *dev = get_card_device();
- if (dev) dev->set_nubus_tag(m_nubus_tag, m_nubus_slottag);
+ if (dev)
+ {
+ dev->set_nubus_tag(m_nubus.target(), m_nubus_slottag);
+ m_nubus->add_nubus_card(*dev);
+ }
}
-//**************************************************************************
-// GLOBAL VARIABLES
-//**************************************************************************
-
-DEFINE_DEVICE_TYPE(NUBUS, nubus_device, "nubus", "NuBus")
-
-//**************************************************************************
-// LIVE DEVICE
-//**************************************************************************
-
//-------------------------------------------------
-// nubus_device - constructor
+// device_start - device-specific startup
//-------------------------------------------------
-nubus_device::nubus_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) :
+void nubus_slot_device::device_start()
+{
+}
+
+DEFINE_DEVICE_TYPE(NUBUS, nubus_device, "nubus", "NuBus")
+
+nubus_device::nubus_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock) :
nubus_device(mconfig, NUBUS, tag, owner, clock)
{
}
-nubus_device::nubus_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock) :
+nubus_device::nubus_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, u32 clock) :
device_t(mconfig, type, tag, owner, clock),
+ device_memory_interface(mconfig, *this),
m_space(*this, finder_base::DUMMY_TAG, -1),
+ m_mem_config("nubus", ENDIANNESS_BIG, 32, 32),
m_out_irq9_cb(*this),
m_out_irqa_cb(*this),
m_out_irqb_cb(*this),
m_out_irqc_cb(*this),
m_out_irqd_cb(*this),
- m_out_irqe_cb(*this)
+ m_out_irqe_cb(*this),
+ m_bus_mode(nubus_mode_t::NORMAL),
+ 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();
}
-//-------------------------------------------------
-// device_start - device-specific startup
-//-------------------------------------------------
+device_memory_interface::space_config_vector nubus_device::memory_space_config() const
+{
+ return space_config_vector{
+ std::make_pair(AS_DATA, &m_mem_config)};
+}
void nubus_device::device_start()
{
+ switch (m_bus_mode)
+ {
+ case nubus_mode_t::NORMAL:
+ m_space->install_read_handler(0x90000000, 0xefffffff, emu::rw_delegate(*this, FUNC(nubus_device::bus_memory_r<0x90000000>)));
+ m_space->install_write_handler(0x90000000, 0xefffffff, emu::rw_delegate(*this, FUNC(nubus_device::bus_memory_w<0x90000000>)));
+ m_space->install_read_handler(0xf9000000, 0xfeffffff, emu::rw_delegate(*this, FUNC(nubus_device::bus_memory_r<0xf9000000>)));
+ m_space->install_write_handler(0xf9000000, 0xfeffffff, emu::rw_delegate(*this, FUNC(nubus_device::bus_memory_w<0xf9000000>)));
+ break;
+
+ case nubus_mode_t::QUADRA_DAFB:
+ m_space->install_read_handler(0xa0000000, 0xefffffff, emu::rw_delegate(*this, FUNC(nubus_device::bus_memory_r<0x90000000>)));
+ m_space->install_write_handler(0xa0000000, 0xefffffff, emu::rw_delegate(*this, FUNC(nubus_device::bus_memory_w<0x90000000>)));
+ m_space->install_read_handler(0xfa000000, 0xfeffffff, emu::rw_delegate(*this, FUNC(nubus_device::bus_memory_r<0xf9000000>)));
+ m_space->install_write_handler(0xfa000000, 0xfeffffff, emu::rw_delegate(*this, FUNC(nubus_device::bus_memory_w<0xf9000000>)));
+ break;
+
+ case nubus_mode_t::LC_PDS:
+ m_space->install_read_handler(0x80e00000, 0x80ffffff, emu::rw_delegate(*this, FUNC(nubus_device::bus_memory_r<0x80e00000>)));
+ m_space->install_write_handler(0x80e00000, 0x80ffffff, emu::rw_delegate(*this, FUNC(nubus_device::bus_memory_w<0x80e00000>)));
+ m_space->install_read_handler(0x00e00000, 0x00efffff, emu::rw_delegate(*this, FUNC(nubus_device::bus_memory_r<0x80e00000>)));
+ m_space->install_write_handler(0x00e00000, 0x00efffff, emu::rw_delegate(*this, FUNC(nubus_device::bus_memory_w<0x80e00000>)));
+ break;
+
+ case nubus_mode_t::SE30:
+ m_space->install_read_handler(0x90000000, 0xdfffffff, emu::rw_delegate(*this, FUNC(nubus_device::bus_memory_r<0x90000000>)));
+ m_space->install_write_handler(0x90000000, 0xdfffffff, emu::rw_delegate(*this, FUNC(nubus_device::bus_memory_w<0x90000000>)));
+ m_space->install_read_handler(0xf9000000, 0xfdffffff, emu::rw_delegate(*this, FUNC(nubus_device::bus_memory_r<0xf9000000>)));
+ m_space->install_write_handler(0xf9000000, 0xfdffffff, emu::rw_delegate(*this, FUNC(nubus_device::bus_memory_w<0xf9000000>)));
+ break;
+ }
}
-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);
}
-void nubus_device::install_device(offs_t start, offs_t end, read8_delegate rhandler, write8_delegate whandler, uint32_t mask)
+template <u32 Base>
+u32 nubus_device::bus_memory_r(offs_t offset, u32 mem_mask)
{
- int buswidth = m_space->data_width();
- switch(buswidth)
- {
- case 32:
- m_space->install_readwrite_handler(start, end, rhandler, whandler, mask);
- break;
- case 64:
- m_space->install_readwrite_handler(start, end, rhandler, whandler, ((uint64_t)mask<<32)|mask);
- break;
- default:
- fatalerror("NUBUS: Bus width %d not supported\n", buswidth);
- }
+ return this->space(AS_DATA).read_dword(Base + (offset * 4), mem_mask);
}
-void nubus_device::install_device(offs_t start, offs_t end, read16_delegate rhandler, write16_delegate whandler, uint32_t mask)
+template <u32 Base>
+void nubus_device::bus_memory_w(offs_t offset, u32 data, u32 mem_mask)
{
- int buswidth = m_space->data_width();
- switch(buswidth)
- {
- case 32:
- m_space->install_readwrite_handler(start, end, rhandler, whandler, mask);
- break;
- case 64:
- m_space->install_readwrite_handler(start, end, rhandler, whandler, ((uint64_t)mask<<32)|mask);
- break;
- default:
- fatalerror("NUBUS: Bus width %d not supported\n", buswidth);
- }
+ this->space(AS_DATA).write_dword(Base + (offset * 4), data, mem_mask);
}
-void nubus_device::install_device(offs_t start, offs_t end, read32_delegate rhandler, write32_delegate whandler, uint32_t mask)
+template u32 nubus_device::bus_memory_r<0x90000000>(offs_t offset, u32 mem_mask);
+template void nubus_device::bus_memory_w<0x90000000>(offs_t offset, u32 data, u32 mem_mask);
+template u32 nubus_device::bus_memory_r<0xf9000000>(offs_t offset, u32 mem_mask);
+template void nubus_device::bus_memory_w<0xf9000000>(offs_t offset, u32 data, u32 mem_mask);
+
+template u32 nubus_device::bus_memory_r<0xa0000000>(offs_t offset, u32 mem_mask);
+template void nubus_device::bus_memory_w<0xa0000000>(offs_t offset, u32 data, u32 mem_mask);
+template u32 nubus_device::bus_memory_r<0xfa000000>(offs_t offset, u32 mem_mask);
+template void nubus_device::bus_memory_w<0xfa000000>(offs_t offset, u32 data, u32 mem_mask);
+
+template u32 nubus_device::bus_memory_r<0x00e00000>(offs_t offset, u32 mem_mask);
+template void nubus_device::bus_memory_w<0x00e00000>(offs_t offset, u32 data, u32 mem_mask);
+template u32 nubus_device::bus_memory_r<0x80e00000>(offs_t offset, u32 mem_mask);
+template void nubus_device::bus_memory_w<0x80e00000>(offs_t offset, u32 data, u32 mem_mask);
+
+template <typename R, typename W>
+void nubus_device::install_device(offs_t start, offs_t end, R rhandler, W whandler, u32 mask)
{
- int buswidth = m_space->data_width();
- switch(buswidth)
- {
- case 32:
- m_space->install_readwrite_handler(start, end, rhandler, whandler, mask);
- break;
- case 64:
- m_space->install_readwrite_handler(start, end, rhandler, whandler, ((uint64_t)mask<<32)|mask);
- break;
- default:
- fatalerror("NUBUS: Bus width %d not supported\n", buswidth);
- }
+ start &= m_addr_mask;
+ end &= m_addr_mask;
+ space(AS_DATA).install_readwrite_handler(start, end, rhandler, whandler, mask);
}
-void nubus_device::install_readonly_device(offs_t start, offs_t end, read32_delegate rhandler, uint32_t mask)
+template void nubus_device::install_device<read8_delegate, write8_delegate >(offs_t start, offs_t end, read8_delegate rhandler, write8_delegate whandler, u32 mask);
+template void nubus_device::install_device<read8s_delegate, write8s_delegate >(offs_t start, offs_t end, read8s_delegate rhandler, write8s_delegate whandler, u32 mask);
+template void nubus_device::install_device<read8sm_delegate, write8sm_delegate >(offs_t start, offs_t end, read8sm_delegate rhandler, write8sm_delegate whandler, u32 mask);
+template void nubus_device::install_device<read8smo_delegate, write8smo_delegate >(offs_t start, offs_t end, read8smo_delegate rhandler, write8smo_delegate whandler, u32 mask);
+template void nubus_device::install_device<read16_delegate, write16_delegate >(offs_t start, offs_t end, read16_delegate rhandler, write16_delegate whandler, u32 mask);
+template void nubus_device::install_device<read16s_delegate, write16s_delegate >(offs_t start, offs_t end, read16s_delegate rhandler, write16s_delegate whandler, u32 mask);
+template void nubus_device::install_device<read16sm_delegate, write16sm_delegate >(offs_t start, offs_t end, read16sm_delegate rhandler, write16sm_delegate whandler, u32 mask);
+template void nubus_device::install_device<read16smo_delegate, write16smo_delegate>(offs_t start, offs_t end, read16smo_delegate rhandler, write16smo_delegate whandler, u32 mask);
+template void nubus_device::install_device<read32_delegate, write32_delegate >(offs_t start, offs_t end, read32_delegate rhandler, write32_delegate whandler, u32 mask);
+template void nubus_device::install_device<read32s_delegate, write32s_delegate >(offs_t start, offs_t end, read32s_delegate rhandler, write32s_delegate whandler, u32 mask);
+template void nubus_device::install_device<read32sm_delegate, write32sm_delegate >(offs_t start, offs_t end, read32sm_delegate rhandler, write32sm_delegate whandler, u32 mask);
+template void nubus_device::install_device<read32smo_delegate, write32smo_delegate>(offs_t start, offs_t end, read32smo_delegate rhandler, write32smo_delegate whandler, u32 mask);
+
+template <typename R>
+void nubus_device::install_readonly_device(offs_t start, offs_t end, R rhandler, u32 mask)
{
- int buswidth = m_space->data_width();
- switch(buswidth)
- {
- case 32:
- m_space->install_read_handler(start, end, rhandler, mask);
- break;
- case 64:
- m_space->install_read_handler(start, end, rhandler, ((uint64_t)mask<<32)|mask);
- break;
- default:
- fatalerror("NUBUS: Bus width %d not supported\n", buswidth);
- }
+ start &= m_addr_mask;
+ end &= m_addr_mask;
+ space(AS_DATA).install_read_handler(start, end, rhandler, mask);
}
-void nubus_device::install_writeonly_device(offs_t start, offs_t end, write32_delegate whandler, uint32_t mask)
+template void nubus_device::install_readonly_device<read8_delegate >(offs_t start, offs_t end, read8_delegate rhandler, u32 mask);
+template void nubus_device::install_readonly_device<read8s_delegate >(offs_t start, offs_t end, read8s_delegate rhandler, u32 mask);
+template void nubus_device::install_readonly_device<read8sm_delegate >(offs_t start, offs_t end, read8sm_delegate rhandler, u32 mask);
+template void nubus_device::install_readonly_device<read8smo_delegate >(offs_t start, offs_t end, read8smo_delegate rhandler, u32 mask);
+template void nubus_device::install_readonly_device<read16_delegate >(offs_t start, offs_t end, read16_delegate rhandler, u32 mask);
+template void nubus_device::install_readonly_device<read16s_delegate >(offs_t start, offs_t end, read16s_delegate rhandler, u32 mask);
+template void nubus_device::install_readonly_device<read16sm_delegate >(offs_t start, offs_t end, read16sm_delegate rhandler, u32 mask);
+template void nubus_device::install_readonly_device<read16smo_delegate>(offs_t start, offs_t end, read16smo_delegate rhandler, u32 mask);
+template void nubus_device::install_readonly_device<read32_delegate >(offs_t start, offs_t end, read32_delegate rhandler, u32 mask);
+template void nubus_device::install_readonly_device<read32s_delegate >(offs_t start, offs_t end, read32s_delegate rhandler, u32 mask);
+template void nubus_device::install_readonly_device<read32sm_delegate >(offs_t start, offs_t end, read32sm_delegate rhandler, u32 mask);
+template void nubus_device::install_readonly_device<read32smo_delegate>(offs_t start, offs_t end, read32smo_delegate rhandler, u32 mask);
+
+template <typename W>
+void nubus_device::install_writeonly_device(offs_t start, offs_t end, W whandler, u32 mask)
{
- int buswidth = m_space->data_width();
- switch(buswidth)
- {
- case 32:
- m_space->install_write_handler(start, end, whandler, mask);
- break;
- case 64:
- m_space->install_write_handler(start, end, whandler, ((uint64_t)mask<<32)|mask);
- break;
- default:
- fatalerror("NUBUS: Bus width %d not supported\n", buswidth);
- }
+ start &= m_addr_mask;
+ end &= m_addr_mask;
+ space(AS_DATA).install_write_handler(start, end, whandler, mask);
+}
+
+template void nubus_device::install_writeonly_device<write8_delegate >(offs_t start, offs_t end, write8_delegate whandler, u32 mask);
+template void nubus_device::install_writeonly_device<write8s_delegate >(offs_t start, offs_t end, write8s_delegate whandler, u32 mask);
+template void nubus_device::install_writeonly_device<write8sm_delegate >(offs_t start, offs_t end, write8sm_delegate whandler, u32 mask);
+template void nubus_device::install_writeonly_device<write8smo_delegate >(offs_t start, offs_t end, write8smo_delegate whandler, u32 mask);
+template void nubus_device::install_writeonly_device<write16_delegate >(offs_t start, offs_t end, write16_delegate whandler, u32 mask);
+template void nubus_device::install_writeonly_device<write16s_delegate >(offs_t start, offs_t end, write16s_delegate whandler, u32 mask);
+template void nubus_device::install_writeonly_device<write16sm_delegate >(offs_t start, offs_t end, write16sm_delegate whandler, u32 mask);
+template void nubus_device::install_writeonly_device<write16smo_delegate>(offs_t start, offs_t end, write16smo_delegate whandler, u32 mask);
+template void nubus_device::install_writeonly_device<write32_delegate >(offs_t start, offs_t end, write32_delegate whandler, u32 mask);
+template void nubus_device::install_writeonly_device<write32s_delegate >(offs_t start, offs_t end, write32s_delegate whandler, u32 mask);
+template void nubus_device::install_writeonly_device<write32sm_delegate >(offs_t start, offs_t end, write32sm_delegate whandler, u32 mask);
+template void nubus_device::install_writeonly_device<write32smo_delegate>(offs_t start, offs_t end, write32smo_delegate whandler, u32 mask);
+
+void nubus_device::install_bank(offs_t start, offs_t end, void *data)
+{
+ start &= m_addr_mask;
+ end &= m_addr_mask;
+ space(AS_DATA).install_ram(start, end, data);
}
-void nubus_device::install_bank(offs_t start, offs_t end, const char *tag, uint8_t *data)
+void nubus_device::install_view(offs_t start, offs_t end, memory_view &view)
{
-// printf("install_bank: %s @ %x->%x\n", tag, start, end);
- m_space->install_readwrite_bank(start, end, 0, tag);
- machine().root_device().membank(siblingtag(tag).c_str())->set_base(data);
+ start &= m_addr_mask;
+ end &= m_addr_mask;
+ space(AS_DATA).install_view(start, end, view);
}
void nubus_device::set_irq_line(int slot, int state)
@@ -211,12 +255,14 @@ 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); }
+
+DEFINE_DEVICE_TYPE(MACSE30_PDS_BUS, se30_pds_bus_device, "se30bus", "Mac SE/30 expansion bus");
//**************************************************************************
// DEVICE CONFIG NUBUS CARD INTERFACE
@@ -231,10 +277,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_slot_card_interface(mconfig, device),
- m_nubus(nullptr),
- m_nubus_tag(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)
{
}
@@ -249,86 +296,69 @@ device_nubus_card_interface::~device_nubus_card_interface()
void device_nubus_card_interface::interface_pre_start()
{
- if (!m_nubus)
+ if ((!strncmp(m_nubus_slottag, "pds030", 6)) || (!strncmp(m_nubus_slottag, "siexp", 5)))
{
- if (!strncmp(m_nubus_slottag, "pds030", 6))
- {
- m_slot = 0x9; // '030 PDS slots phantom slot as NuBus slots $9, $A, and $B
- }
- else if (!strncmp(m_nubus_slottag, "lcpds", 6))
- {
- m_slot = 0xe; // LC PDS slots phantom slot as NuBus slot $E
- }
- else
- {
- // extract the slot number from the last digit of the slot tag
- int tlen = strlen(m_nubus_slottag);
-
- if (m_nubus_slottag[tlen-1] == '9')
- {
- m_slot = (m_nubus_slottag[tlen-1] - '9') + 9;
- }
- else
- {
- m_slot = (m_nubus_slottag[tlen-1] - 'a') + 0xa;
- }
- }
+ 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 phantom slots as slot $E in most cases
+ }
+ else
+ {
+ // extract the slot number from the last digit of the slot tag
+ int tlen = strlen(m_nubus_slottag);
- if (m_slot < 9 || m_slot > 0xe)
+ if (m_nubus_slottag[tlen-1] == '9')
{
- fatalerror("Slot %x out of range for Apple NuBus\n", m_slot);
+ m_slot = (m_nubus_slottag[tlen-1] - '9') + 9;
}
-
- device_t *const bus = device().machine().device(m_nubus_tag);
- if (!bus)
+ else
{
- fatalerror("Can't find NuBus device %s\n", m_nubus_tag);
+ m_slot = (m_nubus_slottag[tlen-1] - 'a') + 0xa;
}
+ }
- m_nubus = dynamic_cast<nubus_device *>(bus);
- if (!m_nubus)
- {
- fatalerror("Device %s (%s) is not an instance of nubus_device\n", bus->tag(), bus->name());
- }
+ if (m_slot < 9 || m_slot > 0xe)
+ {
+ fatalerror("Slot %x out of range for Apple NuBus\n", m_slot);
+ }
- nubus().add_nubus_card(this);
+ if (!m_nubus)
+ {
+ fatalerror("Can't find NuBus device\n");
}
}
-void device_nubus_card_interface::install_bank(offs_t start, offs_t end, const char *tag, uint8_t *data)
+void device_nubus_card_interface::install_bank(offs_t start, offs_t end, void *data)
{
- char bank[256];
-
- // append an underscore and the slot name to the bank so it's guaranteed unique
- snprintf(bank, sizeof(bank), "%s_%s", tag, m_nubus_slottag);
+ nubus().install_bank(start, end, data);
+}
- nubus().install_bank(start, end, bank, data);
+void device_nubus_card_interface::install_view(offs_t start, offs_t end, memory_view &view)
+{
+ nubus().install_view(start, end, view);
}
-void device_nubus_card_interface::install_declaration_rom(device_t *dev, const char *romregion, bool mirror_all_mb, bool reverse_rom)
+void device_nubus_card_interface::install_declaration_rom(const char *romregion, bool mirror_all_mb, bool reverse_rom)
{
bool inverted = false;
- uint8_t *rom = device().machine().root_device().memregion(dev->subtag(romregion).c_str())->base();
- uint32_t romlen = device().machine().root_device().memregion(dev->subtag(romregion).c_str())->bytes();
+ u8 *rom = device().memregion(romregion)->base();
+ u32 romlen = device().memregion(romregion)->bytes();
// printf("ROM length is %x, last bytes are %02x %02x\n", romlen, rom[romlen-2], rom[romlen-1]);
if (reverse_rom)
{
- uint8_t temp;
- uint32_t endptr = romlen-1;
-
- for (uint32_t idx = 0; idx < romlen / 2; idx++)
+ for (u32 idx = 0, endptr = romlen-1; idx < endptr; idx++, endptr--)
{
- temp = rom[idx];
- rom[idx] = rom[endptr];
- rom[endptr] = temp;
- endptr--;
+ using std::swap;
+ swap(rom[idx], rom[endptr]);
}
}
- uint8_t byteLanes = rom[romlen-1];
+ u8 byteLanes = rom[romlen-1];
// check if all bits are inverted
if (rom[romlen-2] == 0xff)
{
@@ -336,13 +366,6 @@ void device_nubus_card_interface::install_declaration_rom(device_t *dev, const c
inverted = true;
}
- #if 0
- FILE *f;
- f = fopen("romout.bin", "wb");
- fwrite(rom, romlen, 1, f);
- fclose(f);
- #endif
-
switch (byteLanes)
{
case 0x0f: // easy case: all 4 lanes (still must scramble for 32-bit BE bus though)
@@ -354,8 +377,8 @@ void device_nubus_card_interface::install_declaration_rom(device_t *dev, const c
break;
case 0xe1: // lane 0 only
- m_declaration_rom.resize(romlen*4);
- memset(&m_declaration_rom[0], 0, romlen*4);
+ m_declaration_rom.resize(romlen * 4);
+ std::fill_n(&m_declaration_rom[0], romlen * 4, 0);
for (int i = 0; i < romlen; i++)
{
m_declaration_rom[BYTE4_XOR_BE(i*4)] = rom[i];
@@ -364,8 +387,8 @@ void device_nubus_card_interface::install_declaration_rom(device_t *dev, const c
break;
case 0xd2: // lane 1 only
- m_declaration_rom.resize(romlen*4);
- memset(&m_declaration_rom[0], 0, romlen*4);
+ m_declaration_rom.resize(romlen * 4);
+ std::fill_n(&m_declaration_rom[0], romlen * 4, 0);
for (int i = 0; i < romlen; i++)
{
m_declaration_rom[BYTE4_XOR_BE((i*4)+1)] = rom[i];
@@ -374,8 +397,8 @@ void device_nubus_card_interface::install_declaration_rom(device_t *dev, const c
break;
case 0xb4: // lane 2 only
- m_declaration_rom.resize(romlen*4);
- memset(&m_declaration_rom[0], 0, romlen*4);
+ m_declaration_rom.resize(romlen * 4);
+ std::fill_n(&m_declaration_rom[0], romlen * 4, 0);
for (int i = 0; i < romlen; i++)
{
m_declaration_rom[BYTE4_XOR_BE((i*4)+2)] = rom[i];
@@ -384,8 +407,8 @@ void device_nubus_card_interface::install_declaration_rom(device_t *dev, const c
break;
case 0x78: // lane 3 only
- m_declaration_rom.resize(romlen*4);
- memset(&m_declaration_rom[0], 0, romlen*4);
+ m_declaration_rom.resize(romlen * 4);
+ std::fill_n(&m_declaration_rom[0], romlen * 4, 0);
for (int i = 0; i < romlen; i++)
{
m_declaration_rom[BYTE4_XOR_BE((i*4)+3)] = rom[i];
@@ -394,9 +417,9 @@ void device_nubus_card_interface::install_declaration_rom(device_t *dev, const c
break;
case 0xc3: // lanes 0, 1
- m_declaration_rom.resize(romlen*2);
- memset(&m_declaration_rom[0], 0, romlen*2);
- for (int i = 0; i < romlen/2; i++)
+ m_declaration_rom.resize(romlen * 2);
+ std::fill_n(&m_declaration_rom[0], romlen * 2, 0);
+ for (int i = 0; i < romlen / 2; i++)
{
m_declaration_rom[BYTE4_XOR_BE((i*4)+0)] = rom[(i*2)];
m_declaration_rom[BYTE4_XOR_BE((i*4)+1)] = rom[(i*2)+1];
@@ -405,8 +428,8 @@ void device_nubus_card_interface::install_declaration_rom(device_t *dev, const c
break;
case 0xa5: // lanes 0, 2
- m_declaration_rom.resize(romlen*2);
- memset(&m_declaration_rom[0], 0, romlen*2);
+ m_declaration_rom.resize(romlen * 2);
+ std::fill_n(&m_declaration_rom[0], romlen * 2, 0);
for (int i = 0; i < romlen/2; i++)
{
m_declaration_rom[BYTE4_XOR_BE((i*4)+0)] = rom[(i*2)];
@@ -416,8 +439,8 @@ void device_nubus_card_interface::install_declaration_rom(device_t *dev, const c
break;
case 0x3c: // lanes 2,3
- m_declaration_rom.resize(romlen*2);
- memset(&m_declaration_rom[0], 0, romlen*2);
+ m_declaration_rom.resize(romlen * 2);
+ std::fill_n(&m_declaration_rom[0], romlen * 2, 0);
for (int i = 0; i < romlen/2; i++)
{
m_declaration_rom[BYTE4_XOR_BE((i*4)+2)] = rom[(i*2)];
@@ -427,7 +450,7 @@ void device_nubus_card_interface::install_declaration_rom(device_t *dev, const c
break;
default:
- fatalerror("NuBus: unhandled byteLanes value %02x\n", byteLanes);
+ fatalerror("nubus: unhandled byteLanes value %02x\n", byteLanes);
}
// the slot manager can supposedly handle inverted ROMs by itself, but let's do it for it anyway
@@ -440,21 +463,18 @@ void device_nubus_card_interface::install_declaration_rom(device_t *dev, const c
}
// now install the ROM
- uint32_t addr = get_slotspace() + 0x01000000;
- char bankname[128];
- snprintf(bankname, sizeof(bankname), "rom_%s", m_nubus_slottag);
+ u32 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;
+ u32 off = 0;
while(off < 0x1000000) {
- nubus().install_bank(addr + off, addr+off+romlen-1, bankname, &m_declaration_rom[0]);
+ nubus().install_bank(addr + off, addr+off+romlen-1, &m_declaration_rom[0]);
off += romlen;
}
}
else
{
- nubus().install_bank(addr, addr+romlen-1, bankname, &m_declaration_rom[0]);
+ nubus().install_bank(addr, addr+romlen-1, &m_declaration_rom[0]);
}
}
diff --git a/src/devices/bus/nubus/nubus.h b/src/devices/bus/nubus/nubus.h
index a1b9496fcf8..75f8e899cf7 100644
--- a/src/devices/bus/nubus/nubus.h
+++ b/src/devices/bus/nubus/nubus.h
@@ -13,6 +13,12 @@
#pragma once
+#include "screen.h"
+
+#include <functional>
+#include <utility>
+#include <vector>
+
//**************************************************************************
// TYPE DEFINITIONS
@@ -20,32 +26,79 @@
class nubus_device;
-class nubus_slot_device : public device_t, public device_slot_interface
+// ======================> device_nubus_card_interface
+
+// class representing interface-specific live nubus card
+class device_nubus_card_interface : public device_interface
{
+ friend class nubus_device;
public:
// construction/destruction
- template <typename T>
- nubus_slot_device(const machine_config &mconfig, const char *tag, device_t *owner, const char *nbtag, T &&opts, const char *dflt)
- : nubus_slot_device(mconfig, tag, owner, (uint32_t)0)
+ virtual ~device_nubus_card_interface();
+
+ // 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);
+ void install_view(offs_t start, offs_t end, memory_view &view);
+
+ u32 get_slotspace() { return 0xf0000000 | (m_slot<<24); }
+ u32 get_super_slotspace() { return m_slot<<28; }
+
+ 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; }
+
+protected:
+ device_nubus_card_interface(const machine_config &mconfig, device_t &device);
+ virtual void interface_pre_start() override;
+
+ int slotno() const { assert(m_nubus); return m_slot; }
+ nubus_device &nubus() { assert(m_nubus); return *m_nubus; }
+
+private:
+ nubus_device *m_nubus;
+ const char *m_nubus_slottag;
+ int m_slot;
+ std::vector<u8> m_declaration_rom;
+};
+class nubus_slot_device : public device_t, public device_single_card_slot_interface<device_nubus_card_interface>
+{
+public:
+ // construction/destruction
+ template <typename T, typename U>
+ nubus_slot_device(const machine_config &mconfig, T &&tag, device_t *owner, const char *nbtag, U &&opts, const char *dflt)
+ : nubus_slot_device(mconfig, tag, owner, (u32)0)
{
option_reset();
opts(*this);
set_default_option(dflt);
- set_nubus_slot(nbtag, tag);
+ set_nubus_slot(std::forward<T>(nbtag), tag);
}
- nubus_slot_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
+ nubus_slot_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock);
// inline configuration
- void set_nubus_slot(const char *tag, const char *slottag) { m_nubus_tag = tag; m_nubus_slottag = slottag; }
+ template <typename T>
+ void set_nubus_slot(T &&tag, const char *slottag)
+ {
+ m_nubus.set_tag(std::forward<T>(tag));
+ m_nubus_slottag = slottag;
+ }
+
protected:
- nubus_slot_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock);
+ nubus_slot_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, u32 clock);
- // device-level overrides
- virtual void device_start() override;
+ // device_t implementation
+ virtual void device_resolve_objects() override ATTR_COLD;
+ virtual void device_start() override ATTR_COLD;
// configuration
- const char *m_nubus_tag, *m_nubus_slottag;
+ required_device<nubus_device> m_nubus;
+ const char *m_nubus_slottag;
};
// device type definition
@@ -54,12 +107,12 @@ DECLARE_DEVICE_TYPE(NUBUS_SLOT, nubus_slot_device)
class device_nubus_card_interface;
// ======================> nubus_device
-class nubus_device : public device_t
+class nubus_device : public device_t, public device_memory_interface
{
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(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock);
+ ~nubus_device();
// inline configuration
template <typename T> void set_space(T &&tag, int spacenum) { m_space.set_tag(std::forward<T>(tag), spacenum); }
@@ -70,32 +123,68 @@ 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 install_device(offs_t start, offs_t end, read8_delegate rhandler, write8_delegate whandler, uint32_t mask=0xffffffff);
- void install_device(offs_t start, offs_t end, read16_delegate rhandler, write16_delegate whandler, uint32_t mask=0xffffffff);
- void install_device(offs_t start, offs_t end, read32_delegate rhandler, write32_delegate whandler, uint32_t mask=0xffffffff);
- void install_readonly_device(offs_t start, offs_t end, read32_delegate rhandler, uint32_t mask=0xffffffff);
- void install_writeonly_device(offs_t start, offs_t end, write32_delegate whandler, uint32_t mask=0xffffffff);
- void install_bank(offs_t start, offs_t end, const char *tag, uint8_t *data);
+ typedef enum NUBUS_MODE_T
+ {
+ NORMAL = 0,
+ QUADRA_DAFB, // omits slot 9 space
+ LC_PDS, // takes slot $E space only, with A31 in both states, for V8 based systems
+ SE30 // omits slot $E space for SE/30 internal video
+ } nubus_mode_t;
+ void set_bus_mode(nubus_mode_t newMode) { m_bus_mode = newMode; }
+
+ 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, u32 mask=0xffffffff);
+ template <typename R> void install_readonly_device(offs_t start, offs_t end, R rhandler, u32 mask=0xffffffff);
+ template <typename W> void install_writeonly_device(offs_t start, offs_t end, W whandler, u32 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);
+
+ /// \brief Installs a map for the slot's 16 MiB slot space, $Fs00'0000-$FsFF'FFFF
+ template <typename T>
+ void install_map(T &device, void (T::*map)(address_map &map))
+ {
+ const offs_t start = device.get_slotspace();
+ const offs_t end = (start + 0x01000000) - 1;
+
+ space(AS_DATA).install_device(start, end, device, map);
+ }
+
+ /// \brief Installs a map for the slot's 256 MiB super slot space, $s000'0000-$sFFF'FFFF
+ template <typename T>
+ void install_super_map(T &device, void (T::*map)(address_map &map))
+ {
+ const offs_t start = device.get_super_slotspace();
+ const offs_t end = (start + 0x10000000) - 1;
+
+ space(AS_DATA).install_device(start, end, device, map);
+ }
+
void set_irq_line(int slot, int state);
+ void set_address_mask(u32 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);
+ nubus_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, u32 clock);
+
+ // device_t implementation
+ virtual void device_start() override ATTR_COLD;
+
+ virtual space_config_vector memory_space_config() const override;
- // device-level overrides
- virtual void device_resolve_objects() override;
- virtual void device_start() override;
+ template <u32 Base> u32 bus_memory_r(offs_t offset, u32 mem_mask);
+ template <u32 Base> void bus_memory_w(offs_t offset, u32 data, u32 mem_mask);
// internal state
required_address_space m_space;
+ address_space_config m_mem_config;
+
devcb_write_line m_out_irq9_cb;
devcb_write_line m_out_irqa_cb;
devcb_write_line m_out_irqb_cb;
@@ -103,54 +192,40 @@ 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;
+
+ nubus_mode_t m_bus_mode;
+ u32 m_addr_mask;
};
+inline void device_nubus_card_interface::raise_slot_irq()
+{
+ nubus().set_irq_line(m_slot, ASSERT_LINE);
+}
+
+inline void device_nubus_card_interface::lower_slot_irq()
+{
+ nubus().set_irq_line(m_slot, CLEAR_LINE);
+}
// device type definition
DECLARE_DEVICE_TYPE(NUBUS, nubus_device)
-// ======================> device_nubus_card_interface
-
-// class representing interface-specific live nubus card
-class device_nubus_card_interface : public device_slot_card_interface
+DECLARE_DEVICE_TYPE(MACSE30_PDS_BUS, se30_pds_bus_device);
+class se30_pds_bus_device: public nubus_device
{
- 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(device_t *dev, const char *romregion, bool mirror_all_mb = false, bool reverse_rom = false);
- void install_bank(offs_t start, offs_t end, const char *tag, uint8_t *data);
-
- uint32_t get_slotspace() { return 0xf0000000 | (m_slot<<24); }
- uint32_t get_super_slotspace() { return m_slot<<28; }
-
- void raise_slot_irq() { nubus().set_irq_line(m_slot, ASSERT_LINE); }
- void lower_slot_irq() { nubus().set_irq_line(m_slot, CLEAR_LINE); }
-
- // inline configuration
- void set_nubus_tag(const char *tag, const char *slottag) { m_nubus_tag = tag; m_nubus_slottag = slottag; }
-
-protected:
- device_nubus_card_interface(const machine_config &mconfig, device_t &device);
- virtual void interface_pre_start() override;
+ se30_pds_bus_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock)
+ : nubus_device(mconfig, MACSE30_PDS_BUS, tag, owner, clock),
+ m_internal_screen(*this, finder_base::DUMMY_TAG)
+ {
+ m_bus_mode = SE30;
+ }
- int slotno() const { assert(m_nubus); return m_slot; }
- nubus_device &nubus() { assert(m_nubus); return *m_nubus; }
+ template <typename... T>
+ void set_screen_tag(T &&...args) { m_internal_screen.set_tag(std::forward<T>(args)...); }
-private:
- nubus_device *m_nubus;
- const char *m_nubus_tag, *m_nubus_slottag;
- int m_slot;
- std::vector<uint8_t> m_declaration_rom;
- device_nubus_card_interface *m_next;
+ required_device<screen_device> m_internal_screen;
};
#endif // MAME_BUS_NUBUS_NUBUS_H
diff --git a/src/devices/bus/nubus/nubus_48gc.cpp b/src/devices/bus/nubus/nubus_48gc.cpp
index 86f4fca21ec..3175b6d5e04 100644
--- a/src/devices/bus/nubus/nubus_48gc.cpp
+++ b/src/devices/bus/nubus/nubus_48gc.cpp
@@ -1,22 +1,233 @@
// license:BSD-3-Clause
-// copyright-holders:R. Belmont
+// copyright-holders:R. Belmont, Vas Crabb
/***************************************************************************
- Apple 4*8 Graphics Card (model 630-0400) emulation
- Apple 8*24 Graphics Card emulation (cards have the same framebuffer chip
- w/different ROMs and RAMDACs, apparently)
+ Apple Macintosh Display Card 4•8 (MDC 1.0.1, model 630-0400)
+ Apple Macintosh Display Card 8•24 (MDC 1.2)
+
+ Cards have the same framebuffer, CRTC, clock synthesizer, and RAMDAC,
+ but use different ROMs and support different monitor profiles.
+
+ When 1 MB VRAM is installed, 24-bit direct color is available at up
+ to 640×480 resolution, 8-bit indexed color is available at all
+ supported resolutions, and 1:2:1 convolution is used for interlaced
+ modes with indexed color. When 512 kB VRAM is installed, 8-bit
+ indexed color is available at up to 640×480 resolution, 4-bit indexed
+ color is available at all supported resolutions, and 1:2:1
+ convolution will not be used.
+
+ Monitor type changes take effect on had reset. MDC 1.2 defaults to
+ the “Page-White Gamma” profile for the 21" and 16" color monitors,
+ which affects white balance. Use the Monitors control panel to switch
+ to the “Uncorrected Gamma” profile if you don’t like it.
+
+ System 6 will hang on start if 1 MB VRAM is installed, a PAL monitor
+ or encoder is connected, and the card has not been set up. To avoid
+ this, start the system with a different monitor connected, use the
+ Monitors control panel to select a color mode and resolution, and shut
+ down the system cleanly. After this, a PAL monitor or encoder can be
+ connected. System 7 does not suffer from this issue.
+
+ The CRTC counts half-lines vertically, which doesn’t integrate very
+ well with MAME’s screen device. The screen device also lacks any
+ support for interlaced modes. To make interlaced modes usable, a few
+ simplifying assumptions are made:
+ * Assume the framebuffer controller’s interlaced mode will be set when
+ when CRTC is configured for interlaced modes (and vice versa).
+ * Assume NTSC-like structure where frame starts with even field where
+ vertical sync coincides with horizontal sync.
+ * Assume the framebuffer controller and RAMDAC are configured for the
+ same pixel format.
+
+ TODO:
+ * Precise interrupt timing.
+ * Precise timing for odd field flag.
+ * Remaining CRTC registers.
+ * Interlaced modes.
***************************************************************************/
#include "emu.h"
#include "nubus_48gc.h"
+
+#include "layout/generic.h"
#include "screen.h"
-#define VRAM_SIZE (0x200000) // 2 megs, maxed out
+#include <algorithm>
+
+#define LOG_CRTC (1U << 1)
+#define LOG_RAMDAC (1U << 2)
+#define LOG_CLUT (1U << 3)
+#define LOG_CLKGEN (1U << 4)
+
+//#define VERBOSE (LOG_GENERAL | LOG_CRTC | LOG_RAMDAC | LOG_CLKGEN)
+//#define LOG_OUTPUT_FUNC osd_printf_error
+#include "logmacro.h"
-#define GC48_SCREEN_NAME "48gc_screen"
+#define LOGCRTC(...) LOGMASKED(LOG_CRTC, __VA_ARGS__)
+#define LOGRAMDAC(...) LOGMASKED(LOG_RAMDAC, __VA_ARGS__)
+#define LOGCLUT(...) LOGMASKED(LOG_CLUT, __VA_ARGS__)
+#define LOGCLKGEN(...) LOGMASKED(LOG_CLKGEN, __VA_ARGS__)
+
+
+#define GC48_SCREEN_NAME "screen"
#define GC48_ROM_REGION "48gc_rom"
+namespace {
+
+//**************************************************************************
+// TYPE DEFINITIONS
+//**************************************************************************
+
+// ======================> jmfb_device
+
+class jmfb_device :
+ public device_t,
+ public device_nubus_card_interface,
+ public device_video_interface,
+ public device_palette_interface
+{
+protected:
+ // construction/destruction
+ jmfb_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, u32 clock);
+
+ // 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_palette_interface implementation
+ u32 palette_entries() const noexcept override;
+
+ // memory map
+ void card_map(address_map &map);
+
+private:
+ static constexpr offs_t VRAM_MAX = 0x10'0000 / 4; // chip supports 2M but card can only use 1M
+
+ TIMER_CALLBACK_MEMBER(vbl_start);
+ void set_vbl_timer();
+
+ u32 screen_update(screen_device &screen, bitmap_rgb32 &bitmap, const rectangle &cliprect);
+ template <u8 Mode>
+ void update_screen(screen_device &screen, bitmap_rgb32 &bitmap, const rectangle &cliprect);
+ template <u8 Mode, bool Convolution, bool Mono>
+ void update_screen(screen_device &screen, bitmap_rgb32 &bitmap, const rectangle &cliprect);
+ void update_crtc();
+
+ u32 jmfb_r(offs_t offset);
+ u32 crtc_r(offs_t offset);
+ u32 ramdac_r(offs_t offset);
+ void jmfb_w(offs_t offset, u32 data);
+ void crtc_w(offs_t offset, u32 data);
+ void ramdac_w(offs_t offset, u32 data);
+ void clkgen_w(offs_t offset, u32 data);
+
+ u32 rgb_unpack(offs_t offset, u32 mem_mask = ~0);
+ void rgb_pack(offs_t offset, u32 data, u32 mem_mask = ~0);
+
+ bool ctrl_sense2() const { return BIT(m_control, 11); }
+ bool ctrl_sense1() const { return BIT(m_control, 10); }
+ bool ctrl_sense0() const { return BIT(m_control, 9); }
+ bool ctrl_transfer() const { return BIT(m_control, 6); }
+ bool ctrl_convolution() const { return BIT(m_control, 5); }
+ bool ctrl_interlace() const { return BIT(m_control, 4); }
+ bool ctrl_rgb() const { return BIT(m_control, 2); }
+
+ required_ioport m_config;
+ memory_view m_vram_view;
+ emu_timer *m_timer;
+
+ bool m_configured;
+ bool m_clut_addr_read;
+ u8 m_monitor_type;
+
+ std::unique_ptr<u32 []> m_vram;
+ u16 m_control;
+ u16 m_preload;
+ u32 m_base, m_stride;
+
+ u8 m_colors[3], m_clutcnt, m_clutoffs;
+ u8 m_ramdac_mode, m_ramdac_conv;
+
+ u16 m_hhalf, m_hactive, m_hbporch, m_hsync, m_hfporch;
+ u16 m_vactive, m_vbporch, m_vsync, m_vfporch;
+ u32 m_vbl_disable;
+ u16 m_halfline_pixels;
+
+ u16 m_multiplier;
+ u16 m_modulus;
+ u8 m_pdiv;
+};
+
+class nubus_48gc_device : public jmfb_device
+{
+public:
+ nubus_48gc_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 ATTR_COLD;
+ virtual ioport_constructor device_input_ports() const override ATTR_COLD;
+
+private:
+ void mac_48gc_w(offs_t offset, u32 data, u32 mem_mask = ~0);
+};
+
+class nubus_824gc_device : public jmfb_device
+{
+public:
+ nubus_824gc_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 ATTR_COLD;
+ virtual ioport_constructor device_input_ports() const override ATTR_COLD;
+};
+
+
+INPUT_PORTS_START( 48gc )
+ PORT_START("CONFIG")
+ PORT_CONFNAME(0x0f, 0x06, u8"Attached monitor")
+ PORT_CONFSETTING( 0x00, u8"Macintosh Two-Page Monitor (1152\u00d7870)")
+ PORT_CONFSETTING( 0x01, u8"Macintosh Portrait Display (B&W 15\" 640\u00d7870)")
+ PORT_CONFSETTING( 0x02, u8"Macintosh RGB Display (12\" 512\u00d7384)")
+ PORT_CONFSETTING( 0x03, u8"Macintosh Two-Page Monitor (B&W 21\" 1152\u00d7870)")
+ PORT_CONFSETTING( 0x04, u8"NTSC Monitor (512\u00d7384, 640\u00d7480)") // requires interlace modes
+ PORT_CONFSETTING( 0x05, u8"Macintosh Portrait Display (640\u00d7870)")
+ PORT_CONFSETTING( 0x06, u8"Macintosh Hi-Res Display (12-14\" 640\u00d7480)")
+ PORT_CONFSETTING( 0x0b, u8"NTSC Encoder (512\u00d7384, 640\u00d7480)") // requires interlace modes
+ PORT_CONFNAME(0x10, 0x00, u8"VRAM size")
+ PORT_CONFSETTING( 0x00, u8"512 kB (4\u20228)")
+ PORT_CONFSETTING( 0x10, u8"1 MB (8\u202224)")
+ PORT_CONFNAME(0x20, 0x00, u8"CLUT address read")
+ PORT_CONFSETTING( 0x00, "Disable")
+ PORT_CONFSETTING( 0x20, "Enable")
+INPUT_PORTS_END
+
+
+INPUT_PORTS_START( 824gc )
+ PORT_START("CONFIG")
+ PORT_CONFNAME(0x0f, 0x06, u8"Attached monitor")
+ PORT_CONFSETTING( 0x00, u8"Mac 21\" Color Display (1152\u00d7870)")
+ PORT_CONFSETTING( 0x01, u8"Mac Portrait Display (B&W 15\" 640\u00d7870)")
+ PORT_CONFSETTING( 0x02, u8"Mac RGB Display (12\" 512\u00d7384)")
+ PORT_CONFSETTING( 0x03, u8"Mac Two-Page Display (B&W 21\" 1152\u00d7870)")
+ PORT_CONFSETTING( 0x04, u8"NTSC Monitor (512\u00d7384, 640\u00d7480)") // requires interlace modes
+ PORT_CONFSETTING( 0x06, u8"Mac Hi-Res Display (12-14\" 640\u00d7480)")
+ PORT_CONFSETTING( 0x0a, u8"PAL Encoder (640\u00d7480, 768\u00d7576)") // requires interlace modes
+ PORT_CONFSETTING( 0x0b, u8"NTSC Encoder (512\u00d7384, 640\u00d7480)") // requires interlace modes
+ PORT_CONFSETTING( 0x0d, u8"Mac 16\" Color Display (832\u00d7624)")
+ PORT_CONFSETTING( 0x1e, u8"PAL Monitor (640\u00d7480, 768\u00d7576)") // requires interlace modes
+ PORT_CONFNAME(0x10, 0x10, u8"VRAM size")
+ PORT_CONFSETTING( 0x00, u8"512 kB (4\u20228)")
+ PORT_CONFSETTING( 0x10, u8"1 MB (8\u202224)")
+ PORT_CONFNAME(0x20, 0x00, u8"CLUT address read")
+ PORT_CONFSETTING( 0x00, "Disable")
+ PORT_CONFSETTING( 0x20, "Enable")
+INPUT_PORTS_END
+
+
ROM_START( gc48 )
ROM_REGION(0x8000, GC48_ROM_REGION, 0)
ROM_LOAD( "3410801.bin", 0x0000, 0x8000, CRC(e283da91) SHA1(4ae21d6d7bbaa6fc7aa301bee2b791ed33b1dcf9) )
@@ -27,12 +238,29 @@ ROM_START( gc824 )
ROM_LOAD( "3410868.bin", 0x000000, 0x008000, CRC(57f925fa) SHA1(4d3c0632711b7b31c8e0c5cfdd7ec1904f178336) ) /* Label: "341-0868 // (C)APPLE COMPUTER // INC. 1986-1991 // ALL RIGHTS // RESERVED W5" */
ROM_END
-//**************************************************************************
-// GLOBAL VARIABLES
-//**************************************************************************
-DEFINE_DEVICE_TYPE(NUBUS_48GC, nubus_48gc_device, "nb_48gc", "Apple 4*8 video card")
-DEFINE_DEVICE_TYPE(NUBUS_824GC, nubus_824gc_device, "nb_824gc", "Apple 8*24 video card")
+// TODO: find a better place for this table to live
+struct mac_monitor_info { bool mono; unsigned sense[4]; };
+mac_monitor_info const f_monitors[] = {
+ // 512×385 640×480 640×870 832×624 1024×768 1152×870 640×480
+ // 60.15 Hz 66.67 Hz 75.08 Hz 74.55 Hz 74.93 Hz 75.08 Hz 59.94 Hz 55.98 Hz 59.94 Hz 50.00 Hz
+ // portrait interlaced interlaced
+ { false, { 0, 0, 0, 0 } }, // 0: RGB 21" yes
+ { true, { 1, 1, 1, 0 } }, // 1: Full-Page (B&W 15") yes
+ { false, { 2, 2, 0, 2 } }, // 2: RGB 12" yes
+ { true, { 3, 3, 1, 2 } }, // 3: Two-Page (B&W 21") yes
+ { false, { 4, 0, 4, 4 } }, // 4: NTSC Monitor yes
+ { false, { 5, 1, 5, 4 } }, // 5: RGB 15" yes
+ { false, { 6, 2, 4, 6 } }, // 6: Hi-Res (12-14") yes
+ { false, { 6, 0, 0, 6 } }, // 7: Multiple Scan 14" yes yes
+ { false, { 6, 0, 4, 6 } }, // 8: Multiple Scan 16" yes yes yes
+ { false, { 6, 2, 0, 6 } }, // 9: Multiple Scan 21" yes yes yes yes
+ { false, { 7, 0, 0, 0 } }, // 10: PAL Encoder yes
+ { false, { 7, 1, 1, 0 } }, // 11: NTSC Encoder yes
+ { false, { 7, 1, 1, 6 } }, // 12: VGA/Super VGA yes yes
+ { false, { 7, 2, 5, 2 } }, // 13: RGB 16" yes
+ { false, { 7, 3, 0, 0 } }, // 14: PAL Monitor yes
+ { false, { 7, 3, 4, 4 } } }; // 15: RGB 19" yes
//-------------------------------------------------
@@ -41,20 +269,20 @@ DEFINE_DEVICE_TYPE(NUBUS_824GC, nubus_824gc_device, "nb_824gc", "Apple 8*24 vide
void jmfb_device::device_add_mconfig(machine_config &config)
{
+ config.set_default_layout(layout_monitors);
+
screen_device &screen(SCREEN(config, GC48_SCREEN_NAME, SCREEN_TYPE_RASTER));
screen.set_screen_update(FUNC(jmfb_device::screen_update));
- screen.set_raw(25175000, 800, 0, 640, 525, 0, 480);
-// screen.set_size(1152, 870);
-// screen.set_visarea(0, 1152-1, 0, 870-1);
-// screen.set_refresh_hz(75);
-// screen.set_vblank_time(ATTOSECONDS_IN_USEC(1260));
+ screen.set_raw(20_MHz_XTAL / 21 * 127 / 4, 864, 0, 640, 525, 0, 480);
+ //screen.set_raw(20_MHz_XTAL / 19 * 190 / 2, 1'456, 0, 1'152, 915, 0, 870);
+ screen.set_video_attributes(VIDEO_UPDATE_SCANLINE);
}
//-------------------------------------------------
// rom_region - device-specific ROM region
//-------------------------------------------------
-const tiny_rom_entry *jmfb_device::device_rom_region() const
+const tiny_rom_entry *nubus_48gc_device::device_rom_region() const
{
return ROM_NAME( gc48 );
}
@@ -64,6 +292,30 @@ const tiny_rom_entry *nubus_824gc_device::device_rom_region() const
return ROM_NAME( gc824 );
}
+//-------------------------------------------------
+// input_ports - device-specific input ports
+//-------------------------------------------------
+
+ioport_constructor nubus_48gc_device::device_input_ports() const
+{
+ return INPUT_PORTS_NAME( 48gc );
+}
+
+ioport_constructor nubus_824gc_device::device_input_ports() const
+{
+ return INPUT_PORTS_NAME( 824gc );
+}
+
+//-------------------------------------------------
+// palette_entries - entries in color palette
+//-------------------------------------------------
+
+u32 jmfb_device::palette_entries() const noexcept
+{
+ return 256;
+}
+
+
//**************************************************************************
// LIVE DEVICE
//**************************************************************************
@@ -72,24 +324,34 @@ const tiny_rom_entry *nubus_824gc_device::device_rom_region() const
// jmfb_device - constructor
//-------------------------------------------------
-jmfb_device::jmfb_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock, bool is824) :
+jmfb_device::jmfb_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_screen(nullptr), m_timer(nullptr), m_mode(0), m_vbl_disable(0), m_toggle(0), m_stride(0), m_base(0), m_count(0), m_clutoffs(0), m_xres(0), m_yres(0),
- m_is824(is824)
+ device_video_interface(mconfig, *this),
+ device_palette_interface(mconfig, *this),
+ m_config(*this, "CONFIG"),
+ m_vram_view(*this, "vram"),
+ m_timer(nullptr)
{
set_screen(*this, GC48_SCREEN_NAME);
}
-nubus_48gc_device::nubus_48gc_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) :
- jmfb_device(mconfig, NUBUS_48GC, tag, owner, clock, false)
+nubus_48gc_device::nubus_48gc_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock) :
+ jmfb_device(mconfig, NUBUS_MDC48, tag, owner, clock)
+{
+}
+
+nubus_824gc_device::nubus_824gc_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock) :
+ jmfb_device(mconfig, NUBUS_MDC824, tag, owner, clock)
{
}
-nubus_824gc_device::nubus_824gc_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) :
- jmfb_device(mconfig, NUBUS_824GC, tag, owner, clock, true)
+void jmfb_device::card_map(address_map &map)
{
+ map(0x20'0000, 0x20'000f).rw(FUNC(jmfb_device::jmfb_r), FUNC(jmfb_device::jmfb_w));
+ map(0x20'0100, 0x20'01ff).rw(FUNC(jmfb_device::crtc_r), FUNC(jmfb_device::crtc_w));
+ map(0x20'0200, 0x20'020f).rw(FUNC(jmfb_device::ramdac_r), FUNC(jmfb_device::ramdac_w));
+ map(0x20'0300, 0x20'033f).w(FUNC(jmfb_device::clkgen_w));
}
//-------------------------------------------------
@@ -98,21 +360,50 @@ nubus_824gc_device::nubus_824gc_device(const machine_config &mconfig, const char
void jmfb_device::device_start()
{
- uint32_t slotspace;
+ install_declaration_rom(GC48_ROM_REGION);
+
+ u32 const slotspace = get_slotspace();
+
+ LOG("[JMFB %p] slotspace = %x\n", this, slotspace);
- install_declaration_rom(this, GC48_ROM_REGION);
+ m_vram = std::make_unique<u32 []>(VRAM_MAX);
+ install_view(slotspace, slotspace + 0x1f'ffff, m_vram_view);
- slotspace = get_slotspace();
+ nubus().install_map(*this, &jmfb_device::card_map);
-// printf("[JMFB %p] slotspace = %x\n", this, slotspace);
+ m_timer = timer_alloc(FUNC(jmfb_device::vbl_start), this);
- m_vram.resize(VRAM_SIZE);
- install_bank(slotspace, slotspace+VRAM_SIZE-1, "bank_48gc", &m_vram[0]);
+ m_configured = false;
+ m_clut_addr_read = false;
+ m_monitor_type = 0;
- nubus().install_device(slotspace+0x200000, slotspace+0x2003ff, read32_delegate(FUNC(jmfb_device::mac_48gc_r), this), write32_delegate(FUNC(jmfb_device::mac_48gc_w), this));
+ m_ramdac_mode = 0;
+ m_ramdac_conv = 0;
- m_timer = timer_alloc(0, nullptr);
- m_screen = nullptr; // can we look this up now?
+ save_item(NAME(m_monitor_type));
+ save_pointer(NAME(m_vram), VRAM_MAX);
+ save_item(NAME(m_control));
+ save_item(NAME(m_preload));
+ save_item(NAME(m_base));
+ save_item(NAME(m_stride));
+ save_item(NAME(m_colors));
+ save_item(NAME(m_clutcnt));
+ save_item(NAME(m_clutoffs));
+ save_item(NAME(m_ramdac_mode));
+ save_item(NAME(m_ramdac_conv));
+ save_item(NAME(m_hactive));
+ save_item(NAME(m_hbporch));
+ save_item(NAME(m_hsync));
+ save_item(NAME(m_hfporch));
+ save_item(NAME(m_vactive));
+ save_item(NAME(m_vbporch));
+ save_item(NAME(m_vsync));
+ save_item(NAME(m_vfporch));
+ save_item(NAME(m_vbl_disable));
+ save_item(NAME(m_halfline_pixels));
+ save_item(NAME(m_multiplier));
+ save_item(NAME(m_modulus));
+ save_item(NAME(m_pdiv));
}
//-------------------------------------------------
@@ -121,17 +412,99 @@ void jmfb_device::device_start()
void jmfb_device::device_reset()
{
- m_toggle = 0;
- m_clutoffs = 0;
- m_count = 0;
+ if (!m_configured)
+ {
+ m_configured = true;
+ ioport_value const config = m_config->read();
+
+ m_monitor_type = config & 0x0f;
+ if (m_monitor_type > std::size(f_monitors))
+ {
+ throw emu_fatalerror("%s: Invalid monitor selection %d\n", tag(), m_monitor_type);
+ }
+
+ u32 const slotspace = get_slotspace();
+ u32 const vramsize = VRAM_MAX * 4 / (BIT(config, 4) ? 1 : 2);
+ m_vram_view[0].install_ram(slotspace, slotspace + vramsize - 1, &m_vram[0]);
+ m_vram_view[1].install_readwrite_handler(
+ slotspace, slotspace + (vramsize / 3 * 4) - 1,
+ read32s_delegate(*this, FUNC(jmfb_device::rgb_unpack)), write32s_delegate(*this, FUNC(jmfb_device::rgb_pack)));
+ switch (vramsize % 3)
+ {
+ case 0:
+ break;
+ case 1:
+ m_vram_view[1].install_readwrite_handler(
+ slotspace + (vramsize / 3 * 4), slotspace + (vramsize / 3 * 4) + 3,
+ read32s_delegate(
+ *this,
+ NAME(([this, vramsize] (offs_t offset, u32 mem_mask) -> u32
+ {
+ auto const color = util::big_endian_cast<u8 const>(&m_vram[0]) + (vramsize - 1);
+ return u32(color[0]) << 16;
+ }))),
+ write32s_delegate(
+ *this,
+ NAME(([this, vramsize] (offs_t offset, u32 data, u32 mem_mask)
+ {
+ auto const color = util::big_endian_cast<u8>(&m_vram[0]) + (vramsize - 1);
+ if (ACCESSING_BITS_16_23)
+ color[0] = u8(data >> 16);
+ }))));
+ break;
+ case 2:
+ m_vram_view[1].install_readwrite_handler(
+ slotspace + (vramsize / 3 * 4), slotspace + (vramsize / 3 * 4) + 3,
+ read32s_delegate(
+ *this,
+ NAME(([this, vramsize] (offs_t offset, u32 mem_mask) -> u32
+ {
+ auto const color = util::big_endian_cast<u8 const>(&m_vram[0]) + (vramsize - 2);
+ return (u32(color[0]) << 16) | (u32(color[1]) << 8);
+ }))),
+ write32s_delegate(
+ *this,
+ NAME(([this, vramsize] (offs_t offset, u32 data, u32 mem_mask)
+ {
+ auto const color = util::big_endian_cast<u8>(&m_vram[0]) + (vramsize - 2);
+ if (ACCESSING_BITS_16_23)
+ color[0] = u8(data >> 16);
+ if (ACCESSING_BITS_8_15)
+ color[1] = u8(data >> 8);
+ }))));
+ break;
+ }
+
+ m_clut_addr_read = BIT(config, 5);
+ }
+
+ m_vram_view.select(0);
+
+ std::fill_n(&m_vram[0], VRAM_MAX, 0);
m_vbl_disable = 1;
- m_stride = 80;
+ m_control = 0x0002;
+ m_preload = 256 - 8;
m_base = 0;
- m_xres = 640;
- m_yres = 480;
- m_mode = 0;
- memset(&m_vram[0], 0, VRAM_SIZE);
- memset(m_palette, 0, sizeof(m_palette));
+ m_stride = 80 / 4;
+
+ m_clutoffs = 0;
+ m_clutcnt = 0;
+ m_ramdac_mode = 0;
+ m_ramdac_conv = 0;
+
+ m_hactive = 286;
+ m_hbporch = 22;
+ m_hsync = 30;
+ m_hfporch = 18;
+ m_vactive = 1740;
+ m_vbporch = 78;
+ m_vsync = 6;
+ m_vfporch = 6;
+ m_halfline_pixels = 576;
+
+ m_multiplier = 190;
+ m_modulus = 19;
+ m_pdiv = 1;
}
/***************************************************************************
@@ -140,223 +513,656 @@ void jmfb_device::device_reset()
***************************************************************************/
-void jmfb_device::device_timer(emu_timer &timer, device_timer_id tid, int param, void *ptr)
+TIMER_CALLBACK_MEMBER(jmfb_device::vbl_start)
{
if (!m_vbl_disable)
{
raise_slot_irq();
}
- m_timer->adjust(m_screen->time_until_pos(479, 0), 0);
+ set_vbl_timer();
}
-uint32_t jmfb_device::screen_update(screen_device &screen, bitmap_rgb32 &bitmap, const rectangle &cliprect)
+void jmfb_device::set_vbl_timer()
{
- uint32_t *scanline, *base;
- int x, y;
- uint8_t *vram8 = &m_vram[0];
- uint8_t pixels;
+ // TODO: precise VBL timing in interlaced modes if half-line split is offset (likely doesn't matter in practice)
+ rectangle const &visarea = screen().visible_area();
+ int const height = screen().height();
+ if ((visarea.bottom() + 1) < height)
+ {
+ m_timer->adjust(screen().time_until_pos(visarea.bottom() + 1));
+ }
+ else
+ {
+ m_timer->adjust(screen().time_until_pos(visarea.bottom() + 1 - height));
+ }
+}
- // first time? kick off the VBL timer
- if (!m_screen)
+u32 jmfb_device::screen_update(screen_device &screen, bitmap_rgb32 &bitmap, const rectangle &cliprect)
+{
+ if (!ctrl_transfer())
{
- m_screen = &screen;
- m_timer->adjust(m_screen->time_until_pos(479, 0), 0);
+ bitmap.fill(0, cliprect);
+ return 0;
}
- vram8 += 0xa00;
+ switch (m_ramdac_mode)
+ {
+ case 0x0: // 1bpp
+ update_screen<0x0>(screen, bitmap, cliprect);
+ break;
+
+ case 0x4: // 2bpp
+ update_screen<0x4>(screen, bitmap, cliprect);
+ break;
+
+ case 0x8: // 4 bpp
+ update_screen<0x8>(screen, bitmap, cliprect);
+ break;
+
+ case 0xc: // 8 bpp
+ update_screen<0xc>(screen, bitmap, cliprect);
+ break;
+
+ case 0xd: // 24 bpp
+ update_screen<0xd>(screen, bitmap, cliprect);
+ break;
- switch (m_mode)
+ default:
+ throw emu_fatalerror("%s: Unsupported RAMDAC mode %d\n", tag(), m_ramdac_mode);
+ }
+
+ return 0;
+}
+
+template <u8 Mode>
+void jmfb_device::update_screen(screen_device &screen, bitmap_rgb32 &bitmap, const rectangle &cliprect)
+{
+ if (!ctrl_convolution())
{
- case 0: // 1bpp
- for (y = 0; y < m_yres; y++)
- {
- scanline = &bitmap.pix32(y);
- for (x = 0; x < m_xres/8; x++)
- {
- pixels = vram8[(y * m_stride) + (BYTE4_XOR_BE(x))];
-
- *scanline++ = m_palette[(pixels>>7)&1];
- *scanline++ = m_palette[(pixels>>6)&1];
- *scanline++ = m_palette[(pixels>>5)&1];
- *scanline++ = m_palette[(pixels>>4)&1];
- *scanline++ = m_palette[(pixels>>3)&1];
- *scanline++ = m_palette[(pixels>>2)&1];
- *scanline++ = m_palette[(pixels>>1)&1];
- *scanline++ = m_palette[pixels&1];
- }
- }
- break;
+ if (!f_monitors[m_monitor_type].mono)
+ update_screen<Mode, false, false>(screen, bitmap, cliprect);
+ else
+ update_screen<Mode, false, true>(screen, bitmap, cliprect);
+ }
+ else
+ {
+ if (!f_monitors[m_monitor_type].mono)
+ update_screen<Mode, true, false>(screen, bitmap, cliprect);
+ else
+ update_screen<Mode, true, true>(screen, bitmap, cliprect);
+ }
+}
- case 1: // 2bpp
- for (y = 0; y < m_yres; y++)
- {
- scanline = &bitmap.pix32(y);
- for (x = 0; x < m_xres/4; x++)
- {
- pixels = vram8[(y * m_stride) + (BYTE4_XOR_BE(x))];
+template <u8 Mode, bool Convolution, bool Mono>
+void jmfb_device::update_screen(screen_device &screen, bitmap_rgb32 &bitmap, const rectangle &cliprect)
+{
+ // TODO: interlaced mode
+ auto const baseoffset = m_base << (((0xd == Mode) ? 6 : 5) + (Convolution ? 1 : 0));
+ auto const screenbase = util::big_endian_cast<u8 const>(&m_vram[0]) + baseoffset;
+ auto const stride = m_stride << ((0xd == Mode) ? 3 : 2);
- *scanline++ = m_palette[(pixels>>6)&0x3];
- *scanline++ = m_palette[(pixels>>4)&0x3];
- *scanline++ = m_palette[(pixels>>2)&0x3];
- *scanline++ = m_palette[pixels&3];
- }
- }
- break;
+ auto const trans =
+ [] (rgb_t color)
+ {
+ return !Mono ? color : rgb_t(color.b(), color.b(), color.b());
+ };
- case 2: // 4 bpp
- for (y = 0; y < m_yres; y++)
+ rectangle const &visarea = screen.visible_area();
+ int const xstart = visarea.left();
+ int xres = visarea.width();
+ if (0x0 == Mode)
+ {
+ xres /= 8;
+ }
+ else if (0x4 == Mode)
+ {
+ xres /= 4;
+ }
+ else if (0x8 == Mode)
+ {
+ xres /= 2;
+ }
+
+ int y = cliprect.top();
+ while (y < visarea.top())
+ {
+ std::fill_n(&bitmap.pix(y++, xstart), visarea.width(), 0);
+ }
+ while ((y <= cliprect.bottom()) && (y <= visarea.bottom()))
+ {
+ auto source = screenbase + ((y - visarea.top()) * stride);
+ u32 *scanline = &bitmap.pix(y, xstart);
+ y++;
+ for (int x = 0; x <= xres; x++)
+ {
+ if (0xd == Mode) // 24bpp
{
- scanline = &bitmap.pix32(y);
+ if (!f_monitors[m_monitor_type].mono)
+ *scanline++ = rgb_t(source[0], source[1], source[2]);
+ else
+ *scanline++ = rgb_t(source[2], source[2], source[2]);
+ source += 3;
+ }
+ else if (!Convolution)
+ {
+ u8 const pixels = *source++;
- for (x = 0; x < m_xres/2; x++)
+ if (0x0 == Mode) // 1bpp
{
- pixels = vram8[(y * m_stride) + (BYTE4_XOR_BE(x))];
-
- *scanline++ = m_palette[(pixels>>4)&0xf];
- *scanline++ = m_palette[pixels&0xf];
+ *scanline++ = trans(pen_color(BIT(pixels, 7)));
+ *scanline++ = trans(pen_color(BIT(pixels, 6)));
+ *scanline++ = trans(pen_color(BIT(pixels, 5)));
+ *scanline++ = trans(pen_color(BIT(pixels, 4)));
+ *scanline++ = trans(pen_color(BIT(pixels, 3)));
+ *scanline++ = trans(pen_color(BIT(pixels, 2)));
+ *scanline++ = trans(pen_color(BIT(pixels, 1)));
+ *scanline++ = trans(pen_color(BIT(pixels, 0)));
+ }
+ else if (0x4 == Mode) // 2bpp
+ {
+ *scanline++ = trans(pen_color(BIT(pixels, 6, 2)));
+ *scanline++ = trans(pen_color(BIT(pixels, 4, 2)));
+ *scanline++ = trans(pen_color(BIT(pixels, 2, 2)));
+ *scanline++ = trans(pen_color(BIT(pixels, 0, 2)));
+ }
+ else if (0x8 == Mode) // 4bpp
+ {
+ *scanline++ = trans(pen_color(BIT(pixels, 4, 4)));
+ *scanline++ = trans(pen_color(BIT(pixels, 0, 4)));
+ }
+ else if (0xc == Mode) // 8bpp
+ {
+ *scanline++ = trans(pen_color(pixels));
}
}
- break;
-
- case 3: // 8 bpp
- for (y = 0; y < m_yres; y++)
+ else
{
- scanline = &bitmap.pix32(y);
+ u8 const pixabove = source[0 * stride];
+ u8 const pixels = source[1 * stride];
+ u8 const pixbelow = source[2 * stride];
+ source++;
- for (x = 0; x < m_xres; x++)
+ if (0x0 == Mode) // 1bpp
{
- pixels = vram8[(y * m_stride) + (BYTE4_XOR_BE(x))];
- *scanline++ = m_palette[pixels];
+ for (int p = 7; p >= 0; p--)
+ {
+ rgb_t const a = pen_color(BIT(pixabove, p));
+ rgb_t const b = pen_color(BIT(pixels, p));
+ rgb_t const c = pen_color(BIT(pixbelow, p));
+ *scanline++ = trans(
+ rgb_t(
+ (a.r() + (u16(b.r()) << 1) + c.r() + 2) >> 2,
+ (a.g() + (u16(b.g()) << 1) + c.g() + 2) >> 2,
+ (a.b() + (u16(b.b()) << 1) + c.b() + 2) >> 2));
+ }
}
- }
- break;
-
- case 4: // 24 bpp
- for (y = 0; y < m_yres; y++)
- {
- scanline = &bitmap.pix32(y);
- base = (uint32_t *)&m_vram[y * m_stride];
- for (x = 0; x < m_xres; x++)
+ else if (0x4 == Mode) // 2bpp
+ {
+ for (int p = 6; p >= 0; p -= 2)
+ {
+ rgb_t const a = pen_color(BIT(pixabove, p, 2));
+ rgb_t const b = pen_color(BIT(pixels, p, 2));
+ rgb_t const c = pen_color(BIT(pixbelow, p, 2));
+ *scanline++ = trans(
+ rgb_t(
+ (a.r() + (u16(b.r()) << 1) + c.r() + 2) >> 2,
+ (a.g() + (u16(b.g()) << 1) + c.g() + 2) >> 2,
+ (a.b() + (u16(b.b()) << 1) + c.b() + 2) >> 2));
+ }
+ }
+ else if (0x8 == Mode) // 4bpp
{
- *scanline++ = *base++;
+ for (int p = 4; p >= 0; p -= 4)
+ {
+ rgb_t const a = pen_color(BIT(pixabove, p, 4));
+ rgb_t const b = pen_color(BIT(pixels, p, 4));
+ rgb_t const c = pen_color(BIT(pixbelow, p, 4));
+ *scanline++ = trans(
+ rgb_t(
+ (a.r() + (u16(b.r()) << 1) + c.r() + 2) >> 2,
+ (a.g() + (u16(b.g()) << 1) + c.g() + 2) >> 2,
+ (a.b() + (u16(b.b()) << 1) + c.b() + 2) >> 2));
+ }
+ }
+ else if (0xc == Mode) // 8bpp
+ {
+ rgb_t const a = pen_color(pixabove);
+ rgb_t const b = pen_color(pixels);
+ rgb_t const c = pen_color(pixbelow);
+ *scanline++ = trans(
+ rgb_t(
+ (a.r() + (u16(b.r()) << 1) + c.r() + 2) >> 2,
+ (a.g() + (u16(b.g()) << 1) + c.g() + 2) >> 2,
+ (a.b() + (u16(b.b()) << 1) + c.b() + 2) >> 2));
}
}
+ }
+ }
+ while (y <= cliprect.bottom())
+ {
+ std::fill_n(&bitmap.pix(y++, xstart), visarea.width(), 0);
+ }
+}
+
+void jmfb_device::update_crtc()
+{
+ // Vertical values are always in half-lines.
+ // In progressive modes, we give the screen device numbers of full lines.
+ // In interlaced modes we let the screen device base horizontal timing on half-lines.
+ int const vtotal = m_vactive + m_vbporch + m_vsync + m_vfporch;
+ if (vtotal && m_vactive && m_multiplier && m_modulus)
+ {
+ bool const interlace = vtotal % 2;
+ bool const convolution = ctrl_convolution();
+
+ int const vstart = m_vsync + m_vbporch;
+ int const vlines = vtotal >> (interlace ? 0 : 1);
+ int const top = vstart >> (interlace ? 0 : 1);
+ int const height = m_vactive >> (interlace ? 0 : 1);
+
+ int const divider = 256 - m_preload;
+ XTAL const refclk = 20_MHz_XTAL / m_modulus;
+ XTAL const vcoout = refclk * m_multiplier;
+ XTAL const pixclk = vcoout / (1 << m_pdiv);
+ XTAL const dacclk = pixclk / divider;
+ LOGCLKGEN("reference clock %d VCO output %d pixel clock %d RAMDAC longword load clock %d\n",
+ refclk.value(), vcoout.value(), pixclk.value(), dacclk.value());
+
+ int const htotal = m_hactive + m_hbporch + m_hsync + m_hfporch + 8;
+ int const hstart = m_hbporch + m_hsync + 4;
+ int const hactive = m_hactive + 2;
+
+ int scale = 0;
+ switch (m_ramdac_mode)
+ {
+ case 0x0: // 1bpp - 32 pixels/longword
+ scale = 5;
+ break;
+ case 0x4: // 2bpp - 16 pixels/longword
+ scale = 4;
break;
+ case 0x8: // 4bpp - 8 pixels/longword
+ scale = 3;
+ break;
+ case 0xc: // 8bpp - 4 pixels/longword
+ scale = 2;
+ break;
+ case 0xd: // 24bpp - 1 pixel/longword
+ scale = 0;
+ break;
+ }
+ int const hpixels = (htotal << scale >> (convolution ? 2 : 0)) / divider;
+ int const left = (hstart << scale >> (convolution ? 2 : 0)) / divider;
+ int const width = (hactive << scale >> (convolution ? 2 : 0)) / divider;
+ m_halfline_pixels = (m_hhalf << scale >> (convolution ? 2 : 0)) / divider;
+ LOGCRTC("vertical total %d start %d active %d horizontal total %d start %d active %d (mode %x %d/%d)\n",
+ vtotal, vstart, m_vactive, htotal, hstart, hactive, m_ramdac_mode, width, hpixels);
+
+ int const frametotal = hpixels * vlines;
+
+ screen().configure(
+ hpixels, vlines,
+ rectangle(left, left + width - 1, top, top + height - 1),
+ attotime::from_ticks(frametotal << (convolution ? 2 : 0) >> (interlace ? 1 : 0), pixclk).attoseconds());
+
+ set_vbl_timer();
}
+}
- return 0;
+u32 jmfb_device::jmfb_r(offs_t offset)
+{
+ switch (offset)
+ {
+ case 0x00/4:
+ {
+ u16 sense = f_monitors[m_monitor_type].sense[0];
+ if (ctrl_sense2())
+ sense &= f_monitors[m_monitor_type].sense[1];
+ if (ctrl_sense1())
+ sense &= f_monitors[m_monitor_type].sense[2];
+ if (ctrl_sense0())
+ sense &= f_monitors[m_monitor_type].sense[3];
+ return (m_control & 0xf1ff) | (sense << 9);
+ }
+
+ case 0x04/4: return m_preload; // RAMDAC longword load clock divider preload
+ case 0x08/4: return m_base; // base - 32-byte increments for indexed, 64-byte increments for direct
+ case 0x0c/4: return m_stride; // stride - 4-byte increments for indexed, 8-byte increments for direct
+
+ default:
+ LOG("%s: read unimplemented JMFB register %x/4\n", machine().describe_context(), offset * 4);
+ return 0;
+ }
}
-WRITE32_MEMBER( jmfb_device::mac_48gc_w )
+u32 jmfb_device::crtc_r(offs_t offset)
{
- COMBINE_DATA(&m_registers[offset&0xff]);
+// printf("%s crtc_r: @ %x, mask %08x\n", machine().describe_context().c_str(), offset, mem_mask);
switch (offset)
{
- case 0x8/4: // base
-// printf("%x to base\n", data);
- m_base = (data*2)<<4;
- break;
+ case 0x08/4: return m_hhalf; // half line length from start of active area
+ case 0x0c/4: return m_hactive; // active pixel cells - 2
+ case 0x10/4: return m_hbporch; // horizontal back porch - 2
+ case 0x14/4: return m_hsync; // horizontal sync pulse width - 2
+ case 0x18/4: return m_hfporch; // horizontal front porch - 2
+
+ case 0x24/4: return m_vactive; // active lines * 2
+ case 0x28/4: return m_vbporch; // vertical back porch * 2
+ case 0x2c/4: return m_vsync; // vertical sync pulse width * 2
+ case 0x30/4: return m_vfporch; // vertical front porch * 2
+
+ case 0xc0/4: // beam position/status
+ {
+ // TODO: remaining two flags - interrupt status?
+ rectangle const &visarea = screen().visible_area();
+ int const vpos = screen().vpos();
+ int const hpos = screen().hpos();
+ int const hsplit = visarea.left() + m_halfline_pixels;
+ int const vtotal = m_vactive + m_vbporch + m_vsync + m_vfporch;
+ u8 result = 0x0f;
- case 0xc/4: // stride
-// printf("%x to stride\n", data);
- // this value is in DWORDs for 1-8 bpp and, uhh, strange for 24bpp
- if (m_mode < 4)
+ int halfline;
+ int truehpos;
+ if (vtotal % 2)
{
- m_stride = data*4;
+ // screen device configured to count half-lines vertically
+ int const oddfield = screen().frame_number() % 2;
+ int const oddhalfline = vpos % 2;
+ truehpos = (hpos + ((oddfield != oddhalfline) ? screen().width() : 0)) >> 1;
+
+ // adjust half line count in case half line position is offset
+ if ((oddfield == oddhalfline) && (truehpos >= hsplit))
+ {
+ halfline = vpos + 1;
+ if (halfline >= vtotal)
+ {
+ halfline -= vtotal;
+ }
+ }
+ else if ((oddfield != oddhalfline) && (truehpos < hsplit))
+ {
+ halfline = vpos - 1;
+ if (halfline < 0)
+ {
+ halfline += vtotal;
+ }
+ }
+ else
+ {
+ halfline = vpos;
+ }
+
+ // set odd field flag
+ if (oddfield)
+ {
+ // TODO: confirm where this flips - on sync or on front porch?
+ result |= 0x10; // odd field
+ }
}
else
{
- m_stride = (data*32)/3;
+ // vertical counts are in half-lines but screen device uses full lines
+ halfline = (vpos << 1) | ((hpos >= hsplit) ? 1 : 0);
+ truehpos = hpos;
}
- break;
- case 0x200/4: // DAC control
-// printf("%08x to DAC control\n", data);
- if (m_is824)
+ // set horizontal beam position flag
+ if ((truehpos < visarea.left()) || (truehpos > visarea.right()))
{
- m_clutoffs = data&0xff;
+ result |= 0x20; // horizontal blanking
}
- else
- {
- m_clutoffs = data>>24;
- }
- m_count = 0;
- break;
- case 0x204/4: // DAC data
- if (m_is824)
+ // set appropriate vertical beam position flag (active low)
+ if (halfline < m_vsync)
{
- m_colors[m_count++] = data&0xff;
+ result &= ~0x04; // sync pulse
}
- else
+ else if (halfline < (m_vsync + m_vbporch))
{
- m_colors[m_count++] = data>>24;
+ result &= ~0x02; // back porch
}
-
- if (m_count == 3)
+ else if (halfline < (m_vsync + m_vbporch + m_vactive))
{
-// printf("RAMDAC: color %d = %02x %02x %02x\n", m_clutoffs, m_colors[0], m_colors[1], m_colors[2]);
- m_palette[m_clutoffs] = rgb_t(m_colors[0], m_colors[1], m_colors[2]);
- m_clutoffs++;
- m_count = 0;
+ result &= ~0x01; // active
}
- break;
-
- case 0x208/4: // mode control
- m_mode = (data>>3)&3;
- if (m_mode == 3) // this can be 8 or 24 bpp
+ else
{
- // check pixel format for 24bpp
- if (m_is824)
- {
- if (data & 2)
- {
- m_mode = 4; // 24bpp
- }
- }
- else
- {
- if (((data>>5)&3) == 0)
- {
- m_mode = 4; // 24bpp
- }
- }
+ result &= ~0x08; // front porch
}
-// printf("%02x to mode (m_mode = %d)\n", data, m_mode);
- break;
- case 0x13c/4: // bit 1 = VBL disable (1=no interrupts)
- m_vbl_disable = (data & 2) ? 1 : 0;
- break;
+ return result;
+ }
- case 0x148/4: // write 1 here to clear interrupt
- if (data == 1)
- {
- lower_slot_irq();
- }
- break;
+ case 0xcc/4: // TODO: What is this? Waits for bit 3 to clear before clearing interrupts.
+ return 0;
- default:
- break;
+ default:
+ LOGCRTC("%s: read unimplemented CRTC register %02x/4\n", machine().describe_context(), offset * 4);
+ return 0;
}
}
-READ32_MEMBER( jmfb_device::mac_48gc_r )
+u32 jmfb_device::ramdac_r(offs_t offset)
{
-// printf("%s 48gc_r: @ %x, mask %08x\n", machine().describe_context().c_str(), offset, mem_mask);
+ switch (offset)
+ {
+ case 0x00/4: // CLUT address
+ // The firmware explicitly checks whether it can read the value written to the CLUT address
+ // What difference this makes is not known
+ return m_clut_addr_read ? m_clutoffs : 0;
+ default:
+ LOGRAMDAC("%s: read unimplemented RAMDAC register %x/4\n", machine().describe_context(), offset * 4);
+ return 0;
+ }
+}
+
+void jmfb_device::jmfb_w(offs_t offset, u32 data)
+{
+ data &= 0xffff; // 16 bits wide, but lane select is ignored and firmware relies on smearing
switch (offset)
{
- case 0:
- return 0x0c00; // sense 13" RGB for now
-// return 0x0000; // sense "RGB Kong" monitor
+ case 0x00/4: // control
+ LOG("%s: %04x to control (%spixel clock %x sense %x transfer %x convolution %x interlace %x refresh %x RGB %x RAM %dk)\n",
+ machine().describe_context(), data,
+ BIT(data, 15) ? "reset " : "",
+ BIT(data, 12, 3),
+ BIT(data, 9, 3),
+ BIT(data, 6),
+ BIT(data, 5),
+ BIT(data, 4),
+ BIT(data, 3),
+ BIT(data, 2),
+ BIT(data, 0) ? 256 : 128);
+ m_control = data & 0x7fff; // video reset bit needs to read as zero
+ m_vram_view.select(ctrl_rgb() ? 1 : 0); // packed RGB mode
+ break;
+
+ case 0x04/4: // RAMDAC longword load clock divider preload
+ LOG("%s: 256-%d to preload\n", machine().describe_context(), data & 0xff);
+ m_preload = data & 0xff;
+ update_crtc();
+ break;
+
+ case 0x08/4: // base - 32-byte increments for indexed, 64-byte increments for direct
+ LOG("%s: %x to base\n", machine().describe_context(), data);
+ m_base = data;
+ break;
- case 0x1c0/4:
- m_toggle ^= 0xffffffff;
- return m_toggle;
+ case 0x0c/4: // stride - 4-byte increments for indexed, 8-byte increments for direct
+ LOG("%s: %x to stride\n", machine().describe_context(), data);
+ m_stride = data;
+ break;
}
+}
- return 0;
+void jmfb_device::crtc_w(offs_t offset, u32 data)
+{
+ data &= 0xffff; // 16 bits wide, but lane select is ignored and firmware relies on smearing
+ switch (offset)
+ {
+ case 0x08/4: // half line length from start of active area
+ LOGCRTC("%s: %d to half line cells\n", machine().describe_context(), data);
+ m_hhalf = data & 0x0fff;
+ update_crtc();
+ break;
+
+ case 0x0c/4: // active pixel cells - 2
+ LOGCRTC("%s: %d+2 to active cells\n", machine().describe_context(), data);
+ m_hactive = data & 0x0fff;
+ update_crtc();
+ break;
+
+ case 0x10/4: // horizontal back porch - 2
+ LOGCRTC("%s: %d+2 to horizontal back porch\n", machine().describe_context(), data);
+ m_hbporch = data & 0x0fff;
+ update_crtc();
+ break;
+
+ case 0x14/4: // horizontal sync pulse width - 2
+ LOGCRTC("%s: %d+2 to horizontal sync pulse width\n", machine().describe_context(), data);
+ m_hsync = data & 0x0fff;
+ update_crtc();
+ break;
+
+ case 0x18/4: // horizontal front porch - 2
+ LOGCRTC("%s: %d+2 to horizontal front porch\n", machine().describe_context(), data);
+ m_hfporch = data & 0x0fff;
+ update_crtc();
+ break;
+
+ case 0x24/4: // active lines * 2
+ LOGCRTC("%s: %d/2 to active lines\n", machine().describe_context(), data);
+ m_vactive = data & 0x0fff;
+ update_crtc();
+ break;
+
+ case 0x28/4: // vertical back porch * 2
+ LOGCRTC("%s: %d/2 to vertical back porch\n", machine().describe_context(), data);
+ m_vbporch = data & 0x0fff;
+ update_crtc();
+ break;
+
+ case 0x2c/4: // vertical sync pulse width * 2
+ LOGCRTC("%s: %d/2 to vertical sync pulse width\n", machine().describe_context(), data);
+ m_vsync = data & 0x0fff;
+ update_crtc();
+ break;
+
+ case 0x30/4: // vertical front porch * 2
+ LOGCRTC("%s: %d/2 to vertical front porch\n", machine().describe_context(), data);
+ m_vfporch = data & 0x0fff;
+ update_crtc();
+ break;
+
+ case 0x3c/4: // bit 1 = VBL disable (1=no interrupts)
+ m_vbl_disable = (data & 2) ? 1 : 0;
+ break;
+
+ case 0x48/4: // write here to clear interrupt
+ lower_slot_irq();
+ break;
+
+ default:
+ LOGCRTC("%s: %03x to unimplemented CRTC register %x/4\n", machine().describe_context(), data, offset * 4);
+ }
+}
+
+void jmfb_device::ramdac_w(offs_t offset, u32 data)
+{
+ data &= 0xff; // 8 bits wide, but lane select is ignored and firmware relies on smearing
+ switch (offset)
+ {
+ case 0x00/4: // CLUT address
+ LOGCLUT("%s: %u to RAMDAC color address\n", machine().describe_context(), data);
+ m_clutoffs = data;
+ m_clutcnt = 0;
+ break;
+
+ case 0x04/4: // CLUT data
+ m_colors[m_clutcnt++] = data & 0xff;
+ if (m_clutcnt == 3)
+ {
+ LOGCLUT("%s: RAMDAC color %u = %02x %02x %02x\n", machine().describe_context(), m_clutoffs, m_colors[0], m_colors[1], m_colors[2]);
+ set_pen_color(m_clutoffs, rgb_t(m_colors[0], m_colors[1], m_colors[2]));
+ m_clutoffs++;
+ m_clutcnt = 0;
+ }
+ break;
+
+ case 0x08/4: // RAMDAC mode control
+ m_ramdac_mode = (data >> 1) & 0xf;
+ m_ramdac_conv = BIT(data, 0);
+ LOGRAMDAC("%s: %02x to RAMDAC control (mode %x convolution %x)\n",
+ machine().describe_context(), data, m_ramdac_mode, m_ramdac_conv);
+ update_crtc();
+ break;
+
+ default:
+ LOGRAMDAC("%s: %02x to unimplemented RAMDAC register %x/4\n", machine().describe_context(), data, offset * 4);
+ }
}
+
+void jmfb_device::clkgen_w(offs_t offset, u32 data)
+{
+ data &= 0x0f; // four bits wide, but lane select is ignored and firmware relies on smearing
+ switch (offset)
+ {
+ case 0x00/4:
+ case 0x04/4:
+ case 0x08/4:
+ case 0x0c/4:
+ m_multiplier &= ~(0x0f << ((offset & 3) * 4));
+ m_multiplier |= data << ((offset & 3) * 4);
+ LOGCLKGEN("%s: %d to multiplier\n", machine().describe_context(), m_multiplier);
+ update_crtc();
+ break;
+
+ case 0x10/4:
+ case 0x14/4:
+ case 0x18/4:
+ m_modulus &= ~(0x0f << ((offset & 3) * 4));
+ m_modulus |= data << ((offset & 3) * 4);
+ LOGCLKGEN("%s: %d to reference clock divider\n", machine().describe_context(), m_modulus);
+ update_crtc();
+ break;
+
+ case 0x24/4:
+ m_pdiv = data;
+ LOGCLKGEN("%s: 1<<%d to pixel clock divider\n", machine().describe_context(), m_pdiv);
+ update_crtc();
+ break;
+
+ default:
+ LOGCRTC("%s: %x to unimplemented clock synthesiser register %x/4\n", machine().describe_context(), data, offset * 4);
+ }
+}
+
+u32 jmfb_device::rgb_unpack(offs_t offset, u32 mem_mask)
+{
+ auto const color = util::big_endian_cast<u8 const>(&m_vram[0]) + (offset * 3);
+ return (u32(color[0]) << 16) | (u32(color[1]) << 8) | u32(color[2]);
+}
+
+void jmfb_device::rgb_pack(offs_t offset, u32 data, u32 mem_mask)
+{
+ auto const color = util::big_endian_cast<u8>(&m_vram[0]) + (offset * 3);
+ if (ACCESSING_BITS_16_23)
+ color[0] = u8(data >> 16);
+ if (ACCESSING_BITS_8_15)
+ color[1] = u8(data >> 8);
+ if (ACCESSING_BITS_0_7)
+ color[2] = u8(data);
+}
+
+} // anonymous namespace
+
+
+//**************************************************************************
+// DEVICE TYPE DEFINITIONS
+//**************************************************************************
+
+DEFINE_DEVICE_TYPE_PRIVATE(NUBUS_MDC48, device_nubus_card_interface, nubus_48gc_device, "nb_mdc48", "Apple Macintosh Display Card 4/8 (MDC 1.0.1)")
+DEFINE_DEVICE_TYPE_PRIVATE(NUBUS_MDC824, device_nubus_card_interface, nubus_824gc_device, "nb_mdc824", "Apple Macintosh Display Card 8/24 (MDC 1.2)")
diff --git a/src/devices/bus/nubus/nubus_48gc.h b/src/devices/bus/nubus/nubus_48gc.h
index 3c73befdaea..4603150077b 100644
--- a/src/devices/bus/nubus/nubus_48gc.h
+++ b/src/devices/bus/nubus/nubus_48gc.h
@@ -1,5 +1,5 @@
// license:BSD-3-Clause
-// copyright-holders:R. Belmont
+// copyright-holders:R. Belmont, Vas Crabb
#ifndef MAME_BUS_NUBUS_NUBUS_48GC_H
#define MAME_BUS_NUBUS_NUBUS_48GC_H
@@ -7,62 +7,8 @@
#include "nubus.h"
-//**************************************************************************
-// TYPE DEFINITIONS
-//**************************************************************************
-
-// ======================> jmfb_device
-
-class jmfb_device :
- public device_t,
- public device_video_interface,
- public device_nubus_card_interface
-{
-protected:
- // construction/destruction
- jmfb_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock, bool is824);
-
- // device-level overrides
- virtual void device_start() override;
- virtual void device_reset() override;
- virtual void device_timer(emu_timer &timer, device_timer_id id, int param, void *ptr) override;
-
- // optional information overrides
- virtual void device_add_mconfig(machine_config &config) override;
- virtual const tiny_rom_entry *device_rom_region() const override;
-
-private:
- DECLARE_READ32_MEMBER(mac_48gc_r);
- DECLARE_WRITE32_MEMBER(mac_48gc_w);
-
- uint32_t screen_update(screen_device &screen, bitmap_rgb32 &bitmap, const rectangle &cliprect);
-
- screen_device *m_screen;
- emu_timer *m_timer;
-
- std::vector<uint8_t> m_vram;
- uint32_t m_mode, m_vbl_disable, m_toggle, m_stride, m_base;
- uint32_t m_palette[256], m_colors[3], m_count, m_clutoffs;
- uint32_t m_registers[0x100];
- int m_xres, m_yres;
- const bool m_is824;
-};
-
-class nubus_48gc_device : public jmfb_device
-{
-public:
- nubus_48gc_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
-};
-
-class nubus_824gc_device : public jmfb_device
-{
-public:
- nubus_824gc_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_48GC, nubus_48gc_device)
-DECLARE_DEVICE_TYPE(NUBUS_824GC, nubus_824gc_device)
+DECLARE_DEVICE_TYPE(NUBUS_MDC48, device_nubus_card_interface)
+DECLARE_DEVICE_TYPE(NUBUS_MDC824, device_nubus_card_interface)
#endif /// MAME_BUS_NUBUS_NUBUS_48GC_H
diff --git a/src/devices/bus/nubus/nubus_asntmc3b.cpp b/src/devices/bus/nubus/nubus_asntmc3b.cpp
index f6c0135af5f..2756ca16456 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 ATTR_COLD;
+ virtual void device_reset() override ATTR_COLD;
-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 ATTR_COLD;
+ virtual const tiny_rom_entry *device_rom_region() const override ATTR_COLD;
+ 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 ATTR_COLD;
+};
+
+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 ATTR_COLD;
+
+protected:
+ virtual void device_start() override ATTR_COLD;
+};
+
+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 ATTR_COLD;
+
+protected:
+ virtual void device_start() override ATTR_COLD;
+};
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,95 +134,112 @@ 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(this, 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;
- nubus().install_device(slotspace+0xd0000, slotspace+0xdffff, read8_delegate(FUNC(nubus_mac8390_device::asntm3b_ram_r), this), write8_delegate(FUNC(nubus_mac8390_device::asntm3b_ram_w), this));
- nubus().install_device(slotspace+0xe0000, slotspace+0xe003f, read32_delegate(FUNC(nubus_mac8390_device::en_r), this), write32_delegate(FUNC(nubus_mac8390_device::en_w), this));
- nubus().install_device(slotspace+0xd0000+ofs_24bit, slotspace+0xdffff+ofs_24bit, read8_delegate(FUNC(nubus_mac8390_device::asntm3b_ram_r), this), write8_delegate(FUNC(nubus_mac8390_device::asntm3b_ram_w), this));
- nubus().install_device(slotspace+0xe0000+ofs_24bit, slotspace+0xe003f+ofs_24bit, read32_delegate(FUNC(nubus_mac8390_device::en_r), this), write32_delegate(FUNC(nubus_mac8390_device::en_w), this));
+ // 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::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::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);
- m_dp83902->dp8390_cs(0);
- memcpy(m_prom, m_dp83902->get_mac(), 6);
+ memcpy(m_prom, &m_dp83902->get_mac()[0], 6);
}
-WRITE8_MEMBER( nubus_mac8390_device::asntm3b_ram_w )
+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;
}
-READ8_MEMBER( nubus_mac8390_device::asntm3b_ram_r )
+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];
}
-WRITE32_MEMBER( nubus_mac8390_device::en_w )
+void nubus_mac8390_device::dp_w(offs_t offset, u32 data, u32 mem_mask)
{
if (mem_mask == 0xff000000)
{
// printf("%02x to 8390 @ %x\n", data>>24, 0xf-offset);
- m_dp83902->dp8390_w(space, 0xf-offset, data>>24);
+ m_dp83902->cs_write(0xf-offset, data>>24);
}
else if (mem_mask == 0xffff0000)
{
- m_dp83902->dp8390_cs(1);
- m_dp83902->dp8390_w(space, 0xf-offset, data>>16);
- m_dp83902->dp8390_cs(0);
+ m_dp83902->remote_write(data>>16);
}
else
{
@@ -159,17 +247,15 @@ WRITE32_MEMBER( nubus_mac8390_device::en_w )
}
}
-READ32_MEMBER( nubus_mac8390_device::en_r )
+u32 nubus_mac8390_device::dp_r(offs_t offset, u32 mem_mask)
{
if (mem_mask == 0xff000000)
{
- return (m_dp83902->dp8390_r(space, 0xf-offset)<<24);
+ return (m_dp83902->cs_read(0xf-offset)<<24);
}
else if (mem_mask == 0xffff0000)
{
- m_dp83902->dp8390_cs(1);
- return (m_dp83902->dp8390_r(space, 0xf-offset)<<16);
- m_dp83902->dp8390_cs(0);
+ return (m_dp83902->remote_read()<<16);
}
else
{
@@ -179,7 +265,7 @@ READ32_MEMBER( nubus_mac8390_device::en_r )
return 0;
}
-WRITE_LINE_MEMBER( nubus_mac8390_device::dp_irq_w )
+void nubus_mac8390_device::dp_irq_w(int state)
{
if (state)
{
@@ -191,14 +277,21 @@ WRITE_LINE_MEMBER( nubus_mac8390_device::dp_irq_w )
}
}
-READ8_MEMBER( nubus_mac8390_device::dp_mem_read )
+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];
}
-WRITE8_MEMBER( nubus_mac8390_device::dp_mem_write )
+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 7b1ee196a13..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;
-
- DECLARE_READ8_MEMBER(asntm3b_ram_r);
- DECLARE_WRITE8_MEMBER(asntm3b_ram_w);
- DECLARE_READ32_MEMBER(en_r);
- DECLARE_WRITE32_MEMBER(en_w);
-
- required_device<dp8390_device> m_dp83902;
-
-private:
- void dp_irq_w(int state);
- DECLARE_READ8_MEMBER(dp_mem_read);
- DECLARE_WRITE8_MEMBER(dp_mem_write);
-
- 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 01bff0877da..e4946ae2baa 100644
--- a/src/devices/bus/nubus/nubus_cb264.cpp
+++ b/src/devices/bus/nubus/nubus_cb264.cpp
@@ -4,78 +4,165 @@
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
+ for 30 Hz interlaced NTSC output.
+
+ The card has 1.5 MiB of VRAM mapped into a 2 MiB space. It's divided into
+ 3 banks of 512KiB each, divided up as 512K of red, 512K of green, and 512K
+ of blue.
+
+ In paletted modes (1, 2, 4, and 8 bits per pixel), the framebuffer
+ is the 512K red bank exclusively on every byte lane.
+
+ In 24-bit mode, for each 32-bit word, byte 0 is from the red bank, byte 1
+ is from the green bank, and byte 2 is from the blue bank. Byte 3 reads as zero
+ and writes are discarded. We don't currently emulate this mechanism, but
+ may in the future.
***************************************************************************/
#include "emu.h"
+
#include "nubus_cb264.h"
+
+#include "video/bt47x.h"
+
+#include "emupal.h"
#include "screen.h"
-#define CB264_SCREEN_NAME "cb264_screen"
-#define CB264_ROM_REGION "cb264_rom"
+#include <algorithm>
+
+#define VERBOSE (0)
+
+#include "logmacro.h"
+namespace {
+
+ // 12x TC524256J (256K x 4 bit VRAM) for 1.5 MiB total.
+ // To make emulation easier/more performant, we allocate the 4th 512K bank
+ // and just zero it out n 24-bit mode.
+ static constexpr u32 VRAM_SIZE = 0x20'0000;
+
+ enum
+ {
+ VSyncEnd = 0,
+ VBlankStart,
+ VTotal,
+ HSyncEnd,
+ HBlankEnd,
+ HBlankStart,
+ HTotal,
+ HHalfLineCount,
+ VBlankEnd,
+
+ CRTC_Length
+ };
+
+ class nubus_cb264_device : public device_t,
+ public device_nubus_card_interface,
+ public device_video_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);
+
+ // device-level overrides
+ virtual void device_start() override ATTR_COLD;
+ virtual void device_reset() override ATTR_COLD;
+
+ // optional information overrides
+ virtual void device_add_mconfig(machine_config &config) override ATTR_COLD;
+ virtual const tiny_rom_entry *device_rom_region() const override ATTR_COLD;
+ virtual ioport_constructor device_input_ports() const override ATTR_COLD;
+
+ u32 cb264_r(offs_t offset, u32 mem_mask = ~0);
+ void cb264_w(offs_t offset, u32 data, u32 mem_mask = ~0);
+ u32 cb264_ramdac_r(offs_t offset);
+ void cb264_ramdac_w(offs_t offset, u32 data);
+ u32 cb264_vram_r(offs_t offset);
+ void cb264_vram_w(offs_t offset, u32 data, u32 mem_mask);
+
+ private:
+ u32 screen_update(screen_device &screen, bitmap_rgb32 &bitmap, const rectangle &cliprect);
+
+ void card_map(address_map &map);
-#define VRAM_SIZE (0x200000) // 2 megs, maxed out
+ TIMER_CALLBACK_MEMBER(vbl_tick);
+ required_device<screen_device> m_screen;
+ required_device<palette_device> m_palette;
+ required_ioport m_config;
+ std::unique_ptr<u32[]> m_vram;
+
+ emu_timer *m_vbl_timer;
+
+ u32 m_cb264_mode, m_cb264_vbl_disable;
+ u32 m_colors[3], m_count, m_clutoffs;
+ u32 m_force_blank, m_osc_select;
+ u32 m_crtc[CRTC_Length];
+};
ROM_START( cb264 )
- ROM_REGION(0x4000, CB264_ROM_REGION, 0)
+ ROM_REGION(0x4000, "declrom", 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
-//**************************************************************************
-// GLOBAL VARIABLES
-//**************************************************************************
-
-DEFINE_DEVICE_TYPE(NUBUS_CB264, nubus_cb264_device, "nb_c264", "RasterOps ColorBoard 264 video card")
+INPUT_PORTS_START( cb264 )
+ PORT_START("CONFIG")
+ PORT_CONFNAME( 0x01, 0x00, "Monitor Type" )
+ PORT_CONFSETTING( 0x00, "Macintosh 13\" 640x480");
+ PORT_CONFSETTING( 0x01, "NTSC");
+INPUT_PORTS_END
-
-//-------------------------------------------------
-// device_add_mconfig - add device configuration
-//-------------------------------------------------
+ioport_constructor nubus_cb264_device::device_input_ports() const
+{
+ return INPUT_PORTS_NAME(cb264);
+}
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, "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::nubus_cb264_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock) :
nubus_cb264_device(mconfig, NUBUS_CB264, tag, owner, clock)
{
}
-nubus_cb264_device::nubus_cb264_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock) :
+nubus_cb264_device::nubus_cb264_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_cb264_mode(0), m_cb264_vbl_disable(0), m_cb264_toggle(0), m_count(0), m_clutoffs(0)
+ device_video_interface(mconfig, *this),
+ m_screen(*this, "screen"),
+ m_palette(*this, "palette"),
+ m_config(*this, "CONFIG"),
+ m_cb264_mode(0), m_cb264_vbl_disable(0), m_count(0), m_clutoffs(0),
+ m_force_blank(0), m_osc_select(0)
{
+ std::fill_n(&m_crtc[0], CRTC_Length, 0);
+ set_screen(*this, "screen");
+}
+
+void nubus_cb264_device::card_map(address_map &map)
+{
+ map(0x00'0000, 0x1f'ffff).rw(FUNC(nubus_cb264_device::cb264_vram_r), FUNC(nubus_cb264_device::cb264_vram_w));
+ map(0xff'6000, 0xff'60ff).rw(FUNC(nubus_cb264_device::cb264_r), FUNC(nubus_cb264_device::cb264_w));
+ map(0xff'7000, 0xff'70ff).rw(FUNC(nubus_cb264_device::cb264_ramdac_r), FUNC(nubus_cb264_device::cb264_ramdac_w));
}
//-------------------------------------------------
@@ -84,133 +171,115 @@ nubus_cb264_device::nubus_cb264_device(const machine_config &mconfig, device_typ
void nubus_cb264_device::device_start()
{
- uint32_t slotspace;
-
- install_declaration_rom(this, CB264_ROM_REGION);
-
- slotspace = get_slotspace();
+ install_declaration_rom("declrom");
-// printf("[cb264 %p] slotspace = %x\n", this, slotspace);
+ m_vram = std::make_unique<u32[]>(VRAM_SIZE / sizeof(u32));
+ nubus().install_map(*this, &nubus_cb264_device::card_map);
- m_vram.resize(VRAM_SIZE);
- install_bank(slotspace, slotspace+VRAM_SIZE-1, "bank_cb264", &m_vram[0]);
+ 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_item(NAME(m_force_blank));
+ save_item(NAME(m_osc_select));
+ save_pointer(NAME(m_vram), VRAM_SIZE / sizeof(u32));
- nubus().install_device(slotspace+0xff6000, slotspace+0xff60ff, read32_delegate(FUNC(nubus_cb264_device::cb264_r), this), write32_delegate(FUNC(nubus_cb264_device::cb264_w), this));
- nubus().install_device(slotspace+0xff7000, slotspace+0xff70ff, read32_delegate(FUNC(nubus_cb264_device::cb264_ramdac_r), this), write32_delegate(FUNC(nubus_cb264_device::cb264_ramdac_w), this));
+ m_vbl_timer = timer_alloc(FUNC(nubus_cb264_device::vbl_tick), this);
}
-//-------------------------------------------------
-// device_reset - device-specific reset
-//-------------------------------------------------
-
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;
- memset(&m_vram[0], 0, VRAM_SIZE);
- memset(m_palette, 0, sizeof(m_palette));
+ m_force_blank = 0;
+ 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)
+u32 nubus_cb264_device::screen_update(screen_device &screen, bitmap_rgb32 &bitmap, const rectangle &cliprect)
{
- uint32_t *scanline, *base;
- int x, y;
- uint8_t pixels;
-
- if (!m_cb264_vbl_disable)
+ if (!BIT(m_force_blank, 0))
{
- raise_slot_irq();
+ bitmap.fill(0, cliprect);
+ return 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 (y = 0; y < 480; y++)
+ for (int y = 0; y < 480; y++)
{
- scanline = &bitmap.pix32(y);
- for (x = 0; x < 640/8; x++)
+ u32 *scanline = &bitmap.pix(y);
+ for (int x = 0; x < 640/8; x++)
{
- pixels = m_vram[(y * 1024) + (BYTE4_XOR_BE(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;
case 1: // 2 bpp (3f/7f/bf/ff)
- for (y = 0; y < 480; y++)
+ for (int y = 0; y < 480; y++)
{
- scanline = &bitmap.pix32(y);
- for (x = 0; x < 640/4; x++)
+ u32 *scanline = &bitmap.pix(y);
+ for (int x = 0; x < 640/4; x++)
{
- pixels = m_vram[(y * 1024) + (BYTE4_XOR_BE(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;
case 2: // 4 bpp
- for (y = 0; y < 480; y++)
+ for (int y = 0; y < 480; y++)
{
- scanline = &bitmap.pix32(y);
-
- for (x = 0; x < 640/2; x++)
+ u32 *scanline = &bitmap.pix(y);
+ for (int x = 0; x < 640/2; x++)
{
- pixels = m_vram[(y * 1024) + (BYTE4_XOR_BE(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;
case 3: // 8 bpp
- for (y = 0; y < 480; y++)
+ for (int y = 0; y < 480; y++)
{
- scanline = &bitmap.pix32(y);
-
- for (x = 0; x < 640; x++)
+ u32 *scanline = &bitmap.pix(y);
+ for (int x = 0; x < 640; x++)
{
- pixels = m_vram[(y * 1024) + (BYTE4_XOR_BE(x))];
- *scanline++ = m_palette[pixels];
+ u8 const pixels = vram8[(y * 1024) + x];
+ *scanline++ = pens[pixels];
}
}
break;
case 4: // 24 bpp
- case 7: // ???
+ case 5:
+ case 6:
+ case 7: // if bit 2 is set the ASIC forces 24bpp regardless of bits 0 & 1
+ for (int y = 0; y < 480; y++)
{
- uint32_t *vram32 = (uint32_t *)&m_vram[0];
-
- for (y = 0; y < 480; y++)
- {
- scanline = &bitmap.pix32(y);
- base = &vram32[y * 1024];
- for (x = 0; x < 640; x++)
- {
- *scanline++ = *base++;
- }
- }
+ std::copy_n(&m_vram[y * 1024], 640, &bitmap.pix(y));
}
break;
@@ -221,39 +290,87 @@ uint32_t nubus_cb264_device::screen_update(screen_device &screen, bitmap_rgb32 &
return 0;
}
-WRITE32_MEMBER( nubus_cb264_device::cb264_w )
+void nubus_cb264_device::cb264_w(offs_t offset, u32 data, u32 mem_mask)
{
- switch (offset)
+ switch (offset<<2)
{
- case 0x4/4: // 0 = 1 bpp, 1 = 2bpp, 2 = 4bpp, 3 = 8bpp, 4 = 24bpp
- m_cb264_mode = data;
+ case 0x4: // 0 = 1 bpp, 1 = 2bpp, 2 = 4bpp, 3 = 8bpp, 4 = 24bpp
+ m_cb264_mode = data & 7;
+ break;
+
+ case 0xc: // Oscillator select
+ m_osc_select = data;
break;
- case 0x14/4: // VBL ack
+ case 0x14: // VBL clear
lower_slot_irq();
break;
- case 0x3c/4: // VBL disable
+ case 0x1c: // force blank
+ data &= 1;
+ if ((data != m_force_blank) && (data = 1))
+ {
+ const u32 hres = (m_crtc[HBlankStart] - m_crtc[HBlankEnd]) * 4;
+ const u32 htotal = m_crtc[HTotal] * 4;
+ u32 vres = m_crtc[VBlankStart] - m_crtc[VBlankEnd];
+ u32 vtotal = m_crtc[VTotal] + 1;
+
+ // bit 1 is the actual oscillator select
+ const u32 pixel_clock = BIT(m_osc_select, 1) ? 12'335'600 : 30'240'000;
+
+ // bit 0 is NTSC mode
+ if (BIT(m_osc_select, 0))
+ {
+ vres *= 2;
+ vtotal *= 2;
+ }
+
+ LOG("osc_select %d pixel_clock %d\n", m_osc_select, pixel_clock);
+ LOG("hres %d vres %d htotal %d vtotal %d\n", hres, vres, htotal, vtotal);
+
+ const rectangle visarea(0, hres - 1, 0, vres - 1);
+ m_screen->configure(htotal, vtotal, visarea, attotime::from_ticks(htotal * vtotal, 30'240'000).as_attoseconds());
+ }
+
+ m_force_blank = data;
+ break;
+
+ case 0x3c: // VBL disable
m_cb264_vbl_disable = data;
+
+ if (!data)
+ {
+ const u32 hres = (m_crtc[HBlankStart] - m_crtc[HBlankEnd]) * 4;
+ m_vbl_timer->adjust(m_screen->time_until_pos(hres - 1, 0), 0);
+ }
+ break;
+
+ case 0x40: case 0x44: case 0x48: case 0x4c: case 0x50: case 0x54: case 0x58: case 0x5c:
+ case 0x60:
+ m_crtc[(offset - (0x40 >> 2))] = data;
break;
default:
-// printf("%s cb264_w: %x to reg %x (mask %x)\n", machine().describe_context().c_str(), data, offset*4, mem_mask);
+ LOG("%s cb264_w: %x to reg %x (mask %x)\n", machine().describe_context().c_str(), data, offset*4, mem_mask);
break;
}
}
-READ32_MEMBER( nubus_cb264_device::cb264_r )
+u32 nubus_cb264_device::cb264_r(offs_t offset, u32 mem_mask)
{
- switch (offset)
+ switch (offset<<2)
{
- case 0x0c/4:
- case 0x28/4:
- break;
+ case 0xc:
+ return m_osc_select;
+
+ case 0x1c:
+ return m_force_blank;
- case 0x34/4:
- m_cb264_toggle ^= 1;
- return m_cb264_toggle; // bit 0 is vblank?
+ case 0x28:
+ return 0x4 | (m_config->read() << 1); // bit 2 = 1 is monitor connected, bit 1 = 0 for 60 Hz non-interlaced, bit 0 = 0 for option RAM connected
+
+ case 0x34:
+ 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());
@@ -263,7 +380,7 @@ READ32_MEMBER( nubus_cb264_device::cb264_r )
return 0;
}
-WRITE32_MEMBER( nubus_cb264_device::cb264_ramdac_w )
+void nubus_cb264_device::cb264_ramdac_w(offs_t offset, u32 data)
{
switch (offset)
{
@@ -277,19 +394,50 @@ WRITE32_MEMBER( nubus_cb264_device::cb264_ramdac_w )
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;
}
break;
default:
-// printf("%x to unknown RAMDAC register @ %x\n", data, offset);
+ LOG("%x to unknown RAMDAC register @ %x\n", data, offset);
break;
}
}
-READ32_MEMBER( nubus_cb264_device::cb264_ramdac_r )
+u32 nubus_cb264_device::cb264_ramdac_r(offs_t offset)
{
return 0;
}
+
+u32 nubus_cb264_device::cb264_vram_r(offs_t offset)
+{
+ if (BIT(m_cb264_mode, 2))
+ {
+ return m_vram[offset] & 0x00ffffff;
+ }
+
+ return m_vram[offset];
+}
+
+void nubus_cb264_device::cb264_vram_w(offs_t offset, u32 data, u32 mem_mask)
+{
+ if (BIT(m_cb264_mode, 2))
+ {
+ data &= 0x00ffffff;
+ }
+ COMBINE_DATA(&m_vram[offset]);
+}
+
+TIMER_CALLBACK_MEMBER(nubus_cb264_device::vbl_tick)
+{
+ raise_slot_irq();
+ m_vbl_timer->adjust(m_screen->time_until_pos(479, 0), 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 07719f8ccae..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;
-
- DECLARE_READ32_MEMBER(cb264_r);
- DECLARE_WRITE32_MEMBER(cb264_w);
- DECLARE_READ32_MEMBER(cb264_ramdac_r);
- DECLARE_WRITE32_MEMBER(cb264_ramdac_w);
-
-private:
- uint32_t screen_update(screen_device &screen, bitmap_rgb32 &bitmap, const rectangle &cliprect);
-
- std::vector<uint8_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 8e2d39fb943..2eb95ce5ad8 100644
--- a/src/devices/bus/nubus/nubus_image.cpp
+++ b/src/devices/bus/nubus/nubus_image.cpp
@@ -2,102 +2,164 @@
// copyright-holders:R. Belmont
/***************************************************************************
- nubus_image.c - synthetic NuBus card to allow reading/writing "raw"
+ nubus_image.cpp - synthetic NuBus card to allow reading/writing "raw"
HFS images, including floppy images (DD and HD) and vMac/Basilisk HDD
volumes up to 256 MB in size.
+ TODO:
+ * Get get directory and get listing commands have no way to indicate
+ that the path/name is too long for the buffer.
+ * The set directory command doesn't work well with host filesystems that
+ have roots (e.g. Windows drive letters).
+ * The set directory command assumes '/' is a valid host directory
+ separator character.
+ * The get listing commands have no way to indicate whether an entry is
+ a directory.
+
***************************************************************************/
#include "emu.h"
#include "nubus_image.h"
-#include "osdcore.h"
-#define IMAGE_ROM_REGION "image_rom"
-#define IMAGE_DISK0_TAG "nb_disk"
-
-#define MESSIMG_DISK_SECTOR_SIZE (512)
+#include "osdcore.h"
+#include "osdfile.h"
+#include <algorithm>
-// nubus_image_device::messimg_disk_image_device
+constexpr auto MAMEIMG_DISK_SECTOR_SIZE = 512;
-class nubus_image_device::messimg_disk_image_device : public device_t,
- public device_image_interface
+class nubus_image_device : public device_t,
+ public device_nubus_card_interface
{
public:
+ class mameimg_disk_image_device;
+
// construction/destruction
- messimg_disk_image_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
+ nubus_image_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock);
- // image-level overrides
- virtual iodevice_t image_type() const override { return IO_QUICKLOAD; }
+protected:
+ enum
+ {
+ kFileCmdGetDir = 1,
+ kFileCmdSetDir,
+ kFileCmdGetFirstListing,
+ kFileCmdGetNextListing,
+ kFileCmdGetFile,
+ kFileCmdPutFile
+ };
+
+ struct nbfilectx
+ {
+ u32 curcmd;
+ char filename[128];
+ std::string curdir;
+ osd::directory::ptr dirp;
+ osd_file::ptr fd;
+ u64 filelen;
+ u32 bytecount;
+ };
- virtual bool is_readable() const override { return 1; }
- virtual bool is_writeable() const override { return 1; }
- virtual bool is_creatable() const override { return 0; }
- virtual bool must_be_loaded() const override { return 0; }
- virtual bool is_reset_on_load() const override { return 0; }
- virtual const char *file_extensions() const override { return "img"; }
- virtual const char *custom_instance_name() const override { return "disk"; }
- virtual const char *custom_brief_instance_name() const override { return "disk"; }
+ nubus_image_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, u32 clock);
- virtual image_init_result call_load() override;
+ // device-level overrides
+ virtual void device_start() override ATTR_COLD;
+
+ // optional information overrides
+ virtual void device_add_mconfig(machine_config &config) override ATTR_COLD;
+ virtual const tiny_rom_entry *device_rom_region() const override ATTR_COLD;
+
+ void card_map(address_map &map);
+ void card_super_map(address_map &map);
+
+ u32 image_status_r();
+ void image_status_w(u32 data);
+ u32 image_r();
+ void image_w(u32 data);
+ u32 image_super_r(offs_t offset, u32 mem_mask = ~0);
+ void image_super_w(offs_t offset, u32 data, u32 mem_mask = ~0);
+ u32 file_cmd_r();
+ void file_cmd_w(u32 data);
+ u32 file_data_r();
+ void file_data_w(u32 data);
+ u32 file_len_r();
+ void file_len_w(u32 data);
+ u32 file_name_r(offs_t offset);
+ void file_name_w(offs_t offset, u32 data);
+
+ mameimg_disk_image_device *m_image;
+ nbfilectx filectx;
+};
+
+// nubus_image_device::mameimg_disk_image_device
+
+class nubus_image_device::mameimg_disk_image_device : public device_t, public device_image_interface
+{
+public:
+ // construction/destruction
+ mameimg_disk_image_device(const machine_config &mconfig, const char *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 true; }
+ 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 "img"; }
+ virtual const char *image_type_name() const noexcept override { return "disk"; }
+ virtual const char *image_brief_type_name() const noexcept override { return "disk"; }
+
+ virtual std::pair<std::error_condition, std::string> call_load() override;
virtual void call_unload() override;
- protected:
+protected:
// device-level overrides
- virtual void device_start() override;
- virtual void device_reset() override;
+ virtual void device_start() override ATTR_COLD;
+
public:
- uint32_t m_size;
- std::unique_ptr<uint8_t[]> m_data;
+ u32 m_size;
+ std::unique_ptr<u8[]> m_data;
bool m_ejected;
};
+DEFINE_DEVICE_TYPE(MAMEIMG_DISK, nubus_image_device::mameimg_disk_image_device, "messimg_disk_image", "Mac image")
-// device type definition
-DEFINE_DEVICE_TYPE_NS(MESSIMG_DISK, nubus_image_device, messimg_disk_image_device, "messimg_disk_image", "Mac image")
-
-nubus_image_device::messimg_disk_image_device::messimg_disk_image_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) :
- device_t(mconfig, MESSIMG_DISK, tag, owner, clock),
+nubus_image_device::mameimg_disk_image_device::mameimg_disk_image_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock) :
+ device_t(mconfig, MAMEIMG_DISK, tag, owner, clock),
device_image_interface(mconfig, *this),
m_size(0), m_data(nullptr), m_ejected(false)
{
}
-
-/*-------------------------------------------------
- device start callback
--------------------------------------------------*/
-
-void nubus_image_device::messimg_disk_image_device::device_start()
+void nubus_image_device::mameimg_disk_image_device::device_start()
{
m_data = nullptr;
- if (exists() && fseek(0, SEEK_END) == 0)
+ if (exists() && !fseek(0, SEEK_END))
{
- m_size = (uint32_t)ftell();
+ m_size = u32(ftell());
}
}
-image_init_result nubus_image_device::messimg_disk_image_device::call_load()
+std::pair<std::error_condition, std::string> nubus_image_device::mameimg_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 = make_unique_clear<uint8_t[]>(m_size);
+ m_data.reset(new (std::nothrow) u8 [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.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()
+void nubus_image_device::mameimg_disk_image_device::call_unload()
{
// TODO: track dirty sectors and only write those
fseek(0, SEEK_SET);
@@ -106,33 +168,14 @@ void nubus_image_device::messimg_disk_image_device::call_unload()
//free(m_data);
}
-/*-------------------------------------------------
- device reset callback
--------------------------------------------------*/
-
-void nubus_image_device::messimg_disk_image_device::device_reset()
-{
-}
-
ROM_START( image )
- ROM_REGION(0x2000, IMAGE_ROM_REGION, 0)
+ ROM_REGION(0x2000, "declrom", 0)
ROM_LOAD( "nb_fake.bin", 0x000000, 0x002000, CRC(9264bac5) SHA1(540c2ce3c90382b2da6e1e21182cdf8fc3f0c930) )
ROM_END
-//**************************************************************************
-// GLOBAL VARIABLES
-//**************************************************************************
-
-DEFINE_DEVICE_TYPE(NUBUS_IMAGE, nubus_image_device, "nb_image", "NuBus Disk Image Pseudo-Card")
-
-
-//-------------------------------------------------
-// device_add_mconfig - add device configuration
-//-------------------------------------------------
-
void nubus_image_device::device_add_mconfig(machine_config &config)
{
- MESSIMG_DISK(config, IMAGE_DISK0_TAG, 0);
+ MAMEIMG_DISK(config, "nb_disk", 0);
}
//-------------------------------------------------
@@ -144,72 +187,52 @@ const tiny_rom_entry *nubus_image_device::device_rom_region() const
return ROM_NAME( image );
}
-//**************************************************************************
-// LIVE DEVICE
-//**************************************************************************
-
-//-------------------------------------------------
-// nubus_image_device - constructor
-//-------------------------------------------------
-
-nubus_image_device::nubus_image_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) :
+nubus_image_device::nubus_image_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock) :
nubus_image_device(mconfig, NUBUS_IMAGE, tag, owner, clock)
{
}
-nubus_image_device::nubus_image_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock) :
+nubus_image_device::nubus_image_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_image(nullptr)
{
}
-//-------------------------------------------------
-// device_start - device-specific startup
-//-------------------------------------------------
-
-void nubus_image_device::device_start()
+void nubus_image_device::card_map(address_map &map)
{
- uint32_t slotspace;
- uint32_t superslotspace;
-
- install_declaration_rom(this, IMAGE_ROM_REGION);
-
- slotspace = get_slotspace();
- superslotspace = get_super_slotspace();
-
-// printf("[image %p] slotspace = %x, super = %x\n", this, slotspace, superslotspace);
-
- nubus().install_device(slotspace, slotspace+3, read32_delegate(FUNC(nubus_image_device::image_r), this), write32_delegate(FUNC(nubus_image_device::image_w), this));
- nubus().install_device(slotspace+4, slotspace+7, read32_delegate(FUNC(nubus_image_device::image_status_r), this), write32_delegate(FUNC(nubus_image_device::image_status_w), this));
- nubus().install_device(slotspace+8, slotspace+11, read32_delegate(FUNC(nubus_image_device::file_cmd_r), this), write32_delegate(FUNC(nubus_image_device::file_cmd_w), this));
- nubus().install_device(slotspace+12, slotspace+15, read32_delegate(FUNC(nubus_image_device::file_data_r), this), write32_delegate(FUNC(nubus_image_device::file_data_w), this));
- nubus().install_device(slotspace+16, slotspace+19, read32_delegate(FUNC(nubus_image_device::file_len_r), this), write32_delegate(FUNC(nubus_image_device::file_len_w), this));
- nubus().install_device(slotspace+20, slotspace+147, read32_delegate(FUNC(nubus_image_device::file_name_r), this), write32_delegate(FUNC(nubus_image_device::file_name_w), this));
- nubus().install_device(superslotspace, superslotspace+((256*1024*1024)-1), read32_delegate(FUNC(nubus_image_device::image_super_r), this), write32_delegate(FUNC(nubus_image_device::image_super_w), this));
-
- m_image = subdevice<messimg_disk_image_device>(IMAGE_DISK0_TAG);
-
- filectx.curdir[0] = '.';
- filectx.curdir[1] = '\0';
- filectx.dirp = nullptr;
- filectx.fd = nullptr;
+ map(0x0000, 0x0003).rw(FUNC(nubus_image_device::image_r), FUNC(nubus_image_device::image_w));
+ map(0x0004, 0x0007).rw(FUNC(nubus_image_device::image_status_r), FUNC(nubus_image_device::image_status_w));
+ map(0x0008, 0x000b).rw(FUNC(nubus_image_device::file_cmd_r), FUNC(nubus_image_device::file_cmd_w));
+ map(0x000c, 0x000f).rw(FUNC(nubus_image_device::file_data_r), FUNC(nubus_image_device::file_data_w));
+ map(0x0010, 0x0013).rw(FUNC(nubus_image_device::file_len_r), FUNC(nubus_image_device::file_len_w));
+ map(0x0014, 0x009b).rw(FUNC(nubus_image_device::file_name_r), FUNC(nubus_image_device::file_name_w));
}
-//-------------------------------------------------
-// device_reset - device-specific reset
-//-------------------------------------------------
+void nubus_image_device::card_super_map(address_map &map)
+{
+ map(0x0000'0000, 0x0fff'ffff).rw(FUNC(nubus_image_device::image_super_r), FUNC(nubus_image_device::image_super_w));
+}
-void nubus_image_device::device_reset()
+void nubus_image_device::device_start()
{
+ install_declaration_rom("declrom");
+ nubus().install_map(*this, &nubus_image_device::card_map);
+ nubus().install_super_map(*this, &nubus_image_device::card_super_map);
+
+ m_image = subdevice<mameimg_disk_image_device>("nb_disk");
+
+ filectx.curdir = ".";
+ filectx.dirp.reset();
+ filectx.fd.reset();
}
-WRITE32_MEMBER( nubus_image_device::image_status_w )
+void nubus_image_device::image_status_w(u32 data)
{
m_image->m_ejected = true;
}
-READ32_MEMBER( nubus_image_device::image_status_r )
+u32 nubus_image_device::image_status_r()
{
if(m_image->m_ejected) {
return 0;
@@ -221,101 +244,98 @@ READ32_MEMBER( nubus_image_device::image_status_r )
return 0;
}
-WRITE32_MEMBER( nubus_image_device::image_w )
+void nubus_image_device::image_w(u32 data)
{
}
-READ32_MEMBER( nubus_image_device::image_r )
+u32 nubus_image_device::image_r()
{
return m_image->m_size;
}
-WRITE32_MEMBER( nubus_image_device::image_super_w )
+void nubus_image_device::image_super_w(offs_t offset, u32 data, u32 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);
+ u32 *image = (u32*)m_image->m_data.get();
+ data = swapendian_int32(data);
+ mem_mask = swapendian_int32(mem_mask);
COMBINE_DATA(&image[offset]);
}
-READ32_MEMBER( nubus_image_device::image_super_r )
+u32 nubus_image_device::image_super_r(offs_t offset, u32 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);
+ u32 *image = (u32*)m_image->m_data.get();
+ return swapendian_int32(image[offset]);
}
-WRITE32_MEMBER( nubus_image_device::file_cmd_w )
+void nubus_image_device::file_cmd_w(u32 data)
{
-// data = ((data & 0xff) << 24) | ((data & 0xff00) << 8) | ((data & 0xff0000) >> 8) | ((data & 0xff000000) >> 24);
filectx.curcmd = data;
- switch(data) {
+ switch (data) {
case kFileCmdGetDir:
- strcpy((char*)filectx.filename, (char*)filectx.curdir);
+ strncpy(filectx.filename, filectx.curdir.c_str(), std::size(filectx.filename));
break;
case kFileCmdSetDir:
if ((filectx.filename[0] == '/') || (filectx.filename[0] == '$')) {
- strcpy((char*)filectx.curdir, (char*)filectx.filename);
+ filectx.curdir.assign(std::begin(filectx.filename), std::find(std::begin(filectx.filename), std::end(filectx.filename), '\0'));
} else {
- strcat((char*)filectx.curdir, "/");
- strcat((char*)filectx.curdir, (char*)filectx.filename);
+ filectx.curdir += '/';
+ filectx.curdir.append(std::begin(filectx.filename), std::find(std::begin(filectx.filename), std::end(filectx.filename), '\0'));
}
break;
case kFileCmdGetFirstListing:
- filectx.dirp = osd::directory::open((const char *)filectx.curdir);
+ filectx.dirp = osd::directory::open(filectx.curdir);
+ [[fallthrough]];
case kFileCmdGetNextListing:
if (filectx.dirp) {
osd::directory::entry const *const dp = filectx.dirp->read();
- if(dp) {
- strncpy((char*)filectx.filename, dp->name, sizeof(filectx.filename));
+ if (dp) {
+ strncpy(filectx.filename, dp->name, std::size(filectx.filename));
} else {
- memset(filectx.filename, 0, sizeof(filectx.filename));
+ std::fill(std::begin(filectx.filename), std::end(filectx.filename), '\0');
}
}
else {
- memset(filectx.filename, 0, sizeof(filectx.filename));
+ std::fill(std::begin(filectx.filename), std::end(filectx.filename), '\0');
}
break;
case kFileCmdGetFile:
{
- std::string fullpath;
- fullpath.reserve(1024);
- fullpath.assign((const char *)filectx.curdir);
- fullpath.append(PATH_SEPARATOR);
- fullpath.append((const char*)filectx.filename);
- if(osd_file::open(fullpath, OPEN_FLAG_READ, filectx.fd, filectx.filelen) != osd_file::error::NONE)
- osd_printf_error("Error opening %s\n", fullpath.c_str());
+ std::string fullpath(filectx.curdir);
+ fullpath += PATH_SEPARATOR;
+ fullpath.append(std::begin(filectx.filename), std::find(std::begin(filectx.filename), std::end(filectx.filename), '\0'));
+ std::error_condition const filerr = osd_file::open(fullpath, OPEN_FLAG_READ, filectx.fd, filectx.filelen);
+ if (filerr)
+ osd_printf_error("%s: Error opening %s (%s:%d %s)\n", tag(), fullpath, filerr.category().name(), filerr.value(), filerr.message());
filectx.bytecount = 0;
}
break;
case kFileCmdPutFile:
{
- std::string fullpath;
- fullpath.reserve(1024);
- fullpath.assign((const char *)filectx.curdir);
- fullpath.append(PATH_SEPARATOR);
- fullpath.append((const char*)filectx.filename);
- uint64_t filesize; // unused, but it's an output from the open call
- if(osd_file::open(fullpath, OPEN_FLAG_WRITE|OPEN_FLAG_CREATE, filectx.fd, filesize) != osd_file::error::NONE)
- osd_printf_error("Error opening %s\n", fullpath.c_str());
+ std::string fullpath(filectx.curdir);
+ fullpath += PATH_SEPARATOR;
+ fullpath.append(std::begin(filectx.filename), std::find(std::begin(filectx.filename), std::end(filectx.filename), '\0'));
+ u64 filesize; // unused, but it's an output from the open call
+ std::error_condition const filerr = osd_file::open(fullpath, OPEN_FLAG_WRITE | OPEN_FLAG_CREATE, filectx.fd, filesize);
+ if (filerr)
+ osd_printf_error("%s: Error opening %s (%s:%d %s)\n", tag(), fullpath, filerr.category().name(), filerr.value(), filerr.message());
filectx.bytecount = 0;
}
break;
}
}
-READ32_MEMBER( nubus_image_device::file_cmd_r )
+u32 nubus_image_device::file_cmd_r()
{
return 0;
}
-WRITE32_MEMBER( nubus_image_device::file_data_w )
+void nubus_image_device::file_data_w(u32 data)
{
- std::uint32_t count = 4;
- std::uint32_t actualcount = 0;
+ u32 count = 4;
+ u32 actualcount = 0;
- data = ((data & 0xff) << 24) | ((data & 0xff00) << 8) | ((data & 0xff0000) >> 8) | ((data & 0xff000000) >> 24);
+ data = swapendian_int32(data);
if(filectx.fd) {
//data = big_endianize_int32(data);
if((filectx.bytecount + count) > filectx.filelen) count = filectx.filelen - filectx.bytecount;
@@ -328,11 +348,11 @@ WRITE32_MEMBER( nubus_image_device::file_data_w )
}
}
-READ32_MEMBER( nubus_image_device::file_data_r )
+u32 nubus_image_device::file_data_r()
{
if(filectx.fd) {
- std::uint32_t ret;
- std::uint32_t actual = 0;
+ u32 ret;
+ u32 actual = 0;
filectx.fd->read(&ret, filectx.bytecount, sizeof(ret), actual);
filectx.bytecount += actual;
if(actual < sizeof(ret)) {
@@ -343,25 +363,25 @@ READ32_MEMBER( nubus_image_device::file_data_r )
return 0;
}
-WRITE32_MEMBER( nubus_image_device::file_len_w )
+void nubus_image_device::file_len_w(u32 data)
{
- data = ((data & 0xff) << 24) | ((data & 0xff00) << 8) | ((data & 0xff0000) >> 8) | ((data & 0xff000000) >> 24);
+ data = swapendian_int32(data);
filectx.filelen = big_endianize_int32(data);
}
-READ32_MEMBER( nubus_image_device::file_len_r )
+u32 nubus_image_device::file_len_r()
{
return filectx.filelen;
}
-WRITE32_MEMBER( nubus_image_device::file_name_w )
+void nubus_image_device::file_name_w(offs_t offset, u32 data)
{
- ((uint32_t*)(filectx.filename))[offset] = big_endianize_int32(data);
+ reinterpret_cast<u32 *>(filectx.filename)[offset] = big_endianize_int32(data);
}
-READ32_MEMBER( nubus_image_device::file_name_r )
+u32 nubus_image_device::file_name_r(offs_t offset)
{
- uint32_t ret;
- ret = big_endianize_int32(((uint32_t*)(filectx.filename))[offset]);
- return ret;
+ return big_endianize_int32(reinterpret_cast<u32 const *>(filectx.filename)[offset]);
}
+
+DEFINE_DEVICE_TYPE_PRIVATE(NUBUS_IMAGE, device_nubus_card_interface, nubus_image_device, "nb_image", "NuBus Disk Image Pseudo-Card")
diff --git a/src/devices/bus/nubus/nubus_image.h b/src/devices/bus/nubus/nubus_image.h
index b2185f14d0f..148a0ebdce3 100644
--- a/src/devices/bus/nubus/nubus_image.h
+++ b/src/devices/bus/nubus/nubus_image.h
@@ -4,79 +4,8 @@
#define MAME_BUS_NUBUS_NUBUS_IMAGE_H
#pragma once
-
#include "nubus.h"
-#include "osdcore.h"
-
-//**************************************************************************
-// TYPE DEFINITIONS
-//**************************************************************************
-
-// ======================> nubus_image_device
-
-class nubus_image_device :
- public device_t,
- public device_nubus_card_interface
-{
-public:
- class messimg_disk_image_device;
-
- // construction/destruction
- nubus_image_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
-
-protected:
- enum
- {
- kFileCmdGetDir = 1,
- kFileCmdSetDir,
- kFileCmdGetFirstListing,
- kFileCmdGetNextListing,
- kFileCmdGetFile,
- kFileCmdPutFile
- };
-
- struct nbfilectx
- {
- uint32_t curcmd;
- uint8_t filename[128];
- uint8_t curdir[1024];
- osd::directory::ptr dirp;
- osd_file::ptr fd;
- uint64_t filelen;
- uint32_t bytecount;
- };
-
- nubus_image_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;
-
- DECLARE_READ32_MEMBER(image_status_r);
- DECLARE_WRITE32_MEMBER(image_status_w);
- DECLARE_READ32_MEMBER(image_r);
- DECLARE_WRITE32_MEMBER(image_w);
- DECLARE_READ32_MEMBER(image_super_r);
- DECLARE_WRITE32_MEMBER(image_super_w);
- DECLARE_READ32_MEMBER(file_cmd_r);
- DECLARE_WRITE32_MEMBER(file_cmd_w);
- DECLARE_READ32_MEMBER(file_data_r);
- DECLARE_WRITE32_MEMBER(file_data_w);
- DECLARE_READ32_MEMBER(file_len_r);
- DECLARE_WRITE32_MEMBER(file_len_w);
- DECLARE_READ32_MEMBER(file_name_r);
- DECLARE_WRITE32_MEMBER(file_name_w);
-
- messimg_disk_image_device *m_image;
- nbfilectx filectx;
-};
-
// device type definition
-DECLARE_DEVICE_TYPE(NUBUS_IMAGE, nubus_image_device)
-
+DECLARE_DEVICE_TYPE(NUBUS_IMAGE, device_nubus_card_interface)
#endif // MAME_BUS_NUBUS_NUBUS_IMAGE_H
diff --git a/src/devices/bus/nubus/nubus_m2hires.cpp b/src/devices/bus/nubus/nubus_m2hires.cpp
index c575f7d94b1..8fcf23f9034 100644
--- a/src/devices/bus/nubus/nubus_m2hires.cpp
+++ b/src/devices/bus/nubus/nubus_m2hires.cpp
@@ -2,304 +2,528 @@
// copyright-holders:R. Belmont
/***************************************************************************
- Apple Hi-Resolution Video Card emulation
+ Apple Macintosh II High Resolution Video Card
+ Apple Portrait Card
+ Apple Workstation Card
- RAMDAC: control at Fs0940e0, data at Fs0940e4
- Fs090010 bit 16 is vbl status, bit 17 must be "1" for proper operation
- Fs08000x are the control registers
+ Same hardware, different ROMs, crystals, and speed grades of the Bt453/454.
+ The High Resolution card is intended to drive the color 640x480 13" standard
+ AppleColor High Resolution RGB monitor.
+ The Workstation/Portrait card was sold in two configurations: as the Portrait
+ card to drive the 640x870 15" Portrait monochrome monitor, and as the
+ Workstation card to drive the 1152x870 21" monochrome monitor.
+
+ Video ASIC for High Resolution and Portrait is TFB 2.2, Apple part number 344S0077
+ Video ASIC for Workstation is TFB 2.0, Apple part number 344S0013
+ RAMDAC is Bt453 for Mac II Hi-Res, Bt454 for Workstation and Portrait
***************************************************************************/
#include "emu.h"
+
#include "nubus_m2hires.h"
+#include "video/bt45x.h"
+
#include "screen.h"
-#define M2HIRES_SCREEN_NAME "m2hires_screen"
-#define M2HIRES_ROM_REGION "m2hires_rom"
+#include <algorithm>
-#define VRAM_SIZE (0x80000) // 512k max
+#define LOG_REGISTERS (1U << 1)
+#define LOG_CRTC (1U << 2)
+#define VERBOSE (0)
-ROM_START( m2hires )
- ROM_REGION(0x2000, M2HIRES_ROM_REGION, 0)
- ROM_LOAD( "341-0660.bin", 0x0000, 0x2000, CRC(ea6f7913) SHA1(37c59f38ae34021d0cb86c2e76a598b7e6077c0d) )
-ROM_END
+#include "logmacro.h"
-//**************************************************************************
-// GLOBAL VARIABLES
-//**************************************************************************
+namespace {
-DEFINE_DEVICE_TYPE(NUBUS_M2HIRES, nubus_m2hires_device, "nb_m2hr", "Macintosh II Hi-Resolution video card")
+enum
+{
+ BASE = 0, // Offset to start drawing from the base of VRAM, in 32-bit words
+ LENGTH, // Stride of each scanline, in 32-bit words
+ MISC, // A whole bunch of random small parameters, including the pixel depth
+ SYNCINTERVAL, // Time from the middle of the scanline to the rising edge of the RS170 composite sync vertical serration
+ VFRONTPORCH, // V front porch length, minus 1
+ VBACKPORCH, // V back porch length, minus 8
+ VLINES, // Total visible half-lines, minus 1
+ HFRONTPORCH, // Front porch in pixel clocks, minus 2
+ HSYNCPULSE, // H sync pulse width in pixel clocks, minus 4
+ HBACKPORCH, // Back porch in pixel clocks, minus 4
+ HFIRST, // First section of visible area, minus 2
+ HLAST, // Second section of visible area, minus 2
+ SOFTRESET, // Bit 0 = 1 to enable video generation
+};
+
+static constexpr u32 VRAM_SIZE = 0x80000; // 512k max
+
+class nubus_m2hires_device : public device_t,
+ public device_video_interface,
+ public device_nubus_card_interface
+{
+public:
+ // construction/destruction
+ nubus_m2hires_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock);
+protected:
+ nubus_m2hires_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, u32 clock);
-//-------------------------------------------------
-// device_add_mconfig - add device configuration
-//-------------------------------------------------
+ // device-level overrides
+ virtual void device_start() override ATTR_COLD;
+ virtual void device_reset() override ATTR_COLD;
-void nubus_m2hires_device::device_add_mconfig(machine_config &config)
+ // optional information overrides
+ virtual void device_add_mconfig(machine_config &config) override ATTR_COLD;
+ virtual const tiny_rom_entry *device_rom_region() const override ATTR_COLD;
+
+ TIMER_CALLBACK_MEMBER(vbl_tick);
+
+ void card_map(address_map &map);
+
+ virtual u32 vblank_r(offs_t offset, u32 mem_mask = ~0);
+ virtual void ramdac_w(offs_t offset, u32 data);
+
+ u32 screen_update(screen_device &screen, bitmap_rgb32 &bitmap, const rectangle &cliprect);
+
+ required_device<screen_device> m_screen;
+ required_device<bt45x_rgb_device_base> m_ramdac;
+
+ std::vector<u32> m_vram;
+ u32 m_htotal, m_hres, m_vtotal, m_vres, m_mode;
+ int m_bt_type;
+ XTAL m_pclock;
+
+private:
+ void registers_w(offs_t offset, u32 data, u32 mem_mask = ~0);
+ void vbl_w(offs_t offset, u8 data);
+ u32 vram_r(offs_t offset, u32 mem_mask = ~0);
+ void vram_w(offs_t offset, u32 data, u32 mem_mask = ~0);
+
+ u32 m_vbl_disable;
+ u32 m_registers[0x10];
+ emu_timer *m_timer;
+};
+
+void nubus_m2hires_device::card_map(address_map &map)
{
- screen_device &screen(SCREEN(config, M2HIRES_SCREEN_NAME, SCREEN_TYPE_RASTER));
- screen.set_screen_update(FUNC(nubus_m2hires_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);
+ map(0x00'0000, 0x07'ffff).rw(FUNC(nubus_m2hires_device::vram_r), FUNC(nubus_m2hires_device::vram_w)).mirror(0xf00000);
+ map(0x08'0000, 0x08'ffff).w(FUNC(nubus_m2hires_device::registers_w)).mirror(0xf00000);
+ map(0x09'0000, 0x09'ffff).rw(FUNC(nubus_m2hires_device::vblank_r), FUNC(nubus_m2hires_device::ramdac_w)).mirror(0xf00000);
+ map(0x0a'0000, 0x0a'ffff).w(FUNC(nubus_m2hires_device::vbl_w)).umask32(0xffffffff).mirror(0xf00000);
}
-//-------------------------------------------------
-// rom_region - device-specific ROM region
-//-------------------------------------------------
+ROM_START( m2hires )
+ ROM_REGION(0x2000, "declrom", 0)
+ ROM_LOAD( "341-0660.bin", 0x0000, 0x2000, CRC(ea6f7913) SHA1(37c59f38ae34021d0cb86c2e76a598b7e6077c0d) )
+ROM_END
+
+void nubus_m2hires_device::device_add_mconfig(machine_config &config)
+{
+ SCREEN(config, m_screen, SCREEN_TYPE_RASTER);
+ m_screen->set_screen_update(FUNC(nubus_m2hires_device::screen_update));
+ m_screen->set_raw(30.24_MHz_XTAL, 896, 0, 640, 525, 0, 480);
+
+ BT453(config, m_ramdac, 0);
+}
const tiny_rom_entry *nubus_m2hires_device::device_rom_region() const
{
return ROM_NAME( m2hires );
}
-//**************************************************************************
-// LIVE DEVICE
-//**************************************************************************
-
-//-------------------------------------------------
-// nubus_m2hires_device - constructor
-//-------------------------------------------------
-
-nubus_m2hires_device::nubus_m2hires_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) :
+nubus_m2hires_device::nubus_m2hires_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock) :
nubus_m2hires_device(mconfig, NUBUS_M2HIRES, tag, owner, clock)
{
}
-nubus_m2hires_device::nubus_m2hires_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock) :
+nubus_m2hires_device::nubus_m2hires_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_vram32(nullptr), m_mode(0), m_vbl_disable(0), m_toggle(0), m_count(0), m_clutoffs(0), m_timer(nullptr)
+ m_screen(*this, "screen"),
+ m_ramdac(*this, "bt453"),
+ m_htotal(896),
+ m_hres(640),
+ m_vtotal(525),
+ m_vres(480),
+ m_mode(0),
+ m_bt_type(453),
+ m_pclock(30.24_MHz_XTAL),
+ m_vbl_disable(0), m_timer(nullptr)
{
- set_screen(*this, M2HIRES_SCREEN_NAME);
+ set_screen(*this, "screen");
}
-//-------------------------------------------------
-// device_start - device-specific startup
-//-------------------------------------------------
-
void nubus_m2hires_device::device_start()
{
- uint32_t slotspace;
-
- install_declaration_rom(this, M2HIRES_ROM_REGION, true);
+ install_declaration_rom("declrom", true);
- slotspace = get_slotspace();
+ m_vram.resize(VRAM_SIZE / sizeof(u32));
-// logerror("[m2hires %p] slotspace = %x\n", this, slotspace);
+ nubus().install_map(*this, &nubus_m2hires_device::card_map);
- m_vram.resize(VRAM_SIZE);
- m_vram32 = (uint32_t *)&m_vram[0];
+ save_item(NAME(m_vbl_disable));
+ save_item(NAME(m_registers));
+ save_item(NAME(m_htotal));
+ save_item(NAME(m_hres));
+ save_item(NAME(m_vtotal));
+ save_item(NAME(m_vres));
+ save_item(NAME(m_mode));
- nubus().install_device(slotspace, slotspace+VRAM_SIZE-1, read32_delegate(FUNC(nubus_m2hires_device::vram_r), this), write32_delegate(FUNC(nubus_m2hires_device::vram_w), this));
- nubus().install_device(slotspace+0x900000, slotspace+VRAM_SIZE-1+0x900000, read32_delegate(FUNC(nubus_m2hires_device::vram_r), this), write32_delegate(FUNC(nubus_m2hires_device::vram_w), this));
- nubus().install_device(slotspace+0x80000, slotspace+0xeffff, read32_delegate(FUNC(nubus_m2hires_device::m2hires_r), this), write32_delegate(FUNC(nubus_m2hires_device::m2hires_w), this));
-
- m_timer = timer_alloc(0, nullptr);
+ m_timer = timer_alloc(FUNC(nubus_m2hires_device::vbl_tick), this);
m_timer->adjust(screen().time_until_pos(479, 0), 0);
}
-//-------------------------------------------------
-// device_reset - device-specific reset
-//-------------------------------------------------
-
void nubus_m2hires_device::device_reset()
{
- m_count = 0;
- m_clutoffs = 0;
m_vbl_disable = 1;
- m_mode = 0;
- memset(&m_vram[0], 0, VRAM_SIZE);
- memset(m_palette, 0, sizeof(m_palette));
-
- m_palette[0] = rgb_t(255, 255, 255);
- m_palette[0x80] = rgb_t(0, 0, 0);
+ std::fill(m_vram.begin(), m_vram.end(), 0);
}
-
-void nubus_m2hires_device::device_timer(emu_timer &timer, device_timer_id tid, int param, void *ptr)
+TIMER_CALLBACK_MEMBER(nubus_m2hires_device::vbl_tick)
{
if (!m_vbl_disable)
{
raise_slot_irq();
}
- m_timer->adjust(screen().time_until_pos(479, 0), 0);
+ m_timer->adjust(screen().time_until_pos(m_vres - 1, 0), 0);
}
-/***************************************************************************
-
- Spectrum 24 PDQ section
-
-***************************************************************************/
-
-uint32_t nubus_m2hires_device::screen_update(screen_device &screen, bitmap_rgb32 &bitmap, const rectangle &cliprect)
+u32 nubus_m2hires_device::screen_update(screen_device &screen, bitmap_rgb32 &bitmap, const rectangle &cliprect)
{
- uint32_t *scanline;
- int x, y;
- uint8_t pixels, *vram;
+ if (!BIT(m_registers[SOFTRESET], 0))
+ {
+ bitmap.fill(0, cliprect);
+ return 0;
+ }
- vram = &m_vram[0x20];
+ auto const vram8 = util::big_endian_cast<u8 const>(&m_vram[0]) + ((m_registers[BASE] & 0x1ffff) << 2);
+ pen_t const *const pens = m_ramdac->pens();
+ const u32 stride = (m_registers[LENGTH] & 0x3ff) << 2;
switch (m_mode)
{
- case 0: // 1 bpp?
- for (y = 0; y < 480; y++)
+ case 0: // 1 bpp
+ for (int y = 0; y < m_vres; y++)
{
- scanline = &bitmap.pix32(y);
- for (x = 0; x < 640/8; x++)
+ u32 *scanline = &bitmap.pix(y);
+ for (int x = 0; x < m_hres/8; x++)
{
- pixels = vram[(y * 128) + (BYTE4_XOR_BE(x))];
-
- *scanline++ = m_palette[((pixels>>7)&0x1)];
- *scanline++ = m_palette[((pixels>>6)&0x1)];
- *scanline++ = m_palette[((pixels>>5)&0x1)];
- *scanline++ = m_palette[((pixels>>4)&0x1)];
- *scanline++ = m_palette[((pixels>>3)&0x1)];
- *scanline++ = m_palette[((pixels>>2)&0x1)];
- *scanline++ = m_palette[((pixels>>1)&0x1)];
- *scanline++ = m_palette[(pixels&1)];
+ u8 const pixels = vram8[(y * stride) + 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 (y = 0; y < 480; y++)
+ for (int y = 0; y < m_vres; y++)
{
- scanline = &bitmap.pix32(y);
- for (x = 0; x < 640/4; x++)
+ u32 *scanline = &bitmap.pix(y);
+ for (int x = 0; x < m_hres/4; x++)
{
- pixels = vram[(y * 256) + (BYTE4_XOR_BE(x))];
+ u8 const pixels = vram8[(y * stride) + 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 (y = 0; y < 480; y++)
+ for (int y = 0; y < m_vres; y++)
{
- scanline = &bitmap.pix32(y);
+ u32 *scanline = &bitmap.pix(y);
- for (x = 0; x < 640/2; x++)
+ for (int x = 0; x < m_hres/2; x++)
{
- pixels = vram[(y * 512) + (BYTE4_XOR_BE(x))];
+ u8 const pixels = vram8[(y * stride) + x];
- *scanline++ = m_palette[((pixels&0xf0)>>4)];
- *scanline++ = m_palette[(pixels&0xf)];
+ *scanline++ = pens[((pixels&0xf0)>>4)];
+ *scanline++ = pens[(pixels&0xf)];
}
}
break;
case 3: // 8 bpp
- for (y = 0; y < 480; y++)
+ for (int y = 0; y < m_vres; y++)
{
- scanline = &bitmap.pix32(y);
+ u32 *scanline = &bitmap.pix(y);
- for (x = 0; x < 640; x++)
+ for (int x = 0; x < m_hres; x++)
{
- pixels = vram[(y * 1024) + (BYTE4_XOR_BE(x))];
- *scanline++ = m_palette[pixels];
+ *scanline++ = pens[vram8[(y * stride) + x]];
}
}
break;
-
- default:
- fatalerror("m2hires: unknown video mode %d\n", m_mode);
}
return 0;
}
-WRITE32_MEMBER( nubus_m2hires_device::m2hires_w )
+void nubus_m2hires_device::registers_w(offs_t offset, u32 data, u32 mem_mask)
{
data ^= 0xffffffff;
+ data = swapendian_int32(data);
- switch (offset)
+ LOGMASKED(LOG_REGISTERS, "%s: %08x @ %x, mask %08x %s\n", tag(), data, offset, mem_mask, machine().describe_context());
+ m_registers[offset] = data;
+
+ if (offset == BASE && BIT(m_registers[SOFTRESET], 0))
{
- case 1: // mode
- switch (data)
+ const u32 mode = (m_registers[MISC] >> 8) & 7;
+ if (m_bt_type == 453)
+ {
+ m_mode = mode - 4;
+ }
+ else if (m_bt_type == 454)
+ {
+ switch (mode)
{
- case 0x20000000:
- m_mode = 0;
- break;
-
- case 0x40000000:
- m_mode = 1;
- break;
+ case 0: // 4 bpp
+ m_mode = 2;
+ break;
- case 0x80000000:
- m_mode = 2;
- break;
+ case 2: // 1 bpp
+ m_mode = 0;
+ break;
- case 0x00010000:
- m_mode = 3;
- break;
+ case 3: // 2 bpp
+ m_mode = 1;
+ break;
}
- break;
+ }
- case 0x5038: // DAC control
-// logerror("%08x to DAC control %s\n", data, machine().describe_context());
- m_clutoffs = (data>>24)&0xff;
- break;
+ const int hmult = (16 >> m_mode);
- case 0x5039: // DAC data
- m_colors[m_count++] = (data>>24) & 0xff;
+ m_htotal = ((m_registers[HFRONTPORCH] + 2) +
+ (m_registers[HSYNCPULSE] + 2) +
+ (m_registers[HBACKPORCH] + 4) +
+ (m_registers[HFIRST] + 2) +
+ (m_registers[HLAST] + 2)) * hmult;
- 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[0], m_colors[1], m_colors[2]);
- m_clutoffs++;
- if (m_clutoffs > 255)
- {
- m_clutoffs = 0;
- }
- m_count = 0;
- }
- break;
+ m_vtotal = ((m_registers[VFRONTPORCH] + 1) +
+ (m_registers[VBACKPORCH] + 8) +
+ (m_registers[VLINES] + 1)) / 2;
+ m_vtotal += 3;
- case 0x8000: // enable and ack VBL
- m_vbl_disable = 0;
- lower_slot_irq();
- break;
+ m_vres = (m_registers[VLINES] / 2) + 1;
+ m_hres = (m_registers[HFIRST] + 2 + m_registers[HLAST] + 2) * hmult;
- case 0x8001: // disable VBL
- m_vbl_disable = 1;
- break;
+ LOGMASKED(LOG_CRTC, "htotal %d vtotal %d hres %d vres %d\n", m_htotal, m_vtotal, m_hres, m_vres);
- default:
-// logerror("m2hires_w: %08x @ %x, mask %08x %s\n", data, offset, mem_mask, machine().describe_context());
- break;
+ 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_pclock).as_attoseconds());
+ }
+}
+
+void nubus_m2hires_device::ramdac_w(offs_t offset, u32 data)
+{
+ data ^= 0xffffffff;
+ switch (offset & 1)
+ {
+ case 0:
+ m_ramdac->address_w(data);
+ break;
+
+ case 1:
+ m_ramdac->palette_w(data);
+ break;
+ }
+}
+
+u32 nubus_m2hires_device::vblank_r(offs_t offset, u32 mem_mask)
+{
+ if (offset == 0x10/4)
+ {
+ return (m_screen->vblank() << 16) | (1<<17); // monitor ID bits in 17-20, but inverted
}
+ return 0;
}
-READ32_MEMBER( nubus_m2hires_device::m2hires_r )
+void nubus_m2hires_device::vbl_w(offs_t offset, u8 data)
{
- if (offset == 0x10010/4)
+ if (offset & 4)
+ {
+ m_vbl_disable = 1;
+ }
+ else
{
- m_toggle ^= (1<<16);
- return m_toggle | (1<<17); // bit 17 indicates a 4/8bpp capable ASIC apparently; the firmware won't enter those modes otherwise (although they show in the list)
+ m_vbl_disable = 0;
+ lower_slot_irq();
+ }
+}
+
+void nubus_m2hires_device::vram_w(offs_t offset, u32 data, u32 mem_mask)
+{
+ data ^= 0xffffffff;
+ COMBINE_DATA(&m_vram[offset]);
+}
+
+u32 nubus_m2hires_device::vram_r(offs_t offset, u32 mem_mask)
+{
+ return m_vram[offset] ^ 0xffffffff;
+}
+
+// ***************** Portrait Card support *****************
+
+class nubus_portrait_device : public nubus_m2hires_device
+{
+public:
+ nubus_portrait_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock)
+ : nubus_m2hires_device(mconfig, NUBUS_WSPORTRAIT, tag, owner, clock),
+ m_color_index(0)
+ {
+ }
+
+protected:
+ nubus_portrait_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, u32 clock);
+
+ virtual void device_add_mconfig(machine_config &config) override ATTR_COLD;
+ virtual const tiny_rom_entry *device_rom_region() const override ATTR_COLD;
+ virtual void device_start() override ATTR_COLD;
+
+ virtual u32 vblank_r(offs_t offset, u32 mem_mask = ~0) override;
+ virtual void ramdac_w(offs_t offset, u32 data) override;
+
+private:
+ u8 m_color_index;
+};
+
+void nubus_portrait_device::device_add_mconfig(machine_config &config)
+{
+ SCREEN(config, m_screen, SCREEN_TYPE_RASTER);
+ m_screen->set_screen_update(FUNC(nubus_portrait_device::screen_update));
+ m_screen->set_raw(57.2832_MHz_XTAL, 832, 0, 640, 918, 0, 832);
+ m_screen->set_physical_aspect(3, 4);
+
+ BT454(config, m_ramdac, 0);
+}
+
+ROM_START(wsportrait)
+ ROM_REGION(0x1000, "declrom", 0)
+ ROM_LOAD("341-0732.bin", 0x000000, 0x001000, CRC(ddc35b78) SHA1(ce2bf2374bb994c17962dba8f3d11bc1260e2644))
+ROM_END
+
+const tiny_rom_entry *nubus_portrait_device::device_rom_region() const
+{
+ return ROM_NAME(wsportrait);
+}
+
+nubus_portrait_device::nubus_portrait_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, u32 clock) :
+ nubus_m2hires_device(mconfig, type, tag, owner, clock)
+{
+}
+
+void nubus_portrait_device::device_start()
+{
+ nubus_m2hires_device::device_start();
+ save_item(NAME(m_color_index));
+
+ m_pclock = 57.2832_MHz_XTAL;
+ m_bt_type = 454;
+}
+
+u32 nubus_portrait_device::vblank_r(offs_t offset, u32 mem_mask)
+{
+ if (offset == 0x10 / 4)
+ {
+ return (m_screen->vblank() << 16) | (6 << 17);
}
-/* else
- {
- logerror("m2hires_r: @ %x, mask %08x %s\n", offset, mem_mask, machine().describe_context());
- }*/
return 0;
}
-WRITE32_MEMBER( nubus_m2hires_device::vram_w )
+void nubus_portrait_device::ramdac_w(offs_t offset, u32 data)
{
data ^= 0xffffffff;
- COMBINE_DATA(&m_vram32[offset]);
+ data >>= 24;
+ switch (offset & 1)
+ {
+ case 0:
+ m_ramdac->address_w(data);
+ m_color_index = 0;
+ break;
+
+ case 1:
+ if (m_color_index == 2)
+ {
+ m_ramdac->palette_w(data);
+ m_ramdac->palette_w(data);
+ m_ramdac->palette_w(data);
+ m_color_index = 0;
+ }
+ else
+ {
+ m_color_index++;
+ }
+ break;
+ }
}
-READ32_MEMBER( nubus_m2hires_device::vram_r )
+// ***************** Workstation Card support *****************
+
+class nubus_workstation_device : public nubus_portrait_device
{
- return m_vram32[offset] ^ 0xffffffff;
+public:
+ nubus_workstation_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock) :
+ nubus_portrait_device(mconfig, NUBUS_WORKSTATION, tag, owner, clock)
+ {
+ }
+
+protected:
+ virtual void device_start() override ATTR_COLD;
+ virtual void device_add_mconfig(machine_config &config) override ATTR_COLD;
+ virtual const tiny_rom_entry *device_rom_region() const override ATTR_COLD;
+
+ virtual u32 vblank_r(offs_t offset, u32 mem_mask = ~0) override;
+};
+
+ROM_START(workstation)
+ ROM_REGION(0x1000, "declrom", 0)
+ ROM_LOAD("341-0245a.bin", 0x000000, 0x001000, CRC(aff72693) SHA1(697412843cfd56be2b382f8952ef3f5a8323066a))
+ROM_END
+
+ const tiny_rom_entry *nubus_workstation_device::device_rom_region() const
+ {
+ return ROM_NAME(workstation);
+ }
+
+void nubus_workstation_device::device_add_mconfig(machine_config &config)
+{
+ SCREEN(config, m_screen, SCREEN_TYPE_RASTER);
+ m_screen->set_screen_update(FUNC(nubus_workstation_device::screen_update));
+ m_screen->set_raw(100_MHz_XTAL, 1448, 0, 1152, 913, 0, 832);
+
+ BT454(config, m_ramdac, 0);
+}
+
+void nubus_workstation_device::device_start()
+{
+ nubus_portrait_device::device_start();
+ m_pclock = 100_MHz_XTAL;
+}
+
+u32 nubus_workstation_device::vblank_r(offs_t offset, u32 mem_mask)
+{
+ if (offset == 0x10 / 4)
+ {
+ return (m_screen->vblank() << 16) | (7 << 17);
+ }
+
+ return 0;
}
+
+} // anonymous namespace
+
+DEFINE_DEVICE_TYPE_PRIVATE(NUBUS_M2HIRES, device_nubus_card_interface, nubus_m2hires_device, "nb_m2hr", "Apple Macintosh II High Resolution Video Card")
+DEFINE_DEVICE_TYPE_PRIVATE(NUBUS_WSPORTRAIT, device_nubus_card_interface, nubus_portrait_device, "nb_wspt", "Macintosh II Portrait Video Card")
+DEFINE_DEVICE_TYPE_PRIVATE(NUBUS_WORKSTATION, device_nubus_card_interface, nubus_workstation_device, "nb_wkstn", "Macintosh II Workstation Video Card")
diff --git a/src/devices/bus/nubus/nubus_m2hires.h b/src/devices/bus/nubus/nubus_m2hires.h
index 339cf8ed00f..7490ee0072e 100644
--- a/src/devices/bus/nubus/nubus_m2hires.h
+++ b/src/devices/bus/nubus/nubus_m2hires.h
@@ -7,49 +7,8 @@
#include "nubus.h"
-//**************************************************************************
-// TYPE DEFINITIONS
-//**************************************************************************
-
-// ======================> nubus_m2hires_device
-
-class nubus_m2hires_device :
- public device_t,
- public device_video_interface,
- public device_nubus_card_interface
-{
-public:
- // construction/destruction
- nubus_m2hires_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
-
-protected:
- nubus_m2hires_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_timer(emu_timer &timer, device_timer_id id, int param, void *ptr) override;
-
- // optional information overrides
- virtual void device_add_mconfig(machine_config &config) override;
- virtual const tiny_rom_entry *device_rom_region() const override;
-
-private:
- DECLARE_READ32_MEMBER(m2hires_r);
- DECLARE_WRITE32_MEMBER(m2hires_w);
- DECLARE_READ32_MEMBER(vram_r);
- DECLARE_WRITE32_MEMBER(vram_w);
-
- uint32_t screen_update(screen_device &screen, bitmap_rgb32 &bitmap, const rectangle &cliprect);
-
- std::vector<uint8_t> m_vram;
- uint32_t *m_vram32;
- 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_M2HIRES, nubus_m2hires_device)
+DECLARE_DEVICE_TYPE(NUBUS_M2HIRES, device_nubus_card_interface)
+DECLARE_DEVICE_TYPE(NUBUS_WSPORTRAIT, device_nubus_card_interface)
+DECLARE_DEVICE_TYPE(NUBUS_WORKSTATION, device_nubus_card_interface)
#endif // MAME_BUS_NUBUS_NUBUS_M2HIRES_H
diff --git a/src/devices/bus/nubus/nubus_m2video.cpp b/src/devices/bus/nubus/nubus_m2video.cpp
index b16391b640d..7cdb49ca198 100644
--- a/src/devices/bus/nubus/nubus_m2video.cpp
+++ b/src/devices/bus/nubus/nubus_m2video.cpp
@@ -4,124 +4,166 @@
Apple Macintosh II Video Card (630-0153) emulation
- Video ASIC is "TFB" 344-0001
- RAMDAC is Bt453: control at Fs09001C, data at Fs090018
- Fs08000x is general framebuffer control (video mode at 0)
- Fs0D0000 bit 0 is VBL status
+ Video ASIC is TFB 1.x, 344-0001
+ RAMDAC is Bt453
-***************************************************************************/
+ ***************************************************************************/
#include "emu.h"
#include "nubus_m2video.h"
+
+#include "video/bt45x.h"
+
#include "screen.h"
+#include <algorithm>
-#define M2VIDEO_SCREEN_NAME "m2video_screen"
-#define M2VIDEO_ROM_REGION "m2video_rom"
+#define LOG_REGISTERS (1U << 1)
+#define LOG_CRTC (1U << 2)
-#define VRAM_SIZE (0x80000) // 512k max
+#define VERBOSE (0)
+#include "logmacro.h"
+namespace {
-ROM_START( m2video )
- ROM_REGION(0x1000, M2VIDEO_ROM_REGION, 0)
- ROM_LOAD( "342-0008-a.bin", 0x000000, 0x001000, CRC(bf50850d) SHA1(abe85d8a882bb2b8187a28bd6707fc2f5d77eedd) )
-ROM_END
+enum
+{
+ LENGTH,
+ MISC,
+ BASEHI,
+ BASELO,
+ SYNCINTERVAL, // 10
+ VLINES_VPP, // 14
+ VLINES, // 18
+ VBACKPORCH, // 1c
+ SYNCINTERVAL8,
+ HSYNCSTART,
+ HSYNCFINISH,
+ HALFLINE_EARLY,
+ HALFLINE,
+ HPIXELS_HLATE,
+ HPIXELS,
+ MISC2
+};
+
+static constexpr u32 VRAM_SIZE = 0x80000; // 512k max
+
+class nubus_m2video_device : public device_t,
+ public device_video_interface,
+ public device_nubus_card_interface
+{
+public:
+ // construction/destruction
+ nubus_m2video_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock);
-//**************************************************************************
-// GLOBAL VARIABLES
-//**************************************************************************
+protected:
+ nubus_m2video_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, u32 clock);
-DEFINE_DEVICE_TYPE(NUBUS_M2VIDEO, nubus_m2video_device, "nb_m2vc", "Macintosh II Video Card")
+ // device-level overrides
+ virtual void device_start() override ATTR_COLD;
+ virtual void device_reset() override ATTR_COLD;
+ // optional information overrides
+ virtual void device_add_mconfig(machine_config &config) override ATTR_COLD;
+ virtual const tiny_rom_entry *device_rom_region() const override ATTR_COLD;
-//-------------------------------------------------
-// device_add_mconfig - add device configuration
-//-------------------------------------------------
+ TIMER_CALLBACK_MEMBER(vbl_tick);
-void nubus_m2video_device::device_add_mconfig(machine_config &config)
+private:
+ u8 vbl_r(offs_t offset);
+ void vbl_w(offs_t offset, u8 data);
+ u8 ramdac_r(offs_t offset);
+ void ramdac_w(offs_t offset, u8 data);
+ void tfb_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);
+
+ void calc_screen_params();
+
+ u32 screen_update(screen_device &screen, bitmap_rgb32 &bitmap, const rectangle &cliprect);
+
+ void card_map(address_map &map);
+
+ required_device<screen_device> m_screen;
+ required_device<bt453_device> m_ramdac;
+
+ std::unique_ptr<u32[]> m_vram;
+ u32 m_mode, m_vbl_disable;
+ u32 m_htotal, m_hres, m_vtotal, m_vres;
+ u8 m_regs[0x10];
+ emu_timer *m_timer;
+};
+
+ROM_START( m2video )
+ ROM_REGION(0x1000, "declrom", 0)
+ ROM_LOAD( "342-0008-a.bin", 0x000000, 0x001000, CRC(bf50850d) SHA1(abe85d8a882bb2b8187a28bd6707fc2f5d77eedd) )
+ROM_END
+
+void nubus_m2video_device::card_map(address_map &map)
{
- screen_device &screen(SCREEN(config, M2VIDEO_SCREEN_NAME, SCREEN_TYPE_RASTER));
- screen.set_screen_update(FUNC(nubus_m2video_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);
+ map(0x00'0000, 0x07'ffff).rw(FUNC(nubus_m2video_device::vram_r), FUNC(nubus_m2video_device::vram_w)).mirror(0xf00000);
+ map(0x08'0000, 0x08'ffff).w(FUNC(nubus_m2video_device::tfb_w)).mirror(0xf00000);
+ map(0x09'0000, 0x09'001f).rw(FUNC(nubus_m2video_device::ramdac_r), FUNC(nubus_m2video_device::ramdac_w)).umask32(0xff000000).mirror(0xf00000);
+ map(0x0a'0000, 0x0a'ffff).w(FUNC(nubus_m2video_device::vbl_w)).umask32(0xffffffff).mirror(0xf00000);
+ map(0x0d'0000, 0x0d'ffff).r(FUNC(nubus_m2video_device::vbl_r)).umask32(0x000000ff).mirror(0xf00000);
}
-//-------------------------------------------------
-// rom_region - device-specific ROM region
-//-------------------------------------------------
+void nubus_m2video_device::device_add_mconfig(machine_config &config)
+{
+ SCREEN(config, m_screen, SCREEN_TYPE_RASTER);
+ m_screen->set_screen_update(FUNC(nubus_m2video_device::screen_update));
+ m_screen->set_raw(25175000, 800, 0, 640, 525, 0, 480);
+
+ BT453(config, m_ramdac, 0);
+}
const tiny_rom_entry *nubus_m2video_device::device_rom_region() const
{
return ROM_NAME( m2video );
}
-//**************************************************************************
-// LIVE DEVICE
-//**************************************************************************
-
-//-------------------------------------------------
-// nubus_m2video_device - constructor
-//-------------------------------------------------
-
-nubus_m2video_device::nubus_m2video_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) :
+nubus_m2video_device::nubus_m2video_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock) :
nubus_m2video_device(mconfig, NUBUS_M2VIDEO, tag, owner, clock)
{
}
-nubus_m2video_device::nubus_m2video_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock) :
+nubus_m2video_device::nubus_m2video_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_vram32(nullptr), m_mode(0), m_vbl_disable(0), m_toggle(0), m_count(0), m_clutoffs(0), m_timer(nullptr)
+ m_screen(*this, "screen"),
+ m_ramdac(*this, "bt453"),
+ m_mode(0),
+ m_vbl_disable(0),
+ m_htotal(896),
+ m_hres(640),
+ m_vtotal(525),
+ m_vres(480),
+ m_timer(nullptr)
{
- set_screen(*this, M2VIDEO_SCREEN_NAME);
+ set_screen(*this, "screen");
}
-//-------------------------------------------------
-// device_start - device-specific startup
-//-------------------------------------------------
-
void nubus_m2video_device::device_start()
{
- uint32_t slotspace;
+ install_declaration_rom("declrom", true, true);
- install_declaration_rom(this, M2VIDEO_ROM_REGION, true, true);
+ m_vram = std::make_unique<u32[]>(VRAM_SIZE / sizeof(u32));
+ nubus().install_map(*this, &nubus_m2video_device::card_map);
- slotspace = get_slotspace();
+ std::fill_n(&m_regs[0], 16, 0);
-// logerror("[m2video %p] slotspace = %x\n", this, slotspace);
-
- m_vram.resize(VRAM_SIZE);
- m_vram32 = (uint32_t *)&m_vram[0];
-
- nubus().install_device(slotspace, slotspace+VRAM_SIZE-1, read32_delegate(FUNC(nubus_m2video_device::vram_r), this), write32_delegate(FUNC(nubus_m2video_device::vram_w), this));
- nubus().install_device(slotspace+0x900000, slotspace+VRAM_SIZE-1+0x900000, read32_delegate(FUNC(nubus_m2video_device::vram_r), this), write32_delegate(FUNC(nubus_m2video_device::vram_w), this));
- nubus().install_device(slotspace+0x80000, slotspace+0xeffff, read32_delegate(FUNC(nubus_m2video_device::m2video_r), this), write32_delegate(FUNC(nubus_m2video_device::m2video_w), this));
-
- m_timer = timer_alloc(0, nullptr);
+ m_timer = timer_alloc(FUNC(nubus_m2video_device::vbl_tick), this);
m_timer->adjust(screen().time_until_pos(479, 0), 0);
}
-//-------------------------------------------------
-// device_reset - device-specific reset
-//-------------------------------------------------
-
void nubus_m2video_device::device_reset()
{
- m_count = 0;
- m_clutoffs = 0;
m_vbl_disable = 1;
m_mode = 0;
- memset(&m_vram[0], 0, VRAM_SIZE);
- memset(m_palette, 0, sizeof(m_palette));
-
- m_palette[0] = rgb_t(255, 255, 255);
- m_palette[0x80] = rgb_t(0, 0, 0);
}
-
-void nubus_m2video_device::device_timer(emu_timer &timer, device_timer_id tid, int param, void *ptr)
+TIMER_CALLBACK_MEMBER(nubus_m2video_device::vbl_tick)
{
if (!m_vbl_disable)
{
@@ -131,82 +173,71 @@ void nubus_m2video_device::device_timer(emu_timer &timer, device_timer_id tid, i
m_timer->adjust(screen().time_until_pos(479, 0), 0);
}
-/***************************************************************************
-
- "TFB" section
-
-***************************************************************************/
-
-uint32_t nubus_m2video_device::screen_update(screen_device &screen, bitmap_rgb32 &bitmap, const rectangle &cliprect)
+u32 nubus_m2video_device::screen_update(screen_device &screen, bitmap_rgb32 &bitmap, const rectangle &cliprect)
{
- uint32_t *scanline;
- int x, y;
- uint8_t pixels, *vram;
-
- vram = &m_vram[0x20];
+ auto const vram8 = util::big_endian_cast<u8 const>(&m_vram[0]) + 0x20;
+ pen_t const *const pens = m_ramdac->pens();
switch (m_mode)
{
- case 0: // 1 bpp?
- for (y = 0; y < 480; y++)
+ case 0: // 1 bpp
+ for (int y = 0; y < m_vres; y++)
{
- scanline = &bitmap.pix32(y);
- for (x = 0; x < 640/8; x++)
+ u32 *scanline = &bitmap.pix(y);
+ for (int x = 0; x < m_hres/8; x++)
{
- pixels = vram[(y * 128) + (BYTE4_XOR_BE(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 * 128) + 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: // 2 bpp
- for (y = 0; y < 480; y++)
+ for (int y = 0; y < m_vres; y++)
{
- scanline = &bitmap.pix32(y);
- for (x = 0; x < 640/4; x++)
+ u32 *scanline = &bitmap.pix(y);
+ for (int x = 0; x < m_hres/4; x++)
{
- pixels = vram[(y * 256) + (BYTE4_XOR_BE(x))];
+ u8 const pixels = vram8[(y * 256) + 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;
case 2: // 4 bpp
- for (y = 0; y < 480; y++)
+ for (int y = 0; y < m_vres; y++)
{
- scanline = &bitmap.pix32(y);
-
- for (x = 0; x < 640/2; x++)
+ u32 *scanline = &bitmap.pix(y);
+ for (int x = 0; x < m_hres/2; x++)
{
- pixels = vram[(y * 512) + (BYTE4_XOR_BE(x))];
+ u8 const pixels = vram8[(y * 512) + x];
- *scanline++ = m_palette[(pixels&0xf0)];
- *scanline++ = m_palette[((pixels&0x0f)<<4)];
+ *scanline++ = pens[(pixels&0xf0)];
+ *scanline++ = pens[((pixels&0x0f)<<4)];
}
}
break;
case 3: // 8 bpp
- for (y = 0; y < 480; y++)
+ for (int y = 0; y < m_vres; y++)
{
- scanline = &bitmap.pix32(y);
-
- for (x = 0; x < 640; x++)
+ u32 *scanline = &bitmap.pix(y);
+ for (int x = 0; x < m_hres; x++)
{
- pixels = vram[(y * 1024) + (BYTE4_XOR_BE(x))];
- *scanline++ = m_palette[pixels];
+ u8 const pixels = vram8[(y * 1024) + x];
+ *scanline++ = pens[pixels];
}
}
break;
@@ -217,90 +248,117 @@ uint32_t nubus_m2video_device::screen_update(screen_device &screen, bitmap_rgb32
return 0;
}
-WRITE32_MEMBER( nubus_m2video_device::m2video_w )
+void nubus_m2video_device::tfb_w(offs_t offset, u32 data, u32 mem_mask)
{
data ^= 0xffffffff;
- switch (offset)
+ offset &= 0xf;
+ LOGMASKED(LOG_REGISTERS, "%s m2video_w: %08x @ %x (mask %08x)\n", machine().describe_context(), data, offset, mem_mask);
+ if (mem_mask == 0xff00'0000)
{
- case 0: // mode
- switch (data & 0xff000000)
- {
- case 0x20000000:
- m_mode = 0;
- break;
+ data >>= 24;
+ }
+ m_regs[offset & 0xf] = data & 0xff;
- case 0x40000000:
- m_mode = 1;
- break;
+ if ((offset & 0xf) == 0xf)
+ {
+ calc_screen_params();
+ }
+}
- case 0x80000000:
- m_mode = 2;
- break;
+void nubus_m2video_device::vbl_w(offs_t offset, u8 data)
+{
+ if (offset & 4)
+ {
+ m_vbl_disable = 1;
+ }
+ else
+ {
+ m_vbl_disable = 0;
+ lower_slot_irq();
+ }
+}
- case 0x00000000:
- m_mode = 3;
- break;
- }
- break;
- case 0x4007: // DAC control
-// logerror("%08x to DAC control %s\n", data, machine().describe_context());
- m_clutoffs = (data>>24)&0xff;
- break;
+u8 nubus_m2video_device::vbl_r(offs_t offset)
+{
+ u8 result = m_screen->vblank() ? 0 : 0xff;
+ return result;
+}
- case 0x4006: // DAC data
- m_colors[m_count++] = (data>>24) & 0xff;
+u8 nubus_m2video_device::ramdac_r(offs_t offset)
+{
+ switch (offset & 3)
+ {
+ case 2:
+ return m_ramdac->palette_r(nubus().space()) ^ 0xff;
- if (m_count == 3)
- {
-// logerror("RAMDAC: color %02x = %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[0], m_colors[1], m_colors[2]);
- m_clutoffs++;
- if (m_clutoffs > 255)
- {
- m_clutoffs = 0;
- }
- m_count = 0;
- }
- break;
+ case 1:
+ case 3:
+ return m_ramdac->address_r() ^ 0xff;
+ }
- case 0x8000: // enable and ack VBL
- m_vbl_disable = 0;
- lower_slot_irq();
- break;
+ return 0;
+}
- case 0x8001: // disable VBL
- m_vbl_disable = 1;
+void nubus_m2video_device::ramdac_w(offs_t offset, u8 data)
+{
+ data ^= 0xff;
+ switch (offset & 3)
+ {
+ case 1:
+ case 3:
+ m_ramdac->address_w(data);
break;
- default:
-// logerror("m2video_w: %08x @ %x, mask %08x %s\n", data, offset, mem_mask, machine().describe_context());
+ case 2:
+ m_ramdac->palette_w(data);
break;
}
}
-READ32_MEMBER( nubus_m2video_device::m2video_r )
+void nubus_m2video_device::vram_w(offs_t offset, u32 data, u32 mem_mask)
{
- if (offset == 0x50000/4) // bit 0 is VBL status
- {
- m_toggle ^= 1;
- return m_toggle;
- }
- else
- {
-// logerror("m2video_r: @ %x, mask %08x %s\n", offset, mem_mask, machine().describe_context());
- }
-
- return 0;
+ data ^= 0xffffffff;
+ COMBINE_DATA(&m_vram[offset]);
}
-WRITE32_MEMBER( nubus_m2video_device::vram_w )
+u32 nubus_m2video_device::vram_r(offs_t offset, u32 mem_mask)
{
- data ^= 0xffffffff;
- COMBINE_DATA(&m_vram32[offset]);
+ return m_vram[offset] ^ 0xffffffff;
}
-READ32_MEMBER( nubus_m2video_device::vram_r )
+// This chip packs the registers in an unpleasant way.
+// TFB 2.2 does it much more pleasantly (see nubus_m2hires.cpp).
+void nubus_m2video_device::calc_screen_params()
{
- return m_vram32[offset] ^ 0xffffffff;
+ m_mode = (m_regs[MISC2] >> 4) & 3;
+
+ const u32 halfline = (m_regs[HALFLINE] | (BIT(m_regs[HALFLINE_EARLY], 7) << 8)) + 2;
+ const u32 hpixels = ((m_regs[HPIXELS] << 2) | BIT(m_regs[HPIXELS_HLATE], 6, 2)) + 2;
+ const u32 hsyncstart = m_regs[HSYNCSTART] + 2;
+ const u32 hsyncfinish = m_regs[HSYNCFINISH] + 2;
+ const u32 hearly = (m_regs[HALFLINE_EARLY] & 0x7f) + 2;
+ const u32 hlate = (m_regs[HPIXELS_HLATE] & 0x3f) + 2;
+ const u32 vfrontporch = (m_regs[VLINES_VPP] & 0x1f) + 1;
+ const u32 vsyncfinish = (m_regs[SYNCINTERVAL8] & 0x7f) + 1;
+ const u32 vbackporch = (m_regs[VBACKPORCH] & 0x3f) + 8;
+ const u32 vlines = ((m_regs[VLINES] << 3) | BIT(m_regs[VLINES_VPP], 5, 3)) + 1;
+
+ m_hres = (halfline + hpixels) * (16 >> m_mode);
+ m_htotal = (halfline + hpixels + hsyncstart + hsyncfinish + hearly + hlate) * (16 >> m_mode);
+ m_vres = vlines / 2;
+ m_vtotal = (vfrontporch * 2) + vsyncfinish + (vbackporch * 2) + (vlines / 2);
+
+ LOGMASKED(LOG_CRTC, "halfline %x hpixels %x depth %d\n", halfline, hpixels, m_mode);
+ LOGMASKED(LOG_CRTC, "hsyncstart %x hsyncfinish %x hearly %x hlate %x\n", hsyncstart, hsyncfinish, hearly, hlate);
+ LOGMASKED(LOG_CRTC, "hvis = %d, htotal = %d\n", m_hres, m_htotal);
+ LOGMASKED(LOG_CRTC, "vfrontporch %x vsyncfinish %x vbackporch %x vlines %x\n", vfrontporch, vsyncfinish, vbackporch, vlines);
+ LOGMASKED(LOG_CRTC, "vvis = %d, vtotal = %d\n", m_vres, m_vtotal);
+
+ 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, 30.24_MHz_XTAL).as_attoseconds());
}
+
+} // anonymous namespace
+
+DEFINE_DEVICE_TYPE_PRIVATE(NUBUS_M2VIDEO, device_nubus_card_interface, nubus_m2video_device, "nb_m2vc", "Apple Macintosh II Video Card")
diff --git a/src/devices/bus/nubus/nubus_m2video.h b/src/devices/bus/nubus/nubus_m2video.h
index 4c4716cdd4f..7fb5df38b5f 100644
--- a/src/devices/bus/nubus/nubus_m2video.h
+++ b/src/devices/bus/nubus/nubus_m2video.h
@@ -7,50 +7,7 @@
#include "nubus.h"
-//**************************************************************************
-// TYPE DEFINITIONS
-//**************************************************************************
-
-// ======================> nubus_m2video_device
-
-class nubus_m2video_device :
- public device_t,
- public device_video_interface,
- public device_nubus_card_interface
-{
-public:
- // construction/destruction
- nubus_m2video_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
-
-protected:
- nubus_m2video_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_timer(emu_timer &timer, device_timer_id id, int param, void *ptr) override;
-
- // optional information overrides
- virtual void device_add_mconfig(machine_config &config) override;
- virtual const tiny_rom_entry *device_rom_region() const override;
-
-private:
- DECLARE_READ32_MEMBER(m2video_r);
- DECLARE_WRITE32_MEMBER(m2video_w);
- DECLARE_READ32_MEMBER(vram_r);
- DECLARE_WRITE32_MEMBER(vram_w);
-
- uint32_t screen_update(screen_device &screen, bitmap_rgb32 &bitmap, const rectangle &cliprect);
-
- std::vector<uint8_t> m_vram;
- uint32_t *m_vram32;
- 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_M2VIDEO, nubus_m2video_device)
+DECLARE_DEVICE_TYPE(NUBUS_M2VIDEO, device_nubus_card_interface)
#endif // MAME_BUS_NUBUS_NUBUS_M2VIDEO_H
diff --git a/src/devices/bus/nubus/nubus_radiustpd.cpp b/src/devices/bus/nubus/nubus_radiustpd.cpp
index 1ee2e0cb7fb..38274e82b27 100644
--- a/src/devices/bus/nubus/nubus_radiustpd.cpp
+++ b/src/devices/bus/nubus/nubus_radiustpd.cpp
@@ -14,164 +14,148 @@
#include "nubus_radiustpd.h"
#include "screen.h"
+#include <algorithm>
-#define RADIUSTPD_SCREEN_NAME "tpd_screen"
-#define RADIUSTPD_ROM_REGION "tpd_rom"
+namespace {
-#define VRAM_SIZE (0x40000) // 256k. 1152x880 1 bit per pixel fits nicely.
+static constexpr u32 VRAM_SIZE = 0x40000; // 256k. 1152x880 1 bit per pixel fits nicely.
+class nubus_radiustpd_device : public device_t,
+ public device_nubus_card_interface
+{
+public:
+ // construction/destruction
+ nubus_radiustpd_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock);
-ROM_START( radiustpd )
- ROM_REGION(0x8000, RADIUSTPD_ROM_REGION, 0)
- ROM_LOAD( "tpd_v22.bin", 0x0000, 0x8000, CRC(7dc5ed05) SHA1(4abb64e49201e966c17a255a94b670564b229934) )
-ROM_END
+protected:
+ nubus_radiustpd_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, u32 clock);
+
+ // device-level overrides
+ virtual void device_start() override ATTR_COLD;
+ virtual void device_reset() override ATTR_COLD;
-//**************************************************************************
-// GLOBAL VARIABLES
-//**************************************************************************
+ // optional information overrides
+ virtual void device_add_mconfig(machine_config &config) override ATTR_COLD;
+ virtual const tiny_rom_entry *device_rom_region() const override ATTR_COLD;
-DEFINE_DEVICE_TYPE(NUBUS_RADIUSTPD, nubus_radiustpd_device, "nb_rtpd", "Radius Two Page Display video card")
+ TIMER_CALLBACK_MEMBER(vbl_tick);
+ void card_map(address_map &map);
-//-------------------------------------------------
-// device_add_mconfig - add device configuration
-//-------------------------------------------------
+private:
+ u32 radiustpd_r(offs_t offset, u32 mem_mask = ~0);
+ void radiustpd_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);
+
+ required_device<screen_device> m_screen;
+ std::unique_ptr<u32[]> m_vram;
+ u32 m_vbl_disable;
+ u32 m_palette[2];
+ emu_timer *m_timer;
+};
+
+ROM_START( radiustpd )
+ ROM_REGION(0x8000, "declrom", 0)
+ ROM_LOAD( "tpd_v22.bin", 0x0000, 0x8000, CRC(7dc5ed05) SHA1(4abb64e49201e966c17a255a94b670564b229934) )
+ROM_END
void nubus_radiustpd_device::device_add_mconfig(machine_config &config)
{
- screen_device &screen(SCREEN(config, RADIUSTPD_SCREEN_NAME, SCREEN_TYPE_RASTER));
- screen.set_screen_update(FUNC(nubus_radiustpd_device::screen_update));
- screen.set_raw(99.522_MHz_XTAL, 1536, 0, 1152, 900, 0, 880); // 64.79 kHz horizontal, 72 Hz refresh
+ SCREEN(config, m_screen, SCREEN_TYPE_RASTER);
+ m_screen->set_screen_update(FUNC(nubus_radiustpd_device::screen_update));
+ m_screen->set_raw(99.522_MHz_XTAL, 1536, 0, 1152, 900, 0, 880); // 64.79 kHz horizontal, 72 Hz refresh
}
-//-------------------------------------------------
-// rom_region - device-specific ROM region
-//-------------------------------------------------
-
const tiny_rom_entry *nubus_radiustpd_device::device_rom_region() const
{
return ROM_NAME( radiustpd );
}
-//**************************************************************************
-// LIVE DEVICE
-//**************************************************************************
-
-//-------------------------------------------------
-// nubus_radiustpd_device - constructor
-//-------------------------------------------------
-
-nubus_radiustpd_device::nubus_radiustpd_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) :
+nubus_radiustpd_device::nubus_radiustpd_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock) :
nubus_radiustpd_device(mconfig, NUBUS_RADIUSTPD, tag, owner, clock)
{
- (void)m_toggle;
- (void)&m_colors[0];
}
-nubus_radiustpd_device::nubus_radiustpd_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock) :
+nubus_radiustpd_device::nubus_radiustpd_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_vram32(nullptr), m_mode(0), m_vbl_disable(0), m_toggle(0), m_count(0), m_clutoffs(0), m_timer(nullptr)
+ m_screen(*this, "screen"),
+ m_vbl_disable(0), m_timer(nullptr)
{
- set_screen(*this, RADIUSTPD_SCREEN_NAME);
+ m_palette[0] = rgb_t(0, 0, 0);
+ m_palette[1] = rgb_t(255, 255, 255);
}
-//-------------------------------------------------
-// device_start - device-specific startup
-//-------------------------------------------------
+void nubus_radiustpd_device::card_map(address_map &map)
+{
+ map(0x00'0000, 0x03'ffff).rw(FUNC(nubus_radiustpd_device::vram_r), FUNC(nubus_radiustpd_device::vram_w)).mirror(0xf00000);
+ map(0x08'0000, 0x0e'ffff).rw(FUNC(nubus_radiustpd_device::radiustpd_r), FUNC(nubus_radiustpd_device::radiustpd_w)).mirror(0xf00000);
+}
void nubus_radiustpd_device::device_start()
{
- uint32_t slotspace;
-
- install_declaration_rom(this, RADIUSTPD_ROM_REGION, true, true);
+ install_declaration_rom("declrom", true, true);
- slotspace = get_slotspace();
+ m_vram = std::make_unique<u32[]>(VRAM_SIZE / sizeof(u32));
- printf("[radiustpd %p] slotspace = %x\n", (void *)this, slotspace);
+ nubus().install_map(*this, &nubus_radiustpd_device::card_map);
- m_vram.resize(VRAM_SIZE);
- m_vram32 = (uint32_t *)&m_vram[0];
+ m_timer = timer_alloc(FUNC(nubus_radiustpd_device::vbl_tick), this);
+ m_timer->adjust(m_screen->time_until_pos(879, 0), 0);
- nubus().install_device(slotspace, slotspace+VRAM_SIZE-1, read32_delegate(FUNC(nubus_radiustpd_device::vram_r), this), write32_delegate(FUNC(nubus_radiustpd_device::vram_w), this));
- nubus().install_device(slotspace+0x900000, slotspace+VRAM_SIZE-1+0x900000, read32_delegate(FUNC(nubus_radiustpd_device::vram_r), this), write32_delegate(FUNC(nubus_radiustpd_device::vram_w), this));
- nubus().install_device(slotspace+0x80000, slotspace+0xeffff, read32_delegate(FUNC(nubus_radiustpd_device::radiustpd_r), this), write32_delegate(FUNC(nubus_radiustpd_device::radiustpd_w), this));
- nubus().install_device(slotspace+0x980000, slotspace+0x9effff, read32_delegate(FUNC(nubus_radiustpd_device::radiustpd_r), this), write32_delegate(FUNC(nubus_radiustpd_device::radiustpd_w), this));
-
- m_timer = timer_alloc(0, nullptr);
- m_timer->adjust(screen().time_until_pos(479, 0), 0);
+ save_pointer(NAME(m_vram), VRAM_SIZE / sizeof(u32));
+ save_item(NAME(m_vbl_disable));
}
-//-------------------------------------------------
-// device_reset - device-specific reset
-//-------------------------------------------------
-
void nubus_radiustpd_device::device_reset()
{
- m_count = 0;
- m_clutoffs = 0;
m_vbl_disable = 1;
- m_mode = 0;
- memset(&m_vram[0], 0, VRAM_SIZE);
- memset(m_palette, 0, sizeof(m_palette));
-
- m_palette[1] = rgb_t(255, 255, 255);
- m_palette[0] = rgb_t(0, 0, 0);
}
-
-void nubus_radiustpd_device::device_timer(emu_timer &timer, device_timer_id tid, int param, void *ptr)
+TIMER_CALLBACK_MEMBER(nubus_radiustpd_device::vbl_tick)
{
if (!m_vbl_disable)
{
raise_slot_irq();
}
- m_timer->adjust(screen().time_until_pos(479, 0), 0);
+ m_timer->adjust(m_screen->time_until_pos(879, 0), 0);
}
-/***************************************************************************
-
- Two Page Display section
-
-***************************************************************************/
-
-uint32_t nubus_radiustpd_device::screen_update(screen_device &screen, bitmap_rgb32 &bitmap, const rectangle &cliprect)
+u32 nubus_radiustpd_device::screen_update(screen_device &screen, bitmap_rgb32 &bitmap, const rectangle &cliprect)
{
- uint32_t *scanline;
- int x, y;
- uint8_t pixels, *vram;
-
- vram = &m_vram[0x200];
+ auto const vram8 = util::big_endian_cast<u8 const>(&m_vram[0]) + 0x200;
- for (y = 0; y < 880; y++)
+ for (int y = 0; y < 880; y++)
{
- scanline = &bitmap.pix32(y);
- for (x = 0; x < 1152/8; x++)
+ u32 *scanline = &bitmap.pix(y);
+ for (int x = 0; x < 1152/8; x++)
{
- pixels = vram[(y * (1152/8)) + (BYTE4_XOR_BE(x))];
-
- *scanline++ = m_palette[((pixels>>7)&0x1)];
- *scanline++ = m_palette[((pixels>>6)&0x1)];
- *scanline++ = m_palette[((pixels>>5)&0x1)];
- *scanline++ = m_palette[((pixels>>4)&0x1)];
- *scanline++ = m_palette[((pixels>>3)&0x1)];
- *scanline++ = m_palette[((pixels>>2)&0x1)];
- *scanline++ = m_palette[((pixels>>1)&0x1)];
- *scanline++ = m_palette[(pixels&1)];
+ u8 const pixels = vram8[(y * (1152/8)) + 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)];
}
}
return 0;
}
-WRITE32_MEMBER( nubus_radiustpd_device::radiustpd_w )
+void nubus_radiustpd_device::radiustpd_w(offs_t offset, u32 data, u32 mem_mask)
{
// printf("TPD: write %08x to %x, mask %08x\n", data, offset, mem_mask);
}
-READ32_MEMBER( nubus_radiustpd_device::radiustpd_r )
+u32 nubus_radiustpd_device::radiustpd_r(offs_t offset, u32 mem_mask)
{
// printf("TPD: read @ %x, mask %08x\n", offset, mem_mask);
@@ -194,13 +178,17 @@ READ32_MEMBER( nubus_radiustpd_device::radiustpd_r )
return 0;
}
-WRITE32_MEMBER( nubus_radiustpd_device::vram_w )
+void nubus_radiustpd_device::vram_w(offs_t offset, u32 data, u32 mem_mask)
{
data ^= 0xffffffff;
- COMBINE_DATA(&m_vram32[offset]);
+ COMBINE_DATA(&m_vram[offset]);
}
-READ32_MEMBER( nubus_radiustpd_device::vram_r )
+u32 nubus_radiustpd_device::vram_r(offs_t offset, u32 mem_mask)
{
- return m_vram32[offset] ^ 0xffffffff;
+ return m_vram[offset] ^ 0xffffffff;
}
+
+} // anonymous namespace
+
+DEFINE_DEVICE_TYPE_PRIVATE(NUBUS_RADIUSTPD, device_nubus_card_interface, nubus_radiustpd_device, "nb_rtpd", "Radius Two Page Display video card")
diff --git a/src/devices/bus/nubus/nubus_radiustpd.h b/src/devices/bus/nubus/nubus_radiustpd.h
index 20400277f1a..25e2648434e 100644
--- a/src/devices/bus/nubus/nubus_radiustpd.h
+++ b/src/devices/bus/nubus/nubus_radiustpd.h
@@ -7,50 +7,7 @@
#include "nubus.h"
-//**************************************************************************
-// TYPE DEFINITIONS
-//**************************************************************************
-
-// ======================> nubus_radiustpd_device
-
-class nubus_radiustpd_device :
- public device_t,
- public device_video_interface,
- public device_nubus_card_interface
-{
-public:
- // construction/destruction
- nubus_radiustpd_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
-
-protected:
- nubus_radiustpd_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_timer(emu_timer &timer, device_timer_id id, int param, void *ptr) override;
-
- // optional information overrides
- virtual void device_add_mconfig(machine_config &config) override;
- virtual const tiny_rom_entry *device_rom_region() const override;
-
-private:
- DECLARE_READ32_MEMBER(radiustpd_r);
- DECLARE_WRITE32_MEMBER(radiustpd_w);
- DECLARE_READ32_MEMBER(vram_r);
- DECLARE_WRITE32_MEMBER(vram_w);
-
- uint32_t screen_update(screen_device &screen, bitmap_rgb32 &bitmap, const rectangle &cliprect);
-
- std::vector<uint8_t> m_vram;
- uint32_t *m_vram32;
- 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_RADIUSTPD, nubus_radiustpd_device)
+DECLARE_DEVICE_TYPE(NUBUS_RADIUSTPD, device_nubus_card_interface)
#endif // MAME_BUS_NUBUS_NUBUS_RADIUSTPD_H
diff --git a/src/devices/bus/nubus/nubus_spec8.cpp b/src/devices/bus/nubus/nubus_spec8.cpp
index 1353d3b9a9d..f04e6512692 100644
--- a/src/devices/bus/nubus/nubus_spec8.cpp
+++ b/src/devices/bus/nubus/nubus_spec8.cpp
@@ -1,39 +1,149 @@
// license:BSD-3-Clause
-// copyright-holders:R. Belmont
+// copyright-holders:R. Belmont, Vas Crabb
/***************************************************************************
SuperMac Spectrum/8 Series III video card
- There is no sign of acceleration or blitting in any mode, and the acceleration
- code from the Spectrum PDQ ROM is absent on this one.
-
- On first boot / with clean PRAM, press SPACE repeatedly when it shows the frame
- that fills the entire screen. If you get it wrong, delete PRAM and try again.
+ This is a high-resolution video card supporting 1-bit, 2-bit, 4-bit and
+ 8-bit modes with 24-bit palette entires. Virtual desktop panning and
+ two-times zoom are supported in hardware. No accelerated drawing
+ features are present.
+
+ On first boot or with clean PRAM, the firmware will cycle through video
+ modes and prompt you to press space when the desired mode is active (on
+ the monitors available at the time, only one mode would produce a stable
+ image). If you want to change video mode later, hold Option as soon as
+ the machine starts. The modes offered depend on the user-supplied
+ oscillator.
+
+ The user-supplied oscillator calibration result is only saved if the
+ value in PRAM is invalid. If you change the oscillator in Machine
+ Configuration settings, you need to zap the PRAM before it will be
+ recognised properly.
+
+ Set breakpoint at 0x2d1e on Mac II with Ver. 1.3 card in slot 9 to catch
+ user oscillator measurement. See the measured value in D0.b when
+ PC = 0x2d6c.
+
+ Expected:
+ 2- 5 57.28 MHz
+ 6-19 bad
+ 20-22 14.32 MHz
+ 23-24 15.67 MHz
+ 25-27 17.73 MHz
+ 27- bad
+
+ Measured:
+ 14.32 MHz 20
+ 15.67 MHz 23
+ 17.73 MHz 26
+ 57.28 MHz 5
+
+ TODO:
+ * Having no oscillator installed at Y1 is not emulated.
+ * Interlaced modes are not understood.
***************************************************************************/
#include "emu.h"
#include "nubus_spec8.h"
+
+#include "supermac.h"
+
+#include "layout/generic.h"
+#include "video/bt47x.h"
#include "screen.h"
+#include <algorithm>
+
+//#define VERBOSE 1
+#include "logmacro.h"
-#define SPEC8S3_SCREEN_NAME "spec8s3_screen"
+
+#define SPEC8S3_SCREEN_NAME "screen"
#define SPEC8S3_ROM_REGION "spec8s3_rom"
-#define VRAM_SIZE (0xc0000) // 768k of VRAM for 1024x768 @ 8 bit
+#define VRAM_SIZE (0x10'0000) // 1M of VRAM for 1024x768 @ 8 bit
-ROM_START( spec8s3 )
- ROM_REGION(0x8000, SPEC8S3_ROM_REGION, 0)
- ROM_LOAD( "1003067-0001d.11b.bin", 0x000000, 0x008000, CRC(12188e2b) SHA1(6552d40364eae99b449842a79843d8c0114c4c70) ) // "1003067-0001D Spec/8 Ser III // Ver. 1.2 (C)Copyright 1990 // SuperMac Technology // All Rights Reserved" 27c256 @11B
- ROM_LOAD( "1003067-0001e.11b.bin", 0x000000, 0x008000, CRC(39fab193) SHA1(124c9847bf07733d131c977c4395cfbbb6470973) ) // "1003067-0001E Spec/8 Ser III // Ver. 1.3 (C)Copyright 1993 // SuperMac Technology // All Rights Reserved" NMC27C256Q @11B
-ROM_END
+namespace {
//**************************************************************************
-// GLOBAL VARIABLES
+// TYPE DEFINITIONS
//**************************************************************************
-DEFINE_DEVICE_TYPE(NUBUS_SPEC8S3, nubus_spec8s3_device, "nb_sp8s3", "SuperMac Spectrum/8 Series III video card")
+class nubus_spec8s3_device :
+ public device_t,
+ public device_nubus_card_interface,
+ public device_video_interface
+{
+public:
+ // construction/destruction
+ nubus_spec8s3_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock);
+
+protected:
+ nubus_spec8s3_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, u32 clock);
+
+ // device-level overrides
+ virtual void device_start() override ATTR_COLD;
+ virtual void device_reset() override ATTR_COLD;
+
+ // optional information overrides
+ virtual void device_add_mconfig(machine_config &config) override ATTR_COLD;
+ virtual const tiny_rom_entry *device_rom_region() const override ATTR_COLD;
+ virtual ioport_constructor device_input_ports() const override ATTR_COLD;
+
+ TIMER_CALLBACK_MEMBER(vbl_tick);
+
+private:
+ u32 spec8s3_r(offs_t offset, u32 mem_mask = ~0);
+ void spec8s3_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);
+
+ void update_crtc();
+
+ u32 screen_update(screen_device &screen, bitmap_rgb32 &bitmap, const rectangle &cliprect);
+
+ required_device<bt478_device> m_ramdac;
+ required_ioport m_userosc;
+ emu_timer *m_timer;
+
+ supermac_spec_crtc m_crtc;
+ supermac_spec_shift_reg m_shiftreg;
+
+ std::vector<u32> m_vram;
+ u32 m_mode, m_vbl_disable;
+ u32 m_count, m_clutoffs;
+
+ u8 m_osc;
+ bool m_interlace;
+
+ u16 m_hpan, m_vpan;
+ u8 m_zoom;
+
+ bool m_vbl_pending;
+};
+
+
+INPUT_PORTS_START( spec8s3 )
+ PORT_START("USEROSC")
+ PORT_CONFNAME(0x07, 0x01, "Oscillator Y1")
+ PORT_CONFSETTING( 0x00, "14.32 MHz (NTSC Underscan)")
+ PORT_CONFSETTING( 0x01, "15.67 MHz (Apple 12\")")
+ PORT_CONFSETTING( 0x02, "17.73 MHz (PAL Underscan)")
+ PORT_CONFSETTING( 0x03, "57.28 MHz (Apple 15\" Portrait, Apple 16\")")
+INPUT_PORTS_END
+
+ROM_START( spec8s3 )
+ ROM_DEFAULT_BIOS("ver13")
+ ROM_SYSTEM_BIOS( 0, "ver12", "Ver. 1.2 (1990)" )
+ ROM_SYSTEM_BIOS( 1, "ver13", "Ver. 1.3 (1993)" )
+
+ ROM_REGION(0x8000, SPEC8S3_ROM_REGION, 0)
+ ROMX_LOAD( "1003067-0001d.11b.bin", 0x000000, 0x008000, CRC(12188e2b) SHA1(6552d40364eae99b449842a79843d8c0114c4c70), ROM_BIOS(0) ) // "1003067-0001D Spec/8 Ser III // Ver. 1.2 (C)Copyright 1990 // SuperMac Technology // All Rights Reserved" 27c256 @11B
+ ROMX_LOAD( "1003067-0001e.11b.bin", 0x000000, 0x008000, CRC(39fab193) SHA1(124c9847bf07733d131c977c4395cfbbb6470973), ROM_BIOS(1) ) // "1003067-0001E Spec/8 Ser III // Ver. 1.3 (C)Copyright 1993 // SuperMac Technology // All Rights Reserved" NMC27C256Q @11B
+ROM_END
//-------------------------------------------------
@@ -42,11 +152,14 @@ DEFINE_DEVICE_TYPE(NUBUS_SPEC8S3, nubus_spec8s3_device, "nb_sp8s3", "SuperMac Sp
void nubus_spec8s3_device::device_add_mconfig(machine_config &config)
{
+ config.set_default_layout(layout_monitors);
+
screen_device &screen(SCREEN(config, SPEC8S3_SCREEN_NAME, SCREEN_TYPE_RASTER));
screen.set_screen_update(FUNC(nubus_spec8s3_device::screen_update));
- screen.set_raw(25175000, 800, 0, 640, 525, 0, 480);
- screen.set_size(1024, 768);
- screen.set_visarea(0, 1024-1, 0, 768-1);
+ screen.set_raw(80.000_MHz_XTAL, 332*4, 64*4, 320*4, 804, 33, 801);
+ screen.set_video_attributes(VIDEO_UPDATE_SCANLINE);
+
+ BT478(config, m_ramdac, 0);
}
//-------------------------------------------------
@@ -58,25 +171,34 @@ const tiny_rom_entry *nubus_spec8s3_device::device_rom_region() const
return ROM_NAME( spec8s3 );
}
-//**************************************************************************
-// LIVE DEVICE
-//**************************************************************************
+//-------------------------------------------------
+// input_ports - device-specific I/O ports
+//-------------------------------------------------
+
+ioport_constructor nubus_spec8s3_device::device_input_ports() const
+{
+ return INPUT_PORTS_NAME( spec8s3 );
+}
//-------------------------------------------------
// nubus_spec8s3_device - constructor
//-------------------------------------------------
-nubus_spec8s3_device::nubus_spec8s3_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) :
+nubus_spec8s3_device::nubus_spec8s3_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock) :
nubus_spec8s3_device(mconfig, NUBUS_SPEC8S3, tag, owner, clock)
{
}
-nubus_spec8s3_device::nubus_spec8s3_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock) :
+nubus_spec8s3_device::nubus_spec8s3_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_vram32(nullptr), m_mode(0), m_vbl_disable(0), m_count(0), m_clutoffs(0), m_timer(nullptr),
- m_vbl_pending(false), m_parameter(0)
+ device_video_interface(mconfig, *this),
+ m_ramdac(*this, "bt478"),
+ m_userosc(*this, "USEROSC"),
+ m_timer(nullptr),
+ m_mode(0), m_vbl_disable(0),
+ m_count(0), m_clutoffs(0),
+ m_vbl_pending(false)
{
set_screen(*this, SPEC8S3_SCREEN_NAME);
}
@@ -87,22 +209,32 @@ nubus_spec8s3_device::nubus_spec8s3_device(const machine_config &mconfig, device
void nubus_spec8s3_device::device_start()
{
- uint32_t slotspace;
-
- install_declaration_rom(this, SPEC8S3_ROM_REGION);
-
- slotspace = get_slotspace();
-
-// printf("[SPEC8S3 %p] slotspace = %x\n", this, slotspace);
-
- m_vram.resize(VRAM_SIZE);
- m_vram32 = (uint32_t *)&m_vram[0];
- nubus().install_device(slotspace, slotspace+VRAM_SIZE-1, read32_delegate(FUNC(nubus_spec8s3_device::vram_r), this), write32_delegate(FUNC(nubus_spec8s3_device::vram_w), this));
- nubus().install_device(slotspace+0x900000, slotspace+VRAM_SIZE-1+0x900000, read32_delegate(FUNC(nubus_spec8s3_device::vram_r), this), write32_delegate(FUNC(nubus_spec8s3_device::vram_w), this));
- nubus().install_device(slotspace+0xd0000, slotspace+0xfffff, read32_delegate(FUNC(nubus_spec8s3_device::spec8s3_r), this), write32_delegate(FUNC(nubus_spec8s3_device::spec8s3_w), this));
-
- m_timer = timer_alloc(0, nullptr);
- m_timer->adjust(screen().time_until_pos(767, 0), 0);
+ install_declaration_rom(SPEC8S3_ROM_REGION);
+
+ u32 const slotspace = get_slotspace();
+ LOG("[SPEC8S3 %p] slotspace = %x\n", this, slotspace);
+
+ m_vram.resize(VRAM_SIZE / sizeof(u32));
+ nubus().install_device(slotspace, slotspace+VRAM_SIZE-1, read32s_delegate(*this, FUNC(nubus_spec8s3_device::vram_r)), write32s_delegate(*this, FUNC(nubus_spec8s3_device::vram_w)));
+ nubus().install_device(slotspace+0x900000, slotspace+VRAM_SIZE-1+0x900000, read32s_delegate(*this, FUNC(nubus_spec8s3_device::vram_r)), write32s_delegate(*this, FUNC(nubus_spec8s3_device::vram_w)));
+ nubus().install_device(slotspace+0xd0000, slotspace+0xfffff, read32s_delegate(*this, FUNC(nubus_spec8s3_device::spec8s3_r)), write32s_delegate(*this, FUNC(nubus_spec8s3_device::spec8s3_w)));
+
+ m_timer = timer_alloc(FUNC(nubus_spec8s3_device::vbl_tick), this);
+
+ m_crtc.register_save(*this);
+ m_shiftreg.register_save(*this);
+
+ save_item(NAME(m_vram));
+ save_item(NAME(m_mode));
+ save_item(NAME(m_vbl_disable));
+ save_item(NAME(m_count));
+ save_item(NAME(m_clutoffs));
+ save_item(NAME(m_osc));
+ save_item(NAME(m_interlace));
+ save_item(NAME(m_hpan));
+ save_item(NAME(m_vpan));
+ save_item(NAME(m_zoom));
+ save_item(NAME(m_vbl_pending));
}
//-------------------------------------------------
@@ -111,21 +243,24 @@ void nubus_spec8s3_device::device_start()
void nubus_spec8s3_device::device_reset()
{
+ m_crtc.reset();
+ m_shiftreg.reset();
+
+ std::fill(m_vram.begin(), m_vram.end(), 0);
+ m_mode = 0;
+ m_vbl_disable = 1;
m_count = 0;
m_clutoffs = 0;
- m_vbl_disable = 1;
- m_mode = 0;
+ m_osc = 0;
+ m_interlace = false;
+ m_hpan = 0;
+ m_vpan = 0;
+ m_zoom = 0;
m_vbl_pending = false;
- m_parameter = 0;
- memset(&m_vram[0], 0, VRAM_SIZE);
- memset(m_palette, 0, sizeof(m_palette));
-
- m_palette[0] = rgb_t(255, 255, 255);
- m_palette[1] = rgb_t(0, 0, 0);
}
-void nubus_spec8s3_device::device_timer(emu_timer &timer, device_timer_id tid, int param, void *ptr)
+TIMER_CALLBACK_MEMBER(nubus_spec8s3_device::vbl_tick)
{
if (!m_vbl_disable)
{
@@ -133,99 +268,209 @@ void nubus_spec8s3_device::device_timer(emu_timer &timer, device_timer_id tid, i
m_vbl_pending = true;
}
- m_timer->adjust(screen().time_until_pos(767, 0), 0);
+ // TODO: confirm vertical blanking interrupt timing
+ m_timer->adjust(screen().time_until_pos((m_crtc.v_end() - 1) * (m_interlace ? 2 : 1), 0));
}
/***************************************************************************
- Spectrum 24 PDQ section
+ Spectrum/8 Series III
***************************************************************************/
-uint32_t nubus_spec8s3_device::screen_update(screen_device &screen, bitmap_rgb32 &bitmap, const rectangle &cliprect)
+void nubus_spec8s3_device::update_crtc()
{
- uint32_t *scanline;
- int x, y;
- uint8_t pixels, *vram;
+ XTAL oscillator = 80.000_MHz_XTAL; // no default constructor
+ switch (m_osc)
+ {
+ case 0: // Y5
+ oscillator = 80.000_MHz_XTAL;
+ break;
+ case 1: // Y1
+ switch (m_userosc->read())
+ {
+ case 0:
+ oscillator = 14.318'18_MHz_XTAL;
+ break;
+ case 1:
+ oscillator = 15.67_MHz_XTAL;
+ break;
+ case 2:
+ oscillator = 17.73_MHz_XTAL;
+ break;
+ case 3:
+ oscillator = 57.28_MHz_XTAL;
+ break;
+ default:
+ throw emu_fatalerror("%s: spec8s3: invalid user oscillator selection %d\n", tag(), m_userosc->read());
+ }
+ break;
+ case 2: // Y2
+ oscillator = 55.000_MHz_XTAL;
+ break;
+ case 3: // Y3
+ oscillator = 30.240_MHz_XTAL;
+ break;
+ case 4: // Y4
+ oscillator = 64.000_MHz_XTAL;
+ break;
+ default:
+ throw emu_fatalerror("%s: spec8s3: invalid oscillator selection %d\n", tag(), m_osc);
+ }
+
+ // FIXME: blatant hack - I don't know how interlace mode is configured
+ m_interlace = m_crtc.v_total() < 320;
+
+ // for some reason you temporarily get invalid screen parameters - ignore them
+ if (m_crtc.valid(*this))
+ {
+ screen().configure(
+ m_crtc.h_total(4),
+ m_crtc.v_total() * (m_interlace ? 2 : 1),
+ rectangle(
+ m_crtc.h_start(4),
+ m_crtc.h_end(4) - 1,
+ m_crtc.v_start() * (m_interlace ? 2 : 1),
+ (m_crtc.v_end() * (m_interlace ? 2 : 1)) - 1),
+ m_crtc.frame_time(4, oscillator));
+
+ // TODO: confirm vertical blanking interrupt timing
+ m_timer->adjust(screen().time_until_pos((m_crtc.v_end() - 1) * (m_interlace ? 2 : 1), 0));
+ }
+}
+
+u32 nubus_spec8s3_device::screen_update(screen_device &screen, bitmap_rgb32 &bitmap, const rectangle &cliprect)
+{
+ auto const screenbase = util::big_endian_cast<u8 const>(&m_vram[0]) + (m_vpan * 2048) + 0x400;
- vram = &m_vram[0x400];
+ int const hstart = m_crtc.h_start(4);
+ int const width = m_crtc.h_active(4);
+ int const pixels = width >> (m_zoom ? 1 : 0);
+ int const vstart = m_crtc.v_start() * (m_interlace ? 2 : 1);
+ int const vend = m_crtc.v_end() * (m_interlace ? 2 : 1);
switch (m_mode)
{
case 0: // 1 bpp
- for (y = 0; y < 768; y++)
+ for (int y = cliprect.top(); y <= cliprect.bottom(); y++)
{
- scanline = &bitmap.pix32(y);
- for (x = 0; x < 1024/8; x++)
+ u32 *scanline = &bitmap.pix(y, hstart);
+ if ((y >= vstart) && (y < vend))
+ {
+ auto const rowbase = screenbase + (((y - vstart) >> (m_zoom ? 1 : 0)) * 512);
+ for (int x = 0; x < (pixels / 2); x++)
+ {
+ u8 const bits = rowbase[(x + m_hpan) / 4];
+ *scanline++ = m_ramdac->pen_color((bits << ((((x + m_hpan) & 0x03) << 1) + 0)) & 0x80);
+ if (m_zoom)
+ *scanline++ = m_ramdac->pen_color((bits << ((((x + m_hpan) & 0x03) << 1) + 0)) & 0x80);
+ *scanline++ = m_ramdac->pen_color((bits << ((((x + m_hpan) & 0x03) << 1) + 1)) & 0x80);
+ if (m_zoom)
+ *scanline++ = m_ramdac->pen_color((bits << ((((x + m_hpan) & 0x03) << 1) + 1)) & 0x80);
+ }
+ }
+ else
{
- pixels = vram[(y * 512) + (BYTE4_XOR_BE(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];
+ std::fill_n(scanline, width, 0);
}
}
break;
case 1: // 2 bpp
- for (y = 0; y < 768; y++)
+ for (int y = cliprect.top(); y <= cliprect.bottom(); y++)
{
- scanline = &bitmap.pix32(y);
- for (x = 0; x < 1024/4; x++)
+ u32 *scanline = &bitmap.pix(y, hstart);
+ if ((y >= vstart) && (y < vend))
{
- pixels = vram[(y * 512) + (BYTE4_XOR_BE(x))];
-
- *scanline++ = m_palette[pixels&0xc0];
- *scanline++ = m_palette[(pixels<<2)&0xc0];
- *scanline++ = m_palette[(pixels<<4)&0xc0];
- *scanline++ = m_palette[(pixels<<6)&0xc0];
+ auto const rowbase = screenbase + (((y - vstart) >> (m_zoom ? 1 : 0)) * 512);
+ for (int x = 0; x < pixels; x++)
+ {
+ u8 const bits = rowbase[(x + m_hpan) / 4];
+ *scanline++ = m_ramdac->pen_color((bits << (((x + m_hpan) & 0x03) << 1)) & 0xc0);
+ if (m_zoom)
+ *scanline++ = m_ramdac->pen_color((bits << (((x + m_hpan) & 0x03) << 1)) & 0xc0);
+ }
+ }
+ else
+ {
+ std::fill_n(scanline, width, 0);
}
}
break;
case 2: // 4 bpp
- for (y = 0; y < 768; y++)
+ for (int y = cliprect.top(); y <= cliprect.bottom(); y++)
{
- scanline = &bitmap.pix32(y);
-
- for (x = 0; x < 1024/2; x++)
+ u32 *scanline = &bitmap.pix(y, hstart);
+ if ((y >= vstart) && (y < vend))
{
- pixels = vram[(y * 512) + (BYTE4_XOR_BE(x))];
-
- *scanline++ = m_palette[pixels&0xf0];
- *scanline++ = m_palette[(pixels<<4)&0xf0];
+ auto const rowbase = screenbase + (((y - vstart) >> (m_zoom ? 1 : 0)) * 512);
+ for (int x = 0; x < pixels; x++)
+ {
+ u8 const bits = rowbase[(x + (m_hpan / 2)) / 2];
+ *scanline++ = m_ramdac->pen_color((bits << (((x + (m_hpan / 2)) & 0x01) << 2)) & 0xf0);
+ if (m_zoom)
+ *scanline++ = m_ramdac->pen_color((bits << (((x + (m_hpan / 2)) & 0x01) << 2)) & 0xf0);
+ }
+ }
+ else
+ {
+ std::fill_n(scanline, width, 0);
}
}
break;
case 3: // 8 bpp
- for (y = 0; y < 768; y++)
+ for (int y = cliprect.top(); y <= cliprect.bottom(); y++)
{
- scanline = &bitmap.pix32(y);
-
- for (x = 0; x < 1024; x++)
+ u32 *scanline = &bitmap.pix(y, hstart);
+ if ((y >= vstart) && (y < vend))
{
- pixels = vram[(y * 1024) + (BYTE4_XOR_BE(x))];
- *scanline++ = m_palette[pixels];
+ auto const rowbase = screenbase + (((y - vstart) >> (m_zoom ? 1 : 0)) * 1024);
+ for (int x = 0; x < pixels; x++)
+ {
+ u8 const bits = rowbase[x + (m_hpan / 4)];
+ *scanline++ = m_ramdac->pen_color(bits);
+ if (m_zoom)
+ *scanline++ = m_ramdac->pen_color(bits);
+ }
+ }
+ else
+ {
+ std::fill_n(scanline, width, 0);
}
}
break;
default:
- fatalerror("spec8s3: unknown video mode %d\n", m_mode);
+ throw emu_fatalerror("%s: spec8s3: unknown video mode %d\n", tag(), m_mode);
}
return 0;
}
-WRITE32_MEMBER( nubus_spec8s3_device::spec8s3_w )
+void nubus_spec8s3_device::spec8s3_w(offs_t offset, u32 data, u32 mem_mask)
{
- switch (offset)
+ if ((offset >= 0x3800) && (offset <= 0x382a))
{
+ m_crtc.write(*this, offset - 0x3800, data);
+ update_crtc();
+ }
+ else switch (offset)
+ {
+ case 0x3844:
+ m_vpan = (m_vpan & 0x0300) | (~data & 0xff);
+ break;
+
+ case 0x3846:
+ // bits 2-7 of this are important - they're read and written back
+ m_vpan = (m_vpan & 0x00ff) | ((~data & 0x03) << 8);
+ m_zoom = BIT(~data, 4);
+ break;
+
+ case 0x3848:
+ m_hpan = (m_hpan & 0x000f) | ((~data & 0xff) << 4);
+ break;
+
case 0x385c: // IRQ enable
if (data & 0x10)
{
@@ -246,60 +491,62 @@ WRITE32_MEMBER( nubus_spec8s3_device::spec8s3_w )
break;
case 0x3a00:
- m_clutoffs = (data & 0xff) ^ 0xff;
+ m_clutoffs = ~data & 0xff;
break;
case 0x3a01:
-// printf("%08x to color (%08x invert)\n", data, data ^ 0xffffffff);
- m_colors[m_count++] = (data & 0xff) ^ 0xff;
+ LOG("%08x to color (%08x invert)\n", data, data ^ 0xffffffff);
+ // This rearrangement probably is actually in the scanout in the real
+ // hardware given the boards have a stock Bt478, but it's more performant
+ // for us to do it here.
+ if (m_count == 0)
+ {
+ m_ramdac->write(0, bitswap<8>(m_clutoffs, 0, 1, 2, 3, 4, 5, 6, 7));
+ }
+ m_ramdac->write(1, ~data & 0xff);
+ m_count++;
if (m_count == 3)
{
- int actual_color = bitswap<8>(m_clutoffs, 0, 1, 2, 3, 4, 5, 6, 7);
-
-// logerror("RAMDAC: color %d = %02x %02x %02x %s\n", actual_color, m_colors[0], m_colors[1], m_colors[2], machine().describe_context() );
- m_palette[actual_color] = rgb_t(m_colors[0], m_colors[1], m_colors[2]);
m_clutoffs++;
- if (m_clutoffs > 255)
- {
- m_clutoffs = 0;
- }
m_count = 0;
}
break;
case 0x3c00:
- if ((m_parameter == 2) && (data != 0xffffffff))
+ m_shiftreg.write_data(*this, data);
+ if (m_shiftreg.ready())
{
- data &= 0xff;
-// logerror("%x to mode\n", data);
- switch (data)
+ switch (m_shiftreg.select())
{
- case 0x5f:
- m_mode = 0;
- break;
-
- case 0x5e:
- m_mode = 1;
- break;
-
- case 0x5d:
- m_mode = 2;
- break;
-
- case 0x5c:
- m_mode = 3;
- break;
+ case 0:
+ // bit depth in low bits, other bits unknown
+ LOG("%s: %x to mode\n", machine().describe_context(), m_shiftreg.value());
+ m_mode = m_shiftreg.value() & 0x03;
+ break;
+ case 1:
+ // bits 0-2 and 7 are unknown
+ LOG("%s: %x to hpan\n", machine().describe_context(), m_shiftreg.value());
+ m_hpan = (m_hpan & 0x07f0) | ((m_shiftreg.value() >> 3) & 0x0f);
+ break;
+ default:
+ LOG("%s: %x to param %x\n", machine().describe_context(), m_shiftreg.value(), m_shiftreg.select());
}
}
- m_parameter++;
break;
case 0x3e02:
- if (data == 1)
- {
- m_parameter = 0;
- }
+ m_shiftreg.write_control(*this, data);
+ break;
+
+ case 0x3e05:
+ case 0x3e06:
+ case 0x3e07:
+ m_osc &= ~(1 << (offset - 0x3e05));
+ m_osc |= BIT(~data, 0) << (offset - 0x3e05);
+ // only update when the high bit is set to avoid bad intermediate values
+ if (offset == 0x3e07)
+ update_crtc();
break;
default:
@@ -308,18 +555,35 @@ WRITE32_MEMBER( nubus_spec8s3_device::spec8s3_w )
}
}
-READ32_MEMBER( nubus_spec8s3_device::spec8s3_r )
+u32 nubus_spec8s3_device::spec8s3_r(offs_t offset, u32 mem_mask)
{
switch (offset)
{
- case 0x3826:
+ case 0x382c:
case 0x382e:
+ {
+ // hack for interlace modes because screen_device doesn't support them
+ int vpos = screen().vpos();
+ if (m_interlace)
+ vpos /= 2;
+ return ~((vpos >> (BIT(offset, 1) ? 8 : 0)) & 0xff);
+ }
+
+ case 0x3826:
return 0xff;
case 0x3824:
- case 0x382c:
return (0xa^0xffffffff);
+ case 0x3846:
+ // it expects at least bits 2-7 will read back what was written
+ // only returning emulated feature fields for now
+ return ~(((m_zoom & 0x01) << 4) | ((m_vpan >> 8) & 0x03));
+
+ case 0x3848:
+ // it expects at least bit 7 will read back what was written
+ return ~((m_hpan >> 4) & 0xff);
+
case 0x385c:
if (m_vbl_pending)
{
@@ -337,13 +601,22 @@ READ32_MEMBER( nubus_spec8s3_device::spec8s3_r )
return 0;
}
-WRITE32_MEMBER( nubus_spec8s3_device::vram_w )
+void nubus_spec8s3_device::vram_w(offs_t offset, u32 data, u32 mem_mask)
{
data ^= 0xffffffff;
- COMBINE_DATA(&m_vram32[offset]);
+ COMBINE_DATA(&m_vram[offset]);
}
-READ32_MEMBER( nubus_spec8s3_device::vram_r )
+u32 nubus_spec8s3_device::vram_r(offs_t offset, u32 mem_mask)
{
- return m_vram32[offset] ^ 0xffffffff;
+ return m_vram[offset] ^ 0xffffffff;
}
+
+} // anonymous namespace
+
+
+//**************************************************************************
+// DEVICE TYPE DEFINITIONS
+//**************************************************************************
+
+DEFINE_DEVICE_TYPE_PRIVATE(NUBUS_SPEC8S3, device_nubus_card_interface, nubus_spec8s3_device, "nb_sp8s3", "SuperMac Spectrum/8 Series III video card")
diff --git a/src/devices/bus/nubus/nubus_spec8.h b/src/devices/bus/nubus/nubus_spec8.h
index 41cb94432d1..4e776d90e33 100644
--- a/src/devices/bus/nubus/nubus_spec8.h
+++ b/src/devices/bus/nubus/nubus_spec8.h
@@ -1,5 +1,5 @@
// license:BSD-3-Clause
-// copyright-holders:R. Belmont
+// copyright-holders:R. Belmont, Vas Crabb
#ifndef MAME_BUS_NUBUS_NUBUS_SPEC8_H
#define MAME_BUS_NUBUS_NUBUS_SPEC8_H
@@ -7,57 +7,7 @@
#include "nubus.h"
-//**************************************************************************
-// TYPE DEFINITIONS
-//**************************************************************************
-
-// ======================> nubus_spec8s3_device
-
-class nubus_spec8s3_device :
- public device_t,
- public device_video_interface,
- public device_nubus_card_interface
-{
-public:
- // construction/destruction
- nubus_spec8s3_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
-
-protected:
- nubus_spec8s3_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;
- virtual void device_timer(emu_timer &timer, device_timer_id id, int param, void *ptr) override;
-
-private:
- DECLARE_READ32_MEMBER(spec8s3_r);
- DECLARE_WRITE32_MEMBER(spec8s3_w);
- DECLARE_READ32_MEMBER(vram_r);
- DECLARE_WRITE32_MEMBER(vram_w);
-
- uint32_t screen_update(screen_device &screen, bitmap_rgb32 &bitmap, const rectangle &cliprect);
-
- std::vector<uint8_t> m_vram;
- uint32_t *m_vram32;
- uint32_t m_mode, m_vbl_disable;
- uint32_t m_palette[256], m_colors[3], m_count, m_clutoffs;
- emu_timer *m_timer;
-
- //uint32_t m_7xxxxx_regs[0x100000/4];
- //int m_width, m_height, m_patofsx, m_patofsy;
- //uint32_t m_vram_addr, m_vram_src;
- //uint8_t m_fillbytes[256];
- bool m_vbl_pending;
- int m_parameter;
-};
-
-
// device type definition
-DECLARE_DEVICE_TYPE(NUBUS_SPEC8S3, nubus_spec8s3_device)
+DECLARE_DEVICE_TYPE(NUBUS_SPEC8S3, device_nubus_card_interface)
#endif // MAME_BUS_NUBUS_NUBUS_SPEC8_H
diff --git a/src/devices/bus/nubus/nubus_specpdq.cpp b/src/devices/bus/nubus/nubus_specpdq.cpp
index 2e09a258bd2..d8403e1204c 100644
--- a/src/devices/bus/nubus/nubus_specpdq.cpp
+++ b/src/devices/bus/nubus/nubus_specpdq.cpp
@@ -1,53 +1,140 @@
// license:BSD-3-Clause
-// copyright-holders:R. Belmont
+// copyright-holders:R. Belmont, Vas Crabb
/***************************************************************************
SuperMac Spectrum PDQ video card
- Accelerated only in 256 color mode. Accleration is not yet emulated
- properly (pattern fill works but has glitches). Use in B&W or 16 colors
- for full functionality right now.
+ Accelerated only in 256 color mode.
+
+ Output is 3 discrete Bt458s, similar to other SuperMac cards of
+ the time like the Thunder II and Thunder II GX.
blitter info:
- ctrl 1 = ?
- ctrl 2 = low 3 bits of Y position in bits 3-5, low 3 bits of X position in bits 0-2
- ctrl 3 = width
- ctrl 4 = height
- ctrl 5 = ?
- ctrl 6 = VRAM offset * 4
- ctrl 7 = command/execute (00000002 for pattern fill, 00000100 for copy)
+ 06 = ?
+ 07 = command - 002 = pattern fill, 100/101 = copy forward/backward
+ 08 = pattern Y offset * 8
+ 09 = VRAM destination * 4
+ 0a = VRAM source * 4
+ 0b = height (inclusive)
+ 0e = width (exclusive)
Busy flag at Fs800000 (bit 8)
- There is 256 bytes of pattern RAM arranged as 32 pixels horizontally by 8
- vertically.
+ There is 256 bytes of pattern RAM arranged as 32 pixels horizontally by
+ 8 vertically.
+
+ TODO:
+ * Having no alternate oscillator installed is not emulated.
+ * Alternate oscillator calibration is currently failing. Fixing this
+ probably requires a complete cycle-accurate Mac II.
***************************************************************************/
#include "emu.h"
#include "nubus_specpdq.h"
+
+#include "supermac.h"
+
+#include "layout/generic.h"
#include "screen.h"
+#include <algorithm>
+
//#define VERBOSE 1
#include "logmacro.h"
-#define SPECPDQ_SCREEN_NAME "specpdq_screen"
+#define SPECPDQ_SCREEN_NAME "screen"
#define SPECPDQ_ROM_REGION "specpdq_rom"
-#define VRAM_SIZE (0x400000)
+#define VRAM_SIZE (0x40'0000)
-ROM_START( specpdq )
- ROM_REGION(0x10000, SPECPDQ_ROM_REGION, 0)
- ROM_LOAD( "specpdq.bin", 0x000000, 0x010000, CRC(82a35f78) SHA1(9511c2df47140f4279196d3b8836b53429879dd9) )
-ROM_END
+
+namespace {
//**************************************************************************
-// GLOBAL VARIABLES
+// TYPE DEFINITIONS
//**************************************************************************
-DEFINE_DEVICE_TYPE(NUBUS_SPECPDQ, nubus_specpdq_device, "nb_spdq", "SuperMac Spectrum PDQ video card")
+class nubus_specpdq_device :
+ public device_t,
+ public device_nubus_card_interface,
+ public device_video_interface,
+ public device_palette_interface
+{
+public:
+ // construction/destruction
+ nubus_specpdq_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock);
+
+protected:
+ nubus_specpdq_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, u32 clock);
+
+ // device-level overrides
+ virtual void device_start() override ATTR_COLD;
+ virtual void device_reset() override ATTR_COLD;
+
+ // optional information overrides
+ virtual void device_add_mconfig(machine_config &config) override ATTR_COLD;
+ virtual const tiny_rom_entry *device_rom_region() const override ATTR_COLD;
+ virtual ioport_constructor device_input_ports() const override ATTR_COLD;
+
+ // palette implementation
+ virtual u32 palette_entries() const noexcept override;
+
+ TIMER_CALLBACK_MEMBER(vbl_tick);
+
+private:
+ u32 specpdq_r(offs_t offset, u32 mem_mask = ~0);
+ void specpdq_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);
+
+ void blitter_pattern_fill();
+ void blitter_copy_forward();
+ void blitter_copy_backward();
+
+ void update_crtc();
+
+ u32 screen_update(screen_device &screen, bitmap_rgb32 &bitmap, const rectangle &cliprect);
+
+ required_ioport m_userosc;
+ emu_timer *m_timer;
+
+ supermac_spec_crtc m_crtc;
+ supermac_spec_shift_reg m_shiftreg;
+
+ std::vector<u32> m_vram;
+ u32 m_mode, m_vbl_disable;
+ u32 m_colors[3], m_count, m_clutoffs;
+
+ u16 m_stride;
+ u16 m_vint;
+ u8 m_hdelay, m_hadjust;
+ u8 m_osc;
+
+ u16 m_blit_stride;
+ u32 m_blit_src, m_blit_dst;
+ u32 m_blit_width, m_blit_height;
+ u8 m_blit_patoffs;
+ u32 m_blit_pat[64];
+
+ u32 m_7xxxxx_regs[0x100000 / 4];
+};
+
+
+INPUT_PORTS_START( specpdq )
+ PORT_START("USEROSC")
+ PORT_CONFNAME(0x07, 0x00, "Alternate oscillator")
+ PORT_CONFSETTING( 0x00, "55.00 MHz (SuperMac 16\")")
+ PORT_CONFSETTING( 0x01, "57.28 MHz (Apple Portrait)")
+ PORT_CONFSETTING( 0x02, "64.00 MHz (SuperMac 19\" 60hz)")
+INPUT_PORTS_END
+
+ROM_START( specpdq )
+ ROM_REGION(0x10000, SPECPDQ_ROM_REGION, 0)
+ ROM_LOAD( "specpdq.bin", 0x000000, 0x010000, CRC(82a35f78) SHA1(9511c2df47140f4279196d3b8836b53429879dd9) )
+ROM_END
//-------------------------------------------------
@@ -56,13 +143,12 @@ DEFINE_DEVICE_TYPE(NUBUS_SPECPDQ, nubus_specpdq_device, "nb_spdq", "SuperMac Spe
void nubus_specpdq_device::device_add_mconfig(machine_config &config)
{
+ config.set_default_layout(layout_monitors);
+
screen_device &screen(SCREEN(config, SPECPDQ_SCREEN_NAME, SCREEN_TYPE_RASTER));
screen.set_screen_update(FUNC(nubus_specpdq_device::screen_update));
- screen.set_raw(25175000, 800, 0, 640, 525, 0, 480);
- screen.set_size(1280, 1024);
- screen.set_visarea(0, 1152-1, 0, 844-1);
-
- PALETTE(config, m_palette).set_entries(256);
+ screen.set_raw(100.000_MHz_XTAL, 1'456, 108, 1'260, 915, 39, 909);
+ screen.set_video_attributes(VIDEO_UPDATE_SCANLINE);
}
//-------------------------------------------------
@@ -74,6 +160,25 @@ const tiny_rom_entry *nubus_specpdq_device::device_rom_region() const
return ROM_NAME( specpdq );
}
+//-------------------------------------------------
+// input_ports - device-specific I/O ports
+//-------------------------------------------------
+
+ioport_constructor nubus_specpdq_device::device_input_ports() const
+{
+ return INPUT_PORTS_NAME( specpdq );
+}
+
+//-------------------------------------------------
+// palette_entries - entries in color palette
+//-------------------------------------------------
+
+u32 nubus_specpdq_device::palette_entries() const noexcept
+{
+ return 256;
+}
+
+
//**************************************************************************
// LIVE DEVICE
//**************************************************************************
@@ -82,18 +187,19 @@ const tiny_rom_entry *nubus_specpdq_device::device_rom_region() const
// nubus_specpdq_device - constructor
//-------------------------------------------------
-nubus_specpdq_device::nubus_specpdq_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) :
+nubus_specpdq_device::nubus_specpdq_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock) :
nubus_specpdq_device(mconfig, NUBUS_SPECPDQ, tag, owner, clock)
{
}
-nubus_specpdq_device::nubus_specpdq_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock) :
+nubus_specpdq_device::nubus_specpdq_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_vram32(nullptr), m_mode(0), m_vbl_disable(0), m_count(0), m_clutoffs(0), m_timer(nullptr),
- m_width(0), m_height(0), m_patofsx(0), m_patofsy(0), m_vram_addr(0), m_vram_src(0),
- m_palette(*this, "palette")
+ device_video_interface(mconfig, *this),
+ device_palette_interface(mconfig, *this),
+ m_userosc(*this, "USEROSC"),
+ m_timer(nullptr),
+ m_mode(0)
{
set_screen(*this, SPECPDQ_SCREEN_NAME);
}
@@ -104,21 +210,39 @@ nubus_specpdq_device::nubus_specpdq_device(const machine_config &mconfig, device
void nubus_specpdq_device::device_start()
{
- uint32_t slotspace;
-
- install_declaration_rom(this, SPECPDQ_ROM_REGION);
-
- slotspace = get_slotspace();
-
-// logerror("[specpdq %p] slotspace = %x\n", this, slotspace);
-
- m_vram.resize(VRAM_SIZE);
- m_vram32 = (uint32_t *)&m_vram[0];
- nubus().install_device(slotspace, slotspace+VRAM_SIZE-1, read32_delegate(FUNC(nubus_specpdq_device::vram_r), this), write32_delegate(FUNC(nubus_specpdq_device::vram_w), this));
- nubus().install_device(slotspace+0x400000, slotspace+0xfbffff, read32_delegate(FUNC(nubus_specpdq_device::specpdq_r), this), write32_delegate(FUNC(nubus_specpdq_device::specpdq_w), this));
-
- m_timer = timer_alloc(0, nullptr);
- m_timer->adjust(screen().time_until_pos(843, 0), 0);
+ install_declaration_rom(SPECPDQ_ROM_REGION);
+
+ u32 const slotspace = get_slotspace();
+ LOG("[specpdq %p] slotspace = %x\n", this, slotspace);
+
+ m_vram.resize(VRAM_SIZE / sizeof(u32));
+ nubus().install_device(slotspace, slotspace+VRAM_SIZE-1, read32s_delegate(*this, FUNC(nubus_specpdq_device::vram_r)), write32s_delegate(*this, FUNC(nubus_specpdq_device::vram_w)));
+ nubus().install_device(slotspace+0x400000, slotspace+0xfbffff, read32s_delegate(*this, FUNC(nubus_specpdq_device::specpdq_r)), write32s_delegate(*this, FUNC(nubus_specpdq_device::specpdq_w)));
+
+ m_timer = timer_alloc(FUNC(nubus_specpdq_device::vbl_tick), this);
+
+ m_crtc.register_save(*this);
+ m_shiftreg.register_save(*this);
+
+ save_item(NAME(m_vram));
+ 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_item(NAME(m_stride));
+ save_item(NAME(m_vint));
+ save_item(NAME(m_hdelay));
+ save_item(NAME(m_hadjust));
+ save_item(NAME(m_osc));
+ save_item(NAME(m_blit_stride));
+ save_item(NAME(m_blit_src));
+ save_item(NAME(m_blit_dst));
+ save_item(NAME(m_blit_width));
+ save_item(NAME(m_blit_height));
+ save_item(NAME(m_blit_patoffs));
+ save_item(NAME(m_blit_pat));
+ save_item(NAME(m_7xxxxx_regs));
}
//-------------------------------------------------
@@ -127,26 +251,42 @@ void nubus_specpdq_device::device_start()
void nubus_specpdq_device::device_reset()
{
+ m_crtc.reset();
+ m_shiftreg.reset();
+
+ std::fill(m_vram.begin(), m_vram.end(), 0);
+ m_mode = 0;
+ m_vbl_disable = 1;
+ std::fill(std::begin(m_colors), std::end(m_colors), 0);
m_count = 0;
m_clutoffs = 0;
- m_vbl_disable = 1;
- m_mode = 0;
- memset(&m_vram[0], 0, VRAM_SIZE);
- memset(m_palette_val, 0, sizeof(m_palette_val));
- m_palette_val[0] = rgb_t(255, 255, 255);
- m_palette_val[0x80] = rgb_t(0, 0, 0);
+ m_stride = 0;
+ m_vint = 0;
+ m_hdelay = 0;
+ m_hadjust = 0;
+ m_osc = 0;
+
+ m_blit_stride = 0;
+ m_blit_src = 0;
+ m_blit_dst = 0;
+ m_blit_width = 0;
+ m_blit_height = 0;
+ m_blit_patoffs = 0;
+ std::fill(std::begin(m_blit_pat), std::end(m_blit_pat), 0);
+
+ std::fill(std::begin(m_7xxxxx_regs), std::end(m_7xxxxx_regs), 0);
}
-void nubus_specpdq_device::device_timer(emu_timer &timer, device_timer_id tid, int param, void *ptr)
+TIMER_CALLBACK_MEMBER(nubus_specpdq_device::vbl_tick)
{
if (!m_vbl_disable)
{
raise_slot_irq();
}
- m_timer->adjust(screen().time_until_pos(843, 0), 0);
+ m_timer->adjust(screen().time_until_pos(m_vint));
}
/***************************************************************************
@@ -155,98 +295,209 @@ void nubus_specpdq_device::device_timer(emu_timer &timer, device_timer_id tid, i
***************************************************************************/
-uint32_t nubus_specpdq_device::screen_update(screen_device &screen, bitmap_rgb32 &bitmap, const rectangle &cliprect)
+void nubus_specpdq_device::update_crtc()
+{
+ XTAL oscillator = 100.000_MHz_XTAL; // no default constructor
+ switch (m_osc)
+ {
+ case 0:
+ switch (m_userosc->read())
+ {
+ case 0:
+ oscillator = 55.00_MHz_XTAL;
+ break;
+ case 1:
+ oscillator = 57.28_MHz_XTAL;
+ break;
+ case 2:
+ oscillator = 64.00_MHz_XTAL;
+ break;
+ default:
+ throw emu_fatalerror("%s: specpdq: invalid user oscillator selection %d\n", tag(), m_userosc->read());
+ }
+ break;
+ case 1:
+ oscillator = 80.00_MHz_XTAL;
+ break;
+ case 2:
+ oscillator = 100.00_MHz_XTAL;
+ break;
+ case 3:
+ oscillator = 30.24_MHz_XTAL;
+ break;
+ }
+
+ // for some reason you temporarily get invalid screen parameters - ignore them
+ if (m_crtc.valid(*this))
+ {
+ // FIXME: there's still something missing in the active width calculation
+ // With the Apple RGB (640*480) monitor selected, the active width is 16 pixels
+ // too wide in black and white mode, and 16 pixels too narrow in greyscale or
+ // colour modes.
+ rectangle const active(
+ m_crtc.h_start(16) + (m_hdelay * 4),
+ m_crtc.h_end(16) + (m_hdelay * 4) - m_hadjust - 1,
+ m_crtc.v_start(),
+ m_crtc.v_end() - 1);
+
+ screen().configure(
+ m_crtc.h_total(16),
+ m_crtc.v_total(),
+ active,
+ m_crtc.frame_time(16, oscillator));
+
+ m_timer->adjust(screen().time_until_pos(m_vint + m_crtc.v_start() - 1));
+ }
+}
+
+u32 nubus_specpdq_device::screen_update(screen_device &screen, bitmap_rgb32 &bitmap, const rectangle &cliprect)
{
- uint32_t *scanline;
- int x, y;
- uint8_t pixels, *vram;
+ auto const screenbase = util::big_endian_cast<u8 const>(&m_vram[0]) + 0x9000;
- // first time? kick off the VBL timer
- vram = &m_vram[0x9000];
+ int const hstart = m_crtc.h_start(16);
+ int const width = m_crtc.h_active(16);
+ int const vstart = m_crtc.v_start();
+ int const vend = m_crtc.v_end();
+ int const hdelay = m_hdelay * 4;
switch (m_mode)
{
case 0: // 1 bpp
- for (y = 0; y < 844; y++)
+ for (int y = cliprect.top(); y <= cliprect.bottom(); y++)
{
- scanline = &bitmap.pix32(y);
- for (x = 0; x < 1152/8; x++)
+ u32 *scanline = &bitmap.pix(y, hstart);
+ if ((y >= vstart) && (y < vend))
+ {
+ scanline = std::fill_n(scanline, hdelay, 0);
+ auto const rowbase = screenbase + ((y - vstart) * m_stride * 4);
+ for (int x = 0; x < ((width - hdelay + 7) / 8); x++)
+ {
+ u8 const pixels = rowbase[x];
+
+ *scanline++ = pen_color((pixels << 0) & 0x80);
+ *scanline++ = pen_color((pixels << 1) & 0x80);
+ *scanline++ = pen_color((pixels << 2) & 0x80);
+ *scanline++ = pen_color((pixels << 3) & 0x80);
+ *scanline++ = pen_color((pixels << 4) & 0x80);
+ *scanline++ = pen_color((pixels << 5) & 0x80);
+ *scanline++ = pen_color((pixels << 6) & 0x80);
+ *scanline++ = pen_color((pixels << 7) & 0x80);
+ }
+ }
+ else
{
- pixels = vram[(y * 512) + (BYTE4_XOR_BE(x))];
-
- *scanline++ = m_palette_val[(pixels&0x80)];
- *scanline++ = m_palette_val[((pixels<<1)&0x80)];
- *scanline++ = m_palette_val[((pixels<<2)&0x80)];
- *scanline++ = m_palette_val[((pixels<<3)&0x80)];
- *scanline++ = m_palette_val[((pixels<<4)&0x80)];
- *scanline++ = m_palette_val[((pixels<<5)&0x80)];
- *scanline++ = m_palette_val[((pixels<<6)&0x80)];
- *scanline++ = m_palette_val[((pixels<<7)&0x80)];
+ std::fill_n(scanline, width, 0);
}
}
break;
case 1: // 2 bpp
- for (y = 0; y < 844; y++)
+ for (int y = cliprect.top(); y <= cliprect.bottom(); y++)
{
- scanline = &bitmap.pix32(y);
- for (x = 0; x < 1152/4; x++)
+ u32 *scanline = &bitmap.pix(y, hstart);
+ if ((y >= vstart) && (y < vend))
{
- pixels = vram[(y * 512) + (BYTE4_XOR_BE(x))];
+ scanline = std::fill_n(scanline, hdelay, 0);
+ auto const rowbase = screenbase + ((y - vstart) * m_stride * 4);
+ for (int x = 0; x < ((width - hdelay) / 4); x++)
+ {
+ u8 const pixels = rowbase[x];
- *scanline++ = m_palette_val[(pixels&0xc0)];
- *scanline++ = m_palette_val[((pixels<<2)&0xc0)];
- *scanline++ = m_palette_val[((pixels<<4)&0xc0)];
- *scanline++ = m_palette_val[((pixels<<6)&0xc0)];
+ *scanline++ = pen_color((pixels << 0) & 0xc0);
+ *scanline++ = pen_color((pixels << 2) & 0xc0);
+ *scanline++ = pen_color((pixels << 4) & 0xc0);
+ *scanline++ = pen_color((pixels << 6) & 0xc0);
+ }
+ }
+ else
+ {
+ std::fill_n(scanline, width, 0);
}
}
break;
case 2: // 4 bpp
- for (y = 0; y < 844; y++)
+ for (int y = cliprect.top(); y <= cliprect.bottom(); y++)
{
- scanline = &bitmap.pix32(y);
-
- for (x = 0; x < 1152/2; x++)
+ u32 *scanline = &bitmap.pix(y, hstart);
+ if ((y >= vstart) && (y < vend))
{
- pixels = vram[(y * 1024) + (BYTE4_XOR_BE(x))];
+ scanline = std::fill_n(scanline, hdelay, 0);
+ auto const rowbase = screenbase + ((y - vstart) * m_stride * 4);
+ for (int x = 0; x < ((width - hdelay) / 2); x++)
+ {
+ u8 const pixels = rowbase[x];
- *scanline++ = m_palette_val[(pixels&0xf0)];
- *scanline++ = m_palette_val[((pixels<<4)&0xf0)];
+ *scanline++ = pen_color((pixels << 0) & 0xf0);
+ *scanline++ = pen_color((pixels << 4) & 0xf0);
+ }
+ }
+ else
+ {
+ std::fill_n(scanline, width, 0);
}
}
break;
case 3: // 8 bpp
- for (y = 0; y < 844; y++)
+ for (int y = cliprect.top(); y <= cliprect.bottom(); y++)
{
- scanline = &bitmap.pix32(y);
-
- for (x = 0; x < 1152; x++)
+ u32 *scanline = &bitmap.pix(y, hstart);
+ if ((y >= vstart) && (y < vend))
{
- pixels = vram[(y * 1152) + (BYTE4_XOR_BE(x))];
- *scanline++ = m_palette_val[pixels];
+ scanline = std::fill_n(scanline, hdelay, 0);
+ auto const rowbase = screenbase + ((y - vstart) * m_stride * 4);
+ for (int x = 0; x < (width - hdelay); x++)
+ {
+ u8 const pixels = rowbase[x];
+ *scanline++ = pen_color(pixels);
+ }
+ }
+ else
+ {
+ std::fill_n(scanline, width, 0);
}
}
break;
default:
- fatalerror("specpdq: unknown video mode %d\n", m_mode);
+ throw emu_fatalerror("specpdq: unknown video mode %d\n", m_mode);
}
return 0;
}
-WRITE32_MEMBER( nubus_specpdq_device::specpdq_w )
+void nubus_specpdq_device::specpdq_w(offs_t offset, u32 data, u32 mem_mask)
{
if (offset >= 0xc0000 && offset < 0x100000)
{
COMBINE_DATA(&m_7xxxxx_regs[offset-0xc0000]);
}
- switch (offset)
+ if ((offset >= 0xc0000) && (offset <= 0xc002a))
+ {
+ m_crtc.write(*this, offset - 0xc0000, data >> 24);
+ update_crtc();
+ }
+ else if ((offset >= 0x181000) && (offset <= 0x18103f))
{
- case 0xc0054: // mode 1
- LOG("%x to mode1\n", data);
+ // 256 pixels worth at 8 bpp
+ m_blit_pat[offset & 0x3f] = ~data;
+ }
+ else switch (offset)
+ {
+ case 0xc0030:
+ case 0xc0032:
+ m_vint &= BIT(offset, 1) ? 0x00ff : 0xff00;
+ m_vint |= (~data & 0xff000000) >> (BIT(offset, 1) ? 16 : 24);
+ update_crtc();
+ LOG("%s: %u to vint\n", machine().describe_context(), m_vint);
+ break;
+
+ case 0xc0054:
+ case 0xc0056:
+ m_stride &= BIT(offset, 1) ? 0x00ff : 0xff00;
+ m_stride |= (~data & 0xff000000) >> (BIT(offset, 1) ? 16 : 24);
+ LOG("%s: %u to stride\n", machine().describe_context(), m_stride);
break;
case 0xc005c: // interrupt control
@@ -264,235 +515,152 @@ WRITE32_MEMBER( nubus_specpdq_device::specpdq_w )
case 0xc005e: // not sure, interrupt related?
break;
- case 0xc007a:
- LOG("%x to mode2\n", data);
-
- switch (data)
- {
- case 0xff7fffff:
- m_mode = 0;
- break;
-
- case 0xfeffffff:
- m_mode = 2;
- break;
+ case 0xc0066:
+ LOG("%s: %u to hadjust\n", machine().describe_context(), ~data & 0xff);
+ m_hadjust = ~data & 0xff;
+ update_crtc();
+ break;
- case 0xfedfffff:
- m_mode = 3;
- break;
- }
+ case 0xc006a:
+ LOG("%s: %u to hdelay\n", machine().describe_context(), ~data & 0xff);
+ m_hdelay = ~data & 0xff;
+ update_crtc();
+ break;
- LOG("m_mode = %d\n", m_mode);
+ case 0xc0078:
+ case 0xc007a:
+ m_blit_stride &= BIT(offset, 1) ? 0x00ff : 0xff00;
+ m_blit_stride |= (~data & 0xff000000) >> (BIT(offset, 1) ? 16 : 24);
+ LOG("%s: %u to blitter stride\n", machine().describe_context(), m_blit_stride);
break;
case 0x120000: // DAC address
- LOG("%08x to DAC control %s\n", data,machine().describe_context());
- m_clutoffs = ((data>>8)&0xff)^0xff;
+ LOG("%s: %08x to DAC control\n", machine().describe_context(), data);
+ m_clutoffs = ~data & 0xff;
break;
case 0x120001: // DAC data
- m_colors[m_count++] = ((data>>8)&0xff)^0xff;
+ m_colors[m_count++] = ~(data >> 8) & 0xff;
if (m_count == 3)
{
LOG("RAMDAC: color %d = %02x %02x %02x %s\n", m_clutoffs, m_colors[0], m_colors[1], m_colors[2], machine().describe_context());
- m_palette->set_pen_color(m_clutoffs, rgb_t(m_colors[0], m_colors[1], m_colors[2]));
- m_palette_val[m_clutoffs] = rgb_t(m_colors[0], m_colors[1], m_colors[2]);
- m_clutoffs++;
- if (m_clutoffs > 255)
- {
- m_clutoffs = 0;
- }
+ set_pen_color(m_clutoffs, rgb_t(m_colors[0], m_colors[1], m_colors[2]));
+ m_clutoffs = (m_clutoffs + 1) & 0xff;
m_count = 0;
}
break;
- // blitter texture? pattern? 256 pixels worth at 8bpp
- case 0x181000:
- case 0x181001:
- case 0x181002:
- case 0x181003:
- case 0x181004:
- case 0x181005:
- case 0x181006:
- case 0x181007:
- case 0x181008:
- case 0x181009:
- case 0x18100a:
- case 0x18100b:
- case 0x18100c:
- case 0x18100d:
- case 0x18100e:
- case 0x18100f:
- case 0x181010:
- case 0x181011:
- case 0x181012:
- case 0x181013:
- case 0x181014:
- case 0x181015:
- case 0x181016:
- case 0x181017:
- case 0x181018:
- case 0x181019:
- case 0x18101a:
- case 0x18101b:
- case 0x18101c:
- case 0x18101d:
- case 0x18101e:
- case 0x18101f:
- case 0x181020:
- case 0x181021:
- case 0x181022:
- case 0x181023:
- case 0x181024:
- case 0x181025:
- case 0x181026:
- case 0x181027:
- case 0x181028:
- case 0x181029:
- case 0x18102a:
- case 0x18102b:
- case 0x18102c:
- case 0x18102d:
- case 0x18102e:
- case 0x18102f:
- case 0x181030:
- case 0x181031:
- case 0x181032:
- case 0x181033:
- case 0x181034:
- case 0x181035:
- case 0x181036:
- case 0x181037:
- case 0x181038:
- case 0x181039:
- case 0x18103a:
- case 0x18103b:
- case 0x18103c:
- case 0x18103d:
- case 0x18103e:
- case 0x18103f:
- if(offset == 0x181000) {
- machine().debug_break();
- LOG("Pattern %08x @ %x\n", data ^ 0xffffffff, offset);
+ case 0x140000:
+ m_shiftreg.write_data(*this, data);
+ if (m_shiftreg.ready())
+ {
+ switch (m_shiftreg.select())
+ {
+ case 0:
+ // bit depth in low bits, other bits unknown
+ LOG("%s: %x to mode\n", machine().describe_context(), m_shiftreg.value());
+ m_mode = m_shiftreg.value() & 0x03;
+ break;
+ default:
+ LOG("%s: %x to param %x\n", machine().describe_context(), m_shiftreg.value(), m_shiftreg.select());
+ }
}
- m_fillbytes[((offset&0x3f)*4)] = ((data>>24) & 0xff) ^ 0xff;
- m_fillbytes[((offset&0x3f)*4)+1] = ((data>>16) & 0xff) ^ 0xff;
- m_fillbytes[((offset&0x3f)*4)+2] = ((data>>8) & 0xff) ^ 0xff;
- m_fillbytes[((offset&0x3f)*4)+3] = (data& 0xff) ^ 0xff;
break;
- // blitter control
- case 0x182006:
- LOG("%08x (%d) to blitter ctrl 1 %s rectangle\n", data^0xffffffff, data^0xffffffff, machine().describe_context());
+ case 0x160000:
+ case 0x160001:
+ m_osc &= ~(1 << (BIT(offset, 0)));
+ m_osc |= BIT(~data, 0) << BIT(offset, 0);
+ LOG("%s: %u to osc\n", machine().describe_context(), m_osc);
break;
- case 0x182008:
- LOG("%08x (%d) to blitter ctrl 2 %s rectangle\n", data^0xffffffff, data^0xffffffff, machine().describe_context());
- m_patofsx = (data ^ 0xffffffff) & 7;
- m_patofsy = ((data ^ 0xffffffff)>>3) & 7;
+ case 0x160007:
+ m_shiftreg.write_control(*this, data);
break;
- case 0x18200e:
- LOG("%08x (%d) to blitter ctrl 3 %s\n", data^0xffffffff, data^0xffffffff, machine().describe_context());
- m_width = data ^ 0xffffffff;
+ case 0x182006:
+ data = ~data;
+ LOG("%08x (%d) to blitter ctrl 1 %s rectangle\n", data, data, machine().describe_context());
break;
- case 0x18200b:
- LOG("%08x (%d) to blitter ctrl 4 %s\n", data^0xffffffff, data^0xffffffff, machine().describe_context());
- m_height = (data ^ 0xffffffff) & 0xffff;
+ case 0x182007:
+ data = ~data;
+ LOG("%s: %08x to blitter command\n", machine().describe_context(), data);
+ switch (data)
+ {
+ case 0x002:
+ blitter_pattern_fill();
+ break;
+ case 0x100:
+ blitter_copy_forward();
+ break;
+ case 0x101:
+ blitter_copy_backward();
+ break;
+ default:
+ logerror("Unknown blitter command %08x\n", data);
+ }
break;
- case 0x18200a:
- data ^= 0xffffffff;
- LOG("%08x to blitter ctrl 5 %s\n", data, machine().describe_context());
- m_vram_src = data>>2;
+ case 0x182008:
+ data = ~data;
+ LOG("%s: %08x (%d) to blitter ctrl 2 rectangle\n", machine().describe_context(), data, data);
+ m_blit_patoffs = (data >> 3) & 0x1fff;
break;
case 0x182009:
- data ^= 0xffffffff;
- LOG("%08x to blitter ctrl 6 %s\n", data, machine().describe_context());
- m_vram_addr = data>>2;
+ data = ~data;
+ LOG("%s: %08x to blitter destination\n", machine().describe_context(), data);
+ m_blit_dst = (data >> 2) & 0x3fffff;
break;
- case 0x182007:
- data ^= 0xffffffff;
- LOG("%08x to blitter ctrl 7 %s\n", data, machine().describe_context());
-
- // fill rectangle
- if (data == 2)
- {
- int x, y;
- uint8_t *vram = &m_vram[m_vram_addr & ~3];
-
- int ddx = m_vram_addr & 3;
-
- LOG("Fill rectangle with %02x %02x %02x %02x, adr %x (%d, %d) width %d height %d delta %d %d\n", m_fillbytes[0], m_fillbytes[1], m_fillbytes[2], m_fillbytes[3], m_vram_addr, m_vram_addr % 1152, m_vram_addr / 1152, m_width, m_height, m_patofsx, m_patofsy);
-
- for (y = 0; y <= m_height; y++)
- {
- for (x = 0; x <= m_width; x++)
- {
- vram[(y * 1152)+BYTE4_XOR_BE(x + ddx)] = m_fillbytes[((m_patofsx + x) & 0x1f)+(((m_patofsy + y) & 0x7) << 5)];
- }
- }
- }
- else if (data == 0x100)
- {
- int x, y;
- uint8_t *vram = &m_vram[m_vram_addr & ~3];
- uint8_t *vramsrc = &m_vram[m_vram_src & ~3];
-
- int sdx = m_vram_src & 3;
- int ddx = m_vram_addr & 3;
-
- LOG("Copy rectangle forwards, width %d height %d dst %x (%d, %d) src %x (%d, %d)\n", m_width, m_height, m_vram_addr, m_vram_addr % 1152, m_vram_addr / 1152, m_vram_src, m_vram_src % 1152, m_vram_src / 1152);
-
- for (y = 0; y <= m_height; y++)
- {
- for (x = 0; x <= m_width; x++)
- {
- vram[(y * 1152)+BYTE4_XOR_BE(x + ddx)] = vramsrc[(y * 1152)+BYTE4_XOR_BE(x + sdx)];
- }
- }
- (void)vramsrc; (void)sdx;
- }
- else if (data == 0x101)
- {
- int x, y;
- uint8_t *vram = &m_vram[m_vram_addr & ~3];
- uint8_t *vramsrc = &m_vram[m_vram_src & ~3];
-
- int sdx = m_vram_src & 3;
- int ddx = m_vram_addr & 3;
+ case 0x18200a:
+ data = ~data;
+ LOG("%s: %08x to blitter source\n", machine().describe_context(), data);
+ m_blit_src = (data >> 2) & 0x3fffff;
+ break;
- LOG("Copy rectangle backwards, width %d height %d dst %x (%d, %d) src %x (%d, %d)\n", m_width, m_height, m_vram_addr, m_vram_addr % 1152, m_vram_addr / 1152, m_vram_src, m_vram_src % 1152, m_vram_src / 1152);
+ case 0x18200b:
+ data = ~data;
+ LOG("%s: %08x (%d) to blitter height\n", machine().describe_context(), data, data);
+ m_blit_height = data;
+ break;
- for (y = 0; y < m_height; y++)
- {
- for (x = 0; x < m_width; x++)
- {
- vram[(-y * 1152)+BYTE4_XOR_BE(-x + ddx)] = vramsrc[(-y * 1152)+BYTE4_XOR_BE(-x + sdx)];
- }
- }
- (void)vramsrc; (void)sdx;
- }
- else
- {
- LOG("Unknown blitter command %08x\n", data);
- }
+ case 0x18200e:
+ data = ~data;
+ LOG("%s: %08x (%d) to blitter width\n", machine().describe_context(), data, data);
+ m_blit_width = data;
break;
default:
- LOG("specpdq_w: %08x @ %x (mask %08x %s)\n", data^0xffffffff, offset, mem_mask, machine().describe_context());
+ LOG("%s: specpdq_w: %08x @ %x (mask %08x)\n", machine().describe_context(), data^0xffffffff, offset, mem_mask);
break;
}
}
-READ32_MEMBER( nubus_specpdq_device::specpdq_r )
+u32 nubus_specpdq_device::specpdq_r(offs_t offset, u32 mem_mask)
{
// if (offset != 0xc005c && offset != 0xc005e) logerror("specpdq_r: @ %x (mask %08x %s)\n", offset, mem_mask, machine().describe_context());
+ switch (offset)
+ {
+ case 0xc002c:
+ case 0xc002e:
+ /*
+ * FIXME: Oscillator calibration is failing.
+ * Set breakpoint at 0x2e0c on Mac II with card in
+ * slot 9 to catch user oscillator measurement. See the
+ * measured value in D0.b when PC = 0x2e48.
+ *
+ * Measured:
+ * 55.00 MHz 64 detected as 55.00 MHz
+ * 57.28 MHz 1 detected as 55.00 MHz
+ * 64.00 MHz 9 detected as 57.28 MHz
+ */
+ return ~((u32(screen().vpos()) << (BIT(offset, 1) ? 16 : 24)) & 0xff000000);
+ }
+
if (offset >= 0xc0000 && offset < 0x100000)
{
return m_7xxxxx_regs[offset-0xc0000];
@@ -501,13 +669,77 @@ READ32_MEMBER( nubus_specpdq_device::specpdq_r )
return 0;
}
-WRITE32_MEMBER( nubus_specpdq_device::vram_w )
+void nubus_specpdq_device::vram_w(offs_t offset, u32 data, u32 mem_mask)
+{
+ data = ~data;
+ COMBINE_DATA(&m_vram[offset]);
+}
+
+u32 nubus_specpdq_device::vram_r(offs_t offset, u32 mem_mask)
+{
+ return ~m_vram[offset];
+}
+
+void nubus_specpdq_device::blitter_pattern_fill()
{
- data ^= 0xffffffff;
- COMBINE_DATA(&m_vram32[offset]);
+ auto const source = util::big_endian_cast<u8 const>(m_blit_pat);
+ auto const dest = util::big_endian_cast<u8>(&m_vram[0]);
+ u32 const patofsx = m_blit_dst & 0x3;
+ u32 const stride = m_blit_stride * 4;
+ LOG("Fill rectangle with %02x %02x %02x %02x, adr %x (%d, %d) width %d height %d delta %d\n",
+ source[0], source[1], source[2], source[3],
+ m_blit_dst, m_blit_dst % (m_blit_stride * 4), m_blit_dst / (m_blit_stride * 4),
+ m_blit_width, m_blit_height, m_blit_patoffs);
+ for (int y = 0; y <= m_blit_height; y++)
+ {
+ for (int x = 0; x < m_blit_width; x++)
+ {
+ dest[(m_blit_dst + (y * stride) + x) & (VRAM_SIZE - 1)] = source[(((m_blit_patoffs + y) & 0x7) << 5) | ((patofsx + x) & 0x1f)];
+ }
+ }
}
-READ32_MEMBER( nubus_specpdq_device::vram_r )
+void nubus_specpdq_device::blitter_copy_forward()
{
- return m_vram32[offset] ^ 0xffffffff;
+ LOG("Copy rectangle forwards, width %d height %d dst %x (%d, %d) src %x (%d, %d)\n",
+ m_blit_width, m_blit_height,
+ m_blit_dst, m_blit_dst % (m_blit_stride * 4), m_blit_dst / (m_blit_stride * 4),
+ m_blit_src, m_blit_src % (m_blit_stride * 4), m_blit_src / (m_blit_stride * 4));
+ auto const source = util::big_endian_cast<u8 const>(&m_vram[0]);
+ auto const dest = util::big_endian_cast<u8>(&m_vram[0]);
+ u32 const stride = m_blit_stride * 4;
+ for (int y = 0; y <= m_blit_height; y++)
+ {
+ for (int x = 0; x < m_blit_width; x++)
+ {
+ dest[(m_blit_dst + (y * stride) + x) & (VRAM_SIZE - 1)] = source[(m_blit_src + (y * stride) + x) & (VRAM_SIZE - 1)];
+ }
+ }
}
+
+void nubus_specpdq_device::blitter_copy_backward()
+{
+ LOG("Copy rectangle backwards, width %d height %d dst %x (%d, %d) src %x (%d, %d)\n",
+ m_blit_width, m_blit_height,
+ m_blit_dst, m_blit_dst % (m_blit_stride * 4), m_blit_dst / (m_blit_stride * 4),
+ m_blit_src, m_blit_src % (m_blit_stride * 4), m_blit_src / (m_blit_stride * 4));
+ auto const source = util::big_endian_cast<u8 const>(&m_vram[0]);
+ auto const dest = util::big_endian_cast<u8>(&m_vram[0]);
+ u32 const stride = m_blit_stride * 4;
+ for (int y = 0; y <= m_blit_height; y++)
+ {
+ for (int x = 0; x < m_blit_width; x++)
+ {
+ dest[(m_blit_dst - (y * stride) - x) & (VRAM_SIZE - 1)] = source[(m_blit_src - (y * stride) - x) & (VRAM_SIZE - 1)];
+ }
+ }
+}
+
+} // anonymous namespace
+
+
+//**************************************************************************
+// DEVICE TYPE DEFINITIONS
+//**************************************************************************
+
+DEFINE_DEVICE_TYPE_PRIVATE(NUBUS_SPECPDQ, device_nubus_card_interface, nubus_specpdq_device, "nb_spdq", "SuperMac Spectrum PDQ video card")
diff --git a/src/devices/bus/nubus/nubus_specpdq.h b/src/devices/bus/nubus/nubus_specpdq.h
index 448b13d4957..01472da292e 100644
--- a/src/devices/bus/nubus/nubus_specpdq.h
+++ b/src/devices/bus/nubus/nubus_specpdq.h
@@ -1,63 +1,13 @@
// license:BSD-3-Clause
-// copyright-holders:R. Belmont
+// copyright-holders:R. Belmont, Vas Crabb
#ifndef MAME_BUS_NUBUS_NUBUS_SPECPDQ_H
#define MAME_BUS_NUBUS_NUBUS_SPECPDQ_H
#pragma once
#include "nubus.h"
-#include "emupal.h"
-
-//**************************************************************************
-// TYPE DEFINITIONS
-//**************************************************************************
-
-// ======================> nubus_specpdq_device
-
-class nubus_specpdq_device :
- public device_t,
- public device_video_interface,
- public device_nubus_card_interface
-{
-public:
- // construction/destruction
- nubus_specpdq_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
-
-protected:
- nubus_specpdq_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;
- virtual void device_timer(emu_timer &timer, device_timer_id id, int param, void *ptr) override;
-
-private:
- DECLARE_READ32_MEMBER(specpdq_r);
- DECLARE_WRITE32_MEMBER(specpdq_w);
- DECLARE_READ32_MEMBER(vram_r);
- DECLARE_WRITE32_MEMBER(vram_w);
-
- uint32_t screen_update(screen_device &screen, bitmap_rgb32 &bitmap, const rectangle &cliprect);
-
- std::vector<uint8_t> m_vram;
- uint32_t *m_vram32;
- uint32_t m_mode, m_vbl_disable;
- uint32_t m_palette_val[256], m_colors[3], m_count, m_clutoffs;
- emu_timer *m_timer;
-
- uint32_t m_7xxxxx_regs[0x100000/4];
- int m_width, m_height, m_patofsx, m_patofsy;
- uint32_t m_vram_addr, m_vram_src;
- uint8_t m_fillbytes[256];
- required_device<palette_device> m_palette;
-};
-
// device type definition
-DECLARE_DEVICE_TYPE(NUBUS_SPECPDQ, nubus_specpdq_device)
+DECLARE_DEVICE_TYPE(NUBUS_SPECPDQ, device_nubus_card_interface)
#endif // MAME_BUS_NUBUS_NUBUS_SPECPDQ_H
diff --git a/src/devices/bus/nubus/nubus_vikbw.cpp b/src/devices/bus/nubus/nubus_vikbw.cpp
index ab3af18fe72..89ac560752f 100644
--- a/src/devices/bus/nubus/nubus_vikbw.cpp
+++ b/src/devices/bus/nubus/nubus_vikbw.cpp
@@ -2,168 +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 the CRTC is a fixed
+ state machine.
+
***************************************************************************/
#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 ATTR_COLD;
+ virtual void device_reset() override ATTR_COLD;
-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 ATTR_COLD;
+ virtual const tiny_rom_entry *device_rom_region() const override ATTR_COLD;
+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(this, VIKBW_ROM_REGION, true);
+ install_declaration_rom("vikingrom", true);
slotspace = get_slotspace();
-// printf("[vikbw %p] slotspace = %x\n", this, slotspace);
+ 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]);
- m_vram.resize(VRAM_SIZE);
- install_bank(slotspace+0x40000, slotspace+0x40000+VRAM_SIZE-1, "bank_vikbw", &m_vram[0]);
- install_bank(slotspace+0x940000, slotspace+0x940000+VRAM_SIZE-1, "bank_vikbw2", &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)));
- nubus().install_device(slotspace, slotspace+3, read32_delegate(FUNC(nubus_vikbw_device::viking_enable_r), this), write32_delegate(FUNC(nubus_vikbw_device::viking_disable_w), this));
- nubus().install_device(slotspace+0x80000, slotspace+0x80000+3, read32_delegate(FUNC(nubus_vikbw_device::viking_ack_r), this), write32_delegate(FUNC(nubus_vikbw_device::viking_ack_w), this));
+ save_item(NAME(m_vbl_disable));
+ save_pointer(NAME(m_vram), VRAM_SIZE / sizeof(u32));
}
-//-------------------------------------------------
-// device_reset - device-specific reset
-//-------------------------------------------------
-
void nubus_vikbw_device::device_reset()
{
m_vbl_disable = 1;
- memset(&m_vram[0], 0, VRAM_SIZE);
-
- 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)
{
- uint32_t *scanline;
- int x, y;
- uint8_t pixels;
-
if (!m_vbl_disable)
{
raise_slot_irq();
}
- for (y = 0; y < 768; y++)
+ auto const vram8 = util::big_endian_cast<u8 const>(&m_vram[0]);
+ for (int y = 0; y < 768; y++)
{
- scanline = &bitmap.pix32(y);
- for (x = 0; x < 1024/8; x++)
+ u16 *scanline = &bitmap.pix(y);
+ for (int x = 0; x < 1024/8; x++)
{
- pixels = m_vram[(y * 128) + (BYTE4_XOR_BE(x))];
-
- *scanline++ = m_palette[(pixels>>7)&1];
- *scanline++ = m_palette[(pixels>>6)&1];
- *scanline++ = m_palette[(pixels>>5)&1];
- *scanline++ = m_palette[(pixels>>4)&1];
- *scanline++ = m_palette[(pixels>>3)&1];
- *scanline++ = m_palette[(pixels>>2)&1];
- *scanline++ = m_palette[(pixels>>1)&1];
- *scanline++ = m_palette[(pixels&1)];
+ 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;
}
-WRITE32_MEMBER( nubus_vikbw_device::viking_ack_w )
+void nubus_vikbw_device::viking_ack_w(u32 data)
{
lower_slot_irq();
}
-READ32_MEMBER( nubus_vikbw_device::viking_ack_r )
+u32 nubus_vikbw_device::viking_ack_r()
{
return 0;
}
-WRITE32_MEMBER( nubus_vikbw_device::viking_disable_w )
+void nubus_vikbw_device::viking_disable_w(u32 data)
{
m_vbl_disable = 1;
}
-READ32_MEMBER( 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 94ce5f1df17..099bd9ea08d 100644
--- a/src/devices/bus/nubus/nubus_vikbw.h
+++ b/src/devices/bus/nubus/nubus_vikbw.h
@@ -1,50 +1,12 @@
// license:BSD-3-Clause
// copyright-holders:R. Belmont
-#ifndef MAME_BUS_NUBUS_VIKBW_H
-#define MAME_BUS_NUBUS_VIKBW_H
+#ifndef MAME_BUS_NUBUS_NUBUS_VIKBW_H
+#define MAME_BUS_NUBUS_NUBUS_VIKBW_H
#pragma once
#include "nubus.h"
-//**************************************************************************
-// TYPE DEFINITIONS
-//**************************************************************************
+DECLARE_DEVICE_TYPE(NUBUS_VIKBW, device_nubus_card_interface)
-// ======================> 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:
- DECLARE_READ32_MEMBER(viking_ack_r);
- DECLARE_WRITE32_MEMBER(viking_ack_w);
- DECLARE_READ32_MEMBER(viking_enable_r);
- DECLARE_WRITE32_MEMBER(viking_disable_w);
-
- uint32_t screen_update(screen_device &screen, bitmap_rgb32 &bitmap, const rectangle &cliprect);
-
- std::vector<uint8_t> m_vram;
- uint32_t m_vbl_disable, m_palette[2];
-};
-
-// device type definition
-DECLARE_DEVICE_TYPE(NUBUS_VIKBW, nubus_vikbw_device)
-
-#endif // MAME_BUS_NUBUS_VIKBW_H
+#endif // MAME_BUS_NUBUS_NUBUS_VIKBW_H
diff --git a/src/devices/bus/nubus/nubus_wsportrait.cpp b/src/devices/bus/nubus/nubus_wsportrait.cpp
deleted file mode 100644
index 12702c052a6..00000000000
--- a/src/devices/bus/nubus/nubus_wsportrait.cpp
+++ /dev/null
@@ -1,301 +0,0 @@
-// license:BSD-3-Clause
-// copyright-holders:R. Belmont
-/***************************************************************************
-
- Apple model 820-5037-C "Macintosh II Portrait Video Card"
- PCB is marked "Workstation/Portrait Card"
- 640x870, 1, 2 or 4bpp grayscale
-
- Fs0900e0 = DAC control
- Fs0900e4 = DAC data
- Fs0A0000 = enable / ack VBL IRQ
- Fs0A0004 = disable VBL IRQ
-
-***************************************************************************/
-
-#include "emu.h"
-#include "nubus_wsportrait.h"
-#include "screen.h"
-
-#define WSPORTRAIT_SCREEN_NAME "wsport_screen"
-#define WSPORTRAIT_ROM_REGION "wsport_rom"
-
-#define VRAM_SIZE (0x80000) // 512k max
-
-
-ROM_START( wsportrait )
- ROM_REGION(0x1000, WSPORTRAIT_ROM_REGION, 0)
- ROM_LOAD( "341-0732.bin", 0x000000, 0x001000, CRC(ddc35b78) SHA1(ce2bf2374bb994c17962dba8f3d11bc1260e2644) )
-ROM_END
-
-//**************************************************************************
-// GLOBAL VARIABLES
-//**************************************************************************
-
-DEFINE_DEVICE_TYPE(NUBUS_WSPORTRAIT, nubus_wsportrait_device, "nb_wspt", "Macintosh II Portrait Video Card")
-
-
-//-------------------------------------------------
-// device_add_mconfig - add device configuration
-//-------------------------------------------------
-
-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);
-}
-
-//-------------------------------------------------
-// rom_region - device-specific ROM region
-//-------------------------------------------------
-
-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(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) :
- device_t(mconfig, type, tag, owner, clock),
- device_video_interface(mconfig, *this),
- device_nubus_card_interface(mconfig, *this),
- m_vram32(nullptr), m_mode(0), m_vbl_disable(0), m_toggle(0), m_count(0), m_clutoffs(0), m_timer(nullptr)
-{
- set_screen(*this, WSPORTRAIT_SCREEN_NAME);
-}
-
-//-------------------------------------------------
-// device_start - device-specific startup
-//-------------------------------------------------
-
-void nubus_wsportrait_device::device_start()
-{
- uint32_t slotspace;
-
- install_declaration_rom(this, WSPORTRAIT_ROM_REGION, true);
-
- slotspace = get_slotspace();
-
- printf("[wsportrait %p] slotspace = %x\n", (void *)this, slotspace);
-
- m_vram.resize(VRAM_SIZE);
- m_vram32 = (uint32_t *)&m_vram[0];
-
- nubus().install_device(slotspace, slotspace+VRAM_SIZE-1, read32_delegate(FUNC(nubus_wsportrait_device::vram_r), this), write32_delegate(FUNC(nubus_wsportrait_device::vram_w), this));
- nubus().install_device(slotspace+0x900000, slotspace+0x900000+VRAM_SIZE-1, read32_delegate(FUNC(nubus_wsportrait_device::vram_r), this), write32_delegate(FUNC(nubus_wsportrait_device::vram_w), this));
- nubus().install_device(slotspace+0x80000, slotspace+0xeffff, read32_delegate(FUNC(nubus_wsportrait_device::wsportrait_r), this), write32_delegate(FUNC(nubus_wsportrait_device::wsportrait_w), this));
-
- m_timer = timer_alloc(0, nullptr);
- m_timer->adjust(screen().time_until_pos(869, 0), 0);
-}
-
-//-------------------------------------------------
-// device_reset - device-specific reset
-//-------------------------------------------------
-
-void nubus_wsportrait_device::device_reset()
-{
- m_count = 0;
- m_clutoffs = 0;
- m_vbl_disable = 1;
- m_mode = 0;
- memset(&m_vram[0], 0, VRAM_SIZE);
- memset(m_palette, 0, sizeof(m_palette));
-}
-
-
-void nubus_wsportrait_device::device_timer(emu_timer &timer, device_timer_id tid, int param, void *ptr)
-{
- if (!m_vbl_disable)
- {
- raise_slot_irq();
- }
-
- 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)
-{
- uint32_t *scanline;
- int x, y;
- uint8_t pixels, *vram;
-
- // first time? kick off the VBL timer
- vram = &m_vram[0x80];
-
- switch (m_mode)
- {
- case 0: // 1 bpp?
- for (y = 0; y < 870; y++)
- {
- scanline = &bitmap.pix32(y);
- for (x = 0; x < 640/8; x++)
- {
- pixels = vram[(y * 128) + (BYTE4_XOR_BE(x))];
-
- *scanline++ = m_palette[((pixels>>7)&0x1)];
- *scanline++ = m_palette[((pixels>>6)&0x1)];
- *scanline++ = m_palette[((pixels>>5)&0x1)];
- *scanline++ = m_palette[((pixels>>4)&0x1)];
- *scanline++ = m_palette[((pixels>>3)&0x1)];
- *scanline++ = m_palette[((pixels>>2)&0x1)];
- *scanline++ = m_palette[((pixels>>1)&0x1)];
- *scanline++ = m_palette[(pixels&1)];
- }
- }
- break;
-
- case 1: // 2 bpp
- for (y = 0; y < 480; y++)
- {
- scanline = &bitmap.pix32(y);
- for (x = 0; x < 640/4; x++)
- {
- pixels = vram[(y * 256) + (BYTE4_XOR_BE(x))];
-
- *scanline++ = m_palette[((pixels>>6)&3)];
- *scanline++ = m_palette[((pixels>>4)&3)];
- *scanline++ = m_palette[((pixels>>2)&3)];
- *scanline++ = m_palette[(pixels&3)];
- }
- }
- break;
-
- case 2: // 4 bpp
- for (y = 0; y < 480; y++)
- {
- scanline = &bitmap.pix32(y);
-
- for (x = 0; x < 640/2; x++)
- {
- pixels = vram[(y * 512) + (BYTE4_XOR_BE(x))];
-
- *scanline++ = m_palette[((pixels&0xf0)>>4)];
- *scanline++ = m_palette[(pixels&0xf)];
- }
- }
- break;
-
- default:
- fatalerror("wsportrait: unknown video mode %d\n", m_mode);
- }
- return 0;
-}
-
-WRITE32_MEMBER( nubus_wsportrait_device::wsportrait_w )
-{
- data ^= 0xffffffff;
-// if (offset != 0x8000) printf("wsportrait: Write %08x @ %x, mask %08x\n", data, offset, mem_mask);
-
- switch (offset)
- {
- case 1: // mode control
-// printf("%08x to mode 1\n", data);
- switch (data & 0xff000000)
- {
- case 0x20000000:
- case 0x24000000:
- m_mode = 0;
- break;
-
- case 0x40000000:
- m_mode = 1;
- break;
-
- case 0x50000000:
- case 0x80000000:
- m_mode = 2;
- break;
- }
- break;
-
- case 0x4038: // DAC control
- m_clutoffs = (data>>24)&0xff;
- break;
-
- case 0x4039: // DAC data - only 4 bits per component!
- m_colors[m_count] = (data>>24) & 0x0f;
- m_colors[m_count] |= (m_colors[m_count]<<4);
- m_count++;
-
- 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_clutoffs++;
- if (m_clutoffs > 255)
- {
- m_clutoffs = 0;
- }
- m_count = 0;
- }
- break;
-
- case 0x8000:
- lower_slot_irq();
- m_vbl_disable = false;
- break;
-
- case 0x8001:
- m_vbl_disable = true;
- break;
- }
-}
-
-READ32_MEMBER( nubus_wsportrait_device::wsportrait_r )
-{
-// 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 0;
-}
-
-WRITE32_MEMBER( nubus_wsportrait_device::vram_w )
-{
- data ^= 0xffffffff;
- COMBINE_DATA(&m_vram32[offset]);
-}
-
-READ32_MEMBER( nubus_wsportrait_device::vram_r )
-{
- return m_vram32[offset] ^ 0xffffffff;
-}
diff --git a/src/devices/bus/nubus/nubus_wsportrait.h b/src/devices/bus/nubus/nubus_wsportrait.h
deleted file mode 100644
index d9614a76eb7..00000000000
--- a/src/devices/bus/nubus/nubus_wsportrait.h
+++ /dev/null
@@ -1,56 +0,0 @@
-// license:BSD-3-Clause
-// copyright-holders:R. Belmont
-#ifndef MAME_BUS_NUBUS_WSPORTRAIT_H
-#define MAME_BUS_NUBUS_WSPORTRAIT_H
-
-#pragma once
-
-#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;
- virtual void device_timer(emu_timer &timer, device_timer_id id, int param, void *ptr) override;
-
- // optional information overrides
- virtual void device_add_mconfig(machine_config &config) override;
- virtual const tiny_rom_entry *device_rom_region() const override;
-
-private:
- DECLARE_READ32_MEMBER(wsportrait_r);
- DECLARE_WRITE32_MEMBER(wsportrait_w);
- DECLARE_READ32_MEMBER(vram_r);
- DECLARE_WRITE32_MEMBER(vram_w);
-
- uint32_t screen_update(screen_device &screen, bitmap_rgb32 &bitmap, const rectangle &cliprect);
-
- std::vector<uint8_t> m_vram;
- uint32_t *m_vram32;
- 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)
-
-#endif // MAME_BUS_NUBUS_WSPORTRAIT_H
diff --git a/src/devices/bus/nubus/pds30_30hr.cpp b/src/devices/bus/nubus/pds30_30hr.cpp
index 190872708f6..ba4d9970a20 100644
--- a/src/devices/bus/nubus/pds30_30hr.cpp
+++ b/src/devices/bus/nubus/pds30_30hr.cpp
@@ -3,308 +3,758 @@
/***************************************************************************
Micron/XCEED Technologies Color 30HR
+ Micron/XCEED Technologies MacroColor 30
+ Emulation rewritten March/April 2025 by R. Belmont
+
+ These cards are based around a custom ASIC called "Gambler" or "Maverick"
+ which is a framebuffer controller and programmable CRTC. The chips are mostly
+ interchangable from both a software and pinout point of view - Gambler is
+ the later version and Maverick is found on earlier production cards, with
+ very minor ROM tweaks.
+
+ The Color 30HR uses a Bt478 RAMDAC and is limited to 256 colors, but has
+ a variety of resolutions while the MacroColor 30 cards use a Bt473 RAMDAC
+ for 24-bit color. There's also a MacroColor 30HR with both, but a ROM is
+ not dumped for that version.
Fs800000 - Mode A
FsA00000 - Mode B
- FsC00000 - RAMDAC write offset
+ FsC00000 - RAMDAC write offset (Bt478)
FsC00004 - RAMDAC write data
FsC00008 - RAMDAC write mask
FsC0000C - RAMDAC read offset
+ Hardware info:
+ https://github.com/ZigZagJoe/Color30HR-ROM
+
+ Most registers on this card are encrypted, or what Micron/XCEED called "muddled".
+
***************************************************************************/
#include "emu.h"
#include "pds30_30hr.h"
-#include "screen.h"
-#define XCEED30HR_SCREEN_NAME "x30hr_screen"
-#define XCEED30HR_ROM_REGION "x30hr_rom"
+#include "video/bt47x.h"
-#define VRAM_SIZE (0x100000) // 1 MB VRAM - max mode is 1024x768 @ 8bpp
+#include "screen.h"
+#define LOG_REGISTERS (1U << 1)
+#define LOG_CRTC (1U << 2)
-ROM_START( xceed30hr )
- ROM_REGION(0x8000, XCEED30HR_ROM_REGION, 0)
- ROM_LOAD( "369c.rom", 0x000000, 0x008000, CRC(b22f0a89) SHA1(be34c8604b8a1ae9c9f3b0b90faba9a1a64a5855) )
-ROM_END
+#define VERBOSE (0)
-//**************************************************************************
-// GLOBAL VARIABLES
-//**************************************************************************
+#include "logmacro.h"
-DEFINE_DEVICE_TYPE(PDS030_XCEED30HR, nubus_xceed30hr_device, "pd3_30hr", "Micron/XCEED Technology Color 30HR")
+namespace {
+static constexpr offs_t B_ExternalModeBits = 0;
+[[maybe_unused]] static constexpr offs_t B_RefreshCount = 1;
+static constexpr offs_t B_ModeRegB = 2;
+[[maybe_unused]] static constexpr offs_t B_ZoomFactor = 3;
+[[maybe_unused]] static constexpr offs_t B_NS = 4;
+static constexpr offs_t B_InterruptClear = 5;
+static constexpr offs_t B_External = 8;
-//-------------------------------------------------
-// device_add_mconfig - add device configuration
-//-------------------------------------------------
+static constexpr int B_ModeB_VideoEnable = 0;
+static constexpr int B_ModeB_IRQEnable = 1;
-void nubus_xceed30hr_device::device_add_mconfig(machine_config &config)
+// These external bits are specific to card ID 369, the 30HR and are different on the MacroColor 30
+static constexpr int B_External_Bartlett = 2;
+[[maybe_unused]] static constexpr int B_External_NoCable = 3; // 0 = cable present, 1 = no cable
+static constexpr int B_External_CBlank = 7;
+
+// encode bits 8-10 to bits 20-23
+static constexpr u8 muddle_table[8] =
{
- screen_device &screen(SCREEN(config, XCEED30HR_SCREEN_NAME, SCREEN_TYPE_RASTER));
- screen.set_screen_update(FUNC(nubus_xceed30hr_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);
-}
+ 0xe, 0xc, 0xa, 0xb, 0x6, 0x4, 0x2, 0x0
+};
-//-------------------------------------------------
-// rom_region - device-specific ROM region
-//-------------------------------------------------
+// decode bits 20-23 to get the original bits 8-10
+static constexpr u8 demuddle_table[16] =
+{
+ 0x7, 0x0, 0x6, 0x0, 0x5, 0x0, 0x4, 0x0,
+ 0x0, 0x0, 0x2, 0x3, 0x1, 0x0, 0x0, 0x0
+};
-const tiny_rom_entry *nubus_xceed30hr_device::device_rom_region() const
+class maverick_device : public device_t,
+ public device_nubus_card_interface
{
- return ROM_NAME( xceed30hr );
-}
+protected:
+ maverick_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, u32 clock);
-//**************************************************************************
-// LIVE DEVICE
-//**************************************************************************
+ TIMER_CALLBACK_MEMBER(vbl_tick);
-//-------------------------------------------------
-// nubus_xceed30hr_device - constructor
-//-------------------------------------------------
+ void base_map(address_map &map);
-nubus_xceed30hr_device::nubus_xceed30hr_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) :
- nubus_xceed30hr_device(mconfig, PDS030_XCEED30HR, tag, owner, clock)
-{
-}
+ void device_start_common(u32 vram_size);
+ virtual u16 read_external_signals();
+ virtual u8 translate_mode();
-nubus_xceed30hr_device::nubus_xceed30hr_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),
- device_nubus_card_interface(mconfig, *this),
- m_vram32(nullptr), m_mode(0), m_vbl_disable(0), m_toggle(0), m_count(0), m_clutoffs(0), m_timer(nullptr)
-{
- set_screen(*this, XCEED30HR_SCREEN_NAME);
-}
+ u32 aregs_r(offs_t offset);
+ void aregs_w(offs_t offset, u32 data);
+ u32 bregs_r(offs_t offset);
+ void bregs_w(offs_t offset, u32 data);
+ u32 vram_r(offs_t offset, u32 mem_mask = ~0);
+ void vram_w(offs_t offset, u32 data, u32 mem_mask = ~0);
-//-------------------------------------------------
-// device_start - device-specific startup
-//-------------------------------------------------
+ u32 screen_update(screen_device &screen, bitmap_rgb32 &bitmap, const rectangle &cliprect);
-void nubus_xceed30hr_device::device_start()
-{
- uint32_t slotspace;
+ screen_device *m_maverick_screen;
+ bt47x_device_base *m_maverick_ramdac;
- install_declaration_rom(this, XCEED30HR_ROM_REGION);
+ u32 m_aregs[0x10], m_bregs[0x10];
- slotspace = get_slotspace();
+ u32 m_skipbytes;
+ u32 m_hres, m_vres, m_htotal, m_vtotal, m_pclock, m_rowbytes;
-// printf("[xceed30hr %p] slotspace = %x\n", this, slotspace);
+private:
+ u32 encrypt(u32 value);
+ u32 decrypt(u32 value);
- m_vram.resize(VRAM_SIZE);
- m_vram32 = (uint32_t *)&m_vram[0];
+ void compute_video_mode();
- nubus().install_device(slotspace, slotspace+VRAM_SIZE-1, read32_delegate(FUNC(nubus_xceed30hr_device::vram_r), this), write32_delegate(FUNC(nubus_xceed30hr_device::vram_w), this));
- nubus().install_device(slotspace+0x800000, slotspace+0xefffff, read32_delegate(FUNC(nubus_xceed30hr_device::xceed30hr_r), this), write32_delegate(FUNC(nubus_xceed30hr_device::xceed30hr_w), this));
+ std::unique_ptr<u32[]> m_vram;
+ emu_timer *m_timer;
+};
- m_timer = timer_alloc(0, nullptr);
- m_timer->adjust(screen().time_until_pos(479, 0), 0);
+void maverick_device::base_map(address_map &map)
+{
+ map(0x80'0000, 0x80'003f).rw(FUNC(maverick_device::aregs_r), FUNC(maverick_device::aregs_w));
+ map(0xa0'0000, 0xa0'003f).rw(FUNC(maverick_device::bregs_r), FUNC(maverick_device::bregs_w));
}
-//-------------------------------------------------
-// device_reset - device-specific reset
-//-------------------------------------------------
+maverick_device::maverick_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_skipbytes(1024),
+ m_hres(640),
+ m_vres(480),
+ m_htotal(896),
+ m_vtotal(525),
+ m_rowbytes(1024),
+ m_timer(nullptr)
+{
+ std::fill_n(&m_aregs[0], 0x10, 0);
+ std::fill_n(&m_bregs[0], 0x10, 0);
+}
-void nubus_xceed30hr_device::device_reset()
+void maverick_device::device_start_common(u32 vram_size)
{
- m_count = 0;
- m_clutoffs = 0;
- m_vbl_disable = 1;
- m_mode = 0;
- memset(&m_vram[0], 0, VRAM_SIZE);
- memset(m_palette, 0, sizeof(m_palette));
+ install_declaration_rom("declrom");
- m_palette[0] = rgb_t(255, 255, 255);
- m_palette[0x80] = rgb_t(0, 0, 0);
-}
+ m_vram = make_unique_clear<u32[]>(vram_size / sizeof(u32));
+ m_timer = timer_alloc(FUNC(maverick_device::vbl_tick), this);
+ m_timer->adjust(m_maverick_screen->time_until_pos(479, 0), 0);
-void nubus_xceed30hr_device::device_timer(emu_timer &timer, device_timer_id tid, int param, void *ptr)
+ save_pointer(NAME(m_vram), vram_size / sizeof(u32));
+ save_pointer(NAME(m_aregs), 0x10);
+ save_pointer(NAME(m_bregs), 0x10);
+}
+
+TIMER_CALLBACK_MEMBER(maverick_device::vbl_tick)
{
- if (!m_vbl_disable)
+ if (BIT(m_bregs[B_ModeRegB], B_ModeB_IRQEnable))
{
raise_slot_irq();
}
- m_timer->adjust(screen().time_until_pos(479, 0), 0);
+ m_timer->adjust(m_maverick_screen->time_until_pos(479, 0), 0);
}
-/***************************************************************************
-
- CB264 section
-
-***************************************************************************/
+u8 maverick_device::translate_mode()
+{
+ return m_bregs[B_ExternalModeBits] & 3;
+}
-uint32_t nubus_xceed30hr_device::screen_update(screen_device &screen, bitmap_rgb32 &bitmap, const rectangle &cliprect)
+u32 maverick_device::screen_update(screen_device &screen, bitmap_rgb32 &bitmap, const rectangle &cliprect)
{
- uint32_t *scanline;
- int x, y;
- uint8_t pixels, *vram;
+ if (!BIT(m_bregs[B_ModeRegB], B_ModeB_VideoEnable))
+ {
+ bitmap.fill(0, cliprect);
+ return 0;
+ }
- vram = &m_vram[1024];
+ auto const vram8 = util::big_endian_cast<u8 const>(&m_vram[0]) + m_skipbytes;
+ pen_t const *const pens = m_maverick_ramdac->pens();
- switch (m_mode)
+ switch (translate_mode())
{
- case 0: // 1 bpp?
- for (y = 0; y < 480; y++)
+ case 4: // 24 bpp
+ for (int y = 0; y < m_vres; y++)
{
- scanline = &bitmap.pix32(y);
- for (x = 0; x < 640/8; x++)
+ std::copy_n(&m_vram[(y * m_rowbytes)], m_hres, &bitmap.pix(y));
+ }
+ break;
+
+ case 3: // 1 bpp
+ for (int y = 0; y < m_vres; y++)
+ {
+ u32 *scanline = &bitmap.pix(y);
+ for (int x = 0; x < m_hres/8; x++)
{
- pixels = vram[(y * 1024) + (BYTE4_XOR_BE(x))];
-
- *scanline++ = m_palette[(pixels>>7)&1];
- *scanline++ = m_palette[(pixels>>6)&1];
- *scanline++ = m_palette[(pixels>>5)&1];
- *scanline++ = m_palette[(pixels>>4)&1];
- *scanline++ = m_palette[(pixels>>3)&1];
- *scanline++ = m_palette[(pixels>>2)&1];
- *scanline++ = m_palette[(pixels>>1)&1];
- *scanline++ = m_palette[pixels&1];
+ u8 const pixels = vram8[(y * m_rowbytes) + 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 (y = 0; y < 480; y++)
+ case 2: // 2 bpp
+ for (int y = 0; y < m_vres; y++)
{
- scanline = &bitmap.pix32(y);
- for (x = 0; x < 640/4; x++)
+ u32 *scanline = &bitmap.pix(y);
+ for (int x = 0; x < m_hres/4; x++)
{
- pixels = vram[(y * 1024) + (BYTE4_XOR_BE(x))];
+ u8 const pixels = vram8[(y * m_rowbytes) + 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 (y = 0; y < 480; y++)
+ case 1: // 4 bpp
+ for (int y = 0; y < m_vres; y++)
{
- scanline = &bitmap.pix32(y);
-
- for (x = 0; x < 640/2; x++)
+ u32 *scanline = &bitmap.pix(y);
+ for (int x = 0; x < m_hres/2; x++)
{
- pixels = vram[(y * 1024) + (BYTE4_XOR_BE(x))];
+ u8 const pixels = vram8[(y * m_rowbytes) + x];
- *scanline++ = m_palette[(pixels>>4)];
- *scanline++ = m_palette[(pixels&0xf)];
+ *scanline++ = pens[(pixels>>4)];
+ *scanline++ = pens[(pixels&0xf)];
}
}
break;
- case 3: // 8 bpp
- for (y = 0; y < 480; y++)
+ case 0: // 8 bpp
+ for (int y = 0; y < m_vres; y++)
{
- scanline = &bitmap.pix32(y);
-
- for (x = 0; x < 640; x++)
+ u32 *scanline = &bitmap.pix(y);
+ for (int x = 0; x < m_hres; x++)
{
- pixels = vram[(y * 1024) + (BYTE4_XOR_BE(x))];
- *scanline++ = m_palette[pixels];
+ u8 const pixels = vram8[(y * m_rowbytes) + x];
+ *scanline++ = pens[pixels];
}
}
break;
-
- default:
- fatalerror("xceed30hr: unknown video mode %d\n", m_mode);
}
return 0;
}
-WRITE32_MEMBER( nubus_xceed30hr_device::xceed30hr_w )
+u32 maverick_device::aregs_r(offs_t offset)
{
+ return encrypt(m_aregs[offset]);
+}
+
+void maverick_device::aregs_w(offs_t offset, u32 data)
+{
+ LOGMASKED(LOG_REGISTERS, "aregs_w: %08x @ %x (crypt %08x) %s\n", decrypt(data), offset, data, machine().describe_context().c_str());
+ m_aregs[offset] = decrypt(data);
+}
+
+u32 maverick_device::bregs_r(offs_t offset)
+{
+ LOGMASKED(LOG_REGISTERS, "bregs_r: @ %x, %s\n", offset, machine().describe_context().c_str());
+ if (offset == B_External)
+ {
+ return read_external_signals();
+ }
+
+ return m_bregs[offset];
+}
+
+void maverick_device::bregs_w(offs_t offset, u32 data)
+{
+ if (offset != B_InterruptClear)
+ {
+ LOGMASKED(LOG_REGISTERS, "bregs_w: %08x @ %x (crypt %08x) %s\n", decrypt(data), offset, data, machine().describe_context().c_str());
+ }
+
switch (offset)
{
- case 0x80000: // mode
- switch (data & 0xff000000)
+ case B_InterruptClear: // ack VBL
+ lower_slot_irq();
+ break;
+
+ case B_ModeRegB:
+ if (BIT(decrypt(data), B_ModeB_VideoEnable))
+ {
+ compute_video_mode();
+ }
+ break;
+ }
+
+ // External is NOT encrypted
+ if (offset != B_External)
+ {
+ m_bregs[offset] = decrypt(data);
+ }
+ else
+ {
+ m_bregs[offset] = data;
+ }
+}
+
+// This is a HACK to compute the video mode from the register values until
+// the CRTC is understood.
+void maverick_device::compute_video_mode()
+{
+ m_rowbytes = 512; // most modes are this, so assume it until proven otherwise
+
+ // start from the pixel clock
+ switch (m_bregs[B_External])
+ {
+ case 0: // 30.24 MHz (Apple 640x480)
+ m_pclock = 30'240'000;
+ m_hres = 640;
+ m_vres = 480;
+ m_htotal = 864;
+ m_vtotal = 525;
+ m_rowbytes = 1024;
+ break;
+
+ case 1: // 15.66 MHz (SE/30 internal monitor, Apple 12" 512x384)
+ m_pclock = 15'667'200;
+ if (m_aregs[3] == 0xbc) // check HLine value
{
- case 0xfc000000:
- m_mode = 0;
- break;
+ // 12" monitor
+ m_hres = 512;
+ m_vres = 384;
+ m_htotal = 640;
+ m_vtotal = 407;
+ }
+ else if (m_aregs[3] == 0x9d) // classic Mac video mode for the SE/30 internal CRT
+ {
+ m_hres = 512;
+ m_vres = 342;
+ m_htotal = 704;
+ m_vtotal = 370;
+ }
+ m_rowbytes = 1024;
+ break;
- case 0xfd000000:
- m_mode = 1;
+ case 4: // 57.28 MHz Apple portrait monitor and SVGA 800x600 @ 72 Hz and Apple 832x624 16"
+ m_pclock = 57'283'200;
+ switch (m_aregs[3])
+ {
+ case 0x6d: // Apple portrait
+ m_hres = 640;
+ m_vres = 870;
+ m_htotal = 832;
+ m_vtotal = 918;
break;
- case 0xfe000000:
- m_mode = 2;
+ case 0x80: // Apple 16" 832x624
+ m_hres = 832;
+ m_vres = 624;
+ m_htotal = 1152;
+ m_vtotal = 667;
break;
- case 0xff000000:
- m_mode = 3;
+ case 0x5c: // SVGA 800x600 @ 72 Hz
+ m_hres = 800;
+ m_vres = 600;
+ m_htotal = 1040;
+ m_vtotal = 666;
break;
}
break;
- case 0x80005: // ack VBL
- lower_slot_irq();
+ case 9: // 25.175 MHz VGA 640x480
+ m_pclock = 25'175'000;
+ m_hres = 640;
+ m_vres = 480;
+ m_htotal = 800;
+ m_vtotal = 524;
+ m_rowbytes = 1024;
break;
- case 0x100000:
-// logerror("%08x to DAC control %s\n", data, machine().describe_context());
- m_clutoffs = (data&0xff);
- m_count = 0;
+ case 0xd: // 36? MHz SVGA 800x600 @ 56 Hz
+ m_pclock = 38'100'000;
+ m_hres = 800;
+ m_vres = 600;
+ m_htotal = 1088;
+ m_vtotal = 619;
break;
- case 0x100001:
-// logerror("%08x to DAC data %s\n", data, machine().describe_context());
- m_colors[m_count++] = (data & 0xff);
-
- if (m_count == 3)
- {
-// logerror("RAMDAC: color %02x = %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[0], m_colors[1], m_colors[2]);
- m_clutoffs++;
- if (m_clutoffs > 255)
- {
- m_clutoffs = 0;
- }
- m_count = 0;
- }
+ case 0xf: // 40 MHz SVGA 800x600 @ 60 Hz
+ m_pclock = 40'000'000;
+ m_hres = 800;
+ m_vres = 600;
+ m_htotal = 1056;
+ m_vtotal = 628;
break;
- case 0x100002: // VBL control
- if (data & 0x06000000)
- {
- m_vbl_disable = 0;
- lower_slot_irq();
- }
- else
- {
- m_vbl_disable = 1;
- }
+ case 0x15: // 65 MHz SVGA 1024x768
+ m_pclock = 65'000'000;
+ m_hres = 1024;
+ m_vres = 768;
+ m_htotal = 1344;
+ m_vtotal = 806;
break;
+ }
- default:
-// logerror("xceed30hr_w: %08x @ %x, mask %08x %s\n", data, offset, mem_mask, machine().describe_context());
- break;
+ LOGMASKED(LOG_CRTC, "New video mode: %d x %d at %d pixel clock, rowbytes %d\n", m_hres, m_vres, m_pclock, m_rowbytes);
+
+ rectangle visarea(0, m_hres - 1, 0, m_vres - 1);
+ m_maverick_screen->configure(m_htotal, m_vtotal, visarea, attotime::from_ticks(m_htotal * m_vtotal, m_pclock).as_attoseconds());
+}
+
+u16 maverick_device::read_external_signals()
+{
+ return 0;
+}
+
+void maverick_device::vram_w(offs_t offset, u32 data, u32 mem_mask)
+{
+ COMBINE_DATA(&m_vram[offset]);
+}
+
+u32 maverick_device::vram_r(offs_t offset, u32 mem_mask)
+{
+ return m_vram[offset];
+}
+
+u32 maverick_device::encrypt(u32 value)
+{
+ u32 result = ((value & 0xff) ^ 0xff) << 24;
+ result |= muddle_table[(value >> 8) & 0x7] << 20;
+ return result;
+}
+
+u32 maverick_device::decrypt(u32 value)
+{
+ u16 result = (value >> 24) ^ 0xff;
+ result |= demuddle_table[(value >> 20) & 0xf] << 8;
+ return result;
+}
+
+// **** Color 30HR section
+class nubus_xceed30hr_device : public maverick_device
+{
+public:
+ nubus_xceed30hr_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 ATTR_COLD;
+ virtual const tiny_rom_entry *device_rom_region() const override ATTR_COLD;
+
+ void card_map(address_map &map) ATTR_COLD;
+
+ virtual u16 read_external_signals() override;
+
+ required_device<screen_device> m_screen;
+ required_device<bt47x_device_base> m_ramdac;
+};
+
+void nubus_xceed30hr_device::card_map(address_map &map)
+{
+ maverick_device::base_map(map);
+
+ map(0x00'0000, 0x0f'ffff).rw(FUNC(nubus_xceed30hr_device::vram_r), FUNC(nubus_xceed30hr_device::vram_w));
+ map(0xc0'0000, 0xc0'001f).rw(m_ramdac, FUNC(bt47x_device_base::read), FUNC(bt47x_device_base::write)).umask32(0x000000ff);
+}
+
+// **** Color 30HR using the SE/30 internal display
+void nubus_xceed30hr_device::device_add_mconfig(machine_config &config)
+{
+ SCREEN(config, m_screen, SCREEN_TYPE_RASTER);
+ m_screen->set_screen_update(FUNC(nubus_xceed30hr_device::screen_update));
+ m_screen->set_raw(25175000, 800, 0, 640, 525, 0, 480);
+
+ BT478(config, m_ramdac, 0);
+}
+
+nubus_xceed30hr_device::nubus_xceed30hr_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock) :
+ maverick_device(mconfig, PDS030_XCEED30HR, tag, owner, clock),
+ m_screen(*this, "screen"),
+ m_ramdac(*this, "bt478")
+{
+}
+
+void nubus_xceed30hr_device::device_start()
+{
+ m_maverick_screen = m_screen;
+ maverick_device::device_start_common(1 * 1024 * 1024);
+ nubus().install_map(*this, &nubus_xceed30hr_device::card_map);
+
+ m_maverick_ramdac = m_ramdac;
+}
+
+u16 nubus_xceed30hr_device::read_external_signals()
+{
+ u32 result = 0;
+
+ if (m_maverick_screen->vblank() || m_maverick_screen->hblank())
+ {
+ result |= (1 << B_External_CBlank);
}
+ return result;
}
+class nubus_xceed30hr_internal_device : public maverick_device
+{
+public:
+ nubus_xceed30hr_internal_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock);
+
+ static auto parent_rom_device_type() { return &PDS030_XCEED30HR; }
+
+protected:
+ virtual void device_start() override;
+ virtual void device_add_mconfig(machine_config &config) override ATTR_COLD;
+ virtual const tiny_rom_entry *device_rom_region() const override ATTR_COLD;
-READ32_MEMBER( nubus_xceed30hr_device::xceed30hr_r )
+ void card_map(address_map &map) ATTR_COLD;
+
+ virtual u16 read_external_signals() override;
+
+ required_device<bt47x_device_base> m_ramdac;
+};
+
+void nubus_xceed30hr_internal_device::card_map(address_map &map)
{
-// logerror("xceed30hr_r: @ %x, mask %08x %s\n", offset, mem_mask, machine().describe_context());
- if (offset == 0x80008)
+ maverick_device::base_map(map);
+
+ map(0x00'0000, 0x0f'ffff).rw(FUNC(nubus_xceed30hr_internal_device::vram_r), FUNC(nubus_xceed30hr_internal_device::vram_w));
+ map(0xc0'0000, 0xc0'001f).rw(m_ramdac, FUNC(bt47x_device_base::read), FUNC(bt47x_device_base::write)).umask32(0x000000ff);
+}
+
+void nubus_xceed30hr_internal_device::device_add_mconfig(machine_config &config)
+{
+ BT478(config, m_ramdac, 0);
+}
+
+ROM_START(xceed30hr)
+ ROM_REGION(0x8000, "declrom", 0)
+ ROM_LOAD("369c.rom", 0x000000, 0x008000, CRC(b22f0a89) SHA1(be34c8604b8a1ae9c9f3b0b90faba9a1a64a5855))
+ROM_END
+
+const tiny_rom_entry *nubus_xceed30hr_device::device_rom_region() const
+{
+ return ROM_NAME(xceed30hr);
+}
+
+nubus_xceed30hr_internal_device::nubus_xceed30hr_internal_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock) :
+ maverick_device(mconfig, PDS030_XCEED30HRINT, tag, owner, clock),
+ m_ramdac(*this, "bt478")
+{
+}
+
+void nubus_xceed30hr_internal_device::device_start()
+{
+ se30_pds_bus_device &pds = downcast<se30_pds_bus_device &>(nubus());
+ m_maverick_screen = pds.m_internal_screen;
+ maverick_device::device_start_common(1 * 1024 * 1024);
+ pds.install_map(*this, &nubus_xceed30hr_internal_device::card_map);
+
+ m_maverick_ramdac = m_ramdac;
+
+ m_maverick_screen->set_screen_update(*this, FUNC(nubus_xceed30hr_internal_device::screen_update));
+}
+
+u16 nubus_xceed30hr_internal_device::read_external_signals()
+{
+ u32 result = (1 << B_External_NoCable);
+
+ if (m_maverick_screen->vblank() || m_maverick_screen->hblank())
{
- m_toggle ^= 0x80;
- return m_toggle;
+ result |= (1 << B_External_CBlank);
}
+ return result;
+}
- return 0;
+const tiny_rom_entry *nubus_xceed30hr_internal_device::device_rom_region() const
+{
+ return ROM_NAME(xceed30hr);
+}
+
+// **** MacroColor 30 section
+class nubus_xceedmc30_device : public maverick_device
+{
+public:
+ nubus_xceedmc30_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock);
+
+protected:
+ virtual const tiny_rom_entry *device_rom_region() const override ATTR_COLD;
+
+ virtual void device_start() override ATTR_COLD;
+ virtual void device_add_mconfig(machine_config &config) override ATTR_COLD;
+
+ void card_map(address_map &map) ATTR_COLD;
+
+ virtual u16 read_external_signals() override;
+ virtual u8 translate_mode() override;
+
+ required_device<screen_device> m_screen;
+ required_device<bt47x_device_base> m_ramdac;
+};
+
+ROM_START(xceedmc30)
+ ROM_REGION(0x8000, "declrom", 0)
+ ROM_LOAD("0390.bin", 0x000000, 0x008000, CRC(adea7a18) SHA1(9141eb1a0e5061e0409d65a89b4eaeb119ee4ffb))
+ROM_END
+
+const tiny_rom_entry *nubus_xceedmc30_device::device_rom_region() const
+{
+ return ROM_NAME(xceedmc30);
}
-WRITE32_MEMBER( nubus_xceed30hr_device::vram_w )
+void nubus_xceedmc30_device::device_add_mconfig(machine_config &config)
{
- COMBINE_DATA(&m_vram32[offset]);
+ SCREEN(config, m_screen, SCREEN_TYPE_RASTER);
+ m_screen->set_screen_update(FUNC(nubus_xceedmc30_device::screen_update));
+ m_screen->set_raw(25175000, 800, 0, 640, 525, 0, 480);
+
+ BT473(config, m_ramdac, 0);
+}
+
+void nubus_xceedmc30_device::card_map(address_map &map)
+{
+ maverick_device::base_map(map);
+
+ map(0x00'0000, 0x1f'ffff).rw(FUNC(nubus_xceedmc30_device::vram_r), FUNC(nubus_xceedmc30_device::vram_w));
+ map(0xc0'0000, 0xc0'001f).rw(m_ramdac, FUNC(bt47x_device_base::read), FUNC(bt47x_device_base::write)).umask32(0xff000000);
+}
+
+nubus_xceedmc30_device::nubus_xceedmc30_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock) :
+ maverick_device(mconfig, PDS030_XCEEDMC30, tag, owner, clock),
+ m_screen(*this, "screen"),
+ m_ramdac(*this, "bt478")
+{
+}
+
+void nubus_xceedmc30_device::device_start()
+{
+ m_maverick_screen = m_screen;
+ maverick_device::device_start_common(2 * 1024 * 1024); // more VRAM to handle 24-bit mode
+ nubus().install_map(*this, &nubus_xceedmc30_device::card_map);
+
+ m_skipbytes = 4096;
+ m_maverick_ramdac = m_ramdac;
+}
+
+u16 nubus_xceedmc30_device::read_external_signals()
+{
+ u32 result = 0;
+
+ if (m_screen->vblank() || m_screen->hblank())
+ {
+ result |= (1 << 2);
+ }
+ return result;
}
-READ32_MEMBER( nubus_xceed30hr_device::vram_r )
+u8 nubus_xceedmc30_device::translate_mode()
{
- return m_vram32[offset];
+ switch (m_bregs[B_ExternalModeBits])
+ {
+ case 7: return 0; // 8bpp
+ case 6: return 1; // 4bpp
+ case 5: return 2; // 2bpp
+ case 4: return 3; // 1bpp
+ case 0: return 4; // 24bpp
+ }
+
+ return 3;
}
+
+// **** MacroColor 30 using the SE/30 internal display
+class nubus_xceedmc30_internal_device : public maverick_device
+{
+public:
+ nubus_xceedmc30_internal_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock);
+
+ static auto parent_rom_device_type() { return &PDS030_XCEEDMC30; }
+
+protected:
+ virtual const tiny_rom_entry *device_rom_region() const override ATTR_COLD;
+
+ virtual void device_start() override ATTR_COLD;
+ virtual void device_add_mconfig(machine_config &config) override ATTR_COLD;
+
+ void card_map(address_map &map) ATTR_COLD;
+
+ virtual u16 read_external_signals() override;
+ virtual u8 translate_mode() override;
+
+ required_device<bt47x_device_base> m_ramdac;
+};
+
+const tiny_rom_entry *nubus_xceedmc30_internal_device::device_rom_region() const
+{
+ return ROM_NAME(xceedmc30);
+}
+
+void nubus_xceedmc30_internal_device::device_add_mconfig(machine_config &config)
+{
+ BT473(config, m_ramdac, 0);
+}
+
+void nubus_xceedmc30_internal_device::card_map(address_map &map)
+{
+ maverick_device::base_map(map);
+
+ map(0x00'0000, 0x1f'ffff).rw(FUNC(nubus_xceedmc30_internal_device::vram_r), FUNC(nubus_xceedmc30_internal_device::vram_w));
+ map(0xc0'0000, 0xc0'001f).rw(m_ramdac, FUNC(bt47x_device_base::read), FUNC(bt47x_device_base::write)).umask32(0xff000000);
+}
+
+nubus_xceedmc30_internal_device::nubus_xceedmc30_internal_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock) :
+ maverick_device(mconfig, PDS030_XCEEDMC30INT, tag, owner, clock),
+ m_ramdac(*this, "bt478")
+{
+}
+
+void nubus_xceedmc30_internal_device::device_start()
+{
+ se30_pds_bus_device &pds = downcast<se30_pds_bus_device &>(nubus());
+ m_maverick_screen = pds.m_internal_screen;
+ maverick_device::device_start_common(2 * 1024 * 1024); // more VRAM to handle 24-bit mode
+ pds.install_map(*this, &nubus_xceedmc30_internal_device::card_map);
+
+ m_skipbytes = 4096;
+ m_maverick_screen->set_screen_update(*this, FUNC(nubus_xceedmc30_internal_device::screen_update));
+ m_maverick_ramdac = m_ramdac;
+}
+
+u16 nubus_xceedmc30_internal_device::read_external_signals()
+{
+ u32 result = (1 << 1); // internal SE/30 CRT cable detect
+
+ if (m_maverick_screen->vblank() || m_maverick_screen->hblank())
+ {
+ result |= (1 << 2); // combined blanking signal
+ }
+ return result;
+}
+
+u8 nubus_xceedmc30_internal_device::translate_mode()
+{
+ switch (m_bregs[B_ExternalModeBits] & 7)
+ {
+ case 7: return 0; // 8bpp
+ case 6: return 1; // 4bpp
+ case 5: return 2; // 2bpp
+ case 4: return 3; // 1bpp
+ case 0: return 4; // 24bpp
+ }
+
+ return 3;
+}
+
+} // anonymous namespace
+
+DEFINE_DEVICE_TYPE_PRIVATE(PDS030_XCEED30HR, device_nubus_card_interface, nubus_xceed30hr_device, "pd3_30hr", "Micron/XCEED Technology Color 30HR")
+DEFINE_DEVICE_TYPE_PRIVATE(PDS030_XCEED30HRINT, device_nubus_card_interface, nubus_xceed30hr_internal_device, "pd3_30hrint", "Micron/XCEED Technology Color 30HR (internal grayscale)")
+DEFINE_DEVICE_TYPE_PRIVATE(PDS030_XCEEDMC30, device_nubus_card_interface, nubus_xceedmc30_device, "pd3_mclr", "Micron/XCEED Technology MacroColor 30")
+DEFINE_DEVICE_TYPE_PRIVATE(PDS030_XCEEDMC30INT, device_nubus_card_interface, nubus_xceedmc30_internal_device, "pd3_mclrint", "Micron/XCEED Technology MacroColor 30 (internal grayscale)")
diff --git a/src/devices/bus/nubus/pds30_30hr.h b/src/devices/bus/nubus/pds30_30hr.h
index 6249f016205..475c25efb38 100644
--- a/src/devices/bus/nubus/pds30_30hr.h
+++ b/src/devices/bus/nubus/pds30_30hr.h
@@ -7,50 +7,10 @@
#include "nubus.h"
-//**************************************************************************
-// TYPE DEFINITIONS
-//**************************************************************************
-// ======================> nubus_xceed30hr_device
-
-class nubus_xceed30hr_device :
- public device_t,
- public device_video_interface,
- public device_nubus_card_interface
-{
-public:
- // construction/destruction
- nubus_xceed30hr_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
-
-protected:
- nubus_xceed30hr_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_timer(emu_timer &timer, device_timer_id id, int param, void *ptr) override;
-
- // optional information overrides
- virtual void device_add_mconfig(machine_config &config) override;
- virtual const tiny_rom_entry *device_rom_region() const override;
-
-private:
- DECLARE_READ32_MEMBER(xceed30hr_r);
- DECLARE_WRITE32_MEMBER(xceed30hr_w);
- DECLARE_READ32_MEMBER(vram_r);
- DECLARE_WRITE32_MEMBER(vram_w);
-
- uint32_t screen_update(screen_device &screen, bitmap_rgb32 &bitmap, const rectangle &cliprect);
-
- std::vector<uint8_t> m_vram;
- uint32_t *m_vram32;
- 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(PDS030_XCEED30HR, nubus_xceed30hr_device)
+DECLARE_DEVICE_TYPE(PDS030_XCEED30HR, device_nubus_card_interface)
+DECLARE_DEVICE_TYPE(PDS030_XCEED30HRINT, device_nubus_card_interface)
+DECLARE_DEVICE_TYPE(PDS030_XCEEDMC30, device_nubus_card_interface)
+DECLARE_DEVICE_TYPE(PDS030_XCEEDMC30INT, device_nubus_card_interface)
#endif // MAME_BUS_NUBUS_PDS30_30HR_H
diff --git a/src/devices/bus/nubus/pds30_cb264.cpp b/src/devices/bus/nubus/pds30_cb264.cpp
index 4d153596fe0..f97cbf86c32 100644
--- a/src/devices/bus/nubus/pds30_cb264.cpp
+++ b/src/devices/bus/nubus/pds30_cb264.cpp
@@ -4,221 +4,210 @@
RasterOps ColorBoard 264/SE30 video card emulation
+ TMS34061 video controller
+ Bt473 RAMDAC
+
***************************************************************************/
#include "emu.h"
#include "pds30_cb264.h"
+
+#include "video/bt47x.h"
+#include "video/tms34061.h"
+
#include "screen.h"
-#define CB264SE30_SCREEN_NAME "cb264_screen"
-#define CB264SE30_ROM_REGION "cb264_rom"
+#include <algorithm>
-#define VRAM_SIZE (0x200000)
+namespace {
+static constexpr u32 VRAM_SIZE = 0x200000;
-ROM_START( cb264se30 )
- ROM_REGION(0x8000, CB264SE30_ROM_REGION, 0)
- ROM_LOAD( "0002-2019_10-02-90.bin", 0x000000, 0x008000, CRC(5b5b2fab) SHA1(0584deb38b402718f2abef456b0035b34fddb473) ) // EPROM label "264/30 V1.3 0002-2019 10/02/90"
-ROM_END
+class nubus_cb264se30_device : public device_t,
+ public device_nubus_card_interface
+{
+public:
+ // construction/destruction
+ nubus_cb264se30_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock);
+
+protected:
+ nubus_cb264se30_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, u32 clock);
+
+ // device-level overrides
+ virtual void device_start() override ATTR_COLD;
+ virtual void device_reset() override ATTR_COLD;
+
+ // optional information overrides
+ virtual void device_add_mconfig(machine_config &config) override ATTR_COLD;
+ virtual const tiny_rom_entry *device_rom_region() const override ATTR_COLD;
+
+ required_device<screen_device> m_screen;
+ required_device<bt473_device> m_ramdac;
+ required_device<tms34061_device> m_tms34061;
+
+ void card_map(address_map &map);
-//**************************************************************************
-// GLOBAL VARIABLES
-//**************************************************************************
+private:
+ u32 tms_r(offs_t offset, u32 mem_mask);
+ void tms_w(offs_t offset, u32 data, u32 mem_mask);
+ u8 vbl_r();
+ u8 mode_r();
+ void mode_w(u8 data);
+ u32 cb264se30_r(offs_t offset, u32 mem_mask = ~0);
+ void cb264se30_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);
-DEFINE_DEVICE_TYPE(PDS030_CB264SE30, nubus_cb264se30_device, "pd3_c264", "RasterOps Colorboard 264/SE30")
+ void vblank_w(int state);
+ u32 screen_update(screen_device &screen, bitmap_rgb32 &bitmap, const rectangle &cliprect);
-//-------------------------------------------------
-// device_add_mconfig - add device configuration
-//-------------------------------------------------
+ std::unique_ptr<u32[]> m_vram;
+ u32 m_mode;
+};
+
+ROM_START(cb264se30)
+ ROM_REGION(0x8000, "declrom", 0)
+ ROM_LOAD( "0002-2019_10-02-90.bin", 0x000000, 0x008000, CRC(5b5b2fab) SHA1(0584deb38b402718f2abef456b0035b34fddb473) ) // EPROM label "264/30 V1.3 0002-2019 10/02/90"
+ROM_END
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(config, m_screen, SCREEN_TYPE_RASTER);
+ m_screen->set_screen_update(FUNC(nubus_cb264se30_device::screen_update));
+ m_screen->set_raw(30.24_MHz_XTAL, 864, 0, 640, 525, 0, 480);
+
+ BT473(config, m_ramdac, 0);
-//-------------------------------------------------
-// rom_region - device-specific ROM region
-//-------------------------------------------------
+ TMS34061(config, m_tms34061, 0);
+ m_tms34061->set_rowshift(10); // VRAM address is (row << rowshift) | col
+ m_tms34061->set_vram_size(VRAM_SIZE);
+ m_tms34061->set_screen(m_screen);
+ m_tms34061->int_callback().set(FUNC(nubus_cb264se30_device::vblank_w));
+}
const tiny_rom_entry *nubus_cb264se30_device::device_rom_region() const
{
return ROM_NAME( cb264se30 );
}
-//**************************************************************************
-// LIVE DEVICE
-//**************************************************************************
-
-//-------------------------------------------------
-// nubus_cb264se30_device - constructor
-//-------------------------------------------------
-
-nubus_cb264se30_device::nubus_cb264se30_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) :
+nubus_cb264se30_device::nubus_cb264se30_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock) :
nubus_cb264se30_device(mconfig, PDS030_CB264SE30, tag, owner, clock)
{
- (void)m_toggle;
}
-nubus_cb264se30_device::nubus_cb264se30_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock) :
+nubus_cb264se30_device::nubus_cb264se30_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_vram32(nullptr), m_mode(0), m_vbl_disable(0), m_toggle(0), m_count(0), m_clutoffs(0), m_timer(nullptr)
+ m_screen(*this, "screen"),
+ m_ramdac(*this, "bt473"),
+ m_tms34061(*this, "tms34061"),
+ m_mode(0)
{
- set_screen(*this, CB264SE30_SCREEN_NAME);
}
-//-------------------------------------------------
-// device_start - device-specific startup
-//-------------------------------------------------
+void nubus_cb264se30_device::card_map(address_map &map)
+{
+ map(0x00'0000, 0x1f'ffff).rw(FUNC(nubus_cb264se30_device::vram_r), FUNC(nubus_cb264se30_device::vram_w));
+ map(0xfb'0000, 0xfb'00ff).rw(FUNC(nubus_cb264se30_device::tms_r), FUNC(nubus_cb264se30_device::tms_w));
+ map(0xfd'0000, 0xfd'0003).r(FUNC(nubus_cb264se30_device::vbl_r)).umask32(0xff000000);
+ map(0xfe'0000, 0xfe'0007).m(m_ramdac, FUNC(bt473_device::map)).umask32(0xff00ff00);
+ map(0xfe'000c, 0xfe'000f).rw(FUNC(nubus_cb264se30_device::mode_r), FUNC(nubus_cb264se30_device::mode_w)).umask32(0xff000000);
+}
void nubus_cb264se30_device::device_start()
{
- uint32_t slotspace;
-
- install_declaration_rom(this, CB264SE30_ROM_REGION);
+ install_declaration_rom("declrom");
- slotspace = get_slotspace();
+ m_vram = make_unique_clear<u32[]>(VRAM_SIZE / sizeof(u32));
-// printf("[cb264se30 %p] slotspace = %x\n", this, slotspace);
-
- m_vram.resize(VRAM_SIZE);
- m_vram32 = (uint32_t *)&m_vram[0];
-
- nubus().install_device(slotspace, slotspace+VRAM_SIZE-1, read32_delegate(FUNC(nubus_cb264se30_device::vram_r), this), write32_delegate(FUNC(nubus_cb264se30_device::vram_w), this));
- nubus().install_device(slotspace+0xf00000, slotspace+0xfeffff, read32_delegate(FUNC(nubus_cb264se30_device::cb264se30_r), this), write32_delegate(FUNC(nubus_cb264se30_device::cb264se30_w), this));
-
- m_timer = timer_alloc(0, nullptr);
- m_timer->adjust(screen().time_until_pos(479, 0), 0);
+ nubus().install_map(*this, &nubus_cb264se30_device::card_map);
}
-//-------------------------------------------------
-// device_reset - device-specific reset
-//-------------------------------------------------
-
void nubus_cb264se30_device::device_reset()
{
- m_count = 0;
- m_clutoffs = 0;
- m_vbl_disable = 1;
- m_mode = 4;
- memset(&m_vram[0], 0, VRAM_SIZE);
- memset(m_palette, 0, sizeof(m_palette));
-
- m_palette[0] = rgb_t(255, 255, 255);
- m_palette[0x80] = rgb_t(0, 0, 0);
}
-
-void nubus_cb264se30_device::device_timer(emu_timer &timer, device_timer_id tid, int param, void *ptr)
+u32 nubus_cb264se30_device::screen_update(screen_device &screen, bitmap_rgb32 &bitmap, const rectangle &cliprect)
{
- if (!m_vbl_disable)
+ auto const vram8 = util::big_endian_cast<u8 const>(&m_vram[0]) + (8*1024);
+ const pen_t *pens = m_ramdac->pens();
+
+ m_tms34061->get_display_state();
+ if (m_tms34061->blanked())
{
- raise_slot_irq();
+ bitmap.fill(rgb_t::black(), cliprect);
+ return 0;
}
- m_timer->adjust(screen().time_until_pos(479, 0), 0);
-}
-
-/***************************************************************************
-
- CB264 section
-
-***************************************************************************/
-
-uint32_t nubus_cb264se30_device::screen_update(screen_device &screen, bitmap_rgb32 &bitmap, const rectangle &cliprect)
-{
- uint32_t *scanline;
- int x, y;
- uint8_t pixels, *vram;
-
- vram = &m_vram[8*1024];
-
- switch (m_mode)
+ switch (m_mode & 7)
{
case 0: // 1 bpp?
- for (y = 0; y < 480; y++)
+ for (int y = 0; y < 480; y++)
{
- scanline = &bitmap.pix32(y);
- for (x = 0; x < 640/8; x++)
+ u32 *scanline = &bitmap.pix(y);
+ for (int x = 0; x < 640/8; x++)
{
- pixels = vram[(y * 1024) + (BYTE4_XOR_BE(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;
case 1: // 2 bpp
- for (y = 0; y < 480; y++)
+ for (int y = 0; y < 480; y++)
{
- scanline = &bitmap.pix32(y);
- for (x = 0; x < 640/4; x++)
+ u32 *scanline = &bitmap.pix(y);
+ for (int x = 0; x < 640/4; x++)
{
- pixels = vram[(y * 1024) + (BYTE4_XOR_BE(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;
case 2: // 4 bpp
- for (y = 0; y < 480; y++)
+ for (int y = 0; y < 480; y++)
{
- scanline = &bitmap.pix32(y);
-
- for (x = 0; x < 640/2; x++)
+ u32 *scanline = &bitmap.pix(y);
+ for (int x = 0; x < 640/2; x++)
{
- pixels = vram[(y * 1024) + (BYTE4_XOR_BE(x))];
+ u8 const pixels = vram8[(y * 1024) + x];
- *scanline++ = m_palette[(pixels&0xf0)];
- *scanline++ = m_palette[((pixels&0x0f)<<4)];
+ *scanline++ = pens[(pixels&0xf0)];
+ *scanline++ = pens[((pixels&0x0f)<<4)];
}
}
break;
case 3: // 8 bpp
- for (y = 0; y < 480; y++)
+ for (int y = 0; y < 480; y++)
{
- scanline = &bitmap.pix32(y);
-
- for (x = 0; x < 640; x++)
+ u32 *scanline = &bitmap.pix(y);
+ for (int x = 0; x < 640; x++)
{
- pixels = vram[(y * 1024) + (BYTE4_XOR_BE(x))];
- *scanline++ = m_palette[pixels];
+ u8 const pixels = vram8[(y * 1024) + x];
+ *scanline++ = pens[pixels];
}
}
break;
- case 4: // 24 bpp
+ case 7: // 24 bpp
+ for (int y = 0; y < 480; y++)
{
- uint32_t *vram32 = (uint32_t *)&m_vram[0];
- uint32_t *base;
-
- for (y = 0; y < 480; y++)
- {
- scanline = &bitmap.pix32(y);
- base = &vram32[y * 1024];
- for (x = 0; x < 640; x++)
- {
- *scanline++ = *base++;
- }
- }
+ std::copy_n(&m_vram[y * 1024], 640, &bitmap.pix(y));
}
break;
@@ -228,89 +217,60 @@ uint32_t nubus_cb264se30_device::screen_update(screen_device &screen, bitmap_rgb
return 0;
}
-WRITE32_MEMBER( nubus_cb264se30_device::cb264se30_w )
+u32 nubus_cb264se30_device::tms_r(offs_t offset, u32 mem_mask)
{
- switch (offset)
- {
- case 0x38003: // mode
-// if (data != 0x08000000) printf("%08x to mode\n", data);
- switch (data & 0xff000000)
- {
- case 0x38000000:
- m_mode = 0;
- break;
-
- case 0x39000000:
- m_mode = 1;
- break;
-
- case 0x3a000000:
- m_mode = 2;
- break;
-
- case 0x3b000000:
- m_mode = 3;
- break;
+ return m_tms34061->read(offset << 1, 0, 0) << 24;
+}
- case 0x3f000000:
- m_mode = 4;
- break;
- }
- break;
+void nubus_cb264se30_device::tms_w(offs_t offset, u32 data, u32 mem_mask)
+{
+ if (mem_mask == 0xff000000)
+ {
+ m_tms34061->write(offset << 1, 0, 0, data >> 24);
+ }
+ else
+ {
+ logerror("TMS write with unknown mask %08x\n", mem_mask);
+ }
+}
- case 0x38000:
- if (mem_mask == 0xff000000)
- {
- // logerror("%08x to DAC control %s\n", data, machine().describe_context());
- m_clutoffs = (data>>24)&0xff;
- }
- else if (mem_mask == 0x0000ff00)
- {
- m_colors[m_count++] = (data>>8) & 0xff;
-
- if (m_count == 3)
- {
-// logerror("RAMDAC: color %02x = %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[0], m_colors[1], m_colors[2]);
- m_clutoffs++;
- if (m_clutoffs > 255)
- {
- m_clutoffs = 0;
- }
- m_count = 0;
- }
- }
- break;
+u8 nubus_cb264se30_device::vbl_r()
+{
+ return 0;
+}
- case 0x2c017: // VBL control
- if (data & 0x06000000)
- {
- m_vbl_disable = 0;
- lower_slot_irq();
- }
- else
- {
- m_vbl_disable = 1;
- }
- break;
+u8 nubus_cb264se30_device::mode_r()
+{
+ return m_mode;
+}
- default:
-// logerror("cb264se30_w: %08x @ %x, mask %08x %s\n", data, offset, mem_mask, machine().describe_context());
- break;
- }
+void nubus_cb264se30_device::mode_w(u8 data)
+{
+ m_mode = data;
}
-READ32_MEMBER( nubus_cb264se30_device::cb264se30_r )
+void nubus_cb264se30_device::vram_w(offs_t offset, u32 data, u32 mem_mask)
{
- return 0;
+ COMBINE_DATA(&m_vram[offset]);
}
-WRITE32_MEMBER( nubus_cb264se30_device::vram_w )
+u32 nubus_cb264se30_device::vram_r(offs_t offset, u32 mem_mask)
{
- COMBINE_DATA(&m_vram32[offset]);
+ return m_vram[offset];
}
-READ32_MEMBER( nubus_cb264se30_device::vram_r )
+void nubus_cb264se30_device::vblank_w(int state)
{
- return m_vram32[offset];
+ if (state)
+ {
+ raise_slot_irq();
+ }
+ else
+ {
+ lower_slot_irq();
+ }
}
+
+} // anonymous namespace
+
+DEFINE_DEVICE_TYPE_PRIVATE(PDS030_CB264SE30, device_nubus_card_interface, nubus_cb264se30_device, "pd3_c264", "RasterOps ColorBoard 264/SE30")
diff --git a/src/devices/bus/nubus/pds30_cb264.h b/src/devices/bus/nubus/pds30_cb264.h
index f32289fb0af..54de3acbbfd 100644
--- a/src/devices/bus/nubus/pds30_cb264.h
+++ b/src/devices/bus/nubus/pds30_cb264.h
@@ -7,50 +7,6 @@
#include "nubus.h"
-//**************************************************************************
-// TYPE DEFINITIONS
-//**************************************************************************
-
-// ======================> nubus_cb264se30_device
-
-class nubus_cb264se30_device :
- public device_t,
- public device_video_interface,
- public device_nubus_card_interface
-{
-public:
- // construction/destruction
- nubus_cb264se30_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
-
-protected:
- nubus_cb264se30_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_timer(emu_timer &timer, device_timer_id id, int param, void *ptr) override;
-
- // optional information overrides
- virtual void device_add_mconfig(machine_config &config) override;
- virtual const tiny_rom_entry *device_rom_region() const override;
-
-private:
- DECLARE_READ32_MEMBER(cb264se30_r);
- DECLARE_WRITE32_MEMBER(cb264se30_w);
- DECLARE_READ32_MEMBER(vram_r);
- DECLARE_WRITE32_MEMBER(vram_w);
-
- uint32_t screen_update(screen_device &screen, bitmap_rgb32 &bitmap, const rectangle &cliprect);
-
- std::vector<uint8_t> m_vram;
- uint32_t *m_vram32;
- 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(PDS030_CB264SE30, nubus_cb264se30_device)
+DECLARE_DEVICE_TYPE(PDS030_CB264SE30, device_nubus_card_interface);
#endif // MAME_BUS_NUBUS_PDS30_CB264_H
diff --git a/src/devices/bus/nubus/pds30_mc30.cpp b/src/devices/bus/nubus/pds30_mc30.cpp
deleted file mode 100644
index 6770b517deb..00000000000
--- a/src/devices/bus/nubus/pds30_mc30.cpp
+++ /dev/null
@@ -1,327 +0,0 @@
-// license:BSD-3-Clause
-// copyright-holders:R. Belmont
-/***************************************************************************
-
- Micron/XCEED Technologies MacroColor 30
-
- Similar to the 30HR, but registers are rearranged and 24bpp support
- was added.
-
-***************************************************************************/
-
-#include "emu.h"
-#include "pds30_mc30.h"
-#include "screen.h"
-
-#define XCEEDMC30_SCREEN_NAME "x30hr_screen"
-#define XCEEDMC30_ROM_REGION "x30hr_rom"
-
-#define VRAM_SIZE (0x200000) // 16 42C4256 256Kx4 VRAMs on the board = 2MB
-
-
-ROM_START( xceedmc30 )
- ROM_REGION(0x8000, XCEEDMC30_ROM_REGION, 0)
- ROM_LOAD( "0390.bin", 0x000000, 0x008000, CRC(adea7a18) SHA1(9141eb1a0e5061e0409d65a89b4eaeb119ee4ffb) )
-ROM_END
-
-//**************************************************************************
-// GLOBAL VARIABLES
-//**************************************************************************
-
-DEFINE_DEVICE_TYPE(PDS030_XCEEDMC30, nubus_xceedmc30_device, "pd3_mclr", "Micron/XCEED Technology MacroColor 30")
-
-
-//-------------------------------------------------
-// device_add_mconfig - add device configuration
-//-------------------------------------------------
-
-void nubus_xceedmc30_device::device_add_mconfig(machine_config &config)
-{
- screen_device &screen(SCREEN(config, XCEEDMC30_SCREEN_NAME, SCREEN_TYPE_RASTER));
- screen.set_screen_update(FUNC(nubus_xceedmc30_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);
-}
-
-//-------------------------------------------------
-// rom_region - device-specific ROM region
-//-------------------------------------------------
-
-const tiny_rom_entry *nubus_xceedmc30_device::device_rom_region() const
-{
- return ROM_NAME( xceedmc30 );
-}
-
-//**************************************************************************
-// LIVE DEVICE
-//**************************************************************************
-
-//-------------------------------------------------
-// nubus_xceedmc30_device - constructor
-//-------------------------------------------------
-
-nubus_xceedmc30_device::nubus_xceedmc30_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) :
- nubus_xceedmc30_device(mconfig, PDS030_XCEEDMC30, tag, owner, clock)
-{
-}
-
-nubus_xceedmc30_device::nubus_xceedmc30_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),
- device_nubus_card_interface(mconfig, *this),
- m_vram32(nullptr), m_mode(0), m_vbl_disable(0), m_toggle(0), m_count(0), m_clutoffs(0), m_timer(nullptr)
-{
- set_screen(*this, XCEEDMC30_SCREEN_NAME);
-}
-
-//-------------------------------------------------
-// device_start - device-specific startup
-//-------------------------------------------------
-
-void nubus_xceedmc30_device::device_start()
-{
- uint32_t slotspace;
-
- install_declaration_rom(this, XCEEDMC30_ROM_REGION);
-
- slotspace = get_slotspace();
-
-// printf("[xceedmc30 %p] slotspace = %x\n", this, slotspace);
-
- m_vram.resize(VRAM_SIZE);
- m_vram32 = (uint32_t *)&m_vram[0];
-
- nubus().install_device(slotspace, slotspace+VRAM_SIZE-1, read32_delegate(FUNC(nubus_xceedmc30_device::vram_r), this), write32_delegate(FUNC(nubus_xceedmc30_device::vram_w), this));
- nubus().install_device(slotspace+0x800000, slotspace+0xefffff, read32_delegate(FUNC(nubus_xceedmc30_device::xceedmc30_r), this), write32_delegate(FUNC(nubus_xceedmc30_device::xceedmc30_w), this));
-
- m_timer = timer_alloc(0, nullptr);
- m_timer->adjust(screen().time_until_pos(479, 0), 0);
-}
-
-//-------------------------------------------------
-// device_reset - device-specific reset
-//-------------------------------------------------
-
-void nubus_xceedmc30_device::device_reset()
-{
- m_count = 0;
- m_clutoffs = 0;
- m_vbl_disable = 1;
- m_mode = 0;
- memset(&m_vram[0], 0, VRAM_SIZE);
- memset(m_palette, 0, sizeof(m_palette));
-
- m_palette[0] = rgb_t(255, 255, 255);
- m_palette[0x80] = rgb_t(0, 0, 0);
-}
-
-
-void nubus_xceedmc30_device::device_timer(emu_timer &timer, device_timer_id tid, int param, void *ptr)
-{
- if (!m_vbl_disable)
- {
- raise_slot_irq();
- }
-
- m_timer->adjust(screen().time_until_pos(479, 0), 0);
-}
-
-/***************************************************************************
-
- CB264 section
-
-***************************************************************************/
-
-uint32_t nubus_xceedmc30_device::screen_update(screen_device &screen, bitmap_rgb32 &bitmap, const rectangle &cliprect)
-{
- uint32_t *scanline;
- int x, y;
- uint8_t pixels, *vram;
-
- vram = &m_vram[4*1024];
-
- switch (m_mode)
- {
- case 0: // 1 bpp?
- for (y = 0; y < 480; y++)
- {
- scanline = &bitmap.pix32(y);
- for (x = 0; x < 640/8; x++)
- {
- pixels = vram[(y * 1024) + (BYTE4_XOR_BE(x))];
-
- *scanline++ = m_palette[(pixels>>7)&1];
- *scanline++ = m_palette[(pixels>>6)&1];
- *scanline++ = m_palette[(pixels>>5)&1];
- *scanline++ = m_palette[(pixels>>4)&1];
- *scanline++ = m_palette[(pixels>>3)&1];
- *scanline++ = m_palette[(pixels>>2)&1];
- *scanline++ = m_palette[(pixels>>1)&1];
- *scanline++ = m_palette[pixels&1];
- }
- }
- break;
-
- case 1: // 2 bpp
- for (y = 0; y < 480; y++)
- {
- scanline = &bitmap.pix32(y);
- for (x = 0; x < 640/4; x++)
- {
- pixels = vram[(y * 1024) + (BYTE4_XOR_BE(x))];
-
- *scanline++ = m_palette[((pixels>>6)&3)];
- *scanline++ = m_palette[((pixels>>4)&3)];
- *scanline++ = m_palette[((pixels>>2)&3)];
- *scanline++ = m_palette[(pixels&3)];
- }
- }
- break;
-
- case 2: // 4 bpp
- for (y = 0; y < 480; y++)
- {
- scanline = &bitmap.pix32(y);
-
- for (x = 0; x < 640/2; x++)
- {
- pixels = vram[(y * 1024) + (BYTE4_XOR_BE(x))];
-
- *scanline++ = m_palette[(pixels>>4)];
- *scanline++ = m_palette[(pixels&0xf)];
- }
- }
- break;
-
- case 3: // 8 bpp
- for (y = 0; y < 480; y++)
- {
- scanline = &bitmap.pix32(y);
-
- for (x = 0; x < 640; x++)
- {
- pixels = vram[(y * 1024) + (BYTE4_XOR_BE(x))];
- *scanline++ = m_palette[pixels];
- }
- }
- break;
-
- case 4: // 24 bpp
- {
- uint32_t *vram32 = (uint32_t *)vram;
- uint32_t *base;
-
- for (y = 0; y < 480; y++)
- {
- scanline = &bitmap.pix32(y);
- base = &vram32[y * 1024];
- for (x = 0; x < 640; x++)
- {
- *scanline++ = *base++;
- }
- }
- }
- break;
-
- default:
- fatalerror("xceedmc30: unknown video mode %d\n", m_mode);
- }
- return 0;
-}
-
-WRITE32_MEMBER( nubus_xceedmc30_device::xceedmc30_w )
-{
- switch (offset)
- {
- case 0x80000: // mode
- switch (data & 0xff000000)
- {
- case 0xfb000000:
- m_mode = 0;
- break;
-
- case 0xfa000000:
- m_mode = 1;
- break;
-
- case 0xf9000000:
- m_mode = 2;
- break;
-
- case 0xf8000000:
- m_mode = 3;
- break;
-
- case 0xff000000:
- m_mode = 4;
- break;
- }
- break;
-
- case 0x80005: // ack VBL
- lower_slot_irq();
- break;
-
- case 0x100000:
-// logerror("%s %08x to DAC control\n", machine().describe_context(), data);
- m_clutoffs = (data&0xff);
- m_count = 0;
- break;
-
- case 0x100001:
-// printf("%s %08x to DAC data\n", machine().describe_context().c_str(), data);
- m_colors[m_count++] = ((data>>24) & 0xff);
-
- if (m_count == 3)
- {
-// printf("%s RAMDAC: color %02x = %02x %02x %02x\n", machine().describe_context().c_str(), m_clutoffs, m_colors[0], m_colors[1], m_colors[2]);
- m_palette[m_clutoffs] = rgb_t(m_colors[0], m_colors[1], m_colors[2]);
- m_clutoffs++;
- if (m_clutoffs > 255)
- {
- m_clutoffs = 0;
- }
- m_count = 0;
- }
- break;
-
- case 0x80002: // VBL control
- if (data == 0xdcef0000)
- {
- m_vbl_disable = 0;
- lower_slot_irq();
- }
- else
- {
- m_vbl_disable = 1;
- }
- break;
-
- default:
-// printf("%s xceedmc30_w: %08x @ %x, mask %08x\n", machine().describe_context().c_str(), data, offset, mem_mask);
- break;
- }
-}
-
-READ32_MEMBER( nubus_xceedmc30_device::xceedmc30_r )
-{
-// printf("xceedmc30_r: @ %x, mask %08x [PC=%x]\n", offset, mem_mask, machine().device<cpu_device>("maincpu")->pc());
- if (offset == 0x80008)
- {
- m_toggle ^= 0x04;
- return m_toggle;
- }
-
- return 0;
-}
-
-WRITE32_MEMBER( nubus_xceedmc30_device::vram_w )
-{
- COMBINE_DATA(&m_vram32[offset]);
-}
-
-READ32_MEMBER( nubus_xceedmc30_device::vram_r )
-{
- return m_vram32[offset];
-}
diff --git a/src/devices/bus/nubus/pds30_mc30.h b/src/devices/bus/nubus/pds30_mc30.h
deleted file mode 100644
index db4fe782753..00000000000
--- a/src/devices/bus/nubus/pds30_mc30.h
+++ /dev/null
@@ -1,56 +0,0 @@
-// license:BSD-3-Clause
-// copyright-holders:R. Belmont
-#ifndef MAME_BUS_NUBUS_PDS30_MC30_H
-#define MAME_BUS_NUBUS_PDS30_MC30_H
-
-#pragma once
-
-#include "nubus.h"
-
-//**************************************************************************
-// TYPE DEFINITIONS
-//**************************************************************************
-
-// ======================> nubus_xceedmc30_device
-
-class nubus_xceedmc30_device :
- public device_t,
- public device_video_interface,
- public device_nubus_card_interface
-{
-public:
- // construction/destruction
- nubus_xceedmc30_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
-
-protected:
- nubus_xceedmc30_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_timer(emu_timer &timer, device_timer_id id, int param, void *ptr) override;
-
- // optional information overrides
- virtual void device_add_mconfig(machine_config &config) override;
- virtual const tiny_rom_entry *device_rom_region() const override;
-
-private:
- DECLARE_READ32_MEMBER(xceedmc30_r);
- DECLARE_WRITE32_MEMBER(xceedmc30_w);
- DECLARE_READ32_MEMBER(vram_r);
- DECLARE_WRITE32_MEMBER(vram_w);
-
- uint32_t screen_update(screen_device &screen, bitmap_rgb32 &bitmap, const rectangle &cliprect);
-
- std::vector<uint8_t> m_vram;
- uint32_t *m_vram32;
- 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(PDS030_XCEEDMC30, nubus_xceedmc30_device)
-
-#endif // MAME_BUS_NUBUS_PDS30_MC30_H
diff --git a/src/devices/bus/nubus/pds30_procolor816.cpp b/src/devices/bus/nubus/pds30_procolor816.cpp
index 440ba6c86d7..3d90d784f8d 100644
--- a/src/devices/bus/nubus/pds30_procolor816.cpp
+++ b/src/devices/bus/nubus/pds30_procolor816.cpp
@@ -10,20 +10,27 @@
FsFF7000: Bit 2 is VBL IRQ enable/ack
FsFF7001: Bit 0 is VBL status
+ All of Lapis' cards for Macs have the same architecture:
+ A Xilinx FPGA that the declaration ROM reprograms for each color depth
+ A TLC34075 or TLC34076 RAMDAC
+
***************************************************************************/
#include "emu.h"
#include "pds30_procolor816.h"
+
+#include "video/tlc34076.h"
+
#include "screen.h"
-#define PROCOLOR816_SCREEN_NAME "cb264_screen"
-#define PROCOLOR816_ROM_REGION "cb264_rom"
+#include <algorithm>
-#define VRAM_SIZE (0x200000) // 2 megs?
+static constexpr u32 VRAM_SIZE = 0x200000;
+namespace {
ROM_START( procolor816 )
- ROM_REGION(0x8000, PROCOLOR816_ROM_REGION, 0)
+ ROM_REGION(0x8000, "declrom", 0)
ROM_LOAD( "procolor_ver60590.bin", 0x000000, 0x008000, CRC(ebef6168) SHA1(e41ecc7d12fc13bc74f9223ca02920e8a7eb072b) )
ROM_END
@@ -31,97 +38,112 @@ ROM_END
// GLOBAL VARIABLES
//**************************************************************************
-DEFINE_DEVICE_TYPE(PDS030_PROCOLOR816, nubus_procolor816_device, "pd3_pc16", "Lapis ProColor Server 8*16")
+class nubus_procolor816_device : public device_t,
+ public device_video_interface,
+ public device_nubus_card_interface
+{
+public:
+ // construction/destruction
+ nubus_procolor816_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock);
+protected:
+ nubus_procolor816_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, u32 clock);
-//-------------------------------------------------
-// device_add_mconfig - add device configuration
-//-------------------------------------------------
+ // device-level overrides
+ virtual void device_start() override ATTR_COLD;
+ virtual void device_reset() override ATTR_COLD;
-void nubus_procolor816_device::device_add_mconfig(machine_config &config)
+ // optional information overrides
+ virtual void device_add_mconfig(machine_config &config) override ATTR_COLD;
+ virtual const tiny_rom_entry *device_rom_region() const override ATTR_COLD;
+
+ void card_map(address_map &map);
+
+ TIMER_CALLBACK_MEMBER(vbl_tick);
+
+ bool m_has_15bpp;
+
+private:
+ u8 regs_r(offs_t offset);
+ void regs_w(offs_t offset, u8 data);
+ 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);
+
+ required_device<screen_device> m_screen;
+ required_device<tlc34076_device> m_dac;
+
+ std::unique_ptr<u32[]> m_vram;
+ u8 m_video_enable, m_vbl_disable;
+ emu_timer *m_timer;
+};
+
+void nubus_procolor816_device::card_map(address_map &map)
{
- screen_device &screen(SCREEN(config, PROCOLOR816_SCREEN_NAME, SCREEN_TYPE_RASTER));
- screen.set_screen_update(FUNC(nubus_procolor816_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);
+ map(0x00'0000, 0x1f'ffff).rw(FUNC(nubus_procolor816_device::vram_r), FUNC(nubus_procolor816_device::vram_w));
+ map(0xfd'6000, 0xfd'603f).rw(m_dac, FUNC(tlc34076_device::read), FUNC(tlc34076_device::write)).umask32(0x00ff0000);
+ map(0xfd'7000, 0xfd'7fff).rw(FUNC(nubus_procolor816_device::regs_r), FUNC(nubus_procolor816_device::regs_w));
+ map(0xff'6000, 0xff'601f).rw(m_dac, FUNC(tlc34076_device::read), FUNC(tlc34076_device::write)).umask32(0x00ff00ff);
+ map(0xff'7000, 0xff'7fff).rw(FUNC(nubus_procolor816_device::regs_r), FUNC(nubus_procolor816_device::regs_w));
}
-//-------------------------------------------------
-// rom_region - device-specific ROM region
-//-------------------------------------------------
+void nubus_procolor816_device::device_add_mconfig(machine_config &config)
+{
+ SCREEN(config, m_screen, SCREEN_TYPE_RASTER);
+ m_screen->set_screen_update(FUNC(nubus_procolor816_device::screen_update));
+ m_screen->set_raw(25175000, 800, 0, 640, 525, 0, 480);
+
+ TLC34076(config, m_dac, tlc34076_device::TLC34076_8_BIT); // actually a TLC34075, but I can't find a difference
+}
const tiny_rom_entry *nubus_procolor816_device::device_rom_region() const
{
return ROM_NAME( procolor816 );
}
-//**************************************************************************
-// LIVE DEVICE
-//**************************************************************************
-
-//-------------------------------------------------
-// nubus_procolor816_device - constructor
-//-------------------------------------------------
-
-nubus_procolor816_device::nubus_procolor816_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) :
+nubus_procolor816_device::nubus_procolor816_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock) :
nubus_procolor816_device(mconfig, PDS030_PROCOLOR816, tag, owner, clock)
{
}
-nubus_procolor816_device::nubus_procolor816_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock) :
+nubus_procolor816_device::nubus_procolor816_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_vram32(nullptr), m_mode(0), m_vbl_disable(0), m_toggle(0), m_count(0), m_clutoffs(0), m_timer(nullptr)
+ m_has_15bpp(true),
+ m_screen(*this, "screen"),
+ m_dac(*this, "tlc34076"),
+ m_video_enable(0),
+ m_vbl_disable(0),
+ m_timer(nullptr)
{
- set_screen(*this, PROCOLOR816_SCREEN_NAME);
+ set_screen(*this, "screen");
}
-//-------------------------------------------------
-// device_start - device-specific startup
-//-------------------------------------------------
-
void nubus_procolor816_device::device_start()
{
- uint32_t slotspace;
-
- install_declaration_rom(this, PROCOLOR816_ROM_REGION);
-
- slotspace = get_slotspace();
-
-// printf("[procolor816 %p] slotspace = %x\n", this, slotspace);
+ m_vram = make_unique_clear<u32[]>(VRAM_SIZE / sizeof(u32));
- m_vram.resize(VRAM_SIZE);
- m_vram32 = (uint32_t *)&m_vram[0];
+ install_declaration_rom("declrom");
+ nubus().install_map(*this, &nubus_procolor816_device::card_map);
- nubus().install_device(slotspace, slotspace+VRAM_SIZE-1, read32_delegate(FUNC(nubus_procolor816_device::vram_r), this), write32_delegate(FUNC(nubus_procolor816_device::vram_w), this));
- nubus().install_device(slotspace+0x900000, slotspace+VRAM_SIZE-1+0x900000, read32_delegate(FUNC(nubus_procolor816_device::vram_r), this), write32_delegate(FUNC(nubus_procolor816_device::vram_w), this));
- nubus().install_device(slotspace+0xf00000, slotspace+0xff7fff, read32_delegate(FUNC(nubus_procolor816_device::procolor816_r), this), write32_delegate(FUNC(nubus_procolor816_device::procolor816_w), this));
-
- m_timer = timer_alloc(0, nullptr);
+ m_timer = timer_alloc(FUNC(nubus_procolor816_device::vbl_tick), this);
m_timer->adjust(screen().time_until_pos(479, 0), 0);
-}
-//-------------------------------------------------
-// device_reset - device-specific reset
-//-------------------------------------------------
+ save_item(NAME(m_video_enable));
+ save_item(NAME(m_vbl_disable));
+ save_pointer(NAME(m_vram), VRAM_SIZE / sizeof(u32));
+}
void nubus_procolor816_device::device_reset()
{
- m_count = 0;
- m_clutoffs = 0;
m_vbl_disable = 1;
- m_mode = 3;
- memset(&m_vram[0], 0, VRAM_SIZE);
- memset(m_palette, 0, sizeof(m_palette));
-
- m_palette[0] = rgb_t(255, 255, 255);
- m_palette[0x80] = rgb_t(0, 0, 0);
+ m_video_enable = 0;
+ std::fill_n(&m_vram[0], VRAM_SIZE / sizeof(u32), 0);
}
-
-void nubus_procolor816_device::device_timer(emu_timer &timer, device_timer_id tid, int param, void *ptr)
+TIMER_CALLBACK_MEMBER(nubus_procolor816_device::vbl_tick)
{
if (!m_vbl_disable)
{
@@ -131,211 +153,213 @@ void nubus_procolor816_device::device_timer(emu_timer &timer, device_timer_id ti
m_timer->adjust(screen().time_until_pos(479, 0), 0);
}
-/***************************************************************************
-
- CB264 section
-
-***************************************************************************/
-
-uint32_t nubus_procolor816_device::screen_update(screen_device &screen, bitmap_rgb32 &bitmap, const rectangle &cliprect)
+u32 nubus_procolor816_device::screen_update(screen_device &screen, bitmap_rgb32 &bitmap, const rectangle &cliprect)
{
- uint32_t *scanline;
- int x, y;
- uint8_t pixels, *vram;
+ if (!m_video_enable)
+ {
+ bitmap.fill(0, cliprect);
+ return 0;
+ }
- vram = &m_vram[4];
+ auto const vram8 = util::big_endian_cast<u8 const>(&m_vram[0]) + 4;
+ pen_t const *const pens = m_dac->pens();
+ const auto clock_select = m_dac->read(0xa); // get the TLC34076 output clock select
+ const auto pixel_mask = m_dac->read(2); // get the TLC34076 pixel mask
- switch (m_mode)
+ switch (pixel_mask)
{
- case 0: // 1 bpp?
- for (y = 0; y < 480; y++)
+ case 0x1: // 1 bpp - SCLK = DOTCLK/32
+ for (int y = 0; y < 480; y++)
{
- scanline = &bitmap.pix32(y);
- for (x = 0; x < 640/8; x++)
+ u32 *scanline = &bitmap.pix(y);
+ for (int x = 0; x < 640/8; x++)
{
- pixels = vram[(y * 640/8) + (BYTE4_XOR_BE(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 * 640/8) + x];
+
+ *scanline++ = pens[(pixels>>7)&1];
+ *scanline++ = pens[(pixels>>6)&1];
+ *scanline++ = pens[(pixels>>5)&1];
+ *scanline++ = pens[(pixels>>4)&1];
+ *scanline++ = pens[(pixels>>3)&1];
+ *scanline++ = pens[(pixels>>2)&1];
+ *scanline++ = pens[(pixels>>1)&1];
+ *scanline++ = pens[pixels&1];
}
}
break;
- case 1: // 2 bpp
- for (y = 0; y < 480; y++)
+ case 0x3: // 2 bpp - SCLK = DOTCLK/16
+ for (int y = 0; y < 480; y++)
{
- scanline = &bitmap.pix32(y);
- for (x = 0; x < 640/4; x++)
+ u32 *scanline = &bitmap.pix(y);
+ for (int x = 0; x < 640/4; x++)
{
- pixels = vram[(y * 640/4) + (BYTE4_XOR_BE(x))];
+ u8 const pixels = vram8[(y * 640/4) + 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>>6)&3];
+ *scanline++ = pens[(pixels>>4)&3];
+ *scanline++ = pens[(pixels>>2)&3];
+ *scanline++ = pens[pixels & 0x3];
}
}
break;
- case 2: // 4 bpp
- for (y = 0; y < 480; y++)
+ case 0xf: // 4 bpp - SCLK = DOTCLK/8
+ for (int y = 0; y < 480; y++)
{
- scanline = &bitmap.pix32(y);
-
- for (x = 0; x < 640/2; x++)
+ u32 *scanline = &bitmap.pix(y);
+ for (int x = 0; x < 640/2; x++)
{
- pixels = vram[(y * 640/2) + (BYTE4_XOR_BE(x))];
+ u8 const pixels = bitswap(vram8[(y * 640 / 2) + x], 4, 5, 6, 7, 0, 1, 2, 3);
- *scanline++ = m_palette[(pixels&0xf0)];
- *scanline++ = m_palette[((pixels&0x0f)<<4)];
+ *scanline++ = pens[(pixels>>4)&0xf];
+ *scanline++ = pens[pixels&0xf];
}
}
break;
- case 3: // 8 bpp
- for (y = 0; y < 480; y++)
+ case 0xff: // 8 bpp - SCLK = DOTCLK/4
+ if ((clock_select == 0x19) && (m_has_15bpp))
{
- scanline = &bitmap.pix32(y);
+ auto const vram16 = util::big_endian_cast<u16 const>(&m_vram[0]);
- for (x = 0; x < 640; x++)
+ for (int y = 0; y < 480; y++)
{
- pixels = vram[(y * 640) + (BYTE4_XOR_BE(x))];
- *scanline++ = m_palette[pixels];
+ u32 *scanline = &bitmap.pix(y);
+ for (int x = 0; x < 640; x++)
+ {
+ u16 const pixels = vram16[(y * 640) + x];
+ *scanline++ = rgb_t(pal5bit((pixels >> 10) & 0x1f), pal5bit((pixels >> 5) & 0x1f), pal5bit(pixels & 0x1f));
+ }
}
}
- break;
-
- case 4: // 15 bpp
+ else
{
- uint16_t *vram16 = (uint16_t *)&m_vram[0];
- uint16_t pixels;
-
- for (y = 0; y < 480; y++)
+ for (int y = 0; y < 480; y++)
{
- scanline = &bitmap.pix32(y);
- for (x = 0; x < 640; x++)
+ u32 *scanline = &bitmap.pix(y);
+ for (int x = 0; x < 640; x++)
{
- pixels = vram16[(y * 640) + (x^1)];
- *scanline++ = rgb_t(((pixels>>10) & 0x1f)<<3, ((pixels>>5) & 0x1f)<<3, (pixels & 0x1f)<<3);
+ u8 const pixels = bitswap(vram8[(y * 640) + x], 0, 1, 2, 3, 4, 5, 6, 7);
+ *scanline++ = pens[pixels];
}
}
}
break;
default:
- fatalerror("procolor816: unknown video mode %d\n", m_mode);
+ fatalerror("procolor816: unknown video mode %x\n", clock_select);
}
+
return 0;
}
-WRITE32_MEMBER( nubus_procolor816_device::procolor816_w )
+void nubus_procolor816_device::regs_w(offs_t offset, u8 data)
{
switch (offset)
{
- case 0x3d805: // mode
- if (mem_mask == 0xff)
- {
- switch (data & 0xff)
- {
- case 0x13:
- m_mode = 0;
- break;
-
- case 0x17:
- m_mode = 1;
- break;
-
- case 0x1b:
- m_mode = 2;
- break;
+ case 0: // bit 3 = screen enable, bit 2 = VBL control
+ case 3: // ProColor 8 mirrors this here
+ m_video_enable = BIT(data, 3);
- case 0x1e:
- m_mode = 3;
- break;
-
- case 0x0a:
- m_mode = 4;
- break;
- }
- }
- break;
-
- case 0x3d800:
- if (mem_mask == 0x00ff0000)
+ if (BIT(data, 2))
{
- // printf("%s %08x to DAC control\n", machine().describe_context().c_str(), data);
- m_clutoffs = bitswap<8>((data>>16)&0xff, 0, 1, 2, 3, 4, 5, 6, 7);
+ m_vbl_disable = 0;
+ lower_slot_irq();
}
- else if (mem_mask == 0x000000ff)
+ else
{
- m_colors[m_count++] = (data & 0xff);
-
- if (m_count == 3)
- {
-// printf("%s RAMDAC: color %02x = %02x %02x %02x\n", machine().describe_context().c_str(), m_clutoffs, m_colors[0], m_colors[1], m_colors[2]);
- m_palette[m_clutoffs] = rgb_t(m_colors[0], m_colors[1], m_colors[2]);
- m_clutoffs++;
- if (m_clutoffs > 255)
- {
- m_clutoffs = 0;
- }
- m_count = 0;
- }
+ m_vbl_disable = 1;
}
break;
- case 0x3dc00: // VBL control
- if (mem_mask == 0xff000000)
- {
- if (data & 0x04000000)
- {
- m_vbl_disable = 0;
- lower_slot_irq();
- }
- else
- {
- m_vbl_disable = 1;
- }
- }
+ case 0x800: // Xilinx XC3030 FPGA bitstream write
break;
default:
-// printf("%s procolor816_w: %08x @ %x, mask %08x\n", machine().describe_context().c_str(), data, offset, mem_mask);
+ logerror("%s procolor816_w: %08x @ %x\n", machine().describe_context().c_str(), data, offset);
break;
}
}
-READ32_MEMBER( nubus_procolor816_device::procolor816_r )
+u8 nubus_procolor816_device::regs_r(offs_t offset)
{
- if (offset == 0x3dc00)
- {
- m_toggle ^= 0xffffffff;
- return m_toggle;
- }
- else if (offset == 0x3d807)
- {
- return 0;
- }
- else
+ switch (offset)
{
-// printf("procolor816_r: @ %x, mask %08x [PC=%x]\n", offset, mem_mask, machine().device<cpu_device>("maincpu")->pc());
- }
+ case 0x1:
+ return m_screen->vblank() ? 1 : 0;
+ default:
+ logerror("%s procolor816_r: unknown @ %x\n", machine().describe_context().c_str(), offset);
+ break;
+ }
return 0;
}
-WRITE32_MEMBER( nubus_procolor816_device::vram_w )
+void nubus_procolor816_device::vram_w(offs_t offset, u32 data, u32 mem_mask)
{
- COMBINE_DATA(&m_vram32[offset]);
+ COMBINE_DATA(&m_vram[offset]);
}
-READ32_MEMBER( nubus_procolor816_device::vram_r )
+u32 nubus_procolor816_device::vram_r(offs_t offset, u32 mem_mask)
{
- return m_vram32[offset];
+ return m_vram[offset];
}
+
+class pds30_procolor8_device : public nubus_procolor816_device
+{
+public:
+ // construction/destruction
+ pds30_procolor8_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock);
+
+protected:
+ virtual const tiny_rom_entry *device_rom_region() const override ATTR_COLD;
+};
+
+ROM_START( procolor8_pds )
+ ROM_REGION(0x8000, "declrom", 0)
+ ROM_LOAD( "procolorserver8.bin", 0x000000, 0x008000, CRC(8701ba41) SHA1(ef2d7ad3309a0df16ec392a82110118830d276b5) )
+ROM_END
+
+const tiny_rom_entry *pds30_procolor8_device::device_rom_region() const
+{
+ return ROM_NAME(procolor8_pds);
+}
+
+pds30_procolor8_device::pds30_procolor8_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock) :
+ nubus_procolor816_device(mconfig, PDS030_PROCOLOR8, tag, owner, clock)
+{
+ m_has_15bpp = false;
+}
+
+class nubus_procolor8_device : public nubus_procolor816_device
+{
+public:
+ // construction/destruction
+ nubus_procolor8_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock);
+
+protected:
+ virtual const tiny_rom_entry *device_rom_region() const override ATTR_COLD;
+};
+
+ROM_START( procolor8_nb )
+ ROM_REGION(0x8000, "declrom", 0)
+ ROM_LOAD( "lapisprocolorserver.bin", 0x000000, 0x008000, CRC(cd2a726b) SHA1(bd4ceb4b229c9ce3e8f5386d5132ff26de6067e1) )
+ROM_END
+
+const tiny_rom_entry *nubus_procolor8_device::device_rom_region() const
+{
+ return ROM_NAME(procolor8_nb);
+}
+
+nubus_procolor8_device::nubus_procolor8_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock) :
+ nubus_procolor816_device(mconfig, NUBUS_PROCOLOR8, tag, owner, clock)
+{
+ m_has_15bpp = false;
+}
+
+} // anonymous namespace
+
+DEFINE_DEVICE_TYPE_PRIVATE(PDS030_PROCOLOR816, device_nubus_card_interface, nubus_procolor816_device, "pd3_pc16", "Lapis ProColor Server 8*16")
+DEFINE_DEVICE_TYPE_PRIVATE(PDS030_PROCOLOR8, device_nubus_card_interface, pds30_procolor8_device, "pd3_pcs8", "Lapis ProColor Server 8 (PDS)")
+DEFINE_DEVICE_TYPE_PRIVATE(NUBUS_PROCOLOR8, device_nubus_card_interface, nubus_procolor8_device, "nb_pcs8", "Lapis ProColor Server 8")
diff --git a/src/devices/bus/nubus/pds30_procolor816.h b/src/devices/bus/nubus/pds30_procolor816.h
index dee825d4096..e8f6e0b712d 100644
--- a/src/devices/bus/nubus/pds30_procolor816.h
+++ b/src/devices/bus/nubus/pds30_procolor816.h
@@ -7,50 +7,9 @@
#include "nubus.h"
-//**************************************************************************
-// TYPE DEFINITIONS
-//**************************************************************************
-
-// ======================> nubus_procolor816_device
-
-class nubus_procolor816_device :
- public device_t,
- public device_video_interface,
- public device_nubus_card_interface
-{
-public:
- // construction/destruction
- nubus_procolor816_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
-
-protected:
- nubus_procolor816_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_timer(emu_timer &timer, device_timer_id id, int param, void *ptr) override;
-
- // optional information overrides
- virtual void device_add_mconfig(machine_config &config) override;
- virtual const tiny_rom_entry *device_rom_region() const override;
-
-private:
- DECLARE_READ32_MEMBER(procolor816_r);
- DECLARE_WRITE32_MEMBER(procolor816_w);
- DECLARE_READ32_MEMBER(vram_r);
- DECLARE_WRITE32_MEMBER(vram_w);
-
- uint32_t screen_update(screen_device &screen, bitmap_rgb32 &bitmap, const rectangle &cliprect);
-
- std::vector<uint8_t> m_vram;
- uint32_t *m_vram32;
- 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(PDS030_PROCOLOR816, nubus_procolor816_device)
+DECLARE_DEVICE_TYPE(PDS030_PROCOLOR816, device_nubus_card_interface)
+DECLARE_DEVICE_TYPE(PDS030_PROCOLOR8, device_nubus_card_interface)
+DECLARE_DEVICE_TYPE(NUBUS_PROCOLOR8, device_nubus_card_interface)
#endif // MAME_BUS_NUBUS_PDS30_PROCOLOR816_H
diff --git a/src/devices/bus/nubus/pds30_sigmalview.cpp b/src/devices/bus/nubus/pds30_sigmalview.cpp
index 51f27a03713..887a2c7e678 100644
--- a/src/devices/bus/nubus/pds30_sigmalview.cpp
+++ b/src/devices/bus/nubus/pds30_sigmalview.cpp
@@ -4,109 +4,111 @@
Sigma Designs L-View card
-***************************************************************************/
+ TODO: This is clearly related closely to the NuBus laserview.cpp card,
+ but there are differences. (The protection latch seems reversed, for
+ starters. Figure it out and merge this into that!)
+
+ ***************************************************************************/
#include "emu.h"
#include "pds30_sigmalview.h"
#include "screen.h"
-#define LVIEW_SCREEN_NAME "lview_screen"
-#define LVIEW_ROM_REGION "lview_rom"
+#include <algorithm>
-#define VRAM_SIZE (0x80000) // 512K?
+namespace {
+static constexpr u32 VRAM_SIZE = 0x80000;
-ROM_START( lview )
- ROM_REGION(0x4000, LVIEW_ROM_REGION, 0)
- ROM_LOAD( "lv_asi_4_00.bin", 0x000000, 0x004000, CRC(b806f875) SHA1(1e58593b1a8720193d1651b0d8a0d43e4e47563d) )
-ROM_END
+class nubus_lview_device :
+ public device_t,
+ public device_video_interface,
+ public device_nubus_card_interface
+{
+public:
+ // construction/destruction
+ nubus_lview_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock);
+
+protected:
+ // device-level overrides
+ virtual void device_start() override ATTR_COLD;
+ virtual void device_reset() override ATTR_COLD;
-//**************************************************************************
-// GLOBAL VARIABLES
-//**************************************************************************
+ // optional information overrides
+ virtual void device_add_mconfig(machine_config &config) override ATTR_COLD;
+ virtual const tiny_rom_entry *device_rom_region() const override ATTR_COLD;
-DEFINE_DEVICE_TYPE(PDS030_LVIEW, nubus_lview_device, "pd3_lviw", "Sigma Designs L-View")
+ TIMER_CALLBACK_MEMBER(vbl_tick);
+private:
+ u8 lview_r(offs_t offset);
+ void lview_w(offs_t offset, u8 data);
+ u32 vram_r(offs_t offset, u32 mem_mask = ~0);
+ void vram_w(offs_t offset, u32 data, u32 mem_mask = ~0);
-//-------------------------------------------------
-// device_add_mconfig - add device configuration
-//-------------------------------------------------
+ void card_map(address_map &map);
+
+ u32 screen_update(screen_device &screen, bitmap_rgb32 &bitmap, const rectangle &cliprect);
+
+ required_device<screen_device> m_screen;
+ std::vector<u32> m_vram;
+ u32 m_vbl_disable;
+ u32 m_palette[256];
+ emu_timer *m_timer;
+ int m_protstate;
+};
+
+ROM_START( lview )
+ ROM_REGION(0x4000, "declrom", 0)
+ ROM_LOAD( "lv_asi_4_00.bin", 0x000000, 0x004000, CRC(b806f875) SHA1(1e58593b1a8720193d1651b0d8a0d43e4e47563d) )
+ROM_END
void nubus_lview_device::device_add_mconfig(machine_config &config)
{
- screen_device &screen(SCREEN(config, LVIEW_SCREEN_NAME, SCREEN_TYPE_RASTER));
- screen.set_screen_update(FUNC(nubus_lview_device::screen_update));
- screen.set_size(832, 600);
- screen.set_refresh_hz(70);
- screen.set_visarea(0, 832-1, 0, 600-1);
+ SCREEN(config, m_screen, SCREEN_TYPE_RASTER);
+ m_screen->set_screen_update(FUNC(nubus_lview_device::screen_update));
+ m_screen->set_size(832, 600);
+ m_screen->set_refresh_hz(70);
+ m_screen->set_visarea(0, 832-1, 0, 600-1);
}
-//-------------------------------------------------
-// rom_region - device-specific ROM region
-//-------------------------------------------------
-
const tiny_rom_entry *nubus_lview_device::device_rom_region() const
{
return ROM_NAME( lview );
}
-//**************************************************************************
-// LIVE DEVICE
-//**************************************************************************
-
-//-------------------------------------------------
-// nubus_lview_device - constructor
-//-------------------------------------------------
-
-nubus_lview_device::nubus_lview_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) :
- nubus_lview_device(mconfig, PDS030_LVIEW, tag, owner, clock)
-{
- (void)m_toggle;
-}
-
-nubus_lview_device::nubus_lview_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_lview_device::nubus_lview_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock) :
+ device_t(mconfig, PDS030_LVIEW, tag, owner, clock),
device_video_interface(mconfig, *this),
device_nubus_card_interface(mconfig, *this),
- m_vram32(nullptr), m_vbl_disable(0), m_toggle(0), m_timer(nullptr), m_protstate(0)
+ m_screen(*this, "screen"),
+ m_vbl_disable(0), m_timer(nullptr), m_protstate(0)
{
- set_screen(*this, LVIEW_SCREEN_NAME);
+ set_screen(*this, "screen");
}
-//-------------------------------------------------
-// device_start - device-specific startup
-//-------------------------------------------------
+void nubus_lview_device::card_map(address_map &map)
+{
+ map(0x0000'0000, 0x0007'ffff).rw(FUNC(nubus_lview_device::vram_r), FUNC(nubus_lview_device::vram_w)).mirror(0x00f0'0000);
+ map(0x000b'0000, 0x000b'ffff).rw(FUNC(nubus_lview_device::lview_r), FUNC(nubus_lview_device::lview_w)).mirror(0x00f0'0000);
+}
void nubus_lview_device::device_start()
{
- uint32_t slotspace;
-
- install_declaration_rom(this, LVIEW_ROM_REGION);
+ install_declaration_rom("declrom");
+ m_vram.resize(VRAM_SIZE / sizeof(u32));
- slotspace = get_slotspace();
+ nubus().install_map(*this, &nubus_lview_device::card_map);
-// printf("[lview %p] slotspace = %x\n", this, slotspace);
-
- m_vram.resize(VRAM_SIZE);
- m_vram32 = (uint32_t *)&m_vram[0];
-
- nubus().install_device(slotspace, slotspace+VRAM_SIZE-1, read32_delegate(FUNC(nubus_lview_device::vram_r), this), write32_delegate(FUNC(nubus_lview_device::vram_w), this));
- nubus().install_device(slotspace+0x900000, slotspace+VRAM_SIZE-1+0x900000, read32_delegate(FUNC(nubus_lview_device::vram_r), this), write32_delegate(FUNC(nubus_lview_device::vram_w), this));
- nubus().install_device(slotspace+0xb0000, slotspace+0xbffff, read32_delegate(FUNC(nubus_lview_device::lview_r), this), write32_delegate(FUNC(nubus_lview_device::lview_w), this));
-
- m_timer = timer_alloc(0, nullptr);
+ m_timer = timer_alloc(FUNC(nubus_lview_device::vbl_tick), this);
m_timer->adjust(screen().time_until_pos(599, 0), 0);
}
-//-------------------------------------------------
-// device_reset - device-specific reset
-//-------------------------------------------------
-
void nubus_lview_device::device_reset()
{
m_vbl_disable = 1;
m_protstate = 0;
- memset(&m_vram[0], 0, VRAM_SIZE);
+ std::fill(m_vram.begin(), m_vram.end(), 0);
memset(m_palette, 0, sizeof(m_palette));
m_palette[0] = rgb_t(255, 255, 255);
@@ -114,7 +116,7 @@ void nubus_lview_device::device_reset()
}
-void nubus_lview_device::device_timer(emu_timer &timer, device_timer_id tid, int param, void *ptr)
+TIMER_CALLBACK_MEMBER(nubus_lview_device::vbl_tick)
{
if (!m_vbl_disable)
{
@@ -124,26 +126,16 @@ void nubus_lview_device::device_timer(emu_timer &timer, device_timer_id tid, int
m_timer->adjust(screen().time_until_pos(599, 0), 0);
}
-/***************************************************************************
-
- CB264 section
-
-***************************************************************************/
-
-uint32_t nubus_lview_device::screen_update(screen_device &screen, bitmap_rgb32 &bitmap, const rectangle &cliprect)
+u32 nubus_lview_device::screen_update(screen_device &screen, bitmap_rgb32 &bitmap, const rectangle &cliprect)
{
- uint32_t *scanline;
- int x, y;
- uint8_t pixels, *vram;
-
- vram = &m_vram[0x20];
+ auto const vram8 = util::big_endian_cast<u8 const>(&m_vram[0]) + 0x20;
- for (y = 0; y < 600; y++)
+ for (int y = 0; y < 600; y++)
{
- scanline = &bitmap.pix32(y);
- for (x = 0; x < 832/8; x++)
+ u32 *scanline = &bitmap.pix(y);
+ for (int x = 0; x < 832/8; x++)
{
- pixels = vram[(y * (832/8)) + (BYTE4_XOR_BE(x))];
+ u8 const pixels = vram8[(y * (832/8)) + x];
*scanline++ = m_palette[(pixels&0x80)];
*scanline++ = m_palette[((pixels<<1)&0x80)];
@@ -159,50 +151,57 @@ uint32_t nubus_lview_device::screen_update(screen_device &screen, bitmap_rgb32 &
return 0;
}
-READ32_MEMBER( nubus_lview_device::lview_r )
+u8 nubus_lview_device::lview_r(offs_t offset)
{
- uint32_t rv = 0;
+ u8 rv = 0;
-// printf("%s prot_r: @ %x, mask %08x [state %d]\n", machine().describe_context().c_str(), offset, mem_mask, m_protstate);
+ if (offset == 0xff04)
+ {
+ return m_screen->vblank();
+ }
- if ((m_protstate == 1) || (m_protstate == 10) || (machine().device<cpu_device>("maincpu")->pc() == 0x5aac))
+ if ((m_protstate == 1) || (m_protstate == 10) || (m_protstate == 17) || (m_protstate == 20) || (m_protstate == 22))
{
- rv = 0x02020202;
+ rv = 0x02;
}
if (m_protstate == 8)
{
- rv = 0x01010101;
+ rv = 0x01;
}
m_protstate++;
return rv;
}
-WRITE32_MEMBER( nubus_lview_device::lview_w )
+void nubus_lview_device::lview_w(offs_t offset, u8 data)
{
-// if (offset != 0x7a && offset != 0x3ffb) logerror("prot_w: %08x @ %x, mask %08x %s\n", data, offset, mem_mask, machine().describe_context());
-
- if (offset == 0x7a)
+ switch (offset)
{
- if (data == 1)
- {
- m_vbl_disable = 0;
- lower_slot_irq();
- }
- else
- {
- m_vbl_disable = 1;
- }
+ case 0xffef:
+ if (data == 4)
+ {
+ m_vbl_disable = 0;
+ }
+ else
+ {
+ lower_slot_irq();
+ }
+ break;
+ }
+
}
-}
-WRITE32_MEMBER( nubus_lview_device::vram_w )
+void nubus_lview_device::vram_w(offs_t offset, u32 data, u32 mem_mask)
{
- COMBINE_DATA(&m_vram32[offset]);
+ COMBINE_DATA(&m_vram[offset]);
}
-READ32_MEMBER( nubus_lview_device::vram_r )
+u32 nubus_lview_device::vram_r(offs_t offset, u32 mem_mask)
{
- return m_vram32[offset];
+ return m_vram[offset];
}
+
+};
+
+DEFINE_DEVICE_TYPE_PRIVATE(PDS030_LVIEW, device_nubus_card_interface, nubus_lview_device, "pd3_lviw", "Sigma Designs L-View")
diff --git a/src/devices/bus/nubus/pds30_sigmalview.h b/src/devices/bus/nubus/pds30_sigmalview.h
index 66cfd175b42..decac949797 100644
--- a/src/devices/bus/nubus/pds30_sigmalview.h
+++ b/src/devices/bus/nubus/pds30_sigmalview.h
@@ -7,51 +7,6 @@
#include "nubus.h"
-//**************************************************************************
-// TYPE DEFINITIONS
-//**************************************************************************
-
-// ======================> nubus_lview_device
-
-class nubus_lview_device :
- public device_t,
- public device_video_interface,
- public device_nubus_card_interface
-{
-public:
- // construction/destruction
- nubus_lview_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
-
-protected:
- nubus_lview_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_timer(emu_timer &timer, device_timer_id id, int param, void *ptr) override;
-
- // optional information overrides
- virtual void device_add_mconfig(machine_config &config) override;
- virtual const tiny_rom_entry *device_rom_region() const override;
-
-private:
- DECLARE_READ32_MEMBER(lview_r);
- DECLARE_WRITE32_MEMBER(lview_w);
- DECLARE_READ32_MEMBER(vram_r);
- DECLARE_WRITE32_MEMBER(vram_w);
-
- uint32_t screen_update(screen_device &screen, bitmap_rgb32 &bitmap, const rectangle &cliprect);
-
- std::vector<uint8_t> m_vram;
- uint32_t *m_vram32;
- uint32_t m_vbl_disable, m_toggle;
- uint32_t m_palette[256];
- emu_timer *m_timer;
- int m_protstate;
-};
-
-
-// device type definition
-DECLARE_DEVICE_TYPE(PDS030_LVIEW, nubus_lview_device)
+DECLARE_DEVICE_TYPE(PDS030_LVIEW, device_nubus_card_interface)
#endif // MAME_BUS_NUBUS_PDS30_SIGMALVIEW_H
diff --git a/src/devices/bus/nubus/quadralink.cpp b/src/devices/bus/nubus/quadralink.cpp
index 9ba40a99748..4d4e0ca9cba 100644
--- a/src/devices/bus/nubus/quadralink.cpp
+++ b/src/devices/bus/nubus/quadralink.cpp
@@ -11,86 +11,87 @@
#include "bus/rs232/rs232.h"
#include "bus/rs232/terminal.h"
#include "bus/rs232/null_modem.h"
+#include "machine/z80scc.h"
#include "screen.h"
-static void isa_com(device_slot_interface &device)
+namespace {
+class nubus_quadralink_device : public device_t,
+ public device_nubus_card_interface
+{
+public:
+ // construction/destruction
+ nubus_quadralink_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock);
+
+protected:
+ nubus_quadralink_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, u32 clock);
+
+ required_device<z80scc_device> m_scc1, m_scc2;
+
+ // device-level overrides
+ virtual void device_start() override ATTR_COLD;
+
+ // optional information overrides
+ virtual void device_add_mconfig(machine_config &config) override ATTR_COLD;
+ virtual const tiny_rom_entry *device_rom_region() const override ATTR_COLD;
+
+private:
+ u32 dev_r(offs_t offset, u32 mem_mask = ~0);
+ void dev_w(offs_t offset, u32 data, u32 mem_mask = ~0);
+};
+
+static void ql_com(device_slot_interface &device)
{
device.option_add("terminal", SERIAL_TERMINAL);
device.option_add("null_modem", NULL_MODEM);
}
-#define QUADRALINK_ROM_REGION "qdlink_rom"
-
ROM_START( quadralink )
- ROM_REGION(0x4000, QUADRALINK_ROM_REGION, 0)
+ ROM_REGION(0x4000, "declrom", 0)
ROM_LOAD( "ql_2.2.bin", 0x000000, 0x004000, CRC(88c323b8) SHA1(d70bc32ad50ceb5cb75c6251293cacd65d8313aa) )
ROM_END
-//**************************************************************************
-// GLOBAL VARIABLES
-//**************************************************************************
-
-DEFINE_DEVICE_TYPE(NUBUS_QUADRALINK, nubus_quadralink_device, "nb_qdlink", "Applied Engineering Quadralink serial card")
-
-
-//-------------------------------------------------
-// device_add_mconfig - add device configuration
-//-------------------------------------------------
-
void nubus_quadralink_device::device_add_mconfig(machine_config &config)
{
- SCC8530N(config, m_scc1, 3.6864_MHz_XTAL);
+ SCC8530(config, m_scc1, 3.6864_MHz_XTAL);
m_scc1->out_txda_callback().set("serport0", FUNC(rs232_port_device::write_txd));
m_scc1->out_txdb_callback().set("serport1", FUNC(rs232_port_device::write_txd));
- SCC8530N(config, m_scc2, 3.6864_MHz_XTAL);
+ SCC8530(config, m_scc2, 3.6864_MHz_XTAL);
m_scc2->out_txda_callback().set("serport2", FUNC(rs232_port_device::write_txd));
m_scc2->out_txdb_callback().set("serport3", FUNC(rs232_port_device::write_txd));
- rs232_port_device &serport0(RS232_PORT(config, "serport0", isa_com, nullptr));
+ rs232_port_device &serport0(RS232_PORT(config, "serport0", ql_com, nullptr));
serport0.rxd_handler().set(m_scc1, FUNC(z80scc_device::rxa_w));
serport0.dcd_handler().set(m_scc1, FUNC(z80scc_device::dcda_w));
serport0.cts_handler().set(m_scc1, FUNC(z80scc_device::ctsa_w));
- rs232_port_device &serport1(RS232_PORT(config, "serport1", isa_com, nullptr));
+ rs232_port_device &serport1(RS232_PORT(config, "serport1", ql_com, nullptr));
serport1.rxd_handler().set(m_scc1, FUNC(z80scc_device::rxb_w));
serport1.dcd_handler().set(m_scc1, FUNC(z80scc_device::dcdb_w));
serport1.cts_handler().set(m_scc1, FUNC(z80scc_device::ctsb_w));
- rs232_port_device &serport2(RS232_PORT(config, "serport2", isa_com, nullptr));
+ rs232_port_device &serport2(RS232_PORT(config, "serport2", ql_com, nullptr));
serport2.rxd_handler().set(m_scc2, FUNC(z80scc_device::rxa_w));
serport2.dcd_handler().set(m_scc2, FUNC(z80scc_device::dcda_w));
serport2.cts_handler().set(m_scc2, FUNC(z80scc_device::ctsa_w));
- rs232_port_device &serport3(RS232_PORT(config, "serport3", isa_com, nullptr));
+ rs232_port_device &serport3(RS232_PORT(config, "serport3", ql_com, nullptr));
serport3.rxd_handler().set(m_scc2, FUNC(z80scc_device::rxb_w));
serport3.dcd_handler().set(m_scc2, FUNC(z80scc_device::dcdb_w));
serport3.cts_handler().set(m_scc2, FUNC(z80scc_device::ctsb_w));
}
-//-------------------------------------------------
-// rom_region - device-specific ROM region
-//-------------------------------------------------
-
const tiny_rom_entry *nubus_quadralink_device::device_rom_region() const
{
return ROM_NAME( quadralink );
}
-//**************************************************************************
-// LIVE DEVICE
-//**************************************************************************
-
-//-------------------------------------------------
-// nubus_quadralink_device - constructor
-//-------------------------------------------------
-
-nubus_quadralink_device::nubus_quadralink_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) :
+nubus_quadralink_device::nubus_quadralink_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock) :
nubus_quadralink_device(mconfig, NUBUS_QUADRALINK, tag, owner, clock)
{
}
-nubus_quadralink_device::nubus_quadralink_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock) :
+nubus_quadralink_device::nubus_quadralink_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_scc1(*this, "scc1"),
@@ -98,30 +99,18 @@ nubus_quadralink_device::nubus_quadralink_device(const machine_config &mconfig,
{
}
-//-------------------------------------------------
-// device_start - device-specific startup
-//-------------------------------------------------
-
void nubus_quadralink_device::device_start()
{
- uint32_t slotspace;
+ u32 slotspace;
- install_declaration_rom(this, QUADRALINK_ROM_REGION);
+ install_declaration_rom("declrom");
slotspace = get_slotspace();
- nubus().install_device(slotspace, slotspace+0xefffff, read32_delegate(FUNC(nubus_quadralink_device::dev_r), this), write32_delegate(FUNC(nubus_quadralink_device::dev_w), this));
+ nubus().install_device(slotspace, slotspace+0xefffff, read32s_delegate(*this, FUNC(nubus_quadralink_device::dev_r)), write32s_delegate(*this, FUNC(nubus_quadralink_device::dev_w)));
}
-//-------------------------------------------------
-// device_reset - device-specific reset
-//-------------------------------------------------
-
-void nubus_quadralink_device::device_reset()
-{
-}
-
-WRITE32_MEMBER( nubus_quadralink_device::dev_w )
+void nubus_quadralink_device::dev_w(offs_t offset, u32 data, u32 mem_mask)
{
//printf("write %x to QL space @ %x, mask %08x\n", data, offset, mem_mask);
switch (offset)
@@ -160,7 +149,7 @@ WRITE32_MEMBER( nubus_quadralink_device::dev_w )
}
}
-READ32_MEMBER( nubus_quadralink_device::dev_r )
+u32 nubus_quadralink_device::dev_r(offs_t offset, u32 mem_mask)
{
//printf("read QL space @ %x, mask %08x\n", offset, mem_mask);
switch (offset)
@@ -191,3 +180,7 @@ READ32_MEMBER( nubus_quadralink_device::dev_r )
}
return 0xffffffff;
}
+
+} // anonymous namespace
+
+DEFINE_DEVICE_TYPE_PRIVATE(NUBUS_QUADRALINK, device_nubus_card_interface, nubus_quadralink_device, "nb_qdlink", "Applied Engineering Quadralink serial card")
diff --git a/src/devices/bus/nubus/quadralink.h b/src/devices/bus/nubus/quadralink.h
index 28f3eadbf47..7f392eacfca 100644
--- a/src/devices/bus/nubus/quadralink.h
+++ b/src/devices/bus/nubus/quadralink.h
@@ -4,43 +4,9 @@
#define MAME_BUS_NUBUS_QUADRALINK_H
#pragma once
-
#include "nubus.h"
-#include "machine/z80scc.h"
-
-//**************************************************************************
-// TYPE DEFINITIONS
-//**************************************************************************
-
-// ======================> nubus_quadralink_device
-
-class nubus_quadralink_device :
- public device_t,
- public device_nubus_card_interface
-{
-public:
- // construction/destruction
- nubus_quadralink_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
-
-protected:
- nubus_quadralink_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock);
-
- required_device<z80scc_device> m_scc1, m_scc2;
-
- // 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:
- DECLARE_READ32_MEMBER(dev_r);
- DECLARE_WRITE32_MEMBER(dev_w);
-};
// device type definition
-DECLARE_DEVICE_TYPE(NUBUS_QUADRALINK, nubus_quadralink_device)
+DECLARE_DEVICE_TYPE(NUBUS_QUADRALINK, device_nubus_card_interface)
#endif // MAME_BUS_NUBUS_QUADRALINK_H
diff --git a/src/devices/bus/nubus/supermac.cpp b/src/devices/bus/nubus/supermac.cpp
new file mode 100644
index 00000000000..67b26485aea
--- /dev/null
+++ b/src/devices/bus/nubus/supermac.cpp
@@ -0,0 +1,167 @@
+// license:BSD-3-Clause
+// copyright-holders:Vas Crabb
+
+#include "emu.h"
+#include "supermac.h"
+
+#include "screen.h"
+
+#include <utility>
+
+#define LOG_CRTC (1U << 1)
+#define LOG_SHIFTREG (1U << 2)
+
+//#define VERBOSE (LOG_CRTC | LOG_SHIFTREG)
+#define LOG_OUTPUT_FUNC [&device] (auto &&... args) { device.logerror(std::forward<decltype(args)>(args)...); }
+#include "logmacro.h"
+
+#define LOGCRTC(...) LOGMASKED(LOG_CRTC, __VA_ARGS__)
+#define LOGSHIFTREG(...) LOGMASKED(LOG_SHIFTREG, __VA_ARGS__)
+
+
+namespace {
+
+void ctrc_reg_w(u16 &param, u32 offset, u32 data) noexcept
+{
+ param &= 0xff << (BIT(offset, 1) ? 0 : 8);
+ param |= (~data & 0xff) << (BIT(offset, 1) ? 8 : 0);
+}
+
+} // anonymous namespace
+
+
+void supermac_spec_crtc::register_save(device_t &device)
+{
+ device.save_item(NAME(m_hsync));
+ device.save_item(NAME(m_hstart));
+ device.save_item(NAME(m_hend));
+ device.save_item(NAME(m_htotal));
+ device.save_item(NAME(m_vsync));
+ device.save_item(NAME(m_vstart));
+ device.save_item(NAME(m_vend));
+ device.save_item(NAME(m_vtotal));
+}
+
+
+void supermac_spec_crtc::reset() noexcept
+{
+ // invalid - let the firmware initialise it before changing screen parameters
+ m_hsync = 0;
+ m_hstart = 0;
+ m_hend = 0;
+ m_htotal = 0;
+ m_vsync = 0;
+ m_vstart = 0;
+ m_vend = 0;
+ m_vtotal = 0;
+}
+
+
+void supermac_spec_crtc::write(device_t &device, offs_t offset, u32 data)
+{
+ switch (offset)
+ {
+ case 0x04:
+ case 0x06:
+ ctrc_reg_w(m_hsync, offset, data);
+ LOGCRTC("%s: CRTC H sync = %u\n", device.machine().describe_context(), m_hsync);
+ break;
+
+ case 0x08:
+ case 0x0a:
+ ctrc_reg_w(m_hstart, offset, data);
+ LOGCRTC("%s: CRTC H start = %u\n", device.machine().describe_context(), m_hstart);
+ break;
+
+ case 0x0c:
+ case 0x0e:
+ ctrc_reg_w(m_hend, offset, data);
+ LOGCRTC("%s: CRTC H end = %u\n", device.machine().describe_context(), m_hend);
+ break;
+
+ case 0x10:
+ case 0x12:
+ ctrc_reg_w(m_htotal, offset, data);
+ LOGCRTC("%s: CRTC H total = %u\n", device.machine().describe_context(), m_htotal);
+ break;
+
+ case 0x18:
+ case 0x1a:
+ ctrc_reg_w(m_vsync, offset, data);
+ LOGCRTC("%s: CRTC V sync = %u\n", device.machine().describe_context(), m_vsync);
+ break;
+
+ case 0x1c:
+ case 0x1e:
+ ctrc_reg_w(m_vstart, offset, data);
+ LOGCRTC("%s: CRTC V start = %u\n", device.machine().describe_context(), m_vstart);
+ break;
+
+ case 0x24:
+ case 0x26:
+ ctrc_reg_w(m_vend, offset, data);
+ LOGCRTC("%s: CRTC V end = %u\n", device.machine().describe_context(), m_vend);
+ break;
+
+ case 0x28:
+ case 0x2a:
+ ctrc_reg_w(m_vtotal, offset, data);
+ LOGCRTC("%s: CRTC V total = %u\n", device.machine().describe_context(), m_vtotal);
+ break;
+
+ default:
+ device.logerror("%s: unknown CRTC register %02x = %08x\n", device.machine().describe_context(), offset, data);
+ }
+}
+
+
+bool supermac_spec_crtc::valid(device_t &device) const
+{
+ if ((m_hsync < m_hstart) && (m_hstart < m_hend) && (m_hend < m_htotal) && (m_vsync < m_vstart) && (m_vstart < m_vend) && (m_vend < m_vtotal))
+ {
+ return true;
+ }
+ else
+ {
+ LOGCRTC("invalid CRTC parameters (%u %u %u %u) (%u %u %u %u)\n",
+ m_hsync, m_hstart, m_hend, m_htotal,
+ m_vsync, m_vstart, m_vend, m_vtotal);
+ return false;
+ }
+}
+
+
+void supermac_spec_shift_reg::register_save(device_t &device)
+{
+ device.save_item(NAME(m_shift_data));
+ device.save_item(NAME(m_shift_count));
+}
+
+
+void supermac_spec_shift_reg::reset() noexcept
+{
+ m_shift_data = 0;
+ m_shift_count = 0;
+}
+
+
+void supermac_spec_shift_reg::write_control(device_t &device, u32 data)
+{
+ // Sequence is:
+ // * 1 -> control
+ // * 0 -> data
+ // * 0 -> control
+ // * two select bits to data
+ // * eight data bits to data, least significant bit first
+ if (!BIT(~data, 0))
+ m_shift_count = 0;
+}
+
+
+void supermac_spec_shift_reg::write_data(device_t &device, u32 data)
+{
+ m_shift_data = (m_shift_data >> 1) | (BIT(~data, 0) << 15);
+ ++m_shift_count;
+ if (ready())
+ LOGSHIFTREG("%s: shift register parameter %d = %02x\n", device.machine().describe_context(), select(), value());
+}
diff --git a/src/devices/bus/nubus/supermac.h b/src/devices/bus/nubus/supermac.h
new file mode 100644
index 00000000000..25b57b09683
--- /dev/null
+++ b/src/devices/bus/nubus/supermac.h
@@ -0,0 +1,70 @@
+// license:BSD-3-Clause
+// copyright-holders:Vas Crabb
+#ifndef MAME_BUS_NUBUS_SUPERMAC_H
+#define MAME_BUS_NUBUS_SUPERMAC_H
+
+#pragma once
+
+
+class supermac_spec_crtc
+{
+public:
+ void register_save(device_t &device);
+
+ void reset() noexcept;
+
+ void write(device_t &device, offs_t offset, u32 data);
+
+ bool valid(device_t &device) const;
+
+ u32 h_sync(u32 scale) const noexcept
+ { return (m_hsync + 1) * scale; }
+ u32 h_total(u32 scale) const noexcept
+ { return (m_htotal + 1) * scale; }
+ u32 h_active(u32 scale) const noexcept
+ { return (m_hend - m_hstart) * scale; }
+ u32 h_start(u32 scale) const noexcept
+ { return (m_hstart + 1) * scale; }
+ u32 h_end(u32 scale) const noexcept
+ { return (m_hend + 1) * scale; }
+
+ u16 v_sync() const noexcept
+ { return m_vsync + 1; }
+ u16 v_total() const noexcept
+ { return m_vtotal + 1; }
+ u32 v_active() const noexcept
+ { return (m_vend - m_vstart); }
+ u16 v_start() const noexcept
+ { return m_vstart + 1; }
+ u16 v_end() const noexcept
+ { return m_vend + 1; }
+
+ attoseconds_t frame_time(u32 scale, XTAL const &osc) const noexcept
+ { return attotime::from_ticks((m_htotal + 1) * (m_vtotal + 1) * scale, osc).attoseconds(); }
+
+private:
+ u16 m_hsync, m_hstart, m_hend, m_htotal;
+ u16 m_vsync, m_vstart, m_vend, m_vtotal;
+};
+
+
+class supermac_spec_shift_reg
+{
+public:
+ void register_save(device_t &device);
+
+ void reset() noexcept;
+
+ void write_control(device_t &device, u32 data);
+ void write_data(device_t &device, u32 data);
+
+ bool ready() const noexcept { return m_shift_count == 10; }
+ u8 select() const noexcept { return (m_shift_data >> 6) & 0x03; }
+ u8 value() const noexcept { return (m_shift_data >> 8) & 0xff; }
+
+private:
+ u16 m_shift_data;
+ u8 m_shift_count;
+};
+
+#endif // MAME_BUS_NUBUS_SUPERMAC_H
diff --git a/src/devices/bus/nubus/thunder4gx.cpp b/src/devices/bus/nubus/thunder4gx.cpp
new file mode 100644
index 00000000000..f2d38a8bd63
--- /dev/null
+++ b/src/devices/bus/nubus/thunder4gx.cpp
@@ -0,0 +1,905 @@
+// 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.
+
+ DAC is an Analog Devices ADV7152.
+
+ 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 ATTR_COLD;
+ virtual void device_reset() override ATTR_COLD;
+
+ // optional information overrides
+ virtual void device_add_mconfig(machine_config &config) override ATTR_COLD;
+ virtual const tiny_rom_entry *device_rom_region() const override ATTR_COLD;
+ virtual ioport_constructor device_input_ports() const override ATTR_COLD;
+
+ u32 registers_r(offs_t offset, u32 mem_mask);
+ void registers_w(offs_t offset, u32 data, u32 mem_mask);
+ u32 crtc_r(offs_t offset, u32 mem_mask);
+ void crtc_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);
+
+ void card_map(address_map &map);
+
+ 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::card_map(address_map &map)
+{
+ map(0xc0'0000, 0xc0'000f).w(FUNC(nubus_thunder4gx_device::clockgen_w));
+ map(0xc4'0000, 0xc7'ffff).rw(FUNC(nubus_thunder4gx_device::registers_r), FUNC(nubus_thunder4gx_device::registers_w));
+ map(0xc8'0000, 0xc8'ffff).rw(FUNC(nubus_thunder4gx_device::crtc_r), FUNC(nubus_thunder4gx_device::crtc_w));
+ map(0xcc'0000, 0xcc'1fff).rw(FUNC(nubus_thunder4gx_device::accel_r), FUNC(nubus_thunder4gx_device::accel_w));
+ map(0xd0'0000, 0xd0'00ff).rw(FUNC(nubus_thunder4gx_device::ramdac_r), FUNC(nubus_thunder4gx_device::ramdac_w));
+}
+
+void nubus_thunder4gx_device::device_start()
+{
+ const u32 slotspace = get_slotspace();
+ const u32 superspace = get_super_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);
+
+ nubus().install_map(*this, &nubus_thunder4gx_device::card_map);
+
+ install_bank(slotspace, slotspace+VRAM_SIZE-1, &m_vram[0]);
+ install_bank(superspace, superspace + VRAM_SIZE - 1, &m_vram[0]);
+}
+
+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;
+
+ 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::crtc_r(offs_t offset, u32 mem_mask)
+{
+ switch (offset)
+ {
+ case 0x00: // mode
+ return m_mode;
+
+ case 0x02: // 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;
+ }
+
+ case 0x05:
+ case 0x06:
+ case 0x07:
+ case 0x08:
+ case 0x09:
+ case 0x0a:
+ case 0x0b:
+ case 0x0c:
+ case 0x0d:
+ case 0x0e:
+ case 0x0f:
+ return m_crtc[offset - 5];
+
+ default:
+ LOGMASKED(LOG_GENERAL, "Read @ C8xxxx %08x mask %08x\n", offset, mem_mask);
+ break;
+ }
+ return 0;
+}
+
+void nubus_thunder4gx_device::crtc_w(offs_t offset, u32 data, u32 mem_mask)
+{
+ data &= mem_mask;
+ switch (offset)
+ {
+ case 0x00:
+ m_mode = data & 0xf;
+ LOGMASKED(LOG_GENERAL, "%x to mode\n", data);
+ break;
+
+ case 0x02:
+ LOGMASKED(LOG_MONSENSE, "%x to monitor drive\n", data);
+ m_monitor_id = data;
+ break;
+
+ case 0x05:
+ case 0x06:
+ case 0x07:
+ case 0x08:
+ case 0x09:
+ case 0x0a:
+ case 0x0b:
+ case 0x0c:
+ case 0x0d:
+ case 0x0e:
+ case 0x0f:
+ m_crtc[offset - 5] = 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 @ C8xxxx: %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());
+ }
+}
+
+class nubus_thunder4gx16_device : public nubus_thunder4gx_device
+{
+public:
+ nubus_thunder4gx16_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock) :
+ nubus_thunder4gx_device(mconfig, NUBUS_THUNDERIVGX16, tag, owner, clock)
+ {
+ }
+
+ virtual const tiny_rom_entry *device_rom_region() const override;
+};
+
+ROM_START( thundergx1600 )
+ ROM_REGION(0x10000, "declrom", 0)
+ ROM_LOAD( "radius thunder iv gx1600 0010-415-0003.bin", 0x000000, 0x010000, CRC(b0c036c1) SHA1(ea008fa93f56807f48d9535f70efebdf3def2609) )
+ROM_END
+
+const tiny_rom_entry *nubus_thunder4gx16_device::device_rom_region() const
+{
+ return ROM_NAME( thundergx1600 );
+}
+
+} // anonymous namespace
+
+DEFINE_DEVICE_TYPE_PRIVATE(NUBUS_THUNDERIVGX, device_nubus_card_interface, nubus_thunder4gx_device, "nb_thungx", "Radius Thunder IV GX video card")
+DEFINE_DEVICE_TYPE_PRIVATE(NUBUS_THUNDERIVGX16, device_nubus_card_interface, nubus_thunder4gx16_device, "nb_thungx16", "Radius Thunder IV GX 1600 video card")
diff --git a/src/devices/bus/nubus/thunder4gx.h b/src/devices/bus/nubus/thunder4gx.h
new file mode 100644
index 00000000000..c261cda52e9
--- /dev/null
+++ b/src/devices/bus/nubus/thunder4gx.h
@@ -0,0 +1,13 @@
+// license:BSD-3-Clause
+// copyright-holders:R. Belmont
+#ifndef MAME_BUS_NUBUS_THUNDER4GX_H
+#define MAME_BUS_NUBUS_THUNDER4GX_H
+
+#pragma once
+
+#include "nubus.h"
+
+DECLARE_DEVICE_TYPE(NUBUS_THUNDERIVGX, device_nubus_card_interface)
+DECLARE_DEVICE_TYPE(NUBUS_THUNDERIVGX16, device_nubus_card_interface)
+
+#endif // MAME_BUS_NUBUS_THUNDER4GX_H
diff --git a/src/devices/bus/odyssey2/4in1.cpp b/src/devices/bus/odyssey2/4in1.cpp
new file mode 100644
index 00000000000..5adb1ecc403
--- /dev/null
+++ b/src/devices/bus/odyssey2/4in1.cpp
@@ -0,0 +1,79 @@
+// license:BSD-3-Clause
+// copyright-holders:hap
+/******************************************************************************
+
+Videopac 31/40 cartridge emulation
+
+4KB ROM (program ROM is fixed, data ROM is 'bankswitched' via P11)
+
+Used in:
+- #31: Musician
+- #40: 4 in 1 Row
+
+******************************************************************************/
+
+#include "emu.h"
+#include "4in1.h"
+
+namespace {
+
+//-------------------------------------------------
+// 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 ATTR_COLD;
+
+ 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)
+{ }
+
+void o2_4in1_device::device_start()
+{
+ save_item(NAME(m_control));
+ save_item(NAME(m_bank));
+}
+
+void o2_4in1_device::cart_init()
+{
+ if (m_rom_size != 0x1000)
+ fatalerror("o2_4in1_device: ROM size must be 4KB\n");
+}
+
+
+//-------------------------------------------------
+// mapper specific handlers
+//-------------------------------------------------
+
+u8 o2_4in1_device::io_read(offs_t offset)
+{
+ if (m_control & 2)
+ return m_rom[m_bank << 8 | 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
new file mode 100644
index 00000000000..ad5414345c3
--- /dev/null
+++ b/src/devices/bus/odyssey2/4in1.h
@@ -0,0 +1,18 @@
+// license:BSD-3-Clause
+// copyright-holders:hap
+/**********************************************************************
+
+ Videopac 31/40 cartridge emulation
+
+**********************************************************************/
+
+#ifndef MAME_BUS_ODYSSEY2_4IN1_H
+#define MAME_BUS_ODYSSEY2_4IN1_H
+
+#pragma once
+
+#include "slot.h"
+
+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 44890a394ce..ae8efb14ce8 100644
--- a/src/devices/bus/odyssey2/chess.cpp
+++ b/src/devices/bus/odyssey2/chess.cpp
@@ -1,43 +1,120 @@
// license:BSD-3-Clause
-// copyright-holders:Fabio Priuli
-/***********************************************************************************************************
+// copyright-holders:hap
+/******************************************************************************
+Videopac C7010 Chess Module emulation
- Videopac Chess Module emulation
+The chess engine is Wim Rens's Gambiet, evidently based on the 1980 version.
- TODO:
- - this code is just a stub... hence, almost everything is still to do!
-
- ***********************************************************************************************************/
+Hardware notes:
+- NSC800 (Z80-compatible) @ 4.43MHz
+- 8KB ROM, 2KB RAM
+******************************************************************************/
#include "emu.h"
#include "chess.h"
+#include "cpu/z80/nsc800.h"
+#include "machine/gen_latch.h"
+
+namespace {
//-------------------------------------------------
-// o2_chess_device - constructor
+// initialization
//-------------------------------------------------
-DEFINE_DEVICE_TYPE(O2_ROM_CHESS, o2_chess_device, "o2_chess", "Odyssey 2 Videopac Chess Module")
+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 ATTR_COLD;
+ virtual void device_add_mconfig(machine_config &config) override ATTR_COLD;
+
+ 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]; }
-o2_chess_device::o2_chess_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
- : o2_rom_device(mconfig, O2_ROM_CHESS, tag, owner, clock)
- , m_cpu(*this, "subcpu")
+ void chess_io(address_map &map) ATTR_COLD;
+ void chess_mem(address_map &map) ATTR_COLD;
+};
+
+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),
+ m_maincpu(*this, "maincpu"),
+ m_latch(*this, "latch%u", 0)
+{ }
+
+void o2_chess_device::device_start()
+{
+ save_item(NAME(m_control));
+}
+
+void o2_chess_device::cart_init()
{
+ if (m_rom_size != 0x800 || m_exrom_size != 0x2000)
+ fatalerror("o2_chess_device: Wrong ROM region size\n");
}
+//-------------------------------------------------
+// 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
+//-------------------------------------------------
+
void o2_chess_device::chess_mem(address_map &map)
{
- map(0x0000, 0x07ff).r(FUNC(o2_chess_device::read_rom04));
+ map(0x0000, 0x1fff).r(FUNC(o2_chess_device::internal_rom_r));
+ map(0xe000, 0xe7ff).mirror(0x1800).ram();
}
void o2_chess_device::chess_io(address_map &map)
{
- map.unmap_value_high();
map.global_mask(0xff);
+ map(0x00, 0x00).mirror(0xff).r(m_latch[1], FUNC(generic_latch_8_device::read)).w(m_latch[0], FUNC(generic_latch_8_device::write));
}
@@ -47,7 +124,16 @@ void o2_chess_device::chess_io(address_map &map)
void o2_chess_device::device_add_mconfig(machine_config &config)
{
- NSC800(config, m_cpu, XTAL(4'000'000));
- m_cpu->set_addrmap(AS_PROGRAM, &o2_chess_device::chess_mem);
- m_cpu->set_addrmap(AS_IO, &o2_chess_device::chess_io);
+ // basic machine hardware
+ NSC800(config, m_maincpu, 4.433619_MHz_XTAL);
+ m_maincpu->set_addrmap(AS_PROGRAM, &o2_chess_device::chess_mem);
+ m_maincpu->set_addrmap(AS_IO, &o2_chess_device::chess_io);
+
+ GENERIC_LATCH_8(config, m_latch[0]);
+ GENERIC_LATCH_8(config, m_latch[1]);
}
+
+} // anonymous namespace
+
+
+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 da8bee54b9d..4fddc07dc53 100644
--- a/src/devices/bus/odyssey2/chess.h
+++ b/src/devices/bus/odyssey2/chess.h
@@ -1,35 +1,18 @@
// license:BSD-3-Clause
-// copyright-holders:Fabio Priuli
+// copyright-holders:hap
+/**********************************************************************
+
+ Videopac C7010 Chess Module emulation
+
+**********************************************************************/
+
#ifndef MAME_BUS_ODYSSEY2_CHESS_H
#define MAME_BUS_ODYSSEY2_CHESS_H
#pragma once
#include "slot.h"
-#include "rom.h"
-#include "cpu/z80/z80.h"
-
-
-// ======================> o2_chess_device
-
-class o2_chess_device : public o2_rom_device
-{
-public:
- // construction/destruction
- o2_chess_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 rom_entry *device_rom_region() const;
-
-private:
- required_device<nsc800_device> m_cpu;
-
- void chess_io(address_map &map);
- void chess_mem(address_map &map);
-};
-// 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
new file mode 100644
index 00000000000..5b0457ebcb5
--- /dev/null
+++ b/src/devices/bus/odyssey2/homecomp.cpp
@@ -0,0 +1,253 @@
+// license:BSD-3-Clause
+// copyright-holders:hap
+/******************************************************************************
+
+Videopac+ C7420 Home Computer Module emulation
+
+This module only works on the Videopac+ G7400, although the cartridge can still
+be inserted into the Odyssey 2/G7000.
+
+Hardware notes:
+- Z80 @ 3.547MHz
+- 2*8KB ROM, 16KB RAM(2*TMS4416, 2 unpopulated locations)
+- optional data recorder
+
+The RAM can be expanded to 32KB by simply adding two more TMS4416. To enable it,
+enter command CLEAR 50,-2
+
+TODO:
+- lots of unacknowledged writes to latch 1, probably harmless
+- cassette data saved from MAME can be loaded fine, but other WAVs can't, even
+ when they are good quality, maybe a filter on the data input?
+
+******************************************************************************/
+
+#include "emu.h"
+#include "homecomp.h"
+
+#include "cpu/z80/z80.h"
+#include "imagedev/cassette.h"
+#include "machine/gen_latch.h"
+
+#include "speaker.h"
+
+namespace {
+
+//-------------------------------------------------
+// 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 ATTR_COLD;
+ virtual void device_reset() override ATTR_COLD;
+ virtual void device_add_mconfig(machine_config &config) override ATTR_COLD;
+ virtual ioport_constructor device_input_ports() const override ATTR_COLD;
+
+ 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) ATTR_COLD;
+ void homecomp_mem(address_map &map) ATTR_COLD;
+};
+
+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),
+ m_maincpu(*this, "maincpu"),
+ m_latch(*this, "latch%u", 0),
+ m_cass(*this, "cassette")
+{ }
+
+void o2_homecomp_device::device_start()
+{
+ save_item(NAME(m_control));
+ save_item(NAME(m_installed));
+
+ // allocate maximum RAM beforehand
+ m_ram = std::make_unique<u8[]>(0x8000);
+ save_pointer(NAME(m_ram), 0x8000);
+}
+
+void o2_homecomp_device::device_reset()
+{
+ if (!m_installed)
+ {
+ // install RAM
+ u32 ramsize = ioport("RAM")->read() ? 0x8000 : 0x4000;
+ m_maincpu->space(AS_PROGRAM).install_ram(0x8000, ramsize - 1 + 0x8000, m_ram.get());
+
+ m_installed = true;
+ }
+}
+
+void o2_homecomp_device::cart_init()
+{
+ if (m_rom_size != 0x800 || m_exrom_size != 0x4000)
+ fatalerror("o2_homecomp_device: Wrong ROM region size\n");
+}
+
+
+//-------------------------------------------------
+// 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);
+}
+
+
+//-------------------------------------------------
+// internal i/o
+//-------------------------------------------------
+
+u8 o2_homecomp_device::internal_io_r(offs_t offset)
+{
+ u8 data = 0;
+
+ // A7: input latch
+ if (~offset & 0x80)
+ data |= m_latch[1]->read();
+
+ // A6: other i/o
+ if (~offset & 0x40)
+ {
+ // d0: latch 0 status
+ data |= m_latch[0]->pending_r() ^ 1;
+
+ if (m_cass->is_playing() && m_cass->motor_on())
+ {
+ // d6: cass clock
+ // d7: cass data
+ double level = m_cass->input();
+ if (level > 0.04)
+ data |= 0xc0;
+ else if (level < -0.04)
+ data |= 0x80;
+ }
+ }
+
+ return data;
+}
+
+void o2_homecomp_device::internal_io_w(offs_t offset, u8 data)
+{
+ // A7: output latch
+ if (~offset & 0x80)
+ m_latch[0]->write(data);
+
+ // A6: other i/o
+ if (~offset & 0x40)
+ {
+ // d7: cass remote control (also with data)
+ m_cass->set_motor((data & 0x81) ? 1 : 0);
+
+ // d0: cass data
+ // d1: cass clock
+ double level = 0.0;
+ if (data & 1)
+ level = (data & 2) ? 0.8 : -0.8;
+ m_cass->output(level);
+ }
+}
+
+void o2_homecomp_device::homecomp_mem(address_map &map)
+{
+ map(0x0000, 0x3fff).r(FUNC(o2_homecomp_device::internal_rom_r));
+}
+
+void o2_homecomp_device::homecomp_io(address_map &map)
+{
+ map.global_mask(0xff);
+ map(0x00, 0xff).rw(FUNC(o2_homecomp_device::internal_io_r), FUNC(o2_homecomp_device::internal_io_w));
+}
+
+
+//-------------------------------------------------
+// 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
+//-------------------------------------------------
+
+void o2_homecomp_device::device_add_mconfig(machine_config &config)
+{
+ // basic machine hardware
+ Z80(config, m_maincpu, 3.547_MHz_XTAL);
+ m_maincpu->set_addrmap(AS_PROGRAM, &o2_homecomp_device::homecomp_mem);
+ m_maincpu->set_addrmap(AS_IO, &o2_homecomp_device::homecomp_io);
+
+ GENERIC_LATCH_8(config, m_latch[0]);
+ GENERIC_LATCH_8(config, m_latch[1]);
+
+ // cassette
+ CASSETTE(config, m_cass);
+ m_cass->set_default_state(CASSETTE_STOPPED | CASSETTE_SPEAKER_MUTED | CASSETTE_MOTOR_DISABLED);
+ SPEAKER(config, "cass_output").front_center(); // on data recorder
+ m_cass->add_route(ALL_OUTPUTS, "cass_output", 0.05);
+}
+
+} // anonymous namespace
+
+
+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
new file mode 100644
index 00000000000..0ae5d789898
--- /dev/null
+++ b/src/devices/bus/odyssey2/homecomp.h
@@ -0,0 +1,18 @@
+// license:BSD-3-Clause
+// copyright-holders:hap
+/**********************************************************************
+
+ Videopac+ C7420 Home Computer Module emulation
+
+**********************************************************************/
+
+#ifndef MAME_BUS_ODYSSEY2_HOMECOMP_H
+#define MAME_BUS_ODYSSEY2_HOMECOMP_H
+
+#pragma once
+
+#include "slot.h"
+
+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
new file mode 100644
index 00000000000..fa45748f6b5
--- /dev/null
+++ b/src/devices/bus/odyssey2/ktaa.cpp
@@ -0,0 +1,88 @@
+// license:BSD-3-Clause
+// copyright-holders:Wilbert Pol, Fabio Priuli, hap
+/******************************************************************************
+
+Homebrew KTAA(Kill the Attacking Aliens) cartridge emulation
+
+Bankswitched ROM with page size of 3KB.
+
+******************************************************************************/
+
+#include "emu.h"
+#include "ktaa.h"
+
+namespace {
+
+//-------------------------------------------------
+// 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 ATTR_COLD;
+
+ 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)
+{ }
+
+void o2_ktaa_device::device_start()
+{
+ save_item(NAME(m_bank));
+}
+
+void o2_ktaa_device::cart_init()
+{
+ bool err = false;
+
+ if (m_rom_size & (m_rom_size - 1))
+ {
+ // freely released binary file is 12KB
+ err = m_rom_size != 0xc00 && m_rom_size != 0xc00*2 && m_rom_size != 0xc00*4;
+ m_page_size = 0xc00;
+ }
+ else
+ {
+ // actual ROM is 16KB(27C128), first 1KB of each 4KB block is empty
+ err = m_rom_size < 0x1000;
+ m_page_size = 0x1000;
+ }
+
+ if (err)
+ fatalerror("o2_ktaa_device: ROM size must be multiple of 3KB or 4KB\n");
+
+ m_bank_mask = (m_rom_size / m_page_size) - 1;
+}
+
+
+//-------------------------------------------------
+// mapper specific handlers
+//-------------------------------------------------
+
+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
new file mode 100644
index 00000000000..89772bf9cd3
--- /dev/null
+++ b/src/devices/bus/odyssey2/ktaa.h
@@ -0,0 +1,18 @@
+// license:BSD-3-Clause
+// copyright-holders:Wilbert Pol, Fabio Priuli, hap
+/**********************************************************************
+
+ Homebrew KTAA cartridge emulation
+
+**********************************************************************/
+
+#ifndef MAME_BUS_ODYSSEY2_KTAA_H
+#define MAME_BUS_ODYSSEY2_KTAA_H
+
+#pragma once
+
+#include "slot.h"
+
+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
new file mode 100644
index 00000000000..37ad1d2c89c
--- /dev/null
+++ b/src/devices/bus/odyssey2/rally.cpp
@@ -0,0 +1,142 @@
+// license:BSD-3-Clause
+// copyright-holders:hap
+/******************************************************************************
+
+Videopac+ 55/58/59/60 cartridge emulation
+
+Bankswitched ROM via latch, either 16KB/2*8KB, or 4KB+8KB.
+
+Used in:
+- #55: Neutron Star
+- #58: Air Battle
+- #59: Helicopter Rescue
+- #60: Trans American Rally
+
+#55 and #58 also work on the G7000.
+
+It's used by the Videopac+ Service Test cartridge too, with 2 7segs added. The
+7segs are just for showing error codes, it will still work fine without them.
+
+******************************************************************************/
+
+#include "emu.h"
+#include "rally.h"
+
+namespace {
+
+//-------------------------------------------------
+// initialization
+//-------------------------------------------------
+
+// Rally / shared
+
+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:
+ o2_rally_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, u32 clock);
+
+ virtual void device_start() override ATTR_COLD;
+
+ 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;
+
+ u8 m_control = 0;
+ u8 m_bank = 0;
+};
+
+o2_rally_device::o2_rally_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, u32 clock) :
+ device_t(mconfig, type, tag, owner, clock),
+ device_o2_cart_interface(mconfig, *this)
+{ }
+
+o2_rally_device::o2_rally_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock) :
+ o2_rally_device(mconfig, O2_ROM_RALLY, tag, owner, clock)
+{ }
+
+void o2_rally_device::device_start()
+{
+ save_item(NAME(m_control));
+ save_item(NAME(m_bank));
+}
+
+void o2_rally_device::cart_init()
+{
+ if (m_rom_size & (m_rom_size - 1) || m_rom_size < 0x800)
+ fatalerror("o2_rally_device: ROM size must be 2^x\n");
+}
+
+
+// Service Test Cartridge
+
+class o2_testpl_device : public o2_rally_device
+{
+public:
+ o2_testpl_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock);
+
+protected:
+ virtual void device_start() override ATTR_COLD;
+
+ virtual void io_write(offs_t offset, u8 data) override;
+
+private:
+ output_finder<2> m_digit_out;
+};
+
+o2_testpl_device::o2_testpl_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock) :
+ o2_rally_device(mconfig, O2_ROM_TESTPL, tag, owner, clock),
+ m_digit_out(*this, "tc_digit%u", 0U)
+{ }
+
+void o2_testpl_device::device_start()
+{
+ o2_rally_device::device_start();
+
+ m_digit_out.resolve();
+}
+
+
+//-------------------------------------------------
+// mapper specific handlers
+//-------------------------------------------------
+
+u8 o2_rally_device::read_rom04(offs_t offset)
+{
+ // P10 enables latch output
+ u8 bank = (m_control & 1) ? ~0 : m_bank;
+ return m_rom[(offset + bank * 0x800) & (m_rom_size - 1)];
+}
+
+void o2_rally_device::io_write(offs_t offset, u8 data)
+{
+ if (offset & 0x80 && ~m_control & 0x10)
+ m_bank = data;
+}
+
+void o2_testpl_device::io_write(offs_t offset, u8 data)
+{
+ o2_rally_device::io_write(offset, data);
+
+ // write to 7segs if P11 is low
+ if (~m_control & 2)
+ {
+ static const u8 ls48_map[0x10] =
+ { 0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7c,0x07,0x7f,0x67,0x58,0x4c,0x62,0x69,0x78,0x00 };
+
+ m_digit_out[0] = ls48_map[data >> 4];
+ m_digit_out[1] = ls48_map[data & 0xf];
+ }
+}
+
+} // anonymous namespace
+
+
+DEFINE_DEVICE_TYPE_PRIVATE(O2_ROM_RALLY, device_o2_cart_interface, o2_rally_device, "o2_rally", "Videopac+ 60 Cartridge")
+DEFINE_DEVICE_TYPE_PRIVATE(O2_ROM_TESTPL, device_o2_cart_interface, o2_testpl_device, "o2_testpl", "Videopac+ Service Test Cartridge")
diff --git a/src/devices/bus/odyssey2/rally.h b/src/devices/bus/odyssey2/rally.h
new file mode 100644
index 00000000000..b9715050e49
--- /dev/null
+++ b/src/devices/bus/odyssey2/rally.h
@@ -0,0 +1,19 @@
+// license:BSD-3-Clause
+// copyright-holders:hap
+/**********************************************************************
+
+ Videopac+ 55/58/59/60 cartridge emulation
+
+**********************************************************************/
+
+#ifndef MAME_BUS_ODYSSEY2_RALLY_H
+#define MAME_BUS_ODYSSEY2_RALLY_H
+
+#pragma once
+
+#include "slot.h"
+
+DECLARE_DEVICE_TYPE(O2_ROM_RALLY, device_o2_cart_interface)
+DECLARE_DEVICE_TYPE(O2_ROM_TESTPL, 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 a7b705308fd..a64d8d3d1b9 100644
--- a/src/devices/bus/odyssey2/rom.cpp
+++ b/src/devices/bus/odyssey2/rom.cpp
@@ -1,96 +1,67 @@
// license:BSD-3-Clause
-// copyright-holders:Fabio Priuli
-/***********************************************************************************************************
+// copyright-holders:Wilbert Pol, Fabio Priuli, hap
+/******************************************************************************
+Standard cartridges emulation, optionally bankswitched up to 8KB.
- Magnavox Odyssey cart emulation
-
-
- ***********************************************************************************************************/
-
+******************************************************************************/
#include "emu.h"
#include "rom.h"
+namespace {
//-------------------------------------------------
-// o2_rom_device - constructor
+// initialization
//-------------------------------------------------
-DEFINE_DEVICE_TYPE(O2_ROM_STD, o2_rom_device, "o2_rom", "Odyssey 2 Standard Carts")
-DEFINE_DEVICE_TYPE(O2_ROM_12K, o2_rom12_device, "o2_rom12", "Odyssey 2 12K Carts")
-DEFINE_DEVICE_TYPE(O2_ROM_16K, o2_rom16_device, "o2_rom16", "Odyssey 2 16K Carts")
-
-
-o2_rom_device::o2_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_o2_cart_interface(mconfig, *this)
- , m_bank_base(0)
+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);
-o2_rom_device::o2_rom_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
- : o2_rom_device(mconfig, O2_ROM_STD, tag, owner, clock)
-{
-}
+protected:
+ virtual void device_start() override ATTR_COLD;
-o2_rom12_device::o2_rom12_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
- : o2_rom_device(mconfig, O2_ROM_12K, tag, owner, clock)
-{
-}
+ virtual void cart_init() override;
-o2_rom16_device::o2_rom16_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
- : o2_rom_device(mconfig, O2_ROM_16K, tag, owner, clock)
-{
-}
+ 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; }
-//-------------------------------------------------
-// device_start/device_reset - device-specific startup
-//-------------------------------------------------
+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)
+{ }
void o2_rom_device::device_start()
{
- save_item(NAME(m_bank_base));
+ save_item(NAME(m_bank));
}
-void o2_rom_device::device_reset()
+void o2_rom_device::cart_init()
{
- m_bank_base = 0;
+ m_cart_mask = (1 << (31 - count_leading_zeros_32(m_rom_size))) - 1;
}
-/*-------------------------------------------------
- mapper specific handlers
- -------------------------------------------------*/
-void o2_rom_device::write_bank(int bank)
-{
- m_bank_base = bank;
-}
+//-------------------------------------------------
+// mapper specific handlers
+//-------------------------------------------------
-READ8_MEMBER(o2_rom_device::read_rom04)
+u8 o2_rom_device::read_rom04(offs_t offset)
{
- return m_rom[(offset + (m_bank_base & 0x03) * 0x800) & (m_rom_size - 1)];
-}
-READ8_MEMBER(o2_rom_device::read_rom0c)
-{
- return m_rom[(offset + (m_bank_base & 0x03) * 0x800) & (m_rom_size - 1)];
+ offset = (offset + m_bank * 0x800) & m_cart_mask;
+ return (offset < m_rom_size) ? m_rom[offset] : 0xff;
}
-READ8_MEMBER(o2_rom12_device::read_rom04)
-{
- return m_rom[offset + (m_bank_base & 0x03) * 0xc00];
-}
-READ8_MEMBER(o2_rom12_device::read_rom0c)
-{
- return m_rom[offset + 0x800 + (m_bank_base & 0x03) * 0xc00];
-}
+} // anonymous namespace
-READ8_MEMBER(o2_rom16_device::read_rom04)
-{
- return m_rom[offset + 0x400 + (m_bank_base & 0x03) * 0x1000];
-}
-READ8_MEMBER(o2_rom16_device::read_rom0c)
-{
- return m_rom[offset + 0xc00 + (m_bank_base & 0x03) * 0x1000];
-}
+
+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 823b47462c7..9305a4c6345 100644
--- a/src/devices/bus/odyssey2/rom.h
+++ b/src/devices/bus/odyssey2/rom.h
@@ -1,5 +1,11 @@
// license:BSD-3-Clause
-// copyright-holders:Fabio Priuli
+// copyright-holders:Wilbert Pol, Fabio Priuli, hap
+/**********************************************************************
+
+ Standard cartridges emulation
+
+**********************************************************************/
+
#ifndef MAME_BUS_ODYSSEY2_ROM_H
#define MAME_BUS_ODYSSEY2_ROM_H
@@ -7,62 +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, uint32_t clock);
-
- // reading and writing
- virtual DECLARE_READ8_MEMBER(read_rom04) override;
- virtual DECLARE_READ8_MEMBER(read_rom0c) override;
-
- virtual void write_bank(int bank) override;
-
-protected:
- o2_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;
-
- int m_bank_base;
-};
-
-// ======================> o2_rom12_device
-
-class o2_rom12_device : public o2_rom_device
-{
-public:
- // construction/destruction
- o2_rom12_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
-
- // reading and writing
- virtual DECLARE_READ8_MEMBER(read_rom04) override;
- virtual DECLARE_READ8_MEMBER(read_rom0c) override;
-};
-
-// ======================> o2_rom16_device
-
-class o2_rom16_device : public o2_rom_device
-{
-public:
- // construction/destruction
- o2_rom16_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
-
- // reading and writing
- virtual DECLARE_READ8_MEMBER(read_rom04) override;
- virtual DECLARE_READ8_MEMBER(read_rom0c) override;
-};
-
-
-// device type definition
-DECLARE_DEVICE_TYPE(O2_ROM_STD, o2_rom_device)
-DECLARE_DEVICE_TYPE(O2_ROM_12K, o2_rom12_device)
-DECLARE_DEVICE_TYPE(O2_ROM_16K, o2_rom16_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 417bb27a38b..a5090c41f4a 100644
--- a/src/devices/bus/odyssey2/slot.cpp
+++ b/src/devices/bus/odyssey2/slot.cpp
@@ -5,12 +5,14 @@
Magnavox Odyssey 2 cart emulation
(through slot devices)
- ***********************************************************************************************************/
-
+***********************************************************************************************************/
#include "emu.h"
#include "slot.h"
+#include <tuple>
+
+
//**************************************************************************
// GLOBAL VARIABLES
//**************************************************************************
@@ -25,44 +27,14 @@ DEFINE_DEVICE_TYPE(O2_CART_SLOT, o2_cart_slot_device, "o2_cart_slot", "Odyssey 2
// device_o2_cart_interface - constructor
//-------------------------------------------------
-device_o2_cart_interface::device_o2_cart_interface(const machine_config &mconfig, device_t &device)
- : device_slot_card_interface(mconfig, device)
- , m_rom(nullptr)
- , m_rom_size(0)
-{
-}
-
-
-//-------------------------------------------------
-// ~device_o2_cart_interface - destructor
-//-------------------------------------------------
-
-device_o2_cart_interface::~device_o2_cart_interface()
-{
-}
-
-//-------------------------------------------------
-// rom_alloc - alloc the space for the cart
-//-------------------------------------------------
+device_o2_cart_interface::device_o2_cart_interface(const machine_config &mconfig, device_t &device) :
+ device_interface(device, "odyssey2cart"),
+ m_rom_size(0),
+ m_exrom_size(0),
+ m_voice_size(0)
+{ }
-void device_o2_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(O2SLOT_ROM_REGION_TAG).c_str(), size, 1, ENDIANNESS_LITTLE)->base();
- m_rom_size = size;
- }
-}
-
-
-//-------------------------------------------------
-// ram_alloc - alloc the space for the ram
-//-------------------------------------------------
-
-void device_o2_cart_interface::ram_alloc(uint32_t size)
-{
- m_ram.resize(size);
-}
+device_o2_cart_interface::~device_o2_cart_interface() { }
//**************************************************************************
@@ -72,22 +44,19 @@ void device_o2_cart_interface::ram_alloc(uint32_t size)
//-------------------------------------------------
// o2_cart_slot_device - constructor
//-------------------------------------------------
-o2_cart_slot_device::o2_cart_slot_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
- : device_t(mconfig, O2_CART_SLOT, tag, owner, clock)
- , device_image_interface(mconfig, *this)
- , device_slot_interface(mconfig, *this)
- , m_type(O2_STD), m_cart(nullptr)
-{
-}
+o2_cart_slot_device::o2_cart_slot_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock) :
+ device_t(mconfig, O2_CART_SLOT, tag, owner, clock),
+ device_cartrom_image_interface(mconfig, *this),
+ device_single_card_slot_interface<device_o2_cart_interface>(mconfig, *this),
+ m_type(O2_STD),
+ m_cart(nullptr),
+ m_conf(*this, "CONF"),
+ m_b(0)
+{ }
-//-------------------------------------------------
-// o2_cart_slot_device - destructor
-//-------------------------------------------------
+o2_cart_slot_device::~o2_cart_slot_device() { }
-o2_cart_slot_device::~o2_cart_slot_device()
-{
-}
//-------------------------------------------------
// device_start - device-specific startup
@@ -95,7 +64,7 @@ o2_cart_slot_device::~o2_cart_slot_device()
void o2_cart_slot_device::device_start()
{
- m_cart = dynamic_cast<device_o2_cart_interface *>(get_card_device());
+ m_cart = get_card_device();
}
@@ -105,26 +74,33 @@ void o2_cart_slot_device::device_start()
struct o2_slot
{
- int pcb_id;
- const char *slot_option;
+ 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 o2_slot slot_list[] =
{
{ O2_STD, "o2_rom" },
- { O2_ROM12, "o2_rom12" },
- { O2_ROM16, "o2_rom16" },
+ { O2_4IN1, "o2_4in1" },
+ { O2_RALLY, "o2_rally" },
+ { O2_KTAA, "o2_ktaa" },
{ O2_CHESS, "o2_chess" },
+ { O2_HOMECOMP, "o2_homecomp" },
+ { O2_TEST, "o2_test" },
+ { O2_TESTPL, "o2_testpl" },
{ O2_VOICE, "o2_voice" }
};
static int o2_get_pcb_id(const char *slot)
{
- for (auto & elem : slot_list)
+ if (slot)
{
- if (!core_stricmp(elem.slot_option, slot))
- return elem.pcb_id;
+ for (auto & elem : slot_list)
+ {
+ if (!strcmp(elem.slot_option, slot))
+ return elem.pcb_id;
+ }
}
return 0;
@@ -144,64 +120,75 @@ 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)
{
- uint32_t size = !loaded_through_softlist() ? length() : get_software_region_length("rom");
- m_cart->rom_alloc(size, tag());
-
- if (!loaded_through_softlist())
- fread(m_cart->get_rom_base(), size);
- else
- memcpy(m_cart->get_rom_base(), get_software_region("rom"), size);
-
- if (!loaded_through_softlist())
+ if (loaded_through_softlist())
{
- m_type = O2_STD;
- if (size == 12288)
- m_type = O2_ROM12;
- if (size == 16384)
- m_type = O2_ROM16;
+ load_software_region("rom", m_cart->m_rom);
+ load_software_region("exrom", m_cart->m_exrom);
+ load_software_region("voice", m_cart->m_voice);
+ m_cart->m_rom_size = get_software_region_length("rom");
+ m_cart->m_exrom_size = get_software_region_length("exrom");
+ m_cart->m_voice_size = get_software_region_length("voice");
+
+ m_type = o2_get_pcb_id(get_feature("slot"));
+
+ // Videopac+ determines whether the screen should have a border, with a gate connected
+ // to the cartridge B pin. This way, old Videopac games can still run in full screen.
+ const char *b_pin = get_feature("b_pin");
+ m_b = b_pin && strtoul(b_pin, nullptr, 0) ? 1 : 0;
}
else
{
- const char *pcb_name = get_feature("slot");
- if (pcb_name)
- m_type = o2_get_pcb_id(pcb_name);
+ 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;
+ }
}
- //printf("Type: %s\n", o2_get_slot(m_type));
-
- return image_init_result::PASS;
+ if (m_cart->get_rom_size() > 0)
+ m_cart->cart_init();
+ else if (!err)
+ err = image_error::UNSPECIFIED;
+ }
+ else
+ {
+ err = image_error::UNSPECIFIED;
}
- return image_init_result::PASS;
+ return std::make_pair(err, std::string());
}
/*-------------------------------------------------
get default card software
- -------------------------------------------------*/
+-------------------------------------------------*/
std::string o2_cart_slot_device::get_default_card_software(get_default_card_software_hook &hook) const
{
if (hook.image_file())
{
- const char *slot_string;
- uint32_t size = hook.image_file()->size();
- int type = O2_STD;
-
- if (size == 12288)
- type = O2_ROM12;
- if (size == 16384)
- type = O2_ROM16;
-
- slot_string = o2_get_slot(type);
-
- //printf("type: %s\n", slot_string);
+ uint64_t size;
+ hook.image_file()->length(size); // FIXME: check error return
+ int const type = (size == 0x4000) ? O2_RALLY : O2_STD;
+ char const *const slot_string = o2_get_slot(type);
return std::string(slot_string);
}
@@ -209,46 +196,118 @@ std::string o2_cart_slot_device::get_default_card_software(get_default_card_soft
return software_get_default_slot("o2_rom");
}
+
/*-------------------------------------------------
read_rom**
- -------------------------------------------------*/
+-------------------------------------------------*/
-READ8_MEMBER(o2_cart_slot_device::read_rom04)
+u8 o2_cart_slot_device::read_rom04(offs_t offset)
{
if (m_cart)
- return m_cart->read_rom04(space, offset);
+ return m_cart->read_rom04(offset);
else
return 0xff;
}
-READ8_MEMBER(o2_cart_slot_device::read_rom0c)
+u8 o2_cart_slot_device::read_rom0c(offs_t offset)
{
if (m_cart)
- return m_cart->read_rom0c(space, offset);
+ return m_cart->read_rom0c(offset);
else
return 0xff;
}
+
/*-------------------------------------------------
- io_write
- -------------------------------------------------*/
+ io
+-------------------------------------------------*/
+
+void o2_cart_slot_device::io_write(offs_t offset, u8 data)
+{
+ if (m_cart)
+ m_cart->io_write(offset, data);
+}
+
+u8 o2_cart_slot_device::io_read(offs_t offset)
+{
+ return (m_cart) ? m_cart->io_read(offset) : 0xff;
+}
-WRITE8_MEMBER(o2_cart_slot_device::io_write)
+void o2_cart_slot_device::bus_write(u8 data)
{
if (m_cart)
- m_cart->io_write(space, offset, data);
+ m_cart->bus_write(data);
+}
+
+u8 o2_cart_slot_device::bus_read()
+{
+ return (m_cart) ? m_cart->bus_read() : 0xff;
+}
+
+int o2_cart_slot_device::t0_read()
+{
+ return (m_cart) ? m_cart->t0_read() : 0;
+}
+
+int o2_cart_slot_device::b_read()
+{
+ int b_user = m_conf->read() & 3;
+ int b = b_user & 1;
+
+ if (m_cart)
+ {
+ // cartridge may override pin B setting
+ int b_cart = m_cart->b_read();
+
+ if (b_cart >= 0)
+ b = b_cart;
+ else if (b_user & 2)
+ b = m_b;
+ }
+
+ return b;
+}
+
+
+/*-------------------------------------------------
+ input ports
+-------------------------------------------------*/
+
+// Pin B only affects Videopac+ consoles: cartridges can decide whether to mask display edges or not,
+// by wiring the pin to either VCC or GND.
+
+static INPUT_PORTS_START( o2_cart_slot )
+ PORT_START("CONF")
+ PORT_CONFNAME( 0x03, 0x02, "Cartridge Pin B" )
+ PORT_CONFSETTING( 0x02, "Auto" ) // get setting from softwarelist
+ PORT_CONFSETTING( 0x00, "0" )
+ PORT_CONFSETTING( 0x01, "1" )
+INPUT_PORTS_END
+
+ioport_constructor o2_cart_slot_device::device_input_ports() const
+{
+ return INPUT_PORTS_NAME(o2_cart_slot);
}
#include "bus/odyssey2/rom.h"
+#include "bus/odyssey2/4in1.h"
+#include "bus/odyssey2/rally.h"
+#include "bus/odyssey2/ktaa.h"
#include "bus/odyssey2/chess.h"
+#include "bus/odyssey2/homecomp.h"
+#include "bus/odyssey2/test.h"
#include "bus/odyssey2/voice.h"
void o2_cart(device_slot_interface &device)
{
- device.option_add_internal("o2_rom", O2_ROM_STD);
- device.option_add_internal("o2_rom12", O2_ROM_12K);
- device.option_add_internal("o2_rom16", O2_ROM_16K);
- device.option_add_internal("o2_chess", O2_ROM_CHESS);
- device.option_add_internal("o2_voice", O2_ROM_VOICE);
+ device.option_add_internal("o2_rom", O2_ROM_STD);
+ device.option_add_internal("o2_4in1", O2_ROM_4IN1);
+ device.option_add_internal("o2_rally", O2_ROM_RALLY);
+ device.option_add_internal("o2_ktaa", O2_ROM_KTAA);
+ device.option_add_internal("o2_chess", O2_ROM_CHESS);
+ device.option_add_internal("o2_homecomp", O2_ROM_HOMECOMP);
+ device.option_add_internal("o2_test", O2_ROM_TEST);
+ device.option_add_internal("o2_testpl", O2_ROM_TESTPL);
+ device.option_add_internal("o2_voice", O2_ROM_VOICE);
}
diff --git a/src/devices/bus/odyssey2/slot.h b/src/devices/bus/odyssey2/slot.h
index bfb10c025bd..7f57a796f93 100644
--- a/src/devices/bus/odyssey2/slot.h
+++ b/src/devices/bus/odyssey2/slot.h
@@ -5,69 +5,104 @@
#pragma once
-#include "softlist_dev.h"
+#include "imagedev/cartrom.h"
+/*
-/***************************************************************************
- TYPE DEFINITIONS
- ***************************************************************************/
+Videopac / Odyssey 2 cartridge pinout:
+ bot. top
+ T0 1 A I/O _WR
+ B0 2 B GND
+ B1 3 C GND
+ B2 4 D 5V
+ B3 5 E I/O RD
+ B4 6 F _PSEN
+ B5 7 G A0
+ B6 8 H A1
+ B7 9 J A2
+ A10 10 K A3
+ P14 11 L A4
+ P11 12 M A5
+ P10 13 N A6
+ A11 14 P A7
+ A9 15 R A8
-/* PCB */
+A8-A11 are the same pins as P20-P23
+on Videopac+, B is used for video mixer override
+
+*/
+
+
+// PCB
enum
{
O2_STD = 0,
- O2_ROM12,
- O2_ROM16,
+ O2_4IN1,
+ O2_RALLY,
+ O2_KTAA,
O2_CHESS,
+ O2_HOMECOMP,
+ O2_TEST,
+ O2_TESTPL,
O2_VOICE
};
// ======================> device_o2_cart_interface
-class device_o2_cart_interface : public device_slot_card_interface
+class device_o2_cart_interface : public device_interface
{
+ friend class o2_cart_slot_device;
+
public:
// construction/destruction
virtual ~device_o2_cart_interface();
// reading and writing
- virtual DECLARE_READ8_MEMBER(read_rom04) { return 0xff; }
- virtual DECLARE_READ8_MEMBER(read_rom0c) { return 0xff; }
- virtual void write_bank(int bank) { }
+ virtual u8 read_rom04(offs_t offset) { return 0xff; }
+ virtual u8 read_rom0c(offs_t offset) { return 0xff; }
+ virtual void write_p1(u8 data) { }
+ virtual void write_p2(u8 data) { }
- virtual DECLARE_WRITE8_MEMBER(io_write) { }
- virtual DECLARE_READ_LINE_MEMBER(t0_read) { return 0; }
+ virtual void io_write(offs_t offset, u8 data) { }
+ virtual u8 io_read(offs_t offset) { return 0xff; }
+ virtual void bus_write(u8 data) { }
+ virtual u8 bus_read() { return 0xff; }
+ virtual int t0_read() { return 0; }
+ virtual int b_read() { return -1; }
- 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(); }
+ virtual void cart_init() { } // called after loading ROM
+
+ u8* get_rom_base() { return m_rom ? m_rom.get() : nullptr; }
+ u32 get_rom_size() { return m_rom_size; }
+
+ u8* get_voice_base() { return m_voice ? m_voice.get() : nullptr; }
+ u32 get_voice_size() { return m_voice_size; }
protected:
device_o2_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;
+ std::unique_ptr<uint8_t[]> m_rom;
+ std::unique_ptr<uint8_t[]> m_exrom;
+ std::unique_ptr<uint8_t[]> m_voice;
+ u32 m_rom_size;
+ u32 m_exrom_size;
+ u32 m_voice_size;
};
// ======================> o2_cart_slot_device
class o2_cart_slot_device : public device_t,
- public device_image_interface,
- public device_slot_interface
+ public device_cartrom_image_interface,
+ public device_single_card_slot_interface<device_o2_cart_interface>
{
public:
// construction/destruction
template <typename T>
- o2_cart_slot_device(machine_config const &mconfig, char const *tag, device_t *owner, T &&opts, char const *dflt)
- : o2_cart_slot_device(mconfig, tag, owner, 0)
+ o2_cart_slot_device(machine_config const &mconfig, char const *tag, device_t *owner, T &&opts, char const *dflt) :
+ o2_cart_slot_device(mconfig, tag, owner, 0)
{
option_reset();
opts(*this);
@@ -75,55 +110,53 @@ public:
set_fixed(false);
}
- o2_cart_slot_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock = 0);
+ o2_cart_slot_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock = 0);
virtual ~o2_cart_slot_device();
- // 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 void call_unload() override { }
- virtual const software_list_loader &get_software_list_loader() const override { return rom_software_list_loader::instance(); }
- int get_type() { return m_type; }
+ 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"; }
- virtual iodevice_t image_type() const override { return IO_CARTSLOT; }
- virtual bool is_readable() const override { return 1; }
- virtual bool is_writeable() const override { return 0; }
- virtual bool is_creatable() const override { return 0; }
- virtual bool must_be_loaded() const override { return 0; }
- virtual bool is_reset_on_load() const override { return 1; }
- virtual const char *image_interface() const override { return "odyssey_cart"; }
- virtual const char *file_extensions() const 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
- DECLARE_READ8_MEMBER(read_rom04);
- DECLARE_READ8_MEMBER(read_rom0c);
- DECLARE_WRITE8_MEMBER(io_write);
- DECLARE_READ_LINE_MEMBER(t0_read) { if (m_cart) return m_cart->t0_read(); else return 0; }
+ int get_type() { return m_type; }
+ device_o2_cart_interface* cart() { return m_cart; }
- void write_bank(int bank) { if (m_cart) m_cart->write_bank(bank); }
+ // reading and writing
+ u8 read_rom04(offs_t offset);
+ u8 read_rom0c(offs_t offset);
+ void io_write(offs_t offset, u8 data);
+ u8 io_read(offs_t offset);
+ void bus_write(u8 data);
+ u8 bus_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_t implementation
+ virtual void device_start() override ATTR_COLD;
+ virtual ioport_constructor device_input_ports() const override ATTR_COLD;
+private:
int m_type;
device_o2_cart_interface* m_cart;
+
+ required_ioport m_conf;
+ int m_b;
};
// device type definition
DECLARE_DEVICE_TYPE(O2_CART_SLOT, o2_cart_slot_device)
-/***************************************************************************
- DEVICE CONFIGURATION MACROS
- ***************************************************************************/
-
-#define O2SLOT_ROM_REGION_TAG ":cart:rom"
-
void o2_cart(device_slot_interface &device);
#endif // MAME_BUS_ODYSSEY2_SLOT_H
diff --git a/src/devices/bus/odyssey2/test.cpp b/src/devices/bus/odyssey2/test.cpp
new file mode 100644
index 00000000000..4130c010d04
--- /dev/null
+++ b/src/devices/bus/odyssey2/test.cpp
@@ -0,0 +1,92 @@
+// license:BSD-3-Clause
+// copyright-holders:hap
+/******************************************************************************
+
+Videopac Service Test cartridge emulation
+
+It's a standard 2KB ROM, the difference is that the PCB has a 7seg LED on it.
+The program will still work fine if the 7seg is not hooked up (eg. O2_ROM_STD).
+
+Test 1: press all joystick inputs
+Test 4: type "NAGEL137"
+(the other initial tests are automatic)
+
+Hold UP to advance to next test.
+
+******************************************************************************/
+
+#include "emu.h"
+#include "test.h"
+
+namespace {
+
+//-------------------------------------------------
+// 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 ATTR_COLD;
+
+ 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),
+ m_digit_out(*this, "tc_digit")
+{ }
+
+void o2_test_device::device_start()
+{
+ m_digit_out.resolve();
+
+ save_item(NAME(m_control));
+ save_item(NAME(m_bus_data));
+}
+
+void o2_test_device::cart_init()
+{
+ if (m_rom_size != 0x800)
+ fatalerror("o2_test_device: ROM size must be 2KB\n");
+}
+
+
+//-------------------------------------------------
+// mapper specific handlers
+//-------------------------------------------------
+
+void o2_test_device::write_p1(u8 data)
+{
+ u8 output = m_digit_out;
+
+ // P10: latch digit segments
+ if (m_control & ~data & 1)
+ output = ~m_bus_data;
+
+ // P11: digit DP
+ m_digit_out = (output & 0x7f) | (~data << 6 & 0x80);
+
+ 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
new file mode 100644
index 00000000000..2bc179e215c
--- /dev/null
+++ b/src/devices/bus/odyssey2/test.h
@@ -0,0 +1,18 @@
+// license:BSD-3-Clause
+// copyright-holders:hap
+/**********************************************************************
+
+ Videopac Service Test cartridge emulation
+
+**********************************************************************/
+
+#ifndef MAME_BUS_ODYSSEY2_TEST_H
+#define MAME_BUS_ODYSSEY2_TEST_H
+
+#pragma once
+
+#include "slot.h"
+
+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 83c199f7431..9ca1ea26101 100644
--- a/src/devices/bus/odyssey2/voice.cpp
+++ b/src/devices/bus/odyssey2/voice.cpp
@@ -1,41 +1,129 @@
// license:BSD-3-Clause
-// copyright-holders:Fabio Priuli
-/***********************************************************************************************************
+// copyright-holders:Wilbert Pol, Fabio Priuli
+/******************************************************************************
+Magnavox The Voice emulation
- Magnavox The Voice emulation
+Hardware notes:
+- SP0256B-019 with 2KB internal ROM
+- 16KB speech ROM, or 8*2KB on a daughterboard(same contents)
+- passthrough cartridge slot, with support for extra speech ROM
- TODO:
- - load speech ROM from softlist
- - move external speech rom for S.I.D. the Spellbinder into the softlist entry
+Cartridge pins A,B,E,1,10,11 are repurposed for the extra speech ROM. This means
+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"
+namespace {
//-------------------------------------------------
-// o2_voice_device - constructor
+// initialization
//-------------------------------------------------
-DEFINE_DEVICE_TYPE(O2_ROM_VOICE, o2_voice_device, "o2_voice", "Odyssey 2 The Voice Passthrough Cart")
+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 ATTR_COLD;
+ virtual void device_reset() override ATTR_COLD;
+ virtual void device_add_mconfig(machine_config &config) override ATTR_COLD;
+ virtual const tiny_rom_entry *device_rom_region() const override ATTR_COLD;
-o2_voice_device::o2_voice_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
- : o2_rom_device(mconfig, O2_ROM_VOICE, tag, owner, clock)
- , m_speech(*this, "sp0256_speech")
- , m_subslot(*this, "subslot")
- , m_lrq_state(0)
+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),
+ m_speech(*this, "speech"),
+ m_subslot(*this, "subslot")
+{ }
+
+void o2_voice_device::device_start()
{
+ save_item(NAME(m_control));
+ save_item(NAME(m_reset));
}
+void o2_voice_device::cart_init()
+{
+ u32 size = get_voice_size();
+ if (size == 0)
+ fatalerror("o2_voice_device: No voice region found\n");
-void o2_voice_device::device_start()
+ size = (size > 0x8000) ? 0x8000 : size;
+ memcpy(memregion("speech")->base(), get_voice_base(), size);
+}
+
+void o2_voice_device::device_reset()
{
- save_item(NAME(m_lrq_state));
+ if (m_subslot->exists() && m_subslot->cart() && m_subslot->cart()->get_voice_size())
+ {
+ // load additional speech data
+ u32 size = m_subslot->cart()->get_voice_size();
+ size = (size > 0x8000) ? 0x8000 : size;
+ memcpy(memregion("speech")->base() + 0x8000, m_subslot->cart()->get_voice_base(), size);
+ }
+}
+
+
+//-------------------------------------------------
+// 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;
+ }
}
@@ -47,33 +135,15 @@ void o2_voice_device::device_add_mconfig(machine_config &config)
{
SPEAKER(config, "mono").front_center();
- SP0256(config, m_speech, 3120000);
- m_speech->data_request_callback().set(FUNC(o2_voice_device::lrq_callback));
+ SP0256(config, m_speech, 3.12_MHz_XTAL);
// The Voice uses a speaker with its own volume control so the relative volumes to use are subjective, these sound good
m_speech->add_route(ALL_OUTPUTS, "mono", 1.00);
O2_CART_SLOT(config, m_subslot, o2_cart, nullptr);
}
-
ROM_START( o2voice )
- ROM_REGION( 0x10000, "sp0256_speech", 0 )
- // SP0256B-019 Speech chip w/2KiB mask rom
- ROM_LOAD( "sp0256b-019.bin", 0x1000, 0x0800, CRC(4bb43724) SHA1(49f5326ad45392dc96c89d1d4e089a20bd21e609) )
-
- /* A note about "The Voice": Two versions of "The Voice" exist:
- * An earlier version with eight 2KiB speech roms, spr016-??? through spr016-??? on a small daughterboard
- <note to self: fill in numbers later>
- * A later version with one 16KiB speech rom, spr128-003, mounted directly on the mainboard
- The rom contents of these two versions are EXACTLY the same.
- Both versions have an sp0256b-019 speech chip, which has 2KiB of its own internal speech data
- Thanks to kevtris for this info. - LN
- */
-
- // External 16KiB speech ROM (spr128-003) from "The Voice"
- ROM_LOAD( "spr128-003.bin", 0x4000, 0x4000, CRC(509367b5) SHA1(0f31f46bc02e9272885779a6dd7102c78b18895b) )
- // Additional External 16KiB speech ROM (spr128-004) from S.I.D. the Spellbinder
- ROM_LOAD( "spr128-004.bin", 0x8000, 0x4000, CRC(e79dfb75) SHA1(37f33d79ffd1739d7c2f226b010a1eac28d74ca0) )
+ ROM_REGION( 0x10000, "speech", ROMREGION_ERASE00 )
ROM_END
const tiny_rom_entry *o2_voice_device::device_rom_region() const
@@ -81,15 +151,7 @@ const tiny_rom_entry *o2_voice_device::device_rom_region() const
return ROM_NAME( o2voice );
}
-WRITE_LINE_MEMBER(o2_voice_device::lrq_callback)
-{
- m_lrq_state = state;
-}
+} // anonymous namespace
-WRITE8_MEMBER(o2_voice_device::io_write)
-{
- 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 296094e5bca..a773b333846 100644
--- a/src/devices/bus/odyssey2/voice.h
+++ b/src/devices/bus/odyssey2/voice.h
@@ -1,51 +1,18 @@
// license:BSD-3-Clause
-// copyright-holders:Fabio Priuli
+// copyright-holders:Wilbert Pol, Fabio Priuli
+/******************************************************************************
+
+ Magnavox The Voice emulation
+
+******************************************************************************/
+
#ifndef MAME_BUS_ODYSSEY2_VOICE_H
#define MAME_BUS_ODYSSEY2_VOICE_H
#pragma once
#include "slot.h"
-#include "rom.h"
-#include "sound/sp0256.h"
-
-
-// ======================> o2_voice_device
-
-class o2_voice_device : public o2_rom_device
-{
-public:
- // construction/destruction
- o2_voice_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
-
- // reading and writing
- virtual DECLARE_READ8_MEMBER(read_rom04) override { if (m_subslot->exists()) return m_subslot->read_rom04(space, offset); else return 0xff; }
- virtual DECLARE_READ8_MEMBER(read_rom0c) override { if (m_subslot->exists()) return m_subslot->read_rom0c(space, offset); else return 0xff; }
-
- virtual void write_bank(int bank) override { if (m_subslot->exists()) m_subslot->write_bank(bank); }
-
- virtual DECLARE_WRITE8_MEMBER(io_write) override;
- virtual DECLARE_READ_LINE_MEMBER(t0_read) override { return m_speech->lrq_r() ? 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;
- virtual const tiny_rom_entry *device_rom_region() const override;
-
-private:
- DECLARE_WRITE_LINE_MEMBER(lrq_callback);
-
- required_device<sp0256_device> m_speech;
- required_device<o2_cart_slot_device> m_subslot;
-
- int m_lrq_state;
-};
-
-// 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 bff09d06026..811a1c4d9e8 100644
--- a/src/devices/bus/oricext/jasmin.cpp
+++ b/src/devices/bus/oricext/jasmin.cpp
@@ -3,17 +3,23 @@
#include "emu.h"
#include "jasmin.h"
#include "formats/oric_dsk.h"
+#include "formats/fs_oric_jasmin.h"
-DEFINE_DEVICE_TYPE(JASMIN, jasmin_device, "jasmin", "Jasmin floppy drive interface")
+DEFINE_DEVICE_TYPE(ORIC_JASMIN, oric_jasmin_device, "oric_jasmin", "Jasmin floppy drive interface")
ROM_START( jasmin )
ROM_REGION( 0x800, "jasmin", 0 )
ROM_LOAD("jasmin.rom", 0, 0x800, CRC(37220e89) SHA1(70e59b8abd67092f050462abc6cb5271e4c15f01) )
ROM_END
-FLOPPY_FORMATS_MEMBER( jasmin_device::floppy_formats )
- FLOPPY_ORIC_DSK_FORMAT
-FLOPPY_FORMATS_END
+void oric_jasmin_device::floppy_formats(format_registration &fr)
+{
+ fr.add_mfm_containers();
+ fr.add(FLOPPY_ORIC_DSK_FORMAT);
+ fr.add(FLOPPY_ORIC_JASMIN_FORMAT);
+
+ fr.add(fs::ORIC_JASMIN);
+}
static void jasmin_floppies(device_slot_interface &device)
{
@@ -22,17 +28,29 @@ static void jasmin_floppies(device_slot_interface &device)
INPUT_PORTS_START( jasmin )
PORT_START("JASMIN")
- PORT_BIT( 0x01, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_NAME("Boot") PORT_CODE(KEYCODE_F1) PORT_CHAR(UCHAR_MAMEKEY(F1)) PORT_CHANGED_MEMBER(DEVICE_SELF, jasmin_device, boot_pressed, 0)
+ 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, FUNC(oric_jasmin_device::boot_pressed), 0)
INPUT_PORTS_END
-void jasmin_device::map(address_map &map)
+void oric_jasmin_device::map_io(address_space_installer &space)
+{
+ 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()
{
- map(0x3f4, 0x3f7).rw("fdc", FUNC(wd1770_device::read), FUNC(wd1770_device::write));
- map(0x3f8, 0x3ff).w(m_fdlatch, FUNC(ls259_device::write_d0));
+ (*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);
}
-jasmin_device::jasmin_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) :
- oricext_device(mconfig, JASMIN, tag, owner, clock),
+oric_jasmin_device::oric_jasmin_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) :
+ device_t(mconfig, ORIC_JASMIN, tag, owner, clock),
+ device_oricext_interface(mconfig, *this),
m_fdc(*this, "fdc"),
m_fdlatch(*this, "fdlatch"),
m_floppies(*this, "fdc:%u", 0U),
@@ -41,109 +59,86 @@ jasmin_device::jasmin_device(const machine_config &mconfig, const char *tag, dev
{
}
-jasmin_device::~jasmin_device()
+oric_jasmin_device::~oric_jasmin_device()
{
}
-void jasmin_device::device_start()
+void oric_jasmin_device::device_start()
{
- oricext_device::device_start();
- cpu->space(AS_PROGRAM).install_device(0x0000, 0xffff, *this, &jasmin_device::map);
}
-const tiny_rom_entry *jasmin_device::device_rom_region() const
+const tiny_rom_entry *oric_jasmin_device::device_rom_region() const
{
return ROM_NAME( jasmin );
}
-void jasmin_device::device_add_mconfig(machine_config &config)
+void oric_jasmin_device::device_add_mconfig(machine_config &config)
{
WD1770(config, m_fdc, 8_MHz_XTAL);
- m_fdc->drq_wr_callback().set(FUNC(oricext_device::irq_w));
+ m_fdc->drq_wr_callback().set(FUNC(oric_jasmin_device::irq_w));
- FLOPPY_CONNECTOR(config, "fdc:0", jasmin_floppies, "3dsdd", jasmin_device::floppy_formats);
- FLOPPY_CONNECTOR(config, "fdc:1", jasmin_floppies, nullptr, jasmin_device::floppy_formats);
- FLOPPY_CONNECTOR(config, "fdc:2", jasmin_floppies, nullptr, jasmin_device::floppy_formats);
- FLOPPY_CONNECTOR(config, "fdc:3", jasmin_floppies, nullptr, jasmin_device::floppy_formats);
+ FLOPPY_CONNECTOR(config, "fdc:0", jasmin_floppies, "3dsdd", oric_jasmin_device::floppy_formats);
+ FLOPPY_CONNECTOR(config, "fdc:1", jasmin_floppies, nullptr, oric_jasmin_device::floppy_formats);
+ FLOPPY_CONNECTOR(config, "fdc:2", jasmin_floppies, nullptr, oric_jasmin_device::floppy_formats);
+ FLOPPY_CONNECTOR(config, "fdc:3", jasmin_floppies, nullptr, oric_jasmin_device::floppy_formats);
LS259(config, m_fdlatch); // U14
- m_fdlatch->q_out_cb<0>().set(FUNC(jasmin_device::side_sel_w));
+ m_fdlatch->q_out_cb<0>().set(FUNC(oric_jasmin_device::side_sel_w));
m_fdlatch->q_out_cb<1>().set(m_fdc, FUNC(wd1770_device::mr_w));
- m_fdlatch->q_out_cb<2>().set(FUNC(jasmin_device::ram_access_w));
- m_fdlatch->q_out_cb<3>().set(FUNC(jasmin_device::rom_access_w));
- m_fdlatch->q_out_cb<4>().set(FUNC(jasmin_device::select_w));
- m_fdlatch->q_out_cb<5>().set(FUNC(jasmin_device::select_w));
- m_fdlatch->q_out_cb<6>().set(FUNC(jasmin_device::select_w));
- m_fdlatch->q_out_cb<7>().set(FUNC(jasmin_device::select_w));
+ m_fdlatch->q_out_cb<2>().set(FUNC(oric_jasmin_device::ram_access_w));
+ m_fdlatch->q_out_cb<3>().set(FUNC(oric_jasmin_device::rom_access_w));
+ m_fdlatch->q_out_cb<4>().set(FUNC(oric_jasmin_device::select_w));
+ m_fdlatch->q_out_cb<5>().set(FUNC(oric_jasmin_device::select_w));
+ m_fdlatch->q_out_cb<6>().set(FUNC(oric_jasmin_device::select_w));
+ m_fdlatch->q_out_cb<7>().set(FUNC(oric_jasmin_device::select_w));
}
-ioport_constructor jasmin_device::device_input_ports() const
+ioport_constructor oric_jasmin_device::device_input_ports() const
{
return INPUT_PORTS_NAME( jasmin );
}
-void jasmin_device::remap()
+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);
}
}
-INPUT_CHANGED_MEMBER(jasmin_device::boot_pressed)
+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(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(jasmin_device::ram_access_w)
+void oric_jasmin_device::ram_access_w(int state)
{
remap();
}
-WRITE_LINE_MEMBER(jasmin_device::rom_access_w)
+void oric_jasmin_device::rom_access_w(int state)
{
remap();
}
-WRITE_LINE_MEMBER(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 a9c6fe78ba9..0dc008cb9cf 100644
--- a/src/devices/bus/oricext/jasmin.h
+++ b/src/devices/bus/oricext/jasmin.h
@@ -10,33 +10,34 @@
#include "machine/74259.h"
#include "machine/wd_fdc.h"
-DECLARE_DEVICE_TYPE(JASMIN, jasmin_device)
+DECLARE_DEVICE_TYPE(ORIC_JASMIN, oric_jasmin_device)
-class jasmin_device : public oricext_device
+class oric_jasmin_device : public device_t, public device_oricext_interface
{
public:
- jasmin_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
- virtual ~jasmin_device();
+ oric_jasmin_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
+ virtual ~oric_jasmin_device();
DECLARE_INPUT_CHANGED_MEMBER(boot_pressed);
protected:
- virtual void device_start() override;
+ virtual void device_start() override ATTR_COLD;
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_add_mconfig(machine_config &config) override ATTR_COLD;
+ virtual ioport_constructor device_input_ports() const override ATTR_COLD;
+
+ 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);
- DECLARE_FLOPPY_FORMATS(floppy_formats);
+ static void floppy_formats(format_registration &fr);
required_device<wd1770_device> m_fdc;
required_device<ls259_device> m_fdlatch;
diff --git a/src/devices/bus/oricext/microdisc.cpp b/src/devices/bus/oricext/microdisc.cpp
index a5e4bb4d889..9abe2debd27 100644
--- a/src/devices/bus/oricext/microdisc.cpp
+++ b/src/devices/bus/oricext/microdisc.cpp
@@ -4,115 +4,99 @@
#include "microdisc.h"
#include "formats/oric_dsk.h"
-DEFINE_DEVICE_TYPE(MICRODISC, microdisc_device, "microdisc", "Microdisc floppy drive interface")
+DEFINE_DEVICE_TYPE(ORIC_MICRODISC, oric_microdisc_device, "oric_microdisc", "Microdisc floppy drive interface")
ROM_START( microdisc )
ROM_REGION( 0x2000, "microdisc", 0 )
ROM_LOAD ("microdis.rom", 0, 0x02000, CRC(a9664a9c) SHA1(0d2ef6e67322f48f4b7e08d8bbe68827e2074561) )
ROM_END
-FLOPPY_FORMATS_MEMBER( microdisc_device::floppy_formats )
- FLOPPY_ORIC_DSK_FORMAT
-FLOPPY_FORMATS_END
+void oric_microdisc_device::floppy_formats(format_registration &fr)
+{
+ fr.add_mfm_containers();
+ fr.add(FLOPPY_ORIC_DSK_FORMAT);
+}
static void microdisc_floppies(device_slot_interface &device)
{
device.option_add("3dsdd", FLOPPY_3_DSDD);
+ device.option_add("3dsqd", FLOPPY_3_DSQD);
}
-void 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(microdisc_device::port_314_r), FUNC(microdisc_device::port_314_w));
- map(0x318, 0x318).r(FUNC(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)));
}
-microdisc_device::microdisc_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) :
- oricext_device(mconfig, MICRODISC, tag, owner, clock),
- fdc(*this, "fdc"), microdisc_rom(nullptr), port_314(0), intrq_state(false), drq_state(false), hld_state(false)
+void oric_microdisc_device::map_rom()
{
+ (*view)[2].unmap_write(0xe000, 0xffff);
+ (*view)[2].install_rom(0xe000, 0xffff, microdisc_rom);
}
-microdisc_device::~microdisc_device()
+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(*this, "microdisc"),
+ floppies(*this, "fdc:%u", 0U),
+ port_314(0), intrq_state(false), drq_state(false), hld_state(false)
{
}
-void microdisc_device::device_start()
+oric_microdisc_device::~oric_microdisc_device()
{
- oricext_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, &microdisc_device::map);
+}
- for(int i=0; i<4; i++) {
- char name[32];
- sprintf(name, "fdc:%d", i);
- floppies[i] = subdevice<floppy_connector>(name)->get_device();
- }
+void oric_microdisc_device::device_start()
+{
intrq_state = drq_state = hld_state = false;
}
-void microdisc_device::device_reset()
+void oric_microdisc_device::device_reset()
{
port_314 = 0x00;
+ view->select(2);
irq_w(false);
- remap();
- fdc->set_floppy(floppies[0]);
-
- // The bootstrap checksums part of the high ram and if the sum is
- // 0 it goes wrong.
- ram[0xe000] = 0x42;
+ fdc->set_floppy(floppies[0]->get_device());
}
-const tiny_rom_entry *microdisc_device::device_rom_region() const
+const tiny_rom_entry *oric_microdisc_device::device_rom_region() const
{
return ROM_NAME( microdisc );
}
-void microdisc_device::device_add_mconfig(machine_config &config)
+void oric_microdisc_device::device_add_mconfig(machine_config &config)
{
FD1793(config, fdc, 8_MHz_XTAL / 8);
- fdc->intrq_wr_callback().set(FUNC(microdisc_device::fdc_irq_w));
- fdc->drq_wr_callback().set(FUNC(microdisc_device::fdc_drq_w));
- fdc->hld_wr_callback().set(FUNC(microdisc_device::fdc_hld_w));
+ fdc->intrq_wr_callback().set(FUNC(oric_microdisc_device::fdc_irq_w));
+ fdc->drq_wr_callback().set(FUNC(oric_microdisc_device::fdc_drq_w));
+ fdc->hld_wr_callback().set(FUNC(oric_microdisc_device::fdc_hld_w));
fdc->set_force_ready(true);
- FLOPPY_CONNECTOR(config, "fdc:0", microdisc_floppies, "3dsdd", microdisc_device::floppy_formats);
- FLOPPY_CONNECTOR(config, "fdc:1", microdisc_floppies, nullptr, microdisc_device::floppy_formats);
- FLOPPY_CONNECTOR(config, "fdc:2", microdisc_floppies, nullptr, microdisc_device::floppy_formats);
- FLOPPY_CONNECTOR(config, "fdc:3", microdisc_floppies, nullptr, microdisc_device::floppy_formats);
-}
-
-void 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);
- }
- }
+ FLOPPY_CONNECTOR(config, "fdc:0", microdisc_floppies, "3dsqd", oric_microdisc_device::floppy_formats);
+ FLOPPY_CONNECTOR(config, "fdc:1", microdisc_floppies, nullptr, oric_microdisc_device::floppy_formats);
+ FLOPPY_CONNECTOR(config, "fdc:2", microdisc_floppies, nullptr, oric_microdisc_device::floppy_formats);
+ FLOPPY_CONNECTOR(config, "fdc:3", microdisc_floppies, nullptr, oric_microdisc_device::floppy_formats);
}
-WRITE8_MEMBER(microdisc_device::port_314_w)
+void oric_microdisc_device::port_314_w(uint8_t data)
{
port_314 = data;
- remap();
- floppy_image_device *floppy = floppies[(port_314 >> 5) & 3];
+ 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);
if(floppy) {
@@ -122,30 +106,31 @@ WRITE8_MEMBER(microdisc_device::port_314_w)
irq_w(intrq_state && (port_314 & P_IRQEN));
}
-READ8_MEMBER(microdisc_device::port_314_r)
+uint8_t oric_microdisc_device::port_314_r()
{
return (intrq_state && (port_314 & P_IRQEN)) ? 0x7f : 0xff;
}
-READ8_MEMBER(microdisc_device::port_318_r)
+uint8_t oric_microdisc_device::port_318_r()
{
return drq_state ? 0x7f : 0xff;
}
-WRITE_LINE_MEMBER(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(microdisc_device::fdc_drq_w)
+void oric_microdisc_device::fdc_drq_w(int state)
{
drq_state = state;
}
-WRITE_LINE_MEMBER(microdisc_device::fdc_hld_w)
+void oric_microdisc_device::fdc_hld_w(int state)
{
- logerror("hld %d\n", state);
hld_state = state;
- floppies[(port_314 >> 5) & 3]->mon_w(!hld_state);
+ floppy_image_device *floppy = floppies[(port_314 >> 5) & 3]->get_device();
+ if(floppy)
+ floppy->mon_w(!hld_state);
}
diff --git a/src/devices/bus/oricext/microdisc.h b/src/devices/bus/oricext/microdisc.h
index a5f97151f0d..49919482441 100644
--- a/src/devices/bus/oricext/microdisc.h
+++ b/src/devices/bus/oricext/microdisc.h
@@ -7,14 +7,13 @@
#include "imagedev/floppy.h"
#include "machine/wd_fdc.h"
-DECLARE_DEVICE_TYPE(MICRODISC, microdisc_device)
+DECLARE_DEVICE_TYPE(ORIC_MICRODISC, oric_microdisc_device)
-class microdisc_device : public oricext_device
+class oric_microdisc_device : public device_t, public device_oricext_interface
{
public:
- microdisc_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
- virtual ~microdisc_device();
-
+ oric_microdisc_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
+ virtual ~oric_microdisc_device();
protected:
enum {
@@ -27,32 +26,31 @@ protected:
P_EPROM = 0x80
};
- required_device<fd1793_device> fdc;
-
- uint8_t *microdisc_rom;
- floppy_image_device *floppies[4];
- uint8_t port_314;
- bool intrq_state, drq_state, hld_state;
-
- virtual void device_start() override;
- virtual void device_reset() override;
+ virtual void device_start() override ATTR_COLD;
+ virtual void device_reset() override ATTR_COLD;
const tiny_rom_entry *device_rom_region() const override;
- virtual void device_add_mconfig(machine_config &config) override;
+ virtual void device_add_mconfig(machine_config &config) override ATTR_COLD;
- 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;
- DECLARE_WRITE8_MEMBER(port_314_w);
- DECLARE_READ8_MEMBER(port_314_r);
- DECLARE_READ8_MEMBER(port_318_r);
+ void fdc_irq_w(int state);
+ void fdc_drq_w(int state);
+ void fdc_hld_w(int state);
- void map(address_map &map);
+ void port_314_w(uint8_t data);
+ uint8_t port_314_r();
+ uint8_t port_318_r();
- DECLARE_FLOPPY_FORMATS(floppy_formats);
+ static void floppy_formats(format_registration &fr);
};
#endif // MAME_BUS_ORICEXT_MICRODISC_H
diff --git a/src/devices/bus/oricext/oricext.cpp b/src/devices/bus/oricext/oricext.cpp
index 8f1204d0f57..ee8c285c3ef 100644
--- a/src/devices/bus/oricext/oricext.cpp
+++ b/src/devices/bus/oricext/oricext.cpp
@@ -7,11 +7,11 @@
DEFINE_DEVICE_TYPE(ORICEXT_CONNECTOR, oricext_connector, "oricext_connector", "ORIC extension connector")
-oricext_connector::oricext_connector(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
- : device_t(mconfig, ORICEXT_CONNECTOR, tag, owner, clock)
- , device_slot_interface(mconfig, *this)
- , irq_handler(*this)
- , cputag(nullptr)
+oricext_connector::oricext_connector(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) :
+ device_t(mconfig, ORICEXT_CONNECTOR, tag, owner, clock),
+ device_single_card_slot_interface<device_oricext_interface>(mconfig, *this),
+ irq_handler(*this),
+ reset_handler(*this)
{
}
@@ -19,14 +19,8 @@ oricext_connector::~oricext_connector()
{
}
-void oricext_connector::set_cputag(const char *tag)
-{
- cputag = tag;
-}
-
void oricext_connector::device_start()
{
- irq_handler.resolve_safe();
}
void oricext_connector::irq_w(int state)
@@ -34,59 +28,61 @@ void oricext_connector::irq_w(int state)
irq_handler(state);
}
-void oricext_connector::device_config_complete()
+void oricext_connector::reset_w(int state)
{
- oricext_device *dev = dynamic_cast<oricext_device *>(get_card_device());
- if(dev)
- dev->set_cputag(cputag);
+ reset_handler(state);
}
-oricext_device::oricext_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_card_interface(mconfig, *this),
- cputag(nullptr),
- 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)
+void oricext_connector::set_view(memory_view &_view)
{
+ auto card = get_card_device();
+ if(card)
+ card->set_view(_view);
}
-void oricext_device::set_cputag(const char *tag)
+void oricext_connector::map_io(address_space_installer &space)
{
- cputag = tag;
+ auto card = get_card_device();
+ if(card)
+ card->map_io(space);
}
-void oricext_device::device_start()
+void oricext_connector::map_rom()
{
- cpu = machine().device<m6502_device>(cputag);
- connector = downcast<oricext_connector *>(owner());
- bank_c000_r = membank(":bank_c000_r");
- bank_e000_r = membank(":bank_e000_r");
- bank_f800_r = membank(":bank_f800_r");
- bank_c000_w = membank(":bank_c000_w");
- bank_e000_w = membank(":bank_e000_w");
- bank_f800_w = membank(":bank_f800_w");
- rom = (uint8_t *)machine().root_device().memregion(cputag)->base();
- ram = (uint8_t *)memshare(":ram")->ptr();
+ 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"),
+ view(nullptr),
+ connector(nullptr)
+{
+}
- memset(junk_read, 0xff, sizeof(junk_read));
- memset(junk_write, 0x00, sizeof(junk_write));
+void device_oricext_interface::interface_pre_start()
+{
+ connector = downcast<oricext_connector *>(device().owner());
}
-WRITE_LINE_MEMBER(oricext_device::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", JASMIN);
- device.option_add("microdisc", MICRODISC);
+ device.option_add("jasmin", ORIC_JASMIN);
+ device.option_add("microdisc", ORIC_MICRODISC);
}
diff --git a/src/devices/bus/oricext/oricext.h b/src/devices/bus/oricext/oricext.h
index 067d1f611c7..e442cfdc4ac 100644
--- a/src/devices/bus/oricext/oricext.h
+++ b/src/devices/bus/oricext/oricext.h
@@ -13,55 +13,60 @@
#include "cpu/m6502/m6502.h"
-class oricext_device;
+class device_oricext_interface;
-class oricext_connector: public device_t, public device_slot_interface
+class oricext_connector: public device_t, public device_single_card_slot_interface<device_oricext_interface>
{
+ friend class device_oricext_interface;
+
public:
template <typename T>
- oricext_connector(const machine_config &mconfig, const char *tag, device_t *owner, T &&opts, const char *dflt, const char *cputag)
+ 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(cputag);
}
oricext_connector(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
virtual ~oricext_connector();
- void set_cputag(const char *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;
- virtual void device_config_complete() override;
+ virtual void device_start() override ATTR_COLD;
devcb_write_line irq_handler;
- const char *cputag;
+ devcb_write_line reset_handler;
};
-class oricext_device : public device_t,
- public device_slot_card_interface
+class device_oricext_interface : public device_interface
{
public:
- void set_cputag(const char *tag);
- 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:
- oricext_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock);
+ device_oricext_interface(const machine_config &mconfig, device_t &device);
- virtual void device_start() override;
+ virtual void interface_pre_start() override;
- const char *cputag;
- 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/pac2.cpp b/src/devices/bus/pasopia/pac2.cpp
new file mode 100644
index 00000000000..13955bba61f
--- /dev/null
+++ b/src/devices/bus/pasopia/pac2.cpp
@@ -0,0 +1,159 @@
+// license:BSD-3-Clause
+// copyright-holders:AJR
+/****************************************************************************
+
+ Toshiba Pasopia PAC2 slot
+
+ This is the smallest of the three Pasopia expansion connectors. Despite
+ only providing access to a 4-by-8-bit space, this was mostly used for
+ memory cartridges.
+
+ ______
+ CDB 7 1 | . . | 2 CDB 6
+ GND 3 | . . | 4 CDB 5
+ CDB 4 5 | . . | 6 CDB 3
+ GND 7 | . . | 8 CDB 2
+ CDB 1 9 | . . | 10 CDB 0
+ CDAD01 11 | . . | 12 CDAD00
+ GND 13 | . . | 14 CSELP2
+ CDRD 15 | . . | 16 CDWR
+ GND 17 | . . | 18 GND
+ +5V 19 | . . | 20 +5V
+ ------
+
+****************************************************************************/
+
+#include "emu.h"
+#include "pac2.h"
+
+#include "pac2exp.h"
+#include "rampac2.h"
+#include "rompac2.h"
+
+//**************************************************************************
+// GLOBAL VARIABLES
+//**************************************************************************
+
+// device type definition
+DEFINE_DEVICE_TYPE(PASOPIA_PAC2, pasopia_pac2_slot_device, "pasopia_pac2", "Pasopia PAC2 Slot")
+
+//**************************************************************************
+// PAC2 SLOT DEVICE
+//**************************************************************************
+
+//-------------------------------------------------
+// pasopia_pac2_slot_device - construction
+//-------------------------------------------------
+
+pasopia_pac2_slot_device::pasopia_pac2_slot_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock)
+ : device_t(mconfig, PASOPIA_PAC2, tag, owner, clock)
+ , device_single_card_slot_interface<pac2_card_interface>(mconfig, *this)
+ , m_card(nullptr)
+{
+}
+
+
+//-------------------------------------------------
+// device_resolve_objects - resolve objects that
+// may be needed for other devices to set
+// initial conditions at start time
+//-------------------------------------------------
+
+void pasopia_pac2_slot_device::device_resolve_objects()
+{
+ m_card = get_card_device();
+ if (m_card != nullptr)
+ m_card->m_slot = this;
+}
+
+
+//-------------------------------------------------
+// device_start - device-specific startup
+//-------------------------------------------------
+
+void pasopia_pac2_slot_device::device_start()
+{
+}
+
+
+//-------------------------------------------------
+// read - I/O read access
+//-------------------------------------------------
+
+u8 pasopia_pac2_slot_device::read(offs_t offset)
+{
+ if (m_card == nullptr)
+ {
+ if (!machine().side_effects_disabled())
+ logerror("%s: Read from unconnected PAC2 (CDAD = %X)\n", machine().describe_context(), offset);
+ return 0;
+ }
+
+ return m_card->pac2_read(offset);
+}
+
+
+//-------------------------------------------------
+// write - I/O write access
+//-------------------------------------------------
+
+void pasopia_pac2_slot_device::write(offs_t offset, u8 data)
+{
+ if (m_card != nullptr)
+ m_card->pac2_write(offset, data);
+}
+
+//**************************************************************************
+// PAC2 CARD INTERFACE
+//**************************************************************************
+
+//-------------------------------------------------
+// pac2_card_interface - construction
+//-------------------------------------------------
+
+pac2_card_interface::pac2_card_interface(const machine_config &mconfig, device_t &device)
+ : device_interface(device, "pac2card")
+ , m_slot(nullptr)
+{
+}
+
+
+//-------------------------------------------------
+// interface_pre_start - called before the
+// device's own start function
+//-------------------------------------------------
+
+void pac2_card_interface::interface_pre_start()
+{
+ if (!m_slot)
+ throw device_missing_dependencies();
+}
+
+
+//-------------------------------------------------
+// pac2_subslot_devices - add standard options
+// for subslots
+//-------------------------------------------------
+
+void pac2_subslot_devices(device_slot_interface &device)
+{
+ //device.option_add("ram4k", PASOPIA_PA7241);
+ device.option_add("ram16k", PASOPIA_PA7243);
+ device.option_add("ram32k", PASOPIA_PA7245);
+ device.option_add("kanji", PASOPIA_PA7246);
+ //device.option_add("kanji2", PASOPIA_PA7247);
+ device.option_add("ram64k", PASOPIA_PA7248);
+ //device.option_add("joy", PASOPIA_PA7390);
+}
+
+
+//-------------------------------------------------
+// pac2_default_devices - add standard options
+// for main slots
+//-------------------------------------------------
+
+void pac2_default_devices(device_slot_interface &device)
+{
+ device.option_add("exp", PASOPIA_PA7234);
+ pac2_subslot_devices(device);
+}
diff --git a/src/devices/bus/pasopia/pac2.h b/src/devices/bus/pasopia/pac2.h
new file mode 100644
index 00000000000..a03e274151f
--- /dev/null
+++ b/src/devices/bus/pasopia/pac2.h
@@ -0,0 +1,83 @@
+// license:BSD-3-Clause
+// copyright-holders:AJR
+/**********************************************************************
+
+ Toshiba Pasopia PAC2 slot
+
+**********************************************************************/
+
+#ifndef MAME_BUS_PASOPIA_PAC2_H
+#define MAME_BUS_PASOPIA_PAC2_H
+
+#pragma once
+
+
+//**************************************************************************
+// TYPE DEFINITIONS
+//**************************************************************************
+
+// forward declarations
+class pac2_card_interface;
+
+// ======================> pasopia_pac2_slot_device
+
+class pasopia_pac2_slot_device : public device_t, public device_single_card_slot_interface<pac2_card_interface>
+{
+ friend class pac2_card_interface;
+
+public:
+ // construction/destruction
+ template <typename T>
+ pasopia_pac2_slot_device(machine_config const &mconfig, char const *tag, device_t *owner, T &&opts, char const *dflt)
+ : pasopia_pac2_slot_device(mconfig, tag, owner, 0)
+ {
+ option_reset();
+ opts(*this);
+ set_default_option(dflt);
+ set_fixed(false);
+ }
+
+ pasopia_pac2_slot_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock = 0);
+
+ // memory accesses
+ u8 read(offs_t offset);
+ void write(offs_t offset, u8 data);
+
+protected:
+ // device-specific overrides
+ virtual void device_resolve_objects() override ATTR_COLD;
+ virtual void device_start() override ATTR_COLD;
+
+private:
+ pac2_card_interface *m_card;
+};
+
+
+// ======================> pac2_card_interface
+
+class pac2_card_interface : public device_interface
+{
+ friend class pasopia_pac2_slot_device;
+
+protected:
+ // construction/destruction
+ pac2_card_interface(const machine_config &mconfig, device_t &device);
+
+ // required overrides
+ virtual u8 pac2_read(offs_t offset) = 0;
+ virtual void pac2_write(offs_t offset, u8 data) = 0;
+
+private:
+ virtual void interface_pre_start() override;
+
+ pasopia_pac2_slot_device *m_slot;
+};
+
+
+// device type definition
+DECLARE_DEVICE_TYPE(PASOPIA_PAC2, pasopia_pac2_slot_device)
+
+void pac2_subslot_devices(device_slot_interface &device);
+void pac2_default_devices(device_slot_interface &device);
+
+#endif // MAME_BUS_PASOPIA_PAC2_H
diff --git a/src/devices/bus/pasopia/pac2exp.cpp b/src/devices/bus/pasopia/pac2exp.cpp
new file mode 100644
index 00000000000..2638a7bc645
--- /dev/null
+++ b/src/devices/bus/pasopia/pac2exp.cpp
@@ -0,0 +1,92 @@
+// license:BSD-3-Clause
+// copyright-holders:AJR
+/****************************************************************************
+
+ Toshiba Pasopia PAC2 expander
+
+ Not much is known about the internal circuitry of this 4-slot expansion.
+ It was apparently designed primarily for the Pasopia 7, with the cord
+ connecting the sidecar to the main unit through a hole in a modified
+ slot cover.
+
+ The one-based slot selection scheme is due to the need to avoid
+ interfering with the 0x80 control byte needed to configure the PPI on
+ the PA7241 RAM PAC2.
+
+****************************************************************************/
+
+#include "emu.h"
+#include "pac2exp.h"
+
+//**************************************************************************
+// GLOBAL VARIABLES
+//**************************************************************************
+
+// device type definition
+DEFINE_DEVICE_TYPE(PASOPIA_PA7234, pasopia_pa7234_device, "pa7234", "PA7234 Pasopia PAC2 Expansion Unit")
+
+//**************************************************************************
+// DEVICE DEFINITION
+//**************************************************************************
+
+//-------------------------------------------------
+// pasopia_pa7234_device - construction
+//-------------------------------------------------
+
+pasopia_pa7234_device::pasopia_pa7234_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock)
+ : device_t(mconfig, PASOPIA_PA7234, tag, owner, clock)
+ , pac2_card_interface(mconfig, *this)
+ , m_slot(*this, "slot%u", 1U)
+ , m_slot_selected(0)
+{
+}
+
+
+//-------------------------------------------------
+// device_add_mconfig - add device-specific
+// machine configuration
+//-------------------------------------------------
+
+void pasopia_pa7234_device::device_add_mconfig(machine_config &config)
+{
+ for (auto &slot : m_slot)
+ PASOPIA_PAC2(config, slot, pac2_subslot_devices, nullptr);
+}
+
+
+//-------------------------------------------------
+// device_start - device-specific startup
+//-------------------------------------------------
+
+void pasopia_pa7234_device::device_start()
+{
+ save_item(NAME(m_slot_selected));
+}
+
+//**************************************************************************
+// PAC2 INTERFACE
+//**************************************************************************
+
+//-------------------------------------------------
+// pac2_read - I/O read access
+//-------------------------------------------------
+
+u8 pasopia_pa7234_device::pac2_read(offs_t offset)
+{
+ return m_slot[m_slot_selected]->read(offset);
+}
+
+
+//-------------------------------------------------
+// pac2_write - I/O write access
+//-------------------------------------------------
+
+void pasopia_pa7234_device::pac2_write(offs_t offset, u8 data)
+{
+ // Assume all writes are passed through
+ m_slot[m_slot_selected]->write(offset, data);
+
+ // 1, 2, 3, 4 or 7 may supposedly be written here
+ if ((offset & 3) == 3 && (data & 0x07) != 0)
+ m_slot_selected = (data - 1) & 0x03;
+}
diff --git a/src/devices/bus/pasopia/pac2exp.h b/src/devices/bus/pasopia/pac2exp.h
new file mode 100644
index 00000000000..d2fb5b994a0
--- /dev/null
+++ b/src/devices/bus/pasopia/pac2exp.h
@@ -0,0 +1,44 @@
+// license:BSD-3-Clause
+// copyright-holders:AJR
+
+#ifndef MAME_BUS_PASOPIA_PAC2EXP_H
+#define MAME_BUS_PASOPIA_PAC2EXP_H
+
+#pragma once
+
+#include "pac2.h"
+
+
+//**************************************************************************
+// TYPE DEFINITIONS
+//**************************************************************************
+
+// ======================> pasopia_pa7234_device
+
+class pasopia_pa7234_device : public device_t, public pac2_card_interface
+{
+public:
+ // device type constructor
+ pasopia_pa7234_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock);
+
+protected:
+ // device-level overrides
+ virtual void device_add_mconfig(machine_config &config) override ATTR_COLD;
+ virtual void device_start() override ATTR_COLD;
+
+ // pac2_card_interface overrides
+ virtual u8 pac2_read(offs_t offset) override;
+ virtual void pac2_write(offs_t offset, u8 data) override;
+
+private:
+ // object finders
+ required_device_array<pasopia_pac2_slot_device, 4> m_slot;
+
+ // internal state
+ u8 m_slot_selected;
+};
+
+// device type declaration
+DECLARE_DEVICE_TYPE(PASOPIA_PA7234, pasopia_pa7234_device)
+
+#endif // MAME_BUS_PASOPIA_PAC2EXP_H
diff --git a/src/devices/bus/pasopia/rampac2.cpp b/src/devices/bus/pasopia/rampac2.cpp
new file mode 100644
index 00000000000..21ec9c2baaa
--- /dev/null
+++ b/src/devices/bus/pasopia/rampac2.cpp
@@ -0,0 +1,151 @@
+// license:BSD-3-Clause
+// copyright-holders:AJR, Angelo Salese
+/****************************************************************************
+
+ Toshiba Pasopia RAM PAC2 emulation
+
+ This emulates the later, larger cartridges, but not the original 4K
+ model which used a 8255 PPI to latch the RAM address.
+
+****************************************************************************/
+
+#include "emu.h"
+#include "rampac2.h"
+
+//**************************************************************************
+// GLOBAL VARIABLES
+//**************************************************************************
+
+// device type definitions
+DEFINE_DEVICE_TYPE(PASOPIA_PA7243, pasopia_pa7243_device, "pa7243", "PA7243 Pasopia RAM PAC2 (16KB)")
+DEFINE_DEVICE_TYPE(PASOPIA_PA7245, pasopia_pa7245_device, "pa7245", "PA7245 Pasopia RAM PAC2 (32KB)")
+DEFINE_DEVICE_TYPE(PASOPIA_PA7248, pasopia_pa7248_device, "pa7248", "PA7248 Pasopia RAM PAC2 (64KB)")
+
+//**************************************************************************
+// DEVICE DEFINITION
+//**************************************************************************
+
+//-------------------------------------------------
+// pasopia_rampac2_device - construction
+//-------------------------------------------------
+
+pasopia_rampac2_device::pasopia_rampac2_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)
+ , pac2_card_interface(mconfig, *this)
+ , device_nvram_interface(mconfig, *this)
+ , m_ram_size(ram_size)
+ , m_ram_index(0)
+{
+}
+
+
+//-------------------------------------------------
+// pasopia_pa7243_device - construction
+//-------------------------------------------------
+
+pasopia_pa7243_device::pasopia_pa7243_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock)
+ : pasopia_rampac2_device(mconfig, PASOPIA_PA7243, tag, owner, clock, 0x4000)
+{
+}
+
+
+//-------------------------------------------------
+// pasopia_pa7245_device - construction
+//-------------------------------------------------
+
+pasopia_pa7245_device::pasopia_pa7245_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock)
+ : pasopia_rampac2_device(mconfig, PASOPIA_PA7245, tag, owner, clock, 0x8000)
+{
+}
+
+
+//-------------------------------------------------
+// pasopia_pa7248_device - construction
+//-------------------------------------------------
+
+pasopia_pa7248_device::pasopia_pa7248_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock)
+ : pasopia_rampac2_device(mconfig, PASOPIA_PA7248, tag, owner, clock, 0x10000)
+{
+}
+
+
+//-------------------------------------------------
+// device_start - device-specific startup
+//-------------------------------------------------
+
+void pasopia_rampac2_device::device_start()
+{
+ m_ram = std::make_unique<u8[]>(m_ram_size);
+
+ save_pointer(NAME(m_ram), m_ram_size);
+ save_item(NAME(m_ram_index));
+}
+
+
+//-------------------------------------------------
+// nvram_read - read NVRAM from the file
+//-------------------------------------------------
+
+bool pasopia_rampac2_device::nvram_read(util::read_stream &file)
+{
+ auto const [err, actual] = read(file, &m_ram[0], m_ram_size);
+ return !err && (actual == m_ram_size);
+}
+
+
+//-------------------------------------------------
+// nvram_write - write NVRAM to the file
+//-------------------------------------------------
+
+bool pasopia_rampac2_device::nvram_write(util::write_stream &file)
+{
+ auto const [err, actual] = write(file, &m_ram[0], m_ram_size);
+ return !err;
+}
+
+
+//-------------------------------------------------
+// nvram_default - initialize NVRAM to its
+// default state
+//-------------------------------------------------
+
+void pasopia_rampac2_device::nvram_default()
+{
+ std::fill_n(&m_ram[0], m_ram_size, 0);
+}
+
+//**************************************************************************
+// PAC2 INTERFACE
+//**************************************************************************
+
+//-------------------------------------------------
+// pac2_read - I/O read access
+//-------------------------------------------------
+
+u8 pasopia_rampac2_device::pac2_read(offs_t offset)
+{
+ return m_ram[m_ram_index & (m_ram_size - 1)];
+}
+
+
+//-------------------------------------------------
+// pac2_write - I/O write access
+//-------------------------------------------------
+
+void pasopia_rampac2_device::pac2_write(offs_t offset, u8 data)
+{
+ switch (offset)
+ {
+ case 0:
+ m_ram_index = (m_ram_index & 0xff00) | (data & 0xff);
+ break;
+
+ case 1:
+ m_ram_index = (m_ram_index & 0xff) | ((data & 0xff) << 8);
+ break;
+
+ case 2: // PAC2 RAM write
+ m_ram[m_ram_index & (m_ram_size - 1)] = data;
+ break;
+ }
+}
diff --git a/src/devices/bus/pasopia/rampac2.h b/src/devices/bus/pasopia/rampac2.h
new file mode 100644
index 00000000000..19cf9dcc478
--- /dev/null
+++ b/src/devices/bus/pasopia/rampac2.h
@@ -0,0 +1,76 @@
+// license:BSD-3-Clause
+// copyright-holders:AJR
+
+#ifndef MAME_BUS_PASOPIA_RAMPAC2_H
+#define MAME_BUS_PASOPIA_RAMPAC2_H
+
+#pragma once
+
+#include "pac2.h"
+
+
+//**************************************************************************
+// TYPE DEFINITIONS
+//**************************************************************************
+
+// ======================> pasopia_rampac2_device
+
+class pasopia_rampac2_device : public device_t, public pac2_card_interface, public device_nvram_interface
+{
+protected:
+ // construction/destruction
+ pasopia_rampac2_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, u32 clock, u32 ram_size);
+
+ // device-level overrides
+ virtual void device_start() override ATTR_COLD;
+
+ // device_nvram_interface overrides
+ virtual bool nvram_read(util::read_stream &file) override;
+ virtual bool nvram_write(util::write_stream &file) override;
+ virtual void nvram_default() override;
+
+ // pac2_card_interface overrides
+ virtual u8 pac2_read(offs_t offset) override;
+ virtual void pac2_write(offs_t offset, u8 data) override;
+
+private:
+ const u32 m_ram_size;
+
+ // internal state
+ std::unique_ptr<u8[]> m_ram;
+ u16 m_ram_index;
+};
+
+// ======================> pasopia_pa7243_device
+
+class pasopia_pa7243_device : public pasopia_rampac2_device
+{
+public:
+ // device type constructor
+ pasopia_pa7243_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock);
+};
+
+// ======================> pasopia_pa7245_device
+
+class pasopia_pa7245_device : public pasopia_rampac2_device
+{
+public:
+ // device type constructor
+ pasopia_pa7245_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock);
+};
+
+// ======================> pasopia_pa7248_device
+
+class pasopia_pa7248_device : public pasopia_rampac2_device
+{
+public:
+ // device type constructor
+ pasopia_pa7248_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock);
+};
+
+// device type declarations
+DECLARE_DEVICE_TYPE(PASOPIA_PA7243, pasopia_pa7243_device)
+DECLARE_DEVICE_TYPE(PASOPIA_PA7245, pasopia_pa7245_device)
+DECLARE_DEVICE_TYPE(PASOPIA_PA7248, pasopia_pa7248_device)
+
+#endif // MAME_BUS_PASOPIA_RAMPAC2_H
diff --git a/src/devices/bus/pasopia/rompac2.cpp b/src/devices/bus/pasopia/rompac2.cpp
new file mode 100644
index 00000000000..5ec120ac120
--- /dev/null
+++ b/src/devices/bus/pasopia/rompac2.cpp
@@ -0,0 +1,98 @@
+// license:BSD-3-Clause
+// copyright-holders:AJR, Angelo Salese
+/****************************************************************************
+
+ Toshiba Pasopia Kanji ROM PAC2 emulation
+
+ TODO: find out the difference between PA7246 and PA7247 (which one
+ is actually dumped here?)
+
+****************************************************************************/
+
+#include "emu.h"
+#include "rompac2.h"
+
+//**************************************************************************
+// GLOBAL VARIABLES
+//**************************************************************************
+
+// device type definition
+DEFINE_DEVICE_TYPE(PASOPIA_PA7246, pasopia_pa7246_device, "pa7246", "PA7246 Pasopia Kanji ROM PAC2")
+
+//**************************************************************************
+// DEVICE DEFINITION
+//**************************************************************************
+
+//-------------------------------------------------
+// pasopia_pa7246_device - construction
+//-------------------------------------------------
+
+pasopia_pa7246_device::pasopia_pa7246_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock)
+ : device_t(mconfig, PASOPIA_PA7246, tag, owner, clock)
+ , pac2_card_interface(mconfig, *this)
+ , m_kanji_rom(*this, "kanji")
+ , m_kanji_index(0)
+{
+}
+
+
+ROM_START(pa7246)
+ ROM_REGION(0x20000, "kanji", 0)
+ ROM_LOAD("kanji.rom", 0x00000, 0x20000, CRC(6109e308) SHA1(5c21cf1f241ef1fa0b41009ea41e81771729785f))
+ROM_END
+
+//-------------------------------------------------
+// device_rom_region - return a pointer to the
+// rom region description for this device
+//-------------------------------------------------
+
+const tiny_rom_entry *pasopia_pa7246_device::device_rom_region() const
+{
+ return ROM_NAME(pa7246);
+}
+
+
+//-------------------------------------------------
+// device_start - device-specific startup
+//-------------------------------------------------
+
+void pasopia_pa7246_device::device_start()
+{
+ save_item(NAME(m_kanji_index));
+}
+
+//**************************************************************************
+// PAC2 INTERFACE
+//**************************************************************************
+
+//-------------------------------------------------
+// pac2_read - I/O read access
+//-------------------------------------------------
+
+u8 pasopia_pa7246_device::pac2_read(offs_t offset)
+{
+ return m_kanji_rom[m_kanji_index];
+}
+
+
+//-------------------------------------------------
+// pac2_write - I/O write access
+//-------------------------------------------------
+
+void pasopia_pa7246_device::pac2_write(offs_t offset, u8 data)
+{
+ switch (offset)
+ {
+ case 0:
+ m_kanji_index = (m_kanji_index & 0x1ff00) | ((data & 0xff) << 0);
+ break;
+
+ case 1:
+ m_kanji_index = (m_kanji_index & 0x100ff) | ((data & 0xff) << 8);
+ break;
+
+ case 2:
+ m_kanji_index = (m_kanji_index & 0x0ffff) | ((data & 0x01) << 16);
+ break;
+ }
+}
diff --git a/src/devices/bus/pasopia/rompac2.h b/src/devices/bus/pasopia/rompac2.h
new file mode 100644
index 00000000000..3a709d69745
--- /dev/null
+++ b/src/devices/bus/pasopia/rompac2.h
@@ -0,0 +1,44 @@
+// license:BSD-3-Clause
+// copyright-holders:AJR
+
+#ifndef MAME_BUS_PASOPIA_ROMPAC2_H
+#define MAME_BUS_PASOPIA_ROMPAC2_H
+
+#pragma once
+
+#include "pac2.h"
+
+
+//**************************************************************************
+// TYPE DEFINITIONS
+//**************************************************************************
+
+// ======================> pasopia_pa7246_device
+
+class pasopia_pa7246_device : public device_t, public pac2_card_interface
+{
+public:
+ // device type constructor
+ pasopia_pa7246_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock);
+
+protected:
+ // device-level overrides
+ virtual const tiny_rom_entry *device_rom_region() const override ATTR_COLD;
+ virtual void device_start() override ATTR_COLD;
+
+ // pac2_card_interface overrides
+ virtual u8 pac2_read(offs_t offset) override;
+ virtual void pac2_write(offs_t offset, u8 data) override;
+
+private:
+ // object finders
+ required_region_ptr<u8> m_kanji_rom;
+
+ // internal state
+ u32 m_kanji_index;
+};
+
+// device type declaration
+DECLARE_DEVICE_TYPE(PASOPIA_PA7246, pasopia_pa7246_device)
+
+#endif // MAME_BUS_PASOPIA_ROMPAC2_H
diff --git a/src/devices/bus/pc1512/mouse.cpp b/src/devices/bus/pc1512/mouse.cpp
index 882284e89d2..2cf5616d4b1 100644
--- a/src/devices/bus/pc1512/mouse.cpp
+++ b/src/devices/bus/pc1512/mouse.cpp
@@ -29,7 +29,7 @@ DEFINE_DEVICE_TYPE(PC1512_MOUSE, pc1512_mouse_device, "pc1512_mouse",
//-------------------------------------------------
device_pc1512_mouse_port_interface::device_pc1512_mouse_port_interface(const machine_config &mconfig, device_t &device) :
- device_slot_card_interface(mconfig, device)
+ device_interface(device, "pc1512mouse")
{
m_port = dynamic_cast<pc1512_mouse_port_device *>(device.owner());
}
@@ -46,7 +46,7 @@ device_pc1512_mouse_port_interface::device_pc1512_mouse_port_interface(const mac
pc1512_mouse_port_device::pc1512_mouse_port_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) :
device_t(mconfig, PC1512_MOUSE_PORT, tag, owner, clock),
- device_slot_interface(mconfig, *this),
+ device_single_card_slot_interface<device_pc1512_mouse_port_interface>(mconfig, *this),
m_write_x(*this),
m_write_y(*this),
m_write_m1(*this),
@@ -68,13 +68,7 @@ pc1512_mouse_device::pc1512_mouse_device(const machine_config &mconfig, const ch
void pc1512_mouse_port_device::device_start()
{
- m_device = dynamic_cast<device_pc1512_mouse_port_interface *>(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();
+ m_device = get_card_device();
}
void pc1512_mouse_device::device_start()
@@ -88,14 +82,14 @@ void pc1512_mouse_device::device_start()
static INPUT_PORTS_START( mouse )
PORT_START("MOUSEB")
- PORT_BIT( 0x01, IP_ACTIVE_LOW, IPT_OTHER ) PORT_NAME("Left Mouse Button") PORT_CODE(MOUSECODE_BUTTON1) PORT_CHANGED_MEMBER(DEVICE_SELF, pc1512_mouse_device, mouse_button_1_changed, 0)
- PORT_BIT( 0x02, IP_ACTIVE_LOW, IPT_OTHER ) PORT_NAME("Right Mouse Button") PORT_CODE(MOUSECODE_BUTTON2) PORT_CHANGED_MEMBER(DEVICE_SELF, pc1512_mouse_device, mouse_button_2_changed, 0)
+ PORT_BIT( 0x01, IP_ACTIVE_LOW, IPT_OTHER ) PORT_NAME("Left Mouse Button") PORT_CODE(MOUSECODE_BUTTON1) PORT_CHANGED_MEMBER(DEVICE_SELF, FUNC(pc1512_mouse_device::mouse_button_1_changed), 0)
+ PORT_BIT( 0x02, IP_ACTIVE_LOW, IPT_OTHER ) PORT_NAME("Right Mouse Button") PORT_CODE(MOUSECODE_BUTTON2) PORT_CHANGED_MEMBER(DEVICE_SELF, FUNC(pc1512_mouse_device::mouse_button_2_changed), 0)
PORT_START("MOUSEX")
- PORT_BIT( 0xff, 0x00, IPT_MOUSE_X ) PORT_SENSITIVITY(100) PORT_KEYDELTA(5) PORT_MINMAX(0, 255) PORT_PLAYER(1) PORT_CHANGED_MEMBER(DEVICE_SELF, pc1512_mouse_device, mouse_x_changed, 0)
+ PORT_BIT( 0xff, 0x00, IPT_MOUSE_X ) PORT_SENSITIVITY(100) PORT_KEYDELTA(5) PORT_MINMAX(0, 255) PORT_PLAYER(1) PORT_CHANGED_MEMBER(DEVICE_SELF, FUNC(pc1512_mouse_device::mouse_x_changed), 0)
PORT_START("MOUSEY")
- PORT_BIT( 0xff, 0x00, IPT_MOUSE_Y ) PORT_SENSITIVITY(100) PORT_KEYDELTA(5) PORT_MINMAX(0, 255) PORT_PLAYER(1) PORT_CHANGED_MEMBER(DEVICE_SELF, pc1512_mouse_device, mouse_y_changed, 0)
+ PORT_BIT( 0xff, 0x00, IPT_MOUSE_Y ) PORT_SENSITIVITY(100) PORT_KEYDELTA(5) PORT_MINMAX(0, 255) PORT_PLAYER(1) PORT_CHANGED_MEMBER(DEVICE_SELF, FUNC(pc1512_mouse_device::mouse_y_changed), 0)
INPUT_PORTS_END
diff --git a/src/devices/bus/pc1512/mouse.h b/src/devices/bus/pc1512/mouse.h
index 9c71eb4d89d..64c6f9479b1 100644
--- a/src/devices/bus/pc1512/mouse.h
+++ b/src/devices/bus/pc1512/mouse.h
@@ -27,13 +27,6 @@
//**************************************************************************
-// INTERFACE CONFIGURATION MACROS
-//**************************************************************************
-
-#define PC1512_MOUSE_PORT_TAG "mous"
-
-
-//**************************************************************************
// TYPE DEFINITIONS
//**************************************************************************
@@ -42,7 +35,7 @@ class pc1512_mouse_port_device;
// ======================> device_pc1512_mouse_port_interface
-class device_pc1512_mouse_port_interface : public device_slot_card_interface
+class device_pc1512_mouse_port_interface : public device_interface
{
public:
// construction/destruction
@@ -57,7 +50,7 @@ protected:
// ======================> pc1512_mouse_port_device
-class pc1512_mouse_port_device : public device_t, public device_slot_interface
+class pc1512_mouse_port_device : public device_t, public device_single_card_slot_interface<device_pc1512_mouse_port_interface>
{
public:
// construction/destruction
@@ -87,7 +80,7 @@ public:
protected:
// device-level overrides
- virtual void device_start() override;
+ virtual void device_start() override ATTR_COLD;
devcb_write8 m_write_x;
devcb_write8 m_write_y;
@@ -107,7 +100,7 @@ public:
pc1512_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;
+ virtual ioport_constructor device_input_ports() const override ATTR_COLD;
DECLARE_INPUT_CHANGED_MEMBER( mouse_x_changed ) { m_port->x_w(newval); }
DECLARE_INPUT_CHANGED_MEMBER( mouse_y_changed ) { m_port->y_w(newval); }
@@ -116,7 +109,7 @@ public:
protected:
// device-level overrides
- virtual void device_start() override;
+ virtual void device_start() override ATTR_COLD;
};
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/gsx8800.cpp b/src/devices/bus/pc8801/gsx8800.cpp
new file mode 100644
index 00000000000..df630cf83bf
--- /dev/null
+++ b/src/devices/bus/pc8801/gsx8800.cpp
@@ -0,0 +1,54 @@
+// license:BSD-3-Clause
+// copyright-holders:Angelo Salese
+/**************************************************************************************************
+
+HAL GSX-8800
+
+TODO:
+- Untested (failed attempt for rcmpc88v which seems to access $a0-$a1 for a "direct" MIDI);
+- multi-card support, can move $a0-$a3 into $a4-$a7 thru a jumper for dual GSX;
+- MIDI-IN/OUT connector, 8251 serial and 8253;
+- RHYTHM-BOX connector (?)
+
+**************************************************************************************************/
+
+
+#include "emu.h"
+#include "gsx8800.h"
+
+
+DEFINE_DEVICE_TYPE(GSX8800, gsx8800_device, "gsx8800", "HAL GSX-8800")
+
+gsx8800_device::gsx8800_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
+ : pc8801_exp_device(mconfig, GSX8800, tag, owner, clock)
+ , m_psg(*this, "psg.%u", 0U)
+{
+}
+
+void gsx8800_device::io_map(address_map &map)
+{
+ map(0xa1, 0xa1).r(m_psg[0], FUNC(ym2149_device::data_r));
+ map(0xa0, 0xa1).w(m_psg[0], FUNC(ym2149_device::address_data_w));
+ map(0xa3, 0xa3).r(m_psg[1], FUNC(ym2149_device::data_r));
+ map(0xa2, 0xa3).w(m_psg[1], FUNC(ym2149_device::address_data_w));
+// map(0xc2, 0xc3) 8251 to MIDI
+ // TODO: PIT location is unknown
+}
+
+void gsx8800_device::device_add_mconfig(machine_config &config)
+{
+ // TODO: should be 3'993'600, divided by 32 (?)
+ constexpr XTAL psg_x1_clock = XTAL(4'000'000);
+
+ // TODO: mixing routing may be swapped
+ // it's just known that one goes to the left and the other to the right
+ // cfr. http://mydocuments.g2.xrea.com/html/p8/soundinfo.html
+ YM2149(config, m_psg[0], psg_x1_clock);
+ m_psg[0]->add_route(ALL_OUTPUTS, "^^speaker", 0.50, 0);
+
+ YM2149(config, m_psg[1], psg_x1_clock);
+ m_psg[1]->add_route(ALL_OUTPUTS, "^^speaker", 0.50, 1);
+
+
+// ...->irq_handler().set(FUNC(gsx8800_device::int3_w));
+}
diff --git a/src/devices/bus/pc8801/gsx8800.h b/src/devices/bus/pc8801/gsx8800.h
new file mode 100644
index 00000000000..dd44faaea9a
--- /dev/null
+++ b/src/devices/bus/pc8801/gsx8800.h
@@ -0,0 +1,30 @@
+// license:BSD-3-Clause
+// copyright-holders:Angelo Salese
+
+#ifndef MAME_BUS_PC8801_GSX8800_H
+#define MAME_BUS_PC8801_GSX8800_H
+
+#pragma once
+
+#include "pc8801_exp.h"
+#include "sound/ay8910.h"
+
+class gsx8800_device : public pc8801_exp_device
+{
+public:
+ gsx8800_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
+
+ static constexpr feature_type unemulated_features() { return feature::SOUND; }
+
+ virtual void io_map(address_map &map) override ATTR_COLD;
+
+private:
+ virtual void device_add_mconfig(machine_config &config) override ATTR_COLD;
+
+ required_device_array<ym2149_device, 2> m_psg;
+};
+
+DECLARE_DEVICE_TYPE(GSX8800, gsx8800_device)
+
+
+#endif // MAME_BUS_PC8801_GSX8800_H
diff --git a/src/devices/bus/pc8801/hmb20.cpp b/src/devices/bus/pc8801/hmb20.cpp
new file mode 100644
index 00000000000..6da14585d6e
--- /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, "^^speaker", 0.50, 0);
+ m_opm->add_route(ALL_OUTPUTS, "^^speaker", 0.50, 1);
+}
diff --git a/src/devices/bus/pc8801/hmb20.h b/src/devices/bus/pc8801/hmb20.h
new file mode 100644
index 00000000000..a197c2ae069
--- /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 ATTR_COLD;
+
+private:
+ virtual void device_add_mconfig(machine_config &config) override ATTR_COLD;
+
+ 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
new file mode 100644
index 00000000000..a5beb667a31
--- /dev/null
+++ b/src/devices/bus/pc8801/jmbx1.cpp
@@ -0,0 +1,58 @@
+// license:BSD-3-Clause
+// copyright-holders:Angelo Salese
+/**************************************************************************************************
+
+ JMB-X1 sound card
+
+ Used for PC-8001mkII/PC-8801 NRTDRV88J sound program
+ http://upd780c1.g1.xrea.com/pc-8001/j80-25.html
+
+ TODO:
+ - Source claims it runs on INT3, but the vector that uses NRTDRV is clearly INT4.
+ Is it configurable?
+
+**************************************************************************************************/
+
+#include "emu.h"
+#include "jmbx1.h"
+
+
+DEFINE_DEVICE_TYPE(JMBX1, jmbx1_device, "jmbx1", "JMB-X1 \"Sound Board X\"")
+
+jmbx1_device::jmbx1_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
+ : pc8801_exp_device(mconfig, JMBX1, tag, owner, clock)
+ , m_opm1(*this, "opm1")
+ , m_opm2(*this, "opm2")
+ , m_ssg(*this, "ssg")
+{
+}
+
+void jmbx1_device::io_map(address_map &map)
+{
+ map(0xc8, 0xc9).rw(m_opm1, FUNC(ym2151_device::read), FUNC(ym2151_device::write));
+ map(0xca, 0xcb).rw(m_opm2, FUNC(ym2151_device::read), FUNC(ym2151_device::write));
+ map(0xcc, 0xcd).w(m_ssg, FUNC(ym2149_device::address_data_w));
+ map(0xcd, 0xcd).r(m_ssg, FUNC(ym2149_device::data_r));
+}
+
+void jmbx1_device::device_add_mconfig(machine_config &config)
+{
+ constexpr XTAL jmb_x1_clock = XTAL(8'000'000);
+
+ // TODO: OPM mixing
+ // (SSG is mono)
+ // doesn't seem to have irq mask
+ YM2151(config, m_opm1, jmb_x1_clock / 2);
+ m_opm1->irq_handler().set(FUNC(jmbx1_device::int4_w));
+ m_opm1->add_route(ALL_OUTPUTS, "^^speaker", 0.25, 0);
+ m_opm1->add_route(ALL_OUTPUTS, "^^speaker", 0.25, 1);
+
+ YM2151(config, m_opm2, jmb_x1_clock / 2);
+ m_opm2->add_route(ALL_OUTPUTS, "^^speaker", 0.25, 0);
+ m_opm2->add_route(ALL_OUTPUTS, "^^speaker", 0.25, 1);
+
+ YM2149(config, m_ssg, jmb_x1_clock / 4);
+ // TODO: adds a non-negligible DC offset, likely needs high pass filter
+ m_ssg->add_route(ALL_OUTPUTS, "^^speaker", 0.20, 0);
+ m_ssg->add_route(ALL_OUTPUTS, "^^speaker", 0.20, 1);
+}
diff --git a/src/devices/bus/pc8801/jmbx1.h b/src/devices/bus/pc8801/jmbx1.h
new file mode 100644
index 00000000000..50ea182d9f9
--- /dev/null
+++ b/src/devices/bus/pc8801/jmbx1.h
@@ -0,0 +1,31 @@
+// license:BSD-3-Clause
+// copyright-holders:Angelo Salese
+
+#ifndef MAME_BUS_PC8801_JMBX1_H
+#define MAME_BUS_PC8801_JMBX1_H
+
+#pragma once
+
+#include "pc8801_exp.h"
+#include "sound/ay8910.h"
+#include "sound/ymopm.h"
+
+class jmbx1_device : public pc8801_exp_device
+{
+public:
+ jmbx1_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
+
+ virtual void io_map(address_map &map) override ATTR_COLD;
+
+private:
+ virtual void device_add_mconfig(machine_config &config) override ATTR_COLD;
+
+ required_device<ym2151_device> m_opm1;
+ required_device<ym2151_device> m_opm2;
+ required_device<ym2149_device> m_ssg;
+};
+
+DECLARE_DEVICE_TYPE(JMBX1, jmbx1_device)
+
+
+#endif // MAME_BUS_PC8801_JMBX1_H
diff --git a/src/devices/bus/pc8801/pc8801_23.cpp b/src/devices/bus/pc8801/pc8801_23.cpp
new file mode 100644
index 00000000000..6f73ca0ff76
--- /dev/null
+++ b/src/devices/bus/pc8801/pc8801_23.cpp
@@ -0,0 +1,89 @@
+// license:BSD-3-Clause
+// copyright-holders:Angelo Salese
+/**************************************************************************************************
+
+ NEC PC-8801-23 / -24 / -25 "Sound Board II"
+
+ TODO:
+ - Irq hangs if there's a PC-8801 OPN/OPNA declared in driver.
+ Master OPNA keeps sending acks in the correlated INT4 handler that hampers irq
+ signals from here;
+ - Confirm there's no DB9 joyport on any variants of this;
+
+**************************************************************************************************/
+
+#include "emu.h"
+#include "pc8801_23.h"
+
+DEFINE_DEVICE_TYPE(PC8801_23, pc8801_23_device, "pc8801_23", "NEC PC-8801-23 \"Sound Board II\"")
+
+pc8801_23_device::pc8801_23_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
+ : pc8801_exp_device(mconfig, PC8801_23, tag, owner, clock)
+ , m_opna(*this, "opna")
+{
+}
+
+void pc8801_23_device::io_map(address_map &map)
+{
+ map(0xa8, 0xa9).rw(m_opna, FUNC(ym2608_device::read), FUNC(ym2608_device::write));
+ map(0xaa, 0xaa).rw(FUNC(pc8801_23_device::irq_status_r), FUNC(pc8801_23_device::irq_mask_w));
+ map(0xac, 0xad).lrw8(
+ NAME([this] (offs_t offset) { return m_opna->read(offset | 2); }),
+ NAME([this] (offs_t offset, u8 data) { m_opna->write(offset | 2, data); })
+ );
+}
+
+void pc8801_23_device::opna_map(address_map &map)
+{
+ // TODO: confirm it really is ROMless
+ // TODO: confirm size
+ map(0x000000, 0x1fffff).ram();
+}
+
+void pc8801_23_device::device_add_mconfig(machine_config &config)
+{
+ constexpr XTAL sound_clock = XTAL(31'948'800) / 4;
+
+ YM2608(config, m_opna, sound_clock);
+ m_opna->set_addrmap(0, &pc8801_23_device::opna_map);
+ m_opna->irq_handler().set(FUNC(pc8801_23_device::int4_w));
+// m_opna->port_a_read_callback().set(FUNC(pc8801_23_device::opn_porta_r));
+// m_opna->port_b_read_callback().set_ioport("OPN_PB");
+ // TODO: per-channel mixing is unconfirmed
+ m_opna->add_route(0, "^^speaker", 0.75, 0);
+ m_opna->add_route(0, "^^speaker", 0.75, 1);
+ m_opna->add_route(1, "^^speaker", 0.75, 0);
+ m_opna->add_route(2, "^^speaker", 0.75, 1);
+}
+
+void pc8801_23_device::device_start()
+{
+ save_item(NAME(m_irq_mask));
+ save_item(NAME(m_irq_pending));
+}
+
+void pc8801_23_device::device_reset()
+{
+ m_irq_mask = true;
+ m_irq_pending = false;
+}
+
+u8 pc8801_23_device::irq_status_r()
+{
+ return 0x7f | (m_irq_mask << 7);
+}
+
+void pc8801_23_device::irq_mask_w(u8 data)
+{
+ m_irq_mask = bool(BIT(data, 7));
+
+ if (!m_irq_mask && m_irq_pending)
+ int4_w(m_irq_pending);
+}
+
+void pc8801_23_device::int4_w(int state)
+{
+ bool irq_state = (!m_irq_mask) & state;
+ pc8801_exp_device::int4_w(irq_state);
+ m_irq_pending = state;
+}
diff --git a/src/devices/bus/pc8801/pc8801_23.h b/src/devices/bus/pc8801/pc8801_23.h
new file mode 100644
index 00000000000..385a2080b54
--- /dev/null
+++ b/src/devices/bus/pc8801/pc8801_23.h
@@ -0,0 +1,42 @@
+// license:BSD-3-Clause
+// copyright-holders:Angelo Salese
+
+#ifndef MAME_BUS_PC8801_PC8801_23_H
+#define MAME_BUS_PC8801_PC8801_23_H
+
+#pragma once
+
+#include "pc8801_exp.h"
+#include "sound/ymopn.h"
+
+class pc8801_23_device : public pc8801_exp_device
+{
+public:
+ pc8801_23_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
+
+ static constexpr feature_type unemulated_features() { return feature::SOUND; }
+
+ virtual void io_map(address_map &map) override ATTR_COLD;
+
+protected:
+ virtual void device_start() override ATTR_COLD;
+ virtual void device_reset() override ATTR_COLD;
+ virtual void int4_w(int state) override;
+
+private:
+ virtual void device_add_mconfig(machine_config &config) override ATTR_COLD;
+
+ required_device<ym2608_device> m_opna;
+
+ u8 irq_status_r();
+ void irq_mask_w(u8 data);
+
+ bool m_irq_mask = false;
+ bool m_irq_pending = false;
+
+ void opna_map(address_map &map) ATTR_COLD;
+};
+
+DECLARE_DEVICE_TYPE(PC8801_23, pc8801_23_device)
+
+#endif // MAME_BUS_PC8801_PC8801_23_H
diff --git a/src/devices/bus/pc8801/pc8801_31.cpp b/src/devices/bus/pc8801/pc8801_31.cpp
new file mode 100644
index 00000000000..d125b9c9ad6
--- /dev/null
+++ b/src/devices/bus/pc8801/pc8801_31.cpp
@@ -0,0 +1,251 @@
+// license:BSD-3-Clause
+// copyright-holders:Angelo Salese
+/**************************************************************************************************
+
+ NEC PC8801-31 CD-ROM I/F
+
+ TODO:
+ - Interface with PC8801-30 (the actual CD drive);
+ - Make it a slot option for PC-8801MA (does it have same ROM as the internal MC version?)
+
+**************************************************************************************************/
+
+#include "emu.h"
+#include "pc8801_31.h"
+
+
+//**************************************************************************
+// GLOBAL VARIABLES
+//**************************************************************************
+
+
+// device type definition
+DEFINE_DEVICE_TYPE(PC8801_31, pc8801_31_device, "pc8801_31", "NEC PC8801-31 CD-ROM I/F")
+
+
+//**************************************************************************
+// LIVE DEVICE
+//**************************************************************************
+
+
+//-------------------------------------------------
+// pc8801_31_device - constructor
+//-------------------------------------------------
+
+
+pc8801_31_device::pc8801_31_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
+ : device_t(mconfig, PC8801_31, tag, owner, clock)
+ , m_scsibus(*this, "scsi")
+ , m_rom_bank_cb(*this)
+ , m_sel_off_timer(nullptr)
+{
+}
+
+
+//-------------------------------------------------
+// device_add_mconfig - device-specific machine
+// configuration addiitons
+//-------------------------------------------------
+
+static void pc8801_scsi_devices(device_slot_interface &device)
+{
+ // TODO: PC8801-30
+ device.option_add("cdrom", NSCSI_CDROM);
+ // TODO: at very least HxC Floppy emulator option
+}
+
+void pc8801_31_device::device_add_mconfig(machine_config &config)
+{
+ NSCSI_BUS(config, m_scsibus);
+ NSCSI_CONNECTOR(config, "scsi:0", pc8801_scsi_devices, "cdrom");
+ NSCSI_CONNECTOR(config, "scsi:1", pc8801_scsi_devices, nullptr);
+ NSCSI_CONNECTOR(config, "scsi:2", pc8801_scsi_devices, nullptr);
+ NSCSI_CONNECTOR(config, "scsi:3", pc8801_scsi_devices, nullptr);
+ NSCSI_CONNECTOR(config, "scsi:4", pc8801_scsi_devices, nullptr);
+ NSCSI_CONNECTOR(config, "scsi:5", pc8801_scsi_devices, nullptr);
+ NSCSI_CONNECTOR(config, "scsi:6", pc8801_scsi_devices, nullptr);
+ NSCSI_CONNECTOR(config, "scsi:7", pc8801_scsi_devices, nullptr);
+
+ SOFTWARE_LIST(config, "cd_list").set_original("pc8801_cdrom");
+}
+
+
+//-------------------------------------------------
+// device_start - device-specific startup
+//-------------------------------------------------
+
+void pc8801_31_device::device_start()
+{
+ m_sel_off_timer = timer_alloc(FUNC(pc8801_31_device::select_off), this);
+
+ save_item(NAME(m_clock_hb));
+ save_item(NAME(m_cddrive_enable));
+}
+
+
+//-------------------------------------------------
+// device_reset - device-specific reset
+//-------------------------------------------------
+
+
+void pc8801_31_device::device_reset()
+{
+ m_clock_hb = false;
+ m_cddrive_enable = false;
+
+ m_sel_off_timer->adjust(attotime::never);
+}
+
+TIMER_CALLBACK_MEMBER(pc8801_31_device::select_off)
+{
+ m_scsibus->ctrl_w(0, 0, nscsi_device::S_SEL);
+}
+
+
+
+//**************************************************************************
+// READ/WRITE HANDLERS
+//**************************************************************************
+
+
+void pc8801_31_device::amap(address_map &map)
+{
+ map(0x00, 0x00).rw(FUNC(pc8801_31_device::scsi_status_r), FUNC(pc8801_31_device::scsi_sel_w));
+ map(0x01, 0x01).lrw8(
+ NAME([this]() { return m_scsibus->data_r(); }),
+ NAME([this](u8 data) { m_scsibus->data_w(0, data); })
+ );
+ map(0x04, 0x04).w(FUNC(pc8801_31_device::scsi_reset_w));
+ map(0x08, 0x08).rw(FUNC(pc8801_31_device::clock_r), FUNC(pc8801_31_device::volume_control_w));
+ map(0x09, 0x09).rw(FUNC(pc8801_31_device::id_r), FUNC(pc8801_31_device::rom_bank_w));
+ map(0x0b, 0x0b).r(FUNC(pc8801_31_device::volume_meter_r));
+ map(0x0d, 0x0d).r(FUNC(pc8801_31_device::volume_meter_r));
+ map(0x0f, 0x0f).lw8(
+ NAME([this](u8 data) { m_cddrive_enable = bool(BIT(data, 0)); })
+ );
+}
+
+/*
+ * I/O Port $90
+ *
+ * x--- ---- BSY
+ * -x-- ---- REQ
+ * --x- ---- MSG
+ * ---x ---- CD
+ * ---- x--- IO
+ * ---- ---x CD-ROM drive status (from $9f)
+ *
+ * BIOS expects a bit 6 to go high then checks if (MSG | CD | IO) == CD.
+ * It eventually moves on floppy/BASIC fallback if this check fails.
+ *
+ */
+u8 pc8801_31_device::scsi_status_r()
+{
+ u32 ctrl = m_scsibus->ctrl_r();
+ return (
+ (ctrl & nscsi_device::S_BSY ? 0x80 : 0x00) |
+ (ctrl & nscsi_device::S_REQ ? 0x40 : 0x00) |
+ (ctrl & nscsi_device::S_MSG ? 0x20 : 0x00) |
+ (ctrl & nscsi_device::S_CTL ? 0x10 : 0x00) |
+ (ctrl & nscsi_device::S_INP ? 0x08 : 0x00) |
+ m_cddrive_enable
+ );
+}
+
+void pc8801_31_device::scsi_sel_w(u8 data)
+{
+ bool sel_on = bool(BIT(data, 0));
+ m_scsibus->ctrl_w(
+ 0,
+ sel_on ? nscsi_device::S_SEL : 0,
+ nscsi_device::S_SEL
+ );
+
+ // TODO: timing
+ if (sel_on)
+ m_sel_off_timer->adjust(attotime::from_usec(10));
+}
+
+/*
+ * I/O Port $98
+ *
+ * x--- ---- (r/o?) device clock heartbeat?
+ * ---- -xxx (w/o?) CD-DA volume control (not unlike PCE)
+ * ---- -00x enable
+ * ---- -01x disable
+ * ---- -100 fade-in short (100 msec)
+ * ---- -101 fade-in long (1500 msec)
+ * ---- -110 fade-out short (100 msec)
+ * ---- -111 fade-out long (1500 msec)
+ *
+ */
+u8 pc8801_31_device::clock_r()
+{
+ // Checked 11 times on POST before giving up, definitely some kind of timing-based CD-ROM or board identification.
+ // If check passes the BIOS goes on with the "CD-System initialize\n[Space]->CD player" screen.
+ // A similar PCE pattern is mapped as "CDDA data select".
+ // There's no way to load floppies with this always on unless STOP key is held on boot (which doesn't look convenient).
+ // TODO: identify source and verify how much fast this really is.
+ m_clock_hb ^= 1;
+ return m_clock_hb << 7;
+}
+
+void pc8801_31_device::volume_control_w(u8 data)
+{
+ logerror("%s: volume_w %02x\n", machine().describe_context(), data);
+}
+
+/*
+ * I/O Port $94
+ *
+ * x--- ---- to SCSI RST
+ *
+ */
+void pc8801_31_device::scsi_reset_w(u8 data)
+{
+ m_scsibus->ctrl_w(
+ 0,
+ BIT(data, 7) ? nscsi_device::S_RST : 0,
+ nscsi_device::S_RST
+ );
+}
+
+u8 pc8801_31_device::id_r()
+{
+ // PC=A9AA CD-Player checks this against 0xcd, branches with $71 bit 0 set (N88 extended ROM bank)
+ // Identifier for a 8801MC?
+ logerror("%s: id_r\n", machine().describe_context());
+ return 0xcd;
+}
+
+/*
+ * I/O Port $99
+ *
+ * ---x ---- CD-ROM BIOS bank
+ * ---- ---x CD-ROM E-ROM bank (?)
+ *
+ */
+void pc8801_31_device::rom_bank_w(u8 data)
+{
+ m_rom_bank_cb(bool(BIT(data, 4)));
+
+ if (data & 0xef)
+ logerror("%s: rom_bank_w %02x\n", machine().describe_context(), data);
+}
+
+/*
+ * I/O Port $9b / $9d CDDA Left/Right output meter
+ *
+ * ?xxx xx-- L/R metering
+ *
+ * M88 hardwires this as 0x3c, CD player shows arbitrary clamp with
+ * timed flicker on ticks depending on the value read.
+ * i.e. a value of 0x70 will make the uppermost tick to flicker more than 0x74,
+ * while 0x7c won't flicker at all
+ *
+ */
+// TODO: templatìze, measure via real HW tests
+u8 pc8801_31_device::volume_meter_r()
+{
+ return 0;
+}
diff --git a/src/devices/bus/pc8801/pc8801_31.h b/src/devices/bus/pc8801/pc8801_31.h
new file mode 100644
index 00000000000..cc68677ca6d
--- /dev/null
+++ b/src/devices/bus/pc8801/pc8801_31.h
@@ -0,0 +1,66 @@
+// license:BSD-3-Clause
+// copyright-holders:Angelo Salese
+/**************************************************************************************************
+
+ NEC PC8801-31 CD-ROM I/F
+
+**************************************************************************************************/
+
+#ifndef MAME_BUS_PC8801_PC8801_31_H
+#define MAME_BUS_PC8801_PC8801_31_H
+
+#pragma once
+
+#include "machine/nscsi_bus.h"
+#include "bus/nscsi/cd.h"
+
+//**************************************************************************
+// TYPE DEFINITIONS
+//**************************************************************************
+
+class pc8801_31_device : public device_t
+{
+public:
+ // construction/destruction
+ pc8801_31_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
+
+ static constexpr feature_type unemulated_features() { return feature::DISK; }
+
+ auto rom_bank_cb() { return m_rom_bank_cb.bind(); }
+
+ // I/O operations
+ void amap(address_map &map) ATTR_COLD;
+
+protected:
+ // device_t implementation
+ 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;
+
+ TIMER_CALLBACK_MEMBER(select_off);
+
+private:
+ required_device<nscsi_bus_device> m_scsibus;
+
+ devcb_write_line m_rom_bank_cb;
+
+ emu_timer *m_sel_off_timer;
+
+ u8 scsi_status_r();
+ void scsi_sel_w(u8 data);
+ void scsi_reset_w(u8 data);
+ u8 clock_r();
+ void volume_control_w(u8 data);
+ u8 id_r();
+ void rom_bank_w(u8 data);
+ u8 volume_meter_r();
+
+ bool m_clock_hb;
+ bool m_cddrive_enable;
+};
+
+
+// device type definition
+DECLARE_DEVICE_TYPE(PC8801_31, pc8801_31_device)
+
+#endif // MAME_BUS_PC8801_PC8801_31_H
diff --git a/src/devices/bus/pc8801/pc8801_exp.cpp b/src/devices/bus/pc8801/pc8801_exp.cpp
new file mode 100644
index 00000000000..cf975c17d44
--- /dev/null
+++ b/src/devices/bus/pc8801/pc8801_exp.cpp
@@ -0,0 +1,94 @@
+// license:BSD-3-Clause
+// copyright-holders:Angelo Salese
+/**************************************************************************************************
+
+ PC-8801 EXPansion bus
+
+ 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);
+
+**************************************************************************************************/
+
+#include "emu.h"
+#include "pc8801_exp.h"
+
+DEFINE_DEVICE_TYPE(PC8801_EXP_SLOT, pc8801_exp_slot_device, "pc8801_exp_slot", "PC-8801 Expansion Slot")
+
+pc8801_exp_slot_device::pc8801_exp_slot_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
+ : device_t(mconfig, PC8801_EXP_SLOT, tag, owner, clock)
+ , device_single_card_slot_interface<device_pc8801_exp_interface>(mconfig, *this)
+ , m_iospace(*this, finder_base::DUMMY_TAG, -1)
+ , m_int3_cb(*this)
+ , m_int4_cb(*this)
+ , m_int5_cb(*this)
+{
+}
+
+pc8801_exp_slot_device::~pc8801_exp_slot_device()
+{
+}
+
+void pc8801_exp_slot_device::device_start()
+{
+}
+
+device_pc8801_exp_interface::device_pc8801_exp_interface(const machine_config &mconfig, device_t &device)
+ : device_interface(device, "pc8801exp")
+{
+ m_slot = dynamic_cast<pc8801_exp_slot_device *>(device.owner());
+}
+
+device_pc8801_exp_interface::~device_pc8801_exp_interface()
+{
+}
+
+void device_pc8801_exp_interface::interface_pre_start()
+{
+ if (!m_slot->started())
+ throw device_missing_dependencies();
+}
+
+void device_pc8801_exp_interface::interface_post_start()
+{
+ m_slot->install_io_device(*this, &device_pc8801_exp_interface::io_map);
+}
+
+// generic passthroughs to INT* lines
+// NB: clients are responsible to handle irq masking just like base HW if available
+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)
+ , device_pc8801_exp_interface(mconfig, *this)
+{
+}
+
+void pc8801_exp_device::device_start()
+{
+
+}
+
+
+
+// slot devices
+#include "gsx8800.h"
+#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);
+ device.option_add("gsx8800", GSX8800);
+}
diff --git a/src/devices/bus/pc8801/pc8801_exp.h b/src/devices/bus/pc8801/pc8801_exp.h
new file mode 100644
index 00000000000..b393fc8c40a
--- /dev/null
+++ b/src/devices/bus/pc8801/pc8801_exp.h
@@ -0,0 +1,94 @@
+// license:BSD-3-Clause
+// copyright-holders:Angelo Salese
+
+#ifndef MAME_BUS_PC8801_PC8801_EXP_H
+#define MAME_BUS_PC8801_PC8801_EXP_H
+
+#pragma once
+
+class device_pc8801_exp_interface;
+class pc8801_exp_device;
+
+class pc8801_exp_slot_device : public device_t, public device_single_card_slot_interface<device_pc8801_exp_interface>
+{
+ friend class device_pc8801_exp_interface;
+public:
+ // construction/destruction
+ template <typename T>
+ pc8801_exp_slot_device(machine_config const &mconfig, char const *tag, device_t *owner, T &&opts, char const *dflt)
+ : pc8801_exp_slot_device(mconfig, tag, owner, (uint32_t)0)
+ {
+ option_reset();
+ opts(*this);
+ set_default_option(dflt);
+ set_fixed(false);
+ }
+ pc8801_exp_slot_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
+ virtual ~pc8801_exp_slot_device();
+
+ template <typename T> void set_iospace(T &&tag, int spacenum) { m_iospace.set_tag(std::forward<T>(tag), spacenum); }
+
+ template<typename T> void install_io_device(T &device, void (T::*map)(class address_map &map))
+ {
+ m_iospace->install_device(0x00, 0xff, device, map);
+ }
+
+ auto int3_callback() { return m_int3_cb.bind(); }
+ auto int4_callback() { return m_int4_cb.bind(); }
+ auto int5_callback() { return m_int5_cb.bind(); }
+
+protected:
+ // device_t implementation
+ virtual void device_start() override ATTR_COLD;
+
+private:
+ required_address_space m_iospace;
+
+// device_pc8801_exp_interface *m_exp;
+
+ devcb_write_line m_int3_cb;
+ devcb_write_line m_int4_cb;
+ devcb_write_line m_int5_cb;
+};
+
+class device_pc8801_exp_interface : public device_interface
+{
+public:
+ // construction/destruction
+ virtual ~device_pc8801_exp_interface();
+
+ virtual void io_map(address_map &map) { }
+
+protected:
+ device_pc8801_exp_interface(const machine_config &mconfig, device_t &device);
+
+ virtual void interface_pre_start() override;
+ virtual void interface_post_start() override;
+
+ pc8801_exp_slot_device *m_slot;
+
+ 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
+{
+public:
+ // construction/destruction
+ pc8801_exp_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock);
+
+
+protected:
+// virtual void device_add_mconfig(machine_config &config) override ATTR_COLD;
+ virtual void device_start() override ATTR_COLD;
+
+
+};
+
+// device type definition
+DECLARE_DEVICE_TYPE(PC8801_EXP_SLOT, pc8801_exp_slot_device)
+
+void pc8801_exp_devices(device_slot_interface &device);
+
+#endif // MAME_MACHINE_PC8801_PC8801_EXP_H
diff --git a/src/devices/bus/pc8801/pcg8100.cpp b/src/devices/bus/pc8801/pcg8100.cpp
new file mode 100644
index 00000000000..f97c6a36d9f
--- /dev/null
+++ b/src/devices/bus/pc8801/pcg8100.cpp
@@ -0,0 +1,109 @@
+// license:BSD-3-Clause
+// copyright-holders:Angelo Salese
+/**************************************************************************************************
+
+ HAL PCG-8100
+
+ Used on a bunch of PC-8001 games, adds a Programmable Character Generator overlay,
+ a write-only 8253 with channels tied to three DAC1BIT
+
+**************************************************************************************************/
+
+#include "emu.h"
+#include "pcg8100.h"
+
+
+DEFINE_DEVICE_TYPE(PCG8100, pcg8100_device, "pcg8100", "HAL Laboratory PCG-8100")
+
+pcg8100_device::pcg8100_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
+ : pc8801_exp_device(mconfig, PCG8100, tag, owner, clock)
+ , m_pit(*this, "pit")
+ , m_dac1bit(*this, "dac1bit%u", 0L)
+ , m_cg_rom(*this, "^^cgrom")
+{
+}
+
+void pcg8100_device::io_map(address_map &map)
+{
+ map(0x00, 0x00).lw8(NAME([this] (u8 data) { m_pcg_data = data; }));
+ map(0x01, 0x01).lw8(NAME([this] (u8 data) { m_pcg_address = (m_pcg_address & 0x300) | data; }));
+ map(0x02, 0x02).w(FUNC(pcg8100_device::pcg_latch_w));
+ map(0x0c, 0x0f).w(m_pit, FUNC(pit8253_device::write));
+}
+
+void pcg8100_device::device_add_mconfig(machine_config &config)
+{
+ constexpr XTAL pcg_clock = XTAL(31'948'800) / 8;
+
+ PIT8253(config, m_pit, 0);
+ m_pit->set_clk<0>(pcg_clock);
+ m_pit->out_handler<0>().set(m_dac1bit[0], FUNC(speaker_sound_device::level_w));
+ m_pit->set_clk<1>(pcg_clock);
+ m_pit->out_handler<1>().set(m_dac1bit[1], FUNC(speaker_sound_device::level_w));
+ m_pit->set_clk<2>(pcg_clock);
+ m_pit->out_handler<2>().set(m_dac1bit[2], FUNC(speaker_sound_device::level_w));
+
+ for (auto &dac1bit : m_dac1bit)
+ {
+ SPEAKER_SOUND(config, dac1bit);
+ dac1bit->add_route(ALL_OUTPUTS, "^^speaker", 0.25, 0);
+ dac1bit->add_route(ALL_OUTPUTS, "^^speaker", 0.25, 1);
+ }
+}
+
+void pcg8100_device::device_start()
+{
+ save_item(NAME(m_pcg_data));
+ save_item(NAME(m_pcg_address));
+
+ // PCG overlays directly to the internal PC-8001 3301 CG ROM base.
+ // Save a local copy of the original data here, card can eventually restore data at later time.
+ for (int i = 0x000; i < 0x400; i++)
+ m_original_rom[i] = m_cg_rom[i | 0x400];
+
+ save_item(NAME(m_original_rom));
+}
+
+void pcg8100_device::device_reset()
+{
+ int i;
+ m_pcg_data = 0;
+ m_pcg_address = 0;
+ m_pcg_latch = 0;
+
+ for (i = 0x000; i < 0x400; i++)
+ m_cg_rom[i | 0x400] = m_original_rom[i];
+
+ for (i = 0; i < 3; i++)
+ audio_channel(i, false);
+}
+
+void pcg8100_device::audio_channel(u8 ch, bool keyon)
+{
+ m_dac1bit[ch]->set_output_gain(0, keyon ? 1.0 : 0.0);
+}
+
+/*
+ * x--- ---- DAC1BIT #2
+ * -x-- ---- DAC1BIT #1
+ * --x- ---- (0) select overlay on latch (1) select PC-8001/PC-8801 original CG ROM
+ * ---x ---- latch data into current PCG address RAM
+ * ---- x--- DAC1BIT #0
+ * ---- --xx upper PCG address
+ */
+void pcg8100_device::pcg_latch_w(u8 data)
+{
+ if (BIT(m_pcg_latch, 4) && !(BIT(data, 4)))
+ {
+ if (BIT(m_pcg_latch, 5))
+ m_cg_rom[0x400 | m_pcg_address] = m_original_rom[m_pcg_address];
+ else
+ m_cg_rom[0x400 | m_pcg_address] = m_pcg_data;
+ }
+ m_pcg_address = (m_pcg_address & 0xff) | ((data & 0x3) << 8);
+ m_pcg_latch = data;
+
+ audio_channel(0, bool(BIT(data, 3)));
+ audio_channel(1, bool(BIT(data, 6)));
+ audio_channel(2, bool(BIT(data, 7)));
+}
diff --git a/src/devices/bus/pc8801/pcg8100.h b/src/devices/bus/pc8801/pcg8100.h
new file mode 100644
index 00000000000..0fc6f84eea7
--- /dev/null
+++ b/src/devices/bus/pc8801/pcg8100.h
@@ -0,0 +1,44 @@
+// license:BSD-3-Clause
+// copyright-holders:Angelo Salese
+
+#ifndef MAME_BUS_PC8801_PCG8100_H
+#define MAME_BUS_PC8801_PCG8100_H
+
+#pragma once
+
+#include "pc8801_exp.h"
+#include "machine/pit8253.h"
+#include "sound/spkrdev.h"
+
+class pcg8100_device : public pc8801_exp_device
+{
+public:
+ pcg8100_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
+
+ virtual void io_map(address_map &map) override ATTR_COLD;
+
+protected:
+ virtual void device_start() override ATTR_COLD;
+ virtual void device_reset() override ATTR_COLD;
+
+private:
+ virtual void device_add_mconfig(machine_config &config) override ATTR_COLD;
+
+ u8 m_pcg_data = 0;
+ u16 m_pcg_address = 0;
+ u8 m_pcg_latch = 0;
+
+ void pcg_latch_w(u8 data);
+
+ required_device<pit8253_device> m_pit;
+ required_device_array<speaker_sound_device, 3> m_dac1bit;
+
+ required_region_ptr<u8> m_cg_rom;
+ std::array<u8, 0x400> m_original_rom;
+ void audio_channel(u8 ch, bool keyon);
+};
+
+DECLARE_DEVICE_TYPE(PCG8100, pcg8100_device)
+
+
+#endif // MAME_BUS_PC8801_JMBX1_H
diff --git a/src/devices/bus/pc_joy/pc_joy.cpp b/src/devices/bus/pc_joy/pc_joy.cpp
index 3e59be3a86c..98bd20deaef 100644
--- a/src/devices/bus/pc_joy/pc_joy.cpp
+++ b/src/devices/bus/pc_joy/pc_joy.cpp
@@ -10,13 +10,14 @@
#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")
pc_joy_device::pc_joy_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) :
device_t(mconfig, PC_JOY, tag, owner, clock),
- device_slot_interface(mconfig, *this),
+ device_single_card_slot_interface<device_pc_joy_interface>(mconfig, *this),
m_dev(nullptr)
{
option_reset();
@@ -25,7 +26,7 @@ pc_joy_device::pc_joy_device(const machine_config &mconfig, const char *tag, dev
set_fixed(false);
}
-READ8_MEMBER ( pc_joy_device::joy_port_r )
+uint8_t pc_joy_device::joy_port_r()
{
int delta = ((machine().time() - m_stime) * 256 * 2325).seconds();
@@ -35,7 +36,7 @@ READ8_MEMBER ( pc_joy_device::joy_port_r )
return (m_dev->btn() << 4) | (m_dev->y2(delta) << 3) | (m_dev->x2(delta) << 2) | (m_dev->y1(delta) << 1) | m_dev->x1(delta);
}
-WRITE8_MEMBER ( pc_joy_device::joy_port_w )
+void pc_joy_device::joy_port_w(uint8_t data)
{
m_stime = machine().time();
if(!m_dev)
@@ -45,11 +46,11 @@ WRITE8_MEMBER ( pc_joy_device::joy_port_w )
void pc_joy_device::device_config_complete()
{
- m_dev = dynamic_cast<device_pc_joy_interface *>(get_card_device());
+ m_dev = get_card_device();
}
device_pc_joy_interface::device_pc_joy_interface(const machine_config &mconfig, device_t &device) :
- device_slot_card_interface(mconfig, device)
+ device_interface(device, "pcjoy")
{
}
@@ -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 66729b76fc4..0593325817f 100644
--- a/src/devices/bus/pc_joy/pc_joy.h
+++ b/src/devices/bus/pc_joy/pc_joy.h
@@ -16,7 +16,7 @@
void pc_joysticks(device_slot_interface &device);
-class device_pc_joy_interface : public device_slot_card_interface
+class device_pc_joy_interface : public device_interface
{
public:
virtual ~device_pc_joy_interface();
@@ -32,13 +32,13 @@ protected:
device_pc_joy_interface(const machine_config &mconfig, device_t &device);
};
-class pc_joy_device : public device_t, public device_slot_interface
+class pc_joy_device : public device_t, public device_single_card_slot_interface<device_pc_joy_interface>
{
public:
pc_joy_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock = 0);
- DECLARE_READ8_MEMBER(joy_port_r);
- DECLARE_WRITE8_MEMBER(joy_port_w);
+ uint8_t joy_port_r();
+ void joy_port_w(uint8_t data);
protected:
virtual void device_start() override { m_stime = machine().time(); }
@@ -56,7 +56,7 @@ class pc_basic_joy_device : public device_t,
{
public:
pc_basic_joy_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock = 0);
- virtual ioport_constructor device_input_ports() const override;
+ virtual ioport_constructor device_input_ports() const override ATTR_COLD;
virtual uint8_t x1(int delta) override { return (m_x1->read() > delta); }
virtual uint8_t x2(int delta) override { return (m_x2->read() > delta); }
@@ -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..c6af086819b
--- /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_PC_JOY_MAGNUM6_H
+#define MAME_BUS_PC_JOY_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 ATTR_COLD;
+};
+
+DECLARE_DEVICE_TYPE(PC_MAGNUM6_PAD, pc_joy_magnum6_device)
+
+#endif // MAME_BUS_PC_JOY_PC_JOY_MAGNUM6_H
diff --git a/src/devices/bus/pc_joy/pc_joy_sw.cpp b/src/devices/bus/pc_joy/pc_joy_sw.cpp
index 0fbe1e67e45..8c9b2c75d4b 100644
--- a/src/devices/bus/pc_joy/pc_joy_sw.cpp
+++ b/src/devices/bus/pc_joy/pc_joy_sw.cpp
@@ -24,7 +24,7 @@ pc_mssw_pad_device::pc_mssw_pad_device(const machine_config& mconfig, const char
void pc_mssw_pad_device::device_start()
{
- m_timer = timer_alloc();
+ m_timer = timer_alloc(FUNC(pc_mssw_pad_device::timer_tick), this);
}
void pc_mssw_pad_device::device_reset()
@@ -35,7 +35,7 @@ void pc_mssw_pad_device::device_reset()
m_timer->adjust(attotime::never, 0);
}
-void pc_mssw_pad_device::device_timer(emu_timer &timer, device_timer_id tid, int param, void *ptr)
+TIMER_CALLBACK_MEMBER(pc_mssw_pad_device::timer_tick)
{
uint16_t pad_state = 0;
// only multibit mode for now
diff --git a/src/devices/bus/pc_joy/pc_joy_sw.h b/src/devices/bus/pc_joy/pc_joy_sw.h
index cb76b268a36..6083dbec589 100644
--- a/src/devices/bus/pc_joy/pc_joy_sw.h
+++ b/src/devices/bus/pc_joy/pc_joy_sw.h
@@ -10,16 +10,17 @@ class pc_mssw_pad_device : public device_t,
{
public:
pc_mssw_pad_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
- virtual ioport_constructor device_input_ports() const override;
+ virtual ioport_constructor device_input_ports() const override ATTR_COLD;
virtual uint8_t btn() override { return m_state; }
// timing is guessed, calibrated for at486
virtual void port_write() override { if(!m_active) { m_timer->adjust(attotime::from_usec(50), 0, attotime::from_usec(5)); m_active = true; } }
protected:
- virtual void device_start() override;
- virtual void device_reset() override;
- virtual void device_timer(emu_timer &timer, device_timer_id tid, int param, void *ptr) override;
+ virtual void device_start() override ATTR_COLD;
+ virtual void device_reset() override ATTR_COLD;
+
+ TIMER_CALLBACK_MEMBER(timer_tick);
private:
required_ioport m_btn1;
diff --git a/src/devices/bus/pc_kbd/cherry_mx1500.cpp b/src/devices/bus/pc_kbd/cherry_mx1500.cpp
new file mode 100644
index 00000000000..c0f796d40e6
--- /dev/null
+++ b/src/devices/bus/pc_kbd/cherry_mx1500.cpp
@@ -0,0 +1,333 @@
+// license:BSD-3-Clause
+// copyright-holders:AJR
+/***************************************************************************
+
+ Cherry MX 1500 101/102-key keyboards
+
+ These AT and PS/2-compatible keyboards have a built-in smartcard reader
+ programmed to read medical cards. The electrical interface is nominally
+ ISO 7816-2 compliant, but none of the three supported synchronous
+ protocols adheres to the ISO 7816-3 standard. (One of these formats
+ appears to be simply a 24C04 I²C EEPROM.) The three LEDs at the top
+ right of the keyboard (Error, Data, Power) are related to the smartcard
+ reader, as are several undocumented keyboard commands. All this
+ additional functionality is currently unemulated.
+
+***************************************************************************/
+
+#include "emu.h"
+#include "cherry_mx1500.h"
+
+#include "cpu/mcs51/mcs51.h"
+
+
+// device type definition
+DEFINE_DEVICE_TYPE(CHERRY_G80_1500, cherry_g80_1500_device, "g80_1500", "Cherry G80-1500 Multi-Function Keyboard")
+
+cherry_g80_1500_device::cherry_g80_1500_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock)
+ : device_t(mconfig, CHERRY_G80_1500, tag, owner, clock)
+ , device_pc_kbd_interface(mconfig, *this)
+ , m_mcu(*this, "mcu")
+ , m_keys(*this, "ROW%u", 0U)
+ , m_leds(*this, "led%u", 0U)
+ , m_p1(0xff)
+{
+}
+
+void cherry_g80_1500_device::device_start()
+{
+ m_leds.resolve();
+
+ set_pc_kbdc_device();
+
+ save_item(NAME(m_p1));
+}
+
+
+static INPUT_PORTS_START(g80_1500)
+ PORT_START("CONFIG")
+ PORT_CONFNAME(3, 0, "Layout")
+ PORT_CONFSETTING(0, "US-International (G80-1500 HAU)")
+ PORT_CONFSETTING(1, "German (G80-1500 HAD)")
+ PORT_CONFSETTING(2, "French (G80-1500 HAF)")
+ //PORT_CONFSETTING(3, "UK-English (G80-1500 HAG)")
+
+ PORT_START("ROW0")
+ 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(ASTERISK)) PORT_CODE(KEYCODE_ASTERISK)
+ PORT_BIT(0x04, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CHAR(UCHAR_MAMEKEY(PLUS_PAD)) PORT_CODE(KEYCODE_PLUS_PAD)
+ PORT_BIT(0x08, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CHAR(',') PORT_CHAR('<') PORT_CODE(KEYCODE_COMMA) PORT_CONDITION("CONFIG", 3, EQUALS, 0)
+ PORT_BIT(0x08, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CHAR(',') PORT_CHAR(';') PORT_CODE(KEYCODE_COMMA) PORT_CONDITION("CONFIG", 3, EQUALS, 1)
+ PORT_BIT(0x08, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CHAR(';') PORT_CHAR('.') PORT_CODE(KEYCODE_COMMA) PORT_CONDITION("CONFIG", 3, EQUALS, 2)
+ PORT_BIT(0x10, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("L") PORT_CHAR('l') PORT_CHAR('L') PORT_CODE(KEYCODE_L)
+ 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(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")
+ 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(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(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)
+ PORT_BIT(0x40, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CHAR('8') PORT_CHAR('*') PORT_CODE(KEYCODE_8) PORT_CONDITION("CONFIG", 3, EQUALS, 0)
+ PORT_BIT(0x40, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CHAR('8') PORT_CHAR('(') PORT_CHAR('[') PORT_CODE(KEYCODE_8) PORT_CONDITION("CONFIG", 3, EQUALS, 1)
+ PORT_BIT(0x40, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CHAR('_') PORT_CHAR('8') PORT_CHAR('\\') PORT_CODE(KEYCODE_8) PORT_CONDITION("CONFIG", 3, EQUALS, 2)
+ PORT_BIT(0x80, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CHAR(UCHAR_MAMEKEY(DEL_PAD)) PORT_CODE(KEYCODE_DEL_PAD)
+
+ PORT_START("ROW2")
+ PORT_BIT(0x01, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CHAR(UCHAR_MAMEKEY(F10)) PORT_CODE(KEYCODE_F10)
+ PORT_BIT(0x02, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CHAR(UCHAR_MAMEKEY(PGUP)) PORT_CODE(KEYCODE_PGUP)
+ PORT_BIT(0x04, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CHAR(UCHAR_MAMEKEY(PGDN)) PORT_CODE(KEYCODE_PGDN)
+ 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(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(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_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)
+
+ PORT_START("ROW3")
+ 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_CHAR(UCHAR_MAMEKEY(HOME)) PORT_CODE(KEYCODE_HOME)
+ 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(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_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_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(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")
+ PORT_BIT(0x01, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CHAR(UCHAR_MAMEKEY(F8)) PORT_CODE(KEYCODE_F8)
+ PORT_BIT(0x02, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CHAR(UCHAR_MAMEKEY(SLASH_PAD)) PORT_CODE(KEYCODE_SLASH_PAD)
+ PORT_BIT(0x04, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CHAR(UCHAR_MAMEKEY(1_PAD)) PORT_CODE(KEYCODE_1_PAD)
+ PORT_BIT(0x08, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CHAR('.') PORT_CHAR('>') PORT_CODE(KEYCODE_STOP) PORT_CONDITION("CONFIG", 3, EQUALS, 0)
+ 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(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(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")
+ 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(9_PAD)) PORT_CODE(KEYCODE_9_PAD)
+ PORT_BIT(0x04, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CHAR(UCHAR_MAMEKEY(6_PAD)) PORT_CODE(KEYCODE_6_PAD)
+ 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_NAME("J") PORT_CHAR('j') PORT_CHAR('J') PORT_CODE(KEYCODE_J)
+ 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(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")
+ 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(7_PAD)) PORT_CODE(KEYCODE_7_PAD)
+ PORT_BIT(0x04, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CHAR(UCHAR_MAMEKEY(UP)) PORT_CODE(KEYCODE_UP)
+ 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_NAME("F") PORT_CHAR('f') PORT_CHAR('F') PORT_CODE(KEYCODE_F)
+ 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('4') PORT_CHAR('$') PORT_CODE(KEYCODE_4) PORT_CONDITION("CONFIG", 3, NOTEQUALS, 2)
+ PORT_BIT(0x40, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CHAR('\'') PORT_CHAR('4') PORT_CHAR('{') PORT_CODE(KEYCODE_4) PORT_CONDITION("CONFIG", 3, EQUALS, 2)
+ PORT_BIT(0x80, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CHAR(UCHAR_MAMEKEY(F1)) PORT_CODE(KEYCODE_F1)
+
+ PORT_START("ROW7")
+ PORT_BIT(0x01, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CHAR(UCHAR_MAMEKEY(PRTSCR)) PORT_CODE(KEYCODE_PRTSCR)
+ 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(2_PAD)) PORT_CODE(KEYCODE_2_PAD)
+ 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_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(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)
+
+ PORT_START("ROW8")
+ PORT_BIT(0x01, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CHAR(UCHAR_MAMEKEY(SCRLOCK)) PORT_CODE(KEYCODE_SCRLOCK)
+ PORT_BIT(0x02, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CHAR(UCHAR_MAMEKEY(PAUSE)) PORT_CODE(KEYCODE_PAUSE)
+ PORT_BIT(0x04, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CHAR(UCHAR_MAMEKEY(5_PAD)) PORT_CODE(KEYCODE_5_PAD)
+ PORT_BIT(0x08, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("Z") PORT_CHAR('z') PORT_CHAR('Z') PORT_CODE(KEYCODE_Z) PORT_CONDITION("CONFIG", 3, EQUALS, 0)
+ PORT_BIT(0x08, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("Y") PORT_CHAR('y') PORT_CHAR('Y') PORT_CODE(KEYCODE_Z) PORT_CONDITION("CONFIG", 3, EQUALS, 1)
+ PORT_BIT(0x08, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("W") PORT_CHAR('w') PORT_CHAR('W') PORT_CODE(KEYCODE_Z) PORT_CONDITION("CONFIG", 3, EQUALS, 2)
+ 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_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(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")
+ PORT_BIT(0x01, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CHAR(UCHAR_MAMEKEY(F12)) PORT_CODE(KEYCODE_F12)
+ PORT_BIT(0x02, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CHAR(UCHAR_MAMEKEY(INSERT)) PORT_CODE(KEYCODE_INSERT)
+ PORT_BIT(0x04, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CHAR(UCHAR_MAMEKEY(DEL)) PORT_CODE(KEYCODE_DEL)
+ PORT_BIT(0x08, IP_ACTIVE_LOW, IPT_UNUSED) PORT_CONDITION("CONFIG", 3, EQUALS, 0) // INT 1 key
+ PORT_BIT(0x08, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CHAR('<') PORT_CHAR('>') PORT_CHAR('|') PORT_CODE(KEYCODE_BACKSLASH2) PORT_CONDITION("CONFIG", 3, EQUALS, 1)
+ PORT_BIT(0x08, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CHAR('<') PORT_CHAR('>') PORT_CODE(KEYCODE_BACKSLASH2) PORT_CONDITION("CONFIG", 3, EQUALS, 2)
+ PORT_BIT(0x10, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("A") PORT_CHAR('a') PORT_CHAR('A') PORT_CODE(KEYCODE_A) PORT_CONDITION("CONFIG", 3, NOTEQUALS, 2)
+ PORT_BIT(0x10, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("Q") PORT_CHAR('q') PORT_CHAR('Q') PORT_CODE(KEYCODE_A) PORT_CONDITION("CONFIG", 3, EQUALS, 2)
+ PORT_BIT(0x20, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("Q") PORT_CHAR('q') PORT_CHAR('Q') PORT_CODE(KEYCODE_Q) PORT_CONDITION("CONFIG", 3, EQUALS, 0)
+ PORT_BIT(0x20, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("Q @") PORT_CHAR('q') PORT_CHAR('Q') PORT_CHAR('@') PORT_CODE(KEYCODE_Q) PORT_CONDITION("CONFIG", 3, EQUALS, 1)
+ PORT_BIT(0x20, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("A") PORT_CHAR('a') PORT_CHAR('A') PORT_CODE(KEYCODE_Q) PORT_CONDITION("CONFIG", 3, EQUALS, 2)
+ PORT_BIT(0x40, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CHAR('1') PORT_CHAR('!') PORT_CODE(KEYCODE_1) PORT_CONDITION("CONFIG", 3, NOTEQUALS, 2)
+ PORT_BIT(0x40, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CHAR('&') PORT_CHAR('1') PORT_CODE(KEYCODE_1) PORT_CONDITION("CONFIG", 3, EQUALS, 2)
+ PORT_BIT(0x80, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CHAR(UCHAR_MAMEKEY(LCONTROL)) PORT_CODE(KEYCODE_LCONTROL)
+
+ PORT_START("ROW10")
+ PORT_BIT(0x01, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CHAR(UCHAR_MAMEKEY(F11)) PORT_CODE(KEYCODE_F11)
+ PORT_BIT(0x02, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CHAR(0x08) PORT_CODE(KEYCODE_BACKSPACE)
+ PORT_BIT(0x04, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CHAR(0x0d) PORT_CODE(KEYCODE_ENTER)
+ PORT_BIT(0x08, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CHAR(UCHAR_SHIFT_1) PORT_CODE(KEYCODE_LSHIFT)
+ 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(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")
+ 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(NUMLOCK)) PORT_CODE(KEYCODE_NUMLOCK)
+ PORT_BIT(0x04, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CHAR(UCHAR_MAMEKEY(4_PAD)) PORT_CODE(KEYCODE_4_PAD)
+ 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_NAME("G") PORT_CHAR('g') PORT_CHAR('G') PORT_CODE(KEYCODE_G)
+ 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('5') PORT_CHAR('%') PORT_CODE(KEYCODE_5) PORT_CONDITION("CONFIG", 3, NOTEQUALS, 2)
+ PORT_BIT(0x40, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CHAR('(') PORT_CHAR('5') PORT_CHAR('[') PORT_CODE(KEYCODE_5) PORT_CONDITION("CONFIG", 3, EQUALS, 2)
+ PORT_BIT(0x80, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CHAR(UCHAR_MAMEKEY(RALT)) PORT_CODE(KEYCODE_RALT) PORT_CONDITION("CONFIG", 3, EQUALS, 0)
+ PORT_BIT(0x80, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("Alt Gr") PORT_CHAR(UCHAR_SHIFT_2) PORT_CODE(KEYCODE_RALT) PORT_CONDITION("CONFIG", 3, NOTEQUALS, 0)
+
+ PORT_START("ROW12")
+ 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('\\') PORT_CHAR('|') PORT_CODE(KEYCODE_BACKSLASH) PORT_CONDITION("CONFIG", 3, EQUALS, 0)
+ PORT_BIT(0x02, IP_ACTIVE_LOW, IPT_UNUSED) PORT_CONDITION("CONFIG", 3, NOTEQUALS, 0)
+ PORT_BIT(0x04, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("B") PORT_CHAR('b') PORT_CHAR('B') PORT_CODE(KEYCODE_B)
+ PORT_BIT(0x08, IP_ACTIVE_HIGH, IPT_UNKNOWN) // smartcard-related
+ 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("Y") PORT_CHAR('y') PORT_CHAR('Y') PORT_CODE(KEYCODE_Y) PORT_CONDITION("CONFIG", 3, NOTEQUALS, 1)
+ PORT_BIT(0x20, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("Z") PORT_CHAR('z') PORT_CHAR('Z') PORT_CODE(KEYCODE_Y) PORT_CONDITION("CONFIG", 3, EQUALS, 1)
+ PORT_BIT(0x40, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CHAR('6') PORT_CHAR('^') PORT_CODE(KEYCODE_6) PORT_CONDITION("CONFIG", 3, EQUALS, 0)
+ PORT_BIT(0x40, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CHAR('6') PORT_CHAR('&') PORT_CODE(KEYCODE_6) PORT_CONDITION("CONFIG", 3, EQUALS, 1)
+ PORT_BIT(0x40, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CHAR('-') PORT_CHAR('6') PORT_CHAR('|') PORT_CODE(KEYCODE_6) PORT_CONDITION("CONFIG", 3, EQUALS, 2)
+ PORT_BIT(0x80, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CHAR(UCHAR_MAMEKEY(LALT)) PORT_CODE(KEYCODE_LALT)
+INPUT_PORTS_END
+
+ioport_constructor cherry_g80_1500_device::device_input_ports() const
+{
+ return INPUT_PORTS_NAME(g80_1500);
+}
+
+
+void cherry_g80_1500_device::data_write(int state)
+{
+ m_mcu->set_input_line(MCS51_INT1_LINE, state ? CLEAR_LINE : ASSERT_LINE);
+}
+
+void cherry_g80_1500_device::mcu_p1_w(u8 data)
+{
+ // P1.7 is clock output to smartcard (TODO)
+ m_p1 = data;
+}
+
+u8 cherry_g80_1500_device::mcu_p3_r()
+{
+ // P3.0 (RXD) must be high to enable keycode output
+ // P3.4 (T0) is smartcard-related (TODO)
+ return m_pc_kbdc->clock_signal() ? 0xff : 0xfe;
+}
+
+void cherry_g80_1500_device::mcu_p3_w(u8 data)
+{
+ // P3.1 (TXD) is serial data output to PC
+ m_pc_kbdc->data_write_from_kb(BIT(data, 1));
+
+ // P3.2 (INT0) is clock output to PC
+ m_pc_kbdc->clock_write_from_kb(BIT(data, 2));
+
+ // P3.5 (T1) is serial data output to smartcard (TODO)
+}
+
+u8 cherry_g80_1500_device::matrix_r(offs_t offset)
+{
+ u16 strobe = u16(m_p1) << 8 | offset >> 8;
+
+ u8 data = 0xff;
+ for (int i = 0; i < 13; i++)
+ {
+ if (BIT(strobe, 14))
+ data &= m_keys[i]->read();
+
+ // Skip over P1.1
+ if (i == 4)
+ strobe <<= 2;
+ else
+ strobe <<= 1;
+ }
+
+ return ~data;
+}
+
+void cherry_g80_1500_device::outputs_w(offs_t offset, u8 data)
+{
+ // Bit 0 = Scroll Lock key LED
+ // Bit 1 = Caps Lock key LED
+ // Bit 2 = Num Lock key LED
+ for (int i = 0; i < 3; i++)
+ m_leds[i] = BIT(data, i);
+
+ // TODO: upper bits = other LEDs and smartcard-related signals
+}
+
+
+void cherry_g80_1500_device::prog_map(address_map &map)
+{
+ map(0x0000, 0x7fff).rom().region("eprom", 0);
+}
+
+void cherry_g80_1500_device::ext_map(address_map &map)
+{
+ map(0x0000, 0xffff).rw(FUNC(cherry_g80_1500_device::matrix_r), FUNC(cherry_g80_1500_device::outputs_w));
+}
+
+void cherry_g80_1500_device::device_add_mconfig(machine_config &config)
+{
+ i8032_device &mcu(I8032(config, m_mcu, 7'392'000)); // exact type and clock unknown (might actually use a more conventional 7.3728 MHz XTAL, as on G80-1000)
+ mcu.set_addrmap(AS_PROGRAM, &cherry_g80_1500_device::prog_map);
+ mcu.set_addrmap(AS_IO, &cherry_g80_1500_device::ext_map);
+ mcu.port_out_cb<1>().set(FUNC(cherry_g80_1500_device::mcu_p1_w));
+ mcu.port_in_cb<3>().set(FUNC(cherry_g80_1500_device::mcu_p3_r));
+ mcu.port_out_cb<3>().set(FUNC(cherry_g80_1500_device::mcu_p3_w));
+}
+
+ROM_START(g80_1500)
+ ROM_REGION(0x8000, "eprom", 0)
+ ROM_LOAD("nm27c256q_635-0945 index 05.bin", 0x0000, 0x8000, CRC(223714f4) SHA1(009fc939f86bf70d288523446e292095d9706ab2))
+ROM_END
+
+const tiny_rom_entry *cherry_g80_1500_device::device_rom_region() const
+{
+ return ROM_NAME(g80_1500);
+}
diff --git a/src/devices/bus/pc_kbd/cherry_mx1500.h b/src/devices/bus/pc_kbd/cherry_mx1500.h
new file mode 100644
index 00000000000..7581a17faeb
--- /dev/null
+++ b/src/devices/bus/pc_kbd/cherry_mx1500.h
@@ -0,0 +1,44 @@
+// license:BSD-3-Clause
+// copyright-holders:AJR
+
+#ifndef MAME_BUS_PC_KBD_CHERRY_MX1500_H
+#define MAME_BUS_PC_KBD_CHERRY_MX1500_H
+
+#pragma once
+
+#include "pc_kbdc.h"
+
+class cherry_g80_1500_device : public device_t, public device_pc_kbd_interface
+{
+public:
+ cherry_g80_1500_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock);
+
+protected:
+ virtual void data_write(int state) override;
+
+ virtual ioport_constructor device_input_ports() const override ATTR_COLD;
+ virtual void device_start() override ATTR_COLD;
+ virtual void device_add_mconfig(machine_config &config) override ATTR_COLD;
+ virtual const tiny_rom_entry *device_rom_region() const override ATTR_COLD;
+
+private:
+ void mcu_p1_w(u8 data);
+ u8 mcu_p3_r();
+ void mcu_p3_w(u8 data);
+ u8 matrix_r(offs_t offset);
+ void outputs_w(offs_t offset, u8 data);
+
+ void prog_map(address_map &map) ATTR_COLD;
+ void ext_map(address_map &map) ATTR_COLD;
+
+ required_device<cpu_device> m_mcu;
+ required_ioport_array<13> m_keys;
+ output_finder<3> m_leds;
+
+ u8 m_p1;
+};
+
+// device type declaration
+DECLARE_DEVICE_TYPE(CHERRY_G80_1500, cherry_g80_1500_device)
+
+#endif // MAME_BUS_PC_KBD_CHERRY_MX1500_H
diff --git a/src/devices/bus/pc_kbd/ec1841.cpp b/src/devices/bus/pc_kbd/ec1841.cpp
index 2a36345e1fa..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);
}
@@ -344,7 +343,7 @@ WRITE_LINE_MEMBER( ec_1841_keyboard_device::data_write )
// bus_w -
//-------------------------------------------------
-WRITE8_MEMBER( ec_1841_keyboard_device::bus_w )
+void ec_1841_keyboard_device::bus_w(uint8_t data)
{
LOGDBG("bus_w %02x\n", data);
@@ -356,7 +355,7 @@ WRITE8_MEMBER( ec_1841_keyboard_device::bus_w )
// p1_r -
//-------------------------------------------------
-READ8_MEMBER( ec_1841_keyboard_device::p1_r )
+uint8_t ec_1841_keyboard_device::p1_r()
{
/*
@@ -388,7 +387,7 @@ READ8_MEMBER( ec_1841_keyboard_device::p1_r )
// p1_w -
//-------------------------------------------------
-WRITE8_MEMBER( ec_1841_keyboard_device::p1_w )
+void ec_1841_keyboard_device::p1_w(uint8_t data)
{
/*
bit description
@@ -412,7 +411,7 @@ WRITE8_MEMBER( ec_1841_keyboard_device::p1_w )
// p2_w -
//-------------------------------------------------
-WRITE8_MEMBER( ec_1841_keyboard_device::p2_w )
+void ec_1841_keyboard_device::p2_w(uint8_t data)
{
/*
bit description
@@ -439,7 +438,7 @@ WRITE8_MEMBER( ec_1841_keyboard_device::p2_w )
// 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 72e9dc639d0..2c70ce91abd 100644
--- a/src/devices/bus/pc_kbd/ec1841.h
+++ b/src/devices/bus/pc_kbd/ec1841.h
@@ -30,24 +30,24 @@ public:
protected:
// device-level overrides
- virtual void device_start() override;
- virtual void device_reset() override;
+ virtual void device_start() override ATTR_COLD;
+ virtual void device_reset() override ATTR_COLD;
// optional information 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 const tiny_rom_entry *device_rom_region() const override ATTR_COLD;
+ virtual void device_add_mconfig(machine_config &config) override ATTR_COLD;
+ virtual ioport_constructor device_input_ports() const override ATTR_COLD;
// 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:
- DECLARE_WRITE8_MEMBER( bus_w );
- DECLARE_READ8_MEMBER( p1_r );
- DECLARE_WRITE8_MEMBER( p1_w );
- DECLARE_WRITE8_MEMBER( p2_w );
- DECLARE_READ_LINE_MEMBER( t1_r );
+ void bus_w(uint8_t data);
+ uint8_t p1_r();
+ void p1_w(uint8_t data);
+ void p2_w(uint8_t data);
+ 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 b88f5b40039..507a3be8d94 100644
--- a/src/devices/bus/pc_kbd/hle_mouse.cpp
+++ b/src/devices/bus/pc_kbd/hle_mouse.cpp
@@ -8,7 +8,7 @@
* byte PS/2 mouse protocol. Serial I/O is driven at 10kHz by a 40kHz timer
* to generate somewhat accurate clock rising and falling edges, as well as
* sampling or writing the data line in the middle of each high or low cycle
- * as exoected by the protocol.
+ * as expected by the protocol.
*
* The original IBM PS/2 mouse had only two buttons and the documented protocol
* reflects this, however it also allows a third button to be added without any
@@ -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)
@@ -104,8 +103,8 @@ void hle_ps2_mouse_device::device_start()
set_pc_kbdc_device();
- m_serial = machine().scheduler().timer_alloc(timer_expired_delegate(FUNC(hle_ps2_mouse_device::serial), this));
- m_sample = machine().scheduler().timer_alloc(timer_expired_delegate(FUNC(hle_ps2_mouse_device::sample), this));
+ m_serial = timer_alloc(FUNC(hle_ps2_mouse_device::serial), this);
+ m_sample = timer_alloc(FUNC(hle_ps2_mouse_device::sample), this);
}
void hle_ps2_mouse_device::device_reset()
@@ -155,7 +154,7 @@ void hle_ps2_mouse_device::resume()
}
}
-void hle_ps2_mouse_device::serial(void *ptr, s32 param)
+void hle_ps2_mouse_device::serial(s32 param)
{
// host may inhibit device communication by holding the clock low for 100µs
if (!clock_signal() && clock_held(100))
@@ -474,7 +473,7 @@ void hle_ps2_mouse_device::command(u8 const command)
}
}
-void hle_ps2_mouse_device::sample(void *ptr, s32 param)
+void hle_ps2_mouse_device::sample(s32 param)
{
// read mouse state
s16 const x = m_port_x_axis->read();
diff --git a/src/devices/bus/pc_kbd/hle_mouse.h b/src/devices/bus/pc_kbd/hle_mouse.h
index d4222a35fd2..6d90cf80d05 100644
--- a/src/devices/bus/pc_kbd/hle_mouse.h
+++ b/src/devices/bus/pc_kbd/hle_mouse.h
@@ -1,8 +1,8 @@
// license:BSD-3-Clause
// copyright-holders:Patrick Mackinlay
-#ifndef MAME_BUS_HLE_PS2_MOUSE_H
-#define MAME_BUS_HLE_PS2_MOUSE_H
+#ifndef MAME_BUS_PC_KBD_HLE_MOUSE_H
+#define MAME_BUS_PC_KBD_HLE_MOUSE_H
#pragma once
@@ -17,9 +17,9 @@ public:
protected:
// device_t overrides
- virtual ioport_constructor device_input_ports() const override;
- virtual void device_start() override;
- virtual void device_reset() override;
+ virtual ioport_constructor device_input_ports() const override ATTR_COLD;
+ virtual void device_start() override ATTR_COLD;
+ virtual void device_reset() override ATTR_COLD;
// device_pc_kbd_interface overrides
virtual void clock_write(int state) override;
@@ -95,4 +95,4 @@ private:
// device type definition
DECLARE_DEVICE_TYPE(HLE_PS2_MOUSE, hle_ps2_mouse_device)
-#endif // MAME_BUS_HLE_PS2_MOUSE_H
+#endif // MAME_BUS_PC_KBD_HLE_MOUSE_H
diff --git a/src/devices/bus/pc_kbd/iskr1030.cpp b/src/devices/bus/pc_kbd/iskr1030.cpp
index 3f91451d9ab..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;
@@ -392,7 +391,7 @@ READ_LINE_MEMBER( iskr_1030_keyboard_device::t1_r )
// ram_w -
//-------------------------------------------------
-WRITE8_MEMBER( iskr_1030_keyboard_device::ram_w )
+void iskr_1030_keyboard_device::ram_w(offs_t offset, uint8_t data)
{
LOGDBG("ram_w[%02x] <- %02x\n", offset, data);
@@ -405,7 +404,7 @@ WRITE8_MEMBER( iskr_1030_keyboard_device::ram_w )
// ram_r -
//-------------------------------------------------
-READ8_MEMBER( iskr_1030_keyboard_device::ram_r )
+uint8_t iskr_1030_keyboard_device::ram_r(offs_t offset)
{
LOGDBG("ram_r[%02x] = %02x\n", offset, m_ram[offset]);
@@ -417,7 +416,7 @@ READ8_MEMBER( iskr_1030_keyboard_device::ram_r )
// p1_r -
//-------------------------------------------------
-READ8_MEMBER( iskr_1030_keyboard_device::p1_r )
+uint8_t iskr_1030_keyboard_device::p1_r()
{
/*
bit description
@@ -444,7 +443,7 @@ READ8_MEMBER( iskr_1030_keyboard_device::p1_r )
// p2_w -
//-------------------------------------------------
-WRITE8_MEMBER( iskr_1030_keyboard_device::p2_w )
+void iskr_1030_keyboard_device::p2_w(uint8_t data)
{
/*
bit description
@@ -468,7 +467,7 @@ WRITE8_MEMBER( iskr_1030_keyboard_device::p2_w )
// p1_w - OK
//-------------------------------------------------
-WRITE8_MEMBER( iskr_1030_keyboard_device::p1_w )
+void iskr_1030_keyboard_device::p1_w(uint8_t data)
{
/*
bit description
diff --git a/src/devices/bus/pc_kbd/iskr1030.h b/src/devices/bus/pc_kbd/iskr1030.h
index 0bc0796360f..b879dd00b53 100644
--- a/src/devices/bus/pc_kbd/iskr1030.h
+++ b/src/devices/bus/pc_kbd/iskr1030.h
@@ -31,28 +31,28 @@ public:
protected:
// device-level overrides
- virtual void device_start() override;
- virtual void device_reset() override;
+ virtual void device_start() override ATTR_COLD;
+ virtual void device_reset() override ATTR_COLD;
// optional information 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 const tiny_rom_entry *device_rom_region() const override ATTR_COLD;
+ virtual void device_add_mconfig(machine_config &config) override ATTR_COLD;
+ virtual ioport_constructor device_input_ports() const override ATTR_COLD;
// 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:
- DECLARE_READ8_MEMBER( p1_r );
- DECLARE_WRITE8_MEMBER( p1_w );
- DECLARE_WRITE8_MEMBER( p2_w );
- DECLARE_READ_LINE_MEMBER( t1_r );
+ uint8_t p1_r();
+ void p1_w(uint8_t data);
+ void p2_w(uint8_t data);
+ int t1_r();
- DECLARE_READ8_MEMBER( ram_r );
- DECLARE_WRITE8_MEMBER( ram_w );
+ uint8_t ram_r(offs_t offset);
+ void ram_w(offs_t offset, uint8_t data);
- void iskr_1030_keyboard_io(address_map &map);
+ void iskr_1030_keyboard_io(address_map &map) ATTR_COLD;
required_device<i8048_device> m_maincpu;
required_ioport m_md00;
diff --git a/src/devices/bus/pc_kbd/keyboards.cpp b/src/devices/bus/pc_kbd/keyboards.cpp
index ff6e5a65d0a..abb8524df06 100644
--- a/src/devices/bus/pc_kbd/keyboards.cpp
+++ b/src/devices/bus/pc_kbd/keyboards.cpp
@@ -3,6 +3,7 @@
#include "emu.h"
#include "keyboards.h"
+#include "cherry_mx1500.h"
#include "ec1841.h"
#include "iskr1030.h"
#include "keytro.h"
@@ -30,6 +31,7 @@ void pc_at_keyboards(device_slot_interface &device)
device.option_add(STR_KBD_IBM_PC_AT_84, PC_KBD_IBM_PC_AT_84);
device.option_add(STR_KBD_IBM_3270PC_122, PC_KBD_IBM_3270PC_122);
device.option_add(STR_KBD_IBM_PC_AT_101, PC_KBD_IBM_PC_AT_101);
+ device.option_add(STR_KBD_CHERRY_G80_1500, CHERRY_G80_1500);
}
void ps2_mice(device_slot_interface &device)
diff --git a/src/devices/bus/pc_kbd/keyboards.h b/src/devices/bus/pc_kbd/keyboards.h
index 408a98628c4..4c87848c0a2 100644
--- a/src/devices/bus/pc_kbd/keyboards.h
+++ b/src/devices/bus/pc_kbd/keyboards.h
@@ -28,6 +28,7 @@ void pc_xt_keyboards(device_slot_interface &device);
#define STR_KBD_IBM_PC_AT_84 "pcat"
#define STR_KBD_IBM_3270PC_122 "3270pc"
#define STR_KBD_IBM_PC_AT_101 "pcat101"
+#define STR_KBD_CHERRY_G80_1500 "g80_1500"
void pc_at_keyboards(device_slot_interface &device);
diff --git a/src/devices/bus/pc_kbd/keytro.cpp b/src/devices/bus/pc_kbd/keytro.cpp
index 72149e8ddea..53a140894e7 100644
--- a/src/devices/bus/pc_kbd/keytro.cpp
+++ b/src/devices/bus/pc_kbd/keytro.cpp
@@ -456,19 +456,19 @@ 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);
}
-READ8_MEMBER( pc_kbd_keytronic_pc3270_device::internal_data_read )
+uint8_t pc_kbd_keytronic_pc3270_device::internal_data_read(offs_t offset)
{
if (LOG)
logerror("keytronic_pc3270::internal_data_read(): read from %04x\n", offset);
@@ -483,7 +483,7 @@ READ8_MEMBER( pc_kbd_keytronic_pc3270_device::internal_data_read )
}
-WRITE8_MEMBER( pc_kbd_keytronic_pc3270_device::internal_data_write )
+void pc_kbd_keytronic_pc3270_device::internal_data_write(offs_t offset, uint8_t data)
{
if (LOG)
logerror("keytronic_pc3270::internal_data_write(): write to offset %04x\n", offset);
@@ -585,13 +585,13 @@ WRITE8_MEMBER( pc_kbd_keytronic_pc3270_device::internal_data_write )
}
-READ8_MEMBER( pc_kbd_keytronic_pc3270_device::p1_read )
+uint8_t pc_kbd_keytronic_pc3270_device::p1_read()
{
return m_p1 & m_p1_data;
}
-WRITE8_MEMBER( pc_kbd_keytronic_pc3270_device::p1_write )
+void pc_kbd_keytronic_pc3270_device::p1_write(uint8_t data)
{
if (LOG)
logerror("keytronic_pc3270::p1_write(): write %02x\n", data);
@@ -600,13 +600,13 @@ WRITE8_MEMBER( pc_kbd_keytronic_pc3270_device::p1_write )
}
-READ8_MEMBER( pc_kbd_keytronic_pc3270_device::p2_read )
+uint8_t pc_kbd_keytronic_pc3270_device::p2_read()
{
return m_p2;
}
-WRITE8_MEMBER( pc_kbd_keytronic_pc3270_device::p2_write )
+void pc_kbd_keytronic_pc3270_device::p2_write(uint8_t data)
{
if (LOG)
logerror("keytronic_pc3270::p2_write(): write %02x\n", data);
@@ -615,7 +615,7 @@ WRITE8_MEMBER( pc_kbd_keytronic_pc3270_device::p2_write )
}
-READ8_MEMBER( pc_kbd_keytronic_pc3270_device::p3_read )
+uint8_t pc_kbd_keytronic_pc3270_device::p3_read()
{
uint8_t data = m_p3;
@@ -628,7 +628,7 @@ READ8_MEMBER( pc_kbd_keytronic_pc3270_device::p3_read )
}
-WRITE8_MEMBER( pc_kbd_keytronic_pc3270_device::p3_write )
+void pc_kbd_keytronic_pc3270_device::p3_write(uint8_t data)
{
if (LOG)
logerror("keytronic_pc3270::p3_write(): write %02x\n", data);
diff --git a/src/devices/bus/pc_kbd/keytro.h b/src/devices/bus/pc_kbd/keytro.h
index c1e86e92f82..df4515511df 100644
--- a/src/devices/bus/pc_kbd/keytro.h
+++ b/src/devices/bus/pc_kbd/keytro.h
@@ -36,28 +36,28 @@ protected:
uint32_t clock);
// device-level overrides
- virtual void device_start() override;
- virtual void device_reset() override;
+ virtual void device_start() override ATTR_COLD;
+ virtual void device_reset() override ATTR_COLD;
// optional information 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;
+ virtual void device_add_mconfig(machine_config &config) override ATTR_COLD;
+ virtual ioport_constructor device_input_ports() const override ATTR_COLD;
+ virtual const tiny_rom_entry *device_rom_region() const override ATTR_COLD;
- 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;
- DECLARE_READ8_MEMBER( internal_data_read );
- DECLARE_WRITE8_MEMBER( internal_data_write );
- DECLARE_READ8_MEMBER( p1_read );
- DECLARE_WRITE8_MEMBER( p1_write );
- DECLARE_READ8_MEMBER( p2_read );
- DECLARE_WRITE8_MEMBER( p2_write );
- DECLARE_READ8_MEMBER( p3_read );
- DECLARE_WRITE8_MEMBER( p3_write );
+ uint8_t internal_data_read(offs_t offset);
+ void internal_data_write(offs_t offset, uint8_t data);
+ uint8_t p1_read();
+ void p1_write(uint8_t data);
+ uint8_t p2_read();
+ void p2_write(uint8_t data);
+ uint8_t p3_read();
+ void p3_write(uint8_t data);
- void keytronic_pc3270_io(address_map &map);
- void keytronic_pc3270_program(address_map &map);
+ void keytronic_pc3270_io(address_map &map) ATTR_COLD;
+ void keytronic_pc3270_program(address_map &map) ATTR_COLD;
required_device<i8051_device> m_cpu;
@@ -75,7 +75,7 @@ public:
// construction/destruction
pc_kbd_keytronic_pc3270_at_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
- virtual ioport_constructor device_input_ports() const override;
+ virtual ioport_constructor device_input_ports() const override ATTR_COLD;
};
diff --git a/src/devices/bus/pc_kbd/msnat.cpp b/src/devices/bus/pc_kbd/msnat.cpp
index 67919240d72..bc6310c9465 100644
--- a/src/devices/bus/pc_kbd/msnat.cpp
+++ b/src/devices/bus/pc_kbd/msnat.cpp
@@ -272,17 +272,17 @@ 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)
{
}
-READ8_MEMBER( pc_kbd_microsoft_natural_device::p0_read )
+uint8_t pc_kbd_microsoft_natural_device::p0_read()
{
uint8_t data = 0xFF;
@@ -341,25 +341,25 @@ READ8_MEMBER( pc_kbd_microsoft_natural_device::p0_read )
}
-WRITE8_MEMBER( pc_kbd_microsoft_natural_device::p0_write )
+void pc_kbd_microsoft_natural_device::p0_write(uint8_t data)
{
m_p0 = data;
}
-WRITE8_MEMBER( pc_kbd_microsoft_natural_device::p1_write )
+void pc_kbd_microsoft_natural_device::p1_write(uint8_t data)
{
m_p1 = data;
}
-WRITE8_MEMBER( pc_kbd_microsoft_natural_device::p2_write )
+void pc_kbd_microsoft_natural_device::p2_write(uint8_t data)
{
m_p2 = data;
}
-READ8_MEMBER( pc_kbd_microsoft_natural_device::p3_read )
+uint8_t pc_kbd_microsoft_natural_device::p3_read()
{
uint8_t data = m_p3 & ~0x21;
@@ -373,7 +373,7 @@ READ8_MEMBER( pc_kbd_microsoft_natural_device::p3_read )
}
-WRITE8_MEMBER( pc_kbd_microsoft_natural_device::p3_write )
+void pc_kbd_microsoft_natural_device::p3_write(uint8_t data)
{
if ( m_pc_kbdc )
{
diff --git a/src/devices/bus/pc_kbd/msnat.h b/src/devices/bus/pc_kbd/msnat.h
index d4453c8b64d..ee339b1772b 100644
--- a/src/devices/bus/pc_kbd/msnat.h
+++ b/src/devices/bus/pc_kbd/msnat.h
@@ -6,8 +6,8 @@
***************************************************************************/
-#ifndef MAME_BUS_PC_KB_MSNAT_H
-#define MAME_BUS_PC_KB_MSNAT_H
+#ifndef MAME_BUS_PC_KBD_MSNAT_H
+#define MAME_BUS_PC_KBD_MSNAT_H
#pragma once
@@ -27,16 +27,16 @@ public:
protected:
// device-level overrides
- virtual void device_start() override;
- virtual void device_reset() override;
+ virtual void device_start() override ATTR_COLD;
+ virtual void device_reset() override ATTR_COLD;
// optional information 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;
+ virtual void device_add_mconfig(machine_config &config) override ATTR_COLD;
+ virtual ioport_constructor device_input_ports() const override ATTR_COLD;
+ virtual const tiny_rom_entry *device_rom_region() const override ATTR_COLD;
- 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;
@@ -49,16 +49,16 @@ private:
uint8_t m_p2;
uint8_t m_p3;
- DECLARE_READ8_MEMBER(p0_read);
- DECLARE_WRITE8_MEMBER(p0_write);
- DECLARE_WRITE8_MEMBER(p1_write);
- DECLARE_WRITE8_MEMBER(p2_write);
- DECLARE_READ8_MEMBER(p3_read);
- DECLARE_WRITE8_MEMBER(p3_write);
+ uint8_t p0_read();
+ void p0_write(uint8_t data);
+ void p1_write(uint8_t data);
+ void p2_write(uint8_t data);
+ uint8_t p3_read();
+ void p3_write(uint8_t data);
};
// device type definition
DECLARE_DEVICE_TYPE(PC_KBD_MICROSOFT_NATURAL, pc_kbd_microsoft_natural_device)
-#endif // MAME_BUS_PC_KB_MSNAT_H
+#endif // MAME_BUS_PC_KBD_MSNAT_H
diff --git a/src/devices/bus/pc_kbd/pc83.cpp b/src/devices/bus/pc_kbd/pc83.cpp
index 9cfc3ee31e0..53c85c4d254 100644
--- a/src/devices/bus/pc_kbd/pc83.cpp
+++ b/src/devices/bus/pc_kbd/pc83.cpp
@@ -265,7 +265,7 @@ void ibm_pc_83_keyboard_device::device_reset()
// bus_w -
//-------------------------------------------------
-WRITE8_MEMBER( ibm_pc_83_keyboard_device::bus_w )
+void ibm_pc_83_keyboard_device::bus_w(uint8_t data)
{
/*
@@ -290,7 +290,7 @@ WRITE8_MEMBER( ibm_pc_83_keyboard_device::bus_w )
// p1_r -
//-------------------------------------------------
-READ8_MEMBER( ibm_pc_83_keyboard_device::p1_r )
+uint8_t ibm_pc_83_keyboard_device::p1_r()
{
/*
@@ -320,7 +320,7 @@ READ8_MEMBER( ibm_pc_83_keyboard_device::p1_r )
// p2_w -
//-------------------------------------------------
-WRITE8_MEMBER( ibm_pc_83_keyboard_device::p2_w )
+void ibm_pc_83_keyboard_device::p2_w(uint8_t data)
{
/*
@@ -346,7 +346,7 @@ WRITE8_MEMBER( ibm_pc_83_keyboard_device::p2_w )
// 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 6b800c7b8a0..0459b9043c5 100644
--- a/src/devices/bus/pc_kbd/pc83.h
+++ b/src/devices/bus/pc_kbd/pc83.h
@@ -32,23 +32,23 @@ public:
protected:
// device-level overrides
- virtual void device_start() override;
- virtual void device_reset() override;
+ virtual void device_start() override ATTR_COLD;
+ virtual void device_reset() override ATTR_COLD;
// optional information 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 const tiny_rom_entry *device_rom_region() const override ATTR_COLD;
+ virtual void device_add_mconfig(machine_config &config) override ATTR_COLD;
+ virtual ioport_constructor device_input_ports() const override ATTR_COLD;
// 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:
- DECLARE_WRITE8_MEMBER( bus_w );
- DECLARE_READ8_MEMBER( p1_r );
- DECLARE_WRITE8_MEMBER( p2_w );
- DECLARE_READ_LINE_MEMBER( t0_r );
+ void bus_w(uint8_t data);
+ uint8_t p1_r();
+ void p2_w(uint8_t data);
+ 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 0b308b57f96..4eee89f4188 100644
--- a/src/devices/bus/pc_kbd/pc_kbdc.cpp
+++ b/src/devices/bus/pc_kbd/pc_kbdc.cpp
@@ -16,57 +16,27 @@ The following basic program can be useful for identifying scancodes:
#include "emu.h"
#include "pc_kbdc.h"
-#define LOG_SIGNALS (1U<<1)
-#define VERBOSE ( LOG_GENERAL )
-
+#define LOG_SIGNALS (1U << 1)
+//#define VERBOSE (LOG_GENERAL)
#include "logmacro.h"
+
//**************************************************************************
// GLOBAL VARIABLES
//**************************************************************************
-DEFINE_DEVICE_TYPE(PC_KBDC_SLOT, pc_kbdc_slot_device, "pc_kbdc_slot", "PC keyboard port")
+DEFINE_DEVICE_TYPE(PC_KBDC, pc_kbdc_device, "pc_kbdc", "PC keyboard connector")
//**************************************************************************
// LIVE DEVICE
//**************************************************************************
//-------------------------------------------------
-// pc_kbdc_slot_device - constructor
-//-------------------------------------------------
-pc_kbdc_slot_device::pc_kbdc_slot_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) :
- device_t(mconfig, PC_KBDC_SLOT, tag, owner, clock),
- device_slot_interface(mconfig, *this),
- m_kbdc_device(nullptr)
-{
-}
-
-
-//-------------------------------------------------
-// device_start - device-specific startup
-//-------------------------------------------------
-
-void pc_kbdc_slot_device::device_start()
-{
- device_pc_kbd_interface *pc_kbd = dynamic_cast<device_pc_kbd_interface *>(get_card_device());
-
- if (pc_kbd)
- pc_kbd->set_pc_kbdc(m_kbdc_device);
-}
-
-
-//**************************************************************************
-// GLOBAL VARIABLES
-//**************************************************************************
-
-DEFINE_DEVICE_TYPE(PC_KBDC, pc_kbdc_device, "pc_kbdc", "PC KBDC")
-
-
-//-------------------------------------------------
// pc_kbdc_device - constructor
//-------------------------------------------------
pc_kbdc_device::pc_kbdc_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) :
device_t(mconfig, PC_KBDC, tag, owner, clock),
+ device_single_card_slot_interface<device_pc_kbd_interface>(mconfig, *this),
m_out_clock_cb(*this),
m_out_data_cb(*this),
m_clock_state(-1),
@@ -88,8 +58,9 @@ void pc_kbdc_device::set_keyboard(device_pc_kbd_interface *keyboard)
//-------------------------------------------------
void pc_kbdc_device::device_resolve_objects()
{
- m_out_clock_cb.resolve_safe();
- m_out_data_cb.resolve_safe();
+ device_pc_kbd_interface *const pc_kbd = get_card_device();
+ if (pc_kbd)
+ pc_kbd->set_pc_kbdc(this);
}
void pc_kbdc_device::device_start()
@@ -152,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);
@@ -189,7 +160,7 @@ WRITE_LINE_MEMBER(pc_kbdc_device::data_write_from_kb)
//-------------------------------------------------
device_pc_kbd_interface::device_pc_kbd_interface(const machine_config &mconfig, device_t &device)
- : device_slot_card_interface(mconfig, device)
+ : device_interface(device, "pckbd")
, m_pc_kbdc(nullptr)
, m_pc_kbdc_tag(nullptr)
{
@@ -205,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 34161c23c5a..78e683b1d5b 100644
--- a/src/devices/bus/pc_kbd/pc_kbdc.h
+++ b/src/devices/bus/pc_kbd/pc_kbdc.h
@@ -20,45 +20,22 @@ set the data line and then set the clock line.
// TYPE DEFINITIONS
//**************************************************************************
+class device_pc_kbd_interface;
+
-class pc_kbdc_slot_device : public device_t,
- public device_slot_interface
+class pc_kbdc_device : public device_t, public device_single_card_slot_interface<device_pc_kbd_interface>
{
public:
// construction/destruction
template <typename T>
- pc_kbdc_slot_device(machine_config const &mconfig, char const *tag, device_t *owner, T &&opts, char const *dflt)
- : pc_kbdc_slot_device(mconfig, tag, owner, (uint32_t)0)
+ pc_kbdc_device(machine_config const &mconfig, char const *tag, device_t *owner, T &&opts, char const *dflt)
+ : pc_kbdc_device(mconfig, tag, owner, (uint32_t)0)
{
option_reset();
opts(*this);
set_default_option(dflt);
set_fixed(false);
}
- pc_kbdc_slot_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
-
- // inline configuration
- void set_pc_kbdc_slot(device_t *kbdc_device) { m_kbdc_device = kbdc_device; }
-
-protected:
- // device-level overrides
- virtual void device_start() override;
-
- // configuration
- device_t *m_kbdc_device;
-};
-
-
-// device type definition
-DECLARE_DEVICE_TYPE(PC_KBDC_SLOT, pc_kbdc_slot_device)
-
-
-class device_pc_kbd_interface;
-
-class pc_kbdc_device : public device_t
-{
-public:
- // construction/destruction
pc_kbdc_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
auto out_clock_cb() { return m_out_clock_cb.bind(); }
@@ -69,15 +46,15 @@ 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
- virtual void device_resolve_objects() override;
- virtual void device_start() override;
+ virtual void device_resolve_objects() override ATTR_COLD;
+ virtual void device_start() override ATTR_COLD;
void update_clock_state(bool fromkb);
void update_data_state(bool fromkb);
@@ -103,7 +80,7 @@ DECLARE_DEVICE_TYPE(PC_KBDC, pc_kbdc_device)
// ======================> device_pc_pbd_interface
-class device_pc_kbd_interface : public device_slot_card_interface
+class device_pc_kbd_interface : public device_interface
{
friend class pc_kbdc_device;
public:
@@ -114,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); }
@@ -131,5 +108,4 @@ protected:
};
-
#endif // MAME_BUS_PC_KBD_PC_KBDC_H
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/pcat101.h b/src/devices/bus/pc_kbd/pcat101.h
index 449947eccad..b60370141fd 100644
--- a/src/devices/bus/pc_kbd/pcat101.h
+++ b/src/devices/bus/pc_kbd/pcat101.h
@@ -19,13 +19,13 @@ public:
protected:
// device-level overrides
- virtual void device_start() override;
- virtual void device_reset() override;
+ virtual void device_start() override ATTR_COLD;
+ virtual void device_reset() override ATTR_COLD;
// optional information 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 const tiny_rom_entry *device_rom_region() const override ATTR_COLD;
+ virtual void device_add_mconfig(machine_config &config) override ATTR_COLD;
+ virtual ioport_constructor device_input_ports() const override ATTR_COLD;
// device_pc_kbd_interface overrides
virtual void data_write(int state) override;
diff --git a/src/devices/bus/pc_kbd/pcat84.cpp b/src/devices/bus/pc_kbd/pcat84.cpp
index 47cb48496e9..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))
@@ -395,7 +395,7 @@ void ibm_pc_at_84_keyboard_device::device_reset()
// bus_w -
//-------------------------------------------------
-WRITE8_MEMBER( ibm_pc_at_84_keyboard_device::bus_w )
+void ibm_pc_at_84_keyboard_device::bus_w(uint8_t data)
{
/*
@@ -425,7 +425,7 @@ WRITE8_MEMBER( ibm_pc_at_84_keyboard_device::bus_w )
// p1_r -
//-------------------------------------------------
-READ8_MEMBER( ibm_pc_at_84_keyboard_device::p1_r )
+uint8_t ibm_pc_at_84_keyboard_device::p1_r()
{
/*
@@ -454,7 +454,7 @@ READ8_MEMBER( ibm_pc_at_84_keyboard_device::p1_r )
// p1_w -
//-------------------------------------------------
-WRITE8_MEMBER( ibm_pc_at_84_keyboard_device::p1_w )
+void ibm_pc_at_84_keyboard_device::p1_w(uint8_t data)
{
/*
@@ -484,7 +484,7 @@ WRITE8_MEMBER( ibm_pc_at_84_keyboard_device::p1_w )
// p2_r -
//-------------------------------------------------
-READ8_MEMBER( ibm_pc_at_84_keyboard_device::p2_r )
+uint8_t ibm_pc_at_84_keyboard_device::p2_r()
{
/*
@@ -513,7 +513,7 @@ READ8_MEMBER( ibm_pc_at_84_keyboard_device::p2_r )
// p2_w -
//-------------------------------------------------
-WRITE8_MEMBER( ibm_pc_at_84_keyboard_device::p2_w )
+void ibm_pc_at_84_keyboard_device::p2_w(uint8_t data)
{
/*
@@ -543,7 +543,7 @@ WRITE8_MEMBER( ibm_pc_at_84_keyboard_device::p2_w )
// 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 2ed3fcc2b7c..72a99c82b2e 100644
--- a/src/devices/bus/pc_kbd/pcat84.h
+++ b/src/devices/bus/pc_kbd/pcat84.h
@@ -34,26 +34,26 @@ protected:
ibm_pc_at_84_keyboard_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_start() override ATTR_COLD;
+ virtual void device_reset() override ATTR_COLD;
// optional information 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 const tiny_rom_entry *device_rom_region() const override ATTR_COLD;
+ virtual void device_add_mconfig(machine_config &config) override ATTR_COLD;
+ virtual ioport_constructor device_input_ports() const override ATTR_COLD;
// 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:
- DECLARE_WRITE8_MEMBER( bus_w );
- DECLARE_READ8_MEMBER( p1_r );
- DECLARE_WRITE8_MEMBER( p1_w );
- DECLARE_READ8_MEMBER( p2_r );
- DECLARE_WRITE8_MEMBER( p2_w );
- DECLARE_READ_LINE_MEMBER( t0_r );
- DECLARE_READ_LINE_MEMBER( t1_r );
+ void bus_w(uint8_t data);
+ uint8_t p1_r();
+ void p1_w(uint8_t data);
+ uint8_t p2_r();
+ void p2_w(uint8_t data);
+ int t0_r();
+ int t1_r();
enum
{
@@ -86,8 +86,8 @@ public:
ibm_3270pc_122_keyboard_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 ioport_constructor device_input_ports() const override;
+ virtual const tiny_rom_entry *device_rom_region() const override ATTR_COLD;
+ virtual ioport_constructor device_input_ports() const override ATTR_COLD;
};
diff --git a/src/devices/bus/pc_kbd/pcxt83.cpp b/src/devices/bus/pc_kbd/pcxt83.cpp
index 366ef89332f..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);
}
@@ -293,9 +293,9 @@ WRITE_LINE_MEMBER( ibm_pc_xt_83_keyboard_device::data_write )
// bus_r -
//-------------------------------------------------
-READ8_MEMBER( ibm_pc_xt_83_keyboard_device::bus_r )
+uint8_t ibm_pc_xt_83_keyboard_device::bus_r()
{
- // HACK this should be handled in mcs48.c
+ // HACK this should be handled in mcs48.cpp
return m_bus;
}
@@ -304,7 +304,7 @@ READ8_MEMBER( ibm_pc_xt_83_keyboard_device::bus_r )
// bus_w -
//-------------------------------------------------
-WRITE8_MEMBER( ibm_pc_xt_83_keyboard_device::bus_w )
+void ibm_pc_xt_83_keyboard_device::bus_w(uint8_t data)
{
/*
@@ -352,7 +352,7 @@ WRITE8_MEMBER( ibm_pc_xt_83_keyboard_device::bus_w )
// p1_w -
//-------------------------------------------------
-WRITE8_MEMBER( ibm_pc_xt_83_keyboard_device::p1_w )
+void ibm_pc_xt_83_keyboard_device::p1_w(uint8_t data)
{
/*
@@ -377,7 +377,7 @@ WRITE8_MEMBER( ibm_pc_xt_83_keyboard_device::p1_w )
// p2_w -
//-------------------------------------------------
-WRITE8_MEMBER( ibm_pc_xt_83_keyboard_device::p2_w )
+void ibm_pc_xt_83_keyboard_device::p2_w(uint8_t data)
{
/*
@@ -407,7 +407,7 @@ WRITE8_MEMBER( ibm_pc_xt_83_keyboard_device::p2_w )
// 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 d2e7175e8c4..b1740603279 100644
--- a/src/devices/bus/pc_kbd/pcxt83.h
+++ b/src/devices/bus/pc_kbd/pcxt83.h
@@ -31,25 +31,25 @@ public:
protected:
// device-level overrides
- virtual void device_start() override;
- virtual void device_reset() override;
+ virtual void device_start() override ATTR_COLD;
+ virtual void device_reset() override ATTR_COLD;
// optional information 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 const tiny_rom_entry *device_rom_region() const override ATTR_COLD;
+ virtual void device_add_mconfig(machine_config &config) override ATTR_COLD;
+ virtual ioport_constructor device_input_ports() const override ATTR_COLD;
// 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:
- DECLARE_READ8_MEMBER( bus_r );
- DECLARE_WRITE8_MEMBER( bus_w );
- DECLARE_WRITE8_MEMBER( p1_w );
- DECLARE_WRITE8_MEMBER( p2_w );
- DECLARE_READ_LINE_MEMBER( t0_r );
- DECLARE_READ_LINE_MEMBER( t1_r );
+ uint8_t bus_r();
+ void bus_w(uint8_t data);
+ void p1_w(uint8_t data);
+ void p2_w(uint8_t data);
+ int t0_r();
+ int t1_r();
required_device<i8048_device> m_maincpu;
required_ioport_array<12> m_md;
diff --git a/src/devices/machine/ataflash.cpp b/src/devices/bus/pccard/ataflash.cpp
index 392d07b465e..5dc6f83fcfd 100644
--- a/src/devices/machine/ataflash.cpp
+++ b/src/devices/bus/pccard/ataflash.cpp
@@ -3,28 +3,53 @@
#include "emu.h"
#include "ataflash.h"
-DEFINE_DEVICE_TYPE(ATA_FLASH_PCCARD, ata_flash_pccard_device, "ataflash", "ATA Flash PC Card")
-
-ata_flash_pccard_device::ata_flash_pccard_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) :
- ata_flash_pccard_device(mconfig, ATA_FLASH_PCCARD, tag, owner, clock)
+ata_flash_pccard_device::ata_flash_pccard_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
+ : ata_flash_pccard_device(mconfig, ATA_FLASH_PCCARD, tag, owner, clock)
{
}
ata_flash_pccard_device::ata_flash_pccard_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock)
- : ide_hdd_device(mconfig, type, tag, owner, clock)
+ : cf_device_base(mconfig, type, tag, owner, clock)
+ , device_pccard_interface(mconfig, *this)
+{
+}
+
+void ata_flash_pccard_device::device_start()
{
+ cf_device_base::device_start();
+
+ m_cd1_cb(0);
+ m_cd2_cb(0);
}
void ata_flash_pccard_device::device_reset()
{
- ide_hdd_device::device_reset();
+ cf_device_base::device_reset();
- uint32_t metalength;
- memset(m_cis, 0xff, 512);
+ bool cis = m_image->exists() && !m_image->get_cis_data(m_cis);
+ m_cis.resize(512, 0xff);
- if (m_handle != nullptr)
+ if (!cis)
{
- m_handle->read_metadata(PCMCIA_CIS_METADATA_TAG, 0, m_cis, 512, metalength);
+ m_cis[0] = 0x01; // CISTPL_DEVICE
+ m_cis[1] = 0x04; // TPL_LINK
+ m_cis[2] = 0xdf; // 4:device type/1:WPS/3:device speed
+ m_cis[3] = 0x4a; // extended device speed (1:ext 4:mantissa 3:speed) (if speed==7)
+ m_cis[4] = 0x01; // device size byte (5:# of address units -1 3: size code)
+ m_cis[5] = 0xff; // end of device info field
+ m_cis[6] = 0x1a; // CISTPL_CONFIG
+ m_cis[7] = 0x05; // TPL_LINK
+ m_cis[8] = 0x01; // Size of Fields Byte (2:TPCC_RFSZ 4:TPCC_RMSZ 2:TPCC_RASZ)
+ m_cis[9] = 0x03; // TPCC_LAST (2:RFU 6:Last Index) (count of 0x1b?)
+ m_cis[10] = 0x00; // TPCC_RADR
+ m_cis[11] = 0x02; // TPCC_RADR
+ m_cis[12] = 0x0f; // TPCC_RMSK
+ m_cis[13] = 0x21; // CISTPL_FUNCID
+ m_cis[14] = 0x02; // TPL_LINK
+ m_cis[15] = 0x04; // TPLFID_FUNCTION
+ m_cis[16] = 0x01; // TPLFID_SYSINIT
+ m_cis[17] = 0xff; // CISTPL_END
+ m_cis[18] = 0xff; // TPL_LINK
}
m_configuration_option = 0;
@@ -32,16 +57,16 @@ void ata_flash_pccard_device::device_reset()
m_pin_replacement = 0x002e;
}
-READ16_MEMBER( ata_flash_pccard_device::read_memory )
+uint16_t ata_flash_pccard_device::read_memory(offs_t offset, uint16_t mem_mask)
{
if(offset <= 7)
{
m_8bit_data_transfers = !ACCESSING_BITS_8_15; // HACK
- return read_cs0(offset, mem_mask);
+ return command_r(offset);
}
else if(offset <= 15)
{
- return read_cs1(offset & 7, mem_mask);
+ return control_r(offset & 7);
}
else
{
@@ -49,20 +74,20 @@ READ16_MEMBER( ata_flash_pccard_device::read_memory )
}
}
-WRITE16_MEMBER( ata_flash_pccard_device::write_memory )
+void ata_flash_pccard_device::write_memory(offs_t offset, uint16_t data, uint16_t mem_mask)
{
if(offset <= 7)
{
m_8bit_data_transfers = !ACCESSING_BITS_8_15; // HACK
- write_cs0(offset, data, mem_mask);
+ command_w(offset, data);
}
else if( offset <= 15)
{
- write_cs1(offset & 7, data, mem_mask);
+ control_w(offset & 7, data);
}
}
-READ16_MEMBER( ata_flash_pccard_device::read_reg )
+uint16_t ata_flash_pccard_device::read_reg(offs_t offset, uint16_t mem_mask)
{
switch (offset)
{
@@ -80,10 +105,10 @@ READ16_MEMBER( ata_flash_pccard_device::read_reg )
return m_cis[offset];
}
- return pccard_interface::read_reg(space, offset, mem_mask);
+ return device_pccard_interface::read_reg(offset, mem_mask);
}
-WRITE16_MEMBER( ata_flash_pccard_device::write_reg )
+void ata_flash_pccard_device::write_reg(offs_t offset, uint16_t data, uint16_t mem_mask)
{
/// TODO: get offsets from CIS
switch (offset)
@@ -106,19 +131,18 @@ WRITE16_MEMBER( ata_flash_pccard_device::write_reg )
break;
default:
- pccard_interface::write_reg(space, offset, data, mem_mask);
+ device_pccard_interface::write_reg(offset, data, mem_mask);
break;
}
}
-attotime ata_flash_pccard_device::seek_time()
+void ata_flash_pccard_device::ide_build_identify_device()
{
- return attotime::zero;
+ cf_device_base::ide_build_identify_device();
+ m_identify_buffer[0] = 0x848a; /* 0: configuration bits */
}
-DEFINE_DEVICE_TYPE(TAITO_PCCARD1, taito_pccard1_device, "taito_pccard1", "Taito PC Card (Type 1)")
-
taito_pccard1_device::taito_pccard1_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) :
ata_flash_pccard_device(mconfig, TAITO_PCCARD1, tag, owner, clock),
m_locked(0)
@@ -136,16 +160,14 @@ void taito_pccard1_device::device_reset()
{
ata_flash_pccard_device::device_reset();
- uint32_t metalength;
- memset(m_key, 0, sizeof(m_key));
-
- if (m_handle != nullptr && m_handle->read_metadata(HARD_DISK_KEY_METADATA_TAG, 0, m_key, 5, metalength) == CHDERR_NONE)
+ if (m_image->exists() && !m_image->get_disk_key_data(m_key) && m_key.size() == 5)
{
m_locked = 0x1ff;
}
+ m_key.resize(5, 0);
}
-READ16_MEMBER(taito_pccard1_device::read_reg)
+uint16_t taito_pccard1_device::read_reg(offs_t offset, uint16_t mem_mask)
{
switch (offset)
{
@@ -153,17 +175,17 @@ READ16_MEMBER(taito_pccard1_device::read_reg)
return m_locked != 0;
default:
- return ata_flash_pccard_device::read_reg(space, offset, mem_mask);
+ return ata_flash_pccard_device::read_reg(offset, mem_mask);
}
}
-WRITE16_MEMBER(taito_pccard1_device::write_reg)
+void taito_pccard1_device::write_reg(offs_t offset, uint16_t data, uint16_t mem_mask)
{
if (offset >= 0x280 && offset <= 0x288)
{
uint8_t v = data;
int pos = offset - 0x280;
- uint8_t k = pos < sizeof(m_key) ? m_key[pos] : 0;
+ uint8_t k = pos < m_key.size() ? m_key[pos] : 0;
// TODO: find out if unlocking the key then using an incorrect key will re-lock the card.
if (v == k)
@@ -179,7 +201,7 @@ WRITE16_MEMBER(taito_pccard1_device::write_reg)
}
else
{
- ata_flash_pccard_device::write_reg(space, offset, data, mem_mask);
+ ata_flash_pccard_device::write_reg(offset, data, mem_mask);
}
}
@@ -208,8 +230,6 @@ bool taito_pccard1_device::is_ready()
return m_locked == 0;
}
-DEFINE_DEVICE_TYPE(TAITO_PCCARD2, taito_pccard2_device, "taito_pccard2", "Taito PC Card (Type 2)")
-
taito_pccard2_device::taito_pccard2_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) :
ata_flash_pccard_device(mconfig, TAITO_PCCARD2, tag, owner, clock),
m_locked(false)
@@ -227,13 +247,11 @@ void taito_pccard2_device::device_reset()
{
ata_flash_pccard_device::device_reset();
- uint32_t metalength;
- memset(m_key, 0, sizeof(m_key));
-
- if (m_handle != nullptr && m_handle->read_metadata(HARD_DISK_KEY_METADATA_TAG, 0, m_key, 5, metalength) == CHDERR_NONE)
+ if (m_image->exists() && !m_image->get_disk_key_data(m_key) && m_key.size() == 5)
{
m_locked = true;
}
+ m_key.resize(5, 0);
}
void taito_pccard2_device::process_command()
@@ -307,7 +325,6 @@ bool taito_pccard2_device::is_ready()
return !m_locked;
}
-DEFINE_DEVICE_TYPE(TAITO_COMPACT_FLASH, taito_compact_flash_device, "taito_cf", "Taito Compact Flash")
taito_compact_flash_device::taito_compact_flash_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) :
ata_flash_pccard_device(mconfig, TAITO_COMPACT_FLASH, tag, owner, clock),
@@ -326,13 +343,11 @@ void taito_compact_flash_device::device_reset()
{
ata_flash_pccard_device::device_reset();
- uint32_t metalength;
- memset(m_key, 0, sizeof(m_key));
-
- if (m_handle != nullptr && m_handle->read_metadata(HARD_DISK_KEY_METADATA_TAG, 0, m_key, 5, metalength) == CHDERR_NONE)
+ if (m_image->exists() && !m_image->get_disk_key_data(m_key) && m_key.size() == 5)
{
m_locked = true;
}
+ m_key.resize(5, 0);
}
void taito_compact_flash_device::process_command()
@@ -376,3 +391,8 @@ bool taito_compact_flash_device::is_ready()
{
return !m_locked;
}
+
+DEFINE_DEVICE_TYPE(ATA_FLASH_PCCARD, ata_flash_pccard_device, "ataflash", "ATA Flash PC Card")
+DEFINE_DEVICE_TYPE(TAITO_PCCARD1, taito_pccard1_device, "taito_pccard1", "Taito PC Card (Type 1)")
+DEFINE_DEVICE_TYPE(TAITO_PCCARD2, taito_pccard2_device, "taito_pccard2", "Taito PC Card (Type 2)")
+DEFINE_DEVICE_TYPE(TAITO_COMPACT_FLASH, taito_compact_flash_device, "taito_cf", "Taito Compact Flash")
diff --git a/src/devices/machine/ataflash.h b/src/devices/bus/pccard/ataflash.h
index 71024dda20e..02e82378a28 100644
--- a/src/devices/machine/ataflash.h
+++ b/src/devices/bus/pccard/ataflash.h
@@ -1,71 +1,71 @@
// license:BSD-3-Clause
// copyright-holders:smf
-#ifndef MAME_MACHINE_ATAFLASH_H
-#define MAME_MACHINE_ATAFLASH_H
+#ifndef MAME_BUS_PCCARD_ATAFLASH_H
+#define MAME_BUS_PCCARD_ATAFLASH_H
#pragma once
#include "pccard.h"
-#include "machine/idehd.h"
+#include "machine/atastorage.h"
-DECLARE_DEVICE_TYPE(ATA_FLASH_PCCARD, ata_flash_pccard_device)
-
-class ata_flash_pccard_device : public ide_hdd_device, public pccard_interface
+class ata_flash_pccard_device : public cf_device_base, public device_pccard_interface
{
public:
ata_flash_pccard_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
- virtual DECLARE_READ16_MEMBER(read_memory) override;
- virtual DECLARE_WRITE16_MEMBER(write_memory) override;
- virtual DECLARE_READ16_MEMBER(read_reg) override;
- virtual DECLARE_WRITE16_MEMBER(write_reg) override;
+ virtual uint16_t read_memory(offs_t offset, uint16_t mem_mask = ~0) override;
+ virtual void write_memory(offs_t offset, uint16_t data, uint16_t mem_mask = ~0) override;
+ virtual uint16_t read_reg(offs_t offset, uint16_t mem_mask = ~0) override;
+ virtual void write_reg(offs_t offset, uint16_t data, uint16_t mem_mask = ~0) override;
protected:
ata_flash_pccard_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock);
- // device-level overrides
- virtual void device_reset() override;
-
- virtual attotime seek_time() override;
+ // device_t implementation
+ virtual void device_start() override ATTR_COLD;
+ virtual void device_reset() override ATTR_COLD;
private:
- uint8_t m_cis[512];
+ // ata_hle_device_base implementation
+ virtual void ide_build_identify_device() override;
+ 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 { }
+
+ std::vector<uint8_t> m_cis;
uint8_t m_configuration_option;
uint8_t m_configuration_and_status;
uint8_t m_pin_replacement;
};
-DECLARE_DEVICE_TYPE(TAITO_PCCARD1, taito_pccard1_device)
-
class taito_pccard1_device : public ata_flash_pccard_device
{
public:
taito_pccard1_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
- virtual DECLARE_READ16_MEMBER(read_reg) override;
- virtual DECLARE_WRITE16_MEMBER(write_reg) override;
+ virtual uint16_t read_reg(offs_t offset, uint16_t mem_mask = ~0) override;
+ virtual void write_reg(offs_t offset, uint16_t data, uint16_t mem_mask = ~0) override;
protected:
- virtual void device_start() override;
- virtual void device_reset() override;
+ virtual void device_start() override ATTR_COLD;
+ virtual void device_reset() override ATTR_COLD;
virtual void process_command() override;
virtual bool is_ready() override;
private:
- uint8_t m_key[5];
+ std::vector<uint8_t> m_key;
uint16_t m_locked;
};
-DECLARE_DEVICE_TYPE(TAITO_PCCARD2, taito_pccard2_device)
-
class taito_pccard2_device : public ata_flash_pccard_device
{
public:
taito_pccard2_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_start() override ATTR_COLD;
+ virtual void device_reset() override ATTR_COLD;
virtual void process_command() override;
virtual void process_buffer() override;
virtual bool is_ready() override;
@@ -74,28 +74,31 @@ protected:
static const int IDE_COMMAND_TAITO_GNET_UNLOCK_2 = 0xfc;
private:
- uint8_t m_key[5];
+ std::vector<uint8_t> m_key;
bool m_locked;
};
-DECLARE_DEVICE_TYPE(TAITO_COMPACT_FLASH, taito_compact_flash_device)
-
class taito_compact_flash_device : public ata_flash_pccard_device
{
public:
taito_compact_flash_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_start() override ATTR_COLD;
+ virtual void device_reset() override ATTR_COLD;
virtual void process_command() override;
virtual bool is_ready() override;
static constexpr int IDE_COMMAND_TAITO_COMPACT_FLASH_UNLOCK = 0x0f;
private:
- uint8_t m_key[5];
+ std::vector<uint8_t> m_key;
bool m_locked;
};
-#endif // MAME_MACHINE_ATAFLASH_H
+DECLARE_DEVICE_TYPE(TAITO_PCCARD1, taito_pccard1_device)
+DECLARE_DEVICE_TYPE(TAITO_PCCARD2, taito_pccard2_device)
+DECLARE_DEVICE_TYPE(TAITO_COMPACT_FLASH, taito_compact_flash_device)
+DECLARE_DEVICE_TYPE(ATA_FLASH_PCCARD, ata_flash_pccard_device)
+
+#endif // MAME_BUS_PCCARD_ATAFLASH_H
diff --git a/src/devices/bus/pccard/k573npu.cpp b/src/devices/bus/pccard/k573npu.cpp
new file mode 100644
index 00000000000..f7109fee4f2
--- /dev/null
+++ b/src/devices/bus/pccard/k573npu.cpp
@@ -0,0 +1,101 @@
+// license:BSD-3-Clause
+// copyright-holders:smf
+/*
+ * Konami 573 Network PCB Unit
+ *
+ */
+
+#include "emu.h"
+#include "k573npu.h"
+
+/*
+
+ System 573 Hard Drive and Network Unit
+ --------------------------------------
+
+ This box is used with later Drum Mania and Guitar Freaks (possibly 9 to 11)
+
+ PCB Layout
+ ----------
+
+ PWB0000100991 (C)2001 KONAMI
+ |--------------------------------------------------------------------------|
+ | CN1 MB3793 74HC14 FLASH.24E RJ45 |
+ | |
+ | LCX245 DIP40 CN3|
+ |LCX245 LCX245|-------| PE68515L |
+ | | | DS2401 |--------| SP232 |
+ |PQ30RV21 |XC2S100| XC9572XL |NATIONAL| 25MHz |
+ | | | |DP83815 | 93LC46|
+ | |-------| | | |
+ | 74LS245 74LS245 |--------| L|
+ |PQ30RV21 74LS245 74LS245 L|
+ | IDE44 HDD_LED LCX245 LCX245 LCX245 DIPSW(8)L|
+ |---------------------------------| LCX245 LCX245 L|
+ | L|
+ | 74LS273 L|
+ | L|
+ | 48LC4M16 |------------| L|
+ | |TOSHIBA | |
+ | |TMPR3927CF | |
+ | | | 74LS245 |
+ | | | |
+ | | | |
+ | 48LC4M16 |------------| |
+ | |
+ | 8.28MHz CN2|
+ | |
+ |----------------------------------------|
+ Notes: (all IC's shown)
+ TMPR3927 - Toshiba TMPR3927CF Risc Microprocessor (QFP240)
+ FLASH - Fujitsu 29F400TC Flash ROM (TSOP48)
+ IDE44 - IDE44 44-pin laptop type HDD connector. The Hard Drive connected is a
+ 2.5" Fujitsu MHR2010AT 10GB HDD with Konami sticker C07JAA03
+ 48LC4M16 - Micron Technology 48LC4M16 4M x16-bit SDRAM (TSSOP54)
+ XC9572XL - XILINX XC9572XL In-system Programmable CPLD stamped 'UC07A1' (TQFP100)
+ XC2S100 - XILINX XC2S100 SPARTAN-II 2.5V FPGA (TQFP144)
+ DS2401 - MAXIM Dallas DS2401 Silicon Serial Number (SOIC6)
+ 93LC46 - 128 bytes x8-bit EEPROM (SOIC8)
+ MB3793 - Fujitsu MB3793 Power-Voltage Monitoring IC with Watchdog Timer (SOIC8)
+ PE68515L - Pulse PE-68515L 10/100 Base-T Single Port Transformer Module
+ DP83815 - National Semiconductor DP83815 10/100 Mb/s Integrated PCI Ethernet Media
+ Access Controller and Physical Layer (TQFP144)
+ SP232 - Sipex Corporation SP232 Enhanced RS-232 Line Drivers/Receiver (SOIC16)
+ RJ45 - RJ45 network connector
+ DIP40 - Empty DIP40 socket
+ CN1 - Custom multi-pin connector for special cable. The other end of the
+ cable has a PCMCIA card which plugs into the PCMCIA slot on a
+ System 573 main board
+ CN2 - 6-pin power input connector
+ CN3 - 4-pin connector
+ L - LED
+
+*/
+
+k573npu_device::k573npu_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) :
+ device_t(mconfig, KONAMI_573_NETWORK_PCB_UNIT, tag, owner, clock),
+ device_pccard_interface(mconfig, *this)
+{
+}
+
+ROM_START( k573npu )
+ ROM_REGION( 0x080000, "maincpu", 0 )
+ ROM_LOAD16_WORD_SWAP( "29f400.24e", 0x000000, 0x080000, CRC(8dcf294b) SHA1(efac79e18db22c30886463ec1bc448187da7a95a) )
+ROM_END
+
+const tiny_rom_entry *k573npu_device::device_rom_region() const
+{
+ return ROM_NAME( k573npu );
+}
+
+void k573npu_device::device_start()
+{
+}
+
+void k573npu_device::maincpu_program_map(address_map &map)
+{
+ map(0x00000000, 0x007fffff).ram();
+ map(0x1fc00000, 0x1fc7ffff).rom().region("maincpu", 0);
+}
+
+DEFINE_DEVICE_TYPE(KONAMI_573_NETWORK_PCB_UNIT, k573npu_device, "k573npu", "Konami 573 Network PCB Unit")
diff --git a/src/devices/bus/pccard/k573npu.h b/src/devices/bus/pccard/k573npu.h
new file mode 100644
index 00000000000..5b8f1a53ab1
--- /dev/null
+++ b/src/devices/bus/pccard/k573npu.h
@@ -0,0 +1,29 @@
+// license:BSD-3-Clause
+// copyright-holders:smf
+/*
+ * Konami 573 Network PCB Unit
+ *
+ */
+#ifndef MAME_BUS_PCCARD_K573NPU_H
+#define MAME_BUS_PCCARD_K573NPU_H
+
+#pragma once
+
+#include "pccard.h"
+
+class k573npu_device : public device_t,
+ public device_pccard_interface
+{
+public:
+ k573npu_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 ATTR_COLD;
+ virtual void device_start() override ATTR_COLD;
+
+ void maincpu_program_map(address_map &map) ATTR_COLD;
+};
+
+DECLARE_DEVICE_TYPE(KONAMI_573_NETWORK_PCB_UNIT, k573npu_device)
+
+#endif // MAME_BUS_PCCARD_K573NPU_H
diff --git a/src/devices/bus/pccard/konami_dual.cpp b/src/devices/bus/pccard/konami_dual.cpp
new file mode 100644
index 00000000000..e141fd71b21
--- /dev/null
+++ b/src/devices/bus/pccard/konami_dual.cpp
@@ -0,0 +1,93 @@
+// license:GPL-2.0+
+// copyright-holders:smf
+/*
+ |--|-------------------------|--|
+ | | | |
+ | | | |
+ | | | |
+ | | | |
+ | | | |
+ | | | |
+ | | | |
+ | | | |
+ | | PC Card slot 3 (bottom) | |
+ | | PC Card slot 4 (top) | |
+ | | | |
+ | | | |
+ | | | |
+ | | | |
+ | | | |
+ | | | |
+ | | | |
+ | | | |
+ | |-------------------------| |
+ | |
+ | |
+ | |
+ | |
+ | |
+ | |
+ | |
+ | |
+ | |
+ | 74LS245 74LS245 74LS245 |
+ | |
+ | 74LS245 74LS245 74LS245 |
+ | |
+ | |
+ | BD-8 BD-8 BD-8 BD-8 BD-8 BD-8 |
+ | |
+ | |
+ | |
+ | |
+ | |
+ | CN1 CN2 |
+ |-------------------------------|
+ Notes:
+ CN1 68 pin VHDCI connector
+ CN2 (unpopulated)
+
+ Requires ADAPTER PC Card PN 0000088797 & cable
+*/
+
+#include "emu.h"
+#include "konami_dual.h"
+#include "linflash.h"
+
+konami_dual_pccard_device::konami_dual_pccard_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) :
+ device_t(mconfig, KONAMI_DUAL_PCCARD, tag, owner, clock),
+ device_pccard_interface(mconfig, *this),
+ m_slot(*this, "slot%u", 3U)
+{
+}
+
+void konami_dual_pccard_device::device_add_mconfig(machine_config &config)
+{
+ for (size_t i = 0; i < m_slot.size(); i++)
+ {
+ PCCARD_SLOT(config, m_slot[i]);
+ m_slot[i]->option_add("16mb", FUJITSU_16MB_FLASH_CARD);
+ m_slot[i]->option_add("32mb", FUJITSU_32MB_FLASH_CARD);
+ m_slot[i]->option_add("id245p01", ID245P01);
+ m_slot[i]->option_add("pm24276", PM24276);
+ m_slot[i]->set_default_option("32mb");
+ }
+}
+
+void konami_dual_pccard_device::device_start()
+{
+ m_cd1_cb(0);
+ m_cd2_cb(0);
+}
+
+uint16_t konami_dual_pccard_device::read_memory(offs_t offset, uint16_t mem_mask)
+{
+ return m_slot[BIT(offset, 24)]->read_memory(BIT(offset, 0, 24), mem_mask);
+}
+
+void konami_dual_pccard_device::write_memory(offs_t offset, uint16_t data, uint16_t mem_mask)
+{
+ m_slot[BIT(offset, 24)]->write_memory(BIT(offset, 0, 24), data, mem_mask);
+}
+
+DEFINE_DEVICE_TYPE(KONAMI_DUAL_PCCARD, konami_dual_pccard_device, "konami_dual_pccard", "Konami Dual PC Card Adapter (PWB0000085455)")
diff --git a/src/devices/bus/pccard/konami_dual.h b/src/devices/bus/pccard/konami_dual.h
new file mode 100644
index 00000000000..c364aee57a2
--- /dev/null
+++ b/src/devices/bus/pccard/konami_dual.h
@@ -0,0 +1,30 @@
+// license:GPL-2.0+
+// copyright-holders:smf
+#ifndef MAME_BUS_PCCARD_KONAMI_DUAL_H
+#define MAME_BUS_PCCARD_KONAMI_DUAL_H
+
+#pragma once
+
+#include "pccard.h"
+
+class konami_dual_pccard_device :
+ public device_t,
+ public device_pccard_interface
+{
+public:
+ konami_dual_pccard_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock = 0);
+
+ virtual uint16_t read_memory(offs_t offset, uint16_t mem_mask = ~0) override;
+ virtual void write_memory(offs_t offset, uint16_t data, uint16_t mem_mask = ~0) override;
+
+protected:
+ // device_t
+ virtual void device_add_mconfig(machine_config &config) override ATTR_COLD;
+ virtual void device_start() override ATTR_COLD;
+
+ required_device_array<pccard_slot_device, 2> m_slot;
+};
+
+DECLARE_DEVICE_TYPE(KONAMI_DUAL_PCCARD, konami_dual_pccard_device)
+
+#endif // MAME_BUS_PCCARD_KONAMI_DUAL_H
diff --git a/src/devices/bus/pccard/linflash.cpp b/src/devices/bus/pccard/linflash.cpp
new file mode 100644
index 00000000000..0a6704c4d2d
--- /dev/null
+++ b/src/devices/bus/pccard/linflash.cpp
@@ -0,0 +1,249 @@
+// license:GPL-2.0+
+// copyright-holders:smf
+/*
+ Fujitsu 32MB Flash Card
+ -----------------------
+
+ Front
+
+ |----PCMCIA CONNECTOR-----|
+ | |
+ | HT04A MB624018 MB624019 |
+ | AT28C16 |
+ | |
+ | 29F017A.1L 29F017A.1U |
+ | 90PFTR 90PFTN |
+ | |
+ | 29F017A.2L 29F017A.2U |
+ | 90PFTN 90PFTR |
+ | |
+ | 29F017A.3L 29F017A.3U |
+ | 90PFTR 90PFTN |
+ | |
+ | 29F017A.4L 29F017A.4U |
+ | 90PFTN 90PFTR |
+ | |
+ |------------------SWITCH-|
+
+ Back
+
+ |----PCMCIA CONNECTOR-----|
+ | |
+ | |
+ | |
+ | |
+ | 29F017A.5U 29F017A.5L |
+ | 90PFTR 90PFTN |
+ | |
+ | 29F017A.6U 29F017A.6L |
+ | 90PFTN 90PFTR |
+ | |
+ | 29F017A.7U 29F017A.7L |
+ | 90PFTR 90PFTN |
+ | |
+ | 29F017A.8U 29F017A.8L |
+ | 90PFTN 90PFTR |
+ | |
+ |-SWITCH------------------|
+
+ Texas Instruments HT04A
+ Fujitsu MB624018 CMOS GATE ARRAY
+ Fujitsu MB624019 CMOS GATE ARRAY
+ Atmel AT28C16 16K (2K x 8) Parallel EEPROM
+ Fujitsu 29F017A-90PFTR 16M (2M x 8) BIT Flash Memory Reverse Pinout (Gacha Gachamp card used 29F017-12PFTR instead)
+ Fujitsu 29F017A-90PFTN 16M (2M x 8) BIT Flash Memory Standard Pinout
+
+*/
+
+#include "emu.h"
+#include "linflash.h"
+
+#define LOG_READ (1U << 1)
+#define LOG_WRITE (1U << 2)
+
+//#define VERBOSE (LOG_READ | LOG_WRITE)
+//#define LOG_OUTPUT_FUNC osd_printf_info
+#include "logmacro.h"
+
+#define LOGREAD(...) LOGMASKED(LOG_READ, __VA_ARGS__)
+#define LOGWRITE(...) LOGMASKED(LOG_WRITE, __VA_ARGS__)
+
+linear_flash_pccard_device::linear_flash_pccard_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock, address_map_constructor amap) :
+ device_t(mconfig, type, tag, owner, clock),
+ device_pccard_interface(mconfig, *this),
+ device_memory_interface(mconfig, *this),
+ m_space_config("memory", ENDIANNESS_LITTLE, 16, 26, 0, amap),
+ m_wp(0)
+{
+}
+
+namespace {
+
+static INPUT_PORTS_START(linflash)
+ PORT_START("CONF")
+ PORT_CONFNAME(0x01, 0x00, "Write Protect") PORT_WRITE_LINE_DEVICE_MEMBER(DEVICE_SELF, FUNC(linear_flash_pccard_device::update_wp))
+ PORT_CONFSETTING( 0x01, DEF_STR(Yes))
+ PORT_CONFSETTING( 0x00, DEF_STR(No))
+INPUT_PORTS_END
+
+}; // anonymous namespace
+
+ioport_constructor linear_flash_pccard_device::device_input_ports() const
+{
+ return INPUT_PORTS_NAME(linflash);
+}
+
+void linear_flash_pccard_device::device_start()
+{
+ m_space = &space(0);
+ m_cd1_cb(0);
+ m_cd2_cb(0);
+
+ // Correct for ID245P01, TODO: check other cards
+ m_bvd1_cb(1);
+ m_bvd2_cb(1);
+
+ save_item(NAME(m_wp));
+
+ m_wp_cb(m_wp);
+}
+
+device_memory_interface::space_config_vector linear_flash_pccard_device::memory_space_config() const
+{
+ return space_config_vector{ std::make_pair(0, &m_space_config) };
+}
+
+uint16_t linear_flash_pccard_device::read_memory(offs_t offset, uint16_t mem_mask)
+{
+ uint16_t data = m_space->read_word(offset * 2, mem_mask);
+ LOGREAD("%s read_memory(%08x, %08x) %08x\n", machine().describe_context(), offset, mem_mask, data);
+ return data;
+}
+
+void linear_flash_pccard_device::write_memory(offs_t offset, uint16_t data, uint16_t mem_mask)
+{
+ LOGWRITE("%s write_memory(%08x, %08x, %08x)%s\n", machine().describe_context(), offset, data, mem_mask, m_wp ? " (write protected)" : "");
+ if (!m_wp)
+ m_space->write_word(offset * 2, data, mem_mask);
+}
+
+void linear_flash_pccard_device::update_wp(int state)
+{
+ if (m_wp != state)
+ {
+ m_wp = state;
+ m_wp_cb(m_wp);
+ }
+}
+
+
+template<unsigned N>
+linear_flash_pccard_8bit_device<N>::linear_flash_pccard_8bit_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock) :
+ linear_flash_pccard_device(mconfig, type, tag, owner, clock, address_map_constructor(FUNC(linear_flash_pccard_8bit_device<N>::amap), this)),
+ m_l(*this, "%ul", 1U),
+ m_u(*this, "%uu", 1U)
+{
+}
+
+template<unsigned N>
+void linear_flash_pccard_8bit_device<N>::amap(address_map &map)
+{
+ map.global_mask((N * 0x00400000) - 1);
+
+ for (size_t i = 0; i < N; i++)
+ {
+ map(0x00400000 * i, (0x00400000 * (i + 1)) - 1).rw(m_l[i], FUNC(intelfsh8_device::read), FUNC(intelfsh8_device::write)).umask16(0x00ff);
+ map(0x00400000 * i, (0x00400000 * (i + 1)) - 1).rw(m_u[i], FUNC(intelfsh8_device::read), FUNC(intelfsh8_device::write)).umask16(0xff00);
+ }
+}
+
+
+template<unsigned N>
+linear_flash_pccard_16bit_device<N>::linear_flash_pccard_16bit_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock) :
+ linear_flash_pccard_device(mconfig, type, tag, owner, clock, address_map_constructor(FUNC(linear_flash_pccard_16bit_device<N>::amap), this)),
+ m_flash(*this, "flash.%u", 1U)
+{
+}
+
+template<unsigned N>
+void linear_flash_pccard_16bit_device<N>::amap(address_map &map)
+{
+ map.global_mask((m_flash.size() * 0x00800000) - 1);
+
+ for (size_t i = 0; i < N; i++)
+ map(0x00800000 * i, (0x00800000 * (i + 1)) - 1).rw(m_flash[i], FUNC(intelfsh16_device::read), FUNC(intelfsh16_device::write));
+}
+
+
+template<unsigned N>
+linear_flash_pccard_29f017a_device<N>::linear_flash_pccard_29f017a_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock) :
+ linear_flash_pccard_8bit_device<N>(mconfig, type, tag, owner, clock)
+{
+}
+
+template<unsigned N>
+void linear_flash_pccard_29f017a_device<N>::device_add_mconfig(machine_config &config)
+{
+ for (size_t i = 0; i < N; i++)
+ {
+ FUJITSU_29F016A(config, linear_flash_pccard_8bit_device<N>::m_l[i]);
+ FUJITSU_29F016A(config, linear_flash_pccard_8bit_device<N>::m_u[i]);
+ }
+}
+
+
+template<unsigned N>
+linear_flash_pccard_lh28f016s_device<N>::linear_flash_pccard_lh28f016s_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock) :
+ linear_flash_pccard_8bit_device<N>(mconfig, type, tag, owner, clock)
+{
+}
+
+
+template<unsigned N>
+void linear_flash_pccard_lh28f016s_device<N>::device_add_mconfig(machine_config &config)
+{
+ for (size_t i = 0; i < N; i++)
+ {
+ SHARP_LH28F016S(config, linear_flash_pccard_8bit_device<N>::m_l[i]);
+ SHARP_LH28F016S(config, linear_flash_pccard_8bit_device<N>::m_u[i]);
+ }
+}
+
+
+template<unsigned N>
+linear_flash_pccard_28f640j5_device<N>::linear_flash_pccard_28f640j5_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock) :
+ linear_flash_pccard_16bit_device<N>(mconfig, type, tag, owner, clock)
+{
+}
+
+template<unsigned N>
+void linear_flash_pccard_28f640j5_device<N>::device_add_mconfig(machine_config &config)
+{
+ for (size_t i = 0; i < N; i++)
+ INTEL_28F640J5(config, linear_flash_pccard_16bit_device<N>::m_flash[i]);
+}
+
+fujitsu_16mb_flash_card_device::fujitsu_16mb_flash_card_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) :
+ linear_flash_pccard_29f017a_device(mconfig, FUJITSU_16MB_FLASH_CARD, tag, owner, clock)
+{
+}
+
+fujitsu_32mb_flash_card_device::fujitsu_32mb_flash_card_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) :
+ linear_flash_pccard_29f017a_device(mconfig, FUJITSU_32MB_FLASH_CARD, tag, owner, clock)
+{
+}
+
+id245p01_device::id245p01_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) :
+ linear_flash_pccard_lh28f016s_device(mconfig, ID245P01, tag, owner, clock)
+{
+}
+
+pm24276_device::pm24276_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) :
+ linear_flash_pccard_28f640j5_device(mconfig, PM24276, tag, owner, clock)
+{
+}
+
+DEFINE_DEVICE_TYPE(FUJITSU_16MB_FLASH_CARD, fujitsu_16mb_flash_card_device, "fujitsu_16mb_flash_card", "Fujitsu 16MB Flash Card")
+DEFINE_DEVICE_TYPE(FUJITSU_32MB_FLASH_CARD, fujitsu_32mb_flash_card_device, "fujitsu_32mb_flash_card", "Fujitsu 32MB Flash Card")
+DEFINE_DEVICE_TYPE(ID245P01, id245p01_device, "id245p01", "Sharp ID245P01 32MB Linear Flash Memory Card")
+DEFINE_DEVICE_TYPE(PM24276, pm24276_device, "pm24276", "PM24276 32MB Linear Flash Memory Card")
diff --git a/src/devices/bus/pccard/linflash.h b/src/devices/bus/pccard/linflash.h
new file mode 100644
index 00000000000..07a8b9ccba6
--- /dev/null
+++ b/src/devices/bus/pccard/linflash.h
@@ -0,0 +1,124 @@
+// license:GPL-2.0+
+// copyright-holders:smf
+#ifndef MAME_BUS_PCCARD_LINFLASH_H
+#define MAME_BUS_PCCARD_LINFLASH_H
+
+#pragma once
+
+#include "machine/intelfsh.h"
+#include "pccard.h"
+
+class linear_flash_pccard_device :
+ public device_t,
+ public device_pccard_interface,
+ public device_memory_interface
+{
+public:
+ virtual uint16_t read_memory(offs_t offset, uint16_t mem_mask = ~0) override;
+ virtual void write_memory(offs_t offset, uint16_t data, uint16_t mem_mask = ~0) override;
+
+ void update_wp(int state);
+
+protected:
+ linear_flash_pccard_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock, address_map_constructor amap);
+
+ // device_t
+ virtual ioport_constructor device_input_ports() const override ATTR_COLD;
+ virtual void device_start() override ATTR_COLD;
+
+ // device_memory_interface
+ virtual space_config_vector memory_space_config() const override;
+
+ address_space_config m_space_config;
+ address_space *m_space;
+ int8_t m_wp;
+};
+
+template<unsigned N>
+class linear_flash_pccard_8bit_device :
+ public linear_flash_pccard_device
+{
+protected:
+ linear_flash_pccard_8bit_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock);
+
+ void amap(address_map &map) ATTR_COLD;
+
+ required_device_array<intelfsh8_device, N> m_l;
+ required_device_array<intelfsh8_device, N> m_u;
+};
+
+template<unsigned N>
+class linear_flash_pccard_16bit_device :
+ public linear_flash_pccard_device
+{
+protected:
+ linear_flash_pccard_16bit_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock);
+
+ void amap(address_map &map) ATTR_COLD;
+
+ required_device_array<intelfsh16_device, N> m_flash;
+};
+
+template<unsigned N>
+class linear_flash_pccard_29f017a_device :
+ public linear_flash_pccard_8bit_device<N>
+{
+protected:
+ linear_flash_pccard_29f017a_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock);
+
+ // device_t
+ virtual void device_add_mconfig(machine_config &config) override ATTR_COLD;
+};
+
+template<unsigned N>
+class linear_flash_pccard_lh28f016s_device :
+ public linear_flash_pccard_8bit_device<N>
+{
+protected:
+ linear_flash_pccard_lh28f016s_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock);
+
+ // device_t
+ virtual void device_add_mconfig(machine_config &config) override ATTR_COLD;
+};
+
+template<unsigned N>
+class linear_flash_pccard_28f640j5_device :
+ public linear_flash_pccard_16bit_device<N>
+{
+protected:
+ linear_flash_pccard_28f640j5_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock);
+
+ // device_t
+ virtual void device_add_mconfig(machine_config &config) override ATTR_COLD;
+};
+
+class fujitsu_16mb_flash_card_device : public linear_flash_pccard_29f017a_device<4>
+{
+public:
+ fujitsu_16mb_flash_card_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
+};
+
+class fujitsu_32mb_flash_card_device : public linear_flash_pccard_29f017a_device<8>
+{
+public:
+ fujitsu_32mb_flash_card_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
+};
+
+class id245p01_device : public linear_flash_pccard_lh28f016s_device<8>
+{
+public:
+ id245p01_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
+};
+
+class pm24276_device : public linear_flash_pccard_28f640j5_device<4>
+{
+public:
+ pm24276_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
+};
+
+DECLARE_DEVICE_TYPE(FUJITSU_16MB_FLASH_CARD, fujitsu_16mb_flash_card_device)
+DECLARE_DEVICE_TYPE(FUJITSU_32MB_FLASH_CARD, fujitsu_32mb_flash_card_device)
+DECLARE_DEVICE_TYPE(ID245P01, id245p01_device)
+DECLARE_DEVICE_TYPE(PM24276, pm24276_device)
+
+#endif // MAME_BUS_PCCARD_LINFLASH_H
diff --git a/src/devices/bus/pccard/pccard.cpp b/src/devices/bus/pccard/pccard.cpp
new file mode 100644
index 00000000000..f90d01510da
--- /dev/null
+++ b/src/devices/bus/pccard/pccard.cpp
@@ -0,0 +1,122 @@
+// license:GPL-2.0+
+// copyright-holders:smf
+#include "emu.h"
+#include "pccard.h"
+
+//#define VERBOSE 1
+#include "logmacro.h"
+
+device_pccard_interface::device_pccard_interface(const machine_config &mconfig, device_t &device) :
+ device_interface(device, "pccard"),
+ m_cd1_cb(*this),
+ m_cd2_cb(*this),
+ m_bvd1_cb(*this),
+ m_bvd2_cb(*this),
+ m_wp_cb(*this)
+{
+}
+
+uint16_t device_pccard_interface::read_memory(offs_t offset, uint16_t mem_mask)
+{
+ if (VERBOSE & LOG_GENERAL)
+ device().logerror("unhandled memory read %08x %04x\n", offset, mem_mask);
+ return 0xffff;
+}
+
+void device_pccard_interface::write_memory(offs_t offset, uint16_t data, uint16_t mem_mask)
+{
+ if (VERBOSE & LOG_GENERAL)
+ device().logerror("unhandled memory write %08x %04x %04x\n", offset, data, mem_mask);
+}
+
+uint16_t device_pccard_interface::read_reg(offs_t offset, uint16_t mem_mask)
+{
+ if (VERBOSE & LOG_GENERAL)
+ device().logerror("unhandled register read %08x %04x\n", offset, mem_mask);
+ return 0xffff;
+}
+
+void device_pccard_interface::write_reg(offs_t offset, uint16_t data, uint16_t mem_mask)
+{
+ if (VERBOSE & LOG_GENERAL)
+ device().logerror("unhandled register write %08x %04x %04x\n", offset, data, mem_mask);
+}
+
+pccard_slot_device::pccard_slot_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) :
+ device_t(mconfig, PCCARD_SLOT, tag, owner, clock),
+ device_single_card_slot_interface<device_pccard_interface>(mconfig, *this),
+ device_pccard_interface(mconfig, *this)
+{
+}
+
+void pccard_slot_device::device_config_complete()
+{
+ m_dev = get_card_device();
+ if (m_dev)
+ {
+ m_dev->cd1().set(*this, FUNC(pccard_slot_device::update_cd1));
+ m_dev->cd2().set(*this, FUNC(pccard_slot_device::update_cd2));
+ m_dev->bvd1().set(*this, FUNC(pccard_slot_device::update_bvd1));
+ m_dev->bvd2().set(*this, FUNC(pccard_slot_device::update_bvd2));
+ m_dev->wp().set(*this, FUNC(pccard_slot_device::update_wp));
+ }
+}
+
+void pccard_slot_device::device_start()
+{
+}
+
+uint16_t pccard_slot_device::read_memory(offs_t offset, uint16_t mem_mask)
+{
+ if (m_dev)
+ return m_dev->read_memory(offset, mem_mask);
+ else
+ return 0xffff;
+}
+
+void pccard_slot_device::write_memory(offs_t offset, uint16_t data, uint16_t mem_mask)
+{
+ if (m_dev)
+ m_dev->write_memory(offset, data, mem_mask);
+}
+
+uint16_t pccard_slot_device::read_reg(offs_t offset, uint16_t mem_mask)
+{
+ if (m_dev)
+ return m_dev->read_reg(offset, mem_mask);
+ else
+ return 0xffff;
+}
+
+void pccard_slot_device::write_reg(offs_t offset, uint16_t data, uint16_t mem_mask)
+{
+ if (m_dev)
+ m_dev->write_reg(offset, data, mem_mask);
+}
+
+void pccard_slot_device::update_cd1(int state)
+{
+ m_cd1_cb(state);
+}
+
+void pccard_slot_device::update_cd2(int state)
+{
+ m_cd2_cb(state);
+}
+
+void pccard_slot_device::update_bvd1(int state)
+{
+ m_bvd1_cb(state);
+}
+
+void pccard_slot_device::update_bvd2(int state)
+{
+ m_bvd2_cb(state);
+}
+
+void pccard_slot_device::update_wp(int state)
+{
+ m_wp_cb(state);
+}
+
+DEFINE_DEVICE_TYPE(PCCARD_SLOT, pccard_slot_device, "pccard", "PC Card Slot")
diff --git a/src/devices/bus/pccard/pccard.h b/src/devices/bus/pccard/pccard.h
new file mode 100644
index 00000000000..9af4d483232
--- /dev/null
+++ b/src/devices/bus/pccard/pccard.h
@@ -0,0 +1,87 @@
+// license:GPL-2.0+
+// copyright-holders:smf
+#ifndef MAME_BUS_PCCARD_PCCARD_H
+#define MAME_BUS_PCCARD_PCCARD_H
+
+#pragma once
+
+class pccard_slot_device;
+
+class device_pccard_interface :
+ public device_interface
+{
+public:
+ virtual ~device_pccard_interface() {}
+
+ virtual uint16_t read_memory(offs_t offset, uint16_t mem_mask = ~0);
+ virtual uint16_t read_reg(offs_t offset, uint16_t mem_mask = ~0);
+ virtual void write_memory(offs_t offset, uint16_t data, uint16_t mem_mask = ~0);
+ virtual void write_reg(offs_t offset, uint16_t data, uint16_t mem_mask = ~0);
+
+ // 16-bit byte swapped trampolines
+ uint16_t read_memory_swap(offs_t offset, uint16_t mem_mask = 0xffff) { return swapendian_int16(read_memory(offset, swapendian_int16(mem_mask))); }
+ uint16_t read_reg_swap(offs_t offset, uint16_t mem_mask = 0xffff) { return swapendian_int16(read_reg(offset, swapendian_int16(mem_mask))); }
+ void write_memory_swap(offs_t offset, uint16_t data, uint16_t mem_mask = 0xffff) { write_memory(offset, swapendian_int16(data), swapendian_int16(mem_mask)); }
+ void write_reg_swap(offs_t offset, uint16_t data, uint16_t mem_mask = 0xffff) { write_reg(offset, swapendian_int16(data), swapendian_int16(mem_mask)); }
+
+ // 8-bit trampolines
+ uint8_t read_memory_byte(offs_t offset) { return read_memory(offset >> 1, 0xff << (BIT(offset, 0) * 8)) >> (BIT(offset, 0) * 8); }
+ uint8_t read_reg_byte(offs_t offset) { return read_reg(offset >> 1, 0xff << (BIT(offset, 0) * 8)) >> (BIT(offset, 0) * 8); }
+ void write_memory_byte(offs_t offset, uint8_t data) { write_memory(offset >> 1, data << (BIT(offset, 0) * 8), 0xff << (BIT(offset, 0) * 8)); }
+ void write_reg_byte(offs_t offset, uint8_t data) { write_reg(offset >> 1, data << (BIT(offset, 0) * 8), 0xff << (BIT(offset, 0) * 8)); }
+
+ auto cd1() { return m_cd1_cb.bind(); }
+ auto cd2() { return m_cd2_cb.bind(); }
+ auto bvd1() { return m_bvd1_cb.bind(); }
+ auto bvd2() { return m_bvd2_cb.bind(); }
+ auto wp() { return m_wp_cb.bind(); }
+
+protected:
+ device_pccard_interface(const machine_config &mconfig, device_t &device);
+
+ devcb_write_line m_cd1_cb;
+ devcb_write_line m_cd2_cb;
+ devcb_write_line m_bvd1_cb;
+ devcb_write_line m_bvd2_cb;
+ devcb_write_line m_wp_cb;
+};
+
+class pccard_slot_device :
+ public device_t,
+ public device_single_card_slot_interface<device_pccard_interface>,
+ public device_pccard_interface
+{
+public:
+ pccard_slot_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock = 0);
+
+ template <typename T>
+ pccard_slot_device(machine_config const &mconfig, char const *tag, device_t *owner, T &&opts, char const *dflt)
+ : pccard_slot_device(mconfig, tag, owner, (uint32_t)0)
+ {
+ option_reset();
+ opts(*this);
+ set_default_option(dflt);
+ set_fixed(false);
+ }
+
+ virtual uint16_t read_memory(offs_t offset, uint16_t mem_mask = ~0) override;
+ virtual uint16_t read_reg(offs_t offset, uint16_t mem_mask = ~0) override;
+ virtual void write_memory(offs_t offset, uint16_t data, uint16_t mem_mask = ~0) override;
+ virtual void write_reg(offs_t offset, uint16_t data, uint16_t mem_mask = ~0) override;
+
+protected:
+ virtual void device_config_complete() override;
+ virtual void device_start() override ATTR_COLD;
+
+ void update_cd1(int state);
+ void update_cd2(int state);
+ void update_bvd1(int state);
+ void update_bvd2(int state);
+ void update_wp(int state);
+
+ device_pccard_interface *m_dev;
+};
+
+DECLARE_DEVICE_TYPE(PCCARD_SLOT, pccard_slot_device)
+
+#endif // MAME_BUS_PCCARD_PCCARD_H
diff --git a/src/devices/bus/pccard/sram.cpp b/src/devices/bus/pccard/sram.cpp
new file mode 100644
index 00000000000..dadb86104f4
--- /dev/null
+++ b/src/devices/bus/pccard/sram.cpp
@@ -0,0 +1,413 @@
+// license: BSD-3-Clause
+// copyright-holders: Dirk Best
+/***************************************************************************
+
+ SRAM PC Cards
+
+***************************************************************************/
+
+#include "emu.h"
+#include "sram.h"
+#include "machine/nvram.h"
+
+#define LOG_ATTRIBUTE (1U << 1)
+
+#define VERBOSE (LOG_GENERAL | LOG_ATTRIBUTE)
+#include "logmacro.h"
+
+
+//**************************************************************************
+// DEVICE DEFINITIONS
+//**************************************************************************
+
+// devices without attribute memory
+DEFINE_DEVICE_TYPE(PCCARD_SRAM_MITSUBISHI_1M, pccard_mitsubishi_mf31m1_lycat01_device, "mitsubishi_mf31m1_lycat01", "Mitsubishi Melcard 1 MB SRAM")
+
+// devices with attribute memory
+DEFINE_DEVICE_TYPE(PCCARD_SRAM_CENTENNIAL_1M, pccard_centennial_sl01m_15_11194_device, "centennial_sl01m_15_11194", "Centennial 1 MB SRAM")
+DEFINE_DEVICE_TYPE(PCCARD_SRAM_CENTENNIAL_2M, pccard_centennial_sl02m_15_11194_device, "centennial_sl02m_15_11194", "Centennial 2 MB SRAM")
+DEFINE_DEVICE_TYPE(PCCARD_SRAM_CENTENNIAL_4M, pccard_centennial_sl04m_15_11194_device, "centennial_sl04m_15_11194", "Centennial 4 MB SRAM")
+
+//-------------------------------------------------
+// inputs
+//-------------------------------------------------
+
+static INPUT_PORTS_START( card )
+ PORT_START("switches")
+ PORT_CONFNAME(0x01, 0x01, "Battery Failed") PORT_WRITE_LINE_DEVICE_MEMBER(DEVICE_SELF, FUNC(pccard_sram_device::battery_voltage_1_w))
+ PORT_CONFSETTING( 0x00, DEF_STR(Yes))
+ PORT_CONFSETTING( 0x01, DEF_STR(No))
+ PORT_CONFNAME(0x02, 0x02, "Battery Low") PORT_WRITE_LINE_DEVICE_MEMBER(DEVICE_SELF, FUNC(pccard_sram_device::battery_voltage_2_w))
+ PORT_CONFSETTING( 0x00, DEF_STR(Yes))
+ PORT_CONFSETTING( 0x02, DEF_STR(No))
+ PORT_CONFNAME(0x04, 0x00, "Write Protect") PORT_WRITE_LINE_DEVICE_MEMBER(DEVICE_SELF, FUNC(pccard_sram_device::write_protect_w))
+ PORT_CONFSETTING( 0x04, DEF_STR(Yes))
+ PORT_CONFSETTING( 0x00, DEF_STR(No))
+INPUT_PORTS_END
+
+ioport_constructor pccard_sram_device::device_input_ports() const
+{
+ return INPUT_PORTS_NAME(card);
+}
+
+
+//**************************************************************************
+// LIVE DEVICE
+//**************************************************************************
+
+//-------------------------------------------------
+// pccard_sram_device - constructor
+//-------------------------------------------------
+
+pccard_sram_device::pccard_sram_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_image_interface(mconfig, *this),
+ device_pccard_interface(mconfig, *this),
+ m_cd(1),
+ m_bvd1(1),
+ m_bvd2(1),
+ m_wp(0)
+{
+}
+
+//-------------------------------------------------
+// device_start - device-specific startup
+//-------------------------------------------------
+
+void pccard_sram_device::device_start()
+{
+ save_item(NAME(m_cd));
+ save_item(NAME(m_bvd1));
+ save_item(NAME(m_bvd2));
+ save_item(NAME(m_wp));
+
+ set_cd(m_cd);
+}
+
+//-------------------------------------------------
+// memory_space_config - configure memory space
+//-------------------------------------------------
+
+device_memory_interface::space_config_vector pccard_sram_device::memory_space_config() const
+{
+ return space_config_vector
+ {
+ std::make_pair(0, &m_memory_space_config),
+ std::make_pair(1, &m_attribute_space_config)
+ };
+}
+
+//-------------------------------------------------
+// device_pccard_interface
+//-------------------------------------------------
+
+uint16_t pccard_sram_device::read_memory(offs_t offset, uint16_t mem_mask)
+{
+ uint16_t data = 0xffff;
+
+ if (!m_cd)
+ data = space(0).read_word(offset * 2, mem_mask);
+
+ return data;
+}
+
+void pccard_sram_device::write_memory(offs_t offset, uint16_t data, uint16_t mem_mask)
+{
+ if (!m_cd && !m_wp)
+ space(0).write_word(offset * 2, data, mem_mask);
+}
+
+uint16_t pccard_sram_device::read_reg(offs_t offset, uint16_t mem_mask)
+{
+ uint16_t data = 0xffff;
+
+ if (!m_cd && has_configured_map(1))
+ data = space(1).read_word(offset * 2, mem_mask);
+
+ LOGMASKED(LOG_ATTRIBUTE, "attribute memory r: %06x = %04x & %04x\n", offset, data, mem_mask);
+
+ return data & 0x00ff;
+}
+
+void pccard_sram_device::write_reg(offs_t offset, uint16_t data, uint16_t mem_mask)
+{
+ LOGMASKED(LOG_ATTRIBUTE, "attribute memory w: %06x = %04x & %04x\n", offset, data, mem_mask);
+
+ if (!m_cd && !m_wp && has_configured_map(1))
+ space(1).write_word(offset * 2, data & 0x00ff, mem_mask);
+}
+
+void pccard_sram_device::set_cd(bool state)
+{
+ m_cd = state;
+ m_cd1_cb(m_cd);
+ m_cd2_cb(m_cd);
+ m_bvd1_cb(m_bvd1 || m_cd);
+ m_bvd2_cb(m_bvd2 || m_cd);
+ m_wp_cb(m_wp || m_cd);
+}
+
+void pccard_sram_device::battery_voltage_1_w(int state)
+{
+ if (m_bvd1 != state)
+ {
+ m_bvd1 = state;
+
+ if (!m_cd)
+ m_bvd1_cb(m_bvd1);
+ }
+}
+
+void pccard_sram_device::battery_voltage_2_w(int state)
+{
+ if (m_bvd2 != state)
+ {
+ m_bvd2 = state;
+
+ if (!m_cd)
+ m_bvd2_cb(m_bvd2);
+ }
+}
+
+void pccard_sram_device::write_protect_w(int state)
+{
+ if (m_wp != state)
+ {
+ m_wp = state;
+
+ if (!m_cd)
+ m_wp_cb(m_wp);
+ }
+}
+
+/***************************************************************************
+
+ Mitsubishi Melcard
+
+ MF31M1-LYCAT01: 8/16-bit Data Bus Static RAM Card
+
+***************************************************************************/
+
+pccard_mitsubishi_sram_device::pccard_mitsubishi_sram_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock) :
+ pccard_sram_device(mconfig, type, tag, owner, clock),
+ m_sram(*this, "sram")
+{
+}
+
+std::pair<std::error_condition, std::string> pccard_mitsubishi_sram_device::call_load()
+{
+ set_cd(1);
+
+ if (length() != m_sram.bytes())
+ return std::make_pair(image_error::INVALIDLENGTH, std::string());
+
+ if (fread(&m_sram[0], m_sram.bytes()) != m_sram.bytes())
+ return std::make_pair(image_error::UNSPECIFIED, std::string());
+
+ set_cd(0);
+
+ return std::make_pair(std::error_condition(), std::string());
+}
+
+std::pair<std::error_condition, std::string> pccard_mitsubishi_sram_device::call_create(int format_type, util::option_resolution *format_options)
+{
+ set_cd(1);
+
+ // clear ram
+ std::fill_n(&m_sram[0], m_sram.length(), 0);
+
+ if (fwrite(&m_sram[0], m_sram.bytes()) != m_sram.bytes())
+ return std::make_pair(image_error::UNSPECIFIED, std::string());
+
+ set_cd(0);
+
+ return std::make_pair(std::error_condition(), std::string());
+}
+
+void pccard_mitsubishi_sram_device::call_unload()
+{
+ if (!m_cd && !is_readonly())
+ {
+ fseek(0, SEEK_SET);
+ fwrite(&m_sram[0], m_sram.bytes());
+ }
+
+ std::fill_n(&m_sram[0], m_sram.length(), 0);
+
+ set_cd(1);
+}
+
+pccard_mitsubishi_mf31m1_lycat01_device::pccard_mitsubishi_mf31m1_lycat01_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) :
+ pccard_mitsubishi_sram_device(mconfig, PCCARD_SRAM_MITSUBISHI_1M, tag, owner, clock)
+{
+ m_memory_space_config = address_space_config("memory", ENDIANNESS_LITTLE, 16, 20, 0, address_map_constructor(FUNC(pccard_mitsubishi_mf31m1_lycat01_device::memory_map), this));
+ m_attribute_space_config = address_space_config("attribute", ENDIANNESS_LITTLE, 16, 14, 0);
+}
+
+void pccard_mitsubishi_mf31m1_lycat01_device::memory_map(address_map &map)
+{
+ map(0x000000, 0x0fffff).ram().share("sram");
+}
+
+
+/***************************************************************************
+
+ Centennial SRAM
+
+ SL01M-15-11194: 1 MB SRAM w/ Write Protect - 150 ns Rechargeable Lithium Battery
+ SL02M-15-11194: 2 MB SRAM w/ Write Protect - 150 ns Rechargeable Lithium Battery
+ SL04M-15-11194: 4 MB SRAM w/ Write Protect - 150 ns Rechargeable Lithium Battery
+
+ TODO:
+ - Get a real EEPROM dump from a factory new card and verify attribute
+ memory map
+ - Add more variants
+
+ Notes:
+ - EEPROM type is probably 28C64A, possible variants with 28C16A
+
+***************************************************************************/
+
+pccard_centennial_sram_device::pccard_centennial_sram_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock) :
+ pccard_sram_device(mconfig, type, tag, owner, clock),
+ m_sram(*this, "sram"),
+ m_eeprom(*this, "eeprom"),
+ m_eeprom_default(*this, "eeprom")
+{
+}
+
+std::pair<std::error_condition, std::string> pccard_centennial_sram_device::call_load()
+{
+ set_cd(1);
+
+ if (length() != m_sram.bytes() + m_eeprom.bytes())
+ return std::make_pair(image_error::INVALIDLENGTH, std::string());
+
+ if (fread(&m_sram[0], m_sram.bytes()) != m_sram.bytes())
+ return std::make_pair(image_error::UNSPECIFIED, std::string());
+
+ if (fread(&m_eeprom[0], m_eeprom.bytes()) != m_eeprom.bytes())
+ return std::make_pair(image_error::UNSPECIFIED, std::string());
+
+ set_cd(0);
+
+ return std::make_pair(std::error_condition(), std::string());
+}
+
+std::pair<std::error_condition, std::string> pccard_centennial_sram_device::call_create(int format_type, util::option_resolution *format_options)
+{
+ set_cd(1);
+
+ // clear ram
+ std::fill_n(&m_sram[0], m_sram.length(), 0);
+
+ // initialize EEPROM data from default data
+ std::copy_n(m_eeprom_default->base(), m_eeprom.length(), &m_eeprom[0]);
+
+ if (fwrite(&m_sram[0], m_sram.bytes()) != m_sram.bytes())
+ return std::make_pair(image_error::UNSPECIFIED, std::string());
+
+ if (fwrite(&m_eeprom[0], m_eeprom.bytes()) != m_eeprom.bytes())
+ return std::make_pair(image_error::UNSPECIFIED, std::string());
+
+ set_cd(0);
+
+ return std::make_pair(std::error_condition(), std::string());
+}
+
+void pccard_centennial_sram_device::call_unload()
+{
+ if (!m_cd && !is_readonly())
+ {
+ fseek(0, SEEK_SET);
+ fwrite(&m_sram[0], m_sram.bytes());
+ fwrite(&m_eeprom[0], m_eeprom.bytes());
+ }
+
+ std::fill_n(&m_sram[0], m_sram.length(), 0);
+ std::fill_n(&m_eeprom[0], m_eeprom.length(), 0);
+
+ set_cd(1);
+}
+
+pccard_centennial_sl01m_15_11194_device::pccard_centennial_sl01m_15_11194_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) :
+ pccard_centennial_sram_device(mconfig, PCCARD_SRAM_CENTENNIAL_1M, tag, owner, clock)
+{
+ m_memory_space_config = address_space_config("memory", ENDIANNESS_LITTLE, 16, 20, 0, address_map_constructor(FUNC(pccard_centennial_sl01m_15_11194_device::memory_map), this));
+ m_attribute_space_config = address_space_config("attribute", ENDIANNESS_LITTLE, 16, 14, 0, address_map_constructor(FUNC(pccard_centennial_sl01m_15_11194_device::attribute_map), this));
+}
+
+void pccard_centennial_sl01m_15_11194_device::memory_map(address_map &map)
+{
+ map(0x000000, 0x0fffff).ram().share("sram");
+}
+
+void pccard_centennial_sl01m_15_11194_device::attribute_map(address_map &map)
+{
+ map(0x00000, 0x03fff).ram().share("eeprom");
+}
+
+ROM_START( eeprom_01 )
+ ROM_REGION(0x2000, "eeprom", 0)
+ ROM_LOAD("eeprom.bin", 0x0000, 0x2000, BAD_DUMP CRC(2caacff3) SHA1(8141459dccf63a64f4bdf4e2171b0884f2cc390d))
+ROM_END
+
+const tiny_rom_entry *pccard_centennial_sl01m_15_11194_device::device_rom_region() const
+{
+ return ROM_NAME( eeprom_01 );
+}
+
+pccard_centennial_sl02m_15_11194_device::pccard_centennial_sl02m_15_11194_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) :
+ pccard_centennial_sram_device(mconfig, PCCARD_SRAM_CENTENNIAL_2M, tag, owner, clock)
+{
+ m_memory_space_config = address_space_config("memory", ENDIANNESS_LITTLE, 16, 21, 0, address_map_constructor(FUNC(pccard_centennial_sl02m_15_11194_device::memory_map), this));
+ m_attribute_space_config = address_space_config("attribute", ENDIANNESS_LITTLE, 16, 14, 0, address_map_constructor(FUNC(pccard_centennial_sl02m_15_11194_device::attribute_map), this));
+}
+
+void pccard_centennial_sl02m_15_11194_device::memory_map(address_map &map)
+{
+ map(0x000000, 0x1fffff).ram().share("sram");
+}
+
+void pccard_centennial_sl02m_15_11194_device::attribute_map(address_map &map)
+{
+ map(0x00000, 0x03fff).ram().share("eeprom");
+}
+
+ROM_START( eeprom_02 )
+ ROM_REGION(0x2000, "eeprom", 0)
+ ROM_LOAD("eeprom.bin", 0x0000, 0x2000, BAD_DUMP CRC(0d094f14) SHA1(a542a7395b306b9e34fd0be42d895b7b30013390))
+ROM_END
+
+const tiny_rom_entry *pccard_centennial_sl02m_15_11194_device::device_rom_region() const
+{
+ return ROM_NAME( eeprom_02 );
+}
+
+pccard_centennial_sl04m_15_11194_device::pccard_centennial_sl04m_15_11194_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) :
+ pccard_centennial_sram_device(mconfig, PCCARD_SRAM_CENTENNIAL_4M, tag, owner, clock)
+{
+ m_memory_space_config = address_space_config("memory", ENDIANNESS_LITTLE, 16, 22, 0, address_map_constructor(FUNC(pccard_centennial_sl04m_15_11194_device::memory_map), this));
+ m_attribute_space_config = address_space_config("attribute", ENDIANNESS_LITTLE, 16, 14, 0, address_map_constructor(FUNC(pccard_centennial_sl04m_15_11194_device::attribute_map), this));
+}
+
+void pccard_centennial_sl04m_15_11194_device::memory_map(address_map &map)
+{
+ map(0x000000, 0x3fffff).ram().share("sram");
+}
+
+void pccard_centennial_sl04m_15_11194_device::attribute_map(address_map &map)
+{
+ map(0x00000, 0x03fff).ram().share("eeprom");
+}
+
+ROM_START( eeprom_04 )
+ ROM_REGION(0x2000, "eeprom", 0)
+ ROM_LOAD("eeprom.bin", 0x0000, 0x2000, BAD_DUMP CRC(ce38fc21) SHA1(155edb39e554cb78547d3b9934a049ee46edc424))
+ROM_END
+
+const tiny_rom_entry *pccard_centennial_sl04m_15_11194_device::device_rom_region() const
+{
+ return ROM_NAME( eeprom_04 );
+}
diff --git a/src/devices/bus/pccard/sram.h b/src/devices/bus/pccard/sram.h
new file mode 100644
index 00000000000..ae65b711164
--- /dev/null
+++ b/src/devices/bus/pccard/sram.h
@@ -0,0 +1,165 @@
+// license: BSD-3-Clause
+// copyright-holders: Dirk Best
+/***************************************************************************
+
+ SRAM PC Cards
+
+***************************************************************************/
+
+#ifndef MAME_BUS_PCCARD_SRAM_H
+#define MAME_BUS_PCCARD_SRAM_H
+
+#pragma once
+
+#include "pccard.h"
+
+
+//**************************************************************************
+// TYPE DEFINITIONS
+//**************************************************************************
+
+// ======================> pccard_sram_device
+
+class pccard_sram_device :
+ public device_t,
+ public device_memory_interface,
+ public device_image_interface,
+ public device_pccard_interface
+{
+public:
+ void battery_voltage_1_w(int state);
+ void battery_voltage_2_w(int state);
+ void write_protect_w(int state);
+
+protected:
+ // construction/destruction
+ pccard_sram_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock);
+
+ // device_t overrides
+ virtual ioport_constructor device_input_ports() const override ATTR_COLD;
+ virtual void device_start() override ATTR_COLD;
+
+ // device_memory_interface overrides
+ virtual space_config_vector memory_space_config() const override;
+
+ // device_image_interface overrides
+ 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 true; }
+ virtual bool is_reset_on_load() const noexcept override { return false; }
+ virtual bool support_command_line_image_creation() const noexcept override { return true; }
+ virtual char const *file_extensions() const noexcept override { return "bin"; }
+ virtual const char *image_type_name() const noexcept override { return "sramcard"; }
+ virtual const char *image_brief_type_name() const noexcept override { return "sram"; }
+
+ // device_pccard_interface overrides
+ virtual uint16_t read_memory(offs_t offset, uint16_t mem_mask = ~0) override;
+ virtual uint16_t read_reg(offs_t offset, uint16_t mem_mask = ~0) override;
+ virtual void write_memory(offs_t offset, uint16_t data, uint16_t mem_mask = ~0) override;
+ virtual void write_reg(offs_t offset, uint16_t data, uint16_t mem_mask = ~0) override;
+
+ void set_cd(bool state);
+
+ address_space_config m_memory_space_config;
+ address_space_config m_attribute_space_config;
+
+ int8_t m_cd;
+ int8_t m_bvd1;
+ int8_t m_bvd2;
+ int8_t m_wp;
+};
+
+class pccard_mitsubishi_sram_device : public pccard_sram_device
+{
+protected:
+ pccard_mitsubishi_sram_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock);
+
+protected:
+ // device_image_interface overrides
+ 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;
+ virtual void call_unload() override;
+
+private:
+ required_shared_ptr<uint16_t> m_sram;
+};
+
+class pccard_mitsubishi_mf31m1_lycat01_device : public pccard_mitsubishi_sram_device
+{
+public:
+ // construction/destruction
+ pccard_mitsubishi_mf31m1_lycat01_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock = 0);
+
+private:
+ void memory_map(address_map &map) ATTR_COLD;
+};
+
+class pccard_centennial_sram_device : public pccard_sram_device
+{
+protected:
+ pccard_centennial_sram_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock);
+
+protected:
+ // device_image_interface overrides
+ 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;
+ virtual void call_unload() override;
+
+private:
+ required_shared_ptr<uint16_t> m_sram;
+ required_shared_ptr<uint16_t> m_eeprom;
+ required_memory_region m_eeprom_default;
+};
+
+class pccard_centennial_sl01m_15_11194_device : public pccard_centennial_sram_device
+{
+public:
+ // construction/destruction
+ pccard_centennial_sl01m_15_11194_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock = 0);
+
+protected:
+ // device_t overrides
+ virtual const tiny_rom_entry *device_rom_region() const override ATTR_COLD;
+
+private:
+ void memory_map(address_map &map) ATTR_COLD;
+ void attribute_map(address_map &map) ATTR_COLD;
+};
+
+class pccard_centennial_sl02m_15_11194_device : public pccard_centennial_sram_device
+{
+public:
+ // construction/destruction
+ pccard_centennial_sl02m_15_11194_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock = 0);
+
+protected:
+ // device_t overrides
+ virtual const tiny_rom_entry *device_rom_region() const override ATTR_COLD;
+
+private:
+ void memory_map(address_map &map) ATTR_COLD;
+ void attribute_map(address_map &map) ATTR_COLD;
+};
+
+class pccard_centennial_sl04m_15_11194_device : public pccard_centennial_sram_device
+{
+public:
+ // construction/destruction
+ pccard_centennial_sl04m_15_11194_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock = 0);
+
+protected:
+ // device_t overrides
+ virtual const tiny_rom_entry *device_rom_region() const override ATTR_COLD;
+
+private:
+ void memory_map(address_map &map) ATTR_COLD;
+ void attribute_map(address_map &map) ATTR_COLD;
+};
+
+// device type definition
+DECLARE_DEVICE_TYPE(PCCARD_SRAM_MITSUBISHI_1M, pccard_mitsubishi_mf31m1_lycat01_device)
+DECLARE_DEVICE_TYPE(PCCARD_SRAM_CENTENNIAL_1M, pccard_centennial_sl01m_15_11194_device)
+DECLARE_DEVICE_TYPE(PCCARD_SRAM_CENTENNIAL_2M, pccard_centennial_sl02m_15_11194_device)
+DECLARE_DEVICE_TYPE(PCCARD_SRAM_CENTENNIAL_4M, pccard_centennial_sl04m_15_11194_device)
+
+#endif // MAME_BUS_PCCARD_SRAM_H
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..e7e148c0516
--- /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 ATTR_COLD;
+ virtual void device_reset() override ATTR_COLD;
+
+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 ATTR_COLD;
+
+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 cb4070d14a1..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
***********************************************************************************************************/
@@ -13,20 +13,20 @@
#include "pce_rom.h"
+
//-------------------------------------------------
// 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)
{
}
@@ -35,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)
{
}
@@ -62,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()
@@ -111,111 +102,81 @@ void pce_tennokoe_device::nvram_default()
memcpy(m_bram + 0x1800, m_rom + 0x8800, 0x800);
}
-void pce_tennokoe_device::nvram_read(emu_file &file)
+bool pce_tennokoe_device::nvram_read(util::read_stream &file)
{
- file.read(m_bram, m_bram_size);
+ auto const [err, actual] = read(file, m_bram, m_bram_size);
+ return !err && (actual == m_bram_size);
}
-void pce_tennokoe_device::nvram_write(emu_file &file)
+bool pce_tennokoe_device::nvram_write(util::write_stream &file)
{
- file.write(m_bram, m_bram_size);
+ auto const [err, actual] = write(file, m_bram, m_bram_size);
+ return !err;
}
/*-------------------------------------------------
mapper specific handlers
-------------------------------------------------*/
-READ8_MEMBER(pce_rom_device::read_cart)
+uint8_t pce_rom_device::rom_r(offs_t offset)
{
int bank = offset / 0x20000;
return m_rom[rom_bank_map[bank] * 0x20000 + (offset & 0x1ffff)];
}
-
-READ8_MEMBER(pce_cdsys3_device::read_cart)
+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]);
}
-WRITE8_MEMBER(pce_cdsys3_device::write_cart)
+
+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);
}
-READ8_MEMBER(pce_populous_device::read_cart)
+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)];
}
-WRITE8_MEMBER(pce_populous_device::write_cart)
+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);
+}
-READ8_MEMBER(pce_sf2_device::read_cart)
+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)];
-}
-
-WRITE8_MEMBER(pce_sf2_device::write_cart)
-{
- if (offset >= 0x1ff0 && offset < 0x1ff4)
- m_bank_base = offset & 3;
-}
-
-READ8_MEMBER(pce_tennokoe_device::read_cart)
-{
- 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;
-}
-
-WRITE8_MEMBER(pce_tennokoe_device::write_cart)
-{
- 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);
- 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 7521e764d03..368fd604083 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 DECLARE_READ8_MEMBER(read_cart) 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 DECLARE_READ8_MEMBER(read_cart) override;
- virtual DECLARE_WRITE8_MEMBER(write_cart) 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 DECLARE_READ8_MEMBER(read_cart) override;
- virtual DECLARE_WRITE8_MEMBER(write_cart) 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 DECLARE_READ8_MEMBER(read_cart) override;
- virtual DECLARE_WRITE8_MEMBER(write_cart) override;
+ virtual void install_memory_handlers(address_space &space) override;
protected:
// device-level overrides
- virtual void device_start() override;
- virtual void device_reset() override;
+ virtual void device_reset() override ATTR_COLD;
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,18 +72,21 @@ public:
pce_tennokoe_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
// reading and writing
- virtual DECLARE_READ8_MEMBER(read_cart) override;
- virtual DECLARE_WRITE8_MEMBER(write_cart) override;
+ virtual void install_memory_handlers(address_space &space) override;
protected:
// device-level overrides
- virtual void device_start() override;
- virtual void device_reset() override;
+ virtual void device_start() override ATTR_COLD;
+ virtual void device_reset() override ATTR_COLD;
virtual void nvram_default() override;
- virtual void nvram_read(emu_file &file) override;
- virtual void nvram_write(emu_file &file) override;
+ virtual bool nvram_read(util::read_stream &file) override;
+ 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..9bc962d42fa
--- /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 ATTR_COLD;
+
+ // 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 ATTR_COLD;
+};
+
+// 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 ea49389206b..2a6d3dd3290 100644
--- a/src/devices/bus/pce/pce_slot.cpp
+++ b/src/devices/bus/pce/pce_slot.cpp
@@ -11,7 +11,6 @@
***********************************************************************************************************/
-
#include "emu.h"
#include "pce_slot.h"
@@ -29,10 +28,10 @@ DEFINE_DEVICE_TYPE(PCE_CART_SLOT, pce_cart_slot_device, "pce_cart_slot", "PCE/TG
// device_pce_cart_interface - constructor
//-------------------------------------------------
-device_pce_cart_interface::device_pce_cart_interface(const machine_config &mconfig, device_t &device)
- : device_slot_card_interface(mconfig, device),
- m_rom(nullptr),
- m_rom_size(0)
+device_pce_cart_interface::device_pce_cart_interface(const machine_config &mconfig, device_t &device) :
+ device_interface(device, "pcecart"),
+ m_rom(nullptr),
+ m_rom_size(0)
{
}
@@ -49,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;
}
}
@@ -137,10 +136,12 @@ void device_pce_cart_interface::rom_map_setup(uint32_t size)
//-------------------------------------------------
pce_cart_slot_device::pce_cart_slot_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) :
device_t(mconfig, PCE_CART_SLOT, tag, owner, clock),
- device_image_interface(mconfig, *this),
- device_slot_interface(mconfig, *this),
+ 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)
{
}
@@ -159,7 +160,7 @@ pce_cart_slot_device::~pce_cart_slot_device()
void pce_cart_slot_device::device_start()
{
- m_cart = dynamic_cast<device_pce_cart_interface *>(get_card_device());
+ m_cart = get_card_device();
}
@@ -182,13 +183,15 @@ 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)
{
for (auto & elem : slot_list)
{
- if (!core_stricmp(elem.slot_option, slot))
+ if (!strcmp(elem.slot_option, slot))
return elem.pcb_id;
}
@@ -211,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);
@@ -264,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());
}
@@ -322,15 +320,14 @@ std::string pce_cart_slot_device::get_default_card_software(get_default_card_sof
{
if (hook.image_file())
{
- const char *slot_string;
- uint32_t len = hook.image_file()->size();
+ uint64_t len;
+ hook.image_file()->length(len); // FIXME: check error return, guard against excessively large files
std::vector<uint8_t> rom(len);
- int type;
- hook.image_file()->read(&rom[0], len);
+ read(*hook.image_file(), &rom[0], len); // FIXME: check error return or read returning short
- type = get_cart_type(&rom[0], len);
- slot_string = pce_get_slot(type);
+ int const type = get_cart_type(&rom[0], len);
+ char const *const slot_string = pce_get_slot(type);
//printf("type: %s\n", slot_string);
@@ -339,25 +336,3 @@ std::string pce_cart_slot_device::get_default_card_software(get_default_card_sof
return software_get_default_slot("rom");
}
-
-/*-------------------------------------------------
- read
- -------------------------------------------------*/
-
-READ8_MEMBER(pce_cart_slot_device::read_cart)
-{
- if (m_cart)
- return m_cart->read_cart(space, offset);
- else
- return 0xff;
-}
-
-/*-------------------------------------------------
- write
- -------------------------------------------------*/
-
-WRITE8_MEMBER(pce_cart_slot_device::write_cart)
-{
- if (m_cart)
- m_cart->write_cart(space, offset, data);
-}
diff --git a/src/devices/bus/pce/pce_slot.h b/src/devices/bus/pce/pce_slot.h
index 53d690cc4ce..cb022445335 100644
--- a/src/devices/bus/pce/pce_slot.h
+++ b/src/devices/bus/pce/pce_slot.h
@@ -5,7 +5,7 @@
#pragma once
-#include "softlist_dev.h"
+#include "imagedev/cartrom.h"
/***************************************************************************
@@ -21,23 +21,23 @@ enum
PCE_CDSYS3U,
PCE_POPULOUS,
PCE_SF2,
- PCE_TENNOKOE
+ PCE_TENNOKOE,
+ PCE_ACARD_DUO,
+ PCE_ACARD_PRO
};
// ======================> device_pce_cart_interface
-class device_pce_cart_interface : public device_slot_card_interface
+class device_pce_cart_interface : public device_interface
{
public:
// construction/destruction
virtual ~device_pce_cart_interface();
- // reading and writing
- virtual DECLARE_READ8_MEMBER(read_cart) { return 0xff; }
- virtual DECLARE_WRITE8_MEMBER(write_cart) {};
+ 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]; }
@@ -61,8 +61,8 @@ protected:
// ======================> pce_cart_slot_device
class pce_cart_slot_device : public device_t,
- public device_image_interface,
- public device_slot_interface
+ public device_cartrom_image_interface,
+ public device_single_card_slot_interface<device_pce_cart_interface>
{
public:
// construction/destruction
@@ -80,39 +80,33 @@ public:
pce_cart_slot_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
virtual ~pce_cart_slot_device();
- // device-level overrides
- virtual void device_start() override;
+ // configuration
+ 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 const software_list_loader &get_software_list_loader() const override { return rom_software_list_loader::instance(); }
+
+ 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"; }
+
+ // 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; }
static int get_cart_type(const uint8_t *ROM, uint32_t len);
void set_intf(const char * interface) { m_interface = interface; }
- virtual iodevice_t image_type() const override { return IO_CARTSLOT; }
- virtual bool is_readable() const override { return 1; }
- virtual bool is_writeable() const override { return 0; }
- virtual bool is_creatable() const override { return 0; }
- virtual bool must_be_loaded() const override { return 1; }
- virtual bool is_reset_on_load() const override { return 1; }
- virtual const char *image_interface() const override { return m_interface; }
- virtual const char *file_extensions() const override { return "pce,bin"; }
-
- // slot interface overrides
- virtual std::string get_default_card_software(get_default_card_software_hook &hook) const override;
-
- // reading and writing
- virtual DECLARE_READ8_MEMBER(read_cart);
- virtual DECLARE_WRITE8_MEMBER(write_cart);
-
protected:
+ // device_t implementation
+ virtual void device_start() override ATTR_COLD;
+
const char *m_interface;
int m_type;
device_pce_cart_interface *m_cart;
+ required_address_space m_address_space;
};
@@ -120,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
new file mode 100644
index 00000000000..121647cfbf7
--- /dev/null
+++ b/src/devices/bus/pce_ctrl/joypad2.cpp
@@ -0,0 +1,318 @@
+// license:BSD-3-Clause
+// copyright-holders:cam900
+/**********************************************************************
+
+ NEC PC Engine/TurboGrafx-16 2 button joypad emulation
+
+ Based on SMS controller port emulation (devices\bus\sms_ctrl\*.*)
+ by Fabio Priuli,
+ PC engine emulation (mame\*\pce.*)
+ by Charles MacDonald, Wilbert Pol, Angelo Salese
+
+ First party models:
+
+ NEC PC Engine Pad (PI-PD001)
+ No autofire, Bundled in PC Engine
+
+ NEC Turbo Pad (PI-PD002 and Later models)
+ Add autofire support, Bundled in PC Engine CoreGrafx and later
+ models
+
+ NEC Turbo Stick (PI-PD4)
+ Arcade joystick variation of Turbo Pad, with separated autofire
+ buttons.
+ Turbo Stick for TurboGrafx-16 has slow motion.
+
+ Everything else PI-PD001 supports Autofire.
+
+ TODO:
+ - Needs verifications for Part numbers
+
+**********************************************************************/
+
+#include "emu.h"
+#include "joypad2.h"
+
+#include "machine/74157.h"
+
+
+namespace {
+
+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_BIT( 0x08, IP_ACTIVE_LOW, IPT_START ) PORT_NAME("%p Run")
+
+ PORT_START("DIRECTION")
+ PORT_BIT( 0x01, IP_ACTIVE_LOW, IPT_JOYSTICK_UP ) PORT_8WAY
+ PORT_BIT( 0x02, IP_ACTIVE_LOW, IPT_JOYSTICK_RIGHT ) PORT_8WAY
+ PORT_BIT( 0x04, IP_ACTIVE_LOW, IPT_JOYSTICK_DOWN ) PORT_8WAY
+ PORT_BIT( 0x08, IP_ACTIVE_LOW, IPT_JOYSTICK_LEFT ) PORT_8WAY
+INPUT_PORTS_END
+
+
+INPUT_PORTS_START( pce_joypad2_turbo )
+ PORT_INCLUDE( pce_joypad2 )
+
+ PORT_START("TURBO")
+ PORT_CONFNAME( 0x03, 0x00, "Button I Turbo" )
+ PORT_CONFSETTING( 0x00, DEF_STR( Off ) )
+ PORT_CONFSETTING( 0x02, "Slow" )
+ PORT_CONFSETTING( 0x03, "Fast" )
+ PORT_CONFNAME( 0x0c, 0x00, "Button II Turbo" )
+ PORT_CONFSETTING( 0x00, DEF_STR( Off ) )
+ PORT_CONFSETTING( 0x08, "Slow" )
+ PORT_CONFSETTING( 0x0c, "Fast" )
+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 ATTR_COLD;
+
+ // device-level overrides
+ virtual void device_add_mconfig(machine_config &config) override ATTR_COLD;
+ virtual void device_start() override ATTR_COLD;
+
+ // 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 ATTR_COLD;
+
+ // device-level overrides
+ 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;
+
+ // 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
+//-------------------------------------------------
+
+ioport_constructor pce_joypad2_device::device_input_ports() const
+{
+ return INPUT_PORTS_NAME( pce_joypad2 );
+}
+
+
+ioport_constructor pce_joypad2_turbo_device::device_input_ports() const
+{
+ return INPUT_PORTS_NAME( pce_joypad2_turbo );
+}
+
+
+
+//**************************************************************************
+// LIVE DEVICE
+//**************************************************************************
+
+//-------------------------------------------------
+// pce_joypad2_device - constructor
+//-------------------------------------------------
+
+pce_joypad2_device::pce_joypad2_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, u32 clock) :
+ device_t(mconfig, type, tag, owner, clock),
+ device_pce_control_port_interface(mconfig, *this),
+ m_muxer(*this, "mux")
+{
+}
+
+pce_joypad2_device::pce_joypad2_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock) :
+ pce_joypad2_device(mconfig, PCE_JOYPAD2, tag, owner, clock)
+{
+}
+
+
+//-------------------------------------------------
+// pce_joypad2_turbo_device - constructor
+//-------------------------------------------------
+
+pce_joypad2_turbo_device::pce_joypad2_turbo_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock) :
+ pce_joypad2_device(mconfig, PCE_JOYPAD2_TURBO, tag, owner, clock),
+ m_buttons_io(*this, "BUTTONS"),
+ m_turbo_io(*this, "TURBO"),
+ m_counter(0),
+ m_prev_clr(false)
+{
+}
+
+
+//-------------------------------------------------
+// device_add_mconfig - device-specific machine
+// configuration addiitons
+//-------------------------------------------------
+
+void pce_joypad2_device::device_add_mconfig(machine_config &config)
+{
+ LS157(config, m_muxer);
+ m_muxer->a_in_callback().set_ioport("BUTTONS");
+ m_muxer->b_in_callback().set_ioport("DIRECTION");
+}
+
+
+void pce_joypad2_turbo_device::device_add_mconfig(machine_config &config)
+{
+ pce_joypad2_device::device_add_mconfig(config);
+ m_muxer->a_in_callback().set(FUNC(pce_joypad2_turbo_device::buttons_r));
+}
+
+
+//-------------------------------------------------
+// device_start - device-specific startup
+//-------------------------------------------------
+
+void pce_joypad2_device::device_start()
+{
+}
+
+
+void pce_joypad2_turbo_device::device_start()
+{
+ pce_joypad2_device::device_start();
+ save_item(NAME(m_counter));
+ save_item(NAME(m_prev_clr));
+}
+
+
+//-------------------------------------------------
+// device_reset - device-specific reset
+//-------------------------------------------------
+
+void pce_joypad2_turbo_device::device_reset()
+{
+ m_counter = 0;
+ m_prev_clr = false;
+}
+
+
+//-------------------------------------------------
+// peripheral_r - joypad read
+//-------------------------------------------------
+
+u8 pce_joypad2_device::peripheral_r()
+{
+ return m_muxer->output_r();
+}
+
+
+//-------------------------------------------------
+// sel_w - MUXer select pin write
+//-------------------------------------------------
+
+void pce_joypad2_device::sel_w(int state)
+{
+ m_muxer->select_w(state);
+}
+
+
+//-------------------------------------------------
+// clr_w - MUXer strobe pin write
+//-------------------------------------------------
+
+void pce_joypad2_device::clr_w(int state)
+{
+ m_muxer->strobe_w(state);
+}
+
+
+void pce_joypad2_turbo_device::clr_w(int state)
+{
+ pce_joypad2_device::clr_w(state);
+ if ((!m_prev_clr) && state) // rising edge, connected to 74xx163 clock pin
+ m_counter = (m_counter + 1) & 7; // QA, QD pin not connected
+
+ m_prev_clr = state;
+}
+
+
+//-------------------------------------------------
+// buttons_r - read button with autofire counter
+//-------------------------------------------------
+
+u8 pce_joypad2_turbo_device::buttons_r()
+{
+ u8 ret = m_buttons_io->read() & 0xf;
+ const u8 turbo = m_turbo_io->read() & 0xf;
+ for (int i = 0; i < 2; i++)
+ {
+ const u8 enable_bit = 1 + (i << 1);
+ const u8 rate_bit = (i << 1);
+ if (BIT(turbo, enable_bit)) // enable autofire
+ {
+ if (BIT(turbo, rate_bit)) // Fast
+ {
+ if (BIT(m_counter, 1)) // QB pin from 74xx163
+ ret |= (1 << i);
+ }
+ else // Slow
+ {
+ if (BIT(m_counter, 2)) // QC pin from 74xx163
+ ret |= (1 << i);
+ }
+ }
+ }
+ 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
new file mode 100644
index 00000000000..008a9100825
--- /dev/null
+++ b/src/devices/bus/pce_ctrl/joypad2.h
@@ -0,0 +1,19 @@
+// license:BSD-3-Clause
+// copyright-holders:cam900
+/**********************************************************************
+
+ 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 "pcectrl.h"
+
+
+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
new file mode 100644
index 00000000000..49b804f3e38
--- /dev/null
+++ b/src/devices/bus/pce_ctrl/joypad6.cpp
@@ -0,0 +1,388 @@
+// license:BSD-3-Clause
+// copyright-holders:cam900
+/**********************************************************************
+
+ NEC PC Engine/TurboGrafx-16 6 button joypad emulation
+
+ Based on SMS controller port emulation (devices\bus\sms_ctrl\*.*)
+ by Fabio Priuli,
+ PC engine emulation (mame\*\pce.*)
+ by Charles MacDonald, Wilbert Pol, Angelo Salese
+
+ There's 2 officially licensed 6 button joypad models:
+
+ NEC Avenue Pad 6 (NAPD-1002)
+ - Supports autofire for Button I, II, Run (slow motion)
+
+ NEC Arcade Pad 6 (PCE-TP1)
+ - Supports autofire for Button I-VI, Bundled in PC Engine Duo-RX
+
+ TODO:
+ - Needs verifications for Part numbers
+ - Verify DTC114Y function for Slow motion in Avenue Pad 6
+
+**********************************************************************/
+
+#include "emu.h"
+#include "joypad6.h"
+
+#include "machine/74157.h"
+
+
+namespace {
+
+//**************************************************************************
+// 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 ATTR_COLD;
+ virtual void device_start() override ATTR_COLD;
+ virtual void device_reset() override ATTR_COLD;
+
+ // 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 ATTR_COLD;
+
+ // device-level overrides
+ virtual void device_add_mconfig(machine_config &config) override ATTR_COLD;
+
+ 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 ATTR_COLD;
+};
+
+
+
+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")
+ PORT_BIT( 0x02, IP_ACTIVE_LOW, IPT_BUTTON2 ) PORT_NAME("%p Button II")
+ PORT_BIT( 0x04, IP_ACTIVE_LOW, IPT_SELECT ) PORT_NAME("%p Select")
+ PORT_BIT( 0x08, IP_ACTIVE_LOW, IPT_START ) PORT_NAME("%p Run")
+
+ PORT_START("DIRECTION")
+ PORT_BIT( 0x01, IP_ACTIVE_LOW, IPT_JOYSTICK_UP ) PORT_8WAY
+ PORT_BIT( 0x02, IP_ACTIVE_LOW, IPT_JOYSTICK_RIGHT ) PORT_8WAY
+ PORT_BIT( 0x04, IP_ACTIVE_LOW, IPT_JOYSTICK_DOWN ) PORT_8WAY
+ PORT_BIT( 0x08, IP_ACTIVE_LOW, IPT_JOYSTICK_LEFT ) PORT_8WAY
+
+ PORT_START("BUTTONS_1")
+ PORT_BIT( 0x01, IP_ACTIVE_LOW, IPT_BUTTON3 ) PORT_NAME("%p Button III")
+ PORT_BIT( 0x02, IP_ACTIVE_LOW, IPT_BUTTON4 ) PORT_NAME("%p Button IV")
+ PORT_BIT( 0x04, IP_ACTIVE_LOW, IPT_BUTTON5 ) PORT_NAME("%p Button V")
+ PORT_BIT( 0x08, IP_ACTIVE_LOW, IPT_BUTTON6 ) PORT_NAME("%p Button VI")
+
+ PORT_START("JOY_MODE")
+ PORT_CONFNAME( 0x01, 0x00, "Joypad Mode" ) PORT_CHANGED_MEMBER(DEVICE_SELF, FUNC(pce_joypad6_base_device::joypad_mode_changed), 0)
+ PORT_CONFSETTING( 0x00, "2-buttons mode" ) // A at avenue pad 6
+ PORT_CONFSETTING( 0x01, "6-buttons mode" ) // B at avenue pad 6
+INPUT_PORTS_END
+
+
+static INPUT_PORTS_START( pce_avenue_pad_6 )
+ PORT_INCLUDE( pce_joypad6 )
+
+ PORT_START("TURBO")
+ PORT_CONFNAME( 0x01, 0x00, "Button I Turbo" )
+ PORT_CONFSETTING( 0x00, DEF_STR( Off ) )
+ PORT_CONFSETTING( 0x01, DEF_STR( On ) )
+ PORT_CONFNAME( 0x02, 0x00, "Button II Turbo" )
+ PORT_CONFSETTING( 0x00, DEF_STR( Off ) )
+ PORT_CONFSETTING( 0x02, DEF_STR( On ) )
+ PORT_CONFNAME( 0x08, 0x00, "Slow motion" ) // TODO: 74xx163 QB pin is connected with DTC114Y for Slow motion (Run button)
+ PORT_CONFSETTING( 0x00, DEF_STR( Off ) )
+ PORT_CONFSETTING( 0x08, DEF_STR( On ) )
+ PORT_BIT( 0xf4, IP_ACTIVE_HIGH, IPT_UNUSED )
+INPUT_PORTS_END
+
+
+static INPUT_PORTS_START( pce_arcade_pad_6 )
+ PORT_INCLUDE( pce_joypad6 )
+
+ PORT_START("TURBO")
+ PORT_CONFNAME( 0x01, 0x00, "Button I Turbo" )
+ PORT_CONFSETTING( 0x00, DEF_STR( Off ) )
+ PORT_CONFSETTING( 0x01, DEF_STR( On ) )
+ PORT_CONFNAME( 0x02, 0x00, "Button II Turbo" )
+ PORT_CONFSETTING( 0x00, DEF_STR( Off ) )
+ PORT_CONFSETTING( 0x02, DEF_STR( On ) )
+ PORT_BIT( 0x0c, IP_ACTIVE_HIGH, IPT_UNUSED )
+ PORT_CONFNAME( 0x10, 0x00, "Button III Turbo" )
+ PORT_CONFSETTING( 0x00, DEF_STR( Off ) )
+ PORT_CONFSETTING( 0x10, DEF_STR( On ) )
+ PORT_CONFNAME( 0x20, 0x00, "Button IV Turbo" )
+ PORT_CONFSETTING( 0x00, DEF_STR( Off ) )
+ PORT_CONFSETTING( 0x20, DEF_STR( On ) )
+ PORT_CONFNAME( 0x40, 0x00, "Button V Turbo" )
+ PORT_CONFSETTING( 0x00, DEF_STR( Off ) )
+ PORT_CONFSETTING( 0x40, DEF_STR( On ) )
+ PORT_CONFNAME( 0x80, 0x00, "Button VI Turbo" )
+ PORT_CONFSETTING( 0x00, DEF_STR( Off ) )
+ PORT_CONFSETTING( 0x80, DEF_STR( On ) )
+INPUT_PORTS_END
+
+
+//-------------------------------------------------
+// input_ports - device-specific input ports
+//-------------------------------------------------
+
+ioport_constructor pce_avenue_pad_6_device::device_input_ports() const
+{
+ return INPUT_PORTS_NAME( pce_avenue_pad_6 );
+}
+
+
+ioport_constructor pce_arcade_pad_6_device::device_input_ports() const
+{
+ return INPUT_PORTS_NAME( pce_arcade_pad_6 );
+}
+
+
+
+//**************************************************************************
+// LIVE DEVICE
+//**************************************************************************
+
+//-------------------------------------------------
+// pce_joypad6_base_device - constructor
+//-------------------------------------------------
+
+pce_joypad6_base_device::pce_joypad6_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_pce_control_port_interface(mconfig, *this),
+ m_muxer(*this, "mux_%u", 0U),
+ m_joypad_mode(*this, "JOY_MODE"),
+ m_counter(0),
+ m_prev_clr(false)
+{
+}
+
+
+//-------------------------------------------------
+// pce_avenue_pad_6_device - constructor
+//-------------------------------------------------
+
+pce_avenue_pad_6_device::pce_avenue_pad_6_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, u32 clock) :
+ pce_joypad6_base_device(mconfig, type, tag, owner, clock),
+ m_buttons_io(*this, "BUTTONS_%u", 0U),
+ m_turbo_io(*this, "TURBO")
+{
+}
+
+
+pce_avenue_pad_6_device::pce_avenue_pad_6_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock) :
+ pce_avenue_pad_6_device(mconfig, PCE_AVENUE_PAD_6, tag, owner, clock)
+{
+}
+
+
+//-------------------------------------------------
+// pce_arcade_pad_6_device - constructor
+//-------------------------------------------------
+
+pce_arcade_pad_6_device::pce_arcade_pad_6_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock) :
+ pce_avenue_pad_6_device(mconfig, PCE_ARCADE_PAD_6, tag, owner, clock)
+{
+}
+
+
+//-------------------------------------------------
+// device_add_mconfig - device-specific machine
+// configuration addiitons
+//-------------------------------------------------
+
+void pce_joypad6_base_device::device_add_mconfig(machine_config &config)
+{
+ LS157(config, m_muxer[0]);
+ m_muxer[0]->a_in_callback().set_ioport("BUTTONS_0");
+ m_muxer[0]->b_in_callback().set_ioport("DIRECTION");
+
+ LS157(config, m_muxer[1]);
+ m_muxer[1]->a_in_callback().set_ioport("BUTTONS_1");
+ m_muxer[1]->b_in_callback().set_constant(0x0); // 6-button pad header
+
+ LS157(config, m_muxer[2]);
+ m_muxer[2]->a_in_callback().set(m_muxer[0], FUNC(ls157_device::output_r));
+ m_muxer[2]->b_in_callback().set(m_muxer[1], FUNC(ls157_device::output_r));
+}
+
+
+void pce_avenue_pad_6_device::device_add_mconfig(machine_config &config)
+{
+ pce_joypad6_base_device::device_add_mconfig(config);
+ m_muxer[0]->a_in_callback().set(FUNC(pce_avenue_pad_6_device::buttons_r<0>));
+ m_muxer[1]->a_in_callback().set(FUNC(pce_avenue_pad_6_device::buttons_r<1>));
+}
+
+
+//-------------------------------------------------
+// device_start - device-specific startup
+//-------------------------------------------------
+
+void pce_joypad6_base_device::device_start()
+{
+ save_item(NAME(m_counter));
+ save_item(NAME(m_prev_clr));
+}
+
+
+//-------------------------------------------------
+// device_reset - device-specific reset
+//-------------------------------------------------
+
+void pce_joypad6_base_device::device_reset()
+{
+ m_counter = 0;
+ m_prev_clr = false;
+}
+
+
+//-------------------------------------------------
+// peripheral_r - joypad read
+//-------------------------------------------------
+
+u8 pce_joypad6_base_device::peripheral_r()
+{
+ return m_muxer[2]->output_r();
+}
+
+
+//-------------------------------------------------
+// sel_w - MUXer select pin write
+//-------------------------------------------------
+
+void pce_joypad6_base_device::sel_w(int state)
+{
+ m_muxer[0]->select_w(state);
+ m_muxer[1]->select_w(state);
+}
+
+
+//-------------------------------------------------
+// clr_w - MUXer strobe pin write, toggle button
+// set and autofire control
+//-------------------------------------------------
+
+void pce_joypad6_base_device::clr_w(int state)
+{
+ m_muxer[0]->strobe_w(state);
+ m_muxer[1]->strobe_w(state);
+ if ((!m_prev_clr) && state) // rising edge, connected to 74xx163 clock pin
+ m_counter = (m_counter + 1) & 0x3; // Toggle buttons/autofire, connected to 74xx163; QC, QD pin not used
+
+ m_prev_clr = state;
+ buttonset_update();
+}
+
+
+//-------------------------------------------------
+// buttonset_update - toggle buttonsets
+//-------------------------------------------------
+
+void pce_joypad6_base_device::buttonset_update()
+{
+ m_muxer[2]->select_w((m_joypad_mode->read() & 1) ? BIT(m_counter, 0) : 0);
+}
+
+
+//-------------------------------------------------
+// joypad_mode_changed
+//-------------------------------------------------
+
+INPUT_CHANGED_MEMBER(pce_joypad6_base_device::joypad_mode_changed)
+{
+ buttonset_update();
+}
+
+
+//-------------------------------------------------
+// buttons_r - read button with autofire counter
+//-------------------------------------------------
+
+template<unsigned Buttonset>
+u8 pce_avenue_pad_6_device::buttons_r()
+{
+ u8 ret = m_buttons_io[Buttonset]->read() & 0xf;
+ const u8 turbo = BIT(m_turbo_io->read(), Buttonset << 2, 4);
+ for (int i = 0; i < 4; i++)
+ {
+ if (BIT(turbo, i)) // enable autofire
+ {
+ if (BIT(m_counter, 1)) // QB pin from 74xx163
+ ret |= (1 << i);
+ }
+ }
+ 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
new file mode 100644
index 00000000000..88d83b4e3c2
--- /dev/null
+++ b/src/devices/bus/pce_ctrl/joypad6.h
@@ -0,0 +1,19 @@
+// license:BSD-3-Clause
+// copyright-holders:cam900
+/**********************************************************************
+
+ 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 "pcectrl.h"
+
+
+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..5f0fd47625f
--- /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 ATTR_COLD;
+
+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/multitap.cpp b/src/devices/bus/pce_ctrl/multitap.cpp
new file mode 100644
index 00000000000..22d08658b77
--- /dev/null
+++ b/src/devices/bus/pce_ctrl/multitap.cpp
@@ -0,0 +1,123 @@
+// license:BSD-3-Clause
+// copyright-holders:cam900
+/**********************************************************************
+
+ NEC PC Engine/TurboGrafx-16 Multi Tap emulation
+
+ Based on SMS controller port emulation (devices\bus\sms_ctrl\*.*)
+ by Fabio Priuli,
+ PC engine emulation (mame\*\pce.*)
+ by Charles MacDonald, Wilbert Pol, Angelo Salese
+
+ First party model (PI-PD003, and US released TurboTap and DuoTap)
+ has allowed up to 5 controllers, Third-party Multi Taps are has
+ allowed up to 2-4 controllers, and also compatible?
+
+**********************************************************************/
+
+#include "emu.h"
+#include "multitap.h"
+
+
+//**************************************************************************
+// DEVICE DEFINITIONS
+//**************************************************************************
+
+DEFINE_DEVICE_TYPE(PCE_MULTITAP, pce_multitap_device, "pce_multitap", "NEC PC Engine/TurboGrafx-16 Multi Tap")
+
+
+//**************************************************************************
+// LIVE DEVICE
+//**************************************************************************
+
+//-------------------------------------------------
+// pce_multitap_device - constructor
+//-------------------------------------------------
+
+pce_multitap_device::pce_multitap_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock) :
+ device_t(mconfig, PCE_MULTITAP, tag, owner, clock),
+ device_pce_control_port_interface(mconfig, *this),
+ m_subctrl_port(*this, "ctrl%u", 1U),
+ m_port_sel(0),
+ m_prev_sel(0)
+{
+}
+
+
+//-------------------------------------------------
+// device_add_mconfig - add device configuration
+//-------------------------------------------------
+
+void pce_multitap_device::device_add_mconfig(machine_config &config)
+{
+ for (auto & elem : m_subctrl_port)
+ PCE_CONTROL_PORT(config, elem, pce_control_port_devices, "joypad2");
+}
+
+
+//-------------------------------------------------
+// device_start - device-specific startup
+//-------------------------------------------------
+
+void pce_multitap_device::device_start()
+{
+ save_item(NAME(m_port_sel));
+ save_item(NAME(m_prev_sel));
+}
+
+
+//-------------------------------------------------
+// device_reset - device-specific reset
+//-------------------------------------------------
+
+void pce_multitap_device::device_reset()
+{
+ m_port_sel = 0;
+ m_prev_sel = false;
+}
+
+
+//-------------------------------------------------
+// peripheral_r - multitap read
+//-------------------------------------------------
+
+u8 pce_multitap_device::peripheral_r()
+{
+ u8 data = 0xf;
+ if (m_port_sel < 5) // up to 5 controller ports
+ data = m_subctrl_port[m_port_sel]->port_r();
+
+ return data;
+}
+
+
+//-------------------------------------------------
+// sel_w - SEL pin write, with port select
+//-------------------------------------------------
+
+void pce_multitap_device::sel_w(int state)
+{
+ for (auto & elem : m_subctrl_port)
+ elem->sel_w(state);
+
+ // bump counter on a low-to-high transition of SEL bit
+ if ((!m_prev_sel) && state)
+ m_port_sel = (m_port_sel + 1) & 7;
+
+ m_prev_sel = state;
+}
+
+
+//-------------------------------------------------
+// clr_w - CLR pin write, with reset multitap
+//-------------------------------------------------
+
+void pce_multitap_device::clr_w(int state)
+{
+ for (auto & elem : m_subctrl_port)
+ elem->clr_w(state);
+
+ // clear counter if Reset bit is set
+ if (state)
+ m_port_sel = 0;
+}
diff --git a/src/devices/bus/pce_ctrl/multitap.h b/src/devices/bus/pce_ctrl/multitap.h
new file mode 100644
index 00000000000..c814d563772
--- /dev/null
+++ b/src/devices/bus/pce_ctrl/multitap.h
@@ -0,0 +1,57 @@
+// license:BSD-3-Clause
+// copyright-holders:cam900
+/**********************************************************************
+
+ NEC PC Engine/TurboGrafx-16 Multi Tap emulation
+
+**********************************************************************/
+
+#ifndef MAME_BUS_PCE_CTRL_MULTITAP_H
+#define MAME_BUS_PCE_CTRL_MULTITAP_H
+
+#pragma once
+
+
+#include "pcectrl.h"
+
+
+
+//**************************************************************************
+// TYPE DEFINITIONS
+//**************************************************************************
+
+// ======================> pce_multitap_device
+
+class pce_multitap_device : public device_t,
+ public device_pce_control_port_interface
+{
+public:
+ // construction/destruction
+ pce_multitap_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock);
+
+protected:
+ // device-level overrides
+ 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;
+
+ // 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;
+
+private:
+ // controller ports
+ required_device_array<pce_control_port_device, 5> m_subctrl_port;
+
+ // internal states
+ u8 m_port_sel; // select port to read
+ bool m_prev_sel; // previous SEL pin state
+};
+
+
+// device type definition
+DECLARE_DEVICE_TYPE(PCE_MULTITAP, pce_multitap_device)
+
+
+#endif // MAME_BUS_PCE_CTRL_MULTITAP_H
diff --git a/src/devices/bus/pce_ctrl/pachinko.cpp b/src/devices/bus/pce_ctrl/pachinko.cpp
new file mode 100644
index 00000000000..4913dac3e5b
--- /dev/null
+++ b/src/devices/bus/pce_ctrl/pachinko.cpp
@@ -0,0 +1,151 @@
+// license:BSD-3-Clause
+// copyright-holders:kmg
+/**********************************************************************
+
+ NEC PC Engine Coconuts Japan CJPC-101 Pachinko Controller
+
+ This controller was originally released as a set with PC Engine CD
+ game Pachio-kun Maboroshi no Densetsu. A near identical model was
+ then put out for the Famicom.
+
+ Functionally, this works like the non-turbo 2-button joypad with an
+ additional spring loaded analog rotating trigger. The trigger is read
+ after the standard buttons, much like a 2nd controller on a multitap.
+ Hence, this controller cannot be used in conjunction with a multitap.
+
+ TODO: according to games' packaging this controller works with all four
+ Pachio-kun games. However, only Maboroshi no Densetsu and Juuban Shoubu
+ prompt for controller type at boot. How to enable on the other two games?
+
+**********************************************************************/
+
+#include "emu.h"
+#include "pachinko.h"
+
+
+
+//**************************************************************************
+// DEVICE DEFINITIONS
+//**************************************************************************
+
+DEFINE_DEVICE_TYPE(PCE_PACHINKO, pce_pachinko_device, "pce_pachinko", "Coconuts Japan Pachinko Controller CJPC-101")
+
+
+static INPUT_PORTS_START( pce_pachinko )
+ // 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( 0x08, IP_ACTIVE_LOW, IPT_START ) PORT_NAME("%p Run")
+
+ PORT_START("DPAD")
+ PORT_BIT( 0x01, IP_ACTIVE_LOW, IPT_JOYSTICK_UP ) PORT_8WAY
+ PORT_BIT( 0x02, IP_ACTIVE_LOW, IPT_JOYSTICK_RIGHT ) PORT_8WAY
+ PORT_BIT( 0x04, IP_ACTIVE_LOW, IPT_JOYSTICK_DOWN ) PORT_8WAY
+ PORT_BIT( 0x08, IP_ACTIVE_LOW, IPT_JOYSTICK_LEFT ) PORT_8WAY
+
+ PORT_START("TRIGGER")
+ PORT_BIT( 0xff, 0x80, IPT_PEDAL ) PORT_MINMAX(0x80, 0xff) PORT_SENSITIVITY(10) PORT_KEYDELTA(20) PORT_INVERT PORT_REVERSE
+INPUT_PORTS_END
+
+
+//-------------------------------------------------
+// input_ports - device-specific input ports
+//-------------------------------------------------
+
+ioport_constructor pce_pachinko_device::device_input_ports() const
+{
+ return INPUT_PORTS_NAME( pce_pachinko );
+}
+
+
+
+//**************************************************************************
+// LIVE DEVICE
+//**************************************************************************
+
+//-------------------------------------------------
+// pce_pachinko_device - constructor
+//-------------------------------------------------
+
+pce_pachinko_device::pce_pachinko_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock) :
+ device_t(mconfig, PCE_PACHINKO, tag, owner, clock),
+ device_pce_control_port_interface(mconfig, *this),
+ m_buttons(*this, "BUTTONS"),
+ m_dpad(*this, "DPAD"),
+ m_trigger(*this, "TRIGGER"),
+ m_counter(0),
+ m_prev_sel(false),
+ m_prev_clr(false)
+{
+}
+
+
+//-------------------------------------------------
+// device_start - device-specific startup
+//-------------------------------------------------
+
+void pce_pachinko_device::device_start()
+{
+ save_item(NAME(m_counter));
+ save_item(NAME(m_prev_sel));
+ save_item(NAME(m_prev_clr));
+}
+
+
+//-------------------------------------------------
+// peripheral_r - joypad read
+//-------------------------------------------------
+
+u8 pce_pachinko_device::peripheral_r()
+{
+ u8 data = 0xf;
+
+ if (!m_prev_clr)
+ {
+ switch (m_counter)
+ {
+ case 0:
+ data = m_dpad->read();
+ break;
+ case 1:
+ data = m_buttons->read();
+ break;
+ case 2:
+ data = m_trigger->read() >> 4;
+ break;
+ case 3:
+ data = m_trigger->read();
+ break;
+ }
+ }
+
+ return data;
+}
+
+
+//-------------------------------------------------
+// sel_w - MUXer select pin write
+//-------------------------------------------------
+
+void pce_pachinko_device::sel_w(int state)
+{
+ if (!m_prev_clr && m_prev_sel != state)
+ m_counter = (m_counter + 1) & 7;
+
+ m_prev_sel = state;
+}
+
+
+//-------------------------------------------------
+// clr_w - MUXer strobe pin write
+//-------------------------------------------------
+
+void pce_pachinko_device::clr_w(int state)
+{
+ if (m_prev_sel && !m_prev_clr && state)
+ m_counter = 0;
+
+ m_prev_clr = state;
+}
diff --git a/src/devices/bus/pce_ctrl/pachinko.h b/src/devices/bus/pce_ctrl/pachinko.h
new file mode 100644
index 00000000000..3e1808c3195
--- /dev/null
+++ b/src/devices/bus/pce_ctrl/pachinko.h
@@ -0,0 +1,61 @@
+// license:BSD-3-Clause
+// copyright-holders:kmg
+/**********************************************************************
+
+ NEC PC Engine Coconuts Japan CJPC-101 Pachinko Controller
+
+**********************************************************************/
+
+#ifndef MAME_BUS_PCE_CTRL_PACHINKO_H
+#define MAME_BUS_PCE_CTRL_PACHINKO_H
+
+#pragma once
+
+
+#include "pcectrl.h"
+
+
+
+//**************************************************************************
+// TYPE DEFINITIONS
+//**************************************************************************
+
+// ======================> pce_pachinko_device
+
+class pce_pachinko_device : public device_t,
+ public device_pce_control_port_interface
+{
+public:
+ // construction/destruction
+ pce_pachinko_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 ATTR_COLD;
+
+ // device-level overrides
+ virtual void device_start() override ATTR_COLD;
+
+ // 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;
+
+private:
+ // IO ports
+ required_ioport m_buttons;
+ required_ioport m_dpad;
+ required_ioport m_trigger;
+
+ // internal states
+ u8 m_counter;
+ bool m_prev_sel; // previous SEL pin state
+ bool m_prev_clr; // previous CLR pin state
+};
+
+
+// device type definition
+DECLARE_DEVICE_TYPE(PCE_PACHINKO, pce_pachinko_device)
+
+
+#endif // MAME_BUS_PCE_CTRL_PACHINKO_H
diff --git a/src/devices/bus/pce_ctrl/pcectrl.cpp b/src/devices/bus/pce_ctrl/pcectrl.cpp
new file mode 100644
index 00000000000..6d0f9ffa7de
--- /dev/null
+++ b/src/devices/bus/pce_ctrl/pcectrl.cpp
@@ -0,0 +1,200 @@
+// license:BSD-3-Clause
+// copyright-holders:cam900
+/**********************************************************************
+
+ NEC PC Engine/TurboGrafx-16 controller port emulation
+
+ Based on SMS controller port emulation (devices\bus\sms_ctrl\*.*)
+ by Fabio Priuli,
+ PC engine emulation (mame\*\pce.*)
+ by Charles MacDonald, Wilbert Pol, Angelo Salese
+
+ Controller port interface layout:
+
+ DIN-8 interface for TurboGrafx-16:
+
+ /-------------\
+ //-------------\\
+ // 2 \\
+ || 5 4 ||
+ || ||
+ || 3 8 1 ||
+ || ||
+ || 7 6 ||
+ \\ --- //
+ \\----/ \----//
+ \-------------/
+
+ Mini DIN-8 interface for others:
+
+ /-------------\
+ //----| |----\\
+ // |---| \\
+ || 6 7 8 ||
+ || ||
+ || 3 4 5 ||
+ || ||
+ ||--| 1 2 |--||
+ \ | | /
+ \ |-----------| /
+ \-------------/
+
+ 1: +5V
+ 2: O0 (Read bit 0)
+ 3: O1 (Read bit 1)
+ 4: O2 (Read bit 2)
+ 5: O3 (Read bit 3)
+ 6: SEL (Write bit 0)
+ 7: CLR (Write bit 1)
+ 8: GND
+
+**********************************************************************/
+
+#include "emu.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"
+
+
+
+//**************************************************************************
+// GLOBAL VARIABLES
+//**************************************************************************
+
+DEFINE_DEVICE_TYPE(PCE_CONTROL_PORT, pce_control_port_device, "pce_control_port", "NEC PC Engine/TurboGrafx-16 controller port")
+
+
+
+//**************************************************************************
+// CARD INTERFACE
+//**************************************************************************
+
+//-------------------------------------------------
+// device_pce_control_port_interface - constructor
+//-------------------------------------------------
+
+device_pce_control_port_interface::device_pce_control_port_interface(const machine_config &mconfig, device_t &device)
+ : device_interface(device, "pcectrl")
+{
+ m_port = dynamic_cast<pce_control_port_device *>(device.owner());
+}
+
+
+//-------------------------------------------------
+// ~device_pce_control_port_interface - destructor
+//-------------------------------------------------
+
+device_pce_control_port_interface::~device_pce_control_port_interface()
+{
+}
+
+
+
+//**************************************************************************
+// LIVE DEVICE
+//**************************************************************************
+
+//-------------------------------------------------
+// pce_control_port_device - constructor
+//-------------------------------------------------
+
+pce_control_port_device::pce_control_port_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock) :
+ device_t(mconfig, PCE_CONTROL_PORT, tag, owner, clock),
+ device_slot_interface(mconfig, *this),
+ m_device(nullptr)
+{
+}
+
+
+//-------------------------------------------------
+// pce_control_port_device - destructor
+//-------------------------------------------------
+
+pce_control_port_device::~pce_control_port_device()
+{
+}
+
+
+//-------------------------------------------------
+// device_start - device-specific startup
+//-------------------------------------------------
+
+void pce_control_port_device::device_start()
+{
+ m_device = dynamic_cast<device_pce_control_port_interface *>(get_card_device());
+}
+
+
+//-------------------------------------------------
+// port_r - controller port read
+//-------------------------------------------------
+
+u8 pce_control_port_device::port_r()
+{
+ u8 data = 0xf;
+ if (m_device)
+ data = m_device->peripheral_r() & 0xf; // 4 bit
+ return data;
+}
+
+
+//-------------------------------------------------
+// sel_w - SEL pin write
+//-------------------------------------------------
+
+void pce_control_port_device::sel_w(int state)
+{
+ if (m_device)
+ m_device->sel_w(state);
+}
+
+
+//-------------------------------------------------
+// clr_w - CLR pin write
+//-------------------------------------------------
+
+void pce_control_port_device::clr_w(int state)
+{
+ if (m_device)
+ m_device->clr_w(state);
+}
+
+
+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 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/pcectrl.h b/src/devices/bus/pce_ctrl/pcectrl.h
new file mode 100644
index 00000000000..ac3aa841fbb
--- /dev/null
+++ b/src/devices/bus/pce_ctrl/pcectrl.h
@@ -0,0 +1,81 @@
+// license:BSD-3-Clause
+// copyright-holders:cam900
+/**********************************************************************
+
+ NEC PC Engine/TurboGrafx-16 controller port emulation
+
+**********************************************************************/
+
+#ifndef MAME_BUS_PCE_CTRL_PCECTRL_H
+#define MAME_BUS_PCE_CTRL_PCECTRL_H
+
+#pragma once
+
+
+//**************************************************************************
+// TYPE DEFINITIONS
+//**************************************************************************
+
+// ======================> pce_control_port_device
+
+class device_pce_control_port_interface;
+
+class pce_control_port_device : public device_t,
+ public device_slot_interface
+{
+public:
+ // construction/destruction
+ template <typename T>
+ pce_control_port_device(machine_config const &mconfig, char const *tag, device_t *owner, T &&opts, char const *dflt)
+ : pce_control_port_device(mconfig, tag, owner, 0)
+ {
+ option_reset();
+ opts(*this);
+ set_default_option(dflt);
+ set_fixed(false);
+ }
+
+ pce_control_port_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock);
+ virtual ~pce_control_port_device();
+
+ u8 port_r();
+
+ void sel_w(int state);
+ void clr_w(int state);
+
+protected:
+ // device-level overrides
+ virtual void device_start() override ATTR_COLD;
+
+ device_pce_control_port_interface *m_device;
+};
+
+
+// ======================> device_pce_control_port_interface
+
+// class representing interface-specific live pce_control_port card
+class device_pce_control_port_interface : public device_interface
+{
+public:
+ // construction/destruction
+ virtual ~device_pce_control_port_interface();
+
+ virtual u8 peripheral_r() { return 0xf; }
+ virtual void sel_w(int state) {}
+ virtual void clr_w(int state) {}
+
+protected:
+ device_pce_control_port_interface(const machine_config &mconfig, device_t &device);
+
+ pce_control_port_device *m_port;
+};
+
+
+// device type definition
+DECLARE_DEVICE_TYPE(PCE_CONTROL_PORT, pce_control_port_device)
+
+
+void pce_control_port_devices(device_slot_interface &device);
+
+
+#endif // MAME_BUS_PCE_CTRL_PCECTRL_H
diff --git a/src/devices/bus/pce_ctrl/xhe3.cpp b/src/devices/bus/pce_ctrl/xhe3.cpp
new file mode 100644
index 00000000000..2484ffb259f
--- /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 ATTR_COLD;
+ virtual ioport_constructor device_input_ports() const override { return INPUT_PORTS_NAME(pce_xhe3); }
+ virtual void device_start() override ATTR_COLD;
+
+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..2eb465d21b4
--- /dev/null
+++ b/src/devices/bus/pci/aha2940au.cpp
@@ -0,0 +1,149 @@
+// license:BSD-3-Clause
+// copyright-holders:
+/**************************************************************************************************
+
+Adaptec AHA-2940AU PCI
+
+Based off AIC-7860/7861
+
+References:
+- https://github.com/torvalds/linux/tree/master/drivers/scsi/aic7xxx
+
+TODO:
+- Stub, enough to make it surpass initial POST and nothing else;
+- Lack specific documentation for AIC-7860, we base on AIC-7890 for now;
+
+**************************************************************************************************/
+
+#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_eeprom(*this, "eeprom")
+ , m_scsi_rom(*this, "scsi_rom")
+{
+ // TODO: unknown revision
+ // class code should be 0x01'0000 as per AIC-7890 manual
+ set_ids(0x90046178, 0x00, 0x010000, 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_REGION16_LE( 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
+
+ EEPROM_93C46_16BIT(config, m_eeprom);
+}
+
+void aha2940au_scsi_device::device_start()
+{
+ pci_card_device::device_start();
+
+ // TODO: BAR setup from AIC-7890, verify
+ add_map( 256, M_IO, FUNC(aha2940au_scsi_device::io_map));
+ // TODO: enables M_64A on demand
+ add_map( 4096, M_MEM, FUNC(aha2940au_scsi_device::mem_map));
+
+ add_rom((u8 *)m_scsi_rom->base(), 0x8000);
+ expansion_rom_base = 0xc8000;
+
+ // TODO: BIST capable
+
+ // INTA#
+ intr_pin = 1;
+ // TODO: definitely uses PCI regs 0x3e/0x3f
+ // max_lat = 0x19, min_gnt = 0x27 for AIC-7890
+ // others may be different
+}
+
+void aha2940au_scsi_device::device_reset()
+{
+ pci_card_device::device_reset();
+
+ command = 0x0000;
+ // Can be bus master (bit 2), can use Memory Write and Invalidate (bit 4)
+ command_mask = 0x17;
+ // cap list (bit 4), fast back-to-back (bit 7), medium DEVSEL#
+ status = 0x0290;
+
+ remap_cb();
+}
+
+u8 aha2940au_scsi_device::capptr_r()
+{
+ return 0xdc;
+}
+
+void aha2940au_scsi_device::config_map(address_map &map)
+{
+ pci_card_device::config_map(map);
+// map(0x40, 0x40) DEVCONFIG
+// map(0x41, 0x41) DEVSTATUS0
+// map(0x42, 0x42) DEVSTATUS1
+// map(0x43, 0x43) PCIERRGEN
+
+ // PME 1.0
+ map(0xdc, 0xdf).lr32(NAME([] { return 0x0001'0001; }));
+// map(0xe0, 0xe1) PM_CSR
+// map(0xe2, 0xe2) PMCSR_BSE
+// map(0xe3, 0xe3) PM_DATA
+// map(0xff, 0xff) IDENREG
+}
+
+void aha2940au_scsi_device::io_map(address_map &map)
+{
+ // SEECTL
+ map(0x1e, 0x1e).lrw8(
+ NAME([this] (offs_t offset) {
+ return 0x10 | m_eeprom->do_read();
+ }),
+ NAME([this] (offs_t offset, u8 data) {
+ LOG("SEECTL %02x\n", data);
+ m_eeprom->di_write(BIT(data, 1));
+ m_eeprom->clk_write(BIT(data, 2));
+ m_eeprom->cs_write(BIT(data, 3));
+ })
+ );
+ // HCNTRL
+ map(0x87, 0x87).lr8(NAME([] () { return 0xff; }));
+}
+
+void aha2940au_scsi_device::mem_map(address_map &map)
+{
+}
+
diff --git a/src/devices/bus/pci/aha2940au.h b/src/devices/bus/pci/aha2940au.h
new file mode 100644
index 00000000000..c7964e672b7
--- /dev/null
+++ b/src/devices/bus/pci/aha2940au.h
@@ -0,0 +1,47 @@
+// license:BSD-3-Clause
+// copyright-holders:
+
+#ifndef MAME_BUS_PCI_AHA2940AU_H
+#define MAME_BUS_PCI_AHA2940AU_H
+
+#pragma once
+
+#include "pci_slot.h"
+
+#include "machine/eepromser.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 ATTR_COLD;
+ virtual void device_reset() override ATTR_COLD;
+ virtual void device_add_mconfig(machine_config &config) override ATTR_COLD;
+
+ virtual const tiny_rom_entry *device_rom_region() const override ATTR_COLD;
+
+// 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 ATTR_COLD;
+
+ virtual u8 capptr_r() override;
+
+ required_device<eeprom_serial_93cxx_device> m_eeprom;
+
+private:
+ void io_map(address_map &map);
+ void mem_map(address_map &map);
+
+ required_memory_region m_scsi_rom;
+};
+
+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..74f87216073
--- /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 ATTR_COLD;
+ virtual void device_reset() override ATTR_COLD;
+ virtual void device_add_mconfig(machine_config &config) override ATTR_COLD;
+
+// virtual const tiny_rom_entry *device_rom_region() const override ATTR_COLD;
+
+// 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 ATTR_COLD;
+
+private:
+ void map(address_map &map) ATTR_COLD;
+};
+
+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..9bb9b54a676
--- /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) ATTR_COLD;
+ void legacy_io_map(address_map &map) ATTR_COLD;
+
+protected:
+ 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;
+
+ virtual const tiny_rom_entry *device_rom_region() const override ATTR_COLD;
+
+ 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 ATTR_COLD;
+
+ virtual void mmio_map(address_map &map) ATTR_COLD;
+ virtual void vram_aperture_map(address_map &map) ATTR_COLD;
+ virtual void gpio_map(address_map &map) ATTR_COLD;
+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..601378e1d73
--- /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) ATTR_COLD;
+ void legacy_io_map(address_map &map) ATTR_COLD;
+
+protected:
+ 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;
+
+ virtual const tiny_rom_entry *device_rom_region() const override ATTR_COLD;
+
+ 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 ATTR_COLD;
+
+ virtual void mmio_map(address_map &map) ATTR_COLD;
+ virtual void vram_aperture_map(address_map &map) ATTR_COLD;
+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..b184b3db664
--- /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 ATTR_COLD;
+ virtual void device_reset() override ATTR_COLD;
+};
+
+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..72b7bfb3fb5
--- /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 ATTR_COLD;
+ virtual void device_reset() override ATTR_COLD;
+ virtual void device_add_mconfig(machine_config &config) override ATTR_COLD;
+
+// virtual const tiny_rom_entry *device_rom_region() const override ATTR_COLD;
+
+// 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 ATTR_COLD;
+
+ virtual u8 capptr_r() override;
+
+private:
+ void extended_map(address_map &map) ATTR_COLD;
+ void sb_map(address_map &map) ATTR_COLD;
+ void vcbase_map(address_map &map) ATTR_COLD;
+ void mpu_map(address_map &map) ATTR_COLD;
+ void gameport_map(address_map &map) ATTR_COLD;
+};
+
+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..eebbb87145f
--- /dev/null
+++ b/src/devices/bus/pci/geforce.h
@@ -0,0 +1,58 @@
+// 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);
+
+ // ELSA protection
+ static constexpr feature_type unemulated_features() { return feature::PROTECTION; }
+
+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 ATTR_COLD;
+ virtual void device_start() override ATTR_COLD;
+};
+
+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 ATTR_COLD;
+};
+
+class quadro_device : public geforce256_device
+{
+public:
+ quadro_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
+
+ // ELSA protection
+ static constexpr feature_type unemulated_features() { return feature::PROTECTION; }
+
+protected:
+ virtual const tiny_rom_entry *device_rom_region() const override ATTR_COLD;
+};
+
+
+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..745d915c54e
--- /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) ATTR_COLD;
+ void legacy_io_map(address_map &map) ATTR_COLD;
+
+protected:
+ 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;
+ virtual space_config_vector memory_space_config() const override;
+
+ virtual const tiny_rom_entry *device_rom_region() const override ATTR_COLD;
+
+ 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 ATTR_COLD;
+
+ void mgabase1_map(address_map &map) ATTR_COLD;
+ void mgabase2_map(address_map &map) ATTR_COLD;
+
+ void dwgreg_map(address_map &map) ATTR_COLD;
+
+ 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/ncr53c825.cpp b/src/devices/bus/pci/ncr53c825.cpp
new file mode 100644
index 00000000000..b30263cd604
--- /dev/null
+++ b/src/devices/bus/pci/ncr53c825.cpp
@@ -0,0 +1,95 @@
+// license:BSD-3-Clause
+// copyright-holders:
+/**************************************************************************************************
+
+NCR / Symbios Logic / LSI Logic 53C825A
+
+**************************************************************************************************/
+
+#include "emu.h"
+#include "ncr53c825.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(NCR53C825_PCI, ncr53c825_pci_device, "ncr53c825_pci", "NCR/Symbios Logic/LSI Logic 53C825A PCI")
+
+ncr53c825_pci_device::ncr53c825_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_scsi_rom(*this, "scsi_rom")
+{
+ // '825AE straps subvendor with 0x1000'1000, revision 0x26
+ set_ids(0x10000003, 0x14, 0x010000, 0x00000000);
+}
+
+ncr53c825_pci_device::ncr53c825_pci_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
+ : ncr53c825_pci_device(mconfig, NCR53C825_PCI, tag, owner, clock)
+{
+}
+
+void ncr53c825_pci_device::device_add_mconfig(machine_config &config)
+{
+ // TODO: SCSI controller, derives from 53C710 according to ROM
+}
+
+ROM_START( ncr53c825 )
+ ROM_REGION32_LE( 0x10000, "scsi_rom", ROMREGION_ERASEFF )
+ // misc/odyssey.cpp SCSI board
+ ROM_SYSTEM_BIOS( 0, "odyssey", "NCR SDMS PCI-3.07.00 Lomas Optimum III" )
+ ROMX_LOAD( "tms28f512a.u4", 0x0000, 0x10000, CRC(0d5a8054) SHA1(ed22a726976fdc34db6176a1384609f93d50f27a), ROM_BIOS(0) )
+ROM_END
+
+const tiny_rom_entry *ncr53c825_pci_device::device_rom_region() const
+{
+ return ROM_NAME(ncr53c825);
+}
+
+
+void ncr53c825_pci_device::device_start()
+{
+ pci_card_device::device_start();
+
+ add_map( 128, M_IO, FUNC(ncr53c825_pci_device::io_map));
+ add_map( 128, M_MEM, FUNC(ncr53c825_pci_device::io_map));
+ add_map( 4*1024, M_MEM, FUNC(ncr53c825_pci_device::scripts_map));
+ add_rom((u8 *)m_scsi_rom->base(), 0x8000);
+ expansion_rom_base = 0xc8000;
+
+ // INTA#
+ intr_pin = 1;
+
+ // TODO: min_gnt = 0x11, max_lat = 0x40
+}
+
+void ncr53c825_pci_device::device_reset()
+{
+ pci_card_device::device_reset();
+
+ command = 0x0000;
+ command_mask = 0x157;
+ // status = 0x0010; for 'AE only
+ status = 0x0000;
+
+ remap_cb();
+}
+
+void ncr53c825_pci_device::config_map(address_map &map)
+{
+ pci_card_device::config_map(map);
+// map(0x40, 0x40) power management capability for 'AE
+// map(0x46, 0x46) bridge support extension for 'A
+}
+
+void ncr53c825_pci_device::io_map(address_map &map)
+{
+}
+
+void ncr53c825_pci_device::scripts_map(address_map &map)
+{
+}
diff --git a/src/devices/bus/pci/ncr53c825.h b/src/devices/bus/pci/ncr53c825.h
new file mode 100644
index 00000000000..fe363ca22c5
--- /dev/null
+++ b/src/devices/bus/pci/ncr53c825.h
@@ -0,0 +1,39 @@
+// license:BSD-3-Clause
+// copyright-holders:
+
+#ifndef MAME_BUS_PCI_NCR53C825_H
+#define MAME_BUS_PCI_NCR53C825_H
+
+#pragma once
+
+#include "pci_slot.h"
+
+class ncr53c825_pci_device : public pci_card_device
+{
+public:
+ ncr53c825_pci_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
+
+ static constexpr feature_type unemulated_features() { return feature::MEDIA; }
+
+protected:
+ ncr53c825_pci_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock);
+
+ 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;
+
+ virtual const tiny_rom_entry *device_rom_region() const override ATTR_COLD;
+
+ virtual void config_map(address_map &map) override ATTR_COLD;
+
+ void io_map(address_map &map) ATTR_COLD;
+ void scripts_map(address_map &map) ATTR_COLD;
+
+ required_memory_region m_scsi_rom;
+private:
+ // ...
+};
+
+DECLARE_DEVICE_TYPE(NCR53C825_PCI, ncr53c825_pci_device)
+
+#endif // MAME_BUS_PCI_NCR53C825_H
diff --git a/src/devices/bus/pci/neon250.cpp b/src/devices/bus/pci/neon250.cpp
new file mode 100644
index 00000000000..b0908182e9c
--- /dev/null
+++ b/src/devices/bus/pci/neon250.cpp
@@ -0,0 +1,188 @@
+// license:BSD-3-Clause
+// copyright-holders:
+/**************************************************************************************************
+
+VideoLogic PowerVR Neon 250
+
+TODO:
+- stub device;
+- detects 0Kb of RAM in SDD test, plays with pvr_io_map $54 (IIC Interface B);
+
+**************************************************************************************************/
+
+#include "emu.h"
+#include "neon250.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(NEON250, neon250_device, "neon250", "VideoLogic PowerVR Neon 250 (PMX1)")
+
+neon250_device::neon250_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")
+{
+ // PowerVR Neon 250 AGP (NEC branded)
+ set_ids_agp(0x10330067, 0x02, 0x10100120);
+}
+
+neon250_device::neon250_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
+ : neon250_device(mconfig, NEON250, tag, owner, clock)
+{
+}
+
+ROM_START( neon250 )
+ ROM_REGION32_LE( 0x20000, "vga_rom", ROMREGION_ERASEFF )
+ ROM_SYSTEM_BIOS( 0, "neon250", "NEC Neon 250" )
+ ROMX_LOAD( "n0020331.bin", 0x000000, 0x20000, CRC(e76008f5) SHA1(1ddda1494d5b32148e2c9e7a6557f00ee9cffea6), ROM_BIOS(0) )
+// ROMX_LOAD( "ppvr201i.bin", 0x000000, 0x10000, CRC(b6e763c9) SHA1(1e1fecbb663dde5295a9db98dde70a4e1bd8338d), ROM_BIOS(0) )
+// ROMX_LOAD( "b1002816.bin", 0x000000, 0x10000, CRC(d3cf607a) SHA1(8fea7c3e678bc585ed5729d7f1a4b203bae8d15d), ROM_BIOS(0) )
+ // from VGA Legacy MkIII, bad
+// ROMX_LOAD( "neon250agp.vbi", 0x000000, 0x009200, CRC(41a46c28) SHA1(f99482b906436d9b1db25e68de5a2bc96a192128) BAD_DUMP, ROM_BIOS(0) )
+ROM_END
+
+const tiny_rom_entry *neon250_device::device_rom_region() const
+{
+ return ROM_NAME(neon250);
+}
+
+void neon250_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(vga_device::screen_update));
+
+ // TODO: PVR "VGA Emulator"
+ VGA(config, m_svga, 0);
+ m_svga->set_screen("screen");
+ m_svga->set_vram_size(32*1024*1024);
+}
+
+
+
+void neon250_device::device_start()
+{
+ pci_card_device::device_start();
+
+ add_map( 64*1024*1024, M_MEM | M_PREF, FUNC(neon250_device::pvr_fb_map));
+ add_map( 16*1024, M_MEM | M_PREF, FUNC(neon250_device::pvr_mmio_map));
+ add_map( 128*1024, M_MEM | M_PREF, FUNC(neon250_device::vga_fb_map));
+ add_map( 2*1024, M_MEM, FUNC(neon250_device::vga_mmio_map));
+ // not indicated, assume no-pref again
+ add_map( 256, M_IO, FUNC(neon250_device::pvr_io_map));
+
+ add_rom((u8 *)m_vga_rom->base(), 128*1024 );
+ expansion_rom_base = 0xc0000;
+
+ // INTA#
+ intr_pin = 1;
+}
+
+void neon250_device::device_reset()
+{
+ pci_card_device::device_reset();
+
+ command = 0x0000;
+ // can VGA palette snoop, can MWI (bit 4)
+ command_mask = 0x0037;
+ // medium DEVSELB + fast back to back + new cap support
+ // can set AGP bit 5
+ status = 0x0290;
+
+ remap_cb();
+}
+
+u8 neon250_device::capptr_r()
+{
+ return 0x60;
+}
+
+void neon250_device::config_map(address_map &map)
+{
+ pci_device::config_map(map);
+
+ // AGP
+ map(0x40, 0x43).lr32(NAME([] { return 0x0010'0002; }));
+ // AGP 1x & 2x + SBA + 31 RQ
+ map(0x44, 0x47).lr32(NAME([] { return 0x1f00'0203; }));
+
+// map(0x4c, 0x4d) Discard Timer
+// map(0x50, 0x50) 16T Timer
+// map(0x54, 0x54) 8T Timer
+// map(0x58, 0x59) SSVIDW
+// map(0x5a, 0x5b) Subsystem Control
+// map(0x5c, 0x5d) SSDEVW
+
+ // Power management
+ // PCI PM 1.0 compliant + Device Specific Init (DSI) + D1 & D2 support
+ // TODO: disables capptr if AGP is unset
+ map(0x60, 0x63).lr32(NAME([] { return 0x0621'4001; }));
+
+// map(0x70, 0x71) AGP PLL Control
+// map(0x72, 0x73) Core PLL Control
+}
+
+
+
+void neon250_device::pvr_fb_map(address_map &map)
+{
+
+}
+
+void neon250_device::pvr_mmio_map(address_map &map)
+{
+}
+
+void neon250_device::pvr_io_map(address_map &map)
+{
+}
+
+void neon250_device::vga_fb_map(address_map &map)
+{
+}
+
+void neon250_device::vga_mmio_map(address_map &map)
+{
+}
+
+// TODO: this should really be a subclass of VGA
+void neon250_device::legacy_memory_map(address_map &map)
+{
+ map(0xa0000, 0xbffff).rw(FUNC(neon250_device::vram_r), FUNC(neon250_device::vram_w));
+}
+
+void neon250_device::legacy_io_map(address_map &map)
+{
+ map(0, 0x02f).m(m_svga, FUNC(vga_device::io_map));
+}
+
+uint8_t neon250_device::vram_r(offs_t offset)
+{
+ return downcast<vga_device *>(m_svga.target())->mem_r(offset);
+}
+
+void neon250_device::vram_w(offs_t offset, uint8_t data)
+{
+ downcast<vga_device *>(m_svga.target())->mem_w(offset, data);
+}
+
+void neon250_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 (command & 7)
+ {
+ memory_space->install_readwrite_handler(0xa0000, 0xbffff, read8sm_delegate(*this, FUNC(neon250_device::vram_r)), write8sm_delegate(*this, FUNC(neon250_device::vram_w)));
+
+ io_space->install_device(0x03b0, 0x03df, *this, &neon250_device::legacy_io_map);
+ //memory_space->install_rom(0xc0000, 0xcffff, (void *)expansion_rom);
+ }
+}
diff --git a/src/devices/bus/pci/neon250.h b/src/devices/bus/pci/neon250.h
new file mode 100644
index 00000000000..286f25a4343
--- /dev/null
+++ b/src/devices/bus/pci/neon250.h
@@ -0,0 +1,53 @@
+// license:BSD-3-Clause
+// copyright-holders:
+#ifndef MAME_BUS_PCI_NEON250_H
+#define MAME_BUS_PCI_NEON250_H
+
+#pragma once
+
+#include "pci_slot.h"
+#include "video/pc_vga.h"
+
+class neon250_device : public pci_card_device
+{
+public:
+ neon250_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
+
+ void legacy_memory_map(address_map &map) ATTR_COLD;
+ void legacy_io_map(address_map &map) ATTR_COLD;
+
+protected:
+ neon250_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock);
+
+ 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;
+
+ virtual const tiny_rom_entry *device_rom_region() const override ATTR_COLD;
+
+ 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 ATTR_COLD;
+
+ required_device<vga_device> m_svga;
+ required_memory_region m_vga_rom;
+
+ virtual u8 capptr_r() override;
+
+// bool m_vga_legacy_enable = false;
+private:
+ u8 vram_r(offs_t offset);
+ void vram_w(offs_t offset, uint8_t data);
+
+ void pvr_fb_map(address_map &map) ATTR_COLD;
+ void pvr_mmio_map(address_map &map) ATTR_COLD;
+ void pvr_io_map(address_map &map) ATTR_COLD;
+
+ void vga_fb_map(address_map &map) ATTR_COLD;
+ void vga_mmio_map(address_map &map) ATTR_COLD;
+};
+
+DECLARE_DEVICE_TYPE(NEON250, neon250_device)
+
+#endif // MAME_BUS_PCI_NEON250_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..10ac39172d7
--- /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) ATTR_COLD;
+
+protected:
+ virtual void device_start() override ATTR_COLD;
+ virtual void device_reset() override ATTR_COLD;
+
+ 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..5494f9701c3
--- /dev/null
+++ b/src/devices/bus/pci/oti_spitfire.h
@@ -0,0 +1,47 @@
+// license:BSD-3-Clause
+// copyright-holders:Angelo Salese
+#ifndef MAME_BUS_PCI_OTI_SPITFIRE_H
+#define MAME_BUS_PCI_OTI_SPITFIRE_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) ATTR_COLD;
+
+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 ATTR_COLD;
+ virtual void device_reset() override ATTR_COLD;
+ virtual void device_add_mconfig(machine_config &config) override ATTR_COLD;
+
+ virtual const tiny_rom_entry *device_rom_region() const override ATTR_COLD;
+
+ 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 ATTR_COLD;
+
+ required_device<oak_oti111_vga_device> m_svga;
+ required_memory_region m_vga_rom;
+private:
+ void mmio_map(address_map &map) ATTR_COLD;
+ void vram_aperture_map(address_map &map) ATTR_COLD;
+ void extio_map(address_map &map) ATTR_COLD;
+
+ 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_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..ae9d42afc63
--- /dev/null
+++ b/src/devices/bus/pci/pci_slot.cpp
@@ -0,0 +1,186 @@
+// 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 "ncr53c825.h"
+#include "neon250.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("ncr53c825", NCR53C825_PCI);
+ 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("virgevx", VIRGEVX_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)
+{
+ // nVidia
+ 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);
+ // Cirrus Logic
+ device.option_add("laguna3d", GD5465_LAGUNA3D);
+ // PowerVR VideoLogic
+ device.option_add("neon250", NEON250);
+ // SiS
+ 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..3d63159437c
--- /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 ATTR_COLD;
+
+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 ATTR_COLD;
+ virtual void device_reset() override ATTR_COLD;
+
+ 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..83e051684c3
--- /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 compliant
+
+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..9278c158d9c
--- /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 ATTR_COLD;
+ virtual void device_reset() override ATTR_COLD;
+ virtual void device_add_mconfig(machine_config &config) override ATTR_COLD;
+
+ virtual const tiny_rom_entry *device_rom_region() const override ATTR_COLD;
+
+// 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 ATTR_COLD;
+
+private:
+ void ide1_command_map(address_map &map) ATTR_COLD;
+ void ide1_control_map(address_map &map) ATTR_COLD;
+ void ide2_command_map(address_map &map) ATTR_COLD;
+ void ide2_control_map(address_map &map) ATTR_COLD;
+ void bus_master_ide_control_map(address_map &map) ATTR_COLD;
+ void extra_map(address_map &map) ATTR_COLD;
+
+// 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..704d6deb354
--- /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) ATTR_COLD;
+ void legacy_io_map(address_map &map) ATTR_COLD;
+
+ 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 ATTR_COLD;
+ virtual void device_reset() override ATTR_COLD;
+ virtual void device_add_mconfig(machine_config &config) override ATTR_COLD;
+
+ virtual const tiny_rom_entry *device_rom_region() const override ATTR_COLD;
+
+ 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 ATTR_COLD;
+
+ 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) ATTR_COLD;
+};
+
+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..a01d8721729
--- /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) ATTR_COLD;
+ void legacy_io_map(address_map &map) ATTR_COLD;
+
+protected:
+ riva128_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock);
+
+ 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;
+
+ virtual const tiny_rom_entry *device_rom_region() const override ATTR_COLD;
+
+ 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 ATTR_COLD;
+
+ virtual void mmio_map(address_map &map) ATTR_COLD;
+ virtual void vram_aperture_map(address_map &map) ATTR_COLD;
+ virtual void indirect_io_map(address_map &map) ATTR_COLD;
+
+ 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 ATTR_COLD;
+};
+
+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..be68c9f7bb6
--- /dev/null
+++ b/src/devices/bus/pci/rivatnt.h
@@ -0,0 +1,71 @@
+// license:BSD-3-Clause
+// copyright-holders: Angelo Salese
+#ifndef MAME_BUS_PCI_RIVATNT_H
+#define MAME_BUS_PCI_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 ATTR_COLD;
+ virtual void device_start() override ATTR_COLD;
+};
+
+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 ATTR_COLD;
+ virtual void device_start() override ATTR_COLD;
+};
+
+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 ATTR_COLD;
+};
+
+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 ATTR_COLD;
+};
+
+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 ATTR_COLD;
+};
+
+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 // MAME_BUS_PCI_RIVATNT_H
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..746d41b36ff
--- /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 ATTR_COLD;
+ virtual void device_reset() override ATTR_COLD;
+ virtual void device_add_mconfig(machine_config &config) override ATTR_COLD;
+
+// virtual const tiny_rom_entry *device_rom_region() const override ATTR_COLD;
+
+// 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 ATTR_COLD;
+
+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..bef9d7aeb8c
--- /dev/null
+++ b/src/devices/bus/pci/rtl8139_pci.h
@@ -0,0 +1,37 @@
+// license:BSD-3-Clause
+// copyright-holders:
+#ifndef MAME_BUS_PCI_RTL8139_PCI_H
+#define MAME_BUS_PCI_RTL8139_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 ATTR_COLD;
+ virtual void device_reset() override ATTR_COLD;
+ virtual void device_add_mconfig(machine_config &config) override ATTR_COLD;
+
+// virtual const tiny_rom_entry *device_rom_region() const override ATTR_COLD;
+
+// 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 ATTR_COLD;
+
+private:
+ // ...
+};
+
+DECLARE_DEVICE_TYPE(RTL8139_PCI, rtl8139_pci_device)
+
+#endif // MAME_NETWORK_RTL8139_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..ff467785024
--- /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 ATTR_COLD;
+ virtual void device_reset() override ATTR_COLD;
+ virtual void device_add_mconfig(machine_config &config) override ATTR_COLD;
+
+ virtual const tiny_rom_entry *device_rom_region() const override ATTR_COLD;
+
+ 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 ATTR_COLD;
+
+ virtual u8 capptr_r() override;
+
+ void vram_aperture_map(address_map &map) ATTR_COLD;
+ void mmio_map(address_map &map) ATTR_COLD;
+ void vmi_map(address_map &map) ATTR_COLD;
+private:
+ required_device<sis6236_vga_device> m_vga;
+ required_memory_region m_vga_rom;
+
+ void legacy_memory_map(address_map &map) ATTR_COLD;
+ void legacy_io_map(address_map &map) ATTR_COLD;
+
+ 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..e17a6abe582
--- /dev/null
+++ b/src/devices/bus/pci/sonicvibes.cpp
@@ -0,0 +1,162 @@
+// 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, "speaker", 2).front();
+
+ // 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, "speaker", 1.0, 0);
+ m_opl3->add_route(1, "speaker", 1.0, 1);
+ m_opl3->add_route(2, "speaker", 1.0, 0);
+ m_opl3->add_route(3, "speaker", 1.0, 1);
+
+// DAC_16BIT_R2R(config, m_ldac, 0).add_route(ALL_OUTPUTS, "speaker", 0.5); // unknown DAC
+// DAC_16BIT_R2R(config, m_rdac, 0).add_route(ALL_OUTPUTS, "speaker", 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..7a216a83f8e
--- /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 ATTR_COLD;
+ virtual void device_reset() override ATTR_COLD;
+ virtual void device_add_mconfig(machine_config &config) override ATTR_COLD;
+
+ virtual void config_map(address_map &map) override ATTR_COLD;
+
+private:
+ required_device<ymf262_device> m_opl3;
+ required_device<pc_joy_device> m_joy;
+
+ void games_legacy_map(address_map &map) ATTR_COLD;
+ void enhanced_map(address_map &map) ATTR_COLD;
+ void fm_map(address_map &map) ATTR_COLD;
+ void midi_map(address_map &map) ATTR_COLD;
+ void gameport_map(address_map &map) ATTR_COLD;
+};
+
+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..6b91069db92
--- /dev/null
+++ b/src/devices/bus/pci/sw1000xg.cpp
@@ -0,0 +1,93 @@
+// 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, "speaker", 2).front();
+
+ SWP30(config, m_swp30);
+ m_swp30->set_addrmap(AS_DATA, &sw1000xg_device::swp30_map);
+ m_swp30->add_route(0, "speaker", 1.0, 0);
+ m_swp30->add_route(1, "speaker", 1.0, 1);
+}
+
diff --git a/src/devices/bus/pci/sw1000xg.h b/src/devices/bus/pci/sw1000xg.h
new file mode 100644
index 00000000000..bb375a704ee
--- /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 ATTR_COLD;
+ virtual void device_reset() override ATTR_COLD;
+ const tiny_rom_entry *device_rom_region() const override;
+ virtual void device_add_mconfig(machine_config &config) override ATTR_COLD;
+
+private:
+ required_device<h83002_device> m_maincpu;
+ required_device<swp30_device> m_swp30;
+
+ void h8_map(address_map &map) ATTR_COLD;
+ void swp30_map(address_map &map) ATTR_COLD;
+};
+
+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..2e746a25ac4
--- /dev/null
+++ b/src/devices/bus/pci/virge_pci.cpp
@@ -0,0 +1,347 @@
+// license:BSD-3-Clause
+// copyright-holders:Barry Rodewald
+
+
+#include "emu.h"
+#include "virge_pci.h"
+
+#include "screen.h"
+
+DEFINE_DEVICE_TYPE(VIRGE_PCI, virge_pci_device, "virge_pci", "S3 86C325 ViRGE")
+DEFINE_DEVICE_TYPE(VIRGEVX_PCI, virgevx_pci_device, "virgevx_pci", "S3 86C988 ViRGE/VX")
+DEFINE_DEVICE_TYPE(VIRGEDX_PCI, virgedx_pci_device, "virgedx_pci", "S3 86C375 ViRGE/DX")
+//VIRGEGX_PCI, /DX with SGRAM/SDRAM support
+
+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)
+{
+}
+
+virgevx_pci_device::virgevx_pci_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
+ : virge_pci_device(mconfig, VIRGEVX_PCI, tag, owner, clock)
+{
+}
+
+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(0x8000,0x8043) PCI Configuration Space regs
+ map(0x8180,0x81ff).m(m_vga, FUNC(s3virge_vga_device::streams_control_map));
+
+ //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));
+ // TODO: writeable
+ 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).m(m_vga, FUNC(s3virge_vga_device::s3d_register_map));
+
+ // alternate image transfer ports
+ map(0xd000,0xefff).w(m_vga, FUNC(s3virge_vga_device::image_xfer));
+
+ //map(0xff00, 0xff5f) LPB Local Peripheral Bus control
+ //map(0xff1c, 0xff1f) LPB GIP/GOP General Input/Output Port (for OEM implementations)
+ map(0xff20, 0xff23).rw(m_vga, FUNC(s3virge_vga_device::serial_port_r), FUNC(s3virge_vga_device::serial_port_w));
+ //map(0xff24, 0xff27) LPB Video Input Window Size
+ //map(0xff28, 0xff2b) LPB Video Data Offsets
+ //map(0xff2c, 0xff2f) LPB Horizontal Decimation Control Register
+ //map(0xff30, 0xff33) LPB Vertical Decimation Control Register
+ //map(0xff34, 0xff37) LPB Line Stride
+ //map(0xff40, 0xff5f) LPB Output FIFO Register
+}
+
+void virge_pci_device::lfb_map(address_map& map)
+{
+ // NOTE: upper mirror is i/f for BE hosts.
+ map(0x0, 0x00ffffff).mirror(0x02000000).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);
+
+ command = 0x0000;
+ // DAC SNP / BME / MEM / I/O
+ command_mask = 0x27;
+ // medium DEVSELB
+ status = 0x0200;
+
+ remap_cb();
+ machine().save().register_postload(save_prepost_delegate(FUNC(virge_pci_device::postload), this));
+}
+
+void virgevx_pci_device::device_start()
+{
+ set_ids(0x5333883d, 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(virgevx_pci_device::lfb_map));
+ set_map_address(0, 0x70000000);
+
+ command = 0x0000;
+ // DAC SNP / BME / MEM / I/O
+ command_mask = 0x27;
+ // medium DEVSELB
+ status = 0x0200;
+
+ remap_cb();
+ machine().save().register_postload(save_prepost_delegate(FUNC(virgevx_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);
+
+ command = 0x0000;
+ // DAC SNP / BME / MEM / I/O
+ command_mask = 0x27;
+ // medium DEVSELB
+ status = 0x0200;
+
+ 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)
+{
+ if (BIT(command, 1))
+ {
+ 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)));
+ // 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())
+ {
+ 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);
+
+ get_bar_address |= 0x02000000;
+ memory_space->install_device(get_bar_address, get_bar_address | 0xffff, *this, &virge_pci_device::mmio_map);
+ }
+ }
+
+ if (BIT(command, 0))
+ {
+ io_space->install_device(0x03b0, 0x03df, *this, &virge_pci_device::legacy_io_map);
+
+ // Available at MMFF20 only if true
+ if (m_vga->read_pd26_strapping() == false)
+ {
+ const u16 port_offset = m_vga->read_pd25_strapping() ? 0xe2 : 0xe8;
+ io_space->install_readwrite_handler(port_offset, port_offset, read8sm_delegate(m_vga, FUNC(s3virge_vga_device::serial_port_r)), write8sm_delegate(m_vga, FUNC(s3virge_vga_device::serial_port_w)));
+ }
+ }
+}
+
+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 virgevx_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));
+
+ S3VIRGEVX(config, m_vga, 0);
+ m_vga->set_screen("screen");
+ // 2MB, 4MB and 8MB, EDO RAM
+ m_vga->set_vram_size(0x400000);
+ m_vga->linear_config_changed().set(FUNC(virgevx_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
+
+const tiny_rom_entry *virge_pci_device::device_rom_region() const
+{
+ return ROM_NAME( virge_pci );
+}
+
+ROM_START( virgevx_pci )
+ ROM_REGION(0x8000,"bios", 0)
+ ROM_DEFAULT_BIOS("dms3d3k")
+
+ // Vlask dump
+ // v2.xx BIOSes known to exist
+ ROM_SYSTEM_BIOS( 0, "dms3d3k", "Diamond Stealth 3D 3000 HQ v1.00" )
+ ROMX_LOAD("diamondstealth3000.vbi", 0x0000, 0x8000, CRC(c2423896) SHA1(fdab43f15da1d66bca286583f9da86873f3e22de), ROM_BIOS(0) )
+ROM_END
+
+const tiny_rom_entry *virgevx_pci_device::device_rom_region() const
+{
+ return ROM_NAME( virgevx_pci );
+}
+
+
+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_SYSTEM_BIOS( 2, "s600dx", "Leadtek WinFast 3D S600DX V1.01.03" )
+ ROMX_LOAD("winfast_3d_s600dx.bin", 0x00000, 0x8000, CRC(d68db9f4) SHA1(9a7f58fab7811342a00bbc76837b4f9015913ddb), ROM_BIOS(2) )
+ROM_END
+
+const tiny_rom_entry *virgedx_pci_device::device_rom_region() const
+{
+ return ROM_NAME( virgedx_pci );
+}
diff --git a/src/devices/video/virge_pci.h b/src/devices/bus/pci/virge_pci.h
index a672fb03b08..30e7c348c7e 100644
--- a/src/devices/video/virge_pci.h
+++ b/src/devices/bus/pci/virge_pci.h
@@ -5,15 +5,15 @@
* S3 ViRGE 3D accelerator card
*/
-#ifndef MAME_VIDEO_VIRGE_PCI_H
-#define MAME_VIDEO_VIRGE_PCI_H
+#ifndef MAME_BUS_PCI_VIRGE_PCI_H
+#define MAME_BUS_PCI_VIRGE_PCI_H
#pragma once
-#include "machine/pci.h"
-#include "bus/isa/s3virge.h"
+#include "pci_slot.h"
+#include "video/s3virge.h"
-class virge_pci_device : public pci_device
+class virge_pci_device : public pci_card_device
{
public:
template <typename T>
@@ -34,28 +34,24 @@ public:
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);
+ void lfb_map(address_map &map) ATTR_COLD;
+ void mmio_map(address_map &map) ATTR_COLD;
- DECLARE_READ32_MEMBER(vga_3b0_r);
- DECLARE_WRITE32_MEMBER(vga_3b0_w);
- DECLARE_READ32_MEMBER(vga_3c0_r);
- DECLARE_WRITE32_MEMBER(vga_3c0_w);
- DECLARE_READ32_MEMBER(vga_3d0_r);
- DECLARE_WRITE32_MEMBER(vga_3d0_w);
- DECLARE_READ8_MEMBER(vram_r);
- DECLARE_WRITE8_MEMBER(vram_w);
- DECLARE_READ32_MEMBER(base_address_r);
- DECLARE_WRITE32_MEMBER(base_address_w);
+ 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) ATTR_COLD;
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 device_start() override ATTR_COLD;
+ virtual void device_add_mconfig(machine_config &config) override ATTR_COLD;
+ virtual const tiny_rom_entry *device_rom_region() const override ATTR_COLD;
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 config_map(address_map &map) override ATTR_COLD;
void postload(void);
@@ -63,10 +59,32 @@ protected:
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();
+};
- uint8_t m_current_crtc_reg;
+class virgevx_pci_device : public virge_pci_device
+{
+public:
+ template <typename T>
+ virgevx_pci_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock, T &&screen_tag)
+ : virgevx_pci_device(mconfig, tag, owner, clock)
+ {
+ set_screen_tag(std::forward<T>(screen_tag));
+ }
+ virgevx_pci_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
+
+protected:
+ virtual void device_start() override ATTR_COLD;
+ virtual void device_add_mconfig(machine_config &config) override ATTR_COLD;
+ virtual const tiny_rom_entry *device_rom_region() const override ATTR_COLD;
+
+// required_device<s3virge_vga_device> m_vga;
+// required_memory_region m_bios;
+// optional_device<screen_device> m_screen;
};
class virgedx_pci_device : public virge_pci_device
@@ -81,9 +99,9 @@ public:
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;
+ virtual void device_start() override ATTR_COLD;
+ virtual void device_add_mconfig(machine_config &config) override ATTR_COLD;
+ virtual const tiny_rom_entry *device_rom_region() const override ATTR_COLD;
// required_device<s3virge_vga_device> m_vga;
// required_memory_region m_bios;
@@ -91,6 +109,7 @@ protected:
};
DECLARE_DEVICE_TYPE(VIRGE_PCI, virge_pci_device)
+DECLARE_DEVICE_TYPE(VIRGEVX_PCI, virgevx_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..366a5b31ec8
--- /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_VISION_H
+#define MAME_BUS_PCI_VISION_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) ATTR_COLD;
+
+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 ATTR_COLD;
+ virtual void device_reset() override ATTR_COLD;
+ virtual void device_add_mconfig(machine_config &config) override ATTR_COLD;
+
+ virtual const tiny_rom_entry *device_rom_region() const override ATTR_COLD;
+
+ 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 ATTR_COLD;
+
+ virtual const tiny_rom_entry *device_rom_region() const override ATTR_COLD;
+};
+
+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 ATTR_COLD;
+
+ virtual const tiny_rom_entry *device_rom_region() const override ATTR_COLD;
+ virtual void device_start() override ATTR_COLD;
+ virtual void device_reset() override ATTR_COLD;
+
+ 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) ATTR_COLD;
+};
+
+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_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..485f16aac22
--- /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 ATTR_COLD;
+ virtual void device_reset() override ATTR_COLD;
+ virtual void device_add_mconfig(machine_config &config) override ATTR_COLD;
+
+// 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 ATTR_COLD;
+
+private:
+ void ohci_mmio_map(address_map &map) ATTR_COLD;
+ void vio_map(address_map &map) ATTR_COLD;
+
+ 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..13bf3961e7c
--- /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) ATTR_COLD;
+
+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 ATTR_COLD;
+ virtual void device_reset() override ATTR_COLD;
+ virtual void device_add_mconfig(machine_config &config) override ATTR_COLD;
+
+ virtual const tiny_rom_entry *device_rom_region() const override ATTR_COLD;
+
+ 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 ATTR_COLD;
+
+private:
+ required_device<wd90c33_vga_device> m_svga;
+ required_memory_region m_vga_rom;
+
+ void vram_aperture_map(address_map &map) ATTR_COLD;
+
+ 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..c19e797ab15
--- /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 ATTR_COLD;
+ virtual void device_reset() override ATTR_COLD;
+
+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) ATTR_COLD;
+
+ 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..f8a0ac98f85
--- /dev/null
+++ b/src/devices/bus/pci/zr36057.cpp
@@ -0,0 +1,779 @@
+// license:BSD-3-Clause
+// copyright-holders: Angelo Salese
+/**************************************************************************************************
+
+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/v6.13/driver-api/media/drivers/zoran.html
+- Currently using DC10+ configuration:
+ ZR36067 + ZR36060 (ZR36050 + ZR36016 glued together)
+ SAA7110a (TV decoder) + adv7176 (TV encoder, Linux driver name is adv7175)
+ZR36057 is known to have two HW quirks that are been fixed with ZR36067.
+
+TODO:
+- Enough to pass board functions in dc10plus HW test, requires GIRQ1 signal source to continue
+(from SAA7110? On its own it doesn't touch any of the sync registers);
+- Hookup busmaster;
+- What are i2c 0x8e >> 1 address device checks for?
+\- Can't be adv7175 (0xd4 >> 1) nor adv7176 (0x54 >> 1)
+- Noisy on undocumented guest ID 7 once VidCap capturing is enabled;
+...
+- Soft Reset & Write lock mechanisms (each register have separate macro-groups);
+- GuestBus slot mechanism (relevant when multiple devices are hooked);
+- eventually decouple AV PCI controller part from the actual client cards;
+
+Known mix-ins:
+- s3virge.cpp uses SAA7110 for Scenic Highway overlay available with its S3 LPB connector;
+- apple/pippin.cpp uses bt856, reused by LML33 as TV encoder;
+- jaleco/tetrisp2.cpp stepstag uses adv7176;
+- misc/sliver.cpp uses ZR36050 + ZR36011 + MD0208 (alias for something else?);
+- misc/magictg.cpp uses ZR36120 + ZR36050 + ZR36016;
+- namco/namcos23.cpp gunwars camera uses VPX3220A, shared with DC10(old) and DC30/DC30+;
+- nintendo/cham24.cpp has SAA7111A on-board, reused with Iomega Buz cards in non-A variant;
+
+**************************************************************************************************/
+
+#include "emu.h"
+#include "zr36057.h"
+
+#define LOG_WARN (1U << 1)
+#define LOG_PO (1U << 2) // PostOffice interactions
+#define LOG_VFE (1U << 3) // Log Video Front End
+#define LOG_SYNC (1U << 4) // Log Sync signals and Active Area (as SyncMstr)
+
+#define VERBOSE (LOG_GENERAL | LOG_WARN | LOG_VFE | LOG_SYNC)
+//#define LOG_OUTPUT_FUNC osd_printf_info
+#include "logmacro.h"
+
+#define LOGWARN(...) LOGMASKED(LOG_WARN, __VA_ARGS__)
+#define LOGPO(...) LOGMASKED(LOG_PO, __VA_ARGS__)
+#define LOGVFE(...) LOGMASKED(LOG_VFE, __VA_ARGS__)
+#define LOGSYNC(...) LOGMASKED(LOG_SYNC, __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)
+ , m_guest(*this, "guest")
+ , m_decoder(*this, "decoder")
+{
+ // ZR36057PQC Video cutting chipset
+ // device ID reportedly same for ZR36057 and ZR36067, revision 0x02 for latter.
+ // Known subvendors list (earlier cards don't define one):
+ // - 0x10317efe: Pinnacle/Miro DC10+
+ // - 0x1031d801: Pinnacle/Miro DC30+
+ // - 0x1031fc00: Pinnacle/Miro DC50, Motion JPEG Capture/CODEC Board
+ // - 0x12f88a02: Electronic Design GmbH Tekram Video Kit a.k.a. Linux Media Labs LML33R10
+ // - 0x13ca4231: Iomega Buz 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, 0x02, 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)
+{
+ ZR36060(config, m_guest, XTAL(27'000'000));
+
+ SAA7110A(config, m_decoder, XTAL(26'800'000));
+ m_decoder->sda_callback().set([this](int state) { m_decoder_sdao_state = state; });
+ //m_decoder->vs_callback().set(FUNC(zr36057_device::girq1_w));
+
+ //ADV7176(config, m_encoder, XTAL(27'000'000));
+
+ // S-Video input/output
+ // composite video input/output
+
+ // video and audio input/output pins on PCB, for cross connection with other boards
+
+ // DC30 combines the two audio input/output as an external jack option
+}
+
+void zr36057_device::device_start()
+{
+ pci_card_device::device_start();
+
+ add_map(4 * 1024, M_MEM, FUNC(zr36057_device::asr_map));
+
+ // INTA#
+ intr_pin = 1;
+}
+
+void zr36057_device::device_reset()
+{
+ pci_card_device::device_reset();
+
+ // fast DEVSEL# (00), can enable busmaster
+ command = 0x0000;
+ command_mask = 0x0006;
+ status = 0x0000;
+ intr_line = 0x0a;
+ // TODO: PCI regs 0x3e/0x3f max_lat = 0x10 (4 usec), min_gnt = 0x02 (0.5 usec)
+
+ remap_cb();
+
+ m_softreset = 0;
+ software_reset();
+}
+
+void zr36057_device::software_reset()
+{
+ LOG("SoftReset\n");
+ m_vfe.hspol = m_vfe.vspol = 0;
+ m_vfe.hstart = m_vfe.vstart = 0x001;
+ m_vfe.hend = m_vfe.vend = 0x3ff;
+ m_vfe.horizontal_config = (m_vfe.hspol << 30) | (m_vfe.hstart << 10) | (m_vfe.hend << 0);
+ m_vfe.vertical_config = (m_vfe.vspol << 30) | (m_vfe.vstart << 10) | (m_vfe.vend << 0);
+
+ m_vfe.ext_fi = 0;
+ m_vfe.top_field = 1;
+ m_vfe.vclk_pol = 0;
+ m_vfe.hfilter = 0;
+ m_vfe.dup_fld = 0;
+ m_vfe.hor_dcm = 0;
+ m_vfe.ver_dcm = 0;
+ m_vfe.disp_mod = 0;
+ m_vfe.yuv2rgb = 2;
+ m_vfe.err_dif = 0;
+ m_vfe.pack24 = 0;
+ m_vfe.little_endian = 1;
+ m_vfe.format_config = (m_vfe.top_field << 25) | (m_vfe.yuv2rgb << 3) | (m_vfe.little_endian << 0);
+ m_vfe.vid_bottom_base = m_vfe.vid_top_base = m_vfe.mask_bottom_base = m_vfe.mask_top_base = 0xffff'fffc;
+ m_vfe.disp_stride = 0xfffc;
+ m_vfe.vid_ovf = m_vfe.snapshot = m_vfe.frame_grab = false;
+ m_vfe.vid_en = false;
+ m_vfe.min_pix = 0xf;
+ m_vfe.triton = false;
+ m_vfe.window_height = 0x0f0;
+ m_vfe.window_width = 0x3ff;
+ m_vfe.display_config = (m_vfe.vid_en << 31) | (m_vfe.min_pix << 24) | (m_vfe.window_height << 12) | (m_vfe.window_width);
+
+ m_vfe.ovl_enable = false;
+ m_vfe.mask_stride = 0xff;
+
+ // TODO: these also go in process_reset fn
+ // defaults in MPEG mode
+ m_jpeg.mode = false;
+ m_jpeg.sub_mode = 3;
+ m_jpeg.rtbsy_fb = m_jpeg.go_en = m_jpeg.sync_mstr = m_jpeg.fld_per_buff = false;
+ m_jpeg.vfifo_fb = m_jpeg.cfifo_fb = false;
+ m_jpeg.still_lendian = true;
+ m_jpeg.p_reset = true;
+ m_jpeg.cod_trns_en = false;
+ m_jpeg.active = false;
+
+ m_sync_gen.vsync_size = 6;
+ m_sync_gen.vtotal = 525;
+ m_sync_gen.hsync_start = 640;
+ m_sync_gen.htotal = 780;
+
+ m_active_area.nax = 0;
+ m_active_area.pax = 640;
+ m_active_area.nay = 10;
+ m_active_area.pay = 240;
+ m_active_area.odd = true;
+
+ m_jpeg.guest_id = 4;
+ m_jpeg.guest_reg = 0;
+
+ m_irq_status = m_irq_enable = 0;
+ m_inta_pin_enable = false;
+
+ m_pci_waitstate_control = 0;
+ m_gpio_ddr = 0xff; // all inputs
+ // GuestBus ID default
+ // m_gpio_data = 0xf0;
+ for (int i = 0; i < 4; i++)
+ m_guestbus.time[i] = 0;
+
+ m_po.pending = false;
+ m_po.time_out = false;
+ m_po.dir = true;
+ m_po.guest_id = 0;
+ m_po.guest_reg = 0;
+}
+
+void zr36057_device::config_map(address_map &map)
+{
+ pci_card_device::config_map(map);
+ map(0x3e, 0x3e).lr8(NAME([] () { return 0x02; }));
+ map(0x3f, 0x3f).lr8(NAME([] () { return 0x10; }));
+}
+
+// Application Specific Register(s)
+void zr36057_device::asr_map(address_map &map)
+{
+ map(0x000, 0x003).lrw32(
+ NAME([this] (offs_t offset) {
+ // NOTE: wants to read-back here, throws "Bus Master ASIC error" otherwise (?)
+ LOGVFE("Video Front End: Horizontal Configuration R\n");
+ return m_vfe.horizontal_config;
+ }),
+ NAME([this] (offs_t offset, u32 data, u32 mem_mask) {
+ COMBINE_DATA(&m_vfe.horizontal_config);
+ LOGVFE("Video Front End: Horizontal Configuration W %08x & %08x\n", data, mem_mask);
+ m_vfe.hspol = BIT(m_vfe.horizontal_config, 30);
+ m_vfe.hstart = (m_vfe.horizontal_config >> 10) & 0x3ff;
+ m_vfe.hend = (m_vfe.horizontal_config >> 0) & 0x3ff;
+ LOGVFE("\tHSPol %d, HStart %d, HEnd %d\n", m_vfe.hspol, m_vfe.hstart, m_vfe.hend);
+ })
+ );
+ map(0x004, 0x007).lrw32(
+ NAME([this] (offs_t offset) {
+ LOGVFE("Video Front End: Vertical Configuration R\n");
+ return m_vfe.vertical_config;
+ }),
+ NAME([this] (offs_t offset, u32 data, u32 mem_mask) {
+ COMBINE_DATA(&m_vfe.vertical_config);
+ LOGVFE("Video Front End: Vertical Configuration W %08x & %08x\n", data, mem_mask);
+ m_vfe.vspol = BIT(m_vfe.vertical_config, 30);
+ m_vfe.vstart = (m_vfe.vertical_config >> 10) & 0x3ff;
+ m_vfe.vend = (m_vfe.vertical_config >> 0) & 0x3ff;
+ LOGVFE("\tVSPol %d, VStart %d, VEnd %d\n", m_vfe.vspol, m_vfe.vstart, m_vfe.vend);
+ })
+ );
+ map(0x008, 0x00b).lrw32(
+ NAME([this] (offs_t offset) {
+ LOGVFE("Video Front End: Format Configuration R\n");
+ return m_vfe.format_config;
+ }),
+ NAME([this] (offs_t offset, u32 data, u32 mem_mask) {
+ COMBINE_DATA(&m_vfe.format_config);
+ LOGVFE("Video Front End: Format Configuration W %08x & %08x\n", data, mem_mask);
+ m_vfe.ext_fi = BIT(m_vfe.format_config, 26);
+ m_vfe.top_field = BIT(m_vfe.format_config, 25);
+ m_vfe.vclk_pol = BIT(m_vfe.format_config, 24);
+ LOGVFE("\tExtFI %d, TopField %d, VCLKPol %d\n"
+ , m_vfe.ext_fi, m_vfe.top_field, m_vfe.vclk_pol
+ );
+ // Video Scaler
+ m_vfe.hfilter = (m_vfe.format_config >> 21) & 7;
+ m_vfe.dup_fld = BIT(m_vfe.format_config, 20);
+ m_vfe.hor_dcm = (m_vfe.format_config >> 14) & 0x3f;
+ m_vfe.ver_dcm = (m_vfe.format_config >> 8) & 0x3f;
+ LOGVFE("\tHFilter %d, DupFld %d, HorDcm %d, VerDcm %d\n"
+ , m_vfe.hfilter
+ , m_vfe.dup_fld
+ , m_vfe.hor_dcm
+ , m_vfe.ver_dcm
+ );
+ // Pixel Formatter
+ m_vfe.disp_mod = BIT(m_vfe.format_config, 6);
+ m_vfe.yuv2rgb = (m_vfe.format_config >> 3) & 3;
+ m_vfe.err_dif = BIT(m_vfe.format_config, 2);
+ m_vfe.pack24 = BIT(m_vfe.format_config, 1);
+ m_vfe.little_endian = BIT(m_vfe.format_config, 0);
+ LOGVFE("\tDispMod %d, YUV2RGB %d, ErrDif %d, Pack24 %d, LittleEndian %d\n"
+ , m_vfe.disp_mod
+ , m_vfe.yuv2rgb
+ , m_vfe.err_dif
+ , m_vfe.pack24
+ , m_vfe.little_endian
+ );
+ })
+ );
+ map(0x00c, 0x00f).lrw32(
+ NAME([this] (offs_t offset) {
+ LOGVFE("Video Display Top R\n");
+ return m_vfe.vid_top_base;
+ }),
+ NAME([this] (offs_t offset, u32 data, u32 mem_mask) {
+ COMBINE_DATA(&m_vfe.vid_top_base);
+ m_vfe.vid_top_base &= 0xffff'fffc;
+ LOGVFE("Video Display Top W %08x & %08x\n", data, mem_mask);
+ })
+ );
+ map(0x010, 0x013).lrw32(
+ NAME([this] (offs_t offset) {
+ LOGVFE("Video Display Top R\n");
+ return m_vfe.vid_bottom_base;
+ }),
+ NAME([this] (offs_t offset, u32 data, u32 mem_mask) {
+ COMBINE_DATA(&m_vfe.vid_bottom_base);
+ m_vfe.vid_bottom_base &= 0xffff'fffc;
+ LOGVFE("Video Display Bottom W %08x & %08x\n", data, mem_mask);
+ })
+ );
+ map(0x014, 0x017).lrw32(
+ NAME([this] (offs_t offset) {
+ LOGVFE("Video Stride, Status and Frame Grab R\n");
+ return (m_vfe.disp_stride << 16) | (m_vfe.vid_ovf << 8) | (m_vfe.snapshot << 1) | (m_vfe.frame_grab << 0);
+ }),
+ NAME([this] (offs_t offset, u32 data, u32 mem_mask) {
+ LOGVFE("Video Stride, Status and Frame Grab W %08x & %08x\n", data, mem_mask);
+ if (ACCESSING_BITS_16_31)
+ {
+ COMBINE_DATA(&m_vfe.disp_stride);
+ m_vfe.disp_stride &= 0xfffc;
+ LOGVFE("\tDispStride %d\n", m_vfe.disp_stride);
+ }
+
+ if (ACCESSING_BITS_8_15)
+ {
+ // bit 8 high clears the overflow flag
+ if (BIT(data, 8))
+ {
+ m_vfe.vid_ovf = false;
+ LOGVFE("\tVidOvf clear\n");
+ }
+ }
+
+ if (ACCESSING_BITS_0_7)
+ {
+ m_vfe.snapshot = !!(BIT(data, 1));
+ m_vfe.frame_grab = !!(BIT(data, 0));
+ LOGVFE("\tSnapShot %d, FrameGrab %d\n", m_vfe.snapshot, m_vfe.frame_grab);
+ // Presumably this will stall the emulation (goes off after two fields)
+ if (m_vfe.frame_grab)
+ popmessage("zr36057: FrameGrab enabled");
+ }
+ })
+ );
+ map(0x018, 0x01b).lrw32(
+ NAME([this] (offs_t offset) {
+ LOG("Video Display Configuration R\n");
+ return m_vfe.display_config;
+ }),
+ NAME([this] (offs_t offset, u32 data, u32 mem_mask) {
+ COMBINE_DATA(&m_vfe.display_config);
+ LOGVFE("Video Display Configuration W %08x & %08x\n", data, mem_mask);
+ m_vfe.vid_en = !!BIT(m_vfe.display_config, 31);
+ // Not a mistake: min_pix overlaps with the /Triton setting
+ m_vfe.min_pix = (m_vfe.display_config >> 24) & 0x7f;
+ m_vfe.triton = !!BIT(~m_vfe.display_config, 24);
+ LOGVFE("\tVidEn %d, MinPix %d, Triton %s Controller\n"
+ , m_vfe.vid_en
+ , m_vfe.min_pix
+ , m_vfe.triton ? "Intel 'Triton' Bridge" : "Other PCI Bridge"
+ );
+ m_vfe.window_height = (m_vfe.display_config >> 12) & 0x3ff;
+ m_vfe.window_width = (m_vfe.display_config >> 0) & 0x3ff;
+ LOGVFE("\tVidWinHt %d, VidWinWid %d\n", m_vfe.window_height, m_vfe.window_width);
+ })
+ );
+ map(0x01c, 0x01f).lrw32(
+ NAME([this] (offs_t offset) {
+ LOGVFE("Masking Map Top R\n");
+ return m_vfe.mask_top_base;
+ }),
+ NAME([this] (offs_t offset, u32 data, u32 mem_mask) {
+ COMBINE_DATA(&m_vfe.mask_top_base);
+ m_vfe.mask_top_base &= 0xffff'fffc;
+ LOGVFE("Masking Map Top W %08x & %08x\n", data, mem_mask);
+ })
+ );
+ map(0x020, 0x023).lrw32(
+ NAME([this] (offs_t offset) {
+ LOGVFE("Masking Map Bottom R\n");
+ return m_vfe.mask_bottom_base;
+ }),
+ NAME([this] (offs_t offset, u32 data, u32 mem_mask) {
+ COMBINE_DATA(&m_vfe.mask_bottom_base);
+ m_vfe.mask_bottom_base &= 0xffff'fffc;
+ LOGVFE("Masking Map Bottom W %08x & %08x\n", data, mem_mask);
+ })
+ );
+ map(0x024, 0x027).lrw32(
+ NAME([this] (offs_t offset) {
+ LOGVFE("Overlay Control R\n");
+ return (m_vfe.ovl_enable << 15) | (m_vfe.mask_stride << 0);
+ }),
+ NAME([this] (offs_t offset, u32 data, u32 mem_mask) {
+ LOGVFE("Overlay Control W %08x & %08x\n", data, mem_mask);
+ if (ACCESSING_BITS_8_15)
+ {
+ m_vfe.ovl_enable = !!(BIT(data, 15));
+ LOGVFE("\tOvlEnable %d\n", m_vfe.ovl_enable);
+ }
+
+ if (ACCESSING_BITS_0_7)
+ {
+ m_vfe.mask_stride = data & 0xff;
+ LOGVFE("\tMaskStride %d\n", m_vfe.mask_stride);
+ }
+ })
+ );
+ map(0x028, 0x02b).lrw32(
+ NAME([this] (offs_t offset) {
+ return (m_softreset << 24) | (m_pci_waitstate_control << 16) | m_gpio_ddr;
+ }),
+ NAME([this] (offs_t offset, u32 data, u32 mem_mask) {
+ LOG("System, PCI and General Purpose Pins Control %08x & %08x\n", data, mem_mask);
+ if (ACCESSING_BITS_24_31)
+ {
+ m_softreset = !!BIT(data, 24);
+ // TODO: will lock all writes in asr_map but this bit
+ // (inclusive of the "all" group?)
+ if (!m_softreset)
+ {
+ software_reset();
+ return;
+ }
+ }
+ if (ACCESSING_BITS_16_23)
+ m_pci_waitstate_control = (data >> 16) & 7;
+
+ if (ACCESSING_BITS_0_7)
+ m_gpio_ddr = data & 0xff;
+ })
+ );
+ map(0x02c, 0x02f).lrw32(
+ NAME([this] (offs_t offset) {
+ LOG("General Purpose Pins and GuestBus Control R\n");
+
+ // The doc claims 0xf0 default for GPIO, but win98 driver will throw "subvendor ID failed"
+ // while testing various ID combinations here
+ // This should come from GDAT pin at strapping time
+ return (0x7e << 24) | (m_guestbus.time[3] << 12) | (m_guestbus.time[2] << 8) | (m_guestbus.time[1] << 4) | (m_guestbus.time[0] << 0);
+ }),
+ NAME([this] (offs_t offset, u32 data, u32 mem_mask) {
+ LOG("General Purpose Pins and GuestBus Control W %08x & %08x\n", data, mem_mask);
+
+ // if (ACCESSING_BITS_24_31)
+ // GenPurIO writes, TBD
+
+ if (ACCESSING_BITS_8_15)
+ {
+ m_guestbus.time[3] = (data >> 12) & 0xf;
+ m_guestbus.time[2] = (data >> 8) & 0xf;
+ }
+
+ if (ACCESSING_BITS_0_7)
+ {
+ m_guestbus.time[1] = (data >> 4) & 0xf;
+ m_guestbus.time[0] = (data >> 0) & 0xf;
+ }
+ })
+ );
+// map(0x030, 0x033) MPEG Code Source Address
+// map(0x034, 0x037) MPEG Code Transfer Control
+// map(0x038, 0x03b) MPEG Code Memory Pointer
+ map(0x03c, 0x03f).lrw32(
+ NAME([this] (offs_t offset) {
+ return m_irq_status;
+ }),
+ NAME([this] (offs_t offset, u32 data, u32 mem_mask) {
+ if (ACCESSING_BITS_24_31)
+ {
+ m_irq_status &= ~data;
+ m_irq_status &= 0x7800'0000;
+ update_irq_status();
+ }
+ })
+ );
+ map(0x040, 0x043).lrw32(
+ NAME([this] (offs_t offset) {
+ return m_irq_enable | (m_inta_pin_enable << 24);
+ }),
+ NAME([this] (offs_t offset, u32 data, u32 mem_mask) {
+ if (ACCESSING_BITS_24_31)
+ {
+ LOG("IRQ Enable W %08x & %08x\n", data, mem_mask);
+ m_irq_enable = data;
+ m_irq_enable &= 0x7800'0000;
+ m_inta_pin_enable = BIT(data, 24);
+ LOG("\tINTA enable %d\n", m_inta_pin_enable);
+ LOG("\tGIRQ1 %d GIRQ0 %d CodRepIRQ %d JPEGRepIRQ\n"
+ , BIT(data, 30)
+ , BIT(data, 29)
+ , BIT(data, 28)
+ , BIT(data, 27)
+ );
+ update_irq_status();
+ }
+ })
+ );
+ map(0x044, 0x047).lrw32(
+ NAME([this] (offs_t offset) {
+ //LOG("I2C R\n");
+ // avoid win98 stall for now
+ return m_decoder_sdao_state << 1 | 1;
+ //return 3;
+ }),
+ NAME([this] (offs_t offset, u32 data, u32 mem_mask) {
+ //LOG("I2C %02x %08x\n", data, mem_mask);
+ if (ACCESSING_BITS_0_7)
+ {
+ m_decoder->sda_write(BIT(data, 1));
+ m_decoder->scl_write(BIT(data, 0));
+ }
+ })
+ );
+ map(0x100, 0x103).lrw32(
+ NAME([this] (offs_t offset) {
+ LOG("JPEG Mode and Control R\n");
+ return (m_jpeg.mode << 31) | (m_jpeg.sub_mode << 29)
+ | (m_jpeg.rtbsy_fb << 6) | (m_jpeg.go_en << 5) | (m_jpeg.sync_mstr << 4)
+ | (m_jpeg.fld_per_buff << 3) | (m_jpeg.vfifo_fb << 2)
+ | (m_jpeg.cfifo_fb << 1) | (m_jpeg.still_lendian << 0);
+ }),
+ NAME([this] (offs_t offset, u32 data, u32 mem_mask) {
+ LOG("JPEG Mode and Control W %08x & %08x\n", data, mem_mask);
+ if (ACCESSING_BITS_24_31)
+ {
+ m_jpeg.mode = !!BIT(data, 31);
+ // --x- (0) Still Image (1) Motion Video
+ // ---x (0) Decompression (1) Compression
+ m_jpeg.sub_mode = (data >> 29) & 3;
+ LOG("\tJPG %s Mode, JPGMode %d\n"
+ , m_jpeg.mode ? "JPEG" : "MPEG"
+ , m_jpeg.sub_mode
+ );
+ }
+
+ if (ACCESSING_BITS_0_7)
+ {
+ m_jpeg.rtbsy_fb = !!BIT(data, 6);
+ m_jpeg.go_en = !!BIT(data, 5);
+ m_jpeg.sync_mstr = !!BIT(data, 4);
+ m_jpeg.fld_per_buff = !!BIT(data, 3);
+ m_jpeg.vfifo_fb = !!BIT(data, 2);
+ m_jpeg.cfifo_fb = !!BIT(data, 1);
+ m_jpeg.still_lendian = !!BIT(data, 0);
+ LOG("\tRTBSY_FB %d, Go_en %d, SyncMstr %d, Fld_per_buff %s, VFIFO_FB %d, CFIFO_FB %d, Still_LitEndian %s\n"
+ , m_jpeg.rtbsy_fb
+ , m_jpeg.go_en
+ , m_jpeg.sync_mstr
+ , m_jpeg.fld_per_buff ? "1 (One code field)" : "0 (Two code fields, one code frame)"
+ , m_jpeg.vfifo_fb
+ , m_jpeg.cfifo_fb
+ , m_jpeg.still_lendian ? "Little" : "Gib"
+ );
+ if (m_jpeg.go_en)
+ popmessage("zr36057.cpp: go_en enabled");
+ }
+ })
+ );
+ map(0x104, 0x107).lrw32(
+ NAME([this] (offs_t offset) {
+ LOG("JPEG Process Control R\n");
+ return (m_jpeg.p_reset << 7) | (m_jpeg.cod_trns_en << 5) | (m_jpeg.active << 0);
+ }),
+ NAME([this] (offs_t offset, u32 data, u32 mem_mask) {
+ LOG("JPEG Process Control W %08x & %08x\n", data, mem_mask);
+ if (ACCESSING_BITS_0_7)
+ {
+ m_jpeg.p_reset = !!BIT(data, 7);
+ m_jpeg.cod_trns_en = !!BIT(data, 5);
+ m_jpeg.active = !!BIT(data, 0);
+ LOG("\tP_reset %d, CodTrnsEn %d, Active %d\n"
+ , m_jpeg.p_reset
+ , m_jpeg.cod_trns_en
+ , m_jpeg.active
+ );
+ }
+ })
+ );
+ map(0x108, 0x10b).lrw32(
+ NAME([this] (offs_t offset) {
+ LOGSYNC("Vertical Sync Parameters R\n");
+ return (m_sync_gen.vsync_size << 16) | (m_sync_gen.vtotal);
+ }),
+ NAME([this] (offs_t offset, u32 data, u32 mem_mask) {
+ LOGSYNC("Vertical Sync Parameters W %08x & %08x\n", data, mem_mask);
+ if (ACCESSING_BITS_16_23)
+ {
+ m_sync_gen.vsync_size = (data >> 16) & 0xff;
+ LOGSYNC("\tVsyncSize %d\n", m_sync_gen.vsync_size);
+ }
+
+ if (ACCESSING_BITS_0_15)
+ {
+ m_sync_gen.vtotal = data & 0xffff;
+ LOGSYNC("\tFrmTot %d\n", m_sync_gen.vtotal);
+ }
+ })
+ );
+ map(0x10c, 0x10f).lrw32(
+ NAME([this] (offs_t offset) {
+ LOGSYNC("Horizontal Sync Parameters R\n");
+ return (m_sync_gen.hsync_start << 16) | (m_sync_gen.htotal);
+ }),
+ NAME([this] (offs_t offset, u32 data, u32 mem_mask) {
+ LOGSYNC("Horizontal Sync Parameters W %08x & %08x\n", data, mem_mask);
+ if (ACCESSING_BITS_16_31)
+ {
+ m_sync_gen.hsync_start = (data >> 16) & 0xffff;
+ LOGSYNC("\tHsyncStart %d\n", m_sync_gen.hsync_start);
+ }
+
+ if (ACCESSING_BITS_0_15)
+ {
+ m_sync_gen.htotal = data & 0xffff;
+ LOGSYNC("\tLineTot %d\n", m_sync_gen.htotal);
+ }
+ })
+ );
+ map(0x110, 0x113).lrw32(
+ NAME([this] (offs_t offset) {
+ LOGSYNC("Field Horizontal Active Portion R\n");
+ return (m_active_area.nax << 16) | (m_active_area.pax);
+ }),
+ NAME([this] (offs_t offset, u32 data, u32 mem_mask) {
+ LOGSYNC("Field Horizontal Active Portion W %08x & %08x\n", data, mem_mask);
+ if (ACCESSING_BITS_16_31)
+ {
+ m_active_area.nax = (data >> 16) & 0xffff;
+ LOGSYNC("\tNAX %d\n", m_active_area.nax);
+ }
+
+ if (ACCESSING_BITS_0_15)
+ {
+ m_active_area.pax = data & 0xffff;
+ LOGSYNC("\tPAX %d\n", m_active_area.pax);
+ }
+ })
+ );
+ map(0x114, 0x117).lrw32(
+ NAME([this] (offs_t offset) {
+ LOGSYNC("Field Vertical Active Portion R\n");
+ return (m_active_area.nay << 16) | (m_active_area.pay);
+ }),
+ NAME([this] (offs_t offset, u32 data, u32 mem_mask) {
+ LOGSYNC("Field Vertical Active Portion W %08x & %08x\n", data, mem_mask);
+ if (ACCESSING_BITS_16_31)
+ {
+ m_active_area.nay = (data >> 16) & 0xffff;
+ LOGSYNC("\tNAY %d\n", m_active_area.nay);
+ }
+
+ if (ACCESSING_BITS_0_15)
+ {
+ m_active_area.pay = data & 0xffff;
+ LOGSYNC("\tPAY %d\n", m_active_area.pay);
+ }
+ })
+ );
+ map(0x118, 0x11b).lrw32(
+ NAME([this] (offs_t offset) {
+ LOGSYNC("Field Process Parameters R\n");
+ return m_active_area.odd;
+ }),
+ NAME([this] (offs_t offset, u32 data, u32 mem_mask) {
+ LOGSYNC("Field Process Parameters W %08x & %08x\n", data, mem_mask);
+ if (ACCESSING_BITS_0_7)
+ {
+ m_active_area.odd = !!BIT(data, 0);
+ LOGSYNC("\tOdd_Even: %s\n", m_active_area.odd ? "Odd" : "Even");
+ }
+ })
+ );
+// map(0x11c, 0x11f) JPEG Code Base Address
+// map(0x120, 0x123) JPEG Code FIFO Threshold
+ map(0x124, 0x124).lrw8(
+ NAME([this] (offs_t offset) {
+ LOG("JPEG Codec Guest ID R\n");
+ return (m_jpeg.guest_id << 4) | (m_jpeg.guest_reg << 0);
+ }),
+ NAME([this] (offs_t offset, u8 data) {
+ m_jpeg.guest_id = (data >> 4) & 7;
+ m_jpeg.guest_reg = (data >> 0) & 7;
+ LOG("JPEG Codec Guest ID W %02x\n", data);
+ })
+ );
+ map(0x12c, 0x12f).lrw32(
+ NAME([this] (offs_t offset) {
+ LOG("GuestBus Control (II) R\n");
+
+ return (0 << 16) | (m_guestbus.time[7] << 12) | (m_guestbus.time[6] << 8) | (m_guestbus.time[5] << 4) | (m_guestbus.time[4] << 0);
+ }),
+ NAME([this] (offs_t offset, u32 data, u32 mem_mask) {
+ LOG("GuestBus Control (II) W %08x & %08x\n", data, mem_mask);
+
+ if (ACCESSING_BITS_8_15)
+ {
+ m_guestbus.time[7] = (data >> 12) & 0xf;
+ m_guestbus.time[6] = (data >> 8) & 0xf;
+ }
+
+ if (ACCESSING_BITS_0_7)
+ {
+ m_guestbus.time[5] = (data >> 4) & 0xf;
+ m_guestbus.time[4] = (data >> 0) & 0xf;
+ }
+ })
+ );
+
+ map(0x200, 0x2ff).rw(FUNC(zr36057_device::postoffice_r), FUNC(zr36057_device::postoffice_w));
+// map(0x300, 0x303) Still Transfer
+}
+
+// TODO: PostOffice accesses thru GuestBus are dictated with PCI clock cycles, asynchronous
+// We pretend they are synchronous as a starting point, and one port only (which may matter later
+// with CODE transfers). A time out happens 64 PCI cycles later in ZR36067, '120 halves that threshold.
+// This should eventually be expressed in a osd_work_queue, with guestbus address_space roughly as:
+// for (int i = 0; i < 8; i++)
+// {
+// if (<is_device_installed>)
+// map(0 | (i << 2), 3 | (i << 2)).flags(<fn>).m(m_guest[i], map);
+// else
+// map(0 | (i << 2), 3 | (i << 2)).flags(<abort_fn>);
+// }
+u32 zr36057_device::postoffice_r(offs_t offset)
+{
+ //LOGPO("PO R %d %d\n", m_po.guest_id, m_po.guest_reg);
+ u8 res = 0;
+ if (m_po.guest_id == 0)
+ {
+ if (m_po.dir == false)
+ res = m_guest->read(m_po.guest_reg);
+ }
+ else if (!machine().side_effects_disabled())
+ {
+ m_po.time_out = true;
+ LOGWARN("Warning: PO access unmapped POGuestID read %d %02x\n", m_po.guest_id, m_po.guest_reg);
+ }
+
+ return (m_po.pending << 25)
+ | (m_po.time_out << 24)
+ | (m_po.dir << 23)
+ | (m_po.guest_id << 20)
+ | (m_po.guest_reg << 16)
+ | res;
+}
+
+void zr36057_device::postoffice_w(offs_t offset, u32 data, u32 mem_mask)
+{
+ // clear a previously set time out flag
+ if (BIT(data, 24))
+ m_po.time_out = false;
+ m_po.dir = !!(BIT(data, 23));
+ m_po.guest_id = (data >> 20) & 7;
+ m_po.guest_reg = (data >> 16) & 7;
+ LOGPO("PO W [%08x] %08x & %08x PODir %s POGuestID %d POGuestReg %d POData %02x\n"
+ , offset << 2
+ , data
+ , mem_mask
+ , m_po.dir ? "Write" : "Read"
+ , m_po.guest_id
+ , m_po.guest_reg
+ , data & 0xff
+ );
+ if (m_po.guest_id == 0)
+ {
+ if (m_po.dir == true)
+ m_guest->write(m_po.guest_reg, data & 0xff);
+ }
+ else
+ {
+ m_po.time_out = true;
+ LOGWARN("Warning: PO access unmapped POGuestID write %d %02x\n", m_po.guest_id, m_po.guest_reg);
+ }
+}
+
+void zr36057_device::update_irq_status()
+{
+ if (m_inta_pin_enable)
+ {
+ irq_pin_w(0, m_irq_status & m_irq_enable);
+ }
+}
diff --git a/src/devices/bus/pci/zr36057.h b/src/devices/bus/pci/zr36057.h
new file mode 100644
index 00000000000..727f5bcff53
--- /dev/null
+++ b/src/devices/bus/pci/zr36057.h
@@ -0,0 +1,121 @@
+// license:BSD-3-Clause
+// copyright-holders: Angelo Salese
+
+#ifndef MAME_BUS_PCI_ZR36057_H
+#define MAME_BUS_PCI_ZR36057_H
+
+#pragma once
+
+#include "pci_slot.h"
+#include "video/saa7110.h"
+#include "video/zr36060.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 ATTR_COLD;
+ virtual void device_reset() override ATTR_COLD;
+ virtual void device_add_mconfig(machine_config &config) override ATTR_COLD;
+
+// virtual const tiny_rom_entry *device_rom_region() const override ATTR_COLD;
+
+ virtual void config_map(address_map &map) override ATTR_COLD;
+
+private:
+ required_device<zr36060_device> m_guest;
+ required_device<saa7110a_device> m_decoder;
+ void asr_map(address_map &map) ATTR_COLD;
+
+ void software_reset();
+ u32 postoffice_r(offs_t offset);
+ void postoffice_w(offs_t offset, u32 data, u32 mem_mask);
+
+ // Video Front End
+ struct {
+ u32 horizontal_config;
+ u32 vertical_config;
+ u32 format_config;
+ int hspol, vspol;
+ u16 hstart, hend, vstart, vend;
+
+ int ext_fi, top_field, vclk_pol;
+ u8 hfilter;
+ int dup_fld;
+ u8 hor_dcm, ver_dcm;
+ int disp_mod;
+ u8 yuv2rgb;
+ int err_dif, pack24, little_endian;
+
+ u32 vid_top_base, vid_bottom_base;
+
+ u16 disp_stride;
+ bool vid_ovf;
+ bool snapshot, frame_grab;
+
+ u32 display_config;
+ bool vid_en;
+ u8 min_pix;
+ bool triton;
+ u16 window_height, window_width;
+
+ u32 mask_top_base, mask_bottom_base;
+ bool ovl_enable;
+ u8 mask_stride;
+ } m_vfe;
+
+ bool m_softreset;
+ u8 m_gpio_ddr, m_pci_waitstate_control;
+
+ // NOTE: these are technically external/public pins.
+ void girq1_w(int state) { m_irq_status |= 1 << 30; update_irq_status(); }
+ void girq0_w(int state) { m_irq_status |= 1 << 29; update_irq_status(); }
+ void cod_rep_irq_w(int state) { m_irq_status |= 1 << 28; update_irq_status(); }
+ void jpeg_rep_irq_w(int state) { m_irq_status |= 1 << 27; update_irq_status(); }
+
+ void update_irq_status();
+ u32 m_irq_status, m_irq_enable;
+ bool m_inta_pin_enable;
+ int m_decoder_sdao_state;
+
+ struct {
+ u8 guest_id, guest_reg;
+ bool mode;
+ u8 sub_mode;
+ bool rtbsy_fb, go_en, sync_mstr, fld_per_buff, vfifo_fb, cfifo_fb, still_lendian;
+ bool p_reset, cod_trns_en, active;
+ } m_jpeg;
+
+ struct {
+ u8 vsync_size;
+ u16 hsync_start;
+ u16 vtotal, htotal;
+ } m_sync_gen;
+
+ struct {
+ u16 nax, pax, nay, pay;
+ bool odd;
+ } m_active_area;
+
+ struct {
+ u8 time[8];
+ } m_guestbus;
+
+ struct {
+ bool dir; /**< true: Write, false: Read */
+ bool time_out;
+ bool pending;
+ u8 guest_id;
+ u8 guest_reg;
+ } m_po; /**< PostOffice */
+};
+
+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 7bc3915a283..d5f17db1e37 100644
--- a/src/devices/bus/pet/2joysnd.cpp
+++ b/src/devices/bus/pet/2joysnd.cpp
@@ -49,7 +49,6 @@ Connections
#include "emu.h"
#include "2joysnd.h"
-#include "sound/volt_reg.h"
#include "speaker.h"
@@ -66,18 +65,18 @@ DEFINE_DEVICE_TYPE(PET_USERPORT_JOYSTICK_AND_SOUND_DEVICE, pet_userport_joystick
static INPUT_PORTS_START( 2joysnd )
PORT_START("JOY")
- PORT_BIT( 0x01, IP_ACTIVE_LOW, IPT_JOYSTICK_RIGHT ) PORT_8WAY PORT_PLAYER(1) PORT_WRITE_LINE_DEVICE_MEMBER(DEVICE_SELF, device_pet_user_port_interface, output_c)
- PORT_BIT( 0x02, IP_ACTIVE_LOW, IPT_JOYSTICK_LEFT ) PORT_8WAY PORT_PLAYER(1) PORT_WRITE_LINE_DEVICE_MEMBER(DEVICE_SELF, device_pet_user_port_interface, output_d)
- PORT_BIT( 0x04, IP_ACTIVE_LOW, IPT_JOYSTICK_DOWN ) PORT_8WAY PORT_PLAYER(1) PORT_WRITE_LINE_DEVICE_MEMBER(DEVICE_SELF, pet_userport_joystick_and_sound_device, write_down1)
- PORT_BIT( 0x08, IP_ACTIVE_LOW, IPT_JOYSTICK_UP ) PORT_8WAY PORT_PLAYER(1) PORT_WRITE_LINE_DEVICE_MEMBER(DEVICE_SELF, pet_userport_joystick_and_sound_device, write_up1)
- PORT_BIT( 0x10, IP_ACTIVE_LOW, IPT_JOYSTICK_RIGHT ) PORT_8WAY PORT_PLAYER(2) PORT_WRITE_LINE_DEVICE_MEMBER(DEVICE_SELF, device_pet_user_port_interface, output_h)
- PORT_BIT( 0x20, IP_ACTIVE_LOW, IPT_JOYSTICK_LEFT ) PORT_8WAY PORT_PLAYER(2) PORT_WRITE_LINE_DEVICE_MEMBER(DEVICE_SELF, device_pet_user_port_interface, output_j)
- PORT_BIT( 0x40, IP_ACTIVE_LOW, IPT_JOYSTICK_DOWN ) PORT_8WAY PORT_PLAYER(2) PORT_WRITE_LINE_DEVICE_MEMBER(DEVICE_SELF, pet_userport_joystick_and_sound_device, write_down2)
- PORT_BIT( 0x80, IP_ACTIVE_LOW, IPT_JOYSTICK_UP ) PORT_8WAY PORT_PLAYER(2) PORT_WRITE_LINE_DEVICE_MEMBER(DEVICE_SELF, pet_userport_joystick_and_sound_device, write_up2)
+ PORT_BIT( 0x01, IP_ACTIVE_LOW, IPT_JOYSTICK_RIGHT ) PORT_8WAY PORT_PLAYER(1) PORT_WRITE_LINE_DEVICE_MEMBER(DEVICE_SELF, FUNC(device_pet_user_port_interface::output_c))
+ PORT_BIT( 0x02, IP_ACTIVE_LOW, IPT_JOYSTICK_LEFT ) PORT_8WAY PORT_PLAYER(1) PORT_WRITE_LINE_DEVICE_MEMBER(DEVICE_SELF, FUNC(device_pet_user_port_interface::output_d))
+ PORT_BIT( 0x04, IP_ACTIVE_LOW, IPT_JOYSTICK_DOWN ) PORT_8WAY PORT_PLAYER(1) PORT_WRITE_LINE_DEVICE_MEMBER(DEVICE_SELF, FUNC(pet_userport_joystick_and_sound_device::write_down1))
+ PORT_BIT( 0x08, IP_ACTIVE_LOW, IPT_JOYSTICK_UP ) PORT_8WAY PORT_PLAYER(1) PORT_WRITE_LINE_DEVICE_MEMBER(DEVICE_SELF, FUNC(pet_userport_joystick_and_sound_device::write_up1))
+ PORT_BIT( 0x10, IP_ACTIVE_LOW, IPT_JOYSTICK_RIGHT ) PORT_8WAY PORT_PLAYER(2) PORT_WRITE_LINE_DEVICE_MEMBER(DEVICE_SELF, FUNC(device_pet_user_port_interface::output_h))
+ PORT_BIT( 0x20, IP_ACTIVE_LOW, IPT_JOYSTICK_LEFT ) PORT_8WAY PORT_PLAYER(2) PORT_WRITE_LINE_DEVICE_MEMBER(DEVICE_SELF, FUNC(device_pet_user_port_interface::output_j))
+ PORT_BIT( 0x40, IP_ACTIVE_LOW, IPT_JOYSTICK_DOWN ) PORT_8WAY PORT_PLAYER(2) PORT_WRITE_LINE_DEVICE_MEMBER(DEVICE_SELF, FUNC(pet_userport_joystick_and_sound_device::write_down2))
+ PORT_BIT( 0x80, IP_ACTIVE_LOW, IPT_JOYSTICK_UP ) PORT_8WAY PORT_PLAYER(2) PORT_WRITE_LINE_DEVICE_MEMBER(DEVICE_SELF, FUNC(pet_userport_joystick_and_sound_device::write_up2))
PORT_START("FIRE")
- PORT_BIT( 0x03, IP_ACTIVE_LOW, IPT_BUTTON1 ) PORT_PLAYER(1) PORT_WRITE_LINE_DEVICE_MEMBER(DEVICE_SELF, pet_userport_joystick_and_sound_device, write_fire1)
- PORT_BIT( 0x30, IP_ACTIVE_LOW, IPT_BUTTON1 ) PORT_PLAYER(2) PORT_WRITE_LINE_DEVICE_MEMBER(DEVICE_SELF, pet_userport_joystick_and_sound_device, write_fire2)
+ PORT_BIT( 0x03, IP_ACTIVE_LOW, IPT_BUTTON1 ) PORT_PLAYER(1) PORT_WRITE_LINE_DEVICE_MEMBER(DEVICE_SELF, FUNC(pet_userport_joystick_and_sound_device::write_fire1))
+ PORT_BIT( 0x30, IP_ACTIVE_LOW, IPT_BUTTON1 ) PORT_PLAYER(2) PORT_WRITE_LINE_DEVICE_MEMBER(DEVICE_SELF, FUNC(pet_userport_joystick_and_sound_device::write_fire2))
INPUT_PORTS_END
//-------------------------------------------------
@@ -97,8 +96,6 @@ void pet_userport_joystick_and_sound_device::device_add_mconfig(machine_config &
{
SPEAKER(config, "speaker").front_center();
DAC_1BIT(config, m_dac, 0).add_route(ALL_OUTPUTS, "speaker", 0.99);
- voltage_regulator_device &vref(VOLTAGE_REGULATOR(config, "vref"));
- vref.add_route(0, "dac", 1.0, DAC_VREF_POS_INPUT);
}
//**************************************************************************
@@ -155,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..0359bddd618 100644
--- a/src/devices/bus/pet/2joysnd.h
+++ b/src/devices/bus/pet/2joysnd.h
@@ -28,23 +28,23 @@ 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
- virtual void device_start() override;
+ virtual void device_start() override ATTR_COLD;
// optional information overrides
- virtual ioport_constructor device_input_ports() const override;
- virtual void device_add_mconfig(machine_config &config) override;
+ virtual ioport_constructor device_input_ports() const override ATTR_COLD;
+ virtual void device_add_mconfig(machine_config &config) override ATTR_COLD;
void update_port1();
void update_port2();
diff --git a/src/devices/bus/pet/64k.cpp b/src/devices/bus/pet/64k.cpp
index 85f91114386..7e335ba97ff 100644
--- a/src/devices/bus/pet/64k.cpp
+++ b/src/devices/bus/pet/64k.cpp
@@ -79,7 +79,7 @@ inline void pet_64k_expansion_device::write_ram(offs_t offset, uint8_t data)
pet_64k_expansion_device::pet_64k_expansion_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) :
device_t(mconfig, PET_64K, tag, owner, clock),
device_pet_expansion_card_interface(mconfig, *this),
- m_ram(*this, "ram"),
+ m_ram(*this, "ram", 0x10000, ENDIANNESS_LITTLE),
m_ctrl(0)
{
}
@@ -91,9 +91,6 @@ pet_64k_expansion_device::pet_64k_expansion_device(const machine_config &mconfig
void pet_64k_expansion_device::device_start()
{
- // allocate memory
- m_ram.allocate(0x10000);
-
// state saving
save_item(NAME(m_ctrl));
}
diff --git a/src/devices/bus/pet/64k.h b/src/devices/bus/pet/64k.h
index 7cf03cd621b..02a3db20ebb 100644
--- a/src/devices/bus/pet/64k.h
+++ b/src/devices/bus/pet/64k.h
@@ -29,8 +29,8 @@ public:
protected:
// device-level overrides
- virtual void device_start() override;
- virtual void device_reset() override;
+ virtual void device_start() override ATTR_COLD;
+ virtual void device_reset() override ATTR_COLD;
// device_pet_expansion_card_interface overrides
virtual int pet_norom_r(offs_t offset, int sel) override;
@@ -41,7 +41,7 @@ private:
inline uint8_t read_ram(offs_t offset);
inline void write_ram(offs_t offset, uint8_t data);
- optional_shared_ptr<uint8_t> m_ram;
+ memory_share_creator<uint8_t> m_ram;
uint8_t m_ctrl;
};
diff --git a/src/devices/bus/pet/c2n.cpp b/src/devices/bus/pet/c2n.cpp
index e7ac6e27c28..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"
+
//**************************************************************************
@@ -84,16 +86,16 @@ c1531_device::c1531_device(const machine_config &mconfig, const char *tag, devic
void c2n_device::device_start()
{
// allocate timers
- m_read_timer = timer_alloc();
+ m_read_timer = timer_alloc(FUNC(c2n_device::read_tick), this);
m_read_timer->adjust(attotime::from_hz(44100), 0, attotime::from_hz(44100));
}
//-------------------------------------------------
-// device_timer - handler timer events
+// read_tick - periodically read the datasette
//-------------------------------------------------
-void c2n_device::device_timer(emu_timer &timer, device_timer_id id, int param, void *ptr)
+TIMER_CALLBACK_MEMBER(c2n_device::read_tick)
{
if (m_motor)
{
diff --git a/src/devices/bus/pet/c2n.h b/src/devices/bus/pet/c2n.h
index 6430d1b01a0..1af93b59684 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"
@@ -34,11 +33,10 @@ protected:
c2n_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_timer(emu_timer &timer, device_timer_id id, int param, void *ptr) override;
+ virtual void device_start() override ATTR_COLD;
// optional information overrides
- virtual void device_add_mconfig(machine_config &config) override;
+ virtual void device_add_mconfig(machine_config &config) override ATTR_COLD;
// device_pet_datassette_port_interface overrides
virtual int datassette_read() override;
@@ -46,6 +44,8 @@ protected:
virtual int datassette_sense() override;
virtual void datassette_motor(int state) override;
+ TIMER_CALLBACK_MEMBER(read_tick);
+
private:
required_device<cassette_image_device> m_cassette;
diff --git a/src/devices/bus/pet/cass.cpp b/src/devices/bus/pet/cass.cpp
index 52b501b68b4..332d0140312 100644
--- a/src/devices/bus/pet/cass.cpp
+++ b/src/devices/bus/pet/cass.cpp
@@ -28,7 +28,7 @@ DEFINE_DEVICE_TYPE(PET_DATASSETTE_PORT, pet_datassette_port_device, "pet_datasse
//-------------------------------------------------
device_pet_datassette_port_interface::device_pet_datassette_port_interface(const machine_config &mconfig, device_t &device)
- : device_slot_card_interface(mconfig,device)
+ : device_interface(device, "petcass")
{
m_slot = dynamic_cast<pet_datassette_port_device *>(device.owner());
}
@@ -54,7 +54,7 @@ device_pet_datassette_port_interface::~device_pet_datassette_port_interface()
pet_datassette_port_device::pet_datassette_port_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) :
device_t(mconfig, PET_DATASSETTE_PORT, tag, owner, clock),
- device_slot_interface(mconfig, *this),
+ device_single_card_slot_interface<device_pet_datassette_port_interface>(mconfig, *this),
m_read_handler(*this), m_cart(nullptr)
{
}
@@ -75,19 +75,16 @@ pet_datassette_port_device::~pet_datassette_port_device()
void pet_datassette_port_device::device_start()
{
- m_cart = dynamic_cast<device_pet_datassette_port_interface *>(get_card_device());
-
- // resolve callbacks
- m_read_handler.resolve_safe();
+ m_cart = get_card_device();
}
-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 babfdf2058d..c0f53276733 100644
--- a/src/devices/bus/pet/cass.h
+++ b/src/devices/bus/pet/cass.h
@@ -39,7 +39,7 @@
class device_pet_datassette_port_interface;
-class pet_datassette_port_device : public device_t, public device_slot_interface
+class pet_datassette_port_device : public device_t, public device_single_card_slot_interface<device_pet_datassette_port_interface>
{
public:
template <typename T>
@@ -59,17 +59,17 @@ 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
- virtual void device_start() override;
+ virtual void device_start() override ATTR_COLD;
devcb_write_line m_read_handler;
@@ -80,7 +80,7 @@ protected:
// ======================> device_pet_datassette_port_interface
// class representing interface-specific live c64_expansion card
-class device_pet_datassette_port_interface : public device_slot_card_interface
+class device_pet_datassette_port_interface : public device_interface
{
public:
// construction/destruction
diff --git a/src/devices/bus/pet/cb2snd.cpp b/src/devices/bus/pet/cb2snd.cpp
index fffbb70923e..17dfc72b30b 100644
--- a/src/devices/bus/pet/cb2snd.cpp
+++ b/src/devices/bus/pet/cb2snd.cpp
@@ -11,7 +11,6 @@
#include "emu.h"
#include "cb2snd.h"
-#include "sound/volt_reg.h"
#include "speaker.h"
@@ -30,8 +29,6 @@ void pet_userport_cb2_sound_device::device_add_mconfig(machine_config &config)
{
SPEAKER(config, "speaker").front_center();
DAC_1BIT(config, m_dac, 0).add_route(ALL_OUTPUTS, "speaker", 0.99);
- voltage_regulator_device &vref(VOLTAGE_REGULATOR(config, "vref"));
- vref.add_route(0, "dac", 1.0, DAC_VREF_POS_INPUT);
}
//**************************************************************************
@@ -58,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..a6dd4e7c2cd 100644
--- a/src/devices/bus/pet/cb2snd.h
+++ b/src/devices/bus/pet/cb2snd.h
@@ -25,13 +25,13 @@ 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
- virtual void device_start() override;
+ virtual void device_start() override ATTR_COLD;
- virtual void device_add_mconfig(machine_config &config) override;
+ virtual void device_add_mconfig(machine_config &config) override ATTR_COLD;
required_device<dac_bit_interface> m_dac;
};
diff --git a/src/devices/bus/pet/diag.h b/src/devices/bus/pet/diag.h
index 8bcf1bfd415..634b030356a 100644
--- a/src/devices/bus/pet/diag.h
+++ b/src/devices/bus/pet/diag.h
@@ -28,23 +28,23 @@ 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
- virtual void device_start() override;
+ virtual void device_start() override ATTR_COLD;
};
diff --git a/src/devices/bus/pet/diag264_lb_tape.h b/src/devices/bus/pet/diag264_lb_tape.h
index 6eb11fd395d..205780114df 100644
--- a/src/devices/bus/pet/diag264_lb_tape.h
+++ b/src/devices/bus/pet/diag264_lb_tape.h
@@ -30,7 +30,7 @@ public:
protected:
// device-level overrides
- virtual void device_start() override;
+ virtual void device_start() override ATTR_COLD;
// device_pet_datassette_port_interface overrides
virtual int datassette_read() override;
diff --git a/src/devices/bus/pet/exp.cpp b/src/devices/bus/pet/exp.cpp
index 07aa7155b93..ee22ba3fc5d 100644
--- a/src/devices/bus/pet/exp.cpp
+++ b/src/devices/bus/pet/exp.cpp
@@ -37,8 +37,9 @@ DEFINE_DEVICE_TYPE(PET_EXPANSION_SLOT, pet_expansion_slot_device, "pet_expansion
pet_expansion_slot_device::pet_expansion_slot_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) :
device_t(mconfig, PET_EXPANSION_SLOT, tag, owner, clock),
- device_slot_interface(mconfig, *this), m_card(nullptr),
- m_read_dma(*this),
+ device_single_card_slot_interface<device_pet_expansion_card_interface>(mconfig, *this),
+ m_card(nullptr),
+ m_read_dma(*this, 0),
m_write_dma(*this)
{
}
@@ -58,7 +59,7 @@ pet_expansion_slot_device::~pet_expansion_slot_device()
//-------------------------------------------------
device_pet_expansion_card_interface::device_pet_expansion_card_interface(const machine_config &mconfig, device_t &device)
- : device_slot_card_interface(mconfig, device)
+ : device_interface(device, "petexp")
{
m_slot = dynamic_cast<pet_expansion_slot_device *>(device.owner());
}
@@ -74,40 +75,12 @@ device_pet_expansion_card_interface::~device_pet_expansion_card_interface()
//-------------------------------------------------
-// device_validity_check -
-//-------------------------------------------------
-
-void pet_expansion_slot_device::device_validity_check(validity_checker &valid) const
-{
- device_t *const carddev = get_card_device();
- if (carddev && !dynamic_cast<device_pet_expansion_card_interface *>(carddev))
- osd_printf_error("Card device %s (%s) does not implement device_pet_expansion_card_interface\n", carddev->tag(), carddev->name());
-}
-
-
-//-------------------------------------------------
// device_start - device-specific startup
//-------------------------------------------------
void pet_expansion_slot_device::device_start()
{
- device_t *const carddev = get_card_device();
- m_card = dynamic_cast<device_pet_expansion_card_interface *>(carddev);
- if (carddev && !m_card)
- fatalerror("Card device %s (%s) does not implement device_pet_expansion_card_interface\n", carddev->tag(), carddev->name());
-
- // resolve callbacks
- m_read_dma.resolve_safe(0);
- m_write_dma.resolve_safe();
-}
-
-
-//-------------------------------------------------
-// device_reset - device-specific reset
-//-------------------------------------------------
-
-void pet_expansion_slot_device::device_reset()
-{
+ m_card = get_card_device();
}
@@ -127,10 +100,8 @@ int pet_expansion_slot_device::norom_r(offs_t offset, int sel)
uint8_t pet_expansion_slot_device::read(offs_t offset, uint8_t data, int &sel)
{
- if (m_card != nullptr)
- {
+ if (m_card)
data = m_card->pet_bd_r(offset, data, sel);
- }
return data;
}
@@ -153,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;
}
@@ -163,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 39309b65f4c..a95dc536300 100644
--- a/src/devices/bus/pet/exp.h
+++ b/src/devices/bus/pet/exp.h
@@ -17,13 +17,6 @@
//**************************************************************************
-// CONSTANTS
-//**************************************************************************
-
-#define PET_EXPANSION_SLOT_TAG "exp"
-
-
-//**************************************************************************
// TYPE DEFINITIONS
//**************************************************************************
@@ -32,7 +25,7 @@
class device_pet_expansion_card_interface;
class pet_expansion_slot_device : public device_t,
- public device_slot_interface
+ public device_single_card_slot_interface<device_pet_expansion_card_interface>
{
public:
template <typename T>
@@ -55,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);
@@ -86,9 +79,7 @@ public:
protected:
// device-level overrides
- virtual void device_validity_check(validity_checker &valid) const override;
- virtual void device_start() override;
- virtual void device_reset() override;
+ virtual void device_start() override ATTR_COLD;
device_pet_expansion_card_interface *m_card;
@@ -99,7 +90,7 @@ protected:
// ======================> device_pet_expansion_card_interface
-class device_pet_expansion_card_interface : public device_slot_card_interface
+class device_pet_expansion_card_interface : public device_interface
{
friend class pet_expansion_slot_device;
@@ -112,8 +103,8 @@ protected:
// runtime
virtual int pet_norom_r(offs_t offset, int sel) { return 1; }
- virtual uint8_t pet_bd_r(offs_t offset, uint8_t data, int &sel) { return data; };
- virtual void pet_bd_w(offs_t offset, uint8_t data, int &sel) { };
+ virtual uint8_t pet_bd_r(offs_t offset, uint8_t data, int &sel) { return data; }
+ virtual void pet_bd_w(offs_t offset, uint8_t data, int &sel) { }
virtual int pet_diag_r() { return 1; }
virtual void pet_irq_w(int state) { }
diff --git a/src/devices/bus/pet/hsg.h b/src/devices/bus/pet/hsg.h
index e86cb101ac3..394dd6b7526 100644
--- a/src/devices/bus/pet/hsg.h
+++ b/src/devices/bus/pet/hsg.h
@@ -29,11 +29,11 @@ protected:
cbm8000_hsg_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_start() override ATTR_COLD;
+ virtual void device_reset() override ATTR_COLD;
// optional information overrides
- virtual const tiny_rom_entry *device_rom_region() const override;
+ virtual const tiny_rom_entry *device_rom_region() const override ATTR_COLD;
// device_pet_expansion_card_interface overrides
virtual int pet_norom_r(offs_t offset, int sel) override;
@@ -58,10 +58,10 @@ public:
protected:
// optional information overrides
- virtual void device_add_mconfig(machine_config &config) override;
+ virtual void device_add_mconfig(machine_config &config) override ATTR_COLD;
private:
- void hsg_a_map(address_map &map);
+ void hsg_a_map(address_map &map) ATTR_COLD;
};
@@ -75,10 +75,10 @@ public:
protected:
// optional information overrides
- virtual void device_add_mconfig(machine_config &config) override;
+ virtual void device_add_mconfig(machine_config &config) override ATTR_COLD;
private:
- void hsg_b_map(address_map &map);
+ void hsg_b_map(address_map &map) ATTR_COLD;
};
diff --git a/src/devices/bus/pet/petuja.cpp b/src/devices/bus/pet/petuja.cpp
index aee8c2a1f0f..70275910615 100644
--- a/src/devices/bus/pet/petuja.cpp
+++ b/src/devices/bus/pet/petuja.cpp
@@ -26,18 +26,18 @@ DEFINE_DEVICE_TYPE(PET_USERPORT_JOYSTICK_ADAPTER, pet_userport_joystick_adapter_
static INPUT_PORTS_START( petuja )
PORT_START("JOY")
- PORT_BIT( 0x01, IP_ACTIVE_LOW, IPT_JOYSTICK_UP ) PORT_8WAY PORT_PLAYER(1) PORT_WRITE_LINE_DEVICE_MEMBER(DEVICE_SELF, pet_userport_joystick_adapter_device, write_up1)
- PORT_BIT( 0x02, IP_ACTIVE_LOW, IPT_JOYSTICK_DOWN ) PORT_8WAY PORT_PLAYER(1) PORT_WRITE_LINE_DEVICE_MEMBER(DEVICE_SELF, pet_userport_joystick_adapter_device, write_down1)
- PORT_BIT( 0x04, IP_ACTIVE_LOW, IPT_JOYSTICK_LEFT ) PORT_8WAY PORT_PLAYER(1) PORT_WRITE_LINE_DEVICE_MEMBER(DEVICE_SELF, device_pet_user_port_interface, output_e)
- PORT_BIT( 0x08, IP_ACTIVE_LOW, IPT_JOYSTICK_RIGHT ) PORT_8WAY PORT_PLAYER(1) PORT_WRITE_LINE_DEVICE_MEMBER(DEVICE_SELF, device_pet_user_port_interface, output_f)
- PORT_BIT( 0x10, IP_ACTIVE_LOW, IPT_JOYSTICK_UP ) PORT_8WAY PORT_PLAYER(2) PORT_WRITE_LINE_DEVICE_MEMBER(DEVICE_SELF, pet_userport_joystick_adapter_device, write_up2)
- PORT_BIT( 0x20, IP_ACTIVE_LOW, IPT_JOYSTICK_DOWN ) PORT_8WAY PORT_PLAYER(2) PORT_WRITE_LINE_DEVICE_MEMBER(DEVICE_SELF, pet_userport_joystick_adapter_device, write_down2)
- PORT_BIT( 0x40, IP_ACTIVE_LOW, IPT_JOYSTICK_LEFT ) PORT_8WAY PORT_PLAYER(2) PORT_WRITE_LINE_DEVICE_MEMBER(DEVICE_SELF, device_pet_user_port_interface, output_k)
- PORT_BIT( 0x80, IP_ACTIVE_LOW, IPT_JOYSTICK_RIGHT ) PORT_8WAY PORT_PLAYER(2) PORT_WRITE_LINE_DEVICE_MEMBER(DEVICE_SELF, device_pet_user_port_interface, output_l)
+ PORT_BIT( 0x01, IP_ACTIVE_LOW, IPT_JOYSTICK_UP ) PORT_8WAY PORT_PLAYER(1) PORT_WRITE_LINE_DEVICE_MEMBER(DEVICE_SELF, FUNC(pet_userport_joystick_adapter_device::write_up1))
+ PORT_BIT( 0x02, IP_ACTIVE_LOW, IPT_JOYSTICK_DOWN ) PORT_8WAY PORT_PLAYER(1) PORT_WRITE_LINE_DEVICE_MEMBER(DEVICE_SELF, FUNC(pet_userport_joystick_adapter_device::write_down1))
+ PORT_BIT( 0x04, IP_ACTIVE_LOW, IPT_JOYSTICK_LEFT ) PORT_8WAY PORT_PLAYER(1) PORT_WRITE_LINE_DEVICE_MEMBER(DEVICE_SELF, FUNC(device_pet_user_port_interface::output_e))
+ PORT_BIT( 0x08, IP_ACTIVE_LOW, IPT_JOYSTICK_RIGHT ) PORT_8WAY PORT_PLAYER(1) PORT_WRITE_LINE_DEVICE_MEMBER(DEVICE_SELF, FUNC(device_pet_user_port_interface::output_f))
+ PORT_BIT( 0x10, IP_ACTIVE_LOW, IPT_JOYSTICK_UP ) PORT_8WAY PORT_PLAYER(2) PORT_WRITE_LINE_DEVICE_MEMBER(DEVICE_SELF, FUNC(pet_userport_joystick_adapter_device::write_up2))
+ PORT_BIT( 0x20, IP_ACTIVE_LOW, IPT_JOYSTICK_DOWN ) PORT_8WAY PORT_PLAYER(2) PORT_WRITE_LINE_DEVICE_MEMBER(DEVICE_SELF, FUNC(pet_userport_joystick_adapter_device::write_down2))
+ PORT_BIT( 0x40, IP_ACTIVE_LOW, IPT_JOYSTICK_LEFT ) PORT_8WAY PORT_PLAYER(2) PORT_WRITE_LINE_DEVICE_MEMBER(DEVICE_SELF, FUNC(device_pet_user_port_interface::output_k))
+ PORT_BIT( 0x80, IP_ACTIVE_LOW, IPT_JOYSTICK_RIGHT ) PORT_8WAY PORT_PLAYER(2) PORT_WRITE_LINE_DEVICE_MEMBER(DEVICE_SELF, FUNC(device_pet_user_port_interface::output_l))
PORT_START("FIRE")
- PORT_BIT( 0x03, IP_ACTIVE_LOW, IPT_BUTTON1 ) PORT_PLAYER(1) PORT_WRITE_LINE_DEVICE_MEMBER(DEVICE_SELF, pet_userport_joystick_adapter_device, write_fire1)
- PORT_BIT( 0x30, IP_ACTIVE_LOW, IPT_BUTTON1 ) PORT_PLAYER(2) PORT_WRITE_LINE_DEVICE_MEMBER(DEVICE_SELF, pet_userport_joystick_adapter_device, write_fire2)
+ PORT_BIT( 0x03, IP_ACTIVE_LOW, IPT_BUTTON1 ) PORT_PLAYER(1) PORT_WRITE_LINE_DEVICE_MEMBER(DEVICE_SELF, FUNC(pet_userport_joystick_adapter_device::write_fire1))
+ PORT_BIT( 0x30, IP_ACTIVE_LOW, IPT_BUTTON1 ) PORT_PLAYER(2) PORT_WRITE_LINE_DEVICE_MEMBER(DEVICE_SELF, FUNC(pet_userport_joystick_adapter_device::write_fire2))
INPUT_PORTS_END
diff --git a/src/devices/bus/pet/petuja.h b/src/devices/bus/pet/petuja.h
index b268c0d1519..80003dee386 100644
--- a/src/devices/bus/pet/petuja.h
+++ b/src/devices/bus/pet/petuja.h
@@ -30,19 +30,19 @@ public:
pet_userport_joystick_adapter_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;
+ virtual ioport_constructor device_input_ports() const override ATTR_COLD;
// 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
- virtual void device_start() override;
+ virtual void device_start() override ATTR_COLD;
void update_port1();
void update_port2();
diff --git a/src/devices/bus/pet/superpet.cpp b/src/devices/bus/pet/superpet.cpp
index ab518bec49f..1b6bb9e80df 100644
--- a/src/devices/bus/pet/superpet.cpp
+++ b/src/devices/bus/pet/superpet.cpp
@@ -135,14 +135,14 @@ inline void superpet_device::update_cpu()
if (cpu)
{
// 6502 active
- m_maincpu->set_input_line(INPUT_LINE_HALT, ASSERT_LINE);
m_maincpu->set_input_line(INPUT_LINE_HALT, CLEAR_LINE);
+ m_maincpu->set_input_line(INPUT_LINE_HALT, ASSERT_LINE);
}
else
{
// 6809 active
- m_maincpu->set_input_line(INPUT_LINE_HALT, CLEAR_LINE);
m_maincpu->set_input_line(INPUT_LINE_HALT, ASSERT_LINE);
+ m_maincpu->set_input_line(INPUT_LINE_HALT, CLEAR_LINE);
}
}
@@ -173,7 +173,7 @@ superpet_device::superpet_device(const machine_config &mconfig, const char *tag,
m_acia(*this, MOS6551_TAG),
m_dongle(*this, MOS6702_TAG),
m_rom(*this, M6809_TAG),
- m_ram(*this, "ram"),
+ m_ram(*this, "ram", 0x10000, ENDIANNESS_LITTLE),
m_io_sw1(*this, "SW1"),
m_io_sw2(*this, "SW2"),
m_system(0),
@@ -191,9 +191,6 @@ superpet_device::superpet_device(const machine_config &mconfig, const char *tag,
void superpet_device::device_start()
{
- // allocate memory
- m_ram.allocate(0x10000);
-
// state saving
save_item(NAME(m_system));
save_item(NAME(m_bank));
@@ -400,7 +397,7 @@ void superpet_device::pet_irq_w(int state)
// read -
//-------------------------------------------------
-READ8_MEMBER( superpet_device::read )
+uint8_t superpet_device::read(offs_t offset)
{
return m_slot->dma_bd_r(offset);
}
@@ -410,7 +407,7 @@ READ8_MEMBER( superpet_device::read )
// write -
//-------------------------------------------------
-WRITE8_MEMBER( superpet_device::write )
+void superpet_device::write(offs_t offset, uint8_t data)
{
m_slot->dma_bd_w(offset, data);
}
@@ -420,7 +417,7 @@ WRITE8_MEMBER( superpet_device::write )
// 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 6a6dfde0889..2625d85f997 100644
--- a/src/devices/bus/pet/superpet.h
+++ b/src/devices/bus/pet/superpet.h
@@ -32,13 +32,13 @@ public:
protected:
// device-level overrides
- virtual void device_start() override;
- virtual void device_reset() override;
+ virtual void device_start() override ATTR_COLD;
+ virtual void device_reset() override ATTR_COLD;
// optional information 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 const tiny_rom_entry *device_rom_region() const override ATTR_COLD;
+ virtual void device_add_mconfig(machine_config &config) override ATTR_COLD;
+ virtual ioport_constructor device_input_ports() const override ATTR_COLD;
// device_pet_expansion_card_interface overrides
virtual int pet_norom_r(offs_t offset, int sel) override;
@@ -48,18 +48,18 @@ protected:
virtual void pet_irq_w(int state) override;
private:
- DECLARE_WRITE_LINE_MEMBER( acia_irq_w );
+ void acia_irq_w(int state);
- DECLARE_READ8_MEMBER( read );
- DECLARE_WRITE8_MEMBER( write );
+ uint8_t read(offs_t offset);
+ void write(offs_t offset, uint8_t data);
- void superpet_mem(address_map &map);
+ void superpet_mem(address_map &map) ATTR_COLD;
required_device<cpu_device> m_maincpu;
required_device<mos6551_device> m_acia;
required_device<mos6702_device> m_dongle;
required_memory_region m_rom;
- optional_shared_ptr<uint8_t> m_ram;
+ memory_share_creator<uint8_t> m_ram;
required_ioport m_io_sw1;
required_ioport m_io_sw2;
diff --git a/src/devices/bus/pet/user.cpp b/src/devices/bus/pet/user.cpp
index d0f889db0b6..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,31 +66,31 @@ 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
device_pet_user_port_interface::device_pet_user_port_interface(const machine_config &mconfig, device_t &device)
- : device_slot_card_interface(mconfig,device)
+ : device_interface(device, "petuser")
{
m_slot = dynamic_cast<pet_user_port_device *>(device.owner());
}
diff --git a/src/devices/bus/pet/user.h b/src/devices/bus/pet/user.h
index 51e5b6f3efe..99a2e76cf4f 100644
--- a/src/devices/bus/pet/user.h
+++ b/src/devices/bus/pet/user.h
@@ -31,8 +31,7 @@ DECLARE_DEVICE_TYPE(PET_USER_PORT, pet_user_port_device)
class device_pet_user_port_interface;
-class pet_user_port_device : public device_t,
- public device_slot_interface
+class pet_user_port_device : public device_t, public device_slot_interface
{
friend class device_pet_user_port_interface;
@@ -68,30 +67,30 @@ 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
virtual void device_config_complete() override;
- virtual void device_start() override;
+ virtual void device_start() override ATTR_COLD;
devcb_write_line m_2_handler;
devcb_write_line m_3_handler;
@@ -118,55 +117,55 @@ private:
};
-class device_pet_user_port_interface : public device_slot_card_interface
+class device_pet_user_port_interface : public device_interface
{
friend class pet_user_port_device;
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..ee8a5050c14
--- /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 ATTR_COLD;
+ virtual void device_reset() override ATTR_COLD;
+ const tiny_rom_entry *device_rom_region() const override;
+ virtual void device_add_mconfig(machine_config &config) override ATTR_COLD;
+
+private:
+ required_device<h83002_device> m_cpu;
+ required_device<dspv_device> m_dspv;
+
+ void map(address_map &map) ATTR_COLD;
+};
+
+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, 0);
+ m_dspv->add_route(1, DEVICE_SELF_OWNER, 1.0, 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..e4485c4929b
--- /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_PLG100_VL_H
+#define MAME_BUS_PLG1X0_PLG100_VL_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..c1455819fa7
--- /dev/null
+++ b/src/devices/bus/plg1x0/plg150-ap.cpp
@@ -0,0 +1,93 @@
+// 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 ATTR_COLD;
+ virtual void device_reset() override ATTR_COLD;
+ const tiny_rom_entry *device_rom_region() const override;
+ virtual void device_add_mconfig(machine_config &config) override ATTR_COLD;
+
+private:
+ required_device<swx00_device> m_cpu;
+
+ void map(address_map &map) ATTR_COLD;
+};
+
+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)
+{
+ logerror("%s rx=%d\n", machine().time().to_string(), 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..6316689193e
--- /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_PLG150_AP_H
+#define MAME_BUS_PLG1X0_PLG150_AP_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..1f0fec2fd51
--- /dev/null
+++ b/src/devices/bus/plg1x0/plg1x0.cpp
@@ -0,0 +1,50 @@
+// 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),
+ m_midi_tx(*this)
+{
+}
+
+void plg1x0_connector::device_start()
+{
+}
+
+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..b3af4bb075b
--- /dev/null
+++ b/src/devices/bus/plg1x0/plg1x0.h
@@ -0,0 +1,81 @@
+// 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:
+ devcb_write_line m_midi_tx;
+
+ virtual void device_start() override ATTR_COLD;
+};
+
+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 333dea55fb0..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"
+
//**************************************************************************
@@ -16,8 +19,6 @@
//**************************************************************************
#define M6510T_TAG "u2"
-#define M6523_0_TAG "u3"
-#define M6523_1_TAG "ci_u2"
#define C64H156_TAG "u6"
#define PLA_TAG "u1"
@@ -325,10 +326,11 @@ void c1551_device::c1551_mem(address_map &map)
// FLOPPY_FORMATS( floppy_formats )
//-------------------------------------------------
-FLOPPY_FORMATS_MEMBER( c1551_device::floppy_formats )
- FLOPPY_D64_FORMAT,
- FLOPPY_G64_FORMAT
-FLOPPY_FORMATS_END
+void c1551_device::floppy_formats(format_registration &fr)
+{
+ fr.add(FLOPPY_D64_FORMAT);
+ fr.add(FLOPPY_G64_FORMAT);
+}
//-------------------------------------------------
@@ -341,15 +343,14 @@ 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.m_perfect_cpu_quantum = subtag(M6510T_TAG);
PLS100(config, m_pla);
TPI6525(config, m_tpi0, 0);
m_tpi0->in_pa_cb().set(FUNC(c1551_device::tcbm_data_r));
m_tpi0->out_pa_cb().set(FUNC(c1551_device::tcbm_data_w));
- m_tpi0->in_pb_cb().set(C64H156_TAG, FUNC(c64h156_device::yb_r));
- m_tpi0->out_pb_cb().set(C64H156_TAG, FUNC(c64h156_device::yb_w));
+ m_tpi0->in_pb_cb().set(m_ga, FUNC(c64h156_device::yb_r));
+ m_tpi0->out_pb_cb().set(m_ga, FUNC(c64h156_device::yb_w));
m_tpi0->in_pc_cb().set(FUNC(c1551_device::tpi0_pc_r));
m_tpi0->out_pc_cb().set(FUNC(c1551_device::tpi0_pc_w));
@@ -361,7 +362,7 @@ void c1551_device::device_add_mconfig(machine_config &config)
m_tpi1->out_pc_cb().set(FUNC(c1551_device::tpi1_pc_w));
C64H156(config, m_ga, XTAL(16'000'000));
- m_ga->byte_callback().set(C64H156_TAG, FUNC(c64h156_device::atni_w));
+ m_ga->byte_callback().set(m_ga, FUNC(c64h156_device::atni_w));
floppy_connector &connector(FLOPPY_CONNECTOR(config, C64H156_TAG":0", 0));
connector.option_add("525ssqd", FLOPPY_525_SSQD);
@@ -369,7 +370,7 @@ void c1551_device::device_add_mconfig(machine_config &config)
connector.set_fixed(true);
connector.set_formats(c1551_device::floppy_formats);
- PLUS4_EXPANSION_SLOT(config, m_exp, 0);
+ PLUS4_EXPANSION_SLOT(config, m_exp, DERIVED_CLOCK(1, 1));
m_exp->irq_wr_callback().set(DEVICE_SELF_OWNER, FUNC(plus4_expansion_slot_device::irq_w));
m_exp->cd_rd_callback().set(DEVICE_SELF_OWNER, FUNC(plus4_expansion_slot_device::dma_cd_r));
m_exp->cd_wr_callback().set(DEVICE_SELF_OWNER, FUNC(plus4_expansion_slot_device::dma_cd_w));
@@ -413,12 +414,12 @@ c1551_device::c1551_device(const machine_config &mconfig, const char *tag, devic
: device_t(mconfig, C1551, tag, owner, clock)
, device_plus4_expansion_card_interface(mconfig, *this)
, m_maincpu(*this, M6510T_TAG)
- , m_tpi0(*this, M6523_0_TAG)
- , m_tpi1(*this, M6523_1_TAG)
+ , m_tpi0(*this, "u3")
+ , m_tpi1(*this, "ci_u2")
, m_ga(*this, C64H156_TAG)
, m_pla(*this, PLA_TAG)
, m_floppy(*this, C64H156_TAG":0:525ssqd")
- , m_exp(*this, PLUS4_EXPANSION_SLOT_TAG)
+ , m_exp(*this, "exp")
, m_jp1(*this, "JP1")
, m_leds(*this, "led%u", 0U)
, m_tcbm_data(0xff)
@@ -440,7 +441,7 @@ void c1551_device::device_start()
m_leds.resolve();
// allocate timers
- m_irq_timer = timer_alloc();
+ m_irq_timer = timer_alloc(FUNC(c1551_device::irq_timer_tick), this);
m_irq_timer->adjust(attotime::zero, CLEAR_LINE);
// install image callbacks
@@ -476,10 +477,10 @@ void c1551_device::device_reset()
//-------------------------------------------------
-// device_timer - handler timer events
+// irq_timer_tick - update IRQ line state
//-------------------------------------------------
-void c1551_device::device_timer(emu_timer &timer, device_timer_id id, int param, void *ptr)
+TIMER_CALLBACK_MEMBER(c1551_device::irq_timer_tick)
{
m_maincpu->set_input_line(M6502_IRQ_LINE, param);
diff --git a/src/devices/bus/plus4/c1551.h b/src/devices/bus/plus4/c1551.h
index 3fce289461c..3868fe1b7d5 100644
--- a/src/devices/bus/plus4/c1551.h
+++ b/src/devices/bus/plus4/c1551.h
@@ -34,19 +34,20 @@ public:
protected:
// device-level overrides
- virtual void device_start() override;
- virtual void device_reset() override;
- virtual void device_timer(emu_timer &timer, device_timer_id id, int param, void *ptr) override;
+ virtual void device_start() override ATTR_COLD;
+ virtual void device_reset() override ATTR_COLD;
// optional information 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 const tiny_rom_entry *device_rom_region() const override ATTR_COLD;
+ virtual void device_add_mconfig(machine_config &config) override ATTR_COLD;
+ virtual ioport_constructor device_input_ports() const override ATTR_COLD;
// device_plus4_expansion_card_interface overrides
virtual uint8_t plus4_cd_r(offs_t offset, uint8_t data, int ba, int cs0, int c1l, int c2l, int cs1, int c1h, int c2h) override;
virtual void plus4_cd_w(offs_t offset, uint8_t data, int ba, int cs0, int c1l, int c2l, int cs1, int c1h, int c2h) override;
+ TIMER_CALLBACK_MEMBER(irq_timer_tick);
+
private:
uint8_t port_r();
void port_w(uint8_t data);
@@ -63,9 +64,9 @@ private:
uint8_t tpi0_r(offs_t offset);
void tpi0_w(offs_t offset, uint8_t data);
- void c1551_mem(address_map &map);
+ void c1551_mem(address_map &map) ATTR_COLD;
- DECLARE_FLOPPY_FORMATS( floppy_formats );
+ static void floppy_formats(format_registration &fr);
enum
{
diff --git a/src/devices/bus/plus4/diag264_lb_user.h b/src/devices/bus/plus4/diag264_lb_user.h
index dd45e469106..e2f50055500 100644
--- a/src/devices/bus/plus4/diag264_lb_user.h
+++ b/src/devices/bus/plus4/diag264_lb_user.h
@@ -29,26 +29,26 @@ public:
protected:
// device-level overrides
- virtual void device_start() override;
+ virtual void device_start() override ATTR_COLD;
// 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 83e8ad4277a..b475875145c 100644
--- a/src/devices/bus/plus4/exp.cpp
+++ b/src/devices/bus/plus4/exp.cpp
@@ -36,15 +36,11 @@ DEFINE_DEVICE_TYPE(PLUS4_EXPANSION_SLOT, plus4_expansion_slot_device, "plus4_exp
//-------------------------------------------------
device_plus4_expansion_card_interface::device_plus4_expansion_card_interface(const machine_config &mconfig, device_t &device) :
- device_slot_card_interface(mconfig, device),
- m_c1l(*this, "c1l"),
- m_c1h(*this, "c1h"),
- m_c2l(*this, "c2l"),
- m_c2h(*this, "c2h"),
- m_c1l_mask(0),
- m_c1h_mask(0),
- m_c2l_mask(0),
- m_c2h_mask(0)
+ device_interface(device, "plus4exp"),
+ m_c1l_size(0),
+ m_c1h_size(0),
+ m_c2l_size(0),
+ m_c2h_size(0)
{
m_slot = dynamic_cast<plus4_expansion_slot_device *>(device.owner());
}
@@ -70,61 +66,24 @@ device_plus4_expansion_card_interface::~device_plus4_expansion_card_interface()
plus4_expansion_slot_device::plus4_expansion_slot_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) :
device_t(mconfig, PLUS4_EXPANSION_SLOT, tag, owner, clock),
- device_slot_interface(mconfig, *this),
- device_image_interface(mconfig, *this),
+ 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)
+ m_write_aec(*this),
+ m_card(nullptr)
{
}
//-------------------------------------------------
-// device_validity_check -
-//-------------------------------------------------
-
-void plus4_expansion_slot_device::device_validity_check(validity_checker &valid) const
-{
- device_t *const carddev = get_card_device();
- if (carddev && !dynamic_cast<device_plus4_expansion_card_interface *>(carddev))
- osd_printf_error("Card device %s (%s) does not implement device_plus4_expansion_card_interface\n", carddev->tag(), carddev->name());
-}
-
-
-//-------------------------------------------------
// device_start - device-specific startup
//-------------------------------------------------
void plus4_expansion_slot_device::device_start()
{
- device_t *const carddev = get_card_device();
- m_card = dynamic_cast<device_plus4_expansion_card_interface *>(carddev);
- if (carddev && !m_card)
- fatalerror("Card device %s (%s) does not implement device_plus4_expansion_card_interface\n", carddev->tag(), carddev->name());
-
- // 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();
-
- // inherit bus clock
- if (clock() == 0)
- {
- plus4_expansion_slot_device *root = machine().device<plus4_expansion_slot_device>(PLUS4_EXPANSION_SLOT_TAG);
- assert(root);
- set_unscaled_clock(root->clock());
- }
-}
-
-
-//-------------------------------------------------
-// device_reset - device-specific reset
-//-------------------------------------------------
-
-void plus4_expansion_slot_device::device_reset()
-{
+ m_card = get_card_device();
}
@@ -132,13 +91,14 @@ void plus4_expansion_slot_device::device_reset()
// 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
{
@@ -146,10 +106,17 @@ image_init_result plus4_expansion_slot_device::call_load()
load_software_region("c1h", m_card->m_c1h);
load_software_region("c2l", m_card->m_c2l);
load_software_region("c2h", m_card->m_c2h);
+ m_card->m_c1l_size = get_software_region_length("c1l");
+ m_card->m_c1h_size = get_software_region_length("c1h");
+ m_card->m_c2l_size = get_software_region_length("c2l");
+ 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)))
+ 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 9f625442d99..951031c9796 100644
--- a/src/devices/bus/plus4/exp.h
+++ b/src/devices/bus/plus4/exp.h
@@ -39,14 +39,7 @@
#pragma once
-#include "softlist_dev.h"
-
-
-//**************************************************************************
-// CONSTANTS
-//**************************************************************************
-
-#define PLUS4_EXPANSION_SLOT_TAG "exp"
+#include "imagedev/cartrom.h"
//**************************************************************************
@@ -58,8 +51,8 @@
class device_plus4_expansion_card_interface;
class plus4_expansion_slot_device : public device_t,
- public device_slot_interface,
- public device_image_interface
+ public device_single_card_slot_interface<device_plus4_expansion_card_interface>,
+ public device_cartrom_image_interface
{
public:
// construction/destruction
@@ -86,31 +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
- virtual void device_validity_check(validity_checker &valid) const override;
- virtual void device_start() override;
- virtual void device_reset() override;
-
- // image-level overrides
- virtual image_init_result call_load() override;
- virtual const software_list_loader &get_software_list_loader() const override { return rom_software_list_loader::instance(); }
-
- virtual iodevice_t image_type() const override { return IO_CARTSLOT; }
-
- virtual bool is_readable() const override { return 1; }
- virtual bool is_writeable() const override { return 0; }
- virtual bool is_creatable() const override { return 0; }
- virtual bool must_be_loaded() const override { return 0; }
- virtual bool is_reset_on_load() const override { return 1; }
- virtual const char *image_interface() const override { return "plus4_cart"; }
- virtual const char *file_extensions() const override { return "rom,bin"; }
-
- // slot interface overrides
+ // device_t implementation
+ virtual void device_start() override ATTR_COLD;
+
+ // 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"; }
+
+ // 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 +108,7 @@ protected:
// ======================> device_plus4_expansion_card_interface
-class device_plus4_expansion_card_interface : public device_slot_card_interface
+class device_plus4_expansion_card_interface : public device_interface
{
friend class plus4_expansion_slot_device;
@@ -139,15 +123,15 @@ public:
protected:
device_plus4_expansion_card_interface(const machine_config &mconfig, device_t &device);
- optional_shared_ptr<uint8_t> m_c1l;
- optional_shared_ptr<uint8_t> m_c1h;
- optional_shared_ptr<uint8_t> m_c2l;
- optional_shared_ptr<uint8_t> m_c2h;
+ std::unique_ptr<uint8_t[]> m_c1l;
+ std::unique_ptr<uint8_t[]> m_c1h;
+ std::unique_ptr<uint8_t[]> m_c2l;
+ std::unique_ptr<uint8_t[]> m_c2h;
- size_t m_c1l_mask;
- size_t m_c1h_mask;
- size_t m_c2l_mask;
- size_t m_c2h_mask;
+ size_t m_c1l_size;
+ size_t m_c1h_size;
+ size_t m_c2l_size;
+ size_t m_c2h_size;
plus4_expansion_slot_device *m_slot;
};
diff --git a/src/devices/bus/plus4/sid.cpp b/src/devices/bus/plus4/sid.cpp
index 1ebfdafd657..b5c6e9d897f 100644
--- a/src/devices/bus/plus4/sid.cpp
+++ b/src/devices/bus/plus4/sid.cpp
@@ -122,7 +122,7 @@ uint8_t plus4_sid_cartridge_device::plus4_cd_r(offs_t offset, uint8_t data, int
}
else if (offset >= 0xfd80 && offset < 0xfd90)
{
- data = m_joy->joy_r(machine().dummy_space(), 0);
+ data = m_joy->read_joy();
}
return data;
diff --git a/src/devices/bus/plus4/sid.h b/src/devices/bus/plus4/sid.h
index 1566381e6d2..1e91e046934 100644
--- a/src/devices/bus/plus4/sid.h
+++ b/src/devices/bus/plus4/sid.h
@@ -32,12 +32,12 @@ public:
protected:
// device-level overrides
- virtual void device_start() override;
- virtual void device_reset() override;
+ virtual void device_start() override ATTR_COLD;
+ virtual void device_reset() override ATTR_COLD;
// optional information overrides
- virtual const tiny_rom_entry *device_rom_region() const override;
- virtual void device_add_mconfig(machine_config &config) override;
+ virtual const tiny_rom_entry *device_rom_region() const override ATTR_COLD;
+ virtual void device_add_mconfig(machine_config &config) override ATTR_COLD;
// device_plus4_expansion_card_interface overrides
virtual uint8_t plus4_cd_r(offs_t offset, uint8_t data, int ba, int cs0, int c1l, int c2l, int cs1, int c1h, int c2h) override;
diff --git a/src/devices/bus/plus4/std.cpp b/src/devices/bus/plus4/std.cpp
index c8efe4b679f..ed9e9ff83a5 100644
--- a/src/devices/bus/plus4/std.cpp
+++ b/src/devices/bus/plus4/std.cpp
@@ -49,21 +49,21 @@ void plus4_standard_cartridge_device::device_start()
uint8_t plus4_standard_cartridge_device::plus4_cd_r(offs_t offset, uint8_t data, int ba, int cs0, int c1l, int c2l, int cs1, int c1h, int c2h)
{
- if (!c1l && m_c1l.bytes())
+ if (!c1l && m_c1l)
{
- data = m_c1l[offset & m_c1l.mask()];
+ data = m_c1l[offset & (m_c1l_size - 1)];
}
- else if (!c1h && m_c1h.bytes())
+ else if (!c1h && m_c1h)
{
- data = m_c1h[offset & m_c1h.mask()];
+ data = m_c1h[offset & (m_c1h_size - 1)];
}
- else if (!c2l && m_c2l.bytes())
+ else if (!c2l && m_c2l)
{
- data = m_c2l[offset & m_c2l.mask()];
+ data = m_c2l[offset & (m_c2l_size - 1)];
}
- else if (!c2h && m_c2h.bytes())
+ else if (!c2h && m_c2h)
{
- data = m_c2h[offset & m_c2h.mask()];
+ data = m_c2h[offset & (m_c2h_size - 1)];
}
return data;
diff --git a/src/devices/bus/plus4/std.h b/src/devices/bus/plus4/std.h
index f1f3ae75328..a3379305f71 100644
--- a/src/devices/bus/plus4/std.h
+++ b/src/devices/bus/plus4/std.h
@@ -30,7 +30,7 @@ public:
protected:
// device-level overrides
- virtual void device_start() override;
+ virtual void device_start() override ATTR_COLD;
// device_plus4_expansion_card_interface overrides
virtual uint8_t plus4_cd_r(offs_t offset, uint8_t data, int ba, int cs0, int c1l, int c2l, int cs1, int c1h, int c2h) override;
diff --git a/src/devices/bus/pofo/ccm.cpp b/src/devices/bus/pofo/ccm.cpp
index 9562ddfecd6..d2b60021f1d 100644
--- a/src/devices/bus/pofo/ccm.cpp
+++ b/src/devices/bus/pofo/ccm.cpp
@@ -9,6 +9,10 @@
#include "emu.h"
#include "ccm.h"
+#include "softlist_dev.h"
+
+#include <tuple>
+
//**************************************************************************
@@ -28,9 +32,7 @@ DEFINE_DEVICE_TYPE(PORTFOLIO_MEMORY_CARD_SLOT, portfolio_memory_card_slot_device
//-------------------------------------------------
device_portfolio_memory_card_slot_interface::device_portfolio_memory_card_slot_interface(const machine_config &mconfig, device_t &device) :
- device_slot_card_interface(mconfig, device),
- m_rom(*this, "rom"),
- m_nvram(*this, "nvram")
+ device_interface(device, "pofoccm")
{
m_slot = dynamic_cast<portfolio_memory_card_slot_device *>(device.owner());
}
@@ -47,8 +49,8 @@ device_portfolio_memory_card_slot_interface::device_portfolio_memory_card_slot_i
portfolio_memory_card_slot_device::portfolio_memory_card_slot_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) :
device_t(mconfig, PORTFOLIO_MEMORY_CARD_SLOT, tag, owner, clock),
- device_slot_interface(mconfig, *this),
- device_image_interface(mconfig, *this),
+ device_single_card_slot_interface<device_portfolio_memory_card_slot_interface>(mconfig, *this),
+ device_memcard_image_interface(mconfig, *this),
m_card(nullptr)
{
}
@@ -60,7 +62,7 @@ portfolio_memory_card_slot_device::portfolio_memory_card_slot_device(const machi
void portfolio_memory_card_slot_device::device_start()
{
- m_card = dynamic_cast<device_portfolio_memory_card_slot_interface *>(get_card_device());
+ m_card = get_card_device();
}
@@ -68,13 +70,19 @@ 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
{
@@ -82,7 +90,17 @@ image_init_result portfolio_memory_card_slot_device::call_load()
}
}
- return image_init_result::PASS;
+ return std::make_pair(err, std::string());
+}
+
+
+//-------------------------------------------------
+// get_software_list_loader -
+//-------------------------------------------------
+
+const software_list_loader &portfolio_memory_card_slot_device::get_software_list_loader() const
+{
+ return rom_software_list_loader::instance();
}
diff --git a/src/devices/bus/pofo/ccm.h b/src/devices/bus/pofo/ccm.h
index 42bfcb4356d..df889bd4bab 100644
--- a/src/devices/bus/pofo/ccm.h
+++ b/src/devices/bus/pofo/ccm.h
@@ -48,7 +48,7 @@
#pragma once
-#include "softlist_dev.h"
+#include "imagedev/memcard.h"
@@ -68,7 +68,7 @@
class portfolio_memory_card_slot_device;
-class device_portfolio_memory_card_slot_interface : public device_slot_card_interface
+class device_portfolio_memory_card_slot_interface : public device_interface
{
friend class portfolio_memory_card_slot_device;
@@ -82,8 +82,7 @@ protected:
// construction/destruction
device_portfolio_memory_card_slot_interface(const machine_config &mconfig, device_t &device);
- optional_shared_ptr<uint8_t> m_rom;
- optional_shared_ptr<uint8_t> m_nvram;
+ std::unique_ptr<uint8_t[]> m_rom;
portfolio_memory_card_slot_device *m_slot;
};
@@ -92,8 +91,8 @@ protected:
// ======================> portfolio_memory_card_slot_device
class portfolio_memory_card_slot_device : public device_t,
- public device_slot_interface,
- public device_image_interface
+ public device_single_card_slot_interface<device_portfolio_memory_card_slot_interface>,
+ public device_memcard_image_interface
{
public:
// construction/destruction
@@ -116,24 +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
- virtual void device_start() override;
+ // device_t implementation
+ virtual void device_start() override ATTR_COLD;
- // image-level overrides
- virtual image_init_result call_load() override;
- virtual const software_list_loader &get_software_list_loader() const override { return rom_software_list_loader::instance(); }
+ // 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 iodevice_t image_type() const override { return IO_CARTSLOT; }
+ 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"; }
- virtual bool is_readable() const override { return 1; }
- virtual bool is_writeable() const override { return 1; }
- virtual bool is_creatable() const override { return 1; }
- virtual bool must_be_loaded() const override { return 0; }
- virtual bool is_reset_on_load() const override { return 1; }
- virtual const char *image_interface() const override { return "pofo_card"; }
- virtual const char *file_extensions() const 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 f8a892fbe6c..d97b229624a 100644
--- a/src/devices/bus/pofo/exp.cpp
+++ b/src/devices/bus/pofo/exp.cpp
@@ -28,14 +28,14 @@ DEFINE_DEVICE_TYPE(PORTFOLIO_EXPANSION_SLOT, portfolio_expansion_slot_device, "p
//-------------------------------------------------
device_portfolio_expansion_slot_interface::device_portfolio_expansion_slot_interface(const machine_config &mconfig, device_t &device) :
- device_slot_card_interface(mconfig,device)
+ device_interface(device, "pofoexp")
{
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); }
@@ -49,7 +49,7 @@ WRITE_LINE_MEMBER( device_portfolio_expansion_slot_interface::wake_w ) { m_slot-
portfolio_expansion_slot_device::portfolio_expansion_slot_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) :
device_t(mconfig, PORTFOLIO_EXPANSION_SLOT, tag, owner, clock),
- device_slot_interface(mconfig, *this),
+ device_single_card_slot_interface<device_portfolio_expansion_slot_interface>(mconfig, *this),
m_write_eint(*this),
m_write_nmio(*this),
m_write_wake(*this),
@@ -64,12 +64,7 @@ portfolio_expansion_slot_device::portfolio_expansion_slot_device(const machine_c
void portfolio_expansion_slot_device::device_start()
{
- m_card = dynamic_cast<device_portfolio_expansion_slot_interface *>(get_card_device());
-
- // resolve callbacks
- m_write_eint.resolve_safe();
- m_write_nmio.resolve_safe();
- m_write_wake.resolve_safe();
+ m_card = get_card_device();
}
diff --git a/src/devices/bus/pofo/exp.h b/src/devices/bus/pofo/exp.h
index 2206d5af2fe..9dd1dbe9ffa 100644
--- a/src/devices/bus/pofo/exp.h
+++ b/src/devices/bus/pofo/exp.h
@@ -48,13 +48,6 @@
//**************************************************************************
-// CONSTANTS
-//**************************************************************************
-
-#define PORTFOLIO_EXPANSION_SLOT_TAG "exp"
-
-
-//**************************************************************************
// TYPE DEFINITIONS
//**************************************************************************
@@ -62,7 +55,7 @@
class portfolio_expansion_slot_device;
-class device_portfolio_expansion_slot_interface : public device_slot_card_interface
+class device_portfolio_expansion_slot_interface : public device_interface
{
public:
virtual bool nmd1() { return 1; }
@@ -75,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
@@ -91,7 +84,7 @@ protected:
// ======================> portfolio_expansion_slot_device
-class portfolio_expansion_slot_device : public device_t, public device_slot_interface
+class portfolio_expansion_slot_device : public device_t, public device_single_card_slot_interface<device_portfolio_expansion_slot_interface>
{
public:
// construction/destruction
@@ -116,23 +109,23 @@ public:
bool pdet_r() { return (m_card != nullptr) ? m_card->pdet() : 0; }
bool cdet_r() { return (m_card != nullptr) ? m_card->cdet() : 1; }
- uint8_t iack_r() { return (m_card != nullptr) ? m_card->iack_r() : 0xff; };
- uint8_t eack_r() { return (m_card != nullptr) ? m_card->eack_r() : 0xff; };
+ uint8_t iack_r() { return (m_card != nullptr) ? m_card->iack_r() : 0xff; }
+ uint8_t eack_r() { return (m_card != nullptr) ? m_card->eack_r() : 0xff; }
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
- virtual void device_start() override;
- virtual void device_reset() override;
+ virtual void device_start() override ATTR_COLD;
+ virtual void device_reset() override ATTR_COLD;
devcb_write_line m_write_eint;
devcb_write_line m_write_nmio;
diff --git a/src/devices/bus/pofo/hpc101.cpp b/src/devices/bus/pofo/hpc101.cpp
index d62f1002f7d..692c42ae7fc 100644
--- a/src/devices/bus/pofo/hpc101.cpp
+++ b/src/devices/bus/pofo/hpc101.cpp
@@ -36,9 +36,9 @@ DEFINE_DEVICE_TYPE(POFO_HPC101, pofo_hpc101_device, "pofo_hpc101", "Atari Portfo
void pofo_hpc101_device::device_add_mconfig(machine_config &config)
{
I8255A(config, m_ppi);
- m_ppi->out_pa_callback().set("cent_data_out", FUNC(output_latch_device::bus_w));
- m_ppi->out_pb_callback().set("cent_ctrl_out", FUNC(output_latch_device::bus_w));
- m_ppi->in_pc_callback().set("cent_status_in", FUNC(input_buffer_device::bus_r));
+ m_ppi->out_pa_callback().set("cent_data_out", FUNC(output_latch_device::write));
+ m_ppi->out_pb_callback().set("cent_ctrl_out", FUNC(output_latch_device::write));
+ m_ppi->in_pc_callback().set("cent_status_in", FUNC(input_buffer_device::read));
centronics_device &centronics(CENTRONICS(config, CENTRONICS_TAG, centronics_devices, "printer"));
centronics.ack_handler().set("cent_status_in", FUNC(input_buffer_device::write_bit5));
diff --git a/src/devices/bus/pofo/hpc101.h b/src/devices/bus/pofo/hpc101.h
index fa18b5d6d4d..22832457173 100644
--- a/src/devices/bus/pofo/hpc101.h
+++ b/src/devices/bus/pofo/hpc101.h
@@ -31,11 +31,11 @@ public:
protected:
// device-level overrides
- virtual void device_start() override;
- virtual void device_reset() override;
+ virtual void device_start() override ATTR_COLD;
+ virtual void device_reset() override ATTR_COLD;
// optional information overrides
- virtual void device_add_mconfig(machine_config &config) override;
+ virtual void device_add_mconfig(machine_config &config) override ATTR_COLD;
// device_portfolio_expansion_slot_interface overrides
bool pdet() override { return 1; }
diff --git a/src/devices/bus/pofo/hpc102.h b/src/devices/bus/pofo/hpc102.h
index c7168b12787..a05664eed3c 100644
--- a/src/devices/bus/pofo/hpc102.h
+++ b/src/devices/bus/pofo/hpc102.h
@@ -31,11 +31,11 @@ public:
protected:
// device-level overrides
- virtual void device_start() override;
- virtual void device_reset() override;
+ virtual void device_start() override ATTR_COLD;
+ virtual void device_reset() override ATTR_COLD;
// optional information overrides
- virtual void device_add_mconfig(machine_config &config) override;
+ virtual void device_add_mconfig(machine_config &config) override ATTR_COLD;
// device_portfolio_expansion_slot_interface overrides
bool pdet() override { return 1; }
diff --git a/src/devices/bus/pofo/hpc104.cpp b/src/devices/bus/pofo/hpc104.cpp
index a6e66f13da8..01dd6beb7c2 100644
--- a/src/devices/bus/pofo/hpc104.cpp
+++ b/src/devices/bus/pofo/hpc104.cpp
@@ -100,8 +100,8 @@ pofo_hpc104_device::pofo_hpc104_device(const machine_config &mconfig, device_typ
device_portfolio_expansion_slot_interface(mconfig, *this),
device_nvram_interface(mconfig, *this),
m_ccm(*this, PORTFOLIO_MEMORY_CARD_SLOT_B_TAG),
- m_exp(*this, PORTFOLIO_EXPANSION_SLOT_TAG),
- m_nvram(*this, "nvram"),
+ m_exp(*this, "exp"),
+ m_nvram(*this, "nvram", 0x40000, ENDIANNESS_LITTLE),
m_io_sw1(*this, "SW1")
{
}
@@ -128,8 +128,6 @@ pofo_hpc104_2_device::pofo_hpc104_2_device(const machine_config &mconfig, const
void pofo_hpc104_device::device_start()
{
- // allocate memory
- m_nvram.allocate(0x40000);
}
@@ -143,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
//-------------------------------------------------
@@ -171,7 +188,7 @@ uint8_t pofo_hpc104_device::nrdi_r(offs_t offset, uint8_t data, bool iom, bool b
{
if (offset >= 0x1f000 && offset < 0x5f000)
{
- data = m_nvram[offset - 0x1f000] = data;
+ data = m_nvram[offset - 0x1f000];
}
}
}
diff --git a/src/devices/bus/pofo/hpc104.h b/src/devices/bus/pofo/hpc104.h
index 042bece210e..9dded68f9e1 100644
--- a/src/devices/bus/pofo/hpc104.h
+++ b/src/devices/bus/pofo/hpc104.h
@@ -13,7 +13,6 @@
#include "exp.h"
#include "bus/pofo/ccm.h"
-#include "machine/nvram.h"
@@ -34,31 +33,29 @@ 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;
+ // device_t implementation
+ virtual void device_add_mconfig(machine_config &config) override ATTR_COLD;
+ virtual ioport_constructor device_input_ports() const override ATTR_COLD;
+ virtual void device_start() override ATTR_COLD;
+ virtual void device_reset() override ATTR_COLD;
- // optional information overrides
- virtual void device_add_mconfig(machine_config &config) override;
- virtual ioport_constructor device_input_ports() const override;
-
- // device_nvram_interface overrides
- virtual void nvram_default() override { }
- virtual void nvram_read(emu_file &file) override { if (m_nvram != nullptr) { file.read(m_nvram, m_nvram.bytes()); } }
- virtual void nvram_write(emu_file &file) override { if (m_nvram != nullptr) { file.write(m_nvram, 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_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;
required_device<portfolio_expansion_slot_device> m_exp;
- optional_shared_ptr<uint8_t> m_nvram;
+ memory_share_creator<uint8_t> m_nvram;
required_ioport m_io_sw1;
bool m_sw1;
@@ -75,7 +72,7 @@ public:
pofo_hpc104_2_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;
+ virtual ioport_constructor device_input_ports() const override ATTR_COLD;
};
diff --git a/src/devices/bus/pofo/ram.cpp b/src/devices/bus/pofo/ram.cpp
index 5498a9b8c32..253b30d228b 100644
--- a/src/devices/bus/pofo/ram.cpp
+++ b/src/devices/bus/pofo/ram.cpp
@@ -29,7 +29,8 @@ DEFINE_DEVICE_TYPE(PORTFOLIO_RAM_CARD, portfolio_ram_card_device, "portfolio_ram
portfolio_ram_card_device::portfolio_ram_card_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) :
device_t(mconfig, PORTFOLIO_RAM_CARD, tag, owner, clock),
device_portfolio_memory_card_slot_interface(mconfig, *this),
- device_nvram_interface(mconfig, *this)
+ device_nvram_interface(mconfig, *this),
+ m_nvram(*this, "nvram", 0x20000, ENDIANNESS_LITTLE)
{
}
@@ -40,7 +41,25 @@ portfolio_ram_card_device::portfolio_ram_card_device(const machine_config &mconf
void portfolio_ram_card_device::device_start()
{
- m_nvram.allocate(0x20000);
+}
+
+
+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;
}
diff --git a/src/devices/bus/pofo/ram.h b/src/devices/bus/pofo/ram.h
index 2c19f807816..edd7326dff0 100644
--- a/src/devices/bus/pofo/ram.h
+++ b/src/devices/bus/pofo/ram.h
@@ -12,7 +12,6 @@
#pragma once
#include "ccm.h"
-#include "machine/nvram.h"
@@ -31,19 +30,21 @@ public:
portfolio_ram_card_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
protected:
- // device-level overrides
- virtual void device_start() override;
+ // device_t implementation
+ virtual void device_start() override ATTR_COLD;
- // device_nvram_interface overrides
- virtual void nvram_default() override { }
- virtual void nvram_read(emu_file &file) override { if (m_nvram != nullptr) { file.read(m_nvram, m_nvram.bytes()); } }
- virtual void nvram_write(emu_file &file) override { if (m_nvram != nullptr) { file.write(m_nvram, 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;
virtual void nwri_w(offs_t offset, uint8_t data) override;
+
+ memory_share_creator<uint8_t> m_nvram;
};
diff --git a/src/devices/bus/pofo/rom.cpp b/src/devices/bus/pofo/rom.cpp
index ac336eb0b77..2e49c3df8dd 100644
--- a/src/devices/bus/pofo/rom.cpp
+++ b/src/devices/bus/pofo/rom.cpp
@@ -48,5 +48,5 @@ void portfolio_rom_card_device::device_start()
uint8_t portfolio_rom_card_device::nrdi_r(offs_t offset)
{
- return m_rom[offset];
+ return (m_rom) ? m_rom[offset] : 0xff;
}
diff --git a/src/devices/bus/pofo/rom.h b/src/devices/bus/pofo/rom.h
index 6df19402a36..8be5e4e882c 100644
--- a/src/devices/bus/pofo/rom.h
+++ b/src/devices/bus/pofo/rom.h
@@ -30,7 +30,7 @@ public:
protected:
// device-level overrides
- virtual void device_start() override;
+ virtual void device_start() override ATTR_COLD;
// device_portfolio_memory_card_slot_interface overrides
virtual bool cdet() override { return 0; }
diff --git a/src/devices/bus/psi_kbd/ergoline.h b/src/devices/bus/psi_kbd/ergoline.h
index 3b3329d45cb..4a94376167e 100644
--- a/src/devices/bus/psi_kbd/ergoline.h
+++ b/src/devices/bus/psi_kbd/ergoline.h
@@ -32,18 +32,18 @@ public:
protected:
// device_t overrides
- 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;
+ virtual const tiny_rom_entry *device_rom_region() const override ATTR_COLD;
+ virtual ioport_constructor device_input_ports() const override ATTR_COLD;
+ 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;
// from host
virtual void tx_w(int state) override;
private:
- void kbd_io(address_map &map);
- void kbd_mem(address_map &map);
+ void kbd_io(address_map &map) ATTR_COLD;
+ void kbd_mem(address_map &map) ATTR_COLD;
};
diff --git a/src/devices/bus/psi_kbd/hle.cpp b/src/devices/bus/psi_kbd/hle.cpp
index 84adfc5ff82..c041f5fae07 100644
--- a/src/devices/bus/psi_kbd/hle.cpp
+++ b/src/devices/bus/psi_kbd/hle.cpp
@@ -98,7 +98,7 @@ static INPUT_PORTS_START( keyboard )
PORT_BIT(0x0001, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CODE(KEYCODE_ESC) PORT_NAME("ESC/STOP") PORT_CHAR(UCHAR_MAMEKEY(ESC))
PORT_BIT(0x0002, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CODE(KEYCODE_1) PORT_CHAR('1') PORT_CHAR('!')
PORT_BIT(0x0004, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CODE(KEYCODE_2) PORT_CHAR('2') PORT_CHAR('"')
- PORT_BIT(0x0008, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CODE(KEYCODE_3) PORT_CHAR('3') PORT_CHAR(0xa7) // §
+ PORT_BIT(0x0008, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CODE(KEYCODE_3) PORT_CHAR('3') PORT_CHAR(U'§')
PORT_BIT(0x0010, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CODE(KEYCODE_4) PORT_CHAR('4') PORT_CHAR('$')
PORT_BIT(0x0020, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CODE(KEYCODE_5) PORT_CHAR('5') PORT_CHAR('%')
PORT_BIT(0x0040, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CODE(KEYCODE_6) PORT_CHAR('6') PORT_CHAR('&')
@@ -106,8 +106,8 @@ static INPUT_PORTS_START( keyboard )
PORT_BIT(0x0100, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CODE(KEYCODE_8) PORT_CHAR('8') PORT_CHAR('(')
PORT_BIT(0x0200, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CODE(KEYCODE_9) PORT_CHAR('9') PORT_CHAR(')')
PORT_BIT(0x0400, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CODE(KEYCODE_0) PORT_CHAR('0') PORT_CHAR('=')
- PORT_BIT(0x0800, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CODE(KEYCODE_MINUS) PORT_CHAR(0xdf) PORT_CHAR('?') // ß
- PORT_BIT(0x1000, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CODE(KEYCODE_EQUALS) PORT_CHAR(0xb4) PORT_CHAR('`')
+ PORT_BIT(0x0800, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CODE(KEYCODE_MINUS) PORT_CHAR(U'ß') PORT_CHAR('?')
+ PORT_BIT(0x1000, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CODE(KEYCODE_EQUALS) PORT_CHAR(U'´') PORT_CHAR('`')
PORT_BIT(0x2000, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CODE(KEYCODE_TILDE) PORT_CHAR('|') PORT_CHAR('^')
PORT_BIT(0x4000, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CODE(KEYCODE_BACKSPACE) PORT_NAME("RUB OUT") PORT_CHAR(0x08)
PORT_BIT(0x8000, IP_ACTIVE_HIGH, IPT_UNUSED)
@@ -124,7 +124,7 @@ static INPUT_PORTS_START( keyboard )
PORT_BIT(0x0100, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CODE(KEYCODE_I) PORT_CHAR('i') PORT_CHAR('I')
PORT_BIT(0x0200, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CODE(KEYCODE_O) PORT_CHAR('o') PORT_CHAR('O')
PORT_BIT(0x0400, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CODE(KEYCODE_P) PORT_CHAR('p') PORT_CHAR('P')
- PORT_BIT(0x0800, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CODE(KEYCODE_OPENBRACE) PORT_CHAR(0xfc) PORT_CHAR(0xdc) // ü Ü
+ PORT_BIT(0x0800, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CODE(KEYCODE_OPENBRACE) PORT_CHAR(U'ü') PORT_CHAR(U'Ü')
PORT_BIT(0x1000, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CODE(KEYCODE_CLOSEBRACE) PORT_CHAR('+') PORT_CHAR('*')
PORT_BIT(0x2000, IP_ACTIVE_HIGH, IPT_UNUSED) // LF, same code as cursor down
PORT_BIT(0x4000, IP_ACTIVE_HIGH, IPT_UNUSED)
@@ -142,8 +142,8 @@ static INPUT_PORTS_START( keyboard )
PORT_BIT(0x0100, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CODE(KEYCODE_J) PORT_CHAR('j') PORT_CHAR('J')
PORT_BIT(0x0200, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CODE(KEYCODE_K) PORT_CHAR('k') PORT_CHAR('K')
PORT_BIT(0x0400, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CODE(KEYCODE_L) PORT_CHAR('l') PORT_CHAR('L')
- PORT_BIT(0x0800, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CODE(KEYCODE_COLON) PORT_CHAR(0xf6) PORT_CHAR(0xd6) // ö Ö
- PORT_BIT(0x1000, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CODE(KEYCODE_QUOTE) PORT_CHAR(0xe4) PORT_CHAR(0xc4) // ä Ä
+ PORT_BIT(0x0800, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CODE(KEYCODE_COLON) PORT_CHAR(U'ö') PORT_CHAR(U'Ö')
+ PORT_BIT(0x1000, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CODE(KEYCODE_QUOTE) PORT_CHAR(U'ä') PORT_CHAR(U'Ä')
PORT_BIT(0x2000, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CODE(KEYCODE_BACKSLASH) PORT_CHAR('#') PORT_CHAR('\'')
PORT_BIT(0x4000, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CODE(KEYCODE_ENTER) PORT_NAME("CR") PORT_CHAR(0x0d)
PORT_BIT(0x8000, IP_ACTIVE_HIGH, IPT_UNUSED)
@@ -175,7 +175,7 @@ static INPUT_PORTS_START( keyboard )
PORT_BIT(0x0020, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CODE(KEYCODE_ASTERISK) PORT_NAME("] }") PORT_CHAR(']') PORT_CHAR('}')
PORT_BIT(0x0040, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CODE(KEYCODE_MINUS_PAD) PORT_NAME("\\ |") PORT_CHAR('\\') PORT_CHAR('|')
PORT_BIT(0x0080, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CODE(KEYCODE_DEL) PORT_NAME("DEL CHAR") PORT_CHAR(UCHAR_MAMEKEY(DEL))
- PORT_BIT(0x0100, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CODE(KEYCODE_END) PORT_NAME("ER \xe2\x87\xa5") // ER ⇥
+ PORT_BIT(0x0100, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CODE(KEYCODE_END) PORT_NAME(u8"ER \u21e5") // ER ⇥
PORT_BIT(0x0200, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CODE(KEYCODE_PLUS_PAD) PORT_NAME("ER PAGE")
PORT_BIT(0x0400, IP_ACTIVE_HIGH, IPT_UNUSED)
PORT_BIT(0x0800, IP_ACTIVE_HIGH, IPT_UNUSED)
@@ -185,18 +185,18 @@ static INPUT_PORTS_START( keyboard )
PORT_BIT(0x8000, IP_ACTIVE_HIGH, IPT_UNUSED)
PORT_START("row_6")
- PORT_BIT(0x0001, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CODE(KEYCODE_7_PAD) PORT_NAME("\xe2\x86\x96") // ↖
- PORT_BIT(0x0002, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CODE(KEYCODE_8_PAD) PORT_CODE(KEYCODE_UP) PORT_NAME("\xe2\x86\x91") PORT_CHAR(UCHAR_MAMEKEY(UP))
- PORT_BIT(0x0004, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CODE(KEYCODE_9_PAD) PORT_NAME("\xe2\x86\x97") // ↗
- PORT_BIT(0x0008, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CODE(KEYCODE_4_PAD) PORT_CODE(KEYCODE_LEFT) PORT_NAME("\xe2\x86\x90") PORT_CHAR(UCHAR_MAMEKEY(LEFT))
+ PORT_BIT(0x0001, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CODE(KEYCODE_7_PAD) PORT_NAME(u8"\u2196") // ↖
+ PORT_BIT(0x0002, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CODE(KEYCODE_8_PAD) PORT_CODE(KEYCODE_UP) PORT_NAME(u8"\u2191") PORT_CHAR(UCHAR_MAMEKEY(UP))
+ PORT_BIT(0x0004, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CODE(KEYCODE_9_PAD) PORT_NAME(u8"\u2197") // ↗
+ PORT_BIT(0x0008, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CODE(KEYCODE_4_PAD) PORT_CODE(KEYCODE_LEFT) PORT_NAME(u8"\u2190") PORT_CHAR(UCHAR_MAMEKEY(LEFT))
PORT_BIT(0x0010, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CODE(KEYCODE_HOME) PORT_NAME("HOME") PORT_CHAR(UCHAR_MAMEKEY(HOME))
- PORT_BIT(0x0020, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CODE(KEYCODE_6_PAD) PORT_CODE(KEYCODE_RIGHT) PORT_NAME("\xe2\x86\x92") PORT_CHAR(UCHAR_MAMEKEY(RIGHT))
- PORT_BIT(0x0040, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CODE(KEYCODE_1_PAD) PORT_NAME("\xe2\x86\x99") // ↙
- PORT_BIT(0x0080, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CODE(KEYCODE_2_PAD) PORT_CODE(KEYCODE_DOWN) PORT_NAME("\xe2\x86\x93") PORT_CHAR(UCHAR_MAMEKEY(DOWN))
- PORT_BIT(0x0100, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CODE(KEYCODE_3_PAD) PORT_NAME("\xe2\x86\x98") // ↘
- PORT_BIT(0x0200, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CODE(KEYCODE_PGUP) PORT_NAME("\xe2\x87\xa7")
+ PORT_BIT(0x0020, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CODE(KEYCODE_6_PAD) PORT_CODE(KEYCODE_RIGHT) PORT_NAME(u8"\u2192") PORT_CHAR(UCHAR_MAMEKEY(RIGHT))
+ PORT_BIT(0x0040, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CODE(KEYCODE_1_PAD) PORT_NAME(u8"\u2199") // ↙
+ PORT_BIT(0x0080, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CODE(KEYCODE_2_PAD) PORT_CODE(KEYCODE_DOWN) PORT_NAME(u8"\u2193") PORT_CHAR(UCHAR_MAMEKEY(DOWN))
+ PORT_BIT(0x0100, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CODE(KEYCODE_3_PAD) PORT_NAME(u8"\u2198") // ↘
+ PORT_BIT(0x0200, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CODE(KEYCODE_PGUP) PORT_NAME(u8"\u21e7") // ⇧
PORT_BIT(0x0400, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CODE(KEYCODE_INSERT) PORT_NAME("INS CHAR") PORT_CHAR(UCHAR_MAMEKEY(INSERT))
- PORT_BIT(0x0800, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CODE(KEYCODE_PGDN) PORT_NAME("\xe2\x87\xa9")
+ PORT_BIT(0x0800, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CODE(KEYCODE_PGDN) PORT_NAME(u8"\u21e9") // ⇩
PORT_BIT(0x1000, IP_ACTIVE_HIGH, IPT_UNUSED)
PORT_BIT(0x2000, IP_ACTIVE_HIGH, IPT_UNUSED)
PORT_BIT(0x4000, IP_ACTIVE_HIGH, IPT_UNUSED)
@@ -308,7 +308,7 @@ uint8_t psi_hle_keyboard_device::translate(uint8_t row, uint8_t column)
void psi_hle_keyboard_device::send_key(uint8_t code)
{
- m_host->key_data_w(machine().dummy_space(), 0, code);
+ m_host->key_data_w(code);
m_host->key_strobe_w(1);
m_host->key_strobe_w(0);
}
diff --git a/src/devices/bus/psi_kbd/hle.h b/src/devices/bus/psi_kbd/hle.h
index b563489ef22..266270e115c 100644
--- a/src/devices/bus/psi_kbd/hle.h
+++ b/src/devices/bus/psi_kbd/hle.h
@@ -31,9 +31,9 @@ public:
protected:
// device_t overrides
- virtual ioport_constructor device_input_ports() const override;
- virtual void device_start() override;
- virtual void device_reset() override;
+ virtual ioport_constructor device_input_ports() const override ATTR_COLD;
+ virtual void device_start() override ATTR_COLD;
+ virtual void device_reset() override ATTR_COLD;
// device_matrix_keyboard_interface overrides
virtual void key_make(uint8_t row, uint8_t column) override;
diff --git a/src/devices/bus/psi_kbd/psi_kbd.cpp b/src/devices/bus/psi_kbd/psi_kbd.cpp
index 36a29518213..08c072d2d68 100644
--- a/src/devices/bus/psi_kbd/psi_kbd.cpp
+++ b/src/devices/bus/psi_kbd/psi_kbd.cpp
@@ -29,7 +29,7 @@ DEFINE_DEVICE_TYPE(PSI_KEYBOARD_INTERFACE, psi_keyboard_bus_device, "psi_kbd", "
psi_keyboard_bus_device::psi_keyboard_bus_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) :
device_t(mconfig, PSI_KEYBOARD_INTERFACE, tag, owner, clock),
- device_slot_interface(mconfig, *this),
+ device_single_card_slot_interface<device_psi_keyboard_interface>(mconfig, *this),
m_kbd(nullptr),
m_rx_handler(*this),
m_key_strobe_handler(*this),
@@ -52,11 +52,7 @@ psi_keyboard_bus_device::~psi_keyboard_bus_device()
void psi_keyboard_bus_device::device_start()
{
// get connected keyboard
- m_kbd = dynamic_cast<device_psi_keyboard_interface *>(get_card_device());
-
- // resolve callbacks
- m_rx_handler.resolve_safe();
- m_key_strobe_handler.resolve_safe();
+ m_kbd = get_card_device();
}
//-------------------------------------------------
@@ -65,14 +61,14 @@ void psi_keyboard_bus_device::device_start()
void psi_keyboard_bus_device::device_reset()
{
- m_key_data = 0xff;
+ m_key_data = 0xff; // FIXME: dumb port devices shouldn't mess with data - the keyboard should push this if lines change state on 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);
@@ -88,7 +84,7 @@ WRITE_LINE_MEMBER( psi_keyboard_bus_device::tx_w )
//-------------------------------------------------
device_psi_keyboard_interface::device_psi_keyboard_interface(const machine_config &mconfig, device_t &device) :
- device_slot_card_interface(mconfig, device)
+ device_interface(device, "psikbd")
{
m_host = dynamic_cast<psi_keyboard_bus_device *>(device.owner());
}
diff --git a/src/devices/bus/psi_kbd/psi_kbd.h b/src/devices/bus/psi_kbd/psi_kbd.h
index 39aaa84d9d3..e2ba0f6f642 100644
--- a/src/devices/bus/psi_kbd/psi_kbd.h
+++ b/src/devices/bus/psi_kbd/psi_kbd.h
@@ -41,7 +41,7 @@ class device_psi_keyboard_interface;
// ======================> psi_keyboard_bus_device
-class psi_keyboard_bus_device : public device_t, public device_slot_interface
+class psi_keyboard_bus_device : public device_t, public device_single_card_slot_interface<device_psi_keyboard_interface>
{
public:
// construction/destruction
@@ -61,18 +61,18 @@ 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); }
- DECLARE_WRITE8_MEMBER( key_data_w ) { m_key_data = data; }
+ 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 );
- DECLARE_READ8_MEMBER( key_data_r ) { return m_key_data; }
+ void tx_w(int state);
+ uint8_t key_data_r() { return m_key_data; }
protected:
// device-level overrides
- virtual void device_start() override;
- virtual void device_reset() override;
+ virtual void device_start() override ATTR_COLD;
+ virtual void device_reset() override ATTR_COLD;
private:
device_psi_keyboard_interface *m_kbd;
@@ -85,13 +85,13 @@ private:
// ======================> device_psi_keyboard_interface
-class device_psi_keyboard_interface : public device_slot_card_interface
+class device_psi_keyboard_interface : public device_interface
{
public:
// construction/destruction
virtual ~device_psi_keyboard_interface();
- virtual void tx_w(int state) {};
+ virtual void tx_w(int state) { }
protected:
device_psi_keyboard_interface(const machine_config &mconfig, device_t &device);
diff --git a/src/devices/bus/psion/honda/parallel.cpp b/src/devices/bus/psion/honda/parallel.cpp
new file mode 100644
index 00000000000..417845f92c9
--- /dev/null
+++ b/src/devices/bus/psion/honda/parallel.cpp
@@ -0,0 +1,67 @@
+// license:BSD-3-Clause
+// copyright-holders:Nigel Barnes
+/**********************************************************************
+
+ Psion Parallel Printer Link cable
+
+ TODO:
+ - dump PIC internal ROM and hook up.
+
+**********************************************************************/
+
+#include "emu.h"
+#include "parallel.h"
+
+#include "bus/centronics/ctronics.h"
+#include "cpu/pic16c62x/pic16c62x.h"
+
+
+namespace {
+
+class psion_parallel_device : public device_t, public device_psion_honda_interface
+{
+public:
+ psion_parallel_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
+ : device_t(mconfig, PSION_PARALLEL, tag, owner, clock)
+ , device_psion_honda_interface(mconfig, *this)
+ {
+ }
+
+ static constexpr feature_type unemulated_features() { return feature::PRINTER; }
+
+protected:
+ virtual void device_start() override ATTR_COLD { }
+
+ virtual void device_add_mconfig(machine_config &config) override ATTR_COLD
+ {
+ PIC16C620(config, "mcu", 9.8304_MHz_XTAL).set_disable();
+
+ CENTRONICS(config, "centronics", centronics_devices, "printer");
+ }
+
+ virtual const tiny_rom_entry *device_rom_region() const override ATTR_COLD;
+};
+
+
+//-------------------------------------------------
+// ROM( psion_parallel )
+//-------------------------------------------------
+
+ROM_START(psion_parallel)
+ ROM_REGION(0x0400, "mcu", ROMREGION_ERASEFF)
+ ROM_LOAD("pic16c620.bin", 0x0000, 0x0400, NO_DUMP)
+ROM_END
+
+//-------------------------------------------------
+// rom_region - device-specific ROM region
+//-------------------------------------------------
+
+const tiny_rom_entry *psion_parallel_device::device_rom_region() const
+{
+ return ROM_NAME(psion_parallel);
+}
+
+} // anonymous namespace
+
+
+DEFINE_DEVICE_TYPE_PRIVATE(PSION_PARALLEL, device_psion_honda_interface, psion_parallel_device, "psion_parallel", "Psion Parallel Printer Link cable")
diff --git a/src/devices/bus/psion/honda/parallel.h b/src/devices/bus/psion/honda/parallel.h
new file mode 100644
index 00000000000..cb2596c3f49
--- /dev/null
+++ b/src/devices/bus/psion/honda/parallel.h
@@ -0,0 +1,13 @@
+// license:BSD-3-Clause
+// copyright-holders:Nigel Barnes
+#ifndef MAME_BUS_PSION_HONDA_PARALLEL_H
+#define MAME_BUS_PSION_HONDA_PARALLEL_H
+
+#pragma once
+
+#include "slot.h"
+
+
+DECLARE_DEVICE_TYPE(PSION_PARALLEL, device_psion_honda_interface)
+
+#endif // MAME_BUS_PSION_HONDA_PARALLEL_H
diff --git a/src/devices/bus/psion/honda/pclink.cpp b/src/devices/bus/psion/honda/pclink.cpp
new file mode 100644
index 00000000000..64943554015
--- /dev/null
+++ b/src/devices/bus/psion/honda/pclink.cpp
@@ -0,0 +1,50 @@
+// license:BSD-3-Clause
+// copyright-holders:Nigel Barnes
+/**********************************************************************
+
+ Psion PC Link cable
+
+**********************************************************************/
+
+#include "emu.h"
+#include "pclink.h"
+
+#include "bus/rs232/rs232.h"
+
+
+namespace {
+
+class psion_pclink_device : public device_t, public device_psion_honda_interface
+{
+public:
+ psion_pclink_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
+ : device_t(mconfig, PSION_PCLINK, tag, owner, clock)
+ , device_psion_honda_interface(mconfig, *this)
+ , m_rs232(*this, "rs232")
+ {
+ }
+
+protected:
+ virtual void device_start() override ATTR_COLD { }
+
+ virtual void device_add_mconfig(machine_config &config) override ATTR_COLD
+ {
+ RS232_PORT(config, m_rs232, default_rs232_devices, nullptr);
+ m_rs232->rxd_handler().set(DEVICE_SELF_OWNER, FUNC(psion_honda_slot_device::write_rxd));
+ m_rs232->dcd_handler().set(DEVICE_SELF_OWNER, FUNC(psion_honda_slot_device::write_dcd));
+ m_rs232->dsr_handler().set(DEVICE_SELF_OWNER, FUNC(psion_honda_slot_device::write_dsr));
+ m_rs232->cts_handler().set(DEVICE_SELF_OWNER, FUNC(psion_honda_slot_device::write_cts));
+ }
+
+ virtual void write_txd(int state) override { m_rs232->write_txd(state); }
+ virtual void write_dtr(int state) override { m_rs232->write_dtr(state); }
+ virtual void write_rts(int state) override { m_rs232->write_rts(state); }
+
+private:
+ required_device<rs232_port_device> m_rs232;
+};
+
+} // anonymous namespace
+
+
+DEFINE_DEVICE_TYPE_PRIVATE(PSION_PCLINK, device_psion_honda_interface, psion_pclink_device, "psion_pclink", "Psion PC Link cable")
diff --git a/src/devices/bus/psion/honda/pclink.h b/src/devices/bus/psion/honda/pclink.h
new file mode 100644
index 00000000000..2feb67a7f72
--- /dev/null
+++ b/src/devices/bus/psion/honda/pclink.h
@@ -0,0 +1,13 @@
+// license:BSD-3-Clause
+// copyright-holders:Nigel Barnes
+#ifndef MAME_BUS_PSION_HONDA_PCLINK_H
+#define MAME_BUS_PSION_HONDA_PCLINK_H
+
+#pragma once
+
+#include "slot.h"
+
+
+DECLARE_DEVICE_TYPE(PSION_PCLINK, device_psion_honda_interface)
+
+#endif // MAME_BUS_PSION_HONDA_PCLINK_H
diff --git a/src/devices/bus/psion/honda/slot.cpp b/src/devices/bus/psion/honda/slot.cpp
new file mode 100644
index 00000000000..b0f28309215
--- /dev/null
+++ b/src/devices/bus/psion/honda/slot.cpp
@@ -0,0 +1,126 @@
+// 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 "cyclone.h"
+#include "parallel.h"
+#include "pclink.h"
+#include "ssd.h"
+
+void psion_honda_devices(device_slot_interface &device)
+{
+ //device.option_add("cyclone", PSION_HONDA_CYCLONE); // Cyclone Floppy Drive (Honda)
+ 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..5f7eeef0165
--- /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 ATTR_COLD;
+
+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..07571663d7d
--- /dev/null
+++ b/src/devices/bus/psion/honda/ssd.cpp
@@ -0,0 +1,59 @@
+// license:BSD-3-Clause
+// copyright-holders:Nigel Barnes
+/**********************************************************************
+
+ Psion Siena SSD Drive
+
+**********************************************************************/
+
+#include "emu.h"
+#include "ssd.h"
+
+#include "bus/psion/honda/slot.h"
+#include "machine/psion_ssd.h"
+
+
+namespace {
+
+class psion_siena_ssd_device : public device_t, public device_psion_honda_interface
+{
+public:
+ 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")
+ , m_honda(*this, "honda")
+ {
+ }
+
+protected:
+ virtual void device_start() override ATTR_COLD { }
+
+ virtual void device_add_mconfig(machine_config &config) override ATTR_COLD
+ {
+ PSION_SSD(config, m_ssd);
+ m_ssd->door_cb().set(DEVICE_SELF_OWNER, FUNC(psion_honda_slot_device::write_sdoe));
+
+ PSION_HONDA_SLOT(config, m_honda, psion_honda_devices, nullptr);
+ m_honda->rxd_handler().set(DEVICE_SELF_OWNER, FUNC(psion_honda_slot_device::write_rxd));
+ m_honda->dcd_handler().set(DEVICE_SELF_OWNER, FUNC(psion_honda_slot_device::write_dcd));
+ m_honda->dsr_handler().set(DEVICE_SELF_OWNER, FUNC(psion_honda_slot_device::write_dsr));
+ m_honda->cts_handler().set(DEVICE_SELF_OWNER, FUNC(psion_honda_slot_device::write_cts));
+ }
+
+ virtual uint8_t data_r() override { return m_ssd->data_r(); }
+ virtual void data_w(uint16_t data) override { m_ssd->data_w(data); }
+
+ virtual void write_txd(int state) override { m_honda->write_txd(state); }
+ virtual void write_dtr(int state) override { m_honda->write_dtr(state); }
+ virtual void write_rts(int state) override { m_honda->write_rts(state); }
+
+private:
+ required_device<psion_ssd_device> m_ssd;
+ required_device<psion_honda_slot_device> m_honda;
+};
+
+} // anonymous namespace
+
+
+DEFINE_DEVICE_TYPE_PRIVATE(PSION_SIENA_SSD, device_psion_honda_interface, psion_siena_ssd_device, "psion_siena_ssd", "Psion Siena SSD Drive")
diff --git a/src/devices/bus/psion/honda/ssd.h b/src/devices/bus/psion/honda/ssd.h
new file mode 100644
index 00000000000..d45b8eb07eb
--- /dev/null
+++ b/src/devices/bus/psion/honda/ssd.h
@@ -0,0 +1,12 @@
+// license:BSD-3-Clause
+// copyright-holders:Nigel Barnes
+#ifndef MAME_BUS_PSION_HONDA_SSD_H
+#define MAME_BUS_PSION_HONDA_SSD_H
+
+
+#include "slot.h"
+
+
+DECLARE_DEVICE_TYPE(PSION_SIENA_SSD, device_psion_honda_interface)
+
+#endif // MAME_BUS_PSION_HONDA_SSD_H
diff --git a/src/devices/bus/psion/module/serpar.cpp b/src/devices/bus/psion/module/serpar.cpp
new file mode 100644
index 00000000000..ff3cee82253
--- /dev/null
+++ b/src/devices/bus/psion/module/serpar.cpp
@@ -0,0 +1,91 @@
+// license:BSD-3-Clause
+// copyright-holders:Nigel Barnes
+/**********************************************************************
+
+ Psion RS232/Parallel Module
+
+**********************************************************************/
+
+#include "emu.h"
+#include "serpar.h"
+
+#include "bus/centronics/ctronics.h"
+#include "bus/rs232/rs232.h"
+#include "machine/output_latch.h"
+#include "machine/psion_asic5.h"
+
+
+namespace {
+
+class psion_serial_parallel_device : public device_t, public device_psion_module_interface
+{
+public:
+ psion_serial_parallel_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
+ : device_t(mconfig, PSION_SERIAL_PARALLEL, tag, owner, clock)
+ , device_psion_module_interface(mconfig, *this)
+ , m_asic5(*this, "asic5")
+ , m_cent_ctrl_out(*this, "cent_ctrl_out")
+ {
+ }
+
+protected:
+ // device_t overrides
+ virtual void device_start() override ATTR_COLD { };
+ virtual void device_reset() override ATTR_COLD { m_cent_ctrl_out->write(0xff); };
+
+ // optional information overrides
+ virtual void device_add_mconfig(machine_config &config) override ATTR_COLD;
+
+ 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_add_mconfig - add device configuration
+//-------------------------------------------------
+
+void psion_serial_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(0x03); // RS232 + 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));
+ m_asic5->txd_handler().set("rs232", FUNC(rs232_port_device::write_txd));
+ m_asic5->rts_handler().set("rs232", FUNC(rs232_port_device::write_rts));
+ m_asic5->dtr_handler().set("rs232", FUNC(rs232_port_device::write_dtr));
+ m_asic5->int_handler().set(DEVICE_SELF_OWNER, FUNC(psion_module_slot_device::intr_w));
+
+ rs232_port_device &rs232(RS232_PORT(config, "rs232", default_rs232_devices, nullptr));
+ rs232.rxd_handler().set(m_asic5, FUNC(psion_asic5_device::write_rxd));
+ rs232.dcd_handler().set(m_asic5, FUNC(psion_asic5_device::write_dcd));
+ rs232.dsr_handler().set(m_asic5, FUNC(psion_asic5_device::write_dsr));
+ rs232.cts_handler().set(m_asic5, FUNC(psion_asic5_device::write_cts));
+
+ 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");
+}
+
+} // anonymous namespace
+
+
+DEFINE_DEVICE_TYPE_PRIVATE(PSION_SERIAL_PARALLEL, device_psion_module_interface, psion_serial_parallel_device, "psion_serpar", "Psion RS232/Parallel Module")
diff --git a/src/devices/bus/psion/module/serpar.h b/src/devices/bus/psion/module/serpar.h
new file mode 100644
index 00000000000..7c434d78230
--- /dev/null
+++ b/src/devices/bus/psion/module/serpar.h
@@ -0,0 +1,13 @@
+// license:BSD-3-Clause
+// copyright-holders:Nigel Barnes
+#ifndef MAME_BUS_PSION_MODULE_SERPAR_H
+#define MAME_BUS_PSION_MODULE_SERPAR_H
+
+#pragma once
+
+#include "slot.h"
+
+
+DECLARE_DEVICE_TYPE(PSION_SERIAL_PARALLEL, device_psion_module_interface)
+
+#endif // MAME_BUS_PSION_MODULE_SERPAR_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..1388110534d
--- /dev/null
+++ b/src/devices/bus/psion/module/slot.cpp
@@ -0,0 +1,114 @@
+// 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_intr_cb(*this)
+ , m_card(nullptr)
+{
+}
+
+
+//-------------------------------------------------
+// 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 "serpar.h"
+
+void psion_hcmodule_devices(device_slot_interface &device)
+{
+ device.option_add("serpar", PSION_SERIAL_PARALLEL); // Psion RS232/Parallel Module
+}
+
+void psion_mcmodule_devices(device_slot_interface &device)
+{
+ device.option_add("serpar", PSION_SERIAL_PARALLEL); // Psion RS232/Parallel Module
+}
diff --git a/src/devices/bus/psion/module/slot.h b/src/devices/bus/psion/module/slot.h
new file mode 100644
index 00000000000..93acbebdbca
--- /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_t overrides
+ virtual void device_start() override ATTR_COLD;
+
+private:
+ devcb_write_line m_intr_cb;
+
+ device_psion_module_interface *m_card;
+};
+
+
+// ======================> 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..43fb614d803
--- /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 ATTR_COLD;
+
+ // optional information overrides
+ virtual void device_add_mconfig(machine_config &config) override ATTR_COLD;
+ virtual const tiny_rom_entry *device_rom_region() const override ATTR_COLD;
+
+ 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) ATTR_COLD;
+};
+
+
+// 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..f25c9f341e0
--- /dev/null
+++ b/src/devices/bus/psion/sibo/3link.h
@@ -0,0 +1,81 @@
+// 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);
+
+protected:
+ // device_t overrides
+ virtual void device_start() override ATTR_COLD;
+ virtual void device_reset() override ATTR_COLD;
+
+ // optional information overrides
+ virtual void device_add_mconfig(machine_config &config) override ATTR_COLD;
+ virtual const tiny_rom_entry *device_rom_region() const override ATTR_COLD;
+
+ 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 ATTR_COLD;
+ virtual void device_reset() override ATTR_COLD;
+
+ // optional information overrides
+ virtual void device_add_mconfig(machine_config &config) override ATTR_COLD;
+
+ 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..9b035732b27
--- /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 ATTR_COLD;
+
+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/analogue.cpp b/src/devices/bus/psx/analogue.cpp
index daf7a7f689f..0c6bd2398e8 100644
--- a/src/devices/bus/psx/analogue.cpp
+++ b/src/devices/bus/psx/analogue.cpp
@@ -97,7 +97,7 @@ bool psx_analog_controller_device::get_pad(int count, uint8_t *odata, uint8_t id
case CONFIG_MODE: // 43
if(count == 3)
m_temp = idata;
- /* no break */
+ [[fallthrough]];
case QUERY_PAD_STATE: // 42
*odata = pad_data(count, true);
break;
@@ -142,7 +142,7 @@ bool psx_analog_controller_device::get_pad(int count, uint8_t *odata, uint8_t id
{
case 3:
m_temp = idata;
- /* no break */
+ [[fallthrough]];
default:
*odata = 0x00;
break;
@@ -181,7 +181,7 @@ bool psx_analog_controller_device::get_pad(int count, uint8_t *odata, uint8_t id
case 3:
if(m_cmd == CONFIG_MODE)
m_temp = idata;
- /* no break */
+ [[fallthrough]];
default:
*odata = pad_data(count, true);
break;
@@ -207,7 +207,7 @@ bool psx_analog_controller_device::get_pad(int count, uint8_t *odata, uint8_t id
case 3:
if(m_cmd == CONFIG_MODE)
m_temp = idata;
- /* no break */
+ [[fallthrough]];
default:
*odata = pad_data(count, false);
break;
@@ -254,7 +254,7 @@ static INPUT_PORTS_START( psx_analog_controller )
PORT_BIT( 0xff, 0x80, IPT_PADDLE ) PORT_NAME("Left Analog Y") PORT_SENSITIVITY(100)
PORT_START("PSXMISC")
- PORT_BIT( 0x01, IP_ACTIVE_HIGH, IPT_BUTTON11 ) PORT_NAME("Analog") PORT_TOGGLE PORT_CHANGED_MEMBER(DEVICE_SELF, psx_analog_controller_device, change_mode, 0)
+ PORT_BIT( 0x01, IP_ACTIVE_HIGH, IPT_BUTTON11 ) PORT_NAME("Analog") PORT_TOGGLE PORT_CHANGED_MEMBER(DEVICE_SELF, FUNC(psx_analog_controller_device::change_mode), 0)
INPUT_PORTS_END
ioport_constructor psx_analog_controller_device::device_input_ports() const
diff --git a/src/devices/bus/psx/analogue.h b/src/devices/bus/psx/analogue.h
index 09eaf9baa65..825b3895efd 100644
--- a/src/devices/bus/psx/analogue.h
+++ b/src/devices/bus/psx/analogue.h
@@ -14,7 +14,7 @@ class psx_analog_controller_device : public device_t,
public device_psx_controller_interface
{
public:
- virtual ioport_constructor device_input_ports() const override;
+ virtual ioport_constructor device_input_ports() const override ATTR_COLD;
DECLARE_INPUT_CHANGED_MEMBER(change_mode);
protected:
enum class model { JOYSTICK, DUALSHOCK };
@@ -22,7 +22,7 @@ protected:
psx_analog_controller_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock, model mod);
virtual void device_start() override { }
- virtual void device_reset() override;
+ virtual void device_reset() override ATTR_COLD;
private:
virtual bool get_pad(int count, uint8_t *odata, uint8_t idata) override;
diff --git a/src/devices/bus/psx/ctlrport.cpp b/src/devices/bus/psx/ctlrport.cpp
index 05aae5c5b72..bd445add41e 100644
--- a/src/devices/bus/psx/ctlrport.cpp
+++ b/src/devices/bus/psx/ctlrport.cpp
@@ -4,16 +4,19 @@
#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")
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_slot_interface(mconfig, *this),
+ 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")
@@ -22,7 +25,7 @@ psx_controller_port_device::psx_controller_port_device(const machine_config &mco
void psx_controller_port_device::device_config_complete()
{
- m_dev = dynamic_cast<device_psx_controller_interface *>(get_card_device());
+ m_dev = get_card_device();
}
void psx_controller_port_device::device_add_mconfig(machine_config &config)
@@ -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);
@@ -98,7 +98,8 @@ void psxcontrollerports_device::ack()
}
device_psx_controller_interface::device_psx_controller_interface(const machine_config &mconfig, device_t &device) :
- device_slot_card_interface(mconfig, device), m_odata(0), m_idata(0), m_bit(0), m_count(0), m_memcard(false), m_clock(false), m_sel(false),
+ device_interface(device, "psxctrl"),
+ m_odata(0), m_idata(0), m_bit(0), m_count(0), m_memcard(false), m_clock(false), m_sel(false),
m_ack(true), m_rx(false), m_ack_timer(nullptr), m_owner(nullptr)
{
}
@@ -107,6 +108,13 @@ device_psx_controller_interface::~device_psx_controller_interface()
{
}
+void device_psx_controller_interface::interface_pre_start()
+{
+ m_owner = dynamic_cast<psx_controller_port_device *>(device().owner());
+ if (!m_ack_timer)
+ m_ack_timer = device().machine().scheduler().timer_alloc(timer_expired_delegate(FUNC(device_psx_controller_interface::ack_timer), this));
+}
+
void device_psx_controller_interface::interface_pre_reset()
{
m_bit = 0;
@@ -121,24 +129,23 @@ void device_psx_controller_interface::interface_pre_reset()
m_owner->ack();
}
-void device_psx_controller_interface::interface_pre_start()
+void device_psx_controller_interface::interface_post_stop()
{
- m_owner = dynamic_cast<psx_controller_port_device *>(device().owner());
- m_ack_timer = device().machine().scheduler().timer_alloc(timer_expired_delegate(FUNC(device_psx_controller_interface::ack_timer), this));
+ m_ack_timer = nullptr;
}
-void device_psx_controller_interface::ack_timer(void *ptr, int param)
+void device_psx_controller_interface::ack_timer(int32_t param)
{
m_ack = param;
m_owner->ack();
- if(!param)
+ if (!param)
m_ack_timer->adjust(attotime::from_usec(2), 1);
}
void device_psx_controller_interface::do_pad()
{
- if(!m_bit)
+ if (!m_bit)
{
if(!m_count)
m_odata = 0xff;
diff --git a/src/devices/bus/psx/ctlrport.h b/src/devices/bus/psx/ctlrport.h
index 2058cf4868c..24e65ecedb0 100644
--- a/src/devices/bus/psx/ctlrport.h
+++ b/src/devices/bus/psx/ctlrport.h
@@ -16,7 +16,7 @@ DECLARE_DEVICE_TYPE(PSX_STANDARD_CONTROLLER, psx_standard_controller_device)
class psx_controller_port_device;
-class device_psx_controller_interface : public device_slot_card_interface
+class device_psx_controller_interface : public device_interface
{
friend class psx_multitap_device;
public:
@@ -31,8 +31,9 @@ public:
protected:
device_psx_controller_interface(const machine_config &mconfig, device_t &device);
- virtual void interface_pre_reset() override;
virtual void interface_pre_start() override;
+ virtual void interface_pre_reset() override;
+ virtual void interface_post_stop() override;
enum
{
@@ -43,7 +44,7 @@ protected:
private:
virtual bool get_pad(int count, uint8_t *odata, uint8_t idata) = 0;
virtual void do_pad();
- void ack_timer(void *ptr, int param);
+ void ack_timer(int32_t param);
uint8_t m_odata;
uint8_t m_idata;
@@ -66,7 +67,7 @@ class psx_standard_controller_device : public device_t,
public:
psx_standard_controller_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
- virtual ioport_constructor device_input_ports() const override;
+ virtual ioport_constructor device_input_ports() const override ATTR_COLD;
protected:
virtual void device_start() override { }
@@ -88,12 +89,12 @@ 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;
+ virtual void device_start() override ATTR_COLD;
private:
required_device<psx_controller_port_device> m_port0;
@@ -104,9 +105,11 @@ private:
};
class psx_controller_port_device : public device_t,
- public device_slot_interface
+ 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)
@@ -118,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;
+ virtual void device_add_mconfig(machine_config &config) override ATTR_COLD;
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 309ff1949a3..1c414ca41a2 100644
--- a/src/devices/bus/psx/gamebooster.cpp
+++ b/src/devices/bus/psx/gamebooster.cpp
@@ -11,6 +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
//**************************************************************************
@@ -22,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
@@ -46,115 +49,96 @@ 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()
{
}
+
+//**************************************************************************
+// 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) };
+}
+
+
//**************************************************************************
-// IMPLEMENTATION
+// PSX_PARALLEL_INTERFACE IMPLEMENTATION
//**************************************************************************
-READ16_MEMBER(psx_gamebooster_device::exp_r)
+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;;
+ 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;
+ }
}
-WRITE16_MEMBER(psx_gamebooster_device::exp_w)
+void psx_gamebooster_device::exp_w(offs_t offset, uint16_t data, uint16_t mem_mask)
{
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 a6c06844d7e..9d6571c3c6c 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
- virtual const tiny_rom_entry *device_rom_region() const override;
- virtual void device_add_mconfig(machine_config &config) override;
+protected:
+ // device_t implementation
+ virtual const tiny_rom_entry *device_rom_region() const override ATTR_COLD;
+ 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;
- virtual DECLARE_READ16_MEMBER(exp_r) override;
- virtual DECLARE_WRITE16_MEMBER(exp_w) 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 7f53c69dcfa..927f52688d4 100644
--- a/src/devices/bus/psx/memcard.cpp
+++ b/src/devices/bus/psx/memcard.cpp
@@ -4,7 +4,7 @@
psxcard.c - Sony PlayStation memory card device
by pSXAuthor
- MESS conversion by R. Belmont
+ MAME conversion by R. Belmont
*/
#include "emu.h"
@@ -43,7 +43,7 @@ enum transfer_states
psxcard_device::psxcard_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
: device_t(mconfig, PSXCARD, tag, owner, clock),
- device_image_interface(mconfig, *this),
+ device_memcard_image_interface(mconfig, *this),
pkt_ptr(0),
pkt_sz(0),
cmd(0),
@@ -67,7 +67,7 @@ psxcard_device::psxcard_device(const machine_config &mconfig, const char *tag, d
void psxcard_device::device_start()
{
m_owner = dynamic_cast<psx_controller_port_device *>(owner());
- m_ack_timer = machine().scheduler().timer_alloc(timer_expired_delegate(FUNC(psxcard_device::ack_timer), this));
+ m_ack_timer = timer_alloc(FUNC(psxcard_device::ack_timer), this);
m_ack = true;
m_disabled = false;
@@ -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()
@@ -360,7 +356,7 @@ void psxcard_device::do_card()
}
}
-void psxcard_device::ack_timer(void *ptr, int param)
+void psxcard_device::ack_timer(int32_t param)
{
m_ack = param;
m_owner->ack();
diff --git a/src/devices/bus/psx/memcard.h b/src/devices/bus/psx/memcard.h
index e292d89e589..e4ec1dfc5d3 100644
--- a/src/devices/bus/psx/memcard.h
+++ b/src/devices/bus/psx/memcard.h
@@ -5,27 +5,23 @@
#pragma once
+#include "imagedev/memcard.h"
+
class psx_controller_port_device;
class psxcard_device : public device_t,
- public device_image_interface
+ public device_memcard_image_interface
{
public:
psxcard_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
- virtual iodevice_t image_type() const override { return IO_MEMCARD; }
-
- virtual bool is_readable() const override { return 1; }
- virtual bool is_writeable() const override { return 1; }
- virtual bool is_creatable() const override { return 1; }
- virtual bool must_be_loaded() const override { return 0; }
- virtual bool is_reset_on_load() const override { return 0; }
- virtual const char *file_extensions() const override { return "mc"; }
+ 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(); }
@@ -35,8 +31,8 @@ public:
bool ack_r() { return m_ack; }
protected:
- virtual void device_start() override;
- virtual void device_reset() override;
+ virtual void device_start() override ATTR_COLD;
+ virtual void device_reset() override ATTR_COLD;
private:
void read_card(const unsigned short addr, unsigned char *buf);
@@ -44,7 +40,7 @@ private:
unsigned char checksum_data(const unsigned char *buf, const unsigned int sz);
void do_card();
bool transfer(uint8_t to, uint8_t *from);
- void ack_timer(void *ptr, int param);
+ void ack_timer(int32_t param);
unsigned char pkt[0x8b], pkt_ptr, pkt_sz, cmd;
unsigned short addr;
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/psx/multitap.h b/src/devices/bus/psx/multitap.h
index 0ac7e6626f7..d8a0321d19d 100644
--- a/src/devices/bus/psx/multitap.h
+++ b/src/devices/bus/psx/multitap.h
@@ -14,12 +14,12 @@ public:
psx_multitap_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
protected:
- virtual void device_start() override;
+ virtual void device_start() override ATTR_COLD;
virtual void device_stop() override { device_psx_controller_interface::m_owner->disable_card(false); }
virtual void device_reset() override { device_psx_controller_interface::m_owner->disable_card(true); }
virtual void interface_pre_reset() override;
- virtual void device_add_mconfig(machine_config &config) override;
+ virtual void device_add_mconfig(machine_config &config) override ATTR_COLD;
private:
virtual bool get_pad(int count, uint8_t *odata, uint8_t idata) override;
diff --git a/src/devices/bus/psx/parallel.cpp b/src/devices/bus/psx/parallel.cpp
index b7947e11921..8faf038cfec 100644
--- a/src/devices/bus/psx/parallel.cpp
+++ b/src/devices/bus/psx/parallel.cpp
@@ -24,8 +24,8 @@ DEFINE_DEVICE_TYPE(PSX_PARALLEL_SLOT, psx_parallel_slot_device, "psx_parallel_sl
// psx_parallel_interface - constructor
//-------------------------------------------------
-psx_parallel_interface::psx_parallel_interface(const machine_config &mconfig, device_t &device)
- : device_slot_card_interface(mconfig, device)
+psx_parallel_interface::psx_parallel_interface(const machine_config &mconfig, device_t &device) :
+ device_interface(device, "psxparallel")
{
}
@@ -48,7 +48,7 @@ psx_parallel_interface::~psx_parallel_interface()
psx_parallel_slot_device::psx_parallel_slot_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) :
device_t(mconfig, PSX_PARALLEL_SLOT, tag, owner, clock),
- device_slot_interface(mconfig, *this),
+ device_single_card_slot_interface<psx_parallel_interface>(mconfig, *this),
m_card(nullptr)
{
}
@@ -67,25 +67,17 @@ psx_parallel_slot_device::~psx_parallel_slot_device()
void psx_parallel_slot_device::device_start()
{
- m_card = dynamic_cast<psx_parallel_interface *>(get_card_device());
-}
-
-//-------------------------------------------------
-// device_reset - device-specific reset
-//-------------------------------------------------
-
-void psx_parallel_slot_device::device_reset()
-{
+ m_card = get_card_device();
}
//-------------------------------------------------
// exp_r
//-------------------------------------------------
-READ16_MEMBER(psx_parallel_slot_device::exp_r)
+uint16_t psx_parallel_slot_device::exp_r(offs_t offset)
{
if (m_card)
- return m_card->exp_r(space, offset);
+ return m_card->exp_r(offset);
else
return 0xff;
}
@@ -94,10 +86,10 @@ READ16_MEMBER(psx_parallel_slot_device::exp_r)
// exp_w
//-------------------------------------------------
-WRITE16_MEMBER(psx_parallel_slot_device::exp_w)
+void psx_parallel_slot_device::exp_w(offs_t offset, uint16_t data)
{
if (m_card)
- m_card->exp_w(space, offset, data);
+ m_card->exp_w(offset, data);
}
//-------------------------------------------------
diff --git a/src/devices/bus/psx/parallel.h b/src/devices/bus/psx/parallel.h
index fc478149547..7d75093a34d 100644
--- a/src/devices/bus/psx/parallel.h
+++ b/src/devices/bus/psx/parallel.h
@@ -14,7 +14,7 @@
class psx_parallel_interface;
-class psx_parallel_slot_device : public device_t, public device_slot_interface
+class psx_parallel_slot_device : public device_t, public device_single_card_slot_interface<psx_parallel_interface>
{
public:
// construction/destruction
@@ -30,36 +30,31 @@ public:
psx_parallel_slot_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
virtual ~psx_parallel_slot_device();
- DECLARE_READ16_MEMBER(exp_r);
- DECLARE_WRITE16_MEMBER(exp_w);
+ uint16_t exp_r(offs_t offset);
+ void exp_w(offs_t offset, uint16_t data);
- const bool hascard() const
- {
- return bool(m_card);
- };
+ bool hascard() const { return bool(m_card); }
protected:
// device-level overrides
- virtual void device_start() override;
- virtual void device_reset() override;
-
- psx_parallel_interface *m_card;
+ virtual void device_start() override ATTR_COLD;
private:
+ psx_parallel_interface *m_card;
};
// ======================> psx_parallel_interface
-class psx_parallel_interface : public device_slot_card_interface
+class psx_parallel_interface : public device_interface
{
public:
// construction/destruction
virtual ~psx_parallel_interface();
// reading and writing
- virtual DECLARE_READ16_MEMBER(exp_r) { return 0xff; }
- virtual DECLARE_WRITE16_MEMBER(exp_w) { }
+ virtual uint16_t exp_r(offs_t offset, uint16_t mem_mask = ~0) { return 0xff; }
+ virtual void exp_w(offs_t offset, uint16_t data, uint16_t mem_mask = ~0) { }
protected:
psx_parallel_interface(const machine_config &mconfig, device_t &device);
diff --git a/src/devices/bus/qbus/bk_kmd.cpp b/src/devices/bus/qbus/bk_kmd.cpp
new file mode 100644
index 00000000000..cb7bdada6ad
--- /dev/null
+++ b/src/devices/bus/qbus/bk_kmd.cpp
@@ -0,0 +1,132 @@
+// license:BSD-3-Clause
+// copyright-holders:Sergey Svishchev
+/***************************************************************************
+
+ BK0011 floppy controller (device driver BY.SYS)
+
+ Also compatible with BK0010.
+
+ ROM revisions:
+ - 253 -- shipped with BK0011; supports 10-sector format only (800 KB)
+ - 326 -- shipped with BK0011M; also supports 9-sector format (720 KB)
+ - 327v12 -- 3rd party; also supports PC formats (without Index Mark)
+
+***************************************************************************/
+
+#include "emu.h"
+#include "bk_kmd.h"
+
+#include "machine/1801vp128.h"
+
+#include "formats/bk0010_dsk.h"
+
+
+namespace {
+
+ROM_START(bk_kmd)
+ ROM_REGION(0x1000, "maincpu", 0)
+ ROM_DEFAULT_BIOS("326")
+ ROM_SYSTEM_BIOS(0, "253", "mask 253")
+ ROMX_LOAD("disk_253.rom", 0, 0x1000, CRC(7a21b887) SHA1(f2c08147558816c59f0ef59e7c40ccb4b555e887), ROM_BIOS(0))
+ ROM_SYSTEM_BIOS(1, "326", "mask 326")
+ ROMX_LOAD("disk_326.rom", 0, 0x1000, CRC(fde7583d) SHA1(14f29dcb0fa81f7f1a8efade0bda66b042e47aba), ROM_BIOS(1))
+ ROM_SYSTEM_BIOS(2, "327v12", "327 v12") // "FDD/HDD BIOS 327 V12 (c) JD/DWG!" -- modified mask 326
+ ROMX_LOAD("disk_327.rom", 0, 0x1000, CRC(ed8a43ae) SHA1(28eefbb63047b26e4aec104aeeca74e2f9d0276c), ROM_BIOS(2))
+ROM_END
+
+
+/***************************************************************************
+ TYPE DEFINITIONS
+***************************************************************************/
+
+// ======================> bk_kmd_device
+
+class bk_kmd_device : public device_t,
+ public device_qbus_card_interface
+{
+public:
+ // construction/destruction
+ bk_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;
+ virtual const tiny_rom_entry *device_rom_region() const override;
+
+ required_device<k1801vp128_device> m_fdc;
+
+private:
+ static void floppy_formats(format_registration &fr);
+};
+
+
+//**************************************************************************
+// LIVE DEVICE
+//**************************************************************************
+
+//-------------------------------------------------
+// bk_kmd_device - constructor
+//-------------------------------------------------
+
+bk_kmd_device::bk_kmd_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
+ : device_t(mconfig, BK_KMD, tag, owner, clock)
+ , device_qbus_card_interface(mconfig, *this)
+ , m_fdc(*this, "fdc")
+{
+}
+
+void bk_kmd_device::floppy_formats(format_registration &fr)
+{
+ fr.add_mfm_containers();
+ fr.add(FLOPPY_BK0010_FORMAT);
+}
+
+static void bk_floppies(device_slot_interface &device)
+{
+ device.option_add("525qd", FLOPPY_525_QD);
+}
+
+const tiny_rom_entry *bk_kmd_device::device_rom_region() const
+{
+ return ROM_NAME(bk_kmd);
+}
+
+void bk_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 & 15)
+ {
+ case 1: return 0;
+ case 2: return 1;
+ default: return -1;
+ }
+ });
+ FLOPPY_CONNECTOR(config, "fdc:0", bk_floppies, "525qd", bk_kmd_device::floppy_formats);
+ FLOPPY_CONNECTOR(config, "fdc:1", bk_floppies, "525qd", bk_kmd_device::floppy_formats);
+}
+
+
+//-------------------------------------------------
+// device_start - device-specific startup
+//-------------------------------------------------
+
+void bk_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)));
+ m_bus->program_space().install_rom(0160000, 0167777, memregion("maincpu")->base());
+}
+
+} // anonymous namespace
+
+
+//**************************************************************************
+// DEVICE DEFINITIONS
+//**************************************************************************
+
+DEFINE_DEVICE_TYPE_PRIVATE(BK_KMD, device_qbus_card_interface, bk_kmd_device, "bk_kmd", "BK0010 floppy")
diff --git a/src/devices/bus/qbus/bk_kmd.h b/src/devices/bus/qbus/bk_kmd.h
new file mode 100644
index 00000000000..27075c6cbbe
--- /dev/null
+++ b/src/devices/bus/qbus/bk_kmd.h
@@ -0,0 +1,20 @@
+// license:BSD-3-Clause
+// copyright-holders:Sergey Svishchev
+/***************************************************************************
+
+ BK0011 floppy controller (device driver BY.SYS)
+
+***************************************************************************/
+
+#ifndef MAME_BUS_QBUS_BK_KMD_H
+#define MAME_BUS_QBUS_BK_KMD_H
+
+#pragma once
+
+
+#include "qbus.h"
+
+
+DECLARE_DEVICE_TYPE(BK_KMD, device_qbus_card_interface)
+
+#endif
diff --git a/src/devices/bus/qbus/dsd4432.cpp b/src/devices/bus/qbus/dsd4432.cpp
new file mode 100644
index 00000000000..eebb97f05fc
--- /dev/null
+++ b/src/devices/bus/qbus/dsd4432.cpp
@@ -0,0 +1,255 @@
+// license:BSD-3-Clause
+// copyright-holders:AJR
+/**********************************************************************
+
+ Data Systems Design A4432 Floppy Disk Interface
+
+ This is an LSI-11 compatible, DMA-capable interface board for the
+ DSD 440, an RX02-like floppy disk system from Data Systems
+ Design (later known as Qualogy). The serial interface to the drive
+ controller board might be logically compatible with DEC's own
+ interfaces, though the 26-pin connector is not. PDP-11 (Unibus)
+ and PDP-8 (Omnibus) interfaces were also available for the DSD 440;
+ these were numbered 4430 and 2131 respectively.
+
+ Currently this is a skeleton device with no real emulation. The
+ DSD 440 controller itself has its own ROMs, 8085A CPU and Am2911
+ bitslice sequencer.
+
+**********************************************************************/
+
+#include "emu.h"
+#include "dsd4432.h"
+
+// device type definition
+DEFINE_DEVICE_TYPE(DSD4432, dsd4432_device, "dsd4432", "DSD A4432 Floppy Disk Interface")
+
+dsd4432_device::dsd4432_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock)
+ : device_t(mconfig, DSD4432, tag, owner, clock)
+ , device_qbus_card_interface(mconfig, *this)
+ , m_bootstrap(*this, "bootstrap")
+ , m_bootaddr(*this, "BOOT")
+ , m_iv(*this, "IV")
+ , m_mode(*this, "MODE")
+{
+}
+
+void dsd4432_device::device_start()
+{
+ // ADI = A2, ADH = A3, ADG = A4, ADF = HI ROM, ADE = A5, ADD = A6, ADC = A7, ADB = A8, ADA = A1
+ u16 *romdata = &m_bootstrap[0];
+ const std::vector<u16> origdata(&romdata[0], &romdata[01000]);
+ for (offs_t addr = 0; addr < 01000; addr++)
+ romdata[addr] = origdata[bitswap<9>(addr, 1, 2, 3, 8, 4, 5, 6, 7, 0)];
+}
+
+static INPUT_PORTS_START(dsd4432)
+ PORT_START("BOOT")
+ PORT_DIPNAME(020, 020, "Bootstrap PROM") PORT_DIPLOCATION("5F:8") // Position is marked "DBST"
+ PORT_DIPSETTING(000, DEF_STR(Off))
+ PORT_DIPSETTING(020, DEF_STR(On))
+ PORT_DIPNAME(014, 000, "Bootstrap PROM Address") PORT_DIPLOCATION("6B:1,2") // Positions are marked B-2 and B-1 and numbered 4 and 3 in manual
+ PORT_DIPSETTING(014, "166000")
+ PORT_DIPSETTING(010, "171000")
+ PORT_DIPSETTING(000, "173000")
+ PORT_DIPSETTING(004, "175000")
+ PORT_DIPNAME(003, 000, "Starting Register Address") PORT_DIPLOCATION("6B:4,3") // Positions are marked A-2 and A-1 and numbered 1 and 2 in manual
+ PORT_DIPSETTING(002, "177140")
+ PORT_DIPSETTING(003, "177150")
+ PORT_DIPSETTING(001, "177160")
+ PORT_DIPSETTING(000, "177170")
+
+ PORT_START("IV")
+ PORT_DIPNAME(0774, 0264, "Interrupt Vector") PORT_DIPLOCATION("5F:1,2,3,4,5,6,7") // Positions are marked "IV2" to "IV8"
+ PORT_DIPSETTING(0000, "000")
+ PORT_DIPSETTING(0004, "004")
+ PORT_DIPSETTING(0010, "010")
+ PORT_DIPSETTING(0014, "014")
+ PORT_DIPSETTING(0020, "020")
+ PORT_DIPSETTING(0024, "024")
+ PORT_DIPSETTING(0030, "030")
+ PORT_DIPSETTING(0034, "034")
+ PORT_DIPSETTING(0040, "040")
+ PORT_DIPSETTING(0044, "044")
+ PORT_DIPSETTING(0050, "050")
+ PORT_DIPSETTING(0054, "054")
+ PORT_DIPSETTING(0060, "060")
+ PORT_DIPSETTING(0064, "064")
+ PORT_DIPSETTING(0070, "070")
+ PORT_DIPSETTING(0074, "074")
+ PORT_DIPSETTING(0100, "100")
+ PORT_DIPSETTING(0104, "104")
+ PORT_DIPSETTING(0110, "110")
+ PORT_DIPSETTING(0114, "114")
+ PORT_DIPSETTING(0120, "120")
+ PORT_DIPSETTING(0124, "124")
+ PORT_DIPSETTING(0130, "130")
+ PORT_DIPSETTING(0134, "134")
+ PORT_DIPSETTING(0140, "140")
+ PORT_DIPSETTING(0144, "144")
+ PORT_DIPSETTING(0150, "150")
+ PORT_DIPSETTING(0154, "154")
+ PORT_DIPSETTING(0160, "160")
+ PORT_DIPSETTING(0164, "164")
+ PORT_DIPSETTING(0170, "170")
+ PORT_DIPSETTING(0174, "174")
+ PORT_DIPSETTING(0200, "200")
+ PORT_DIPSETTING(0204, "204")
+ PORT_DIPSETTING(0210, "210")
+ PORT_DIPSETTING(0214, "214")
+ PORT_DIPSETTING(0220, "220")
+ PORT_DIPSETTING(0224, "224")
+ PORT_DIPSETTING(0230, "230")
+ PORT_DIPSETTING(0234, "234")
+ PORT_DIPSETTING(0240, "240")
+ PORT_DIPSETTING(0244, "244")
+ PORT_DIPSETTING(0250, "250")
+ PORT_DIPSETTING(0254, "254")
+ PORT_DIPSETTING(0260, "260")
+ PORT_DIPSETTING(0264, "264")
+ PORT_DIPSETTING(0270, "270")
+ PORT_DIPSETTING(0274, "274")
+ PORT_DIPSETTING(0300, "300")
+ PORT_DIPSETTING(0304, "304")
+ PORT_DIPSETTING(0310, "310")
+ PORT_DIPSETTING(0314, "314")
+ PORT_DIPSETTING(0320, "320")
+ PORT_DIPSETTING(0324, "324")
+ PORT_DIPSETTING(0330, "330")
+ PORT_DIPSETTING(0334, "334")
+ PORT_DIPSETTING(0340, "340")
+ PORT_DIPSETTING(0344, "344")
+ PORT_DIPSETTING(0350, "350")
+ PORT_DIPSETTING(0354, "354")
+ PORT_DIPSETTING(0360, "360")
+ PORT_DIPSETTING(0364, "364")
+ PORT_DIPSETTING(0370, "370")
+ PORT_DIPSETTING(0374, "374")
+ PORT_DIPSETTING(0400, "400")
+ PORT_DIPSETTING(0404, "404")
+ PORT_DIPSETTING(0410, "410")
+ PORT_DIPSETTING(0414, "414")
+ PORT_DIPSETTING(0420, "420")
+ PORT_DIPSETTING(0424, "424")
+ PORT_DIPSETTING(0430, "430")
+ PORT_DIPSETTING(0434, "434")
+ PORT_DIPSETTING(0440, "440")
+ PORT_DIPSETTING(0444, "444")
+ PORT_DIPSETTING(0450, "450")
+ PORT_DIPSETTING(0454, "454")
+ PORT_DIPSETTING(0460, "460")
+ PORT_DIPSETTING(0464, "464")
+ PORT_DIPSETTING(0470, "470")
+ PORT_DIPSETTING(0474, "474")
+ PORT_DIPSETTING(0500, "500")
+ PORT_DIPSETTING(0504, "504")
+ PORT_DIPSETTING(0510, "510")
+ PORT_DIPSETTING(0514, "514")
+ PORT_DIPSETTING(0520, "520")
+ PORT_DIPSETTING(0524, "524")
+ PORT_DIPSETTING(0530, "530")
+ PORT_DIPSETTING(0534, "534")
+ PORT_DIPSETTING(0540, "540")
+ PORT_DIPSETTING(0544, "544")
+ PORT_DIPSETTING(0550, "550")
+ PORT_DIPSETTING(0554, "554")
+ PORT_DIPSETTING(0560, "560")
+ PORT_DIPSETTING(0564, "564")
+ PORT_DIPSETTING(0570, "570")
+ PORT_DIPSETTING(0574, "574")
+ PORT_DIPSETTING(0600, "600")
+ PORT_DIPSETTING(0604, "604")
+ PORT_DIPSETTING(0610, "610")
+ PORT_DIPSETTING(0614, "614")
+ PORT_DIPSETTING(0620, "620")
+ PORT_DIPSETTING(0624, "624")
+ PORT_DIPSETTING(0630, "630")
+ PORT_DIPSETTING(0634, "634")
+ PORT_DIPSETTING(0640, "640")
+ PORT_DIPSETTING(0644, "644")
+ PORT_DIPSETTING(0650, "650")
+ PORT_DIPSETTING(0654, "654")
+ PORT_DIPSETTING(0660, "660")
+ PORT_DIPSETTING(0664, "664")
+ PORT_DIPSETTING(0670, "670")
+ PORT_DIPSETTING(0674, "674")
+ PORT_DIPSETTING(0700, "700")
+ PORT_DIPSETTING(0704, "704")
+ PORT_DIPSETTING(0710, "710")
+ PORT_DIPSETTING(0714, "714")
+ PORT_DIPSETTING(0720, "720")
+ PORT_DIPSETTING(0724, "724")
+ PORT_DIPSETTING(0730, "730")
+ PORT_DIPSETTING(0734, "734")
+ PORT_DIPSETTING(0740, "740")
+ PORT_DIPSETTING(0744, "744")
+ PORT_DIPSETTING(0750, "750")
+ PORT_DIPSETTING(0754, "754")
+ PORT_DIPSETTING(0760, "760")
+ PORT_DIPSETTING(0764, "764")
+ PORT_DIPSETTING(0770, "770")
+ PORT_DIPSETTING(0774, "774")
+ PORT_BIT(0176003, IP_ACTIVE_HIGH, IPT_UNUSED) // Other A inputs for 74LS257 multiplexers are grounded
+
+ PORT_START("MODE")
+ PORT_DIPNAME(1, 1, "Operating Mode") PORT_DIPLOCATION("J12:1") // Position labeled "EN RX01"
+ PORT_DIPSETTING(0, "1 (RX01 Compatible)")
+ PORT_DIPSETTING(1, "2 (RX02 Compatible)")
+
+ // Numerous other jumpers exist, but are for debug use only
+INPUT_PORTS_END
+
+ioport_constructor dsd4432_device::device_input_ports() const
+{
+ return INPUT_PORTS_NAME(dsd4432);
+}
+
+void dsd4432_device::device_add_mconfig(machine_config &config)
+{
+ // TODO
+}
+
+ROM_START(dsd4432)
+ ROM_REGION16_LE(0x400, "bootstrap", 0)
+ // Boot PROMs may be up to 512x8 (74S472 or compatible) each, with the high ROM area mapped separately.
+ // However, the standard bootstrap program requires only 256 words; pin 16 is ADF on 74S472 but ~E2 on 74S471.
+ ROM_LOAD16_BYTE("80035.5a", 0x000, 0x020, CRC(f839c90e) SHA1(aff7a56c228922e45f4bf9f0c838544363239ec2)) // MMI 6309-1J
+ ROM_CONTINUE(0x080, 0x020)
+ ROM_CONTINUE(0x100, 0x020)
+ ROM_CONTINUE(0x180, 0x020)
+ ROM_CONTINUE(0x200, 0x020)
+ ROM_CONTINUE(0x280, 0x020)
+ ROM_CONTINUE(0x300, 0x020)
+ ROM_CONTINUE(0x380, 0x020)
+ ROM_LOAD16_BYTE("80036.6a", 0x001, 0x020, CRC(9fc1a036) SHA1(5f447bfe90dc06cd195b2dcf7c88ca90c3e82295)) // SN74S471N
+ ROM_CONTINUE(0x081, 0x020)
+ ROM_CONTINUE(0x101, 0x020)
+ ROM_CONTINUE(0x181, 0x020)
+ ROM_CONTINUE(0x201, 0x020)
+ ROM_CONTINUE(0x281, 0x020)
+ ROM_CONTINUE(0x301, 0x020)
+ ROM_CONTINUE(0x381, 0x020)
+
+ ROM_REGION(0x200, "hiaddr", 0)
+ // A8 = 6B:2, A7 = 6B:1, A6 = 6B:3, A5 = 6B:4, A4 = DIN12, A3 = DIN11, A2 = DIN10, A1 = DIN9, A0 = BS7
+ ROM_LOAD("80034.5c", 0x000, 0x200, CRC(a8e89bc9) SHA1(e4b0f519ffbdb413b166301ad3fdc7f43bae1f37)) // MMI 6305-1J
+
+ ROM_REGION(0x200, "loaddr", 0)
+ // A8 = 6B:3, A7 = 6B:4, A6 = DIN8, A5 = DIN7, A4 = DIN6, A3 = DIN5, A2 = DIN4, A1 = DIN3, A0 = DIN2
+ ROM_LOAD("80033.7c", 0x000, 0x200, CRC(d45c9327) SHA1(de38874bb6038338840fb71c7304a8e462584681)) // MMI 6305-1J
+
+ ROM_REGION(0x400, "shiftmux", 0)
+ // A9 = parity, A8 = SR15, A7 = SR11, A6 = SR7, A5 = IF DONE, A4 = ENDMA, A3 = HIGH BYTE L, A2 = 3H:QC, A1 = 3H:QD, A0 = IF DATA
+ ROM_LOAD("80032.4h", 0x000, 0x400, CRC(c5c80468) SHA1(12c90cd62d2287ee5018801e4ceb1042051b6783)) // N82S137N
+
+ ROM_REGION(0xf5, "shiftpla", 0)
+ ROM_LOAD("80037.7h", 0x00, 0xf5, NO_DUMP) // N82S100N
+
+ ROM_REGION(0xf5, "dmapla", 0)
+ ROM_LOAD("80038.9h", 0x00, 0xf5, NO_DUMP) // N82S100N
+ROM_END
+
+const tiny_rom_entry *dsd4432_device::device_rom_region() const
+{
+ return ROM_NAME(dsd4432);
+}
diff --git a/src/devices/bus/qbus/dsd4432.h b/src/devices/bus/qbus/dsd4432.h
new file mode 100644
index 00000000000..0b18d9532a5
--- /dev/null
+++ b/src/devices/bus/qbus/dsd4432.h
@@ -0,0 +1,46 @@
+// copyright-holders:AJR
+/***************************************************************************
+
+ Data Systems Design A4432 Floppy Disk Interface
+
+***************************************************************************/
+
+#ifndef MAME_BUS_QBUS_DSD4432_H
+#define MAME_BUS_QBUS_DSD4432_H
+
+#pragma once
+
+#include "qbus.h"
+
+
+//**************************************************************************
+// TYPE DEFINITIONS
+//**************************************************************************
+
+// ======================> dsd4432_device
+
+class dsd4432_device : public device_t, public device_qbus_card_interface
+{
+public:
+ // device type constructor
+ dsd4432_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 ATTR_COLD;
+ virtual ioport_constructor device_input_ports() const override ATTR_COLD;
+ virtual void device_add_mconfig(machine_config &config) override ATTR_COLD;
+ virtual const tiny_rom_entry *device_rom_region() const override ATTR_COLD;
+
+ required_region_ptr<u16> m_bootstrap;
+ required_ioport m_bootaddr;
+ required_ioport m_iv;
+ required_ioport m_mode;
+};
+
+// device type declaration
+DECLARE_DEVICE_TYPE(DSD4432, dsd4432_device)
+
+#endif // MAME_BUS_QBUS_DSD4432_H
diff --git a/src/devices/bus/qbus/dvk_kgd.cpp b/src/devices/bus/qbus/dvk_kgd.cpp
new file mode 100644
index 00000000000..1c7f28c5fc8
--- /dev/null
+++ b/src/devices/bus/qbus/dvk_kgd.cpp
@@ -0,0 +1,163 @@
+// license:BSD-3-Clause
+// copyright-holders:Sergey Svishchev
+/***************************************************************************
+
+ Monochrome register-addressable framebuffer used in DVK.
+
+ To do: overlay on IE15's screen.
+
+***************************************************************************/
+
+#include "emu.h"
+
+#include "dvk_kgd.h"
+
+#include "emupal.h"
+
+
+//**************************************************************************
+// DEVICE DEFINITIONS
+//**************************************************************************
+
+DEFINE_DEVICE_TYPE(DVK_KGD, dvk_kgd_device, "kgd", "DVK KGD framebuffer")
+
+
+//**************************************************************************
+// LIVE DEVICE
+//**************************************************************************
+
+//-------------------------------------------------
+// dvk_kgd_device - constructor
+//-------------------------------------------------
+
+dvk_kgd_device::dvk_kgd_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
+ : device_t(mconfig, DVK_KGD, tag, owner, clock)
+ , device_qbus_card_interface(mconfig, *this)
+ , m_screen(*this, "screen")
+{
+}
+
+
+uint32_t dvk_kgd_device::screen_update(screen_device &screen, bitmap_ind16 &bitmap, const rectangle &cliprect)
+{
+ // CR bit 15: display graphics
+ // CR bit 14: pass through video signal (usually from IE15)
+ if (!(m_cr & (2 << 14)))
+ {
+ bitmap.fill(0);
+ return 0;
+ }
+
+ for (u16 y = 0; y < 286; y++)
+ {
+ for (u16 x = 0; x < 50; x++)
+ {
+ u16 const code = m_videoram[y * 50 + x];
+ for (u8 b = 0; b < 8; b++)
+ {
+ bitmap.pix(y, x * 16 + b + b) = BIT(code, b);
+ bitmap.pix(y, x * 16 + b + b + 1) = BIT(code, b);
+ }
+ }
+ }
+ return 0;
+}
+
+void dvk_kgd_device::device_add_mconfig(machine_config &config)
+{
+ SCREEN(config, m_screen, SCREEN_TYPE_RASTER);
+ m_screen->set_color(rgb_t::green());
+ m_screen->set_screen_update(FUNC(dvk_kgd_device::screen_update));
+ m_screen->set_raw(XTAL(30'800'000) / 2, 800, 0, 800, 286, 0, 286);
+ m_screen->set_palette("palette");
+
+ PALETTE(config, "palette", palette_device::MONOCHROME);
+}
+
+//-------------------------------------------------
+// device_start - device-specific startup
+//-------------------------------------------------
+
+void dvk_kgd_device::device_start()
+{
+ m_bus->install_device(0176640, 0176647, read16sm_delegate(*this, FUNC(dvk_kgd_device::read)),
+ write16sm_delegate(*this, FUNC(dvk_kgd_device::write)));
+
+ // save state
+ save_item(NAME(m_cr));
+ save_item(NAME(m_dr));
+ save_item(NAME(m_ar));
+ save_item(NAME(m_ct));
+
+ m_videoram_base = std::make_unique<uint8_t[]>(16384);
+ m_videoram = m_videoram_base.get();
+}
+
+
+//-------------------------------------------------
+// device_reset - device-specific reset
+//-------------------------------------------------
+
+void dvk_kgd_device::device_reset()
+{
+ m_cr = m_dr = m_ar = m_ct = 0;
+}
+
+
+//-------------------------------------------------
+// read - register read
+//-------------------------------------------------
+
+uint16_t dvk_kgd_device::read(offs_t offset)
+{
+ uint16_t data = 0;
+
+ switch (offset & 3)
+ {
+ case 0:
+ data = m_cr;
+ break;
+
+ case 1:
+ data = m_videoram[m_ar];
+ break;
+
+ case 2:
+ data = m_ar;
+ break;
+
+ case 3:
+ data = m_ct;
+ break;
+ }
+
+ return data;
+}
+
+
+//-------------------------------------------------
+// write - register write
+//-------------------------------------------------
+
+void dvk_kgd_device::write(offs_t offset, uint16_t data)
+{
+ switch (offset & 3)
+ {
+ case 0:
+ m_cr = ((m_cr & ~KGDCR_WR) | (data & KGDCR_WR));
+ break;
+
+ case 1:
+ m_dr = ((m_dr & ~KGDDR_WR) | (data & KGDDR_WR));
+ m_videoram[m_ar] = m_dr;
+ break;
+
+ case 2:
+ m_ar = ((m_ar & ~KGDAR_WR) | (data & KGDAR_WR));
+ break;
+
+ case 3:
+ m_ct = ((m_ct & ~KGDCT_WR) | (data & KGDCT_WR));
+ break;
+ }
+}
diff --git a/src/devices/bus/qbus/dvk_kgd.h b/src/devices/bus/qbus/dvk_kgd.h
new file mode 100644
index 00000000000..dfcb027706d
--- /dev/null
+++ b/src/devices/bus/qbus/dvk_kgd.h
@@ -0,0 +1,65 @@
+// license:BSD-3-Clause
+// copyright-holders:Sergey Svishchev
+/***************************************************************************
+
+ Monochrome register-addressable framebuffer used in DVK.
+
+***************************************************************************/
+
+#ifndef MAME_BUS_QBUS_DVK_KGD_H
+#define MAME_BUS_QBUS_DVK_KGD_H
+
+#pragma once
+
+#include "qbus.h"
+
+#include "screen.h"
+
+
+static constexpr int KGDCR_WR = 0140000;
+static constexpr int KGDDR_WR = 0000377;
+static constexpr int KGDAR_WR = 0037777;
+static constexpr int KGDCT_WR = 0037777;
+
+
+/***************************************************************************
+ TYPE DEFINITIONS
+***************************************************************************/
+
+// ======================> dvk_kgd_device
+
+class dvk_kgd_device : public device_t,
+ public device_qbus_card_interface
+{
+public:
+ // construction/destruction
+ dvk_kgd_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
+
+ uint32_t screen_update(screen_device &screen, bitmap_ind16 &bitmap, const rectangle &cliprect);
+
+ uint16_t read(offs_t offset);
+ void write(offs_t offset, uint16_t data);
+
+protected:
+ // device-level overrides
+ 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;
+
+ required_device<screen_device> m_screen;
+
+private:
+ std::unique_ptr<uint8_t[]> m_videoram_base;
+ uint8_t *m_videoram;
+
+ uint16_t m_cr;
+ uint16_t m_dr;
+ uint16_t m_ar;
+ uint16_t m_ct;
+};
+
+
+// device type definition
+DECLARE_DEVICE_TYPE(DVK_KGD, dvk_kgd_device)
+
+#endif
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..556ec5839fb
--- /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 ATTR_COLD;
+ virtual void device_reset() override ATTR_COLD;
+ virtual void device_add_mconfig(machine_config &config) override ATTR_COLD;
+
+ 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
new file mode 100644
index 00000000000..c27e240cc08
--- /dev/null
+++ b/src/devices/bus/qbus/pc11.cpp
@@ -0,0 +1,232 @@
+// license:BSD-3-Clause
+// copyright-holders:Sergey Svishchev
+/***************************************************************************
+
+ DEC PC11 paper tape reader and punch controller (punch not implemented)
+
+ FIXME: PC11 is a Unibus device with no direct Q-bus counterpart
+
+***************************************************************************/
+
+#include "emu.h"
+#include "pc11.h"
+
+
+#define LOG_DBG (1U << 1)
+
+//#define VERBOSE (LOG_GENERAL | LOG_DBG)
+//#define LOG_OUTPUT_FUNC osd_printf_info
+
+#include "logmacro.h"
+
+#define LOGDBG(...) LOGMASKED(LOG_DBG, __VA_ARGS__)
+
+
+//**************************************************************************
+// DEVICE DEFINITIONS
+//**************************************************************************
+
+DEFINE_DEVICE_TYPE(DEC_PC11, pc11_device, "pc11", "DEC PC11 controller")
+
+
+//**************************************************************************
+// MACROS / CONSTANTS
+//**************************************************************************
+
+enum
+{
+ REGISTER_RCSR = 0,
+ REGISTER_RBUF,
+ REGISTER_TCSR,
+ REGISTER_TBUF
+};
+
+const char* pc11_regnames[] = {
+ "RCSR", "RBUF", "TCSR", "TBUF"
+};
+
+//**************************************************************************
+// LIVE DEVICE
+//**************************************************************************
+
+//-------------------------------------------------
+// pc11_device - constructor
+//-------------------------------------------------
+
+pc11_device::pc11_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
+ : paper_tape_reader_device(mconfig, DEC_PC11, tag, owner, clock)
+ , device_qbus_card_interface(mconfig, *this)
+ , m_rxvec(070)
+ , m_txvec(074)
+{
+ (void)pc11_regnames;
+}
+
+
+//-------------------------------------------------
+// device_start - device-specific startup
+//-------------------------------------------------
+
+void pc11_device::device_start()
+{
+ m_bus->install_device(0177550, 0177557, read16sm_delegate(*this, FUNC(pc11_device::read)),
+ write16sm_delegate(*this, FUNC(pc11_device::write)));
+
+ // resolve callbacks
+
+ // save state
+ save_item(NAME(m_rcsr));
+ save_item(NAME(m_rbuf));
+ save_item(NAME(m_tcsr));
+ save_item(NAME(m_tbuf));
+
+ // about 300 cps
+ m_read_timer = timer_alloc(FUNC(pc11_device::read_tick), this);
+ m_read_timer->adjust(attotime::from_usec(333), 0, attotime::from_usec(333));
+}
+
+
+//-------------------------------------------------
+// device_reset - device-specific reset
+//-------------------------------------------------
+
+void pc11_device::device_reset()
+{
+ LOG("Reset, rxvec %03o txvec %03o\n", m_rxvec, m_txvec);
+
+ m_rcsr = m_rbuf = m_tbuf = 0;
+ m_tcsr = CSR_DONE;
+ m_rxrdy = m_txrdy = CLEAR_LINE;
+
+ m_bus->birq4_w(CLEAR_LINE);
+}
+
+int pc11_device::z80daisy_irq_state()
+{
+ if (m_rxrdy == ASSERT_LINE || m_txrdy == ASSERT_LINE)
+ return Z80_DAISY_INT;
+ else
+ return 0;
+}
+
+int pc11_device::z80daisy_irq_ack()
+{
+ int vec = -1;
+
+ if (m_rxrdy == ASSERT_LINE)
+ {
+ m_rxrdy = CLEAR_LINE;
+ vec = m_rxvec;
+ }
+ else if (m_txrdy == ASSERT_LINE)
+ {
+ m_txrdy = CLEAR_LINE;
+ vec = m_txvec;
+ }
+
+ if (vec > 0)
+ LOGDBG("IRQ ACK vec %03o\n", vec);
+
+ return vec;
+}
+
+void pc11_device::z80daisy_irq_reti()
+{
+}
+
+
+std::pair<std::error_condition, std::string> pc11_device::call_load()
+{
+ /* reader unit */
+ m_fd = this;
+ m_rcsr &= ~(CSR_ERR | CSR_BUSY);
+
+ LOG("call_load filename %s is_open %d\n", m_fd->filename(), m_fd->is_open());
+
+ return std::make_pair(std::error_condition(), std::string());
+}
+
+void pc11_device::call_unload()
+{
+ /* reader unit */
+ m_fd = nullptr;
+ m_rcsr |= CSR_ERR;
+}
+
+
+//-------------------------------------------------
+// read - register read
+//-------------------------------------------------
+
+uint16_t pc11_device::read(offs_t offset)
+{
+ uint16_t data = 0;
+
+ switch (offset & 0x03)
+ {
+ case REGISTER_RCSR:
+ data = m_rcsr & PTRCSR_IMP;
+ break;
+
+ case REGISTER_RBUF:
+ data = m_rbuf & 0377;
+ m_rcsr &= ~CSR_DONE;
+ clear_virq(m_bus->birq4_w, m_rcsr, CSR_IE, m_rxrdy);
+ break;
+ }
+
+ LOGDBG("R %06o == %06o\n", 0177550 + (offset << 1), data);
+
+ return data;
+}
+
+
+//-------------------------------------------------
+// write - register write
+//-------------------------------------------------
+
+void pc11_device::write(offs_t offset, uint16_t data)
+{
+ LOGDBG("W %06o <- %06o\n", 0177550 + (offset << 1), data);
+
+ switch (offset & 0x03)
+ {
+ case REGISTER_RCSR:
+ if ((data & CSR_IE) == 0)
+ {
+ clear_virq(m_bus->birq4_w, 1, 1, m_rxrdy);
+ }
+ else if ((m_rcsr & (CSR_DONE + CSR_IE)) == CSR_DONE)
+ {
+ raise_virq(m_bus->birq4_w, 1, 1, m_rxrdy);
+ }
+ if (data & CSR_GO)
+ {
+ m_rcsr = (m_rcsr & ~CSR_DONE) | CSR_BUSY;
+ clear_virq(m_bus->birq4_w, m_rcsr, CSR_IE, m_rxrdy);
+ }
+ m_rcsr = ((m_rcsr & ~PTRCSR_WR) | (data & PTRCSR_WR));
+ break;
+
+ case REGISTER_RBUF:
+ break;
+ }
+}
+
+TIMER_CALLBACK_MEMBER(pc11_device::read_tick)
+{
+ uint8_t reply;
+
+ if (!(m_rcsr & CSR_BUSY))
+ return;
+
+ LOGDBG("Timer rcsr %06o param %d m_fd %p\n", m_rcsr, param, m_fd);
+
+ m_rcsr = (m_rcsr | CSR_ERR) & ~CSR_BUSY;
+ if (m_fd && m_fd->exists() && (m_fd->fread(&reply, 1) == 1))
+ {
+ m_rcsr = (m_rcsr | CSR_DONE) & ~CSR_ERR;
+ m_rbuf = reply;
+ }
+ raise_virq(m_bus->birq4_w, m_rcsr, CSR_IE, m_rxrdy);
+}
diff --git a/src/devices/bus/qbus/pc11.h b/src/devices/bus/qbus/pc11.h
new file mode 100644
index 00000000000..1793808826c
--- /dev/null
+++ b/src/devices/bus/qbus/pc11.h
@@ -0,0 +1,84 @@
+// license:BSD-3-Clause
+// copyright-holders:Sergey Svishchev
+/***************************************************************************
+
+ DEC PC11 paper tape reader and punch controller (punch not implemented)
+
+***************************************************************************/
+
+#ifndef MAME_BUS_QBUS_PC11_H
+#define MAME_BUS_QBUS_PC11_H
+
+#pragma once
+
+#include "qbus.h"
+
+#include "imagedev/papertape.h"
+#include "machine/pdp11.h"
+
+
+#define PTRCSR_IMP (CSR_ERR + CSR_BUSY + CSR_DONE + CSR_IE)
+#define PTRCSR_WR (CSR_IE)
+#define PTPCSR_IMP (CSR_ERR + CSR_DONE + CSR_IE)
+#define PTPCSR_WR (CSR_IE)
+
+
+/***************************************************************************
+ TYPE DEFINITIONS
+***************************************************************************/
+
+// ======================> pc11_device
+
+class pc11_device : public paper_tape_reader_device,
+ public device_qbus_card_interface
+{
+public:
+ // construction/destruction
+ pc11_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 "pdp11_ptap"; }
+ virtual const char *file_extensions() const noexcept override { return "bin,bim,lda"; }
+
+ 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_t implementation
+ virtual void device_start() override ATTR_COLD;
+ virtual void device_reset() override ATTR_COLD;
+
+ // device_z80daisy_interface implementation
+ virtual int z80daisy_irq_state() override;
+ virtual int z80daisy_irq_ack() override;
+ virtual void z80daisy_irq_reti() override;
+
+ TIMER_CALLBACK_MEMBER(read_tick);
+
+private:
+ int m_rxvec;
+ int m_txvec;
+
+ device_image_interface *m_fd;
+
+ line_state m_rxrdy;
+ line_state m_txrdy;
+
+ uint16_t m_rcsr;
+ uint16_t m_rbuf;
+ uint16_t m_tcsr;
+ uint16_t m_tbuf;
+
+ emu_timer *m_read_timer;
+
+ const char *pc11_regnames[4];
+};
+
+
+// device type definition
+DECLARE_DEVICE_TYPE(DEC_PC11, pc11_device)
+
+#endif // MAME_BUS_QBUS_PC11_H
diff --git a/src/devices/bus/qbus/qbus.cpp b/src/devices/bus/qbus/qbus.cpp
new file mode 100644
index 00000000000..d3b639c801f
--- /dev/null
+++ b/src/devices/bus/qbus/qbus.cpp
@@ -0,0 +1,197 @@
+// license:BSD-3-Clause
+// copyright-holders:Sergey Svishchev
+/**********************************************************************
+
+ DEC Q-Bus emulation (skeleton)
+
+**********************************************************************/
+
+#include "emu.h"
+
+#include "qbus.h"
+
+// Peripheral boards
+#include "bk_kmd.h"
+#include "dsd4432.h"
+#include "dvk_kgd.h"
+#include "dvk_mx.h"
+#include "pc11.h"
+#include "qg640.h"
+#include "qtx.h"
+#include "tdl12.h"
+#include "uknc_kmd.h"
+
+
+void qbus_cards(device_slot_interface &device)
+{
+ device.option_add("pc11", DEC_PC11); /* Paper tape reader and punch */
+ 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);
+ device.option_add("by", BK_KMD);
+ device.option_add("tdl12", TDL12);
+}
+
+
+//**************************************************************************
+// DEVICE DEFINITIONS
+//**************************************************************************
+
+DEFINE_DEVICE_TYPE(QBUS, qbus_device, "qbus", "DEC Qbus bus")
+DEFINE_DEVICE_TYPE(QBUS_SLOT, qbus_slot_device, "qbus_slot", "DEC Qbus slot")
+
+
+//**************************************************************************
+// LIVE DEVICE
+//**************************************************************************
+
+//-------------------------------------------------
+// device_qbus_card_interface - constructor
+//-------------------------------------------------
+
+device_qbus_card_interface::device_qbus_card_interface(const machine_config &mconfig, device_t &device) :
+ device_interface(device, "qbus"),
+ m_bus(nullptr)
+{
+}
+
+
+//-------------------------------------------------
+// qbus_slot_device - constructor
+//-------------------------------------------------
+qbus_slot_device::qbus_slot_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) :
+ device_t(mconfig, QBUS_SLOT, tag, owner, clock),
+ device_slot_interface(mconfig, *this),
+ m_write_birq4(*this),
+ m_write_birq5(*this),
+ m_write_birq6(*this),
+ m_write_birq7(*this),
+ m_write_bdmr(*this),
+ m_card(nullptr),
+ m_bus(*this, DEVICE_SELF_OWNER)
+{
+}
+
+
+//-------------------------------------------------
+// device_start - device-specific startup
+//-------------------------------------------------
+
+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);
+}
+
+
+//-------------------------------------------------
+// qbus_device - constructor
+//-------------------------------------------------
+
+qbus_device::qbus_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) :
+ device_t(mconfig, QBUS, tag, owner, clock),
+ device_memory_interface(mconfig, *this),
+ device_z80daisy_interface(mconfig, *this),
+ m_program_config("a18", ENDIANNESS_BIG, 16, 16, 0, address_map_constructor()),
+ m_space(*this, finder_base::DUMMY_TAG, -1),
+ m_out_birq4_cb(*this),
+ m_out_birq5_cb(*this),
+ m_out_birq6_cb(*this),
+ m_out_birq7_cb(*this),
+ m_out_bdmr_cb(*this)
+{
+}
+
+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
+//-------------------------------------------------
+
+void qbus_device::device_start()
+{
+}
+
+
+//-------------------------------------------------
+// device_reset - device-specific reset
+//-------------------------------------------------
+
+void qbus_device::device_reset()
+{
+}
+
+void qbus_device::init_w()
+{
+ for (device_qbus_card_interface &entry : m_device_list)
+ {
+ entry.init_w();
+ }
+}
+
+
+//-------------------------------------------------
+// add_card - add card
+//-------------------------------------------------
+
+void qbus_device::add_card(device_qbus_card_interface &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)
+{
+ m_space->install_readwrite_handler(start, end, rhandler, whandler, mask);
+}
+
+
+//-------------------------------------------------
+// z80daisy_interface
+//-------------------------------------------------
+
+int qbus_device::z80daisy_irq_state()
+{
+ int data = 0;
+
+ for (device_qbus_card_interface &entry : m_device_list)
+ {
+ data = entry.z80daisy_irq_state();
+ if (data)
+ return data;
+ }
+
+ return data;
+}
+
+int qbus_device::z80daisy_irq_ack()
+{
+ int vec = -1;
+
+ for (device_qbus_card_interface &entry : m_device_list)
+ {
+ vec = entry.z80daisy_irq_ack();
+ if (vec > 0)
+ return vec;
+ }
+
+ return vec;
+}
+
+void qbus_device::z80daisy_irq_reti()
+{
+}
diff --git a/src/devices/bus/qbus/qbus.h b/src/devices/bus/qbus/qbus.h
new file mode 100644
index 00000000000..c33af439080
--- /dev/null
+++ b/src/devices/bus/qbus/qbus.h
@@ -0,0 +1,167 @@
+// license:BSD-3-Clause
+// copyright-holders:Sergey Svishchev
+/**********************************************************************
+
+ DEC Q-Bus emulation (skeleton)
+
+**********************************************************************/
+
+#ifndef MAME_BUS_QBUS_QBUS_H
+#define MAME_BUS_QBUS_QBUS_H
+
+#pragma once
+
+#include "machine/z80daisy.h"
+
+#include <functional>
+#include <vector>
+
+
+//**************************************************************************
+// TYPE DEFINITIONS
+//**************************************************************************
+
+class qbus_device;
+
+// ======================> device_qbus_card_interface
+
+class device_qbus_card_interface : public device_interface
+{
+ friend class qbus_device;
+
+public:
+ // Q-Bus interface
+ virtual void biaki_w(int state) { }
+ virtual void bdmgi_w(int state) { }
+ virtual void init_w() { device_reset(); }
+
+protected:
+ // construction/destruction
+ device_qbus_card_interface(const machine_config &mconfig, device_t &device);
+
+ virtual void device_reset() { }
+
+ virtual int z80daisy_irq_state() { return 0; }
+ virtual int z80daisy_irq_ack() { return -1; }
+ virtual void z80daisy_irq_reti() { }
+
+ qbus_device *m_bus;
+};
+
+
+
+// ======================> qbus_device
+
+class qbus_device : public device_t,
+ public device_memory_interface,
+ public device_z80daisy_interface
+{
+public:
+ // construction/destruction
+ template <typename T>
+ qbus_device(const machine_config &mconfig, const char *tag, device_t *owner, T &&cputag, int spacenum)
+ : qbus_device(mconfig, tag, owner, (uint32_t)0)
+ {
+ set_cputag(std::forward<T>(cputag), spacenum);
+ }
+
+ qbus_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
+
+ ~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;
+ address_space &program_space() const { return *m_space; }
+
+ 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 install_device(offs_t start, offs_t end, read16sm_delegate rhandler, write16sm_delegate whandler, uint32_t mask=0xffffffff);
+
+ void init_w();
+
+ 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); }
+
+ void bdmr_w(int state) { m_out_bdmr_cb(state); }
+
+ const address_space_config m_program_config;
+
+protected:
+ // device_t implementation
+ virtual void device_start() override ATTR_COLD;
+ virtual void device_reset() override ATTR_COLD;
+
+ // device_z80daisy_interface implementation
+ virtual int z80daisy_irq_state() override;
+ virtual int z80daisy_irq_ack() override;
+ virtual void z80daisy_irq_reti() override;
+
+ // internal state
+ 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;
+
+ card_vector m_device_list;
+};
+
+
+// ======================> qbus_slot_device
+
+class qbus_slot_device : public device_t, public device_slot_interface
+{
+public:
+ // construction/destruction
+ template <typename T>
+ qbus_slot_device(machine_config const &mconfig, char const *tag, device_t *owner, T &&opts, char const *dflt)
+ : qbus_slot_device(mconfig, tag, owner, DERIVED_CLOCK(1, 1))
+ {
+ option_reset();
+ opts(*this);
+ set_default_option(dflt);
+ set_fixed(false);
+ }
+ qbus_slot_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
+
+ // computer interface
+ 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_t implementation
+ virtual void device_start() override ATTR_COLD;
+
+ devcb_write_line m_write_birq4;
+ devcb_write_line m_write_birq5;
+ devcb_write_line m_write_birq6;
+ devcb_write_line m_write_birq7;
+ devcb_write_line m_write_bdmr;
+
+ device_qbus_card_interface *m_card;
+
+private:
+ required_device<qbus_device> m_bus;
+};
+
+
+// device type definition
+DECLARE_DEVICE_TYPE(QBUS, qbus_device)
+DECLARE_DEVICE_TYPE(QBUS_SLOT, qbus_slot_device)
+
+void qbus_cards(device_slot_interface &device);
+
+#endif // MAME_BUS_QBUS_QBUS_H
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..5138a22c99a
--- /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 ATTR_COLD;
+ virtual void device_add_mconfig(machine_config &config) override ATTR_COLD;
+ virtual const tiny_rom_entry *device_rom_region() const override ATTR_COLD;
+
+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) ATTR_COLD;
+ void videoram_map(address_map &map) ATTR_COLD;
+
+ 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
new file mode 100644
index 00000000000..b4e684577d1
--- /dev/null
+++ b/src/devices/bus/qbus/qtx.cpp
@@ -0,0 +1,166 @@
+// license:BSD-3-Clause
+// copyright-holders:AJR
+/***********************************************************************************************************************************
+
+2017-11-02 Skeleton
+
+Transitional Technology Inc. SCSI Q-bus host adapter, part of the QTx series
+(x = 'S' for single-ended, x = 'D' for differential). UTx-1 was also provided for Unibus.
+
+Chips: NCR 53C90A, Motorola MC68901P, Fujitsu 8464A-10L (8KB static ram), Xicor X24C44P (16x16 serial NOVRAM), and 14 undumped
+Lattice PLDs.
+
+Other: LED, 20MHz crystal. Next to the MC68901P is another chip just as large (48 pin DIL), with a huge "MFG. UNDER LICENSE FROM
+ DIGITAL EQUIPMENT CORP." sticker covering all details. Assumed to be a Motorola MC68008 CPU.
+
+************************************************************************************************************************************/
+
+#include "emu.h"
+#include "qtx.h"
+
+#include "bus/nscsi/devices.h"
+#include "bus/rs232/rs232.h"
+#include "cpu/m68000/m68008.h"
+#include "machine/74259.h"
+#include "machine/eepromser.h"
+
+
+// device type definition
+DEFINE_DEVICE_TYPE(TTI_QTS1, qts1_device, "qts1", "TTI QTS-1 SCSI Host Adapter")
+
+
+qts1_device::qts1_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock)
+ : device_t(mconfig, TTI_QTS1, tag, owner, clock)
+ , device_qbus_card_interface(mconfig, *this)
+ , m_localcpu(*this, "localcpu")
+ , m_mfp(*this, "mfp")
+ , m_asc(*this, "scsibus:7:asc")
+ , m_dma_address(0)
+{
+}
+
+void qts1_device::device_start()
+{
+ save_item(NAME(m_dma_address));
+}
+
+
+u8 qts1_device::asc_r(offs_t offset)
+{
+ return m_asc->read(offset ^ 1);
+}
+
+void qts1_device::asc_w(offs_t offset, u8 data)
+{
+ m_asc->write(offset ^ 1, data);
+}
+
+void qts1_device::dma_address_w(offs_t offset, u8 data)
+{
+ m_dma_address &= ~(0xff000000 >> (offset * 8));
+ m_dma_address |= u32(data) << (24 - offset * 8);
+}
+
+u8 qts1_device::io_status_r()
+{
+ return 0;
+}
+
+void qts1_device::channel_w(u8 data)
+{
+ switch (data & 0x03)
+ {
+ case 0:
+ m_mfp->i4_w(0);
+ break;
+
+ case 1:
+ m_mfp->i3_w(0);
+ break;
+
+ case 3:
+ m_mfp->i5_w(0);
+ break;
+ }
+}
+
+void qts1_device::prg_map(address_map &map)
+{
+ map(0x00000, 0x07fff).rom().region("firmware", 0);
+ map(0x7e000, 0x7ffff).ram();
+ map(0x80000, 0x80017).rw(m_mfp, FUNC(mc68901_device::read), FUNC(mc68901_device::write));
+ map(0x80018, 0x8001f).ram();
+ map(0x80020, 0x80029).rw(FUNC(qts1_device::asc_r), FUNC(qts1_device::asc_w));
+ map(0x80070, 0x80077).w("bitlatch", FUNC(ls259_device::write_d0));
+ map(0x80078, 0x8007b).w(FUNC(qts1_device::dma_address_w));
+ map(0x8007c, 0x8007c).r(FUNC(qts1_device::io_status_r));
+ map(0x8007d, 0x8007d).w(FUNC(qts1_device::channel_w));
+}
+
+void qts1_device::fc7_map(address_map &map)
+{
+ map(0xffff5, 0xffff5).r(m_mfp, FUNC(mc68901_device::get_vector));
+}
+
+static void qtx_scsi_devices(device_slot_interface &device)
+{
+ default_scsi_devices(device);
+ device.option_add_internal("asc", NCR53C90A);
+}
+
+void qts1_device::asc_config(device_t *device)
+{
+ ncr53c90a_device &adapter = downcast<ncr53c90a_device &>(*device);
+
+ adapter.set_clock(20_MHz_XTAL);
+
+ adapter.irq_handler_cb().set(m_mfp, FUNC(mc68901_device::i7_w)).invert();
+ //adapter.drq_handler_cb().set(?);
+}
+
+void qts1_device::device_add_mconfig(machine_config &config)
+{
+ M68008(config, m_localcpu, 20_MHz_XTAL / 2); // guess
+ m_localcpu->set_addrmap(AS_PROGRAM, &qts1_device::prg_map);
+ m_localcpu->set_addrmap(m68008_device::AS_CPU_SPACE, &qts1_device::fc7_map);
+
+ MC68901(config, m_mfp, 20_MHz_XTAL / 2); // guess
+ m_mfp->set_timer_clock(20_MHz_XTAL / 8); // guess
+ m_mfp->out_tco_cb().set(m_mfp, FUNC(mc68901_device::rc_w));
+ m_mfp->out_tco_cb().append(m_mfp, FUNC(mc68901_device::tc_w));
+ m_mfp->out_so_cb().set("rs232", FUNC(rs232_port_device::write_txd));
+ m_mfp->out_irq_cb().set_inputline("localcpu", M68K_IRQ_2); // probably
+
+ NSCSI_BUS(config, "scsibus");
+ NSCSI_CONNECTOR(config, "scsibus:0", qtx_scsi_devices, nullptr);
+ NSCSI_CONNECTOR(config, "scsibus:1", qtx_scsi_devices, nullptr);
+ NSCSI_CONNECTOR(config, "scsibus:2", qtx_scsi_devices, nullptr);
+ NSCSI_CONNECTOR(config, "scsibus:3", qtx_scsi_devices, nullptr);
+ NSCSI_CONNECTOR(config, "scsibus:4", qtx_scsi_devices, nullptr);
+ NSCSI_CONNECTOR(config, "scsibus:5", qtx_scsi_devices, nullptr);
+ NSCSI_CONNECTOR(config, "scsibus:6", qtx_scsi_devices, nullptr);
+ NSCSI_CONNECTOR(config, "scsibus:7", qtx_scsi_devices, "asc", true).set_option_machine_config("asc", [this] (device_t *device) { asc_config(device); });
+
+ rs232_port_device &rs232(RS232_PORT(config, "rs232", default_rs232_devices, "terminal"));
+ rs232.rxd_handler().set(m_mfp, FUNC(mc68901_device::si_w));
+
+ EEPROM_X24C44_16BIT(config, "novram").do_callback().set("mfp", FUNC(mc68901_device::i0_w));
+
+ ls259_device &bitlatch(LS259(config, "bitlatch")); // U17
+ bitlatch.q_out_cb<0>().set("novram", FUNC(eeprom_serial_x24c44_device::di_write));
+ bitlatch.q_out_cb<1>().set("novram", FUNC(eeprom_serial_x24c44_device::clk_write));
+ bitlatch.q_out_cb<2>().set("novram", FUNC(eeprom_serial_x24c44_device::cs_write));
+}
+
+ROM_START(qts1)
+ ROM_REGION(0x8000, "firmware", 0)
+ ROM_SYSTEM_BIOS(0, "v2.3", "Firmware Version 2.3")
+ ROMX_LOAD("tti_10012000_rev2.3.bin", 0x0000, 0x8000, CRC(95a5bce8) SHA1(46d7c99e37ca5598aec2062dfd9759853a237c14), ROM_BIOS(0))
+ ROM_SYSTEM_BIOS(1, "v1.7", "Firmware Version 1.7")
+ ROMX_LOAD("tti_10012000_rev1.7.bin", 0x0000, 0x8000, CRC(6660c059) SHA1(05d97009b5b8034dda520f655c73c474da97f822), ROM_BIOS(1))
+ROM_END
+
+const tiny_rom_entry *qts1_device::device_rom_region() const
+{
+ return ROM_NAME(qts1);
+}
diff --git a/src/devices/bus/qbus/qtx.h b/src/devices/bus/qbus/qtx.h
new file mode 100644
index 00000000000..ae48ecd7150
--- /dev/null
+++ b/src/devices/bus/qbus/qtx.h
@@ -0,0 +1,54 @@
+// license:BSD-3-Clause
+// copyright-holders:AJR
+
+#ifndef MAME_BUS_QBUS_QTX_H
+#define MAME_BUS_QBUS_QTX_H
+
+#pragma once
+
+#include "qbus.h"
+#include "machine/mc68901.h"
+#include "machine/ncr53c90.h"
+
+
+//**************************************************************************
+// TYPE DEFINITIONS
+//**************************************************************************
+
+// ======================> qts1_device
+
+class qts1_device : public device_t, public device_qbus_card_interface
+{
+public:
+ // device type constructor
+ qts1_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock);
+
+protected:
+ // device-level overrides
+ virtual void device_start() override ATTR_COLD;
+ virtual void device_add_mconfig(machine_config &config) override ATTR_COLD;
+ virtual const tiny_rom_entry *device_rom_region() const override ATTR_COLD;
+
+private:
+ u8 asc_r(offs_t offset);
+ void asc_w(offs_t offset, u8 data);
+ void dma_address_w(offs_t offset, u8 data);
+ u8 io_status_r();
+ void channel_w(u8 data);
+
+ void asc_config(device_t *device);
+
+ void prg_map(address_map &map) ATTR_COLD;
+ void fc7_map(address_map &map) ATTR_COLD;
+
+ required_device<cpu_device> m_localcpu;
+ required_device<mc68901_device> m_mfp;
+ required_device<ncr53c90a_device> m_asc;
+
+ u32 m_dma_address;
+};
+
+// device type declaration
+DECLARE_DEVICE_TYPE(TTI_QTS1, qts1_device)
+
+#endif // MAME_BUS_QBUS_QTX_H
diff --git a/src/devices/bus/qbus/tdl12.cpp b/src/devices/bus/qbus/tdl12.cpp
new file mode 100644
index 00000000000..7556669fe01
--- /dev/null
+++ b/src/devices/bus/qbus/tdl12.cpp
@@ -0,0 +1,137 @@
+// license:BSD-3-Clause
+// copyright-holders:AJR
+/***********************************************************************************************************************************
+
+ TDL-12 SCSI Host Adapter (© 1985 T.D. Systems)
+
+************************************************************************************************************************************/
+
+#include "emu.h"
+#include "tdl12.h"
+
+#include "bus/nscsi/devices.h"
+#include "cpu/z80/z80.h"
+#include "machine/eepromser.h"
+#include "machine/ncr5380.h"
+#include "machine/z8536.h"
+
+
+// device type definition
+DEFINE_DEVICE_TYPE(TDL12, tdl12_device, "tdl12", "TDL-12 SCSI Host Adapter")
+
+
+tdl12_device::tdl12_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock)
+ : device_t(mconfig, TDL12, tag, owner, clock)
+ , device_qbus_card_interface(mconfig, *this)
+ , m_tdcpu(*this, "tdcpu")
+{
+}
+
+void tdl12_device::device_start()
+{
+}
+
+u8 tdl12_device::latch_r(offs_t offset)
+{
+ if (!machine().side_effects_disabled())
+ logerror("%s: Reading from latch %c\n", machine().describe_context(), offset ? 'H' : 'L');
+ return 0;
+}
+
+void tdl12_device::latch_w(offs_t offset, u8 data)
+{
+ logerror("%s: Writing %02X to latch %c\n", machine().describe_context(), data, offset ? 'H' : 'L');
+}
+
+u8 tdl12_device::in40_r()
+{
+ // Used as low 8 bits of jump offset
+ // Valid values include 0x00, 0x10, 0x20, 0x30, 0x40, 0x50, 0x60, 0x70, 0x80, 0x90, 0xa0, 0xb0, 0xd0, 0xff
+ return 0xff;
+}
+
+void tdl12_device::out40_w(u8 data)
+{
+ logerror("%s: Output %02X to port 40\n", machine().describe_context(), data);
+}
+
+void tdl12_device::out70_w(u8 data)
+{
+ // Data written is irrelevant
+ logerror("%s: Output to port 70\n", machine().describe_context());
+}
+
+void tdl12_device::out74_w(u8 data)
+{
+ // Data written is irrelevant
+ logerror("%s: Output to port 74\n", machine().describe_context());
+}
+
+void tdl12_device::mem_map(address_map &map)
+{
+ map(0x0000, 0x3fff).rom().region("firmware", 0);
+ map(0x4000, 0x47ff).ram();
+ map(0x8000, 0x8001).rw(FUNC(tdl12_device::latch_r), FUNC(tdl12_device::latch_w));
+}
+
+void tdl12_device::io_map(address_map &map)
+{
+ map.global_mask(0xff);
+ map(0x00, 0x03).rw("cio", FUNC(z8536_device::read), FUNC(z8536_device::write));
+ map(0x40, 0x40).rw(FUNC(tdl12_device::in40_r), FUNC(tdl12_device::out40_w));
+ map(0x70, 0x70).w(FUNC(tdl12_device::out70_w));
+ map(0x74, 0x74).w(FUNC(tdl12_device::out74_w));
+ map(0x80, 0x87).m("scsi:7:ncr5380", FUNC(ncr5380_device::map));
+}
+
+void tdl12_device::device_add_mconfig(machine_config &config)
+{
+ Z80(config, m_tdcpu, 12_MHz_XTAL / 2); // covered by "TD SYSTEMS INC." sticker (most likely Z80B)
+ m_tdcpu->set_addrmap(AS_PROGRAM, &tdl12_device::mem_map);
+ m_tdcpu->set_addrmap(AS_IO, &tdl12_device::io_map);
+
+ z8536_device &cio(Z8536(config, "cio", 12_MHz_XTAL / 2)); // ST Z8536AB1
+ cio.irq_wr_cb().set_inputline(m_tdcpu, 0);
+ cio.pb_wr_cb().set("eeprom", FUNC(eeprom_serial_93cxx_device::clk_write)).bit(0);
+ cio.pb_wr_cb().append("eeprom", FUNC(eeprom_serial_93cxx_device::di_write)).bit(1);
+ cio.pc_rd_cb().set("eeprom", FUNC(eeprom_serial_93cxx_device::do_read)).lshift(3);
+ cio.pc_wr_cb().set("eeprom", FUNC(eeprom_serial_93cxx_device::cs_write)).bit(2);
+
+ NSCSI_BUS(config, "scsi");
+ NSCSI_CONNECTOR(config, "scsi:0", default_scsi_devices, nullptr);
+ NSCSI_CONNECTOR(config, "scsi:1", default_scsi_devices, nullptr);
+ NSCSI_CONNECTOR(config, "scsi:2", default_scsi_devices, nullptr);
+ NSCSI_CONNECTOR(config, "scsi:3", default_scsi_devices, nullptr);
+ NSCSI_CONNECTOR(config, "scsi:4", default_scsi_devices, nullptr);
+ NSCSI_CONNECTOR(config, "scsi:5", default_scsi_devices, nullptr);
+ NSCSI_CONNECTOR(config, "scsi:6", default_scsi_devices, nullptr);
+ NSCSI_CONNECTOR(config, "scsi:7").option_set("ncr5380", NCR5380).machine_config([this](device_t *device) {
+ (void)this;
+ });
+
+ EEPROM_93C46_16BIT(config, "eeprom"); // NMC9346N
+}
+
+
+ROM_START(tdl12)
+ ROM_REGION(0x4000, "firmware", 0)
+ ROM_LOAD("tdl-12_v180.bin", 0x0000, 0x4000, CRC(fd0f4468) SHA1(1cf0bf8702747ff3047691d2b661bb08d40754f0)) // Am(27128?)-25DC
+
+ ROM_REGION16_LE(0x40, "proms", 0) // probably PDP-11 bootstrap code (address & CE inputs are in common)
+ ROM_LOAD16_BYTE("m_tdl-11.bin", 0x00, 0x20, NO_DUMP) // N82S123AN
+ ROM_LOAD16_BYTE("m_tdl-12.bin", 0x01, 0x20, NO_DUMP) // N82S123AN
+
+ ROM_REGION(0x7a1, "plds", 0)
+ ROM_LOAD("mst_tdl-13.bin", 0x000, 0x117, NO_DUMP) // TIBPAL16L8-25CN (socketed, next to A/B jumpers; also decodes address)
+ ROM_LOAD("mst_tdl-21.bin", 0x117, 0x117, NO_DUMP) // TIBPAL16L8-25CN
+ ROM_LOAD("mst_tdl-26.bin", 0x22e, 0x117, NO_DUMP) // TIBPAL16L8-25CN
+ ROM_LOAD("mst_tdl-31.bin", 0x345, 0x117, NO_DUMP) // TIBPAL16L8-25CN
+ ROM_LOAD("mst_tdl-40.bin", 0x45c, 0x117, NO_DUMP) // TIBPAL16L8-25CN
+ ROM_LOAD("mst_tdl-41.bin", 0x573, 0x117, NO_DUMP) // TIBPAL16L8-25CN
+ ROM_LOAD("mst_tdl-42.bin", 0x68a, 0x117, NO_DUMP) // TIBPAL16L8-25CN
+ROM_END
+
+const tiny_rom_entry *tdl12_device::device_rom_region() const
+{
+ return ROM_NAME(tdl12);
+}
diff --git a/src/devices/bus/qbus/tdl12.h b/src/devices/bus/qbus/tdl12.h
new file mode 100644
index 00000000000..46716f98ff7
--- /dev/null
+++ b/src/devices/bus/qbus/tdl12.h
@@ -0,0 +1,42 @@
+// license:BSD-3-Clause
+// copyright-holders:AJR
+
+#ifndef MAME_BUS_QBUS_TDL12_H
+#define MAME_BUS_QBUS_TDL12_H
+
+#pragma once
+
+#include "qbus.h"
+#include "machine/ncr5380.h"
+
+
+class tdl12_device : public device_t, public device_qbus_card_interface
+{
+public:
+ // device type constructor
+ tdl12_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock);
+
+protected:
+ // device-level overrides
+ virtual void device_start() override ATTR_COLD;
+ virtual void device_add_mconfig(machine_config &config) override ATTR_COLD;
+ virtual const tiny_rom_entry *device_rom_region() const override ATTR_COLD;
+
+private:
+ u8 latch_r(offs_t offset);
+ void latch_w(offs_t offset, u8 data);
+ u8 in40_r();
+ void out40_w(u8 data);
+ void out70_w(u8 data);
+ void out74_w(u8 data);
+
+ void mem_map(address_map &map) ATTR_COLD;
+ void io_map(address_map &map) ATTR_COLD;
+
+ required_device<cpu_device> m_tdcpu;
+};
+
+// device type declaration
+DECLARE_DEVICE_TYPE(TDL12, tdl12_device)
+
+#endif // MAME_BUS_QBUS_TDL12_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..4e3a4cb916e
--- /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 ATTR_COLD;
+ virtual void device_add_mconfig(machine_config &config) override ATTR_COLD;
+
+ 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..75e8228e0f8 100644
--- a/src/devices/bus/ql/cst_q_plus4.h
+++ b/src/devices/bus/ql/cst_q_plus4.h
@@ -30,21 +30,21 @@ public:
protected:
// device-level overrides
- virtual void device_start() override;
+ virtual void device_start() override ATTR_COLD;
// optional information overrides
- virtual const tiny_rom_entry *device_rom_region() const override;
- virtual void device_add_mconfig(machine_config &config) override;
+ virtual const tiny_rom_entry *device_rom_region() const override ATTR_COLD;
+ virtual void device_add_mconfig(machine_config &config) override ATTR_COLD;
// device_ql_expansion_card_interface overrides
virtual uint8_t read(offs_t offset, uint8_t data) override;
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/cst_qdisc.h b/src/devices/bus/ql/cst_qdisc.h
index fdd492f1230..90df785ce98 100644
--- a/src/devices/bus/ql/cst_qdisc.h
+++ b/src/devices/bus/ql/cst_qdisc.h
@@ -29,11 +29,11 @@ public:
cst_ql_disc_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;
+ virtual const tiny_rom_entry *device_rom_region() const override ATTR_COLD;
protected:
// device-level overrides
- virtual void device_start() override;
+ virtual void device_start() override ATTR_COLD;
// device_ql_expansion_card_interface overrides
virtual uint8_t read(offs_t offset, uint8_t data) override;
diff --git a/src/devices/bus/ql/cumana_fdi.h b/src/devices/bus/ql/cumana_fdi.h
index 2080251fcf3..89006faeec7 100644
--- a/src/devices/bus/ql/cumana_fdi.h
+++ b/src/devices/bus/ql/cumana_fdi.h
@@ -28,11 +28,11 @@ public:
cumana_floppy_disk_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;
+ virtual const tiny_rom_entry *device_rom_region() const override ATTR_COLD;
protected:
// device-level overrides
- virtual void device_start() override;
+ virtual void device_start() override ATTR_COLD;
// device_ql_expansion_card_interface overrides
virtual uint8_t read(offs_t offset, uint8_t data) override;
diff --git a/src/devices/bus/ql/exp.cpp b/src/devices/bus/ql/exp.cpp
index 433f8e257ff..ab2bb007d80 100644
--- a/src/devices/bus/ql/exp.cpp
+++ b/src/devices/bus/ql/exp.cpp
@@ -28,7 +28,7 @@ DEFINE_DEVICE_TYPE(QL_EXPANSION_SLOT, ql_expansion_slot_device, "ql_expansion_sl
//-------------------------------------------------
device_ql_expansion_card_interface::device_ql_expansion_card_interface(const machine_config &mconfig, device_t &device) :
- device_slot_card_interface(mconfig, device),
+ device_interface(device, "qlexp"),
m_slot(dynamic_cast<ql_expansion_slot_device *>(device.owner())),
m_romoeh(0)
{
@@ -37,8 +37,6 @@ device_ql_expansion_card_interface::device_ql_expansion_card_interface(const mac
void device_ql_expansion_card_interface::interface_post_start()
{
- device_slot_card_interface::interface_post_start();
-
device().save_item(NAME(m_romoeh));
}
@@ -54,11 +52,12 @@ void device_ql_expansion_card_interface::interface_post_start()
ql_expansion_slot_device::ql_expansion_slot_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) :
device_t(mconfig, QL_EXPANSION_SLOT, tag, owner, clock),
- device_slot_interface(mconfig, *this),
+ device_single_card_slot_interface<device_ql_expansion_card_interface>(mconfig, *this),
m_write_ipl0l(*this),
m_write_ipl1l(*this),
m_write_berrl(*this),
- m_write_extintl(*this), m_card(nullptr)
+ m_write_extintl(*this),
+ m_card(nullptr)
{
}
@@ -67,29 +66,13 @@ ql_expansion_slot_device::ql_expansion_slot_device(const machine_config &mconfig
// device_start - device-specific startup
//-------------------------------------------------
-void ql_expansion_slot_device::device_validity_check(validity_checker &valid) const
-{
- device_t *const card(get_card_device());
- if (card && !dynamic_cast<device_ql_expansion_card_interface *>(card))
- osd_printf_error("Card device %s (%s) does not implement device_ql_expansion_card_interface\n", card->tag(), card->name());
-}
-
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 = dynamic_cast<device_ql_expansion_card_interface *>(get_card_device());
+ m_card = get_card_device();
}
void ql_expansion_slot_device::device_start()
{
- device_t *const card(get_card_device());
- if (card && !m_card)
- throw emu_fatalerror("ql_expansion_slot_device: card device %s (%s) does not implement device_ql_expansion_card_interface\n", card->tag(), card->name());
}
diff --git a/src/devices/bus/ql/exp.h b/src/devices/bus/ql/exp.h
index 43e8a7b77d5..32d24f85862 100644
--- a/src/devices/bus/ql/exp.h
+++ b/src/devices/bus/ql/exp.h
@@ -56,7 +56,7 @@
class ql_expansion_slot_device;
-class device_ql_expansion_card_interface : public device_slot_card_interface
+class device_ql_expansion_card_interface : public device_interface
{
friend class ql_expansion_slot_device;
@@ -79,7 +79,7 @@ protected:
// ======================> ql_expansion_slot_device
-class ql_expansion_slot_device : public device_t, public device_slot_interface
+class ql_expansion_slot_device : public device_t, public device_single_card_slot_interface<device_ql_expansion_card_interface>
{
public:
// construction/destruction
@@ -102,19 +102,18 @@ 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
- virtual void device_validity_check(validity_checker &valid) const override;
- virtual void device_resolve_objects() override;
- virtual void device_start() override;
+ virtual void device_resolve_objects() override ATTR_COLD;
+ virtual void device_start() override ATTR_COLD;
devcb_write_line m_write_ipl0l;
devcb_write_line m_write_ipl1l;
diff --git a/src/devices/bus/ql/kempston_di.h b/src/devices/bus/ql/kempston_di.h
index cc75a5fe0fc..c7e942cbd7f 100644
--- a/src/devices/bus/ql/kempston_di.h
+++ b/src/devices/bus/ql/kempston_di.h
@@ -6,8 +6,8 @@
**********************************************************************/
-#ifndef MAME_BUS_QQL_KEMPSTON_DI_H
-#define MAME_BUS_QQL_KEMPSTON_DI_H
+#ifndef MAME_BUS_QL_KEMPSTON_DI_H
+#define MAME_BUS_QL_KEMPSTON_DI_H
#pragma once
@@ -28,11 +28,11 @@ public:
kempston_disk_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;
+ virtual const tiny_rom_entry *device_rom_region() const override ATTR_COLD;
protected:
// device-level overrides
- virtual void device_start() override;
+ virtual void device_start() override ATTR_COLD;
// device_ql_expansion_card_interface overrides
virtual uint8_t read(offs_t offset, uint8_t data) override;
@@ -44,4 +44,4 @@ protected:
DECLARE_DEVICE_TYPE(KEMPSTON_DISK_INTERFACE, kempston_disk_interface_device)
-#endif // MAME_BUS_QQL_KEMPSTON_DI_H
+#endif // MAME_BUS_QL_KEMPSTON_DI_H
diff --git a/src/devices/bus/ql/miracle_gold_card.h b/src/devices/bus/ql/miracle_gold_card.h
index 7ed9d0e2eb8..1f3dc5b73db 100644
--- a/src/devices/bus/ql/miracle_gold_card.h
+++ b/src/devices/bus/ql/miracle_gold_card.h
@@ -28,11 +28,11 @@ public:
miracle_gold_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 const tiny_rom_entry *device_rom_region() const override ATTR_COLD;
protected:
// device-level overrides
- virtual void device_start() override;
+ virtual void device_start() override ATTR_COLD;
// device_ql_expansion_card_interface overrides
virtual uint8_t read(offs_t offset, uint8_t data) override;
diff --git a/src/devices/bus/ql/miracle_hd.h b/src/devices/bus/ql/miracle_hd.h
index 983dce66f8b..ec89dbcb1bc 100644
--- a/src/devices/bus/ql/miracle_hd.h
+++ b/src/devices/bus/ql/miracle_hd.h
@@ -6,8 +6,8 @@
**********************************************************************/
-#ifndef MAME_BUS_QL_MIRACLE_HD
-#define MAME_BUS_QL_MIRACLE_HD
+#ifndef MAME_BUS_QL_MIRACLE_HD_H
+#define MAME_BUS_QL_MIRACLE_HD_H
#pragma once
@@ -29,11 +29,11 @@ public:
miracle_hard_disk_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 const tiny_rom_entry *device_rom_region() const override ATTR_COLD;
protected:
// device-level overrides
- virtual void device_start() override;
+ virtual void device_start() override ATTR_COLD;
// device_ql_rom_cartridge_card_interface overrides
virtual uint8_t read(offs_t offset, uint8_t data) override;
@@ -44,4 +44,4 @@ protected:
// device type definition
DECLARE_DEVICE_TYPE(MIRACLE_HARD_DISK, miracle_hard_disk_device)
-#endif // MAME_BUS_QL_MIRACLE_HD
+#endif // MAME_BUS_QL_MIRACLE_HD_H
diff --git a/src/devices/bus/ql/mp_fdi.h b/src/devices/bus/ql/mp_fdi.h
index 3fc9d9d8c83..5a27246e02a 100644
--- a/src/devices/bus/ql/mp_fdi.h
+++ b/src/devices/bus/ql/mp_fdi.h
@@ -27,11 +27,11 @@ public:
micro_peripherals_floppy_disk_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;
+ virtual const tiny_rom_entry *device_rom_region() const override ATTR_COLD;
protected:
// device-level overrides
- virtual void device_start() override;
+ virtual void device_start() override ATTR_COLD;
// device_ql_expansion_card_interface overrides
virtual uint8_t read(offs_t offset, uint8_t data) override;
diff --git a/src/devices/bus/ql/opd_basic_master.h b/src/devices/bus/ql/opd_basic_master.h
index 3592823dd2b..431176d3e3e 100644
--- a/src/devices/bus/ql/opd_basic_master.h
+++ b/src/devices/bus/ql/opd_basic_master.h
@@ -28,11 +28,11 @@ public:
opd_basic_master_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 const tiny_rom_entry *device_rom_region() const override ATTR_COLD;
protected:
// device-level overrides
- virtual void device_start() override;
+ virtual void device_start() override ATTR_COLD;
// device_ql_expansion_card_interface overrides
virtual uint8_t read(offs_t offset, uint8_t data) override;
diff --git a/src/devices/bus/ql/pcml_qdisk.h b/src/devices/bus/ql/pcml_qdisk.h
index cedd3f953f7..e0cb7d01e33 100644
--- a/src/devices/bus/ql/pcml_qdisk.h
+++ b/src/devices/bus/ql/pcml_qdisk.h
@@ -28,11 +28,11 @@ public:
pcml_q_disk_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;
+ virtual const tiny_rom_entry *device_rom_region() const override ATTR_COLD;
protected:
// device-level overrides
- virtual void device_start() override;
+ virtual void device_start() override ATTR_COLD;
// device_ql_expansion_card_interface overrides
virtual uint8_t read(offs_t offset, uint8_t data) override;
diff --git a/src/devices/bus/ql/qubide.cpp b/src/devices/bus/ql/qubide.cpp
index 10583d28023..7ed66ef8886 100644
--- a/src/devices/bus/ql/qubide.cpp
+++ b/src/devices/bus/ql/qubide.cpp
@@ -211,15 +211,15 @@ uint8_t qubide_device::read(offs_t offset, uint8_t data)
switch (offset & 0x0f)
{
case 0:
- data = m_ata->read_cs1(0x07, 0xff);
+ data = m_ata->cs1_r(0x07, 0xff);
break;
default:
- data = m_ata->read_cs0(offset & 0x07, 0xff);
+ data = m_ata->cs0_r(offset & 0x07, 0xff);
break;
case 0x08: case 0x0a: case 0x0c:
- m_ata_data = m_ata->read_cs0(0);
+ m_ata_data = m_ata->cs0_r(0);
data = m_ata_data >> 8;
break;
@@ -229,7 +229,7 @@ uint8_t qubide_device::read(offs_t offset, uint8_t data)
break;
case 0x0e: case 0x0f:
- data = m_ata->read_cs1(0x05, 0xff);
+ data = m_ata->cs1_r(0x05, 0xff);
break;
}
}
@@ -256,7 +256,7 @@ void qubide_device::write(offs_t offset, uint8_t data)
switch (offset & 0x0f)
{
case 0: case 0x0e: case 0x0f:
- m_ata->write_cs1(0x05, data, 0xff);
+ m_ata->cs1_w(0x05, data, 0xff);
break;
case 0x08: case 0x0a: case 0x0c:
@@ -266,11 +266,11 @@ void qubide_device::write(offs_t offset, uint8_t data)
case 0x09: case 0x0b: case 0x0d:
m_ata_data = (m_ata_data & 0xff00) | data;
- m_ata->write_cs0(0, m_ata_data);
+ m_ata->cs0_w(0, m_ata_data);
break;
default:
- m_ata->write_cs0(offset & 0x07, data, 0xff);
+ m_ata->cs0_w(offset & 0x07, data, 0xff);
break;
}
}
diff --git a/src/devices/bus/ql/qubide.h b/src/devices/bus/ql/qubide.h
index 5e1ac6d1860..8685e5c247c 100644
--- a/src/devices/bus/ql/qubide.h
+++ b/src/devices/bus/ql/qubide.h
@@ -12,7 +12,7 @@
#pragma once
#include "exp.h"
-#include "machine/ataintf.h"
+#include "bus/ata/ataintf.h"
@@ -30,13 +30,13 @@ public:
protected:
// device-level overrides
- virtual void device_start() override;
- virtual void device_reset() override;
+ virtual void device_start() override ATTR_COLD;
+ virtual void device_reset() override ATTR_COLD;
// optional information 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 const tiny_rom_entry *device_rom_region() const override ATTR_COLD;
+ virtual void device_add_mconfig(machine_config &config) override ATTR_COLD;
+ virtual ioport_constructor device_input_ports() const override ATTR_COLD;
// device_ql_expansion_card_interface overrides
virtual uint8_t read(offs_t offset, uint8_t data) override;
diff --git a/src/devices/bus/ql/rom.cpp b/src/devices/bus/ql/rom.cpp
index 28bc29d00f4..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>
+
//**************************************************************************
@@ -28,8 +30,7 @@ DEFINE_DEVICE_TYPE(QL_ROM_CARTRIDGE_SLOT, ql_rom_cartridge_slot_device, "ql_rom_
//-------------------------------------------------
device_ql_rom_cartridge_card_interface::device_ql_rom_cartridge_card_interface(const machine_config &mconfig, device_t &device) :
- device_slot_card_interface(mconfig, device),
- m_rom(*this, "rom"),
+ device_interface(device, "qlrom"),
m_slot(dynamic_cast<ql_rom_cartridge_slot_device *>(device.owner())),
m_romoeh(0)
{
@@ -47,8 +48,6 @@ device_ql_rom_cartridge_card_interface::~device_ql_rom_cartridge_card_interface(
void device_ql_rom_cartridge_card_interface::interface_post_start()
{
- device_slot_card_interface::interface_post_start();
-
device().save_item(NAME(m_romoeh));
}
@@ -64,8 +63,9 @@ void device_ql_rom_cartridge_card_interface::interface_post_start()
ql_rom_cartridge_slot_device::ql_rom_cartridge_slot_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) :
device_t(mconfig, QL_ROM_CARTRIDGE_SLOT, tag, owner, clock),
- device_slot_interface(mconfig, *this),
- device_image_interface(mconfig, *this), m_card(nullptr)
+ device_single_card_slot_interface<device_ql_rom_cartridge_card_interface>(mconfig, *this),
+ device_cartrom_image_interface(mconfig, *this),
+ m_card(nullptr)
{
}
@@ -73,24 +73,13 @@ ql_rom_cartridge_slot_device::ql_rom_cartridge_slot_device(const machine_config
//-------------------------------------------------
// device_start - device-specific startup
//-------------------------------------------------
-
-void ql_rom_cartridge_slot_device::device_validity_check(validity_checker &valid) const
-{
- device_t *const card(get_card_device());
- if (card && !dynamic_cast<device_ql_rom_cartridge_card_interface *>(card))
- osd_printf_error("Card device %s (%s) does not implement device_ql_rom_cartridge_card_interface\n", card->tag(), card->name());
-}
-
void ql_rom_cartridge_slot_device::device_resolve_objects()
{
- m_card = dynamic_cast<device_ql_rom_cartridge_card_interface *>(get_card_device());
+ m_card = get_card_device();
}
void ql_rom_cartridge_slot_device::device_start()
{
- device_t *const card(get_card_device());
- if (card && !m_card)
- throw emu_fatalerror("ql_rom_cartridge_slot_device: card device %s (%s) does not implement device_ql_rom_cartridge_card_interface\n", card->tag(), card->name());
}
@@ -98,18 +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)
{
- size_t size;
-
if (!loaded_through_softlist())
{
- size = length();
-
- m_card->m_rom.allocate(size);
- fread(m_card->m_rom, size);
+ 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
{
@@ -117,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 0c8ec4a6bca..b9bccfc21aa 100644
--- a/src/devices/bus/ql/rom.h
+++ b/src/devices/bus/ql/rom.h
@@ -30,7 +30,7 @@
#pragma once
-#include "softlist_dev.h"
+#include "imagedev/cartrom.h"
//**************************************************************************
@@ -41,7 +41,7 @@
class ql_rom_cartridge_slot_device;
-class device_ql_rom_cartridge_card_interface : public device_slot_card_interface
+class device_ql_rom_cartridge_card_interface : public device_interface
{
friend class ql_rom_cartridge_slot_device;
@@ -58,7 +58,7 @@ protected:
virtual void interface_post_start() override;
- optional_shared_ptr<uint8_t> m_rom;
+ std::unique_ptr<uint8_t[]> m_rom;
ql_rom_cartridge_slot_device *const m_slot;
@@ -69,8 +69,8 @@ protected:
// ======================> ql_rom_cartridge_slot_device
class ql_rom_cartridge_slot_device : public device_t,
- public device_slot_interface,
- public device_image_interface
+ public device_single_card_slot_interface<device_ql_rom_cartridge_card_interface>,
+ public device_cartrom_image_interface
{
public:
// construction/destruction
@@ -88,29 +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
- virtual void device_validity_check(validity_checker &valid) const override;
- virtual void device_resolve_objects() override;
- virtual void device_start() override;
-
- // image-level overrides
- virtual image_init_result call_load() override;
- virtual const software_list_loader &get_software_list_loader() const override { return rom_software_list_loader::instance(); }
-
- virtual iodevice_t image_type() const override { return IO_CARTSLOT; }
-
- virtual bool is_readable() const override { return 1; }
- virtual bool is_writeable() const override { return 0; }
- virtual bool is_creatable() const override { return 0; }
- virtual bool must_be_loaded() const override { return 0; }
- virtual bool is_reset_on_load() const override { return 1; }
- virtual const char *image_interface() const override { return "ql_cart"; }
- virtual const char *file_extensions() const override { return "rom,bin"; }
-
- // slot interface overrides
+ // device_t implementation
+ virtual void device_resolve_objects() override ATTR_COLD;
+ virtual void device_start() override ATTR_COLD;
+
+ // 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"; }
+
+ // 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 1af96f2de81..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"
+
//**************************************************************************
@@ -62,16 +64,18 @@ static void sandy_super_disk_floppies(device_slot_interface &device)
// FLOPPY_FORMATS( floppy_formats )
//-------------------------------------------------
-FLOPPY_FORMATS_MEMBER( sandy_super_disk_device::floppy_formats )
- FLOPPY_QL_FORMAT
-FLOPPY_FORMATS_END
+void sandy_super_disk_device::floppy_formats(format_registration &fr)
+{
+ fr.add_mfm_containers();
+ fr.add(FLOPPY_QL_FORMAT);
+}
//-------------------------------------------------
// centronics
//-------------------------------------------------
-WRITE_LINE_MEMBER( sandy_super_disk_device::busy_w )
+void sandy_super_disk_device::busy_w(int state)
{
m_busy = state;
check_interrupt();
@@ -85,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));
@@ -108,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"),
@@ -228,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 5a264272e12..75f99aef7bf 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"
@@ -33,27 +32,26 @@ public:
protected:
// device-level overrides
- virtual void device_start() override;
- virtual void device_reset() override;
+ virtual void device_start() override ATTR_COLD;
+ virtual void device_reset() override ATTR_COLD;
// optional information overrides
- virtual const tiny_rom_entry *device_rom_region() const override;
- virtual void device_add_mconfig(machine_config &config) override;
+ virtual const tiny_rom_entry *device_rom_region() const override ATTR_COLD;
+ virtual void device_add_mconfig(machine_config &config) override ATTR_COLD;
// device_ql_expansion_card_interface overrides
virtual uint8_t read(offs_t offset, uint8_t data) override;
virtual void write(offs_t offset, uint8_t data) override;
private:
- WRITE_LINE_MEMBER( busy_w );
+ void busy_w(int state);
- DECLARE_FLOPPY_FORMATS( floppy_formats );
+ 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 9fbd2f49c77..ebcc731d07e 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"
+
//**************************************************************************
@@ -75,16 +77,18 @@ static void sandy_superqboard_floppies(device_slot_interface &device)
// FLOPPY_FORMATS( floppy_formats )
//-------------------------------------------------
-FLOPPY_FORMATS_MEMBER( sandy_superqboard_device::floppy_formats )
- FLOPPY_QL_FORMAT
-FLOPPY_FORMATS_END
+void sandy_superqboard_device::floppy_formats(format_registration &fr)
+{
+ fr.add_mfm_containers();
+ fr.add(FLOPPY_QL_FORMAT);
+}
//-------------------------------------------------
// centronics
//-------------------------------------------------
-WRITE_LINE_MEMBER( sandy_superqboard_device::busy_w )
+void sandy_superqboard_device::busy_w(int state)
{
if (state)
{
@@ -106,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));
@@ -164,10 +168,10 @@ INPUT_CHANGED_MEMBER( sandy_superqboard_device::mouse_y_changed )
INPUT_PORTS_START( sandy_superqmouse )
PORT_START("mouse_x")
- PORT_BIT( 0xff, 0x00, IPT_MOUSE_X ) PORT_SENSITIVITY(50) PORT_KEYDELTA(5) PORT_MINMAX(0, 255) PORT_CHANGED_MEMBER(DEVICE_SELF, sandy_superqboard_device, mouse_x_changed, 0)
+ PORT_BIT( 0xff, 0x00, IPT_MOUSE_X ) PORT_SENSITIVITY(50) PORT_KEYDELTA(5) PORT_MINMAX(0, 255) PORT_CHANGED_MEMBER(DEVICE_SELF, FUNC(sandy_superqboard_device::mouse_x_changed), 0)
PORT_START("mouse_y")
- PORT_BIT( 0xff, 0x00, IPT_MOUSE_Y ) PORT_SENSITIVITY(50) PORT_KEYDELTA(5) PORT_MINMAX(0, 255) PORT_CHANGED_MEMBER(DEVICE_SELF, sandy_superqboard_device, mouse_y_changed, 0)
+ PORT_BIT( 0xff, 0x00, IPT_MOUSE_Y ) PORT_SENSITIVITY(50) PORT_KEYDELTA(5) PORT_MINMAX(0, 255) PORT_CHANGED_MEMBER(DEVICE_SELF, FUNC(sandy_superqboard_device::mouse_y_changed), 0)
PORT_START("mouse_buttons")
PORT_BIT( 0x02, IP_ACTIVE_LOW, IPT_BUTTON3 ) PORT_NAME("Middle Mouse Button") PORT_CODE(MOUSECODE_BUTTON3)
@@ -214,12 +218,11 @@ 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"),
- m_ram(*this, "ram"),
+ m_ram(*this, "ram", ram_size, ENDIANNESS_BIG),
m_buttons(*this, "mouse_buttons"),
m_ram_size(ram_size),
m_fd6(0),
@@ -250,9 +253,6 @@ sandy_superqmouse_512k_device::sandy_superqmouse_512k_device(const machine_confi
void sandy_superqboard_device::device_start()
{
- // allocate memory
- m_ram.allocate(m_ram_size);
-
// state saving
save_item(NAME(m_fd6));
save_item(NAME(m_fd7));
@@ -378,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 94bfe0c7dad..571e54e6209 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"
@@ -38,21 +37,21 @@ protected:
sandy_superqboard_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock, int ram_size);
// device-level overrides
- virtual void device_start() override;
- virtual void device_reset() override;
+ virtual void device_start() override ATTR_COLD;
+ virtual void device_reset() override ATTR_COLD;
// optional information overrides
- virtual const tiny_rom_entry *device_rom_region() const override;
- virtual void device_add_mconfig(machine_config &config) override;
+ virtual const tiny_rom_entry *device_rom_region() const override ATTR_COLD;
+ virtual void device_add_mconfig(machine_config &config) override ATTR_COLD;
// device_ql_expansion_card_interface overrides
virtual uint8_t read(offs_t offset, uint8_t data) override;
virtual void write(offs_t offset, uint8_t data) override;
private:
- WRITE_LINE_MEMBER( busy_w );
+ void busy_w(int state);
- DECLARE_FLOPPY_FORMATS( floppy_formats );
+ static void floppy_formats(format_registration &fr);
enum
{
@@ -69,12 +68,11 @@ 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;
- optional_shared_ptr<uint8_t> m_ram;
+ memory_share_creator<uint8_t> m_ram;
optional_ioport m_buttons;
int m_ram_size;
@@ -104,7 +102,7 @@ public:
sandy_superqmouse_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;
+ virtual ioport_constructor device_input_ports() const override ATTR_COLD;
};
@@ -117,7 +115,7 @@ public:
sandy_superqmouse_512k_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;
+ virtual ioport_constructor device_input_ports() const override ATTR_COLD;
};
diff --git a/src/devices/bus/ql/std.cpp b/src/devices/bus/ql/std.cpp
index b1171c46336..7524cc1693d 100644
--- a/src/devices/bus/ql/std.cpp
+++ b/src/devices/bus/ql/std.cpp
@@ -49,9 +49,9 @@ void ql_standard_rom_cartridge_device::device_start()
uint8_t ql_standard_rom_cartridge_device::read(offs_t offset, uint8_t data)
{
- if (m_romoeh && m_rom.bytes())
+ if (m_romoeh && m_rom)
{
- data = m_rom[offset & m_rom.mask()];
+ data = m_rom[offset];
}
return data;
diff --git a/src/devices/bus/ql/std.h b/src/devices/bus/ql/std.h
index 823c3a70008..5e1572fa32c 100644
--- a/src/devices/bus/ql/std.h
+++ b/src/devices/bus/ql/std.h
@@ -29,7 +29,7 @@ public:
protected:
// device-level overrides
- virtual void device_start() override;
+ virtual void device_start() override ATTR_COLD;
// device_ql_rom_cartridge_card_interface overrides
virtual uint8_t read(offs_t offset, uint8_t data) override;
diff --git a/src/devices/bus/ql/trumpcard.cpp b/src/devices/bus/ql/trumpcard.cpp
index 473fc9bb78e..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"
//**************************************************************************
@@ -77,9 +78,11 @@ static void ql_trump_card_floppies(device_slot_interface &device)
// FLOPPY_FORMATS( floppy_formats )
//-------------------------------------------------
-FLOPPY_FORMATS_MEMBER( ql_trump_card_device::floppy_formats )
- FLOPPY_QL_FORMAT
-FLOPPY_FORMATS_END
+void ql_trump_card_device::floppy_formats(format_registration &fr)
+{
+ fr.add_mfm_containers();
+ fr.add(FLOPPY_QL_FORMAT);
+}
//-------------------------------------------------
@@ -89,8 +92,8 @@ FLOPPY_FORMATS_END
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);
}
@@ -111,10 +114,9 @@ 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"),
+ m_ram(*this, "ram", ram_size, ENDIANNESS_BIG),
m_ram_size(ram_size),
m_rom_en(false)
{
@@ -142,9 +144,6 @@ ql_trump_card_768k_device::ql_trump_card_768k_device(const machine_config &mconf
void ql_trump_card_device::device_start()
{
- // allocate memory
- m_ram.allocate(m_ram_size);
-
// state saving
save_item(NAME(m_rom_en));
}
@@ -248,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 d9926160928..6570e7f6cb0 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"
@@ -34,12 +33,12 @@ protected:
ql_trump_card_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock, int ram_size);
// device-level overrides
- virtual void device_start() override;
- virtual void device_reset() override;
+ virtual void device_start() override ATTR_COLD;
+ virtual void device_reset() override ATTR_COLD;
// optional information overrides
- virtual const tiny_rom_entry *device_rom_region() const override;
- virtual void device_add_mconfig(machine_config &config) override;
+ virtual const tiny_rom_entry *device_rom_region() const override ATTR_COLD;
+ virtual void device_add_mconfig(machine_config &config) override ATTR_COLD;
// device_ql_expansion_card_interface overrides
virtual uint8_t read(offs_t offset, uint8_t data) override;
@@ -47,13 +46,12 @@ protected:
private:
- DECLARE_FLOPPY_FORMATS( floppy_formats );
+ 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;
- optional_shared_ptr<uint8_t> m_ram;
+ memory_share_creator<uint8_t> m_ram;
int m_ram_size;
bool m_rom_en;
diff --git a/src/devices/bus/rc2014/cf.cpp b/src/devices/bus/rc2014/cf.cpp
new file mode 100644
index 00000000000..60e91639fd6
--- /dev/null
+++ b/src/devices/bus/rc2014/cf.cpp
@@ -0,0 +1,67 @@
+// license:BSD-3-Clause
+// copyright-holders:Miodrag Milanovic
+/***************************************************************************
+
+ RC2014 Compact Flash Module
+
+****************************************************************************/
+
+#include "emu.h"
+#include "cf.h"
+#include "bus/ata/ataintf.h"
+
+namespace {
+
+//**************************************************************************
+// RC2014 Compact Flash module
+// Module author: Spencer Owen
+//**************************************************************************
+
+class compact_flash_device : public device_t, public device_rc2014_card_interface
+{
+public:
+ // construction/destruction
+ compact_flash_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock);
+
+protected:
+ // device-level overrides
+ 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;
+
+ 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); }
+private:
+ required_device<ata_interface_device> m_ata;
+};
+
+compact_flash_device::compact_flash_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock)
+ : device_t(mconfig, RC2014_COMPACT_FLASH, tag, owner, clock)
+ , device_rc2014_card_interface(mconfig, *this)
+ , m_ata(*this, "ata")
+{
+}
+
+void compact_flash_device::device_start()
+{
+}
+
+void compact_flash_device::device_reset()
+{
+ // A15-A8 and A7 not connected
+ m_bus->installer(AS_IO)->install_readwrite_handler(0x10, 0x17, 0, 0xff80, 0, read8sm_delegate(*this, FUNC(compact_flash_device::ide_cs0_r)), write8sm_delegate(*this, FUNC(compact_flash_device::ide_cs0_w)));
+}
+
+void compact_flash_device::device_add_mconfig(machine_config &config)
+{
+ ATA_INTERFACE(config, m_ata).options(ata_devices, "cf", nullptr, true);
+}
+
+}
+//**************************************************************************
+// DEVICE DEFINITIONS
+//**************************************************************************
+
+DEFINE_DEVICE_TYPE_PRIVATE(RC2014_COMPACT_FLASH, device_rc2014_card_interface, compact_flash_device, "rc2014_cf", "RC2014 Compact Flash module")
diff --git a/src/devices/bus/rc2014/cf.h b/src/devices/bus/rc2014/cf.h
new file mode 100644
index 00000000000..c024735abd3
--- /dev/null
+++ b/src/devices/bus/rc2014/cf.h
@@ -0,0 +1,18 @@
+// license:BSD-3-Clause
+// copyright-holders:Miodrag Milanovic
+/**********************************************************************
+
+ RC2014 Compact Flash Module
+
+**********************************************************************/
+
+#ifndef MAME_BUS_RC2014_CF_H
+#define MAME_BUS_RC2014_CF_H
+
+#pragma once
+
+#include "bus/rc2014/rc2014.h"
+
+DECLARE_DEVICE_TYPE(RC2014_COMPACT_FLASH, device_rc2014_card_interface)
+
+#endif // MAME_BUS_RC2014_CF_H
diff --git a/src/devices/bus/rc2014/clock.cpp b/src/devices/bus/rc2014/clock.cpp
new file mode 100644
index 00000000000..4399c79e1e7
--- /dev/null
+++ b/src/devices/bus/rc2014/clock.cpp
@@ -0,0 +1,230 @@
+// license:BSD-3-Clause
+// copyright-holders:Miodrag Milanovic
+/***************************************************************************
+
+ RC2014 Clock Module
+
+****************************************************************************/
+
+#include "emu.h"
+#include "clock.h"
+#include "machine/clock.h"
+
+namespace {
+
+//**************************************************************************
+// RC2014 Clock module
+// Module author: Spencer Owen
+//**************************************************************************
+
+class single_clock_device : public device_t, public device_rc2014_card_interface
+{
+public:
+ // construction/destruction
+ single_clock_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock);
+
+protected:
+ // device-level overrides
+ virtual void device_start() override ATTR_COLD;
+ virtual void device_add_mconfig(machine_config &config) override ATTR_COLD;
+
+ 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)
+ : device_t(mconfig, RC2014_SINGLE_CLOCK, tag, owner, clock)
+ , device_rc2014_card_interface(mconfig, *this)
+{
+}
+
+void single_clock_device::device_start()
+{
+ m_bus->set_bus_clock(XTAL(7'372'800));
+}
+
+void single_clock_device::device_add_mconfig(machine_config &config)
+{
+ clock_device &clock(CLOCK(config, "clock", XTAL(7'372'800)));
+ clock.signal_handler().set(FUNC(single_clock_device::clk_w));
+}
+
+//**************************************************************************
+// RC2014 Dual Clock module
+// Module author: Spencer Owen
+//**************************************************************************
+
+//**************************************************************************
+// dual_clock_base
+//**************************************************************************
+
+class dual_clock_base : public device_t
+{
+protected:
+ // construction/destruction
+ dual_clock_base(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, u32 clock);
+
+ // device-level overrides
+ 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;
+ virtual ioport_constructor device_input_ports() const override ATTR_COLD;
+
+ virtual void clk_w(int state) = 0;
+ virtual void clk2_w(int state) = 0;
+
+ // base-class members
+ required_device<clock_device> m_clock_1;
+ required_device<clock_device> m_clock_2;
+ required_ioport m_clk_sel_1;
+ required_ioport m_clk_sel_2;
+};
+
+dual_clock_base::dual_clock_base(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, u32 clock)
+ : device_t(mconfig, type, tag, owner, clock)
+ , m_clock_1(*this, "clock1")
+ , m_clock_2(*this, "clock2")
+ , m_clk_sel_1(*this, "CLOCK1")
+ , m_clk_sel_2(*this, "CLOCK2")
+{
+}
+
+void dual_clock_base::device_start()
+{
+}
+
+static constexpr u32 clock_mapping[] =
+{
+ 7'372'800/1,
+ 7'372'800/2,
+ 7'372'800/3,
+ 7'372'800/6,
+ 7'372'800/8,
+ 7'372'800/12,
+ 7'372'800/24,
+ 10'000,
+ 0, // TODO: Support manual clocking (not possible for now)
+ 0 // TODO: Support external clocking
+};
+
+void dual_clock_base::device_reset()
+{
+ u32 clk1 = clock_mapping[m_clk_sel_1->read()];
+ m_clock_1->set_clock(clk1);
+
+ u32 clk2 = clock_mapping[m_clk_sel_2->read()];
+ m_clock_2->set_clock(clk2);
+
+ notify_clock_changed();
+}
+
+static INPUT_PORTS_START( dual_clock_jumpers )
+ PORT_START("CLOCK1")
+ PORT_CONFNAME( 0xf, 0x0, "Clock 1" )
+ PORT_CONFSETTING( 0x0, "7.3728 MHz" )
+ PORT_CONFSETTING( 0x1, "3.6864 MHz" )
+ PORT_CONFSETTING( 0x2, "2.4576 MHz" )
+ PORT_CONFSETTING( 0x3, "1.2288 MHz" )
+ PORT_CONFSETTING( 0x4, "0.9216 MHz" )
+ PORT_CONFSETTING( 0x5, "0.6144 MHz" )
+ PORT_CONFSETTING( 0x6, "0.3072 MHz" )
+ PORT_CONFSETTING( 0x7, "Slow" )
+ PORT_CONFSETTING( 0x8, "Manual" )
+ PORT_CONFSETTING( 0x9, "External" )
+ PORT_START("CLOCK2")
+ PORT_CONFNAME( 0xf, 0x0, "Clock 2" )
+ PORT_CONFSETTING( 0x0, "7.3728 MHz" )
+ PORT_CONFSETTING( 0x1, "3.6864 MHz" )
+ PORT_CONFSETTING( 0x2, "2.4576 MHz" )
+ PORT_CONFSETTING( 0x3, "1.2288 MHz" )
+ PORT_CONFSETTING( 0x4, "0.9216 MHz" )
+ PORT_CONFSETTING( 0x5, "0.6144 MHz" )
+ PORT_CONFSETTING( 0x6, "0.3072 MHz" )
+ PORT_CONFSETTING( 0x7, "Slow" )
+ PORT_CONFSETTING( 0x8, "Manual" )
+ PORT_CONFSETTING( 0x9, "External" )
+INPUT_PORTS_END
+
+ioport_constructor dual_clock_base::device_input_ports() const
+{
+ return INPUT_PORTS_NAME( dual_clock_jumpers );
+}
+
+void dual_clock_base::device_add_mconfig(machine_config &config)
+{
+ CLOCK(config, m_clock_1, 0);
+ m_clock_1->signal_handler().set(FUNC(dual_clock_base::clk_w));
+
+ CLOCK(config, m_clock_2, 0);
+ m_clock_2->signal_handler().set(FUNC(dual_clock_base::clk2_w));
+}
+
+//**************************************************************************
+// RC2014 Dual Clock module in extended bus
+//**************************************************************************
+
+class dual_clock_device : public dual_clock_base, public device_rc2014_ext_card_interface
+{
+public:
+ // construction/destruction
+ dual_clock_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock);
+
+protected:
+ // device-level overrides
+ virtual void device_reset() override ATTR_COLD;
+
+ // base-class overrides
+ 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)
+ : dual_clock_base(mconfig, RC2014_DUAL_CLOCK, tag, owner, clock)
+ , device_rc2014_ext_card_interface(mconfig, *this)
+{
+}
+
+void dual_clock_device::device_reset()
+{
+ m_bus->set_bus_clock(clock_mapping[m_clk_sel_1->read()]);
+ dual_clock_base::device_reset();
+}
+
+//**************************************************************************
+// RC2014 Dual Clock module in standard bus
+//**************************************************************************
+
+class dual_clock_device_40pin : public dual_clock_base, public device_rc2014_card_interface
+{
+public:
+ // construction/destruction
+ dual_clock_device_40pin(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock);
+
+protected:
+ // device-level overrides
+ virtual void device_reset() override ATTR_COLD;
+
+ // base-class overrides
+ 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)
+ : dual_clock_base(mconfig, RC2014_DUAL_CLOCK_40P, tag, owner, clock)
+ , device_rc2014_card_interface(mconfig, *this)
+{
+}
+
+void dual_clock_device_40pin::device_reset()
+{
+ m_bus->set_bus_clock(clock_mapping[m_clk_sel_1->read()]);
+ dual_clock_base::device_reset();
+}
+
+}
+//**************************************************************************
+// DEVICE DEFINITIONS
+//**************************************************************************
+
+DEFINE_DEVICE_TYPE_PRIVATE(RC2014_SINGLE_CLOCK, device_rc2014_card_interface, single_clock_device, "rc2014_clock", "RC2014 Clock module")
+DEFINE_DEVICE_TYPE_PRIVATE(RC2014_DUAL_CLOCK, device_rc2014_ext_card_interface, dual_clock_device, "rc2014_dual_clock", "RC2014 Dual Clock module")
+DEFINE_DEVICE_TYPE_PRIVATE(RC2014_DUAL_CLOCK_40P, device_rc2014_card_interface, dual_clock_device_40pin, "rc2014_dual_clock_40p", "RC2014 Dual Clock module (40 pin)")
diff --git a/src/devices/bus/rc2014/clock.h b/src/devices/bus/rc2014/clock.h
new file mode 100644
index 00000000000..225a2e09333
--- /dev/null
+++ b/src/devices/bus/rc2014/clock.h
@@ -0,0 +1,20 @@
+// license:BSD-3-Clause
+// copyright-holders:Miodrag Milanovic
+/**********************************************************************
+
+ RC2014 Clock Module
+
+**********************************************************************/
+
+#ifndef MAME_BUS_RC2014_CLOCK_H
+#define MAME_BUS_RC2014_CLOCK_H
+
+#pragma once
+
+#include "bus/rc2014/rc2014.h"
+
+DECLARE_DEVICE_TYPE(RC2014_SINGLE_CLOCK, device_rc2014_card_interface)
+DECLARE_DEVICE_TYPE(RC2014_DUAL_CLOCK, device_rc2014_ext_card_interface)
+DECLARE_DEVICE_TYPE(RC2014_DUAL_CLOCK_40P, device_rc2014_card_interface)
+
+#endif // MAME_BUS_RC2014_CLOCK_H
diff --git a/src/devices/bus/rc2014/edge.cpp b/src/devices/bus/rc2014/edge.cpp
new file mode 100644
index 00000000000..505ec77125d
--- /dev/null
+++ b/src/devices/bus/rc2014/edge.cpp
@@ -0,0 +1,203 @@
+// license:BSD-3-Clause
+// copyright-holders:Miodrag Milanovic
+/***************************************************************************
+
+ RC2014 Modular Backplane Extensions
+
+****************************************************************************/
+
+#include "emu.h"
+#include "edge.h"
+#include "modules.h"
+
+namespace {
+
+//**************************************************************************
+// SC106 - Modular Backplane (RC2014)
+// Module author: Stephen C Cousins
+//**************************************************************************
+
+class sc106_device : public device_t, public device_rc2014_rc80_card_interface
+{
+public:
+ // construction/destruction
+ sc106_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock);
+
+protected:
+ sc106_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, u32 clock);
+
+ // device-level overrides
+ virtual void device_start() override ATTR_COLD;
+ virtual void device_add_mconfig(machine_config &config) override ATTR_COLD;
+
+private:
+ required_device<rc2014_rc80_bus_device> m_rc80_bus;
+};
+
+sc106_device::sc106_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, u32 clock)
+ : device_t(mconfig, type, tag, owner, clock)
+ , device_rc2014_rc80_card_interface(mconfig, *this)
+ , m_rc80_bus(*this, ":bus")
+{
+}
+
+sc106_device::sc106_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock)
+ : sc106_device(mconfig, RC2014_SC106, tag, owner, clock)
+{
+}
+
+void sc106_device::device_start()
+{
+}
+
+void sc106_device::device_add_mconfig(machine_config &config)
+{
+ RC2014_RC80_SLOT(config, "1", m_rc80_bus, rc2014_rc80_bus_modules, nullptr);
+ RC2014_RC80_SLOT(config, "2", m_rc80_bus, rc2014_rc80_bus_modules, nullptr);
+ RC2014_RC80_SLOT(config, "3", m_rc80_bus, rc2014_rc80_bus_modules, nullptr);
+ RC2014_RC80_SLOT(config, "4", m_rc80_bus, rc2014_rc80_bus_modules, nullptr);
+ RC2014_RC80_SLOT(config, "5", m_rc80_bus, rc2014_rc80_bus_modules, nullptr);
+ RC2014_RC80_SLOT(config, "6", m_rc80_bus, rc2014_rc80_bus_modules, nullptr);
+ RC2014_RC80_SLOT(config, "e", m_rc80_bus, rc2014_rc80_bus_edge_modules, nullptr);
+
+}
+
+//**************************************************************************
+// SC107 - Modular Backplane (RC2014)
+// Module author: Stephen C Cousins
+//
+// TODO: Pins 37 and 38 form an interrupt daisy chain
+//**************************************************************************
+
+class sc107_device : public sc106_device
+{
+ public:
+ // construction/destruction
+ sc107_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock);
+};
+
+sc107_device::sc107_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock)
+ : sc106_device(mconfig, RC2014_SC107, tag, owner, clock)
+{
+}
+
+//**************************************************************************
+// SC113 - Modular Backplane (RC2014)
+// Module author: Stephen C Cousins
+//
+// TODO: Jumpers on board
+//**************************************************************************
+
+class sc113_device : public sc106_device
+{
+ public:
+ // construction/destruction
+ sc113_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock);
+};
+
+sc113_device::sc113_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock)
+ : sc106_device(mconfig, RC2014_SC113, tag, owner, clock)
+{
+}
+
+//**************************************************************************
+// SC141 - Modular Backplane (RC2014)
+// Module author: Stephen C Cousins
+//**************************************************************************
+
+class sc141_device : public device_t, public device_rc2014_card_interface
+{
+public:
+ // construction/destruction
+ sc141_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock);
+
+protected:
+ // device-level overrides
+ virtual void device_start() override ATTR_COLD;
+ virtual void device_add_mconfig(machine_config &config) override ATTR_COLD;
+
+private:
+ required_device<rc2014_bus_device> m_rc40_bus;
+};
+
+sc141_device::sc141_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock)
+ : device_t(mconfig, RC2014_SC141, tag, owner, clock)
+ , device_rc2014_card_interface(mconfig, *this)
+ , m_rc40_bus(*this, ":bus")
+{
+}
+
+void sc141_device::device_start()
+{
+}
+
+void sc141_device::device_add_mconfig(machine_config &config)
+{
+ RC2014_SLOT(config, "1", m_rc40_bus, rc2014_bus_modules, nullptr);
+ RC2014_SLOT(config, "2", m_rc40_bus, rc2014_bus_modules, nullptr);
+ RC2014_SLOT(config, "3", m_rc40_bus, rc2014_bus_modules, nullptr);
+ RC2014_SLOT(config, "4", m_rc40_bus, rc2014_bus_modules, nullptr);
+ RC2014_SLOT(config, "5", m_rc40_bus, rc2014_bus_modules, nullptr);
+ RC2014_SLOT(config, "6", m_rc40_bus, rc2014_bus_modules, nullptr);
+ RC2014_SLOT(config, "7", m_rc40_bus, rc2014_bus_modules, nullptr);
+ RC2014_SLOT(config, "8", m_rc40_bus, rc2014_bus_modules, nullptr);
+ RC2014_SLOT(config, "9", m_rc40_bus, rc2014_bus_modules, nullptr);
+ RC2014_SLOT(config, "10", m_rc40_bus, rc2014_bus_modules, nullptr);
+ RC2014_SLOT(config, "11", m_rc40_bus, rc2014_bus_modules, nullptr);
+ RC2014_SLOT(config, "12", m_rc40_bus, rc2014_bus_modules, nullptr);
+ RC2014_SLOT(config, "e", m_rc40_bus, rc2014_bus_edge_modules, nullptr);
+}
+
+//**************************************************************************
+// SC147 - Modular Backplane (RC2014)
+// Module author: Stephen C Cousins
+//**************************************************************************
+
+class sc147_device : public device_t, public device_rc2014_card_interface
+{
+public:
+ // construction/destruction
+ sc147_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock);
+
+protected:
+ // device-level overrides
+ virtual void device_start() override ATTR_COLD;
+ virtual void device_add_mconfig(machine_config &config) override ATTR_COLD;
+
+private:
+ required_device<rc2014_bus_device> m_rc40_bus;
+};
+
+sc147_device::sc147_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock)
+ : device_t(mconfig, RC2014_SC147, tag, owner, clock)
+ , device_rc2014_card_interface(mconfig, *this)
+ , m_rc40_bus(*this, ":bus")
+{
+}
+
+void sc147_device::device_start()
+{
+}
+
+void sc147_device::device_add_mconfig(machine_config &config)
+{
+ RC2014_SLOT(config, "1", m_rc40_bus, rc2014_bus_modules, nullptr);
+ RC2014_SLOT(config, "2", m_rc40_bus, rc2014_bus_modules, nullptr);
+ RC2014_SLOT(config, "3", m_rc40_bus, rc2014_bus_modules, nullptr);
+ RC2014_SLOT(config, "4", m_rc40_bus, rc2014_bus_modules, nullptr);
+ RC2014_SLOT(config, "5", m_rc40_bus, rc2014_bus_modules, nullptr);
+ RC2014_SLOT(config, "6", m_rc40_bus, rc2014_bus_modules, nullptr);
+ RC2014_SLOT(config, "e", m_rc40_bus, rc2014_bus_edge_modules, nullptr);
+}
+
+}
+//**************************************************************************
+// DEVICE DEFINITIONS
+//**************************************************************************
+
+DEFINE_DEVICE_TYPE_PRIVATE(RC2014_SC106, device_rc2014_rc80_card_interface, sc106_device, "rc2014_sc106", "SC106 - Modular Backplane (RC2014)")
+DEFINE_DEVICE_TYPE_PRIVATE(RC2014_SC107, device_rc2014_rc80_card_interface, sc107_device, "rc2014_sc107", "SC107 - Modular Backplane (RC2014)")
+DEFINE_DEVICE_TYPE_PRIVATE(RC2014_SC113, device_rc2014_rc80_card_interface, sc113_device, "rc2014_sc113", "SC113 - Modular Backplane (RC2014)")
+
+DEFINE_DEVICE_TYPE_PRIVATE(RC2014_SC141, device_rc2014_card_interface, sc141_device, "rc2014_sc141", "SC141 - Modular Backplane (RC2014)")
+DEFINE_DEVICE_TYPE_PRIVATE(RC2014_SC147, device_rc2014_card_interface, sc147_device, "rc2014_sc147", "SC147 - Modular Backplane (RC2014)")
diff --git a/src/devices/bus/rc2014/edge.h b/src/devices/bus/rc2014/edge.h
new file mode 100644
index 00000000000..9369c0b783a
--- /dev/null
+++ b/src/devices/bus/rc2014/edge.h
@@ -0,0 +1,23 @@
+// license:BSD-3-Clause
+// copyright-holders:Miodrag Milanovic
+/**********************************************************************
+
+ RC2014 Modular Backplane Extensions
+
+**********************************************************************/
+
+#ifndef MAME_BUS_RC2014_EDGE_H
+#define MAME_BUS_RC2014_EDGE_H
+
+#pragma once
+
+#include "bus/rc2014/rc2014.h"
+
+DECLARE_DEVICE_TYPE(RC2014_SC106, device_rc2014_rc80_card_interface)
+DECLARE_DEVICE_TYPE(RC2014_SC107, device_rc2014_rc80_card_interface)
+DECLARE_DEVICE_TYPE(RC2014_SC113, device_rc2014_rc80_card_interface)
+
+DECLARE_DEVICE_TYPE(RC2014_SC141, device_rc2014_card_interface)
+DECLARE_DEVICE_TYPE(RC2014_SC147, device_rc2014_card_interface)
+
+#endif // MAME_BUS_RC2014_EDGE_H
diff --git a/src/devices/bus/rc2014/fdc.cpp b/src/devices/bus/rc2014/fdc.cpp
new file mode 100644
index 00000000000..6a774c682d8
--- /dev/null
+++ b/src/devices/bus/rc2014/fdc.cpp
@@ -0,0 +1,232 @@
+// license:BSD-3-Clause
+// copyright-holders:Miodrag Milanovic
+/***************************************************************************
+
+ RC2014 FDC
+
+****************************************************************************/
+
+#include "emu.h"
+#include "fdc.h"
+
+#include "machine/upd765.h"
+#include "imagedev/floppy.h"
+
+namespace {
+
+//**************************************************************************
+// RC2014 Floppy Disk Controller FDC9266
+// Module author: Dr. Scott M. Baker
+//**************************************************************************
+
+class rc2014_fdc9266_device : public device_t, public device_rc2014_card_interface
+{
+public:
+ // construction/destruction
+ rc2014_fdc9266_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock);
+
+protected:
+ // device-level overrides
+ 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;
+ virtual ioport_constructor device_input_ports() const override ATTR_COLD;
+private:
+ void control_w(offs_t offset, uint8_t data);
+
+ required_ioport m_addr;
+ required_ioport_array<4> m_jp;
+ required_device<upd765a_device> m_fdc;
+ required_device_array<floppy_connector, 2> m_floppy;
+};
+
+rc2014_fdc9266_device::rc2014_fdc9266_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock)
+ : device_t(mconfig, RC2014_FDC9266, tag, owner, clock)
+ , device_rc2014_card_interface(mconfig, *this)
+ , m_addr(*this, "SV1")
+ , m_jp(*this, "JP%u", 1U)
+ , m_fdc(*this, "fdc")
+ , m_floppy(*this, "fdc:%u", 0U)
+{
+}
+
+void rc2014_fdc9266_device::device_start()
+{
+}
+
+void rc2014_fdc9266_device::device_reset()
+{
+ uint8_t base = m_addr->read() << 5; // SV1
+ // A15-A8 and A1 not connected
+ m_bus->installer(AS_IO)->install_read_handler(base+0x10, base+0x10, 0, 0xff02, 0, read8smo_delegate(m_fdc, FUNC(upd765a_device::msr_r)));
+ m_bus->installer(AS_IO)->install_readwrite_handler(base+0x11, base+0x11, 0, 0xff02, 0, read8smo_delegate(m_fdc, FUNC(upd765a_device::fifo_r)), write8smo_delegate(m_fdc, FUNC(upd765a_device::fifo_w)));
+ m_bus->installer(AS_IO)->install_write_handler(base+0x18, base+0x18, 0, 0xff02, 0, write8sm_delegate(*this, FUNC(rc2014_fdc9266_device::control_w)));
+ // TODO: Use jumpers
+}
+
+void rc2014_fdc9266_device::control_w(offs_t, uint8_t data)
+{
+ // D0 - TC
+ // D1 - MOTEA
+ // D2 - MOTEB
+ // D3 - P2
+ // D4 - P1
+ // D5 - P0
+ // D6 - DENSEL
+ // D7 - FDC_RST (trough inverter)
+ m_fdc->tc_w(BIT(data,0)? true : false);
+ if (m_floppy[0]->get_device())
+ m_floppy[0]->get_device()->mon_w(!BIT(data,1));
+ if (m_floppy[1]->get_device())
+ m_floppy[1]->get_device()->mon_w(!BIT(data,2));
+
+ m_fdc->set_rate(BIT(data,6) ? 500000 : 250000);
+ m_fdc->reset_w(!BIT(data,7) ? ASSERT_LINE : CLEAR_LINE);
+}
+
+static void rc2014_floppies(device_slot_interface &device)
+{
+ device.option_add("35hd", FLOPPY_35_HD);
+}
+
+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", 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 )
+ PORT_START("SV1")
+ PORT_CONFNAME( 0x7, 0x2, "Base Address" )
+ PORT_CONFSETTING( 0x0, "0x00" )
+ PORT_CONFSETTING( 0x1, "0x20" )
+ PORT_CONFSETTING( 0x2, "0x40" )
+ PORT_CONFSETTING( 0x3, "0x60" )
+ PORT_CONFSETTING( 0x4, "0x80" )
+ PORT_CONFSETTING( 0x5, "0xa0" )
+ PORT_CONFSETTING( 0x6, "0xc0" )
+ PORT_CONFSETTING( 0x7, "0xe0" )
+ PORT_START("JP1")
+ PORT_CONFNAME( 0x1, 0x1, "Two Side" )
+ PORT_CONFSETTING( 0x0, "GND" )
+ PORT_CONFSETTING( 0x1, "None" )
+ PORT_START("JP2")
+ PORT_CONFNAME( 0x1, 0x0, "/FAULT" )
+ PORT_CONFSETTING( 0x0, "None" )
+ PORT_CONFSETTING( 0x1, "+5V" )
+ PORT_START("JP3")
+ PORT_CONFNAME( 0x1, 0x1, "MINI" )
+ PORT_CONFSETTING( 0x0, "GND" )
+ PORT_CONFSETTING( 0x1, "+5V" )
+ PORT_START("JP4")
+ PORT_CONFNAME( 0x1, 0x4, "RDY" )
+ PORT_CONFSETTING( 0x0, "GND" )
+ PORT_CONFSETTING( 0x4, "DC/RDY" )
+INPUT_PORTS_END
+
+ioport_constructor rc2014_fdc9266_device::device_input_ports() const
+{
+ return INPUT_PORTS_NAME( rc2014_fdc9266_jumpers );
+}
+
+//**************************************************************************
+// RC2014 Floppy Disk Controller WD37C65
+// Module author: Dr. Scott M. Baker
+//**************************************************************************
+
+class rc2014_wd37c65_device : public device_t, public device_rc2014_card_interface
+{
+public:
+ // construction/destruction
+ rc2014_wd37c65_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock);
+
+protected:
+ // device-level overrides
+ 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;
+ virtual ioport_constructor device_input_ports() const override ATTR_COLD;
+
+ // DACK confirmation is same as pulsing TC
+ uint8_t dack_r(address_space &space, offs_t) { m_fdc->tc_w(true); m_fdc->tc_w(false); return space.unmap(); }
+private:
+ required_ioport m_addr;
+ required_ioport_array<2> m_jp;
+ required_device<wd37c65c_device> m_fdc;
+ required_device_array<floppy_connector, 2> m_floppy;
+};
+
+rc2014_wd37c65_device::rc2014_wd37c65_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock)
+ : device_t(mconfig, RC2014_WD37C65, tag, owner, clock)
+ , device_rc2014_card_interface(mconfig, *this)
+ , m_addr(*this, "SV1")
+ , m_jp(*this, "JP%u", 1U)
+ , m_fdc(*this, "fdc")
+ , m_floppy(*this, "fdc:%u", 0U)
+{
+}
+
+void rc2014_wd37c65_device::device_start()
+{
+}
+
+void rc2014_wd37c65_device::device_reset()
+{
+ uint8_t base = m_addr->read() << 5; // SV1
+ // A15-A8 and A1 not connected
+ m_bus->installer(AS_IO)->install_read_handler(base+0x10, base+0x10, 0, 0xff02, 0, read8smo_delegate(m_fdc, FUNC(wd37c65c_device::msr_r)));
+ m_bus->installer(AS_IO)->install_readwrite_handler(base+0x11, base+0x11, 0, 0xff02, 0, read8smo_delegate(m_fdc, FUNC(wd37c65c_device::fifo_r)), write8smo_delegate(m_fdc, FUNC(wd37c65c_device::fifo_w)));
+
+ // A15-A8 and A0 and A1 not connected
+ m_bus->installer(AS_IO)->install_write_handler(base+0x08, base+0x08, 0, 0xff06, 0, write8smo_delegate(m_fdc, FUNC(wd37c65c_device::ccr_w)));
+ m_bus->installer(AS_IO)->install_write_handler(base+0x18, base+0x18, 0, 0xff06, 0, write8smo_delegate(m_fdc, FUNC(wd37c65c_device::dor_w)));
+ m_bus->installer(AS_IO)->install_read_handler(base+0x18, base+0x18, 0, 0xff06, 0, read8m_delegate(*this, FUNC(rc2014_wd37c65_device::dack_r)));
+ // TODO: Use jumpers
+}
+
+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", 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 )
+ PORT_START("SV1")
+ PORT_CONFNAME( 0x7, 0x2, "Base Address" )
+ PORT_CONFSETTING( 0x0, "0x00" )
+ PORT_CONFSETTING( 0x1, "0x20" )
+ PORT_CONFSETTING( 0x2, "0x40" )
+ PORT_CONFSETTING( 0x3, "0x60" )
+ PORT_CONFSETTING( 0x4, "0x80" )
+ PORT_CONFSETTING( 0x5, "0xa0" )
+ PORT_CONFSETTING( 0x6, "0xc0" )
+ PORT_CONFSETTING( 0x7, "0xe0" )
+ PORT_START("JP1")
+ PORT_CONFNAME( 0x1, 0x1, "DACK" )
+ PORT_CONFSETTING( 0x0, "Share with DOR" )
+ PORT_CONFSETTING( 0x1, "Use offset 0" )
+ PORT_START("JP2")
+ PORT_CONFNAME( 0x1, 0x0, "TC" )
+ PORT_CONFSETTING( 0x0, "Port offset 4" )
+ PORT_CONFSETTING( 0x1, "+5V" )
+INPUT_PORTS_END
+
+ioport_constructor rc2014_wd37c65_device::device_input_ports() const
+{
+ return INPUT_PORTS_NAME( rc2014_wd37c65_jumpers );
+}
+
+}
+//**************************************************************************
+// DEVICE DEFINITIONS
+//**************************************************************************
+
+DEFINE_DEVICE_TYPE_PRIVATE(RC2014_FDC9266, device_rc2014_card_interface, rc2014_fdc9266_device, "rc2014_fdc9266", "RC2014 Floppy Disk Controller FDC9266")
+DEFINE_DEVICE_TYPE_PRIVATE(RC2014_WD37C65, device_rc2014_card_interface, rc2014_wd37c65_device, "rc2014_wd37c65", "RC2014 Floppy Disk Controller WD37C65")
diff --git a/src/devices/bus/rc2014/fdc.h b/src/devices/bus/rc2014/fdc.h
new file mode 100644
index 00000000000..ed1c50cd6b9
--- /dev/null
+++ b/src/devices/bus/rc2014/fdc.h
@@ -0,0 +1,19 @@
+// license:BSD-3-Clause
+// copyright-holders:Miodrag Milanovic
+/**********************************************************************
+
+ RC2014 FDC
+
+**********************************************************************/
+
+#ifndef MAME_BUS_RC2014_FDC_H
+#define MAME_BUS_RC2014_FDC_H
+
+#pragma once
+
+#include "bus/rc2014/rc2014.h"
+
+DECLARE_DEVICE_TYPE(RC2014_FDC9266, device_rc2014_card_interface)
+DECLARE_DEVICE_TYPE(RC2014_WD37C65, device_rc2014_card_interface)
+
+#endif // MAME_BUS_RC2014_FDC_H
diff --git a/src/devices/bus/rc2014/ide.cpp b/src/devices/bus/rc2014/ide.cpp
new file mode 100644
index 00000000000..7c5d596ea1c
--- /dev/null
+++ b/src/devices/bus/rc2014/ide.cpp
@@ -0,0 +1,295 @@
+// license:BSD-3-Clause
+// copyright-holders:Miodrag Milanovic
+/***************************************************************************
+
+ RC2014 IDE
+
+****************************************************************************/
+
+#include "emu.h"
+#include "ide.h"
+#include "machine/i8255.h"
+#include "bus/ata/ataintf.h"
+
+namespace {
+
+//**************************************************************************
+// rc2014_ide_base
+//**************************************************************************
+
+class rc2014_ide_base : public device_t, public device_rc2014_card_interface
+{
+protected:
+ // construction/destruction
+ rc2014_ide_base(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, u32 clock);
+
+ // device-level overrides
+ virtual void device_start() override ATTR_COLD;
+ virtual void device_add_mconfig(machine_config &config) override ATTR_COLD;
+
+ uint8_t ppi_pa_r() { return m_data.b.l; }
+ uint8_t ppi_pb_r() { return m_data.b.h; }
+ void ppi_pa_w(uint8_t data) { m_data.b.l = data; }
+ void ppi_pb_w(uint8_t data) { m_data.b.h = data; }
+ virtual void ppi_pc_w(uint8_t data) = 0;
+
+ // base-class members
+ required_device<ata_interface_device> m_ata;
+ required_device<i8255_device> m_ppi;
+
+ PAIR16 m_data;
+ uint8_t m_prev;
+};
+
+rc2014_ide_base::rc2014_ide_base(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, u32 clock)
+ : device_t(mconfig, type, tag, owner, clock)
+ , device_rc2014_card_interface(mconfig, *this)
+ , m_ata(*this, "ata")
+ , m_ppi(*this, "82c55")
+ , m_prev(0)
+{
+}
+
+void rc2014_ide_base::device_start()
+{
+}
+
+void rc2014_ide_base::device_add_mconfig(machine_config &config)
+{
+ I8255(config, m_ppi, 0);
+ m_ppi->in_pa_callback().set(FUNC(rc2014_ide_base::ppi_pa_r));
+ m_ppi->in_pb_callback().set(FUNC(rc2014_ide_base::ppi_pb_r));
+ m_ppi->out_pa_callback().set(FUNC(rc2014_ide_base::ppi_pa_w));
+ m_ppi->out_pb_callback().set(FUNC(rc2014_ide_base::ppi_pb_w));
+ m_ppi->out_pc_callback().set(FUNC(rc2014_ide_base::ppi_pc_w));
+
+ ATA_INTERFACE(config, m_ata).options(ata_devices, "hdd", "hdd", false);
+}
+
+//**************************************************************************
+// RC2014 82C55 IDE Interface
+// Module author: Ed Brindley
+//**************************************************************************
+
+class rc2014_82c55_ide_device : public rc2014_ide_base
+{
+public:
+ // construction/destruction
+ rc2014_82c55_ide_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock);
+
+protected:
+ // device-level overrides
+ virtual void device_reset() override ATTR_COLD;
+ virtual ioport_constructor device_input_ports() const override ATTR_COLD;
+
+ void ppi_pc_w(uint8_t data) override;
+private:
+ required_ioport m_sw;
+ required_ioport_array<4> m_jp;
+
+ uint8_t m_da0;
+ uint8_t m_da1;
+ uint8_t m_dcs1;
+ uint8_t m_dior;
+};
+
+rc2014_82c55_ide_device::rc2014_82c55_ide_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock)
+ : rc2014_ide_base(mconfig, RC2014_82C55_IDE, tag, owner, clock)
+ , m_sw(*this, "SW1")
+ , m_jp(*this, "JP%u", 1U)
+{
+}
+
+void rc2014_82c55_ide_device::device_reset()
+{
+ m_da0 = (m_jp[0]->read() == 1) ? 4 : 0;
+ m_dcs1 = (m_jp[1]->read() == 1) ? 0 : 4;
+ m_da1 = (m_jp[2]->read() == 1) ? 6 : 1;
+ m_dior = (m_jp[3]->read() == 1) ? 1 : 6;
+
+ uint8_t base = m_sw->read(); // SW1
+ // A15-A8 not connected
+ m_bus->installer(AS_IO)->install_readwrite_handler(base, base+0x03, 0, 0xff00, 0, read8sm_delegate(m_ppi, FUNC(i8255_device::read)), write8sm_delegate(m_ppi, FUNC(i8255_device::write)));
+}
+
+void rc2014_82c55_ide_device::ppi_pc_w(uint8_t data)
+{
+ // On IDE connector DIOW and DIOR are inverted
+ // write is on falling and read on rising edge
+ uint8_t offset = BIT(data,2) << 2 | BIT(data,m_da1) << 1 | BIT(data,m_da0);
+
+ if (BIT(data,3)) // DCS0
+ {
+ if (BIT(data,5)==0 && BIT(m_prev,5)==1) // DIOW
+ {
+ m_ata->cs0_w(offset, m_data.w);
+ }
+ if (BIT(data,m_dior)==1 && BIT(m_prev,m_dior)==0) // DIOR
+ {
+ m_data.w = m_ata->cs0_r(offset);
+ }
+ }
+ if (BIT(data,m_dcs1)) // DCS1
+ {
+ if (BIT(data,5)==0 && BIT(m_prev,5)==1) // DIOW
+ {
+ m_ata->cs1_w(offset, m_data.w);
+ }
+ if (BIT(data,m_dior)==1 && BIT(m_prev,m_dior)==0) // DIOR
+ {
+ m_data.w = m_ata->cs1_r(offset);
+ }
+ }
+ if (BIT(data,7)) // DRESET
+ {
+ // RESET IDE Disk
+ m_ata->reset();
+ }
+ m_prev = data;
+
+}
+
+static INPUT_PORTS_START( rc2014_82c55_ide_jumpers )
+ PORT_START("SW1")
+ PORT_DIPNAME(0x04, 0x00, "0x04") PORT_DIPLOCATION("Base Address:1")
+ PORT_DIPSETTING(0x00, DEF_STR( Off ) )
+ PORT_DIPSETTING(0x04, DEF_STR( On ) )
+ PORT_DIPNAME(0x08, 0x00, "0x08") PORT_DIPLOCATION("Base Address:2")
+ PORT_DIPSETTING(0x00, DEF_STR( Off ) )
+ PORT_DIPSETTING(0x08, DEF_STR( On ) )
+ PORT_DIPNAME(0x10, 0x00, "0x10") PORT_DIPLOCATION("Base Address:3")
+ PORT_DIPSETTING(0x00, DEF_STR( Off ) )
+ PORT_DIPSETTING(0x10, DEF_STR( On ) )
+ PORT_DIPNAME(0x20, 0x20, "0x20") PORT_DIPLOCATION("Base Address:4")
+ PORT_DIPSETTING(0x00, DEF_STR( Off ) )
+ PORT_DIPSETTING(0x20, DEF_STR( On ) )
+ PORT_DIPNAME(0x40, 0x00, "0x40") PORT_DIPLOCATION("Base Address:5")
+ PORT_DIPSETTING(0x00, DEF_STR( Off ) )
+ PORT_DIPSETTING(0x40, DEF_STR( On ) )
+ PORT_DIPNAME(0x80, 0x00, "0x80") PORT_DIPLOCATION("Base Address:6")
+ PORT_DIPSETTING(0x00, DEF_STR( Off ) )
+ PORT_DIPSETTING(0x80, DEF_STR( On ) )
+ PORT_START("JP1")
+ PORT_CONFNAME( 0x1, 0x0, "DA0" )
+ PORT_CONFSETTING( 0x0, "PC0" )
+ PORT_CONFSETTING( 0x1, "PC4" )
+ PORT_START("JP2")
+ PORT_CONFNAME( 0x1, 0x0, "DCS1" )
+ PORT_CONFSETTING( 0x0, "PC4" )
+ PORT_CONFSETTING( 0x1, "PC0" )
+ PORT_START("JP3")
+ PORT_CONFNAME( 0x1, 0x0, "DA1" )
+ PORT_CONFSETTING( 0x0, "PC1" )
+ PORT_CONFSETTING( 0x1, "PC6" )
+ PORT_START("JP4")
+ PORT_CONFNAME( 0x1, 0x0, "DIOR" )
+ PORT_CONFSETTING( 0x0, "PC6" )
+ PORT_CONFSETTING( 0x1, "PC1" )
+ PORT_START("JP5")
+ PORT_CONFNAME( 0x1, 0x0, "Power" )
+ PORT_CONFSETTING( 0x0, "Bus" )
+ PORT_CONFSETTING( 0x1, "External" )
+INPUT_PORTS_END
+
+ioport_constructor rc2014_82c55_ide_device::device_input_ports() const
+{
+ return INPUT_PORTS_NAME( rc2014_82c55_ide_jumpers );
+}
+
+//**************************************************************************
+// RC2014 IDE Hard Drive Module
+// Module author: Spencer Owen
+// Based on design from Ed Brindley, but simplified
+//**************************************************************************
+
+class rc2014_ide_hdd_device : public rc2014_ide_base
+{
+public:
+ // construction/destruction
+ rc2014_ide_hdd_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock);
+
+protected:
+ // device-level overrides
+ virtual void device_reset() override ATTR_COLD;
+ virtual ioport_constructor device_input_ports() const override ATTR_COLD;
+
+ void ppi_pc_w(uint8_t data) override;
+private:
+ required_ioport m_jp;
+};
+
+rc2014_ide_hdd_device::rc2014_ide_hdd_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock)
+ : rc2014_ide_base(mconfig, RC2014_IDE_HDD, tag, owner, clock)
+ , m_jp(*this, "J1")
+{
+}
+
+void rc2014_ide_hdd_device::device_reset()
+{
+ uint8_t base = m_jp->read() << 3;
+ // A15-A8 are not connected, A7,A6 and A2 must be 0
+ m_bus->installer(AS_IO)->install_readwrite_handler(base, base+0x03, 0, 0xff00, 0, read8sm_delegate(m_ppi, FUNC(i8255_device::read)), write8sm_delegate(m_ppi, FUNC(i8255_device::write)));
+}
+
+void rc2014_ide_hdd_device::ppi_pc_w(uint8_t data)
+{
+ uint8_t offset = data & 7;
+
+ if (BIT(data,3)) // DCS0
+ {
+ if (BIT(data,5)==0 && BIT(m_prev,5)==1) // DIOW
+ {
+ m_ata->cs0_w(offset, m_data.w);
+ }
+ if (BIT(data,6)==1 && BIT(m_prev,6)==0) // DIOR
+ {
+ m_data.w = m_ata->cs0_r(offset);
+ }
+ }
+ if (BIT(data,4)) // DCS1
+ {
+ if (BIT(data,5)==0 && BIT(m_prev,5)==1) // DIOW
+ {
+ m_ata->cs1_w(offset, m_data.w);
+ }
+ if (BIT(data,6)==1 && BIT(m_prev,6)==0) // DIOR
+ {
+ m_data.w = m_ata->cs1_r(offset);
+ }
+ }
+ if (BIT(data,7)) // DRESET
+ {
+ // RESET IDE Disk
+ m_ata->reset();
+ }
+ m_prev = data;
+
+}
+
+static INPUT_PORTS_START( rc2014_ide_hdd_jumpers )
+ PORT_START("J1")
+ PORT_CONFNAME( 0x7, 0x4, "Base Address" )
+ PORT_CONFSETTING( 0x1, "0x08" )
+ PORT_CONFSETTING( 0x2, "0x10" )
+ PORT_CONFSETTING( 0x3, "0x18" )
+ PORT_CONFSETTING( 0x4, "0x20" )
+ PORT_CONFSETTING( 0x5, "0x28" )
+ PORT_CONFSETTING( 0x6, "0x30" )
+ PORT_CONFSETTING( 0x7, "0x38" )
+ PORT_START("JP1")
+ PORT_CONFNAME( 0x1, 0x0, "Power" )
+ PORT_CONFSETTING( 0x0, "Bus" )
+ PORT_CONFSETTING( 0x1, "External" )
+INPUT_PORTS_END
+
+ioport_constructor rc2014_ide_hdd_device::device_input_ports() const
+{
+ return INPUT_PORTS_NAME( rc2014_ide_hdd_jumpers );
+}
+
+}
+//**************************************************************************
+// DEVICE DEFINITIONS
+//**************************************************************************
+DEFINE_DEVICE_TYPE_PRIVATE(RC2014_82C55_IDE, device_rc2014_card_interface, rc2014_82c55_ide_device, "rc2014_82c55_ide", "RC2014 82C55 IDE Interface")
+DEFINE_DEVICE_TYPE_PRIVATE(RC2014_IDE_HDD, device_rc2014_card_interface, rc2014_ide_hdd_device, "rc2014_ide_hdd", "RC2014 IDE Hard Drive Module")
diff --git a/src/devices/bus/rc2014/ide.h b/src/devices/bus/rc2014/ide.h
new file mode 100644
index 00000000000..02cecc00aae
--- /dev/null
+++ b/src/devices/bus/rc2014/ide.h
@@ -0,0 +1,19 @@
+// license:BSD-3-Clause
+// copyright-holders:Miodrag Milanovic
+/**********************************************************************
+
+ RC2014 IDE
+
+**********************************************************************/
+
+#ifndef MAME_BUS_RC2014_IDE_H
+#define MAME_BUS_RC2014_IDE_H
+
+#pragma once
+
+#include "bus/rc2014/rc2014.h"
+
+DECLARE_DEVICE_TYPE(RC2014_82C55_IDE, device_rc2014_card_interface)
+DECLARE_DEVICE_TYPE(RC2014_IDE_HDD, device_rc2014_card_interface)
+
+#endif // MAME_BUS_RC2014_IDE_H
diff --git a/src/devices/bus/rc2014/micro.cpp b/src/devices/bus/rc2014/micro.cpp
new file mode 100644
index 00000000000..d119f54e519
--- /dev/null
+++ b/src/devices/bus/rc2014/micro.cpp
@@ -0,0 +1,303 @@
+// license:BSD-3-Clause
+// copyright-holders:Miodrag Milanovic
+/***************************************************************************
+
+ RC2014 Micro Module
+
+****************************************************************************/
+
+#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"
+
+
+namespace {
+
+//**************************************************************************
+// RC2014 Micro module
+// Module author: Spencer Owen
+//**************************************************************************
+
+class rc2014_micro : public device_t, public device_rc2014_card_interface
+{
+public:
+ // construction/destruction
+ rc2014_micro(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock);
+
+private:
+ // device_t implementation
+ virtual void device_start() override ATTR_COLD;
+ virtual void device_reset() override ATTR_COLD;
+ virtual void device_resolve_objects() override ATTR_COLD;
+ virtual void device_add_mconfig(machine_config &config) override ATTR_COLD;
+ virtual ioport_constructor device_input_ports() const override ATTR_COLD;
+ virtual const tiny_rom_entry *device_rom_region() const override ATTR_COLD;
+
+ 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(); }
+
+ required_device<z80_device> m_maincpu;
+ required_device<acia6850_device> m_acia;
+ required_memory_region m_rom;
+ required_ioport m_rom_selector;
+ required_ioport m_rom_present;
+
+ std::unique_ptr<u8[]> m_ram;
+
+ static constexpr XTAL MAIN_CLOCK = XTAL(7'372'800);
+};
+
+rc2014_micro::rc2014_micro(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock)
+ : device_t(mconfig, RC2014_MICRO, tag, owner, clock)
+ , device_rc2014_card_interface(mconfig, *this)
+ , m_maincpu(*this, "maincpu")
+ , m_acia(*this, "acia")
+ , m_rom(*this, "rom")
+ , m_rom_selector(*this, "JP2-JP4")
+ , m_rom_present(*this, "ROM")
+ , m_ram(nullptr)
+{
+}
+
+void rc2014_micro::device_start()
+{
+ // Setup CPU
+ m_bus->set_bus_clock(MAIN_CLOCK);
+ m_maincpu->set_daisy_config(m_bus->get_daisy_chain());
+
+ // Setup RAM
+ m_ram = std::make_unique<u8[]>(0x8000);
+ std::fill_n(m_ram.get(), 0x8000, 0xff);
+ save_pointer(NAME(m_ram), 0x8000);
+ m_bus->installer(AS_PROGRAM)->install_ram(0x8000, 0xffff, m_ram.get());
+}
+
+void rc2014_micro::device_reset()
+{
+ // Setup ACIA
+ // A15-A8 and A5-A1 not connected
+ 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)));
+
+ // Setup ROM
+ if (m_rom_present->read())
+ m_bus->installer(AS_PROGRAM)->install_rom(0x0000, 0x1fff, 0x0000, m_rom->base() + (m_rom_selector->read() & 7) * 0x2000);
+}
+
+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));
+}
+
+static DEVICE_INPUT_DEFAULTS_START( terminal )
+ DEVICE_INPUT_DEFAULTS( "RS232_RXBAUD", 0xff, RS232_BAUD_115200 )
+ DEVICE_INPUT_DEFAULTS( "RS232_TXBAUD", 0xff, RS232_BAUD_115200 )
+ 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
+
+void rc2014_micro::device_add_mconfig(machine_config &config)
+{
+ Z80(config, m_maincpu, MAIN_CLOCK);
+ m_maincpu->set_addrmap(AS_PROGRAM, &rc2014_micro::addrmap_mem);
+ m_maincpu->set_addrmap(AS_IO, &rc2014_micro::addrmap_io);
+
+ clock_device &clock(CLOCK(config, "clock", MAIN_CLOCK));
+ clock.signal_handler().append(FUNC(rc2014_micro::clk_w));
+ clock.signal_handler().append(m_acia, FUNC(acia6850_device::write_txc));
+ clock.signal_handler().append(m_acia, FUNC(acia6850_device::write_rxc));
+
+ ACIA6850(config, m_acia, 0);
+ m_acia->txd_handler().set("rs232", FUNC(rs232_port_device::write_txd));
+ m_acia->txd_handler().append(FUNC(rc2014_micro::tx_w));
+ m_acia->rts_handler().set("rs232", FUNC(rs232_port_device::write_rts));
+ m_acia->irq_handler().set_inputline(m_maincpu, INPUT_LINE_IRQ0);
+
+ rs232_port_device &rs232(RS232_PORT(config, "rs232", default_rs232_devices, "terminal"));
+ rs232.rxd_handler().set(m_acia, FUNC(acia6850_device::write_rxd));
+ rs232.set_option_device_input_defaults("terminal", DEVICE_INPUT_DEFAULTS_NAME(terminal));
+ rs232.set_option_device_input_defaults("null_modem", DEVICE_INPUT_DEFAULTS_NAME(terminal));
+}
+
+static INPUT_PORTS_START( rc2014_micro_jumpers )
+ // JP1 is used to enable power from USB-to-Serial cable
+ PORT_START("JP2-JP4")
+ PORT_CONFNAME( 0x7, 0x0, "ROM Bank (A13-A15)" )
+ PORT_CONFSETTING( 0x0, "BASIC" )
+ PORT_CONFSETTING( 0x1, "EMPTY1" )
+ PORT_CONFSETTING( 0x2, "EMPTY2" )
+ PORT_CONFSETTING( 0x3, "EMPTY3" )
+ PORT_CONFSETTING( 0x4, "EMPTY4" )
+ PORT_CONFSETTING( 0x5, "EMPTY5" )
+ PORT_CONFSETTING( 0x6, "EMPTY6" )
+ PORT_CONFSETTING( 0x7, "SCM" )
+ PORT_START("ROM")
+ PORT_CONFNAME( 0x1, 0x1, "ROM Socket" )
+ PORT_CONFSETTING( 0x0, "Empty" )
+ PORT_CONFSETTING( 0x1, "Populated" )
+INPUT_PORTS_END
+
+ioport_constructor rc2014_micro::device_input_ports() const
+{
+ return INPUT_PORTS_NAME( rc2014_micro_jumpers );
+}
+
+ROM_START(rc2014_rom)
+ ROM_REGION( 0x10000, "rom",0 )
+ ROM_LOAD( "r0000009.bin", 0x0000, 0x10000, CRC(3fb1ced7) SHA1(40a030b931ebe6cca654ce056c228297f245b057) )
+ROM_END
+
+const tiny_rom_entry *rc2014_micro::device_rom_region() const
+{
+ return ROM_NAME( rc2014_rom );
+}
+
+//**************************************************************************
+// RC2014 Mini CP/M Upgrade module
+// Module author: Spencer Owen
+//**************************************************************************
+
+class rc2014_mini_cpm : public device_t, public device_rc2014_card_interface
+{
+public:
+ // construction/destruction
+ rc2014_mini_cpm(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock);
+
+protected:
+ // device_t implementation
+ virtual void device_start() override ATTR_COLD;
+ virtual void device_reset() override ATTR_COLD;
+ virtual void device_post_load() override { update_banks(); }
+ virtual void device_add_mconfig(machine_config &config) override ATTR_COLD;
+ virtual ioport_constructor device_input_ports() const override ATTR_COLD;
+ virtual const tiny_rom_entry *device_rom_region() const override ATTR_COLD;
+
+ 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); }
+ void reset_bank_w(offs_t, uint8_t) { m_view_num = 0; update_banks(); }
+ void toggle_bank_w(offs_t, uint8_t) { m_view_num = m_view_num ? 0 : 1; update_banks(); }
+
+private:
+ void update_banks() { m_view.select(m_view_num); }
+
+ // base-class members
+ uint8_t m_view_num;
+ std::unique_ptr<u8[]> m_ram;
+
+ required_device<ata_interface_device> m_ata;
+ required_device<rc2014_bus_device> m_rc2014_bus;
+ required_memory_region m_rom;
+ required_ioport m_jp1;
+ memory_view m_view;
+ memory_bank_creator m_rombank;
+ memory_bank_creator m_rambank;
+};
+
+rc2014_mini_cpm::rc2014_mini_cpm(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock)
+ : device_t(mconfig, RC2014_MINI_CPM, tag, owner, clock)
+ , device_rc2014_card_interface(mconfig, *this)
+ , m_ata(*this, "ata")
+ , m_rc2014_bus(*this, ":bus")
+ , m_rom(*this, "rom")
+ , m_jp1(*this, "JP1-JP2")
+ , m_view(*this, "view")
+ , m_rombank(*this, "bank")
+ , m_rambank(*this, "ram")
+{
+}
+
+void rc2014_mini_cpm::device_start()
+{
+ // Additional 32K RAM
+ m_ram = std::make_unique<u8[]>(0x8000);
+ std::fill_n(m_ram.get(), 0x8000, 0xff);
+ save_pointer(NAME(m_ram), 0x8000);
+ save_item(NAME(m_view_num));
+
+ // Install RAM/ROM
+ m_bus->installer(AS_PROGRAM)->install_view(0x0000, 0x7fff, m_view);
+ m_view[0].install_read_bank(0x0000, 0x3fff, m_rombank);
+ m_view[0].install_write_bank(0x0000, 0x3fff, m_rambank);
+ m_view[1].install_readwrite_bank(0x0000, 0x7fff, m_rambank);
+
+ // Setup banks
+ m_rombank->configure_entry(0, m_rom->base() + 0x0000);
+ m_rombank->configure_entry(1, m_rom->base() + 0x4000);
+ m_rombank->configure_entry(2, m_rom->base() + 0x8000);
+ m_rombank->configure_entry(3, m_rom->base() + 0xc000);
+
+ m_rambank->configure_entry(0, m_ram.get());
+}
+
+void rc2014_mini_cpm::device_reset()
+{
+ // A15-A8, A7 and A2-A0 not connected, A6 must be 0
+ m_bus->installer(AS_IO)->install_write_handler(0x30, 0x30, 0, 0xff87, 0, write8sm_delegate(*this, FUNC(rc2014_mini_cpm::reset_bank_w)));
+ m_bus->installer(AS_IO)->install_write_handler(0x38, 0x38, 0, 0xff87, 0, write8sm_delegate(*this, FUNC(rc2014_mini_cpm::toggle_bank_w)));
+ // A15-A8 and A7 not connected
+ m_bus->installer(AS_IO)->install_readwrite_handler(0x10, 0x17, 0, 0xff80, 0, read8sm_delegate(*this, FUNC(rc2014_mini_cpm::ide_cs0_r)), write8sm_delegate(*this, FUNC(rc2014_mini_cpm::ide_cs0_w)));
+
+ // Set default banks
+ m_view_num = 0;
+ m_rombank->set_entry(m_jp1->read());
+ update_banks();
+}
+
+void rc2014_mini_cpm::device_add_mconfig(machine_config &config)
+{
+ ATA_INTERFACE(config, m_ata).options(ata_devices, "hdd", nullptr, true);
+
+ RC2014_SLOT(config, "1", m_rc2014_bus, rc2014_bus_modules, nullptr);
+ RC2014_SLOT(config, "2", m_rc2014_bus, rc2014_bus_modules, nullptr);
+}
+
+static INPUT_PORTS_START( rc2014_mini_cpm_jumpers )
+ PORT_START("JP1-JP2")
+ PORT_CONFNAME( 0x3, 0x1, "Bank" )
+ PORT_CONFSETTING( 0x0, "0" )
+ PORT_CONFSETTING( 0x1, "1" )
+ PORT_CONFSETTING( 0x2, "2" )
+ PORT_CONFSETTING( 0x3, "3" )
+INPUT_PORTS_END
+
+ioport_constructor rc2014_mini_cpm::device_input_ports() const
+{
+ return INPUT_PORTS_NAME( rc2014_mini_cpm_jumpers );
+}
+
+ROM_START(rc2014_mini_cpm)
+ ROM_REGION( 0x10000, "rom",0 )
+ ROM_LOAD( "r0881099.bin", 0x00000, 0x10000, CRC(5619f399) SHA1(c96e9ebd6ce019c264aaea156532fcf807d4c74c) )
+ROM_END
+
+const tiny_rom_entry *rc2014_mini_cpm::device_rom_region() const
+{
+ return ROM_NAME( rc2014_mini_cpm );
+}
+
+} // anonymous namespace
+
+
+//**************************************************************************
+// DEVICE DEFINITIONS
+//**************************************************************************
+
+DEFINE_DEVICE_TYPE_PRIVATE(RC2014_MICRO, device_rc2014_card_interface, rc2014_micro, "rc2014_micro", "RC2014 Micro module")
+DEFINE_DEVICE_TYPE_PRIVATE(RC2014_MINI_CPM, device_rc2014_card_interface, rc2014_mini_cpm, "rc2014_mini_cpm", "Mini CP/M Upgrade module")
diff --git a/src/devices/bus/rc2014/micro.h b/src/devices/bus/rc2014/micro.h
new file mode 100644
index 00000000000..f5683d0a426
--- /dev/null
+++ b/src/devices/bus/rc2014/micro.h
@@ -0,0 +1,19 @@
+// license:BSD-3-Clause
+// copyright-holders:Miodrag Milanovic
+/**********************************************************************
+
+ RC2014 Micro Module
+
+**********************************************************************/
+
+#ifndef MAME_BUS_RC2014_MICRO_H
+#define MAME_BUS_RC2014_MICRO_H
+
+#pragma once
+
+#include "bus/rc2014/rc2014.h"
+
+DECLARE_DEVICE_TYPE(RC2014_MICRO, device_rc2014_card_interface)
+DECLARE_DEVICE_TYPE(RC2014_MINI_CPM, device_rc2014_card_interface)
+
+#endif // MAME_BUS_RC2014_MICRO_H
diff --git a/src/devices/bus/rc2014/modules.cpp b/src/devices/bus/rc2014/modules.cpp
new file mode 100644
index 00000000000..8ce74ae2cc1
--- /dev/null
+++ b/src/devices/bus/rc2014/modules.cpp
@@ -0,0 +1,88 @@
+// license:BSD-3-Clause
+// copyright-holders:Miodrag Milanovic
+/**********************************************************************
+
+ RC2014 Modules
+
+**********************************************************************/
+
+#include "emu.h"
+#include "bus/rc2014/rc2014.h"
+
+#include "bus/rc2014/cf.h"
+#include "bus/rc2014/clock.h"
+#include "bus/rc2014/edge.h"
+#include "bus/rc2014/fdc.h"
+#include "bus/rc2014/ide.h"
+#include "bus/rc2014/micro.h"
+#include "bus/rc2014/ram.h"
+#include "bus/rc2014/rom.h"
+#include "bus/rc2014/romram.h"
+#include "bus/rc2014/rtc.h"
+#include "bus/rc2014/serial.h"
+#include "bus/rc2014/sound.h"
+#include "bus/rc2014/z180cpu.h"
+#include "bus/rc2014/z80cpu.h"
+
+void rc2014_bus_modules(device_slot_interface &device)
+{
+ device.option_add("z80", RC2014_Z80CPU);
+ // Z80 2.1 on standard bus is same as Z80 module
+ device.option_add("z80_21_40p", RC2014_Z80CPU);
+ device.option_add("clock", RC2014_SINGLE_CLOCK);
+ device.option_add("dual_clk_40p", RC2014_DUAL_CLOCK_40P);
+ device.option_add("ram32k", RC2014_RAM_32K);
+ device.option_add("ram64k_40p", RC2014_RAM_64K_40P);
+ device.option_add("sw_rom", RC2014_SWITCHABLE_ROM);
+ device.option_add("serial", RC2014_SERIAL_IO);
+ device.option_add("sio_40p", RC2014_DUAL_SERIAL_40P);
+ device.option_add("cf", RC2014_COMPACT_FLASH);
+ device.option_add("rom_ram", RC2014_ROM_RAM_512);
+ device.option_add("rtc", RC2014_DS1302_RTC);
+ device.option_add("ym_sound", RC2014_YM2149_SOUND);
+ device.option_add("ay_sound", RC2014_AY8190_SOUND);
+ device.option_add("82c55_ide", RC2014_82C55_IDE);
+ device.option_add("ide_hdd", RC2014_IDE_HDD);
+ device.option_add("fdc_smc", RC2014_FDC9266);
+ device.option_add("fdc_wdc", RC2014_WD37C65);
+ device.option_add("micro", RC2014_MICRO);
+}
+
+// Mini mezzanine boards
+void rc2014_mini_bus_modules(device_slot_interface &device)
+{
+ rc2014_bus_modules(device);
+ device.option_add("mini", RC2014_MICRO);
+ device.option_add("mini_cpm", RC2014_MINI_CPM);
+}
+
+void rc2014_bus_edge_modules(device_slot_interface &device)
+{
+ device.option_add("sc141", RC2014_SC141);
+ device.option_add("sc147", RC2014_SC147);
+ rc2014_bus_modules(device);
+}
+void rc2014_ext_bus_modules(device_slot_interface &device)
+{
+ rc2014_bus_modules(device);
+ device.option_add("z80_21", RC2014_Z80CPU_21);
+ device.option_add("dual_clk", RC2014_DUAL_CLOCK);
+ device.option_add("sio", RC2014_DUAL_SERIAL);
+ device.option_add("page_rom", RC2014_PAGABLE_ROM);
+ device.option_add("ram64k", RC2014_RAM_64K);
+}
+
+void rc2014_rc80_bus_modules(device_slot_interface &device)
+{
+ rc2014_ext_bus_modules(device);
+ device.option_add("sc111", RC2014_SC111);
+ device.option_add("sc119", RC2014_SC119);
+}
+
+void rc2014_rc80_bus_edge_modules(device_slot_interface &device)
+{
+ device.option_add("sc106", RC2014_SC106);
+ device.option_add("sc107", RC2014_SC107);
+ device.option_add("sc113", RC2014_SC113);
+ rc2014_rc80_bus_modules(device);
+}
diff --git a/src/devices/bus/rc2014/modules.h b/src/devices/bus/rc2014/modules.h
new file mode 100644
index 00000000000..6f0368b0236
--- /dev/null
+++ b/src/devices/bus/rc2014/modules.h
@@ -0,0 +1,22 @@
+// license:BSD-3-Clause
+// copyright-holders:Miodrag Milanovic
+/**********************************************************************
+
+ RC2014 Modules
+
+**********************************************************************/
+
+#ifndef MAME_BUS_RC2014_MODULES_H
+#define MAME_BUS_RC2014_MODULES_H
+
+#pragma once
+
+// supported devices
+void rc2014_bus_modules(device_slot_interface &device);
+void rc2014_bus_edge_modules(device_slot_interface &device);
+void rc2014_mini_bus_modules(device_slot_interface &device);
+void rc2014_ext_bus_modules(device_slot_interface &device);
+void rc2014_rc80_bus_modules(device_slot_interface &device);
+void rc2014_rc80_bus_edge_modules(device_slot_interface &device);
+
+#endif // MAME_BUS_RC2014_MODULES_H
diff --git a/src/devices/bus/rc2014/ram.cpp b/src/devices/bus/rc2014/ram.cpp
new file mode 100644
index 00000000000..1e42dd3113e
--- /dev/null
+++ b/src/devices/bus/rc2014/ram.cpp
@@ -0,0 +1,216 @@
+// license:BSD-3-Clause
+// copyright-holders:Miodrag Milanovic
+/***************************************************************************
+
+ RC2014 RAM Module
+
+****************************************************************************/
+
+#include "emu.h"
+#include "ram.h"
+
+namespace {
+
+//**************************************************************************
+// RC2014 32K RAM module
+// Module author: Spencer Owen
+//**************************************************************************
+
+class ram_32k_device : public device_t, public device_rc2014_card_interface
+{
+public:
+ // construction/destruction
+ ram_32k_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock);
+
+protected:
+ // device_t implementation
+ virtual void device_start() override ATTR_COLD;
+
+private:
+ std::unique_ptr<u8[]> m_ram;
+};
+
+ram_32k_device::ram_32k_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock)
+ : device_t(mconfig, RC2014_RAM_32K, tag, owner, clock)
+ , device_rc2014_card_interface(mconfig, *this)
+ , m_ram(nullptr)
+{
+}
+
+void ram_32k_device::device_start()
+{
+ m_ram = std::make_unique<u8[]>(0x8000);
+ std::fill_n(m_ram.get(), 0x8000, 0xff);
+ save_pointer(NAME(m_ram), 0x8000);
+
+ m_bus->installer(AS_PROGRAM)->install_ram(0x8000, 0xffff, m_ram.get());
+}
+
+//**************************************************************************
+// RC2014 64K RAM module
+// Module author: Spencer Owen
+//**************************************************************************
+
+//**************************************************************************
+// ram_64k_base
+//**************************************************************************
+
+class ram_64k_base : public device_t
+{
+protected:
+ // construction/destruction
+ ram_64k_base(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, u32 clock);
+
+ // device_t implementation
+ virtual void device_start() override ATTR_COLD;
+ virtual void device_reset() override ATTR_COLD;
+ virtual void device_post_load() override { update_banks(); }
+
+ virtual ioport_constructor device_input_ports() const override ATTR_COLD;
+
+ void page_w(int state) { m_bank = state; update_banks(); }
+
+ virtual void update_banks() = 0;
+
+ // base-class members
+ int m_bank;
+ std::unique_ptr<u8[]> m_ram;
+ required_ioport m_start_addr;
+ required_ioport m_paged;
+};
+
+ram_64k_base::ram_64k_base(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, u32 clock)
+ : device_t(mconfig, type, tag, owner, clock)
+ , m_bank(0)
+ , m_ram(nullptr)
+ , m_start_addr(*this, "START_ADDR")
+ , m_paged(*this, "PAGED")
+{
+}
+
+void ram_64k_base::device_start()
+{
+ m_ram = std::make_unique<u8[]>(0x10000);
+ std::fill_n(m_ram.get(), 0x10000, 0xff);
+ save_pointer(NAME(m_ram), 0x10000);
+ save_item(NAME(m_bank));
+}
+
+void ram_64k_base::device_reset()
+{
+ m_bank = 0;
+ update_banks();
+}
+
+static INPUT_PORTS_START( ram_64k_jumpers )
+ PORT_START("START_ADDR")
+ PORT_CONFNAME( 0x7, 0x0, "Start address" )
+ PORT_CONFSETTING( 0x0, "0x0000" )
+ PORT_CONFSETTING( 0x1, "0x1000" )
+ PORT_CONFSETTING( 0x2, "0x2000" )
+ PORT_CONFSETTING( 0x4, "0x4000" )
+ PORT_START("PAGED")
+ PORT_CONFNAME( 0x1, 0x1, "Paged" )
+ PORT_CONFSETTING( 0x0, DEF_STR( No ) )
+ PORT_CONFSETTING( 0x1, DEF_STR( Yes ) )
+INPUT_PORTS_END
+
+ioport_constructor ram_64k_base::device_input_ports() const
+{
+ return INPUT_PORTS_NAME( ram_64k_jumpers );
+}
+
+//**************************************************************************
+// RC2014 64K RAM module in extended bus
+//**************************************************************************
+
+class ram_64k_device : public ram_64k_base, public device_rc2014_ext_card_interface
+{
+public:
+ // construction/destruction
+ ram_64k_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock);
+
+protected:
+ // device_t implementation
+ virtual void device_reset() override ATTR_COLD;
+
+ // 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)
+ : ram_64k_base(mconfig, RC2014_RAM_64K, tag, owner, clock)
+ , device_rc2014_ext_card_interface(mconfig, *this)
+{
+}
+
+void ram_64k_device::device_reset()
+{
+ ram_64k_base::device_reset();
+ if (m_paged->read())
+ m_bus->installer(AS_PROGRAM)->install_ram(0x8000, 0xffff, m_ram.get() + 0x8000);
+ else
+ 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::update_banks()
+{
+ if (m_paged->read() == 0) return; // If not paged skip
+
+ if (m_bank == 0)
+ m_bus->installer(AS_PROGRAM)->install_writeonly(0x0000, 0x7fff, m_ram.get());
+ else
+ m_bus->installer(AS_PROGRAM)->install_ram(0x0000, 0x7fff, m_ram.get());
+}
+
+//**************************************************************************
+// RC2014 64K RAM module in standard bus
+//**************************************************************************
+
+class ram_64k_device_40pin : public ram_64k_base, public device_rc2014_card_interface
+{
+public:
+ // construction/destruction
+ ram_64k_device_40pin(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock);
+
+protected:
+ // device_t implementation
+ virtual void device_reset() override ATTR_COLD;
+
+ // base-class overrides
+ void update_banks() override {};
+};
+
+ram_64k_device_40pin::ram_64k_device_40pin(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock)
+ : ram_64k_base(mconfig, RC2014_RAM_64K_40P, tag, owner, clock)
+ , device_rc2014_card_interface(mconfig, *this)
+{
+}
+
+void ram_64k_device_40pin::device_reset()
+{
+ ram_64k_base::device_reset();
+ // page pin not connected so we can set all at once
+ if (m_paged->read())
+ {
+ m_bus->installer(AS_PROGRAM)->install_ram(0x8000, 0xffff, m_ram.get() + 0x8000);
+ m_bus->installer(AS_PROGRAM)->install_writeonly(0x0000, 0x7fff, m_ram.get());
+ }
+ else
+ {
+ m_bus->installer(AS_PROGRAM)->install_ram(m_start_addr->read() * 0x1000, 0xffff, m_ram.get() + m_start_addr->read() * 0x1000);
+ }
+}
+
+} // anonymous namespace
+
+
+//**************************************************************************
+// DEVICE DEFINITIONS
+//**************************************************************************
+
+DEFINE_DEVICE_TYPE_PRIVATE(RC2014_RAM_32K, device_rc2014_card_interface, ram_32k_device, "rc2014_ram_32k", "RC2014 32K RAM module")
+DEFINE_DEVICE_TYPE_PRIVATE(RC2014_RAM_64K, device_rc2014_ext_card_interface, ram_64k_device, "rc2014_ram_64k", "RC2014 64K RAM module")
+DEFINE_DEVICE_TYPE_PRIVATE(RC2014_RAM_64K_40P, device_rc2014_card_interface, ram_64k_device_40pin, "rc2014_ram_64k_40p", "RC2014 64K RAM module (40 pin)")
diff --git a/src/devices/bus/rc2014/ram.h b/src/devices/bus/rc2014/ram.h
new file mode 100644
index 00000000000..c55424b7871
--- /dev/null
+++ b/src/devices/bus/rc2014/ram.h
@@ -0,0 +1,20 @@
+// license:BSD-3-Clause
+// copyright-holders:Miodrag Milanovic
+/**********************************************************************
+
+ RC2014 RAM Module
+
+**********************************************************************/
+
+#ifndef MAME_BUS_RC2014_RAM_H
+#define MAME_BUS_RC2014_RAM_H
+
+#pragma once
+
+#include "bus/rc2014/rc2014.h"
+
+DECLARE_DEVICE_TYPE(RC2014_RAM_32K, device_rc2014_card_interface)
+DECLARE_DEVICE_TYPE(RC2014_RAM_64K, device_rc2014_ext_card_interface)
+DECLARE_DEVICE_TYPE(RC2014_RAM_64K_40P, device_rc2014_card_interface)
+
+#endif // MAME_BUS_RC2014_RAM_H
diff --git a/src/devices/bus/rc2014/rc2014.cpp b/src/devices/bus/rc2014/rc2014.cpp
new file mode 100644
index 00000000000..baee04e8e37
--- /dev/null
+++ b/src/devices/bus/rc2014/rc2014.cpp
@@ -0,0 +1,361 @@
+// license:BSD-3-Clause
+// copyright-holders:Miodrag Milanovic
+/***************************************************************************
+
+ RC2014 Bus Device
+
+***************************************************************************/
+
+#include "emu.h"
+#include "rc2014.h"
+
+//**************************************************************************
+// RC2014 Standard Bus
+//**************************************************************************
+
+//-------------------------------------------------
+// rc2014_bus_device
+//-------------------------------------------------
+
+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_daisy_chain{}
+{
+}
+
+rc2014_bus_device::rc2014_bus_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
+ : rc2014_bus_device(mconfig, RC2014_BUS, tag, owner, clock)
+{
+}
+
+rc2014_bus_device::~rc2014_bus_device()
+{
+ for(size_t i = 0; i < m_daisy.size(); i++)
+ delete [] m_daisy_chain[i];
+ delete [] m_daisy_chain;
+}
+
+void rc2014_bus_device::device_start()
+{
+}
+
+void rc2014_bus_device::device_reset()
+{
+ if (m_installer[AS_IO])
+ 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);
+ notify_clock_changed();
+}
+
+void rc2014_bus_device::assign_installer(int index, address_space_installer *installer)
+{
+ if (m_installer[index] != nullptr )
+ throw emu_fatalerror("Address installer already set on RC2014 bus !!!");
+ m_installer[index] = installer;
+}
+
+address_space_installer *rc2014_bus_device::installer(int index) const
+{
+ assert(index >= 0 && index < 4);
+ if (m_installer[index] == nullptr )
+ throw emu_fatalerror("Address installer not set on RC2014 bus !!! Add CPU module.");
+ return m_installer[index];
+}
+
+const z80_daisy_config* rc2014_bus_device::get_daisy_chain()
+{
+ m_daisy_chain = new char*[m_daisy.size() + 1];
+ for(size_t i = 0; i < m_daisy.size(); i++)
+ {
+ m_daisy_chain[i] = new char[m_daisy[i].size() + 1];
+ strcpy(m_daisy_chain[i], m_daisy[i].c_str());
+ }
+ m_daisy_chain[m_daisy.size()] = nullptr;
+ 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
+//-------------------------------------------------
+
+device_rc2014_card_interface::device_rc2014_card_interface(const machine_config &mconfig, device_t &device)
+ : device_interface(device, "rc2014bus")
+ , m_bus(nullptr)
+{
+}
+
+//-------------------------------------------------
+// rc2014_slot_device
+//-------------------------------------------------
+
+rc2014_slot_device::rc2014_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_bus(*this, finder_base::DUMMY_TAG)
+{
+}
+
+rc2014_slot_device::rc2014_slot_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
+ : rc2014_slot_device(mconfig, RC2014_SLOT, tag, owner, clock)
+{
+}
+
+void rc2014_slot_device::device_start()
+{
+}
+
+void rc2014_slot_device::device_resolve_objects()
+{
+ device_rc2014_card_interface *const card(dynamic_cast<device_rc2014_card_interface *>(get_card_device()));
+
+ if (card)
+ m_bus->add_card(*card);
+}
+
+//**************************************************************************
+// RC2014 Extended Bus
+//**************************************************************************
+
+//-------------------------------------------------
+// rc2014_ext_bus_device
+//-------------------------------------------------
+
+rc2014_ext_bus_device::rc2014_ext_bus_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
+ : rc2014_ext_bus_device(mconfig, RC2014_EXT_BUS, tag, owner, clock)
+{
+}
+
+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)
+{
+}
+
+void rc2014_ext_bus_device::add_card(device_rc2014_ext_card_interface &card)
+{
+ card.m_bus = this;
+ m_device_list.emplace_back(card);
+}
+
+//-------------------------------------------------
+// device_rc2014_ext_card_interface
+//-------------------------------------------------
+
+device_rc2014_ext_card_interface::device_rc2014_ext_card_interface(const machine_config &mconfig, device_t &device)
+ : device_rc2014_card_interface(mconfig, device)
+ , m_bus(nullptr)
+{
+}
+//-------------------------------------------------
+// rc2014_ext_slot_device
+//-------------------------------------------------
+
+rc2014_ext_slot_device::rc2014_ext_slot_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
+ : rc2014_ext_slot_device(mconfig, RC2014_EXT_SLOT, tag, owner, clock)
+{
+}
+
+rc2014_ext_slot_device::rc2014_ext_slot_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock)
+ : rc2014_slot_device(mconfig, type, tag, owner, clock)
+{
+}
+
+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)
+ ((rc2014_ext_bus_device*)m_bus.lookup())->add_card(*card);
+}
+
+//**************************************************************************
+// RC2014 RC80 Bus
+//**************************************************************************
+
+//-------------------------------------------------
+// rc2014_rc80_bus_device
+//-------------------------------------------------
+
+rc2014_rc80_bus_device::rc2014_rc80_bus_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
+ : rc2014_rc80_bus_device(mconfig, RC2014_RC80_BUS, tag, owner, clock)
+{
+}
+
+rc2014_rc80_bus_device::rc2014_rc80_bus_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock)
+ : rc2014_ext_bus_device(mconfig, type, tag, owner, clock)
+
+{
+}
+
+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
+//-------------------------------------------------
+
+device_rc2014_rc80_card_interface::device_rc2014_rc80_card_interface(const machine_config &mconfig, device_t &device)
+ : device_rc2014_ext_card_interface(mconfig, device)
+ , m_bus(nullptr)
+{
+}
+
+//-------------------------------------------------
+// rc2014_rc80_slot_device
+//-------------------------------------------------
+
+rc2014_rc80_slot_device::rc2014_rc80_slot_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
+ : rc2014_ext_slot_device(mconfig, RC2014_RC80_SLOT, tag, owner, clock)
+{
+}
+
+void rc2014_rc80_slot_device::device_start()
+{
+}
+
+void rc2014_rc80_slot_device::device_resolve_objects()
+{
+ rc2014_ext_slot_device::device_resolve_objects();
+ device_rc2014_rc80_card_interface *const card(dynamic_cast<device_rc2014_rc80_card_interface *>(get_card_device()));
+
+ if (card)
+ ((rc2014_rc80_bus_device*)m_bus.lookup())->add_card(*card);
+}
+
+//**************************************************************************
+// DEVICE DEFINITIONS
+//**************************************************************************
+
+DEFINE_DEVICE_TYPE(RC2014_BUS, rc2014_bus_device, "rc2014_bus", "RC2014 Standard Bus")
+DEFINE_DEVICE_TYPE(RC2014_SLOT, rc2014_slot_device, "rc2014_slot", "RC2014 Standard Bus Slot")
+
+DEFINE_DEVICE_TYPE(RC2014_EXT_BUS, rc2014_ext_bus_device, "rc2014_ext_bus", "RC2014 Extended Bus")
+DEFINE_DEVICE_TYPE(RC2014_EXT_SLOT, rc2014_ext_slot_device, "rc2014_ext_slot", "RC2014 Extended Bus Slot")
+
+DEFINE_DEVICE_TYPE(RC2014_RC80_BUS, rc2014_rc80_bus_device, "rc2014_rc80_bus", "RC2014 RC80 Bus")
+DEFINE_DEVICE_TYPE(RC2014_RC80_SLOT, rc2014_rc80_slot_device, "rc2014_rc80_slot", "RC2014 RC80 Bus Slot")
diff --git a/src/devices/bus/rc2014/rc2014.h b/src/devices/bus/rc2014/rc2014.h
new file mode 100644
index 00000000000..2cca6e784d7
--- /dev/null
+++ b/src/devices/bus/rc2014/rc2014.h
@@ -0,0 +1,330 @@
+// license:BSD-3-Clause
+// copyright-holders:Miodrag Milanovic
+/***************************************************************************
+
+ RC2014 Bus Device
+
+===========================================================================
+ Standard Bus| Extended Bus | RC80 RC2014 Bus
+=============|============================|================================
+ Pin Signal |Pin Signal Pin Signal |Pin # Signal Pin Signal
+=============|============================|================================
+ 1 A15 |1 Not used 1 A15 |41 #41 (custom) 1 A15
+ 2 A14 |2 Not used 2 A14 |42 #42 (custom) 2 A14
+ 3 A13 |3 Not used 3 A13 |43 #43 (custom) 3 A13
+ 4 A12 |4 Not used 4 A12 |44 #44 (custom) 4 A12
+ 5 A11 |5 Not used 5 A11 |45 #45 (custom) 5 A11
+ 6 A10 |6 Not used 6 A10 |46 #46 (custom) 6 A10
+ 7 A9 |7 Not used 7 A9 |47 #47 (custom) 7 A9
+ 8 A8 |8 Not used 8 A8 |48 #48 (custom) 8 A8
+ 9 A7 |9 Not used 9 A7 |49 A23 9 A7
+ 10 A6 |10 Not used 10 A6 |50 A22 10 A6
+ 11 A5 |11 Not used 11 A5 |51 A21 11 A5
+ 12 A4 |12 Not used 12 A4 |52 A20 12 A4
+ 13 A3 |13 Not used 13 A3 |53 A19 13 A3
+ 14 A2 |14 Not used 14 A2 |54 A18 14 A2
+ 15 A1 |15 Not used 15 A1 |55 A17 15 A1
+ 16 A0 |16 Not used 16 A0 |56 A16 16 A0
+ 17 GND |17 GND 17 GND |57 GND 17 GND
+ 18 5V |18 5V 18 5V |58 5V 18 5V
+ 19 /M1 |19 /RFSH 19 /M1 |59 /RFSH 19 /M1
+ 20 /RESET |20 PAGE(/RESET2)20 /RESET |60 PAGE 20 /RESET
+ 21 CLK |21 CLK2 21 CLK |61 CLK2 21 CLK
+ 22 /INT |22 /BUSAK 22 /INT |62 /BUSAK 22 /INT
+ 23 /MREQ |23 /HALT 23 /MREQ |63 /HALT 23 /MREQ
+ 24 /WR |24 /BUSRQ 24 /WR |64 /BUSRQ 24 /WR
+ 25 /RD |25 /WAIT 25 /RD |65 /WAIT 25 /RD
+ 26 /IORQ |26 /NMI 26 /IORQ |66 /NMI 26 /IORQ
+ 27 D0 |27 D8 27 D0 |67 #67 (custom) 27 D0
+ 28 D1 |28 D9 28 D1 |68 #68 (custom) 28 D1
+ 29 D2 |29 D10 29 D2 |69 #69 (custom) 29 D2
+ 30 D3 |30 D11 30 D3 |70 #70 (custom) 30 D3
+ 31 D4 |31 D12 31 D4 |71 #71 (custom) 31 D4
+ 32 D5 |32 D13 32 D5 |72 #72 (custom) 32 D5
+ 33 D6 |33 D14 33 D6 |73 #73 (custom) 33 D6
+ 34 D7 |34 D15 34 D7 |74 #74 (custom) 34 D7
+ 35 TX |35 TX2 35 TX |75 TX2 35 TX
+ 36 RX |36 RX2 36 RX |76 RX2 36 RX
+ 37 USER1 |37 USER5 37 USER1 |77 USER5 37 USER1
+ 38 USER2 |38 USER6 38 USER2 |78 USER6 38 USER2
+ 39 USER3 |39 USER7 39 USER3 |79 USER7 39 USER3
+ 40 USER4 |40 USER8 40 USER4 |80 USER8(IEI) 40 USER4(IEO)
+===========================================================================
+
+***************************************************************************/
+
+#ifndef MAME_BUS_RC2014_RC2014_H
+#define MAME_BUS_RC2014_RC2014_H
+
+#pragma once
+
+#include "machine/z80daisy.h"
+
+#include <functional>
+#include <vector>
+
+
+//**************************************************************************
+// TYPE DEFINITIONS
+//**************************************************************************
+
+//**************************************************************************
+// RC2014 Standard Bus
+//**************************************************************************
+
+// ======================> rc2014_bus_device
+class device_rc2014_card_interface;
+
+class rc2014_bus_device : public device_t
+{
+public:
+ // construction/destruction
+ rc2014_bus_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
+ virtual ~rc2014_bus_device();
+
+ 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()); }
+ void assign_installer(int index, address_space_installer *installer);
+ address_space_installer *installer(int index) const;
+ 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_t implementation
+ virtual void device_start() override ATTR_COLD;
+ virtual void device_reset() override ATTR_COLD;
+
+private:
+ using card_vector = std::vector<std::reference_wrapper<device_rc2014_card_interface> >;
+
+ address_space_installer *m_installer[4];
+ std::vector<std::string> m_daisy;
+ char **m_daisy_chain;
+ card_vector m_device_list;
+};
+
+// ======================> device_rc2014_card_interface
+
+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);
+
+ 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;
+};
+
+// ======================> rc2014_slot_device
+
+class rc2014_slot_device : public device_t, public device_slot_interface
+{
+public:
+ rc2014_slot_device(machine_config const &mconfig, char const *tag, device_t *owner, u32 clock);
+
+ template <typename T, typename U>
+ rc2014_slot_device(machine_config const &mconfig, char const *tag, device_t *owner, T &&bus_tag, U &&slot_options, char const *default_option, bool fixed = false)
+ : rc2014_slot_device(mconfig, tag, owner, DERIVED_CLOCK(1,1))
+ {
+ m_bus.set_tag(std::forward<T>(bus_tag));
+ option_reset();
+ slot_options(*this);
+ set_default_option(default_option);
+ set_fixed(fixed);
+ }
+
+protected:
+ rc2014_slot_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;
+ virtual void device_resolve_objects() override ATTR_COLD;
+
+ required_device<rc2014_bus_device> m_bus;
+};
+
+//**************************************************************************
+// RC2014 Extended Bus
+//**************************************************************************
+
+// ======================> rc2014_ext_bus_device
+class device_rc2014_ext_card_interface;
+
+class rc2014_ext_bus_device : public rc2014_bus_device
+{
+public:
+ // construction/destruction
+ rc2014_ext_bus_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
+
+ 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);
+
+private:
+ using card_vector = std::vector<std::reference_wrapper<device_rc2014_ext_card_interface> >;
+ card_vector m_device_list;
+};
+
+// ======================> device_rc2014_ext_card_interface
+
+class device_rc2014_ext_card_interface : public device_rc2014_card_interface
+{
+ friend class rc2014_ext_bus_device;
+
+protected:
+ // construction/destruction
+ device_rc2014_ext_card_interface(const machine_config &mconfig, device_t &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;
+};
+
+// ======================> rc2014_ext_slot_device
+
+class rc2014_ext_slot_device : public rc2014_slot_device
+{
+public:
+ rc2014_ext_slot_device(machine_config const &mconfig, char const *tag, device_t *owner, u32 clock);
+
+ template <typename T, typename U>
+ rc2014_ext_slot_device(machine_config const &mconfig, char const *tag, device_t *owner, T &&bus_tag, U &&slot_options, char const *default_option, bool fixed = false)
+ : rc2014_ext_slot_device(mconfig, tag, owner, DERIVED_CLOCK(1,1))
+ {
+ m_bus.set_tag(std::forward<T>(bus_tag));
+ option_reset();
+ slot_options(*this);
+ set_default_option(default_option);
+ set_fixed(fixed);
+ }
+
+protected:
+ rc2014_ext_slot_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;
+ virtual void device_resolve_objects() override ATTR_COLD;
+};
+
+//**************************************************************************
+// RC2014 RC80 Bus
+//**************************************************************************
+
+// ======================> rc2014_rc80_bus_device
+class device_rc2014_rc80_card_interface;
+
+class rc2014_rc80_bus_device : public rc2014_ext_bus_device
+{
+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_t implementation
+ virtual void device_start() override ATTR_COLD;
+
+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 device_rc2014_rc80_card_interface : public device_rc2014_ext_card_interface
+{
+ friend class rc2014_rc80_bus_device;
+
+protected:
+ // construction/destruction
+ device_rc2014_rc80_card_interface(const machine_config &mconfig, device_t &device);
+
+ rc2014_rc80_bus_device *m_bus;
+};
+
+// ======================> rc2014_rc80_slot_device
+
+class rc2014_rc80_slot_device : public rc2014_ext_slot_device
+{
+public:
+ rc2014_rc80_slot_device(machine_config const &mconfig, char const *tag, device_t *owner, u32 clock);
+
+ template <typename T, typename U>
+ rc2014_rc80_slot_device(machine_config const &mconfig, char const *tag, device_t *owner, T &&bus_tag, U &&slot_options, char const *default_option, bool fixed = false)
+ : rc2014_rc80_slot_device(mconfig, tag, owner, DERIVED_CLOCK(1,1))
+ {
+ m_bus.set_tag(std::forward<T>(bus_tag));
+ option_reset();
+ slot_options(*this);
+ set_default_option(default_option);
+ set_fixed(fixed);
+ }
+
+protected:
+ // device_t implementation
+ virtual void device_start() override ATTR_COLD;
+ virtual void device_resolve_objects() override ATTR_COLD;
+};
+
+
+// device type declarations
+DECLARE_DEVICE_TYPE(RC2014_BUS, rc2014_bus_device)
+DECLARE_DEVICE_TYPE(RC2014_SLOT, rc2014_slot_device)
+
+DECLARE_DEVICE_TYPE(RC2014_EXT_BUS, rc2014_ext_bus_device)
+DECLARE_DEVICE_TYPE(RC2014_EXT_SLOT, rc2014_ext_slot_device)
+
+DECLARE_DEVICE_TYPE(RC2014_RC80_BUS, rc2014_rc80_bus_device)
+DECLARE_DEVICE_TYPE(RC2014_RC80_SLOT, rc2014_rc80_slot_device)
+
+#endif // MAME_BUS_RC2014_RC2014_H
diff --git a/src/devices/bus/rc2014/rom.cpp b/src/devices/bus/rc2014/rom.cpp
new file mode 100644
index 00000000000..acdddb55c4a
--- /dev/null
+++ b/src/devices/bus/rc2014/rom.cpp
@@ -0,0 +1,262 @@
+// license:BSD-3-Clause
+// copyright-holders:Miodrag Milanovic
+/***************************************************************************
+
+ RC2014 ROM Module
+
+****************************************************************************/
+
+#include "emu.h"
+#include "rom.h"
+
+namespace {
+
+//**************************************************************************
+// RC2014 Switchable ROM module
+// Module author: Spencer Owen
+//**************************************************************************
+
+class switchable_rom_device : public device_t, public device_rc2014_card_interface
+{
+public:
+ // construction/destruction
+ switchable_rom_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock);
+
+protected:
+ // device-level overrides
+ virtual void device_start() override ATTR_COLD;
+ virtual void device_reset() override ATTR_COLD;
+ virtual ioport_constructor device_input_ports() const override ATTR_COLD;
+ virtual const tiny_rom_entry *device_rom_region() const override ATTR_COLD;
+private:
+ required_memory_region m_rom;
+ required_ioport m_rom_selector;
+};
+
+switchable_rom_device::switchable_rom_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock)
+ : device_t(mconfig, RC2014_SWITCHABLE_ROM, tag, owner, clock)
+ , device_rc2014_card_interface(mconfig, *this)
+ , m_rom(*this, "rom")
+ , m_rom_selector(*this, "A13-A15")
+{
+}
+
+void switchable_rom_device::device_start()
+{
+}
+
+void switchable_rom_device::device_reset()
+{
+ m_bus->installer(AS_PROGRAM)->install_rom(0x0000, 0x1fff, 0x0000, m_rom->base() + (m_rom_selector->read() & 7) * 0x2000);
+}
+
+static INPUT_PORTS_START( switchable_rom_jumpers )
+ PORT_START("A13-A15") /* jumpers to select ROM region */
+ PORT_CONFNAME( 0x7, 0x7, "ROM Bank" )
+ PORT_CONFSETTING( 0x0, "Bank 0" )
+ PORT_CONFSETTING( 0x1, "Bank 1" )
+ PORT_CONFSETTING( 0x2, "Bank 2" )
+ PORT_CONFSETTING( 0x3, "Bank 3" )
+ PORT_CONFSETTING( 0x4, "Bank 4" )
+ PORT_CONFSETTING( 0x5, "Bank 5" )
+ PORT_CONFSETTING( 0x6, "Bank 6" )
+ PORT_CONFSETTING( 0x7, "Bank 7" )
+INPUT_PORTS_END
+
+ioport_constructor switchable_rom_device::device_input_ports() const
+{
+ return INPUT_PORTS_NAME( switchable_rom_jumpers );
+}
+
+ROM_START(rc2014_switchable_rom)
+ ROM_REGION( 0x10000, "rom",0 )
+ //
+ // Decoding ROM labels
+ //
+ // 0 - Empty bank, available for user to program
+ // R - Microsoft BASIC, for 32k RAM, 68B50 ACIA, with origin 0x0000
+ // K - Microsoft BASIC, for 56k RAM, 68B50 ACIA, with origin 0x0000
+ // 1 - CP/M Monitor, for pageable ROM, 64k RAM, 68B50 ACIA, CF Module at 0x10, with origin at 0x0000
+ // 2 - Microsoft BASIC, for 32k RAM, SIO/2, with origin 0x0000
+ // 4 - Microsoft BASIC, for 56k RAM, SIO/2, with origin 0x0000
+ // 6 - CP/M Monitor, for pageable ROM, 64k RAM, SIO/2, CF Module at 0x10, with origin at 0x0000
+ // 88 - Small Computer Monitor for pageable ROM, 64k RAM, SIO/2 or 68B50 ACIA, with Microsoft BASIC a
+ // and CP/M boot options [Note that this is a 16k image, so Page Size needs to be set to 16k and
+ // only A14 and A15 jumpers to select]
+ // 9 - Small Computer Monitor for any ROM, any RAM, any UART
+ //
+ ROM_DEFAULT_BIOS("r0000009")
+ ROM_SYSTEM_BIOS(0, "r0000009", "BASIC 32K ACIA + SCM")
+ ROMX_LOAD( "r0000009.bin", 0x0000, 0x10000, CRC(3fb1ced7) SHA1(40a030b931ebe6cca654ce056c228297f245b057), ROM_BIOS(0))
+ ROM_SYSTEM_BIOS(1, "00001000", "CP/M Monitor ACIA")
+ ROMX_LOAD( "00001000.bin", 0x0000, 0x10000, CRC(e6509de9) SHA1(e5f3b528e972f63cd243bd5057e7e7850436b671), ROM_BIOS(1))
+ ROM_SYSTEM_BIOS(2, "k0001000", "BASIC 56K + CP/M Monitor ACIA")
+ ROMX_LOAD( "k0001000.bin", 0x0000, 0x10000, CRC(619a9c3e) SHA1(c1213316746a6e2a7d2030b283f75c4f3a9c177a), ROM_BIOS(2))
+ ROM_SYSTEM_BIOS(3, "r0001000", "BASIC 32K + CP/M Monitor ACIA")
+ ROMX_LOAD( "r0001000.bin", 0x0000, 0x10000, CRC(5b174833) SHA1(97c204ada65129ef61507faf74e29c8ec7a05064), ROM_BIOS(3))
+ ROM_SYSTEM_BIOS(4, "r0001009", "BASIC 32K + CP/M Monitor ACIA + SCM")
+ ROMX_LOAD( "r0001009.bin", 0x0000, 0x10000, CRC(074a2d70) SHA1(0077ab5e669da6e95ed2f66c9e759067c4236e36), ROM_BIOS(4))
+ROM_END
+
+const tiny_rom_entry *switchable_rom_device::device_rom_region() const
+{
+ return ROM_NAME( rc2014_switchable_rom );
+}
+
+//**************************************************************************
+// RC2014 Pageable ROM module
+// Module author: Spencer Owen
+//**************************************************************************
+
+class pagable_rom_device : public device_t, public device_rc2014_ext_card_interface
+{
+public:
+ // construction/destruction
+ pagable_rom_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock);
+
+protected:
+ // device-level overrides
+ virtual void device_start() override ATTR_COLD;
+ virtual void device_reset() override ATTR_COLD;
+ virtual void device_post_load() override { update_banks(); }
+ virtual ioport_constructor device_input_ports() const override ATTR_COLD;
+ virtual const tiny_rom_entry *device_rom_region() const override ATTR_COLD;
+
+ void reset_bank_w(offs_t, uint8_t) { m_bank = 0; update_banks(); m_bus->page_w(CLEAR_LINE);}
+ void toggle_bank_w(offs_t, uint8_t) { m_bank = m_bank ? 0 : 1; update_banks(); m_bus->page_w(m_bank ? ASSERT_LINE : CLEAR_LINE); }
+
+ void update_banks();
+private:
+ int m_bank;
+ u16 m_start_offset;
+ u16 m_end_addr;
+ required_memory_region m_rom;
+ required_ioport m_page_size_conf;
+ required_ioport_array<6> m_page_addr_conf;
+};
+
+pagable_rom_device::pagable_rom_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock)
+ : device_t(mconfig, RC2014_PAGABLE_ROM, tag, owner, clock)
+ , device_rc2014_ext_card_interface(mconfig, *this)
+ , m_bank(0)
+ , m_rom(*this, "rom")
+ , m_page_size_conf(*this, "PAGE_SIZE")
+ , m_page_addr_conf(*this, "A1%u", 0U)
+{
+}
+
+void pagable_rom_device::device_start()
+{
+ save_item(NAME(m_bank));
+}
+
+void pagable_rom_device::device_reset()
+{
+ static constexpr u16 page_size[] = { 0x0400, 0x0800, 0x1000, 0x2000, 0x4000, 0x8000 };
+ static constexpr u16 page_mask[] = { 0xfc00, 0xf800, 0xf000, 0xe000, 0xc000, 0x8000 };
+
+ int index = 0;
+ m_start_offset = 0x0000;
+ for (auto& addr : m_page_addr_conf)
+ {
+ if (addr->read() != 0)
+ m_start_offset += (addr->read() - 1) * page_size[index];
+ index++;
+ }
+ m_start_offset &= page_mask[m_page_size_conf->read()];
+ m_end_addr = page_size[m_page_size_conf->read()] - 1;
+ reset_bank_w(0,0);
+
+ // A15-A8, A7 and A2-A0 not connected, A6 must be 0
+ m_bus->installer(AS_IO)->install_write_handler(0x30, 0x30, 0, 0xff87, 0, write8sm_delegate(*this, FUNC(pagable_rom_device::reset_bank_w)));
+ m_bus->installer(AS_IO)->install_write_handler(0x38, 0x38, 0, 0xff87, 0, write8sm_delegate(*this, FUNC(pagable_rom_device::toggle_bank_w)));
+}
+
+void pagable_rom_device::update_banks()
+{
+ if (m_bank == 0)
+ m_bus->installer(AS_PROGRAM)->install_rom(0x0000, m_end_addr, 0x0000, m_rom->base() + m_start_offset);
+}
+
+static INPUT_PORTS_START( pagable_rom_jumpers )
+ PORT_START("PAGE_SIZE")
+ PORT_CONFNAME( 0x7, 0x4, "Page Size" )
+ PORT_CONFSETTING( 0x0, "1K" )
+ PORT_CONFSETTING( 0x1, "2K" )
+ PORT_CONFSETTING( 0x2, "4K" )
+ PORT_CONFSETTING( 0x3, "8K" )
+ PORT_CONFSETTING( 0x4, "16K" )
+ PORT_CONFSETTING( 0x5, "32K" )
+ PORT_START("A10")
+ PORT_CONFNAME( 0x3, 0x0, "A10" )
+ PORT_CONFSETTING( 0x0, DEF_STR( None ) )
+ PORT_CONFSETTING( 0x1, "0" )
+ PORT_CONFSETTING( 0x2, "1" )
+ PORT_START("A11")
+ PORT_CONFNAME( 0x3, 0x0, "A11" )
+ PORT_CONFSETTING( 0x0, DEF_STR( None ) )
+ PORT_CONFSETTING( 0x1, "0" )
+ PORT_CONFSETTING( 0x2, "1" )
+ PORT_START("A12")
+ PORT_CONFNAME( 0x3, 0x0, "A12" )
+ PORT_CONFSETTING( 0x0, DEF_STR( None ) )
+ PORT_CONFSETTING( 0x1, "0" )
+ PORT_CONFSETTING( 0x2, "1" )
+ PORT_START("A13")
+ PORT_CONFNAME( 0x3, 0x0, "A13" )
+ PORT_CONFSETTING( 0x0, DEF_STR( None ) )
+ PORT_CONFSETTING( 0x1, "0" )
+ PORT_CONFSETTING( 0x2, "1" )
+ PORT_START("A14")
+ PORT_CONFNAME( 0x3, 0x2, "A14" )
+ PORT_CONFSETTING( 0x0, DEF_STR( None ) )
+ PORT_CONFSETTING( 0x1, "0" )
+ PORT_CONFSETTING( 0x2, "1" )
+ PORT_START("A15")
+ PORT_CONFNAME( 0x3, 0x1, "A15" )
+ PORT_CONFSETTING( 0x0, DEF_STR( None ) )
+ PORT_CONFSETTING( 0x1, "0" )
+ PORT_CONFSETTING( 0x2, "1" )
+INPUT_PORTS_END
+
+ioport_constructor pagable_rom_device::device_input_ports() const
+{
+ return INPUT_PORTS_NAME( pagable_rom_jumpers );
+}
+
+ROM_START(rc2014_pagable_rom)
+ //
+ // Decoding ROM labels
+ //
+ // 0 - Empty bank, available for user to program
+ // R - Microsoft BASIC, for 32k RAM, 68B50 ACIA, with origin 0x0000
+ // K - Microsoft BASIC, for 56k RAM, 68B50 ACIA, with origin 0x0000
+ // 1 - CP/M Monitor, for pageable ROM, 64k RAM, 68B50 ACIA, CF Module at 0x10, with origin at 0x0000
+ // 2 - Microsoft BASIC, for 32k RAM, SIO/2, with origin 0x0000
+ // 4 - Microsoft BASIC, for 56k RAM, SIO/2, with origin 0x0000
+ // 6 - CP/M Monitor, for pageable ROM, 64k RAM, SIO/2, CF Module at 0x10, with origin at 0x0000
+ // 88 - Small Computer Monitor for pageable ROM, 64k RAM, SIO/2 or 68B50 ACIA, with Microsoft BASIC a
+ // and CP/M boot options [Note that this is a 16k image, so Page Size needs to be set to 16k and
+ // only A14 and A15 jumpers to select]
+ // 9 - Small Computer Monitor for any ROM, any RAM, any UART
+ //
+ ROM_REGION( 0x10000, "rom",0 )
+ ROM_DEFAULT_BIOS("24886009")
+ ROM_SYSTEM_BIOS(0, "24886009", "BASIC 32K/56K SIO/2 + CP/M + SCM Pagable + SCM")
+ ROMX_LOAD( "24886009.bin", 0x00000, 0x10000, CRC(2731ca52) SHA1(e9ac663cb85de4e3e041bce444712c00f46b6eb2), ROM_BIOS(0))
+ ROM_SYSTEM_BIOS(1, "24006000", "BASIC 32K/56K SIO/2 + CP/M Monitor")
+ ROMX_LOAD( "24006000.bin", 0x00000, 0x10000, CRC(3532872b) SHA1(ff5b3873abdcbe8ab48f62a9dbdf39314b938e89), ROM_BIOS(1))
+ROM_END
+
+const tiny_rom_entry *pagable_rom_device::device_rom_region() const
+{
+ return ROM_NAME( rc2014_pagable_rom );
+}
+
+}
+//**************************************************************************
+// DEVICE DEFINITIONS
+//**************************************************************************
+
+DEFINE_DEVICE_TYPE_PRIVATE(RC2014_SWITCHABLE_ROM, device_rc2014_card_interface, switchable_rom_device, "rc2014_switchable_rom", "RC2014 Switchable ROM module")
+DEFINE_DEVICE_TYPE_PRIVATE(RC2014_PAGABLE_ROM, device_rc2014_ext_card_interface, pagable_rom_device, "rc2014_pagable_rom", "RC2014 Pageable ROM module")
diff --git a/src/devices/bus/rc2014/rom.h b/src/devices/bus/rc2014/rom.h
new file mode 100644
index 00000000000..e4d92b987e0
--- /dev/null
+++ b/src/devices/bus/rc2014/rom.h
@@ -0,0 +1,19 @@
+// license:BSD-3-Clause
+// copyright-holders:Miodrag Milanovic
+/**********************************************************************
+
+ RC2014 ROM Module
+
+**********************************************************************/
+
+#ifndef MAME_BUS_RC2014_ROM_H
+#define MAME_BUS_RC2014_ROM_H
+
+#pragma once
+
+#include "bus/rc2014/rc2014.h"
+
+DECLARE_DEVICE_TYPE(RC2014_SWITCHABLE_ROM, device_rc2014_card_interface)
+DECLARE_DEVICE_TYPE(RC2014_PAGABLE_ROM, device_rc2014_ext_card_interface)
+
+#endif // MAME_BUS_RC2014_ROM_H
diff --git a/src/devices/bus/rc2014/romram.cpp b/src/devices/bus/rc2014/romram.cpp
new file mode 100644
index 00000000000..c774ba64ee7
--- /dev/null
+++ b/src/devices/bus/rc2014/romram.cpp
@@ -0,0 +1,226 @@
+// license:BSD-3-Clause
+// copyright-holders:Miodrag Milanovic
+/***************************************************************************
+
+ RC2014 ROM/RAM Module
+
+****************************************************************************/
+
+#include "emu.h"
+#include "romram.h"
+#include "machine/intelfsh.h"
+
+namespace {
+
+//**************************************************************************
+// RC2014 512K RAM / 512K Flash
+// Module author: Spencer Owen
+//**************************************************************************
+
+class rom_ram_512k_device : public device_t, public device_rc2014_card_interface
+{
+public:
+ // construction/destruction
+ rom_ram_512k_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock);
+
+protected:
+ // device-level overrides
+ 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;
+ virtual const tiny_rom_entry *device_rom_region() const override ATTR_COLD;
+
+ void page_w(offs_t offset, uint8_t data) { m_page_reg[offset & 3] = data & 0x3f; }
+ void page_en_w(offs_t, uint8_t data) { m_page_en = data & 1; }
+
+private:
+ template<uint8_t Bank> void mem_w(offs_t offset, uint8_t data);
+ template<uint8_t Bank> uint8_t mem_r(offs_t offset);
+
+ uint8_t m_page_reg[4];
+ uint8_t m_page_en;
+ std::unique_ptr<u8[]> m_ram;
+ required_device<sst_39sf040_device> m_flash;
+};
+
+rom_ram_512k_device::rom_ram_512k_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock)
+ : device_t(mconfig, RC2014_ROM_RAM_512, tag, owner, clock)
+ , device_rc2014_card_interface(mconfig, *this)
+ , m_page_reg{0,0,0,0}
+ , m_page_en(0)
+ , m_ram(nullptr)
+ , m_flash(*this, "flash")
+{
+}
+
+void rom_ram_512k_device::device_start()
+{
+ m_ram = std::make_unique<u8[]>(0x80000);
+ std::fill_n(m_ram.get(), 0x80000, 0xff);
+ save_pointer(NAME(m_ram), 0x80000);
+ save_item(NAME(m_page_en));
+ save_item(NAME(m_page_reg));
+
+ m_bus->installer(AS_PROGRAM)->install_readwrite_handler(0x0000, 0x3fff, 0, 0, 0, read8sm_delegate(*this, FUNC(rom_ram_512k_device::mem_r<0>)), write8sm_delegate(*this, FUNC(rom_ram_512k_device::mem_w<0>)));
+ m_bus->installer(AS_PROGRAM)->install_readwrite_handler(0x4000, 0x7fff, 0, 0, 0, read8sm_delegate(*this, FUNC(rom_ram_512k_device::mem_r<1>)), write8sm_delegate(*this, FUNC(rom_ram_512k_device::mem_w<1>)));
+ m_bus->installer(AS_PROGRAM)->install_readwrite_handler(0x8000, 0xbfff, 0, 0, 0, read8sm_delegate(*this, FUNC(rom_ram_512k_device::mem_r<2>)), write8sm_delegate(*this, FUNC(rom_ram_512k_device::mem_w<2>)));
+ m_bus->installer(AS_PROGRAM)->install_readwrite_handler(0xc000, 0xffff, 0, 0, 0, read8sm_delegate(*this, FUNC(rom_ram_512k_device::mem_r<3>)), write8sm_delegate(*this, FUNC(rom_ram_512k_device::mem_w<3>)));
+}
+
+void rom_ram_512k_device::device_reset()
+{
+ m_page_en = 0;
+ m_page_reg[0] = 0;
+ m_page_reg[1] = 0;
+ m_page_reg[2] = 0;
+ m_page_reg[3] = 0;
+
+ // A15-A8 and A3 not connected
+ m_bus->installer(AS_IO)->install_write_handler(0x70, 0x73, 0, 0xff08, 0, write8sm_delegate(*this, FUNC(rom_ram_512k_device::page_w)));
+ // A15-A8, A3, A1 and A0 not connected
+ m_bus->installer(AS_IO)->install_write_handler(0x74, 0x74, 0, 0xff0b, 0, write8sm_delegate(*this, FUNC(rom_ram_512k_device::page_en_w)));
+}
+
+void rom_ram_512k_device::device_add_mconfig(machine_config &config)
+{
+ SST_39SF040(config, m_flash);
+}
+
+template<uint8_t Bank>
+void rom_ram_512k_device::mem_w(offs_t offset, uint8_t data)
+{
+ if (m_page_en)
+ {
+ if (m_page_reg[Bank] & 0x20) {
+ m_ram[offset + ((m_page_reg[Bank] & 0x1f) << 14)] = data;
+ } else {
+ m_flash->write(offset + (m_page_reg[Bank] << 14), data);
+ }
+ }
+ else
+ {
+ m_flash->write(offset + (Bank << 14), data);
+ }
+}
+
+template<uint8_t Bank>
+uint8_t rom_ram_512k_device::mem_r(offs_t offset)
+{
+ if (m_page_en)
+ {
+ if ((offset>>14 == 0) && (m_page_reg[Bank] & 0x20)) {
+ return m_ram[offset + ((m_page_reg[Bank] & 0x1f) << 14)];
+ } else {
+ return m_flash->read(offset + (m_page_reg[Bank] << 14));
+ }
+ }
+ return m_flash->read(offset + (Bank << 14));
+}
+
+ROM_START(rc2014_rom_ram_512k)
+ ROM_REGION( 0x80000, "flash", 0)
+ ROM_DEFAULT_BIOS("3.0.1")
+ // Official ROMs distributed with kit
+ ROM_SYSTEM_BIOS(0, "1.512k", "RomWBW RC_Std.ROM 2.9.1-pre5")
+ ROMX_LOAD( "rc_1.512k.rom", 0x00000, 0x80000, CRC(f360d908) SHA1(e9c0c79f873eecff9184836025c13915630274c5), ROM_BIOS(0))
+ ROM_SYSTEM_BIOS(1, "2.512k", "RomWBW RC_Std.ROM 2.9.1-pre5 With PPIDE")
+ ROMX_LOAD( "rc_2.512k.rom", 0x00000, 0x80000, CRC(c3aefb4e) SHA1(34541851dc781033b00cdfbe445e1d91811da5c2), ROM_BIOS(1))
+ ROM_SYSTEM_BIOS(2, "3.512k", "RomWBW RC_Std.ROM 2.9.1-pre5 With RTC")
+ ROMX_LOAD( "rc_3.512k.rom", 0x00000, 0x80000, CRC(749f7973) SHA1(2b78bb5ad0595b63c95dc58d48c5144320237362), ROM_BIOS(2))
+ ROM_SYSTEM_BIOS(3, "4.512k", "RomWBW RC_Std.ROM 2.9.1-pre5 With PPIDE and RTC")
+ ROMX_LOAD( "rc_4.512k.rom", 0x00000, 0x80000, CRC(fbe44292) SHA1(ae0407f0a605e9b1262ce00acf393c30fd87d1e4), ROM_BIOS(3))
+ ROM_SYSTEM_BIOS(4, "5.512k", "RomWBW RC_Std.ROM 2.9.1-pre5 With WDC Floppy")
+ ROMX_LOAD( "rc_5.512k.rom", 0x00000, 0x80000, CRC(4e1d00dd) SHA1(57b21ce416a0a23e034c2efdb54f669f4b110878), ROM_BIOS(4))
+ ROM_SYSTEM_BIOS(5, "6.512k", "RomWBW RC_Std.ROM 2.9.1-pre5 With WDC Floppy and PPIDE")
+ ROMX_LOAD( "rc_6.512k.rom", 0x00000, 0x80000, CRC(f2f1535e) SHA1(9121ca4246c520169cca47fda07143de8e903b3e), ROM_BIOS(5))
+ ROM_SYSTEM_BIOS(6, "7.512k", "RomWBW RC_Std.ROM 2.9.1-pre5 With WDC Floppy and RTC")
+ ROMX_LOAD( "rc_7.512k.rom", 0x00000, 0x80000, CRC(57efe210) SHA1(b9ee93215d69c185d5af511a1105ee06e6474ff2), ROM_BIOS(6))
+ ROM_SYSTEM_BIOS(7, "8.512k", "RomWBW RC_Std.ROM 2.9.1-pre5 With WDC Floppy, PPIDE and RTC")
+ ROMX_LOAD( "rc_8.512k.rom", 0x00000, 0x80000, CRC(38cc2dfc) SHA1(6e740224276b9d0ae32bb28095c8a8ccb47c38b5), ROM_BIOS(7))
+ // Official distribution of ROMWBW
+ // Taken from https://github.com/wwarthen/RomWBW/releases
+ ROM_SYSTEM_BIOS(8, "2.9.0", "Official RomWBW 2.9.0")
+ ROMX_LOAD( "rc_std_2_9_0.rom", 0x00000, 0x80000, CRC(2045d238) SHA1(dd37c945fd531192b368d80b20b0154e6b2d2a75), ROM_BIOS(8))
+ ROM_SYSTEM_BIOS(9, "2.9.1", "Official RomWBW 2.9.1")
+ ROMX_LOAD( "rcz80_std_2_9_1.rom", 0x00000, 0x80000, CRC(f7c52c5f) SHA1(86a0dbbecfea118cf66f9f35a21f138ce64ae788), ROM_BIOS(9))
+ ROM_SYSTEM_BIOS(10, "3.0.0", "Official RomWBW 3.0.0")
+ ROMX_LOAD( "rcz80_std_3_0_0.rom", 0x00000, 0x80000, CRC(15b802f8) SHA1(0941c6b00ccdca460d64d16fb374c0380dd431ad), ROM_BIOS(10))
+ ROM_SYSTEM_BIOS(11, "3.0.1", "Official RomWBW 3.0.1")
+ ROMX_LOAD( "rcz80_std_3_0_1.rom", 0x00000, 0x80000, CRC(6d6b60c5) SHA1(5c642cb3113bc0a51562dc92c8b46bde414adb6c), ROM_BIOS(11))
+ROM_END
+
+const tiny_rom_entry *rom_ram_512k_device::device_rom_region() const
+{
+ return ROM_NAME( rc2014_rom_ram_512k );
+}
+
+//**************************************************************************
+// SC119 Z180 Memory module
+// Module author: Stephen C Cousins
+//**************************************************************************
+
+class sc119_device : public device_t, public device_rc2014_rc80_card_interface
+{
+public:
+ // construction/destruction
+ sc119_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock);
+
+protected:
+ // device-level overrides
+ virtual void device_start() override ATTR_COLD;
+ virtual void device_add_mconfig(machine_config &config) override ATTR_COLD;
+ virtual const tiny_rom_entry *device_rom_region() const override ATTR_COLD;
+
+private:
+ std::unique_ptr<u8[]> m_ram;
+ required_device<sst_39sf040_device> m_flash;
+};
+
+sc119_device::sc119_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock)
+ : device_t(mconfig, RC2014_SC119, tag, owner, clock)
+ , device_rc2014_rc80_card_interface(mconfig, *this)
+ , m_ram(nullptr)
+ , m_flash(*this, "flash")
+{
+}
+
+void sc119_device::device_start()
+{
+ m_ram = std::make_unique<u8[]>(0x80000);
+ std::fill_n(m_ram.get(), 0x80000, 0xff);
+ save_pointer(NAME(m_ram), 0x80000);
+
+ // TODO: fix intelfsh
+ //m_bus->installer(AS_PROGRAM)->install_readwrite_handler(0x00000, 0x7ffff, read8sm_delegate(m_flash, FUNC(intelfsh8_device::read)), write8sm_delegate(m_flash, FUNC(intelfsh8_device::write)));
+ m_bus->installer(AS_PROGRAM)->install_readwrite_handler(0x00000, 0x7ffff, read8sm_delegate(m_flash, FUNC(intelfsh8_device::read_raw)), write8sm_delegate(m_flash, FUNC(intelfsh8_device::write_raw)));
+ m_bus->installer(AS_PROGRAM)->install_ram(0x80000, 0xfffff, m_ram.get());
+}
+
+void sc119_device::device_add_mconfig(machine_config &config)
+{
+ SST_39SF040(config, m_flash);
+}
+
+ROM_START(sc119_rom)
+ ROM_REGION( 0x80000, "flash", 0)
+ ROM_DEFAULT_BIOS("3.0.1")
+ ROM_SYSTEM_BIOS(0, "2.9.1", "Official RomWBW 2.9.1") // requires 38400 baudrate
+ ROMX_LOAD( "rcz180_nat_2_9_1.rom", 0x00000, 0x80000, CRC(a538538f) SHA1(8f989e7e777bd37fe552d55bc0b14771c4cb340b), ROM_BIOS(0))
+ ROM_SYSTEM_BIOS(1, "3.0.0", "Official RomWBW 3.0.0")
+ ROMX_LOAD( "rcz180_nat_3_0_0.rom", 0x00000, 0x80000, CRC(9715e94e) SHA1(8dd7179a3bc471fb7fc1e5e2d1a930e8a858ab24), ROM_BIOS(1))
+ ROM_SYSTEM_BIOS(2, "3.0.1", "Official RomWBW 3.0.1")
+ ROMX_LOAD( "rcz180_nat_3_0_1.rom", 0x00000, 0x80000, CRC(a6cb0d80) SHA1(cf4ad058931f0297fd2f8f81d15eb83ecbd29376), ROM_BIOS(2))
+ROM_END
+
+const tiny_rom_entry *sc119_device::device_rom_region() const
+{
+ return ROM_NAME( sc119_rom );
+}
+
+}
+//**************************************************************************
+// DEVICE DEFINITIONS
+//**************************************************************************
+
+DEFINE_DEVICE_TYPE_PRIVATE(RC2014_ROM_RAM_512, device_rc2014_card_interface, rom_ram_512k_device, "rc2014_rom_ram_512k", "RC2014 512K RAM / 512K Flash")
+DEFINE_DEVICE_TYPE_PRIVATE(RC2014_SC119, device_rc2014_rc80_card_interface, sc119_device, "sc119", "SC119 Z180 Memory module")
diff --git a/src/devices/bus/rc2014/romram.h b/src/devices/bus/rc2014/romram.h
new file mode 100644
index 00000000000..67193b62a31
--- /dev/null
+++ b/src/devices/bus/rc2014/romram.h
@@ -0,0 +1,19 @@
+// license:BSD-3-Clause
+// copyright-holders:Miodrag Milanovic
+/**********************************************************************
+
+ RC2014 ROM/RAM Module
+
+**********************************************************************/
+
+#ifndef MAME_BUS_RC2014_ROMRAM_H
+#define MAME_BUS_RC2014_ROMRAM_H
+
+#pragma once
+
+#include "bus/rc2014/rc2014.h"
+
+DECLARE_DEVICE_TYPE(RC2014_ROM_RAM_512, device_rc2014_card_interface)
+DECLARE_DEVICE_TYPE(RC2014_SC119, device_rc2014_rc80_card_interface)
+
+#endif // MAME_BUS_RC2014_ROMRAM_H
diff --git a/src/devices/bus/rc2014/rtc.cpp b/src/devices/bus/rc2014/rtc.cpp
new file mode 100644
index 00000000000..4c3834f9928
--- /dev/null
+++ b/src/devices/bus/rc2014/rtc.cpp
@@ -0,0 +1,107 @@
+// license:BSD-3-Clause
+// copyright-holders:Miodrag Milanovic
+/***************************************************************************
+
+ RC2014 Real Time Clock
+
+****************************************************************************/
+
+#include "emu.h"
+#include "rtc.h"
+#include "machine/ds1302.h"
+
+namespace {
+
+//**************************************************************************
+// RC2014 Real Time Clock DS1302 module
+// Module author: Ed Brindley
+//**************************************************************************
+
+class rc2014_ds1302_device : public device_t, public device_rc2014_card_interface
+{
+public:
+ // construction/destruction
+ rc2014_ds1302_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock);
+
+protected:
+ // device-level overrides
+ 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;
+ virtual ioport_constructor device_input_ports() const override ATTR_COLD;
+
+ uint8_t rtc_r(offs_t offset);
+ void rtc_w(offs_t offset, uint8_t data);
+private:
+ required_device<ds1302_device> m_rtc;
+ required_ioport m_addr;
+};
+
+rc2014_ds1302_device::rc2014_ds1302_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock)
+ : device_t(mconfig, RC2014_DS1302_RTC, tag, owner, clock)
+ , device_rc2014_card_interface(mconfig, *this)
+ , m_rtc(*this, "rtc")
+ , m_addr(*this, "SW1")
+{
+}
+
+void rc2014_ds1302_device::device_start()
+{
+}
+
+void rc2014_ds1302_device::device_reset()
+{
+ // A15-A8, A1 and A0 not connected
+ m_bus->installer(AS_IO)->install_readwrite_handler(m_addr->read(), m_addr->read(), 0, 0xff03, 0, read8sm_delegate(*this, FUNC(rc2014_ds1302_device::rtc_r)), write8sm_delegate(*this, FUNC(rc2014_ds1302_device::rtc_w)));
+}
+
+void rc2014_ds1302_device::device_add_mconfig(machine_config &config)
+{
+ DS1302(config, m_rtc, 32.768_kHz_XTAL);
+}
+
+uint8_t rc2014_ds1302_device::rtc_r(offs_t offset)
+{
+ return m_rtc->io_r() ? 0x01 : 0x00;
+}
+
+void rc2014_ds1302_device::rtc_w(offs_t, uint8_t data)
+{
+ m_rtc->ce_w(BIT(data,4));
+ if (BIT(data,5)==0) m_rtc->io_w(BIT(data,7));
+ m_rtc->sclk_w(BIT(data,6));
+}
+
+static INPUT_PORTS_START( rc2014_ds1302_jumpers )
+ PORT_START("SW1")
+ PORT_DIPNAME(0x04, 0x00, "0x04") PORT_DIPLOCATION("Base Address:1")
+ PORT_DIPSETTING(0x00, DEF_STR( Off ) )
+ PORT_DIPSETTING(0x04, DEF_STR( On ) )
+ PORT_DIPNAME(0x08, 0x00, "0x08") PORT_DIPLOCATION("Base Address:2")
+ PORT_DIPSETTING(0x00, DEF_STR( Off ) )
+ PORT_DIPSETTING(0x08, DEF_STR( On ) )
+ PORT_DIPNAME(0x10, 0x00, "0x10") PORT_DIPLOCATION("Base Address:3")
+ PORT_DIPSETTING(0x00, DEF_STR( Off ) )
+ PORT_DIPSETTING(0x10, DEF_STR( On ) )
+ PORT_DIPNAME(0x20, 0x00, "0x20") PORT_DIPLOCATION("Base Address:4")
+ PORT_DIPSETTING(0x00, DEF_STR( Off ) )
+ PORT_DIPSETTING(0x20, DEF_STR( On ) )
+ PORT_DIPNAME(0x40, 0x40, "0x40") PORT_DIPLOCATION("Base Address:5")
+ PORT_DIPSETTING(0x00, DEF_STR( Off ) )
+ PORT_DIPSETTING(0x40, DEF_STR( On ) )
+ PORT_DIPNAME(0x80, 0x80, "0x80") PORT_DIPLOCATION("Base Address:6")
+ PORT_DIPSETTING(0x00, DEF_STR( Off ) )
+ PORT_DIPSETTING(0x80, DEF_STR( On ) )
+INPUT_PORTS_END
+
+ioport_constructor rc2014_ds1302_device::device_input_ports() const
+{
+ return INPUT_PORTS_NAME( rc2014_ds1302_jumpers );
+}
+
+}
+//**************************************************************************
+// DEVICE DEFINITIONS
+//**************************************************************************
+
+DEFINE_DEVICE_TYPE_PRIVATE(RC2014_DS1302_RTC, device_rc2014_card_interface, rc2014_ds1302_device, "rc2014_ds1302", "RC2014 Real Time Clock DS1302 module")
diff --git a/src/devices/bus/rc2014/rtc.h b/src/devices/bus/rc2014/rtc.h
new file mode 100644
index 00000000000..025e6cf5363
--- /dev/null
+++ b/src/devices/bus/rc2014/rtc.h
@@ -0,0 +1,18 @@
+// license:BSD-3-Clause
+// copyright-holders:Miodrag Milanovic
+/**********************************************************************
+
+ RC2014 Real Time Clock
+
+**********************************************************************/
+
+#ifndef MAME_BUS_RC2014_RTC_H
+#define MAME_BUS_RC2014_RTC_H
+
+#pragma once
+
+#include "bus/rc2014/rc2014.h"
+
+DECLARE_DEVICE_TYPE(RC2014_DS1302_RTC, device_rc2014_card_interface)
+
+#endif // MAME_BUS_RC2014_RTC_H
diff --git a/src/devices/bus/rc2014/serial.cpp b/src/devices/bus/rc2014/serial.cpp
new file mode 100644
index 00000000000..c78eaad5559
--- /dev/null
+++ b/src/devices/bus/rc2014/serial.cpp
@@ -0,0 +1,274 @@
+// license:BSD-3-Clause
+// copyright-holders:Miodrag Milanovic
+/***************************************************************************
+
+ RC2014 Serial Module
+
+****************************************************************************/
+
+#include "emu.h"
+#include "serial.h"
+
+#include "bus/rs232/rs232.h"
+#include "machine/6850acia.h"
+#include "machine/z80sio.h"
+
+
+namespace {
+
+//**************************************************************************
+// RC2014 Serial I/O module
+// Module author: Spencer Owen
+//**************************************************************************
+
+class serial_io_device : public device_t, public device_rc2014_card_interface
+{
+public:
+ // construction/destruction
+ serial_io_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock);
+
+protected:
+ // 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;
+
+ 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;
+};
+
+serial_io_device::serial_io_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock)
+ : device_t(mconfig, RC2014_SERIAL_IO, tag, owner, clock)
+ , device_rc2014_card_interface(mconfig, *this)
+ , m_acia(*this, "acia")
+{
+}
+
+void serial_io_device::device_start()
+{
+}
+
+void serial_io_device::device_reset()
+{
+ // A15-A8 and A5-A1 not connected
+ 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)));
+}
+
+
+// JP1 is used to enable power from USB-to-Serial cable
+
+static DEVICE_INPUT_DEFAULTS_START( terminal )
+ DEVICE_INPUT_DEFAULTS( "RS232_RXBAUD", 0xff, RS232_BAUD_115200 )
+ DEVICE_INPUT_DEFAULTS( "RS232_TXBAUD", 0xff, RS232_BAUD_115200 )
+ 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
+
+void serial_io_device::device_add_mconfig(machine_config &config)
+{
+ ACIA6850(config, m_acia, 0);
+ m_acia->txd_handler().set("rs232", FUNC(rs232_port_device::write_txd));
+ m_acia->txd_handler().append(FUNC(serial_io_device::tx_w));
+ m_acia->rts_handler().set("rs232", FUNC(rs232_port_device::write_rts));
+ m_acia->irq_handler().set(FUNC(serial_io_device::irq_w));
+
+ rs232_port_device &rs232(RS232_PORT(config, "rs232", default_rs232_devices, "terminal"));
+ rs232.rxd_handler().set(m_acia, FUNC(acia6850_device::write_rxd));
+ rs232.set_option_device_input_defaults("terminal", DEVICE_INPUT_DEFAULTS_NAME(terminal));
+ rs232.set_option_device_input_defaults("null_modem", DEVICE_INPUT_DEFAULTS_NAME(terminal));
+}
+
+//**************************************************************************
+// RC2014 Dual Serial module SIO/2
+// Module author: Spencer Owen
+//**************************************************************************
+
+//**************************************************************************
+// dual_serial_base
+//**************************************************************************
+
+class dual_serial_base : public device_t
+{
+protected:
+ // construction/destruction
+ dual_serial_base(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, u32 clock);
+
+ // device-level overrides
+ 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;
+ virtual ioport_constructor device_input_ports() const override ATTR_COLD;
+
+ 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;
+ required_ioport m_portb;
+ required_device<z80sio_device> m_sio;
+};
+
+dual_serial_base::dual_serial_base(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, u32 clock)
+ : device_t(mconfig, type, tag, owner, clock)
+ , m_clk_portb(0)
+ , m_portb(*this, "JP1")
+ , m_sio(*this, "sio")
+{
+}
+
+void dual_serial_base::device_start()
+{
+}
+
+void dual_serial_base::device_reset()
+{
+ m_clk_portb = m_portb->read();
+}
+
+void dual_serial_base::device_add_mconfig(machine_config &config)
+{
+ Z80SIO(config, m_sio, 0);
+ m_sio->out_txda_callback().set("rs232a", FUNC(rs232_port_device::write_txd));
+ m_sio->out_txda_callback().append(FUNC(dual_serial_base::tx_w));
+ m_sio->out_rtsa_callback().set("rs232a", FUNC(rs232_port_device::write_rts));
+ m_sio->out_txdb_callback().set("rs232b", FUNC(rs232_port_device::write_txd));
+ m_sio->out_txdb_callback().append(FUNC(dual_serial_base::tx2_w));
+ m_sio->out_rtsb_callback().set("rs232b", FUNC(rs232_port_device::write_rts));
+ m_sio->out_int_callback().set(FUNC(dual_serial_base::irq_w));
+
+ rs232_port_device &rs232a(RS232_PORT(config, "rs232a", default_rs232_devices, "terminal"));
+ rs232a.rxd_handler().set(m_sio, FUNC(z80sio_device::rxa_w));
+ rs232a.set_option_device_input_defaults("terminal", DEVICE_INPUT_DEFAULTS_NAME(terminal));
+ rs232a.set_option_device_input_defaults("null_modem", DEVICE_INPUT_DEFAULTS_NAME(terminal));
+
+ rs232_port_device &rs232b(RS232_PORT(config, "rs232b", default_rs232_devices, nullptr));
+ rs232b.rxd_handler().set(m_sio, FUNC(z80sio_device::rxb_w));
+ rs232b.set_option_device_input_defaults("terminal", DEVICE_INPUT_DEFAULTS_NAME(terminal));
+ rs232b.set_option_device_input_defaults("null_modem", DEVICE_INPUT_DEFAULTS_NAME(terminal));
+}
+
+static INPUT_PORTS_START( dual_serial_jumpers )
+ PORT_START("JP1")
+ PORT_CONFNAME( 0x1, 0x0, "Port B" )
+ PORT_CONFSETTING( 0x0, "CLK2 (Open)" )
+ PORT_CONFSETTING( 0x1, "CLK1 (Closed)" )
+ // JP2 and JP3 are used to enable power from USB-to-Serial cable
+INPUT_PORTS_END
+
+ioport_constructor dual_serial_base::device_input_ports() const
+{
+ return INPUT_PORTS_NAME( dual_serial_jumpers );
+}
+
+//**************************************************************************
+// RC2014 Dual Serial module SIO/2 in extended bus
+//**************************************************************************
+
+class dual_serial_device : public dual_serial_base, public device_rc2014_ext_card_interface
+{
+public:
+ // construction/destruction
+ dual_serial_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock);
+
+protected:
+ // device-level overrides
+ virtual void device_reset() override ATTR_COLD;
+ virtual void device_resolve_objects() override ATTR_COLD;
+
+ // base-class overrides
+ 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)
+ : dual_serial_base(mconfig, RC2014_DUAL_SERIAL, tag, owner, clock)
+ , device_rc2014_ext_card_interface(mconfig, *this)
+{
+}
+
+void dual_serial_device::device_reset()
+{
+ dual_serial_base::device_reset();
+ // A15-A8 and A2 not connected
+ m_bus->installer(AS_IO)->install_readwrite_handler(0x80, 0x80, 0, 0xff04, 0, read8smo_delegate(*m_sio, FUNC(z80sio_device::ca_r)), write8smo_delegate(*m_sio, FUNC(z80sio_device::ca_w)));
+ m_bus->installer(AS_IO)->install_readwrite_handler(0x81, 0x81, 0, 0xff04, 0, read8smo_delegate(*m_sio, FUNC(z80sio_device::da_r)), write8smo_delegate(*m_sio, FUNC(z80sio_device::da_w)));
+ m_bus->installer(AS_IO)->install_readwrite_handler(0x82, 0x82, 0, 0xff04, 0, read8smo_delegate(*m_sio, FUNC(z80sio_device::cb_r)), write8smo_delegate(*m_sio, FUNC(z80sio_device::cb_w)));
+ m_bus->installer(AS_IO)->install_readwrite_handler(0x83, 0x83, 0, 0xff04, 0, read8smo_delegate(*m_sio, FUNC(z80sio_device::db_r)), write8smo_delegate(*m_sio, FUNC(z80sio_device::db_w)));
+}
+
+void dual_serial_device::device_resolve_objects()
+{
+ m_bus->add_to_daisy_chain(m_sio->tag());
+}
+
+//**************************************************************************
+// RC2014 Dual Serial module SIO/2 in standard bus
+//**************************************************************************
+
+class dual_serial_device_40pin : public dual_serial_base, public device_rc2014_card_interface
+{
+public:
+ // construction/destruction
+ dual_serial_device_40pin(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock);
+
+protected:
+ // device-level overrides
+ virtual void device_reset() override ATTR_COLD;
+ virtual void device_resolve_objects() override ATTR_COLD;
+
+ // base-class overrides
+ 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)
+ : dual_serial_base(mconfig, RC2014_DUAL_SERIAL_40P, tag, owner, clock)
+ , device_rc2014_card_interface(mconfig, *this)
+{
+}
+
+void dual_serial_device_40pin::device_reset()
+{
+ dual_serial_base::device_reset();
+ // A15-A8 and A2 not connected
+ m_bus->installer(AS_IO)->install_readwrite_handler(0x80, 0x80, 0, 0xff04, 0, read8smo_delegate(*m_sio, FUNC(z80sio_device::ca_r)), write8smo_delegate(*m_sio, FUNC(z80sio_device::ca_w)));
+ m_bus->installer(AS_IO)->install_readwrite_handler(0x81, 0x81, 0, 0xff04, 0, read8smo_delegate(*m_sio, FUNC(z80sio_device::da_r)), write8smo_delegate(*m_sio, FUNC(z80sio_device::da_w)));
+ m_bus->installer(AS_IO)->install_readwrite_handler(0x82, 0x82, 0, 0xff04, 0, read8smo_delegate(*m_sio, FUNC(z80sio_device::cb_r)), write8smo_delegate(*m_sio, FUNC(z80sio_device::cb_w)));
+ m_bus->installer(AS_IO)->install_readwrite_handler(0x83, 0x83, 0, 0xff04, 0, read8smo_delegate(*m_sio, FUNC(z80sio_device::db_r)), write8smo_delegate(*m_sio, FUNC(z80sio_device::db_w)));
+}
+
+void dual_serial_device_40pin::device_resolve_objects()
+{
+ m_bus->add_to_daisy_chain(m_sio->tag());
+}
+
+} // anonymous namespace
+
+
+//**************************************************************************
+// DEVICE DEFINITIONS
+//**************************************************************************
+
+DEFINE_DEVICE_TYPE_PRIVATE(RC2014_SERIAL_IO, device_rc2014_card_interface, serial_io_device, "rc2014_serial_io", "RC2014 Serial I/O module")
+DEFINE_DEVICE_TYPE_PRIVATE(RC2014_DUAL_SERIAL, device_rc2014_ext_card_interface, dual_serial_device, "rc2014_dual_serial", "RC2014 Dual Serial module SIO/2")
+DEFINE_DEVICE_TYPE_PRIVATE(RC2014_DUAL_SERIAL_40P, device_rc2014_card_interface, dual_serial_device_40pin, "rc2014_dual_serial_40p", "RC2014 Dual Serial module SIO/2 (40 pin)")
diff --git a/src/devices/bus/rc2014/serial.h b/src/devices/bus/rc2014/serial.h
new file mode 100644
index 00000000000..60fe94d838f
--- /dev/null
+++ b/src/devices/bus/rc2014/serial.h
@@ -0,0 +1,20 @@
+// license:BSD-3-Clause
+// copyright-holders:Miodrag Milanovic
+/**********************************************************************
+
+ RC2014 Serial Module
+
+**********************************************************************/
+
+#ifndef MAME_BUS_RC2014_SERIAL_H
+#define MAME_BUS_RC2014_SERIAL_H
+
+#pragma once
+
+#include "bus/rc2014/rc2014.h"
+
+DECLARE_DEVICE_TYPE(RC2014_SERIAL_IO, device_rc2014_card_interface)
+DECLARE_DEVICE_TYPE(RC2014_DUAL_SERIAL, device_rc2014_ext_card_interface)
+DECLARE_DEVICE_TYPE(RC2014_DUAL_SERIAL_40P, device_rc2014_card_interface)
+
+#endif // MAME_BUS_RC2014_SERIAL_H
diff --git a/src/devices/bus/rc2014/sound.cpp b/src/devices/bus/rc2014/sound.cpp
new file mode 100644
index 00000000000..3dafc5a7fb8
--- /dev/null
+++ b/src/devices/bus/rc2014/sound.cpp
@@ -0,0 +1,207 @@
+// license:BSD-3-Clause
+// copyright-holders:Miodrag Milanovic
+/***************************************************************************
+
+ RC2014 Sound
+
+****************************************************************************/
+
+#include "emu.h"
+#include "sound.h"
+#include "sound/ay8910.h"
+#include "speaker.h"
+
+namespace {
+
+//**************************************************************************
+// RC2014 YM2149F/AY-3-8190 Sound card
+// Module author: Ed Brindley
+//**************************************************************************
+
+class rc2014_ym_ay_device : public device_t, public device_rc2014_card_interface
+{
+protected:
+ // construction/destruction
+ rc2014_ym_ay_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, u32 clock);
+
+ // device-level overrides
+ virtual void device_start() override ATTR_COLD;
+ virtual void device_reset() override ATTR_COLD;
+ virtual ioport_constructor device_input_ports() const override ATTR_COLD;
+
+ // base class members
+ required_device<ay8910_device> m_psg;
+ required_ioport_array<6> m_jp;
+};
+
+rc2014_ym_ay_device::rc2014_ym_ay_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, u32 clock)
+ : device_t(mconfig, type, tag, owner, clock)
+ , device_rc2014_card_interface(mconfig, *this)
+ , m_psg(*this, "psg")
+ , m_jp(*this, "JP%u", 1U)
+{
+}
+
+void rc2014_ym_ay_device::device_start()
+{
+}
+
+void rc2014_ym_ay_device::device_reset()
+{
+ uint16_t base;
+ uint16_t reg;
+ // A13-A8 and A0 not connected
+ uint16_t mask = 0x3f01;
+ // JP2 - Addressing mode
+ if (m_jp[1]->read())
+ {
+ base = 0x8000; // A15 for Spectrum mode
+ mask |= 0x0F00; // A7-A4 are not connected
+ }
+ else
+ {
+ base = m_jp[3]->read() << 4; // JP4
+ base |= m_jp[0]->read() ? 0x10 : 0x00; // JP1
+ mask |= 0x8000; // A15 not connected
+ }
+ // JP3 - Register mode
+ switch(m_jp[2]->read())
+ {
+ case 0 : // A14 (Spectrum)
+ reg = 0x4000; // A14
+ mask |= 0x000c; // A2 and A3 not connected
+ break;
+ case 1 : // A3 (Base + 8)
+ reg = 0x0008; // A3
+ mask |= 0x4004; // A14 and A2 not connected
+ break;
+ default : // A2 (Base + 4)
+ reg = 0x0004; // A2
+ mask |= 0x4008; // A14 and A3 not connected
+ break;
+ }
+ m_bus->installer(AS_IO)->install_write_handler(base, base, 0, mask, 0, write8smo_delegate(m_psg, FUNC(ay8910_device::data_w)));
+ m_bus->installer(AS_IO)->install_readwrite_handler(base + reg, base + reg, 0, mask, 0, read8smo_delegate(m_psg, FUNC(ay8910_device::data_r)), write8smo_delegate(m_psg, FUNC(ay8910_device::address_w)));
+ // JP5 - Clock divider
+ m_psg->set_clock(clock() / m_jp[4]->read());
+}
+
+static INPUT_PORTS_START( rc2014_ym_ay_jumpers )
+ PORT_START("JP1") // JP1 and JP7
+ PORT_CONFNAME( 0x1, 0x1, "A4 Chip Enable" )
+ PORT_CONFSETTING( 0x0, "Low" )
+ PORT_CONFSETTING( 0x1, "High" )
+ PORT_START("JP2")
+ PORT_CONFNAME( 0x1, 0x0, "Addressing mode" )
+ PORT_CONFSETTING( 0x0, "Default" )
+ PORT_CONFSETTING( 0x1, "Spectrum 128" )
+ PORT_START("JP3")
+ PORT_CONFNAME( 0x3, 0x1, "Register mode" )
+ PORT_CONFSETTING( 0x0, "A14 (Spectrum)" )
+ PORT_CONFSETTING( 0x1, "A3 (Base + 8)" )
+ PORT_CONFSETTING( 0x2, "A2 (Base + 4)" )
+ PORT_START("JP4")
+ PORT_CONFNAME( 0xf, 0xc, "Base Address" )
+ PORT_CONFSETTING( 0x0, "0x00 / 0x10" )
+ PORT_CONFSETTING( 0x8, "0x80 / 0x90" )
+ PORT_CONFSETTING( 0x4, "0x40 / 0x50" )
+ PORT_CONFSETTING( 0xc, "0xC0 / 0xD0" )
+ PORT_CONFSETTING( 0x2, "0x20 / 0x30" )
+ PORT_CONFSETTING( 0xa, "0xA0 / 0xB0" )
+ PORT_CONFSETTING( 0x6, "0x60 / 0x70" )
+ PORT_CONFSETTING( 0xe, "0xE0 / 0xF0" )
+ PORT_START("JP5")
+ PORT_CONFNAME( 0x7, 0x4, "Divide by" )
+ PORT_CONFSETTING( 0x2, "2" )
+ PORT_CONFSETTING( 0x4, "4" )
+ PORT_START("JP6")
+ PORT_CONFNAME( 0x1, 0x0, "YM2149 half clock" )
+ PORT_CONFSETTING( 0x0, DEF_STR( No ) )
+ PORT_CONFSETTING( 0x1, DEF_STR( Yes ) )
+INPUT_PORTS_END
+
+ioport_constructor rc2014_ym_ay_device::device_input_ports() const
+{
+ return INPUT_PORTS_NAME( rc2014_ym_ay_jumpers );
+}
+
+//**************************************************************************
+// With YM2149F chip
+//**************************************************************************
+
+class rc2014_ym2149_device : public rc2014_ym_ay_device
+{
+public:
+ // construction/destruction
+ rc2014_ym2149_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock);
+
+protected:
+ // device-level overrides
+ virtual void device_reset() override ATTR_COLD;
+ virtual void device_add_mconfig(machine_config &config) override ATTR_COLD;
+};
+
+rc2014_ym2149_device::rc2014_ym2149_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock)
+ : rc2014_ym_ay_device(mconfig, RC2014_YM2149_SOUND, tag, owner, clock)
+{
+}
+
+void rc2014_ym2149_device::device_reset()
+{
+ rc2014_ym_ay_device::device_reset();
+ // JP6 - YM2149 half clock
+ if (m_jp[5]->read())
+ {
+ m_psg->set_pin26_low_w();
+ }
+}
+
+void rc2014_ym2149_device::device_add_mconfig(machine_config &config)
+{
+ SPEAKER(config, "speaker", 2).front();
+
+ YM2149(config, m_psg, 0);
+ m_psg->add_route(0, "speaker", 0.25, 1);
+ m_psg->add_route(2, "speaker", 0.25, 1);
+ m_psg->add_route(1, "speaker", 0.25, 0);
+ m_psg->add_route(2, "speaker", 0.25, 0);
+}
+
+//**************************************************************************
+// With AY-3-8190 chip
+//**************************************************************************
+
+class rc2014_ay8190_device : public rc2014_ym_ay_device
+{
+public:
+ // construction/destruction
+ rc2014_ay8190_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock);
+
+protected:
+ // device-level overrides
+ virtual void device_add_mconfig(machine_config &config) override ATTR_COLD;
+};
+
+rc2014_ay8190_device::rc2014_ay8190_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock)
+ : rc2014_ym_ay_device(mconfig, RC2014_AY8190_SOUND, tag, owner, clock)
+{
+}
+
+void rc2014_ay8190_device::device_add_mconfig(machine_config &config)
+{
+ SPEAKER(config, "speaker", 2).front();
+
+ AY8910(config, m_psg, 0);
+ m_psg->add_route(0, "speaker", 0.25, 1);
+ m_psg->add_route(2, "speaker", 0.25, 1);
+ m_psg->add_route(1, "speaker", 0.25, 0);
+ m_psg->add_route(2, "speaker", 0.25, 0);
+}
+
+}
+//**************************************************************************
+// DEVICE DEFINITIONS
+//**************************************************************************
+
+DEFINE_DEVICE_TYPE_PRIVATE(RC2014_YM2149_SOUND, device_rc2014_card_interface, rc2014_ym2149_device, "rc2014_ym2149", "RC2014 YM2149F Sound card")
+DEFINE_DEVICE_TYPE_PRIVATE(RC2014_AY8190_SOUND, device_rc2014_card_interface, rc2014_ay8190_device, "rc2014_ay8190", "RC2014 AY-3-8190 Sound card")
diff --git a/src/devices/bus/rc2014/sound.h b/src/devices/bus/rc2014/sound.h
new file mode 100644
index 00000000000..a00a0e01654
--- /dev/null
+++ b/src/devices/bus/rc2014/sound.h
@@ -0,0 +1,19 @@
+// license:BSD-3-Clause
+// copyright-holders:Miodrag Milanovic
+/**********************************************************************
+
+ RC2014 Sound
+
+**********************************************************************/
+
+#ifndef MAME_BUS_RC2014_SOUND_H
+#define MAME_BUS_RC2014_SOUND_H
+
+#pragma once
+
+#include "bus/rc2014/rc2014.h"
+
+DECLARE_DEVICE_TYPE(RC2014_YM2149_SOUND, device_rc2014_card_interface)
+DECLARE_DEVICE_TYPE(RC2014_AY8190_SOUND, device_rc2014_card_interface)
+
+#endif // MAME_BUS_RC2014_SOUND_H
diff --git a/src/devices/bus/rc2014/z180cpu.cpp b/src/devices/bus/rc2014/z180cpu.cpp
new file mode 100644
index 00000000000..09e59c7c94a
--- /dev/null
+++ b/src/devices/bus/rc2014/z180cpu.cpp
@@ -0,0 +1,135 @@
+// license:BSD-3-Clause
+// copyright-holders:Miodrag Milanovic
+/***************************************************************************
+
+ RC2014 Z80 CPU Module
+
+****************************************************************************/
+
+#include "emu.h"
+#include "z180cpu.h"
+
+#include "bus/rs232/rs232.h"
+#include "cpu/z180/z180.h"
+#include "machine/clock.h"
+
+
+namespace {
+
+//**************************************************************************
+// Z180 CPU base class
+//**************************************************************************
+
+class z180cpu_base : public device_t, public device_rc2014_rc80_card_interface
+{
+protected:
+ // construction/destruction
+ z180cpu_base(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, u32 clock);
+
+ // device_t implementation
+ virtual void device_start() override ATTR_COLD;
+ virtual void device_resolve_objects() override ATTR_COLD;
+ virtual void device_add_mconfig(machine_config &config) override ATTR_COLD;
+
+ void addrmap_mem(address_map &map) { map.unmap_value_high(); }
+ void addrmap_io(address_map &map) { map.unmap_value_high(); }
+
+ 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;
+
+ static constexpr XTAL MAIN_CLOCK = XTAL(18'432'000);
+};
+
+z180cpu_base::z180cpu_base(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, u32 clock)
+ : device_t(mconfig, type, tag, owner, clock)
+ , device_rc2014_rc80_card_interface(mconfig, *this)
+ , m_maincpu(*this, "maincpu")
+{
+}
+
+void z180cpu_base::device_start()
+{
+ m_bus->set_bus_clock(MAIN_CLOCK);
+ m_maincpu->set_daisy_config(m_bus->get_daisy_chain());
+}
+
+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));
+}
+
+// This is here only to configure our terminal for interactive use
+static DEVICE_INPUT_DEFAULTS_START( terminal )
+ DEVICE_INPUT_DEFAULTS( "RS232_RXBAUD", 0xff, RS232_BAUD_115200 )
+ DEVICE_INPUT_DEFAULTS( "RS232_TXBAUD", 0xff, RS232_BAUD_115200 )
+ 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
+
+void z180cpu_base::device_add_mconfig(machine_config &config)
+{
+ Z8S180(config, m_maincpu, MAIN_CLOCK);
+ m_maincpu->set_addrmap(AS_PROGRAM, &z180cpu_base::addrmap_mem);
+ m_maincpu->set_addrmap(AS_IO, &z180cpu_base::addrmap_io);
+ m_maincpu->txa0_wr_callback().set("rs232a", FUNC(rs232_port_device::write_txd));
+ m_maincpu->txa0_wr_callback().append(FUNC(z180cpu_base::tx_w));
+ m_maincpu->txa1_wr_callback().set("rs232b", FUNC(rs232_port_device::write_txd));
+ m_maincpu->txa1_wr_callback().append(FUNC(z180cpu_base::tx2_w));
+
+ clock_device &clock(CLOCK(config, "clock", MAIN_CLOCK));
+ clock.signal_handler().append(FUNC(z180cpu_base::clk_w));
+
+ rs232_port_device &rs232a(RS232_PORT(config, "rs232a", default_rs232_devices, "terminal"));
+ rs232a.set_option_device_input_defaults("terminal", DEVICE_INPUT_DEFAULTS_NAME(terminal));
+ rs232a.set_option_device_input_defaults("null_modem", DEVICE_INPUT_DEFAULTS_NAME(terminal));
+ rs232a.rxd_handler().set(m_maincpu, FUNC(z180_device::rxa0_w));
+
+ rs232_port_device &rs232b(RS232_PORT(config, "rs232b", default_rs232_devices, nullptr));
+ rs232b.set_option_device_input_defaults("terminal", DEVICE_INPUT_DEFAULTS_NAME(terminal));
+ rs232b.set_option_device_input_defaults("null_modem", DEVICE_INPUT_DEFAULTS_NAME(terminal));
+ rs232b.rxd_handler().set(m_maincpu, FUNC(z180_device::rxa1_w));
+}
+
+//**************************************************************************
+// SC111 Z180 CPU module
+// Module author: Stephen C Cousins
+//**************************************************************************
+
+class sc111_device : public z180cpu_base
+{
+public:
+ // construction/destruction
+ sc111_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock);
+
+protected:
+ // device_t implementation
+ virtual void device_start() override ATTR_COLD;
+};
+
+sc111_device::sc111_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock)
+ : z180cpu_base(mconfig, RC2014_SC111, tag, owner, clock)
+{
+}
+
+void sc111_device::device_start()
+{
+}
+
+} // anonymous namespace
+
+
+//**************************************************************************
+// DEVICE DEFINITIONS
+//**************************************************************************
+
+DEFINE_DEVICE_TYPE_PRIVATE(RC2014_SC111, device_rc2014_rc80_card_interface, sc111_device, "rc2014_sc111", "SC111 Z180 CPU module")
diff --git a/src/devices/bus/rc2014/z180cpu.h b/src/devices/bus/rc2014/z180cpu.h
new file mode 100644
index 00000000000..e699a83a433
--- /dev/null
+++ b/src/devices/bus/rc2014/z180cpu.h
@@ -0,0 +1,18 @@
+// license:BSD-3-Clause
+// copyright-holders:Miodrag Milanovic
+/**********************************************************************
+
+ RC2014 Z180 CPU Module
+
+**********************************************************************/
+
+#ifndef MAME_BUS_RC2014_Z180CPU_H
+#define MAME_BUS_RC2014_Z180CPU_H
+
+#pragma once
+
+#include "bus/rc2014/rc2014.h"
+
+DECLARE_DEVICE_TYPE(RC2014_SC111, device_rc2014_rc80_card_interface)
+
+#endif // MAME_BUS_RC2014_Z180CPU_H
diff --git a/src/devices/bus/rc2014/z80cpu.cpp b/src/devices/bus/rc2014/z80cpu.cpp
new file mode 100644
index 00000000000..b33d3ef22a4
--- /dev/null
+++ b/src/devices/bus/rc2014/z80cpu.cpp
@@ -0,0 +1,135 @@
+// license:BSD-3-Clause
+// copyright-holders:Miodrag Milanovic
+/***************************************************************************
+
+ RC2014 Z80 CPU Module
+
+****************************************************************************/
+
+#include "emu.h"
+#include "z80cpu.h"
+
+#include "cpu/z80/z80.h"
+
+namespace {
+
+//**************************************************************************
+// Z80 CPU base class
+//**************************************************************************
+
+class z80cpu_base : public device_t
+{
+protected:
+ // construction/destruction
+ z80cpu_base(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, u32 clock);
+
+ // device_t implementation
+ virtual void device_start() override ATTR_COLD;
+ virtual void device_add_mconfig(machine_config &config) override ATTR_COLD;
+
+ void addrmap_mem(address_map &map) { map.unmap_value_high(); }
+ void addrmap_io(address_map &map) { map.unmap_value_high(); }
+
+ // object finders
+ required_device<z80_device> m_maincpu;
+};
+
+z80cpu_base::z80cpu_base(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, u32 clock)
+ : device_t(mconfig, type, tag, owner, clock)
+ , m_maincpu(*this, "maincpu")
+{
+}
+
+void z80cpu_base::device_start()
+{
+}
+
+void z80cpu_base::device_add_mconfig(machine_config &config)
+{
+ Z80(config, m_maincpu, DERIVED_CLOCK(1,1));
+ m_maincpu->set_addrmap(AS_PROGRAM, &z80cpu_base::addrmap_mem);
+ m_maincpu->set_addrmap(AS_IO, &z80cpu_base::addrmap_io);
+}
+
+//**************************************************************************
+// RC2014 Z80 CPU module
+// Module author: Spencer Owen
+//**************************************************************************
+
+class z80cpu_device : public z80cpu_base, public device_rc2014_card_interface
+{
+public:
+ // construction/destruction
+ z80cpu_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock);
+
+protected:
+ // device_t implementation
+ virtual void device_start() override ATTR_COLD;
+ virtual void device_resolve_objects() override ATTR_COLD;
+
+ 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)
+ : z80cpu_base(mconfig, RC2014_Z80CPU, tag, owner, clock)
+ , device_rc2014_card_interface(mconfig, *this)
+{
+}
+
+void z80cpu_device::device_start()
+{
+ m_maincpu->set_daisy_config(m_bus->get_daisy_chain());
+}
+
+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));
+}
+
+//**************************************************************************
+// RC2014 Z80 CPU 2.1 module
+// Module author: Spencer Owen
+//**************************************************************************
+
+class z80cpu21_device : public z80cpu_base, public device_rc2014_ext_card_interface
+{
+public:
+ // construction/destruction
+ z80cpu21_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock);
+
+protected:
+ // device_t implementation
+ virtual void device_start() override ATTR_COLD;
+ virtual void device_resolve_objects() override ATTR_COLD;
+
+ 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)
+ : z80cpu_base(mconfig, RC2014_Z80CPU_21, tag, owner, clock)
+ , device_rc2014_ext_card_interface(mconfig, *this)
+{
+}
+
+void z80cpu21_device::device_start()
+{
+ m_maincpu->set_daisy_config(m_bus->get_daisy_chain());
+}
+
+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));
+}
+
+} // anonymous namespace
+
+
+//**************************************************************************
+// DEVICE DEFINITIONS
+//**************************************************************************
+
+DEFINE_DEVICE_TYPE_PRIVATE(RC2014_Z80CPU, device_rc2014_card_interface, z80cpu_device, "rc2014_z80", "RC2014 Z80 CPU module")
+DEFINE_DEVICE_TYPE_PRIVATE(RC2014_Z80CPU_21, device_rc2014_ext_card_interface, z80cpu21_device, "rc2014_z8021", "RC2014 Z80 CPU 2.1 module")
diff --git a/src/devices/bus/rc2014/z80cpu.h b/src/devices/bus/rc2014/z80cpu.h
new file mode 100644
index 00000000000..1d07b2175ca
--- /dev/null
+++ b/src/devices/bus/rc2014/z80cpu.h
@@ -0,0 +1,19 @@
+// license:BSD-3-Clause
+// copyright-holders:Miodrag Milanovic
+/**********************************************************************
+
+ RC2014 Z80 CPU Module
+
+**********************************************************************/
+
+#ifndef MAME_BUS_RC2014_Z80CPU_H
+#define MAME_BUS_RC2014_Z80CPU_H
+
+#pragma once
+
+#include "bus/rc2014/rc2014.h"
+
+DECLARE_DEVICE_TYPE(RC2014_Z80CPU, device_rc2014_card_interface)
+DECLARE_DEVICE_TYPE(RC2014_Z80CPU_21, device_rc2014_ext_card_interface)
+
+#endif // MAME_BUS_RC2014_Z80CPU_H
diff --git a/src/devices/bus/rs232/exorterm.cpp b/src/devices/bus/rs232/exorterm.cpp
new file mode 100644
index 00000000000..9f3a1471246
--- /dev/null
+++ b/src/devices/bus/rs232/exorterm.cpp
@@ -0,0 +1,86 @@
+// license:BSD-3-Clause
+// copyright-holders:68bit
+
+#include "emu.h"
+#include "exorterm.h"
+
+exorterm155_terminal_device::exorterm155_terminal_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
+ : device_t(mconfig, SERIAL_TERMINAL_EXORTERM155, tag, owner, clock)
+ , device_rs232_port_interface(mconfig, *this)
+ , m_exorterm155(*this, "exorterm155")
+ , m_flow_control(*this, "FLOW_CONTROL")
+{
+}
+
+void exorterm155_terminal_device::device_add_mconfig(machine_config &config)
+{
+ EXORTERM155(config, m_exorterm155, 0);
+ m_exorterm155->rs232_conn_txd_handler().set(FUNC(exorterm155_terminal_device::output_rxd));
+ m_exorterm155->rs232_conn_rts_handler().set(FUNC(exorterm155_terminal_device::route_term_rts));
+ m_exorterm155->rs232_conn_dtr_handler().set(FUNC(exorterm155_terminal_device::route_term_dtr));
+}
+
+INPUT_PORTS_START(exorterm155_terminal)
+
+ PORT_START("FLOW_CONTROL")
+ PORT_CONFNAME(0x1, 1, "Flow Control") PORT_CHANGED_MEMBER(DEVICE_SELF, FUNC(exorterm155_terminal_device::flow_control), 0)
+ PORT_CONFSETTING(0x00, "None")
+ PORT_CONFSETTING(0x01, "Terminal DTR to remote CTS")
+
+INPUT_PORTS_END
+
+ioport_constructor exorterm155_terminal_device::device_input_ports() const
+{
+ return INPUT_PORTS_NAME(exorterm155_terminal);
+}
+
+void exorterm155_terminal_device::input_txd(int state)
+{
+ m_exorterm155->rs232_conn_rxd_w(state);
+}
+
+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.
+void exorterm155_terminal_device::route_term_dtr(int state)
+{
+ if (m_flow_control->read())
+ {
+ // Connect the terminal DTR output to CTS at the other end.
+ output_cts(state);
+ }
+
+ // Cache the state, in case the ioport setting changes.
+ m_dtr = state;
+}
+
+INPUT_CHANGED_MEMBER(exorterm155_terminal_device::flow_control)
+{
+ if (newval)
+ output_cts(m_dtr);
+ else
+ output_cts(0);
+}
+
+void exorterm155_terminal_device::device_start()
+{
+ save_item(NAME(m_dtr));
+}
+
+void exorterm155_terminal_device::device_reset()
+{
+ // To the terminal
+ m_exorterm155->rs232_conn_cts_w(0);
+
+ // To the computer
+ output_dcd(0);
+ output_dsr(0);
+ if (!m_flow_control->read())
+ output_cts(0);
+}
+
+DEFINE_DEVICE_TYPE(SERIAL_TERMINAL_EXORTERM155, exorterm155_terminal_device, "exorterm155_terminal", "EXORterm 155 Terminal")
diff --git a/src/devices/bus/rs232/exorterm.h b/src/devices/bus/rs232/exorterm.h
new file mode 100644
index 00000000000..a87aba800f2
--- /dev/null
+++ b/src/devices/bus/rs232/exorterm.h
@@ -0,0 +1,40 @@
+// license:BSD-3-Clause
+// copyright-holders:68bit
+
+#ifndef MAME_BUS_RS232_EXORTERM_H
+#define MAME_BUS_RS232_EXORTERM_H
+
+#pragma once
+
+#include "rs232.h"
+#include "machine/exorterm.h"
+
+
+class exorterm155_terminal_device : public device_t, public device_rs232_port_interface
+{
+public:
+ exorterm155_terminal_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
+
+ virtual void input_txd(int state) override;
+
+ DECLARE_INPUT_CHANGED_MEMBER(flow_control);
+
+protected:
+ 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;
+ virtual ioport_constructor device_input_ports() const override ATTR_COLD;
+
+private:
+ required_device<exorterm155_device> m_exorterm155;
+ required_ioport m_flow_control;
+
+ void route_term_rts(int state);
+ void route_term_dtr(int state);
+
+ int m_dtr;
+};
+
+DECLARE_DEVICE_TYPE(SERIAL_TERMINAL_EXORTERM155, exorterm155_terminal_device)
+
+#endif // MAME_BUS_RS232_EXORTERM_H
diff --git a/src/devices/bus/rs232/hlemouse.cpp b/src/devices/bus/rs232/hlemouse.cpp
index 0c2a95916c1..796a9cf980b 100644
--- a/src/devices/bus/rs232/hlemouse.cpp
+++ b/src/devices/bus/rs232/hlemouse.cpp
@@ -42,7 +42,7 @@
report can be identified by a fixed pattern in the five most
significant bits.
- Reports are five bytes long. The first byte contains the the button
+ Reports are five bytes long. The first byte contains the button
state; the second and fourth bytes contain X delta; the third and
fifth bytes contain Y delta. The two delta values for each axis
should be summed. Delta values range from -120 to 127 to prevent
@@ -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
@@ -74,30 +74,30 @@
// Device type globals
//**************************************************
-DEFINE_DEVICE_TYPE_NS(MSFT_HLE_SERIAL_MOUSE, bus::rs232, hle_msft_mouse_device, "rs232_mouse_hle_msft", "Microsoft 2-Button Serial Mouse (HLE)")
-DEFINE_DEVICE_TYPE_NS(LOGITECH_HLE_SERIAL_MOUSE, bus::rs232, hle_logitech_mouse_device, "rs232_mouse_hle_logitech", "Logitech 3-Button Serial Mouse (HLE)")
-DEFINE_DEVICE_TYPE_NS(WHEEL_HLE_SERIAL_MOUSE, bus::rs232, hle_wheel_mouse_device, "rs232_mouse_hle_wheel", "Microsoft Serial Mouse with Wheel (HLE)")
-DEFINE_DEVICE_TYPE_NS(MSYSTEMS_HLE_SERIAL_MOUSE, bus::rs232, hle_msystems_mouse_device, "rs232_mouse_hle_msystems", "Mouse Systems Non-rotatable Mouse (HLE)")
-DEFINE_DEVICE_TYPE_NS(ROTATABLE_HLE_SERIAL_MOUSE, bus::rs232, hle_rotatable_mouse_device, "rs232_mouse_hle_rotatable", "Mouse Systems Rotatable Mouse (HLE)")
-DEFINE_DEVICE_TYPE_NS(SGI_HLE_SERIAL_MOUSE, bus::rs232, hle_sgi_mouse_device, "rs232_mouse_hle_sgi", "SGI IRIS Indigo Mouse (HLE)")
+DEFINE_DEVICE_TYPE(MSFT_HLE_SERIAL_MOUSE, bus::rs232::hle_msft_mouse_device, "rs232_mouse_hle_msft", "Microsoft 2-Button Serial Mouse (HLE)")
+DEFINE_DEVICE_TYPE(LOGITECH_HLE_SERIAL_MOUSE, bus::rs232::hle_logitech_mouse_device, "rs232_mouse_hle_logitech", "Logitech 3-Button Serial Mouse (HLE)")
+DEFINE_DEVICE_TYPE(WHEEL_HLE_SERIAL_MOUSE, bus::rs232::hle_wheel_mouse_device, "rs232_mouse_hle_wheel", "Microsoft Serial Mouse with Wheel (HLE)")
+DEFINE_DEVICE_TYPE(MSYSTEMS_HLE_SERIAL_MOUSE, bus::rs232::hle_msystems_mouse_device, "rs232_mouse_hle_msystems", "Mouse Systems Non-rotatable Mouse (HLE)")
+DEFINE_DEVICE_TYPE(ROTATABLE_HLE_SERIAL_MOUSE, bus::rs232::hle_rotatable_mouse_device, "rs232_mouse_hle_rotatable", "Mouse Systems Rotatable Mouse (HLE)")
+DEFINE_DEVICE_TYPE(SGI_HLE_SERIAL_MOUSE, bus::rs232::hle_sgi_mouse_device, "rs232_mouse_hle_sgi", "SGI IRIS Indigo Mouse (HLE)")
-namespace bus { namespace rs232 {
+namespace bus::rs232 {
namespace {
INPUT_PORTS_START(msft)
PORT_START("BTN")
PORT_BIT( 0xfffc, IP_ACTIVE_HIGH, IPT_UNUSED )
- PORT_BIT( 0x0002, IP_ACTIVE_HIGH, IPT_BUTTON1 ) PORT_CODE(MOUSECODE_BUTTON1) PORT_CHANGED_MEMBER(DEVICE_SELF, hle_msmouse_device_base, input_changed, 0)
- PORT_BIT( 0x0001, IP_ACTIVE_HIGH, IPT_BUTTON2 ) PORT_CODE(MOUSECODE_BUTTON2) PORT_CHANGED_MEMBER(DEVICE_SELF, hle_msmouse_device_base, input_changed, 0)
+ PORT_BIT( 0x0002, IP_ACTIVE_HIGH, IPT_BUTTON1 ) PORT_CODE(MOUSECODE_BUTTON1) PORT_CHANGED_MEMBER(DEVICE_SELF, FUNC(hle_msmouse_device_base::input_changed), 0)
+ PORT_BIT( 0x0001, IP_ACTIVE_HIGH, IPT_BUTTON2 ) PORT_CODE(MOUSECODE_BUTTON2) PORT_CHANGED_MEMBER(DEVICE_SELF, FUNC(hle_msmouse_device_base::input_changed), 0)
PORT_START("X")
PORT_BIT( 0xf000, IP_ACTIVE_HIGH, IPT_UNUSED )
- PORT_BIT( 0x0fff, 0x00, IPT_MOUSE_X ) PORT_SENSITIVITY(100) PORT_KEYDELTA(0) PORT_CHANGED_MEMBER(DEVICE_SELF, hle_msmouse_device_base, input_changed, 0)
+ PORT_BIT( 0x0fff, 0x00, IPT_MOUSE_X ) PORT_SENSITIVITY(100) PORT_KEYDELTA(0) PORT_CHANGED_MEMBER(DEVICE_SELF, FUNC(hle_msmouse_device_base::input_changed), 0)
PORT_START("Y")
PORT_BIT( 0xf000, IP_ACTIVE_HIGH, IPT_UNUSED )
- PORT_BIT( 0x0fff, 0x00, IPT_MOUSE_Y ) PORT_SENSITIVITY(100) PORT_KEYDELTA(0) PORT_CHANGED_MEMBER(DEVICE_SELF, hle_msmouse_device_base, input_changed, 0)
+ PORT_BIT( 0x0fff, 0x00, IPT_MOUSE_Y ) PORT_SENSITIVITY(100) PORT_KEYDELTA(0) PORT_CHANGED_MEMBER(DEVICE_SELF, FUNC(hle_msmouse_device_base::input_changed), 0)
INPUT_PORTS_END
@@ -105,8 +105,8 @@ INPUT_PORTS_START(logitech)
PORT_INCLUDE(msft)
PORT_MODIFY("BTN")
- PORT_BIT( 0x0004, IP_ACTIVE_HIGH, IPT_BUTTON2 ) PORT_CODE(MOUSECODE_BUTTON3) PORT_CHANGED_MEMBER(DEVICE_SELF, hle_msmouse_device_base, input_changed, 0)
- PORT_BIT( 0x0001, IP_ACTIVE_HIGH, IPT_BUTTON3 ) PORT_CODE(MOUSECODE_BUTTON2) PORT_CHANGED_MEMBER(DEVICE_SELF, hle_msmouse_device_base, input_changed, 0)
+ PORT_BIT( 0x0004, IP_ACTIVE_HIGH, IPT_BUTTON2 ) PORT_CODE(MOUSECODE_BUTTON3) PORT_CHANGED_MEMBER(DEVICE_SELF, FUNC(hle_msmouse_device_base::input_changed), 0)
+ PORT_BIT( 0x0001, IP_ACTIVE_HIGH, IPT_BUTTON3 ) PORT_CODE(MOUSECODE_BUTTON2) PORT_CHANGED_MEMBER(DEVICE_SELF, FUNC(hle_msmouse_device_base::input_changed), 0)
INPUT_PORTS_END
@@ -115,24 +115,24 @@ INPUT_PORTS_START(wheel)
PORT_START("WHEEL")
PORT_BIT( 0xf000, IP_ACTIVE_HIGH, IPT_UNUSED )
- PORT_BIT( 0x0fff, 0x00, IPT_DIAL_V ) PORT_SENSITIVITY(10) PORT_CHANGED_MEMBER(DEVICE_SELF, hle_msmouse_device_base, input_changed, 0)
+ PORT_BIT( 0x0fff, 0x00, IPT_DIAL_V ) PORT_SENSITIVITY(10) PORT_CHANGED_MEMBER(DEVICE_SELF, FUNC(hle_msmouse_device_base::input_changed), 0)
INPUT_PORTS_END
INPUT_PORTS_START(msystems)
PORT_START("BTN")
PORT_BIT( 0xfff8, IP_ACTIVE_HIGH, IPT_UNUSED )
- PORT_BIT( 0x0004, IP_ACTIVE_LOW, IPT_BUTTON1 ) PORT_CODE(MOUSECODE_BUTTON1) PORT_CHANGED_MEMBER(DEVICE_SELF, hle_msystems_device_base, input_changed, 0)
- PORT_BIT( 0x0002, IP_ACTIVE_LOW, IPT_BUTTON2 ) PORT_CODE(MOUSECODE_BUTTON3) PORT_CHANGED_MEMBER(DEVICE_SELF, hle_msystems_device_base, input_changed, 0)
- PORT_BIT( 0x0001, IP_ACTIVE_LOW, IPT_BUTTON3 ) PORT_CODE(MOUSECODE_BUTTON2) PORT_CHANGED_MEMBER(DEVICE_SELF, hle_msystems_device_base, input_changed, 0)
+ PORT_BIT( 0x0004, IP_ACTIVE_LOW, IPT_BUTTON1 ) PORT_CODE(MOUSECODE_BUTTON1) PORT_CHANGED_MEMBER(DEVICE_SELF, FUNC(hle_msystems_device_base::input_changed), 0)
+ PORT_BIT( 0x0002, IP_ACTIVE_LOW, IPT_BUTTON2 ) PORT_CODE(MOUSECODE_BUTTON3) PORT_CHANGED_MEMBER(DEVICE_SELF, FUNC(hle_msystems_device_base::input_changed), 0)
+ PORT_BIT( 0x0001, IP_ACTIVE_LOW, IPT_BUTTON3 ) PORT_CODE(MOUSECODE_BUTTON2) PORT_CHANGED_MEMBER(DEVICE_SELF, FUNC(hle_msystems_device_base::input_changed), 0)
PORT_START("X")
PORT_BIT( 0xf000, IP_ACTIVE_HIGH, IPT_UNUSED )
- PORT_BIT( 0x0fff, 0x00, IPT_MOUSE_X ) PORT_SENSITIVITY(100) PORT_KEYDELTA(0) PORT_CHANGED_MEMBER(DEVICE_SELF, hle_msystems_device_base, input_changed, 0)
+ PORT_BIT( 0x0fff, 0x00, IPT_MOUSE_X ) PORT_SENSITIVITY(100) PORT_KEYDELTA(0) PORT_CHANGED_MEMBER(DEVICE_SELF, FUNC(hle_msystems_device_base::input_changed), 0)
PORT_START("Y")
PORT_BIT( 0xf000, IP_ACTIVE_HIGH, IPT_UNUSED )
- PORT_BIT( 0x0fff, 0x00, IPT_MOUSE_Y ) PORT_SENSITIVITY(100) PORT_KEYDELTA(0) PORT_CHANGED_MEMBER(DEVICE_SELF, hle_msystems_device_base, input_changed, 0)
+ PORT_BIT( 0x0fff, 0x00, IPT_MOUSE_Y ) PORT_SENSITIVITY(100) PORT_KEYDELTA(0) PORT_CHANGED_MEMBER(DEVICE_SELF, FUNC(hle_msystems_device_base::input_changed), 0)
INPUT_PORTS_END
@@ -141,7 +141,7 @@ INPUT_PORTS_START(rotatable)
PORT_START("ROT")
PORT_BIT( 0xf000, IP_ACTIVE_HIGH, IPT_UNUSED )
- PORT_BIT( 0x0fff, 0x00, IPT_DIAL ) PORT_SENSITIVITY(10) PORT_CHANGED_MEMBER(DEVICE_SELF, hle_msystems_device_base, input_changed, 0)
+ PORT_BIT( 0x0fff, 0x00, IPT_DIAL ) PORT_SENSITIVITY(10) PORT_CHANGED_MEMBER(DEVICE_SELF, FUNC(hle_msystems_device_base::input_changed), 0)
INPUT_PORTS_END
@@ -239,15 +239,15 @@ 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_dtr = state ? 1U : 0U;
+ m_rts = state ? 1U : 0U;
check_enable();
}
@@ -720,4 +720,4 @@ void hle_sgi_mouse_device::device_start()
transmit_register_reset();
}
-} } // namespace bus::rs232
+} // namespace bus::rs232
diff --git a/src/devices/bus/rs232/hlemouse.h b/src/devices/bus/rs232/hlemouse.h
index f6fb537e51c..2911e8de9ce 100644
--- a/src/devices/bus/rs232/hlemouse.h
+++ b/src/devices/bus/rs232/hlemouse.h
@@ -16,7 +16,7 @@
#include <type_traits>
-namespace bus { namespace rs232 {
+namespace bus::rs232 {
//**************************************************
// Microsoft mouse base
@@ -30,11 +30,11 @@ public:
protected:
hle_msmouse_device_base(machine_config const &mconfig, device_type type, char const *tag, device_t *owner, uint32_t clock);
- virtual void device_resolve_objects() override;
- virtual void device_start() override;
+ virtual void device_resolve_objects() override ATTR_COLD;
+ virtual void device_start() override ATTR_COLD;
- 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;
@@ -68,7 +68,7 @@ public:
hle_msft_mouse_device(machine_config const &mconfig, char const *tag, device_t *owner, uint32_t clock);
protected:
- virtual ioport_constructor device_input_ports() const override;
+ virtual ioport_constructor device_input_ports() const override ATTR_COLD;
private:
virtual void reset_and_identify() override;
@@ -86,7 +86,7 @@ public:
hle_logitech_mouse_device(machine_config const &mconfig, char const *tag, device_t *owner, uint32_t clock);
protected:
- virtual ioport_constructor device_input_ports() const override;
+ virtual ioport_constructor device_input_ports() const override ATTR_COLD;
private:
virtual void reset_and_identify() override;
@@ -104,8 +104,8 @@ public:
hle_wheel_mouse_device(machine_config const &mconfig, char const *tag, device_t *owner, uint32_t clock);
protected:
- virtual ioport_constructor device_input_ports() const override;
- virtual void device_start() override;
+ virtual ioport_constructor device_input_ports() const override ATTR_COLD;
+ virtual void device_start() override ATTR_COLD;
virtual bool read_inputs() override;
@@ -131,7 +131,7 @@ public:
protected:
hle_msystems_device_base(machine_config const &mconfig, device_type type, char const *tag, device_t *owner, uint32_t clock);
- virtual void device_start() override;
+ virtual void device_start() override ATTR_COLD;
virtual void tra_callback() override;
virtual void tra_complete() override;
@@ -162,8 +162,8 @@ public:
protected:
hle_msystems_mouse_device(machine_config const &mconfig, device_type type, char const *tag, device_t *owner, uint32_t clock);
- virtual ioport_constructor device_input_ports() const override;
- virtual void device_start() override;
+ virtual ioport_constructor device_input_ports() const override ATTR_COLD;
+ virtual void device_start() override ATTR_COLD;
private:
virtual bool read_inputs() override;
@@ -190,8 +190,8 @@ public:
hle_rotatable_mouse_device(machine_config const &mconfig, char const *tag, device_t *owner, uint32_t clock);
protected:
- virtual ioport_constructor device_input_ports() const override;
- virtual void device_start() override;
+ virtual ioport_constructor device_input_ports() const override ATTR_COLD;
+ virtual void device_start() override ATTR_COLD;
private:
virtual bool read_inputs() override;
@@ -217,10 +217,10 @@ public:
hle_sgi_mouse_device(machine_config const &mconfig, char const *tag, device_t *owner, uint32_t clock);
protected:
- virtual void device_start() override;
+ virtual void device_start() override ATTR_COLD;
};
-} } // namespace bus::rs232
+} // namespace bus::rs232
//**************************************************
diff --git a/src/devices/bus/rs232/ie15.cpp b/src/devices/bus/rs232/ie15.cpp
index 72520f87dea..286b75b098c 100644
--- a/src/devices/bus/rs232/ie15.cpp
+++ b/src/devices/bus/rs232/ie15.cpp
@@ -4,87 +4,61 @@
#include "emu.h"
#include "ie15.h"
-ie15_terminal_device::ie15_terminal_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
- : ie15_device(mconfig, SERIAL_TERMINAL_IE15, tag, owner, clock)
- , device_rs232_port_interface(mconfig, *this)
- , m_rs232_txbaud(*this, "RS232_TXBAUD")
- , m_rs232_rxbaud(*this, "RS232_RXBAUD")
- , m_rs232_startbits(*this, "RS232_STARTBITS")
- , m_rs232_databits(*this, "RS232_DATABITS")
- , m_rs232_parity(*this, "RS232_PARITY")
- , m_rs232_stopbits(*this, "RS232_STOPBITS")
-{
-}
-
-static INPUT_PORTS_START(ie15_terminal)
- PORT_INCLUDE(ie15)
-
- PORT_RS232_BAUD("RS232_TXBAUD", RS232_BAUD_9600, "TX Baud", ie15_terminal_device, update_serial)
- PORT_RS232_BAUD("RS232_RXBAUD", RS232_BAUD_9600, "RX Baud", ie15_terminal_device, update_serial)
- PORT_RS232_STARTBITS("RS232_STARTBITS", RS232_STARTBITS_1, "Start Bits", ie15_terminal_device, update_serial)
- PORT_RS232_DATABITS("RS232_DATABITS", RS232_DATABITS_8, "Data Bits", ie15_terminal_device, update_serial)
- PORT_RS232_PARITY("RS232_PARITY", RS232_PARITY_NONE, "Parity", ie15_terminal_device, update_serial)
- PORT_RS232_STOPBITS("RS232_STOPBITS", RS232_STOPBITS_1, "Stop Bits", ie15_terminal_device, update_serial)
-INPUT_PORTS_END
+#include "machine/ie15.h"
-ioport_constructor ie15_terminal_device::device_input_ports() const
-{
- return INPUT_PORTS_NAME(ie15_terminal);
-}
+namespace {
-WRITE_LINE_MEMBER(ie15_terminal_device::update_serial)
+class ie15_terminal_device : public device_t, public device_rs232_port_interface
{
- int startbits = convert_startbits(m_rs232_startbits->read());
- int databits = convert_databits(m_rs232_databits->read());
- parity_t parity = convert_parity(m_rs232_parity->read());
- stop_bits_t stopbits = convert_stopbits(m_rs232_stopbits->read());
-
- set_data_frame(startbits, databits, parity, stopbits);
+public:
+ ie15_terminal_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
+ : device_t(mconfig, SERIAL_TERMINAL_IE15, tag, owner, clock)
+ , device_rs232_port_interface(mconfig, *this)
+ , m_ie15(*this, "ie15")
+ {
+ }
- int txbaud = convert_baud(m_rs232_txbaud->read());
- set_tra_rate(txbaud);
+ virtual void input_txd(int state) override { m_ie15->rs232_conn_rxd_w(state); }
- int rxbaud = convert_baud(m_rs232_rxbaud->read());
- set_rcv_rate(rxbaud);
+protected:
+ virtual void device_start() override { }
+ virtual void device_reset() override ATTR_COLD;
+ virtual void device_add_mconfig(machine_config &config) override ATTR_COLD;
+ virtual ioport_constructor device_input_ports() const override ATTR_COLD;
- output_rxd(1);
+private:
+ required_device<ie15_device> m_ie15;
+};
- // TODO: make this configurable
- output_dcd(0);
- output_dsr(0);
- output_cts(0);
-}
-void ie15_terminal_device::tra_callback()
+void ie15_terminal_device::device_add_mconfig(machine_config &config)
{
- output_rxd(transmit_register_get_data_bit());
-}
+ IE15(config, m_ie15, 0);
-void ie15_terminal_device::tra_complete()
-{
- ie15_device::tra_complete();
+ m_ie15->rs232_conn_txd_handler().set(FUNC(ie15_terminal_device::output_rxd));
+ //m_ie15->rs232_conn_rts_handler().set(FUNC(ie15_terminal_device::route_term_rts));
+ //m_ie15->rs232_conn_dtr_handler().set(FUNC(ie15_terminal_device::route_term_dtr));
}
-void ie15_terminal_device::rcv_complete()
-{
- receive_register_extract();
- term_write(get_received_char());
-}
+INPUT_PORTS_START(ie15_terminal)
+INPUT_PORTS_END
-void ie15_terminal_device::device_start()
+ioport_constructor ie15_terminal_device::device_input_ports() const
{
- ie15_device::device_start();
+ return INPUT_PORTS_NAME(ie15_terminal);
}
void ie15_terminal_device::device_reset()
{
- update_serial(0);
- ie15_device::device_reset();
-}
+ output_rxd(1);
-void ie15_terminal_device::device_timer(emu_timer &timer, device_timer_id id, int param, void *ptr)
-{
- ie15_device::device_timer(timer, id, param, ptr);
+ // TODO: make this configurable
+ output_dcd(0);
+ output_dsr(0);
+ output_cts(0);
}
-DEFINE_DEVICE_TYPE(SERIAL_TERMINAL_IE15, ie15_terminal_device, "ie15_terminal", "IE15 Terminal")
+} // anonymous namespace
+
+
+DEFINE_DEVICE_TYPE_PRIVATE(SERIAL_TERMINAL_IE15, device_rs232_port_interface, ie15_terminal_device, "ie15_terminal", "IE15 Terminal")
diff --git a/src/devices/bus/rs232/ie15.h b/src/devices/bus/rs232/ie15.h
index c5c7ba3f6de..9f65e0a22b2 100644
--- a/src/devices/bus/rs232/ie15.h
+++ b/src/devices/bus/rs232/ie15.h
@@ -7,38 +7,8 @@
#pragma once
#include "rs232.h"
-#include "machine/ie15.h"
-class ie15_terminal_device : public ie15_device,
- public device_rs232_port_interface
-{
-public:
- ie15_terminal_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
-
- virtual DECLARE_WRITE_LINE_MEMBER( input_txd ) override { ie15_device::serial_rx_callback(state); }
-
- DECLARE_WRITE_LINE_MEMBER(update_serial);
-
-protected:
- virtual ioport_constructor device_input_ports() const override;
- virtual void device_start() override;
- virtual void device_reset() override;
- virtual void device_timer(emu_timer &timer, device_timer_id id, int param, void *ptr) override;
-
- virtual void tra_callback() override;
- virtual void tra_complete() override;
- virtual void rcv_complete() override;
-
-private:
- required_ioport m_rs232_txbaud;
- required_ioport m_rs232_rxbaud;
- required_ioport m_rs232_startbits;
- required_ioport m_rs232_databits;
- required_ioport m_rs232_parity;
- required_ioport m_rs232_stopbits;
-};
-
-DECLARE_DEVICE_TYPE(SERIAL_TERMINAL_IE15, ie15_terminal_device)
+DECLARE_DEVICE_TYPE(SERIAL_TERMINAL_IE15, device_rs232_port_interface)
#endif // MAME_BUS_RS232_IE15_H
diff --git a/src/devices/bus/rs232/keyboard.cpp b/src/devices/bus/rs232/keyboard.cpp
index 31d77555d06..f29057588cc 100644
--- a/src/devices/bus/rs232/keyboard.cpp
+++ b/src/devices/bus/rs232/keyboard.cpp
@@ -4,15 +4,16 @@
#include "keyboard.h"
namespace {
+
INPUT_PORTS_START(serial_keyboard)
PORT_INCLUDE(generic_keyboard)
PORT_RS232_BAUD("RS232_TXBAUD", RS232_BAUD_9600, "TX Baud", serial_keyboard_device, update_serial)
- PORT_RS232_STARTBITS("RS232_STARTBITS", RS232_STARTBITS_1, "Start Bits", serial_keyboard_device, update_serial)
PORT_RS232_DATABITS("RS232_DATABITS", RS232_DATABITS_8, "Data Bits", serial_keyboard_device, update_serial)
PORT_RS232_PARITY("RS232_PARITY", RS232_PARITY_NONE, "Parity", serial_keyboard_device, update_serial)
PORT_RS232_STOPBITS("RS232_STOPBITS", RS232_STOPBITS_1, "Stop Bits", serial_keyboard_device, update_serial)
INPUT_PORTS_END
+
} // anonymous namespace
serial_keyboard_device::serial_keyboard_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
@@ -25,7 +26,6 @@ serial_keyboard_device::serial_keyboard_device(const machine_config &mconfig, de
, device_buffered_serial_interface(mconfig, *this)
, device_rs232_port_interface(mconfig, *this)
, m_rs232_txbaud(*this, "RS232_TXBAUD")
- , m_rs232_startbits(*this, "RS232_STARTBITS")
, m_rs232_databits(*this, "RS232_DATABITS")
, m_rs232_parity(*this, "RS232_PARITY")
, m_rs232_stopbits(*this, "RS232_STOPBITS")
@@ -37,12 +37,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();
}
@@ -53,7 +53,7 @@ void serial_keyboard_device::device_reset()
clear_fifo();
- int const startbits = convert_startbits(m_rs232_startbits->read());
+ int const startbits = 1;
int const databits = convert_databits(m_rs232_databits->read());
parity_t const parity = convert_parity(m_rs232_parity->read());
stop_bits_t const stopbits = convert_stopbits(m_rs232_stopbits->read());
diff --git a/src/devices/bus/rs232/keyboard.h b/src/devices/bus/rs232/keyboard.h
index a10f9a78385..5580eb840e4 100644
--- a/src/devices/bus/rs232/keyboard.h
+++ b/src/devices/bus/rs232/keyboard.h
@@ -5,8 +5,6 @@
#pragma once
-#pragma once
-
#include "rs232.h"
#include "machine/keyboard.h"
@@ -18,16 +16,16 @@ class serial_keyboard_device
public:
serial_keyboard_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
- virtual ioport_constructor device_input_ports() const override;
+ virtual ioport_constructor device_input_ports() const override ATTR_COLD;
- 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);
- virtual void device_reset() override;
+ virtual void device_reset() override ATTR_COLD;
virtual void tra_callback() override;
virtual void send_key(uint8_t code) override;
@@ -35,7 +33,6 @@ private:
virtual void received_byte(uint8_t byte) override;
required_ioport m_rs232_txbaud;
- required_ioport m_rs232_startbits;
required_ioport m_rs232_databits;
required_ioport m_rs232_parity;
required_ioport m_rs232_stopbits;
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..112ce148148 100644
--- a/src/devices/bus/rs232/loopback.h
+++ b/src/devices/bus/rs232/loopback.h
@@ -13,12 +13,12 @@ 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;
+ virtual void device_start() override ATTR_COLD;
};
class dec_rs232_loopback_device : public device_t, public device_rs232_port_interface
@@ -26,13 +26,13 @@ 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;
+ virtual void device_start() override ATTR_COLD;
};
DECLARE_DEVICE_TYPE(RS232_LOOPBACK, rs232_loopback_device)
diff --git a/src/devices/bus/rs232/mboardd.cpp b/src/devices/bus/rs232/mboardd.cpp
new file mode 100644
index 00000000000..1ec2bdc8c9b
--- /dev/null
+++ b/src/devices/bus/rs232/mboardd.cpp
@@ -0,0 +1,144 @@
+// license:BSD-3-Clause
+// copyright-holders:R. Belmont
+
+/*
+ mboardd.cpp - Mockingboard D emulation
+ by R. Belmont
+
+ The Apple IIc didn't have slots, so Sweet Micro Systems came up with this, a Mockingboard
+ in a little box that attached to the IIc's modem port. There's nothing special about the
+ IIc though - with a proper cable, anything that speaks 9600 8N1 RS-232 could drive this
+ device.
+
+ A decent disassembly of the 6803 firmware is available from the Apple II Documentation Project:
+ https://mirrors.apple2.org.za/Apple%20II%20Documentation%20Project/Interface%20Cards/Audio/Sweet%20Microsystems%20Mockingboard/Source%20Code/
+
+*/
+
+#include "emu.h"
+#include "mboardd.h"
+
+#include "cpu/m6800/m6801.h"
+#include "sound/ay8910.h"
+
+#include "speaker.h"
+
+
+namespace {
+
+ROM_START(mboardd)
+ ROM_REGION(0x800, "mbcpu", 0)
+ ROM_LOAD("mockingboard d rom.bin", 0x000000, 0x000800, CRC(277b1813) SHA1(e8d20f4b59fe867ff76434d35a14d2cbdc8533e3))
+ROM_END
+
+class mockingboard_d_device : public device_t, public device_rs232_port_interface
+{
+public:
+ mockingboard_d_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
+
+ virtual void input_txd(int state) override;
+
+ required_device<m6803_cpu_device> m_cpu;
+ required_device<ay8913_device> m_ay1;
+ required_device<ay8913_device> m_ay2;
+
+protected:
+ 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;
+ virtual const tiny_rom_entry *device_rom_region() const override ATTR_COLD;
+
+private:
+ u8 p2_r() { return m_rx_state<<3; };
+ void p1_w(u8 data);
+
+ void ser_tx_w(int state) { output_rxd(state); }
+
+ void c000_w(u8 data) { m_c000_latch = data; };
+
+ void m6803_mem(address_map &map) ATTR_COLD;
+ int m_rx_state;
+ u8 m_c000_latch;
+};
+
+mockingboard_d_device::mockingboard_d_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
+ : device_t(mconfig, SERIAL_MOCKINGBOARD_D, tag, owner, clock)
+ , device_rs232_port_interface(mconfig, *this)
+ , m_cpu(*this, "mbdcpu")
+ , m_ay1(*this, "ay1")
+ , m_ay2(*this, "ay2")
+{
+}
+
+void mockingboard_d_device::device_add_mconfig(machine_config &config)
+{
+ M6803(config, m_cpu, 4.9152_MHz_XTAL); // value reverse-engineered from 9600 baud SCI rate needed
+ m_cpu->set_addrmap(AS_PROGRAM, &mockingboard_d_device::m6803_mem);
+ m_cpu->in_p2_cb().set(FUNC(mockingboard_d_device::p2_r));
+ m_cpu->out_p1_cb().set(FUNC(mockingboard_d_device::p1_w));
+ m_cpu->out_ser_tx_cb().set(FUNC(mockingboard_d_device::ser_tx_w));
+
+ SPEAKER(config, "speaker", 2).front();
+ AY8913(config, m_ay1, 1022727);
+ m_ay1->add_route(ALL_OUTPUTS, "speaker", 0.5, 0);
+ AY8913(config, m_ay2, 1022727);
+ m_ay2->add_route(ALL_OUTPUTS, "speaker", 0.5, 0);
+}
+
+const tiny_rom_entry *mockingboard_d_device::device_rom_region() const
+{
+ return ROM_NAME(mboardd);
+}
+
+void mockingboard_d_device::device_start()
+{
+}
+
+void mockingboard_d_device::device_reset()
+{
+ output_dcd(0);
+ output_dsr(0);
+ output_cts(0);
+}
+
+void mockingboard_d_device::m6803_mem(address_map &map)
+{
+ map(0x8000, 0x83ff).ram();
+ // SSI-263 at a000/a001
+ map(0xc000, 0xc000).w(FUNC(mockingboard_d_device::c000_w));
+ map(0xf800, 0xffff).rom().region("mbcpu", 0);
+}
+
+void mockingboard_d_device::input_txd(int state)
+{
+ m_rx_state = (state & 1);
+}
+
+void mockingboard_d_device::p1_w(u8 data)
+{
+ if (BIT(data, 3))
+ {
+ m_ay2->address_w(m_c000_latch);
+ //printf("%02x to AY2 address\n", m_c000_latch);
+ }
+ else if (BIT(data, 2))
+ {
+ m_ay2->data_w(m_c000_latch);
+ //printf("%02x to AY2 data\n", m_c000_latch);
+ }
+ else if (BIT(data, 1))
+ {
+ m_ay1->address_w(m_c000_latch);
+ //printf("%02x to AY1 address\n", m_c000_latch);
+ }
+ else if (BIT(data, 0))
+ {
+ m_ay1->data_w(m_c000_latch);
+ //printf("%02x to AY1 data\n", m_c000_latch);
+ }
+}
+
+} // anonymous namespace
+
+
+DEFINE_DEVICE_TYPE_PRIVATE(SERIAL_MOCKINGBOARD_D, device_rs232_port_interface, mockingboard_d_device, "mockingboardd", "Sweet Micro Systems Mockingboard D")
diff --git a/src/devices/bus/rs232/mboardd.h b/src/devices/bus/rs232/mboardd.h
new file mode 100644
index 00000000000..0203ad3b372
--- /dev/null
+++ b/src/devices/bus/rs232/mboardd.h
@@ -0,0 +1,12 @@
+// license:BSD-3-Clause
+// copyright-holders:R. Belmont
+#ifndef MAME_BUS_RS232_MBOARDD_H
+#define MAME_BUS_RS232_MBOARDD_H
+
+#pragma once
+
+#include "rs232.h"
+
+DECLARE_DEVICE_TYPE(SERIAL_MOCKINGBOARD_D, device_rs232_port_interface)
+
+#endif // MAME_BUS_RS232_MBOARDD_H
diff --git a/src/devices/bus/rs232/nss_tvinterface.cpp b/src/devices/bus/rs232/nss_tvinterface.cpp
new file mode 100644
index 00000000000..1a8433e4a1e
--- /dev/null
+++ b/src/devices/bus/rs232/nss_tvinterface.cpp
@@ -0,0 +1,251 @@
+// 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 ATTR_COLD;
+ virtual void device_add_mconfig(machine_config &config) override ATTR_COLD;
+
+ virtual const tiny_rom_entry *device_rom_region() const override ATTR_COLD;
+ virtual ioport_constructor device_input_ports() const override ATTR_COLD;
+
+ 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;
+ required_ioport m_in;
+
+ 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) ATTR_COLD;
+
+ 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"),
+ m_in(*this, "IN")
+{ }
+
+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(m_in);
+ 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")
+ 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 5cff5d8cf89..083fcb0d516 100644
--- a/src/devices/bus/rs232/null_modem.cpp
+++ b/src/devices/bus/rs232/null_modem.cpp
@@ -3,14 +3,13 @@
#include "emu.h"
#include "null_modem.h"
-null_modem_device::null_modem_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
- : device_t(mconfig, NULL_MODEM, tag, owner, clock),
+null_modem_device::null_modem_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) :
+ device_t(mconfig, NULL_MODEM, tag, owner, clock),
device_serial_interface(mconfig, *this),
device_rs232_port_interface(mconfig, *this),
m_stream(*this, "stream"),
m_rs232_txbaud(*this, "RS232_TXBAUD"),
m_rs232_rxbaud(*this, "RS232_RXBAUD"),
- m_rs232_startbits(*this, "RS232_STARTBITS"),
m_rs232_databits(*this, "RS232_DATABITS"),
m_rs232_parity(*this, "RS232_PARITY"),
m_rs232_stopbits(*this, "RS232_STOPBITS"),
@@ -18,7 +17,9 @@ null_modem_device::null_modem_device(const machine_config &mconfig, const char *
m_input_count(0),
m_input_index(0),
m_timer_poll(nullptr),
- m_rts(0)
+ m_rts(0),
+ m_dtr(0),
+ m_xoff(0)
{
}
@@ -30,15 +31,16 @@ void null_modem_device::device_add_mconfig(machine_config &config)
static INPUT_PORTS_START(null_modem)
PORT_RS232_BAUD("RS232_TXBAUD", RS232_BAUD_9600, "TX Baud", null_modem_device, update_serial)
PORT_RS232_BAUD("RS232_RXBAUD", RS232_BAUD_9600, "RX Baud", null_modem_device, update_serial)
- PORT_RS232_STARTBITS("RS232_STARTBITS", RS232_STARTBITS_1, "Start Bits", null_modem_device, update_serial)
PORT_RS232_DATABITS("RS232_DATABITS", RS232_DATABITS_8, "Data Bits", null_modem_device, update_serial)
PORT_RS232_PARITY("RS232_PARITY", RS232_PARITY_NONE, "Parity", null_modem_device, update_serial)
PORT_RS232_STOPBITS("RS232_STOPBITS", RS232_STOPBITS_1, "Stop Bits", null_modem_device, update_serial)
PORT_START("FLOW_CONTROL")
- PORT_CONFNAME(0x01, 0x00, "Flow Control")
- PORT_CONFSETTING(0x00, "Off")
- PORT_CONFSETTING(0x01, "On")
+ 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 null_modem_device::device_input_ports() const
@@ -48,12 +50,12 @@ ioport_constructor null_modem_device::device_input_ports() const
void null_modem_device::device_start()
{
- m_timer_poll = timer_alloc(TIMER_POLL);
+ 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 = convert_startbits(m_rs232_startbits->read());
+ int startbits = 1;
int databits = convert_databits(m_rs232_databits->read());
parity_t parity = convert_parity(m_rs232_parity->read());
stop_bits_t stopbits = convert_stopbits(m_rs232_stopbits->read());
@@ -73,29 +75,16 @@ WRITE_LINE_MEMBER(null_modem_device::update_serial)
output_dsr(0);
output_cts(0);
- m_rts = 0;
+ m_xoff = 0;
}
void null_modem_device::device_reset()
{
update_serial(0);
- queue();
+ update_queue(0);
}
-void null_modem_device::device_timer(emu_timer &timer, device_timer_id id, int param, void *ptr)
-{
- switch (id)
- {
- case TIMER_POLL:
- queue();
- break;
-
- default:
- break;
- }
-}
-
-void null_modem_device::queue()
+TIMER_CALLBACK_MEMBER(null_modem_device::update_queue)
{
if (is_transmit_register_empty())
{
@@ -105,17 +94,20 @@ void null_modem_device::queue()
m_input_count = m_stream->input(m_input_buffer, sizeof(m_input_buffer));
}
- if (m_input_count != 0 && (m_rts == 0 || !m_flow->read()))
+ if (m_input_count != 0)
{
- transmit_register_setup(m_input_buffer[m_input_index++]);
-
- m_timer_poll->adjust(attotime::never);
- }
- else
- {
- int txbaud = convert_baud(m_rs232_txbaud->read());
- m_timer_poll->adjust(attotime::from_hz(txbaud));
+ 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))
+ {
+ 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));
}
}
@@ -126,13 +118,35 @@ void null_modem_device::tra_callback()
void null_modem_device::tra_complete()
{
- queue();
+ update_queue(0);
}
void null_modem_device::rcv_complete()
{
receive_register_extract();
- m_stream->output(get_received_char());
+
+ uint8_t const data = get_received_char();
+ if (m_flow->read() != 4)
+ {
+ m_stream->output(data);
+ }
+ else
+ {
+ switch (data)
+ {
+ case 0x13: // XOFF
+ m_xoff = 1;
+ return;
+
+ case 0x11: // XON
+ m_xoff = 0;
+ return;
+
+ default:
+ break;
+ }
+ m_stream->output(data);
+ }
}
-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 7ba5cddbb78..94e2b7a85d0 100644
--- a/src/devices/bus/rs232/null_modem.h
+++ b/src/devices/bus/rs232/null_modem.h
@@ -3,6 +3,8 @@
#ifndef MAME_BUS_RS232_NULL_MODEM_H
#define MAME_BUS_RS232_NULL_MODEM_H
+#pragma once
+
#include "rs232.h"
#include "imagedev/bitbngr.h"
#include "diserial.h"
@@ -14,32 +16,29 @@ 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 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;
- virtual void device_start() override;
- virtual void device_reset() override;
- virtual void device_timer(emu_timer &timer, device_timer_id id, int param, void *ptr) override;
- virtual void device_add_mconfig(machine_config &config) override;
+ virtual ioport_constructor device_input_ports() const override ATTR_COLD;
+ 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;
virtual void tra_callback() override;
virtual void tra_complete() override;
virtual void rcv_complete() override;
private:
- static constexpr int TIMER_POLL = 1;
-
- void queue();
+ TIMER_CALLBACK_MEMBER(update_queue);
required_device<bitbanger_device> m_stream;
required_ioport m_rs232_txbaud;
required_ioport m_rs232_rxbaud;
- required_ioport m_rs232_startbits;
required_ioport m_rs232_databits;
required_ioport m_rs232_parity;
required_ioport m_rs232_stopbits;
@@ -50,6 +49,8 @@ private:
uint32_t m_input_index;
emu_timer *m_timer_poll;
int m_rts;
+ int m_dtr;
+ int m_xoff;
};
DECLARE_DEVICE_TYPE(NULL_MODEM, null_modem_device)
diff --git a/src/devices/bus/rs232/patchbox.cpp b/src/devices/bus/rs232/patchbox.cpp
new file mode 100644
index 00000000000..cc84dff5818
--- /dev/null
+++ b/src/devices/bus/rs232/patchbox.cpp
@@ -0,0 +1,214 @@
+// license:BSD-3-Clause
+// copyright-holders:Vas Crabb
+
+#include "emu.h"
+#include "patchbox.h"
+
+#include <algorithm>
+#include <iterator>
+
+
+namespace {
+
+enum : ioport_value
+{
+ // DB25 DE9 V.24 circuit
+ TXD, // 2 3 103
+ RXD, // 3 2 104
+ RTS, // 4 7 105
+ CTS, // 5 8 106
+ DSR, // 6 6 107
+ DTR, // 20 4 108/2
+ DCD, // 8 1 109
+ SPDS, // 23 111
+ SI, // 112
+ ETC, // 24 113
+ TXC, // 15 114
+ RXC, // 17 115
+ RI, // 22 9 125
+ ASSERT,
+ DEASSERT,
+
+ SIGNAL_COUNT
+};
+
+
+class rs232_patch_box_device: public device_t, public device_rs232_port_interface
+{
+public:
+ rs232_patch_box_device(
+ machine_config const &mconfig,
+ char const *tag,
+ device_t *owner,
+ uint32_t clock)
+ : device_t(mconfig, RS232_PATCH_BOX, tag, owner, clock)
+ , device_rs232_port_interface(mconfig, *this)
+ , m_dce_port(*this, "dce")
+ , m_conf(*this, "CONF%u", 0)
+ {
+ }
+
+ DECLARE_INPUT_CHANGED_MEMBER(source_changed)
+ {
+ unsigned const newsource = m_conf[param]->read() & 0x0f;
+ u8 const newsig = m_signals[newsource];
+ bool const changed = m_signals[m_sources[param]] != newsig;
+ m_sources[param] = newsource;
+ if (changed)
+ {
+ u8 const newout = newsig ^ m_invert[param];
+ switch (param)
+ {
+ case RXD: output_rxd(newout); break;
+ case DCD: output_dcd(newout); break;
+ case DSR: output_dsr(newout); break;
+ case RI: output_ri(newout); break;
+ case SI: output_si(newout); break;
+ case CTS: output_cts(newout); break;
+ case RXC: output_rxc(newout); break;
+ case TXC: output_txc(newout); break;
+
+ case TXD: m_dce_port->write_txd(newout); break;
+ case DTR: m_dce_port->write_dtr(newout); break;
+ case RTS: m_dce_port->write_rts(newout); break;
+ case ETC: m_dce_port->write_etc(newout); break;
+ case SPDS: m_dce_port->write_spds(newout); break;
+ }
+ }
+ }
+
+protected:
+ virtual void device_add_mconfig(machine_config &config) override
+ {
+ RS232_PORT(config, m_dce_port, default_rs232_devices, nullptr);
+ m_dce_port->rxd_handler().set(FUNC(rs232_patch_box_device::signal_in<RXD>));
+ m_dce_port->dcd_handler().set(FUNC(rs232_patch_box_device::signal_in<DCD>));
+ m_dce_port->dsr_handler().set(FUNC(rs232_patch_box_device::signal_in<DSR>));
+ m_dce_port->ri_handler().set(FUNC(rs232_patch_box_device::signal_in<RI>));
+ m_dce_port->si_handler().set(FUNC(rs232_patch_box_device::signal_in<SI>));
+ m_dce_port->cts_handler().set(FUNC(rs232_patch_box_device::signal_in<CTS>));
+ m_dce_port->rxc_handler().set(FUNC(rs232_patch_box_device::signal_in<RXC>));
+ m_dce_port->txc_handler().set(FUNC(rs232_patch_box_device::signal_in<TXC>));
+ }
+
+ virtual ioport_constructor device_input_ports() const override ATTR_COLD;
+
+ virtual void device_resolve_objects() override
+ {
+ std::fill(std::begin(m_sources), std::end(m_sources), DEASSERT);
+ std::fill(std::begin(m_invert), std::end(m_invert), 0);
+ std::fill(std::begin(m_signals), std::end(m_signals), 1);
+ m_signals[ASSERT] = 0;
+ }
+
+ virtual void device_start() override
+ {
+ save_item(NAME(m_signals));
+ }
+
+ virtual void device_reset() override
+ {
+ for (unsigned i = 0; m_conf.size() > i; ++i)
+ m_sources[i] = m_conf[i]->read() & 0x0f;
+
+ output_rxd(m_signals[m_sources[RXD]] ^ m_invert[RXD]);
+ output_dcd(m_signals[m_sources[DCD]] ^ m_invert[DCD]);
+ output_dsr(m_signals[m_sources[DSR]] ^ m_invert[DSR]);
+ output_ri(m_signals[m_sources[RI]] ^ m_invert[RI]);
+ output_si(m_signals[m_sources[SI]] ^ m_invert[SI]);
+ output_cts(m_signals[m_sources[CTS]] ^ m_invert[CTS]);
+ output_rxc(m_signals[m_sources[RXC]] ^ m_invert[RXC]);
+ output_txc(m_signals[m_sources[TXC]] ^ m_invert[TXC]);
+
+ m_dce_port->write_txd(m_signals[m_sources[TXD]] ^ m_invert[TXD]);
+ m_dce_port->write_dtr(m_signals[m_sources[DTR]] ^ m_invert[DTR]);
+ m_dce_port->write_rts(m_signals[m_sources[RTS]] ^ m_invert[RTS]);
+ m_dce_port->write_etc(m_signals[m_sources[ETC]] ^ m_invert[ETC]);
+ m_dce_port->write_spds(m_signals[m_sources[SPDS]] ^ m_invert[SPDS]);
+ }
+
+ 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>
+ void signal_in(int state)
+ {
+ state = state ? 1 : 0;
+ if (m_signals[Signal] != state)
+ {
+ m_signals[Signal] = state;
+
+ if (Signal == m_sources[RXD]) output_rxd(state ^ m_invert[RXD]);
+ if (Signal == m_sources[DCD]) output_dcd(state ^ m_invert[DCD]);
+ if (Signal == m_sources[DSR]) output_dsr(state ^ m_invert[DSR]);
+ if (Signal == m_sources[RI]) output_ri(state ^ m_invert[RI]);
+ if (Signal == m_sources[SI]) output_si(state ^ m_invert[SI]);
+ if (Signal == m_sources[CTS]) output_cts(state ^ m_invert[CTS]);
+ if (Signal == m_sources[RXC]) output_rxc(state ^ m_invert[RXC]);
+ if (Signal == m_sources[TXC]) output_txc(state ^ m_invert[TXC]);
+
+ if (Signal == m_sources[TXD]) m_dce_port->write_txd(state ^ m_invert[TXD]);
+ if (Signal == m_sources[DTR]) m_dce_port->write_dtr(state ^ m_invert[DTR]);
+ if (Signal == m_sources[RTS]) m_dce_port->write_rts(state ^ m_invert[RTS]);
+ if (Signal == m_sources[ETC]) m_dce_port->write_etc(state ^ m_invert[ETC]);
+ if (Signal == m_sources[SPDS]) m_dce_port->write_spds(state ^ m_invert[SPDS]);
+ }
+ }
+
+ required_device<rs232_port_device> m_dce_port;
+ required_ioport_array<13> m_conf;
+ u8 m_sources[13];
+ u8 m_invert[SIGNAL_COUNT];
+ u8 m_signals[SIGNAL_COUNT];
+};
+
+
+#define SOURCE_OPTIONS(prtname, dflt, cnfname) \
+ PORT_START(prtname) \
+ PORT_CONFNAME(0x0f, dflt, cnfname) PORT_CHANGED_MEMBER(DEVICE_SELF, FUNC(rs232_patch_box_device::source_changed), dflt) \
+ PORT_CONFSETTING(TXD, "TxD") \
+ PORT_CONFSETTING(RXD, "RxD") \
+ PORT_CONFSETTING(RTS, "RTS") \
+ PORT_CONFSETTING(CTS, "CTS") \
+ PORT_CONFSETTING(DSR, "DSR") \
+ PORT_CONFSETTING(DTR, "DTR") \
+ PORT_CONFSETTING(DCD, "DCD") \
+ PORT_CONFSETTING(SPDS, "SpdS") \
+ PORT_CONFSETTING(SI, "SI") \
+ PORT_CONFSETTING(ETC, "ETC") \
+ PORT_CONFSETTING(TXC, "TxC") \
+ PORT_CONFSETTING(RXC, "RxC") \
+ PORT_CONFSETTING(RI, "RI") \
+ PORT_CONFSETTING(ASSERT, "Asserted") \
+ PORT_CONFSETTING(DEASSERT, "Deasserted")
+
+INPUT_PORTS_START(patchbox)
+ SOURCE_OPTIONS("CONF0", TXD, "TxD Source (V.24 103)")
+ SOURCE_OPTIONS("CONF1", RXD, "RxD Source (V.24 104)")
+ SOURCE_OPTIONS("CONF2", RTS, "RTS Source (V.24 105)")
+ SOURCE_OPTIONS("CONF3", CTS, "CTS Source (V.24 106)")
+ SOURCE_OPTIONS("CONF4", DSR, "DSR Source (V.24 107)")
+ SOURCE_OPTIONS("CONF5", DTR, "DTR Source (V.24 108/2)")
+ SOURCE_OPTIONS("CONF6", DCD, "DCD Source (V.24 109)")
+ SOURCE_OPTIONS("CONF7", SPDS,"SpdS Source (V.24 111)")
+ SOURCE_OPTIONS("CONF8", SI, "SI Source (V.24 112)")
+ SOURCE_OPTIONS("CONF9", ETC, "ETC Source (V.24 113)")
+ SOURCE_OPTIONS("CONF10", TXC, "TxC Source (V.24 114)")
+ SOURCE_OPTIONS("CONF11", RXC, "RxC Source (V.24 115)")
+ SOURCE_OPTIONS("CONF12", RI, "RI Source (V.24 125)")
+INPUT_PORTS_END
+
+
+ioport_constructor rs232_patch_box_device::device_input_ports() const
+{
+ return INPUT_PORTS_NAME(patchbox);
+}
+
+} // anonymous namespace
+
+
+DEFINE_DEVICE_TYPE_PRIVATE(RS232_PATCH_BOX, device_rs232_port_interface, rs232_patch_box_device, "rs232_patch_box", "RS-232 Patch Box")
diff --git a/src/devices/bus/rs232/patchbox.h b/src/devices/bus/rs232/patchbox.h
new file mode 100644
index 00000000000..584963b32ba
--- /dev/null
+++ b/src/devices/bus/rs232/patchbox.h
@@ -0,0 +1,13 @@
+// license:BSD-3-Clause
+// copyright-holders:Vas Crabb
+#ifndef MAME_BUS_RS232_PATCHBOX_H
+#define MAME_BUS_RS232_PATCHBOX_H
+
+#pragma once
+
+#include "rs232.h"
+
+
+DECLARE_DEVICE_TYPE(RS232_PATCH_BOX, device_rs232_port_interface)
+
+#endif // MAME_BUS_RS232_PATCHBOX_H
diff --git a/src/devices/bus/rs232/printer.cpp b/src/devices/bus/rs232/printer.cpp
index b9e13ca4ef2..0112edc8715 100644
--- a/src/devices/bus/rs232/printer.cpp
+++ b/src/devices/bus/rs232/printer.cpp
@@ -1,15 +1,32 @@
// license:BSD-3-Clause
// copyright-holders:smf
+
+/**************************************************************************
+
+ Simple printer emulation
+
+ This allows capturing the byte stream to a file.
+
+ Radio Shack printers differ in that the RX line is used as a
+ busy signal.
+
+**************************************************************************/
+
#include "emu.h"
#include "printer.h"
serial_printer_device::serial_printer_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
- : device_t(mconfig, SERIAL_PRINTER, tag, owner, clock),
+ : serial_printer_device(mconfig, SERIAL_PRINTER, tag, owner, clock)
+{
+}
+
+serial_printer_device::serial_printer_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_serial_interface(mconfig, *this),
device_rs232_port_interface(mconfig, *this),
+ m_initial_rx_state(1),
m_printer(*this, "printer"),
m_rs232_rxbaud(*this, "RS232_RXBAUD"),
- m_rs232_startbits(*this, "RS232_STARTBITS"),
m_rs232_databits(*this, "RS232_DATABITS"),
m_rs232_parity(*this, "RS232_PARITY"),
m_rs232_stopbits(*this, "RS232_STOPBITS")
@@ -24,7 +41,6 @@ void serial_printer_device::device_add_mconfig(machine_config &config)
static INPUT_PORTS_START(serial_printer)
PORT_RS232_BAUD("RS232_RXBAUD", RS232_BAUD_9600, "RX Baud", serial_printer_device, update_serial)
- PORT_RS232_STARTBITS("RS232_STARTBITS", RS232_STARTBITS_1, "Start Bits", serial_printer_device, update_serial)
PORT_RS232_DATABITS("RS232_DATABITS", RS232_DATABITS_8, "Data Bits", serial_printer_device, update_serial)
PORT_RS232_PARITY("RS232_PARITY", RS232_PARITY_NONE, "Parity", serial_printer_device, update_serial)
PORT_RS232_STOPBITS("RS232_STOPBITS", RS232_STOPBITS_1, "Stop Bits", serial_printer_device, update_serial)
@@ -39,9 +55,9 @@ void serial_printer_device::device_start()
{
}
-WRITE_LINE_MEMBER(serial_printer_device::update_serial)
+void serial_printer_device::update_serial(int state)
{
- int startbits = convert_startbits(m_rs232_startbits->read());
+ int startbits = 1;
int databits = convert_databits(m_rs232_databits->read());
parity_t parity = convert_parity(m_rs232_parity->read());
stop_bits_t stopbits = convert_stopbits(m_rs232_stopbits->read());
@@ -52,7 +68,7 @@ WRITE_LINE_MEMBER(serial_printer_device::update_serial)
set_rcv_rate(rxbaud);
// TODO: make this configurable
- output_rxd(0);
+ output_rxd(m_initial_rx_state);
output_dcd(0);
output_dsr(0);
output_cts(0);
@@ -63,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: ?
}
@@ -74,4 +90,11 @@ void serial_printer_device::rcv_complete()
m_printer->output(get_received_char());
}
+radio_shack_serial_printer_device::radio_shack_serial_printer_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
+ : serial_printer_device(mconfig, RADIO_SHACK_SERIAL_PRINTER, tag, owner, clock)
+{
+ m_initial_rx_state = 0;
+}
+
DEFINE_DEVICE_TYPE(SERIAL_PRINTER, serial_printer_device, "serial_printer", "Serial Printer")
+DEFINE_DEVICE_TYPE(RADIO_SHACK_SERIAL_PRINTER, radio_shack_serial_printer_device, "rs_serial_printer", "Radio Shack Serial Printer")
diff --git a/src/devices/bus/rs232/printer.h b/src/devices/bus/rs232/printer.h
index 8cab55e7344..ece0bad54f2 100644
--- a/src/devices/bus/rs232/printer.h
+++ b/src/devices/bus/rs232/printer.h
@@ -16,30 +16,38 @@ 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:
- 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;
+ serial_printer_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 ATTR_COLD;
+ virtual ioport_constructor device_input_ports() const override ATTR_COLD;
+ virtual void device_start() override ATTR_COLD;
+ virtual void device_reset() override ATTR_COLD;
virtual void rcv_complete() override;
+ int m_initial_rx_state;
private:
- DECLARE_WRITE_LINE_MEMBER(printer_online);
+ void printer_online(int state);
required_device<printer_image_device> m_printer;
required_ioport m_rs232_rxbaud;
- required_ioport m_rs232_startbits;
required_ioport m_rs232_databits;
required_ioport m_rs232_parity;
required_ioport m_rs232_stopbits;
};
+class radio_shack_serial_printer_device : public serial_printer_device
+{
+public:
+ radio_shack_serial_printer_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
+};
+
DECLARE_DEVICE_TYPE(SERIAL_PRINTER, serial_printer_device)
+DECLARE_DEVICE_TYPE(RADIO_SHACK_SERIAL_PRINTER, radio_shack_serial_printer_device)
#endif // MAME_BUS_RS232_PRINTER_H
diff --git a/src/devices/bus/rs232/pty.cpp b/src/devices/bus/rs232/pty.cpp
index 4c8c9f6bbf7..f633f72bdec 100644
--- a/src/devices/bus/rs232/pty.cpp
+++ b/src/devices/bus/rs232/pty.cpp
@@ -4,11 +4,9 @@
#include "emu.h"
#include "pty.h"
-#include <stdio.h>
+#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),
@@ -16,19 +14,22 @@ pseudo_terminal_device::pseudo_terminal_device(const machine_config &mconfig, co
device_pty_interface(mconfig, *this),
m_rs232_txbaud(*this, "RS232_TXBAUD"),
m_rs232_rxbaud(*this, "RS232_RXBAUD"),
- m_rs232_startbits(*this, "RS232_STARTBITS"),
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 = convert_startbits(m_rs232_startbits->read());
+ int startbits = 1;
int databits = convert_databits(m_rs232_databits->read());
parity_t parity = convert_parity(m_rs232_parity->read());
stop_bits_t stopbits = convert_stopbits(m_rs232_stopbits->read());
@@ -47,15 +48,23 @@ 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)
PORT_RS232_BAUD("RS232_TXBAUD", RS232_BAUD_9600, "TX Baud", pseudo_terminal_device, update_serial)
PORT_RS232_BAUD("RS232_RXBAUD", RS232_BAUD_9600, "RX Baud", pseudo_terminal_device, update_serial)
- PORT_RS232_STARTBITS("RS232_STARTBITS", RS232_STARTBITS_1, "Start Bits", pseudo_terminal_device, update_serial)
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
@@ -65,7 +74,7 @@ ioport_constructor pseudo_terminal_device::device_input_ports() const
void pseudo_terminal_device::device_start()
{
- m_timer_poll = timer_alloc(TIMER_POLL);
+ m_timer_poll = timer_alloc(FUNC(pseudo_terminal_device::update_queue), this);
open();
}
@@ -78,20 +87,7 @@ void pseudo_terminal_device::device_stop()
void pseudo_terminal_device::device_reset()
{
update_serial(0);
- queue();
-}
-
-void pseudo_terminal_device::device_timer(emu_timer &timer, device_timer_id id, int param, void *ptr)
-{
- switch (id)
- {
- case TIMER_POLL:
- queue();
- break;
-
- default:
- break;
- }
+ update_queue(0);
}
void pseudo_terminal_device::tra_callback()
@@ -101,42 +97,66 @@ void pseudo_terminal_device::tra_callback()
void pseudo_terminal_device::tra_complete()
{
- queue();
+ update_queue(0);
}
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);
+ }
}
-void pseudo_terminal_device::queue(void)
+TIMER_CALLBACK_MEMBER(pseudo_terminal_device::update_queue)
{
if (is_transmit_register_empty())
{
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 88550fd5791..ea4cd39c7c3 100644
--- a/src/devices/bus/rs232/pty.h
+++ b/src/devices/bus/rs232/pty.h
@@ -17,35 +17,37 @@ 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;
- virtual void device_start() override;
- virtual void device_stop() override;
- virtual void device_reset() override;
- virtual void device_timer(emu_timer &timer, device_timer_id id, int param, void *ptr) override;
+ virtual ioport_constructor device_input_ports() const override ATTR_COLD;
+ virtual void device_start() override ATTR_COLD;
+ virtual void device_stop() override ATTR_COLD;
+ virtual void device_reset() override ATTR_COLD;
virtual void tra_callback() override;
virtual void tra_complete() override;
virtual void rcv_complete() override;
private:
- void queue(void);
+ TIMER_CALLBACK_MEMBER(update_queue);
required_ioport m_rs232_txbaud;
required_ioport m_rs232_rxbaud;
- required_ioport m_rs232_startbits;
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 1db03002775..b54a0d86bcd 100644
--- a/src/devices/bus/rs232/rs232.cpp
+++ b/src/devices/bus/rs232/rs232.cpp
@@ -42,7 +42,7 @@
#include "emu.h"
#include "rs232.h"
-DEFINE_DEVICE_TYPE(RS232_PORT, rs232_port_device, "rs232", "RS232 Port")
+DEFINE_DEVICE_TYPE(RS232_PORT, rs232_port_device, "rs232", "RS-232 Port")
rs232_port_device::rs232_port_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) :
rs232_port_device(mconfig, RS232_PORT, tag, owner, clock)
@@ -51,7 +51,7 @@ rs232_port_device::rs232_port_device(const machine_config &mconfig, const char *
rs232_port_device::rs232_port_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),
+ device_single_card_slot_interface<device_rs232_port_interface>(mconfig, *this),
m_rxd(0),
m_dcd(0),
m_dsr(0),
@@ -78,19 +78,27 @@ rs232_port_device::~rs232_port_device()
void rs232_port_device::device_config_complete()
{
- m_dev = dynamic_cast<device_rs232_port_interface *>(get_card_device());
+ m_dev = get_card_device();
}
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;
+ m_ri = 1;
+ m_si = 1;
+ m_cts = 1;
+}
+
+void rs232_port_device::device_reset()
+{
+ m_rxd_handler(m_rxd);
+ m_dcd_handler(m_dcd);
+ m_dsr_handler(m_dsr);
+ m_ri_handler(m_ri);
+ m_si_handler(m_si);
+ m_cts_handler(m_cts);
}
void rs232_port_device::device_start()
@@ -103,54 +111,40 @@ void rs232_port_device::device_start()
save_item(NAME(m_cts));
save_item(NAME(m_dce_rxc));
save_item(NAME(m_dce_txc));
-
- m_rxd = 1;
- m_dcd = 1;
- m_dsr = 1;
- m_ri = 1;
- m_si = 1;
- m_cts = 1;
-
- m_rxd_handler(1);
- m_dcd_handler(1);
- m_dsr_handler(1);
- m_ri_handler(1);
- m_si_handler(1);
- m_cts_handler(1);
}
-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);
}
device_rs232_port_interface::device_rs232_port_interface(const machine_config &mconfig, device_t &device) :
- device_slot_card_interface(mconfig, device)
+ device_interface(device, "rs232")
{
m_port = dynamic_cast<rs232_port_device *>(device.owner());
}
@@ -159,24 +153,43 @@ device_rs232_port_interface::~device_rs232_port_interface()
{
}
+
+#include "ie15.h"
+#include "hlemouse.h"
#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"
-#include "ie15.h"
+
+template class device_finder<device_rs232_port_interface, false>;
+template class device_finder<device_rs232_port_interface, true>;
void default_rs232_devices(device_slot_interface &device)
{
- device.option_add("keyboard", SERIAL_KEYBOARD);
- device.option_add("loopback", RS232_LOOPBACK);
- device.option_add("dec_loopback", DEC_RS232_LOOPBACK);
- device.option_add("null_modem", NULL_MODEM);
- device.option_add("printer", SERIAL_PRINTER);
- device.option_add("terminal", SERIAL_TERMINAL);
- device.option_add("pty", PSEUDO_TERMINAL);
- device.option_add("sunkbd", SUN_KBD_ADAPTOR);
- device.option_add("ie15", SERIAL_TERMINAL_IE15);
+ device.option_add("dec_loopback", DEC_RS232_LOOPBACK);
+ device.option_add("ie15", SERIAL_TERMINAL_IE15);
+ device.option_add("keyboard", SERIAL_KEYBOARD);
+ device.option_add("loopback", RS232_LOOPBACK);
+ device.option_add("mockingboard", SERIAL_MOCKINGBOARD_D);
+ device.option_add("msystems_mouse",MSYSTEMS_HLE_SERIAL_MOUSE);
+ 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 781fb95d072..2ac20051b8e 100644
--- a/src/devices/bus/rs232/rs232.h
+++ b/src/devices/bus/rs232/rs232.h
@@ -22,17 +22,33 @@
#define RS232_BAUD_38400 (0x0b)
#define RS232_BAUD_57600 (0x0c)
#define RS232_BAUD_115200 (0x0d)
-#define RS232_BAUD_7200 (0x0e)
+
+#define RS232_BAUD_50 (0x0e)
+#define RS232_BAUD_75 (0x0f)
+#define RS232_BAUD_134_5 (0x10)
+#define RS232_BAUD_200 (0x11)
+#define RS232_BAUD_1800 (0x12)
+#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) \
- PORT_CONFNAME(0xff, _default_baud, _description) PORT_WRITE_LINE_DEVICE_MEMBER(DEVICE_SELF, _class, _write_line) \
+ PORT_CONFNAME(0xff, _default_baud, _description) PORT_WRITE_LINE_DEVICE_MEMBER(DEVICE_SELF, FUNC(_class::_write_line)) \
+ PORT_CONFSETTING( RS232_BAUD_50, "50") \
+ PORT_CONFSETTING( RS232_BAUD_75, "75") \
PORT_CONFSETTING( RS232_BAUD_110, "110") \
+ PORT_CONFSETTING( RS232_BAUD_134_5, "134.5") \
PORT_CONFSETTING( RS232_BAUD_150, "150") \
+ PORT_CONFSETTING( RS232_BAUD_200, "200") \
PORT_CONFSETTING( RS232_BAUD_300, "300") \
PORT_CONFSETTING( RS232_BAUD_600, "600") \
PORT_CONFSETTING( RS232_BAUD_1200, "1200") \
+ PORT_CONFSETTING( RS232_BAUD_1800, "1800") \
+ PORT_CONFSETTING( RS232_BAUD_2000, "2000") \
PORT_CONFSETTING( RS232_BAUD_2400, "2400") \
+ PORT_CONFSETTING( RS232_BAUD_3600, "3600") \
PORT_CONFSETTING( RS232_BAUD_4800, "4800") \
PORT_CONFSETTING( RS232_BAUD_7200, "7200") \
PORT_CONFSETTING( RS232_BAUD_9600, "9600") \
@@ -41,17 +57,9 @@
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_STARTBITS_0 (0x00)
-#define RS232_STARTBITS_1 (0x01)
-
-#define PORT_RS232_STARTBITS(_tag, _default_startbits, _description, _class, _write_line) \
- PORT_START(_tag) \
- PORT_CONFNAME(0xff, _default_startbits, _description) PORT_WRITE_LINE_DEVICE_MEMBER(DEVICE_SELF, _class, _write_line) \
- PORT_CONFSETTING( RS232_STARTBITS_0, "0") \
- PORT_CONFSETTING( RS232_STARTBITS_1, "1")
-
#define RS232_DATABITS_5 (0x00)
#define RS232_DATABITS_6 (0x01)
#define RS232_DATABITS_7 (0x02)
@@ -59,7 +67,7 @@
#define PORT_RS232_DATABITS(_tag, _default_databits, _description, _class, _write_line) \
PORT_START(_tag) \
- PORT_CONFNAME(0xff, _default_databits, _description) PORT_WRITE_LINE_DEVICE_MEMBER(DEVICE_SELF, _class, _write_line) \
+ PORT_CONFNAME(0xff, _default_databits, _description) PORT_WRITE_LINE_DEVICE_MEMBER(DEVICE_SELF, FUNC(_class::_write_line)) \
PORT_CONFSETTING( RS232_DATABITS_5, "5") \
PORT_CONFSETTING( RS232_DATABITS_6, "6") \
PORT_CONFSETTING( RS232_DATABITS_7, "7") \
@@ -73,7 +81,7 @@
#define PORT_RS232_PARITY(_tag, _default_parity, _description, _class, _write_line) \
PORT_START(_tag) \
- PORT_CONFNAME(0xff, _default_parity, "Parity") PORT_WRITE_LINE_DEVICE_MEMBER(DEVICE_SELF, _class, _write_line) \
+ PORT_CONFNAME(0xff, _default_parity, "Parity") PORT_WRITE_LINE_DEVICE_MEMBER(DEVICE_SELF, FUNC(_class::_write_line)) \
PORT_CONFSETTING( RS232_PARITY_NONE, "None") \
PORT_CONFSETTING( RS232_PARITY_ODD, "Odd") \
PORT_CONFSETTING( RS232_PARITY_EVEN, "Even") \
@@ -87,7 +95,7 @@
#define PORT_RS232_STOPBITS(_tag, _default_stopbits, _description, _class, _write_line) \
PORT_START(_tag) \
- PORT_CONFNAME(0xff, 0x01, _description) PORT_WRITE_LINE_DEVICE_MEMBER(DEVICE_SELF, _class, _write_line) \
+ PORT_CONFNAME(0xff, 0x01, _description) PORT_WRITE_LINE_DEVICE_MEMBER(DEVICE_SELF, FUNC(_class::_write_line)) \
PORT_CONFSETTING( RS232_STOPBITS_0, "0") \
PORT_CONFSETTING( RS232_STOPBITS_1, "1") \
PORT_CONFSETTING( RS232_STOPBITS_1_5, "1.5") \
@@ -95,7 +103,7 @@
class device_rs232_port_interface;
-class rs232_port_device : public device_t, public device_slot_interface
+class rs232_port_device : public device_t, public device_single_card_slot_interface<device_rs232_port_interface>
{
friend class device_rs232_port_interface;
@@ -109,7 +117,7 @@ public:
set_default_option(dflt);
set_fixed(false);
}
- rs232_port_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
+ rs232_port_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock = 0);
virtual ~rs232_port_device();
// static configuration helpers
@@ -122,26 +130,27 @@ public:
auto rxc_handler() { return m_rxc_handler.bind(); }
auto txc_handler() { return m_txc_handler.bind(); }
- DECLARE_WRITE_LINE_MEMBER( write_txd );
- DECLARE_WRITE_LINE_MEMBER( write_dtr );
- DECLARE_WRITE_LINE_MEMBER( write_rts );
- DECLARE_WRITE_LINE_MEMBER( write_etc );
- DECLARE_WRITE_LINE_MEMBER( write_spds );
-
- DECLARE_READ_LINE_MEMBER( rxd_r ) { return m_rxd; }
- DECLARE_READ_LINE_MEMBER( dcd_r ) { return m_dcd; }
- DECLARE_READ_LINE_MEMBER( dsr_r ) { return m_dsr; }
- DECLARE_READ_LINE_MEMBER( ri_r ) { return m_ri; }
- DECLARE_READ_LINE_MEMBER( si_r ) { return m_si; }
- DECLARE_READ_LINE_MEMBER( cts_r ) { return m_cts; }
- DECLARE_READ_LINE_MEMBER( rxc_r ) { return m_dce_rxc; }
- DECLARE_READ_LINE_MEMBER( txc_r ) { return m_dce_txc; }
+ 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);
- virtual void device_resolve_objects() override;
- virtual void device_start() override;
+ virtual void device_resolve_objects() override ATTR_COLD;
+ virtual void device_reset() override ATTR_COLD;
+ virtual void device_start() override ATTR_COLD;
virtual void device_config_complete() override;
int m_rxd;
@@ -166,27 +175,27 @@ private:
device_rs232_port_interface *m_dev;
};
-class device_rs232_port_interface : public device_slot_card_interface
+class device_rs232_port_interface : public device_interface
{
friend class rs232_port_device;
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);
@@ -211,21 +220,19 @@ protected:
38400,
57600,
115200,
- 7200
- };
-
- return values[baud];
- }
- static int convert_startbits(uint8_t startbits)
- {
- static const int values[] =
- {
- 0,
- 1
+ 50,
+ 75,
+ 134, // -0.37% error
+ 200,
+ 1800,
+ 2000,
+ 3600,
+ 7200,
+ 111900
};
- return values[startbits];
+ return values[baud];
}
static int convert_databits(uint8_t databits)
@@ -273,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
new file mode 100644
index 00000000000..9812087b363
--- /dev/null
+++ b/src/devices/bus/rs232/rs232_sync_io.cpp
@@ -0,0 +1,201 @@
+// license:BSD-3-Clause
+// copyright-holders: F. Ulivi
+/*********************************************************************
+
+ rs232_sync_io.cpp
+
+ Synchronous I/O on RS232 port
+
+ This device provides a bitbanger-based interface to a synchronous
+ RS232 port.
+ It has the following functions:
+ - Provides Tx and/or Rx clock to RS232 port; clocks can be
+ individually turned off when not needed (e.g. Tx clock can
+ disabled when receiving in half-duplex mode)
+ - In the tx direction, it gathers bits from TxD,
+ packs them into bytes LSB to MSB, then sends them out to
+ bitbanger
+ - In the rx direction, it extracts bytes from bitbanger
+ and serializes them to RxD, LSB to MSB.
+ - Supports both full-duplex and half-duplex modes
+ - Generates CTS signal
+
+ There's no kind of synchronization to any higher-level framing:
+ bits are just clocked in/out of the port, packed/unpacked into
+ bytes and exchanged with bitbanger.
+ There's also no automatic stuffing of idle line characters, this
+ function is to be implemented externally if needed.
+
+*********************************************************************/
+
+#include "emu.h"
+#include "rs232_sync_io.h"
+
+// Debugging
+
+#include "logmacro.h"
+//#undef VERBOSE
+//#define VERBOSE LOG_GENERAL
+
+// Bit manipulation
+namespace {
+ template<typename T> constexpr T BIT_MASK(unsigned n)
+ {
+ return (T)1U << n;
+ }
+
+ template<typename T> void BIT_CLR(T& w , unsigned n)
+ {
+ w &= ~BIT_MASK<T>(n);
+ }
+
+ template<typename T> void BIT_SET(T& w , unsigned n)
+ {
+ w |= BIT_MASK<T>(n);
+ }
+}
+
+rs232_sync_io_device::rs232_sync_io_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
+ : device_t(mconfig , RS232_SYNC_IO , tag , owner , clock)
+ , device_rs232_port_interface(mconfig , *this)
+ , m_stream(*this , "stream")
+ , m_rs232_baud(*this , "RS232_BAUD")
+ , m_rts_duplex(*this , "rtsduplex")
+ , m_txc_setting(*this , "txcontrol")
+ , m_rxc_setting(*this , "rxcontrol")
+{
+}
+
+rs232_sync_io_device:: ~rs232_sync_io_device()
+{
+}
+
+void rs232_sync_io_device::input_txd(int state)
+{
+ m_txd = state;
+ LOG("TxD %d %u\n" , state , m_tx_counter);
+}
+
+void rs232_sync_io_device::input_rts(int state)
+{
+ m_rts = state;
+}
+
+static INPUT_PORTS_START(rs232_sync_io)
+ PORT_RS232_BAUD("RS232_BAUD" , RS232_BAUD_2400 , "Baud rate" , rs232_sync_io_device , update_serial)
+
+ PORT_START("rtsduplex")
+ PORT_CONFNAME(1 , 1 , "RTS controls half-duplex")
+ PORT_CONFSETTING(0 , DEF_STR(Off))
+ PORT_CONFSETTING(1 , DEF_STR(On))
+
+ PORT_START("txcontrol")
+ PORT_CONFNAME(1 , 1 , "TxC generated")
+ PORT_CONFSETTING(0 , "Always")
+ PORT_CONFSETTING(1 , "When Tx is active")
+
+ PORT_START("rxcontrol")
+ PORT_CONFNAME(3 , 1 , "RxC generated")
+ PORT_CONFSETTING(0 , "Always")
+ PORT_CONFSETTING(1 , "When Rx is active")
+ PORT_CONFSETTING(2 , "When a byte is available")
+INPUT_PORTS_END
+
+ioport_constructor rs232_sync_io_device::device_input_ports() const
+{
+ return INPUT_PORTS_NAME(rs232_sync_io);
+}
+
+void rs232_sync_io_device::device_add_mconfig(machine_config &config)
+{
+ BITBANGER(config , m_stream , 0);
+}
+
+void rs232_sync_io_device::device_start()
+{
+ m_clk_timer = timer_alloc(FUNC(rs232_sync_io_device::clock_tick), this);
+}
+
+void rs232_sync_io_device::device_reset()
+{
+ output_dcd(0);
+ output_dsr(0);
+ output_rxd(1);
+ output_cts(1);
+
+ update_serial(0);
+
+ m_clk = false;
+ m_rx_byte = 0xff;
+ m_rx_counter = 0;
+ m_tx_counter = 0;
+ m_tx_enabled = false;
+ m_rx_enabled = false;
+
+ output_txc(1);
+ output_rxc(1);
+}
+
+TIMER_CALLBACK_MEMBER(rs232_sync_io_device::clock_tick)
+{
+ m_clk = !m_clk;
+ if (m_clk) {
+ output_txc(1);
+ output_rxc(1);
+ if (m_tx_enabled) {
+ // Rising edge: capture TxD
+ m_tx_byte = (m_tx_byte >> 1) & 0x7f;
+ if (m_txd) {
+ BIT_SET(m_tx_byte , 7);
+ }
+ if (++m_tx_counter >= 8) {
+ LOG("Tx %02x @%s\n" , m_tx_byte , machine().time().to_string());
+ m_tx_counter = 0;
+ m_stream->output(m_tx_byte);
+ m_tx_enabled = false;
+ }
+ }
+ } else {
+ if (!m_tx_enabled) {
+ m_tx_enabled = !m_rts || !m_rts_duplex->read();
+ output_cts(!m_tx_enabled);
+ }
+ if (m_tx_enabled || m_txc_setting->read() == 0) {
+ output_txc(0);
+ }
+ if (!m_rx_enabled) {
+ m_rx_enabled = m_rts || !m_rts_duplex->read();
+ if (m_rx_enabled) {
+ if (m_stream->input(&m_rx_byte , 1) == 0) {
+ m_rx_byte = ~0;
+ if (m_rxc_setting->read() == 2) {
+ m_rx_enabled = false;
+ }
+ } else {
+ LOG("Rx %02x @%s\n" , m_rx_byte , machine().time().to_string());
+ }
+ }
+ }
+ if (m_rx_enabled || m_rxc_setting->read() == 0) {
+ output_rxc(0);
+ }
+ if (m_rx_enabled) {
+ // Falling edge: update RxD
+ output_rxd(BIT(m_rx_byte , 0));
+ m_rx_byte >>= 1;
+ if (++m_rx_counter >= 8) {
+ m_rx_counter = 0;
+ m_rx_enabled = false;
+ }
+ }
+ }
+}
+
+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", "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
new file mode 100644
index 00000000000..c8d83002cf5
--- /dev/null
+++ b/src/devices/bus/rs232/rs232_sync_io.h
@@ -0,0 +1,62 @@
+// license:BSD-3-Clause
+// copyright-holders: F. Ulivi
+/*********************************************************************
+
+ rs232_sync_io.h
+
+ Synchronous I/O on RS232 port
+
+*********************************************************************/
+
+#ifndef MAME_BUS_RS232_RS232_SYNC_IO_H
+#define MAME_BUS_RS232_RS232_SYNC_IO_H
+
+#pragma once
+
+#include "rs232.h"
+#include "imagedev/bitbngr.h"
+
+class rs232_sync_io_device : public device_t, public device_rs232_port_interface
+{
+public:
+ // construction/destruction
+ rs232_sync_io_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
+ virtual ~rs232_sync_io_device();
+
+ virtual void input_txd(int state) override;
+ virtual void input_rts(int state) override;
+
+ void update_serial(int state);
+
+protected:
+ // device-level overrides
+ virtual ioport_constructor device_input_ports() const override ATTR_COLD;
+ 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;
+
+ TIMER_CALLBACK_MEMBER(clock_tick);
+
+private:
+ required_device<bitbanger_device> m_stream;
+ required_ioport m_rs232_baud;
+ required_ioport m_rts_duplex;
+ required_ioport m_txc_setting;
+ required_ioport m_rxc_setting;
+
+ emu_timer *m_clk_timer;
+ bool m_clk;
+ bool m_txd;
+ bool m_rts;
+ bool m_tx_enabled;
+ bool m_rx_enabled;
+ uint8_t m_tx_byte;
+ uint8_t m_rx_byte;
+ uint8_t m_tx_counter;
+ uint8_t m_rx_counter;
+};
+
+// device type definitions
+DECLARE_DEVICE_TYPE(RS232_SYNC_IO, rs232_sync_io_device)
+
+#endif // MAME_BUS_RS232_RS232_SYNC_IO_H
diff --git a/src/devices/bus/rs232/scorpion.cpp b/src/devices/bus/rs232/scorpion.cpp
new file mode 100644
index 00000000000..0019e89944c
--- /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 ATTR_COLD;
+ virtual const tiny_rom_entry *device_rom_region() const override ATTR_COLD;
+
+ virtual void device_start() override ATTR_COLD;
+ virtual void device_reset() override ATTR_COLD;
+
+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) ATTR_COLD;
+
+ 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 4a7034e90b5..316a2012b82 100644
--- a/src/devices/bus/rs232/sun_kbd.cpp
+++ b/src/devices/bus/rs232/sun_kbd.cpp
@@ -1,49 +1,51 @@
#include "emu.h"
#include "sun_kbd.h"
+#include "bus/sunkbd/sunkbd.h"
-DEFINE_DEVICE_TYPE(SUN_KBD_ADAPTOR, sun_keyboard_adaptor_device, "sunkbd_adaptor", "Sun Keyboard Adaptor")
+namespace {
-sun_keyboard_adaptor_device::sun_keyboard_adaptor_device(
- machine_config const &mconfig,
- char const *tag,
- device_t *owner,
- uint32_t clock)
- : device_t(mconfig, SUN_KBD_ADAPTOR, tag, owner, clock)
- , device_rs232_port_interface(mconfig, *this)
- , m_keyboard_port(*this, "keyboard")
+class sun_keyboard_adaptor_device : public device_t, public device_rs232_port_interface
{
-}
-
-
-sun_keyboard_adaptor_device::~sun_keyboard_adaptor_device()
-{
-}
-
-
-void sun_keyboard_adaptor_device::device_add_mconfig(machine_config &config)
-{
- SUNKBD_PORT(config, m_keyboard_port, default_sun_keyboard_devices, nullptr);
- m_keyboard_port->rxd_handler().set(FUNC(sun_keyboard_adaptor_device::output_rxd));
-}
-
-
-WRITE_LINE_MEMBER(sun_keyboard_adaptor_device::input_txd)
-{
- m_keyboard_port->write_txd(state);
-}
-
-
-void sun_keyboard_adaptor_device::device_start()
-{
-}
-
-
-void sun_keyboard_adaptor_device::device_reset()
-{
- output_rxd(1);
- output_dcd(0);
- output_dsr(0);
- output_cts(0);
-}
+public:
+ sun_keyboard_adaptor_device(
+ machine_config const &mconfig,
+ char const *tag,
+ device_t *owner,
+ uint32_t clock)
+ : device_t(mconfig, SUN_KBD_ADAPTOR, tag, owner, clock)
+ , device_rs232_port_interface(mconfig, *this)
+ , m_keyboard_port(*this, "keyboard")
+ {
+ }
+
+ virtual void input_txd(int state) override { m_keyboard_port->write_txd(state); }
+
+protected:
+ virtual void device_add_mconfig(machine_config &config) override
+ {
+ SUNKBD_PORT(config, m_keyboard_port, default_sun_keyboard_devices, nullptr);
+ m_keyboard_port->rxd_handler().set(FUNC(sun_keyboard_adaptor_device::output_rxd));
+ }
+
+ virtual void device_start() override
+ {
+ }
+
+ virtual void device_reset() override
+ {
+ output_rxd(1);
+ output_dcd(0);
+ output_dsr(0);
+ output_cts(0);
+ }
+
+private:
+ required_device<sun_keyboard_port_device> m_keyboard_port;
+};
+
+} // anonymous namespace
+
+
+DEFINE_DEVICE_TYPE_PRIVATE(SUN_KBD_ADAPTOR, device_rs232_port_interface, sun_keyboard_adaptor_device, "sunkbd_adaptor", "Sun Keyboard Adaptor")
diff --git a/src/devices/bus/rs232/sun_kbd.h b/src/devices/bus/rs232/sun_kbd.h
index a93646f79de..208a81341f9 100644
--- a/src/devices/bus/rs232/sun_kbd.h
+++ b/src/devices/bus/rs232/sun_kbd.h
@@ -6,28 +6,8 @@
#pragma once
#include "rs232.h"
-#include "bus/sunkbd/sunkbd.h"
-DECLARE_DEVICE_TYPE(SUN_KBD_ADAPTOR, sun_keyboard_adaptor_device)
-
-
-class sun_keyboard_adaptor_device : public device_t, public device_rs232_port_interface
-{
-public:
- sun_keyboard_adaptor_device(machine_config const &mconfig, char const *tag, device_t *owner, uint32_t clock);
- virtual ~sun_keyboard_adaptor_device() override;
-
- virtual DECLARE_WRITE_LINE_MEMBER( input_txd ) override;
-
-protected:
- virtual void device_start() override;
- virtual void device_reset() override;
-
- virtual void device_add_mconfig(machine_config &config) override;
-
-private:
- required_device<sun_keyboard_port_device> m_keyboard_port;
-};
+DECLARE_DEVICE_TYPE(SUN_KBD_ADAPTOR, device_rs232_port_interface)
#endif // MAME_BUS_RS232_SUN_KBD_H
diff --git a/src/devices/bus/rs232/swtpc8212.cpp b/src/devices/bus/rs232/swtpc8212.cpp
new file mode 100644
index 00000000000..7ba9ce72660
--- /dev/null
+++ b/src/devices/bus/rs232/swtpc8212.cpp
@@ -0,0 +1,87 @@
+// license:BSD-3-Clause
+// copyright-holders:68bit
+
+#include "emu.h"
+#include "swtpc8212.h"
+
+swtpc8212_terminal_device::swtpc8212_terminal_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
+ : device_t(mconfig, SERIAL_TERMINAL_SWTPC8212, tag, owner, clock)
+ , device_rs232_port_interface(mconfig, *this)
+ , m_swtpc8212(*this, "swtpc8212")
+ , m_flow_control(*this, "FLOW_CONTROL")
+{
+}
+
+void swtpc8212_terminal_device::device_add_mconfig(machine_config &config)
+{
+ SWTPC8212(config, m_swtpc8212, 0);
+ m_swtpc8212->rs232_conn_txd_handler().set(FUNC(swtpc8212_terminal_device::output_rxd));
+ m_swtpc8212->rs232_conn_rts_handler().set(FUNC(swtpc8212_terminal_device::route_term_rts));
+ m_swtpc8212->rs232_conn_dtr_handler().set(FUNC(swtpc8212_terminal_device::route_term_dtr));
+}
+
+INPUT_PORTS_START(swtpc8212_terminal)
+
+ PORT_START("FLOW_CONTROL")
+ PORT_CONFNAME(0x1, 1, "Flow control") PORT_CHANGED_MEMBER(DEVICE_SELF, FUNC(swtpc8212_terminal_device::flow_control), 0)
+ PORT_CONFSETTING(0x00, "None")
+ PORT_CONFSETTING(0x01, "Terminal DTR to remote CTS")
+
+INPUT_PORTS_END
+
+ioport_constructor swtpc8212_terminal_device::device_input_ports() const
+{
+ return INPUT_PORTS_NAME(swtpc8212_terminal);
+}
+
+void swtpc8212_terminal_device::input_txd(int state)
+{
+ m_swtpc8212->rs232_conn_rxd_w(state);
+}
+
+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.
+void swtpc8212_terminal_device::route_term_dtr(int state)
+{
+ if (m_flow_control->read())
+ {
+ // Connect the terminal DTR output to CTS at the other end.
+ output_cts(state);
+ }
+
+ // Cache the state, in case the ioport setting changes.
+ m_dtr = state;
+}
+
+INPUT_CHANGED_MEMBER(swtpc8212_terminal_device::flow_control)
+{
+ if (newval)
+ output_cts(m_dtr);
+ else
+ output_cts(0);
+}
+
+void swtpc8212_terminal_device::device_start()
+{
+ save_item(NAME(m_dtr));
+}
+
+void swtpc8212_terminal_device::device_reset()
+{
+ // To the terminal
+ m_swtpc8212->rs232_conn_cts_w(0);
+
+ // To the computer
+ output_rxd(1);
+ output_dcd(0);
+ output_dsr(0);
+ if (!m_flow_control->read())
+ output_cts(0);
+}
+
+DEFINE_DEVICE_TYPE(SERIAL_TERMINAL_SWTPC8212, swtpc8212_terminal_device, "swtpc8212_terminal", "SWTPC8212 Terminal")
diff --git a/src/devices/bus/rs232/swtpc8212.h b/src/devices/bus/rs232/swtpc8212.h
new file mode 100644
index 00000000000..13d1fe1f6d3
--- /dev/null
+++ b/src/devices/bus/rs232/swtpc8212.h
@@ -0,0 +1,40 @@
+// license:BSD-3-Clause
+// copyright-holders:68bit
+
+#ifndef MAME_BUS_RS232_SWTPC8212_H
+#define MAME_BUS_RS232_SWTPC8212_H
+
+#pragma once
+
+#include "rs232.h"
+#include "machine/swtpc8212.h"
+
+
+class swtpc8212_terminal_device : public device_t, public device_rs232_port_interface
+{
+public:
+ swtpc8212_terminal_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
+
+ virtual void input_txd(int state) override;
+
+ DECLARE_INPUT_CHANGED_MEMBER(flow_control);
+
+protected:
+ 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;
+ virtual ioport_constructor device_input_ports() const override ATTR_COLD;
+
+private:
+ required_device<swtpc8212_device> m_swtpc8212;
+ required_ioport m_flow_control;
+
+ void route_term_rts(int state);
+ void route_term_dtr(int state);
+
+ int m_dtr;
+};
+
+DECLARE_DEVICE_TYPE(SERIAL_TERMINAL_SWTPC8212, swtpc8212_terminal_device)
+
+#endif // MAME_BUS_RS232_SWTPC8212_H
diff --git a/src/devices/bus/rs232/teletex800.cpp b/src/devices/bus/rs232/teletex800.cpp
new file mode 100644
index 00000000000..0bde70f4f67
--- /dev/null
+++ b/src/devices/bus/rs232/teletex800.cpp
@@ -0,0 +1,161 @@
+// license:BSD-3-Clause
+// copyright-holders:Curt Coder
+
+#include "emu.h"
+#include "printer.h"
+#include "teletex800.h"
+#include "cpu/z80/z80.h"
+#include "machine/6821pia.h"
+#include "machine/6850acia.h"
+#include "machine/z80ctc.h"
+#include "machine/z80daisy.h"
+#include "machine/z80sio.h"
+#include "teletex800.lh"
+
+namespace {
+
+class teletex_800_device : public device_t, public device_rs232_port_interface
+{
+public:
+ teletex_800_device(machine_config const &mconfig, char const *tag, device_t *owner, uint32_t clock) :
+ device_t(mconfig, TELETEX_800, tag, owner, clock),
+ device_rs232_port_interface(mconfig, *this),
+ m_maincpu(*this, "z80"),
+ m_ctc(*this, "ctc"),
+ m_sio(*this, "sio"),
+ m_acia(*this, "acia"),
+ m_pia(*this, "pia"),
+ m_pia_cp(*this, "pia_cp"),
+ m_bat_led(*this, "bat_led"),
+ m_pr_led(*this, "pr_led"),
+ m_telex_led(*this, "telex_led"),
+ m_mem_led(*this, "mem_led"),
+ m_obs_led(*this, "obs_led"),
+ m_write_led(*this, "write_led"),
+ m_log_led(*this, "log_led"),
+ m_queue_led(*this, "queue_led"),
+ m_all_led(*this, "all_led"),
+ m_time_led(*this, "time_led"),
+ m_date_led(*this, "date_led"),
+ m_year_led(*this, "year_led"),
+ m_rx_digits(*this, "rx_digit%u", 0U),
+ m_tx_digits(*this, "tx_digit%u", 0U)
+ {
+ }
+
+protected:
+ virtual const tiny_rom_entry *device_rom_region() const override
+ {
+ return ROM_NAME( teletex800 );
+ }
+
+ virtual void device_add_mconfig(machine_config &config) override
+ {
+ config.set_default_layout(layout_teletex800);
+
+ // main board
+ Z80(config, m_maincpu, XTAL(4'915'200));
+ m_maincpu->set_daisy_config(z80_daisy_chain);
+ m_maincpu->set_addrmap(AS_PROGRAM, &teletex_800_device::program_map);
+ m_maincpu->set_addrmap(AS_IO, &teletex_800_device::io_map);
+
+ Z80CTC(config, m_ctc, XTAL(4'915'200));
+ Z80SIO(config, m_sio, XTAL(4'915'200));
+ ACIA6850(config, m_acia);
+ PIA6821(config, m_pia);
+
+ RS232_PORT(config, "pr", printer_devices, "printer");
+
+ // control panel
+ PIA6821(config, m_pia_cp);
+ }
+
+ virtual ioport_constructor device_input_ports() const override
+ {
+ return INPUT_PORTS_NAME( teletex800 );
+ }
+
+ virtual void device_start() override
+ {
+ m_bat_led.resolve();
+ m_pr_led.resolve();
+ m_telex_led.resolve();
+ m_mem_led.resolve();
+ m_obs_led.resolve();
+ m_write_led.resolve();
+ m_log_led.resolve();
+ m_queue_led.resolve();
+ m_all_led.resolve();
+ m_time_led.resolve();
+ m_date_led.resolve();
+ m_year_led.resolve();
+ m_rx_digits.resolve();
+ m_tx_digits.resolve();
+ }
+
+ virtual void device_reset() override
+ {
+ }
+
+private:
+ required_device<z80_device> m_maincpu;
+ required_device<z80ctc_device> m_ctc;
+ required_device<z80sio_device> m_sio;
+ required_device<acia6850_device> m_acia;
+ required_device<pia6821_device> m_pia;
+ required_device<pia6821_device> m_pia_cp;
+
+ output_finder<> m_bat_led;
+ output_finder<> m_pr_led;
+ output_finder<> m_telex_led;
+ output_finder<> m_mem_led;
+ output_finder<> m_obs_led;
+ output_finder<> m_write_led;
+ output_finder<> m_log_led;
+ output_finder<> m_queue_led;
+ output_finder<> m_all_led;
+ output_finder<> m_time_led;
+ output_finder<> m_date_led;
+ output_finder<> m_year_led;
+ output_finder<2> m_rx_digits;
+ output_finder<2> m_tx_digits;
+
+ void program_map(address_map &map)
+ {
+ map(0x0000, 0x0fff).rom().region("z80", 0);
+ }
+
+ void io_map(address_map &map)
+ {
+ }
+
+ constexpr static const z80_daisy_config z80_daisy_chain[] =
+ {
+ { nullptr }
+ };
+
+ static void printer_devices(device_slot_interface &device)
+ {
+ device.option_add("printer", SERIAL_PRINTER);
+ }
+
+ INPUT_CHANGED_MEMBER( write ) { };
+ INPUT_CHANGED_MEMBER( all ) { };
+ INPUT_CHANGED_MEMBER( clock ) { };
+
+ static INPUT_PORTS_START( teletex800 )
+ PORT_START("BTN")
+ PORT_BIT( 0x01, IP_ACTIVE_LOW, IPT_OTHER ) PORT_NAME("SKRIV") PORT_CHANGED_MEMBER(DEVICE_SELF, FUNC(teletex_800_device::write), 0)
+ PORT_BIT( 0x02, IP_ACTIVE_LOW, IPT_OTHER ) PORT_NAME("ALLA") PORT_CHANGED_MEMBER(DEVICE_SELF, FUNC(teletex_800_device::all), 0)
+ PORT_BIT( 0x04, IP_ACTIVE_LOW, IPT_OTHER ) PORT_NAME("KLOCK") PORT_CHANGED_MEMBER(DEVICE_SELF, FUNC(teletex_800_device::clock), 0)
+ INPUT_PORTS_END
+
+ constexpr ROM_START( teletex800 )
+ ROM_REGION( 0x1000, "z80", 0 )
+ ROM_LOAD( "ix44_ver1.1.u57", 0x0000, 0x1000, CRC(5c11b89c) SHA1(4911332709a8dcda12e72bcdf7a0acd58d65cbfd) )
+ ROM_END
+};
+
+} // anonymous namespace
+
+DEFINE_DEVICE_TYPE_PRIVATE(TELETEX_800, device_rs232_port_interface, teletex_800_device, "teletex800", "Luxor Teletex 800")
diff --git a/src/devices/bus/rs232/teletex800.h b/src/devices/bus/rs232/teletex800.h
new file mode 100644
index 00000000000..970a309d31e
--- /dev/null
+++ b/src/devices/bus/rs232/teletex800.h
@@ -0,0 +1,13 @@
+// license:BSD-3-Clause
+// copyright-holders:Curt Coder
+#ifndef MAME_BUS_RS232_TELETEX800_H
+#define MAME_BUS_RS232_TELETEX800_H
+
+#pragma once
+
+#include "rs232.h"
+
+
+DECLARE_DEVICE_TYPE(TELETEX_800, device_rs232_port_interface)
+
+#endif // MAME_BUS_RS232_TELETEX800_H
diff --git a/src/devices/bus/rs232/terminal.cpp b/src/devices/bus/rs232/terminal.cpp
index 0955cd58a99..d9748f07003 100644
--- a/src/devices/bus/rs232/terminal.cpp
+++ b/src/devices/bus/rs232/terminal.cpp
@@ -3,13 +3,45 @@
#include "emu.h"
#include "terminal.h"
+#include "machine/terminal.h"
+
+
+namespace {
+
+class serial_terminal_device : public generic_terminal_device,
+ public device_buffered_serial_interface<16U>,
+ public device_rs232_port_interface
+{
+public:
+ serial_terminal_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
+
+ virtual void input_txd(int state) override { device_buffered_serial_interface::rx_w(state); }
+
+ void update_serial(int state);
+
+protected:
+ virtual ioport_constructor device_input_ports() const override ATTR_COLD;
+ virtual void device_reset() override ATTR_COLD;
+
+ virtual void tra_callback() override;
+ virtual void send_key(uint8_t code) override;
+
+private:
+ virtual void received_byte(uint8_t byte) override;
+
+ required_ioport m_rs232_txbaud;
+ required_ioport m_rs232_rxbaud;
+ required_ioport m_rs232_databits;
+ required_ioport m_rs232_parity;
+ required_ioport m_rs232_stopbits;
+};
+
serial_terminal_device::serial_terminal_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
: generic_terminal_device(mconfig, SERIAL_TERMINAL, tag, owner, clock, TERMINAL_WIDTH, TERMINAL_HEIGHT)
, device_buffered_serial_interface(mconfig, *this)
, device_rs232_port_interface(mconfig, *this)
, m_rs232_txbaud(*this, "RS232_TXBAUD")
, m_rs232_rxbaud(*this, "RS232_RXBAUD")
- , m_rs232_startbits(*this, "RS232_STARTBITS")
, m_rs232_databits(*this, "RS232_DATABITS")
, m_rs232_parity(*this, "RS232_PARITY")
, m_rs232_stopbits(*this, "RS232_STOPBITS")
@@ -21,7 +53,6 @@ static INPUT_PORTS_START(serial_terminal)
PORT_RS232_BAUD("RS232_TXBAUD", RS232_BAUD_9600, "TX Baud", serial_terminal_device, update_serial)
PORT_RS232_BAUD("RS232_RXBAUD", RS232_BAUD_9600, "RX Baud", serial_terminal_device, update_serial)
- PORT_RS232_STARTBITS("RS232_STARTBITS", RS232_STARTBITS_1, "Start Bits", serial_terminal_device, update_serial)
PORT_RS232_DATABITS("RS232_DATABITS", RS232_DATABITS_8, "Data Bits", serial_terminal_device, update_serial)
PORT_RS232_PARITY("RS232_PARITY", RS232_PARITY_NONE, "Parity", serial_terminal_device, update_serial)
PORT_RS232_STOPBITS("RS232_STOPBITS", RS232_STOPBITS_1, "Stop Bits", serial_terminal_device, update_serial)
@@ -32,11 +63,11 @@ 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();
- int const startbits = convert_startbits(m_rs232_startbits->read());
+ int const startbits = 1;
int const databits = convert_databits(m_rs232_databits->read());
parity_t const parity = convert_parity(m_rs232_parity->read());
stop_bits_t const stopbits = convert_stopbits(m_rs232_stopbits->read());
@@ -81,4 +112,7 @@ void serial_terminal_device::received_byte(uint8_t byte)
term_write(byte);
}
-DEFINE_DEVICE_TYPE(SERIAL_TERMINAL, serial_terminal_device, "serial_terminal", "Serial Terminal")
+} // anonymous namespace
+
+
+DEFINE_DEVICE_TYPE_PRIVATE(SERIAL_TERMINAL, device_rs232_port_interface, serial_terminal_device, "serial_terminal", "Serial Terminal")
diff --git a/src/devices/bus/rs232/terminal.h b/src/devices/bus/rs232/terminal.h
index 727b3122583..d1dd528bcf1 100644
--- a/src/devices/bus/rs232/terminal.h
+++ b/src/devices/bus/rs232/terminal.h
@@ -3,39 +3,11 @@
#ifndef MAME_BUS_RS232_TERMINAL_H
#define MAME_BUS_RS232_TERMINAL_H
-#include "rs232.h"
-#include "machine/terminal.h"
-
-
-class serial_terminal_device : public generic_terminal_device,
- public device_buffered_serial_interface<16U>,
- public device_rs232_port_interface
-{
-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); }
+#pragma once
- DECLARE_WRITE_LINE_MEMBER(update_serial);
-
-protected:
- virtual ioport_constructor device_input_ports() const override;
- virtual void device_reset() override;
-
- virtual void tra_callback() override;
- virtual void send_key(uint8_t code) override;
-
-private:
- virtual void received_byte(uint8_t byte) override;
+#include "rs232.h"
- required_ioport m_rs232_txbaud;
- required_ioport m_rs232_rxbaud;
- required_ioport m_rs232_startbits;
- required_ioport m_rs232_databits;
- required_ioport m_rs232_parity;
- required_ioport m_rs232_stopbits;
-};
-DECLARE_DEVICE_TYPE(SERIAL_TERMINAL, serial_terminal_device)
+DECLARE_DEVICE_TYPE(SERIAL_TERMINAL, device_rs232_port_interface)
#endif // MAME_BUS_RS232_TERMINAL_H
diff --git a/src/devices/bus/rs232/xvd701.cpp b/src/devices/bus/rs232/xvd701.cpp
index b2635d21c02..3b1c3843f96 100644
--- a/src/devices/bus/rs232/xvd701.cpp
+++ b/src/devices/bus/rs232/xvd701.cpp
@@ -1,12 +1,23 @@
// license:BSD-3-Clause
-// copyright-holders:smf
+// copyright-holders:smf, DragonMinded, windyfairy
+
#include "emu.h"
#include "xvd701.h"
+#define LOG_COMMAND (1U << 1)
+// #define VERBOSE (LOG_COMMAND)
+// #define LOG_OUTPUT_STREAM std::cout
+
+#include "logmacro.h"
+
+#define LOGCMD(...) LOGMASKED(LOG_COMMAND, __VA_ARGS__)
+
+
jvc_xvd701_device::jvc_xvd701_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
: device_t(mconfig, JVC_XVD701, tag, owner, clock),
device_serial_interface(mconfig, *this),
device_rs232_port_interface(mconfig, *this),
+ m_media_type(JVC_MEDIA_VCD), // TODO: This should be changed based on the type of disc inserted or else seeking won't work properly
m_response_index(0),
m_timer_response(nullptr)
{
@@ -47,7 +58,7 @@ void jvc_xvd701_device::device_start()
output_ri(0);
output_cts(0);
- m_timer_response = timer_alloc(TIMER_RESPONSE);
+ m_timer_response = timer_alloc(FUNC(jvc_xvd701_device::send_response), this);
}
void jvc_xvd701_device::device_reset()
@@ -55,19 +66,11 @@ void jvc_xvd701_device::device_reset()
memset(m_command, 0, sizeof(m_command));
m_response_index = sizeof(m_response);
-}
-void jvc_xvd701_device::device_timer(emu_timer &timer, device_timer_id id, int param, void *ptr)
-{
- switch (id)
- {
- case TIMER_RESPONSE:
- send_response();
- break;
-
- default:
- break;
- }
+ m_jlip_id = 33; // Twinkle default
+ m_is_powered = false;
+ m_chapter = 0;
+ m_playback_status = STATUS_STOP;
}
void jvc_xvd701_device::tra_callback()
@@ -82,15 +85,28 @@ void jvc_xvd701_device::tra_complete()
unsigned char jvc_xvd701_device::sum(unsigned char *buffer, int length)
{
- int sum = 0;
+ int sum = 0x80;
for (int i = 0; i < length; i++)
- sum += buffer[i];
+ sum -= buffer[i] & 0x7f;
return sum & 0x7f;
}
-void jvc_xvd701_device::send_response()
+void jvc_xvd701_device::create_packet(unsigned char status, const unsigned char response[6])
+{
+ m_response[0] = 0xfc;
+ m_response[1] = 0xff;
+ m_response[2] = m_jlip_id;
+ m_response[3] = status;
+ memcpy(&m_response[4], response, 6);
+ m_response[10] = sum(m_response, sizeof(m_response) - 1);
+
+ m_response_index = 0;
+ m_timer_response->adjust(attotime::from_msec(100));
+}
+
+TIMER_CALLBACK_MEMBER(jvc_xvd701_device::send_response)
{
if (m_response_index < sizeof(m_response) && is_transmit_register_empty())
{
@@ -99,6 +115,22 @@ void jvc_xvd701_device::send_response()
}
}
+bool jvc_xvd701_device::seek_chapter(int chapter)
+{
+ if (chapter <= 0)
+ {
+ // Chapters are from 1 and up
+ return false;
+ }
+
+ m_chapter = chapter;
+
+ if (m_playback_status != STATUS_PAUSE)
+ m_playback_status = STATUS_PLAYING;
+
+ return true;
+}
+
void jvc_xvd701_device::rcv_complete()
{
receive_register_extract();
@@ -110,39 +142,162 @@ void jvc_xvd701_device::rcv_complete()
if (m_command[0] == 0xff &&
m_command[1] == 0xff &&
- m_command[2] == 0x21 &&
- sum(m_command, sizeof(m_command)) == 0)
+ m_command[10] == sum(m_command, sizeof(m_command) - 1))
{
- // printf("xvd701");
-
- //for (int i = 0; i < sizeof(m_command); i++)
- // printf(" %02x", m_command[i]);
-
- //printf("\n");
-
- // FF FF 21 3E 40 70 00 00 00 00 73 DEVICE ON
- // FF FF 21 3E 40 60 00 00 00 00 03 DEVICE OFF
- // FF FF 21 0C 44 60 00 00 00 00 31 STOP
- // FF FF 21 0C 43 75 00 00 00 00 1D PLAY
- // FF FF 21 0C 43 6D 00 00 00 00 25 PAUSE
- // FF FF 21 0C 50 20 00 00 00 00 63 SEEK TO SPECIFIC CHAPTER
- // FF FF 21 0C 50 73 00 00 00 00 12 FF (SEEK TO NEXT CHAPTER)
- // FF FF 21 0C 50 61 00 00 00 00 24 PREV (SEEK TO PREVIOUS CHAPTER)
-
- m_response[0] = 0xff;
- m_response[1] = 0xfe;
- m_response[2] = 0x7f;
- m_response[3] = 0x7e;
- m_response[4] = 0x7d;
- m_response[5] = 0x7c;
- m_response[6] = 0x7b;
- m_response[7] = 0x7a;
- m_response[8] = 0x79;
- m_response[9] = 0x78;
- m_response[10] = 0x77;
- m_response_index = 0;
-
- m_timer_response->adjust(attotime::from_msec(100));
+ if (m_command[3] == 0x0c && m_command[4] == 0x43 && m_command[5] == 0x6d)
+ {
+ // FF FF 21 0C 43 6D 00 00 00 00 25 PAUSE
+ LOGCMD("xvd701: Playback PAUSE\n");
+ m_playback_status = STATUS_PAUSE;
+ create_packet(STATUS_OK, NO_RESPONSE);
+ }
+ else if (m_command[3] == 0x0c && m_command[4] == 0x43 && m_command[5] == 0x75)
+ {
+ // FF FF 21 0C 43 75 00 00 00 00 1D PLAY
+ LOGCMD("xvd701: Playback PLAY\n");
+
+ auto status = STATUS_OK;
+ if (m_playback_status == STATUS_STOP)
+ {
+ // Force video to load again if the video was stopped then started again
+ if (!seek_chapter(m_chapter))
+ status = STATUS_ERROR;
+ }
+
+ if (status == STATUS_OK)
+ m_playback_status = STATUS_PLAYING;
+
+ create_packet(status, NO_RESPONSE);
+ }
+ else if (m_command[3] == 0x0c && m_command[4] == 0x44 && m_command[5] == 0x60)
+ {
+ // FF FF 21 0C 44 60 00 00 00 00 31 STOP
+ LOGCMD("xvd701: Playback STOP\n");
+
+ m_playback_status = STATUS_STOP;
+ create_packet(STATUS_OK, NO_RESPONSE);
+ }
+ else if (m_command[3] == 0x0c && m_command[4] == 0x50 && m_command[5] == 0x20)
+ {
+ // FF FF 21 0C 50 20 00 00 00 00 63 SEEK TO SPECIFIC CHAPTER
+ auto chapter = ((m_command[6] % 10) * 100) + ((m_command[7] % 10) * 10) + (m_command[8] % 10);
+
+ if (m_media_type == JVC_MEDIA_VCD)
+ {
+ // VCD can only go to 99, so it sticks the data in the first two spots
+ chapter /= 10;
+ }
+
+ auto status = seek_chapter(chapter);
+ LOGCMD("xvd701: Seek chapter %d -> %d\n", chapter, status);
+ create_packet(status ? STATUS_OK : STATUS_ERROR, NO_RESPONSE);
+ }
+ else if (m_command[3] == 0x0c && m_command[4] == 0x50 && m_command[5] == 0x61)
+ {
+ // FF FF 21 0C 50 61 00 00 00 00 24 PREV (SEEK TO PREVIOUS CHAPTER)
+ auto chapter = m_chapter - 1;
+ if (m_playback_status != STATUS_PLAYING && chapter == 0)
+ chapter = 1;
+
+ auto status = seek_chapter(chapter);
+ LOGCMD("xvd701: Seek prev -> %d\n", status);
+ create_packet(status ? STATUS_OK : STATUS_ERROR, NO_RESPONSE);
+ }
+ else if (m_command[3] == 0x0c && m_command[4] == 0x50 && m_command[5] == 0x73)
+ {
+ // FF FF 21 0C 50 73 00 00 00 00 12 FF (SEEK TO NEXT CHAPTER)
+ auto status = seek_chapter(m_chapter + 1);
+ LOGCMD("xvd701: Seek FF -> %d\n", status);
+ create_packet(status ? STATUS_OK : STATUS_ERROR, NO_RESPONSE);
+ }
+
+ else if (m_command[3] == 0x3e && m_command[4] == 0x40 && m_command[5] == 0x60)
+ {
+ // FF FF 21 3E 40 60 00 00 00 00 03 DEVICE OFF
+ LOGCMD("xvd701: Device OFF\n");
+
+ auto status = m_is_powered ? STATUS_OK : STATUS_ERROR;
+ if (m_is_powered)
+ m_is_powered = false;
+
+ create_packet(status, NO_RESPONSE);
+
+ }
+ else if (m_command[3] == 0x3e && m_command[4] == 0x40 && m_command[5] == 0x70)
+ {
+ // FF FF 21 3E 40 70 00 00 00 00 73 DEVICE ON
+ LOGCMD("xvd701: Device ON\n");
+
+ auto status = !m_is_powered ? STATUS_OK : STATUS_ERROR;
+ if (!m_is_powered)
+ m_is_powered = true;
+
+ create_packet(status, NO_RESPONSE);
+ }
+ else if (m_command[3] == 0x3e && m_command[4] == 0x4e && m_command[5] == 0x20)
+ {
+ LOGCMD("xvd701: Device power status request\n");
+ const unsigned char response[6] = { m_is_powered, 0x20, 0, 0, 0, 0 };
+ create_packet(STATUS_OK, response);
+ }
+ else if (m_command[3] == 0x7c && m_command[4] == 0x41)
+ {
+ auto new_id = m_command[5];
+ LOGCMD("xvd701: Change JLIP ID to %02x\n", new_id);
+
+ if (new_id > 0 && new_id < 64)
+ {
+ m_jlip_id = new_id;
+ create_packet(STATUS_OK, NO_RESPONSE);
+ }
+ else
+ {
+ create_packet(STATUS_ERROR, NO_RESPONSE);
+ }
+ }
+ else if (m_command[3] == 0x7c && m_command[4] == 0x45 && m_command[5] == 0x00)
+ {
+ LOGCMD("xvd701: Machine code request\n");
+
+ const unsigned char response[6] = { 0x00, 0x01, 0x03, 0x00, 0x03, 0x01 };
+ create_packet(STATUS_OK, response);
+ }
+ else if (m_command[3] == 0x7c && m_command[4] == 0x48 && m_command[5] == 0x20)
+ {
+ LOGCMD("xvd701: Baud rate request\n");
+
+ // Hardcoded to 9600 baud
+ const unsigned char response[6] = { 0x20, 0x00, 0x00, 0x00, 0x00, 0x00 };
+ create_packet(STATUS_OK, response);
+ }
+ else if (m_command[3] == 0x7c && m_command[4] == 0x49 && m_command[5] == 0x00)
+ {
+ LOGCMD("xvd701: Device code request\n");
+
+ const unsigned char response[6] = { 0x03, 0x0C, 0x7F, 0x7F, 0x7F, 0x7F };
+ create_packet(STATUS_OK, response);
+ }
+ else if (m_command[3] == 0x7c && m_command[4] == 0x4c && m_command[5] == 0x00)
+ {
+ LOGCMD("xvd701: Device name first half request\n");
+
+ const unsigned char response[6] = { 'D', 'V', 'D', ' ', 'P', 'L' };
+ create_packet(STATUS_OK, response);
+ }
+ else if (m_command[3] == 0x7c && m_command[4] == 0x4d && m_command[5] == 0x00)
+ {
+ LOGCMD("xvd701: Device name last half request\n");
+
+ const unsigned char response[6] = { 'A', 'Y', 'E', 'R', 0x7F, 0x7F };
+ create_packet(STATUS_OK, response);
+ }
+ else if (m_command[3] == 0x7c && m_command[4] == 0x4e && m_command[5] == 0x20)
+ {
+ LOGCMD("xvd701: NOP request\n");
+
+ const unsigned char response[6] = { 0x01, 0x00, 0x00, 0x00, 0x00, 0x00 };
+ create_packet(STATUS_OK, response);
+ }
}
}
diff --git a/src/devices/bus/rs232/xvd701.h b/src/devices/bus/rs232/xvd701.h
index b018659210e..ba12a3b48a3 100644
--- a/src/devices/bus/rs232/xvd701.h
+++ b/src/devices/bus/rs232/xvd701.h
@@ -13,28 +13,57 @@ 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;
- virtual void device_reset() override;
- virtual void device_timer(emu_timer &timer, device_timer_id id, int param, void *ptr) override;
- virtual void device_add_mconfig(machine_config &config) override;
+ virtual ioport_constructor device_input_ports() const override ATTR_COLD;
+ 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;
virtual void tra_callback() override;
virtual void tra_complete() override;
virtual void rcv_complete() override;
private:
- static constexpr int TIMER_RESPONSE = 1;
+ enum jvc_xvd701_media_type : uint32_t
+ {
+ JVC_MEDIA_VCD = 0,
+ JVC_MEDIA_DVD = 1,
+ };
- void send_response();
+ enum jvc_xvd701_playback_status : uint32_t
+ {
+ STATUS_STOP = 0,
+ STATUS_PLAYING = 1,
+ STATUS_PAUSE = 2,
+ };
+
+ TIMER_CALLBACK_MEMBER(send_response);
unsigned char sum(unsigned char *buffer, int length);
+ void create_packet(unsigned char status, const unsigned char response[6]);
+
+ bool seek_chapter(int chapter);
+
+ jvc_xvd701_media_type m_media_type;
unsigned char m_command[11];
unsigned char m_response[11];
int m_response_index;
emu_timer *m_timer_response;
+
+ jvc_xvd701_playback_status m_playback_status;
+
+ unsigned char m_jlip_id;
+ bool m_is_powered;
+
+ int m_chapter;
+
+ enum : unsigned char {
+ STATUS_UNKNOWN_COMMAND = 1,
+ STATUS_OK = 3,
+ STATUS_ERROR = 5,
+ };
+ const unsigned char NO_RESPONSE[6] = { 0 };
};
DECLARE_DEVICE_TYPE(JVC_XVD701, jvc_xvd701_device)
diff --git a/src/devices/bus/rtpc/kbd.cpp b/src/devices/bus/rtpc/kbd.cpp
new file mode 100644
index 00000000000..f403114b8f7
--- /dev/null
+++ b/src/devices/bus/rtpc/kbd.cpp
@@ -0,0 +1,466 @@
+// license:BSD-3-Clause
+// copyright-holders:Patrick Mackinlay
+
+/*
+ * IBM RT PC keyboard.
+ *
+ * There are at least two distinct variants of the RT PC keyboard. One appears
+ * very similar to the IBM Model M 101-key keyboard, and uses a conventional
+ * matrix scan to detect keypresses. The variant emulated here has individually
+ * addressable capacitive switches, an i8749-compatible microcontroller and is
+ * labelled 556-712-01.
+ *
+ * The keyboard uses an AT or PS/2 compatible protocol, however it connects via
+ * a 6-pin AMP connector which also contains speaker control lines. The command
+ * set and scan codes are very similar to a PC keyboard (scan code "set 3").
+ *
+ * Sources:
+ * - IBM RT PC Hardware Technical Reference Volume I, 75X0232, March 1987
+ *
+ * Key switches are addressed using an 8 bit code as follows:
+ *
+ * ggrrrccc
+ *
+ * Where:
+ *
+ * gg is a group of keys (only groups 0, 1 and 3 are used)
+ * rrr is a row, from 0 to 5 (rows 6 and 7 are unused)
+ * ccc is a column within the group, from left to right
+ *
+ * This diagram approximates the keyboard layout, and shows the groups, rows
+ * and encoded key addresses.
+ *
+ * Row |------ group 0 ------| |------- group 1 -------| |---- group 3 ----|
+ * 0 00 02 03 04 05 06 07 40 41 43 44 45 46 47 c0 c1
+ * 1 08 09 0a 0b 0c 0d 0e 0f 48 49 4a 4b 4c 4e 4f c8 c9 ca cb cc cd
+ * 2 10 11 12 13 14 15 16 17 50 51 52 53 54 55 57 d0 d1 d2 d3 d4
+ * 3 18 19 1a 1b 1c 1d 1e 1f 58 59 5a 5b 5c 5d da db dc dd
+ * 4 20 21 22 23 24 25 26 27 60 61 62 63 64 e0 e2 e3 e4
+ * 5 28 2a 2e 6b 6d 6f e8 e9 ea ec ed
+ *
+ * Two key addresses (21 and 5c) are scanned and produce scan codes, but do not
+ * have corresponding keys on this keyboard; they are probably used in other
+ * language configurations.
+ */
+
+#include "emu.h"
+#include "kbd.h"
+
+#include "sound/spkrdev.h"
+#include "speaker.h"
+
+#define LOG_PORTS (1U << 1)
+
+//#define VERBOSE (LOG_GENERAL)
+#include "logmacro.h"
+
+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)
+ , device_rtpc_kbd_interface(mconfig, *this)
+ , m_mcu(*this, "mcu")
+ , m_matrix{ { *this, "g0.col.%d", 0U }, { *this, "g1.col.%d", 0U }, {*this, "g2.col.%d", 0U }, { *this, "g3.col.%d", 0U } }
+ , m_leds(*this, "kbd_led%x", 0U)
+{
+}
+
+void rtpc_kbd_device::device_add_mconfig(machine_config &config)
+{
+ // NEC D8749HD
+ I8749(config, m_mcu, 11_MHz_XTAL);
+
+ // inputs
+ m_mcu->p2_in_cb().set([this]() { return m_p2; });
+ m_mcu->t0_in_cb().set([this]() { return clock_signal(); });
+ m_mcu->t1_in_cb().set([this]() { return int(m_t1); });
+
+ // outputs
+ m_mcu->bus_out_cb().set(FUNC(rtpc_kbd_device::bus_w));
+ m_mcu->p1_out_cb().set(FUNC(rtpc_kbd_device::p1_w));
+ m_mcu->p2_out_cb().set(FUNC(rtpc_kbd_device::p2_w));
+
+ // the speaker is physically present inside the keyboard housing, but it
+ // is wired to and controlled directly by the host; it is not connected to
+ // the keyboard mcu at all
+ SPEAKER(config, "mono").front_left();
+ speaker_sound_device &speaker(SPEAKER_SOUND(config, "speaker"));
+ speaker.add_route(ALL_OUTPUTS, "mono", 0.50);
+}
+
+void rtpc_kbd_device::device_start()
+{
+ save_item(NAME(m_t1));
+ save_item(NAME(m_bus));
+ save_item(NAME(m_p1));
+ save_item(NAME(m_p2));
+
+ m_leds.resolve();
+
+ m_t1 = true;
+ m_bus = 0xff;
+ m_p1 = 0xff;
+ m_p2 = 0xff;
+}
+
+void rtpc_kbd_device::device_reset()
+{
+}
+
+void rtpc_kbd_device::bus_w(u8 data)
+{
+ LOGMASKED(LOG_PORTS, "bus_w 0x%02x (%s)\n", data, machine().describe_context());
+
+ m_bus = data;
+}
+
+void rtpc_kbd_device::p1_w(u8 data)
+{
+ LOGMASKED(LOG_PORTS, "p1_w 0x%02x (%s)\n", data, machine().describe_context());
+
+ // bit purpose
+ // 0-2 used by keyboard scan
+ // 3-5 unused
+ // 6 clock out
+ // 7 data out
+
+ if (VERBOSE & LOG_GENERAL)
+ {
+ if ((m_mcu->pc() == 0x675 || m_mcu->pc() == 0x65e))
+ {
+ auto const suppressor(machine().disable_side_effects());
+
+ address_space &mcu_ram(m_mcu->space(AS_DATA));
+ const u8 bit_count(mcu_ram.read_byte(0x18));
+ const u8 byte(mcu_ram.read_byte(0x58));
+
+ if (bit_count == 8)
+ LOG("tx byte 0x%02x\n", byte);
+ }
+ else if (m_mcu->pc() == 0x6cc)
+ {
+ auto const suppressor(machine().disable_side_effects());
+
+ // r0' == 2 -> receive parity & stop
+ address_space &mcu_ram(m_mcu->space(AS_DATA));
+ const u8 bit_count(mcu_ram.read_byte(0x18));
+ const u8 byte(mcu_ram.read_byte(0x59));
+
+ if (bit_count == 2)
+ LOG("rx byte 0x%02x\n", byte);
+ }
+ }
+
+ if (BIT(m_p1 ^ data, 7))
+ m_port->data_write_from_kb(BIT(data, 7));
+
+ if (BIT(m_p1 ^ data, 6))
+ m_port->clock_write_from_kb(BIT(data, 6));
+
+ // test key down
+ // TODO: not sure exactly how bits 0..2 gate or enable the sample
+ if (BIT(m_p1, 1) && BIT(m_p1, 2) && !BIT(data, 2))
+ m_t1 = BIT(m_matrix[m_bus >> 6][m_bus & 7]->read(), (m_bus >> 3) & 7);
+
+ m_p1 = data;
+}
+
+void rtpc_kbd_device::p2_w(u8 data)
+{
+ LOGMASKED(LOG_PORTS, "p2_w 0x%02x (%s)\n", data, machine().describe_context());
+
+ // bit purpose
+ // 0 num lock led
+ // 1 caps lock led
+ // 2 scroll lock led
+ // 3-6 unused
+ // 7 keyboard id (i/o)
+
+ m_leds[0] = BIT(data, 0);
+ m_leds[1] = BIT(data, 1);
+ m_leds[2] = BIT(data, 2);
+
+ m_p2 = data;
+}
+
+void rtpc_kbd_device::data_w(int state)
+{
+ m_mcu->set_input_line(MCS48_INPUT_IRQ, !state);
+}
+
+INPUT_PORTS_START(rtpc_kbd_device)
+ // pos 110, 1, 16, 30, 44, 58
+ PORT_START("g0.col.0")
+ PORT_BIT(0x01, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_ESC) PORT_CHAR(UCHAR_MAMEKEY(ESC))
+ PORT_BIT(0x02, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_TILDE) PORT_CHAR('`') PORT_CHAR('~')
+ PORT_BIT(0x04, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_TAB) PORT_CHAR(UCHAR_MAMEKEY(TAB))
+ PORT_BIT(0x08, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_CAPSLOCK) PORT_CHAR(UCHAR_MAMEKEY(CAPSLOCK))
+ PORT_BIT(0x10, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_LSHIFT) PORT_CHAR(UCHAR_MAMEKEY(LSHIFT))
+ PORT_BIT(0x20, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_LCONTROL) PORT_CHAR(UCHAR_MAMEKEY(LCONTROL))
+ PORT_BIT(0x40, IP_ACTIVE_LOW, IPT_UNUSED)
+ PORT_BIT(0x80, IP_ACTIVE_LOW, IPT_UNUSED)
+
+ // pos , 2, 17, 31, 45, 59
+ PORT_START("g0.col.1")
+ PORT_BIT(0x01, IP_ACTIVE_LOW, IPT_UNUSED)
+ PORT_BIT(0x02, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_1) PORT_CHAR('1') PORT_CHAR('!')
+ PORT_BIT(0x04, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_Q) PORT_CHAR('q') PORT_CHAR('Q')
+ PORT_BIT(0x08, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_A) PORT_CHAR('a') PORT_CHAR('A')
+ PORT_BIT(0x10, IP_ACTIVE_LOW, IPT_UNUSED) // position 45 scan code 0x13
+ PORT_BIT(0x20, IP_ACTIVE_LOW, IPT_UNUSED)
+ PORT_BIT(0x40, IP_ACTIVE_LOW, IPT_UNUSED)
+ PORT_BIT(0x80, IP_ACTIVE_LOW, IPT_UNUSED)
+
+ // pos 112, 3, 18, 32, 46, 60
+ PORT_START("g0.col.2")
+ PORT_BIT(0x01, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_F1) PORT_CHAR(UCHAR_MAMEKEY(F1))
+ PORT_BIT(0x02, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_2) PORT_CHAR('2') PORT_CHAR('@')
+ PORT_BIT(0x04, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_W) PORT_CHAR('w') PORT_CHAR('W')
+ PORT_BIT(0x08, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_S) PORT_CHAR('s') PORT_CHAR('S')
+ PORT_BIT(0x10, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_Z) PORT_CHAR('z') PORT_CHAR('Z')
+ PORT_BIT(0x20, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_LALT) PORT_CHAR(UCHAR_MAMEKEY(LALT))
+ PORT_BIT(0x40, IP_ACTIVE_LOW, IPT_UNUSED)
+ PORT_BIT(0x80, IP_ACTIVE_LOW, IPT_UNUSED)
+
+ // pos 113, 4, 19, 33, 47
+ PORT_START("g0.col.3")
+ PORT_BIT(0x01, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_F2) PORT_CHAR(UCHAR_MAMEKEY(F2))
+ 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_D) PORT_CHAR('d') PORT_CHAR('D')
+ PORT_BIT(0x10, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_X) PORT_CHAR('x') PORT_CHAR('X')
+ PORT_BIT(0x20, IP_ACTIVE_LOW, IPT_UNUSED)
+ PORT_BIT(0x40, IP_ACTIVE_LOW, IPT_UNUSED)
+ PORT_BIT(0x80, IP_ACTIVE_LOW, IPT_UNUSED)
+
+ // pos 114, 5, 20, 34, 48
+ PORT_START("g0.col.4")
+ PORT_BIT(0x01, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_F3) PORT_CHAR(UCHAR_MAMEKEY(F3))
+ PORT_BIT(0x02, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_4) PORT_CHAR('4') PORT_CHAR('$')
+ PORT_BIT(0x04, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_R) PORT_CHAR('r') PORT_CHAR('R')
+ PORT_BIT(0x08, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_F) PORT_CHAR('f') PORT_CHAR('F')
+ PORT_BIT(0x10, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_C) PORT_CHAR('c') PORT_CHAR('C')
+ PORT_BIT(0x20, IP_ACTIVE_LOW, IPT_UNUSED)
+ PORT_BIT(0x40, IP_ACTIVE_LOW, IPT_UNUSED)
+ PORT_BIT(0x80, IP_ACTIVE_LOW, IPT_UNUSED)
+
+ // pos 115, 6, 21, 35, 49
+ PORT_START("g0.col.5")
+ PORT_BIT(0x01, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_F4) PORT_CHAR(UCHAR_MAMEKEY(F4))
+ PORT_BIT(0x02, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_5) PORT_CHAR('5') PORT_CHAR('%')
+ PORT_BIT(0x04, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_T) PORT_CHAR('t') PORT_CHAR('T')
+ PORT_BIT(0x08, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_G) PORT_CHAR('g') PORT_CHAR('G')
+ PORT_BIT(0x10, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_V) PORT_CHAR('v') PORT_CHAR('V')
+ PORT_BIT(0x20, IP_ACTIVE_LOW, IPT_UNUSED)
+ PORT_BIT(0x40, IP_ACTIVE_LOW, IPT_UNUSED)
+ PORT_BIT(0x80, IP_ACTIVE_LOW, IPT_UNUSED)
+
+ // pos 116, 7, 22, 36, 50, 61
+ PORT_START("g0.col.6")
+ PORT_BIT(0x01, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_F5) PORT_CHAR(UCHAR_MAMEKEY(F5))
+ PORT_BIT(0x02, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_6) PORT_CHAR('6') PORT_CHAR('^')
+ PORT_BIT(0x04, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_Y) PORT_CHAR('y') PORT_CHAR('Y')
+ PORT_BIT(0x08, 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_B) PORT_CHAR('b') PORT_CHAR('B')
+ PORT_BIT(0x20, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_SPACE) PORT_CHAR(' ')
+ PORT_BIT(0x40, IP_ACTIVE_LOW, IPT_UNUSED)
+ PORT_BIT(0x80, IP_ACTIVE_LOW, IPT_UNUSED)
+
+ // pos 117, 8, 23, 37, 51
+ PORT_START("g0.col.7")
+ PORT_BIT(0x01, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_F6) PORT_CHAR(UCHAR_MAMEKEY(F6))
+ PORT_BIT(0x02, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_7) PORT_CHAR('7') PORT_CHAR('&')
+ PORT_BIT(0x04, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_U) PORT_CHAR('u') PORT_CHAR('U')
+ PORT_BIT(0x08, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_J) PORT_CHAR('j') PORT_CHAR('J')
+ PORT_BIT(0x10, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_N) PORT_CHAR('n') PORT_CHAR('N')
+ PORT_BIT(0x20, IP_ACTIVE_LOW, IPT_UNUSED)
+ PORT_BIT(0x40, IP_ACTIVE_LOW, IPT_UNUSED)
+ PORT_BIT(0x80, IP_ACTIVE_LOW, IPT_UNUSED)
+
+ // pos 118, 9, 24, 38, 52
+ PORT_START("g1.col.0")
+ PORT_BIT(0x01, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_F7) PORT_CHAR(UCHAR_MAMEKEY(F7))
+ PORT_BIT(0x02, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_8) PORT_CHAR('8') PORT_CHAR('*')
+ PORT_BIT(0x04, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_I) PORT_CHAR('i') PORT_CHAR('I')
+ PORT_BIT(0x08, 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_M) PORT_CHAR('m') PORT_CHAR('M')
+ PORT_BIT(0x20, IP_ACTIVE_LOW, IPT_UNUSED)
+ PORT_BIT(0x40, IP_ACTIVE_LOW, IPT_UNUSED)
+ PORT_BIT(0x80, IP_ACTIVE_LOW, IPT_UNUSED)
+
+ // pos 119, 10, 25, 39, 53
+ PORT_START("g1.col.1")
+ PORT_BIT(0x01, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_F8) PORT_CHAR(UCHAR_MAMEKEY(F8))
+ PORT_BIT(0x02, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_9) PORT_CHAR('9') PORT_CHAR('(')
+ 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_L) PORT_CHAR('l') PORT_CHAR('L')
+ PORT_BIT(0x10, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_COMMA) PORT_CHAR(',') PORT_CHAR('<')
+ PORT_BIT(0x20, IP_ACTIVE_LOW, IPT_UNUSED)
+ PORT_BIT(0x40, IP_ACTIVE_LOW, IPT_UNUSED)
+ PORT_BIT(0x80, IP_ACTIVE_LOW, IPT_UNUSED)
+
+ // pos , 11, 26, 40, 54
+ PORT_START("g1.col.2")
+ PORT_BIT(0x01, IP_ACTIVE_LOW, IPT_UNUSED)
+ PORT_BIT(0x02, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_0) PORT_CHAR('0') PORT_CHAR(')')
+ PORT_BIT(0x04, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_P) PORT_CHAR('p') PORT_CHAR('P')
+ PORT_BIT(0x08, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_COLON) PORT_CHAR(';') PORT_CHAR(':')
+ PORT_BIT(0x10, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_STOP) PORT_CHAR('.') PORT_CHAR('>')
+ PORT_BIT(0x20, IP_ACTIVE_LOW, IPT_UNUSED)
+ PORT_BIT(0x40, IP_ACTIVE_LOW, IPT_UNUSED)
+ PORT_BIT(0x80, IP_ACTIVE_LOW, IPT_UNUSED)
+
+ // pos 120, 12, 27, 41, 55, 62
+ PORT_START("g1.col.3")
+ PORT_BIT(0x01, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_F9) PORT_CHAR(UCHAR_MAMEKEY(F9))
+ 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('[') PORT_CHAR('{')
+ PORT_BIT(0x08, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_QUOTE) PORT_CHAR('\'') PORT_CHAR('"')
+ PORT_BIT(0x10, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_SLASH) PORT_CHAR('/') PORT_CHAR('?')
+ PORT_BIT(0x20, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_RALT) PORT_CHAR(UCHAR_MAMEKEY(RALT))
+ PORT_BIT(0x40, IP_ACTIVE_LOW, IPT_UNUSED)
+ PORT_BIT(0x80, IP_ACTIVE_LOW, IPT_UNUSED)
+
+ // pos 121, 13, 28, 42, 57
+ PORT_START("g1.col.4")
+ PORT_BIT(0x01, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_F10) PORT_CHAR(UCHAR_MAMEKEY(F10))
+ PORT_BIT(0x02, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_EQUALS) PORT_CHAR('=') PORT_CHAR('+')
+ PORT_BIT(0x04, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_CLOSEBRACE) PORT_CHAR(']') PORT_CHAR('}')
+ PORT_BIT(0x08, IP_ACTIVE_LOW, IPT_UNUSED) // position 42 scan code 0x53
+ PORT_BIT(0x10, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_RSHIFT) PORT_CHAR(UCHAR_MAMEKEY(RSHIFT))
+ PORT_BIT(0x20, IP_ACTIVE_LOW, IPT_UNUSED)
+ PORT_BIT(0x40, IP_ACTIVE_LOW, IPT_UNUSED)
+ PORT_BIT(0x80, IP_ACTIVE_LOW, IPT_UNUSED)
+
+ // pos 122, , 29, 43, , 64
+ PORT_START("g1.col.5")
+ PORT_BIT(0x01, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_F11) PORT_CHAR(UCHAR_MAMEKEY(F11))
+ PORT_BIT(0x02, IP_ACTIVE_LOW, IPT_UNUSED)
+ PORT_BIT(0x04, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_BACKSLASH) PORT_CHAR('\\') PORT_CHAR('|')
+ PORT_BIT(0x08, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_ENTER) PORT_CHAR(13)
+ PORT_BIT(0x10, IP_ACTIVE_LOW, IPT_UNUSED)
+ PORT_BIT(0x20, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_RCONTROL) PORT_CHAR(UCHAR_MAMEKEY(RCONTROL)) PORT_NAME("Action")
+ PORT_BIT(0x40, IP_ACTIVE_LOW, IPT_UNUSED)
+ PORT_BIT(0x80, IP_ACTIVE_LOW, IPT_UNUSED)
+
+ // pos 123, 15
+ PORT_START("g1.col.6")
+ PORT_BIT(0x01, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_F12) PORT_CHAR(UCHAR_MAMEKEY(F12))
+ PORT_BIT(0x02, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_BACKSPACE) PORT_CHAR(8)
+ PORT_BIT(0x04, IP_ACTIVE_LOW, IPT_UNUSED)
+ PORT_BIT(0x08, IP_ACTIVE_LOW, IPT_UNUSED)
+ PORT_BIT(0x10, IP_ACTIVE_LOW, IPT_UNUSED)
+ PORT_BIT(0x20, IP_ACTIVE_LOW, IPT_UNUSED)
+ PORT_BIT(0x40, IP_ACTIVE_LOW, IPT_UNUSED)
+ PORT_BIT(0x80, IP_ACTIVE_LOW, IPT_UNUSED)
+
+ // pos 124, 75, 76, , , 79
+ PORT_START("g1.col.7")
+ PORT_BIT(0x01, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_PRTSCR) PORT_CHAR(UCHAR_MAMEKEY(PRTSCR))
+ PORT_BIT(0x02, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_INSERT) PORT_CHAR(UCHAR_MAMEKEY(INSERT))
+ PORT_BIT(0x04, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_DEL) PORT_CHAR(UCHAR_MAMEKEY(DEL))
+ PORT_BIT(0x08, IP_ACTIVE_LOW, IPT_UNUSED)
+ PORT_BIT(0x10, IP_ACTIVE_LOW, IPT_UNUSED)
+ PORT_BIT(0x20, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_LEFT) PORT_CHAR(UCHAR_MAMEKEY(LEFT))
+ PORT_BIT(0x40, IP_ACTIVE_LOW, IPT_UNUSED)
+ PORT_BIT(0x80, IP_ACTIVE_LOW, IPT_UNUSED)
+
+ // group 2 is unused
+ PORT_START("g2.col.0")
+ PORT_BIT(0xff, IP_ACTIVE_LOW, IPT_UNUSED)
+ PORT_START("g2.col.1")
+ PORT_BIT(0xff, IP_ACTIVE_LOW, IPT_UNUSED)
+ PORT_START("g2.col.2")
+ PORT_BIT(0xff, IP_ACTIVE_LOW, IPT_UNUSED)
+ PORT_START("g2.col.3")
+ PORT_BIT(0xff, IP_ACTIVE_LOW, IPT_UNUSED)
+ PORT_START("g2.col.4")
+ PORT_BIT(0xff, IP_ACTIVE_LOW, IPT_UNUSED)
+ PORT_START("g2.col.5")
+ PORT_BIT(0xff, IP_ACTIVE_LOW, IPT_UNUSED)
+ PORT_START("g2.col.6")
+ PORT_BIT(0xff, IP_ACTIVE_LOW, IPT_UNUSED)
+ PORT_START("g2.col.7")
+ PORT_BIT(0xff, IP_ACTIVE_LOW, IPT_UNUSED)
+
+ PORT_START("g3.col.0")
+ PORT_BIT(0x01, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_SCRLOCK) PORT_CHAR(UCHAR_MAMEKEY(SCRLOCK))
+ PORT_BIT(0x02, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_HOME) PORT_CHAR(UCHAR_MAMEKEY(HOME))
+ PORT_BIT(0x04, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_END) PORT_CHAR(UCHAR_MAMEKEY(END))
+ PORT_BIT(0x08, IP_ACTIVE_LOW, IPT_UNUSED)
+ PORT_BIT(0x10, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_UP) PORT_CHAR(UCHAR_MAMEKEY(UP))
+ PORT_BIT(0x20, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_DOWN) PORT_CHAR(UCHAR_MAMEKEY(DOWN))
+ PORT_BIT(0x40, IP_ACTIVE_LOW, IPT_UNUSED)
+ PORT_BIT(0x80, IP_ACTIVE_LOW, IPT_UNUSED)
+
+ PORT_START("g3.col.1")
+ PORT_BIT(0x01, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_PAUSE) PORT_CHAR(UCHAR_MAMEKEY(PAUSE))
+ PORT_BIT(0x02, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_PGUP) PORT_CHAR(UCHAR_MAMEKEY(PGUP))
+ PORT_BIT(0x04, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_PGDN) PORT_CHAR(UCHAR_MAMEKEY(PGDN))
+ PORT_BIT(0x08, IP_ACTIVE_LOW, IPT_UNUSED)
+ PORT_BIT(0x10, IP_ACTIVE_LOW, IPT_UNUSED)
+ PORT_BIT(0x20, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_RIGHT) PORT_CHAR(UCHAR_MAMEKEY(RIGHT))
+ PORT_BIT(0x40, IP_ACTIVE_LOW, IPT_UNUSED)
+ PORT_BIT(0x80, IP_ACTIVE_LOW, IPT_UNUSED)
+
+ PORT_START("g3.col.2")
+ PORT_BIT(0x01, IP_ACTIVE_LOW, IPT_UNUSED)
+ PORT_BIT(0x02, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_NUMLOCK) PORT_CHAR(UCHAR_MAMEKEY(NUMLOCK))
+ PORT_BIT(0x04, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_7_PAD) PORT_CHAR(UCHAR_MAMEKEY(7_PAD))
+ PORT_BIT(0x08, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_4_PAD) PORT_CHAR(UCHAR_MAMEKEY(4_PAD))
+ PORT_BIT(0x10, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_1_PAD) PORT_CHAR(UCHAR_MAMEKEY(1_PAD))
+ PORT_BIT(0x20, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_0_PAD) PORT_CHAR(UCHAR_MAMEKEY(0_PAD))
+ PORT_BIT(0x40, IP_ACTIVE_LOW, IPT_UNUSED)
+ PORT_BIT(0x80, IP_ACTIVE_LOW, IPT_UNUSED)
+
+ PORT_START("g3.col.3")
+ PORT_BIT(0x01, IP_ACTIVE_LOW, IPT_UNUSED)
+ PORT_BIT(0x02, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_SLASH_PAD) PORT_CHAR(UCHAR_MAMEKEY(SLASH_PAD))
+ PORT_BIT(0x04, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_8_PAD) PORT_CHAR(UCHAR_MAMEKEY(8_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_CODE(KEYCODE_2_PAD) PORT_CHAR(UCHAR_MAMEKEY(2_PAD))
+ PORT_BIT(0x20, IP_ACTIVE_LOW, IPT_UNUSED)
+ PORT_BIT(0x40, IP_ACTIVE_LOW, IPT_UNUSED)
+ PORT_BIT(0x80, IP_ACTIVE_LOW, IPT_UNUSED)
+
+ PORT_START("g3.col.4")
+ PORT_BIT(0x01, IP_ACTIVE_LOW, IPT_UNUSED)
+ PORT_BIT(0x02, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_ASTERISK) PORT_CHAR(UCHAR_MAMEKEY(ASTERISK))
+ PORT_BIT(0x04, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_9_PAD) PORT_CHAR(UCHAR_MAMEKEY(9_PAD))
+ PORT_BIT(0x08, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_6_PAD) PORT_CHAR(UCHAR_MAMEKEY(6_PAD))
+ PORT_BIT(0x10, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_3_PAD) PORT_CHAR(UCHAR_MAMEKEY(3_PAD))
+ PORT_BIT(0x20, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_DEL_PAD) PORT_CHAR(UCHAR_MAMEKEY(DEL_PAD))
+ PORT_BIT(0x40, IP_ACTIVE_LOW, IPT_UNUSED)
+ PORT_BIT(0x80, IP_ACTIVE_LOW, IPT_UNUSED)
+
+ PORT_START("g3.col.5")
+ PORT_BIT(0x01, IP_ACTIVE_LOW, IPT_UNUSED)
+ PORT_BIT(0x02, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_MINUS_PAD) PORT_CHAR(UCHAR_MAMEKEY(MINUS_PAD))
+ PORT_BIT(0x04, IP_ACTIVE_LOW, IPT_UNUSED)
+ PORT_BIT(0x08, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_PLUS_PAD) PORT_CHAR(UCHAR_MAMEKEY(PLUS_PAD))
+ PORT_BIT(0x10, IP_ACTIVE_LOW, IPT_UNUSED)
+ PORT_BIT(0x20, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_ENTER_PAD) PORT_CHAR(UCHAR_MAMEKEY(ENTER_PAD))
+ PORT_BIT(0x40, IP_ACTIVE_LOW, IPT_UNUSED)
+ PORT_BIT(0x80, IP_ACTIVE_LOW, IPT_UNUSED)
+
+ // group 3 columns 6 and 7 unused
+ PORT_START("g3.col.6")
+ PORT_BIT(0xff, IP_ACTIVE_LOW, IPT_UNUSED)
+ PORT_START("g3.col.7")
+ PORT_BIT(0xff, IP_ACTIVE_LOW, IPT_UNUSED)
+INPUT_PORTS_END
+
+ioport_constructor rtpc_kbd_device::device_input_ports() const
+{
+ return INPUT_PORTS_NAME(rtpc_kbd_device);
+}
+
+ROM_START(rtpc_kbd_device)
+ ROM_REGION(0x800, "mcu", 0)
+ ROM_LOAD("71201_8749.bin", 0x000, 0x800, CRC(4c44e488) SHA1(d7305e978e9c047a34d2c26176ce7ac0467f1219))
+ROM_END
+
+const tiny_rom_entry *rtpc_kbd_device::device_rom_region() const
+{
+ return ROM_NAME(rtpc_kbd_device);
+}
diff --git a/src/devices/bus/rtpc/kbd.h b/src/devices/bus/rtpc/kbd.h
new file mode 100644
index 00000000000..be349c5f342
--- /dev/null
+++ b/src/devices/bus/rtpc/kbd.h
@@ -0,0 +1,47 @@
+// license:BSD-3-Clause
+// copyright-holders:Patrick Mackinlay
+
+#ifndef MAME_BUS_RTPC_KBD_H
+#define MAME_BUS_RTPC_KBD_H
+
+#pragma once
+
+#include "kbd_con.h"
+#include "cpu/mcs48/mcs48.h"
+
+class rtpc_kbd_device
+ : public device_t
+ , public device_rtpc_kbd_interface
+{
+public:
+ rtpc_kbd_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 ATTR_COLD;
+ virtual void device_add_mconfig(machine_config &config) override ATTR_COLD;
+ virtual ioport_constructor device_input_ports() const override ATTR_COLD;
+ virtual void device_start() override ATTR_COLD;
+ virtual void device_reset() override ATTR_COLD;
+
+ // device_rtpc_kbd_interface overrides
+ virtual void data_w(int state) override;
+
+private:
+ void bus_w(u8 data);
+ void p1_w(u8 data);
+ void p2_w(u8 data);
+
+ required_device<i8749_device> m_mcu;
+ required_ioport_array<8> m_matrix[4];
+ output_finder<3> m_leds;
+
+ bool m_t1;
+ u8 m_bus;
+ u8 m_p1;
+ u8 m_p2;
+};
+
+DECLARE_DEVICE_TYPE(RTPC_KBD, rtpc_kbd_device)
+
+#endif // MAME_BUS_RTPC_KBD_H
diff --git a/src/devices/bus/rtpc/kbd_con.cpp b/src/devices/bus/rtpc/kbd_con.cpp
new file mode 100644
index 00000000000..3e689485594
--- /dev/null
+++ b/src/devices/bus/rtpc/kbd_con.cpp
@@ -0,0 +1,121 @@
+// license:BSD-3-Clause
+// copyright-holders:Patrick Mackinlay
+
+/*
+ * While not physically compatible, the RT PC keyboard protocol is logically
+ * and electrically identical to the PC/AT. This implementation is copied from
+ * pc_kbdc and implements the same bi-directional clock and data lines.
+ */
+
+#include "emu.h"
+#include "kbd_con.h"
+
+//#define VERBOSE (LOG_GENERAL)
+#include "logmacro.h"
+
+DEFINE_DEVICE_TYPE(RTPC_KBD_CON, rtpc_kbd_con_device, "rtpc_kbd_con", "RT PC keyboard connector")
+
+rtpc_kbd_con_device::rtpc_kbd_con_device(machine_config const &mconfig, char const *tag, device_t *owner, u32 clock)
+ : device_t(mconfig, RTPC_KBD_CON, tag, owner, clock)
+ , device_single_card_slot_interface<device_rtpc_kbd_interface>(mconfig, *this)
+ , m_out_clock_cb(*this)
+ , m_out_data_cb(*this)
+ , m_clock_state(-1)
+ , m_data_state(-1)
+ , m_mb_clock_state(0)
+ , m_mb_data_state(0)
+ , m_kb_clock_state(1)
+ , m_kb_data_state(1)
+ , m_keyboard(nullptr)
+{
+}
+
+void rtpc_kbd_con_device::device_config_complete()
+{
+ m_keyboard = get_card_device();
+}
+
+void rtpc_kbd_con_device::device_start()
+{
+ save_item(NAME(m_clock_state));
+ save_item(NAME(m_data_state));
+
+ save_item(NAME(m_mb_clock_state));
+ save_item(NAME(m_mb_data_state));
+ save_item(NAME(m_kb_clock_state));
+ save_item(NAME(m_kb_data_state));
+
+ m_clock_state = -1;
+ m_data_state = -1;
+
+ m_mb_clock_state = 1;
+ m_mb_data_state = 1;
+ m_kb_clock_state = 1;
+ m_kb_data_state = 1;
+}
+
+void rtpc_kbd_con_device::update_clock_state(bool fromkb)
+{
+ int new_clock_state = m_mb_clock_state & m_kb_clock_state;
+
+ if (new_clock_state != m_clock_state)
+ {
+ m_clock_state = new_clock_state;
+ LOG("%s clock: %d\n", fromkb? "<-" : "->", m_clock_state);
+
+ // send state to host
+ m_out_clock_cb(m_clock_state);
+
+ // send state to keyboard
+ if (m_keyboard)
+ m_keyboard->clock_w(m_clock_state);
+ }
+}
+
+void rtpc_kbd_con_device::update_data_state(bool fromkb)
+{
+ int new_data_state = m_mb_data_state & m_kb_data_state;
+
+ if (new_data_state != m_data_state)
+ {
+ m_data_state = new_data_state;
+ LOG("%s data: %d\n", fromkb? "<-" : "->", m_data_state);
+
+ // send state to host
+ m_out_data_cb(m_data_state);
+
+ // send state to keyboard
+ if (m_keyboard)
+ m_keyboard->data_w(m_data_state);
+ }
+}
+
+void rtpc_kbd_con_device::clock_write_from_mb(int state)
+{
+ m_mb_clock_state = state;
+ update_clock_state(false);
+}
+
+void rtpc_kbd_con_device::data_write_from_mb(int state)
+{
+ m_mb_data_state = state;
+ update_data_state(false);
+}
+
+void rtpc_kbd_con_device::clock_write_from_kb(int state)
+{
+ m_kb_clock_state = state;
+ update_clock_state(true);
+}
+
+void rtpc_kbd_con_device::data_write_from_kb(int state)
+{
+ m_kb_data_state = state;
+ update_data_state(true);
+}
+
+device_rtpc_kbd_interface::device_rtpc_kbd_interface(machine_config const &mconfig, device_t &device)
+ : device_interface(device, "rtpc_kbd_if")
+ , m_port(dynamic_cast<rtpc_kbd_con_device *>(device.owner()))
+{
+}
diff --git a/src/devices/bus/rtpc/kbd_con.h b/src/devices/bus/rtpc/kbd_con.h
new file mode 100644
index 00000000000..da3e0798005
--- /dev/null
+++ b/src/devices/bus/rtpc/kbd_con.h
@@ -0,0 +1,79 @@
+// license:BSD-3-Clause
+// copyright-holders:Patrick Mackinlay
+
+#ifndef MAME_BUS_RTPC_KBD_CON_H
+#define MAME_BUS_RTPC_KBD_CON_H
+
+#pragma once
+
+class device_rtpc_kbd_interface;
+
+class rtpc_kbd_con_device
+ : public device_t
+ , public device_single_card_slot_interface<device_rtpc_kbd_interface>
+{
+public:
+ template <typename T>
+ rtpc_kbd_con_device(machine_config const &mconfig, char const *tag, device_t *owner, T &&opts, char const *dflt)
+ : rtpc_kbd_con_device(mconfig, tag, owner, 0U)
+ {
+ option_reset();
+ opts(*this);
+ set_default_option(dflt);
+ set_fixed(false);
+ }
+ rtpc_kbd_con_device(machine_config const &mconfig, char const *tag, device_t *owner, u32 clock = 0U);
+
+ auto out_clock_cb() { return m_out_clock_cb.bind(); }
+ auto out_data_cb() { return m_out_data_cb.bind(); }
+
+ int clock_signal() { return m_clock_state; }
+ int data_signal() { return m_data_state; }
+
+ 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:
+ virtual void device_config_complete() override;
+ virtual void device_start() override ATTR_COLD;
+
+ void update_clock_state(bool fromkb);
+ void update_data_state(bool fromkb);
+
+ devcb_write_line m_out_clock_cb;
+ devcb_write_line m_out_data_cb;
+
+ int8_t m_clock_state;
+ int8_t m_data_state;
+
+ uint8_t m_mb_clock_state;
+ uint8_t m_mb_data_state;
+ uint8_t m_kb_clock_state;
+ uint8_t m_kb_data_state;
+
+ device_rtpc_kbd_interface *m_keyboard;
+};
+
+DECLARE_DEVICE_TYPE(RTPC_KBD_CON, rtpc_kbd_con_device)
+
+class device_rtpc_kbd_interface : public device_interface
+{
+ friend class rtpc_kbd_port_device;
+public:
+ virtual ~device_rtpc_kbd_interface() {}
+
+ virtual void clock_w(int state) {}
+ virtual void data_w(int state) {}
+
+protected:
+ device_rtpc_kbd_interface(machine_config const &mconfig, device_t &device);
+
+ int clock_signal() const { return m_port->clock_signal(); }
+ int data_signal() const { return m_port->data_signal(); }
+
+ rtpc_kbd_con_device *m_port;
+};
+
+#endif // MAME_BUS_RTPC_KBD_CON_H
diff --git a/src/devices/bus/s100/am310.cpp b/src/devices/bus/s100/am310.cpp
index ec2ccf5a608..07edfe8b0df 100644
--- a/src/devices/bus/s100/am310.cpp
+++ b/src/devices/bus/s100/am310.cpp
@@ -23,7 +23,7 @@
#include "machine/am9517a.h"
#include "machine/gen_latch.h"
#include "machine/input_merger.h"
-#include "machine/mc2661.h"
+#include "machine/scn_pci.h"
class s100_am310_device : public device_t, public device_s100_card_interface
{
@@ -33,11 +33,11 @@ public:
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;
- virtual const tiny_rom_entry *device_rom_region() const override;
+ virtual void device_start() override ATTR_COLD;
+ virtual void device_reset() override ATTR_COLD;
+ virtual ioport_constructor device_input_ports() const override ATTR_COLD;
+ virtual void device_add_mconfig(machine_config &config) override ATTR_COLD;
+ virtual const tiny_rom_entry *device_rom_region() const override ATTR_COLD;
// device_s100_card_interface overrides
virtual u8 s100_sinp_r(offs_t offset) override;
@@ -53,7 +53,7 @@ private:
void int_w(offs_t offset, u8 data);
// address map
- void z80_map(address_map &map);
+ void z80_map(address_map &map) ATTR_COLD;
// object finders
required_device<z80_device> m_z80;
@@ -62,7 +62,7 @@ private:
required_device<generic_latch_8_device> m_dilatch;
required_device<generic_latch_8_device> m_statlatch;
required_device<am9517a_device> m_dma;
- required_device_array<mc2661_device, 4> m_pci;
+ required_device_array<scn_pci_device, 4> m_pci;
required_ioport m_adr;
required_ioport m_intr;
};
@@ -187,14 +187,14 @@ void s100_am310_device::z80_map(address_map &map)
map(0x8000, 0x800f).mirror(0x3ff0).rw(m_dma, FUNC(am9517a_device::read), FUNC(am9517a_device::write));
map(0xc000, 0xc000).mirror(0x3fc7).w(m_statlatch, FUNC(generic_latch_8_device::write));
map(0xc008, 0xc008).mirror(0x3fc7).r(m_cmdlatch, FUNC(generic_latch_8_device::read));
- map(0xc010, 0xc013).mirror(0x3fc0).r(m_pci[0], FUNC(mc2661_device::read));
- map(0xc014, 0xc017).mirror(0x3fc0).w(m_pci[0], FUNC(mc2661_device::write));
- map(0xc018, 0xc01b).mirror(0x3fc0).r(m_pci[1], FUNC(mc2661_device::read));
- map(0xc01c, 0xc01f).mirror(0x3fc0).w(m_pci[1], FUNC(mc2661_device::write));
- map(0xc020, 0xc023).mirror(0x3fc0).r(m_pci[2], FUNC(mc2661_device::read));
- map(0xc024, 0xc027).mirror(0x3fc0).w(m_pci[2], FUNC(mc2661_device::write));
- map(0xc028, 0xc02b).mirror(0x3fc0).r(m_pci[3], FUNC(mc2661_device::read));
- map(0xc02c, 0xc02f).mirror(0x3fc0).w(m_pci[3], FUNC(mc2661_device::write));
+ map(0xc010, 0xc013).mirror(0x3fc0).r(m_pci[0], FUNC(scn_pci_device::read));
+ map(0xc014, 0xc017).mirror(0x3fc0).w(m_pci[0], FUNC(scn_pci_device::write));
+ map(0xc018, 0xc01b).mirror(0x3fc0).r(m_pci[1], FUNC(scn_pci_device::read));
+ map(0xc01c, 0xc01f).mirror(0x3fc0).w(m_pci[1], FUNC(scn_pci_device::write));
+ map(0xc020, 0xc023).mirror(0x3fc0).r(m_pci[2], FUNC(scn_pci_device::read));
+ map(0xc024, 0xc027).mirror(0x3fc0).w(m_pci[2], FUNC(scn_pci_device::write));
+ map(0xc028, 0xc02b).mirror(0x3fc0).r(m_pci[3], FUNC(scn_pci_device::read));
+ map(0xc02c, 0xc02f).mirror(0x3fc0).w(m_pci[3], FUNC(scn_pci_device::write));
map(0xc030, 0xc030).mirror(0x3fc7).select(8).rw(FUNC(s100_am310_device::int_r), FUNC(s100_am310_device::int_w));
}
@@ -309,7 +309,7 @@ void s100_am310_device::device_add_mconfig(machine_config &config)
GENERIC_LATCH_8(config, m_dilatch); // U40
GENERIC_LATCH_8(config, m_statlatch); // U41
- MC2661(config, m_pci[0], 5.0688_MHz_XTAL); // U30
+ SCN2651(config, m_pci[0], 5.0688_MHz_XTAL); // U30
m_pci[0]->rts_handler().set("ch1", FUNC(rs232_port_device::write_rts));
m_pci[0]->dtr_handler().set("ch1", FUNC(rs232_port_device::write_dtr));
m_pci[0]->txd_handler().set("ch1", FUNC(rs232_port_device::write_txd));
@@ -317,7 +317,7 @@ void s100_am310_device::device_add_mconfig(machine_config &config)
m_pci[0]->txrdy_handler().set("irq", FUNC(input_merger_device::in_w<1>));
m_pci[0]->rxrdy_handler().set("irq", FUNC(input_merger_device::in_w<2>));
- MC2661(config, m_pci[1], 5.0688_MHz_XTAL); // U28
+ SCN2651(config, m_pci[1], 5.0688_MHz_XTAL); // U28
m_pci[1]->rts_handler().set("ch2", FUNC(rs232_port_device::write_rts));
m_pci[1]->dtr_handler().set("ch2", FUNC(rs232_port_device::write_dtr));
m_pci[1]->txd_handler().set("ch2", FUNC(rs232_port_device::write_txd));
@@ -325,7 +325,7 @@ void s100_am310_device::device_add_mconfig(machine_config &config)
m_pci[1]->txrdy_handler().set("irq", FUNC(input_merger_device::in_w<4>));
m_pci[1]->rxrdy_handler().set("irq", FUNC(input_merger_device::in_w<5>));
- MC2661(config, m_pci[2], 5.0688_MHz_XTAL); // U27
+ SCN2651(config, m_pci[2], 5.0688_MHz_XTAL); // U27
m_pci[2]->rts_handler().set("ch3", FUNC(rs232_port_device::write_rts));
m_pci[2]->dtr_handler().set("ch3", FUNC(rs232_port_device::write_dtr));
m_pci[2]->txd_handler().set("ch3", FUNC(rs232_port_device::write_txd));
@@ -333,7 +333,7 @@ void s100_am310_device::device_add_mconfig(machine_config &config)
m_pci[2]->txrdy_handler().set("irq", FUNC(input_merger_device::in_w<7>));
m_pci[2]->rxrdy_handler().set("irq", FUNC(input_merger_device::in_w<8>));
- MC2661(config, m_pci[3], 5.0688_MHz_XTAL); // U29
+ SCN2651(config, m_pci[3], 5.0688_MHz_XTAL); // U29
m_pci[3]->rts_handler().set("ch4", FUNC(rs232_port_device::write_rts));
m_pci[3]->dtr_handler().set("ch4", FUNC(rs232_port_device::write_dtr));
m_pci[3]->txd_handler().set("ch4", FUNC(rs232_port_device::write_txd));
@@ -342,28 +342,28 @@ void s100_am310_device::device_add_mconfig(machine_config &config)
m_pci[3]->rxrdy_handler().set("irq", FUNC(input_merger_device::in_w<11>));
rs232_port_device &ch1(RS232_PORT(config, "ch1", default_rs232_devices, nullptr)); // J2
- ch1.rxd_handler().set(m_pci[0], FUNC(mc2661_device::rx_w));
- ch1.dcd_handler().set(m_pci[0], FUNC(mc2661_device::dcd_w));
- ch1.dsr_handler().set(m_pci[0], FUNC(mc2661_device::dsr_w));
- ch1.cts_handler().set(m_pci[0], FUNC(mc2661_device::cts_w));
+ ch1.rxd_handler().set(m_pci[0], FUNC(scn_pci_device::rxd_w));
+ ch1.dcd_handler().set(m_pci[0], FUNC(scn_pci_device::dcd_w));
+ ch1.dsr_handler().set(m_pci[0], FUNC(scn_pci_device::dsr_w));
+ ch1.cts_handler().set(m_pci[0], FUNC(scn_pci_device::cts_w));
rs232_port_device &ch2(RS232_PORT(config, "ch2", default_rs232_devices, nullptr)); // J3
- ch2.rxd_handler().set(m_pci[1], FUNC(mc2661_device::rx_w));
- ch2.dcd_handler().set(m_pci[1], FUNC(mc2661_device::dcd_w));
- ch2.dsr_handler().set(m_pci[1], FUNC(mc2661_device::dsr_w));
- ch2.cts_handler().set(m_pci[1], FUNC(mc2661_device::cts_w));
+ ch2.rxd_handler().set(m_pci[1], FUNC(scn_pci_device::rxd_w));
+ ch2.dcd_handler().set(m_pci[1], FUNC(scn_pci_device::dcd_w));
+ ch2.dsr_handler().set(m_pci[1], FUNC(scn_pci_device::dsr_w));
+ ch2.cts_handler().set(m_pci[1], FUNC(scn_pci_device::cts_w));
rs232_port_device &ch3(RS232_PORT(config, "ch3", default_rs232_devices, nullptr)); // J4
- ch3.rxd_handler().set(m_pci[2], FUNC(mc2661_device::rx_w));
- ch3.dcd_handler().set(m_pci[2], FUNC(mc2661_device::dcd_w));
- ch3.dsr_handler().set(m_pci[2], FUNC(mc2661_device::dsr_w));
- ch3.cts_handler().set(m_pci[2], FUNC(mc2661_device::cts_w));
+ ch3.rxd_handler().set(m_pci[2], FUNC(scn_pci_device::rxd_w));
+ ch3.dcd_handler().set(m_pci[2], FUNC(scn_pci_device::dcd_w));
+ ch3.dsr_handler().set(m_pci[2], FUNC(scn_pci_device::dsr_w));
+ ch3.cts_handler().set(m_pci[2], FUNC(scn_pci_device::cts_w));
rs232_port_device &ch4(RS232_PORT(config, "ch4", default_rs232_devices, nullptr)); // J5
- ch4.rxd_handler().set(m_pci[3], FUNC(mc2661_device::rx_w));
- ch4.dcd_handler().set(m_pci[3], FUNC(mc2661_device::dcd_w));
- ch4.dsr_handler().set(m_pci[3], FUNC(mc2661_device::dsr_w));
- ch4.cts_handler().set(m_pci[3], FUNC(mc2661_device::cts_w));
+ ch4.rxd_handler().set(m_pci[3], FUNC(scn_pci_device::rxd_w));
+ ch4.dcd_handler().set(m_pci[3], FUNC(scn_pci_device::dcd_w));
+ ch4.dsr_handler().set(m_pci[3], FUNC(scn_pci_device::dsr_w));
+ ch4.cts_handler().set(m_pci[3], FUNC(scn_pci_device::cts_w));
}
diff --git a/src/devices/bus/s100/ascsasi.cpp b/src/devices/bus/s100/ascsasi.cpp
new file mode 100644
index 00000000000..9193913e2e1
--- /dev/null
+++ b/src/devices/bus/s100/ascsasi.cpp
@@ -0,0 +1,366 @@
+// license:BSD-3-Clause
+// copyright-holders:AJR
+/**********************************************************************
+
+ ASC Associates SASI Host Computer Adapter
+
+ This is a simple host adapter using LSTTL latches and buffers to
+ interface a SASI Winchester drive to the S-100 bus. The 2716 PROM
+ contains 8080 bootstrap code for a CP/M system.
+
+ For a technical description of this board by its designers, see
+ "Building a Hard-Disk Interface for a S-100 Bus System" by Andrew
+ C. Cruce and Scott A. Alexander in the March, April and May 1983
+ issues of BYTE magazine. (The schematic diagrams contain various
+ minor errors.)
+
+**********************************************************************/
+
+#include "emu.h"
+#include "ascsasi.h"
+
+#include "bus/nscsi/devices.h"
+#include "machine/nscsi_bus.h"
+#include "machine/nscsi_cb.h"
+
+class asc_sasi_device : public device_t, public device_s100_card_interface
+{
+ // N.B. actual pulse widths depend on S-100 bus characteristics
+ static constexpr attotime s_pulse_width = attotime::from_nsec(500);
+
+public:
+ // construction/destruction
+ asc_sasi_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock);
+
+protected:
+ // device-level overrides
+ virtual void device_start() override ATTR_COLD;
+ virtual void device_reset() override ATTR_COLD;
+ virtual ioport_constructor device_input_ports() const override ATTR_COLD;
+ virtual void device_add_mconfig(machine_config &config) override ATTR_COLD;
+ virtual const tiny_rom_entry *device_rom_region() const override ATTR_COLD;
+
+ // device_s100_card_interface overrides
+ virtual u8 s100_smemr_r(offs_t offset) override;
+ virtual u8 s100_sinp_r(offs_t offset) override;
+ virtual void s100_sout_w(offs_t offset, u8 data) override;
+
+private:
+ void iio_w(int state);
+ void req_w(int state);
+ void sasi_sel_pulse();
+ void sasi_rst_pulse();
+ TIMER_CALLBACK_MEMBER(sel_off);
+ TIMER_CALLBACK_MEMBER(rst_off);
+
+ // object finders
+ required_device<nscsi_bus_device> m_sasi;
+ required_region_ptr<u8> m_bootstrap;
+ required_ioport m_memsel;
+ required_ioport m_iosel;
+
+ // pulse timers
+ emu_timer *m_sel_off_timer;
+ emu_timer *m_rst_off_timer;
+
+ // internal state
+ u8 m_data_latch;
+ bool m_boot;
+};
+
+constexpr attotime asc_sasi_device::s_pulse_width; // stupid non-inline semantics
+
+DEFINE_DEVICE_TYPE_PRIVATE(S100_ASC_SASI, device_s100_card_interface, asc_sasi_device, "ascsasi", "ASC Associates SASI Host Computer Adapter")
+
+asc_sasi_device::asc_sasi_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock)
+ : device_t(mconfig, S100_ASC_SASI, tag, owner, clock)
+ , device_s100_card_interface(mconfig, *this)
+ , m_sasi(*this, "sasi")
+ , m_bootstrap(*this, "bootstrap")
+ , m_memsel(*this, "MEMSEL")
+ , m_iosel(*this, "IOSEL")
+ , m_sel_off_timer(nullptr)
+ , m_rst_off_timer(nullptr)
+ , m_data_latch(0)
+ , m_boot(false)
+{
+}
+
+void asc_sasi_device::device_start()
+{
+ // initialize timers
+ m_sel_off_timer = timer_alloc(FUNC(asc_sasi_device::sel_off), this);
+ m_rst_off_timer = timer_alloc(FUNC(asc_sasi_device::rst_off), this);
+
+ // save state
+ save_item(NAME(m_data_latch));
+ save_item(NAME(m_boot));
+}
+
+void asc_sasi_device::device_reset()
+{
+ // POC causes RST pulse on SASI bus (unless jumper is removed)
+ sasi_rst_pulse();
+
+ // CLR sets flip-flop (IC10a)
+ m_boot = true;
+}
+
+void asc_sasi_device::iio_w(int state)
+{
+ // Release data bus when I/O is asserted
+ if (state)
+ m_sasi->data_w(7, 0);
+ else
+ m_sasi->data_w(7, m_data_latch);
+}
+
+void asc_sasi_device::req_w(int state)
+{
+ // Clear ACK when REQ is negated
+ if (!state)
+ m_sasi->ctrl_w(7, 0, nscsi_device::S_ACK);
+}
+
+void asc_sasi_device::sasi_sel_pulse()
+{
+ m_sasi->ctrl_w(7, nscsi_device::S_SEL, nscsi_device::S_SEL);
+ m_sel_off_timer->adjust(s_pulse_width);
+}
+
+void asc_sasi_device::sasi_rst_pulse()
+{
+ m_sasi->ctrl_w(7, nscsi_device::S_RST, nscsi_device::S_RST);
+ m_rst_off_timer->adjust(s_pulse_width);
+}
+
+TIMER_CALLBACK_MEMBER(asc_sasi_device::sel_off)
+{
+ m_sasi->ctrl_w(7, 0, nscsi_device::S_SEL);
+}
+
+TIMER_CALLBACK_MEMBER(asc_sasi_device::rst_off)
+{
+ m_sasi->ctrl_w(7, 0, nscsi_device::S_RST);
+}
+
+u8 asc_sasi_device::s100_smemr_r(offs_t offset)
+{
+ u8 memsel = m_memsel->read();
+ if (m_boot && BIT(memsel, 0) && (offset & 0xf800) == (memsel & 0x3e) << 10)
+ return m_bootstrap[offset & 0x7ff];
+ else
+ return 0xff;
+}
+
+u8 asc_sasi_device::s100_sinp_r(offs_t offset)
+{
+ // Only two input ports are decoded
+ if ((offset & 0xfe) == (m_iosel->read() & 0x3f) << 2)
+ {
+ if (BIT(offset, 0))
+ {
+ // 74LS240 buffer (IC7)
+ u32 ctrl = m_sasi->ctrl_r();
+ return (ctrl & nscsi_device::S_INP ? 0x01 : 0x00)
+ | (ctrl & nscsi_device::S_BSY ? 0x04 : 0x00)
+ | (ctrl & nscsi_device::S_REQ ? 0x10 : 0x00)
+ | (ctrl & nscsi_device::S_CTL ? 0x80 : 0x00);
+ }
+ else
+ {
+ // INDAT: 74LS240 buffer (IC13)
+ if (!machine().side_effects_disabled() && (m_sasi->ctrl_r() & nscsi_device::S_REQ))
+ m_sasi->ctrl_w(7, nscsi_device::S_ACK, nscsi_device::S_ACK);
+ return m_sasi->data_r();
+ }
+ }
+ else
+ return 0xff;
+}
+
+void asc_sasi_device::s100_sout_w(offs_t offset, u8 data)
+{
+ if ((offset & 0xfc) == (m_iosel->read() & 0x3f) << 2)
+ {
+ switch (offset & 0x03)
+ {
+ case 0:
+ // LATENA: 74LS373 latch (IC8) outputs to 74LS240 buffer (IC9)
+ if (!machine().side_effects_disabled() && (m_sasi->ctrl_r() & nscsi_device::S_REQ))
+ m_sasi->ctrl_w(7, nscsi_device::S_ACK, nscsi_device::S_ACK);
+ m_data_latch = data;
+ if (!(m_sasi->ctrl_r() & nscsi_device::S_INP))
+ m_sasi->data_w(7, data);
+ break;
+
+ case 1:
+ sasi_sel_pulse();
+ break;
+
+ case 2:
+ // MEMCON: clock DO5 into flip-flop (IC10a)
+ m_boot = BIT(data, 5);
+ break;
+
+ case 3:
+ sasi_rst_pulse();
+ break;
+ }
+ }
+}
+
+
+static INPUT_PORTS_START(ascsasi)
+ PORT_START("MEMSEL")
+ PORT_DIPNAME(0x01, 0x01, "Bootstrap PROM")
+ PORT_DIPSETTING(0x00, DEF_STR(Off))
+ PORT_DIPSETTING(0x01, DEF_STR(On))
+ PORT_DIPNAME(0x3e, 0x38, "PROM Address Decode") PORT_DIPLOCATION("SW1:2,3,4,5,6")
+ PORT_DIPSETTING(0x00, "0000-07FF")
+ PORT_DIPSETTING(0x02, "0800-0FFF")
+ PORT_DIPSETTING(0x04, "1000-17FF")
+ PORT_DIPSETTING(0x06, "1800-1FFF")
+ PORT_DIPSETTING(0x08, "2000-27FF")
+ PORT_DIPSETTING(0x0a, "2800-2FFF")
+ PORT_DIPSETTING(0x0c, "3000-37FF")
+ PORT_DIPSETTING(0x0e, "3800-3FFF")
+ PORT_DIPSETTING(0x10, "4000-47FF")
+ PORT_DIPSETTING(0x12, "4800-4FFF")
+ PORT_DIPSETTING(0x14, "5000-57FF")
+ PORT_DIPSETTING(0x16, "5800-5FFF")
+ PORT_DIPSETTING(0x18, "6000-67FF")
+ PORT_DIPSETTING(0x1a, "6800-6FFF")
+ PORT_DIPSETTING(0x1c, "7000-77FF")
+ PORT_DIPSETTING(0x1e, "7800-7FFF")
+ PORT_DIPSETTING(0x20, "8000-87FF")
+ PORT_DIPSETTING(0x22, "8800-8FFF")
+ PORT_DIPSETTING(0x24, "9000-97FF")
+ PORT_DIPSETTING(0x26, "9800-9FFF")
+ PORT_DIPSETTING(0x28, "A000-A7FF")
+ PORT_DIPSETTING(0x2a, "A800-AFFF")
+ PORT_DIPSETTING(0x2c, "B000-B7FF")
+ PORT_DIPSETTING(0x2e, "B800-BFFF")
+ PORT_DIPSETTING(0x30, "C000-C7FF")
+ PORT_DIPSETTING(0x32, "C800-CFFF")
+ PORT_DIPSETTING(0x34, "D000-D7FF")
+ PORT_DIPSETTING(0x36, "D800-DFFF")
+ PORT_DIPSETTING(0x38, "E000-E7FF")
+ PORT_DIPSETTING(0x3a, "E800-EFFF")
+ PORT_DIPSETTING(0x3c, "F000-F7FF")
+ PORT_DIPSETTING(0x3e, "F800-FFFF")
+ PORT_DIPNAME(0x40, 0x40, "PHANTOM Signal") PORT_DIPLOCATION("SW1:7") // not emulated
+ PORT_DIPSETTING(0x40, DEF_STR(Off))
+ PORT_DIPSETTING(0x00, DEF_STR(On))
+ PORT_DIPNAME(0x80, 0x80, "Memory Wait State") PORT_DIPLOCATION("SW1:8") // not emulated
+ PORT_DIPSETTING(0x80, DEF_STR(Off))
+ PORT_DIPSETTING(0x00, DEF_STR(On))
+
+ PORT_START("IOSEL")
+ PORT_DIPNAME(0x3f, 0x28, "I/O Address Decode") PORT_DIPLOCATION("SW2:1,2,3,4,5,6")
+ PORT_DIPSETTING(0x00, "00-03")
+ PORT_DIPSETTING(0x01, "04-07")
+ PORT_DIPSETTING(0x02, "08-0B")
+ PORT_DIPSETTING(0x03, "0C-0F")
+ PORT_DIPSETTING(0x04, "10-13")
+ PORT_DIPSETTING(0x05, "14-17")
+ PORT_DIPSETTING(0x06, "18-1B")
+ PORT_DIPSETTING(0x07, "1C-1F")
+ PORT_DIPSETTING(0x08, "20-23")
+ PORT_DIPSETTING(0x09, "24-27")
+ PORT_DIPSETTING(0x0a, "28-2B")
+ PORT_DIPSETTING(0x0b, "2C-2F")
+ PORT_DIPSETTING(0x0c, "30-33")
+ PORT_DIPSETTING(0x0d, "34-37")
+ PORT_DIPSETTING(0x0e, "38-3B")
+ PORT_DIPSETTING(0x0f, "3C-3F")
+ PORT_DIPSETTING(0x10, "40-43")
+ PORT_DIPSETTING(0x11, "44-47")
+ PORT_DIPSETTING(0x12, "48-4B")
+ PORT_DIPSETTING(0x13, "4C-4F")
+ PORT_DIPSETTING(0x14, "50-53")
+ PORT_DIPSETTING(0x15, "54-57")
+ PORT_DIPSETTING(0x16, "58-5B")
+ PORT_DIPSETTING(0x17, "5C-5F")
+ PORT_DIPSETTING(0x18, "60-63")
+ PORT_DIPSETTING(0x19, "64-67")
+ PORT_DIPSETTING(0x1a, "68-6B")
+ PORT_DIPSETTING(0x1b, "6C-6F")
+ PORT_DIPSETTING(0x1c, "70-73")
+ PORT_DIPSETTING(0x1d, "74-77")
+ PORT_DIPSETTING(0x1e, "78-7B")
+ PORT_DIPSETTING(0x1f, "7C-7F")
+ PORT_DIPSETTING(0x20, "80-83")
+ PORT_DIPSETTING(0x21, "84-87")
+ PORT_DIPSETTING(0x22, "88-8B")
+ PORT_DIPSETTING(0x23, "8C-8F")
+ PORT_DIPSETTING(0x24, "90-93")
+ PORT_DIPSETTING(0x25, "94-97")
+ PORT_DIPSETTING(0x26, "98-9B")
+ PORT_DIPSETTING(0x27, "9C-9F")
+ PORT_DIPSETTING(0x28, "A0-A3")
+ PORT_DIPSETTING(0x29, "A4-A7")
+ PORT_DIPSETTING(0x2a, "A8-AB")
+ PORT_DIPSETTING(0x2b, "AC-AF")
+ PORT_DIPSETTING(0x2c, "B0-B3")
+ PORT_DIPSETTING(0x2d, "B4-B7")
+ PORT_DIPSETTING(0x2e, "B8-BB")
+ PORT_DIPSETTING(0x2f, "BC-BF")
+ PORT_DIPSETTING(0x30, "C0-C3")
+ PORT_DIPSETTING(0x31, "C4-C7")
+ PORT_DIPSETTING(0x32, "C8-CB")
+ PORT_DIPSETTING(0x33, "CC-CF")
+ PORT_DIPSETTING(0x34, "D0-D3")
+ PORT_DIPSETTING(0x35, "D4-D7")
+ PORT_DIPSETTING(0x36, "D8-DB")
+ PORT_DIPSETTING(0x37, "DC-DF")
+ PORT_DIPSETTING(0x38, "E0-E3")
+ PORT_DIPSETTING(0x39, "E4-E7")
+ PORT_DIPSETTING(0x3a, "E8-EB")
+ PORT_DIPSETTING(0x3b, "EC-EF")
+ PORT_DIPSETTING(0x3c, "F0-F3")
+ PORT_DIPSETTING(0x3d, "F4-F7")
+ PORT_DIPSETTING(0x3e, "F8-FB")
+ PORT_DIPSETTING(0x3f, "FC-FF")
+ PORT_DIPNAME(0x40, 0x40, DEF_STR(Unused)) PORT_DIPLOCATION("SW2:7")
+ PORT_DIPSETTING(0x40, DEF_STR(Off))
+ PORT_DIPSETTING(0x00, DEF_STR(On))
+ PORT_DIPNAME(0x80, 0x80, DEF_STR(Unused)) PORT_DIPLOCATION("SW2:8")
+ PORT_DIPSETTING(0x80, DEF_STR(Off))
+ PORT_DIPSETTING(0x00, DEF_STR(On))
+INPUT_PORTS_END
+
+
+ioport_constructor asc_sasi_device::device_input_ports() const
+{
+ return INPUT_PORTS_NAME(ascsasi);
+}
+
+void asc_sasi_device::device_add_mconfig(machine_config &config)
+{
+ NSCSI_BUS(config, m_sasi);
+ NSCSI_CONNECTOR(config, "sasi:0", default_scsi_devices, nullptr);
+ NSCSI_CONNECTOR(config, "sasi:1", default_scsi_devices, nullptr);
+ NSCSI_CONNECTOR(config, "sasi:2", default_scsi_devices, nullptr);
+ NSCSI_CONNECTOR(config, "sasi:3", default_scsi_devices, nullptr);
+ NSCSI_CONNECTOR(config, "sasi:4", default_scsi_devices, nullptr);
+ NSCSI_CONNECTOR(config, "sasi:5", default_scsi_devices, nullptr);
+ NSCSI_CONNECTOR(config, "sasi:6", default_scsi_devices, nullptr);
+ NSCSI_CONNECTOR(config, "sasi:7", default_scsi_devices, "sasicb", true)
+ .option_add_internal("sasicb", NSCSI_CB)
+ .machine_config([this] (device_t *device) {
+ downcast<nscsi_callback_device &>(*device).io_callback().set(*this, FUNC(asc_sasi_device::iio_w));
+ downcast<nscsi_callback_device &>(*device).req_callback().set(*this, FUNC(asc_sasi_device::req_w));
+ });
+}
+
+
+ROM_START(ascsasi)
+ ROM_REGION(0x800, "bootstrap", 0)
+ ROM_LOAD("asc_sasi.bin", 0x000, 0x800, CRC(aac84077) SHA1(e94b39875e29daff199d120c4e79dfb1adbedab2)) // MODEL 1 REV. 2
+ROM_END
+
+const tiny_rom_entry *asc_sasi_device::device_rom_region() const
+{
+ return ROM_NAME(ascsasi);
+}
diff --git a/src/devices/bus/s100/ascsasi.h b/src/devices/bus/s100/ascsasi.h
new file mode 100644
index 00000000000..2b5bb0ace69
--- /dev/null
+++ b/src/devices/bus/s100/ascsasi.h
@@ -0,0 +1,18 @@
+// license:BSD-3-Clause
+// copyright-holders:AJR
+/**********************************************************************
+
+ ASC Associates SASI Host Computer Adapter
+
+**********************************************************************/
+
+#ifndef MAME_BUS_S100_ASCSASI_H
+#define MAME_BUS_S100_ASCSASI_H
+
+#pragma once
+
+#include "bus/s100/s100.h"
+
+DECLARE_DEVICE_TYPE(S100_ASC_SASI, device_s100_card_interface)
+
+#endif // MAME_BUS_S100_ASCSASI_H
diff --git a/src/devices/bus/s100/dg640.cpp b/src/devices/bus/s100/dg640.cpp
index 7f79983f17d..f6adb27cfa8 100644
--- a/src/devices/bus/s100/dg640.cpp
+++ b/src/devices/bus/s100/dg640.cpp
@@ -39,28 +39,26 @@ void dg640_device::device_start()
uint32_t dg640_device::screen_update(screen_device &screen, bitmap_ind16 &bitmap, const rectangle &cliprect)
{
// attributes bit 0 = flash, bit 1 = lores. Also bit 7 of the character = reverse-video (text only).
- uint8_t y,ra,chr,gfx,attr,inv,gfxbit;
- uint16_t sy=0,ma=0,x;
- bool flash;
+ uint16_t sy=0,ma=0;
m_framecnt++;
- for (y = 0; y < 16; y++)
+ for (uint8_t y = 0; y < 16; y++)
{
- for (ra = 0; ra < 16; ra++)
+ for (uint8_t ra = 0; ra < 16; ra++)
{
- uint16_t *p = &bitmap.pix16(sy++);
+ uint16_t *p = &bitmap.pix(sy++);
- for (x = ma; x < ma + 64; x++)
+ for (uint16_t x = ma; x < ma + 64; x++)
{
- attr = m_p_attribram[x];
- chr = m_p_videoram[x];
- flash = BIT(m_framecnt, 4) & BIT(attr, 0);
+ uint8_t attr = m_p_attribram[x];
+ uint8_t chr = m_p_videoram[x];
+ bool flash = BIT(m_framecnt, 4) & BIT(attr, 0);
if (BIT(attr, 1)) // lores gfx - can flash
{
if (flash) chr = 0; // blank part of flashing
- gfxbit = (ra & 0x0c)>>1;
+ uint8_t gfxbit = (ra & 0x0c) >> 1;
/* Display one line of a lores character (8 pixels) */
*p++ = BIT(chr, gfxbit);
*p++ = BIT(chr, gfxbit);
@@ -74,11 +72,11 @@ uint32_t dg640_device::screen_update(screen_device &screen, bitmap_ind16 &bitmap
}
else
{
- gfx = 0;
+ uint8_t gfx = 0;
if (!flash)
{
- inv = BIT(chr, 7) ? 0xff : 0; // text with bit 7 high is reversed
+ uint8_t inv = BIT(chr, 7) ? 0xff : 0; // text with bit 7 high is reversed
chr &= 0x7f;
gfx = inv;
diff --git a/src/devices/bus/s100/dg640.h b/src/devices/bus/s100/dg640.h
index 97d1a3ecbc3..746d2c7f6c3 100644
--- a/src/devices/bus/s100/dg640.h
+++ b/src/devices/bus/s100/dg640.h
@@ -21,10 +21,10 @@ public:
protected:
// device-level overrides
- virtual void device_start() override;
- virtual ioport_constructor device_input_ports() const override;
- virtual void device_add_mconfig(machine_config &config) override;
- virtual const tiny_rom_entry *device_rom_region() const override;
+ virtual void device_start() override ATTR_COLD;
+ virtual ioport_constructor device_input_ports() const override ATTR_COLD;
+ virtual void device_add_mconfig(machine_config &config) override ATTR_COLD;
+ virtual const tiny_rom_entry *device_rom_region() const override ATTR_COLD;
// device_s100_card_interface overrides
virtual u8 s100_smemr_r(offs_t offset) override;
diff --git a/src/devices/bus/s100/dj2db.cpp b/src/devices/bus/s100/dj2db.cpp
index 7c33182ea5d..cd160593425 100644
--- a/src/devices/bus/s100/dj2db.cpp
+++ b/src/devices/bus/s100/dj2db.cpp
@@ -17,6 +17,8 @@
#include "emu.h"
#include "dj2db.h"
+#include "machine/ay31015.h"
+
//**************************************************************************
@@ -64,17 +66,12 @@ const tiny_rom_entry *s100_dj2db_device::device_rom_region() const
// COM8116_INTERFACE( brg_intf )
//-------------------------------------------------
-WRITE_LINE_MEMBER( s100_dj2db_device::fr_w )
-{
- // S1602 RRC/TRC
-}
-
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);
@@ -92,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);
}
@@ -104,17 +101,20 @@ WRITE_LINE_MEMBER( s100_dj2db_device::fdc_drq_w )
void s100_dj2db_device::device_add_mconfig(machine_config &config)
{
- COM8116(config, m_dbrg, 5.0688_MHz_XTAL);
- m_dbrg->fr_handler().set(FUNC(s100_dj2db_device::fr_w));
+ COM8116(config, m_dbrg, 5.0688_MHz_XTAL); // BR2941
+ m_dbrg->fr_handler().set(m_uart, FUNC(ay51013_device::write_tcp));
+ m_dbrg->fr_handler().append(m_uart, FUNC(ay51013_device::write_rcp));
- MB8866(config, m_fdc, 10_MHz_XTAL / 5);
+ AY51013(config, m_uart); // TR1602
+
+ MB8866(config, m_fdc, 10_MHz_XTAL / 10); // clocked by QC output of LS390
m_fdc->intrq_wr_callback().set(FUNC(s100_dj2db_device::fdc_intrq_w));
m_fdc->drq_wr_callback().set(FUNC(s100_dj2db_device::fdc_drq_w));
- FLOPPY_CONNECTOR(config, m_floppy0, s100_dj2db_floppies, "8dsdd", floppy_image_device::default_floppy_formats);
- FLOPPY_CONNECTOR(config, m_floppy1, s100_dj2db_floppies, nullptr, floppy_image_device::default_floppy_formats);
- FLOPPY_CONNECTOR(config, m_floppy2, s100_dj2db_floppies, nullptr, floppy_image_device::default_floppy_formats);
- FLOPPY_CONNECTOR(config, m_floppy3, s100_dj2db_floppies, nullptr, floppy_image_device::default_floppy_formats);
+ FLOPPY_CONNECTOR(config, m_floppy0, s100_dj2db_floppies, "8dsdd", floppy_image_device::default_mfm_floppy_formats);
+ FLOPPY_CONNECTOR(config, m_floppy1, s100_dj2db_floppies, nullptr, floppy_image_device::default_mfm_floppy_formats);
+ FLOPPY_CONNECTOR(config, m_floppy2, s100_dj2db_floppies, nullptr, floppy_image_device::default_mfm_floppy_formats);
+ FLOPPY_CONNECTOR(config, m_floppy3, s100_dj2db_floppies, nullptr, floppy_image_device::default_mfm_floppy_formats);
}
@@ -247,13 +247,14 @@ s100_dj2db_device::s100_dj2db_device(const machine_config &mconfig, const char *
device_s100_card_interface(mconfig, *this),
m_fdc(*this, MB8866_TAG),
m_dbrg(*this, BR1941_TAG),
+ m_uart(*this, S1602_TAG),
m_floppy0(*this, MB8866_TAG":0"),
m_floppy1(*this, MB8866_TAG":1"),
m_floppy2(*this, MB8866_TAG":2"),
m_floppy3(*this, MB8866_TAG":3"),
m_floppy(nullptr),
m_rom(*this, "dj2db"),
- m_ram(*this, "ram"),
+ m_ram(*this, "ram", 0x400, ENDIANNESS_LITTLE),
m_j1a(*this, "J1A"),
m_j3a(*this, "J3A"),
m_j4(*this, "J4"),
@@ -274,9 +275,6 @@ s100_dj2db_device::s100_dj2db_device(const machine_config &mconfig, const char *
void s100_dj2db_device::device_start()
{
- // allocate memory
- m_ram.allocate(0x400);
-
// state saving
save_item(NAME(m_drive));
save_item(NAME(m_head));
@@ -294,6 +292,8 @@ void s100_dj2db_device::device_start()
void s100_dj2db_device::device_reset()
{
m_board_enbl = m_j4->read();
+
+ m_fdc->mr_w(0);
}
@@ -432,7 +432,7 @@ void s100_dj2db_device::s100_mwrt_w(offs_t offset, uint8_t data)
m_access_enbl = BIT(data, 6);
// master reset
- if (!BIT(data, 7)) m_fdc->soft_reset();
+ m_fdc->mr_w(BIT(data, 7));
}
else if (offset == 0xfbfa) // FUNCTION SEL
{
diff --git a/src/devices/bus/s100/dj2db.h b/src/devices/bus/s100/dj2db.h
index 616113bb038..8536b3774c8 100644
--- a/src/devices/bus/s100/dj2db.h
+++ b/src/devices/bus/s100/dj2db.h
@@ -13,6 +13,7 @@
#include "s100.h"
#include "imagedev/floppy.h"
+#include "machine/ay31015.h"
#include "machine/com8116.h"
#include "machine/wd_fdc.h"
@@ -33,13 +34,13 @@ public:
protected:
// device-level overrides
- virtual void device_start() override;
- virtual void device_reset() override;
+ virtual void device_start() override ATTR_COLD;
+ virtual void device_reset() override ATTR_COLD;
// optional information 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 const tiny_rom_entry *device_rom_region() const override ATTR_COLD;
+ virtual void device_add_mconfig(machine_config &config) override ATTR_COLD;
+ virtual ioport_constructor device_input_ports() const override ATTR_COLD;
// device_s100_card_interface overrides
virtual uint8_t s100_smemr_r(offs_t offset) override;
@@ -49,20 +50,20 @@ protected:
virtual void s100_phantom_w(int state) override;
private:
- DECLARE_WRITE_LINE_MEMBER( fr_w );
- 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;
required_device<com8116_device> m_dbrg;
+ required_device<ay31015_device> m_uart;
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_memory_region m_rom;
- optional_shared_ptr<uint8_t> m_ram;
+ memory_share_creator<uint8_t> m_ram;
required_ioport m_j1a;
required_ioport m_j3a;
required_ioport m_j4;
diff --git a/src/devices/bus/s100/djdma.h b/src/devices/bus/s100/djdma.h
index d9453aef25c..e763e4aef2c 100644
--- a/src/devices/bus/s100/djdma.h
+++ b/src/devices/bus/s100/djdma.h
@@ -30,19 +30,19 @@ public:
protected:
// device-level overrides
- virtual void device_start() override;
- virtual void device_reset() override;
+ virtual void device_start() override ATTR_COLD;
+ virtual void device_reset() override ATTR_COLD;
// bus-level overrides;
virtual void s100_sout_w(offs_t offset, uint8_t data) 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 device_add_mconfig(machine_config &config) override ATTR_COLD;
+ virtual const tiny_rom_entry *device_rom_region() const override ATTR_COLD;
private:
- void djdma_io(address_map &map);
- void djdma_mem(address_map &map);
+ void djdma_io(address_map &map) ATTR_COLD;
+ void djdma_mem(address_map &map) ATTR_COLD;
void reset_int_w(u8 data);
u8 disk_di_r();
diff --git a/src/devices/bus/s100/mm65k16s.cpp b/src/devices/bus/s100/mm65k16s.cpp
index ae098a2e29c..5f64ce67aa4 100644
--- a/src/devices/bus/s100/mm65k16s.cpp
+++ b/src/devices/bus/s100/mm65k16s.cpp
@@ -205,7 +205,7 @@ ioport_constructor s100_mm65k16s_device::device_input_ports() const
s100_mm65k16s_device::s100_mm65k16s_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) :
device_t(mconfig, S100_MM65K16S, tag, owner, clock),
device_s100_card_interface(mconfig, *this),
- m_ram(*this, "ram")
+ m_ram(*this, "ram", 0x10000, ENDIANNESS_LITTLE)
{
}
@@ -216,7 +216,6 @@ s100_mm65k16s_device::s100_mm65k16s_device(const machine_config &mconfig, const
void s100_mm65k16s_device::device_start()
{
- m_ram.allocate(0x10000);
}
diff --git a/src/devices/bus/s100/mm65k16s.h b/src/devices/bus/s100/mm65k16s.h
index 10fa1daff7a..c0e38867d8d 100644
--- a/src/devices/bus/s100/mm65k16s.h
+++ b/src/devices/bus/s100/mm65k16s.h
@@ -29,13 +29,13 @@ public:
s100_mm65k16s_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 ioport_constructor device_input_ports() const override;
+ virtual const tiny_rom_entry *device_rom_region() const override ATTR_COLD;
+ virtual ioport_constructor device_input_ports() const override ATTR_COLD;
protected:
// device-level overrides
- virtual void device_start() override;
- virtual void device_reset() override;
+ virtual void device_start() override ATTR_COLD;
+ virtual void device_reset() override ATTR_COLD;
// device_s100_card_interface overrides
virtual uint8_t s100_smemr_r(offs_t offset) override;
@@ -43,7 +43,7 @@ protected:
virtual void s100_phantom_w(int state) override;
private:
- optional_shared_ptr<uint8_t> m_ram;
+ memory_share_creator<uint8_t> m_ram;
};
diff --git a/src/devices/bus/s100/nsmdsa.cpp b/src/devices/bus/s100/nsmdsa.cpp
index 90d19b3fcb3..53441107c7d 100644
--- a/src/devices/bus/s100/nsmdsa.cpp
+++ b/src/devices/bus/s100/nsmdsa.cpp
@@ -60,7 +60,7 @@ static void mds_a_floppies(device_slot_interface &device)
void s100_mds_a_device::device_add_mconfig(machine_config &config)
{
for (auto &floppy : m_floppy)
- FLOPPY_CONNECTOR(config, floppy, mds_a_floppies, "525sd", floppy_image_device::default_floppy_formats);
+ FLOPPY_CONNECTOR(config, floppy, mds_a_floppies, "525sd", floppy_image_device::default_mfm_floppy_formats);
}
diff --git a/src/devices/bus/s100/nsmdsa.h b/src/devices/bus/s100/nsmdsa.h
index a36f39127ec..bfe25954f27 100644
--- a/src/devices/bus/s100/nsmdsa.h
+++ b/src/devices/bus/s100/nsmdsa.h
@@ -31,12 +31,12 @@ public:
protected:
// device-level overrides
- virtual void device_start() override;
- virtual void device_reset() override;
+ virtual void device_start() override ATTR_COLD;
+ virtual void device_reset() override ATTR_COLD;
// optional information overrides
- virtual const tiny_rom_entry *device_rom_region() const override;
- virtual void device_add_mconfig(machine_config &config) override;
+ virtual const tiny_rom_entry *device_rom_region() const override ATTR_COLD;
+ virtual void device_add_mconfig(machine_config &config) override ATTR_COLD;
// device_s100_card_interface overrides
virtual uint8_t s100_smemr_r(offs_t offset) override;
diff --git a/src/devices/bus/s100/nsmdsad.cpp b/src/devices/bus/s100/nsmdsad.cpp
index d1358e85bf0..00343623711 100644
--- a/src/devices/bus/s100/nsmdsad.cpp
+++ b/src/devices/bus/s100/nsmdsad.cpp
@@ -61,7 +61,7 @@ static void mds_ad_floppies(device_slot_interface &device)
void s100_mds_ad_device::device_add_mconfig(machine_config &config)
{
for (auto &floppy : m_floppy)
- FLOPPY_CONNECTOR(config, floppy, mds_ad_floppies, "525dd", floppy_image_device::default_floppy_formats);
+ FLOPPY_CONNECTOR(config, floppy, mds_ad_floppies, "525dd", floppy_image_device::default_mfm_floppy_formats);
}
diff --git a/src/devices/bus/s100/nsmdsad.h b/src/devices/bus/s100/nsmdsad.h
index ce5a248d553..3636f171b35 100644
--- a/src/devices/bus/s100/nsmdsad.h
+++ b/src/devices/bus/s100/nsmdsad.h
@@ -31,12 +31,12 @@ public:
protected:
// device-level overrides
- virtual void device_start() override;
- virtual void device_reset() override;
+ virtual void device_start() override ATTR_COLD;
+ virtual void device_reset() override ATTR_COLD;
// optional information overrides
- virtual const tiny_rom_entry *device_rom_region() const override;
- virtual void device_add_mconfig(machine_config &config) override;
+ virtual const tiny_rom_entry *device_rom_region() const override ATTR_COLD;
+ virtual void device_add_mconfig(machine_config &config) override ATTR_COLD;
// device_s100_card_interface overrides
virtual uint8_t s100_smemr_r(offs_t offset) override;
diff --git a/src/devices/bus/s100/poly16k.cpp b/src/devices/bus/s100/poly16k.cpp
index 98861545d39..af1566348ea 100644
--- a/src/devices/bus/s100/poly16k.cpp
+++ b/src/devices/bus/s100/poly16k.cpp
@@ -30,8 +30,8 @@ public:
protected:
// device-specific overrides
- virtual ioport_constructor device_input_ports() const override;
- virtual void device_start() override;
+ virtual ioport_constructor device_input_ports() const override ATTR_COLD;
+ virtual void device_start() override ATTR_COLD;
// S-100 memory access handlers
virtual u8 s100_smemr_r(offs_t offset) override;
diff --git a/src/devices/bus/s100/polyfdc.cpp b/src/devices/bus/s100/polyfdc.cpp
index ca5defd523c..f36411af7ef 100644
--- a/src/devices/bus/s100/polyfdc.cpp
+++ b/src/devices/bus/s100/polyfdc.cpp
@@ -4,9 +4,9 @@
PolyMorphic Systems Disk Controller
- This board controls up to three Shugart SA-400 drives using only
- generic serial and parallel interface chips and TTL (and an onboard
- 4 MHz XTAL). No schematics for this board have been found.
+ This board controls up to three Shugart SA400 Minifloppy drives using
+ only generic serial and parallel interface chips and TTL (and an
+ onboard 4 MHz XTAL).
****************************************************************************/
@@ -26,8 +26,8 @@ public:
protected:
// device-level overrides
- virtual void device_start() override;
- virtual void device_add_mconfig(machine_config &config) override;
+ virtual void device_start() override ATTR_COLD;
+ virtual void device_add_mconfig(machine_config &config) override ATTR_COLD;
// device_s100_card_interface overrides
virtual u8 s100_sinp_r(offs_t offset) override;
@@ -39,8 +39,8 @@ private:
void pc_w(u8 data);
// object finders
- required_device<mc6852_device> m_ssda;
- required_device<i8255_device> m_ppi;
+ required_device<mc6852_device> m_usrt;
+ required_device<i8255_device> m_pio;
};
DEFINE_DEVICE_TYPE_PRIVATE(S100_POLY_FDC, device_s100_card_interface, poly_fdc_device, "polyfdc", "PolyMorphic Systems Disk Controller")
@@ -48,8 +48,8 @@ DEFINE_DEVICE_TYPE_PRIVATE(S100_POLY_FDC, device_s100_card_interface, poly_fdc_d
poly_fdc_device::poly_fdc_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock)
: device_t(mconfig, S100_POLY_FDC, tag, owner, clock)
, device_s100_card_interface(mconfig, *this)
- , m_ssda(*this, "ssda")
- , m_ppi(*this, "ppi")
+ , m_usrt(*this, "usrt")
+ , m_pio(*this, "pio")
{
}
@@ -59,12 +59,12 @@ void poly_fdc_device::device_start()
u8 poly_fdc_device::s100_sinp_r(offs_t offset)
{
- if ((offset & 0xf000) == 0x2000)
+ if ((offset & 0x00f0) == 0x0020)
{
- if (BIT(offset, 11))
- return m_ppi->read(offset & 3);
+ if (BIT(offset, 3))
+ return m_pio->read(offset & 3);
else
- return m_ssda->read(offset & 1);
+ return m_usrt->read(offset & 1);
}
return 0xff;
@@ -72,37 +72,54 @@ u8 poly_fdc_device::s100_sinp_r(offs_t offset)
void poly_fdc_device::s100_sout_w(offs_t offset, u8 data)
{
- if ((offset & 0xf000) == 0x2000)
+ if ((offset & 0x00f0) == 0x20)
{
- if (BIT(offset, 11))
- m_ppi->write(offset & 3, data);
+ if (BIT(offset, 3))
+ m_pio->write(offset & 3, data);
else
- m_ssda->write(offset & 1, data);
+ m_usrt->write(offset & 1, data);
}
}
void poly_fdc_device::pa_w(u8 data)
{
+ // PA0, PA1 are decoded onto drive select lines
+ // DS1- (pin 10) = ~(~PA1 & PA0)
+ // DS2- (pin 12) = ~(PA1 & ~PA0)
+ // DS3- (pin 14) = ~(PA1 & PA0)
}
u8 poly_fdc_device::pb_r()
{
- return 0xff;
+ // PB0 = SC0+ (from index/sector counting circuit)
+ // PB1 = SC1+
+ // PB2 = SC2+
+ // PB3 = SC3+
+ // PB4 = TR0+ (inverted from SA400 pin 26)
+ // PB5 = WPRT+ (inverted from SA400 pin 28)
+ // PB6 = PB7 = GND
+ return 0;
}
void poly_fdc_device::pc_w(u8 data)
{
- // Port B interrupt
+ // PC0 = INT+ (buffered onto VI5-)
+ // PC2 = SCTR-
+ // PC3 = MTRON+ (inverted onto SA400 pin 16)
+ // PC4 = WCMD+
+ // PC5 = RCMD+
+ // PC6 = DS+ (inverted onto SA400 pin 18)
+ // PC7 = STEP+ (inverted onto SA400 pin 20)
m_bus->vi5_w(BIT(data, 0) ? ASSERT_LINE : CLEAR_LINE);
}
void poly_fdc_device::device_add_mconfig(machine_config &config)
{
- MC6852(config, m_ssda, 4_MHz_XTAL / 4); // actual clock unknown
+ MC6852(config, m_usrt, 0); // E generated from PDBIN+ and PWR-
- I8255(config, m_ppi);
- m_ppi->out_pa_callback().set(FUNC(poly_fdc_device::pa_w));
- m_ppi->in_pb_callback().set(FUNC(poly_fdc_device::pb_r));
- m_ppi->out_pc_callback().set(FUNC(poly_fdc_device::pc_w));
- m_ppi->tri_pc_callback().set_constant(0xfe);
+ I8255(config, m_pio);
+ m_pio->out_pa_callback().set(FUNC(poly_fdc_device::pa_w));
+ m_pio->in_pb_callback().set(FUNC(poly_fdc_device::pb_r));
+ m_pio->out_pc_callback().set(FUNC(poly_fdc_device::pc_w));
+ m_pio->tri_pc_callback().set_constant(0xfe);
}
diff --git a/src/devices/bus/s100/polyvti.cpp b/src/devices/bus/s100/polyvti.cpp
index 973e89c0693..5aa3009762f 100644
--- a/src/devices/bus/s100/polyvti.cpp
+++ b/src/devices/bus/s100/polyvti.cpp
@@ -40,10 +40,10 @@ public:
protected:
// device-level overrides
- virtual void device_start() override;
- virtual ioport_constructor device_input_ports() const override;
- virtual void device_add_mconfig(machine_config &config) override;
- virtual const tiny_rom_entry *device_rom_region() const override;
+ virtual void device_start() override ATTR_COLD;
+ virtual ioport_constructor device_input_ports() const override ATTR_COLD;
+ virtual void device_add_mconfig(machine_config &config) override ATTR_COLD;
+ virtual const tiny_rom_entry *device_rom_region() const override ATTR_COLD;
// device_s100_card_interface overrides
virtual u8 s100_smemr_r(offs_t offset) override;
@@ -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;
@@ -119,22 +119,22 @@ u32 poly_vti_device::screen_update(screen_device &screen, bitmap_ind16 &bitmap,
{
u8 r = b/5;
if (l==0 && r==0)
- bitmap.pix16(y*15+j, xpos+b ) = BIT(code,5) ? 0 : 1;
+ bitmap.pix(y*15+j, xpos+b ) = BIT(code,5) ? 0 : 1;
if (l==0 && r==1)
- bitmap.pix16(y*15+j, xpos+b ) = BIT(code,2) ? 0 : 1;
+ bitmap.pix(y*15+j, xpos+b ) = BIT(code,2) ? 0 : 1;
if (l==1 && r==0)
- bitmap.pix16(y*15+j, xpos+b ) = BIT(code,4) ? 0 : 1;
+ bitmap.pix(y*15+j, xpos+b ) = BIT(code,4) ? 0 : 1;
if (l==1 && r==1)
- bitmap.pix16(y*15+j, xpos+b ) = BIT(code,1) ? 0 : 1;
+ bitmap.pix(y*15+j, xpos+b ) = BIT(code,1) ? 0 : 1;
if (l==2 && r==0)
- bitmap.pix16(y*15+j, xpos+b ) = BIT(code,3) ? 0 : 1;
+ bitmap.pix(y*15+j, xpos+b ) = BIT(code,3) ? 0 : 1;
if (l==2 && r==1)
- bitmap.pix16(y*15+j, xpos+b ) = BIT(code,0) ? 0 : 1;
+ bitmap.pix(y*15+j, xpos+b ) = BIT(code,0) ? 0 : 1;
}
}
}
@@ -156,11 +156,11 @@ u32 poly_vti_device::screen_update(screen_device &screen, bitmap_ind16 &bitmap,
}
for (int b = 0; b < 7; b++)
- bitmap.pix16(y*15+j, xpos+b ) = (l >> (6-b)) & 1;
+ bitmap.pix(y*15+j, xpos+b ) = (l >> (6-b)) & 1;
- bitmap.pix16(y*15+j, xpos+7 ) = 0;
- bitmap.pix16(y*15+j, xpos+8 ) = 0;
- bitmap.pix16(y*15+j, xpos+9 ) = 0;
+ bitmap.pix(y*15+j, xpos+7 ) = 0;
+ bitmap.pix(y*15+j, xpos+8 ) = 0;
+ bitmap.pix(y*15+j, xpos+9 ) = 0;
}
}
xpos += 10;
@@ -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 23333ce500f..403c0e6e5b6 100644
--- a/src/devices/bus/s100/s100.cpp
+++ b/src/devices/bus/s100/s100.cpp
@@ -28,19 +28,24 @@ 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_slot_card_interface(mconfig, device),
- m_bus(nullptr),
- m_next(nullptr)
+ device_interface(device, "s100bus"),
+ m_bus(nullptr)
{
}
+void device_s100_card_interface::interface_pre_start()
+{
+ if (!m_bus)
+ throw device_missing_dependencies();
+}
+
//-------------------------------------------------
// s100_slot_device - constructor
//-------------------------------------------------
s100_slot_device::s100_slot_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) :
device_t(mconfig, S100_SLOT, tag, owner, clock),
- device_slot_interface(mconfig, *this),
+ device_single_card_slot_interface<device_s100_card_interface>(mconfig, *this),
m_bus(*this, DEVICE_SELF_OWNER)
{
}
@@ -52,8 +57,9 @@ s100_slot_device::s100_slot_device(const machine_config &mconfig, const char *ta
void s100_slot_device::device_start()
{
- device_s100_card_interface *dev = dynamic_cast<device_s100_card_interface *>(get_card_device());
- if (dev) m_bus->add_card(dev);
+ device_s100_card_interface *const dev = get_card_device();
+ if (dev)
+ m_bus->add_card(*dev);
}
@@ -83,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
@@ -90,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();
}
@@ -124,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);
}
@@ -139,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;
}
@@ -157,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);
}
@@ -175,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;
}
@@ -193,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 cbaefb802a4..13f895cf7a0 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>
@@ -75,14 +77,11 @@ class s100_bus_device;
// ======================> device_s100_card_interface
-class device_s100_card_interface : public device_slot_card_interface
+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) { }
@@ -122,10 +121,9 @@ protected:
// construction/destruction
device_s100_card_interface(const machine_config &mconfig, device_t &device);
- s100_bus_device *m_bus;
+ virtual void interface_pre_start() override;
-private:
- device_s100_card_interface *m_next;
+ s100_bus_device *m_bus;
};
@@ -137,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(); }
@@ -157,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);
@@ -165,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
- virtual void device_start() override;
- virtual void device_reset() override;
+ // device_t implementation
+ virtual void device_start() override ATTR_COLD;
+ virtual void device_reset() override ATTR_COLD;
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;
@@ -207,13 +207,13 @@ 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;
};
// ======================> s100_slot_device
-class s100_slot_device : public device_t, public device_slot_interface
+class s100_slot_device : public device_t, public device_single_card_slot_interface<device_s100_card_interface>
{
public:
// construction/destruction
@@ -228,9 +228,11 @@ public:
}
s100_slot_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
+ template <typename T> void set_bus(T &&tag) { m_bus.set_tag(std::forward<T>(tag)); }
+
protected:
// device-level overrides
- virtual void device_start() override;
+ virtual void device_start() override ATTR_COLD;
private:
required_device<s100_bus_device> m_bus;
diff --git a/src/devices/bus/s100/seals8k.cpp b/src/devices/bus/s100/seals8k.cpp
index 949c7d6d2c5..e5aa23623ec 100644
--- a/src/devices/bus/s100/seals8k.cpp
+++ b/src/devices/bus/s100/seals8k.cpp
@@ -47,8 +47,8 @@ protected:
s100_8k_sc_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, u32 clock);
// device-specific overrides
- virtual ioport_constructor device_input_ports() const override;
- virtual void device_start() override;
+ virtual ioport_constructor device_input_ports() const override ATTR_COLD;
+ virtual void device_start() override ATTR_COLD;
// S-100 memory access handlers
virtual u8 s100_smemr_r(offs_t offset) override;
@@ -75,8 +75,8 @@ public:
protected:
// device_nvram_interface overrides
- virtual void nvram_read(emu_file &file) override;
- virtual void nvram_write(emu_file &file) override;
+ virtual bool nvram_read(util::read_stream &file) override;
+ virtual bool nvram_write(util::write_stream &file) override;
virtual void nvram_default() override;
};
@@ -162,9 +162,10 @@ void s100_8k_sc_device::device_start()
// nvram_read - read NVRAM from the file
//-------------------------------------------------
-void s100_8k_sc_bb_device::nvram_read(emu_file &file)
+bool s100_8k_sc_bb_device::nvram_read(util::read_stream &file)
{
- file.read(m_ram.get(), 0x2000);
+ auto const [err, actual] = read(file, m_ram.get(), 0x2000);
+ return !err && (actual == 0x2000);
}
@@ -172,9 +173,10 @@ void s100_8k_sc_bb_device::nvram_read(emu_file &file)
// nvram_write - write NVRAM to the file
//-------------------------------------------------
-void s100_8k_sc_bb_device::nvram_write(emu_file &file)
+bool s100_8k_sc_bb_device::nvram_write(util::write_stream &file)
{
- file.write(m_ram.get(), 0x2000);
+ auto const [err, actual] = write(file, m_ram.get(), 0x2000);
+ return !err;
}
diff --git a/src/devices/bus/s100/seals8k.h b/src/devices/bus/s100/seals8k.h
index 8d12cc6de9d..fc4020e7e15 100644
--- a/src/devices/bus/s100/seals8k.h
+++ b/src/devices/bus/s100/seals8k.h
@@ -6,8 +6,8 @@
**********************************************************************/
-#ifndef MAME_BUS_S100_8K_SC_H
-#define MAME_BUS_S100_8K_SC_H
+#ifndef MAME_BUS_S100_SEALS8K_H
+#define MAME_BUS_S100_SEALS8K_H
#pragma once
@@ -16,4 +16,4 @@
DECLARE_DEVICE_TYPE(S100_8K_SC, device_s100_card_interface)
DECLARE_DEVICE_TYPE(S100_8K_SC_BB, device_s100_card_interface)
-#endif // MAME_BUS_S100_8K_SC_H
+#endif // MAME_BUS_S100_SEALS8K_H
diff --git a/src/devices/bus/s100/vectordualmode.cpp b/src/devices/bus/s100/vectordualmode.cpp
new file mode 100644
index 00000000000..fbf66d0d06e
--- /dev/null
+++ b/src/devices/bus/s100/vectordualmode.cpp
@@ -0,0 +1,358 @@
+// 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_fdd_sector_counter(0xf)
+ , m_read(false)
+ , m_busy(false)
+ , m_last_sector_pulse(attotime::zero)
+ , m_pll()
+ , m_byte_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);
+ }
+ m_byte_timer->enable(false);
+ m_busy = false;
+}
+
+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)
+{
+ if (m_busy)
+ return 0xff;
+ // 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_busy; // returned early if true
+ 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)
+{
+ if (m_busy)
+ 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);
+ flop->setup_index_pulse_cb(floppy_image_device::index_pulse_cb(&s100_vector_dualmode_device::floppy_index_cb, this));
+ }
+ } 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
+ m_busy = m_motor_on_timer->enabled();
+ }
+}
+
+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;
+}
+
+void s100_vector_dualmode_device::floppy_index_cb(floppy_image_device *floppy, int state)
+{
+ if (hdd_selected() || m_floppy[m_drive]->get_device() != floppy)
+ return;
+ if (!state)
+ return;
+ attotime now = machine().time();
+ // U25 74LS221: 61.9 KOhm * .22 uF * .75
+ if (now - m_last_sector_pulse < attotime::from_nsec(10213500)) {
+ m_fdd_sector_counter = 0xf;
+ } else {
+ m_last_sector_pulse = now;
+ m_fdd_sector_counter++;
+ m_fdd_sector_counter &= 0xf;
+ start_of_sector();
+ }
+}
+
+void s100_vector_dualmode_device::start_of_sector()
+{
+ if (!m_busy)
+ return;
+
+ if (m_byte_timer->enabled()) {
+ // op completed
+ m_byte_timer->enable(false);
+ m_busy = false;
+ if (m_read)
+ m_ram[274] = 0; // Ignore ECC
+ return;
+ }
+
+ uint8_t cur_sector = m_fdd_sector_counter;
+ if (cur_sector == m_sector) {
+ 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);
+ }
+ }
+}
+
+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);
+
+ for (auto& f : m_floppy) {
+ if (f->get_device())
+ f->get_device()->setup_index_pulse_cb(floppy_image_device::index_pulse_cb(&s100_vector_dualmode_device::floppy_index_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_fdd_sector_counter));
+ save_item(NAME(m_read));
+ save_item(NAME(m_busy));
+ save_item(NAME(m_last_sector_pulse));
+ 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);
+ m_floppy[0]->set_sectoring_type(floppy_image::H16);
+ FLOPPY_CONNECTOR(config, m_floppy[1], vector4_floppies, "525", vector4_formats).enable_sound(true);
+ m_floppy[1]->set_sectoring_type(floppy_image::H16);
+ FLOPPY_CONNECTOR(config, m_floppy[2], vector4_floppies, "525", vector4_formats).enable_sound(true);
+ m_floppy[2]->set_sectoring_type(floppy_image::H16);
+ FLOPPY_CONNECTOR(config, m_floppy[3], vector4_floppies, "525", vector4_formats).enable_sound(true);
+ m_floppy[3]->set_sectoring_type(floppy_image::H16);
+}
+
+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..c2d3ecd8ad5
--- /dev/null
+++ b/src/devices/bus/s100/vectordualmode.h
@@ -0,0 +1,54 @@
+// 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 ATTR_COLD;
+ void device_reset() override ATTR_COLD;
+ 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(byte_cb);
+ bool hdd_selected();
+ bool get_next_bit(attotime &tm, const attotime &limit);
+ void floppy_index_cb(floppy_image_device *floppy, int state);
+ void start_of_sector();
+
+ 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;
+ uint8_t m_fdd_sector_counter;
+ bool m_read;
+ bool m_busy;
+ emu_timer *m_motor_on_timer;
+ attotime m_last_sector_pulse; // fdd
+
+ fdc_pll_t m_pll;
+ emu_timer *m_byte_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 64eb9638d74..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);
}
@@ -61,7 +61,6 @@ WRITE_LINE_MEMBER( s100_wunderbus_device::pic_int_w )
static DEVICE_INPUT_DEFAULTS_START( terminal )
DEVICE_INPUT_DEFAULTS( "RS232_TXBAUD", 0xff, RS232_BAUD_110 )
DEVICE_INPUT_DEFAULTS( "RS232_RXBAUD", 0xff, RS232_BAUD_110 )
- DEVICE_INPUT_DEFAULTS( "RS232_STARTBITS", 0xff, RS232_STARTBITS_1 )
DEVICE_INPUT_DEFAULTS( "RS232_DATABITS", 0xff, RS232_DATABITS_8 )
DEVICE_INPUT_DEFAULTS( "RS232_PARITY", 0xff, RS232_PARITY_NONE )
DEVICE_INPUT_DEFAULTS( "RS232_STOPBITS", 0xff, RS232_STOPBITS_2 )
@@ -72,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..69be1df1fc1 100644
--- a/src/devices/bus/s100/wunderbus.h
+++ b/src/devices/bus/s100/wunderbus.h
@@ -33,12 +33,12 @@ public:
protected:
// device-level overrides
- virtual void device_start() override;
- virtual void device_reset() override;
+ virtual void device_start() override ATTR_COLD;
+ virtual void device_reset() override ATTR_COLD;
// optional information overrides
- virtual void device_add_mconfig(machine_config &config) override;
- virtual ioport_constructor device_input_ports() const override;
+ virtual void device_add_mconfig(machine_config &config) override ATTR_COLD;
+ virtual ioport_constructor device_input_ports() const override ATTR_COLD;
// device_s100_card_interface overrides
virtual void s100_vi0_w(int state) override;
@@ -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
new file mode 100644
index 00000000000..a226a8ffafc
--- /dev/null
+++ b/src/devices/bus/saitek_osa/expansion.cpp
@@ -0,0 +1,167 @@
+// 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"
+
+#include "maestro.h"
+#include "maestroa.h"
+#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
+//-------------------------------------------------
+
+saitekosa_expansion_device::saitekosa_expansion_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock) :
+ device_t(mconfig, SAITEKOSA_EXPANSION, tag, owner, clock),
+ device_single_card_slot_interface<device_saitekosa_expansion_interface>(mconfig, *this),
+ m_stb_handler(*this),
+ m_rts_handler(*this),
+ m_module(nullptr)
+{ }
+
+//-------------------------------------------------
+// saitekosa_expansion_device - destructor
+//-------------------------------------------------
+
+saitekosa_expansion_device::~saitekosa_expansion_device()
+{
+}
+
+//-------------------------------------------------
+// device_start - device-specific startup
+//-------------------------------------------------
+
+void saitekosa_expansion_device::device_start()
+{
+ // get inserted module
+ m_module = get_card_device();
+
+ // register for savestates
+ save_item(NAME(m_data));
+ save_item(NAME(m_nmi));
+ save_item(NAME(m_ack));
+}
+
+//-------------------------------------------------
+// device_add_mconfig - add device configuration
+//-------------------------------------------------
+
+void saitekosa_expansion_device::device_add_mconfig(machine_config &config)
+{
+ // optional embedded screen
+ auto &screen(SCREEN(config, "screen", SCREEN_TYPE_LCD));
+ screen.set_refresh_hz(60);
+ screen.set_size(6 * 16 + 3, 16);
+ screen.set_visarea_full();
+ screen.set_screen_update(FUNC(saitekosa_expansion_device::screen_update));
+}
+
+//-------------------------------------------------
+// host to module interface
+//-------------------------------------------------
+
+u8 saitekosa_expansion_device::data_r()
+{
+ if (m_module)
+ return m_module->data_r();
+
+ return 0xff;
+}
+
+void saitekosa_expansion_device::data_w(u8 data)
+{
+ if (m_module)
+ m_module->data_w(data);
+
+ m_data = data;
+}
+
+void saitekosa_expansion_device::nmi_w(int state)
+{
+ state = (state) ? 1 : 0;
+
+ if (m_module)
+ m_module->nmi_w(state);
+
+ m_nmi = state;
+}
+
+void saitekosa_expansion_device::ack_w(int state)
+{
+ state = (state) ? 1 : 0;
+
+ if (m_module)
+ m_module->ack_w(state);
+
+ m_ack = state;
+}
+
+void saitekosa_expansion_device::pw_w(int state)
+{
+ state = (state) ? 1 : 0;
+
+ if (m_module)
+ m_module->pw_w(state);
+
+ m_pw = state;
+}
+
+u32 saitekosa_expansion_device::screen_update(screen_device &screen, bitmap_rgb32 &bitmap, const rectangle &cliprect)
+{
+ return (m_module) ? m_module->screen_update(screen, bitmap, cliprect) : 0;
+}
+
+
+//******************************************************************************
+// MODULE INTERFACE
+//******************************************************************************
+
+//-------------------------------------------------
+// device_saitekosa_expansion_interface - constructor
+//-------------------------------------------------
+
+device_saitekosa_expansion_interface::device_saitekosa_expansion_interface(const machine_config &mconfig, device_t &device) :
+ device_interface(device, "saitekosaexp")
+{
+ m_expansion = dynamic_cast<saitekosa_expansion_device *>(device.owner());
+}
+
+//-------------------------------------------------
+// ~device_saitekosa_expansion_interface - destructor
+//-------------------------------------------------
+
+device_saitekosa_expansion_interface::~device_saitekosa_expansion_interface()
+{
+}
+
+//-------------------------------------------------
+// module list
+//-------------------------------------------------
+
+void saitekosa_expansion_modules(device_slot_interface &device)
+{
+ device.option_add("analyst", OSA_ANALYST);
+ device.option_add("maestro", OSA_MAESTRO);
+ device.option_add("maestroa", OSA_MAESTROA);
+ device.option_add("sparc", OSA_SPARC);
+}
diff --git a/src/devices/bus/saitek_osa/expansion.h b/src/devices/bus/saitek_osa/expansion.h
new file mode 100644
index 00000000000..3646e663bad
--- /dev/null
+++ b/src/devices/bus/saitek_osa/expansion.h
@@ -0,0 +1,126 @@
+// license:BSD-3-Clause
+// copyright-holders:Dirk Best, hap
+/*******************************************************************************
+
+ Saitek OSA Expansion Slot
+
+ 15-pin slot "PIO"
+
+ STB-P <
+ D0 <>
+ D1 <>
+ D2 <>
+ D3 <>
+ D4 <>
+ D5 <>
+ D6 <>
+ D7 <>
+ ACK-P >
+ RTS-P <
+ PW >
+ GND >
+ NMI-P >
+ V+ >
+
+*******************************************************************************/
+
+#ifndef MAME_BUS_SAITEK_OSA_EXPANSION_H
+#define MAME_BUS_SAITEK_OSA_EXPANSION_H
+
+#pragma once
+
+#include "screen.h"
+
+DECLARE_DEVICE_TYPE(SAITEKOSA_EXPANSION, saitekosa_expansion_device)
+
+
+//******************************************************************************
+// TYPE DEFINITIONS
+//******************************************************************************
+
+class device_saitekosa_expansion_interface;
+
+// ======================> saitekosa_expansion_device
+
+class saitekosa_expansion_device : public device_t, public device_single_card_slot_interface<device_saitekosa_expansion_interface>
+{
+public:
+ // construction/destruction
+ template <typename T>
+ saitekosa_expansion_device(machine_config const &mconfig, char const *tag, device_t *owner, T &&opts) :
+ saitekosa_expansion_device(mconfig, tag, owner, u32(0))
+ {
+ option_reset();
+ opts(*this);
+ set_default_option(nullptr);
+ set_fixed(false);
+ }
+
+ saitekosa_expansion_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock);
+ virtual ~saitekosa_expansion_device();
+
+ // callbacks
+ auto stb_handler() { return m_stb_handler.bind(); }
+ auto rts_handler() { return m_rts_handler.bind(); }
+
+ // called from module device
+ void stb_w(int state) { m_stb_handler(state); }
+ void rts_w(int state) { m_rts_handler(state); }
+
+ u8 data_state() { return m_data; }
+ int nmi_state() { return m_nmi; }
+ int ack_state() { return m_ack; }
+ int pw_state() { return m_pw; }
+
+ // called from host
+ u8 data_r();
+ void data_w(u8 data);
+ void nmi_w(int state);
+ void ack_w(int state);
+ void pw_w(int state);
+
+protected:
+ // device-level overrides
+ virtual void device_start() override ATTR_COLD;
+ virtual void device_add_mconfig(machine_config &config) override ATTR_COLD;
+
+private:
+ devcb_write_line m_stb_handler;
+ devcb_write_line m_rts_handler;
+
+ // input pins state
+ u8 m_data = 0;
+ int m_nmi = 0;
+ int m_ack = 0;
+ 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
+
+class device_saitekosa_expansion_interface : public device_interface
+{
+public:
+ // construction/destruction
+ virtual ~device_saitekosa_expansion_interface();
+
+ virtual u8 data_r() { return 0xff; }
+ virtual void data_w(u8 data) { }
+ virtual void nmi_w(int state) { }
+ virtual void ack_w(int state) { }
+ virtual void pw_w(int state) { }
+
+ virtual u32 screen_update(screen_device &screen, bitmap_rgb32 &bitmap, const rectangle &cliprect) { return 0; }
+
+protected:
+ device_saitekosa_expansion_interface(const machine_config &mconfig, device_t &device);
+
+ saitekosa_expansion_device *m_expansion;
+};
+
+void saitekosa_expansion_modules(device_slot_interface &device);
+
+#endif // MAME_BUS_SAITEK_OSA_EXPANSION_H
diff --git a/src/devices/bus/saitek_osa/maestro.cpp b/src/devices/bus/saitek_osa/maestro.cpp
new file mode 100644
index 00000000000..971daa32e0b
--- /dev/null
+++ b/src/devices/bus/saitek_osa/maestro.cpp
@@ -0,0 +1,436 @@
+// 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.*
+
+The hardware and chess engine is similar to the Stratos/Turbo King series.
+
+Version B is compatible with the 1st EGR expansion ROM, version C/D uses
+EGR II. Versions D+ and D++ are post-production improvements, they were not
+sold officially.
+
+Hardware notes:
+- CPU: see notes below
+- 64KB ROM (2*27C256)
+- 16KB RAM (2*HY62C64P-70), one of them is optional
+- 1 ROM socket for EGR expansion ROM
+
+Analyst adds a HD44780A00H and a small 16-char LCD screen.
+
+Both were sold at 4MHz, 6MHz, 8MHz speeds, Maestro also had a 10MHz version.
+CPUs used were: R65C02P4, RP65C02F, W65C02P-8. In almost all cases with the
+higher speed versions, they overclocked the CPU. And if the CPU couldn't
+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"
+
+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 ATTR_COLD;
+ virtual ioport_constructor device_input_ports() const override ATTR_COLD;
+ 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;
+
+ 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) ATTR_COLD;
+
+ 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),
+ m_maincpu(*this, "maincpu"),
+ m_banked_ram(*this, "banked_ram", 0x2000, ENDIANNESS_LITTLE),
+ m_rambank(*this, "rambank"),
+ m_rombank(*this, "rombank"),
+ m_extrom(*this, "extrom")
+{ }
+
+saitekosa_maestro_device::saitekosa_maestro_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock) :
+ 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 ATTR_COLD;
+ virtual void device_add_mconfig(machine_config &config) override ATTR_COLD;
+
+private:
+ required_device<hd44780_device> m_lcd;
+
+ virtual void main_map(address_map &map) override ATTR_COLD;
+};
+
+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
+ m_rombank->configure_entries(0, 2, memregion("maincpu")->base(), 0x8000);
+ m_rambank->configure_entries(0, 2, m_banked_ram, 0x1000);
+
+ // register for savestates
+ save_item(NAME(m_latch_enable));
+ save_item(NAME(m_latch));
+ save_item(NAME(m_extrom_bank));
+}
+
+void saitekosa_maestro_device::device_reset()
+{
+ control_w(0);
+}
+
+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[newval % 6]);
+}
+
+
+//-------------------------------------------------
+// host i/o
+//-------------------------------------------------
+
+u8 saitekosa_maestro_device::data_r()
+{
+ return m_latch_enable ? m_latch : 0xff;
+}
+
+void saitekosa_maestro_device::nmi_w(int state)
+{
+ m_maincpu->set_input_line(0, !state ? ASSERT_LINE : CLEAR_LINE);
+}
+
+void saitekosa_maestro_device::ack_w(int state)
+{
+ if (state != m_expansion->ack_state())
+ machine().scheduler().perfect_quantum(attotime::from_usec(100));
+}
+
+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;
+ }
+
+ return 0;
+}
+
+
+//-------------------------------------------------
+// internal i/o
+//-------------------------------------------------
+
+u8 saitekosa_maestro_device::extrom_r(offs_t offset)
+{
+ u16 bank = m_extrom_bank * 0x4000;
+ return (m_extrom->exists()) ? m_extrom->read_rom(offset | bank) : 0xff;
+}
+
+template <int N> void saitekosa_maestro_device::stall_w(u8 data)
+{
+ // cpu clock divider
+}
+
+u8 saitekosa_maestro_device::rts_r()
+{
+ if (!machine().side_effects_disabled())
+ {
+ // strobe RTS-P
+ m_expansion->rts_w(1);
+ m_expansion->rts_w(0);
+ }
+
+ return 0xff;
+}
+
+void saitekosa_maestro_device::xdata_w(u8 data)
+{
+ // clock latch
+ m_latch = data;
+}
+
+u8 saitekosa_maestro_device::xdata_r()
+{
+ return m_expansion->data_state();
+}
+
+void saitekosa_maestro_device::control_w(u8 data)
+{
+ // d0: main rom bank
+ m_rombank->set_entry(data & 1);
+
+ // d1: ext rom bank
+ // d1: ram bank
+ m_extrom_bank = BIT(data, 1);
+ m_rambank->set_entry(m_extrom_bank);
+
+ // d3: enable latch output
+ m_latch_enable = bool(data & 8);
+
+ // d2: STB-P
+ m_expansion->stb_w(BIT(data, 2));
+}
+
+u8 saitekosa_maestro_device::ack_r()
+{
+ // d6: _Vcc
+ // d7: ACK-P
+ return m_expansion->ack_state() ? 0x80 : 0x00;
+}
+
+void saitekosa_maestro_device::main_map(address_map &map)
+{
+ map(0x0000, 0x1fff).ram();
+ map(0x2000, 0x2000).mirror(0x01ff).w(FUNC(saitekosa_maestro_device::stall_w<0>));
+ map(0x2200, 0x2200).mirror(0x01ff).rw(FUNC(saitekosa_maestro_device::rts_r), FUNC(saitekosa_maestro_device::stall_w<1>));
+ map(0x2400, 0x2400).mirror(0x01ff).rw(FUNC(saitekosa_maestro_device::xdata_r), FUNC(saitekosa_maestro_device::xdata_w));
+ map(0x2600, 0x2600).mirror(0x01ff).rw(FUNC(saitekosa_maestro_device::ack_r), FUNC(saitekosa_maestro_device::control_w));
+ map(0x2800, 0x37ff).bankrw("rambank");
+ map(0x4000, 0x7fff).r(FUNC(saitekosa_maestro_device::extrom_r));
+ map(0x8000, 0xffff).bankr("rombank");
+}
+
+void saitekosa_analyst_device::main_map(address_map &map)
+{
+ saitekosa_maestro_device::main_map(map);
+ map(0x3800, 0x3801).mirror(0x07fe).rw(m_lcd, FUNC(hd44780_device::read), FUNC(hd44780_device::write));
+}
+
+
+//-------------------------------------------------
+// input_ports - device-specific input ports
+//-------------------------------------------------
+
+static INPUT_PORTS_START( maestro )
+ PORT_START("CPU")
+ PORT_CONFNAME( 0x07, 0x04, "CPU Frequency" ) PORT_CHANGED_MEMBER(DEVICE_SELF, FUNC(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 INPUT_PORTS_NAME(maestro);
+}
+
+
+//-------------------------------------------------
+// device_add_mconfig - add device configuration
+//-------------------------------------------------
+
+void saitekosa_maestro_device::device_add_mconfig(machine_config &config)
+{
+ // 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_analyst_device::device_add_mconfig(machine_config &config)
+{
+ saitekosa_maestro_device::device_add_mconfig(config);
+
+ // video hardware
+ HD44780(config, m_lcd, 270'000); // OSC = 91K resistor
+}
+
+
+//-------------------------------------------------
+// rom_region - device-specific ROM region
+//-------------------------------------------------
+
+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))
+
+ ROM_SYSTEM_BIOS(2, "b3", "Maestro B (set 3)")
+ ROMX_LOAD("m6c_530_u2.u2", 0x0000, 0x8000, CRC(a8be85d8) SHA1(a7fb2b6a185bd5b355b3ba78439332a25c456773), ROM_BIOS(2))
+ ROMX_LOAD("b6c_528a_u3.u3", 0x8000, 0x8000, CRC(c03dfe60) SHA1(efbc9abd5e93f51d5c49376c3fd7c87ee4ede82b), ROM_BIOS(2))
+
+ // C (C and above are shared Maestro/Analyst)
+ ROM_SYSTEM_BIOS(3, "c1", "Maestro C (set 1)")
+ ROMX_LOAD("m6l_b30d_u2.u2", 0x0000, 0x8000, CRC(bb10e15c) SHA1(7b0fb987c49da76a03b46c80d2b4eacaa785ee75), ROM_BIOS(3))
+ ROMX_LOAD("b6c_721_u3.u3", 0x8000, 0x8000, CRC(b1e57023) SHA1(6cec5cdc0bf4f8ac88afb0397fcb4738136b0431), ROM_BIOS(3))
+
+ ROM_SYSTEM_BIOS(4, "c2", "Maestro C (set 2)")
+ ROMX_LOAD("m6l_b30b_u2.u2", 0x0000, 0x8000, CRC(4b5026d7) SHA1(9715a0220c1bd3456480104f1c7ae61cbf1a1d73), ROM_BIOS(4))
+ ROMX_LOAD("b6c_721_u3.u3", 0x8000, 0x8000, CRC(b1e57023) SHA1(6cec5cdc0bf4f8ac88afb0397fcb4738136b0431), ROM_BIOS(4))
+
+ ROM_SYSTEM_BIOS(5, "c3", "Maestro C (set 3)")
+ ROMX_LOAD("m6l_b25_u2.u2", 0x0000, 0x8000, CRC(217ae56c) SHA1(27ec80d0f82723c2710e2ccb477705934a4c2119), ROM_BIOS(5))
+ ROMX_LOAD("b6c_721_u3.u3", 0x8000, 0x8000, CRC(b1e57023) SHA1(6cec5cdc0bf4f8ac88afb0397fcb4738136b0431), ROM_BIOS(5))
+
+ // D
+ ROM_SYSTEM_BIOS(6, "d1", "Maestro D (set 1)")
+ ROMX_LOAD("ma3_714a_u2.u2", 0x0000, 0x8000, CRC(435e1e30) SHA1(0d82df7c40443cb341dacebdf65f33c3e03bce70), ROM_BIOS(6))
+ ROMX_LOAD("b6m_b15_u3.u3", 0x8000, 0x8000, CRC(6155de90) SHA1(bb5cdf061dde2d1dc7925d455891c3ade1d274e3), ROM_BIOS(6))
+
+ ROM_SYSTEM_BIOS(7, "d2", "Maestro D (set 2)")
+ ROMX_LOAD("ma3_714a_u2.u2", 0x0000, 0x8000, CRC(435e1e30) SHA1(0d82df7c40443cb341dacebdf65f33c3e03bce70), ROM_BIOS(7))
+ ROMX_LOAD("b6m_629_u3.u3", 0x8000, 0x8000, CRC(15e7b1f1) SHA1(d2a757114f13c6141d74a15671aa06b675304b4a), ROM_BIOS(7))
+
+ // D+
+ ROM_SYSTEM_BIOS(8, "dp", "Maestro D+")
+ ROMX_LOAD("m6m_625_u2.u2", 0x0000, 0x8000, CRC(aa7b5cfd) SHA1(e909108fdace633a519fecf0b9876fe6a46b2067), ROM_BIOS(8))
+ ROMX_LOAD("b6m_614_u3.u3", 0x8000, 0x8000, CRC(eff75543) SHA1(d7c1b3824bc87d5ffada6f5c8c72a8b292ff3d46), ROM_BIOS(8))
+
+ // D++
+ ROM_SYSTEM_BIOS(9, "dpp", "Maestro D++")
+ ROMX_LOAD("d++_u2.u2", 0x0000, 0x8000, CRC(48ef032c) SHA1(d336cb2096780b4d3bcceda0d2ed1246e780cd8d), ROM_BIOS(9))
+ ROMX_LOAD("b6m_614_u3.u3", 0x8000, 0x8000, CRC(eff75543) SHA1(d7c1b3824bc87d5ffada6f5c8c72a8b292ff3d46), ROM_BIOS(9))
+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
new file mode 100644
index 00000000000..a3440416c7a
--- /dev/null
+++ b/src/devices/bus/saitek_osa/maestro.h
@@ -0,0 +1,19 @@
+// license:BSD-3-Clause
+// copyright-holders:hap
+/*******************************************************************************
+
+ Saitek OSA Module: Kasparov Maestro/Analyst
+
+*******************************************************************************/
+
+#ifndef MAME_BUS_SAITEK_OSA_MAESTRO_H
+#define MAME_BUS_SAITEK_OSA_MAESTRO_H
+
+#pragma once
+
+#include "expansion.h"
+
+DECLARE_DEVICE_TYPE(OSA_MAESTRO, device_saitekosa_expansion_interface)
+DECLARE_DEVICE_TYPE(OSA_ANALYST, device_saitekosa_expansion_interface)
+
+#endif // MAME_BUS_SAITEK_OSA_MAESTRO_H
diff --git a/src/devices/bus/saitek_osa/maestroa.cpp b/src/devices/bus/saitek_osa/maestroa.cpp
new file mode 100644
index 00000000000..866fcabf201
--- /dev/null
+++ b/src/devices/bus/saitek_osa/maestroa.cpp
@@ -0,0 +1,230 @@
+// license:BSD-3-Clause
+// copyright-holders:hap
+// thanks-to:Berger
+/*******************************************************************************
+
+Saitek OSA Module: Kasparov Maestro A (SciSys, 1986)
+
+The chess engine revision is in-between Kaplan's Stratos and Turbostar.
+
+Hardware notes:
+- PCB label: M6L-PE-012 REV.2
+- R65C02P4 @ 4MHz / 5.67MHz / 6MHz
+- 32KB ROM (D27C256)
+- 8KB RAM (HM6264LP-15)
+- 3 more sockets, one for KSO expansion ROM, 2 unused
+
+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"
+
+#include "bus/generic/slot.h"
+#include "bus/generic/carts.h"
+#include "cpu/m6502/r65c02.h"
+
+#include "softlist_dev.h"
+
+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 ATTR_COLD;
+ virtual ioport_constructor device_input_ports() const override ATTR_COLD;
+ 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:
+ required_device<cpu_device> m_maincpu;
+
+ u8 m_latch = 0xff;
+ bool m_latch_enable = false;
+
+ void main_map(address_map &map) ATTR_COLD;
+
+ 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),
+ m_maincpu(*this, "maincpu")
+{ }
+
+void saitekosa_maestroa_device::device_start()
+{
+ save_item(NAME(m_latch_enable));
+ save_item(NAME(m_latch));
+}
+
+void saitekosa_maestroa_device::device_reset()
+{
+ control_w(0);
+}
+
+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[newval % 3]);
+}
+
+
+//-------------------------------------------------
+// host i/o
+//-------------------------------------------------
+
+u8 saitekosa_maestroa_device::data_r()
+{
+ return m_latch_enable ? m_latch : 0xff;
+}
+
+void saitekosa_maestroa_device::nmi_w(int state)
+{
+ m_maincpu->set_input_line(INPUT_LINE_NMI, !state ? ASSERT_LINE : CLEAR_LINE);
+}
+
+void saitekosa_maestroa_device::ack_w(int state)
+{
+ if (state != m_expansion->ack_state())
+ machine().scheduler().perfect_quantum(attotime::from_usec(100));
+}
+
+
+//-------------------------------------------------
+// internal i/o
+//-------------------------------------------------
+
+u8 saitekosa_maestroa_device::rts_r()
+{
+ if (!machine().side_effects_disabled())
+ {
+ // strobe RTS-P
+ m_expansion->rts_w(1);
+ m_expansion->rts_w(0);
+ }
+
+ return 0xff;
+}
+
+void saitekosa_maestroa_device::xdata_w(u8 data)
+{
+ // clock latch
+ m_latch = data;
+}
+
+u8 saitekosa_maestroa_device::xdata_r()
+{
+ return m_expansion->data_state();
+}
+
+void saitekosa_maestroa_device::control_w(u8 data)
+{
+ // d3: enable latch output
+ m_latch_enable = bool(data & 8);
+
+ // d2: STB-P
+ m_expansion->stb_w(BIT(data, 2));
+}
+
+u8 saitekosa_maestroa_device::ack_r()
+{
+ // d7: ACK-P
+ return m_expansion->ack_state() ? 0x80 : 0;
+}
+
+void saitekosa_maestroa_device::main_map(address_map &map)
+{
+ map.unmap_value_high();
+ map(0x0000, 0x1fff).ram();
+ map(0x2200, 0x2200).mirror(0x01ff).r(FUNC(saitekosa_maestroa_device::rts_r));
+ map(0x2400, 0x2400).mirror(0x01ff).rw(FUNC(saitekosa_maestroa_device::xdata_r), FUNC(saitekosa_maestroa_device::xdata_w));
+ map(0x2600, 0x2600).mirror(0x01ff).rw(FUNC(saitekosa_maestroa_device::ack_r), FUNC(saitekosa_maestroa_device::control_w));
+ map(0x4000, 0x5fff).r("extrom", FUNC(generic_slot_device::read_rom));
+ map(0x8000, 0xffff).rom();
+}
+
+
+//-------------------------------------------------
+// input_ports - device-specific input ports
+//-------------------------------------------------
+
+static INPUT_PORTS_START( maestroa )
+ PORT_START("CPU")
+ PORT_CONFNAME( 0x03, 0x02, "CPU Frequency" ) PORT_CHANGED_MEMBER(DEVICE_SELF, FUNC(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 INPUT_PORTS_NAME(maestroa);
+}
+
+
+//-------------------------------------------------
+// device_add_mconfig - add device configuration
+//-------------------------------------------------
+
+void saitekosa_maestroa_device::device_add_mconfig(machine_config &config)
+{
+ // 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");
+}
+
+
+//-------------------------------------------------
+// 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
+{
+ 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
new file mode 100644
index 00000000000..9ce0909040d
--- /dev/null
+++ b/src/devices/bus/saitek_osa/maestroa.h
@@ -0,0 +1,18 @@
+// license:BSD-3-Clause
+// copyright-holders:hap
+/*******************************************************************************
+
+ Saitek OSA Module: Kasparov Maestro A
+
+*******************************************************************************/
+
+#ifndef MAME_BUS_SAITEK_OSA_MAESTROA_H
+#define MAME_BUS_SAITEK_OSA_MAESTROA_H
+
+#pragma once
+
+#include "expansion.h"
+
+DECLARE_DEVICE_TYPE(OSA_MAESTROA, device_saitekosa_expansion_interface)
+
+#endif // MAME_BUS_SAITEK_OSA_MAESTROA_H
diff --git a/src/devices/bus/saitek_osa/sparc.cpp b/src/devices/bus/saitek_osa/sparc.cpp
new file mode 100644
index 00000000000..82f4e04a005
--- /dev/null
+++ b/src/devices/bus/saitek_osa/sparc.cpp
@@ -0,0 +1,237 @@
+// license:BSD-3-Clause
+// copyright-holders:hap
+// thanks-to:Berger
+/*******************************************************************************
+
+Saitek OSA Module: Kasparov Sparc (1993)
+
+The chess engine is by the Spracklen's. Their last, and also their strongest.
+
+Hardware notes:
+- Fujitsu MB86930-20 SPARClite @ 20MHz
+- 256KB ROM (4*AMD AM27C512)
+- 1MB DRAM (8*NEC 424256-60), expandable to 4MB
+- ESAN 31A-5500 delay line (only on newer PCB)
+
+Two PCB revisions are known, the older one is a lighter green PCB, it has
+empty positions for more ICs (maybe expanded RAM?), and does not have a
+delay line chip.
+
+The module doesn't have its own LCD screen. It has a grill+fan underneath
+at the front part, and a heatsink on the CPU.
+
+About expanded RAM: The 4MB expansion mentioned in the manual works well,
+but it doesn't look like the software was designed to work with other options.
+At 2MB it doesn't work at all. At 8MB or 16MB it becomes very inefficient,
+only using 5MB or 9MB of the available RAM for hash tables.
+
+TODO:
+- runs too slow? solving mate problems is around 60% slower than real device,
+ 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"
+
+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 ATTR_COLD;
+ virtual ioport_constructor device_input_ports() const override ATTR_COLD;
+ 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:
+ 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) ATTR_COLD;
+
+ 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),
+ m_maincpu(*this, "maincpu"),
+ m_rom(*this, "maincpu"),
+ m_ram(*this, "ram")
+{ }
+
+void saitekosa_sparc_device::device_start()
+{
+ m_rom_mask = m_rom.length() - 1;
+ set_ram_mask(20); // 1MB default
+
+ // register for savestates
+ save_item(NAME(m_data_out));
+ save_item(NAME(m_rom_mask));
+ save_item(NAME(m_ram_mask));
+ save_item(NAME(m_installed));
+}
+
+void saitekosa_sparc_device::device_reset()
+{
+ if (!m_installed)
+ {
+ // MAME doesn't allow reading ioport at device_start
+ set_ram_mask(ioport("RAM")->read() ? 22 : 20);
+ m_installed = true;
+ }
+
+ host_io_w(0, 0x1c00);
+}
+
+
+//-------------------------------------------------
+// host i/o
+//-------------------------------------------------
+
+u8 saitekosa_sparc_device::data_r()
+{
+ return (m_data_out & 0x400) ? 0xff : (u8)m_data_out;
+}
+
+void saitekosa_sparc_device::nmi_w(int state)
+{
+ m_maincpu->set_input_line(SPARC_IRQ1, !state ? ASSERT_LINE : CLEAR_LINE);
+}
+
+void saitekosa_sparc_device::ack_w(int state)
+{
+ if (state != m_expansion->ack_state())
+ machine().scheduler().perfect_quantum(attotime::from_usec(100));
+}
+
+
+//-------------------------------------------------
+// internal i/o
+//-------------------------------------------------
+
+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);
+}
+
+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);
+
+ // 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
+}
+
+
+//-------------------------------------------------
+// input_ports - device-specific input ports
+//-------------------------------------------------
+
+static INPUT_PORTS_START( sparc )
+ PORT_START("RAM")
+ PORT_CONFNAME( 0x01, 0x00, "RAM Size" )
+ PORT_CONFSETTING( 0x00, "1MB" )
+ PORT_CONFSETTING( 0x01, "4MB" )
+INPUT_PORTS_END
+
+ioport_constructor saitekosa_sparc_device::device_input_ports() const
+{
+ return INPUT_PORTS_NAME(sparc);
+}
+
+
+//-------------------------------------------------
+// device_add_mconfig - add device configuration
+//-------------------------------------------------
+
+void saitekosa_sparc_device::device_add_mconfig(machine_config &config)
+{
+ // basic machine hardware
+ MB86930(config, m_maincpu, 20_MHz_XTAL);
+ m_maincpu->set_addrmap(0x00, &saitekosa_sparc_device::debugger_map);
+ m_maincpu->cs0_read_cb().set(FUNC(saitekosa_sparc_device::rom_r));
+ m_maincpu->cs2_read_cb().set(FUNC(saitekosa_sparc_device::ram_r));
+ m_maincpu->cs2_write_cb().set(FUNC(saitekosa_sparc_device::ram_w));
+ m_maincpu->cs3_read_cb().set(FUNC(saitekosa_sparc_device::host_io_r));
+ m_maincpu->cs3_write_cb().set(FUNC(saitekosa_sparc_device::host_io_w));
+}
+
+
+//-------------------------------------------------
+// rom_region - device-specific ROM region
+//-------------------------------------------------
+
+#define ROM_LOAD32_BYTE_BIOS(bios, name, offset, length, hash) \
+ ROMX_LOAD(name, offset, length, hash, ROM_SKIP(3) | ROM_BIOS(bios))
+
+ROM_START( sparc )
+ ROM_REGION32_BE(0x40000, "maincpu", 0)
+
+ ROM_DEFAULT_BIOS("v518")
+
+ 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) )
+
+ 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
+
+const tiny_rom_entry *saitekosa_sparc_device::device_rom_region() const
+{
+ return ROM_NAME(sparc);
+}
+
+} // anonymous namespace
+
+
+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
new file mode 100644
index 00000000000..eb5484c9dc6
--- /dev/null
+++ b/src/devices/bus/saitek_osa/sparc.h
@@ -0,0 +1,18 @@
+// license:BSD-3-Clause
+// copyright-holders:hap
+/*******************************************************************************
+
+ Saitek OSA Module: Kasparov Sparc
+
+*******************************************************************************/
+
+#ifndef MAME_BUS_SAITEK_OSA_SPARC_H
+#define MAME_BUS_SAITEK_OSA_SPARC_H
+
+#pragma once
+
+#include "expansion.h"
+
+DECLARE_DEVICE_TYPE(OSA_SPARC, device_saitekosa_expansion_interface)
+
+#endif // MAME_BUS_SAITEK_OSA_SPARC_H
diff --git a/src/devices/bus/samcoupe/drive/atom.cpp b/src/devices/bus/samcoupe/drive/atom.cpp
new file mode 100644
index 00000000000..d810b27b74d
--- /dev/null
+++ b/src/devices/bus/samcoupe/drive/atom.cpp
@@ -0,0 +1,120 @@
+// license: GPL-2.0+
+// copyright-holders: Dirk Best
+/***************************************************************************
+
+ ATOM hard disk interface for SAM Coupe
+
+***************************************************************************/
+
+#include "emu.h"
+#include "atom.h"
+
+
+//**************************************************************************
+// DEVICE DEFINITIONS
+//**************************************************************************
+
+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
+//-------------------------------------------------
+
+void sam_atom_hdd_device::device_add_mconfig(machine_config &config)
+{
+ ATA_INTERFACE(config, m_ata).options(ata_devices, "hdd", nullptr, false);
+}
+
+
+//**************************************************************************
+// LIVE DEVICE
+//**************************************************************************
+
+//-------------------------------------------------
+// sam_atom_hdd_device - constructor
+//-------------------------------------------------
+
+sam_atom_hdd_device::sam_atom_hdd_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) :
+ device_t(mconfig, SAM_ATOM_HDD, tag, owner, clock),
+ device_samcoupe_drive_interface(mconfig, *this),
+ m_ata(*this, "ata"),
+ m_address_latch(0),
+ m_read_latch(0x00), m_write_latch(0x00)
+{
+}
+
+//-------------------------------------------------
+// device_start - device-specific startup
+//-------------------------------------------------
+
+void sam_atom_hdd_device::device_start()
+{
+ // register for savestates
+ save_item(NAME(m_address_latch));
+ save_item(NAME(m_read_latch));
+ save_item(NAME(m_write_latch));
+}
+
+
+//**************************************************************************
+// IMPLEMENTATION
+//**************************************************************************
+
+uint8_t sam_atom_hdd_device::read(offs_t offset)
+{
+ uint8_t data = 0xff;
+
+ switch (offset)
+ {
+ // high byte
+ case 0x06:
+ if (BIT(m_address_latch, 5))
+ {
+ uint16_t result = 0;
+
+ if (BIT(m_address_latch, 3) == 0)
+ result = m_ata->cs0_r(m_address_latch & 0x07);
+ if (BIT(m_address_latch, 4) == 0)
+ result = m_ata->cs1_r(m_address_latch & 0x07);
+
+ m_read_latch = result;
+ data = result >> 8;
+ }
+ break;
+
+ // low byte
+ case 0x07:
+ data = m_read_latch;
+ break;
+ }
+
+ return data;
+}
+
+void sam_atom_hdd_device::write(offs_t offset, uint8_t data)
+{
+ switch (offset)
+ {
+ // control
+ case 0x05:
+ if (BIT(data, 5))
+ m_address_latch = data;
+ break;
+
+ // high byte
+ case 0x06:
+ m_write_latch = data;
+ break;
+
+ // low byte
+ case 0x07:
+ if (BIT(m_address_latch, 5))
+ {
+ if (BIT(m_address_latch, 3) == 0)
+ m_ata->cs0_w(m_address_latch & 0x07, (m_write_latch << 8) | data);
+ if (BIT(m_address_latch, 4) == 0)
+ m_ata->cs1_w(m_address_latch & 0x07, (m_write_latch << 8) | data);
+ }
+ break;
+ }
+}
diff --git a/src/devices/bus/samcoupe/drive/atom.h b/src/devices/bus/samcoupe/drive/atom.h
new file mode 100644
index 00000000000..243a3010a46
--- /dev/null
+++ b/src/devices/bus/samcoupe/drive/atom.h
@@ -0,0 +1,48 @@
+// license: GPL-2.0+
+// copyright-holders: Dirk Best
+/***************************************************************************
+
+ ATOM hard disk interface for SAM Coupe
+
+***************************************************************************/
+
+#ifndef MAME_BUS_SAMCOUPE_DRIVE_ATOM_H
+#define MAME_BUS_SAMCOUPE_DRIVE_ATOM_H
+
+#pragma once
+
+#include "drive.h"
+#include "bus/ata/ataintf.h"
+
+
+//**************************************************************************
+// TYPE DEFINITIONS
+//**************************************************************************
+
+// ======================> sam_atom_hdd_device
+
+class sam_atom_hdd_device : public device_t, public device_samcoupe_drive_interface
+{
+public:
+ // construction/destruction
+ sam_atom_hdd_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
+
+ // from host
+ virtual uint8_t read(offs_t offset) override;
+ virtual void write(offs_t offset, uint8_t data) override;
+
+protected:
+ virtual void device_add_mconfig(machine_config &config) override ATTR_COLD;
+ virtual void device_start() override ATTR_COLD;
+
+private:
+ required_device<ata_interface_device> m_ata;
+
+ int m_address_latch;
+ uint8_t m_read_latch, m_write_latch;
+};
+
+// device type definition
+DECLARE_DEVICE_TYPE(SAM_ATOM_HDD, sam_atom_hdd_device)
+
+#endif // MAME_BUS_SAMCOUPE_DRIVE_ATOM_H
diff --git a/src/devices/bus/samcoupe/drive/drive.cpp b/src/devices/bus/samcoupe/drive/drive.cpp
new file mode 100644
index 00000000000..b5764aa01b7
--- /dev/null
+++ b/src/devices/bus/samcoupe/drive/drive.cpp
@@ -0,0 +1,94 @@
+// license: GPL-2.0+
+// copyright-holders: Dirk Best
+/***************************************************************************
+
+ SAM Coupe Drive Slot
+
+ 32-pin slot
+
+***************************************************************************/
+
+#include "emu.h"
+#include "drive.h"
+
+
+//**************************************************************************
+// DEVICE DEFINITIONS
+//**************************************************************************
+
+DEFINE_DEVICE_TYPE(SAMCOUPE_DRIVE_PORT, samcoupe_drive_port_device, "samcoupe_drive_port", u8"SAM Coupé Drive Port")
+
+
+//**************************************************************************
+// SLOT DEVICE
+//**************************************************************************
+
+//-------------------------------------------------
+// samcoupe_drive_port_device - constructor
+//-------------------------------------------------
+
+samcoupe_drive_port_device::samcoupe_drive_port_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) :
+ device_t(mconfig, SAMCOUPE_DRIVE_PORT, tag, owner, clock),
+ device_single_card_slot_interface<device_samcoupe_drive_interface>(mconfig, *this),
+ m_module(nullptr)
+{
+}
+
+//-------------------------------------------------
+// samcoupe_drive_port_device - destructor
+//-------------------------------------------------
+
+samcoupe_drive_port_device::~samcoupe_drive_port_device()
+{
+}
+
+//-------------------------------------------------
+// device_start - device-specific startup
+//-------------------------------------------------
+
+void samcoupe_drive_port_device::device_start()
+{
+ // get inserted module
+ m_module = get_card_device();
+}
+
+//-------------------------------------------------
+// host to module interface
+//-------------------------------------------------
+
+uint8_t samcoupe_drive_port_device::read(offs_t offset)
+{
+ if (m_module)
+ return m_module->read(offset);
+
+ return 0xff;
+}
+
+void samcoupe_drive_port_device::write(offs_t offset, uint8_t data)
+{
+ if (m_module)
+ m_module->write(offset, data);
+}
+
+
+//**************************************************************************
+// MODULE INTERFACE
+//**************************************************************************
+
+//-------------------------------------------------
+// device_samcoupe_drive_interface - constructor
+//-------------------------------------------------
+
+device_samcoupe_drive_interface::device_samcoupe_drive_interface(const machine_config &mconfig, device_t &device) :
+ device_interface(device, "samcoupedrive")
+{
+ m_port = dynamic_cast<samcoupe_drive_port_device *>(device.owner());
+}
+
+//-------------------------------------------------
+// ~device_samcoupe_drive_interface - destructor
+//-------------------------------------------------
+
+device_samcoupe_drive_interface::~device_samcoupe_drive_interface()
+{
+}
diff --git a/src/devices/bus/samcoupe/drive/drive.h b/src/devices/bus/samcoupe/drive/drive.h
new file mode 100644
index 00000000000..5033769aebb
--- /dev/null
+++ b/src/devices/bus/samcoupe/drive/drive.h
@@ -0,0 +1,96 @@
+// license: GPL-2.0+
+// copyright-holders: Dirk Best
+/***************************************************************************
+
+ SAM Coupe Drive Slot
+
+ 32-pin slot
+
+ 1A 0 VOLTS 1B WR
+ 2A 0 VOLTS 2B A0
+ 3A 0 VOLTS 3B A1
+ 4A 0 VOLTS 4B D0
+ 5A 0 VOLTS 5B D1
+ 6A 0 VOLTS 6B D2
+ 7A 0 VOLTS 7B D3
+ 8A 0 VOLTS 8B D4
+ 9A 0 VOLTS 9B D5
+ 10A 0 VOLTS 10B D6
+ 11A 0 VOLTS 11B D7
+ 12A 0 VOLTS 12B 8 MHz
+ 13A 0 VOLTS 13B RST
+ 14A 0 VOLTS 14B N/C
+ 15A 0 VOLTS 15B A2
+ 16A 0 VOLTS 16B DISK 1 OR DISK 2
+
+***************************************************************************/
+
+#ifndef MAME_BUS_SAMCOUPE_DRIVE_DRIVE_H
+#define MAME_BUS_SAMCOUPE_DRIVE_DRIVE_H
+
+#pragma once
+
+
+//**************************************************************************
+// TYPE DEFINITIONS
+//**************************************************************************
+
+class device_samcoupe_drive_interface;
+
+// ======================> samcoupe_drive_port_device
+
+class samcoupe_drive_port_device : public device_t, public device_single_card_slot_interface<device_samcoupe_drive_interface>
+{
+public:
+ // construction/destruction
+ template <typename T>
+ samcoupe_drive_port_device(machine_config const &mconfig, char const *tag, device_t *owner, T &&opts, const char *dflt)
+ : samcoupe_drive_port_device(mconfig, tag, owner, uint32_t(0))
+ {
+ option_reset();
+ opts(*this);
+ set_default_option(dflt);
+ set_fixed(false);
+ }
+
+ samcoupe_drive_port_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
+ virtual ~samcoupe_drive_port_device();
+
+ // called from host
+ uint8_t read(offs_t offset);
+ void write(offs_t offset, uint8_t data);
+
+ void disk1_w(int state);
+
+protected:
+ // device-level overrides
+ virtual void device_start() override ATTR_COLD;
+
+private:
+ device_samcoupe_drive_interface *m_module;
+};
+
+// ======================> device_samcoupe_drive_interface
+
+class device_samcoupe_drive_interface : public device_interface
+{
+public:
+ // construction/destruction
+ virtual ~device_samcoupe_drive_interface();
+
+ virtual uint8_t read(offs_t offset) { return 0xff; }
+ virtual void write(offs_t offset, uint8_t data) { }
+
+protected:
+ device_samcoupe_drive_interface(const machine_config &mconfig, device_t &device);
+
+ samcoupe_drive_port_device *m_port;
+};
+
+// device type definition
+DECLARE_DEVICE_TYPE(SAMCOUPE_DRIVE_PORT, samcoupe_drive_port_device)
+
+// include here so drivers don't need to
+#include "modules.h"
+
+#endif // MAME_BUS_SAMCOUPE_DRIVE_DRIVE_H
diff --git a/src/devices/bus/samcoupe/drive/floppy.cpp b/src/devices/bus/samcoupe/drive/floppy.cpp
new file mode 100644
index 00000000000..3c2888ab5b0
--- /dev/null
+++ b/src/devices/bus/samcoupe/drive/floppy.cpp
@@ -0,0 +1,93 @@
+// license: GPL-2.0+
+// copyright-holders: Dirk Best
+/***************************************************************************
+
+ Internal floppy drive for SAM Coupe
+
+***************************************************************************/
+
+#include "emu.h"
+#include "floppy.h"
+#include "formats/coupedsk.h"
+
+
+//**************************************************************************
+// DEVICE DEFINITIONS
+//**************************************************************************
+
+DEFINE_DEVICE_TYPE(SAM_FLOPPY, sam_floppy_device, "sam_floppy", u8"SAM Coupé Internal Floppy")
+
+void sam_floppy_device::floppy_formats(format_registration &fr)
+{
+ fr.add_mfm_containers();
+ fr.add(FLOPPY_MGT_FORMAT);
+}
+
+static void samcoupe_floppies(device_slot_interface &device)
+{
+ device.option_add("35dd", FLOPPY_35_DD);
+}
+
+//-------------------------------------------------
+// device_add_mconfig - add device configuration
+//-------------------------------------------------
+
+void sam_floppy_device::device_add_mconfig(machine_config &config)
+{
+ WD1772(config, m_fdc, 24_MHz_XTAL / 3);
+ FLOPPY_CONNECTOR(config, "fdc:0", samcoupe_floppies, "35dd", sam_floppy_device::floppy_formats);
+}
+
+
+//**************************************************************************
+// LIVE DEVICE
+//**************************************************************************
+
+//-------------------------------------------------
+// sam_floppy_device - constructor
+//-------------------------------------------------
+
+sam_floppy_device::sam_floppy_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) :
+ device_t(mconfig, SAM_FLOPPY, tag, owner, clock),
+ device_samcoupe_drive_interface(mconfig, *this),
+ m_fdc(*this, "fdc"),
+ m_drive(*this, "fdc:0")
+{
+}
+
+//-------------------------------------------------
+// device_start - device-specific startup
+//-------------------------------------------------
+
+void sam_floppy_device::device_start()
+{
+}
+
+
+//**************************************************************************
+// IMPLEMENTATION
+//**************************************************************************
+
+uint8_t sam_floppy_device::read(offs_t offset)
+{
+ floppy_image_device *floppy = m_drive->get_device();
+
+ if (floppy)
+ floppy->ss_w(BIT(offset, 2));
+
+ m_fdc->set_floppy(floppy);
+
+ return m_fdc->read(offset & 0x03);
+}
+
+void sam_floppy_device::write(offs_t offset, uint8_t data)
+{
+ floppy_image_device *floppy = m_drive->get_device();
+
+ if (floppy)
+ floppy->ss_w(BIT(offset, 2));
+
+ m_fdc->set_floppy(floppy);
+
+ m_fdc->write(offset & 0x03, data);
+}
diff --git a/src/devices/bus/samcoupe/drive/floppy.h b/src/devices/bus/samcoupe/drive/floppy.h
new file mode 100644
index 00000000000..de624669cbe
--- /dev/null
+++ b/src/devices/bus/samcoupe/drive/floppy.h
@@ -0,0 +1,49 @@
+// license: GPL-2.0+
+// copyright-holders: Dirk Best
+/***************************************************************************
+
+ Internal floppy drive for SAM Coupe
+
+***************************************************************************/
+
+#ifndef MAME_BUS_SAMCOUPE_DRIVE_FLOPPY_H
+#define MAME_BUS_SAMCOUPE_DRIVE_FLOPPY_H
+
+#pragma once
+
+#include "drive.h"
+#include "machine/wd_fdc.h"
+#include "imagedev/floppy.h"
+
+
+//**************************************************************************
+// TYPE DEFINITIONS
+//**************************************************************************
+
+// ======================> sam_floppy_device
+
+class sam_floppy_device : public device_t, public device_samcoupe_drive_interface
+{
+public:
+ // construction/destruction
+ sam_floppy_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
+
+ // from host
+ virtual uint8_t read(offs_t offset) override;
+ virtual void write(offs_t offset, uint8_t data) override;
+
+protected:
+ virtual void device_add_mconfig(machine_config &config) override ATTR_COLD;
+ virtual void device_start() override ATTR_COLD;
+
+private:
+ required_device<wd1772_device> m_fdc;
+ required_device<floppy_connector> m_drive;
+
+ static void floppy_formats(format_registration &fr);
+};
+
+// device type definition
+DECLARE_DEVICE_TYPE(SAM_FLOPPY, sam_floppy_device)
+
+#endif // MAME_BUS_SAMCOUPE_DRIVE_FLOPPY_H
diff --git a/src/devices/bus/samcoupe/drive/modules.cpp b/src/devices/bus/samcoupe/drive/modules.cpp
new file mode 100644
index 00000000000..c8b708e2d6d
--- /dev/null
+++ b/src/devices/bus/samcoupe/drive/modules.cpp
@@ -0,0 +1,19 @@
+// license: GPL-2.0+
+// copyright-holders: Dirk Best
+/***************************************************************************
+
+ SAM Coupe Drive Port modules
+
+***************************************************************************/
+
+#include "emu.h"
+#include "modules.h"
+
+#include "atom.h"
+#include "floppy.h"
+
+void samcoupe_drive_modules(device_slot_interface &device)
+{
+ device.option_add("atom", SAM_ATOM_HDD);
+ device.option_add("floppy", SAM_FLOPPY);
+}
diff --git a/src/devices/bus/samcoupe/drive/modules.h b/src/devices/bus/samcoupe/drive/modules.h
new file mode 100644
index 00000000000..47fed4418b4
--- /dev/null
+++ b/src/devices/bus/samcoupe/drive/modules.h
@@ -0,0 +1,16 @@
+// license: GPL-2.0+
+// copyright-holders: Dirk Best
+/***************************************************************************
+
+ SAM Coupe Drive Port modules
+
+***************************************************************************/
+
+#ifndef MAME_BUS_SAMCOUPE_DRIVE_MODULES_H
+#define MAME_BUS_SAMCOUPE_DRIVE_MODULES_H
+
+#pragma once
+
+void samcoupe_drive_modules(device_slot_interface &device);
+
+#endif // MAME_BUS_SAMCOUPE_DRIVE_MODULES_H
diff --git a/src/devices/bus/samcoupe/expansion/blue_sampler.cpp b/src/devices/bus/samcoupe/expansion/blue_sampler.cpp
new file mode 100644
index 00000000000..9a70d3cac3d
--- /dev/null
+++ b/src/devices/bus/samcoupe/expansion/blue_sampler.cpp
@@ -0,0 +1,115 @@
+// license: GPL-2.0+
+// copyright-holders: Dirk Best
+/***************************************************************************
+
+ Blue Alpha Sound Sampler for SAM Coupe
+
+***************************************************************************/
+
+#include "emu.h"
+#include "machine/rescap.h"
+#include "blue_sampler.h"
+#include "speaker.h"
+
+
+//**************************************************************************
+// DEVICE DEFINITIONS
+//**************************************************************************
+
+DEFINE_DEVICE_TYPE(SAM_BLUE_SOUND_SAMPLER, sam_blue_sound_sampler_device, "blue_sampler", "Blue Alpha Sound Sampler")
+
+//-------------------------------------------------
+// device_add_mconfig - add device configuration
+//-------------------------------------------------
+
+void sam_blue_sound_sampler_device::device_add_mconfig(machine_config &config)
+{
+ SPEAKER(config, "mono").front_center();
+
+ I8255A(config, m_ppi);
+ m_ppi->out_pa_callback().set("dac", FUNC(dac_byte_interface::data_w));
+ m_ppi->out_pb_callback().set(FUNC(sam_blue_sound_sampler_device::ppi_portb_w));
+ m_ppi->in_pc_callback().set(FUNC(sam_blue_sound_sampler_device::ppi_portc_r));
+
+ ZN426E(config, m_dac, 0).add_route(ALL_OUTPUTS, "mono", 0.5);
+
+ // TODO: ZN449E ADC
+
+ // 555 with variable resistor ~19.342hz
+ TIMER(config, "timer").configure_periodic(FUNC(sam_blue_sound_sampler_device::clock_callback), PERIOD_OF_555_MONOSTABLE(RES_K(1), CAP_N(47)));
+}
+
+
+//**************************************************************************
+// LIVE DEVICE
+//**************************************************************************
+
+//-------------------------------------------------
+// sam_blue_sound_sampler_device - constructor
+//-------------------------------------------------
+
+sam_blue_sound_sampler_device::sam_blue_sound_sampler_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) :
+ device_t(mconfig, SAM_BLUE_SOUND_SAMPLER, tag, owner, clock),
+ device_samcoupe_expansion_interface(mconfig, *this),
+ m_ppi(*this, "ppi"),
+ m_dac(*this, "dac"),
+ m_portc(0)
+{
+}
+
+//-------------------------------------------------
+// device_start - device-specific startup
+//-------------------------------------------------
+
+void sam_blue_sound_sampler_device::device_start()
+{
+ // register for savestates
+ save_item(NAME(m_portc));
+}
+
+
+//**************************************************************************
+// IMPLEMENTATION
+//**************************************************************************
+
+TIMER_DEVICE_CALLBACK_MEMBER( sam_blue_sound_sampler_device::clock_callback )
+{
+ m_portc ^= 1;
+}
+
+void sam_blue_sound_sampler_device::ppi_portb_w(uint8_t data)
+{
+ // 765432-- not used
+ // ------1- enable for adc
+ // -------0 enable for dac and ppi pc6
+
+ m_ppi->pc6_w(BIT(data, 0));
+}
+
+uint8_t sam_blue_sound_sampler_device::ppi_portc_r()
+{
+ // 7------- not used
+ // -6------ from ppi pb0
+ // --5----- not used
+ // ---4---- busy output from zn449e adc
+ // ----321- not used
+ // -------- clock input from 555
+
+ return m_portc;
+}
+
+uint8_t sam_blue_sound_sampler_device::iorq_r(offs_t offset)
+{
+ uint8_t data = 0xff;
+
+ if ((offset & 0xff) == 0x7f)
+ return m_ppi->read(offset >> 8);
+
+ return data;
+}
+
+void sam_blue_sound_sampler_device::iorq_w(offs_t offset, uint8_t data)
+{
+ if ((offset & 0xff) == 0x7f)
+ m_ppi->write(offset >> 8, data);
+}
diff --git a/src/devices/bus/samcoupe/expansion/blue_sampler.h b/src/devices/bus/samcoupe/expansion/blue_sampler.h
new file mode 100644
index 00000000000..56080059784
--- /dev/null
+++ b/src/devices/bus/samcoupe/expansion/blue_sampler.h
@@ -0,0 +1,54 @@
+// license: GPL-2.0+
+// copyright-holders: Dirk Best
+/***************************************************************************
+
+ Blue Alpha Sound Sampler for SAM Coupe
+
+***************************************************************************/
+
+#ifndef MAME_BUS_SAMCOUPE_EXPANSION_BLUE_SAMPLER_H
+#define MAME_BUS_SAMCOUPE_EXPANSION_BLUE_SAMPLER_H
+
+#pragma once
+
+#include "expansion.h"
+#include "machine/i8255.h"
+#include "machine/timer.h"
+#include "sound/dac.h"
+
+
+//**************************************************************************
+// TYPE DEFINITIONS
+//**************************************************************************
+
+// ======================> sam_blue_sound_sampler_device
+
+class sam_blue_sound_sampler_device : public device_t, public device_samcoupe_expansion_interface
+{
+public:
+ // construction/destruction
+ sam_blue_sound_sampler_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
+
+ // from host
+ virtual uint8_t iorq_r(offs_t offset) override;
+ virtual void iorq_w(offs_t offset, uint8_t data) override;
+
+protected:
+ virtual void device_add_mconfig(machine_config &config) override ATTR_COLD;
+ virtual void device_start() override ATTR_COLD;
+
+private:
+ TIMER_DEVICE_CALLBACK_MEMBER(clock_callback);
+ void ppi_portb_w(uint8_t data);
+ uint8_t ppi_portc_r();
+
+ required_device<i8255_device> m_ppi;
+ required_device<zn426e_device> m_dac;
+
+ uint8_t m_portc;
+};
+
+// device type definition
+DECLARE_DEVICE_TYPE(SAM_BLUE_SOUND_SAMPLER, sam_blue_sound_sampler_device)
+
+#endif // MAME_BUS_SAMCOUPE_EXPANSION_BLUE_SAMPLER_H
diff --git a/src/devices/bus/samcoupe/expansion/dallas.cpp b/src/devices/bus/samcoupe/expansion/dallas.cpp
new file mode 100644
index 00000000000..d877b94e6e1
--- /dev/null
+++ b/src/devices/bus/samcoupe/expansion/dallas.cpp
@@ -0,0 +1,85 @@
+// license: GPL-2.0+
+// copyright-holders: Dirk Best
+/***************************************************************************
+
+ Dallas Clock for SAM Coupe
+
+***************************************************************************/
+
+#include "emu.h"
+#include "dallas.h"
+
+
+//**************************************************************************
+// DEVICE DEFINITIONS
+//**************************************************************************
+
+DEFINE_DEVICE_TYPE(SAM_DALLAS_CLOCK, sam_dallas_clock_device, "sam_dallas_clock", "Dallas Clock")
+
+//-------------------------------------------------
+// device_add_mconfig - add device configuration
+//-------------------------------------------------
+
+void sam_dallas_clock_device::device_add_mconfig(machine_config &config)
+{
+ DS12885(config, m_rtc, 32.768_kHz_XTAL); // should be DS12887 or DS1287
+ m_rtc->set_24hrs(true);
+}
+
+
+//**************************************************************************
+// LIVE DEVICE
+//**************************************************************************
+
+//-------------------------------------------------
+// sam_dallas_clock_device - constructor
+//-------------------------------------------------
+
+sam_dallas_clock_device::sam_dallas_clock_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) :
+ device_t(mconfig, SAM_DALLAS_CLOCK, tag, owner, clock),
+ device_samcoupe_expansion_interface(mconfig, *this),
+ m_rtc(*this, "rtc"),
+ m_print(0)
+{
+}
+
+//-------------------------------------------------
+// device_start - device-specific startup
+//-------------------------------------------------
+
+void sam_dallas_clock_device::device_start()
+{
+ // register for savestates
+ save_item(NAME(m_print));
+}
+
+
+//**************************************************************************
+// IMPLEMENTATION
+//**************************************************************************
+
+void sam_dallas_clock_device::print_w(int state)
+{
+ m_print = state;
+}
+
+uint8_t sam_dallas_clock_device::iorq_r(offs_t offset)
+{
+ uint8_t data = 0xff;
+
+ if (m_print && (offset & 0xff07) == 0xff07)
+ data &= m_rtc->data_r();
+
+ return data;
+}
+
+void sam_dallas_clock_device::iorq_w(offs_t offset, uint8_t data)
+{
+ if (m_print && (offset & 0xfe07) == 0xfe07)
+ {
+ if (BIT(offset, 8))
+ m_rtc->data_w(data);
+ else
+ m_rtc->address_w(data);
+ }
+}
diff --git a/src/devices/bus/samcoupe/expansion/dallas.h b/src/devices/bus/samcoupe/expansion/dallas.h
new file mode 100644
index 00000000000..94630939bf3
--- /dev/null
+++ b/src/devices/bus/samcoupe/expansion/dallas.h
@@ -0,0 +1,49 @@
+// license: GPL-2.0+
+// copyright-holders: Dirk Best
+/***************************************************************************
+
+ Dallas Clock for SAM Coupe
+
+***************************************************************************/
+
+#ifndef MAME_BUS_SAMCOUPE_EXPANSION_DALLAS_H
+#define MAME_BUS_SAMCOUPE_EXPANSION_DALLAS_H
+
+#pragma once
+
+#include "expansion.h"
+#include "machine/ds128x.h"
+
+
+//**************************************************************************
+// TYPE DEFINITIONS
+//**************************************************************************
+
+// ======================> sam_dallas_clock_device
+
+class sam_dallas_clock_device : public device_t, public device_samcoupe_expansion_interface
+{
+public:
+ // construction/destruction
+ sam_dallas_clock_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
+
+ // from host
+ virtual void print_w(int state) override;
+
+ virtual uint8_t iorq_r(offs_t offset) override;
+ virtual void iorq_w(offs_t offset, uint8_t data) override;
+
+protected:
+ virtual void device_add_mconfig(machine_config &config) override ATTR_COLD;
+ virtual void device_start() override ATTR_COLD;
+
+private:
+ required_device<ds12885_device> m_rtc;
+
+ int m_print;
+};
+
+// device type definition
+DECLARE_DEVICE_TYPE(SAM_DALLAS_CLOCK, sam_dallas_clock_device)
+
+#endif // MAME_BUS_SAMCOUPE_EXPANSION_DALLAS_H
diff --git a/src/devices/bus/samcoupe/expansion/expansion.cpp b/src/devices/bus/samcoupe/expansion/expansion.cpp
new file mode 100644
index 00000000000..d67d9df1f82
--- /dev/null
+++ b/src/devices/bus/samcoupe/expansion/expansion.cpp
@@ -0,0 +1,121 @@
+// license: GPL-2.0+
+// copyright-holders: Dirk Best
+/***************************************************************************
+
+ SAM Coupe Expansion Slot
+
+ 64-pin slot
+
+***************************************************************************/
+
+#include "emu.h"
+#include "expansion.h"
+
+
+//**************************************************************************
+// DEVICE DEFINITIONS
+//**************************************************************************
+
+DEFINE_DEVICE_TYPE(SAMCOUPE_EXPANSION, samcoupe_expansion_device, "samcoupe_expansion", u8"SAM Coupé Expansion Bus")
+
+
+//**************************************************************************
+// SLOT DEVICE
+//**************************************************************************
+
+//-------------------------------------------------
+// samcoupe_expansion_device - constructor
+//-------------------------------------------------
+
+samcoupe_expansion_device::samcoupe_expansion_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) :
+ device_t(mconfig, SAMCOUPE_EXPANSION, tag, owner, clock),
+ device_single_card_slot_interface<device_samcoupe_expansion_interface>(mconfig, *this),
+ m_int_handler(*this),
+ m_module(nullptr)
+{
+}
+
+//-------------------------------------------------
+// samcoupe_expansion_device - destructor
+//-------------------------------------------------
+
+samcoupe_expansion_device::~samcoupe_expansion_device()
+{
+}
+
+//-------------------------------------------------
+// device_start - device-specific startup
+//-------------------------------------------------
+
+void samcoupe_expansion_device::device_start()
+{
+ // get inserted module
+ m_module = get_card_device();
+}
+
+//-------------------------------------------------
+// host to module interface
+//-------------------------------------------------
+
+uint8_t samcoupe_expansion_device::mreq_r(offs_t offset)
+{
+ if (m_module)
+ return m_module->mreq_r(offset);
+
+ return 0xff;
+}
+
+void samcoupe_expansion_device::mreq_w(offs_t offset, uint8_t data)
+{
+ if (m_module)
+ m_module->mreq_w(offset, data);
+}
+
+uint8_t samcoupe_expansion_device::iorq_r(offs_t offset)
+{
+ if (m_module)
+ return m_module->iorq_r(offset);
+
+ return 0xff;
+}
+
+void samcoupe_expansion_device::iorq_w(offs_t offset, uint8_t data)
+{
+ if (m_module)
+ m_module->iorq_w(offset, data);
+}
+
+void samcoupe_expansion_device::xmem_w(int state)
+{
+ if (m_module)
+ m_module->xmem_w(state);
+}
+
+void samcoupe_expansion_device::print_w(int state)
+{
+ if (m_module)
+ m_module->print_w(state);
+}
+
+
+//**************************************************************************
+// MODULE INTERFACE
+//**************************************************************************
+
+//-------------------------------------------------
+// device_samcoupe_expansion_interface - constructor
+//-------------------------------------------------
+
+device_samcoupe_expansion_interface::device_samcoupe_expansion_interface(const machine_config &mconfig, device_t &device) :
+ device_interface(device, "samcoupeexp")
+{
+ m_expansion = dynamic_cast<samcoupe_expansion_device *>(device.owner());
+}
+
+//-------------------------------------------------
+// ~device_samcoupe_expansion_interface - destructor
+//-------------------------------------------------
+
+device_samcoupe_expansion_interface::~device_samcoupe_expansion_interface()
+{
+}
diff --git a/src/devices/bus/samcoupe/expansion/expansion.h b/src/devices/bus/samcoupe/expansion/expansion.h
new file mode 100644
index 00000000000..c052de71741
--- /dev/null
+++ b/src/devices/bus/samcoupe/expansion/expansion.h
@@ -0,0 +1,128 @@
+// license: GPL-2.0+
+// copyright-holders: Dirk Best
+/***************************************************************************
+
+ SAM Coupe Expansion Slot
+
+ 64-pin slot
+
+ 1A DBDIR 1C IORQL
+ 2A RDL 2C MREQL
+ 3A WRL 3C HALTL
+ 4A BUSAKL 4C NMIL
+ 5A WAITL 5C INTL
+ 6A BUSREQL 6C CD1
+ 7A RESETL 7C CD0
+ 8A CM1L 8C CD7
+ 9A REFRESHL 9C CD2
+ 10A 0 VOLTS 10C +5 VOLTS
+ 11A A0 11C CD6
+ 12A A1 12C CD5
+ 13A A2 13C CD3
+ 14A A3 14C CD4
+ 15A A4 15C CPU CLK
+ 16A A5 16C A15
+ 17A A6 17C A14
+ 18A A7 18C A13
+ 19A A8 19C A12
+ 20A A9 20C A11
+ 21A A10 21C DISK 2L
+ 22A MSEINTL 22C ROMCSL
+ 23A XMEML 23C EARMIC
+ 24A 8 MHz 24C DISK 1L
+ 25A RED 1 25C PRINTL
+ 26A GREEN 1 26C BLUE 1
+ 27A C SYNC 27C ROMCSRL
+ 28A SPEN 28C AUDIO RIGHT
+ 29A BLUE 0 29C AUDIO LEFT
+ 30A RED 0 30C COMP VIDEO
+ 31A BRIGHT 31C GREEN 0
+ 32A +5 VOLTS 32C 0 VOLTS
+
+***************************************************************************/
+
+#ifndef MAME_BUS_SAMCOUPE_EXPANSION_EXPANSION_H
+#define MAME_BUS_SAMCOUPE_EXPANSION_EXPANSION_H
+
+#pragma once
+
+
+//**************************************************************************
+// TYPE DEFINITIONS
+//**************************************************************************
+
+class device_samcoupe_expansion_interface;
+
+// ======================> samcoupe_expansion_device
+
+class samcoupe_expansion_device : public device_t, public device_single_card_slot_interface<device_samcoupe_expansion_interface>
+{
+public:
+ // construction/destruction
+ template <typename T>
+ samcoupe_expansion_device(machine_config const &mconfig, char const *tag, device_t *owner, T &&opts)
+ : samcoupe_expansion_device(mconfig, tag, owner, uint32_t(0))
+ {
+ option_reset();
+ opts(*this);
+ set_default_option(nullptr);
+ set_fixed(false);
+ }
+
+ samcoupe_expansion_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
+ virtual ~samcoupe_expansion_device();
+
+ // callbacks
+ auto int_handler() { return m_int_handler.bind(); }
+
+ // called from cart device
+ void int_w(int state) { m_int_handler(state); }
+
+ // called from host
+ uint8_t mreq_r(offs_t offset);
+ 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);
+
+ void xmem_w(int state);
+ void print_w(int state);
+
+protected:
+ // device-level overrides
+ virtual void device_start() override ATTR_COLD;
+
+private:
+ devcb_write_line m_int_handler;
+
+ device_samcoupe_expansion_interface *m_module;
+};
+
+// ======================> device_samcoupe_expansion_interface
+
+class device_samcoupe_expansion_interface : public device_interface
+{
+public:
+ // construction/destruction
+ virtual ~device_samcoupe_expansion_interface();
+
+ 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 void xmem_w(int state) { }
+ virtual void print_w(int state) { }
+
+protected:
+ device_samcoupe_expansion_interface(const machine_config &mconfig, device_t &device);
+
+ samcoupe_expansion_device *m_expansion;
+};
+
+// device type definition
+DECLARE_DEVICE_TYPE(SAMCOUPE_EXPANSION, samcoupe_expansion_device)
+
+// include here so drivers don't need to
+#include "modules.h"
+
+#endif // MAME_BUS_SAMCOUPE_EXPANSION_EXPANSION_H
diff --git a/src/devices/bus/samcoupe/expansion/modules.cpp b/src/devices/bus/samcoupe/expansion/modules.cpp
new file mode 100644
index 00000000000..cd85b69258d
--- /dev/null
+++ b/src/devices/bus/samcoupe/expansion/modules.cpp
@@ -0,0 +1,32 @@
+// license: GPL-2.0+
+// copyright-holders: Dirk Best
+/***************************************************************************
+
+ SAM Coupe Expansion Slot modules
+
+***************************************************************************/
+
+#include "emu.h"
+#include "modules.h"
+
+#include "blue_sampler.h"
+#include "dallas.h"
+#include "onemeg.h"
+#include "sambus.h"
+#include "sdide.h"
+#include "sid.h"
+#include "spi.h"
+#include "voicebox.h"
+
+void samcoupe_expansion_modules(device_slot_interface &device)
+{
+ device.option_add("blue_sampler", SAM_BLUE_SOUND_SAMPLER);
+ device.option_add("dallas", SAM_DALLAS_CLOCK);
+ device.option_add("onemeg", SAM_ONEMEG);
+ device.option_add("sambus", SAM_SAMBUS);
+ device.option_add("sdide", SAM_SDIDE);
+ device.option_add("sid6581", SAM_SID6581);
+ device.option_add("sid8580", SAM_SID8580);
+ device.option_add("spi", SAM_SPI);
+ device.option_add("voicebox", SAM_VOICEBOX);
+}
diff --git a/src/devices/bus/samcoupe/expansion/modules.h b/src/devices/bus/samcoupe/expansion/modules.h
new file mode 100644
index 00000000000..f58328f11d5
--- /dev/null
+++ b/src/devices/bus/samcoupe/expansion/modules.h
@@ -0,0 +1,16 @@
+// license: GPL-2.0+
+// copyright-holders: Dirk Best
+/***************************************************************************
+
+ SAM Coupe Expansion Slot modules
+
+***************************************************************************/
+
+#ifndef MAME_BUS_SAMCOUPE_EXPANSION_MODULES_H
+#define MAME_BUS_SAMCOUPE_EXPANSION_MODULES_H
+
+#pragma once
+
+void samcoupe_expansion_modules(device_slot_interface &device);
+
+#endif // MAME_BUS_SAMCOUPE_EXPANSION_MODULES_H
diff --git a/src/devices/bus/samcoupe/expansion/onemeg.cpp b/src/devices/bus/samcoupe/expansion/onemeg.cpp
new file mode 100644
index 00000000000..05c7c01860d
--- /dev/null
+++ b/src/devices/bus/samcoupe/expansion/onemeg.cpp
@@ -0,0 +1,110 @@
+// license: GPL-2.0+
+// copyright-holders: Dirk Best
+/***************************************************************************
+
+ 1 Mb Interface for SAM Coupe
+
+***************************************************************************/
+
+#include "emu.h"
+#include "onemeg.h"
+
+
+//**************************************************************************
+// DEVICE DEFINITIONS
+//**************************************************************************
+
+DEFINE_DEVICE_TYPE(SAM_ONEMEG, sam_onemeg_device, "onemeg", "1 Mb Interface")
+
+//-------------------------------------------------
+// input_ports - device-specific input ports
+//-------------------------------------------------
+
+static INPUT_PORTS_START( onemeg )
+ PORT_START("dip")
+ PORT_DIPNAME(0x03, 0x03, "Board ID")
+ PORT_DIPSETTING(0x00, "1")
+ PORT_DIPSETTING(0x01, "2")
+ PORT_DIPSETTING(0x02, "3")
+ PORT_DIPSETTING(0x03, "4")
+INPUT_PORTS_END
+
+ioport_constructor sam_onemeg_device::device_input_ports() const
+{
+ return INPUT_PORTS_NAME( onemeg );
+}
+
+
+//**************************************************************************
+// LIVE DEVICE
+//**************************************************************************
+
+//-------------------------------------------------
+// sam_onemeg_device - constructor
+//-------------------------------------------------
+
+sam_onemeg_device::sam_onemeg_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) :
+ device_t(mconfig, SAM_ONEMEG, tag, owner, clock),
+ device_samcoupe_expansion_interface(mconfig, *this),
+ m_dip(*this, "dip"),
+ m_xmem(0),
+ m_expage{ 0x00, 0x00 }
+{
+}
+
+//-------------------------------------------------
+// device_start - device-specific startup
+//-------------------------------------------------
+
+void sam_onemeg_device::device_start()
+{
+ // init ram
+ m_ram = std::make_unique<uint8_t[]>(0x100000);
+ memset(m_ram.get(), 0x55, 0x100000);
+
+ // register for savestates
+ save_item(NAME(m_xmem));
+ save_item(NAME(m_expage[0]));
+ save_item(NAME(m_expage[1]));
+ save_pointer(NAME(m_ram), 0x100000);
+}
+
+
+//**************************************************************************
+// IMPLEMENTATION
+//**************************************************************************
+
+void sam_onemeg_device::xmem_w(int state)
+{
+ m_xmem = state;
+}
+
+uint8_t sam_onemeg_device::mreq_r(offs_t offset)
+{
+ uint8_t data = 0xff;
+
+ // read if external memory is enabled and the id matches
+ if (m_xmem && (m_expage[BIT(offset, 14)] >> 6 == m_dip->read()))
+ data = m_ram[((m_expage[BIT(offset, 14)] & 0x3f) << 14) | (offset & 0x3fff)];
+
+ return data;
+}
+
+void sam_onemeg_device::mreq_w(offs_t offset, uint8_t data)
+{
+ // write if external memory is enabled and the id matches
+ if (m_xmem && (m_expage[BIT(offset, 14)] >> 6 == m_dip->read()))
+ m_ram[((m_expage[BIT(offset, 14)] & 0x3f) << 14) | (offset & 0x3fff)] = data;
+}
+
+void sam_onemeg_device::iorq_w(offs_t offset, uint8_t data)
+{
+ // 0x80: EXPAGE-C
+ // 0x81: EXPAGE-D
+
+ // 76------ selected memory expansion
+ // --543210 memory bank
+
+ if ((offset & 0xfe) == 0x80)
+ m_expage[BIT(offset, 0)] = data;
+}
diff --git a/src/devices/bus/samcoupe/expansion/onemeg.h b/src/devices/bus/samcoupe/expansion/onemeg.h
new file mode 100644
index 00000000000..2f6a9b0b1e9
--- /dev/null
+++ b/src/devices/bus/samcoupe/expansion/onemeg.h
@@ -0,0 +1,52 @@
+// license: GPL-2.0+
+// copyright-holders: Dirk Best
+/***************************************************************************
+
+ 1 Mb Interface for SAM Coupe
+
+***************************************************************************/
+
+#ifndef MAME_BUS_SAMCOUPE_EXPANSION_ONEMEG_H
+#define MAME_BUS_SAMCOUPE_EXPANSION_ONEMEG_H
+
+#pragma once
+
+#include "expansion.h"
+
+
+//**************************************************************************
+// TYPE DEFINITIONS
+//**************************************************************************
+
+// ======================> sam_onemeg_device
+
+class sam_onemeg_device : public device_t, public device_samcoupe_expansion_interface
+{
+public:
+ // construction/destruction
+ sam_onemeg_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
+
+ // from host
+ virtual void xmem_w(int state) override;
+
+ virtual uint8_t mreq_r(offs_t offset) override;
+ virtual void mreq_w(offs_t offset, uint8_t data) override;
+ virtual void iorq_w(offs_t offset, uint8_t data) override;
+
+protected:
+ virtual ioport_constructor device_input_ports() const override ATTR_COLD;
+ virtual void device_start() override ATTR_COLD;
+
+private:
+ required_ioport m_dip;
+
+ int m_xmem;
+ uint8_t m_expage[2];
+
+ std::unique_ptr<uint8_t[]> m_ram;
+};
+
+// device type definition
+DECLARE_DEVICE_TYPE(SAM_ONEMEG, sam_onemeg_device)
+
+#endif // MAME_BUS_SAMCOUPE_EXPANSION_ONEMEG_H
diff --git a/src/devices/bus/samcoupe/expansion/sambus.cpp b/src/devices/bus/samcoupe/expansion/sambus.cpp
new file mode 100644
index 00000000000..5b68ff49f88
--- /dev/null
+++ b/src/devices/bus/samcoupe/expansion/sambus.cpp
@@ -0,0 +1,116 @@
+// license: GPL-2.0+
+// copyright-holders: Dirk Best
+/***************************************************************************
+
+ SAMBUS 4-slot Expansion Interface for SAM Coupe
+
+***************************************************************************/
+
+#include "emu.h"
+#include "sambus.h"
+
+
+//**************************************************************************
+// DEVICE DEFINITIONS
+//**************************************************************************
+
+DEFINE_DEVICE_TYPE(SAM_SAMBUS, sam_sambus_device, "sambus", "SAMBUS 4-slot Expansion Interface")
+
+//-------------------------------------------------
+// device_add_mconfig - add device configuration
+//-------------------------------------------------
+
+void sam_sambus_device::device_add_mconfig(machine_config &config)
+{
+ MSM6242(config, m_rtc, 32.768_kHz_XTAL);
+
+ SAMCOUPE_EXPANSION(config, m_exp[0], samcoupe_expansion_modules);
+ SAMCOUPE_EXPANSION(config, m_exp[1], samcoupe_expansion_modules);
+ SAMCOUPE_EXPANSION(config, m_exp[2], samcoupe_expansion_modules);
+ SAMCOUPE_EXPANSION(config, m_exp[3], samcoupe_expansion_modules);
+}
+
+
+//**************************************************************************
+// LIVE DEVICE
+//**************************************************************************
+
+//-------------------------------------------------
+// sam_sambus_device - constructor
+//-------------------------------------------------
+
+sam_sambus_device::sam_sambus_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) :
+ device_t(mconfig, SAM_SAMBUS, tag, owner, clock),
+ device_samcoupe_expansion_interface(mconfig, *this),
+ m_rtc(*this, "rtc"),
+ m_exp(*this, "%u", 0U),
+ m_print(0)
+{
+}
+
+//-------------------------------------------------
+// device_start - device-specific startup
+//-------------------------------------------------
+
+void sam_sambus_device::device_start()
+{
+ // register for savestates
+ save_item(NAME(m_print));
+}
+
+
+//**************************************************************************
+// IMPLEMENTATION
+//**************************************************************************
+
+void sam_sambus_device::xmem_w(int state)
+{
+ for (int i = 0; i < 4; i++)
+ m_exp[i]->xmem_w(state);
+}
+
+void sam_sambus_device::print_w(int state)
+{
+ for (int i = 0; i < 4; i++)
+ m_exp[i]->print_w(state);
+
+ m_print = state;
+}
+
+uint8_t sam_sambus_device::mreq_r(offs_t offset)
+{
+ uint8_t data = 0xff;
+
+ for (int i = 0; i < 4; i++)
+ data &= m_exp[i]->mreq_r(offset);
+
+ return data;
+}
+
+void sam_sambus_device::mreq_w(offs_t offset, uint8_t data)
+{
+ for (int i = 0; i < 4; i++)
+ m_exp[i]->mreq_w(offset, data);
+}
+
+uint8_t sam_sambus_device::iorq_r(offs_t offset)
+{
+ uint8_t data = 0xff;
+
+ if (m_print && (offset & 0x07) == 0x07)
+ data &= m_rtc->read(offset >> 12);
+
+ for (int i = 0; i < 4; i++)
+ data &= m_exp[i]->iorq_r(offset);
+
+ return data;
+}
+
+void sam_sambus_device::iorq_w(offs_t offset, uint8_t data)
+{
+ if (m_print && (offset & 0x07) == 0x07)
+ m_rtc->write(offset >> 12, data);
+
+ for (int i = 0; i < 4; i++)
+ m_exp[i]->iorq_w(offset, data);
+}
diff --git a/src/devices/bus/samcoupe/expansion/sambus.h b/src/devices/bus/samcoupe/expansion/sambus.h
new file mode 100644
index 00000000000..e2cb0542f4a
--- /dev/null
+++ b/src/devices/bus/samcoupe/expansion/sambus.h
@@ -0,0 +1,53 @@
+// license: GPL-2.0+
+// copyright-holders: Dirk Best
+/***************************************************************************
+
+ SAMBUS 4-slot Expansion Interface for SAM Coupe
+
+***************************************************************************/
+
+#ifndef MAME_BUS_SAMCOUPE_EXPANSION_SAMBUS_H
+#define MAME_BUS_SAMCOUPE_EXPANSION_SAMBUS_H
+
+#pragma once
+
+#include "expansion.h"
+#include "machine/msm6242.h"
+
+
+//**************************************************************************
+// TYPE DEFINITIONS
+//**************************************************************************
+
+// ======================> sam_sambus_device
+
+class sam_sambus_device : public device_t, public device_samcoupe_expansion_interface
+{
+public:
+ // construction/destruction
+ sam_sambus_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
+
+ // from host
+ virtual void xmem_w(int state) override;
+ virtual void print_w(int state) 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;
+ virtual void iorq_w(offs_t offset, uint8_t data) override;
+
+protected:
+ virtual void device_add_mconfig(machine_config &config) override ATTR_COLD;
+ virtual void device_start() override ATTR_COLD;
+
+private:
+ required_device<msm6242_device> m_rtc;
+ required_device_array<samcoupe_expansion_device, 4> m_exp;
+
+ int m_print;
+};
+
+// device type definition
+DECLARE_DEVICE_TYPE(SAM_SAMBUS, sam_sambus_device)
+
+#endif // MAME_BUS_SAMCOUPE_EXPANSION_SAMBUS_H
diff --git a/src/devices/bus/samcoupe/expansion/sdide.cpp b/src/devices/bus/samcoupe/expansion/sdide.cpp
new file mode 100644
index 00000000000..4c442b816c6
--- /dev/null
+++ b/src/devices/bus/samcoupe/expansion/sdide.cpp
@@ -0,0 +1,116 @@
+// license: GPL-2.0+
+// copyright-holders: Dirk Best
+/***************************************************************************
+
+ S D IDE Adapter for SAM Coupe
+
+***************************************************************************/
+
+#include "emu.h"
+#include "sdide.h"
+
+
+//**************************************************************************
+// DEVICE DEFINITIONS
+//**************************************************************************
+
+DEFINE_DEVICE_TYPE(SAM_SDIDE, sam_sdide_device, "sam_sdide", "S D IDE Adapter")
+
+//-------------------------------------------------
+// device_add_mconfig - add device configuration
+//-------------------------------------------------
+
+void sam_sdide_device::device_add_mconfig(machine_config &config)
+{
+ ATA_INTERFACE(config, m_ata).options(ata_devices, "hdd", nullptr, false);
+}
+
+
+//**************************************************************************
+// LIVE DEVICE
+//**************************************************************************
+
+//-------------------------------------------------
+// sam_sdide_device - constructor
+//-------------------------------------------------
+
+sam_sdide_device::sam_sdide_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) :
+ device_t(mconfig, SAM_SDIDE, tag, owner, clock),
+ device_samcoupe_expansion_interface(mconfig, *this),
+ m_ata(*this, "ata"),
+ m_address_latch(0),
+ m_data_latch(0),
+ m_data_pending(false)
+{
+}
+
+//-------------------------------------------------
+// device_start - device-specific startup
+//-------------------------------------------------
+
+void sam_sdide_device::device_start()
+{
+ // register for savestates
+ save_item(NAME(m_address_latch));
+ save_item(NAME(m_data_latch));
+ save_item(NAME(m_data_pending));
+}
+
+
+//**************************************************************************
+// IMPLEMENTATION
+//**************************************************************************
+
+uint8_t sam_sdide_device::iorq_r(offs_t offset)
+{
+ uint8_t data = 0xff;
+
+ switch (offset & 0xff)
+ {
+ case 0xbd: // data
+ if (m_data_pending)
+ data = m_data_latch;
+ else
+ {
+ uint16_t result = 0;
+
+ if (BIT(m_address_latch, 3) == 0)
+ result = m_ata->cs0_r(m_address_latch & 0x07);
+ if (BIT(m_address_latch, 4) == 0)
+ result = m_ata->cs1_r(m_address_latch & 0x07);
+
+ m_data_latch = result >> 8;
+ data = result;
+ }
+
+ m_data_pending = !m_data_pending;
+ break;
+ }
+
+ return data;
+}
+
+void sam_sdide_device::iorq_w(offs_t offset, uint8_t data)
+{
+ switch (offset & 0xff)
+ {
+ case 0xbd: // data
+ if (!m_data_pending)
+ m_data_latch = data;
+ else
+ {
+ if (BIT(m_address_latch, 3) == 0)
+ m_ata->cs0_w(m_address_latch & 0x07, (data << 8) | m_data_latch);
+ if (BIT(m_address_latch, 4) == 0)
+ m_ata->cs1_w(m_address_latch & 0x07, (data << 8) | m_data_latch);
+ }
+
+ m_data_pending = !m_data_pending;
+ break;
+
+ case 0xbf: // register select
+ m_address_latch = data;
+ m_data_pending = false;
+ break;
+ }
+}
diff --git a/src/devices/bus/samcoupe/expansion/sdide.h b/src/devices/bus/samcoupe/expansion/sdide.h
new file mode 100644
index 00000000000..d9054bf4c2f
--- /dev/null
+++ b/src/devices/bus/samcoupe/expansion/sdide.h
@@ -0,0 +1,49 @@
+// license: GPL-2.0+
+// copyright-holders: Dirk Best
+/***************************************************************************
+
+ S D IDE Adapter for SAM Coupe
+
+***************************************************************************/
+
+#ifndef MAME_BUS_SAMCOUPE_EXPANSION_SDIDE_H
+#define MAME_BUS_SAMCOUPE_EXPANSION_SDIDE_H
+
+#pragma once
+
+#include "expansion.h"
+#include "bus/ata/ataintf.h"
+
+
+//**************************************************************************
+// TYPE DEFINITIONS
+//**************************************************************************
+
+// ======================> sam_sdide_device
+
+class sam_sdide_device : public device_t, public device_samcoupe_expansion_interface
+{
+public:
+ // construction/destruction
+ sam_sdide_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
+
+ // from host
+ virtual uint8_t iorq_r(offs_t offset) override;
+ virtual void iorq_w(offs_t offset, uint8_t data) override;
+
+protected:
+ virtual void device_add_mconfig(machine_config &config) override ATTR_COLD;
+ virtual void device_start() override ATTR_COLD;
+
+private:
+ required_device<ata_interface_device> m_ata;
+
+ uint8_t m_address_latch;
+ uint8_t m_data_latch;
+ bool m_data_pending;
+};
+
+// device type definition
+DECLARE_DEVICE_TYPE(SAM_SDIDE, sam_sdide_device)
+
+#endif // MAME_BUS_SAMCOUPE_EXPANSION_SDIDE_H
diff --git a/src/devices/bus/samcoupe/expansion/sid.cpp b/src/devices/bus/samcoupe/expansion/sid.cpp
new file mode 100644
index 00000000000..45c3c0c7f83
--- /dev/null
+++ b/src/devices/bus/samcoupe/expansion/sid.cpp
@@ -0,0 +1,90 @@
+// license: GPL-2.0+
+// copyright-holders: Dirk Best
+/***************************************************************************
+
+ SID Soundchip Interface for SAM Coupe
+
+***************************************************************************/
+
+#include "emu.h"
+#include "sid.h"
+#include "speaker.h"
+
+
+//**************************************************************************
+// DEVICE DEFINITIONS
+//**************************************************************************
+
+DEFINE_DEVICE_TYPE(SAM_SID6581, sam_sid6581_device, "sid6581", "SID Soundchip Interface (6581)")
+DEFINE_DEVICE_TYPE(SAM_SID8580, sam_sid8580_device, "sid8580", "SID Soundchip Interface (8580)")
+
+//-------------------------------------------------
+// device_add_mconfig - add device configuration
+//-------------------------------------------------
+
+void sam_sid6581_device::device_add_mconfig(machine_config &config)
+{
+ SPEAKER(config, "mono").front_center();
+ MOS6581(config, m_sid, 1_MHz_XTAL);
+ m_sid->add_route(ALL_OUTPUTS, "mono", 1.00);
+}
+
+void sam_sid8580_device::device_add_mconfig(machine_config &config)
+{
+ SPEAKER(config, "mono").front_center();
+ MOS8580(config, m_sid, 1_MHz_XTAL);
+ m_sid->add_route(ALL_OUTPUTS, "mono", 1.00);
+}
+
+
+//**************************************************************************
+// LIVE DEVICE
+//**************************************************************************
+
+//-------------------------------------------------
+// sam_sid_device - constructor
+//-------------------------------------------------
+
+sam_sid_device::sam_sid_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_samcoupe_expansion_interface(mconfig, *this),
+ m_sid(*this, "sid")
+{
+}
+
+//-------------------------------------------------
+// sam_sid6581_device - constructor
+//-------------------------------------------------
+
+sam_sid6581_device::sam_sid6581_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) :
+ sam_sid_device(mconfig, SAM_SID6581, tag, owner, clock)
+{
+}
+
+//-------------------------------------------------
+// sam_sid8580_device - constructor
+//-------------------------------------------------
+
+sam_sid8580_device::sam_sid8580_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) :
+ sam_sid_device(mconfig, SAM_SID8580, tag, owner, clock)
+{
+}
+
+//-------------------------------------------------
+// device_start - device-specific startup
+//-------------------------------------------------
+
+void sam_sid_device::device_start()
+{
+}
+
+
+//**************************************************************************
+// IMPLEMENTATION
+//**************************************************************************
+
+void sam_sid_device::iorq_w(offs_t offset, uint8_t data)
+{
+ if ((offset & 0xff) == 0xd4)
+ m_sid->write(offset >> 8, data);
+}
diff --git a/src/devices/bus/samcoupe/expansion/sid.h b/src/devices/bus/samcoupe/expansion/sid.h
new file mode 100644
index 00000000000..f5e46958bfc
--- /dev/null
+++ b/src/devices/bus/samcoupe/expansion/sid.h
@@ -0,0 +1,67 @@
+// license: GPL-2.0+
+// copyright-holders: Dirk Best
+/***************************************************************************
+
+ SID Soundchip Interface for SAM Coupe
+
+***************************************************************************/
+
+#ifndef MAME_BUS_SAMCOUPE_EXPANSION_SID_H
+#define MAME_BUS_SAMCOUPE_EXPANSION_SID_H
+
+#pragma once
+
+#include "expansion.h"
+#include "sound/mos6581.h"
+
+
+//**************************************************************************
+// TYPE DEFINITIONS
+//**************************************************************************
+
+// ======================> sam_sid_device
+
+class sam_sid_device : public device_t, public device_samcoupe_expansion_interface
+{
+public:
+ // construction/destruction
+ sam_sid_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock);
+
+ // from host
+ virtual void iorq_w(offs_t offset, uint8_t data) override;
+
+protected:
+ virtual void device_start() override ATTR_COLD;
+
+ required_device<mos6581_device> m_sid;
+};
+
+// ======================> sam_sid6581_device
+
+class sam_sid6581_device : public sam_sid_device
+{
+public:
+ // construction/destruction
+ sam_sid6581_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
+
+protected:
+ virtual void device_add_mconfig(machine_config &config) override ATTR_COLD;
+};
+
+// ======================> sam_sid8580_device
+
+class sam_sid8580_device : public sam_sid_device
+{
+public:
+ // construction/destruction
+ sam_sid8580_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
+
+protected:
+ virtual void device_add_mconfig(machine_config &config) override ATTR_COLD;
+};
+
+// device type definition
+DECLARE_DEVICE_TYPE(SAM_SID6581, sam_sid6581_device)
+DECLARE_DEVICE_TYPE(SAM_SID8580, sam_sid8580_device)
+
+#endif // MAME_BUS_SAMCOUPE_EXPANSION_SID_H
diff --git a/src/devices/bus/samcoupe/expansion/spi.cpp b/src/devices/bus/samcoupe/expansion/spi.cpp
new file mode 100644
index 00000000000..e005a39ba70
--- /dev/null
+++ b/src/devices/bus/samcoupe/expansion/spi.cpp
@@ -0,0 +1,120 @@
+// license: GPL-2.0+
+// copyright-holders: Dirk Best
+/***************************************************************************
+
+ S.P.I. SAM Parallel Interface for SAM Coupe
+
+***************************************************************************/
+
+#include "emu.h"
+#include "spi.h"
+
+
+//**************************************************************************
+// DEVICE DEFINITIONS
+//**************************************************************************
+
+DEFINE_DEVICE_TYPE(SAM_SPI, sam_spi_device, "spi", "S.P.I. SAM Parallel Interface")
+
+//-------------------------------------------------
+// device_add_mconfig - add device configuration
+//-------------------------------------------------
+
+void sam_spi_device::device_add_mconfig(machine_config &config)
+{
+ OUTPUT_LATCH(config, m_data_out);
+
+ CENTRONICS(config, m_centronics, centronics_devices, "printer");
+ m_centronics->busy_handler().set(FUNC(sam_spi_device::centronics_busy_w));
+ m_centronics->set_output_latch(*m_data_out);
+}
+
+
+//**************************************************************************
+// LIVE DEVICE
+//**************************************************************************
+
+//-------------------------------------------------
+// sambus_device - constructor
+//-------------------------------------------------
+
+sam_spi_device::sam_spi_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) :
+ device_t(mconfig, SAM_SPI, tag, owner, clock),
+ device_samcoupe_expansion_interface(mconfig, *this),
+ m_data_out(*this, "data_out"),
+ m_centronics(*this, "centronics"),
+ m_print(0),
+ m_busy(0),
+ m_mode(0)
+{
+}
+
+//-------------------------------------------------
+// device_start - device-specific startup
+//-------------------------------------------------
+
+void sam_spi_device::device_start()
+{
+ // register for savestates
+ save_item(NAME(m_print));
+ save_item(NAME(m_busy));
+ save_item(NAME(m_mode));
+}
+
+
+//**************************************************************************
+// IMPLEMENTATION
+//**************************************************************************
+
+void sam_spi_device::centronics_busy_w(int state)
+{
+ m_busy = state;
+}
+
+void sam_spi_device::print_w(int state)
+{
+ m_print = state;
+}
+
+uint8_t sam_spi_device::iorq_r(offs_t offset)
+{
+ uint8_t data = 0xff;
+
+ if (m_print)
+ {
+ switch (offset & 0x07)
+ {
+ case 0x01:
+ data = 0xfe | m_busy;
+ break;
+
+ case 0x02:
+ logerror("Warning: Data read unsupported\n");
+ data = 0xff;
+ break;
+ }
+ }
+
+ return data;
+}
+
+void sam_spi_device::iorq_w(offs_t offset, uint8_t data)
+{
+ if (m_print)
+ {
+ switch (offset & 0x07)
+ {
+ case 0x00:
+ m_data_out->write(data);
+ break;
+
+ case 0x01:
+ m_centronics->write_strobe(BIT(data, 0));
+ break;
+
+ case 0x02:
+ m_mode = BIT(data, 0); // 0 = output (default), 1 = input
+ break;
+ }
+ }
+}
diff --git a/src/devices/bus/samcoupe/expansion/spi.h b/src/devices/bus/samcoupe/expansion/spi.h
new file mode 100644
index 00000000000..acd1eaca3ab
--- /dev/null
+++ b/src/devices/bus/samcoupe/expansion/spi.h
@@ -0,0 +1,54 @@
+// license: GPL-2.0+
+// copyright-holders: Dirk Best
+/***************************************************************************
+
+ S.P.I. SAM Parallel Interface for SAM Coupe
+
+***************************************************************************/
+
+#ifndef MAME_BUS_SAMCOUPE_EXPANSION_SPI_H
+#define MAME_BUS_SAMCOUPE_EXPANSION_SPI_H
+
+#pragma once
+
+#include "expansion.h"
+#include "bus/centronics/ctronics.h"
+
+
+//**************************************************************************
+// TYPE DEFINITIONS
+//**************************************************************************
+
+// ======================> sam_spi_device
+
+class sam_spi_device : public device_t, public device_samcoupe_expansion_interface
+{
+public:
+ // construction/destruction
+ sam_spi_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
+
+ // from host
+ virtual void print_w(int state) override;
+
+ virtual uint8_t iorq_r(offs_t offset) override;
+ virtual void iorq_w(offs_t offset, uint8_t data) override;
+
+protected:
+ virtual void device_add_mconfig(machine_config &config) override ATTR_COLD;
+ virtual void device_start() override ATTR_COLD;
+
+private:
+ required_device<output_latch_device> m_data_out;
+ required_device<centronics_device> m_centronics;
+
+ void centronics_busy_w(int state);
+
+ int m_print;
+ int m_busy;
+ int m_mode;
+};
+
+// device type definition
+DECLARE_DEVICE_TYPE(SAM_SPI, sam_spi_device)
+
+#endif // MAME_BUS_SAMCOUPE_EXPANSION_SPI_H
diff --git a/src/devices/bus/samcoupe/expansion/voicebox.cpp b/src/devices/bus/samcoupe/expansion/voicebox.cpp
new file mode 100644
index 00000000000..d52fc3275a7
--- /dev/null
+++ b/src/devices/bus/samcoupe/expansion/voicebox.cpp
@@ -0,0 +1,88 @@
+// license: GPL-2.0+
+// copyright-holders: Dirk Best
+/***************************************************************************
+
+ Voicebox for SAM Coupe
+
+***************************************************************************/
+
+#include "emu.h"
+#include "voicebox.h"
+#include "speaker.h"
+
+
+//**************************************************************************
+// DEVICE DEFINITIONS
+//**************************************************************************
+
+DEFINE_DEVICE_TYPE(SAM_VOICEBOX, sam_voicebox_device, "voicebox", "Voicebox")
+
+//-------------------------------------------------
+// rom_region - device-specific ROM region
+//-------------------------------------------------
+
+ROM_START( sp0256 )
+ ROM_REGION(0x10000, "sp0256", 0)
+ ROM_LOAD("sp0256a-al2.bin", 0x1000, 0x0800, CRC(b504ac15) SHA1(e60fcb5fa16ff3f3b69d36c7a6e955744d3feafc))
+ROM_END
+
+const tiny_rom_entry *sam_voicebox_device::device_rom_region() const
+{
+ return ROM_NAME( sp0256 );
+}
+
+//-------------------------------------------------
+// device_add_mconfig - add device configuration
+//-------------------------------------------------
+
+void sam_voicebox_device::device_add_mconfig(machine_config &config)
+{
+ SPEAKER(config, "mono").front_center();
+ SP0256(config, m_sp0256, 3000000); // ???
+ m_sp0256->add_route(ALL_OUTPUTS, "mono", 1.00);
+}
+
+
+//**************************************************************************
+// LIVE DEVICE
+//**************************************************************************
+
+//-------------------------------------------------
+// sam_voicebox_device - constructor
+//-------------------------------------------------
+
+sam_voicebox_device::sam_voicebox_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) :
+ device_t(mconfig, SAM_VOICEBOX, tag, owner, clock),
+ device_samcoupe_expansion_interface(mconfig, *this),
+ m_sp0256(*this, "sp0256")
+{
+}
+
+//-------------------------------------------------
+// device_start - device-specific startup
+//-------------------------------------------------
+
+void sam_voicebox_device::device_start()
+{
+}
+
+
+//**************************************************************************
+// IMPLEMENTATION
+//**************************************************************************
+
+uint8_t sam_voicebox_device::iorq_r(offs_t offset)
+{
+ uint8_t data = 0xff;
+
+ if ((offset & 0xff) == 0x7f)
+ data = 0x18 | m_sp0256->lrq_r();
+
+ return data;
+}
+
+void sam_voicebox_device::iorq_w(offs_t offset, uint8_t data)
+{
+ if ((offset & 0xff) == 0x7f)
+ m_sp0256->ald_w(data);
+}
diff --git a/src/devices/bus/samcoupe/expansion/voicebox.h b/src/devices/bus/samcoupe/expansion/voicebox.h
new file mode 100644
index 00000000000..07b7dd3659c
--- /dev/null
+++ b/src/devices/bus/samcoupe/expansion/voicebox.h
@@ -0,0 +1,46 @@
+// license: GPL-2.0+
+// copyright-holders: Dirk Best
+/***************************************************************************
+
+ Voicebox for SAM Coupe
+
+***************************************************************************/
+
+#ifndef MAME_BUS_SAMCOUPE_EXPANSION_VOICEBOX_H
+#define MAME_BUS_SAMCOUPE_EXPANSION_VOICEBOX_H
+
+#pragma once
+
+#include "expansion.h"
+#include "sound/sp0256.h"
+
+
+//**************************************************************************
+// TYPE DEFINITIONS
+//**************************************************************************
+
+// ======================> sam_voicebox_device
+
+class sam_voicebox_device : public device_t, public device_samcoupe_expansion_interface
+{
+public:
+ // construction/destruction
+ sam_voicebox_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
+
+ // from host
+ virtual uint8_t iorq_r(offs_t offset) override;
+ virtual void iorq_w(offs_t offset, uint8_t data) override;
+
+protected:
+ virtual const tiny_rom_entry *device_rom_region() const override ATTR_COLD;
+ virtual void device_add_mconfig(machine_config &config) override ATTR_COLD;
+ virtual void device_start() override ATTR_COLD;
+
+private:
+ required_device<sp0256_device> m_sp0256;
+};
+
+// device type definition
+DECLARE_DEVICE_TYPE(SAM_VOICEBOX, sam_voicebox_device)
+
+#endif // MAME_BUS_SAMCOUPE_EXPANSION_VOICEBOX_H
diff --git a/src/devices/bus/samcoupe/mouse/modules.cpp b/src/devices/bus/samcoupe/mouse/modules.cpp
new file mode 100644
index 00000000000..2079e1b3f4b
--- /dev/null
+++ b/src/devices/bus/samcoupe/mouse/modules.cpp
@@ -0,0 +1,17 @@
+// license: GPL-2.0+
+// copyright-holders: Dirk Best
+/***************************************************************************
+
+ SAM Coupe Mouse Port modules
+
+***************************************************************************/
+
+#include "emu.h"
+#include "modules.h"
+
+#include "mouse.h"
+
+void samcoupe_mouse_modules(device_slot_interface &device)
+{
+ device.option_add("mouse", SAM_MOUSE);
+}
diff --git a/src/devices/bus/samcoupe/mouse/modules.h b/src/devices/bus/samcoupe/mouse/modules.h
new file mode 100644
index 00000000000..5a2b3bb7dcc
--- /dev/null
+++ b/src/devices/bus/samcoupe/mouse/modules.h
@@ -0,0 +1,16 @@
+// license: GPL-2.0+
+// copyright-holders: Dirk Best
+/***************************************************************************
+
+ SAM Coupe Mouse Port modules
+
+***************************************************************************/
+
+#ifndef MAME_BUS_SAMCOUPE_MOUSE_MODULES_H
+#define MAME_BUS_SAMCOUPE_MOUSE_MODULES_H
+
+#pragma once
+
+void samcoupe_mouse_modules(device_slot_interface &device);
+
+#endif // MAME_BUS_SAMCOUPE_MOUSE_MODULES_H
diff --git a/src/devices/bus/samcoupe/mouse/mouse.cpp b/src/devices/bus/samcoupe/mouse/mouse.cpp
new file mode 100644
index 00000000000..324a9998a17
--- /dev/null
+++ b/src/devices/bus/samcoupe/mouse/mouse.cpp
@@ -0,0 +1,137 @@
+// license: GPL-2.0+
+// copyright-holders: Dirk Best
+/***************************************************************************
+
+ SAM Mouse Interface for SAM Coupe
+
+***************************************************************************/
+
+#include "emu.h"
+#include "mouse.h"
+
+
+//**************************************************************************
+// DEVICE DEFINITIONS
+//**************************************************************************
+
+DEFINE_DEVICE_TYPE(SAM_MOUSE, sam_mouse_device, "sam_mouse", u8"SAM Coupé Mouse Interface")
+
+//-------------------------------------------------
+// input_ports - device-specific input ports
+//-------------------------------------------------
+
+static INPUT_PORTS_START( mouse )
+ PORT_START("buttons")
+ PORT_BIT(0x01, IP_ACTIVE_LOW, IPT_BUTTON1) PORT_CODE(MOUSECODE_BUTTON1) PORT_NAME("Mouse Button 1")
+ PORT_BIT(0x02, IP_ACTIVE_LOW, IPT_BUTTON3) PORT_CODE(MOUSECODE_BUTTON3) PORT_NAME("Mouse Button 3")
+ PORT_BIT(0x04, IP_ACTIVE_LOW, IPT_BUTTON2) PORT_CODE(MOUSECODE_BUTTON2) PORT_NAME("Mouse Button 2")
+ PORT_BIT(0xf8, IP_ACTIVE_LOW, IPT_UNUSED)
+
+ PORT_START("x")
+ PORT_BIT(0xfff, 0x000, IPT_MOUSE_X) PORT_PLAYER(1) PORT_SENSITIVITY(50) PORT_KEYDELTA(0) PORT_REVERSE
+
+ PORT_START("y")
+ PORT_BIT(0xfff, 0x000, IPT_MOUSE_Y) PORT_PLAYER(1) PORT_SENSITIVITY(50) PORT_KEYDELTA(0)
+INPUT_PORTS_END
+
+ioport_constructor sam_mouse_device::device_input_ports() const
+{
+ return INPUT_PORTS_NAME( mouse );
+}
+
+
+//**************************************************************************
+// LIVE DEVICE
+//**************************************************************************
+
+//-------------------------------------------------
+// sam_mouse_device - constructor
+//-------------------------------------------------
+
+sam_mouse_device::sam_mouse_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) :
+ device_t(mconfig, SAM_MOUSE, tag, owner, clock),
+ device_samcoupe_mouse_interface(mconfig, *this),
+ m_io_buttons(*this, "buttons"),
+ m_io_x(*this, "x"),
+ m_io_y(*this, "y")
+{
+}
+
+//-------------------------------------------------
+// device_start - device-specific startup
+//-------------------------------------------------
+
+void sam_mouse_device::device_start()
+{
+ // allocate timer
+ m_reset = timer_alloc(FUNC(sam_mouse_device::reset_tick), this);
+
+ // register for savestates
+ save_item(NAME(m_mouse_index));
+ save_item(NAME(m_mouse_data));
+ save_item(NAME(m_mouse_x));
+ save_item(NAME(m_mouse_y));
+}
+
+//-------------------------------------------------
+// device_reset - device-specific startup
+//-------------------------------------------------
+
+void sam_mouse_device::device_reset()
+{
+ m_mouse_index = 0;
+ m_mouse_data[0] = 0xff;
+ m_mouse_data[1] = 0xff;
+}
+
+//-------------------------------------------------
+// reset_tick - reset the mouse index
+//-------------------------------------------------
+
+TIMER_CALLBACK_MEMBER(sam_mouse_device::reset_tick)
+{
+ m_mouse_index = 0;
+}
+
+
+//**************************************************************************
+// IMPLEMENTATION
+//**************************************************************************
+
+uint8_t sam_mouse_device::read()
+{
+ uint8_t data;
+
+ // on a read, reset the timer
+ m_reset->adjust(attotime::from_usec(50));
+
+ // update when we are about to read the first real values
+ if (m_mouse_index == 2)
+ {
+ int mouse_x = m_io_x->read();
+ int mouse_y = m_io_y->read();
+
+ // distance moved
+ int mouse_dx = m_mouse_x - mouse_x;
+ int mouse_dy = m_mouse_y - mouse_y;
+
+ m_mouse_x = mouse_x;
+ m_mouse_y = mouse_y;
+
+ m_mouse_data[2] = m_io_buttons->read();
+ m_mouse_data[3] = (mouse_dy & 0xf00) >> 8;
+ m_mouse_data[4] = (mouse_dy & 0x0f0) >> 4;
+ m_mouse_data[5] = (mouse_dy & 0x00f) >> 0;
+ m_mouse_data[6] = (mouse_dx & 0xf00) >> 8;
+ m_mouse_data[7] = (mouse_dx & 0x0f0) >> 4;
+ m_mouse_data[8] = (mouse_dx & 0x00f) >> 0;
+ }
+
+ data = m_mouse_data[m_mouse_index++];
+
+ // reset if we are at the end
+ if (m_mouse_index == sizeof(m_mouse_data))
+ m_mouse_index = 1;
+
+ return data;
+}
diff --git a/src/devices/bus/samcoupe/mouse/mouse.h b/src/devices/bus/samcoupe/mouse/mouse.h
new file mode 100644
index 00000000000..57368bff608
--- /dev/null
+++ b/src/devices/bus/samcoupe/mouse/mouse.h
@@ -0,0 +1,54 @@
+// license: GPL-2.0+
+// copyright-holders: Dirk Best
+/***************************************************************************
+
+ SAM Mouse Interface for SAM Coupe
+
+***************************************************************************/
+
+#ifndef MAME_BUS_SAMCOUPE_MOUSE_MOUSE_H
+#define MAME_BUS_SAMCOUPE_MOUSE_MOUSE_H
+
+#pragma once
+
+#include "mouseport.h"
+
+
+//**************************************************************************
+// TYPE DEFINITIONS
+//**************************************************************************
+
+// ======================> sam_mouse_device
+
+class sam_mouse_device : public device_t, public device_samcoupe_mouse_interface
+{
+public:
+ // construction/destruction
+ sam_mouse_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
+
+ // from host
+ virtual uint8_t read() override;
+
+protected:
+ virtual ioport_constructor device_input_ports() const override ATTR_COLD;
+ virtual void device_start() override ATTR_COLD;
+ virtual void device_reset() override ATTR_COLD;
+
+ TIMER_CALLBACK_MEMBER(reset_tick);
+
+private:
+ required_ioport m_io_buttons;
+ required_ioport m_io_x;
+ required_ioport m_io_y;
+
+ emu_timer *m_reset;
+
+ int m_mouse_index;
+ uint8_t m_mouse_data[9];
+ int m_mouse_x, m_mouse_y;
+};
+
+// device type definition
+DECLARE_DEVICE_TYPE(SAM_MOUSE, sam_mouse_device)
+
+#endif // MAME_BUS_SAMCOUPE_MOUSE_MOUSE_H
diff --git a/src/devices/bus/samcoupe/mouse/mouseport.cpp b/src/devices/bus/samcoupe/mouse/mouseport.cpp
new file mode 100644
index 00000000000..e5c3edc09ae
--- /dev/null
+++ b/src/devices/bus/samcoupe/mouse/mouseport.cpp
@@ -0,0 +1,89 @@
+// license: GPL-2.0+
+// copyright-holders: Dirk Best
+/***************************************************************************
+
+ SAM Coupe Mouse Port
+
+ 8-pin connector
+
+***************************************************************************/
+
+#include "emu.h"
+#include "mouseport.h"
+
+
+//**************************************************************************
+// DEVICE DEFINITIONS
+//**************************************************************************
+
+DEFINE_DEVICE_TYPE(SAMCOUPE_MOUSE_PORT, samcoupe_mouse_port_device, "samcoupe_mouse_port", u8"SAM Coupé Mouse Port")
+
+
+//**************************************************************************
+// SLOT DEVICE
+//**************************************************************************
+
+//-------------------------------------------------
+// samcoupe_mouse_port_device - constructor
+//-------------------------------------------------
+
+samcoupe_mouse_port_device::samcoupe_mouse_port_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) :
+ device_t(mconfig, SAMCOUPE_MOUSE_PORT, tag, owner, clock),
+ device_single_card_slot_interface<device_samcoupe_mouse_interface>(mconfig, *this),
+ m_mseint_handler(*this),
+ m_module(nullptr)
+{
+}
+
+//-------------------------------------------------
+// samcoupe_mouse_port_device - destructor
+//-------------------------------------------------
+
+samcoupe_mouse_port_device::~samcoupe_mouse_port_device()
+{
+}
+
+//-------------------------------------------------
+// device_start - device-specific startup
+//-------------------------------------------------
+
+void samcoupe_mouse_port_device::device_start()
+{
+ // get inserted module
+ m_module = get_card_device();
+}
+
+//-------------------------------------------------
+// host to module interface
+//-------------------------------------------------
+
+uint8_t samcoupe_mouse_port_device::read()
+{
+ if (m_module)
+ return m_module->read();
+
+ return 0xff;
+}
+
+
+//**************************************************************************
+// MODULE INTERFACE
+//**************************************************************************
+
+//-------------------------------------------------
+// device_samcoupe_mouse_interface - constructor
+//-------------------------------------------------
+
+device_samcoupe_mouse_interface::device_samcoupe_mouse_interface(const machine_config &mconfig, device_t &device) :
+ device_interface(device, "samcoupemouse")
+{
+ m_port = dynamic_cast<samcoupe_mouse_port_device *>(device.owner());
+}
+
+//-------------------------------------------------
+// ~device_samcoupe_mouse_interface - destructor
+//-------------------------------------------------
+
+device_samcoupe_mouse_interface::~device_samcoupe_mouse_interface()
+{
+}
diff --git a/src/devices/bus/samcoupe/mouse/mouseport.h b/src/devices/bus/samcoupe/mouse/mouseport.h
new file mode 100644
index 00000000000..f7b188e5e56
--- /dev/null
+++ b/src/devices/bus/samcoupe/mouse/mouseport.h
@@ -0,0 +1,92 @@
+// license: GPL-2.0+
+// copyright-holders: Dirk Best
+/***************************************************************************
+
+ SAM Coupe Mouse Port
+
+ 8-pin connector
+
+ 1 K3
+ 2 K2
+ 3 K1
+ 4 K5
+ 5 K4
+ 6 MSEINT
+ 7 RDMSEL
+ 8 5V
+
+***************************************************************************/
+
+#ifndef MAME_BUS_SAMCOUPE_MOUSE_MOUSEPORT_H
+#define MAME_BUS_SAMCOUPE_MOUSE_MOUSEPORT_H
+
+#pragma once
+
+
+//**************************************************************************
+// TYPE DEFINITIONS
+//**************************************************************************
+
+class device_samcoupe_mouse_interface;
+
+// ======================> samcoupe_mouse_port_device
+
+class samcoupe_mouse_port_device : public device_t, public device_single_card_slot_interface<device_samcoupe_mouse_interface>
+{
+public:
+ // construction/destruction
+ template <typename T>
+ samcoupe_mouse_port_device(machine_config const &mconfig, char const *tag, device_t *owner, T &&opts)
+ : samcoupe_mouse_port_device(mconfig, tag, owner, uint32_t(0))
+ {
+ option_reset();
+ opts(*this);
+ set_default_option(nullptr);
+ set_fixed(false);
+ }
+
+ samcoupe_mouse_port_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
+ virtual ~samcoupe_mouse_port_device();
+
+ // callbacks
+ auto mseint_handler() { return m_mseint_handler.bind(); }
+
+ // called from cart device
+ void mseint_w(int state) { m_mseint_handler(state); }
+
+ // called from host
+ uint8_t read();
+
+protected:
+ // device-level overrides
+ virtual void device_start() override ATTR_COLD;
+
+private:
+ devcb_write_line m_mseint_handler;
+
+ device_samcoupe_mouse_interface *m_module;
+};
+
+// ======================> device_samcoupe_mouse_interface
+
+class device_samcoupe_mouse_interface : public device_interface
+{
+public:
+ // construction/destruction
+ virtual ~device_samcoupe_mouse_interface();
+
+ virtual uint8_t read() { return 0xff; }
+
+protected:
+ device_samcoupe_mouse_interface(const machine_config &mconfig, device_t &device);
+
+ samcoupe_mouse_port_device *m_port;
+};
+
+// device type definition
+DECLARE_DEVICE_TYPE(SAMCOUPE_MOUSE_PORT, samcoupe_mouse_port_device)
+
+// include here so drivers don't need to
+#include "modules.h"
+
+#endif // MAME_BUS_SAMCOUPE_MOUSE_MOUSEPORT_H
diff --git a/src/devices/bus/sat_ctrl/analog.h b/src/devices/bus/sat_ctrl/analog.h
index d86313e59a1..642e181d8c5 100644
--- a/src/devices/bus/sat_ctrl/analog.h
+++ b/src/devices/bus/sat_ctrl/analog.h
@@ -28,12 +28,12 @@ public:
saturn_analog_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;
+ virtual ioport_constructor device_input_ports() const override ATTR_COLD;
protected:
// device-level overrides
- virtual void device_start() override;
- virtual void device_reset() override;
+ virtual void device_start() override ATTR_COLD;
+ virtual void device_reset() override ATTR_COLD;
// device_saturn_control_port_interface overrides
virtual uint8_t read_ctrl(uint8_t offset) override;
diff --git a/src/devices/bus/sat_ctrl/ctrl.cpp b/src/devices/bus/sat_ctrl/ctrl.cpp
index ebe435655ab..aeff9244cc8 100644
--- a/src/devices/bus/sat_ctrl/ctrl.cpp
+++ b/src/devices/bus/sat_ctrl/ctrl.cpp
@@ -36,8 +36,8 @@ DEFINE_DEVICE_TYPE(SATURN_CONTROL_PORT, saturn_control_port_device, "saturn_cont
// device_saturn_control_port_interface - constructor
//-------------------------------------------------
-device_saturn_control_port_interface::device_saturn_control_port_interface(const machine_config &mconfig, device_t &device)
- : device_slot_card_interface(mconfig,device)
+device_saturn_control_port_interface::device_saturn_control_port_interface(const machine_config &mconfig, device_t &device) :
+ device_interface(device, "saturnctrl")
{
m_port = dynamic_cast<saturn_control_port_device *>(device.owner());
}
@@ -62,7 +62,8 @@ device_saturn_control_port_interface::~device_saturn_control_port_interface()
saturn_control_port_device::saturn_control_port_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) :
device_t(mconfig, SATURN_CONTROL_PORT, tag, owner, clock),
- device_slot_interface(mconfig, *this), m_device(nullptr)
+ device_single_card_slot_interface<device_saturn_control_port_interface>(mconfig, *this),
+ m_device(nullptr)
{
}
@@ -82,7 +83,7 @@ saturn_control_port_device::~saturn_control_port_device()
void saturn_control_port_device::device_start()
{
- m_device = dynamic_cast<device_saturn_control_port_interface *>(get_card_device());
+ m_device = get_card_device();
}
diff --git a/src/devices/bus/sat_ctrl/ctrl.h b/src/devices/bus/sat_ctrl/ctrl.h
index 6e18936f782..1b62546c1a5 100644
--- a/src/devices/bus/sat_ctrl/ctrl.h
+++ b/src/devices/bus/sat_ctrl/ctrl.h
@@ -6,7 +6,6 @@
**********************************************************************/
-
#ifndef MAME_BUS_SAT_CTRL_CTRL_H
#define MAME_BUS_SAT_CTRL_CTRL_H
@@ -21,7 +20,7 @@ class saturn_control_port_device;
// ======================> device_saturn_control_port_interface
-class device_saturn_control_port_interface : public device_slot_card_interface
+class device_saturn_control_port_interface : public device_interface
{
public:
// construction/destruction
@@ -41,8 +40,7 @@ protected:
// ======================> saturn_control_port_device
-class saturn_control_port_device : public device_t,
- public device_slot_interface
+class saturn_control_port_device : public device_t, public device_single_card_slot_interface<device_saturn_control_port_interface>
{
public:
// construction/destruction
@@ -65,7 +63,7 @@ public:
uint8_t read_id(int idx);
// device-level overrides
- virtual void device_start() override;
+ virtual void device_start() override ATTR_COLD;
protected:
device_saturn_control_port_interface *m_device;
diff --git a/src/devices/bus/sat_ctrl/joy.h b/src/devices/bus/sat_ctrl/joy.h
index b4e124fc034..9ea27b80b9d 100644
--- a/src/devices/bus/sat_ctrl/joy.h
+++ b/src/devices/bus/sat_ctrl/joy.h
@@ -28,12 +28,12 @@ public:
saturn_joy_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;
+ virtual ioport_constructor device_input_ports() const override ATTR_COLD;
protected:
// device-level overrides
- virtual void device_start() override;
- virtual void device_reset() override;
+ virtual void device_start() override ATTR_COLD;
+ virtual void device_reset() override ATTR_COLD;
// device_saturn_control_port_interface overrides
virtual uint16_t read_direct() override;
diff --git a/src/devices/bus/sat_ctrl/joy_md.h b/src/devices/bus/sat_ctrl/joy_md.h
index 845c6bce9da..8490ca1c234 100644
--- a/src/devices/bus/sat_ctrl/joy_md.h
+++ b/src/devices/bus/sat_ctrl/joy_md.h
@@ -28,7 +28,7 @@ public:
saturn_joymd3b_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;
+ virtual ioport_constructor device_input_ports() const override ATTR_COLD;
protected:
// device-level overrides
@@ -55,7 +55,7 @@ public:
saturn_joymd6b_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;
+ virtual ioport_constructor device_input_ports() const override ATTR_COLD;
protected:
// device-level overrides
diff --git a/src/devices/bus/sat_ctrl/keybd.cpp b/src/devices/bus/sat_ctrl/keybd.cpp
index 3ab0d8dc4ab..e48378be3e6 100644
--- a/src/devices/bus/sat_ctrl/keybd.cpp
+++ b/src/devices/bus/sat_ctrl/keybd.cpp
@@ -20,171 +20,171 @@ static INPUT_PORTS_START( saturn_keybd )
// TODO: there's no info about the keycode used on Saturn keyboard, the following is trial & error with Game Basic software
PORT_START("KEY.0") // 0x00 - 0x07
PORT_BIT(0x01,IP_ACTIVE_HIGH,IPT_UNUSED)
- PORT_BIT(0x02,IP_ACTIVE_HIGH,IPT_KEYBOARD) PORT_NAME("F1") /*PORT_CODE(KEYCODE_F1)*/ PORT_CHANGED_MEMBER(DEVICE_SELF, saturn_keybd_device, key_stroke, 0x01)
- PORT_BIT(0x04,IP_ACTIVE_HIGH,IPT_KEYBOARD) PORT_NAME("0-3") /*PORT_CODE(KEYCODE_2) PORT_CHAR('2')*/ PORT_CHANGED_MEMBER(DEVICE_SELF, saturn_keybd_device, key_stroke, 0x02)
- PORT_BIT(0x08,IP_ACTIVE_HIGH,IPT_KEYBOARD) PORT_NAME("F2") /*PORT_CODE(KEYCODE_F2)*/ PORT_CHANGED_MEMBER(DEVICE_SELF, saturn_keybd_device, key_stroke, 0x03) // RUN
- PORT_BIT(0x10,IP_ACTIVE_HIGH,IPT_KEYBOARD) PORT_NAME("F3") /*PORT_CODE(KEYCODE_F3)*/ PORT_CHANGED_MEMBER(DEVICE_SELF, saturn_keybd_device, key_stroke, 0x04) // LIST
- PORT_BIT(0x20,IP_ACTIVE_HIGH,IPT_KEYBOARD) PORT_NAME("F4") /*PORT_CODE(KEYCODE_F4)*/ PORT_CHANGED_MEMBER(DEVICE_SELF, saturn_keybd_device, key_stroke, 0x05) // EDIT
- PORT_BIT(0x40,IP_ACTIVE_HIGH,IPT_KEYBOARD) PORT_NAME("F5") /*PORT_CODE(KEYCODE_F5)*/ PORT_CHANGED_MEMBER(DEVICE_SELF, saturn_keybd_device, key_stroke, 0x06)
- PORT_BIT(0x80,IP_ACTIVE_HIGH,IPT_KEYBOARD) PORT_NAME("CLR SCR") PORT_CHANGED_MEMBER(DEVICE_SELF, saturn_keybd_device, key_stroke, 0x07)
+ PORT_BIT(0x02,IP_ACTIVE_HIGH,IPT_KEYBOARD) PORT_NAME("F1") /*PORT_CODE(KEYCODE_F1)*/ PORT_CHANGED_MEMBER(DEVICE_SELF, FUNC(saturn_keybd_device::key_stroke), 0x01)
+ PORT_BIT(0x04,IP_ACTIVE_HIGH,IPT_KEYBOARD) PORT_NAME("0-3") /*PORT_CODE(KEYCODE_2) PORT_CHAR('2')*/ PORT_CHANGED_MEMBER(DEVICE_SELF, FUNC(saturn_keybd_device::key_stroke), 0x02)
+ PORT_BIT(0x08,IP_ACTIVE_HIGH,IPT_KEYBOARD) PORT_NAME("F2") /*PORT_CODE(KEYCODE_F2)*/ PORT_CHANGED_MEMBER(DEVICE_SELF, FUNC(saturn_keybd_device::key_stroke), 0x03) // RUN
+ PORT_BIT(0x10,IP_ACTIVE_HIGH,IPT_KEYBOARD) PORT_NAME("F3") /*PORT_CODE(KEYCODE_F3)*/ PORT_CHANGED_MEMBER(DEVICE_SELF, FUNC(saturn_keybd_device::key_stroke), 0x04) // LIST
+ PORT_BIT(0x20,IP_ACTIVE_HIGH,IPT_KEYBOARD) PORT_NAME("F4") /*PORT_CODE(KEYCODE_F4)*/ PORT_CHANGED_MEMBER(DEVICE_SELF, FUNC(saturn_keybd_device::key_stroke), 0x05) // EDIT
+ PORT_BIT(0x40,IP_ACTIVE_HIGH,IPT_KEYBOARD) PORT_NAME("F5") /*PORT_CODE(KEYCODE_F5)*/ PORT_CHANGED_MEMBER(DEVICE_SELF, FUNC(saturn_keybd_device::key_stroke), 0x06)
+ PORT_BIT(0x80,IP_ACTIVE_HIGH,IPT_KEYBOARD) PORT_NAME("CLR SCR") PORT_CHANGED_MEMBER(DEVICE_SELF, FUNC(saturn_keybd_device::key_stroke), 0x07)
PORT_START("KEY.1") // 0x08 - 0x0f
- PORT_BIT(0x01,IP_ACTIVE_HIGH,IPT_KEYBOARD) PORT_NAME("1-1") /*PORT_CODE(KEYCODE_1) PORT_CHAR('1')*/ PORT_CHANGED_MEMBER(DEVICE_SELF, saturn_keybd_device, key_stroke, 0x08)
- PORT_BIT(0x02,IP_ACTIVE_HIGH,IPT_KEYBOARD) PORT_NAME("F6") /*PORT_CODE(KEYCODE_F6)*/ PORT_CHANGED_MEMBER(DEVICE_SELF, saturn_keybd_device, key_stroke, 0x09)
- PORT_BIT(0x04,IP_ACTIVE_HIGH,IPT_KEYBOARD) PORT_NAME("F7") /*PORT_CODE(KEYCODE_F7)*/ PORT_CHANGED_MEMBER(DEVICE_SELF, saturn_keybd_device, key_stroke, 0x0a)
- PORT_BIT(0x08,IP_ACTIVE_HIGH,IPT_KEYBOARD) PORT_NAME("F8") /*PORT_CODE(KEYCODE_F8)*/ PORT_CHANGED_MEMBER(DEVICE_SELF, saturn_keybd_device, key_stroke, 0x0b)
- PORT_BIT(0x10,IP_ACTIVE_HIGH,IPT_KEYBOARD) PORT_NAME("F9") /*PORT_CODE(KEYCODE_F9)*/ PORT_CHANGED_MEMBER(DEVICE_SELF, saturn_keybd_device, key_stroke, 0x0c) // LIST again
- PORT_BIT(0x20,IP_ACTIVE_HIGH,IPT_KEYBOARD) PORT_NAME("1-6") /*PORT_CODE(KEYCODE_5) PORT_CHAR('5')*/ PORT_CHANGED_MEMBER(DEVICE_SELF, saturn_keybd_device, key_stroke, 0x0d)
- PORT_BIT(0x40,IP_ACTIVE_HIGH,IPT_KEYBOARD) PORT_NAME("1-7") /*PORT_CODE(KEYCODE_6) PORT_CHAR('6')*/ PORT_CHANGED_MEMBER(DEVICE_SELF, saturn_keybd_device, key_stroke, 0x0e)
- PORT_BIT(0x80,IP_ACTIVE_HIGH,IPT_KEYBOARD) PORT_NAME("1-8") /*PORT_CODE(KEYCODE_7) PORT_CHAR('7')*/ PORT_CHANGED_MEMBER(DEVICE_SELF, saturn_keybd_device, key_stroke, 0x0f)
+ PORT_BIT(0x01,IP_ACTIVE_HIGH,IPT_KEYBOARD) PORT_NAME("1-1") /*PORT_CODE(KEYCODE_1) PORT_CHAR('1')*/ PORT_CHANGED_MEMBER(DEVICE_SELF, FUNC(saturn_keybd_device::key_stroke), 0x08)
+ PORT_BIT(0x02,IP_ACTIVE_HIGH,IPT_KEYBOARD) PORT_NAME("F6") /*PORT_CODE(KEYCODE_F6)*/ PORT_CHANGED_MEMBER(DEVICE_SELF, FUNC(saturn_keybd_device::key_stroke), 0x09)
+ PORT_BIT(0x04,IP_ACTIVE_HIGH,IPT_KEYBOARD) PORT_NAME("F7") /*PORT_CODE(KEYCODE_F7)*/ PORT_CHANGED_MEMBER(DEVICE_SELF, FUNC(saturn_keybd_device::key_stroke), 0x0a)
+ PORT_BIT(0x08,IP_ACTIVE_HIGH,IPT_KEYBOARD) PORT_NAME("F8") /*PORT_CODE(KEYCODE_F8)*/ PORT_CHANGED_MEMBER(DEVICE_SELF, FUNC(saturn_keybd_device::key_stroke), 0x0b)
+ PORT_BIT(0x10,IP_ACTIVE_HIGH,IPT_KEYBOARD) PORT_NAME("F9") /*PORT_CODE(KEYCODE_F9)*/ PORT_CHANGED_MEMBER(DEVICE_SELF, FUNC(saturn_keybd_device::key_stroke), 0x0c) // LIST again
+ PORT_BIT(0x20,IP_ACTIVE_HIGH,IPT_KEYBOARD) PORT_NAME("1-6") /*PORT_CODE(KEYCODE_5) PORT_CHAR('5')*/ PORT_CHANGED_MEMBER(DEVICE_SELF, FUNC(saturn_keybd_device::key_stroke), 0x0d)
+ PORT_BIT(0x40,IP_ACTIVE_HIGH,IPT_KEYBOARD) PORT_NAME("1-7") /*PORT_CODE(KEYCODE_6) PORT_CHAR('6')*/ PORT_CHANGED_MEMBER(DEVICE_SELF, FUNC(saturn_keybd_device::key_stroke), 0x0e)
+ PORT_BIT(0x80,IP_ACTIVE_HIGH,IPT_KEYBOARD) PORT_NAME("1-8") /*PORT_CODE(KEYCODE_7) PORT_CHAR('7')*/ PORT_CHANGED_MEMBER(DEVICE_SELF, FUNC(saturn_keybd_device::key_stroke), 0x0f)
PORT_START("KEY.2") // 0x10 - 0x17
- PORT_BIT(0x01,IP_ACTIVE_HIGH,IPT_KEYBOARD) PORT_NAME("2-1") /*PORT_CODE(KEYCODE_1) PORT_CHAR('1')*/ PORT_CHANGED_MEMBER(DEVICE_SELF, saturn_keybd_device, key_stroke, 0x10)
- PORT_BIT(0x02,IP_ACTIVE_HIGH,IPT_KEYBOARD) PORT_NAME("2-2") /*PORT_CODE(KEYCODE_1) PORT_CHAR('1')*/ PORT_CHANGED_MEMBER(DEVICE_SELF, saturn_keybd_device, key_stroke, 0x11)
+ PORT_BIT(0x01,IP_ACTIVE_HIGH,IPT_KEYBOARD) PORT_NAME("2-1") /*PORT_CODE(KEYCODE_1) PORT_CHAR('1')*/ PORT_CHANGED_MEMBER(DEVICE_SELF, FUNC(saturn_keybd_device::key_stroke), 0x10)
+ PORT_BIT(0x02,IP_ACTIVE_HIGH,IPT_KEYBOARD) PORT_NAME("2-2") /*PORT_CODE(KEYCODE_1) PORT_CHAR('1')*/ PORT_CHANGED_MEMBER(DEVICE_SELF, FUNC(saturn_keybd_device::key_stroke), 0x11)
/* TODO: break codes! */
- PORT_BIT(0x04,IP_ACTIVE_HIGH,IPT_KEYBOARD) PORT_NAME("SHIFT") /*PORT_CODE(KEYCODE_2) PORT_CHAR('2')*/ PORT_CHANGED_MEMBER(DEVICE_SELF, saturn_keybd_device, key_stroke, 0x12)
- PORT_BIT(0x08,IP_ACTIVE_HIGH,IPT_KEYBOARD) PORT_NAME("KANA SHIFT") /*PORT_CODE(KEYCODE_3) PORT_CHAR('3')*/ PORT_CHANGED_MEMBER(DEVICE_SELF, saturn_keybd_device, key_stroke, 0x13)
- PORT_BIT(0x10,IP_ACTIVE_HIGH,IPT_KEYBOARD) PORT_NAME("(special keys)") /*PORT_CODE(KEYCODE_4) PORT_CHAR('4')*/ PORT_CHANGED_MEMBER(DEVICE_SELF, saturn_keybd_device, key_stroke, 0x14)
+ PORT_BIT(0x04,IP_ACTIVE_HIGH,IPT_KEYBOARD) PORT_NAME("SHIFT") /*PORT_CODE(KEYCODE_2) PORT_CHAR('2')*/ PORT_CHANGED_MEMBER(DEVICE_SELF, FUNC(saturn_keybd_device::key_stroke), 0x12)
+ PORT_BIT(0x08,IP_ACTIVE_HIGH,IPT_KEYBOARD) PORT_NAME("KANA SHIFT") /*PORT_CODE(KEYCODE_3) PORT_CHAR('3')*/ PORT_CHANGED_MEMBER(DEVICE_SELF, FUNC(saturn_keybd_device::key_stroke), 0x13)
+ PORT_BIT(0x10,IP_ACTIVE_HIGH,IPT_KEYBOARD) PORT_NAME("(special keys)") /*PORT_CODE(KEYCODE_4) PORT_CHAR('4')*/ PORT_CHANGED_MEMBER(DEVICE_SELF, FUNC(saturn_keybd_device::key_stroke), 0x14)
- PORT_BIT(0x20,IP_ACTIVE_HIGH,IPT_KEYBOARD) PORT_NAME("Q") PORT_CODE(KEYCODE_Q) PORT_CHAR('Q') PORT_CHANGED_MEMBER(DEVICE_SELF, saturn_keybd_device, key_stroke, 0x15)
- PORT_BIT(0x40,IP_ACTIVE_HIGH,IPT_KEYBOARD) PORT_NAME("1") PORT_CODE(KEYCODE_1) PORT_CHAR('1') PORT_CHANGED_MEMBER(DEVICE_SELF, saturn_keybd_device, key_stroke, 0x16)
- PORT_BIT(0x80,IP_ACTIVE_HIGH,IPT_KEYBOARD) PORT_NAME("2-8") /*PORT_CODE(KEYCODE_7) PORT_CHAR('7')*/ PORT_CHANGED_MEMBER(DEVICE_SELF, saturn_keybd_device, key_stroke, 0x17)
+ PORT_BIT(0x20,IP_ACTIVE_HIGH,IPT_KEYBOARD) PORT_NAME("Q") PORT_CODE(KEYCODE_Q) PORT_CHAR('Q') PORT_CHANGED_MEMBER(DEVICE_SELF, FUNC(saturn_keybd_device::key_stroke), 0x15)
+ PORT_BIT(0x40,IP_ACTIVE_HIGH,IPT_KEYBOARD) PORT_NAME("1") PORT_CODE(KEYCODE_1) PORT_CHAR('1') PORT_CHANGED_MEMBER(DEVICE_SELF, FUNC(saturn_keybd_device::key_stroke), 0x16)
+ PORT_BIT(0x80,IP_ACTIVE_HIGH,IPT_KEYBOARD) PORT_NAME("2-8") /*PORT_CODE(KEYCODE_7) PORT_CHAR('7')*/ PORT_CHANGED_MEMBER(DEVICE_SELF, FUNC(saturn_keybd_device::key_stroke), 0x17)
PORT_START("KEY.3") // 0x18 - 0x1f
- PORT_BIT(0x01,IP_ACTIVE_HIGH,IPT_KEYBOARD) PORT_NAME("3-1") /*PORT_CODE(KEYCODE_1) PORT_CHAR('1')*/ PORT_CHANGED_MEMBER(DEVICE_SELF, saturn_keybd_device, key_stroke, 0x18)
- PORT_BIT(0x02,IP_ACTIVE_HIGH,IPT_KEYBOARD) PORT_NAME("3-2") /*PORT_CODE(KEYCODE_1) PORT_CHAR('1')*/ PORT_CHANGED_MEMBER(DEVICE_SELF, saturn_keybd_device, key_stroke, 0x19)
- PORT_BIT(0x04,IP_ACTIVE_HIGH,IPT_KEYBOARD) PORT_NAME("Z") PORT_CODE(KEYCODE_Z) PORT_CHAR('Z') PORT_CHANGED_MEMBER(DEVICE_SELF, saturn_keybd_device, key_stroke, 0x1a)
- PORT_BIT(0x08,IP_ACTIVE_HIGH,IPT_KEYBOARD) PORT_NAME("S") PORT_CODE(KEYCODE_S) PORT_CHAR('S') PORT_CHANGED_MEMBER(DEVICE_SELF, saturn_keybd_device, key_stroke, 0x1b)
- PORT_BIT(0x10,IP_ACTIVE_HIGH,IPT_KEYBOARD) PORT_NAME("A") PORT_CODE(KEYCODE_A) PORT_CHAR('A') PORT_CHANGED_MEMBER(DEVICE_SELF, saturn_keybd_device, key_stroke, 0x1c)
- PORT_BIT(0x20,IP_ACTIVE_HIGH,IPT_KEYBOARD) PORT_NAME("W") PORT_CODE(KEYCODE_W) PORT_CHAR('W') PORT_CHANGED_MEMBER(DEVICE_SELF, saturn_keybd_device, key_stroke, 0x1d)
- PORT_BIT(0x40,IP_ACTIVE_HIGH,IPT_KEYBOARD) PORT_NAME("2") PORT_CODE(KEYCODE_2) PORT_CHAR('2') PORT_CHANGED_MEMBER(DEVICE_SELF, saturn_keybd_device, key_stroke, 0x1e)
- PORT_BIT(0x80,IP_ACTIVE_HIGH,IPT_KEYBOARD) PORT_NAME("3-8") /*PORT_CODE(KEYCODE_7) PORT_CHAR('7')*/ PORT_CHANGED_MEMBER(DEVICE_SELF, saturn_keybd_device, key_stroke, 0x1f)
+ PORT_BIT(0x01,IP_ACTIVE_HIGH,IPT_KEYBOARD) PORT_NAME("3-1") /*PORT_CODE(KEYCODE_1) PORT_CHAR('1')*/ PORT_CHANGED_MEMBER(DEVICE_SELF, FUNC(saturn_keybd_device::key_stroke), 0x18)
+ PORT_BIT(0x02,IP_ACTIVE_HIGH,IPT_KEYBOARD) PORT_NAME("3-2") /*PORT_CODE(KEYCODE_1) PORT_CHAR('1')*/ PORT_CHANGED_MEMBER(DEVICE_SELF, FUNC(saturn_keybd_device::key_stroke), 0x19)
+ PORT_BIT(0x04,IP_ACTIVE_HIGH,IPT_KEYBOARD) PORT_NAME("Z") PORT_CODE(KEYCODE_Z) PORT_CHAR('Z') PORT_CHANGED_MEMBER(DEVICE_SELF, FUNC(saturn_keybd_device::key_stroke), 0x1a)
+ PORT_BIT(0x08,IP_ACTIVE_HIGH,IPT_KEYBOARD) PORT_NAME("S") PORT_CODE(KEYCODE_S) PORT_CHAR('S') PORT_CHANGED_MEMBER(DEVICE_SELF, FUNC(saturn_keybd_device::key_stroke), 0x1b)
+ PORT_BIT(0x10,IP_ACTIVE_HIGH,IPT_KEYBOARD) PORT_NAME("A") PORT_CODE(KEYCODE_A) PORT_CHAR('A') PORT_CHANGED_MEMBER(DEVICE_SELF, FUNC(saturn_keybd_device::key_stroke), 0x1c)
+ PORT_BIT(0x20,IP_ACTIVE_HIGH,IPT_KEYBOARD) PORT_NAME("W") PORT_CODE(KEYCODE_W) PORT_CHAR('W') PORT_CHANGED_MEMBER(DEVICE_SELF, FUNC(saturn_keybd_device::key_stroke), 0x1d)
+ PORT_BIT(0x40,IP_ACTIVE_HIGH,IPT_KEYBOARD) PORT_NAME("2") PORT_CODE(KEYCODE_2) PORT_CHAR('2') PORT_CHANGED_MEMBER(DEVICE_SELF, FUNC(saturn_keybd_device::key_stroke), 0x1e)
+ PORT_BIT(0x80,IP_ACTIVE_HIGH,IPT_KEYBOARD) PORT_NAME("3-8") /*PORT_CODE(KEYCODE_7) PORT_CHAR('7')*/ PORT_CHANGED_MEMBER(DEVICE_SELF, FUNC(saturn_keybd_device::key_stroke), 0x1f)
PORT_START("KEY.4") // 0x20 - 0x27
- PORT_BIT(0x01,IP_ACTIVE_HIGH,IPT_KEYBOARD) PORT_NAME("4-1") /*PORT_CODE(KEYCODE_1) PORT_CHAR('1')*/ PORT_CHANGED_MEMBER(DEVICE_SELF, saturn_keybd_device, key_stroke, 0x20)
- PORT_BIT(0x02,IP_ACTIVE_HIGH,IPT_KEYBOARD) PORT_NAME("C") PORT_CODE(KEYCODE_C) PORT_CHAR('C') PORT_CHANGED_MEMBER(DEVICE_SELF, saturn_keybd_device, key_stroke, 0x21)
- PORT_BIT(0x04,IP_ACTIVE_HIGH,IPT_KEYBOARD) PORT_NAME("X") PORT_CODE(KEYCODE_X) PORT_CHAR('X') PORT_CHANGED_MEMBER(DEVICE_SELF, saturn_keybd_device, key_stroke, 0x22)
- PORT_BIT(0x08,IP_ACTIVE_HIGH,IPT_KEYBOARD) PORT_NAME("D") PORT_CODE(KEYCODE_D) PORT_CHAR('D') PORT_CHANGED_MEMBER(DEVICE_SELF, saturn_keybd_device, key_stroke, 0x23)
- PORT_BIT(0x10,IP_ACTIVE_HIGH,IPT_KEYBOARD) PORT_NAME("E") PORT_CODE(KEYCODE_E) PORT_CHAR('E') PORT_CHANGED_MEMBER(DEVICE_SELF, saturn_keybd_device, key_stroke, 0x24)
- PORT_BIT(0x20,IP_ACTIVE_HIGH,IPT_KEYBOARD) PORT_NAME("4") PORT_CODE(KEYCODE_4) PORT_CHAR('4') PORT_CHANGED_MEMBER(DEVICE_SELF, saturn_keybd_device, key_stroke, 0x25)
- PORT_BIT(0x40,IP_ACTIVE_HIGH,IPT_KEYBOARD) PORT_NAME("3") PORT_CODE(KEYCODE_3) PORT_CHAR('3') PORT_CHANGED_MEMBER(DEVICE_SELF, saturn_keybd_device, key_stroke, 0x26)
- PORT_BIT(0x80,IP_ACTIVE_HIGH,IPT_KEYBOARD) PORT_NAME("4-8") /*PORT_CODE(KEYCODE_7) PORT_CHAR('7')*/ PORT_CHANGED_MEMBER(DEVICE_SELF, saturn_keybd_device, key_stroke, 0x27)
+ PORT_BIT(0x01,IP_ACTIVE_HIGH,IPT_KEYBOARD) PORT_NAME("4-1") /*PORT_CODE(KEYCODE_1) PORT_CHAR('1')*/ PORT_CHANGED_MEMBER(DEVICE_SELF, FUNC(saturn_keybd_device::key_stroke), 0x20)
+ PORT_BIT(0x02,IP_ACTIVE_HIGH,IPT_KEYBOARD) PORT_NAME("C") PORT_CODE(KEYCODE_C) PORT_CHAR('C') PORT_CHANGED_MEMBER(DEVICE_SELF, FUNC(saturn_keybd_device::key_stroke), 0x21)
+ PORT_BIT(0x04,IP_ACTIVE_HIGH,IPT_KEYBOARD) PORT_NAME("X") PORT_CODE(KEYCODE_X) PORT_CHAR('X') PORT_CHANGED_MEMBER(DEVICE_SELF, FUNC(saturn_keybd_device::key_stroke), 0x22)
+ PORT_BIT(0x08,IP_ACTIVE_HIGH,IPT_KEYBOARD) PORT_NAME("D") PORT_CODE(KEYCODE_D) PORT_CHAR('D') PORT_CHANGED_MEMBER(DEVICE_SELF, FUNC(saturn_keybd_device::key_stroke), 0x23)
+ PORT_BIT(0x10,IP_ACTIVE_HIGH,IPT_KEYBOARD) PORT_NAME("E") PORT_CODE(KEYCODE_E) PORT_CHAR('E') PORT_CHANGED_MEMBER(DEVICE_SELF, FUNC(saturn_keybd_device::key_stroke), 0x24)
+ PORT_BIT(0x20,IP_ACTIVE_HIGH,IPT_KEYBOARD) PORT_NAME("4") PORT_CODE(KEYCODE_4) PORT_CHAR('4') PORT_CHANGED_MEMBER(DEVICE_SELF, FUNC(saturn_keybd_device::key_stroke), 0x25)
+ PORT_BIT(0x40,IP_ACTIVE_HIGH,IPT_KEYBOARD) PORT_NAME("3") PORT_CODE(KEYCODE_3) PORT_CHAR('3') PORT_CHANGED_MEMBER(DEVICE_SELF, FUNC(saturn_keybd_device::key_stroke), 0x26)
+ PORT_BIT(0x80,IP_ACTIVE_HIGH,IPT_KEYBOARD) PORT_NAME("4-8") /*PORT_CODE(KEYCODE_7) PORT_CHAR('7')*/ PORT_CHANGED_MEMBER(DEVICE_SELF, FUNC(saturn_keybd_device::key_stroke), 0x27)
PORT_START("KEY.5") // 0x28 - 0x2f
- PORT_BIT(0x01,IP_ACTIVE_HIGH,IPT_KEYBOARD) PORT_NAME("5-1") /*PORT_CODE(KEYCODE_F) PORT_CHAR('F')*/ PORT_CHANGED_MEMBER(DEVICE_SELF, saturn_keybd_device, key_stroke, 0x28) // another F?
- PORT_BIT(0x02,IP_ACTIVE_HIGH,IPT_KEYBOARD) PORT_NAME("SPACE") PORT_CODE(KEYCODE_SPACE) PORT_CHAR(' ') PORT_CHANGED_MEMBER(DEVICE_SELF, saturn_keybd_device, key_stroke, 0x29)
- PORT_BIT(0x04,IP_ACTIVE_HIGH,IPT_KEYBOARD) PORT_NAME("V") PORT_CODE(KEYCODE_V) PORT_CHAR('V') PORT_CHANGED_MEMBER(DEVICE_SELF, saturn_keybd_device, key_stroke, 0x2a)
- PORT_BIT(0x08,IP_ACTIVE_HIGH,IPT_KEYBOARD) PORT_NAME("F") PORT_CODE(KEYCODE_F) PORT_CHAR('F') PORT_CHANGED_MEMBER(DEVICE_SELF, saturn_keybd_device, key_stroke, 0x2b)
- PORT_BIT(0x10,IP_ACTIVE_HIGH,IPT_KEYBOARD) PORT_NAME("T") PORT_CODE(KEYCODE_T) PORT_CHAR('T') PORT_CHANGED_MEMBER(DEVICE_SELF, saturn_keybd_device, key_stroke, 0x2c)
- PORT_BIT(0x20,IP_ACTIVE_HIGH,IPT_KEYBOARD) PORT_NAME("R") PORT_CODE(KEYCODE_R) PORT_CHAR('R') PORT_CHANGED_MEMBER(DEVICE_SELF, saturn_keybd_device, key_stroke, 0x2d)
- PORT_BIT(0x40,IP_ACTIVE_HIGH,IPT_KEYBOARD) PORT_NAME("5") PORT_CODE(KEYCODE_5) PORT_CHAR('5') PORT_CHANGED_MEMBER(DEVICE_SELF, saturn_keybd_device, key_stroke, 0x2e)
- PORT_BIT(0x80,IP_ACTIVE_HIGH,IPT_KEYBOARD) PORT_NAME("5-8") /*PORT_CODE(KEYCODE_7) PORT_CHAR('7')*/ PORT_CHANGED_MEMBER(DEVICE_SELF, saturn_keybd_device, key_stroke, 0x2f)
+ PORT_BIT(0x01,IP_ACTIVE_HIGH,IPT_KEYBOARD) PORT_NAME("5-1") /*PORT_CODE(KEYCODE_F) PORT_CHAR('F')*/ PORT_CHANGED_MEMBER(DEVICE_SELF, FUNC(saturn_keybd_device::key_stroke), 0x28) // another F?
+ PORT_BIT(0x02,IP_ACTIVE_HIGH,IPT_KEYBOARD) PORT_NAME("SPACE") PORT_CODE(KEYCODE_SPACE) PORT_CHAR(' ') PORT_CHANGED_MEMBER(DEVICE_SELF, FUNC(saturn_keybd_device::key_stroke), 0x29)
+ PORT_BIT(0x04,IP_ACTIVE_HIGH,IPT_KEYBOARD) PORT_NAME("V") PORT_CODE(KEYCODE_V) PORT_CHAR('V') PORT_CHANGED_MEMBER(DEVICE_SELF, FUNC(saturn_keybd_device::key_stroke), 0x2a)
+ PORT_BIT(0x08,IP_ACTIVE_HIGH,IPT_KEYBOARD) PORT_NAME("F") PORT_CODE(KEYCODE_F) PORT_CHAR('F') PORT_CHANGED_MEMBER(DEVICE_SELF, FUNC(saturn_keybd_device::key_stroke), 0x2b)
+ PORT_BIT(0x10,IP_ACTIVE_HIGH,IPT_KEYBOARD) PORT_NAME("T") PORT_CODE(KEYCODE_T) PORT_CHAR('T') PORT_CHANGED_MEMBER(DEVICE_SELF, FUNC(saturn_keybd_device::key_stroke), 0x2c)
+ PORT_BIT(0x20,IP_ACTIVE_HIGH,IPT_KEYBOARD) PORT_NAME("R") PORT_CODE(KEYCODE_R) PORT_CHAR('R') PORT_CHANGED_MEMBER(DEVICE_SELF, FUNC(saturn_keybd_device::key_stroke), 0x2d)
+ PORT_BIT(0x40,IP_ACTIVE_HIGH,IPT_KEYBOARD) PORT_NAME("5") PORT_CODE(KEYCODE_5) PORT_CHAR('5') PORT_CHANGED_MEMBER(DEVICE_SELF, FUNC(saturn_keybd_device::key_stroke), 0x2e)
+ PORT_BIT(0x80,IP_ACTIVE_HIGH,IPT_KEYBOARD) PORT_NAME("5-8") /*PORT_CODE(KEYCODE_7) PORT_CHAR('7')*/ PORT_CHANGED_MEMBER(DEVICE_SELF, FUNC(saturn_keybd_device::key_stroke), 0x2f)
PORT_START("KEY.6") // 0x30 - 0x37
- PORT_BIT(0x01,IP_ACTIVE_HIGH,IPT_KEYBOARD) PORT_NAME("6-1") /*PORT_CODE(KEYCODE_1) PORT_CHAR('1')*/ PORT_CHANGED_MEMBER(DEVICE_SELF, saturn_keybd_device, key_stroke, 0x30)
- PORT_BIT(0x02,IP_ACTIVE_HIGH,IPT_KEYBOARD) PORT_NAME("N") PORT_CODE(KEYCODE_N) PORT_CHAR('N') PORT_CHANGED_MEMBER(DEVICE_SELF, saturn_keybd_device, key_stroke, 0x31)
- PORT_BIT(0x04,IP_ACTIVE_HIGH,IPT_KEYBOARD) PORT_NAME("B") PORT_CODE(KEYCODE_B) PORT_CHAR('B') PORT_CHANGED_MEMBER(DEVICE_SELF, saturn_keybd_device, key_stroke, 0x32)
- PORT_BIT(0x08,IP_ACTIVE_HIGH,IPT_KEYBOARD) PORT_NAME("H") PORT_CODE(KEYCODE_H) PORT_CHAR('H') PORT_CHANGED_MEMBER(DEVICE_SELF, saturn_keybd_device, key_stroke, 0x33)
- PORT_BIT(0x10,IP_ACTIVE_HIGH,IPT_KEYBOARD) PORT_NAME("G") PORT_CODE(KEYCODE_G) PORT_CHAR('G') PORT_CHANGED_MEMBER(DEVICE_SELF, saturn_keybd_device, key_stroke, 0x34)
- PORT_BIT(0x20,IP_ACTIVE_HIGH,IPT_KEYBOARD) PORT_NAME("Y") PORT_CODE(KEYCODE_Y) PORT_CHAR('Y') PORT_CHANGED_MEMBER(DEVICE_SELF, saturn_keybd_device, key_stroke, 0x35)
- PORT_BIT(0x40,IP_ACTIVE_HIGH,IPT_KEYBOARD) PORT_NAME("6") PORT_CODE(KEYCODE_6) PORT_CHAR('6') PORT_CHANGED_MEMBER(DEVICE_SELF, saturn_keybd_device, key_stroke, 0x36)
- PORT_BIT(0x80,IP_ACTIVE_HIGH,IPT_KEYBOARD) PORT_NAME("6-8") /*PORT_CODE(KEYCODE_7) PORT_CHAR('7')*/ PORT_CHANGED_MEMBER(DEVICE_SELF, saturn_keybd_device, key_stroke, 0x37)
+ PORT_BIT(0x01,IP_ACTIVE_HIGH,IPT_KEYBOARD) PORT_NAME("6-1") /*PORT_CODE(KEYCODE_1) PORT_CHAR('1')*/ PORT_CHANGED_MEMBER(DEVICE_SELF, FUNC(saturn_keybd_device::key_stroke), 0x30)
+ PORT_BIT(0x02,IP_ACTIVE_HIGH,IPT_KEYBOARD) PORT_NAME("N") PORT_CODE(KEYCODE_N) PORT_CHAR('N') PORT_CHANGED_MEMBER(DEVICE_SELF, FUNC(saturn_keybd_device::key_stroke), 0x31)
+ PORT_BIT(0x04,IP_ACTIVE_HIGH,IPT_KEYBOARD) PORT_NAME("B") PORT_CODE(KEYCODE_B) PORT_CHAR('B') PORT_CHANGED_MEMBER(DEVICE_SELF, FUNC(saturn_keybd_device::key_stroke), 0x32)
+ PORT_BIT(0x08,IP_ACTIVE_HIGH,IPT_KEYBOARD) PORT_NAME("H") PORT_CODE(KEYCODE_H) PORT_CHAR('H') PORT_CHANGED_MEMBER(DEVICE_SELF, FUNC(saturn_keybd_device::key_stroke), 0x33)
+ PORT_BIT(0x10,IP_ACTIVE_HIGH,IPT_KEYBOARD) PORT_NAME("G") PORT_CODE(KEYCODE_G) PORT_CHAR('G') PORT_CHANGED_MEMBER(DEVICE_SELF, FUNC(saturn_keybd_device::key_stroke), 0x34)
+ PORT_BIT(0x20,IP_ACTIVE_HIGH,IPT_KEYBOARD) PORT_NAME("Y") PORT_CODE(KEYCODE_Y) PORT_CHAR('Y') PORT_CHANGED_MEMBER(DEVICE_SELF, FUNC(saturn_keybd_device::key_stroke), 0x35)
+ PORT_BIT(0x40,IP_ACTIVE_HIGH,IPT_KEYBOARD) PORT_NAME("6") PORT_CODE(KEYCODE_6) PORT_CHAR('6') PORT_CHANGED_MEMBER(DEVICE_SELF, FUNC(saturn_keybd_device::key_stroke), 0x36)
+ PORT_BIT(0x80,IP_ACTIVE_HIGH,IPT_KEYBOARD) PORT_NAME("6-8") /*PORT_CODE(KEYCODE_7) PORT_CHAR('7')*/ PORT_CHANGED_MEMBER(DEVICE_SELF, FUNC(saturn_keybd_device::key_stroke), 0x37)
PORT_START("KEY.7") // 0x38 - 0x3f
- PORT_BIT(0x01,IP_ACTIVE_HIGH,IPT_KEYBOARD) PORT_NAME("7-1") /*PORT_CODE(KEYCODE_1) PORT_CHAR('1')*/ PORT_CHANGED_MEMBER(DEVICE_SELF, saturn_keybd_device, key_stroke, 0x38)
- PORT_BIT(0x02,IP_ACTIVE_HIGH,IPT_KEYBOARD) PORT_NAME("7-2") /*PORT_CODE(KEYCODE_1) PORT_CHAR('1')*/ PORT_CHANGED_MEMBER(DEVICE_SELF, saturn_keybd_device, key_stroke, 0x39)
- PORT_BIT(0x04,IP_ACTIVE_HIGH,IPT_KEYBOARD) PORT_NAME("M") PORT_CODE(KEYCODE_M) PORT_CHAR('M') PORT_CHANGED_MEMBER(DEVICE_SELF, saturn_keybd_device, key_stroke, 0x3a)
- PORT_BIT(0x08,IP_ACTIVE_HIGH,IPT_KEYBOARD) PORT_NAME("J") PORT_CODE(KEYCODE_J) PORT_CHAR('J') PORT_CHANGED_MEMBER(DEVICE_SELF, saturn_keybd_device, key_stroke, 0x3b)
- PORT_BIT(0x10,IP_ACTIVE_HIGH,IPT_KEYBOARD) PORT_NAME("U") PORT_CODE(KEYCODE_U) PORT_CHAR('U') PORT_CHANGED_MEMBER(DEVICE_SELF, saturn_keybd_device, key_stroke, 0x3c)
- PORT_BIT(0x20,IP_ACTIVE_HIGH,IPT_KEYBOARD) PORT_NAME("7") PORT_CODE(KEYCODE_7) PORT_CHAR('7') PORT_CHANGED_MEMBER(DEVICE_SELF, saturn_keybd_device, key_stroke, 0x3d)
- PORT_BIT(0x40,IP_ACTIVE_HIGH,IPT_KEYBOARD) PORT_NAME("8") PORT_CODE(KEYCODE_8) PORT_CHAR('8') PORT_CHANGED_MEMBER(DEVICE_SELF, saturn_keybd_device, key_stroke, 0x3e)
- PORT_BIT(0x80,IP_ACTIVE_HIGH,IPT_KEYBOARD) PORT_NAME("7-8") /*PORT_CODE(KEYCODE_7) PORT_CHAR('7')*/ PORT_CHANGED_MEMBER(DEVICE_SELF, saturn_keybd_device, key_stroke, 0x3f)
+ PORT_BIT(0x01,IP_ACTIVE_HIGH,IPT_KEYBOARD) PORT_NAME("7-1") /*PORT_CODE(KEYCODE_1) PORT_CHAR('1')*/ PORT_CHANGED_MEMBER(DEVICE_SELF, FUNC(saturn_keybd_device::key_stroke), 0x38)
+ PORT_BIT(0x02,IP_ACTIVE_HIGH,IPT_KEYBOARD) PORT_NAME("7-2") /*PORT_CODE(KEYCODE_1) PORT_CHAR('1')*/ PORT_CHANGED_MEMBER(DEVICE_SELF, FUNC(saturn_keybd_device::key_stroke), 0x39)
+ PORT_BIT(0x04,IP_ACTIVE_HIGH,IPT_KEYBOARD) PORT_NAME("M") PORT_CODE(KEYCODE_M) PORT_CHAR('M') PORT_CHANGED_MEMBER(DEVICE_SELF, FUNC(saturn_keybd_device::key_stroke), 0x3a)
+ PORT_BIT(0x08,IP_ACTIVE_HIGH,IPT_KEYBOARD) PORT_NAME("J") PORT_CODE(KEYCODE_J) PORT_CHAR('J') PORT_CHANGED_MEMBER(DEVICE_SELF, FUNC(saturn_keybd_device::key_stroke), 0x3b)
+ PORT_BIT(0x10,IP_ACTIVE_HIGH,IPT_KEYBOARD) PORT_NAME("U") PORT_CODE(KEYCODE_U) PORT_CHAR('U') PORT_CHANGED_MEMBER(DEVICE_SELF, FUNC(saturn_keybd_device::key_stroke), 0x3c)
+ PORT_BIT(0x20,IP_ACTIVE_HIGH,IPT_KEYBOARD) PORT_NAME("7") PORT_CODE(KEYCODE_7) PORT_CHAR('7') PORT_CHANGED_MEMBER(DEVICE_SELF, FUNC(saturn_keybd_device::key_stroke), 0x3d)
+ PORT_BIT(0x40,IP_ACTIVE_HIGH,IPT_KEYBOARD) PORT_NAME("8") PORT_CODE(KEYCODE_8) PORT_CHAR('8') PORT_CHANGED_MEMBER(DEVICE_SELF, FUNC(saturn_keybd_device::key_stroke), 0x3e)
+ PORT_BIT(0x80,IP_ACTIVE_HIGH,IPT_KEYBOARD) PORT_NAME("7-8") /*PORT_CODE(KEYCODE_7) PORT_CHAR('7')*/ PORT_CHANGED_MEMBER(DEVICE_SELF, FUNC(saturn_keybd_device::key_stroke), 0x3f)
PORT_START("KEY.8") // 0x40 - 0x47
- PORT_BIT(0x01,IP_ACTIVE_HIGH,IPT_KEYBOARD) PORT_NAME("8-1") /*PORT_CODE(KEYCODE_1) PORT_CHAR('1')*/ PORT_CHANGED_MEMBER(DEVICE_SELF, saturn_keybd_device, key_stroke, 0x40)
- PORT_BIT(0x02,IP_ACTIVE_HIGH,IPT_KEYBOARD) PORT_NAME(",") /*PORT_CODE(KEYCODE_1) PORT_CHAR('1')*/ PORT_CHANGED_MEMBER(DEVICE_SELF, saturn_keybd_device, key_stroke, 0x41)
- PORT_BIT(0x04,IP_ACTIVE_HIGH,IPT_KEYBOARD) PORT_NAME("K") PORT_CODE(KEYCODE_K) PORT_CHAR('K') PORT_CHANGED_MEMBER(DEVICE_SELF, saturn_keybd_device, key_stroke, 0x42)
- PORT_BIT(0x08,IP_ACTIVE_HIGH,IPT_KEYBOARD) PORT_NAME("I") PORT_CODE(KEYCODE_I) PORT_CHAR('I') PORT_CHANGED_MEMBER(DEVICE_SELF, saturn_keybd_device, key_stroke, 0x43)
- PORT_BIT(0x10,IP_ACTIVE_HIGH,IPT_KEYBOARD) PORT_NAME("O") PORT_CODE(KEYCODE_O) PORT_CHAR('O') PORT_CHANGED_MEMBER(DEVICE_SELF, saturn_keybd_device, key_stroke, 0x44)
- PORT_BIT(0x20,IP_ACTIVE_HIGH,IPT_KEYBOARD) PORT_NAME("0") PORT_CODE(KEYCODE_0) PORT_CHAR('0') PORT_CHANGED_MEMBER(DEVICE_SELF, saturn_keybd_device, key_stroke, 0x45)
- PORT_BIT(0x40,IP_ACTIVE_HIGH,IPT_KEYBOARD) PORT_NAME("9") PORT_CODE(KEYCODE_9) PORT_CHAR('9') PORT_CHANGED_MEMBER(DEVICE_SELF, saturn_keybd_device, key_stroke, 0x46)
- PORT_BIT(0x80,IP_ACTIVE_HIGH,IPT_KEYBOARD) PORT_NAME("8-8") /*PORT_CODE(KEYCODE_7) PORT_CHAR('7')*/ PORT_CHANGED_MEMBER(DEVICE_SELF, saturn_keybd_device, key_stroke, 0x47)
+ PORT_BIT(0x01,IP_ACTIVE_HIGH,IPT_KEYBOARD) PORT_NAME("8-1") /*PORT_CODE(KEYCODE_1) PORT_CHAR('1')*/ PORT_CHANGED_MEMBER(DEVICE_SELF, FUNC(saturn_keybd_device::key_stroke), 0x40)
+ PORT_BIT(0x02,IP_ACTIVE_HIGH,IPT_KEYBOARD) PORT_NAME(",") /*PORT_CODE(KEYCODE_1) PORT_CHAR('1')*/ PORT_CHANGED_MEMBER(DEVICE_SELF, FUNC(saturn_keybd_device::key_stroke), 0x41)
+ PORT_BIT(0x04,IP_ACTIVE_HIGH,IPT_KEYBOARD) PORT_NAME("K") PORT_CODE(KEYCODE_K) PORT_CHAR('K') PORT_CHANGED_MEMBER(DEVICE_SELF, FUNC(saturn_keybd_device::key_stroke), 0x42)
+ PORT_BIT(0x08,IP_ACTIVE_HIGH,IPT_KEYBOARD) PORT_NAME("I") PORT_CODE(KEYCODE_I) PORT_CHAR('I') PORT_CHANGED_MEMBER(DEVICE_SELF, FUNC(saturn_keybd_device::key_stroke), 0x43)
+ PORT_BIT(0x10,IP_ACTIVE_HIGH,IPT_KEYBOARD) PORT_NAME("O") PORT_CODE(KEYCODE_O) PORT_CHAR('O') PORT_CHANGED_MEMBER(DEVICE_SELF, FUNC(saturn_keybd_device::key_stroke), 0x44)
+ PORT_BIT(0x20,IP_ACTIVE_HIGH,IPT_KEYBOARD) PORT_NAME("0") PORT_CODE(KEYCODE_0) PORT_CHAR('0') PORT_CHANGED_MEMBER(DEVICE_SELF, FUNC(saturn_keybd_device::key_stroke), 0x45)
+ PORT_BIT(0x40,IP_ACTIVE_HIGH,IPT_KEYBOARD) PORT_NAME("9") PORT_CODE(KEYCODE_9) PORT_CHAR('9') PORT_CHANGED_MEMBER(DEVICE_SELF, FUNC(saturn_keybd_device::key_stroke), 0x46)
+ PORT_BIT(0x80,IP_ACTIVE_HIGH,IPT_KEYBOARD) PORT_NAME("8-8") /*PORT_CODE(KEYCODE_7) PORT_CHAR('7')*/ PORT_CHANGED_MEMBER(DEVICE_SELF, FUNC(saturn_keybd_device::key_stroke), 0x47)
PORT_START("KEY.9") // 0x48 - 0x4f
- PORT_BIT(0x01,IP_ACTIVE_HIGH,IPT_KEYBOARD) PORT_NAME("9-1") /*PORT_CODE(KEYCODE_1) PORT_CHAR('1')*/ PORT_CHANGED_MEMBER(DEVICE_SELF, saturn_keybd_device, key_stroke, 0x48)
- PORT_BIT(0x02,IP_ACTIVE_HIGH,IPT_KEYBOARD) PORT_NAME(".") /*PORT_CODE(KEYCODE_1) PORT_CHAR('1')*/ PORT_CHANGED_MEMBER(DEVICE_SELF, saturn_keybd_device, key_stroke, 0x49)
- 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, 0x4a)
- PORT_BIT(0x08,IP_ACTIVE_HIGH,IPT_KEYBOARD) PORT_NAME("L") PORT_CODE(KEYCODE_L) PORT_CHAR('L') PORT_CHANGED_MEMBER(DEVICE_SELF, saturn_keybd_device, key_stroke, 0x4b)
- 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, 0x4c)
- PORT_BIT(0x20,IP_ACTIVE_HIGH,IPT_KEYBOARD) PORT_NAME("P") PORT_CODE(KEYCODE_P) PORT_CHAR('P') PORT_CHANGED_MEMBER(DEVICE_SELF, saturn_keybd_device, key_stroke, 0x4d)
- PORT_BIT(0x40,IP_ACTIVE_HIGH,IPT_KEYBOARD) PORT_NAME("- / =") PORT_CODE(KEYCODE_MINUS) PORT_CHAR('-') PORT_CHANGED_MEMBER(DEVICE_SELF, saturn_keybd_device, key_stroke, 0x4e)
- PORT_BIT(0x80,IP_ACTIVE_HIGH,IPT_KEYBOARD) PORT_NAME("9-8") /*PORT_CODE(KEYCODE_7) PORT_CHAR('7')*/ PORT_CHANGED_MEMBER(DEVICE_SELF, saturn_keybd_device, key_stroke, 0x4f)
+ PORT_BIT(0x01,IP_ACTIVE_HIGH,IPT_KEYBOARD) PORT_NAME("9-1") /*PORT_CODE(KEYCODE_1) PORT_CHAR('1')*/ PORT_CHANGED_MEMBER(DEVICE_SELF, FUNC(saturn_keybd_device::key_stroke), 0x48)
+ PORT_BIT(0x02,IP_ACTIVE_HIGH,IPT_KEYBOARD) PORT_NAME(".") /*PORT_CODE(KEYCODE_1) PORT_CHAR('1')*/ PORT_CHANGED_MEMBER(DEVICE_SELF, FUNC(saturn_keybd_device::key_stroke), 0x49)
+ PORT_BIT(0x04,IP_ACTIVE_HIGH,IPT_KEYBOARD) PORT_NAME("/") /*PORT_CODE(KEYCODE_2) PORT_CHAR('2')*/ PORT_CHANGED_MEMBER(DEVICE_SELF, FUNC(saturn_keybd_device::key_stroke), 0x4a)
+ PORT_BIT(0x08,IP_ACTIVE_HIGH,IPT_KEYBOARD) PORT_NAME("L") PORT_CODE(KEYCODE_L) PORT_CHAR('L') PORT_CHANGED_MEMBER(DEVICE_SELF, FUNC(saturn_keybd_device::key_stroke), 0x4b)
+ PORT_BIT(0x10,IP_ACTIVE_HIGH,IPT_KEYBOARD) PORT_NAME(";") /*PORT_CODE(KEYCODE_4) PORT_CHAR('4')*/ PORT_CHANGED_MEMBER(DEVICE_SELF, FUNC(saturn_keybd_device::key_stroke), 0x4c)
+ PORT_BIT(0x20,IP_ACTIVE_HIGH,IPT_KEYBOARD) PORT_NAME("P") PORT_CODE(KEYCODE_P) PORT_CHAR('P') PORT_CHANGED_MEMBER(DEVICE_SELF, FUNC(saturn_keybd_device::key_stroke), 0x4d)
+ PORT_BIT(0x40,IP_ACTIVE_HIGH,IPT_KEYBOARD) PORT_NAME("- / =") PORT_CODE(KEYCODE_MINUS) PORT_CHAR('-') PORT_CHANGED_MEMBER(DEVICE_SELF, FUNC(saturn_keybd_device::key_stroke), 0x4e)
+ PORT_BIT(0x80,IP_ACTIVE_HIGH,IPT_KEYBOARD) PORT_NAME("9-8") /*PORT_CODE(KEYCODE_7) PORT_CHAR('7')*/ PORT_CHANGED_MEMBER(DEVICE_SELF, FUNC(saturn_keybd_device::key_stroke), 0x4f)
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(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)
- PORT_BIT(0x20,IP_ACTIVE_HIGH,IPT_KEYBOARD) PORT_NAME("^") /*PORT_CODE(KEYCODE_5) PORT_CHAR(0xd)*/ PORT_CHANGED_MEMBER(DEVICE_SELF, saturn_keybd_device, key_stroke, 0x55)
- PORT_BIT(0x40,IP_ACTIVE_HIGH,IPT_KEYBOARD) PORT_NAME("A-7") /*PORT_CODE(KEYCODE_6) PORT_CHAR('6')*/ PORT_CHANGED_MEMBER(DEVICE_SELF, saturn_keybd_device, key_stroke, 0x56)
- PORT_BIT(0x80,IP_ACTIVE_HIGH,IPT_KEYBOARD) PORT_NAME("A-8") /*PORT_CODE(KEYCODE_7) PORT_CHAR('7')*/ PORT_CHANGED_MEMBER(DEVICE_SELF, saturn_keybd_device, key_stroke, 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, FUNC(saturn_keybd_device::key_stroke), 0x50)
+ PORT_BIT(0x02,IP_ACTIVE_HIGH,IPT_KEYBOARD) PORT_NAME(u8"¥") /*PORT_CODE(KEYCODE_1) PORT_CHAR('1')*/ PORT_CHANGED_MEMBER(DEVICE_SELF, FUNC(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, FUNC(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, FUNC(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, FUNC(saturn_keybd_device::key_stroke), 0x54)
+ PORT_BIT(0x20,IP_ACTIVE_HIGH,IPT_KEYBOARD) PORT_NAME("^") /*PORT_CODE(KEYCODE_5) PORT_CHAR(0xd)*/ PORT_CHANGED_MEMBER(DEVICE_SELF, FUNC(saturn_keybd_device::key_stroke), 0x55)
+ PORT_BIT(0x40,IP_ACTIVE_HIGH,IPT_KEYBOARD) PORT_NAME("A-7") /*PORT_CODE(KEYCODE_6) PORT_CHAR('6')*/ PORT_CHANGED_MEMBER(DEVICE_SELF, FUNC(saturn_keybd_device::key_stroke), 0x56)
+ PORT_BIT(0x80,IP_ACTIVE_HIGH,IPT_KEYBOARD) PORT_NAME("A-8") /*PORT_CODE(KEYCODE_7) PORT_CHAR('7')*/ PORT_CHANGED_MEMBER(DEVICE_SELF, FUNC(saturn_keybd_device::key_stroke), 0x57)
PORT_START("KEY.11") // 0x58 - 0x5f
- PORT_BIT(0x01,IP_ACTIVE_HIGH,IPT_KEYBOARD) PORT_NAME("B-1") /*PORT_CODE(KEYCODE_1) PORT_CHAR('1')*/ PORT_CHANGED_MEMBER(DEVICE_SELF, saturn_keybd_device, key_stroke, 0x58)
- PORT_BIT(0x02,IP_ACTIVE_HIGH,IPT_KEYBOARD) PORT_NAME("B-2") /*PORT_CODE(KEYCODE_1) PORT_CHAR('1')*/ PORT_CHANGED_MEMBER(DEVICE_SELF, saturn_keybd_device, key_stroke, 0x59)
- PORT_BIT(0x04,IP_ACTIVE_HIGH,IPT_KEYBOARD) PORT_NAME("ENTER") PORT_CODE(KEYCODE_ENTER) PORT_CHAR(0x0d) PORT_CHANGED_MEMBER(DEVICE_SELF, saturn_keybd_device, key_stroke, 0x5a)
- PORT_BIT(0x08,IP_ACTIVE_HIGH,IPT_KEYBOARD) PORT_NAME("[") /*PORT_CODE(KEYCODE_3) PORT_CHAR('3')*/ PORT_CHANGED_MEMBER(DEVICE_SELF, saturn_keybd_device, key_stroke, 0x5b) // {
- PORT_BIT(0x10,IP_ACTIVE_HIGH,IPT_KEYBOARD) PORT_NAME("B-5") /*PORT_CODE(KEYCODE_4) PORT_CHAR('4')*/ PORT_CHANGED_MEMBER(DEVICE_SELF, saturn_keybd_device, key_stroke, 0x5c)
- PORT_BIT(0x20,IP_ACTIVE_HIGH,IPT_KEYBOARD) PORT_NAME("]") /*PORT_CODE(KEYCODE_5) PORT_CHAR(0xd)*/ PORT_CHANGED_MEMBER(DEVICE_SELF, saturn_keybd_device, key_stroke, 0x5d) // }
- PORT_BIT(0x40,IP_ACTIVE_HIGH,IPT_KEYBOARD) PORT_NAME("B-7") /*PORT_CODE(KEYCODE_6) PORT_CHAR('6')*/ PORT_CHANGED_MEMBER(DEVICE_SELF, saturn_keybd_device, key_stroke, 0x5e)
- PORT_BIT(0x80,IP_ACTIVE_HIGH,IPT_KEYBOARD) PORT_NAME("B-8") /*PORT_CODE(KEYCODE_7) PORT_CHAR('7')*/ PORT_CHANGED_MEMBER(DEVICE_SELF, saturn_keybd_device, key_stroke, 0x5f)
+ PORT_BIT(0x01,IP_ACTIVE_HIGH,IPT_KEYBOARD) PORT_NAME("B-1") /*PORT_CODE(KEYCODE_1) PORT_CHAR('1')*/ PORT_CHANGED_MEMBER(DEVICE_SELF, FUNC(saturn_keybd_device::key_stroke), 0x58)
+ PORT_BIT(0x02,IP_ACTIVE_HIGH,IPT_KEYBOARD) PORT_NAME("B-2") /*PORT_CODE(KEYCODE_1) PORT_CHAR('1')*/ PORT_CHANGED_MEMBER(DEVICE_SELF, FUNC(saturn_keybd_device::key_stroke), 0x59)
+ PORT_BIT(0x04,IP_ACTIVE_HIGH,IPT_KEYBOARD) PORT_NAME("ENTER") PORT_CODE(KEYCODE_ENTER) PORT_CHAR(0x0d) PORT_CHANGED_MEMBER(DEVICE_SELF, FUNC(saturn_keybd_device::key_stroke), 0x5a)
+ PORT_BIT(0x08,IP_ACTIVE_HIGH,IPT_KEYBOARD) PORT_NAME("[") /*PORT_CODE(KEYCODE_3) PORT_CHAR('3')*/ PORT_CHANGED_MEMBER(DEVICE_SELF, FUNC(saturn_keybd_device::key_stroke), 0x5b) // {
+ PORT_BIT(0x10,IP_ACTIVE_HIGH,IPT_KEYBOARD) PORT_NAME("B-5") /*PORT_CODE(KEYCODE_4) PORT_CHAR('4')*/ PORT_CHANGED_MEMBER(DEVICE_SELF, FUNC(saturn_keybd_device::key_stroke), 0x5c)
+ PORT_BIT(0x20,IP_ACTIVE_HIGH,IPT_KEYBOARD) PORT_NAME("]") /*PORT_CODE(KEYCODE_5) PORT_CHAR(0xd)*/ PORT_CHANGED_MEMBER(DEVICE_SELF, FUNC(saturn_keybd_device::key_stroke), 0x5d) // }
+ PORT_BIT(0x40,IP_ACTIVE_HIGH,IPT_KEYBOARD) PORT_NAME("B-7") /*PORT_CODE(KEYCODE_6) PORT_CHAR('6')*/ PORT_CHANGED_MEMBER(DEVICE_SELF, FUNC(saturn_keybd_device::key_stroke), 0x5e)
+ PORT_BIT(0x80,IP_ACTIVE_HIGH,IPT_KEYBOARD) PORT_NAME("B-8") /*PORT_CODE(KEYCODE_7) PORT_CHAR('7')*/ PORT_CHANGED_MEMBER(DEVICE_SELF, FUNC(saturn_keybd_device::key_stroke), 0x5f)
PORT_START("KEY.12") // 0x60 - 0x67
- PORT_BIT(0x01,IP_ACTIVE_HIGH,IPT_KEYBOARD) PORT_NAME("C-1") /*PORT_CODE(KEYCODE_1) PORT_CHAR('1')*/ PORT_CHANGED_MEMBER(DEVICE_SELF, saturn_keybd_device, key_stroke, 0x60)
- PORT_BIT(0x02,IP_ACTIVE_HIGH,IPT_KEYBOARD) PORT_NAME("C-2") /*PORT_CODE(KEYCODE_1) PORT_CHAR('1')*/ PORT_CHANGED_MEMBER(DEVICE_SELF, saturn_keybd_device, key_stroke, 0x61)
- PORT_BIT(0x04,IP_ACTIVE_HIGH,IPT_KEYBOARD) PORT_NAME("C-3") /*PORT_CODE(KEYCODE_2) PORT_CHAR('2')*/ PORT_CHANGED_MEMBER(DEVICE_SELF, saturn_keybd_device, key_stroke, 0x62)
- PORT_BIT(0x08,IP_ACTIVE_HIGH,IPT_KEYBOARD) PORT_NAME("C-4") /*PORT_CODE(KEYCODE_3) PORT_CHAR('3')*/ PORT_CHANGED_MEMBER(DEVICE_SELF, saturn_keybd_device, key_stroke, 0x63)
- PORT_BIT(0x10,IP_ACTIVE_HIGH,IPT_KEYBOARD) PORT_NAME("C-5") /*PORT_CODE(KEYCODE_4) PORT_CHAR('4')*/ PORT_CHANGED_MEMBER(DEVICE_SELF, saturn_keybd_device, key_stroke, 0x64)
- PORT_BIT(0x20,IP_ACTIVE_HIGH,IPT_KEYBOARD) PORT_NAME("C-6") /*PORT_CODE(KEYCODE_5) PORT_CHAR(0xd)*/ PORT_CHANGED_MEMBER(DEVICE_SELF, saturn_keybd_device, key_stroke, 0x65)
- PORT_BIT(0x40,IP_ACTIVE_HIGH,IPT_KEYBOARD) PORT_NAME("BACKSPACE") PORT_CODE(KEYCODE_BACKSPACE) /* PORT_CHAR('6')*/ PORT_CHANGED_MEMBER(DEVICE_SELF, saturn_keybd_device, key_stroke, 0x66)
- PORT_BIT(0x80,IP_ACTIVE_HIGH,IPT_KEYBOARD) PORT_NAME("C-8") /*PORT_CODE(KEYCODE_7) PORT_CHAR('7')*/ PORT_CHANGED_MEMBER(DEVICE_SELF, saturn_keybd_device, key_stroke, 0x67)
+ PORT_BIT(0x01,IP_ACTIVE_HIGH,IPT_KEYBOARD) PORT_NAME("C-1") /*PORT_CODE(KEYCODE_1) PORT_CHAR('1')*/ PORT_CHANGED_MEMBER(DEVICE_SELF, FUNC(saturn_keybd_device::key_stroke), 0x60)
+ PORT_BIT(0x02,IP_ACTIVE_HIGH,IPT_KEYBOARD) PORT_NAME("C-2") /*PORT_CODE(KEYCODE_1) PORT_CHAR('1')*/ PORT_CHANGED_MEMBER(DEVICE_SELF, FUNC(saturn_keybd_device::key_stroke), 0x61)
+ PORT_BIT(0x04,IP_ACTIVE_HIGH,IPT_KEYBOARD) PORT_NAME("C-3") /*PORT_CODE(KEYCODE_2) PORT_CHAR('2')*/ PORT_CHANGED_MEMBER(DEVICE_SELF, FUNC(saturn_keybd_device::key_stroke), 0x62)
+ PORT_BIT(0x08,IP_ACTIVE_HIGH,IPT_KEYBOARD) PORT_NAME("C-4") /*PORT_CODE(KEYCODE_3) PORT_CHAR('3')*/ PORT_CHANGED_MEMBER(DEVICE_SELF, FUNC(saturn_keybd_device::key_stroke), 0x63)
+ PORT_BIT(0x10,IP_ACTIVE_HIGH,IPT_KEYBOARD) PORT_NAME("C-5") /*PORT_CODE(KEYCODE_4) PORT_CHAR('4')*/ PORT_CHANGED_MEMBER(DEVICE_SELF, FUNC(saturn_keybd_device::key_stroke), 0x64)
+ PORT_BIT(0x20,IP_ACTIVE_HIGH,IPT_KEYBOARD) PORT_NAME("C-6") /*PORT_CODE(KEYCODE_5) PORT_CHAR(0xd)*/ PORT_CHANGED_MEMBER(DEVICE_SELF, FUNC(saturn_keybd_device::key_stroke), 0x65)
+ PORT_BIT(0x40,IP_ACTIVE_HIGH,IPT_KEYBOARD) PORT_NAME("BACKSPACE") PORT_CODE(KEYCODE_BACKSPACE) /* PORT_CHAR('6')*/ PORT_CHANGED_MEMBER(DEVICE_SELF, FUNC(saturn_keybd_device::key_stroke), 0x66)
+ PORT_BIT(0x80,IP_ACTIVE_HIGH,IPT_KEYBOARD) PORT_NAME("C-8") /*PORT_CODE(KEYCODE_7) PORT_CHAR('7')*/ PORT_CHANGED_MEMBER(DEVICE_SELF, FUNC(saturn_keybd_device::key_stroke), 0x67)
PORT_START("KEY.13") // 0x68 - 0x6f
- PORT_BIT(0x01,IP_ACTIVE_HIGH,IPT_KEYBOARD) PORT_NAME("D-1") /*PORT_CODE(KEYCODE_1) PORT_CHAR('1')*/ PORT_CHANGED_MEMBER(DEVICE_SELF, saturn_keybd_device, key_stroke, 0x68)
- PORT_BIT(0x02,IP_ACTIVE_HIGH,IPT_KEYBOARD) PORT_NAME("D-2") /*PORT_CODE(KEYCODE_1) PORT_CHAR('1')*/ PORT_CHANGED_MEMBER(DEVICE_SELF, saturn_keybd_device, key_stroke, 0x69)
- PORT_BIT(0x04,IP_ACTIVE_HIGH,IPT_KEYBOARD) PORT_NAME("D-3") /*PORT_CODE(KEYCODE_2) PORT_CHAR('2')*/ PORT_CHANGED_MEMBER(DEVICE_SELF, saturn_keybd_device, key_stroke, 0x6a)
- PORT_BIT(0x08,IP_ACTIVE_HIGH,IPT_KEYBOARD) PORT_NAME("D-4") /*PORT_CODE(KEYCODE_3) PORT_CHAR('3')*/ PORT_CHANGED_MEMBER(DEVICE_SELF, saturn_keybd_device, key_stroke, 0x6b)
- PORT_BIT(0x10,IP_ACTIVE_HIGH,IPT_KEYBOARD) PORT_NAME("D-5") /*PORT_CODE(KEYCODE_4) PORT_CHAR('4')*/ PORT_CHANGED_MEMBER(DEVICE_SELF, saturn_keybd_device, key_stroke, 0x6c)
- PORT_BIT(0x20,IP_ACTIVE_HIGH,IPT_KEYBOARD) PORT_NAME("D-6") /*PORT_CODE(KEYCODE_5) PORT_CHAR(0xd)*/ PORT_CHANGED_MEMBER(DEVICE_SELF, saturn_keybd_device, key_stroke, 0x6d)
- PORT_BIT(0x40,IP_ACTIVE_HIGH,IPT_KEYBOARD) PORT_NAME("D-7") /*PORT_CODE(KEYCODE_6) PORT_CHAR('6')*/ PORT_CHANGED_MEMBER(DEVICE_SELF, saturn_keybd_device, key_stroke, 0x6e)
- PORT_BIT(0x80,IP_ACTIVE_HIGH,IPT_KEYBOARD) PORT_NAME("D-8") /*PORT_CODE(KEYCODE_7) PORT_CHAR('7')*/ PORT_CHANGED_MEMBER(DEVICE_SELF, saturn_keybd_device, key_stroke, 0x6f)
+ PORT_BIT(0x01,IP_ACTIVE_HIGH,IPT_KEYBOARD) PORT_NAME("D-1") /*PORT_CODE(KEYCODE_1) PORT_CHAR('1')*/ PORT_CHANGED_MEMBER(DEVICE_SELF, FUNC(saturn_keybd_device::key_stroke), 0x68)
+ PORT_BIT(0x02,IP_ACTIVE_HIGH,IPT_KEYBOARD) PORT_NAME("D-2") /*PORT_CODE(KEYCODE_1) PORT_CHAR('1')*/ PORT_CHANGED_MEMBER(DEVICE_SELF, FUNC(saturn_keybd_device::key_stroke), 0x69)
+ PORT_BIT(0x04,IP_ACTIVE_HIGH,IPT_KEYBOARD) PORT_NAME("D-3") /*PORT_CODE(KEYCODE_2) PORT_CHAR('2')*/ PORT_CHANGED_MEMBER(DEVICE_SELF, FUNC(saturn_keybd_device::key_stroke), 0x6a)
+ PORT_BIT(0x08,IP_ACTIVE_HIGH,IPT_KEYBOARD) PORT_NAME("D-4") /*PORT_CODE(KEYCODE_3) PORT_CHAR('3')*/ PORT_CHANGED_MEMBER(DEVICE_SELF, FUNC(saturn_keybd_device::key_stroke), 0x6b)
+ PORT_BIT(0x10,IP_ACTIVE_HIGH,IPT_KEYBOARD) PORT_NAME("D-5") /*PORT_CODE(KEYCODE_4) PORT_CHAR('4')*/ PORT_CHANGED_MEMBER(DEVICE_SELF, FUNC(saturn_keybd_device::key_stroke), 0x6c)
+ PORT_BIT(0x20,IP_ACTIVE_HIGH,IPT_KEYBOARD) PORT_NAME("D-6") /*PORT_CODE(KEYCODE_5) PORT_CHAR(0xd)*/ PORT_CHANGED_MEMBER(DEVICE_SELF, FUNC(saturn_keybd_device::key_stroke), 0x6d)
+ PORT_BIT(0x40,IP_ACTIVE_HIGH,IPT_KEYBOARD) PORT_NAME("D-7") /*PORT_CODE(KEYCODE_6) PORT_CHAR('6')*/ PORT_CHANGED_MEMBER(DEVICE_SELF, FUNC(saturn_keybd_device::key_stroke), 0x6e)
+ PORT_BIT(0x80,IP_ACTIVE_HIGH,IPT_KEYBOARD) PORT_NAME("D-8") /*PORT_CODE(KEYCODE_7) PORT_CHAR('7')*/ PORT_CHANGED_MEMBER(DEVICE_SELF, FUNC(saturn_keybd_device::key_stroke), 0x6f)
PORT_START("KEY.14") // 0x70 - 0x77
- PORT_BIT(0x01,IP_ACTIVE_HIGH,IPT_KEYBOARD) PORT_NAME("E-1") /*PORT_CODE(KEYCODE_1) PORT_CHAR('1')*/ PORT_CHANGED_MEMBER(DEVICE_SELF, saturn_keybd_device, key_stroke, 0x70)
- PORT_BIT(0x02,IP_ACTIVE_HIGH,IPT_KEYBOARD) PORT_NAME("E-2") /*PORT_CODE(KEYCODE_1) PORT_CHAR('1')*/ PORT_CHANGED_MEMBER(DEVICE_SELF, saturn_keybd_device, key_stroke, 0x71)
- PORT_BIT(0x04,IP_ACTIVE_HIGH,IPT_KEYBOARD) PORT_NAME("E-3") /*PORT_CODE(KEYCODE_2) PORT_CHAR('2')*/ PORT_CHANGED_MEMBER(DEVICE_SELF, saturn_keybd_device, key_stroke, 0x72)
- PORT_BIT(0x08,IP_ACTIVE_HIGH,IPT_KEYBOARD) PORT_NAME("E-4") /*PORT_CODE(KEYCODE_3) PORT_CHAR('3')*/ PORT_CHANGED_MEMBER(DEVICE_SELF, saturn_keybd_device, key_stroke, 0x73)
- PORT_BIT(0x10,IP_ACTIVE_HIGH,IPT_KEYBOARD) PORT_NAME("E-5") /*PORT_CODE(KEYCODE_4) PORT_CHAR('4')*/ PORT_CHANGED_MEMBER(DEVICE_SELF, saturn_keybd_device, key_stroke, 0x74)
- PORT_BIT(0x20,IP_ACTIVE_HIGH,IPT_KEYBOARD) PORT_NAME("E-6") /*PORT_CODE(KEYCODE_5) PORT_CHAR(0xd)*/ PORT_CHANGED_MEMBER(DEVICE_SELF, saturn_keybd_device, key_stroke, 0x75)
- PORT_BIT(0x40,IP_ACTIVE_HIGH,IPT_KEYBOARD) PORT_NAME("E-7") /*PORT_CODE(KEYCODE_6) PORT_CHAR('6')*/ PORT_CHANGED_MEMBER(DEVICE_SELF, saturn_keybd_device, key_stroke, 0x76)
- PORT_BIT(0x80,IP_ACTIVE_HIGH,IPT_KEYBOARD) PORT_NAME("E-8") /*PORT_CODE(KEYCODE_7) PORT_CHAR('7')*/ PORT_CHANGED_MEMBER(DEVICE_SELF, saturn_keybd_device, key_stroke, 0x77)
+ PORT_BIT(0x01,IP_ACTIVE_HIGH,IPT_KEYBOARD) PORT_NAME("E-1") /*PORT_CODE(KEYCODE_1) PORT_CHAR('1')*/ PORT_CHANGED_MEMBER(DEVICE_SELF, FUNC(saturn_keybd_device::key_stroke), 0x70)
+ PORT_BIT(0x02,IP_ACTIVE_HIGH,IPT_KEYBOARD) PORT_NAME("E-2") /*PORT_CODE(KEYCODE_1) PORT_CHAR('1')*/ PORT_CHANGED_MEMBER(DEVICE_SELF, FUNC(saturn_keybd_device::key_stroke), 0x71)
+ PORT_BIT(0x04,IP_ACTIVE_HIGH,IPT_KEYBOARD) PORT_NAME("E-3") /*PORT_CODE(KEYCODE_2) PORT_CHAR('2')*/ PORT_CHANGED_MEMBER(DEVICE_SELF, FUNC(saturn_keybd_device::key_stroke), 0x72)
+ PORT_BIT(0x08,IP_ACTIVE_HIGH,IPT_KEYBOARD) PORT_NAME("E-4") /*PORT_CODE(KEYCODE_3) PORT_CHAR('3')*/ PORT_CHANGED_MEMBER(DEVICE_SELF, FUNC(saturn_keybd_device::key_stroke), 0x73)
+ PORT_BIT(0x10,IP_ACTIVE_HIGH,IPT_KEYBOARD) PORT_NAME("E-5") /*PORT_CODE(KEYCODE_4) PORT_CHAR('4')*/ PORT_CHANGED_MEMBER(DEVICE_SELF, FUNC(saturn_keybd_device::key_stroke), 0x74)
+ PORT_BIT(0x20,IP_ACTIVE_HIGH,IPT_KEYBOARD) PORT_NAME("E-6") /*PORT_CODE(KEYCODE_5) PORT_CHAR(0xd)*/ PORT_CHANGED_MEMBER(DEVICE_SELF, FUNC(saturn_keybd_device::key_stroke), 0x75)
+ PORT_BIT(0x40,IP_ACTIVE_HIGH,IPT_KEYBOARD) PORT_NAME("E-7") /*PORT_CODE(KEYCODE_6) PORT_CHAR('6')*/ PORT_CHANGED_MEMBER(DEVICE_SELF, FUNC(saturn_keybd_device::key_stroke), 0x76)
+ PORT_BIT(0x80,IP_ACTIVE_HIGH,IPT_KEYBOARD) PORT_NAME("E-8") /*PORT_CODE(KEYCODE_7) PORT_CHAR('7')*/ PORT_CHANGED_MEMBER(DEVICE_SELF, FUNC(saturn_keybd_device::key_stroke), 0x77)
PORT_START("KEY.15") // 0x78 - 0x7f
- PORT_BIT(0x01,IP_ACTIVE_HIGH,IPT_KEYBOARD) PORT_NAME("F-1") /*PORT_CODE(KEYCODE_1) PORT_CHAR('1')*/ PORT_CHANGED_MEMBER(DEVICE_SELF, saturn_keybd_device, key_stroke, 0x78)
- PORT_BIT(0x02,IP_ACTIVE_HIGH,IPT_KEYBOARD) PORT_NAME("F-2") /*PORT_CODE(KEYCODE_1) PORT_CHAR('1')*/ PORT_CHANGED_MEMBER(DEVICE_SELF, saturn_keybd_device, key_stroke, 0x79)
- PORT_BIT(0x04,IP_ACTIVE_HIGH,IPT_KEYBOARD) PORT_NAME("F-3") /*PORT_CODE(KEYCODE_2) PORT_CHAR('2')*/ PORT_CHANGED_MEMBER(DEVICE_SELF, saturn_keybd_device, key_stroke, 0x7a)
- PORT_BIT(0x08,IP_ACTIVE_HIGH,IPT_KEYBOARD) PORT_NAME("F-4") /*PORT_CODE(KEYCODE_3) PORT_CHAR('3')*/ PORT_CHANGED_MEMBER(DEVICE_SELF, saturn_keybd_device, key_stroke, 0x7b)
- PORT_BIT(0x10,IP_ACTIVE_HIGH,IPT_KEYBOARD) PORT_NAME("F-5") /*PORT_CODE(KEYCODE_4) PORT_CHAR('4')*/ PORT_CHANGED_MEMBER(DEVICE_SELF, saturn_keybd_device, key_stroke, 0x7c)
- PORT_BIT(0x20,IP_ACTIVE_HIGH,IPT_KEYBOARD) PORT_NAME("F-6") /*PORT_CODE(KEYCODE_5) PORT_CHAR(0xd)*/ PORT_CHANGED_MEMBER(DEVICE_SELF, saturn_keybd_device, key_stroke, 0x7d)
- PORT_BIT(0x40,IP_ACTIVE_HIGH,IPT_KEYBOARD) PORT_NAME("F-7") /*PORT_CODE(KEYCODE_6) PORT_CHAR('6')*/ PORT_CHANGED_MEMBER(DEVICE_SELF, saturn_keybd_device, key_stroke, 0x7e)
- PORT_BIT(0x80,IP_ACTIVE_HIGH,IPT_KEYBOARD) PORT_NAME("ESC") /*PORT_CODE(KEYCODE_7) PORT_CHAR('7')*/ PORT_CHANGED_MEMBER(DEVICE_SELF, saturn_keybd_device, key_stroke, 0x7f) //SYSTEM CONFIGURATION
+ PORT_BIT(0x01,IP_ACTIVE_HIGH,IPT_KEYBOARD) PORT_NAME("F-1") /*PORT_CODE(KEYCODE_1) PORT_CHAR('1')*/ PORT_CHANGED_MEMBER(DEVICE_SELF, FUNC(saturn_keybd_device::key_stroke), 0x78)
+ PORT_BIT(0x02,IP_ACTIVE_HIGH,IPT_KEYBOARD) PORT_NAME("F-2") /*PORT_CODE(KEYCODE_1) PORT_CHAR('1')*/ PORT_CHANGED_MEMBER(DEVICE_SELF, FUNC(saturn_keybd_device::key_stroke), 0x79)
+ PORT_BIT(0x04,IP_ACTIVE_HIGH,IPT_KEYBOARD) PORT_NAME("F-3") /*PORT_CODE(KEYCODE_2) PORT_CHAR('2')*/ PORT_CHANGED_MEMBER(DEVICE_SELF, FUNC(saturn_keybd_device::key_stroke), 0x7a)
+ PORT_BIT(0x08,IP_ACTIVE_HIGH,IPT_KEYBOARD) PORT_NAME("F-4") /*PORT_CODE(KEYCODE_3) PORT_CHAR('3')*/ PORT_CHANGED_MEMBER(DEVICE_SELF, FUNC(saturn_keybd_device::key_stroke), 0x7b)
+ PORT_BIT(0x10,IP_ACTIVE_HIGH,IPT_KEYBOARD) PORT_NAME("F-5") /*PORT_CODE(KEYCODE_4) PORT_CHAR('4')*/ PORT_CHANGED_MEMBER(DEVICE_SELF, FUNC(saturn_keybd_device::key_stroke), 0x7c)
+ PORT_BIT(0x20,IP_ACTIVE_HIGH,IPT_KEYBOARD) PORT_NAME("F-6") /*PORT_CODE(KEYCODE_5) PORT_CHAR(0xd)*/ PORT_CHANGED_MEMBER(DEVICE_SELF, FUNC(saturn_keybd_device::key_stroke), 0x7d)
+ PORT_BIT(0x40,IP_ACTIVE_HIGH,IPT_KEYBOARD) PORT_NAME("F-7") /*PORT_CODE(KEYCODE_6) PORT_CHAR('6')*/ PORT_CHANGED_MEMBER(DEVICE_SELF, FUNC(saturn_keybd_device::key_stroke), 0x7e)
+ PORT_BIT(0x80,IP_ACTIVE_HIGH,IPT_KEYBOARD) PORT_NAME("ESC") /*PORT_CODE(KEYCODE_7) PORT_CHAR('7')*/ PORT_CHANGED_MEMBER(DEVICE_SELF, FUNC(saturn_keybd_device::key_stroke), 0x7f) //SYSTEM CONFIGURATION
PORT_START("KEYS_1") // special keys
- PORT_BIT(0x01,IP_ACTIVE_HIGH,IPT_KEYBOARD) PORT_NAME("UP") PORT_CODE(KEYCODE_UP) /*PORT_CHAR('1')*/ PORT_CHANGED_MEMBER(DEVICE_SELF, saturn_keybd_device, key_stroke, 0x78)
- PORT_BIT(0x02,IP_ACTIVE_HIGH,IPT_KEYBOARD) PORT_NAME("DOWN") PORT_CODE(KEYCODE_DOWN) /*PORT_CHAR('1')*/ PORT_CHANGED_MEMBER(DEVICE_SELF, saturn_keybd_device, key_stroke, 0x79)
- PORT_BIT(0x04,IP_ACTIVE_HIGH,IPT_KEYBOARD) PORT_NAME("LEFT") PORT_CODE(KEYCODE_LEFT) /*PORT_CHAR('2')*/ PORT_CHANGED_MEMBER(DEVICE_SELF, saturn_keybd_device, key_stroke, 0x7a)
- PORT_BIT(0x08,IP_ACTIVE_HIGH,IPT_KEYBOARD) PORT_NAME("RIGHT") PORT_CODE(KEYCODE_RIGHT) /*PORT_CHAR('3')*/ PORT_CHANGED_MEMBER(DEVICE_SELF, saturn_keybd_device, key_stroke, 0x7b)
+ PORT_BIT(0x01,IP_ACTIVE_HIGH,IPT_KEYBOARD) PORT_NAME("UP") PORT_CODE(KEYCODE_UP) /*PORT_CHAR('1')*/ PORT_CHANGED_MEMBER(DEVICE_SELF, FUNC(saturn_keybd_device::key_stroke), 0x78)
+ PORT_BIT(0x02,IP_ACTIVE_HIGH,IPT_KEYBOARD) PORT_NAME("DOWN") PORT_CODE(KEYCODE_DOWN) /*PORT_CHAR('1')*/ PORT_CHANGED_MEMBER(DEVICE_SELF, FUNC(saturn_keybd_device::key_stroke), 0x79)
+ PORT_BIT(0x04,IP_ACTIVE_HIGH,IPT_KEYBOARD) PORT_NAME("LEFT") PORT_CODE(KEYCODE_LEFT) /*PORT_CHAR('2')*/ PORT_CHANGED_MEMBER(DEVICE_SELF, FUNC(saturn_keybd_device::key_stroke), 0x7a)
+ PORT_BIT(0x08,IP_ACTIVE_HIGH,IPT_KEYBOARD) PORT_NAME("RIGHT") PORT_CODE(KEYCODE_RIGHT) /*PORT_CHAR('3')*/ PORT_CHANGED_MEMBER(DEVICE_SELF, FUNC(saturn_keybd_device::key_stroke), 0x7b)
INPUT_PORTS_END
diff --git a/src/devices/bus/sat_ctrl/keybd.h b/src/devices/bus/sat_ctrl/keybd.h
index dafb932974c..f4ff4e2515a 100644
--- a/src/devices/bus/sat_ctrl/keybd.h
+++ b/src/devices/bus/sat_ctrl/keybd.h
@@ -28,14 +28,14 @@ public:
saturn_keybd_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;
+ virtual ioport_constructor device_input_ports() const override ATTR_COLD;
DECLARE_INPUT_CHANGED_MEMBER(key_stroke);
protected:
// device-level overrides
- virtual void device_start() override;
- virtual void device_reset() override;
+ virtual void device_start() override ATTR_COLD;
+ virtual void device_reset() override ATTR_COLD;
// device_saturn_control_port_interface overrides
virtual uint8_t read_ctrl(uint8_t offset) override;
diff --git a/src/devices/bus/sat_ctrl/mouse.h b/src/devices/bus/sat_ctrl/mouse.h
index 2b896ca6b49..cf053e36c5f 100644
--- a/src/devices/bus/sat_ctrl/mouse.h
+++ b/src/devices/bus/sat_ctrl/mouse.h
@@ -28,12 +28,12 @@ public:
saturn_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;
+ virtual ioport_constructor device_input_ports() const override ATTR_COLD;
protected:
// device-level overrides
- virtual void device_start() override;
- virtual void device_reset() override;
+ virtual void device_start() override ATTR_COLD;
+ virtual void device_reset() override ATTR_COLD;
// device_saturn_control_port_interface overrides
virtual uint8_t read_ctrl(uint8_t offset) override;
diff --git a/src/devices/bus/sat_ctrl/multitap.cpp b/src/devices/bus/sat_ctrl/multitap.cpp
index 76fd4c3094a..71eacdf0053 100644
--- a/src/devices/bus/sat_ctrl/multitap.cpp
+++ b/src/devices/bus/sat_ctrl/multitap.cpp
@@ -22,10 +22,6 @@ DEFINE_DEVICE_TYPE(SATURN_MULTITAP, saturn_multitap_device, "saturn_multitap", "
// LIVE DEVICE
//**************************************************************************
-//-------------------------------------------------
-// saturn_multitap_device - constructor
-//-------------------------------------------------
-
saturn_multitap_device::saturn_multitap_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
: device_t(mconfig, SATURN_MULTITAP, tag, owner, clock)
, device_saturn_control_port_interface(mconfig, *this)
@@ -34,49 +30,23 @@ saturn_multitap_device::saturn_multitap_device(const machine_config &mconfig, co
}
-//-------------------------------------------------
-// device_start - device-specific startup
-//-------------------------------------------------
-
void saturn_multitap_device::device_start()
{
- for (int i = 0; i < 6; i++)
- m_subctrl_port[i]->device_start();
}
-//-------------------------------------------------
-// device_reset - device-specific reset
-//-------------------------------------------------
-
-void saturn_multitap_device::device_reset()
+void saturn_multitap_device::device_add_mconfig(machine_config &config)
{
+ for (auto &port : m_subctrl_port)
+ SATURN_CONTROL_PORT(config, port, saturn_joys, "joypad");
}
-//-------------------------------------------------
-// read_ctrl
-//-------------------------------------------------
uint8_t saturn_multitap_device::read_ctrl(uint8_t offset)
{
return m_subctrl_port[offset < 12 ? (offset >> 1) : 0]->read_ctrl(offset & 1);
}
-//-------------------------------------------------
-// read_id
-//-------------------------------------------------
-
uint8_t saturn_multitap_device::read_id(int idx)
{
return m_subctrl_port[idx < 6 ? idx : 0]->read_id(0);
}
-
-
-void saturn_multitap_device::device_add_mconfig(machine_config &config)
-{
- SATURN_CONTROL_PORT(config, m_subctrl_port[0], saturn_joys, "joypad");
- SATURN_CONTROL_PORT(config, m_subctrl_port[1], saturn_joys, "joypad");
- SATURN_CONTROL_PORT(config, m_subctrl_port[2], saturn_joys, "joypad");
- SATURN_CONTROL_PORT(config, m_subctrl_port[3], saturn_joys, "joypad");
- SATURN_CONTROL_PORT(config, m_subctrl_port[4], saturn_joys, "joypad");
- SATURN_CONTROL_PORT(config, m_subctrl_port[5], saturn_joys, "joypad");
-}
diff --git a/src/devices/bus/sat_ctrl/multitap.h b/src/devices/bus/sat_ctrl/multitap.h
index c90b559d96c..1d142a6cc9d 100644
--- a/src/devices/bus/sat_ctrl/multitap.h
+++ b/src/devices/bus/sat_ctrl/multitap.h
@@ -15,15 +15,11 @@
#include "ctrl.h"
-
//**************************************************************************
// TYPE DEFINITIONS
//**************************************************************************
-// ======================> saturn_multitap_device
-
-class saturn_multitap_device : public device_t,
- public device_saturn_control_port_interface
+class saturn_multitap_device : public device_t, public device_saturn_control_port_interface
{
public:
// construction/destruction
@@ -31,11 +27,8 @@ 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 void device_start() override ATTR_COLD;
+ virtual void device_add_mconfig(machine_config &config) override ATTR_COLD;
// device_saturn_control_port_interface overrides
virtual uint8_t read_ctrl(uint8_t offset) override;
diff --git a/src/devices/bus/sat_ctrl/pointer.h b/src/devices/bus/sat_ctrl/pointer.h
index 869455706ef..b2e082dd942 100644
--- a/src/devices/bus/sat_ctrl/pointer.h
+++ b/src/devices/bus/sat_ctrl/pointer.h
@@ -28,12 +28,12 @@ public:
saturn_track_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;
+ virtual ioport_constructor device_input_ports() const override ATTR_COLD;
protected:
// device-level overrides
- virtual void device_start() override;
- virtual void device_reset() override;
+ virtual void device_start() override ATTR_COLD;
+ virtual void device_reset() override ATTR_COLD;
// device_saturn_control_port_interface overrides
virtual uint8_t read_ctrl(uint8_t offset) override;
diff --git a/src/devices/bus/sat_ctrl/racing.h b/src/devices/bus/sat_ctrl/racing.h
index 9f426c9ef51..837c8e7c7cd 100644
--- a/src/devices/bus/sat_ctrl/racing.h
+++ b/src/devices/bus/sat_ctrl/racing.h
@@ -28,12 +28,12 @@ public:
saturn_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;
+ virtual ioport_constructor device_input_ports() const override ATTR_COLD;
protected:
// device-level overrides
- virtual void device_start() override;
- virtual void device_reset() override;
+ virtual void device_start() override ATTR_COLD;
+ virtual void device_reset() override ATTR_COLD;
// device_saturn_control_port_interface overrides
virtual uint8_t read_ctrl(uint8_t offset) override;
diff --git a/src/devices/bus/sat_ctrl/segatap.cpp b/src/devices/bus/sat_ctrl/segatap.cpp
index e36400125fe..baaa52071ed 100644
--- a/src/devices/bus/sat_ctrl/segatap.cpp
+++ b/src/devices/bus/sat_ctrl/segatap.cpp
@@ -10,7 +10,6 @@
#include "segatap.h"
-
//**************************************************************************
// DEVICE DEFINITIONS
//**************************************************************************
@@ -22,10 +21,6 @@ DEFINE_DEVICE_TYPE(SATURN_SEGATAP, saturn_segatap_device, "saturn_segatap", "sat
// LIVE DEVICE
//**************************************************************************
-//-------------------------------------------------
-// saturn_segatap_device - constructor
-//-------------------------------------------------
-
saturn_segatap_device::saturn_segatap_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
: device_t(mconfig, SATURN_SEGATAP, tag, owner, clock)
, device_saturn_control_port_interface(mconfig, *this)
@@ -34,47 +29,23 @@ saturn_segatap_device::saturn_segatap_device(const machine_config &mconfig, cons
}
-//-------------------------------------------------
-// device_start - device-specific startup
-//-------------------------------------------------
-
void saturn_segatap_device::device_start()
{
- for (int i = 0; i < 4; i++)
- m_subctrl_port[i]->device_start();
}
-//-------------------------------------------------
-// device_reset - device-specific reset
-//-------------------------------------------------
-
-void saturn_segatap_device::device_reset()
+void saturn_segatap_device::device_add_mconfig(machine_config &config)
{
+ for (auto &port : m_subctrl_port)
+ SATURN_CONTROL_PORT(config, port, saturn_joys, "joypad");
}
-//-------------------------------------------------
-// read_ctrl
-//-------------------------------------------------
uint8_t saturn_segatap_device::read_ctrl(uint8_t offset)
{
return m_subctrl_port[offset < 8 ? (offset >> 1) : 0]->read_ctrl(offset & 1);
}
-//-------------------------------------------------
-// read_id
-//-------------------------------------------------
-
uint8_t saturn_segatap_device::read_id(int idx)
{
return m_subctrl_port[idx < 4 ? idx : 0]->read_id(0);
}
-
-
-void saturn_segatap_device::device_add_mconfig(machine_config &config)
-{
- SATURN_CONTROL_PORT(config, m_subctrl_port[0], saturn_joys, "joypad");
- SATURN_CONTROL_PORT(config, m_subctrl_port[1], saturn_joys, "joypad");
- SATURN_CONTROL_PORT(config, m_subctrl_port[2], saturn_joys, "joypad");
- SATURN_CONTROL_PORT(config, m_subctrl_port[3], saturn_joys, "joypad");
-}
diff --git a/src/devices/bus/sat_ctrl/segatap.h b/src/devices/bus/sat_ctrl/segatap.h
index 987699e0a5a..d8ee8a0b8d8 100644
--- a/src/devices/bus/sat_ctrl/segatap.h
+++ b/src/devices/bus/sat_ctrl/segatap.h
@@ -20,10 +20,7 @@
// TYPE DEFINITIONS
//**************************************************************************
-// ======================> saturn_segatap_device
-
-class saturn_segatap_device : public device_t,
- public device_saturn_control_port_interface
+class saturn_segatap_device : public device_t, public device_saturn_control_port_interface
{
public:
// construction/destruction
@@ -31,11 +28,8 @@ 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 void device_start() override ATTR_COLD;
+ virtual void device_add_mconfig(machine_config &config) override ATTR_COLD;
// device_saturn_control_port_interface overrides
virtual uint8_t read_ctrl(uint8_t offset) override;
diff --git a/src/devices/bus/saturn/bram.cpp b/src/devices/bus/saturn/bram.cpp
index cdcc7ad4376..d8ee2764da0 100644
--- a/src/devices/bus/saturn/bram.cpp
+++ b/src/devices/bus/saturn/bram.cpp
@@ -55,14 +55,31 @@ saturn_bram32mb_device::saturn_bram32mb_device(const machine_config &mconfig, co
void saturn_bram_device::device_start()
{
+ if (m_ext_bram.empty())
+ nvram_enable_backup(false);
}
void saturn_bram_device::device_reset()
{
}
+bool saturn_bram_device::nvram_read(util::read_stream &file)
+{
+ 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)
+{
+ auto const [err, actual] = write(file, &m_ext_bram[0], m_ext_bram.size());
+ return !err;
+}
+
void saturn_bram_device::nvram_default()
{
+ if (m_ext_bram.empty())
+ return;
+
static const uint8_t init[16] =
{ 'B', 'a', 'c', 'k', 'U', 'p', 'R', 'a', 'm', ' ', 'F', 'o', 'r', 'm', 'a', 't' };
memset(&m_ext_bram[0], 0, m_ext_bram.size());
@@ -81,7 +98,7 @@ void saturn_bram_device::nvram_default()
// Battery RAM: single chip
-READ32_MEMBER(saturn_bram_device::read_ext_bram)
+uint32_t saturn_bram_device::read_ext_bram(offs_t offset)
{
if (offset < m_ext_bram.size()/2)
return (m_ext_bram[offset * 2] << 16) | m_ext_bram[offset * 2 + 1];
@@ -92,7 +109,7 @@ READ32_MEMBER(saturn_bram_device::read_ext_bram)
}
}
-WRITE32_MEMBER(saturn_bram_device::write_ext_bram)
+void saturn_bram_device::write_ext_bram(offs_t offset, uint32_t data, uint32_t mem_mask)
{
if (offset < m_ext_bram.size()/2)
{
diff --git a/src/devices/bus/saturn/bram.h b/src/devices/bus/saturn/bram.h
index a295bc78333..7833eccd8e4 100644
--- a/src/devices/bus/saturn/bram.h
+++ b/src/devices/bus/saturn/bram.h
@@ -14,21 +14,21 @@ class saturn_bram_device : public device_t,
{
public:
// reading and writing
- virtual DECLARE_READ32_MEMBER(read_ext_bram) override;
- virtual DECLARE_WRITE32_MEMBER(write_ext_bram) override;
+ virtual uint32_t read_ext_bram(offs_t offset) override;
+ virtual void write_ext_bram(offs_t offset, uint32_t data, uint32_t mem_mask = ~0) override;
protected:
// construction/destruction
saturn_bram_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock, int cart_type);
// device-level overrides
- virtual void device_start() override;
- virtual void device_reset() override;
+ virtual void device_start() override ATTR_COLD;
+ virtual void device_reset() override ATTR_COLD;
// device_nvram_interface overrides
virtual void nvram_default() override;
- virtual void nvram_read(emu_file &file) override { if (!m_ext_bram.empty()) file.read(&m_ext_bram[0], m_ext_bram.size()); }
- virtual void nvram_write(emu_file &file) override { if (!m_ext_bram.empty()) file.write(&m_ext_bram[0], m_ext_bram.size()); }
+ virtual bool nvram_read(util::read_stream &file) override;
+ virtual bool nvram_write(util::write_stream &file) override;
};
class saturn_bram4mb_device : public saturn_bram_device
diff --git a/src/devices/bus/saturn/dram.cpp b/src/devices/bus/saturn/dram.cpp
index 6d574dc28e3..c0380752aea 100644
--- a/src/devices/bus/saturn/dram.cpp
+++ b/src/devices/bus/saturn/dram.cpp
@@ -55,7 +55,7 @@ void saturn_dram_device::device_reset()
// RAM: two DRAM chips are present in the cart, thus accesses only go up to m_size/2!
-READ32_MEMBER(saturn_dram_device::read_ext_dram0)
+uint32_t saturn_dram_device::read_ext_dram0(offs_t offset)
{
if (offset < (0x400000/2)/4)
return m_ext_dram0[offset % m_ext_dram0.size()];
@@ -66,7 +66,7 @@ READ32_MEMBER(saturn_dram_device::read_ext_dram0)
}
}
-READ32_MEMBER(saturn_dram_device::read_ext_dram1)
+uint32_t saturn_dram_device::read_ext_dram1(offs_t offset)
{
if (offset < (0x400000/2)/4)
return m_ext_dram1[offset % m_ext_dram1.size()];
@@ -77,7 +77,7 @@ READ32_MEMBER(saturn_dram_device::read_ext_dram1)
}
}
-WRITE32_MEMBER(saturn_dram_device::write_ext_dram0)
+void saturn_dram_device::write_ext_dram0(offs_t offset, uint32_t data, uint32_t mem_mask)
{
if (offset < (0x400000/2)/4)
COMBINE_DATA(&m_ext_dram0[offset % m_ext_dram0.size()]);
@@ -85,7 +85,7 @@ WRITE32_MEMBER(saturn_dram_device::write_ext_dram0)
popmessage("DRAM0 write beyond its boundary! offs: %X data: %X\n", offset, data);
}
-WRITE32_MEMBER(saturn_dram_device::write_ext_dram1)
+void saturn_dram_device::write_ext_dram1(offs_t offset, uint32_t data, uint32_t mem_mask)
{
if (offset < (0x400000/2)/4)
COMBINE_DATA(&m_ext_dram1[offset % m_ext_dram1.size()]);
diff --git a/src/devices/bus/saturn/dram.h b/src/devices/bus/saturn/dram.h
index 1bef596993a..0d603093439 100644
--- a/src/devices/bus/saturn/dram.h
+++ b/src/devices/bus/saturn/dram.h
@@ -13,18 +13,18 @@ class saturn_dram_device : public device_t,
{
public:
// reading and writing
- virtual DECLARE_READ32_MEMBER(read_ext_dram0) override;
- virtual DECLARE_READ32_MEMBER(read_ext_dram1) override;
- virtual DECLARE_WRITE32_MEMBER(write_ext_dram0) override;
- virtual DECLARE_WRITE32_MEMBER(write_ext_dram1) override;
+ virtual uint32_t read_ext_dram0(offs_t offset) override;
+ virtual uint32_t read_ext_dram1(offs_t offset) override;
+ virtual void write_ext_dram0(offs_t offset, uint32_t data, uint32_t mem_mask = ~0) override;
+ virtual void write_ext_dram1(offs_t offset, uint32_t data, uint32_t mem_mask = ~0) override;
protected:
// construction/destruction
saturn_dram_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock, int cart_type);
// device-level overrides
- virtual void device_start() override;
- virtual void device_reset() override;
+ virtual void device_start() override ATTR_COLD;
+ virtual void device_reset() override ATTR_COLD;
};
class saturn_dram8mb_device : public saturn_dram_device
diff --git a/src/devices/bus/saturn/rom.cpp b/src/devices/bus/saturn/rom.cpp
index 1421018c298..5853a7b4bdb 100644
--- a/src/devices/bus/saturn/rom.cpp
+++ b/src/devices/bus/saturn/rom.cpp
@@ -47,7 +47,7 @@ void saturn_rom_device::device_reset()
mapper specific handlers
-------------------------------------------------*/
-READ32_MEMBER(saturn_rom_device::read_rom)
+uint32_t saturn_rom_device::read_rom(offs_t offset)
{
return m_rom[offset & (m_rom_size/4 - 1)];
}
diff --git a/src/devices/bus/saturn/rom.h b/src/devices/bus/saturn/rom.h
index 0fc8f2ecbea..e0ad109835a 100644
--- a/src/devices/bus/saturn/rom.h
+++ b/src/devices/bus/saturn/rom.h
@@ -15,14 +15,14 @@ public:
saturn_rom_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
// reading and writing
- virtual DECLARE_READ32_MEMBER(read_rom) override;
+ virtual uint32_t read_rom(offs_t offset) override;
protected:
saturn_rom_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock, int cart_type);
// device-level overrides
- virtual void device_start() override;
- virtual void device_reset() override;
+ virtual void device_start() override ATTR_COLD;
+ virtual void device_reset() override ATTR_COLD;
};
diff --git a/src/devices/bus/saturn/sat_slot.cpp b/src/devices/bus/saturn/sat_slot.cpp
index defdd4d025b..34a329b47ef 100644
--- a/src/devices/bus/saturn/sat_slot.cpp
+++ b/src/devices/bus/saturn/sat_slot.cpp
@@ -37,7 +37,7 @@ DEFINE_DEVICE_TYPE(SATURN_CART_SLOT, sat_cart_slot_device, "sat_cart_slot", "Sat
//-------------------------------------------------
device_sat_cart_interface::device_sat_cart_interface(const machine_config &mconfig, device_t &device, int cart_type) :
- device_slot_card_interface(mconfig, device),
+ device_interface(device, "saturncart"),
m_cart_type(cart_type),
m_rom(nullptr),
m_rom_size(0)
@@ -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;
}
}
@@ -104,8 +104,9 @@ void device_sat_cart_interface::dram1_alloc(uint32_t size)
//-------------------------------------------------
sat_cart_slot_device::sat_cart_slot_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) :
device_t(mconfig, SATURN_CART_SLOT, tag, owner, clock),
- device_image_interface(mconfig, *this),
- device_slot_interface(mconfig, *this), m_cart(nullptr)
+ device_cartrom_image_interface(mconfig, *this),
+ device_single_card_slot_interface<device_sat_cart_interface>(mconfig, *this),
+ m_cart(nullptr)
{
}
@@ -124,7 +125,7 @@ sat_cart_slot_device::~sat_cart_slot_device()
void sat_cart_slot_device::device_start()
{
- m_cart = dynamic_cast<device_sat_cart_interface *>(get_card_device());
+ m_cart = get_card_device();
}
@@ -134,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)
{
@@ -144,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);
@@ -156,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
{
@@ -176,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());
}
@@ -218,34 +209,34 @@ int sat_cart_slot_device::get_cart_type()
read
-------------------------------------------------*/
-READ32_MEMBER(sat_cart_slot_device::read_rom)
+uint32_t sat_cart_slot_device::read_rom(offs_t offset)
{
if (m_cart)
- return m_cart->read_rom(space, offset, mem_mask);
+ return m_cart->read_rom(offset);
else
return 0xffffffff;
}
-READ32_MEMBER(sat_cart_slot_device::read_ext_dram0)
+uint32_t sat_cart_slot_device::read_ext_dram0(offs_t offset)
{
if (m_cart)
- return m_cart->read_ext_dram0(space, offset, mem_mask);
+ return m_cart->read_ext_dram0(offset);
else
return 0xffffffff;
}
-READ32_MEMBER(sat_cart_slot_device::read_ext_dram1)
+uint32_t sat_cart_slot_device::read_ext_dram1(offs_t offset)
{
if (m_cart)
- return m_cart->read_ext_dram1(space, offset, mem_mask);
+ return m_cart->read_ext_dram1(offset);
else
return 0xffffffff;
}
-READ32_MEMBER(sat_cart_slot_device::read_ext_bram)
+uint32_t sat_cart_slot_device::read_ext_bram(offs_t offset)
{
if (m_cart)
- return m_cart->read_ext_bram(space, offset, mem_mask);
+ return m_cart->read_ext_bram(offset);
else
return 0xffffffff;
}
@@ -254,20 +245,20 @@ READ32_MEMBER(sat_cart_slot_device::read_ext_bram)
write
-------------------------------------------------*/
-WRITE32_MEMBER(sat_cart_slot_device::write_ext_dram0)
+void sat_cart_slot_device::write_ext_dram0(offs_t offset, uint32_t data, uint32_t mem_mask)
{
if (m_cart)
- m_cart->write_ext_dram0(space, offset, data, mem_mask);
+ m_cart->write_ext_dram0(offset, data, mem_mask);
}
-WRITE32_MEMBER(sat_cart_slot_device::write_ext_dram1)
+void sat_cart_slot_device::write_ext_dram1(offs_t offset, uint32_t data, uint32_t mem_mask)
{
if (m_cart)
- m_cart->write_ext_dram1(space, offset, data, mem_mask);
+ m_cart->write_ext_dram1(offset, data, mem_mask);
}
-WRITE32_MEMBER(sat_cart_slot_device::write_ext_bram)
+void sat_cart_slot_device::write_ext_bram(offs_t offset, uint32_t data, uint32_t mem_mask)
{
if (m_cart)
- m_cart->write_ext_bram(space, offset, data, mem_mask);
+ m_cart->write_ext_bram(offset, data, mem_mask);
}
diff --git a/src/devices/bus/saturn/sat_slot.h b/src/devices/bus/saturn/sat_slot.h
index 63a9ae0dbca..261042a1ab1 100644
--- a/src/devices/bus/saturn/sat_slot.h
+++ b/src/devices/bus/saturn/sat_slot.h
@@ -3,7 +3,7 @@
#ifndef MAME_BUS_SATURN_SAT_SLOT_H
#define MAME_BUS_SATURN_SAT_SLOT_H
-#include "softlist_dev.h"
+#include "imagedev/cartrom.h"
/***************************************************************************
@@ -13,25 +13,25 @@
// ======================> device_sat_cart_interface
-class device_sat_cart_interface : public device_slot_card_interface
+class device_sat_cart_interface : public device_interface
{
public:
virtual ~device_sat_cart_interface();
// reading from ROM
- virtual DECLARE_READ32_MEMBER(read_rom) { return 0xffffffff; }
+ virtual uint32_t read_rom(offs_t offset) { return 0xffffffff; }
// reading and writing to Extended DRAM chips
- virtual DECLARE_READ32_MEMBER(read_ext_dram0) { return 0xffffffff; }
- virtual DECLARE_WRITE32_MEMBER(write_ext_dram0) { }
- virtual DECLARE_READ32_MEMBER(read_ext_dram1) { return 0xffffffff; }
- virtual DECLARE_WRITE32_MEMBER(write_ext_dram1) { }
+ virtual uint32_t read_ext_dram0(offs_t offset) { return 0xffffffff; }
+ virtual void write_ext_dram0(offs_t offset, uint32_t data, uint32_t mem_mask = ~0) { }
+ virtual uint32_t read_ext_dram1(offs_t offset) { return 0xffffffff; }
+ virtual void write_ext_dram1(offs_t offset, uint32_t data, uint32_t mem_mask = ~0) { }
// reading and writing to Extended BRAM chip
- virtual DECLARE_READ32_MEMBER(read_ext_bram) { return 0xffffffff; }
- virtual DECLARE_WRITE32_MEMBER(write_ext_bram) { }
+ virtual uint32_t read_ext_bram(offs_t offset) { return 0xffffffff; }
+ virtual void write_ext_bram(offs_t offset, uint32_t data, uint32_t mem_mask = ~0) { }
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);
@@ -62,8 +62,8 @@ protected:
// ======================> sat_cart_slot_device
class sat_cart_slot_device : public device_t,
- public device_image_interface,
- public device_slot_interface
+ public device_cartrom_image_interface,
+ public device_single_card_slot_interface<device_sat_cart_interface>
{
public:
// construction/destruction
@@ -79,37 +79,31 @@ 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 const software_list_loader &get_software_list_loader() const override { return rom_software_list_loader::instance(); }
- int get_cart_type();
-
- virtual iodevice_t image_type() const override { return IO_CARTSLOT; }
- virtual bool is_readable() const override { return 1; }
- virtual bool is_writeable() const override { return 0; }
- virtual bool is_creatable() const override { return 0; }
- virtual bool must_be_loaded() const override { return 0; }
- virtual bool is_reset_on_load() const override { return 1; }
- virtual const char *image_interface() const override { return "sat_cart"; }
- virtual const char *file_extensions() const override { return "bin"; }
+ 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();
+
// reading and writing
- virtual DECLARE_READ32_MEMBER(read_rom);
- virtual DECLARE_READ32_MEMBER(read_ext_dram0);
- virtual DECLARE_WRITE32_MEMBER(write_ext_dram0);
- virtual DECLARE_READ32_MEMBER(read_ext_dram1);
- virtual DECLARE_WRITE32_MEMBER(write_ext_dram1);
- virtual DECLARE_READ32_MEMBER(read_ext_bram);
- virtual DECLARE_WRITE32_MEMBER(write_ext_bram);
+ virtual uint32_t read_rom(offs_t offset);
+ virtual uint32_t read_ext_dram0(offs_t offset);
+ virtual void write_ext_dram0(offs_t offset, uint32_t data, uint32_t mem_mask = ~0);
+ virtual uint32_t read_ext_dram1(offs_t offset);
+ virtual void write_ext_dram1(offs_t offset, uint32_t data, uint32_t mem_mask = ~0);
+ virtual uint32_t read_ext_bram(offs_t offset);
+ virtual void write_ext_bram(offs_t offset, uint32_t data, uint32_t mem_mask = ~0);
protected:
- // device-level overrides
- virtual void device_start() override;
+ // device_t implementation
+ virtual void device_start() override ATTR_COLD;
private:
device_sat_cart_interface* m_cart;
@@ -119,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/artecon.cpp b/src/devices/bus/sbus/artecon.cpp
index f306494035b..0117ec12cd9 100644
--- a/src/devices/bus/sbus/artecon.cpp
+++ b/src/devices/bus/sbus/artecon.cpp
@@ -55,18 +55,18 @@ void sbus_artecon_device::install_device()
m_sbus->install_device(m_base, m_base + 0x1ffffff, *this, &sbus_artecon_device::mem_map);
}
-READ32_MEMBER(sbus_artecon_device::unknown_r)
+uint32_t sbus_artecon_device::unknown_r(offs_t offset, uint32_t mem_mask)
{
logerror("%s: unknown_r: %08x & %08x\n", machine().describe_context(), offset << 2, mem_mask);
return 0;
}
-WRITE32_MEMBER(sbus_artecon_device::unknown_w)
+void sbus_artecon_device::unknown_w(offs_t offset, uint32_t data, uint32_t mem_mask)
{
logerror("%s: unknown_w: %08x = %08x & %08x\n", machine().describe_context(), offset << 2, data, mem_mask);
}
-READ32_MEMBER(sbus_artecon_device::rom_r)
+uint32_t sbus_artecon_device::rom_r(offs_t offset)
{
return ((uint32_t*)m_rom->base())[offset];
}
diff --git a/src/devices/bus/sbus/artecon.h b/src/devices/bus/sbus/artecon.h
index ce414cf51b9..4395b79bf76 100644
--- a/src/devices/bus/sbus/artecon.h
+++ b/src/devices/bus/sbus/artecon.h
@@ -22,16 +22,16 @@ public:
protected:
// device_t 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 const tiny_rom_entry *device_rom_region() const override ATTR_COLD;
+ virtual void device_add_mconfig(machine_config &config) override ATTR_COLD;
+ virtual void device_start() override ATTR_COLD;
// device_sbus_slot_interface overrides
virtual void install_device() override;
- DECLARE_READ32_MEMBER(unknown_r);
- DECLARE_WRITE32_MEMBER(unknown_w);
- DECLARE_READ32_MEMBER(rom_r);
+ uint32_t unknown_r(offs_t offset, uint32_t mem_mask = ~0);
+ void unknown_w(offs_t offset, uint32_t data, uint32_t mem_mask = ~0);
+ uint32_t rom_r(offs_t offset);
private:
void mem_map(address_map &map) override;
diff --git a/src/devices/bus/sbus/bwtwo.cpp b/src/devices/bus/sbus/bwtwo.cpp
index 65f40df715c..c034d43e05f 100644
--- a/src/devices/bus/sbus/bwtwo.cpp
+++ b/src/devices/bus/sbus/bwtwo.cpp
@@ -10,6 +10,9 @@
#include "bwtwo.h"
#include "screen.h"
+#include <algorithm>
+
+
DEFINE_DEVICE_TYPE(SBUS_BWTWO, sbus_bwtwo_device, "bwtwo", "Sun bwtwo SBus Video")
void sbus_bwtwo_device::mem_map(address_map &map)
@@ -72,14 +75,14 @@ void sbus_bwtwo_device::install_device()
uint32_t sbus_bwtwo_device::screen_update(screen_device &screen, bitmap_rgb32 &bitmap, const rectangle &cliprect)
{
- uint8_t *line = &m_vram[0];
+ uint8_t const *line = &m_vram[0];
for (int y = 0; y < 900; y++)
{
- uint32_t *scanline = &bitmap.pix32(y);
+ uint32_t *scanline = &bitmap.pix(y);
for (int x = 0; x < 1152/8; x++)
{
- memcpy(scanline, m_mono_lut[*line], sizeof(uint32_t) * 8);
+ std::copy_n(m_mono_lut[*line], 8, scanline);
line++;
scanline += 8;
}
@@ -88,28 +91,28 @@ uint32_t sbus_bwtwo_device::screen_update(screen_device &screen, bitmap_rgb32 &b
return 0;
}
-READ8_MEMBER(sbus_bwtwo_device::regs_r)
+uint8_t sbus_bwtwo_device::regs_r(offs_t offset)
{
logerror("%s: regs_r (unimplemented): %08x\n", machine().describe_context(), 0x400000 + offset);
return 0;
}
-WRITE8_MEMBER(sbus_bwtwo_device::regs_w)
+void sbus_bwtwo_device::regs_w(offs_t offset, uint8_t data)
{
logerror("%s: regs_w (unimplemented): %08x = %02x\n", machine().describe_context(), 0x400000 + offset, data);
}
-READ32_MEMBER(sbus_bwtwo_device::rom_r)
+uint32_t sbus_bwtwo_device::rom_r(offs_t offset)
{
return ((uint32_t*)m_rom->base())[offset];
}
-READ8_MEMBER(sbus_bwtwo_device::vram_r)
+uint8_t sbus_bwtwo_device::vram_r(offs_t offset)
{
return m_vram[offset];
}
-WRITE8_MEMBER(sbus_bwtwo_device::vram_w)
+void sbus_bwtwo_device::vram_w(offs_t offset, uint8_t data)
{
m_vram[offset] = data;
}
diff --git a/src/devices/bus/sbus/bwtwo.h b/src/devices/bus/sbus/bwtwo.h
index fb3408db7d4..9a9f949d20c 100644
--- a/src/devices/bus/sbus/bwtwo.h
+++ b/src/devices/bus/sbus/bwtwo.h
@@ -22,18 +22,18 @@ public:
protected:
// device_t 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 const tiny_rom_entry *device_rom_region() const override ATTR_COLD;
+ virtual void device_add_mconfig(machine_config &config) override ATTR_COLD;
+ virtual void device_start() override ATTR_COLD;
// device_sbus_slot_interface overrides
virtual void install_device() override;
- DECLARE_READ8_MEMBER(regs_r);
- DECLARE_WRITE8_MEMBER(regs_w);
- DECLARE_READ32_MEMBER(rom_r);
- DECLARE_READ8_MEMBER(vram_r);
- DECLARE_WRITE8_MEMBER(vram_w);
+ uint8_t regs_r(offs_t offset);
+ void regs_w(offs_t offset, uint8_t data);
+ uint32_t rom_r(offs_t offset);
+ uint8_t vram_r(offs_t offset);
+ void vram_w(offs_t offset, uint8_t data);
private:
uint32_t screen_update(screen_device &screen, bitmap_rgb32 &bitmap, const rectangle &cliprect);
diff --git a/src/devices/bus/sbus/cgsix.cpp b/src/devices/bus/sbus/cgsix.cpp
index beebe3dadd9..46685deb58a 100644
--- a/src/devices/bus/sbus/cgsix.cpp
+++ b/src/devices/bus/sbus/cgsix.cpp
@@ -21,6 +21,10 @@ void sbus_cgsix_device::base_map(address_map &map)
map(0x00000000, 0x01ffffff).rw(FUNC(sbus_cgsix_device::unknown_r), FUNC(sbus_cgsix_device::unknown_w));
map(0x00000000, 0x00007fff).r(FUNC(sbus_cgsix_device::rom_r));
map(0x00200000, 0x0020000f).m(m_ramdac, FUNC(bt458_device::map)).umask32(0xff000000);
+ map(0x00300000, 0x00300fff).rw(FUNC(sbus_cgsix_device::fbc_r), FUNC(sbus_cgsix_device::fbc_w));
+ map(0x00301818, 0x0030181b).rw(FUNC(sbus_cgsix_device::thc_misc_r), FUNC(sbus_cgsix_device::thc_misc_w));
+ map(0x003018fc, 0x003018ff).rw(FUNC(sbus_cgsix_device::cursor_address_r), FUNC(sbus_cgsix_device::cursor_address_w));
+ map(0x00301900, 0x003019ff).rw(FUNC(sbus_cgsix_device::cursor_ram_r), FUNC(sbus_cgsix_device::cursor_ram_w));
map(0x00700000, 0x00700fff).rw(FUNC(sbus_cgsix_device::fbc_r), FUNC(sbus_cgsix_device::fbc_w));
}
@@ -36,10 +40,14 @@ sbus_cgsix_device::sbus_cgsix_device(const machine_config &mconfig, device_type
void sbus_cgsix_device::device_start()
{
m_vram = std::make_unique<uint32_t[]>(m_vram_size / 4);
-
save_pointer(NAME(m_vram), m_vram_size / 4);
save_item(NAME(m_vram_size));
+ m_cursor_ram = std::make_unique<uint32_t[]>(32 * 2);
+ save_pointer(NAME(m_cursor_ram), 32 * 2);
+
+ save_item(NAME(m_fbc.m_config));
+ save_item(NAME(m_fbc.m_misc));
save_item(NAME(m_fbc.m_clip_check));
save_item(NAME(m_fbc.m_status));
save_item(NAME(m_fbc.m_draw_status));
@@ -84,6 +92,8 @@ void sbus_cgsix_device::device_start()
save_item(NAME(m_fbc.m_pixel_mask));
save_item(NAME(m_fbc.m_patt_align));
+ save_item(NAME(m_fbc.m_patt_align_x));
+ save_item(NAME(m_fbc.m_patt_align_y));
save_item(NAME(m_fbc.m_pattern));
save_item(NAME(m_fbc.m_ipoint_absx));
@@ -143,39 +153,50 @@ void sbus_cgsix_device::device_start()
save_item(NAME(m_fbc.m_vertex_count));
- for (int i = 0; i < 0x1000; i++)
- {
- save_item(NAME(m_fbc.m_prim_buf[i].m_absx), i);
- save_item(NAME(m_fbc.m_prim_buf[i].m_absy), i);
- save_item(NAME(m_fbc.m_prim_buf[i].m_absz), i);
- save_item(NAME(m_fbc.m_prim_buf[i].m_relx), i);
- save_item(NAME(m_fbc.m_prim_buf[i].m_rely), i);
- save_item(NAME(m_fbc.m_prim_buf[i].m_relz), i);
- save_item(NAME(m_fbc.m_prim_buf[i].m_r), i);
- save_item(NAME(m_fbc.m_prim_buf[i].m_g), i);
- save_item(NAME(m_fbc.m_prim_buf[i].m_b), i);
- save_item(NAME(m_fbc.m_prim_buf[i].m_a), i);
- }
+ m_fbc.m_prim_buf = std::make_unique<vertex[]>(0x1000); // Unknown size on hardware
+ save_pointer(NAME(reinterpret_cast<uint8_t*>(m_fbc.m_prim_buf.get())), sizeof(vertex) * 0x1000);
save_item(NAME(m_fbc.m_curr_prim_type));
+
+ save_item(NAME(m_thc_misc));
+ save_item(NAME(m_cursor_x));
+ save_item(NAME(m_cursor_y));
}
void sbus_cgsix_device::device_reset()
{
- memset(&m_fbc, 0, sizeof(m_fbc));
+ m_fbc.m_vertex_count = 0;
+ m_thc_misc = 0;
}
uint32_t sbus_cgsix_device::screen_update(screen_device &screen, bitmap_rgb32 &bitmap, const rectangle &cliprect)
{
- const pen_t *pens = m_ramdac->pens();
- uint8_t *vram = (uint8_t *)&m_vram[0];
+ pen_t const *const pens = m_ramdac->pens();
+ auto const vram = util::big_endian_cast<uint8_t const>(&m_vram[0]);
- for (int y = 0; y < 900; y++)
+ for (int16_t y = 0; y < 900; y++)
{
- uint32_t *scanline = &bitmap.pix32(y);
- for (int x = 0; x < 1152; x++)
+ uint32_t *scanline = &bitmap.pix(y);
+ const bool cursor_row_hit = (y >= m_cursor_y && y < (m_cursor_y + 32));
+ for (int16_t x = 0; x < 1152; x++)
{
- const uint8_t pixel = vram[y * 1152 + BYTE4_XOR_BE(x)];
+ uint8_t cursor_pixel = 0;
+ const bool cursor_column_hit = (x >= m_cursor_x && x < (m_cursor_x + 32));
+ if (cursor_row_hit && cursor_column_hit)
+ {
+ const int16_t cursor_row = y - m_cursor_y;
+ const uint32_t cursor_bit = 31 - (x - m_cursor_x);
+ const uint32_t cursor_plane_a = m_cursor_ram[cursor_row];
+ const uint32_t cursor_plane_b = m_cursor_ram[cursor_row + 32];
+ cursor_pixel = (BIT(cursor_plane_b, cursor_bit) << 1) | BIT(cursor_plane_a, cursor_bit);
+ if (cursor_pixel)
+ {
+ *scanline++ = pens[0x100 + cursor_pixel];
+ continue;
+ }
+ }
+
+ const uint8_t pixel = vram[y * 1152 + x];
*scanline++ = pens[pixel];
}
}
@@ -183,36 +204,42 @@ uint32_t sbus_cgsix_device::screen_update(screen_device &screen, bitmap_rgb32 &b
return 0;
}
-READ32_MEMBER(sbus_cgsix_device::rom_r)
+uint32_t sbus_cgsix_device::rom_r(offs_t offset)
{
return ((uint32_t*)m_rom->base())[offset];
}
-READ32_MEMBER(sbus_cgsix_device::unknown_r)
+uint32_t sbus_cgsix_device::unknown_r(offs_t offset, uint32_t mem_mask)
{
logerror("%s: unknown_r: %08x & %08x\n", machine().describe_context(), offset << 2, mem_mask);
return 0;
}
-WRITE32_MEMBER(sbus_cgsix_device::unknown_w)
+void sbus_cgsix_device::unknown_w(offs_t offset, uint32_t data, uint32_t mem_mask)
{
logerror("%s: unknown_w: %08x = %08x & %08x\n", machine().describe_context(), offset << 2, data, mem_mask);
}
-READ32_MEMBER(sbus_cgsix_device::vram_r)
+uint32_t sbus_cgsix_device::vram_r(offs_t offset)
{
return m_vram[offset];
}
-WRITE32_MEMBER(sbus_cgsix_device::vram_w)
+void sbus_cgsix_device::vram_w(offs_t offset, uint32_t data, uint32_t mem_mask)
{
COMBINE_DATA(&m_vram[offset]);
}
-uint8_t sbus_cgsix_device::perform_rasterop(uint8_t src, uint8_t dst)
+uint8_t sbus_cgsix_device::perform_rasterop(uint8_t src, uint8_t dst, uint8_t mask)
{
const uint32_t rops[4] = { fbc_rasterop_rop00(), fbc_rasterop_rop01(), fbc_rasterop_rop10(), fbc_rasterop_rop11() };
+ if (fbc_misc_data() == FBC_MISC_DATA_COLOR1)
+ {
+ src = BIT(src, 0) * 0xff;
+ dst = BIT(dst, 0) * 0xff;
+ }
+
uint8_t result = 0;
//logerror("src:%02x dst:%02x\n", src, dst);
for (int bit = 0; bit < 8; bit++)
@@ -223,7 +250,8 @@ uint8_t sbus_cgsix_device::perform_rasterop(uint8_t src, uint8_t dst)
const uint8_t s = src & mask;
const uint8_t d = dst & mask;
const uint32_t rop = rops[f | b];
- //logerror("f:%d b:%d s:%02x d:%02x rop:%d\n", f >> 1, b, s, d, rop);
+ //if (fbc_misc_data() == FBC_MISC_DATA_COLOR8)
+ //logerror("f:%d b:%d s:%02x d:%02x rop:%d\n", f >> 1, b, s, d, rop);
uint8_t value = 0;
switch (rop)
@@ -248,31 +276,45 @@ uint8_t sbus_cgsix_device::perform_rasterop(uint8_t src, uint8_t dst)
}
result |= value & mask;
}
+ //if (fbc_misc_data() == FBC_MISC_DATA_COLOR8)
+ //logerror("result: %02x\n", result);
return result;
}
void sbus_cgsix_device::handle_font_poke()
{
- if (fbc_misc_draw() != FBC_MISC_DRAW_RENDER)
+ if (fbc_misc_draw() > FBC_MISC_DRAW_RENDER)
{
logerror("handle_font_poke: Unsupported font draw mode %d, abandoning draw\n", fbc_misc_draw());
return;
}
+ const bool color8 = (fbc_misc_data() == FBC_MISC_DATA_COLOR8);
+
+ uint32_t pixel_mask = fbc_get_pixel_mask();
+ uint8_t plane_mask = fbc_get_plane_mask();
+
const uint32_t daddr = m_fbc.m_y0 * 1152;
- uint8_t *vram = (uint8_t*)&m_vram[0];
- vram += daddr;
+ auto const vram = util::big_endian_cast<uint8_t>(&m_vram[0]) + daddr;
const int width = (int)m_fbc.m_x1 - (int)m_fbc.m_x0;
const uint32_t font = m_fbc.m_font;
uint32_t x = m_fbc.m_x0;
- logerror("Width: %d, bits %d to %d\n", width, 31, 31 - width);
- for (int bit = 31; bit >= (31 - width); bit--)
+ //logerror("Width: %d, bits %d to %d\n", width, 31, 31 - width);
+ int step_size = color8 ? 8 : 1;
+ int start_bit = 32 - step_size;
+
+ for (int bit = start_bit; bit >= (start_bit - width * step_size) && x < 1152; bit -= step_size, x++)
{
- const uint8_t src = BIT(font, bit) ? 0xff : 0x00;
- const uint8_t dst = vram[BYTE4_XOR_BE(x)];
- vram[BYTE4_XOR_BE(x)]= perform_rasterop(src, dst);
- x++;
- if (x >= 1152) break;
+ if (!BIT(pixel_mask, 31 - (x % 32)))
+ continue;
+
+ uint8_t src = 0;
+ if (color8)
+ src = (font >> bit) & 0xff;
+ else
+ src = BIT(font, bit) ? 0xff : 0x00;
+ const uint8_t dst = vram[x];
+ vram[x] = perform_rasterop(src, dst, plane_mask);
}
m_fbc.m_x0 += m_fbc.m_autoincx;
m_fbc.m_x1 += m_fbc.m_autoincx;
@@ -280,10 +322,42 @@ void sbus_cgsix_device::handle_font_poke()
m_fbc.m_y1 += m_fbc.m_autoincy;
}
+uint32_t sbus_cgsix_device::fbc_get_pixel_mask()
+{
+ switch (fbc_rasterop_pixel())
+ {
+ default: // Ignore
+ return 0xffffffff;
+ case 1: // Zeros
+ return 0x00000000;
+ case 2: // Ones
+ return 0xffffffff;
+ break;
+ case 3: // Mask
+ return m_fbc.m_pixel_mask;
+ }
+}
+
+uint8_t sbus_cgsix_device::fbc_get_plane_mask()
+{
+ switch (fbc_rasterop_plane())
+ {
+ default: // Ignore
+ return 0xff;
+ case 1: // Zeros
+ return 0x00;
+ case 2: // Ones
+ return 0xff;
+ break;
+ case 3: // Mask
+ return (uint8_t)m_fbc.m_plane_mask;
+ }
+}
+
// NOTE: This is basically untested, and probably full of bugs!
void sbus_cgsix_device::handle_draw_command()
{
- if (fbc_misc_draw() != FBC_MISC_DRAW_RENDER)
+ if (fbc_misc_draw() > FBC_MISC_DRAW_RENDER)
{
logerror("handle_draw_command: Unsupported draw mode %d, abandoning draw\n", fbc_misc_draw());
return;
@@ -301,23 +375,48 @@ void sbus_cgsix_device::handle_draw_command()
return;
}
- uint8_t *vram = (uint8_t*)&m_vram[0];
+ auto const vram = util::big_endian_cast<uint8_t>(&m_vram[0]);
+
+ uint32_t pixel_mask = fbc_get_pixel_mask();
+ uint8_t plane_mask = fbc_get_plane_mask();
uint32_t vindex = 0;
while (vindex < m_fbc.m_vertex_count)
{
- vertex_t &v0 = m_fbc.m_prim_buf[vindex++];
- vertex_t &v1 = m_fbc.m_prim_buf[vindex++];
+ vertex &v0 = m_fbc.m_prim_buf[vindex++];
+ vertex &v1 = m_fbc.m_prim_buf[vindex++];
for (uint32_t y = v0.m_absy; y <= v1.m_absy; y++)
{
- uint8_t *line = &vram[y * 1152];
+ auto const line = vram + (y * 1152);
+ const uint16_t patt_y_index = (y - m_fbc.m_patt_align_y) % 16;
for (uint32_t x = v0.m_absx; x <= v1.m_absx; x++)
{
- const uint32_t native_x = BYTE4_XOR_BE(x);
- const uint8_t src = line[native_x];
- const uint8_t dst = src;
- line[native_x] = perform_rasterop(src, dst);
+ if (!BIT(pixel_mask, 31 - (x % 32)))
+ continue;
+
+ uint8_t src = line[x];
+
+ switch (fbc_rasterop_pattern())
+ {
+ default: // Ignore
+ break;
+ case 1: // Zeroes
+ src = 0x00;
+ break;
+ case 2: // Ones
+ src = 0xff;
+ break;
+ case 3: // Pattern register
+ {
+ const uint16_t patt_x_index = 15 - ((x - m_fbc.m_patt_align_x) % 16);
+ src = BIT(m_fbc.m_patterns[patt_y_index], patt_x_index) ? 0xff : 0x00;
+ break;
+ }
+ }
+
+ const uint8_t dst = line[x];
+ line[x] = perform_rasterop(src, dst, plane_mask);
}
}
}
@@ -327,7 +426,7 @@ void sbus_cgsix_device::handle_draw_command()
// NOTE: This is basically untested, and probably full of bugs!
void sbus_cgsix_device::handle_blit_command()
{
- uint8_t *vram = (uint8_t*)&m_vram[0];
+ auto const vram = util::big_endian_cast<uint8_t>(&m_vram[0]);
const uint32_t fbw = 1152;//(m_fbc.m_clip_maxx + 1);
logerror("Copying from %d,%d-%d,%d to %d,%d-%d,%d, width %d, height %d\n"
, m_fbc.m_x0, m_fbc.m_y0
@@ -339,27 +438,32 @@ void sbus_cgsix_device::handle_blit_command()
uint32_t dsty = m_fbc.m_y2;
for (; srcy < m_fbc.m_y1; srcy++, dsty++)
{
- uint8_t *srcline = &vram[srcy * fbw];
- uint8_t *dstline = &vram[dsty * fbw];
+ auto srcline = vram + (srcy * fbw);
+ auto dstline = vram + (dsty * fbw);
uint32_t srcx = m_fbc.m_x0;
uint32_t dstx = m_fbc.m_x2;
for (; srcx < m_fbc.m_x1; srcx++, dstx++)
{
- const uint32_t native_dstx = BYTE4_XOR_BE(dstx);
- const uint8_t src = srcline[BYTE4_XOR_BE(srcx)];
- const uint8_t dst = dstline[native_dstx];
+ const uint8_t src = srcline[srcx];
+ const uint8_t dst = dstline[dstx];
const uint8_t result = perform_rasterop(src, dst);
//logerror("vram[%d] = %02x\n", result);
- dstline[native_dstx] = result;
+ dstline[dstx] = result;
}
}
}
-READ32_MEMBER(sbus_cgsix_device::fbc_r)
+uint32_t sbus_cgsix_device::fbc_r(offs_t offset, uint32_t mem_mask)
{
uint32_t ret = 0;
switch (offset)
{
+ case FBC_CONFIG:
+ {
+ const uint32_t data = (m_fbc.m_config & FBC_CONFIG_MASK) | FBC_CONFIG_FBID | FBC_CONFIG_VERSION;
+ logerror("%s: fbc_r: CONFIG (%08x & %08x)\n", machine().describe_context(), data, mem_mask);
+ return data;
+ }
case FBC_MISC:
logerror("fbc_r: MISC (%08x & %08x)\n", m_fbc.m_misc, mem_mask);
return m_fbc.m_misc;
@@ -662,7 +766,7 @@ READ32_MEMBER(sbus_cgsix_device::fbc_r)
return ret;
}
-WRITE32_MEMBER(sbus_cgsix_device::fbc_w)
+void sbus_cgsix_device::fbc_w(offs_t offset, uint32_t data, uint32_t mem_mask)
{
static char const *const misc_bdisp_name[4] = { "IGNORE", "0", "1", "ILLEGAL" };
static char const *const misc_bread_name[4] = { "IGNORE", "0", "1", "ILLEGAL" };
@@ -686,6 +790,10 @@ WRITE32_MEMBER(sbus_cgsix_device::fbc_w)
switch (offset)
{
+ case FBC_CONFIG:
+ COMBINE_DATA(&m_fbc.m_config);
+ logerror("fbc_w: CONFIG = %08x & %08x)\n", data, mem_mask);
+ break;
case FBC_MISC:
COMBINE_DATA(&m_fbc.m_misc);
logerror("fbc_w: MISC = %08x & %08x\n", data, mem_mask);
@@ -818,7 +926,7 @@ WRITE32_MEMBER(sbus_cgsix_device::fbc_w)
COMBINE_DATA(&m_fbc.m_clip_maxx);
break;
case FBC_CLIP_MAXY:
- logerror("fbc_w: CLIP_MAXY (%08x & %08x\n", data, mem_mask);
+ logerror("fbc_w: CLIP_MAXY = %08x & %08x\n", data, mem_mask);
COMBINE_DATA(&m_fbc.m_clip_maxy);
break;
@@ -857,38 +965,56 @@ WRITE32_MEMBER(sbus_cgsix_device::fbc_w)
case FBC_PATT_ALIGN:
logerror("fbc_w: PATT_ALIGN = %08x & %08x\n", data, mem_mask);
COMBINE_DATA(&m_fbc.m_patt_align);
+ m_fbc.m_patt_align_x = (m_fbc.m_patt_align >> 16) & 0x000f;
+ m_fbc.m_patt_align_y = m_fbc.m_patt_align & 0x000f;
break;
case FBC_PATTERN0:
logerror("fbc_w: PATTERN0 = %08x & %08x\n", data, mem_mask);
COMBINE_DATA(&m_fbc.m_pattern[0]);
+ m_fbc.m_patterns[0] = m_fbc.m_pattern[0] >> 16;
+ m_fbc.m_patterns[1] = (uint16_t)m_fbc.m_pattern[0];
break;
case FBC_PATTERN1:
logerror("fbc_w: PATTERN1 = %08x & %08x\n", data, mem_mask);
COMBINE_DATA(&m_fbc.m_pattern[1]);
+ m_fbc.m_patterns[2] = m_fbc.m_pattern[1] >> 16;
+ m_fbc.m_patterns[3] = (uint16_t)m_fbc.m_pattern[1];
break;
case FBC_PATTERN2:
logerror("fbc_w: PATTERN2 = %08x & %08x\n", data, mem_mask);
COMBINE_DATA(&m_fbc.m_pattern[2]);
+ m_fbc.m_patterns[4] = m_fbc.m_pattern[2] >> 16;
+ m_fbc.m_patterns[5] = (uint16_t)m_fbc.m_pattern[2];
break;
case FBC_PATTERN3:
logerror("fbc_w: PATTERN3 = %08x & %08x\n", data, mem_mask);
COMBINE_DATA(&m_fbc.m_pattern[3]);
+ m_fbc.m_patterns[6] = m_fbc.m_pattern[3] >> 16;
+ m_fbc.m_patterns[7] = (uint16_t)m_fbc.m_pattern[3];
break;
case FBC_PATTERN4:
logerror("fbc_w: PATTERN4 = %08x & %08x\n", data, mem_mask);
COMBINE_DATA(&m_fbc.m_pattern[4]);
+ m_fbc.m_patterns[8] = m_fbc.m_pattern[4] >> 16;
+ m_fbc.m_patterns[9] = (uint16_t)m_fbc.m_pattern[4];
break;
case FBC_PATTERN5:
logerror("fbc_w: PATTERN5 = %08x & %08x\n", data, mem_mask);
COMBINE_DATA(&m_fbc.m_pattern[5]);
+ m_fbc.m_patterns[10] = m_fbc.m_pattern[5] >> 16;
+ m_fbc.m_patterns[11] = (uint16_t)m_fbc.m_pattern[5];
break;
case FBC_PATTERN6:
logerror("fbc_w: PATTERN6 = %08x & %08x\n", data, mem_mask);
COMBINE_DATA(&m_fbc.m_pattern[6]);
+ m_fbc.m_patterns[12] = m_fbc.m_pattern[6] >> 16;
+ m_fbc.m_patterns[13] = (uint16_t)m_fbc.m_pattern[6];
break;
case FBC_PATTERN7:
logerror("fbc_w: PATTERN7 = %08x & %08x\n", data, mem_mask);
COMBINE_DATA(&m_fbc.m_pattern[7]);
+ m_fbc.m_patterns[14] = m_fbc.m_pattern[7] >> 16;
+ m_fbc.m_patterns[15] = (uint16_t)m_fbc.m_pattern[7];
break;
case FBC_IPOINT_ABSX:
@@ -1104,6 +1230,71 @@ WRITE32_MEMBER(sbus_cgsix_device::fbc_w)
}
}
+uint32_t sbus_cgsix_device::cursor_address_r()
+{
+ return (m_cursor_x << 16) | (uint16_t)m_cursor_y;
+}
+
+void sbus_cgsix_device::cursor_address_w(uint32_t data)
+{
+ m_cursor_x = (int16_t)(data >> 16);
+ m_cursor_y = (int16_t)data;
+}
+
+uint32_t sbus_cgsix_device::cursor_ram_r(offs_t offset)
+{
+ return m_cursor_ram[offset];
+}
+
+void sbus_cgsix_device::cursor_ram_w(offs_t offset, uint32_t data, uint32_t mem_mask)
+{
+ COMBINE_DATA(&m_cursor_ram[offset]);
+}
+
+uint32_t sbus_cgsix_device::thc_misc_r(offs_t offset, uint32_t mem_mask)
+{
+ logerror("thc_misc_r: %08x & %08x\n", m_thc_misc | THC_MISC_REV, mem_mask);
+ return m_thc_misc | THC_MISC_REV;
+}
+
+void sbus_cgsix_device::thc_misc_w(offs_t offset, uint32_t data, uint32_t mem_mask)
+{
+ logerror("thc_misc_w: %08x & %08x\n", data, mem_mask);
+ if (BIT(data, THC_MISC_IRQ_BIT) && BIT(m_thc_misc, THC_MISC_IRQ_BIT))
+ {
+ data &= ~(1 << THC_MISC_IRQ_BIT);
+ lower_irq(4);
+ }
+ if (BIT(data, THC_MISC_IRQEN_BIT))
+ {
+ data &= ~(1 << THC_MISC_IRQ_BIT);
+ }
+
+ COMBINE_DATA(&m_thc_misc);
+ m_thc_misc &= THC_MISC_WRITE_MASK;
+}
+
+void sbus_cgsix_device::vblank_w(int state)
+{
+ int old_state = BIT(m_thc_misc, THC_MISC_VSYNC_BIT);
+ if (old_state != state)
+ {
+ if (state)
+ {
+ m_thc_misc |= 1 << THC_MISC_VSYNC_BIT;
+ if (BIT(m_thc_misc, THC_MISC_IRQEN_BIT))
+ {
+ m_thc_misc |= 1 << THC_MISC_IRQ_BIT;
+ raise_irq(4);
+ }
+ }
+ else
+ {
+ m_thc_misc &= ~(1 << THC_MISC_VSYNC_BIT);
+ }
+ }
+}
+
//-------------------------------------------------
// TurboGX implementation
//-------------------------------------------------
@@ -1128,9 +1319,8 @@ void sbus_turbogx_device::device_add_mconfig(machine_config &config)
{
SCREEN(config, m_screen, SCREEN_TYPE_RASTER);
m_screen->set_screen_update(FUNC(sbus_turbogx_device::screen_update));
- m_screen->set_size(1152, 900);
- m_screen->set_visarea(0, 1152-1, 0, 900-1);
- m_screen->set_refresh_hz(72);
+ m_screen->set_raw(105.561_MHz_XTAL, 1472, 0, 1152, 943, 0, 900);
+ m_screen->screen_vblank().set(FUNC(sbus_turbogx_device::vblank_w));
BT458(config, m_ramdac, 0);
}
@@ -1172,6 +1362,7 @@ void sbus_turbogxp_device::device_add_mconfig(machine_config &config)
m_screen->set_size(1152, 900);
m_screen->set_visarea(0, 1152-1, 0, 900-1);
m_screen->set_refresh_hz(72);
+ m_screen->screen_vblank().set(FUNC(sbus_turbogxp_device::vblank_w));
BT467(config, m_ramdac, 0);
}
diff --git a/src/devices/bus/sbus/cgsix.h b/src/devices/bus/sbus/cgsix.h
index 3bee124d229..e6fd8da7790 100644
--- a/src/devices/bus/sbus/cgsix.h
+++ b/src/devices/bus/sbus/cgsix.h
@@ -34,24 +34,31 @@ protected:
void set_vram_size(uint32_t vram_size) { m_vram_size = vram_size; }
// device_t overrides
- virtual void device_start() override;
- virtual void device_reset() override;
-
- DECLARE_READ32_MEMBER(rom_r);
- DECLARE_READ32_MEMBER(unknown_r);
- DECLARE_WRITE32_MEMBER(unknown_w);
- DECLARE_READ32_MEMBER(vram_r);
- DECLARE_WRITE32_MEMBER(vram_w);
- DECLARE_READ32_MEMBER(fbc_r);
- DECLARE_WRITE32_MEMBER(fbc_w);
+ virtual void device_start() override ATTR_COLD;
+ virtual void device_reset() override ATTR_COLD;
+
+ uint32_t rom_r(offs_t offset);
+ uint32_t unknown_r(offs_t offset, uint32_t mem_mask = ~0);
+ void unknown_w(offs_t offset, uint32_t data, uint32_t mem_mask = ~0);
+ uint32_t vram_r(offs_t offset);
+ void vram_w(offs_t offset, uint32_t data, uint32_t mem_mask = ~0);
+ uint32_t fbc_r(offs_t offset, uint32_t mem_mask = ~0);
+ void fbc_w(offs_t offset, uint32_t data, uint32_t mem_mask = ~0);
+ uint32_t thc_misc_r(offs_t offset, uint32_t mem_mask = ~0);
+ void thc_misc_w(offs_t offset, uint32_t data, uint32_t mem_mask = ~0);
+ uint32_t cursor_address_r();
+ 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);
+ 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 perform_rasterop(uint8_t src, uint8_t dst, uint8_t mask = 0xff);
void handle_font_poke();
void handle_draw_command();
void handle_blit_command();
- void base_map(address_map &map);
+ void base_map(address_map &map) ATTR_COLD;
enum
{
@@ -75,6 +82,27 @@ protected:
enum
{
+ THC_MISC_IRQ_BIT = 4,
+ THC_MISC_IRQEN_BIT = 5,
+ THC_MISC_CURRES_BIT = 6,
+ THC_MISC_SYNCEN_BIT = 7,
+ THC_MISC_VSYNC_BIT = 8,
+ THC_MISC_SYNC_BIT = 9,
+ THC_MISC_ENVID_BIT = 10,
+ THC_MISC_RESET_BIT = 12,
+ THC_MISC_REV = 0x00010000,
+ THC_MISC_WRITE_MASK = 0x000014ff
+ };
+
+ enum
+ {
+ FBC_CONFIG_FBID = 0x60000000,
+ FBC_CONFIG_VERSION = 0x00100000,
+ FBC_CONFIG_MASK = 0x000f3fff
+ };
+
+ enum
+ {
FBC_MISC_INDEX_SHIFT = 4,
FBC_MISC_INDEX_MOD_SHIFT = 6,
FBC_MISC_BDISP_SHIFT = 7,
@@ -148,6 +176,8 @@ protected:
inline uint32_t fbc_misc_draw() { return (m_fbc.m_misc >> FBC_MISC_DRAW_SHIFT) & FBC_MISC_DRAW_MASK; }
inline uint32_t fbc_misc_data() { return (m_fbc.m_misc >> FBC_MISC_DATA_SHIFT) & FBC_MISC_DATA_MASK; }
inline uint32_t fbc_misc_blit() { return (m_fbc.m_misc >> FBC_MISC_BLIT_SHIFT) & FBC_MISC_BLIT_MASK; }
+ inline uint8_t fbc_get_plane_mask();
+ inline uint32_t fbc_get_pixel_mask();
enum
{
@@ -227,6 +257,7 @@ protected:
enum
{
+ FBC_CONFIG = 0x000/4,
FBC_MISC = 0x004/4,
FBC_CLIP_CHECK = 0x008/4,
@@ -333,7 +364,7 @@ protected:
FBC_IRECT_A = 0x93c/4,
};
- struct vertex_t
+ struct vertex
{
uint32_t m_absx;
uint32_t m_absy;
@@ -358,8 +389,9 @@ protected:
PRIM_COUNT
};
- struct fbc_t
+ struct fbc
{
+ uint32_t m_config;
uint32_t m_misc;
uint32_t m_clip_check;
uint32_t m_status;
@@ -405,7 +437,10 @@ protected:
uint32_t m_pixel_mask;
uint32_t m_patt_align;
+ uint16_t m_patt_align_x;
+ uint16_t m_patt_align_y;
uint32_t m_pattern[8];
+ uint16_t m_patterns[16];
uint32_t m_ipoint_absx;
uint32_t m_ipoint_absy;
@@ -462,17 +497,22 @@ protected:
uint32_t m_irect_b;
uint32_t m_irect_a;
- vertex_t m_prim_buf[0x1000]; // unknown size
+ std::unique_ptr<vertex[]> m_prim_buf;
uint32_t m_vertex_count;
uint32_t m_curr_prim_type;
};
+ uint32_t m_thc_misc;
+ int16_t m_cursor_x;
+ int16_t m_cursor_y;
+
required_memory_region m_rom;
std::unique_ptr<uint32_t[]> m_vram;
+ std::unique_ptr<uint32_t[]> m_cursor_ram;
required_device<screen_device> m_screen;
required_device<bt458_device> m_ramdac;
- fbc_t m_fbc;
+ fbc m_fbc;
uint32_t m_vram_size;
};
@@ -484,7 +524,7 @@ public:
protected:
// device_t overrides
- virtual const tiny_rom_entry *device_rom_region() const override;
+ virtual const tiny_rom_entry *device_rom_region() const override ATTR_COLD;
void device_add_mconfig(machine_config &config) override;
// device_sbus_slot_interface overrides
@@ -500,7 +540,7 @@ public:
protected:
// device_t overrides
- virtual const tiny_rom_entry *device_rom_region() const override;
+ virtual const tiny_rom_entry *device_rom_region() const override ATTR_COLD;
void device_add_mconfig(machine_config &config) override;
// device_sbus_slot_interface overrides
diff --git a/src/devices/bus/sbus/cgthree.cpp b/src/devices/bus/sbus/cgthree.cpp
index 091efef3b21..2ca7e930c04 100644
--- a/src/devices/bus/sbus/cgthree.cpp
+++ b/src/devices/bus/sbus/cgthree.cpp
@@ -67,15 +67,15 @@ void sbus_cgthree_device::install_device()
uint32_t sbus_cgthree_device::screen_update(screen_device &screen, bitmap_rgb32 &bitmap, const rectangle &cliprect)
{
- const pen_t *pens = m_ramdac->pens();
- uint8_t *vram = (uint8_t *)&m_vram[0];
+ pen_t const *const pens = m_ramdac->pens();
+ auto const vram = util::big_endian_cast<uint8_t const>(&m_vram[0]);
for (int y = 0; y < 900; y++)
{
- uint32_t *scanline = &bitmap.pix32(y);
+ uint32_t *scanline = &bitmap.pix(y);
for (int x = 0; x < 1152; x++)
{
- const uint8_t pixel = vram[y * 1152 + BYTE4_XOR_BE(x)];
+ const uint8_t pixel = vram[y * 1152 + x];
*scanline++ = pens[pixel];
}
}
@@ -83,39 +83,39 @@ uint32_t sbus_cgthree_device::screen_update(screen_device &screen, bitmap_rgb32
return 0;
}
-READ32_MEMBER(sbus_cgthree_device::unknown_r)
+uint32_t sbus_cgthree_device::unknown_r(offs_t offset, uint32_t mem_mask)
{
logerror("%s: unknown_r: %08x & %08x\n", machine().describe_context(), offset << 2, mem_mask);
return 0;
}
-WRITE32_MEMBER(sbus_cgthree_device::unknown_w)
+void sbus_cgthree_device::unknown_w(offs_t offset, uint32_t data, uint32_t mem_mask)
{
logerror("%s: unknown_w: %08x = %08x & %08x\n", machine().describe_context(), offset << 2, data, mem_mask);
}
-READ8_MEMBER(sbus_cgthree_device::regs_r)
+uint8_t sbus_cgthree_device::regs_r(offs_t offset)
{
logerror("%s: regs_r: Unimplemented: %08x\n", machine().describe_context(), 0x7ff800 + offset);
return 0;
}
-WRITE8_MEMBER(sbus_cgthree_device::regs_w)
+void sbus_cgthree_device::regs_w(offs_t offset, uint8_t data)
{
logerror("%s: regs_w: Unimplemented: %08x = %02x\n", machine().describe_context(), 0x7ff800 + offset, data);
}
-READ32_MEMBER(sbus_cgthree_device::rom_r)
+uint32_t sbus_cgthree_device::rom_r(offs_t offset)
{
return ((uint32_t*)m_rom->base())[offset];
}
-READ32_MEMBER(sbus_cgthree_device::vram_r)
+uint32_t sbus_cgthree_device::vram_r(offs_t offset)
{
return m_vram[offset];
}
-WRITE32_MEMBER(sbus_cgthree_device::vram_w)
+void sbus_cgthree_device::vram_w(offs_t offset, uint32_t data, uint32_t mem_mask)
{
COMBINE_DATA(&m_vram[offset]);
}
diff --git a/src/devices/bus/sbus/cgthree.h b/src/devices/bus/sbus/cgthree.h
index 9b99d4a2fba..4169f73ffa5 100644
--- a/src/devices/bus/sbus/cgthree.h
+++ b/src/devices/bus/sbus/cgthree.h
@@ -24,22 +24,21 @@ public:
protected:
// device_t 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;
+ virtual const tiny_rom_entry *device_rom_region() const override ATTR_COLD;
+ 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;
// device_sbus_slot_interface overrides
virtual void install_device() override;
- DECLARE_READ32_MEMBER(unknown_r);
- DECLARE_WRITE32_MEMBER(unknown_w);
- DECLARE_WRITE32_MEMBER(palette_w);
- DECLARE_READ8_MEMBER(regs_r);
- DECLARE_WRITE8_MEMBER(regs_w);
- DECLARE_READ32_MEMBER(rom_r);
- DECLARE_READ32_MEMBER(vram_r);
- DECLARE_WRITE32_MEMBER(vram_w);
+ uint32_t unknown_r(offs_t offset, uint32_t mem_mask = ~0);
+ void unknown_w(offs_t offset, uint32_t data, uint32_t mem_mask = ~0);
+ uint8_t regs_r(offs_t offset);
+ void regs_w(offs_t offset, uint8_t data);
+ uint32_t rom_r(offs_t offset);
+ uint32_t vram_r(offs_t offset);
+ void vram_w(offs_t offset, uint32_t data, uint32_t mem_mask = ~0);
private:
uint32_t screen_update(screen_device &screen, bitmap_rgb32 &bitmap, const rectangle &cliprect);
diff --git a/src/devices/bus/sbus/hme.cpp b/src/devices/bus/sbus/hme.cpp
index eb6d5852138..b11354f8e1e 100644
--- a/src/devices/bus/sbus/hme.cpp
+++ b/src/devices/bus/sbus/hme.cpp
@@ -54,18 +54,18 @@ void sbus_hme_device::install_device()
m_sbus->install_device(m_base, m_base + 0x1ffffff, *this, &sbus_hme_device::mem_map);
}
-READ32_MEMBER(sbus_hme_device::unknown_r)
+uint32_t sbus_hme_device::unknown_r(offs_t offset, uint32_t mem_mask)
{
logerror("%s: unknown_r: %08x & %08x\n", machine().describe_context(), offset << 2, mem_mask);
return 0;
}
-WRITE32_MEMBER(sbus_hme_device::unknown_w)
+void sbus_hme_device::unknown_w(offs_t offset, uint32_t data, uint32_t mem_mask)
{
logerror("%s: unknown_w: %08x = %08x & %08x\n", machine().describe_context(), offset << 2, data, mem_mask);
}
-READ32_MEMBER(sbus_hme_device::rom_r)
+uint32_t sbus_hme_device::rom_r(offs_t offset)
{
return ((uint32_t*)m_rom->base())[offset];
}
diff --git a/src/devices/bus/sbus/hme.h b/src/devices/bus/sbus/hme.h
index c3bb4ff2dfd..61e0b3cbc4d 100644
--- a/src/devices/bus/sbus/hme.h
+++ b/src/devices/bus/sbus/hme.h
@@ -22,16 +22,16 @@ public:
protected:
// device_t 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 const tiny_rom_entry *device_rom_region() const override ATTR_COLD;
+ virtual void device_add_mconfig(machine_config &config) override ATTR_COLD;
+ virtual void device_start() override ATTR_COLD;
// device_sbus_slot_interface overrides
virtual void install_device() override;
- DECLARE_READ32_MEMBER(unknown_r);
- DECLARE_WRITE32_MEMBER(unknown_w);
- DECLARE_READ32_MEMBER(rom_r);
+ uint32_t unknown_r(offs_t offset, uint32_t mem_mask = ~0);
+ void unknown_w(offs_t offset, uint32_t data, uint32_t mem_mask = ~0);
+ uint32_t rom_r(offs_t offset);
private:
void mem_map(address_map &map) override;
diff --git a/src/devices/bus/sbus/sbus.cpp b/src/devices/bus/sbus/sbus.cpp
index 3fa46c124a0..efd0a6991b5 100644
--- a/src/devices/bus/sbus/sbus.cpp
+++ b/src/devices/bus/sbus/sbus.cpp
@@ -42,7 +42,7 @@ sbus_slot_device::sbus_slot_device(const machine_config &mconfig, const char *ta
sbus_slot_device::sbus_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)
+ , device_single_card_slot_interface<device_sbus_card_interface>(mconfig, *this)
, m_sbus(*this, finder_base::DUMMY_TAG)
, m_slot(-1)
{
@@ -52,24 +52,17 @@ void sbus_slot_device::device_validity_check(validity_checker &valid) const
{
if (m_slot < 0 || m_slot > 2)
osd_printf_error("Slot %d out of range for Sun SBus\n", m_slot);
-
- device_t *const card(get_card_device());
- if (card && !dynamic_cast<device_sbus_card_interface *>(card))
- osd_printf_error("Card device %s (%s) does not implement device_sbus_card_interface\n", card->tag(), card->name());
}
void sbus_slot_device::device_resolve_objects()
{
- device_sbus_card_interface *const sbus_card(dynamic_cast<device_sbus_card_interface *>(get_card_device()));
+ device_sbus_card_interface *const sbus_card(get_card_device());
if (sbus_card)
sbus_card->set_sbus(m_sbus, m_slot);
}
void sbus_slot_device::device_start()
{
- device_t *const card(get_card_device());
- if (card && !dynamic_cast<device_sbus_card_interface *>(card))
- throw emu_fatalerror("sbus_slot_device: card device %s (%s) does not implement device_sbus_card_interface\n", card->tag(), card->name());
}
@@ -90,33 +83,25 @@ sbus_device::sbus_device(const machine_config &mconfig, const char *tag, device_
sbus_device::sbus_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_space_config("SBus Space", ENDIANNESS_BIG, 32, 32, 0, address_map_constructor())
+ , m_space_config("sbus", ENDIANNESS_BIG, 32, 32, 0, address_map_constructor())
, m_maincpu(*this, finder_base::DUMMY_TAG)
- , m_type1space(*this, finder_base::DUMMY_TAG)
- , m_irq_cb{{*this}, {*this}, {*this}, {*this}, {*this}, {*this}, {*this}}
+ , m_type1space(*this, finder_base::DUMMY_TAG, -1)
+ , m_irq_cb(*this)
, m_buserr(*this)
{
}
-void sbus_device::device_resolve_objects()
-{
- // resolve callbacks
- for (int i = 0; i < 7; i++)
- m_irq_cb[i].resolve_safe();
- m_buserr.resolve_safe();
-}
-
void sbus_device::device_start()
{
std::fill(std::begin(m_device_list), std::end(m_device_list), nullptr);
m_space = &space(0);
- m_space->install_readwrite_handler(0x00000000, 0x01ffffff, read32_delegate(FUNC(sbus_device::slot_timeout_r<0>), this), write32_delegate(FUNC(sbus_device::slot_timeout_w<0>), this));
- m_space->install_readwrite_handler(0x02000000, 0x03ffffff, read32_delegate(FUNC(sbus_device::slot_timeout_r<1>), this), write32_delegate(FUNC(sbus_device::slot_timeout_w<1>), this));
- m_space->install_readwrite_handler(0x04000000, 0x05ffffff, read32_delegate(FUNC(sbus_device::slot_timeout_r<2>), this), write32_delegate(FUNC(sbus_device::slot_timeout_w<2>), this));
+ m_space->install_readwrite_handler(0x00000000, 0x01ffffff, read32smo_delegate(*this, FUNC(sbus_device::slot_timeout_r<0>)), write32smo_delegate(*this, FUNC(sbus_device::slot_timeout_w<0>)));
+ m_space->install_readwrite_handler(0x02000000, 0x03ffffff, read32smo_delegate(*this, FUNC(sbus_device::slot_timeout_r<1>)), write32smo_delegate(*this, FUNC(sbus_device::slot_timeout_w<1>)));
+ m_space->install_readwrite_handler(0x04000000, 0x05ffffff, read32smo_delegate(*this, FUNC(sbus_device::slot_timeout_r<2>)), write32smo_delegate(*this, FUNC(sbus_device::slot_timeout_w<2>)));
}
-template <unsigned Slot> READ32_MEMBER(sbus_device::slot_timeout_r)
+template <unsigned Slot> uint32_t sbus_device::slot_timeout_r()
{
m_maincpu->set_mae();
m_buserr(0, 0x20);
@@ -124,19 +109,19 @@ template <unsigned Slot> READ32_MEMBER(sbus_device::slot_timeout_r)
return 0;
}
-template <unsigned Slot> WRITE32_MEMBER(sbus_device::slot_timeout_w)
+template <unsigned Slot> void sbus_device::slot_timeout_w(uint32_t data)
{
m_maincpu->set_mae();
m_buserr(0, 0x8020);
m_buserr(1, 0xffa00000 + (Slot << 21));
}
-READ32_MEMBER(sbus_device::read)
+uint32_t sbus_device::read(offs_t offset, uint32_t mem_mask)
{
return m_space->read_dword(offset << 2, mem_mask);
}
-WRITE32_MEMBER(sbus_device::write)
+void sbus_device::write(offs_t offset, uint32_t data, uint32_t mem_mask)
{
m_space->write_dword(offset << 2, data, mem_mask);
}
@@ -170,7 +155,7 @@ void sbus_device::set_irq_line(int state, int line)
device_sbus_card_interface::device_sbus_card_interface(const machine_config &mconfig, device_t &device)
- : device_slot_card_interface(mconfig, device)
+ : device_interface(device, "sbus")
, m_sbus_finder(device, finder_base::DUMMY_TAG)
, m_sbus(nullptr)
, m_slot(-1)
@@ -190,8 +175,6 @@ void device_sbus_card_interface::interface_validity_check(validity_checker &vali
void device_sbus_card_interface::interface_pre_start()
{
- device_slot_card_interface::interface_pre_start();
-
if (!m_sbus)
{
m_sbus = m_sbus_finder;
diff --git a/src/devices/bus/sbus/sbus.h b/src/devices/bus/sbus/sbus.h
index 29d2e2c26bb..9439fc916ec 100644
--- a/src/devices/bus/sbus/sbus.h
+++ b/src/devices/bus/sbus/sbus.h
@@ -14,9 +14,11 @@
#include "cpu/sparc/sparc.h"
#include "machine/bankdev.h"
+class device_sbus_card_interface;
class sbus_device;
-class sbus_slot_device : public device_t, public device_slot_interface
+
+class sbus_slot_device : public device_t, public device_single_card_slot_interface<device_sbus_card_interface>
{
public:
// construction/destruction
@@ -36,24 +38,19 @@ 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;
+ virtual void device_resolve_objects() override ATTR_COLD;
+ virtual void device_start() override ATTR_COLD;
// configuration
required_device<sbus_device> m_sbus;
int m_slot;
-
- DECLARE_READ32_MEMBER(timeout_r);
- DECLARE_WRITE32_MEMBER(timeout_w);
};
DECLARE_DEVICE_TYPE(SBUS_SLOT, sbus_slot_device)
-class device_sbus_card_interface;
-
class sbus_device : public device_t,
public device_memory_interface
{
@@ -61,20 +58,18 @@ class sbus_device : public device_t,
public:
// construction/destruction
template <typename T, typename U>
- sbus_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock, T &&cpu_tag, U &&space_tag)
+ sbus_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock, T &&cpu_tag, U &&space_tag, int space_num)
: sbus_device(mconfig, tag, owner, clock)
{
- set_cpu_tag(std::forward<T>(cpu_tag));
- set_space_tag(std::forward<U>(space_tag));
+ set_cpu(std::forward<T>(cpu_tag));
+ set_type1space(std::forward<U>(space_tag), space_num);
}
sbus_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
// inline configuration
- template <typename T> void set_cpu_tag(T &&tag) { m_maincpu.set_tag(std::forward<T>(tag)); }
- template <typename T> void set_space_tag(T &&tag) { m_type1space.set_tag(std::forward<T>(tag)); }
-
- // devcb3
+ template <typename T> void set_cpu(T &&tag) { m_maincpu.set_tag(std::forward<T>(tag)); }
+ template <typename T> void set_type1space(T &&tag, int num) { m_type1space.set_tag(std::forward<T>(tag), num); }
template <unsigned Line> auto irq() { return m_irq_cb[Line].bind(); }
auto buserr() { return m_buserr.bind(); }
@@ -92,40 +87,39 @@ public:
m_space->install_device(addrstart, addrend, device, map, unitmask);
}
- DECLARE_READ32_MEMBER(read);
- DECLARE_WRITE32_MEMBER(write);
+ uint32_t read(offs_t offset, uint32_t mem_mask = ~0);
+ void write(offs_t offset, uint32_t data, uint32_t mem_mask = ~0);
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;
- virtual void device_start() override;
+ // device_t implementation
+ virtual void device_start() override ATTR_COLD;
// internal state
- required_device<mb86901_device> m_maincpu;
- required_device<address_map_bank_device> m_type1space;
+ required_device<sparc_base_device> m_maincpu;
+ required_address_space m_type1space;
address_space *m_space;
- devcb_write_line m_irq_cb[7];
- devcb_write32 m_buserr;
+ devcb_write_line::array<7> m_irq_cb;
+ devcb_write32 m_buserr;
device_sbus_card_interface *m_device_list[3];
private:
- void slot1_timeout_map(address_map &map);
- void slot2_timeout_map(address_map &map);
- void slot3_timeout_map(address_map &map);
+ void slot1_timeout_map(address_map &map) ATTR_COLD;
+ void slot2_timeout_map(address_map &map) ATTR_COLD;
+ void slot3_timeout_map(address_map &map) ATTR_COLD;
- template <unsigned Slot> DECLARE_READ32_MEMBER(slot_timeout_r);
- template <unsigned Slot> DECLARE_WRITE32_MEMBER(slot_timeout_w);
+ template <unsigned Slot> uint32_t slot_timeout_r();
+ template <unsigned Slot> void slot_timeout_w(uint32_t data);
};
DECLARE_DEVICE_TYPE(SBUS, sbus_device)
// class representing interface-specific live sbus card
-class device_sbus_card_interface : public device_slot_card_interface
+class device_sbus_card_interface : public device_interface
{
friend class sbus_device;
public:
diff --git a/src/devices/bus/sbus/sunpc.cpp b/src/devices/bus/sbus/sunpc.cpp
index 7036e857393..bfb88b4726f 100644
--- a/src/devices/bus/sbus/sunpc.cpp
+++ b/src/devices/bus/sbus/sunpc.cpp
@@ -54,18 +54,18 @@ void sbus_sunpc_device::install_device()
m_sbus->install_device(m_base, m_base + 0x1ffffff, *this, &sbus_sunpc_device::mem_map);
}
-READ32_MEMBER(sbus_sunpc_device::unknown_r)
+uint32_t sbus_sunpc_device::unknown_r(offs_t offset, uint32_t mem_mask)
{
logerror("%s: unknown_r: %08x & %08x\n", machine().describe_context(), offset << 2, mem_mask);
return 0;
}
-WRITE32_MEMBER(sbus_sunpc_device::unknown_w)
+void sbus_sunpc_device::unknown_w(offs_t offset, uint32_t data, uint32_t mem_mask)
{
logerror("%s: unknown_w: %08x = %08x & %08x\n", machine().describe_context(), offset << 2, data, mem_mask);
}
-READ32_MEMBER(sbus_sunpc_device::rom_r)
+uint32_t sbus_sunpc_device::rom_r(offs_t offset)
{
return ((uint32_t*)m_rom->base())[offset];
}
diff --git a/src/devices/bus/sbus/sunpc.h b/src/devices/bus/sbus/sunpc.h
index 8c20c1be27e..13b61680c3a 100644
--- a/src/devices/bus/sbus/sunpc.h
+++ b/src/devices/bus/sbus/sunpc.h
@@ -22,16 +22,16 @@ public:
protected:
// device_t 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 const tiny_rom_entry *device_rom_region() const override ATTR_COLD;
+ virtual void device_add_mconfig(machine_config &config) override ATTR_COLD;
+ virtual void device_start() override ATTR_COLD;
// device_sbus_slot_interface overrides
virtual void install_device() override;
- DECLARE_READ32_MEMBER(unknown_r);
- DECLARE_WRITE32_MEMBER(unknown_w);
- DECLARE_READ32_MEMBER(rom_r);
+ uint32_t unknown_r(offs_t offset, uint32_t mem_mask = ~0);
+ void unknown_w(offs_t offset, uint32_t data, uint32_t mem_mask = ~0);
+ uint32_t rom_r(offs_t offset);
private:
void mem_map(address_map &map) override;
diff --git a/src/devices/bus/scsi/cdu76s.cpp b/src/devices/bus/scsi/cdu76s.cpp
index 231445f1077..01860e7f31c 100644
--- a/src/devices/bus/scsi/cdu76s.cpp
+++ b/src/devices/bus/scsi/cdu76s.cpp
@@ -46,3 +46,17 @@ sony_cdu76s_device::sony_cdu76s_device(const machine_config &mconfig, const char
scsicd_device(mconfig, CDU76S, tag, owner, clock)
{
}
+
+ROM_START(cdu76s)
+ ROM_REGION(0x10000, "eprom", 0)
+ ROM_DEFAULT_BIOS("1.1c")
+ ROM_SYSTEM_BIOS( 0, "1.1c", "CDU76S firmware 1.1c" )
+ ROMX_LOAD("76s.1.1c.ic206", 0x00000, 0x10000, CRC(8a233f19) SHA1(5f3c3f1ec181cb7f18daea5c8c592f6910aac3b2), ROM_BIOS(0))
+ ROM_SYSTEM_BIOS( 1, "1.1a", "CDU76S firmware 1.1a" )
+ ROMX_LOAD("76s.1.1a.ic206", 0x00000, 0x10000, CRC(1df044f9) SHA1(8d1f6ccd6fb5e04b987b9aa21e602a21df7505a4), ROM_BIOS(1)) // 95.06.01
+ROM_END
+
+const tiny_rom_entry *sony_cdu76s_device::device_rom_region() const
+{
+ return ROM_NAME(cdu76s);
+}
diff --git a/src/devices/bus/scsi/cdu76s.h b/src/devices/bus/scsi/cdu76s.h
index 2e91525bfdc..99b6f06d410 100644
--- a/src/devices/bus/scsi/cdu76s.h
+++ b/src/devices/bus/scsi/cdu76s.h
@@ -23,6 +23,9 @@ public:
virtual void ExecCommand() override;
virtual void ReadData( uint8_t *data, int dataLength ) override;
+
+protected:
+ virtual const tiny_rom_entry *device_rom_region() const override ATTR_COLD;
};
// device type definition
diff --git a/src/devices/bus/scsi/omti5100.cpp b/src/devices/bus/scsi/omti5100.cpp
index 519aa723a0b..b4c46de8553 100644
--- a/src/devices/bus/scsi/omti5100.cpp
+++ b/src/devices/bus/scsi/omti5100.cpp
@@ -15,7 +15,7 @@ DEFINE_DEVICE_TYPE(OMTI5100, omti5100_device, "omti5100", "OMTI 5100")
#if 0
ROM_START( omti5100 )
ROM_REGION(0x1000, "mcu", 0) // Hitachi Z8
- ROM_LOAD("100240-N.7a", 0x0000, 0x1000, CRC(d227d6cb) SHA1(3d6140764d3d043428c941826370ebf1597c63bd))
+ ROM_LOAD("100240-n.7a", 0x0000, 0x1000, CRC(d227d6cb) SHA1(3d6140764d3d043428c941826370ebf1597c63bd))
ROM_END
const tiny_rom_entry *omti5100_device::device_rom_region() const
@@ -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();
@@ -54,7 +54,7 @@ void omti5100_device::ExecCommand()
m_transfer_length = 0;
return;
}
- hard_disk_info *info = hard_disk_get_info(image);
+ const auto &info = image->get_info();
switch(command[0])
{
case OMTI_READ_DATA_BUFFER:
@@ -77,7 +77,7 @@ void omti5100_device::ExecCommand()
{
int track = ((command[1]&0x1f)<<16 | command[2]<<8 | command[3]) / (m_param[drive].sectors ? m_param[drive].sectors : 1);
int heads = m_param[drive].heads ? m_param[drive].heads : 1;
- if(((track % heads) > info->heads) || (track >= (info->cylinders * heads)))
+ if(((track % heads) > info.heads) || (track >= (info.cylinders * heads)))
{
m_phase = SCSI_PHASE_STATUS;
m_status_code = SCSI_STATUS_CODE_CHECK_CONDITION;
@@ -86,7 +86,6 @@ void omti5100_device::ExecCommand()
}
else
{
- SetDevice(image);
scsihd_device::ExecCommand();
}
break;
@@ -94,15 +93,15 @@ void omti5100_device::ExecCommand()
case OMTI_FORMAT_TRACK:
{
int track = ((command[1]&0x1f)<<16 | command[2]<<8 | command[3]) / m_param[drive].sectors;
- if(((track % m_param[drive].heads) <= info->heads) && (track < (info->cylinders * m_param[drive].heads)))
+ if(((track % m_param[drive].heads) <= info.heads) && (track < (info.cylinders * m_param[drive].heads)))
{
- std::vector<uint8_t> sector(info->sectorbytes);
- memset(&sector[0], 0xe5, info->sectorbytes);
+ std::vector<uint8_t> sector(info.sectorbytes);
+ memset(&sector[0], 0xe5, info.sectorbytes);
m_phase = SCSI_PHASE_STATUS;
m_status_code = SCSI_STATUS_CODE_GOOD;
m_transfer_length = 0;
- for(int i = 0; i < info->sectors; i++)
- hard_disk_write(image, track * info->sectors + i, &sector[0]);
+ for(int i = 0; i < info.sectors; i++)
+ image->write(track * info.sectors + i, &sector[0]);
}
else
{
@@ -114,7 +113,6 @@ void omti5100_device::ExecCommand()
break;
}
default:
- SetDevice(image);
scsihd_device::ExecCommand();
break;
}
@@ -144,12 +142,12 @@ 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(hard_disk_get_info(image)->sectorbytes)
+ switch(image->get_info().sectorbytes)
{
case 128:
m_param[drive].sectors = 53;
diff --git a/src/devices/bus/scsi/omti5100.h b/src/devices/bus/scsi/omti5100.h
index c33ab701626..7a4af5f3170 100644
--- a/src/devices/bus/scsi/omti5100.h
+++ b/src/devices/bus/scsi/omti5100.h
@@ -17,14 +17,14 @@ public:
virtual void WriteData( uint8_t *data, int dataLength ) override;
protected:
- void device_start() override;
+ void device_start() override ATTR_COLD;
- virtual void device_add_mconfig(machine_config &config) override;
+ virtual void device_add_mconfig(machine_config &config) override ATTR_COLD;
private:
required_device<harddisk_image_device> m_image0;
required_device<harddisk_image_device> m_image1;
- hard_disk_info m_param[2];
+ hard_disk_file::info m_param[2];
};
DECLARE_DEVICE_TYPE(OMTI5100, omti5100_device)
diff --git a/src/devices/bus/scsi/pc9801_sasi.cpp b/src/devices/bus/scsi/pc9801_sasi.cpp
index b7c93f98094..117de034ca1 100644
--- a/src/devices/bus/scsi/pc9801_sasi.cpp
+++ b/src/devices/bus/scsi/pc9801_sasi.cpp
@@ -22,8 +22,35 @@ void pc9801_sasi_device::ExecCommand()
m_transfer_length = 10;
break;
+ // TODO: command 0x0e during pc88va2 HDFORM command (failed earlier?)
+
default:
scsihd_device::ExecCommand();
break;
}
}
+
+void pc9801_sasi_device::ReadData(uint8_t *data, int dataLength)
+{
+ switch(command[0])
+ {
+ default:
+ scsihd_device::ReadData(data, dataLength);
+ break;
+ }
+}
+
+void pc9801_sasi_device::WriteData( uint8_t *data, int dataLength )
+{
+ switch( command[0] )
+ {
+ case SASI_CMD_SPECIFY:
+ logerror("pc9801-07: C2 SPECIFY %d\n", dataLength);
+ break;
+
+ default:
+ scsihd_device::WriteData( data, dataLength );
+ break;
+ }
+}
+
diff --git a/src/devices/bus/scsi/pc9801_sasi.h b/src/devices/bus/scsi/pc9801_sasi.h
index 773de463c61..a3a0745a90a 100644
--- a/src/devices/bus/scsi/pc9801_sasi.h
+++ b/src/devices/bus/scsi/pc9801_sasi.h
@@ -11,7 +11,10 @@ public:
// construction/destruction
pc9801_sasi_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
+protected:
virtual void ExecCommand() override;
+ virtual void WriteData( uint8_t *data, int dataLength ) override;
+ virtual void ReadData( uint8_t *data, int dataLength ) override;
};
// device type definition
diff --git a/src/devices/bus/scsi/s1410.cpp b/src/devices/bus/scsi/s1410.cpp
index 5416089fd9d..2873a281783 100644
--- a/src/devices/bus/scsi/s1410.cpp
+++ b/src/devices/bus/scsi/s1410.cpp
@@ -112,7 +112,8 @@ ROM_START( s1410 )
ROM_REGION( 0x1000, Z8400A_TAG, 0 )
ROM_LOAD( "104521f", 0x0000, 0x1000, CRC(305b8e76) SHA1(9efaa53ae86bc111bd263ad433e083f78a000cab) )
ROM_LOAD( "104521g", 0x0000, 0x1000, CRC(24385115) SHA1(c389f6108cd5ed798a090acacce940ee43d77042) )
- ROM_LOAD( "104788d", 0x0000, 0x1000, CRC(2e385e2d) SHA1(7e2c349b2b6e95f2134f82cffc38d86b8a68390d) )
+ ROM_LOAD( "104788d", 0x0000, 0x1000, CRC(2e385e2d) SHA1(7e2c349b2b6e95f2134f82cffc38d86b8a68390d) ) // BASF 6188
+ ROM_LOAD( "104788e", 0x0000, 0x1000, CRC(40a7195d) SHA1(bf68e99dad182bfcbb5d488aeb440cba572a6ef8) ) // Seagate ST-251
ROM_REGION( 0x20, "103911", 0 )
ROM_LOAD( "103911", 0x00, 0x20, NO_DUMP ) // DM74S288N
@@ -172,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");
}
@@ -186,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")
{
}
@@ -247,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 (!hard_disk_write(m_disk, 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..806f21fad85 100644
--- a/src/devices/bus/scsi/s1410.h
+++ b/src/devices/bus/scsi/s1410.h
@@ -21,16 +21,18 @@ public:
protected:
// optional information overrides
- virtual const tiny_rom_entry *device_rom_region() const override;
- virtual void device_add_mconfig(machine_config &config) override;
+ virtual const tiny_rom_entry *device_rom_region() const override ATTR_COLD;
+ virtual void device_add_mconfig(machine_config &config) override ATTR_COLD;
virtual void ExecCommand() override;
virtual void WriteData( uint8_t *data, int dataLength ) override;
virtual void ReadData( uint8_t *data, int dataLength ) override;
private:
- void s1410_io(address_map &map);
- void s1410_mem(address_map &map);
+ required_device<harddisk_image_device> m_image;
+
+ void s1410_io(address_map &map) ATTR_COLD;
+ void s1410_mem(address_map &map) ATTR_COLD;
};
diff --git a/src/devices/bus/scsi/sa1403d.h b/src/devices/bus/scsi/sa1403d.h
index f4b229d6514..80a5acf143a 100644
--- a/src/devices/bus/scsi/sa1403d.h
+++ b/src/devices/bus/scsi/sa1403d.h
@@ -25,9 +25,9 @@ public:
protected:
// optional information 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 const tiny_rom_entry *device_rom_region() const override ATTR_COLD;
+ virtual void device_add_mconfig(machine_config &config) override ATTR_COLD;
+ virtual ioport_constructor device_input_ports() const override ATTR_COLD;
};
diff --git a/src/devices/bus/scsi/scsi.cpp b/src/devices/bus/scsi/scsi.cpp
index 5997266b84d..d42e0a527da 100644
--- a/src/devices/bus/scsi/scsi.cpp
+++ b/src/devices/bus/scsi/scsi.cpp
@@ -4,8 +4,8 @@
#include "emu.h"
#include "scsi.h"
-scsi_port_device::scsi_port_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
- : device_t(mconfig, SCSI_PORT, tag, owner, clock),
+scsi_port_device::scsi_port_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) :
+ device_t(mconfig, SCSI_PORT, tag, owner, clock),
m_bsy_handler(*this),
m_sel_handler(*this),
m_cd_handler(*this),
@@ -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)
{
@@ -673,7 +655,7 @@ DEFINE_DEVICE_TYPE(SCSI_PORT, scsi_port_device, "scsi", "SCSI Port")
scsi_port_slot_device::scsi_port_slot_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) :
device_t(mconfig, SCSI_PORT_SLOT, tag, owner, clock),
- device_slot_interface(mconfig, *this),
+ device_single_card_slot_interface<scsi_port_interface>(mconfig, *this),
m_dev(nullptr),
m_bsy(0),
m_sel(0),
@@ -706,8 +688,8 @@ void scsi_port_slot_device::device_start()
DEFINE_DEVICE_TYPE(SCSI_PORT_SLOT, scsi_port_slot_device, "scsi_slot", "SCSI Connector")
-scsi_port_interface::scsi_port_interface(const machine_config &mconfig, device_t &device)
- : device_slot_card_interface(mconfig, device)
+scsi_port_interface::scsi_port_interface(const machine_config &mconfig, device_t &device) :
+ device_interface(device, "scsi")
{
m_slot = dynamic_cast<scsi_port_slot_device *>(device.owner());
}
diff --git a/src/devices/bus/scsi/scsi.h b/src/devices/bus/scsi/scsi.h
index 66ddae370d6..c91bc1c5312 100644
--- a/src/devices/bus/scsi/scsi.h
+++ b/src/devices/bus/scsi/scsi.h
@@ -62,31 +62,31 @@ 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);
protected:
// device-level overrides
- virtual void device_start() override;
- virtual void device_add_mconfig(machine_config &config) override;
+ virtual void device_start() override ATTR_COLD;
+ virtual void device_add_mconfig(machine_config &config) override ATTR_COLD;
void update_bsy();
void update_sel();
@@ -168,8 +168,7 @@ DECLARE_DEVICE_TYPE(SCSI_PORT, scsi_port_device)
class scsi_port_interface;
-class scsi_port_slot_device : public device_t,
- public device_slot_interface
+class scsi_port_slot_device : public device_t, public device_single_card_slot_interface<scsi_port_interface>
{
friend class scsi_port_device;
friend class scsi_port_interface;
@@ -182,7 +181,7 @@ public:
protected:
// device-level overrides
- virtual void device_start() override;
+ virtual void device_start() override ATTR_COLD;
virtual void device_config_complete() override;
protected:
@@ -210,46 +209,46 @@ protected:
DECLARE_DEVICE_TYPE(SCSI_PORT_SLOT, scsi_port_slot_device)
-class scsi_port_interface : public device_slot_card_interface
+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..7f1bc54ed7e 100644
--- a/src/devices/bus/scsi/scsicd.h
+++ b/src/devices/bus/scsi/scsicd.h
@@ -20,9 +20,10 @@ 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_add_mconfig(machine_config &config) override;
+ 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;
+ virtual bool exists() const override;
};
// device type definition
diff --git a/src/devices/bus/scsi/scsicd512.cpp b/src/devices/bus/scsi/scsicd512.cpp
index 5395d9ff5b4..52e5f7d7f32 100644
--- a/src/devices/bus/scsi/scsicd512.cpp
+++ b/src/devices/bus/scsi/scsicd512.cpp
@@ -10,7 +10,7 @@
#include "scsicd512.h"
DEFINE_DEVICE_TYPE(RRD45, dec_rrd45_device, "rrd45", "DEC RRD45")
-DEFINE_DEVICE_TYPE(XM3301, toshiba_xm3301_device, "xm3301", "Toshiba XM-3301TA CD-ROM")
+DEFINE_DEVICE_TYPE(XM3301TA, toshiba_xm3301ta_device, "xm3301ta", "Toshiba XM-3301TA CD-ROM")
DEFINE_DEVICE_TYPE(XM5301SUN, toshiba_xm5301_sun_device, "xm5301sun", "Toshiba XM-5301B Sun 4x CD-ROM")
DEFINE_DEVICE_TYPE(XM5401SUN, toshiba_xm5401_sun_device, "xm5401sun", "Toshiba XM-5401B Sun 4x CD-ROM")
DEFINE_DEVICE_TYPE(XM5701, toshiba_xm5701_device, "xm5701", "Toshiba XM-5701B 12x CD-ROM")
@@ -76,8 +76,8 @@ dec_rrd45_device::dec_rrd45_device(const machine_config &mconfig, const char *ta
{
}
-toshiba_xm3301_device::toshiba_xm3301_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) :
- scsicd512_device(mconfig, XM3301, tag, owner, "TOSHIBA ", "CD-ROM XM-3301TA", "0272", 0x88)
+toshiba_xm3301ta_device::toshiba_xm3301ta_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) :
+ scsicd512_device(mconfig, XM3301TA, tag, owner, "TOSHIBA ", "CD-ROM XM-3301TA", "0272", 0x88)
{
}
diff --git a/src/devices/bus/scsi/scsicd512.h b/src/devices/bus/scsi/scsicd512.h
index 0345a74ca9a..b858aeea3f2 100644
--- a/src/devices/bus/scsi/scsicd512.h
+++ b/src/devices/bus/scsi/scsicd512.h
@@ -6,8 +6,8 @@
***************************************************************************/
-#ifndef DEVICES_BUS_SCSI_SCSICD512_H
-#define DEVICES_BUS_SCSI_SCSICD512_H
+#ifndef MAME_BUS_SCSI_SCSICD512_H
+#define MAME_BUS_SCSI_SCSICD512_H
#pragma once
@@ -32,7 +32,7 @@ protected:
m_data = data;
}
- virtual void device_reset() override;
+ virtual void device_reset() override ATTR_COLD;
char m_manufacturer[8];
char m_product[16];
@@ -46,10 +46,10 @@ public:
dec_rrd45_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock = 0);
};
-class toshiba_xm3301_device : public scsicd512_device
+class toshiba_xm3301ta_device : public scsicd512_device
{
public:
- toshiba_xm3301_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock = 0);
+ toshiba_xm3301ta_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock = 0);
};
class toshiba_xm5301_sun_device : public scsicd512_device
@@ -77,10 +77,10 @@ public:
};
DECLARE_DEVICE_TYPE(RRD45, dec_rrd45_device)
-DECLARE_DEVICE_TYPE(XM3301, toshiba_xm3301_device)
+DECLARE_DEVICE_TYPE(XM3301TA, toshiba_xm3301ta_device)
DECLARE_DEVICE_TYPE(XM5301SUN, toshiba_xm5301_sun_device)
DECLARE_DEVICE_TYPE(XM5401SUN, toshiba_xm5401_sun_device)
DECLARE_DEVICE_TYPE(XM5701, toshiba_xm5701_device)
DECLARE_DEVICE_TYPE(XM5701SUN, toshiba_xm5701_sun_device)
-#endif // DEVICES_BUS_SCSI_SCSICD512_H
+#endif // MAME_BUS_SCSI_SCSICD512_H
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..95456ca3d5f 100644
--- a/src/devices/bus/scsi/scsihd.h
+++ b/src/devices/bus/scsi/scsihd.h
@@ -22,9 +22,9 @@ 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 void device_start() override ATTR_COLD;
+ virtual void device_add_mconfig(machine_config &config) override ATTR_COLD;
+ 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 ed63dae450e..da0d6c45817 100644
--- a/src/devices/bus/scsi/scsihle.cpp
+++ b/src/devices/bus/scsi/scsihle.cpp
@@ -82,9 +82,9 @@ void scsihle_device::device_start()
{
t10_start(*this);
- req_timer = timer_alloc(0);
- sel_timer = timer_alloc(1);
- dataout_timer = timer_alloc(2);
+ req_timer = timer_alloc(FUNC(scsihle_device::req_tick), this);
+ sel_timer = timer_alloc(FUNC(scsihle_device::sel_tick), this);
+ dataout_timer = timer_alloc(FUNC(scsihle_device::dataout_tick), this);
}
void scsihle_device::device_reset()
@@ -206,27 +206,24 @@ void scsihle_device::scsibus_write_data()
data_idx=0;
}
-void scsihle_device::device_timer(emu_timer &timer, device_timer_id tid, int param, void *ptr)
+TIMER_CALLBACK_MEMBER(scsihle_device::req_tick)
{
- switch (tid)
- {
- case 0:
- output_req(param);
- break;
+ output_req(param);
+}
- case 1:
- output_bsy(param);
- break;
+TIMER_CALLBACK_MEMBER(scsihle_device::sel_tick)
+{
+ output_bsy(param);
+}
- case 2:
- // Some drives, notably the ST225N and ST125N, accept fromat unit commands
- // with flags set indicating that bad block data should be transferred but
- // don't then implemnt a data in phase, this timeout it to catch these !
- if (IS_COMMAND(SCSI_CMD_FORMAT_UNIT) && (data_idx==0))
- {
- scsi_change_phase(SCSI_PHASE_STATUS);
- }
- break;
+TIMER_CALLBACK_MEMBER(scsihle_device::dataout_tick)
+{
+ // Some drives, notably the ST225N and ST125N, accept fromat unit commands
+ // with flags set indicating that bad block data should be transferred but
+ // don't then implemnt a data in phase, this timeout it to catch these
+ if (IS_COMMAND(SCSI_CMD_FORMAT_UNIT) && (data_idx==0))
+ {
+ scsi_change_phase(SCSI_PHASE_STATUS);
}
}
@@ -408,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)
@@ -418,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)
{
@@ -438,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)
{
@@ -497,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);
@@ -576,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 e98e38122e7..2ea069b702d 100644
--- a/src/devices/bus/scsi/scsihle.h
+++ b/src/devices/bus/scsi/scsihle.h
@@ -23,27 +23,32 @@ 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
scsihle_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock);
// device-level overrides
- virtual ioport_constructor device_input_ports() const override;
- virtual void device_start() override;
- virtual void device_reset() override;
- virtual void device_timer(emu_timer &timer, device_timer_id id, int param, void *ptr) override;
+ virtual ioport_constructor device_input_ports() const override ATTR_COLD;
+ virtual void device_start() override ATTR_COLD;
+ virtual void device_reset() override ATTR_COLD;
+
+ TIMER_CALLBACK_MEMBER(req_tick);
+ TIMER_CALLBACK_MEMBER(sel_tick);
+ TIMER_CALLBACK_MEMBER(dataout_tick);
private:
required_ioport m_scsi_id;
diff --git a/src/devices/bus/scv/rom.cpp b/src/devices/bus/scv/rom.cpp
index be0dc7aea2c..d430b6de04a 100644
--- a/src/devices/bus/scv/rom.cpp
+++ b/src/devices/bus/scv/rom.cpp
@@ -13,191 +13,231 @@
#include "rom.h"
-//-------------------------------------------------
-// scv_rom_device - constructor
-//-------------------------------------------------
+namespace {
-DEFINE_DEVICE_TYPE(SCV_ROM8K, scv_rom8_device, "scv_rom8", "SCV 8K Carts")
-DEFINE_DEVICE_TYPE(SCV_ROM16K, scv_rom16_device, "scv_rom16", "SCV 16K Carts")
-DEFINE_DEVICE_TYPE(SCV_ROM32K, scv_rom32_device, "scv_rom32", "SCV 32K Carts")
-DEFINE_DEVICE_TYPE(SCV_ROM32K_RAM8K, scv_rom32ram8_device, "scv_rom32_ram8", "SCV 32K + RAM 8K Carts")
-DEFINE_DEVICE_TYPE(SCV_ROM64K, scv_rom64_device, "scv_rom64", "SCV 64K Carts")
-DEFINE_DEVICE_TYPE(SCV_ROM128K, scv_rom128_device, "scv_rom128", "SCV 128K Carts")
-DEFINE_DEVICE_TYPE(SCV_ROM128K_RAM4K, scv_rom128ram4_device, "scv_rom128_ram4", "SCV 128K + RAM 4K Carts")
+class scv_rom8_device : public device_t,
+ public device_scv_cart_interface
+{
+public:
+ scv_rom8_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock)
+ : scv_rom8_device(mconfig, SCV_ROM8K, tag, owner, clock)
+ { }
+ virtual void install_memory_handlers(address_space *space) override;
-scv_rom8_device::scv_rom8_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_scv_cart_interface(mconfig, *this)
-{
-}
+protected:
+ scv_rom8_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, u32 clock)
+ : device_t(mconfig, type, tag, owner, clock), device_scv_cart_interface(mconfig, *this)
+ { }
-scv_rom8_device::scv_rom8_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
- : scv_rom8_device(mconfig, SCV_ROM8K, tag, owner, clock)
-{
-}
+ virtual void device_start() override { }
+ virtual void device_reset() override { }
-scv_rom16_device::scv_rom16_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
- : scv_rom8_device(mconfig, SCV_ROM16K, tag, owner, clock)
-{
-}
+ static constexpr u16 CARTRIDGE_ADDRESS_END = 0xff7f;
+};
-scv_rom32_device::scv_rom32_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
- : scv_rom8_device(mconfig, SCV_ROM32K, tag, owner, clock)
+void scv_rom8_device::install_memory_handlers(address_space *space)
{
+ space->install_rom(0x8000, 0x9fff, cart_rom_region()->base());
+ space->install_rom(0xa000, 0xbfff, cart_rom_region()->base());
+ space->install_rom(0xc000, 0xdfff, cart_rom_region()->base());
+ space->install_rom(0xe000, CARTRIDGE_ADDRESS_END, cart_rom_region()->base());
}
-scv_rom32ram8_device::scv_rom32ram8_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
- : scv_rom8_device(mconfig, SCV_ROM32K_RAM8K, tag, owner, clock), m_ram_enabled(0)
-{
-}
-scv_rom64_device::scv_rom64_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
- : scv_rom8_device(mconfig, SCV_ROM64K, tag, owner, clock), m_bank_base(0)
-{
-}
-scv_rom128_device::scv_rom128_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
- : scv_rom8_device(mconfig, SCV_ROM128K, tag, owner, clock), m_bank_base(0)
+class scv_rom16_device : public scv_rom8_device
{
-}
+public:
+ scv_rom16_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock)
+ : scv_rom8_device(mconfig, SCV_ROM16K, tag, owner, clock)
+ { }
-scv_rom128ram4_device::scv_rom128ram4_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
- : scv_rom8_device(mconfig, SCV_ROM128K_RAM4K, tag, owner, clock), m_bank_base(0), m_ram_enabled(0)
+ virtual void install_memory_handlers(address_space *space) override;
+};
+
+void scv_rom16_device::install_memory_handlers(address_space *space)
{
+ space->install_rom(0x8000, 0xbfff, cart_rom_region()->base());
+ space->install_rom(0xc000, CARTRIDGE_ADDRESS_END, cart_rom_region()->base());
}
-//-------------------------------------------------
-// mapper specific start/reset
-//-------------------------------------------------
-void scv_rom32ram8_device::device_start()
+class scv_rom32_device : public scv_rom8_device
{
- save_item(NAME(m_ram_enabled));
-}
+public:
+ scv_rom32_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock)
+ : scv_rom8_device(mconfig, SCV_ROM32K, tag, owner, clock)
+ { }
-void scv_rom32ram8_device::device_reset()
+ virtual void install_memory_handlers(address_space *space) override;
+};
+
+void scv_rom32_device::install_memory_handlers(address_space *space)
{
- m_ram_enabled = 1;
+ space->install_rom(0x8000, CARTRIDGE_ADDRESS_END, cart_rom_region()->base());
}
-void scv_rom64_device::device_start()
-{
- save_item(NAME(m_bank_base));
-}
-void scv_rom64_device::device_reset()
+class scv_rom32ram8_device : public scv_rom8_device
{
- m_bank_base = 0;
-}
+public:
+ scv_rom32ram8_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock)
+ : scv_rom8_device(mconfig, SCV_ROM32K_RAM8K, tag, owner, clock)
+ , m_view(*this, "view")
+ { }
+
+ virtual void install_memory_handlers(address_space *space) override;
+ virtual void write_bank(uint8_t data) override;
+protected:
+ virtual void device_reset() override ATTR_COLD;
-void scv_rom128_device::device_start()
+private:
+ memory_view m_view;
+};
+
+void scv_rom32ram8_device::device_reset()
{
- save_item(NAME(m_bank_base));
+ m_view.select(1);
}
-void scv_rom128_device::device_reset()
+void scv_rom32ram8_device::install_memory_handlers(address_space *space)
{
- m_bank_base = 0;
+ space->install_rom(0x8000, CARTRIDGE_ADDRESS_END, cart_rom_region()->base());
+ space->install_view(0xe000, CARTRIDGE_ADDRESS_END, m_view);
+ m_view[0];
+ m_view[1].install_ram(0xe000, CARTRIDGE_ADDRESS_END, cart_ram_region()->base());
}
-
-void scv_rom128ram4_device::device_start()
+void scv_rom32ram8_device::write_bank(uint8_t data)
{
- save_item(NAME(m_bank_base));
- save_item(NAME(m_ram_enabled));
+ m_view.select(BIT(data, 5));
}
-void scv_rom128ram4_device::device_reset()
+
+
+class scv_rom64_device : public scv_rom8_device
{
- m_bank_base = 0;
- m_ram_enabled = 1;
-}
+public:
+ scv_rom64_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock)
+ : scv_rom8_device(mconfig, SCV_ROM64K, tag, owner, clock)
+ , m_bank(*this, "bank")
+ { }
+ virtual void install_memory_handlers(address_space *space) override;
+ virtual void write_bank(uint8_t data) override;
+protected:
+ virtual void device_reset() override ATTR_COLD;
-/*-------------------------------------------------
- mapper specific handlers
- -------------------------------------------------*/
+private:
+ memory_bank_creator m_bank;
+};
-READ8_MEMBER(scv_rom8_device::read_cart)
+void scv_rom64_device::device_reset()
{
- return m_rom[offset & 0x1fff];
+ m_bank->set_entry(0);
}
-
-READ8_MEMBER(scv_rom16_device::read_cart)
+void scv_rom64_device::install_memory_handlers(address_space *space)
{
- return m_rom[offset & 0x3fff];
+ m_bank->configure_entries(0, 2, cart_rom_region()->base(), 0x8000);
+ space->install_read_bank(0x8000, CARTRIDGE_ADDRESS_END, m_bank);
}
-
-READ8_MEMBER(scv_rom32_device::read_cart)
+void scv_rom64_device::write_bank(uint8_t data)
{
- return m_rom[offset];
+ m_bank->set_entry(BIT(data, 5));
}
-READ8_MEMBER(scv_rom32ram8_device::read_cart)
+
+class scv_rom128_device : public scv_rom8_device
{
- if (m_ram_enabled && offset >= 0x6000)
- return m_ram[offset & 0x1fff];
+public:
+ scv_rom128_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock)
+ : scv_rom8_device(mconfig, SCV_ROM128K, tag, owner, clock)
+ , m_bank(*this, "bank")
+ { }
- return m_rom[offset];
-}
+ virtual void install_memory_handlers(address_space *space) override;
+ virtual void write_bank(uint8_t data) override;
-WRITE8_MEMBER(scv_rom32ram8_device::write_cart)
-{
- if (m_ram_enabled && offset >= 0x6000)
- m_ram[offset & 0x1fff] = data;
-}
+protected:
+ virtual void device_reset() override ATTR_COLD;
-WRITE8_MEMBER(scv_rom32ram8_device::write_bank)
+private:
+ memory_bank_creator m_bank;
+};
+
+void scv_rom128_device::device_reset()
{
- m_ram_enabled = BIT(data, 5);
+ m_bank->set_entry(0);
}
-
-READ8_MEMBER(scv_rom64_device::read_cart)
+void scv_rom128_device::install_memory_handlers(address_space *space)
{
- return m_rom[offset + (m_bank_base * 0x8000)];
+ m_bank->configure_entries(0, 4, cart_rom_region()->base(), 0x8000);
+ space->install_read_bank(0x8000, CARTRIDGE_ADDRESS_END, m_bank);
}
-WRITE8_MEMBER(scv_rom64_device::write_bank)
+void scv_rom128_device::write_bank(uint8_t data)
{
- m_bank_base = BIT(data, 5);
+ m_bank->set_entry((data >> 5) & 0x03);
}
-READ8_MEMBER(scv_rom128_device::read_cart)
-{
- return m_rom[offset + (m_bank_base * 0x8000)];
-}
-WRITE8_MEMBER(scv_rom128_device::write_bank)
+class scv_rom128ram4_device : public scv_rom8_device
{
- m_bank_base = (data >> 5) & 0x03;
-}
+public:
+ scv_rom128ram4_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock)
+ : scv_rom8_device(mconfig, SCV_ROM128K_RAM4K, tag, owner, clock)
+ , m_bank(*this, "bank")
+ , m_view(*this, "view")
+ { }
+ virtual void install_memory_handlers(address_space *space) override;
+ virtual void write_bank(uint8_t data) override;
-READ8_MEMBER(scv_rom128ram4_device::read_cart)
-{
- if (m_ram_enabled && offset >= 0x7000)
- return m_ram[offset & 0xfff];
+protected:
+ virtual void device_reset() override ATTR_COLD;
+
+private:
+ memory_bank_creator m_bank;
+ memory_view m_view;
+};
- return m_rom[offset + (m_bank_base * 0x8000)];
+void scv_rom128ram4_device::device_reset()
+{
+ m_bank->set_entry(0);
+ m_view.select(0);
}
-WRITE8_MEMBER(scv_rom128ram4_device::write_cart)
+void scv_rom128ram4_device::install_memory_handlers(address_space *space)
{
- if (m_ram_enabled && offset >= 0x7000)
- m_ram[offset & 0xfff] = data;
+ m_bank->configure_entries(0, 4, cart_rom_region()->base(), 0x8000);
+ space->install_read_bank(0x8000, CARTRIDGE_ADDRESS_END, m_bank);
+ space->install_view(0xf000, CARTRIDGE_ADDRESS_END, m_view);
+ m_view[0];
+ m_view[1].install_ram(0xf000, CARTRIDGE_ADDRESS_END, cart_ram_region()->base());
}
-WRITE8_MEMBER(scv_rom128ram4_device::write_bank)
+void scv_rom128ram4_device::write_bank(uint8_t data)
{
- m_bank_base = (data >> 5) & 0x03;
- m_ram_enabled = BIT(data, 6);
+ m_bank->set_entry((data >> 5) & 0x03);
+ m_view.select(BIT(data, 6));
}
+
+} // anonymous namespace
+
+DEFINE_DEVICE_TYPE_PRIVATE(SCV_ROM8K, device_scv_cart_interface, scv_rom8_device, "scv_rom8", "SCV 8K Cartridge")
+DEFINE_DEVICE_TYPE_PRIVATE(SCV_ROM16K, device_scv_cart_interface, scv_rom16_device, "scv_rom16", "SCV 16K Cartridge")
+DEFINE_DEVICE_TYPE_PRIVATE(SCV_ROM32K, device_scv_cart_interface, scv_rom32_device, "scv_rom32", "SCV 32K Cartridge")
+DEFINE_DEVICE_TYPE_PRIVATE(SCV_ROM32K_RAM8K, device_scv_cart_interface, scv_rom32ram8_device, "scv_rom32_ram8", "SCV 32K + RAM 8K Cartridge")
+DEFINE_DEVICE_TYPE_PRIVATE(SCV_ROM64K, device_scv_cart_interface, scv_rom64_device, "scv_rom64", "SCV 64K Cartridge")
+DEFINE_DEVICE_TYPE_PRIVATE(SCV_ROM128K, device_scv_cart_interface, scv_rom128_device, "scv_rom128", "SCV 128K Cartridge")
+DEFINE_DEVICE_TYPE_PRIVATE(SCV_ROM128K_RAM4K, device_scv_cart_interface, scv_rom128ram4_device, "scv_rom128_ram4", "SCV 128K + RAM 4K Cartridge")
diff --git a/src/devices/bus/scv/rom.h b/src/devices/bus/scv/rom.h
index 4a6b90b39a1..20f0cefbf23 100644
--- a/src/devices/bus/scv/rom.h
+++ b/src/devices/bus/scv/rom.h
@@ -8,148 +8,13 @@
#include "slot.h"
-// ======================> scv_rom8_device
-
-class scv_rom8_device : public device_t,
- public device_scv_cart_interface
-{
-public:
- // construction/destruction
- scv_rom8_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
-
- // reading and writing
- virtual DECLARE_READ8_MEMBER(read_cart) override;
-
-protected:
- scv_rom8_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 { }
-};
-
-// ======================> scv_rom16_device
-
-class scv_rom16_device : public scv_rom8_device
-{
-public:
- // construction/destruction
- scv_rom16_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
-
- // reading and writing
- virtual DECLARE_READ8_MEMBER(read_cart) override;
-};
-
-
-// ======================> scv_rom32_device
-
-class scv_rom32_device : public scv_rom8_device
-{
-public:
- // construction/destruction
- scv_rom32_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
-
- // reading and writing
- virtual DECLARE_READ8_MEMBER(read_cart) override;
-};
-
-
-// ======================> scv_rom32ram8_device
-
-class scv_rom32ram8_device : public scv_rom8_device
-{
-public:
- // construction/destruction
- scv_rom32ram8_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
-
- // reading and writing
- virtual DECLARE_READ8_MEMBER(read_cart) override;
- virtual DECLARE_WRITE8_MEMBER(write_cart) override;
- virtual DECLARE_WRITE8_MEMBER(write_bank) override;
-
-protected:
- // device-level overrides
- virtual void device_start() override;
- virtual void device_reset() override;
-
-private:
- uint8_t m_ram_enabled;
-};
-
-
-// ======================> scv_rom64_device
-
-class scv_rom64_device : public scv_rom8_device
-{
-public:
- // construction/destruction
- scv_rom64_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
-
- // device-level overrides
- virtual void device_start() override;
- virtual void device_reset() override;
-
- // reading and writing
- virtual DECLARE_READ8_MEMBER(read_cart) override;
- virtual DECLARE_WRITE8_MEMBER(write_bank) override;
-
-private:
- uint8_t m_bank_base;
-};
-
-
-// ======================> scv_rom128_device
-
-class scv_rom128_device : public scv_rom8_device
-{
-public:
- // construction/destruction
- scv_rom128_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
-
- // reading and writing
- virtual DECLARE_READ8_MEMBER(read_cart) override;
- virtual DECLARE_WRITE8_MEMBER(write_bank) override;
-
-protected:
- // device-level overrides
- virtual void device_start() override;
- virtual void device_reset() override;
-
-private:
- uint8_t m_bank_base;
-};
-
-
-// ======================> scv_rom128ram4_device
-
-class scv_rom128ram4_device : public scv_rom8_device
-{
-public:
- // construction/destruction
- scv_rom128ram4_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
-
- // reading and writing
- virtual DECLARE_READ8_MEMBER(read_cart) override;
- virtual DECLARE_WRITE8_MEMBER(write_cart) override;
- virtual DECLARE_WRITE8_MEMBER(write_bank) override;
-
-protected:
- // device-level overrides
- virtual void device_start() override;
- virtual void device_reset() override;
-
-private:
- uint8_t m_bank_base, m_ram_enabled;
-};
-
-
// device type definition
-DECLARE_DEVICE_TYPE(SCV_ROM8K, scv_rom8_device)
-DECLARE_DEVICE_TYPE(SCV_ROM16K, scv_rom16_device)
-DECLARE_DEVICE_TYPE(SCV_ROM32K, scv_rom32_device)
-DECLARE_DEVICE_TYPE(SCV_ROM32K_RAM8K, scv_rom32ram8_device)
-DECLARE_DEVICE_TYPE(SCV_ROM64K, scv_rom64_device)
-DECLARE_DEVICE_TYPE(SCV_ROM128K, scv_rom128_device)
-DECLARE_DEVICE_TYPE(SCV_ROM128K_RAM4K, scv_rom128ram4_device)
+DECLARE_DEVICE_TYPE(SCV_ROM8K, device_scv_cart_interface)
+DECLARE_DEVICE_TYPE(SCV_ROM16K, device_scv_cart_interface)
+DECLARE_DEVICE_TYPE(SCV_ROM32K, device_scv_cart_interface)
+DECLARE_DEVICE_TYPE(SCV_ROM32K_RAM8K, device_scv_cart_interface)
+DECLARE_DEVICE_TYPE(SCV_ROM64K, device_scv_cart_interface)
+DECLARE_DEVICE_TYPE(SCV_ROM128K, device_scv_cart_interface)
+DECLARE_DEVICE_TYPE(SCV_ROM128K_RAM4K, device_scv_cart_interface)
#endif // MAME_BUS_SCV_ROM_H
diff --git a/src/devices/bus/scv/slot.cpp b/src/devices/bus/scv/slot.cpp
index c95f872089a..fe813fa141d 100644
--- a/src/devices/bus/scv/slot.cpp
+++ b/src/devices/bus/scv/slot.cpp
@@ -7,95 +7,73 @@
***********************************************************************************************************/
-
#include "emu.h"
#include "slot.h"
-//**************************************************************************
-// GLOBAL VARIABLES
-//**************************************************************************
DEFINE_DEVICE_TYPE(SCV_CART_SLOT, scv_cart_slot_device, "scv_cart_slot", "SCV Cartridge Slot")
+
+enum
+{
+ SCV_8K = 0,
+ SCV_16K,
+ SCV_32K,
+ SCV_32K_RAM,
+ SCV_64K,
+ SCV_128K,
+ SCV_128K_RAM
+};
+
//**************************************************************************
// SCV cartridges Interface
//**************************************************************************
-//-------------------------------------------------
-// device_scv_cart_interface - constructor
-//-------------------------------------------------
-
-device_scv_cart_interface::device_scv_cart_interface(const machine_config &mconfig, device_t &device)
- : device_slot_card_interface(mconfig, device),
- m_rom(nullptr),
- m_rom_size(0)
+device_scv_cart_interface::device_scv_cart_interface(const machine_config &mconfig, device_t &device) :
+ device_interface(device, "scvcart"),
+ m_slot(dynamic_cast<scv_cart_slot_device *>(device.owner()))
{
}
-//-------------------------------------------------
-// ~device_scv_cart_interface - destructor
-//-------------------------------------------------
-
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::savestate_ram()
{
- if (m_rom == nullptr)
+ if (cart_ram_region())
{
- m_rom = device().machine().memory().region_alloc(std::string(tag).append(SCVSLOT_ROM_REGION_TAG).c_str(), size, 1, ENDIANNESS_LITTLE)->base();
- m_rom_size = size;
+ u8 *rambase(&cart_ram_region()->as_u8());
+ device().save_pointer(NAME(rambase), cart_ram_region()->bytes());
}
}
-//-------------------------------------------------
-// ram_alloc - alloc the space for the ram
-//-------------------------------------------------
-
-void device_scv_cart_interface::ram_alloc(uint32_t size)
-{
- m_ram.resize(size);
-}
-
-
//**************************************************************************
// LIVE DEVICE
//**************************************************************************
-//-------------------------------------------------
-// scv_cart_slot_device - constructor
-//-------------------------------------------------
-scv_cart_slot_device::scv_cart_slot_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) :
+scv_cart_slot_device::scv_cart_slot_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock) :
device_t(mconfig, SCV_CART_SLOT, tag, owner, clock),
- device_image_interface(mconfig, *this),
- device_slot_interface(mconfig, *this),
- m_type(SCV_8K), m_cart(nullptr)
+ device_cartrom_image_interface(mconfig, *this),
+ device_single_card_slot_interface<device_scv_cart_interface>(mconfig, *this),
+ m_type(SCV_8K),
+ m_cart(nullptr),
+ m_address_space(*this, finder_base::DUMMY_TAG, -1, 8)
{
}
-//-------------------------------------------------
-// scv_cart_slot_device - destructor
-//-------------------------------------------------
-
scv_cart_slot_device::~scv_cart_slot_device()
{
}
-//-------------------------------------------------
-// device_start - device-specific startup
-//-------------------------------------------------
void scv_cart_slot_device::device_start()
{
- m_cart = dynamic_cast<device_scv_cart_interface *>(get_card_device());
+ m_cart = get_card_device();
}
@@ -125,11 +103,11 @@ static int scv_get_pcb_id(const char *slot)
{
for (auto & elem : slot_list)
{
- if (!core_stricmp(elem.slot_option, slot))
+ if (!strcmp(elem.slot_option, slot))
return elem.pcb_id;
}
- return 0;
+ return slot_list[0].pcb_id;
}
static const char *scv_get_slot(int type)
@@ -140,41 +118,32 @@ static const char *scv_get_slot(int type)
return elem.slot_option;
}
- return "rom8k";
+ return slot_list[0].slot_option;
}
-/*-------------------------------------------------
- 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");
+ const u32 len = loaded_through_softlist() ? get_software_region_length("rom") : length();
+ const bool has_ram = loaded_through_softlist() && get_software_region("ram");
if (len > 0x20000)
- {
- seterror(IMAGE_ERROR_UNSPECIFIED, "Unsupported cartridge size");
- return image_init_result::FAIL;
- }
-
- m_cart->rom_alloc(len, tag());
- if (has_ram)
- m_cart->ram_alloc(get_software_region_length("ram"));
-
- ROM = m_cart->get_rom_base();
+ return std::make_pair(image_error::INVALIDLENGTH, "Unsupported cartridge size (must be no more than 128K)");
if (!loaded_through_softlist())
- fread(ROM, len);
- else
- memcpy(ROM, get_software_region("rom"), len);
+ {
+ u32 length_aligned = 0x2000;
+ while (length_aligned < len)
+ length_aligned *= 2;
- if (!loaded_through_softlist())
- m_type = get_cart_type(ROM, len);
+ memory_region *const romregion = machine().memory().region_alloc(subtag("rom"), length_aligned, 1, ENDIANNESS_LITTLE);
+ if (fread(romregion->base(), len) != len)
+ return std::make_pair(image_error::UNSPECIFIED, "Unable to fully read file");
+
+ m_type = get_cart_type(len);
+ }
else
{
const char *pcb_name = get_feature("slot");
@@ -189,25 +158,19 @@ image_init_result scv_cart_slot_device::call_load()
if (m_type == SCV_128K && has_ram)
m_type = SCV_128K_RAM;
- //printf("Type: %s\n", scv_get_slot(m_type));
-
- return image_init_result::PASS;
+ m_cart->install_memory_handlers(m_address_space.target());
+ m_cart->savestate_ram();
}
- return image_init_result::PASS;
+ return std::make_pair(std::error_condition(), std::string());
}
-/*-------------------------------------------------
- get_cart_type - code to detect NVRAM type from
- fullpath
- -------------------------------------------------*/
-
-int scv_cart_slot_device::get_cart_type(const uint8_t *ROM, uint32_t len)
+int scv_cart_slot_device::get_cart_type(u32 len)
{
int type = SCV_8K;
- // TO DO: is there any way to identify carts with RAM?!?
+ // TODO: is there any way to identify carts with RAM?!?
switch (len)
{
case 0x2000:
@@ -231,61 +194,25 @@ int scv_cart_slot_device::get_cart_type(const uint8_t *ROM, uint32_t len)
}
-/*-------------------------------------------------
- get default card software
- -------------------------------------------------*/
-
std::string scv_cart_slot_device::get_default_card_software(get_default_card_software_hook &hook) const
{
if (hook.image_file())
{
- const char *slot_string;
- uint32_t len = hook.image_file()->size();
- std::vector<uint8_t> rom(len);
- int type;
+ u64 len = 0;
+ hook.image_file()->length(len); // FIXME: check error return, guard against excessively large files
- hook.image_file()->read(&rom[0], len);
-
- type = get_cart_type(&rom[0], len);
- slot_string = scv_get_slot(type);
-
- //printf("type: %s\n", slot_string);
+ const int type = get_cart_type(len);
+ const char *const slot_string = scv_get_slot(type);
return std::string(slot_string);
}
- return software_get_default_slot("rom8k");
-}
-
-/*-------------------------------------------------
- read
- -------------------------------------------------*/
-
-READ8_MEMBER(scv_cart_slot_device::read_cart)
-{
- if (m_cart)
- return m_cart->read_cart(space, offset);
- else
- return 0xff;
+ return software_get_default_slot(slot_list[0].slot_option);
}
-/*-------------------------------------------------
- write
- -------------------------------------------------*/
-
-WRITE8_MEMBER(scv_cart_slot_device::write_cart)
-{
- if (m_cart)
- m_cart->write_cart(space, offset, data);
-}
-
-
-/*-------------------------------------------------
- write_bank
- -------------------------------------------------*/
-WRITE8_MEMBER(scv_cart_slot_device::write_bank)
+void scv_cart_slot_device::write_bank(u8 data)
{
if (m_cart)
- m_cart->write_bank(space, offset, data);
+ m_cart->write_bank(data);
}
diff --git a/src/devices/bus/scv/slot.h b/src/devices/bus/scv/slot.h
index 357c593c404..f1d385d95b4 100644
--- a/src/devices/bus/scv/slot.h
+++ b/src/devices/bus/scv/slot.h
@@ -5,64 +5,17 @@
#pragma once
-#include "softlist_dev.h"
+#include "imagedev/cartrom.h"
-/***************************************************************************
- TYPE DEFINITIONS
- ***************************************************************************/
-
-
-/* PCB */
-enum
-{
- SCV_8K = 0,
- SCV_16K,
- SCV_32K,
- SCV_32K_RAM,
- SCV_64K,
- SCV_128K,
- SCV_128K_RAM
-};
-
-
-// ======================> device_scv_cart_interface
-
-class device_scv_cart_interface : public device_slot_card_interface
-{
-public:
- // construction/destruction
- virtual ~device_scv_cart_interface();
-
- // reading and writing
- virtual DECLARE_READ8_MEMBER(read_cart) { return 0xff; }
- virtual DECLARE_WRITE8_MEMBER(write_cart) { }
- virtual DECLARE_WRITE8_MEMBER(write_bank) { }
-
- 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 save_ram() { device().save_item(NAME(m_ram)); }
-
-protected:
- device_scv_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;
-};
+class device_scv_cart_interface;
// ======================> scv_cart_slot_device
class scv_cart_slot_device : public device_t,
- public device_image_interface,
- public device_slot_interface
+ public device_cartrom_image_interface,
+ public device_single_card_slot_interface<device_scv_cart_interface>
{
public:
// construction/destruction
@@ -76,54 +29,63 @@ public:
set_fixed(false);
}
- scv_cart_slot_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock = 0);
+ scv_cart_slot_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock = 0);
virtual ~scv_cart_slot_device();
- // image-level overrides
- virtual image_init_result call_load() override;
- virtual void call_unload() override {}
- virtual const software_list_loader &get_software_list_loader() const override { return rom_software_list_loader::instance(); }
+ template <typename T> void set_address_space(T &&tag, int no) { m_address_space.set_tag(std::forward<T>(tag), no); }
- int get_type() { return m_type; }
- static int get_cart_type(const uint8_t *ROM, uint32_t len);
-
- void save_ram() { if (m_cart && m_cart->get_ram_size()) m_cart->save_ram(); }
+ // device_image_interface implementation
+ virtual std::pair<std::error_condition, std::string> call_load() override;
+ virtual void call_unload() override { }
- virtual iodevice_t image_type() const override { return IO_CARTSLOT; }
- virtual bool is_readable() const override { return 1; }
- virtual bool is_writeable() const override { return 0; }
- virtual bool is_creatable() const override { return 0; }
- virtual bool must_be_loaded() const override { return 0; }
- virtual bool is_reset_on_load() const override { return 1; }
- virtual const char *image_interface() const override { return "scv_cart"; }
- virtual const char *file_extensions() const override { return "bin"; }
+ 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; }
+ static int get_cart_type(u32 len);
+
// reading and writing
- virtual DECLARE_READ8_MEMBER(read_cart);
- virtual DECLARE_WRITE8_MEMBER(write_cart);
- virtual DECLARE_WRITE8_MEMBER(write_bank);
+ void write_bank(u8 data);
protected:
- // device-level overrides
- virtual void device_start() override;
+ // device_t implementation
+ virtual void device_start() override ATTR_COLD;
int m_type;
- device_scv_cart_interface* m_cart;
+ device_scv_cart_interface *m_cart;
+ optional_address_space m_address_space;
};
+// ======================> device_scv_cart_interface
-// device type definition
-DECLARE_DEVICE_TYPE(SCV_CART_SLOT, scv_cart_slot_device)
+class device_scv_cart_interface : public device_interface
+{
+public:
+ // construction/destruction
+ virtual ~device_scv_cart_interface();
+
+ virtual void install_memory_handlers(address_space *space) { }
+ virtual void write_bank(u8 data) { }
+
+ void savestate_ram();
+
+protected:
+ device_scv_cart_interface(const machine_config &mconfig, device_t &device);
+
+ 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; }
+private:
+ scv_cart_slot_device *const m_slot;
+};
-/***************************************************************************
- DEVICE CONFIGURATION MACROS
- ***************************************************************************/
-#define SCVSLOT_ROM_REGION_TAG ":cart:rom"
+// device type definition
+DECLARE_DEVICE_TYPE(SCV_CART_SLOT, scv_cart_slot_device)
#endif // MAME_BUS_SCV_SLOT_H
diff --git a/src/devices/bus/sdk85/i8755.cpp b/src/devices/bus/sdk85/i8755.cpp
new file mode 100644
index 00000000000..8c1d7a79fbf
--- /dev/null
+++ b/src/devices/bus/sdk85/i8755.cpp
@@ -0,0 +1,65 @@
+// license:BSD-3-Clause
+// copyright-holders:AJR
+
+#include "emu.h"
+#include "i8755.h"
+
+// device type definition
+DEFINE_DEVICE_TYPE(SDK85_I8755, sdk85exp_i8755_device, "sdk85exp_i8755", "SDK-85 PROM I/O Expansion (Intel 8755)")
+
+sdk85exp_i8755_device::sdk85exp_i8755_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock)
+ : device_t(mconfig, SDK85_I8755, tag, owner, clock)
+ , device_sdk85_romexp_card_interface(mconfig, *this)
+ , m_i8755(*this, "i8755")
+{
+}
+
+void sdk85exp_i8755_device::device_start()
+{
+}
+
+u8 sdk85exp_i8755_device::read_memory(offs_t offset)
+{
+ return m_i8755->memory_r(offset);
+}
+
+void sdk85exp_i8755_device::write_memory(offs_t offset, u8 data)
+{
+ logerror("Writing %02Xh to base + %03Xh\n", data, offset);
+ m_i8755->io_w(offset & 3, data);
+}
+
+u8 sdk85exp_i8755_device::read_io(offs_t offset)
+{
+ return m_i8755->io_r(offset & 3);
+}
+
+void sdk85exp_i8755_device::write_io(offs_t offset, u8 data)
+{
+ m_i8755->io_w(offset & 3, data);
+}
+
+void sdk85exp_i8755_device::device_add_mconfig(machine_config &config)
+{
+ I8355(config, m_i8755, DERIVED_CLOCK(1, 1));
+}
+
+u8 *sdk85exp_i8755_device::get_rom_base(u32 size)
+{
+ if (size != 0x800)
+ {
+ osd_printf_error("sdk85exp_i8755: Data length must be 2,048 bytes\n");
+ return nullptr;
+ }
+
+ return memregion("i8755")->base();
+}
+
+ROM_START(sdk85exp_i8755)
+ ROM_REGION(0x800, "i8755", ROMREGION_ERASE00)
+ROM_END
+
+const tiny_rom_entry *sdk85exp_i8755_device::device_rom_region() const
+{
+ return ROM_NAME(sdk85exp_i8755);
+}
diff --git a/src/devices/bus/sdk85/i8755.h b/src/devices/bus/sdk85/i8755.h
new file mode 100644
index 00000000000..c62779a8b76
--- /dev/null
+++ b/src/devices/bus/sdk85/i8755.h
@@ -0,0 +1,40 @@
+// license:BSD-3-Clause
+// copyright-holders:AJR
+
+#ifndef MAME_BUS_SDK85_I8755_H
+#define MAME_BUS_SDK85_I8755_H
+
+#pragma once
+
+#include "memexp.h"
+#include "machine/i8355.h"
+
+// ======================> sdk85exp_i8755_device
+
+class sdk85exp_i8755_device : public device_t, public device_sdk85_romexp_card_interface
+{
+public:
+ // construction/destruction
+ sdk85exp_i8755_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock);
+
+protected:
+ // device-level overrides
+ virtual void device_start() override ATTR_COLD;
+ virtual void device_add_mconfig(machine_config &config) override ATTR_COLD;
+ virtual const tiny_rom_entry *device_rom_region() const override ATTR_COLD;
+
+ // device_sdk85_romexp_card_interface overrides
+ virtual u8 read_memory(offs_t offset) override;
+ virtual void write_memory(offs_t offset, u8 data) override;
+ virtual u8 read_io(offs_t offset) override;
+ virtual void write_io(offs_t offset, u8 data) override;
+ virtual u8 *get_rom_base(u32 size) override;
+
+private:
+ required_device<i8355_device> m_i8755;
+};
+
+// device type declaration
+DECLARE_DEVICE_TYPE(SDK85_I8755, sdk85exp_i8755_device)
+
+#endif // MAME_BUS_SDK85_I8755_H
diff --git a/src/devices/bus/sdk85/memexp.cpp b/src/devices/bus/sdk85/memexp.cpp
new file mode 100644
index 00000000000..58a05e2fc88
--- /dev/null
+++ b/src/devices/bus/sdk85/memexp.cpp
@@ -0,0 +1,94 @@
+// license:BSD-3-Clause
+// copyright-holders:AJR
+/***************************************************************************
+
+ SDK-85 memory expansion (ALE-multiplexed)
+
+***************************************************************************/
+
+#include "emu.h"
+#include "memexp.h"
+
+#include "i8755.h"
+
+// device type definition
+DEFINE_DEVICE_TYPE(SDK85_ROMEXP, sdk85_romexp_device, "sdk85_romexp", "SDK-85 expansion ROM socket")
+
+sdk85_romexp_device::sdk85_romexp_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock)
+ : device_t(mconfig, SDK85_ROMEXP, tag, owner, clock)
+ , device_rom_image_interface(mconfig, *this)
+ , device_single_card_slot_interface<device_sdk85_romexp_card_interface>(mconfig, *this)
+ , m_dev(nullptr)
+{
+}
+
+std::pair<std::error_condition, std::string> sdk85_romexp_device::call_load()
+{
+ if (get_card_device())
+ {
+ 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);
+ else
+ fread(base, size);
+ }
+
+ 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
+{
+ return software_get_default_slot("i8755");
+}
+
+void sdk85_romexp_device::device_start()
+{
+ m_dev = get_card_device();
+}
+
+u8 sdk85_romexp_device::memory_r(offs_t offset)
+{
+ if (m_dev != nullptr)
+ return m_dev->read_memory(offset);
+ else
+ return 0xff;
+}
+
+void sdk85_romexp_device::memory_w(offs_t offset, u8 data)
+{
+ if (m_dev != nullptr)
+ m_dev->write_memory(offset, data);
+}
+
+u8 sdk85_romexp_device::io_r(offs_t offset)
+{
+ if (m_dev != nullptr)
+ return m_dev->read_io(offset);
+ else
+ return 0xff;
+}
+
+void sdk85_romexp_device::io_w(offs_t offset, u8 data)
+{
+ if (m_dev != nullptr)
+ m_dev->write_io(offset, data);
+}
+
+void sdk85_romexp_device::rom_options(device_slot_interface &slot)
+{
+ slot.option_add_internal("i8755", SDK85_I8755);
+}
+
+device_sdk85_romexp_card_interface::device_sdk85_romexp_card_interface(const machine_config &mconfig, device_t &device)
+ : device_interface(device, "sdk85_romexp")
+{
+}
+
+u8 *device_sdk85_romexp_card_interface::get_rom_base(u32 size)
+{
+ return nullptr;
+}
diff --git a/src/devices/bus/sdk85/memexp.h b/src/devices/bus/sdk85/memexp.h
new file mode 100644
index 00000000000..b42182a49ba
--- /dev/null
+++ b/src/devices/bus/sdk85/memexp.h
@@ -0,0 +1,76 @@
+// license:BSD-3-Clause
+// copyright-holders:AJR
+
+#ifndef MAME_BUS_SDK85_MEMEXP_H
+#define MAME_BUS_SDK85_MEMEXP_H
+
+#pragma once
+
+#include "imagedev/cartrom.h"
+
+// ======================> device_sdk85_romexp_card_interface
+
+class device_sdk85_romexp_card_interface : public device_interface
+{
+ friend class sdk85_romexp_device;
+
+protected:
+ device_sdk85_romexp_card_interface(const machine_config &mconfig, device_t &device);
+
+ virtual u8 read_memory(offs_t offset) = 0;
+ virtual void write_memory(offs_t offset, u8 data) = 0;
+ virtual u8 read_io(offs_t offset) = 0;
+ virtual void write_io(offs_t offset, u8 data) = 0;
+
+ virtual u8 *get_rom_base(u32 size);
+};
+
+// ======================> sdk85_romexp_device
+
+class sdk85_romexp_device : public device_t,
+ public device_rom_image_interface,
+ public device_single_card_slot_interface<device_sdk85_romexp_card_interface>
+{
+public:
+ // construction/destruction
+ sdk85_romexp_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock);
+ template <typename T>
+ sdk85_romexp_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock, T &&opts, const char *dflt)
+ : sdk85_romexp_device(mconfig, tag, owner, clock)
+ {
+ option_reset();
+ opts(*this);
+ set_default_option(dflt);
+ set_fixed(false);
+ }
+
+ static void rom_options(device_slot_interface &device);
+
+ u8 memory_r(offs_t offset);
+ void memory_w(offs_t offset, u8 data);
+ u8 io_r(offs_t offset);
+ void io_w(offs_t offset, u8 data);
+
+protected:
+ // device_t implementation
+ virtual void device_start() override ATTR_COLD;
+
+ // 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"; }
+
+ // device_slot_interface implementation
+ virtual std::string get_default_card_software(get_default_card_software_hook &hook) const override;
+
+private:
+ device_sdk85_romexp_card_interface *m_dev;
+};
+
+// device type declaration
+DECLARE_DEVICE_TYPE(SDK85_ROMEXP, sdk85_romexp_device)
+
+#endif // MAME_BUS_SDK85_MEMEXP_H
diff --git a/src/devices/bus/sega8/ccatch.cpp b/src/devices/bus/sega8/ccatch.cpp
index 1180e7a793b..baf7fc52151 100644
--- a/src/devices/bus/sega8/ccatch.cpp
+++ b/src/devices/bus/sega8/ccatch.cpp
@@ -33,15 +33,15 @@ sega8_cardcatch_device::sega8_cardcatch_device(const machine_config &mconfig, co
mapper specific handlers
-------------------------------------------------*/
-READ8_MEMBER(sega8_cardcatch_device::read_cart)
+uint8_t sega8_cardcatch_device::read_cart(offs_t offset)
{
if (offset < 0x8000)
- return m_card->read_cart(space, offset);
+ return m_card->read_cart(offset);
return 0xff;
}
-WRITE8_MEMBER(sega8_cardcatch_device::write_cart)
+void sega8_cardcatch_device::write_cart(offs_t offset, uint8_t data)
{
// this should never happen, because there is no RAM on cards
if (offset < 0x8000)
diff --git a/src/devices/bus/sega8/ccatch.h b/src/devices/bus/sega8/ccatch.h
index 72d69d32dbd..869d32e831c 100644
--- a/src/devices/bus/sega8/ccatch.h
+++ b/src/devices/bus/sega8/ccatch.h
@@ -17,12 +17,12 @@ public:
sega8_cardcatch_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
// reading and writing
- virtual DECLARE_READ8_MEMBER(read_cart) override;
- virtual DECLARE_WRITE8_MEMBER(write_cart) override;
- virtual DECLARE_WRITE8_MEMBER(write_mapper) override {}
+ virtual uint8_t read_cart(offs_t offset) override;
+ virtual void write_cart(offs_t offset, uint8_t data) override;
+ virtual void write_mapper(offs_t offset, uint8_t data) override {}
protected:
- virtual void device_add_mconfig(machine_config &config) override;
+ virtual void device_add_mconfig(machine_config &config) override ATTR_COLD;
required_device<sega8_card_slot_device> m_card;
};
diff --git a/src/devices/bus/sega8/mgear.cpp b/src/devices/bus/sega8/mgear.cpp
index 46fb6a4ad52..1c128c830ec 100644
--- a/src/devices/bus/sega8/mgear.cpp
+++ b/src/devices/bus/sega8/mgear.cpp
@@ -15,7 +15,7 @@
#include "emu.h"
#include "mgear.h"
-#include "softlist.h"
+#include "softlist_dev.h"
//-------------------------------------------------
// constructors
diff --git a/src/devices/bus/sega8/mgear.h b/src/devices/bus/sega8/mgear.h
index 465ae3d5693..5ce47c56d5a 100644
--- a/src/devices/bus/sega8/mgear.h
+++ b/src/devices/bus/sega8/mgear.h
@@ -18,17 +18,17 @@ public:
sega8_mgear_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
// reading and writing
- virtual DECLARE_READ8_MEMBER(read_cart) override { return m_subslot->read_cart(space, offset); }
- virtual DECLARE_WRITE8_MEMBER(write_cart) override { m_subslot->write_cart(space, offset, data); }
- virtual DECLARE_WRITE8_MEMBER(write_mapper) override { m_subslot->write_mapper(space, offset, data); }
+ virtual uint8_t read_cart(offs_t offset) override { return m_subslot->read_cart(offset); }
+ virtual void write_cart(offs_t offset, uint8_t data) override { m_subslot->write_cart(offset, data); }
+ virtual void write_mapper(offs_t offset, uint8_t data) override { m_subslot->write_mapper(offset, data); }
virtual int get_lphaser_xoffs() override { return m_subslot->get_lphaser_xoffs(); }
protected:
// device-level overrides
- virtual void device_start() override;
- virtual void device_reset() override;
+ virtual void device_start() override ATTR_COLD;
+ virtual void device_reset() override ATTR_COLD;
- virtual void device_add_mconfig(machine_config &config) override;
+ virtual void device_add_mconfig(machine_config &config) override ATTR_COLD;
required_device<sega8_cart_slot_device> m_subslot;
};
diff --git a/src/devices/bus/sega8/rom.cpp b/src/devices/bus/sega8/rom.cpp
index 1f039361a12..6d7abd8338c 100644
--- a/src/devices/bus/sega8/rom.cpp
+++ b/src/devices/bus/sega8/rom.cpp
@@ -11,6 +11,7 @@
#include "emu.h"
#include "rom.h"
+#include "softlist_dev.h"
//-------------------------------------------------
@@ -39,8 +40,10 @@ DEFINE_DEVICE_TYPE(SEGA8_ROM_NEMESIS, sega8_nemesis_device, "sega8_nem
DEFINE_DEVICE_TYPE(SEGA8_ROM_JANGGUN, sega8_janggun_device, "sega8_janggun", "SMS Janggun Cart")
DEFINE_DEVICE_TYPE(SEGA8_ROM_HICOM, sega8_hicom_device, "sega8_hicom", "SMS Hi-Com Carts")
DEFINE_DEVICE_TYPE(SEGA8_ROM_KOREAN, sega8_korean_device, "sega8_korean", "SMS Korean Carts")
+DEFINE_DEVICE_TYPE(SEGA8_ROM_KOREAN_188, sega8_korean_188_device, "sega8_korean_188", "SMS Korean 188 in 1 Multicart")
DEFINE_DEVICE_TYPE(SEGA8_ROM_KOREAN_NB, sega8_korean_nb_device, "sega8_korean_nb", "SMS Korean No-Bank Mapper Carts")
DEFINE_DEVICE_TYPE(SEGA8_ROM_SEOJIN, sega8_seojin_device, "sega8_seojin", "SMS Seo Jin Multi-cart")
+DEFINE_DEVICE_TYPE(SEGA8_ROM_X_TERMINATOR, sega8_x_terminator_device, "sega8_x_terminator", "GG X-Terminator")
// Specific SC-3000 cart types
DEFINE_DEVICE_TYPE(SEGA8_ROM_MULTICART, sega8_multicart_device, "sega8_multicart", "SC-3000 MkII Multicart Cart")
@@ -176,6 +179,13 @@ sega8_korean_device::sega8_korean_device(const machine_config &mconfig, const ch
}
+sega8_korean_188_device::sega8_korean_188_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock)
+ : sega8_rom_device(mconfig, SEGA8_ROM_KOREAN_188, tag, owner, clock)
+ , m_rom_bank_base(0)
+{
+}
+
+
sega8_korean_nb_device::sega8_korean_nb_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
: sega8_rom_device(mconfig, SEGA8_ROM_KOREAN_NB, tag, owner, clock)
{
@@ -256,6 +266,7 @@ void sega8_codemasters_device::device_reset()
m_ram_enabled = 0;
}
+
void sega8_4pak_device::device_start()
{
save_item(NAME(m_rom_bank_base));
@@ -283,6 +294,17 @@ void sega8_zemina_device::device_reset()
}
+void sega8_korean_188_device::device_start()
+{
+ save_item(NAME(m_rom_bank_base));
+}
+
+void sega8_korean_188_device::device_reset()
+{
+ m_rom_bank_base = 0;
+}
+
+
void sega8_multicart_device::device_start()
{
save_item(NAME(m_block));
@@ -383,7 +405,7 @@ void sega8_korean_device::late_bank_setup()
-------------------------------------------------*/
-READ8_MEMBER(sega8_rom_device::read_cart)
+uint8_t sega8_rom_device::read_cart(offs_t offset)
{
int bank = offset / 0x4000;
@@ -396,7 +418,7 @@ READ8_MEMBER(sega8_rom_device::read_cart)
return m_rom[m_rom_bank_base[bank] * 0x4000 + (offset & 0x3fff)];
}
-WRITE8_MEMBER(sega8_rom_device::write_cart)
+void sega8_rom_device::write_cart(offs_t offset, uint8_t data)
{
int bank = offset / 0x4000;
@@ -404,7 +426,7 @@ WRITE8_MEMBER(sega8_rom_device::write_cart)
m_ram[(m_ram_base * 0x4000 + (offset & 0x3fff)) % m_ram.size()] = data;
}
-WRITE8_MEMBER(sega8_rom_device::write_mapper)
+void sega8_rom_device::write_mapper(offs_t offset, uint8_t data)
{
switch (offset)
{
@@ -439,7 +461,7 @@ WRITE8_MEMBER(sega8_rom_device::write_mapper)
-------------------------------------------------*/
-READ8_MEMBER(sega8_othello_device::read_cart)
+uint8_t sega8_othello_device::read_cart(offs_t offset)
{
// 8K of RAM sits in 0x8000-0x9fff
if (offset >= 0x8000 && offset < 0xa000)
@@ -448,7 +470,7 @@ READ8_MEMBER(sega8_othello_device::read_cart)
return m_rom[offset % m_rom_size];
}
-WRITE8_MEMBER(sega8_othello_device::write_cart)
+void sega8_othello_device::write_cart(offs_t offset, uint8_t data)
{
// 2K of RAM sits in 0x8000-0x9fff
if (offset >= 0x8000 && offset < 0xa000)
@@ -463,7 +485,7 @@ WRITE8_MEMBER(sega8_othello_device::write_cart)
-------------------------------------------------*/
-READ8_MEMBER(sega8_castle_device::read_cart)
+uint8_t sega8_castle_device::read_cart(offs_t offset)
{
// 8K of RAM sits in 0x8000-0x9fff
if (offset >= 0x8000 && offset < 0xa000)
@@ -472,7 +494,7 @@ READ8_MEMBER(sega8_castle_device::read_cart)
return m_rom[offset % m_rom_size];
}
-WRITE8_MEMBER(sega8_castle_device::write_cart)
+void sega8_castle_device::write_cart(offs_t offset, uint8_t data)
{
// 8K of RAM sits in 0x8000-0x9fff
if (offset >= 0x8000 && offset < 0xa000)
@@ -487,7 +509,7 @@ WRITE8_MEMBER(sega8_castle_device::write_cart)
-------------------------------------------------*/
-READ8_MEMBER(sega8_basic_l3_device::read_cart)
+uint8_t sega8_basic_l3_device::read_cart(offs_t offset)
{
// 8K of RAM sits in 0x8000-0x9fff
if (offset >= 0x8000)
@@ -496,19 +518,19 @@ READ8_MEMBER(sega8_basic_l3_device::read_cart)
return m_rom[offset % m_rom_size];
}
-WRITE8_MEMBER(sega8_basic_l3_device::write_cart)
+void sega8_basic_l3_device::write_cart(offs_t offset, uint8_t data)
{
// 8K of RAM sits in 0x8000-0x9fff
if (offset >= 0x8000)
m_ram[offset & 0x3fff] = data;
}
-READ8_MEMBER(sega8_basic_l3_device::read_ram)
+uint8_t sega8_basic_l3_device::read_ram(offs_t offset)
{
return m_ram[0x4000 + (offset & 0x3fff)];
}
-WRITE8_MEMBER(sega8_basic_l3_device::write_ram)
+void sega8_basic_l3_device::write_ram(offs_t offset, uint8_t data)
{
m_ram[0x4000 + (offset & 0x3fff)] = data;
}
@@ -521,7 +543,7 @@ WRITE8_MEMBER(sega8_basic_l3_device::write_ram)
-------------------------------------------------*/
-READ8_MEMBER(sega8_music_editor_device::read_cart)
+uint8_t sega8_music_editor_device::read_cart(offs_t offset)
{
// 8K of RAM sits in 0x8000-0x9fff
if (offset >= 0x8000 && offset < 0xa000)
@@ -530,21 +552,21 @@ READ8_MEMBER(sega8_music_editor_device::read_cart)
return m_rom[offset % m_rom_size];
}
-WRITE8_MEMBER(sega8_music_editor_device::write_cart)
+void sega8_music_editor_device::write_cart(offs_t offset, uint8_t data)
{
// 8K of RAM sits in 0x8000-0x9fff
if (offset >= 0x8000 && offset < 0xa000)
m_ram[offset & 0x1fff] = data;
}
-READ8_MEMBER(sega8_music_editor_device::read_ram)
+uint8_t sega8_music_editor_device::read_ram(offs_t offset)
{
// 2K more of RAM sits in 0xc000-0xc3ff (and mirrored up to 0xffff)
// or should it simply go to the 2K of SC3000 RAM???
return m_ram[0x2000 + (offset & 0x7ff)];
}
-WRITE8_MEMBER(sega8_music_editor_device::write_ram)
+void sega8_music_editor_device::write_ram(offs_t offset, uint8_t data)
{
// 2K more of RAM sits in 0xc000-0xc3ff (and mirrored up to 0xffff)
// or should it simply go to the 2K of SC3000 RAM???
@@ -576,7 +598,7 @@ WRITE8_MEMBER(sega8_music_editor_device::write_ram)
*/
-READ8_MEMBER(sega8_terebi_device::read_cart)
+uint8_t sega8_terebi_device::read_cart(offs_t offset)
{
int bank = offset / 0x4000;
@@ -588,7 +610,7 @@ READ8_MEMBER(sega8_terebi_device::read_cart)
return m_rom[m_rom_bank_base[bank] * 0x4000 + (offset & 0x3fff)];
}
-WRITE8_MEMBER(sega8_terebi_device::write_cart)
+void sega8_terebi_device::write_cart(offs_t offset, uint8_t data)
{
switch (offset)
{
@@ -640,7 +662,7 @@ ioport_constructor sega8_terebi_device::device_input_ports() const
-------------------------------------------------*/
// TYPE A
-READ8_MEMBER(sega8_dahjee_typea_device::read_cart)
+uint8_t sega8_dahjee_typea_device::read_cart(offs_t offset)
{
// 8K of RAM sits in 0x2000-0x3fff
if (offset >= 0x2000 && offset < 0x4000)
@@ -649,21 +671,21 @@ READ8_MEMBER(sega8_dahjee_typea_device::read_cart)
return m_rom[offset % m_rom_size];
}
-WRITE8_MEMBER(sega8_dahjee_typea_device::write_cart)
+void sega8_dahjee_typea_device::write_cart(offs_t offset, uint8_t data)
{
// 8K of RAM sits in 0x2000-0x3fff
if (offset >= 0x2000 && offset < 0x4000)
m_ram[offset & 0x1fff] = data;
}
-READ8_MEMBER(sega8_dahjee_typea_device::read_ram)
+uint8_t sega8_dahjee_typea_device::read_ram(offs_t offset)
{
// 1K more of RAM sits in 0xc000-0xc3ff (and mirrored up to 0xffff
// or should it simply go to the 1K of SG1000 RAM???
return m_ram[0x2000 + (offset & 0x3ff)];
}
-WRITE8_MEMBER(sega8_dahjee_typea_device::write_ram)
+void sega8_dahjee_typea_device::write_ram(offs_t offset, uint8_t data)
{
// 1K more of RAM sits in 0xc000-0xc3ff (and mirrored up to 0xffff
// or should it simply go to the 1K of SG1000 RAM???
@@ -672,18 +694,18 @@ WRITE8_MEMBER(sega8_dahjee_typea_device::write_ram)
// TYPE B
-READ8_MEMBER(sega8_dahjee_typeb_device::read_cart)
+uint8_t sega8_dahjee_typeb_device::read_cart(offs_t offset)
{
return m_rom[offset % m_rom_size];
}
-READ8_MEMBER(sega8_dahjee_typeb_device::read_ram)
+uint8_t sega8_dahjee_typeb_device::read_ram(offs_t offset)
{
// 8K more of RAM sits in 0xc000-0xffff
return m_ram[offset & 0x1fff];
}
-WRITE8_MEMBER(sega8_dahjee_typeb_device::write_ram)
+void sega8_dahjee_typeb_device::write_ram(offs_t offset, uint8_t data)
{
// 8K more of RAM sits in 0xc000-0xffff
m_ram[offset & 0x1fff] = data;
@@ -700,7 +722,7 @@ WRITE8_MEMBER(sega8_dahjee_typeb_device::write_ram)
-------------------------------------------------*/
-READ8_MEMBER(sega8_eeprom_device::read_cart)
+uint8_t sega8_eeprom_device::read_cart(offs_t offset)
{
int bank = offset / 0x4000;
@@ -717,7 +739,7 @@ READ8_MEMBER(sega8_eeprom_device::read_cart)
return m_rom[m_rom_bank_base[bank] * 0x4000 + (offset & 0x3fff)];
}
-WRITE8_MEMBER(sega8_eeprom_device::write_cart)
+void sega8_eeprom_device::write_cart(offs_t offset, uint8_t data)
{
if (offset == 0x8000 && m_93c46_enabled)
{
@@ -728,7 +750,7 @@ WRITE8_MEMBER(sega8_eeprom_device::write_cart)
}
}
-WRITE8_MEMBER(sega8_eeprom_device::write_mapper)
+void sega8_eeprom_device::write_mapper(offs_t offset, uint8_t data)
{
switch (offset)
{
@@ -764,7 +786,7 @@ void sega8_eeprom_device::device_add_mconfig(machine_config &config)
-------------------------------------------------*/
-READ8_MEMBER(sega8_codemasters_device::read_cart)
+uint8_t sega8_codemasters_device::read_cart(offs_t offset)
{
int bank = offset / 0x2000;
@@ -774,7 +796,7 @@ READ8_MEMBER(sega8_codemasters_device::read_cart)
return m_rom[m_rom_bank_base[bank/2] * 0x4000 + (offset & 0x3fff)];
}
-WRITE8_MEMBER(sega8_codemasters_device::write_cart)
+void sega8_codemasters_device::write_cart(offs_t offset, uint8_t data)
{
int bank = offset / 0x2000;
@@ -811,7 +833,7 @@ WRITE8_MEMBER(sega8_codemasters_device::write_cart)
-------------------------------------------------*/
-READ8_MEMBER(sega8_4pak_device::read_cart)
+uint8_t sega8_4pak_device::read_cart(offs_t offset)
{
int bank = offset / 0x4000;
@@ -819,7 +841,7 @@ READ8_MEMBER(sega8_4pak_device::read_cart)
}
-WRITE8_MEMBER(sega8_4pak_device::write_cart)
+void sega8_4pak_device::write_cart(offs_t offset, uint8_t data)
{
switch (offset)
{
@@ -846,7 +868,7 @@ WRITE8_MEMBER(sega8_4pak_device::write_cart)
-------------------------------------------------*/
-READ8_MEMBER(sega8_zemina_device::read_cart)
+uint8_t sega8_zemina_device::read_cart(offs_t offset)
{
int bank = offset / 0x2000;
@@ -856,7 +878,7 @@ READ8_MEMBER(sega8_zemina_device::read_cart)
return m_rom[m_rom_bank_base[bank] * 0x2000 + (offset & 0x1fff)];
}
-WRITE8_MEMBER(sega8_zemina_device::write_cart)
+void sega8_zemina_device::write_cart(offs_t offset, uint8_t data)
{
int bank = offset / 0x2000;
@@ -902,7 +924,7 @@ WRITE8_MEMBER(sega8_zemina_device::write_cart)
-------------------------------------------------*/
-READ8_MEMBER(sega8_janggun_device::read_cart)
+uint8_t sega8_janggun_device::read_cart(offs_t offset)
{
int bank = offset / 0x2000;
@@ -913,7 +935,7 @@ READ8_MEMBER(sega8_janggun_device::read_cart)
}
-WRITE8_MEMBER(sega8_janggun_device::write_cart)
+void sega8_janggun_device::write_cart(offs_t offset, uint8_t data)
{
switch (offset)
{
@@ -932,7 +954,7 @@ WRITE8_MEMBER(sega8_janggun_device::write_cart)
}
}
-WRITE8_MEMBER(sega8_janggun_device::write_mapper)
+void sega8_janggun_device::write_mapper(offs_t offset, uint8_t data)
{
switch (offset)
{
@@ -956,7 +978,7 @@ WRITE8_MEMBER(sega8_janggun_device::write_mapper)
-------------------------------------------------*/
-READ8_MEMBER(sega8_hicom_device::read_cart)
+uint8_t sega8_hicom_device::read_cart(offs_t offset)
{
if (offset >= 0x8000)
return m_rom[offset & 0x3fff];
@@ -964,7 +986,7 @@ READ8_MEMBER(sega8_hicom_device::read_cart)
return m_rom[(m_rom_bank_base * 0x8000) + offset];
}
-WRITE8_MEMBER(sega8_hicom_device::write_mapper)
+void sega8_hicom_device::write_mapper(offs_t offset, uint8_t data)
{
if (offset == 0x03)
m_rom_bank_base = data % (m_rom_page_count << 1);
@@ -977,7 +999,7 @@ WRITE8_MEMBER(sega8_hicom_device::write_mapper)
-------------------------------------------------*/
-WRITE8_MEMBER(sega8_korean_device::write_cart)
+void sega8_korean_device::write_cart(offs_t offset, uint8_t data)
{
int bank = offset / 0x4000;
@@ -988,6 +1010,36 @@ WRITE8_MEMBER(sega8_korean_device::write_cart)
m_rom_bank_base[2] = data % m_rom_page_count;
}
+
+/*-------------------------------------------------
+
+ Korean Game 188 multicart,
+ writes to 0x2000 switch 8K banks at 0x4000-0xbfff
+
+ TODO: figure out why menu #s 6, 13, etc don't load.
+ Add dumps of other compatible multicarts.
+
+ -------------------------------------------------*/
+
+u8 sega8_korean_188_device::read_cart(offs_t offset)
+{
+ if (offset < 0x4000)
+ return m_rom[offset];
+ else
+ {
+ int bank = m_rom_bank_base ^ 0x1f;
+ bank %= m_rom_page_count * 2;
+ return m_rom[bank * 0x2000 + offset - 0x4000];
+ }
+}
+
+void sega8_korean_188_device::write_cart(offs_t offset, u8 data)
+{
+ if ((offset & 0x6000) == 0x2000)
+ m_rom_bank_base = data;
+}
+
+
/*-------------------------------------------------
Seo Jin Multi-Carts
@@ -1012,7 +1064,7 @@ void sega8_seojin_device::device_reset()
}
-READ8_MEMBER(sega8_seojin_device::read_cart)
+uint8_t sega8_seojin_device::read_cart(offs_t offset)
{
int bank = offset / 0x4000;
@@ -1024,11 +1076,11 @@ READ8_MEMBER(sega8_seojin_device::read_cart)
return m_rom[bank_to_use * 0x4000 + (offset & 0x3fff)]^m_readxor;
}
-WRITE8_MEMBER(sega8_seojin_device::write_cart)
+void sega8_seojin_device::write_cart(offs_t offset, uint8_t data)
{
}
-WRITE8_MEMBER(sega8_seojin_device::write_mapper)
+void sega8_seojin_device::write_mapper(offs_t offset, uint8_t data)
{
switch (offset)
{
@@ -1045,7 +1097,7 @@ WRITE8_MEMBER(sega8_seojin_device::write_mapper)
// it might not have RAM inside, but the only way to get 0xfff0 to fall through to the cart with the current hook-up
// is by saying there is.
-WRITE8_MEMBER(sega8_seojin_device::write_ram)
+void sega8_seojin_device::write_ram(offs_t offset, uint8_t data)
{
m_ram[offset & 0x3fff] = data;
@@ -1055,7 +1107,7 @@ WRITE8_MEMBER(sega8_seojin_device::write_ram)
}
}
-READ8_MEMBER(sega8_seojin_device::read_ram)
+uint8_t sega8_seojin_device::read_ram(offs_t offset)
{
return m_ram[offset & 0x3fff];
}
@@ -1066,7 +1118,7 @@ READ8_MEMBER(sega8_seojin_device::read_ram)
-------------------------------------------------*/
-READ8_MEMBER(sega8_multicart_device::read_cart)
+uint8_t sega8_multicart_device::read_cart(offs_t offset)
{
// 16K of RAM sits in 0x8000-0xbfff
if (offset >= 0x8000)
@@ -1075,24 +1127,24 @@ READ8_MEMBER(sega8_multicart_device::read_cart)
return m_rom[(offset & 0x7fff) | (m_block << 15) % m_rom_size];
}
-WRITE8_MEMBER(sega8_multicart_device::write_cart)
+void sega8_multicart_device::write_cart(offs_t offset, uint8_t data)
{
// 16K of RAM sits in 0x8000-0xbfff
if (offset >= 0x8000)
m_ram[offset & 0x3fff] = data;
}
-READ8_MEMBER(sega8_multicart_device::read_ram)
+uint8_t sega8_multicart_device::read_ram(offs_t offset)
{
return m_ram[0x4000 + (offset & 0x3fff)];
}
-WRITE8_MEMBER(sega8_multicart_device::write_ram)
+void sega8_multicart_device::write_ram(offs_t offset, uint8_t data)
{
m_ram[0x4000 + (offset & 0x3fff)] = data;
}
-WRITE8_MEMBER(sega8_multicart_device::write_io)
+void sega8_multicart_device::write_io(offs_t offset, uint8_t data)
{
if ((offset & 0xe0) == 0xe0)
m_block = (data & 0x80) ? ((data & 0x1f) | ((data & 0x40) ? 0x20 : 0x00)) : 0x3f;
@@ -1104,7 +1156,7 @@ WRITE8_MEMBER(sega8_multicart_device::write_io)
-------------------------------------------------*/
-READ8_MEMBER(sega8_megacart_device::read_cart)
+uint8_t sega8_megacart_device::read_cart(offs_t offset)
{
// 16K of RAM sits in 0x8000-0xbfff
if (offset >= 0x8000)
@@ -1113,25 +1165,169 @@ READ8_MEMBER(sega8_megacart_device::read_cart)
return m_rom[(offset & 0x7fff) | (m_block << 15) % m_rom_size];
}
-WRITE8_MEMBER(sega8_megacart_device::write_cart)
+void sega8_megacart_device::write_cart(offs_t offset, uint8_t data)
{
// 16K of RAM sits in 0x8000-0xbfff
if (offset >= 0x8000)
m_ram[offset & 0x3fff] = data;
}
-READ8_MEMBER(sega8_megacart_device::read_ram)
+uint8_t sega8_megacart_device::read_ram(offs_t offset)
{
return m_ram[0x4000 + (offset & 0x3fff)];
}
-WRITE8_MEMBER(sega8_megacart_device::write_ram)
+void sega8_megacart_device::write_ram(offs_t offset, uint8_t data)
{
m_ram[0x4000 + (offset & 0x3fff)] = data;
}
-WRITE8_MEMBER(sega8_megacart_device::write_io)
+void sega8_megacart_device::write_io(offs_t offset, uint8_t data)
{
if ((offset & 0xe0) == 0xe0)
m_block = (data & 0x1f) | (data & 0xc0) >> 1;
}
+
+
+/*-------------------------------------------------
+
+GG X-Terminator
+
+The cartridge has a switch to choose NORMAL or ACTION mode
+and a RESET button.
+
+The X-Terminator has logic to switch between the X-Terminator's
+ROM and game ROM when $0038 is read.
+When starting up the X-Terminator's ROM is active. In NORMAL
+mode any read of $38 switches to game ROM. In ACTION mode any
+read of $38 switches between game ROM and X-Terminator ROM (this
+allows the X-Terminator to inject cheat codes during IRQs).
+
+While running a game the RESET button is used to get back
+into the X-Terminator to search for cheat codes.
+
+ -------------------------------------------------*/
+
+sega8_x_terminator_device::sega8_x_terminator_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
+ : sega8_rom_device(mconfig, SEGA8_ROM_X_TERMINATOR, tag, owner, clock)
+ , m_subslot(*this, "subslot")
+ , m_switch(*this, "SWITCH")
+ , m_reset(*this, "RESET")
+ , m_active(true)
+{
+}
+
+static INPUT_PORTS_START( x_terminator )
+ PORT_START("SWITCH")
+ PORT_DIPNAME( 0x01, 0x00, "NORMAL/ACTION" )
+ PORT_DIPSETTING( 0x00, "NORMAL" )
+ PORT_DIPSETTING( 0x01, "ACTION" )
+
+ PORT_START("RESET")
+ PORT_BIT( 0x01, IP_ACTIVE_LOW, IPT_BUTTON3 ) PORT_NAME("Reset")
+INPUT_PORTS_END
+
+ioport_constructor sega8_x_terminator_device::device_input_ports() const
+{
+ return INPUT_PORTS_NAME( x_terminator );
+}
+
+void sega8_x_terminator_device::device_add_mconfig(machine_config &config)
+{
+ GAMEGEAR_CART_SLOT(config, "subslot", gg_cart, nullptr);
+ SOFTWARE_LIST(config, "cart_list").set_original("gamegear");
+}
+
+void sega8_x_terminator_device::device_start()
+{
+ save_item(NAME(m_active));
+}
+
+void sega8_x_terminator_device::device_reset()
+{
+ m_active = true;
+}
+
+uint8_t sega8_x_terminator_device::read_cart(offs_t offset)
+{
+ if (offset == 0x38 && !machine().side_effects_disabled())
+ {
+ if (BIT(m_switch->read(), 0))
+ {
+ // ACTION
+ m_active = !m_active;
+ }
+ else if (!BIT(m_reset->read(), 0))
+ {
+ // RESET button pressed
+ m_active = true;
+ }
+ else
+ {
+ // NORMAL
+ m_active = false;
+ }
+ }
+ if (m_active)
+ {
+ // RAM at 0x2000-0x3fff
+ if (offset >= 0x2000 && offset < 0x4000)
+ return m_ram[offset & 0x1fff];
+
+ // Check RESET button
+ if (offset == 0x0007)
+ return m_reset->read();
+
+ return m_rom[offset % m_rom_size];
+ }
+ else
+ {
+ // Pass-through to inserted game cartridge
+ return m_subslot->read_cart(offset);
+ }
+}
+
+void sega8_x_terminator_device::write_cart(offs_t offset, uint8_t data)
+{
+ if (m_active)
+ {
+ // RAM at 0x2000-0x23fff
+ if (offset >= 0x2000 && offset < 0x4000)
+ m_ram[offset & 0x1fff] = data;
+ }
+ else
+ {
+ // Pass-through to inserted game cartridge
+ m_subslot->write_cart(offset, data);
+ }
+}
+
+void sega8_x_terminator_device::write_mapper(offs_t offset, uint8_t data)
+{
+ // Pass-through to inserted game cartridge
+ m_subslot->write_mapper(offset, data);
+}
+
+uint8_t sega8_x_terminator_device::read_ram(offs_t offset)
+{
+ // Pass-through to inserted game cartridge
+ return m_subslot->read_ram(offset);
+}
+
+void sega8_x_terminator_device::write_ram(offs_t offset, uint8_t data)
+{
+ // Pass-through to inserted game cartridge
+ m_subslot->write_ram(offset, data);
+}
+
+uint8_t sega8_x_terminator_device::read_io(offs_t offset)
+{
+ // Pass-through to inserted game cartridge
+ return m_subslot->read_io(offset);
+}
+
+void sega8_x_terminator_device::write_io(offs_t offset, uint8_t data)
+{
+ // Pass-through to inserted game cartridge
+ m_subslot->write_io(offset, data);
+}
diff --git a/src/devices/bus/sega8/rom.h b/src/devices/bus/sega8/rom.h
index 4f9dc80d967..479ea4d7048 100644
--- a/src/devices/bus/sega8/rom.h
+++ b/src/devices/bus/sega8/rom.h
@@ -20,16 +20,16 @@ public:
virtual void late_bank_setup() override;
// reading and writing
- virtual DECLARE_READ8_MEMBER(read_cart) override;
- virtual DECLARE_WRITE8_MEMBER(write_cart) override;
- virtual DECLARE_WRITE8_MEMBER(write_mapper) override;
+ virtual uint8_t read_cart(offs_t offset) override;
+ virtual void write_cart(offs_t offset, uint8_t data) override;
+ virtual void write_mapper(offs_t offset, uint8_t data) override;
protected:
sega8_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 void device_start() override ATTR_COLD;
+ virtual void device_reset() override ATTR_COLD;
uint8_t m_rom_bank_base[3];
uint8_t m_ram_base;
@@ -48,9 +48,9 @@ public:
sega8_othello_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
// reading and writing
- virtual DECLARE_READ8_MEMBER(read_cart) override;
- virtual DECLARE_WRITE8_MEMBER(write_cart) override;
- virtual DECLARE_WRITE8_MEMBER(write_mapper) override { }
+ virtual uint8_t read_cart(offs_t offset) override;
+ virtual void write_cart(offs_t offset, uint8_t data) override;
+ virtual void write_mapper(offs_t offset, uint8_t data) override { }
};
@@ -63,9 +63,9 @@ public:
sega8_castle_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
// reading and writing
- virtual DECLARE_READ8_MEMBER(read_cart) override;
- virtual DECLARE_WRITE8_MEMBER(write_cart) override;
- virtual DECLARE_WRITE8_MEMBER(write_mapper) override { }
+ virtual uint8_t read_cart(offs_t offset) override;
+ virtual void write_cart(offs_t offset, uint8_t data) override;
+ virtual void write_mapper(offs_t offset, uint8_t data) override { }
};
@@ -78,13 +78,13 @@ public:
sega8_basic_l3_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
// reading and writing
- virtual DECLARE_READ8_MEMBER(read_cart) override;
- virtual DECLARE_WRITE8_MEMBER(write_cart) override;
- virtual DECLARE_WRITE8_MEMBER(write_mapper) override { }
+ virtual uint8_t read_cart(offs_t offset) override;
+ virtual void write_cart(offs_t offset, uint8_t data) override;
+ virtual void write_mapper(offs_t offset, uint8_t data) override { }
// has internal RAM which overwrites the system one!
- virtual DECLARE_READ8_MEMBER(read_ram) override;
- virtual DECLARE_WRITE8_MEMBER(write_ram) override;
+ virtual uint8_t read_ram(offs_t offset) override;
+ virtual void write_ram(offs_t offset, uint8_t data) override;
};
@@ -97,13 +97,13 @@ public:
sega8_music_editor_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
// reading and writing
- virtual DECLARE_READ8_MEMBER(read_cart) override;
- virtual DECLARE_WRITE8_MEMBER(write_cart) override;
- virtual DECLARE_WRITE8_MEMBER(write_mapper) override { }
+ virtual uint8_t read_cart(offs_t offset) override;
+ virtual void write_cart(offs_t offset, uint8_t data) override;
+ virtual void write_mapper(offs_t offset, uint8_t data) override { }
// has internal RAM which overwrites the system one!
- virtual DECLARE_READ8_MEMBER(read_ram) override;
- virtual DECLARE_WRITE8_MEMBER(write_ram) override;
+ virtual uint8_t read_ram(offs_t offset) override;
+ virtual void write_ram(offs_t offset, uint8_t data) override;
};
@@ -116,20 +116,20 @@ public:
sega8_terebi_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;
+ virtual ioport_constructor device_input_ports() const override ATTR_COLD;
required_ioport m_tvdraw_x;
required_ioport m_tvdraw_y;
required_ioport m_tvdraw_pen;
// reading and writing
- virtual DECLARE_READ8_MEMBER(read_cart) override;
- virtual DECLARE_WRITE8_MEMBER(write_cart) override;
- virtual DECLARE_WRITE8_MEMBER(write_mapper) override { }
+ virtual uint8_t read_cart(offs_t offset) override;
+ virtual void write_cart(offs_t offset, uint8_t data) override;
+ virtual void write_mapper(offs_t offset, uint8_t data) override { }
protected:
- virtual void device_start() override;
- virtual void device_reset() override;
+ virtual void device_start() override ATTR_COLD;
+ virtual void device_reset() override ATTR_COLD;
uint8_t m_tvdraw_data;
};
@@ -144,13 +144,13 @@ public:
sega8_dahjee_typea_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
// reading and writing
- virtual DECLARE_READ8_MEMBER(read_cart) override;
- virtual DECLARE_WRITE8_MEMBER(write_cart) override;
- virtual DECLARE_WRITE8_MEMBER(write_mapper) override { }
+ virtual uint8_t read_cart(offs_t offset) override;
+ virtual void write_cart(offs_t offset, uint8_t data) override;
+ virtual void write_mapper(offs_t offset, uint8_t data) override { }
// has internal RAM which overwrites the system one!
- virtual DECLARE_READ8_MEMBER(read_ram) override;
- virtual DECLARE_WRITE8_MEMBER(write_ram) override;
+ virtual uint8_t read_ram(offs_t offset) override;
+ virtual void write_ram(offs_t offset, uint8_t data) override;
};
@@ -163,13 +163,13 @@ public:
sega8_dahjee_typeb_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
// reading and writing
- virtual DECLARE_READ8_MEMBER(read_cart) override;
- virtual DECLARE_WRITE8_MEMBER(write_cart) override { }
- virtual DECLARE_WRITE8_MEMBER(write_mapper) override { }
+ virtual uint8_t read_cart(offs_t offset) override;
+ virtual void write_cart(offs_t offset, uint8_t data) override { }
+ virtual void write_mapper(offs_t offset, uint8_t data) override { }
// has internal RAM which overwrites the system one!
- virtual DECLARE_READ8_MEMBER(read_ram) override;
- virtual DECLARE_WRITE8_MEMBER(write_ram) override;
+ virtual uint8_t read_ram(offs_t offset) override;
+ virtual void write_ram(offs_t offset, uint8_t data) override;
};
@@ -187,16 +187,16 @@ public:
virtual void late_bank_setup() override;
// reading and writing
- virtual DECLARE_READ8_MEMBER(read_cart) override;
- virtual DECLARE_WRITE8_MEMBER(write_cart) override;
- virtual DECLARE_WRITE8_MEMBER(write_mapper) override;
+ virtual uint8_t read_cart(offs_t offset) override;
+ virtual void write_cart(offs_t offset, uint8_t data) override;
+ virtual void write_mapper(offs_t offset, uint8_t data) override;
protected:
- virtual void device_start() override;
- virtual void device_reset() override;
+ virtual void device_start() override ATTR_COLD;
+ virtual void device_reset() override ATTR_COLD;
// device-level overrides
- virtual void device_add_mconfig(machine_config &config) override;
+ virtual void device_add_mconfig(machine_config &config) override ATTR_COLD;
uint8_t m_rom_bank_base[3];
@@ -218,14 +218,14 @@ public:
virtual void late_bank_setup() override;
// reading and writing
- virtual DECLARE_READ8_MEMBER(read_cart) override;
- virtual DECLARE_WRITE8_MEMBER(write_cart) override;
+ virtual uint8_t read_cart(offs_t offset) override;
+ virtual void write_cart(offs_t offset, uint8_t data) override;
// no mapper write for this!
protected:
// device-level overrides
- virtual void device_start() override;
- virtual void device_reset() override;
+ virtual void device_start() override ATTR_COLD;
+ virtual void device_reset() override ATTR_COLD;
uint8_t m_rom_bank_base[3];
uint8_t m_ram_base;
@@ -242,13 +242,13 @@ public:
sega8_4pak_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
// reading and writing
- virtual DECLARE_READ8_MEMBER(read_cart) override;
- virtual DECLARE_WRITE8_MEMBER(write_cart) 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_start() override ATTR_COLD;
+ virtual void device_reset() override ATTR_COLD;
private:
uint8_t m_reg[3];
@@ -267,16 +267,16 @@ public:
virtual void late_bank_setup() override;
// reading and writing
- virtual DECLARE_READ8_MEMBER(read_cart) override;
- virtual DECLARE_WRITE8_MEMBER(write_cart) override;
+ virtual uint8_t read_cart(offs_t offset) override;
+ virtual void write_cart(offs_t offset, uint8_t data) override;
// no mapper write for this!
protected:
sega8_zemina_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_start() override ATTR_COLD;
+ virtual void device_reset() override ATTR_COLD;
uint8_t m_rom_bank_base[6];
uint8_t m_ram_base;
@@ -308,9 +308,9 @@ public:
virtual void late_bank_setup() override;
// reading and writing
- virtual DECLARE_READ8_MEMBER(read_cart) override;
- virtual DECLARE_WRITE8_MEMBER(write_cart) override;
- virtual DECLARE_WRITE8_MEMBER(write_mapper) override;
+ virtual uint8_t read_cart(offs_t offset) override;
+ virtual void write_cart(offs_t offset, uint8_t data) override;
+ virtual void write_mapper(offs_t offset, uint8_t data) override;
protected:
// device-level overrides
@@ -331,9 +331,9 @@ public:
virtual void late_bank_setup() override;
// reading and writing
- virtual DECLARE_READ8_MEMBER(read_cart) override;
- virtual DECLARE_WRITE8_MEMBER(write_cart) override {}
- virtual DECLARE_WRITE8_MEMBER(write_mapper) override;
+ virtual uint8_t read_cart(offs_t offset) override;
+ virtual void write_cart(offs_t offset, uint8_t data) override {}
+ virtual void write_mapper(offs_t offset, uint8_t data) override;
protected:
// device-level overrides
@@ -354,8 +354,30 @@ public:
virtual void late_bank_setup() override;
// reading and writing
- virtual DECLARE_WRITE8_MEMBER(write_cart) override;
- virtual DECLARE_WRITE8_MEMBER(write_mapper) override {}
+ virtual void write_cart(offs_t offset, uint8_t data) override;
+ virtual void write_mapper(offs_t offset, uint8_t data) override {}
+};
+
+
+// ======================> sega8_korean_188_device
+
+class sega8_korean_188_device : public sega8_rom_device
+{
+public:
+ // construction/destruction
+ sega8_korean_188_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock);
+
+ // reading and writing
+ virtual u8 read_cart(offs_t offset) override;
+ virtual void write_cart(offs_t offset, u8 data) override;
+
+protected:
+ // device-level overrides
+ virtual void device_start() override ATTR_COLD;
+ virtual void device_reset() override ATTR_COLD;
+
+private:
+ u8 m_rom_bank_base;
};
@@ -368,7 +390,7 @@ public:
sega8_korean_nb_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
// reading and writing
- virtual DECLARE_WRITE8_MEMBER(write_mapper) override {}
+ virtual void write_mapper(offs_t offset, uint8_t data) override {}
};
@@ -381,16 +403,16 @@ public:
sega8_seojin_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
// reading and writing
- virtual DECLARE_READ8_MEMBER(read_cart) override;
- virtual DECLARE_WRITE8_MEMBER(write_cart) override;
- virtual DECLARE_WRITE8_MEMBER(write_mapper) override;
- virtual DECLARE_READ8_MEMBER(read_ram) override;
- virtual DECLARE_WRITE8_MEMBER(write_ram) override;
+ virtual uint8_t read_cart(offs_t offset) override;
+ virtual void write_cart(offs_t offset, uint8_t data) override;
+ virtual void write_mapper(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;
+ virtual void device_start() override ATTR_COLD;
+ virtual void device_reset() override ATTR_COLD;
uint8_t m_gamesel;
uint8_t m_readxor;
@@ -406,18 +428,18 @@ public:
sega8_multicart_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
// reading and writing
- virtual DECLARE_READ8_MEMBER(read_cart) override;
- virtual DECLARE_WRITE8_MEMBER(write_cart) override;
- virtual DECLARE_WRITE8_MEMBER(write_io) override;
+ virtual uint8_t read_cart(offs_t offset) override;
+ virtual void write_cart(offs_t offset, uint8_t data) override;
+ virtual void write_io(offs_t offset, uint8_t data) override;
// has internal RAM which overwrites the system one!
- virtual DECLARE_READ8_MEMBER(read_ram) override;
- virtual DECLARE_WRITE8_MEMBER(write_ram) 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;
+ virtual void device_start() override ATTR_COLD;
+ virtual void device_reset() override ATTR_COLD;
private:
uint8_t m_block;
@@ -433,23 +455,50 @@ public:
sega8_megacart_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
// reading and writing
- virtual DECLARE_READ8_MEMBER(read_cart) override;
- virtual DECLARE_WRITE8_MEMBER(write_cart) override;
- virtual DECLARE_WRITE8_MEMBER(write_io) override;
+ virtual uint8_t read_cart(offs_t offset) override;
+ virtual void write_cart(offs_t offset, uint8_t data) override;
+ virtual void write_io(offs_t offset, uint8_t data) override;
// has internal RAM which overwrites the system one!
- virtual DECLARE_READ8_MEMBER(read_ram) override;
- virtual DECLARE_WRITE8_MEMBER(write_ram) 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;
+ virtual void device_start() override ATTR_COLD;
+ virtual void device_reset() override ATTR_COLD;
private:
uint8_t m_block;
};
+class sega8_x_terminator_device : public sega8_rom_device
+{
+public:
+ sega8_x_terminator_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
+
+ virtual ioport_constructor device_input_ports() const override ATTR_COLD;
+
+ // 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 write_mapper(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;
+ virtual uint8_t read_io(offs_t offset) override;
+ virtual void write_io(offs_t offset, uint8_t data) override;
+
+protected:
+ // device-level overrides
+ 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;
+
+ required_device<sega8_cart_slot_device> m_subslot;
+ required_ioport m_switch;
+ required_ioport m_reset;
+ bool m_active;
+};
// device type definition
DECLARE_DEVICE_TYPE(SEGA8_ROM_STD, sega8_rom_device)
@@ -468,9 +517,11 @@ DECLARE_DEVICE_TYPE(SEGA8_ROM_NEMESIS, sega8_nemesis_device)
DECLARE_DEVICE_TYPE(SEGA8_ROM_JANGGUN, sega8_janggun_device)
DECLARE_DEVICE_TYPE(SEGA8_ROM_HICOM, sega8_hicom_device)
DECLARE_DEVICE_TYPE(SEGA8_ROM_KOREAN, sega8_korean_device)
+DECLARE_DEVICE_TYPE(SEGA8_ROM_KOREAN_188, sega8_korean_188_device)
DECLARE_DEVICE_TYPE(SEGA8_ROM_KOREAN_NB, sega8_korean_nb_device)
DECLARE_DEVICE_TYPE(SEGA8_ROM_SEOJIN, sega8_seojin_device)
DECLARE_DEVICE_TYPE(SEGA8_ROM_MULTICART, sega8_multicart_device)
DECLARE_DEVICE_TYPE(SEGA8_ROM_MEGACART, sega8_megacart_device)
+DECLARE_DEVICE_TYPE(SEGA8_ROM_X_TERMINATOR, sega8_x_terminator_device)
#endif // MAME_BUS_SEGA8_ROM_H
diff --git a/src/devices/bus/sega8/sega8_slot.cpp b/src/devices/bus/sega8/sega8_slot.cpp
index 4af1059cb74..d30b5c4e869 100644
--- a/src/devices/bus/sega8/sega8_slot.cpp
+++ b/src/devices/bus/sega8/sega8_slot.cpp
@@ -25,10 +25,11 @@
***********************************************************************************************************/
-
#include "emu.h"
#include "sega8_slot.h"
+#include "multibyte.h"
+
#define VERBOSE 0
#include "logmacro.h"
@@ -60,7 +61,7 @@ DEFINE_DEVICE_TYPE(SG1000_CARD_SLOT, sg1000_card_slot_device, "sg1000_card
//-------------------------------------------------
device_sega8_cart_interface::device_sega8_cart_interface(const machine_config &mconfig, device_t &device)
- : device_slot_card_interface(mconfig, device)
+ : device_interface(device, "sega8cart")
, m_rom(nullptr)
, m_rom_size(0)
, m_rom_page_count(0)
@@ -84,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)
@@ -119,8 +120,8 @@ void device_sega8_cart_interface::ram_alloc(uint32_t size)
sega8_cart_slot_device::sega8_cart_slot_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock, bool is_card)
: device_t(mconfig, type, tag, owner, clock)
- , device_image_interface(mconfig, *this)
- , device_slot_interface(mconfig, *this)
+ , device_cartrom_image_interface(mconfig, *this)
+ , device_single_card_slot_interface<device_sega8_cart_interface>(mconfig, *this)
, m_type(SEGA8_BASE_ROM)
, m_is_card(is_card)
, m_cart(nullptr)
@@ -198,7 +199,7 @@ sega8_cart_slot_device::~sega8_cart_slot_device()
void sega8_cart_slot_device::device_start()
{
- m_cart = dynamic_cast<device_sega8_cart_interface *>(get_card_device());
+ m_cart = get_card_device();
}
//-------------------------------------------------
@@ -224,6 +225,7 @@ static const sega8_slot slot_list[] =
{ SEGA8_NEMESIS, "nemesis" },
{ SEGA8_JANGGUN, "janggun" },
{ SEGA8_KOREAN, "korean" },
+ { SEGA8_KOREAN_188IN1, "korean_188in1" },
{ SEGA8_KOREAN_NOBANK, "korean_nb" },
{ SEGA8_OTHELLO, "othello" },
{ SEGA8_CASTLE, "castle" },
@@ -233,14 +235,15 @@ static const sega8_slot slot_list[] =
{ SEGA8_DAHJEE_TYPEB, "dahjee_typeb" },
{ SEGA8_SEOJIN, "seojin" },
{ SEGA8_MULTICART, "multicart" },
- { SEGA8_MEGACART, "megacart" }
+ { SEGA8_MEGACART, "megacart" },
+ { SEGA8_X_TERMINATOR, "xterminator" }
};
static int sega8_get_pcb_id(const char *slot)
{
for (auto & elem : slot_list)
{
- if (!core_stricmp(elem.slot_option, slot))
+ if (!strcmp(elem.slot_option, slot))
return elem.pcb_id;
}
@@ -263,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] =
{
@@ -358,6 +363,12 @@ void sega8_cart_slot_device::setup_ram()
m_cart->ram_alloc(0x10000);
m_cart->set_has_battery(false);
}
+ else if (m_type == SEGA8_X_TERMINATOR)
+ {
+ // X-Terminator seems to have 8192 bytes of RAM
+ // Unknown if the RAM is battery backed
+ m_cart->ram_alloc(0x2000);
+ }
else
{
// for generic carts loaded from fullpath we have no way to know exactly if there was RAM,
@@ -381,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_UNSPECIFIED, "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())
{
@@ -417,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())
@@ -446,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());
}
@@ -534,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)
@@ -583,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)
{
@@ -647,6 +652,8 @@ int sega8_cart_slot_device::get_cart_type(const uint8_t *ROM, uint32_t len) cons
if (len == 0x400000)
type = SEGA8_MEGACART;
+ if (len == 0x2000)
+ type = SEGA8_X_TERMINATOR;
return type;
}
@@ -658,18 +665,16 @@ std::string sega8_cart_slot_device::get_default_card_software(get_default_card_s
{
if (hook.image_file())
{
- const char *slot_string;
- uint32_t len = hook.image_file()->size(), offset = 0;
+ uint64_t len;
+ hook.image_file()->length(len); // FIXME: check error return, guard against excessively large files
std::vector<uint8_t> rom(len);
- int type;
- hook.image_file()->read(&rom[0], len);
+ /*auto const [err, actual] =*/ read(*hook.image_file(), &rom[0], len); // FIXME: check error return or read returning short
- if ((len % 0x4000) == 512)
- offset = 512;
+ uint32_t const offset = ((len % 0x4000) == 512) ? 512 : 0;
- type = get_cart_type(&rom[offset], len - offset);
- slot_string = sega8_get_slot(type);
+ int const type = get_cart_type(&rom[offset], len - offset);
+ char const *const slot_string = sega8_get_slot(type);
//printf("type: %s\n", slot_string);
@@ -685,26 +690,26 @@ std::string sega8_cart_slot_device::get_default_card_software(get_default_card_s
read
-------------------------------------------------*/
-READ8_MEMBER(sega8_cart_slot_device::read_cart)
+uint8_t sega8_cart_slot_device::read_cart(offs_t offset)
{
if (m_cart)
- return m_cart->read_cart(space, offset);
+ return m_cart->read_cart(offset);
else
return 0xff;
}
-READ8_MEMBER(sega8_cart_slot_device::read_ram)
+uint8_t sega8_cart_slot_device::read_ram(offs_t offset)
{
if (m_cart)
- return m_cart->read_ram(space, offset);
+ return m_cart->read_ram(offset);
else
return 0xff;
}
-READ8_MEMBER(sega8_cart_slot_device::read_io)
+uint8_t sega8_cart_slot_device::read_io(offs_t offset)
{
if (m_cart)
- return m_cart->read_io(space, offset);
+ return m_cart->read_io(offset);
else
return 0xff;
}
@@ -714,28 +719,28 @@ READ8_MEMBER(sega8_cart_slot_device::read_io)
write
-------------------------------------------------*/
-WRITE8_MEMBER(sega8_cart_slot_device::write_mapper)
+void sega8_cart_slot_device::write_mapper(offs_t offset, uint8_t data)
{
if (m_cart)
- m_cart->write_mapper(space, offset, data);
+ m_cart->write_mapper(offset, data);
}
-WRITE8_MEMBER(sega8_cart_slot_device::write_cart)
+void sega8_cart_slot_device::write_cart(offs_t offset, uint8_t data)
{
if (m_cart)
- m_cart->write_cart(space, offset, data);
+ m_cart->write_cart(offset, data);
}
-WRITE8_MEMBER(sega8_cart_slot_device::write_ram)
+void sega8_cart_slot_device::write_ram(offs_t offset, uint8_t data)
{
if (m_cart)
- m_cart->write_ram(space, offset, data);
+ m_cart->write_ram(offset, data);
}
-WRITE8_MEMBER(sega8_cart_slot_device::write_io)
+void sega8_cart_slot_device::write_io(offs_t offset, uint8_t data)
{
if (m_cart)
- m_cart->write_io(space, offset, data);
+ m_cart->write_io(offset, data);
}
@@ -743,7 +748,7 @@ WRITE8_MEMBER(sega8_cart_slot_device::write_io)
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[] =
{
@@ -785,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" );
@@ -807,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" );
@@ -849,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
@@ -864,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;
}
}
@@ -909,6 +907,7 @@ void sg1000mk3_cart(device_slot_interface &device)
device.option_add_internal("janggun", SEGA8_ROM_JANGGUN);
device.option_add_internal("hicom", SEGA8_ROM_HICOM);
device.option_add_internal("korean", SEGA8_ROM_KOREAN);
+ device.option_add_internal("korean_188in1", SEGA8_ROM_KOREAN_188);
device.option_add_internal("korean_nb", SEGA8_ROM_KOREAN_NB);
device.option_add_internal("seojin", SEGA8_ROM_SEOJIN);
device.option_add_internal("othello", SEGA8_ROM_OTHELLO);
@@ -930,6 +929,7 @@ void sms_cart(device_slot_interface &device)
device.option_add_internal("janggun", SEGA8_ROM_JANGGUN);
device.option_add_internal("hicom", SEGA8_ROM_HICOM);
device.option_add_internal("korean", SEGA8_ROM_KOREAN);
+ device.option_add_internal("korean_188in1", SEGA8_ROM_KOREAN_188);
device.option_add_internal("korean_nb", SEGA8_ROM_KOREAN_NB);
}
@@ -939,4 +939,5 @@ void gg_cart(device_slot_interface &device)
device.option_add_internal("eeprom", SEGA8_ROM_EEPROM);
device.option_add_internal("codemasters", SEGA8_ROM_CODEMASTERS);
device.option_add_internal("mgear", SEGA8_ROM_MGEAR);
+ device.option_add_internal("xterminator", SEGA8_ROM_X_TERMINATOR);
}
diff --git a/src/devices/bus/sega8/sega8_slot.h b/src/devices/bus/sega8/sega8_slot.h
index 9e1236076ae..7f320b4fc42 100644
--- a/src/devices/bus/sega8/sega8_slot.h
+++ b/src/devices/bus/sega8/sega8_slot.h
@@ -1,11 +1,11 @@
// license:BSD-3-Clause
// copyright-holders:Fabio Priuli
-#ifndef MAME_BUS_SEGA8_SLOT_H
-#define MAME_BUS_SEGA8_SLOT_H
+#ifndef MAME_BUS_SEGA8_SEGA8_SLOT_H
+#define MAME_BUS_SEGA8_SEGA8_SLOT_H
#pragma once
-#include "softlist_dev.h"
+#include "imagedev/cartrom.h"
/***************************************************************************
@@ -25,6 +25,7 @@ enum
SEGA8_NEMESIS,
SEGA8_JANGGUN,
SEGA8_KOREAN,
+ SEGA8_KOREAN_188IN1,
SEGA8_KOREAN_NOBANK,
SEGA8_OTHELLO,
SEGA8_CASTLE,
@@ -34,7 +35,8 @@ enum
SEGA8_DAHJEE_TYPEB,
SEGA8_SEOJIN,
SEGA8_MULTICART,
- SEGA8_MEGACART
+ SEGA8_MEGACART,
+ SEGA8_X_TERMINATOR
};
@@ -44,25 +46,25 @@ DECLARE_DEVICE_TYPE(SEGA8_CARD_SLOT, sega8_card_slot_device)
// ======================> device_sega8_cart_interface
-class device_sega8_cart_interface : public device_slot_card_interface
+class device_sega8_cart_interface : public device_interface
{
public:
// construction/destruction
virtual ~device_sega8_cart_interface();
// reading and writing
- virtual DECLARE_READ8_MEMBER(read_cart) { return 0xff; }
- virtual DECLARE_WRITE8_MEMBER(write_cart) { }
- virtual DECLARE_WRITE8_MEMBER(write_mapper) { }
+ virtual uint8_t read_cart(offs_t offset) { return 0xff; }
+ virtual void write_cart(offs_t offset, uint8_t data) { }
+ virtual void write_mapper(offs_t offset, uint8_t data) { }
virtual int get_lphaser_xoffs() { return m_lphaser_xoffs; }
// a few carts (for SG1000) acts as a RAM expansion, taking control of the system RAM in 0xc000-0xffff
- virtual DECLARE_READ8_MEMBER(read_ram) { return 0xff; }
- virtual DECLARE_WRITE8_MEMBER(write_ram) { }
+ virtual uint8_t read_ram(offs_t offset) { return 0xff; }
+ virtual void write_ram(offs_t offset, uint8_t data) { }
// the SC3000 has I/OR, I/OW lines connected
- virtual DECLARE_READ8_MEMBER(read_io) { return 0xff; }
- virtual DECLARE_WRITE8_MEMBER(write_io) { }
+ 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() { }
@@ -106,51 +108,43 @@ protected:
// ======================> sega8_cart_slot_device
class sega8_cart_slot_device : public device_t,
- public device_image_interface,
- public device_slot_interface
+ public device_cartrom_image_interface,
+ public device_single_card_slot_interface<device_sega8_cart_interface>
{
public:
// construction/destruction
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 const software_list_loader &get_software_list_loader() const override { return rom_software_list_loader::instance(); }
- virtual const char *custom_instance_name() const override { return "cartridge"; }
- virtual const char *custom_brief_instance_name() const override { return "cart"; }
+
+ 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"; }
+
+ // 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(); }
- virtual iodevice_t image_type() const override { return IO_CARTSLOT; }
- virtual bool is_readable() const override { return 1; }
- virtual bool is_writeable() const override { return 0; }
- virtual bool is_creatable() const override { return 0; }
- virtual bool is_reset_on_load() const override { return 1; }
- virtual bool must_be_loaded() const override { return false; }
- virtual const char *image_interface() const override { return "sms_cart"; }
- virtual const char *file_extensions() const override { return "bin"; }
-
- // slot interface overrides
- virtual std::string get_default_card_software(get_default_card_software_hook &hook) const override;
-
// reading and writing
- virtual DECLARE_READ8_MEMBER(read_cart);
- virtual DECLARE_WRITE8_MEMBER(write_cart);
- virtual DECLARE_WRITE8_MEMBER(write_mapper);
- virtual DECLARE_READ8_MEMBER(read_ram);
- virtual DECLARE_WRITE8_MEMBER(write_ram);
- virtual DECLARE_READ8_MEMBER(read_io);
- virtual DECLARE_WRITE8_MEMBER(write_io);
+ uint8_t read_cart(offs_t offset);
+ void write_cart(offs_t offset, uint8_t data);
+ void write_mapper(offs_t offset, uint8_t data);
+ uint8_t read_ram(offs_t offset);
+ void write_ram(offs_t offset, uint8_t data);
+ uint8_t read_io(offs_t offset);
+ void write_io(offs_t offset, uint8_t data);
int get_lphaser_xoffs() { return m_cart ? m_cart->get_lphaser_xoffs() : -1; }
int get_sms_mode() { return m_cart->get_sms_mode(); }
@@ -158,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
- virtual void device_start() override;
+ // device_t implementation
+ virtual void device_start() override ATTR_COLD;
int m_type;
bool const m_is_card;
- device_sega8_cart_interface* m_cart;
+ device_sega8_cart_interface *m_cart;
};
// ======================> sega8_card_slot_device
@@ -174,8 +168,8 @@ public:
// construction/destruction
sega8_card_slot_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
- virtual const char *custom_instance_name() const override { return "card"; }
- virtual const char *custom_brief_instance_name() const override { return "card"; }
+ virtual const char *image_type_name() const noexcept override { return "card"; }
+ virtual const char *image_brief_type_name() const noexcept override { return "card"; }
protected:
// construction/destruction
@@ -198,9 +192,8 @@ public:
set_fixed(false);
}
sg1000_cart_slot_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
- virtual bool must_be_loaded() const override { return true; }
- virtual const char *image_interface() const override { return "sg1000_cart"; }
- virtual const char *file_extensions() const override { return "bin,sg"; }
+ virtual const char *image_interface() const noexcept override { return "sg1000_cart"; }
+ virtual const char *file_extensions() const noexcept override { return "bin,sg"; }
};
// ======================> omv_cart_slot_device
@@ -219,9 +212,8 @@ public:
set_fixed(false);
}
omv_cart_slot_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
- virtual bool must_be_loaded() const override { return false; }
- virtual const char *image_interface() const override { return "sg1000_cart"; }
- virtual const char *file_extensions() const override { return "bin,sg"; }
+ virtual const char *image_interface() const noexcept override { return "sg1000_cart"; }
+ virtual const char *file_extensions() const noexcept override { return "bin,sg"; }
};
// ======================> sc3000_cart_slot_device
@@ -240,9 +232,8 @@ public:
set_fixed(false);
}
sc3000_cart_slot_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
- virtual bool must_be_loaded() const override { return true; }
- virtual const char *image_interface() const override { return "sg1000_cart"; }
- virtual const char *file_extensions() const override { return "bin,sg,sc"; }
+ virtual const char *image_interface() const noexcept override { return "sg1000_cart"; }
+ virtual const char *file_extensions() const noexcept override { return "bin,sg,sc"; }
};
// ======================> sg1000mk3_cart_slot_device
@@ -261,9 +252,8 @@ public:
set_fixed(false);
}
sg1000mk3_cart_slot_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
- virtual bool must_be_loaded() const override { return false; }
- virtual const char *image_interface() const override { return "sms_cart,sg1000_cart"; }
- virtual const char *file_extensions() const override { return "bin,sms,sg"; }
+ virtual const char *image_interface() const noexcept override { return "sms_cart,sg1000_cart"; }
+ virtual const char *file_extensions() const noexcept override { return "bin,sms,sg"; }
};
// ======================> sms_cart_slot_device
@@ -282,9 +272,8 @@ public:
set_fixed(false);
}
sms_cart_slot_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
- virtual bool must_be_loaded() const override { return false; }
- virtual const char *image_interface() const override { return "sms_cart"; }
- virtual const char *file_extensions() const override { return "bin,sms"; }
+ virtual const char *image_interface() const noexcept override { return "sms_cart"; }
+ virtual const char *file_extensions() const noexcept override { return "bin,sms"; }
};
// ======================> gamegear_cart_slot_device
@@ -303,9 +292,8 @@ public:
set_fixed(false);
}
gamegear_cart_slot_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
- virtual bool must_be_loaded() const override { return true; }
- virtual const char *image_interface() const override { return "gamegear_cart"; }
- virtual const char *file_extensions() const override { return "bin,gg"; }
+ virtual const char *image_interface() const noexcept override { return "gamegear_cart"; }
+ virtual const char *file_extensions() const noexcept override { return "bin,gg"; }
};
@@ -325,9 +313,8 @@ public:
set_fixed(false);
}
sms_card_slot_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
- virtual bool must_be_loaded() const override { return false; }
- virtual const char *image_interface() const override { return "sms_card"; }
- virtual const char *file_extensions() const override { return "bin"; }
+ virtual const char *image_interface() const noexcept override { return "sms_card"; }
+ virtual const char *file_extensions() const noexcept override { return "bin"; }
};
// ======================> sg1000_card_slot_device
@@ -346,8 +333,8 @@ public:
set_fixed(false);
}
sg1000_card_slot_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
- virtual const char *image_interface() const override { return "sg1000_cart"; }
- virtual const char *file_extensions() const override { return "bin,sg"; }
+ virtual const char *image_interface() const noexcept override { return "sg1000_cart"; }
+ virtual const char *file_extensions() const noexcept override { return "bin,sg"; }
};
DECLARE_DEVICE_TYPE(SG1000_CART_SLOT, sg1000_cart_slot_device)
@@ -359,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);
@@ -372,4 +353,4 @@ void sg1000mk3_cart(device_slot_interface &device);
void sms_cart(device_slot_interface &device);
void gg_cart(device_slot_interface &device);
-#endif // MAME_BUS_SEGA8_SLOT_H
+#endif // MAME_BUS_SEGA8_SEGA8_SLOT_H
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..2eef6014261
--- /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_SEGAAI_EXP_H
+#define MAME_BUS_SEGAAI_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 // MAME_BUS_SEGAAI_SEGAAI_EXP_H
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..ce1e1d76c07
--- /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_SEGAAI_SLOT_H
+#define MAME_BUS_SEGAAI_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 ATTR_COLD;
+
+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 // MAME_BUS_SEGAAI_SEGAAI_SLOT_H
diff --git a/src/devices/bus/segaai/soundbox.cpp b/src/devices/bus/segaai/soundbox.cpp
new file mode 100644
index 00000000000..230275da343
--- /dev/null
+++ b/src/devices/bus/segaai/soundbox.cpp
@@ -0,0 +1,319 @@
+// 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 ATTR_COLD;
+ virtual const tiny_rom_entry *device_rom_region() const override ATTR_COLD;
+ virtual ioport_constructor device_input_ports() const override ATTR_COLD;
+ virtual void device_start() override ATTR_COLD;
+
+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, "speaker", 2).front();
+ 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, "speaker", 1.00, 0);
+ m_ym2151->add_route(1, "speaker", 1.00, 1);
+}
+
+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/fm_unit.cpp b/src/devices/bus/sg1000_exp/fm_unit.cpp
index a7bdc4bcc5d..339b41254b2 100644
--- a/src/devices/bus/sg1000_exp/fm_unit.cpp
+++ b/src/devices/bus/sg1000_exp/fm_unit.cpp
@@ -102,7 +102,7 @@ void sega_fm_unit_device::device_reset()
// peripheral_r - fm unit read
//-------------------------------------------------
-READ8_MEMBER(sega_fm_unit_device::peripheral_r)
+uint8_t sega_fm_unit_device::peripheral_r(offs_t offset)
{
// the value previously written to the control port is returned on all
// active read offsets.
@@ -118,7 +118,7 @@ READ8_MEMBER(sega_fm_unit_device::peripheral_r)
// peripheral_w - fm unit write
//-------------------------------------------------
-WRITE8_MEMBER(sega_fm_unit_device::peripheral_w)
+void sega_fm_unit_device::peripheral_w(offs_t offset, uint8_t data)
{
switch (offset)
{
diff --git a/src/devices/bus/sg1000_exp/fm_unit.h b/src/devices/bus/sg1000_exp/fm_unit.h
index cb1ddd072db..8b2ec889bad 100644
--- a/src/devices/bus/sg1000_exp/fm_unit.h
+++ b/src/devices/bus/sg1000_exp/fm_unit.h
@@ -12,8 +12,8 @@
#pragma once
-#include "sound/ym2413.h"
#include "sound/sn76496.h"
+#include "sound/ymopl.h"
#include "sg1000exp.h"
@@ -33,13 +33,13 @@ public:
protected:
// device-level overrides
- virtual void device_start() override;
- virtual void device_reset() override;
- virtual void device_add_mconfig(machine_config &config) override;
+ 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_sg1000_expansion_slot_interface overrides
- virtual DECLARE_READ8_MEMBER(peripheral_r) override;
- virtual DECLARE_WRITE8_MEMBER(peripheral_w) override;
+ virtual uint8_t peripheral_r(offs_t offset) override;
+ virtual void peripheral_w(offs_t offset, uint8_t data) override;
virtual bool is_readable(uint8_t offset) override;
virtual bool is_writeable(uint8_t offset) override;
void set_audio_control(uint8_t data);
diff --git a/src/devices/bus/sg1000_exp/kblink.cpp b/src/devices/bus/sg1000_exp/kblink.cpp
index 039c7f91196..8d98e006f94 100644
--- a/src/devices/bus/sg1000_exp/kblink.cpp
+++ b/src/devices/bus/sg1000_exp/kblink.cpp
@@ -81,9 +81,9 @@ sk1100_link_cable_device::sk1100_link_cable_device(const machine_config &mconfig
void sk1100_link_cable_device::device_start()
{
- m_timer_poll = timer_alloc(TIMER_POLL);
- m_timer_send = timer_alloc(TIMER_SEND);
- m_timer_read = timer_alloc(TIMER_READ);
+ m_timer_poll = timer_alloc(FUNC(sk1100_link_cable_device::update_queue), this);
+ m_timer_send = timer_alloc(FUNC(sk1100_link_cable_device::send_tick), this);
+ m_timer_read = timer_alloc(FUNC(sk1100_link_cable_device::read_tick), this);
/* register for state saving */
save_item(NAME(m_data));
@@ -103,7 +103,7 @@ void sk1100_link_cable_device::device_start()
void sk1100_link_cable_device::device_reset()
{
- queue();
+ update_queue(0);
}
@@ -116,29 +116,7 @@ void sk1100_link_cable_device::device_add_mconfig(machine_config &config)
BITBANGER(config, m_stream, 0);
}
-
-void sk1100_link_cable_device::device_timer(emu_timer &timer, device_timer_id id, int param, void *ptr)
-{
- switch (id)
- {
- case TIMER_POLL:
- queue();
- break;
-
- case TIMER_SEND:
- m_stream->output(u8(param));
- break;
-
- case TIMER_READ:
- m_update_received_data = true;
- break;
-
- default:
- break;
- }
-}
-
-void sk1100_link_cable_device::queue()
+TIMER_CALLBACK_MEMBER(sk1100_link_cable_device::update_queue)
{
if (m_input_index == m_input_count)
{
@@ -151,6 +129,16 @@ void sk1100_link_cable_device::queue()
}
}
+TIMER_CALLBACK_MEMBER(sk1100_link_cable_device::send_tick)
+{
+ m_stream->output(u8(param));
+}
+
+TIMER_CALLBACK_MEMBER(sk1100_link_cable_device::read_tick)
+{
+ m_update_received_data = true;
+}
+
void sk1100_link_cable_device::set_data_read()
{
// Check if a new byte from the input buffer was read for this timeslice.
@@ -162,7 +150,7 @@ void sk1100_link_cable_device::set_data_read()
// there is no way to read what was sent from peer as feed bit.
m_fault = BIT(byte, 0); // sent from peer as data bit
m_busy = BIT(byte, 1); // sent from peer as reset bit
- queue();
+ update_queue(0);
}
// Set to read next byte only after the end of this timeslice.
m_update_received_data = false;
diff --git a/src/devices/bus/sg1000_exp/kblink.h b/src/devices/bus/sg1000_exp/kblink.h
index 65e5782f4a2..f8c84faa214 100644
--- a/src/devices/bus/sg1000_exp/kblink.h
+++ b/src/devices/bus/sg1000_exp/kblink.h
@@ -9,8 +9,8 @@ is supported by the game F-16 Fighting Falcon for its 2 players mode.
**********************************************************************/
-#ifndef MAME_BUS_SG1000_EXP_SK1100_KBLINK_H
-#define MAME_BUS_SG1000_EXP_SK1100_KBLINK_H
+#ifndef MAME_BUS_SG1000_EXP_KBLINK_H
+#define MAME_BUS_SG1000_EXP_KBLINK_H
#pragma once
@@ -35,19 +35,21 @@ public:
protected:
// device-level overrides
- virtual void device_start() override;
- virtual void device_reset() override;
- virtual void device_timer(emu_timer &timer, device_timer_id id, int param, void *ptr) override;
- virtual void device_add_mconfig(machine_config &config) override;
+ 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_sk1100_link_cable_interface overrides
+ 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_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 int output_fault() override { set_data_read(); return m_fault; }
+ virtual int output_busy() override { set_data_read(); return m_busy; }
- 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; }
+ TIMER_CALLBACK_MEMBER(update_queue);
+ TIMER_CALLBACK_MEMBER(send_tick);
+ TIMER_CALLBACK_MEMBER(read_tick);
private:
static constexpr int TIMER_POLL = 1;
@@ -79,4 +81,4 @@ private:
DECLARE_DEVICE_TYPE(SK1100_LINK_CABLE, sk1100_link_cable_device)
-#endif // MAME_BUS_SG1000_EXP_SK1100_KBLINK_H
+#endif // MAME_BUS_SG1000_EXP_KBLINK_H
diff --git a/src/devices/bus/sg1000_exp/sg1000exp.cpp b/src/devices/bus/sg1000_exp/sg1000exp.cpp
index 09e6e826515..0cc164448e8 100644
--- a/src/devices/bus/sg1000_exp/sg1000exp.cpp
+++ b/src/devices/bus/sg1000_exp/sg1000exp.cpp
@@ -31,8 +31,8 @@ DEFINE_DEVICE_TYPE(SG1000_EXPANSION_SLOT, sg1000_expansion_slot_device, "sg1000_
// device_sg1000_expansion_slot_interface - constructor
//-------------------------------------------------
-device_sg1000_expansion_slot_interface::device_sg1000_expansion_slot_interface(const machine_config &mconfig, device_t &device)
- : device_slot_card_interface(mconfig,device)
+device_sg1000_expansion_slot_interface::device_sg1000_expansion_slot_interface(const machine_config &mconfig, device_t &device) :
+ device_interface(device, "sg1000exp")
{
}
@@ -57,7 +57,7 @@ device_sg1000_expansion_slot_interface::~device_sg1000_expansion_slot_interface(
sg1000_expansion_slot_device::sg1000_expansion_slot_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) :
device_t(mconfig, SG1000_EXPANSION_SLOT, tag, owner, clock),
- device_slot_interface(mconfig, *this),
+ device_single_card_slot_interface<device_sg1000_expansion_slot_interface>(mconfig, *this),
m_device(nullptr)
{
}
@@ -78,7 +78,7 @@ sg1000_expansion_slot_device::~sg1000_expansion_slot_device()
void sg1000_expansion_slot_device::device_start()
{
- m_device = dynamic_cast<device_sg1000_expansion_slot_interface *>(get_card_device());
+ m_device = get_card_device();
}
@@ -86,18 +86,18 @@ void sg1000_expansion_slot_device::device_start()
// has only 3 address lines (A0, A1, A2).
-READ8_MEMBER(sg1000_expansion_slot_device::read)
+uint8_t sg1000_expansion_slot_device::read(offs_t offset)
{
uint8_t data = 0xff;
if (m_device)
- data = m_device->peripheral_r(space, offset & 0x07);
+ data = m_device->peripheral_r(offset & 0x07);
return data;
}
-WRITE8_MEMBER(sg1000_expansion_slot_device::write)
+void sg1000_expansion_slot_device::write(offs_t offset, uint8_t data)
{
if (m_device)
- m_device->peripheral_w(space, offset & 0x07, data);
+ m_device->peripheral_w(offset & 0x07, data);
}
@@ -124,5 +124,6 @@ bool sg1000_expansion_slot_device::is_writeable(uint8_t offset)
void sg1000_expansion_devices(device_slot_interface &device)
{
device.option_add("sk1100", SEGA_SK1100);
+ device.option_add("sk1100e", SEGA_SK1100E);
device.option_add("fm", SEGA_FM_UNIT);
}
diff --git a/src/devices/bus/sg1000_exp/sg1000exp.h b/src/devices/bus/sg1000_exp/sg1000exp.h
index c132b48d9dd..53c1c486338 100644
--- a/src/devices/bus/sg1000_exp/sg1000exp.h
+++ b/src/devices/bus/sg1000_exp/sg1000exp.h
@@ -23,7 +23,7 @@
class device_sg1000_expansion_slot_interface;
-class sg1000_expansion_slot_device : public device_t, public device_slot_interface
+class sg1000_expansion_slot_device : public device_t, public device_single_card_slot_interface<device_sg1000_expansion_slot_interface>
{
public:
// construction/destruction
@@ -40,14 +40,14 @@ public:
sg1000_expansion_slot_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock = 0);
virtual ~sg1000_expansion_slot_device();
- DECLARE_READ8_MEMBER(read);
- DECLARE_WRITE8_MEMBER(write);
+ uint8_t read(offs_t offset);
+ void write(offs_t offset, uint8_t data);
bool is_readable(uint8_t offset);
bool is_writeable(uint8_t offset);
protected:
// device-level overrides
- virtual void device_start() override;
+ virtual void device_start() override ATTR_COLD;
private:
device_sg1000_expansion_slot_interface *m_device;
@@ -57,14 +57,14 @@ private:
// ======================> device_sg1000_expansion_slot_interface
// class representing interface-specific live sg1000_expansion card
-class device_sg1000_expansion_slot_interface : public device_slot_card_interface
+class device_sg1000_expansion_slot_interface : public device_interface
{
public:
// construction/destruction
virtual ~device_sg1000_expansion_slot_interface();
- virtual DECLARE_READ8_MEMBER(peripheral_r) { return 0xff; }
- virtual DECLARE_WRITE8_MEMBER(peripheral_w) { }
+ virtual uint8_t peripheral_r(offs_t offset) { return 0xff; }
+ virtual void peripheral_w(offs_t offset, uint8_t data) { }
virtual bool is_readable(uint8_t offset) { return true; }
virtual bool is_writeable(uint8_t offset) { return true; }
diff --git a/src/devices/bus/sg1000_exp/sk1100.cpp b/src/devices/bus/sg1000_exp/sk1100.cpp
index 1bb0a01adfd..f0ad0388562 100644
--- a/src/devices/bus/sg1000_exp/sk1100.cpp
+++ b/src/devices/bus/sg1000_exp/sk1100.cpp
@@ -9,16 +9,23 @@ Release data from the Sega Retro project:
Year: 1984 Country/region: JP Model code: SK-1100
+Though no export version of the SK-1100 itself was actually released,
+the export SC-3000 keyboard is identical aside from key labels (mostly
+letters with diacritics replacing katakana), and functional differences
+are all handled by software.
+
TODO:
-- SP-400 serial printer
+- SP-400 serial printer (custom 7-pin TTL-level connector)
**********************************************************************/
#include "emu.h"
#include "sk1100.h"
-#include "softlist.h"
+#include "softlist_dev.h"
+
+#include "formats/sc3000_bit.h"
@@ -27,6 +34,7 @@ TODO:
//**************************************************************************
DEFINE_DEVICE_TYPE(SEGA_SK1100, sega_sk1100_device, "sega_sk1100", "Sega SK-1100 Keyboard")
+DEFINE_DEVICE_TYPE(SEGA_SK1100E, sega_sk1100e_device, "sega_sk1100e", "Sega SK-1100 Keyboard (with diareses)")
/*-------------------------------------------------
@@ -35,108 +43,217 @@ DEFINE_DEVICE_TYPE(SEGA_SK1100, sega_sk1100_device, "sega_sk1100", "Sega SK-1100
static INPUT_PORTS_START( sk1100_keys )
PORT_START("PA0")
- PORT_BIT( 0x01, IP_ACTIVE_LOW, IPT_KEYBOARD ) PORT_CODE(KEYCODE_1) PORT_CHAR('1') PORT_CHAR('!')
- PORT_BIT( 0x02, IP_ACTIVE_LOW, IPT_KEYBOARD ) PORT_CODE(KEYCODE_Q) PORT_CHAR('Q') PORT_CHAR('q')
- PORT_BIT( 0x04, IP_ACTIVE_LOW, IPT_KEYBOARD ) PORT_CODE(KEYCODE_A) PORT_CHAR('A') PORT_CHAR('a')
- PORT_BIT( 0x08, IP_ACTIVE_LOW, IPT_KEYBOARD ) PORT_CODE(KEYCODE_Z) PORT_CHAR('Z') PORT_CHAR('z')
- PORT_BIT( 0x10, IP_ACTIVE_LOW, IPT_KEYBOARD ) PORT_NAME("ENG DIER'S") PORT_CODE(KEYCODE_RALT) PORT_CHAR(UCHAR_MAMEKEY(RALT))
- PORT_BIT( 0x20, IP_ACTIVE_LOW, IPT_KEYBOARD ) PORT_CODE(KEYCODE_COMMA) PORT_CHAR(',') PORT_CHAR('<')
- PORT_BIT( 0x40, IP_ACTIVE_LOW, IPT_KEYBOARD ) PORT_CODE(KEYCODE_K) PORT_CHAR('K') PORT_CHAR('k')
- PORT_BIT( 0x80, IP_ACTIVE_LOW, IPT_KEYBOARD ) PORT_CODE(KEYCODE_I) PORT_CHAR('I') PORT_CHAR('i')
+ PORT_BIT( 0x01, IP_ACTIVE_LOW, IPT_KEYBOARD ) PORT_NAME(u8"1 \u30CC ! GOTO") PORT_CODE(KEYCODE_1) PORT_CHAR('1', 0x30cc) PORT_CHAR('!') // ヌ
+ PORT_BIT( 0x02, IP_ACTIVE_LOW, IPT_KEYBOARD ) PORT_NAME(u8"Q \u30BF REM") PORT_CODE(KEYCODE_Q) PORT_CHAR('Q', 0x30bf) PORT_CHAR('q') // タ
+ PORT_BIT( 0x04, IP_ACTIVE_LOW, IPT_KEYBOARD ) PORT_NAME(u8"A \u30C1 CHR$(") PORT_CODE(KEYCODE_A) PORT_CHAR('A', 0x30c1) PORT_CHAR('a') // チ
+ PORT_BIT( 0x08, IP_ACTIVE_LOW, IPT_KEYBOARD ) PORT_NAME(u8"Z \u30C4 ASC(") PORT_CODE(KEYCODE_Z) PORT_CHAR('Z', 0x30c4) PORT_CHAR('z', 0x30c3) // ツ ッ
+ PORT_BIT( 0x10, IP_ACTIVE_LOW, IPT_KEYBOARD ) PORT_NAME(u8"\u82F1\u6570/\u30AB\u30CA (Alphanumerics/Kana)") PORT_CODE(KEYCODE_RALT) PORT_CHAR(UCHAR_MAMEKEY(RALT)) // 英数/カナ
+ PORT_BIT( 0x20, IP_ACTIVE_LOW, IPT_KEYBOARD ) PORT_NAME(u8", \u30CD < \u3001 SGN(") PORT_CODE(KEYCODE_COMMA) PORT_CHAR(',', 0x30cd) PORT_CHAR('<', 0x3001) // ネ 、
+ PORT_BIT( 0x40, IP_ACTIVE_LOW, IPT_KEYBOARD ) PORT_NAME(u8"K \u30CE COS(") PORT_CODE(KEYCODE_K) PORT_CHAR('K', 0x30ce) PORT_CHAR('k') // ノ
+ PORT_BIT( 0x80, IP_ACTIVE_LOW, IPT_KEYBOARD ) PORT_NAME(u8"I \u30CB TO") PORT_CODE(KEYCODE_I) PORT_CHAR('I', 0x30cb) PORT_CHAR('i') // ニ
PORT_START("PA1")
- PORT_BIT( 0x01, IP_ACTIVE_LOW, IPT_KEYBOARD ) PORT_CODE(KEYCODE_2) PORT_CHAR('2') PORT_CHAR('"')
- PORT_BIT( 0x02, IP_ACTIVE_LOW, IPT_KEYBOARD ) PORT_CODE(KEYCODE_W) PORT_CHAR('W') PORT_CHAR('w')
- PORT_BIT( 0x04, IP_ACTIVE_LOW, IPT_KEYBOARD ) PORT_CODE(KEYCODE_S) PORT_CHAR('S') PORT_CHAR('s')
- PORT_BIT( 0x08, IP_ACTIVE_LOW, IPT_KEYBOARD ) PORT_CODE(KEYCODE_X) PORT_CHAR('X') PORT_CHAR('x')
+ PORT_BIT( 0x01, IP_ACTIVE_LOW, IPT_KEYBOARD ) PORT_NAME(u8"2 \u30D5 \" GOSUB") PORT_CODE(KEYCODE_2) PORT_CHAR('2', 0x30d5) PORT_CHAR('"') // フ
+ PORT_BIT( 0x02, IP_ACTIVE_LOW, IPT_KEYBOARD ) PORT_NAME(u8"W \u30C6 DATA") PORT_CODE(KEYCODE_W) PORT_CHAR('W', 0x30c6) PORT_CHAR('w') // テ
+ PORT_BIT( 0x04, IP_ACTIVE_LOW, IPT_KEYBOARD ) PORT_NAME(u8"S \u30C8 STR$(") PORT_CODE(KEYCODE_S) PORT_CHAR('S', 0x30c8) PORT_CHAR('s') // ト
+ PORT_BIT( 0x08, IP_ACTIVE_LOW, IPT_KEYBOARD ) PORT_NAME(u8"X \u30B5 VAL(") PORT_CODE(KEYCODE_X) PORT_CHAR('X', 0x30b5) PORT_CHAR('x') // サ
PORT_BIT( 0x10, IP_ACTIVE_LOW, IPT_KEYBOARD ) PORT_NAME("SPC") PORT_CODE(KEYCODE_SPACE) PORT_CHAR(' ')
- PORT_BIT( 0x20, IP_ACTIVE_LOW, IPT_KEYBOARD ) PORT_CODE(KEYCODE_STOP) PORT_CHAR('.') PORT_CHAR('>')
- PORT_BIT( 0x40, IP_ACTIVE_LOW, IPT_KEYBOARD ) PORT_CODE(KEYCODE_L) PORT_CHAR('L') PORT_CHAR('l')
- PORT_BIT( 0x80, IP_ACTIVE_LOW, IPT_KEYBOARD ) PORT_CODE(KEYCODE_O) PORT_CHAR('O') PORT_CHAR('o')
+ PORT_BIT( 0x20, IP_ACTIVE_LOW, IPT_KEYBOARD ) PORT_NAME(u8". \u30EB > \u3002 RND(") PORT_CODE(KEYCODE_STOP) PORT_CHAR('.', 0x30eb) PORT_CHAR('>', 0x3002) // ル 。
+ PORT_BIT( 0x40, IP_ACTIVE_LOW, IPT_KEYBOARD ) PORT_NAME(u8"L \u30EA TAN(") PORT_CODE(KEYCODE_L) PORT_CHAR('L', 0x30ea) PORT_CHAR('l') // リ
+ PORT_BIT( 0x80, IP_ACTIVE_LOW, IPT_KEYBOARD ) PORT_NAME(u8"O \u30E9 STEP") PORT_CODE(KEYCODE_O) PORT_CHAR('O', 0x30e9) PORT_CHAR('o') // ラ
PORT_START("PA2")
- PORT_BIT( 0x01, IP_ACTIVE_LOW, IPT_KEYBOARD ) PORT_CODE(KEYCODE_3) PORT_CHAR('3') PORT_CHAR('#')
- 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')
- PORT_BIT( 0x10, IP_ACTIVE_LOW, IPT_KEYBOARD ) PORT_NAME("HOME CLR") PORT_CODE(KEYCODE_HOME) PORT_CHAR(UCHAR_MAMEKEY(HOME))
- PORT_BIT( 0x20, IP_ACTIVE_LOW, IPT_KEYBOARD ) PORT_CODE(KEYCODE_SLASH) PORT_CHAR('/') PORT_CHAR('?')
- PORT_BIT( 0x40, IP_ACTIVE_LOW, IPT_KEYBOARD ) PORT_CODE(KEYCODE_COLON) PORT_CHAR(';') PORT_CHAR('+')
- PORT_BIT( 0x80, IP_ACTIVE_LOW, IPT_KEYBOARD ) PORT_CODE(KEYCODE_P) PORT_CHAR('P') PORT_CHAR('p')
+ PORT_BIT( 0x01, IP_ACTIVE_LOW, IPT_KEYBOARD ) PORT_NAME(u8"3 \u30A2 # RETURN") PORT_CODE(KEYCODE_3) PORT_CHAR('3', 0x30a2) PORT_CHAR('#', 0x30a1) // ア ァ
+ PORT_BIT( 0x02, IP_ACTIVE_LOW, IPT_KEYBOARD ) PORT_NAME(u8"E \u30A4 READ") PORT_CODE(KEYCODE_E) PORT_CHAR('E', 0x30a4) PORT_CHAR('e', 0x30a3) // イ ィ
+ PORT_BIT( 0x04, IP_ACTIVE_LOW, IPT_KEYBOARD ) PORT_NAME(u8"D \u30B7 TIME$") PORT_CODE(KEYCODE_D) PORT_CHAR('D', 0x30b7) PORT_CHAR('d') // シ
+ PORT_BIT( 0x08, IP_ACTIVE_LOW, IPT_KEYBOARD ) PORT_NAME(u8"C \u30BD SQR(") PORT_CODE(KEYCODE_C) PORT_CHAR('C', 0x30bd) PORT_CHAR('c') // ソ
+ PORT_BIT( 0x10, IP_ACTIVE_LOW, IPT_KEYBOARD ) PORT_NAME("Clr Home CLS") PORT_CODE(KEYCODE_INSERT) PORT_CHAR(UCHAR_MAMEKEY(HOME))
+ PORT_BIT( 0x20, IP_ACTIVE_LOW, IPT_KEYBOARD ) PORT_NAME(u8"/ \u30E1 ? FRE") PORT_CODE(KEYCODE_SLASH) PORT_CHAR('/', 0x30e1) PORT_CHAR('?') // メ
+ PORT_BIT( 0x40, IP_ACTIVE_LOW, IPT_KEYBOARD ) PORT_NAME(u8"; \u30EC + RAD(") PORT_CODE(KEYCODE_COLON) PORT_CHAR(';', 0x30ec) PORT_CHAR('+') // レ
+ PORT_BIT( 0x80, IP_ACTIVE_LOW, IPT_KEYBOARD ) PORT_NAME(u8"P \u30BB NEXT") PORT_CODE(KEYCODE_P) PORT_CHAR('P', 0x30bb) PORT_CHAR('p') // セ
PORT_START("PA3")
- PORT_BIT( 0x01, IP_ACTIVE_LOW, IPT_KEYBOARD ) PORT_CODE(KEYCODE_4) PORT_CHAR('4') PORT_CHAR('$')
- PORT_BIT( 0x02, IP_ACTIVE_LOW, IPT_KEYBOARD ) PORT_CODE(KEYCODE_R) PORT_CHAR('R') PORT_CHAR('r')
- 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( 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('`')
+ PORT_BIT( 0x01, IP_ACTIVE_LOW, IPT_KEYBOARD ) PORT_NAME(u8"4 \u30A6 $ SCREEN") PORT_CODE(KEYCODE_4) PORT_CHAR('4', 0x30a6) PORT_CHAR('$', 0x30a5) // ウ ゥ
+ PORT_BIT( 0x02, IP_ACTIVE_LOW, IPT_KEYBOARD ) PORT_NAME(u8"R \u30B9 RESTORE") PORT_CODE(KEYCODE_R) PORT_CHAR('R', 0x30b9) PORT_CHAR('r') // ス
+ PORT_BIT( 0x04, IP_ACTIVE_LOW, IPT_KEYBOARD ) PORT_NAME(u8"F \u30CF LEFT$(") PORT_CODE(KEYCODE_F) PORT_CHAR('F', 0x30cf) PORT_CHAR('f') // ハ
+ PORT_BIT( 0x08, IP_ACTIVE_LOW, IPT_KEYBOARD ) PORT_NAME(u8"V \u30D2 EXP(") PORT_CODE(KEYCODE_V) PORT_CHAR('V', 0x30d2) PORT_CHAR('v') // ヒ
+ PORT_BIT( 0x10, IP_ACTIVE_LOW, IPT_KEYBOARD ) PORT_NAME("Del Ins DELETE") PORT_CODE(KEYCODE_DEL) PORT_CHAR(8) PORT_CHAR(UCHAR_MAMEKEY(INSERT))
+ PORT_BIT( 0x20, IP_ACTIVE_LOW, IPT_KEYBOARD ) PORT_NAME(u8"\u30ED π PI") PORT_CODE(KEYCODE_BACKSLASH2) PORT_CHAR(0x30ed) PORT_CHAR(U'π') // ロ
+ PORT_BIT( 0x40, IP_ACTIVE_LOW, IPT_KEYBOARD ) PORT_NAME(u8": \u30B1 * PRINT") PORT_CODE(KEYCODE_QUOTE) PORT_CHAR(':', 0x30b1) PORT_CHAR('*') // ケ
+ PORT_BIT( 0x80, IP_ACTIVE_LOW, IPT_KEYBOARD ) PORT_NAME(u8"@ \u309B ` IF") PORT_CODE(KEYCODE_OPENBRACE) PORT_CHAR('@', 0x309b) PORT_CHAR('`') // ゛
PORT_START("PA4")
- PORT_BIT( 0x01, IP_ACTIVE_LOW, IPT_KEYBOARD ) PORT_CODE(KEYCODE_5) PORT_CHAR('5') PORT_CHAR('%')
- PORT_BIT( 0x02, IP_ACTIVE_LOW, IPT_KEYBOARD ) PORT_CODE(KEYCODE_T) PORT_CHAR('T') PORT_CHAR('t')
- 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( 0x01, IP_ACTIVE_LOW, IPT_KEYBOARD ) PORT_NAME(u8"5 \u30A8 % POSITION") PORT_CODE(KEYCODE_5) PORT_CHAR('5', 0x30a8) PORT_CHAR('%', 0x30a7) // エ ェ
+ PORT_BIT( 0x02, IP_ACTIVE_LOW, IPT_KEYBOARD ) PORT_NAME(u8"T \u30AB INPUT") PORT_CODE(KEYCODE_T) PORT_CHAR('T', 0x30ab) PORT_CHAR('t') // カ
+ PORT_BIT( 0x04, IP_ACTIVE_LOW, IPT_KEYBOARD ) PORT_NAME(u8"G \u30AD RIGHT$(") PORT_CODE(KEYCODE_G) PORT_CHAR('G', 0x30ad) PORT_CHAR('g') // キ
+ PORT_BIT( 0x08, IP_ACTIVE_LOW, IPT_KEYBOARD ) PORT_NAME(u8"B \u30B3 LOG(") PORT_CODE(KEYCODE_B) PORT_CHAR('B', 0x30b3) 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( 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('{')
+ 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_NAME(u8"] \u30E0 } \u300d LIST") PORT_CODE(KEYCODE_BACKSLASH) PORT_CHAR(']', 0x30e0) PORT_CHAR('}', 0x300d) // ム 」
+ PORT_BIT( 0x80, IP_ACTIVE_LOW, IPT_KEYBOARD ) PORT_NAME(u8"[ \u309C { \u300c THEN") PORT_CODE(KEYCODE_CLOSEBRACE) PORT_CHAR('[', 0x309c) PORT_CHAR('{', 0x300c) // ゜ 「
PORT_START("PA5")
- PORT_BIT( 0x01, IP_ACTIVE_LOW, IPT_KEYBOARD ) PORT_CODE(KEYCODE_6) PORT_CHAR('6') PORT_CHAR('&')
- PORT_BIT( 0x02, IP_ACTIVE_LOW, IPT_KEYBOARD ) PORT_CODE(KEYCODE_Y) PORT_CHAR('Y') PORT_CHAR('y')
- 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( 0x01, IP_ACTIVE_LOW, IPT_KEYBOARD ) PORT_NAME(u8"6 \u30AA & COLOR") PORT_CODE(KEYCODE_6) PORT_CHAR('6', 0x30aa) PORT_CHAR('&', 0x30a9) // オ ォ
+ PORT_BIT( 0x02, IP_ACTIVE_LOW, IPT_KEYBOARD ) PORT_NAME(u8"Y \u30F3 DIM") PORT_CODE(KEYCODE_Y) PORT_CHAR('Y', 0x30f3) PORT_CHAR('y') // ン
+ PORT_BIT( 0x04, IP_ACTIVE_LOW, IPT_KEYBOARD ) PORT_NAME(u8"H \u30AF MID$(") PORT_CODE(KEYCODE_H) PORT_CHAR('H', 0x30af) PORT_CHAR('h') // ク
+ PORT_BIT( 0x08, IP_ACTIVE_LOW, IPT_KEYBOARD ) PORT_NAME(u8"N \u30DF ABS(") PORT_CODE(KEYCODE_N) PORT_CHAR('N', 0x30df) 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 )
PORT_START("PA6")
- 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_U) PORT_CHAR('U') PORT_CHAR('u')
- 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( 0x01, IP_ACTIVE_LOW, IPT_KEYBOARD ) PORT_NAME(u8"7 \u30E4 ' LINE") PORT_CODE(KEYCODE_7) PORT_CHAR('7', 0x30e4) PORT_CHAR('\'', 0x30e3) // ヤ ャ
+ PORT_BIT( 0x02, IP_ACTIVE_LOW, IPT_KEYBOARD ) PORT_NAME(u8"U \u30CA FOR") PORT_CODE(KEYCODE_U) PORT_CHAR('U', 0x30ca) PORT_CHAR('u') // ナ
+ PORT_BIT( 0x04, IP_ACTIVE_LOW, IPT_KEYBOARD ) PORT_NAME(u8"J \u30DE SIN(") PORT_CODE(KEYCODE_J) PORT_CHAR('J', 0x30de) PORT_CHAR('j') // マ
+ PORT_BIT( 0x08, IP_ACTIVE_LOW, IPT_KEYBOARD ) PORT_NAME(u8"M \u30E2 INT(") PORT_CODE(KEYCODE_M) PORT_CHAR('M', 0x30e2) 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")
PORT_BIT( 0xff, IP_ACTIVE_LOW, IPT_UNUSED ) // keyboard disabled
PORT_START("PB0")
- PORT_BIT( 0x01, IP_ACTIVE_LOW, IPT_KEYBOARD ) PORT_CODE(KEYCODE_8) PORT_CHAR('8') PORT_CHAR('(')
+ PORT_BIT( 0x01, IP_ACTIVE_LOW, IPT_KEYBOARD ) PORT_NAME(u8"8 \u30E6 ( PSET") PORT_CODE(KEYCODE_8) PORT_CHAR('8', 0x30e6) PORT_CHAR('(', 0x30e5) // ユ ュ
PORT_BIT( 0x0e, IP_ACTIVE_LOW, IPT_UNUSED )
PORT_START("PB1")
- PORT_BIT( 0x01, IP_ACTIVE_LOW, IPT_KEYBOARD ) PORT_CODE(KEYCODE_9) PORT_CHAR('9') PORT_CHAR(')')
+ PORT_BIT( 0x01, IP_ACTIVE_LOW, IPT_KEYBOARD ) PORT_NAME(u8"9 \u30E8 ) SAVE\"") PORT_CODE(KEYCODE_9) PORT_CHAR('9', 0x30e8) PORT_CHAR(')', 0x30e7) // ヨ ョ
PORT_BIT( 0x0e, IP_ACTIVE_LOW, IPT_UNUSED )
PORT_START("PB2")
- PORT_BIT( 0x01, IP_ACTIVE_LOW, IPT_KEYBOARD ) PORT_CODE(KEYCODE_0) PORT_CHAR('0')
+ PORT_BIT( 0x01, IP_ACTIVE_LOW, IPT_KEYBOARD ) PORT_NAME(u8"0 \u30EF LOAD\"") PORT_CODE(KEYCODE_0) PORT_CHAR('0', 0x30ef) // ワ
PORT_BIT( 0x0e, IP_ACTIVE_LOW, IPT_UNUSED )
PORT_START("PB3")
- PORT_BIT( 0x01, IP_ACTIVE_LOW, IPT_KEYBOARD ) PORT_CODE(KEYCODE_MINUS) PORT_CHAR('-') PORT_CHAR('=')
+ PORT_BIT( 0x01, IP_ACTIVE_LOW, IPT_KEYBOARD ) PORT_NAME(u8"- \u30DB = VERIFY\"") PORT_CODE(KEYCODE_MINUS) PORT_CHAR('-', 0x30db) PORT_CHAR('=') // ホ
PORT_BIT( 0x0e, IP_ACTIVE_LOW, IPT_UNUSED )
PORT_START("PB4")
- PORT_BIT( 0x01, IP_ACTIVE_LOW, IPT_KEYBOARD ) PORT_CODE(KEYCODE_BACKSLASH2) PORT_CHAR('^')
+ PORT_BIT( 0x01, IP_ACTIVE_LOW, IPT_KEYBOARD ) PORT_NAME(u8"^ \u30D8 ~ AUTO") PORT_CODE(KEYCODE_EQUALS) PORT_CHAR('^', 0x30d8) PORT_CHAR('~') // ヘ
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_NAME(u8"¥ \u30FC | RUN") PORT_CODE(KEYCODE_BACKSPACE) PORT_CHAR(U'¥', 0x30fc) PORT_CHAR('|') // ー
PORT_BIT( 0x06, IP_ACTIVE_LOW, IPT_UNUSED )
- PORT_BIT( 0x08, IP_ACTIVE_LOW, IPT_KEYBOARD ) PORT_NAME("FUNC") PORT_CODE(KEYCODE_TAB)
+ PORT_BIT( 0x08, IP_ACTIVE_LOW, IPT_KEYBOARD ) PORT_NAME("Func") PORT_CODE(KEYCODE_TAB)
PORT_START("PB6")
- PORT_BIT( 0x01, IP_ACTIVE_LOW, IPT_KEYBOARD ) PORT_NAME("BREAK") PORT_CODE(KEYCODE_ESC) PORT_CHAR(UCHAR_MAMEKEY(ESC))
- PORT_BIT( 0x02, IP_ACTIVE_LOW, IPT_KEYBOARD ) PORT_NAME("GRAPH") PORT_CODE(KEYCODE_LALT) PORT_CHAR(UCHAR_MAMEKEY(LALT))
- PORT_BIT( 0x04, IP_ACTIVE_LOW, IPT_KEYBOARD ) PORT_NAME("CTRL") PORT_CODE(KEYCODE_LCONTROL) PORT_CHAR(UCHAR_MAMEKEY(LCONTROL))
- PORT_BIT( 0x08, IP_ACTIVE_LOW, IPT_KEYBOARD ) PORT_NAME("SHIFT") PORT_CODE(KEYCODE_LSHIFT) PORT_CODE(KEYCODE_RSHIFT) PORT_CHAR(UCHAR_SHIFT_1)
+ PORT_BIT( 0x01, IP_ACTIVE_LOW, IPT_KEYBOARD ) PORT_NAME("Break") PORT_CODE(KEYCODE_ESC) PORT_CHAR(UCHAR_MAMEKEY(ESC))
+ PORT_BIT( 0x02, IP_ACTIVE_LOW, IPT_KEYBOARD ) PORT_NAME("Graph") PORT_CODE(KEYCODE_LALT) PORT_CHAR(UCHAR_MAMEKEY(LALT))
+ PORT_BIT( 0x04, IP_ACTIVE_LOW, IPT_KEYBOARD ) PORT_NAME("Ctrl") PORT_CODE(KEYCODE_LCONTROL) PORT_CHAR(UCHAR_MAMEKEY(LCONTROL))
+ PORT_BIT( 0x08, IP_ACTIVE_LOW, IPT_KEYBOARD ) PORT_NAME("Shift") PORT_CODE(KEYCODE_LSHIFT) PORT_CODE(KEYCODE_RSHIFT) PORT_CHAR(UCHAR_SHIFT_1)
+
+ PORT_START("PB7")
+ PORT_BIT( 0x0f, IP_ACTIVE_LOW, IPT_UNUSED ) // keyboard disabled
+INPUT_PORTS_END
+
+static INPUT_PORTS_START( sk1100e_keys )
+ PORT_START("PA0")
+ PORT_BIT( 0x01, IP_ACTIVE_LOW, IPT_KEYBOARD ) PORT_NAME(u8"1 ! Â GOTO") PORT_CODE(KEYCODE_1) PORT_CHAR('1') PORT_CHAR('!') PORT_CHAR(U'Â')
+ PORT_BIT( 0x02, IP_ACTIVE_LOW, IPT_KEYBOARD ) PORT_NAME(u8"Q Á REM") PORT_CODE(KEYCODE_Q) PORT_CHAR('Q') PORT_CHAR('q') PORT_CHAR(U'Á')
+ PORT_BIT( 0x04, IP_ACTIVE_LOW, IPT_KEYBOARD ) PORT_NAME(u8"A Ä CHR$(") PORT_CODE(KEYCODE_A) PORT_CHAR('A') PORT_CHAR('a') PORT_CHAR(U'Ä')
+ PORT_BIT( 0x08, IP_ACTIVE_LOW, IPT_KEYBOARD ) PORT_NAME(u8"Z μ ASC(") PORT_CODE(KEYCODE_Z) PORT_CHAR('Z') PORT_CHAR('z') PORT_CHAR(U'μ')
+ PORT_BIT( 0x10, IP_ACTIVE_LOW, IPT_KEYBOARD ) PORT_NAME("Eng Dier's") PORT_CODE(KEYCODE_RALT) PORT_CHAR(UCHAR_SHIFT_2)
+ PORT_BIT( 0x20, IP_ACTIVE_LOW, IPT_KEYBOARD ) PORT_NAME(u8", < Ū SGN(") PORT_CODE(KEYCODE_COMMA) PORT_CHAR(',') PORT_CHAR('<') PORT_CHAR(U'Ū')
+ PORT_BIT( 0x40, IP_ACTIVE_LOW, IPT_KEYBOARD ) PORT_NAME(u8"K Ü COS(") PORT_CODE(KEYCODE_K) PORT_CHAR('K') PORT_CHAR('k') PORT_CHAR(U'Ü')
+ PORT_BIT( 0x80, IP_ACTIVE_LOW, IPT_KEYBOARD ) PORT_NAME(u8"I Ù TO") PORT_CODE(KEYCODE_I) PORT_CHAR('I') PORT_CHAR('i') PORT_CHAR(U'Ù')
+
+ PORT_START("PA1")
+ PORT_BIT( 0x01, IP_ACTIVE_LOW, IPT_KEYBOARD ) PORT_NAME(u8"2 \" Ǎ GOSUB") PORT_CODE(KEYCODE_2) PORT_CHAR('2') PORT_CHAR('"') PORT_CHAR(U'Ă')
+ PORT_BIT( 0x02, IP_ACTIVE_LOW, IPT_KEYBOARD ) PORT_NAME(u8"W À DATA") PORT_CODE(KEYCODE_W) PORT_CHAR('W') PORT_CHAR('w') PORT_CHAR(U'À')
+ PORT_BIT( 0x04, IP_ACTIVE_LOW, IPT_KEYBOARD ) PORT_NAME(u8"S Å STR$(") PORT_CODE(KEYCODE_S) PORT_CHAR('S') PORT_CHAR('s') PORT_CHAR(U'Å')
+ PORT_BIT( 0x08, IP_ACTIVE_LOW, IPT_KEYBOARD ) PORT_NAME(u8"X Λ VAL(") PORT_CODE(KEYCODE_X) PORT_CHAR('X') PORT_CHAR('x') PORT_CHAR(U'Λ')
+ PORT_BIT( 0x10, IP_ACTIVE_LOW, IPT_KEYBOARD ) PORT_NAME("SPC") PORT_CODE(KEYCODE_SPACE) PORT_CHAR(' ')
+ PORT_BIT( 0x20, IP_ACTIVE_LOW, IPT_KEYBOARD ) PORT_NAME(u8". > Î RND(") PORT_CODE(KEYCODE_STOP) PORT_CHAR('.') PORT_CHAR('>') PORT_CHAR(U'Î')
+ PORT_BIT( 0x40, IP_ACTIVE_LOW, IPT_KEYBOARD ) PORT_NAME(u8"L Í TAN(") PORT_CODE(KEYCODE_L) PORT_CHAR('L') PORT_CHAR('l') PORT_CHAR(U'Í')
+ PORT_BIT( 0x80, IP_ACTIVE_LOW, IPT_KEYBOARD ) PORT_NAME(u8"O Ì STEP") PORT_CODE(KEYCODE_O) PORT_CHAR('O') PORT_CHAR('o') PORT_CHAR(U'Ì')
+
+ PORT_START("PA2")
+ PORT_BIT( 0x01, IP_ACTIVE_LOW, IPT_KEYBOARD ) PORT_NAME(u8"3 # Ê RETURN") PORT_CODE(KEYCODE_3) PORT_CHAR('3') PORT_CHAR('#') PORT_CHAR(U'Ê')
+ PORT_BIT( 0x02, IP_ACTIVE_LOW, IPT_KEYBOARD ) PORT_NAME(u8"E É READ") PORT_CODE(KEYCODE_E) PORT_CHAR('E') PORT_CHAR('e') PORT_CHAR(U'É')
+ PORT_BIT( 0x04, IP_ACTIVE_LOW, IPT_KEYBOARD ) PORT_NAME(u8"D Ã TIME$") PORT_CODE(KEYCODE_D) PORT_CHAR('D') PORT_CHAR('d') PORT_CHAR(U'Ã')
+ PORT_BIT( 0x08, IP_ACTIVE_LOW, IPT_KEYBOARD ) PORT_NAME(u8"C Ç SQR(") PORT_CODE(KEYCODE_C) PORT_CHAR('C') PORT_CHAR('c') PORT_CHAR(U'Ç')
+ PORT_BIT( 0x10, IP_ACTIVE_LOW, IPT_KEYBOARD ) PORT_NAME("Clr Home CLS") PORT_CODE(KEYCODE_INSERT) PORT_CHAR(UCHAR_MAMEKEY(HOME))
+ PORT_BIT( 0x20, IP_ACTIVE_LOW, IPT_KEYBOARD ) PORT_NAME(u8"/ ? Ī FRE") PORT_CODE(KEYCODE_SLASH) PORT_CHAR('/') PORT_CHAR('?') PORT_CHAR(U'Ī')
+ PORT_BIT( 0x40, IP_ACTIVE_LOW, IPT_KEYBOARD ) PORT_NAME(u8"; + Ï RAD(") PORT_CODE(KEYCODE_COLON) PORT_CHAR(';') PORT_CHAR('+') PORT_CHAR(U'Ï')
+ PORT_BIT( 0x80, IP_ACTIVE_LOW, IPT_KEYBOARD ) PORT_NAME(u8"P Ó NEXT") PORT_CODE(KEYCODE_P) PORT_CHAR('P') PORT_CHAR('p') PORT_CHAR(U'Ó')
+
+ PORT_START("PA3")
+ PORT_BIT( 0x01, IP_ACTIVE_LOW, IPT_KEYBOARD ) PORT_NAME(u8"4 $ Ě SCREEN") PORT_CODE(KEYCODE_4) PORT_CHAR('4') PORT_CHAR('$') PORT_CHAR(U'Ě')
+ PORT_BIT( 0x02, IP_ACTIVE_LOW, IPT_KEYBOARD ) PORT_NAME(u8"R È RESTORE") PORT_CODE(KEYCODE_R) PORT_CHAR('R') PORT_CHAR('r') PORT_CHAR(U'È')
+ PORT_BIT( 0x04, IP_ACTIVE_LOW, IPT_KEYBOARD ) PORT_NAME(u8"F Ā LEFT$(") PORT_CODE(KEYCODE_F) PORT_CHAR('F') PORT_CHAR('f') PORT_CHAR(U'Ā')
+ PORT_BIT( 0x08, IP_ACTIVE_LOW, IPT_KEYBOARD ) PORT_NAME(u8"V ¿ EXP(") PORT_CODE(KEYCODE_V) PORT_CHAR('V') PORT_CHAR('v') PORT_CHAR(U'¿')
+ PORT_BIT( 0x10, IP_ACTIVE_LOW, IPT_KEYBOARD ) PORT_NAME("Del Ins DELETE") PORT_CODE(KEYCODE_DEL) PORT_CHAR(8) PORT_CHAR(UCHAR_MAMEKEY(INSERT))
+ PORT_BIT( 0x20, IP_ACTIVE_LOW, IPT_KEYBOARD ) PORT_NAME(u8"Õ π PI") PORT_CODE(KEYCODE_BACKSLASH2) PORT_CHAR(U'Õ') PORT_CHAR(U'π')
+ PORT_BIT( 0x40, IP_ACTIVE_LOW, IPT_KEYBOARD ) PORT_NAME(u8": * Ö PRINT") PORT_CODE(KEYCODE_QUOTE) PORT_CHAR(':') PORT_CHAR('*') PORT_CHAR(U'Ö')
+ PORT_BIT( 0x80, IP_ACTIVE_LOW, IPT_KEYBOARD ) PORT_NAME(u8"@ ` Ò IF") PORT_CODE(KEYCODE_OPENBRACE) PORT_CHAR('@') PORT_CHAR('`') PORT_CHAR(U'Ò')
+
+ PORT_START("PA4")
+ PORT_BIT( 0x01, IP_ACTIVE_LOW, IPT_KEYBOARD ) PORT_NAME(u8"5 % Ë POSITION") PORT_CODE(KEYCODE_5) PORT_CHAR('5') PORT_CHAR('%') PORT_CHAR(U'Ë')
+ PORT_BIT( 0x02, IP_ACTIVE_LOW, IPT_KEYBOARD ) PORT_NAME(u8"T Ñ INPUT") PORT_CODE(KEYCODE_T) PORT_CHAR('T') PORT_CHAR('t') PORT_CHAR(U'Ñ')
+ PORT_BIT( 0x04, IP_ACTIVE_LOW, IPT_KEYBOARD ) PORT_NAME(u8"G α RIGHT$(") PORT_CODE(KEYCODE_G) PORT_CHAR('G') PORT_CHAR('g') PORT_CHAR(U'α')
+ PORT_BIT( 0x08, IP_ACTIVE_LOW, IPT_KEYBOARD ) PORT_NAME(u8"B ¡ LOG(") PORT_CODE(KEYCODE_B) PORT_CHAR('B') PORT_CHAR('b') PORT_CHAR(U'¡')
+ PORT_BIT( 0x10, IP_ACTIVE_LOW, IPT_UNUSED )
+ 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_NAME(u8"] } Σ LIST") PORT_CODE(KEYCODE_BACKSLASH) PORT_CHAR(']') PORT_CHAR('}') PORT_CHAR(U'Σ')
+ PORT_BIT( 0x80, IP_ACTIVE_LOW, IPT_KEYBOARD ) PORT_NAME(u8"[ { Φ THEN") PORT_CODE(KEYCODE_CLOSEBRACE) PORT_CHAR('[') PORT_CHAR('{') PORT_CHAR(U'Φ')
+
+ PORT_START("PA5")
+ PORT_BIT( 0x01, IP_ACTIVE_LOW, IPT_KEYBOARD ) PORT_NAME(u8"6 & Ē COLOR") PORT_CODE(KEYCODE_6) PORT_CHAR('6') PORT_CHAR('&') PORT_CHAR(U'Ē')
+ PORT_BIT( 0x02, IP_ACTIVE_LOW, IPT_KEYBOARD ) PORT_NAME(u8"Y Nˆ DIM") PORT_CODE(KEYCODE_Y) PORT_CHAR('Y') PORT_CHAR('y')
+ PORT_BIT( 0x04, IP_ACTIVE_LOW, IPT_KEYBOARD ) PORT_NAME(u8"H β MID$(") PORT_CODE(KEYCODE_H) PORT_CHAR('H') PORT_CHAR('h') PORT_CHAR(U'β')
+ PORT_BIT( 0x08, IP_ACTIVE_LOW, IPT_KEYBOARD ) PORT_NAME(u8"N Æ ABS(") PORT_CODE(KEYCODE_N) PORT_CHAR('N') PORT_CHAR('n') PORT_CHAR(U'Æ')
+ PORT_BIT( 0x10, IP_ACTIVE_LOW, IPT_UNUSED )
+ 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 )
+
+ PORT_START("PA6")
+ PORT_BIT( 0x01, IP_ACTIVE_LOW, IPT_KEYBOARD ) PORT_NAME(u8"7 ' Û LINE") PORT_CODE(KEYCODE_7) PORT_CHAR('7') PORT_CHAR('\'') PORT_CHAR(U'Û')
+ PORT_BIT( 0x02, IP_ACTIVE_LOW, IPT_KEYBOARD ) PORT_NAME(u8"U Ú FOR") PORT_CODE(KEYCODE_U) PORT_CHAR('U') PORT_CHAR('u') PORT_CHAR(U'Ú')
+ PORT_BIT( 0x04, IP_ACTIVE_LOW, IPT_KEYBOARD ) PORT_NAME(u8"J θ SIN(") PORT_CODE(KEYCODE_J) PORT_CHAR('J') PORT_CHAR('j') PORT_CHAR(U'θ')
+ PORT_BIT( 0x08, IP_ACTIVE_LOW, IPT_KEYBOARD ) PORT_NAME(u8"M Ω INT(") PORT_CODE(KEYCODE_M) PORT_CHAR('M') PORT_CHAR('m') PORT_CHAR(U'Ω')
+ PORT_BIT( 0x10, IP_ACTIVE_LOW, IPT_UNUSED )
+ 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")
+ PORT_BIT( 0xff, IP_ACTIVE_LOW, IPT_UNUSED ) // keyboard disabled
+
+ PORT_START("PB0")
+ PORT_BIT( 0x01, IP_ACTIVE_LOW, IPT_KEYBOARD ) PORT_NAME(u8"8 ( Ǔ PSET") PORT_CODE(KEYCODE_8) PORT_CHAR('8') PORT_CHAR('(') PORT_CHAR(U'Ǔ')
+ PORT_BIT( 0x0e, IP_ACTIVE_LOW, IPT_UNUSED )
+
+ PORT_START("PB1")
+ PORT_BIT( 0x01, IP_ACTIVE_LOW, IPT_KEYBOARD ) PORT_NAME(u8"9 ) Ǐ SAVE\"") PORT_CODE(KEYCODE_9) PORT_CHAR('9') PORT_CHAR(')') PORT_CHAR(U'Ǐ')
+ PORT_BIT( 0x0e, IP_ACTIVE_LOW, IPT_UNUSED )
+
+ PORT_START("PB2")
+ PORT_BIT( 0x01, IP_ACTIVE_LOW, IPT_KEYBOARD ) PORT_NAME(u8"0 Ô LOAD\"") PORT_CODE(KEYCODE_0) PORT_CHAR('0')
+ PORT_BIT( 0x0e, IP_ACTIVE_LOW, IPT_UNUSED )
+
+ PORT_START("PB3")
+ PORT_BIT( 0x01, IP_ACTIVE_LOW, IPT_KEYBOARD ) PORT_NAME(u8"- = Ǒ VERIFY\"") PORT_CODE(KEYCODE_MINUS) PORT_CHAR('-') PORT_CHAR('=') PORT_CHAR(U'Ǒ')
+ PORT_BIT( 0x0e, IP_ACTIVE_LOW, IPT_UNUSED )
+
+ PORT_START("PB4")
+ PORT_BIT( 0x01, IP_ACTIVE_LOW, IPT_KEYBOARD ) PORT_NAME(u8"^ ~ O¸ AUTO") PORT_CODE(KEYCODE_EQUALS) PORT_CHAR('^') PORT_CHAR('~')
+ PORT_BIT( 0x0e, IP_ACTIVE_LOW, IPT_UNUSED )
+
+ PORT_START("PB5")
+ PORT_BIT( 0x01, IP_ACTIVE_LOW, IPT_KEYBOARD ) PORT_NAME(u8"¥ | £ RUN") PORT_CODE(KEYCODE_BACKSPACE) PORT_CHAR(U'¥') PORT_CHAR('|') 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)
+
+ PORT_START("PB6")
+ PORT_BIT( 0x01, IP_ACTIVE_LOW, IPT_KEYBOARD ) PORT_NAME("Break") PORT_CODE(KEYCODE_ESC) PORT_CHAR(UCHAR_MAMEKEY(ESC))
+ PORT_BIT( 0x02, IP_ACTIVE_LOW, IPT_KEYBOARD ) PORT_NAME("Graph") PORT_CODE(KEYCODE_LALT) PORT_CHAR(UCHAR_MAMEKEY(LALT))
+ PORT_BIT( 0x04, IP_ACTIVE_LOW, IPT_KEYBOARD ) PORT_NAME("Ctrl") PORT_CODE(KEYCODE_LCONTROL) PORT_CHAR(UCHAR_MAMEKEY(LCONTROL))
+ PORT_BIT( 0x08, IP_ACTIVE_LOW, IPT_KEYBOARD ) PORT_NAME("Shift") PORT_CODE(KEYCODE_LSHIFT) PORT_CODE(KEYCODE_RSHIFT) PORT_CHAR(UCHAR_SHIFT_1)
PORT_START("PB7")
PORT_BIT( 0x0f, IP_ACTIVE_LOW, IPT_UNUSED ) // keyboard disabled
@@ -152,6 +269,11 @@ ioport_constructor sega_sk1100_device::device_input_ports() const
return INPUT_PORTS_NAME( sk1100_keys );
}
+ioport_constructor sega_sk1100e_device::device_input_ports() const
+{
+ return INPUT_PORTS_NAME( sk1100e_keys );
+}
+
void sega_sk1100_device::device_add_mconfig(machine_config &config)
{
@@ -181,18 +303,28 @@ void sega_sk1100_device::device_add_mconfig(machine_config &config)
// sega_sk1100_device - constructor
//-------------------------------------------------
-sega_sk1100_device::sega_sk1100_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) :
- device_t(mconfig, SEGA_SK1100, tag, owner, clock),
+sega_sk1100_device::sega_sk1100_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_sg1000_expansion_slot_interface(mconfig, *this),
m_cassette(*this, "cassette"),
m_ppi(*this, UPD9255_0_TAG),
m_printer_port(*this, "printer"),
- m_pa(*this, {"PA0", "PA1", "PA2", "PA3", "PA4", "PA5", "PA6", "PA7"}),
- m_pb(*this, {"PB0", "PB1", "PB2", "PB3", "PB4", "PB5", "PB6", "PB7"}),
+ m_pa(*this, "PA%u", 0U),
+ m_pb(*this, "PB%u", 0U),
m_keylatch(0)
{
}
+sega_sk1100_device::sega_sk1100_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) :
+ sega_sk1100_device(mconfig, SEGA_SK1100, tag, owner, clock)
+{
+}
+
+sega_sk1100e_device::sega_sk1100e_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) :
+ sega_sk1100_device(mconfig, SEGA_SK1100E, tag, owner, clock)
+{
+}
+
//-------------------------------------------------
// device_start - device-specific startup
@@ -209,7 +341,7 @@ void sega_sk1100_device::device_start()
// peripheral_r - keyboard read
//-------------------------------------------------
-READ8_MEMBER(sega_sk1100_device::peripheral_r)
+uint8_t sega_sk1100_device::peripheral_r(offs_t offset)
{
return m_ppi->read(offset & 0x03);
}
@@ -219,7 +351,7 @@ READ8_MEMBER(sega_sk1100_device::peripheral_r)
// peripheral_w - keyboard write
//-------------------------------------------------
-WRITE8_MEMBER(sega_sk1100_device::peripheral_w)
+void sega_sk1100_device::peripheral_w(offs_t offset, uint8_t data)
{
m_ppi->write(offset & 0x03, data);
}
@@ -235,7 +367,7 @@ bool sega_sk1100_device::is_readable(uint8_t offset)
I8255 INTERFACE
-------------------------------------------------*/
-READ8_MEMBER( sega_sk1100_device::ppi_pa_r )
+uint8_t sega_sk1100_device::ppi_pa_r()
{
/*
Signal Description
@@ -253,7 +385,7 @@ READ8_MEMBER( sega_sk1100_device::ppi_pa_r )
return m_pa[m_keylatch]->read();
}
-READ8_MEMBER( sega_sk1100_device::ppi_pb_r )
+uint8_t sega_sk1100_device::ppi_pb_r()
{
/*
Signal Description
@@ -284,7 +416,7 @@ READ8_MEMBER( sega_sk1100_device::ppi_pb_r )
return data;
}
-WRITE8_MEMBER( sega_sk1100_device::ppi_pc_w )
+void sega_sk1100_device::ppi_pc_w(uint8_t data)
{
/*
Signal Description
diff --git a/src/devices/bus/sg1000_exp/sk1100.h b/src/devices/bus/sg1000_exp/sk1100.h
index 13ff5780f64..a587f4cc845 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"
@@ -35,23 +34,23 @@ public:
// construction/destruction
sega_sk1100_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:
+ sega_sk1100_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_add_mconfig(machine_config &config) override;
+ virtual void device_start() override ATTR_COLD;
+ virtual void device_add_mconfig(machine_config &config) override ATTR_COLD;
+ virtual ioport_constructor device_input_ports() const override ATTR_COLD;
// device_sg1000_expansion_slot_interface overrides
- virtual DECLARE_READ8_MEMBER(peripheral_r) override;
- virtual DECLARE_WRITE8_MEMBER(peripheral_w) override;
+ virtual uint8_t peripheral_r(offs_t offset) override;
+ virtual void peripheral_w(offs_t offset, uint8_t data) override;
virtual bool is_readable(uint8_t offset) override;
private:
- DECLARE_READ8_MEMBER( ppi_pa_r );
- DECLARE_READ8_MEMBER( ppi_pb_r );
- DECLARE_WRITE8_MEMBER( ppi_pc_w );
+ uint8_t ppi_pa_r();
+ uint8_t ppi_pb_r();
+ void ppi_pc_w(uint8_t data);
required_device<cassette_image_device> m_cassette;
required_device<i8255_device> m_ppi;
@@ -63,9 +62,20 @@ private:
uint8_t m_keylatch;
};
+class sega_sk1100e_device : public sega_sk1100_device
+{
+public:
+ // construction/destruction
+ sega_sk1100e_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
+
+protected:
+ // optional information overrides
+ virtual ioport_constructor device_input_ports() const override ATTR_COLD;
+};
// device type definition
DECLARE_DEVICE_TYPE(SEGA_SK1100, sega_sk1100_device)
+DECLARE_DEVICE_TYPE(SEGA_SK1100E, sega_sk1100e_device)
#endif // MAME_BUS_SG1000_EXP_SK1100_H
diff --git a/src/devices/bus/sg1000_exp/sk1100prn.cpp b/src/devices/bus/sg1000_exp/sk1100prn.cpp
index b902ce3992f..24d5808c229 100644
--- a/src/devices/bus/sg1000_exp/sk1100prn.cpp
+++ b/src/devices/bus/sg1000_exp/sk1100prn.cpp
@@ -9,7 +9,7 @@
#include "emu.h"
#include "sk1100prn.h"
// slot devices
-//#include "sp400.h"
+#include "sp400.h"
#include "kblink.h"
@@ -30,8 +30,8 @@ DEFINE_DEVICE_TYPE(SK1100_PRINTER_PORT, sk1100_printer_port_device, "sk1100_prin
// device_sk1100_printer_port_interface - constructor
//-------------------------------------------------
-device_sk1100_printer_port_interface::device_sk1100_printer_port_interface(const machine_config &mconfig, device_t &device)
- : device_slot_card_interface(mconfig,device)
+device_sk1100_printer_port_interface::device_sk1100_printer_port_interface(const machine_config &mconfig, device_t &device) :
+ device_interface(device, "sk1000prn")
{
}
@@ -56,7 +56,7 @@ device_sk1100_printer_port_interface::~device_sk1100_printer_port_interface()
sk1100_printer_port_device::sk1100_printer_port_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock) :
device_t(mconfig, SK1100_PRINTER_PORT, tag, owner, clock),
- device_slot_interface(mconfig, *this),
+ device_single_card_slot_interface<device_sk1100_printer_port_interface>(mconfig, *this),
m_device(nullptr)
{
}
@@ -77,28 +77,28 @@ sk1100_printer_port_device::~sk1100_printer_port_device()
void sk1100_printer_port_device::device_start()
{
- m_device = dynamic_cast<device_sk1100_printer_port_interface *>(get_card_device());
+ 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();
@@ -120,6 +120,6 @@ READ_LINE_MEMBER(sk1100_printer_port_device::busy_r)
void sk1100_printer_port_devices(device_slot_interface &device)
{
- //device.option_add("sp400", SP400_PRINTER); /* serial printer */
+ device.option_add("sp400", SP400_PRINTER); /* serial printer */
device.option_add("kblink", SK1100_LINK_CABLE);
}
diff --git a/src/devices/bus/sg1000_exp/sk1100prn.h b/src/devices/bus/sg1000_exp/sk1100prn.h
index b926f311f29..9dfcfca5a6c 100644
--- a/src/devices/bus/sg1000_exp/sk1100prn.h
+++ b/src/devices/bus/sg1000_exp/sk1100prn.h
@@ -9,8 +9,8 @@
**********************************************************************/
-#ifndef MAME_BUS_SG1000_EXP_SK1100_PRN_H
-#define MAME_BUS_SG1000_EXP_SK1100_PRN_H
+#ifndef MAME_BUS_SG1000_EXP_SK1100PRN_H
+#define MAME_BUS_SG1000_EXP_SK1100PRN_H
#pragma once
@@ -23,7 +23,7 @@
class device_sk1100_printer_port_interface;
-class sk1100_printer_port_device : public device_t, public device_slot_interface
+class sk1100_printer_port_device : public device_t, public device_single_card_slot_interface<device_sk1100_printer_port_interface>
{
public:
// construction/destruction
@@ -40,16 +40,16 @@ 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
- virtual void device_start() override;
+ virtual void device_start() override ATTR_COLD;
private:
device_sk1100_printer_port_interface *m_device;
@@ -59,7 +59,7 @@ private:
// ======================> device_sk1100_printer_port_interface
// class representing interface-specific live sk1100_printer_port peripheral
-class device_sk1100_printer_port_interface : public device_slot_card_interface
+class device_sk1100_printer_port_interface : public device_interface
{
friend class sk1100_printer_port_device;
public:
@@ -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; }
};
@@ -84,5 +84,4 @@ DECLARE_DEVICE_TYPE(SK1100_PRINTER_PORT, sk1100_printer_port_device)
void sk1100_printer_port_devices(device_slot_interface &device);
-
-#endif // MAME_BUS_SG1000_EXP_SK1100_PRN_H
+#endif // MAME_BUS_SG1000_EXP_SK1100PRN_H
diff --git a/src/devices/bus/sg1000_exp/sp400.cpp b/src/devices/bus/sg1000_exp/sp400.cpp
new file mode 100644
index 00000000000..fce22cf7d51
--- /dev/null
+++ b/src/devices/bus/sg1000_exp/sp400.cpp
@@ -0,0 +1,233 @@
+// license: BSD-3-Clause
+// copyright-holders: Fabio Dalla Libera
+
+/*
+ Sega SP-400 Plotter
+
+ 6805 dumped using https://github.com/charlesmacd/HD6805_Reader
+
+ Plotter uses ALPS Micrographic Printer DPG 1302 mechanism.
+
+ IC list:
+
+ * M5L8035LP (Mitsubishi clone of I8035)
+
+ P1 is the deserialized output data
+ P2.4 is the input serial data
+ P2.5 is busy (output to the computer)
+ P2.6 is the output strobe
+ P2.7 is busy (input from the 6805)
+
+ * HD6805V (Hitachi chip, pin compatible with MC6805P2, with 4K of ROM)
+
+ port A connected to the panel buttons
+ "By analyzing the disassembly I found out that three pins (PA5,6,7 of the 6805) are used to set
+ different configurations. The resolution can be changed, probably to support different mechanics.
+ The baud rate is 4800."
+ port B connected to the motors
+ port C connected to the pen and misc signals
+ port D connected to M5L8035LP parallel data
+*/
+
+// this is currently incomplete: missing paper output and pen sensor, everything else is working
+
+#include "emu.h"
+#include "sp400.h"
+
+#include "cpu/m6805/m68705.h"
+#include "cpu/mcs48/mcs48.h"
+
+
+namespace {
+
+class sp400_printer_device : public device_t, public device_sk1100_printer_port_interface
+{
+public:
+ static constexpr feature_type unemulated_features() { return feature::PRINTER; }
+
+ sp400_printer_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
+
+ virtual void device_add_mconfig(machine_config &config) override ATTR_COLD;
+ virtual void device_start() override ATTR_COLD;
+
+ const tiny_rom_entry *device_rom_region() const override ATTR_COLD;
+ virtual ioport_constructor device_input_ports() const override ATTR_COLD;
+
+ virtual void input_data(int state) override { m_data = state; }
+ virtual int output_busy() override { return m_busy; }
+
+private:
+ void dser_map(address_map &map);
+ void dser_p1_w(uint8_t data);
+ uint8_t dser_p2_r();
+ void dser_p2_w(uint8_t data);
+
+ uint8_t mot_pa_r();
+ void mot_pb_w(uint8_t data);
+ uint8_t mot_pc_r();
+ void mot_pc_w(uint8_t data);
+ uint8_t mot_pd_r();
+ void update_pen_state(uint8_t data);
+ uint8_t pen_sensor() { return 0; } // not currently hooked up
+
+ required_device<i8035_device> m_dsercpu; // "deserializer CPU"
+ required_device<m6805_hmos_device> m_motcpu; // "motor CPU"
+
+ uint8_t m_data, m_busy;
+ uint8_t m_dserdataout, m_dserstrobe;
+ uint8_t m_motbusy, m_motpenup, m_motpendown;
+ uint8_t m_pendown;
+
+ required_ioport m_buttons;
+};
+
+sp400_printer_device::sp400_printer_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) :
+ device_t(mconfig, SP400_PRINTER, tag, owner, clock),
+ device_sk1100_printer_port_interface(mconfig, *this),
+ m_dsercpu(*this, "dsercpu"),
+ m_motcpu(*this, "motcpu"),
+ m_data(0),
+ m_busy(1),
+ m_dserdataout(0xff),
+ m_dserstrobe(1),
+ m_motbusy(0),
+ m_motpenup(1),
+ m_motpendown(1),
+ m_pendown(0),
+ m_buttons(*this, "BUTTONS")
+{
+}
+
+void sp400_printer_device::device_start()
+{
+ save_item(NAME(m_data));
+ save_item(NAME(m_busy));
+ save_item(NAME(m_dserdataout));
+ save_item(NAME(m_dserstrobe));
+ save_item(NAME(m_motbusy));
+ save_item(NAME(m_motpenup));
+ save_item(NAME(m_motpendown));
+ save_item(NAME(m_pendown));
+}
+
+void sp400_printer_device::dser_map(address_map &map)
+{
+ map(0x0000, 0x0fff).rom();
+}
+
+void sp400_printer_device::dser_p1_w(uint8_t data)
+{
+ m_dserdataout = data;
+}
+
+void sp400_printer_device::dser_p2_w(uint8_t data)
+{
+ m_busy = BIT(data, 5);
+ m_dserstrobe = BIT(data, 6);
+ m_motcpu->set_input_line(M6805_IRQ_LINE, m_dserstrobe);
+}
+
+uint8_t sp400_printer_device::dser_p2_r()
+{
+ return
+ (m_motbusy << 7) |
+ (m_dserstrobe << 6) |
+ (m_busy << 5) |
+ (m_data << 4) |
+ (1 << 3) |
+ (1 << 2) |
+ (1 << 1) |
+ (1 << 0);
+}
+
+uint8_t sp400_printer_device::mot_pa_r()
+{
+ return
+ (0 << 0) |
+ (0 << 1) |
+ (m_buttons->read() << 2) | // bits 2..4
+ (0 << 5) |
+ (0 << 6) |
+ (1 << 7);
+}
+
+void sp400_printer_device::mot_pb_w(uint8_t data)
+{
+ // cr stepper data in 0..3
+ // pf stepper data in 4..7
+}
+
+uint8_t sp400_printer_device::mot_pc_r()
+{
+ return
+ (m_motpenup << 0) |
+ (m_motpendown << 1) |
+ (1 << 2) |
+ (pen_sensor() << 3) |
+ (m_motbusy << 4) |
+ (1 << 5) | (1 << 6) | (1 << 7); // unconfirmed
+}
+
+void sp400_printer_device::mot_pc_w(uint8_t data)
+{
+ m_motpenup = BIT(data, 0);
+ m_motpendown = BIT(data, 1);
+ m_motbusy = BIT(data, 4);
+ update_pen_state(data);
+}
+
+uint8_t sp400_printer_device::mot_pd_r()
+{
+ return sp400_printer_device::m_dserdataout;
+}
+
+void sp400_printer_device::update_pen_state(uint8_t data)
+{
+ if (!BIT(data, 0)) m_pendown = 0;
+ if (!BIT(data, 1)) m_pendown = 1;
+}
+
+void sp400_printer_device::device_add_mconfig(machine_config &config)
+{
+ I8035(config, m_dsercpu, 4_MHz_XTAL);
+ m_dsercpu->p1_out_cb().set(FUNC(sp400_printer_device::dser_p1_w));
+ m_dsercpu->p2_in_cb().set(FUNC(sp400_printer_device::dser_p2_r));
+ m_dsercpu->p2_out_cb().set(FUNC(sp400_printer_device::dser_p2_w));
+ m_dsercpu->set_addrmap(AS_PROGRAM, &sp400_printer_device::dser_map);
+
+ M6805U3(config, m_motcpu, 4_MHz_XTAL);
+ m_motcpu->porta_r().set(FUNC(sp400_printer_device::mot_pa_r));
+ m_motcpu->portb_w().set(FUNC(sp400_printer_device::mot_pb_w));
+ m_motcpu->portc_r().set(FUNC(sp400_printer_device::mot_pc_r));
+ m_motcpu->portc_w().set(FUNC(sp400_printer_device::mot_pc_w));
+ m_motcpu->portd_r().set(FUNC(sp400_printer_device::mot_pd_r));
+}
+
+ROM_START( sp400 )
+ ROM_REGION( 0x1000, "dsercpu", 0 )
+ ROM_LOAD( "sp400_8035.bin", 0x0000, 0x1000, CRC(0eb48272) SHA1(08a2727f1592f5d2ecb2e368126ad7bfc5d3c270) )
+
+ ROM_REGION(0x1000, "motcpu", 0 )
+ ROM_LOAD( "sp400_hd6805v1.bin", 0x0000, 0x1000, CRC(aa073745) SHA1(65016f3b022af30cc6b084af1e43b29168721a60) )
+ROM_END
+
+const tiny_rom_entry *sp400_printer_device::device_rom_region() const
+{
+ return ROM_NAME( sp400 );
+}
+
+INPUT_PORTS_START( sp400 )
+ PORT_START("BUTTONS")
+ PORT_BIT(0x01, IP_ACTIVE_LOW, IPT_KEYPAD) PORT_NAME("Color Select") PORT_CODE(KEYCODE_2_PAD)
+ PORT_BIT(0x02, IP_ACTIVE_LOW, IPT_KEYPAD) PORT_NAME("Line Feed") PORT_CODE(KEYCODE_1_PAD)
+ PORT_BIT(0x04, IP_ACTIVE_LOW, IPT_KEYPAD) PORT_NAME("Pen Change") PORT_CODE(KEYCODE_3_PAD)
+INPUT_PORTS_END
+
+ioport_constructor sp400_printer_device::device_input_ports() const
+{
+ return INPUT_PORTS_NAME(sp400);
+}
+
+} // anonymous namespace
+
+DEFINE_DEVICE_TYPE_PRIVATE(SP400_PRINTER, device_sk1100_printer_port_interface, sp400_printer_device, "sega_sp400", "Sega SP-400 Plotter")
diff --git a/src/devices/bus/sg1000_exp/sp400.h b/src/devices/bus/sg1000_exp/sp400.h
new file mode 100644
index 00000000000..fa1d87c0878
--- /dev/null
+++ b/src/devices/bus/sg1000_exp/sp400.h
@@ -0,0 +1,13 @@
+// license: BSD-3-Clause
+// copyright-holders: Fabio Dalla Libera
+
+#ifndef MAME_BUS_SG1000_EXP_SP400_H
+#define MAME_BUS_SG1000_EXP_SP400_H
+
+#pragma once
+
+#include "sk1100prn.h"
+
+DECLARE_DEVICE_TYPE(SP400_PRINTER, device_sk1100_printer_port_interface)
+
+#endif // MAME_BUS_SG1000_EXP_SP400_H
diff --git a/src/devices/bus/sgikbd/hlekbd.cpp b/src/devices/bus/sgikbd/hlekbd.cpp
deleted file mode 100644
index 517e8496fa0..00000000000
--- a/src/devices/bus/sgikbd/hlekbd.cpp
+++ /dev/null
@@ -1,413 +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_NS(SGI_HLE_KEYBOARD, bus::sgikbd, hle_device, "hlekbd", "SGI Indigo Keyboard (HLE)")
-
-namespace bus { namespace 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(TIMER_CLICK);
- m_beep_timer = timer_alloc(TIMER_BEEP);
-
- 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));
-}
-
-void hle_device::device_timer(emu_timer &timer, device_timer_id id, int param, void *ptr)
-{
- switch (id)
- {
- case TIMER_CLICK:
- m_beeper_state &= ~BEEPER_CLICK;
- m_beeper->set_state(m_beeper_state ? 1 : 0);
- break;
-
- case TIMER_BEEP:
- m_beeper_state &= ~BEEPER_BELL;
- m_beeper->set_state(m_beeper_state ? 1 : 0);
- break;
-
- default:
- break;
- }
-}
-
-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 a83268693bc..00000000000
--- a/src/devices/bus/sgikbd/hlekbd.h
+++ /dev/null
@@ -1,117 +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 { namespace 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 void device_timer(emu_timer &timer, device_timer_id id, int param, void *ptr) 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);
-
-private:
- enum
- {
- TIMER_CLICK = 30000,
- TIMER_BEEP = 30001
- };
-
- 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 4ad2d1f925a..00000000000
--- a/src/devices/bus/sgikbd/sgikbd.cpp
+++ /dev/null
@@ -1,89 +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")
-
-
-int const device_sgi_keyboard_port_interface::START_BIT_COUNT;
-int const device_sgi_keyboard_port_interface::DATA_BIT_COUNT;
-device_serial_interface::parity_t const device_sgi_keyboard_port_interface::PARITY;
-device_serial_interface::stop_bits_t const device_sgi_keyboard_port_interface::STOP_BITS;
-int const device_sgi_keyboard_port_interface::BAUD;
-
-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_slot_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 = dynamic_cast<device_sgi_keyboard_port_interface *>(get_card_device());
-}
-
-void sgi_keyboard_port_device::device_validity_check(validity_checker &valid) const
-{
- device_t *const card(get_card_device());
- if (card && !dynamic_cast<device_sgi_keyboard_port_interface *>(card))
- {
- logerror("Card device %s (%s) does not implement device_sgi_keyboard_port_interface\n", card->tag(), card->name());
- }
-}
-
-void sgi_keyboard_port_device::device_resolve_objects()
-{
- m_rxd_handler.resolve_safe();
-}
-
-void sgi_keyboard_port_device::device_start()
-{
- if (get_card_device() && !m_dev)
- {
- throw emu_fatalerror("Card device %s (%s) does not implement device_sgi_keyboard_port_interface\n", get_card_device()->tag(), get_card_device()->name());
- }
-
- 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_slot_card_interface(mconfig, device)
- , 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 1aa87bd43ad..00000000000
--- a/src/devices/bus/sgikbd/sgikbd.h
+++ /dev/null
@@ -1,82 +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_slot_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_validity_check(validity_checker &valid) const 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_slot_card_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..7ab811b7ca4
--- /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 ATTR_COLD;
+ virtual void device_start() override ATTR_COLD;
+
+private:
+ void program_map(address_map &map) ATTR_COLD;
+ void data_map(address_map &map) ATTR_COLD;
+
+ 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..fa46594ded7 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 ATTR_COLD;
+
+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 2dead793887..a008b081f6d 100644
--- a/src/devices/bus/sms_ctrl/lphaser.cpp
+++ b/src/devices/bus/sms_ctrl/lphaser.cpp
@@ -19,47 +19,63 @@ 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); }
+ // device_sms_control_interface implementation
+ virtual uint8_t in_r() override { return m_trigger->read(); }
-#define LGUN_RADIUS 6
-#define LGUN_X_INTERVAL 4
+protected:
+ // device_t implementation
+ virtual ioport_constructor device_input_ports() const override ATTR_COLD;
+ virtual void device_start() override ATTR_COLD;
+ virtual void device_reset() override ATTR_COLD;
+private:
+ required_ioport m_trigger;
+ required_ioport m_x_axis;
+ required_ioport m_y_axis;
-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;
-}
+ emu_timer *m_update_timer;
+ int m_sensor_last_state;
-INPUT_CHANGED_MEMBER( sms_light_phaser_device::position_changed )
-{
- if (newval != oldval)
- sensor_check();
-}
+ 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)
+ 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, FUNC(sms_light_phaser_device::position_changed), 0)
PORT_START("LPHASER_Y")
- PORT_BIT( 0xff, 0x00, IPT_LIGHTGUN_Y) PORT_CROSSHAIR(Y, 1.0, 0.0, 0) PORT_SENSITIVITY(50) PORT_KEYDELTA(15) PORT_CHANGED_MEMBER(DEVICE_SELF, sms_light_phaser_device, position_changed, 0)
+ PORT_BIT( 0xff, 0x00, IPT_LIGHTGUN_Y) PORT_CROSSHAIR(Y, 1.0, 0.0, 0) PORT_SENSITIVITY(50) PORT_KEYDELTA(15) PORT_CHANGED_MEMBER(DEVICE_SELF, FUNC(sms_light_phaser_device::position_changed), 0)
INPUT_PORTS_END
@@ -69,25 +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)
{
}
@@ -98,61 +111,61 @@ 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(TIMER_LPHASER);
-}
+ 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
}
/*
Light Phaser (light gun) emulation notes:
- - The sensor is activated based on color brightness of some individual
- pixels being drawn by the beam, at circular area where the gun is aiming.
+ - The sensor is activated based on the brightness of individual pixels being
+ drawn by the beam, in circular area where the gun is aiming.
- Currently, brightness is calculated based only on single pixels.
- In general, after the trigger is pressed, games draw the next frame using
- a light color pattern, to make sure sensor will be activated. If emulation
- skips that frame, sensor may stay deactivated. Frameskip set to 0 (no skip)
+ a bright pattern, to make sure the sensor will be activated. If the emulation
+ skips that frame, the sensor may stay deactivated. Setting frameskip to 0
is recommended to avoid problems.
- - When sensor switches from on (0) to off (1), a value is latched for the
+ - When the sensor switches from on (0) to off (1), a value is latched for the
HCount register.
- - When sensor switches from off to on, a flag is set. The emulation uses the
- flag to signal that TH line is activated when the status of the input port
- is read. After read, the flag is cleared, or else it is cleared later when
- the Pause status is read (end of a frame). This is necessary because the
+ - When the sensor switches from off to on, a flag is set. The emulation uses
+ this flag to signal that the TH line is activated during status reads of the
+ input port. After reading, the flag is cleared, or it is cleared when the
+ Pause status is read at the end of a frame. This is necessary because the
"Color & Switch Test" ROM only reads the TH state after VINT occurs.
- - The gun test of "Color & Switch Test" is an example that requires checks
- of sensor status independent of other events, like trigger press or TH bit
+ - The gun test in "Color & Switch Test" is an example that requires checks
+ of the sensor status independent of other events, like trigger press or TH bit
reads. Another example is the title screen of "Hang-On & Safari Hunt", where
- the game only reads HCount register in a loop, expecting a latch by the gun.
- - The whole procedure is managed by a timer callback, that always reschedule
- itself to run in some intervals when the beam is at the circular area.
+ the game only reads the HCount register in a loop, expecting a latch by the gun.
+ - The whole procedure is managed by a periodic timer callback, which is scheduled
+ to run in intervals when the beam is within the circular area.
*/
-int sms_light_phaser_device::bright_aim_area( emu_timer *timer, int lgun_x, int lgun_y )
+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 dy, result = 1;
- double dx_radius;
+ 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;
aim_area.min_y = std::max(lgun_y - LGUN_RADIUS, visarea.min_y);
@@ -160,29 +173,25 @@ int sms_light_phaser_device::bright_aim_area( emu_timer *timer, int lgun_x, int
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;
}
- dy = abs(beam_y - lgun_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. */
- switch (dy)
+ // Calculate distance in x of the radius, relative to beam's y distance. First try some shortcuts.
+ double dx_radius = 0;
+ if (dy == 0)
{
- case LGUN_RADIUS:
- dx_radius = 0;
- break;
- case 0:
dx_radius = LGUN_RADIUS;
- break;
- default:
- /* 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((float) sqrt((float) (r_x_r - (dy * dy))));
+ }
+ 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)
+ dx_radius = ceil(sqrt(double(r_x_r - (dy * dy))));
}
aim_area.min_x = std::max(int32_t(lgun_x - dx_radius), visarea.min_x);
@@ -190,8 +199,7 @@ int sms_light_phaser_device::bright_aim_area( emu_timer *timer, int lgun_x, int
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;
@@ -199,8 +207,7 @@ int sms_light_phaser_device::bright_aim_area( emu_timer *timer, int lgun_x, int
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;
@@ -208,58 +215,52 @@ int sms_light_phaser_device::bright_aim_area( emu_timer *timer, int lgun_x, int
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;
+ scr.update_now();
+ const rgb_t color = scr.pixel(beam_x, beam_y);
- m_port->m_screen->update_now();
- color = m_port->m_screen->pixel(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);
- /* 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);
-
- 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;
}
}
}
- 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;
}
@@ -267,36 +268,34 @@ 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;
}
-void sms_light_phaser_device::sensor_check()
+TIMER_CALLBACK_MEMBER(sms_light_phaser_device::sensor_check)
{
- int sensor_new_state;
-
- const int x = screen_hpos_nonscaled(m_lphaser_x->read());
- const int y = screen_vpos_nonscaled(m_lphaser_y->read());
-
- sensor_new_state = bright_aim_area(m_lphaser_timer, 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
-void sms_light_phaser_device::device_timer(emu_timer &timer, device_timer_id id, int param, void *ptr)
-{
- switch (id)
- {
- case TIMER_LPHASER:
- sensor_check();
- break;
- default:
- throw emu_fatalerror("sms_light_phaser_device(%s): Unknown timer ID", tag());
- }
-}
+
+
+//**************************************************************************
+// 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 123241e2663..c9d3a2b6eb5 100644
--- a/src/devices/bus/sms_ctrl/lphaser.h
+++ b/src/devices/bus/sms_ctrl/lphaser.h
@@ -5,63 +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;
- static const device_timer_id TIMER_LPHASER = 0;
-
- void device_timer(emu_timer &timer, device_timer_id id, int param, void *ptr) override;
- void sensor_check();
- int bright_aim_area( emu_timer *timer, 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..7b5f145e744
--- /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 ATTR_COLD;
+ virtual void device_reset() override ATTR_COLD;
+
+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..7df30b42de0
--- /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 ATTR_COLD;
+
+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..bf34dc8f5fd
--- /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 ATTR_COLD;
+
+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..5634f0c989d 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 ATTR_COLD;
+ virtual void device_resolve_objects() override ATTR_COLD;
+ virtual void device_start() override ATTR_COLD;
+
+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 87f8b091274..7484c0d1c68 100644
--- a/src/devices/bus/sms_ctrl/multitap.h
+++ b/src/devices/bus/sms_ctrl/multitap.h
@@ -5,54 +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:
- DECLARE_READ32_MEMBER(pixel_r);
-
- 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..13462c43f3c 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 ATTR_COLD;
+ virtual ioport_constructor device_input_ports() const override ATTR_COLD;
+ virtual void device_config_complete() override;
+ virtual void device_start() override ATTR_COLD;
+ virtual void device_reset() override ATTR_COLD;
+
+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(FUNC(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(FUNC(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..e6fb0b6ecd9
--- /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 ATTR_COLD;
+
+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..27335514b51
--- /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_RS232ADAPT_H
+#define MAME_BUS_SMS_CTRL_RS232ADAPT_H
+
+#pragma once
+
+#include "smsctrl.h"
+
+
+DECLARE_DEVICE_TYPE(SMS_RS232, device_sms_control_interface)
+
+#endif // MAME_BUS_SMS_CTRL_RS232ADAPT_H
diff --git a/src/devices/bus/sms_ctrl/smsctrl.cpp b/src/devices/bus/sms_ctrl/smsctrl.cpp
index a2c117dcb74..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_slot_card_interface(mconfig,device)
+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 ced9176efb0..d88869b9539 100644
--- a/src/devices/bus/sms_ctrl/smsctrl.h
+++ b/src/devices/bus/sms_ctrl/smsctrl.h
@@ -1,36 +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"
+
+#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);
@@ -38,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;
+ virtual void device_start() override ATTR_COLD;
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;
+ friend class device_sms_control_interface;
+};
-// ======================> device_sms_control_port_interface
-// class representing interface-specific live sms_expansion card
-class device_sms_control_port_interface : public device_slot_card_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 dee6af4eb63..dc8bc7c13bf 100644
--- a/src/devices/bus/sms_ctrl/sports.cpp
+++ b/src/devices/bus/sms_ctrl/sports.cpp
@@ -11,29 +11,28 @@ Release data from the Sega Retro project:
TODO:
-- For low-level emulation, a device for the TMP42C66P, a Toshiba 4bit
- microcontroller, needs to be created, but a dump of its internal ROM
- seems to be required.
+- For low-level emulation, a device for the TMP42C66P, a Toshiba 4-bit
+ microcontroller, is needed along with a dump of its internal ROM.
- Auto-repeat and Control/Sports mode switches are not emulated.
Notes:
Games designed for the US model of the Sports Pad controller use the
- TH line of the controller port to select which nibble, of the two axis
- bytes, will be read at a time. The Japanese cartridge Sports Pad Soccer
- uses a different mode when not detect a SMSJ, because the Sega Mark III
- lacks the TH line. There is 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).
+ TH line of the controller port to select which nibble of the two axis
+ to read. The Japanese cartridge Sports Pad Soccer uses a different mode
+ 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.cpp).
It was discovered that games designed for the Paddle Controller, released
- in Japan, switch to a mode incompatible with the original Paddle when
- detect the system region as Export. Similar to how the US model of the
- Sports Pad works, that mode uses the TH line as output to select which
+ in Japan, will switch to a mode incompatible with the original Paddle when
+ the system region is detected as Export. Similar to how the US model of the
+ Sports Pad works, that mode uses the TH line as an output to select which
nibble of the X axis will be read. So, on an Export console version,
paddle games are somewhat playable with the US Sport Pad model, 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.
+ needs to be used inverted and the trackball needs to be moved slowly,
+ otherwise the software for the paddle think it's moving backward.
See http://mametesters.org/view.php?id=5872 for discussion.
**********************************************************************/
@@ -41,120 +40,61 @@ 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)")
-
-// time interval not verified
-#define SPORTS_PAD_INTERVAL attotime::from_hz(XTAL(10'738'635)/3/512)
+namespace {
+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
-void sms_sports_pad_device::device_timer(emu_timer &timer, device_timer_id id, int param, void *ptr)
-{
- switch (id)
- {
- case TIMER_SPORTSPAD:
- // values for x and y axis need to be resetted for Sports Pad games, but
- // are not resetted for paddle games, so it was assumed the reset occurs
- // only when this timer fires after the read state reached 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;
- }
-
- break;
- default:
- throw emu_fatalerror("sms_sports_pad_device(%s): Unknown timer ID", tag());
- }
-}
-
+ 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;
-
- 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;
- }
-
- // The returned value is inverted due to IP_ACTIVE_LOW mapping.
- return ~(data & 0x0f);
-}
-
-
-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)
-
- 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)
-
- PORT_START("SPORTS_X") /* Sports Pad X axis */
- PORT_BIT( 0xff, 0x00, IPT_TRACKBALL_X ) PORT_SENSITIVITY(50) PORT_KEYDELTA(40) PORT_REVERSE
+public:
+ // construction/destruction
+ sms_sports_pad_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
- 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
+ // 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_sports_pad); }
+ virtual void device_start() override ATTR_COLD;
-//-------------------------------------------------
-// input_ports - device-specific input ports
-//-------------------------------------------------
+private:
+ TIMER_CALLBACK_MEMBER(timeout);
-ioport_constructor sms_sports_pad_device::device_input_ports() const
-{
- return INPUT_PORTS_NAME( sms_sports_pad );
-}
+ required_ioport m_buttons;
+ required_ioport_array<2> m_axes;
+ emu_timer *m_timeout_timer;
+ uint8_t m_th_state;
+ uint8_t m_phase;
+ uint8_t m_output;
+ uint8_t m_base[2];
+ uint8_t m_data[2];
+};
-//**************************************************************************
-// LIVE DEVICE
-//**************************************************************************
//-------------------------------------------------
// sms_sports_pad_device - constructor
@@ -162,17 +102,13 @@ ioport_constructor sms_sports_pad_device::device_input_ports() const
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 start playing 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)
{
}
@@ -183,30 +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(TIMER_SPORTSPAD);
-
- 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));
+ 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));
}
-//-------------------------------------------------
-// sms_peripheral_r - sports pad read
-//-------------------------------------------------
-
-uint8_t sms_sports_pad_device::peripheral_r()
+uint8_t sms_sports_pad_device::in_r()
{
- return m_sports_in->read();
+ return m_buttons->read() | m_output;
}
-//-------------------------------------------------
-// sms_peripheral_w - sports pad write
-//-------------------------------------------------
+void sms_sports_pad_device::out_w(uint8_t data, uint8_t mem_mask)
+{
+ // 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 6644541f36a..ac6e75e5626 100644
--- a/src/devices/bus/sms_ctrl/sports.h
+++ b/src/devices/bus/sms_ctrl/sports.h
@@ -5,65 +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;
- static const device_timer_id TIMER_SPORTSPAD = 0;
-
- void device_timer(emu_timer &timer, device_timer_id id, int param, void *ptr) override;
-};
-
-
-// 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..9947a717d0f 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
+#ifndef MAME_BUS_SMS_CTRL_SPORTSJP_H
+#define MAME_BUS_SMS_CTRL_SPORTSJP_H
#pragma once
-
#include "smsctrl.h"
+DECLARE_DEVICE_TYPE(SMS_SPORTS_PAD_JP, device_sms_control_interface)
-//**************************************************************************
-// 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)
-
-
-#endif // MAME_BUS_SMS_CTROL_SPORTSJP_H
+#endif // MAME_BUS_SMS_CTRL_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..8f3106b3b62
--- /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 ATTR_COLD;
+ virtual ioport_constructor device_input_ports() const override ATTR_COLD;
+ virtual void device_resolve_objects() override ATTR_COLD;
+ virtual void device_start() override ATTR_COLD;
+
+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, FUNC(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..3f0a4369f16
--- /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", FUNC(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", FUNC(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/sms_exp/gender.cpp b/src/devices/bus/sms_exp/gender.cpp
index 227aae8a1da..87bb97ea7a2 100644
--- a/src/devices/bus/sms_exp/gender.cpp
+++ b/src/devices/bus/sms_exp/gender.cpp
@@ -56,14 +56,14 @@ void sms_gender_adapter_device::device_start()
// read
//-------------------------------------------------
-READ8_MEMBER(sms_gender_adapter_device::read)
+uint8_t sms_gender_adapter_device::read(offs_t offset)
{
- return m_subslot->read_cart(space, offset);
+ return m_subslot->read_cart(offset);
}
-READ8_MEMBER(sms_gender_adapter_device::read_ram)
+uint8_t sms_gender_adapter_device::read_ram(offs_t offset)
{
- return m_subslot->read_ram(space, offset);
+ return m_subslot->read_ram(offset);
}
int sms_gender_adapter_device::get_lphaser_xoffs()
@@ -76,19 +76,19 @@ int sms_gender_adapter_device::get_lphaser_xoffs()
// write
//-------------------------------------------------
-WRITE8_MEMBER(sms_gender_adapter_device::write_mapper)
+void sms_gender_adapter_device::write_mapper(offs_t offset, uint8_t data)
{
- m_subslot->write_mapper(space, offset, data);
+ m_subslot->write_mapper(offset, data);
}
-WRITE8_MEMBER(sms_gender_adapter_device::write)
+void sms_gender_adapter_device::write(offs_t offset, uint8_t data)
{
- m_subslot->write_cart(space, offset, data);
+ m_subslot->write_cart(offset, data);
}
-WRITE8_MEMBER(sms_gender_adapter_device::write_ram)
+void sms_gender_adapter_device::write_ram(offs_t offset, uint8_t data)
{
- m_subslot->write_ram(space, offset, data);
+ m_subslot->write_ram(offset, data);
}
//-------------------------------------------------
diff --git a/src/devices/bus/sms_exp/gender.h b/src/devices/bus/sms_exp/gender.h
index 5bc93cbad5c..27eaf33fc7d 100644
--- a/src/devices/bus/sms_exp/gender.h
+++ b/src/devices/bus/sms_exp/gender.h
@@ -31,18 +31,18 @@ public:
sms_gender_adapter_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
// device_sms_expansion_slot_interface overrides
- virtual DECLARE_READ8_MEMBER(read) override;
- virtual DECLARE_WRITE8_MEMBER(write) override;
- virtual DECLARE_WRITE8_MEMBER(write_mapper) override;
- virtual DECLARE_READ8_MEMBER(read_ram) override;
- virtual DECLARE_WRITE8_MEMBER(write_ram) override;
+ virtual uint8_t read(offs_t offset) override;
+ virtual void write(offs_t offset, uint8_t data) override;
+ virtual void write_mapper(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;
virtual int get_lphaser_xoffs() override;
protected:
// device-level overrides
- virtual void device_start() override;
- virtual void device_add_mconfig(machine_config &config) override;
+ virtual void device_start() override ATTR_COLD;
+ virtual void device_add_mconfig(machine_config &config) override ATTR_COLD;
private:
required_device<sega8_cart_slot_device> m_subslot;
diff --git a/src/devices/bus/sms_exp/smsexp.cpp b/src/devices/bus/sms_exp/smsexp.cpp
index f7c4b12c159..0d330f888b6 100644
--- a/src/devices/bus/sms_exp/smsexp.cpp
+++ b/src/devices/bus/sms_exp/smsexp.cpp
@@ -31,8 +31,8 @@ DEFINE_DEVICE_TYPE(SMS_EXPANSION_SLOT, sms_expansion_slot_device, "sms_expansion
// device_sms_expansion_slot_interface - constructor
//-------------------------------------------------
-device_sms_expansion_slot_interface::device_sms_expansion_slot_interface(const machine_config &mconfig, device_t &device)
- : device_slot_card_interface(mconfig,device)
+device_sms_expansion_slot_interface::device_sms_expansion_slot_interface(const machine_config &mconfig, device_t &device) :
+ device_interface(device, "smsexp")
{
}
@@ -57,7 +57,7 @@ device_sms_expansion_slot_interface::~device_sms_expansion_slot_interface()
sms_expansion_slot_device::sms_expansion_slot_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) :
device_t(mconfig, SMS_EXPANSION_SLOT, tag, owner, clock),
- device_slot_interface(mconfig, *this),
+ device_single_card_slot_interface<device_sms_expansion_slot_interface>(mconfig, *this),
m_device(nullptr)
{
}
@@ -78,7 +78,7 @@ sms_expansion_slot_device::~sms_expansion_slot_device()
void sms_expansion_slot_device::device_start()
{
- m_device = dynamic_cast<device_sms_expansion_slot_interface *>(get_card_device());
+ m_device = get_card_device();
}
diff --git a/src/devices/bus/sms_exp/smsexp.h b/src/devices/bus/sms_exp/smsexp.h
index 6933b9a9df8..88a1b4aa613 100644
--- a/src/devices/bus/sms_exp/smsexp.h
+++ b/src/devices/bus/sms_exp/smsexp.h
@@ -22,18 +22,18 @@
// ======================> device_sms_expansion_slot_interface
// class representing interface-specific live sms_expansion card
-class device_sms_expansion_slot_interface : public device_slot_card_interface
+class device_sms_expansion_slot_interface : public device_interface
{
public:
// construction/destruction
virtual ~device_sms_expansion_slot_interface();
// reading and writing
- virtual DECLARE_READ8_MEMBER(read) { return 0xff; }
- virtual DECLARE_WRITE8_MEMBER(write) { }
- virtual DECLARE_WRITE8_MEMBER(write_mapper) { }
- virtual DECLARE_READ8_MEMBER(read_ram) { return 0xff; }
- virtual DECLARE_WRITE8_MEMBER(write_ram) { }
+ virtual uint8_t read(offs_t offset) { return 0xff; }
+ virtual void write(offs_t offset, uint8_t data) { }
+ virtual void write_mapper(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) { }
virtual int get_lphaser_xoffs() { return 0; }
@@ -44,8 +44,7 @@ protected:
// ======================> sms_expansion_slot_device
-class sms_expansion_slot_device : public device_t,
- public device_slot_interface
+class sms_expansion_slot_device : public device_t, public device_single_card_slot_interface<device_sms_expansion_slot_interface>
{
public:
// construction/destruction
@@ -62,11 +61,11 @@ public:
virtual ~sms_expansion_slot_device();
// reading and writing
- DECLARE_READ8_MEMBER(read) { return m_device ? m_device->read(space, offset, mem_mask) : 0xff; }
- DECLARE_WRITE8_MEMBER(write) { if (m_device) m_device->write(space, offset, data, mem_mask); }
- DECLARE_WRITE8_MEMBER(write_mapper) { if (m_device) m_device->write_mapper(space, offset, data, mem_mask); }
- DECLARE_READ8_MEMBER(read_ram) { return m_device ? m_device->read_ram(space, offset, mem_mask) : 0xff; }
- DECLARE_WRITE8_MEMBER(write_ram) { if (m_device) m_device->write_ram(space, offset, data, mem_mask); }
+ uint8_t read(offs_t offset) { return m_device ? m_device->read(offset) : 0xff; }
+ void write(offs_t offset, uint8_t data) { if (m_device) m_device->write(offset, data); }
+ void write_mapper(offs_t offset, uint8_t data) { if (m_device) m_device->write_mapper(offset, data); }
+ uint8_t read_ram(offs_t offset) { return m_device ? m_device->read_ram(offset) : 0xff; }
+ void write_ram(offs_t offset, uint8_t data) { if (m_device) m_device->write_ram(offset, data); }
int get_lphaser_xoffs() { return m_device ? m_device->get_lphaser_xoffs() : 0; }
@@ -74,7 +73,7 @@ public:
protected:
// device-level overrides
- virtual void device_start() override;
+ virtual void device_start() override ATTR_COLD;
device_sms_expansion_slot_interface *m_device;
};
diff --git a/src/devices/bus/snes/bsx.h b/src/devices/bus/snes/bsx.h
index e144ff118ff..9a7314302e2 100644
--- a/src/devices/bus/snes/bsx.h
+++ b/src/devices/bus/snes/bsx.h
@@ -50,10 +50,10 @@ protected:
sns_rom_bsx_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_start() override ATTR_COLD;
+ virtual void device_reset() override ATTR_COLD;
- virtual void device_add_mconfig(machine_config &config) override;
+ virtual void device_add_mconfig(machine_config &config) override ATTR_COLD;
void access_update();
@@ -89,9 +89,9 @@ public:
protected:
// device-level overrides
- virtual void device_start() override;
+ virtual void device_start() override ATTR_COLD;
- virtual void device_add_mconfig(machine_config &config) override;
+ virtual void device_add_mconfig(machine_config &config) override ATTR_COLD;
private:
required_device<sns_bsx_cart_slot_device> m_slot;
@@ -111,9 +111,9 @@ public:
protected:
// device-level overrides
- virtual void device_start() override;
+ virtual void device_start() override ATTR_COLD;
- virtual void device_add_mconfig(machine_config &config) override;
+ virtual void device_add_mconfig(machine_config &config) override ATTR_COLD;
private:
required_device<sns_bsx_cart_slot_device> m_slot;
@@ -138,8 +138,8 @@ public:
protected:
// device-level overrides
- virtual void device_start() override;
- virtual void device_reset() override;
+ virtual void device_start() override ATTR_COLD;
+ virtual void device_reset() override ATTR_COLD;
// flash regs
uint32_t m_command;
diff --git a/src/devices/bus/snes/event.cpp b/src/devices/bus/snes/event.cpp
index 3591a2a679a..fe9a367e54d 100644
--- a/src/devices/bus/snes/event.cpp
+++ b/src/devices/bus/snes/event.cpp
@@ -4,7 +4,7 @@
Super NES/Famicom Event cartridges emulation (for SNES/SFC)
- TODO: figure out how the Test Mode switch works...
+ TODO: Figure out how the Test Mode switch works
***********************************************************************************************************/
@@ -38,7 +38,7 @@ void sns_pfest94_device::device_start()
{
m_dsp_prg.resize(0x2000/sizeof(uint32_t));
m_dsp_data.resize(0x800/sizeof(uint16_t));
- pfest94_timer = timer_alloc(TIMER_EVENT);
+ pfest94_timer = timer_alloc(FUNC(sns_pfest94_device::event_tick), this);
pfest94_timer->reset();
save_item(NAME(m_base_bank));
@@ -102,7 +102,7 @@ uint8_t sns_pfest94_device::read_h(offs_t offset)
}
-// these are used for two diff effects: both to select game from menu and to access the DSP when running SMK!
+// these are used both to select game from the menu and to access the DSP when running Super Mario Kart.
uint8_t sns_pfest94_device::chip_read(offs_t offset)
{
if (offset & 0x8000)
@@ -113,8 +113,10 @@ uint8_t sns_pfest94_device::chip_read(offs_t offset)
else
{
// DSP access
- offset &= 0x1fff;
- return m_upd7725->snesdsp_read(offset < 0x1000);
+ if (BIT(offset, 12))
+ return m_upd7725->status_r();
+ else
+ return m_upd7725->data_r();
}
}
@@ -151,8 +153,10 @@ void sns_pfest94_device::chip_write(offs_t offset, uint8_t data)
else
{
// DSP access
- offset &= 0x1fff;
- m_upd7725->snesdsp_write(offset < 0x1000, data);
+ if (BIT(~offset, 12))
+ m_upd7725->data_w(data);
+ else
+ logerror("%s: Writing DSP status to %02x, ignored", machine().describe_context(), data);
}
}
@@ -166,6 +170,7 @@ inline uint32_t get_prg(uint8_t *CPU, uint32_t addr)
{
return ((CPU[addr * 4] << 24) | (CPU[addr * 4 + 1] << 16) | (CPU[addr * 4 + 2] << 8) | 0x00);
}
+
inline uint16_t get_data(uint8_t *CPU, uint32_t addr)
{
return ((CPU[addr * 2] << 8) | CPU[addr * 2 + 1]);
@@ -173,10 +178,8 @@ inline uint16_t get_data(uint8_t *CPU, uint32_t addr)
void sns_pfest94_device::speedup_addon_bios_access()
{
- m_upd7725->space(AS_PROGRAM).install_read_bank(0x0000, 0x07ff, "dsp_prg");
- m_upd7725->space(AS_DATA).install_read_bank(0x0000, 0x03ff, "dsp_data");
- membank("dsp_prg")->set_base(&m_dsp_prg[0]);
- membank("dsp_data")->set_base(&m_dsp_data[0]);
+ m_upd7725->space(AS_PROGRAM).install_rom(0x0000, 0x07ff, &m_dsp_prg[0]);
+ m_upd7725->space(AS_DATA).install_rom(0x0000, 0x03ff, &m_dsp_data[0]);
// copy data in the correct format
for (int x = 0; x < 0x800; x++)
m_dsp_prg[x] = (m_bios[x * 4] << 24) | (m_bios[x * 4 + 1] << 16) | (m_bios[x * 4 + 2] << 8) | 0x00;
@@ -185,7 +188,7 @@ void sns_pfest94_device::speedup_addon_bios_access()
}
-// DSP dump contains prg at offset 0 and data at offset 0x2000
+// DSP dump contains program code at offset 0 and data at offset 0x2000
uint32_t sns_pfest94_device::necdsp_prg_r(offs_t offset)
{
return get_prg(&m_bios[0], offset);
@@ -264,20 +267,12 @@ ioport_constructor sns_pfest94_device::device_input_ports() const
return INPUT_PORTS_NAME( pfest94_dsw );
}
-
-//-------------------------------------------------
-// device_timer - handler timer events
-//-------------------------------------------------
-
-void sns_pfest94_device::device_timer(emu_timer &timer, device_timer_id id, int param, void *ptr)
+TIMER_CALLBACK_MEMBER(sns_pfest94_device::event_tick)
{
- if (id == TIMER_EVENT)
+ if (!m_count)
{
- if (!m_count)
- {
- m_status |= 2;
- pfest94_timer->reset();
- }
- m_count--;
+ m_status |= 2;
+ pfest94_timer->reset();
}
+ m_count--;
}
diff --git a/src/devices/bus/snes/event.h b/src/devices/bus/snes/event.h
index dedd18f921a..b37052be814 100644
--- a/src/devices/bus/snes/event.h
+++ b/src/devices/bus/snes/event.h
@@ -19,15 +19,12 @@ public:
sns_pfest94_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
protected:
- static constexpr device_timer_id TIMER_EVENT = 0;
-
// device-level overrides
- virtual void device_start() override;
- virtual void device_reset() override;
+ virtual void device_start() override ATTR_COLD;
+ virtual void device_reset() override ATTR_COLD;
- virtual void device_timer(emu_timer &timer, device_timer_id id, int param, void *ptr) override;
- virtual void device_add_mconfig(machine_config &config) override;
- virtual ioport_constructor device_input_ports() const override;
+ virtual void device_add_mconfig(machine_config &config) override ATTR_COLD;
+ virtual ioport_constructor device_input_ports() const override ATTR_COLD;
virtual void speedup_addon_bios_access() override;
@@ -40,6 +37,8 @@ protected:
virtual uint32_t necdsp_prg_r(offs_t offset);
virtual uint16_t necdsp_data_r(offs_t offset);
+ TIMER_CALLBACK_MEMBER(event_tick);
+
private:
required_device<upd7725_device> m_upd7725;
required_ioport m_dsw;
@@ -54,8 +53,8 @@ private:
emu_timer *pfest94_timer;
- void dsp_data_map_lorom(address_map &map);
- void dsp_prg_map_lorom(address_map &map);
+ void dsp_data_map_lorom(address_map &map) ATTR_COLD;
+ void dsp_prg_map_lorom(address_map &map) ATTR_COLD;
};
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..9f2c6415c6a
--- /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 ATTR_COLD;
+ virtual void device_reset() override ATTR_COLD;
+ virtual void device_add_mconfig(machine_config &config) override ATTR_COLD;
+ virtual const tiny_rom_entry *device_rom_region() const override ATTR_COLD;
+};
+
+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 ATTR_COLD;
+ virtual void device_reset() override ATTR_COLD;
+ virtual void device_add_mconfig(machine_config &config) override ATTR_COLD;
+ virtual const tiny_rom_entry *device_rom_region() const override ATTR_COLD;
+};
+
+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 ATTR_COLD;
+ virtual void device_reset() override ATTR_COLD;
+ virtual void device_add_mconfig(machine_config &config) override ATTR_COLD;
+ virtual const tiny_rom_entry *device_rom_region() const override ATTR_COLD;
+};
+
+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 ATTR_COLD;
+ virtual void device_reset() override ATTR_COLD;
+ virtual void device_add_mconfig(machine_config &config) override ATTR_COLD;
+ virtual const tiny_rom_entry *device_rom_region() const override ATTR_COLD;
+};
+
+
+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/rom.cpp b/src/devices/bus/snes/rom.cpp
index 3308808a008..0bfa07ac6af 100644
--- a/src/devices/bus/snes/rom.cpp
+++ b/src/devices/bus/snes/rom.cpp
@@ -20,7 +20,7 @@ DEFINE_DEVICE_TYPE(SNS_LOROM_OBC1, sns_rom_obc1_device, "sns_rom_obc1",
// LoROM pirate carts with protection
DEFINE_DEVICE_TYPE(SNS_LOROM_POKEMON, sns_rom_pokemon_device, "sns_rom_pokemon", "SNES Pirate Carts with Protection")
DEFINE_DEVICE_TYPE(SNS_LOROM_TEKKEN2, sns_rom_tekken2_device, "sns_rom_tekken2", "SNES Tekken 2")
-DEFINE_DEVICE_TYPE(SNS_LOROM_SOULBLAD, sns_rom_soulblad_device, "sns_rom_soulblad", "SNES Sound Blade")
+DEFINE_DEVICE_TYPE(SNS_LOROM_SOULBLAD, sns_rom_soulblad_device, "sns_rom_soulblad", "SNES Soul Blade")
DEFINE_DEVICE_TYPE(SNS_LOROM_BANANA, sns_rom_banana_device, "sns_rom_banana", "SNES Banana de Pijamas")
DEFINE_DEVICE_TYPE(SNS_LOROM_BUGSLIFE, sns_rom_bugs_device, "sns_rom_bugslife", "SNES A Bug's Life")
// LoROM pirate multicarts
@@ -371,29 +371,13 @@ void sns_rom_tekken2_device::chip_write(offs_t offset, uint8_t data)
}
-// Soul Blade: Adresses $xxx0-$xxx3 in banks $80-$bf always read $55, $0f, $aa, $f0.
+// Soul Blade: Addresses $xxx0-$xxx3 in banks $80-$bf always read $55, $0f, $aa, $f0.
// Banks $c0-$ff return open bus.
uint8_t sns_rom_soulblad_device::chip_read(offs_t offset)
{
- uint8_t value;
- offset &= 3;
- switch (offset)
- {
- case 0:
- default:
- value = 0x55;
- break;
- case 1:
- value = 0x0f;
- break;
- case 2:
- value = 0xaa;
- break;
- case 3:
- value = 0xf0;
- break;
- }
- return value;
+ static constexpr uint8_t lut[4] = { 0x55, 0x0f, 0xaa, 0xf0 };
+
+ return lut[offset & 3];
}
// Multicart pirate banking emulation
diff --git a/src/devices/bus/snes/rom.h b/src/devices/bus/snes/rom.h
index d2a09b774c1..8901846e3fe 100644
--- a/src/devices/bus/snes/rom.h
+++ b/src/devices/bus/snes/rom.h
@@ -24,7 +24,7 @@ protected:
sns_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_start() override ATTR_COLD;
};
// ======================> sns_rom_obc1_device
@@ -41,8 +41,8 @@ public:
protected:
// device-level overrides
- virtual void device_start() override;
- virtual void device_reset() override;
+ virtual void device_start() override ATTR_COLD;
+ virtual void device_reset() override ATTR_COLD;
int m_address;
int m_offset;
@@ -66,8 +66,8 @@ public:
protected:
// device-level overrides
- virtual void device_start() override;
- virtual void device_reset() override;
+ virtual void device_start() override ATTR_COLD;
+ virtual void device_reset() override ATTR_COLD;
uint8_t m_latch;
};
@@ -86,8 +86,8 @@ public:
protected:
// device-level overrides
- virtual void device_start() override;
- virtual void device_reset() override;
+ virtual void device_start() override ATTR_COLD;
+ virtual void device_reset() override ATTR_COLD;
void update_prot(uint32_t offset);
@@ -123,8 +123,8 @@ public:
protected:
// device-level overrides
- virtual void device_start() override;
- virtual void device_reset() override;
+ virtual void device_start() override ATTR_COLD;
+ virtual void device_reset() override ATTR_COLD;
uint8_t m_base_bank;
};
@@ -144,8 +144,8 @@ public:
protected:
// device-level overrides
- virtual void device_start() override;
- virtual void device_reset() override;
+ virtual void device_start() override ATTR_COLD;
+ virtual void device_reset() override ATTR_COLD;
uint8_t m_base_bank;
};
@@ -165,7 +165,7 @@ public:
protected:
// device-level overrides
- virtual void device_start() override;
+ virtual void device_start() override ATTR_COLD;
uint8_t m_base_bank;
};
@@ -204,8 +204,8 @@ public:
protected:
// device-level overrides
- virtual void device_start() override;
- virtual void device_reset() override;
+ virtual void device_start() override ATTR_COLD;
+ virtual void device_reset() override ATTR_COLD;
uint8_t m_latch[0x800];
};
diff --git a/src/devices/bus/snes/rom21.cpp b/src/devices/bus/snes/rom21.cpp
index 8cc1f6fddb6..9bf43d05894 100644
--- a/src/devices/bus/snes/rom21.cpp
+++ b/src/devices/bus/snes/rom21.cpp
@@ -128,8 +128,8 @@ uint8_t sns_rom21_srtc_device::srtc_weekday( uint32_t year, uint32_t month, uint
uint32_t sum = 0; // Number of days passed since epoch
year = std::max(1900U, year);
- month = std::max(1U, std::min(12U, month));
- day = std::max(1U, std::min(31U, day));
+ month = std::clamp(month, 1U, 12U);
+ day = std::clamp(day, 1U, 31U);
while (y < year)
{
diff --git a/src/devices/bus/snes/rom21.h b/src/devices/bus/snes/rom21.h
index fb9b0b6c65a..5614d19ee8f 100644
--- a/src/devices/bus/snes/rom21.h
+++ b/src/devices/bus/snes/rom21.h
@@ -25,8 +25,8 @@ protected:
sns_rom21_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_start() override ATTR_COLD;
+ virtual void device_reset() override ATTR_COLD;
};
// ======================> sns_rom21_srtc_device
@@ -52,8 +52,8 @@ protected:
};
// device-level overrides
- virtual void device_start() override;
- virtual void device_reset() override;
+ virtual void device_start() override ATTR_COLD;
+ virtual void device_reset() override ATTR_COLD;
void update_time();
uint8_t srtc_weekday(uint32_t year, uint32_t month, uint32_t day);
diff --git a/src/devices/bus/snes/sa1.cpp b/src/devices/bus/snes/sa1.cpp
index 487f176fd86..65ff3d5b251 100644
--- a/src/devices/bus/snes/sa1.cpp
+++ b/src/devices/bus/snes/sa1.cpp
@@ -5,17 +5,17 @@
SA-1 add-on chip emulation (for SNES/SFC)
Note:
- - SA-1 register description below is based on no$cash docs.
- - about bankswitch handling: no matter what is ROM size, at loading the ROM is mirrored up to 8MB and a
+ - SA-1 register description below is based on nocash docs.
+ - Bankswitch handling: no matter what ROM size is used, at loading the ROM is mirrored up to 8MB and a
rom_bank_map[0x100] array is built as a lookup table for 256x32KB banks filling the 8MB accessible ROM
- area; this allows to handle any 0-7 value written to CXB/DXB/EXB/FXB SA-1 registers without any masking!
- - about BWRAM "bitmap mode": in 2bits mode
+ area; this allows any value from 0-7 being written to CXB/DXB/EXB/FXB SA-1 registers without any masking.
+ - about BWRAM "bitmap mode": in 2-bit mode
600000h.Bit0-1 mirrors to 400000h.Bit0-1
600001h.Bit0-1 mirrors to 400000h.Bit2-3
600002h.Bit0-1 mirrors to 400000h.Bit4-5
600003h.Bit0-1 mirrors to 400000h.Bit6-7
...
- in 4bits mode
+ in 4-bit mode
600000h.Bit0-3 mirrors to 400000h.Bit0-3
600001h.Bit0-3 mirrors to 400000h.Bit4-7
600002h.Bit0-3 mirrors to 400001h.Bit0-3
@@ -24,9 +24,10 @@
to handle the separate modes, bitmap accesses go to offset + 0x100000
TODO:
- - test case for BWRAM & IRAM write protect (bsnes does not seem to ever protect either, so it's not implemented
+ - Test case for BWRAM write protect (bsnes does not seem to protect either, so it's not implemented
for the moment)
- - almost everything CPU related!
+ - Almost everything CPU related
+ - Bus conflicts
Compatibility:
asahishi: plays OK
@@ -34,13 +35,13 @@
derbyjo2: hangs going into game
dbzhypd, dbzhypdj: plays OK
habumeij: boots, goes into game, on-screen timer counts down after SA-1 is enabled but controls aren't responsive
- haruaug3a, pebble, haruaug3: uses SA-1 DMA
+ haruaug3a, pebble, haruaug3: plays OK
itoibass: boots, some missing gfx
jikkparo: plays OK
jl96drem: plays OK
jumpind: boots and runs, uses SA-1 normal DMA only but has corrupt gfx
kakinoki: S-CPU crashes after pressing start
- kirby3j, kirby3: uses SA-1 DMA
+ kirby3j, kirby3: plays OK
kirbysdb, kirbyss, kirbyfun, kirbysd, kirbysda: plays OK
marvelou: plays OK, uses SA-1 normal DMA only but has corrupt gfx
miniyonk: plays OK
@@ -55,13 +56,13 @@
shinshog: plays OK
shogisai: plays OK
shogisa2: plays OK
- smrpgj, smrpg: needs SA-1 character conversion for level up Bonus Chance (possible to get past now)
+ smrpgj, smrpg: plays OK
srobotg: some corrupt in-game GFX, may be SNES rendering errors
sshogi3: plays OK
taikyoid: plays OK
takemiya: plays OK
- [Note: for Igo & Shougi games, "plays OK" means you can get ingame and the CPU replies to your moves... subtle bugs
- might indeed exist...]
+ Note: for Igo & Shougi games, "plays OK" means you can get ingame and the CPU replies to your moves; subtle bugs
+ might indeed exist.
***********************************************************************************************************/
@@ -85,61 +86,121 @@
DEFINE_DEVICE_TYPE(SNS_LOROM_SA1, sns_sa1_device, "sns_rom_sa1", "SNES Cart + SA-1")
-sns_sa1_device::sns_sa1_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
+sns_sa1_device::sns_sa1_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock)
: device_t(mconfig, SNS_LOROM_SA1, tag, owner, clock)
, device_sns_cart_interface(mconfig, *this)
, m_sa1(*this, "sa1cpu")
- , m_sa1_ctrl(0), m_scpu_sie(0), m_sa1_reset(0), m_sa1_nmi(0), m_sa1_irq(0), m_scpu_ctrl(0), m_sa1_sie(0)
+ , m_sa1_timer(nullptr)
+ , m_sa1_ctrl(0), m_sa1_reset_flag(true), m_scpu_sie(0), m_sa1_reset_vector(0), m_sa1_nmi_vector(0), m_sa1_irq_vector(0), m_scpu_ctrl(0), m_sa1_sie(0)
, m_irq_vector(0), m_nmi_vector(0)
+ , m_timer_ctrl(0)
+ , m_hpos(0), m_vpos(0)
, m_hcount(0), m_vcount(0)
- , m_bank_c_hi(0), m_bank_c_rom(0), m_bank_d_hi(0), m_bank_d_rom(0), m_bank_e_hi(0), m_bank_e_rom(0), m_bank_f_hi(0), m_bank_f_rom(0)
- , m_bwram_snes(0), m_bwram_sa1(0), m_bwram_sa1_source(0), m_bwram_sa1_format(0), m_bwram_write_snes(0), m_bwram_write_sa1(0), m_bwpa_sa1(0)
+ , m_bank_hi{false,false,false,false}, m_bank_rom{0,0,0,0}
+ , m_bwram_snes(0), m_bwram_sa1(0), m_bwram_sa1_source(false), m_bwram_sa1_format(false), m_bwram_write_snes(false), m_bwram_write_sa1(false), m_bwpa_sa1(0)
, m_iram_write_snes(0), m_iram_write_sa1(0)
, m_dma_ctrl(0), m_dma_ccparam(0), m_src_addr(0), m_dst_addr(0), m_dma_cnt(0)
, m_math_ctlr(0), m_math_overflow(0), m_math_a(0), m_math_b(0), m_math_res(0)
- , m_vda(0), m_vbit(0), m_vlen(0), m_drm(0), m_scpu_flags(0), m_sa1_flags(0), m_hcr(0), m_vcr(0)
+ , m_vda(0), m_vbit(0), m_vlen(0), m_drm(false), m_scpu_flags(0), m_sa1_flags(0), m_hcr(0), m_vcr(0)
+ , m_cconv1_dma_active(false), m_cconv2_line(0)
{
}
void sns_sa1_device::device_start()
{
+ m_internal_ram = make_unique_clear<u8[]>(0x800);
+ m_sa1_timer = timer_alloc(FUNC(sns_sa1_device::timer_tick), this);
+
m_scpu_ctrl = 0;
m_nmi_vector = 0;
- m_bank_c_hi = 0;
- m_bank_c_rom = 0;
+ m_bank_hi[0] = false;
+ m_bank_rom[0] = 0;
+
+ save_pointer(NAME(m_internal_ram), 0x800);
+ save_item(NAME(m_sa1_ctrl));
+ save_item(NAME(m_sa1_reset_flag));
+ save_item(NAME(m_scpu_sie));
+ save_item(NAME(m_sa1_reset_vector));
+ save_item(NAME(m_sa1_nmi_vector));
+ save_item(NAME(m_sa1_irq_vector));
+ save_item(NAME(m_scpu_ctrl));
+ save_item(NAME(m_sa1_sie));
+ save_item(NAME(m_irq_vector));
+ save_item(NAME(m_nmi_vector));
+ save_item(NAME(m_timer_ctrl));
+ save_item(NAME(m_hpos));
+ save_item(NAME(m_vpos));
+ save_item(NAME(m_hcount));
+ save_item(NAME(m_vcount));
+ save_item(NAME(m_bank_hi));
+ save_item(NAME(m_bank_rom));
+ save_item(NAME(m_bwram_snes));
+ save_item(NAME(m_bwram_sa1));
+ save_item(NAME(m_bwram_sa1_source));
+ save_item(NAME(m_bwram_sa1_format));
+ save_item(NAME(m_bwram_write_snes));
+ save_item(NAME(m_bwram_write_sa1));
+ save_item(NAME(m_bwpa_sa1));
+ save_item(NAME(m_iram_write_snes));
+ save_item(NAME(m_iram_write_sa1));
+ save_item(NAME(m_dma_ctrl));
+ save_item(NAME(m_dma_ccparam));
+ save_item(NAME(m_src_addr));
+ save_item(NAME(m_dst_addr));
+ save_item(NAME(m_dma_cnt));
+ save_item(NAME(m_brf_reg));
+ save_item(NAME(m_math_ctlr));
+ save_item(NAME(m_math_overflow));
+ save_item(NAME(m_math_a));
+ save_item(NAME(m_math_b));
+ save_item(NAME(m_math_res));
+ save_item(NAME(m_vda));
+ save_item(NAME(m_vbit));
+ save_item(NAME(m_vlen));
+ save_item(NAME(m_drm));
+ save_item(NAME(m_scpu_flags));
+ save_item(NAME(m_sa1_flags));
+ save_item(NAME(m_hcr));
+ save_item(NAME(m_vcr));
+ save_item(NAME(m_cconv1_dma_active));
+ save_item(NAME(m_cconv2_line));
}
void sns_sa1_device::device_reset()
{
- memset(m_internal_ram, 0, sizeof(m_internal_ram));
+ std::fill_n(&m_internal_ram[0], 0x800, 0);
m_sa1_ctrl = 0x20;
+ m_sa1_reset_flag = true;
m_scpu_ctrl = 0;
m_irq_vector = 0;
m_nmi_vector = 0;
+ m_timer_ctrl = 0;
+ m_hpos = 0;
+ m_vpos = 0;
m_hcount = 0;
m_vcount = 0;
- m_bank_c_hi = 0;
- m_bank_c_rom = 0;
- m_bank_d_hi = 0;
- m_bank_d_rom = 1;
- m_bank_e_hi = 0;
- m_bank_e_rom = 2;
- m_bank_f_hi = 0;
- m_bank_f_rom = 3;
+ m_bank_hi[0] = false;
+ m_bank_hi[1] = false;
+ m_bank_hi[2] = false;
+ m_bank_hi[3] = false;
+ m_bank_rom[0] = 0;
+ m_bank_rom[1] = 1;
+ m_bank_rom[2] = 2;
+ m_bank_rom[3] = 3;
m_bwram_snes = 0;
m_bwram_sa1 = 0;
- m_bwram_sa1_source = 0;
- m_bwram_sa1_format = 0;
- m_bwram_write_snes = 1;
- m_bwram_write_sa1 = 1;
- m_bwpa_sa1 = 0x0f;
- m_iram_write_snes = 1;
- m_iram_write_sa1 = 1;
+ m_bwram_sa1_source = false;
+ m_bwram_sa1_format = false;
+ m_bwram_write_snes = false;
+ m_bwram_write_sa1 = false;
+ m_bwpa_sa1 = 0x100 << 0x0f;
+ m_iram_write_snes = 0;
+ m_iram_write_sa1 = 0;
m_src_addr = 0;
m_dst_addr = 0;
- memset(m_brf_reg, 0, sizeof(m_brf_reg));
+ std::fill(std::begin(m_brf_reg), std::end(m_brf_reg), 0);
m_math_ctlr = 0;
m_math_overflow = 0;
m_math_a = 0;
@@ -148,7 +209,7 @@ void sns_sa1_device::device_reset()
m_vda = 0;
m_vbit = 0;
m_vlen = 0;
- m_drm = 0;
+ m_drm = false;
m_hcr = 0;
m_vcr = 0;
m_scpu_sie = m_sa1_sie = 0;
@@ -156,11 +217,63 @@ void sns_sa1_device::device_reset()
m_dma_ctrl = 0;
m_dma_ccparam = 0;
m_dma_cnt = 0;
+ m_cconv1_dma_active = false;
+ m_cconv2_line = 0;
- // sa-1 CPU starts out not running?
+ // SA-1 CPU starts out not running
m_sa1->set_input_line(INPUT_LINE_HALT, ASSERT_LINE);
+ // Timer is run in sync with the CPU
+ m_sa1_timer->adjust(m_sa1->clocks_to_attotime(2), 0, m_sa1->clocks_to_attotime(2));
}
+TIMER_CALLBACK_MEMBER(sns_sa1_device::timer_tick)
+{
+ if (TMC_HVSELB())
+ {
+ // 18 bit Linear timer
+ m_hpos++;
+ m_vpos += m_hpos >> 9;
+ m_hpos &= 0x1ff;
+ m_vpos &= 0x1ff;
+ }
+ else
+ {
+ // H/V timer
+ if (++m_hpos >= 341)
+ {
+ m_hpos = 0;
+ if (++m_vpos >= scanlines_r())
+ m_vpos = 0;
+ }
+ }
+ // send timer IRQ
+ if (TMC_HEN() && TMC_VEN()) // both H and V count enabled
+ {
+ if ((m_hpos == m_hcount) && (m_vpos == m_vcount))
+ {
+ m_sa1_flags |= SA1_IRQ_TIMER;
+ recalc_irqs();
+ }
+ }
+ else if (TMC_HEN()) // H count only
+ {
+ if (m_hpos == m_hcount)
+ {
+ m_sa1_flags |= SA1_IRQ_TIMER;
+ recalc_irqs();
+ }
+ }
+ else if (TMC_VEN()) // V count only
+ {
+ if ((m_hpos == 0) && (m_vpos == m_vcount))
+ {
+ m_sa1_flags |= SA1_IRQ_TIMER;
+ recalc_irqs();
+ }
+ }
+
+ // TODO: Math & DMA timer
+}
/*-------------------------------------------------
mapper specific handlers
@@ -169,31 +282,19 @@ void sns_sa1_device::device_reset()
void sns_sa1_device::recalc_irqs()
{
if (m_scpu_flags & m_scpu_sie & (SCPU_IRQ_SA1|SCPU_IRQ_CHARCONV))
- {
write_irq(ASSERT_LINE);
- }
else
- {
write_irq(CLEAR_LINE);
- }
- if (m_sa1_flags & m_sa1_sie & (SA1_IRQ_SCPU|SA1_IRQ_TIMER|SA1_IRQ_DMA))
- {
+ if ((!sa1_halted()) && (m_sa1_flags & m_sa1_sie & (SA1_IRQ_SCPU|SA1_IRQ_TIMER|SA1_IRQ_DMA)))
m_sa1->set_input_line(G65816_LINE_IRQ, ASSERT_LINE);
- }
else
- {
m_sa1->set_input_line(G65816_LINE_IRQ, CLEAR_LINE);
- }
- if (m_sa1_flags & m_sa1_sie & SA1_NMI_SCPU)
- {
+ if ((!sa1_halted()) && (m_sa1_flags & m_sa1_sie & SA1_NMI_SCPU))
m_sa1->set_input_line(G65816_LINE_NMI, ASSERT_LINE);
- }
else
- {
m_sa1->set_input_line(G65816_LINE_NMI, CLEAR_LINE);
- }
}
@@ -202,17 +303,18 @@ void sns_sa1_device::recalc_irqs()
-------------------------------------------------*/
-// handle this separately to avoid accessing recursively the regs?
+// TODO: Handle this separately to avoid accessing the regs recursively
-uint8_t sns_sa1_device::var_length_read(uint32_t offset)
+u8 sns_sa1_device::var_length_read(offs_t offset)
{
+ // TODO: memory access cycle
// handle 0xffea/0xffeb/0xffee/0xffef
if ((offset & 0xffffe0) == 0x00ffe0)
{
- if (offset == 0xffea && BIT(m_scpu_ctrl, 4)) return (m_nmi_vector >> 0) & 0xff;
- if (offset == 0xffeb && BIT(m_scpu_ctrl, 4)) return (m_nmi_vector >> 8) & 0xff;
- if (offset == 0xffee && BIT(m_scpu_ctrl, 6)) return (m_irq_vector >> 0) & 0xff;
- if (offset == 0xffef && BIT(m_scpu_ctrl, 6)) return (m_irq_vector >> 8) & 0xff;
+ if (offset == 0xffea && SCNT_SNESCPU_NVSW()) return (m_nmi_vector >> 0) & 0xff;
+ if (offset == 0xffeb && SCNT_SNESCPU_NVSW()) return (m_nmi_vector >> 8) & 0xff;
+ if (offset == 0xffee && SCNT_SNESCPU_IVSW()) return (m_irq_vector >> 0) & 0xff;
+ if (offset == 0xffef && SCNT_SNESCPU_IVSW()) return (m_irq_vector >> 8) & 0xff;
}
if ((offset & 0xc08000) == 0x008000) //$00-3f:8000-ffff
@@ -225,10 +327,10 @@ uint8_t sns_sa1_device::var_length_read(uint32_t offset)
return read_h(offset & 0x7fffff);
if ((offset & 0x40e000) == 0x006000) //$00-3f|80-bf:6000-7fff
- return read_bwram((m_bwram_snes * 0x2000) + (offset & 0x1fff));
+ return read_bwram<true>((m_bwram_snes * 0x2000) + (offset & 0x1fff));
if ((offset & 0xf00000) == 0x400000) //$40-4f:0000-ffff
- return read_bwram(offset & 0xfffff);
+ return read_bwram<true>(offset & 0xfffff);
if ((offset & 0x40f800) == 0x000000) //$00-3f|80-bf:0000-07ff
return read_iram(offset);
@@ -241,70 +343,57 @@ uint8_t sns_sa1_device::var_length_read(uint32_t offset)
void sns_sa1_device::dma_transfer()
{
-// printf("DMA src %08x (%d), dst %08x (%d) cnt %d\n", m_src_addr, m_dma_ctrl & 3, m_dst_addr, m_dma_ctrl & 4, m_dma_cnt);
-
while (m_dma_cnt--)
{
- uint8_t data = 0; // open bus?
- uint32_t dma_src = m_src_addr++;
- uint32_t dma_dst = m_dst_addr++;
+ u8 data = 0; // TODO: open bus
+ const u32 dma_src = m_src_addr++;
+ const u32 dma_dst = m_dst_addr++;
// source and destination cannot be the same
// source = { 0=ROM, 1=BWRAM, 2=IRAM }
// destination = { 0=IRAM, 1=BWRAM }
- if ((m_dma_ctrl & 0x03) == 1 && (m_dma_ctrl & 0x04) == 0x04) continue;
- if ((m_dma_ctrl & 0x03) == 2 && (m_dma_ctrl & 0x04) == 0x00) continue;
+ if (((DCNT_SD()) == 1) && (DCNT_DD())) continue;
+ if (((DCNT_SD()) == 2) && (!(DCNT_DD()))) continue;
- switch (m_dma_ctrl & 0x03)
+ int cycle = 1; // 1 cycle per memory access
+ switch (DCNT_SD())
{
case 0: // ROM
- if ((dma_src & 0x408000) == 0x008000 && (dma_src & 0x800000) == 0x000000)
- {
- data = read_l(dma_src & 0x7fffff);
- }
- if ((dma_src & 0x408000) == 0x008000 && (dma_src & 0x800000) == 0x800000)
- {
- data = read_h(dma_src & 0x7fffff);
- }
- if ((dma_src & 0xc00000) == 0xc00000)
- {
- data = read_h(dma_src & 0x7fffff);
- }
+ if (bus_conflict_rom() && (cycle < 2)) // wait 1 cycle if conflict
+ cycle = 2;
+ data = rom_r(dma_src & 0xffffff);
break;
case 1: // BWRAM
- if ((dma_src & 0x40e000) == 0x006000)
- {
- data = read_bwram((m_bwram_sa1 * 0x2000) + (dma_src & 0x1fff));
- }
- if ((dma_src & 0xf00000) == 0x400000)
- {
- data = read_bwram(dma_src & 0xfffff);
- }
+ if (bus_conflict_bwram() && (cycle < 4)) // wait 3 cycle if conflict
+ cycle = 4;
+ else if (cycle < 2)
+ cycle = 2;
+ data = read_bwram<true>(dma_src & 0xfffff);
break;
case 2: // IRAM
+ if (bus_conflict_iram() && (cycle < 3)) // wait 2 cycle if conflict
+ cycle = 3;
data = read_iram(dma_src);
break;
}
- switch (m_dma_ctrl & 0x04)
+ if (DCNT_DD()) // BWRAM
{
- case 0x00: // IRAM
- write_iram(dma_dst, data);
- break;
-
- case 0x04: // BWRAM
- if ((dma_dst & 0x40e000) == 0x006000)
- {
- write_bwram((m_bwram_sa1 * 0x2000) + (dma_dst & 0x1fff), data);
- }
- if ((dma_dst & 0xf00000) == 0x400000)
- {
- write_bwram(dma_dst & 0xfffff, data);
- }
- break;
+ if (bus_conflict_bwram() && (cycle < 4)) // wait 3 cycle if conflict
+ cycle = 4;
+ else if (cycle < 2)
+ cycle = 2;
+ write_bwram(dma_dst & 0xfffff, data);
+ }
+ else // IRAM
+ {
+ if (bus_conflict_iram() && (cycle < 3)) // wait 2 cycle if conflict
+ cycle = 3;
+ write_iram(dma_dst, data);
}
+ m_sa1->adjust_icount(-cycle); // progress
}
m_sa1_flags |= SA1_IRQ_DMA;
@@ -313,35 +402,75 @@ void sns_sa1_device::dma_transfer()
void sns_sa1_device::dma_cctype1_transfer()
{
+ m_cconv1_dma_active = true;
m_scpu_flags |= SCPU_IRQ_CHARCONV;
recalc_irqs();
}
void sns_sa1_device::dma_cctype2_transfer()
{
+ const u8 bank = BIT(m_cconv2_line, 0) << 3;
+ const u8 bpp = 2 << (2 - m_dma_cconv_bits);
+ const u32 tx = BIT(m_cconv2_line, 3) << (6 - m_dma_cconv_bits);
+ const u32 ty = (BIT(m_cconv2_line, 0, 3) << 1);
+ const u32 dst_addr = (m_dst_addr & ~((1 << (7 - m_dma_cconv_bits)) - 1)) + tx + ty;
+
+ // TODO: memory access/process cycle
+ for (u8 bit = 0; bit < bpp; bit++)
+ {
+ u8 byte = 0;
+ const offs_t plane = BIT(bit, 0) | (BIT(bit, 1, 2) << 4);
+ for (u8 x = 0; x < 8; x++)
+ byte |= BIT(m_brf_reg[bank | x], bit) << (7 - x);
+
+ write_iram(dst_addr + plane, byte);
+ }
+
+ m_cconv2_line = (m_cconv2_line + 1) & 0xf;
}
-uint8_t sns_sa1_device::read_regs(uint32_t offset)
+u8 sns_sa1_device::host_r(offs_t offset)
{
- uint8_t value = 0xff;
+ u8 value = read_open_bus();
offset &= 0x1ff; // $2200 + offset gives the reg value to compare with docs
switch (offset)
{
case 0x100:
// S-CPU Flag Read
- value = (m_scpu_ctrl & 0x0f) | m_scpu_flags;
+ value = SCNT_CMEG() | m_scpu_flags;
+ break;
+ case 0x10e:
+ // SNES VC Version Code Register (R)
+ // value = read_open_bus(); // verified
break;
+ default:
+ logerror("S-CPU Read access to an unmapped reg (%x)", offset);
+ break;
+ }
+ return value;
+}
+
+u8 sns_sa1_device::read_regs(offs_t offset)
+{
+ u8 value = 0xff; // unverified
+ offset &= 0x1ff; // $2200 + offset gives the reg value to compare with docs
+
+ switch (offset)
+ {
case 0x101:
// SA-1 Flag Read
- value = (m_sa1_ctrl & 0x0f) | m_sa1_flags;
+ value = CCNT_SMEG() | m_sa1_flags;
break;
case 0x102:
// H-Count Read Low
- //latch counters
- m_hcr = m_hcount >> 2;
- m_vcr = m_vcount;
- //then return h-count
+ if (!machine().side_effects_disabled())
+ {
+ // latch counters
+ m_hcr = m_hpos;
+ m_vcr = m_vpos;
+ }
+ // return h-count
value = (m_hcr >> 0) & 0xff;
break;
case 0x103:
@@ -357,34 +486,33 @@ uint8_t sns_sa1_device::read_regs(uint32_t offset)
value = (m_vcr >> 8) & 0xff;
break;
case 0x106:
- // Math Result bits0-7
- value = (uint64_t)(m_math_res >> 0) & 0xff;
+ // Math Result bits 0-7
+ value = (u64)(m_math_res >> 0) & 0xff;
break;
case 0x107:
- // Math Result bits8-15
- value = (uint64_t)(m_math_res >> 8) & 0xff;
+ // Math Result bits 8-15
+ value = (u64)(m_math_res >> 8) & 0xff;
break;
case 0x108:
- // Math Result bits16-23
- value = (uint64_t)(m_math_res >> 16) & 0xff;
+ // Math Result bits 16-23
+ value = (u64)(m_math_res >> 16) & 0xff;
break;
case 0x109:
- // Math Result bits24-31
- value = (uint64_t)(m_math_res >> 24) & 0xff;
+ // Math Result bits 24-31
+ value = (u64)(m_math_res >> 24) & 0xff;
break;
case 0x10a:
- // Math Result bits32-39
- value = (uint64_t)(m_math_res >> 32) & 0xff;
+ // Math Result bits 32-39
+ value = (u64)(m_math_res >> 32) & 0xff;
break;
case 0x10b:
- // Math Overflow (above 40bit result)
+ // Math Overflow (above 40-bit result)
value = m_math_overflow;
break;
case 0x10c:
// Var-Length Read Port Low
{
- uint32_t data = (var_length_read(m_vda + 0) << 0) | (var_length_read(m_vda + 1) << 8)
- | (var_length_read(m_vda + 2) << 16);
+ u32 data = (var_length_read(m_vda + 0) << 0) | (var_length_read(m_vda + 1) << 8) | (var_length_read(m_vda + 2) << 16);
data >>= m_vbit;
value = (data >> 0) & 0xff;
}
@@ -392,24 +520,23 @@ uint8_t sns_sa1_device::read_regs(uint32_t offset)
case 0x10d:
// Var-Length Read Port High
{
- uint32_t data = (var_length_read(m_vda + 0) << 0) | (var_length_read(m_vda + 1) << 8)
- | (var_length_read(m_vda + 2) << 16);
+ u32 data = (var_length_read(m_vda + 0) << 0) | (var_length_read(m_vda + 1) << 8) | (var_length_read(m_vda + 2) << 16);
data >>= m_vbit;
- if (m_drm == 1)
+ if (!machine().side_effects_disabled())
{
- //auto-increment mode
- m_vbit += m_vlen;
- m_vda += (m_vbit >> 3);
- m_vbit &= 7;
+ if (m_drm)
+ {
+ // auto-increment mode
+ m_vbit += m_vlen;
+ m_vda += (m_vbit >> 3);
+ m_vbit &= 7;
+ }
}
value = (data >> 8) & 0xff;
}
break;
- case 0x10e:
- // SNES VC Version Code Register (R)
- break;
default:
logerror("SA-1 Read access to an unmapped reg (%x)", offset);
break;
@@ -417,7 +544,7 @@ uint8_t sns_sa1_device::read_regs(uint32_t offset)
return value;
}
-void sns_sa1_device::write_regs(uint32_t offset, uint8_t data)
+void sns_sa1_device::host_w(offs_t offset, u8 data)
{
offset &= 0x1ff; // $2200 + offset gives the reg value to compare with docs
@@ -425,152 +552,197 @@ void sns_sa1_device::write_regs(uint32_t offset, uint8_t data)
{
case 0x000:
// SA-1 control flags
-// printf("%02x to SA-1 control\n", data);
- if ((BIT(data, 5)) && !(BIT(m_sa1_ctrl, 5)))
+ if (CCNT_SA1_CPU_RDYB() && BIT(data, 5)) // Pull up reset pin
+ m_sa1_reset_flag = true;
+
+ if ((BIT(data, 5, 2) != 0) && (BIT(m_sa1_ctrl, 5, 2) == 0))
{
-// printf("Engaging SA-1 reset\n");
m_sa1->set_input_line(INPUT_LINE_HALT, ASSERT_LINE);
+ if (BIT(data, 5)) // Pull up reset pin
+ m_sa1_reset_flag = true;
}
- else if (!(BIT(data, 5)) && (BIT(m_sa1_ctrl, 5)))
+ else if ((BIT(data, 5, 2) == 0) && (BIT(m_sa1_ctrl, 5, 2) != 0))
{
-// printf("Releasing SA-1 reset\n");
m_sa1->set_input_line(INPUT_LINE_HALT, CLEAR_LINE);
- m_sa1->set_input_line(INPUT_LINE_RESET, ASSERT_LINE);
- m_sa1->set_input_line(INPUT_LINE_RESET, CLEAR_LINE);
+ if (m_sa1_reset_flag && (!BIT(data, 5)))
+ {
+ m_sa1->set_input_line(INPUT_LINE_RESET, ASSERT_LINE);
+ m_sa1->set_input_line(INPUT_LINE_RESET, CLEAR_LINE);
+ m_sa1_reset_flag = false;
+ }
}
m_sa1_ctrl = data;
- // message to S-CPU
- m_scpu_ctrl &= 0xf0;
- m_scpu_ctrl |= (data & 0x0f);
-
- if (BIT(m_sa1_ctrl, 7))
- {
+ if (CCNT_SA1_CPU_IRQ())
m_sa1_flags |= SA1_IRQ_SCPU;
- }
- if (BIT(m_sa1_ctrl, 4))
- {
+
+ if (CCNT_SA1_CPU_NMI())
m_sa1_flags |= SA1_NMI_SCPU;
- }
+
recalc_irqs();
break;
case 0x001:
- // SNES SIE 00h SNES CPU Int Enable (W)
+ // SNES CPU Int Enable
m_scpu_sie = data;
-// printf("S-CPU IE = %02x\n", data);
recalc_irqs();
break;
case 0x002:
- // SNES SIC 00h SNES CPU Int Clear (W)
+ // SNES CPU Int Clear
if (BIT(data, 7)) // ack IRQ from SA-1
- {
m_scpu_flags &= ~SCPU_IRQ_SA1;
- }
+
if (BIT(data, 5)) // ack character conversion IRQ
- {
m_scpu_flags &= ~SCPU_IRQ_CHARCONV;
- }
+
recalc_irqs();
break;
case 0x003:
- // SNES CRV - SA-1 CPU Reset Vector Lsb (W)
- m_sa1_reset &= 0xff00;
- m_sa1_reset |= data;
+ // SA-1 CPU Reset Vector LSB
+ m_sa1_reset_vector &= 0xff00;
+ m_sa1_reset_vector |= data;
break;
case 0x004:
- // SNES CRV - SA-1 CPU Reset Vector Msb (W)
- m_sa1_reset &= 0x00ff;
- m_sa1_reset |= (data<<8);
+ // SA-1 CPU Reset Vector MSB
+ m_sa1_reset_vector &= 0x00ff;
+ m_sa1_reset_vector |= (data<<8);
break;
case 0x005:
- // SNES CNV - SA-1 CPU NMI Vector Lsb (W)
- m_sa1_nmi &= 0xff00;
- m_sa1_nmi |= data;
+ // SA-1 CPU NMI Vector LSB
+ m_sa1_nmi_vector &= 0xff00;
+ m_sa1_nmi_vector |= data;
break;
case 0x006:
- // SNES CNV - SA-1 CPU NMI Vector Msb (W)
- m_sa1_nmi &= 0x00ff;
- m_sa1_nmi |= (data<<8);
+ // SA-1 CPU NMI Vector MSB
+ m_sa1_nmi_vector &= 0x00ff;
+ m_sa1_nmi_vector |= (data<<8);
break;
case 0x007:
- // SNES CIV - SA-1 CPU IRQ Vector Lsb (W)
- m_sa1_irq &= 0xff00;
- m_sa1_irq |= data;
+ // SA-1 CPU IRQ Vector LSB
+ m_sa1_irq_vector &= 0xff00;
+ m_sa1_irq_vector |= data;
break;
case 0x008:
- // SNES CIV - SA-1 CPU IRQ Vector Msb (W)
- m_sa1_irq &= 0x00ff;
- m_sa1_irq |= (data<<8);
+ // SA-1 CPU IRQ Vector MSB
+ m_sa1_irq_vector &= 0x00ff;
+ m_sa1_irq_vector |= (data<<8);
+ break;
+ case 0x020:
+ // Super MMC Bank C
+ m_bank_hi[0] = BIT(data, 7); // [00-1f][8000-ffff] is mirror of [c0-cf][0000-ffff] bank or first 1MB of ROM
+ m_bank_rom[0] = data & 0x07; // ROM 1MB bank for [c0-cf]
break;
+ case 0x021:
+ // Super MMC Bank D
+ m_bank_hi[1] = BIT(data, 7); // [20-3f][8000-ffff] is mirror of [d0-df][0000-ffff] bank or second 1MB of ROM
+ m_bank_rom[1] = data & 0x07; // ROM 1MB bank for [d0-df]
+ break;
+ case 0x022:
+ // Super MMC Bank E
+ m_bank_hi[2] = BIT(data, 7); // [80-9f][8000-ffff] is mirror of [e0-ef][0000-ffff] bank or third 1MB of ROM
+ m_bank_rom[2] = data & 0x07; // ROM 1MB bank for [e0-ef]
+ break;
+ case 0x023:
+ // Super MMC Bank F
+ m_bank_hi[3] = BIT(data, 7); // [a0-bf][8000-ffff] is mirror of [e0-ef][0000-ffff] bank or fourth 1MB of ROM
+ m_bank_rom[3] = data & 0x07; // ROM 1MB bank for [f0-ff]
+ break;
+ case 0x024:
+ // BWRAM bank from SNES side
+ m_bwram_snes = data & 0x1f; // max 32x8K banks
+ break;
+ case 0x026:
+ // enable writing to BWRAM from SNES
+ m_bwram_write_snes = BIT(data, 7);
+ break;
+ case 0x028:
+ // write protected area at bottom of BWRAM
+ m_bwpa_sa1 = 0x100 << (data & 0x0f);
+ break;
+ case 0x029:
+ // enable writing to IRAM from SNES (1 bit for each 0x100 chunk)
+ m_iram_write_snes = data;
+ break;
+ case 0x031: // Character Conversion DMA Parameters
+ case 0x032: // DMA Source Device Start Address Low
+ case 0x033: // DMA Source Device Start Address Mid
+ case 0x034: // DMA Source Device Start Address High
+ case 0x035: // DMA Dest Device Start Address Low
+ case 0x036: // DMA Dest Device Start Address Mid
+ case 0x037: // DMA Dest Device Start Address High
+ shared_regs_w(offset, data);
+ break;
+ default:
+ logerror("S-CPU Write access to an unmapped reg (%x) with data %x", offset, data);
+ break;
+ }
+}
+
+void sns_sa1_device::write_regs(offs_t offset, u8 data)
+{
+ offset &= 0x1ff; // $2200 + offset gives the reg value to compare with docs
+
+ switch (offset)
+ {
case 0x009:
// S-CPU control flags
m_scpu_ctrl = data;
- if (m_scpu_ctrl & 0x80)
+ if (SCNT_SNESCPU_IRQ())
{
m_scpu_flags |= SCPU_IRQ_SA1;
-// printf("SA-1 cause S-CPU IRQ\n");
}
- // message to SA-1
- m_sa1_ctrl &= 0xf0;
- m_sa1_ctrl |= (data & 0x0f);
-
- // clear IRQ/NMI override flags in flags word
+ // acquire IRQ/NMI override flags from data
m_scpu_flags &= ~(SCPU_IRQV_ALT|SCPU_NMIV_ALT);
-
- // and set them
m_scpu_flags |= (data & (SCPU_IRQV_ALT|SCPU_NMIV_ALT));
recalc_irqs();
break;
case 0x00a:
- // SA-1 CIE 00h SA-1 CPU Int Enable (W)
+ // SA-1 CPU Int Enable
m_sa1_sie = data;
-// printf("SA-1 IE = %02x\n", data);
recalc_irqs();
break;
case 0x00b:
- // SA-1 CIC 00h SA-1 CPU Int Clear (W)
+ // SA-1 CPU Int Clear
if (BIT(data, 7))
- {
m_sa1_flags &= ~SA1_IRQ_SCPU;
- }
+
if (BIT(data, 6))
- {
m_sa1_flags &= ~SA1_IRQ_TIMER;
- }
+
if (BIT(data, 5))
- {
m_sa1_flags &= ~SA1_IRQ_DMA;
- }
+
if (BIT(data, 4))
- {
m_sa1_flags &= ~SA1_NMI_SCPU;
- }
+
recalc_irqs();
break;
case 0x00c:
- // NMI Vector Low
+ // SA-1 NMI Vector Low
m_nmi_vector = (m_nmi_vector & 0xff00) | (data << 0);
break;
case 0x00d:
- // NMI Vector High
+ // SA-1 NMI Vector High
m_nmi_vector = (m_nmi_vector & 0x00ff) | (data << 8);
break;
case 0x00e:
- // IRQ Vector Low
+ // SA-1 IRQ Vector Low
m_irq_vector = (m_irq_vector & 0xff00) | (data << 0);
break;
case 0x00f:
- // IRQ Vector High
+ // SA-1 IRQ Vector High
m_irq_vector = (m_irq_vector & 0x00ff) | (data << 8);
break;
case 0x010:
- // SA-1 TMC 00h H/V Timer Control (W)
+ // H/V Timer Control
+ m_timer_ctrl = data;
break;
case 0x011:
- // SA-1 CTR - SA-1 CPU Timer Restart (W)
+ // CPU Timer Restart
+ m_hpos = m_vpos = 0;
+ m_sa1_timer->adjust(m_sa1->clocks_to_attotime(2), 0, m_sa1->clocks_to_attotime(2));
break;
case 0x012:
// H-Count Low
@@ -588,123 +760,45 @@ void sns_sa1_device::write_regs(uint32_t offset, uint8_t data)
// V-Count High
m_vcount = (m_vcount & 0x00ff) | (data << 8);
break;
- case 0x020:
- // ROM 1MB bank for [c0-cf]
- m_bank_c_hi = BIT(data, 7);
- m_bank_c_rom = data & 0x07;
- break;
- case 0x021:
- // ROM 1MB bank for [d0-df]
- m_bank_d_hi = BIT(data, 7);
- m_bank_d_rom = data & 0x07;
- break;
- case 0x022:
- // ROM 1MB bank for [e0-ef]
- m_bank_e_hi = BIT(data, 7);
- m_bank_e_rom = data & 0x07;
- break;
- case 0x023:
- // ROM 1MB bank for [f0-ff]
- m_bank_f_hi = BIT(data, 7);
- m_bank_f_rom = data & 0x07;
- break;
- case 0x024:
- // BWRAM bank from SNES side
- m_bwram_snes = data & 0x1f; // max 32x8K banks
- break;
case 0x025:
// BWRAM bank & type from SA-1 side
- m_bwram_sa1_source = BIT(data, 7); // 0 = normal, 1 = bitmap?
- m_bwram_sa1 = data & 0x7f; // up to 128x8K banks here?
- break;
- case 0x026:
- // enable writing to BWRAM from SNES
- m_bwram_write_snes = BIT(data, 7);
+ m_bwram_sa1_source = BIT(data, 7); // 0 = normal, 1 = bitmap
+ m_bwram_sa1 = data & 0x7f; // up to 128x8K banks here
break;
case 0x027:
// enable writing to BWRAM from SA-1
m_bwram_write_sa1 = BIT(data, 7);
break;
- case 0x028:
- // write protected area at bottom of BWRAM
- m_bwpa_sa1 = 0x100 * (data & 0x0f);
- break;
- case 0x029:
- // enable writing to IRAM from SNES (1 bit for each 0x100 chunk)
- m_iram_write_snes = data;
- break;
case 0x02a:
// enable writing to IRAM from SA-1 (1 bit for each 0x100 chunk)
m_iram_write_sa1 = data;
break;
case 0x030:
- // SA-1 DCNT 00h DMA Control (W)
-// printf("%02x to SA-1 DMA control\n", data);
+ // DMA Control (W)
m_dma_ctrl = data;
break;
- case 0x031:
- // Both CDMA 00h Character Conversion DMA Parameters (W)
- m_dma_ccparam = data;
- break;
- case 0x032:
- // DMA Source Device Start Address Low
- m_src_addr = (m_src_addr & 0xffff00) | (data << 0);
- break;
- case 0x033:
- // DMA Source Device Start Address Mid
- m_src_addr = (m_src_addr & 0xff00ff) | (data << 8);
- break;
- case 0x034:
- // DMA Source Device Start Address High
- m_src_addr = (m_src_addr & 0x00ffff) | (data << 16);
- break;
- case 0x035:
- // DMA Dest Device Start Address Low
- m_dst_addr = (m_dst_addr & 0xffff00) | (data << 0);
- break;
- case 0x036:
- // DMA Dest Device Start Address Mid
- m_dst_addr = (m_dst_addr & 0xff00ff) | (data << 8);
- if (m_dma_ctrl & 0x80)
- {
- if (!(m_dma_ctrl & 0x20) && !(m_dma_ctrl & 0x04)) // Normal DMA to IRAM
- {
- dma_transfer();
-// printf("SA-1: normal DMA to IRAM\n");
- }
-
- if (m_dma_ctrl & 0x20 && m_dma_ctrl & 0x10) // CC DMA Type 1
- {
-// printf("SA-1: CC DMA type 1\n");
- dma_cctype1_transfer();
- }
- }
- break;
- case 0x037:
- // DMA Dest Device Start Address High
- m_dst_addr = (m_dst_addr & 0xffff00) | (data << 16);
- if (m_dma_ctrl & 0x80)
- {
- if (!(m_dma_ctrl & 0x20) && m_dma_ctrl & 0x04) // Normal DMA to BWRAM
- {
-// printf("SA-1: normal DMA to BWRAM\n");
- dma_transfer();
- }
- }
+ case 0x031: // Character Conversion DMA Parameters (W)
+ case 0x032: // DMA Source Device Start Address Low
+ case 0x033: // DMA Source Device Start Address Mid
+ case 0x034: // DMA Source Device Start Address High
+ case 0x035: // DMA Dest Device Start Address Low
+ case 0x036: // DMA Dest Device Start Address Mid
+ case 0x037: // DMA Dest Device Start Address High
+ shared_regs_w(offset, data);
break;
case 0x038:
- // SA-1 DTC - DMA Terminal Counter Lsb (W)
+ // DMA Terminal Counter LSB
m_dma_cnt &= 0xff00;
m_dma_cnt |= data;
break;
case 0x039:
- // SA-1 DTC - DMA Terminal Counter Msb (W)
+ // DMA Terminal Counter MSB
m_dma_cnt &= 0x00ff;
m_dma_cnt |= (data<<8);
break;
case 0x03f:
// Format for BWRAM when mapped to bitmap
- m_bwram_sa1_format = BIT(data, 7); // 0 = 4bit, 1 = 2bit
+ m_bwram_sa1_format = BIT(data, 7); // 0 = 4-bit, 1 = 2-bit
break;
case 0x040:
case 0x041:
@@ -724,11 +818,10 @@ void sns_sa1_device::write_regs(uint32_t offset, uint8_t data)
case 0x04f:
// Bit Map Register File (2240h..224Fh)
m_brf_reg[offset & 0x0f] = data;
- if ((offset & 0x07) == 7 && m_dma_ctrl & 0x80)
+ if (((offset & 0x07) == 7) && DCNT_DMAEN())
{
- if (m_dma_ctrl & 0x20 && !(m_dma_ctrl & 0x10)) // CC DMA Type 2
+ if (DCNT_CDEN() && (!(DCNT_CDSEL()))) // CC DMA Type 2
{
-// printf("SA-1: CC DMA type 2\n");
dma_cctype2_transfer();
}
}
@@ -754,27 +847,27 @@ void sns_sa1_device::write_regs(uint32_t offset, uint8_t data)
case 0x054:
// Math B High
m_math_b = (data << 8) | (m_math_b & 0x00ff);
- // After Math B has been written, we do math
+ // After Math B has been written, perform the operation
switch (m_math_ctlr)
{
- case 0: //signed multiplication
- m_math_res = (int16_t)m_math_a * (int16_t)m_math_b;
+ case 0: // signed multiplication (5 cycles required)
+ m_math_res = (s16)m_math_a * (s16)m_math_b;
m_math_b = 0;
break;
- case 1: //unsigned division
+ case 1: // unsigned division (5 cycles required)
if (m_math_b == 0)
m_math_res = 0;
else
{
- int16_t quotient = (int16_t)m_math_a / (uint16_t)m_math_b;
- uint16_t remainder = (int16_t)m_math_a % (uint16_t)m_math_b;
- m_math_res = (uint64_t)((remainder << 16) | quotient);
+ s16 quotient = (s16)m_math_a / (u16)m_math_b;
+ u16 remainder = (s16)m_math_a % (u16)m_math_b;
+ m_math_res = (u64)((remainder << 16) | quotient);
}
break;
- case 2: //sigma (accumulative multiplication)
+ case 2: // sigma (accumulative multiplication) (6 cycles required)
case 3:
- uint64_t acum = (int16_t)m_math_a * (int16_t)m_math_b;
- uint64_t mask = 0xffffffffffU;
+ u64 acum = (s16)m_math_a * (s16)m_math_b;
+ u64 mask = 0xffffffffffU;
m_math_res += acum;
m_math_overflow = (m_math_res > mask) ? 0x80 : 0;
m_math_res &= mask;
@@ -789,9 +882,9 @@ void sns_sa1_device::write_regs(uint32_t offset, uint8_t data)
if (m_vlen == 0)
m_vlen = 16;
- if (m_drm == 0)
+ if (!m_drm)
{
- //fixed mode
+ // fixed mode
m_vbit += m_vlen;
m_vda += (m_vbit >> 3);
m_vbit &= 7;
@@ -816,82 +909,189 @@ void sns_sa1_device::write_regs(uint32_t offset, uint8_t data)
}
}
-uint8_t sns_sa1_device::read_iram(uint32_t offset)
+void sns_sa1_device::shared_regs_w(offs_t offset, u8 data)
+{
+ offset &= 0x1ff; // $2200 + offset gives the reg value to compare with docs
+
+ switch (offset)
+ {
+ case 0x031:
+ // Character Conversion DMA Parameters (W)
+ m_dma_ccparam = data;
+ m_dma_cconv_size = CDMA_SIZE();
+ m_dma_cconv_bits = CDMA_CB();
+ if (CDMA_CHDEND())
+ m_cconv1_dma_active = false;
+ break;
+ case 0x032:
+ // DMA Source Device Start Address Low
+ m_src_addr = (m_src_addr & 0xffff00) | (data << 0);
+ break;
+ case 0x033:
+ // DMA Source Device Start Address Mid
+ m_src_addr = (m_src_addr & 0xff00ff) | (data << 8);
+ break;
+ case 0x034:
+ // DMA Source Device Start Address High
+ m_src_addr = (m_src_addr & 0x00ffff) | (data << 16);
+ break;
+ case 0x035:
+ // DMA Dest Device Start Address Low
+ m_dst_addr = (m_dst_addr & 0xffff00) | (data << 0);
+ break;
+ case 0x036:
+ // DMA Dest Device Start Address Mid
+ m_dst_addr = (m_dst_addr & 0xff00ff) | (data << 8);
+ if (DCNT_DMAEN())
+ {
+ if ((!(DCNT_CDEN())) && (!(DCNT_DD()))) // Normal DMA to IRAM
+ dma_transfer();
+
+ if (DCNT_CDEN() && DCNT_CDSEL()) // CC DMA Type 1
+ dma_cctype1_transfer();
+ }
+ break;
+ case 0x037:
+ // DMA Dest Device Start Address High
+ m_dst_addr = (m_dst_addr & 0x00ffff) | (data << 16);
+ if (DCNT_DMAEN())
+ {
+ if ((!(DCNT_CDEN())) && DCNT_DD()) // Normal DMA to BWRAM
+ {
+ dma_transfer();
+ }
+ }
+ break;
+ default:
+ logerror("SA-1 Write access to an unmapped reg (%x) with data %x", offset, data);
+ break;
+ }
+}
+
+u8 sns_sa1_device::read_iram(offs_t offset)
{
return m_internal_ram[offset & 0x7ff];
}
-void sns_sa1_device::write_iram(uint32_t offset, uint8_t data)
+void sns_sa1_device::write_iram(offs_t offset, u8 data)
{
m_internal_ram[offset & 0x7ff] = data;
}
-uint8_t sns_sa1_device::read_bwram(uint32_t offset)
+u8 sns_sa1_device::read_cconv1_dma(offs_t offset)
{
- int shift;
- uint8_t mask;
+ const u32 store_mask = (1 << (6 - m_dma_cconv_bits)) - 1;
+ if (!machine().side_effects_disabled())
+ {
+ if ((offset & store_mask) == 0)
+ {
+ const u32 bpp = 2 << (2 - m_dma_cconv_bits);
+ const u32 tile_stride = (8 << m_dma_cconv_size) >> m_dma_cconv_bits;
+ const u32 bwram_addr_mask = m_nvram.size() - 1;
+ const u32 tile = ((offset - m_src_addr) & bwram_addr_mask) >> (6 - m_dma_cconv_bits);
+ const u32 ty = (tile >> m_dma_cconv_size);
+ const u32 tx = tile & ((1 << m_dma_cconv_size) - 1);
+ u32 bwram_src = m_src_addr + ty * 8 * tile_stride + tx * bpp;
+
+ // TODO: memory access/process cycle
+ for (u32 y = 0; y < 8; y++)
+ {
+ u64 raw_pixels = 0;
+ for (u64 bit = 0; bit < bpp; bit++)
+ raw_pixels |= (u64)m_nvram[(bwram_src + bit) & bwram_addr_mask] << (bit << 3);
+
+ bwram_src += tile_stride;
+
+ u8 linear[8] = {0, 0, 0, 0, 0, 0, 0, 0};
+ for (u8 x = 0; x < 8; x++)
+ {
+ for (u8 bit = 0; bit < bpp; bit++)
+ linear[bit] |= BIT(raw_pixels, bit) << (7 - x);
+
+ raw_pixels >>= bpp;
+ }
+
+ const u32 dy = (y << 1);
+ for (u8 byte = 0; byte < bpp; byte++)
+ {
+ const u32 plane = BIT(byte, 0) | (BIT(byte, 1, 2) << 4);
+ write_iram(m_dst_addr + dy + plane, linear[byte]);
+ }
+ }
+ }
+ }
+
+ return read_iram(m_dst_addr + (offset & store_mask));
+}
+
+template<bool SA1Read>
+u8 sns_sa1_device::read_bwram(offs_t offset, bool bitmap)
+{
if (m_nvram.empty())
return 0xff; // this should probably never happen, or are there SA-1 games with no BWRAM?
- if (offset < 0x100000)
- return m_nvram[offset & (m_nvram.size() - 1)];
+ if (m_cconv1_dma_active && !SA1Read)
+ return read_cconv1_dma(offset);
+
+ const offs_t bwram_addr_mask = (m_nvram.size() - 1);
+ if (!bitmap)
+ return m_nvram[offset & bwram_addr_mask];
// Bitmap BWRAM
- offset -= 0x100000;
+ u8 shift, mask;
if (m_bwram_sa1_format)
{
- // 2bits mode
- offset /= 4;
- shift = ((offset % 4) * 2);
+ // 2-bit mode
+ shift = ((offset & 3) << 1);
mask = 0x03;
+ offset >>= 2;
}
else
{
- // 4bits mode
- offset /= 2;
- shift = ((offset % 2) * 4);
+ // 4-bit mode
+ shift = ((offset & 1) << 2);
mask = 0x0f;
+ offset >>= 1;
}
// only return the correct bits
- return (m_nvram[offset & (m_nvram.size() - 1)] >> shift) & mask;
+ return (m_nvram[offset & bwram_addr_mask] >> shift) & mask;
}
-void sns_sa1_device::write_bwram(uint32_t offset, uint8_t data)
+void sns_sa1_device::write_bwram(offs_t offset, u8 data, bool bitmap)
{
- uint8_t mask;
-
if (m_nvram.empty())
return; // this should probably never happen, or are there SA-1 games with no BWRAM?
- if (offset < 0x100000)
+ const offs_t bwram_addr_mask = (m_nvram.size() - 1);
+ if (!bitmap)
{
- m_nvram[offset & (m_nvram.size() - 1)] = data;
+ m_nvram[offset & bwram_addr_mask] = data;
return;
}
// Bitmap BWRAM
- offset -= 0x100000;
+ u8 mask;
if (m_bwram_sa1_format)
{
- // 2bits mode
- offset /= 4;
- data = (data & 0x03) << ((offset % 4) * 2);
- mask = 0x03 << ((offset % 4) * 2);
+ // 2-bit mode
+ data = (data & 0x03) << ((offset & 3) << 1);
+ mask = 0x03 << ((offset & 3) << 1);
+ offset >>= 2;
}
else
{
- // 4bits mode
- offset /= 2;
- data = (data & 0x0f) << ((offset % 2) * 4);
- mask = 0x0f << ((offset % 2) * 4);
+ // 4-bit mode
+ data = (data & 0x0f) << ((offset & 1) << 2);
+ mask = 0x0f << ((offset & 1) << 2);
+ offset >>= 1;
}
// only change the correct bits, keeping the rest untouched
- m_nvram[offset & (m_nvram.size() - 1)] = (m_nvram[offset & (m_nvram.size() - 1)] & ~mask) | data;
+ m_nvram[offset & bwram_addr_mask] = (m_nvram[offset & bwram_addr_mask] & ~mask) | data;
}
@@ -901,117 +1101,90 @@ void sns_sa1_device::write_bwram(uint32_t offset, uint8_t data)
-------------------------------------------------*/
-uint8_t sns_sa1_device::read_l(offs_t offset)
+u8 sns_sa1_device::rom_r(offs_t offset)
{
- int bank;
-
- if (offset == 0xffea && BIT(m_scpu_ctrl, 4)) return (m_nmi_vector >> 0) & 0xff;
- if (offset == 0xffeb && BIT(m_scpu_ctrl, 4)) return (m_nmi_vector >> 8) & 0xff;
- if (offset == 0xffee && BIT(m_scpu_ctrl, 6)) return (m_irq_vector >> 0) & 0xff;
- if (offset == 0xffef && BIT(m_scpu_ctrl, 6)) return (m_irq_vector >> 8) & 0xff;
+ u8 ret = 0; // TODO: unverified & unknown value
- // ROM is mapped to [00-3f][8000-ffff] only here
- if (offset < 0x200000)
+ if ((offset & 0xc00000) == 0xc00000) // [c0-ff][0000-ffff]
+ ret = m_rom[(rom_bank_map[(m_bank_rom[BIT(offset, 20, 2)] << 5) | BIT(offset, 15, 5)] << 15) | (offset & 0x7fff)];
+ else if ((offset & 0x408000) == 0x008000) // [00-3f][8000-ffff], [80-bf][8000-ffff]
{
- if (!m_bank_c_hi) // when HiROM mapping is disabled, we always access first 1MB here
- bank = (offset / 0x10000) + 0x00;
- else // when HiROM mapping is enabled, we mirror [c0-cf][0000-ffff] bank
- bank = (offset / 0x10000) + (m_bank_c_rom * 0x20);
+ const u8 slot = (BIT(offset, 23) << 1) | BIT(offset, 21);
+ u8 bank; // 256 banks (64 Mbit limited)
- bank &= 0xff;
- return m_rom[rom_bank_map[bank] * 0x8000 + (offset & 0x7fff)];
- }
- else if (offset < 0x400000)
- {
- offset -= 0x200000;
- if (!m_bank_d_hi) // when HiROM mapping is disabled, we always access second 1MB here
- bank = (offset / 0x10000) + 0x20;
- else // when HiROM mapping is enabled, we mirror [d0-df][0000-ffff] bank
- bank = (offset / 0x10000) + (m_bank_d_rom * 0x20);
-
- bank &= 0xff;
- return m_rom[rom_bank_map[bank] * 0x8000 + (offset & 0x7fff)];
+ if (!m_bank_hi[slot]) // when HiROM mapping is disabled, we always access each 1MB here
+ bank = BIT(offset, 16, 5) | (slot << 5);
+ else // when HiROM mapping is enabled, we mirror [(cx,dx,ex,fx)][0000-ffff] bank
+ bank = BIT(offset, 16, 5) | (m_bank_rom[slot] << 5);
+
+ ret = m_rom[(rom_bank_map[bank] << 15) | (offset & 0x7fff)];
}
+ return ret;
+}
+
+u8 sns_sa1_device::read_l(offs_t offset)
+{
+ if (offset == 0xffea && SCNT_SNESCPU_NVSW()) return (m_nmi_vector >> 0) & 0xff;
+ if (offset == 0xffeb && SCNT_SNESCPU_NVSW()) return (m_nmi_vector >> 8) & 0xff;
+ if (offset == 0xffee && SCNT_SNESCPU_IVSW()) return (m_irq_vector >> 0) & 0xff;
+ if (offset == 0xffef && SCNT_SNESCPU_IVSW()) return (m_irq_vector >> 8) & 0xff;
+
+ // ROM is mapped to [00-3f][8000-ffff] only here
+ if (offset < 0x400000)
+ return rom_r(offset);
else
return 0; // this should not happen (the driver should only call read_l in the above case)
}
-uint8_t sns_sa1_device::read_h(offs_t offset)
+u8 sns_sa1_device::read_h(offs_t offset)
{
- int bank;
-
// ROM is mapped to [80-bf][8000-ffff] & [c0-ff][0000-ffff]
- if (offset < 0x200000)
- {
- if (!m_bank_e_hi) // when HiROM mapping is disabled, we always access third 1MB here
- bank = (offset / 0x10000) + 0x40;
- else // when HiROM mapping is enabled, we mirror [e0-ef][0000-ffff] bank
- bank = (offset / 0x10000) + (m_bank_e_rom * 0x20);
-
- bank &= 0xff;
- return m_rom[rom_bank_map[bank] * 0x8000 + (offset & 0x7fff)];
- }
- else if (offset < 0x400000)
- {
- offset -= 0x200000;
- if (!m_bank_f_hi) // when HiROM mapping is disabled, we always access fourth 1MB here
- bank = (offset / 0x10000) + 0x60;
- else // when HiROM mapping is enabled, we mirror [f0-ff][0000-ffff] bank
- bank = (offset / 0x10000) + (m_bank_f_rom * 0x20);
-
- bank &= 0xff;
- return m_rom[rom_bank_map[bank] * 0x8000 + (offset & 0x7fff)];
- }
- else if (offset < 0x500000)
- return m_rom[rom_bank_map[(m_bank_c_rom * 0x20) + ((offset - 0x400000) / 0x8000)] * 0x8000 + (offset & 0x7fff)];
- else if (offset < 0x600000)
- return m_rom[rom_bank_map[(m_bank_d_rom * 0x20) + ((offset - 0x500000) / 0x8000)] * 0x8000 + (offset & 0x7fff)];
- else if (offset < 0x700000)
- return m_rom[rom_bank_map[(m_bank_e_rom * 0x20) + ((offset - 0x600000) / 0x8000)] * 0x8000 + (offset & 0x7fff)];
- else
- return m_rom[rom_bank_map[(m_bank_f_rom * 0x20) + ((offset - 0x700000) / 0x8000)] * 0x8000 + (offset & 0x7fff)];
+ return rom_r(offset | 0x800000);
}
-void sns_sa1_device::write_l(offs_t offset, uint8_t data)
+void sns_sa1_device::write_l(offs_t offset, u8 data)
{
}
-void sns_sa1_device::write_h(offs_t offset, uint8_t data)
+void sns_sa1_device::write_h(offs_t offset, u8 data)
{
}
-uint8_t sns_sa1_device::chip_read(offs_t offset)
+u8 sns_sa1_device::chip_read(offs_t offset)
{
- uint16_t address = offset & 0xffff;
+ u16 address = offset & 0xffff;
if (offset < 0x400000 && address >= 0x2200 && address < 0x2400)
- return read_regs(address & 0x1ff); // SA-1 Regs
+ return host_r(address & 0x1ff); // SA-1 Regs
if (offset < 0x400000 && address >= 0x3000 && address < 0x3800)
- return read_iram(address & 0x7ff); // Internal SA-1 RAM (2K)
+ return read_iram(address & 0x7ff);
if (offset < 0x400000 && address >= 0x6000 && address < 0x8000)
- return read_bwram((m_bwram_snes * 0x2000) + (offset & 0x1fff)); // SA-1 BWRAM
+ return read_bwram<false>((m_bwram_snes * 0x2000) + (offset & 0x1fff));
if (offset >= 0x400000 && offset < 0x500000)
- return read_bwram(offset & 0xfffff); // SA-1 BWRAM again (but not called for the [c0-cf] range, because it's not mirrored)
+ return read_bwram<false>(offset & 0xfffff); // SA-1 BWRAM again (but not called for the [c0-cf] range, because it's not mirrored)
return 0xff;
}
-void sns_sa1_device::chip_write(offs_t offset, uint8_t data)
+void sns_sa1_device::chip_write(offs_t offset, u8 data)
{
- uint16_t address = offset & 0xffff;
+ u16 address = offset & 0xffff;
if (offset < 0x400000 && address >= 0x2200 && address < 0x2400)
- write_regs(address & 0x1ff, data); // SA-1 Regs
+ host_w(address & 0x1ff, data); // SA-1 Regs
if (offset < 0x400000 && address >= 0x3000 && address < 0x3800)
- write_iram(address & 0x7ff, data); // Internal SA-1 RAM (2K)
+ {
+ if (BIT(m_iram_write_snes, BIT(address, 8, 3)))
+ write_iram(address & 0x7ff, data);
+ }
if (offset < 0x400000 && address >= 0x6000 && address < 0x8000)
- write_bwram((m_bwram_snes * 0x2000) + (offset & 0x1fff), data); // SA-1 BWRAM
+ write_bwram((m_bwram_snes * 0x2000) + (offset & 0x1fff), data);
if (offset >= 0x400000 && offset < 0x500000)
write_bwram(offset & 0xfffff, data); // SA-1 BWRAM again (but not called for the [c0-cf] range, because it's not mirrored)
@@ -1026,111 +1199,162 @@ void sns_sa1_device::chip_write(offs_t offset, uint8_t data)
// I/O regs or WRAM, and there are a few additional accesses to IRAM (in [00-3f][0000-07ff])
// and to BWRAM (in [60-6f][0000-ffff], so-called bitmap mode)
-uint8_t sns_sa1_device::sa1_hi_r(offs_t offset)
+u8 sns_sa1_device::sa1_rom_r(offs_t offset)
{
- uint16_t address = offset & 0xffff;
+ if (bus_conflict_rom())
+ m_sa1->adjust_icount(-1); // wait 1 cycle
+
+ return rom_r(offset);
+}
+
+u8 sns_sa1_device::sa1_iram_r(offs_t offset)
+{
+ if (bus_conflict_iram())
+ m_sa1->adjust_icount(-2); // wait 2 cycles
+ return read_iram(offset & 0x7ff);
+}
+
+void sns_sa1_device::sa1_iram_w(offs_t offset, u8 data)
+{
+ if (bus_conflict_iram())
+ m_sa1->adjust_icount(-2); // wait 2 cycles
+
+ if (BIT(m_iram_write_sa1, BIT(offset, 8, 3)))
+ write_iram(offset & 0x7ff, data);
+}
+
+u8 sns_sa1_device::sa1_bwram_r(offs_t offset, bool bitmap)
+{
+ if (bus_conflict_bwram())
+ m_sa1->adjust_icount(-3); // wait 3 cycles
+ else
+ m_sa1->adjust_icount(-1); // wait 1 cycle
+
+ return read_bwram<true>(offset, bitmap);
+}
+
+void sns_sa1_device::sa1_bwram_w(offs_t offset, u8 data, bool bitmap)
+{
+ if (bus_conflict_bwram())
+ m_sa1->adjust_icount(-3); // wait 3 cycles
+ else
+ m_sa1->adjust_icount(-1); // wait 1 cycle
+
+ // TODO: write protectable?
+ write_bwram(offset, data, bitmap);
+}
+
+u8 sns_sa1_device::sa1_hi_r(offs_t offset)
+{
+ u16 address = offset & 0xffff;
if (offset < 0x400000)
{
if (address < 0x6000)
{
if (address < 0x0800)
- return read_iram(offset); // Internal SA-1 RAM (2K)
+ return sa1_iram_r(offset);
else if (address >= 0x2200 && address < 0x2400)
- return read_regs(offset & 0x1ff); // SA-1 Regs
+ return read_regs(offset & 0x1ff);
else if (address >= 0x3000 && address < 0x3800)
- return read_iram(offset); // Internal SA-1 RAM (2K)
+ return sa1_iram_r(offset);
}
else if (address < 0x8000)
- return read_bwram((m_bwram_sa1 * 0x2000) + (offset & 0x1fff) + (m_bwram_sa1_source * 0x100000)); // SA-1 BWRAM
+ return sa1_bwram_r((m_bwram_sa1 * 0x2000) + (offset & 0x1fff), m_bwram_sa1_source);
else
- return read_h(offset); // ROM
+ return sa1_rom_r(offset | 0x800000);
- return 0xff; // maybe open bus? same as the main system one or diff? (currently not accessible from carts anyway...)
+ return 0xff; // TOOD: Maybe open bus. Check if same as the main system or different (currently not accessible from carts anyway).
}
else
- return read_h(offset); // ROM
+ return sa1_rom_r(offset | 0xc00000);
}
-uint8_t sns_sa1_device::sa1_lo_r(offs_t offset)
+u8 sns_sa1_device::sa1_lo_r(offs_t offset)
{
- uint16_t address = offset & 0xffff;
+ u16 address = offset & 0xffff;
if (offset < 0x400000)
{
if (address < 0x6000)
{
if (address < 0x0800)
- return read_iram(offset); // Internal SA-1 RAM (2K)
+ return sa1_iram_r(offset);
else if (address >= 0x2200 && address < 0x2400)
- return read_regs(offset & 0x1ff); // SA-1 Regs
+ return read_regs(offset & 0x1ff);
else if (address >= 0x3000 && address < 0x3800)
- return read_iram(offset); // Internal SA-1 RAM (2K)
+ return sa1_iram_r(offset);
}
else if (address < 0x8000)
- return read_bwram((m_bwram_sa1 * 0x2000) + (offset & 0x1fff) + (m_bwram_sa1_source * 0x100000)); // SA-1 BWRAM
- else if (offset == 0xffee)
- {
- return m_sa1_irq & 0xff;
- }
- else if (offset == 0xffef)
- {
- return m_sa1_irq>>8;
- }
- else if (offset == 0xffea)
- {
- return m_sa1_nmi & 0xff;
- }
- else if (offset == 0xffeb)
- {
- return m_sa1_nmi>>8;
- }
- else if (offset == 0xfffc)
- {
- return m_sa1_reset & 0xff;
- }
- else if (offset == 0xfffd)
+ return sa1_bwram_r((m_bwram_sa1 * 0x2000) + (offset & 0x1fff), m_bwram_sa1_source); // SA-1 BWRAM
+ else
{
- return m_sa1_reset>>8;
+ if (bus_conflict_rom())
+ m_sa1->adjust_icount(-1); // wait 1 cycle
+
+ if (offset == 0xffee)
+ {
+ return m_sa1_irq_vector & 0xff;
+ }
+ else if (offset == 0xffef)
+ {
+ return m_sa1_irq_vector >> 8;
+ }
+ else if (offset == 0xffea)
+ {
+ return m_sa1_nmi_vector & 0xff;
+ }
+ else if (offset == 0xffeb)
+ {
+ return m_sa1_nmi_vector >> 8;
+ }
+ else if (offset == 0xfffc)
+ {
+ return m_sa1_reset_vector & 0xff;
+ }
+ else if (offset == 0xfffd)
+ {
+ return m_sa1_reset_vector >> 8;
+ }
+ else
+ return rom_r(offset);
}
- else
- return read_l(offset); // ROM
- return 0xff; // maybe open bus? same as the main system one or diff? (currently not accessible from carts anyway...)
+ return 0xff; // TOOD: Maybe open bus. Check if same as the main system or different (currently not accessible from carts anyway).
}
else if (offset < 0x500000)
- return read_bwram(offset & 0xfffff); // SA-1 BWRAM (not mirrored above!)
+ return sa1_bwram_r(offset & 0xfffff, false); // SA-1 BWRAM (not mirrored above)
else if (offset >= 0x600000 && offset < 0x700000)
- return read_bwram((offset & 0xfffff) + 0x100000); // SA-1 BWRAM Bitmap mode
+ return sa1_bwram_r(offset & 0xfffff, true); // SA-1 BWRAM Bitmap mode
else
- return 0xff; // nothing should be mapped here, so maybe open bus?
+ return 0xff; // nothing should be mapped here, so maybe open bus
}
-void sns_sa1_device::sa1_hi_w(offs_t offset, uint8_t data)
+void sns_sa1_device::sa1_hi_w(offs_t offset, u8 data)
{
- uint16_t address = offset & 0xffff;
+ u16 address = offset & 0xffff;
if (offset < 0x400000)
{
if (address < 0x6000)
{
if (address < 0x0800)
- write_iram(offset, data); // Internal SA-1 RAM (2K)
+ sa1_iram_w(offset, data);
else if (address >= 0x2200 && address < 0x2400)
- write_regs(offset & 0x1ff, data); // SA-1 Regs
+ write_regs(offset & 0x1ff, data);
else if (address >= 0x3000 && address < 0x3800)
- write_iram(offset, data); // Internal SA-1 RAM (2K)
+ sa1_iram_w(offset, data);
}
else if (address < 0x8000)
- write_bwram((m_bwram_sa1 * 0x2000) + (offset & 0x1fff) + (m_bwram_sa1_source * 0x100000), data); // SA-1 BWRAM
+ sa1_bwram_w((m_bwram_sa1 * 0x2000) + (offset & 0x1fff), data, m_bwram_sa1_source);
}
}
-void sns_sa1_device::sa1_lo_w(offs_t offset, uint8_t data)
+void sns_sa1_device::sa1_lo_w(offs_t offset, u8 data)
{
if (offset >= 0x400000 && offset < 0x500000)
- write_bwram(offset & 0xfffff, data); // SA-1 BWRAM (not mirrored above!)
+ sa1_bwram_w(offset & 0xfffff, data, false); // SA-1 BWRAM (not mirrored above)
else if (offset >= 0x600000 && offset < 0x700000)
- write_bwram((offset & 0xfffff) + 0x100000, data); // SA-1 BWRAM Bitmap mode
+ sa1_bwram_w(offset & 0xfffff, data, true); // SA-1 BWRAM Bitmap mode
else
sa1_hi_w(offset, data);
}
@@ -1145,6 +1369,6 @@ void sns_sa1_device::sa1_map(address_map &map)
void sns_sa1_device::device_add_mconfig(machine_config &config)
{
- G65816(config, m_sa1, 10000000);
+ G65816(config, m_sa1, DERIVED_CLOCK(1,2)); // Nintendo SA1 RF5A123, 10.738636MHz (21.477272MHz XTAL / 2)
m_sa1->set_addrmap(AS_PROGRAM, &sns_sa1_device::sa1_map);
}
diff --git a/src/devices/bus/snes/sa1.h b/src/devices/bus/snes/sa1.h
index e4fb646385a..b32b27a32fa 100644
--- a/src/devices/bus/snes/sa1.h
+++ b/src/devices/bus/snes/sa1.h
@@ -7,6 +7,7 @@
#include "snes_slot.h"
#include "cpu/g65816/g65816.h"
+#include <algorithm>
// ======================> sns_sa1_device
@@ -16,99 +17,168 @@ class sns_sa1_device : public device_t,
{
public:
// construction/destruction
- sns_sa1_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
+ sns_sa1_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_start() override ATTR_COLD;
+ virtual void device_reset() override ATTR_COLD;
- virtual void device_add_mconfig(machine_config &config) override;
+ virtual void device_add_mconfig(machine_config &config) override ATTR_COLD;
// reading and writing
- virtual uint8_t read_l(offs_t offset) override;
- virtual uint8_t read_h(offs_t offset) override;
- virtual void write_l(offs_t offset, uint8_t data) override;
- virtual void write_h(offs_t offset, uint8_t data) override;
+ virtual u8 read_l(offs_t offset) override;
+ virtual u8 read_h(offs_t offset) override;
+ virtual void write_l(offs_t offset, u8 data) override;
+ virtual void write_h(offs_t offset, u8 data) override;
// additional reading and writing
- virtual uint8_t chip_read(offs_t offset) override;
- virtual void chip_write(offs_t offset, uint8_t data) override;
+ virtual u8 chip_read(offs_t offset) override;
+ virtual void chip_write(offs_t offset, u8 data) override;
+
+ TIMER_CALLBACK_MEMBER(timer_tick);
private:
- uint8_t var_length_read(uint32_t offset);
+ u8 var_length_read(offs_t offset);
void dma_transfer();
void dma_cctype1_transfer();
void dma_cctype2_transfer();
- uint8_t read_regs(uint32_t offset);
- uint8_t read_iram(uint32_t offset);
- uint8_t read_bwram(uint32_t offset);
- void write_regs(uint32_t offset, uint8_t data);
- void write_iram(uint32_t offset, uint8_t data);
- void write_bwram(uint32_t offset, uint8_t data);
+ u8 host_r(offs_t offset);
+ void host_w(offs_t offset, u8 data);
+ void shared_regs_w(offs_t offset, u8 data);
+
+ u8 read_regs(offs_t offset);
+ u8 read_iram(offs_t offset);
+ template<bool SA1Read> u8 read_bwram(offs_t offset, bool bitmap = false);
+ u8 read_cconv1_dma(offs_t offset);
+ void write_regs(offs_t offset, u8 data);
+ void write_iram(offs_t offset, u8 data);
+ void write_bwram(offs_t offset, u8 data, bool bitmap = false);
void recalc_irqs();
+ u8 rom_r(offs_t offset);
+ u8 sa1_rom_r(offs_t offset);
+
+ u8 sa1_iram_r(offs_t offset);
+ void sa1_iram_w(offs_t offset, u8 data);
+
+ u8 sa1_bwram_r(offs_t offset, bool bitmap = false);
+ void sa1_bwram_w(offs_t offset, u8 data, bool bitmap = false);
+
required_device<g65816_device> m_sa1;
+ emu_timer *m_sa1_timer;
+
+ std::unique_ptr<u8[]> m_internal_ram;
- uint8_t m_internal_ram[0x800];
+ // bus conflict related:
+ // ROM: [00-3f][8000-ffff], [80-bf][8000-ffff], [c0-ff][0000-ffff]
+ // IRAM: [00-3f][3000-38ff], [80-bf][3000-38ff]
+ // BWRAM: [00-3f][6000-7fff], [40-4f][0000-ffff], [80-bf][6000-7fff]
+ inline const bool bus_conflict_rom() { return ((address_r() & 0x408000) == 0x008000) || ((address_r() & 0xc00000) == 0xc00000); }
+ inline const bool bus_conflict_iram() { return ((address_r() & 0x40f800) == 0x003000); }
+ inline const bool bus_conflict_bwram() { return ((address_r() & 0x40e000) == 0x006000) || ((address_r() & 0xf00000) == 0x400000); }
// register related
// $2200
- uint8_t m_sa1_ctrl;
+ u8 m_sa1_ctrl;
+ bool m_sa1_reset_flag;
+ // SA-1 CPU Control (CCNT)
+ inline const bool CCNT_SA1_CPU_IRQ() { return BIT(m_sa1_ctrl, 7); } // SA-1 CPU IRQ (from SNES CPU)
+ inline const bool CCNT_SA1_CPU_RDYB() { return BIT(m_sa1_ctrl, 6); } // SA-1 CPU ready
+ inline const bool CCNT_SA1_CPU_RESB() { return BIT(m_sa1_ctrl, 5); } // SA-1 CPU reset
+ inline const bool CCNT_SA1_CPU_NMI() { return BIT(m_sa1_ctrl, 4); } // SA-1 CPU NMI (from SNES CPU)
+ inline const u8 CCNT_SMEG() { return BIT(m_sa1_ctrl, 0, 4); } // Message from SNES CPU to SA-1 CPU
+ inline const bool sa1_halted() { return (CCNT_SA1_CPU_RDYB() || CCNT_SA1_CPU_RESB()); } // SA-1 is halted?
// $2201
- uint8_t m_scpu_sie;
+ u8 m_scpu_sie;
// $2203-$2208
- uint16_t m_sa1_reset, m_sa1_nmi, m_sa1_irq;
+ u16 m_sa1_reset_vector, m_sa1_nmi_vector, m_sa1_irq_vector;
// $2209
- uint8_t m_scpu_ctrl;
+ u8 m_scpu_ctrl;
+ // SNES CPU Control (SCNT)
+ inline const bool SCNT_SNESCPU_IRQ() { return BIT(m_scpu_ctrl, 7); } // IRQ from SA-1 CPU to SNES CPU
+ inline const bool SCNT_SNESCPU_IVSW() { return BIT(m_scpu_ctrl, 6); } // SNES CPU IRQ vector selection (ROM, IRQ vector register)
+ inline const bool SCNT_SNESCPU_NVSW() { return BIT(m_scpu_ctrl, 4); } // SNES CPU NMI vector selection (ROM, NMI vector register)
+ inline const u8 SCNT_CMEG() { return BIT(m_scpu_ctrl, 0, 4); } // Message from SA-1 CPU to SNES CPU
// $220a
- uint8_t m_sa1_sie;
- // $200c-$200d - S-CPU vectors
- uint16_t m_irq_vector, m_nmi_vector;
- // $2012-$2015
- uint16_t m_hcount, m_vcount;
+ u8 m_sa1_sie;
+ // $220c-$220d - S-CPU vectors
+ u16 m_irq_vector, m_nmi_vector;
+ // $2210-$2211
+ u8 m_timer_ctrl;
+ // H/V Timer control (TMC)
+ inline const bool TMC_HVSELB() { return BIT(m_timer_ctrl, 7); } // Select HV timer (HV timer, Linear timer)
+ inline const bool TMC_VEN() { return BIT(m_timer_ctrl, 1); } // V count enable
+ inline const bool TMC_HEN() { return BIT(m_timer_ctrl, 0); } // H count enable
+ // H/V Timer position
+ u16 m_hpos, m_vpos;
+ // $2212-$2215
+ u16 m_hcount, m_vcount;
// $2220-$2223
- int m_bank_c_hi, m_bank_c_rom;
- int m_bank_d_hi, m_bank_d_rom;
- int m_bank_e_hi, m_bank_e_rom;
- int m_bank_f_hi, m_bank_f_rom;
+ /*
+ enum super_mmc_t
+ {
+ CXB = 0,
+ DXB = 1,
+ EXB = 2,
+ FXB = 3
+ };
+ */
+ bool m_bank_hi[4];
+ u8 m_bank_rom[4];
// $2224-$2225 & $223f
- uint8_t m_bwram_snes, m_bwram_sa1;
- int m_bwram_sa1_source, m_bwram_sa1_format;
+ u8 m_bwram_snes, m_bwram_sa1;
+ bool m_bwram_sa1_source, m_bwram_sa1_format;
// $2226-$2227
- int m_bwram_write_snes, m_bwram_write_sa1;
+ bool m_bwram_write_snes, m_bwram_write_sa1;
// $2228
- uint32_t m_bwpa_sa1;
+ u32 m_bwpa_sa1;
// $2229-$222a
- uint8_t m_iram_write_snes, m_iram_write_sa1;
+ u8 m_iram_write_snes, m_iram_write_sa1;
// $2230-$2231
- uint8_t m_dma_ctrl, m_dma_ccparam;
+ u8 m_dma_ctrl, m_dma_ccparam;
+ u8 m_dma_cconv_size;
+ u8 m_dma_cconv_bits;
+ // DMA Control (DCNT)
+ inline const bool DCNT_DMAEN() { return BIT(m_dma_ctrl, 7); } // DMA Enable control
+ //inline const bool DCNT_DPRIO() { return BIT(m_dma_ctrl, 6); } // Processing priority between SA-1 CPU and DMA; Not emulated currently
+ inline const bool DCNT_CDEN() { return BIT(m_dma_ctrl, 5); } // DMA mode selection (Normal/Character conversion)
+ inline const bool DCNT_CDSEL() { return BIT(m_dma_ctrl, 4); } // Character conversion DMA type
+ inline const bool DCNT_DD() { return BIT(m_dma_ctrl, 2); } // Destination device (IRAM, BWRAM)
+ inline const u8 DCNT_SD() { return BIT(m_dma_ctrl, 0, 1); } // Source device (ROM, IRAM, BWRAM)
+ // Character conversion DMA parameters (CDMA)
+ inline const bool CDMA_CHDEND() { return BIT(m_dma_ccparam, 7); } // End character conversion 1
+ inline const u8 CDMA_SIZE() { return std::min<u8>(5, BIT(m_dma_ccparam, 2, 3)); } // Number of virtual VRAM horizontal characters (1 << SIZE)
+ inline const u8 CDMA_CB() { return std::min<u8>(2, BIT(m_dma_ccparam, 0, 2)); } // Character conversion DMA color mode (8bpp, 4bpp, 2bpp)
// $2232-$2237
- uint32_t m_src_addr, m_dst_addr;
+ u32 m_src_addr, m_dst_addr;
// $2238-$2239
- uint16_t m_dma_cnt;
+ u16 m_dma_cnt;
// $2240-$224f
- uint8_t m_brf_reg[0x10];
+ u8 m_brf_reg[0x10];
// $2250-$2254
- uint8_t m_math_ctlr, m_math_overflow;
- uint16_t m_math_a, m_math_b;
- uint64_t m_math_res;
+ u8 m_math_ctlr, m_math_overflow;
+ u16 m_math_a, m_math_b;
+ u64 m_math_res;
// $2258-$225b
- uint32_t m_vda;
- uint8_t m_vbit, m_vlen;
- int m_drm;
+ u32 m_vda;
+ u8 m_vbit, m_vlen;
+ bool m_drm;
// $2300-$2301
- uint8_t m_scpu_flags, m_sa1_flags;
+ u8 m_scpu_flags, m_sa1_flags;
// $2302-$2305
- uint16_t m_hcr, m_vcr;
+ u16 m_hcr, m_vcr;
+
+ bool m_cconv1_dma_active;
+ u8 m_cconv2_line;
- uint8_t sa1_lo_r(offs_t offset);
- uint8_t sa1_hi_r(offs_t offset);
- void sa1_lo_w(offs_t offset, uint8_t data);
- void sa1_hi_w(offs_t offset, uint8_t data);
+ u8 sa1_lo_r(offs_t offset);
+ u8 sa1_hi_r(offs_t offset);
+ void sa1_lo_w(offs_t offset, u8 data);
+ void sa1_hi_w(offs_t offset, u8 data);
- void sa1_map(address_map &map);
+ void sa1_map(address_map &map) ATTR_COLD;
};
diff --git a/src/devices/bus/snes/sdd1.cpp b/src/devices/bus/snes/sdd1.cpp
index 94374d07681..3b60be87609 100644
--- a/src/devices/bus/snes/sdd1.cpp
+++ b/src/devices/bus/snes/sdd1.cpp
@@ -435,11 +435,8 @@ void sns_rom_sdd1_device::device_start()
save_item(NAME(m_xfer_enable));
save_item(NAME(m_mmc));
- for (int i = 0; i < 8; i++)
- {
- save_item(NAME(m_dma[i].addr), i);
- save_item(NAME(m_dma[i].size), i);
- }
+ save_item(STRUCT_MEMBER(m_dma, addr));
+ save_item(STRUCT_MEMBER(m_dma, size));
save_pointer(NAME(m_buffer.data), 0x10000);
save_item(NAME(m_buffer.offset));
diff --git a/src/devices/bus/snes/sdd1.h b/src/devices/bus/snes/sdd1.h
index 5164a169f65..d650f2447b5 100644
--- a/src/devices/bus/snes/sdd1.h
+++ b/src/devices/bus/snes/sdd1.h
@@ -30,8 +30,8 @@ protected:
sns_rom_sdd1_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_start() override ATTR_COLD;
+ virtual void device_reset() override ATTR_COLD;
// misc classes for the S-DD1
diff --git a/src/devices/bus/snes/sfx.cpp b/src/devices/bus/snes/sfx.cpp
index 59908b9b06e..88405e67feb 100644
--- a/src/devices/bus/snes/sfx.cpp
+++ b/src/devices/bus/snes/sfx.cpp
@@ -14,15 +14,26 @@
// sns_rom_superfx_device - constructor
//-------------------------------------------------
-DEFINE_DEVICE_TYPE(SNS_LOROM_SUPERFX, sns_rom_superfx_device, "sns_rom_superfx", "SNES Cart (LoROM) + SuperFX")
+DEFINE_DEVICE_TYPE(SNS_LOROM_SUPERFX1, sns_rom_superfx1_device, "sns_rom_superfx1", "SNES Cart (LoROM) + SuperFX 1")
+DEFINE_DEVICE_TYPE(SNS_LOROM_SUPERFX2, sns_rom_superfx2_device, "sns_rom_superfx2", "SNES Cart (LoROM) + SuperFX 2")
-sns_rom_superfx_device::sns_rom_superfx_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
- : sns_rom_device(mconfig, SNS_LOROM_SUPERFX, tag, owner, clock)
+sns_rom_superfx_device::sns_rom_superfx_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_superfx(*this, "superfx")
{
}
+sns_rom_superfx1_device::sns_rom_superfx1_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
+ : sns_rom_superfx_device(mconfig, SNS_LOROM_SUPERFX1, tag, owner, clock)
+{
+}
+
+sns_rom_superfx2_device::sns_rom_superfx2_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
+ : sns_rom_superfx_device(mconfig, SNS_LOROM_SUPERFX2, tag, owner, clock)
+{
+}
+
void sns_rom_superfx_device::device_start()
{
save_item(NAME(sfx_ram));
@@ -79,17 +90,24 @@ 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);
}
-void sns_rom_superfx_device::device_add_mconfig(machine_config &config)
+void sns_rom_superfx1_device::device_add_mconfig(machine_config &config)
+{
+ SUPERFX1(config, m_superfx, DERIVED_CLOCK(1, 1)); /* 21.48MHz, with internal /2 divider */
+ m_superfx->set_addrmap(AS_PROGRAM, &sns_rom_superfx1_device::sfx_map);
+ m_superfx->irq().set(FUNC(sns_rom_superfx1_device::snes_extern_irq_w)); /* IRQ line from cart */
+}
+
+void sns_rom_superfx2_device::device_add_mconfig(machine_config &config)
{
- SUPERFX(config, m_superfx, DERIVED_CLOCK(1, 1)); /* 21.48MHz */
- m_superfx->set_addrmap(AS_PROGRAM, &sns_rom_superfx_device::sfx_map);
- m_superfx->irq().set(FUNC(sns_rom_superfx_device::snes_extern_irq_w)); /* IRQ line from cart */
+ SUPERFX2(config, m_superfx, DERIVED_CLOCK(1, 1)); /* 21.48MHz */
+ m_superfx->set_addrmap(AS_PROGRAM, &sns_rom_superfx2_device::sfx_map);
+ m_superfx->irq().set(FUNC(sns_rom_superfx2_device::snes_extern_irq_w)); /* IRQ line from cart */
}
uint8_t sns_rom_superfx_device::chip_read(offs_t offset)
diff --git a/src/devices/bus/snes/sfx.h b/src/devices/bus/snes/sfx.h
index 7c92e411749..36fb7135c10 100644
--- a/src/devices/bus/snes/sfx.h
+++ b/src/devices/bus/snes/sfx.h
@@ -12,18 +12,15 @@
class sns_rom_superfx_device : public sns_rom_device
{
-public:
+protected:
// construction/destruction
- sns_rom_superfx_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
+ sns_rom_superfx_device(const machine_config &mconfig, device_type type, 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_start() override ATTR_COLD;
+ virtual void device_reset() override ATTR_COLD;
- virtual void device_add_mconfig(machine_config &config) 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;
@@ -40,16 +37,35 @@ protected:
void superfx_w_bank2(offs_t offset, uint8_t data);
void superfx_w_bank3(offs_t offset, uint8_t data);
-private:
required_device<superfx_device> m_superfx;
uint8_t sfx_ram[0x200000];
- void sfx_map(address_map &map);
+ void sfx_map(address_map &map) ATTR_COLD;
};
+class sns_rom_superfx1_device : public sns_rom_superfx_device
+{
+public:
+ // construction/destruction
+ sns_rom_superfx1_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
+
+protected:
+ virtual void device_add_mconfig(machine_config &config) override ATTR_COLD;
+};
+
+class sns_rom_superfx2_device : public sns_rom_superfx_device
+{
+public:
+ // construction/destruction
+ sns_rom_superfx2_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
+
+protected:
+ virtual void device_add_mconfig(machine_config &config) override ATTR_COLD;
+};
// device type definition
-DECLARE_DEVICE_TYPE(SNS_LOROM_SUPERFX, sns_rom_superfx_device)
+DECLARE_DEVICE_TYPE(SNS_LOROM_SUPERFX1, sns_rom_superfx1_device)
+DECLARE_DEVICE_TYPE(SNS_LOROM_SUPERFX2, sns_rom_superfx2_device)
#endif // MAME_BUS_SNES_SFX_H
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..f022217abe2 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"
@@ -28,8 +26,8 @@ protected:
sns_rom_sgb_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_start() override ATTR_COLD;
+ virtual void device_reset() override ATTR_COLD;
// reading and writing
virtual uint8_t read_l(offs_t offset) override;
@@ -37,18 +35,12 @@ 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);
void gb_ie_w(offs_t offset, uint8_t data);
- void supergb_map(address_map &map);
+ void supergb_map(address_map &map) ATTR_COLD;
required_device<lr35902_cpu_device> m_sgb_cpu;
required_device<gameboy_sound_device> m_sgb_apu;
@@ -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;
};
@@ -89,8 +81,8 @@ public:
protected:
// device-level overrides
- virtual void device_add_mconfig(machine_config &config) override;
- virtual const tiny_rom_entry *device_rom_region() const override;
+ virtual void device_add_mconfig(machine_config &config) override ATTR_COLD;
+ virtual const tiny_rom_entry *device_rom_region() const override ATTR_COLD;
};
@@ -102,8 +94,8 @@ public:
protected:
// device-level overrides
- virtual void device_add_mconfig(machine_config &config) override;
- virtual const tiny_rom_entry *device_rom_region() const override;
+ virtual void device_add_mconfig(machine_config &config) override ATTR_COLD;
+ virtual const tiny_rom_entry *device_rom_region() const override ATTR_COLD;
};
// device type definition
diff --git a/src/devices/bus/snes/snes_carts.cpp b/src/devices/bus/snes/snes_carts.cpp
index 274b1e0af9b..f29610c20e2 100644
--- a/src/devices/bus/snes/snes_carts.cpp
+++ b/src/devices/bus/snes/snes_carts.cpp
@@ -7,19 +7,22 @@
**********************************************************************/
#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"
#include "sgb.h"
#include "spc7110.h"
+#include "st018.h"
#include "sufami.h"
#include "upd.h"
-#include "event.h"
void snes_cart(device_slot_interface &device)
@@ -32,12 +35,13 @@ void snes_cart(device_slot_interface &device)
device.option_add_internal("lorom_obc1", SNS_LOROM_OBC1);
device.option_add_internal("lorom_sa1", SNS_LOROM_SA1); // Cart + SA1 - unsupported
device.option_add_internal("lorom_sdd1", SNS_LOROM_SDD1);
- device.option_add_internal("lorom_sfx", SNS_LOROM_SUPERFX);
+ device.option_add_internal("lorom_gsu1", SNS_LOROM_SUPERFX1);
+ device.option_add_internal("lorom_gsu2", SNS_LOROM_SUPERFX2);
device.option_add_internal("lorom_sgb", SNS_LOROM_SUPERGB); // SuperGB base cart - unsupported
device.option_add_internal("lorom_sgb2", SNS_LOROM_SUPERGB2); // SuperGB2 base cart - unsupported
device.option_add_internal("lorom_st010", SNS_LOROM_SETA10);
device.option_add_internal("lorom_st011", SNS_LOROM_SETA11);
- device.option_add_internal("lorom_st018", SNS_LOROM); // Cart + ST018 - unsupported
+ device.option_add_internal("lorom_st018", SNS_LOROM_ST018);
device.option_add_internal("lorom_sufami", SNS_LOROM_SUFAMI); // Sufami Turbo base cart
device.option_add_internal("hirom", SNS_HIROM);
device.option_add_internal("hirom_bsx", SNS_HIROM_BSX); // HiROM + BS-X slot - unsupported
@@ -65,4 +69,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 7af674e9f6d..d447c390bd2 100644
--- a/src/devices/bus/snes/snes_slot.cpp
+++ b/src/devices/bus/snes/snes_slot.cpp
@@ -48,7 +48,6 @@
***********************************************************************************************************/
-
#include "emu.h"
#include "snes_slot.h"
@@ -69,7 +68,7 @@ DEFINE_DEVICE_TYPE(SNS_BSX_CART_SLOT, sns_bsx_cart_slot_device, "sns_bsx_c
//-------------------------------------------------
device_sns_cart_interface::device_sns_cart_interface(const machine_config &mconfig, device_t &device) :
- device_slot_card_interface(mconfig, device),
+ device_interface(device, "snescart"),
m_rom(nullptr),
m_rom_size(0),
m_slot(nullptr)
@@ -89,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;
}
}
@@ -171,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);
@@ -189,6 +188,30 @@ uint8_t device_sns_cart_interface::read_open_bus()
return 0xff;
}
+//-------------------------------------------------
+// scanlines_r - get motherboard scanline count
+//-------------------------------------------------
+
+int device_sns_cart_interface::scanlines_r()
+{
+ if (m_slot != nullptr)
+ return m_slot->scanlines_r();
+
+ return 0xff;
+}
+
+//-------------------------------------------------
+// address_r - get address pin from S-CPU
+//-------------------------------------------------
+
+offs_t device_sns_cart_interface::address_r()
+{
+ if (m_slot != nullptr)
+ return m_slot->address_r();
+
+ return 0xff;
+}
+
//**************************************************************************
// LIVE DEVICE
//**************************************************************************
@@ -198,13 +221,13 @@ uint8_t device_sns_cart_interface::read_open_bus()
//-------------------------------------------------
base_sns_cart_slot_device::base_sns_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_image_interface(mconfig, *this),
+ device_cartrom_image_interface(mconfig, *this),
device_slot_interface(mconfig, *this),
m_addon(ADDON_NONE),
m_type(SNES_MODE20),
m_cart(nullptr),
m_irq_callback(*this),
- m_open_bus_callback(*this)
+ m_open_bus_callback(*this, 0xff)
{
}
@@ -240,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);
}
@@ -268,7 +288,8 @@ static const sns_slot slot_list[] =
{ SNES_OBC1, "lorom_obc1"},
{ SNES_SA1, "lorom_sa1"},
{ SNES_SDD1, "lorom_sdd1"},
- { SNES_SFX, "lorom_sfx"},
+ { SNES_GSU1, "lorom_gsu1"},
+ { SNES_GSU2, "lorom_gsu2"},
{ SNES_Z80GB, "lorom_sgb"},
{ SNES_ST010, "lorom_st010"},
{ SNES_ST011, "lorom_st011"},
@@ -311,7 +332,7 @@ static int sns_get_pcb_id(const char *slot)
{
for (auto & elem : slot_list)
{
- if (!core_stricmp(elem.slot_option, slot))
+ if (!strcmp(elem.slot_option, slot))
return elem.pcb_id;
}
@@ -522,9 +543,9 @@ static uint32_t snes_find_hilo_mode(const device_t *device, const uint8_t *buffe
}
-static int snes_find_addon_chip( const uint8_t *buffer, uint32_t start_offs )
+static int snes_find_addon_chip(const uint8_t *buffer, uint32_t start_offs, uint32_t len)
{
- /* Info mostly taken from http://snesemu.black-ship.net/misc/hardware/-from%20nsrt.edgeemu.com-chipinfo.htm */
+ /* Info mostly taken from http://black-ship.net/~tukuyomi/snesemu/misc/hardware/-from%20nsrt.edgeemu.com-chipinfo.htm */
switch (buffer[start_offs + 0x16])
{
case 0x00:
@@ -558,7 +579,12 @@ static int snes_find_addon_chip( const uint8_t *buffer, uint32_t start_offs )
case 0x15: // GSU-x
case 0x1a: // GSU-1 (21 MHz at start)
if (buffer[start_offs + 0x15] == 0x20)
- return ADDON_SFX;
+ {
+ if (len > 1048576)
+ return ADDON_GSU2;
+ else
+ return ADDON_GSU1;
+ }
break;
case 0x25:
@@ -620,15 +646,12 @@ static int snes_find_addon_chip( const uint8_t *buffer, uint32_t start_offs )
-------------------------------------------------*/
-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();
@@ -638,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
@@ -664,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())
@@ -696,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());
}
@@ -822,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;
@@ -868,7 +890,7 @@ void base_sns_cart_slot_device::setup_nvram()
if (!loaded_through_softlist())
{
int hilo_mode = snes_find_hilo_mode(this, ROM, m_cart->get_rom_size());
- uint8_t sram_size = (m_type == SNES_SFX) ? (ROM[0x00ffbd] & 0x07) : (ROM[hilo_mode + 0x18] & 0x07);
+ uint8_t sram_size = (m_type == SNES_GSU1 || m_type == SNES_GSU2) ? (ROM[0x00ffbd] & 0x07) : (ROM[hilo_mode + 0x18] & 0x07);
if (sram_size)
{
uint32_t max = (hilo_mode == 0x007fc0) ? 0x80000 : 0x20000; // MODE20 vs MODE21
@@ -944,7 +966,7 @@ void base_sns_cart_slot_device::get_cart_type_addon(const uint8_t *ROM, uint32_t
// check for add-on chips...
if (len >= hilo_mode + 0x1a)
{
- addon = snes_find_addon_chip(ROM, hilo_mode);
+ addon = snes_find_addon_chip(ROM, hilo_mode, len);
if (addon != -1)
{
// m_type handles DSP1,2,3 in the same way, but snes_add requires them to be separate...
@@ -976,8 +998,11 @@ void base_sns_cart_slot_device::get_cart_type_addon(const uint8_t *ROM, uint32_t
case ADDON_SDD1:
type = SNES_SDD1;
break;
- case ADDON_SFX:
- type = SNES_SFX;
+ case ADDON_GSU1:
+ type = SNES_GSU1;
+ break;
+ case ADDON_GSU2:
+ type = SNES_GSU2;
break;
case ADDON_SPC7110:
type = SNES_SPC7110;
@@ -1013,13 +1038,13 @@ std::string base_sns_cart_slot_device::get_default_card_software(get_default_car
{
if (hook.image_file())
{
- const char *slot_string;
uint32_t offset;
- uint32_t len = hook.image_file()->size();
+ uint64_t len;
+ hook.image_file()->length(len); // FIXME: check error return, guard against excessively large file
std::vector<uint8_t> rom(len);
int type = 0, addon = 0;
- hook.image_file()->read(&rom[0], len);
+ /*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);
@@ -1062,7 +1087,7 @@ std::string base_sns_cart_slot_device::get_default_card_software(get_default_car
break;
}
- slot_string = sns_get_slot(type);
+ char const *const slot_string = sns_get_slot(type);
return std::string(slot_string);
}
@@ -1143,26 +1168,12 @@ void base_sns_cart_slot_device::chip_write(offs_t offset, uint8_t data)
/* We use this to convert the company_id in the header to int value to be passed in companies[] */
static int char_to_int_conv( char id )
{
- int value;
-
- if (id == '1') value = 0x01;
- else if (id == '2') value = 0x02;
- else if (id == '3') value = 0x03;
- else if (id == '4') value = 0x04;
- else if (id == '5') value = 0x05;
- else if (id == '6') value = 0x06;
- else if (id == '7') value = 0x07;
- else if (id == '8') value = 0x08;
- else if (id == '9') value = 0x09;
- else if (id == 'A') value = 0x0a;
- else if (id == 'B') value = 0x0b;
- else if (id == 'C') value = 0x0c;
- else if (id == 'D') value = 0x0d;
- else if (id == 'E') value = 0x0e;
- else if (id == 'F') value = 0x0f;
- else value = 0x00;
-
- return value;
+ if (id >= '0' && id <= '9')
+ return id - '0';
+ else if (id >= 'A' && id <= 'F')
+ return id - 'A' + 0x0a;
+ else
+ return 0;
}
#define UNK "UNKNOWN"
@@ -1294,7 +1305,7 @@ void base_sns_cart_slot_device::internal_header_logging(uint8_t *ROM, uint32_t l
}
}
- addon = snes_find_addon_chip(ROM, hilo_mode);
+ addon = snes_find_addon_chip(ROM, hilo_mode, len);
if (addon != -1)
{
if (type == SNES_MODE20 && addon == SNES_DSP)
@@ -1352,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]);
@@ -1364,16 +1375,16 @@ void base_sns_cart_slot_device::internal_header_logging(uint8_t *ROM, uint32_t l
logerror( "\tSize: %d megabits [%d]\n", 1 << (ROM[hilo_mode + 0x17] - 7), ROM[hilo_mode + 0x17]);
logerror( "\tSRAM: %d kilobits [%d]\n", ROM[hilo_mode + 0x18] * 8, ROM[hilo_mode + 0x18] );
- if (ROM[hilo_mode + 0x19] < ARRAY_LENGTH(countries))
+ if (ROM[hilo_mode + 0x19] < std::size(countries))
logerror( "\tCountry: %s [%d]\n", countries[ROM[hilo_mode + 0x19]], ROM[hilo_mode + 0x19]);
else
logerror( "\tCountry: Unknown [%d]\n", ROM[hilo_mode + 0x19]);
logerror( "\tLicense: %s [%X]\n", companies[ROM[hilo_mode + 0x1a]], ROM[hilo_mode + 0x1a]);
logerror( "\tVersion: 1.%d\n", ROM[hilo_mode + 0x1b]);
- logerror( "\tInv Checksum: %X %X\n", ROM[hilo_mode + 0x1d], ROM[hilo_mode + 0x1c]);
- logerror( "\tChecksum: %X %X\n", ROM[hilo_mode + 0x1f], ROM[hilo_mode + 0x1e]);
- logerror( "\tNMI Address: %2X%2Xh\n", ROM[hilo_mode + 0x3b], ROM[hilo_mode + 0x3a]);
- logerror( "\tStart Address: %2X%2Xh\n\n", ROM[hilo_mode + 0x3d], ROM[hilo_mode + 0x3c]);
+ logerror( "\tInv Checksum: %02X%02Xh\n", ROM[hilo_mode + 0x1d], ROM[hilo_mode + 0x1c]);
+ logerror( "\tChecksum: %02X%02Xh\n", ROM[hilo_mode + 0x1f], ROM[hilo_mode + 0x1e]);
+ logerror( "\tNMI Address: %02X%02Xh\n", ROM[hilo_mode + 0x3b], ROM[hilo_mode + 0x3a]);
+ logerror( "\tStart Address: %02X%02Xh\n\n", ROM[hilo_mode + 0x3d], ROM[hilo_mode + 0x3c]);
logerror( "\tMode: %d\n", type);
}
diff --git a/src/devices/bus/snes/snes_slot.h b/src/devices/bus/snes/snes_slot.h
index 9d63a1ba9c2..59f920fa900 100644
--- a/src/devices/bus/snes/snes_slot.h
+++ b/src/devices/bus/snes/snes_slot.h
@@ -5,7 +5,7 @@
#pragma once
-#include "softlist_dev.h"
+#include "imagedev/cartrom.h"
/***************************************************************************
@@ -40,7 +40,8 @@ enum
SNES_OBC1,
SNES_SA1,
SNES_SDD1,
- SNES_SFX,
+ SNES_GSU1,
+ SNES_GSU2,
SNES_SPC7110,
SNES_SPC7110_RTC,
SNES_SRTC,
@@ -88,7 +89,8 @@ enum
ADDON_OBC1,
ADDON_SA1,
ADDON_SDD1,
- ADDON_SFX,
+ ADDON_GSU1,
+ ADDON_GSU2,
ADDON_SPC7110,
ADDON_SPC7110_RTC,
ADDON_ST010,
@@ -102,7 +104,7 @@ class base_sns_cart_slot_device;
// ======================> device_sns_cart_interface
-class device_sns_cart_interface : public device_slot_card_interface
+class device_sns_cart_interface : public device_interface
{
friend class base_sns_cart_slot_device;
@@ -121,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);
@@ -141,8 +143,10 @@ 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();
// internal state
uint8_t *m_rom;
@@ -160,7 +164,7 @@ protected:
// ======================> base_sns_cart_slot_device
class base_sns_cart_slot_device : public device_t,
- public device_image_interface,
+ public device_cartrom_image_interface,
public device_slot_interface
{
public:
@@ -170,14 +174,17 @@ public:
// configuration
auto irq_callback() { return m_irq_callback.bind(); }
auto open_bus_callback() { return m_open_bus_callback.bind(); }
+ void set_scanlines(int scanlines) { m_scanlines = scanlines; }
+ void set_address(offs_t address) { m_address = address; }
- // 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 void call_unload() override;
- virtual const software_list_loader &get_software_list_loader() const override { return rom_software_list_loader::instance(); }
+
+ virtual bool is_reset_on_load() const noexcept override { return true; }
+
+ // 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;
uint32_t snes_skip_header(const uint8_t *ROM, uint32_t snes_rom_size) const;
@@ -186,18 +193,14 @@ public:
void setup_nvram();
void internal_header_logging(uint8_t *ROM, uint32_t len);
- void save_ram() { if (m_cart && m_cart->get_nvram_size()) m_cart->save_nvram();
- if (m_cart && m_cart->get_rtc_ram_size()) m_cart->save_rtc_ram(); }
-
- virtual iodevice_t image_type() const override { return IO_CARTSLOT; }
- virtual bool is_readable() const override { return 1; }
- virtual bool is_writeable() const override { return 0; }
- virtual bool is_creatable() const override { return 0; }
- virtual bool must_be_loaded() const override { return 1; }
- virtual bool is_reset_on_load() const override { return 1; }
-
- // slot interface overrides
- virtual std::string get_default_card_software(get_default_card_software_hook &hook) const override;
+ void save_ram()
+ {
+ save_item(NAME(m_address));
+ if (m_cart && m_cart->get_nvram_size())
+ m_cart->save_nvram();
+ if (m_cart && m_cart->get_rtc_ram_size())
+ m_cart->save_rtc_ram();
+ }
// reading and writing
uint8_t read_l(offs_t offset);
@@ -209,8 +212,10 @@ 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; }
// in order to support legacy dumps + add-on CPU dump appended at the end of the file, we
// check if the required data is present and update bank map accordingly
@@ -231,9 +236,14 @@ public:
protected:
base_sns_cart_slot_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 ATTR_COLD;
+
private:
devcb_write_line m_irq_callback;
devcb_read8 m_open_bus_callback;
+ int m_scanlines;
+ offs_t m_address;
};
// ======================> sns_cart_slot_device
@@ -252,8 +262,8 @@ public:
set_fixed(false);
}
sns_cart_slot_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
- virtual const char *image_interface() const override { return "snes_cart"; }
- virtual const char *file_extensions() const override { return "sfc"; }
+ virtual const char *image_interface() const noexcept override { return "snes_cart"; }
+ virtual const char *file_extensions() const noexcept override { return "sfc"; }
};
// ======================> sns_sufami_cart_slot_device
@@ -272,9 +282,8 @@ public:
set_fixed(false);
}
sns_sufami_cart_slot_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
- virtual const char *image_interface() const override { return "st_cart"; }
- virtual const char *file_extensions() const override { return "st"; }
- virtual bool must_be_loaded() const override { return 0; }
+ virtual const char *image_interface() const noexcept override { return "st_cart"; }
+ virtual const char *file_extensions() const noexcept override { return "st"; }
};
// ======================> sns_sufami_cart_slot_device
@@ -293,9 +302,8 @@ public:
set_fixed(false);
}
sns_bsx_cart_slot_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
- virtual const char *image_interface() const override { return "bspack"; }
- virtual const char *file_extensions() const override { return "bs"; }
- virtual bool must_be_loaded() const override { return 0; }
+ virtual const char *image_interface() const noexcept override { return "bspack"; }
+ virtual const char *file_extensions() const noexcept override { return "bs"; }
};
@@ -304,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/spc7110.h b/src/devices/bus/snes/spc7110.h
index a7c798244c1..ecb43869f1c 100644
--- a/src/devices/bus/snes/spc7110.h
+++ b/src/devices/bus/snes/spc7110.h
@@ -30,7 +30,7 @@ protected:
sns_rom_spc7110_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_start() override ATTR_COLD;
class SPC7110_Decomp
{
@@ -207,7 +207,7 @@ public:
protected:
// device-level overrides
- virtual void device_start() override;
+ virtual void device_start() override ATTR_COLD;
};
// device type definition
diff --git a/src/devices/bus/snes/st018.cpp b/src/devices/bus/snes/st018.cpp
new file mode 100644
index 00000000000..adc15a921d0
--- /dev/null
+++ b/src/devices/bus/snes/st018.cpp
@@ -0,0 +1,161 @@
+// license:BSD-3-Clause
+// copyright-holders:cam900
+/***********************************************************************************************************
+
+ ARMv3 add-on chip emulation (for SNES/SFC)
+ used in carts with ST-018 add-on chips
+
+ ***********************************************************************************************************/
+
+
+#include "emu.h"
+#include "st018.h"
+
+
+// helpers
+inline uint32_t get_prg(uint8_t *CPU, uint32_t addr)
+{
+ return (CPU[addr * 4] | (CPU[addr * 4 + 1] << 8) | (CPU[addr * 4 + 2] << 16) | (CPU[addr * 4 + 3] << 24));
+}
+
+//-------------------------------------------------
+// constructor
+//-------------------------------------------------
+
+DEFINE_DEVICE_TYPE(SNS_LOROM_ST018, sns_rom_st018_device, "sns_rom_st018", "SNES Cart (LoROM) + Seta ST018")
+
+
+sns_rom_st018_device::sns_rom_st018_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
+ : sns_rom_device(mconfig, SNS_LOROM_ST018, tag, owner, clock)
+ , m_copro(*this, "copro")
+ , m_cpu2copro(*this, "cpu2copro")
+ , m_copro2cpu(*this, "copro2cpu")
+ , m_signal(false)
+ , m_copro_reset(false)
+{
+}
+
+void sns_rom_st018_device::device_start()
+{
+ m_copro_prg.resize(0x20000/sizeof(uint32_t));
+ m_copro_data.resize(0x8000/sizeof(uint32_t));
+
+ save_item(NAME(m_signal));
+ save_item(NAME(m_copro_reset));
+}
+
+void sns_rom_st018_device::device_reset()
+{
+ m_signal = false;
+ m_copro_reset = false;
+ m_copro->set_input_line(INPUT_LINE_RESET, CLEAR_LINE);
+}
+
+/*-------------------------------------------------
+ mapper specific handlers
+ -------------------------------------------------*/
+
+//-------------------------------------------------
+// Seta ST018
+//-------------------------------------------------
+
+// ST018 dump contains prg at offset 0 and data at offset 0x20000
+uint32_t sns_rom_st018_device::copro_prg_r(offs_t offset)
+{
+ return get_prg(&m_bios[0], offset);
+}
+
+uint32_t sns_rom_st018_device::copro_data_r(offs_t offset)
+{
+ return get_prg(&m_bios[0], offset + 0x20000/4);
+}
+
+uint8_t sns_rom_st018_device::status_r()
+{
+ return (m_copro2cpu->pending_r() ? 0x01 : 0) |
+ (m_signal ? 0x04 : 0) |
+ (m_cpu2copro->pending_r() ? 0x08 : 0) |
+ (m_copro_reset ? 0 : 0x80);
+}
+
+void sns_rom_st018_device::signal_w(uint8_t data)
+{
+ m_signal = true;
+}
+
+//-------------------------------------------------
+// copro_map
+//-------------------------------------------------
+
+void sns_rom_st018_device::copro_map(address_map &map)
+{
+ map(0x0000'0000, 0x0001'ffff).r(FUNC(sns_rom_st018_device::copro_prg_r));
+ map(0x4000'0000, 0x4000'0000).w(m_copro2cpu, FUNC(generic_latch_8_device::write));
+ map(0x4000'0010, 0x4000'0010).r(m_cpu2copro, FUNC(generic_latch_8_device::read)).w(FUNC(sns_rom_st018_device::signal_w));
+ map(0x4000'0020, 0x4000'0020).r(FUNC(sns_rom_st018_device::status_r));
+ map(0x4000'0020, 0x4000'002f).nopw(); // Unknown write
+ map(0xa000'0000, 0xa000'7fff).r(FUNC(sns_rom_st018_device::copro_data_r));
+ map(0xe000'0000, 0xe000'3fff).ram();
+}
+
+
+//-------------------------------------------------
+// device_add_mconfig - add device configuration
+//-------------------------------------------------
+
+void sns_rom_st018_device::device_add_mconfig(machine_config &config)
+{
+ ARM7(config, m_copro, 21440000); // TODO: ARMv3
+ m_copro->set_addrmap(AS_PROGRAM, &sns_rom_st018_device::copro_map);
+
+ GENERIC_LATCH_8(config, m_cpu2copro);
+ GENERIC_LATCH_8(config, m_copro2cpu);
+}
+
+uint8_t sns_rom_st018_device::chip_read(offs_t offset)
+{
+ uint8_t ret = 0xff;
+ switch (offset & 0x06)
+ {
+ case 0x00:
+ ret = m_copro2cpu->read();
+ break;
+ case 0x02:
+ if (!machine().side_effects_disabled())
+ m_signal = false;
+ break;
+ case 0x04:
+ ret = status_r();
+ break;
+ }
+ return ret;
+}
+
+
+void sns_rom_st018_device::chip_write(offs_t offset, uint8_t data)
+{
+ switch (offset & 0x06)
+ {
+ case 0x02:
+ m_cpu2copro->write(data);
+ break;
+ case 0x04:
+ m_copro_reset = BIT(data, 0);
+ m_copro->set_input_line(INPUT_LINE_RESET, m_copro_reset ? ASSERT_LINE : CLEAR_LINE);
+ break;
+ }
+}
+
+
+// To make faster DSP access to its internal rom, let's install read banks and map m_bios there with correct byte order
+
+void sns_rom_st018_device::speedup_addon_bios_access()
+{
+ m_copro->space(AS_PROGRAM).install_rom(0x0000'0000, 0x0001'ffff, &m_copro_prg[0]);
+ m_copro->space(AS_PROGRAM).install_rom(0xa000'0000, 0xa000'7fff, &m_copro_data[0]);
+ // copy data in the correct format
+ for (int x = 0; x < 0x8000; x++)
+ m_copro_prg[x] = m_bios[x * 4] | (m_bios[x * 4 + 1] << 8) | (m_bios[x * 4 + 2] << 16) | (m_bios[x * 4 + 3] << 24);
+ for (int x = 0; x < 0x2000; x++)
+ m_copro_data[x] = m_bios[0x20000 + x * 4] | (m_bios[0x20000 + x * 4 + 1] << 8) | (m_bios[0x20000 + x * 4 + 2] << 16) | (m_bios[0x20000 + x * 4 + 3] << 24);
+}
diff --git a/src/devices/bus/snes/st018.h b/src/devices/bus/snes/st018.h
new file mode 100644
index 00000000000..1621c7598d7
--- /dev/null
+++ b/src/devices/bus/snes/st018.h
@@ -0,0 +1,56 @@
+// license:BSD-3-Clause
+// copyright-holders:cam900
+#ifndef MAME_BUS_SNES_ST018_H
+#define MAME_BUS_SNES_ST018_H
+
+#pragma once
+
+#include "snes_slot.h"
+#include "rom.h"
+#include "cpu/arm7/arm7.h"
+#include "machine/gen_latch.h"
+
+// ======================> sns_rom_st018_device
+
+class sns_rom_st018_device : public sns_rom_device
+{
+public:
+ // construction/destruction
+ sns_rom_st018_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
+
+protected:
+ // device-level overrides
+ 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;
+
+ virtual void speedup_addon_bios_access() override;
+
+ // additional reading and writing
+ virtual uint8_t chip_read(offs_t offset) override;
+ virtual void chip_write(offs_t offset, uint8_t data) override;
+
+private:
+ uint32_t copro_prg_r(offs_t offset);
+ uint32_t copro_data_r(offs_t offset);
+
+ uint8_t status_r();
+ void signal_w(uint8_t data);
+
+ void copro_map(address_map &map) ATTR_COLD;
+
+ required_device<arm7_cpu_device> m_copro;
+ required_device<generic_latch_8_device> m_cpu2copro;
+ required_device<generic_latch_8_device> m_copro2cpu;
+
+ std::vector<uint32_t> m_copro_prg;
+ std::vector<uint32_t> m_copro_data;
+
+ bool m_signal;
+ bool m_copro_reset;
+};
+
+// device type definition
+DECLARE_DEVICE_TYPE(SNS_LOROM_ST018, sns_rom_st018_device)
+
+#endif // MAME_BUS_SNES_ST018_H
diff --git a/src/devices/bus/snes/sufami.h b/src/devices/bus/snes/sufami.h
index 1b231131a2b..feb4464576b 100644
--- a/src/devices/bus/snes/sufami.h
+++ b/src/devices/bus/snes/sufami.h
@@ -25,9 +25,9 @@ public:
protected:
// device-level overrides
- virtual void device_start() override;
+ virtual void device_start() override ATTR_COLD;
- virtual void device_add_mconfig(machine_config &config) override;
+ virtual void device_add_mconfig(machine_config &config) override ATTR_COLD;
private:
required_device<sns_sufami_cart_slot_device> m_slot1;
@@ -47,7 +47,7 @@ public:
protected:
// device-level overrides
- virtual void device_start() override;
+ virtual void device_start() override ATTR_COLD;
};
diff --git a/src/devices/bus/snes/upd.cpp b/src/devices/bus/snes/upd.cpp
index 70396938e89..aa64a656d0d 100644
--- a/src/devices/bus/snes/upd.cpp
+++ b/src/devices/bus/snes/upd.cpp
@@ -13,13 +13,13 @@
// helpers
-inline uint32_t get_prg(uint8_t *CPU, uint32_t addr)
+inline uint32_t get_prg(uint8_t const *CPU, uint32_t addr)
{
- return ((CPU[addr * 4] << 24) | (CPU[addr * 4 + 1] << 16) | (CPU[addr * 4 + 2] << 8) | 0x00);
+ return (CPU[addr * 4] << 24) | (CPU[addr * 4 + 1] << 16) | (CPU[addr * 4 + 2] << 8) | 0x00;
}
-inline uint16_t get_data(uint8_t *CPU, uint32_t addr)
+inline uint16_t get_data(uint8_t const *CPU, uint32_t addr)
{
- return ((CPU[addr * 2] << 8) | CPU[addr * 2 + 1]);
+ return (CPU[addr * 2] << 8) | CPU[addr * 2 + 1];
}
//-------------------------------------------------
@@ -141,15 +141,19 @@ void sns_rom20_necdsp_device::device_add_mconfig(machine_config &config)
uint8_t sns_rom20_necdsp_device::chip_read(offs_t offset)
{
- offset &= 0x7fff;
- return m_upd7725->snesdsp_read(offset < 0x4000);
+ if (BIT(offset, 14))
+ return m_upd7725->status_r();
+ else
+ return m_upd7725->data_r();
}
void sns_rom20_necdsp_device::chip_write(offs_t offset, uint8_t data)
{
- offset &= 0x7fff;
- m_upd7725->snesdsp_write(offset < 0x4000, data);
+ if (BIT(~offset, 14))
+ m_upd7725->data_w(data);
+ else
+ logerror("%s: Writing DSP status to %02x, ignored", machine().describe_context(), data);
}
@@ -199,15 +203,19 @@ void sns_rom21_necdsp_device::device_add_mconfig(machine_config &config)
uint8_t sns_rom21_necdsp_device::chip_read(offs_t offset)
{
- offset &= 0x1fff;
- return m_upd7725->snesdsp_read(offset < 0x1000);
+ if (BIT(offset, 12))
+ return m_upd7725->status_r();
+ else
+ return m_upd7725->data_r();
}
void sns_rom21_necdsp_device::chip_write(offs_t offset, uint8_t data)
{
- offset &= 0x1fff;
- m_upd7725->snesdsp_write(offset < 0x1000, data);
+ if (BIT(~offset, 12))
+ m_upd7725->data_w(data);
+ else
+ logerror("%s: Writing DSP status to %02x, ignored", machine().describe_context(), data);
}
@@ -220,13 +228,18 @@ void sns_rom21_necdsp_device::chip_write(offs_t offset, uint8_t data)
uint8_t sns_rom_setadsp_device::chip_read(offs_t offset)
{
if (offset >= 0x600000 && offset < 0x680000 && (offset & 0xffff) < 0x4000)
- m_upd96050->snesdsp_read((offset & 0x01) ? false : true);
+ {
+ if (BIT(offset, 0))
+ return m_upd96050->status_r();
+ else
+ return m_upd96050->data_r();
+ }
if (offset >= 0x680000 && offset < 0x700000 && (offset & 0xffff) < 0x8000)
{
- uint16_t address = offset & 0xffff;
- uint16_t temp = m_upd96050->dataram_r(address/2);
- if (offset & 1)
+ uint16_t const address = offset & 0xffff;
+ uint16_t const temp = m_upd96050->dataram_r(address >> 1);
+ if (BIT(offset, 0))
return temp >> 8;
else
return temp & 0xff;
@@ -240,27 +253,18 @@ void sns_rom_setadsp_device::chip_write(offs_t offset, uint8_t data)
{
if (offset >= 0x600000 && offset < 0x680000 && (offset & 0xffff) < 0x4000)
{
- m_upd96050->snesdsp_write((offset & 0x01) ? false : true, data);
+ if (BIT(~offset, 0))
+ m_upd96050->data_w(data);
+ else
+ logerror("%s: Writing DSP status to %02x, ignored", machine().describe_context(), data);
return;
}
if (offset >= 0x680000 && offset < 0x700000 && (offset & 0xffff) < 0x8000)
{
- uint16_t address = offset & 0xffff;
- uint16_t temp = m_upd96050->dataram_r(address/2);
-
- if (offset & 1)
- {
- temp &= 0xff;
- temp |= data << 8;
- }
- else
- {
- temp &= 0xff00;
- temp |= data;
- }
-
- m_upd96050->dataram_w(address/2, temp);
+ uint16_t const address = (offset & 0xffff) >> 1;
+ uint8_t const shift = BIT(offset, 0) << 3;
+ m_upd96050->dataram_w(address, (uint16_t(data) << 8) | data, uint16_t(0xff) << shift);
return;
}
}
@@ -322,10 +326,8 @@ void sns_rom_seta11dsp_device::device_add_mconfig(machine_config &config)
void sns_rom20_necdsp_device::speedup_addon_bios_access()
{
- m_upd7725->space(AS_PROGRAM).install_read_bank(0x0000, 0x07ff, "dsp_prg");
- m_upd7725->space(AS_DATA).install_read_bank(0x0000, 0x03ff, "dsp_data");
- membank("dsp_prg")->set_base(&m_dsp_prg[0]);
- membank("dsp_data")->set_base(&m_dsp_data[0]);
+ m_upd7725->space(AS_PROGRAM).install_rom(0x0000, 0x07ff, &m_dsp_prg[0]);
+ m_upd7725->space(AS_DATA).install_rom(0x0000, 0x03ff, &m_dsp_data[0]);
// copy data in the correct format
for (int x = 0; x < 0x800; x++)
m_dsp_prg[x] = (m_bios[x * 4] << 24) | (m_bios[x * 4 + 1] << 16) | (m_bios[x * 4 + 2] << 8) | 0x00;
@@ -335,10 +337,8 @@ void sns_rom20_necdsp_device::speedup_addon_bios_access()
void sns_rom21_necdsp_device::speedup_addon_bios_access()
{
- m_upd7725->space(AS_PROGRAM).install_read_bank(0x0000, 0x07ff, "dsp_prg");
- m_upd7725->space(AS_DATA).install_read_bank(0x0000, 0x03ff, "dsp_data");
- membank("dsp_prg")->set_base(&m_dsp_prg[0]);
- membank("dsp_data")->set_base(&m_dsp_data[0]);
+ m_upd7725->space(AS_PROGRAM).install_rom(0x0000, 0x07ff, &m_dsp_prg[0]);
+ m_upd7725->space(AS_DATA).install_rom(0x0000, 0x03ff, &m_dsp_data[0]);
// copy data in the correct format
for (int x = 0; x < 0x800; x++)
m_dsp_prg[x] = (m_bios[x * 4] << 24) | (m_bios[x * 4 + 1] << 16) | (m_bios[x * 4 + 2] << 8) | 0x00;
@@ -348,10 +348,8 @@ void sns_rom21_necdsp_device::speedup_addon_bios_access()
void sns_rom_setadsp_device::speedup_addon_bios_access()
{
- m_upd96050->space(AS_PROGRAM).install_read_bank(0x0000, 0x3fff, "dsp_prg");
- m_upd96050->space(AS_DATA).install_read_bank(0x0000, 0x07ff, "dsp_data");
- membank("dsp_prg")->set_base(&m_dsp_prg[0]);
- membank("dsp_data")->set_base(&m_dsp_data[0]);
+ m_upd96050->space(AS_PROGRAM).install_rom(0x0000, 0x3fff, &m_dsp_prg[0]);
+ m_upd96050->space(AS_DATA).install_rom(0x0000, 0x07ff, &m_dsp_data[0]);
// copy data in the correct format
for (int x = 0; x < 0x4000; x++)
m_dsp_prg[x] = (m_bios[x * 4] << 24) | (m_bios[x * 4 + 1] << 16) | (m_bios[x * 4 + 2] << 8) | 0x00;
diff --git a/src/devices/bus/snes/upd.h b/src/devices/bus/snes/upd.h
index 65dd780c725..d7ed6040795 100644
--- a/src/devices/bus/snes/upd.h
+++ b/src/devices/bus/snes/upd.h
@@ -22,8 +22,8 @@ protected:
sns_rom20_necdsp_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_add_mconfig(machine_config &config) override;
+ virtual void device_start() override ATTR_COLD;
+ virtual void device_add_mconfig(machine_config &config) override ATTR_COLD;
virtual void speedup_addon_bios_access() override;
@@ -34,8 +34,8 @@ protected:
uint32_t necdsp_prg_r(offs_t offset);
uint16_t necdsp_data_r(offs_t offset);
- void dsp_data_map_lorom(address_map &map);
- void dsp_prg_map_lorom(address_map &map);
+ void dsp_data_map_lorom(address_map &map) ATTR_COLD;
+ void dsp_prg_map_lorom(address_map &map) ATTR_COLD;
required_device<upd7725_device> m_upd7725;
@@ -56,8 +56,8 @@ protected:
sns_rom21_necdsp_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_add_mconfig(machine_config &config) override;
+ virtual void device_start() override ATTR_COLD;
+ virtual void device_add_mconfig(machine_config &config) override ATTR_COLD;
virtual void speedup_addon_bios_access() override;
@@ -68,8 +68,8 @@ protected:
uint32_t necdsp_prg_r(offs_t offset);
uint16_t necdsp_data_r(offs_t offset);
- void dsp_data_map_hirom(address_map &map);
- void dsp_prg_map_hirom(address_map &map);
+ void dsp_data_map_hirom(address_map &map) ATTR_COLD;
+ void dsp_prg_map_hirom(address_map &map) ATTR_COLD;
required_device<upd7725_device> m_upd7725;
@@ -90,7 +90,7 @@ protected:
sns_rom_setadsp_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_start() override ATTR_COLD;
// additional reading and writing
virtual uint8_t chip_read(offs_t offset) override;
@@ -99,8 +99,8 @@ protected:
virtual uint32_t setadsp_prg_r(offs_t offset);
virtual uint16_t setadsp_data_r(offs_t offset);
- void st01x_data_map(address_map &map);
- void st01x_prg_map(address_map &map);
+ void st01x_data_map(address_map &map) ATTR_COLD;
+ void st01x_prg_map(address_map &map) ATTR_COLD;
required_device<upd96050_device> m_upd96050;
@@ -119,7 +119,7 @@ public:
protected:
// device-level overrides
- virtual void device_add_mconfig(machine_config &config) override;
+ virtual void device_add_mconfig(machine_config &config) override ATTR_COLD;
};
// ======================> sns_rom_seta11dsp_device [Faster CPU than ST010]
@@ -132,7 +132,7 @@ public:
protected:
// device-level overrides
- virtual void device_add_mconfig(machine_config &config) override;
+ virtual void device_add_mconfig(machine_config &config) override ATTR_COLD;
};
@@ -154,8 +154,8 @@ public:
protected:
// device-level overrides
- virtual void device_add_mconfig(machine_config &config) override;
- virtual const tiny_rom_entry *device_rom_region() const override;
+ virtual void device_add_mconfig(machine_config &config) override ATTR_COLD;
+ virtual const tiny_rom_entry *device_rom_region() const override ATTR_COLD;
};
class sns_rom20_necdsp1b_legacy_device : public sns_rom20_necdsp_device
@@ -166,8 +166,8 @@ public:
protected:
// device-level overrides
- virtual void device_add_mconfig(machine_config &config) override;
- virtual const tiny_rom_entry *device_rom_region() const override;
+ virtual void device_add_mconfig(machine_config &config) override ATTR_COLD;
+ virtual const tiny_rom_entry *device_rom_region() const override ATTR_COLD;
};
class sns_rom20_necdsp2_legacy_device : public sns_rom20_necdsp_device
@@ -178,8 +178,8 @@ public:
protected:
// device-level overrides
- virtual void device_add_mconfig(machine_config &config) override;
- virtual const tiny_rom_entry *device_rom_region() const override;
+ virtual void device_add_mconfig(machine_config &config) override ATTR_COLD;
+ virtual const tiny_rom_entry *device_rom_region() const override ATTR_COLD;
};
class sns_rom20_necdsp3_legacy_device : public sns_rom20_necdsp_device
@@ -190,8 +190,8 @@ public:
protected:
// device-level overrides
- virtual void device_add_mconfig(machine_config &config) override;
- virtual const tiny_rom_entry *device_rom_region() const override;
+ virtual void device_add_mconfig(machine_config &config) override ATTR_COLD;
+ virtual const tiny_rom_entry *device_rom_region() const override ATTR_COLD;
};
class sns_rom20_necdsp4_legacy_device : public sns_rom20_necdsp_device
@@ -202,8 +202,8 @@ public:
protected:
// device-level overrides
- virtual void device_add_mconfig(machine_config &config) override;
- virtual const tiny_rom_entry *device_rom_region() const override;
+ virtual void device_add_mconfig(machine_config &config) override ATTR_COLD;
+ virtual const tiny_rom_entry *device_rom_region() const override ATTR_COLD;
};
class sns_rom21_necdsp1_legacy_device : public sns_rom21_necdsp_device
@@ -214,8 +214,8 @@ public:
protected:
// device-level overrides
- virtual void device_add_mconfig(machine_config &config) override;
- virtual const tiny_rom_entry *device_rom_region() const override;
+ virtual void device_add_mconfig(machine_config &config) override ATTR_COLD;
+ virtual const tiny_rom_entry *device_rom_region() const override ATTR_COLD;
};
class sns_rom_seta10dsp_legacy_device : public sns_rom_setadsp_device
@@ -226,8 +226,8 @@ public:
protected:
// device-level overrides
- virtual void device_add_mconfig(machine_config &config) override;
- virtual const tiny_rom_entry *device_rom_region() const override;
+ virtual void device_add_mconfig(machine_config &config) override ATTR_COLD;
+ virtual const tiny_rom_entry *device_rom_region() const override ATTR_COLD;
};
class sns_rom_seta11dsp_legacy_device : public sns_rom_setadsp_device
@@ -238,8 +238,8 @@ public:
protected:
// device-level overrides
- virtual void device_add_mconfig(machine_config &config) override;
- virtual const tiny_rom_entry *device_rom_region() const override;
+ virtual void device_add_mconfig(machine_config &config) override ATTR_COLD;
+ virtual const tiny_rom_entry *device_rom_region() const override ATTR_COLD;
};
DECLARE_DEVICE_TYPE(SNS_LOROM_NECDSP1_LEG, sns_rom20_necdsp1_legacy_device)
diff --git a/src/devices/bus/snes_ctrl/bcbattle.cpp b/src/devices/bus/snes_ctrl/bcbattle.cpp
index 138a4ef4669..c5d78bc04b3 100644
--- a/src/devices/bus/snes_ctrl/bcbattle.cpp
+++ b/src/devices/bus/snes_ctrl/bcbattle.cpp
@@ -26,47 +26,40 @@ void snes_bcbattle_device::device_add_mconfig(machine_config &config)
}
-//-------------------------------------------------
-// device_timer - handler timer events
-//-------------------------------------------------
-
-// This part is the hacky replacement for the real Barcode unit [shared with NES implementation]:
+// This part is a hacky replacement for the real Barcode unit [shared with NES implementation]:
// code periodically checks whether a new code has been scanned and it moves it to the
// m_current_barcode array
-void snes_bcbattle_device::device_timer(emu_timer &timer, device_timer_id id, int param, void *ptr)
+TIMER_CALLBACK_MEMBER(snes_bcbattle_device::scan_tick)
{
- if (id == TIMER_BATTLER)
+ int old = m_new_code;
+ m_new_code = m_reader->get_pending_code();
+ // has something new been scanned?
+ if (old < m_new_code)
{
- int old = m_new_code;
- m_new_code = m_reader->get_pending_code();
- // has something new been scanned?
- if (old < m_new_code)
+ if (m_reader->get_byte_length() == 13)
{
- if (m_reader->get_byte_length() == 13)
- {
- for (int i = 0; i < 13; i++)
- m_current_barcode[i] = m_reader->read_code() + '0';
- }
- else if (m_reader->get_byte_length() == 8)
- {
- for (int i = 0; i < 5; i++)
- m_current_barcode[i] = 0x20;
- for (int i = 5; i < 13; i++)
- m_current_barcode[i] = m_reader->read_code() + '0';
- }
- // read one more, to reset the internal byte counter
- m_reader->read_code();
-
- // the string "SUNSOFT" is accepted as well by Barcode World
- m_current_barcode[13] = 'E';
- m_current_barcode[14] = 'P';
- m_current_barcode[15] = 'O';
- m_current_barcode[16] = 'C';
- m_current_barcode[17] = 'H';
- m_current_barcode[18] = 0x0d;
- m_current_barcode[19] = 0x0a;
- m_pending_code = 1;
+ for (int i = 0; i < 13; i++)
+ m_current_barcode[i] = m_reader->read_code() + '0';
+ }
+ else if (m_reader->get_byte_length() == 8)
+ {
+ for (int i = 0; i < 5; i++)
+ m_current_barcode[i] = 0x20;
+ for (int i = 5; i < 13; i++)
+ m_current_barcode[i] = m_reader->read_code() + '0';
}
+ // read one more, to reset the internal byte counter
+ m_reader->read_code();
+
+ // the string "SUNSOFT" is accepted as well by Barcode World
+ m_current_barcode[13] = 'E';
+ m_current_barcode[14] = 'P';
+ m_current_barcode[15] = 'O';
+ m_current_barcode[16] = 'C';
+ m_current_barcode[17] = 'H';
+ m_current_barcode[18] = 0x0d;
+ m_current_barcode[19] = 0x0a;
+ m_pending_code = 1;
}
}
@@ -98,7 +91,7 @@ void snes_bcbattle_device::device_start()
// lacking emulation of the standalone Barcode Battler, we refresh periodically the input from the reader
// proper emulation would have the standalone unit acknowledging that a new barcode has been scanned
// and sending the proper serial bits, instead of our read_current_bit() function!
- battler_timer = timer_alloc(TIMER_BATTLER);
+ battler_timer = timer_alloc(FUNC(snes_bcbattle_device::scan_tick), this);
battler_timer->adjust(attotime::zero, 0, machine().device<cpu_device>("maincpu")->cycles_to_attotime(1000));
save_item(NAME(m_current_barcode));
@@ -121,7 +114,7 @@ void snes_bcbattle_device::device_reset()
m_transmitting = 0;
m_cur_bit = 0;
m_cur_byte = 0;
- memset(m_current_barcode, 0, ARRAY_LENGTH(m_current_barcode));
+ std::fill(std::begin(m_current_barcode), std::end(m_current_barcode), 0);
}
diff --git a/src/devices/bus/snes_ctrl/bcbattle.h b/src/devices/bus/snes_ctrl/bcbattle.h
index 808a5332f68..aaa45759bfd 100644
--- a/src/devices/bus/snes_ctrl/bcbattle.h
+++ b/src/devices/bus/snes_ctrl/bcbattle.h
@@ -30,11 +30,10 @@ public:
protected:
// device-level overrides
- virtual void device_start() override;
- virtual void device_reset() override;
- virtual void device_timer(emu_timer &timer, device_timer_id id, int param, void *ptr) override;
+ virtual void device_start() override ATTR_COLD;
+ virtual void device_reset() override ATTR_COLD;
- virtual void device_add_mconfig(machine_config &config) override;
+ virtual void device_add_mconfig(machine_config &config) override ATTR_COLD;
virtual uint8_t read_pin4() override;
virtual void write_strobe(uint8_t data) override;
@@ -42,9 +41,9 @@ protected:
int read_current_bit();
-private:
- static constexpr device_timer_id TIMER_BATTLER = 1;
+ TIMER_CALLBACK_MEMBER(scan_tick);
+private:
required_device<barcode_reader_device> m_reader;
uint8_t m_current_barcode[20];
int m_pending_code, m_new_code, m_transmitting, m_cur_bit, m_cur_byte;
diff --git a/src/devices/bus/snes_ctrl/ctrl.cpp b/src/devices/bus/snes_ctrl/ctrl.cpp
index 09079bd9c91..69fe2554725 100644
--- a/src/devices/bus/snes_ctrl/ctrl.cpp
+++ b/src/devices/bus/snes_ctrl/ctrl.cpp
@@ -35,8 +35,8 @@ DEFINE_DEVICE_TYPE(SNES_CONTROL_PORT, snes_control_port_device, "snes_control_po
// device_snes_control_port_interface - constructor
//-------------------------------------------------
-device_snes_control_port_interface::device_snes_control_port_interface(const machine_config &mconfig, device_t &device)
- : device_slot_card_interface(mconfig,device)
+device_snes_control_port_interface::device_snes_control_port_interface(const machine_config &mconfig, device_t &device) :
+ device_interface(device, "snesctrl")
{
m_port = dynamic_cast<snes_control_port_device *>(device.owner());
}
@@ -61,7 +61,10 @@ device_snes_control_port_interface::~device_snes_control_port_interface()
snes_control_port_device::snes_control_port_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) :
device_t(mconfig, SNES_CONTROL_PORT, tag, owner, clock),
- device_slot_interface(mconfig, *this), m_device(nullptr)
+ device_single_card_slot_interface<device_snes_control_port_interface>(mconfig, *this),
+ m_onscreen_cb(*this),
+ m_gunlatch_cb(*this),
+ m_device(nullptr)
{
}
@@ -81,9 +84,9 @@ snes_control_port_device::~snes_control_port_device()
void snes_control_port_device::device_start()
{
- m_device = dynamic_cast<device_snes_control_port_interface *>(get_card_device());
- m_onscreen_cb.bind_relative_to(*owner());
- m_gunlatch_cb.bind_relative_to(*owner());
+ m_device = get_card_device();
+ 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 37db69537cc..3b9ed59844d 100644
--- a/src/devices/bus/snes_ctrl/ctrl.h
+++ b/src/devices/bus/snes_ctrl/ctrl.h
@@ -20,11 +20,9 @@ class snes_control_port_device;
// ======================> device_snes_control_port_interface
-class device_snes_control_port_interface : public device_slot_card_interface
+class device_snes_control_port_interface : public device_interface
{
public:
- // construction/destruction
- device_snes_control_port_interface(const machine_config &mconfig, device_t &device);
virtual ~device_snes_control_port_interface();
virtual uint8_t read_pin4() { return 0; }
@@ -34,20 +32,23 @@ public:
virtual void port_poll() { }
protected:
+ device_snes_control_port_interface(const machine_config &mconfig, device_t &device);
+
snes_control_port_device *m_port;
};
-typedef device_delegate<bool (int16_t x, int16_t y)> snesctrl_onscreen_delegate;
#define SNESCTRL_ONSCREEN_CB(name) bool name(int16_t x, int16_t y)
-typedef device_delegate<void (int16_t x, int16_t y)> snesctrl_gunlatch_delegate;
#define SNESCTRL_GUNLATCH_CB(name) void name(int16_t x, int16_t y)
// ======================> snes_control_port_device
-class snes_control_port_device : public device_t, public device_slot_interface
+class snes_control_port_device : public device_t, public device_single_card_slot_interface<device_snes_control_port_interface>
{
public:
+ typedef device_delegate<bool (int16_t x, int16_t y)> onscreen_delegate;
+ typedef device_delegate<void (int16_t x, int16_t y)> gunlatch_delegate;
+
// construction/destruction
template <typename T>
snes_control_port_device(machine_config const &mconfig, char const *tag, device_t *owner, T &&opts, char const *dflt)
@@ -61,8 +62,8 @@ public:
snes_control_port_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock = 0);
virtual ~snes_control_port_device();
- template <typename... T> void set_onscreen_callback(T &&... args) { m_onscreen_cb = snesctrl_onscreen_delegate(std::forward<T>(args)...); }
- template <typename... T> void set_gunlatch_callback(T &&... args) { m_gunlatch_cb = snesctrl_gunlatch_delegate(std::forward<T>(args)...); }
+ template <typename... T> void set_onscreen_callback(T &&... args) { m_onscreen_cb.set(std::forward<T>(args)...); }
+ template <typename... T> void set_gunlatch_callback(T &&... args) { m_gunlatch_cb.set(std::forward<T>(args)...); }
uint8_t read_pin4();
uint8_t read_pin5();
@@ -70,15 +71,15 @@ 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
- virtual void device_start() override;
+ virtual void device_start() override ATTR_COLD;
- snesctrl_onscreen_delegate m_onscreen_cb;
- snesctrl_gunlatch_delegate m_gunlatch_cb;
+ onscreen_delegate m_onscreen_cb;
+ gunlatch_delegate m_gunlatch_cb;
device_snes_control_port_interface *m_device;
};
diff --git a/src/devices/bus/snes_ctrl/joypad.cpp b/src/devices/bus/snes_ctrl/joypad.cpp
index 359cb4cec53..b421ba1de11 100644
--- a/src/devices/bus/snes_ctrl/joypad.cpp
+++ b/src/devices/bus/snes_ctrl/joypad.cpp
@@ -18,18 +18,18 @@ DEFINE_DEVICE_TYPE(SNES_JOYPAD, snes_joypad_device, "snes_joypad", "Nintendo SNE
static INPUT_PORTS_START( snes_joypad )
PORT_START("JOYPAD")
- PORT_BIT( 0x0001, IP_ACTIVE_HIGH, IPT_BUTTON2 ) PORT_NAME("B")
- PORT_BIT( 0x0002, IP_ACTIVE_HIGH, IPT_BUTTON1 ) PORT_NAME("Y")
- PORT_BIT( 0x0004, IP_ACTIVE_HIGH, IPT_SELECT ) PORT_NAME("Select")
- PORT_BIT( 0x0008, IP_ACTIVE_HIGH, IPT_START ) PORT_NAME("Start")
+ PORT_BIT( 0x0001, IP_ACTIVE_HIGH, IPT_BUTTON2 ) PORT_NAME("%p B")
+ PORT_BIT( 0x0002, IP_ACTIVE_HIGH, IPT_BUTTON1 ) PORT_NAME("%p Y")
+ PORT_BIT( 0x0004, IP_ACTIVE_HIGH, IPT_SELECT )
+ PORT_BIT( 0x0008, IP_ACTIVE_HIGH, IPT_START )
PORT_BIT( 0x0010, IP_ACTIVE_HIGH, IPT_JOYSTICK_UP )
PORT_BIT( 0x0020, IP_ACTIVE_HIGH, IPT_JOYSTICK_DOWN )
PORT_BIT( 0x0040, IP_ACTIVE_HIGH, IPT_JOYSTICK_LEFT )
PORT_BIT( 0x0080, IP_ACTIVE_HIGH, IPT_JOYSTICK_RIGHT )
- PORT_BIT( 0x0100, IP_ACTIVE_HIGH, IPT_BUTTON3 ) PORT_NAME("A")
- PORT_BIT( 0x0200, IP_ACTIVE_HIGH, IPT_BUTTON4 ) PORT_NAME("X")
- PORT_BIT( 0x0400, IP_ACTIVE_HIGH, IPT_BUTTON6 ) PORT_NAME("L")
- PORT_BIT( 0x0800, IP_ACTIVE_HIGH, IPT_BUTTON5 ) PORT_NAME("R")
+ PORT_BIT( 0x0100, IP_ACTIVE_HIGH, IPT_BUTTON3 ) PORT_NAME("%p A")
+ PORT_BIT( 0x0200, IP_ACTIVE_HIGH, IPT_BUTTON4 ) PORT_NAME("%p X")
+ PORT_BIT( 0x0400, IP_ACTIVE_HIGH, IPT_BUTTON5 ) PORT_NAME("%p L")
+ PORT_BIT( 0x0800, IP_ACTIVE_HIGH, IPT_BUTTON6 ) PORT_NAME("%p R")
PORT_BIT( 0xf000, IP_ACTIVE_HIGH, IPT_UNUSED )
INPUT_PORTS_END
diff --git a/src/devices/bus/snes_ctrl/joypad.h b/src/devices/bus/snes_ctrl/joypad.h
index 204cceac6d5..251c96afb50 100644
--- a/src/devices/bus/snes_ctrl/joypad.h
+++ b/src/devices/bus/snes_ctrl/joypad.h
@@ -28,12 +28,12 @@ public:
snes_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;
+ virtual ioport_constructor device_input_ports() const override ATTR_COLD;
protected:
// device-level overrides
- virtual void device_start() override;
- virtual void device_reset() override;
+ virtual void device_start() override ATTR_COLD;
+ virtual void device_reset() override ATTR_COLD;
// device_snes_control_port_interface overrides
virtual uint8_t read_pin4() override;
diff --git a/src/devices/bus/snes_ctrl/miracle.cpp b/src/devices/bus/snes_ctrl/miracle.cpp
index a0d9c70874c..f20647a10b4 100644
--- a/src/devices/bus/snes_ctrl/miracle.cpp
+++ b/src/devices/bus/snes_ctrl/miracle.cpp
@@ -32,15 +32,12 @@ void snes_miracle_device::device_add_mconfig(machine_config &config)
//-------------------------------------------------
-// device_timer - handler timer events
+// strobe_tick - increment strobe counter
//-------------------------------------------------
-void snes_miracle_device::device_timer(emu_timer &timer, device_timer_id id, int param, void *ptr)
+TIMER_CALLBACK_MEMBER(snes_miracle_device::strobe_tick)
{
- if (id == TIMER_STROBE_ON)
- {
- m_strobe_clock++;
- }
+ m_strobe_clock++;
}
//**************************************************************************
@@ -70,7 +67,7 @@ snes_miracle_device::snes_miracle_device(const machine_config &mconfig, const ch
void snes_miracle_device::device_start()
{
- strobe_timer = timer_alloc(TIMER_STROBE_ON);
+ strobe_timer = timer_alloc(FUNC(snes_miracle_device::strobe_tick), this);
strobe_timer->adjust(attotime::never);
save_item(NAME(m_strobe_on));
save_item(NAME(m_sent_bits));
diff --git a/src/devices/bus/snes_ctrl/miracle.h b/src/devices/bus/snes_ctrl/miracle.h
index cb1b89a6eda..602bacdb6e6 100644
--- a/src/devices/bus/snes_ctrl/miracle.h
+++ b/src/devices/bus/snes_ctrl/miracle.h
@@ -31,17 +31,14 @@ public:
snes_miracle_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
protected:
- static constexpr device_timer_id TIMER_STROBE_ON = 0;
-
static constexpr int XMIT_RING_SIZE = 64;
static constexpr int RECV_RING_SIZE = 64;
// device-level overrides
- virtual void device_start() override;
- virtual void device_reset() override;
- virtual void device_timer(emu_timer &timer, device_timer_id id, int param, void *ptr) override;
+ virtual void device_start() override ATTR_COLD;
+ virtual void device_reset() override ATTR_COLD;
- virtual void device_add_mconfig(machine_config &config) override;
+ virtual void device_add_mconfig(machine_config &config) override ATTR_COLD;
// serial overrides
virtual void rcv_complete() override; // Rx completed receiving byte
@@ -54,6 +51,8 @@ protected:
void xmit_char(uint8_t data);
+ TIMER_CALLBACK_MEMBER(strobe_tick);
+
required_device<midi_port_device> m_midiin, m_midiout;
emu_timer *strobe_timer;
diff --git a/src/devices/bus/snes_ctrl/mouse.cpp b/src/devices/bus/snes_ctrl/mouse.cpp
index 636a4f3f640..24e3e13ba23 100644
--- a/src/devices/bus/snes_ctrl/mouse.cpp
+++ b/src/devices/bus/snes_ctrl/mouse.cpp
@@ -31,11 +31,11 @@ static INPUT_PORTS_START( snes_mouse )
// due to the relative nature of movement detection in SNES mouse, when we wrap the system would
// detect a sudden jump in the wrong direction, making the usage unfriendly...
PORT_START("MOUSE_X")
- PORT_BIT( 0x1ff, 0x100, IPT_LIGHTGUN_X ) PORT_NAME("Superscope X Axis") PORT_SENSITIVITY(30) PORT_KEYDELTA(5)
+ PORT_BIT( 0x1ff, 0x100, IPT_LIGHTGUN_X ) PORT_NAME("Mouse X Axis") PORT_SENSITIVITY(30) PORT_KEYDELTA(5)
// PORT_BIT( 0xff, 0x00, IPT_MOUSE_X) PORT_SENSITIVITY(30) PORT_KEYDELTA(5)
PORT_START("MOUSE_Y")
- PORT_BIT( 0x1ff, 0x100, IPT_LIGHTGUN_Y) PORT_NAME("Superscope Y Axis") PORT_SENSITIVITY(30) PORT_KEYDELTA(5)
+ PORT_BIT( 0x1ff, 0x100, IPT_LIGHTGUN_Y) PORT_NAME("Mouse Y Axis") PORT_SENSITIVITY(30) PORT_KEYDELTA(5)
// PORT_BIT( 0xff, 0x00, IPT_MOUSE_Y) PORT_SENSITIVITY(30) PORT_KEYDELTA(5)
INPUT_PORTS_END
diff --git a/src/devices/bus/snes_ctrl/mouse.h b/src/devices/bus/snes_ctrl/mouse.h
index cd6f3839950..08e91e3da75 100644
--- a/src/devices/bus/snes_ctrl/mouse.h
+++ b/src/devices/bus/snes_ctrl/mouse.h
@@ -28,12 +28,12 @@ public:
snes_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;
+ virtual ioport_constructor device_input_ports() const override ATTR_COLD;
protected:
// device-level overrides
- virtual void device_start() override;
- virtual void device_reset() override;
+ virtual void device_start() override ATTR_COLD;
+ virtual void device_reset() override ATTR_COLD;
// device_snes_control_port_interface overrides
virtual uint8_t read_pin4() override;
diff --git a/src/devices/bus/snes_ctrl/multitap.h b/src/devices/bus/snes_ctrl/multitap.h
index 779744fe753..0099bca5b9d 100644
--- a/src/devices/bus/snes_ctrl/multitap.h
+++ b/src/devices/bus/snes_ctrl/multitap.h
@@ -29,12 +29,12 @@ public:
protected:
// device-level overrides
- virtual void device_start() override;
- virtual void device_reset() override;
+ virtual void device_start() override ATTR_COLD;
+ virtual void device_reset() override ATTR_COLD;
// optional information overrides
- virtual ioport_constructor device_input_ports() const override;
- virtual void device_add_mconfig(machine_config &config) override;
+ virtual ioport_constructor device_input_ports() const override ATTR_COLD;
+ virtual void device_add_mconfig(machine_config &config) override ATTR_COLD;
// device_snes_control_port_interface overrides
virtual uint8_t read_pin4() override;
diff --git a/src/devices/bus/snes_ctrl/pachinko.h b/src/devices/bus/snes_ctrl/pachinko.h
index 0fffa05767a..d2f1cb52b48 100644
--- a/src/devices/bus/snes_ctrl/pachinko.h
+++ b/src/devices/bus/snes_ctrl/pachinko.h
@@ -28,12 +28,12 @@ public:
snes_pachinko_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;
+ virtual ioport_constructor device_input_ports() const override ATTR_COLD;
protected:
// device-level overrides
- virtual void device_start() override;
- virtual void device_reset() override;
+ virtual void device_start() override ATTR_COLD;
+ virtual void device_reset() override ATTR_COLD;
// device_snes_control_port_interface overrides
virtual uint8_t read_pin4() override;
diff --git a/src/devices/bus/snes_ctrl/sscope.h b/src/devices/bus/snes_ctrl/sscope.h
index b81afda179d..3c4d718c010 100644
--- a/src/devices/bus/snes_ctrl/sscope.h
+++ b/src/devices/bus/snes_ctrl/sscope.h
@@ -6,8 +6,8 @@
**********************************************************************/
-#ifndef MAME_BUS_SNES_CTRL_SUPERSCOPE_H
-#define MAME_BUS_SNES_CTRL_SUPERSCOPE_H
+#ifndef MAME_BUS_SNES_CTRL_SSCOPE_H
+#define MAME_BUS_SNES_CTRL_SSCOPE_H
#pragma once
@@ -28,12 +28,12 @@ public:
snes_sscope_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;
+ virtual ioport_constructor device_input_ports() const override ATTR_COLD;
protected:
// device-level overrides
- virtual void device_start() override;
- virtual void device_reset() override;
+ virtual void device_start() override ATTR_COLD;
+ virtual void device_reset() override ATTR_COLD;
// device_snes_control_port_interface overrides
virtual uint8_t read_pin4() override;
@@ -55,4 +55,4 @@ private:
// device type definition
DECLARE_DEVICE_TYPE(SNES_SUPERSCOPE, snes_sscope_device)
-#endif // MAME_BUS_SNES_CTRL_SUPERSCOPE_H
+#endif // MAME_BUS_SNES_CTRL_SSCOPE_H
diff --git a/src/devices/bus/snes_ctrl/twintap.h b/src/devices/bus/snes_ctrl/twintap.h
index ccd1d4cfef8..60345cc8048 100644
--- a/src/devices/bus/snes_ctrl/twintap.h
+++ b/src/devices/bus/snes_ctrl/twintap.h
@@ -28,12 +28,12 @@ public:
snes_twintap_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;
+ virtual ioport_constructor device_input_ports() const override ATTR_COLD;
protected:
// device-level overrides
- virtual void device_start() override;
- virtual void device_reset() override;
+ virtual void device_start() override ATTR_COLD;
+ virtual void device_reset() override ATTR_COLD;
// device_snes_control_port_interface overrides
virtual uint8_t read_pin4() override;
diff --git a/src/devices/bus/spc1000/exp.cpp b/src/devices/bus/spc1000/exp.cpp
index 5a987845a43..ba8b22c1456 100644
--- a/src/devices/bus/spc1000/exp.cpp
+++ b/src/devices/bus/spc1000/exp.cpp
@@ -17,8 +17,8 @@
DEFINE_DEVICE_TYPE(SPC1000_EXP_SLOT, spc1000_exp_device, "spc1000_exp", "Samsung SPC-1000 expansion")
-device_spc1000_card_interface::device_spc1000_card_interface(const machine_config &mconfig, device_t &device)
- : device_slot_card_interface(mconfig, device)
+device_spc1000_card_interface::device_spc1000_card_interface(const machine_config &mconfig, device_t &device) :
+ device_interface(device, "spc1000exp")
{
}
@@ -37,7 +37,7 @@ device_spc1000_card_interface::~device_spc1000_card_interface()
//-------------------------------------------------
spc1000_exp_device::spc1000_exp_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) :
device_t(mconfig, SPC1000_EXP_SLOT, tag, owner, clock),
- device_slot_interface(mconfig, *this),
+ device_single_card_slot_interface<device_spc1000_card_interface>(mconfig, *this),
m_card(nullptr)
{
}
@@ -57,17 +57,17 @@ spc1000_exp_device::~spc1000_exp_device()
void spc1000_exp_device::device_start()
{
- m_card = dynamic_cast<device_spc1000_card_interface *>(get_card_device());
+ m_card = get_card_device();
}
/*-------------------------------------------------
read
-------------------------------------------------*/
-READ8_MEMBER(spc1000_exp_device::read)
+uint8_t spc1000_exp_device::read(offs_t offset)
{
if (m_card)
- return m_card->read(space, offset);
+ return m_card->read(offset);
else
return 0xff;
}
@@ -76,8 +76,8 @@ READ8_MEMBER(spc1000_exp_device::read)
write
-------------------------------------------------*/
-WRITE8_MEMBER(spc1000_exp_device::write)
+void spc1000_exp_device::write(offs_t offset, uint8_t data)
{
if (m_card)
- m_card->write(space, offset, data);
+ m_card->write(offset, data);
}
diff --git a/src/devices/bus/spc1000/exp.h b/src/devices/bus/spc1000/exp.h
index d10fe516401..78cf7776327 100644
--- a/src/devices/bus/spc1000/exp.h
+++ b/src/devices/bus/spc1000/exp.h
@@ -7,15 +7,15 @@
// ======================> device_spc1000_card_interface
-class device_spc1000_card_interface : public device_slot_card_interface
+class device_spc1000_card_interface : public device_interface
{
public:
// construction/destruction
virtual ~device_spc1000_card_interface();
// reading and writing
- virtual DECLARE_READ8_MEMBER(read) { return 0xff; }
- virtual DECLARE_WRITE8_MEMBER(write) { }
+ virtual uint8_t read(offs_t offset) { return 0xff; }
+ virtual void write(offs_t offset, uint8_t data) { }
protected:
device_spc1000_card_interface(const machine_config &mconfig, device_t &device);
@@ -24,7 +24,7 @@ protected:
// ======================> spc1000_exp_device
-class spc1000_exp_device : public device_t, public device_slot_interface
+class spc1000_exp_device : public device_t, public device_single_card_slot_interface<device_spc1000_card_interface>
{
public:
// construction/destruction
@@ -41,12 +41,12 @@ public:
virtual ~spc1000_exp_device();
// reading and writing
- virtual DECLARE_READ8_MEMBER(read);
- virtual DECLARE_WRITE8_MEMBER(write);
+ uint8_t read(offs_t offset);
+ void write(offs_t offset, uint8_t data);
protected:
// device-level overrides
- virtual void device_start() override;
+ virtual void device_start() override ATTR_COLD;
device_spc1000_card_interface* m_card;
};
diff --git a/src/devices/bus/spc1000/fdd.cpp b/src/devices/bus/spc1000/fdd.cpp
index d89035df9c1..fe668127328 100644
--- a/src/devices/bus/spc1000/fdd.cpp
+++ b/src/devices/bus/spc1000/fdd.cpp
@@ -14,17 +14,17 @@
IMPLEMENTATION
***************************************************************************/
-READ8_MEMBER(spc1000_fdd_exp_device::i8255_c_r)
+uint8_t spc1000_fdd_exp_device::i8255_c_r()
{
return m_i8255_0_pc >> 4;
}
-WRITE8_MEMBER(spc1000_fdd_exp_device::i8255_b_w)
+void spc1000_fdd_exp_device::i8255_b_w(uint8_t data)
{
m_i8255_portb = data;
}
-WRITE8_MEMBER(spc1000_fdd_exp_device::i8255_c_w)
+void spc1000_fdd_exp_device::i8255_c_w(uint8_t data)
{
m_i8255_1_pc = data;
}
@@ -33,33 +33,38 @@ WRITE8_MEMBER(spc1000_fdd_exp_device::i8255_c_w)
// fdc interrupt
//-------------------------------------------------
-READ8_MEMBER( spc1000_fdd_exp_device::tc_r )
+uint8_t spc1000_fdd_exp_device::tc_r()
{
- logerror("%s: tc_r\n", machine().describe_context());
+ if (!machine().side_effects_disabled())
+ {
+ logerror("%s: tc_r\n", machine().describe_context());
- // toggle tc on read
- m_fdc->tc_w(true);
- m_timer_tc->adjust(attotime::zero);
+ // toggle tc on read
+ m_fdc->tc_w(true);
+ m_timer_tc->adjust(attotime::zero);
+ }
return 0xff;
}
-WRITE8_MEMBER( spc1000_fdd_exp_device::control_w )
+void spc1000_fdd_exp_device::control_w(uint8_t data)
{
logerror("%s: control_w(%02x)\n", machine().describe_context(), data);
// bit 0, motor on signal
- if (m_fd0)
- m_fd0->mon_w(!BIT(data, 0));
- if (m_fd1)
- m_fd1->mon_w(!BIT(data, 0));
+ for (auto &fd : m_fd)
+ {
+ floppy_image_device *img = fd->get_device();
+ if (img)
+ img->mon_w(!BIT(data, 0));
+ }
}
void spc1000_fdd_exp_device::sd725_mem(address_map &map)
{
map.unmap_value_high();
- map(0x0000, 0x1fff).rom();
- map(0x2000, 0xffff).ram();
+ map(0x0000, 0x0fff).rom().region("fdccpu", 0);
+ map(0x4000, 0x7fff).ram(); // 16K dynamic RAM (2x TMS4416-15NL)
}
void spc1000_fdd_exp_device::sd725_io(address_map &map)
@@ -82,10 +87,11 @@ static void sd725_floppies(device_slot_interface &device)
void spc1000_fdd_exp_device::device_add_mconfig(machine_config &config)
{
- // sub CPU (5 inch floppy drive)
- Z80(config, m_cpu, XTAL(4'000'000));
+ // Z80A sub CPU (5 inch floppy drive)
+ Z80(config, m_cpu, 8_MHz_XTAL / 2);
m_cpu->set_addrmap(AS_PROGRAM, &spc1000_fdd_exp_device::sd725_mem);
m_cpu->set_addrmap(AS_IO, &spc1000_fdd_exp_device::sd725_io);
+ m_cpu->set_irq_acknowledge_callback(NAME([](device_t &, int) { return 0xcf; })); // vector to 0008 in IM 0
I8255(config, m_ppi);
m_ppi->in_pa_callback().set(m_ppi, FUNC(i8255_device::pb_r));
@@ -95,16 +101,16 @@ void spc1000_fdd_exp_device::device_add_mconfig(machine_config &config)
m_ppi->out_pc_callback().set(FUNC(spc1000_fdd_exp_device::i8255_c_w));
// floppy disk controller
- UPD765A(config, m_fdc, 4'000'000, true, true);
+ UPD765A(config, m_fdc, 8_MHz_XTAL / 2, true, true);
m_fdc->intrq_wr_callback().set_inputline(m_cpu, INPUT_LINE_IRQ0);
// floppy drives
- FLOPPY_CONNECTOR(config, "upd765:0", sd725_floppies, "sd320", floppy_image_device::default_floppy_formats);
- FLOPPY_CONNECTOR(config, "upd765:1", sd725_floppies, "sd320", floppy_image_device::default_floppy_formats);
+ FLOPPY_CONNECTOR(config, "upd765:0", sd725_floppies, "sd320", floppy_image_device::default_mfm_floppy_formats);
+ FLOPPY_CONNECTOR(config, "upd765:1", sd725_floppies, "sd320", floppy_image_device::default_mfm_floppy_formats);
}
ROM_START( spc1000_fdd )
- ROM_REGION(0x10000, "fdccpu", 0)
+ ROM_REGION(0x1000, "fdccpu", 0)
ROM_LOAD("sd725a.bin", 0x0000, 0x1000, CRC(96ac2eb8) SHA1(8e9d8f63a7fb87af417e95603e71cf537a6e83f1))
ROM_END
@@ -138,7 +144,8 @@ spc1000_fdd_exp_device::spc1000_fdd_exp_device(const machine_config &mconfig, co
m_cpu(*this, "fdccpu"),
m_fdc(*this, "upd765"),
m_ppi(*this, "d8255_master"),
- m_fd0(nullptr), m_fd1(nullptr), m_timer_tc(nullptr), m_i8255_0_pc(0), m_i8255_1_pc(0), m_i8255_portb(0)
+ m_fd(*this, "upd765:%u", 0U),
+ m_timer_tc(nullptr), m_i8255_0_pc(0), m_i8255_1_pc(0), m_i8255_portb(0)
{
}
@@ -149,11 +156,7 @@ spc1000_fdd_exp_device::spc1000_fdd_exp_device(const machine_config &mconfig, co
void spc1000_fdd_exp_device::device_start()
{
- m_timer_tc = timer_alloc(TIMER_TC);
- m_timer_tc->adjust(attotime::never);
-
- m_fd0 = subdevice<floppy_connector>("upd765:0")->get_device();
- m_fd1 = subdevice<floppy_connector>("upd765:1")->get_device();
+ m_timer_tc = timer_alloc(FUNC(spc1000_fdd_exp_device::tc_off), this);
}
//-------------------------------------------------
@@ -162,27 +165,18 @@ void spc1000_fdd_exp_device::device_start()
void spc1000_fdd_exp_device::device_reset()
{
- m_cpu->set_input_line_vector(0, 0); // Z80
-
- // enable rom (is this really needed? it does not seem necessary for FDD to work)
- m_cpu->space(AS_PROGRAM).install_rom(0x0000, 0x0fff, 0x2000, memregion("fdccpu")->base());
}
-void spc1000_fdd_exp_device::device_timer(emu_timer &timer, device_timer_id id, int param, void *ptr)
+TIMER_CALLBACK_MEMBER(spc1000_fdd_exp_device::tc_off)
{
- switch (id)
- {
- case TIMER_TC:
- m_fdc->tc_w(false);
- break;
- }
+ m_fdc->tc_w(false);
}
/*-------------------------------------------------
read
-------------------------------------------------*/
-READ8_MEMBER(spc1000_fdd_exp_device::read)
+uint8_t spc1000_fdd_exp_device::read(offs_t offset)
{
// this should be m_ppi->read on the whole 0x00-0x03 range?
if (offset >= 3)
@@ -207,7 +201,7 @@ READ8_MEMBER(spc1000_fdd_exp_device::read)
// write
//-------------------------------------------------
-WRITE8_MEMBER(spc1000_fdd_exp_device::write)
+void spc1000_fdd_exp_device::write(offs_t offset, uint8_t data)
{
// this should be m_ppi->write on the whole 0x00-0x03 range?
if (offset < 3)
diff --git a/src/devices/bus/spc1000/fdd.h b/src/devices/bus/spc1000/fdd.h
index 93994369efe..e571ef1b544 100644
--- a/src/devices/bus/spc1000/fdd.h
+++ b/src/devices/bus/spc1000/fdd.h
@@ -25,25 +25,22 @@ public:
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;
- virtual void device_timer(emu_timer &timer, device_timer_id id, int param, void *ptr) override;
+ 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;
+ virtual const tiny_rom_entry *device_rom_region() const override ATTR_COLD;
- virtual DECLARE_READ8_MEMBER(read) override;
- virtual DECLARE_WRITE8_MEMBER(write) override;
+ virtual uint8_t read(offs_t offset) override;
+ virtual void write(offs_t offset, uint8_t data) override;
private:
- static constexpr device_timer_id TIMER_TC = 0;
+ TIMER_CALLBACK_MEMBER(tc_off);
// internal state
required_device<z80_device> m_cpu;
required_device<upd765a_device> m_fdc;
required_device<i8255_device> m_ppi;
-
- floppy_image_device *m_fd0;
- floppy_image_device *m_fd1;
+ required_device_array<floppy_connector, 2> m_fd;
emu_timer *m_timer_tc;
@@ -51,15 +48,15 @@ private:
uint8_t m_i8255_1_pc;
uint8_t m_i8255_portb;
- DECLARE_WRITE8_MEMBER(i8255_b_w);
- DECLARE_READ8_MEMBER(i8255_c_r);
- DECLARE_WRITE8_MEMBER(i8255_c_w);
+ void i8255_b_w(uint8_t data);
+ uint8_t i8255_c_r();
+ void i8255_c_w(uint8_t data);
- DECLARE_READ8_MEMBER(tc_r);
- DECLARE_WRITE8_MEMBER(control_w);
+ uint8_t tc_r();
+ void control_w(uint8_t data);
- void sd725_io(address_map &map);
- void sd725_mem(address_map &map);
+ void sd725_io(address_map &map) ATTR_COLD;
+ void sd725_mem(address_map &map) ATTR_COLD;
};
diff --git a/src/devices/bus/spc1000/vdp.cpp b/src/devices/bus/spc1000/vdp.cpp
index 61f496183b7..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?
}
@@ -74,7 +74,7 @@ void spc1000_vdp_exp_device::device_reset()
/*-------------------------------------------------
read
-------------------------------------------------*/
-READ8_MEMBER(spc1000_vdp_exp_device::read)
+uint8_t spc1000_vdp_exp_device::read(offs_t offset)
{
if (!(offset & 0x800))
return 0xff;
@@ -89,7 +89,7 @@ READ8_MEMBER(spc1000_vdp_exp_device::read)
// write
//-------------------------------------------------
-WRITE8_MEMBER(spc1000_vdp_exp_device::write)
+void spc1000_vdp_exp_device::write(offs_t offset, uint8_t data)
{
if (offset & 0x800)
{
diff --git a/src/devices/bus/spc1000/vdp.h b/src/devices/bus/spc1000/vdp.h
index 757c6cda0ec..b7612f0dad0 100644
--- a/src/devices/bus/spc1000/vdp.h
+++ b/src/devices/bus/spc1000/vdp.h
@@ -23,14 +23,14 @@ public:
protected:
// device-level overrides
- virtual void device_start() override;
- virtual void device_reset() override;
- virtual void device_add_mconfig(machine_config &config) override;
+ 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;
- virtual DECLARE_READ8_MEMBER(read) override;
- virtual DECLARE_WRITE8_MEMBER(write) override;
+ 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 c171f54cd33..1d08e95673b 100644
--- a/src/devices/bus/spectrum/beta.cpp
+++ b/src/devices/bus/spectrum/beta.cpp
@@ -1,5 +1,5 @@
// license:BSD-3-Clause
-// copyright-holders:Nigel Barnes, David Haywood
+// copyright-holders:Nigel Barnes, David Haywood, MetalliC
/*********************************************************************
Technology Research Beta Disk interface & clones
@@ -9,38 +9,50 @@
'hand made' PCB with V2 ROM:
- possible prototype / low production run
- - 4k ROM
+ - 4Kbyte ROM
+ - D0 and D7 ROM lines swapped
- FORMAT, COPY etc. must be loaded from a disk to be used
- disks are password protected
- - uses 1771 disk controller
+ - uses FD1771 disk controller
+ - disk format: FM, 7 or 10 256-byte sectors per track, 2 system sectors (max 30 files)
+ - supports up to 3 drives
https://www.youtube.com/watch?v=gSJIuZjbFYs
Original Beta Disk release with V3 ROM:
- - same features as above
- - uses a 1793 controller
+ similar to above but:
+ - uses a FD1793 controller
+ - disk format: MFM, 16 256-byte sectors per track, 9 system sectors (max 128 files)
+ - port FF bits was changed
+ - supports up to 4 drives
Re-release dubbed "Beta Disk plus" with V4 ROM:
- - many operations moved into a larger capacity (8k) ROM rather
- than requiring a utility disk
- - uses a 1793 controller
- - adds 'magic button' to dump the running state of the machine
- to disk
+ similar to above but:
+ - 8Kbyte ROM
+ - FORMAT and COPY commands moved into ROM
+ - adds 'magic button' to dump the running state of the machine to disk
- disk password system removed
+ - adds auto boot feature
Many clones exist, some specific to the various Spectrum clones.
- (not yet added)
+
+ Original Beta Disk (V2) clones
+ - Sandy FDD2 SP-DOS (straight clone?)
Original Beta Disk (V3) clones
- - Sandy FDD2 SP-DOS
- - AC DOS P.Z.APINA
+ - AC DOS P.Z.APINA (straight clone?)
Beta Disk plus (V4) clones
- - CAS DOS Cheyenne Advanced System
- - CBI-95
- - SYNCHRON IDS91
- - SYNCHRON IDS2001ne
- - ARCADE AR-20
- - Vision Desktop Betadisk
+ - CAS DOS Cheyenne Advanced System (supposedly straight clone)
+ - common Brazilian clones: usually use FD1797 instead of FD1793, no ROM bits D0/D7 swap, DOS ROM area 3CXX might be disabled, equiped with printer port.
+ - CBI-95
+ - SYNCHRON IDS91
+ - SYNCHRON IDS2001ne (added interface disable jumper)
+ - ARCADE AR-20
+ - MIDAS Gammadisk - 3 versions known to exists:
+ - straight clone
+ - added i8255 PPI for joystick and printer, uses 32KByte ROM with modified BASIC48 ROM in one half and TR-DOS 4.12 in another
+ - same as above plus 6850 ACIA
+ - number of straight clones with "Vision Desktop" boot ROM
Some units also exist that allow population of both V3 and V4
ROM types with a switch (unofficial, for compatibility?)
@@ -49,12 +61,6 @@
NOTE:
- ROMs really need verifying, real dumps appear to be bitswapped
- on original boards, so we're using those ones where possible,
- however sizes are unconfirmed (some sources state that the data
- is duplicated across the 16k in ROM, others state it just mirrors
- in memory) and some might be modified or bad.
-
beta128.cpp could be modified to expand on this, as it builds
on the features of the betaplus, but for now I've kept them
separate as the enable / disable mechanisms are different and
@@ -62,17 +68,24 @@
---
- Based on older BDI schematics, it seems the logic is like:
+ Based on older BDI schematics, the logic is:
memory access 0x3CXX (any type of access: code or data, read or write) -> temporary use BDI ROM (NOT permanent latch/switch like in beta128)
memory access <0x4000 area and BDI ROM_latch==true -> use BDI ROM
- IO write to port 0bxxxxxx00 -> D7 master_latch, 0=enable, 1=disable
+ IO write to port 0bxxxxxx00 -> D7 - BDI I/O access, 0=enable, 1=disable (when BDI I/O enabled - /IORQ passthrough to next expansions is blocked)
+ CBI clones: D6 - 1=disable permanent BDI ROM mapping at 3c00-3cff, 0=enable (like original BDI)
+ Gammadisk : D6 - 0 - enable Gammadisk I/O (/IORQ passthrough blocked), 1=disable all Gammadisk I/O (enable /IORQ passthrough)
+ D7 - (have effect if D6 is 0) 0=enable FDC I/O, 1=enable PPI and ACIA I/O;
- while master_latch is enabled access to regular Spectrum IO is blocked (output /IORQ forced to 1) but enabled BDI ports:
+ BDI I/O ports:
- IO write to port 0b1xxxx111 -> D7 BDI ROM_latch (0=enable, 1=disble), D6 - FDC DDEN, D4 - SIDE, D3 - FDC HLT, D2 - FDC /MR (reset), D0-1 - floppy drive select.
+ IO write to port 0b1xxxx111 ->
+ V2: D7 BDI ROM_latch (0=enable, 1=disble), D4 - FDC HLT, D3 - SIDE, D0-2 - floppy drive select (bitmask, active low).
+ V3-V4: D7 BDI ROM_latch (0=enable, 1=disble), D6 - FDC DDEN, D4 - SIDE, D3 - FDC HLT, D2 - FDC /MR (reset), D0-1 - floppy drive select (binary value).
+ CBI clones: D5 - printer port /STROBE
IO read port 0b1xxxx111 <- D7 - FDC INTRQ, D6 - FDC DRQ
+ CBI clones: D5 - printer port BUSY, D4 - printer standard select jumper (ABICOMP / MSX1.1)
IO read/write ports 0b0YYxx111 - access FDC ports YY
So mostly the same as beta128, except for new BDI ROM_latch bit
@@ -83,14 +96,19 @@
#include "emu.h"
#include "beta.h"
+#include "formats/trd_dsk.h"
+
/***************************************************************************
DEVICE DEFINITIONS
***************************************************************************/
-DEFINE_DEVICE_TYPE(SPECTRUM_BETAV2, spectrum_betav2_device, "spectrum_betav2", "TR Beta Disk Interface (older, FD1771 based)")
-DEFINE_DEVICE_TYPE(SPECTRUM_BETAV3, spectrum_betav3_device, "spectrum_betav3", "TR Beta Disk Interface (newer, FD1793 based)")
+DEFINE_DEVICE_TYPE(SPECTRUM_BETAV2, spectrum_betav2_device, "spectrum_betav2", "TR Beta Disk Interface V2 (FD1771 based)")
+DEFINE_DEVICE_TYPE(SPECTRUM_BETAV3, spectrum_betav3_device, "spectrum_betav3", "TR Beta Disk Interface V3 (FD1793 based)")
DEFINE_DEVICE_TYPE(SPECTRUM_BETAPLUS, spectrum_betaplus_device, "spectrum_betaplus", "TR Beta Disk Plus Interface")
+DEFINE_DEVICE_TYPE(SPECTRUM_BETACLONE,spectrum_betaclone_device,"spectrum_betaclone","Beta Disk Plus clones")
+DEFINE_DEVICE_TYPE(SPECTRUM_BETACBI, spectrum_betacbi_device, "spectrum_betacbi", "CBI-95 Disk Interface")
+DEFINE_DEVICE_TYPE(SPECTRUM_GAMMA, spectrum_gamma_device, "spectrum_gamma", "MIDAS Gammadisk Interface")
//-------------------------------------------------
// SLOT_INTERFACE( beta_floppies )
@@ -99,15 +117,20 @@ DEFINE_DEVICE_TYPE(SPECTRUM_BETAPLUS, spectrum_betaplus_device, "spectrum_betapl
static void beta_floppies(device_slot_interface &device)
{
device.option_add("525qd", FLOPPY_525_QD);
+ device.option_add("525dd", FLOPPY_525_DD);
+ device.option_add("35dd", FLOPPY_35_DD);
+ device.option_add("3dsdd", FLOPPY_3_DSDD);
}
//-------------------------------------------------
-// floppy_format_type floppy_formats
+// floppy_formats
//-------------------------------------------------
-FLOPPY_FORMATS_MEMBER(spectrum_betav2_device::floppy_formats)
- FLOPPY_TRD_FORMAT
-FLOPPY_FORMATS_END
+void spectrum_betav2_device::floppy_formats(format_registration &fr)
+{
+ fr.add_mfm_containers();
+ fr.add(FLOPPY_TRD_FORMAT);
+}
//-------------------------------------------------
// ROM( beta )
@@ -121,6 +144,11 @@ ROM_START(betav2)
ROM_RELOAD(0x1000,0x1000)
ROM_RELOAD(0x2000,0x1000)
ROM_RELOAD(0x3000,0x1000)
+ ROM_SYSTEM_BIOS(1, "sandy", "SP-DOS v1.0 (Sandy)") // match 2.0 ROM, only name text and checksum was changed
+ ROMX_LOAD("sandy.bin", 0x0000, 0x1000, CRC(a51b820f) SHA1(1c5ec9f56651ae527cdc092af1c602803104d5c3), ROM_BIOS(1))
+ ROM_RELOAD(0x1000,0x1000)
+ ROM_RELOAD(0x2000,0x1000)
+ ROM_RELOAD(0x3000,0x1000)
ROM_END
@@ -135,7 +163,7 @@ ROM_END
ROM_START(betav3)
ROM_REGION(0x4000, "rom", 0)
ROM_DEFAULT_BIOS("trd30")
- ROM_SYSTEM_BIOS(0, "trd30", "TR-DOS v3.0 (set 1)")
+ ROM_SYSTEM_BIOS(0, "trd30", "TR-DOS v3.0")
ROMX_LOAD("trd30.bin", 0x0000, 0x1000, CRC(c814179d) SHA1(b617ab59639beaa7b5d8e5b4e4a543a8eb0217c8), ROM_BIOS(0))
ROM_RELOAD(0x1000,0x1000)
ROM_RELOAD(0x2000,0x1000)
@@ -145,24 +173,81 @@ ROM_START(betav3)
// ROM_RELOAD(0x1000,0x1000)
// ROM_RELOAD(0x2000,0x1000)
// ROM_RELOAD(0x3000,0x1000)
- ROM_SYSTEM_BIOS(1, "trd30p", "TR-DOS v3.0 (set 2, Profisoft)") // is this a clone device?
+ ROM_SYSTEM_BIOS(1, "trd30p", "TR-DOS v3.0 (Profisoft)") // is this a clone device?
ROMX_LOAD("trd30ps.bin", 0x0000, 0x1000, CRC(b0f175a3) SHA1(ac95bb4d89072224deef58a1655e8029f811a7fa), ROM_BIOS(1))
ROM_RELOAD(0x1000,0x1000)
ROM_RELOAD(0x2000,0x1000)
ROM_RELOAD(0x3000,0x1000)
+ ROM_SYSTEM_BIOS(2, "acdos", "AC DOS v1.0") // match 3.0 ROM, only name text and checksum was changed
+ ROMX_LOAD("acdos.bin", 0x0000, 0x1000, CRC(c6d90a1e) SHA1(9480e5402bb8611b88657107a8aad889f353071b), ROM_BIOS(2))
+ ROM_RELOAD(0x1000,0x1000)
+ ROM_RELOAD(0x2000,0x1000)
+ ROM_RELOAD(0x3000,0x1000)
ROM_END
-// some sources indicate these should be 16kb roms with both halves duplicated, others suggest the same but with the first byte being 0x00 instead (maybe an issue with the dumping)
-// there are also some '412' unscrambled dumps with most of the data in the mirror regions as 0xff (maybe official, maybe from clone devices that should be treated separately?)
ROM_START(betaplus)
ROM_REGION(0x4000, "rom", 0)
- ROM_DEFAULT_BIOS("trd409")
+ ROM_DEFAULT_BIOS("trd412")
ROM_SYSTEM_BIOS(0, "trd409", "TR-DOS v4.09")
ROMX_LOAD("trd409.bin", 0x0000, 0x2000, CRC(18365bdc) SHA1(a0e7c80905423c54bd497575026ea8821061175a), ROM_BIOS(0))
ROM_RELOAD(0x2000,0x2000)
ROM_SYSTEM_BIOS(1, "trd411", "TR-DOS v4.11")
ROMX_LOAD("trd411.bin", 0x0000, 0x2000, CRC(26902902) SHA1(cb90fc31bf62d5968730db23a600344338e31e7e), ROM_BIOS(1))
ROM_RELOAD(0x2000,0x2000)
+ ROM_SYSTEM_BIOS(2, "trd412", "TR-DOS v4.12")
+ ROMX_LOAD("trd412.bin", 0x0000, 0x2000, CRC(f72efdf4) SHA1(b53ea4020be846ffc02ce586f7b52938c2c76f98), ROM_BIOS(2))
+ ROM_RELOAD(0x2000, 0x2000)
+ ROM_SYSTEM_BIOS(3, "trd4127", "TR-DOS v4.12 (FD1797)") // 6 bytes was changed for FD1797 compatibility (type II commands sector size bit), more probable from clone board.
+ ROMX_LOAD("trd4127.bin", 0x0000, 0x2000, CRC(4313234c) SHA1(214a10c9d2edf386c4685c0379efa2e87ff0e20c), ROM_BIOS(3))
+ ROM_RELOAD(0x2000,0x2000)
+ ROM_SYSTEM_BIOS(4, "cas86", "CAS DOS 1986") // v4.12 with name text changed
+ ROMX_LOAD("cas1986.bin", 0x0000, 0x2000, CRC(da0cfdcc) SHA1(a2dbcf2f899250b9e7c5c7b31969667024457a72), ROM_BIOS(4))
+ ROM_RELOAD(0x2000,0x2000)
+ ROM_SYSTEM_BIOS(5, "cas87", "CAS DOS 1987") // 4.12 with texts translated
+ ROMX_LOAD("cas1987.bin", 0x0000, 0x2000, CRC(a6a9450c) SHA1(b54b173a9f11ed730804d94584a1679193993e3c), ROM_BIOS(5))
+ ROM_RELOAD(0x2000,0x2000)
+ ROM_SYSTEM_BIOS(6, "icdos", "IC-DOS JUMBO v2.0") // v4.11 with name text changed
+ ROMX_LOAD("icdos.bin", 0x0000, 0x2000, CRC(1398d13a) SHA1(bf8cee39eb4b2a09a3f07db4cb8e7952bce4d3dd), ROM_BIOS(6))
+ ROM_RELOAD(0x2000,0x2000)
+ROM_END
+
+ROM_START(betaclone)
+ ROM_REGION(0x4000, "rom", 0)
+ ROM_DEFAULT_BIOS("vision10")
+ ROM_SYSTEM_BIOS(0, "vision10", "Vision 1.0 TR-DOS v4.12")
+ ROMX_LOAD("vision10.bin", 0x0000, 0x4000, CRC(20f49ff5) SHA1(d391324cb39e9fc6b93b867a71caec019c353518), ROM_BIOS(0))
+ ROM_SYSTEM_BIOS(1, "vision14", "Vision 1.4 TR-DOS v4.40")
+ ROMX_LOAD("vision14.bin", 0x0000, 0x4000, CRC(9903f577) SHA1(579627a2865caf3079cbae360bdaf0309d4a2911), ROM_BIOS(1))
+ ROM_SYSTEM_BIOS(2, "vision17b", "Vision 1.7 TR-DOS v4.82")
+ ROMX_LOAD("vision17b.bin", 0x0000, 0x4000, CRC(ecee1ff1) SHA1(ffde2a0f9b13328b6462fbf4eb95cfe8202a2d3f), ROM_BIOS(2))
+ ROM_SYSTEM_BIOS(3, "vision17c", "Vision 1.7 TR-DOS v4.83")
+ ROMX_LOAD("vision17c.bin", 0x0000, 0x4000, CRC(c192a6b1) SHA1(d9eb1e06e28b2fb45c704cffd4a8b8a912041d08), ROM_BIOS(3))
+ ROM_SYSTEM_BIOS(4, "vision18", "Vision 1.8 TR-DOS v4.80")
+ ROMX_LOAD("vision18.bin", 0x0000, 0x4000, CRC(3ee7a488) SHA1(57167b82a6a3ffa8b25e97fa8cc208da361f1cc7), ROM_BIOS(4))
+ ROM_SYSTEM_BIOS(5, "vision19", "Vision 1.9 TR-DOS v4.81")
+ ROMX_LOAD("vision19.bin", 0x0000, 0x4000, CRC(1a793d53) SHA1(cdbd0ac2262ede3852998174f88ae333419a570f), ROM_BIOS(5))
+ROM_END
+
+ROM_START(betacbi)
+ ROM_REGION(0x4000, "rom", 0)
+ ROM_DEFAULT_BIOS("cbi24")
+ ROM_SYSTEM_BIOS(0, "cbi23", "CBI-95 v2.3")
+ ROMX_LOAD("cbi95-23.bin", 0x0000, 0x4000, CRC(7fbefca6) SHA1(aa0c10162d440bc569648c524bbfc0b6d7c0b0dd), ROM_BIOS(0))
+ ROM_SYSTEM_BIOS(1, "cbi24", "CBI-95 v2.4")
+ ROMX_LOAD("cbi95-24.bin", 0x0000, 0x4000, CRC(afe4cec3) SHA1(6a30ab6997ac91798830f5f5d9645ba150050760), ROM_BIOS(1))
+ ROM_SYSTEM_BIOS(2, "ids91", "SYNCHRON IDS91")
+ ROMX_LOAD("ids91.bin", 0x0000, 0x4000, CRC(d569c67a) SHA1(50de5dbd49d8e03c97e416d4e0586870b90a4b87), ROM_BIOS(2))
+ ROM_SYSTEM_BIOS(3, "ids2001", "SYNCHRON IDS2001ne")
+ ROMX_LOAD("ids2001.bin", 0x0000, 0x4000, CRC(a1701f84) SHA1(32bd5f980bec168677513c568c8381a9a59aada3), ROM_BIOS(3))
+ ROM_SYSTEM_BIOS(4, "ar20", "ARCADE AR-20")
+ ROMX_LOAD("ar-20.bin", 0x0000, 0x4000, CRC(0ceeaa4d) SHA1(3e5f7d43218b5bd2a6e2aa28220c77cb651f5daa), ROM_BIOS(4))
+ROM_END
+
+ROM_START(gamma)
+ ROM_REGION(0x8000, "rom", 0)
+ ROM_DEFAULT_BIOS("gamma")
+ ROM_SYSTEM_BIOS(0, "gamma", "Gammadisk v4.1")
+ ROMX_LOAD("gamma.bin", 0x0000, 0x8000, CRC(00e4a835) SHA1(dffeb9f47b3eca94afbb61373eba003efd4675ff), ROM_BIOS(0))
ROM_END
@@ -181,18 +266,54 @@ void spectrum_betav2_device::device_add_mconfig_base(machine_config& config)
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));
}
void spectrum_betav2_device::device_add_mconfig(machine_config &config)
{
FD1771(config, m_fdc, 4_MHz_XTAL / 4);
+ m_fdc->hld_wr_callback().set(FUNC(spectrum_betav2_device::fdc_hld_w));
+
device_add_mconfig_base(config);
}
void spectrum_betav3_device::device_add_mconfig(machine_config& config)
{
FD1793(config, m_fdc, 4_MHz_XTAL / 4);
+ m_fdc->hld_wr_callback().set(FUNC(spectrum_betav3_device::fdc_hld_w));
+
+ device_add_mconfig_base(config);
+}
+
+void spectrum_betacbi_device::device_add_mconfig(machine_config& config)
+{
+ FD1797(config, m_fdc, 4_MHz_XTAL / 4);
+ m_fdc->hld_wr_callback().set(FUNC(spectrum_betacbi_device::fdc_hld_w));
+
+ device_add_mconfig_base(config);
+
+ CENTRONICS(config, m_centronics, centronics_devices, "printer");
+ m_centronics->busy_handler().set([this](u8 data) { m_centronics_busy = data; });
+}
+
+void spectrum_gamma_device::device_add_mconfig(machine_config& config)
+{
+ FD1793(config, m_fdc, 4_MHz_XTAL / 4);
+ m_fdc->hld_wr_callback().set(FUNC(spectrum_gamma_device::fdc_hld_w));
+
device_add_mconfig_base(config);
+
+ I8255(config, m_ppi);
+ m_ppi->in_pa_callback().set_ioport("JOY");
+ m_ppi->out_pb_callback().set("cent_data_out", FUNC(output_latch_device::write));
+ m_ppi->out_pc_callback().set([this](u8 data) { m_centronics->write_strobe(BIT(data, 7)); });
+
+ output_latch_device &cent_data_out(OUTPUT_LATCH(config, "cent_data_out"));
+ CENTRONICS(config, m_centronics, centronics_devices, "printer");
+ m_centronics->busy_handler().set([this](u8 data) { m_centronics_busy = data; });
+ m_centronics->set_output_latch(cent_data_out);
+
+ ACIA6850(config, m_acia, 0); // schematics missing, wiring unknown
}
const tiny_rom_entry *spectrum_betav2_device::device_rom_region() const
@@ -210,6 +331,21 @@ const tiny_rom_entry *spectrum_betaplus_device::device_rom_region() const
return ROM_NAME(betaplus);
}
+const tiny_rom_entry *spectrum_betaclone_device::device_rom_region() const
+{
+ return ROM_NAME(betaclone);
+}
+
+const tiny_rom_entry *spectrum_betacbi_device::device_rom_region() const
+{
+ return ROM_NAME(betacbi);
+}
+
+const tiny_rom_entry *spectrum_gamma_device::device_rom_region() const
+{
+ return ROM_NAME(gamma);
+}
+
//**************************************************************************
// LIVE DEVICE
@@ -226,6 +362,7 @@ spectrum_betav2_device::spectrum_betav2_device(const machine_config &mconfig, de
, m_fdc(*this, "fdc")
, m_floppy(*this, "fdc:%u", 0)
, m_exp(*this, "exp")
+ , m_control(0)
{
}
@@ -254,6 +391,42 @@ spectrum_betaplus_device::spectrum_betaplus_device(const machine_config &mconfig
{
}
+spectrum_betaclone_device::spectrum_betaclone_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock)
+ : spectrum_betaplus_device(mconfig, type, tag, owner, clock)
+{
+}
+
+spectrum_betaclone_device::spectrum_betaclone_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
+ : spectrum_betaclone_device(mconfig, SPECTRUM_BETACLONE, tag, owner, clock)
+{
+}
+
+spectrum_betacbi_device::spectrum_betacbi_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock)
+ : spectrum_betaclone_device(mconfig, type, tag, owner, clock)
+ , m_centronics(*this, "centronics")
+ , m_centronics_busy(0)
+{
+}
+
+spectrum_betacbi_device::spectrum_betacbi_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
+ : spectrum_betacbi_device(mconfig, SPECTRUM_BETACBI, tag, owner, clock)
+{
+}
+
+spectrum_gamma_device::spectrum_gamma_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock)
+ : spectrum_betaplus_device(mconfig, type, tag, owner, clock)
+ , m_ppi(*this, "ppi")
+ , m_acia(*this, "acia")
+ , m_centronics(*this, "centronics")
+ , m_centronics_busy(0)
+{
+}
+
+spectrum_gamma_device::spectrum_gamma_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
+ : spectrum_gamma_device(mconfig, SPECTRUM_GAMMA, tag, owner, clock)
+{
+}
+
//-------------------------------------------------
// device_start - device-specific startup
@@ -262,6 +435,9 @@ spectrum_betaplus_device::spectrum_betaplus_device(const machine_config &mconfig
void spectrum_betav2_device::device_start()
{
save_item(NAME(m_romcs));
+ save_item(NAME(m_masterdisable));
+ save_item(NAME(m_control));
+ save_item(NAME(m_motor_active));
#if 0 // we do this in realtime instead
for (int i = 0; i < m_rom->bytes(); i++)
@@ -273,25 +449,37 @@ void spectrum_betav2_device::device_start()
#endif
}
+void spectrum_betacbi_device::device_start()
+{
+ spectrum_betav2_device::device_start();
+ save_item(NAME(m_centronics_busy));
+}
+
+void spectrum_gamma_device::device_start()
+{
+ spectrum_betav2_device::device_start();
+ save_item(NAME(m_centronics_busy));
+}
+
//-------------------------------------------------
// device_reset - device-specific reset
//-------------------------------------------------
void spectrum_betav2_device::device_reset()
{
- // always paged in on boot? (no mode switch like beta128)
+ // always paged in on boot, no mode switch like beta128.
m_romcs = 1;
- m_romlatch = 0;
-// m_masterportdisable = 1;
+ m_control = 0;
+ m_masterdisable = 0;
}
//**************************************************************************
// 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)
@@ -303,7 +491,24 @@ void spectrum_betav2_device::fetch(offs_t offset)
else
m_romcs = 0;
- if (!m_romlatch)
+ if (!(m_control & 0x80))
+ {
+ if (offset < 0x4000)
+ m_romcs = 1;
+ }
+ }
+}
+
+void spectrum_betacbi_device::fetch(offs_t offset)
+{
+ if (!machine().side_effects_disabled())
+ {
+ if ((offset & 0xff00) == 0x3c00 && !(m_masterdisable & 0x40))
+ m_romcs = 1;
+ else
+ m_romcs = 0;
+
+ if (!(m_control & 0x80))
{
if (offset < 0x4000)
m_romcs = 1;
@@ -325,46 +530,82 @@ void spectrum_betav2_device::pre_data_fetch(offs_t offset)
uint8_t spectrum_betav2_device::iorq_r(offs_t offset)
{
- uint8_t data = m_exp->iorq_r(offset);
+ uint8_t data = 0xff;
-// if (!m_masterportdisable)
- if (m_romcs)
+ if (!(m_masterdisable & 0x80))
{
- switch (offset & 0xff)
+ switch (offset & 0x87)
{
- case 0x1f: case 0x3f: case 0x5f: case 0x7f:
+ case 0x07:
data = m_fdc->read((offset >> 5) & 0x03);
break;
- case 0xff:
+ case 0x87:
data &= 0x3f; // actually open bus
data |= m_fdc->drq_r() ? 0x40 : 0;
data |= m_fdc->intrq_r() ? 0x80 : 0;
break;
}
}
+ else
+ data = m_exp->iorq_r(offset);
return data;
}
void spectrum_betav2_device::iorq_w(offs_t offset, uint8_t data)
{
-// if ((offset & 0x03) == 0x00)
-// {
-// m_masterportdisable = data & 0x80;
-// }
+ if ((offset & 3) == 0)
+ m_masterdisable = data;
-// if (!m_masterportdisable)
- if (m_romcs)
+ if (!(m_masterdisable & 0x80))
+ {
+ switch (offset & 0x87)
+ {
+ case 0x07:
+ m_fdc->write((offset >> 5) & 0x03, data);
+ break;
+
+ case 0x87:
+ m_control = data;
+
+ floppy_image_device* floppy = nullptr;
+ for (int i = 0; i < 3; i++)
+ if (!(data & (1 << i)))
+ {
+ floppy = m_floppy[i]->get_device();
+ break;
+ }
+
+ m_fdc->set_floppy(floppy);
+ if (floppy)
+ floppy->ss_w(BIT(data, 3) ? 0 : 1);
+
+ m_fdc->hlt_w(BIT(data, 4));
+
+ motors_control();
+ break;
+ }
+ }
+ else
+ m_exp->iorq_w(offset, data);
+}
+
+void spectrum_betav3_device::iorq_w(offs_t offset, uint8_t data)
+{
+ if ((offset & 3) == 0)
+ m_masterdisable = data;
+
+ if (!(m_masterdisable & 0x80))
{
- switch (offset & 0xff)
+ switch (offset & 0x87)
{
- case 0x1f: case 0x3f: case 0x5f: case 0x7f:
+ case 0x07:
m_fdc->write((offset >> 5) & 0x03, data);
break;
- case 0xff:
- m_romlatch = data & 0x80;
+ case 0x87:
+ m_control = data;
floppy_image_device* floppy = m_floppy[data & 3]->get_device();
@@ -373,26 +614,181 @@ void spectrum_betav2_device::iorq_w(offs_t offset, uint8_t data)
floppy->ss_w(BIT(data, 4) ? 0 : 1);
m_fdc->dden_w(BIT(data, 6));
- // bit 3 connected to pin 23 "HLT" of FDC and via diode to INDEX
- //m_fdc->hlt_w(BIT(data, 3)); // not handled in current wd_fdc
+ m_fdc->hlt_w(BIT(data, 3));
- if (BIT(data, 2) == 0) // reset
+ m_fdc->mr_w(BIT(data, 2));
+ motors_control();
+ break;
+ }
+ }
+ else
+ m_exp->iorq_w(offset, data);
+}
+
+uint8_t spectrum_betacbi_device::iorq_r(offs_t offset)
+{
+ uint8_t data = 0xff;
+
+ if (!(m_masterdisable & 0x80))
+ {
+ switch (offset & 0x87)
+ {
+ case 0x07:
+ data = m_fdc->read((offset >> 5) & 0x03);
+ break;
+
+ case 0x87:
+ data &= 0x0f; // actually open bus
+ data |= 0x10; // some switch, unk purpose
+ data |= m_centronics_busy ? 0x20: 0;
+ data |= m_fdc->drq_r() ? 0x40 : 0;
+ data |= m_fdc->intrq_r() ? 0x80 : 0;
+ break;
+ }
+ }
+ else
+ data = m_exp->iorq_r(offset);
+
+ return data;
+}
+
+void spectrum_betacbi_device::iorq_w(offs_t offset, uint8_t data)
+{
+ if ((offset & 3) == 0)
+ m_masterdisable = data;
+
+ if (!BIT(offset, 2))
+ {
+ m_centronics->write_data0(BIT(data, 0));
+ m_centronics->write_data1(BIT(data, 1));
+ m_centronics->write_data2(BIT(data, 2));
+ m_centronics->write_data3(BIT(data, 3));
+ m_centronics->write_data4(BIT(data, 4));
+ m_centronics->write_data5(BIT(data, 5));
+ m_centronics->write_data6(BIT(data, 6));
+ m_centronics->write_data7(BIT(data, 7));
+ }
+
+ if (!(m_masterdisable & 0x80))
+ {
+ switch (offset & 0x87)
+ {
+ case 0x07:
+ m_fdc->write((offset >> 5) & 0x03, data);
+ break;
+
+ case 0x87:
+ m_control = data;
+
+ floppy_image_device* floppy = m_floppy[data & 3]->get_device();
+
+ m_fdc->set_floppy(floppy);
+ if (floppy)
+ floppy->ss_w(BIT(data, 4) ? 0 : 1);
+ m_fdc->dden_w(BIT(data, 6));
+
+ m_fdc->hlt_w(BIT(data, 3));
+
+ m_fdc->mr_w(BIT(data, 2));
+ motors_control();
+
+ m_centronics->write_strobe(!BIT(data, 5));
+ break;
+ }
+ }
+ else
+ m_exp->iorq_w(offset, data);
+}
+
+uint8_t spectrum_gamma_device::iorq_r(offs_t offset)
+{
+ uint8_t data = 0xff;
+
+ if (!(m_masterdisable & 0x40))
+ {
+ if (!(m_masterdisable & 0x80))
+ {
+ switch (offset & 0x9f)
{
- m_fdc->reset();
- if (floppy)
- floppy->mon_w(ASSERT_LINE);
+ case 0x1f:
+ data = m_fdc->read((offset >> 5) & 0x03);
+ break;
+
+ case 0x9f:
+ data &= 0x3f; // actually open bus
+ data |= m_fdc->drq_r() ? 0x40 : 0;
+ data |= m_fdc->intrq_r() ? 0x80 : 0;
+ break;
}
- else
+ }
+ else
+ {
+ switch (offset & 0x9f)
{
- // TODO: implement correct motor control, FDD motor and RDY FDC pin controlled by HLD pin of FDC
- if (floppy)
- floppy->mon_w(CLEAR_LINE);
+ case 0x1f:
+ data = m_ppi->read((offset >> 5) & 0x03);
+ break;
+
+ case 0x9f:
+ data = m_acia->read((offset >> 6) & 0x01);
+ break;
}
- break;
}
}
+ else
+ data = m_exp->iorq_r(offset);
- m_exp->iorq_w(offset, data);
+ return data;
+}
+
+void spectrum_gamma_device::iorq_w(offs_t offset, uint8_t data)
+{
+ if ((offset & 3) == 0)
+ m_masterdisable = data;
+
+ if (!(m_masterdisable & 0x40))
+ {
+ if (!(m_masterdisable & 0x80))
+ {
+ switch (offset & 0x9f)
+ {
+ case 0x1f:
+ m_fdc->write((offset >> 5) & 0x03, data);
+ break;
+
+ case 0x9f:
+ m_control = data;
+
+ floppy_image_device* floppy = m_floppy[data & 3]->get_device();
+
+ m_fdc->set_floppy(floppy);
+ if (floppy)
+ floppy->ss_w(BIT(data, 4) ? 0 : 1);
+ m_fdc->dden_w(BIT(data, 6));
+
+ m_fdc->hlt_w(BIT(data, 3));
+
+ m_fdc->mr_w(BIT(data, 2));
+ motors_control();
+ break;
+ }
+ }
+ else
+ {
+ switch (offset & 0x9f)
+ {
+ case 0x1f:
+ m_ppi->write((offset >> 5) & 0x03, data);
+ break;
+
+ case 0x9f:
+ m_acia->write((offset >> 6) & 0x01, data);
+ break;
+ }
+ }
+ }
+ else
+ m_exp->iorq_w(offset, data);
}
uint8_t spectrum_betav2_device::mreq_r(offs_t offset)
@@ -411,31 +807,97 @@ uint8_t spectrum_betav2_device::mreq_r(offs_t offset)
return data;
}
-void spectrum_betav2_device::mreq_w(offs_t offset, uint8_t data)
+uint8_t spectrum_betaclone_device::mreq_r(offs_t offset)
{
+ uint8_t data = 0xff;
+
+ if (m_romcs)
+ data = m_rom->base()[offset & 0x3fff];
+
if (m_exp->romcs())
- m_exp->mreq_w(offset, data);
+ data &= m_exp->mreq_r(offset);
+
+ return data;
+}
+
+uint8_t spectrum_gamma_device::mreq_r(offs_t offset)
+{
+ return m_rom->base()[(offset & 0x3fff) + (m_romcs ? 0x4000 : 0)];
+}
+
+void spectrum_betav2_device::fdc_hld_w(int state)
+{
+ m_fdc->set_force_ready(state); // HLD connected to RDY pin
+ m_motor_active = state;
+ motors_control();
+}
+
+void spectrum_betav2_device::motors_control()
+{
+ for (int i = 0; i < 3; i++)
+ {
+ floppy_image_device* floppy = m_floppy[i]->get_device();
+ if (!floppy)
+ continue;
+ if (m_motor_active && !(m_control & (1 << i)))
+ floppy->mon_w(CLEAR_LINE);
+ else
+ floppy->mon_w(ASSERT_LINE);
+ }
+}
+
+void spectrum_betav3_device::motors_control()
+{
+ for (int i = 0; i < 4; i++)
+ {
+ floppy_image_device* floppy = m_floppy[i]->get_device();
+ if (!floppy)
+ continue;
+ if (m_motor_active && (m_control & 3) == i)
+ floppy->mon_w(CLEAR_LINE);
+ else
+ floppy->mon_w(ASSERT_LINE);
+ }
}
// Betaplus has a 'magic button' for dumping RAM
INPUT_PORTS_START(betaplus)
PORT_START("BUTTON") // don't use F12, it clashes with the 'exit from debugger' button
- PORT_BIT(0x01, IP_ACTIVE_LOW, IPT_BUTTON1) PORT_NAME("Magic Button") PORT_CODE(KEYCODE_MINUS_PAD) PORT_CHANGED_MEMBER(DEVICE_SELF, spectrum_betaplus_device, magic_button, 0)
+ PORT_BIT(0x01, IP_ACTIVE_LOW, IPT_BUTTON1) PORT_NAME("Magic Button") PORT_CODE(KEYCODE_MINUS_PAD) PORT_CHANGED_MEMBER(DEVICE_SELF, FUNC(spectrum_betaplus_device::magic_button), 0)
+INPUT_PORTS_END
+
+INPUT_PORTS_START(gamma)
+ PORT_INCLUDE(betaplus)
+
+ PORT_START("JOY")
+ PORT_BIT(0x01, IP_ACTIVE_HIGH, IPT_JOYSTICK_RIGHT) PORT_8WAY
+ PORT_BIT(0x02, IP_ACTIVE_HIGH, IPT_JOYSTICK_LEFT) PORT_8WAY
+ PORT_BIT(0x04, IP_ACTIVE_HIGH, IPT_JOYSTICK_DOWN) PORT_8WAY
+ PORT_BIT(0x08, IP_ACTIVE_HIGH, IPT_JOYSTICK_UP) PORT_8WAY
+ PORT_BIT(0x10, IP_ACTIVE_HIGH, IPT_BUTTON1)
+ PORT_BIT(0x60, IP_ACTIVE_HIGH, IPT_UNUSED)
+ PORT_BIT(0x80, IP_ACTIVE_HIGH, IPT_CUSTOM) PORT_CUSTOM_MEMBER(FUNC(spectrum_gamma_device::busy_r))
INPUT_PORTS_END
+
ioport_constructor spectrum_betaplus_device::device_input_ports() const
{
return INPUT_PORTS_NAME(betaplus);
}
+ioport_constructor spectrum_gamma_device::device_input_ports() const
+{
+ return INPUT_PORTS_NAME(gamma);
+}
+
INPUT_CHANGED_MEMBER(spectrum_betaplus_device::magic_button)
{
if (newval && !oldval)
{
m_slot->nmi_w(ASSERT_LINE);
m_romcs = 1;
- m_romlatch = 0;
+ m_control &= ~0x80;
}
else
{
diff --git a/src/devices/bus/spectrum/beta.h b/src/devices/bus/spectrum/beta.h
index 7fed611a49b..cec3bb8be05 100644
--- a/src/devices/bus/spectrum/beta.h
+++ b/src/devices/bus/spectrum/beta.h
@@ -11,8 +11,10 @@
#include "exp.h"
#include "softlist.h"
#include "imagedev/floppy.h"
+#include "bus/centronics/ctronics.h"
#include "machine/wd_fdc.h"
-#include "formats/trd_dsk.h"
+#include "machine/i8255.h"
+#include "machine/6850acia.h"
//**************************************************************************
// TYPE DEFINITIONS
@@ -28,36 +30,43 @@ public:
spectrum_betav2_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock);
spectrum_betav2_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
- DECLARE_FLOPPY_FORMATS(floppy_formats);
+ static void floppy_formats(format_registration &fr);
protected:
// device-level overrides
- virtual void device_start() override;
- virtual void device_reset() override;
+ virtual void device_start() override ATTR_COLD;
+ virtual void device_reset() override ATTR_COLD;
// optional information overrides
void device_add_mconfig_base(machine_config& config);
- virtual void device_add_mconfig(machine_config &config) override;
- virtual const tiny_rom_entry *device_rom_region() const override;
+ virtual void device_add_mconfig(machine_config &config) override ATTR_COLD;
+ virtual const tiny_rom_entry *device_rom_region() const override ATTR_COLD;
virtual void pre_opcode_fetch(offs_t offset) override;
virtual void pre_data_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 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); }
+ 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); }
required_memory_region m_rom;
required_device<wd_fdc_device_base> m_fdc;
required_device_array<floppy_connector, 4> m_floppy;
required_device<spectrum_expansion_slot_device> m_exp;
- int m_romcs;
- int m_romlatch;
-// int m_masterportdisable;
+ bool m_romcs;
+ u8 m_masterdisable;
+ u8 m_control;
+ bool m_motor_active;
+ void fdc_hld_w(int state);
+ virtual void motors_control();
- void fetch(offs_t offset);
+ virtual void fetch(offs_t offset);
};
class spectrum_betav3_device :
@@ -69,8 +78,10 @@ public:
spectrum_betav3_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_add_mconfig(machine_config &config) override ATTR_COLD;
+ virtual const tiny_rom_entry *device_rom_region() const override ATTR_COLD;
+ virtual void iorq_w(offs_t offset, uint8_t data) override;
+ virtual void motors_control() override;
};
@@ -85,14 +96,78 @@ public:
DECLARE_INPUT_CHANGED_MEMBER(magic_button);
protected:
- virtual const tiny_rom_entry *device_rom_region() const override;
- virtual ioport_constructor device_input_ports() const override;
+ virtual const tiny_rom_entry *device_rom_region() const override ATTR_COLD;
+ virtual ioport_constructor device_input_ports() const override ATTR_COLD;
+
+};
+
+class spectrum_betaclone_device :
+ public spectrum_betaplus_device
+{
+public:
+ // construction/destruction
+ spectrum_betaclone_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock);
+ spectrum_betaclone_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
+
+protected:
+ virtual uint8_t mreq_r(offs_t offset) override;
+ virtual const tiny_rom_entry *device_rom_region() const override ATTR_COLD;
+
+};
+
+class spectrum_betacbi_device :
+ public spectrum_betaclone_device
+{
+public:
+ // construction/destruction
+ spectrum_betacbi_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock);
+ spectrum_betacbi_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
+
+protected:
+ virtual void device_start() override ATTR_COLD;
+ virtual void device_add_mconfig(machine_config &config) override ATTR_COLD;
+ virtual void fetch(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 const tiny_rom_entry *device_rom_region() const override ATTR_COLD;
+
+ required_device<centronics_device> m_centronics;
+
+ int m_centronics_busy;
+};
+
+class spectrum_gamma_device :
+ public spectrum_betaplus_device
+{
+public:
+ // construction/destruction
+ spectrum_gamma_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock);
+ spectrum_gamma_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
+
+ ioport_value busy_r() { return !m_centronics_busy; }
+protected:
+ virtual void device_start() override ATTR_COLD;
+ virtual void device_add_mconfig(machine_config &config) override ATTR_COLD;
+ virtual ioport_constructor device_input_ports() const override ATTR_COLD;
+ virtual uint8_t mreq_r(offs_t offset) override;
+ virtual const tiny_rom_entry *device_rom_region() const override ATTR_COLD;
+ virtual uint8_t iorq_r(offs_t offset) override;
+ virtual void iorq_w(offs_t offset, uint8_t data) override;
+ virtual bool romcs() override { return 1; }
+
+ required_device<i8255_device> m_ppi;
+ required_device<acia6850_device> m_acia;
+ required_device<centronics_device> m_centronics;
+ int m_centronics_busy;
};
// device type definition
DECLARE_DEVICE_TYPE(SPECTRUM_BETAV2, spectrum_betav2_device)
DECLARE_DEVICE_TYPE(SPECTRUM_BETAV3, spectrum_betav3_device)
DECLARE_DEVICE_TYPE(SPECTRUM_BETAPLUS, spectrum_betaplus_device)
+DECLARE_DEVICE_TYPE(SPECTRUM_BETACLONE, spectrum_betaclone_device)
+DECLARE_DEVICE_TYPE(SPECTRUM_BETACBI, spectrum_betacbi_device)
+DECLARE_DEVICE_TYPE(SPECTRUM_GAMMA, spectrum_gamma_device)
#endif // MAME_BUS_SPECTRUM_BETA_H
diff --git a/src/devices/bus/spectrum/beta128.cpp b/src/devices/bus/spectrum/beta128.cpp
index a2240da737c..c27e02cd8f1 100644
--- a/src/devices/bus/spectrum/beta128.cpp
+++ b/src/devices/bus/spectrum/beta128.cpp
@@ -10,22 +10,8 @@
due to changes in the 128k ROM structure etc. (enable address
is moved from 3cxx to 3dxx for example)
- Issues:
-
- Using the FD1793 device a 'CAT' operation in the 'spectrum' driver
- will always report 'No Disk' but using the Soviet clone KR1818VG93
- it properly gives the disk catalogue. Despite this files can still
- be loaded from disk.
-
- The 128k Spectrum drivers have a similar issues, although even if
- you replace the controller doing a 'CAT' operation seems to have
- an adverse effect on the system memory setup as things become
- corrupt (LOADing or MERGEing a program afterwards can cause a reset)
-
- Neither of these issues occur in other Spectrum emulators using
- the same ROMs and floppy images.
-
TODO:
+ original ROMs should have bits 0 and 7 swapped
there were many unofficial ROMs available for this, make them
available for use.
@@ -35,6 +21,8 @@
#include "emu.h"
#include "beta128.h"
+#include "formats/trd_dsk.h"
+
/***************************************************************************
DEVICE DEFINITIONS
@@ -49,12 +37,12 @@ DEFINE_DEVICE_TYPE(SPECTRUM_BETA128, spectrum_beta128_device, "spectrum_beta128"
INPUT_PORTS_START(beta128)
PORT_START("BUTTON") // don't use F12, it clashes with the 'exit from debugger' button
- PORT_BIT(0x01, IP_ACTIVE_LOW, IPT_BUTTON1) PORT_NAME("Magic Button") PORT_CODE(KEYCODE_MINUS_PAD) PORT_CHANGED_MEMBER(DEVICE_SELF, spectrum_beta128_device, magic_button, 0)
+ PORT_BIT(0x01, IP_ACTIVE_LOW, IPT_BUTTON1) PORT_NAME("Magic Button") PORT_CODE(KEYCODE_MINUS_PAD) PORT_CHANGED_MEMBER(DEVICE_SELF, FUNC(spectrum_beta128_device::magic_button), 0)
PORT_START("SWITCH")
- PORT_CONFNAME(0x03, 0x01, "System Switch") //PORT_CHANGED_MEMBER(DEVICE_SELF, spectrum_beta128_device, switch_changed, 0)
+ PORT_CONFNAME(0x03, 0x01, "System Switch") //PORT_CHANGED_MEMBER(DEVICE_SELF, FUNC(spectrum_beta128_device::switch_changed), 0)
PORT_CONFSETTING(0x00, "Off (128)")
- PORT_CONFSETTING(0x01, "Normal (auto-boot)")
+ PORT_CONFSETTING(0x01, "Normal (auto-boot)") // also enable Beta-disk V3/V4 compatibility, auto-boot feature does not work on Spectrum128.
//PORT_CONFSETTING(0x02, "Reset") // TODO: implement RESET callback
INPUT_PORTS_END
@@ -77,12 +65,14 @@ static void beta_floppies(device_slot_interface &device)
}
//-------------------------------------------------
-// floppy_format_type floppy_formats
+// floppy_formats
//-------------------------------------------------
-FLOPPY_FORMATS_MEMBER(spectrum_beta128_device::floppy_formats)
- FLOPPY_TRD_FORMAT
-FLOPPY_FORMATS_END
+void spectrum_beta128_device::floppy_formats(format_registration &fr)
+{
+ fr.add_mfm_containers();
+ fr.add(FLOPPY_TRD_FORMAT);
+}
//-------------------------------------------------
// ROM( beta )
@@ -90,13 +80,21 @@ FLOPPY_FORMATS_END
ROM_START(beta128)
ROM_REGION(0x4000, "rom", 0)
- ROM_DEFAULT_BIOS("trd504")
+ ROM_DEFAULT_BIOS("trd503")
+
+ // original, but in plain form, should be replaced with "proper dumps" with data bits 0 and 7 swapped
ROM_SYSTEM_BIOS(0, "trd501", "TR-DOS v5.01")
ROMX_LOAD("trd501.rom", 0x0000, 0x4000, CRC(3e3cdd4c) SHA1(8303ba0cc79daa6c04cd1e6ce27e8b6886a3f0de), ROM_BIOS(0))
- ROM_SYSTEM_BIOS(1, "trd503", "TR-DOS v5.03")
- ROMX_LOAD("trd503.rom", 0x0000, 0x4000, CRC(10751aba) SHA1(21695e3f2a8f796386ce66eea8a246b0ac44810c), ROM_BIOS(1))
- ROM_SYSTEM_BIOS(2, "trd504", "TR-DOS v5.04")
- ROMX_LOAD("trd504.rom", 0x0000, 0x4000, CRC(ba310874) SHA1(05e55e37df8eee6c68601ba9cf6c92195852ce3f), ROM_BIOS(2))
+ ROM_SYSTEM_BIOS(1, "trd502", "TR-DOS v5.02")
+ ROMX_LOAD("trd502.rom", 0x0000, 0x4000, CRC(64f0fcf8) SHA1(862e0af2245f68fca3d6a5b10186d09fd1faee55), ROM_BIOS(1))
+ ROM_SYSTEM_BIOS(2, "trd503", "TR-DOS v5.03")
+ ROMX_LOAD("trd503.rom", 0x0000, 0x4000, CRC(10751aba) SHA1(21695e3f2a8f796386ce66eea8a246b0ac44810c), ROM_BIOS(2))
+
+ // clone/homebrew modifications based on original v5.03
+ ROM_SYSTEM_BIOS(3, "trd504t", "TR-DOS v5.04T (hack)")
+ // increased step rate (6ms), FORMAT command got interleave 1:1 option for faster read/write speed, this firmware was most common at post-soviet space in 90x.
+ ROMX_LOAD("trd504t.rom", 0x0000, 0x4000, CRC(e212d1e0) SHA1(745e9caf576e64a5386ad845256d28593d34cc40), ROM_BIOS(3))
+ // trd504.rom CRC ba310874 is bad dump of 5.03 with edited version text, no actual code changes.
ROM_END
//-------------------------------------------------
@@ -106,6 +104,7 @@ ROM_END
void spectrum_beta128_device::device_add_mconfig(machine_config &config)
{
FD1793(config, m_fdc, 4_MHz_XTAL / 4);
+ m_fdc->hld_wr_callback().set(FUNC(spectrum_beta128_device::fdc_hld_w));
//KR1818VG93(config, m_fdc, 4_MHz_XTAL / 4);
FLOPPY_CONNECTOR(config, "fdc:0", beta_floppies, "525qd", spectrum_beta128_device::floppy_formats).enable_sound(true);
@@ -117,6 +116,7 @@ void spectrum_beta128_device::device_add_mconfig(machine_config &config)
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));
}
const tiny_rom_entry *spectrum_beta128_device::device_rom_region() const
@@ -141,6 +141,8 @@ spectrum_beta128_device::spectrum_beta128_device(const machine_config &mconfig,
, m_floppy(*this, "fdc:%u", 0)
, m_exp(*this, "exp")
, m_switch(*this, "SWITCH")
+ , m_control(0)
+ , m_motor_active(false)
{
}
@@ -151,6 +153,9 @@ spectrum_beta128_device::spectrum_beta128_device(const machine_config &mconfig,
void spectrum_beta128_device::device_start()
{
save_item(NAME(m_romcs));
+ save_item(NAME(m_control));
+ save_item(NAME(m_motor_active));
+ save_item(NAME(m_128rom_bit));
}
//-------------------------------------------------
@@ -164,15 +169,17 @@ void spectrum_beta128_device::device_reset()
m_romcs = 1;
else
m_romcs = 0;
+
+ m_128rom_bit = true;
}
//**************************************************************************
// 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();
}
@@ -182,72 +189,74 @@ void spectrum_beta128_device::pre_opcode_fetch(offs_t offset)
if (!machine().side_effects_disabled())
{
- if ((offset == 0x0066) || (offset & 0xff00) == 0x3d00)
+ u8 offs = offset >> 8;
+
+ if (offs == 0x3d && m_128rom_bit)
m_romcs = 1;
- else if (offset >= 0x4000)
+ else if (offs == 0x3c && m_128rom_bit && m_switch->read() == 0x01)
+ m_romcs = 1;
+ else if (offs >= 0x40)
m_romcs = 0;
}
}
uint8_t spectrum_beta128_device::iorq_r(offs_t offset)
{
- uint8_t data = m_exp->iorq_r(offset);
+ uint8_t data = 0xff;
if (m_romcs)
{
- switch (offset & 0xff)
+ switch (offset & 0x83)
{
- case 0x1f: case 0x3f: case 0x5f: case 0x7f:
+ case 0x03:
data = m_fdc->read((offset >> 5) & 0x03);
break;
- case 0xff:
+ case 0x83:
data &= 0x3f; // actually open bus
data |= m_fdc->drq_r() ? 0x40 : 0;
data |= m_fdc->intrq_r() ? 0x80 : 0;
break;
}
- }
+ } else
+ data = m_exp->iorq_r(offset);
+
return data;
}
void spectrum_beta128_device::iorq_w(offs_t offset, uint8_t data)
{
+ if ((offset & 0x8002) == 0)
+ m_128rom_bit = bool(data & 0x10);
+
if (m_romcs)
{
- switch (offset & 0xff)
+ switch (offset & 0x83)
{
- case 0x1f: case 0x3f: case 0x5f: case 0x7f:
+ case 0x03:
m_fdc->write((offset >> 5) & 0x03, data);
break;
- case 0xff:
+ case 0x83:
floppy_image_device* floppy = m_floppy[data & 3]->get_device();
+ m_control = data;
m_fdc->set_floppy(floppy);
if (floppy)
floppy->ss_w(BIT(data, 4) ? 0 : 1);
m_fdc->dden_w(BIT(data, 6));
- // bit 3 connected to pin 23 "HLT" of FDC and via diode to INDEX
- //m_fdc->hlt_w(BIT(data, 3)); // not handled in current wd_fdc
-
- if (BIT(data, 2) == 0) // reset
- {
- m_fdc->reset();
- if (floppy)
- floppy->mon_w(ASSERT_LINE);
- }
- else
- {
- // TODO: implement correct motor control, FDD motor and RDY FDC pin controlled by HLD pin of FDC
- if (floppy)
- floppy->mon_w(CLEAR_LINE);
- }
+ m_fdc->hlt_w(BIT(data, 3));
+ // bit 3 also connected to FDC /IP pin via diode, AND logic: if this bit is 0 - /IP will be forcibly set to low.
+ // used for bitbang index pulses generation to stop FDD drive motor with no disk inserted, currently not emulated.
+
+ m_fdc->mr_w(BIT(data, 2));
+ motors_control();
break;
}
}
- m_exp->iorq_w(offset, data);
+ else
+ m_exp->iorq_w(offset, data);
}
uint8_t spectrum_beta128_device::mreq_r(offs_t offset)
@@ -265,16 +274,11 @@ uint8_t spectrum_beta128_device::mreq_r(offs_t offset)
return data;
}
-void spectrum_beta128_device::mreq_w(offs_t offset, uint8_t data)
-{
- if (m_exp->romcs())
- m_exp->mreq_w(offset, data);
-}
-
INPUT_CHANGED_MEMBER(spectrum_beta128_device::magic_button)
{
if (newval && !oldval)
{
+ m_romcs = 1;
m_slot->nmi_w(ASSERT_LINE);
}
else
@@ -282,3 +286,24 @@ INPUT_CHANGED_MEMBER(spectrum_beta128_device::magic_button)
m_slot->nmi_w(CLEAR_LINE);
}
}
+
+void spectrum_beta128_device::fdc_hld_w(int state)
+{
+ m_fdc->set_force_ready(state); // HLD connected to RDY pin
+ m_motor_active = state;
+ motors_control();
+}
+
+void spectrum_beta128_device::motors_control()
+{
+ for (int i = 0; i < 4; i++)
+ {
+ floppy_image_device* floppy = m_floppy[i]->get_device();
+ if (!floppy)
+ continue;
+ if (m_motor_active && (m_control & 3) == i)
+ floppy->mon_w(CLEAR_LINE);
+ else
+ floppy->mon_w(ASSERT_LINE);
+ }
+}
diff --git a/src/devices/bus/spectrum/beta128.h b/src/devices/bus/spectrum/beta128.h
index b3734687e72..38495782ea1 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
@@ -27,25 +26,30 @@ public:
// construction/destruction
spectrum_beta128_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
- DECLARE_FLOPPY_FORMATS(floppy_formats);
+ static void floppy_formats(format_registration &fr);
DECLARE_INPUT_CHANGED_MEMBER(magic_button);
protected:
// device-level overrides
- virtual void device_start() override;
- virtual void device_reset() override;
+ virtual void device_start() override ATTR_COLD;
+ virtual void device_reset() override ATTR_COLD;
// 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 void device_add_mconfig(machine_config &config) override ATTR_COLD;
+ virtual const tiny_rom_entry *device_rom_region() const override ATTR_COLD;
+ virtual ioport_constructor device_input_ports() const override ATTR_COLD;
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 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); }
+ 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); }
required_memory_region m_rom;
required_device<wd_fdc_device_base> m_fdc;
@@ -53,7 +57,12 @@ 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;
+ void fdc_hld_w(int state);
+ void motors_control();
};
diff --git a/src/devices/bus/spectrum/d40.cpp b/src/devices/bus/spectrum/d40.cpp
new file mode 100644
index 00000000000..50927561ac8
--- /dev/null
+++ b/src/devices/bus/spectrum/d40.cpp
@@ -0,0 +1,473 @@
+// license:BSD-3-Clause
+// copyright-holders:MetalliC
+/**********************************************************************
+
+ Didaktik D40/D80 disk interface
+ (C) 1991 Didaktik Skalica
+
+ useful commands:
+ RUN - boot disc
+ CAT - files list
+ LIST * - system information
+ LOAD *"filename" - load program
+
+**********************************************************************/
+
+
+#include "emu.h"
+#include "d40.h"
+
+
+//**************************************************************************
+// DEVICE DEFINITIONS
+//**************************************************************************
+
+DEFINE_DEVICE_TYPE(SPECTRUM_D40, spectrum_d40_device, "spectrum_d40", "Didaktik D40")
+DEFINE_DEVICE_TYPE(SPECTRUM_D80, spectrum_d80_device, "spectrum_d80", "Didaktik D80 (MDOS 1, 2793 FDC)")
+DEFINE_DEVICE_TYPE(SPECTRUM_D80V2, spectrum_d80v2_device, "spectrum_d80v2", "Didaktik D80 (MDOS 2, 8272 FDC)")
+
+//-------------------------------------------------
+// INPUT_PORTS
+//-------------------------------------------------
+
+INPUT_PORTS_START(d40)
+ PORT_START("BUTTON")
+ PORT_BIT(0x01, IP_ACTIVE_HIGH, IPT_BUTTON1) PORT_NAME("Snapshot Button") PORT_CODE(KEYCODE_MINUS_PAD) PORT_CHANGED_MEMBER(DEVICE_SELF, FUNC(spectrum_d40base_device::snapshot_button), 0)
+
+ PORT_START("JOY")
+ PORT_BIT(0x01, IP_ACTIVE_HIGH, IPT_JOYSTICK_RIGHT) PORT_8WAY
+ PORT_BIT(0x02, IP_ACTIVE_HIGH, IPT_JOYSTICK_LEFT) PORT_8WAY
+ PORT_BIT(0x04, IP_ACTIVE_HIGH, IPT_JOYSTICK_DOWN) PORT_8WAY
+ PORT_BIT(0x08, IP_ACTIVE_HIGH, IPT_JOYSTICK_UP) PORT_8WAY
+ PORT_BIT(0x10, IP_ACTIVE_HIGH, IPT_BUTTON1)
+ PORT_BIT(0xe0, IP_ACTIVE_HIGH, IPT_UNUSED)
+INPUT_PORTS_END
+
+//-------------------------------------------------
+// input_ports - device-specific input ports
+//-------------------------------------------------
+
+ioport_constructor spectrum_d40base_device::device_input_ports() const
+{
+ return INPUT_PORTS_NAME(d40);
+}
+
+//-------------------------------------------------
+// SLOT_INTERFACE( floppies )
+//-------------------------------------------------
+
+static void didaktik_floppies(device_slot_interface &device)
+{
+ device.option_add("35dd", FLOPPY_35_DD);
+ device.option_add("525dd", FLOPPY_525_DD);
+}
+
+//-------------------------------------------------
+// ROM
+//-------------------------------------------------
+
+ROM_START(d40)
+ ROM_REGION(0x4000, "rom", 0)
+ ROM_DEFAULT_BIOS("mdos11")
+ ROM_SYSTEM_BIOS(0, "mdos11", "MDOS 1.0 (1991)")
+ ROMX_LOAD("mdos10.bin", 0x0000, 0x4000, CRC(e6b70939) SHA1(308c4b5daf6bb1f05c68a447129d723da423326e), ROM_BIOS(0))
+ ROM_SYSTEM_BIOS(1, "mdos12", "MDOS 1.0+ (1992)") // possible unofficial modification
+ ROMX_LOAD("mdos10p.bin", 0x0000, 0x4000, CRC(92c45741) SHA1(b8473235feecff4eccbace56a90cf1d8c79506eb), ROM_BIOS(1))
+ROM_END
+
+ROM_START(d80v2)
+ ROM_REGION(0x4000, "rom", 0)
+ ROM_DEFAULT_BIOS("mdos2")
+ ROM_SYSTEM_BIOS(0, "mdos2", "MDOS 2.0 (1993)")
+ ROMX_LOAD("mdos20.bin", 0x0000, 0x4000, CRC(9e79d022) SHA1(e8d3355051fb287dd0dda34ba8824442130c8254), ROM_BIOS(0))
+ROM_END
+
+//-------------------------------------------------
+// device_add_mconfig - add device configuration
+//-------------------------------------------------
+
+void spectrum_d40_device::device_add_mconfig(machine_config &config)
+{
+ WD2797(config, m_fdc, 4_MHz_XTAL / 4);
+ m_fdc->intrq_wr_callback().set(FUNC(spectrum_d40_device::fdc_intrq_w));
+ m_fdc->drq_wr_callback().set(FUNC(spectrum_d40_device::fdc_drq_w));
+ FLOPPY_CONNECTOR(config, "fdc:0", didaktik_floppies, "525dd", floppy_image_device::default_pc_floppy_formats).enable_sound(true);
+ FLOPPY_CONNECTOR(config, "fdc:1", didaktik_floppies, "525dd", floppy_image_device::default_pc_floppy_formats).enable_sound(true);
+
+ I8255(config, m_ppi);
+ m_ppi->in_pa_callback().set_ioport("JOY");
+
+ /* software list */
+ //SOFTWARE_LIST(config, "flop_list").set_original("spectrum_d40_flop");
+}
+
+void spectrum_d80_device::device_add_mconfig(machine_config &config)
+{
+ WD2797(config, m_fdc, 4_MHz_XTAL / 4);
+ m_fdc->intrq_wr_callback().set(FUNC(spectrum_d80_device::fdc_intrq_w));
+ m_fdc->drq_wr_callback().set(FUNC(spectrum_d80_device::fdc_drq_w));
+ FLOPPY_CONNECTOR(config, "fdc:0", didaktik_floppies, "35dd", floppy_image_device::default_pc_floppy_formats).enable_sound(true);
+ FLOPPY_CONNECTOR(config, "fdc:1", didaktik_floppies, "35dd", floppy_image_device::default_pc_floppy_formats).enable_sound(true);
+
+ I8255(config, m_ppi);
+
+ /* software list */
+ //SOFTWARE_LIST(config, "flop_list").set_original("spectrum_d40_flop");
+}
+
+void spectrum_d80v2_device::device_add_mconfig(machine_config &config)
+{
+ WD37C65C(config, m_fdc, 16_MHz_XTAL); // actually GM82C765B
+ FLOPPY_CONNECTOR(config, "fdc:0", didaktik_floppies, "35dd", floppy_image_device::default_pc_floppy_formats).enable_sound(true);
+ FLOPPY_CONNECTOR(config, "fdc:1", didaktik_floppies, "35dd", floppy_image_device::default_pc_floppy_formats).enable_sound(true);
+
+ I8255(config, m_ppi);
+
+ /* software list */
+ //SOFTWARE_LIST(config, "flop_list").set_original("spectrum_d40_flop");
+}
+
+const tiny_rom_entry *spectrum_d40_device::device_rom_region() const
+{
+ return ROM_NAME(d40);
+}
+
+const tiny_rom_entry *spectrum_d80v2_device::device_rom_region() const
+{
+ return ROM_NAME(d80v2);
+}
+
+//**************************************************************************
+// LIVE DEVICE
+//**************************************************************************
+
+//-------------------------------------------------
+// spectrum_d40base_device - constructor
+//-------------------------------------------------
+
+spectrum_d40base_device::spectrum_d40base_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_spectrum_expansion_interface(mconfig, *this)
+ , m_rom(*this, "rom")
+ , m_ppi(*this, "ppi")
+ , m_snap(*this, "BUTTON")
+{
+}
+
+spectrum_d40_device::spectrum_d40_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
+ : spectrum_d40base_device(mconfig, SPECTRUM_D40, tag, owner, clock)
+ , m_fdc(*this, "fdc")
+ , m_floppy(*this, "fdc:%u", 0)
+{
+}
+
+spectrum_d40_device::spectrum_d40_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock)
+ :spectrum_d40base_device(mconfig, type, tag, owner, clock)
+ , m_fdc(*this, "fdc")
+ , m_floppy(*this, "fdc:%u", 0)
+{
+}
+
+spectrum_d80_device::spectrum_d80_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
+ : spectrum_d40_device(mconfig, SPECTRUM_D80, tag, owner, clock)
+{
+}
+
+spectrum_d80v2_device::spectrum_d80v2_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
+ : spectrum_d40base_device(mconfig, SPECTRUM_D80V2, tag, owner, clock)
+ , m_fdc(*this, "fdc")
+ , m_floppy(*this, "fdc:%u", 0)
+{
+}
+
+//-------------------------------------------------
+// device_start - device-specific startup
+//-------------------------------------------------
+
+void spectrum_d40base_device::device_start()
+{
+ std::fill(std::begin(m_ram), std::end(m_ram), 0);
+ save_item(NAME(m_romcs));
+ save_item(NAME(m_ram));
+ save_item(NAME(m_snap_flag));
+ save_item(NAME(m_8255_reset));
+ save_item(NAME(m_8255_enable));
+}
+
+//-------------------------------------------------
+// device_reset - device-specific reset
+//-------------------------------------------------
+
+void spectrum_d40base_device::device_reset()
+{
+ m_romcs = 0;
+ m_snap_flag = 0;
+ m_8255_reset = 0;
+ m_8255_enable = 0;
+}
+
+
+//**************************************************************************
+// IMPLEMENTATION spectrum_d40base_device
+//**************************************************************************
+
+bool spectrum_d40base_device::romcs()
+{
+ return m_romcs;
+}
+
+void spectrum_d40base_device::pre_opcode_fetch(offs_t offset)
+{
+ if (!machine().side_effects_disabled())
+ {
+ switch (offset)
+ {
+ case 0x0000:
+ case 0x0008:
+ m_romcs = 1;
+ nmi_check();
+ break;
+ case 0x0066:
+ if (!m_romcs)
+ {
+ m_romcs = 1;
+ m_snap_flag = 1;
+ nmi_check();
+ }
+ break;
+ case 0x1700:
+ if (!m_snap_flag)
+ m_romcs = 0;
+ nmi_check();
+ break;
+ }
+ }
+}
+
+uint8_t spectrum_d40base_device::iorq_r(offs_t offset)
+{
+ uint8_t data = offset & 1 ? m_slot->fb_r() : 0xff;
+
+ switch (offset & 0xf9)
+ {
+ case 0x81: // FDC
+ data = fdc0_r(offset);
+ break;
+ case 0x89: // FDC
+ data = fdc1_r(offset);
+ break;
+ }
+
+ if (!BIT(offset, 7) && m_8255_enable) // 1F/3F/5F/7F
+ data = m_ppi->read((offset >> 5) & 3);
+
+ return data;
+}
+
+void spectrum_d40base_device::iorq_w(offs_t offset, uint8_t data)
+{
+ switch (offset & 0xf9)
+ {
+ case 0x81: // FDC
+ fdc0_w(offset, data);
+ break;
+ case 0x89: // control port
+ fdc1_w(offset, data);
+ break;
+ case 0x91: // PPI reset
+ m_8255_reset = BIT(data, 5);
+ if (!m_8255_reset)
+ {
+ m_ppi->reset();
+ m_8255_enable = 0;
+ }
+ break;
+ case 0x99: // PPI enable
+ if (m_8255_reset)
+ m_8255_enable = BIT(data, 4);
+ break;
+ }
+
+ if (!BIT(offset, 7) && m_8255_enable) // 1F/3F/5F/7F
+ m_ppi->write((offset >> 5) & 3, data);
+}
+
+uint8_t spectrum_d40base_device::mreq_r(offs_t offset)
+{
+ if (m_snap_flag && offset == 0x66)
+ {
+ m_snap_flag = 0; // hacky, real hardware reset this latch by Z80 /WR line
+ return 0xc7; // RST 0 inject
+ }
+
+ uint8_t data = 0xff;
+
+ if (m_romcs)
+ {
+ if (offset < 0x3800)
+ data = m_rom->base()[offset];
+ else
+ data = m_ram[offset & 0x7ff];
+ }
+
+ return data;
+}
+
+void spectrum_d40base_device::mreq_w(offs_t offset, uint8_t data)
+{
+ if (m_romcs)
+ {
+ if ((offset & 0xf800) == 0x3800)
+ m_ram[offset & 0x7ff] = data;
+ }
+}
+
+INPUT_CHANGED_MEMBER(spectrum_d40base_device::snapshot_button)
+{
+ nmi_check();
+}
+
+void spectrum_d40base_device::nmi_check()
+{
+ int state = CLEAR_LINE;
+
+ if (!m_romcs && m_snap->read())
+ state = ASSERT_LINE;
+
+ m_slot->nmi_w(state);
+}
+
+//**************************************************************************
+// IMPLEMENTATION spectrum_d40_device
+//**************************************************************************
+
+void spectrum_d40_device::device_start()
+{
+ spectrum_d40base_device::device_start();
+ save_item(NAME(m_control));
+ save_item(NAME(m_intrq));
+ save_item(NAME(m_drq));
+}
+
+void spectrum_d40_device::device_reset()
+{
+ spectrum_d40base_device::device_reset();
+ m_control = 0;
+ m_intrq = 0;
+ m_drq = 0;
+}
+
+uint8_t spectrum_d40_device::fdc0_r(offs_t offset)
+{
+ return m_fdc->read((offset >> 1) & 0x03);
+}
+
+void spectrum_d40_device::fdc0_w(offs_t offset, uint8_t data)
+{
+ m_fdc->write((offset >> 1) & 0x03, data);
+}
+
+void spectrum_d40_device::fdc1_w(offs_t offset, uint8_t data)
+{
+ m_control = data;
+
+ floppy_image_device* floppy = nullptr;
+ if (BIT(data, 0))
+ floppy = m_floppy[0]->get_device();
+ else if (BIT(data, 1))
+ floppy = m_floppy[1]->get_device();
+ m_fdc->set_floppy(floppy);
+
+ m_floppy[0]->get_device()->mon_w(BIT(data, 2) ? 0 : 1);
+ m_floppy[1]->get_device()->mon_w(BIT(data, 3) ? 0 : 1);
+
+ nmi_check();
+}
+
+void spectrum_d40_device::fdc_intrq_w(int state)
+{
+ m_intrq = state;
+ nmi_check();
+}
+
+void spectrum_d40_device::fdc_drq_w(int state)
+{
+ m_drq = state;
+ nmi_check();
+}
+
+void spectrum_d40_device::nmi_check()
+{
+ int state = CLEAR_LINE;
+
+ if (!m_romcs && m_snap->read())
+ state = ASSERT_LINE;
+
+ if (m_intrq && BIT(m_control, 7))
+ state = ASSERT_LINE;
+
+ if (m_drq && BIT(m_control, 6))
+ state = ASSERT_LINE;
+
+ m_slot->nmi_w(state);
+}
+
+//**************************************************************************
+// IMPLEMENTATION spectrum_d80v2_device
+//**************************************************************************
+
+void spectrum_d80v2_device::pre_opcode_fetch(offs_t offset)
+{
+ if (!machine().side_effects_disabled())
+ {
+ switch (offset)
+ {
+ case 0x0000:
+ case 0x0008:
+ case 0x0066:
+ m_romcs = 1;
+ nmi_check();
+ break;
+ case 0x1700:
+ m_romcs = 0;
+ nmi_check();
+ break;
+ }
+ }
+}
+
+uint8_t spectrum_d80v2_device::fdc0_r(offs_t offset)
+{
+ return BIT(offset, 2) ? m_fdc->fifo_r() : m_fdc->msr_r();
+}
+
+uint8_t spectrum_d80v2_device::fdc1_r(offs_t offset)
+{
+ return m_fdc->dor_r();
+}
+
+void spectrum_d80v2_device::fdc0_w(offs_t offset, uint8_t data)
+{
+ if (BIT(offset, 2))
+ m_fdc->fifo_w(data);
+}
+
+void spectrum_d80v2_device::fdc1_w(offs_t offset, uint8_t data)
+{
+ m_fdc->dor_w(data);
+}
+
+uint8_t spectrum_d80v2_device::mreq_r(offs_t offset)
+{
+ uint8_t data = 0xff;
+
+ if (m_romcs)
+ {
+ if (offset < 0x3800)
+ data = m_rom->base()[offset];
+ else
+ data = m_ram[offset & 0x7ff];
+ }
+
+ return data;
+}
diff --git a/src/devices/bus/spectrum/d40.h b/src/devices/bus/spectrum/d40.h
new file mode 100644
index 00000000000..f63438f5eb4
--- /dev/null
+++ b/src/devices/bus/spectrum/d40.h
@@ -0,0 +1,130 @@
+// license:BSD-3-Clause
+// copyright-holders:MetalliC
+/**********************************************************************
+
+ Didaktik D40/D80 interface
+
+**********************************************************************/
+
+#ifndef MAME_BUS_SPECTRUM_D40_H
+#define MAME_BUS_SPECTRUM_D40_H
+
+#pragma once
+
+#include "exp.h"
+//#include "softlist.h"
+#include "imagedev/floppy.h"
+#include "machine/wd_fdc.h"
+#include "machine/upd765.h"
+#include "machine/i8255.h"
+
+//**************************************************************************
+// TYPE DEFINITIONS
+//**************************************************************************
+
+class spectrum_d40base_device: public device_t, public device_spectrum_expansion_interface
+{
+public:
+ DECLARE_INPUT_CHANGED_MEMBER(snapshot_button);
+
+protected:
+ spectrum_d40base_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 ATTR_COLD;
+ virtual void device_reset() override ATTR_COLD;
+
+ // optional information overrides
+ virtual ioport_constructor device_input_ports() const override ATTR_COLD;
+
+ 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 uint8_t iorq_r(offs_t offset) override;
+ virtual void iorq_w(offs_t offset, uint8_t data) 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; }
+ virtual void fdc0_w(offs_t offset, uint8_t data) { }
+ virtual void fdc1_w(offs_t offset, uint8_t data) { }
+ virtual void nmi_check();
+
+ required_memory_region m_rom;
+ required_device<i8255_device> m_ppi;
+ required_ioport m_snap;
+
+ bool m_romcs;
+ uint8_t m_ram[2 * 1024];
+ int m_snap_flag;
+ int m_8255_reset;
+ int m_8255_enable;
+};
+
+class spectrum_d40_device :
+ public spectrum_d40base_device
+{
+public:
+ spectrum_d40_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
+
+protected:
+ spectrum_d40_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 ATTR_COLD;
+ virtual const tiny_rom_entry *device_rom_region() const override ATTR_COLD;
+
+ virtual void device_start() override ATTR_COLD;
+ virtual void device_reset() override ATTR_COLD;
+
+ required_device<wd_fdc_device_base> m_fdc;
+ required_device_array<floppy_connector, 2> m_floppy;
+
+ virtual uint8_t fdc0_r(offs_t offset) override;
+ virtual void fdc0_w(offs_t offset, uint8_t data) override;
+ virtual void fdc1_w(offs_t offset, uint8_t data) override;
+ void fdc_intrq_w(int state);
+ void fdc_drq_w(int state);
+ virtual void nmi_check() override;
+
+ uint8_t m_control;
+ int m_intrq;
+ int m_drq;
+};
+
+class spectrum_d80_device :
+ public spectrum_d40_device
+{
+public:
+ spectrum_d80_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
+
+protected:
+ virtual void device_add_mconfig(machine_config &config) override ATTR_COLD;
+};
+
+class spectrum_d80v2_device :
+ public spectrum_d40base_device
+{
+public:
+ spectrum_d80v2_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
+
+protected:
+ virtual void device_add_mconfig(machine_config &config) override ATTR_COLD;
+ virtual const tiny_rom_entry *device_rom_region() const override ATTR_COLD;
+
+ virtual void pre_opcode_fetch(offs_t offset) override;
+ virtual uint8_t mreq_r(offs_t offset) override;
+
+ required_device<wd37c65c_device> m_fdc;
+ required_device_array<floppy_connector, 2> m_floppy;
+
+ virtual uint8_t fdc0_r(offs_t offset) override;
+ virtual uint8_t fdc1_r(offs_t offset) override;
+ virtual void fdc0_w(offs_t offset, uint8_t data) override;
+ virtual void fdc1_w(offs_t offset, uint8_t data) override;
+};
+
+// device type definition
+DECLARE_DEVICE_TYPE(SPECTRUM_D40, spectrum_d40_device)
+DECLARE_DEVICE_TYPE(SPECTRUM_D80, spectrum_d80_device)
+DECLARE_DEVICE_TYPE(SPECTRUM_D80V2, spectrum_d80v2_device)
+
+#endif // MAME_BUS_SPECTRUM_D40_H
diff --git a/src/devices/bus/spectrum/exp.cpp b/src/devices/bus/spectrum/exp.cpp
index 6092f87d9ce..22d0a5665e5 100644
--- a/src/devices/bus/spectrum/exp.cpp
+++ b/src/devices/bus/spectrum/exp.cpp
@@ -25,8 +25,8 @@ DEFINE_DEVICE_TYPE(SPECTRUM_EXPANSION_SLOT, spectrum_expansion_slot_device, "spe
// device_spectrum_expansion_interface - constructor
//-------------------------------------------------
-device_spectrum_expansion_interface::device_spectrum_expansion_interface(const machine_config &mconfig, device_t &device)
- : device_slot_card_interface(mconfig, device)
+device_spectrum_expansion_interface::device_spectrum_expansion_interface(const machine_config &mconfig, device_t &device) :
+ device_interface(device, "spectrumexp")
{
m_slot = dynamic_cast<spectrum_expansion_slot_device *>(device.owner());
}
@@ -42,54 +42,29 @@ device_spectrum_expansion_interface::device_spectrum_expansion_interface(const m
spectrum_expansion_slot_device::spectrum_expansion_slot_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) :
device_t(mconfig, SPECTRUM_EXPANSION_SLOT, tag, owner, clock),
- device_slot_interface(mconfig, *this),
+ device_single_card_slot_interface<device_spectrum_expansion_interface>(mconfig, *this),
m_card(nullptr),
m_irq_handler(*this),
- m_nmi_handler(*this)
+ m_nmi_handler(*this),
+ m_fb_r_handler(*this, 0xff)
{
}
//-------------------------------------------------
-// device_validity_check - device-specific checks
-//-------------------------------------------------
-
-void spectrum_expansion_slot_device::device_validity_check(validity_checker &valid) const
-{
- device_t *const card(get_card_device());
- if (card && !dynamic_cast<device_spectrum_expansion_interface *>(card))
- osd_printf_error("Card device %s (%s) does not implement device_spectrum_expansion_interface\n", card->tag(), card->name());
-}
-
-//-------------------------------------------------
// device_start - device-specific startup
//-------------------------------------------------
void spectrum_expansion_slot_device::device_start()
{
- device_t *const card_device(get_card_device());
- m_card = dynamic_cast<device_spectrum_expansion_interface *>(card_device);
- if (card_device && !m_card)
- throw emu_fatalerror("spectrum_expansion_slot_device: card device %s (%s) does not implement device_spectrum_expansion_interface\n", card_device->tag(), card_device->name());
-
- // resolve callbacks
- m_irq_handler.resolve_safe();
- m_nmi_handler.resolve_safe();
-}
-
-//-------------------------------------------------
-// device_reset - device-specific reset
-//-------------------------------------------------
-
-void spectrum_expansion_slot_device::device_reset()
-{
+ m_card = get_card_device();
}
//-------------------------------------------------
// romcs
//-------------------------------------------------
-READ_LINE_MEMBER(spectrum_expansion_slot_device::romcs)
+bool spectrum_expansion_slot_device::romcs()
{
if (m_card)
return m_card->romcs();
@@ -134,7 +109,7 @@ uint8_t spectrum_expansion_slot_device::iorq_r(offs_t offset)
if (m_card)
return m_card->iorq_r(offset);
else
- return 0xff;
+ return offset & 1 ? fb_r() : 0xff;
}
//-------------------------------------------------
@@ -178,22 +153,33 @@ void spectrum_expansion_slot_device::mreq_w(offs_t offset, uint8_t data)
// slot devices
#include "beta.h"
#include "beta128.h"
-//#include "disciple.h"
+#include "d40.h"
#include "intf1.h"
#include "intf2.h"
+#include "floppyone.h"
#include "fuller.h"
#include "kempjoy.h"
+#include "kempdisc.h"
+#include "logitek.h"
+#include "lprint.h"
#include "melodik.h"
#include "mface.h"
+#include "mgt.h"
#include "mikroplus.h"
+#include "mpoker.h"
+#include "musicmachine.h"
#include "opus.h"
#include "plus2test.h"
-//#include "plusd.h"
#include "protek.h"
+#include "sdi.h"
+#include "sixword.h"
#include "specdrum.h"
+#include "speccydos.h"
+#include "specmate.h"
#include "uslot.h"
#include "usource.h"
#include "uspeech.h"
+#include "vtx5000.h"
#include "wafa.h"
void spectrum_expansion_devices(device_slot_interface &device)
@@ -201,46 +187,81 @@ void spectrum_expansion_devices(device_slot_interface &device)
device.option_add("betav2", SPECTRUM_BETAV2);
device.option_add("betav3", SPECTRUM_BETAV3);
device.option_add("betaplus", SPECTRUM_BETAPLUS);
+ device.option_add("betaclone", SPECTRUM_BETACLONE);
+ device.option_add("betacbi", SPECTRUM_BETACBI);
+ device.option_add("gamma", SPECTRUM_GAMMA);
device.option_add("beta128", SPECTRUM_BETA128);
- //device.option_add("disciple", SPECTRUM_DISCIPLE);
+ device.option_add("d40", SPECTRUM_D40);
+ device.option_add("d80", SPECTRUM_D80);
+ device.option_add("d80v2", SPECTRUM_D80V2);
+ device.option_add("disciple", SPECTRUM_DISCIPLE);
device.option_add("intf1", SPECTRUM_INTF1);
device.option_add("intf2", SPECTRUM_INTF2);
+ device.option_add("flpone", SPECTRUM_FLPONE);
device.option_add("fuller", SPECTRUM_FULLER);
device.option_add("kempjoy", SPECTRUM_KEMPJOY);
+ device.option_add("kempdisc", SPECTRUM_KEMPDISC);
+ device.option_add("kempcentrs", SPECTRUM_KEMPCENTRS);
+ device.option_add("kempcentref", SPECTRUM_KEMPCENTREF);
+ device.option_add("kempcentreu", SPECTRUM_KEMPCENTREU);
+ device.option_add("lprint", SPECTRUM_LPRINT);
+ device.option_add("lprint3", SPECTRUM_LPRINT3);
device.option_add("melodik", SPECTRUM_MELODIK);
+ device.option_add("mface1v1", SPECTRUM_MFACE1V1);
+ device.option_add("mface1v2", SPECTRUM_MFACE1V2);
+ device.option_add("mface1v3", SPECTRUM_MFACE1V3);
device.option_add("mface1", SPECTRUM_MFACE1);
+ device.option_add("mface128v1", SPECTRUM_MFACE128V1);
device.option_add("mface128", SPECTRUM_MFACE128);
device.option_add("mikroplus", SPECTRUM_MIKROPLUS);
+ device.option_add("mpoker", SPECTRUM_MPOKER);
device.option_add("mprint", SPECTRUM_MPRINT);
+ device.option_add("musicmachine", SPECTRUM_MUSICMACHINE);
device.option_add("opus", SPECTRUM_OPUS);
- //device.option_add("plusd", SPECTRUM_PLUSD);
+ device.option_add("plusd", SPECTRUM_PLUSD);
+ device.option_add("proceed", SPECTRUM_PROCEED);
device.option_add("protek", SPECTRUM_PROTEK);
+ device.option_add("sdi", SPECTRUM_SDI);
+ device.option_add("speccydos", SPECTRUM_SPECCYDOS);
+ device.option_add("spdos", SPECTRUM_SPDOS);
device.option_add("specdrum", SPECTRUM_SPECDRUM);
+ device.option_add("specmate", SPECTRUM_SPECMATE);
+ device.option_add("swiftdisc", SPECTRUM_SWIFTDISC);
+ device.option_add("swiftdisc2", SPECTRUM_SWIFTDISC2);
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);
}
void spec128_expansion_devices(device_slot_interface &device)
{
device.option_add("beta128", SPECTRUM_BETA128);
- //device.option_add("disciple", SPECTRUM_DISCIPLE);
+ device.option_add("disciple", SPECTRUM_DISCIPLE);
device.option_add("intf1", SPECTRUM_INTF1);
device.option_add("intf2", SPECTRUM_INTF2);
device.option_add("kempjoy", SPECTRUM_KEMPJOY);
+ device.option_add("mface128v1", SPECTRUM_MFACE128V1);
device.option_add("mface128", SPECTRUM_MFACE128);
device.option_add("mikroplus", SPECTRUM_MIKROPLUS);
device.option_add("mprint", SPECTRUM_MPRINT);
+ device.option_add("musicmachine", SPECTRUM_MUSICMACHINE);
device.option_add("opus", SPECTRUM_OPUS);
+ device.option_add("plusd", SPECTRUM_PLUSD);
device.option_add("plus2test", SPECTRUM_PLUS2TEST);
device.option_add("protek", SPECTRUM_PROTEK);
+ device.option_add("speccydos", SPECTRUM_SPECCYDOS);
device.option_add("specdrum", SPECTRUM_SPECDRUM);
+ device.option_add("swiftdisc", SPECTRUM_SWIFTDISC);
+ device.option_add("swiftdisc2", SPECTRUM_SWIFTDISC2);
device.option_add("wafadrive", SPECTRUM_WAFA);
}
void specpls3_expansion_devices(device_slot_interface &device)
{
+ device.option_add("kempjoy", SPECTRUM_KEMPJOY);
device.option_add("mface3", SPECTRUM_MFACE3);
+ device.option_add("musicmachine", SPECTRUM_MUSICMACHINE);
}
diff --git a/src/devices/bus/spectrum/exp.h b/src/devices/bus/spectrum/exp.h
index 5de81d4ae43..030986fa6e8 100644
--- a/src/devices/bus/spectrum/exp.h
+++ b/src/devices/bus/spectrum/exp.h
@@ -8,34 +8,38 @@
Pinout:
- A15 1 A14
- A13 2 A12
- D7 3 +5v
- ¬OE 4 NC
- SLOT 5 SLOT
- D0 6 0v
- D1 7 0v
- D2 8 ¬CK
- D6 9 A0
- D5 10 A1
- D3 11 A2
- D4 12 A3
- ¬INT 13 NC
- ¬NMI 14 0v
- ¬HALT 15 ¬OE
- ¬MREQ 16 NC
- ¬IORQ 17 NC
- ¬RD 18 NC
- ¬WR 19 ¬BUSRQ
- NC 20 ¬RESET
- ¬WAIT 21 A7
- +12v 22 A6
- NC 23 A5
- ¬M1 24 A4
- ¬RFSH 25 ¬ROMCS
- A8 26 ¬BUSACK
- A10 27 A9
- NC 28 A11
+ 48K 128K/+2 +2A/+2B/+3/3B
+
+ A B A B A B
+ A15 1 A14 A15 1 A14 A15 1 A14
+ A13 2 A12 A13 2 A12 A13 2 A12
+ D7 3 +5V D7 3 +5v D7 3 +5v
+ NC 4 +9V NC 4 +9V /OE ROM1 4 NC
+ SLOT 5 SLOT SLOT 5 SLOT SLOT 5 SLOT
+ D0 6 GND D0 6 GND D0 6 GND
+ D1 7 GND D1 7 GND D1 7 GND
+ D2 8 CLK D2 8 CLK D2 8 CKEXT
+ D6 9 A0 D6 9 A0 D6 9 A0
+ D5 10 A1 D5 10 A1 D5 10 A1
+ D3 11 A2 D3 11 A2 D3 11 A2
+ D4 12 A3 D4 12 A3 D4 12 A3
+ /INT 13 /IORQGE /INT 13 /IORQGE (+2 only) /INT 13 NC
+ /NMI 14 GND /NMI 14 GND /NMI 14 GND
+ /HALT 15 VIDEO /HALT 15 NC /HALT 15 /OE ROM2
+ /MREQ 16 /Y /MREQ 16 NC /MREQ 16 /DRD
+ /IORQ 17 V /IORQ 17 NC /IORQ 17 /DWR
+ /RD 18 U /RD 18 NC /RD 18 /MTR
+ /WR 19 /BUSRQ /WR 19 /BUSRQ /WR 19 /BUSRQ
+ -5V 20 /RESET -5V 20 /RESET NC 20 /RESET
+ /WAIT 21 A7 /WAIT 21 A7 /WAIT 21 A7
+ +12V 22 A6 +12V 22 A6 +12V 22 A6
+ 12VAC 23 A5 12VAC 23 A5 -12V 23 A5
+ /M1 24 A4 /M1 24 A4 /M1 24 A4
+ /RFSH 25 /ROMCS /RFSH 25 /ROMCS /RFSH 25 NC
+ A8 26 /BUSACK A8 26 /BUSACK A8 26 /BUSACK
+ A10 27 A9 A10 27 A9 A10 27 A9
+ NC 28 A11 NC 28 A11 RESET 28 A11
+
**********************************************************************/
@@ -53,7 +57,7 @@
class device_spectrum_expansion_interface;
-class spectrum_expansion_slot_device : public device_t, public device_slot_interface
+class spectrum_expansion_slot_device : public device_t, public device_single_card_slot_interface<device_spectrum_expansion_interface>
{
public:
// construction/destruction
@@ -72,6 +76,7 @@ public:
// callbacks
auto irq_handler() { return m_irq_handler.bind(); }
auto nmi_handler() { return m_nmi_handler.bind(); }
+ auto fb_r_handler() { return m_fb_r_handler.bind(); }
void pre_opcode_fetch(offs_t offset);
void post_opcode_fetch(offs_t offset);
@@ -82,45 +87,45 @@ 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:
// device-level overrides
- virtual void device_validity_check(validity_checker &valid) const override;
- virtual void device_start() override;
- virtual void device_reset() override;
+ virtual void device_start() override ATTR_COLD;
device_spectrum_expansion_interface *m_card;
private:
devcb_write_line m_irq_handler;
devcb_write_line m_nmi_handler;
+ devcb_read8 m_fb_r_handler;
};
// ======================> device_spectrum_expansion_interface
-class device_spectrum_expansion_interface : public device_slot_card_interface
+class device_spectrum_expansion_interface : public device_interface
{
public:
- // construction/destruction
- device_spectrum_expansion_interface(const machine_config &mconfig, device_t &device);
-
// reading and writing
- virtual void pre_opcode_fetch(offs_t offset) { };
- virtual void post_opcode_fetch(offs_t offset) { };
- virtual void pre_data_fetch(offs_t offset) { };
- virtual void post_data_fetch(offs_t offset) { };
+ virtual void pre_opcode_fetch(offs_t offset) { }
+ virtual void post_opcode_fetch(offs_t offset) { }
+ virtual void pre_data_fetch(offs_t offset) { }
+ virtual void post_data_fetch(offs_t offset) { }
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 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
+ device_spectrum_expansion_interface(const machine_config &mconfig, device_t &device);
+
spectrum_expansion_slot_device *m_slot;
};
diff --git a/src/devices/bus/spectrum/floppyone.cpp b/src/devices/bus/spectrum/floppyone.cpp
new file mode 100644
index 00000000000..59b4a8a2f39
--- /dev/null
+++ b/src/devices/bus/spectrum/floppyone.cpp
@@ -0,0 +1,317 @@
+// license:BSD-3-Clause
+// copyright-holders:MetalliC
+/*********************************************************************
+
+ FloppyOne DOS Interface
+ (c) 1984/5 Rocky P. Gush (RSA)
+
+ FD1791-based floppy drive and printer interface with 4K RAM and 8K ROM
+ Was mainly designed as tape replacement, and sort of emulate how tapes works,
+ which allows to copy and use most of existing software and (not protected) games with no modification.
+
+ Doube-side drives considered as 2 separate floppies (0 and 4, 1 and 5 etc) probably to mimic tape sides A/B,
+ disks is password protected.
+
+ Main commands:
+ !D=n - change current drive, where 'n' 0-3 = FDD 0-3 side 0, 4-7 = FDD 0-3 side 1, 8 = enable LOAD from tape
+ CAT - list disk contents
+ LOAD "name" - load program, LOAD "" will load first program (unless was disabled by !d=8 command)
+ LOAD *"m";1;"name" - same as above
+ SAVE "name" - save program
+ !FORMAT "diskname";"password";tracks - format disk, if disk was already formatted you'll be prompted for password.
+ !6=n - set text mode, 0 - regular 32-column, 3 - 64-column
+ !B=rs232delay, 0=use parallel printer (default)
+ There is more of special "!x=n" commands, but theirs functions is not known, manual is missing.
+ Some information about this device https://worldofspectrum.org/forums/discussion/42944/rocky-gush-floppy-drive-interface/p1
+
+ Notes / TODOs:
+ - Interface1 compatibility mode is not well understood and not fully implemented
+ - RS232 partially implemented
+
+*********************************************************************/
+
+#include "emu.h"
+#include "floppyone.h"
+
+#include "formats/fl1_dsk.h"
+
+
+/***************************************************************************
+ DEVICE DEFINITIONS
+***************************************************************************/
+
+DEFINE_DEVICE_TYPE(SPECTRUM_FLPONE, spectrum_flpone_device, "spectrum_flpone", "FloppyOne DOS Interface")
+
+
+//-------------------------------------------------
+// INPUT_PORTS
+//-------------------------------------------------
+
+INPUT_PORTS_START(flpone)
+ PORT_START("BUTTON")
+ PORT_BIT(0x01, IP_ACTIVE_HIGH, IPT_BUTTON1) PORT_NAME("Snapshot Button") PORT_CODE(KEYCODE_MINUS_PAD) PORT_CHANGED_MEMBER(DEVICE_SELF, FUNC(spectrum_flpone_device::snapshot_button), 0)
+
+ PORT_START("SW1")
+ PORT_CONFNAME(0x01, 0x01, "Disc Interface")
+ PORT_CONFSETTING(0x01, "Enabled")
+ PORT_CONFSETTING(0x00, "Disabled")
+ PORT_START("SW2")
+ PORT_CONFNAME(0x01, 0x00, "Interface 1")
+ PORT_CONFSETTING(0x01, "Enable")
+ PORT_CONFSETTING(0x00, "Disable")
+INPUT_PORTS_END
+
+//-------------------------------------------------
+// input_ports - device-specific input ports
+//-------------------------------------------------
+
+ioport_constructor spectrum_flpone_device::device_input_ports() const
+{
+ return INPUT_PORTS_NAME(flpone);
+}
+
+//-------------------------------------------------
+// SLOT_INTERFACE( floppies )
+//-------------------------------------------------
+
+static void flpone_floppies(device_slot_interface &device)
+{
+ device.option_add("525ssdd", FLOPPY_525_SSDD);
+ device.option_add("525dd", FLOPPY_525_DD);
+ device.option_add("525ssqd", FLOPPY_525_SSQD);
+ device.option_add("525qd", FLOPPY_525_QD);
+ device.option_add("35ssdd", FLOPPY_35_SSDD);
+ device.option_add("35dd", FLOPPY_35_DD);
+}
+
+//-------------------------------------------------
+// floppy_formats
+//-------------------------------------------------
+
+void spectrum_flpone_device::floppy_formats(format_registration &fr)
+{
+ fr.add_mfm_containers();
+ fr.add(FLOPPY_FL1_FORMAT);
+}
+
+//-------------------------------------------------
+// ROM( flpone )
+//-------------------------------------------------
+
+ROM_START(flpone)
+ ROM_REGION(0x2000, "rom", 0)
+ ROM_DEFAULT_BIOS("v4")
+
+ ROM_SYSTEM_BIOS(0, "v4", "FloppyOne DOS V4")
+ ROMX_LOAD("fldos4.bin", 0x0000, 0x2000, CRC(a012f64f) SHA1(f54b47d83c1d45c0e1e10302e519693bc734ae5c), ROM_BIOS(0))
+
+ ROM_REGION(0x4000, "prom", 0)
+ ROM_LOAD("ula.bin", 0x0000, 0x2000, CRC(d67d85aa) SHA1(eb1d28bf8aa35bfab3a45a5827f252498ac2c651)) // 1st half is not used, A13 tied to Vcc
+ ROM_CONTINUE(0x0000, 0x2000)
+ROM_END
+
+//-------------------------------------------------
+// device_add_mconfig - add device configuration
+//-------------------------------------------------
+
+void spectrum_flpone_device::device_add_mconfig(machine_config &config)
+{
+ FD1791(config, m_fdc, 1_MHz_XTAL);
+
+ FLOPPY_CONNECTOR(config, "fdc:0", flpone_floppies, "525qd", spectrum_flpone_device::floppy_formats).enable_sound(true);
+ FLOPPY_CONNECTOR(config, "fdc:1", flpone_floppies, "525qd", spectrum_flpone_device::floppy_formats).enable_sound(true);
+ FLOPPY_CONNECTOR(config, "fdc:2", flpone_floppies, nullptr, spectrum_flpone_device::floppy_formats).enable_sound(true);
+ FLOPPY_CONNECTOR(config, "fdc:3", flpone_floppies, nullptr, spectrum_flpone_device::floppy_formats).enable_sound(true);
+
+ // parallel printer port
+ CENTRONICS(config, m_centronics, centronics_devices, "printer");
+ m_centronics->busy_handler().set(FUNC(spectrum_flpone_device::busy_w));
+
+ RS232_PORT(config, m_rs232, default_rs232_devices, nullptr);
+
+ // 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));
+}
+
+const tiny_rom_entry *spectrum_flpone_device::device_rom_region() const
+{
+ return ROM_NAME(flpone);
+}
+
+
+//**************************************************************************
+// LIVE DEVICE
+//**************************************************************************
+
+//-------------------------------------------------
+// spectrum_flpone_device - constructor
+//-------------------------------------------------
+
+spectrum_flpone_device::spectrum_flpone_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
+ : device_t(mconfig, SPECTRUM_FLPONE, tag, owner, clock)
+ , device_spectrum_expansion_interface(mconfig, *this)
+ , m_rom(*this, "rom")
+ , m_prom(*this, "prom")
+ , m_fdc(*this, "fdc")
+ , m_floppy(*this, "fdc:%u", 0)
+ , m_exp(*this, "exp")
+ , m_centronics(*this, "centronics")
+ , m_rs232(*this, "rs232")
+ , m_sw1(*this, "SW1")
+ , m_sw2(*this, "SW2")
+{
+}
+
+//-------------------------------------------------
+// device_start - device-specific startup
+//-------------------------------------------------
+
+void spectrum_flpone_device::device_start()
+{
+ memset(m_ram, 0, sizeof(m_ram));
+
+ save_item(NAME(m_romcs));
+ save_item(NAME(m_ram));
+ save_item(NAME(m_busy));
+ save_item(NAME(m_shifter));
+}
+
+//-------------------------------------------------
+// device_reset - device-specific reset
+//-------------------------------------------------
+
+void spectrum_flpone_device::device_reset()
+{
+ m_romcs = 0;
+ m_if1cs = 0;
+ m_busy = 1;
+ m_shifter = 0;
+}
+
+//**************************************************************************
+// IMPLEMENTATION
+//**************************************************************************
+
+bool spectrum_flpone_device::romcs()
+{
+ return m_romcs || m_exp->romcs();
+}
+
+void spectrum_flpone_device::post_opcode_fetch(offs_t offset)
+{
+ m_exp->post_opcode_fetch(offset);
+
+ if (!machine().side_effects_disabled() && m_sw1->read())
+ {
+ if (offset < 0x2000)
+ {
+ u8 data = m_prom->base()[offset];
+ m_romcs |= BIT(data, 4) ^ 1;
+ m_romcs &= BIT(data, 6);
+ if (m_sw2->read())
+ {
+ m_if1cs |= BIT(data, 7) ^ 1;
+ m_if1cs &= BIT(data, 5);
+ m_romcs &= !m_if1cs;
+ }
+ }
+ }
+}
+
+uint8_t spectrum_flpone_device::mreq_r(offs_t offset)
+{
+ u8 data = 0xff;
+
+ if (m_romcs)
+ {
+ switch (offset & 0xf000)
+ {
+ case 0x0000: case 0x1000:
+ data = m_rom->base()[offset];
+ break;
+ case 0x3000:
+ data = m_ram[offset & 0xfff];
+ break;
+ case 0x2000:
+ switch (offset & 0xc)
+ {
+ case 0: case 8:
+ data = m_fdc->read(offset & 3);
+ break;
+ case 4: // D5 - Centronics /BUSY / RS232 /DSR
+ data &= ~(m_busy << 5);
+ //data &= ~(m_rs232->dsr_r() << 5); // TODO findout how both of these combined at same bit
+ break;
+ case 0xc: // Centronics STROBE pulse
+ m_centronics->write_strobe(1);
+ m_centronics->write_strobe(0);
+ m_centronics->write_strobe(1);
+ break;
+ }
+ break;
+ }
+ }
+
+ if (m_exp->romcs())
+ data &= m_exp->mreq_r(offset);
+
+ return data;
+}
+
+void spectrum_flpone_device::mreq_w(offs_t offset, uint8_t data)
+{
+ if (m_romcs)
+ {
+ switch (offset & 0xf000)
+ {
+ case 0x3000:
+ m_ram[offset & 0xfff] = data;
+ break;
+ case 0x2000:
+ switch (offset & 0xc)
+ {
+ case 0: case 8:
+ m_fdc->write(offset & 3, data);
+ break;
+ case 4: // D7 - Centronics shifter data / RS232 TX
+ m_shifter = (m_shifter << 1) | BIT(data, 7);
+
+ m_centronics->write_data0(BIT(m_shifter, 0));
+ m_centronics->write_data1(BIT(m_shifter, 1));
+ m_centronics->write_data2(BIT(m_shifter, 2));
+ m_centronics->write_data3(BIT(m_shifter, 3));
+ m_centronics->write_data4(BIT(m_shifter, 4));
+ m_centronics->write_data5(BIT(m_shifter, 5));
+ m_centronics->write_data6(BIT(m_shifter, 6));
+ m_centronics->write_data7(BIT(m_shifter, 7));
+
+ m_rs232->write_txd(BIT(data, 7));
+ break;
+ case 0xc:
+ {
+ floppy_image_device* floppy = nullptr;
+ for (int i = 3; i >= 0; i--)
+ {
+ floppy_image_device* fl = m_floppy[i]->get_device();
+ if (fl)
+ {
+ fl->ss_w(BIT(data, 4));
+ fl->mon_w((BIT(data, 5) && BIT(data, i)) ? CLEAR_LINE : ASSERT_LINE);
+ if (BIT(data, i))
+ floppy = fl;
+ }
+ }
+ m_fdc->set_floppy(floppy);
+ }
+ break;
+ }
+ break;
+ }
+ }
+
+ if (m_exp->romcs())
+ m_exp->mreq_w(offset, data);
+}
diff --git a/src/devices/bus/spectrum/floppyone.h b/src/devices/bus/spectrum/floppyone.h
new file mode 100644
index 00000000000..e77fb61d5be
--- /dev/null
+++ b/src/devices/bus/spectrum/floppyone.h
@@ -0,0 +1,81 @@
+// license:BSD-3-Clause
+// copyright-holders:MetalliC
+/*********************************************************************
+
+ FloppyOne DOS Interface
+ (c) 1984/5 R.P.Gush
+
+*********************************************************************/
+#ifndef MAME_BUS_SPECTRUM_FLOPPYONE_H
+#define MAME_BUS_SPECTRUM_FLOPPYONE_H
+
+#include "exp.h"
+
+#include "bus/centronics/ctronics.h"
+#include "bus/rs232/rs232.h"
+#include "imagedev/floppy.h"
+#include "machine/wd_fdc.h"
+
+
+//**************************************************************************
+// TYPE DEFINITIONS
+//**************************************************************************
+
+class spectrum_flpone_device :
+ public device_t,
+ public device_spectrum_expansion_interface
+
+{
+public:
+ // construction/destruction
+ spectrum_flpone_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
+
+ static void floppy_formats(format_registration &fr);
+ DECLARE_INPUT_CHANGED_MEMBER(snapshot_button) { m_slot->nmi_w(newval ? ASSERT_LINE : CLEAR_LINE); }
+
+protected:
+ // device-level overrides
+ virtual void device_start() override ATTR_COLD;
+ virtual void device_reset() override ATTR_COLD;
+
+ // optional information overrides
+ virtual ioport_constructor device_input_ports() const override ATTR_COLD;
+
+ virtual void device_add_mconfig(machine_config &config) override ATTR_COLD;
+ virtual const tiny_rom_entry *device_rom_region() const override ATTR_COLD;
+
+ 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 bool romcs() override;
+
+ // passthru
+ virtual void pre_opcode_fetch(offs_t offset) override { m_exp->pre_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 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); }
+
+ void busy_w(int state) { m_busy = state; }
+
+ required_memory_region m_rom;
+ required_memory_region m_prom;
+ required_device<wd_fdc_device_base> m_fdc;
+ required_device_array<floppy_connector, 4> m_floppy;
+ required_device<spectrum_expansion_slot_device> m_exp;
+ required_device<centronics_device> m_centronics;
+ required_device<rs232_port_device> m_rs232;
+ required_ioport m_sw1;
+ required_ioport m_sw2;
+
+ bool m_romcs, m_if1cs;
+ u8 m_ram[0x1000];
+ int m_busy;
+ uint8_t m_shifter;
+};
+
+
+// device type definition
+DECLARE_DEVICE_TYPE(SPECTRUM_FLPONE, spectrum_flpone_device)
+
+#endif // MAME_BUS_SPECTRUM_FLOPPYONE_H
diff --git a/src/devices/bus/spectrum/fuller.cpp b/src/devices/bus/spectrum/fuller.cpp
index f44965e5a03..0346a806171 100644
--- a/src/devices/bus/spectrum/fuller.cpp
+++ b/src/devices/bus/spectrum/fuller.cpp
@@ -55,6 +55,7 @@ void spectrum_fuller_device::device_add_mconfig(machine_config &config)
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));
}
//**************************************************************************
@@ -88,32 +89,6 @@ void spectrum_fuller_device::device_start()
// IMPLEMENTATION
//**************************************************************************
-READ_LINE_MEMBER(spectrum_fuller_device::romcs)
-{
- return m_exp->romcs();
-}
-
-void spectrum_fuller_device::pre_opcode_fetch(offs_t offset)
-{
- m_exp->pre_opcode_fetch(offset);
-}
-
-uint8_t spectrum_fuller_device::mreq_r(offs_t offset)
-{
- uint8_t data = 0xff;
-
- if (m_exp->romcs())
- data &= m_exp->mreq_r(offset);
-
- return data;
-}
-
-void spectrum_fuller_device::mreq_w(offs_t offset, uint8_t data)
-{
- if (m_exp->romcs())
- m_exp->mreq_w(offset, data);
-}
-
uint8_t spectrum_fuller_device::iorq_r(offs_t offset)
{
uint8_t data = m_exp->iorq_r(offset);
@@ -121,10 +96,10 @@ uint8_t spectrum_fuller_device::iorq_r(offs_t offset)
switch (offset & 0xff)
{
case 0x5f:
- data &= m_psg->data_r();
+ data = m_psg->data_r();
break;
case 0x7f:
- data &= m_joy->read() | (0xff ^ 0x8f);
+ data = m_joy->read() | (0xff ^ 0x8f);
break;
}
return data;
diff --git a/src/devices/bus/spectrum/fuller.h b/src/devices/bus/spectrum/fuller.h
index cc6a4c8fec0..dc60cc3631e 100644
--- a/src/devices/bus/spectrum/fuller.h
+++ b/src/devices/bus/spectrum/fuller.h
@@ -31,18 +31,23 @@ public:
protected:
// device-level overrides
- virtual void device_start() override;
+ virtual void device_start() override ATTR_COLD;
// optional information overrides
- virtual void device_add_mconfig(machine_config &config) override;
- virtual ioport_constructor device_input_ports() const override;
+ virtual void device_add_mconfig(machine_config &config) override ATTR_COLD;
+ virtual ioport_constructor device_input_ports() const override ATTR_COLD;
- 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 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;
+
+ // 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 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 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 bbdf324b2e0..f80a02723ef 100644
--- a/src/devices/bus/spectrum/intf1.cpp
+++ b/src/devices/bus/spectrum/intf1.cpp
@@ -12,6 +12,7 @@
#include "emu.h"
#include "intf1.h"
+#include "softlist_dev.h"
//**************************************************************************
@@ -53,6 +54,7 @@ void spectrum_intf1_device::device_add_mconfig(machine_config &config)
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));
SOFTWARE_LIST(config, "microdrive_list").set_original("spectrum_microdrive");
}
@@ -103,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
@@ -156,12 +158,6 @@ uint8_t spectrum_intf1_device::mreq_r(offs_t offset)
return data;
}
-void spectrum_intf1_device::mreq_w(offs_t offset, uint8_t data)
-{
- if (m_exp->romcs())
- m_exp->mreq_w(offset, data);
-}
-
uint8_t spectrum_intf1_device::iorq_r(offs_t offset)
{
uint8_t data = 0xff;
diff --git a/src/devices/bus/spectrum/intf1.h b/src/devices/bus/spectrum/intf1.h
index b128c42ea92..59ffaf95838 100644
--- a/src/devices/bus/spectrum/intf1.h
+++ b/src/devices/bus/spectrum/intf1.h
@@ -30,20 +30,24 @@ public:
static constexpr feature_type unemulated_features() { return feature::DISK | feature::LAN; }
protected:
- virtual void device_start() override;
- virtual void device_reset() override;
+ virtual void device_start() override ATTR_COLD;
+ virtual void device_reset() override ATTR_COLD;
// optional information overrides
- virtual void device_add_mconfig(machine_config &config) override;
- virtual const tiny_rom_entry *device_rom_region() const override;
+ virtual void device_add_mconfig(machine_config &config) override ATTR_COLD;
+ virtual const tiny_rom_entry *device_rom_region() const override ATTR_COLD;
virtual void pre_opcode_fetch(offs_t offset) override;
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 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); }
+ 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;
@@ -52,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 ab9caf68f8c..514a7e42151 100644
--- a/src/devices/bus/spectrum/intf2.cpp
+++ b/src/devices/bus/spectrum/intf2.cpp
@@ -12,6 +12,7 @@
#include "emu.h"
#include "intf2.h"
+#include "softlist_dev.h"
//**************************************************************************
@@ -58,7 +59,7 @@ void spectrum_intf2_device::device_add_mconfig(machine_config &config)
{
/* cartridge */
GENERIC_CARTSLOT(config, m_cart, generic_plain_slot, "spectrum_cart", "bin,rom");
- m_cart->set_device_load(FUNC(spectrum_intf2_device::cart_load), this);
+ m_cart->set_device_load(FUNC(spectrum_intf2_device::cart_load));
SOFTWARE_LIST(config, "cart_list").set_original("spectrum_cart");
}
@@ -95,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_UNSPECIFIED, "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;
@@ -127,7 +125,7 @@ uint8_t spectrum_intf2_device::mreq_r(offs_t offset)
uint8_t spectrum_intf2_device::iorq_r(offs_t offset)
{
- uint8_t data = 0xff;
+ uint8_t data = offset & 1 ? m_slot->fb_r() : 0xff;
switch (offset & 0xff)
{
diff --git a/src/devices/bus/spectrum/intf2.h b/src/devices/bus/spectrum/intf2.h
index 4faecbae93a..5fb9adcb217 100644
--- a/src/devices/bus/spectrum/intf2.h
+++ b/src/devices/bus/spectrum/intf2.h
@@ -28,18 +28,18 @@ public:
spectrum_intf2_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
protected:
- virtual void device_start() override;
+ virtual void device_start() override ATTR_COLD;
// optional information overrides
- virtual void device_add_mconfig(machine_config &config) override;
- virtual ioport_constructor device_input_ports() const override;
+ virtual void device_add_mconfig(machine_config &config) override ATTR_COLD;
+ virtual ioport_constructor device_input_ports() const override ATTR_COLD;
- 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
new file mode 100644
index 00000000000..059403959fa
--- /dev/null
+++ b/src/devices/bus/spectrum/kempdisc.cpp
@@ -0,0 +1,282 @@
+// license:BSD-3-Clause
+// copyright-holders:MetalliC
+/*********************************************************************
+
+ Kempston Disc Interface
+ (c) Abbeydale Designers ltd 1985
+
+ Known clones:
+ Sandy Disco Vers. 3
+
+ Few useful K-DOS commands (should be preceded with PRINT #4: ):
+ CAT - disc file list
+ LOAD "filename" - load and run program
+ COPY - tape to disc transfer utility
+ FORMAT "discname": PRINT drive#, tracks#, sides#, steprate - format disc
+
+ Manual https://archive.org/download/World_of_Spectrum_June_2017_Mirror/World%20of%20Spectrum%20June%202017%20Mirror.zip/World%20of%20Spectrum%20June%202017%20Mirror/sinclair/hardware-info/k/KempstonDiscInterface_Manual.pdf
+
+ Notes/TODO:
+ - schematics is missing, actual I/O ports decode might be not right
+ - find out port 0xDF 3 MSB bits wiring, probably FDC /DDEN, /MR
+ - implement onboard Kempston Centronics E interace and joystick port
+ - add more docs/information
+
+*********************************************************************
+
+ Watford SP-DOS Interface
+ (c) Abbeydale Designers ltd 1984
+
+ Earlier version of Kempston Disc, uses 2Kbyte ROM with small boot loader, same FDC ports but slightly different paging.
+ Require "System disk" with DOS to function, which is not dumped / missing at the moment.
+
+*********************************************************************/
+
+#include "emu.h"
+#include "kempdisc.h"
+
+
+/***************************************************************************
+ DEVICE DEFINITIONS
+***************************************************************************/
+
+DEFINE_DEVICE_TYPE(SPECTRUM_KEMPDISC, spectrum_kempdisc_device, "spectrum_kempdisc", "Kempston Disc Interface")
+DEFINE_DEVICE_TYPE(SPECTRUM_SPDOS, spectrum_spdos_device, "spectrum_spdos", "Watford SP-DOS Interface")
+
+
+//-------------------------------------------------
+// SLOT_INTERFACE( floppies )
+//-------------------------------------------------
+
+static void kempdisc_floppies(device_slot_interface &device)
+{
+ device.option_add("525dd", FLOPPY_525_DD);
+ device.option_add("525qd", FLOPPY_525_QD);
+ device.option_add("35dd", FLOPPY_35_DD);
+ device.option_add("3dsdd", FLOPPY_3_DSDD);
+}
+
+//-------------------------------------------------
+// ROM( kempdisc )
+//-------------------------------------------------
+
+ROM_START(kempdisc)
+ ROM_REGION(0x2000, "rom", 0)
+ ROM_DEFAULT_BIOS("kd21")
+
+ // original
+ ROM_SYSTEM_BIOS(0, "kd20", "K-DOS v2.0")
+ ROMX_LOAD("kd20.rom", 0x0000, 0x2000, CRC(244816a7) SHA1(b08e0e30f1db4f57d38b112be0115256528c6621), ROM_BIOS(0))
+ ROM_SYSTEM_BIOS(1, "kd21", "K-DOS v2.1")
+ ROMX_LOAD("kd21.rom", 0x0000, 0x2000, CRC(3a0705eb) SHA1(adebc46c1b6718eaed7e2844506011787117cb05), ROM_BIOS(1))
+ //ROMX_LOAD("kd21.rom", 0x0000, 0x2000, CRC(d18fb812) SHA1(b3e00bc4111ef6311789159024fb4cd25c32a72f), ROM_BIOS(1)) // bad dump
+ ROM_SYSTEM_BIOS(2, "kd21it", "K-DOS v2.1 Italian") // copyrights and texts changed and translated
+ ROMX_LOAD("kd21it.rom", 0x0000, 0x2000, CRC(f8ccdf8a) SHA1(4a75fb4951d74e254c230d56b5566c924b3c38f6), ROM_BIOS(2))
+ROM_END
+
+ROM_START(spdos)
+ ROM_REGION(0x0800, "rom", 0)
+ ROM_LOAD("spdos.rom", 0x0000, 0x0800, CRC(87b954a3) SHA1(bb0706cf1538da8acd12b8c9cd2cd75ca689ec44))
+ROM_END
+
+//-------------------------------------------------
+// device_add_mconfig - add device configuration
+//-------------------------------------------------
+
+void spectrum_kempdisc_device::device_add_mconfig(machine_config &config)
+{
+ WD1770(config, m_fdc, 16_MHz_XTAL / 2);
+
+ FLOPPY_CONNECTOR(config, "fdc:0", kempdisc_floppies, "525qd", floppy_image_device::default_mfm_floppy_formats).enable_sound(true);
+ FLOPPY_CONNECTOR(config, "fdc:1", kempdisc_floppies, "525qd", floppy_image_device::default_mfm_floppy_formats).enable_sound(true);
+ FLOPPY_CONNECTOR(config, "fdc:2", kempdisc_floppies, nullptr, floppy_image_device::default_mfm_floppy_formats).enable_sound(true);
+ FLOPPY_CONNECTOR(config, "fdc:3", kempdisc_floppies, nullptr, floppy_image_device::default_mfm_floppy_formats).enable_sound(true);
+
+ // 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));
+}
+
+const tiny_rom_entry *spectrum_kempdisc_device::device_rom_region() const
+{
+ return ROM_NAME(kempdisc);
+}
+
+const tiny_rom_entry *spectrum_spdos_device::device_rom_region() const
+{
+ return ROM_NAME(spdos);
+}
+
+
+//**************************************************************************
+// LIVE DEVICE
+//**************************************************************************
+
+//-------------------------------------------------
+// spectrum_kempdisc_device - constructor
+//-------------------------------------------------
+
+spectrum_kempdisc_device::spectrum_kempdisc_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_spectrum_expansion_interface(mconfig, *this)
+ , m_rom(*this, "rom")
+ , m_fdc(*this, "fdc")
+ , m_floppy(*this, "fdc:%u", 0)
+ , m_exp(*this, "exp")
+// , m_control(0)
+{
+}
+
+spectrum_kempdisc_device::spectrum_kempdisc_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
+ : spectrum_kempdisc_device(mconfig, SPECTRUM_KEMPDISC, tag, owner, clock)
+{
+}
+
+spectrum_spdos_device::spectrum_spdos_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
+ : spectrum_kempdisc_device(mconfig, SPECTRUM_SPDOS, tag, owner, clock)
+{
+}
+
+//-------------------------------------------------
+// device_start - device-specific startup
+//-------------------------------------------------
+
+void spectrum_kempdisc_device::device_start()
+{
+ save_item(NAME(m_romcs));
+// save_item(NAME(m_control));
+}
+
+//-------------------------------------------------
+// device_reset - device-specific reset
+//-------------------------------------------------
+
+void spectrum_kempdisc_device::device_reset()
+{
+ m_romcs = 1;
+}
+
+//**************************************************************************
+// IMPLEMENTATION
+//**************************************************************************
+
+bool spectrum_kempdisc_device::romcs()
+{
+ return m_romcs || m_exp->romcs();
+}
+
+
+uint8_t spectrum_kempdisc_device::iorq_r(offs_t offset)
+{
+ uint8_t data = m_exp->iorq_r(offset);
+
+ switch (offset & 0xff)
+ {
+ case 0xe5: case 0xe7: case 0xed: case 0xef:
+ data = m_fdc->read(BIT(offset, 1) | (BIT(offset, 3) << 1));
+ break;
+ }
+
+ return data;
+}
+
+void spectrum_kempdisc_device::iorq_w(offs_t offset, uint8_t data)
+{
+ switch (offset & 0xff)
+ {
+ case 0xe5: case 0xe7: case 0xed: case 0xef:
+ m_fdc->write(BIT(offset, 1) | (BIT(offset, 3) << 1), data);
+ break;
+ case 0xdf:
+ {
+ floppy_image_device* floppy = nullptr;
+ for (int i = 1; i < 5; i++)
+ if (BIT(data, i))
+ {
+ floppy = m_floppy[i - 1]->get_device();
+ break;
+ }
+
+// m_control = data;
+ m_fdc->set_floppy(floppy);
+ if (floppy) floppy->ss_w(BIT(data, 0));
+ if (data & 0xe0)
+ logerror("port DF unhandled %02X\n", data);
+ }
+ break;
+ case 0xfd:
+ m_romcs = 1;
+ break;
+ case 0xd7:
+ m_romcs = 0;
+ break;
+ }
+
+ m_exp->iorq_w(offset, data);
+}
+
+uint8_t spectrum_kempdisc_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;
+}
+
+
+void spectrum_spdos_device::iorq_w(offs_t offset, uint8_t data)
+{
+ switch (offset & 0xff)
+ {
+ case 0xe5: case 0xe7: case 0xed: case 0xef:
+ m_fdc->write(BIT(offset, 1) | (BIT(offset, 3) << 1), data);
+ break;
+ case 0xdf:
+ {
+ floppy_image_device* floppy = nullptr;
+ for (int i = 1; i < 5; i++)
+ if (BIT(data, i))
+ {
+ floppy = m_floppy[i - 1]->get_device();
+ break;
+ }
+
+// m_control = data;
+ m_fdc->set_floppy(floppy);
+ if (floppy) floppy->ss_w(BIT(data, 0));
+ if (data & 0xe0)
+ logerror("port DF unhandled %02X\n", data);
+ m_romcs = 0;
+ }
+ break;
+ // below probably is wrong/different for this device
+ case 0xfd:
+ m_romcs = 1;
+ break;
+ case 0xd7:
+ m_romcs = 0;
+ break;
+ }
+
+ m_exp->iorq_w(offset, data);
+}
+
+uint8_t spectrum_spdos_device::mreq_r(offs_t offset)
+{
+ uint8_t data = 0xff;
+
+ if (m_romcs)
+ data = m_rom->base()[offset & 0x7ff];
+
+ if (m_exp->romcs())
+ data &= m_exp->mreq_r(offset);
+
+ return data;
+}
diff --git a/src/devices/bus/spectrum/kempdisc.h b/src/devices/bus/spectrum/kempdisc.h
new file mode 100644
index 00000000000..7f5ad23f593
--- /dev/null
+++ b/src/devices/bus/spectrum/kempdisc.h
@@ -0,0 +1,83 @@
+// license:BSD-3-Clause
+// copyright-holders:MetalliC
+/*********************************************************************
+
+ Kempston Disc Interface
+
+*********************************************************************/
+#ifndef MAME_BUS_SPECTRUM_KEMPDISC_H
+#define MAME_BUS_SPECTRUM_KEMPDISC_H
+
+#include "exp.h"
+#include "softlist.h"
+#include "imagedev/floppy.h"
+#include "machine/wd_fdc.h"
+
+//**************************************************************************
+// TYPE DEFINITIONS
+//**************************************************************************
+
+class spectrum_kempdisc_device :
+ public device_t,
+ public device_spectrum_expansion_interface
+
+{
+public:
+ // construction/destruction
+ spectrum_kempdisc_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
+
+ static void floppy_formats(format_registration &fr);
+
+protected:
+ spectrum_kempdisc_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 ATTR_COLD;
+ virtual void device_reset() override ATTR_COLD;
+
+ // optional information overrides
+ virtual void device_add_mconfig(machine_config &config) override ATTR_COLD;
+ virtual const tiny_rom_entry *device_rom_region() const override ATTR_COLD;
+
+ 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); }
+
+ required_memory_region m_rom;
+ required_device<wd_fdc_device_base> m_fdc;
+ required_device_array<floppy_connector, 4> m_floppy;
+ required_device<spectrum_expansion_slot_device> m_exp;
+
+ bool m_romcs;
+// u8 m_control;
+};
+
+class spectrum_spdos_device :
+ public spectrum_kempdisc_device
+{
+public:
+ // construction/destruction
+ spectrum_spdos_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
+
+protected:
+ // optional information overrides
+ virtual const tiny_rom_entry *device_rom_region() const override ATTR_COLD;
+
+ virtual void iorq_w(offs_t offset, uint8_t data) override;
+ virtual uint8_t mreq_r(offs_t offset) override;
+};
+
+
+// device type definition
+DECLARE_DEVICE_TYPE(SPECTRUM_KEMPDISC, spectrum_kempdisc_device)
+DECLARE_DEVICE_TYPE(SPECTRUM_SPDOS, spectrum_spdos_device)
+
+
+#endif // MAME_BUS_SPECTRUM_KEMPDISC_H
diff --git a/src/devices/bus/spectrum/kempjoy.cpp b/src/devices/bus/spectrum/kempjoy.cpp
index a433d615e8c..4dee6eabba0 100644
--- a/src/devices/bus/spectrum/kempjoy.cpp
+++ b/src/devices/bus/spectrum/kempjoy.cpp
@@ -71,9 +71,9 @@ void spectrum_kempjoy_device::device_start()
uint8_t spectrum_kempjoy_device::iorq_r(offs_t offset)
{
- uint8_t data = 0xff;
+ uint8_t data = offset & 1 ? m_slot->fb_r() : 0xff;
- if (offset == 0x1f)
+ if ((offset & 0xe0) == 0) // 000- ---- uses 0x1f
{
data = m_joy->read() & 0x1f;
}
diff --git a/src/devices/bus/spectrum/kempjoy.h b/src/devices/bus/spectrum/kempjoy.h
index 466dceb7517..0f7557b3911 100644
--- a/src/devices/bus/spectrum/kempjoy.h
+++ b/src/devices/bus/spectrum/kempjoy.h
@@ -30,10 +30,10 @@ public:
protected:
// device-level overrides
- virtual void device_start() override;
+ virtual void device_start() override ATTR_COLD;
// optional information overrides
- virtual ioport_constructor device_input_ports() const override;
+ virtual ioport_constructor device_input_ports() const override ATTR_COLD;
virtual uint8_t iorq_r(offs_t offset) override;
diff --git a/src/devices/bus/spectrum/logitek.cpp b/src/devices/bus/spectrum/logitek.cpp
new file mode 100644
index 00000000000..2224a54bbc3
--- /dev/null
+++ b/src/devices/bus/spectrum/logitek.cpp
@@ -0,0 +1,216 @@
+// license:BSD-3-Clause
+// copyright-holders:MetalliC
+/*********************************************************************
+
+ Proceed 1 - Commodore IEC Bus and printer interface
+ (c) 1984 Logitek (Germany)
+
+ Allows to connect and use Commodore 1541 disk drive.
+ Components: Z8420 PIO, 8K ROM, 256x4 PROM, NMI button.
+
+ Photos and manual https://k1.spdns.de/Vintage/Sinclair/82/Peripherals/Disc%20Interfaces/Logitek%20Proceed%201%20C64%20Disc%20Interface/
+
+ Notes / TODOs:
+ - require "quantum perfect" host machine config, otherwise floppy drive access doesn't work with "Device timeout" error message.
+
+ - ROM paging performed by undumped PROM, current logic might be innacurate.
+ wiring: A0-A5 - Z80 A8-A13, A6 - PIO PB7, A7 - nc, /CE1 - A14, /CE2 - A15,
+ Q1 - ROM A11, Q2 - ROM A10, Q3 - ROM /CE, Q4 - /ROMCS
+
+*********************************************************************/
+
+#include "emu.h"
+#include "logitek.h"
+
+
+/***************************************************************************
+ DEVICE DEFINITIONS
+***************************************************************************/
+
+DEFINE_DEVICE_TYPE(SPECTRUM_PROCEED, spectrum_proceed_device, "spectrum_proceed", "Logitek Proceed 1 Interface")
+
+
+//-------------------------------------------------
+// INPUT_PORTS
+//-------------------------------------------------
+
+INPUT_PORTS_START(proceed)
+ PORT_START("BUTTON")
+ PORT_BIT(0x01, IP_ACTIVE_HIGH, IPT_BUTTON1) PORT_NAME("NMI Button") PORT_CODE(KEYCODE_MINUS_PAD) PORT_CHANGED_MEMBER(DEVICE_SELF, FUNC(spectrum_proceed_device::nmi_button), 0)
+INPUT_PORTS_END
+
+//-------------------------------------------------
+// input_ports - device-specific input ports
+//-------------------------------------------------
+
+ioport_constructor spectrum_proceed_device::device_input_ports() const
+{
+ return INPUT_PORTS_NAME(proceed);
+}
+
+//-------------------------------------------------
+// ROM( proceed )
+//-------------------------------------------------
+
+ROM_START(proceed)
+ ROM_REGION(0x2000, "rom", 0)
+ ROM_DEFAULT_BIOS("ldos21")
+
+ ROM_SYSTEM_BIOS(0, "ldos21", "LDOS v2.1")
+ ROMX_LOAD("ldos_v21.bin", 0x0000, 0x2000, CRC(a7c47bac) SHA1(c999b0e4f5537405ed56c4c96beca5e7f5eb2b1e), ROM_BIOS(0))
+ROM_END
+
+//-------------------------------------------------
+// device_add_mconfig - add device configuration
+//-------------------------------------------------
+
+void spectrum_proceed_device::device_add_mconfig(machine_config &config)
+{
+ Z80PIO(config, m_z80pio, 3500000);
+ m_z80pio->out_pa_callback().set(FUNC(spectrum_proceed_device::pioa_w));
+ m_z80pio->in_pb_callback().set(FUNC(spectrum_proceed_device::piob_r));
+ m_z80pio->out_pb_callback().set(FUNC(spectrum_proceed_device::piob_w));
+ m_z80pio->out_int_callback().set(DEVICE_SELF_OWNER, FUNC(spectrum_expansion_slot_device::irq_w));
+
+ cbm_iec_slot_device::add(config, m_iec, "c1541");
+
+ CENTRONICS(config, m_centronics, centronics_devices, "printer");
+ m_centronics->busy_handler().set(m_z80pio, FUNC(z80pio_device::pb0_w));
+}
+
+const tiny_rom_entry *spectrum_proceed_device::device_rom_region() const
+{
+ return ROM_NAME(proceed);
+}
+
+
+//**************************************************************************
+// LIVE DEVICE
+//**************************************************************************
+
+//-------------------------------------------------
+// spectrum_proceed_device - constructor
+//-------------------------------------------------
+
+spectrum_proceed_device::spectrum_proceed_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
+ : device_t(mconfig, SPECTRUM_PROCEED, tag, owner, clock)
+ , device_spectrum_expansion_interface(mconfig, *this)
+ , m_rom(*this, "rom")
+ , m_z80pio(*this, "z80pio")
+ , m_iec(*this, "iec_bus")
+ , m_centronics(*this, "centronics")
+{
+}
+
+//-------------------------------------------------
+// device_start - device-specific startup
+//-------------------------------------------------
+
+void spectrum_proceed_device::device_start()
+{
+ save_item(NAME(m_romcs));
+ save_item(NAME(m_romen));
+}
+
+//-------------------------------------------------
+// device_reset - device-specific reset
+//-------------------------------------------------
+
+void spectrum_proceed_device::device_reset()
+{
+ m_romcs = 0;
+ m_romen = 0;
+ m_iec->reset();
+}
+
+//**************************************************************************
+// IMPLEMENTATION
+//**************************************************************************
+
+bool spectrum_proceed_device::romcs()
+{
+ return m_romcs;
+}
+
+void spectrum_proceed_device::fetch(offs_t offset)
+{
+ switch (offset >> 8)
+ {
+ // always override
+ case 0x00:
+ case 0x0e:
+ case 0x39: case 0x3a: case 0x3b: case 0x3c:
+ m_romcs = 1;
+ break;
+ case 0x1b:
+ m_romcs = 1;
+ offset |= 0x0400; // 1Bxx -> 1Fxx
+ break;
+ // override only if PIO PB7 is 0
+ case 0x01: case 0x02: case 0x03: case 0x04: case 0x05: case 0x06: case 0x07: case 0x08: case 0x09: case 0x0a: case 0x0b: case 0x0c: case 0x0d:
+ case 0x0f: case 0x10: case 0x11: case 0x12: case 0x13: case 0x14: case 0x15: case 0x16: case 0x17: case 0x18:
+ case 0x1d: case 0x1e:
+ m_romcs = m_romen;
+ break;
+
+ default:
+ m_romcs = 0;
+ }
+}
+
+uint8_t spectrum_proceed_device::mreq_r(offs_t offset)
+{
+ u8 data = 0xff;
+
+ if (m_romcs)
+ data = m_rom->base()[offset & 0x1fff];
+
+ return data;
+}
+
+uint8_t spectrum_proceed_device::iorq_r(offs_t offset)
+{
+ uint8_t data = offset & 1 ? m_slot->fb_r() : 0xff;
+
+ if (!BIT(offset, 5))
+ data = m_z80pio->read((offset >> 6) & 3);
+
+ return data;
+}
+
+void spectrum_proceed_device::iorq_w(offs_t offset, uint8_t data)
+{
+ if (!BIT(offset, 5))
+ m_z80pio->write((offset >> 6) & 3, data);
+}
+
+void spectrum_proceed_device::pioa_w(uint8_t data)
+{
+ m_centronics->write_data0(BIT(data, 0));
+ m_centronics->write_data1(BIT(data, 1));
+ m_centronics->write_data2(BIT(data, 2));
+ m_centronics->write_data3(BIT(data, 3));
+ m_centronics->write_data4(BIT(data, 4));
+ m_centronics->write_data5(BIT(data, 5));
+ m_centronics->write_data6(BIT(data, 6));
+ m_centronics->write_data7(BIT(data, 7));
+}
+
+uint8_t spectrum_proceed_device::piob_r()
+{
+ u8 data = 0;
+
+ data |= m_iec->clk_r() << 3;
+ data |= m_iec->data_r() << 2;
+
+ return data;
+}
+
+void spectrum_proceed_device::piob_w(uint8_t data)
+{
+ m_romen = !BIT(data, 7);
+ m_iec->host_atn_w(BIT(data, 6));
+ m_iec->host_clk_w(BIT(data, 5));
+ m_iec->host_data_w(BIT(data, 4));
+ m_centronics->write_strobe(BIT(data, 1));
+}
diff --git a/src/devices/bus/spectrum/logitek.h b/src/devices/bus/spectrum/logitek.h
new file mode 100644
index 00000000000..71ab217f821
--- /dev/null
+++ b/src/devices/bus/spectrum/logitek.h
@@ -0,0 +1,73 @@
+// license:BSD-3-Clause
+// copyright-holders:MetalliC
+/*********************************************************************
+
+ Proceed 1 Interface
+ (c) 1984 Logitek
+
+*********************************************************************/
+#ifndef MAME_BUS_SPECTRUM_LOGITEK_H
+#define MAME_BUS_SPECTRUM_LOGITEK_H
+
+#include "exp.h"
+#include "softlist.h"
+#include "machine/z80pio.h"
+#include "bus/cbmiec/cbmiec.h"
+#include "bus/centronics/ctronics.h"
+
+//**************************************************************************
+// TYPE DEFINITIONS
+//**************************************************************************
+
+class spectrum_proceed_device :
+ public device_t,
+ public device_spectrum_expansion_interface
+
+{
+public:
+ // construction/destruction
+ spectrum_proceed_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
+
+ static constexpr feature_type unemulated_features() { return feature::DISK; }
+
+ DECLARE_INPUT_CHANGED_MEMBER(nmi_button) { m_slot->nmi_w(newval ? ASSERT_LINE : CLEAR_LINE); }
+
+protected:
+ // device-level overrides
+ virtual void device_start() override ATTR_COLD;
+ virtual void device_reset() override ATTR_COLD;
+
+ // optional information overrides
+ virtual ioport_constructor device_input_ports() const override ATTR_COLD;
+
+ virtual void device_add_mconfig(machine_config &config) override ATTR_COLD;
+ virtual const tiny_rom_entry *device_rom_region() const override ATTR_COLD;
+
+ void fetch(offs_t offset);
+
+ virtual void pre_opcode_fetch(offs_t offset) override { fetch(offset); }
+ virtual void pre_data_fetch(offs_t offset) override { fetch(offset); }
+ 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;
+
+ required_memory_region m_rom;
+ required_device<z80pio_device> m_z80pio;
+ required_device<cbm_iec_device> m_iec;
+ required_device<centronics_device> m_centronics;
+
+ void pioa_w(uint8_t data);
+ void piob_w(uint8_t data);
+ uint8_t piob_r();
+
+ bool m_romcs;
+ int m_romen;
+};
+
+
+// device type definition
+DECLARE_DEVICE_TYPE(SPECTRUM_PROCEED, spectrum_proceed_device)
+
+
+#endif // MAME_BUS_SPECTRUM_LOGITEK_H
diff --git a/src/devices/bus/spectrum/lprint.cpp b/src/devices/bus/spectrum/lprint.cpp
new file mode 100644
index 00000000000..92b1e8d533e
--- /dev/null
+++ b/src/devices/bus/spectrum/lprint.cpp
@@ -0,0 +1,522 @@
+// license:BSD-3-Clause
+// copyright-holders:MetalliC
+/*********************************************************************
+
+ Common printer interfaces
+
+ ZX Lprint
+ (c) 1983 Euroelectronics (UK)
+
+ ZX Lprint III
+ (c) 1984 Euroelectronics (UK)
+ Centronics and RS232 interface, most common printer interface for ZX-Spectrum.
+
+ Hilderbay Interface (c) 1983 Hilderbay Ltd (UK)
+ AKA
+ Kempston Centronics S Interface (c) 1983 Kempston Micro Electronics Ltd (UK)
+ ROM-less device, require printer driver to be loaded from tape.
+
+ Kempston Centronics E Interface
+ (c) 1984 Kempston Micro Electronics Ltd (UK)
+
+ Notes/TODOs:
+ - add information and docs
+
+*********************************************************************/
+
+#include "emu.h"
+#include "lprint.h"
+#include <algorithm>
+
+
+/***************************************************************************
+ DEVICE DEFINITIONS
+***************************************************************************/
+
+DEFINE_DEVICE_TYPE(SPECTRUM_LPRINT, spectrum_lprint_device, "spectrum_lprint", "ZX Lprint")
+DEFINE_DEVICE_TYPE(SPECTRUM_LPRINT3, spectrum_lprint3_device, "spectrum_lprint3", "ZX Lprint III")
+DEFINE_DEVICE_TYPE(SPECTRUM_KEMPCENTRS, spectrum_kempcentrs_device, "spectrum_kempcentrs", "Hilderbay / Kempston Centronics S")
+DEFINE_DEVICE_TYPE(SPECTRUM_KEMPCENTREF, spectrum_kempcentre_device, "spectrum_kempcentref", "Kempston Centronics E (flat)")
+DEFINE_DEVICE_TYPE(SPECTRUM_KEMPCENTREU, spectrum_kempcentreu_device, "spectrum_kempcentreu", "Kempston Centronics E (upright)")
+
+//-------------------------------------------------
+// ROMs
+//-------------------------------------------------
+
+ROM_START(lprint)
+ ROM_REGION(0x800, "rom", 0)
+ ROM_LOAD("lprint.rom", 0x0000, 0x0800, CRC(3c3483e5) SHA1(3e4c7ecd8c3eb011cdf75eb23faf8d8ea8329757)) // permanently overlay 0x0800-0x0fff ROM area
+ROM_END
+
+ROM_START(lprint3)
+ ROM_REGION(0x800, "rom", 0)
+ ROM_DEFAULT_BIOS("v2")
+
+ // original
+ ROM_SYSTEM_BIOS(0, "v1", "v1.0")
+ ROMX_LOAD("v10.rom", 0x0000, 0x0800, CRC(a5014f40) SHA1(fe823a8b87a8bdacb14aac848bc7fe946f76faae), ROM_BIOS(0))
+ ROM_SYSTEM_BIOS(1, "v2", "v2.0")
+ ROMX_LOAD("v20.rom", 0x0000, 0x0800, CRC(b8f9a58d) SHA1(4966664badbed44ddb1c1a2ca01bdef60f0a30f8), ROM_BIOS(1))
+
+ // clones
+ ROM_SYSTEM_BIOS(2, "kp", "Sandy") // from Sandy Disco V3 (Kempston Disc clone) lower PCB, also have joystick port and passthru connector
+ ROMX_LOAD("sandy.rom", 0x0000, 0x0800, CRC(77e752f2) SHA1(11f44c5e743a413e8bc0d07c4249f36d2c0a172a), ROM_BIOS(2))
+ ROM_SYSTEM_BIOS(3, "rus", "Art East Computers (RU)") // added support for popular Soviet and Eastern Bloc made printers
+ ROMX_LOAD("himak.rom", 0x0000, 0x0800, CRC(b1f15976) SHA1(d9c0297c05e8092fb7e0198f4172d3d4e6ed252c), ROM_BIOS(3))
+ROM_END
+
+ROM_START(kempcentref)
+ ROM_REGION(0x800, "rom", 0)
+ ROM_LOAD("kemp-e.rom", 0x0000, 0x0800, CRC(a58b1e97) SHA1(b26e9f720a215019b8710a4a094d6fde6ecae5fd))
+ROM_END
+
+ROM_START(kempcentreu)
+ ROM_REGION(0x800, "rom", 0)
+ ROM_LOAD("7f.rom", 0x0000, 0x0800, CRC(b67a416d) SHA1(6d0772e81cfd9bc994b1c91d4e01b45e0fc0d3d3)) // scrambled
+ROM_END
+
+//-------------------------------------------------
+// device_add_mconfig - add device configuration
+//-------------------------------------------------
+
+void spectrum_lprint_device::device_add_mconfig(machine_config &config)
+{
+ CENTRONICS(config, m_centronics, centronics_devices, "printer");
+ m_centronics->busy_handler().set(FUNC(spectrum_lprint_device::busy_w));
+}
+
+void spectrum_lprint3_device::device_add_mconfig(machine_config &config)
+{
+ CENTRONICS(config, m_centronics, centronics_devices, "printer");
+ m_centronics->busy_handler().set(FUNC(spectrum_lprint3_device::busy_w));
+
+ RS232_PORT(config, m_rs232, default_rs232_devices, nullptr);
+
+ // passthru
+ // this is not really accurate, original ZX-Lprint boards had no passthru connector, but only some of clones
+ // TODO: populate expansion port only for devices which really had it
+ 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));
+}
+
+void spectrum_kempcentrs_device::device_add_mconfig(machine_config &config)
+{
+ CENTRONICS(config, m_centronics, centronics_devices, "printer");
+ m_centronics->busy_handler().set(FUNC(spectrum_kempcentrs_device::busy_w));
+}
+
+void spectrum_kempcentre_device::device_add_mconfig(machine_config &config)
+{
+ CENTRONICS(config, m_centronics, centronics_devices, "printer");
+ m_centronics->busy_handler().set(FUNC(spectrum_kempcentre_device::busy_w));
+}
+
+const tiny_rom_entry *spectrum_lprint_device::device_rom_region() const
+{
+ return ROM_NAME(lprint);
+}
+
+const tiny_rom_entry *spectrum_lprint3_device::device_rom_region() const
+{
+ return ROM_NAME(lprint3);
+}
+
+const tiny_rom_entry *spectrum_kempcentre_device::device_rom_region() const
+{
+ return ROM_NAME(kempcentref);
+}
+
+const tiny_rom_entry *spectrum_kempcentreu_device::device_rom_region() const
+{
+ return ROM_NAME(kempcentreu);
+}
+
+
+//**************************************************************************
+// LIVE DEVICE
+//**************************************************************************
+
+//-------------------------------------------------
+// spectrum_lprint_device - constructors
+//-------------------------------------------------
+
+spectrum_lprint_device::spectrum_lprint_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
+ : device_t(mconfig, SPECTRUM_LPRINT, tag, owner, clock)
+ , device_spectrum_expansion_interface(mconfig, *this)
+ , m_rom(*this, "rom")
+ , m_centronics(*this, "centronics")
+{
+}
+
+spectrum_lprint3_device::spectrum_lprint3_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
+ : device_t(mconfig, SPECTRUM_LPRINT3, tag, owner, clock)
+ , device_spectrum_expansion_interface(mconfig, *this)
+ , m_rom(*this, "rom")
+ , m_centronics(*this, "centronics")
+ , m_rs232(*this, "rs232")
+ , m_exp(*this, "exp")
+{
+}
+
+spectrum_kempcentrs_device::spectrum_kempcentrs_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
+ : device_t(mconfig, SPECTRUM_KEMPCENTRS, tag, owner, clock)
+ , device_spectrum_expansion_interface(mconfig, *this)
+ , m_centronics(*this, "centronics")
+{
+}
+
+spectrum_kempcentre_device::spectrum_kempcentre_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_spectrum_expansion_interface(mconfig, *this)
+ , m_rom(*this, "rom")
+ , m_centronics(*this, "centronics")
+{
+}
+
+spectrum_kempcentre_device::spectrum_kempcentre_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
+ : spectrum_kempcentre_device(mconfig, SPECTRUM_KEMPCENTREF, tag, owner, clock)
+{
+}
+
+spectrum_kempcentreu_device::spectrum_kempcentreu_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
+ : spectrum_kempcentre_device(mconfig, SPECTRUM_KEMPCENTREU, tag, owner, clock)
+{
+}
+
+
+//-------------------------------------------------
+// device_start - device-specific startup
+//-------------------------------------------------
+
+void spectrum_lprint_device::device_start()
+{
+ m_busy = 0;
+ save_item(NAME(m_romcs));
+ save_item(NAME(m_busy));
+}
+
+void spectrum_lprint3_device::device_start()
+{
+ m_busy = 0;
+ save_item(NAME(m_romcs));
+ save_item(NAME(m_busy));
+}
+
+void spectrum_kempcentrs_device::device_start()
+{
+ m_busy = 0;
+ save_item(NAME(m_busy));
+}
+
+void spectrum_kempcentre_device::device_start()
+{
+ m_busy = 0;
+ save_item(NAME(m_active));
+ save_item(NAME(m_romcs));
+ save_item(NAME(m_busy));
+}
+
+//-------------------------------------------------
+// device_reset - device-specific reset
+//-------------------------------------------------
+
+void spectrum_lprint_device::device_reset()
+{
+ m_romcs = 0;
+ m_centronics->write_strobe(1);
+}
+
+void spectrum_lprint3_device::device_reset()
+{
+ m_romcs = 0;
+ m_centronics->write_strobe(1);
+}
+
+void spectrum_kempcentrs_device::device_reset()
+{
+ m_centronics->write_strobe(1);
+}
+
+void spectrum_kempcentre_device::device_reset()
+{
+ m_active = 0;
+ m_romcs = 0;
+ m_centronics->write_strobe(1);
+}
+
+
+//**************************************************************************
+// IMPLEMENTATION (lprint)
+//**************************************************************************
+
+bool spectrum_lprint_device::romcs()
+{
+ return m_romcs;
+}
+
+void spectrum_lprint_device::pre_opcode_fetch(offs_t offset)
+{
+ if (!machine().side_effects_disabled())
+ m_romcs = offset >= 0x0800 && offset < 0x1000;
+}
+
+void spectrum_lprint_device::pre_data_fetch(offs_t offset)
+{
+ if (!machine().side_effects_disabled())
+ m_romcs = offset >= 0x0800 && offset < 0x1000;
+}
+
+uint8_t spectrum_lprint_device::mreq_r(offs_t offset)
+{
+ uint8_t data = 0xff;
+
+ if (m_romcs)
+ data = m_rom->base()[offset & 0x7ff];
+
+ return data;
+}
+
+uint8_t spectrum_lprint_device::iorq_r(offs_t offset)
+{
+ uint8_t data = offset & 1 ? m_slot->fb_r() : 0xff;
+
+ if (!BIT(offset, 2))
+ {
+ // code check this like - if (value & 0xe0) == 0x40, bit 6 probably /BUSY
+ data &= ~0xe0;
+ data |= !m_busy << 6;
+ }
+
+ return data;
+}
+
+void spectrum_lprint_device::iorq_w(offs_t offset, uint8_t data)
+{
+ if (!BIT(offset, 2))
+ {
+ m_centronics->write_data0(BIT(data, 0));
+ m_centronics->write_data1(BIT(data, 1));
+ m_centronics->write_data2(BIT(data, 2));
+ m_centronics->write_data3(BIT(data, 3));
+ m_centronics->write_data4(BIT(data, 4));
+ m_centronics->write_data5(BIT(data, 5));
+ m_centronics->write_data6(BIT(data, 6));
+ m_centronics->write_data7(BIT(data, 7));
+ m_centronics->write_strobe(1); // strobe probably fired automatically
+ m_centronics->write_strobe(0);
+ m_centronics->write_strobe(1);
+ }
+}
+
+
+//**************************************************************************
+// IMPLEMENTATION (lprint3)
+//**************************************************************************
+
+bool spectrum_lprint3_device::romcs()
+{
+ return m_romcs || m_exp->romcs();
+}
+
+uint8_t spectrum_lprint3_device::iorq_r(offs_t offset)
+{
+ uint8_t data = m_exp->iorq_r(offset);
+
+ if (!BIT(offset, 2))
+ {
+ if (!machine().side_effects_disabled())
+ m_romcs = BIT(offset, 7);
+ data &= ~0xc0;
+ data |= !m_rs232->dsr_r() << 6;
+ data |= m_busy << 7;
+ }
+
+ return data;
+}
+
+void spectrum_lprint3_device::iorq_w(offs_t offset, uint8_t data)
+{
+ if (!BIT(offset, 2))
+ {
+ m_centronics->write_data0(BIT(data, 0));
+ m_centronics->write_data1(BIT(data, 1));
+ m_centronics->write_data2(BIT(data, 2));
+ m_centronics->write_data3(BIT(data, 3));
+ m_centronics->write_data4(BIT(data, 4));
+ m_centronics->write_data5(BIT(data, 5));
+ m_centronics->write_data6(BIT(data, 6));
+ m_centronics->write_data7(BIT(data, 7));
+ m_centronics->write_strobe(BIT(offset, 7));
+ m_rs232->write_txd(!BIT(data, 7));
+ }
+
+ m_exp->iorq_w(offset, data);
+}
+
+uint8_t spectrum_lprint3_device::mreq_r(offs_t offset)
+{
+ uint8_t data = 0xff;
+
+ if (m_romcs)
+ data = m_rom->base()[offset & 0x7ff];
+
+ if (m_exp->romcs())
+ data &= m_exp->mreq_r(offset);
+
+ return data;
+}
+
+
+//**************************************************************************
+// IMPLEMENTATION (kempcentrs)
+//**************************************************************************
+
+uint8_t spectrum_kempcentrs_device::iorq_r(offs_t offset)
+{
+ uint8_t data = offset & 1 ? m_slot->fb_r() : 0xff;
+
+ switch (offset)
+ {
+ case 0xe2bf:
+ data &= ~1;
+ data |= m_busy << 0;
+ break;
+ }
+
+ return data;
+}
+
+void spectrum_kempcentrs_device::iorq_w(offs_t offset, uint8_t data)
+{
+ switch (offset)
+ {
+ case 0xe0bf:
+ m_centronics->write_data0(BIT(data, 0));
+ m_centronics->write_data1(BIT(data, 1));
+ m_centronics->write_data2(BIT(data, 2));
+ m_centronics->write_data3(BIT(data, 3));
+ m_centronics->write_data4(BIT(data, 4));
+ m_centronics->write_data5(BIT(data, 5));
+ m_centronics->write_data6(BIT(data, 6));
+ m_centronics->write_data7(BIT(data, 7));
+ break;
+ case 0xe3bf:
+ // bit 0 is /STROBE, other bits not known, upon init driver writes to this port 0x81 then 0x0f
+ m_centronics->write_strobe(BIT(data, 0));
+ break;
+ }
+}
+
+
+//**************************************************************************
+// IMPLEMENTATION (kempcentre)
+//**************************************************************************
+
+bool spectrum_kempcentre_device::romcs()
+{
+ return m_romcs;
+}
+
+void spectrum_kempcentre_device::pre_opcode_fetch(offs_t offset)
+{
+ if (!machine().side_effects_disabled())
+ m_romcs = m_active && offset >= 0x0800 && offset < 0x1000;
+}
+
+void spectrum_kempcentre_device::pre_data_fetch(offs_t offset)
+{
+ if (!machine().side_effects_disabled())
+ m_romcs = m_active && offset >= 0x0800 && offset < 0x1000;
+}
+
+uint8_t spectrum_kempcentre_device::iorq_r(offs_t offset)
+{
+ uint8_t data = offset & 1 ? m_slot->fb_r() : 0xff;
+
+ if (!BIT(offset, 2)) // earlier version ? uses same paging as Lprint III
+ {
+ if (!machine().side_effects_disabled())
+ m_active = BIT(offset, 7);
+ }
+
+ if ((offset & 0xf0) == 0xb0) // BB or BF, actual address decode is not known
+ {
+ data &= ~0xc0;
+ data |= m_busy << 6;
+ }
+
+ return data;
+}
+
+void spectrum_kempcentre_device::iorq_w(offs_t offset, uint8_t data)
+{
+ if ((offset & 0xf0) == 0xb0) // BB or BF, actual address decode is not known
+ {
+ m_centronics->write_data0(BIT(data, 0));
+ m_centronics->write_data1(BIT(data, 1));
+ m_centronics->write_data2(BIT(data, 2));
+ m_centronics->write_data3(BIT(data, 3));
+ m_centronics->write_data4(BIT(data, 4));
+ m_centronics->write_data5(BIT(data, 5));
+ m_centronics->write_data6(BIT(data, 6));
+ m_centronics->write_data7(BIT(data, 7));
+ m_centronics->write_strobe(BIT(offset, 2));
+ }
+}
+
+uint8_t spectrum_kempcentre_device::mreq_r(offs_t offset)
+{
+ uint8_t data = 0xff;
+
+ if (m_romcs)
+ data = m_rom->base()[offset & 0x7ff];
+
+ return data;
+}
+
+
+//**************************************************************************
+// IMPLEMENTATION (kempcentreu)
+//**************************************************************************
+
+void spectrum_kempcentreu_device::device_start()
+{
+ // descramble ROM
+ std::vector<uint8_t> temp(m_rom->bytes());
+ std::copy_n(m_rom->base(), m_rom->bytes(), &temp[0]);
+ for (int i = 0; i < m_rom->bytes(); i++)
+ {
+ uint16_t addr = bitswap<11>(i, 10, 1, 0, 3, 7, 2, 6, 5, 4, 8, 9);
+ m_rom->base()[i] = bitswap<8>(temp[addr], 4, 5, 0, 1, 6, 7, 2, 3);
+ }
+ spectrum_kempcentre_device::device_start();
+}
+
+void spectrum_kempcentreu_device::pre_opcode_fetch(offs_t offset)
+{
+ if (!machine().side_effects_disabled())
+ {
+ if (offset == 0x09F4 || offset == 0x0eb4) // later version ? paged at PRINT and COPY routines
+ m_active = 1;
+
+ m_romcs = m_active && offset >= 0x0800 && offset < 0x1000;
+ }
+}
+
+uint8_t spectrum_kempcentreu_device::iorq_r(offs_t offset)
+{
+ uint8_t data = offset & 1 ? m_slot->fb_r() : 0xff;
+
+ if ((offset & 0xf0) == 0xb0) // BB or BF, actual address decode is not known
+ {
+ if (!machine().side_effects_disabled())
+ m_active = !BIT(offset, 2);
+ data &= ~0xc0;
+ data |= m_busy << 6;
+ //data |= something_centronics << 7; // wired to centronics port, but connected to GND via wire-mod
+ }
+
+ return data;
+}
diff --git a/src/devices/bus/spectrum/lprint.h b/src/devices/bus/spectrum/lprint.h
new file mode 100644
index 00000000000..ccf330b7ded
--- /dev/null
+++ b/src/devices/bus/spectrum/lprint.h
@@ -0,0 +1,185 @@
+// license:BSD-3-Clause
+// copyright-holders:MetalliC
+/*********************************************************************
+
+ Common printer interfaces
+
+*********************************************************************/
+#ifndef MAME_BUS_SPECTRUM_LPRINT_H
+#define MAME_BUS_SPECTRUM_LPRINT_H
+
+#include "exp.h"
+#include "bus/centronics/ctronics.h"
+#include "bus/rs232/rs232.h"
+
+//**************************************************************************
+// TYPE DEFINITIONS
+//**************************************************************************
+
+class spectrum_lprint_device :
+ public device_t,
+ public device_spectrum_expansion_interface
+
+{
+public:
+ // construction/destruction
+ spectrum_lprint_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
+
+protected:
+ // device-level overrides
+ virtual void device_start() override ATTR_COLD;
+ virtual void device_reset() override ATTR_COLD;
+
+ // optional information overrides
+ virtual void device_add_mconfig(machine_config &config) override ATTR_COLD;
+ virtual const tiny_rom_entry *device_rom_region() const override ATTR_COLD;
+
+ virtual void pre_opcode_fetch(offs_t offset) override;
+ virtual void pre_data_fetch(offs_t offset) 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;
+
+ void busy_w(int state) { m_busy = state; }
+
+ required_memory_region m_rom;
+ required_device<centronics_device> m_centronics;
+
+ bool m_romcs;
+ int m_busy;
+};
+
+class spectrum_lprint3_device :
+ public device_t,
+ public device_spectrum_expansion_interface
+
+{
+public:
+ // construction/destruction
+ spectrum_lprint3_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
+
+protected:
+ // device-level overrides
+ virtual void device_start() override ATTR_COLD;
+ virtual void device_reset() override ATTR_COLD;
+
+ // optional information overrides
+ virtual void device_add_mconfig(machine_config &config) override ATTR_COLD;
+ virtual const tiny_rom_entry *device_rom_region() const override ATTR_COLD;
+
+ 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); }
+
+ 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;
+
+ bool m_romcs;
+ int m_busy;
+};
+
+class spectrum_kempcentrs_device :
+ public device_t,
+ public device_spectrum_expansion_interface
+
+{
+public:
+ // construction/destruction
+ spectrum_kempcentrs_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
+
+protected:
+ // device-level overrides
+ virtual void device_start() override ATTR_COLD;
+ virtual void device_reset() override ATTR_COLD;
+
+ // optional information overrides
+ virtual void device_add_mconfig(machine_config &config) override ATTR_COLD;
+
+ virtual uint8_t iorq_r(offs_t offset) override;
+ virtual void iorq_w(offs_t offset, uint8_t data) override;
+
+ void busy_w(int state) { m_busy = state; }
+
+ required_device<centronics_device> m_centronics;
+
+ int m_busy;
+};
+
+class spectrum_kempcentre_device :
+ public device_t,
+ public device_spectrum_expansion_interface
+
+{
+public:
+ // construction/destruction
+ spectrum_kempcentre_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
+
+protected:
+ spectrum_kempcentre_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 ATTR_COLD;
+ virtual void device_reset() override ATTR_COLD;
+
+ // optional information overrides
+ virtual void device_add_mconfig(machine_config &config) override ATTR_COLD;
+ virtual const tiny_rom_entry *device_rom_region() const override ATTR_COLD;
+
+ virtual void pre_opcode_fetch(offs_t offset) override;
+ virtual void pre_data_fetch(offs_t offset) 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;
+
+ void busy_w(int state) { m_busy = state; }
+
+ required_memory_region m_rom;
+ required_device<centronics_device> m_centronics;
+
+ int m_active;
+ bool m_romcs;
+ int m_busy;
+};
+
+class spectrum_kempcentreu_device :
+ public spectrum_kempcentre_device
+{
+public:
+ // construction/destruction
+ spectrum_kempcentreu_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
+
+protected:
+ // device-level overrides
+ virtual void device_start() override ATTR_COLD;
+
+ // optional information overrides
+ virtual const tiny_rom_entry *device_rom_region() const override ATTR_COLD;
+
+ virtual void pre_opcode_fetch(offs_t offset) override;
+ virtual uint8_t iorq_r(offs_t offset) override;
+};
+
+
+// device type definition
+DECLARE_DEVICE_TYPE(SPECTRUM_LPRINT, spectrum_lprint_device)
+DECLARE_DEVICE_TYPE(SPECTRUM_LPRINT3, spectrum_lprint3_device)
+DECLARE_DEVICE_TYPE(SPECTRUM_KEMPCENTRS, spectrum_kempcentrs_device)
+DECLARE_DEVICE_TYPE(SPECTRUM_KEMPCENTREF, spectrum_kempcentre_device)
+DECLARE_DEVICE_TYPE(SPECTRUM_KEMPCENTREU, spectrum_kempcentreu_device)
+
+
+#endif // MAME_BUS_SPECTRUM_LPRINT_H
diff --git a/src/devices/bus/spectrum/melodik.cpp b/src/devices/bus/spectrum/melodik.cpp
index 9a6f743a65b..0b77635c051 100644
--- a/src/devices/bus/spectrum/melodik.cpp
+++ b/src/devices/bus/spectrum/melodik.cpp
@@ -32,6 +32,7 @@ void spectrum_melodik_device::device_add_mconfig(machine_config &config)
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));
}
//**************************************************************************
@@ -64,32 +65,6 @@ void spectrum_melodik_device::device_start()
// IMPLEMENTATION
//**************************************************************************
-READ_LINE_MEMBER(spectrum_melodik_device::romcs)
-{
- return m_exp->romcs();
-}
-
-void spectrum_melodik_device::pre_opcode_fetch(offs_t offset)
-{
- m_exp->pre_opcode_fetch(offset);
-}
-
-uint8_t spectrum_melodik_device::mreq_r(offs_t offset)
-{
- uint8_t data = 0xff;
-
- if (m_exp->romcs())
- data &= m_exp->mreq_r(offset);
-
- return data;
-}
-
-void spectrum_melodik_device::mreq_w(offs_t offset, uint8_t data)
-{
- if (m_exp->romcs())
- m_exp->mreq_w(offset, data);
-}
-
uint8_t spectrum_melodik_device::iorq_r(offs_t offset)
{
uint8_t data = m_exp->iorq_r(offset);
@@ -97,7 +72,7 @@ uint8_t spectrum_melodik_device::iorq_r(offs_t offset)
switch (offset & 0xc002)
{
case 0xc000:
- data &= m_psg->data_r();
+ data = m_psg->data_r();
break;
}
return data;
@@ -108,10 +83,10 @@ void spectrum_melodik_device::iorq_w(offs_t offset, uint8_t data)
switch (offset & 0xc002)
{
case 0x8000:
- m_psg->address_w(data);
+ m_psg->data_w(data);
break;
case 0xc000:
- m_psg->data_w(data);
+ m_psg->address_w(data);
break;
}
m_exp->iorq_w(offset, data);
diff --git a/src/devices/bus/spectrum/melodik.h b/src/devices/bus/spectrum/melodik.h
index bf1514f600c..5364ae6906e 100644
--- a/src/devices/bus/spectrum/melodik.h
+++ b/src/devices/bus/spectrum/melodik.h
@@ -31,17 +31,22 @@ public:
protected:
// device-level overrides
- virtual void device_start() override;
+ virtual void device_start() override ATTR_COLD;
// optional information overrides
- virtual void device_add_mconfig(machine_config &config) override;
+ virtual void device_add_mconfig(machine_config &config) override ATTR_COLD;
- 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 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;
+
+ // 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 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 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 807787126b2..2fa4aa7e1bd 100644
--- a/src/devices/bus/spectrum/mface.cpp
+++ b/src/devices/bus/spectrum/mface.cpp
@@ -3,6 +3,118 @@
/*********************************************************************
Romantic Robot Multiface One/128/3
+ ----------------------------------
+
+ " MULTI-PURPOSE INTERFACE FOR THE ZX SPECTRUM "
+
+ MULTIFACE ONE comprises three interfaces in one box:
+ 1) Fully universal and 100% automatic SAVE facility for tape, microdrive, wafadrive, Beta,
+ Discovery and indirectly (via tape) for other disc systems
+ 2) Joystick interface – Kempston compatible (IN 31)
+ 3) 8K RAM extension – fully accessible, usable as a RAM disk, buffer etc. Also used by
+ MULTIFACE for MULTI TOOLKIT routines, buffer & other purposes.
+
+ © Romantic Robot UK Ltd 1985
+
+
+ Compatibility (real hardware)
+ -------------
+ mface1 models work with 48K, 128K/+2 (only in 48K mode), don't work with +2A/+3
+ mface128 models work with 48K/128K/+2, don't work with +2A/+3
+ mface3 works only with +2A/+3
+ mprint works with 48K/128K/+2, doesn't work with +2A/+3
+ incompatibility is due mainly to expansion slot pinout changes on last Amstrad built models.
+
+
+ Multiface One
+ -------------
+ Many versions exist, a very good source of info is: https://x128.speccy.cz/multiface/multiface.htm
+
+ Summary:
+ Earliest version has 2KB of RAM, composite video output, and no pokes or toolkit.
+ Next version has 8KB of RAM, composite video output, and basic toolkit (just pokes).
+ Latest and most common version dropped the composite video output, added an enable/disable switch, and full-featured toolkit.
+ A special (and rare) version supports the Kempston Disc interface but drops Beta support. (not sold in stores, available only on request).
+ At some point the page out port changed from 0x5f to 0x1f (rev 2.0 pcb?)
+ Three pcb revs are known: 1.2, 2.0, 2.1.
+ Various clone/hacked rom versions are known to exist as well.
+
+ Roms:
+ The MUxx in the rom name is pcb revision (silkscreen marking).
+ The two hex digits are the rom checksum.
+ With the MF menu on-screen, press Symbol Shift + A (STOP) to see checksum, space to return.
+
+ The "joystick disable" jumper is required for use with Beta disk which would otherwise not work due to port clash.
+ Real world mf1/beta combo only works spectrum->mf1->beta, with jumper open, the user manual suggests Beta users may like to fit a switch instead.
+ Some confusion exactly how this works, as an original-looking schematic shows the jumper simply setting data bits 6,7 hi-z, with the actual joystick still operational.
+ 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...?
+
+ 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.
+
+ rom maps to 0x0000
+ ram maps to 0x2000
+
+ I/O R/W early ver late ver
+ ---------+-----+-----------+-----------
+ page in R 0x9f 0x9f
+ page out R 0x5f 0x1f
+ nmi reset W 0x5f 0x1f
+ joystick R 0x1f 0x1f
+
+
+ Multiface 128
+ -------------
+ 128K/+2 support (also works with 48K)
+ Software enable/disable (in menu, press 'o' to toggle on/off)
+ Some new 128k-exclusive menu features when running in 128k mode (mode is auto-detected)
+ No joystick port
+ No Beta support
+ Pass-through connector was optional
+ Original hardware version isn't compatible with DISCiPLE/+D (port clash), has "hypertape" high-speed tape recording
+ Second hardware version added DISCiPLE/+D compatibility and support as save device (uses different ports) but lost hypertape support
+
+ supported devices rom
+ -----+----------------------------------------+-------------
+ v1 Tape, Hypertape, Microdrive, Opus 87.1, 87.12
+ v2 Tape, Microdrive, Opus, DISCiPLE/+D 87.2
+
+ I/O R/W v1 v2
+ ---------+-----+-----------+-----------
+ page in R 0x9f 0xbf
+ page out R 0x1f 0x3f
+ nmi reset W 0x9f 0xbf
+ hide W 0x1f 0x3f
+
+
+ Multiface 3
+ -----------
+ +2A/+2B/+3/+3B support (doesn't work with 48K/128K/+2)
+ +3 disk support
+ Pass-through connector was optional
+ No support for older external disk interfaces (Beta, Opus, +D etc.)
+ Pcb/logic is quite different to other models, has a PAL16L8 and 74LS670 4x4 register file.
+ A schematic created from the Hard Mirco clone pcb is available, used for various modern "re-creation" projects,
+ official version assumed to be very similar if not identical.
+ Hard Mirco clone has double size ROM (16K), but contains two identical 8K halves of data. Pcb does have ability to select rom half via software,
+ so perhaps an unused multi-bios feature? (unknown if unique to clone pcb or present on official pcb also).
+
+
+ Multiprint
+ ----------
+ Printer interface with some mface features
+ No backup/snapshot feature
+ Has all other usual mface features: cheat/poke, 8KB RAM, magic button etc.
+ Centronics parallel printer port
+ Kempston E and ZX Lprint compatible (LPRINT, LLIST, COPY etc.)
+ Unique "REM" command set (commands "hidden" in rem comments)
+ Pass-through connector was optional
+
+ Todo: find other print command hooks, only magic button triggered menu works for now...
+
*********************************************************************/
@@ -14,7 +126,11 @@
DEVICE DEFINITIONS
***************************************************************************/
+DEFINE_DEVICE_TYPE(SPECTRUM_MFACE1V1, spectrum_mface1v1_device, "spectrum_mface1v1", "Multiface One v1")
+DEFINE_DEVICE_TYPE(SPECTRUM_MFACE1V2, spectrum_mface1v2_device, "spectrum_mface1v2", "Multiface One v2")
+DEFINE_DEVICE_TYPE(SPECTRUM_MFACE1V3, spectrum_mface1v3_device, "spectrum_mface1v3", "Multiface One v3")
DEFINE_DEVICE_TYPE(SPECTRUM_MFACE1, spectrum_mface1_device, "spectrum_mface1", "Multiface One")
+DEFINE_DEVICE_TYPE(SPECTRUM_MFACE128V1, spectrum_mface128v1_device, "spectrum_mface128v1", "Multiface 128 v1")
DEFINE_DEVICE_TYPE(SPECTRUM_MFACE128, spectrum_mface128_device, "spectrum_mface128", "Multiface 128")
DEFINE_DEVICE_TYPE(SPECTRUM_MFACE3, spectrum_mface3_device, "spectrum_mface3", "Multiface 3")
DEFINE_DEVICE_TYPE(SPECTRUM_MPRINT, spectrum_mprint_device, "spectrum_mprint", "MultiPrint")
@@ -24,51 +140,130 @@ DEFINE_DEVICE_TYPE(SPECTRUM_MPRINT, spectrum_mprint_device, "spectrum_mprint", "
// INPUT_PORTS( mface )
//-------------------------------------------------
-INPUT_PORTS_START(mface)
+INPUT_PORTS_START( mface )
PORT_START("BUTTON")
- PORT_BIT(0x01, IP_ACTIVE_LOW, IPT_BUTTON1) PORT_NAME("Multiface") PORT_CODE(KEYCODE_F12) PORT_CHANGED_MEMBER(DEVICE_SELF, spectrum_mface1_device, magic_button, 0)
+ PORT_BIT(0x01, IP_ACTIVE_LOW, IPT_BUTTON1) PORT_NAME("Red Button") PORT_CODE(KEYCODE_PLUS_PAD) PORT_CHANGED_MEMBER(DEVICE_SELF, FUNC(spectrum_mface_base_device::magic_button), 0)
+INPUT_PORTS_END
+
+INPUT_PORTS_START( mface1v2 )
+ PORT_INCLUDE( mface )
+
+ PORT_START("CONFIG")
+ PORT_CONFNAME(0x02, 0x00, "Joystick Enable Jumper")
+ PORT_CONFSETTING(0x00, "Closed")
+ PORT_CONFSETTING(0x02, "Open")
+ PORT_BIT(0xfd, IP_ACTIVE_LOW, IPT_UNUSED)
+
+ PORT_START("JOY")
+ PORT_BIT(0x01, IP_ACTIVE_HIGH, IPT_JOYSTICK_RIGHT) PORT_8WAY
+ PORT_BIT(0x02, IP_ACTIVE_HIGH, IPT_JOYSTICK_LEFT) PORT_8WAY
+ PORT_BIT(0x04, IP_ACTIVE_HIGH, IPT_JOYSTICK_DOWN) PORT_8WAY
+ PORT_BIT(0x08, IP_ACTIVE_HIGH, IPT_JOYSTICK_UP) PORT_8WAY
+ PORT_BIT(0x10, IP_ACTIVE_HIGH, IPT_BUTTON1)
+INPUT_PORTS_END
+
+INPUT_PORTS_START( mface1 )
+ PORT_INCLUDE( mface1v2 )
+
+ PORT_MODIFY("CONFIG")
+ PORT_CONFNAME(0x01, 0x00, "Interface Enable Switch")
+ PORT_CONFSETTING(0x00, "Enabled")
+ PORT_CONFSETTING(0x01, "Disabled")
+ PORT_BIT(0xfc, IP_ACTIVE_LOW, IPT_UNUSED)
INPUT_PORTS_END
//-------------------------------------------------
// input_ports - device-specific input ports
//-------------------------------------------------
-ioport_constructor spectrum_mface1_device::device_input_ports() const
+ioport_constructor spectrum_mface_base_device::device_input_ports() const
{
return INPUT_PORTS_NAME(mface);
}
+ioport_constructor spectrum_mface1v2_device::device_input_ports() const
+{
+ return INPUT_PORTS_NAME(mface1v2);
+}
+
+ioport_constructor spectrum_mface1_device::device_input_ports() const
+{
+ return INPUT_PORTS_NAME(mface1);
+}
+
//-------------------------------------------------
-// ROM( mface1 )
+// ROM( mface )
//-------------------------------------------------
-ROM_START(mface1)
+ROM_START(mface1v1) // pcb rev 1.2
ROM_REGION(0x2000, "rom", 0)
- ROM_DEFAULT_BIOS("mu21e7")
- ROM_SYSTEM_BIOS(0, "mu20fe", "MU 2.0 FE")
+ ROM_DEFAULT_BIOS("mu12cb")
+ ROM_SYSTEM_BIOS(0, "mu12cb", "MU12 CB") // 2KB RAM, no pokes or toolkit, page out port 0x5f
+ ROMX_LOAD("mf1_12_cb.rom", 0x0000, 0x2000, CRC(c88fbf9f) SHA1(c3018d1b495b8bc0a135038db0987de7091c9d4c), ROM_BIOS(0))
+ROM_END
+
+ROM_START(mface1v2) // unknown pcb rev (probably <2.0)
+ ROM_REGION(0x2000, "rom", 0)
+ ROM_DEFAULT_BIOS("muxx23")
+ ROM_SYSTEM_BIOS(0, "muxx23", "MU x.x 23") // 8KB RAM, pokes only (no toolkit), page out port 0x5f
+ ROMX_LOAD("mf1_xx_23.rom", 0x0000, 0x2000, CRC(d4ae8953) SHA1(b442eb634a72fb63f1ccbbd0021a7a581152888d), ROM_BIOS(0))
+ROM_END
+
+ROM_START(mface1v3) // pcb rev 2.0
+ ROM_REGION(0x2000, "rom", 0)
+ ROM_DEFAULT_BIOS("mu20fe")
+ ROM_SYSTEM_BIOS(0, "mu20fe", "MU 2.0 FE") // pokes only (no toolkit)
ROMX_LOAD("mf1_20_fe.rom", 0x0000, 0x2000, CRC(fa1b8b0d) SHA1(20cd508b0143166558a7238c7a9ccfbe37b90b0d), ROM_BIOS(0))
- ROM_SYSTEM_BIOS(1, "mu2167", "MU 2.1 67")
- ROMX_LOAD("mf1_21_67.rom", 0x0000, 0x2000, CRC(d720ec1b) SHA1(91a40d8f503ef825df3e2ed712897dbf4ca3671d), ROM_BIOS(1))
- ROM_SYSTEM_BIOS(2, "mu21e4", "MU 2.1 E4")
- ROMX_LOAD("mf1_21_e4.rom", 0x0000, 0x2000, CRC(4b31a971) SHA1(ba28754a3cc31a4ca579829ed4310c313409cf5d), ROM_BIOS(2))
- ROM_SYSTEM_BIOS(3, "mu21e7", "MU 2.1 E7")
- ROMX_LOAD("mf1_21_e7.rom", 0x0000, 0x2000, CRC(670f0ec2) SHA1(50fba2d628f3a2e9219f72980e4efd62fc9ec1f8), ROM_BIOS(3))
+ // ROM_SYSTEM_BIOS(1, "mu2090", "MU 2.0, 90") // alt, unknown if earlier or later, no dump
+ // ROMX_LOAD("mf1_20_90.rom", 0x0000, 0x2000, CRC(2eaf8e41) SHA1(?), ROM_BIOS(1))
+ROM_END
+
+ROM_START(mface1) // pcb rev 2.1
+ ROM_REGION(0x2000, "rom", 0)
+ ROM_DEFAULT_BIOS("mu21e4")
+ ROM_SYSTEM_BIOS(0, "mu21e4", "MU 2.1 E4") // most common version
+ ROMX_LOAD("mf1_21_e4.rom", 0x0000, 0x2000, CRC(4b31a971) SHA1(ba28754a3cc31a4ca579829ed4310c313409cf5d), ROM_BIOS(0))
+ ROM_SYSTEM_BIOS(1, "mu21e7", "MU 2.1 E7") // alt, unknown if earlier or later, glitchy with Betaplus
+ ROMX_LOAD("mf1_21_e7.rom", 0x0000, 0x2000, CRC(670f0ec2) SHA1(50fba2d628f3a2e9219f72980e4efd62fc9ec1f8), ROM_BIOS(1))
+ ROM_SYSTEM_BIOS(2, "mu2167", "MU 2.1 67") // Kempston Disc support, no Beta support
+ ROMX_LOAD("mf1_21_67.rom", 0x0000, 0x2000, CRC(d720ec1b) SHA1(91a40d8f503ef825df3e2ed712897dbf4ca3671d), ROM_BIOS(2))
+ ROM_SYSTEM_BIOS(3, "bc96", "Brazilian clone 96") // Brazilian clone, unknown pcb version
+ ROMX_LOAD("mf1_bc_96.rom", 0x0000, 0x2000, CRC(e6fe4507) SHA1(a7e03e7fee3aa05ce1501072aab4534ea7bae257), ROM_BIOS(3))
+ // ROM_SYSTEM_BIOS(4, "bc93", "Brazilian clone 93") // another Brazilian clone, unknown pcb version, no dump
+ // ROMX_LOAD("mf1_bc_93.rom", 0x0000, 0x2000, CRC(8c17113b) SHA1(?), ROM_BIOS(4))
ROM_END
-ROM_START(mface128)
+ROM_START(mface128v1)
+ ROM_REGION(0x2000, "rom", 0)
+ ROM_DEFAULT_BIOS("v350f")
+ ROM_SYSTEM_BIOS(0, "v340d", "87.1 V34 0D")
+ ROMX_LOAD("mf128_34_0d.rom", 0x0000, 0x2000, CRC(8d8cfd39) SHA1(2104962bb6097e58fcab63969bbaca424a872bb5), ROM_BIOS(0))
+ ROM_SYSTEM_BIOS(1, "v350f", "87.12 V35 0F")
+ ROMX_LOAD("mf128_35_0f.rom", 0x0000, 0x2000, CRC(cfefd560) SHA1(6cd6fd2c0fbb40a989a568db9d08ba8eed49cbbd), ROM_BIOS(1))
+ROM_END
+
+ROM_START(mface128) // DISCiPLE/+D compatible version
ROM_REGION(0x2000, "rom", 0)
ROM_DEFAULT_BIOS("v363c")
- ROM_SYSTEM_BIOS(0, "v363c", "87.2 V36 3C")
- ROMX_LOAD("mf128_36_3c.rom", 0x0000, 0x2000, CRC(78ec8cfd) SHA1(8df204ab490b87c389971ce0c7fb5f9cbd281f14), ROM_BIOS(0))
+ ROM_SYSTEM_BIOS(0, "vxx1d", "87.2 Vxx 1D") // unknown PCB version
+ ROMX_LOAD("mf128_xx_1d.rom", 0x0000, 0x2000, CRC(f473991e) SHA1(f03f4ecbcf4a654f4775d16bda0d4cc47f884379), ROM_BIOS(0))
+ ROM_SYSTEM_BIOS(1, "v363c", "87.2 V36 3C")
+ ROMX_LOAD("mf128_36_3c.rom", 0x0000, 0x2000, CRC(78ec8cfd) SHA1(8df204ab490b87c389971ce0c7fb5f9cbd281f14), ROM_BIOS(1))
ROM_END
ROM_START(mface3)
ROM_REGION(0x2000, "rom", 0)
- ROM_DEFAULT_BIOS("v50fe")
- ROM_SYSTEM_BIOS(0, "v5013", "V50 13")
- ROMX_LOAD("mf3_50_13.rom", 0x0000, 0x2000, CRC(2d594640) SHA1(5d74d2e2e5a537639da92ff120f8a6d86f474495), ROM_BIOS(0))
- ROM_SYSTEM_BIOS(1, "v50fe", "V50 FE")
- ROMX_LOAD("mf3_50_fe.rom", 0x0000, 0x2000, CRC(b5c00f28) SHA1(983699a07665186f498f5827f9b35c442c2178ba), ROM_BIOS(1))
+ ROM_DEFAULT_BIOS("v5013")
+ ROM_SYSTEM_BIOS(0, "v50fe", "3.9 V50 FE") // doesn't have "lock 48K" option in save menu
+ ROMX_LOAD("mf3_50_fe.rom", 0x0000, 0x2000, CRC(b5c00f28) SHA1(983699a07665186f498f5827f9b35c442c2178ba), ROM_BIOS(0))
+ ROM_SYSTEM_BIOS(1, "v5013", "3.c V50 13")
+ ROMX_LOAD("mf3_50_13.rom", 0x0000, 0x2000, CRC(2d594640) SHA1(5d74d2e2e5a537639da92ff120f8a6d86f474495), ROM_BIOS(1))
+ ROM_SYSTEM_BIOS(2, "vxx9a", "Hard Micro Multiface 3 clone Vxx 9A")
+ ROMX_LOAD("mf3_hm_9a.rom", 0x0000, 0x2000, CRC(2ce53095) SHA1(5fa286f1552f26575a14ab32125d59c26ce95978), ROM_BIOS(2))
+ ROM_IGNORE(0x2000) // ROM is 16K, but contains two identical 8K halves
+
+ ROM_REGION( 0x200, "plds", 0 ) // pal from Hard Micro clone, probably the same for all
+ ROM_LOAD( "mf3_pal16l8a.icx", 0x000, 0x104, CRC(710186a1) SHA1(6573c2b8f55f66ef71ce3992f654080141e09739) )
ROM_END
ROM_START(mprint)
@@ -84,12 +279,45 @@ ROM_END
// device_add_mconfig - add device configuration
//-------------------------------------------------
-void spectrum_mface1_device::device_add_mconfig(machine_config &config)
+void spectrum_mface_base_device::device_add_mconfig(machine_config &config)
{
/* 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));
+}
+
+void spectrum_mface3_device::device_add_mconfig(machine_config &config)
+{
+ spectrum_mface_base_device::device_add_mconfig(config);
+
+ /* passthru (+3 compatible devices only) */
+ SPECTRUM_EXPANSION_SLOT(config.replace(), m_exp, specpls3_expansion_devices, nullptr);
+}
+
+void spectrum_mprint_device::device_add_mconfig(machine_config &config)
+{
+ spectrum_mface_base_device::device_add_mconfig(config);
+
+ /* printer port */
+ CENTRONICS(config, m_centronics, centronics_devices, "printer");
+ m_centronics->busy_handler().set(FUNC(spectrum_mprint_device::busy_w));
+}
+
+const tiny_rom_entry *spectrum_mface1v1_device::device_rom_region() const
+{
+ return ROM_NAME(mface1v1);
+}
+
+const tiny_rom_entry *spectrum_mface1v2_device::device_rom_region() const
+{
+ return ROM_NAME(mface1v2);
+}
+
+const tiny_rom_entry *spectrum_mface1v3_device::device_rom_region() const
+{
+ return ROM_NAME(mface1v3);
}
const tiny_rom_entry *spectrum_mface1_device::device_rom_region() const
@@ -97,6 +325,11 @@ const tiny_rom_entry *spectrum_mface1_device::device_rom_region() const
return ROM_NAME(mface1);
}
+const tiny_rom_entry *spectrum_mface128v1_device::device_rom_region() const
+{
+ return ROM_NAME(mface128v1);
+}
+
const tiny_rom_entry *spectrum_mface128_device::device_rom_region() const
{
return ROM_NAME(mface128);
@@ -118,10 +351,10 @@ const tiny_rom_entry *spectrum_mprint_device::device_rom_region() const
//**************************************************************************
//-------------------------------------------------
-// spectrum_opus_device - constructor
+// spectrum_mface_base_device - constructor
//-------------------------------------------------
-spectrum_mface1_device::spectrum_mface1_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock)
+spectrum_mface_base_device::spectrum_mface_base_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_spectrum_expansion_interface(mconfig, *this)
, m_rom(*this, "rom")
@@ -129,23 +362,66 @@ spectrum_mface1_device::spectrum_mface1_device(const machine_config &mconfig, de
{
}
+spectrum_mface1v2_device::spectrum_mface1v2_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock)
+ : spectrum_mface_base_device(mconfig, type, tag, owner, clock)
+ , m_joy(*this, "JOY")
+ , m_hwconfig(*this, "CONFIG")
+{
+}
+
+spectrum_mface1v2_device::spectrum_mface1v2_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
+ : spectrum_mface1v2_device(mconfig, SPECTRUM_MFACE1V2, tag, owner, clock)
+{
+}
+
+spectrum_mface1v1_device::spectrum_mface1v1_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
+ : spectrum_mface1v2_device(mconfig, SPECTRUM_MFACE1V1, tag, owner, clock)
+{
+}
+
+spectrum_mface1v3_device::spectrum_mface1v3_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock)
+ : spectrum_mface1v2_device(mconfig, type, tag, owner, clock)
+{
+}
+
+spectrum_mface1v3_device::spectrum_mface1v3_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
+ : spectrum_mface1v3_device(mconfig, SPECTRUM_MFACE1V3, tag, owner, clock)
+{
+}
+
spectrum_mface1_device::spectrum_mface1_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
- : spectrum_mface1_device(mconfig, SPECTRUM_MFACE1, tag, owner, clock)
+ : spectrum_mface1v3_device(mconfig, SPECTRUM_MFACE1, tag, owner, clock)
+{
+}
+
+spectrum_mface128_base_device::spectrum_mface128_base_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock)
+ : spectrum_mface_base_device(mconfig, type, tag, owner, clock)
+{
+}
+
+spectrum_mface128v1_device::spectrum_mface128v1_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock)
+ : spectrum_mface128_base_device(mconfig, type, tag, owner, clock)
+{
+}
+
+spectrum_mface128v1_device::spectrum_mface128v1_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
+ : spectrum_mface128v1_device(mconfig, SPECTRUM_MFACE128V1, tag, owner, clock)
{
}
spectrum_mface128_device::spectrum_mface128_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
- : spectrum_mface1_device(mconfig, SPECTRUM_MFACE128, tag, owner, clock)
+ : spectrum_mface128v1_device(mconfig, SPECTRUM_MFACE128, tag, owner, clock)
{
}
spectrum_mface3_device::spectrum_mface3_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
- : spectrum_mface1_device(mconfig, SPECTRUM_MFACE3, tag, owner, clock)
+ : spectrum_mface128_base_device(mconfig, SPECTRUM_MFACE3, tag, owner, clock)
{
}
spectrum_mprint_device::spectrum_mprint_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
- : spectrum_mface1_device(mconfig, SPECTRUM_MPRINT, tag, owner, clock)
+ : spectrum_mface128_base_device(mconfig, SPECTRUM_MPRINT, tag, owner, clock)
+ , m_centronics(*this, "centronics")
{
}
@@ -153,18 +429,79 @@ spectrum_mprint_device::spectrum_mprint_device(const machine_config &mconfig, co
// device_start - device-specific startup
//-------------------------------------------------
-void spectrum_mface1_device::device_start()
+void spectrum_mface_base_device::device_start()
{
save_item(NAME(m_romcs));
+ save_item(NAME(m_nmi_pending));
+}
+
+void spectrum_mface1v2_device::device_start()
+{
+ m_ram = std::make_unique<uint8_t[]>(8 * 1024);
+ save_pointer(NAME(m_ram), 8 * 1024);
+ spectrum_mface_base_device::device_start();
+}
+
+void spectrum_mface1v1_device::device_start()
+{
+ m_ram = std::make_unique<uint8_t[]>(2 * 1024);
+ save_pointer(NAME(m_ram), 2 * 1024);
+ spectrum_mface_base_device::device_start();
+}
+
+void spectrum_mface128_base_device::device_start()
+{
+ m_ram = std::make_unique<uint8_t[]>(8 * 1024);
+ save_pointer(NAME(m_ram), 8 * 1024);
+ save_item(NAME(m_hidden));
+ spectrum_mface_base_device::device_start();
+}
+
+void spectrum_mface128v1_device::device_start()
+{
+ spectrum_mface128_base_device::device_start();
+ save_item(NAME(m_d3_ff));
+}
+
+void spectrum_mface3_device::device_start()
+{
+ spectrum_mface128_base_device::device_start();
+ save_item(NAME(m_disable));
+}
+
+void spectrum_mprint_device::device_start()
+{
+ spectrum_mface128_base_device::device_start();
+ m_busy = 0;
+ save_item(NAME(m_busy));
}
//-------------------------------------------------
// device_reset - device-specific reset
//-------------------------------------------------
-void spectrum_mface1_device::device_reset()
+void spectrum_mface_base_device::device_reset()
{
m_romcs = 0;
+ m_nmi_pending = 0;
+}
+
+void spectrum_mface128_base_device::device_reset()
+{
+ spectrum_mface_base_device::device_reset();
+ m_hidden = 1;
+}
+
+void spectrum_mface3_device::device_reset()
+{
+ spectrum_mface128_base_device::device_reset();
+ m_disable = 0;
+}
+
+void spectrum_mprint_device::device_reset()
+{
+ spectrum_mface128_base_device::device_reset();
+ m_centronics->write_strobe(1);
}
@@ -172,31 +509,63 @@ void spectrum_mface1_device::device_reset()
// IMPLEMENTATION
//**************************************************************************
-READ_LINE_MEMBER(spectrum_mface1_device::romcs)
+bool spectrum_mface_base_device::romcs()
{
- return m_romcs | m_exp->romcs();
+ return m_romcs || m_exp->romcs();
}
-void spectrum_mface1_device::pre_opcode_fetch(offs_t offset)
+void spectrum_mface_base_device::pre_opcode_fetch(offs_t offset)
{
m_exp->pre_opcode_fetch(offset);
if (!machine().side_effects_disabled())
{
- if (offset == 0x0066)
+ if (offset == 0x0066 && m_nmi_pending)
m_romcs = 1;
}
}
-uint8_t spectrum_mface1_device::iorq_r(offs_t offset)
+void spectrum_mface128_device::pre_opcode_fetch(offs_t offset)
+{
+ // pass-thru pin a15 is controlled by some extra logic on v2 pcb
+ m_exp->pre_opcode_fetch((m_nmi_pending || m_romcs) ? offset | 0x8000 : offset);
+
+ if (!machine().side_effects_disabled())
+ {
+ if (offset == 0x0066 && m_nmi_pending)
+ m_romcs = 1;
+ }
+}
+
+void spectrum_mprint_device::pre_opcode_fetch(offs_t offset)
+{
+ m_exp->pre_opcode_fetch(offset);
+
+ if (!machine().side_effects_disabled())
+ {
+ if (offset == 0x0066 && m_nmi_pending)
+ m_romcs = 1;
+
+ // todo: must be some other hooks here...
+ // at least LPRINT, LLIST and COPY should be caught
+ // also unique REM xx commands
+ // menu should pop up for LPRINT and REM MP
+ }
+}
+
+uint8_t spectrum_mface1v2_device::iorq_r(offs_t offset)
{
uint8_t data = m_exp->iorq_r(offset);
if (!machine().side_effects_disabled())
{
- switch (offset & 0xff)
+ switch (offset & 0xff) // real decodes tbc...
{
case 0x1f:
+ if (!(m_hwconfig->read() & 0x02))
+ data = m_joy->read() & 0x1f;
+ break;
+ case 0x5f:
m_romcs = 0;
break;
case 0x9f:
@@ -207,20 +576,92 @@ uint8_t spectrum_mface1_device::iorq_r(offs_t offset)
return data;
}
-uint8_t spectrum_mface128_device::iorq_r(offs_t offset)
+uint8_t spectrum_mface1v3_device::iorq_r(offs_t offset)
{
uint8_t data = m_exp->iorq_r(offset);
if (!machine().side_effects_disabled())
{
- switch (offset & 0xff)
+ switch (offset & 0xff) // real decodes tbc...
{
- case 0xbf:
+ case 0x1f:
+ m_romcs = 0;
+ if (!(m_hwconfig->read() & 0x02))
+ data = m_joy->read() & 0x1f;
+ break;
+ case 0x9f:
m_romcs = 1;
break;
- case 0x3f:
+ }
+ }
+ return data;
+}
+
+uint8_t spectrum_mface1_device::iorq_r(offs_t offset)
+{
+ uint8_t data = m_exp->iorq_r(offset);
+
+ if (m_hwconfig->read() & 0x01) // disable switch
+ return data;
+
+ if (!machine().side_effects_disabled())
+ {
+ switch (offset & 0xf2) // -001 --1-
+ {
+ case 0x12: // 0001 --1- uses 0x1f
+ m_romcs = 0;
+ if (!(m_hwconfig->read() & 0x02))
+ data = m_joy->read() & 0x1f;
+ break;
+ case 0x92: // 1001 --1- uses 0x9f
+ m_romcs = 1;
+ break;
+ }
+ }
+ return data;
+}
+
+uint8_t spectrum_mface128v1_device::iorq_r(offs_t offset)
+{
+ uint8_t data = m_exp->iorq_r(offset);
+
+ if (!machine().side_effects_disabled())
+ {
+ switch (offset & 0xf0) // -001 ----
+ {
+ case 0x10: // 0001 ---- uses 0x1f
m_romcs = 0;
break;
+ case 0x90: // 1001 ---- uses 0x9f
+ if (!m_hidden)
+ {
+ m_romcs = 1;
+ data = (data & 0x7f) | (m_d3_ff << 7);
+ }
+ break;
+ }
+ }
+ return data;
+}
+
+uint8_t spectrum_mface128_device::iorq_r(offs_t offset)
+{
+ uint8_t data = m_exp->iorq_r(offset);
+
+ if (!machine().side_effects_disabled())
+ {
+ switch (offset & 0xf4) // -011 -1--
+ {
+ case 0x34: // 0011 -1-- uses 0x3f
+ m_romcs = 0;
+ break;
+ case 0xb4: // 1011 -1-- uses 0xbf
+ if (!m_hidden)
+ {
+ m_romcs = 1;
+ data = (data & 0x7f) | (m_d3_ff << 7);
+ }
+ break;
}
}
return data;
@@ -232,16 +673,26 @@ uint8_t spectrum_mface3_device::iorq_r(offs_t offset)
if (!machine().side_effects_disabled())
{
- switch (offset & 0xff)
+ switch (offset & 0xff) // fully decoded by PAL16L8
{
case 0x3f:
- m_romcs = 1;
+ if (!m_hidden)
+ m_romcs = 1;
break;
case 0xbf:
m_romcs = 0;
break;
}
}
+
+ // mface3 monitors writes to the +3 memory ctrl registers (ports 1ffd, 7ffd)
+ // keeps copies of the low nibbles in a 74LS670 4x4 register file
+ if ((offset & 0x7f) == 0x3f && !m_hidden)
+ {
+ data = 0xf0; // get stored copy of 1ffd, 7ffd
+ data |= m_reg_file[(offset >> 13) & 3] & 0xf;
+ }
+
return data;
}
@@ -251,25 +702,148 @@ uint8_t spectrum_mprint_device::iorq_r(offs_t offset)
if (!machine().side_effects_disabled())
{
- switch (offset & 0xff)
+ switch (offset & 0xff) // real decodes tbc...
{
- case 0xbb:
- m_romcs = 1;
- break;
case 0xbf:
m_romcs = 0;
break;
+ case 0xbb:
+ if (!m_hidden)
+ m_romcs = 1;
+ data &= ~0x40;
+ data |= m_busy << 6;
+ break;
}
}
return data;
}
+void spectrum_mface1v2_device::iorq_w(offs_t offset, uint8_t data)
+{
+ if ((offset & 0xff) == 0x5f) // real decodes tbc...
+ nmi(CLEAR_LINE);
+
+ m_exp->iorq_w(offset, data);
+}
+
+void spectrum_mface1v3_device::iorq_w(offs_t offset, uint8_t data)
+{
+ if ((offset & 0xff) == 0x1f) // real decodes tbc...
+ nmi(CLEAR_LINE);
+
+ m_exp->iorq_w(offset, data);
+}
+
void spectrum_mface1_device::iorq_w(offs_t offset, uint8_t data)
{
+ if ((offset & 0xf2) == 0x12) // 0001 --1- uses 0x1f
+ nmi(CLEAR_LINE);
+
+ m_exp->iorq_w(offset, data);
+}
+
+void spectrum_mface128v1_device::iorq_w(offs_t offset, uint8_t data)
+{
+ switch (offset & 0xf0) // -001 ----
+ {
+ case 0x10: // 0001 ---- uses 0x1f
+ m_hidden = 1;
+ [[fallthrough]];
+ case 0x90: // 1001 ---- uses 0x9f
+ nmi(CLEAR_LINE);
+ break;
+ }
+
+ // mface128 monitors writes to the 128K memory ctrl register (port 7ffd)
+ // keeps a copy of D3 (screen select bit) in a D flip-flop
+ if ((offset & 0x8002) == 0) // 0--- ---- ---- --0- uses 7ffd
+ m_d3_ff = (data >> 3) & 1;
+
+ m_exp->iorq_w(offset, data);
+}
+
+void spectrum_mface128_device::iorq_w(offs_t offset, uint8_t data)
+{
+ switch (offset & 0xf4) // -011 -1--
+ {
+ case 0x34: // 0011 -1-- uses 0x3f
+ m_hidden = 1;
+ [[fallthrough]];
+ case 0xb4: // 1011 -1-- uses 0xbf
+ nmi(CLEAR_LINE);
+ break;
+ }
+
+ // mface128 monitors writes to the 128K memory ctrl register (port 7ffd)
+ // keeps a copy of D3 (screen select bit) in a D flip-flop
+ if ((offset & 0x8002) == 0) // 0--- ---- ---- --0- uses 7ffd
+ m_d3_ff = (data >> 3) & 1;
+
+ m_exp->iorq_w(offset, data);
+}
+
+void spectrum_mface3_device::iorq_w(offs_t offset, uint8_t data)
+{
+ switch (offset & 0xff) // fully decoded by PAL16L8
+ {
+ case 0x3f:
+ m_hidden = 1; // also Hard Micro clone: D0 is 16KB rom msb (unused)
+ [[fallthrough]];
+ case 0xbf:
+ nmi(CLEAR_LINE);
+ break;
+ }
+
+ // mface3 monitors writes to the +3 memory ctrl registers (ports 1ffd, 7ffd)
+ // keeps copies of the low nibbles in a 74LS670 4x4 register file
+ if ((offset & 0x90fd) == 0x10fd)
+ m_reg_file[(offset >> 13) & 3] = data & 0x0f;
+
+ // also disables itself if special paging mode bit is set (CP/M)
+ if ((offset & 0xf0fd) == 0x10fd)
+ m_disable = data & 1;
+
+ m_exp->iorq_w(offset, data);
+}
+
+void spectrum_mprint_device::iorq_w(offs_t offset, uint8_t data)
+{
+ // write_strobe is fired by wr seq: 0xbf, 0xbb, 0xbf
+ switch (offset & 0xff) // real decodes tbc...
+ {
+ case 0xbf:
+ m_centronics->write_data0(BIT(data, 0));
+ m_centronics->write_data1(BIT(data, 1));
+ m_centronics->write_data2(BIT(data, 2));
+ m_centronics->write_data3(BIT(data, 3));
+ m_centronics->write_data4(BIT(data, 4));
+ m_centronics->write_data5(BIT(data, 5));
+ m_centronics->write_data6(BIT(data, 6));
+ m_centronics->write_data7(BIT(data, 7));
+ m_centronics->write_strobe(1);
+ break;
+ case 0xbb:
+ m_centronics->write_strobe(0);
+ break;
+ }
+
+ switch (offset & 0x5ff)
+ {
+ case 0x4bf:
+ nmi(CLEAR_LINE);
+ break;
+ case 0x4fb: // not essential yet, for other hooks?
+ m_hidden = 0;
+ break;
+ case 0x5fb:
+ m_hidden = 1;
+ break;
+ }
+
m_exp->iorq_w(offset, data);
}
-uint8_t spectrum_mface1_device::mreq_r(offs_t offset)
+uint8_t spectrum_mface_base_device::mreq_r(offs_t offset)
{
uint8_t data = 0xff;
@@ -292,7 +866,30 @@ uint8_t spectrum_mface1_device::mreq_r(offs_t offset)
return data;
}
-void spectrum_mface1_device::mreq_w(offs_t offset, uint8_t data)
+uint8_t spectrum_mface1v1_device::mreq_r(offs_t offset)
+{
+ uint8_t data = 0xff;
+
+ if (m_romcs)
+ {
+ switch (offset & 0xe000)
+ {
+ case 0x0000:
+ data = m_rom->base()[offset & 0x1fff];
+ break;
+ case 0x2000:
+ data = m_ram[offset & 0x7ff];
+ break;
+ }
+ }
+
+ if (m_exp->romcs())
+ data &= m_exp->mreq_r(offset);
+
+ return data;
+}
+
+void spectrum_mface_base_device::mreq_w(offs_t offset, uint8_t data)
{
if (m_romcs)
{
@@ -308,14 +905,58 @@ void spectrum_mface1_device::mreq_w(offs_t offset, uint8_t data)
m_exp->mreq_w(offset, data);
}
+void spectrum_mface1v1_device::mreq_w(offs_t offset, uint8_t data)
+{
+ if (m_romcs)
+ {
+ switch (offset & 0xe000)
+ {
+ case 0x2000:
+ m_ram[offset & 0x7ff] = data;
+ break;
+ }
+ }
+
+ if (m_exp->romcs())
+ m_exp->mreq_w(offset, data);
+}
+
+INPUT_CHANGED_MEMBER(spectrum_mface1v2_device::magic_button)
+{
+ if (!newval)
+ {
+ nmi(ASSERT_LINE);
+ }
+}
+
INPUT_CHANGED_MEMBER(spectrum_mface1_device::magic_button)
{
- if (newval && !oldval)
+ if (!newval)
{
- m_slot->nmi_w(ASSERT_LINE);
+ if (!(m_hwconfig->read() & 0x01))
+ {
+ nmi(ASSERT_LINE);
+ }
}
- else
+}
+
+INPUT_CHANGED_MEMBER(spectrum_mface128_base_device::magic_button)
+{
+ if (!newval)
+ {
+ m_hidden = 0;
+ nmi(ASSERT_LINE);
+ }
+}
+
+INPUT_CHANGED_MEMBER(spectrum_mface3_device::magic_button)
+{
+ if (!newval)
{
- m_slot->nmi_w(CLEAR_LINE);
+ if (!m_disable)
+ {
+ m_hidden = 0;
+ nmi(ASSERT_LINE);
+ }
}
}
diff --git a/src/devices/bus/spectrum/mface.h b/src/devices/bus/spectrum/mface.h
index bf286cf9823..9cd172dbdf0 100644
--- a/src/devices/bus/spectrum/mface.h
+++ b/src/devices/bus/spectrum/mface.h
@@ -9,88 +9,234 @@
#define MAME_BUS_SPECTRUM_MFACE_H
#include "exp.h"
-
+#include "bus/centronics/ctronics.h"
//**************************************************************************
// TYPE DEFINITIONS
//**************************************************************************
-class spectrum_mface1_device :
+class spectrum_mface_base_device :
public device_t,
public device_spectrum_expansion_interface
-
{
public:
// construction/destruction
- spectrum_mface1_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
+ spectrum_mface_base_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
- DECLARE_INPUT_CHANGED_MEMBER(magic_button);
+ virtual DECLARE_INPUT_CHANGED_MEMBER(magic_button) { m_slot->nmi_w(newval ? CLEAR_LINE : ASSERT_LINE); }
protected:
- spectrum_mface1_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock);
+ spectrum_mface_base_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_start() override ATTR_COLD;
+ virtual void device_reset() override ATTR_COLD;
// 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 void device_add_mconfig(machine_config &config) override ATTR_COLD;
+ virtual ioport_constructor device_input_ports() const override ATTR_COLD;
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 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); }
+ 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 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); }
+
+ void nmi(line_state state) { m_slot->nmi_w(state); m_nmi_pending = state; }
required_memory_region m_rom;
required_device<spectrum_expansion_slot_device> m_exp;
- uint8_t m_ram[8 * 1024];
- int m_romcs;
+ bool m_romcs;
+ int m_nmi_pending;
+ std::unique_ptr<uint8_t[]> m_ram;
+};
+
+class spectrum_mface1v2_device : public spectrum_mface_base_device
+{
+public:
+ spectrum_mface1v2_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
+
+ DECLARE_INPUT_CHANGED_MEMBER(magic_button) override;
+
+protected:
+ spectrum_mface1v2_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 ATTR_COLD;
+
+ // optional information overrides
+ virtual const tiny_rom_entry *device_rom_region() const override ATTR_COLD;
+ virtual ioport_constructor device_input_ports() const override ATTR_COLD;
+
+ virtual uint8_t iorq_r(offs_t offset) override;
+ virtual void iorq_w(offs_t offset, uint8_t data) override;
+
+ required_ioport m_joy;
+ required_ioport m_hwconfig;
+};
+
+class spectrum_mface1v1_device : public spectrum_mface1v2_device
+{
+public:
+ spectrum_mface1v1_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
+
+protected:
+ // device-level overrides
+ virtual void device_start() override ATTR_COLD;
+
+ // optional information overrides
+ virtual const tiny_rom_entry *device_rom_region() const override ATTR_COLD;
+
+ virtual uint8_t mreq_r(offs_t offset) override;
+ virtual void mreq_w(offs_t offset, uint8_t data) override;
+};
+
+class spectrum_mface1v3_device : public spectrum_mface1v2_device
+{
+public:
+ spectrum_mface1v3_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
+
+protected:
+ spectrum_mface1v3_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock);
+
+ // optional information overrides
+ virtual const tiny_rom_entry *device_rom_region() const override ATTR_COLD;
+
+ virtual uint8_t iorq_r(offs_t offset) override;
+ virtual void iorq_w(offs_t offset, uint8_t data) override;
};
-class spectrum_mface128_device : public spectrum_mface1_device
+class spectrum_mface1_device : public spectrum_mface1v3_device
+{
+public:
+ spectrum_mface1_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
+
+ DECLARE_INPUT_CHANGED_MEMBER(magic_button) override;
+
+protected:
+ // optional information overrides
+ virtual const tiny_rom_entry *device_rom_region() const override ATTR_COLD;
+ virtual ioport_constructor device_input_ports() const override ATTR_COLD;
+
+ virtual uint8_t iorq_r(offs_t offset) override;
+ virtual void iorq_w(offs_t offset, uint8_t data) override;
+};
+
+class spectrum_mface128_base_device : public spectrum_mface_base_device
+{
+public:
+ spectrum_mface128_base_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
+
+ DECLARE_INPUT_CHANGED_MEMBER(magic_button) override;
+
+protected:
+ spectrum_mface128_base_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 ATTR_COLD;
+ virtual void device_reset() override ATTR_COLD;
+
+ int m_hidden;
+};
+
+class spectrum_mface128v1_device : public spectrum_mface128_base_device
+{
+public:
+ spectrum_mface128v1_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
+
+protected:
+ spectrum_mface128v1_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 ATTR_COLD;
+
+ // optional information overrides
+ virtual const tiny_rom_entry *device_rom_region() const override ATTR_COLD;
+
+ virtual uint8_t iorq_r(offs_t offset) override;
+ virtual void iorq_w(offs_t offset, uint8_t data) override;
+
+ int m_d3_ff; // no initial state
+};
+
+class spectrum_mface128_device : public spectrum_mface128v1_device
{
public:
spectrum_mface128_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
protected:
// optional information overrides
- virtual const tiny_rom_entry *device_rom_region() const override;
+ virtual const tiny_rom_entry *device_rom_region() const override ATTR_COLD;
+ virtual void pre_opcode_fetch(offs_t offset) override;
virtual uint8_t iorq_r(offs_t offset) override;
+ virtual void iorq_w(offs_t offset, uint8_t data) override;
};
-class spectrum_mface3_device : public spectrum_mface1_device
+class spectrum_mface3_device : public spectrum_mface128_base_device
{
public:
spectrum_mface3_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
+ DECLARE_INPUT_CHANGED_MEMBER(magic_button) override;
+
protected:
+ // device-level overrides
+ virtual void device_start() override ATTR_COLD;
+ virtual void device_reset() override ATTR_COLD;
+
// optional information overrides
- virtual const tiny_rom_entry *device_rom_region() const override;
+ virtual void device_add_mconfig(machine_config &config) override ATTR_COLD;
+ virtual const tiny_rom_entry *device_rom_region() const override ATTR_COLD;
virtual uint8_t iorq_r(offs_t offset) override;
+ virtual void iorq_w(offs_t offset, uint8_t data) override;
+
+private:
+ uint8_t m_reg_file[4]; // no initial state
+ int m_disable;
};
-class spectrum_mprint_device : public spectrum_mface1_device
+class spectrum_mprint_device : public spectrum_mface128_base_device
{
public:
spectrum_mprint_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
protected:
+ // device-level overrides
+ virtual void device_start() override ATTR_COLD;
+ virtual void device_reset() override ATTR_COLD;
+
// optional information overrides
- virtual const tiny_rom_entry *device_rom_region() const override;
+ virtual void device_add_mconfig(machine_config &config) override ATTR_COLD;
+ virtual const tiny_rom_entry *device_rom_region() const override ATTR_COLD;
+ virtual void pre_opcode_fetch(offs_t offset) override;
virtual uint8_t iorq_r(offs_t offset) override;
+ virtual void iorq_w(offs_t offset, uint8_t data) override;
+
+private:
+ void busy_w(int state) { m_busy = state; }
+
+ required_device<centronics_device> m_centronics;
+
+ int m_busy;
};
// device type definition
+DECLARE_DEVICE_TYPE(SPECTRUM_MFACE1V1, spectrum_mface1v1_device)
+DECLARE_DEVICE_TYPE(SPECTRUM_MFACE1V2, spectrum_mface1v2_device)
+DECLARE_DEVICE_TYPE(SPECTRUM_MFACE1V3, spectrum_mface1v3_device)
DECLARE_DEVICE_TYPE(SPECTRUM_MFACE1, spectrum_mface1_device)
+DECLARE_DEVICE_TYPE(SPECTRUM_MFACE128V1, spectrum_mface128v1_device)
DECLARE_DEVICE_TYPE(SPECTRUM_MFACE128, spectrum_mface128_device)
DECLARE_DEVICE_TYPE(SPECTRUM_MFACE3, spectrum_mface3_device)
DECLARE_DEVICE_TYPE(SPECTRUM_MPRINT, spectrum_mprint_device)
diff --git a/src/devices/bus/spectrum/mgt.cpp b/src/devices/bus/spectrum/mgt.cpp
new file mode 100644
index 00000000000..b196a88a1f7
--- /dev/null
+++ b/src/devices/bus/spectrum/mgt.cpp
@@ -0,0 +1,725 @@
+// license:BSD-3-Clause
+// copyright-holders:TwistedTom
+/**********************************************************************
+
+ DISCiPLE Multi-purpose Interface
+ +D Disk and Printer Interface
+
+ Miles Gordon Technology, UK, 1986-1990 (also produced the Sam Coupé home computer.)
+
+ DISCiPLE was MGT's first disk interface, a large plastic base that sat under the Spectrum, similar to Sinclair's official Interface 1.
+ +D was MGT's second (and last) disk interface, a cost and feature reduced version of the Disciple, a small metal-cased,
+ stand-alone unit which connects to ZX Spectrum's expansion slot via a ribbon cable.
+ A second Datel version of the +D exists (following the closure of MGT, it was licensed and produced by Datel.)
+ Many unofficial versions of +D exist and modern versions are still seen today as DIY-style projects/kits.
+ It's said the device's design and roms were officially released into the public domain at some point?
+
+ DISCiPLE features:
+ 8KB ROM
+ 8KB RAM
+ single floppy disk interface (2 drives)
+ Centronics parallel printer interface
+ "magic button" style memory snapshot grabber
+ 2 ATARI joystick ports (Sinclair 1/Kempston, Sinclair 2)
+ 2 network connectors (Interface 1 compatible, 3.5mm mono jack)
+ inhibit button (to lock out the interface)
+ pass-through expansion connector (to chain other devices)
+
+ +D features:
+ same as DISCiPLE
+ lost the joystick/network ports, inhibit button and pass-through expansion connector
+
+ DISCiPLE's official DOS was "GDOS".
+ +D's official DOS was "G+DOS".
+ Both of these were later superseded by "SAM DOS" (used by MGT's Sam Coupé.)
+ A 3rd party company SD Software released an alternative DOS "UNI-DOS" for both interfaces. (consisting of a disk and replacement ROM)
+
+ FDD support:
+
+ DISCiPLE's manual states any Shugart 400 SD/DD drive should work:
+ "The disciple will accept 5.25" or 3.5" drives, whether they are 40 track or 80 track,
+ single sided or double sided, single density or double density."
+
+ +D's manual states any Shugart 400 DD drive should work (but not SD)
+ "we recommend 3.5" or 5.25" 80-track double sided and double density drives,
+ which will give you up to 780K of storage per drive. But Shugart
+ 400-type 3" drives will also work."
+
+ +D only: Pin 26 /DDEN of the WD1772 is tied to ground, so permanent DD mode.
+ DISCiPLE only: /DDEN can be directly controlled via s/w by an IO write to 0x1f, bit 2.
+
+ Disks use "MGT filesystem".
+ A good description available at https://faqwiki.zxnet.co.uk/wiki/MGT_filesystem
+
+ Disk format is 512 bytes/sector, 10 sectors/track
+ 40 track, 1 side = 204,800 bytes (512*10*40*1)
+ 40 track, 2 side = 409,600 bytes
+ 80 track, 1 side = 409,600 bytes
+ 80 track, 2 side = 819,200 bytes <-- only this one supported so far
+
+ .mgt files work ok
+ .img files don't work (not in coupedsk.cpp)
+
+ The DOS must be loaded from a "System Disk" which is itself created from "System Tape" which was supplied with the unit.
+ The ROM provides just the RUN command, which boots the system disk and loads the full DOS.
+ Presumably the unit wasn't supplied with a system disk due to wide range of drives that can be used? (3", 3.5", 5.25")
+ The DOS survives a reset, so reloading of system disk is only required after full power cycle.
+
+ A few useful commands:
+ RUN Boots the system
+ CAT 1 Displays catalogue (drive 1)
+ CAT 1! Displays shortened catalogue (drive 1)
+ SAVE D1 "filename" Saves file
+ VERIFY D1 "filename" Confirms save has been made
+ LOAD D1 "filename" Loads file (except Snapshot files)
+ LOAD D1 "filename" S Loads 48K Snapshot file
+ LOAD D1 "filename" K Loads 128K Snapshot file
+ LOAD D1 "filename" SCREEN$ Loads screen file
+ LOAD Pn Loads the program (from its number)
+ ERASE D1 "file" TO "new file" Renames a file
+ ERASE D1 "filename" Erases a file
+ SAVE D1 "file" TO D2 Copies a file from drive1 to drive2
+ FORMAT D1 Formats disc in drive 1
+ FORMAT D1 TO 2 Formats drive 1; copies from 2 to 1
+
+ DISCiPLE snapshot button:
+ Caps Shift + button system freezes with a multi-coloured border effect
+ then, key 3 save current SCREEN
+ 4 save 48K PROGRAM
+ 5 save 128K PROGRAM
+ Caps Shift + number saves to drive 2 (or 1 if running from 2)
+
+ +D snapshot button:
+ button system freezes with a multi-coloured border effect (don't need to hold caps shift)
+ then, key 3 save current SCREEN
+ 4 save 48K PROGRAM
+ 5 save 128K PROGRAM
+ X do nothing, return to running program
+ Caps Shift + number saves to drive 2 (or 1 if running from 2)
+
+ DISCiPLE GDOS versions:
+ The rom/system disk versions must match,
+ v2 rom: use system disk/system tape ver 2, 2b, 2c
+ v3 rom: use system disk/system tape ver 3a, 3b or 3d
+
+ +D G+DOS versions:
+ The rom/system disk versions must match,
+ v1 rom: system disk/system tape ver 1
+ v1a rom: system disk/system tape ver 2a
+
+ +D only curiosities:
+ The earliest v1.0 unit has a very crude pcb (no solder resist or silkscreen markings),
+ has various rework modifications (cut tracks, flying wires, piggy-backed chips etc.),
+ the PAL is a 16L6 rather than a 20L8 used in later version (only known dump is bruteforced and converted to gal20v8 target.)
+ details here: https://web.archive.org/web/20171118171054/http://trastero.speccy.org/cosas/JL/PlusD/PlusD-v1-0.html
+
+ from "pick-poke-it" user manual (regarding v1.0 unit):
+ "A few PLUS D users are still using Version 1 of the ROM which was used in PLUS D's sold in December 1987-January 1988.
+ ... check the serial number on the bottom of your PLUS D. If it's a 4-figure number commencing with 1,
+ then you have a PLUS D with the Version 1 ROM."
+
+ DISCiPLE only curiosities:
+ The pass-through expansion connector has 4 extra pins (1 top/bottom each end)
+ so 2x30 pins compared to ususal 2x28 of Spectrum expansion slot.
+ Presumably this was intended for some unique expansion device that never appeared?
+ One of these extra pins can be directly controlled via s/w by an IO write to 0x1f, bit 5.
+ 2 other pins appear to be able to override the /ce signal from PAL ic9 to the rom.
+ 4th pin is unused.
+
+ The design allows for use of a larger 27128 (16KB) rom,
+ with the highest address line A13 controllable via s/w by an IO write to 0x1f, bit 3.
+ No larger roms seem to exist (or perhaps not yet found...?)
+ Some 16KB dumps can be found but these are combined dumps of the 8KB rom and 8KB ram (with the full DOS loaded).
+
+
+ Current status:
+ --------------
+
+ DISCiPLE
+ GDOS v3: all ok
+ GDOS v2: all ok
+ UNIDOS: all ok
+
+ +D
+ G+DOS: all ok
+ UNIDOS: all ok
+
+
+ DISCiPLE and 128K compatibility notes:
+ there is some magic involved and its still not clear how exactly it boots on 128K (but it was confirmed to work on real hardware),
+ currently we assume paging in cannot be triggered for a while after reset.
+
+**********************************************************************/
+
+#include "emu.h"
+#include "mgt.h"
+#include "softlist_dev.h"
+
+#include "formats/coupedsk.h"
+
+
+//**************************************************************************
+// DEVICE DEFINITIONS
+//**************************************************************************
+
+DEFINE_DEVICE_TYPE(SPECTRUM_PLUSD, spectrum_plusd_device, "spectrum_plusd", "MGT +D")
+DEFINE_DEVICE_TYPE(SPECTRUM_DISCIPLE, spectrum_disciple_device, "spectrum_disciple", "MGT DISCiPLE")
+
+//-------------------------------------------------
+// INPUT_PORTS( plusd )
+//-------------------------------------------------
+
+INPUT_PORTS_START(plusd)
+ PORT_START("BUTTON")
+ PORT_BIT(0x01, IP_ACTIVE_LOW, IPT_BUTTON1) PORT_NAME("Snapshot Button") PORT_CODE(KEYCODE_MINUS_PAD) PORT_CHANGED_MEMBER(DEVICE_SELF, FUNC(spectrum_plusd_device::snapshot_button), 0)
+INPUT_PORTS_END
+
+//-------------------------------------------------
+// INPUT_PORTS( disciple )
+//-------------------------------------------------
+
+INPUT_PORTS_START(disciple)
+ PORT_INCLUDE(plusd)
+
+ // Joystick 1 (right-hand) is both Kempston (port 0x1f) and Sinclair 1 (keys 6,7,8,9,0)
+ // Joystick 2 (left-hand) is Sinclair 2 (keys 1,2,3,4,5)
+
+ PORT_START("JOY1") /* Sinclair 1 (keys 6,7,8,9,0) 0xeffe , Kempston 0x1f */
+ PORT_BIT(0x01, IP_ACTIVE_LOW, IPT_BUTTON1) PORT_PLAYER(1) PORT_NAME("Kempston\\Sinclair P1 Button 1")
+ PORT_BIT(0x02, IP_ACTIVE_LOW, IPT_JOYSTICK_UP) PORT_8WAY PORT_PLAYER(1) PORT_NAME("Kempston\\Sinclair P1 Up")
+ PORT_BIT(0x04, IP_ACTIVE_LOW, IPT_JOYSTICK_DOWN) PORT_8WAY PORT_PLAYER(1) PORT_NAME("Kempston\\Sinclair P1 Down")
+ PORT_BIT(0x08, IP_ACTIVE_LOW, IPT_JOYSTICK_RIGHT) PORT_8WAY PORT_PLAYER(1) PORT_NAME("Kempston\\Sinclair P1 Right")
+ PORT_BIT(0x10, IP_ACTIVE_LOW, IPT_JOYSTICK_LEFT) PORT_8WAY PORT_PLAYER(1) PORT_NAME("Kempston\\Sinclair P1 Left")
+
+ PORT_START("JOY2") /* Sinclair 2 (keys 1,2,3,4,5) 0xf7fe */
+ PORT_BIT(0x01, IP_ACTIVE_LOW, IPT_JOYSTICK_LEFT) PORT_8WAY PORT_PLAYER(2) PORT_NAME("Sinclair P2 Left") PORT_CODE(KEYCODE_4_PAD)
+ PORT_BIT(0x02, IP_ACTIVE_LOW, IPT_JOYSTICK_RIGHT) PORT_8WAY PORT_PLAYER(2) PORT_NAME("Sinclair P2 Right") PORT_CODE(KEYCODE_6_PAD)
+ PORT_BIT(0x04, IP_ACTIVE_LOW, IPT_JOYSTICK_DOWN) PORT_8WAY PORT_PLAYER(2) PORT_NAME("Sinclair P2 Down") PORT_CODE(KEYCODE_2_PAD)
+ PORT_BIT(0x08, IP_ACTIVE_LOW, IPT_JOYSTICK_UP) PORT_8WAY PORT_PLAYER(2) PORT_NAME("Sinclair P2 Up") PORT_CODE(KEYCODE_8_PAD)
+ PORT_BIT(0x10, IP_ACTIVE_LOW, IPT_BUTTON1) PORT_PLAYER(2) PORT_NAME("Sinclair P2 Button 1") PORT_CODE(KEYCODE_0_PAD)
+
+ PORT_START("INH")
+ PORT_CONFNAME(0x01, 0x01, "Inhibit Button") PORT_CHANGED_MEMBER(DEVICE_SELF, FUNC(spectrum_disciple_device::inhibit_button), 0)
+ PORT_CONFSETTING(0x01, "Off (Disciple enabled)")
+ PORT_CONFSETTING(0x00, "On (Disciple disabled)")
+INPUT_PORTS_END
+
+//-------------------------------------------------
+// input_ports - device-specific input ports
+//-------------------------------------------------
+
+ioport_constructor spectrum_plusd_device::device_input_ports() const
+{
+ return INPUT_PORTS_NAME(plusd);
+}
+
+ioport_constructor spectrum_disciple_device::device_input_ports() const
+{
+ return INPUT_PORTS_NAME(disciple);
+}
+
+//-------------------------------------------------
+// SLOT_INTERFACE( plusd_floppies )
+//-------------------------------------------------
+
+static void plusd_floppies(device_slot_interface &device)
+{
+ device.option_add("35dd", FLOPPY_35_DD);
+}
+
+//-------------------------------------------------
+// floppy_formats
+//-------------------------------------------------
+
+void spectrum_plusd_device::floppy_formats(format_registration &fr)
+{
+ fr.add_mfm_containers();
+ fr.add(FLOPPY_MGT_FORMAT);
+}
+
+//-------------------------------------------------
+// ROM( plusd )
+//-------------------------------------------------
+
+ROM_START(plusd)
+ ROM_REGION(0x2000, "rom", 0)
+
+ ROM_DEFAULT_BIOS("gdos")
+
+ ROM_SYSTEM_BIOS(0, "gdos", "G+DOS v1a")
+ ROMX_LOAD("plusd_g.rom", 0x0000, 0x2000, CRC(569f7e55) SHA1(6b841dc5797ef7eb219ad455cd1e434ca3b9d30d), ROM_BIOS(0))
+
+ ROM_SYSTEM_BIOS(1, "unidos", "UNI-DOS v2")
+ ROMX_LOAD("plusd_uni.rom", 0x0000, 0x2000, CRC(60920496) SHA1(399c8c7c8335bc59849a2182c32347603fd0288a), ROM_BIOS(1))
+
+ ROM_SYSTEM_BIOS(2, "gdos1", "G+DOS v1")
+ ROMX_LOAD("plusd_g1.rom", 0x0000, 0x2000, CRC(e29c0d41) SHA1(fd7e4557d0080a3532200ce72211eb1b185d7d0a), ROM_BIOS(2))
+
+ ROM_REGION( 0x400, "plds", 0 )
+ ROM_LOAD( "alice_pal20l8.ic4", 0x000, 0x144, CRC(60135856) SHA1(41273f13a3680b29ba84ae1e85829482c783c55e) )
+ ROM_LOAD( "v1_pal16l6.icx", 0x200, 0x157, CRC(77076102) SHA1(5142068ae01ff29979b08e6b322512750fbc6a04) ) // v1.0 pcb, ic ref unknown (no silkscreen on pcb!), gal20v8 target
+ROM_END
+
+//-------------------------------------------------
+// ROM( disciple )
+//-------------------------------------------------
+
+ROM_START(disciple)
+ ROM_REGION(0x2000, "rom", 0)
+
+ ROM_DEFAULT_BIOS("gdos")
+
+ ROM_SYSTEM_BIOS(0, "gdos", "GDOS v3")
+ ROMX_LOAD("disciple_g.rom", 0x0000, 0x2000, CRC(82047489) SHA1(9a75ed4b293f968985be4c9aa893cd88276d1ced), ROM_BIOS(0))
+
+ ROM_SYSTEM_BIOS(1, "gdos2", "GDOS v2")
+ ROMX_LOAD("disciple_g2.rom", 0x0000, 0x2000, CRC(9d971781) SHA1(a03e67e4ee275a85153843f42269fa980875d551), ROM_BIOS(1))
+
+ ROM_SYSTEM_BIOS(2, "unidos", "UNI-DOS v2")
+ ROMX_LOAD("disciple_uni.rom", 0x0000, 0x2000, CRC(1fe7f4fa) SHA1(6277abe6358c99ab894795536a1eb9393f25b9b1), ROM_BIOS(2))
+
+ ROM_REGION( 0x400, "plds", 0 )
+ ROM_LOAD( "pal20l8.ic8", 0x000, 0x144, CRC(e53b2fcc) SHA1(85ce9634890d41be37cd9e0252698e5350a4c9c9) )
+ ROM_LOAD( "pal20l8.ic9", 0x200, 0x144, CRC(43ff2e38) SHA1(b872377ea9f91b29a811b0d484699ffe87bdf9fd) )
+ROM_END
+
+//-------------------------------------------------
+// device_add_mconfig - add device configuration
+//-------------------------------------------------
+
+void spectrum_plusd_device::device_add_mconfig(machine_config &config)
+{
+ WD1772(config, m_fdc, 8_MHz_XTAL);
+ FLOPPY_CONNECTOR(config, "fdc:0", plusd_floppies, "35dd", spectrum_plusd_device::floppy_formats).enable_sound(true);
+ FLOPPY_CONNECTOR(config, "fdc:1", plusd_floppies, "35dd", spectrum_plusd_device::floppy_formats).enable_sound(true);
+
+ /* printer port */
+ CENTRONICS(config, m_centronics, centronics_devices, "printer");
+ m_centronics->busy_handler().set(FUNC(spectrum_plusd_device::busy_w));
+
+ /* software list */
+ SOFTWARE_LIST(config, "flop_list").set_original("spectrum_mgt_flop");
+}
+
+void spectrum_disciple_device::device_add_mconfig(machine_config &config)
+{
+ spectrum_plusd_device::device_add_mconfig(config);
+
+ /* pass-through */
+ 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));
+}
+
+const tiny_rom_entry *spectrum_plusd_device::device_rom_region() const
+{
+ return ROM_NAME(plusd);
+}
+
+const tiny_rom_entry *spectrum_disciple_device::device_rom_region() const
+{
+ return ROM_NAME(disciple);
+}
+
+//**************************************************************************
+// LIVE DEVICE
+//**************************************************************************
+
+//-------------------------------------------------
+// spectrum_plusd_device - constructor
+//-------------------------------------------------
+
+spectrum_plusd_device::spectrum_plusd_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_spectrum_expansion_interface(mconfig, *this)
+ , m_rom(*this, "rom")
+ , m_fdc(*this, "fdc")
+ , m_floppy(*this, "fdc:%u", 0)
+ , m_centronics(*this, "centronics")
+ , m_centronics_busy(false)
+{
+}
+
+spectrum_plusd_device::spectrum_plusd_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
+ : spectrum_plusd_device(mconfig, SPECTRUM_PLUSD, tag, owner, clock)
+{
+}
+
+//-------------------------------------------------
+// spectrum_disciple_device - constructor
+//-------------------------------------------------
+
+spectrum_disciple_device::spectrum_disciple_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
+ : spectrum_plusd_device(mconfig, SPECTRUM_DISCIPLE, tag, owner, clock)
+ , m_exp(*this, "exp")
+ , m_joy1(*this, "JOY1")
+ , m_joy2(*this, "JOY2")
+ , m_inhibit(*this, "INH")
+ , m_control(0) // CHECKME: what is 74LS374 power-on state ?
+{
+}
+
+//-------------------------------------------------
+// device_start - device-specific startup
+//-------------------------------------------------
+
+void spectrum_plusd_device::device_start()
+{
+ m_romcs = 0;
+ std::fill(std::begin(m_ram), std::end(m_ram), 0);
+ save_item(NAME(m_romcs));
+ save_item(NAME(m_ram));
+ save_item(NAME(m_centronics_busy));
+}
+
+void spectrum_disciple_device::device_start()
+{
+ spectrum_plusd_device::device_start();
+ save_item(NAME(m_map));
+ save_item(NAME(m_control));
+ save_item(NAME(m_reset_delay));
+
+ m_reset_timer = timer_alloc(FUNC(spectrum_disciple_device::reset_tick), this);
+}
+
+//-------------------------------------------------
+// device_reset - device-specific reset
+//-------------------------------------------------
+
+void spectrum_plusd_device::device_reset()
+{
+ m_centronics->write_strobe(0);
+}
+
+void spectrum_disciple_device::device_reset()
+{
+ m_romcs = 0;
+ m_map = false;
+ m_reset_delay = true;
+ m_reset_timer->adjust(attotime::from_usec(10)); // delay time is a guess
+}
+
+//**************************************************************************
+// IMPLEMENTATION spectrum_plusd_device
+//**************************************************************************
+
+bool spectrum_plusd_device::romcs()
+{
+ return m_romcs;
+}
+
+void spectrum_plusd_device::pre_opcode_fetch(offs_t offset)
+{
+ if (!machine().side_effects_disabled())
+ {
+ switch (offset)
+ {
+ case 0x0008:
+ case 0x003a:
+ case 0x0066:
+ m_romcs = 1;
+ break;
+ }
+ }
+}
+
+uint8_t spectrum_plusd_device::iorq_r(offs_t offset)
+{
+ uint8_t data = offset & 1 ? m_slot->fb_r() : 0xff;
+
+ switch (offset & 0x7e) // address lines 0 and 7-15 ignored
+ {
+ case 0x62: // fdc status reg
+ case 0x6a: // fdc track reg
+ case 0x72: // fdc sector reg
+ case 0x7a: // fdc data reg
+ data = m_fdc->read((offset >> 3) & 0x03);
+ break;
+ case 0x66: // page in
+ if (!machine().side_effects_disabled())
+ m_romcs = 1;
+ break;
+ case 0x76: // bit 7: printer busy
+ data = m_centronics_busy ? 0x80 : 0x00;
+ break;
+ }
+
+ return data;
+}
+
+void spectrum_plusd_device::iorq_w(offs_t offset, uint8_t data)
+{
+ switch (offset & 0x7e) // address lines 0 and 7-15 ignored
+ {
+ case 0x62: // fdc command reg
+ case 0x6a: // fdc track reg
+ case 0x72: // fdc sector reg
+ case 0x7a: // fdc data reg
+ m_fdc->write((offset >> 3) & 0x03, data);
+ break;
+ case 0x6e: // bit 0-1: drive select, 6: printer strobe, 7: side select
+ {
+ floppy_image_device* floppy = nullptr;
+ if (data & 1)
+ floppy = m_floppy[0]->get_device();
+ else if (data & 2)
+ floppy = m_floppy[1]->get_device();
+ m_fdc->set_floppy(floppy);
+ m_centronics->write_strobe(BIT(data, 6));
+ if (floppy) floppy->ss_w(BIT(data, 7));
+ }
+ break;
+ case 0x66: // page out
+ m_romcs = 0;
+ break;
+ case 0x76: // printer data
+ m_centronics->write_data0(BIT(data, 0));
+ m_centronics->write_data1(BIT(data, 1));
+ m_centronics->write_data2(BIT(data, 2));
+ m_centronics->write_data3(BIT(data, 3));
+ m_centronics->write_data4(BIT(data, 4));
+ m_centronics->write_data5(BIT(data, 5));
+ m_centronics->write_data6(BIT(data, 6));
+ m_centronics->write_data7(BIT(data, 7));
+ break;
+ }
+}
+
+uint8_t spectrum_plusd_device::mreq_r(offs_t offset)
+{
+ uint8_t data = 0xff;
+
+ if (m_romcs)
+ {
+ switch (offset & 0xe000)
+ {
+ case 0x0000:
+ data = m_rom->base()[offset & 0x1fff];
+ break;
+ case 0x2000:
+ data = m_ram[offset & 0x1fff];
+ break;
+ }
+ }
+
+ return data;
+}
+
+void spectrum_plusd_device::mreq_w(offs_t offset, uint8_t data)
+{
+ if (m_romcs)
+ {
+ switch (offset & 0xe000)
+ {
+ case 0x2000:
+ m_ram[offset & 0x1fff] = data;
+ break;
+ }
+ }
+}
+
+INPUT_CHANGED_MEMBER(spectrum_plusd_device::snapshot_button)
+{
+ if (newval && !oldval)
+ {
+ m_slot->nmi_w(CLEAR_LINE);
+ }
+ else
+ {
+ m_slot->nmi_w(ASSERT_LINE);
+ }
+}
+
+void spectrum_plusd_device::busy_w(int state)
+{
+ m_centronics_busy = state;
+}
+
+//**************************************************************************
+// IMPLEMENTATION spectrum_disciple_device
+//**************************************************************************
+
+bool spectrum_disciple_device::romcs()
+{
+ return m_romcs || m_exp->romcs();
+}
+
+void spectrum_disciple_device::pre_opcode_fetch(offs_t offset)
+{
+ if (m_inhibit->read() || !BIT(m_control, 4)) // when inhibit button pressed - /M1 passthrought might be blocked
+ m_exp->pre_opcode_fetch(offset);
+
+ if (!machine().side_effects_disabled())
+ {
+ switch (offset)
+ {
+ case 0x0001:
+ case 0x0008:
+ case 0x0066:
+ case 0x028e:
+ if (!m_reset_delay && (m_inhibit->read() || BIT(m_control, 4)))
+ m_romcs = 1;
+ break;
+ }
+ }
+}
+
+uint8_t spectrum_disciple_device::iorq_r(offs_t offset)
+{
+ uint8_t data = m_exp->iorq_r(offset);
+
+ switch (offset & 0xff)
+ {
+ case 0x1b: // fdc status reg
+ case 0x5b: // fdc track reg
+ case 0x9b: // fdc sector reg
+ case 0xdb: // fdc data reg
+ data = m_fdc->read((offset >> 6) & 0x03);
+ break;
+ case 0x1f: // bit 0-4: kempston joystick, bit 6: printer busy, bit 7: network
+ data = bitswap<8>(~m_joy1->read(), 7, 6, 5, 0, 1, 2, 4, 3 ) & 0x1f;
+ data |= m_centronics_busy ? 0x00 : 0x40; // inverted by IC10 74ls240
+ // 7: network...
+ break;
+ case 0x7b: // reset boot
+ if (!machine().side_effects_disabled() && !m_reset_delay)
+ m_map = false;
+ break;
+ case 0xbb: // page in
+ if (!machine().side_effects_disabled() && !m_reset_delay && (m_inhibit->read() || BIT(m_control, 4)))
+ m_romcs = 1;
+ break;
+ case 0xfe: // sinclair joysticks
+ if (((offset >> 8) & 16) == 0)
+ data = m_joy1->read() | (0xff ^ 0x1f);
+ if (((offset >> 8) & 8) == 0)
+ data = m_joy2->read() | (0xff ^ 0x1f);
+ break;
+ }
+
+ return data;
+}
+
+void spectrum_disciple_device::iorq_w(offs_t offset, uint8_t data)
+{
+ switch (offset & 0xff)
+ {
+ case 0x1b: // fdc command reg
+ case 0x5b: // fdc track reg
+ case 0x9b: // fdc sector reg
+ case 0xdb: // fdc data reg
+ m_fdc->write((offset >> 6) & 0x03, data);
+ break;
+ case 0x1f: // bit 0: drive select, 1: side select, 2: density, 3: rom bank, 4: inhibit switch control, 5: exp select, 6: printer strobe, 7: network
+ {
+ floppy_image_device* floppy = m_floppy[~data & 1]->get_device();
+ m_fdc->set_floppy(floppy);
+ if (floppy) floppy->ss_w(BIT(data, 1));
+ m_fdc->dden_w(BIT(data, 2));
+ // 3: rom bank...
+ // 4: inhibit switch control...
+ // 5: exp select...
+ m_centronics->write_strobe(BIT(data, 6));
+ // 7: network...
+ m_control = data;
+ if (!m_inhibit->read() && !BIT(m_control, 4))
+ m_romcs = 0;
+ }
+ break;
+ case 0x3b: // wait when net=1
+ // ...
+ break;
+ case 0x7b: // set boot
+ if (!m_reset_delay)
+ m_map = true;
+ break;
+ case 0xbb: // page out
+ if (!m_reset_delay)
+ m_romcs = 0;
+ break;
+ case 0xfb: // printer data
+ m_centronics->write_data0(BIT(data, 0));
+ m_centronics->write_data1(BIT(data, 1));
+ m_centronics->write_data2(BIT(data, 2));
+ m_centronics->write_data3(BIT(data, 3));
+ m_centronics->write_data4(BIT(data, 4));
+ m_centronics->write_data5(BIT(data, 5));
+ m_centronics->write_data6(BIT(data, 6));
+ m_centronics->write_data7(BIT(data, 7));
+ break;
+ }
+
+ m_exp->iorq_w(offset, data);
+}
+
+uint8_t spectrum_disciple_device::mreq_r(offs_t offset)
+{
+ uint8_t data = 0xff;
+
+ if (m_romcs)
+ {
+ if (m_map)
+ {
+ switch (offset & 0xe000)
+ {
+ case 0x0000:
+ data = m_ram[offset & 0x1fff];
+ break;
+ case 0x2000:
+ data = m_rom->base()[offset & 0x1fff];
+ break;
+ }
+ }
+ else
+ {
+ switch (offset & 0xe000)
+ {
+ case 0x0000:
+ data = m_rom->base()[offset & 0x1fff];
+ break;
+ case 0x2000:
+ data = m_ram[offset & 0x1fff];
+ break;
+ }
+ }
+ }
+
+ if (m_exp->romcs())
+ data &= m_exp->mreq_r(offset);
+
+ return data;
+}
+
+void spectrum_disciple_device::mreq_w(offs_t offset, uint8_t data)
+{
+ if (m_romcs)
+ {
+ if (m_map)
+ {
+ switch (offset & 0xe000)
+ {
+ case 0x0000:
+ m_ram[offset & 0x1fff] = data;
+ break;
+ }
+ }
+ else
+ {
+ switch (offset & 0xe000)
+ {
+ case 0x2000:
+ m_ram[offset & 0x1fff] = data;
+ break;
+ }
+ }
+ }
+
+ if (m_exp->romcs())
+ m_exp->mreq_w(offset, data);
+}
+
+TIMER_CALLBACK_MEMBER(spectrum_disciple_device::reset_tick)
+{
+ m_reset_delay = false;
+}
diff --git a/src/devices/bus/spectrum/mgt.h b/src/devices/bus/spectrum/mgt.h
new file mode 100644
index 00000000000..0e3b2a72a79
--- /dev/null
+++ b/src/devices/bus/spectrum/mgt.h
@@ -0,0 +1,111 @@
+// license:BSD-3-Clause
+// copyright-holders:TwistedTom
+/**********************************************************************
+
+ DISCiPLE Multi-purpose Interface
+ +D Disk and Printer Interface
+
+ (Miles Gordon Technology)
+
+**********************************************************************/
+
+#ifndef MAME_BUS_SPECTRUM_MGT_H
+#define MAME_BUS_SPECTRUM_MGT_H
+
+#pragma once
+
+#include "exp.h"
+#include "softlist.h"
+#include "imagedev/floppy.h"
+#include "machine/wd_fdc.h"
+#include "bus/centronics/ctronics.h"
+
+//**************************************************************************
+// TYPE DEFINITIONS
+//**************************************************************************
+
+class spectrum_plusd_device: public device_t, public device_spectrum_expansion_interface
+{
+public:
+ // construction/destruction
+ spectrum_plusd_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
+
+ static void floppy_formats(format_registration &fr);
+ DECLARE_INPUT_CHANGED_MEMBER(snapshot_button);
+
+protected:
+ spectrum_plusd_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 ATTR_COLD;
+ virtual void device_reset() override ATTR_COLD;
+
+ // optional information overrides
+ virtual void device_add_mconfig(machine_config &config) override ATTR_COLD;
+ virtual ioport_constructor device_input_ports() const override ATTR_COLD;
+ virtual const tiny_rom_entry *device_rom_region() const override ATTR_COLD;
+
+ 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 uint8_t iorq_r(offs_t offset) override;
+ virtual void iorq_w(offs_t offset, uint8_t data) override;
+ virtual bool romcs() override;
+
+ 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;
+
+ bool m_romcs;
+ uint8_t m_ram[8 * 1024];
+ bool m_centronics_busy;
+};
+
+class spectrum_disciple_device: public spectrum_plusd_device
+{
+public:
+ // construction/destruction
+ spectrum_disciple_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
+
+ DECLARE_INPUT_CHANGED_MEMBER(inhibit_button) { if (!newval) m_romcs = 0; }
+
+protected:
+ // device-level overrides
+ virtual void device_start() override ATTR_COLD;
+ virtual void device_reset() override ATTR_COLD;
+
+ // optional information overrides
+ virtual void device_add_mconfig(machine_config &config) override ATTR_COLD;
+ virtual ioport_constructor device_input_ports() const override ATTR_COLD;
+ virtual const tiny_rom_entry *device_rom_region() const override ATTR_COLD;
+
+ 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 uint8_t iorq_r(offs_t offset) override;
+ virtual void iorq_w(offs_t offset, uint8_t data) override;
+ virtual bool romcs() override;
+
+ TIMER_CALLBACK_MEMBER(reset_tick);
+
+private:
+ required_device<spectrum_expansion_slot_device> m_exp;
+ required_ioport m_joy1;
+ required_ioport m_joy2;
+ required_ioport m_inhibit;
+
+ bool m_map;
+ u8 m_control;
+ bool m_reset_delay;
+ emu_timer *m_reset_timer;
+};
+
+
+// device type definition
+DECLARE_DEVICE_TYPE(SPECTRUM_PLUSD, spectrum_plusd_device)
+DECLARE_DEVICE_TYPE(SPECTRUM_DISCIPLE, spectrum_disciple_device)
+
+#endif // MAME_BUS_SPECTRUM_MGT_H
diff --git a/src/devices/bus/spectrum/mikroplus.cpp b/src/devices/bus/spectrum/mikroplus.cpp
index 87552f79bf3..76681e372f9 100644
--- a/src/devices/bus/spectrum/mikroplus.cpp
+++ b/src/devices/bus/spectrum/mikroplus.cpp
@@ -91,16 +91,16 @@ void spectrum_mikroplus_device::device_start()
uint8_t spectrum_mikroplus_device::iorq_r(offs_t offset)
{
- uint8_t data = 0xff;
+ uint8_t data = offset & 1 ? m_slot->fb_r() : 0xff;
- if (offset == 0xdf)
+ if ((offset & 0xff) == 0xdf)
{
data = m_joy->read() | (0xff ^ 0x1f);
}
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..2800f5a4c09 100644
--- a/src/devices/bus/spectrum/mikroplus.h
+++ b/src/devices/bus/spectrum/mikroplus.h
@@ -30,13 +30,13 @@ public:
protected:
// device-level overrides
- virtual void device_start() override;
+ virtual void device_start() override ATTR_COLD;
// optional information overrides
- virtual const tiny_rom_entry *device_rom_region() const override;
- virtual ioport_constructor device_input_ports() const override;
+ virtual const tiny_rom_entry *device_rom_region() const override ATTR_COLD;
+ virtual ioport_constructor device_input_ports() const override ATTR_COLD;
- 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
new file mode 100644
index 00000000000..361c4c496b4
--- /dev/null
+++ b/src/devices/bus/spectrum/mpoker.cpp
@@ -0,0 +1,168 @@
+// license:BSD-3-Clause
+// copyright-holders:TwistedTom
+/*********************************************************************
+
+ MICRO-POKEer
+
+ (Micro-Studio, Hungary 1988-1989)
+
+ A back-up/snapshot type device similar to multiface.
+ Saves full ram or screen to tape (normal or high speed)
+ Cheat/poke and jump functions.
+ No pass-through slot.
+
+ Operation:
+ Press freeze button...
+ H: on-screen help
+ space: exit help
+ enter: return
+ r: total ram save
+ R: turbo total ram save
+ s: screen save
+ S: turbo screen save
+ l: turbo screen load
+ L: turbo total ram load
+ w: warm reset
+ m: micro-monitor (poke or jump)
+
+ micro-monitor:
+ black entry box appears...
+ move around with q/a/o/p, enter
+ input address (dec)
+ to jump: j, enter
+ to poke: p, input data (dec), enter (repeats)
+ to quit: q, enter
+
+ normal saves are useable independant of the interface,
+ "turbo" saves need the interface present, must use l or L options to load.
+
+ Lots of info including schematic and rom disassembly:
+ https://bitbandit.org/20141231/disassembling-the-micro-pokeer-rom-firmware/
+
+
+*********************************************************************/
+
+#include "emu.h"
+#include "mpoker.h"
+
+
+/***************************************************************************
+ DEVICE DEFINITIONS
+***************************************************************************/
+
+DEFINE_DEVICE_TYPE(SPECTRUM_MPOKER, spectrum_mpoker_device, "spectrum_mpoker", "MICRO-POKEer")
+
+
+//-------------------------------------------------
+// INPUT_PORTS( mpoker )
+//-------------------------------------------------
+
+INPUT_PORTS_START( mpoker )
+ PORT_START("BUTTON")
+ PORT_BIT(0x01, IP_ACTIVE_LOW, IPT_BUTTON1) PORT_NAME("Freeze Button") PORT_CODE(KEYCODE_PLUS_PAD) PORT_CHANGED_MEMBER(DEVICE_SELF, FUNC(spectrum_mpoker_device::freeze_button), 0)
+INPUT_PORTS_END
+
+
+//-------------------------------------------------
+// input_ports - device-specific input ports
+//-------------------------------------------------
+
+ioport_constructor spectrum_mpoker_device::device_input_ports() const
+{
+ return INPUT_PORTS_NAME(mpoker);
+}
+
+//-------------------------------------------------
+// ROM( mpoker )
+//-------------------------------------------------
+
+ROM_START(mpoker)
+ ROM_REGION(0x2000, "rom", 0) // v1.6
+ ROM_LOAD("mpoker.rom", 0x0000, 0x2000, CRC(11927434) SHA1(fd918519e4bd0eb8220d157a1c3f314669764657))
+ROM_END
+
+//-------------------------------------------------
+// device_add_mconfig - add device configuration
+//-------------------------------------------------
+
+const tiny_rom_entry *spectrum_mpoker_device::device_rom_region() const
+{
+ return ROM_NAME(mpoker);
+}
+
+
+//**************************************************************************
+// LIVE DEVICE
+//**************************************************************************
+
+//-------------------------------------------------
+// spectrum_mpoker_device - constructor
+//-------------------------------------------------
+
+spectrum_mpoker_device::spectrum_mpoker_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
+ : device_t(mconfig, SPECTRUM_MPOKER, tag, owner, clock)
+ , device_spectrum_expansion_interface(mconfig, *this)
+ , m_rom(*this, "rom")
+{
+}
+
+//-------------------------------------------------
+// device_start - device-specific startup
+//-------------------------------------------------
+
+void spectrum_mpoker_device::device_start()
+{
+ save_item(NAME(m_romcs));
+}
+
+//-------------------------------------------------
+// device_reset - device-specific reset
+//-------------------------------------------------
+
+void spectrum_mpoker_device::device_reset()
+{
+ m_romcs = 0;
+}
+
+
+//**************************************************************************
+// IMPLEMENTATION
+//**************************************************************************
+
+bool spectrum_mpoker_device::romcs()
+{
+ return m_romcs;
+}
+
+void spectrum_mpoker_device::iorq_w(offs_t offset, uint8_t data)
+{
+ if ((offset & 0x80) == 0) // 0--- ---- uses 7f
+ {
+ m_romcs = BIT(data, 0);
+ }
+}
+
+uint8_t spectrum_mpoker_device::mreq_r(offs_t offset)
+{
+ uint8_t data = 0xff;
+
+ if (m_romcs)
+ {
+ data = m_rom->base()[offset & 0x1fff];
+ }
+
+ return data;
+}
+
+INPUT_CHANGED_MEMBER(spectrum_mpoker_device::freeze_button)
+{
+ if (newval)
+ {
+ m_slot->nmi_w(CLEAR_LINE);
+ }
+ else
+ {
+ m_romcs = 1;
+ m_slot->nmi_w(ASSERT_LINE);
+ }
+}
diff --git a/src/devices/bus/spectrum/mpoker.h b/src/devices/bus/spectrum/mpoker.h
new file mode 100644
index 00000000000..a04d8c57316
--- /dev/null
+++ b/src/devices/bus/spectrum/mpoker.h
@@ -0,0 +1,49 @@
+// license:BSD-3-Clause
+// copyright-holders:TwistedTom
+/*********************************************************************
+
+ MICRO-POKEer
+
+ (Micro-Studio, Hungary 1988-1989)
+
+*********************************************************************/
+#ifndef MAME_BUS_SPECTRUM_MPOKER_H
+#define MAME_BUS_SPECTRUM_MPOKER_H
+
+#include "exp.h"
+
+
+//**************************************************************************
+// TYPE DEFINITIONS
+//**************************************************************************
+
+class spectrum_mpoker_device : public device_t, public device_spectrum_expansion_interface
+{
+public:
+ // construction/destruction
+ spectrum_mpoker_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
+
+ DECLARE_INPUT_CHANGED_MEMBER(freeze_button);
+
+protected:
+ // device-level overrides
+ virtual void device_start() override ATTR_COLD;
+ virtual void device_reset() override ATTR_COLD;
+
+ // optional information overrides
+ virtual const tiny_rom_entry *device_rom_region() const override ATTR_COLD;
+ virtual ioport_constructor device_input_ports() const override ATTR_COLD;
+
+ virtual uint8_t mreq_r(offs_t offset) override;
+ virtual void iorq_w(offs_t offset, uint8_t data) override;
+ virtual bool romcs() override;
+
+ required_memory_region m_rom;
+
+ bool m_romcs;
+};
+
+// device type definition
+DECLARE_DEVICE_TYPE(SPECTRUM_MPOKER, spectrum_mpoker_device)
+
+#endif // MAME_BUS_SPECTRUM_MPOKER_H
diff --git a/src/devices/bus/spectrum/musicmachine.cpp b/src/devices/bus/spectrum/musicmachine.cpp
new file mode 100644
index 00000000000..f8eb8679bcb
--- /dev/null
+++ b/src/devices/bus/spectrum/musicmachine.cpp
@@ -0,0 +1,149 @@
+// license:BSD-3-Clause
+// copyright-holders:Andrei I. Holub
+/*
+ * The Music Machine - MIDI and sampling expansion
+ * by Ram Electronics Ltd
+ */
+
+#include "emu.h"
+#include "musicmachine.h"
+
+#include "bus/midi/midi.h"
+#include "machine/6850acia.h"
+#include "machine/clock.h"
+#include "sound/dac.h"
+
+#include "speaker.h"
+
+
+namespace {
+
+class spectrum_musicmachine_device : public device_t, public device_spectrum_expansion_interface
+{
+public:
+ // construction/destruction
+ spectrum_musicmachine_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock);
+
+ void write_acia_clock(u8 data);
+
+protected:
+ // 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_spectrum_expansion_interface implementation
+ virtual u8 iorq_r(offs_t offset) override;
+ virtual void iorq_w(offs_t offset, u8 data) override;
+
+private:
+ required_device<acia6850_device> m_acia;
+ required_device<dac_byte_interface> m_dac;
+
+ bool m_irq_select;
+};
+
+
+void spectrum_musicmachine_device::device_add_mconfig(machine_config &config)
+{
+ ACIA6850(config, m_acia).txd_handler().set("mdout", FUNC(midi_port_device::write_txd));
+ m_acia->irq_handler().set(DEVICE_SELF_OWNER, FUNC(spectrum_expansion_slot_device::nmi_w));
+ MIDI_PORT(config, "mdin", midiin_slot, "midiin").rxd_handler().set(m_acia, FUNC(acia6850_device::write_rxd));
+ MIDI_PORT(config, "mdout", midiout_slot, "midiout");
+ clock_device &acia_clock(CLOCK(config, "acia_clock", 31250*16));
+ acia_clock.signal_handler().set(FUNC(spectrum_musicmachine_device::write_acia_clock));
+
+ SPEAKER(config, "speaker").front_center();
+ ZN429E(config, m_dac, 0).add_route(ALL_OUTPUTS, "speaker", 0.2);
+}
+
+
+//**************************************************************************
+// LIVE DEVICE
+//**************************************************************************
+
+spectrum_musicmachine_device::spectrum_musicmachine_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock) :
+ device_t(mconfig, SPECTRUM_MUSICMACHINE, tag, owner, clock)
+ , device_spectrum_expansion_interface(mconfig, *this)
+ , m_acia(*this,"acia")
+ , m_dac(*this,"dac")
+{
+}
+
+//-------------------------------------------------
+// device_start - device-specific startup
+//-------------------------------------------------
+
+void spectrum_musicmachine_device::device_start()
+{
+ save_item(NAME(m_irq_select));
+}
+
+//-------------------------------------------------
+// device_reset - device-specific reset
+//-------------------------------------------------
+
+void spectrum_musicmachine_device::device_reset()
+{
+ m_irq_select = false;
+}
+
+void spectrum_musicmachine_device::write_acia_clock(u8 data)
+{
+ m_acia->write_txc(data);
+ m_acia->write_rxc(data);
+}
+
+u8 spectrum_musicmachine_device::iorq_r(offs_t offset)
+{
+ u8 data = (offset & 1) ? m_slot->fb_r() : 0xff;
+
+ switch (offset & 0xff)
+ {
+ case 0x7f:
+ if ((offset & 0x3ff) == 0x27f)
+ data = m_acia->status_r();
+ else if ((offset & 0x3ff) == 0x37f)
+ data = m_acia->data_r();
+ break;
+ case 0xbf:
+ // TODO ADC_READ
+ break;
+ case 0xdf:
+ // TODO Strobe: ADC_START
+ break;
+ }
+
+ return data;
+}
+
+void spectrum_musicmachine_device::iorq_w(offs_t offset, u8 data)
+{
+ switch (offset & 0xff)
+ {
+ case 0x5f:
+ m_irq_select = data & 1;
+ break;
+ case 0x7f:
+ if ((offset & 0x3ff) == 0x07f)
+ m_acia->control_w(data);
+ else if ((offset & 0x3ff) == 0x17f)
+ m_acia->data_w(data);
+ break;
+ case 0x9f:
+ m_dac->write(data);
+ break;
+ case 0xdf:
+ // TODO Strobe: ADC_START
+ break;
+ }
+}
+
+} // anonymous namespace
+
+
+//**************************************************************************
+// DEVICE DEFINITIONS
+//**************************************************************************
+
+DEFINE_DEVICE_TYPE_PRIVATE(SPECTRUM_MUSICMACHINE, device_spectrum_expansion_interface, spectrum_musicmachine_device, "spectrummusic", "The Music Machine (ZX)")
diff --git a/src/devices/bus/spectrum/musicmachine.h b/src/devices/bus/spectrum/musicmachine.h
new file mode 100644
index 00000000000..59efe6e04e8
--- /dev/null
+++ b/src/devices/bus/spectrum/musicmachine.h
@@ -0,0 +1,20 @@
+// license:BSD-3-Clause
+// copyright-holders:Barry Rodewald
+/*
+ * The Music Machine - MIDI and sampling expansion
+ * by Ram Electronics
+ *
+ * Contains a 6850 AICA, Ferranti ZN429E8 DAC and ZN449 ADC
+ */
+
+#ifndef MAME_BUS_SPECTRUM_MUSICMACHINE_H
+#define MAME_BUS_SPECTRUM_MUSICMACHINE_H
+
+#pragma once
+
+#include "exp.h"
+
+
+DECLARE_DEVICE_TYPE(SPECTRUM_MUSICMACHINE, device_spectrum_expansion_interface)
+
+#endif // MAME_BUS_SPECTRUM_MUSICMACHINE_H
diff --git a/src/devices/bus/spectrum/nemoide.cpp b/src/devices/bus/spectrum/nemoide.cpp
new file mode 100644
index 00000000000..75c83bc31fe
--- /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 ATTR_COLD;
+ virtual void device_start() override ATTR_COLD;
+
+private:
+ void map_io(address_map &map) ATTR_COLD;
+
+ 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(0x0011, 0x0011).mirror(0xff00).lrw8(NAME([this]() { return m_ata_data_latch; })
+ , NAME([this](offs_t offset, u8 data) { m_ata_data_latch = data; }));
+ map(0x0010, 0x0010).select(0xffe0).rw(FUNC(nemoide_device::ata_r), FUNC(nemoide_device::ata_w));
+ map(0x00c8, 0x00c8).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(0x0000, 0xffff, *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..b2af6963064
--- /dev/null
+++ b/src/devices/bus/spectrum/nemoide.h
@@ -0,0 +1,14 @@
+// license:BSD-3-Clause
+// copyright-holders:Andrei I. Holub
+
+#ifndef MAME_BUS_SPECTRUM_NEMOIDE_H
+#define MAME_BUS_SPECTRUM_NEMOIDE_H
+
+#pragma once
+
+#include "zxbus.h"
+
+
+DECLARE_DEVICE_TYPE(ZXBUS_NEMOIDE, device_zxbus_card_interface)
+
+#endif // MAME_BUS_SPECTRUM_NEMOIDE_H
diff --git a/src/devices/bus/spectrum/neogs.cpp b/src/devices/bus/spectrum/neogs.cpp
new file mode 100644
index 00000000000..2848523a328
--- /dev/null
+++ b/src/devices/bus/spectrum/neogs.cpp
@@ -0,0 +1,512 @@
+// 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_ram0(*this, "bank_ram0")
+ , m_bank_ram1(*this, "bank_ram1")
+ , 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 ATTR_COLD;
+ virtual void device_reset() override ATTR_COLD;
+ virtual const tiny_rom_entry *device_rom_region() const override ATTR_COLD;
+ virtual void device_add_mconfig(machine_config &config) override ATTR_COLD;
+
+ void neogsmap(address_map &map) ATTR_COLD;
+
+ INTERRUPT_GEN_MEMBER(irq0_line_assert);
+
+ void map_memory(address_map &map) ATTR_COLD;
+ void map_io(address_map &map) ATTR_COLD;
+ 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_ram0;
+ memory_bank_creator m_bank_ram1;
+ memory_view m_view;
+ required_device_array<dac_word_interface, 2> m_dac;
+ required_device<spi_sdcard_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 & 1) // NOROM
+ {
+ if (BIT(m_gscfg0, 3)) // EXPAG
+ {
+ m_bank_ram0->set_entry(((m_mpag << 1) | BIT(m_mpag, 7))% (m_ram->size() / 0x4000));
+ m_bank_ram1->set_entry(((m_mpagx << 1) | BIT(m_mpagx, 7)) % (m_ram->size() / 0x4000));
+ }
+ else
+ {
+ m_bank_ram0->set_entry(((m_mpag << 1) | 0) % (m_ram->size() / 0x4000));
+ m_bank_ram1->set_entry(((m_mpag << 1) | 1) % (m_ram->size() / 0x4000));
+ }
+ 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
+ {
+ // TODO
+ }
+ }
+ 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, 0xbfff).bankrw(m_bank_ram0);
+ m_view[0](0xc000, 0xffff).bankrw(m_bank_ram1);
+ m_view[1](0x0000, 0x3fff).r(FUNC(neogs_device::ram_bank_r<0>));
+ m_view[1](0x8000, 0xbfff).bankrw(m_bank_ram0);
+ m_view[1](0xc000, 0xffff).bankrw(m_bank_ram1);
+}
+
+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->set_prefer_sdhc();
+ m_sdcard->spi_miso_callback().set([this](int state) { m_spi_data_in_latch <<= 1; m_spi_data_in_latch |= state; });
+
+ SPEAKER(config, "speaker", 2).front();
+
+ DAC_16BIT_R2R_TWOS_COMPLEMENT(config, m_dac[0], 0).add_route(ALL_OUTPUTS, "speaker", 0.75, 0); // TDA1543
+ DAC_16BIT_R2R_TWOS_COMPLEMENT(config, m_dac[1], 0).add_route(ALL_OUTPUTS, "speaker", 0.75, 1);
+}
+
+const tiny_rom_entry *neogs_device::device_rom_region() const
+{
+ return ROM_NAME( neogs );
+}
+
+void neogs_device::neogsmap(address_map &map)
+{
+ map(0x00bb, 0x00bb).mirror(0xff00).rw(FUNC(neogs_device::neogs_status_r), FUNC(neogs_device::neogs_command_w));
+ map(0x00b3, 0x00b3).mirror(0xff00).rw(FUNC(neogs_device::neogs_data_r), FUNC(neogs_device::neogs_data_w));
+ map(0x0033, 0x0033).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_ram0->configure_entries(0, m_ram->size() / 0x4000, m_ram->pointer(), 0x4000);
+ m_bank_ram1->configure_entries(0, m_ram->size() / 0x4000, m_ram->pointer(), 0x4000);
+
+ 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();
+
+ save_item(NAME(m_data_in));
+ save_item(NAME(m_data_out));
+ save_item(NAME(m_command_in));
+ save_item(NAME(m_status));
+ save_item(NAME(m_spi_ctrl));
+ save_item(NAME(m_spi_data_out));
+ save_item(NAME(m_spi_data_in_latch));
+ save_item(NAME(m_spi_clock_cycles));
+ save_item(NAME(m_spi_clock_state));
+ save_item(NAME(m_mpag));
+ save_item(NAME(m_mpagx));
+ save_item(NAME(m_gscfg0));
+ save_pointer(NAME(m_vol), 6);
+ save_pointer(NAME(m_sample), 6);
+}
+
+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..6045520e1f7
--- /dev/null
+++ b/src/devices/bus/spectrum/neogs.h
@@ -0,0 +1,14 @@
+// license:BSD-3-Clause
+// copyright-holders:Andrei I. Holub
+
+#ifndef MAME_BUS_SPECTRUM_NEOGS_H
+#define MAME_BUS_SPECTRUM_NEOGS_H
+
+#pragma once
+
+#include "zxbus.h"
+
+
+DECLARE_DEVICE_TYPE(ZXBUS_NEOGS, device_zxbus_card_interface)
+
+#endif // MAME_BUS_SPECTRUM_NEOGS_H
diff --git a/src/devices/bus/spectrum/opus.cpp b/src/devices/bus/spectrum/opus.cpp
index 88eb2deb6a3..fef2107cb72 100644
--- a/src/devices/bus/spectrum/opus.cpp
+++ b/src/devices/bus/spectrum/opus.cpp
@@ -6,9 +6,11 @@
**********************************************************************/
-
#include "emu.h"
#include "opus.h"
+#include "softlist_dev.h"
+
+#include "formats/opd_dsk.h"
//**************************************************************************
@@ -44,9 +46,11 @@ ioport_constructor spectrum_opus_device::device_input_ports() const
// MACHINE_DRIVER( opus )
//-------------------------------------------------
-FLOPPY_FORMATS_MEMBER( spectrum_opus_device::floppy_formats )
- FLOPPY_OPD_FORMAT
-FLOPPY_FORMATS_END
+void spectrum_opus_device::floppy_formats(format_registration &fr)
+{
+ fr.add_mfm_containers();
+ fr.add(FLOPPY_OPD_FORMAT);
+}
static void spectrum_floppies(device_slot_interface &device)
{
@@ -79,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");
@@ -88,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));
@@ -99,6 +103,7 @@ void spectrum_opus_device::device_add_mconfig(machine_config &config)
/* passthru without NMI */
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->fb_r_handler().set(DEVICE_SELF_OWNER, FUNC(spectrum_expansion_slot_device::fb_r));
}
const tiny_rom_entry *spectrum_opus_device::device_rom_region() const
@@ -122,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")
{
@@ -139,7 +143,6 @@ void spectrum_opus_device::device_start()
save_item(NAME(m_romcs));
save_item(NAME(m_ram));
- save_item(NAME(m_last_pc));
}
//-------------------------------------------------
@@ -149,7 +152,6 @@ void spectrum_opus_device::device_start()
void spectrum_opus_device::device_reset()
{
m_romcs = 0;
- m_last_pc = 0x0000;
}
@@ -157,18 +159,18 @@ 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::pre_opcode_fetch(offs_t offset)
+void spectrum_opus_device::post_opcode_fetch(offs_t offset)
{
- m_exp->pre_opcode_fetch(offset);
+ m_exp->post_opcode_fetch(offset);
if (!machine().side_effects_disabled())
{
- switch (m_last_pc)
+ switch (offset)
{
case 0x0008: case 0x0048: case 0x1708:
m_romcs = 1;
@@ -178,7 +180,6 @@ void spectrum_opus_device::pre_opcode_fetch(offs_t offset)
break;
}
}
- m_last_pc = offset;
}
uint8_t spectrum_opus_device::iorq_r(offs_t offset)
@@ -188,16 +189,11 @@ uint8_t spectrum_opus_device::iorq_r(offs_t offset)
// PIA bit 7 is enable joystick and selected on A5 only
if (!BIT(m_pia->a_output(), 7) && (~offset & 0x20))
{
- data &= m_joy->read() & 0x1f;
+ data = m_joy->read() & 0x1f;
}
return data;
}
-void spectrum_opus_device::iorq_w(offs_t offset, uint8_t data)
-{
- m_exp->iorq_w(offset, data);
-}
-
uint8_t spectrum_opus_device::mreq_r(offs_t offset)
{
uint8_t data = 0xff;
@@ -255,13 +251,13 @@ void spectrum_opus_device::mreq_w(offs_t offset, uint8_t data)
m_exp->mreq_w(offset, data);
}
-WRITE8_MEMBER(spectrum_opus_device::pia_out_a)
+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
@@ -272,8 +268,9 @@ WRITE8_MEMBER(spectrum_opus_device::pia_out_a)
m_fdc->dden_w(BIT(data, 5));
}
-WRITE8_MEMBER(spectrum_opus_device::pia_out_b)
+void spectrum_opus_device::pia_out_b(uint8_t data)
{
+ m_centronics->write_data0(BIT(data, 0));
m_centronics->write_data1(BIT(data, 1));
m_centronics->write_data2(BIT(data, 2));
m_centronics->write_data3(BIT(data, 3));
@@ -283,7 +280,7 @@ WRITE8_MEMBER(spectrum_opus_device::pia_out_b)
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 62e4e640b58..d8e2a158481 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
@@ -30,42 +29,45 @@ public:
// construction/destruction
spectrum_opus_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
- DECLARE_FLOPPY_FORMATS(floppy_formats);
+ static void floppy_formats(format_registration &fr);
protected:
// device-level overrides
- virtual void device_start() override;
- virtual void device_reset() override;
+ virtual void device_start() override ATTR_COLD;
+ virtual void device_reset() override ATTR_COLD;
// optional information 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;
+ virtual void device_add_mconfig(machine_config &config) override ATTR_COLD;
+ virtual ioport_constructor device_input_ports() const override ATTR_COLD;
+ virtual const tiny_rom_entry *device_rom_region() const override ATTR_COLD;
- virtual void pre_opcode_fetch(offs_t offset) override;
+ 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 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); }
+ 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 iorq_w(offs_t offset, uint8_t data) override { m_exp->iorq_w(offset, data); }
private:
- DECLARE_WRITE8_MEMBER(pia_out_a);
- DECLARE_WRITE8_MEMBER(pia_out_b);
- DECLARE_WRITE_LINE_MEMBER(busy_w);
+ void pia_out_a(uint8_t data);
+ void pia_out_b(uint8_t data);
+ 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];
- offs_t m_last_pc;
};
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..2a4d659f8f3 100644
--- a/src/devices/bus/spectrum/plus2test.h
+++ b/src/devices/bus/spectrum/plus2test.h
@@ -30,12 +30,12 @@ public:
protected:
// device-level overrides
- virtual void device_start() override;
+ virtual void device_start() override ATTR_COLD;
// optional information overrides
- virtual const tiny_rom_entry *device_rom_region() const override;
+ virtual const tiny_rom_entry *device_rom_region() const override ATTR_COLD;
- 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/protek.cpp b/src/devices/bus/spectrum/protek.cpp
index d1e122d8dbb..6e21268682e 100644
--- a/src/devices/bus/spectrum/protek.cpp
+++ b/src/devices/bus/spectrum/protek.cpp
@@ -74,7 +74,7 @@ void spectrum_protek_device::device_start()
uint8_t spectrum_protek_device::iorq_r(offs_t offset)
{
- uint8_t data = 0xff;
+ uint8_t data = offset & 1 ? m_slot->fb_r() : 0xff;
switch (offset & 0xff)
{
diff --git a/src/devices/bus/spectrum/protek.h b/src/devices/bus/spectrum/protek.h
index 9edd5a82f29..7d29ff46302 100644
--- a/src/devices/bus/spectrum/protek.h
+++ b/src/devices/bus/spectrum/protek.h
@@ -30,10 +30,10 @@ public:
protected:
// device-level overrides
- virtual void device_start() override;
+ virtual void device_start() override ATTR_COLD;
// optional information overrides
- virtual ioport_constructor device_input_ports() const override;
+ virtual ioport_constructor device_input_ports() const override ATTR_COLD;
virtual uint8_t iorq_r(offs_t offset) override;
diff --git a/src/devices/bus/spectrum/sdi.cpp b/src/devices/bus/spectrum/sdi.cpp
new file mode 100644
index 00000000000..fc5e1de2406
--- /dev/null
+++ b/src/devices/bus/spectrum/sdi.cpp
@@ -0,0 +1,159 @@
+// license:BSD-3-Clause
+// copyright-holders:MetalliC
+/*********************************************************************
+
+ SDI - Commodore IEC Bus / VC1541 interface
+ (c) 198? Milan Uroševič, Ivan Gerenčir
+
+ Simple DIY device from Yugoslavian / Slovenian "Moj mikro" magazine.
+ Article scan http://www.zxspectrum.it.omegahg.com/rom/SDI/SDI.pdf
+ Components: i8255, 4K ROM.
+
+ Enter "RANDOMIZE USR 16000" to init / activate interface.
+
+ Notes / TODOs:
+ - floppy drive access doesn't work even with "quantum perfect" host machine config, cause is unknown.
+
+*********************************************************************/
+
+#include "emu.h"
+#include "sdi.h"
+
+
+/***************************************************************************
+ DEVICE DEFINITIONS
+***************************************************************************/
+
+DEFINE_DEVICE_TYPE(SPECTRUM_SDI, spectrum_sdi_device, "spectrum_sdi", "SDI Interface")
+
+
+//-------------------------------------------------
+// ROM( sdi )
+//-------------------------------------------------
+
+ROM_START(sdi)
+ ROM_REGION(0x1000, "rom", 0)
+ ROM_DEFAULT_BIOS("sdiv1")
+
+ ROM_SYSTEM_BIOS(0, "sdiv1", "DOS v1.0")
+ ROMX_LOAD("sdi10.bin", 0x0000, 0x1000, CRC(d0678a71) SHA1(52405bb42e46a12b57806fd7f26691681afe2d8e), ROM_BIOS(0))
+ROM_END
+
+//-------------------------------------------------
+// device_add_mconfig - add device configuration
+//-------------------------------------------------
+
+void spectrum_sdi_device::device_add_mconfig(machine_config &config)
+{
+ I8255(config, m_ppi);
+ m_ppi->in_pc_callback().set(FUNC(spectrum_sdi_device::ppic_r));
+ m_ppi->out_pc_callback().set(FUNC(spectrum_sdi_device::ppic_w));
+
+ cbm_iec_slot_device::add(config, m_iec, "c1541");
+}
+
+const tiny_rom_entry *spectrum_sdi_device::device_rom_region() const
+{
+ return ROM_NAME(sdi);
+}
+
+
+//**************************************************************************
+// LIVE DEVICE
+//**************************************************************************
+
+//-------------------------------------------------
+// spectrum_sdi_device - constructor
+//-------------------------------------------------
+
+spectrum_sdi_device::spectrum_sdi_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
+ : device_t(mconfig, SPECTRUM_SDI, tag, owner, clock)
+ , device_spectrum_expansion_interface(mconfig, *this)
+ , m_rom(*this, "rom")
+ , m_ppi(*this, "ppi")
+ , m_iec(*this, "iec_bus")
+{
+}
+
+//-------------------------------------------------
+// device_start - device-specific startup
+//-------------------------------------------------
+
+void spectrum_sdi_device::device_start()
+{
+ save_item(NAME(m_romcs));
+}
+
+//-------------------------------------------------
+// device_reset - device-specific reset
+//-------------------------------------------------
+
+void spectrum_sdi_device::device_reset()
+{
+ m_romcs = 0;
+ m_iec->reset();
+}
+
+//**************************************************************************
+// IMPLEMENTATION
+//**************************************************************************
+
+bool spectrum_sdi_device::romcs()
+{
+ return m_romcs;
+}
+
+void spectrum_sdi_device::pre_opcode_fetch(offs_t offset)
+{
+ if (!machine().side_effects_disabled())
+ {
+ if ((offset & 0xfc00) == 0x3c00)
+ m_romcs = 1;
+
+ if (offset < 0x3000)
+ m_romcs = 0;
+ }
+}
+
+uint8_t spectrum_sdi_device::mreq_r(offs_t offset)
+{
+ u8 data = 0xff;
+
+ if (m_romcs)
+ data = m_rom->base()[offset & 0xfff];
+
+ return data;
+}
+
+uint8_t spectrum_sdi_device::iorq_r(offs_t offset)
+{
+ uint8_t data = offset & 1 ? m_slot->fb_r() : 0xff;
+
+ if ((offset & 0x9f) == 0x9f)
+ data = m_ppi->read((offset >> 5) & 3);
+
+ return data;
+}
+
+void spectrum_sdi_device::iorq_w(offs_t offset, uint8_t data)
+{
+ if ((offset & 0x9f) == 0x9f)
+ m_ppi->write((offset >> 5) & 3, data);
+}
+
+uint8_t spectrum_sdi_device::ppic_r()
+{
+ u8 data = 0;
+
+ data |= m_iec->clk_r() << 6;
+ data |= m_iec->data_r() << 7;
+
+ return data;
+}
+
+void spectrum_sdi_device::ppic_w(uint8_t data)
+{
+ m_iec->host_atn_w(!BIT(data, 0));
+ m_iec->host_clk_w(!BIT(data, 2));
+ m_iec->host_data_w(!BIT(data, 3));
+}
diff --git a/src/devices/bus/spectrum/sdi.h b/src/devices/bus/spectrum/sdi.h
new file mode 100644
index 00000000000..71e843d3ebb
--- /dev/null
+++ b/src/devices/bus/spectrum/sdi.h
@@ -0,0 +1,61 @@
+// license:BSD-3-Clause
+// copyright-holders:MetalliC
+/*********************************************************************
+
+ SDI Interface
+
+*********************************************************************/
+#ifndef MAME_BUS_SPECTRUM_SDI_H
+#define MAME_BUS_SPECTRUM_SDI_H
+
+#include "exp.h"
+#include "softlist.h"
+#include "machine/i8255.h"
+#include "bus/cbmiec/cbmiec.h"
+
+//**************************************************************************
+// TYPE DEFINITIONS
+//**************************************************************************
+
+class spectrum_sdi_device :
+ public device_t,
+ public device_spectrum_expansion_interface
+
+{
+public:
+ // construction/destruction
+ spectrum_sdi_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 ATTR_COLD;
+ virtual void device_reset() override ATTR_COLD;
+
+ // optional information overrides
+ virtual void device_add_mconfig(machine_config &config) override ATTR_COLD;
+ virtual const tiny_rom_entry *device_rom_region() const override ATTR_COLD;
+
+ virtual void pre_opcode_fetch(offs_t offset) 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;
+
+ required_memory_region m_rom;
+ required_device<i8255_device> m_ppi;
+ required_device<cbm_iec_device> m_iec;
+
+ void ppic_w(uint8_t data);
+ uint8_t ppic_r();
+
+ bool m_romcs;
+};
+
+
+// device type definition
+DECLARE_DEVICE_TYPE(SPECTRUM_SDI, spectrum_sdi_device)
+
+
+#endif // MAME_BUS_SPECTRUM_SDI_H
diff --git a/src/devices/bus/spectrum/sixword.cpp b/src/devices/bus/spectrum/sixword.cpp
new file mode 100644
index 00000000000..7e55410e78b
--- /dev/null
+++ b/src/devices/bus/spectrum/sixword.cpp
@@ -0,0 +1,604 @@
+// license:BSD-3-Clause
+// copyright-holders:MetalliC
+/*********************************************************************
+
+ Swift Disc
+ (c) 1987 SIXWORD ltd (UK)
+
+ WD1770-based floppy drive interface with 8KB RAM and 16KB ROM, serial printer interface, joystick port and "interrupt" button,
+ supports up to 4x 3'5 (normally) or 5"25 drives, 640KB per disk, compatible with ZX Spectrum 128, was positioned as luxury device.
+ For additional charge was available ZX Interface 1 microdrive emulator software (currently missing).
+
+ How to use:
+ Press "Interrupt" button and you'll get into console where you may type commands, like:
+ C[AT] [drive] - list disk contents, drive 0-3
+ D[ATE] [dd-mm-yy] - set current date, or show firmware build date
+ F[ORMAT] diskname - format disk
+ S[AVE] filename - save snapshot to disk
+ L[OAD] filename - load snapshot from disk
+ A[LTER] address data - change value in RAM
+ Q[UIT] - return to BASIC/game
+ * - reset
+ Starting from Swift Disc O/S V2 most of commands may be called from BASIC using syntax like "COMMAND %drive;"filename"", for example:
+ CAT %0
+ LOAD %0;"game"
+ and so on, plus additional commands for sequential file access.
+ FORMAT %#4;"T",1200,79 - printer setup: channel 4, text mode, 1200 baud, 79 column
+
+ Manual: https://k1.spdns.de/Vintage/Sinclair/82/Peripherals/Disc%20Interfaces/SixWord%20Swift%20Disc%20Interface/Swift%20Disc%20Operating%20Manual.pdf
+
+
+ Swift Disc II
+ (c) 1989 SIXWORD ltd (UK)
+
+ Same as above but extended to 32KB ROM, most of discrete ICs replaced with PALs, smaller form factor.
+ Was available in several favours - with serial or parallel printer port.
+ It seems RAM was planned to be extended to 16KB, but 2nd RAM IC is not populated on known devices.
+ Dumped v4.2 firmware supports only 2 disk drives (but PCB still have wired drive 3 and 4 select) and serial port.
+
+ Notes / TODOs:
+ - serial out not working properly with v4.2 ROM, it produce short TX low pulse after each character, which (mistakenly) considered as start bit by current diserial.cpp.
+ - parallel port hookup based on ROM disassembly and may be not accurate (i.e. ports may require to be enabled by some of m_control bits, or something like that)
+
+*********************************************************************/
+
+#include "emu.h"
+#include "sixword.h"
+
+#include "formats/swd_dsk.h"
+
+
+/***************************************************************************
+ DEVICE DEFINITIONS
+***************************************************************************/
+
+DEFINE_DEVICE_TYPE(SPECTRUM_SWIFTDISC, spectrum_swiftdisc_device, "spectrum_swiftdisc", "Swift Disc Interface")
+DEFINE_DEVICE_TYPE(SPECTRUM_SWIFTDISC2, spectrum_swiftdisc2_device, "spectrum_swiftdisc2", "Swift Disc II Interface")
+
+
+//-------------------------------------------------
+// INPUT_PORTS
+//-------------------------------------------------
+
+INPUT_PORTS_START(swiftdisc)
+ PORT_START("BUTTON")
+ PORT_BIT(0x01, IP_ACTIVE_HIGH, IPT_BUTTON1) PORT_NAME("Interrupt Button") PORT_CODE(KEYCODE_MINUS_PAD) PORT_CHANGED_MEMBER(DEVICE_SELF, FUNC(spectrum_swiftdisc_device::nmi_button), 0)
+
+ PORT_START("JOY")
+ PORT_BIT(0x01, IP_ACTIVE_HIGH, IPT_JOYSTICK_RIGHT) PORT_8WAY
+ PORT_BIT(0x02, IP_ACTIVE_HIGH, IPT_JOYSTICK_LEFT) PORT_8WAY
+ PORT_BIT(0x04, IP_ACTIVE_HIGH, IPT_JOYSTICK_DOWN) PORT_8WAY
+ PORT_BIT(0x08, IP_ACTIVE_HIGH, IPT_JOYSTICK_UP) PORT_8WAY
+ PORT_BIT(0x10, IP_ACTIVE_HIGH, IPT_BUTTON1)
+ PORT_BIT(0xe0, IP_ACTIVE_HIGH, IPT_UNUSED)
+INPUT_PORTS_END
+
+INPUT_PORTS_START(swiftdisc2)
+ PORT_INCLUDE(swiftdisc)
+
+ PORT_START("CONF")
+ PORT_CONFNAME(0x01, 0x01, "Printer intrface")
+ PORT_CONFSETTING(0x01, "Serial")
+ PORT_CONFSETTING(0x00, "Parallel")
+INPUT_PORTS_END
+
+//-------------------------------------------------
+// input_ports - device-specific input ports
+//-------------------------------------------------
+
+ioport_constructor spectrum_swiftdisc_device::device_input_ports() const
+{
+ return INPUT_PORTS_NAME(swiftdisc);
+}
+
+ioport_constructor spectrum_swiftdisc2_device::device_input_ports() const
+{
+ return INPUT_PORTS_NAME(swiftdisc2);
+}
+
+//-------------------------------------------------
+// SLOT_INTERFACE( floppies )
+//-------------------------------------------------
+
+static void swiftdisc_floppies(device_slot_interface &device)
+{
+ device.option_add("35dd", FLOPPY_35_DD);
+ device.option_add("525qd", FLOPPY_525_QD);
+}
+
+//-------------------------------------------------
+// floppy_formats
+//-------------------------------------------------
+
+void spectrum_swiftdisc_device::floppy_formats(format_registration &fr)
+{
+ fr.add_mfm_containers();
+ fr.add(FLOPPY_SWD_FORMAT);
+}
+
+//-------------------------------------------------
+// ROM( swiftdisc )
+//-------------------------------------------------
+
+ROM_START(swiftdisc)
+ ROM_REGION(0x4000, "rom", 0)
+ ROM_DEFAULT_BIOS("v34")
+
+ // v2.3 known to exists, not dumped
+ ROM_SYSTEM_BIOS(0, "v24", "v2.4")
+ ROMX_LOAD("24.ic8", 0x0000, 0x4000, CRC(547f660a) SHA1(73a1b96271760fb0edfc1302368372501455bbfc), ROM_BIOS(0))
+ ROM_SYSTEM_BIOS(1, "v34", "v3.4")
+ ROMX_LOAD("34.ic8", 0x0000, 0x4000, CRC(f7092c0c) SHA1(5afe0364afedc83c03995d44914fe7f207fb5c28), ROM_BIOS(1))
+ROM_END
+
+ROM_START(swiftdisc2)
+ ROM_REGION(0x8000, "rom", 0)
+ ROM_DEFAULT_BIOS("v42")
+
+ ROM_SYSTEM_BIOS(0, "v42", "v4.2")
+ ROMX_LOAD("42.bin", 0x0000, 0x8000, CRC(a6fde15b) SHA1(496be6f655974b6162ff430b6ba0c7002164b736), ROM_BIOS(0))
+
+ ROM_REGION(260, "pals", 0)
+ ROM_LOAD("dec1_pal16l8.bin", 0, 260, BAD_DUMP CRC(1433067c) SHA1(a0cf09a86a0d7a71332005bbb04d27d3aa45291c)) // one of logic equations clearly wrong
+ ROM_LOAD("dec2_pal16l8.bin", 0, 260, CRC(4d088879) SHA1(d1d60b38068d457db25f5df304a705999f285fd9))
+ ROM_LOAD("dec3_pal16l8.bin", 0, 260, CRC(8306722c) SHA1(2ad28d44bc33a50ed5f93f2520f25100dd36841d))
+ROM_END
+
+//-------------------------------------------------
+// device_add_mconfig - add device configuration
+//-------------------------------------------------
+
+void spectrum_swiftdisc_device::device_add_mconfig(machine_config &config)
+{
+ WD1770(config, m_fdc, 8_MHz_XTAL);
+ m_fdc->intrq_wr_callback().set(DEVICE_SELF_OWNER, FUNC(spectrum_expansion_slot_device::nmi_w));
+ m_fdc->drq_wr_callback().set(DEVICE_SELF_OWNER, FUNC(spectrum_expansion_slot_device::nmi_w));
+
+ FLOPPY_CONNECTOR(config, "fdc:0", swiftdisc_floppies, "35dd", spectrum_swiftdisc_device::floppy_formats).enable_sound(true);
+ FLOPPY_CONNECTOR(config, "fdc:1", swiftdisc_floppies, "35dd", spectrum_swiftdisc_device::floppy_formats).enable_sound(true);
+ FLOPPY_CONNECTOR(config, "fdc:2", swiftdisc_floppies, nullptr, spectrum_swiftdisc_device::floppy_formats).enable_sound(true);
+ FLOPPY_CONNECTOR(config, "fdc:3", swiftdisc_floppies, nullptr, spectrum_swiftdisc_device::floppy_formats).enable_sound(true);
+
+ RS232_PORT(config, m_rs232, default_rs232_devices, "printer");
+
+ // 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));
+}
+
+void spectrum_swiftdisc2_device::device_add_mconfig(machine_config &config)
+{
+ spectrum_swiftdisc_device::device_add_mconfig(config);
+
+ // parallel printer port
+ CENTRONICS(config, m_centronics, centronics_devices, nullptr);
+ m_centronics->busy_handler().set(FUNC(spectrum_swiftdisc2_device::busy_w));
+}
+
+const tiny_rom_entry *spectrum_swiftdisc_device::device_rom_region() const
+{
+ return ROM_NAME(swiftdisc);
+}
+
+const tiny_rom_entry *spectrum_swiftdisc2_device::device_rom_region() const
+{
+ return ROM_NAME(swiftdisc2);
+}
+
+//**************************************************************************
+// LIVE DEVICE
+//**************************************************************************
+
+//-------------------------------------------------
+// spectrum_swiftdisc_device - constructor
+//-------------------------------------------------
+
+spectrum_swiftdisc_device::spectrum_swiftdisc_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_spectrum_expansion_interface(mconfig, *this)
+ , m_rom(*this, "rom")
+ , m_fdc(*this, "fdc")
+ , m_floppy(*this, "fdc:%u", 0)
+ , m_exp(*this, "exp")
+ , m_rs232(*this, "rs232")
+ , m_joy(*this, "JOY")
+{
+}
+
+spectrum_swiftdisc_device::spectrum_swiftdisc_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
+ : spectrum_swiftdisc_device(mconfig, SPECTRUM_SWIFTDISC, tag, owner, clock)
+{
+}
+
+spectrum_swiftdisc2_device::spectrum_swiftdisc2_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
+ : spectrum_swiftdisc_device(mconfig, SPECTRUM_SWIFTDISC2, tag, owner, clock)
+ , m_centronics(*this, "centronics")
+ , m_conf(*this, "CONF")
+{
+}
+
+
+//-------------------------------------------------
+// device_start - device-specific startup
+//-------------------------------------------------
+
+void spectrum_swiftdisc_device::device_start()
+{
+ memset(m_ram, 0, sizeof(m_ram));
+
+ save_item(NAME(m_romcs));
+ save_item(NAME(m_ram));
+ save_item(NAME(m_rombank));
+ save_item(NAME(m_control));
+}
+
+void spectrum_swiftdisc2_device::device_start()
+{
+ spectrum_swiftdisc_device::device_start();
+ save_item(NAME(m_rambank));
+ save_item(NAME(m_busy));
+ save_item(NAME(m_txd_on));
+}
+
+//-------------------------------------------------
+// device_reset - device-specific reset
+//-------------------------------------------------
+
+void spectrum_swiftdisc_device::device_reset()
+{
+ m_romcs = 0;
+ m_rombank = 0;
+ m_control = 0;
+ m_rs232->write_txd(1);
+}
+
+void spectrum_swiftdisc2_device::device_reset()
+{
+ spectrum_swiftdisc_device::device_reset();
+ m_rambank = 0;
+ m_busy = 0;
+ m_txd_on = 0;
+ m_rs232->write_dtr(1);
+ m_centronics->write_strobe(1);
+}
+
+//**************************************************************************
+// IMPLEMENTATION (swiftdisc)
+//**************************************************************************
+
+bool spectrum_swiftdisc_device::romcs()
+{
+ return m_romcs || m_exp->romcs();
+}
+
+void spectrum_swiftdisc_device::post_opcode_fetch(offs_t offset)
+{
+ m_exp->post_opcode_fetch(offset);
+
+ if (!machine().side_effects_disabled())
+ {
+ switch (offset)
+ {
+ case 0x000b:
+ m_romcs = !m_romcs;
+ break;
+ case 0x0066:
+ if (m_rombank & 0x1000)
+ m_romcs = !m_romcs;
+ break;
+ }
+ }
+}
+
+uint8_t spectrum_swiftdisc_device::mreq_r(offs_t offset)
+{
+ u8 data = 0xff;
+
+ if (m_romcs)
+ {
+ switch (offset & 0xf000)
+ {
+ case 0x0000:
+ data = m_rom->base()[m_rombank + offset];
+ break;
+ case 0x1000:
+ case 0x2000:
+ data = m_ram[offset - 0x1000];
+ break;
+ case 0x3000:
+ if (!BIT(offset, 3))
+ data = m_fdc->read(offset & 3);
+ else
+ {
+ // D0 - RS232 DSR, D1 - RS232 RX
+ data &= ~3;
+ data |= m_rs232->dsr_r() << 0;
+ data |= m_rs232->rxd_r() << 1;
+ }
+ break;
+ }
+ }
+
+ if (m_exp->romcs())
+ data &= m_exp->mreq_r(offset);
+
+ return data;
+}
+
+void spectrum_swiftdisc_device::mreq_w(offs_t offset, uint8_t data)
+{
+ if (m_romcs)
+ {
+ switch (offset & 0xf000)
+ {
+ case 0x0000:
+ if (BIT(offset, 3))
+ m_rombank ^= 0x1000;
+ else
+ {
+ floppy_image_device* floppy = nullptr;
+ for (int i = 3; i >= 0; i--)
+ {
+ floppy_image_device* fl = m_floppy[i]->get_device();
+ if (fl)
+ {
+ fl->ss_w(BIT(data, 4));
+ if (BIT(data, i))
+ floppy = fl;
+ }
+ }
+ m_fdc->set_floppy(floppy);
+
+ m_rombank &= ~0x2000;
+ m_rombank |= BIT(data, 5) << 13;
+
+ // D3 - RS232 /TX
+ m_rs232->write_txd(!BIT(data, 3));
+ m_control = data;
+ }
+ break;
+ case 0x1000:
+ case 0x2000:
+ m_ram[offset - 0x1000] = data;
+ break;
+ case 0x3000:
+ if (!BIT(offset, 3))
+ m_fdc->write(offset & 3, data);
+ break;
+ }
+ }
+
+ if (m_exp->romcs())
+ m_exp->mreq_w(offset, data);
+}
+
+uint8_t spectrum_swiftdisc_device::iorq_r(offs_t offset)
+{
+ uint8_t data = m_exp->iorq_r(offset);
+
+ if (!BIT(offset, 5))
+ data = m_joy->read() & 0x1f;
+
+ return data;
+}
+
+
+//**************************************************************************
+// IMPLEMENTATION (swiftdisc2)
+//**************************************************************************
+
+void spectrum_swiftdisc2_device::post_opcode_fetch(offs_t offset)
+{
+ m_exp->post_opcode_fetch(offset);
+
+ if (!machine().side_effects_disabled())
+ {
+ switch (offset)
+ {
+ case 0x000b:
+ m_romcs = !m_romcs;
+ break;
+ case 0x0066:
+ if (m_rombank & 0x1000)
+ m_romcs = !m_romcs;
+ break;
+ case 0x1709:
+ if (BIT(m_control,2))
+ m_romcs = !m_romcs;
+ break;
+ }
+ }
+}
+
+uint8_t spectrum_swiftdisc2_device::mreq_r(offs_t offset)
+{
+ u8 data = 0xff;
+
+ if (m_romcs)
+ {
+ switch (offset & 0xf000)
+ {
+ case 0x0000:
+ data = m_rom->base()[m_rombank + offset];
+ break;
+ case 0x1000:
+ case 0x2000:
+ if (!m_rambank)
+ data = m_ram[offset - 0x1000];
+ else
+ {
+ data = 0xff; // 2nd RAM IC not populated
+ logerror("Swift2 RAM2 read %04x\n", offset);
+ }
+ break;
+ case 0x3000:
+ if (!BIT(offset, 4))
+ data = m_fdc->read(offset & 3);
+ else
+ data = control_r();
+ break;
+ }
+ }
+
+ if (m_exp->romcs())
+ data &= m_exp->mreq_r(offset);
+
+ return data;
+}
+
+void spectrum_swiftdisc2_device::mreq_w(offs_t offset, uint8_t data)
+{
+ if (m_romcs)
+ {
+ switch (offset & 0xf000)
+ {
+ case 0x0000:
+ if (BIT(offset, 8))
+ m_rambank = !m_rambank;
+ break;
+ case 0x1000:
+ case 0x2000:
+ if (!m_rambank)
+ m_ram[offset - 0x1000] = data;
+ else
+ {
+ // 2nd RAM IC not populated
+ logerror("Swift2 RAM2 write %04x %02x\n", offset, data);
+ }
+ break;
+ case 0x3000:
+ if ((offset & 0x890) == 0)
+ m_fdc->write(offset & 3, data);
+
+ if (BIT(offset, 4))
+ control_w(data);
+ break;
+ }
+ }
+
+ if (m_exp->romcs())
+ m_exp->mreq_w(offset, data);
+}
+
+uint8_t spectrum_swiftdisc2_device::iorq_r(offs_t offset)
+{
+ uint8_t data = m_exp->iorq_r(offset);
+
+ if (m_romcs && (offset & 0xf890) == 0x3000)
+ data = control_r();
+
+ if (!BIT(offset, 5) && !BIT(m_control, 3))
+ data = m_joy->read() & 0x1f;
+
+ if (m_conf->read())
+ {
+ if (BIT(m_control, 2))
+ {
+ if (!BIT(offset, 3)) // port F7
+ {
+ // D7 - RS232 /RX
+ data &= ~0x80;
+ data |= !m_rs232->rxd_r() << 7;
+ }
+ if (!BIT(offset, 4)) // port EF
+ {
+ // D3 - RS232 /DSR
+ data &= ~0x8;
+ data |= !m_rs232->dsr_r() << 3;
+ }
+ }
+ }
+ else
+ {
+ if (!BIT(offset, 3)) // port F7
+ {
+ // D7 - Centronics /BUSY
+ data &= ~0x80;
+ data |= !m_busy << 7;
+ }
+ }
+
+ return data;
+}
+
+void spectrum_swiftdisc2_device::iorq_w(offs_t offset, uint8_t data)
+{
+ if (m_romcs && (offset & 0xf890) == 0x3000)
+ control_w(data);
+
+ if (m_conf->read())
+ {
+ if (BIT(m_control, 2))
+ {
+ if (!BIT(offset, 3)) // port F7
+ {
+ // D0 - RS232 /TX
+ if (m_txd_on)
+ m_rs232->write_txd(!BIT(data, 0));
+ }
+ if (!BIT(offset, 4)) // port EF
+ {
+ // D0 - 0=reset /TX latch (set output to 1)
+ // D4 - RS232 /DTR
+ m_txd_on = BIT(data, 0);
+ if (!m_txd_on)
+ m_rs232->write_txd(1);
+ m_rs232->write_dtr(!BIT(data, 4));
+ }
+ }
+ }
+ else
+ {
+ if (!BIT(offset, 3)) // F7
+ {
+ // D0 - Centronics /STROBE
+ m_centronics->write_strobe(BIT(data, 0));
+ }
+ if (!BIT(offset, 4)) // EF
+ {
+ // D0 - D7 - Centronics data
+ m_centronics->write_data0(BIT(data, 0));
+ m_centronics->write_data1(BIT(data, 1));
+ m_centronics->write_data2(BIT(data, 2));
+ m_centronics->write_data3(BIT(data, 3));
+ m_centronics->write_data4(BIT(data, 4));
+ m_centronics->write_data5(BIT(data, 5));
+ m_centronics->write_data6(BIT(data, 6));
+ m_centronics->write_data7(BIT(data, 7));
+ }
+ }
+
+ m_exp->iorq_w(offset, data);
+}
+
+uint8_t spectrum_swiftdisc2_device::control_r()
+{
+ // D0 - printer interface type, 0 - parallel, 1 - serial
+ return 0xfe | m_conf->read();
+}
+
+void spectrum_swiftdisc2_device::control_w(uint8_t data)
+{
+ floppy_image_device* floppy = nullptr;
+ for (int i = 3; i >= 0; i--)
+ {
+ floppy_image_device* fl = m_floppy[i]->get_device();
+ if (fl)
+ {
+ fl->ss_w(BIT(data, 4));
+ if (!BIT(data, i))
+ floppy = fl;
+ }
+ }
+ m_fdc->set_floppy(floppy);
+
+ m_rombank &= ~0x6000;
+ m_rombank |= BIT(data, 5) << 13;
+ m_rombank |= BIT(data, 6) << 14;
+
+ if (BIT(data, 7) && !BIT(m_control, 7)) // swap bank at 0->1
+ m_rombank ^= 0x1000;
+ m_control = data;
+}
diff --git a/src/devices/bus/spectrum/sixword.h b/src/devices/bus/spectrum/sixword.h
new file mode 100644
index 00000000000..368352390e0
--- /dev/null
+++ b/src/devices/bus/spectrum/sixword.h
@@ -0,0 +1,114 @@
+// license:BSD-3-Clause
+// copyright-holders:MetalliC
+/*********************************************************************
+
+ SIXWORD Swift Disc Interface
+
+*********************************************************************/
+#ifndef MAME_BUS_SPECTRUM_SIXWORD_H
+#define MAME_BUS_SPECTRUM_SIXWORD_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"
+
+//**************************************************************************
+// TYPE DEFINITIONS
+//**************************************************************************
+
+class spectrum_swiftdisc_device :
+ public device_t,
+ public device_spectrum_expansion_interface
+
+{
+public:
+ // construction/destruction
+ spectrum_swiftdisc_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
+
+ static void floppy_formats(format_registration &fr);
+ DECLARE_INPUT_CHANGED_MEMBER(nmi_button) { m_rombank |= newval << 12; m_slot->nmi_w(newval ? ASSERT_LINE : CLEAR_LINE); }
+
+protected:
+ spectrum_swiftdisc_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 ATTR_COLD;
+ virtual void device_reset() override ATTR_COLD;
+
+ // optional information overrides
+ virtual ioport_constructor device_input_ports() const override ATTR_COLD;
+
+ virtual void device_add_mconfig(machine_config &config) override ATTR_COLD;
+ virtual const tiny_rom_entry *device_rom_region() const override ATTR_COLD;
+
+ 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 uint8_t iorq_r(offs_t offset) override;
+ virtual bool romcs() override;
+
+ // passthru
+ virtual void pre_opcode_fetch(offs_t offset) override { m_exp->pre_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 iorq_w(offs_t offset, uint8_t data) override { m_exp->iorq_w(offset, data); }
+
+ required_memory_region m_rom;
+ required_device<wd_fdc_device_base> m_fdc;
+ required_device_array<floppy_connector, 4> m_floppy;
+ required_device<spectrum_expansion_slot_device> m_exp;
+ required_device<rs232_port_device> m_rs232;
+ required_ioport m_joy;
+
+ bool m_romcs;
+ u8 m_ram[0x2000];
+ u16 m_rombank;
+ u8 m_control;
+};
+
+class spectrum_swiftdisc2_device :
+ public spectrum_swiftdisc_device
+{
+public:
+ // construction/destruction
+ spectrum_swiftdisc2_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
+
+protected:
+ // device-level overrides
+ virtual void device_start() override ATTR_COLD;
+ virtual void device_reset() override ATTR_COLD;
+
+ virtual ioport_constructor device_input_ports() const override ATTR_COLD;
+
+ virtual void device_add_mconfig(machine_config &config) override ATTR_COLD;
+ virtual const tiny_rom_entry *device_rom_region() const override ATTR_COLD;
+
+ 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 uint8_t iorq_r(offs_t offset) override;
+ virtual void iorq_w(offs_t offset, uint8_t data) override;
+ void busy_w(int state) { m_busy = state; }
+
+ required_device<centronics_device> m_centronics;
+ required_ioport m_conf;
+
+ uint8_t control_r();
+ void control_w(uint8_t data);
+
+ int m_rambank;
+ int m_busy;
+ int m_txd_on;
+};
+
+
+
+// device type definition
+DECLARE_DEVICE_TYPE(SPECTRUM_SWIFTDISC, spectrum_swiftdisc_device)
+DECLARE_DEVICE_TYPE(SPECTRUM_SWIFTDISC2, spectrum_swiftdisc2_device)
+
+
+#endif // MAME_BUS_SPECTRUM_SIXWORD_H
diff --git a/src/devices/bus/spectrum/smuc.cpp b/src/devices/bus/spectrum/smuc.cpp
new file mode 100644
index 00000000000..d2ac18278a4
--- /dev/null
+++ b/src/devices/bus/spectrum/smuc.cpp
@@ -0,0 +1,141 @@
+// 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")
+ { }
+
+ virtual void map_shadow_io(address_map &map) 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:
+ void map_io(address_map &map) ATTR_COLD {}
+
+ 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_shadow_io(address_map &map)
+{
+ map(0x18a2, 0x18a2).mirror(0x4718) // 5fba | 0x011xxx101xx010 | Version: 2
+ .lr8(NAME([]() { return 0x40; }));
+ map(0x18a6, 0x18a6).mirror(0x4718) // 5fbe | 0x011xxx101xx110 | Revision: 0
+ .lr8(NAME([]() { return 0x28; }));
+ map(0x38a2, 0x38a2).mirror(0x4718) // 7fba | 0x111xxx101xx010 | VirtualFDD
+ .lrw8(NAME([this]() { return m_port_7fba_data | 0x37; })
+ , NAME([this](u8 data) { m_port_7fba_data = data; }));
+ map(0x38a6, 0x38a6).mirror(0x4718) // 7[ef]be | 0x111xxN101xx110 | i8259 - absent in 2.0
+ .lr8(NAME([]() { return 0x57; })).nopw();
+ map(0x98a2, 0x98a2).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(0x98a6, 0x98a6).mirror(0x4718) // d8be | 1x011xxx101xx110 | IDE-Hi
+ .lrw8(NAME([this]() { return m_ide_hi; }), NAME([this](u8 data) { m_ide_hi = data; }));
+ map(0xb8a2, 0xb8a2).mirror(0x4718) // ffba | 1x111xxx101xx010 | SYS
+ .lr8(NAME([this]() { return m_eeprom->read_sda() ? 0xff : 0xbf; })).w(FUNC(smuc_device::port_ffba_w));
+ map(0xb8a6, 0xb8a6).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(0x0000, 0xffff, *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..93eadd904a3
--- /dev/null
+++ b/src/devices/bus/spectrum/smuc.h
@@ -0,0 +1,14 @@
+// license:BSD-3-Clause
+// copyright-holders:Andrei I. Holub
+
+#ifndef MAME_BUS_SPECTRUM_SMUC_H
+#define MAME_BUS_SPECTRUM_SMUC_H
+
+#pragma once
+
+#include "zxbus.h"
+
+
+DECLARE_DEVICE_TYPE(ZXBUS_SMUC, device_zxbus_card_interface)
+
+#endif // MAME_BUS_SPECTRUM_SMUC_H
diff --git a/src/devices/bus/spectrum/speccydos.cpp b/src/devices/bus/spectrum/speccydos.cpp
new file mode 100644
index 00000000000..609218233f4
--- /dev/null
+++ b/src/devices/bus/spectrum/speccydos.cpp
@@ -0,0 +1,251 @@
+// license:BSD-3-Clause
+// copyright-holders:MetalliC
+/*********************************************************************
+
+ Speccy-DOS Interface
+ (c) 1987? Philips(?)
+
+ WD1770/2-based floppy drive interface with 1K RAM and 8K ROM,
+ presumable developed by Philips & MBLE Belgium, had some popularity in Hungary.
+
+ Main commands:
+ LIST * - list disc contents
+ LOAD *"filename" - load and run program
+ SAVE *"filename" - save program
+ FORMAT *"diskname"dd80 - format double side double density 80 tracks disk
+ ASN *drive# - change drive
+
+ Manual: https://sinclair.hu/speccyalista/konyvtar/kezikonyvek/SpeccyDOSv4_manual.pdf
+
+ Partially compatible with Spectrum128, useable after "USR 0" from basic128 or switch to 48K mode.
+
+ Notes / TODOs:
+ - address decoding performed by large DIP28 chip, probably PROM, not dumped, exact logic is not known.
+ - program ROMs have swapped data lines/bits 1 and 5.
+ - original software disc mentioned in manual is missing.
+ - Magic/NMI function require NMI routine preloaded in RAM by "MAGIC2.x" program (which is missing).
+
+*********************************************************************/
+
+#include "emu.h"
+#include "speccydos.h"
+
+#include "formats/sdd_dsk.h"
+
+
+/***************************************************************************
+ DEVICE DEFINITIONS
+***************************************************************************/
+
+DEFINE_DEVICE_TYPE(SPECTRUM_SPECCYDOS, spectrum_speccydos_device, "spectrum_speccydos", "Speccy-DOS Interface")
+
+
+//-------------------------------------------------
+// INPUT_PORTS
+//-------------------------------------------------
+
+INPUT_PORTS_START(speccydos)
+ PORT_START("BUTTON")
+ PORT_BIT(0x01, IP_ACTIVE_HIGH, IPT_BUTTON1) PORT_NAME("Magic Button") PORT_CODE(KEYCODE_MINUS_PAD) PORT_CHANGED_MEMBER(DEVICE_SELF, FUNC(spectrum_speccydos_device::magic_button), 0)
+INPUT_PORTS_END
+
+//-------------------------------------------------
+// input_ports - device-specific input ports
+//-------------------------------------------------
+
+ioport_constructor spectrum_speccydos_device::device_input_ports() const
+{
+ return INPUT_PORTS_NAME(speccydos);
+}
+
+//-------------------------------------------------
+// SLOT_INTERFACE( floppies )
+//-------------------------------------------------
+
+static void speccydos_floppies(device_slot_interface &device)
+{
+ device.option_add("525sssd_35t", FLOPPY_525_SSSD_35T);
+ device.option_add("525ssdd", FLOPPY_525_SSDD);
+ device.option_add("525dsdd", FLOPPY_525_DD);
+ device.option_add("525ssqd", FLOPPY_525_SSQD);
+ device.option_add("525dsqd", FLOPPY_525_QD);
+ device.option_add("35ssdd", FLOPPY_35_SSDD);
+ device.option_add("35dsdd", FLOPPY_35_DD);
+}
+
+//-------------------------------------------------
+// floppy_formats
+//-------------------------------------------------
+
+void spectrum_speccydos_device::floppy_formats(format_registration &fr)
+{
+ fr.add_mfm_containers();
+ fr.add(FLOPPY_SDD_FORMAT);
+}
+
+//-------------------------------------------------
+// ROM( speccydos )
+//-------------------------------------------------
+
+ROM_START(speccydos)
+ ROM_REGION(0x2000, "rom", 0)
+ ROM_DEFAULT_BIOS("sdos42")
+
+ ROM_SYSTEM_BIOS(0, "sdos41", "Speccy DOS v4.1")
+ ROMX_LOAD("sdos41.bin", 0x0000, 0x2000, CRC(fcfa6dac) SHA1(bcae27b334bbbee257900682859132f476c3be99), ROM_BIOS(0))
+ ROM_SYSTEM_BIOS(1, "sdos42", "Speccy DOS v4.2 (WD1770)")
+ ROMX_LOAD("sdos42.bin", 0x0000, 0x2000, CRC(208e7baa) SHA1(80e82c1dd77ff04b86989f7d2a25d93c5aa1dc42), ROM_BIOS(1))
+ ROM_SYSTEM_BIOS(2, "sdos422", "Speccy DOS v4.2 (WD1772)") // only 4 byte different from above - step rates for 1772
+ ROMX_LOAD("sdos422.bin", 0x0000, 0x2000, CRC(a7317e1d) SHA1(e72d2ea19cbe8f3459e4fc9d3c57975dc9917bd6), ROM_BIOS(2))
+ROM_END
+
+//-------------------------------------------------
+// device_add_mconfig - add device configuration
+//-------------------------------------------------
+
+void spectrum_speccydos_device::device_add_mconfig(machine_config &config)
+{
+ WD1770(config, m_fdc, 8_MHz_XTAL);
+
+ FLOPPY_CONNECTOR(config, "fdc:0", speccydos_floppies, "525dsqd", spectrum_speccydos_device::floppy_formats).enable_sound(true);
+ FLOPPY_CONNECTOR(config, "fdc:1", speccydos_floppies, "525dsqd", spectrum_speccydos_device::floppy_formats).enable_sound(true);
+ FLOPPY_CONNECTOR(config, "fdc:2", speccydos_floppies, nullptr, spectrum_speccydos_device::floppy_formats).enable_sound(true);
+ FLOPPY_CONNECTOR(config, "fdc:3", speccydos_floppies, nullptr, spectrum_speccydos_device::floppy_formats).enable_sound(true);
+
+ // 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));
+}
+
+const tiny_rom_entry *spectrum_speccydos_device::device_rom_region() const
+{
+ return ROM_NAME(speccydos);
+}
+
+
+//**************************************************************************
+// LIVE DEVICE
+//**************************************************************************
+
+//-------------------------------------------------
+// spectrum_speccydos_device - constructor
+//-------------------------------------------------
+
+spectrum_speccydos_device::spectrum_speccydos_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
+ : device_t(mconfig, SPECTRUM_SPECCYDOS, tag, owner, clock)
+ , device_spectrum_expansion_interface(mconfig, *this)
+ , m_rom(*this, "rom")
+ , m_fdc(*this, "fdc")
+ , m_floppy(*this, "fdc:%u", 0)
+ , m_exp(*this, "exp")
+{
+}
+
+//-------------------------------------------------
+// device_start - device-specific startup
+//-------------------------------------------------
+
+void spectrum_speccydos_device::device_start()
+{
+ memset(m_ram, 0, sizeof(m_ram));
+
+ save_item(NAME(m_romcs));
+ save_item(NAME(m_control));
+ save_item(NAME(m_ram));
+}
+
+//-------------------------------------------------
+// device_reset - device-specific reset
+//-------------------------------------------------
+
+void spectrum_speccydos_device::device_reset()
+{
+ m_romcs = 0;
+ m_control = 0;
+}
+
+//**************************************************************************
+// IMPLEMENTATION
+//**************************************************************************
+
+bool spectrum_speccydos_device::romcs()
+{
+ return m_romcs || m_exp->romcs();
+}
+
+void spectrum_speccydos_device::pre_opcode_fetch(offs_t offset)
+{
+ m_exp->pre_opcode_fetch(offset);
+
+ if (!machine().side_effects_disabled())
+ {
+ switch (offset)
+ {
+ case 0x0066:
+ case 0x1292:
+ case 0x1b41:
+ if (!BIT(m_control, 6))
+ m_romcs = 1;
+ break;
+ }
+ }
+}
+
+uint8_t spectrum_speccydos_device::mreq_r(offs_t offset)
+{
+ u8 data = 0xff;
+
+ if (m_romcs)
+ {
+ if (offset < 0x2000)
+ {
+ data = m_rom->base()[offset];
+ data = bitswap<8>(data, 7, 6, 1, 4, 3, 2, 5, 0);
+ }
+ else if (offset < 0x2400)
+ data = m_ram[offset & 0x3ff];
+ else if (offset >= 0x3290 && offset < 0x3294)
+ data = m_fdc->read(offset & 3);
+ else
+ logerror("SpeccyDOS unhandled read %04X\n", offset);
+ }
+
+ if (m_exp->romcs())
+ data &= m_exp->mreq_r(offset);
+
+ return data;
+}
+
+void spectrum_speccydos_device::mreq_w(offs_t offset, uint8_t data)
+{
+ if (offset == 0x3b41)
+ {
+ m_control = data;
+ floppy_image_device* floppy = m_floppy[data & 3]->get_device();
+ m_fdc->set_floppy(floppy);
+
+ if (floppy)
+ floppy->ss_w(BIT(data, 2));
+ m_fdc->dden_w(BIT(data, 7));
+
+ m_romcs = BIT(data, 6) ? 0 : BIT(data, 3);
+ }
+ else
+ if (m_romcs)
+ {
+ if (offset >= 0x2000 && offset < 0x2400)
+ m_ram[offset & 0x3ff] = data;
+ else if (offset >= 0x3290 && offset < 0x3294)
+ m_fdc->write(offset & 3, data);
+ else
+ {
+ logerror("SpeccyDOS unhandled write %04X %02X\n", offset, data);
+ //machine().debug_break();
+ }
+ }
+
+ if (m_exp->romcs())
+ m_exp->mreq_w(offset, data);
+}
diff --git a/src/devices/bus/spectrum/speccydos.h b/src/devices/bus/spectrum/speccydos.h
new file mode 100644
index 00000000000..fc6ecd29c97
--- /dev/null
+++ b/src/devices/bus/spectrum/speccydos.h
@@ -0,0 +1,70 @@
+// license:BSD-3-Clause
+// copyright-holders:MetalliC
+/*********************************************************************
+
+ Speccy DOS Interface
+
+*********************************************************************/
+#ifndef MAME_BUS_SPECTRUM_SPECCYDOS_H
+#define MAME_BUS_SPECTRUM_SPECCYDOS_H
+
+#include "exp.h"
+#include "softlist.h"
+#include "imagedev/floppy.h"
+#include "machine/wd_fdc.h"
+
+//**************************************************************************
+// TYPE DEFINITIONS
+//**************************************************************************
+
+class spectrum_speccydos_device :
+ public device_t,
+ public device_spectrum_expansion_interface
+
+{
+public:
+ // construction/destruction
+ spectrum_speccydos_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
+
+ static void floppy_formats(format_registration &fr);
+ DECLARE_INPUT_CHANGED_MEMBER(magic_button) { m_slot->nmi_w(newval ? ASSERT_LINE : CLEAR_LINE); }
+
+protected:
+ // device-level overrides
+ virtual void device_start() override ATTR_COLD;
+ virtual void device_reset() override ATTR_COLD;
+
+ // optional information overrides
+ virtual ioport_constructor device_input_ports() const override ATTR_COLD;
+
+ virtual void device_add_mconfig(machine_config &config) override ATTR_COLD;
+ virtual const tiny_rom_entry *device_rom_region() const override ATTR_COLD;
+
+ 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 bool romcs() override;
+
+ // passthru
+ 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 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); }
+
+ required_memory_region m_rom;
+ required_device<wd_fdc_device_base> m_fdc;
+ required_device_array<floppy_connector, 4> m_floppy;
+ required_device<spectrum_expansion_slot_device> m_exp;
+
+ bool m_romcs;
+ u8 m_control;
+ u8 m_ram[0x400];
+};
+
+
+// device type definition
+DECLARE_DEVICE_TYPE(SPECTRUM_SPECCYDOS, spectrum_speccydos_device)
+
+
+#endif // MAME_BUS_SPECTRUM_SPECCYDOS_H
diff --git a/src/devices/bus/spectrum/specdrum.cpp b/src/devices/bus/spectrum/specdrum.cpp
index 9c809a1b36a..49764da5da5 100644
--- a/src/devices/bus/spectrum/specdrum.cpp
+++ b/src/devices/bus/spectrum/specdrum.cpp
@@ -8,7 +8,6 @@
#include "emu.h"
#include "specdrum.h"
-#include "sound/volt_reg.h"
#include "speaker.h"
@@ -27,9 +26,6 @@ void spectrum_specdrum_device::device_add_mconfig(machine_config &config)
{
SPEAKER(config, "speaker").front_center();
ZN428E(config, m_dac, 0).add_route(ALL_OUTPUTS, "speaker", 0.5);
- voltage_regulator_device &vref(VOLTAGE_REGULATOR(config, "vref"));
- vref.add_route(0, "dac", 1.0, DAC_VREF_POS_INPUT);
- vref.add_route(0, "dac", -1.0, DAC_VREF_NEG_INPUT);
}
diff --git a/src/devices/bus/spectrum/specdrum.h b/src/devices/bus/spectrum/specdrum.h
index 7412a8509c0..43c454e7bf6 100644
--- a/src/devices/bus/spectrum/specdrum.h
+++ b/src/devices/bus/spectrum/specdrum.h
@@ -32,10 +32,10 @@ public:
protected:
// device-level overrides
- virtual void device_start() override;
+ virtual void device_start() override ATTR_COLD;
// optional information overrides
- virtual void device_add_mconfig(machine_config &config) override;
+ virtual void device_add_mconfig(machine_config &config) override ATTR_COLD;
virtual void iorq_w(offs_t offset, uint8_t data) override;
diff --git a/src/devices/bus/spectrum/specmate.cpp b/src/devices/bus/spectrum/specmate.cpp
new file mode 100644
index 00000000000..01646d882a1
--- /dev/null
+++ b/src/devices/bus/spectrum/specmate.cpp
@@ -0,0 +1,190 @@
+// license:BSD-3-Clause
+// copyright-holders:TwistedTom
+/*********************************************************************
+
+ Spec-Mate back-up interface
+
+ (A, T & Y Computing Ltd.)
+
+ A back-up/snapshot type device similar to multiface.
+ No on-screen UI, feedback is given by border colour changes.
+ Supports saving to Beta-disk, Microdrive, Wafadrive, tape (normal & double-speed modes)
+
+ Only one rom is known, although magazine adverts stated:
+ "Opus users £2 extra, Opus & Sprint users contact us for details", suggesting other roms may exist.
+ (Sprint was a high-speed tape deck, x4 recording on a standard cassette)
+
+ Operation:
+
+ Press freeze button...
+
+ Black border mode: (select device)
+ t = save to tape
+ m = save to microdrive
+ d = save to Beta disk
+ w = save to wafadrive
+ f = save to tape, double-speed mode
+ 0 = remove attributes *1
+
+ Red border mode: (save mode)
+ n = normal save
+ s = screenless save (game starts with blank screen!)
+ a = normal save with a 2nd screen (1st part of 2-part operation) *2
+ b = normal save with a 2nd screen (2nd part of 2-part operation) *2
+
+ Blue border mode: (select which part of vram is used as specmate working ram)
+ 1 = use top 3rd of screen
+ 2 = use middle 3rd of screen
+ 3 = use bottom 3rd of screen
+
+ Magenta border mode: (enter filename)
+ Type a filename, press Enter to save
+
+ System should auto-unfreeze after successful save...
+
+
+ Notes:
+ *1 Removes colour from the frozen screen so that essential data "hidden" in vram can be seen (some games do this as a copy protection),
+ user can then avoid disturbing this data with choice made in blue-border mode.
+ *2 Saves a 2nd screen (eg. a nice loading screen) just for fun. 2-part operation, so load game, freeze, save 1st screen,
+ reset system, re-load game, freeze, save main game and 2nd screen.
+ * Saves are created with stand-alone loader code so are not dependant on the interface for reuse.
+ * Pokes can be added to the save loader: press BREAK as soon as the screen goes black, INK 9, POKE aaaaa,ddd
+
+
+*********************************************************************/
+
+#include "emu.h"
+#include "specmate.h"
+
+
+/***************************************************************************
+ DEVICE DEFINITIONS
+***************************************************************************/
+
+DEFINE_DEVICE_TYPE(SPECTRUM_SPECMATE, spectrum_specmate_device, "spectrum_specmate", "AT&Y Spec-Mate")
+
+
+//-------------------------------------------------
+// INPUT_PORTS( specmate )
+//-------------------------------------------------
+
+INPUT_PORTS_START( specmate )
+ PORT_START("BUTTON")
+ PORT_BIT(0x01, IP_ACTIVE_LOW, IPT_BUTTON1) PORT_NAME("Freeze Button") PORT_CODE(KEYCODE_PLUS_PAD) PORT_CHANGED_MEMBER(DEVICE_SELF, FUNC(spectrum_specmate_device::freeze_button), 0)
+INPUT_PORTS_END
+
+
+//-------------------------------------------------
+// input_ports - device-specific input ports
+//-------------------------------------------------
+
+ioport_constructor spectrum_specmate_device::device_input_ports() const
+{
+ return INPUT_PORTS_NAME(specmate);
+}
+
+//-------------------------------------------------
+// ROM( specmate )
+//-------------------------------------------------
+
+ROM_START(specmate)
+ ROM_REGION(0x2000, "rom", 0) // unknown ver
+ ROM_LOAD("specmate.rom", 0x0000, 0x2000, CRC(8d74b19c) SHA1(c8f128610eeb5142d4d80f28e5dd07b7a5ab6b84))
+ROM_END
+
+//-------------------------------------------------
+// device_add_mconfig - add device configuration
+//-------------------------------------------------
+
+void spectrum_specmate_device::device_add_mconfig(machine_config &config)
+{
+ /* 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));
+}
+
+const tiny_rom_entry *spectrum_specmate_device::device_rom_region() const
+{
+ return ROM_NAME(specmate);
+}
+
+
+//**************************************************************************
+// LIVE DEVICE
+//**************************************************************************
+
+//-------------------------------------------------
+// spectrum_specmate_device - constructor
+//-------------------------------------------------
+
+spectrum_specmate_device::spectrum_specmate_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
+ : device_t(mconfig, SPECTRUM_SPECMATE, tag, owner, clock)
+ , device_spectrum_expansion_interface(mconfig, *this)
+ , m_rom(*this, "rom")
+ , m_exp(*this, "exp")
+{
+}
+
+//-------------------------------------------------
+// device_start - device-specific startup
+//-------------------------------------------------
+
+void spectrum_specmate_device::device_start()
+{
+ save_item(NAME(m_romcs));
+}
+
+//-------------------------------------------------
+// device_reset - device-specific reset
+//-------------------------------------------------
+
+void spectrum_specmate_device::device_reset()
+{
+ m_romcs = 0;
+}
+
+
+//**************************************************************************
+// IMPLEMENTATION
+//**************************************************************************
+
+bool spectrum_specmate_device::romcs()
+{
+ return m_romcs || m_exp->romcs();
+}
+
+void spectrum_specmate_device::pre_opcode_fetch(offs_t offset)
+{
+ m_exp->pre_opcode_fetch(offset);
+
+ if (!machine().side_effects_disabled())
+ {
+ switch (offset & 0xdfff) // a13 isn't used in the decoding
+ {
+ case 0x0066:
+ m_romcs = 1;
+ break;
+ case 0x0071:
+ m_romcs = 0;
+ break;
+ }
+ }
+}
+
+uint8_t spectrum_specmate_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;
+}
diff --git a/src/devices/bus/spectrum/specmate.h b/src/devices/bus/spectrum/specmate.h
new file mode 100644
index 00000000000..5b6ec2773d7
--- /dev/null
+++ b/src/devices/bus/spectrum/specmate.h
@@ -0,0 +1,59 @@
+// license:BSD-3-Clause
+// copyright-holders:TwistedTom
+/*********************************************************************
+
+ Spec-Mate back-up interface
+
+ (A, T & Y Computing Ltd.)
+
+*********************************************************************/
+#ifndef MAME_BUS_SPECTRUM_SPECMATE_H
+#define MAME_BUS_SPECTRUM_SPECMATE_H
+
+#include "exp.h"
+
+
+//**************************************************************************
+// TYPE DEFINITIONS
+//**************************************************************************
+
+class spectrum_specmate_device : public device_t, public device_spectrum_expansion_interface
+{
+public:
+ // construction/destruction
+ spectrum_specmate_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
+
+ DECLARE_INPUT_CHANGED_MEMBER(freeze_button) { m_slot->nmi_w(newval ? CLEAR_LINE : ASSERT_LINE); }
+
+protected:
+ // device-level overrides
+ virtual void device_start() override ATTR_COLD;
+ virtual void device_reset() override ATTR_COLD;
+
+ // optional information overrides
+ virtual void device_add_mconfig(machine_config &config) override ATTR_COLD;
+ virtual const tiny_rom_entry *device_rom_region() const override ATTR_COLD;
+ virtual ioport_constructor device_input_ports() const override ATTR_COLD;
+
+ virtual void pre_opcode_fetch(offs_t offset) override;
+ virtual uint8_t mreq_r(offs_t offset) override;
+ virtual bool romcs() override;
+
+ // passthru
+ 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); }
+ 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); }
+
+ required_memory_region m_rom;
+ required_device<spectrum_expansion_slot_device> m_exp;
+
+ bool m_romcs;
+};
+
+// device type definition
+DECLARE_DEVICE_TYPE(SPECTRUM_SPECMATE, spectrum_specmate_device)
+
+#endif // MAME_BUS_SPECTRUM_SPECMATE_H
diff --git a/src/devices/bus/spectrum/uslot.cpp b/src/devices/bus/spectrum/uslot.cpp
index b689df0cecb..854006b1446 100644
--- a/src/devices/bus/spectrum/uslot.cpp
+++ b/src/devices/bus/spectrum/uslot.cpp
@@ -13,7 +13,7 @@
// DEVICE DEFINITIONS
//**************************************************************************
-DEFINE_DEVICE_TYPE(SPECTRUM_USLOT, spectrum_uslot_device, "spectrum_uslot", "Spectrum Currah \xC2\xB5Slot")
+DEFINE_DEVICE_TYPE(SPECTRUM_USLOT, spectrum_uslot_device, "spectrum_uslot", u8"Spectrum Currah µSlot")
//-------------------------------------------------
@@ -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)
@@ -82,6 +82,24 @@ void spectrum_uslot_device::pre_opcode_fetch(offs_t offset)
m_exp2->pre_opcode_fetch(offset);
}
+void spectrum_uslot_device::post_opcode_fetch(offs_t offset)
+{
+ m_exp1->post_opcode_fetch(offset);
+ m_exp2->post_opcode_fetch(offset);
+}
+
+void spectrum_uslot_device::pre_data_fetch(offs_t offset)
+{
+ m_exp1->pre_data_fetch(offset);
+ m_exp2->pre_data_fetch(offset);
+}
+
+void spectrum_uslot_device::post_data_fetch(offs_t offset)
+{
+ m_exp1->post_data_fetch(offset);
+ m_exp2->post_data_fetch(offset);
+}
+
uint8_t spectrum_uslot_device::mreq_r(offs_t offset)
{
uint8_t data = 0xff;
diff --git a/src/devices/bus/spectrum/uslot.h b/src/devices/bus/spectrum/uslot.h
index 8df9dc79b4a..1c99bc52280 100644
--- a/src/devices/bus/spectrum/uslot.h
+++ b/src/devices/bus/spectrum/uslot.h
@@ -30,18 +30,21 @@ public:
protected:
// device-level overrides
- virtual void device_start() override;
- virtual void device_reset() override;
+ virtual void device_start() override ATTR_COLD;
+ virtual void device_reset() override ATTR_COLD;
// optional information overrides
- virtual void device_add_mconfig(machine_config &config) override;
+ virtual void device_add_mconfig(machine_config &config) override ATTR_COLD;
virtual void pre_opcode_fetch(offs_t offset) override;
+ virtual void post_opcode_fetch(offs_t offset) override;
+ virtual void pre_data_fetch(offs_t offset) override;
+ virtual void post_data_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 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 4acee2141cd..eac47cf55ca 100644
--- a/src/devices/bus/spectrum/usource.cpp
+++ b/src/devices/bus/spectrum/usource.cpp
@@ -15,7 +15,7 @@
// DEVICE DEFINITIONS
//**************************************************************************
-DEFINE_DEVICE_TYPE(SPECTRUM_USOURCE, spectrum_usource_device, "spectrum_usource", "Spectrum Currah \xC2\xB5Source")
+DEFINE_DEVICE_TYPE(SPECTRUM_USOURCE, spectrum_usource_device, "spectrum_usource", u8"Spectrum Currah µSource")
//-------------------------------------------------
@@ -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;
}
@@ -93,5 +93,10 @@ void spectrum_usource_device::pre_opcode_fetch(offs_t offset)
uint8_t spectrum_usource_device::mreq_r(offs_t offset)
{
- return m_rom->base()[offset & 0x1fff];
+ u8 data = 0xff;
+
+ if (m_romcs)
+ data = m_rom->base()[offset & 0x1fff];
+
+ return data;
}
diff --git a/src/devices/bus/spectrum/usource.h b/src/devices/bus/spectrum/usource.h
index 1f0d7d44e58..4e64e412133 100644
--- a/src/devices/bus/spectrum/usource.h
+++ b/src/devices/bus/spectrum/usource.h
@@ -32,20 +32,20 @@ public:
protected:
// device-level overrides
- virtual void device_start() override;
- virtual void device_reset() override;
+ virtual void device_start() override ATTR_COLD;
+ virtual void device_reset() override ATTR_COLD;
// optional information overrides
- virtual const tiny_rom_entry *device_rom_region() const override;
+ virtual const tiny_rom_entry *device_rom_region() const override ATTR_COLD;
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 d3476bbc441..0e465a6f8b6 100644
--- a/src/devices/bus/spectrum/uspeech.cpp
+++ b/src/devices/bus/spectrum/uspeech.cpp
@@ -15,7 +15,7 @@
// DEVICE DEFINITIONS
//**************************************************************************
-DEFINE_DEVICE_TYPE(SPECTRUM_USPEECH, spectrum_uspeech_device, "spectrum_uspeech", "Spectrum Currah \xC2\xB5Speech")
+DEFINE_DEVICE_TYPE(SPECTRUM_USPEECH, spectrum_uspeech_device, "spectrum_uspeech", u8"Spectrum Currah µSpeech")
//-------------------------------------------------
@@ -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;
}
@@ -114,21 +114,24 @@ uint8_t spectrum_uspeech_device::iorq_r(offs_t offset)
m_romcs = !m_romcs;
}
- return 0xff;
+ return offset & 1 ? m_slot->fb_r() : 0xff;
}
uint8_t spectrum_uspeech_device::mreq_r(offs_t offset)
{
uint8_t data = 0xff;
- switch (offset & 0xf000)
+ if (m_romcs)
{
- case 0x0000:
- data = m_rom->base()[offset & 0x7ff];
- break;
- case 0x1000:
- data = !m_nsp->lrq_r();
- break;
+ switch (offset & 0xf000)
+ {
+ case 0x0000:
+ data = m_rom->base()[offset & 0x7ff];
+ break;
+ case 0x1000:
+ data = !m_nsp->lrq_r();
+ break;
+ }
}
return data;
@@ -136,22 +139,25 @@ uint8_t spectrum_uspeech_device::mreq_r(offs_t offset)
void spectrum_uspeech_device::mreq_w(offs_t offset, uint8_t data)
{
- switch (offset & 0xf001)
+ if (m_romcs)
{
- case 0x1000:
- case 0x1001:
- // allophone
- m_nsp->ald_w(data & 0x3f);
- break;
-
- case 0x3000:
- // intonation low
- m_nsp->set_clock(3050000); // oscillator frequency read from hardware
- break;
-
- case 0x3001:
- // intonation high
- m_nsp->set_clock(3260000); // oscillator frequency read from hardware
- break;
+ switch (offset & 0xf001)
+ {
+ case 0x1000:
+ case 0x1001:
+ // allophone
+ m_nsp->ald_w(data & 0x3f);
+ break;
+
+ case 0x3000:
+ // intonation low
+ m_nsp->set_clock(3050000); // oscillator frequency read from hardware
+ break;
+
+ case 0x3001:
+ // intonation high
+ m_nsp->set_clock(3260000); // oscillator frequency read from hardware
+ break;
+ }
}
}
diff --git a/src/devices/bus/spectrum/uspeech.h b/src/devices/bus/spectrum/uspeech.h
index 078e33599af..0cacd79f13c 100644
--- a/src/devices/bus/spectrum/uspeech.h
+++ b/src/devices/bus/spectrum/uspeech.h
@@ -33,15 +33,15 @@ public:
protected:
// device-level overrides
- virtual void device_start() override;
- virtual void device_reset() override;
+ virtual void device_start() override ATTR_COLD;
+ virtual void device_reset() override ATTR_COLD;
// optional information overrides
- virtual const tiny_rom_entry *device_rom_region() const override;
- virtual void device_add_mconfig(machine_config &config) override;
+ virtual const tiny_rom_entry *device_rom_region() const override ATTR_COLD;
+ virtual void device_add_mconfig(machine_config &config) override ATTR_COLD;
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..2c2aa36b4eb
--- /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 ATTR_COLD;
+ virtual void device_reset() override ATTR_COLD;
+
+ virtual void device_add_mconfig(machine_config &config) override ATTR_COLD;
+ virtual const tiny_rom_entry *device_rom_region() const override ATTR_COLD;
+
+ 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 d3757d20e47..f1f722715b3 100644
--- a/src/devices/bus/spectrum/wafa.cpp
+++ b/src/devices/bus/spectrum/wafa.cpp
@@ -22,6 +22,7 @@
#include "emu.h"
#include "wafa.h"
+#include "softlist_dev.h"
//**************************************************************************
// DEVICE DEFINITIONS
@@ -52,6 +53,7 @@ void spectrum_wafa_device::device_add_mconfig(machine_config &config)
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));
SOFTWARE_LIST(config, "wafadrive_list").set_original("spectrum_wafadrive");
}
@@ -101,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)
@@ -158,12 +160,6 @@ uint8_t spectrum_wafa_device::mreq_r(offs_t offset)
return data;
}
-void spectrum_wafa_device::mreq_w(offs_t offset, uint8_t data)
-{
- if (m_exp->romcs())
- m_exp->mreq_w(offset, data);
-}
-
uint8_t spectrum_wafa_device::iorq_r(offs_t offset)
{
uint8_t data = 0xff;
diff --git a/src/devices/bus/spectrum/wafa.h b/src/devices/bus/spectrum/wafa.h
index 81428c61e84..e2d90a2b000 100644
--- a/src/devices/bus/spectrum/wafa.h
+++ b/src/devices/bus/spectrum/wafa.h
@@ -32,20 +32,24 @@ public:
static constexpr feature_type unemulated_features() { return feature::DISK | feature::LAN; }
protected:
- virtual void device_start() override;
- virtual void device_reset() override;
+ virtual void device_start() override ATTR_COLD;
+ virtual void device_reset() override ATTR_COLD;
// optional information overrides
- virtual void device_add_mconfig(machine_config &config) override;
- virtual const tiny_rom_entry *device_rom_region() const override;
+ virtual void device_add_mconfig(machine_config &config) override ATTR_COLD;
+ virtual const tiny_rom_entry *device_rom_region() const override ATTR_COLD;
virtual void pre_opcode_fetch(offs_t offset) override;
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 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); }
+ 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;
@@ -53,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..ac5e83436dd
--- /dev/null
+++ b/src/devices/bus/spectrum/zxbus.cpp
@@ -0,0 +1,94 @@
+// 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)
+ , m_shadow_io_view(nullptr)
+{
+}
+
+void zxbus_device::device_start()
+{
+}
+
+void zxbus_device::add_slot(zxbus_slot_device &slot)
+{
+ m_slot_list.push_front(&slot);
+ if (m_shadow_io_view)
+ {
+ device_zxbus_card_interface *dev = slot.get_card_device();
+ (*m_shadow_io_view).install_device(0x0000, 0xffff, *dev, &device_zxbus_card_interface::map_shadow_io);
+ }
+}
+
+device_zxbus_card_interface::device_zxbus_card_interface(const machine_config &mconfig, device_t &device)
+ : device_interface(device, "zxbus")
+ , m_zxbus(nullptr)
+{
+}
+
+void zxbus_device::install_shadow_io(memory_view::memory_view_entry &io_view)
+{
+ m_shadow_io_view = &io_view;
+}
+
+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);
+}
+
+void zxbus_gmx_cards(device_slot_interface &device)
+{
+ zxbus_cards(device);
+ 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..ddaa176cf9e
--- /dev/null
+++ b/src/devices/bus/spectrum/zxbus.h
@@ -0,0 +1,133 @@
+// 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 ATTR_COLD;
+
+ 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);
+ void install_shadow_io(memory_view::memory_view_entry &io_view);
+
+protected:
+ zxbus_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, u32 clock);
+
+ virtual void device_start() override ATTR_COLD;
+
+private:
+ required_address_space m_iospace;
+ memory_view::memory_view_entry *m_shadow_io_view;
+
+ 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;
+
+public:
+ virtual void map_shadow_io(address_map &map) ATTR_COLD {}
+
+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);
+void zxbus_gmx_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 52bf89a9976..2229e896add 100644
--- a/src/devices/bus/ss50/dc5.cpp
+++ b/src/devices/bus/ss50/dc5.cpp
@@ -31,7 +31,11 @@
#include "dc5.h"
#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"
class ss50_dc5_device : public device_t, public ss50_card_interface
{
@@ -40,43 +44,46 @@ 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_interrupt_select(*this, "interrupt_select")
- , m_address_mode(*this, "address_mode")
- , m_two_control_regs(*this, "two_control_regs")
- , m_ctrl_reg_bit7_side_select(*this, "ctrl_reg_bit7_side_select")
- , m_expected_clock(*this, "expected_clock")
- , m_expected_density(*this, "expected_density")
- , m_expected_sectors(*this, "expected_sectors")
- , m_track_zero_expected_sectors(*this, "track_zero_expected_sectors")
+ , 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")
+ , m_force_ready(*this, "FORCE_READY")
+ , m_ctrl_reg_bit7_side_select(*this, "CTRL_REG_BIT7_SIDE_SELECT")
+ , m_expected_clock(*this, "EXPECTED_CLOCK")
+ , m_expected_density(*this, "EXPECTED_DENSITY")
+ , m_expected_sectors(*this, "EXPECTED_SECTORS")
+ , m_track_zero_expected_sectors(*this, "TRACK_ZERO_EXPECTED_SECTORS")
{
}
+ DECLARE_INPUT_CHANGED_MEMBER(force_ready_change);
+ DECLARE_INPUT_CHANGED_MEMBER(ctrl_reg_bit7_side_select_change);
+ DECLARE_INPUT_CHANGED_MEMBER(expected_clock_change);
+
protected:
- 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;
+ virtual ioport_constructor device_input_ports() const override ATTR_COLD;
+ 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;
virtual uint8_t register_read(offs_t offset) override;
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);
- DECLARE_FLOPPY_FORMATS(floppy_formats);
+ static void floppy_formats(format_registration &fr);
uint8_t m_fdc_status; // for floppy controller
uint8_t m_control_register;
uint8_t m_motor_timer_out;
emu_timer *m_floppy_motor_timer;
floppy_image_device *m_fdc_selected_floppy; // Current selected floppy.
- uint8_t m_fdc_side; // Current floppy side.
- uint32_t m_fdc_clock; // Current clock frequency.
+ uint8_t m_fdc_side; // Current floppy side.
+ uint8_t m_fdc_clock_div; // Current clock frequency divisor.
+ uint8_t m_fdc_prog_clock_div; // Programmed clock frequency divisor.
TIMER_CALLBACK_MEMBER(floppy_motor_callback);
@@ -88,13 +95,11 @@ 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;
+ required_ioport m_force_ready;
required_ioport m_ctrl_reg_bit7_side_select;
required_ioport m_expected_clock;
required_ioport m_expected_density;
@@ -104,22 +109,33 @@ private:
static INPUT_PORTS_START( dc5 )
- PORT_START("interrupt_select")
- PORT_DIPNAME(0xf, 0, "Interrupt select")
+ PORT_START("INTERRUPT_SELECT")
+ PORT_DIPNAME(0x3, 0, "Interrupt select")
PORT_DIPSETTING(0, "N/C")
PORT_DIPSETTING(1, "IRQ")
PORT_DIPSETTING(2, "NMI/FIRQ")
- PORT_START("address_mode")
- PORT_DIPNAME(0xf, 1, "Address mode")
+ PORT_START("ADDRESS_MODE")
+ PORT_DIPNAME(0x1, 1, "Address mode")
PORT_DIPSETTING(0, "4 address")
PORT_DIPSETTING(1, "16 address")
- PORT_START("two_control_regs")
- PORT_DIPNAME(0xf, 0, "Two control registers")
+ PORT_START("TWO_CONTROL_REGS")
+ PORT_DIPNAME(0x1, 0, "Two control registers")
PORT_DIPSETTING(0, "No, DC4 compatible")
PORT_DIPSETTING(1, "Yes, DC5 extension")
+ // The DC5 has two modes for controlling the FDC 'ready' input. One
+ // mode forces the 'ready' line for a period triggered by the chip
+ // select, along with the motors. The other mode detects index pulses
+ // from the disk to control the 'ready' line. Flex2 for the 6800
+ // generally needs the 'ready' line forced and Flex9 can use the index
+ // pulse detection to determine if disks are present.
+ PORT_START("FORCE_READY")
+ PORT_CONFNAME(0x1, 0, "Force ready") PORT_CHANGED_MEMBER(DEVICE_SELF, FUNC(ss50_dc5_device::force_ready_change), 0)
+ PORT_CONFSETTING(0, DEF_STR(No))
+ PORT_CONFSETTING(1, DEF_STR(Yes))
+
// This config setting allows checking of the FDC clock rate and
// overriding it to assist driver development. The DC5 supports
// programming of the clock rate via the second control register, and
@@ -131,53 +147,57 @@ static INPUT_PORTS_START( dc5 )
// 3.5" 'standard' - 1.2MHz
// 3.5" HD - 2.0MHz
// 8" 360rpm - 2.4MHz
- PORT_START("expected_clock")
- PORT_CONFNAME(0xffffff, 0, "FDC expected clock rate")
+ PORT_START("EXPECTED_CLOCK")
+ PORT_CONFNAME(0xf, 0, "FDC expected clock rate") PORT_CHANGED_MEMBER(DEVICE_SELF, FUNC(ss50_dc5_device::expected_clock_change), 0)
PORT_CONFSETTING(0, "-")
- PORT_CONFSETTING(1000000, "1.0 MHz")
- PORT_CONFSETTING(1200000, "1.2 MHz")
- PORT_CONFSETTING(2000000, "2.0 MHz")
- PORT_CONFSETTING(2400000, "2.4 MHz")
+ PORT_CONFSETTING(12, "1.0 MHz")
+ PORT_CONFSETTING(10, "1.2 MHz")
+ PORT_CONFSETTING(6, "2.0 MHz")
+ PORT_CONFSETTING(5, "2.4 MHz")
// It is not uncommon to see drivers using bit 7 of the control
// register as a side selection. This conflicts with the DC5, and
// earlier controllers in this series, which use bit 7 to inhibit
// drive selection. These drivers need to be corrected, but this
// option helps identify this issue and work around it.
- PORT_START("ctrl_reg_bit7_side_select")
- PORT_CONFNAME(0x01, 0, "Control register bit 7")
+ PORT_START("CTRL_REG_BIT7_SIDE_SELECT")
+ PORT_CONFNAME(0x1, 0, "Control register bit 7") PORT_CHANGED_MEMBER(DEVICE_SELF, FUNC(ss50_dc5_device::ctrl_reg_bit7_side_select_change), 0)
PORT_CONFSETTING(0, "Inhibits drive selection")
PORT_CONFSETTING(1, "Erroneous side select")
- // Debug aid to hard code the density. The FLEX format uses single
- // density for track zero. Many virtual disks 'fix' the format to be
- // purely double density and often without properly implement driver
- // support for that. This setting is an aid to report unexpected
- // usage, and it attempts to correct that.
- PORT_START("expected_density")
- PORT_CONFNAME(0xff, 0, "Expected density")
+ // Debug aid to hard code the density. The OS9 format can use single
+ // density for track zero head zero. The FLEX format can use single
+ // density for track zero on all heads, and many virtual disks 'fix'
+ // the format to be purely double density and often without properly
+ // implementing driver support for that. This setting is an aid to
+ // report unexpected usage, and it attempts to correct that.
+ PORT_START("EXPECTED_DENSITY")
+ PORT_CONFNAME(0x7, 0, "Expected density")
PORT_CONFSETTING(0, "-")
PORT_CONFSETTING(1, "single density") // Purely single density.
- PORT_CONFSETTING(2, "double density, with single density track zero") // The default FLEX double density format.
- PORT_CONFSETTING(3, "double density") // Purely double density.
+ PORT_CONFSETTING(2, "double density, with single density track zero head zero") // OS9 format
+ PORT_CONFSETTING(3, "double density, with single density track zero all heads") // The default FLEX double density format.
+ PORT_CONFSETTING(4, "double density") // Purely double density.
// Debug aid, to check that the sector head or side is set as expected
// for the sector ID being read for the FLEX floppy disk format. Many
// FLEX disk images were developed for vitural machines that have
- // little regard for the actual head and can work off the sector ID
- // and their drivers can set the head incorrectly. E.g. a disk with 18
- // sectors per side might have a drive set to switch heads for sectors
- // above 10. Another issue is that double density disk images are
- // often 'fixed' so that they are pure double density without being
- // single density onthe first track, and the drivers might still set
- // the head based track zero being single density. This aid is not
- // intended to be a substitute for fixing the drivers but it does help
- // work through the issues while patching the disks.
- PORT_START("expected_sectors")
- PORT_CONFNAME(0xff, 0, "Expected sectors per side")
+ // little regard for the actual number of heads and can work off the
+ // sector ID and their drivers can set the head incorrectly. E.g. a
+ // disk with 18 sectors per side might have a driver incorrectly switch
+ // heads for sectors above 10. Another issue is that double density
+ // disk images are often 'fixed' so that they are pure double density
+ // without being single density on the first track, and the drivers
+ // might still set the head based on track zero being single
+ // density. This aid is not intended to be a substitute for fixing the
+ // drivers but it does help work through the issues while patching the
+ // disks.
+ PORT_START("EXPECTED_SECTORS")
+ PORT_CONFNAME(0xff, 0, "FLEX expected sectors per side")
PORT_CONFSETTING(0, "-")
PORT_CONFSETTING(10, "10") // 5 1/4" single density 256B
PORT_CONFSETTING(15, "15") // 8" single density 256B
+ PORT_CONFSETTING(16, "16") // 5 1/4" double density 256B
PORT_CONFSETTING(18, "18") // 5 1/4" double density 256B
PORT_CONFSETTING(26, "26") // 8" double density 256B
PORT_CONFSETTING(36, "36") // 3.5" 1.4M QD 256B
@@ -185,11 +205,12 @@ static INPUT_PORTS_START( dc5 )
// 6800 disks did format track zero in single density and if the
// driver sticks to that and if using a double density disk then set a
// single density size here.
- PORT_START("track_zero_expected_sectors")
- PORT_CONFNAME(0xff, 0, "Track zero expected sectors per side")
+ PORT_START("TRACK_ZERO_EXPECTED_SECTORS")
+ PORT_CONFNAME(0xff, 0, "FLEX track zero expected sectors per side")
PORT_CONFSETTING(0, "-")
PORT_CONFSETTING(10, "10") // 5 1/4" single density 256B
PORT_CONFSETTING(15, "15") // 8" single density 256B
+ PORT_CONFSETTING(16, "16") // 5 1/4" double density 256B
PORT_CONFSETTING(18, "18") // 5 1/4" double density 256B
PORT_CONFSETTING(26, "26") // 8" double density 256B
PORT_CONFSETTING(36, "36") // 3.5" 1.4M QD 256B
@@ -211,11 +232,16 @@ ioport_constructor ss50_dc5_device::device_input_ports() const
// machine configuration
//-------------------------------------------------
-FLOPPY_FORMATS_MEMBER( ss50_dc5_device::floppy_formats )
- FLOPPY_FLEX_FORMAT
-FLOPPY_FORMATS_END
+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);
+}
-// todo: implement floppy controller cards as slot devices and do this properly
static void flex_floppies(device_slot_interface &device)
{
device.option_add("sssd35", FLOPPY_525_SSSD_35T); // 35 trks ss sd 5.25
@@ -235,11 +261,9 @@ static void flex_floppies(device_slot_interface &device)
void ss50_dc5_device::device_add_mconfig(machine_config &config)
{
- WD2797(config, m_fdc, 1_MHz_XTAL);
- 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);
+ WD2797(config, m_fdc, 12_MHz_XTAL / 12); // divider is selectable
+ 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));
@@ -249,10 +273,11 @@ void ss50_dc5_device::device_add_mconfig(machine_config &config)
void ss50_dc5_device::device_reset()
{
// Initialize to the expected rate if any, otherwise to 1MHz.
- uint32_t clock = m_expected_clock->read();
- clock = clock ? clock : 1000000;
- m_fdc->set_unscaled_clock(clock);
- m_fdc_clock = clock;
+ m_fdc_prog_clock_div = 12;
+ uint8_t expected_clock_div = m_expected_clock->read();
+ uint8_t clock_div = expected_clock_div ? expected_clock_div : m_fdc_prog_clock_div;
+ m_fdc->set_unscaled_clock(12_MHz_XTAL / clock_div);
+ m_fdc_clock_div = clock_div;
// The reset state of DDEN for the DC5 is one, so selecting single density.
m_fdc->dden_w(1);
@@ -263,11 +288,37 @@ void ss50_dc5_device::device_start()
m_fdc_status = 0;
m_control_register = 0;
m_fdc_side = 0;
- m_floppy_motor_timer = machine().scheduler().timer_alloc(timer_expired_delegate(FUNC(ss50_dc5_device::floppy_motor_callback),this));
+ m_floppy_motor_timer = timer_alloc(FUNC(ss50_dc5_device::floppy_motor_callback), this);
m_motor_timer_out = 0;
+ m_fdc->set_force_ready(0);
+ m_fdc_prog_clock_div = 12;
+
+ save_item(NAME(m_fdc_status));
+ save_item(NAME(m_control_register));
+ save_item(NAME(m_motor_timer_out));
+ save_item(NAME(m_fdc_side));
+ save_item(NAME(m_fdc_clock_div));
+ save_item(NAME(m_fdc_prog_clock_div));
}
+INPUT_CHANGED_MEMBER(ss50_dc5_device::force_ready_change)
+{
+ control_register_update();
+}
+
+INPUT_CHANGED_MEMBER(ss50_dc5_device::ctrl_reg_bit7_side_select_change)
+{
+ control_register_update();
+}
+
+INPUT_CHANGED_MEMBER(ss50_dc5_device::expected_clock_change)
+{
+ uint8_t clock_div = newval ? newval : m_fdc_prog_clock_div;
+ m_fdc->set_unscaled_clock(12_MHz_XTAL / clock_div);
+ m_fdc_clock_div = clock_div;
+}
+
/* Shared floppy support. */
void ss50_dc5_device::floppy_motor_trigger()
@@ -309,7 +360,7 @@ void ss50_dc5_device::validate_floppy_side(uint8_t cmd)
if (m_fdc_side != expected_side)
{
- logerror("%s Unexpected size %d for track %d sector %d expected side %d\n", machine().describe_context(), m_fdc_side, track, sector, expected_side);
+ logerror("%s Unexpected side %d for track %d sector %d expected side %d\n", machine().describe_context(), m_fdc_side, track, sector, expected_side);
if (m_fdc_selected_floppy)
{
m_fdc_selected_floppy->ss_w(expected_side);
@@ -317,8 +368,7 @@ void ss50_dc5_device::validate_floppy_side(uint8_t cmd)
}
}
}
-
- if (expected_sectors)
+ else if (expected_sectors)
{
uint8_t expected_side = sector > expected_sectors ? 1 : 0;
@@ -348,17 +398,17 @@ uint8_t ss50_dc5_device::validate_fdc_dden(uint8_t dden)
return 1;
case 2:
{
- // Double density with track zero single density.
+ // Double density with track zero head zero single density.
uint8_t track = m_fdc->track_r();
- if (track == 0)
+ if (track == 0 && m_fdc_side == 0)
{
- // If this path is call on an update of the
+ // If this path is called on an update of the
// second control register then the track need
// not be accurate so this message might not
// be accurate.
if (!dden)
- logerror("%s Unexpected DDEN %d for single density trak 0\n", machine().describe_context(), dden);
+ logerror("%s Unexpected DDEN %d for single density track 0 head 0\n", machine().describe_context(), dden);
return 1;
}
if (dden)
@@ -366,6 +416,25 @@ uint8_t ss50_dc5_device::validate_fdc_dden(uint8_t dden)
return 0;
}
case 3:
+ {
+ // Double density with track zero all heads single density.
+ uint8_t track = m_fdc->track_r();
+
+ if (track == 0)
+ {
+ // If this path is called on an update of the
+ // second control register then the track need
+ // not be accurate so this message might not
+ // be accurate.
+ if (!dden)
+ logerror("%s Unexpected DDEN %d for single density track 0\n", machine().describe_context(), dden);
+ return 1;
+ }
+ if (dden)
+ logerror("%s Unexpected DDEN %d for double density\n", machine().describe_context(), dden);
+ return 0;
+ }
+ case 4:
// Pure double density.
if (dden)
logerror("%s Unexpected DDEN %d for double density\n", machine().describe_context(), dden);
@@ -384,7 +453,7 @@ uint8_t ss50_dc5_device::validate_fdc_sso(uint8_t cmd)
uint32_t two_regs = m_two_control_regs->read();
if (two_regs)
{
- // How if drivers are attempting to use SSO to control the
+ // If drivers are attempting to use SSO to control the
// density then that might need correcting so report such
// usage.
logerror("%s Unexpected SSO flag set in two control registers mode\n", machine().describe_context());
@@ -426,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;
@@ -436,16 +505,12 @@ WRITE_LINE_MEMBER( ss50_dc5_device::fdc_intrq_w )
uint8_t selection = m_interrupt_select->read();
if (selection == 1)
- {
write_irq(state);
- }
else if (selection == 2)
- {
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;
@@ -453,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.
@@ -477,13 +542,13 @@ WRITE_LINE_MEMBER( ss50_dc5_device::fdc_sso_w )
break;
case 2:
{
- // Double density with track zero single density.
+ // Double density with track zero head zero single density.
uint8_t track = m_fdc->track_r();
- if (track == 0)
+ if (track == 0 && m_fdc_side == 0)
{
if (state)
- logerror("Unexpected SSO %d for single density trak 0\n", state);
+ logerror("Unexpected SSO %d for single density track 0 head 0\n", state);
m_fdc->dden_w(1);
}
else
@@ -495,6 +560,25 @@ WRITE_LINE_MEMBER( ss50_dc5_device::fdc_sso_w )
break;
}
case 3:
+ {
+ // Double density with track zero all heads single density.
+ uint8_t track = m_fdc->track_r();
+
+ if (track == 0)
+ {
+ if (state)
+ logerror("Unexpected SSO %d for single density track 0\n", state);
+ m_fdc->dden_w(1);
+ }
+ else
+ {
+ if (!state)
+ logerror("Unexpected SSO %d for double density\n", state);
+ m_fdc->dden_w(0);
+ }
+ break;
+ }
+ case 4:
// Pure double density.
if (!state)
logerror("Unexpected SSO %d for double density\n", state);
@@ -513,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
@@ -530,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)
{
@@ -560,13 +640,17 @@ void ss50_dc5_device::control_register_update()
// the most useful choice because drivers in error are
// most likely just writing to the wrong bit rather
// than inconsistently to both bits. This allows
- // incremental correction of driver while spotting
+ // incremental correction of drivers while spotting
// remaining uses of bit 7 for side selection.
side |= bit7;
}
floppy->ss_w(side);
m_fdc_side = side;
}
+
+ // Force the FDC 'ready' line on if the motor line is asserted, but
+ // only when this forced mode is enabled.
+ m_fdc->set_force_ready(m_motor_timer_out && m_force_ready->read());
}
@@ -594,7 +678,7 @@ uint8_t ss50_dc5_device::register_read(offs_t offset)
uint32_t two_regs = m_two_control_regs->read();
// Note: access to this control register does not trigger the
- // motor on and and does not reset the motor timer.
+ // motor on and does not reset the motor timer.
if (!two_regs || (offset & 2) == 0)
{
@@ -661,7 +745,7 @@ void ss50_dc5_device::register_write(offs_t offset, uint8_t data)
// Osc20 and osc12 control a clock divider.
uint8_t osc12 = BIT(data, 2);
uint8_t osc20 = BIT(data, 3);
- uint32_t clock = 1000000;
+ uint8_t clock_div = 12;
// Note: supporting 2.4MHz is here is an extension to
// the published DC5 design, and appears necessary to
@@ -676,24 +760,28 @@ void ss50_dc5_device::register_write(offs_t offset, uint8_t data)
// 8" drives run at 300rpm; is there an error in the
// rates elsewhere?
if (osc20 && osc12)
- clock = 2400000;
+ clock_div = 5;
else if (osc20)
- clock = 2000000;
+ clock_div = 6;
else if (osc12)
- clock = 1200000;
+ clock_div = 10;
+
+ // Note the programmed clock divisor, in case the
+ // expected changes.
+ m_fdc_prog_clock_div = clock_div;
- // Compare to the expected clock rate if any.
- uint32_t expected_clock = m_expected_clock->read();
- if (expected_clock && clock != expected_clock)
+ // Compare to the expected clock divisor if any.
+ uint32_t expected_clock_div = m_expected_clock->read();
+ if (expected_clock_div && clock_div != expected_clock_div)
{
- logerror("%s Unexpected clock rate of %dHz expected %dHz.\n", machine().describe_context(), clock, expected_clock);
- clock = expected_clock;
+ logerror("%s Unexpected clock rate of %dHz expected %dHz.\n", machine().describe_context(), 12'000'000 / clock_div, 12'000'000 / expected_clock_div);
+ clock_div = expected_clock_div;
}
- if (clock != m_fdc_clock)
+ if (clock_div != m_fdc_clock_div)
{
- m_fdc->set_unscaled_clock(clock);
- m_fdc_clock = clock;
+ m_fdc->set_unscaled_clock(12_MHz_XTAL / clock_div);
+ m_fdc_clock_div = clock_div;
}
#if 0
diff --git a/src/devices/bus/ss50/dc5.h b/src/devices/bus/ss50/dc5.h
index f795e6d5b13..05ca3e7004f 100644
--- a/src/devices/bus/ss50/dc5.h
+++ b/src/devices/bus/ss50/dc5.h
@@ -5,11 +5,11 @@
SWTPC SS30 DC5 Floppy Disk Controller
**********************************************************************/
-#ifndef MAME_DEVICE_BUS_SS50_DC5_H
-#define MAME_DEVICE_BUS_SS50_DC5_H
+#ifndef MAME_BUS_SS50_DC5_H
+#define MAME_BUS_SS50_DC5_H
#include "interface.h"
DECLARE_DEVICE_TYPE(SS50_DC5, ss50_card_interface)
-#endif // MAME_DEVICE_BUS_SS50_DC5_H
+#endif // MAME_BUS_SS50_DC5_H
diff --git a/src/devices/bus/ss50/interface.cpp b/src/devices/bus/ss50/interface.cpp
index ea0da186afd..af39817693b 100644
--- a/src/devices/bus/ss50/interface.cpp
+++ b/src/devices/bus/ss50/interface.cpp
@@ -103,12 +103,12 @@ DEFINE_DEVICE_TYPE(SS50_INTERFACE, ss50_interface_port_device, "ss50_interface",
// ss50_interface_port_device - construction
//-------------------------------------------------
-ss50_interface_port_device::ss50_interface_port_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock)
- : device_t(mconfig, SS50_INTERFACE, tag, owner, clock),
- device_slot_interface(mconfig, *this),
- m_irq_cb(*this),
- m_firq_cb(*this),
- m_card(nullptr)
+ss50_interface_port_device::ss50_interface_port_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock) :
+ device_t(mconfig, SS50_INTERFACE, tag, owner, clock),
+ device_single_card_slot_interface<ss50_card_interface>(mconfig, *this),
+ m_irq_cb(*this),
+ m_firq_cb(*this),
+ m_card(nullptr)
{
}
@@ -120,12 +120,7 @@ ss50_interface_port_device::ss50_interface_port_device(const machine_config &mco
void ss50_interface_port_device::device_resolve_objects()
{
- logerror("Resolving objects...\n");
-
- m_irq_cb.resolve_safe();
- m_firq_cb.resolve_safe();
-
- m_card = dynamic_cast<ss50_card_interface *>(get_card_device());
+ m_card = get_card_device();
if (m_card != nullptr)
m_card->m_slot = this;
}
@@ -173,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);
@@ -214,10 +209,16 @@ template class device_finder<ss50_card_interface, true>;
// ss50_card_interface - construction
//-------------------------------------------------
-ss50_card_interface::ss50_card_interface(const machine_config &mconfig, device_t &device)
- : device_slot_card_interface(mconfig, device),
- m_slot(nullptr)
+ss50_card_interface::ss50_card_interface(const machine_config &mconfig, device_t &device) :
+ device_interface(device, "ss50card"),
+ m_slot(nullptr)
+{
+}
+
+void ss50_card_interface::interface_pre_start()
{
+ if (!m_slot)
+ throw device_missing_dependencies();
}
void ss50_default_2rs_devices(device_slot_interface &device)
diff --git a/src/devices/bus/ss50/interface.h b/src/devices/bus/ss50/interface.h
index 0be5f422c98..efffd46e7f0 100644
--- a/src/devices/bus/ss50/interface.h
+++ b/src/devices/bus/ss50/interface.h
@@ -6,10 +6,10 @@
**********************************************************************/
-#pragma once
+#ifndef MAME_BUS_SS50_INTERFACE_H
+#define MAME_BUS_SS50_INTERFACE_H
-#ifndef MAME_DEVICES_BUS_SS50_INTERFACE_H
-#define MAME_DEVICES_BUS_SS50_INTERFACE_H
+#pragma once
//**************************************************************************
@@ -21,7 +21,7 @@ class ss50_card_interface;
// ======================> ss50_interface_port_device
-class ss50_interface_port_device : public device_t, public device_slot_interface
+class ss50_interface_port_device : public device_t, public device_single_card_slot_interface<ss50_card_interface>
{
friend class ss50_card_interface;
@@ -48,16 +48,16 @@ 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
- virtual void device_resolve_objects() override;
- virtual void device_start() override;
+ virtual void device_resolve_objects() override ATTR_COLD;
+ virtual void device_start() override ATTR_COLD;
private:
// output callbacks
@@ -70,7 +70,7 @@ private:
// ======================> ss50_card_interface
-class ss50_card_interface : public device_slot_card_interface
+class ss50_card_interface : public device_interface
{
friend class ss50_interface_port_device;
@@ -83,17 +83,19 @@ 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;
+
ss50_interface_port_device *m_slot;
};
@@ -104,4 +106,4 @@ DECLARE_DEVICE_TYPE(SS50_INTERFACE, ss50_interface_port_device)
void ss50_default_2rs_devices(device_slot_interface &device);
//void ss50_default_4rs_devices(device_slot_interface &device);
-#endif
+#endif // MAME_BUS_SS50_INTERFACE_H
diff --git a/src/devices/bus/ss50/mpc.cpp b/src/devices/bus/ss50/mpc.cpp
index 18194605a9c..f18bbff8fe4 100644
--- a/src/devices/bus/ss50/mpc.cpp
+++ b/src/devices/bus/ss50/mpc.cpp
@@ -37,21 +37,21 @@ public:
protected:
// device-specific overrides
- virtual ioport_constructor device_input_ports() const override;
- virtual void device_add_mconfig(machine_config &config) override;
- virtual void device_start() override;
+ virtual ioport_constructor device_input_ports() const override ATTR_COLD;
+ virtual void device_add_mconfig(machine_config &config) override ATTR_COLD;
+ virtual void device_start() override ATTR_COLD;
// 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;
@@ -88,7 +88,6 @@ ioport_constructor ss50_mpc_device::device_input_ports() const
static DEVICE_INPUT_DEFAULTS_START( terminal )
DEVICE_INPUT_DEFAULTS("RS232_RXBAUD", 0xff, RS232_BAUD_300)
DEVICE_INPUT_DEFAULTS("RS232_TXBAUD", 0xff, RS232_BAUD_300)
- DEVICE_INPUT_DEFAULTS("RS232_STARTBITS", 0xff, RS232_STARTBITS_1)
DEVICE_INPUT_DEFAULTS("RS232_DATABITS", 0xff, RS232_DATABITS_8)
DEVICE_INPUT_DEFAULTS("RS232_PARITY", 0xff, RS232_PARITY_NONE)
DEVICE_INPUT_DEFAULTS("RS232_STOPBITS", 0xff, RS232_STOPBITS_1)
@@ -102,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);
@@ -134,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);
}
@@ -175,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/mpc.h b/src/devices/bus/ss50/mpc.h
index 3cf864dc3b3..73cf175af8e 100644
--- a/src/devices/bus/ss50/mpc.h
+++ b/src/devices/bus/ss50/mpc.h
@@ -5,11 +5,11 @@
SWTPC MP-C Serial Control Interface
**********************************************************************/
-#ifndef MAME_DEVICE_BUS_SS50_MPC_H
-#define MAME_DEVICE_BUS_SS50_MPC_H
+#ifndef MAME_BUS_SS50_MPC_H
+#define MAME_BUS_SS50_MPC_H
#include "interface.h"
DECLARE_DEVICE_TYPE(SS50_MPC, ss50_card_interface)
-#endif // MAME_DEVICE_BUS_SS50_MPC_H
+#endif // MAME_BUS_SS50_MPC_H
diff --git a/src/devices/bus/ss50/mps.cpp b/src/devices/bus/ss50/mps.cpp
index 15d7d160e31..9169336bde6 100644
--- a/src/devices/bus/ss50/mps.cpp
+++ b/src/devices/bus/ss50/mps.cpp
@@ -23,51 +23,63 @@ class ss50_mps_device : public device_t, public ss50_card_interface
public:
// construction/destruction
ss50_mps_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock)
- : device_t(mconfig, SS50_MPS, tag, owner, clock),
- ss50_card_interface(mconfig, *this),
- m_acia(*this, "acia"),
- m_irq_jumper(*this, "IRQ"),
- m_rate_jumper(*this, "BAUD")
+ : device_t(mconfig, SS50_MPS, tag, owner, clock)
+ , ss50_card_interface(mconfig, *this)
+ , m_acia(*this, "acia")
+ , m_irq_jumper(*this, "IRQ")
+ , m_rate_jumper(*this, "BAUD")
+ , m_cts_route(*this, "CTS_ROUTE")
{
}
+ DECLARE_INPUT_CHANGED_MEMBER(cts_route_change);
+
protected:
// device-specific overrides
- virtual ioport_constructor device_input_ports() const override;
- virtual void device_add_mconfig(machine_config &config) override;
- virtual void device_start() override { }
+ virtual ioport_constructor device_input_ports() const override ATTR_COLD;
+ virtual void device_add_mconfig(machine_config &config) override ATTR_COLD;
+ virtual void device_start() override ATTR_COLD;
// 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);
+ void acia_irq_w(int state);
+ void route_cts(int state);
required_device<acia6850_device> m_acia;
required_ioport m_irq_jumper;
required_ioport m_rate_jumper;
+ required_ioport m_cts_route;
+ int m_cts;
};
static INPUT_PORTS_START( mps )
PORT_START("IRQ")
- PORT_DIPNAME(1, 0, "IRQ")
- PORT_DIPSETTING(1, DEF_STR(Off))
- PORT_DIPSETTING(0, DEF_STR(On))
+ PORT_CONFNAME(1, 0, "IRQ")
+ PORT_CONFSETTING(1, DEF_STR(Off))
+ PORT_CONFSETTING(0, DEF_STR(On))
PORT_START("BAUD")
- PORT_DIPNAME(0x1f, 0x1d, "Baud Rate")
- PORT_DIPSETTING(0x1e, "110")
- PORT_DIPSETTING(0x1d, "150 / 9600")
- PORT_DIPSETTING(0x1b, "300")
- PORT_DIPSETTING(0x17, "600")
- PORT_DIPSETTING(0x0f, "1200")
+ PORT_CONFNAME(0x1f, 0x1d, "Baud Rate")
+ PORT_CONFSETTING(0x1e, "110")
+ PORT_CONFSETTING(0x1d, "150 / 9600")
+ PORT_CONFSETTING(0x1b, "300")
+ PORT_CONFSETTING(0x17, "600")
+ PORT_CONFSETTING(0x0f, "1200")
+
+ PORT_START("CTS_ROUTE")
+ PORT_CONFNAME(1, 0, "CTS route") PORT_CHANGED_MEMBER(DEVICE_SELF, FUNC(ss50_mps_device::cts_route_change), 0)
+ PORT_CONFSETTING(0, "Wired low (standard)")
+ PORT_CONFSETTING(1, "Connected through (modified)")
+
INPUT_PORTS_END
@@ -84,7 +96,6 @@ ioport_constructor ss50_mps_device::device_input_ports() const
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_STARTBITS", 0xff, RS232_STARTBITS_1)
DEVICE_INPUT_DEFAULTS("RS232_DATABITS", 0xff, RS232_DATABITS_8)
DEVICE_INPUT_DEFAULTS("RS232_PARITY", 0xff, RS232_PARITY_NONE)
DEVICE_INPUT_DEFAULTS("RS232_STOPBITS", 0xff, RS232_STOPBITS_1)
@@ -105,9 +116,14 @@ void ss50_mps_device::device_add_mconfig(machine_config &config)
rs232_port_device &rs232(RS232_PORT(config, "rs232", default_rs232_devices, "terminal"));
rs232.rxd_handler().set(m_acia, FUNC(acia6850_device::write_rxd));
+ rs232.cts_handler().set(FUNC(ss50_mps_device::route_cts));
rs232.set_option_device_input_defaults("terminal", DEVICE_INPUT_DEFAULTS_NAME(terminal));
}
+void ss50_mps_device::device_start()
+{
+ save_item(NAME(m_cts));
+}
//-------------------------------------------------
// register_read - read from a port register
@@ -127,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))
{
@@ -136,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))
{
@@ -145,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))
{
@@ -154,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))
{
@@ -163,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))
{
@@ -172,12 +188,28 @@ 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);
}
+void ss50_mps_device::route_cts(int state)
+{
+ if (m_cts_route->read())
+ m_acia->write_cts(state);
+
+ // Cache the state, in case the ioport setting changes.
+ m_cts = state;
+}
+
+INPUT_CHANGED_MEMBER(ss50_mps_device::cts_route_change)
+{
+ if (newval)
+ m_acia->write_cts(m_cts);
+ else
+ m_acia->write_cts(0);
+}
// device type definition
DEFINE_DEVICE_TYPE_PRIVATE(SS50_MPS, ss50_card_interface, ss50_mps_device, "ss50_mps", "MP-S Serial Interface")
diff --git a/src/devices/bus/ss50/mps.h b/src/devices/bus/ss50/mps.h
index e381efcfa0a..66e3bccb7d6 100644
--- a/src/devices/bus/ss50/mps.h
+++ b/src/devices/bus/ss50/mps.h
@@ -5,11 +5,11 @@
SWTPC MP-S Serial Interface
**********************************************************************/
-#ifndef MAME_DEVICE_BUS_SS50_MPS_H
-#define MAME_DEVICE_BUS_SS50_MPS_H
+#ifndef MAME_BUS_SS50_MPS_H
+#define MAME_BUS_SS50_MPS_H
#include "interface.h"
DECLARE_DEVICE_TYPE(SS50_MPS, ss50_card_interface)
-#endif // MAME_DEVICE_BUS_SS50_MPS_H
+#endif // MAME_BUS_SS50_MPS_H
diff --git a/src/devices/bus/ss50/mps2.cpp b/src/devices/bus/ss50/mps2.cpp
index 7211aea1e3e..ce49fa911fb 100644
--- a/src/devices/bus/ss50/mps2.cpp
+++ b/src/devices/bus/ss50/mps2.cpp
@@ -28,28 +28,28 @@ public:
: device_t(mconfig, SS50_MPS2, tag, owner, clock)
, ss50_card_interface(mconfig, *this)
, m_acia_upper(*this, "acia_upper")
- , m_tx_rate_upper_jumper(*this, "tx_baud_upper")
- , m_rx_rate_upper_jumper(*this, "rx_baud_upper")
+ , m_tx_rate_upper_jumper(*this, "TX_BAUD_UPPER")
+ , m_rx_rate_upper_jumper(*this, "RX_BAUD_UPPER")
, m_acia_lower(*this, "acia_lower")
- , m_tx_rate_lower_jumper(*this, "tx_baud_lower")
- , m_rx_rate_lower_jumper(*this, "rx_baud_lower")
+ , m_tx_rate_lower_jumper(*this, "TX_BAUD_LOWER")
+ , m_rx_rate_lower_jumper(*this, "RX_BAUD_LOWER")
{
}
protected:
// device-specific overrides
- virtual ioport_constructor device_input_ports() const override;
- virtual void device_add_mconfig(machine_config &config) override;
+ virtual ioport_constructor device_input_ports() const override ATTR_COLD;
+ virtual void device_add_mconfig(machine_config &config) override ATTR_COLD;
virtual void device_start() override { }
// 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;
@@ -62,37 +62,37 @@ private:
static INPUT_PORTS_START( mps2 )
- PORT_START("tx_baud_upper")
+ PORT_START("TX_BAUD_UPPER")
PORT_DIPNAME(0x1f, 0x1d, "Upper TX Baud Rate")
- PORT_DIPSETTING(0x1d, "9600 / 38400")
- PORT_DIPSETTING(0x17, "4800 / 19200")
- PORT_DIPSETTING(0x0f, "1200 / 4800")
- PORT_DIPSETTING(0x1b, "300 / 1200")
PORT_DIPSETTING(0x1e, "110 / 440")
+ PORT_DIPSETTING(0x1b, "300 / 1200")
+ PORT_DIPSETTING(0x0f, "1200 / 4800")
+ PORT_DIPSETTING(0x17, "4800 / 19200")
+ PORT_DIPSETTING(0x1d, "9600 / 38400")
- PORT_START("rx_baud_upper")
+ PORT_START("RX_BAUD_UPPER")
PORT_DIPNAME(0x1f, 0x1d, "Upper RX Baud Rate")
- PORT_DIPSETTING(0x1d, "9600 / 38400")
- PORT_DIPSETTING(0x17, "4800 / 19200")
- PORT_DIPSETTING(0x0f, "1200 / 4800")
- PORT_DIPSETTING(0x1b, "300 / 1200")
PORT_DIPSETTING(0x1e, "110 / 440")
+ PORT_DIPSETTING(0x1b, "300 / 1200")
+ PORT_DIPSETTING(0x0f, "1200 / 4800")
+ PORT_DIPSETTING(0x17, "4800 / 19200")
+ PORT_DIPSETTING(0x1d, "9600 / 38400")
- PORT_START("tx_baud_lower")
+ PORT_START("TX_BAUD_LOWER")
PORT_DIPNAME(0x1f, 0x1d, "Lower TX Baud Rate")
- PORT_DIPSETTING(0x1d, "9600 / 38400")
- PORT_DIPSETTING(0x17, "4800 / 19200")
- PORT_DIPSETTING(0x0f, "1200 / 4800")
- PORT_DIPSETTING(0x1b, "300 / 1200")
PORT_DIPSETTING(0x1e, "110 / 440")
+ PORT_DIPSETTING(0x1b, "300 / 1200")
+ PORT_DIPSETTING(0x0f, "1200 / 4800")
+ PORT_DIPSETTING(0x17, "4800 / 19200")
+ PORT_DIPSETTING(0x1d, "9600 / 38400")
- PORT_START("rx_baud_lower")
+ PORT_START("RX_BAUD_LOWER")
PORT_DIPNAME(0x1f, 0x1d, "Lower RX Baud Rate")
- PORT_DIPSETTING(0x1d, "9600 / 38400")
- PORT_DIPSETTING(0x17, "4800 / 19200")
- PORT_DIPSETTING(0x0f, "1200 / 4800")
- PORT_DIPSETTING(0x1b, "300 / 1200")
PORT_DIPSETTING(0x1e, "110 / 440")
+ PORT_DIPSETTING(0x1b, "300 / 1200")
+ PORT_DIPSETTING(0x0f, "1200 / 4800")
+ PORT_DIPSETTING(0x17, "4800 / 19200")
+ PORT_DIPSETTING(0x1d, "9600 / 38400")
INPUT_PORTS_END
@@ -110,7 +110,6 @@ ioport_constructor ss50_mps2_device::device_input_ports() const
static DEVICE_INPUT_DEFAULTS_START( terminal_upper )
DEVICE_INPUT_DEFAULTS("RS232_RXBAUD", 0xff, RS232_BAUD_9600)
DEVICE_INPUT_DEFAULTS("RS232_TXBAUD", 0xff, RS232_BAUD_9600)
- DEVICE_INPUT_DEFAULTS("RS232_STARTBITS", 0xff, RS232_STARTBITS_1)
DEVICE_INPUT_DEFAULTS("RS232_DATABITS", 0xff, RS232_DATABITS_8)
DEVICE_INPUT_DEFAULTS("RS232_PARITY", 0xff, RS232_PARITY_NONE)
DEVICE_INPUT_DEFAULTS("RS232_STOPBITS", 0xff, RS232_STOPBITS_1)
@@ -119,7 +118,6 @@ DEVICE_INPUT_DEFAULTS_END
static DEVICE_INPUT_DEFAULTS_START( terminal_lower )
DEVICE_INPUT_DEFAULTS("RS232_RXBAUD", 0xff, RS232_BAUD_9600)
DEVICE_INPUT_DEFAULTS("RS232_TXBAUD", 0xff, RS232_BAUD_9600)
- DEVICE_INPUT_DEFAULTS("RS232_STARTBITS", 0xff, RS232_STARTBITS_1)
DEVICE_INPUT_DEFAULTS("RS232_DATABITS", 0xff, RS232_DATABITS_8)
DEVICE_INPUT_DEFAULTS("RS232_PARITY", 0xff, RS232_PARITY_NONE)
DEVICE_INPUT_DEFAULTS("RS232_STOPBITS", 0xff, RS232_STOPBITS_1)
@@ -134,20 +132,24 @@ void ss50_mps2_device::device_add_mconfig(machine_config &config)
{
ACIA6850(config, m_acia_upper, 0);
m_acia_upper->txd_handler().set("rs232_upper", FUNC(rs232_port_device::write_txd));
- //m_acia_upper->rts_handler().set(FUNC(ss50_mps2_device::reader_control_w));
+ m_acia_upper->rts_handler().set("rs232_upper", FUNC(rs232_port_device::write_rts));
m_acia_upper->irq_handler().set("irq", FUNC(input_merger_device::in_w<0>));
rs232_port_device &rs232_upper(RS232_PORT(config, "rs232_upper", default_rs232_devices, "terminal"));
rs232_upper.rxd_handler().set(m_acia_upper, FUNC(acia6850_device::write_rxd));
+ rs232_upper.cts_handler().set(m_acia_upper, FUNC(acia6850_device::write_cts));
+ rs232_upper.dcd_handler().set(m_acia_upper, FUNC(acia6850_device::write_dcd));
rs232_upper.set_option_device_input_defaults("terminal", DEVICE_INPUT_DEFAULTS_NAME(terminal_upper));
ACIA6850(config, m_acia_lower, 0);
m_acia_lower->txd_handler().set("rs232_lower", FUNC(rs232_port_device::write_txd));
- //m_acia_lower->rts_handler().set(FUNC(ss50_mps2_device::reader_control_w));
+ m_acia_lower->rts_handler().set("rs232_lower", FUNC(rs232_port_device::write_rts));
m_acia_lower->irq_handler().set("irq", FUNC(input_merger_device::in_w<1>));
rs232_port_device &rs232_lower(RS232_PORT(config, "rs232_lower", default_rs232_devices, "terminal"));
rs232_lower.rxd_handler().set(m_acia_lower, FUNC(acia6850_device::write_rxd));
+ rs232_lower.cts_handler().set(m_acia_lower, FUNC(acia6850_device::write_cts));
+ rs232_lower.dcd_handler().set(m_acia_lower, FUNC(acia6850_device::write_dcd));
rs232_lower.set_option_device_input_defaults("terminal", DEVICE_INPUT_DEFAULTS_NAME(terminal_lower));
INPUT_MERGER_ANY_HIGH(config, "irq").output_handler().set(FUNC(ss50_mps2_device::write_irq));
@@ -193,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);
@@ -205,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);
@@ -217,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);
@@ -229,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);
@@ -241,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/mps2.h b/src/devices/bus/ss50/mps2.h
index a415a2dbe46..e8fe9b51f50 100644
--- a/src/devices/bus/ss50/mps2.h
+++ b/src/devices/bus/ss50/mps2.h
@@ -5,11 +5,11 @@
SWTPC MP-S2 Dual Serial Interface
**********************************************************************/
-#ifndef MAME_DEVICE_BUS_SS50_MPS2_H
-#define MAME_DEVICE_BUS_SS50_MPS2_H
+#ifndef MAME_BUS_SS50_MPS2_H
+#define MAME_BUS_SS50_MPS2_H
#include "interface.h"
DECLARE_DEVICE_TYPE(SS50_MPS2, ss50_card_interface)
-#endif // MAME_DEVICE_BUS_SS50_MPS2_H
+#endif // MAME_BUS_SS50_MPS2_H
diff --git a/src/devices/bus/ss50/mpt.cpp b/src/devices/bus/ss50/mpt.cpp
index 70ce9d0e3fa..ce930c4a3f5 100644
--- a/src/devices/bus/ss50/mpt.cpp
+++ b/src/devices/bus/ss50/mpt.cpp
@@ -21,26 +21,25 @@ public:
: device_t(mconfig, SS50_MPT, tag, owner, clock)
, ss50_card_interface(mconfig, *this)
, m_pia(*this, "pia")
- , m_irqa_jumper(*this, "irqa")
- , m_irqb_jumper(*this, "irqb")
+ , m_irqa_jumper(*this, "IRQA")
+ , m_irqb_jumper(*this, "IRQB")
{
}
protected:
- virtual ioport_constructor device_input_ports() const override;
- virtual void device_add_mconfig(machine_config &config) override;
- virtual void device_start() override;
+ virtual ioport_constructor device_input_ports() const override ATTR_COLD;
+ virtual void device_add_mconfig(machine_config &config) override ATTR_COLD;
+ virtual void device_start() override ATTR_COLD;
virtual u8 register_read(offs_t offset) override;
virtual void register_write(offs_t offset, u8 data) override;
private:
- DECLARE_WRITE8_MEMBER(pia_b_w);
- DECLARE_READ8_MEMBER(pia_cb1_r);
- DECLARE_WRITE_LINE_MEMBER(pia_irq_b);
+ void pia_b_w(uint8_t data);
+ 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;
@@ -53,12 +52,12 @@ private:
static INPUT_PORTS_START( mpt )
- PORT_START("irqa")
+ PORT_START("IRQA")
PORT_DIPNAME(1, 0, "IRQ-A")
PORT_DIPSETTING(0, DEF_STR(Off))
PORT_DIPSETTING(1, DEF_STR(On))
- PORT_START("irqb")
+ PORT_START("IRQB")
PORT_DIPNAME(1, 1, "IRQ-B")
PORT_DIPSETTING(0, DEF_STR(Off))
PORT_DIPSETTING(1, DEF_STR(On))
@@ -81,17 +80,19 @@ 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->readcb1_handler().set(FUNC(ss50_mpt_device::pia_cb1_r));
+ m_pia->cb1_w(0);
m_pia->irqa_handler().set(FUNC(ss50_mpt_device::pia_irqa_w));
m_pia->irqb_handler().set(FUNC(ss50_mpt_device::pia_irqb_w));
}
void ss50_mpt_device::device_start()
{
- m_mpt_timer = machine().scheduler().timer_alloc(timer_expired_delegate(FUNC(ss50_mpt_device::mpt_timer_callback),this));
+ m_mpt_timer = timer_alloc(FUNC(ss50_mpt_device::mpt_timer_callback), this);
m_mpt_timer_state = 0;
+
+ save_item(NAME(m_mpt_timer_state));
}
//-------------------------------------------------
@@ -113,7 +114,7 @@ void ss50_mpt_device::register_write(offs_t offset, u8 data)
}
-WRITE8_MEMBER(ss50_mpt_device::pia_b_w)
+void ss50_mpt_device::pia_b_w(uint8_t data)
{
if (data & 0x80)
{
@@ -169,11 +170,6 @@ WRITE8_MEMBER(ss50_mpt_device::pia_b_w)
m_mpt_timer->enable(true);
}
-READ8_MEMBER(ss50_mpt_device::pia_cb1_r)
-{
- return m_mpt_timer_state;
-}
-
TIMER_CALLBACK_MEMBER(ss50_mpt_device::mpt_timer_callback)
{
m_mpt_timer_state = !m_mpt_timer_state;
@@ -182,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/mpt.h b/src/devices/bus/ss50/mpt.h
index a9344f7873a..bd8a375480c 100644
--- a/src/devices/bus/ss50/mpt.h
+++ b/src/devices/bus/ss50/mpt.h
@@ -5,11 +5,11 @@
SWTPC MP-T Timer / counter
**********************************************************************/
-#ifndef MAME_DEVICE_BUS_SS50_MPT_H
-#define MAME_DEVICE_BUS_SS50_MPT_H
+#ifndef MAME_BUS_SS50_MPT_H
+#define MAME_BUS_SS50_MPT_H
#include "interface.h"
DECLARE_DEVICE_TYPE(SS50_MPT, ss50_card_interface)
-#endif // MAME_DEVICE_BUS_SS50_MPT_H
+#endif // MAME_BUS_SS50_MPT_H
diff --git a/src/devices/bus/ss50/piaide.cpp b/src/devices/bus/ss50/piaide.cpp
index c2b74c6873d..b669805f18b 100644
--- a/src/devices/bus/ss50/piaide.cpp
+++ b/src/devices/bus/ss50/piaide.cpp
@@ -59,8 +59,8 @@ public:
protected:
// device-specific overrides
- virtual void device_add_mconfig(machine_config &config) override;
- virtual void device_start() override { }
+ virtual void device_add_mconfig(machine_config &config) override ATTR_COLD;
+ virtual void device_start() override ATTR_COLD;
// interface-specific overrides
virtual uint8_t register_read(offs_t offset) override;
@@ -73,13 +73,19 @@ private:
uint8_t m_pia_porta;
uint8_t m_pia_portb;
- DECLARE_READ8_MEMBER(pia_a_r);
- DECLARE_READ8_MEMBER(pia_b_r);
- DECLARE_WRITE8_MEMBER(pia_a_w);
- DECLARE_WRITE8_MEMBER(pia_b_w);
+ uint8_t pia_a_r();
+ uint8_t pia_b_r();
+ void pia_a_w(uint8_t data);
+ void pia_b_w(uint8_t data);
};
+void ss50_piaide_device::device_start()
+{
+ save_item(NAME(m_pia_porta));
+ save_item(NAME(m_pia_portb));
+}
+
//-------------------------------------------------
// device_add_mconfig - add device-specific
// machine configuration
@@ -87,7 +93,7 @@ private:
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));
@@ -117,22 +123,22 @@ void ss50_piaide_device::register_write(offs_t offset, uint8_t data)
/******* MC6821 PIA on IDE Board *******/
/* Read/Write handlers for pia ide */
-READ8_MEMBER( ss50_piaide_device::pia_a_r )
+uint8_t ss50_piaide_device::pia_a_r()
{
return m_pia_porta;
}
-READ8_MEMBER( ss50_piaide_device::pia_b_r )
+uint8_t ss50_piaide_device::pia_b_r()
{
return m_pia_portb;
}
-WRITE8_MEMBER( ss50_piaide_device::pia_a_w )
+void ss50_piaide_device::pia_a_w(uint8_t data)
{
m_pia_porta = data;
}
-WRITE8_MEMBER( ss50_piaide_device::pia_b_w )
+void ss50_piaide_device::pia_b_w(uint8_t data)
{
uint16_t tempidedata;
diff --git a/src/devices/bus/ss50/piaide.h b/src/devices/bus/ss50/piaide.h
index 51fa31b58be..a16d8480870 100644
--- a/src/devices/bus/ss50/piaide.h
+++ b/src/devices/bus/ss50/piaide.h
@@ -5,11 +5,11 @@
PIA IDE Hard Disk Interface
**********************************************************************/
-#ifndef MAME_DEVICE_BUS_SS50_PIAIDE_H
-#define MAME_DEVICE_BUS_SS50_PIAIDE_H
+#ifndef MAME_BUS_SS50_PIAIDE_H
+#define MAME_BUS_SS50_PIAIDE_H
#include "interface.h"
DECLARE_DEVICE_TYPE(SS50_PIAIDE, ss50_card_interface)
-#endif // MAME_DEVICE_BUS_SS50_PIAIDE_H
+#endif // MAME_BUS_SS50_PIAIDE_H
diff --git a/src/devices/bus/st/replay.cpp b/src/devices/bus/st/replay.cpp
new file mode 100644
index 00000000000..15dc3aacf97
--- /dev/null
+++ b/src/devices/bus/st/replay.cpp
@@ -0,0 +1,100 @@
+// license:BSD-3-Clause
+// copyright-holders: Olivier Galibert
+
+// Microdeal ST Replay
+
+// A 8-bit mono DAC and a 8-bit mono ADC on a cartridge, with a vague
+// lowpass filter.
+
+// A peculiarity of the ST cartridge port is that it's readonly. So
+// writing to the DAC is done by reading at an appropriate address.
+
+#include "emu.h"
+#include "replay.h"
+
+#include "sound/adc.h"
+#include "sound/dac.h"
+#include "speaker.h"
+
+namespace {
+
+class st_replay_device : public device_t, public device_stcart_interface
+{
+public:
+ st_replay_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock = 0);
+ virtual ~st_replay_device();
+
+ virtual void map(address_space_installer &space) override;
+
+protected:
+ 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;
+
+private:
+ required_device<zn449_device> m_adc;
+ required_device<zn429e_device> m_dac;
+ required_device<microphone_device> m_mic;
+ required_device<speaker_device> m_speaker;
+
+ void cartmap(address_map &map) ATTR_COLD;
+
+ u16 dac_w(offs_t data);
+};
+
+st_replay_device::st_replay_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) :
+ device_t(mconfig, ST_REPLAY, tag, owner, clock),
+ device_stcart_interface(mconfig, *this),
+ m_adc(*this, "adc"),
+ m_dac(*this, "dac"),
+ m_mic(*this, "mic"),
+ m_speaker(*this, "speaker")
+{
+}
+
+st_replay_device::~st_replay_device()
+{
+}
+
+u16 st_replay_device::dac_w(offs_t data)
+{
+ m_dac->write(data);
+ return 0xffff;
+}
+
+void st_replay_device::map(address_space_installer &space)
+{
+ space.install_device(0xfa0000, 0xfbffff, *this, &st_replay_device::cartmap);
+}
+
+void st_replay_device::cartmap(address_map &map)
+{
+ map(0x00000, 0x001ff).r(FUNC(st_replay_device::dac_w)).mirror(0xfe00);
+ map(0x10001, 0x10001).r(m_adc, FUNC(zn449_device::read)).mirror(0xfffe);
+}
+
+void st_replay_device::device_add_mconfig(machine_config &config)
+{
+ MICROPHONE(config, m_mic, 1).front_center();
+ m_mic->add_route(0, m_adc, 1.0, 0);
+
+ ZN449(config, m_adc);
+
+ // ZN429D the schematics say, not sure if any significant difference
+ ZN429E(config, m_dac);
+ m_dac->add_route(0, m_speaker, 1.0, 0);
+
+ SPEAKER(config, m_speaker, 1).front_center();
+}
+
+void st_replay_device::device_start()
+{
+}
+
+void st_replay_device::device_reset()
+{
+}
+
+} // anonymous namespace
+
+DEFINE_DEVICE_TYPE_PRIVATE(ST_REPLAY, device_stcart_interface, st_replay_device, "st_replay", "Microdeal ST Replay")
diff --git a/src/devices/bus/st/replay.h b/src/devices/bus/st/replay.h
new file mode 100644
index 00000000000..b6e2c73a062
--- /dev/null
+++ b/src/devices/bus/st/replay.h
@@ -0,0 +1,15 @@
+// license:BSD-3-Clause
+// copyright-holders:Olivier Galibert
+
+#ifndef MAME_BUS_ST_REPLAY_H
+#define MAME_BUS_ST_REPLAY_H
+
+// Microdeal ST Replay
+
+#pragma once
+
+#include "stcart.h"
+
+DECLARE_DEVICE_TYPE(ST_REPLAY, device_stcart_interface)
+
+#endif // MAME_BUS_ST_REPLAY_H
diff --git a/src/devices/bus/st/stcart.cpp b/src/devices/bus/st/stcart.cpp
new file mode 100644
index 00000000000..0e53093bf92
--- /dev/null
+++ b/src/devices/bus/st/stcart.cpp
@@ -0,0 +1,40 @@
+// license:BSD-3-Clause
+// copyright-holders:Olivier Galibert
+
+#include "emu.h"
+#include "stcart.h"
+
+#include "replay.h"
+
+DEFINE_DEVICE_TYPE(STCART_CONNECTOR, stcart_connector, "stcart_connector", "Atari ST cartridge connector")
+
+stcart_connector::stcart_connector(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) :
+ device_t(mconfig, STCART_CONNECTOR, tag, owner, clock),
+ device_single_card_slot_interface<device_stcart_interface>(mconfig, *this)
+{
+}
+
+void stcart_connector::device_start()
+{
+}
+
+void stcart_connector::map(address_space_installer &space)
+{
+ auto card = get_card_device();
+ if(card)
+ card->map(space);
+}
+
+void stcart_intf(device_slot_interface &device)
+{
+ device.option_add("replay", ST_REPLAY);
+}
+
+device_stcart_interface::device_stcart_interface(const machine_config &mconfig, device_t &device) :
+ device_interface(device, "stcart")
+{
+}
+
+device_stcart_interface::~device_stcart_interface()
+{
+}
diff --git a/src/devices/bus/st/stcart.h b/src/devices/bus/st/stcart.h
new file mode 100644
index 00000000000..49ccb78a2e6
--- /dev/null
+++ b/src/devices/bus/st/stcart.h
@@ -0,0 +1,50 @@
+// license:BSD-3-Clause
+// copyright-holders:Olivier Galibert
+
+// Atari ST cartridges
+
+#ifndef MAME_BUS_ST_STCART_H
+#define MAME_BUS_ST_STCART_H
+
+#pragma once
+
+class device_stcart_interface;
+
+class stcart_connector: public device_t, public device_single_card_slot_interface<device_stcart_interface>
+{
+public:
+ template <typename T>
+ stcart_connector(const machine_config &mconfig, const char *tag, device_t *owner, T &&opts, const char *dflt)
+ : stcart_connector(mconfig, tag, owner, (uint32_t)0)
+ {
+ option_reset();
+ opts(*this);
+ set_default_option(dflt);
+ set_fixed(false);
+ }
+
+ stcart_connector(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
+
+ void map(address_space_installer &space);
+
+protected:
+ virtual void device_start() override ATTR_COLD;
+};
+
+class device_stcart_interface: public device_interface
+{
+public:
+ device_stcart_interface(const machine_config &mconfig, device_t &device);
+ virtual ~device_stcart_interface();
+
+ virtual void map(address_space_installer &space) = 0;
+
+protected:
+
+};
+
+DECLARE_DEVICE_TYPE(STCART_CONNECTOR, stcart_connector)
+
+void stcart_intf(device_slot_interface &device);
+
+#endif // MAME_BUS_ST_STCART_H
diff --git a/src/devices/bus/sunkbd/hlekbd.cpp b/src/devices/bus/sunkbd/hlekbd.cpp
index 21f4de349ed..3be85674976 100644
--- a/src/devices/bus/sunkbd/hlekbd.cpp
+++ b/src/devices/bus/sunkbd/hlekbd.cpp
@@ -24,7 +24,7 @@
0000 1110 ---k lscn LED (1 = on: k = kana, l = caps lock, s = scroll lock, c = compose, n = num lock)
0000 1111 layout request (keyboard responds with layout response)
- message from keyboad to host:
+ message from keyboard to host:
0xxx xxxx key make
1xxx xxxx key break
0111 1111 all keys up
@@ -132,20 +132,7 @@
*/
-/***************************************************************************
- DEVICE TYPE GLOBALS
-***************************************************************************/
-
-DEFINE_DEVICE_TYPE_NS(SUN_TYPE3_HLE_KEYBOARD, bus::sunkbd, hle_type3_device, "kbd_type3_hle", "Sun Type 3 Keyboard (HLE)")
-DEFINE_DEVICE_TYPE_NS(SUN_TYPE4_HLE_KEYBOARD, bus::sunkbd, hle_type4_device, "kbd_type4_hle", "Sun Type 4 Keyboard (HLE)")
-DEFINE_DEVICE_TYPE_NS(SUN_TYPE5_HLE_KEYBOARD, bus::sunkbd, hle_type5_device, "kbd_type5_hle_us", "Sun Type 5 Keyboard (U.S.A. - HLE)")
-DEFINE_DEVICE_TYPE_NS(SUN_TYPE5_GB_HLE_KEYBOARD, bus::sunkbd, hle_type5_gb_device, "kbd_type5_hle_gb", "Sun Type 5 Keyboard (Great Britain - HLE)")
-DEFINE_DEVICE_TYPE_NS(SUN_TYPE5_SE_HLE_KEYBOARD, bus::sunkbd, hle_type5_se_device, "kbd_type5_hle_se", "Sun Type 5 Keyboard (Sweden - HLE)")
-DEFINE_DEVICE_TYPE_NS(SUN_TYPE5_JP_HLE_KEYBOARD, bus::sunkbd, hle_type5_jp_device, "kbd_type5_hle_jp", "Sun Type 5 Keyboard (Japan - HLE)")
-
-
-
-namespace bus { namespace sunkbd {
+namespace bus::sunkbd {
namespace {
@@ -728,6 +715,212 @@ INPUT_PORTS_START( hle_type5_jp_device )
PORT_BIT( 0x2000, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_NAME("Kana") PORT_CODE(KEYCODE_RALT) // かな
INPUT_PORTS_END
+
+
+/***************************************************************************
+ BASE TYPE 4/5/6 HLE KEYBOARD DEVICE
+***************************************************************************/
+
+class hle_type4_device_base : public hle_device_base
+{
+protected:
+ using hle_device_base::hle_device_base;
+
+private:
+ // return identification byte for self test pass response
+ virtual uint8_t ident_byte() override
+ {
+ return (m_dips->read() & 0x80U) ? 0x03U : 0x04U;
+ }
+};
+
+
+
+/***************************************************************************
+ TYPE 3 HLE KEYBOARD DEVICE
+***************************************************************************/
+
+class hle_type3_device : public hle_device_base
+{
+public:
+ hle_type3_device(
+ machine_config const &mconfig,
+ char const *tag,
+ device_t *owner,
+ uint32_t clock)
+ : hle_device_base(
+ mconfig,
+ SUN_TYPE3_HLE_KEYBOARD,
+ tag,
+ owner,
+ clock)
+ {
+ }
+
+protected:
+ virtual ioport_constructor device_input_ports() const override
+ {
+ return INPUT_PORTS_NAME(hle_type3_device);
+ }
+
+private:
+ // return identification byte for self test pass response
+ virtual uint8_t ident_byte() override
+ {
+ return 0x03U;
+ }
+};
+
+
+
+/***************************************************************************
+ TYPE 4 HLE KEYBOARD DEVICE
+***************************************************************************/
+
+class hle_type4_device : public hle_type4_device_base
+{
+public:
+ hle_type4_device(
+ machine_config const &mconfig,
+ char const *tag,
+ device_t *owner,
+ uint32_t clock)
+ : hle_type4_device_base(
+ mconfig,
+ SUN_TYPE4_HLE_KEYBOARD,
+ tag,
+ owner,
+ clock)
+ {
+ }
+
+protected:
+ virtual ioport_constructor device_input_ports() const override
+ {
+ return INPUT_PORTS_NAME(hle_type4_device);
+ }
+};
+
+
+
+/***************************************************************************
+ TYPE 5 HLE KEYBOARD DEVICE
+***************************************************************************/
+
+class hle_type5_device : public hle_type4_device_base
+{
+public:
+ hle_type5_device(
+ machine_config const &mconfig,
+ char const *tag,
+ device_t *owner,
+ uint32_t clock)
+ : hle_type4_device_base(
+ mconfig,
+ SUN_TYPE5_HLE_KEYBOARD,
+ tag,
+ owner,
+ clock)
+ {
+ }
+
+protected:
+ virtual ioport_constructor device_input_ports() const override
+ {
+ return INPUT_PORTS_NAME(hle_type5_device);
+ }
+};
+
+
+
+/***************************************************************************
+ TYPE 5 UK HLE KEYBOARD DEVICE
+***************************************************************************/
+
+class hle_type5_gb_device : public hle_type4_device_base
+{
+public:
+ hle_type5_gb_device(
+ machine_config const &mconfig,
+ char const *tag,
+ device_t *owner,
+ uint32_t clock)
+ : hle_type4_device_base(
+ mconfig,
+ SUN_TYPE5_GB_HLE_KEYBOARD,
+ tag,
+ owner,
+ clock)
+ {
+ }
+
+protected:
+ virtual ioport_constructor device_input_ports() const override
+ {
+ return INPUT_PORTS_NAME(hle_type5_gb_device);
+ }
+};
+
+
+
+/***************************************************************************
+ TYPE 5 SWEDISH HLE KEYBOARD DEVICE
+***************************************************************************/
+
+class hle_type5_se_device : public hle_type4_device_base
+{
+public:
+ hle_type5_se_device(
+ machine_config const &mconfig,
+ char const *tag,
+ device_t *owner,
+ uint32_t clock)
+ : hle_type4_device_base(
+ mconfig,
+ SUN_TYPE5_SE_HLE_KEYBOARD,
+ tag,
+ owner,
+ clock)
+ {
+ }
+
+protected:
+ virtual ioport_constructor device_input_ports() const override
+ {
+ return INPUT_PORTS_NAME(hle_type5_se_device);
+ }
+};
+
+
+
+/***************************************************************************
+ TYPE 5 JAPANESE HLE KEYBOARD DEVICE
+***************************************************************************/
+
+class hle_type5_jp_device : public hle_type4_device_base
+{
+public:
+ hle_type5_jp_device(
+ machine_config const &mconfig,
+ char const *tag,
+ device_t *owner,
+ uint32_t clock)
+ : hle_type4_device_base(
+ mconfig,
+ SUN_TYPE5_JP_HLE_KEYBOARD,
+ tag,
+ owner,
+ clock)
+ {
+ }
+
+protected:
+ virtual ioport_constructor device_input_ports() const override
+ {
+ return INPUT_PORTS_NAME(hle_type5_jp_device);
+ }
+};
+
} // anonymous namespace
@@ -778,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);
}
@@ -805,7 +998,7 @@ void hle_device_base::device_add_mconfig(machine_config &config)
void hle_device_base::device_start()
{
m_leds.resolve();
- m_click_timer = timer_alloc(CLICK_TIMER_ID);
+ m_click_timer = timer_alloc(FUNC(hle_device_base::click_off), this);
save_item(NAME(m_make_count));
save_item(NAME(m_rx_state));
@@ -861,22 +1054,13 @@ void hle_device_base::device_reset()
/*--------------------------------------------------
- hle_device_base::device_timer
- handle timed events
+ click_off - turn the clicker off
--------------------------------------------------*/
-void hle_device_base::device_timer(emu_timer &timer, device_timer_id id, int param, void *ptr)
+TIMER_CALLBACK_MEMBER(hle_device_base::click_off)
{
- switch (id)
- {
- case CLICK_TIMER_ID:
- m_beeper_state &= ~uint8_t(BEEPER_CLICK);
- m_beeper->set_state(m_beeper_state ? 1 : 0);
- break;
-
- default:
- break;
- }
+ m_beeper_state &= ~uint8_t(BEEPER_CLICK);
+ m_beeper->set_state(m_beeper_state ? 1 : 0);
}
@@ -985,6 +1169,7 @@ void hle_device_base::received_byte(uint8_t byte)
default:
assert(m_rx_state == RX_IDLE);
+ [[fallthrough]];
case RX_IDLE:
switch (byte)
{
@@ -1034,249 +1219,17 @@ void hle_device_base::received_byte(uint8_t byte)
}
}
-
-
-/***************************************************************************
- BASE TYPE 4/5/6 HLE KEYBOARD DEVICE
-***************************************************************************/
-
-/*--------------------------------------------------
- hle_type4_device_base::ident_byte
- return identification byte for self test pass
- response
---------------------------------------------------*/
-
-uint8_t hle_type4_device_base::ident_byte()
-{
- return (m_dips->read() & 0x80U) ? 0x03U : 0x04U;
-}
-
-
-
-/***************************************************************************
- TYPE 3 HLE KEYBOARD DEVICE
-***************************************************************************/
-
-/*--------------------------------------------------
- hle_type3_device::hle_type3_device
- abbreviated constructor
---------------------------------------------------*/
-
-hle_type3_device::hle_type3_device(
- machine_config const &mconfig,
- char const *tag,
- device_t *owner,
- uint32_t clock)
- : hle_device_base(
- mconfig,
- SUN_TYPE3_HLE_KEYBOARD,
- tag,
- owner,
- clock)
-{
-}
-
-
-/*--------------------------------------------------
- hle_type3_device::device_input_ports
- get input ports for this device
---------------------------------------------------*/
-
-ioport_constructor hle_type3_device::device_input_ports() const
-{
- return INPUT_PORTS_NAME(hle_type3_device);
-}
-
-
-/*--------------------------------------------------
- hle_type3_device::ident_byte
- return identification byte for self test pass
- response
---------------------------------------------------*/
-
-uint8_t hle_type3_device::ident_byte()
-{
- return 0x03U;
-}
+} // namespace bus::sunkbd
/***************************************************************************
- TYPE 4 HLE KEYBOARD DEVICE
-***************************************************************************/
-
-/*--------------------------------------------------
- hle_type4_device::hle_type4_device
- abbreviated constructor
---------------------------------------------------*/
-
-hle_type4_device::hle_type4_device(
- machine_config const &mconfig,
- char const *tag,
- device_t *owner,
- uint32_t clock)
- : hle_type4_device_base(
- mconfig,
- SUN_TYPE4_HLE_KEYBOARD,
- tag,
- owner,
- clock)
-{
-}
-
-
-/*--------------------------------------------------
- hle_type4_device::device_input_ports
- get input ports for this device
---------------------------------------------------*/
-
-ioport_constructor hle_type4_device::device_input_ports() const
-{
- return INPUT_PORTS_NAME(hle_type4_device);
-}
-
-
-
-/***************************************************************************
- TYPE 5 HLE KEYBOARD DEVICE
-***************************************************************************/
-
-/*--------------------------------------------------
- hle_type5_device::hle_type5_device
- abbreviated constructor
---------------------------------------------------*/
-
-hle_type5_device::hle_type5_device(
- machine_config const &mconfig,
- char const *tag,
- device_t *owner,
- uint32_t clock)
- : hle_type4_device_base(
- mconfig,
- SUN_TYPE5_HLE_KEYBOARD,
- tag,
- owner,
- clock)
-{
-}
-
-
-/*--------------------------------------------------
- hle_type5_device::device_input_ports
- get input ports for this device
---------------------------------------------------*/
-
-ioport_constructor hle_type5_device::device_input_ports() const
-{
- return INPUT_PORTS_NAME(hle_type5_device);
-}
-
-
-
-/***************************************************************************
- TYPE 5 UK HLE KEYBOARD DEVICE
-***************************************************************************/
-
-/*--------------------------------------------------
- hle_type5_gb_device::hle_type5_gb_device
- abbreviated constructor
---------------------------------------------------*/
-
-hle_type5_gb_device::hle_type5_gb_device(
- machine_config const &mconfig,
- char const *tag,
- device_t *owner,
- uint32_t clock)
- : hle_type4_device_base(
- mconfig,
- SUN_TYPE5_GB_HLE_KEYBOARD,
- tag,
- owner,
- clock)
-{
-}
-
-
-/*--------------------------------------------------
- hle_type5_gb_device::device_input_ports
- get input ports for this device
---------------------------------------------------*/
-
-ioport_constructor hle_type5_gb_device::device_input_ports() const
-{
- return INPUT_PORTS_NAME(hle_type5_gb_device);
-}
-
-
-
-/***************************************************************************
- TYPE 5 SWEDISH HLE KEYBOARD DEVICE
-***************************************************************************/
-
-/*--------------------------------------------------
- hle_type5_se_device::hle_type5_se_device
- abbreviated constructor
---------------------------------------------------*/
-
-hle_type5_se_device::hle_type5_se_device(
- machine_config const &mconfig,
- char const *tag,
- device_t *owner,
- uint32_t clock)
- : hle_type4_device_base(
- mconfig,
- SUN_TYPE5_SE_HLE_KEYBOARD,
- tag,
- owner,
- clock)
-{
-}
-
-
-/*--------------------------------------------------
- hle_type5_se_device::device_input_ports
- get input ports for this device
---------------------------------------------------*/
-
-ioport_constructor hle_type5_se_device::device_input_ports() const
-{
- return INPUT_PORTS_NAME(hle_type5_se_device);
-}
-
-
-
-/***************************************************************************
- TYPE 5 JAPANESE HLE KEYBOARD DEVICE
+ DEVICE TYPE GLOBALS
***************************************************************************/
-/*--------------------------------------------------
- hle_type5_jp_device::hle_type5_jp_device
- abbreviated constructor
---------------------------------------------------*/
-
-hle_type5_jp_device::hle_type5_jp_device(
- machine_config const &mconfig,
- char const *tag,
- device_t *owner,
- uint32_t clock)
- : hle_type4_device_base(
- mconfig,
- SUN_TYPE5_JP_HLE_KEYBOARD,
- tag,
- owner,
- clock)
-{
-}
-
-
-/*--------------------------------------------------
- hle_type5_jp_device::device_input_ports
- get input ports for this device
---------------------------------------------------*/
-
-ioport_constructor hle_type5_jp_device::device_input_ports() const
-{
- return INPUT_PORTS_NAME(hle_type5_jp_device);
-}
-
-} } // namespace bus::sunkbd
+DEFINE_DEVICE_TYPE_PRIVATE(SUN_TYPE3_HLE_KEYBOARD, bus::sunkbd::hle_device_base, bus::sunkbd::hle_type3_device, "kbd_type3_hle", "Sun Type 3 Keyboard (HLE)")
+DEFINE_DEVICE_TYPE_PRIVATE(SUN_TYPE4_HLE_KEYBOARD, bus::sunkbd::hle_device_base, bus::sunkbd::hle_type4_device, "kbd_type4_hle", "Sun Type 4 Keyboard (HLE)")
+DEFINE_DEVICE_TYPE_PRIVATE(SUN_TYPE5_HLE_KEYBOARD, bus::sunkbd::hle_device_base, bus::sunkbd::hle_type5_device, "kbd_type5_hle_us", "Sun Type 5 Keyboard (U.S.A. - HLE)")
+DEFINE_DEVICE_TYPE_PRIVATE(SUN_TYPE5_GB_HLE_KEYBOARD, bus::sunkbd::hle_device_base, bus::sunkbd::hle_type5_gb_device, "kbd_type5_hle_gb", "Sun Type 5 Keyboard (Great Britain - HLE)")
+DEFINE_DEVICE_TYPE_PRIVATE(SUN_TYPE5_SE_HLE_KEYBOARD, bus::sunkbd::hle_device_base, bus::sunkbd::hle_type5_se_device, "kbd_type5_hle_se", "Sun Type 5 Keyboard (Sweden - HLE)")
+DEFINE_DEVICE_TYPE_PRIVATE(SUN_TYPE5_JP_HLE_KEYBOARD, bus::sunkbd::hle_device_base, bus::sunkbd::hle_type5_jp_device, "kbd_type5_hle_jp", "Sun Type 5 Keyboard (Japan - HLE)")
diff --git a/src/devices/bus/sunkbd/hlekbd.h b/src/devices/bus/sunkbd/hlekbd.h
index 4f442daad4a..e53fe2f13ef 100644
--- a/src/devices/bus/sunkbd/hlekbd.h
+++ b/src/devices/bus/sunkbd/hlekbd.h
@@ -1,17 +1,18 @@
// license:BSD-3-Clause
// copyright-holders:Vas Crabb
-#ifndef MAME_DEVICES_SUNKBD_HLEKBD_H
-#define MAME_DEVICES_SUNKBD_HLEKBD_H
+#ifndef MAME_BUS_SUNKBD_HLEKBD_H
+#define MAME_BUS_SUNKBD_HLEKBD_H
#pragma once
#include "sunkbd.h"
+
#include "machine/keyboard.h"
#include "sound/beep.h"
#include "diserial.h"
-namespace bus { namespace sunkbd {
+namespace bus::sunkbd {
class hle_device_base
: public device_t
@@ -22,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
@@ -34,10 +35,9 @@ protected:
uint32_t clock);
// device overrides
- virtual void device_add_mconfig(machine_config &config) override;
- virtual void device_start() override;
- virtual void device_reset() override;
- virtual void device_timer(emu_timer &timer, device_timer_id id, int param, void *ptr) override;
+ 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;
// device_buffered_serial_interface overrides
virtual void tra_callback() override;
@@ -50,6 +50,8 @@ protected:
// customised transmit_byte method
void transmit_byte(uint8_t byte);
+ TIMER_CALLBACK_MEMBER(click_off);
+
required_ioport m_dips;
private:
@@ -102,111 +104,14 @@ private:
uint8_t m_beeper_state;
};
-
-class hle_type4_device_base : public hle_device_base
-{
-protected:
- using hle_device_base::hle_device_base;
-
-private:
- virtual uint8_t ident_byte() override;
-};
-
-
-class hle_type3_device : public hle_device_base
-{
-public:
- hle_type3_device(
- machine_config const &mconfig,
- char const *tag,
- device_t *owner,
- uint32_t clock);
-
-protected:
- virtual ioport_constructor device_input_ports() const override;
-
-private:
- virtual uint8_t ident_byte() override;
-};
-
-
-class hle_type4_device : public hle_type4_device_base
-{
-public:
- hle_type4_device(
- machine_config const &mconfig,
- char const *tag,
- device_t *owner,
- uint32_t clock);
-
-protected:
- virtual ioport_constructor device_input_ports() const override;
-};
-
-
-class hle_type5_device : public hle_type4_device_base
-{
-public:
- hle_type5_device(
- machine_config const &mconfig,
- char const *tag,
- device_t *owner,
- uint32_t clock);
-
-protected:
- virtual ioport_constructor device_input_ports() const override;
-};
-
-
-class hle_type5_gb_device : public hle_type4_device_base
-{
-public:
- hle_type5_gb_device(
- machine_config const &mconfig,
- char const *tag,
- device_t *owner,
- uint32_t clock);
-
-protected:
- virtual ioport_constructor device_input_ports() const override;
-};
-
-
-class hle_type5_se_device : public hle_type4_device_base
-{
-public:
- hle_type5_se_device(
- machine_config const &mconfig,
- char const *tag,
- device_t *owner,
- uint32_t clock);
-
-protected:
- virtual ioport_constructor device_input_ports() const override;
-};
-
-
-class hle_type5_jp_device : public hle_type4_device_base
-{
-public:
- hle_type5_jp_device(
- machine_config const &mconfig,
- char const *tag,
- device_t *owner,
- uint32_t clock);
-
-protected:
- virtual ioport_constructor device_input_ports() const override;
-};
-
-} } // namespace bus::sunkbd
+} // namespace bus::sunkbd
-DECLARE_DEVICE_TYPE_NS(SUN_TYPE3_HLE_KEYBOARD, bus::sunkbd, hle_type3_device)
-DECLARE_DEVICE_TYPE_NS(SUN_TYPE4_HLE_KEYBOARD, bus::sunkbd, hle_type4_device)
-DECLARE_DEVICE_TYPE_NS(SUN_TYPE5_HLE_KEYBOARD, bus::sunkbd, hle_type5_device)
-DECLARE_DEVICE_TYPE_NS(SUN_TYPE5_GB_HLE_KEYBOARD, bus::sunkbd, hle_type5_gb_device)
-DECLARE_DEVICE_TYPE_NS(SUN_TYPE5_SE_HLE_KEYBOARD, bus::sunkbd, hle_type5_se_device)
-DECLARE_DEVICE_TYPE_NS(SUN_TYPE5_JP_HLE_KEYBOARD, bus::sunkbd, hle_type5_jp_device)
+DECLARE_DEVICE_TYPE_NS(SUN_TYPE3_HLE_KEYBOARD, bus::sunkbd, hle_device_base)
+DECLARE_DEVICE_TYPE_NS(SUN_TYPE4_HLE_KEYBOARD, bus::sunkbd, hle_device_base)
+DECLARE_DEVICE_TYPE_NS(SUN_TYPE5_HLE_KEYBOARD, bus::sunkbd, hle_device_base)
+DECLARE_DEVICE_TYPE_NS(SUN_TYPE5_GB_HLE_KEYBOARD, bus::sunkbd, hle_device_base)
+DECLARE_DEVICE_TYPE_NS(SUN_TYPE5_SE_HLE_KEYBOARD, bus::sunkbd, hle_device_base)
+DECLARE_DEVICE_TYPE_NS(SUN_TYPE5_JP_HLE_KEYBOARD, bus::sunkbd, hle_device_base)
-#endif // MAME_DEVICES_SUNKBD_HLEKBD_H
+#endif // MAME_BUS_SUNKBD_HLEKBD_H
diff --git a/src/devices/bus/sunkbd/sunkbd.cpp b/src/devices/bus/sunkbd/sunkbd.cpp
index 82152b5f905..315b9332130 100644
--- a/src/devices/bus/sunkbd/sunkbd.cpp
+++ b/src/devices/bus/sunkbd/sunkbd.cpp
@@ -95,13 +95,6 @@
DEFINE_DEVICE_TYPE(SUNKBD_PORT, sun_keyboard_port_device, "sunkbd", "Sun Keyboard Port")
-int const device_sun_keyboard_port_interface::START_BIT_COUNT;
-int const device_sun_keyboard_port_interface::DATA_BIT_COUNT;
-device_serial_interface::parity_t const device_sun_keyboard_port_interface::PARITY;
-device_serial_interface::stop_bits_t const device_sun_keyboard_port_interface::STOP_BITS;
-int const device_sun_keyboard_port_interface::BAUD;
-
-
sun_keyboard_port_device::sun_keyboard_port_device(
machine_config const &mconfig,
@@ -120,7 +113,7 @@ sun_keyboard_port_device::sun_keyboard_port_device(
device_t *owner,
uint32_t clock)
: device_t(mconfig, type, tag, owner, clock)
- , device_slot_interface(mconfig, *this)
+ , device_single_card_slot_interface<device_sun_keyboard_port_interface>(mconfig, *this)
, m_rxd(0)
, m_rxd_handler(*this)
, m_dev(nullptr)
@@ -135,39 +128,12 @@ sun_keyboard_port_device::~sun_keyboard_port_device()
void sun_keyboard_port_device::device_config_complete()
{
- m_dev = dynamic_cast<device_sun_keyboard_port_interface *>(get_card_device());
-}
-
-
-void sun_keyboard_port_device::device_validity_check(validity_checker &valid) const
-{
- device_t *const card(get_card_device());
- if (card && !dynamic_cast<device_sun_keyboard_port_interface *>(card))
- {
- osd_printf_error(
- "Card device %s (%s) does not implement device_sun_keyboard_port_interface\n",
- card->tag(),
- card->name());
- }
-}
-
-
-void sun_keyboard_port_device::device_resolve_objects()
-{
- m_rxd_handler.resolve_safe();
+ m_dev = get_card_device();
}
void sun_keyboard_port_device::device_start()
{
- if (get_card_device() && !m_dev)
- {
- throw emu_fatalerror(
- "Card device %s (%s) does not implement device_sun_keyboard_port_interface\n",
- get_card_device()->tag(),
- get_card_device()->name());
- }
-
save_item(NAME(m_rxd));
m_rxd = 1;
@@ -176,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);
@@ -185,7 +151,7 @@ WRITE_LINE_MEMBER( sun_keyboard_port_device::write_txd )
device_sun_keyboard_port_interface::device_sun_keyboard_port_interface(machine_config const &mconfig, device_t &device)
- : device_slot_card_interface(mconfig, device)
+ : device_interface(device, "sunkbd")
, m_port(dynamic_cast<sun_keyboard_port_device *>(device.owner()))
{
}
diff --git a/src/devices/bus/sunkbd/sunkbd.h b/src/devices/bus/sunkbd/sunkbd.h
index 532193cbf0d..687e92eb5c9 100644
--- a/src/devices/bus/sunkbd/sunkbd.h
+++ b/src/devices/bus/sunkbd/sunkbd.h
@@ -11,7 +11,7 @@
class device_sun_keyboard_port_interface;
-class sun_keyboard_port_device : public device_t, public device_slot_interface
+class sun_keyboard_port_device : public device_t, public device_single_card_slot_interface<device_sun_keyboard_port_interface>
{
friend class device_sun_keyboard_port_interface;
@@ -31,17 +31,15 @@ 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_validity_check(validity_checker &valid) const override;
- virtual void device_resolve_objects() override;
- virtual void device_start() override;
+ virtual void device_start() override ATTR_COLD;
int m_rxd;
@@ -52,7 +50,7 @@ private:
};
-class device_sun_keyboard_port_interface : public device_slot_card_interface
+class device_sun_keyboard_port_interface : public device_interface
{
friend class sun_keyboard_port_device;
@@ -62,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 551a77fac81..34bc4af6de7 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)
@@ -27,33 +26,33 @@
DEVICE TYPE GLOBALS
***************************************************************************/
-DEFINE_DEVICE_TYPE_NS(SUN_1200BAUD_HLE_MOUSE, bus::sunmouse, hle_1200baud_device, "sunmouse_hle1200", "Sun Mouse (1200 Baud, HLE)")
-DEFINE_DEVICE_TYPE_NS(SUN_4800BAUD_HLE_MOUSE, bus::sunmouse, hle_4800baud_device, "sunmouse_hle4800", "Sun Mouse (4800 Baud, HLE)")
+DEFINE_DEVICE_TYPE(SUN_1200BAUD_HLE_MOUSE, bus::sunmouse::hle_1200baud_device, "sunmouse_hle1200", "Sun Mouse (1200 Baud, HLE)")
+DEFINE_DEVICE_TYPE(SUN_4800BAUD_HLE_MOUSE, bus::sunmouse::hle_4800baud_device, "sunmouse_hle4800", "Sun Mouse (4800 Baud, HLE)")
-namespace bus { namespace sunmouse {
+namespace bus::sunmouse {
namespace {
INPUT_PORTS_START( mouse )
PORT_START("BTN")
PORT_BIT( 0xfff8, IP_ACTIVE_HIGH, IPT_UNUSED )
- PORT_BIT( 0x0004, IP_ACTIVE_LOW, IPT_BUTTON1 ) PORT_CODE(MOUSECODE_BUTTON1) PORT_CHANGED_MEMBER(DEVICE_SELF, hle_device_base, input_changed, 0)
- PORT_BIT( 0x0002, IP_ACTIVE_LOW, IPT_BUTTON2 ) PORT_CODE(MOUSECODE_BUTTON3) PORT_CHANGED_MEMBER(DEVICE_SELF, hle_device_base, input_changed, 0)
- PORT_BIT( 0x0001, IP_ACTIVE_LOW, IPT_BUTTON3 ) PORT_CODE(MOUSECODE_BUTTON2) PORT_CHANGED_MEMBER(DEVICE_SELF, hle_device_base, input_changed, 0)
+ PORT_BIT( 0x0004, IP_ACTIVE_LOW, IPT_BUTTON1 ) PORT_CODE(MOUSECODE_BUTTON1) PORT_CHANGED_MEMBER(DEVICE_SELF, FUNC(hle_device_base::input_changed), 0)
+ PORT_BIT( 0x0002, IP_ACTIVE_LOW, IPT_BUTTON2 ) PORT_CODE(MOUSECODE_BUTTON3) PORT_CHANGED_MEMBER(DEVICE_SELF, FUNC(hle_device_base::input_changed), 0)
+ PORT_BIT( 0x0001, IP_ACTIVE_LOW, IPT_BUTTON3 ) PORT_CODE(MOUSECODE_BUTTON2) PORT_CHANGED_MEMBER(DEVICE_SELF, FUNC(hle_device_base::input_changed), 0)
PORT_START("X")
PORT_BIT( 0xf000, IP_ACTIVE_HIGH, IPT_UNUSED )
- PORT_BIT( 0x0fff, 0x00, IPT_MOUSE_X ) PORT_SENSITIVITY(100) PORT_KEYDELTA(0) PORT_CHANGED_MEMBER(DEVICE_SELF, hle_device_base, input_changed, 0)
+ PORT_BIT( 0x0fff, 0x00, IPT_MOUSE_X ) PORT_SENSITIVITY(100) PORT_KEYDELTA(0) PORT_CHANGED_MEMBER(DEVICE_SELF, FUNC(hle_device_base::input_changed), 0)
PORT_START("Y")
PORT_BIT( 0xf000, IP_ACTIVE_HIGH, IPT_UNUSED )
- PORT_BIT( 0x0fff, 0x00, IPT_MOUSE_Y ) PORT_SENSITIVITY(100) PORT_KEYDELTA(0) PORT_CHANGED_MEMBER(DEVICE_SELF, hle_device_base, input_changed, 0)
+ PORT_BIT( 0x0fff, 0x00, IPT_MOUSE_Y ) PORT_SENSITIVITY(100) PORT_KEYDELTA(0) PORT_CHANGED_MEMBER(DEVICE_SELF, FUNC(hle_device_base::input_changed), 0)
INPUT_PORTS_END
uint8_t extract_delta_byte(int32_t &delta)
{
- int32_t const result(std::min<int32_t>(std::max<int32_t>(delta, -120), 127));
+ int32_t const result(std::clamp<int32_t>(delta, -120, 127));
delta -= result;
return uint8_t(int8_t(result));
}
@@ -229,6 +228,7 @@ void hle_device_base::tra_complete()
m_y_delta);
//break; uncommenting this causes problems with early versions of Solaris
}
+ [[fallthrough]];
case 1U:
LOG("Sent %s (B=%X->%x X=%d Y=%d) - sending X delta\n",
(1U == m_phase) ? "button state" : "Y delta",
@@ -292,7 +292,7 @@ hle_1200baud_device::hle_1200baud_device(
char const *tag,
device_t *owner,
uint32_t clock)
- : hle_device_base(mconfig, SUN_1200BAUD_HLE_MOUSE, tag, owner, clock, 8U) // FIXME: hack because z80scc isn't working properly
+ : hle_device_base(mconfig, SUN_1200BAUD_HLE_MOUSE, tag, owner, clock, 1U)
{
}
@@ -311,4 +311,4 @@ hle_4800baud_device::hle_4800baud_device(
{
}
-} } // namespace bus::sunmouse
+} // namespace bus::sunmouse
diff --git a/src/devices/bus/sunmouse/hlemouse.h b/src/devices/bus/sunmouse/hlemouse.h
index 6eb5cf44b63..270aa0d408a 100644
--- a/src/devices/bus/sunmouse/hlemouse.h
+++ b/src/devices/bus/sunmouse/hlemouse.h
@@ -1,7 +1,7 @@
// license:BSD-3-Clause
// copyright-holders:Vas Crabb
-#ifndef MAME_DEVICES_SUNMOUSE_HLEMOUSE_H
-#define MAME_DEVICES_SUNMOUSE_HLEMOUSE_H
+#ifndef MAME_BUS_SUNMOUSE_HLEMOUSE_H
+#define MAME_BUS_SUNMOUSE_HLEMOUSE_H
#pragma once
@@ -9,7 +9,7 @@
#include "diserial.h"
-namespace bus { namespace sunmouse {
+namespace bus::sunmouse {
class hle_device_base
: public device_t
@@ -32,9 +32,9 @@ protected:
unsigned multiplier);
// device overrides
- virtual ioport_constructor device_input_ports() const override;
- virtual void device_start() override;
- virtual void device_reset() override;
+ virtual ioport_constructor device_input_ports() const override ATTR_COLD;
+ virtual void device_start() override ATTR_COLD;
+ virtual void device_reset() override ATTR_COLD;
// device_serial_interface overrides
virtual void tra_callback() override;
@@ -73,10 +73,10 @@ public:
uint32_t clock);
};
-} } // namespace bus::sunmouse
+} // namespace bus::sunmouse
DECLARE_DEVICE_TYPE_NS(SUN_1200BAUD_HLE_MOUSE, bus::sunmouse, hle_1200baud_device)
DECLARE_DEVICE_TYPE_NS(SUN_4800BAUD_HLE_MOUSE, bus::sunmouse, hle_4800baud_device)
-#endif // MAME_DEVICES_SUNMOUSE_HLEMOUSE_H
+#endif // MAME_BUS_SUNMOUSE_HLEMOUSE_H
diff --git a/src/devices/bus/sunmouse/sunmouse.cpp b/src/devices/bus/sunmouse/sunmouse.cpp
index 9b59529c54a..15635831ed2 100644
--- a/src/devices/bus/sunmouse/sunmouse.cpp
+++ b/src/devices/bus/sunmouse/sunmouse.cpp
@@ -72,13 +72,6 @@
DEFINE_DEVICE_TYPE(SUNMOUSE_PORT, sun_mouse_port_device, "sunmouse", "Sun Mouse Port")
-int const device_sun_mouse_port_interface::START_BIT_COUNT;
-int const device_sun_mouse_port_interface::DATA_BIT_COUNT;
-device_serial_interface::parity_t const device_sun_mouse_port_interface::PARITY;
-device_serial_interface::stop_bits_t const device_sun_mouse_port_interface::STOP_BITS;
-int const device_sun_mouse_port_interface::BAUD;
-
-
sun_mouse_port_device::sun_mouse_port_device(
machine_config const &mconfig,
@@ -97,7 +90,7 @@ sun_mouse_port_device::sun_mouse_port_device(
device_t *owner,
uint32_t clock)
: device_t(mconfig, type, tag, owner, clock)
- , device_slot_interface(mconfig, *this)
+ , device_single_card_slot_interface<device_sun_mouse_port_interface>(mconfig, *this)
, m_rxd(0)
, m_rxd_handler(*this)
, m_dev(nullptr)
@@ -112,41 +105,18 @@ sun_mouse_port_device::~sun_mouse_port_device()
void sun_mouse_port_device::device_config_complete()
{
- m_dev = dynamic_cast<device_sun_mouse_port_interface *>(get_card_device());
-}
-
-
-void sun_mouse_port_device::device_validity_check(validity_checker &valid) const
-{
- device_t *const card(get_card_device());
- if (card && !dynamic_cast<device_sun_mouse_port_interface *>(card))
- {
- osd_printf_error(
- "Card device %s (%s) does not implement device_sun_mouse_port_interface\n",
- card->tag(),
- card->name());
- }
+ m_dev = get_card_device();
}
void sun_mouse_port_device::device_resolve_objects()
{
m_rxd = 1;
-
- m_rxd_handler.resolve_safe();
}
void sun_mouse_port_device::device_start()
{
- if (get_card_device() && !m_dev)
- {
- throw emu_fatalerror(
- "Card device %s (%s) does not implement device_sun_mouse_port_interface\n",
- get_card_device()->tag(),
- get_card_device()->name());
- }
-
save_item(NAME(m_rxd));
if (!m_dev)
@@ -154,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);
@@ -163,7 +133,7 @@ WRITE_LINE_MEMBER( sun_mouse_port_device::write_txd )
device_sun_mouse_port_interface::device_sun_mouse_port_interface(machine_config const &mconfig, device_t &device)
- : device_slot_card_interface(mconfig, device)
+ : device_interface(device, "sunmouse")
, m_port(dynamic_cast<sun_mouse_port_device *>(device.owner()))
{
}
diff --git a/src/devices/bus/sunmouse/sunmouse.h b/src/devices/bus/sunmouse/sunmouse.h
index ff7dd9ca86a..e36e94bd6fb 100644
--- a/src/devices/bus/sunmouse/sunmouse.h
+++ b/src/devices/bus/sunmouse/sunmouse.h
@@ -11,7 +11,7 @@
class device_sun_mouse_port_interface;
-class sun_mouse_port_device : public device_t, public device_slot_interface
+class sun_mouse_port_device : public device_t, public device_single_card_slot_interface<device_sun_mouse_port_interface>
{
friend class device_sun_mouse_port_interface;
@@ -31,17 +31,16 @@ 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);
virtual void device_config_complete() override;
- virtual void device_validity_check(validity_checker &valid) const override;
- virtual void device_resolve_objects() override;
- virtual void device_start() override;
+ virtual void device_resolve_objects() override ATTR_COLD;
+ virtual void device_start() override ATTR_COLD;
int m_rxd;
@@ -52,7 +51,7 @@ private:
};
-class device_sun_mouse_port_interface : public device_slot_card_interface
+class device_sun_mouse_port_interface : public device_interface
{
friend class sun_mouse_port_device;
@@ -62,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/supracan/rom.cpp b/src/devices/bus/supracan/rom.cpp
new file mode 100644
index 00000000000..ca3be333df6
--- /dev/null
+++ b/src/devices/bus/supracan/rom.cpp
@@ -0,0 +1,96 @@
+// license:BSD-3-Clause
+// copyright-holders:
+
+#include "emu.h"
+#include "rom.h"
+
+
+//-------------------------------------------------
+// superacan_rom_device - constructor
+//-------------------------------------------------
+
+DEFINE_DEVICE_TYPE(SUPERACAN_ROM_STD, superacan_rom_device, "superacan_rom", "Super A'Can Standard Cart")
+
+
+superacan_rom_device::superacan_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_superacan_cart_interface(mconfig, *this)
+ , m_rom_base(nullptr)
+ , m_nvram_base(nullptr)
+ , m_rom_size(0)
+ , m_nvram_size(0)
+{
+}
+
+superacan_rom_device::superacan_rom_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock)
+ : superacan_rom_device(mconfig, SUPERACAN_ROM_STD, tag, owner, clock)
+{
+}
+
+
+void superacan_rom_device::device_start()
+{
+}
+
+void superacan_rom_device::device_add_mconfig(machine_config &config)
+{
+ // TODO: move UM6650 from funtech folder
+}
+
+std::error_condition superacan_rom_device::load()
+{
+ memory_region *const romregion = memregion("^rom");
+ m_rom_base = reinterpret_cast<const u16 *>(romregion->base());
+ m_rom_size = romregion->bytes() / 2;
+
+// if (m_rom_size > 0x40'0000)
+// return std::make_pair(image_error::INVALIDLENGTH, "Unsupported cartridge size (must be no larger than 4M)");
+
+ 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, 0xff);
+ }
+
+ return std::error_condition();
+}
+
+
+void superacan_rom_device::unload()
+{
+ if (m_nvram_base)
+ battery_save(m_nvram_base, m_nvram_size);
+}
+
+
+/*-------------------------------------------------
+ read/write
+ -------------------------------------------------*/
+
+u16 superacan_rom_device::rom_r(offs_t offset)
+{
+ if (offset < m_rom_size)
+ return m_rom_base[offset];
+ else
+ return 0xffff;
+}
+
+u8 superacan_rom_device::nvram_r(offs_t offset)
+{
+ if (m_nvram_base)
+ return m_nvram_base[offset & (m_nvram_size - 1)];
+ else
+ return 0xff;
+}
+
+void superacan_rom_device::nvram_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/supracan/rom.h b/src/devices/bus/supracan/rom.h
new file mode 100644
index 00000000000..80f4fd42ed4
--- /dev/null
+++ b/src/devices/bus/supracan/rom.h
@@ -0,0 +1,46 @@
+// license:BSD-3-Clause
+// copyright-holders:
+#ifndef MAME_BUS_SUPRACAN_ROM_H
+#define MAME_BUS_SUPRACAN_ROM_H
+
+#pragma once
+
+#include "slot.h"
+
+
+// ======================> superacan_rom_device
+
+class superacan_rom_device : public device_t,
+ public device_superacan_cart_interface
+{
+public:
+ // construction/destruction
+ superacan_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 nvram_r(offs_t offset) override;
+ virtual void nvram_w(offs_t offset, u8 data) override;
+
+protected:
+ superacan_rom_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, u32 clock);
+
+ virtual void device_start() override ATTR_COLD;
+
+ virtual void device_add_mconfig(machine_config &config) override ATTR_COLD;
+
+private:
+ const u16 *m_rom_base;
+ u8 *m_nvram_base;
+ u32 m_rom_size;
+ u32 m_nvram_size;
+};
+
+
+DECLARE_DEVICE_TYPE(SUPERACAN_ROM_STD, superacan_rom_device)
+
+#endif // MAME_BUS_SUPRACAN_ROM_H
diff --git a/src/devices/bus/supracan/slot.cpp b/src/devices/bus/supracan/slot.cpp
new file mode 100644
index 00000000000..19f10c449f6
--- /dev/null
+++ b/src/devices/bus/supracan/slot.cpp
@@ -0,0 +1,116 @@
+// license:BSD-3-Clause
+// copyright-holders:
+
+#include "emu.h"
+#include "slot.h"
+
+
+DEFINE_DEVICE_TYPE(SUPERACAN_CART_SLOT, superacan_cart_slot_device, "superacan_cart_slot", "Super A'Can Cartridge Slot")
+
+
+device_superacan_cart_interface::device_superacan_cart_interface(const machine_config &mconfig, device_t &device)
+ : device_interface(device, "superacan_cart")
+ , m_slot(dynamic_cast<superacan_cart_slot_device *>(device.owner()))
+{
+}
+
+
+device_superacan_cart_interface::~device_superacan_cart_interface()
+{
+}
+
+
+void device_superacan_cart_interface::battery_load(void *buffer, int length, int fill)
+{
+ assert(m_slot);
+ m_slot->battery_load(buffer, length, fill);
+}
+
+void device_superacan_cart_interface::battery_load(void *buffer, int length, void *def_buffer)
+{
+ assert(m_slot);
+ m_slot->battery_load(buffer, length, def_buffer);
+}
+
+void device_superacan_cart_interface::battery_save(const void *buffer, int length)
+{
+ assert(m_slot);
+ m_slot->battery_save(buffer, length);
+}
+
+
+superacan_cart_slot_device::superacan_cart_slot_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock) :
+ device_t(mconfig, SUPERACAN_CART_SLOT, tag, owner, clock),
+ device_cartrom_image_interface(mconfig, *this),
+ device_single_card_slot_interface<device_superacan_cart_interface>(mconfig, *this),
+ m_cart(nullptr)
+{
+}
+
+
+//-------------------------------------------------
+// superacan_cart_slot_device - destructor
+//-------------------------------------------------
+
+superacan_cart_slot_device::~superacan_cart_slot_device()
+{
+}
+
+//-------------------------------------------------
+// device_start - device-specific startup
+//-------------------------------------------------
+
+void superacan_cart_slot_device::device_start()
+{
+ m_cart = get_card_device();
+}
+
+
+
+/*-------------------------------------------------
+ call load
+ -------------------------------------------------*/
+
+std::pair<std::error_condition, std::string> superacan_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");
+ }
+
+ return std::make_pair(m_cart->load(), std::string());
+}
+
+
+/*-------------------------------------------------
+ call unload
+ -------------------------------------------------*/
+
+void superacan_cart_slot_device::call_unload()
+{
+ if (m_cart)
+ m_cart->unload();
+}
+
+
+/*-------------------------------------------------
+ get default card software
+ -------------------------------------------------*/
+
+std::string superacan_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/supracan/slot.h b/src/devices/bus/supracan/slot.h
new file mode 100644
index 00000000000..6b3f308d64f
--- /dev/null
+++ b/src/devices/bus/supracan/slot.h
@@ -0,0 +1,90 @@
+// license:BSD-3-Clause
+// copyright-holders:
+
+#ifndef MAME_BUS_SUPRACAN_SLOT_H
+#define MAME_BUS_SUPRACAN_SLOT_H
+
+#include "imagedev/cartrom.h"
+
+#include <system_error>
+#include <utility>
+
+
+/***************************************************************************
+ TYPE DEFINITIONS
+ ***************************************************************************/
+
+class superacan_cart_slot_device;
+
+
+class device_superacan_cart_interface : public device_interface
+{
+public:
+ virtual ~device_superacan_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 nvram_r(offs_t offset) = 0;
+ virtual void nvram_w(offs_t offset, u8 data) = 0;
+
+protected:
+ // construction/destruction
+ device_superacan_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:
+ superacan_cart_slot_device *const m_slot;
+};
+
+
+class superacan_cart_slot_device : public device_t,
+ public device_cartrom_image_interface,
+ public device_single_card_slot_interface<device_superacan_cart_interface>
+{
+public:
+ // construction/destruction
+ template <typename T>
+ superacan_cart_slot_device(machine_config const &mconfig, char const *tag, device_t *owner, u32 clock, T &&opts, char const *dflt)
+ : superacan_cart_slot_device(mconfig, tag, owner, clock)
+ {
+ option_reset();
+ opts(*this);
+ set_default_option(dflt);
+ set_fixed(false);
+ }
+ superacan_cart_slot_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock);
+ virtual ~superacan_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 "superacan_cart"; }
+ virtual const char *file_extensions() const noexcept override { return "bin"; }
+
+ 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 nvram_r(offs_t offset) { return m_cart ? m_cart->nvram_r(offset) : 0xff; }
+ void nvram_w(offs_t offset, u8 data) { if (m_cart) m_cart->nvram_w(offset, data); }
+
+protected:
+ // device_t implementation
+ virtual void device_start() override ATTR_COLD;
+
+ device_superacan_cart_interface *m_cart;
+};
+
+DECLARE_DEVICE_TYPE(SUPERACAN_CART_SLOT, superacan_cart_slot_device)
+
+#endif // MAME_BUS_SUPRACAN_SLOT_H
diff --git a/src/devices/bus/svi3x8/expander/expander.cpp b/src/devices/bus/svi3x8/expander/expander.cpp
index e9653827fcf..6c305e47082 100644
--- a/src/devices/bus/svi3x8/expander/expander.cpp
+++ b/src/devices/bus/svi3x8/expander/expander.cpp
@@ -29,14 +29,15 @@ 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_slot_interface(mconfig, *this),
+ 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_excsr_handler(*this, 0xff),
m_excsw_handler(*this)
{
}
@@ -56,24 +57,7 @@ svi_expander_device::~svi_expander_device()
void svi_expander_device::device_start()
{
// get inserted module
- m_module = dynamic_cast<device_svi_expander_interface *>(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();
-}
-
-//-------------------------------------------------
-// device_reset - device-specific reset
-//-------------------------------------------------
-
-void svi_expander_device::device_reset()
-{
+ m_module = get_card_device();
}
//-------------------------------------------------
@@ -114,28 +98,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);
}
@@ -148,7 +132,7 @@ WRITE_LINE_MEMBER( svi_expander_device::bk32_w )
//-------------------------------------------------
device_svi_expander_interface::device_svi_expander_interface(const machine_config &mconfig, device_t &device) :
- device_slot_card_interface(mconfig, device)
+ device_interface(device, "svi3x8exp")
{
m_expander = dynamic_cast<svi_expander_device *>(device.owner());
}
diff --git a/src/devices/bus/svi3x8/expander/expander.h b/src/devices/bus/svi3x8/expander/expander.h
index cc7e75f6332..3a8182ad12c 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_slot_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,15 +92,14 @@ 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
- virtual void device_start() override;
- virtual void device_reset() override;
+ virtual void device_start() override ATTR_COLD;
private:
device_svi_expander_interface *m_module;
@@ -113,9 +114,12 @@ private:
devcb_write8 m_excsw_handler;
};
-// ======================> device_svi_expander_interface
-class device_svi_expander_interface : public device_slot_card_interface
+//**************************************************************************
+// CARD INTERFACE
+//**************************************************************************
+
+class device_svi_expander_interface : public device_interface
{
public:
// construction/destruction
@@ -137,7 +141,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 aec81c79ae6..f37c844d5ab 100644
--- a/src/devices/bus/svi3x8/expander/sv601.cpp
+++ b/src/devices/bus/svi3x8/expander/sv601.cpp
@@ -26,13 +26,13 @@ void sv601_device::device_add_mconfig(machine_config &config)
m_slotbus->int_handler().set(FUNC(sv601_device::int_w));
m_slotbus->romdis_handler().set(FUNC(sv601_device::romdis_w));
m_slotbus->ramdis_handler().set(FUNC(sv601_device::ramdis_w));
- SVI_SLOT(config, "0", svi_slot_cards, nullptr);
- SVI_SLOT(config, "1", svi_slot_cards, nullptr);
- SVI_SLOT(config, "2", svi_slot_cards, nullptr);
- SVI_SLOT(config, "3", svi_slot_cards, nullptr);
- SVI_SLOT(config, "4", svi_slot_cards, nullptr);
- SVI_SLOT(config, "5", svi_slot_cards, nullptr);
- SVI_SLOT(config, "6", svi_slot_cards, nullptr);
+ SVI_SLOT(config, "0", m_slotbus, svi_slot_cards, nullptr);
+ SVI_SLOT(config, "1", m_slotbus, svi_slot_cards, nullptr);
+ SVI_SLOT(config, "2", m_slotbus, svi_slot_cards, nullptr);
+ SVI_SLOT(config, "3", m_slotbus, svi_slot_cards, nullptr);
+ SVI_SLOT(config, "4", m_slotbus, svi_slot_cards, nullptr);
+ SVI_SLOT(config, "5", m_slotbus, svi_slot_cards, nullptr);
+ SVI_SLOT(config, "6", m_slotbus, svi_slot_cards, nullptr);
}
@@ -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..f18a4ff4509 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;
@@ -44,8 +44,8 @@ public:
virtual void bk32_w(int state) override;
protected:
- virtual void device_add_mconfig(machine_config &config) override;
- virtual void device_start() override;
+ virtual void device_add_mconfig(machine_config &config) override ATTR_COLD;
+ virtual void device_start() override ATTR_COLD;
private:
required_device<svi_slot_bus_device> m_slotbus;
diff --git a/src/devices/bus/svi3x8/expander/sv602.cpp b/src/devices/bus/svi3x8/expander/sv602.cpp
index 25624a83e9a..3143d9239f1 100644
--- a/src/devices/bus/svi3x8/expander/sv602.cpp
+++ b/src/devices/bus/svi3x8/expander/sv602.cpp
@@ -26,7 +26,7 @@ void sv602_device::device_add_mconfig(machine_config &config)
m_slotbus->int_handler().set(FUNC(sv602_device::int_w));
m_slotbus->romdis_handler().set(FUNC(sv602_device::romdis_w));
m_slotbus->ramdis_handler().set(FUNC(sv602_device::ramdis_w));
- SVI_SLOT(config, "0", sv602_slot_cards, nullptr);
+ SVI_SLOT(config, "0", m_slotbus, sv602_slot_cards, nullptr);
}
@@ -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..b1bad9af7a6 100644
--- a/src/devices/bus/svi3x8/expander/sv602.h
+++ b/src/devices/bus/svi3x8/expander/sv602.h
@@ -39,14 +39,14 @@ public:
virtual void bk32_w(int state) override;
protected:
- virtual void device_add_mconfig(machine_config &config) override;
- virtual void device_start() override;
+ virtual void device_add_mconfig(machine_config &config) override ATTR_COLD;
+ virtual void device_start() override ATTR_COLD;
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 fc8e8c86d96..c52902cc69c 100644
--- a/src/devices/bus/svi3x8/expander/sv603.cpp
+++ b/src/devices/bus/svi3x8/expander/sv603.cpp
@@ -8,8 +8,7 @@
#include "emu.h"
#include "sv603.h"
-#include "softlist.h"
-#include "speaker.h"
+#include "softlist_dev.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..46b6e33b154 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,13 +33,13 @@ 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;
- 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 ATTR_COLD;
+ 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:
required_memory_region m_bios;
@@ -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 eb2137ce629..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,28 +42,16 @@ 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();
-}
-
-//-------------------------------------------------
-// device_reset - device-specific reset
-//-------------------------------------------------
-
-void svi_slot_bus_device::device_reset()
-{
}
//-------------------------------------------------
// add_card - add new card to our bus
//-------------------------------------------------
-void svi_slot_bus_device::add_card(device_svi_slot_interface *card)
+void svi_slot_bus_device::add_card(device_svi_slot_interface &card)
{
- card->set_bus_device(this);
- m_dev.append(*card);
+ card.set_bus_device(*this);
+ m_dev.emplace_back(card);
}
//-------------------------------------------------
@@ -73,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;
}
@@ -91,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);
}
//-------------------------------------------------
@@ -106,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;
}
@@ -124,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);
}
@@ -206,7 +155,8 @@ DEFINE_DEVICE_TYPE(SVI_SLOT, svi_slot_device, "svislot", "SVI Slot")
svi_slot_device::svi_slot_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
: device_t(mconfig, SVI_SLOT, tag, owner, clock)
- , device_slot_interface(mconfig, *this)
+ , device_single_card_slot_interface<device_svi_slot_interface>(mconfig, *this)
+ , m_bus(*this, finder_base::DUMMY_TAG)
{
}
@@ -216,21 +166,9 @@ svi_slot_device::svi_slot_device(const machine_config &mconfig, const char *tag,
void svi_slot_device::device_start()
{
- device_svi_slot_interface *dev = dynamic_cast<device_svi_slot_interface *>(get_card_device());
-
+ device_svi_slot_interface *dev = get_card_device();
if (dev)
- {
- svi_slot_bus_device *bus = downcast<svi_slot_bus_device *>(owner()->subdevice(SVIBUS_TAG));
- bus->add_card(dev);
- }
-}
-
-//-------------------------------------------------
-// device_reset - device-specific reset
-//-------------------------------------------------
-
-void svi_slot_device::device_reset()
-{
+ m_bus->add_card(*dev);
}
@@ -243,9 +181,8 @@ void svi_slot_device::device_reset()
//-------------------------------------------------
device_svi_slot_interface::device_svi_slot_interface(const machine_config &mconfig, device_t &device) :
- device_slot_card_interface(mconfig, device),
- m_bus(nullptr),
- m_next(nullptr)
+ device_interface(device, "svi3x8slot"),
+ m_bus(nullptr)
{
}
@@ -261,7 +198,8 @@ device_svi_slot_interface::~device_svi_slot_interface()
// set_bus_device - set bus we are attached to
//-------------------------------------------------
-void device_svi_slot_interface::set_bus_device(svi_slot_bus_device *bus)
+void device_svi_slot_interface::set_bus_device(svi_slot_bus_device &bus)
{
- m_bus = bus;
+ assert(!device().started());
+ m_bus = &bus;
}
diff --git a/src/devices/bus/svi3x8/slot/slot.h b/src/devices/bus/svi3x8/slot/slot.h
index 756f17658fd..9d48c6d3630 100644
--- a/src/devices/bus/svi3x8/slot/slot.h
+++ b/src/devices/bus/svi3x8/slot/slot.h
@@ -39,12 +39,9 @@
#pragma once
+#include <functional>
+#include <vector>
-//**************************************************************************
-// CONSTANTS / MACROS
-//**************************************************************************
-
-#define SVIBUS_TAG "slot_bux"
//**************************************************************************
@@ -67,12 +64,12 @@ public:
auto romdis_handler() { return m_romdis_handler.bind(); }
auto ramdis_handler() { return m_ramdis_handler.bind(); }
- void add_card(device_svi_slot_interface *card);
+ 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);
@@ -80,17 +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
- virtual void device_start() override;
- virtual void device_reset() override;
+ using card_vector = std::vector<std::reference_wrapper<device_svi_slot_interface> >;
+
+ // device_t implementation
+ virtual void device_start() override ATTR_COLD;
- simple_list<device_svi_slot_interface> m_dev;
+ card_vector m_dev;
devcb_write_line m_int_handler;
devcb_write_line m_romdis_handler;
@@ -102,29 +100,31 @@ DECLARE_DEVICE_TYPE(SVI_SLOT_BUS, svi_slot_bus_device)
// ======================> svi_slot_device
-class svi_slot_device : public device_t, public device_slot_interface
+class svi_slot_device : public device_t, public device_single_card_slot_interface<device_svi_slot_interface>
{
public:
// construction/destruction
- template <typename T>
- svi_slot_device(machine_config const &mconfig, char const *tag, device_t *owner, T &&opts, char const *dflt)
+ template <typename T, typename U>
+ svi_slot_device(machine_config const &mconfig, char const *tag, device_t *owner, T &&bus, U &&opts, char const *dflt)
: svi_slot_device(mconfig, tag, owner, 0)
{
option_reset();
opts(*this);
set_default_option(dflt);
set_fixed(false);
+ set_bus(std::forward<T>(bus));
}
svi_slot_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
+ template <typename T> void set_bus(T &&tag) { m_bus.set_tag(std::forward<T>(tag)); }
+
protected:
- // device-level overrides
- virtual void device_start() override;
- virtual void device_reset() override;
+ // device_t implementation
+ virtual void device_start() override ATTR_COLD;
// configuration
- const char *m_bus_tag;
+ required_device<svi_slot_bus_device> m_bus;
};
// device type definition
@@ -132,34 +132,28 @@ DECLARE_DEVICE_TYPE(SVI_SLOT, svi_slot_device)
// ======================> svi_slot_device
-class device_svi_slot_interface : public device_slot_card_interface
+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; }
+ void set_bus_device(svi_slot_bus_device &bus);
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 9d73b62aec1..514a844e3a0 100644
--- a/src/devices/bus/svi3x8/slot/sv801.cpp
+++ b/src/devices/bus/svi3x8/slot/sv801.cpp
@@ -8,7 +8,7 @@
#include "emu.h"
#include "sv801.h"
-#include "softlist.h"
+#include "softlist_dev.h"
#include "formats/svi_dsk.h"
@@ -18,9 +18,11 @@
DEFINE_DEVICE_TYPE(SV801, sv801_device, "sv801", "SV-801 Disk Controller")
-FLOPPY_FORMATS_MEMBER( sv801_device::floppy_formats )
- FLOPPY_SVI_FORMAT
-FLOPPY_FORMATS_END
+void sv801_device::floppy_formats(format_registration &fr)
+{
+ fr.add_mfm_containers();
+ fr.add(FLOPPY_SVI_FORMAT);
+}
static void svi_floppies(device_slot_interface &device)
{
@@ -87,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 29c2014b872..59773b0380b 100644
--- a/src/devices/bus/svi3x8/slot/sv801.h
+++ b/src/devices/bus/svi3x8/slot/sv801.h
@@ -32,17 +32,17 @@ public:
virtual void iorq_w(offs_t offset, uint8_t data) override;
protected:
- virtual void device_add_mconfig(machine_config &config) override;
- virtual void device_start() override;
- virtual void device_reset() override;
+ 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:
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);
- DECLARE_FLOPPY_FORMATS(floppy_formats);
+ static void floppy_formats(format_registration &fr);
required_device<fd1793_device> m_fdc;
required_device<floppy_connector> m_floppy0;
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..9345b736305 100644
--- a/src/devices/bus/svi3x8/slot/sv802.h
+++ b/src/devices/bus/svi3x8/slot/sv802.h
@@ -32,11 +32,11 @@ public:
virtual void iorq_w(offs_t offset, uint8_t data) override;
protected:
- virtual void device_add_mconfig(machine_config &config) override;
- virtual void device_start() override;
+ virtual void device_add_mconfig(machine_config &config) override ATTR_COLD;
+ virtual void device_start() override ATTR_COLD;
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/sv803.h b/src/devices/bus/svi3x8/slot/sv803.h
index 8cae18acf64..60a8a089812 100644
--- a/src/devices/bus/svi3x8/slot/sv803.h
+++ b/src/devices/bus/svi3x8/slot/sv803.h
@@ -30,8 +30,8 @@ public:
virtual void mreq_w(offs_t offset, uint8_t data) override;
protected:
- virtual void device_start() override;
- virtual void device_reset() override;
+ virtual void device_start() override ATTR_COLD;
+ virtual void device_reset() override ATTR_COLD;
private:
std::unique_ptr<uint8_t[]> m_ram;
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..96c27612d54 100644
--- a/src/devices/bus/svi3x8/slot/sv805.h
+++ b/src/devices/bus/svi3x8/slot/sv805.h
@@ -32,11 +32,11 @@ public:
virtual void iorq_w(offs_t offset, uint8_t data) override;
protected:
- virtual void device_add_mconfig(machine_config &config) override;
- virtual void device_start() override;
+ virtual void device_add_mconfig(machine_config &config) override ATTR_COLD;
+ virtual void device_start() override ATTR_COLD;
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/svi3x8/slot/sv806.cpp b/src/devices/bus/svi3x8/slot/sv806.cpp
index e2319516781..5a7d858d38b 100644
--- a/src/devices/bus/svi3x8/slot/sv806.cpp
+++ b/src/devices/bus/svi3x8/slot/sv806.cpp
@@ -52,7 +52,7 @@ void sv806_device::device_add_mconfig(machine_config &config)
m_crtc->set_screen("80col");
m_crtc->set_show_border_area(false);
m_crtc->set_char_width(8);
- m_crtc->set_update_row_callback(FUNC(sv806_device::crtc_update_row), this);
+ m_crtc->set_update_row_callback(FUNC(sv806_device::crtc_update_row));
}
@@ -94,7 +94,7 @@ void sv806_device::device_start()
MC6845_UPDATE_ROW( sv806_device::crtc_update_row )
{
- const pen_t *pen = m_palette->pens();
+ pen_t const *const pen = m_palette->pens();
for (int i = 0; i < x_count; i++)
{
@@ -103,14 +103,14 @@ MC6845_UPDATE_ROW( sv806_device::crtc_update_row )
if (i == cursor_x)
data = 0xff;
- bitmap.pix32(y, i * 8 + 0) = pen[BIT(data, 7)];
- bitmap.pix32(y, i * 8 + 1) = pen[BIT(data, 6)];
- bitmap.pix32(y, i * 8 + 2) = pen[BIT(data, 5)];
- bitmap.pix32(y, i * 8 + 3) = pen[BIT(data, 4)];
- bitmap.pix32(y, i * 8 + 4) = pen[BIT(data, 3)];
- bitmap.pix32(y, i * 8 + 5) = pen[BIT(data, 2)];
- bitmap.pix32(y, i * 8 + 6) = pen[BIT(data, 1)];
- bitmap.pix32(y, i * 8 + 7) = pen[BIT(data, 0)];
+ bitmap.pix(y, i * 8 + 0) = pen[BIT(data, 7)];
+ bitmap.pix(y, i * 8 + 1) = pen[BIT(data, 6)];
+ bitmap.pix(y, i * 8 + 2) = pen[BIT(data, 5)];
+ bitmap.pix(y, i * 8 + 3) = pen[BIT(data, 4)];
+ bitmap.pix(y, i * 8 + 4) = pen[BIT(data, 3)];
+ bitmap.pix(y, i * 8 + 5) = pen[BIT(data, 2)];
+ bitmap.pix(y, i * 8 + 6) = pen[BIT(data, 1)];
+ bitmap.pix(y, i * 8 + 7) = pen[BIT(data, 0)];
}
}
diff --git a/src/devices/bus/svi3x8/slot/sv806.h b/src/devices/bus/svi3x8/slot/sv806.h
index 095e8291acc..216a722ee97 100644
--- a/src/devices/bus/svi3x8/slot/sv806.h
+++ b/src/devices/bus/svi3x8/slot/sv806.h
@@ -34,9 +34,9 @@ public:
virtual void iorq_w(offs_t offset, uint8_t data) override;
protected:
- 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 const tiny_rom_entry *device_rom_region() const override ATTR_COLD;
+ virtual void device_add_mconfig(machine_config &config) override ATTR_COLD;
+ virtual void device_start() override ATTR_COLD;
private:
MC6845_UPDATE_ROW(crtc_update_row);
diff --git a/src/devices/bus/svi3x8/slot/sv807.h b/src/devices/bus/svi3x8/slot/sv807.h
index 8d12befff79..c84a2fd5d2d 100644
--- a/src/devices/bus/svi3x8/slot/sv807.h
+++ b/src/devices/bus/svi3x8/slot/sv807.h
@@ -27,7 +27,7 @@ public:
sv807_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;
+ virtual ioport_constructor device_input_ports() const override ATTR_COLD;
virtual uint8_t mreq_r(offs_t offset) override;
virtual void mreq_w(offs_t offset, uint8_t data) override;
@@ -38,8 +38,8 @@ public:
virtual void bk32_w(int state) override;
protected:
- virtual void device_start() override;
- virtual void device_reset() override;
+ virtual void device_start() override ATTR_COLD;
+ virtual void device_reset() override ATTR_COLD;
private:
required_ioport m_switch;
diff --git a/src/devices/bus/tanbus/bullsnd.h b/src/devices/bus/tanbus/bullsnd.h
index 1573eab6351..b71813429a4 100644
--- a/src/devices/bus/tanbus/bullsnd.h
+++ b/src/devices/bus/tanbus/bullsnd.h
@@ -29,10 +29,10 @@ public:
protected:
// device-level overrides
- virtual void device_start() override;
+ virtual void device_start() override ATTR_COLD;
// optional information overrides
- virtual void device_add_mconfig(machine_config &config) override;
+ virtual void device_add_mconfig(machine_config &config) override ATTR_COLD;
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;
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..1c4a00a3758
--- /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 ATTR_COLD;
+
+ // optional information overrides
+ virtual void device_add_mconfig(machine_config &config) override ATTR_COLD;
+
+ 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..8aa6fa21634
--- /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 ATTR_COLD;
+
+ // optional information overrides
+ virtual void device_add_mconfig(machine_config &config) override ATTR_COLD;
+
+ 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..cb4020f22b3
--- /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_KEYBOARD_H
+#define MAME_BUS_TANBUS_KEYBOARD_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 ATTR_COLD;
+
+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_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..c5ccdfd47dd
--- /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, FUNC(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..b3d279e2ba0
--- /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 ATTR_COLD;
+
+ // optional information overrides
+ virtual ioport_constructor device_input_ports() const override ATTR_COLD;
+
+ 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..f2e28a1924a
--- /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, FUNC(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..00d3185de07
--- /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 ATTR_COLD;
+ virtual void device_reset() override ATTR_COLD;
+
+ // optional information overrides
+ virtual const tiny_rom_entry *device_rom_region() const override ATTR_COLD;
+ virtual ioport_constructor device_input_ports() const override ATTR_COLD;
+
+ 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..d397ced18fd
--- /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, FUNC(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..aedb3df73a3
--- /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 ATTR_COLD;
+
+ // optional information overrides
+ virtual ioport_constructor device_input_ports() const override ATTR_COLD;
+
+ 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 8463d90b6c5..a74bdddedaf 100644
--- a/src/devices/bus/tanbus/mpvdu.cpp
+++ b/src/devices/bus/tanbus/mpvdu.cpp
@@ -42,7 +42,7 @@ void tanbus_mpvdu_device::device_add_mconfig(machine_config &config)
m_crtc->set_show_border_area(false);
m_crtc->set_char_width(12);
m_crtc->out_vsync_callback().set(FUNC(tanbus_mpvdu_device::vsync_changed));
- m_crtc->set_update_row_callback(FUNC(tanbus_mpvdu_device::crtc_update_row), this);
+ m_crtc->set_update_row_callback(FUNC(tanbus_mpvdu_device::crtc_update_row));
SAA5050(config, m_trom, DERIVED_CLOCK(1, 1));
m_trom->d_cb().set(FUNC(tanbus_mpvdu_device::videoram_r));
@@ -142,20 +142,22 @@ void tanbus_mpvdu_device::set_inhibit_lines(offs_t offset, int &inhram, int &inh
// IMPLEMENTATION
//**************************************************************************
-READ8_MEMBER(tanbus_mpvdu_device::videoram_r)
+uint8_t tanbus_mpvdu_device::videoram_r(offs_t offset)
{
return m_videoram[offset];
}
MC6845_UPDATE_ROW(tanbus_mpvdu_device::crtc_update_row)
{
- uint32_t *p = &bitmap.pix32(y);
+ uint32_t *p = &bitmap.pix(y);
m_trom->lose_w(1);
m_trom->lose_w(0);
for (int column = 0; column < x_count; column++)
{
- m_trom->write(m_videoram[(ma + column) & 0x7ff]);
+ uint8_t code = m_videoram[(ma + column) & 0x7ff];
+
+ m_trom->write(code);
m_trom->f1_w(1);
m_trom->f1_w(0);
@@ -167,16 +169,18 @@ MC6845_UPDATE_ROW(tanbus_mpvdu_device::crtc_update_row)
int col = m_trom->get_rgb() ^ ((column == cursor_x) ? 7 : 0);
- int r = BIT(col, 0) * 0xff;
- int g = BIT(col, 1) * 0xff;
- int b = BIT(col, 2) * 0xff;
+ if (BIT(code, 7)) col ^= 0x07;
+
+ int const r = BIT(col, 0) * 0xff;
+ int const g = BIT(col, 1) * 0xff;
+ int const b = BIT(col, 2) * 0xff;
*p++ = rgb_t(r, g, b);
}
}
}
-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 c4c48b96199..5fff82fb7c7 100644
--- a/src/devices/bus/tanbus/mpvdu.h
+++ b/src/devices/bus/tanbus/mpvdu.h
@@ -33,19 +33,19 @@ public:
protected:
// device-level overrides
- virtual void device_start() override;
+ virtual void device_start() override ATTR_COLD;
// optional information overrides
- virtual void device_add_mconfig(machine_config &config) override;
+ virtual void device_add_mconfig(machine_config &config) override ATTR_COLD;
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;
virtual void set_inhibit_lines(offs_t offset, int &inhram, int &inhrom) override;
private:
- DECLARE_READ8_MEMBER(videoram_r);
+ 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..f4232519a16 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 ATTR_COLD;
+
+ 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 void device_start() override ATTR_COLD;
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 ATTR_COLD;
+
+ // optional information overrides
+ virtual const tiny_rom_entry *device_rom_region() const override ATTR_COLD;
+
+ 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 383a8b0d1bb..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,32 +33,37 @@ 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_floppy_formats).enable_sound(true);
- FLOPPY_CONNECTOR(config, m_floppies[1], tandos_floppies, "525qd", floppy_image_device::default_floppy_formats).enable_sound(true);
- FLOPPY_CONNECTOR(config, m_floppies[2], tandos_floppies, nullptr, floppy_image_device::default_floppy_formats).enable_sound(true);
- FLOPPY_CONNECTOR(config, m_floppies[3], tandos_floppies, nullptr, floppy_image_device::default_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>));
- VIA6522(config, m_via, 4_MHz_XTAL / 4);
+ 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 a4eddf8d0f5..615d4f4fad9 100644
--- a/src/devices/bus/tanbus/radisc.h
+++ b/src/devices/bus/tanbus/radisc.h
@@ -13,34 +13,33 @@
#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);
- DECLARE_FLOPPY_FORMATS(floppy_formats);
+ static void floppy_formats(format_registration &fr);
protected:
// device-level overrides
- virtual void device_start() override;
- virtual void device_reset() override;
+ virtual void device_start() override ATTR_COLD;
// optional information overrides
- virtual void device_add_mconfig(machine_config &config) override;
+ virtual void device_add_mconfig(machine_config &config) override ATTR_COLD;
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;
@@ -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 a68a609c18e..2a20e14cbe5 100644
--- a/src/devices/bus/tanbus/ravdu.cpp
+++ b/src/devices/bus/tanbus/ravdu.cpp
@@ -43,7 +43,7 @@ void tanbus_ravdu_device::device_add_mconfig(machine_config &config)
m_crtc->set_show_border_area(false);
m_crtc->set_char_width(12);
m_crtc->out_vsync_callback().set(FUNC(tanbus_ravdu_device::vsync_changed));
- m_crtc->set_update_row_callback(FUNC(tanbus_ravdu_device::crtc_update_row), this);
+ m_crtc->set_update_row_callback(FUNC(tanbus_ravdu_device::crtc_update_row));
SAA5055(config, m_trom, DERIVED_CLOCK(1, 1));
m_trom->d_cb().set(FUNC(tanbus_ravdu_device::videoram_r));
@@ -154,21 +154,23 @@ void tanbus_ravdu_device::set_inhibit_lines(offs_t offset, int &inhram, int &inh
// IMPLEMENTATION
//**************************************************************************
-READ8_MEMBER(tanbus_ravdu_device::videoram_r)
+uint8_t tanbus_ravdu_device::videoram_r(offs_t offset)
{
return m_videoram[offset & 0x7ff];
}
MC6845_UPDATE_ROW(tanbus_ravdu_device::crtc_update_row)
{
- uint32_t *p = &bitmap.pix32(y);
+ uint32_t *p = &bitmap.pix(y);
m_trom->lose_w(1);
m_trom->lose_w(0);
for (int column = 0; column < x_count; column++)
{
- m_trom->write(m_videoram[(ma + column) & 0x7ff]);
+ uint8_t code = m_videoram[(ma + column) & 0x7ff];
+
+ m_trom->write(code);
m_trom->f1_w(1);
m_trom->f1_w(0);
@@ -180,16 +182,18 @@ MC6845_UPDATE_ROW(tanbus_ravdu_device::crtc_update_row)
int col = m_trom->get_rgb() ^ ((column == cursor_x) ? 7 : 0);
- int r = BIT(col, 0) * 0xff;
- int g = BIT(col, 1) * 0xff;
- int b = BIT(col, 2) * 0xff;
+ if (BIT(code, 7)) col ^= 0x07;
+
+ int const r = BIT(col, 0) * 0xff;
+ int const g = BIT(col, 1) * 0xff;
+ int const b = BIT(col, 2) * 0xff;
*p++ = rgb_t(r, g, b);
}
}
}
-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 4817abb78f4..1736178c565 100644
--- a/src/devices/bus/tanbus/ravdu.h
+++ b/src/devices/bus/tanbus/ravdu.h
@@ -33,20 +33,20 @@ public:
protected:
// device-level overrides
- virtual void device_start() override;
- virtual void device_reset() override;
+ virtual void device_start() override ATTR_COLD;
+ virtual void device_reset() override ATTR_COLD;
// optional information overrides
- virtual void device_add_mconfig(machine_config &config) override;
+ virtual void device_add_mconfig(machine_config &config) override ATTR_COLD;
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;
virtual void set_inhibit_lines(offs_t offset, int &inhram, int &inhrom) override;
private:
- DECLARE_READ8_MEMBER(videoram_r);
+ 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 c7d36a1a578..15d4ab8c976 100644
--- a/src/devices/bus/tanbus/tanbus.cpp
+++ b/src/devices/bus/tanbus/tanbus.cpp
@@ -28,29 +28,18 @@ DEFINE_DEVICE_TYPE(TANBUS_SLOT, tanbus_slot_device, "tanbus_slot", "Microtan Bus
//-------------------------------------------------
tanbus_slot_device::tanbus_slot_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
: device_t(mconfig, TANBUS_SLOT, tag, owner, clock)
- , device_slot_interface(mconfig, *this)
+ , device_single_card_slot_interface<device_tanbus_interface>(mconfig, *this)
, m_tanbus(*this, DEVICE_SELF_OWNER)
{
}
//-------------------------------------------------
-// device_validity_check - device-specific checks
-//-------------------------------------------------
-
-void tanbus_slot_device::device_validity_check(validity_checker &valid) const
-{
- device_t *const card(get_card_device());
- if (card && !dynamic_cast<device_tanbus_interface *>(card))
- osd_printf_error("tanbus_slot_device: card device %s (%s) does not implement device_tanbus_interface\n", card->tag(), card->name());
-}
-
-//-------------------------------------------------
// device_start - device-specific startup
//-------------------------------------------------
void tanbus_slot_device::device_start()
{
- device_tanbus_interface *dev = dynamic_cast<device_tanbus_interface *>(get_card_device());
+ device_tanbus_interface *const dev = get_card_device();
if (dev) m_tanbus->add_card(dev, m_bus_num);
}
@@ -78,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);
}
//-------------------------------------------------
@@ -91,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));
}
@@ -115,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);
}
//-------------------------------------------------
@@ -140,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;
@@ -166,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)
@@ -176,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);
}
}
@@ -200,10 +172,9 @@ void tanbus_device::write(offs_t offset, uint8_t data)
//-------------------------------------------------
device_tanbus_interface::device_tanbus_interface(const machine_config &mconfig, device_t &device)
- : device_slot_card_interface(mconfig, device)
+ : device_interface(device, "tanbus")
, m_tanbus(nullptr)
, m_page(0)
- , m_next(nullptr)
{
}
@@ -215,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)
@@ -235,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 315f2d1b1d8..d8dfe06c95e 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>
//**************************************************************************
@@ -25,7 +27,7 @@ class device_tanbus_interface;
// TYPE DEFINITIONS
//**************************************************************************
-class tanbus_slot_device : public device_t, public device_slot_interface
+class tanbus_slot_device : public device_t, public device_single_card_slot_interface<device_tanbus_interface>
{
public:
// construction/destruction
@@ -37,17 +39,16 @@ public:
opts(*this);
set_default_option(dflt);
set_fixed(false);
- set_tanbus_slot(tag, num);
+ set_tanbus_slot(num);
}
tanbus_slot_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
// inline configuration
- void set_tanbus_slot(const char *tag, int num) { m_bus_num = num; }
+ void set_tanbus_slot(int num) { m_bus_num = num; }
protected:
// device-level overrides
- virtual void device_validity_check(validity_checker &valid) const override;
- virtual void device_start() override;
+ virtual void device_start() override ATTR_COLD;
private:
required_device<tanbus_device> m_tanbus;
@@ -67,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(); }
@@ -82,17 +83,17 @@ 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); }
protected:
// device-level overrides
- virtual void device_start() override;
- virtual void device_reset() override;
+ virtual void device_start() override ATTR_COLD;
+ virtual void device_reset() override ATTR_COLD;
private:
// internal state
@@ -107,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;
};
@@ -116,27 +117,21 @@ DECLARE_DEVICE_TYPE(TANBUS, tanbus_device)
// ======================> device_tanbus_interface
-class device_tanbus_interface : public device_slot_card_interface
+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) { }
- virtual void set_inhibit_lines(offs_t offset, int &inhram, int &inhrom) { };
+ virtual void set_inhibit_lines(offs_t offset, int &inhram, int &inhrom) { }
protected:
device_tanbus_interface(const machine_config &mconfig, device_t &device);
tanbus_device *m_tanbus;
int m_page;
-
-private:
- device_tanbus_interface *m_next;
};
@@ -145,6 +140,6 @@ void tanbus_devices(device_slot_interface &device);
void tanbus6809_devices(device_slot_interface &device);
-typedef device_type_iterator<tanbus_slot_device> tanbus_slot_device_iterator;
+typedef device_type_enumerator<tanbus_slot_device> tanbus_slot_device_enumerator;
#endif // MAME_BUS_TANBUS_TANBUS_H
diff --git a/src/devices/bus/tanbus/tandos.cpp b/src/devices/bus/tanbus/tandos.cpp
index c4cbdab00ae..cefecca7cc6 100644
--- a/src/devices/bus/tanbus/tandos.cpp
+++ b/src/devices/bus/tanbus/tandos.cpp
@@ -55,10 +55,33 @@ void tanbus_tandos_device::device_add_mconfig(machine_config &config)
m_fdc->hld_wr_callback().set(FUNC(tanbus_tandos_device::fdc_hld_w));
m_fdc->set_force_ready(true);
- FLOPPY_CONNECTOR(config, m_floppies[0], tandos_floppies, "525qd", floppy_image_device::default_floppy_formats).enable_sound(true);
- FLOPPY_CONNECTOR(config, m_floppies[1], tandos_floppies, "525qd", floppy_image_device::default_floppy_formats).enable_sound(true);
- FLOPPY_CONNECTOR(config, m_floppies[2], tandos_floppies, nullptr, floppy_image_device::default_floppy_formats).enable_sound(true);
- FLOPPY_CONNECTOR(config, m_floppies[3], tandos_floppies, nullptr, floppy_image_device::default_floppy_formats).enable_sound(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);
+
+ 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 f47cb585ec7..962fa2f5048 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; }
@@ -30,34 +30,36 @@ public:
// construction/destruction
tanbus_tandos_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
- DECLARE_FLOPPY_FORMATS(floppy_formats);
+ static void floppy_formats(format_registration &fr);
protected:
// device-level overrides
- virtual void device_start() override;
- virtual void device_reset() override;
+ virtual void device_start() override ATTR_COLD;
+ virtual void device_reset() override ATTR_COLD;
// optional information overrides
- virtual void device_add_mconfig(machine_config &config) override;
- virtual const tiny_rom_entry *device_rom_region() const override;
+ virtual void device_add_mconfig(machine_config &config) override ATTR_COLD;
+ virtual const tiny_rom_entry *device_rom_region() const override ATTR_COLD;
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;
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 1670040da1b..2af60e172e5 100644
--- a/src/devices/bus/tanbus/tanex.cpp
+++ b/src/devices/bus/tanbus/tanex.cpp
@@ -117,7 +117,7 @@ void tanbus_tanex_device::device_add_mconfig(machine_config &config)
m_rs232->cts_handler().set(m_acia, FUNC(mos6551_device::write_cts));
/* via */
- VIA6522(config, m_via6522[0], DERIVED_CLOCK(1, 8));
+ MOS6522(config, m_via6522[0], DERIVED_CLOCK(1, 8));
m_via6522[0]->readpa_handler().set(FUNC(tanbus_tanex_device::via_0_in_a));
m_via6522[0]->writepa_handler().set(FUNC(tanbus_tanex_device::via_0_out_a));
m_via6522[0]->writepb_handler().set(FUNC(tanbus_tanex_device::via_0_out_b));
@@ -125,7 +125,7 @@ void tanbus_tanex_device::device_add_mconfig(machine_config &config)
m_via6522[0]->cb2_handler().set(FUNC(tanbus_tanex_device::via_0_out_cb2));
m_via6522[0]->irq_handler().set(m_irq_line, FUNC(input_merger_device::in_w<IRQ_VIA_0>));
- VIA6522(config, m_via6522[1], DERIVED_CLOCK(1, 8));
+ MOS6522(config, m_via6522[1], DERIVED_CLOCK(1, 8));
m_via6522[1]->writepa_handler().set(FUNC(tanbus_tanex_device::via_1_out_a));
m_via6522[1]->writepb_handler().set(FUNC(tanbus_tanex_device::via_1_out_b));
m_via6522[1]->ca2_handler().set(FUNC(tanbus_tanex_device::via_1_out_ca2));
@@ -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);
}
@@ -380,19 +380,19 @@ WRITE_LINE_MEMBER(tanbus_tanex_device::bus_irq_w)
// VIA callback functions for VIA #0
//**************************************************************
-READ8_MEMBER(tanbus_tanex_device::via_0_in_a)
+uint8_t tanbus_tanex_device::via_0_in_a()
{
int data = ioport("JOY")->read();
LOG("via_0_in_a %02X\n", data);
return data;
}
-WRITE8_MEMBER(tanbus_tanex_device::via_0_out_a)
+void tanbus_tanex_device::via_0_out_a(uint8_t data)
{
LOG("via_0_out_a %02X\n", data);
}
-WRITE8_MEMBER(tanbus_tanex_device::via_0_out_b)
+void tanbus_tanex_device::via_0_out_b(uint8_t data)
{
LOG("via_0_out_b %02X\n", data);
/* bit #5 is the replay cassette drive */
@@ -401,12 +401,12 @@ WRITE8_MEMBER(tanbus_tanex_device::via_0_out_b)
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);
}
@@ -415,22 +415,22 @@ WRITE_LINE_MEMBER(tanbus_tanex_device::via_0_out_cb2)
// VIA callback functions for VIA #1
//**************************************************************
-WRITE8_MEMBER(tanbus_tanex_device::via_1_out_a)
+void tanbus_tanex_device::via_1_out_a(uint8_t data)
{
LOG("via_1_out_a %02X\n", data);
}
-WRITE8_MEMBER(tanbus_tanex_device::via_1_out_b)
+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 757e75f0224..a0a6550a927 100644
--- a/src/devices/bus/tanbus/tanex.h
+++ b/src/devices/bus/tanbus/tanex.h
@@ -36,13 +36,13 @@ public:
protected:
// device-level overrides
- virtual void device_start() override;
- virtual void device_reset() override;
+ virtual void device_start() override ATTR_COLD;
+ virtual void device_reset() override ATTR_COLD;
// 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 void device_add_mconfig(machine_config &config) override ATTR_COLD;
+ virtual const tiny_rom_entry *device_rom_region() const override ATTR_COLD;
+ virtual ioport_constructor device_input_ports() const override ATTR_COLD;
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;
@@ -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);
- DECLARE_READ8_MEMBER(via_0_in_a);
- DECLARE_WRITE8_MEMBER(via_0_out_a);
- DECLARE_WRITE8_MEMBER(via_0_out_b);
- DECLARE_WRITE_LINE_MEMBER(via_0_out_ca2);
- DECLARE_WRITE_LINE_MEMBER(via_0_out_cb2);
- DECLARE_WRITE8_MEMBER(via_1_out_a);
- DECLARE_WRITE8_MEMBER(via_1_out_b);
- DECLARE_WRITE_LINE_MEMBER(via_1_out_ca2);
- DECLARE_WRITE_LINE_MEMBER(via_1_out_cb2);
+ uint8_t via_0_in_a();
+ void via_0_out_a(uint8_t data);
+ void via_0_out_b(uint8_t data);
+ 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);
+ 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/tanhrg.cpp b/src/devices/bus/tanbus/tanhrg.cpp
index 1c8ffc87ab5..b857e84ac69 100644
--- a/src/devices/bus/tanbus/tanhrg.cpp
+++ b/src/devices/bus/tanbus/tanhrg.cpp
@@ -323,16 +323,13 @@ void tanbus_tanhrgc_device::set_inhibit_lines(offs_t offset, int &inhram, int &i
uint32_t tanbus_tanhrg_device::screen_update(screen_device &screen, bitmap_rgb32 &bitmap, const rectangle &cliprect)
{
- uint16_t offset;
- uint32_t *p;
-
for (int y = 0; y < 256; y++)
{
- p = &bitmap.pix32(y);
+ uint32_t *p = &bitmap.pix(y);
for (int x = 0; x < 256; x++)
{
- offset = (y * 32) + (x / 8);
+ uint16_t const offset = (y * 32) + (x / 8);
*p++ = m_palette->pen_color(BIT(m_videoram[offset], x & 7));
}
@@ -344,21 +341,17 @@ uint32_t tanbus_tanhrg_device::screen_update(screen_device &screen, bitmap_rgb32
uint32_t tanbus_tanhrgc_device::screen_update(screen_device &screen, bitmap_rgb32 &bitmap, const rectangle &cliprect)
{
- uint8_t r, g, b;
- uint16_t offset;
- uint32_t *p;
-
for (int y = 0; y < 256; y++)
{
- p = &bitmap.pix32(y);
+ uint32_t *p = &bitmap.pix(y);
for (int x = 0; x < 256; x++)
{
- offset = (y * 32) + (x / 8);
+ uint16_t const offset = (y * 32) + (x / 8);
- r = m_videoram[0x0000 | offset];
- b = m_videoram[0x2000 | offset];
- g = m_videoram[0x4000 | offset];
+ uint8_t const r = m_videoram[0x0000 | offset];
+ uint8_t const b = m_videoram[0x2000 | offset];
+ uint8_t const g = m_videoram[0x4000 | offset];
*p++ = m_palette->pen_color(BIT(b, x & 7) << 2 | BIT(g, x & 7) << 1 | BIT(r, x & 7));
}
diff --git a/src/devices/bus/tanbus/tanhrg.h b/src/devices/bus/tanbus/tanhrg.h
index bce2c68bd78..0db2d8efaec 100644
--- a/src/devices/bus/tanbus/tanhrg.h
+++ b/src/devices/bus/tanbus/tanhrg.h
@@ -30,11 +30,11 @@ public:
protected:
// device-level overrides
- virtual void device_start() override;
+ virtual void device_start() override ATTR_COLD;
// optional information overrides
- virtual void device_add_mconfig(machine_config &config) override;
- virtual ioport_constructor device_input_ports() const override;
+ virtual void device_add_mconfig(machine_config &config) override ATTR_COLD;
+ virtual ioport_constructor device_input_ports() const override ATTR_COLD;
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;
@@ -61,11 +61,11 @@ public:
protected:
// device-level overrides
- virtual void device_start() override;
+ virtual void device_start() override ATTR_COLD;
// optional information overrides
- virtual void device_add_mconfig(machine_config &config) override;
- virtual ioport_constructor device_input_ports() const override;
+ virtual void device_add_mconfig(machine_config &config) override ATTR_COLD;
+ virtual ioport_constructor device_input_ports() const override ATTR_COLD;
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;
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/tanram.h b/src/devices/bus/tanbus/tanram.h
index 9cdf7970c77..96e8ff2b320 100644
--- a/src/devices/bus/tanbus/tanram.h
+++ b/src/devices/bus/tanbus/tanram.h
@@ -28,7 +28,7 @@ public:
protected:
// device-level overrides
- virtual void device_start() override;
+ virtual void device_start() override ATTR_COLD;
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;
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..b6c75ede992
--- /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 ATTR_COLD;
+
+ // optional information overrides
+ virtual void device_add_mconfig(machine_config &config) override ATTR_COLD;
+
+ 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/tug64k.h b/src/devices/bus/tanbus/tug64k.h
index e6163d7a187..1014cf19906 100644
--- a/src/devices/bus/tanbus/tug64k.h
+++ b/src/devices/bus/tanbus/tug64k.h
@@ -28,10 +28,10 @@ public:
protected:
// device-level overrides
- virtual void device_start() override;
+ virtual void device_start() override ATTR_COLD;
// optional information overrides
- virtual ioport_constructor device_input_ports() const override;
+ virtual ioport_constructor device_input_ports() const override ATTR_COLD;
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;
diff --git a/src/devices/bus/tanbus/tug8082.cpp b/src/devices/bus/tanbus/tug8082.cpp
index 1e4ad1a4504..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)
{
@@ -241,18 +241,14 @@ WRITE_LINE_MEMBER(tanbus_tug8082_device::vdu_irq_w)
uint32_t tanbus_tug8082_device::screen_update(screen_device &screen, bitmap_rgb32 &bitmap, const rectangle &cliprect)
{
- uint32_t *scanline;
- int x, y;
- uint8_t pixels;
+ pen_t const *const pen = m_palette->pens();
- const pen_t *pen = m_palette->pens();
-
- for (y = 0; y < 256; y++)
+ for (int y = 0; y < 256; y++)
{
- scanline = &bitmap.pix32(y);
- for (x = 0; x < 64; x++)
+ uint32_t *scanline = &bitmap.pix(y);
+ for (int x = 0; x < 64; x++)
{
- pixels = m_videoram[(y * 64) + x];
+ uint8_t const pixels = m_videoram[(y * 64) + x];
for (int i = 0; i < 8; ++i)
*scanline++ = pen[BIT(pixels, 7 - i)];
diff --git a/src/devices/bus/tanbus/tug8082.h b/src/devices/bus/tanbus/tug8082.h
index 979e47180e5..9712cbb1179 100644
--- a/src/devices/bus/tanbus/tug8082.h
+++ b/src/devices/bus/tanbus/tug8082.h
@@ -35,19 +35,19 @@ public:
protected:
// device-level overrides
- virtual void device_start() override;
+ virtual void device_start() override ATTR_COLD;
// 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 void device_add_mconfig(machine_config &config) override ATTR_COLD;
+ virtual const tiny_rom_entry *device_rom_region() const override ATTR_COLD;
+ virtual ioport_constructor device_input_ports() const override ATTR_COLD;
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:
- 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);
@@ -59,7 +59,7 @@ private:
required_device<palette_device> m_palette;
required_shared_ptr<uint8_t> m_videoram;
- void vid8082_map(address_map &map);
+ void vid8082_map(address_map &map) ATTR_COLD;
};
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..9f0189ef530
--- /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 ATTR_COLD;
+
+ // optional information overrides
+ virtual void device_add_mconfig(machine_config &config) override ATTR_COLD;
+ virtual ioport_constructor device_input_ports() const override ATTR_COLD;
+
+ // 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 ATTR_COLD;
+
+private:
+ required_device_array<generic_slot_device, 16> m_rom;
+
+ void mem_map(address_map &map) ATTR_COLD;
+};
+
+
+// ======================> 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 ATTR_COLD;
+
+private:
+ required_device_array<generic_slot_device, 16> m_rom;
+
+ void mem_map(address_map &map) ATTR_COLD;
+};
+
+
+// ======================> 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 ATTR_COLD;
+
+private:
+ void mem_map(address_map &map) ATTR_COLD;
+};
+
+
+// ======================> 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/tanbus/tugpgm.h b/src/devices/bus/tanbus/tugpgm.h
index 215f66a397c..c14dadc6421 100644
--- a/src/devices/bus/tanbus/tugpgm.h
+++ b/src/devices/bus/tanbus/tugpgm.h
@@ -30,10 +30,10 @@ public:
protected:
// device-level overrides
- virtual void device_start() override;
+ virtual void device_start() override ATTR_COLD;
// optional information overrides
- virtual ioport_constructor device_input_ports() const override;
+ virtual ioport_constructor device_input_ports() const override ATTR_COLD;
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;
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..3731edfb22f
--- /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 ATTR_COLD;
+ virtual void io_map(address_map &map) override ATTR_COLD;
+
+protected:
+ virtual void device_add_mconfig(machine_config &config) override ATTR_COLD;
+ virtual void device_start() override ATTR_COLD;
+
+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
new file mode 100644
index 00000000000..f51b47f4dd2
--- /dev/null
+++ b/src/devices/bus/thomson/cd90_015.cpp
@@ -0,0 +1,151 @@
+// license:BSD-3-Clause
+// copyright-holders:Olivier Galibert
+
+// CD 90-015 - Floppy disk interface built from a MC6843 single-density controller
+//
+// 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/sap_dsk.h"
+#include "formats/thom_dsk.h"
+
+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),
+ thomson_extension_interface(mconfig, *this),
+ m_fdc(*this, "fdc"),
+ m_floppy(*this, "%u", 0U),
+ m_rom(*this, "rom")
+{
+}
+
+ROM_START(cd90_015)
+ ROM_REGION( 0x7c0, "rom", 0 )
+ ROM_LOAD ( "cd90-015.rom", 0x000, 0x7c0, CRC(821d34c1) SHA1(31a6bb81baaeec5fc8de457c97264f9dfa92c18b) )
+ROM_END
+
+void cd90_015_device::rom_map(address_map &map)
+{
+ map(0x000, 0x7bf).rom().region(m_rom, 0);
+}
+
+void cd90_015_device::io_map(address_map &map)
+{
+ 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
+{
+ 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("ud90_070", UD90_070);
+}
+
+void cd90_015_device::floppy_formats(format_registration &fr)
+{
+ fr.add(FLOPPY_THOMSON_525_FORMAT);
+ fr.add(FLOPPY_SAP_FORMAT);
+}
+
+void cd90_015_device::device_add_mconfig(machine_config &config)
+{
+ 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, "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);
+}
+
+TIMER_CALLBACK_MEMBER(cd90_015_device::motor_tick)
+{
+ m_floppy[param]->get_device()->mon_w(1);
+}
+
+void cd90_015_device::device_start()
+{
+ for(int i=0; i != 4; i++)
+ m_motor_timer[i] = timer_alloc(FUNC(cd90_015_device::motor_tick), this);
+ save_item(NAME(m_select));
+}
+
+void cd90_015_device::device_reset()
+{
+ m_select = 0;
+ for(int i=0; i != 4; i++) {
+ floppy_image_device *f = m_floppy[i]->get_device();
+ if(f)
+ f->mon_w(1);
+ }
+ m_fdc->set_floppy(nullptr);
+}
+
+void cd90_015_device::select_w(u8 data)
+{
+ u8 started = (~m_select) & data;
+ m_select = data & 0xf;
+
+ for(int i = 0; i != 5; i++)
+ if(m_select & (1 << i)) {
+ m_fdc->set_floppy(m_floppy[i]->get_device());
+ goto found;
+ }
+ m_fdc->set_floppy(nullptr);
+
+ found:
+ for(int i = 0; i != 4; i++)
+ if(started & (1 << i)) {
+ if(m_floppy[i]->get_device()) {
+ m_floppy[i]->get_device()->mon_w(0);
+ m_motor_timer[i]->adjust(attotime::from_seconds(5), i);
+ }
+ }
+
+ logerror("select_w %x\n", m_select);
+}
+
+u8 cd90_015_device::motor_r()
+{
+ u8 res = 0xf;
+ for(int i=0; i != 4; i++)
+ if(m_floppy[i]->get_device() && !m_floppy[i]->get_device()->mon_r())
+ res &= ~(1 << i);
+ if(!machine().side_effects_disabled())
+ logerror("motor_r %x\n", res);
+ return res;
+}
diff --git a/src/devices/bus/thomson/cd90_015.h b/src/devices/bus/thomson/cd90_015.h
new file mode 100644
index 00000000000..82fc4cba29e
--- /dev/null
+++ b/src/devices/bus/thomson/cd90_015.h
@@ -0,0 +1,49 @@
+// license:BSD-3-Clause
+// copyright-holders:Olivier Galibert
+
+// CD 90-015 - Floppy drive controller built from a hd 46503s aka hd6843 aka mc6843
+//
+// Handles up to four 5.25 single-sided drives (DD 90-015)
+
+#ifndef MAME_BUS_THOMSON_CD90_015_H
+#define MAME_BUS_THOMSON_CD90_015_H
+
+#include "extension.h"
+#include "imagedev/floppy.h"
+#include "machine/mc6843.h"
+
+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);
+ virtual ~cd90_015_device() = default;
+
+ virtual void rom_map(address_map &map) override ATTR_COLD;
+ virtual void io_map(address_map &map) override ATTR_COLD;
+
+protected:
+ virtual const tiny_rom_entry *device_rom_region() const override ATTR_COLD;
+ 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;
+
+ TIMER_CALLBACK_MEMBER(motor_tick);
+
+private:
+ required_device<mc6843_device> m_fdc;
+ required_device_array<floppy_connector, 4> m_floppy;
+ required_memory_region m_rom;
+
+ emu_timer *m_motor_timer[4];
+ u8 m_select;
+
+ void select_w(u8 data);
+ u8 motor_r();
+
+ static void floppy_formats(format_registration &fr);
+ static void floppy_drives(device_slot_interface &device);
+};
+
+DECLARE_DEVICE_TYPE(CD90_015, cd90_015_device)
+
+#endif
diff --git a/src/devices/bus/thomson/cd90_351.cpp b/src/devices/bus/thomson/cd90_351.cpp
new file mode 100644
index 00000000000..1247a2c3185
--- /dev/null
+++ b/src/devices/bus/thomson/cd90_351.cpp
@@ -0,0 +1,88 @@
+// license:BSD-3-Clause
+// copyright-holders:Olivier Galibert
+
+
+// CD 90-351 - Custom floppy drive controller (THMFC1)
+//
+// Handles up to two 3.5 dual-sided drives (DD 90-352)
+// or up to two 2.8 dual-sided QDD drivers (QD 90-280)
+
+
+#include "emu.h"
+#include "cd90_351.h"
+#include "formats/sap_dsk.h"
+#include "formats/thom_dsk.h"
+#include "machine/thmfc1.h"
+
+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, clock),
+ thomson_extension_interface(mconfig, *this),
+ m_rom(*this, "rom"),
+ m_rom_bank(*this, "rom_bank")
+{
+}
+
+ROM_START(cd90_351)
+ // Rom has been dumped from the system, so the unaccessible ranges are
+ // missing (and probably totally unimportant)
+
+ ROM_REGION( 0x2000, "rom", 0 )
+ ROM_LOAD ( "cd-351-0.rom", 0x0000, 0x7c0, CRC(2c0159fd) SHA1(bab5395ed8bc7c06f9897897f836054e6546e8e8) )
+ ROM_LOAD ( "cd-351-1.rom", 0x0800, 0x7c0, CRC(8e58d159) SHA1(dcf992c96e7556b2faee6bacd3f744e56998e6ea) )
+ ROM_LOAD ( "cd-351-2.rom", 0x1000, 0x7c0, CRC(c9228b60) SHA1(179e10107d5be91e684069dee80f94847b83201f) )
+ ROM_LOAD ( "cd-351-3.rom", 0x1800, 0x7c0, CRC(3ca8e5dc) SHA1(7118636fb5c597c78c2fce17b02aed5e4ba38635) )
+ROM_END
+
+void cd90_351_device::rom_map(address_map &map)
+{
+ map(0x000, 0x7bf).bankr(m_rom_bank);
+}
+
+void cd90_351_device::io_map(address_map &map)
+{
+ map(0x10, 0x17).m("thmfc1", FUNC(thmfc1_device::map));
+ map(0x18, 0x18).w(FUNC(cd90_351_device::bank_w));
+}
+
+const tiny_rom_entry *cd90_351_device::device_rom_region() const
+{
+ return ROM_NAME(cd90_351);
+}
+
+void cd90_351_device::floppy_drives(device_slot_interface &device)
+{
+ device.option_add("dd90_352", FLOPPY_35_DD);
+ // device.option_add("qd90_280", FLOPPY_28_QDD);
+}
+
+void cd90_351_device::floppy_formats(format_registration &fr)
+{
+ fr.add_pc_formats();
+ fr.add(FLOPPY_THOMSON_35_FORMAT);
+ fr.add(FLOPPY_SAP_FORMAT);
+}
+
+void cd90_351_device::device_add_mconfig(machine_config &config)
+{
+ THMFC1(config, "thmfc1", 16000000);
+ FLOPPY_CONNECTOR(config, "thmfc1:0", floppy_drives, "dd90_352", floppy_formats).enable_sound(true);
+ FLOPPY_CONNECTOR(config, "thmfc1:1", floppy_drives, nullptr, floppy_formats).enable_sound(true);
+}
+
+void cd90_351_device::device_start()
+{
+ m_rom_bank->configure_entries(0, 4, m_rom->base(), 0x800);
+}
+
+void cd90_351_device::device_reset()
+{
+ m_rom_bank->set_entry(0);
+}
+
+void cd90_351_device::bank_w(u8 data)
+{
+ logerror("bank_w %d\n", data & 3);
+ m_rom_bank->set_entry(data & 3);
+}
diff --git a/src/devices/bus/thomson/cd90_351.h b/src/devices/bus/thomson/cd90_351.h
new file mode 100644
index 00000000000..de5e40e1ac2
--- /dev/null
+++ b/src/devices/bus/thomson/cd90_351.h
@@ -0,0 +1,42 @@
+// license:BSD-3-Clause
+// copyright-holders:Olivier Galibert
+
+// CD 90-351 - Custom floppy drive controller (THMFC1)
+//
+// Handles up to two 3.5 dual-sided drives (DD 90-352)
+// or up to two 2.8 dual-sided QDD drivers (QD 90-280)
+
+#ifndef MAME_BUS_THOMSON_CD90_351_H
+#define MAME_BUS_THOMSON_CD90_351_H
+
+#include "extension.h"
+#include "imagedev/floppy.h"
+
+class cd90_351_device : public device_t, public thomson_extension_interface
+{
+public:
+ cd90_351_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
+ virtual ~cd90_351_device() = default;
+
+ virtual void rom_map(address_map &map) override ATTR_COLD;
+ virtual void io_map(address_map &map) override ATTR_COLD;
+
+protected:
+ virtual const tiny_rom_entry *device_rom_region() const override ATTR_COLD;
+ 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:
+ required_memory_region m_rom;
+ memory_bank_creator m_rom_bank;
+
+ static void floppy_formats(format_registration &fr);
+ static void floppy_drives(device_slot_interface &device);
+
+ void bank_w(u8 data);
+};
+
+DECLARE_DEVICE_TYPE(CD90_351, cd90_351_device)
+
+#endif
diff --git a/src/devices/bus/thomson/cd90_640.cpp b/src/devices/bus/thomson/cd90_640.cpp
new file mode 100644
index 00000000000..ba8a9a95969
--- /dev/null
+++ b/src/devices/bus/thomson/cd90_640.cpp
@@ -0,0 +1,93 @@
+// license:BSD-3-Clause
+// copyright-holders:Olivier Galibert
+
+// CD 90-640 - Floppy drive controller built from a wd1770
+//
+// Handles up to two 5.25 dual-sided drives (DD 90-320)
+
+#include "emu.h"
+#include "cd90_640.h"
+#include "formats/sap_dsk.h"
+#include "formats/thom_dsk.h"
+
+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),
+ thomson_extension_interface(mconfig, *this),
+ m_fdc(*this, "fdc"),
+ m_floppy(*this, "%u", 0U),
+ m_rom(*this, "rom")
+{
+}
+
+ROM_START(cd90_640)
+ ROM_REGION( 0x7c0, "rom", 0 )
+ ROM_LOAD ( "cd90-640.rom", 0x000, 0x7c0, CRC(5114c0a5) SHA1(5c72566c22d8160ef0c75959e1863a1309bbbe49) )
+ROM_END
+
+void cd90_640_device::rom_map(address_map &map)
+{
+ map(0x000, 0x7bf).rom().region(m_rom, 0);
+}
+
+void cd90_640_device::io_map(address_map &map)
+{
+ 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
+{
+ return ROM_NAME(cd90_640);
+}
+
+void cd90_640_device::floppy_drives(device_slot_interface &device)
+{
+ device.option_add("dd90_320", FLOPPY_525_DD);
+}
+
+void cd90_640_device::floppy_formats(format_registration &fr)
+{
+ fr.add(FLOPPY_THOMSON_525_FORMAT);
+ fr.add(FLOPPY_SAP_FORMAT);
+}
+
+void cd90_640_device::device_add_mconfig(machine_config &config)
+{
+ WD1770(config, m_fdc, 8_MHz_XTAL);
+ FLOPPY_CONNECTOR(config, m_floppy[0], floppy_drives, "dd90_320", floppy_formats).enable_sound(true);
+ FLOPPY_CONNECTOR(config, m_floppy[1], floppy_drives, nullptr, floppy_formats).enable_sound(true);
+}
+
+void cd90_640_device::device_start()
+{
+ save_item(NAME(m_control));
+}
+
+void cd90_640_device::device_reset()
+{
+ m_control = 0;
+ m_fdc->set_floppy(nullptr);
+ m_fdc->dden_w(0);
+}
+
+void cd90_640_device::control_w(u8 data)
+{
+ m_control = data;
+ floppy_image_device *floppy = nullptr;
+ if(m_control & 2)
+ floppy = m_floppy[0]->get_device();
+ else if(m_control & 4)
+ floppy = m_floppy[1]->get_device();
+ if(floppy)
+ floppy->ss_w(m_control & 1);
+ m_fdc->set_floppy(floppy);
+ m_fdc->dden_w(m_control & 0x80 ? 1 : 0);
+ logerror("control %02x\n", m_control);
+}
+
+u8 cd90_640_device::control_r()
+{
+ return m_control;
+}
diff --git a/src/devices/bus/thomson/cd90_640.h b/src/devices/bus/thomson/cd90_640.h
new file mode 100644
index 00000000000..b1a7d35fbab
--- /dev/null
+++ b/src/devices/bus/thomson/cd90_640.h
@@ -0,0 +1,46 @@
+// license:BSD-3-Clause
+// copyright-holders:Olivier Galibert
+
+// CD 90-640 - Floppy drive controller built from a wd1770
+//
+// Handles up to two 5.25 dual-sided drives (DD 90-320)
+
+#ifndef MAME_BUS_THOMSON_CD90_640_H
+#define MAME_BUS_THOMSON_CD90_640_H
+
+#include "extension.h"
+#include "imagedev/floppy.h"
+#include "machine/wd_fdc.h"
+
+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);
+ virtual ~cd90_640_device() = default;
+
+ virtual void rom_map(address_map &map) override ATTR_COLD;
+ virtual void io_map(address_map &map) override ATTR_COLD;
+
+protected:
+ virtual const tiny_rom_entry *device_rom_region() const override ATTR_COLD;
+ 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:
+ required_device<wd1770_device> m_fdc;
+ required_device_array<floppy_connector, 2> m_floppy;
+ required_memory_region m_rom;
+
+ u8 m_control;
+
+ void control_w(u8 data);
+ u8 control_r();
+
+ static void floppy_formats(format_registration &fr);
+ static void floppy_drives(device_slot_interface &device);
+};
+
+DECLARE_DEVICE_TYPE(CD90_640, cd90_640_device)
+
+#endif
diff --git a/src/devices/bus/thomson/cq90_028.cpp b/src/devices/bus/thomson/cq90_028.cpp
new file mode 100644
index 00000000000..8d0ce518b19
--- /dev/null
+++ b/src/devices/bus/thomson/cq90_028.cpp
@@ -0,0 +1,76 @@
+// license:BSD-3-Clause
+// copyright-holders:Olivier Galibert
+
+// CQ 90-028 - QDD drive controller built from a motorola 6852 (serial chip)
+//
+// Handles n? QDD drives (QD 90-128)
+
+// Nonfunctional, essentially because we have no container for the QDD
+// (it's not a floppy, the closest equivalent would be a digital tape)
+
+#include "emu.h"
+#include "cq90_028.h"
+
+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),
+ thomson_extension_interface(mconfig, *this),
+ m_serial(*this, "serial"),
+ m_rom(*this, "rom")
+{
+}
+
+ROM_START(cq90_028)
+ ROM_REGION( 0x7c0, "rom", 0 )
+ ROM_LOAD ( "cq90-028.rom", 0x000, 0x7c0, CRC(ca4dba3d) SHA1(949c1f777c892da62c242215d79757d61e71e62b) )
+ROM_END
+
+void cq90_028_device::rom_map(address_map &map)
+{
+ map(0x000, 0x7bf).rom().region(m_rom, 0);
+}
+
+void cq90_028_device::io_map(address_map &map)
+{
+ 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
+{
+ return ROM_NAME(cq90_028);
+}
+
+void cq90_028_device::device_add_mconfig(machine_config &config)
+{
+ 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
+}
+
+void cq90_028_device::device_start()
+{
+}
+
+void cq90_028_device::device_reset()
+{
+}
+
+void cq90_028_device::drive_w(u8 data)
+{
+ logerror("drive_w %02x\n", data);
+}
+
+void cq90_028_device::motor_w(u8 data)
+{
+ logerror("motor_w %02x\n", data);
+}
+
+u8 cq90_028_device::status_r()
+{
+ // 40 = disk absent
+ // 80 = index pulse
+ return 0x40;
+}
diff --git a/src/devices/bus/thomson/cq90_028.h b/src/devices/bus/thomson/cq90_028.h
new file mode 100644
index 00000000000..8b15366487e
--- /dev/null
+++ b/src/devices/bus/thomson/cq90_028.h
@@ -0,0 +1,42 @@
+// license:BSD-3-Clause
+// copyright-holders:Olivier Galibert
+
+// CQ 90-028 - QDD drive controller built from a motorola 6852 (serial chip)
+//
+// Handles n? QDD drives (QD 90-128)
+
+#ifndef MAME_BUS_THOMSON_CQ90_028_H
+#define MAME_BUS_THOMSON_CQ90_028_H
+
+#include "extension.h"
+#include "machine/mc6852.h"
+
+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);
+ virtual ~cq90_028_device() = default;
+
+ static constexpr feature_type unemulated_features() { return feature::DISK; }
+
+ virtual void rom_map(address_map &map) override ATTR_COLD;
+ virtual void io_map(address_map &map) override ATTR_COLD;
+
+protected:
+ virtual const tiny_rom_entry *device_rom_region() const override ATTR_COLD;
+ 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:
+ required_device<mc6852_device> m_serial;
+ required_memory_region m_rom;
+
+ void drive_w(u8 data);
+ void motor_w(u8 data);
+ u8 status_r();
+};
+
+DECLARE_DEVICE_TYPE(CQ90_028, cq90_028_device)
+
+#endif
diff --git a/src/devices/bus/thomson/extension.cpp b/src/devices/bus/thomson/extension.cpp
new file mode 100644
index 00000000000..4fb2cfbb7ce
--- /dev/null
+++ b/src/devices/bus/thomson/extension.cpp
@@ -0,0 +1,54 @@
+// license:BSD-3-Clause
+// copyright-holders:Olivier Galibert
+
+// Generic Thomson TO*/MO* extension slot
+
+
+#include "emu.h"
+#include "extension.h"
+
+DEFINE_DEVICE_TYPE(THOMSON_EXTENSION, thomson_extension_device, "thomson_extension", "Thomson TO*/MO* extension port")
+
+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),
+ m_firq_callback(*this),
+ m_irq_callback(*this)
+{
+}
+
+void thomson_extension_device::rom_map(address_space_installer &space, offs_t start, offs_t end)
+{
+ auto dev = get_card_device();
+ if(dev)
+ space.install_device(start, end, *dev, &thomson_extension_interface::rom_map);
+}
+
+void thomson_extension_device::io_map(address_space_installer &space, offs_t start, offs_t end)
+{
+ auto dev = get_card_device();
+ if(dev)
+ space.install_device(start, end, *dev, &thomson_extension_interface::io_map);
+}
+
+void thomson_extension_device::device_start()
+{
+}
+
+thomson_extension_interface::thomson_extension_interface(const machine_config &mconfig, device_t &device) :
+ 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
new file mode 100644
index 00000000000..50aaa4c0204
--- /dev/null
+++ b/src/devices/bus/thomson/extension.h
@@ -0,0 +1,55 @@
+// license:BSD-3-Clause
+// copyright-holders:Olivier Galibert
+
+// Generic Thomson TO*/MO* extension slot
+
+#ifndef MAME_BUS_THOMSON_EXTENSION_H
+#define MAME_BUS_THOMSON_EXTENSION_H
+
+class thomson_extension_device;
+
+class thomson_extension_interface : public device_interface
+{
+public:
+ thomson_extension_interface(const machine_config &mconfig, device_t &device);
+ virtual ~thomson_extension_interface() = default;
+
+ // 0x7c0 window at e000 on TO* and a000 on MO*
+ virtual void rom_map(address_map &map) = 0;
+
+ // 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);
+ 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 ATTR_COLD;
+
+ devcb_write_line m_firq_callback;
+ devcb_write_line m_irq_callback;
+};
+
+DECLARE_DEVICE_TYPE(THOMSON_EXTENSION, thomson_extension_device)
+
+#endif
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..efe068ec2bd
--- /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 ATTR_COLD;
+ virtual void io_map(address_map &map) 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:
+ 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..d477ee22610
--- /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 ATTR_COLD;
+ virtual void io_map(address_map &map) override ATTR_COLD;
+
+protected:
+ virtual void device_add_mconfig(machine_config &config) override ATTR_COLD;
+ virtual void device_start() override ATTR_COLD;
+};
+
+// 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
new file mode 100644
index 00000000000..4275fe4fb59
--- /dev/null
+++ b/src/devices/bus/thomson/nanoreseau.cpp
@@ -0,0 +1,204 @@
+// license:BSD-3-Clause
+// copyright-holders:Antoine Mine, Olivier Galibert
+
+// The "Nanoreseau" was a proprietary networking for MO/TO Thomson
+// computers using rs-485. A PC is supposed to be used as a network
+// head.
+
+#include "emu.h"
+#include "nanoreseau.h"
+
+DEFINE_DEVICE_TYPE(NANORESEAU_TO, nanoreseau_to_device, "nanoreseau_to", "Nanoreseau controller (TO rom)")
+DEFINE_DEVICE_TYPE(NANORESEAU_MO, nanoreseau_mo_device, "nanoreseau_mo", "Nanoreseau controller (MO rom)")
+
+ nanoreseau_device::nanoreseau_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock, bool no_id) :
+ device_t(mconfig, type, tag, owner, clock),
+ thomson_extension_interface(mconfig, *this),
+ m_mc6854(*this, "mc6854"),
+ m_rom(*this, "rom"),
+ m_id(*this, "id"),
+ m_no_id(no_id)
+{
+}
+
+nanoreseau_to_device::nanoreseau_to_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock, bool no_id) :
+ nanoreseau_device(mconfig, NANORESEAU_TO, tag, owner, clock)
+{
+}
+
+nanoreseau_mo_device::nanoreseau_mo_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock, bool no_id) :
+ nanoreseau_device(mconfig, NANORESEAU_MO, tag, owner, clock)
+{
+}
+
+ROM_START(nanoreseau_to)
+ ROM_REGION( 0x7c0, "rom", 0 )
+ ROM_LOAD ( "nano7.rom", 0x000, 0x7c0, CRC(42a1d1a6) SHA1(973209f4baa5e81bf7885c0602949e064bac7862) )
+ROM_END
+
+ROM_START(nanoreseau_mo)
+ ROM_REGION( 0x7c0, "rom", 0 )
+ ROM_LOAD ( "nano5.rom", 0x000, 0x7c0, CRC(2f756868) SHA1(b5b7cb6d12493d849330b6b5628efd1a83a4bbf5) )
+ROM_END
+
+static INPUT_PORTS_START(nanoreseau_config)
+ PORT_START("id")
+ PORT_CONFNAME(0x1f, 0x01, "Network ID")
+ PORT_CONFSETTING(0x00, "0 (Master)")
+ PORT_CONFSETTING(0x01, "1")
+ PORT_CONFSETTING(0x02, "2")
+ PORT_CONFSETTING(0x03, "3")
+ PORT_CONFSETTING(0x04, "4")
+ PORT_CONFSETTING(0x05, "5")
+ PORT_CONFSETTING(0x06, "6")
+ PORT_CONFSETTING(0x07, "7")
+ PORT_CONFSETTING(0x08, "8")
+ PORT_CONFSETTING(0x09, "9")
+ PORT_CONFSETTING(0x0a, "10")
+ PORT_CONFSETTING(0x0b, "11")
+ PORT_CONFSETTING(0x0c, "12")
+ PORT_CONFSETTING(0x0d, "13")
+ PORT_CONFSETTING(0x0e, "14")
+ PORT_CONFSETTING(0x0f, "15")
+ PORT_CONFSETTING(0x10, "16")
+ PORT_CONFSETTING(0x11, "17")
+ PORT_CONFSETTING(0x12, "18")
+ PORT_CONFSETTING(0x13, "19")
+ PORT_CONFSETTING(0x14, "20")
+ PORT_CONFSETTING(0x15, "21")
+ PORT_CONFSETTING(0x16, "22")
+ PORT_CONFSETTING(0x17, "23")
+ PORT_CONFSETTING(0x18, "24")
+ PORT_CONFSETTING(0x19, "25")
+ PORT_CONFSETTING(0x1a, "26")
+ PORT_CONFSETTING(0x1b, "27")
+ PORT_CONFSETTING(0x1c, "28")
+ PORT_CONFSETTING(0x1d, "29")
+ PORT_CONFSETTING(0x1e, "30")
+ PORT_CONFSETTING(0x1f, "31")
+INPUT_PORTS_END
+
+void nanoreseau_device::rom_map(address_map &map)
+{
+ map(0x000, 0x7bf).rom().region(m_rom, 0);
+}
+
+void nanoreseau_device::io_map(address_map &map)
+{
+ map(0x10, 0x13).rw(m_mc6854, FUNC(mc6854_device::read), FUNC(mc6854_device::write));
+ if (!m_no_id)
+ map(0x18, 0x18).r(FUNC(nanoreseau_device::id_r));
+}
+
+const tiny_rom_entry *nanoreseau_to_device::device_rom_region() const
+{
+ return ROM_NAME(nanoreseau_to);
+}
+
+const tiny_rom_entry *nanoreseau_mo_device::device_rom_region() const
+{
+ return ROM_NAME(nanoreseau_mo);
+}
+
+void nanoreseau_device::device_add_mconfig(machine_config &config)
+{
+ MC6854(config, m_mc6854);
+ m_mc6854->set_out_frame_callback(FUNC(nanoreseau_device::got_frame));
+}
+
+void nanoreseau_device::device_start()
+{
+ m_timer = timer_alloc(FUNC(nanoreseau_device::answer_tick), this);
+ save_item(NAME(m_answer_step));
+}
+
+void nanoreseau_device::device_reset()
+{
+ m_answer_step = 4;
+ m_mc6854->set_cts(0);
+ m_mc6854->set_cts(1);
+}
+
+ioport_constructor nanoreseau_device::device_input_ports() const
+{
+ return m_no_id ? nullptr : INPUT_PORTS_NAME(nanoreseau_config);
+}
+
+/*********************** Network ************************/
+
+/* The network extension is built as an external floppy controller.
+ It uses the same ROM and I/O space, so it is natural to have the
+ top-level network emulation here.
+
+ NOTE: This is work in progress.
+ For the moment, only hand-checks work: the TO7 can take the line, then
+ perform a DKBOOT request. We do not have the server emulated yet, so
+ there is no way to answer the request.
+*/
+
+/* consigne DKBOOT
+
+ MO5 BASIC
+ $00 $00 $01 $00 $00 $00 $00 $00 $00 $00 $01 $00<$41 $00 $FF $20
+ $3D $4C $01 $60 $20 $3C $4F $01 $05 $20 $3F $9C $19 $25 $03 $11
+ $93 $15 $10 $25 $32 $8A $7E $FF $E1 $FD $E9 $41>$00 $00 $00 $00
+ $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00
+
+ TO7/70 BASIC
+ $00 $00 $01 $00 $00 $00 $00 $00 $00 $00 $02 $00<$20 $42 $41 $53
+ $49 $43 $20 $4D $49 $43 $52 $4F $53 $4F $46 $54 $20 $31 $2E $30
+ $04 $00 $00 $00 $00 $00 $60 $FF $37 $9B $37 $9C>$00 $00 $00 $00
+ $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00
+
+ TO7 BASIC
+ $00 $00 $01 $00 $00 $00 $00 $00 $00 $00 $00 $00<$20 $42 $41 $53
+ $49 $43 $20 $4D $49 $43 $52 $4F $53 $4F $46 $54 $20 $31 $2E $30
+ $04 $00 $00 $00 $00 $00 $60 $FF $37 $9B $37 $9C>$00 $00 $00 $00
+ $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00
+
+ TO7 LOGO
+ $00 $00 $01 $00 $00 $00 $00 $00 $00 $00 $00 $00<$00 $00 $00 $00
+ $00 $20 $4C $4F $47 $4F $04 $00 $00 $00 $00 $00 $00 $00 $00 $00
+ $00 $00 $00 $00 $00 $00 $AA $FF $01 $16 $00 $C8>$00 $00 $00 $00
+ $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00 $00
+
+
+*/
+
+TIMER_CALLBACK_MEMBER(nanoreseau_device::answer_tick)
+{
+ m_answer_step++;
+ m_mc6854->set_cts(m_answer_step & 1);
+ if (m_answer_step < 4)
+ m_timer->adjust(attotime::from_usec(100));
+}
+
+void nanoreseau_device::got_frame(uint8_t *data, int length)
+{
+ std::string frame = util::string_format("%s: frame", machine().time().to_string());
+ for(int i = 0; i < length; i++)
+ frame += util::string_format(" %02x", data[i]);
+ logerror("%s\n", frame);
+
+ if (data[1] == 0xff) {
+ logerror("frame: %d phones %d\n", data[2], data[0]);
+ m_answer_step = 0;
+ m_timer->adjust(attotime::from_usec(100));
+ m_mc6854->set_cts(0);
+
+ } else if (!data[1]) {
+ char name[33];
+ memcpy(name, data + 12, 32);
+ name[32] = 0;
+ for(int i=0; i<32; i++)
+ if (name[i] < 32 || name[i] >= 127)
+ name[i]='.';
+ logerror("DKBOOT system %s appli %s\n", data[10] == 0 ? "TO7" : data[10] == 1 ? "MO5" : data[10] == 2 ? "TO7/70" : "?", name);
+ }
+}
+
+u8 nanoreseau_device::id_r()
+{
+ // network ID of the computer
+ return m_id->read();
+}
diff --git a/src/devices/bus/thomson/nanoreseau.h b/src/devices/bus/thomson/nanoreseau.h
new file mode 100644
index 00000000000..e2c39635d12
--- /dev/null
+++ b/src/devices/bus/thomson/nanoreseau.h
@@ -0,0 +1,67 @@
+// license:BSD-3-Clause
+// copyright-holders:Antoine Mine, Olivier Galibert
+
+// The "Nanoreseau" was a proprietary networking for MO/TO Thomson
+// computers using rs-485. A PC is supposed to be used as a network
+// head.
+
+#ifndef MAME_BUS_THOMSON_NANORESEAU_H
+#define MAME_BUS_THOMSON_NANORESEAU_H
+
+#include "extension.h"
+#include "machine/mc6854.h"
+
+class nanoreseau_device : public device_t, public thomson_extension_interface
+{
+public:
+ nanoreseau_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock, bool no_id = false);
+ virtual ~nanoreseau_device() = default;
+
+ virtual void rom_map(address_map &map) override ATTR_COLD;
+ virtual void io_map(address_map &map) 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;
+ virtual ioport_constructor device_input_ports() const override ATTR_COLD;
+
+ TIMER_CALLBACK_MEMBER(answer_tick);
+
+private:
+ required_device<mc6854_device> m_mc6854;
+ required_memory_region m_rom;
+ required_ioport m_id;
+ bool m_no_id;
+
+ emu_timer *m_timer;
+ int m_answer_step;
+
+ void got_frame(uint8_t *data, int length);
+ u8 id_r();
+};
+
+class nanoreseau_mo_device : public nanoreseau_device
+{
+public:
+ nanoreseau_mo_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock = 0, bool no_id = false);
+ virtual ~nanoreseau_mo_device() = default;
+
+protected:
+ virtual const tiny_rom_entry *device_rom_region() const override ATTR_COLD;
+};
+
+class nanoreseau_to_device : public nanoreseau_device
+{
+public:
+ nanoreseau_to_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock = 0, bool no_id = false);
+ virtual ~nanoreseau_to_device() = default;
+
+protected:
+ virtual const tiny_rom_entry *device_rom_region() const override ATTR_COLD;
+};
+
+DECLARE_DEVICE_TYPE(NANORESEAU_MO, nanoreseau_mo_device)
+DECLARE_DEVICE_TYPE(NANORESEAU_TO, nanoreseau_to_device)
+
+#endif
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..5d552caafd2
--- /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 ATTR_COLD;
+ virtual void io_map(address_map &map) override ATTR_COLD;
+
+protected:
+ virtual void device_add_mconfig(machine_config &config) override ATTR_COLD;
+ virtual void device_start() override ATTR_COLD;
+};
+
+// 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..992a536495d
--- /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 ATTR_COLD;
+ virtual void io_map(address_map &map) override ATTR_COLD;
+
+protected:
+ virtual void device_add_mconfig(machine_config &config) override ATTR_COLD;
+ virtual void device_start() override ATTR_COLD;
+};
+
+// 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 bfe7849aa40..94149c0d642 100644
--- a/src/devices/bus/ti8x/bitsocket.cpp
+++ b/src/devices/bus/ti8x/bitsocket.cpp
@@ -1,14 +1,45 @@
// license:BSD-3-Clause
// copyright-holders:Vas Crabb
+/*
+ Sends raw assert/release signals over a socket. Seriously limits
+ transfer rates and probably won't work if there's much latency, but it
+ allows communication between instances using non-standard protocols.
+
+ bit 0 = data
+ bit 1 = set tip
+ bit 2 = set ring
+ */
#include "emu.h"
#include "bitsocket.h"
+#include "imagedev/bitbngr.h"
+
+
+namespace {
+
+class bit_socket_device
+ : public device_t
+ , public device_ti8x_link_port_interface
+{
+public:
+ bit_socket_device(machine_config const &mconfig, char const *tag, device_t *owner, uint32_t clock);
-DEFINE_DEVICE_TYPE_NS(TI8X_BIT_SOCKET, bus::ti8x, bit_socket_device, "ti8x_bitsock", "TI-8x Bit Socket")
+protected:
+ virtual void device_add_mconfig(machine_config &config) override ATTR_COLD;
+ virtual void device_start() override ATTR_COLD;
+ virtual void input_tip(int state) override;
+ virtual void input_ring(int state) override;
+
+ TIMER_CALLBACK_MEMBER(poll_tick);
+
+private:
+ required_device<bitbanger_device> m_stream;
+ emu_timer * m_poll_timer;
+ bool m_tip_in, m_ring_in;
+};
-namespace bus { namespace ti8x {
bit_socket_device::bit_socket_device(
machine_config const &mconfig,
@@ -33,7 +64,7 @@ void bit_socket_device::device_add_mconfig(machine_config &config)
void bit_socket_device::device_start()
{
- m_poll_timer = timer_alloc(TIMER_ID_POLL);
+ m_poll_timer = timer_alloc(FUNC(bit_socket_device::poll_tick), this);
save_item(NAME(m_tip_in));
save_item(NAME(m_ring_in));
@@ -44,38 +75,31 @@ void bit_socket_device::device_start()
}
-void bit_socket_device::device_timer(emu_timer &timer, device_timer_id id, int param, void *ptr)
+TIMER_CALLBACK_MEMBER(bit_socket_device::poll_tick)
{
- switch (id)
+ u8 data;
+ while (m_stream->input(&data, 1))
{
- case TIMER_ID_POLL:
- {
- u8 data;
- while (m_stream->input(&data, 1))
- {
- if (BIT(data, 1)) output_tip(BIT(data, 0));
- if (BIT(data, 2)) output_ring(BIT(data, 0));
- }
- }
- break;
-
- default:
- break;
+ if (BIT(data, 1)) output_tip(BIT(data, 0));
+ if (BIT(data, 2)) output_ring(BIT(data, 0));
}
}
-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);
}
-} } // namespace bus::ti8x
+} // anonymous namespace
+
+
+DEFINE_DEVICE_TYPE_PRIVATE(TI8X_BIT_SOCKET, device_ti8x_link_port_interface, bit_socket_device, "ti8x_bitsock", "TI-8x Bit Socket")
diff --git a/src/devices/bus/ti8x/bitsocket.h b/src/devices/bus/ti8x/bitsocket.h
index b8729a6c00d..6044e1110cb 100644
--- a/src/devices/bus/ti8x/bitsocket.h
+++ b/src/devices/bus/ti8x/bitsocket.h
@@ -1,14 +1,5 @@
// license:BSD-3-Clause
// copyright-holders:Vas Crabb
-/*
- Sends raw assert/release signals over a socket. Seriously limits
- transfer rates and probably won't work if there's much latency, but it
- allows communication between instances using non-standard protocols.
-
- bit 0 = data
- bit 1 = set tip
- bit 2 = set ring
- */
#ifndef MAME_BUS_TI8X_BITSOCKET_H
#define MAME_BUS_TI8X_BITSOCKET_H
@@ -16,40 +7,7 @@
#include "ti8x.h"
-#include "imagedev/bitbngr.h"
-
-
-namespace bus { namespace ti8x {
-
-class bit_socket_device
- : public device_t
- , public device_ti8x_link_port_interface
-{
-public:
- bit_socket_device(machine_config const &mconfig, char const *tag, device_t *owner, uint32_t clock);
-
-protected:
- enum
- {
- TIMER_ID_POLL = 1
- };
-
- virtual void device_add_mconfig(machine_config &config) override;
- virtual void device_start() override;
- virtual void device_timer(emu_timer &timer, device_timer_id id, int param, void *ptr) override;
-
- virtual DECLARE_WRITE_LINE_MEMBER(input_tip) override;
- virtual DECLARE_WRITE_LINE_MEMBER(input_ring) override;
-
-private:
- required_device<bitbanger_device> m_stream;
- emu_timer * m_poll_timer;
- bool m_tip_in, m_ring_in;
-};
-
-} } // namespace bus::ti8x
-
-DECLARE_DEVICE_TYPE_NS(TI8X_BIT_SOCKET, bus::ti8x, bit_socket_device)
+DECLARE_DEVICE_TYPE(TI8X_BIT_SOCKET, device_ti8x_link_port_interface)
#endif // MAME_BUS_TI8X_BITSOCKET_H
diff --git a/src/devices/bus/ti8x/graphlinkhle.cpp b/src/devices/bus/ti8x/graphlinkhle.cpp
index ecdec035b06..fd01966d7bd 100644
--- a/src/devices/bus/ti8x/graphlinkhle.cpp
+++ b/src/devices/bus/ti8x/graphlinkhle.cpp
@@ -4,11 +4,47 @@
#include "emu.h"
#include "graphlinkhle.h"
+#include "bus/rs232/rs232.h"
-DEFINE_DEVICE_TYPE_NS(TI8X_GRAPH_LINK_HLE, bus::ti8x, graph_link_hle_device, "ti8x_glinkhle", "TI-Graph Link (grey, HLE)")
+#include "diserial.h"
+#include <memory>
+
+
+namespace {
+
+class graph_link_hle_device
+ : public device_t
+ , public device_ti8x_link_port_byte_interface
+ , public device_serial_interface
+{
+public:
+ graph_link_hle_device(machine_config const &mconfig, char const *tag, device_t *owner, uint32_t clock);
+
+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;
+
+ virtual void byte_collision() override;
+ virtual void byte_send_timeout() override;
+ virtual void byte_receive_timeout() override;
+ virtual void byte_sent() override;
+ virtual void byte_received(u8 data) override;
+
+ virtual void rcv_complete() override;
+ virtual void tra_callback() override;
+ virtual void tra_complete() override;
+
+private:
+ static constexpr unsigned BUFLEN = 1U << 16;
+
+ required_device<rs232_port_device> m_serial_port;
+ std::unique_ptr<u8 []> m_buffer;
+ unsigned m_head, m_tail;
+ bool m_empty, m_ready;
+};
-namespace bus { namespace ti8x {
graph_link_hle_device::graph_link_hle_device(
machine_config const &mconfig,
@@ -142,4 +178,7 @@ void graph_link_hle_device::tra_complete()
accept_byte();
}
-} } // namespace bus::ti8x
+} // anonymous namespace
+
+
+DEFINE_DEVICE_TYPE_PRIVATE(TI8X_GRAPH_LINK_HLE, device_ti8x_link_port_interface, graph_link_hle_device, "ti8x_glinkhle", "TI-Graph Link (grey, HLE)")
diff --git a/src/devices/bus/ti8x/graphlinkhle.h b/src/devices/bus/ti8x/graphlinkhle.h
index 310a4daf133..81c331ded57 100644
--- a/src/devices/bus/ti8x/graphlinkhle.h
+++ b/src/devices/bus/ti8x/graphlinkhle.h
@@ -18,50 +18,7 @@
#include "ti8x.h"
-#include "bus/rs232/rs232.h"
-#include "diserial.h"
-
-#include <memory>
-
-
-namespace bus { namespace ti8x {
-
-class graph_link_hle_device
- : public device_t
- , public device_ti8x_link_port_byte_interface
- , public device_serial_interface
-{
-public:
- graph_link_hle_device(machine_config const &mconfig, char const *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;
-
- virtual void byte_collision() override;
- virtual void byte_send_timeout() override;
- virtual void byte_receive_timeout() override;
- virtual void byte_sent() override;
- virtual void byte_received(u8 data) override;
-
- virtual void rcv_complete() override;
- virtual void tra_callback() override;
- virtual void tra_complete() override;
-
-private:
- static constexpr unsigned BUFLEN = 1U << 16;
-
- required_device<rs232_port_device> m_serial_port;
- std::unique_ptr<u8 []> m_buffer;
- unsigned m_head, m_tail;
- bool m_empty, m_ready;
-};
-
-} } // namespace bus::ti8x
-
-
-DECLARE_DEVICE_TYPE_NS(TI8X_GRAPH_LINK_HLE, bus::ti8x, graph_link_hle_device)
+DECLARE_DEVICE_TYPE(TI8X_GRAPH_LINK_HLE, device_ti8x_link_port_interface)
#endif // MAME_BUS_TI8X_GRAPHLINKHLE_H
diff --git a/src/devices/bus/ti8x/teeconn.cpp b/src/devices/bus/ti8x/teeconn.cpp
index 7277d4af93e..e58af49bcbd 100644
--- a/src/devices/bus/ti8x/teeconn.cpp
+++ b/src/devices/bus/ti8x/teeconn.cpp
@@ -1,14 +1,39 @@
// license:BSD-3-Clause
// copyright-holders:Vas Crabb
+/*
+ A T-connector, strangely enough.
+ */
#include "emu.h"
#include "teeconn.h"
-DEFINE_DEVICE_TYPE_NS(TI8X_TEE_CONNECTOR, bus::ti8x, tee_connector_device, "ti8x_tconn", "TI-8x T-connector")
+namespace {
+class tee_connector_device : public device_t, public device_ti8x_link_port_interface
+{
+public:
+ tee_connector_device(machine_config const &mconfig, char const *tag, device_t *owner, uint32_t clock);
+
+protected:
+ virtual void device_add_mconfig(machine_config &config) override ATTR_COLD;
+ virtual void device_start() override ATTR_COLD;
+
+ virtual void input_tip(int state) override;
+ virtual void input_ring(int state) override;
+
+ 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;
+
+ bool m_tip_host, m_tip_a, m_tip_b;
+ bool m_ring_host, m_ring_a, m_ring_b;
+};
-namespace bus { namespace ti8x {
tee_connector_device::tee_connector_device(
machine_config const &mconfig,
@@ -29,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);
@@ -37,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);
@@ -45,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);
@@ -53,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);
@@ -87,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);
@@ -95,11 +120,14 @@ 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);
m_port_b->ring_w((m_ring_host && m_ring_a) ? 1 : 0);
}
-} } // namespace bus::ti8x
+} // anonymous namespace
+
+
+DEFINE_DEVICE_TYPE_PRIVATE(TI8X_TEE_CONNECTOR, device_ti8x_link_port_interface, tee_connector_device, "ti8x_tconn", "TI-8x T-connector")
diff --git a/src/devices/bus/ti8x/teeconn.h b/src/devices/bus/ti8x/teeconn.h
index 65ffa1c6d81..83db867a507 100644
--- a/src/devices/bus/ti8x/teeconn.h
+++ b/src/devices/bus/ti8x/teeconn.h
@@ -1,45 +1,13 @@
// license:BSD-3-Clause
// copyright-holders:Vas Crabb
-/*
- A T-connector, strangely enough.
- */
-#ifndef MAME_DEVICES_BUS_TI8X_TEECONN_H
-#define MAME_DEVICES_BUS_TI8X_TEECONN_H
+#ifndef MAME_BUS_TI8X_TEECONN_H
+#define MAME_BUS_TI8X_TEECONN_H
#pragma once
#include "ti8x.h"
-namespace bus { namespace ti8x {
+DECLARE_DEVICE_TYPE(TI8X_TEE_CONNECTOR, device_ti8x_link_port_interface)
-class tee_connector_device : public device_t, public device_ti8x_link_port_interface
-{
-public:
- tee_connector_device(machine_config const &mconfig, char const *tag, device_t *owner, uint32_t clock);
-
-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;
-
- 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);
-
- required_device<ti8x_link_port_device> m_port_a;
- required_device<ti8x_link_port_device> m_port_b;
-
- bool m_tip_host, m_tip_a, m_tip_b;
- bool m_ring_host, m_ring_a, m_ring_b;
-};
-
-} } // namespace bus::ti8x
-
-
-DECLARE_DEVICE_TYPE_NS(TI8X_TEE_CONNECTOR, bus::ti8x, tee_connector_device)
-
-#endif // MAME_DEVICES_BUS_TI8X_TEECONN_H
+#endif // MAME_BUS_TI8X_TEECONN_H
diff --git a/src/devices/bus/ti8x/ti8x.cpp b/src/devices/bus/ti8x/ti8x.cpp
index 1490c76755b..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
@@ -37,7 +36,7 @@ ti8x_link_port_device::ti8x_link_port_device(
device_t *owner,
uint32_t clock)
: device_t(mconfig, type, tag, owner, clock)
- , device_slot_interface(mconfig, *this)
+ , device_single_card_slot_interface<device_ti8x_link_port_interface>(mconfig, *this)
, m_tip_handler(*this)
, m_ring_handler(*this)
, m_dev(nullptr)
@@ -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));
@@ -88,7 +84,7 @@ void ti8x_link_port_device::device_start()
void ti8x_link_port_device::device_config_complete()
{
- m_dev = dynamic_cast<device_ti8x_link_port_interface *>(get_card_device());
+ m_dev = get_card_device();
}
@@ -96,7 +92,7 @@ void ti8x_link_port_device::device_config_complete()
device_ti8x_link_port_interface::device_ti8x_link_port_interface(
machine_config const &mconfig,
device_t &device)
- : device_slot_card_interface(mconfig, device)
+ : device_interface(device, "ti8xlink")
, m_port(dynamic_cast<ti8x_link_port_device *>(device.owner()))
{
}
@@ -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)
@@ -432,6 +428,7 @@ TIMER_CALLBACK_MEMBER(device_ti8x_link_port_bit_interface::bit_timeout)
// send timeout:
case WAIT_IDLE:
assert(EMPTY != m_tx_bit_buffer);
+ [[fallthrough]];
case WAIT_ACK_0:
case WAIT_ACK_1:
case WAIT_REL_0:
@@ -612,6 +609,12 @@ void device_ti8x_link_port_byte_interface::bit_received(bool data)
#include "teeconn.h"
#include "tispeaker.h"
+
+// must come after including the headers that declare these extern
+template class device_finder<device_ti8x_link_port_interface, false>;
+template class device_finder<device_ti8x_link_port_interface, true>;
+
+
void default_ti8x_link_devices(device_slot_interface &device)
{
device.option_add("bitsock", TI8X_BIT_SOCKET);
diff --git a/src/devices/bus/ti8x/ti8x.h b/src/devices/bus/ti8x/ti8x.h
index e81a4fc5a9e..ca82e9191d0 100644
--- a/src/devices/bus/ti8x/ti8x.h
+++ b/src/devices/bus/ti8x/ti8x.h
@@ -32,8 +32,8 @@
output. This makes implementing things like the tee connector easier.
*/
-#ifndef MAME_DEVICES_BUS_TI8X_TI8X_H
-#define MAME_DEVICES_BUS_TI8X_TI8X_H
+#ifndef MAME_BUS_TI8X_TI8X_H
+#define MAME_BUS_TI8X_TI8X_H
#pragma once
@@ -45,7 +45,7 @@ DECLARE_DEVICE_TYPE(TI8X_LINK_PORT, ti8x_link_port_device)
class device_ti8x_link_port_interface;
-class ti8x_link_port_device : public device_t, public device_slot_interface
+class ti8x_link_port_device : public device_t, public device_single_card_slot_interface<device_ti8x_link_port_interface>
{
public:
template <typename T>
@@ -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(
@@ -77,7 +77,7 @@ protected:
device_t *owner,
u32 clock);
- virtual void device_start() override;
+ virtual void device_start() override ATTR_COLD;
virtual void device_config_complete() override;
devcb_write_line m_tip_handler;
@@ -92,12 +92,12 @@ private:
};
-class device_ti8x_link_port_interface : public device_slot_card_interface
+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;
@@ -200,4 +200,4 @@ private:
void default_ti8x_link_devices(device_slot_interface &device);
-#endif // MAME_DEVICES_BUS_TI8X_TI8X_H
+#endif // MAME_BUS_TI8X_TI8X_H
diff --git a/src/devices/bus/ti8x/tispeaker.cpp b/src/devices/bus/ti8x/tispeaker.cpp
index ed9ec36a5ec..36ab34caae9 100644
--- a/src/devices/bus/ti8x/tispeaker.cpp
+++ b/src/devices/bus/ti8x/tispeaker.cpp
@@ -4,99 +4,114 @@
#include "emu.h"
#include "tispeaker.h"
-#include "speaker.h"
-
+#include "sound/spkrdev.h"
-DEFINE_DEVICE_TYPE_NS(TI8X_SPEAKER_STEREO, bus::ti8x, stereo_speaker_device, "ti8x_stspkr", "TI-8x Speaker (Stereo)")
-DEFINE_DEVICE_TYPE_NS(TI8X_SPEAKER_MONO, bus::ti8x, mono_speaker_device, "ti8x_mspkr", "TI-8x Speaker (Mono)")
+#include "speaker.h"
-namespace bus { namespace ti8x {
+namespace {
-stereo_speaker_device::stereo_speaker_device(
- machine_config const &mconfig,
- char const *tag,
- device_t *owner,
- uint32_t clock)
- : device_t(mconfig, TI8X_SPEAKER_STEREO, tag, owner, clock)
- , device_ti8x_link_port_interface(mconfig, *this)
- , m_left_speaker(*this, "lspkr")
- , m_right_speaker(*this, "rspkr")
+class stereo_speaker_device : public device_t, public device_ti8x_link_port_interface
{
-}
+public:
+ stereo_speaker_device(
+ machine_config const &mconfig,
+ char const *tag,
+ device_t *owner,
+ uint32_t clock)
+ : device_t(mconfig, TI8X_SPEAKER_STEREO, tag, owner, clock)
+ , device_ti8x_link_port_interface(mconfig, *this)
+ , m_left_speaker(*this, "lspkr")
+ , m_right_speaker(*this, "rspkr")
+ {
+ }
+protected:
+ virtual void device_add_mconfig(machine_config &config) override
+ {
+ SPEAKER(config, "outl").front_left();
+ SPEAKER(config, "outr").front_right();
-void stereo_speaker_device::device_add_mconfig(machine_config &config)
-{
- SPEAKER(config, "outl").front_left();
- SPEAKER(config, "outr").front_right();
+ SPEAKER_SOUND(config, m_left_speaker, 0).add_route(ALL_OUTPUTS, "outl", 0.50);
- SPEAKER_SOUND(config, m_left_speaker, 0).add_route(ALL_OUTPUTS, "outl", 0.50);
+ SPEAKER_SOUND(config, m_right_speaker, 0).add_route(ALL_OUTPUTS, "outr", 0.50);
+ }
- SPEAKER_SOUND(config, m_right_speaker, 0).add_route(ALL_OUTPUTS, "outr", 0.50);
-}
+ virtual void device_start() override
+ {
+ }
-void stereo_speaker_device::device_start()
-{
-}
+ virtual void input_tip(int state) override
+ {
+ m_left_speaker->level_w(state);
+ }
+ virtual void input_ring(int state) override
+ {
+ m_right_speaker->level_w(state);
+ }
-WRITE_LINE_MEMBER(stereo_speaker_device::input_tip)
-{
- m_left_speaker->level_w(state);
-}
+ required_device<speaker_sound_device> m_left_speaker;
+ required_device<speaker_sound_device> m_right_speaker;
+};
-WRITE_LINE_MEMBER(stereo_speaker_device::input_ring)
-{
- m_right_speaker->level_w(state);
-}
+class mono_speaker_device : public device_t, public device_ti8x_link_port_interface
+{
+public:
+ mono_speaker_device(
+ machine_config const &mconfig,
+ char const *tag,
+ device_t *owner,
+ uint32_t clock)
+ : device_t(mconfig, TI8X_SPEAKER_MONO, tag, owner, clock)
+ , device_ti8x_link_port_interface(mconfig, *this)
+ , m_speaker(*this, "spkr")
+ , m_tip_state(true)
+ , m_ring_state(true)
+ {
+ }
+protected:
+ virtual void device_add_mconfig(machine_config &config) override
+ {
+ SPEAKER(config, "mono").front_center();
-mono_speaker_device::mono_speaker_device(
- machine_config const &mconfig,
- char const *tag,
- device_t *owner,
- uint32_t clock)
- : device_t(mconfig, TI8X_SPEAKER_MONO, tag, owner, clock)
- , device_ti8x_link_port_interface(mconfig, *this)
- , m_speaker(*this, "spkr")
- , m_tip_state(true)
- , m_ring_state(true)
-{
-}
+ SPEAKER_SOUND(config, m_speaker, 0).add_route(ALL_OUTPUTS, "mono", 0.50);
+ }
+ virtual void device_start() override
+ {
+ save_item(NAME(m_tip_state));
+ save_item(NAME(m_ring_state));
-void mono_speaker_device::device_add_mconfig(machine_config &config)
-{
- SPEAKER(config, "mono").front_center();
+ m_tip_state = m_ring_state = true;
+ }
- SPEAKER_SOUND(config, m_speaker, 0).add_route(ALL_OUTPUTS, "mono", 0.50);
-}
+ virtual void input_tip(int state) override
+ {
+ m_tip_state = bool(state);
+ m_speaker->level_w((m_tip_state || m_ring_state) ? 1 : 0);
+ }
-void mono_speaker_device::device_start()
-{
- save_item(NAME(m_tip_state));
- save_item(NAME(m_ring_state));
+ virtual void input_ring(int state) override
+ {
+ m_ring_state = bool(state);
+ m_speaker->level_w((m_tip_state || m_ring_state) ? 1 : 0);
+ }
- m_tip_state = m_ring_state = true;
-}
+ required_device<speaker_sound_device> m_speaker;
-WRITE_LINE_MEMBER(mono_speaker_device::input_tip)
-{
- m_tip_state = bool(state);
- m_speaker->level_w((m_tip_state || m_ring_state) ? 1 : 0);
-}
+private:
+ bool m_tip_state, m_ring_state;
+};
+} // anonymous namespace
-WRITE_LINE_MEMBER(mono_speaker_device::input_ring)
-{
- m_ring_state = bool(state);
- m_speaker->level_w((m_tip_state || m_ring_state) ? 1 : 0);
-}
-} } // namespace bus::ti8x
+DEFINE_DEVICE_TYPE_PRIVATE(TI8X_SPEAKER_STEREO, device_ti8x_link_port_interface, stereo_speaker_device, "ti8x_stspkr", "TI-8x Speaker (Stereo)")
+DEFINE_DEVICE_TYPE_PRIVATE(TI8X_SPEAKER_MONO, device_ti8x_link_port_interface, mono_speaker_device, "ti8x_mspkr", "TI-8x Speaker (Mono)")
diff --git a/src/devices/bus/ti8x/tispeaker.h b/src/devices/bus/ti8x/tispeaker.h
index 157c94ab060..0173630d48b 100644
--- a/src/devices/bus/ti8x/tispeaker.h
+++ b/src/devices/bus/ti8x/tispeaker.h
@@ -1,55 +1,14 @@
// license:BSD-3-Clause
// copyright-holders:Vas Crabb
-#ifndef MAME_DEVICES_BUS_TI8X_TISPEAKER_H
-#define MAME_DEVICES_BUS_TI8X_TISPEAKER_H
+#ifndef MAME_BUS_TI8X_TISPEAKER_H
+#define MAME_BUS_TI8X_TISPEAKER_H
#pragma once
#include "ti8x.h"
-#include "sound/spkrdev.h"
-namespace bus { namespace ti8x {
+DECLARE_DEVICE_TYPE(TI8X_SPEAKER_STEREO, device_ti8x_link_port_interface)
+DECLARE_DEVICE_TYPE(TI8X_SPEAKER_MONO, device_ti8x_link_port_interface)
-class stereo_speaker_device : public device_t, public device_ti8x_link_port_interface
-{
-public:
- stereo_speaker_device(machine_config const &mconfig, char const *tag, device_t *owner, uint32_t clock);
-
-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;
-
- required_device<speaker_sound_device> m_left_speaker;
- required_device<speaker_sound_device> m_right_speaker;
-};
-
-
-class mono_speaker_device : public device_t, public device_ti8x_link_port_interface
-{
-public:
- mono_speaker_device(machine_config const &mconfig, char const *tag, device_t *owner, uint32_t clock);
-
-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;
-
- required_device<speaker_sound_device> m_speaker;
-
-private:
- bool m_tip_state, m_ring_state;
-};
-
-} } // namespace bus::ti8x
-
-
-DECLARE_DEVICE_TYPE_NS(TI8X_SPEAKER_STEREO, bus::ti8x, stereo_speaker_device)
-DECLARE_DEVICE_TYPE_NS(TI8X_SPEAKER_MONO, bus::ti8x, mono_speaker_device)
-
-#endif // MAME_DEVICES_BUS_TI8X_TISPEAKER_H
+#endif // MAME_BUS_TI8X_TISPEAKER_H
diff --git a/src/devices/bus/ti99/colorbus/busmouse.cpp b/src/devices/bus/ti99/colorbus/busmouse.cpp
index 701be4ee398..a77aeefb661 100644
--- a/src/devices/bus/ti99/colorbus/busmouse.cpp
+++ b/src/devices/bus/ti99/colorbus/busmouse.cpp
@@ -16,16 +16,16 @@
#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_NS(V9938_BUSMOUSE, bus::ti99::colorbus, v9938_busmouse_device, "v9938_busmouse", "V9938 Bus Mouse")
+DEFINE_DEVICE_TYPE(V9938_BUSMOUSE, bus::ti99::colorbus::v9938_busmouse_device, "v9938_busmouse", "V9938 Bus Mouse")
-namespace bus { namespace ti99 { namespace colorbus {
+namespace bus::ti99::colorbus {
v9938_busmouse_device::v9938_busmouse_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
: device_t(mconfig, V9938_BUSMOUSE, tag, owner, clock),
@@ -85,19 +85,20 @@ INPUT_CHANGED_MEMBER( v9938_busmouse_device::mouse_pos_changed )
INPUT_PORTS_START( busmouse )
PORT_START("MOUSEX") /* Mouse - X AXIS */
- PORT_BIT( 0xffff, 0x00, IPT_MOUSE_X) PORT_SENSITIVITY(50) PORT_KEYDELTA(0) PORT_PLAYER(1) PORT_CHANGED_MEMBER(DEVICE_SELF, v9938_busmouse_device, mouse_pos_changed, 1)
+ PORT_BIT( 0xffff, 0x00, IPT_MOUSE_X) PORT_SENSITIVITY(50) PORT_KEYDELTA(0) PORT_PLAYER(1) PORT_CHANGED_MEMBER(DEVICE_SELF, FUNC(v9938_busmouse_device::mouse_pos_changed), 1)
PORT_START("MOUSEY") /* Mouse - Y AXIS */
- PORT_BIT( 0xffff, 0x00, IPT_MOUSE_Y) PORT_SENSITIVITY(50) PORT_KEYDELTA(0) PORT_PLAYER(1) PORT_CHANGED_MEMBER(DEVICE_SELF, v9938_busmouse_device, mouse_pos_changed, 2)
+ PORT_BIT( 0xffff, 0x00, IPT_MOUSE_Y) PORT_SENSITIVITY(50) PORT_KEYDELTA(0) PORT_PLAYER(1) PORT_CHANGED_MEMBER(DEVICE_SELF, FUNC(v9938_busmouse_device::mouse_pos_changed), 2)
PORT_START("MOUSEBUT") /* mouse buttons */
- PORT_BIT( 0x04, IP_ACTIVE_HIGH, IPT_BUTTON1) PORT_NAME("Left mouse button") PORT_CHANGED_MEMBER(DEVICE_SELF, v9938_busmouse_device, mouse_button_changed, 4)
- PORT_BIT( 0x01, IP_ACTIVE_HIGH, IPT_BUTTON2) PORT_NAME("Right mouse button") PORT_CHANGED_MEMBER(DEVICE_SELF, v9938_busmouse_device, mouse_button_changed, 1)
- PORT_BIT( 0x02, IP_ACTIVE_HIGH, IPT_BUTTON3) PORT_NAME("Middle mouse button") PORT_CHANGED_MEMBER(DEVICE_SELF, v9938_busmouse_device, mouse_button_changed, 2)
+ PORT_BIT( 0x04, IP_ACTIVE_HIGH, IPT_BUTTON1) PORT_NAME("Left mouse button") PORT_CHANGED_MEMBER(DEVICE_SELF, FUNC(v9938_busmouse_device::mouse_button_changed), 4)
+ PORT_BIT( 0x01, IP_ACTIVE_HIGH, IPT_BUTTON2) PORT_NAME("Right mouse button") PORT_CHANGED_MEMBER(DEVICE_SELF, FUNC(v9938_busmouse_device::mouse_button_changed), 1)
+ PORT_BIT( 0x02, IP_ACTIVE_HIGH, IPT_BUTTON3) PORT_NAME("Middle mouse button") PORT_CHANGED_MEMBER(DEVICE_SELF, FUNC(v9938_busmouse_device::mouse_button_changed), 2)
INPUT_PORTS_END
ioport_constructor v9938_busmouse_device::device_input_ports() const
{
return INPUT_PORTS_NAME( busmouse );
}
-} } } // end namespace bus::ti99::colorbus
+
+} // end namespace bus::ti99::colorbus
diff --git a/src/devices/bus/ti99/colorbus/busmouse.h b/src/devices/bus/ti99/colorbus/busmouse.h
index 1a76e26e561..c53ed629443 100644
--- a/src/devices/bus/ti99/colorbus/busmouse.h
+++ b/src/devices/bus/ti99/colorbus/busmouse.h
@@ -17,7 +17,7 @@
#include "colorbus.h"
-namespace bus { namespace ti99 { namespace colorbus {
+namespace bus::ti99::colorbus {
class v9938_busmouse_device : public device_t, public device_v9938_colorbus_interface
{
@@ -27,8 +27,8 @@ public:
DECLARE_INPUT_CHANGED_MEMBER( mouse_pos_changed );
protected:
- void device_start() override;
- void device_reset() override;
+ void device_start() override ATTR_COLD;
+ void device_reset() override ATTR_COLD;
ioport_constructor device_input_ports() const override;
private:
@@ -37,7 +37,8 @@ private:
int m_last_y;
int m_bstate;
};
-} } } // end namespace bus::ti99::colorbus
+
+} // end namespace bus::ti99::colorbus
DECLARE_DEVICE_TYPE_NS(V9938_BUSMOUSE, bus::ti99::colorbus, v9938_busmouse_device)
diff --git a/src/devices/bus/ti99/colorbus/colorbus.cpp b/src/devices/bus/ti99/colorbus/colorbus.cpp
index 0fe5411c9a7..d3f26da93f1 100644
--- a/src/devices/bus/ti99/colorbus/colorbus.cpp
+++ b/src/devices/bus/ti99/colorbus/colorbus.cpp
@@ -20,17 +20,16 @@
#include "emu.h"
#include "colorbus.h"
#include "busmouse.h"
-#include "bus/ti99/ti99defs.h"
-DEFINE_DEVICE_TYPE_NS(V9938_COLORBUS, bus::ti99::colorbus, v9938_colorbus_device, "v9938_colorbus", "V9938 Color bus")
+DEFINE_DEVICE_TYPE(V9938_COLORBUS, bus::ti99::colorbus::v9938_colorbus_device, "v9938_colorbus", "V9938 Color bus")
-namespace bus { namespace ti99 { namespace colorbus {
+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_slot_interface(mconfig, *this),
- m_v9938(*owner, TI_VDP_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)
{
}
@@ -52,17 +51,22 @@ 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)
+{
+}
+
void device_v9938_colorbus_interface::interface_config_complete()
{
m_colorbus = dynamic_cast<v9938_colorbus_device*>(device().owner());
}
-} } } // end namespace bus::ti99::colorbus
+} // end namespace bus::ti99::colorbus
void ti99_colorbus_options(device_slot_interface &device)
{
diff --git a/src/devices/bus/ti99/colorbus/colorbus.h b/src/devices/bus/ti99/colorbus/colorbus.h
index d0139e4b736..35d593f5605 100644
--- a/src/devices/bus/ti99/colorbus/colorbus.h
+++ b/src/devices/bus/ti99/colorbus/colorbus.h
@@ -18,26 +18,30 @@
#include "video/v9938.h"
-namespace bus { namespace ti99 { namespace colorbus {
+#define TIGEN_V9938_TAG "vdp"
+#define COLORBUS_TAG "colorbus"
+
+namespace bus::ti99::colorbus {
class v9938_colorbus_device;
/********************************************************************
Common parent class of all devices attached to the color bus
********************************************************************/
-class device_v9938_colorbus_interface : public device_slot_card_interface
+class device_v9938_colorbus_interface : public device_interface
{
protected:
- using device_slot_card_interface::device_slot_card_interface;
+ device_v9938_colorbus_interface(const machine_config &mconfig, device_t &device);
virtual void interface_config_complete() override;
- v9938_colorbus_device* m_colorbus = nullptr;
+
+ v9938_colorbus_device* m_colorbus;
};
/********************************************************************
Color bus port
********************************************************************/
-class v9938_colorbus_device : public device_t, public device_slot_interface
+class v9938_colorbus_device : public device_t, public device_single_card_slot_interface<device_v9938_colorbus_interface>
{
public:
template <typename U>
@@ -61,14 +65,14 @@ public:
void buttons(int bstate);
protected:
- void device_start() override;
+ void device_start() override ATTR_COLD;
private:
required_device<v9938_device> m_v9938;
devcb_write_line m_extra_button;
};
-} } } // end namespace bus::ti99::colorbus
+} // end namespace bus::ti99::colorbus
DECLARE_DEVICE_TYPE_NS(V9938_COLORBUS, bus::ti99::colorbus, v9938_colorbus_device)
diff --git a/src/devices/bus/ti99/gromport/cartridges.cpp b/src/devices/bus/ti99/gromport/cartridges.cpp
index b56e3dbb4f9..e54f82e42ec 100644
--- a/src/devices/bus/ti99/gromport/cartridges.cpp
+++ b/src/devices/bus/ti99/gromport/cartridges.cpp
@@ -15,25 +15,29 @@
#include "emu.h"
#include "cartridges.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_GROM (1U<<8) // GROM access
-#define LOG_RPK (1U<<9) // RPK handler
-
-#define VERBOSE ( LOG_WARN )
+#include "fileio.h"
+
+#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 | LOG_CHANGE)
#include "logmacro.h"
-DEFINE_DEVICE_TYPE_NS(TI99_CART, bus::ti99::gromport, ti99_cartridge_device, "ti99cart", "TI-99 cartridge")
+DEFINE_DEVICE_TYPE(TI99_CART, bus::ti99::gromport::ti99_cartridge_device, "ti99cart", "TI-99 cartridge")
-namespace bus { namespace ti99 { namespace gromport {
+namespace bus::ti99::gromport {
#define CARTGROM_TAG "grom_contents"
-#define CARTROM_TAG "rom_contents"
#define GROM3_TAG "grom3"
#define GROM4_TAG "grom4"
#define GROM5_TAG "grom5"
@@ -56,21 +60,21 @@ enum
PCB_PAGED7
};
-static const pcb_type pcbdefs[] =
-{
- { PCB_STANDARD, "standard" },
- { PCB_PAGED12K, "paged12k" },
- { PCB_PAGED16K, "paged" },
- { PCB_MINIMEM, "minimem" },
- { PCB_SUPER, "super" },
- { PCB_MBX, "mbx" },
- { PCB_PAGED379I, "paged379i" },
- { PCB_PAGED378, "paged378" },
- { PCB_PAGED377, "paged377" },
- { PCB_PAGEDCRU, "pagedcru" },
- { PCB_GROMEMU, "gromemu" },
- { PCB_PAGED7, "paged7" },
- { 0, nullptr}
+static char const *const pcbdefs[] =
+{
+ "standard", // PCB_STANDARD
+ "paged12k", // PCB_PAGED12K
+ "paged", // PCB_PAGED16K
+ "minimem", // PCB_MINIMEM
+ "super", // PCB_SUPER
+ "mbx", // PCB_MBX
+ "paged379i", // PCB_PAGED379I
+ "paged378", // PCB_PAGED378
+ "paged377", // PCB_PAGED377
+ "pagedcru", // PCB_PAGEDCRU
+ "gromemu", // PCB_GROMEMU
+ "paged7", // PCB_PAGED7
+ nullptr
};
static const pcb_type sw_pcbdefs[] =
@@ -88,24 +92,21 @@ static const pcb_type sw_pcbdefs[] =
ti99_cartridge_device::ti99_cartridge_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
: device_t(mconfig, TI99_CART, tag, owner, clock),
- device_image_interface(mconfig, *this),
+ device_cartrom_image_interface(mconfig, *this),
m_pcbtype(0),
- m_slot(0),
m_pcb(nullptr),
- m_connector(nullptr),
- m_rpk(nullptr)
+ m_connector(nullptr)
{
}
void ti99_cartridge_device::prepare_cartridge()
{
- int rom2_length;
+ int rom1_length = 0;
+ int rom2_length = 0;
uint8_t* grom_ptr;
uint8_t* rom_ptr;
-
memory_region *regg;
- memory_region *regr;
// Initialize some values.
m_pcb->m_rom_page = 0;
@@ -117,7 +118,10 @@ void ti99_cartridge_device::prepare_cartridge()
for (int i=0; i < 5; i++) m_pcb->m_grom[i] = nullptr;
m_pcb->m_grom_size = loaded_through_softlist() ? get_software_region_length("grom") : m_rpk->get_resource_length("grom_socket");
- LOGMASKED(LOG_CONFIG, "grom_socket.size=0x%04x\n", m_pcb->m_grom_size);
+ if (m_pcb->m_grom_size == 0)
+ LOGMASKED(LOG_CONFIG, "No GROM dump\n");
+ else
+ LOGMASKED(LOG_CONFIG, "GROM dump size=0x%04x\n", m_pcb->m_grom_size);
if (m_pcb->m_grom_size > 0)
{
@@ -135,31 +139,85 @@ void ti99_cartridge_device::prepare_cartridge()
if (m_pcb->m_grom_size > 0x8000) m_pcb->set_grom_pointer(4, subdevice(GROM7_TAG));
}
- m_pcb->m_rom_size = loaded_through_softlist() ? get_software_region_length("rom") : m_rpk->get_resource_length("rom_socket");
- if (m_pcb->m_rom_size > 0)
- {
- if (m_pcb->m_rom_size > 0x200000) fatalerror("Cartridge ROM size exceeding 2 MiB");
- LOGMASKED(LOG_CONFIG, "rom size=0x%04x\n", m_pcb->m_rom_size);
- regr = memregion(CARTROM_TAG);
- rom_ptr = loaded_through_softlist() ? get_software_region("rom") : m_rpk->get_contents_of_socket("rom_socket");
- memcpy(regr->base(), rom_ptr, m_pcb->m_rom_size);
- // Set both pointers to the same region for now
- m_pcb->m_rom_ptr = regr->base();
- }
+ rom1_length = loaded_through_softlist() ? get_software_region_length("rom") : m_rpk->get_resource_length("rom_socket");
+ m_pcb->m_bank_mask = 0;
- // Softlist uses only one ROM area, no second socket
- if (!loaded_through_softlist())
+ if (rom1_length > 0)
{
- rom2_length = m_rpk->get_resource_length("rom2_socket");
+ LOGMASKED(LOG_CONFIG, "ROM dump size=0x%04x\n", rom1_length);
+
+ // Round up to 8K multiple; dumps may be shorter, but we have
+ // a cartridge ROM window of 8K
+ // TODO: Allow for mirroring?
+ m_pcb->m_rom_size = rom1_length;
+
+ if ((rom1_length % 0x2000)!=0)
+ m_pcb->m_rom_size = (rom1_length + 0x2000) & ~0x1fff;
+
+ // Softlist uses only one ROM area, no second socket
+ if (!loaded_through_softlist())
+ {
+ rom2_length = m_rpk->get_resource_length("rom2_socket");
+ }
+
+ // Using ROM2 socket automatically implies paged12, paged16,
+ // or gromemu schemes
if (rom2_length > 0)
{
- // sizes do not differ between rom and rom2
- // We use the large cartrom space for the second bank as well
- regr = memregion(CARTROM_TAG);
+ LOGMASKED(LOG_CONFIG, "Second ROM dump size = 0x%04x\n", rom2_length);
+ if (rom2_length > 0x2000)
+ {
+ LOGMASKED(LOG_WARN, "Can only use 8K for second socket; dump truncated\n");
+ rom2_length = 0x2000;
+ }
+
+ if (m_pcb->m_rom_size > 0x2000)
+ {
+ m_pcb->m_rom_size = 0x2000;
+ LOGMASKED(LOG_WARN, "Can only use 8K for first socket when there is a second socket; dump truncated.\n");
+ }
+
+ // We assign 16K for both rom1 and rom2, so this is properly
+ // aligned with the 8K spaces even when the dumps are shorter
+ m_romspace = make_unique_clear<u8[]>(0x4000);
+
+ // Load the contents of the second socket in the upper half
+ // The contents of the first socket are copied later
rom_ptr = m_rpk->get_contents_of_socket("rom2_socket");
- memcpy(regr->base() + 0x2000, rom_ptr, rom2_length);
+ memcpy(m_romspace.get() + 0x2000, rom_ptr, rom2_length);
+
+ m_pcb->m_bank_mask = 1;
+ LOGMASKED(LOG_CONFIG, "ROM bank mask=0x0001 (using ROM1/ROM2)\n");
}
+ else
+ {
+ m_romspace = make_unique_clear<u8[]>(m_pcb->m_rom_size);
+
+ // Determine the bank mask for flexible ROM sizes in gromemu
+ int rsizet = m_pcb->m_rom_size;
+ int msizet = 0x2000;
+ int banks = 1;
+
+ while (msizet < rsizet)
+ {
+ m_pcb->m_bank_mask = (m_pcb->m_bank_mask<<1) | 1;
+ banks<<=1;
+ msizet <<= 1;
+ }
+ if (banks > 1)
+ LOGMASKED(LOG_CONFIG, "ROM bank mask=0x%04x (%d banks)\n", m_pcb->m_bank_mask, banks);
+ }
+
+ rom_ptr = loaded_through_softlist() ? get_software_region("rom") : m_rpk->get_contents_of_socket("rom_socket");
+ memcpy(m_romspace.get(), rom_ptr, rom1_length);
+
+ m_pcb->m_rom_ptr = m_romspace.get();
}
+ else
+ {
+ LOGMASKED(LOG_CONFIG, "No ROM dump\n");
+ }
+
// (NV)RAM cartridges
if (loaded_through_softlist())
@@ -171,6 +229,7 @@ void ti99_cartridge_device::prepare_cartridge()
m_pcb->m_nvram.resize(m_pcb->m_ram_size);
m_pcb->m_ram_ptr = &m_pcb->m_nvram[0];
battery_load(m_pcb->m_ram_ptr, m_pcb->m_ram_size, 0xff);
+ LOGMASKED(LOG_CONFIG, "NVRAM size=0x%04x\n", m_pcb->m_ram_size);
}
// Do we have RAM?
@@ -179,6 +238,7 @@ void ti99_cartridge_device::prepare_cartridge()
m_pcb->m_ram_size = get_software_region_length("ram");
m_pcb->m_ram.resize(m_pcb->m_ram_size);
m_pcb->m_ram_ptr = &m_pcb->m_ram[0];
+ LOGMASKED(LOG_CONFIG, "RAM size=0x%04x\n", m_pcb->m_ram_size);
}
}
else
@@ -186,8 +246,8 @@ void ti99_cartridge_device::prepare_cartridge()
m_pcb->m_ram_size = m_rpk->get_resource_length("ram_socket");
if (m_pcb->m_ram_size > 0)
{
- // TODO: Consider to use a region as well. If so, do not forget to memcpy.
m_pcb->m_ram_ptr = m_rpk->get_contents_of_socket("ram_socket");
+ LOGMASKED(LOG_CONFIG, "RAM size=0x%04x\n", m_pcb->m_ram_size);
}
}
}
@@ -210,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())
{
@@ -231,23 +291,21 @@ image_init_result ti99_cartridge_device::call_load()
i++;
} while (sw_pcbdefs[i].id != 0);
LOGMASKED(LOG_CONFIG, "Cartridge type is %s (%d)\n", pcb, m_pcbtype);
- m_rpk = nullptr;
+ m_rpk.reset();
}
else
{
- auto reader = std::make_unique<rpk_reader>(pcbdefs);
- try
+ util::core_file::ptr proxy;
+ std::error_condition err = util::core_file::open_proxy(image_core_file(), proxy);
+ if (!err)
+ err = rpk_open(machine().options(), std::move(proxy), machine().system().name, m_rpk);
+ if (err)
{
- m_rpk = reader->open(machine().options(), filename(), machine().system().name);
- m_pcbtype = m_rpk->get_type();
- }
- catch (rpk_exception& err)
- {
- LOGMASKED(LOG_WARN, "Failed to load cartridge '%s': %s\n", basename(), err.to_string().c_str());
- m_rpk = nullptr;
- m_err = IMAGE_ERROR_INVALIDIMAGE;
- return image_init_result::FAIL;
+ LOGMASKED(LOG_WARN, "Failed to load cartridge '%s': %s\n", basename(), err.message().c_str());
+ m_rpk.reset();
+ return std::make_pair(err, std::string());
}
+ m_pcbtype = m_rpk->get_type();
}
switch (m_pcbtype)
@@ -305,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()
@@ -316,7 +373,7 @@ void ti99_cartridge_device::call_unload()
if (m_rpk != nullptr)
{
m_rpk->close(); // will write NVRAM contents
- delete m_rpk;
+ m_rpk.reset();
}
else
{
@@ -329,16 +386,24 @@ 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();
}
-READ8Z_MEMBER(ti99_cartridge_device::readz)
+void ti99_cartridge_device::readz(offs_t offset, uint8_t *value)
{
if (m_pcb != nullptr)
m_pcb->readz(offset, value);
@@ -350,7 +415,7 @@ void ti99_cartridge_device::write(offs_t offset, uint8_t data)
m_pcb->write(offset, data);
}
-READ8Z_MEMBER(ti99_cartridge_device::crureadz)
+void ti99_cartridge_device::crureadz(offs_t offset, uint8_t *value)
{
if (m_pcb != nullptr) m_pcb->crureadz(offset, value);
}
@@ -360,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)
{
@@ -382,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);
}
@@ -392,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
*/
@@ -410,13 +470,12 @@ void ti99_cartridge_device::device_add_mconfig(machine_config& config)
}
/*
- Memory area for one cartridge. For most cartridges we only need 8 KiB for
- ROM contents, but cartridges of the "paged377" type have up to 2 MiB
- organised as selectable banks, so we must be sure there is enough space.
+ Memory area for one cartridge. This only covers the GROM area, since we
+ assign portions of the memory to subdevices (TMC0430). For the ROM area,
+ we use a dynamically allocated space, since the sizes vary strongly.
*/
ROM_START( cartridge_memory )
ROM_REGION(0xa000, CARTGROM_TAG, ROMREGION_ERASE00)
- ROM_REGION(0x200000, CARTROM_TAG, ROMREGION_ERASE00)
ROM_END
const tiny_rom_entry *ti99_cartridge_device::device_rom_region() const
@@ -493,7 +552,7 @@ void ti99_cartridge_pcb::gromwrite(uint8_t data)
cartridges with up to 16 KiB we need a new PCB type. Unfortunately, such
cartridges were never developed.
*/
-READ8Z_MEMBER(ti99_cartridge_pcb::readz)
+void ti99_cartridge_pcb::readz(offs_t offset, uint8_t *value)
{
if (m_romspace_selected)
{
@@ -519,7 +578,9 @@ void ti99_cartridge_pcb::write(offs_t offset, uint8_t data)
{
if (m_romspace_selected)
{
- if (m_ram_ptr == nullptr) LOGMASKED(LOG_WARN, "Cannot write to cartridge ROM space at %04x\n", offset | 0x6000);
+ // Do not warn by default; devices like Horizon will create a lot of
+ // meaningless warnings at this point
+ if (m_ram_ptr == nullptr) LOGMASKED(LOG_WARNW, "Cannot write to cartridge ROM space at %04x\n", offset | 0x6000);
else
{
// Check if we have RAM in the ROM socket
@@ -536,7 +597,7 @@ void ti99_cartridge_pcb::write(offs_t offset, uint8_t data)
}
}
-READ8Z_MEMBER(ti99_cartridge_pcb::crureadz)
+void ti99_cartridge_pcb::crureadz(offs_t offset, uint8_t *value)
{
}
@@ -550,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);
}
@@ -572,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)
{
@@ -609,7 +670,7 @@ WRITE_LINE_MEMBER(ti99_cartridge_pcb::gclock_in)
******************************************************************************/
-READ8Z_MEMBER(ti99_paged12k_cartridge::readz)
+void ti99_paged12k_cartridge::readz(offs_t offset, uint8_t *value)
{
if (m_romspace_selected)
{
@@ -634,7 +695,7 @@ void ti99_paged12k_cartridge::write(offs_t offset, uint8_t data)
{
m_rom_page = (offset >> 1) & 1;
if ((offset & 1)==0)
- LOGMASKED(LOG_WARN, "Set ROM page = %d (writing to %04x)\n", m_rom_page, (offset | 0x6000));
+ LOGMASKED(LOG_BANKSWITCH, "Set ROM page = %d (writing to %04x)\n", m_rom_page, (offset | 0x6000));
}
else
{
@@ -664,7 +725,7 @@ void ti99_paged12k_cartridge::write(offs_t offset, uint8_t data)
6002 = bank 1).
******************************************************************************/
-READ8Z_MEMBER(ti99_paged16k_cartridge::readz)
+void ti99_paged16k_cartridge::readz(offs_t offset, uint8_t *value)
{
if (m_romspace_selected)
{
@@ -711,7 +772,7 @@ void ti99_paged16k_cartridge::write(offs_t offset, uint8_t data)
******************************************************************************/
/* Read function for the minimem cartridge. */
-READ8Z_MEMBER(ti99_minimem_cartridge::readz)
+void ti99_minimem_cartridge::readz(offs_t offset, uint8_t *value)
{
if (m_romspace_selected)
{
@@ -786,7 +847,7 @@ void ti99_minimem_cartridge::write(offs_t offset, uint8_t data)
******************************************************************************/
/* Read function for the super cartridge. */
-READ8Z_MEMBER(ti99_super_cartridge::readz)
+void ti99_super_cartridge::readz(offs_t offset, uint8_t *value)
{
if (m_romspace_selected)
{
@@ -814,7 +875,7 @@ void ti99_super_cartridge::write(offs_t offset, uint8_t data)
}
}
-READ8Z_MEMBER(ti99_super_cartridge::crureadz)
+void ti99_super_cartridge::crureadz(offs_t offset, uint8_t *value)
{
// offset is the bit number. The CRU base address is already divided by 2.
@@ -903,7 +964,7 @@ void ti99_super_cartridge::cruwrite(offs_t offset, uint8_t data)
******************************************************************************/
/* Read function for the mbx cartridge. */
-READ8Z_MEMBER(ti99_mbx_cartridge::readz)
+void ti99_mbx_cartridge::readz(offs_t offset, uint8_t *value)
{
if (m_romspace_selected)
{
@@ -988,7 +1049,7 @@ void ti99_mbx_cartridge::write(offs_t offset, uint8_t data)
******************************************************************************/
/* Read function for the paged7 cartridge. */
-READ8Z_MEMBER(ti99_paged7_cartridge::readz)
+void ti99_paged7_cartridge::readz(offs_t offset, uint8_t *value)
{
if (m_romspace_selected)
{
@@ -1074,7 +1135,7 @@ void ti99_paged7_cartridge::write(offs_t offset, uint8_t data)
******************************************************************************/
/* Read function for the paged379i cartridge. */
-READ8Z_MEMBER(ti99_paged379i_cartridge::readz)
+void ti99_paged379i_cartridge::readz(offs_t offset, uint8_t *value)
{
if (m_romspace_selected)
*value = m_rom_ptr[(m_rom_page<<13) | (offset & 0x1fff)];
@@ -1106,6 +1167,7 @@ void ti99_paged379i_cartridge::write(offs_t offset, uint8_t data)
Cartridge type: paged378
This type is intended for high-capacity cartridges of up to 512 KiB
plus GROM space of 120KiB (not supported yet)
+ For smaller ROMs, the ROM is automatically mirrored in the bank space.
Due to its huge GROM space it is also called the "UberGROM"
@@ -1125,7 +1187,7 @@ void ti99_paged379i_cartridge::write(offs_t offset, uint8_t data)
******************************************************************************/
/* Read function for the paged378 cartridge. */
-READ8Z_MEMBER(ti99_paged378_cartridge::readz)
+void ti99_paged378_cartridge::readz(offs_t offset, uint8_t *value)
{
if (m_romspace_selected)
*value = m_rom_ptr[(m_rom_page<<13) | (offset & 0x1fff)];
@@ -1138,7 +1200,10 @@ void ti99_paged378_cartridge::write(offs_t offset, uint8_t data)
// x = don't care, bbbb = bank
if (m_romspace_selected)
{
- m_rom_page = ((offset >> 1)&0x003f);
+ // Auto-adapt to the size of the ROM
+ int mask = ((m_rom_size / 8192) - 1) & 0x3f;
+ m_rom_page = ((offset >> 1)&mask);
+
if ((offset & 1)==0)
LOGMASKED(LOG_BANKSWITCH, "Set ROM page = %d (writing to %04x)\n", m_rom_page, (offset | 0x6000));
}
@@ -1165,7 +1230,7 @@ void ti99_paged378_cartridge::write(offs_t offset, uint8_t data)
******************************************************************************/
/* Read function for the paged377 cartridge. */
-READ8Z_MEMBER(ti99_paged377_cartridge::readz)
+void ti99_paged377_cartridge::readz(offs_t offset, uint8_t *value)
{
if (m_romspace_selected)
*value = m_rom_ptr[(m_rom_page<<13) | (offset & 0x1fff)];
@@ -1219,7 +1284,7 @@ void ti99_paged377_cartridge::write(offs_t offset, uint8_t data)
******************************************************************************/
/* Read function for the pagedcru cartridge. */
-READ8Z_MEMBER(ti99_pagedcru_cartridge::readz)
+void ti99_pagedcru_cartridge::readz(offs_t offset, uint8_t *value)
{
if (m_romspace_selected)
*value = m_rom_ptr[(m_rom_page<<13) | (offset & 0x1fff)];
@@ -1231,7 +1296,7 @@ void ti99_pagedcru_cartridge::write(offs_t offset, uint8_t data)
return;
}
-READ8Z_MEMBER(ti99_pagedcru_cartridge::crureadz)
+void ti99_pagedcru_cartridge::crureadz(offs_t offset, uint8_t *value)
{
int page = m_rom_page;
if ((offset & 0xf800)==0x0800)
@@ -1270,23 +1335,16 @@ void ti99_pagedcru_cartridge::cruwrite(offs_t offset, uint8_t data)
will deliver the address when reading.
- No wait states. Reading is generally faster than with real GROMs.
- No wrapping at 8K boundaries.
- - Two pages of ROM at address 6000
-
- If any of these fails, the cartridge will crash, so we'll see.
+ - One or two ROM sockets; if one socket, the standard bank switch scheme is
+ used
Typical cartridges: Third-party cartridges
For the sake of simplicity, we register GROMs like the other PCB types, but
we implement special access methods for the GROM space.
- Still not working:
- rxb1002 (Set page to 1 (6372 <- 00), lockup)
- rxb237 (immediate reset)
- rxbv555 (repeating reset on Master Title Screen)
- superxb (lockup, fix: add RAM at 7c00)
-
Super-MiniMemory is also included here. We assume a RAM area at addresses
- 7000-7fff for this cartridge.
+ 7000-7fff for this cartridge if the RAM option is used.
GROM space
@@ -1296,24 +1354,35 @@ void ti99_pagedcru_cartridge::cruwrite(offs_t offset, uint8_t data)
ROM space
6000 7000 7fff
| | |
- |========== ROM1 ===========| Bank 0 write to 6000, 6004, ... 7ffc
+ |========== ROM1 ===========| Bank 0
| | |
- |========== ROM2 ===========| Bank 1 write to 6002, 6006, ... 7ffe
+ |========== ROM2 ===========| Bank 1
+ ... ...
+ |========== ROMn ===========| Bank n-1
+
+ Depending on the number of banks, a number of address bits is used to select
+ the bank:
+ Write to 011x xxxx xxxx xxx0 -> Set bank number to xxxxxxxxxxxx
+
+ The number xxxxxxxxxxxx has just enough bits to encode the highest bank number.
+ Higher bits are ignored.
+
+ If rom2_socket is used, we assume that rom_socket and rom2_socket contain
+ 8K ROM each, so we have exactly two banks, regardless of the ROM length.
+
+ The maximum ROM size is 32 MiB (4096 pages of 8 KiB)
******************************************************************************/
void ti99_gromemu_cartridge::set_gromlines(line_state mline, line_state moline, line_state gsq)
{
- if (m_grom_ptr != nullptr)
- {
- m_grom_selected = (gsq == ASSERT_LINE);
- m_grom_read_mode = (mline == ASSERT_LINE);
- m_grom_address_mode = (moline == ASSERT_LINE);
- }
+ m_grom_selected = (gsq == ASSERT_LINE);
+ m_grom_read_mode = (mline == ASSERT_LINE);
+ m_grom_address_mode = (moline == ASSERT_LINE);
}
-READ8Z_MEMBER(ti99_gromemu_cartridge::readz)
+void ti99_gromemu_cartridge::readz(offs_t offset, uint8_t *value)
{
if (m_grom_selected)
{
@@ -1349,7 +1418,9 @@ void ti99_gromemu_cartridge::write(offs_t offset, uint8_t data)
}
return; // no paging
}
- m_rom_page = (offset >> 1) & 1;
+
+ m_rom_page = (offset >> 1) & m_bank_mask;
+
if ((offset & 1)==0)
LOGMASKED(LOG_BANKSWITCH, "Set ROM page = %d (writing to %04x)\n", m_rom_page, (offset | 0x6000));
}
@@ -1363,7 +1434,7 @@ void ti99_gromemu_cartridge::write(offs_t offset, uint8_t data)
}
}
-READ8Z_MEMBER(ti99_gromemu_cartridge::gromemureadz)
+void ti99_gromemu_cartridge::gromemureadz(offs_t offset, uint8_t *value)
{
// Similar to the GKracker implemented above, we do not have a readable
// GROM address counter but use the one from the console GROMs.
@@ -1373,7 +1444,8 @@ READ8Z_MEMBER(ti99_gromemu_cartridge::gromemureadz)
if (id > 2)
{
// Cartridge space (0x6000 - 0xffff)
- *value = m_grom_ptr[m_grom_address-0x6000]; // use the GROM memory
+ if (m_grom_ptr != nullptr)
+ *value = m_grom_ptr[m_grom_address-0x6000]; // use the GROM memory
}
// The GROM emulation does not wrap at 8K boundaries.
@@ -1412,51 +1484,10 @@ void ti99_gromemu_cartridge::gromemuwrite(offs_t offset, uint8_t data)
RPK loader
- RPK format support
-
- A RPK file ("rompack") contains a collection of dump files and a layout
- file that defines the kind of circuit board (PCB) used in the cartridge
- and the mapping of dumps to sockets on the board.
-
-Example:
- <?xml version="1.0" encoding="utf-8"?>
- <romset>
- <resources>
- <rom id="gromimage" file="ed-assmg.bin" />
- </resources>
- <configuration>
- <pcb type="standard">
- <socket id="grom_socket" uses="gromimage"/>
- </pcb>
- </configuration>
- </romset>
-
-DTD:
- <!ELEMENT romset (resources, configuration)>
- <!ELEMENT resources (rom|ram)+>
- <!ELEMENT rom EMPTY>
- <!ELEMENT ram EMPTY>
- <!ELEMENT configuration (pcb)>
- <!ELEMENT pcb (socket)+>
- <!ELEMENT socket EMPTY>
- <!ATTLIST romset version CDATA #IMPLIED>
- <!ATTLIST rom id ID #REQUIRED
- <!ATTLIST rom file CDATA #REQUIRED>
- <!ATTLIST rom crc CDATA #IMPLIED>
- <!ATTLIST rom sha1 CDATA #IMPLIED>
- <!ATTLIST ram id ID #REQUIRED>
- <!ATTLIST ram type (volatile|persistent) #IMPLIED>
- <!ATTLIST ram store (internal|external) #IMPLIED>
- <!ATTLIST ram file CDATA #IMPLIED>
- <!ATTLIST ram length CDATA #REQUIRED>
- <!ATTLIST pcb type CDATA #REQUIRED>
- <!ATTLIST socket id ID #REQUIRED>
- <!ATTLIST socket uses IDREF #REQUIRED>
-
****************************************************************************/
#undef LOG_OUTPUT_FUNC
-#define LOG_OUTPUT_FUNC printf
+#define LOG_OUTPUT_FUNC osd_printf_info
/****************************************
RPK class
@@ -1496,7 +1527,7 @@ int ti99_cartridge_device::rpk::get_resource_length(const char *socket_name)
return socket->second->get_content_length();
}
-void ti99_cartridge_device::rpk::add_socket(const char* id, std::unique_ptr<rpk_socket> newsock)
+void ti99_cartridge_device::rpk::add_socket(const char* id, std::unique_ptr<ti99_rpk_socket> &&newsock)
{
m_sockets.emplace(id, std::move(newsock));
}
@@ -1518,8 +1549,8 @@ void ti99_cartridge_device::rpk::close()
throw emu_fatalerror("ti99_cartridge_device::rpk::close: Buffer is null or length is 0");
emu_file file(m_options.nvram_directory(), OPEN_FLAG_WRITE | OPEN_FLAG_CREATE | OPEN_FLAG_CREATE_PATHS);
- osd_file::error filerr = file.open(socket.second->get_pathname());
- if (filerr == osd_file::error::NONE)
+ std::error_condition const filerr = file.open(socket.second->get_pathname());
+ if (!filerr)
file.write(socket.second->get_contents(), socket.second->get_content_length());
}
@@ -1532,191 +1563,68 @@ void ti99_cartridge_device::rpk::close()
not a network socket)
***************************************************************/
-ti99_cartridge_device::rpk_socket::rpk_socket(const char* id, int length, uint8_t* contents, std::string &&pathname)
- : m_id(id), m_length(length), m_contents(contents), m_pathname(std::move(pathname))
+ti99_cartridge_device::ti99_rpk_socket::ti99_rpk_socket(const char* id, int length, std::vector<uint8_t> &&contents, std::string &&pathname)
+ : m_id(id), m_length(length), m_contents(std::move(contents)), m_pathname(std::move(pathname))
{
}
-ti99_cartridge_device::rpk_socket::rpk_socket(const char* id, int length, uint8_t* contents)
- : rpk_socket(id, length, contents, "")
+ti99_cartridge_device::ti99_rpk_socket::ti99_rpk_socket(const char* id, int length, std::vector<uint8_t> &&contents)
+ : ti99_rpk_socket(id, length, std::move(contents), "")
{
}
/*
- Locate a file in the ZIP container
-*/
-int ti99_cartridge_device::rpk_reader::find_file(util::archive_file &zip, const char *filename, uint32_t crc)
-{
- for (int header = zip.first_file(); header >= 0; header = zip.next_file())
- {
- // Ignore directories
- if (!zip.current_is_directory())
- {
- // We don't check for CRC == 0.
- if (crc != 0)
- {
- // if the CRC and name both match, we're good
- // if the CRC matches and the name doesn't, we're still good
- if (zip.current_crc() == crc)
- return header;
- }
- else
- {
- if (core_stricmp(zip.current_name().c_str(), filename) == 0)
- {
- return header;
- }
- }
- }
- }
- return -1;
-}
-
-/*
Load a rom resource and put it in a pcb socket instance.
*/
-std::unique_ptr<ti99_cartridge_device::rpk_socket> ti99_cartridge_device::rpk_reader::load_rom_resource(util::archive_file &zip, util::xml::data_node const* rom_resource_node, const char* socketname)
-{
- const char* file;
- const char* crcstr;
- const char* sha1;
- util::archive_file::error ziperr;
- uint32_t crc;
- int length;
- uint8_t* contents;
- int header;
-
- // find the file attribute (required)
- file = rom_resource_node->get_attribute_string("file", nullptr);
- if (file == nullptr) throw rpk_exception(RPK_INVALID_LAYOUT, "<rom> must have a 'file' attribute");
-
- LOGMASKED(LOG_RPK, "[RPK handler] Loading ROM contents for socket '%s' from file %s\n", socketname, file);
-
- // check for crc
- crcstr = rom_resource_node->get_attribute_string("crc", nullptr);
- if (crcstr==nullptr)
- {
- // no CRC, just find the file in the RPK
- header = find_file(zip, file, 0);
- }
- else
- {
- crc = strtoul(crcstr, nullptr, 16);
- header = find_file(zip, file, crc);
- }
- if (header < 0) throw rpk_exception(RPK_INVALID_FILE_REF, "File not found or CRC check failed");
-
- length = zip.current_uncompressed_length();
-
- // Allocate storage
- contents = global_alloc_array_clear<uint8_t>(length);
- if (contents==nullptr) throw rpk_exception(RPK_OUT_OF_MEMORY);
-
- // and unzip file from the zip file
- ziperr = zip.decompress(contents, length);
- if (ziperr != util::archive_file::error::NONE)
- {
- if (ziperr == util::archive_file::error::UNSUPPORTED) throw rpk_exception(RPK_ZIP_UNSUPPORTED);
- else throw rpk_exception(RPK_ZIP_ERROR);
- }
-
- // check for sha1
- sha1 = rom_resource_node->get_attribute_string("sha1", nullptr);
- if (sha1 != nullptr)
- {
- util::hash_collection actual_hashes;
- actual_hashes.compute((const uint8_t *)contents, length, util::hash_collection::HASH_TYPES_CRC_SHA1);
+std::error_condition ti99_cartridge_device::rpk_load_rom_resource(const rpk_socket &socket, std::unique_ptr<ti99_rpk_socket> &result)
+{
+ LOGMASKED(LOG_RPK, "[RPK handler] Loading ROM contents for socket '%s' from file %s\n", socket.id(), socket.filename());
- util::hash_collection expected_hashes;
- expected_hashes.add_from_string(util::hash_collection::HASH_SHA1, sha1, strlen(sha1));
-
- if (actual_hashes != expected_hashes) throw rpk_exception(RPK_INVALID_FILE_REF, "SHA1 check failed");
- }
+ std::vector<uint8_t> contents;
+ std::error_condition err = socket.read_file(contents);
+ if (err)
+ return err;
// Create a socket instance
- return std::make_unique<rpk_socket>(socketname, length, contents);
+ result = std::make_unique<ti99_rpk_socket>(socket.id().c_str(), contents.size(), std::move(contents));
+ return std::error_condition();
}
/*
Load a ram resource and put it in a pcb socket instance.
*/
-std::unique_ptr<ti99_cartridge_device::rpk_socket> ti99_cartridge_device::rpk_reader::load_ram_resource(emu_options &options, util::xml::data_node const* ram_resource_node, const char* socketname, const char* system_name)
+std::unique_ptr<ti99_cartridge_device::ti99_rpk_socket> ti99_cartridge_device::rpk_load_ram_resource(emu_options &options, const rpk_socket &socket, const char *system_name)
{
- const char* length_string;
- const char* ram_type;
- const char* ram_filename;
- std::string ram_pname;
- unsigned int length;
- uint8_t* contents;
-
- // find the length attribute
- length_string = ram_resource_node->get_attribute_string("length", nullptr);
- if (length_string == nullptr) throw rpk_exception(RPK_MISSING_RAM_LENGTH);
-
- // parse it
- char suffix = '\0';
- sscanf(length_string, "%u%c", &length, &suffix);
- switch(tolower(suffix))
- {
- case 'k': // kilobytes
- length *= 1024;
- break;
-
- case 'm':
- /* megabytes */
- length *= 1024*1024;
- break;
-
- case '\0':
- break;
-
- default: // failed
- throw rpk_exception(RPK_INVALID_RAM_SPEC);
- }
-
// Allocate memory for this resource
- contents = global_alloc_array_clear<uint8_t>(length);
- if (contents==nullptr) throw rpk_exception(RPK_OUT_OF_MEMORY);
+ std::vector<uint8_t> contents;
+ contents.resize(socket.length());
+ std::fill(contents.begin(), contents.end(), 0);
- LOGMASKED(LOG_RPK, "[RPK handler] Allocating RAM buffer (%d bytes) for socket '%s'\n", length, socketname);
+ LOGMASKED(LOG_RPK, "[RPK handler] Allocating RAM buffer (%d bytes) for socket '%s'\n", socket.length(), socket.id());
// That's it for pure RAM. Now check whether the RAM is "persistent", i.e. NVRAM.
// In that case we must load it from the NVRAM directory.
// The file name is given in the RPK file; the subdirectory is the system name.
- ram_type = ram_resource_node->get_attribute_string("type", nullptr);
- if (ram_type != nullptr)
+ std::string ram_pname;
+ if (socket.type() == rpk_socket::socket_type::PERSISTENT_RAM)
{
- if (strcmp(ram_type, "persistent")==0)
- {
- // Get the file name (required if persistent)
- ram_filename = ram_resource_node->get_attribute_string("file", nullptr);
- if (ram_filename==nullptr)
- {
- global_free_array(contents);
- throw rpk_exception(RPK_INVALID_RAM_SPEC, "<ram type='persistent'> must have a 'file' attribute");
- }
- ram_pname = std::string(system_name).append(PATH_SEPARATOR).append(ram_filename);
- // load, and fill rest with 00
- LOGMASKED(LOG_RPK, "[RPK handler] Loading NVRAM contents from '%s'\n", ram_pname.c_str());
-
- // Load the NVRAM contents
- if (!contents || (length <= 0))
- throw emu_fatalerror("ti99_cartridge_device::rpk_reader::load_ram_resource: Buffer is null or length is 0");
-
- // try to open the battery file and read it if possible
- emu_file file(options.nvram_directory(), OPEN_FLAG_READ);
- osd_file::error filerr = file.open(ram_pname);
- int bytes_read = 0;
- if (filerr == osd_file::error::NONE)
- bytes_read = file.read(contents, length);
-
- // fill remaining bytes (if necessary)
- memset(((char *) contents) + bytes_read, 0x00, length - bytes_read);
- }
+ ram_pname = std::string(system_name).append(PATH_SEPARATOR).append(socket.filename());
+ // load, and fill rest with 00
+ LOGMASKED(LOG_RPK, "[RPK handler] Loading NVRAM contents from '%s'\n", ram_pname);
+
+ // try to open the battery file and read it if possible
+ emu_file file(options.nvram_directory(), OPEN_FLAG_READ);
+ std::error_condition const filerr = file.open(ram_pname);
+ int bytes_read = 0;
+ if (!filerr)
+ bytes_read = file.read(&contents[0], contents.size());
+
+ // fill remaining bytes (if necessary)
+ std::fill_n(&contents[bytes_read], contents.size() - bytes_read, 0x00);
}
// Create a socket instance
- return std::make_unique<rpk_socket>(socketname, length, contents, std::move(ram_pname));
+ return std::make_unique<ti99_rpk_socket>(socket.id().c_str(), socket.length(), std::move(contents), std::move(ram_pname));
}
/*-------------------------------------------------
@@ -1725,127 +1633,47 @@ std::unique_ptr<ti99_cartridge_device::rpk_socket> ti99_cartridge_device::rpk_re
system_name - name of the driver (also just for NVRAM handling)
-------------------------------------------------*/
-ti99_cartridge_device::rpk* ti99_cartridge_device::rpk_reader::open(emu_options &options, const char *filename, const char *system_name)
+std::error_condition ti99_cartridge_device::rpk_open(emu_options &options, std::unique_ptr<util::random_read> &&stream, const char *system_name, std::unique_ptr<rpk> &result)
{
- util::archive_file::error ziperr;
+ std::unique_ptr<rpk> newrpk = std::make_unique<rpk>(options, system_name);
- util::archive_file::ptr zipfile;
+ rpk_reader reader(pcbdefs, true);
- std::vector<char> layout_text;
-
- int i;
+ // open the RPK
+ rpk_file::ptr file;
+ std::error_condition err = reader.read(std::move(stream), file);
+ if (err)
+ return err;
- auto newrpk = new rpk(options, system_name);
+ // specify the PCB
+ newrpk->m_type = file->pcb_type() + 1;
+ LOGMASKED(LOG_RPK, "[RPK handler] Cartridge says it has PCB type '%s'\n", pcbdefs[file->pcb_type()]);
- try
+ for (const rpk_socket &socket : file->sockets())
{
- /* open the ZIP file */
- ziperr = util::archive_file::open_zip(filename, zipfile);
- if (ziperr != util::archive_file::error::NONE) throw rpk_exception(RPK_NOT_ZIP_FORMAT);
-
- /* find the layout.xml file */
- if (find_file(*zipfile, "layout.xml", 0) < 0) throw rpk_exception(RPK_MISSING_LAYOUT);
-
- /* reserve space for the layout file contents (+1 for the termination) */
- layout_text.resize(zipfile->current_uncompressed_length() + 1);
-
- /* uncompress the layout text */
- ziperr = zipfile->decompress(&layout_text[0], zipfile->current_uncompressed_length());
- if (ziperr != util::archive_file::error::NONE)
- {
- if (ziperr == util::archive_file::error::UNSUPPORTED) throw rpk_exception(RPK_ZIP_UNSUPPORTED);
- else throw rpk_exception(RPK_ZIP_ERROR);
- }
-
- layout_text[zipfile->current_uncompressed_length()] = '\0'; // Null-terminate
-
- /* parse the layout text */
- util::xml::file::ptr const layout_xml = util::xml::file::string_read(&layout_text[0], nullptr);
- if (!layout_xml) throw rpk_exception(RPK_XML_ERROR);
-
- // Now we work within the XML tree
-
- // romset is the root node
- util::xml::data_node const *const romset_node = layout_xml->get_child("romset");
- if (!romset_node) throw rpk_exception(RPK_INVALID_LAYOUT, "document element must be <romset>");
+ std::unique_ptr<ti99_rpk_socket> ti99_socket;
- // resources is a child of romset
- util::xml::data_node const *const resources_node = romset_node->get_child("resources");
- if (!resources_node) throw rpk_exception(RPK_INVALID_LAYOUT, "<romset> must have a <resources> child");
-
- // configuration is a child of romset; we're actually interested in ...
- util::xml::data_node const *const configuration_node = romset_node->get_child("configuration");
- if (!configuration_node) throw rpk_exception(RPK_INVALID_LAYOUT, "<romset> must have a <configuration> child");
-
- // ... pcb, which is a child of configuration
- util::xml::data_node const *const pcb_node = configuration_node->get_child("pcb");
- if (!pcb_node) throw rpk_exception(RPK_INVALID_LAYOUT, "<configuration> must have a <pcb> child");
-
- // We'll try to find the PCB type on the provided type list.
- char const *const pcb_type = pcb_node->get_attribute_string("type", nullptr);
- if (!pcb_type) throw rpk_exception(RPK_INVALID_LAYOUT, "<pcb> must have a 'type' attribute");
- LOGMASKED(LOG_RPK, "[RPK handler] Cartridge says it has PCB type '%s'\n", pcb_type);
-
- i=0;
- do
+ switch (socket.type())
{
- if (strcmp(pcb_type, m_types[i].name)==0)
- {
- newrpk->m_type = m_types[i].id;
- break;
- }
- i++;
- } while (m_types[i].id != 0);
+ case rpk_socket::socket_type::ROM:
+ err = rpk_load_rom_resource(socket, ti99_socket);
+ if (err)
+ return err;
+ newrpk->add_socket(socket.id().c_str(), std::move(ti99_socket));
+ break;
- if (m_types[i].id==0) throw rpk_exception(RPK_UNKNOWN_PCB_TYPE);
+ case rpk_socket::socket_type::RAM:
+ case rpk_socket::socket_type::PERSISTENT_RAM:
+ newrpk->add_socket(socket.id().c_str(), rpk_load_ram_resource(options, socket, system_name));
+ break;
- // Find the sockets and load their respective resource
- for (util::xml::data_node const *socket_node = pcb_node->get_first_child(); socket_node != nullptr; socket_node = socket_node->get_next_sibling())
- {
- if (strcmp(socket_node->get_name(), "socket")!=0) throw rpk_exception(RPK_INVALID_LAYOUT, "<pcb> element has only <socket> children");
- char const *const id = socket_node->get_attribute_string("id", nullptr);
- if (!id) throw rpk_exception(RPK_INVALID_LAYOUT, "<socket> must have an 'id' attribute");
- char const *const uses_name = socket_node->get_attribute_string("uses", nullptr);
- if (!uses_name) throw rpk_exception(RPK_INVALID_LAYOUT, "<socket> must have a 'uses' attribute");
-
- bool found = false;
- // Locate the resource node
- for (util::xml::data_node const *resource_node = resources_node->get_first_child(); resource_node != nullptr; resource_node = resource_node->get_next_sibling())
- {
- char const *const resource_name = resource_node->get_attribute_string("id", nullptr);
- if (!resource_name) throw rpk_exception(RPK_INVALID_LAYOUT, "resource node must have an 'id' attribute");
-
- if (strcmp(resource_name, uses_name)==0)
- {
- // found it
- if (strcmp(resource_node->get_name(), "rom")==0)
- {
- newrpk->add_socket(id, load_rom_resource(*zipfile, resource_node, id));
- }
- else
- {
- if (strcmp(resource_node->get_name(), "ram")==0)
- {
- newrpk->add_socket(id, load_ram_resource(options, resource_node, id, system_name));
- }
- else throw rpk_exception(RPK_INVALID_LAYOUT, "resource node must be <rom> or <ram>");
- }
- found = true;
- }
- }
- if (!found) throw rpk_exception(RPK_INVALID_RESOURCE_REF, uses_name);
+ default:
+ throw false;
}
}
- catch (rpk_exception &)
- {
- newrpk->close();
-
- // rethrow the exception
- throw;
- }
- return newrpk;
+ result = std::move(newrpk);
+ return std::error_condition();
}
-} } } // end namespace bus::ti99::gromport
-
+} // end namespace bus::ti99::gromport
diff --git a/src/devices/bus/ti99/gromport/cartridges.h b/src/devices/bus/ti99/gromport/cartridges.h
index e2e729f2d59..b25c34accd8 100644
--- a/src/devices/bus/ti99/gromport/cartridges.h
+++ b/src/devices/bus/ti99/gromport/cartridges.h
@@ -8,148 +8,77 @@
#pragma once
-#include "emuopts.h"
-#include "bus/ti99/ti99defs.h"
-#include "machine/tmc0430.h"
-#include "softlist_dev.h"
#include "gromport.h"
-#include "unzip.h"
-#include "xmlfile.h"
-namespace bus { namespace ti99 { namespace gromport {
+#include "imagedev/cartrom.h"
+#include "machine/tmc0430.h"
-class ti99_cartridge_pcb;
+#include "emuopts.h"
-enum rpk_open_error
-{
- RPK_OK,
- RPK_NOT_ZIP_FORMAT,
- RPK_CORRUPT,
- RPK_OUT_OF_MEMORY,
- RPK_XML_ERROR,
- RPK_INVALID_FILE_REF,
- RPK_ZIP_ERROR,
- RPK_ZIP_UNSUPPORTED,
- RPK_MISSING_RAM_LENGTH,
- RPK_INVALID_RAM_SPEC,
- RPK_UNKNOWN_RESOURCE_TYPE,
- RPK_INVALID_RESOURCE_REF,
- RPK_INVALID_LAYOUT,
- RPK_MISSING_LAYOUT,
- RPK_NO_PCB_OR_RESOURCES,
- RPK_UNKNOWN_PCB_TYPE
-};
+#include "utilfwd.h"
-const char *const error_text[16] =
-{
- "No error",
- "Not a RPK (zip) file",
- "Module definition corrupt",
- "Out of memory",
- "XML format error",
- "Invalid file reference",
- "Zip file error",
- "Unsupported zip version",
- "Missing RAM length",
- "Invalid RAM specification",
- "Unknown resource type",
- "Invalid resource reference",
- "layout.xml not valid",
- "Missing layout",
- "No pcb or resource found",
- "Unknown pcb type"
-};
-class ti99_cartridge_device : public device_t, public device_image_interface
+// 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);
- DECLARE_READ8Z_MEMBER(readz);
+ void readz(offs_t offset, uint8_t *value);
void write(offs_t offset, uint8_t data);
- DECLARE_READ8Z_MEMBER(crureadz);
+ 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 void device_add_mconfig(machine_config &config) override ATTR_COLD;
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;
- virtual const software_list_loader &get_software_list_loader() const override { return rom_software_list_loader::instance(); }
void prepare_cartridge();
// device_image_interface
- iodevice_t image_type() const override { return IO_CARTSLOT; }
- bool is_readable() const override { return true; }
- bool is_writeable() const override { return false; }
- bool is_creatable() const override { return false; }
- bool must_be_loaded() const override { return false; }
- bool is_reset_on_load() const override { return false; }
- const char *image_interface() const override { return "ti99_cart"; }
- const char *file_extensions() const override { return "rpk"; }
+ bool is_reset_on_load() const noexcept override { return false; }
+ const char *image_interface() const noexcept override { return "ti99_cart"; }
+ const char *file_extensions() const noexcept override { return "rpk"; }
-private:
+ void set_connector(cartridge_connector_device* conn) { m_connector = conn; }
- /***************** RPK support ********************
- Actually deprecated, and to be removed as soon as
- softlists allow for homebrew cartridges
- ***************************************************/
+private:
- class rpk_socket;
+ class ti99_rpk_socket;
class rpk;
- class rpk_exception
- {
- public:
- rpk_exception(rpk_open_error value): m_err(value), m_detail(nullptr) { }
- rpk_exception(rpk_open_error value, const char* detail) : m_err(value), m_detail(detail) { }
-
- std::string to_string()
- {
- std::string errmsg(error_text[(int)m_err]);
- if (m_detail==nullptr)
- return errmsg;
- return errmsg.append(": ").append(m_detail);
- }
-
- private:
- rpk_open_error m_err;
- const char* m_detail;
- };
-
- class rpk_reader
- {
- public:
- rpk_reader(const pcb_type *types) : m_types(types) { }
-
- rpk *open(emu_options &options, const char *filename, const char *system_name);
-
- private:
- int find_file(util::archive_file &zip, const char *filename, uint32_t crc);
- std::unique_ptr<rpk_socket> load_rom_resource(util::archive_file &zip, util::xml::data_node const* rom_resource_node, const char* socketname);
- std::unique_ptr<rpk_socket> load_ram_resource(emu_options &options, util::xml::data_node const* ram_resource_node, const char* socketname, const char* system_name);
- const pcb_type* m_types;
- };
+ static std::error_condition rpk_open(emu_options &options, std::unique_ptr<util::random_read> &&stream, const char *system_name, std::unique_ptr<rpk> &result);
+ static std::error_condition rpk_load_rom_resource(const rpk_socket &socket, std::unique_ptr<ti99_rpk_socket> &result);
+ static std::unique_ptr<ti99_rpk_socket> rpk_load_ram_resource(emu_options &options, const rpk_socket &socket, const char *system_name);
class rpk
{
- friend class rpk_reader;
+ friend class ti99_cartridge_device;
public:
rpk(emu_options& options, const char* sysname);
~rpk();
@@ -163,43 +92,46 @@ private:
emu_options& m_options; // need this to find the path to the nvram files
int m_type;
//const char* m_system_name; // need this to find the path to the nvram files
- std::unordered_map<std::string,std::unique_ptr<rpk_socket>> m_sockets;
+ std::unordered_map<std::string,std::unique_ptr<ti99_rpk_socket>> m_sockets;
- void add_socket(const char* id, std::unique_ptr<rpk_socket> newsock);
+ void add_socket(const char* id, std::unique_ptr<ti99_rpk_socket> &&newsock);
};
- class rpk_socket
+ class ti99_rpk_socket
{
public:
- rpk_socket(const char *id, int length, uint8_t *contents);
- rpk_socket(const char *id, int length, uint8_t *contents, std::string &&pathname);
- ~rpk_socket() {}
+ ti99_rpk_socket(const char *id, int length, std::vector<uint8_t> &&contents);
+ ti99_rpk_socket(const char *id, int length, std::vector<uint8_t> &&contents, std::string &&pathname);
+ ~ti99_rpk_socket() {}
const char* id() { return m_id; }
int get_content_length() { return m_length; }
- uint8_t* get_contents() { return m_contents; }
+ uint8_t* get_contents() { return &m_contents[0]; }
bool persistent_ram() { return !m_pathname.empty(); }
const char* get_pathname() { return m_pathname.c_str(); }
- void cleanup() { if (m_contents != nullptr) global_free_array(m_contents); }
+ void cleanup() { m_contents.clear(); }
private:
const char* m_id;
uint32_t m_length;
- uint8_t* m_contents;
+ std::vector<uint8_t> m_contents;
const std::string m_pathname;
};
bool m_readrom;
int m_pcbtype;
- int m_slot;
int get_index_from_tagname();
std::unique_ptr<ti99_cartridge_pcb> m_pcb; // inbound
cartridge_connector_device* m_connector; // outbound
+ // We use dynamically allocated space instead of memory regions
+ // because the required spaces are widely varying (8K to 32M)
+ std::unique_ptr<u8[]> m_romspace;
+
// RPK which is associated to this cartridge
// When we close it, the contents are saved to NVRAM if available
- rpk *m_rpk;
+ std::unique_ptr<rpk> m_rpk;
};
/****************************************************************************/
@@ -212,14 +144,14 @@ public:
virtual ~ti99_cartridge_pcb() { }
protected:
- virtual DECLARE_READ8Z_MEMBER(readz);
+ virtual void readz(offs_t offset, uint8_t *value);
virtual void write(offs_t offset, uint8_t data);
- virtual DECLARE_READ8Z_MEMBER(crureadz);
+ 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);
@@ -237,6 +169,7 @@ protected:
int m_grom_size;
int m_rom_size;
int m_ram_size;
+ int m_bank_mask;
uint8_t* m_rom_ptr;
uint8_t* m_ram_ptr;
@@ -262,7 +195,7 @@ public:
class ti99_paged12k_cartridge : public ti99_cartridge_pcb
{
public:
- DECLARE_READ8Z_MEMBER(readz) override;
+ void readz(offs_t offset, uint8_t *value) override;
void write(offs_t offset, uint8_t data) override;
};
@@ -271,7 +204,7 @@ public:
class ti99_paged16k_cartridge : public ti99_cartridge_pcb
{
public:
- DECLARE_READ8Z_MEMBER(readz) override;
+ void readz(offs_t offset, uint8_t *value) override;
void write(offs_t offset, uint8_t data) override;
};
@@ -280,7 +213,7 @@ public:
class ti99_paged7_cartridge : public ti99_cartridge_pcb
{
public:
- DECLARE_READ8Z_MEMBER(readz) override;
+ void readz(offs_t offset, uint8_t *value) override;
void write(offs_t offset, uint8_t data) override;
};
@@ -289,7 +222,7 @@ public:
class ti99_minimem_cartridge : public ti99_cartridge_pcb
{
public:
- DECLARE_READ8Z_MEMBER(readz) override;
+ void readz(offs_t offset, uint8_t *value) override;
void write(offs_t offset, uint8_t data) override;
};
@@ -298,9 +231,9 @@ public:
class ti99_super_cartridge : public ti99_cartridge_pcb
{
public:
- DECLARE_READ8Z_MEMBER(readz) override;
+ void readz(offs_t offset, uint8_t *value) override;
void write(offs_t offset, uint8_t data) override;
- DECLARE_READ8Z_MEMBER(crureadz) override;
+ void crureadz(offs_t offset, uint8_t *value) override;
void cruwrite(offs_t offset, uint8_t data) override;
};
@@ -309,7 +242,7 @@ public:
class ti99_mbx_cartridge : public ti99_cartridge_pcb
{
public:
- DECLARE_READ8Z_MEMBER(readz) override;
+ void readz(offs_t offset, uint8_t *value) override;
void write(offs_t offset, uint8_t data) override;
};
@@ -318,7 +251,7 @@ public:
class ti99_paged379i_cartridge : public ti99_cartridge_pcb
{
public:
- DECLARE_READ8Z_MEMBER(readz) override;
+ void readz(offs_t offset, uint8_t *value) override;
void write(offs_t offset, uint8_t data) override;
private:
int get_paged379i_bank(int rompage);
@@ -329,7 +262,7 @@ private:
class ti99_paged378_cartridge : public ti99_cartridge_pcb
{
public:
- DECLARE_READ8Z_MEMBER(readz) override;
+ void readz(offs_t offset, uint8_t *value) override;
void write(offs_t offset, uint8_t data) override;
};
@@ -338,7 +271,7 @@ public:
class ti99_paged377_cartridge : public ti99_cartridge_pcb
{
public:
- DECLARE_READ8Z_MEMBER(readz) override;
+ void readz(offs_t offset, uint8_t *value) override;
void write(offs_t offset, uint8_t data) override;
};
@@ -347,9 +280,9 @@ public:
class ti99_pagedcru_cartridge : public ti99_cartridge_pcb
{
public:
- DECLARE_READ8Z_MEMBER(readz) override;
+ void readz(offs_t offset, uint8_t *value) override;
void write(offs_t offset, uint8_t data) override;
- DECLARE_READ8Z_MEMBER(crureadz) override;
+ void crureadz(offs_t offset, uint8_t *value) override;
void cruwrite(offs_t offset, uint8_t data) override;
};
@@ -360,9 +293,9 @@ class ti99_gromemu_cartridge : public ti99_cartridge_pcb
public:
ti99_gromemu_cartridge(): m_waddr_LSB(false), m_grom_selected(false), m_grom_read_mode(false), m_grom_address_mode(false)
{ m_grom_address = 0; }
- DECLARE_READ8Z_MEMBER(readz) override;
+ void readz(offs_t offset, uint8_t *value) override;
void write(offs_t offset, uint8_t data) override;
- DECLARE_READ8Z_MEMBER(gromemureadz);
+ void gromemureadz(offs_t offset, uint8_t *value);
void gromemuwrite(offs_t offset, uint8_t data);
void set_gromlines(line_state mline, line_state moline, line_state gsq) override;
@@ -372,7 +305,8 @@ private:
bool m_grom_read_mode;
bool m_grom_address_mode;
};
-} } } // end namespace bus::ti99::gromport
+
+} // end namespace bus::ti99::gromport
DECLARE_DEVICE_TYPE_NS(TI99_CART, bus::ti99::gromport, ti99_cartridge_device)
diff --git a/src/devices/bus/ti99/gromport/gkracker.cpp b/src/devices/bus/ti99/gromport/gkracker.cpp
index 7010b1f34ec..3e2fc34e6c6 100644
--- a/src/devices/bus/ti99/gromport/gkracker.cpp
+++ b/src/devices/bus/ti99/gromport/gkracker.cpp
@@ -97,16 +97,16 @@
#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_NS(TI99_GROMPORT_GK, bus::ti99::gromport, ti99_gkracker_device, "ti99_gkracker", "Miller's Graphics GRAM Kracker")
+DEFINE_DEVICE_TYPE(TI99_GROMPORT_GK, bus::ti99::gromport::ti99_gkracker_device, "ti99_gkracker", "Miller's Graphics GRAM Kracker")
-namespace bus { namespace ti99 { namespace gromport {
+namespace bus::ti99::gromport {
enum
{
@@ -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,10 +171,10 @@ 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();
}
-READ8Z_MEMBER(ti99_gkracker_device::readz)
+void ti99_gkracker_device::readz(offs_t offset, uint8_t *value)
{
if (m_grom_selected)
{
@@ -221,25 +221,19 @@ READ8Z_MEMBER(ti99_gkracker_device::readz)
}
// 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)
{
@@ -305,14 +299,14 @@ void ti99_gkracker_device::write(offs_t offset, uint8_t data)
}
}
-READ8Z_MEMBER( ti99_gkracker_device::crureadz )
+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;
@@ -376,28 +355,33 @@ void ti99_gkracker_device::nvram_default()
m_ram_ptr[0x6100] = 0x0b; // GPL EXIT
}
-void ti99_gkracker_device::nvram_read(emu_file &file)
+bool ti99_gkracker_device::nvram_read(util::read_stream &file)
{
- int readsize = file.read(m_ram_ptr, 81920);
+ 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
if (readsize < 81920)
{
memset(m_ram_ptr + readsize, 0, 81920-readsize);
}
+ return true;
}
-void ti99_gkracker_device::nvram_write(emu_file &file)
+bool ti99_gkracker_device::nvram_write(util::write_stream &file)
{
LOGMASKED(LOG_GKRACKER, "Writing NVRAM\n");
- file.write(m_ram_ptr, 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));
@@ -435,33 +419,33 @@ 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)
PORT_START( GKSWITCH1_TAG )
- PORT_DIPNAME( 0x01, 0x01, "GK switch 1" ) PORT_CHANGED_MEMBER(DEVICE_SELF, ti99_gkracker_device, gk_changed, 1)
+ PORT_DIPNAME( 0x01, 0x01, "GK switch 1" ) PORT_CHANGED_MEMBER(DEVICE_SELF, FUNC(ti99_gkracker_device::gk_changed), 1)
PORT_DIPSETTING( 0x00, "GK Off" )
PORT_DIPSETTING( 0x01, DEF_STR( Normal ) )
PORT_START( GKSWITCH2_TAG )
- PORT_DIPNAME( 0x01, 0x01, "GK switch 2" ) PORT_CHANGED_MEMBER(DEVICE_SELF, ti99_gkracker_device, gk_changed, 2)
+ PORT_DIPNAME( 0x01, 0x01, "GK switch 2" ) PORT_CHANGED_MEMBER(DEVICE_SELF, FUNC(ti99_gkracker_device::gk_changed), 2)
PORT_DIPSETTING( 0x00, "GRAM 0" )
PORT_DIPSETTING( 0x01, "Op Sys" )
PORT_START( GKSWITCH3_TAG )
- PORT_DIPNAME( 0x01, 0x01, "GK switch 3" ) PORT_CHANGED_MEMBER(DEVICE_SELF, ti99_gkracker_device, gk_changed, 3)
+ PORT_DIPNAME( 0x01, 0x01, "GK switch 3" ) PORT_CHANGED_MEMBER(DEVICE_SELF, FUNC(ti99_gkracker_device::gk_changed), 3)
PORT_DIPSETTING( 0x00, "GRAM 1-2" )
PORT_DIPSETTING( 0x01, "TI BASIC" )
PORT_START( GKSWITCH4_TAG )
- PORT_DIPNAME( 0x03, 0x01, "GK switch 4" ) PORT_CHANGED_MEMBER(DEVICE_SELF, ti99_gkracker_device, gk_changed, 4)
+ PORT_DIPNAME( 0x03, 0x01, "GK switch 4" ) PORT_CHANGED_MEMBER(DEVICE_SELF, FUNC(ti99_gkracker_device::gk_changed), 4)
PORT_DIPSETTING( 0x00, "Bank 1" )
PORT_DIPSETTING( 0x01, "W/P" )
PORT_DIPSETTING( 0x02, "Bank 2" )
PORT_START( GKSWITCH5_TAG )
- PORT_DIPNAME( 0x01, 0x00, "GK switch 5" ) PORT_CHANGED_MEMBER(DEVICE_SELF, ti99_gkracker_device, gk_changed, 5)
+ PORT_DIPNAME( 0x01, 0x00, "GK switch 5" ) PORT_CHANGED_MEMBER(DEVICE_SELF, FUNC(ti99_gkracker_device::gk_changed), 5)
PORT_DIPSETTING( 0x00, "Loader On" )
PORT_DIPSETTING( 0x01, "Loader Off" )
INPUT_PORTS_END
@@ -470,5 +454,6 @@ ioport_constructor ti99_gkracker_device::device_input_ports() const
{
return INPUT_PORTS_NAME(gkracker);
}
-} } } // end namespace bus::ti99::gromport
+
+} // end namespace bus::ti99::gromport
diff --git a/src/devices/bus/ti99/gromport/gkracker.h b/src/devices/bus/ti99/gromport/gkracker.h
index 34b267bf640..0d2f272a43a 100644
--- a/src/devices/bus/ti99/gromport/gkracker.h
+++ b/src/devices/bus/ti99/gromport/gkracker.h
@@ -8,44 +8,41 @@
#define MAME_BUS_TI99_GROMPORT_GKRACKER_H
#pragma once
-#include "bus/ti99/ti99defs.h"
#include "cartridges.h"
-namespace bus { namespace ti99 { namespace gromport {
+namespace bus::ti99::gromport {
class ti99_gkracker_device : public cartridge_connector_device, public device_nvram_interface
{
public:
ti99_gkracker_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
- DECLARE_READ8Z_MEMBER(readz) override;
+ void readz(offs_t offset, uint8_t *value) override;
void write(offs_t offset, uint8_t data) override;
- DECLARE_READ8Z_MEMBER(crureadz) 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
bool is_grom_idle() override;
protected:
- virtual void device_start() override;
- virtual void device_reset() override;
+ virtual void device_start() override ATTR_COLD;
+ virtual void device_reset() override ATTR_COLD;
- virtual void device_add_mconfig(machine_config &config) override;
+ virtual void device_add_mconfig(machine_config &config) override ATTR_COLD;
virtual const tiny_rom_entry* device_rom_region() const override;
- virtual ioport_constructor device_input_ports() const override;
+ virtual ioport_constructor device_input_ports() const override ATTR_COLD;
// device_nvram_interface
- void nvram_default() override;
- void nvram_read(emu_file &file) override;
- void nvram_write(emu_file &file) override;
+ virtual void nvram_default() override;
+ virtual bool nvram_read(util::read_stream &file) override;
+ virtual bool nvram_write(util::write_stream &file) override;
private:
int m_gk_switch[6]; // Used to cache the switch settings.
@@ -58,14 +55,14 @@ 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);
};
-} } } // end namespace bus::ti99::gromport
+} // end namespace bus::ti99::gromport
DECLARE_DEVICE_TYPE_NS(TI99_GROMPORT_GK, bus::ti99::gromport, ti99_gkracker_device)
diff --git a/src/devices/bus/ti99/gromport/gromport.cpp b/src/devices/bus/ti99/gromport/gromport.cpp
index 5f893aa4423..6204c9b5af1 100644
--- a/src/devices/bus/ti99/gromport/gromport.cpp
+++ b/src/devices/bus/ti99/gromport/gromport.cpp
@@ -114,20 +114,20 @@
#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_NS(TI99_GROMPORT, bus::ti99::gromport, gromport_device, "gromport", "TI-99 Cartridge port")
+DEFINE_DEVICE_TYPE(TI99_GROMPORT, bus::ti99::gromport::gromport_device, "gromport", "TI-99 Cartridge port")
-namespace bus { namespace ti99 { namespace gromport {
+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),
@@ -139,7 +139,7 @@ gromport_device::gromport_device(const machine_config &mconfig, const char *tag,
Reading via the GROM port. Only 13 address lines are passed through
on the TI-99/4A, and 14 lines on the TI-99/8.
*/
-READ8Z_MEMBER(gromport_device::readz)
+void gromport_device::readz(offs_t offset, uint8_t *value)
{
if (m_connector != nullptr)
{
@@ -161,7 +161,7 @@ void gromport_device::write(offs_t offset, uint8_t data)
}
}
-READ8Z_MEMBER(gromport_device::crureadz)
+void gromport_device::crureadz(offs_t offset, uint8_t *value)
{
if (m_connector != nullptr)
m_connector->crureadz(offset, value);
@@ -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,17 +277,12 @@ 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
+} // 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 9c04ef5a8b8..f70dfaddc78 100644
--- a/src/devices/bus/ti99/gromport/gromport.h
+++ b/src/devices/bus/ti99/gromport/gromport.h
@@ -12,9 +12,9 @@
#pragma once
-#include "bus/ti99/ti99defs.h"
+#define TI99_GROMPORT_TAG "gromport"
-namespace bus { namespace ti99 { namespace gromport {
+namespace bus::ti99::gromport {
struct pcb_type
{
@@ -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>
@@ -40,14 +40,14 @@ public:
gromport_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
- DECLARE_READ8Z_MEMBER(readz);
+ void readz(offs_t offset, uint8_t *value);
void write(offs_t offset, uint8_t data);
- DECLARE_READ8Z_MEMBER(crureadz);
+ 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 ATTR_COLD;
+ virtual void device_reset() override ATTR_COLD;
+ virtual void device_config_complete() override;
+ virtual ioport_constructor device_input_ports() const override ATTR_COLD;
private:
cartridge_connector_device* m_connector;
@@ -75,34 +75,37 @@ private:
class cartridge_connector_device : public device_t
{
+ friend class gromport_device;
+
public:
- virtual DECLARE_READ8Z_MEMBER(readz) = 0;
+ virtual void readz(offs_t offset, uint8_t *value) = 0;
virtual void write(offs_t offset, uint8_t data) = 0;
- virtual DECLARE_SETADDRESS_DBIN_MEMBER( setaddress_dbin ) { }
+ virtual void setaddress_dbin(offs_t offset, int state) { }
- virtual DECLARE_READ8Z_MEMBER(crureadz) = 0;
+ 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
+} // end namespace bus::ti99::gromport
DECLARE_DEVICE_TYPE_NS(TI99_GROMPORT, bus::ti99::gromport, gromport_device)
diff --git a/src/devices/bus/ti99/gromport/multiconn.cpp b/src/devices/bus/ti99/gromport/multiconn.cpp
index ad7e3e2311f..314422be705 100644
--- a/src/devices/bus/ti99/gromport/multiconn.cpp
+++ b/src/devices/bus/ti99/gromport/multiconn.cpp
@@ -43,15 +43,15 @@
#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"
-DEFINE_DEVICE_TYPE_NS(TI99_GROMPORT_MULTI, bus::ti99::gromport, ti99_multi_cart_conn_device, "ti99_mcartconn", "TI-99 Multi-cartridge extender")
+DEFINE_DEVICE_TYPE(TI99_GROMPORT_MULTI, bus::ti99::gromport::ti99_multi_cart_conn_device, "ti99_mcartconn", "TI-99 Multi-cartridge extender")
-namespace bus { namespace ti99 { namespace gromport {
+namespace bus::ti99::gromport {
#define AUTO -1
@@ -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,29 +142,17 @@ 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);
}
-READ8Z_MEMBER(ti99_multi_cart_conn_device::readz)
+void ti99_multi_cart_conn_device::readz(offs_t offset, uint8_t *value)
{
int slot = get_active_slot(true, offset);
@@ -192,23 +163,16 @@ READ8Z_MEMBER(ti99_multi_cart_conn_device::readz)
{
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);
}
}
-READ8Z_MEMBER(ti99_multi_cart_conn_device::crureadz)
+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 )
@@ -317,7 +258,7 @@ INPUT_CHANGED_MEMBER( ti99_multi_cart_conn_device::switch_changed )
INPUT_PORTS_START(multi_slot)
PORT_START( "CARTSLOT" )
- PORT_DIPNAME( 0x0f, 0x00, "Multi-cartridge slot" ) PORT_CHANGED_MEMBER(DEVICE_SELF, ti99_multi_cart_conn_device, switch_changed, 0)
+ PORT_DIPNAME( 0x0f, 0x00, "Multi-cartridge slot" ) PORT_CHANGED_MEMBER(DEVICE_SELF, FUNC(ti99_multi_cart_conn_device::switch_changed), 0)
PORT_DIPSETTING( 0x00, "Auto" )
PORT_DIPSETTING( 0x01, "Slot 1" )
PORT_DIPSETTING( 0x02, "Slot 2" )
@@ -330,5 +271,5 @@ ioport_constructor ti99_multi_cart_conn_device::device_input_ports() const
return INPUT_PORTS_NAME(multi_slot);
}
-} } } // end namespace bus::ti99::gromport
+} // end namespace bus::ti99::gromport
diff --git a/src/devices/bus/ti99/gromport/multiconn.h b/src/devices/bus/ti99/gromport/multiconn.h
index 56a5915cfb2..bfa69936bb7 100644
--- a/src/devices/bus/ti99/gromport/multiconn.h
+++ b/src/devices/bus/ti99/gromport/multiconn.h
@@ -13,50 +13,47 @@
#define MAME_BUS_TI99_GROMPORT_MULTICONN_H
#pragma once
-#include "bus/ti99/ti99defs.h"
#include "cartridges.h"
-namespace bus { namespace ti99 { namespace gromport {
+namespace bus::ti99::gromport {
class ti99_multi_cart_conn_device : public cartridge_connector_device
{
public:
ti99_multi_cart_conn_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
- DECLARE_READ8Z_MEMBER(readz) override;
+ void readz(offs_t offset, uint8_t *value) override;
void write(offs_t offset, uint8_t data) override;
- DECLARE_READ8Z_MEMBER(crureadz) 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;
+ 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;
+ virtual ioport_constructor device_input_ports() const override ATTR_COLD;
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);
};
-} } } // end namespace bus::ti99::gromport
+} // end namespace bus::ti99::gromport
DECLARE_DEVICE_TYPE_NS(TI99_GROMPORT_MULTI, bus::ti99::gromport, ti99_multi_cart_conn_device)
diff --git a/src/devices/bus/ti99/gromport/singleconn.cpp b/src/devices/bus/ti99/gromport/singleconn.cpp
index 9a0b905a9e7..d5b1b8a897e 100644
--- a/src/devices/bus/ti99/gromport/singleconn.cpp
+++ b/src/devices/bus/ti99/gromport/singleconn.cpp
@@ -9,17 +9,17 @@
#include "emu.h"
#include "singleconn.h"
-DEFINE_DEVICE_TYPE_NS(TI99_GROMPORT_SINGLE, bus::ti99::gromport, ti99_single_cart_conn_device, "ti99_scartconn", "TI-99 Standard cartridge connector")
+DEFINE_DEVICE_TYPE(TI99_GROMPORT_SINGLE, bus::ti99::gromport::ti99_single_cart_conn_device, "ti99_scartconn", "TI-99 Standard cartridge connector")
-namespace bus { namespace ti99 { namespace gromport {
+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")
{
}
-READ8Z_MEMBER(ti99_single_cart_conn_device::readz)
+void ti99_single_cart_conn_device::readz(offs_t offset, uint8_t *value)
{
// Pass through
m_cartridge->readz(offset, value);
@@ -31,7 +31,7 @@ void ti99_single_cart_conn_device::write(offs_t offset, uint8_t data)
m_cartridge->write(offset, data);
}
-READ8Z_MEMBER(ti99_single_cart_conn_device::crureadz)
+void ti99_single_cart_conn_device::crureadz(offs_t offset, uint8_t *value)
{
// Pass through
m_cartridge->crureadz(offset, value);
@@ -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,20 +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
-
+} // end namespace bus::ti99::gromport
diff --git a/src/devices/bus/ti99/gromport/singleconn.h b/src/devices/bus/ti99/gromport/singleconn.h
index 831d70ffb18..44db36d070a 100644
--- a/src/devices/bus/ti99/gromport/singleconn.h
+++ b/src/devices/bus/ti99/gromport/singleconn.h
@@ -9,35 +9,34 @@
#pragma once
-#include "bus/ti99/ti99defs.h"
#include "cartridges.h"
-namespace bus { namespace ti99 { namespace gromport {
+namespace bus::ti99::gromport {
class ti99_single_cart_conn_device : public cartridge_connector_device
{
public:
ti99_single_cart_conn_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
- DECLARE_READ8Z_MEMBER(readz) override;
+ void readz(offs_t offset, uint8_t *value) override;
void write(offs_t offset, uint8_t data) override;
- DECLARE_READ8Z_MEMBER(crureadz) 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_add_mconfig(machine_config &config) override;
+ virtual void device_start() override { };
+ virtual void device_add_mconfig(machine_config &config) override ATTR_COLD;
private:
- ti99_cartridge_device *m_cartridge;
+ required_device<ti99_cartridge_device> m_cartridge;
};
-} } } // end namespace bus::ti99::gromport
+
+} // end namespace bus::ti99::gromport
DECLARE_DEVICE_TYPE_NS(TI99_GROMPORT_SINGLE, bus::ti99::gromport, ti99_single_cart_conn_device)
diff --git a/src/devices/bus/ti99/internal/992board.cpp b/src/devices/bus/ti99/internal/992board.cpp
index 071526016f2..23274d08291 100644
--- a/src/devices/bus/ti99/internal/992board.cpp
+++ b/src/devices/bus/ti99/internal/992board.cpp
@@ -7,23 +7,29 @@
This component implements the custom video controller and interface chip
from the TI-99/2 console.
+ Also, we emulate the expansion port at the backside of the console; there
+ are no known expansions except for a RAM expansion that is mentioned
+ in the specifications.
+
May 2018
+ June 2020
***************************************************************************/
#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_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_WARN )
+#define VERBOSE (LOG_GENERAL | LOG_WARN)
#include "logmacro.h"
-#include "992board.h"
/*
Emulation of the CRT Gate Array of the TI-99/2
@@ -123,21 +129,23 @@
[2] VDC Controller CF40052
*/
-DEFINE_DEVICE_TYPE_NS(VIDEO99224, bus::ti99::internal, video992_24_device, "video992_24", "TI-99/2 CRT Controller 24K version")
-DEFINE_DEVICE_TYPE_NS(VIDEO99232, bus::ti99::internal, video992_32_device, "video992_32", "TI-99/2 CRT Controller 32K version")
-DEFINE_DEVICE_TYPE_NS(IO99224, bus::ti99::internal, io992_24_device, "io992_24", "TI-99/2 I/O controller 24K version")
-DEFINE_DEVICE_TYPE_NS(IO99232, bus::ti99::internal, io992_32_device, "io992_32", "TI-99/2 I/O controller 32K version")
+DEFINE_DEVICE_TYPE(VIDEO99224, bus::ti99::internal::video992_24_device, "video992_24", "TI-99/2 CRT Controller 24K version")
+DEFINE_DEVICE_TYPE(VIDEO99232, bus::ti99::internal::video992_32_device, "video992_32", "TI-99/2 CRT Controller 32K version")
+DEFINE_DEVICE_TYPE(IO99224, bus::ti99::internal::io992_24_device, "io992_24", "TI-99/2 I/O controller 24K version")
+DEFINE_DEVICE_TYPE(IO99232, bus::ti99::internal::io992_32_device, "io992_32", "TI-99/2 I/O controller 32K version")
+DEFINE_DEVICE_TYPE(TI992_EXPPORT, bus::ti99::internal::ti992_expport_device, "ti992_expport", "TI-99/2 Expansion Port")
+DEFINE_DEVICE_TYPE(TI992_RAM32K, bus::ti99::internal::ti992_expram_device, "ti992_ram32k", "TI-99/2 RAM Expansion 32K")
-namespace bus { namespace ti99 { namespace internal {
+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)
{
}
@@ -153,34 +161,21 @@ video992_32_device::video992_32_device(const machine_config &mconfig, const char
m_beol = 0x7f;
}
-std::string video992_device::tts(attotime t)
+TIMER_CALLBACK_MEMBER(video992_device::hold_cpu)
{
- 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;
-}
+ int raw_vpos = screen().vpos();
+ 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));
+}
-void video992_device::device_timer(emu_timer &timer, device_timer_id id, int param, void *ptr)
+TIMER_CALLBACK_MEMBER(video992_device::free_cpu)
{
int raw_vpos = screen().vpos();
- if (id == HOLD_TIME)
- {
- // logerror("release time: %s, diff: %s\n", tts(machine().time()), tts(machine().time()-m_hold_time));
- // 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));
- return;
- }
-
- // logerror("hold time: %s\n", tts(machine().time()));
+ LOG("hold time: %s\n", machine().time().to_string());
if (m_videna)
{
// Hold the CPU
@@ -194,31 +189,31 @@ void video992_device::device_timer(emu_timer &timer, device_timer_id id, int par
}
int vpos = raw_vpos * m_vertical_size / screen().height();
- uint32_t *p = &m_tmpbmp.pix32(vpos);
+ uint32_t *p = &m_tmpbmp.pix(vpos);
bool endofline = false;
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 = ((control & 0x04)!=0);
- bool border_white = ((control & 0x02)!=0);
- bool background_white = ((control & 0x01)!=0)? text_white : !text_white;
+ bool text_white = BIT(control, 2);
+ bool border_white = BIT(control, 1);
+ bool background_white = BIT(control, 0) ? text_white : !text_white;
int y = vpos - m_top_border;
if (y < 0 || y >= 192)
{
// Draw border colour
for (int i = 0; i < TOTAL_HORZ; i++)
- p[i] = border_white? rgb_t::white() : rgb_t::black();
+ p[i] = border_white ? rgb_t::white() : rgb_t::black();
// vblank is set at the last cycle of the first inactive line
// not confirmed by the specs, just doing like 9928A.
- if ( y == 193 )
+ if (y == 193)
{
- m_int_cb( ASSERT_LINE );
- m_int_cb( CLEAR_LINE );
+ m_int_cb(ASSERT_LINE);
+ m_int_cb(CLEAR_LINE);
}
}
else
@@ -226,12 +221,12 @@ void video992_device::device_timer(emu_timer &timer, device_timer_id id, int par
// Draw regular line
// Left border
for (int i = 0; i < HORZ_DISPLAY_START; i++)
- p[i] = border_white? rgb_t::white() : rgb_t::black();
+ p[i] = border_white ? rgb_t::white() : rgb_t::black();
int addr = ((y << 2) & 0x3e0) | 0xec00;
// Active display
- for (int x = HORZ_DISPLAY_START; x<HORZ_DISPLAY_START+256; x+=8)
+ for (int x = HORZ_DISPLAY_START; x < HORZ_DISPLAY_START + 256; x+=8)
{
uint8_t charcode = 0;
uint8_t pattern = 0;
@@ -247,16 +242,16 @@ void video992_device::device_timer(emu_timer &timer, device_timer_id id, int par
if (!endofline && m_videna)
{
// Get the pattern
- int addrp = 0x1c00 | (charcode << 3) | (y%8);
+ int addrp = 0x1c00 | (charcode << 3) | (y & 7);
pattern = m_mem_read_cb(addrp);
linelength++;
}
for (int i = 0; i < 8; i++)
{
- if ((pattern & 0x80)!=0)
- p[x+i] = text_white? rgb_t::white() : rgb_t::black();
+ if (BIT(pattern, 7))
+ p[x+i] = text_white ? rgb_t::white() : rgb_t::black();
else
- p[x+i] = background_white? rgb_t::white() : rgb_t::black();
+ p[x+i] = background_white ? rgb_t::white() : rgb_t::black();
pattern <<= 1;
}
@@ -265,27 +260,27 @@ void video992_device::device_timer(emu_timer &timer, device_timer_id id, int par
// Right border
for (int i = HORZ_DISPLAY_START + 256; i < TOTAL_HORZ; i++)
- p[i] = border_white? rgb_t::white() : rgb_t::black();
+ p[i] = border_white ? rgb_t::white() : rgb_t::black();
}
// +1 for the minimum hold time
- // logerror("line length: %d\n", linelength);
- m_hold_timer->adjust(screen().time_until_pos(raw_vpos, HORZ_DISPLAY_START + linelength*8 + 1));
+ LOG("line length: %d\n", linelength);
+ m_hold_timer->adjust(screen().time_until_pos(raw_vpos, HORZ_DISPLAY_START + linelength * 8 + 1));
}
-uint32_t video992_device::screen_update( screen_device &screen, bitmap_rgb32 &bitmap, const rectangle &cliprect )
+uint32_t video992_device::screen_update(screen_device &screen, bitmap_rgb32 &bitmap, const rectangle &cliprect)
{
- copybitmap( bitmap, m_tmpbmp, 0, 0, 0, 0, cliprect );
+ copybitmap(bitmap, m_tmpbmp, 0, 0, 0, 0, cliprect);
return 0;
}
/*
VIDENA pin, positive logic
*/
-WRITE_LINE_MEMBER( video992_device::videna )
+void video992_device::videna(int state)
{
- m_videna = (state==ASSERT_LINE);
+ m_videna = state;
}
void video992_device::device_start()
@@ -294,16 +289,12 @@ void video992_device::device_start()
m_vertical_size = TOTAL_VERT_NTSC;
m_tmpbmp.allocate(TOTAL_HORZ, TOTAL_VERT_NTSC);
- m_hold_timer = timer_alloc(HOLD_TIME);
- m_free_timer = timer_alloc(FREE_TIME);
+ m_hold_timer = timer_alloc(FUNC(video992_device::hold_cpu), this);
+ m_free_timer = timer_alloc(FUNC(video992_device::free_cpu), this);
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()
@@ -348,16 +339,13 @@ void video992_device::device_reset()
io992_device::io992_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock)
: bus::hexbus::hexbus_chained_device(mconfig, type, tag, owner, clock),
- m_hexbus(*this, "^" TI_HEXBUS_TAG),
- m_cassette(*this, "^" TI_CASSETTE),
- m_videoctrl(*this, "^" TI992_VDC_TAG),
+ m_hexbus(*owner, TI992_HEXBUS_TAG),
+ m_cassette(*owner, TI992_CASSETTE),
+ m_videoctrl(*owner, TI992_VDC_TAG),
m_keyboard(*this, "LINE%u", 0U),
m_set_rom_bank(*this),
m_key_row(0),
- m_latch_out(0xd7),
- m_latch_in(0xd7),
- m_communication_disable(true),
- m_response_phase(false)
+ m_hsk_released(true)
{
}
@@ -452,59 +440,55 @@ 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)
{
- int address = offset << 1;
- uint8_t value = 0x7f; // All Hexbus lines high
+ offs_t address = offset << 1;
double inp = 0;
- int i;
- uint8_t bit = 1;
- switch (address & 0xf800)
+ // CRU E000-E7fE: Keyboard
+ // Read: 1110 0*** **** xxx0 (mirror 07f0)
+ if ((address & 0xf800) == 0xe000)
+ return BIT(m_keyboard[m_key_row]->read(), offset & 7);
+
+ // CRU E800-EFFE: Hexbus and other functions
+ // Read: 1110 1*** **** xxx0 (mirror 007f0)
+ switch (address & 0xf80e)
{
- case 0xe000:
- // CRU E000-E7fE: Keyboard
- // Read: 0000 1110 0*** **** (mirror 007f)
- value = m_keyboard[m_key_row]->read();
- break;
+ // Hexbus
case 0xe800:
- // CRU E800-EFFE: Hexbus and other functions
- // Read: 0000 1110 1*** **** (mirror 007f)
- for (i=0; i < 6; i++)
- {
- if ((m_latch_in & m_hexbval[i])==0) value &= ~bit;
- bit <<= 1;
- }
- // e80c (bit 6) seems to be a latch for the response phase
- if (!m_response_phase)
- value &= ~0x40;
+ case 0xe802:
+ case 0xe804:
+ case 0xe806:
+ return data_bit(offset & 3);
+ case 0xe808:
+ return (bus_hsk_level() == ASSERT_LINE) ? 0 : 1;
+ case 0xe80a:
+ return (bus_bav_level() == ASSERT_LINE) ? 0 : 1;
+
+ case 0xe80c:
+ // e80c (bit 6) seems to indicate that the HSK* line has been released
+ // and is now asserted again
+ return (m_hsk_released && (bus_hsk_level() == ASSERT_LINE)) ? 1 : 0;
+ case 0xe80e:
inp = m_cassette->input();
- if (inp > 0)
- value |= 0x80;
LOGMASKED(LOG_CASSETTE, "value=%f\n", inp);
- break;
+ return (inp > 0) ? 1 : 0;
+
default:
- LOGMASKED(LOG_CRU, "Unknown access to %04x\n", address);
+ LOGMASKED(LOG_CRU, "Invalid CRU access to %04x\n", address);
}
-
- LOGMASKED(LOG_CRU, "CRU %04x -> %02x\n", address, value);
-
- return BIT(value, offset & 7);
+ return 0;
}
void io992_device::cruwrite(offs_t offset, uint8_t data)
{
- int address = (offset << 1) & 0xf80e;
+ offs_t address = (offset << 1) & 0xf80e;
LOGMASKED(LOG_CRU, "CRU %04x <- %1x\n", address, data);
- uint8_t olddata = m_latch_out;
-
switch (address)
{
// Select the current keyboard row. Also, bit 0 is used to switch the
@@ -516,15 +500,15 @@ void io992_device::cruwrite(offs_t offset, uint8_t data)
if (m_have_banked_rom)
{
LOGMASKED(LOG_BANK, "set bank = %d\n", data);
- m_set_rom_bank(data==1);
+ m_set_rom_bank(data == 1);
}
- // no break
+ [[fallthrough]];
case 0xe002:
case 0xe004:
case 0xe006:
case 0xe008:
case 0xe00a:
- if (data == 0) m_key_row = offset&7;
+ if (data == 0) m_key_row = offset & 7;
break;
case 0xe00c:
LOGMASKED(LOG_WARN, "Unmapped CRU write to address e00c\n");
@@ -539,50 +523,26 @@ void io992_device::cruwrite(offs_t offset, uint8_t data)
case 0xe802: // ID1
case 0xe804: // ID2
case 0xe806: // ID3
- if (data != 0) m_latch_out |= m_hexbval[offset & 0x07];
- else m_latch_out &= ~m_hexbval[offset & 0x07];
- LOGMASKED(LOG_HEXBUS, "Hexbus latch out = %02x\n", m_latch_out);
+ set_data_latch(data, offset & 0x03);
break;
+
case 0xe80a: // BAV
- // Undocumented, but makes sense according to the ROM
- if (data==0)
- m_response_phase = false;
- // no break
- case 0xe808: // HSK
- if (data != 0) m_latch_out |= m_hexbval[offset & 0x07];
- else m_latch_out &= ~m_hexbval[offset & 0x07];
+ set_bav_line(data != 0 ? CLEAR_LINE : ASSERT_LINE);
+ break;
- if (m_latch_out != olddata)
- {
- LOGMASKED(LOG_HEXBUS, "%s %s\n", (address==0xe808)? "HSK*" : "BAV*", (data==0)? "assert" : "clear");
- if (m_communication_disable)
- {
- // This is not explicitly stated in the specs, but since they
- // also claim that communication is disabled on power-up,
- // we must turn it on here; the ROM fails to do it.
- LOGMASKED(LOG_HEXBUS, "Enabling Hexbus\n");
- m_communication_disable = false;
- }
- LOGMASKED(LOG_HEXBUS, "Writing to Hexbus: BAV*=%d, HSK*=%d, DATA=%01x\n", (m_latch_out&0x04)!=0, (m_latch_out&0x10)!=0, ((m_latch_out>>4)&0x0c)|(m_latch_out&0x03));
- hexbus_write(m_latch_out);
- // Check how the bus has changed. This depends on the states of all
- // connected peripherals
- m_latch_in = hexbus_read();
- }
+ case 0xe808: // HSK
+ set_hsk_line(data != 0 ? CLEAR_LINE : ASSERT_LINE);
+ m_hsk_released = (bus_hsk_level() == CLEAR_LINE);
break;
+
case 0xe80c:
- LOGMASKED(LOG_HEXBUS, "Hexbus inhibit = %d\n", data);
- if (data == 1)
- {
- m_latch_in = 0xd7;
- m_communication_disable = true;
- }
- else m_communication_disable = false;
+ set_communication_enabled(data == 0);
break;
+
case 0xe80e:
LOGMASKED(LOG_CRU, "Cassette output = %d\n", data);
// Tape output. See also ti99_4x.cpp.
- m_cassette->output((data==1)? +1 : -1);
+ m_cassette->output((data == 1) ? +1 : -1);
break;
}
}
@@ -601,29 +561,23 @@ void io992_device::hexbus_value_changed(uint8_t data)
{
// Only latch the incoming data when BAV* is asserted and the Hexbus
// is not inhibited
- bool bav_asserted = ((m_latch_out & bus::hexbus::HEXBUS_LINE_BAV)==0);
- if (!m_communication_disable && bav_asserted)
+ if (own_bav_level() == ASSERT_LINE)
{
- LOGMASKED(LOG_HEXBUS, "Hexbus changed and latched: %02x\n", data);
- m_latch_in = data;
-
- if ((data & bus::hexbus::HEXBUS_LINE_HSK)==0)
+ if (bus_hsk_level() == ASSERT_LINE)
{
- // If HSK* is lowered and we as the host have it up, this indicates
- // the response phase.
- if (!m_response_phase && (m_myvalue & bus::hexbus::HEXBUS_LINE_HSK)!=0)
- {
- LOGMASKED(LOG_HEXBUS, "Incoming response\n");
- m_response_phase = true;
- }
- // We cannot wait for the CPU explicitly latching HSK*
- // as designed, because this implies a true parallel execution
- LOGMASKED(LOG_HEXBUS, "Latching HSK*\n");
- m_myvalue &= ~bus::hexbus::HEXBUS_LINE_HSK;
+ // According to the Hexbus spec, the incoming HSK must be latched
+ // by hardware
+ LOGMASKED(LOG_HEXBUS, "Latching HSK*; got data %01x\n", (data >> 4) | (data & 3));
+ latch_hsk();
+ }
+ else
+ {
+ LOGMASKED(LOG_HEXBUS, "HSK* released\n");
+ m_hsk_released = true;
}
}
else
- LOGMASKED(LOG_HEXBUS, "Ignoring Hexbus change (to %02x), latch=%s, BAV*=%d\n", data, m_communication_disable? "inhibit":"enabled", bav_asserted? 0:1);
+ LOGMASKED(LOG_HEXBUS, "Ignoring Hexbus change (to %02x), BAV*=%d\n", data, (own_bav_level() == ASSERT_LINE) ? 0 : 1);
}
ioport_constructor io992_device::device_input_ports() const
@@ -631,6 +585,82 @@ ioport_constructor io992_device::device_input_ports() const
return INPUT_PORTS_NAME( keys992 );
}
-} } }
+/********************************************************************
+ Expansion port
+********************************************************************/
+
+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_single_card_slot_interface<ti992_expport_attached_device>(mconfig, *this),
+ m_connected(nullptr)
+{
+}
+
+void ti992_expport_device::readz(offs_t offset, uint8_t *value)
+{
+ if (m_connected != nullptr)
+ m_connected->readz(offset, value);
+}
+
+void ti992_expport_device::write(offs_t offset, uint8_t data)
+{
+ if (m_connected != nullptr)
+ m_connected->write(offset, data);
+}
+
+void ti992_expport_device::device_config_complete()
+{
+ m_connected = get_card_device();
+}
+
+/*
+ 32K Expansion cartridge
+ Maps at 6000 - DFFF
+ This is the only known expansion device
+*/
+ti992_expram_device::ti992_expram_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) :
+ ti992_expport_attached_device(mconfig, TI992_RAM32K, tag, owner, clock),
+ m_ram(*this, "ram32k")
+{
+}
+
+void ti992_expram_device::readz(offs_t offset, uint8_t *value)
+{
+ // 000 -> 100 100 -> 000
+ // 001 -> 101 101 -> 001
+ // 010 -> 110 110 -> 010
+ // 011 -> 011 111 -> 111
+ offs_t address = offset;
+ if ((offset & 0x6000) != 0x6000) address ^= 0x8000;
+ if ((address & 0x8000) == 0)
+ {
+ *value = m_ram->read(address);
+ LOGMASKED(LOG_EXPRAM, "expram %04x -> %02x\n", offset, *value);
+ }
+}
+void ti992_expram_device::write(offs_t offset, uint8_t value)
+{
+ offs_t address = offset;
+ if ((offset & 0x6000) != 0x6000) address ^= 0x8000;
+ if ((address & 0x8000) == 0)
+ {
+ m_ram->write(address, value);
+ LOGMASKED(LOG_EXPRAM, "expram %04x <- %02x\n", offset, value);
+ }
+}
+
+void ti992_expram_device::device_add_mconfig(machine_config &config)
+{
+ RAM(config, m_ram, 0);
+ m_ram->set_default_size("32k");
+ m_ram->set_default_value(0);
+}
+
+} // namespace bus::ti99::internal
+
+void ti992_expport_options(device_slot_interface &device)
+{
+ device.option_add("ram32k", TI992_RAM32K);
+}
diff --git a/src/devices/bus/ti99/internal/992board.h b/src/devices/bus/ti99/internal/992board.h
index dff4f570d79..ca2aef61768 100644
--- a/src/devices/bus/ti99/internal/992board.h
+++ b/src/devices/bus/ti99/internal/992board.h
@@ -19,11 +19,15 @@
#pragma once
#include "screen.h"
-#include "bus/ti99/ti99defs.h"
#include "bus/hexbus/hexbus.h"
#include "imagedev/cassette.h"
+#include "machine/ram.h"
-namespace bus { namespace ti99 { namespace internal {
+#define TI992_CASSETTE "cassette"
+#define TI992_VDC_TAG "vdc"
+#define TI992_HEXBUS_TAG "hexbus"
+
+namespace bus::ti99::internal {
class video992_device : public device_t,
public device_video_interface
@@ -42,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(); }
@@ -53,14 +57,13 @@ protected:
video992_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock);
int m_beol;
-private:
- static const device_timer_id HOLD_TIME = 0;
- static const device_timer_id FREE_TIME = 1;
+ virtual void device_start() override ATTR_COLD;
+ virtual void device_reset() override ATTR_COLD;
+
+ TIMER_CALLBACK_MEMBER(hold_cpu);
+ TIMER_CALLBACK_MEMBER(free_cpu);
- void device_start() override;
- void device_reset() override;
- void device_timer(emu_timer &timer, device_timer_id id, int param, void *ptr) override;
- std::string tts(attotime t);
+private:
devcb_read8 m_mem_read_cb; // Callback to read memory
devcb_write_line m_hold_cb;
devcb_write_line m_int_cb;
@@ -105,19 +108,18 @@ public:
uint8_t cruread(offs_t offset);
void cruwrite(offs_t offset, uint8_t data);
- void device_start() override;
- ioport_constructor device_input_ports() const override;
auto rombank_cb() { return m_set_rom_bank.bind(); }
protected:
io992_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock);
bool m_have_banked_rom;
+ virtual void device_start() override ATTR_COLD;
+ virtual ioport_constructor device_input_ports() const override ATTR_COLD;
+
void hexbus_value_changed(uint8_t data) override;
private:
- const uint8_t m_hexbval[6] = { 0x01, 0x02, 0x40, 0x80, 0x10, 0x04 };
-
required_device<hexbus::hexbus_device> m_hexbus;
required_device<cassette_image_device> m_cassette;
required_device<video992_device> m_videoctrl;
@@ -129,18 +131,8 @@ private:
// Keyboard row
int m_key_row;
- // Hexbus outgoing signal latch. Should be set to D7 when idle.
- // (see hexbus.cpp)
- uint8_t m_latch_out;
-
- // Hexbus incoming signal latch. Should be set to D7 when idle.
- uint8_t m_latch_in;
-
- // Hexbus inhibit. This prevents the incoming latches to store the data.
- bool m_communication_disable;
-
- // Bit 6. It is not documented, but likely to indicate the response phase.
- bool m_response_phase;
+ // HSK* released flag. This is queried as CRU bit 6 (with the current HSK* level).
+ bool m_hsk_released;
};
@@ -158,11 +150,87 @@ public:
io992_32_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
};
-} } } // end namespace bus::ti99::internal
+/********************************************************************
+
+ Expansion port
+ This is modeled after the ioport connector of the TI-99/4A
+
+ However, since there are basically no expansion cards available,
+ and only the memory expansion was described in the specs, we
+ only include the necessary connections.
+
+********************************************************************/
+#define TI992_EXPPORT_TAG "expport"
+
+class ti992_expport_attached_device : public device_t
+{
+public:
+ ti992_expport_attached_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock) :
+ device_t(mconfig, type, tag, owner, clock)
+ { }
+
+ // Methods called from the console
+ virtual void readz(offs_t offset, uint8_t *value) { }
+ virtual void write(offs_t offset, uint8_t data) { }
+};
+
+class ti992_expport_device : public device_t, public device_single_card_slot_interface<ti992_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)
+ : ti992_expport_device(mconfig, tag, owner, clock)
+ {
+ option_reset();
+ opts(*this);
+ set_default_option(dflt);
+ set_fixed(false);
+ }
+
+ ti992_expport_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
+
+ // Methods called from the console
+ // More methods should be added, once we can find further 99/2 cartridges
+ void readz(offs_t offset, uint8_t *value);
+ void write(offs_t offset, uint8_t data);
+
+protected:
+ virtual void device_start() override { }
+ virtual void device_config_complete() override;
+
+private:
+ ti992_expport_attached_device* m_connected;
+};
+
+// RAM expansion
+
+class ti992_expram_device : public ti992_expport_attached_device
+{
+public:
+ ti992_expram_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
+ virtual void readz(offs_t offset, uint8_t *value) override;
+ virtual void write(offs_t offset, uint8_t data) override;
+
+protected:
+ virtual void device_start() override {}
+ virtual void device_add_mconfig(machine_config &config) override ATTR_COLD;
+
+private:
+ required_device<ram_device> m_ram;
+};
+
+
+} // end namespace bus::ti99::internal
+
+DECLARE_DEVICE_TYPE_NS(TI992_EXPPORT, bus::ti99::internal, ti992_expport_device)
+
+void ti992_expport_options(device_slot_interface &device);
DECLARE_DEVICE_TYPE_NS(VIDEO99224, bus::ti99::internal, video992_24_device)
DECLARE_DEVICE_TYPE_NS(VIDEO99232, bus::ti99::internal, video992_32_device)
DECLARE_DEVICE_TYPE_NS(IO99224, bus::ti99::internal, io992_24_device)
DECLARE_DEVICE_TYPE_NS(IO99232, bus::ti99::internal, io992_32_device)
+DECLARE_DEVICE_TYPE_NS(TI992_RAM32K, bus::ti99::internal, ti992_expram_device)
+
#endif // MAME_BUS_TI99_INTERNAL_992BOARD_H
diff --git a/src/devices/bus/ti99/internal/998board.cpp b/src/devices/bus/ti99/internal/998board.cpp
index a91ad55344d..684c531895d 100644
--- a/src/devices/bus/ti99/internal/998board.cpp
+++ b/src/devices/bus/ti99/internal/998board.cpp
@@ -107,34 +107,34 @@
#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"
-DEFINE_DEVICE_TYPE_NS(TI99_MAINBOARD8, bus::ti99::internal, mainboard8_device, "ti998_mainboard", "TI-99/8 Mainboard")
-DEFINE_DEVICE_TYPE_NS(TI99_VAQUERRO, bus::ti99::internal, vaquerro_device, "ti998_vaquerro", "TI-99/8 Logical Address Space Decoder")
-DEFINE_DEVICE_TYPE_NS(TI99_MOFETTA, bus::ti99::internal, mofetta_device, "ti998_mofetta", "TI-99/8 Physical Address Space Decoder")
-DEFINE_DEVICE_TYPE_NS(TI99_OSO, bus::ti99::internal, oso_device, "ti998_oso", "TI-99/8 Hexbus interface")
-DEFINE_DEVICE_TYPE_NS(TI99_AMIGO, bus::ti99::internal, amigo_device, "ti998_amigo", "TI-99/8 Address space mapper")
+DEFINE_DEVICE_TYPE(TI99_MAINBOARD8, bus::ti99::internal::mainboard8_device, "ti998_mainboard", "TI-99/8 Mainboard")
+DEFINE_DEVICE_TYPE(TI99_VAQUERRO, bus::ti99::internal::vaquerro_device, "ti998_vaquerro", "TI-99/8 Logical Address Space Decoder")
+DEFINE_DEVICE_TYPE(TI99_MOFETTA, bus::ti99::internal::mofetta_device, "ti998_mofetta", "TI-99/8 Physical Address Space Decoder")
+DEFINE_DEVICE_TYPE(TI99_OSO, bus::ti99::internal::oso_device, "ti998_oso", "TI-99/8 Hexbus interface")
+DEFINE_DEVICE_TYPE(TI99_AMIGO, bus::ti99::internal::amigo_device, "ti998_amigo", "TI-99/8 Address space mapper")
-namespace bus { namespace ti99 { namespace internal {
+namespace bus::ti99::internal {
enum
{
@@ -160,8 +160,8 @@ mainboard8_device::mainboard8_device(const machine_config &mconfig, const char *
m_amigo(*this, TI998_AMIGO_TAG),
m_oso(*this, TI998_OSO_TAG),
m_maincpu(*owner, "maincpu"),
- m_video(*owner, TI_VDP_TAG), // subdevice of main class
- m_sound(*owner, TI_SOUNDCHIP_TAG),
+ m_video(*owner, TI998_VDP_TAG),
+ m_sound(*owner, TI998_SOUNDCHIP_TAG),
m_speech(*owner, TI998_SPEECHSYN_TAG),
m_gromport(*owner, TI99_GROMPORT_TAG),
m_ioport(*owner, TI99_IOPORT_TAG),
@@ -189,6 +189,7 @@ mainboard8_device::mainboard8_device(const machine_config &mconfig, const char *
m_p3grom0(*owner, TI998_GLIB30_TAG),
m_p3grom1(*owner, TI998_GLIB31_TAG),
m_p3grom2(*owner, TI998_GLIB32_TAG),
+ m_tms9901(*owner, TI998_TMS9901_TAG),
m_sgrom_idle(true),
m_tsgrom_idle(true),
m_p8grom_idle(true),
@@ -351,7 +352,7 @@ void mainboard8_device::debugger_write(offs_t offset, uint8_t data)
// =============== CRU bus access ==================
-READ8Z_MEMBER(mainboard8_device::crureadz)
+void mainboard8_device::crureadz(offs_t offset, uint8_t *value)
{
m_ioport->crureadz(offset, value);
}
@@ -383,6 +384,10 @@ void mainboard8_device::setaddress(offs_t offset, uint8_t busctrl)
m_logical_address = offset;
m_physical_address = 0;
+ // Trigger the 9901's clock if S0=1
+ if ((offset & 0x0020) != 0)
+ m_tms9901->update_clock();
+
// In TI's bit order, A14 is the second line from the right side (2^1)
m_A14_set = ((m_logical_address & 2)!=0); // Needed for clock_in
@@ -409,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);
}
@@ -422,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);
}
@@ -430,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);
@@ -681,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);
@@ -955,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);
@@ -967,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);
@@ -977,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();
@@ -1153,7 +1153,7 @@ vaquerro_device::vaquerro_device(const machine_config &mconfig, const char *tag,
{
}
-SETADDRESS_DBIN_MEMBER( vaquerro_device::set_address )
+void vaquerro_device::set_address(offs_t offset, int state)
{
// Do the decoding
// state = dbin, offset = address
@@ -1249,17 +1249,17 @@ SETADDRESS_DBIN_MEMBER( vaquerro_device::set_address )
}
}
-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);
}
@@ -1267,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;
}
@@ -1275,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);
@@ -1302,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;
@@ -1321,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;
}
@@ -1361,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;
@@ -1602,7 +1602,7 @@ mofetta_device::mofetta_device(const machine_config &mconfig, const char *tag, d
{
}
-SETADDRESS_DBIN_MEMBER( mofetta_device::set_address )
+void mofetta_device::set_address(offs_t offset, int state)
{
if (!m_gotfirstword)
{
@@ -1657,7 +1657,7 @@ SETADDRESS_DBIN_MEMBER( mofetta_device::set_address )
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?
{
@@ -1670,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;
}
@@ -1708,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;
}
@@ -1757,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)
{
@@ -1772,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);
}
@@ -1919,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;
@@ -1932,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);
}
@@ -1940,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;
}
@@ -1948,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;
}
@@ -1959,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;
}
@@ -1967,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;
}
@@ -1975,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);
}
@@ -2071,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)
{
@@ -2179,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);
@@ -2189,6 +2189,8 @@ void amigo_device::device_start()
{
m_mainboard = downcast<mainboard8_device*>(owner());
+ std::fill(std::begin(m_base_register), std::end(m_base_register), 0);
+
save_item(NAME(m_memen));
save_pointer(NAME(m_base_register),16);
save_item(NAME(m_logical_space));
@@ -2264,7 +2266,7 @@ void amigo_device::device_reset()
oso_device::oso_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) :
bus::hexbus::hexbus_chained_device(mconfig, TI99_OSO, tag, owner, clock),
m_int(*this),
- m_hexbusout(*this, ":" TI_HEXBUS_TAG),
+ m_hexbusout(*this, ":" TI998_HEXBUS_TAG),
m_data(0),
m_status(0xff),
m_control(0),
@@ -2376,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)
@@ -2667,12 +2669,10 @@ void oso_device::update_hexbus()
// Check how the bus has changed. This depends on the states of all
// connected peripherals
- uint8_t value1 = hexbus_read();
- // if (value1 != value) LOGMASKED(LOG_OSO, "actually: %02x (BAV*=%d, HSK*=%d, data=%01x)\n", value1, (value1 & 0x04)? 1:0, (value1 & 0x10)? 1:0, ((value1>>4)&0x0c) | (value1&0x03));
// Update the state of BAV and HSK
- m_bav = ((value1 & bus::hexbus::HEXBUS_LINE_BAV)==0);
- m_hsk = ((value1 & bus::hexbus::HEXBUS_LINE_HSK)==0);
+ m_bav = (bus_bav_level()==ASSERT_LINE);
+ m_hsk = (bus_hsk_level()==ASSERT_LINE);
// Sometimes, Oso does not have a chance to advance its state after the
// last byte was read. In that case, a change of rdsetin would not be
@@ -2680,7 +2680,7 @@ void oso_device::update_hexbus()
// has happened.
if (m_hsk==false) m_rdsetold = false;
- m_oldvalue = value1;
+ m_oldvalue = m_current_bus_value;
}
/*
@@ -2689,8 +2689,8 @@ void oso_device::update_hexbus()
void oso_device::hexbus_value_changed(uint8_t data)
{
// LOGMASKED(LOG_OSO, "Hexbus value changed to %02x\n", data);
- bool bav = (data & bus::hexbus::HEXBUS_LINE_BAV)==0;
- bool hsk = (data & bus::hexbus::HEXBUS_LINE_HSK)==0;
+ bool bav = (bus_bav_level()==ASSERT_LINE);
+ bool hsk = (bus_hsk_level()==ASSERT_LINE);
if ((bav != m_bav) || (hsk != m_hsk))
{
@@ -2698,7 +2698,7 @@ void oso_device::hexbus_value_changed(uint8_t data)
m_hsk = hsk;
LOGMASKED(LOG_HEXBUS, "BAV*=%d, HSK*=%d\n", m_bav? 0:1, m_hsk? 0:1);
- int nibble = ((data & bus::hexbus::HEXBUS_LINE_BIT32)>>4) | (data & bus::hexbus::HEXBUS_LINE_BIT10);
+ int nibble = data_lines(data);
// The real devices are driven at a similar clock rate like the 99/8.
// The designers assumed that there is a clock tick of Oso between
@@ -2734,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);
@@ -2748,5 +2747,4 @@ void oso_device::device_start()
save_item(NAME(m_xmit));
}
-} } } // end namespace bus::ti99::internal
-
+} // end namespace bus::ti99::internal
diff --git a/src/devices/bus/ti99/internal/998board.h b/src/devices/bus/ti99/internal/998board.h
index 4040295470b..cf80377fce7 100644
--- a/src/devices/bus/ti99/internal/998board.h
+++ b/src/devices/bus/ti99/internal/998board.h
@@ -18,24 +18,29 @@
#pragma once
-#include "bus/ti99/ti99defs.h"
#include "bus/ti99/gromport/gromport.h"
#include "bus/hexbus/hexbus.h"
#include "bus/ti99/internal/ioport.h"
#include "machine/ram.h"
#include "machine/tmc0430.h"
+#include "machine/tms9901.h"
+#include "machine/tms6100.h"
#include "sound/sn76496.h"
#include "sound/tms5220.h"
#include "video/tms9928a.h"
// -------------- Defines ------------------------------------
-#define TI998_SRAM_TAG "sram8"
-#define TI998_DRAM_TAG "dram8"
-#define TI998_MAPPER_TAG "mapper"
+#define TI998_SRAM_TAG "sram8"
+#define TI998_DRAM_TAG "dram8"
+#define TI998_MAPPER_TAG "mapper"
#define TI998_MAINBOARD_TAG "mainboard8"
-#define TI998_SPEECHSYN_TAG "speech"
+#define TI998_SPEECHSYN_TAG "speech"
+#define TI998_SOUNDCHIP_TAG "soundchip"
+#define TI998_TMS9901_TAG "tms9901"
+#define TI998_VDP_TAG "vdp"
+#define TI998_HEXBUS_TAG "hexbus"
#define TI998_ROM0_REG "rom0_region"
#define TI998_ROM1_REG "rom1_region"
@@ -84,7 +89,7 @@
// --------------------------------------------------
-namespace bus { namespace ti99 { namespace internal {
+namespace bus::ti99::internal {
class mainboard8_device;
@@ -95,37 +100,37 @@ class vaquerro_device : public device_t
{
public:
vaquerro_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
- void device_start() override;
- void device_reset() override;
+ void device_start() override ATTR_COLD;
+ void device_reset() override ATTR_COLD;
line_state ready();
void treset();
- DECLARE_SETADDRESS_DBIN_MEMBER( set_address );
+ 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:
/*
@@ -160,17 +165,17 @@ private:
protected:
// Two flipflops
- bool m_counting;
- bool m_generate;
+ bool m_counting = false;
+ bool m_generate = false;
// Counter
- int m_counter;
+ int m_counter = 0;
// Select value (indicates selected line)
- int m_selvalue;
+ int m_selvalue = 0;
// Line state flags
- bool m_addressed;
- bool m_ready;
+ bool m_addressed = false;
+ bool m_ready = false;
};
class grom_waitstate_generator : public waitstate_generator
@@ -188,16 +193,16 @@ private:
};
// Memory cycle state
- bool m_memen;
+ bool m_memen = false;
// Waiting for video
- bool m_video_wait;
+ bool m_video_wait = false;
// State of the CRUS line
- int m_crus;
+ int m_crus = ASSERT_LINE;
// Are the GROM libraries turned on?
- bool m_crugl;
+ bool m_crugl = ASSERT_LINE;
// Do we have a logical address space match?
bool m_lasreq = false;
@@ -206,27 +211,27 @@ private:
bool m_grom_or_video = false;
// Select lines
- bool m_spwt;
- bool m_sccs;
- bool m_sromcs;
- bool m_sprd;
- bool m_vdprd;
- bool m_vdpwt;
+ bool m_spwt = false;
+ bool m_sccs = false;
+ bool m_sromcs = false;
+ bool m_sprd = false;
+ bool m_vdprd = CLEAR_LINE;
+ bool m_vdpwt = CLEAR_LINE;
// Collective GROM select state
- int m_gromsel;
+ int m_gromsel = 0;
// Outgoing READY
- int m_ggrdy;
+ int m_ggrdy = ASSERT_LINE;
// Outgoing READY latch (common flipflop driving SRY)
- bool m_sry;
+ bool m_sry = false;
// Holds the A14 address line state. We need this for the clock_in method.
- int m_a14;
+ int m_a14 = 0;
// Keeps the recent DBIN level
- int m_dbin_level;
+ int m_dbin_level = 0;
// Wait state logic components
grom_waitstate_generator m_sgmws, m_tsgws, m_p8gws, m_p3gws;
@@ -244,80 +249,80 @@ class mofetta_device : public device_t
public:
mofetta_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
- void device_start() override;
- void device_reset() override;
+ void device_start() override ATTR_COLD;
+ void device_reset() override ATTR_COLD;
void cruwrite(offs_t offset, uint8_t data);
- DECLARE_SETADDRESS_DBIN_MEMBER( set_address );
+ void set_address(offs_t offset, int state);
// Debugger support
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
- bool m_pmemen;
+ bool m_pmemen = false;
// Logical access
- bool m_lasreq;
+ bool m_lasreq = false;
// DRAM access
- bool m_skdrcs;
+ bool m_skdrcs = false;
// Indicates the UP level of the GROMCLK
- bool m_gromclk_up;
+ bool m_gromclk_up = false;
// Have we got the upper word of the address?
- bool m_gotfirstword;
+ bool m_gotfirstword = false;
// Address latch
- int m_address_latch;
+ int m_address_latch = 0;
// Most significant byte of the 24-bit address
- int m_prefix;
+ int m_prefix = 0;
// CRU select of the 1700 device
- bool m_alcpg;
+ bool m_alcpg = false;
// CRU select of the 2700 device
- bool m_txspg;
+ bool m_txspg = false;
// ROM1 select lines
- bool m_rom1cs;
- bool m_rom1am;
- bool m_rom1al;
+ bool m_rom1cs = false;
+ bool m_rom1am = false;
+ bool m_rom1al = false;
// OSO select
- bool m_alccs;
+ bool m_alccs = false;
// Pascal ROM select line
- bool m_prcs;
+ bool m_prcs = false;
// Cartridge port select line
- bool m_cmas;
+ bool m_cmas = false;
// GROM clock count (as frequency divider)
- int m_gromclock_count;
+ int m_gromclock_count = 0;
// Remember last msast state for edge detection
- int m_msast;
+ int m_msast = 0;
// Pointer to mainboard
mainboard8_device* m_mainboard;
@@ -330,8 +335,8 @@ class amigo_device : public device_t
{
public:
amigo_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
- void device_start() override;
- void device_reset() override;
+ void device_start() override ATTR_COLD;
+ void device_reset() override ATTR_COLD;
uint8_t read();
void write(uint8_t data);
@@ -341,24 +346,24 @@ 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; }
private:
// Memory cycle state
- bool m_memen;
+ bool m_memen = false;
// DMA methods for loading/saving maps
void mapper_load();
@@ -369,52 +374,52 @@ private:
uint32_t m_base_register[16];
// Indicates a logical space access
- bool m_logical_space;
+ bool m_logical_space = true;
// Physical address
- uint32_t m_physical_address;
+ uint32_t m_physical_address = 0;
// Pointer to SRAM where AMIGO needs to upload/download its map values
- uint8_t* m_sram;
+ uint8_t* m_sram = nullptr;
// Pointer to mainboard
mainboard8_device* m_mainboard;
// Keep the system ready state
- int m_srdy;
+ int m_srdy = 0;
// Outgoing READY level
- int m_ready_out;
+ int m_ready_out = 0;
// Keep the CRUS setting
- int m_crus;
+ int m_crus = 0;
// State of the address creation
- int m_amstate;
+ int m_amstate = 0;
// Protection flags
- int m_protflag;
+ int m_protflag = 0;
// Accessing SRAM
- bool m_sram_accessed;
+ bool m_sram_accessed = false;
// Accessing DRAM
- bool m_dram_accessed;
+ bool m_dram_accessed = false;
// Accessing the mapper
- bool m_mapper_accessed;
+ bool m_mapper_accessed = false;
// HOLDA flag
- bool m_hold_acknowledged;
+ bool m_hold_acknowledged = false;
// Address in SRAM during DMA
- uint32_t m_sram_address;
+ uint32_t m_sram_address = 0;
// Number of the currently loaded/save base register
- int m_basereg;
+ int m_basereg = 0;
// Latched value for mapper DMA transfer
- uint32_t m_mapvalue;
+ uint32_t m_mapvalue = 0;
};
/*
@@ -453,10 +458,10 @@ public:
oso_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
uint8_t read(offs_t offset);
void write(offs_t offset, uint8_t data);
- void device_start() override;
+ void device_start() override ATTR_COLD;
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;
@@ -471,54 +476,54 @@ private:
required_device<bus::hexbus::hexbus_device> m_hexbusout;
// Registers
- uint8_t m_data;
- uint8_t m_status;
- uint8_t m_control;
- uint8_t m_xmit;
+ uint8_t m_data = 0;
+ uint8_t m_status = 0;
+ uint8_t m_control = 0;
+ uint8_t m_xmit = 0;
- bool m_bav; // Bus available; when true, a communication is about to happen
- bool m_sbav; // Stable BAV; the BAV signal is true for two clock cycles
- bool m_sbavold; // Old SBAV state
- bool m_bavold;
+ bool m_bav = false; // Bus available; when true, a communication is about to happen
+ bool m_sbav = false; // Stable BAV; the BAV signal is true for two clock cycles
+ bool m_sbavold = false; // Old SBAV state
+ bool m_bavold = false;
- bool m_hsk; // Handshake line; when true, a bus member needs more time to process the message
- bool m_hsklocal; // Local level of HSK
- bool m_shsk; // Stable HSK
- bool m_hskold;
+ bool m_hsk = false; // Handshake line; when true, a bus member needs more time to process the message
+ bool m_hsklocal = false; // Local level of HSK
+ bool m_shsk = false; // Stable HSK
+ bool m_hskold = false;
// Page 3 in OSO schematics: Write timing
- bool m_wq1; // Flipflop 1
- bool m_wq1old; // Previous state
- bool m_wq2; // Flipflop 2
- bool m_wq2old; // Previous state
- bool m_wnp; // Write nibble selection; true means upper 4 bits
- bool m_wbusy; // When true, direct the transmit register towards the output
- bool m_wbusyold; // Old state of the WBUSY line
- bool m_sendbyte; // Byte has been loaded into the XMIT register
- bool m_wrset; // Start sending
- bool m_counting; // Counter running
- int m_clkcount; // Counter for 30 cycles
+ bool m_wq1 = false; // Flipflop 1
+ bool m_wq1old = false; // Previous state
+ bool m_wq2 = false; // Flipflop 2
+ bool m_wq2old = false; // Previous state
+ bool m_wnp = false; // Write nibble selection; true means upper 4 bits
+ bool m_wbusy = false; // When true, direct the transmit register towards the output
+ bool m_wbusyold = false; // Old state of the WBUSY line
+ bool m_sendbyte = false; // Byte has been loaded into the XMIT register
+ bool m_wrset = false; // Start sending
+ bool m_counting = false; // Counter running
+ int m_clkcount = 0; // Counter for 30 cycles
// Page 4 in OSO schematics: Read timing
- bool m_rq1; // Flipflop 1
- bool m_rq2; // Flipflop 2
- bool m_rq2old; // Previous state
- bool m_rnib; // Read nibble, true means upper 4 bits
- bool m_rnibcold; // Needed to detect the raising edge
- bool m_rdset; // Start reading
- bool m_rdsetold; // Old state
- bool m_msns; // Upper 4 bits
- bool m_lsns; // Lower 4 bits
+ bool m_rq1 = false; // Flipflop 1
+ bool m_rq2 = false; // Flipflop 2
+ bool m_rq2old = false; // Previous state
+ bool m_rnib = false; // Read nibble, true means upper 4 bits
+ bool m_rnibcold = false; // Needed to detect the raising edge
+ bool m_rdset = false; // Start reading
+ bool m_rdsetold = false; // Old state
+ bool m_msns = false; // Upper 4 bits
+ bool m_lsns = false; // Lower 4 bits
// Page 6 (RHSUS*)
- bool m_rhsus; // Needed to assert the HSK line until the CPU has read the byte
+ bool m_rhsus = false; // Needed to assert the HSK line until the CPU has read the byte
- bool m_rbusy;
+ bool m_rbusy = false;
- bool m_phi3;
+ bool m_phi3 = false;
// Debugging help
- uint8_t m_oldvalue;
+ uint8_t m_oldvalue = 0;
/*
// This is a buffer to enqueue changes on the Hexbus
// This is not part of the real implementation, but in the emulation
@@ -548,20 +553,20 @@ public:
void debugger_write(offs_t offset, uint8_t data);
// I/O space
- DECLARE_READ8Z_MEMBER( crureadz );
+ void crureadz(offs_t offset, uint8_t *value);
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(); }
@@ -570,55 +575,55 @@ 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;
- void device_reset() override;
- virtual void device_add_mconfig(machine_config &config) override;
+ void device_start() override ATTR_COLD;
+ void device_reset() override ATTR_COLD;
+ virtual void device_add_mconfig(machine_config &config) override ATTR_COLD;
private:
// Holds the state of the A14 line
- bool m_A14_set;
+ bool m_A14_set = false;
// Propagates the end of the memory cycle
void cycle_end();
// Original logical address.
- int m_logical_address;
+ int m_logical_address = 0;
// Mapped physical address.
- int m_physical_address;
+ int m_physical_address = 0;
// Indicates that a byte is waiting on the data bus (see m_latched_data)
- bool m_pending_write;
+ bool m_pending_write = false;
// Hold the value of the data bus. In a real machine, the data bus continues
// to show that value, but in this emulation we have a push mechanism.
- uint8_t m_latched_data;
+ uint8_t m_latched_data = 0;
// Hold the level of the GROMCLK line
- int m_gromclk;
+ int m_gromclk = 0;
// Selecting GROM libraries
void select_groms();
// Previous select state
- int m_prev_grom;
+ int m_prev_grom = 0;
// Ready states
- bool m_speech_ready;
- bool m_sound_ready;
- bool m_pbox_ready;
+ bool m_speech_ready = true;
+ bool m_sound_ready = true;
+ bool m_pbox_ready = true;
// Keeps the recent DBIN level
- int m_dbin_level;
+ int m_dbin_level = 0;
// Ready line to the CPU
devcb_write_line m_ready;
@@ -649,7 +654,7 @@ private:
required_device<ram_device> m_dram;
// Debugging
- int m_last_ready;
+ int m_last_ready = CLEAR_LINE;
line_state m_crus_debug;
// System GROM library
@@ -682,19 +687,22 @@ private:
required_device<tmc0430_device> m_p3grom1;
required_device<tmc0430_device> m_p3grom2;
+ // Link to the 9901
+ required_device<tms9901_device> m_tms9901;
+
// Idle flags for GROMs
- bool m_sgrom_idle;
- bool m_tsgrom_idle;
- bool m_p8grom_idle;
- bool m_p3grom_idle;
+ bool m_sgrom_idle = true;
+ bool m_tsgrom_idle = true;
+ bool m_p8grom_idle = true;
+ bool m_p3grom_idle = true;
// ROM area of the system.
- uint8_t* m_rom0;
- uint8_t* m_rom1;
- uint8_t* m_pascalrom;
+ uint8_t* m_rom0 = nullptr;
+ uint8_t* m_rom1 = nullptr;
+ uint8_t* m_pascalrom = nullptr;
};
-} } } // end namespace bus::ti99::internal
+} // end namespace bus::ti99::internal
DECLARE_DEVICE_TYPE_NS(TI99_MAINBOARD8, bus::ti99::internal, mainboard8_device)
DECLARE_DEVICE_TYPE_NS(TI99_VAQUERRO, bus::ti99::internal, vaquerro_device)
diff --git a/src/devices/bus/ti99/internal/buffram.cpp b/src/devices/bus/ti99/internal/buffram.cpp
new file mode 100644
index 00000000000..00356eb7817
--- /dev/null
+++ b/src/devices/bus/ti99/internal/buffram.cpp
@@ -0,0 +1,60 @@
+// license:LGPL-2.1+
+// copyright-holders:Michael Zapf
+/*******************************************************************************
+ Buffered SRAM
+
+ Michael Zapf
+ March 2020
+
+*******************************************************************************/
+
+#include "emu.h"
+#include "buffram.h"
+
+#define VERBOSE ( LOG_GENERAL )
+#include "logmacro.h"
+
+#define BUFFRAM_TAG "buffered_ram"
+
+DEFINE_DEVICE_TYPE(BUFF_RAM, bus::ti99::internal::buffered_ram_device, BUFFRAM_TAG, "Buffered SRAM")
+
+namespace bus::ti99::internal {
+
+
+// ========== Buffered SRAM ============
+
+buffered_ram_device::buffered_ram_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
+ : device_t(mconfig, BUFF_RAM, tag, owner, clock),
+ device_nvram_interface(mconfig, *this),
+ m_size(0),
+ m_mem(nullptr)
+{
+}
+
+void buffered_ram_device::device_start()
+{
+ m_mem = std::make_unique<u8 []>(m_size);
+
+ // register for state saving
+ save_item(NAME(m_size));
+ save_pointer(NAME(m_mem), m_size);
+}
+
+void buffered_ram_device::nvram_default()
+{
+ std::fill_n(m_mem.get(), m_size, 0x00);
+}
+
+bool buffered_ram_device::nvram_read(util::read_stream &file)
+{
+ 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)
+{
+ 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/buffram.h b/src/devices/bus/ti99/internal/buffram.h
new file mode 100644
index 00000000000..10e67da9e2a
--- /dev/null
+++ b/src/devices/bus/ti99/internal/buffram.h
@@ -0,0 +1,49 @@
+// license:LGPL-2.1+
+// copyright-holders:Michael Zapf
+/*******************************************************************************
+
+ Buffered RAM circuit.
+
+ Michael Zapf
+ March 2020
+
+*******************************************************************************/
+
+#ifndef MAME_BUS_TI99_INTERNAL_BUFFRAM_H
+#define MAME_BUS_TI99_INTERNAL_BUFFRAM_H
+
+#pragma once
+
+namespace bus::ti99::internal {
+
+// =========== Buffered RAM ================
+class buffered_ram_device : public device_t, public device_nvram_interface
+{
+public:
+ buffered_ram_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
+ buffered_ram_device &set_size(int size) { m_size = size; return *this; }
+
+ // read/write
+ uint8_t read(offs_t offset) { return m_mem[offset % m_size]; }
+ void write(offs_t offset, uint8_t data) { m_mem[offset % m_size] = data; }
+
+ void set_buffered(bool on) { nvram_enable_backup(on); }
+
+private:
+ virtual void device_start() override ATTR_COLD;
+
+ // derived class overrides
+ virtual void nvram_default() override;
+ virtual bool nvram_read(util::read_stream &file) override;
+ virtual bool nvram_write(util::write_stream &file) override;
+
+ int m_size;
+ std::unique_ptr<u8 []> m_mem;
+};
+
+
+} // end namespace bus::ti99::internal
+
+DECLARE_DEVICE_TYPE_NS(BUFF_RAM, bus::ti99::internal, buffered_ram_device)
+
+#endif // MAME_BUS_TI99_INTERNAL_BUFFRAM_H
diff --git a/src/devices/bus/ti99/internal/datamux.cpp b/src/devices/bus/ti99/internal/datamux.cpp
index d0e7d05a6c1..8359e213d8d 100644
--- a/src/devices/bus/ti99/internal/datamux.cpp
+++ b/src/devices/bus/ti99/internal/datamux.cpp
@@ -72,27 +72,27 @@
#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"
-DEFINE_DEVICE_TYPE_NS(TI99_DATAMUX, bus::ti99::internal, datamux_device, "ti99_datamux", "TI-99 Databus multiplexer")
+DEFINE_DEVICE_TYPE(TI99_DATAMUX, bus::ti99::internal::datamux_device, "ti99_datamux", "TI-99 Databus multiplexer")
-namespace bus { namespace ti99 { namespace internal {
+namespace bus::ti99::internal {
/*
Constructor
*/
datamux_device::datamux_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
: device_t(mconfig, TI99_DATAMUX, tag, owner, clock),
- m_video(*owner, TI_VDP_TAG),
- m_sound(*owner, TI_SOUNDCHIP_TAG),
+ m_video(*owner, TI99_VDP_TAG),
+ m_sound(*owner, TI99_SOUNDCHIP_TAG),
m_ioport(*owner, TI99_IOPORT_TAG),
m_gromport(*owner, TI99_GROMPORT_TAG),
m_ram16b(*owner, TI99_EXPRAM_TAG),
@@ -101,6 +101,7 @@ datamux_device::datamux_device(const machine_config &mconfig, const char *tag, d
m_grom0(*owner, TI99_GROM0_TAG),
m_grom1(*owner, TI99_GROM1_TAG),
m_grom2(*owner, TI99_GROM2_TAG),
+ m_tms9901(*owner, TI99_TMS9901_TAG),
m_ready(*this),
m_addr_buf(0),
m_dbin(CLEAR_LINE),
@@ -123,31 +124,25 @@ datamux_device::datamux_device(const machine_config &mconfig, const char *tag, d
void datamux_device::read_all(uint16_t addr, uint8_t *value)
{
- // Valid access
- bool validaccess = ((addr & 0x0400)==0);
-
- if (validaccess)
+ // GROM access
+ if ((addr & 0xfc01)==0x9800)
{
- // GROM access
- if ((addr & 0xf801)==0x9800)
+ if (m_console_groms_present)
{
- if (m_console_groms_present)
- {
- m_grom0->readz(value);
- m_grom1->readz(value);
- m_grom2->readz(value);
- }
- // GROMport (GROMs)
- m_gromport->readz(addr, value);
- m_grom_idle = false;
+ m_grom0->readz(value);
+ m_grom1->readz(value);
+ m_grom2->readz(value);
}
+ // GROMport (GROMs)
+ m_gromport->readz(addr, value);
+ m_grom_idle = false;
+ }
- // Video
- if ((addr & 0xf801)==0x8800)
- {
- // Forward to VDP unless we have an EVPC
- if (m_video != nullptr) *value = m_video->read(addr>>1); // A14 determines data or register read
- }
+ // Video
+ if ((addr & 0xfc01)==0x8800)
+ {
+ // Forward to VDP unless we have an EVPC
+ if (m_video != nullptr) *value = m_video->read((addr>>1)&1); // A14 determines data or register read
}
// GROMport (ROMs)
@@ -185,10 +180,10 @@ void datamux_device::write_all(uint16_t addr, uint8_t value)
}
// Video
- if ((addr & 0xf801)==0x8800)
+ if ((addr & 0xfc01)==0x8c00)
{
// Forward to VDP unless we have an EVPC
- if (m_video != nullptr) m_video->write(addr>>1, value); // A14 determines data or register write
+ if (m_video != nullptr) m_video->write((addr>>1)&1, value); // A14 determines data or register write
}
// I/O port gets all accesses
@@ -210,6 +205,9 @@ void datamux_device::setaddress_all(uint16_t addr)
// Cartridge ROM
bool iscartrom = ((addr & 0xe000)==0x6000);
+ // Speech (1001 0wxx xxxx xxx0)
+ bool sbe = ((addr & 0xf801)==0x9000) && validaccess;
+
// Always deliver to GROM so that the select line may be cleared
line_state gsq = isgrom? ASSERT_LINE : CLEAR_LINE;
if (isgrom) m_grom_idle = false;
@@ -233,6 +231,7 @@ void datamux_device::setaddress_all(uint16_t addr)
// I/O port gets all accesses
m_memen_state = ASSERT_LINE;
m_ioport->memen_in(m_memen_state);
+ m_ioport->sbe(sbe);
m_ioport->setaddress_dbin(addr, m_dbin);
}
@@ -318,14 +317,14 @@ void datamux_device::debugger_write(uint16_t addr, uint16_t data)
if ((addrb & 0xe000)==0x6000)
{
m_gromport->romgq_line(ASSERT_LINE);
- m_gromport->write(addr+1, data & 0xff);
- m_gromport->write(addr, (data>>8) & 0xff);
+ m_gromport->write(addrb+1, data & 0xff);
+ m_gromport->write(addrb, (data>>8) & 0xff);
m_gromport->romgq_line(m_romgq_state); // reset to previous state
}
m_ioport->memen_in(ASSERT_LINE);
- m_ioport->write(addr+1, data & 0xff);
- m_ioport->write(addr, (data>>8) & 0xff);
+ m_ioport->write(addrb+1, data & 0xff);
+ m_ioport->write(addrb, (data>>8) & 0xff);
m_ioport->memen_in(m_memen_state); // reset to previous state
}
}
@@ -378,7 +377,7 @@ uint16_t datamux_device::read(offs_t offset)
// Reading the even address now (addr)
uint8_t hbyte = 0;
read_all(m_addr_buf, &hbyte);
- LOGMASKED(LOG_ACCESS, "Read even byte from address %04x -> %02x\n", m_addr_buf, hbyte);
+ LOGMASKED(LOG_ACCESS, "%04x -> %02x\n", m_addr_buf, hbyte);
value = (hbyte<<8) | m_latch;
}
@@ -442,6 +441,10 @@ void datamux_device::setaddress(offs_t offset, uint16_t busctrl)
LOGMASKED(LOG_ADDRESS, "Set address %04x\n", m_addr_buf);
+ // Trigger the TMS9901 clock when A10 is 1
+ if ((m_addr_buf & 0x0020) != 0)
+ m_tms9901->update_clock();
+
if ((m_addr_buf & 0xe000) == 0x0000)
{
return; // console ROM
@@ -482,7 +485,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)
@@ -506,9 +509,11 @@ WRITE_LINE_MEMBER( datamux_device::clock_in )
}
if (m_waitcount==2)
{
+ // Clear the latch (if no device responds on the bus, we assume the data lines as 0)
+ m_latch = 0;
// read odd byte
read_all(m_addr_buf+1, &m_latch);
- LOGMASKED(LOG_ACCESS, "Read odd byte from address %04x -> %02x\n", m_addr_buf+1, m_latch);
+ LOGMASKED(LOG_ACCESS, "%04x -> %02x\n", m_addr_buf+1, m_latch);
// do the setaddress for the even address
setaddress_all(m_addr_buf);
}
@@ -547,7 +552,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;
@@ -556,7 +561,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;
@@ -580,10 +585,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));
@@ -598,11 +602,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);
@@ -636,5 +640,4 @@ ioport_constructor datamux_device::device_input_ports() const
return INPUT_PORTS_NAME(datamux);
}
-} } } // end namespace bus::ti99::internal
-
+} // end namespace bus::ti99::internal
diff --git a/src/devices/bus/ti99/internal/datamux.h b/src/devices/bus/ti99/internal/datamux.h
index 32e73a091b2..851addb9755 100644
--- a/src/devices/bus/ti99/internal/datamux.h
+++ b/src/devices/bus/ti99/internal/datamux.h
@@ -3,7 +3,7 @@
/****************************************************************************
TI-99/4(A) databus multiplexer circuit
- See datamux.c for documentation
+ See datamux.cpp for documentation
Michael Zapf
@@ -16,15 +16,26 @@
#pragma once
-#include "bus/ti99/ti99defs.h"
#include "machine/tmc0430.h"
#include "bus/ti99/gromport/gromport.h"
#include "bus/ti99/internal/ioport.h"
#include "sound/sn76496.h"
#include "video/tms9928a.h"
#include "machine/ram.h"
+#include "machine/tms9901.h"
-namespace bus { namespace ti99 { namespace internal {
+#define TI99_DATAMUX_TAG "datamux_16_8"
+#define TI99_GROM0_TAG "console_grom_0"
+#define TI99_GROM1_TAG "console_grom_1"
+#define TI99_GROM2_TAG "console_grom_2"
+#define TI99_PADRAM_TAG "scratchpad"
+#define TI99_EXPRAM_TAG "internal_32k_mod"
+#define TI99_CONSOLEROM "console_rom"
+#define TI99_SOUNDCHIP_TAG "soundchip"
+#define TI99_VDP_TAG "vdp"
+#define TI99_TMS9901_TAG "tms9901"
+
+namespace bus::ti99::internal {
/*
Main class
@@ -37,19 +48,19 @@ 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(); }
protected:
/* Constructor */
- void device_start() override;
+ void device_start() override ATTR_COLD;
void device_stop() override;
- void device_reset() override;
+ void device_reset() override ATTR_COLD;
ioport_constructor device_input_ports() const override;
private:
@@ -82,6 +93,9 @@ private:
required_device<tmc0430_device> m_grom1;
required_device<tmc0430_device> m_grom2;
+ // Link to 9901
+ required_device<tms9901_device> m_tms9901;
+
// Common read routine
void read_all(uint16_t addr, uint8_t *target);
@@ -138,7 +152,7 @@ private:
/******************************************************************************/
-} } } // end namespace bus::ti99::internal
+} // end namespace bus::ti99::internal
DECLARE_DEVICE_TYPE_NS(TI99_DATAMUX, bus::ti99::internal, datamux_device)
diff --git a/src/devices/bus/ti99/internal/evpcconn.cpp b/src/devices/bus/ti99/internal/evpcconn.cpp
index 244092fbd11..5c9114e53c7 100644
--- a/src/devices/bus/ti99/internal/evpcconn.cpp
+++ b/src/devices/bus/ti99/internal/evpcconn.cpp
@@ -22,24 +22,24 @@
#include "emu.h"
#include "evpcconn.h"
-DEFINE_DEVICE_TYPE_NS(TI99_EVPCCONN, bus::ti99::internal, evpc_clock_connector, "ti99_evpc_clock", "EVPC clock connector")
+DEFINE_DEVICE_TYPE(TI99_EVPCCONN, bus::ti99::internal::evpc_clock_connector, "ti99_evpc_clock", "EVPC clock connector")
-namespace bus { namespace ti99 { namespace internal {
+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
+
+} // end namespace bus::ti99::internal
diff --git a/src/devices/bus/ti99/internal/evpcconn.h b/src/devices/bus/ti99/internal/evpcconn.h
index 3aad475d3e7..d7eb2b810f8 100644
--- a/src/devices/bus/ti99/internal/evpcconn.h
+++ b/src/devices/bus/ti99/internal/evpcconn.h
@@ -11,17 +11,17 @@
#pragma once
-#include "bus/ti99/ti99defs.h"
+#define TI99_EVPC_CONN_TAG "evpc_conn"
-namespace bus { namespace ti99 { namespace internal {
+namespace bus::ti99::internal {
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 device_start() override;
+ void vclock_line(int state);
+ void device_start() override ATTR_COLD;
auto vdpint_cb() { return m_vdpint.bind(); }
private:
@@ -29,7 +29,7 @@ private:
devcb_write_line m_vdpint;
};
-} } } // end namespace bus::ti99::internal
+} // end namespace bus::ti99::internal
DECLARE_DEVICE_TYPE_NS(TI99_EVPCCONN, bus::ti99::internal, evpc_clock_connector)
diff --git a/src/devices/bus/ti99/internal/genboard.cpp b/src/devices/bus/ti99/internal/genboard.cpp
index 773aa0ef217..7e2ea7e3630 100644
--- a/src/devices/bus/ti99/internal/genboard.cpp
+++ b/src/devices/bus/ti99/internal/genboard.cpp
@@ -1,14 +1,13 @@
// license:LGPL-2.1+
// copyright-holders:Michael Zapf
/***************************************************************************
- Geneve 9640 Gate Array and more components
+ Geneve 9640 Gate Array, PAL, and Genmod daughterboard
This file contains the emulation of the gate array and of the PAL chip
that is used to control wait state generation.
Pins of the Gate Array:
-
- in: AMC, AMB, AMA, A0..A15: Address bus
+ in: A0..A15: Address bus
in: CLKOUT
in: IAQ/HOLDA
in?: NMI*
@@ -34,9 +33,13 @@
out: CSR*: v9938 read
out: RAMENX*: SRAM expansion
+ out: RAMENU*: Ultimate SRAM expansion. This is actually done by a small
+ daughterboard, not directly in the Gate Array.
+
out: RAMEN*: SRAM
out: ROMEN*: EPROM
- out: AB0, AB1, AB2: Mapped address bits
+ out: AB0, AB1, AB2: Mapped address bits (2^15, 2^14, 2^13)
+ out: AMC, AMB, AMA: Higher address bits (2^18, 2^17, 2^16)
in: DBIN*
? : ABUS* / HOLDA
out: DBIN
@@ -48,88 +51,219 @@
out: WE* / CRUCLK
out: PhiCLK: System clock for 9901
- Onboard SRAM configuration:
- There is an adjustable SRAM configuration on board, representing the
- various enhancements by users.
-
- The standard memory configuration as reported by chkdsk (32 KiB):
- 557056 bytes of total memory
+ Onboard SRAM configuration
+ ==========================
- With 64 KiB SRAM:
- 589824 bytes of total memory
+ Earlier versions of this emulation allowed for up to 384 KiB of SRAM.
+ However, this did not reflect the technical options of the real device.
+ In fact, there are only two select lines (RAMEN*, RAMEN-X*) that each
+ select one SRAM chip of 32 KiB capacity. Accordingly, we now only offer
+ the optional 32K expansion.
+
+ Measurements on the real system proved that the zero waitstate access
+ is only available for the banks of stock and expansion SRAM, not for
+ the other areas (including the EPROM).
+
+ The later operating systems of the Geneve (starting with 2.50s)
+ assume the 32K expansion to be available. For this reason, this option is
+ selected by default.
+
+ Higher amounts of SRAM require extensive changes to the hardware (also
+ with respect to the wait state generation).
+
+ Geneve mapper
+ ============
+
+ In the Gate Array, a set of 8 map registers is used to expand the logical
+ address to a physical address of 21 bits length. This is done by defining
+ frames of 8 KiB size (13 bits); the most significant 3 bits select the
+ map register, and its 8 bits are then prepended to the offset.
+
+ Logical address:
+ fffx xxxx xxxx xxxx
+ \|/
+ | Map registers
+ +--> 000: pppp pppp ---> Physical address (21 bits):
+ 001: pppp pppp p pppp pppx xxxx xxxx xxxx
+ 010: pppp pppp
+ ...
+ 111: pppp pppp = 000000 ... 1FFFFF (2 MiB space)
+
+ The map registers are memory-mapped into the logical address space
+ (Geneve mode: F110..F117, TI mode: 8000..8007) and set by writing the
+ bytes into them.
+
+ AMA/B/C decoding
+ ================
+
+ Since TI decided, for some obscure reason, to order the address bits in the
+ direction from MSB to LSB, the highest address bit is called A0. This
+ raises the problem that higher address bits lack a proper number (you
+ don't want to use negative numbers for sure). The Peripheral Expansion Box
+ already has three additional address lines: AMA (for the 2^16 position),
+ AMB (2^17), AMC (2^18).
+
+ The Flex Cable Interface (the card that allows the TI-99/4A console to
+ be connected to the Peribox) sets these bits to 1. The Geneve, however,
+ may use these lines to expand the usual 64K address space.
+
+ The classic Peribox cards check ABA/B/C for being set to 1. Since all
+ addresses starting with 00 or 01 are routed to the Geneve main board
+ itself, and the 11 prefix is reserved for SRAM and the Boot EPROM, the
+ 64K address range of the Peribox cards is on map values 10 111 xxx, which
+ means pages b8..bf. As the DSR (Device Service Routine, the card firmware)
+ is expected on logical addresses 4000-5FFF, this corresponds to the page 0xba.
+
+ A problem occurs with some 3rd party expansion cards which do not check
+ AMA/B/C=1. In a normal TI system, this would have no effect anyway, but
+ with the Geneve this leads to mirroring. The usual DSR space at 4000-5fff
+ which would be reachable via page 0xba is then mirrored on a number of
+ other pages:
- With 384 KiB SRAM:
- 917504 bytes of total memory
+ 10 xxx 010x = 82, 8a, 92, 9a, a2, aa, b2, ba
- The original 32 KiB SRAM memory needs to be expanded to 64 KiB for
- MDOS 2.50s and higher, or the system will lock up. Therefore the emulation
- default is 64 KiB.
+ Another block to take care of is 0xbc which covers 8000-9fff since this
+ area contains the speech synthesizer port at 9000/9400.
- The ultimate expansion is a 512 KiB SRAM circuit wired to the gate array
- to provide 48 pages of fast static RAM. This also requires to build an
- adapter for a larger socket. From the 512 KiB, only 384 KiB will be
- accessed, since the higher pages are hidden behind the EPROM pages.
+ Address map
+ ===========
- === Address map ===
p,q = page value bit (q = AMC, AMB, AMA)
c = address offset within 8 KiB page
p pqqq pppc cccc cccc cccc
- 0 0... .... .... .... .... on-board dram 512 KiB
-
+ 0 .... .... .... .... .... on-board bus (external drivers inactive)
+ 0 0... .... .... .... .... on-board DRAM 512 KiB
0 1... .... .... .... .... on-board future expansion 512 KiB or Memex with Genmod
- 1 00.. .... .... .... .... p-box AMA=0 (256 KiB)
- 1 010. .... .... .... .... p-box AMA=1 AMB=0 (128 KiB)
- 1 0110 .... .... .... .... p-box AMA=1 AMB=1 AMC=0 (64 KiB)
+ 1 0... .... .... .... .... external bus (p-box)
+ 1 0111 .... .... .... .... p-box (AMA/B/C=1)
+ 1 0111 000. .... .... .... address block 0xxx
+ 1 0111 001. .... .... .... address block 2xxx
+ 1 0111 010. .... .... .... address block 4xxx (DSR)
+ 1 0111 011. .... .... .... address block 6xxx
+ 1 0111 100. .... .... .... address block 8xxx (Speech at 0x9000)
+ 1 0111 101. .... .... .... address block axxx
+ 1 0111 110. .... .... .... address block cxxx
+ 1 0111 111. .... .... .... address block exxx
- 1 0111 00.. .... .... .... p-box address block 0xxx, 2xxx
- 1 0111 010. .... .... .... p-box address block 4xxx (DSR)
- 1 0111 011. .... .... .... p-box address block 6xxx
- 1 0111 100. .... .... .... p-box address block 8xxx (Speech at 0x9000)
- 1 0111 101. .... .... .... p-box address block axxx
- 1 0111 11.. .... .... .... p-box address block cxxx, exxx
+ 1 1... .... .... .... .... on-board bus
+ 1 10.. .... .... .... .... Future expansion (Ultimate SRAM expansion)
+ 1 1100 .... .... .... .... Future expansion (Ultimate SRAM expansion)
- 1 100. .... .... .... .... on-board sram (128K) -\
- 1 101. .... .... .... .... on-board sram (128K) --+- maximum SRAM expansion
- 1 1100 .... .... .... .... on-board sram (64K) --/
- 1 1101 0... .... .... .... on-board sram (32K) - additional 32 KiB required for MDOS 2.50s and higher
- 1 1101 1... .... .... .... on-board sram (32K) - standard setup
+ 1 1101 0... .... .... .... on-board sram (32K) - Optional 32 KiB expansion, 0 WS
+ 1 1101 1... .... .... .... on-board sram (32K) - stock 32 KiB SRAM, 0 WS
1 111. ..0. .... .... .... on-board boot1
1 111. ..1. .... .... .... on-board boot2
- The TI console (or more precise, the Flex Cable Interface) sets the AMA/B/C
- lines to 1. Most cards actually check for AMA/B/C=1. However, this decoding
- was forgotten in third party cards which cause the card address space
- to be mirrored. The usual DSR space at 4000-5fff which would be reachable
- via page 0xba is then mirrored on a number of other pages:
- 10 xxx 010x = 82, 8a, 92, 9a, a2, aa, b2, ba
+ Address operation
+ =================
- Another block to take care of is 0xbc which covers 8000-9fff since this
- area contains the speech synthesizer port at 9000/9400.
+ For DRAM access, a separate address bus between the Gate Array and the
+ DRAM circuits is used. The address bus has a width of 9 bits, which makes
+ it 18 bit for the whole address (row/column). Also, two CAS* lines are
+ used, selecting one set of DRAMs.
+
+ For SRAM access, the least significant two map value bits (AB1, AB2)
+ are prepended to the 13 bits of the offset from the logical address.
+ The next bit (AB0) controls the RAMEN* / RAMENX* lines.
+
+ For the EPROM access, the least significant bit of the map value is
+ prepended to the 13 bits of the offset from the logical address. This
+ yields a boot ROM size of 16K, mirrored on pages f0, f2, ..., fe, and
+ f1, f3, ..., ff. Bigger EPROMs (or flash memory, see PFM) require to use
+ the remaining bits AB1, AB0, and AMA.
+
+ The external bus is selected by the two most significant map bits 10.
+
+
+ GROM emulation and cartridge ROM space
+ ======================================
+
+ The Gate Array emulates a 64K GROM space in order to allow TI-99/4A
+ cartridge images to be run on the Geneve in TI mode. Also, two 8K ROM
+ pages are reserved to allow for emulating Extended Basic type cartridges.
- For the standard Geneve, only prefix 10 is routed to the P-Box. The Genmod
- modification wires these address lines to pins 8 and 9 in the P-Box as AMD and
- AME. This requires all cards to be equipped with an additional selection logic
- to detect AMD=0, AME=1. Otherwise these cards, although completely decoding the
- 19-bit address, would reappear at 512 KiB distances.
+ In TI mode, pages 38 to 3f constitute the 64K GROM space. Pages 36 and 37
+ are the two 8K ROM banks. All are located in DRAM with 1 WS. Page 36
+ (or page 37) is mapped to logical space 6000-7FFF, regardless of the
+ mapper value at 8003 (can be set to any value without effect).
+
+ CRU address >1EF8 determines the ROM size (1 or 2 banks):
+ 0 = 1 bank (page 36, fixed)
+ 1 = 2 banks (page 36 when writing a byte to 6000, 6004, ...,
+ page 37 when writing a byte to 6002, 6006, ...)
+
+ CRU address >1EFA write-protects 6000-6FFF when set to 0.
+ CRU address >1EFC write-protects 7000-7FFF when set to 0.
+ Both do not apply for 2-bank settings.
+
+ As with every page, the GROM pages may be mapped to any other memory
+ area as well so that they may be randomly accessed.
+
+ Unlike the real GROM, the GROM emulation allows free access to the whole
+ 8K of its page. Also, the emulation allows writing, so we essentially
+ have a GRAM emulation.
+
+ The Gate Array contains a 16-bit counter that represents the current
+ GROM address. It wraps at 8K boundaries (>3FFE->3FFF->2000->2001). Reading
+ from the GROM read port delivers the byte at the current address and
+ increases the counter. Writing to the GROM port stores the byte at that
+ address, respectively, and then increases the counter.
+
+ Reading the address counter delivers first the MSB, then on every
+ following access, the LSB. The counter itself contains the LSB in both
+ bytes after the first read operation. Thus, its value must be restored
+ after reading.
+
+ Setting the address counter copies its LSB to the MSB and then writes
+ the new byte into the LSB. After the second write (without intermediate
+ data transfer), the counter is increased by one.
+
+
+ Genmod expansion
+ ================
+
+ The objective of the Genmod is to allow the Geneve to access the full
+ 2 MiB physical address space, in conjunction with the MEMEX card that
+ must be plugged into the p-box. There are actually two lines in the box
+ that are unused; those are now defined as AMD and AME. They are located
+ on the p-box bus on pins 8 and 9.
+
+ Since the Gate Array does not output the first two address bits, they have
+ to be reconstructed by two GAL chips on a daughterboard that must be
+ soldered to the backside of the Gate Array.
+
+ When ROMEN is active, the on-board EPROM is accessed, and the external
+ bus is inactive.
+
+ The MEMEX card allows for using 0 waitstate accesses. This means that
+ the wait state generation for box accesses must be inhibited; this is
+ done by cutting the trace from the Gate Array pin READY to the PAL.
+
+ Some peripheral cards must now be modified to check for AMD and AME
+ as well, or they will be mirrored into other memory areas.
+ This GenMod feature is automatically applied to all peripheral cards in
+ this emulation.
+
+ The only remaining issue is that GROM access in the TI mode is under
+ full control of the Gate Array; it will always activate one of the DRAM
+ banks. To change this, the GA would need to be fully replaced. Instead,
+ the real GenMod contains a small box with two switches, which is also
+ emulation here:
- Genmod's double switch box is also emulated. There are two switches:
- Turbo mode: Activates or deactivates the wait state logic on the Geneve
board. This switch may be changed at any time.
- TI mode: Selects between the on-board memory, which is required
- for the GPL interpreter, and the external Memex memory. This switch
+ for the GROM access, and the external Memex memory. This switch
triggers a reset when changed.
- ===================
- Mapping
- ===================
-
- Logical address space: 64 KiB
+ Logical address space layout
+ ============================
Geneve mode
-----------
@@ -154,13 +288,13 @@
Mapper: 8000 - 8007 1000 0000 0000 0xxx
Keyboard: 8008 - 800F 1000 0000 0000 1...
Clock: 8010 - 801F 1000 0000 0001 xxxx
+ Sound: 8400 - 87FE 1000 01.. .... ...0
Speech: 9000 / 9400 1001 0w.. .... ...0
Grom: 9800 / 9802 1001 1w.. .... ..x0
9c00 / 9c02
- Physical address space
- ----------------------
- Address space size = 2 MiB
+ Physical address space layout
+ -----------------------------
Start End Phys.pages
000000 - 07FFFF 00-3F 512 KiB DRAM on-board
@@ -169,7 +303,9 @@
080000 - 0FFFFF 40-7F 512 KiB on-board expansion (never used)
100000 - 16FFFF 80-B7 448 KiB P-Box space (special cards, like MEMEX)
170000 - 17FFFF B8-BF 64 KiB P-Box space (current cards)
- 180000 - 1DFFFF C0-EF 384 KiB SRAM space on-board; stock Geneve comes with 32 KiB
+ 180000 - 1CFFFF C0-E7 Future expansion
+ 1D0000 - 1D7FFF E8-EB 32 KiB SRAM expansion
+ 1D8000 - 1DFFFF EC-EF 32 KiB stock SRAM
1E0000 - 1FFFFF F0-FF 128 KiB EPROM space; 16 KiB actually used, 8 mirrors
@@ -187,7 +323,7 @@
1E0000 - 1FFFFF F0-FF 128 KiB EPROM space; 16 KiB actually used, 8 mirrors
Waitstate handling
- ------------------
+ ==================
Waitstates are caused by a cleared READY line of the TMS9995 processor
during an external memory cycle. That means that waitstates have no effect
for operations within the on-chip memory, and only when an access to the
@@ -197,310 +333,210 @@
and the PAL 16R4, both lacking proper documentation. All of the following
numbers have been determined by experiments with the real machine.
- Waitstates are generated for:
- - memory-mapped devices (mapper, clock, keyboard): 1 WS
- - accesses to the peripheral expansion box: 1 WS
- - accesses to on-board DRAM: 1 WS
- - accesses to video: 15 WS
- - accesses to SRAM: 0 WS
+ Waitstates are generated for all accesses except for the SRAM in pages
+ E8..EF. Video accesses produce 15 waitstates, created by the counter
+ in the PAL. However, these video wait states are effective after the video
+ access has been completed. Wait states are not effective when the
+ execution is running in on-chip RAM.
+ Without additional wait states, the video access takes the usual 1 or 2 WS.
Additional waitstates are created when one of the CRU bits is set. In that
case, all delays are extended to 2 WS (including SRAM).
- Sound waitstates are somewhat unpredictable. It seems as if they depend
- on the clock of the sound chip; the READY line is pulled down until the
- next clock pulse, which may take some value between 18 CPU cycles and
- 30 CPU cycles.
-
- The gate array is able to create wait states for video accesses. However,
- these wait states are effective after the video access has been completed.
- Wait states are not effective when the execution is running in on-chip
- RAM. Additional wait states are requested by m_video_waitstates = true.
- Without additional wait states, the video access takes the usual 1 or 2 WS.
-
- Waitstate behavior (Nov 2013)
- Almost perfect. Only video read access from code in DRAM is too fast
- by one WS
-
- ==========================
- PFM expansion
- ==========================
-
- The "Programmable Flash Memory expansion" is a replacement for the boot
- EPROM.
-
- PFM: Original version, 128 KiB
- PFM+: Expansion of the original version, piggybacked, adds another 128KiB
- PFM512: Using an AT29C040 (not A), 512 KiB
-
- The PFM is visible as four banks in memory pages 0xF0 - 0xFF.
-
- Bank switching is done by four 9901 pins:
-
- 0028: LSB of bank number
- 003A: MSB of bank number
-
- Bank 0 is the boot code, while banks 1-3 can be used as flash drives
+ Sound waitstates depend on the clock of the sound chip; the READY line is
+ pulled down until the next clock pulse.
+
+
+ CRU map
+ =======
+ ---- TMS 9901 ----
+ 0000: flag Clock mode
+ 0002: int INTA* (pbox pin 17)
+ 0004: int Video interrupt
+ 0006: in Joystick button
+ 0008: in left
+ 000A: in right
+ 000C: in down
+ 000E: in up
+ 0010: int Keyboard scancode available
+ 0012: in (mirror of 003A)
+ 0014: in Left mouse button
+ 0016: in Real-time clock interrupt
+ 0018: in INTB* (pbox pin 18)
+ 001A: in (reflects 0032)
+ 001C: -
+ 001E: in (reflects 002E)
+ 0020: out Pbox reset
+ 0022: out Video reset
+ 0024: out Joystick select (0=Joystick 1, 1=Joystick 2)
+ 0026: -
+ 0028: out PFM bank switch LSB
+ 002A: out PFM output enable
+ 002C: out Keyboard reset
+ 002E: out System clock speed (external memory cycles)
+ 0030: -
+ 0032: out Video wait state enable
+ 0034: in (mirror of 0018)
+ 0036: in (mirror of 0016)
+ 0038: in (mirror of 0014)
+ 003A: out PFM bank switch MSB
+ 003C: in (mirror of 0010)
+ 003E: in (mirror of 000E)
+
+ ----Gate Array----
+ 13C0 - 13FE: Single step execution (not implemented, not available for most systems)
+
+ ----TMS9995-internal flag registers----
+ The values are all latched inside the CPU, but output values are visible
+ on the bus outside the CPU
+ 1EE0-1EE8, 1FDA: see tms9995.cpp
+ 1EEA: PAL/NTSC flag
+ 1EEC: (unused)
+ 1EEE: CapsLock flag
+ 1EF0: Keyboard clock
+ 1EF2: Keyboard shift register enable
+ 1EF4: Operation mode (native, GPL)
+ 1EF6: Memory mode (unmapped, mapped)
+ 1EF8: Cartridge size (0: 16 KiB, 1: 8 KiB)
+ 1EFA: Protect 6xxx
+ 1EFC: Protect 7xxx
+ 1EFE: Additional wait state per memory access
+
+ -------------------------------------------------------------------------
Michael Zapf, October 2011
February 2012: rewritten as class, restructured
Aug 2015: PFM added
+ Nov 2019: Extensive rewrite to provide a true emulation of the Gate Array
+ and the PAL, and also to allow for different kinds of external
+ keyboards.
***************************************************************************/
#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_LINES (1U<<7)
-#define LOG_SETTING (1U<<8)
-#define LOG_VIDEOWS (1U<<9)
-#define LOG_PFM (1U<<10)
-#define LOG_DECODE (1U<<11)
-#define LOG_INVADDR (1U<<12)
-
-// Minimum log should be settings and warnings
-#define VERBOSE ( LOG_SETTING | LOG_WARN )
+#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)
#include "genboard.h"
#include "logmacro.h"
-DEFINE_DEVICE_TYPE_NS(GENEVE_GATE_ARRAY, bus::ti99::internal, geneve_gate_array_device, "geneve_gate_array", "Geneve Gate Array")
-DEFINE_DEVICE_TYPE_NS(GENMOD_GATE_ARRAY, bus::ti99::internal, genmod_gate_array_device, "genmod_gate_array", "Geneve Mod Gate Array")
+DEFINE_DEVICE_TYPE(GENEVE_GATE_ARRAY, bus::ti99::internal::geneve_gate_array_device, "geneve_gate_array", "Geneve Gate Array")
+DEFINE_DEVICE_TYPE(GENMOD_DECODER, bus::ti99::internal::genmod_decoder_device, "genmod_decoder", "GenMod decoder circuit")
+DEFINE_DEVICE_TYPE(GENEVE_PAL, bus::ti99::internal::geneve_pal_device, "geneve_pal", "Geneve PAL circuit")
-namespace bus { namespace ti99 { namespace internal {
+namespace bus::ti99::internal {
geneve_gate_array_device::geneve_gate_array_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_boot_rom(0),
- m_gromwaddr_LSB(false),
- m_gromraddr_LSB(false),
+ m_have_waitstate(false),
+ m_have_extra_waitstate(false),
+ m_enable_extra_waitstates(false),
+ m_extready(true),
+ m_sndready(true),
+
m_grom_address(0),
- m_video_waitstates(false),
- m_extra_waitstates(false),
- m_ready_asserted(false),
- m_read_mode(false),
- m_debug_no_ws(false),
- m_geneve_mode(false),
- m_direct_mode(false),
- m_cartridge_size(0),
+ m_cartridge_banked(false),
m_cartridge_secondpage(false),
m_cartridge6_writable(false),
m_cartridge7_writable(false),
- m_pfm_bank(0),
- m_pfm_output_enable(false),
- m_sram_mask(0),
- m_sram_val(0),
- m_ready(*this),
+ m_load_lsb(false),
+
+ m_geneve_mode(false),
+ m_direct_mode(false),
+
m_keyint(*this),
- m_waitcount(0),
- m_video_waitcount(0),
+ m_keyb_clk(*this),
+ m_keyb_data(*this),
m_keyboard_shift_reg(0),
m_keyboard_last_clock(CLEAR_LINE),
m_keyboard_data_in(CLEAR_LINE),
m_shift_reg_enabled(false),
- m_cpu(*owner, "maincpu"),
- m_sound(*owner, TI_SOUNDCHIP_TAG),
- m_video(*owner, TI_VDP_TAG),
- m_rtc(*owner, GENEVE_CLOCK_TAG),
- m_sram(*this, GENEVE_SRAM_PAR_TAG),
- m_dram(*this, GENEVE_DRAM_PAR_TAG),
+
+ m_pal(*owner, GENEVE_PAL_TAG),
m_peribox(*owner, TI_PERIBOX_TAG),
- m_pfm512(*owner, GENEVE_PFM512_TAG),
- m_pfm512a(*owner, GENEVE_PFM512A_TAG),
- m_keyb_conn(*owner, GENEVE_KEYBOARD_CONN_TAG)
+
+ m_debug(false)
{
}
geneve_gate_array_device::geneve_gate_array_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
: geneve_gate_array_device(mconfig, GENEVE_GATE_ARRAY, tag, owner, clock)
{
- m_eprom = nullptr;
- m_pbox_prefix = 0x070000;
}
-genmod_gate_array_device::genmod_gate_array_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
- : geneve_gate_array_device(mconfig, GENMOD_GATE_ARRAY, tag, owner, clock),
- m_gm_timode(false),
- m_turbo(false)
+void geneve_gate_array_device::cru_sstep_write(offs_t offset, uint8_t data)
{
- m_eprom = nullptr;
- m_pbox_prefix = 0x170000;
+ // Single step
+ // 13c0 - 13fe: 0001 0011 11xx xxx0 (offset << 1)
+ LOGMASKED(LOG_WARN, "Single step not implemented; bit %d set to %d\n", offset & 0x001f, data);
}
-INPUT_CHANGED_MEMBER( geneve_gate_array_device::settings_changed )
+void geneve_gate_array_device::cru_ctrl_write(offs_t offset, uint8_t data)
{
- // Used when switching the boot ROMs during runtime, especially the PFM
- m_boot_rom = newval;
-}
-
-INPUT_CHANGED_MEMBER( genmod_gate_array_device::setgm_changed )
-{
- int number = int(param&0x03);
- int value = newval;
-
- switch (number)
+ // This is just mirroring the internal flags of the 9995
+ int bit = (offset & 0x000f);
+ switch (bit)
{
- case 1:
- // Turbo switch. May be changed at any time.
- LOGMASKED(LOG_SETTING, "Setting turbo flag to %d\n", value);
- m_turbo = (value!=0);
+ case 5:
+ // Unknown effect
+ LOGMASKED(LOG_CRU, "Set PAL flag = %02x\n", data);
+ // m_palvideo = (data!=0);
+ break;
+ case 7:
+ // Capslock flag; just to keep track of the current state
break;
- case 2:
- // TIMode switch. Causes reset when changed.
- LOGMASKED(LOG_SETTING, "Setting timode flag to %d\n", value);
- m_gm_timode = (value!=0);
- machine().schedule_hard_reset();
+ case 8:
+ LOGMASKED(LOG_CRUKEY, "Set keyboard clock = %02x\n", data);
+ set_keyboard_clock(data);
break;
- case 3:
- // Used when switching the boot ROMs during runtime, especially the PFM
- m_boot_rom = value;
+ case 9:
+ LOGMASKED(LOG_CRUKEY, "Enable keyboard shift reg = %02x\n", data);
+ enable_shift_register(data);
+ break;
+ case 10:
+ LOGMASKED(LOG_CRU, "Operation mode = %s\n", (data!=0)? "native" : "GPL");
+ m_geneve_mode = (data!=0);
+ break;
+ case 11:
+ LOGMASKED(LOG_CRU, "Addressing mode = %s\n", (data!=0)? "unmapped" : "mapped");
+ m_direct_mode = (data!=0);
+ break;
+ case 12:
+ LOGMASKED(LOG_CRU, "Cartridge ROM: %s\n", (data==0)? "banked" : "unbanked");
+ m_cartridge_banked = (data==0);
+ break;
+ case 13:
+ LOGMASKED(LOG_CRU, "Cartridge ROM 6000-6fff %s\n", (data!=0)? "writable" : "protected");
+ m_cartridge6_writable = (data!=0);
+ break;
+ case 14:
+ LOGMASKED(LOG_CRU, "Cartridge ROM 7000-7fff %s\n", (data!=0)? "writable" : "protected");
+ m_cartridge7_writable = (data!=0);
+ break;
+ case 15:
+ LOGMASKED(LOG_CRU, "Extra wait states %s\n", (data==0)? "enabled" : "disabled");
+ m_enable_extra_waitstates = (data==0);
break;
default:
- LOGMASKED(LOG_WARN, "Unknown setting %d ignored\n", number);
- }
-}
-
-/****************************************************************************
- GROM simulation. The Geneve board simulated GROM circuits within its gate
- array.
-*****************************************************************************/
-
-/*
- Simulates GROM. The real Geneve does not use GROMs but simulates them
- within the gate array. Unlike with real GROMs, no address wrapping occurs,
- and the complete 64K space is available.
-*/
-uint8_t geneve_gate_array_device::read_grom(offs_t offset)
-{
- uint8_t reply;
- if (offset & 0x0002)
- {
- // GROM address handling
- m_gromwaddr_LSB = false;
-
- if (m_gromraddr_LSB)
- {
- reply = m_grom_address & 0xff;
- m_gromraddr_LSB = false;
- }
- else
- {
- reply = (m_grom_address >> 8) & 0xff;
- m_gromraddr_LSB = true;
- }
- }
- else
- {
- // GROM data handling
- // GROMs are stored in pages 38..3f
- int physpage = 0x38;
- reply = m_dram->pointer()[(physpage<<13) + m_grom_address];
- m_grom_address = (m_grom_address + 1) & 0xffff;
- m_gromraddr_LSB = m_gromwaddr_LSB = false;
- }
- return reply;
-}
-
-/*
- Simulates GROM. The real Geneve does not use GROMs but simulates them
- within the gate array.
-*/
-void geneve_gate_array_device::write_grom(offs_t offset, uint8_t data)
-{
- if (offset & 0x0002)
- {
- // set address
- m_gromraddr_LSB = false;
- if (m_gromwaddr_LSB)
- {
- m_grom_address = (m_grom_address & 0xff00) | data;
- m_grom_address = (m_grom_address + 1) & 0xffff;
- m_gromwaddr_LSB = false;
- }
- else
- {
- m_grom_address = (m_grom_address & 0x00ff) | ((uint16_t)data<<8);
- m_gromwaddr_LSB = true;
- }
- }
- else
- { // write GPL data
- // The Geneve GROM simulator allows for GROM writing (verified with a real system)
- int physpage = 0x38;
- m_dram->pointer()[(physpage<<13) + m_grom_address] = data;
-
- m_grom_address = (m_grom_address + 1) & 0xffff;
- m_gromraddr_LSB = m_gromwaddr_LSB = false;
- }
-}
-
-void geneve_gate_array_device::set_wait(int min)
-{
- if (m_extra_waitstates && min < 2) min = 2;
-
- // if we still have video wait states, do not set this counter
- // (or it will assert READY when expiring)
- if (m_video_waitcount > min) return;
-
- // need one more pass so that READY will be asserted again
- m_waitcount = min + 1;
- if (m_waitcount > 1)
- {
- LOGMASKED(LOG_LINES, "Pulling down READY line for %d cycles\n", min);
- m_ready(CLEAR_LINE);
- m_ready_asserted = false;
- }
-}
-
-void geneve_gate_array_device::set_video_waitcount(int min)
-{
- if (m_debug_no_ws) return;
- m_video_waitcount = min;
-}
-
-void geneve_gate_array_device::set_geneve_mode(bool geneve)
-{
- LOGMASKED(LOG_SETTING, "Setting Geneve mode = %d\n", geneve);
- m_geneve_mode = geneve;
-}
-
-void geneve_gate_array_device::set_direct_mode(bool direct)
-{
- LOGMASKED(LOG_SETTING, "Setting direct mode = %d\n", direct);
- m_direct_mode = direct;
-}
-
-void geneve_gate_array_device::set_cartridge_size(int size)
-{
- LOGMASKED(LOG_SETTING, "Setting cartridge size to %d\n", size);
- m_cartridge_size = size;
-}
-
-void geneve_gate_array_device::set_cartridge_writable(int base, bool write)
-{
- LOGMASKED(LOG_SETTING, "Cartridge %04x space writable = %d\n", base, write);
- if (base==0x6000) m_cartridge6_writable = write;
- else m_cartridge7_writable = write;
-}
-
-void geneve_gate_array_device::set_video_waitstates(bool wait)
-{
- // Tends to be called repeatedly
- if (m_video_waitstates != wait)
- {
- LOGMASKED(LOG_SETTING, "Setting video waitstates = %d\n", wait);
+ break;
}
- m_video_waitstates = wait;
-}
-
-void geneve_gate_array_device::set_extra_waitstates(bool wait)
-{
- LOGMASKED(LOG_SETTING, "Setting extra waitstates = %d\n", wait);
- m_extra_waitstates = wait;
}
/******************************************************************
@@ -530,9 +566,9 @@ void geneve_gate_array_device::set_extra_waitstates(bool wait)
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_conn->clock_write_from_mb(state);
+ m_keyb_clk(state);
}
/*
@@ -543,7 +579,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);
@@ -562,7 +598,7 @@ void geneve_gate_array_device::shift_reg_changed()
// The level of the data line is the inverse of the rightmost bit of
// the shift register. This means that once the start bit reaches that
// position, it will pull down the data line and stop the transfer.
- m_keyb_conn->data_write_from_mb(1 - (m_keyboard_shift_reg & 1));
+ m_keyb_data(1 - (m_keyboard_shift_reg & 1));
m_keyint((m_keyboard_shift_reg & 1)? ASSERT_LINE : CLEAR_LINE);
if (m_keyboard_shift_reg & 1)
LOGMASKED(LOG_KEYBOARD, "Scan code complete; raise interrupt, hold down data line\n");
@@ -574,7 +610,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);
@@ -591,474 +627,246 @@ 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;
}
-/************************************************************************
- Called by the address map
-************************************************************************/
-
-/*
- Read a byte via the data bus. The decoding has already been done in the
- SETADDRESS method, and we re-use the values stored there to quickly
- access the appropriate component.
-*/
-uint8_t geneve_gate_array_device::readm(offs_t offset)
-{
- uint8_t value = 0;
+// sysspeed has no effect for vwait/speed
- decdata *dec;
- decdata debug;
+// TODO: Video write timing
- // For the debugger, do the decoding here with no wait states
- if (machine().side_effects_disabled())
- {
- if (m_cpu->is_onchip(offset)) return m_cpu->debug_read_onchip_memory(offset&0xff);
- dec = &debug;
- m_debug_no_ws = true;
- dec->offset = offset;
- decode_logical(true, dec);
- if (dec->function == MUNDEF)
- {
- map_address(m_read_mode, dec);
- decode_physical(dec);
- decode_mod(dec);
- }
- if (dec->function == MBOX)
- {
- m_peribox->memen_in(ASSERT_LINE);
- m_peribox->setaddress_dbin(dec->physaddr, true);
- }
- }
- else
- {
- // Use the values found in the setaddress phase
- dec = &m_decoded;
- m_debug_no_ws = false;
- }
-
- // Logical space
-
- switch (dec->function)
- {
- case MLVIDEO:
- if (!machine().side_effects_disabled())
- {
- value = m_video->read(dec->offset>>1);
- LOGMASKED(LOG_READ, "Read video %04x -> %02x\n", dec->offset, value);
- // Video wait states are created *after* the access
- // Accordingly, they have no effect when execution is in onchip RAM
- if (m_video_waitstates) set_video_waitcount(15);
- }
- break;
-
- case MLMAPPER:
- // mapper
- value = m_map[dec->offset & 0x0007];
- LOGMASKED(LOG_READ, "Read mapper %04x -> %02x\n", dec->offset, value);
- break;
-
- case MLKEY:
- // key
- value = m_keyboard_shift_reg>>1;
- LOGMASKED(LOG_KEYBOARD, "Read keyboard -> %02x\n", value);
- break;
-
- case MLCLOCK:
- // clock
- // Tests on the real machine showed that the upper nibble is 0xf
- // (probably because of the location at f130-f13f?)
- // In TI mode, however, the upper nibble is 1, unless we read 801f,
- // in which case the nibble is 2. Here the location is 8010-801f.
- // Needs more investigation. We might as well ignore this,
- // as the high nibble is obviously undefined and takes some past
- // value floating around.
- value = m_rtc->read(dec->offset & 0x000f);
- if (m_geneve_mode) value |= 0xf0;
- else value |= ((dec->offset & 0x000f)==0x000f)? 0x20 : 0x10;
- LOGMASKED(LOG_READ, "Read clock %04x -> %02x\n", dec->offset, value);
- break;
-
- case MLGROM:
- // grom simulation
- // ++++ ++-- ---- ---+
- // 1001 1000 0000 00x0
- if (!machine().side_effects_disabled()) value = read_grom(dec->offset);
- LOGMASKED(LOG_READ, "Read GROM %04x -> %02x\n", dec->offset, value);
- break;
-
- case MLSOUND:
- value = 0;
- break;
-
- case MPDRAM:
- // DRAM. One wait state.
- value = m_dram->pointer()[dec->physaddr];
- LOGMASKED(LOG_READ, "Read DRAM %04x (%06x) -> %02x\n", dec->offset, dec->physaddr, value);
- break;
-
- case MPEXP:
- // On-board memory expansion for standard Geneve (never used)
- LOGMASKED(LOG_READ, "Read on-board expansion (not available) %06x -> 00\n", dec->physaddr);
- value = 0;
- break;
-
- case MPEPROM:
- // 1 111. ..xx xxxx xxxx xxxx on-board eprom (16K)
- // mirrored for f0, f2, f4, ...; f1, f3, f5, ...
- value = boot_rom(dec->physaddr);
- break;
-
- case MPSRAM:
- if ((dec->physaddr & m_sram_mask)==m_sram_val)
- {
- value = m_sram->pointer()[dec->physaddr & ~m_sram_mask];
- LOGMASKED(LOG_READ, "Read SRAM %04x (%06x) -> %02x\n", dec->offset, dec->physaddr, value);
- }
- else
- {
- LOGMASKED(LOG_INVADDR, "Decoded as SRAM read, but no SRAM at %06x\n", dec->physaddr);
- value = 0;
- }
- // Return in any case
- break;
-
- case MBOX:
- // Route everything else to the P-Box
- // 0x000000-0x07ffff for the stock Geneve (AMC,AMB,AMA,A0 ...,A15)
- // 0x000000-0x1fffff for the GenMod.(AME,AMD,AMC,AMB,AMA,A0 ...,A15)
-
- m_peribox->readz(dec->physaddr, &value);
- m_peribox->memen_in(CLEAR_LINE);
- LOGMASKED(LOG_READ, "Read P-Box %04x (%06x) -> %02x\n", dec->offset, dec->physaddr, value);
- break;
-
- default:
- LOGMASKED(LOG_WARN, "Unknown decoding result type: %d\n", dec->function);
- break;
- }
- return value;
-}
-
-void geneve_gate_array_device::writem(offs_t offset, uint8_t data)
-{
- decdata *dec;
- decdata debug;
-
- // For the debugger, do the decoding here with no wait states
- if (machine().side_effects_disabled())
- {
- // TODO: add debug_write_onchip_memory
- dec = &debug;
- m_debug_no_ws = true;
- dec->offset = offset;
- decode_logical(false, dec);
- if (dec->function == MUNDEF)
- {
- map_address(m_read_mode, dec);
- decode_physical(dec);
- decode_mod(dec);
- }
- if (dec->function == MBOX)
- {
- m_peribox->memen_in(ASSERT_LINE);
- m_peribox->setaddress_dbin(dec->physaddr, false);
- }
- }
- else
- {
- // Use the values found in the setaddress phase
- dec = &m_decoded;
- m_debug_no_ws = false;
- }
-
-
- // Logical space
-
- switch (dec->function)
- {
- case MLVIDEO:
- // video
- // ++++ ++++ ++++ ---+
- // 1111 0001 0000 .cc0
- // Initialize waitstate timer
-
- if (!machine().side_effects_disabled())
- {
- m_video->write(dec->offset>>1, data);
- LOGMASKED(LOG_WRITE, "Write video %04x <- %02x\n", offset, data);
- // See above
- if (m_video_waitstates) set_video_waitcount(15);
- }
- break;
-
- case MLMAPPER:
- // mapper
- m_map[dec->offset & 0x0007] = data;
- LOGMASKED(LOG_WRITE, "Write mapper %04x <- %02x\n", offset, data);
- break;
-
- case MLCLOCK:
- // clock
- // ++++ ++++ ++++ ----
- m_rtc->write(dec->offset & 0x000f, data);
- LOGMASKED(LOG_WRITE, "Write clock %04x <- %02x\n", offset, data);
- break;
-
- case MLSOUND:
- // sound
- // ++++ ++++ ++++ ---+
- m_sound->write(data);
- LOGMASKED(LOG_WRITE, "Write sound <- %02x\n", data);
- break;
-
- case MLGROM:
- // The GROM simulator is only available in TI Mode
- write_grom(dec->offset, data);
- LOGMASKED(LOG_WRITE, "Write GROM %04x <- %02x\n", offset, data);
- break;
-
- // Physical space
- case MPDRAM:
- // DRAM write
- m_dram->pointer()[dec->physaddr] = data;
- LOGMASKED(LOG_WRITE, "Write DRAM %04x (%06x) <- %02x\n", offset, dec->physaddr, data);
- break;
-
- case MPEXP:
- // On-board memory expansion for standard Geneve
- // Actually never built, so we show it as unmapped
- LOGMASKED(LOG_WRITE, "Write on-board expansion (not available) %06x <- %02x\n", dec->physaddr, data);
- break;
-
- case MPEPROM:
- // 1 111. ..xx xxxx xxxx xxxx on-board eprom (16K)
- // mirrored for f0, f2, f4, ...; f1, f3, f5, ...
- // Ignore EPROM write (unless PFM)
- if (m_boot_rom != GENEVE_EPROM) write_to_pfm(dec->physaddr, data);
- else
- LOGMASKED(LOG_INVADDR, "Write EPROM %04x (%06x) <- %02x, ignored\n", offset, dec->physaddr, data);
- break;
-
- case MPSRAM:
- if ((dec->physaddr & m_sram_mask)==m_sram_val)
- {
- m_sram->pointer()[dec->physaddr & ~m_sram_mask] = data;
- LOGMASKED(LOG_WRITE, "Write SRAM %04x (%06x) <- %02x\n", offset, dec->physaddr, data);
- }
- else
- {
- LOGMASKED(LOG_INVADDR, "Decoded as SRAM write, but no SRAM at %06x\n", dec->physaddr);
- }
- break;
-
- case MBOX:
- // Route everything else to the P-Box
- LOGMASKED(LOG_WRITE, "Write P-Box %04x (%06x) <- %02x\n", offset, dec->physaddr, data);
- m_peribox->write(dec->physaddr, data);
- m_peribox->memen_in(CLEAR_LINE);
- break;
-
- default:
- LOGMASKED(LOG_WARN, "Unknown decoding result type: %d\n", dec->function);
- break;
- }
-}
+/*****************************************************************
+ Decoding functions
+******************************************************************/
-const geneve_gate_array_device::logentry_t geneve_gate_array_device::s_logmap[7] =
+const geneve_gate_array_device::logentry_t geneve_gate_array_device::s_logmap[10] =
{
{ 0xf100, 0x000e, 0x8800, 0x03fe, 0x0400, MLVIDEO, "video" },
{ 0xf110, 0x0007, 0x8000, 0x0007, 0x0000, MLMAPPER, "mapper" },
{ 0xf118, 0x0007, 0x8008, 0x0007, 0x0000, MLKEY, "keyboard" },
- { 0xf120, 0x000e, 0x8400, 0x03fe, 0x0000, MLSOUND, "sound" },
+ { 0xf120, 0x000e, 0x8400, 0x01ff, 0x0000, MLSOUND, "sound" },
+ { 0x0000, 0x0000, 0x8600, 0x01ff, 0x0000, MLEXT, "external bus" },
{ 0xf130, 0x000f, 0x8010, 0x000f, 0x0000, MLCLOCK, "clock" },
- { 0x0000, 0x0000, 0x9000, 0x03fe, 0x0400, MBOX, "speech (in P-Box)" },
- { 0x0000, 0x0000, 0x9800, 0x03fe, 0x0400, MLGROM, "GROM" },
+ { 0x0000, 0x0000, 0x9000, 0x03fe, 0x0400, MLEXT, "speech (ext. bus)" },
+ { 0x0000, 0x0000, 0x9800, 0x03fc, 0x0400, MLGROM, "GROM data" },
+ { 0x0000, 0x0000, 0x9802, 0x03fc, 0x0400, MLGROMAD, "GROM address" },
+ { 0x0000, 0x0000, 0x6000, 0x1fff, 0x0000, MLCARTROM, "Cartridge ROM" }
};
-void geneve_gate_array_device::decode_logical(bool reading, geneve_gate_array_device::decdata* dec)
+void geneve_gate_array_device::decode_logical(geneve_gate_array_device::decdata* dec)
{
dec->function = MUNDEF;
- dec->physaddr = m_pbox_prefix | dec->offset;
- dec->wait = 1;
+ int index = -1;
- int i = 0;
- while (i < 7)
+ for (int i = 0; (i < 10) && (index == -1); i++)
{
if (m_geneve_mode)
{
// Skip when genbase is 0
if ((s_logmap[i].genbase != 0) && ((dec->offset & ~s_logmap[i].genmask) == s_logmap[i].genbase))
- break;
+ index = i;
}
else
{
- if (reading)
+ if (dec->read)
{
if ((dec->offset & ~s_logmap[i].timask) == s_logmap[i].tibase)
- break;
+ index = i;
}
else
{
if ((dec->offset & ~s_logmap[i].timask) == (s_logmap[i].tibase | s_logmap[i].writeoff))
- break;
+ index = i;
}
}
- i++;
}
- if (i != 7)
+
+ if (index != -1)
{
- LOGMASKED(LOG_DECODE, "Decoded as %s: %04x\n", s_logmap[i].description, dec->offset);
- dec->function = s_logmap[i].function;
+ LOGMASKED(LOG_DECODE, "Decoded as %s: %04x\n", s_logmap[index].description, dec->offset);
+ dec->function = s_logmap[index].function;
+ }
+
+ // Handle write operations to the cartridge ROM
+ if (dec->function == MLCARTROM && !dec->read)
+ {
+ if (m_cartridge_banked) dec->function = MLCARTBANK;
+ else
+ {
+ if ((((dec->offset & 0x1000)==0) && !m_cartridge6_writable)
+ || (((dec->offset & 0x1000)!=0) && !m_cartridge7_writable))
+ {
+ dec->function = CARTPROT;
+ LOGMASKED(LOG_WARN, "Writing to protected cartridge space %04x ignored\n", dec->offset);
+ }
+ }
}
}
-void geneve_gate_array_device::map_address(bool reading, geneve_gate_array_device::decdata* dec)
+/*
+ Look up the mapper value (page) for the given logical address.
+ Cartridges need special handling.
+*/
+void geneve_gate_array_device::get_page(geneve_gate_array_device::decdata* dec)
{
int logpage = (dec->offset & 0xe000) >> 13;
- int physpage = 0;
+ dec->physpage = 0;
// Determine physical address
- if (m_direct_mode) physpage = 0xf8; // points to boot eprom
+ if (m_direct_mode) dec->physpage = 0xf8; // points to boot eprom
else
{
- // TI mode, accessing logical addresses 6000-7fff
- if (!m_geneve_mode && logpage==3)
+ if (dec->function == MLCARTROM)
+ dec->physpage = (m_cartridge_banked && m_cartridge_secondpage)? 0x37 : 0x36;
+ else
{
- if (reading)
- {
- physpage = (m_cartridge_size==0x4000 && m_cartridge_secondpage)? 0x37 : 0x36;
- }
+ if (dec->function == MLGROM)
+ dec->physpage = ((m_grom_address >> 13) & 0x07) | 0x38;
else
{
- // Emulate the cartridge bank switch feature of Extended Basic
- // TODO: Is this the right place? Or writem()?
- if (m_cartridge_size==0x4000)
+ if (dec->function == MLEXT)
{
- m_cartridge_secondpage = ((dec->offset & 0x0002)!=0);
- LOGMASKED(LOG_WRITE, "Set cartridge page %02x\n", m_cartridge_secondpage);
+ dec->physpage = 0xb8 | logpage;
}
else
- {
- // writing into cartridge rom space (no bank switching)
- if ((((dec->offset & 0x1000)==0x0000) && !m_cartridge6_writable)
- || (((dec->offset & 0x1000)==0x1000) && !m_cartridge7_writable))
- {
- LOGMASKED(LOG_WARN, "Writing to protected cartridge space %04x ignored\n", dec->offset);
- }
- else
- // TODO: Check whether secondpage is really ignored
- physpage = 0x36;
- }
+ dec->physpage = m_map[logpage];
}
}
- else
- physpage = m_map[logpage];
}
- dec->physaddr = ((physpage << 13) | (dec->offset & 0x1fff)) & 0x1fffff;
}
-const geneve_gate_array_device::physentry_t geneve_gate_array_device::s_physmap[4] =
+const geneve_gate_array_device::physentry_t geneve_gate_array_device::s_physmap[8] =
{
- { 0x000000, 0x07ffff, MPDRAM, 1, "DRAM" },
- { 0x080000, 0x07ffff, MPEXP, 1, "on-board expansion" },
- { 0x1e0000, 0x01ffff, MPEPROM, 0, "EPROM" },
- { 0x180000, 0x07ffff, MPSRAM, 0, "SRAM" }
+ { 0x00, 0x3f, MPDRAM, "DRAM" },
+ { 0x40, 0x3f, MPEXP, "Future exp (on-board)" },
+ { 0xc0, 0x1f, MPSRAMU, "Ultimate SRAM exp" },
+ { 0xe0, 0x07, MPSRAMU, "Ultimate SRAM exp" },
+ { 0xe8, 0x03, MPSRAMX, "SRAM exp" },
+ { 0xec, 0x03, MPSRAM, "SRAM" },
+ { 0xf0, 0x0f, MPEPROM, "Boot ROM/PFM" },
+ { 0x80, 0x7f, MBOX, "external" } // catch-all
};
+/*
+ Try to decode the physical address.
+*/
void geneve_gate_array_device::decode_physical(geneve_gate_array_device::decdata* dec)
{
- dec->function = MUNDEF;
-
- int i = 0;
- while (i < 4)
- {
- if ((dec->physaddr & ~s_physmap[i].mask) == s_physmap[i].base)
- break;
- i++;
- }
- if (i != 4)
+ // Search the map
+ if (dec->function == MUNDEF || dec->function == MLCARTROM || dec->function == MLGROM)
{
- LOGMASKED(LOG_DECODE, "Decoded as %s: %06x\n", s_physmap[i].description, dec->physaddr);
- dec->function = s_physmap[i].function;
- dec->wait = s_physmap[i].wait;
- }
- else
- {
- // Route everything else to the P-Box
- dec->function = MBOX;
- dec->wait = 1;
+ if (dec->function == MLGROM)
+ {
+ // If map byte 6 is not set to 03, ignore the access
+ // This seems to be a safety feature, or a glitch in the design
+ // of the Gate array.
+ if (m_map[6] != 0x03)
+ {
+ dec->function = MUNDEF;
+ return;
+ }
+
+ // GROM is actually DRAM; substitute the address and update the address counter
+ // The page has already been set in get_page
+ LOGMASKED(LOG_GROM, "GROM address = %04x\n", m_grom_address);
+ dec->offset = m_grom_address; // Do not wipe the GROM number
+ // Auto-increment here (not in clock_in, as we have two clock cycles by wait states)
+ increase_grom_address();
+ return;
+ }
+
+ // Search for the matching page interval. Cartridge space will be decoded as DRAM.
+ bool found = false;
+ for (int i = 0; (i < 8) && !found; i++)
+ {
+ if ((dec->physpage & ~s_physmap[i].mask) == s_physmap[i].base)
+ {
+ dec->function = s_physmap[i].function;
+ LOGMASKED(LOG_DECODE, "Decoded as %s, page %02x\n", s_physmap[i].description, dec->physpage);
+ found = true;
+ }
+ }
+
+ if (!found)
+ LOGMASKED(LOG_DECODE, "Unmapped address %06x\n", (get_prefix(0xff) | (dec->offset & 0x1fff)) & 0x1fffff);
}
}
-void genmod_gate_array_device::decode_mod(geneve_gate_array_device::decdata* dec)
+void geneve_gate_array_device::increase_grom_address()
{
- // GenMod mode
- // The TI Mode switch activates the DRAM on the board (1 WS)
- // for the first 512K (000000-07ffff)
- if (((dec->function == MPDRAM) && !m_gm_timode) || dec->function==MPSRAM || dec->function==MPEXP)
+ if (!m_debug)
{
- dec->function = MBOX;
+ m_grom_address = ((m_grom_address + 1) & 0x1fff) | (m_grom_address & 0xe000);
+ m_load_lsb = false;
}
-
- if ((dec->function != MPDRAM) && m_turbo)
- dec->wait = 0;
}
/*
- Boot ROM handling, from EPROM or PFM.
+ Are we addressing DRAM?
*/
-uint8_t geneve_gate_array_device::boot_rom(offs_t offset)
+bool geneve_gate_array_device::accessing_dram()
{
- uint8_t value;
- int pfmaddress = (offset & 0x01ffff) | (m_pfm_bank<<17);
+ decdata* dec = (m_debug)? &m_decdebug : &m_decoded;
+ return accessing_dram_s(dec->function);
+}
- switch (m_boot_rom)
- {
- case GENEVE_EPROM:
- value = m_eprom[offset & 0x003fff];
- LOGMASKED(LOG_READ, "Read EPROM %04x -> %02x\n", offset & 0x003fff, value);
- return value;
- case GENEVE_PFM512:
- value = m_pfm512->read(pfmaddress);
- break;
- case GENEVE_PFM512A:
- value = m_pfm512a->read(pfmaddress);
- break;
- default:
- LOGMASKED(LOG_WARN, "Illegal mode for reading boot ROM: %d\n", m_boot_rom);
- value = 0;
- }
+bool geneve_gate_array_device::accessing_dram_s(int function)
+{
+ return (function == MPDRAM) || (function == MLGROM) || (function == MLCARTROM);
+}
+
+bool geneve_gate_array_device::accessing_sram_s(int function)
+{
+ return (function == MPSRAM) || (function == MPSRAMX) || (function == MPSRAMU);
+}
- if (!m_pfm_output_enable) value = 0;
- LOGMASKED(LOG_PFM, "Reading from PFM at address %05x -> %02x\n", pfmaddress, value);
- return value;
+bool geneve_gate_array_device::accessing_devs_s(int function)
+{
+ return (function == MLMAPPER) || (function == MLKEY) || (function == MLCLOCK) || (function == MLGROMAD);
}
-void geneve_gate_array_device::write_to_pfm(offs_t offset, uint8_t data)
+bool geneve_gate_array_device::accessing_grom()
{
- // Nota bene: The PFM must be write protected on startup, or the RESET
- // of the 9995 will attempt to write the return vector into the flash EEPROM
- int address = (offset & 0x01ffff) | (m_pfm_bank<<17);
- LOGMASKED(LOG_PFM, "Writing to PFM at address %05x <- %02x\n", address, data);
+ decdata* dec = (m_debug)? &m_decdebug : &m_decoded;
+ return (dec->function == MLGROM);
+}
- switch (m_boot_rom)
+bool geneve_gate_array_device::accessing_box_s(int function, bool genmod)
+{
+ return (function == MLEXT) || (function == MBOX) || (genmod && function == MPEXP);
+}
+
+/*
+ The Gate Array has a private address bus to the DRAM.
+*/
+offs_t geneve_gate_array_device::get_dram_address()
+{
+ offs_t physaddr = 0;
+ decdata* dec = (m_debug)? &m_decdebug : &m_decoded;
+ int addr13 = dec->offset & 0x1fff;
+
+ // Cartridge access is also done in DRAM; the pages are fixed to
+ // 36, 37 (ROM), 38...3f (GROM), regardless of the mapper.
+
+ if (dec->function == MLGROM)
{
- case GENEVE_PFM512:
- m_pfm512->write(address, data);
- break;
- case GENEVE_PFM512A:
- m_pfm512a->write(address, data);
- break;
- default:
- LOGMASKED(LOG_WARN, "Illegal mode for writing to PFM: %d\n", m_boot_rom);
+ physaddr = (0x38 << 13) | dec->offset;
+ // The GROM address counter is updated in decode_physical
+ }
+ else
+ {
+ if (dec->function == MPDRAM || dec->function == MLCARTROM)
+ {
+ physaddr = (get_prefix(0x3f) | addr13) & 0x7ffff;
+ }
+ else
+ LOGMASKED(LOG_WARN, "Unknown decoding %d for DRAM\n", dec->function);
}
+ return physaddr;
}
-
/*
Accept the address passed over the address bus and decode it appropriately.
This decoding will later be used in the READ/WRITE member functions. Also,
@@ -1066,116 +874,217 @@ void geneve_gate_array_device::write_to_pfm(offs_t offset, uint8_t data)
*/
void geneve_gate_array_device::setaddress(offs_t address, uint8_t busctrl)
{
- LOGMASKED(LOG_DETAIL, "setaddress = %04x\n", address);
- m_debug_no_ws = false;
- m_decoded.offset = address;
+ LOGMASKED(LOG_ADDRESS, "setaddress = %04x%s\n", address, m_debug? " (debug)" : "");
+ decdata& dec = (m_debug)? m_decdebug : m_decoded;
- m_read_mode = ((busctrl & TMS99xx_BUS_DBIN)!=0);
+ dec.offset = address;
+ dec.read = ((busctrl & TMS99xx_BUS_DBIN)!=0);
- decode_logical(m_read_mode, &m_decoded);
- if (m_decoded.function == MUNDEF)
- {
- map_address(m_read_mode, &m_decoded);
- decode_physical(&m_decoded);
- decode_mod(&m_decoded);
- }
-
- set_wait(m_decoded.wait);
+ decode_logical(&dec);
+ get_page(&dec);
+ decode_physical(&dec);
- if (m_decoded.function == MBOX)
+ if (!m_debug)
{
- m_peribox->memen_in(ASSERT_LINE);
- m_peribox->setaddress_dbin(m_decoded.physaddr, m_read_mode);
+ m_have_extra_waitstate = m_enable_extra_waitstates;
+ m_have_waitstate = (dec.function != MPSRAM && dec.function != MPSRAMX) || m_have_extra_waitstate;
}
}
/*
- The mapper is connected to the clock line in order to operate
- the wait state counter.
- The wait counter is decremented on each rising clock edge; when 0, the
- READY line is asserted. However, there is a second counter which is used for
- video wait states.
- The READY line must be asserted when the wait counter reaches 0, but must be
- cleared immediately again if the video counter has not reached 0.
- (See comments at the file header: The additional video wait states do not
- affect the video access itself but become effective after the access; if
- the code runs on the chip, these wait states are ignored.)
+ 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)
{
- if (state==ASSERT_LINE)
+ // Falling CLK
+ if (state == CLEAR_LINE)
{
- // Rising edge
- if (!m_ready_asserted)
- {
- if (m_waitcount > 0)
- {
- m_waitcount--;
- if (m_waitcount == 0)
- {
- LOGMASKED(LOG_CLOCK, "clock, READY asserted\n");
- m_ready(ASSERT_LINE);
- m_ready_asserted = true;
- }
- else
- {
- LOGMASKED(LOG_CLOCK, "clock\n");
- }
- }
- else
- {
- if (m_video_waitcount > 0)
- {
- m_video_waitcount--;
- if (m_video_waitcount == 0)
- {
- LOGMASKED(LOG_CLOCK, "clock, READY asserted after video\n");
- m_ready(ASSERT_LINE);
- m_ready_asserted = true;
- }
- else
- {
- LOGMASKED(LOG_CLOCK, "vclock, ew=%d\n", m_video_waitcount);
- }
- }
- }
- }
+ if (!m_have_extra_waitstate)
+ m_have_waitstate = false;
+ else
+ m_have_extra_waitstate = false;
}
- else
+}
+
+/*
+ READY line from the peribox. Together with the sndready and the READY output
+ of the Gate Array itself, this forms a wired AND.
+*/
+void geneve_gate_array_device::extready_in(int state)
+{
+ LOGMASKED(LOG_READY, "External READY = %d\n", state);
+ m_extready = (state==ASSERT_LINE);
+}
+
+void geneve_gate_array_device::sndready_in(int state)
+{
+ LOGMASKED(LOG_READY, "Sound READY = %d\n", state);
+ m_sndready = (state==ASSERT_LINE);
+}
+
+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;
+}
+
+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;
+}
+
+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;
+}
+
+int geneve_gate_array_device::ramen_out()
+{
+ decdata* dec = (m_debug)? &m_decdebug : &m_decoded;
+ return (dec->function == MPSRAM)? ASSERT_LINE : CLEAR_LINE;
+}
+
+int geneve_gate_array_device::ramenx_out()
+{
+ decdata* dec = (m_debug)? &m_decdebug : &m_decoded;
+ return (dec->function == MPSRAMX)? ASSERT_LINE : CLEAR_LINE;
+}
+
+int geneve_gate_array_device::ramenu_out()
+{
+ decdata* dec = (m_debug)? &m_decdebug : &m_decoded;
+ return (dec->function == MPSRAMU)? ASSERT_LINE : CLEAR_LINE;
+}
+
+int geneve_gate_array_device::rtcen_out()
+{
+ decdata* dec = (m_debug)? &m_decdebug : &m_decoded;
+ return (dec->function == MLCLOCK)? ASSERT_LINE : CLEAR_LINE;
+}
+
+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;
+}
+
+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;
+}
+
+// After setaddress, pull down READY if
+// - we have an extra waitstate OR
+// - we do not access SRAM(X) OR
+// - extready = 0
+
+// In Genmod, pull down READY if
+// - we have an extra waitstate OR
+// - we access the box and have turbo==0 OR
+// - we access DRAM and have timode==1 OR
+// - extready = 0
+
+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
+ // return ((m_decoded.function == MPSRAM || m_decoded.function == MPSRAMX) && !m_have_extra_waitstate)? ASSERT_LINE : CLEAR_LINE;
+ return (m_have_waitstate || m_have_extra_waitstate || !m_extready || !m_sndready)? CLEAR_LINE : ASSERT_LINE;
+}
+
+
+/**********************************************************
+ Gate Array-internal functions
+***********************************************************/
+
+/*
+ Changes the value of the parameter if one of the functions applies.
+*/
+void geneve_gate_array_device::readz(uint8_t& value)
+{
+ decdata* dec = (m_debug)? &m_decdebug : &m_decoded;
+ uint8_t lsb = 0;
+
+ switch (dec->function)
{
- // Falling edge
- // Do we have video wait states? In that case, clear the line again
- if ((m_waitcount == 0) && (m_video_waitcount > 0) && m_ready_asserted)
+ case MLMAPPER:
+ value = m_map[dec->offset & 0x0007];
+ LOGMASKED(LOG_READ, "Read mapper %04x -> %02x\n", dec->offset, value);
+ break;
+ case MLKEY:
+ value = m_keyboard_shift_reg>>1;
+ LOGMASKED(LOG_READ, "Read keyboard %04x -> %02x\n", dec->offset, value);
+ break;
+ case MLGROMAD:
+ if (!m_debug) // don't let the debugger mess with the address counter
{
- LOGMASKED(LOG_CLOCK, "clock, READY cleared for video\n");
- m_ready(CLEAR_LINE);
- m_ready_asserted = false;
+ value = (m_grom_address & 0xff00)>>8;
+ lsb = (m_grom_address & 0xff);
+ m_grom_address = lsb << 8 | lsb;
+ m_load_lsb = false;
+ LOGMASKED(LOG_READ, "Read GROM address %04x -> %02x\n", dec->offset, value);
}
+ break;
+ case MLCARTBANK:
+ break;
+ default:
+ break;
}
}
/*
- PFM expansion: Setting the bank.
+ Internal functions of the Gate Array. Returns without changes if none
+ of the function applies.
*/
-WRITE_LINE_MEMBER( geneve_gate_array_device::pfm_select_lsb )
+void geneve_gate_array_device::write(uint8_t data)
{
- if (state==ASSERT_LINE) m_pfm_bank |= 1;
- else m_pfm_bank &= 0xfe;
- LOGMASKED(LOG_PFM, "Setting bank (l) = %d\n", m_pfm_bank);
-}
+ decdata* dec = (m_debug)? &m_decdebug : &m_decoded;
-WRITE_LINE_MEMBER( geneve_gate_array_device::pfm_select_msb )
-{
- if (state==ASSERT_LINE) m_pfm_bank |= 2;
- else m_pfm_bank &= 0xfd;
- LOGMASKED(LOG_PFM, "Setting bank (u) = %d\n", m_pfm_bank);
+ switch (dec->function)
+ {
+ case MLMAPPER:
+ m_map[dec->offset & 0x0007] = data;
+ // LOGMASKED(LOG_MAPPER, "Write mapper %04x <- %02x\n", dec->offset, data);
+ LOGMASKED(LOG_MAPPER, "Set %04x mapper[%02x %02x %02x %02x %02x %02x %02x %02x]\n",
+ dec->offset, m_map[0], m_map[1], m_map[2], m_map[3], m_map[4], m_map[5], m_map[6], m_map[7]);
+ break;
+ case MLGROMAD:
+ if (!m_debug) // don't let the debugger mess with the address counter
+ {
+ m_grom_address = (m_grom_address << 8 | data) & 0xffff;
+ if (m_load_lsb) increase_grom_address();
+ else m_load_lsb = true;
+ LOGMASKED(LOG_GROM, "Write GROM address %04x <- %02x\n", dec->offset, data);
+ }
+ break;
+ case MLCARTBANK:
+ m_cartridge_secondpage = ((dec->offset & 0x0002)!=0);
+ LOGMASKED(LOG_WRITE, "Set cartridge bank %04x <- %02x\n", dec->offset, data);
+ break;
+ case MLKEY:
+ LOGMASKED(LOG_WRITE, "Write to keyboard ignored\n");
+ break;
+ default:
+ break;
+ }
}
-WRITE_LINE_MEMBER( geneve_gate_array_device::pfm_output_enable )
+/*
+ Address lines that the Gate Array offers. They reflect the 8 bits of
+ the mapper byte. AME and AMD are only used by GenMod.
+ (AME, AMD,) AMC, AMB, AMA, AB0, AB1, AB2
+*/
+int geneve_gate_array_device::get_prefix(int lines)
{
- // Negative logic
- m_pfm_output_enable = (state==CLEAR_LINE);
- LOGMASKED(LOG_PFM, "PFM output %s\n", m_pfm_output_enable? "enable" : "disable");
+ decdata* dec = (m_debug)? &m_decdebug : &m_decoded;
+ return (dec->physpage & lines) << 13;
}
//====================================================================
@@ -1184,109 +1093,443 @@ WRITE_LINE_MEMBER( geneve_gate_array_device::pfm_output_enable )
void geneve_gate_array_device::device_start()
{
- m_ready.resolve_safe();
- m_keyint.resolve_safe();
-
m_geneve_mode = false;
m_direct_mode = true;
// State registration
- save_item(NAME(m_gromwaddr_LSB));
- save_item(NAME(m_gromraddr_LSB));
+ save_item(NAME(m_have_extra_waitstate));
+ save_item(NAME(m_enable_extra_waitstates));
+ save_item(NAME(m_extready));
+ save_item(NAME(m_sndready));
+
save_item(NAME(m_grom_address));
- save_item(NAME(m_video_waitstates));
- save_item(NAME(m_extra_waitstates));
- save_item(NAME(m_ready_asserted));
- save_item(NAME(m_read_mode));
- save_item(NAME(m_debug_no_ws));
- save_item(NAME(m_geneve_mode));
- save_item(NAME(m_direct_mode));
- save_item(NAME(m_cartridge_size));
+ save_item(NAME(m_cartridge_banked));
save_item(NAME(m_cartridge_secondpage));
save_item(NAME(m_cartridge6_writable));
save_item(NAME(m_cartridge7_writable));
+ save_item(NAME(m_load_lsb));
+
+ save_item(NAME(m_geneve_mode));
+ save_item(NAME(m_direct_mode));
+
save_pointer(NAME(m_map), 8);
+
+ save_item(NAME(m_decoded.read));
save_item(NAME(m_decoded.function));
save_item(NAME(m_decoded.offset));
- save_item(NAME(m_decoded.physaddr));
- save_item(NAME(m_boot_rom));
- save_item(NAME(m_pfm_bank));
- save_item(NAME(m_pfm_output_enable));
- save_item(NAME(m_sram_mask));
- save_item(NAME(m_sram_val));
- save_item(NAME(m_waitcount));
- save_item(NAME(m_video_waitcount));
+ save_item(NAME(m_decoded.physpage));
+
+ save_item(NAME(m_keyboard_shift_reg));
+ save_item(NAME(m_shift_reg_enabled));
}
void geneve_gate_array_device::common_reset()
{
- m_extra_waitstates = false;
- m_video_waitstates = true;
- m_read_mode = false;
- m_waitcount = 0;
- m_video_waitcount = 0;
- m_ready_asserted = true;
+ m_have_extra_waitstate = false;
+ m_enable_extra_waitstates = false;
- m_geneve_mode =false;
- m_direct_mode = true;
- m_cartridge_size = 0x4000;
+ m_grom_address = 0;
+ m_cartridge_banked = false;
m_cartridge_secondpage = false;
m_cartridge6_writable = false;
m_cartridge7_writable = false;
- m_grom_address = 0;
- m_pfm_bank = 0;
- m_pfm_output_enable = true;
+
+ m_geneve_mode =false;
+ m_direct_mode = true;
// Clear map
for (auto & elem : m_map) elem = 0;
-
- // Check which boot EPROM we are using (or PFM)
- m_boot_rom = machine().root_device().ioport("BOOTROM")->read();
- m_eprom = machine().root_device().memregion("maincpu")->base();
-
- // Allow for configuring the VRAM size
- uint32_t videoram = (machine().root_device().ioport("VRAM")->read()!=0)? 0x30000 : 0x20000;
- downcast<v99x8_device &>(*m_video.target()).set_vram_size(videoram);
- LOGMASKED(LOG_SETTING, "Video RAM set to %d KiB\n", videoram / 1024);
}
void geneve_gate_array_device::device_reset()
{
common_reset();
+}
- // SRAM is only separately handled for the standard Geneve; Genmod uses
- // the Memex instead
- switch (machine().root_device().ioport("SRAM")->read())
+/* ========================================================================
+
+ The PAL circuit on the Geneve main board. It is the actual waitstate
+ generator, and its task is to control the READY line depending on the
+ accessed device, and to control the outgoing MEMEN* and WE* lines into
+ the peribox.
+
+ The chip is a PAL16R4ACN
+
+ Pin Dir Meaning
+ ---------------------
+ 1 in CLK (assert=H)
+ 2 in WE* (write)
+ 3 in READYIN (from Gate Array and sound chip)
+ 4 in CSR* (Video read)
+ 5 in CRU bit 23 (>002E) ("System clock speed")
+ 6 in MEMEN* (memory access)
+ 7 in DBEN* (external data bus enable)
+ 8 in (Gate Array bit 36)
+ 9 in CSW* (video write)
+ 10 GND
+ 11 in OE*, hardwired to H
+ 12 out WE*
+ 13 out MEMEN*
+ 14 (output of FF1, disabled by pin 11)
+ 15 (output of FF2, disabled by pin 11)
+ 16 (output of FF3, disabled by pin 11)
+ 17 (output of FF4, disabled by pin 11)
+ 18 out READYOUT
+ 19 in VDPWAITEN
+ 20 Vcc
+
+ ======================================================================== */
+
+geneve_pal_device::geneve_pal_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
+ : device_t(mconfig, GENEVE_PAL, tag, owner, clock),
+ m_pin3(true),
+ m_pin4(true),
+ m_pin5(true),
+ m_pin9(true),
+ m_pin19(false),
+ m_pin14d(false),m_pin14q(false),
+ m_pin15d(false),m_pin15q(false),
+ m_pin16d(false),m_pin16q(false),
+ m_pin17d(false),m_pin17q(false),
+ m_prev_ready(CLEAR_LINE),
+ m_peribox(*owner, TI_PERIBOX_TAG),
+ m_ready(*this)
+{
+}
+
+/*
+ READY input from the Gate Array.
+*/
+void geneve_pal_device::gaready_in(int state)
+{
+ bool prev = m_pin3;
+ m_pin3 = (state==ASSERT_LINE);
+ if (prev != m_pin3)
{
-/* 1 100. .... .... .... .... on-board sram (128K) -+
- 1 101. .... .... .... .... on-board sram (128K) -+-- maximum SRAM expansion
- 1 1100 .... .... .... .... on-board sram (64K) --+
- 1 1101 0... .... .... .... on-board sram (32K) - additional 32 KiB required for MDOS 2.50s and higher
- 1 1101 1... .... .... .... on-board sram (32K) - standard setup
+ LOGMASKED(LOG_LINES, "READY(ga) <- %d\n", state);
+ // When GAREADY=L, the video lines have immediate effect on the ready line
+ set_ready();
+ }
+}
+
+/*
+ Video read (ASSERT=low).
*/
- case 0: // 32 KiB
- m_sram_mask = 0x1f8000;
- m_sram_val = 0x1d8000;
- break;
- case 1: // 64 KiB
- m_sram_mask = 0x1f0000;
- m_sram_val = 0x1d0000;
- break;
- case 2: // 384 KiB (actually 512 KiB, but the EPROM masks the upper 128 KiB)
- m_sram_mask = 0x180000;
- m_sram_val = 0x180000;
- break;
+void geneve_pal_device::csr_in(int state)
+{
+ bool prev = m_pin4;
+ m_pin4 = (state==CLEAR_LINE);
+ if (prev != m_pin4)
+ {
+ LOGMASKED(LOG_LINES, "CSR <- %d\n", state);
+ set_ready();
}
}
-void genmod_gate_array_device::device_reset()
+/*
+ Video write (ASSERT=low).
+*/
+void geneve_pal_device::csw_in(int state)
{
- common_reset();
- LOGMASKED(LOG_SETTING, "Using GenMod modification\n");
- m_turbo = ((machine().root_device().ioport("GENMODDIPS")->read() & GENEVE_GM_TURBO)!=0);
- m_gm_timode = ((machine().root_device().ioport("GENMODDIPS")->read() & GENEVE_GM_TIM)!=0);
+ bool prev = m_pin9;
+ m_pin9 = (state==CLEAR_LINE);
+ if (prev != m_pin9)
+ {
+ LOGMASKED(LOG_LINES, "CSW <- %d\n", state);
+ set_ready();
+ }
+}
+
+/*
+ Memory enable (ASSERT=low); pass through
+*/
+void geneve_pal_device::memen(int state)
+{
+ LOGMASKED(LOG_LINES, "MEMEN -> %d\n", state);
+ m_peribox->memen_in(state);
+}
+
+/*
+ Write external mem cycles (0=long, 1=short)
+ System clock speed (PAL pin 5). (ASSERT=high)
+ The function from the equations could not be verified on a real machine.
+ This function seems to have no effect. So either the equations are
+ wrong, or something else is going on.
+*/
+void geneve_pal_device::sysspeed(int state)
+{
+ bool prev = m_pin5;
+ m_pin5 = (state == ASSERT_LINE);
+ if (prev != m_pin5)
+ {
+ LOGMASKED(LOG_SETTING, "System clock speed set to %d\n", state);
+ set_ready();
+ }
+}
+
+/*
+ Write vdp wait cycles (1=add 14 cycles, 0=add none)
+ see above for waitstate handling
+*/
+void geneve_pal_device::vwaiten(int state)
+{
+ bool prev = m_pin19;
+ m_pin19 = (state==ASSERT_LINE);
+ if (prev != m_pin19)
+ {
+ LOGMASKED(LOG_SETTING, "Video wait states %s\n", (state!=0)? "enabled" : "disabled");
+ set_ready();
+ }
+}
+
+/*
+ Clock input. This controls the state of the waitstate counter.
+*/
+void geneve_pal_device::clock_in(int state)
+{
+ LOGMASKED(LOG_CLOCK, "CLK%s\n", state? "?" : "?");
+ // Set the FF
+ if (state==ASSERT_LINE)
+ {
+ m_pin14q = m_pin14d;
+ m_pin15q = m_pin15d;
+ m_pin16q = m_pin16d;
+ m_pin17q = m_pin17d;
+ set_ready();
+ }
+}
+
+/*
+ Called from clock_in and input pin functions. Set the state of the
+ READY line. Since this is the only source for the state, we always have
+ 0 or 1, but no Z state.
+
+ FIXME: The video write wait state handling is still not correct. Unfortunately,
+ the equations of the PAL did not help, in contrast, the problem got worse.
+ Problem: After initiating a video write (CSW*=0), the READY line must
+ remain high for the next falling clock edge so that the CPU can complete
+ the command cycle. By these equations, the READY line immediately goes
+ low when the clock line rises, and thus on the falling edge, a wait state
+ is produced.
+ The effect is that in the real machine, if all code runs in on-chip memory,
+ a video write does not cause any wait state, while in this emulation, it
+ always causes the full 14 cycles of wait states. In rare situations, this
+ may heavily slow down the processing.
+*/
+void geneve_pal_device::set_ready()
+{
+ line_state ready_line;
+
+ // Original equations from the PAL
+/*
+ ready_line = ((!m_pin4 && !m_pin3) ||
+ (!m_pin9 && !m_pin3) ||
+ (m_pin9 && m_pin4 && !m_pin14q) ||
+ (m_pin5 && m_pin4 && !m_pin15q) ||
+ (m_pin5 && m_pin4 && !m_pin16q) ||
+ (m_pin9 && m_pin4 && !m_pin17q))? CLEAR_LINE : ASSERT_LINE;
+
+ m_pin17d = (m_pin9 && m_pin4 && !m_pin17q && !m_pin14q) ||
+ (m_pin9 && m_pin4 && !m_pin17q && !m_pin15q) ||
+ (m_pin9 && m_pin4 && !m_pin17q && !m_pin16q) ||
+ (m_pin9 && m_pin4 && m_pin3 && m_pin16q && m_pin15q && m_pin14q) ||
+ (!m_pin19 && !m_pin17q && !m_pin14q) ||
+ (!m_pin19 && !m_pin17q && !m_pin15q) ||
+ (!m_pin19 && !m_pin17q && !m_pin16q) ||
+ (m_pin3 && !m_pin19 && m_pin16q && m_pin15q && m_pin14q);
+
+ m_pin16d = (m_pin9 && m_pin4 && m_pin17q && !m_pin16q) ||
+ (m_pin9 && m_pin4 && !m_pin17q && m_pin16q) ||
+ (m_pin9 && m_pin4 && m_pin16q && m_pin15q && m_pin14q) ||
+ !m_pin19;
+
+ m_pin15d = (m_pin9 && m_pin4 && m_pin15q && m_pin14q) ||
+ (m_pin9 && m_pin4 && !m_pin16q && m_pin15q) ||
+ (m_pin9 && m_pin4 && !m_pin17q && m_pin15q) ||
+ (m_pin9 && m_pin4 && m_pin17q && m_pin16q && !m_pin15q) ||
+ !m_pin19;
+
+ m_pin14d = (m_pin9 && m_pin4 && m_pin14q) ||
+ (m_pin9 && m_pin4 && m_pin17q && m_pin16q && m_pin15q) ||
+ !m_pin19;
+*/
+
+ // Simplified equations for better performance
+
+ bool pin4_9 = m_pin9 && m_pin4;
+
+ ready_line = ((!m_pin3 && !pin4_9) ||
+ (pin4_9 && (!m_pin14q || !m_pin17q)) ||
+ (m_pin5 && m_pin4 && (!m_pin15q || !m_pin16q)))? CLEAR_LINE : ASSERT_LINE;
+
+ m_pin17d = (pin4_9 && !m_pin17q && (!m_pin14q || !m_pin15q || !m_pin16q)) ||
+ (((pin4_9 && m_pin3) || (m_pin3 && !m_pin19)) && m_pin16q && m_pin15q && m_pin14q) ||
+ (!m_pin19 && !m_pin17q && (!m_pin14q || !m_pin15q || !m_pin16q));
+
+ m_pin16d = (pin4_9 && m_pin17q && !m_pin16q) ||
+ (pin4_9 && !m_pin17q && m_pin16q) ||
+ (pin4_9 && m_pin16q && m_pin15q && m_pin14q) ||
+ !m_pin19;
+
+ m_pin15d = (pin4_9 && m_pin15q && (m_pin14q || !m_pin16q || !m_pin17q)) ||
+ (pin4_9 && m_pin17q && m_pin16q && !m_pin15q) ||
+ !m_pin19;
+
+ m_pin14d = (pin4_9 && m_pin14q) ||
+ (pin4_9 && m_pin17q && m_pin16q && m_pin15q) ||
+ !m_pin19;
+
+ if (m_prev_ready != ready_line)
+ {
+ LOGMASKED(LOG_WAIT, "READY = %d (%d %d %d %d, %d %d %d, %d %d)\n", ready_line, m_pin14d, m_pin15d, m_pin16d, m_pin17d, m_pin3, m_pin4, m_pin9, m_pin5, m_pin19);
+ m_prev_ready = ready_line;
+ }
+ m_ready(ready_line);
}
+void geneve_pal_device::device_start()
+{
+ save_item(NAME(m_pin3));
+ save_item(NAME(m_pin4));
+ save_item(NAME(m_pin5));
+ save_item(NAME(m_pin9));
+ save_item(NAME(m_pin19));
+ save_item(NAME(m_pin17q));
+ save_item(NAME(m_pin16q));
+ save_item(NAME(m_pin15q));
+ save_item(NAME(m_pin14q));
+}
-} } } // end namespace bus::ti99::internal
+/********************************************************************
+ Genmod daughterboard, soldered to the back of the Gate Array
+ The main task of the Genmod is to route all memory accesses to the
+ Memex card in the peripheral box.
+
+ Also, the Genmod may inhibit wait states by flipping on the TURBO switch.
+
+ The TIMODE switch blocks the box access for the DRAM space (pages
+ 00-3F) so that the GROM emulator remains functional. Without this GROM
+ emulation (which is hardwired to the board DRAM), the TI-99/4A
+ software cannot run.
+
+********************************************************************/
+
+genmod_decoder_device::genmod_decoder_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
+ : device_t(mconfig, GENMOD_DECODER, tag, owner, clock),
+ m_debug(false),
+ m_turbo(false),
+ m_timode(false),
+ m_function(0),
+ m_function_debug(0),
+ m_page(0),
+ m_page_debug(0),
+ m_gaready(0),
+ m_extready(ASSERT_LINE),
+ m_sndready(ASSERT_LINE)
+{
+}
+
+void genmod_decoder_device::set_function(int func, int page)
+{
+ if (m_debug)
+ {
+ m_function_debug = func;
+ m_page_debug = page;
+ }
+ else
+ {
+ m_function = func; // values from logical map or physical map
+ m_page = page;
+ }
+}
+
+void genmod_decoder_device::gaready_in(int state)
+{
+ m_gaready = state;
+}
+
+/*
+ READY line from the box. Do not ignore this line, as it is important
+ for device operation.
+*/
+void genmod_decoder_device::extready_in(int state)
+{
+ m_extready = state;
+}
+
+/*
+ READY line from the sound chip.
+*/
+void genmod_decoder_device::sndready_in(int state)
+{
+ m_sndready = state;
+}
+
+/*
+ Wait state generation
+ 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.
+*/
+int genmod_decoder_device::gaready_out()
+{
+ int func = m_debug? m_function_debug : m_function;
+ int page = m_debug? m_page_debug : m_page;
+
+ // External or sound READY must always be respected
+ if (m_extready==CLEAR_LINE || m_sndready==CLEAR_LINE) return CLEAR_LINE;
+
+ // When TURBO is off, pass through
+ if (!m_turbo) return m_gaready;
+
+ // When accessing internal devices, pass through
+ if (geneve_gate_array_device::accessing_devs_s(func)) return m_gaready;
+
+ // In TURBO mode:
+ // When TIMODE is active, and we access the DRAM area, pass through
+ if (m_timode && ((page & 0xc0)==0)) return m_gaready;
+
+ // When accessing SRAM, SRAMX, EPROM, or page BA, pass through
+ if ((((page & 0xf0)==0xf0) || ((page&0xf8)==0xe8) || page == 0xba)) return m_gaready;
+
+ // else no wait states
+ return ASSERT_LINE;
+}
+
+/*
+ Genmod accesses the box also for the DRAM range, but only if timode==0.
+ (This includes GROM and cartridge ROM access.)
+ Note: It is not sufficient to check for the page area; we need to check
+ the select lines (via the static functions).
+*/
+int genmod_decoder_device::dben_out()
+{
+ int func = m_debug? m_function_debug : m_function;
+
+ if (geneve_gate_array_device::accessing_box_s(func, true))
+ return ASSERT_LINE;
+
+ if (!m_timode && geneve_gate_array_device::accessing_dram_s(func))
+ return ASSERT_LINE;
+
+ // This needs to be verified with a real device.
+ if (geneve_gate_array_device::accessing_sram_s(func))
+ return ASSERT_LINE;
+
+ return CLEAR_LINE;
+}
+
+void genmod_decoder_device::device_start()
+{
+ save_item(NAME(m_debug));
+ save_item(NAME(m_turbo));
+ save_item(NAME(m_timode));
+ save_item(NAME(m_function));
+ save_item(NAME(m_function_debug));
+ save_item(NAME(m_page));
+ save_item(NAME(m_page_debug));
+ save_item(NAME(m_gaready));
+ save_item(NAME(m_extready));
+ save_item(NAME(m_sndready));
+}
+} // end namespace bus::ti99::internal
diff --git a/src/devices/bus/ti99/internal/genboard.h b/src/devices/bus/ti99/internal/genboard.h
index 3e927ab70df..bf9f3ef4c27 100644
--- a/src/devices/bus/ti99/internal/genboard.h
+++ b/src/devices/bus/ti99/internal/genboard.h
@@ -15,7 +15,6 @@
#pragma once
-#include "bus/ti99/ti99defs.h"
#include "bus/ti99/peb/peribox.h"
#include "video/v9938.h"
#include "cpu/tms9900/tms9995.h"
@@ -23,7 +22,6 @@
#include "machine/mm58274c.h"
#include "machine/at29x.h"
#include "machine/ram.h"
-#include "bus/pc_kbd/pc_kbdc.h"
enum
{
@@ -39,60 +37,102 @@ enum
};
#define GENEVE_GATE_ARRAY_TAG "gatearray"
+#define GENMOD_DECODER_TAG "genmod"
+#define GENEVE_PAL_TAG "pal"
#define GENEVE_MOUSE_TAG "gmouse"
-#define GENEVE_CLOCK_TAG "mm58274c"
#define GENEVE_PFM512_TAG "pfm512"
#define GENEVE_PFM512A_TAG "pfm512a"
-#define GENEVE_KEYBOARD_CONN_TAG "keybconn"
-#define GENEVE_SRAM_TAG "sram"
-#define GENEVE_DRAM_TAG "dram"
-#define GENEVE_SRAM_PAR_TAG ":sram"
-#define GENEVE_DRAM_PAR_TAG ":dram"
-
-namespace bus { namespace ti99 { namespace internal {
+namespace bus::ti99::internal {
/*****************************************************************************/
+class geneve_pal_device;
+class genmod_decoder_device;
+
class geneve_gate_array_device : public device_t
{
+ // friend class genmod_decoder_device;
+
public:
geneve_gate_array_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
- void set_geneve_mode(bool geneve);
- void set_direct_mode(bool direct);
- void set_cartridge_size(int size);
- void set_cartridge_writable(int base, bool write);
- void set_video_waitstates(bool wait);
- void set_extra_waitstates(bool wait);
-
- uint8_t readm(offs_t offset);
- void writem(offs_t offset, uint8_t data);
+ // Set the internal state and output lines according to the address
void setaddress(offs_t offset, uint8_t busctrl);
- DECLARE_INPUT_CHANGED_MEMBER( settings_changed );
-
- DECLARE_WRITE_LINE_MEMBER( clock_in );
- DECLARE_WRITE_LINE_MEMBER( dbin_in );
+ // Access to Gate Array-internal registers. Depends on the previous
+ // call of setaddress
+ // - Mapper
+ // - Keyboard
+ // - Grom address counter
+ // - Cartridge bank switch
+ void readz(uint8_t& value);
+ void write(uint8_t data);
+
+ // Inputs
+ 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
+ int csr_out();
+ int csw_out();
+ int rtcen_out();
+
+ int romen_out(); // Boot EPROM access
+ int ramen_out(); // Stock SRAM access
+ int ramenx_out(); // 32K expanded SRAM access
+ int ramenu_out(); // Full 384K SRAM access
+
+ int snden_out();
+ int dben_out();
+ int gaready_out();
+
+ int get_prefix(int lines);
+ bool accessing_dram();
+ static bool accessing_dram_s(int function);
+ static bool accessing_sram_s(int function);
+ static bool accessing_box_s(int function, bool genmod);
+ static bool accessing_devs_s(int function);
+
+ bool accessing_grom();
+ 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 );
-
- // PFM support
- DECLARE_WRITE_LINE_MEMBER( pfm_select_lsb );
- DECLARE_WRITE_LINE_MEMBER( pfm_select_msb );
- DECLARE_WRITE_LINE_MEMBER( pfm_output_enable );
-
- auto ready_cb() { return m_ready.bind(); }
+ 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(); }
-protected:
+ // Miscellaneous
+ void set_debug(bool deb) { m_debug = deb; }
+ bool geneve_mode() { return m_geneve_mode; }
+ int get_function() { return m_debug? m_decdebug.function : m_decoded.function; }
+
+private:
geneve_gate_array_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock);
void common_reset();
+ // Mapper function
+ typedef struct
+ {
+ bool read; // Reading
+ int function; // must be a fundamental type to be saveable
+ offs_t offset; // Logical address
+ int physpage; // Physical page
+ } decdata;
+
+ // Functions
+ void decode_logical(decdata* dec);
+ void get_page(decdata* dec);
+ void decode_physical(decdata* dec);
+
/*
Constants for mapper decoding. Naming scheme:
M=Mapper, L=Logical space; P=Physical space
@@ -106,60 +146,55 @@ protected:
MLKEY,
MLSOUND,
MLCLOCK,
+ MLEXT,
MLGROM,
+ MLGROMAD,
+ MLCARTROM,
+ MLCARTBANK,
MPDRAM,
MPEXP,
MPEPROM,
MPSRAM,
+ MPSRAMX,
+ MPSRAMU,
+ MBOX,
- MBOX
- } decfunct_t;
+ CARTPROT
- // Mapper function
- typedef struct
- {
- int function; // must be a fundamental type to be saveable
- offs_t offset; // Logical address
- offs_t physaddr; // Physical address
- int wait; // Wait states
- } decdata;
-
- uint8_t* m_eprom;
- int m_pbox_prefix;
- int m_boot_rom;
+ } decfunct_t;
-private:
void device_start() override;
- virtual void device_reset() override;
-
- // GROM simulation
- bool m_gromwaddr_LSB;
- bool m_gromraddr_LSB;
- int m_grom_address;
- uint8_t read_grom(offs_t offset);
- void write_grom(offs_t offset, uint8_t data);
-
- // wait states
- void set_wait(int min);
- void set_video_waitcount(int min);
- bool m_video_waitstates;
- bool m_extra_waitstates;
- bool m_ready_asserted;
+ virtual void device_reset() override ATTR_COLD;
- bool m_read_mode;
+ // Wait state creation
+ bool m_have_waitstate;
+ bool m_have_extra_waitstate;
+ bool m_enable_extra_waitstates;
+ bool m_extready;
+ bool m_sndready;
- bool m_debug_no_ws;
- bool m_geneve_mode;
- bool m_direct_mode;
- int m_cartridge_size;
+ // Cartridge and GROM support
+ int m_grom_address;
+ bool m_cartridge_banked;
bool m_cartridge_secondpage;
bool m_cartridge6_writable;
bool m_cartridge7_writable;
+ bool m_load_lsb;
+ void increase_grom_address();
+
+ // Global modes
+ bool m_geneve_mode;
+ bool m_direct_mode;
+
+ // Mapper file
int m_map[8];
// The result of decoding
decdata m_decoded;
+ decdata m_decdebug;
+
+ // ====== Decoding ============
// Static decoder entry for the logical space
// Not all entries apply for native mode, e.g. there is no GROM in native
@@ -181,82 +216,117 @@ private:
// There are no differences between native mode and TI mode.
typedef struct
{
- offs_t base; // Base address
+ offs_t base; // Base page
int mask; // Bits that also match this entry
decfunct_t function; // Decoded function
- int wait; // Wait states
const char* description; // Good for logging
} physentry_t;
+ // Tables
static const geneve_gate_array_device::logentry_t s_logmap[];
static const geneve_gate_array_device::physentry_t s_physmap[];
- void decode_logical(bool reading, decdata* dec);
- void map_address(bool reading, decdata* dec);
- void decode_physical(decdata* dec);
- // This is the hook for Genmod. The normal Geneve just does nothing here.
- virtual void decode_mod(decdata* dec) { };
+ // Keyboard support
+ devcb_write_line m_keyint;
+ devcb_write_line m_keyb_clk;
+ devcb_write_line m_keyb_data;
+ uint16_t m_keyboard_shift_reg;
+ line_state m_keyboard_last_clock;
+ line_state m_keyboard_data_in;
+ bool m_shift_reg_enabled;
+ void shift_reg_changed();
- // PFM mod (0 = none, 1 = AT29C040, 2 = AT29C040A)
- uint8_t boot_rom(offs_t offset);
- void write_to_pfm(offs_t offset, uint8_t data);
- int m_pfm_bank;
- bool m_pfm_output_enable;
+ // Devices
+ required_device<geneve_pal_device> m_pal;
+ required_device<bus::ti99::peb::peribox_device> m_peribox;
- // SRAM access
- int m_sram_mask;
- int m_sram_val;
+ // Emulation-specific: Is the debugger active?
+ bool m_debug;
+};
- // Ready line to the CPU
- devcb_write_line m_ready;
+/*****************************************************************************/
- // Keyboard interrupt
- devcb_write_line m_keyint;
+/*
+ PAL circuit, controlling the READY line to the CPU and MEMEN/WE
+ to the peribox
+*/
- // Counter for the wait states.
- int m_waitcount;
- int m_video_waitcount;
+class geneve_pal_device : public device_t
+{
+public:
+ geneve_pal_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
- // Keyboard support
- uint16_t m_keyboard_shift_reg;
- line_state m_keyboard_last_clock;
- line_state m_keyboard_data_in;
- bool m_shift_reg_enabled;
- void shift_reg_changed();
+ 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);
- // Devices
- required_device<tms9995_device> m_cpu;
- required_device<sn76496_base_device> m_sound;
- required_device<v9938_device> m_video;
- required_device<mm58274c_device> m_rtc;
- required_device<ram_device> m_sram;
- required_device<ram_device> m_dram;
+ auto ready_cb() { return m_ready.bind(); }
- required_device<bus::ti99::peb::peribox_device> m_peribox;
+private:
+ void device_start() override ATTR_COLD;
+ void set_ready();
+
+ // Pins
+ bool m_pin3;
+ bool m_pin4;
+ bool m_pin5;
+ bool m_pin9;
+ bool m_pin19;
+ bool m_pin14d,m_pin14q;
+ bool m_pin15d,m_pin15q;
+ bool m_pin16d,m_pin16q;
+ bool m_pin17d,m_pin17q;
+
+ // Debugging
+ int m_prev_ready;
- required_device<at29c040_device> m_pfm512;
- required_device<at29c040a_device> m_pfm512a;
+ required_device<bus::ti99::peb::peribox_device> m_peribox;
- required_device<pc_kbdc_device> m_keyb_conn;
+ // Ready line to the CPU
+ devcb_write_line m_ready;
};
-class genmod_gate_array_device : public geneve_gate_array_device
+class genmod_decoder_device : public device_t
{
public:
- genmod_gate_array_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
- void decode_mod(decdata* dec) override;
- void device_reset() override;
- DECLARE_INPUT_CHANGED_MEMBER( setgm_changed );
+ genmod_decoder_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
+
+ // Set the internal state and output lines according to the address
+ void set_function(int func, int page);
+ void set_debug(bool deb) { m_debug = deb; }
+ void set_turbo(bool turbo) { m_turbo = turbo; }
+ void set_timode(bool timode) { m_timode = timode; }
+
+ int gaready_out();
+ int dben_out();
+ void gaready_in(int state);
+ void extready_in(int state);
+ void sndready_in(int state);
private:
- // Genmod modifications
- bool m_gm_timode;
+ void device_start() override ATTR_COLD;
+
+ // Emulation-specific: Is the debugger active?
+ bool m_debug;
bool m_turbo;
+ bool m_timode;
+ int m_function;
+ int m_function_debug;
+ int m_page;
+ int m_page_debug;
+ int m_gaready;
+ int m_extready;
+ int m_sndready;
};
-} } } // end namespace bus::ti99::internal
+} // end namespace bus::ti99::internal
DECLARE_DEVICE_TYPE_NS(GENEVE_GATE_ARRAY, bus::ti99::internal, geneve_gate_array_device)
-DECLARE_DEVICE_TYPE_NS(GENMOD_GATE_ARRAY, bus::ti99::internal, genmod_gate_array_device)
+DECLARE_DEVICE_TYPE_NS(GENEVE_PAL, bus::ti99::internal, geneve_pal_device)
+DECLARE_DEVICE_TYPE_NS(GENMOD_DECODER, bus::ti99::internal, genmod_decoder_device)
#endif // MAME_BUS_TI99_INTERNAL_GENBOARD_H
diff --git a/src/devices/bus/ti99/internal/genkbd.cpp b/src/devices/bus/ti99/internal/genkbd.cpp
index 92f0e34b66b..14f444c620d 100644
--- a/src/devices/bus/ti99/internal/genkbd.cpp
+++ b/src/devices/bus/ti99/internal/genkbd.cpp
@@ -30,12 +30,12 @@
#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 )
+#define VERBOSE (LOG_GENERAL | LOG_WARN)
#include "logmacro.h"
@@ -203,42 +203,34 @@ geneve_xt_101_hle_keyboard_device::geneve_xt_101_hle_keyboard_device(const machi
{
}
-/*
- Called by the poll timer
-*/
-void geneve_xt_101_hle_keyboard_device::device_timer(emu_timer &timer, device_timer_id id, int param, void *ptr)
+TIMER_CALLBACK_MEMBER(geneve_xt_101_hle_keyboard_device::poll_tick)
+{
+ poll();
+ send_key();
+}
+
+TIMER_CALLBACK_MEMBER(geneve_xt_101_hle_keyboard_device::send_tick)
{
- if (id==0)
+ // Send timer
+ if (m_shift_count == 10)
{
- poll();
- send_key();
+ // Done, all sent
+ m_pc_kbdc->clock_write_from_kb(1);
+ m_pc_kbdc->data_write_from_kb(1);
+ m_send_timer->reset();
+ m_shift_count = 0;
+
+ // Adjust the queue
+ m_queue_head = (m_queue_head + 1) % KEYQUEUESIZE;
+ m_queue_length--;
}
else
{
- if (id==1)
- {
- // Send timer
- if (m_shift_count==10)
- {
- // Done, all sent
- m_pc_kbdc->clock_write_from_kb(1);
- m_pc_kbdc->data_write_from_kb(1);
- m_send_timer->reset();
- m_shift_count = 0;
-
- // Adjust the queue
- m_queue_head = (m_queue_head + 1) % KEYQUEUESIZE;
- m_queue_length--;
- }
- else
- {
- m_pc_kbdc->clock_write_from_kb(1);
- m_pc_kbdc->data_write_from_kb(m_shift_reg&1);
- m_pc_kbdc->clock_write_from_kb(0);
- m_shift_reg>>=1;
- m_shift_count++;
- }
- }
+ m_pc_kbdc->clock_write_from_kb(1);
+ m_pc_kbdc->data_write_from_kb(BIT(m_shift_reg, 0));
+ m_pc_kbdc->clock_write_from_kb(0);
+ m_shift_reg >>= 1;
+ m_shift_count++;
}
}
@@ -271,38 +263,32 @@ static const uint8_t MF1_CODE[0xe] =
void geneve_xt_101_hle_keyboard_device::poll()
{
- uint32_t keystate;
- uint32_t key_transitions;
- uint32_t mask;
- bool pressed = false;
- int keycode = 0;
-
if (m_resetting) return;
// We're testing two 16-bit ports at once
// but only if we have enough space in the queue
- for (int i=0; (i < 4) && (m_queue_length <= (KEYQUEUESIZE-MAXKEYMSGLENGTH)); i++)
+ for (uint8_t i = 0; i < 4 && m_queue_length <= (KEYQUEUESIZE - MAXKEYMSGLENGTH); i++)
{
// Get those two ports and calculate the difference
- keystate = m_keys[2*i]->read() | (m_keys[2*i + 1]->read() << 16);
- key_transitions = keystate ^ m_key_state_save[i];
+ uint32_t keystate = m_keys[2 * i]->read() | (m_keys[2 * i + 1]->read() << 16);
+ uint32_t key_transitions = keystate ^ m_key_state_save[i];
if (key_transitions != 0)
{
- mask = 0x00000001;
+ uint32_t mask = 0x00000001;
// Some key(s) has/have changed (pressed/released)
- for (int j=0; (j < 32) && (m_queue_length <= (KEYQUEUESIZE-MAXKEYMSGLENGTH)); j++)
+ for (uint8_t j = 0; j < 32 && m_queue_length <= (KEYQUEUESIZE - MAXKEYMSGLENGTH); j++)
{
- if ((key_transitions & mask)!=0)
+ if ((key_transitions & mask) != 0)
{
// Found one changed key (i is a 32-key block)
- keycode = (i<<5) | j;
- pressed = (keystate & mask)!=0;
+ uint8_t keycode = (i << 5) | j;
+ bool pressed = (bool)(keystate & mask);
// Auto-repeat
if (pressed)
{
m_autorepeat_code = keycode;
- m_autorepeat_timer = KEYAUTOREPEATDELAY+1;
+ m_autorepeat_timer = KEYAUTOREPEATDELAY + 1;
m_key_state_save[i] |= mask;
}
else
@@ -358,9 +344,9 @@ void geneve_xt_101_hle_keyboard_device::poll()
}
// Extended keycodes
- if ((keycode >= 0x60) && (keycode < 0x6e))
+ if (keycode >= 0x60 && keycode < 0x6e)
{
- if ((keycode >= 0x63) && pressed)
+ if (keycode >= 0x63 && pressed)
{
// Handle shift state
if (keycode == 0x63) // Slash
@@ -373,14 +359,14 @@ void geneve_xt_101_hle_keyboard_device::poll()
}
else
{ // Key function with NumLock=0
- if (m_numlock && (!m_left_shift) && (!m_right_shift))
+ if (m_numlock && !m_left_shift && !m_right_shift)
{
// Fake shift press if numlock is active
m_fake_shift_state = true;
}
else
{
- if ((!m_numlock) && (m_left_shift || m_right_shift))
+ if (!m_numlock && (m_left_shift || m_right_shift))
{
// Fake shift unpress if shift is down
m_fake_unshift_state = true;
@@ -400,7 +386,7 @@ void geneve_xt_101_hle_keyboard_device::poll()
post_in_key_queue(0xaa);
}
}
- keycode = MF1_CODE[keycode-0x60];
+ keycode = MF1_CODE[keycode - 0x60];
if (!pressed) keycode |= 0x80;
post_in_key_queue(0xe0);
post_in_key_queue(keycode);
@@ -422,7 +408,7 @@ void geneve_xt_101_hle_keyboard_device::poll()
else
{
// Handle shift state
- if (pressed && (!m_left_shift) && (!m_right_shift) && (!m_left_ctrl) && (!m_right_ctrl))
+ if (pressed && !m_left_shift && !m_right_shift && !m_left_ctrl && !m_right_ctrl)
{ // Fake shift press
post_in_key_queue(0xe0);
post_in_key_queue(0x2a);
@@ -481,13 +467,13 @@ void geneve_xt_101_hle_keyboard_device::poll()
if (m_autorepeat_code != 0)
{
m_autorepeat_timer--;
- if ((m_autorepeat_timer == 0) && (m_queue_length <= (KEYQUEUESIZE-MAXKEYMSGLENGTH)))
+ if (m_autorepeat_timer == 0 && m_queue_length <= (KEYQUEUESIZE - MAXKEYMSGLENGTH))
{
// Extended code
- if ((m_autorepeat_code >= 0x60) && (m_autorepeat_code < 0x6e))
+ if (m_autorepeat_code >= 0x60 && m_autorepeat_code < 0x6e)
{
post_in_key_queue(0xe0);
- post_in_key_queue(MF1_CODE[m_autorepeat_code-0x60]);
+ post_in_key_queue(MF1_CODE[m_autorepeat_code - 0x60]);
}
else
{
@@ -521,7 +507,7 @@ void geneve_xt_101_hle_keyboard_device::send_key()
if (m_clock_line == CLEAR_LINE)
{
m_reset_timer--;
- if (m_reset_timer==0)
+ if (m_reset_timer == 0)
{
LOG("Reset triggered\n");
reset_line(0);
@@ -530,7 +516,7 @@ void geneve_xt_101_hle_keyboard_device::send_key()
}
else
{
- if (m_data_line==1)
+ if (m_data_line)
{
// Dequeue a key
if (m_queue_length != 0)
@@ -558,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;
@@ -576,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;
@@ -590,14 +576,14 @@ WRITE_LINE_MEMBER( geneve_xt_101_hle_keyboard_device::data_write )
void geneve_xt_101_hle_keyboard_device::device_start()
{
set_pc_kbdc_device();
- m_poll_timer = timer_alloc(0);
- m_send_timer = timer_alloc(1);
+ m_poll_timer = timer_alloc(FUNC(geneve_xt_101_hle_keyboard_device::poll_tick), this);
+ m_send_timer = timer_alloc(FUNC(geneve_xt_101_hle_keyboard_device::send_tick), this);
// state saving
save_item(NAME(m_queue_length));
save_item(NAME(m_queue_head));
- save_pointer(NAME(m_key_state_save),4);
- save_pointer(NAME(m_queue),KEYQUEUESIZE);
+ save_pointer(NAME(m_key_state_save), 4);
+ save_pointer(NAME(m_queue), KEYQUEUESIZE);
}
@@ -614,9 +600,9 @@ 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==0);
+ m_resetting = !state;
if (m_resetting)
{
@@ -645,4 +631,3 @@ WRITE_LINE_MEMBER( geneve_xt_101_hle_keyboard_device::reset_line )
post_in_key_queue(0xaa);
}
}
-
diff --git a/src/devices/bus/ti99/internal/genkbd.h b/src/devices/bus/ti99/internal/genkbd.h
index 78d985a6160..9e359f9991c 100644
--- a/src/devices/bus/ti99/internal/genkbd.h
+++ b/src/devices/bus/ti99/internal/genkbd.h
@@ -26,24 +26,25 @@ 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
- void device_start() override;
- void device_reset() override;
- ioport_constructor device_input_ports() const override;
+ virtual void device_start() override ATTR_COLD;
+ virtual void device_reset() override ATTR_COLD;
+ virtual ioport_constructor device_input_ports() const override ATTR_COLD;
// device_pc_kbd_interface overrides
- DECLARE_WRITE_LINE_MEMBER( clock_write ) override;
- 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);
private:
emu_timer *m_poll_timer;
emu_timer *m_send_timer;
- void device_timer(emu_timer &timer, device_timer_id id, int param, void *ptr) override;
-
static constexpr unsigned KEYQUEUESIZE = 256;
static constexpr unsigned MAXKEYMSGLENGTH = 10;
static constexpr unsigned KEYAUTOREPEATDELAY = 30;
diff --git a/src/devices/bus/ti99/internal/ioport.cpp b/src/devices/bus/ti99/internal/ioport.cpp
index a855fd3bf41..43d083c5797 100644
--- a/src/devices/bus/ti99/internal/ioport.cpp
+++ b/src/devices/bus/ti99/internal/ioport.cpp
@@ -78,22 +78,25 @@
#include "emu.h"
#include "ioport.h"
+#include "splitter.h"
#include "bus/ti99/peb/peribox.h"
+#include "bus/ti99/sidecar/arcturus.h"
+#include "bus/ti99/sidecar/speechsyn.h"
-DEFINE_DEVICE_TYPE_NS(TI99_IOPORT, bus::ti99::internal, ioport_device, "ti99_ioport", "TI-99 I/O Port")
+DEFINE_DEVICE_TYPE(TI99_IOPORT, bus::ti99::internal::ioport_device, "ti99_ioport", "TI-99 I/O Port")
-namespace bus { namespace ti99 { namespace internal {
+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)
{
}
-READ8Z_MEMBER(ioport_device::readz)
+void ioport_device::readz(offs_t offset, uint8_t *value)
{
if (m_connected != nullptr)
m_connected->readz(offset, value);
@@ -105,13 +108,13 @@ void ioport_device::write(offs_t offset, uint8_t data)
m_connected->write(offset, data);
}
-SETADDRESS_DBIN_MEMBER(ioport_device::setaddress_dbin)
+void ioport_device::setaddress_dbin(offs_t offset, int state)
{
if (m_connected != nullptr)
m_connected->setaddress_dbin(offset, state);
}
-READ8Z_MEMBER(ioport_device::crureadz)
+void ioport_device::crureadz(offs_t offset, uint8_t *value)
{
if (m_connected != nullptr)
m_connected->crureadz(offset, value);
@@ -123,56 +126,80 @@ 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);
}
+void ioport_device::reset_in(int state)
+{
+ if (m_connected != nullptr)
+ m_connected->reset_in(state);
+}
+
+void ioport_device::sbe(int state)
+{
+ if (m_connected != nullptr)
+ m_connected->sbe(state);
+}
+
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);
}
-} } } // end namespace bus::ti99::internal
+} // end namespace bus::ti99::internal
void ti99_ioport_options_plain(device_slot_interface &device)
{
device.option_add("peb", TI99_PERIBOX);
+ device.option_add("splitter", TI99_IOSPLIT);
+ device.option_add("arcturus", TI99_ARCTURUS);
+ device.option_add("speechsyn", TI99_SPEECHSYN);
}
void ti99_ioport_options_evpc(device_slot_interface &device)
{
device.option_add("peb", TI99_PERIBOX_EV);
+ device.option_add("splitter", TI99_IOSPLIT);
+ device.option_add("arcturus", TI99_ARCTURUS);
+ device.option_add("speechsyn", TI99_SPEECHSYN);
+}
+
+// Used for the splitter (to avoid getting multiple EVPCs in the system)
+void ti99_ioport_options_evpc1(device_slot_interface &device)
+{
+ device.option_add("peb", TI99_PERIBOX_EV1);
+ device.option_add("splitter", TI99_IOSPLIT);
+ device.option_add("arcturus", TI99_ARCTURUS);
}
diff --git a/src/devices/bus/ti99/internal/ioport.h b/src/devices/bus/ti99/internal/ioport.h
index 6b468007eda..0da1d977621 100644
--- a/src/devices/bus/ti99/internal/ioport.h
+++ b/src/devices/bus/ti99/internal/ioport.h
@@ -9,9 +9,9 @@
#pragma once
-#include "bus/ti99/ti99defs.h"
+#define TI99_IOPORT_TAG "ioport"
-namespace bus { namespace ti99 { namespace internal {
+namespace bus::ti99::internal {
extern const device_type IOPORT;
@@ -29,21 +29,23 @@ public:
{ }
// Methods called from the console / ioport
- virtual DECLARE_READ8Z_MEMBER( readz ) { }
+ virtual void readz(offs_t offset, uint8_t *value) { }
virtual void write(offs_t offset, uint8_t data) { }
- virtual DECLARE_SETADDRESS_DBIN_MEMBER( setaddress_dbin ) { }
- virtual DECLARE_READ8Z_MEMBER( crureadz ) { }
+ 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 void memen_in(int state) { }
+ virtual void msast_in(int state) { }
+ virtual void clock_in(int state) { }
+ virtual void reset_in(int state) { }
+ virtual void sbe(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;
};
@@ -52,7 +54,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;
@@ -70,22 +72,24 @@ public:
ioport_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
// Methods called from the console
- DECLARE_READ8Z_MEMBER( readz );
+ void readz(offs_t offset, uint8_t *value);
void write(offs_t offset, uint8_t data);
- DECLARE_SETADDRESS_DBIN_MEMBER( setaddress_dbin );
- DECLARE_READ8Z_MEMBER( crureadz );
+ 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 );
+ void memen_in(int state);
+ void msast_in(int state);
+ void clock_in(int state);
+ void reset_in(int state);
+ void sbe(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 ATTR_COLD;
+ virtual void device_config_complete() override;
// Methods called back from the external device
devcb_write_line m_console_extint; // EXTINT line
@@ -94,11 +98,13 @@ protected:
private:
ioport_attached_device* m_connected;
};
-} } } // end namespace bus::ti99::internal
+
+} // end namespace bus::ti99::internal
DECLARE_DEVICE_TYPE_NS(TI99_IOPORT, bus::ti99::internal, ioport_device)
void ti99_ioport_options_plain(device_slot_interface &device);
void ti99_ioport_options_evpc(device_slot_interface &device);
+void ti99_ioport_options_evpc1(device_slot_interface &device);
#endif /* __TI99IOPORT__ */
diff --git a/src/devices/bus/ti99/internal/splitter.cpp b/src/devices/bus/ti99/internal/splitter.cpp
new file mode 100644
index 00000000000..404bd04d0c6
--- /dev/null
+++ b/src/devices/bus/ti99/internal/splitter.cpp
@@ -0,0 +1,190 @@
+// license:LGPL-2.1+
+// copyright-holders:Michael Zapf
+/****************************************************************************
+ I/O port splitter
+
+ The I/O port splitter connects to the TI-99/4(A) console at its I/O port
+ and provides two I/O ports. That way, two Peripheral Expansion boxes or
+ one PEB and a sidecar chain may be connected.
+
+ | Port 2
+ v
+ +---+
+ +----------------+ | |
+ | TI-99/4(A) |---+ +--+
+ +------------+---+ Splitter | <-- Port 1
+ | oooooooooo | |----------+
+ | oooooooooo | |
+ +-----------------
+
+ The splitter was designed 2015 by Jim Fetzner (as Tekumel Software)
+
+ March 2025, Michael Zapf
+
+*****************************************************************************/
+
+#include "emu.h"
+#include "ioport.h"
+#include "splitter.h"
+#include "bus/ti99/peb/peribox.h"
+
+#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)
+
+#include "logmacro.h"
+
+DEFINE_DEVICE_TYPE(TI99_IOSPLIT, bus::ti99::internal::ioport_splitter_device, "ti99_iosplit", "TI-99 I/O Port Splitter")
+
+namespace bus::ti99::internal {
+
+#define PORT1 "port1"
+#define PORT2 "port2"
+
+ioport_splitter_device::ioport_splitter_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock)
+ : ioport_attached_device(mconfig, type, tag, owner, clock),
+ m_port1(*this, PORT1),
+ m_port2(*this, PORT2)
+{
+}
+
+ioport_splitter_device::ioport_splitter_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
+ : ioport_splitter_device(mconfig, TI99_IOSPLIT, tag, owner, clock)
+{
+}
+
+void ioport_splitter_device::readz(offs_t offset, uint8_t *value)
+{
+ // With a proper configuration, only one device on one of the branches
+ // will respond.
+ if (m_port1 != nullptr)
+ m_port1->readz(offset, value);
+
+ if (m_port2 != nullptr)
+ m_port2->readz(offset, value);
+}
+
+void ioport_splitter_device::write(offs_t offset, uint8_t data)
+{
+ if (m_port1 != nullptr)
+ m_port1->write(offset, data);
+
+ if (m_port2 != nullptr)
+ m_port2->write(offset, data);
+}
+
+void ioport_splitter_device::setaddress_dbin(offs_t offset, int state)
+{
+ if (m_port1 != nullptr)
+ m_port1->setaddress_dbin(offset, state);
+
+ if (m_port2 != nullptr)
+ m_port2->setaddress_dbin(offset, state);
+}
+
+void ioport_splitter_device::crureadz(offs_t offset, uint8_t *value)
+{
+ if (m_port1 != nullptr)
+ m_port1->crureadz(offset, value);
+
+ if (m_port2 != nullptr)
+ m_port2->crureadz(offset, value);
+}
+
+void ioport_splitter_device::cruwrite(offs_t offset, uint8_t data)
+{
+ if (m_port1 != nullptr)
+ m_port1->cruwrite(offset, data);
+
+ if (m_port2 != nullptr)
+ m_port2->cruwrite(offset, data);
+}
+
+void ioport_splitter_device::memen_in(int state)
+{
+ if (m_port1 != nullptr)
+ m_port1->memen_in(state);
+
+ if (m_port2 != nullptr)
+ m_port2->memen_in(state);
+}
+
+void ioport_splitter_device::msast_in(int state)
+{
+ if (m_port1 != nullptr)
+ m_port1->msast_in(state);
+
+ if (m_port2 != nullptr)
+ m_port2->msast_in(state);
+}
+
+void ioport_splitter_device::clock_in(int state)
+{
+ if (m_port1 != nullptr)
+ m_port1->clock_in(state);
+
+ if (m_port2 != nullptr)
+ m_port2->clock_in(state);
+}
+
+void ioport_splitter_device::reset_in(int state)
+{
+ if (m_port1 != nullptr)
+ m_port1->reset_in(state);
+
+ if (m_port2 != nullptr)
+ m_port2->reset_in(state);
+}
+
+template<int port>
+void ioport_splitter_device::extint(int state)
+{
+ LOGMASKED(LOG_INT, "propagating INTA from port %d to console: %d\n", port, state);
+ if (state==ASSERT_LINE)
+ m_inta_flag |= port; // 1 or 2
+ else
+ m_inta_flag &= ~port; // 1 or 2
+
+ set_extint((m_inta_flag != 0)? ASSERT_LINE : CLEAR_LINE);
+}
+
+template<int port>
+void ioport_splitter_device::ready(int state)
+{
+ LOGMASKED(LOG_READY, "Incoming READY=%d from port %d\n", state, port);
+ // We store the inverse state
+ if (state==CLEAR_LINE)
+ m_ready_flag |= port; // 1 or 2
+ else
+ m_ready_flag &= ~port; // 1 or 2
+
+ set_ready((m_ready_flag != 0)? CLEAR_LINE : ASSERT_LINE);
+}
+
+void ioport_splitter_device::device_start()
+{
+ LOG("Starting I/O Port Splitter\n");
+}
+
+
+void ioport_splitter_device::device_config_complete()
+{
+ m_inta_flag = 0;
+ m_ready_flag = 0;
+}
+
+void ioport_splitter_device::device_add_mconfig(machine_config &config)
+{
+ TI99_IOPORT(config, m_port1, 1, ti99_ioport_options_evpc1, nullptr);
+ TI99_IOPORT(config, m_port2, 2, ti99_ioport_options_evpc1, nullptr);
+
+ m_port1->extint_cb().set(FUNC(ioport_splitter_device::extint<1>));
+ m_port2->extint_cb().set(FUNC(ioport_splitter_device::extint<2>));
+ m_port1->ready_cb().set(FUNC(ioport_splitter_device::ready<1>));
+ m_port2->ready_cb().set(FUNC(ioport_splitter_device::ready<2>));
+}
+
+} // end namespace bus::ti99::internal
diff --git a/src/devices/bus/ti99/internal/splitter.h b/src/devices/bus/ti99/internal/splitter.h
new file mode 100644
index 00000000000..c12fac3648f
--- /dev/null
+++ b/src/devices/bus/ti99/internal/splitter.h
@@ -0,0 +1,65 @@
+// license:LGPL-2.1+
+// copyright-holders:Michael Zapf
+/****************************************************************************
+
+ I/O port splitter
+
+ This plugs into the I/O port of the console as an
+ ioport_attached_device, and it offers two new I/O ports.
+
+*****************************************************************************/
+
+#ifndef MAME_BUS_TI99_INTERNAL_SPLITTER_H
+#define MAME_BUS_TI99_INTERNAL_SPLITTER_H
+
+#pragma once
+
+#include "ioport.h"
+
+namespace bus::ti99::internal {
+
+class ioport_splitter_device : public ioport_attached_device
+{
+
+public:
+ ioport_splitter_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
+
+ // Next methods are called from the console
+ void readz(offs_t offset, uint8_t *value) override;
+ void write(offs_t offset, uint8_t data) override;
+ void setaddress_dbin(offs_t offset, int state) override;
+
+ void crureadz(offs_t offset, uint8_t *value) override;
+ void cruwrite(offs_t offset, uint8_t data) override;
+
+ void memen_in(int state) override;
+ void msast_in(int state) override;
+
+ void clock_in(int state) override;
+ void reset_in(int state) override;
+
+protected:
+ ioport_splitter_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock);
+
+ virtual void device_start() override ATTR_COLD;
+ virtual void device_config_complete() override;
+
+ virtual void device_add_mconfig(machine_config &config) override ATTR_COLD;
+
+ // Callbacks from the two ports
+ template<int port> void extint(int state);
+ template<int port> void ready(int state);
+
+ int m_inta_flag;
+ int m_ready_flag;
+
+private:
+ required_device<ioport_device> m_port1;
+ required_device<ioport_device> m_port2;
+};
+
+} // end namespace bus::ti99::internal
+
+DECLARE_DEVICE_TYPE_NS(TI99_IOSPLIT, bus::ti99::internal, ioport_splitter_device)
+
+#endif /* MAME_BUS_TI99_INTERNAL_SPLITTER_H */
diff --git a/src/devices/bus/ti99/joyport/handset.cpp b/src/devices/bus/ti99/joyport/handset.cpp
index 829b5bca087..d03480378ab 100644
--- a/src/devices/bus/ti99/joyport/handset.cpp
+++ b/src/devices/bus/ti99/joyport/handset.cpp
@@ -39,34 +39,32 @@
#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 )
+#define VERBOSE (LOG_CONFIG | LOG_WARN)
#include "logmacro.h"
-DEFINE_DEVICE_TYPE_NS(TI99_JOYSTICK, bus::ti99::joyport, ti99_twin_joystick_device, "ti99_twinjoy", "TI-99/4(A) Twin Joysticks")
-DEFINE_DEVICE_TYPE_NS(TI99_HANDSET, bus::ti99::joyport, ti99_handset_device, "ti99_handset", "TI-99/4 IR handset")
+DEFINE_DEVICE_TYPE(TI99_JOYSTICK, bus::ti99::joyport::ti99_twin_joystick_device, "ti99_twinjoy", "TI-99/4(A) Twin Joysticks")
+DEFINE_DEVICE_TYPE(TI99_HANDSET, bus::ti99::joyport::ti99_handset_device, "ti99_handset", "TI-99/4 IR handset")
-namespace bus { namespace ti99 { namespace joyport {
-
-#define TRACE_HANDSET 0
-#define TRACE_JOYSTICK 0
-
-static const char *const joynames[2][4] =
-{
- { "JOY0", "JOY2", "JOY4", "JOY6" }, // X axis
- { "JOY1", "JOY3", "JOY5", "JOY7" } // Y axis
-};
-
-static const char *const keynames[] = { "KP0", "KP1", "KP2", "KP3", "KP4" };
+namespace bus::ti99::joyport {
ti99_handset_device::ti99_handset_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
- : device_t(mconfig, TI99_HANDSET, tag, owner, clock), device_ti99_joyport_interface(mconfig, *this), m_ack(0), m_clock_high(false), m_buf(0), m_buflen(0), m_delay_timer(nullptr)
+ : device_t(mconfig, TI99_HANDSET, tag, owner, clock)
+ , device_ti99_joyport_interface(mconfig, *this)
+ , m_joyx(*this, "JOYX%u", 0U)
+ , m_joyy(*this, "JOYY%u", 0U)
+ , m_keys(*this, "KP%u", 0U)
+ , m_ack(0)
+ , m_clock_high(false)
+ , m_buf(0)
+ , m_buflen(0)
+ , m_delay_timer(nullptr)
{
}
@@ -85,7 +83,7 @@ ti99_handset_device::ti99_handset_device(const machine_config &mconfig, const ch
*/
uint8_t ti99_handset_device::read_dev()
{
- return (m_buf & 0xf) | 0x10 | (m_clock_high? 0x20:0) | ( m_buflen==3? 0x00:0x40);
+ return (m_buf & 0xf) | 0x10 | (m_clock_high ? 0x20 : 0x00) | (m_buflen == 3 ? 0x00 : 0x40);
}
void ti99_handset_device::write_dev(uint8_t data)
@@ -100,7 +98,7 @@ void ti99_handset_device::write_dev(uint8_t data)
of P0 is changed, because, in one occasion, the ISR asserts the line before
it reads the data, so we need to delay the acknowledge process.
*/
-void ti99_handset_device::device_timer(emu_timer &timer, device_timer_id id, int param, void *ptr)
+TIMER_CALLBACK_MEMBER(ti99_handset_device::delayed_data_ack)
{
m_clock_high = !m_clock_high;
m_buf >>= 4;
@@ -120,8 +118,10 @@ void ti99_handset_device::device_timer(emu_timer &timer, device_timer_id id, int
}
if (m_buflen == 0)
- /* See if we need to post a new event */
- do_task();
+ {
+ // See if we need to post a new event
+ do_task();
+ }
}
/*
@@ -129,10 +129,10 @@ void ti99_handset_device::device_timer(emu_timer &timer, device_timer_id id, int
*/
void ti99_handset_device::set_acknowledge(int data)
{
- if ((m_buflen !=0) && (data != m_ack))
+ if (m_buflen != 0 && data != m_ack)
{
m_ack = data;
- if ((data!=0) == m_clock_high)
+ if (data != 0 && m_clock_high)
{
// I don't know what the real delay is, but 30us apears to be enough
m_delay_timer->adjust(attotime::from_usec(30));
@@ -167,54 +167,58 @@ void ti99_handset_device::post_message(int message)
*/
bool ti99_handset_device::poll_keyboard(int num)
{
- uint32_t key_buf;
uint8_t current_key;
- int i;
- /* read current key state */
- key_buf = (ioport(keynames[num])->read() | (ioport(keynames[num + 1])->read() << 16) ) >> (4*num);
+ // read current key state
+ uint32_t key_buf = (m_keys[num]->read() | (m_keys[num + 1]->read() << 16)) >> (4*num);
// If a key was previously pressed, this key was not shift, and this key is
// still down, then don't change the current key press.
- if (previous_key[num] !=0 && (previous_key[num] != 0x24)
- && (key_buf & (1 << (previous_key[num] & 0x1f))))
+ if (previous_key[num] !=0 && previous_key[num] != 0x24 && BIT(key_buf, previous_key[num] & 0x1f))
{
- /* check the shift modifier state */
- if (((previous_key[num] & 0x20) != 0) == ((key_buf & 0x0008) != 0))
- /* the shift modifier state has not changed */
+ // check the shift modifier state
+ if (BIT(previous_key[num], 5) == BIT(key_buf, 3))
+ {
+ // the shift modifier state has not changed
return false;
+ }
else
{
// The shift modifier state has changed: we need to update the
// keyboard state
if (key_buf & 0x0008)
- { /* shift has been pressed down */
- previous_key[num] = current_key = previous_key[num] | 0x20;
+ {
+ // shift has been pressed down
+ current_key = previous_key[num] | 0x20;
+ previous_key[num] = current_key;
}
else
{
- previous_key[num] = current_key = previous_key[num] & ~0x20;
+ current_key = previous_key[num] & ~0x20;
+ previous_key[num] = current_key;
}
- /* post message */
- post_message((((unsigned)current_key) << 4) | (num << 1));
+ // post message
+ post_message(((uint32_t)current_key << 4) | (num << 1));
return true;
}
}
- current_key = 0; /* default value if no key is down */
- for (i=0; i<20; i++)
+ current_key = 0; // default value if no key is down
+ for (int i = 0; i < 20; i++)
{
- if (key_buf & (1 << i))
+ if (BIT(key_buf, i))
{
current_key = i + 1;
- if (key_buf & 0x0008)
- current_key |= 0x20; /* set shift flag */
+ if (BIT(key_buf, 3))
+ current_key |= 0x20; // set shift flag
if (current_key != 0x24)
+ {
// If this is the shift key, any other key we may find will
// have higher priority; otherwise, we may exit the loop and keep
// the key we have just found.
break;
+ }
}
}
@@ -222,8 +226,8 @@ bool ti99_handset_device::poll_keyboard(int num)
{
previous_key[num] = current_key;
- /* post message */
- post_message((((unsigned) current_key) << 4) | (num << 1));
+ // post message
+ post_message(((uint32_t)current_key << 4) | (num << 1));
return true;
}
return false;
@@ -238,42 +242,39 @@ bool ti99_handset_device::poll_keyboard(int num)
*/
bool ti99_handset_device::poll_joystick(int num)
{
- uint8_t current_joy;
- int current_joy_x, current_joy_y;
int message;
- /* read joystick position */
- current_joy_x = ioport(joynames[0][num])->read();
- current_joy_y = ioport(joynames[1][num])->read();
+ // read joystick position
+ uint8_t current_joy_x = m_joyx[num]->read();
+ uint8_t current_joy_y = m_joyy[num]->read();
- /* compare with last saved position */
- current_joy = current_joy_x | (current_joy_y << 4);
+ // compare with last saved position
+ uint8_t current_joy = current_joy_x | (current_joy_y << 4);
if (current_joy != previous_joy[num])
{
- /* save position */
+ // save position
previous_joy[num] = current_joy;
- /* transform position to signed quantity */
+ // transform position to signed quantity
current_joy_x -= 7;
current_joy_y -= 7;
message = 0;
- /* set sign */
- // note that we set the sign if the joystick position is 0 to work
+ // set sign, note that we set the sign if the joystick position is 0 to work
// around a bug in the ti99/4 ROMs
if (current_joy_x <= 0)
{
message |= 0x040;
- current_joy_x = - current_joy_x;
+ current_joy_x = -current_joy_x;
}
if (current_joy_y <= 0)
{
message |= 0x400;
- current_joy_y = - current_joy_y;
+ current_joy_y = -current_joy_y;
}
- /* convert absolute values to Gray code and insert in message */
+ // convert absolute values to Gray code and insert in message
if (current_joy_x & 4)
current_joy_x ^= 3;
if (current_joy_x & 2)
@@ -286,10 +287,10 @@ bool ti99_handset_device::poll_joystick(int num)
current_joy_y ^= 1;
message |= current_joy_y << 7;
- /* set joystick address */
+ // set joystick address
message |= (num << 1) | 0x1;
- /* post message */
+ // post message
post_message(message);
return true;
}
@@ -302,25 +303,23 @@ bool ti99_handset_device::poll_joystick(int num)
*/
void ti99_handset_device::do_task()
{
- int i;
-
if (m_buflen == 0)
{
- /* poll every handset */
- for (i=0; i < MAX_HANDSETS; i++)
- if (poll_joystick(i)==true) return;
- for (i=0; i < MAX_HANDSETS; i++)
- if (poll_keyboard(i)==true) return;
+ // poll every handset
+ for (int i = 0; i < MAX_HANDSETS; i++)
+ if (poll_joystick(i)) return;
+ for (int i = 0; i < MAX_HANDSETS; i++)
+ if (poll_keyboard(i)) return;
}
else if (m_buflen == 3)
{ /* update messages after they have been posted */
if (m_buf & 1)
{ /* keyboard */
- poll_keyboard((~(m_buf >> 1)) & 0x3);
+ poll_keyboard(~(m_buf >> 1) & 0x3);
}
else
{ /* joystick */
- poll_joystick((~(m_buf >> 1)) & 0x3);
+ poll_joystick(~(m_buf >> 1) & 0x3);
}
}
}
@@ -333,7 +332,7 @@ void ti99_handset_device::pulse_clock()
void ti99_handset_device::device_start()
{
- m_delay_timer = timer_alloc(DELAY_TIMER);
+ m_delay_timer = timer_alloc(FUNC(ti99_handset_device::delayed_data_ack), this);
save_item(NAME(m_ack));
save_item(NAME(m_clock_high));
save_item(NAME(m_buf));
@@ -358,28 +357,28 @@ INPUT_PORTS_START( handset )
/* 13 pseudo-ports for IR remote handsets */
/* 8 pseudo-ports for the 4 IR joysticks */
- PORT_START("JOY0") /* joystick 1, X axis */
+ PORT_START("JOYX0") /* joystick 1, X axis */
PORT_BIT( 0xf, 0x7, IPT_AD_STICK_X) PORT_SENSITIVITY(JOYSTICK_SENSITIVITY) PORT_KEYDELTA(JOYSTICK_DELTA) PORT_MINMAX(0,0xe) PORT_PLAYER(1)
- PORT_START("JOY1") /* joystick 1, Y axis */
+ PORT_START("JOYY0") /* joystick 1, Y axis */
PORT_BIT( 0xf, 0x7, IPT_AD_STICK_Y) PORT_SENSITIVITY(JOYSTICK_SENSITIVITY) PORT_KEYDELTA(JOYSTICK_DELTA) PORT_MINMAX(0,0xe) PORT_PLAYER(1) PORT_REVERSE
- PORT_START("JOY2") /* joystick 2, X axis */
+ PORT_START("JOYX1") /* joystick 2, X axis */
PORT_BIT( 0xf, 0x7, IPT_AD_STICK_X) PORT_SENSITIVITY(JOYSTICK_SENSITIVITY) PORT_KEYDELTA(JOYSTICK_DELTA) PORT_MINMAX(0,0xe) PORT_PLAYER(2)
- PORT_START("JOY3") /* joystick 2, Y axis */
+ PORT_START("JOYY1") /* joystick 2, Y axis */
PORT_BIT( 0xf, 0x7, IPT_AD_STICK_Y) PORT_SENSITIVITY(JOYSTICK_SENSITIVITY) PORT_KEYDELTA(JOYSTICK_DELTA) PORT_MINMAX(0,0xe) PORT_PLAYER(2) PORT_REVERSE
- PORT_START("JOY4") /* joystick 3, X axis */
+ PORT_START("JOYX2") /* joystick 3, X axis */
PORT_BIT( 0xf, 0x7, IPT_AD_STICK_X) PORT_SENSITIVITY(JOYSTICK_SENSITIVITY) PORT_KEYDELTA(JOYSTICK_DELTA) PORT_MINMAX(0,0xe) PORT_PLAYER(3)
- PORT_START("JOY5") /* joystick 3, Y axis */
+ PORT_START("JOYY2") /* joystick 3, Y axis */
PORT_BIT( 0xf, 0x7, IPT_AD_STICK_Y) PORT_SENSITIVITY(JOYSTICK_SENSITIVITY) PORT_KEYDELTA(JOYSTICK_DELTA) PORT_MINMAX(0,0xe) PORT_PLAYER(3) PORT_REVERSE
- PORT_START("JOY6") /* joystick 4, X axis */
+ PORT_START("JOYX3") /* joystick 4, X axis */
PORT_BIT( 0xf, 0x7, IPT_AD_STICK_X) PORT_SENSITIVITY(JOYSTICK_SENSITIVITY) PORT_KEYDELTA(JOYSTICK_DELTA) PORT_MINMAX(0,0xe) PORT_PLAYER(4)
- PORT_START("JOY7") /* joystick 4, Y axis */
+ PORT_START("JOYY3") /* joystick 4, Y axis */
PORT_BIT( 0xf, 0x7, IPT_AD_STICK_Y) PORT_SENSITIVITY(JOYSTICK_SENSITIVITY) PORT_KEYDELTA(JOYSTICK_DELTA) PORT_MINMAX(0,0xe) PORT_PLAYER(4) PORT_REVERSE
/* 5 pseudo-ports for the 4 IR remote keypads */
@@ -508,7 +507,9 @@ INPUT_PORTS_START( joysticks )
INPUT_PORTS_END
ti99_twin_joystick_device::ti99_twin_joystick_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
- : device_t(mconfig, TI99_JOYSTICK, tag, owner, clock), device_ti99_joyport_interface(mconfig, *this), m_joystick(0)
+ : device_t(mconfig, TI99_JOYSTICK, tag, owner, clock), device_ti99_joyport_interface(mconfig, *this)
+ , m_joystick(0)
+ , m_joys(*this, "JOY%u", 1U)
{
}
@@ -524,12 +525,10 @@ void ti99_twin_joystick_device::device_start()
*/
uint8_t ti99_twin_joystick_device::read_dev()
{
- uint8_t value;
- if (m_joystick==1) value = ioport("JOY1")->read();
- else
+ uint8_t value = 0xff;
+ if (m_joystick > 0 && m_joystick <= 2)
{
- if (m_joystick==2) value = ioport("JOY2")->read();
- else value = 0xff;
+ value = m_joys[m_joystick - 1]->read();
}
LOGMASKED(LOG_JOYSTICK, "joy%d = %02x\n", m_joystick, value);
return value;
@@ -545,4 +544,5 @@ ioport_constructor ti99_twin_joystick_device::device_input_ports() const
{
return INPUT_PORTS_NAME( joysticks );
}
-} } } // end namespace bus::ti99::joyport
+
+} // end namespace bus::ti99::joyport
diff --git a/src/devices/bus/ti99/joyport/handset.h b/src/devices/bus/ti99/joyport/handset.h
index bdeda83899c..3c7a0e03ba3 100644
--- a/src/devices/bus/ti99/joyport/handset.h
+++ b/src/devices/bus/ti99/joyport/handset.h
@@ -21,7 +21,7 @@
#include "joyport.h"
-namespace bus { namespace ti99 { namespace joyport {
+namespace bus::ti99::joyport {
class ti99_handset_device : public device_t, public device_ti99_joyport_interface
{
@@ -34,11 +34,11 @@ public:
void pulse_clock() override;
protected:
- virtual void device_start() override;
- virtual void device_reset() override;
- virtual ioport_constructor device_input_ports() const override;
+ virtual void device_start() override ATTR_COLD;
+ virtual void device_reset() override ATTR_COLD;
+ virtual ioport_constructor device_input_ports() const override ATTR_COLD;
- virtual void device_timer(emu_timer &timer, device_timer_id id, int param, void *ptr) override;
+ TIMER_CALLBACK_MEMBER(delayed_data_ack);
private:
static constexpr unsigned MAX_HANDSETS = 4;
@@ -49,6 +49,10 @@ private:
bool poll_joystick(int num);
void set_acknowledge(int data);
+ required_ioport_array<4> m_joyx;
+ required_ioport_array<4> m_joyy;
+ required_ioport_array<5> m_keys;
+
int m_ack;
bool m_clock_high;
int m_buf;
@@ -65,21 +69,24 @@ class ti99_twin_joystick_device : public device_t, public device_ti99_joyport_in
{
public:
ti99_twin_joystick_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
- virtual void device_start() override;
+ virtual void device_start() override ATTR_COLD;
uint8_t read_dev() override;
void write_dev(uint8_t data) override;
protected:
- virtual ioport_constructor device_input_ports() const override;
+ virtual ioport_constructor device_input_ports() const override ATTR_COLD;
private:
// Which joystick is selected?
// In reality this is no latch but GND is put on one of the selector lines
// and then routed back to the port via the joystick
int m_joystick;
+
+ required_ioport_array<2> m_joys;
};
-} } } // end namespace bus::ti99::joyport
+
+} // end namespace bus::ti99::joyport
DECLARE_DEVICE_TYPE_NS(TI99_HANDSET, bus::ti99::joyport, ti99_handset_device)
DECLARE_DEVICE_TYPE_NS(TI99_JOYSTICK, bus::ti99::joyport, ti99_twin_joystick_device)
diff --git a/src/devices/bus/ti99/joyport/joyport.cpp b/src/devices/bus/ti99/joyport/joyport.cpp
index 1a39c0d6dfa..b8ebafe6ba5 100644
--- a/src/devices/bus/ti99/joyport/joyport.cpp
+++ b/src/devices/bus/ti99/joyport/joyport.cpp
@@ -40,14 +40,21 @@
#include "handset.h"
#include "mecmouse.h"
-DEFINE_DEVICE_TYPE_NS(TI99_JOYPORT, bus::ti99::joyport, joyport_device, "ti99_joyport", "TI-99 Joystick port")
+DEFINE_DEVICE_TYPE(TI99_JOYPORT, bus::ti99::joyport::joyport_device, "ti99_joyport", "TI-99 Joystick port")
-namespace bus { namespace ti99 { namespace joyport {
+namespace bus::ti99::joyport {
+
+device_ti99_joyport_interface::device_ti99_joyport_interface(const machine_config &config, device_t &device)
+ : device_interface(device, "ti99joyport"),
+ m_joyport(nullptr)
+{
+}
joyport_device::joyport_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
: device_t(mconfig, TI99_JOYPORT, tag, owner, clock),
- device_slot_interface(mconfig, *this),
- m_interrupt(*this), m_connected(nullptr)
+ device_single_card_slot_interface<device_ti99_joyport_interface>(mconfig, *this),
+ m_interrupt(*this),
+ m_connected(nullptr)
{
}
@@ -80,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();
}
/*****************************************************************************/
@@ -102,7 +108,7 @@ void device_ti99_joyport_interface::interface_config_complete()
m_joyport = dynamic_cast<joyport_device*>(device().owner());
}
-} } } // end namespace bus::ti99::joyport
+} // end namespace bus::ti99::joyport
void ti99_joyport_options_plain(device_slot_interface &device)
{
diff --git a/src/devices/bus/ti99/joyport/joyport.h b/src/devices/bus/ti99/joyport/joyport.h
index 4011efaaf70..85d2f8acb53 100644
--- a/src/devices/bus/ti99/joyport/joyport.h
+++ b/src/devices/bus/ti99/joyport/joyport.h
@@ -22,7 +22,7 @@
#pragma once
-namespace bus { namespace ti99 { namespace joyport {
+namespace bus::ti99::joyport {
enum
{
@@ -31,12 +31,14 @@ enum
HANDSET
};
+#define TI_JOYPORT_TAG "joyport"
+
class joyport_device;
/********************************************************************
Common parent class of all devices attached to the joystick port
********************************************************************/
-class device_ti99_joyport_interface : public device_slot_card_interface
+class device_ti99_joyport_interface : public device_interface
{
public:
virtual uint8_t read_dev() = 0;
@@ -44,16 +46,16 @@ public:
virtual void pulse_clock() { }
protected:
- using device_slot_card_interface::device_slot_card_interface;
+ device_ti99_joyport_interface(const machine_config &mconfig, device_t &device);
virtual void interface_config_complete() override;
- joyport_device* m_joyport = nullptr;
+ joyport_device* m_joyport;
};
/********************************************************************
Joystick port
********************************************************************/
-class joyport_device : public device_t, public device_slot_interface
+class joyport_device : public device_t, public device_single_card_slot_interface<device_ti99_joyport_interface>
{
public:
template <typename U>
@@ -74,15 +76,15 @@ public:
auto int_cb() { return m_interrupt.bind(); }
protected:
- void device_start() override;
- void device_config_complete() override;
+ virtual void device_start() override ATTR_COLD;
+ virtual void device_config_complete() override;
private:
devcb_write_line m_interrupt;
device_ti99_joyport_interface* m_connected;
};
-} } } // end namespace bus::ti99::joyport
+} // end namespace bus::ti99::joyport
DECLARE_DEVICE_TYPE_NS(TI99_JOYPORT, bus::ti99::joyport, joyport_device)
diff --git a/src/devices/bus/ti99/joyport/mecmouse.cpp b/src/devices/bus/ti99/joyport/mecmouse.cpp
index 51be546a467..68e17da3ec1 100644
--- a/src/devices/bus/ti99/joyport/mecmouse.cpp
+++ b/src/devices/bus/ti99/joyport/mecmouse.cpp
@@ -51,14 +51,25 @@
#include "emu.h"
#include "mecmouse.h"
-DEFINE_DEVICE_TYPE_NS(TI99_MECMOUSE, bus::ti99::joyport, mecmouse_device, "ti99_mecmouse", "TI-99 Mechatronics Mouse")
+DEFINE_DEVICE_TYPE(TI99_MECMOUSE, bus::ti99::joyport::mecmouse_device, "ti99_mecmouse", "TI-99 Mechatronics Mouse")
-namespace bus { namespace ti99 { namespace joyport {
-
-#define POLL_TIMER 1
+namespace bus::ti99::joyport {
mecmouse_device::mecmouse_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
- : device_t(mconfig, TI99_MECMOUSE, tag, owner, clock), device_ti99_joyport_interface(mconfig, *this), m_last_select(0), m_read_y_axis(false), m_x(0), m_y(0), m_x_buf(0), m_y_buf(0), m_last_mx(0), m_last_my(0), m_poll_timer(nullptr)
+ : device_t(mconfig, TI99_MECMOUSE, tag, owner, clock)
+ , device_ti99_joyport_interface(mconfig, *this)
+ , m_mousex(*this, "MOUSEX")
+ , m_mousey(*this, "MOUSEY")
+ , m_mousebutton(*this, "MOUSE0")
+ , m_last_select(0)
+ , m_read_y_axis(false)
+ , m_x(0)
+ , m_y(0)
+ , m_x_buf(0)
+ , m_y_buf(0)
+ , m_last_mx(0)
+ , m_last_my(0)
+ , m_poll_timer(nullptr)
{
}
@@ -66,7 +77,7 @@ mecmouse_device::mecmouse_device(const machine_config &mconfig, const char *tag,
uint8_t mecmouse_device::read_dev()
{
int answer;
- int buttons = ioport("MOUSE0")->read() & 3;
+ int buttons = m_mousebutton->read() & 3;
answer = (m_read_y_axis? m_y_buf : m_x_buf) << 1;
@@ -132,17 +143,14 @@ void mecmouse_device::write_dev(uint8_t data)
}
}
-void mecmouse_device::device_timer(emu_timer &timer, device_timer_id id, int param, void *ptr)
+TIMER_CALLBACK_MEMBER(mecmouse_device::poll_mouse)
{
// Poll the movement
- int new_mx, new_my;
- int delta_x, delta_y;
-
- new_mx = ioport("MOUSEX")->read();
- new_my = ioport("MOUSEY")->read();
+ int new_mx = m_mousex->read();
+ int new_my = m_mousey->read();
// compute x delta
- delta_x = new_mx - m_last_mx;
+ int delta_x = new_mx - m_last_mx;
// Prevent unplausible values at startup.
if (delta_x > 10000 || delta_x<-10000) delta_x = 0;
@@ -150,7 +158,7 @@ void mecmouse_device::device_timer(emu_timer &timer, device_timer_id id, int par
m_last_mx = new_mx;
// compute y delta
- delta_y = new_my - m_last_my;
+ int delta_y = new_my - m_last_my;
if (delta_y > 10000 || delta_y<-10000) delta_y = 0;
@@ -163,7 +171,7 @@ void mecmouse_device::device_timer(emu_timer &timer, device_timer_id id, int par
void mecmouse_device::device_start()
{
- m_poll_timer = timer_alloc(POLL_TIMER);
+ m_poll_timer = timer_alloc(FUNC(mecmouse_device::poll_mouse), this);
// The poll time cannot depend on the console settings, since the TI-99/4A
// has no clock line on the joystick port. The rate is not mentioned in
// the specs; however, if it is too low, the mouse pointer will do jumps
@@ -208,5 +216,4 @@ ioport_constructor mecmouse_device::device_input_ports() const
return INPUT_PORTS_NAME( mecmouse );
}
-} } } // end namespace bus::ti99::joyport
-
+} // end namespace bus::ti99::joyport
diff --git a/src/devices/bus/ti99/joyport/mecmouse.h b/src/devices/bus/ti99/joyport/mecmouse.h
index 6d859376cd7..e6d29e79a07 100644
--- a/src/devices/bus/ti99/joyport/mecmouse.h
+++ b/src/devices/bus/ti99/joyport/mecmouse.h
@@ -16,7 +16,7 @@
#include "joyport.h"
-namespace bus { namespace ti99 { namespace joyport {
+namespace bus::ti99::joyport {
class mecmouse_device : public device_t, public device_ti99_joyport_interface
{
@@ -27,12 +27,17 @@ public:
void write_dev(uint8_t data) override;
protected:
- virtual void device_start() override;
- virtual void device_reset() override;
- virtual ioport_constructor device_input_ports() const override;
- virtual void device_timer(emu_timer &timer, device_timer_id id, int param, void *ptr) override;
+ virtual void device_start() override ATTR_COLD;
+ virtual void device_reset() override ATTR_COLD;
+ virtual ioport_constructor device_input_ports() const override ATTR_COLD;
+
+ TIMER_CALLBACK_MEMBER(poll_mouse);
private:
+ required_ioport m_mousex;
+ required_ioport m_mousey;
+ required_ioport m_mousebutton;
+
int m_last_select;
bool m_read_y_axis;
int m_x;
@@ -44,7 +49,8 @@ private:
emu_timer *m_poll_timer;
};
-} } } // end namespace bus::ti99::joyport
+
+} // end namespace bus::ti99::joyport
DECLARE_DEVICE_TYPE_NS(TI99_MECMOUSE, bus::ti99::joyport, mecmouse_device)
diff --git a/src/devices/bus/ti99/peb/bwg.cpp b/src/devices/bus/ti99/peb/bwg.cpp
index d6e738f90eb..25472b0ed12 100644
--- a/src/devices/bus/ti99/peb/bwg.cpp
+++ b/src/devices/bus/ti99/peb/bwg.cpp
@@ -50,22 +50,22 @@
// ----------------------------------
// 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_NS(TI99_BWG, bus::ti99::peb, snug_bwg_device, "ti99_bwg", "SNUG BwG Floppy Controller")
+DEFINE_DEVICE_TYPE(TI99_BWG, bus::ti99::peb::snug_bwg_device, "ti99_bwg", "SNUG BwG Floppy Controller")
-namespace bus { namespace ti99 { namespace peb {
+namespace bus::ti99::peb {
// ----------------------------------
@@ -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;
@@ -141,7 +142,7 @@ WRITE_LINE_MEMBER( snug_bwg_device::fdc_drq_w )
operate_ready_line();
}
-SETADDRESS_DBIN_MEMBER( snug_bwg_device::setaddress_dbin )
+void snug_bwg_device::setaddress_dbin(offs_t offset, int state)
{
// Do not allow setaddress for debugger
if (machine().side_effects_disabled()) return;
@@ -150,7 +151,7 @@ SETADDRESS_DBIN_MEMBER( snug_bwg_device::setaddress_dbin )
// Is the card being selected?
m_address = offset;
- m_inDsrArea = ((m_address & m_select_mask)==m_select_value);
+ m_inDsrArea = in_dsr_space(m_address, true);
if (!m_inDsrArea) return;
@@ -196,7 +197,7 @@ SETADDRESS_DBIN_MEMBER( snug_bwg_device::setaddress_dbin )
*/
void snug_bwg_device::debug_read(offs_t offset, uint8_t* value)
{
- if (((offset & m_select_mask)==m_select_value) && m_selected)
+ if (in_dsr_space(offset, true) && m_selected)
{
if ((offset & 0x1c00)==0x1c00)
{
@@ -210,7 +211,7 @@ void snug_bwg_device::debug_read(offs_t offset, uint8_t* value)
void snug_bwg_device::debug_write(offs_t offset, uint8_t data)
{
- if (((offset & m_select_mask)==m_select_value) && m_selected)
+ if (in_dsr_space(offset, true) && m_selected)
{
if (((offset & 0x1c00)==0x1c00) && ((offset & 0x1fe0)!=0x1fe0))
m_buffer_ram->pointer()[(m_crulatch8_15->q5_r()<<10) | (m_address & 0x03ff)] = data;
@@ -221,7 +222,7 @@ void snug_bwg_device::debug_write(offs_t offset, uint8_t data)
Read a byte from ROM, RAM, FDC, or RTC. See setaddress_dbin for selection
logic.
*/
-READ8Z_MEMBER(snug_bwg_device::readz)
+void snug_bwg_device::readz(offs_t offset, uint8_t *value)
{
if (machine().side_effects_disabled())
{
@@ -346,7 +347,7 @@ void snug_bwg_device::write(offs_t offset, uint8_t data)
bit 6: Dip 3
bit 7: Dip 4
*/
-READ8Z_MEMBER(snug_bwg_device::crureadz)
+void snug_bwg_device::crureadz(offs_t offset, uint8_t *value)
{
uint8_t reply;
@@ -355,10 +356,10 @@ READ8Z_MEMBER(snug_bwg_device::crureadz)
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();
@@ -527,17 +529,6 @@ void snug_bwg_device::device_start()
void snug_bwg_device::device_reset()
{
- if (m_genmod)
- {
- m_select_mask = 0x1fe000;
- m_select_value = 0x174000;
- }
- else
- {
- m_select_mask = 0x7e000;
- m_select_value = 0x74000;
- }
-
m_DRQ = CLEAR_LINE;
m_IRQ = CLEAR_LINE;
m_MOTOR_ON = CLEAR_LINE;
@@ -553,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);
@@ -568,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" )
@@ -599,10 +578,12 @@ INPUT_PORTS_START( bwg_fdc )
PORT_DIPSETTING( 0x03, "DSK1-DSK4")
INPUT_PORTS_END
-FLOPPY_FORMATS_MEMBER(snug_bwg_device::floppy_formats)
- FLOPPY_TI99_SDF_FORMAT,
- FLOPPY_TI99_TDF_FORMAT
-FLOPPY_FORMATS_END
+void snug_bwg_device::floppy_formats(format_registration &fr)
+{
+ fr.add_mfm_containers();
+ fr.add(FLOPPY_TI99_SDF_FORMAT);
+ fr.add(FLOPPY_TI99_TDF_FORMAT);
+}
static void bwg_floppies(device_slot_interface &device)
{
@@ -624,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);
@@ -664,4 +645,4 @@ const tiny_rom_entry *snug_bwg_device::device_rom_region() const
return ROM_NAME( bwg_fdc );
}
-} } } // end namespace bus::ti99::peb
+} // end namespace bus::ti99::peb
diff --git a/src/devices/bus/ti99/peb/bwg.h b/src/devices/bus/ti99/peb/bwg.h
index 93c484aeb50..13d746a5cd8 100644
--- a/src/devices/bus/ti99/peb/bwg.h
+++ b/src/devices/bus/ti99/peb/bwg.h
@@ -11,8 +11,8 @@
*****************************************************************************/
-#ifndef MAME_BUS_TI99_PED_BWG_H
-#define MAME_BUS_TI99_PED_BWG_H
+#ifndef MAME_BUS_TI99_PEB_BWG_H
+#define MAME_BUS_TI99_PEB_BWG_H
#pragma once
@@ -24,48 +24,47 @@
#include "machine/74259.h"
#include "machine/74123.h"
-namespace bus { namespace ti99 { namespace peb {
+namespace bus::ti99::peb {
class snug_bwg_device : public device_t, public device_ti99_peribox_card_interface
{
public:
snug_bwg_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
- DECLARE_READ8Z_MEMBER(readz) override;
+ void readz(offs_t offset, uint8_t *value) override;
void write(offs_t offset, uint8_t data) override;
- DECLARE_SETADDRESS_DBIN_MEMBER(setaddress_dbin) override;
+ void setaddress_dbin(offs_t offset, int state) override;
- DECLARE_READ8Z_MEMBER(crureadz) override;
+ void crureadz(offs_t offset, uint8_t *value) override;
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 ATTR_COLD;
+ virtual void device_reset() override ATTR_COLD;
- 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 const tiny_rom_entry *device_rom_region() const override ATTR_COLD;
+ virtual void device_add_mconfig(machine_config &config) override ATTR_COLD;
+ virtual ioport_constructor device_input_ports() const override ATTR_COLD;
private:
- DECLARE_FLOPPY_FORMATS( floppy_formats );
+ 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;
@@ -132,8 +131,8 @@ private:
required_device<ttl74123_device> m_motormf;
};
-} } } // end namespace bus::ti99::peb
+} // end namespace bus::ti99::peb
DECLARE_DEVICE_TYPE_NS(TI99_BWG, bus::ti99::peb, snug_bwg_device)
-#endif // MAME_BUS_TI99_PED_BWG_H
+#endif // MAME_BUS_TI99_PEB_BWG_H
diff --git a/src/devices/bus/ti99/peb/cc_fdc.cpp b/src/devices/bus/ti99/peb/cc_fdc.cpp
new file mode 100644
index 00000000000..7663abe04d8
--- /dev/null
+++ b/src/devices/bus/ti99/peb/cc_fdc.cpp
@@ -0,0 +1,809 @@
+// license:LGPL-2.1+
+// copyright-holders:Michael Zapf
+/*******************************************************************************
+ CorComp Disk Controller
+ Based on WD2793/WD1773
+ Double Density, Double-sided
+
+ Two flavors:
+
+ * Original controller
+ Named "PEB-DCC"
+ Single 16K EPROM or two 8K EPROMs (selectable by jumper; only 2x8K emulated)
+ Two PALs
+ WD2793
+
+ * Modified controller with redesigned PCB
+ Named "CorComp FDC Rev A"
+ Two 8K EPROMs (by Millers Graphics, 3rd party HW/SW contributor)
+ Two PALs
+ WD1773
+
+ Michael Zapf
+ March 2020
+
+*******************************************************************************/
+
+#include "emu.h"
+#include "cc_fdc.h"
+#include "formats/ti99_dsk.h"
+#include "machine/rescap.h"
+
+// ----------------------------------
+// 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)
+#include "logmacro.h"
+
+#define CCDCC_TAG "ti99_ccdcc"
+#define CCFDC_TAG "ti99_ccfdc"
+#define WDC_TAG "wdfdc"
+#define MOTORMF_TAG "motor_mf"
+#define TMS9901_TAG "tms9901"
+
+#define CCDCC_PALU2_TAG "palu2"
+#define CCDCC_PALU1_TAG "palu1"
+#define CCFDC_PALU12_TAG "palu12"
+#define CCFDC_PALU6_TAG "palu6"
+
+#define BUFFER "ram"
+
+DEFINE_DEVICE_TYPE(TI99_CCDCC, bus::ti99::peb::corcomp_dcc_device, CCDCC_TAG, "CorComp Disk Controller Card")
+DEFINE_DEVICE_TYPE(TI99_CCFDC, bus::ti99::peb::corcomp_fdca_device, CCFDC_TAG, "CorComp Floppy Disk Controller Card Rev A")
+
+DEFINE_DEVICE_TYPE(CCDCC_PALU2, bus::ti99::peb::ccdcc_palu2_device, CCDCC_PALU2_TAG, "CorComp DCC PAL u2")
+DEFINE_DEVICE_TYPE(CCDCC_PALU1, bus::ti99::peb::ccdcc_palu1_device, CCDCC_PALU1_TAG, "CorComp DCC PAL u1")
+
+DEFINE_DEVICE_TYPE(CCFDC_PALU12, bus::ti99::peb::ccfdc_palu12_device, CCFDC_PALU12_TAG, "CorComp FDC PAL u12")
+DEFINE_DEVICE_TYPE(CCFDC_PALU6, bus::ti99::peb::ccfdc_palu6_device, CCFDC_PALU6_TAG, "CorComp FDC PAL u6")
+
+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, 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(*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),
+ m_dsrrom(nullptr),
+ m_cardsel(false),
+ m_banksel(false),
+ m_selected_drive(0),
+ m_address(0),
+ m_writing(false)
+{
+}
+
+void corcomp_fdc_device::setaddress_dbin(offs_t offset, int state)
+{
+ // Do not allow setaddress for debugger
+ if (machine().side_effects_disabled()) return;
+ m_address = offset;
+ m_writing = (state==CLEAR_LINE);
+ operate_ready_line();
+}
+
+/*
+ Provides the current address to the PALs.
+*/
+offs_t corcomp_fdc_device::get_address()
+{
+ return m_address;
+}
+
+/*
+ Before the 9901 configures the P11 pin as output, it delivers Z output,
+ which is pulled down by R10 on the board. We implement this by using a
+ variable.
+*/
+bool corcomp_fdc_device::upper_bank()
+{
+ return m_banksel;
+}
+
+bool corcomp_fdc_device::card_selected()
+{
+ return m_cardsel;
+}
+
+bool corcomp_fdc_device::write_access()
+{
+ return m_writing;
+}
+
+/*
+ The Debugging access must not have any side effect on the controller.
+ We only allow access to the EPROM and RAM.
+*/
+void corcomp_fdc_device::debug_read(offs_t offset, uint8_t* value)
+{
+ offs_t saveaddress = m_address;
+
+ m_address = offset;
+ *value = 0x00;
+
+ if (m_ctrlpal->selectram())
+ {
+ // SRAM selected
+ *value = m_buffer_ram->pointer()[m_address & 0x7f] & 0xf0; // only the first 4 bits
+ }
+
+ if (m_ctrlpal->selectdsr())
+ {
+ // EPROM selected
+ offs_t base = m_banksel? 0x2000 : 0;
+ uint8_t* rom = &m_dsrrom[base | (m_address & 0x1fff)];
+ *value = *rom;
+ }
+ m_address = saveaddress;
+}
+
+void corcomp_fdc_device::debug_write(offs_t offset, uint8_t data)
+{
+ offs_t saveaddress = m_address;
+ m_address = offset;
+ if (m_ctrlpal->selectram())
+ {
+ m_buffer_ram->pointer()[m_address & 0x7f] = data & 0xf0; // only the first 4 bits
+ }
+ m_address = saveaddress;
+}
+
+/*
+ Operate the wait state logic.
+*/
+void corcomp_fdc_device::operate_ready_line()
+{
+ line_state ready = (line_state)m_ctrlpal->ready_out();
+ m_slot->set_ready(ready);
+}
+
+/*
+ Callbacks from the WDC chip
+*/
+void corcomp_fdc_device::fdc_irq_w(int state)
+{
+ LOGMASKED(LOG_SIGNALS, "INTRQ callback = %d\n", state);
+ operate_ready_line();
+}
+
+void corcomp_fdc_device::fdc_drq_w(int state)
+{
+ LOGMASKED(LOG_DRQ, "DRQ callback = %d\n", state);
+ operate_ready_line();
+}
+
+void corcomp_fdc_device::fdc_hld_w(int state)
+{
+ LOGMASKED(LOG_SIGNALS, "HLD callback = %d\n", state);
+}
+
+void corcomp_fdc_device::readz(offs_t offset, uint8_t *value)
+{
+ if (machine().side_effects_disabled())
+ {
+ debug_read(offset, value);
+ return;
+ }
+
+ if (m_ctrlpal->selectram())
+ {
+ // SRAM selected
+ *value = m_buffer_ram->pointer()[m_address & 0x7f] & 0xf0; // only the first 4 bits
+ LOGMASKED(LOG_RAM, "Read RAM: %04x -> %02x\n", m_address & 0xffff, *value);
+ }
+
+ if (m_ctrlpal->selectwdc())
+ {
+ // WDC selected
+ *value = m_wdc->read((m_address >> 1)&0x03);
+ LOGMASKED(LOG_CONTR, "Read FDC: %04x -> %02x\n", m_address & 0xffff, *value);
+ }
+
+ if (m_ctrlpal->selectdsr())
+ {
+ // EPROM selected
+ offs_t base = m_banksel? 0x2000 : 0;
+ uint8_t* rom = &m_dsrrom[base | (m_address & 0x1fff)];
+ *value = *rom;
+
+ if (WORD_ALIGNED(m_address))
+ {
+ uint16_t val = (*rom << 8) | (*(rom+1));
+ LOGMASKED(LOG_EPROM, "Read DSR: %04x (page %d)-> %04x\n", m_address & 0xffff, base>>13, val);
+ }
+ }
+}
+
+void corcomp_fdc_device::write(offs_t offset, uint8_t data)
+{
+ if (machine().side_effects_disabled())
+ {
+ debug_write(offset, data);
+ return;
+ }
+ if (m_ctrlpal->selectram())
+ {
+ // SRAM selected
+ LOGMASKED(LOG_RAM, "Write RAM: %04x <- %02x\n", m_address & 0xffff, data&0xf0);
+ m_buffer_ram->pointer()[m_address & 0x7f] = data & 0xf0; // only the first 4 bits
+ }
+
+ if (m_ctrlpal->selectwdc())
+ {
+ // WDC selected
+ LOGMASKED(LOG_CONTR, "Write FDC: %04x <- %02x\n", m_address & 0xffff, data);
+ m_wdc->write((m_address >> 1)&0x03, data);
+ }
+}
+
+void corcomp_fdc_device::crureadz(offs_t offset, uint8_t *value)
+{
+ m_address = offset; // Copy the CRU address on the address variable
+ if (m_decpal->address9901())
+ {
+ // The S0 select line is inverted, which means that
+ // a CRU address of 0x1120 is actually address 0x00 for the 9901,
+ // while the CRU address 0x1100 is 0x20 for the 9901.
+ // This trick is necessary to relocate the P0 line to the
+ // first CRU address, which by convention turns on the EPROM
+ // of the card.
+ int bitno = ((offset & 0x3e)^0x20)>>1;
+ *value = m_tms9901->read_bit(bitno)? 0x01 : 0x00;
+ LOGMASKED(LOG_CRU, "cru %04x (bit %d) -> %d\n", offset, bitno, *value);
+ }
+}
+
+void corcomp_fdc_device::cruwrite(offs_t offset, uint8_t data)
+{
+ m_address = offset; // Copy the CRU address on the address variable
+ if (m_decpal->address9901())
+ {
+ int bitno = ((offset & 0x3e)^0x20)>>1;
+ LOGMASKED(LOG_CRU, "cru %04x (bit %d) <- %d\n", offset, bitno, data);
+ m_tms9901->write_bit(bitno, data!=0);
+ }
+}
+
+void corcomp_fdc_device::clock_in(int state)
+{
+ m_tms9901->phi_line(state);
+}
+
+uint8_t corcomp_fdc_device::tms9901_input(offs_t offset)
+{
+ // Inputs
+ // INT1: Switch 8
+ // INT2: Switch 1
+ // INT3: Switch 7
+ // INT4: Switch 5
+ // INT5: Switch 3
+ // INT6: Switch 2
+ // INT7: Switch 4
+ // INT8: Switch 6
+ // INT9: -
+ // P9: MotorMF
+ // P12: WDCu11.28 (HLD)
+ const uint8_t dipswitch[] = { 0x00, 0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80 };
+
+ switch (offset)
+ {
+ case tms9901_device::INT1:
+ return ((ioport("HEADSTEP")->read() & dipswitch[8])!=0)? 0:1;
+ case tms9901_device::INT2:
+ return ((ioport("HEADSTEP")->read() & dipswitch[1])!=0)? 0:1;
+ case tms9901_device::INT3:
+ return ((ioport("HEADSTEP")->read() & dipswitch[7])!=0)? 0:1;
+ case tms9901_device::INT4:
+ return ((ioport("HEADSTEP")->read() & dipswitch[5])!=0)? 0:1;
+ case tms9901_device::INT5:
+ return ((ioport("HEADSTEP")->read() & dipswitch[3])!=0)? 0:1;
+ case tms9901_device::INT6:
+ return ((ioport("HEADSTEP")->read() & dipswitch[2])!=0)? 0:1;
+ case tms9901_device::INT7_P15:
+ return ((ioport("HEADSTEP")->read() & dipswitch[4])!=0)? 0:1;
+ case tms9901_device::INT8_P14:
+ return ((ioport("HEADSTEP")->read() & dipswitch[6])!=0)? 0:1;
+ case tms9901_device::INT10_P12:
+ return (m_wdc->hld_r()==ASSERT_LINE)? 1:0;
+ case tms9901_device::INT13_P9:
+ return (m_motormf->q_r()==0)? 1:0;
+ default:
+ return 1;
+ }
+}
+
+void corcomp_fdc_device::select_dsk(int state)
+{
+ if (state == CLEAR_LINE)
+ {
+ if ( (!m_tms9901->read_bit(tms9901_device::P4))
+ && (!m_tms9901->read_bit(tms9901_device::P5))
+ && (!m_tms9901->read_bit(tms9901_device::P6))
+ && (!m_tms9901->read_bit(tms9901_device::INT14_P8)))
+ {
+ LOGMASKED(LOG_DRIVE, "Unselect all drives\n");
+ m_wdc->set_floppy(nullptr);
+ m_selected_drive = 0;
+ }
+ }
+ else
+ {
+ if (m_tms9901->read_bit(tms9901_device::P4))
+ {
+ m_selected_drive = 1;
+ }
+ else if (m_tms9901->read_bit(tms9901_device::P5))
+ {
+ m_selected_drive = 2;
+ }
+ else if (m_tms9901->read_bit(tms9901_device::P6))
+ {
+ m_selected_drive = 3;
+ }
+ else if (m_tms9901->read_bit(tms9901_device::INT14_P8))
+ {
+ m_selected_drive = 4;
+ }
+ LOGMASKED(LOG_DRIVE, "Select drive DSK%d\n", m_selected_drive);
+
+ if (m_floppy[m_selected_drive-1]->get_device() != nullptr)
+ {
+ m_wdc->set_floppy(m_floppy[m_selected_drive-1]->get_device());
+ side_select(m_tms9901->read_bit(tms9901_device::INT15_P7));
+ }
+ else
+ LOGMASKED(LOG_WARN, "No drive connected as DSK%d\n", m_selected_drive);
+ }
+}
+
+void corcomp_fdc_device::side_select(int state)
+{
+ // Select side of disk (bit 7)
+ if (m_selected_drive != 0)
+ {
+ if (m_floppy[m_selected_drive-1]->get_device() != nullptr)
+ {
+ LOGMASKED(LOG_DRIVE, "Set side (bit 7) = %d on DSK%d\n", state, m_selected_drive);
+ m_floppy[m_selected_drive-1]->get_device()->ss_w(state);
+ }
+ else
+ LOGMASKED(LOG_WARN, "No drive connected as DSK%d\n", m_selected_drive);
+ }
+}
+
+/*
+ All floppy motors are operated by the same line.
+*/
+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->get_device() != nullptr)
+ elem->get_device()->mon_w((state==ASSERT_LINE)? 0 : 1);
+
+ operate_ready_line();
+}
+
+/*
+ Push the P11 state to the variable.
+*/
+void corcomp_fdc_device::select_bank(int state)
+{
+ LOGMASKED(LOG_CRU, "Set bank %d\n", state);
+ m_banksel = (state==ASSERT_LINE);
+ operate_ready_line();
+}
+
+void corcomp_fdc_device::select_card(int state)
+{
+ LOGMASKED(LOG_CRU, "Select card = %d\n", state);
+ m_cardsel = (state==ASSERT_LINE);
+ operate_ready_line();
+}
+
+// =========================================================================
+
+void corcomp_fdc_device::device_start()
+{
+ m_dsrrom = memregion(TI99_DSRROM)->base();
+ save_item(NAME(m_address));
+ save_item(NAME(m_writing));
+ save_item(NAME(m_cardsel));
+ save_item(NAME(m_banksel));
+ save_item(NAME(m_selected_drive));
+}
+
+void corcomp_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());
+ }
+
+ m_decpal->set_board(this);
+ m_ctrlpal->set_board(this);
+ m_ctrlpal->set_decoder(m_decpal);
+}
+
+INPUT_PORTS_START( cc_fdc )
+ PORT_START( "HEADSTEP" )
+ PORT_DIPNAME( 0x03, 0x02, "DSK1 head step time" )
+ PORT_DIPSETTING( 0x00, "15 ms")
+ PORT_DIPSETTING( 0x01, "10 ms")
+ PORT_DIPSETTING( 0x02, "6 ms")
+ PORT_DIPSETTING( 0x03, "3 ms")
+ PORT_DIPNAME( 0x0c, 0x08, "DSK2 head step time" )
+ PORT_DIPSETTING( 0x00, "15 ms")
+ PORT_DIPSETTING( 0x04, "10 ms")
+ PORT_DIPSETTING( 0x08, "6 ms")
+ PORT_DIPSETTING( 0x0c, "3 ms")
+ PORT_DIPNAME( 0x30, 0x20, "DSK3 head step time" )
+ PORT_DIPSETTING( 0x00, "15 ms")
+ PORT_DIPSETTING( 0x10, "10 ms")
+ PORT_DIPSETTING( 0x20, "6 ms")
+ PORT_DIPSETTING( 0x30, "3 ms")
+ PORT_DIPNAME( 0xc0, 0x80, "DSK4 head step time" )
+ PORT_DIPSETTING( 0x00, "15 ms")
+ PORT_DIPSETTING( 0x40, "10 ms")
+ PORT_DIPSETTING( 0x80, "6 ms")
+ PORT_DIPSETTING( 0xc0, "3 ms")
+INPUT_PORTS_END
+
+void corcomp_fdc_device::floppy_formats(format_registration &fr)
+{
+ fr.add_mfm_containers();
+ fr.add(FLOPPY_TI99_SDF_FORMAT);
+ fr.add(FLOPPY_TI99_TDF_FORMAT);
+}
+
+static void ccfdc_floppies(device_slot_interface &device)
+{
+ device.option_add("525dd", FLOPPY_525_DD); // 40 tracks
+ device.option_add("525qd", FLOPPY_525_QD); // 80 tracks
+ device.option_add("35dd", FLOPPY_35_DD); // 80 tracks
+}
+
+void corcomp_fdc_device::common_config(machine_config& config)
+{
+ m_wdc->intrq_wr_callback().set(FUNC(corcomp_fdc_device::fdc_irq_w));
+ m_wdc->drq_wr_callback().set(FUNC(corcomp_fdc_device::fdc_drq_w));
+ m_wdc->hld_wr_callback().set(FUNC(corcomp_fdc_device::fdc_hld_w));
+
+ TMS9901(config, m_tms9901, 0);
+ m_tms9901->read_cb().set(FUNC(corcomp_fdc_device::tms9901_input));
+
+ // Outputs
+ // P0: LED (DSR?), PALu2.1
+ // P1: MFu6.clk (Motor)
+ // P2: PALu1.5 (WATEN)
+ // P3: WDCu11.50 (HLT)
+ // P4: DSK1 select
+ // P5: DSK2 select
+ // P6: DSK3 select
+ // P7: SIDSEL
+ // P8: DSK4 select
+ // P10: WDCu11.37 (DDEN)
+ // P11: ROMBNK
+ // P13: -
+ // P14: -
+ // P15: -
+ m_tms9901->p_out_cb(0).set(FUNC(corcomp_fdc_device::select_card));
+ m_tms9901->p_out_cb(1).set(MOTORMF_TAG, FUNC(ttl74123_device::b_w));
+ m_tms9901->p_out_cb(4).set(FUNC(corcomp_fdc_device::select_dsk));
+ m_tms9901->p_out_cb(5).set(FUNC(corcomp_fdc_device::select_dsk));
+ m_tms9901->p_out_cb(6).set(FUNC(corcomp_fdc_device::select_dsk));
+ m_tms9901->p_out_cb(7).set(FUNC(corcomp_fdc_device::side_select));
+ m_tms9901->p_out_cb(8).set(FUNC(corcomp_fdc_device::select_dsk));
+ m_tms9901->p_out_cb(10).set(WDC_TAG, FUNC(wd_fdc_device_base::dden_w));
+ m_tms9901->p_out_cb(11).set(FUNC(corcomp_fdc_device::select_bank));
+
+ // Motor monoflop
+ TTL74123(config, m_motormf, 0);
+ m_motormf->set_connection_type(TTL74123_GROUNDED);
+ m_motormf->set_resistor_value(RES_K(100));
+ m_motormf->set_capacitor_value(CAP_U(47));
+ m_motormf->set_a_pin_value(0);
+ m_motormf->set_b_pin_value(1);
+ m_motormf->set_clear_pin_value(1);
+ m_motormf->out_cb().set(FUNC(corcomp_fdc_device::motor_w));
+
+ 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);
+}
+
+// ============================================================================
+// Original CorComp Disk Controller Card (PEB-DCC)
+// ============================================================================
+
+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, CCDCC_PALU2_TAG, CCDCC_PALU1_TAG)
+{
+}
+
+void corcomp_dcc_device::device_add_mconfig(machine_config& config)
+{
+ WD2793(config, m_wdc, 4_MHz_XTAL / 4);
+ common_config(config);
+
+ // For the 2793, attach the HLT line
+ m_tms9901->p_out_cb(3).set(WDC_TAG, FUNC(wd_fdc_device_base::hlt_w));
+
+ // PAL circuits are connected in device_config_complete
+ CCDCC_PALU2(config, CCDCC_PALU2_TAG, 0);
+ CCDCC_PALU1(config, CCDCC_PALU1_TAG, 0);
+}
+
+ROM_START( cc_dcc )
+ ROM_REGION(0x4000, TI99_DSRROM, 0)
+ ROM_LOAD("ccdcc_v89.u3", 0x0000, 0x2000, CRC(de3f9476) SHA1(b88aea1141769dad4e4bea5f93ac4f63a627cc82)) /* 8K single ROM bank 1*/
+ ROM_LOAD("ccdcc_v89.u4", 0x2000, 0x2000, CRC(9c4e5c08) SHA1(26f8096ae60f3839902b4e8764c5fde283ad4ba2)) /* 8K single ROM bank 2*/
+ROM_END
+
+ioport_constructor corcomp_fdc_device::device_input_ports() const
+{
+ return INPUT_PORTS_NAME( cc_fdc );
+}
+
+const tiny_rom_entry *corcomp_dcc_device::device_rom_region() const
+{
+ return ROM_NAME( cc_dcc );
+}
+
+// ========================================================================
+// PAL circuits on the CorComp board
+// ========================================================================
+
+ccfdc_dec_pal_device::ccfdc_dec_pal_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_board(nullptr),
+ m_tms9901(*owner, TMS9901_TAG)
+{
+}
+
+ccfdc_sel_pal_device::ccfdc_sel_pal_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_board(nullptr),
+ m_decpal(nullptr),
+ m_motormf(*owner, MOTORMF_TAG),
+ m_tms9901(*owner, TMS9901_TAG),
+ m_wdc(*owner, WDC_TAG)
+{
+}
+
+/*
+ Indicates 9901 addressing.
+*/
+int ccfdc_dec_pal_device::address9901()
+{
+ return ((m_board->get_address() & 0xff80)==0x1100)? ASSERT_LINE : CLEAR_LINE;
+}
+
+/*
+ Indicates SRAM addressing.
+*/
+int ccfdc_dec_pal_device::addressram()
+{
+ return ((m_board->card_selected()) &&
+ (m_board->get_address() & 0xff80)==0x4000)? ASSERT_LINE : CLEAR_LINE;
+}
+
+/*
+ Indicates WDC addressing.
+*/
+int ccfdc_dec_pal_device::addresswdc()
+{
+ return ((m_board->card_selected()) &&
+ (m_board->get_address() & 0xff80)==0x5f80)? ASSERT_LINE : CLEAR_LINE;
+}
+
+/*
+ Indicates DSR addressing.
+*/
+int ccfdc_dec_pal_device::address4()
+{
+ return ((m_board->card_selected()) &&
+ (m_board->get_address() & 0xe000)==0x4000)? ASSERT_LINE : CLEAR_LINE;
+}
+
+/*
+ Indicates SRAM selection.
+*/
+int ccfdc_sel_pal_device::selectram()
+{
+ return (m_decpal->addressram() && (m_board->upper_bank()))
+ ? ASSERT_LINE : CLEAR_LINE;
+}
+
+/*
+ Indicates WDC selection.
+*/
+int ccfdc_sel_pal_device::selectwdc()
+{
+ return (m_decpal->addresswdc() && ((m_board->get_address()&1)==0))? ASSERT_LINE : CLEAR_LINE;
+}
+
+/*
+ Indicates EPROM selection.
+*/
+int ccfdc_sel_pal_device::selectdsr()
+{
+ return (m_decpal->address4()
+ && !m_decpal->addresswdc()
+ && !(m_decpal->addressram() && (m_board->upper_bank())))
+ ? ASSERT_LINE : CLEAR_LINE;
+}
+
+// ========================================================================
+// PAL circuits on the original CorComp board
+// PAL u2 is the address decoder, delivering its results to the
+// selector PAL u1.
+// ========================================================================
+
+ccdcc_palu2_device::ccdcc_palu2_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
+ : ccfdc_dec_pal_device(mconfig, CCDCC_PALU2, tag, owner, clock)
+{
+}
+
+ccdcc_palu1_device::ccdcc_palu1_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
+ : ccfdc_sel_pal_device(mconfig, CCDCC_PALU1, tag, owner, clock)
+{
+}
+
+/*
+ Wait state logic
+*/
+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)
+ bool trap = m_tms9901->read_bit(tms9901_device::P2); // Wait state generation is active (SBO 2)
+ 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
+ bool motor = (m_motormf->q_r()==1); // The disk is spinning
+
+ line_state ready = (wdc && lastdig && trap && waitbyte && noterm && motor)? CLEAR_LINE : ASSERT_LINE; // then clear READY and thus trigger wait states
+
+ LOGMASKED(LOG_READY, "READY = %d (%d,%d,%d,%d,%d,%d)\n", ready, wdc, lastdig, trap, waitbyte, noterm, motor);
+ return ready;
+}
+
+// ============================================================================
+// 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, CCFDC_PALU12_TAG, CCFDC_PALU6_TAG)
+{
+}
+
+void corcomp_fdca_device::device_add_mconfig(machine_config& config)
+{
+ WD1773(config, m_wdc, 8_MHz_XTAL);
+ common_config(config);
+
+ // PAL circuits are connected in device_config_complete
+ CCFDC_PALU12(config, CCFDC_PALU12_TAG, 0);
+ CCFDC_PALU6(config, CCFDC_PALU6_TAG, 0);
+}
+
+/*
+ READY trap circuitry on the revised board (U10)
+*/
+bool corcomp_fdca_device::ready_trap_active()
+{
+ return m_tms9901->read_bit(tms9901_device::P2)
+ && ((m_address & 6)==6)
+ && (m_motormf->q_r()==1);
+}
+
+ROM_START( cc_fdcmg )
+ ROM_REGION(0x8000, TI99_DSRROM, 0)
+ ROM_LOAD("ccfdc_v89mg.u1", 0x0000, 0x2000, CRC(f010e273) SHA1(bd30103d80c43d4b35e0669145cef7b5c6b9813b)) /* 16K single ROM */
+ ROM_LOAD("ccfdc_v89mg.u2", 0x2000, 0x2000, CRC(0cad8f5b) SHA1(7744f777b51eedf614f766576bbc3f8c2c2e0042)) /* 16K single ROM */
+ROM_END
+
+const tiny_rom_entry *corcomp_fdca_device::device_rom_region() const
+{
+ return ROM_NAME( cc_fdcmg );
+}
+
+// ========================================================================
+// PAL circuits on the revised CorComp board
+// PAL u12 is the address decoder, delivering its results to the
+// selector PAL u6.
+// ========================================================================
+
+ccfdc_palu12_device::ccfdc_palu12_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
+ : ccfdc_dec_pal_device(mconfig, CCFDC_PALU12, tag, owner, clock)
+{
+}
+
+/*
+ Indicates 9901 addressing. In this PAL version, the A9 address line is
+ also used.
+*/
+int ccfdc_palu12_device::address9901()
+{
+ return ((m_board->get_address() & 0xffc0)==0x1100)? ASSERT_LINE : CLEAR_LINE;
+}
+
+ccfdc_palu6_device::ccfdc_palu6_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
+ : ccfdc_sel_pal_device(mconfig, CCFDC_PALU6, tag, owner, clock)
+{
+}
+
+/*
+ Indicates WDC selection. Also checks whether A12 and /WE match.
+ That is, when writing (/WE=0), A12 must be 1 (addresses 5ff8..e),
+ otherwise (/WE=1), A12 must be 0 (addresses 5ff0..6)
+*/
+int ccfdc_palu6_device::selectwdc()
+{
+ return (m_decpal->addresswdc()
+ && ((m_board->get_address()&1)==0)
+ && (((m_board->get_address()&8)!=0)==(m_board->write_access())))? ASSERT_LINE : CLEAR_LINE;
+}
+
+/*
+ Indicates EPROM selection. The Rev A selector PAL leads back some of
+ its outputs for this calculation.
+*/
+int ccfdc_palu6_device::selectdsr()
+{
+ return (m_decpal->address4() && !selectwdc() && !selectram())? ASSERT_LINE : CLEAR_LINE;
+}
+
+/*
+ Wait state logic. The Rev A selector relies on an AND circuit on the
+ board which evaluates whether the trap is active.
+*/
+
+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 = 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
+
+ line_state ready = (wdc && even && trap && waitbyte && noterm)? CLEAR_LINE : ASSERT_LINE; // then clear READY and thus trigger wait states
+
+ LOGMASKED(LOG_READY, "READY = %d (%d,%d,%d,%d,%d)\n", ready, wdc, even, trap, waitbyte, noterm);
+ return ready;
+}
+
+} // 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
new file mode 100644
index 00000000000..0946c6246fd
--- /dev/null
+++ b/src/devices/bus/ti99/peb/cc_fdc.h
@@ -0,0 +1,249 @@
+// license:LGPL-2.1+
+// copyright-holders:Michael Zapf
+/****************************************************************************
+
+ Corcomp Disk Controller
+ Based on WD2793/WD1773
+ Double Density, Double-sided
+
+ Michael Zapf, March 2020
+
+*****************************************************************************/
+
+#ifndef MAME_BUS_TI99_PEB_CC_FDC_H
+#define MAME_BUS_TI99_PEB_CC_FDC_H
+
+#pragma once
+
+#include "peribox.h"
+#include "imagedev/floppy.h"
+#include "machine/wd_fdc.h"
+#include "machine/74123.h"
+#include "machine/tms9901.h"
+#include "machine/ram.h"
+
+namespace bus::ti99::peb {
+
+class ccfdc_dec_pal_device;
+class ccfdc_sel_pal_device;
+class ccfdc_palu12_device;
+class ccfdc_palu6_device;
+
+class corcomp_fdc_device : public device_t, public device_ti99_peribox_card_interface
+{
+ friend class ccfdc_dec_pal_device;
+ friend class ccfdc_sel_pal_device;
+ friend class ccdcc_palu1_device;
+ friend class ccfdc_palu6_device;
+ friend class ccfdc_palu12_device;
+
+public:
+ void readz(offs_t offset, uint8_t *value) override;
+ void write(offs_t offset, uint8_t data) override;
+ void setaddress_dbin(offs_t offset, int state) override;
+
+ void crureadz(offs_t offset, uint8_t *value) override;
+ void cruwrite(offs_t offset, uint8_t data) override;
+ void clock_in(int state) override;
+
+ 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);
+ 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, const char *dpname, const char *cpname);
+
+ virtual void device_start() override ATTR_COLD;
+ virtual void device_reset() override ATTR_COLD;
+
+ virtual void device_add_mconfig(machine_config &config) override =0;
+ virtual ioport_constructor device_input_ports() const override ATTR_COLD;
+
+ void common_config(machine_config& config);
+
+ static void floppy_formats(format_registration &fr);
+
+ // Link to the WD controller on the board.
+ required_device<wd_fdc_device_base> m_wdc;
+
+ // PALs
+ 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();
+ bool upper_bank();
+ bool write_access();
+ bool ready_trap_active();
+
+ // Deliver the current state of the address bus
+ offs_t get_address();
+
+ // Wait state logic
+ void operate_ready_line();
+
+ // Link to the attached floppy drives
+ required_device_array<floppy_connector, 4> m_floppy;
+
+ // Motor monoflop
+ required_device<ttl74123_device> m_motormf;
+
+ // Interface chip
+ required_device<tms9901_device> m_tms9901;
+
+ // Debugger accessors
+ void debug_read(offs_t offset, uint8_t* value);
+ void debug_write(offs_t offset, uint8_t data);
+
+ // Buffer RAM
+ required_device<ram_device> m_buffer_ram;
+
+ // DSR ROM
+ uint8_t* m_dsrrom;
+
+ // State of the bank select line. Pulled down initially.
+ bool m_cardsel;
+ bool m_banksel;
+
+ // Selected drive
+ int m_selected_drive;
+
+ // Recent address
+ int m_address;
+
+ // Write access
+ bool m_writing;
+};
+
+
+// ============================================================================
+// Original CorComp disk controller card
+// ============================================================================
+
+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);
+protected:
+ virtual void device_add_mconfig(machine_config &config) override ATTR_COLD;
+ virtual const tiny_rom_entry *device_rom_region() const override ATTR_COLD;
+};
+
+// =========== Decoder PAL circuit ================
+class ccfdc_dec_pal_device : public device_t
+{
+ friend class corcomp_fdc_device;
+public:
+ 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 { }
+
+ 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:
+ 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);
+
+ 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 ================
+
+class ccdcc_palu2_device : public ccfdc_dec_pal_device
+{
+public:
+ ccdcc_palu2_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
+};
+
+// =========== Specific selector PAL circuit of the CCDCC ================
+
+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);
+ int ready_out() override;
+};
+
+// ============================================================================
+// Revised CorComp floppy disk controller card rev a
+// ============================================================================
+
+class corcomp_fdca_device : public corcomp_fdc_device
+{
+ friend class ccfdc_palu6_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 ATTR_COLD;
+ virtual const tiny_rom_entry *device_rom_region() const override ATTR_COLD;
+private:
+ bool ready_trap_active();
+};
+
+// =========== Specific decoder PAL circuit of the CCFDC ================
+
+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);
+ int address9901() override;
+};
+
+// =========== Specific selector PAL circuit of the CCFDC ================
+
+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);
+ int selectwdc() override;
+ int selectdsr() override;
+
+ int ready_out() override;
+};
+
+} // end namespace bus::ti99::peb
+
+DECLARE_DEVICE_TYPE_NS(TI99_CCDCC, bus::ti99::peb, corcomp_dcc_device)
+DECLARE_DEVICE_TYPE_NS(TI99_CCFDC, bus::ti99::peb, corcomp_fdca_device)
+DECLARE_DEVICE_TYPE_NS(CCDCC_PALU2, bus::ti99::peb, ccdcc_palu2_device)
+DECLARE_DEVICE_TYPE_NS(CCDCC_PALU1, bus::ti99::peb, ccdcc_palu1_device)
+DECLARE_DEVICE_TYPE_NS(CCFDC_PALU12, bus::ti99::peb, ccfdc_palu12_device)
+DECLARE_DEVICE_TYPE_NS(CCFDC_PALU6, bus::ti99::peb, ccfdc_palu6_device)
+
+#endif // MAME_BUS_TI99_PEB_CC_FDC_H
diff --git a/src/devices/bus/ti99/peb/evpc.cpp b/src/devices/bus/ti99/peb/evpc.cpp
index 6e532ae11ea..31fff7e1182 100644
--- a/src/devices/bus/ti99/peb/evpc.cpp
+++ b/src/devices/bus/ti99/peb/evpc.cpp
@@ -27,6 +27,9 @@
Thus we assume that in the TI console (option 1) the sound chip has
also been removed.
+ The EVPC has one configuration option:
+ VRAM may be set to 128K or 192K.
+
Important note: The DSR (firmware) of the EVPC expects a memory expansion
to be present; otherwise, the configuration (using CALL EVPC) will crash.
There is no warning if the 32K expansion is not present.
@@ -37,23 +40,26 @@
#include "emu.h"
#include "evpc.h"
+
#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"
-DEFINE_DEVICE_TYPE_NS(TI99_EVPC, bus::ti99::peb, snug_enhanced_video_device, "ti99_evpc", "SNUG Enhanced Video Processor Card")
+DEFINE_DEVICE_TYPE(TI99_EVPC, bus::ti99::peb::snug_enhanced_video_device, "ti99_evpc", "SNUG Enhanced Video Processor Card")
-namespace bus { namespace ti99 { namespace peb {
+namespace bus::ti99::peb {
#define NOVRAM_SIZE 256
#define EVPC_CRU_BASE 0x1400
+#define SOUNDCHIP_TAG "soundchip"
snug_enhanced_video_device::snug_enhanced_video_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock):
device_t(mconfig, TI99_EVPC, tag, owner, clock),
@@ -69,14 +75,14 @@ snug_enhanced_video_device::snug_enhanced_video_device(const machine_config &mco
m_intlevel(0),
m_dsrrom(nullptr),
m_novram(nullptr),
- m_video(*this, TI_VDP_TAG),
- m_sound(*this, TI_SOUNDCHIP_TAG),
+ m_video(*this, TIGEN_V9938_TAG),
+ m_sound(*this, SOUNDCHIP_TAG),
m_colorbus(*this, COLORBUS_TAG),
m_console_conn(*this, ":" TI99_EVPC_CONN_TAG)
{
}
-SETADDRESS_DBIN_MEMBER( snug_enhanced_video_device::setaddress_dbin )
+void snug_enhanced_video_device::setaddress_dbin(offs_t offset, int state)
{
// Do not allow setaddress for the debugger. It will mess up the
// setaddress/memory access pairs when the CPU enters wait states.
@@ -86,10 +92,10 @@ SETADDRESS_DBIN_MEMBER( snug_enhanced_video_device::setaddress_dbin )
m_address = offset;
bool reading = (state==ASSERT_LINE);
- int offbase = (m_address & 0xfc01);
+ int offbase = (m_address & 0x7fc01); // The 7 represents the AMA/B/C lines
// Sound
- m_sound_accessed = ((m_address & 0xff01)==0x8400) && !reading;
+ m_sound_accessed = ((m_address & 0x7ff01)==0x78400) && !reading;
// Video space
// 8800 / 8802 / 8804 / 8806
@@ -97,15 +103,15 @@ SETADDRESS_DBIN_MEMBER( snug_enhanced_video_device::setaddress_dbin )
//
// Bits 1000 1w00 0000 0xx0
// Mask 1111 1000 0000 0001
- m_video_accessed = ((offbase==0x8800) && reading) || ((offbase==0x8c00) && !reading);
+ m_video_accessed = ((offbase==0x78800) && reading) || ((offbase==0x78c00) && !reading);
// Read a byte in evpc DSR space
// 0x4000 - 0x5eff DSR (paged)
// 0x5f00 - 0x5fef NOVRAM
// 0x5ff0 - 0x5fff Palette
- m_inDsrArea = ((m_address & 0xe000)==0x4000);
- m_novram_accessed = ((m_address & 0xff00)==0x5f00);
- m_palette_accessed = ((m_address & 0xfff0)==0x5ff0);
+ m_inDsrArea = in_dsr_space(m_address, true);
+ m_novram_accessed = ((m_address & 0x7ff00)==0x75f00);
+ m_palette_accessed = ((m_address & 0x7fff0)==0x75ff0);
// Note that we check the selection in reverse order so that the overlap is avoided
}
@@ -125,9 +131,10 @@ void snug_enhanced_video_device::nvram_default()
// .nv file
//-------------------------------------------------
-void snug_enhanced_video_device::nvram_read(emu_file &file)
+bool snug_enhanced_video_device::nvram_read(util::read_stream &file)
{
- file.read(m_novram.get(), NOVRAM_SIZE);
+ auto const [err, actual] = util::read(file, m_novram.get(), NOVRAM_SIZE);
+ return !err && (actual == NOVRAM_SIZE);
}
//-------------------------------------------------
@@ -135,9 +142,10 @@ void snug_enhanced_video_device::nvram_read(emu_file &file)
// .nv file
//-------------------------------------------------
-void snug_enhanced_video_device::nvram_write(emu_file &file)
+bool snug_enhanced_video_device::nvram_write(util::write_stream &file)
{
- file.write(m_novram.get(), NOVRAM_SIZE);
+ auto const [err, actual] = util::write(file, m_novram.get(), NOVRAM_SIZE);
+ return !err;
}
/*
@@ -146,7 +154,7 @@ void snug_enhanced_video_device::nvram_write(emu_file &file)
0x5f00 - 0x5fef NOVRAM
0x5ff0 - 0x5fff Palette (5ff0, 5ff2, 5ff4, 5ff6)
*/
-READ8Z_MEMBER(snug_enhanced_video_device::readz)
+void snug_enhanced_video_device::readz(offs_t offset, uint8_t *value)
{
if (m_selected && m_inDsrArea)
{
@@ -317,7 +325,7 @@ void snug_enhanced_video_device::write(offs_t offset, uint8_t data)
7: DIP or NOVRAM
Logic is inverted
*/
-READ8Z_MEMBER(snug_enhanced_video_device::crureadz)
+void snug_enhanced_video_device::crureadz(offs_t offset, uint8_t *value)
{
if ((offset & 0xff00)==EVPC_CRU_BASE)
{
@@ -391,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);
}
@@ -413,11 +421,10 @@ void snug_enhanced_video_device::device_start()
void snug_enhanced_video_device::device_reset()
{
- m_select_mask = 0x7e000;
- m_select_value = 0x74000;
m_dsr_page = 0;
m_RAMEN = false;
m_selected = false;
+ m_video->set_vram_size((ioport("EVPC-MEM")->read()==0)? 0x20000 : 0x30000);
}
void snug_enhanced_video_device::device_stop()
@@ -431,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
@@ -471,6 +478,11 @@ INPUT_PORTS_START( ti99_evpc )
PORT_DIPNAME( 0x01, 0x00, "EVPC Configuration" )
PORT_DIPSETTING( 0x00, "DIP" )
PORT_DIPSETTING( 0x01, "NOVRAM" )
+
+ PORT_START( "EVPC-MEM" )
+ PORT_CONFNAME( 0x01, 0x00, "EVPC video memory" )
+ PORT_DIPSETTING( 0x00, "128K" )
+ PORT_DIPSETTING( 0x01, "192K" )
INPUT_PORTS_END
const tiny_rom_entry *snug_enhanced_video_device::device_rom_region() const
@@ -487,10 +499,11 @@ void snug_enhanced_video_device::device_add_mconfig(machine_config& config)
{
// video hardware
V9938(config, m_video, XTAL(21'477'272)); // typical 9938 clock, not verified
- m_video->set_vram_size(0x20000);
+
m_video->int_cb().set(FUNC(snug_enhanced_video_device::video_interrupt_in));
- m_video->set_screen(TI_SCREEN_TAG);
- screen_device& screen(SCREEN(config, TI_SCREEN_TAG, SCREEN_TYPE_RASTER));
+ m_video->set_screen(EVPC_SCREEN_TAG);
+ m_video->set_vram_size(0x20000); // gets changed at device_reset, but give it a default value to avoid assert
+ screen_device& screen(SCREEN(config, EVPC_SCREEN_TAG, SCREEN_TYPE_RASTER));
screen.set_raw(XTAL(21'477'272),
v99x8_device::HTOTAL,
0,
@@ -498,11 +511,11 @@ void snug_enhanced_video_device::device_add_mconfig(machine_config& config)
v99x8_device::VTOTAL_NTSC * 2,
v99x8_device::VERTICAL_ADJUST * 2,
v99x8_device::VVISIBLE_NTSC * 2 - 1 - v99x8_device::VERTICAL_ADJUST * 2);
- screen.set_screen_update(TI_VDP_TAG, FUNC(v99x8_device::screen_update));
+ screen.set_screen_update(TIGEN_V9938_TAG, FUNC(v99x8_device::screen_update));
// Sound hardware
SPEAKER(config, "sound_out").front_center();
- sn94624_device& soundgen(SN94624(config, TI_SOUNDCHIP_TAG, 3579545/8));
+ sn94624_device& soundgen(SN94624(config, SOUNDCHIP_TAG, 3579545/8));
soundgen.ready_cb().set(FUNC(snug_enhanced_video_device::ready_line));
soundgen.add_route(ALL_OUTPUTS, "sound_out", 0.75);
@@ -510,6 +523,4 @@ void snug_enhanced_video_device::device_add_mconfig(machine_config& config)
V9938_COLORBUS(config, m_colorbus, 0, ti99_colorbus_options, nullptr);
}
-} } } // end namespace bus::ti99::peb
-
-
+} // end namespace bus::ti99::peb
diff --git a/src/devices/bus/ti99/peb/evpc.h b/src/devices/bus/ti99/peb/evpc.h
index 05925d3c5e8..83ef67c86c1 100644
--- a/src/devices/bus/ti99/peb/evpc.h
+++ b/src/devices/bus/ti99/peb/evpc.h
@@ -21,21 +21,20 @@
#include "machine/timer.h"
#include "video/v9938.h"
#include "sound/sn76496.h"
-#include "bus/ti99/ti99defs.h"
#include "bus/ti99/colorbus/colorbus.h"
#include "bus/ti99/internal/evpcconn.h"
-namespace bus { namespace ti99 { namespace peb {
+namespace bus::ti99::peb {
class snug_enhanced_video_device : public device_t, public device_ti99_peribox_card_interface, public device_nvram_interface
{
public:
snug_enhanced_video_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
- DECLARE_READ8Z_MEMBER(readz) override;
+ void readz(offs_t offset, uint8_t *value) override;
void write(offs_t offset, uint8_t data) override;
- DECLARE_SETADDRESS_DBIN_MEMBER(setaddress_dbin) override;
+ void setaddress_dbin(offs_t offset, int state) override;
- DECLARE_READ8Z_MEMBER(crureadz) override;
+ void crureadz(offs_t offset, uint8_t *value) override;
void cruwrite(offs_t offset, uint8_t data) override;
TIMER_DEVICE_CALLBACK_MEMBER( hblank_interrupt );
@@ -50,22 +49,22 @@ protected:
//int dirty;
};
- void device_start() override;
- void device_reset() override;
+ void device_start() override ATTR_COLD;
+ void device_reset() override ATTR_COLD;
void device_stop() override;
- 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 const tiny_rom_entry *device_rom_region() const override ATTR_COLD;
+ virtual ioport_constructor device_input_ports() const override ATTR_COLD;
+ virtual void device_add_mconfig(machine_config &config) override ATTR_COLD;
- void nvram_default() override;
- void nvram_read(emu_file &file) override;
- void nvram_write(emu_file &file) override;
+ virtual void nvram_default() override;
+ virtual bool nvram_read(util::read_stream &file) override;
+ 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;
@@ -89,7 +88,7 @@ private:
optional_device<bus::ti99::internal::evpc_clock_connector> m_console_conn;
};
-} } } // end namespace bus::ti99::peb
+} // end namespace bus::ti99::peb
DECLARE_DEVICE_TYPE_NS(TI99_EVPC, bus::ti99::peb, snug_enhanced_video_device)
diff --git a/src/devices/bus/ti99/peb/forti.cpp b/src/devices/bus/ti99/peb/forti.cpp
new file mode 100644
index 00000000000..25c00556534
--- /dev/null
+++ b/src/devices/bus/ti99/peb/forti.cpp
@@ -0,0 +1,133 @@
+// license:LGPL-2.1+
+// copyright-holders:Michael Zapf
+/*******************************************************************************
+ FORTi Sound card
+
+ 4 x TMS9919 sound generators
+ 4 sound outputs; may be coupled to two stereo outputs
+
+ Mapping:
+
+ 1000 01xx xxxD CBA0
+
+ 8402: Sound chip 1 (A)
+ 8404: Sound chip 2 (B)
+ 8408: Sound chip 3 (C)
+ 8410: Sound chip 4 (D)
+
+ Sound chips may be addressed in parallel:
+ 8406: Sound chips 1+2
+ 841a: Sound chips 1+3+4
+
+ All sound READY lines are combined by a wired-AND as the common
+ READY line to the CPU.
+
+ Michael Zapf
+ March 2020
+
+*******************************************************************************/
+
+#include "emu.h"
+#include "forti.h"
+
+#define LOG_READY (1U << 1)
+
+#define VERBOSE (LOG_GENERAL)
+
+#include "logmacro.h"
+
+#define FORTI_GEN1_TAG "soundchip1"
+#define FORTI_GEN2_TAG "soundchip2"
+#define FORTI_GEN3_TAG "soundchip3"
+#define FORTI_GEN4_TAG "soundchip4"
+
+DEFINE_DEVICE_TYPE(TI99_FORTI, bus::ti99::peb::forti_device, "ti99_forti", "FORTi Sound Card")
+
+namespace bus::ti99::peb {
+
+forti_device::forti_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock):
+ device_t(mconfig, TI99_FORTI, tag, owner, clock),
+ device_ti99_peribox_card_interface(mconfig, *this),
+ m_generator1(*this, FORTI_GEN1_TAG),
+ m_generator2(*this, FORTI_GEN2_TAG),
+ m_generator3(*this, FORTI_GEN3_TAG),
+ m_generator4(*this, FORTI_GEN4_TAG)
+{
+}
+
+/*
+ No read access. The FORTi card does not support any reading.
+*/
+void forti_device::readz(offs_t offset, uint8_t *value)
+{
+ return;
+}
+
+/*
+ READY callbacks from the sound chips.
+*/
+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());
+
+ line_state ready = (m_generator1->ready_r() && m_generator2->ready_r()
+ && m_generator3->ready_r() && m_generator4->ready_r())? ASSERT_LINE : CLEAR_LINE;
+
+ m_slot->set_ready(ready);
+}
+
+void forti_device::write(offs_t offset, uint8_t data)
+{
+ // Decode for 8400-87ff
+ if ((offset & 0xfc01) == 0x8400)
+ {
+ // The generators can be accessed in parallel
+ if ((offset & 0x2)!=0)
+ m_generator1->write(data);
+
+ if ((offset & 0x4)!=0)
+ m_generator2->write(data);
+
+ if ((offset & 0x8)!=0)
+ m_generator3->write(data);
+
+ if ((offset & 0x10)!=0)
+ m_generator4->write(data);
+ }
+}
+
+void forti_device::device_add_mconfig(machine_config& config)
+{
+ // 1 and 3 are mixed to left channel
+ // 2 and 4 are moxed to right channel
+
+ SPEAKER(config, "forti_left").front_left();
+ SPEAKER(config, "forti_right").front_right();
+
+ SN94624(config, m_generator1, XTAL(3'579'545)/8);
+ m_generator1->ready_cb().set(FUNC(forti_device::ready_sound));
+ m_generator1->add_route(ALL_OUTPUTS, "forti_left", 0.75);
+
+ SN94624(config, m_generator2, XTAL(3'579'545)/8);
+ m_generator2->ready_cb().set(FUNC(forti_device::ready_sound));
+ m_generator2->add_route(ALL_OUTPUTS, "forti_right", 0.75);
+
+ SN94624(config, m_generator3, XTAL(3'579'545)/8);
+ m_generator3->ready_cb().set(FUNC(forti_device::ready_sound));
+ m_generator3->add_route(ALL_OUTPUTS, "forti_left", 0.75);
+
+ SN94624(config, m_generator4, XTAL(3'579'545)/8);
+ m_generator4->ready_cb().set(FUNC(forti_device::ready_sound));
+ m_generator4->add_route(ALL_OUTPUTS, "forti_right", 0.75);
+}
+
+void forti_device::device_start()
+{
+}
+
+void forti_device::device_reset()
+{
+}
+
+} // end namespace bus::ti99::peb
diff --git a/src/devices/bus/ti99/peb/forti.h b/src/devices/bus/ti99/peb/forti.h
new file mode 100644
index 00000000000..991014799e7
--- /dev/null
+++ b/src/devices/bus/ti99/peb/forti.h
@@ -0,0 +1,52 @@
+// license:LGPL-2.1+
+// copyright-holders:Michael Zapf
+/*******************************************************************************
+ FORTi Sound card
+
+ 4 x TMS9919 sound generators
+ 4 sound outputs; may be coupled to two stereo outputs
+
+ Michael Zapf
+ March 2020
+
+*******************************************************************************/
+
+#ifndef MAME_BUS_TI99_PEB_FORTI_H
+#define MAME_BUS_TI99_PEB_FORTI_H
+
+#pragma once
+
+#include "peribox.h"
+#include "sound/sn76496.h"
+#include "speaker.h"
+
+namespace bus::ti99::peb {
+
+class forti_device : public device_t, public device_ti99_peribox_card_interface
+{
+public:
+ forti_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
+ void write(offs_t offset, uint8_t data) override;
+ void readz(offs_t offset, uint8_t *value) override;
+ void crureadz(offs_t offset, uint8_t *value) override { }
+ void cruwrite(offs_t offset, uint8_t data) override { }
+
+ void ready_sound(int state);
+
+private:
+ void device_start() override ATTR_COLD;
+ void device_reset() override ATTR_COLD;
+ void device_add_mconfig(machine_config &config) override;
+
+ // TODO: Replace by TMS9919 when available
+ required_device<sn94624_device> m_generator1;
+ required_device<sn94624_device> m_generator2;
+ required_device<sn94624_device> m_generator3;
+ required_device<sn94624_device> m_generator4;
+};
+
+} // end namespace bus::ti99::peb
+
+DECLARE_DEVICE_TYPE_NS(TI99_FORTI, bus::ti99::peb, forti_device)
+
+#endif // MAME_BUS_TI99_PEB_FORTI_H
diff --git a/src/devices/bus/ti99/peb/hfdc.cpp b/src/devices/bus/ti99/peb/hfdc.cpp
index 6a9a89726b2..ad116788507 100644
--- a/src/devices/bus/ti99/peb/hfdc.cpp
+++ b/src/devices/bus/ti99/peb/hfdc.cpp
@@ -59,30 +59,31 @@
#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_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_NS(TI99_HFDC, bus::ti99::peb, myarc_hfdc_device, "ti99_hfdc", "Myarc Hard and Floppy Disk Controller")
+DEFINE_DEVICE_TYPE(TI99_HFDC, bus::ti99::peb::myarc_hfdc_device, "ti99_hfdc", "Myarc Hard and Floppy Disk Controller")
-namespace bus { namespace ti99 { namespace peb {
+namespace bus::ti99::peb {
#define BUFFER "ram"
#define FDC_TAG "hdc9234"
#define CLOCK_TAG "mm58274c"
-#define MOTOR_TIMER 1
+#define NONE -1
#define TAPE_ADDR 0x0fc0
#define HDC_R_ADDR 0x0fd0
@@ -100,8 +101,14 @@ myarc_hfdc_device::myarc_hfdc_device(const machine_config &mconfig, const char *
device_ti99_peribox_card_interface(mconfig, *this),
m_motor_on_timer(nullptr),
m_hdc9234(*this, FDC_TAG),
- m_clock(*this, CLOCK_TAG), m_current_floppy(nullptr),
- m_current_harddisk(nullptr), m_see_switches(false),
+ 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),
+ m_current_hd_index(NONE),
+ m_see_switches(false),
m_irq(), m_dip(), m_motor_running(false),
m_inDsrArea(false), m_HDCsel(false), m_RTCsel(false),
m_tapesel(false), m_RAMsel(false), m_ROMsel(false), m_address(0),
@@ -111,7 +118,7 @@ myarc_hfdc_device::myarc_hfdc_device(const machine_config &mconfig, const char *
{
}
-SETADDRESS_DBIN_MEMBER( myarc_hfdc_device::setaddress_dbin )
+void myarc_hfdc_device::setaddress_dbin(offs_t offset, int state)
{
// Do not allow setaddress for the debugger. It will mess up the
// setaddress/memory access pairs when the CPU enters wait states.
@@ -124,7 +131,7 @@ SETADDRESS_DBIN_MEMBER( myarc_hfdc_device::setaddress_dbin )
// 010x xxxx xxxx xxxx
m_address = offset;
- m_inDsrArea = ((m_address & m_select_mask)==m_select_value);
+ m_inDsrArea = in_dsr_space(m_address, true);
if (!m_inDsrArea) return;
@@ -161,7 +168,7 @@ SETADDRESS_DBIN_MEMBER( myarc_hfdc_device::setaddress_dbin )
*/
void myarc_hfdc_device::debug_read(offs_t offset, uint8_t* value)
{
- if (((offset & m_select_mask)==m_select_value) && m_selected)
+ if (in_dsr_space(offset, true) && m_selected)
{
if ((offset & 0x1000)==RAM_ADDR)
{
@@ -180,7 +187,7 @@ void myarc_hfdc_device::debug_read(offs_t offset, uint8_t* value)
void myarc_hfdc_device::debug_write(offs_t offset, uint8_t data)
{
- if (((offset & m_select_mask)==m_select_value) && m_selected)
+ if (in_dsr_space(offset, true) && m_selected)
{
if ((offset & 0x1000)==RAM_ADDR)
{
@@ -205,7 +212,7 @@ void myarc_hfdc_device::debug_write(offs_t offset, uint8_t data)
HFDC manual, p. 44
*/
-READ8Z_MEMBER(myarc_hfdc_device::readz)
+void myarc_hfdc_device::readz(offs_t offset, uint8_t *value)
{
if (machine().side_effects_disabled())
{
@@ -371,7 +378,7 @@ void myarc_hfdc_device::write(offs_t offset, uint8_t data)
---
0 on all other locations
*/
-READ8Z_MEMBER(myarc_hfdc_device::crureadz)
+void myarc_hfdc_device::crureadz(offs_t offset, uint8_t *value)
{
uint8_t reply;
if ((offset & 0xff00)==m_cru_base)
@@ -501,7 +508,7 @@ void myarc_hfdc_device::cruwrite(offs_t offset, uint8_t data)
/*
Monoflop has gone back to the OFF state.
*/
-void myarc_hfdc_device::device_timer(emu_timer &timer, device_timer_id id, int param, void *ptr)
+TIMER_CALLBACK_MEMBER(myarc_hfdc_device::motor_off)
{
set_floppy_motors_running(false);
}
@@ -542,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();
}
@@ -714,7 +721,7 @@ enum
void myarc_hfdc_device::connect_floppy_unit(int index)
{
// Check if we have a new floppy
- if (m_floppy_unit[index] != m_current_floppy)
+ if (index != m_current_floppy_index)
{
// Clear all latched flags from other drives
m_status_latch = 0;
@@ -722,7 +729,8 @@ 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.
// READY is asserted when DSKx = 1
@@ -732,7 +740,9 @@ void myarc_hfdc_device::connect_floppy_unit(int index)
m_current_floppy->setup_index_pulse_cb(floppy_image_device::index_pulse_cb(&myarc_hfdc_device::floppy_index_callback, this));
else
LOGMASKED(LOG_WARN, "Connection to DSK%d failed because no drive is connected\n", index+1);
- m_hdc9234->connect_floppy_drive(m_floppy_unit[index]);
+
+ // Connect to HDC (or disconnect)
+ m_hdc9234->connect_floppy_drive(m_current_floppy);
}
// We can only run a floppy or a harddisk at a time, not both
@@ -741,15 +751,16 @@ void myarc_hfdc_device::connect_floppy_unit(int index)
void myarc_hfdc_device::connect_harddisk_unit(int index)
{
- if (m_harddisk_unit[index] != m_current_harddisk)
+ if (index != m_current_hd_index)
{
- // Clear all latched flags form other drives
+ // Clear all latched flags from other drives
m_status_latch = 0;
disconnect_hard_drives();
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);
if (m_current_harddisk != nullptr)
@@ -760,6 +771,8 @@ void myarc_hfdc_device::connect_harddisk_unit(int index)
}
else
LOGMASKED(LOG_WARN, "Connection to WDS%d failed because no drive is connected\n", index+1);
+
+ // Connect to HDC (or disconnect)
m_hdc9234->connect_hard_drive(m_current_harddisk);
}
@@ -776,6 +789,7 @@ void myarc_hfdc_device::disconnect_floppy_drives()
m_current_floppy->setup_index_pulse_cb(floppy_image_device::index_pulse_cb());
m_current_floppy = nullptr;
}
+ m_current_floppy_index = NONE;
}
void myarc_hfdc_device::disconnect_hard_drives()
@@ -787,6 +801,7 @@ void myarc_hfdc_device::disconnect_hard_drives()
m_current_harddisk->setup_seek_complete_cb(mfm_harddisk_device::seek_complete_cb());
m_current_harddisk = nullptr;
}
+ m_current_hd_index = NONE;
}
/*
@@ -806,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);
@@ -828,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)
@@ -840,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;
}
@@ -871,19 +886,18 @@ void myarc_hfdc_device::write_buffer(uint8_t data)
void myarc_hfdc_device::device_start()
{
m_dsrrom = memregion(TI99_DSRROM)->base();
- m_motor_on_timer = timer_alloc(MOTOR_TIMER);
+ m_motor_on_timer = timer_alloc(FUNC(myarc_hfdc_device::motor_off), this);
// The HFDC does not use READY; it has on-board RAM for DMA
m_current_floppy = nullptr;
m_current_harddisk = nullptr;
+ m_current_floppy_index = NONE;
+ m_current_hd_index = NONE;
// Parent class members
save_item(NAME(m_senila));
save_item(NAME(m_senilb));
save_item(NAME(m_selected));
- save_item(NAME(m_genmod));
save_item(NAME(m_cru_base));
- save_item(NAME(m_select_mask));
- save_item(NAME(m_select_value));
// Own members
save_item(NAME(m_see_switches));
@@ -911,18 +925,6 @@ void myarc_hfdc_device::device_start()
void myarc_hfdc_device::device_reset()
{
- // The GenMOD mod; our implementation automagically adapts all cards
- if (m_genmod)
- {
- m_select_mask = 0x1fe000;
- m_select_value = 0x174000;
- }
- else
- {
- m_select_mask = 0x7e000;
- m_select_value = 0x74000;
- }
-
m_cru_base = ioport("CRUHFDC")->read();
m_wait_for_hd1 = ioport("WAITHD1")->read();
@@ -943,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
@@ -964,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,
@@ -1040,10 +1019,12 @@ INPUT_PORTS_START( ti99_hfdc )
PORT_DIPSETTING( 0x30, "80 track HD, 2 ms")
INPUT_PORTS_END
-FLOPPY_FORMATS_MEMBER(myarc_hfdc_device::floppy_formats)
- FLOPPY_TI99_SDF_FORMAT,
- FLOPPY_TI99_TDF_FORMAT
-FLOPPY_FORMATS_END
+void myarc_hfdc_device::floppy_formats(format_registration &fr)
+{
+ fr.add_mfm_containers();
+ fr.add(FLOPPY_TI99_SDF_FORMAT);
+ fr.add(FLOPPY_TI99_TDF_FORMAT);
+}
static void hfdc_floppies(device_slot_interface &device)
{
@@ -1078,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
@@ -1103,4 +1084,4 @@ ioport_constructor myarc_hfdc_device::device_input_ports() const
return INPUT_PORTS_NAME( ti99_hfdc );
}
-} } } // end namespace bus::ti99::peb
+} // end namespace bus::ti99::peb
diff --git a/src/devices/bus/ti99/peb/hfdc.h b/src/devices/bus/ti99/peb/hfdc.h
index 88648105eb5..9c7ea88d8ae 100644
--- a/src/devices/bus/ti99/peb/hfdc.h
+++ b/src/devices/bus/ti99/peb/hfdc.h
@@ -27,7 +27,7 @@
#include "machine/hdc92x4.h"
#include "machine/ram.h"
-namespace bus { namespace ti99 { namespace peb {
+namespace bus::ti99::peb {
/*
Implementation for modern floppy system.
@@ -37,32 +37,31 @@ class myarc_hfdc_device : public device_t, public device_ti99_peribox_card_inter
public:
myarc_hfdc_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
- DECLARE_READ8Z_MEMBER(readz) override;
- void write(offs_t offset, uint8_t data) override;
- DECLARE_SETADDRESS_DBIN_MEMBER(setaddress_dbin) override;
- DECLARE_READ8Z_MEMBER(crureadz) override;
- void cruwrite(offs_t offset, uint8_t data) override;
+ virtual void readz(offs_t offset, uint8_t *value) override;
+ virtual void write(offs_t offset, uint8_t data) override;
+ virtual void setaddress_dbin(offs_t offset, int state) override;
+ virtual void crureadz(offs_t offset, uint8_t *value) override;
+ virtual void cruwrite(offs_t offset, uint8_t data) override;
protected:
- void device_config_complete() override;
+ virtual void device_start() override ATTR_COLD;
+ virtual void device_reset() override ATTR_COLD;
-private:
- void device_timer(emu_timer &timer, device_timer_id id, int param, void *ptr) override;
- void device_start() override;
- void device_reset() override;
+ virtual const tiny_rom_entry *device_rom_region() const override ATTR_COLD;
+ virtual void device_add_mconfig(machine_config &config) override ATTR_COLD;
+ virtual ioport_constructor device_input_ports() const override ATTR_COLD;
- 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;
+ TIMER_CALLBACK_MEMBER(motor_off);
- DECLARE_WRITE_LINE_MEMBER( dmarq_w );
- DECLARE_WRITE_LINE_MEMBER( intrq_w );
- DECLARE_WRITE_LINE_MEMBER( dip_w );
+private:
+ 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);
- DECLARE_FLOPPY_FORMATS( floppy_formats );
+ static void floppy_formats(format_registration &fr);
// Debug accessors
void debug_read(offs_t offset, uint8_t* value);
@@ -100,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;
@@ -111,6 +110,12 @@ private:
// Currently selected hard drive
mfm_harddisk_device* m_current_harddisk;
+ // Currently selected floppy disk index
+ int m_current_floppy_index;
+
+ // Currently selected hard disk index
+ int m_current_hd_index;
+
// True: Access to DIP switch settings, false: access to line states
bool m_see_switches;
@@ -187,7 +192,7 @@ private:
int m_readyflags;
};
-} } } // end namespace bus::ti99::peb
+} // end namespace bus::ti99::peb
DECLARE_DEVICE_TYPE_NS(TI99_HFDC, bus::ti99::peb, myarc_hfdc_device)
diff --git a/src/devices/bus/ti99/peb/horizon.cpp b/src/devices/bus/ti99/peb/horizon.cpp
index 89383125cbb..db5b535c40f 100644
--- a/src/devices/bus/ti99/peb/horizon.cpp
+++ b/src/devices/bus/ti99/peb/horizon.cpp
@@ -4,429 +4,533 @@
Horizon Ramdisk
- This emulation realizes the latest development, the HRD 4000, which could
- host up to 16 MiB of SRAM. Real cards rarely had more than 1.5 MiB since
- the SRAM used on the card is rather expensive.
+ This emulation realizes the latest development, the HRD 4000B, which can
+ host up to 16 MiB of SRAM. The SRAM is buffered with a battery pack. Also,
+ there is an option for an additional 32 KiB of unbuffered memory.
- The SRAM is buffered with a battery pack. Also, there is an option for
- an additional 32 KiB of unbuffered memory.
-
- The driver (ROS) of the ramdisk is stored in another buffered 8 KiB SRAM.
+ The driver (ROS) of the ramdisk is stored in another buffered SRAM.
+ Originally set to be 8 KiB, the 4000B offers four banks of 8 KiB storage
+ for the driver.
The Horizon RAMdisk comes with a disk containing the ROS and a configuration
- program (CFG). The latest version is ROS 8.14.
+ program (CFG).
Technical details:
- In the tradition (Horizon) mode, memory is organized as 2 KiB pages. The
+ The card is able to handle 128K*8 and 512K*8 SRAM chips, allowing a total
+ of 16 MiB memory space. The card may be equipped with 0 to 32 SRAM chips;
+ in this implementation, a multiple of 4 can be selected in that range.
+
+ The Horizon 4000(B) implements the AMA decoding, unlike the the earlier
+ models.
+
+ Sockets must be populated contiguously from 0 to 15. Only when all sockets
+ are populated, further SRAM circuits may be soldered on top of the bottom
+ layer chips, again contiguously from 0 to 15.
+
+ The respective CS* lines of the SRAM chips on the top layer must be
+ connected with separate wires to the selector chip.
+
+ === Normal mode ===
+
+ In the normal (Horizon) mode, memory is organized as 2 KiB pages. The
pages are selected via CRU bits and visible in the address area 5800 - 5fff.
- The area 4000-57ff is occupied by the ROS. As with all peripheral cards,
- the 4000-5fff area requires a CRU bit to be set (usually bit 0 of this
- card's CRU base).
-
- Next releases of the HRD included new modes. The RAMBO (RAM Block operator)
- mode gathers four pages to a single 8 KiB page that is visible in the
- area 6000-7fff (cartridge space). Note that due to a possible design glitch,
- each RAMBO page n covers Horizon pages 4n, 4n+2, 4n+1, 4n+3 in this sequence.
- We emulate this by swapping two CRU lines.
-
- The RAMDisk may be split in two separate drives, which is called the
- Phoenix extension. This is particularly important for use in the Geneve.
- As a bootable drive, the RAMdisk must not
- exceed 256 KiB; consequently, the RAM area is split, and one part realizes
- the boot drive while the other is still available for data. Also, there
- is a mechanism for selecting the parts of the card: The TI setting allows
- to select two CRU addresses, one for each part. In the Geneve mode, only
- one CRU address is used (1400 or 1600), and the part is selected by the
- fact that one disk uses CRU bits higher than 8, while the other uses the
- bits lower than 8.
+ The area 4000-57ff is occupied by the ROS. As with most peripheral cards,
+ the 4000-5fff area requires CRU bit 0 to be set.
- The card is able to handle 128K*8 and 512K*8 SRAM chips, allowing a total
- of 16 MiB memory space. Unfortunately, a bug causes the configuration
- program to crash when used with more than 2 MiB. Although the card was
- quite popular, this bug was not found because most cards were sold with
- less than 2 MiB onboard. As the community is still alive we can hope for
- a fix for this problem; so we make the size configurable.
+ CRU bits:
+
+ 15 14 13 12 11 10 9 8 7 6 1 0
+ +-----------------------------------------------------------------+
+ | RAMBO | DSR | SRAM | B | B | B | B | P | P | P ... | P | Ena | 512Kx8
+ | | bank | Layer | Bank (0-15) | Page (0-255) | ble | RAM
+ +-----------------------------------------------------------------+
+
+ 15 14 13 12 11 10 9 8 7 6 1 0
+ +-----------------------------------------------------------------+
+ | RAMBO | DSR | - | - | SRAM | B | B | B | B | P | ... | P | Ena | 128Kx8
+ | | bank | | | Layer| Bank (0-15) | Page(0-63) | ble | RAM
+ +-----------------------------------------------------------------+
+
+ The difference between layer, banks, and pages results from the board
+ design. Logically, the layer, bank, and page information can be seen as a
+ 13-bit page number for 512Kx8 RAMs or a 11-bit page number for 128Kx8 SRAMs.
+
+ The 8-bit page number results from the capacity of a 512Kx8 chip (256 pages
+ of 2 KiB), while the 6-bit number applies to 128Kx8 chips (64 pages of
+ 2 KiB). The bank selects the chip socket. The layer allows for selecting
+ the second layer of chips, piggy-backed on the bottom layer.
+
+ === RAMBO ===
+
+ The RAMBO (RAM Block operator) mode gathers four pages to a single 8 KiB
+ page in the area 6000-7fff (cartridge space). Due to an arguable design
+ glitch in the real hardware (swapped A3/A4 lines), the four pages do not
+ appear in their original order but as the base number plus 0 / 2 / 1 / 3.
+ This can only be noticed when working in both modes (writing to pages in the
+ normal mode, then mapping the group of pages via RAMBO).
+
+ The above CRU bit chart also applies here, but bits 1 and 2 (least signi-
+ ficant page number bits) are ignored.
+
+ === Phoenix ===
+
+ Using jumper JP2 and a DIP switch setting, the card can be configured to the
+ Phoenix mode. This mode was originally intended to allow the Geneve to boot
+ from the Horizon card, because the early boot ROMs did not support a boot
+ drive larger than 256 KiB. Consequently, the RAM area is split, and one part
+ realizes the boot drive while the other is still available for data.
+
+ The Phoenix configuration splits the card in the middle, assigning the
+ lower 8 sockets (bottom M0-M7, top M16-M23) to the Phoenix part, and the
+ upper 8 sockets (bottom M8-M15, top M24-M31) to the normal part.
+
+ The most significant bank selection bit (12 or 10) is ignored, because this
+ bit determines the choice of upper and lower part. The selection is done
+ in this way instead:
+
+ In "TI mode", two separate CRU base addresses must be selected by the DIP
+ switches. When an access occurs on the normal CRU address, the bit is set,
+ while an access to the Phoenix CRU address resets the bit. Accesses occur
+ when the page is set.
+
+ In the "Geneve mode", only one CRU address is used. A CRU write access
+ to bits 8-15 sets the bit to 0, and a CRU write access to bits 0-7 sets
+ the bit to 1. Since the bits keep their semantics, care must be taken in
+ which order the bits are written to. For this reason, the Phoenix mode is
+ rarely used.
+
+ Later investigations proved that the GeneveOS could be loaded normally from
+ the large ramdisk, and the Phoenix mode became obsolete. It is included for
+ test purposes and for the sake of completeness.
+
+ The "Split mode" for TI and Geneve can be used without splitting the RAM
+ space, i.e. a Phoenix address may be set without JP2 set to split. In that
+ case, only the DSR RAM is split in two halves (if its size is 32KiB).
+
+ References
+
+ [1] Software Developer's Guide to the HRD4000B, Sept. 2020
+ [2] Schematics for the HRD4000B
+ [3] Horizon 4000 Ramdisk Construction Guide, Bud Mills Services, 1992
+
+ Original design of the hardware (2000) by Horizon Computer, Ltd., 1986
+ Extensions (3000, 4000) by Bud Mills Services, 1989, 1992
+ HRD 4000B by Jim Fetzner et al., 2019
+
+ Michael Zapf
+ November 2020
*****************************************************************************/
#include "emu.h"
#include "horizon.h"
-#define LOG_WARN (1U<<1) // Warnings
-#define LOG_CONFIG (1U<<2) // Configuration
-#define LOG_READ (1U<<3)
-#define LOG_WRITE (1U<<4)
-#define LOG_CRU (1U<<5)
+#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_CONFIG | LOG_WARN )
+#define VERBOSE (LOG_GENERAL | LOG_CONFIG | LOG_WARN)
#include "logmacro.h"
-DEFINE_DEVICE_TYPE_NS(TI99_HORIZON, bus::ti99::peb, horizon_ramdisk_device, "ti99_horizon", "Horizon 4000 Ramdisk")
+DEFINE_DEVICE_TYPE(TI99_HORIZON, bus::ti99::peb::horizon_ramdisk_device, "ti99_horizon", "Horizon 4000B RAMdisk")
-namespace bus { namespace ti99 { namespace peb {
+namespace bus::ti99::peb {
-#define RAMREGION "ram32k"
-#define ROSREGION "ros8k"
-#define NVRAMREGION "nvram"
+#define CRULATCH1_TAG "u4_latch"
+#define CRULATCH2_TAG "u3_latch"
-#define MAXSIZE 16777216
-#define ROSSIZE 8192
+#define DSRRAM_TAG "u9_dsrram"
+#define OPT32K_TAG "m32_ram"
+#define RAM16M_TAG "m31_m0_ram"
horizon_ramdisk_device::horizon_ramdisk_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock):
device_t(mconfig, TI99_HORIZON, tag, owner, clock),
device_ti99_peribox_card_interface(mconfig, *this),
device_nvram_interface(mconfig, *this),
- m_ram(*this, RAMREGION),
- m_nvram(*this, NVRAMREGION),
- m_ros(*this, ROSREGION),
- m_select6_value(0),
- m_select_all(0),
- m_page(0),
- m_cru_horizon(0),
- m_cru_phoenix(0),
- m_timode(false),
- m_32k_installed(false),
- m_split_mode(false),
- m_rambo_mode(false),
+ m_ram(*this, RAM16M_TAG),
+ m_dsrram(*this, DSRRAM_TAG),
+ m_optram(*this, OPT32K_TAG),
+ m_crulatch_u4(*this, CRULATCH1_TAG),
+ m_crulatch_u3(*this, CRULATCH2_TAG),
+ m_32k_installed(true),
+ m_phoenix_accessed(false),
+ m_dsr32k(true),
+ m_128kx8(true),
+ m_geneve_mode(false),
+ m_phoenix_split(false),
m_hideswitch(false),
- m_use_rambo(false)
+ m_rambo_supported(false),
+ m_reset_in(false),
+ m_modified(false),
+ m_page(0),
+ m_bank(0),
+ m_ramsize(0),
+ m_cru_base_horizon(0),
+ m_cru_base_phoenix(0)
{
}
-//-------------------------------------------------
-// nvram_default - called to initialize NVRAM to
-// its default state
-//-------------------------------------------------
-
-void horizon_ramdisk_device::nvram_default()
+void horizon_ramdisk_device::readz(offs_t offset, uint8_t *value)
{
- int size = 2097152*(1 << ioport("HORIZONSIZE")->read());
- memset(m_nvram->pointer(), 0, size);
- memset(m_ros->pointer(), 0, ROSSIZE);
+ read_write(offset, value, false);
}
-//-------------------------------------------------
-// nvram_read - called to read NVRAM from the
-// .nv file
-//-------------------------------------------------
-
-void horizon_ramdisk_device::nvram_read(emu_file &file)
+void horizon_ramdisk_device::write(offs_t offset, uint8_t data)
{
- int size = 2097152*(1 << ioport("HORIZONSIZE")->read());
-
- // NVRAM plus ROS
- uint8_t* buffer = global_alloc_array_clear<uint8_t>(MAXSIZE + ROSSIZE);
-
- memset(m_nvram->pointer(), 0, size);
- memset(m_ros->pointer(), 0, ROSSIZE);
-
- // We assume the last 8K is ROS
- int filesize = file.read(buffer, MAXSIZE+ROSSIZE);
- int nvramsize = filesize - ROSSIZE;
-
- // If there is a reasonable size
- if (nvramsize >= 0)
- {
- // Copy from buffer to NVRAM and ROS
- memcpy(m_nvram->pointer(), buffer, nvramsize);
- memcpy(m_ros->pointer(), buffer + nvramsize, ROSSIZE);
- }
-
- global_free_array(buffer);
+ read_write(offset, &data, true);
}
-//-------------------------------------------------
-// nvram_write - called to write NVRAM to the
-// .nv file
-//-------------------------------------------------
-
-void horizon_ramdisk_device::nvram_write(emu_file &file)
+/*
+ Read from or write to the card. This can involve the
+ a) optional 32K RAM (M32)
+ b) DSR RAM (U9)
+ c) set of RAM chips (M0-M31)
+*/
+void horizon_ramdisk_device::read_write(offs_t offset, uint8_t *value, bool write)
{
- int nvramsize = 2097152*(1 << ioport("HORIZONSIZE")->read());
+ // If AMA/B/C != 111, do not allow access. This "AMA decoding" was done
+ // by default by TI cards, but third-party cards did not comply in all cases.
- uint8_t* buffer = global_alloc_array_clear<uint8_t>(nvramsize + ROSSIZE);
- memcpy(buffer, m_nvram->pointer(), nvramsize);
- memcpy(buffer + nvramsize, m_ros->pointer(), ROSSIZE);
+ // HRD4000(B) used this decoding (U13); earlier Horizon cards did not
+ // implement it
+ if ((offset & 0x70000) != 0x70000) return;
- file.write(buffer, nvramsize + ROSSIZE);
-}
-
-READ8Z_MEMBER(horizon_ramdisk_device::readz)
-{
// 32K expansion
- // According to the manual, "this memory is not affected by the HIDE switch"
+ // According to [3], this memory is not affected by the HIDE switch
+ // Also, it cannot be mapped out by a CRU bit
+ //
+ // offset a14 a13
+ // ----------------
+ // | E000 | 0 0
+ // ----------------
+ // | C000 | 0 1
+ // ----------------
+ // | A000 | 1 0
+ // ----------------
+ // | 2000 | 1 1
+ // ----------------
+ //
+ // a14=/c*/e, a13=/a*/e (pins of the memory chip, not the address bus)
+
+ int sect = (offset>>13) & 0x07; // 8K sections in the 64K address space
+ int offset8k = (offset & 0x1fff);
+ int offset2k = (offset & 0x07ff);
+
if (m_32k_installed)
{
- switch((offset & 0xe000)>>13)
+ // Decoding by U12 and U11
+ int a14 = ((sect != 6) && (sect != 7))? 0x4000 : 0; // a14: 11x
+ int a13 = ((sect != 5) && (sect != 7))? 0x2000 : 0; // a13: 1x1
+
+ if ((sect == 1) || (sect == 5) || (sect == 6) || (sect == 7))
{
- case 1: // 2000-3fff
- *value = m_ram->pointer()[offset & 0x1fff];
- return;
- case 5: // a000-bfff
- *value = m_ram->pointer()[(offset & 0x1fff) | 0x2000];
- return;
- case 6: // c000-dfff
- *value = m_ram->pointer()[(offset & 0x1fff) | 0x4000];
- return;
- case 7: // e000-ffff
- *value = m_ram->pointer()[(offset & 0x1fff) | 0x6000];
+ if (write)
+ m_optram->write(offset8k | a14 | a13, *value);
+ else
+ *value = m_optram->read(offset8k | a14 | a13);
+
+ LOGMASKED(LOG_32K, "offset=%04x (32K) %s %02x\n", offset&0xffff, write? "<-" : "->", *value);
return;
- default:
- break;
}
}
- if (m_hideswitch) return;
+ // DSR RAM is not affected by SW2 either.
+ // CRU bit 0 must be set to 1 to activate it.
+ // Decoding by U12 and U7
+ int b_a = offset & 0x1800;
+ if (m_rambo_supported && m_crulatch_u3->q7_r()) b_a &= 0x0f00; // clear A3 (RAMBO mode)
- // I think RAMBO mode does not need the card to be selected
- if (!m_selected && !m_rambo_mode) return;
+ bool dsr = m_crulatch_u4->q0_r() && (sect == 2);
- if (!m_rambo_mode)
+ if (dsr && (b_a != 0x1800))
{
- if ((offset & m_select_mask) == m_select_value)
- {
- if ((offset & 0x1800) == 0x1800)
- {
- // NVRAM page of size 2 KiB
- *value = m_nvram->pointer()[(m_page << 11)|(offset & 0x07ff)];
- LOGMASKED(LOG_READ, "offset=%04x, page=%04x -> %02x\n", offset&0xffff, m_page, *value);
- }
- else
- {
- // ROS
- *value = m_ros->pointer()[offset & 0x1fff];
- LOGMASKED(LOG_READ, "offset=%04x (ROS) -> %02x\n", offset&0xffff, *value);
- }
- }
+ // DSR access
+ // All cards 2000-4000 have 8K RAM here
+ // The 4000B supports up to 32K; 4 banks can be selected
+ int a13 = (m_crulatch_u3->q6_r())? 0x2000 : 0;
+ int a14 = (!m_phoenix_accessed)? 0x4000 : 0;
+
+ if (write)
+ m_dsrram->write(offset8k | (m_dsr32k? (a13 | a14) : 0), *value);
+ else
+ *value = m_dsrram->read(offset8k | (m_dsr32k? (a13 | a14) : 0));
+
+ LOGMASKED(LOG_DSR, "offset=%04x (DSR) %s %02x\n", offset&0xffff, write? "<-" : "->", *value);
+ return;
}
- else
+
+ // Lower part of U7
+ if ((dsr && (b_a == 0x1800)) || ((sect == 3) && m_rambo_supported && m_crulatch_u3->q7_r()))
{
- if ((offset & m_select_mask)==m_select_value)
- {
- *value = m_ros->pointer()[offset & 0x1fff];
- LOGMASKED(LOG_READ, "offset=%04x (Rambo) -> %02x\n", offset&0xffff, *value);
- }
- if ((offset & m_select_mask)==m_select6_value)
+ // Access to a selected RAM
+ // Either in normal mode (on 5800) or in RAMBO mode (6000-7fff)
+ int page = m_page;
+ int ramaddress = offset2k;
+
+ // RAMBO mode
+ // If we are here in RAMBO mode, we are accessing 6000-7fff,
+ // because for sect 2 (4000-5fff), b_a was changed to be != 1800
+ if (m_rambo_supported && m_crulatch_u3->q7_r())
{
- // In RAMBO mode the page numbers are multiples of 4
- // (encompassing 4 Horizon pages)
- // We clear away the rightmost two bits
- *value = m_nvram->pointer()[((m_page&0xfffc)<<11) | (offset & 0x1fff)];
- LOGMASKED(LOG_READ, "offset=%04x, page=%04x (Rambo) -> %02x\n", offset&0xffff, m_page, *value);
+ // Replace the last two bits of the page number by address bits A3 and A4
+ // ...xx...........
+ // According to the specs, the lines must be swapped
+ // Hence, the 2k page number sequence in the 6000 space is
+ // base + 0 2 1 3
+ int a3_4 = (((offset & 0x0800)>>10) | ((offset & 0x1000)>>12));
+ page = (page & 0xfc) | a3_4;
}
- }
-}
-void horizon_ramdisk_device::write(offs_t offset, uint8_t data)
-{
- // 32K expansion
- // According to the manual, "this memory is not affected by the HIDE switch"
- if (m_32k_installed)
- {
- switch((offset & 0xe000)>>13)
+ // Just debugging stuff
+ if (page != m_current_page || m_bank != m_current_bank)
{
- case 1: // 2000-3fff
- m_ram->pointer()[offset & 0x1fff] = data;
- return;
- case 5: // a000-bfff
- m_ram->pointer()[(offset & 0x1fff) | 0x2000] = data;
- return;
- case 6: // c000-dfff
- m_ram->pointer()[(offset & 0x1fff) | 0x4000] = data;
- return;
- case 7: // e000-ffff
- m_ram->pointer()[(offset & 0x1fff) | 0x6000] = data;
- return;
- default:
- break;
+ LOGMASKED(LOG_PAGE, "Bank %02x, page %02x\n", m_bank, page);
+ m_current_bank = m_bank;
+ m_current_page = page;
}
- }
-
- if (m_hideswitch) return;
- // I think RAMBO mode does not need the card to be selected
- if (!m_selected && !m_rambo_mode) return;
+ if (m_128kx8)
+ // bb bbbp pppp p... .... ....
+ ramaddress |= ((page << 11) | (m_bank << 17));
+ else
+ // bbbb bppp pppp p... .... ....
+ ramaddress |= ((page << 11) | (m_bank << 19));
- if (!m_rambo_mode)
- {
- if ((offset & m_select_mask) == m_select_value)
+ if (ramaddress < m_ramsize)
{
- if ((offset & 0x1800) == 0x1800)
+ if (write)
{
- // NVRAM page of size 2 KiB
- m_nvram->pointer()[(m_page << 11)|(offset & 0x07ff)] = data;
- LOGMASKED(LOG_WRITE, "offset=%04x, page=%04x <- %02x\n", offset&0xffff, m_page, data);
+ m_modified = true;
+ m_ram->write(ramaddress, *value);
}
else
- {
- // ROS
- m_ros->pointer()[offset & 0x1fff] = data;
- LOGMASKED(LOG_WRITE, "offset=%04x (ROS) <- %02x\n", offset&0xffff, data);
- }
+ *value = m_ram->read(ramaddress);
+
+ LOGMASKED(LOG_RAM, "offset=%04x, page=%02x, bank=%02x %s %02x\n", offset&0xffff, page, m_bank, write? "<-" : "->", *value);
}
+ else
+ LOGMASKED(LOG_ORAM, "offset=%04x, page=%02x, bank=%02x %s outside of RAM space\n", offset&0xffff, page, m_bank, write? "write" : "read");
}
- else
+}
+
+/*
+ CRU read operation. There is not such read feature on the Horizon.
+*/
+void horizon_ramdisk_device::crureadz(offs_t offset, uint8_t *value)
+{
+}
+
+/*
+ CRU write operation.
+*/
+void horizon_ramdisk_device::cruwrite(offs_t offset, uint8_t data)
+{
+ // Horizon and Phoenix set to off = ff00 will never match
+ if (((offset & 0x1f00) != m_cru_base_horizon) && ((offset & 0x1f00) != m_cru_base_phoenix))
+ return;
+
+ int bit = (offset >> 1) & 0x0f;
+
+ // Set the latch U5
+ // For Geneve mode, it is set when a bit 8-15 is accessed; for the TI mode
+ // it is set for an access to the Phoenix CRU area
+ m_phoenix_accessed = m_geneve_mode? (bit >= 8) : ((offset & 0x1f00) == m_cru_base_phoenix);
+
+ // Set the latches U4 and U3 (unless the SW2 hideswitch is turned on)
+ if (m_hideswitch==false)
{
- if ((offset & m_select_mask)==m_select_value)
+ if (bit < 8)
{
- m_ros->pointer()[offset & 0x1fff] = data;
- LOGMASKED(LOG_WRITE, "offset=%04x (Rambo) <- %02x\n", offset&0xffff, data);
+ m_crulatch_u4->write_bit(bit & 7, data & 1);
}
- if ((offset & m_select_mask)==m_select6_value)
+ else
{
- // In RAMBO mode the page numbers are multiples of 4
- // (encompassing 4 Horizon pages)
- // We clear away the rightmost two bits
- m_nvram->pointer()[((m_page&0xfffc)<<11) | (offset & 0x1fff)] = data;
- LOGMASKED(LOG_WRITE, "offset=%04x, page=%04x (Rambo) <- %02x\n", offset&0xffff, m_page, data);
+ m_crulatch_u3->write_bit(bit & 7, data & 1);
}
+ get_address_prefix();
}
}
-READ8Z_MEMBER(horizon_ramdisk_device::crureadz)
+/*
+ Translate latch settings to page and bank.
+ Also called after savestate load.
+ This method is used to avoid reading all settings every time that a memory
+ access occurs.
+*/
+void horizon_ramdisk_device::get_address_prefix()
{
- // There is no CRU read operation for the Horizon.
- return;
-}
+ u8 latch1 = m_crulatch_u4->output_state();
+ u8 latch2 = m_crulatch_u3->output_state();
-void horizon_ramdisk_device::setbit(int& page, int pattern, bool set)
-{
- if (set)
+ // Latch 2 Latch 1
+ // ..lbbbbp ppppppp. 512k
+ // ....lbbb bpppppp. 128k
+ // l=layer b=bank p=page
+
+ if (m_128kx8)
{
- page |= pattern;
+ m_page = (latch1 >> 1) & 0x3f;
+ m_bank = ((latch1 >> 7) & 0x01) | ((latch2 << 1) & 0x1e);
}
else
{
- page &= ~pattern;
+ m_page = ((latch1 >> 1) & 0x7f) | ((latch2 << 7) & 0x80);
+ m_bank = (latch2 >> 1) & 0x1f;
+ }
+
+ // Phoenix jumper JP2
+ if (m_phoenix_split)
+ {
+ m_bank &= 0x08; // Clear the D bit
+ if (!m_phoenix_accessed) m_bank |= 0x08;
}
}
-void horizon_ramdisk_device::cruwrite(offs_t offset, uint8_t data)
+void horizon_ramdisk_device::reset_in(int state)
{
- int size = ioport("HORIZONSIZE")->read();
- int split_bit = size + 10;
- int splitpagebit = 0x0200 << size;
+ m_reset_in = (state==ASSERT_LINE);
- if (((offset & 0xff00)==m_cru_horizon)||((offset & 0xff00)==m_cru_phoenix))
+ // While the hideswitch is on, the /RESET line is pulled down
+ if (!m_hideswitch)
{
- int bit = (offset >> 1) & 0x0f;
- LOGMASKED(LOG_CRU, "CRU write bit %d <- %d\n", bit, data);
- switch (bit)
- {
- case 0:
- m_selected = (data!=0);
- LOGMASKED(LOG_CRU, "Activate ROS = %d\n", m_selected);
- break;
- case 1:
- // Swap the lines so that the access with RAMBO is consistent
- if (!m_rambo_mode) setbit(m_page, 0x0002, data!=0);
- break;
- case 2:
- // Swap the lines so that the access with RAMBO is consistent
- if (!m_rambo_mode) setbit(m_page, 0x0001, data!=0);
- break;
- case 3:
- case 4:
- case 5:
- case 6:
- case 7:
- case 8:
- case 9:
- setbit(m_page, 0x0001 << (bit-1), data!=0);
- break;
- case 14:
- break;
- case 15:
- if (m_use_rambo)
- {
- m_rambo_mode = (data != 0);
- LOGMASKED(LOG_CRU, "RAMBO = %d\n", m_rambo_mode);
- }
- break;
-
- default: // bits 10-13
- if (bit != split_bit || !m_split_mode)
- {
- if (bit <= split_bit) setbit(m_page, 0x0200<<(bit-10), data!=0);
- }
- break;
- }
-
- if (m_split_mode)
- {
- if (m_timode)
- {
- // In TI mode, switch between both RAMDisks using the CRU address
- setbit(m_page, splitpagebit, ((offset & 0xff00)==m_cru_phoenix));
- }
- else
- {
- // In Geneve mode, switch between both RAMdisks by
- // using the bit number of the last CRU access
- setbit(m_page, splitpagebit, (bit>7));
- }
- }
+ 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)
{
- m_cru_horizon = 0;
- m_cru_phoenix = 0;
-
- save_item(NAME(m_select6_value));
- save_item(NAME(m_select_all));
- save_item(NAME(m_page));
- save_item(NAME(m_cru_horizon));
- save_item(NAME(m_cru_phoenix));
- save_item(NAME(m_timode));
- save_item(NAME(m_32k_installed));
- save_item(NAME(m_split_mode));
- save_item(NAME(m_rambo_mode));
- save_item(NAME(m_hideswitch));
- save_item(NAME(m_use_rambo));
+ machine().save().register_postload(save_prepost_delegate(FUNC(horizon_ramdisk_device::get_address_prefix),this));
}
void horizon_ramdisk_device::device_reset(void)
{
- if (m_genmod)
+ m_cru_base_horizon = ioport("CRUHOR")->read();
+ m_cru_base_phoenix = ioport("CRUPHOE")->read();
+ m_32k_installed = (ioport("OPT32K")->read()!=0);
+ m_phoenix_split = (ioport("PHOENIX")->read()!=0);
+ m_hideswitch = (ioport("HIDESW2")->read()!=0);
+ m_dsr32k = (ioport("DSRSIZE")->read()!=0);
+ m_128kx8 = (ioport("CHIPTYPE")->read()==0);
+ m_geneve_mode = (ioport("MODE")->read()!=0);
+ m_rambo_supported = (ioport("RAMBO")->read()!=0);
+
+ int dsrsize = 0;
+ get_mem_size(m_ramsize, dsrsize);
+ LOGMASKED(LOG_CONFIG, "Horizon card memory: %d bytes\n", m_ramsize);
+}
+
+INPUT_CHANGED_MEMBER( horizon_ramdisk_device::hs_changed )
+{
+ if (param == 0)
{
- m_select_mask = 0x1fe000;
- m_select_value = 0x174000;
- m_select6_value = 0x176000;
- m_select_all = 0x170000;
+ 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
{
- m_select_mask = 0x7e000;
- m_select_value = 0x74000;
- m_select6_value = 0x76000;
- m_select_all = 0x70000;
+ LOGMASKED(LOG_CONFIG, "Phoenix split setting changed to %d\n", newval);
+ m_phoenix_split = (newval!=0);
}
+}
+
+/*
+ NVRAM support
+ The size of the file is num_chips * mem_per_chip + dsr_size
+ The contents of the RAM banks are stored first, then the
+ DSR chip contents are appended
+
+ 0 end
+ ____________________
+ | RAM | DSR |
+ --------------------
+*/
+void horizon_ramdisk_device::nvram_default()
+{
+ int ramsize, dsrsize;
+ get_mem_size(ramsize, dsrsize);
+
+ if (ramsize > 0) memset(m_ram->pointer(), 0, ramsize);
+ memset(m_dsrram->pointer(), 0, dsrsize);
+}
- m_cru_horizon = ioport("CRUHOR")->read();
- m_cru_phoenix = ioport("CRUPHOE")->read();
- m_32k_installed = (ioport("HORIZON32")->read()!=0);
+bool horizon_ramdisk_device::nvram_read(util::read_stream &file)
+{
+ int ramsize, dsrsize;
+ get_mem_size(ramsize, dsrsize);
- m_split_mode = (ioport("HORIZONDUAL")->read()!=0);
- m_timode = (ioport("HORIZONDUAL")->read()==1);
+ // NVRAM plus ROS, according to the current configuration
+ auto buffer = make_unique_clear<uint8_t []>(ramsize + dsrsize);
- m_rambo_mode = false;
- m_hideswitch = (ioport("HORIZONACT")->read()!=0);
+ if (ramsize > 0) memset(m_ram->pointer(), 0, ramsize);
+ memset(m_dsrram->pointer(), 0, dsrsize);
- m_use_rambo = (ioport("RAMBO")->read()!=0);
+ // Read complete file, at most ramsize+dsrsize
+ // Mind that the configuration may have changed
+ auto const [err, filesize] = util::read(file, &buffer[0], ramsize + dsrsize);
+ if (err)
+ return false;
+ int nvramsize = int(filesize) - dsrsize;
- m_page = 0;
- m_selected = false;
+ // At least the DSR must be complete
+ if (nvramsize >= 0)
+ {
+ // Copy from buffer to NVRAM and ROS
+ if (nvramsize > 0) memcpy(m_ram->pointer(), &buffer[0], nvramsize);
+ memcpy(m_dsrram->pointer(), &buffer[nvramsize], dsrsize);
+
+ return true;
+ }
+
+ return false;
}
-INPUT_CHANGED_MEMBER( horizon_ramdisk_device::hs_changed )
+bool horizon_ramdisk_device::nvram_write(util::write_stream &file)
{
- LOGMASKED(LOG_CONFIG, "hideswitch changed %d\n", newval);
- m_hideswitch = (newval!=0);
+ int ramsize, dsrsize;
+ get_mem_size(ramsize, dsrsize);
+
+ // NVRAM plus ROS, according to the current configuration
+ auto buffer = make_unique_clear<uint8_t []>(ramsize + dsrsize);
+
+ memcpy(&buffer[0], m_ram->pointer(), ramsize);
+ memcpy(&buffer[ramsize], m_dsrram->pointer(), dsrsize);
+
+ // Store both parts in one file
+ auto const [err, filesize] = util::write(file, buffer.get(), ramsize + dsrsize);
+ return !err;
+}
+
+bool horizon_ramdisk_device::nvram_can_write() const
+{
+ // Do not save if nothing was written. This is helpful to avoid loss of the
+ // contents when the settings were found to be different, and the emulation
+ // has to be restarted after restoring the settings.
+ return m_modified;
+}
+
+
+void horizon_ramdisk_device::get_mem_size(int& ramsize, int& dsrsize)
+{
+ int chipsize = 128*1024*((ioport("CHIPTYPE")->read()*3)+1);
+ ramsize = (ioport("CHIPCOUNT")->read()*4) * chipsize;
+ dsrsize = ((ioport("DSRSIZE")->read()*3)+1)*8192;
}
/*
@@ -434,9 +538,9 @@ INPUT_CHANGED_MEMBER( horizon_ramdisk_device::hs_changed )
*/
INPUT_PORTS_START( horizon )
PORT_START( "CRUHOR" )
- PORT_DIPNAME( 0x1f00, 0x1200, "Horizon CRU base" )
- PORT_DIPSETTING( 0x0000, DEF_STR( Off ) )
- PORT_DIPSETTING( 0x1000, "1000" )
+ PORT_DIPNAME( 0xff00, 0x1200, "SW1 Horizon CRU base" )
+ PORT_DIPSETTING( 0xff00, DEF_STR( Off ) )
+ PORT_DIPSETTING( 0x1000, "1000" ) // 1100 and 1300 not available
PORT_DIPSETTING( 0x1200, "1200" )
PORT_DIPSETTING( 0x1400, "1400" )
PORT_DIPSETTING( 0x1500, "1500" )
@@ -444,46 +548,77 @@ INPUT_PORTS_START( horizon )
PORT_DIPSETTING( 0x1700, "1700" )
PORT_START( "CRUPHOE" )
- PORT_DIPNAME( 0x1f00, 0x0000, "Phoenix CRU base" )
- PORT_DIPSETTING( 0x0000, DEF_STR( Off ) )
- PORT_DIPSETTING( 0x1400, "1400" )
+ PORT_DIPNAME( 0xff00, 0xff00, "SW1 Phoenix CRU base" )
+ PORT_DIPSETTING( 0xff00, DEF_STR( Off ) )
+ PORT_DIPSETTING( 0x1400, "1400" ) // must not be used when selected for Horizon
PORT_DIPSETTING( 0x1600, "1600" )
- PORT_START( "HORIZONDUAL" )
- PORT_DIPNAME( 0x03, 0x00, "Horizon ramdisk split" )
+ PORT_START( "MODE" )
+ PORT_DIPNAME( 0x01, 0x00, "JP4 Split mode" )
+ PORT_DIPSETTING( 0x00, "TI mode" )
+ PORT_DIPSETTING( 0x01, "Geneve mode" )
+
+ PORT_START( "HIDESW2" )
+ PORT_DIPNAME( 0x01, 0x00, "SW2 Hideswitch" ) PORT_CHANGED_MEMBER(DEVICE_SELF, FUNC(horizon_ramdisk_device::hs_changed), 0)
PORT_DIPSETTING( 0x00, DEF_STR( Off ) )
- PORT_DIPSETTING( 0x01, "TI mode" )
- PORT_DIPSETTING( 0x02, "Geneve mode" )
+ PORT_DIPSETTING( 0x01, DEF_STR( On ) )
- PORT_START( "HORIZONACT" )
- PORT_DIPNAME( 0x01, 0x00, "Horizon hideswitch" ) PORT_CHANGED_MEMBER(DEVICE_SELF, horizon_ramdisk_device, hs_changed, 0)
+ PORT_START( "PHOENIX" )
+ PORT_DIPNAME( 0x01, 0x00, "JP2 Phoenix split" ) PORT_CHANGED_MEMBER(DEVICE_SELF, FUNC(horizon_ramdisk_device::hs_changed), 1)
PORT_DIPSETTING( 0x00, DEF_STR( Off ) )
PORT_DIPSETTING( 0x01, DEF_STR( On ) )
- PORT_START( "HORIZON32" )
- PORT_CONFNAME( 0x01, 0x00, "Horizon 32 KiB upgrade" )
+// --------------------------------------------------------------------
+
+ PORT_START( "CHIPTYPE" )
+ PORT_CONFNAME( 0x01, 0x00, "Memory circuit type" )
+ PORT_CONFSETTING( 0x00, "128Kx8")
+ PORT_CONFSETTING( 0x01, "512Kx8")
+
+ PORT_START( "CHIPCOUNT" )
+ PORT_CONFNAME( 0x0f, 0x04, "Memory circuit count" )
+ PORT_CONFSETTING( 0x00, "0")
+ PORT_CONFSETTING( 0x01, "4")
+ PORT_CONFSETTING( 0x02, "8")
+ PORT_CONFSETTING( 0x03, "12")
+ PORT_CONFSETTING( 0x04, "16")
+ PORT_CONFSETTING( 0x05, "20")
+ PORT_CONFSETTING( 0x06, "24")
+ PORT_CONFSETTING( 0x07, "28")
+ PORT_CONFSETTING( 0x08, "32")
+
+ PORT_START( "DSRSIZE" )
+ PORT_CONFNAME( 0x01, 0x00, "DSR memory size" )
+ PORT_CONFSETTING( 0x00, "8 KiB" )
+ PORT_CONFSETTING( 0x01, "32 KiB" )
+
+ PORT_START( "OPT32K" )
+ PORT_CONFNAME( 0x01, 0x00, "Optional 32 KiB memory" )
PORT_CONFSETTING( 0x00, DEF_STR( Off ))
PORT_CONFSETTING( 0x01, DEF_STR( On ))
PORT_START( "RAMBO" )
- PORT_CONFNAME( 0x01, 0x01, "Horizon RAMBO" )
+ PORT_CONFNAME( 0x01, 0x00, "RAMBO support" )
PORT_CONFSETTING( 0x00, DEF_STR( Off ))
PORT_CONFSETTING( 0x01, DEF_STR( On ))
- PORT_START( "HORIZONSIZE" )
- PORT_CONFNAME( 0x03, 0x00, "Horizon size" )
- PORT_CONFSETTING( 0x00, "2 MiB")
- PORT_CONFSETTING( 0x01, "4 MiB")
- PORT_CONFSETTING( 0x02, "8 MiB")
- PORT_CONFSETTING( 0x03, "16 MiB")
-
INPUT_PORTS_END
void horizon_ramdisk_device::device_add_mconfig(machine_config &config)
{
- RAM(config, NVRAMREGION).set_default_size("16M");
- RAM(config, ROSREGION).set_default_size("8K");
- RAM(config, RAMREGION).set_default_size("32K").set_default_value(0);
+ // It could make sense to use buffered_ram (BUFF_RAM) for the 16M RAM and
+ // the DSR RAM which has its own NVRAM handler. However, we want to have
+ // a configurable emulation, and the config switches are not available
+ // before the NVRAM handlers of the subdevices kick in. It could be done
+ // if the NVRAM files always use the same (maximum) size.
+
+ RAM(config, RAM16M_TAG).set_default_size("16M");
+ RAM(config, DSRRAM_TAG).set_default_size("32K");
+ RAM(config, OPT32K_TAG).set_default_size("32K").set_default_value(0);
+
+ // CRU latches
+ LS259(config, m_crulatch_u4);
+ LS259(config, m_crulatch_u3);
}
ioport_constructor horizon_ramdisk_device::device_input_ports() const
@@ -491,4 +626,4 @@ ioport_constructor horizon_ramdisk_device::device_input_ports() const
return INPUT_PORTS_NAME(horizon);
}
-} } } // end namespace bus::ti99::peb
+} // end namespace bus::ti99::peb
diff --git a/src/devices/bus/ti99/peb/horizon.h b/src/devices/bus/ti99/peb/horizon.h
index f72e9f109fc..7fb99429f5b 100644
--- a/src/devices/bus/ti99/peb/horizon.h
+++ b/src/devices/bus/ti99/peb/horizon.h
@@ -18,55 +18,74 @@
#include "peribox.h"
#include "machine/ram.h"
+#include "machine/74259.h"
-namespace bus { namespace ti99 { namespace peb {
+namespace bus::ti99::peb {
class horizon_ramdisk_device : public device_t, public device_ti99_peribox_card_interface, public device_nvram_interface
{
public:
horizon_ramdisk_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
- DECLARE_READ8Z_MEMBER(readz) override;
+ void readz(offs_t offset, uint8_t *value) override;
void write(offs_t offset, uint8_t data) override;
- DECLARE_READ8Z_MEMBER(crureadz) override;
+ void crureadz(offs_t offset, uint8_t *value) override;
void cruwrite(offs_t offset, uint8_t data) override;
DECLARE_INPUT_CHANGED_MEMBER( hs_changed );
protected:
- void device_start() override;
- void device_reset() override;
+ virtual void device_start() override ATTR_COLD;
+ virtual void device_reset() override ATTR_COLD;
- virtual void device_add_mconfig(machine_config &config) override;
- virtual ioport_constructor device_input_ports() const override;
+ virtual void device_add_mconfig(machine_config &config) override ATTR_COLD;
+ virtual ioport_constructor device_input_ports() const override ATTR_COLD;
- void nvram_default() override;
- void nvram_read(emu_file &file) override;
- void nvram_write(emu_file &file) override;
+ virtual void nvram_default() override;
+ virtual bool nvram_read(util::read_stream &file) override;
+ virtual bool nvram_write(util::write_stream &file) override;
+ virtual bool nvram_can_write() const override;
-private:
- void setbit(int& page, int pattern, bool set);
+ void reset_in(int state) override;
+private:
required_device<ram_device> m_ram;
- required_device<ram_device> m_nvram;
- required_device<ram_device> m_ros;
+ required_device<ram_device> m_dsrram;
+ required_device<ram_device> m_optram;
+ required_device<ls259_device> m_crulatch_u4;
+ required_device<ls259_device> m_crulatch_u3;
- int m_select6_value;
- int m_select_all;
+ void get_mem_size(int& ramsize, int& dsrsize);
+ void get_address_prefix();
+ void read_write(offs_t offset, uint8_t *value, bool write);
- int m_page;
-
- int m_cru_horizon;
- int m_cru_phoenix;
- bool m_timode;
bool m_32k_installed;
- bool m_split_mode;
- bool m_rambo_mode;
+ bool m_phoenix_accessed;
+ bool m_dsr32k;
+ bool m_128kx8;
+ bool m_geneve_mode;
+ bool m_phoenix_split;
bool m_hideswitch;
- bool m_use_rambo;
+ bool m_rambo_supported;
+
+ bool m_reset_in;
+
+ // Do not save if nothing was modified.
+ bool m_modified;
+
+ int m_page;
+ int m_bank;
+ int m_ramsize;
+
+ int m_cru_base_horizon;
+ int m_cru_base_phoenix;
+
+ // Debugging
+ int m_current_bank;
+ int m_current_page;
};
-} } } // end namespace bus::ti99::peb
+} // end namespace bus::ti99::peb
DECLARE_DEVICE_TYPE_NS(TI99_HORIZON, bus::ti99::peb, horizon_ramdisk_device)
diff --git a/src/devices/bus/ti99/peb/hsgpl.cpp b/src/devices/bus/ti99/peb/hsgpl.cpp
index 11f40c4d1c8..11c593cd656 100644
--- a/src/devices/bus/ti99/peb/hsgpl.cpp
+++ b/src/devices/bus/ti99/peb/hsgpl.cpp
@@ -121,24 +121,24 @@
#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"
-DEFINE_DEVICE_TYPE_NS(TI99_HSGPL, bus::ti99::peb, snug_high_speed_gpl_device, "ti99_hsgpl", "SNUG High-speed GPL card")
+DEFINE_DEVICE_TYPE(TI99_HSGPL, bus::ti99::peb::snug_high_speed_gpl_device, "ti99_hsgpl", "SNUG High-speed GPL card")
-namespace bus { namespace ti99 { namespace peb {
+namespace bus::ti99::peb {
#define CRU_BASE 0x1B00
#define SUPERCART_BASE 0x0800
@@ -183,7 +183,7 @@ snug_high_speed_gpl_device::snug_high_speed_gpl_device(const machine_config &mco
/*
Read hsgpl CRU interface. None here.
*/
-READ8Z_MEMBER(snug_high_speed_gpl_device::crureadz)
+void snug_high_speed_gpl_device::crureadz(offs_t offset, uint8_t *value)
{
return;
}
@@ -268,7 +268,7 @@ void snug_high_speed_gpl_device::cruwrite(offs_t offset, uint8_t data)
/*
Memory read
*/
-READ8Z_MEMBER(snug_high_speed_gpl_device::readz)
+void snug_high_speed_gpl_device::readz(offs_t offset, uint8_t *value)
{
if ((offset & 0x7e000)==0x74000)
{
@@ -717,4 +717,4 @@ ioport_constructor snug_high_speed_gpl_device::device_input_ports() const
return INPUT_PORTS_NAME(ti99_hsgpl);
}
-} } } // end namespace bus::ti99::peb
+} // end namespace bus::ti99::peb
diff --git a/src/devices/bus/ti99/peb/hsgpl.h b/src/devices/bus/ti99/peb/hsgpl.h
index 7248436963f..e0d58ba42fe 100644
--- a/src/devices/bus/ti99/peb/hsgpl.h
+++ b/src/devices/bus/ti99/peb/hsgpl.h
@@ -22,25 +22,25 @@
#include "machine/at29x.h"
#include "machine/ram.h"
-namespace bus { namespace ti99 { namespace peb {
+namespace bus::ti99::peb {
class snug_high_speed_gpl_device : public device_t, public device_ti99_peribox_card_interface
{
public:
snug_high_speed_gpl_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
- DECLARE_READ8Z_MEMBER(readz) override;
+ void readz(offs_t offset, uint8_t *value) override;
void write(offs_t offset, uint8_t data) override;
- DECLARE_READ8Z_MEMBER(crureadz) override;
+ void crureadz(offs_t offset, uint8_t *value) override;
void cruwrite(offs_t offset, uint8_t data) override;
protected:
- virtual void device_start() override;
- virtual void device_reset() override;
- virtual void device_stop() override;
- virtual ioport_constructor device_input_ports() const override;
+ virtual void device_start() override ATTR_COLD;
+ virtual void device_reset() override ATTR_COLD;
+ virtual void device_stop() override ATTR_COLD;
+ virtual ioport_constructor device_input_ports() const override ATTR_COLD;
- virtual void device_add_mconfig(machine_config &config) override;
+ virtual void device_add_mconfig(machine_config &config) override ATTR_COLD;
private:
required_device<at29c040a_device> m_dsr_eeprom;
@@ -81,7 +81,7 @@ private:
int m_grom_address;
};
-} } } // end namespace bus::ti99::peb
+} // end namespace bus::ti99::peb
DECLARE_DEVICE_TYPE_NS(TI99_HSGPL, bus::ti99::peb, snug_high_speed_gpl_device)
diff --git a/src/devices/bus/ti99/peb/memex.cpp b/src/devices/bus/ti99/peb/memex.cpp
index 3a3116d262d..67011503bf6 100644
--- a/src/devices/bus/ti99/peb/memex.cpp
+++ b/src/devices/bus/ti99/peb/memex.cpp
@@ -15,15 +15,19 @@
#include "emu.h"
#include "memex.h"
-#define LOG_WARN (1U<<1) // Warnings
-#define LOG_CONFIG (1U<<2) // Configuration
-#define VERBOSE ( LOG_CONFIG | LOG_WARN )
+#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)
#include "logmacro.h"
-DEFINE_DEVICE_TYPE_NS(TI99_MEMEX, bus::ti99::peb, geneve_memex_device, "ti99_memex", "Geneve memory expansion card")
+DEFINE_DEVICE_TYPE(TI99_MEMEX, bus::ti99::peb::geneve_memex_device, "ti99_memex", "Geneve memory expansion card")
-namespace bus { namespace ti99 { namespace peb {
+namespace bus::ti99::peb {
#define RAMREGION "ram2meg"
@@ -56,12 +60,19 @@ bool geneve_memex_device::access_enabled(offs_t offset)
// we may have to lock out those areas
int page = (offset >> 13)&0xff;
+ // All mirrors of page ba via AMD/AME are blocked.
+ // These are 3a, 7a, ba, and fa.
+ if ((page & 0x3f)==0x3a)
+ {
+ LOGMASKED(LOG_BLOCK, "memex blocks page %02x\n", page);
+ return false;
+ }
+
// SW2: 10xxx010 locked when SW2=off
// 10111010 locked when SW2=on
- if (page == 0xba) return false;
if ((page & 0xc7)==0x82 && ((m_switches & MDIP2)==0))
{
- LOGMASKED(LOG_CONFIG, "memex blocks page %02x; dip2=%d\n", page, (m_switches & MDIP2)!=0);
+ LOGMASKED(LOG_BLOCK, "memex blocks page %02x; dip2=%d\n", page, (m_switches & MDIP2)!=0);
return false;
}
@@ -88,14 +99,17 @@ bool geneve_memex_device::access_enabled(offs_t offset)
Note that the incomplete decoding of the standard Geneve must be
considered.
*/
-READ8Z_MEMBER( geneve_memex_device::readz )
+void geneve_memex_device::readz(offs_t offset, uint8_t *value)
{
/* If not Genmod, add the upper two address bits 10 */
- if (!m_genmod) offset |= 0x100000;
+// if (!m_genmod) offset |= 0x100000;
// The card is accessed for all addresses in the address space
if (access_enabled(offset))
+ {
*value = m_ram->pointer()[offset];
+ LOGMASKED(LOG_READ, "%06x -> %02x\n", offset, *value);
+ }
}
/*
@@ -104,11 +118,14 @@ READ8Z_MEMBER( geneve_memex_device::readz )
void geneve_memex_device::write(offs_t offset, uint8_t data)
{
/* If not Genmod, add the upper two address bits 10 */
- if (!m_genmod) offset |= 0x100000;
+// if (!m_genmod) offset |= 0x100000;
// The card is accessed for all addresses in the address space
if (access_enabled(offset))
+ {
+ LOGMASKED(LOG_WRITE, "%06x <- %02x\n", offset, data);
m_ram->pointer()[offset] = data;
+ }
}
/**************************************************************************/
@@ -164,4 +181,4 @@ ioport_constructor geneve_memex_device::device_input_ports() const
return INPUT_PORTS_NAME( memex );
}
-} } } // end namespace bus::ti99::peb
+} // end namespace bus::ti99::peb
diff --git a/src/devices/bus/ti99/peb/memex.h b/src/devices/bus/ti99/peb/memex.h
index fb7ca27a1ad..4db2e3d2feb 100644
--- a/src/devices/bus/ti99/peb/memex.h
+++ b/src/devices/bus/ti99/peb/memex.h
@@ -18,31 +18,31 @@
#include "peribox.h"
#include "machine/ram.h"
-namespace bus { namespace ti99 { namespace peb {
-
+namespace bus::ti99::peb {
class geneve_memex_device : public device_t, public device_ti99_peribox_card_interface
{
public:
geneve_memex_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
- DECLARE_READ8Z_MEMBER(readz) override;
+ void readz(offs_t offset, uint8_t *value) override;
void write(offs_t offset, uint8_t data) override;
- DECLARE_READ8Z_MEMBER(crureadz) override { }
+ void crureadz(offs_t offset, uint8_t *value) override { }
void cruwrite(offs_t offset, uint8_t data) override { }
protected:
- void device_start() override;
- void device_reset() override;
- virtual void device_add_mconfig(machine_config &config) override;
- virtual ioport_constructor device_input_ports() const override;
+ void device_start() override ATTR_COLD;
+ void device_reset() override ATTR_COLD;
+ virtual void device_add_mconfig(machine_config &config) override ATTR_COLD;
+ virtual ioport_constructor device_input_ports() const override ATTR_COLD;
private:
bool access_enabled(offs_t offset);
required_device<ram_device> m_ram;
uint8_t m_switches;
};
-} } } // end namespace bus::ti99::peb
+
+} // end namespace bus::ti99::peb
DECLARE_DEVICE_TYPE_NS(TI99_MEMEX, bus::ti99::peb, geneve_memex_device)
diff --git a/src/devices/bus/ti99/peb/myarcfdc.cpp b/src/devices/bus/ti99/peb/myarcfdc.cpp
new file mode 100644
index 00000000000..de8d98962db
--- /dev/null
+++ b/src/devices/bus/ti99/peb/myarcfdc.cpp
@@ -0,0 +1,515 @@
+// license:LGPL-2.1+
+// copyright-holders:Michael Zapf
+/*******************************************************************************
+ Myarc Floppy Disk Controller (DDCC-1)
+ Double Density, Double-sided
+ May be used with a 1770 or 1772 controller
+
+ EPROM 2764A (8Kx8) in two banks (2x 4000-4fff)
+ SRAM HM6116 (2Kx8) (5000-57ff)
+
+ DIP switches (SW1) set the head step rate. For the 1770 controller, closed
+ switches mean 20ms, open switches mean 6ms. For the 1772 controller, closed
+ means 2ms, open means 6 ms. There is an alternative ROM for the 1772 which
+ allows for slower step rates (6ms-12ms).
+
+ Another switch is included (SW2) labeled "Turbo" on schematics, but which
+ is not present on all boards. It may require a different ROM.
+
+ Michael Zapf
+ March 2020
+
+*******************************************************************************/
+
+#include "emu.h"
+#include "myarcfdc.h"
+#include "formats/ti99_dsk.h"
+
+// ----------------------------------
+// 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 << 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"
+#define LATCH_TAG "ls259"
+#define WD1770_TAG "wd1770"
+#define WD1772_TAG "wd1772"
+#define PAL_TAG "pal"
+
+DEFINE_DEVICE_TYPE(TI99_DDCC1, bus::ti99::peb::myarc_fdc_device, "ti99_ddcc1", "Myarc Disk Controller Card")
+DEFINE_DEVICE_TYPE(DDCC1_PAL, bus::ti99::peb::ddcc1_pal_device, PAL_TAG, "Myarc DDCC-1 PAL u1")
+
+namespace bus::ti99::peb {
+
+// ----------------------------------
+
+myarc_fdc_device::myarc_fdc_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock):
+ device_t(mconfig, TI99_DDCC1, tag, owner, clock),
+ device_ti99_peribox_card_interface(mconfig, *this),
+ m_wdc(nullptr),
+ m_wd1770(*this, WD1770_TAG),
+ m_wd1772(*this, WD1772_TAG),
+ m_drivelatch(*this, LATCH_TAG),
+ 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),
+ m_address(0)
+ { }
+
+void myarc_fdc_device::setaddress_dbin(offs_t offset, int state)
+{
+ // Do not allow setaddress for debugger
+ if (machine().side_effects_disabled()) return;
+ m_address = offset;
+}
+
+bool myarc_fdc_device::card_selected()
+{
+ return m_cardsel;
+}
+/*
+ Provides the current address to the PAL.
+*/
+offs_t myarc_fdc_device::get_address()
+{
+ return m_address;
+}
+
+/*
+ Debugger access.
+*/
+void myarc_fdc_device::debug_read(offs_t offset, uint8_t* value)
+{
+ offs_t addrcopy = m_address;
+
+ if (!m_dec_high || amabc_is_set(offset))
+ {
+ m_address = offset;
+ if (m_pal->ramsel())
+ {
+ *value = m_buffer_ram->pointer()[m_address & 0x07ff];
+ }
+
+ if (m_pal->romen())
+ {
+ // EPROM selected
+ offs_t base = m_banksel? 0x1000 : 0;
+ *value = m_dsrrom[base | (m_address & 0x0fff)];
+ }
+ m_address = addrcopy;
+ }
+}
+
+/*
+ Debugger access.
+*/
+void myarc_fdc_device::debug_write(offs_t offset, uint8_t data)
+{
+ offs_t addrcopy = m_address;
+
+ if (!m_dec_high || amabc_is_set(offset))
+ {
+ m_address = offset;
+ if (m_pal->ramsel())
+ {
+ m_buffer_ram->pointer()[m_address & 0x07ff] = data;
+ }
+ m_address = addrcopy;
+ }
+}
+
+/*
+ Read access to the RAM, EPROM, and controller chip.
+*/
+void myarc_fdc_device::readz(offs_t offset, uint8_t *value)
+{
+ if (machine().side_effects_disabled())
+ {
+ debug_read(offset, value);
+ return;
+ }
+
+ // If we have an AMA/B/C decoder and it delivers false, exit here
+ if (m_dec_high && !amabc_is_set(offset)) return;
+
+ if (m_pal->ramsel())
+ {
+ // SRAM selected
+ *value = m_buffer_ram->pointer()[m_address & 0x07ff];
+ LOGMASKED(LOG_RAM, "Read RAM: %04x -> %02x\n", m_address & 0xffff, *value);
+ }
+
+ if (m_pal->romen())
+ {
+ // EPROM selected
+ offs_t base = m_banksel? 0x1000 : 0;
+ uint8_t* rom = &m_dsrrom[base | (m_address & 0x0fff)];
+ *value = *rom;
+
+ if (WORD_ALIGNED(m_address))
+ {
+ uint16_t val = (*rom << 8) | (*(rom+1));
+ LOGMASKED(LOG_EPROM, "Read DSR: %04x (page %d)-> %04x\n", m_address & 0xffff, base>>12, val);
+ }
+ }
+
+ if (m_pal->fdcsel())
+ {
+ // WDC selected
+ *value = m_wdc->read((m_address >> 1)&0x03);
+ LOGMASKED(LOG_CONTR, "Read FDC: %04x -> %02x\n", m_address & 0xffff, *value);
+ }
+}
+
+/*
+ Write access to RAM and the controller chip.
+*/
+void myarc_fdc_device::write(offs_t offset, uint8_t data)
+{
+ if (machine().side_effects_disabled())
+ {
+ debug_write(offset, data);
+ return;
+ }
+
+ // If we have an AMA/B/C decoder and it delivers false, exit here
+ if (m_dec_high && !amabc_is_set(offset)) return;
+
+ if (m_pal->ramsel())
+ {
+ // SRAM selected
+ LOGMASKED(LOG_RAM, "Write RAM: %04x <- %02x\n", m_address & 0xffff, data);
+ m_buffer_ram->pointer()[m_address & 0x07ff] = data;
+ }
+
+ if (m_pal->fdcsel())
+ {
+ // WDC selected
+ LOGMASKED(LOG_CONTR, "Write FDC: %04x <- %02x\n", m_address & 0xffff, data);
+ m_wdc->write((m_address >> 1)&0x03, data);
+ }
+}
+
+/*
+ CRU read access to the LS251 multiplexer.
+*/
+void myarc_fdc_device::crureadz(offs_t offset, uint8_t *value)
+{
+ const uint8_t dipswitch[] = { 0x00, 0x01, 0x02, 0x04, 0x08 };
+ offs_t addrcopy = m_address;
+ m_address = offset; // Copy the CRU address on the address variable
+ if (m_pal->cs251())
+ {
+ int bitno = ((offset & 0x0e)>>1);
+ switch (bitno)
+ {
+ case 0: // INTRQ
+ *value = (m_wdc->intrq_r()==ASSERT_LINE)? 1:0;
+ break;
+ case 1: // DRQ
+ *value = (m_wdc->drq_r()==ASSERT_LINE)? 1:0;
+ break;
+ case 2: // Turbo (not on every card)
+ *value = ioport("SW2")->read();
+ break;
+ case 3: // NC
+ break;
+ default:
+ // Open = 6ms, close = 20ms (2ms)
+ *value = ((ioport("SW1")->read() & dipswitch[8-bitno])!=0)? 0:1;
+ break;
+ }
+ LOGMASKED(LOG_CRU, "cru %04x (bit %d) -> %d\n", offset, bitno, *value);
+ }
+ m_address = addrcopy;
+}
+
+/*
+ CRU write access to the LS259 latch.
+*/
+void myarc_fdc_device::cruwrite(offs_t offset, uint8_t data)
+{
+ offs_t addrcopy = m_address;
+ m_address = offset; // Copy the CRU address on the address variable
+ if (m_pal->cs259())
+ {
+ int bitno = ((offset & 0x0e)>>1);
+ LOGMASKED(LOG_CRU, "cru %04x (bit %d) <- %d\n", offset, bitno, data);
+ m_drivelatch->write_bit(bitno, BIT(data, 0));
+ }
+ m_address = addrcopy;
+}
+
+/*
+ Callbacks from the WDC chip
+*/
+void myarc_fdc_device::fdc_irq_w(int state)
+{
+ LOGMASKED(LOG_IRQ, "INTRQ callback = %d\n", state);
+}
+
+void myarc_fdc_device::fdc_drq_w(int state)
+{
+ LOGMASKED(LOG_DRQ, "DRQ callback = %d\n", state);
+}
+
+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 (auto &flop : m_floppy)
+ if (flop->get_device() != nullptr) flop->get_device()->mon_w(state);
+}
+
+/*
+ Callbacks from the 74LS259 latch
+*/
+void myarc_fdc_device::den_w(int state)
+{
+ LOGMASKED(LOG_CRU, "Card enable = %d\n", state);
+ m_cardsel = (state==1);
+}
+
+void myarc_fdc_device::wdreset_w(int state)
+{
+ LOGMASKED(LOG_CRU, "Controller reset = %d\n", state);
+ m_wdc->mr_w(state);
+}
+
+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]->get_device()->ss_w(state);
+ }
+}
+
+// Selects the EPROM bank, and also controls the DDEN line
+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);
+}
+
+void myarc_fdc_device::drivesel_w(int state)
+{
+ int driveno = 0;
+
+ // We do not know what happens when two drives are selected
+ if (m_drivelatch->q7_r() != 0) driveno = 4;
+ if (m_drivelatch->q6_r() != 0) driveno = 3;
+ if (m_drivelatch->q5_r() != 0) driveno = 2;
+ if (m_drivelatch->q4_r() != 0) driveno = 1;
+
+ if (state == CLEAR_LINE)
+ {
+ // Only when no bit is set, unselect all drives.
+ // The DSR actually selects the new drive first, then unselects
+ // the old drive.
+ if (driveno==0)
+ {
+ LOGMASKED(LOG_DRIVE, "Unselect all drives\n");
+ m_wdc->set_floppy(nullptr);
+ m_selected_drive = 0;
+ }
+ }
+ else
+ {
+ 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]->get_device());
+ m_floppy[driveno-1]->get_device()->ss_w(m_drivelatch->q2_r());
+ }
+ }
+}
+
+void myarc_fdc_device::device_start()
+{
+ m_dsrrom = memregion(TI99_DSRROM)->base();
+ save_item(NAME(m_banksel));
+ save_item(NAME(m_cardsel));
+ save_item(NAME(m_selected_drive));
+ save_item(NAME(m_address));
+}
+
+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);
+
+ m_pal->set_board(this);
+}
+
+void myarc_fdc_device::floppy_formats(format_registration &fr)
+{
+ fr.add_mfm_containers();
+ fr.add(FLOPPY_TI99_SDF_FORMAT);
+ fr.add(FLOPPY_TI99_TDF_FORMAT);
+}
+
+static void myarc_ddcc_floppies(device_slot_interface &device)
+{
+ device.option_add("525dd", FLOPPY_525_DD); // 40 tracks
+ device.option_add("525qd", FLOPPY_525_QD); // 80 tracks
+ device.option_add("35dd", FLOPPY_35_DD); // 80 tracks
+}
+
+INPUT_PORTS_START(myarc_ddcc )
+ PORT_START( "CONTROLLER" )
+ PORT_CONFNAME( 0x01, 0x00, "Controller chip")
+ PORT_CONFSETTING(0x00, "WD1770")
+ PORT_CONFSETTING(0x01, "WD1772")
+
+ PORT_START( "SW2" )
+ PORT_DIPNAME( 0x01, 0x00, "Turbo switch" )
+ PORT_DIPSETTING(0x00, DEF_STR( Off ))
+ PORT_DIPSETTING(0x01, DEF_STR( On ))
+
+ PORT_START( "SW1" )
+ PORT_DIPNAME( 0x01, 0x00, "DSK1 head step time" )
+ PORT_DIPSETTING( 0x00, "6ms") // 6 ms for 1770
+ PORT_DIPSETTING( 0x01, "20ms/2ms") // 20 ms for 1770 and 2ms for 1772
+ PORT_DIPNAME( 0x02, 0x00, "DSK2 head step time" )
+ PORT_DIPSETTING( 0x00, "6ms")
+ PORT_DIPSETTING( 0x02, "20ms/2ms")
+ PORT_DIPNAME( 0x04, 0x00, "DSK3 head step time" )
+ PORT_DIPSETTING( 0x00, "6ms")
+ PORT_DIPSETTING( 0x04, "20ms/2ms")
+ PORT_DIPNAME( 0x08, 0x00, "DSK4 head step time" )
+ PORT_DIPSETTING( 0x00, "6ms")
+ PORT_DIPSETTING( 0x08, "20ms/2ms")
+
+ PORT_START( "AMADECODE" )
+ PORT_CONFNAME( 0x01, 0x01, "Decode AMA/AMB/AMC lines" )
+ PORT_CONFSETTING( 0x00, DEF_STR( Off ))
+ PORT_CONFSETTING( 0x01, DEF_STR( On ))
+INPUT_PORTS_END
+
+
+ROM_START( myarc_ddcc )
+ ROM_REGION(0x2000, TI99_DSRROM, 0)
+ ROM_LOAD("ddcc1.u3", 0x0000, 0x2000, CRC(042968a9) SHA1(17af3130d3631b1bc1aa4d7e32a1b1feb66bbfb6))
+ROM_END
+
+void myarc_fdc_device::device_add_mconfig(machine_config& config)
+{
+ // Cards appeared with one of those controllers
+ WD1770(config, m_wd1770, 8_MHz_XTAL);
+ WD1772(config, m_wd1772, 8_MHz_XTAL);
+
+ m_wd1770->intrq_wr_callback().set(FUNC(myarc_fdc_device::fdc_irq_w));
+ m_wd1770->drq_wr_callback().set(FUNC(myarc_fdc_device::fdc_drq_w));
+ m_wd1770->mon_wr_callback().set(FUNC(myarc_fdc_device::fdc_mon_w));
+ m_wd1770->set_disable_motor_control(true);
+
+ m_wd1772->intrq_wr_callback().set(FUNC(myarc_fdc_device::fdc_irq_w));
+ m_wd1772->drq_wr_callback().set(FUNC(myarc_fdc_device::fdc_drq_w));
+ m_wd1772->mon_wr_callback().set(FUNC(myarc_fdc_device::fdc_mon_w));
+ m_wd1772->set_disable_motor_control(true);
+
+ LS259(config, m_drivelatch); // U10
+ m_drivelatch->q_out_cb<0>().set(FUNC(myarc_fdc_device::den_w));
+ m_drivelatch->q_out_cb<1>().set(FUNC(myarc_fdc_device::wdreset_w));
+ m_drivelatch->q_out_cb<2>().set(FUNC(myarc_fdc_device::sidsel_w));
+ m_drivelatch->q_out_cb<3>().set(FUNC(myarc_fdc_device::bankdden_w));
+ m_drivelatch->q_out_cb<4>().set(FUNC(myarc_fdc_device::drivesel_w));
+ m_drivelatch->q_out_cb<5>().set(FUNC(myarc_fdc_device::drivesel_w));
+ m_drivelatch->q_out_cb<6>().set(FUNC(myarc_fdc_device::drivesel_w));
+ m_drivelatch->q_out_cb<7>().set(FUNC(myarc_fdc_device::drivesel_w));
+
+ // SRAM 6114 2Kx8
+ RAM(config, BUFFER_TAG).set_default_size("2k").set_default_value(0);
+
+ // PAL circuit
+ DDCC1_PAL(config, PAL_TAG, 0);
+
+ // Floppy drives
+ 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
+{
+ return INPUT_PORTS_NAME( myarc_ddcc );
+}
+
+const tiny_rom_entry *myarc_fdc_device::device_rom_region() const
+{
+ return ROM_NAME( myarc_ddcc );
+}
+
+// ========================================================================
+// PAL circuit on the DDCC-1 board
+// ========================================================================
+
+ddcc1_pal_device::ddcc1_pal_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
+ : device_t(mconfig, DDCC1_PAL, tag, owner, clock),
+ m_board(nullptr)
+{
+}
+
+bool ddcc1_pal_device::ramsel()
+{
+ return (((m_board->get_address() & 0xf800)==0x5000) && (m_board->card_selected()));
+}
+
+bool ddcc1_pal_device::romen()
+{
+ return (((m_board->get_address() & 0xf000)==0x4000) && (m_board->card_selected()));
+}
+
+bool ddcc1_pal_device::fdcsel()
+{
+ // The memory mapping of the DDCC-1 differs from the usual scheme, using
+ // addresses 5F01, 5F03, 5F05, 5F07
+ return (((m_board->get_address() & 0xff01)==0x5f01) && (m_board->card_selected()));
+}
+
+bool ddcc1_pal_device::cs251()
+{
+ return ((m_board->get_address() & 0xff00)==0x1100);
+}
+
+bool ddcc1_pal_device::cs259()
+{
+ return ((m_board->get_address() & 0xff00)==0x1100);
+}
+
+} // end namespace bus::ti99::peb
diff --git a/src/devices/bus/ti99/peb/myarcfdc.h b/src/devices/bus/ti99/peb/myarcfdc.h
new file mode 100644
index 00000000000..aa5917f02b2
--- /dev/null
+++ b/src/devices/bus/ti99/peb/myarcfdc.h
@@ -0,0 +1,137 @@
+// license:LGPL-2.1+
+// copyright-holders:Michael Zapf
+/****************************************************************************
+
+ Myarc Disk Controller
+ Double Density, Double-sided
+
+ Michael Zapf, March 2020
+
+*****************************************************************************/
+
+#ifndef MAME_BUS_TI99_PEB_MYARCFDC_H
+#define MAME_BUS_TI99_PEB_MYARCFDC_H
+
+#pragma once
+
+#include "peribox.h"
+#include "imagedev/floppy.h"
+#include "machine/wd_fdc.h"
+#include "machine/74259.h"
+#include "machine/ram.h"
+
+namespace bus::ti99::peb {
+
+class ddcc1_pal_device;
+
+class myarc_fdc_device : public device_t, public device_ti99_peribox_card_interface
+{
+ friend class ddcc1_pal_device;
+
+public:
+ myarc_fdc_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
+
+ void readz(offs_t offset, uint8_t *value) override;
+ void write(offs_t offset, uint8_t data) override;
+ void setaddress_dbin(offs_t offset, int state) override;
+
+ void crureadz(offs_t offset, uint8_t *value) override;
+ void cruwrite(offs_t offset, uint8_t data) override;
+
+protected:
+ virtual void device_start() override ATTR_COLD;
+ virtual void device_reset() override ATTR_COLD;
+
+ virtual const tiny_rom_entry *device_rom_region() const override ATTR_COLD;
+ virtual void device_add_mconfig(machine_config &config) override ATTR_COLD;
+ virtual ioport_constructor device_input_ports() const override ATTR_COLD;
+
+private:
+ static void floppy_formats(format_registration &fr);
+
+ // Callback methods
+ void fdc_irq_w(int state);
+ void fdc_drq_w(int state);
+ void fdc_mon_w(int state);
+
+ 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();
+
+ // Polled from the PAL
+ bool card_selected();
+
+ // Link to the WD controller on the board.
+ wd_fdc_digital_device_base* m_wdc;
+
+ // Two options for the controller chip. Can be selected by the configuration switch.
+ required_device<wd1770_device> m_wd1770;
+ required_device<wd1772_device> m_wd1772;
+
+ // Latch
+ required_device<ls259_device> m_drivelatch;
+
+ // Buffer RAM
+ required_device<ram_device> m_buffer_ram;
+
+ // Decoder PAL
+ required_device<ddcc1_pal_device> m_pal;
+
+ // DSR ROM
+ uint8_t* m_dsrrom;
+
+ // Link to the attached floppy drives
+ required_device_array<floppy_connector, 4> m_floppy;
+
+ // Debugger accessors
+ void debug_read(offs_t offset, uint8_t* value);
+ void debug_write(offs_t offset, uint8_t data);
+
+ // Upper bank selected
+ bool m_banksel;
+
+ // Card enabled
+ bool m_cardsel;
+
+ // Selected drive
+ int m_selected_drive;
+
+ // Recent address
+ int m_address;
+
+ // AMA/B/C decoding active
+ bool m_dec_high;
+};
+
+// =========== 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);
+
+ // Selector output lines of the PAL
+ bool ramsel();
+ bool romen();
+ bool fdcsel();
+ bool cs251();
+ bool cs259();
+
+private:
+ void device_start() override { }
+ myarc_fdc_device* m_board;
+ void set_board(myarc_fdc_device* board) { m_board = board; }
+};
+
+} // end namespace bus::ti99::peb
+
+DECLARE_DEVICE_TYPE_NS(TI99_DDCC1, bus::ti99::peb, myarc_fdc_device)
+DECLARE_DEVICE_TYPE_NS(DDCC1_PAL, bus::ti99::peb, ddcc1_pal_device)
+
+#endif // MAME_BUS_TI99_PEB_MYARCFDC_H
diff --git a/src/devices/bus/ti99/peb/myarcmem.cpp b/src/devices/bus/ti99/peb/myarcmem.cpp
index 79add7a6c72..edee7601c80 100644
--- a/src/devices/bus/ti99/peb/myarcmem.cpp
+++ b/src/devices/bus/ti99/peb/myarcmem.cpp
@@ -30,9 +30,9 @@
#include "emu.h"
#include "myarcmem.h"
-DEFINE_DEVICE_TYPE_NS(TI99_MYARCMEM, bus::ti99::peb, myarc_memory_expansion_device, "ti99_myarcmem", "Myarc Memory expansion card MEXP-1")
+DEFINE_DEVICE_TYPE(TI99_MYARCMEM, bus::ti99::peb::myarc_memory_expansion_device, "ti99_myarcmem", "Myarc Memory expansion card MEXP-1")
-namespace bus { namespace ti99 { namespace peb {
+namespace bus::ti99::peb {
/* This card has two CRU bases where it answers. */
#define MYARCMEM_CRU_BASE1 0x1000
@@ -72,7 +72,7 @@ int myarc_memory_expansion_device::get_base(int offset)
RAM is at 2000-3fff, a000-ffff;
ROM is at 4000-5fff (if CRU bit 0 is set)
*/
-READ8Z_MEMBER(myarc_memory_expansion_device::readz)
+void myarc_memory_expansion_device::readz(offs_t offset, uint8_t *value)
{
int base = get_base(offset);
@@ -127,7 +127,7 @@ void myarc_memory_expansion_device::write(offs_t offset, uint8_t data)
/*
CRU read. None here.
*/
-READ8Z_MEMBER(myarc_memory_expansion_device::crureadz)
+void myarc_memory_expansion_device::crureadz(offs_t offset, uint8_t *value)
{
}
@@ -211,4 +211,4 @@ ioport_constructor myarc_memory_expansion_device::device_input_ports() const
return INPUT_PORTS_NAME(myarc_exp);
}
-} } } // end namespace bus::ti99::peb
+} // end namespace bus::ti99::peb
diff --git a/src/devices/bus/ti99/peb/myarcmem.h b/src/devices/bus/ti99/peb/myarcmem.h
index 175b8d60344..b7d9c864f65 100644
--- a/src/devices/bus/ti99/peb/myarcmem.h
+++ b/src/devices/bus/ti99/peb/myarcmem.h
@@ -18,24 +18,24 @@
#include "peribox.h"
#include "machine/ram.h"
-namespace bus { namespace ti99 { namespace peb {
+namespace bus::ti99::peb {
class myarc_memory_expansion_device : public device_t, public device_ti99_peribox_card_interface
{
public:
myarc_memory_expansion_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
- DECLARE_READ8Z_MEMBER(readz) override;
+ void readz(offs_t offset, uint8_t *value) override;
void write(offs_t offset, uint8_t data) override;
- DECLARE_READ8Z_MEMBER(crureadz) override;
+ void crureadz(offs_t offset, uint8_t *value) override;
void cruwrite(offs_t offset, uint8_t data) override;
protected:
- void device_start() override;
- void device_reset() override;
+ void device_start() override ATTR_COLD;
+ void device_reset() override ATTR_COLD;
const tiny_rom_entry *device_rom_region() const override;
ioport_constructor device_input_ports() const override;
- virtual void device_add_mconfig(machine_config &config) override;
+ virtual void device_add_mconfig(machine_config &config) override ATTR_COLD;
private:
int get_base(int offset);
@@ -45,7 +45,7 @@ private:
int m_size;
};
-} } } // end namespace bus::ti99::peb
+} // end namespace bus::ti99::peb
DECLARE_DEVICE_TYPE_NS(TI99_MYARCMEM, bus::ti99::peb, myarc_memory_expansion_device)
diff --git a/src/devices/bus/ti99/peb/pcode.cpp b/src/devices/bus/ti99/peb/pcode.cpp
index 9b711c6bfc6..75152d8e6bc 100644
--- a/src/devices/bus/ti99/peb/pcode.cpp
+++ b/src/devices/bus/ti99/peb/pcode.cpp
@@ -75,20 +75,20 @@
#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"
-DEFINE_DEVICE_TYPE_NS(TI99_P_CODE, bus::ti99::peb, ti_pcode_card_device, "ti99_pcode", "TI-99 P-Code Card")
+DEFINE_DEVICE_TYPE(TI99_P_CODE, bus::ti99::peb::ti_pcode_card_device, "ti99_pcode", "TI-99 P-Code Card")
-namespace bus { namespace ti99 { namespace peb {
+namespace bus::ti99::peb {
#define PCODE_GROM_TAG "pcode_grom"
#define PCODE_ROM_TAG "pcode_rom"
@@ -115,10 +115,10 @@ ti_pcode_card_device::ti_pcode_card_device(const machine_config &mconfig, const
{
}
-SETADDRESS_DBIN_MEMBER( ti_pcode_card_device::setaddress_dbin )
+void ti_pcode_card_device::setaddress_dbin(offs_t offset, int state)
{
m_address = offset;
- m_inDsrArea = ((m_address & m_select_mask)==m_select_value);
+ m_inDsrArea = in_dsr_space(offset, true);
line_state a14 = ((m_address & 2)!=0)? ASSERT_LINE : CLEAR_LINE;
@@ -142,25 +142,26 @@ SETADDRESS_DBIN_MEMBER( ti_pcode_card_device::setaddress_dbin )
}
}
-void ti_pcode_card_device::debugger_read(uint16_t offset, uint8_t& value)
+void ti_pcode_card_device::debugger_read(offs_t offset, uint8_t& value)
{
// The debuger does not call setaddress
- if (m_active && ((offset & m_select_mask)==m_select_value))
+ if (m_active && in_dsr_space(offset, true))
{
bool isrom0 = ((offset & 0xf000)==0x4000);
bool isrom12 = ((offset & 0xf000)==0x5000);
- if (isrom0) value = m_rom[m_address & 0x0fff];
+ if (isrom0) value = m_rom[offset & 0x0fff];
else
if (isrom12) value = m_rom[(m_bank_select<<12) | (offset & 0x0fff)];
}
}
-READ8Z_MEMBER( ti_pcode_card_device::readz )
+void ti_pcode_card_device::readz(offs_t offset, uint8_t *value)
{
// Care for debugger
if (machine().side_effects_disabled())
{
debugger_read(offset, *value);
+ return;
}
if (m_active && m_inDsrArea && m_selected)
@@ -213,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);
}
@@ -223,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)
@@ -240,7 +241,7 @@ WRITE_LINE_MEMBER( ti_pcode_card_device::clock_in)
we just ignore any request. (Note that CRU lines are not like memory; you
may be able to write to them, but not necessarily read them again.)
*/
-READ8Z_MEMBER(ti_pcode_card_device::crureadz)
+void ti_pcode_card_device::crureadz(offs_t offset, uint8_t *value)
{
}
@@ -259,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);
@@ -287,16 +288,6 @@ void ti_pcode_card_device::device_start()
void ti_pcode_card_device::device_reset()
{
- if (m_genmod)
- {
- m_select_mask = 0x1fe000;
- m_select_value = 0x174000;
- }
- else
- {
- m_select_mask = 0x7e000;
- m_select_value = 0x74000;
- }
m_bank_select = 1;
m_selected = false;
m_clock_count = 0;
@@ -323,7 +314,7 @@ INPUT_CHANGED_MEMBER( ti_pcode_card_device::switch_changed )
INPUT_PORTS_START( ti99_pcode )
PORT_START( ACTIVE_TAG )
- PORT_DIPNAME( 0x01, 0x00, "P-Code activation switch" ) PORT_CHANGED_MEMBER(DEVICE_SELF, ti_pcode_card_device, switch_changed, 0)
+ PORT_DIPNAME( 0x01, 0x00, "P-Code activation switch" ) PORT_CHANGED_MEMBER(DEVICE_SELF, FUNC(ti_pcode_card_device::switch_changed), 0)
PORT_DIPSETTING( 0x00, DEF_STR( Off ) )
PORT_DIPSETTING( 0x01, DEF_STR( On ) )
INPUT_PORTS_END
@@ -366,4 +357,4 @@ ioport_constructor ti_pcode_card_device::device_input_ports() const
return INPUT_PORTS_NAME( ti99_pcode );
}
-} } } // end namespace bus::ti99::peb
+} // end namespace bus::ti99::peb
diff --git a/src/devices/bus/ti99/peb/pcode.h b/src/devices/bus/ti99/peb/pcode.h
index 5e7a2cb6ce0..700508df1a4 100644
--- a/src/devices/bus/ti99/peb/pcode.h
+++ b/src/devices/bus/ti99/peb/pcode.h
@@ -21,37 +21,37 @@
#include "machine/74259.h"
#include "machine/tmc0430.h"
-namespace bus { namespace ti99 { namespace peb {
+namespace bus::ti99::peb {
class ti_pcode_card_device : public device_t, public device_ti99_peribox_card_interface
{
public:
ti_pcode_card_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
- DECLARE_READ8Z_MEMBER(readz) override;
+ void readz(offs_t offset, uint8_t *value) override;
void write(offs_t offset, uint8_t data) override;
- DECLARE_READ8Z_MEMBER(crureadz) override;
+ void crureadz(offs_t offset, uint8_t *value) override;
void cruwrite(offs_t offset, uint8_t data) override;
- DECLARE_SETADDRESS_DBIN_MEMBER(setaddress_dbin) 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 );
protected:
- virtual void device_start() override;
- virtual void device_reset() override;
+ virtual void device_start() override ATTR_COLD;
+ virtual void device_reset() override ATTR_COLD;
virtual void device_config_complete() 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;
+ virtual const tiny_rom_entry *device_rom_region() const override ATTR_COLD;
+ virtual void device_add_mconfig(machine_config &config) override ATTR_COLD;
+ virtual ioport_constructor device_input_ports() const override ATTR_COLD;
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(uint16_t addr, uint8_t& value);
+ void debugger_read(offs_t addr, uint8_t& value);
required_device_array<tmc0430_device, 8> m_groms;
@@ -73,7 +73,7 @@ private:
int m_address;
};
-} } } // end namespace bus::ti99::peb
+} // end namespace bus::ti99::peb
DECLARE_DEVICE_TYPE_NS(TI99_P_CODE, bus::ti99::peb, ti_pcode_card_device)
diff --git a/src/devices/bus/ti99/peb/peribox.cpp b/src/devices/bus/ti99/peb/peribox.cpp
index b75a15a49ed..55de5eccc2c 100644
--- a/src/devices/bus/ti99/peb/peribox.cpp
+++ b/src/devices/bus/ti99/peb/peribox.cpp
@@ -182,6 +182,8 @@ CRUCLK* 51||52 DBIN
#include "ti_fdc.h"
#include "bwg.h"
#include "hfdc.h"
+#include "cc_fdc.h"
+#include "myarcfdc.h"
#include "pcode.h"
#include "myarcmem.h"
#include "samsmem.h"
@@ -190,40 +192,48 @@ CRUCLK* 51||52 DBIN
#include "evpc.h"
#include "hsgpl.h"
#include "ti_rs232.h"
-#include "spchsyn.h"
+#include "speechadapter.h"
#include "memex.h"
#include "horizon.h"
+#include "forti.h"
+#include "pgram.h"
+#include "sidmaster.h"
+#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"
// Peripheral box that is attached to the TI console (also TI with EVPC)
// and has the Flex Cable Interface in slot 1
// This is a device that plugs into the slot "ioport" of the console
-DEFINE_DEVICE_TYPE_NS(TI99_PERIBOX, bus::ti99::peb, peribox_device, "peribox", "Peripheral expansion box")
+DEFINE_DEVICE_TYPE(TI99_PERIBOX, bus::ti99::peb::peribox_device, "peribox", "Peripheral expansion box")
// Peripheral box which has a EVPC card in slot 2 (for use with the ti99_4ev)
-DEFINE_DEVICE_TYPE_NS(TI99_PERIBOX_EV, bus::ti99::peb, peribox_ev_device, "peribox_ev", "Peripheral expansion box with EVPC")
+DEFINE_DEVICE_TYPE(TI99_PERIBOX_EV, bus::ti99::peb::peribox_ev_device, "peribox_ev", "Peripheral expansion box with EVPC inserted")
+
+// Peripheral box with EVPC (for use with the ti99_4ev with the port splitter)
+DEFINE_DEVICE_TYPE(TI99_PERIBOX_EV1, bus::ti99::peb::peribox_ev1_device, "peribox_ev1", "Peripheral expansion box with EVPC")
// Peripheral box which hosts the SGCPU card in slot 1
-DEFINE_DEVICE_TYPE_NS(TI99_PERIBOX_SG, bus::ti99::peb, peribox_sg_device, "peribox_sg", "Peripheral expansion box SGCPU")
+DEFINE_DEVICE_TYPE(TI99_PERIBOX_SG, bus::ti99::peb::peribox_sg_device, "peribox_sg", "Peripheral expansion box SGCPU")
// Peripheral box which hosts the Geneve 9640 in slot 1
-DEFINE_DEVICE_TYPE_NS(TI99_PERIBOX_GEN, bus::ti99::peb, peribox_gen_device, "peribox_gen", "Peripheral expansion box Geneve")
+DEFINE_DEVICE_TYPE(TI99_PERIBOX_GEN, bus::ti99::peb::peribox_gen_device, "peribox_gen", "Peripheral expansion box Geneve")
// Peripheral box which hosts the Geneve 9640 in slot 1 with Genmod
-DEFINE_DEVICE_TYPE_NS(TI99_PERIBOX_GENMOD, bus::ti99::peb, peribox_genmod_device, "peribox_genmod", "Peripheral expansion box Genmod")
+DEFINE_DEVICE_TYPE(TI99_PERIBOX_GENMOD, bus::ti99::peb::peribox_genmod_device, "peribox_genmod", "Peripheral expansion box Genmod")
// Single slot of the PEB
-DEFINE_DEVICE_TYPE_NS(TI99_PERIBOX_SLOT, bus::ti99::peb, peribox_slot_device, "peribox_slot", "TI P-Box slot")
+DEFINE_DEVICE_TYPE(TI99_PERIBOX_SLOT, bus::ti99::peb::peribox_slot_device, "peribox_slot", "TI P-Box slot")
-namespace bus { namespace ti99 { namespace peb {
+namespace bus::ti99::peb {
#define PEBSLOT2 "slot2"
#define PEBSLOT3 "slot3"
@@ -264,11 +274,13 @@ peribox_device::peribox_device(const machine_config &mconfig, device_type type,
peribox_device::peribox_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
: peribox_device(mconfig, TI99_PERIBOX, tag, owner, clock)
{
+ // The address prefix represents a set of pull-up resistors for the
+ // additional address lines AMA, AMB, AMC. They are contained in the
+ // Flex Cable Interface.
m_address_prefix = 0x70000;
- m_genmod = false;
}
-READ8Z_MEMBER(peribox_device::readz)
+void peribox_device::readz(offs_t offset, uint8_t *value)
{
for (int i=2; i <= 8; i++)
{
@@ -284,7 +296,7 @@ void peribox_device::write(offs_t offset, uint8_t data)
}
}
-SETADDRESS_DBIN_MEMBER(peribox_device::setaddress_dbin)
+void peribox_device::setaddress_dbin(offs_t offset, int state)
{
// Ignore the address when the TI-99/8 transmits the high-order 8 bits
if (!m_memen) return;
@@ -295,7 +307,7 @@ SETADDRESS_DBIN_MEMBER(peribox_device::setaddress_dbin)
}
}
-READ8Z_MEMBER(peribox_device::crureadz)
+void peribox_device::crureadz(offs_t offset, uint8_t *value)
{
for (int i=2; i <= 8; i++)
{
@@ -312,10 +324,21 @@ void peribox_device::cruwrite(offs_t offset, uint8_t data)
}
/*
+ RESET line from the console.
+*/
+void peribox_device::reset_in(int state)
+{
+ for (int i=2; i <= 8; i++)
+ {
+ if (m_slot[i]!=nullptr) m_slot[i]->reset_in(state);
+ }
+}
+
+/*
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++)
{
@@ -323,7 +346,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++)
{
@@ -334,7 +357,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);
}
@@ -342,7 +365,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);
}
@@ -351,7 +374,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++)
{
@@ -428,19 +451,11 @@ void peribox_device::ready_join(int slot, int state)
void peribox_device::set_slot_loaded(int slot, peribox_slot_device* slotdev)
{
m_slot[slot] = slotdev;
- if (slotdev != nullptr)
- slotdev->set_genmod(m_genmod);
}
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++)
@@ -464,21 +479,52 @@ void peribox_device::device_config_complete()
m_ready_flag = 0;
}
-void ti99_peribox_slot_standard(device_slot_interface &device)
+// Slot options that work with TI-99/4A (with and without EVPC), SGCPU, Geneve,
+// and TI-99/8 (untested)
+void peribox_common_slots(device_slot_interface &device)
{
- device.option_add("32kmem", TI99_32KMEM);
- device.option_add("myarcmem", TI99_MYARCMEM);
- device.option_add("samsmem", TI99_SAMSMEM);
- device.option_add("pcode", TI99_P_CODE);
- device.option_add("hsgpl", TI99_HSGPL);
device.option_add("tirs232", TI99_RS232);
- device.option_add("speech", TI99_SPEECH);
+ device.option_add("speechadapter", TI99_SPEECHADAPTER);
device.option_add("horizon", TI99_HORIZON);
device.option_add("ide", TI99_IDE);
device.option_add("usbsm", TI99_USBSM);
- device.option_add("bwg", TI99_BWG);
device.option_add("hfdc", TI99_HFDC);
device.option_add("tifdc", TI99_FDC);
+ device.option_add("ccdcc", TI99_CCDCC);
+ device.option_add("ccfdc", TI99_CCFDC);
+ device.option_add("ddcc1", TI99_DDCC1);
+ device.option_add("forti", TI99_FORTI);
+ device.option_add("whtscsi", TI99_WHTSCSI);
+ device.option_add("tipi", TI99_TIPI);
+}
+
+// Slot options for TI-99/4A with or without EVPC and SGCPU
+// The BwG controller will not run with the Geneve due to its wait state
+// logic (see bwg.cpp)
+// The SID master card may have trouble with the Geneve because of its CRU
+// handling (see sidmaster.cpp)
+void peribox_ti99_slots(device_slot_interface &device)
+{
+ device.option_add("myarcmem", TI99_MYARCMEM);
+ device.option_add("samsmem", TI99_SAMSMEM);
+ device.option_add("pcode", TI99_P_CODE);
+ device.option_add("hsgpl", TI99_HSGPL);
+ device.option_add("bwg", TI99_BWG);
+ device.option_add("sidmaster", TI99_SIDMASTER);
+ peribox_common_slots(device);
+}
+
+// Geneve and SGCPU do not work with these memory expansions
+void peribox_std_slots(device_slot_interface &device)
+{
+ device.option_add("32kmem", TI99_32KMEM);
+ device.option_add("pgram", TI99_PGRAM);
+ peribox_ti99_slots(device);
+}
+
+void ti99_peribox_slot_standard(device_slot_interface &device)
+{
+ peribox_std_slots(device);
}
void peribox_device::device_add_mconfig(machine_config &config)
@@ -500,25 +546,12 @@ peribox_ev_device::peribox_ev_device(const machine_config &mconfig, const char *
: peribox_device(mconfig, TI99_PERIBOX_EV, tag, owner, clock)
{
m_address_prefix = 0x70000;
- m_genmod = false;
}
void ti99_peribox_slot_evpc(device_slot_interface &device)
{
- device.option_add("evpc", TI99_EVPC);
- device.option_add("32kmem", TI99_32KMEM);
- device.option_add("myarcmem", TI99_MYARCMEM);
- device.option_add("samsmem", TI99_SAMSMEM);
- device.option_add("pcode", TI99_P_CODE);
- device.option_add("hsgpl", TI99_HSGPL);
- device.option_add("tirs232", TI99_RS232);
- device.option_add("speech", TI99_SPEECH);
- device.option_add("horizon", TI99_HORIZON);
- device.option_add("ide", TI99_IDE);
- device.option_add("usbsm", TI99_USBSM);
- device.option_add("bwg", TI99_BWG);
- device.option_add("hfdc", TI99_HFDC);
- device.option_add("tifdc", TI99_FDC);
+ device.option_add("evpc", TI99_EVPC);
+ peribox_std_slots(device);
}
void peribox_ev_device::device_add_mconfig(machine_config &config)
@@ -533,6 +566,28 @@ void peribox_ev_device::device_add_mconfig(machine_config &config)
}
/****************************************************************************
+ A variant of the box used for the TI-99/4A with EVPC, not inserted
+*****************************************************************************/
+
+peribox_ev1_device::peribox_ev1_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
+ : peribox_device(mconfig, TI99_PERIBOX_EV1, tag, owner, clock)
+{
+ m_address_prefix = 0x70000;
+}
+
+void peribox_ev1_device::device_add_mconfig(machine_config &config)
+{
+ TI99_PERIBOX_SLOT(config, m_slot2, 2, ti99_peribox_slot_evpc, nullptr);
+ TI99_PERIBOX_SLOT(config, m_slot3, 3, ti99_peribox_slot_evpc, nullptr);
+ TI99_PERIBOX_SLOT(config, m_slot4, 4, ti99_peribox_slot_evpc, nullptr);
+ TI99_PERIBOX_SLOT(config, m_slot5, 5, ti99_peribox_slot_evpc, nullptr);
+ TI99_PERIBOX_SLOT(config, m_slot6, 6, ti99_peribox_slot_evpc, nullptr);
+ TI99_PERIBOX_SLOT(config, m_slot7, 7, ti99_peribox_slot_evpc, nullptr);
+ TI99_PERIBOX_SLOT(config, m_slot8, 8, ti99_peribox_slot_evpc, nullptr);
+}
+
+
+/****************************************************************************
A variant of the box used for the Geneve.
*****************************************************************************/
@@ -548,28 +603,18 @@ peribox_gen_device::peribox_gen_device(const machine_config &mconfig, device_typ
peribox_gen_device::peribox_gen_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
: peribox_gen_device(mconfig, TI99_PERIBOX_GEN, tag, owner, clock)
{
- m_genmod = false;
}
peribox_genmod_device::peribox_genmod_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
: peribox_gen_device(mconfig, TI99_PERIBOX_GENMOD, tag, owner, clock)
{
- m_genmod = true;
}
-// The BwG controller will not run with the Geneve due to its wait state
-// logic (see bwg.c)
-
+// All common slot options plus Memex.
void ti99_peribox_slot_geneve(device_slot_interface &device)
{
- device.option_add("memex", TI99_MEMEX);
- device.option_add("tirs232", TI99_RS232);
- device.option_add("speech", TI99_SPEECH);
- device.option_add("horizon", TI99_HORIZON);
- device.option_add("ide", TI99_IDE);
- device.option_add("usbsm", TI99_USBSM);
- device.option_add("hfdc", TI99_HFDC);
- device.option_add("tifdc", TI99_FDC);
+ device.option_add("memex", TI99_MEMEX);
+ peribox_common_slots(device);
}
void peribox_gen_device::device_add_mconfig(machine_config &config)
@@ -601,25 +646,15 @@ void peribox_genmod_device::device_add_mconfig(machine_config &config)
peribox_sg_device::peribox_sg_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
: peribox_device(mconfig, TI99_PERIBOX_SG, tag, owner, clock)
{
+ // The SGCPU card contains pull-up registers for the AMA/AMB/AMC lines
+ // like the Flex Cable Interface
m_address_prefix = 0x70000;
- m_genmod = false;
}
void ti99_peribox_slot_sgcpu(device_slot_interface &device)
{
- device.option_add("evpc", TI99_EVPC);
- device.option_add("myarcmem", TI99_MYARCMEM);
- device.option_add("samsmem", TI99_SAMSMEM);
- device.option_add("pcode", TI99_P_CODE);
- device.option_add("hsgpl", TI99_HSGPL);
- device.option_add("tirs232", TI99_RS232);
- device.option_add("speech", TI99_SPEECH);
- device.option_add("horizon", TI99_HORIZON);
- device.option_add("ide", TI99_IDE);
- device.option_add("usbsm", TI99_USBSM);
- device.option_add("bwg", TI99_BWG);
- device.option_add("hfdc", TI99_HFDC);
- device.option_add("tifdc", TI99_FDC);
+ device.option_add("evpc", TI99_EVPC);
+ peribox_ti99_slots(device);
}
void peribox_sg_device::device_add_mconfig(machine_config &config)
@@ -639,13 +674,14 @@ void peribox_sg_device::device_add_mconfig(machine_config &config)
peribox_slot_device::peribox_slot_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) :
device_t(mconfig, TI99_PERIBOX_SLOT, tag, owner, clock),
- device_slot_interface(mconfig, *this),
+ device_single_card_slot_interface<device_ti99_peribox_card_interface>(mconfig, *this),
m_card(nullptr),
+ m_peb(nullptr),
m_slotnumber(0)
{
}
-READ8Z_MEMBER(peribox_slot_device::readz)
+void peribox_slot_device::readz(offs_t offset, uint8_t *value)
{
m_card->readz(offset, value);
}
@@ -655,12 +691,12 @@ void peribox_slot_device::write(offs_t offset, uint8_t data)
m_card->write(offset, data);
}
-SETADDRESS_DBIN_MEMBER(peribox_slot_device::setaddress_dbin)
+void peribox_slot_device::setaddress_dbin(offs_t offset, int state)
{
m_card->setaddress_dbin(offset, state);
}
-READ8Z_MEMBER(peribox_slot_device::crureadz)
+void peribox_slot_device::crureadz(offs_t offset, uint8_t *value)
{
m_card->crureadz(offset, value);
}
@@ -670,27 +706,24 @@ 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);
}
-/*
- Genmod support
-*/
-void peribox_slot_device::set_genmod(bool set)
+void peribox_slot_device::reset_in(int state)
{
- m_card->m_genmod = set;
+ m_card->reset_in(state);
}
void peribox_slot_device::device_start()
@@ -699,52 +732,49 @@ void peribox_slot_device::device_start()
void peribox_slot_device::device_config_complete()
{
- m_card = dynamic_cast<device_ti99_peribox_card_interface *>(get_card_device());
- peribox_device *peb = dynamic_cast<peribox_device*>(owner());
- if (peb)
- peb->set_slot_loaded(m_slotnumber, m_card ? this : nullptr);
+ m_card = get_card_device();
+ 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);
}
/***************************************************************************/
device_ti99_peribox_card_interface::device_ti99_peribox_card_interface(const machine_config &mconfig, device_t &device):
- device_slot_card_interface(mconfig, device),
+ device_interface(device, "ti99peb"),
m_selected(false),
- m_cru_base(0),
- m_select_mask(0),
- m_select_value(0)
+ m_cru_base(0)
{
m_senila = CLEAR_LINE;
m_senilb = CLEAR_LINE;
- m_genmod = false;
}
void device_ti99_peribox_card_interface::interface_config_complete()
@@ -752,4 +782,20 @@ void device_ti99_peribox_card_interface::interface_config_complete()
m_slot = dynamic_cast<peribox_slot_device*>(device().owner());
}
-} } } // end namespace bus::ti99::peb
+bool device_ti99_peribox_card_interface::in_dsr_space(offs_t offset, bool amadec)
+{
+ if (amadec && !amabc_is_set(offset)) return false;
+ return (offset & 0x0e000)==0x04000;
+}
+
+/*
+ Some cards do not decode the additional address lines AMA, AMB, AMC.
+ This leads to errors when using the card with Genmod. The typical procedure
+ to decode the lines is the same for each card.
+*/
+bool device_ti99_peribox_card_interface::amabc_is_set(offs_t offset)
+{
+ return (((offset >> 16)&0x07)==0x07);
+}
+
+} // end namespace bus::ti99::peb
diff --git a/src/devices/bus/ti99/peb/peribox.h b/src/devices/bus/ti99/peb/peribox.h
index 405ded3338e..7d9c0b6f9e9 100644
--- a/src/devices/bus/ti99/peb/peribox.h
+++ b/src/devices/bus/ti99/peb/peribox.h
@@ -3,7 +3,7 @@
/****************************************************************************
Peripheral expansion box
- See peribox.c for documentation
+ See peribox.cpp for documentation
Michael Zapf
@@ -16,10 +16,12 @@
#pragma once
-#include "bus/ti99/ti99defs.h"
#include "bus/ti99/internal/ioport.h"
-namespace bus { namespace ti99 { namespace peb {
+#define TI_PERIBOX_TAG "peb"
+#define TI99_DSRROM "dsrrom"
+
+namespace bus::ti99::peb {
class peribox_slot_device;
class device_ti99_peribox_card_interface;
@@ -35,20 +37,21 @@ public:
peribox_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
// Next eight methods are called from the console
- DECLARE_READ8Z_MEMBER(readz) override;
+ void readz(offs_t offset, uint8_t *value) override;
void write(offs_t offset, uint8_t data) override;
- DECLARE_SETADDRESS_DBIN_MEMBER(setaddress_dbin) override;
+ void setaddress_dbin(offs_t offset, int state) override;
- DECLARE_READ8Z_MEMBER(crureadz) override;
+ 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;
+ void clock_in(int state) override;
+ void reset_in(int state) override;
// Part of configuration
void set_prefix(int prefix) { m_address_prefix = prefix; }
@@ -62,10 +65,10 @@ public:
protected:
peribox_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_start() override ATTR_COLD;
virtual void device_config_complete() override;
- virtual void device_add_mconfig(machine_config &config) override;
+ virtual void device_add_mconfig(machine_config &config) override ATTR_COLD;
// Next three methods call back the console via slot 1
devcb_write_line m_slot1_inta; // INTA line (Box to console)
@@ -107,9 +110,6 @@ protected:
// Configured as a slot device (of the ioport)
bool m_ioport_connected;
-
- // Used for Genmod
- bool m_genmod;
};
/************************************************************************
@@ -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 ATTR_COLD;
};
/*
@@ -137,7 +137,19 @@ 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 ATTR_COLD;
+};
+
+/*
+ Variation for ti99_4ev without EVPC inserted
+*/
+class peribox_ev1_device : public peribox_device
+{
+public:
+ peribox_ev1_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
+
+protected:
+ virtual void device_add_mconfig(machine_config &config) override ATTR_COLD;
};
@@ -151,7 +163,7 @@ public:
protected:
peribox_gen_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_add_mconfig(machine_config &config) override ATTR_COLD;
};
/*
@@ -163,30 +175,31 @@ 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 ATTR_COLD;
};
/*****************************************************************************
The parent class for all expansion cards.
******************************************************************************/
-class device_ti99_peribox_card_interface : public device_slot_card_interface
+class device_ti99_peribox_card_interface : public device_interface
{
friend class peribox_slot_device;
public:
- virtual DECLARE_READ8Z_MEMBER(readz) = 0;
+ virtual void readz(offs_t offset, uint8_t *value) = 0;
virtual void write(offs_t offset, uint8_t data) = 0;
- virtual DECLARE_READ8Z_MEMBER(crureadz) = 0;
+ virtual void crureadz(offs_t offset, uint8_t *value) = 0;
virtual void cruwrite(offs_t offset, uint8_t data) = 0;
- virtual DECLARE_SETADDRESS_DBIN_MEMBER(setaddress_dbin) { };
+ virtual void setaddress_dbin(offs_t offset, int state) { }
+
+ virtual void clock_in(int state) { }
+ virtual void reset_in(int state) { }
- virtual DECLARE_WRITE_LINE_MEMBER(clock_in) { }
void set_senila(int state) { m_senila = state; }
void set_senilb(int state) { m_senilb = state; }
protected:
- using device_slot_card_interface::device_slot_card_interface;
device_ti99_peribox_card_interface(const machine_config &mconfig, device_t &device);
virtual void interface_config_complete() override;
@@ -197,22 +210,20 @@ protected:
// When true, card is accessible. Indicated by a LED.
bool m_selected;
- // When true, GenMod is selected. Modified by peribox_slot_device.
- bool m_genmod;
-
// CRU base. Used to configure the address by which a card is selected.
int m_cru_base;
- // Used to decide whether this card has been selected.
- int m_select_mask;
- int m_select_value;
+ // Methods to decide whether we are acccessing the 4000-5fff region (DSR)
+ bool in_dsr_space(offs_t offset, bool amadec);
+
+ bool amabc_is_set(offs_t offset);
};
/*****************************************************************************
A single slot in the box.
******************************************************************************/
-class peribox_slot_device : public device_t, public device_slot_interface
+class peribox_slot_device : public device_t, public device_single_card_slot_interface<device_ti99_peribox_card_interface>
{
friend class peribox_device;
public:
@@ -230,42 +241,44 @@ public:
peribox_slot_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
// Called from the box (direction to card)
- DECLARE_READ8Z_MEMBER(readz);
+ void readz(offs_t offset, uint8_t *value);
void write(offs_t offset, uint8_t data);
- DECLARE_SETADDRESS_DBIN_MEMBER(setaddress_dbin);
+ void setaddress_dbin(offs_t offset, int state);
- DECLARE_WRITE_LINE_MEMBER(senila);
- DECLARE_WRITE_LINE_MEMBER(senilb);
- DECLARE_WRITE_LINE_MEMBER(clock_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);
- DECLARE_READ8Z_MEMBER(crureadz);
+ void crureadz(offs_t offset, uint8_t *value);
void cruwrite(offs_t offset, uint8_t data);
// called from the box itself
- void set_genmod(bool set);
void set_number(int number) { m_slotnumber = number; }
protected:
- void device_start() override;
- void device_config_complete() override;
+ virtual void device_start() override ATTR_COLD;
+ 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(); }
};
-} } } // end namespace bus::ti99::peb
+} // end namespace bus::ti99::peb
DECLARE_DEVICE_TYPE_NS(TI99_PERIBOX, bus::ti99::peb, peribox_device)
DECLARE_DEVICE_TYPE_NS(TI99_PERIBOX_EV, bus::ti99::peb, peribox_ev_device)
+DECLARE_DEVICE_TYPE_NS(TI99_PERIBOX_EV1, bus::ti99::peb, peribox_ev1_device)
DECLARE_DEVICE_TYPE_NS(TI99_PERIBOX_SLOT, bus::ti99::peb, peribox_slot_device)
DECLARE_DEVICE_TYPE_NS(TI99_PERIBOX_SG, bus::ti99::peb, peribox_sg_device)
DECLARE_DEVICE_TYPE_NS(TI99_PERIBOX_GEN, bus::ti99::peb, peribox_gen_device)
diff --git a/src/devices/bus/ti99/peb/pgram.cpp b/src/devices/bus/ti99/peb/pgram.cpp
new file mode 100644
index 00000000000..5420e2c305b
--- /dev/null
+++ b/src/devices/bus/ti99/peb/pgram.cpp
@@ -0,0 +1,564 @@
+// license:LGPL-2.1+
+// copyright-holders:Michael Zapf
+/*******************************************************************************
+ PGRAM(+) Memory expansion and GROM simulator
+
+ The PGRAM card is a battery-buffered RAM card. It also contains a circuitry
+ to simulate GROMs (TMC0430), which can also be programmed, thus better
+ called GRAMs.
+
+ Memory chips of the board:
+
+ u21: 43256LP (SRAM 32Kx8) -- GROMs 4-7
+ u22: 6264LP (SRAM 8Kx8) -- GROM 3
+ u23: 43256LP (SRAM 32Kx8) -- 16 KiB DSR (driver) / 16 KiB RAM
+
+ The PGRAM+ is an extension of this card, offering 192 KiB memory:
+
+ u21: e.g. BS62LV1027 (SRAM 128Kx8) -- GROMs 4-7 (4 banks)
+ u22: 43256LP (SRAM 32Kx8) -- GROM 3 (4 banks)
+ u23: 43256LP (SRAM 32Kx8) -- 16 KiB DSR (driver) / 16 KiB RAM
+
+ The socket for u21 is already prepared for the larger package of the
+ 128Kx8 SRAM chip (32 pins). No modifications are needed; the smaller chip
+ can simply be plugged into the larger socket. For u22, a jumper is included
+ on the board for connecting the address line to the bus (PGRAM+)
+ or to high level (PGRAM).
+
+ A real-time clock is also included on the board:
+ u1: MM58167A
+
+ The GROM address counter is implemented by four 74LS161 chips.
+
+ A 3V battery is used to buffer the SRAMs.
+
+ The 74LS259 latch (u14) stores CRU settings and controls select lines.
+
+ Memory/port mapping
+ -------------------
+ The card can be configured to respond to CRU addresses 1000-1700 with the
+ exception of 1100, which is used by most disk controller cards. The
+ address is set by one of seven switches (SW1).
+
+ CRU bits (relative to start address):
+
+ 0 - Map DSR into CPU space 4000-5FFF
+ 1 - Enable GRAM and RAM
+ 2 - Write protect GRAM/RAM
+ 3 - DSR/RAM bank selection
+ 4 - DSR/RAM bank selection (see below)
+
+ The GRAM simulation responds to the usual GROM address base 9800. However,
+ only GROMs 3-7 are simulated; GROMs 0-2 are located in the console. Setting
+ the GROM address is done by writing both bytes of the 16-bit address to
+ address 9C02 (high/low). Reading the address is not possible, but this is
+ provided by the console GROMs. Reading the contents of the GRAM simulation
+ is done by reading a byte from address 9800, which also advances the address
+ counter. Writing to the GRAM is achieved by writing to address 9C00.
+
+ For the PGRAM+ card, four GROM banks are available:
+ Bank 0: 98x0/9Cx0/9Cx2
+ Bank 1: 98x4/9Cx4/9Cx4
+ Bank 2: 98x8/9Cx8/9Cx8
+ Bank 3: 98xC/9CxC/9CxC
+
+ Due to incomplete decoding, the second digit from the right may take any
+ value.
+
+ The real-time clock is mapped to addresses 8640-865E (even addresses only).
+ 8640 = Register 0
+ 865e = Register 15
+
+ The 32K RAM circuit (u23) is used for the DSR (device service routine, i.e.
+ the driver) and 16 KiB RAM. The DSR area is located in the lower half of the
+ address space, while the RAM area is located in the upper half.
+
+ The DSR area is mapped as two selectable 8K blocks into 4000-5FFF.
+ The RAM area is mapped as two selectable 8K blocks into 6000-7FFF.
+
+ +------------+ 0000
+ | DSR bank 0 |
+ +------------+ 2000
+ | DSR bank 1 |
+ +------------+ 4000
+ | RAM bank 0 |
+ +------------+ 6000
+ | RAM bank 1 |
+ +------------+ 7FFF
+
+ The selection of either bank of the DSR space is done by writing a value
+ to an address of 4000/4004/4008... for selecting bank 0, and to 4002/4006/...
+ for selecting bank 1. For the RAM area, the same scheme is applied to
+ 6000/6004/... and 6002/6006/... The selection is buffered by the flipflop
+ u3 for both RAM and DSR, hence it should make no difference whether to
+ write to 6000 or to 4000.
+
+ CRU bits 3 and 4 are fed into the PRE* and CLR* inputs of the flipflop.
+
+ Bits 3 4
+ 0 0 -> not recommended (typically, bit 4 wins)
+ 0 1 -> set lower 8K
+ 1 0 -> set higher 8K
+ 1 1 -> allow switching by write access
+
+ The PGRAM+ card does not allow for expanding this area. This is indeed a
+ limitation, as it does not allow us to store several cartridges with
+ a GROM and ROM part into the PGRAM+.
+
+ Switch SW2 deactivates the card in case the contents prevent a proper
+ startup of the TI console.
+
+ Michael Zapf
+ March 2020
+
+*******************************************************************************/
+
+#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)
+
+#include "logmacro.h"
+
+#define GRAM4567_TAG "u21_gram4567"
+#define GRAM3_TAG "u22_gram3"
+#define DSRRAM_TAG "u23_dsrram"
+#define CLOCK_TAG "u1_rtc"
+#define BANKFF_TAG "u3_bankff"
+#define CRULATCH_TAG "u14_latch"
+
+#define COUNT0_TAG "u13_counter"
+#define COUNT1_TAG "u11_counter"
+#define COUNT2_TAG "u12_counter"
+#define COUNT3_TAG "u10_counter"
+
+DEFINE_DEVICE_TYPE(TI99_PGRAM, bus::ti99::peb::pgram_device, "ti99_pgram", "PGRAM(+) memory card")
+
+namespace bus::ti99::peb {
+
+pgram_device::pgram_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock):
+ device_t(mconfig, TI99_PGRAM, tag, owner, clock),
+ device_ti99_peribox_card_interface(mconfig, *this),
+ m_gram3(*this, GRAM3_TAG),
+ m_gram4567(*this, GRAM4567_TAG),
+ m_dsrram(*this, DSRRAM_TAG),
+ m_clock(*this, CLOCK_TAG),
+ m_crulatch(*this, CRULATCH_TAG),
+ m_bankff(*this, BANKFF_TAG),
+ m_count0(*this, COUNT0_TAG),
+ m_count1(*this, COUNT1_TAG),
+ m_count2(*this, COUNT2_TAG),
+ m_count3(*this, COUNT3_TAG),
+ m_lowbyte(false)
+{
+}
+
+/*
+ Read access to the card. This comprises reading from the RAM circuit for
+ DSR and free space, for GRAM reading, and the real-time clock.
+
+ Decoding is done by the 74ls138 and 74ls139 circuits on the board.
+*/
+void pgram_device::readz(offs_t offset, uint8_t *value)
+{
+ if (!m_active) return;
+
+ // GROMs: 1001 1w.. .... ..00
+ if ((offset & 0xfc03)==0x9800)
+ {
+ gram_read((offset>>2)&0x03, value);
+ }
+ else
+ {
+ // DSR/RAM: 01.
+ if ((offset & 0xc000)==0x4000)
+ {
+ dsr_ram_read(offset & 0x3fff, value);
+ }
+ else
+ {
+ // RTC: 1000 0110 01.. ...0
+ if ((offset & 0xffc1)==0x8640)
+ {
+ uint8_t val = m_clock->read((offset >> 1) & 0x001f);
+ *value = val;
+ }
+ }
+ }
+}
+
+/*
+ Write access to the card. Same comments apply as for the read access.
+*/
+void pgram_device::write(offs_t offset, uint8_t data)
+{
+ if (!m_active) return;
+
+ // GROMs: 1001 11.. .... ..a0
+ if ((offset & 0xfc01)==0x9c00)
+ {
+ if ((offset & 0x0002)!=0)
+ set_gram_address(data);
+ else
+ gram_write((offset>>2)&0x03, data);
+ }
+ else
+ {
+ // DSR/RAM: 01.
+ if ((offset & 0xc000)==0x4000)
+ dsr_ram_write(offset & 0x3fff, data);
+ else
+ {
+ // RTC: 1000 0110 01.. ...0
+ if ((offset & 0xffc1)==0x8640)
+ m_clock->write((offset >> 1) & 0x001f, data);
+ }
+ }
+}
+
+/*
+ Read access to the 32K RAM circuit (u23). This one is used to provide the
+ DSR (driver) in the memory area 4000-5fff, and to provide free space in the
+ area 6000-7fff. A second bank can be selected for both DSR and RAM using
+ CRU bits 3 and 4.
+*/
+void pgram_device::dsr_ram_read(offs_t offset, uint8_t *value)
+{
+ // ..0. .... .... .... = DSR
+ // ..1. .... .... .... = RAM
+ bool dsr = ((offset & 0x2000)==0);
+
+ // Note: On power-up, the ls259 latch is reset, and bits 4 and 3 lead 0
+ // to both PRE* and CLR* of the 7474. This would normally cause the bank
+ // select line to be 1 (unstable).
+
+ // Reset the clock
+ m_bankff->clock_w(1);
+
+ // Latch may have changed; update FF asynchronously
+ m_bankff->clear_w(m_crulatch->q3_r());
+ m_bankff->preset_w(m_crulatch->q4_r());
+
+ offs_t base = (offset & 0x2000)<<1; // DSR:0000, RAM:4000
+ offs_t address = base | (offset & 0x1fff) | (m_bankff->output_r()? 0x2000 : 0);
+
+ if ((dsr && m_crulatch->q0_r()) || (!dsr && m_crulatch->q1_r()))
+ {
+ *value = m_dsrram->read(address);
+
+ if (address&1)
+ {
+ uint16_t b0 = m_dsrram->read(address&0xfffe) << 8 | *value;
+
+ if (dsr)
+ LOGMASKED(LOG_DSR, "%04x (bank %d) -> %04x\n",(offset&0xfffe)|0x4000, m_bankff->output_r()? 1:0, b0);
+ else
+ LOGMASKED(LOG_RAM, "%04x (bank %d) -> %04x\n",(offset&0xfffe)|0x4000, m_bankff->output_r()? 1:0, b0);
+ }
+ }
+}
+
+/*
+ Write access to the 32K RAM circuit (u23). See above for information about
+ the DSR and RAM space.
+ A flipflop (7474) is used to control access to the banks of both DSR and
+ RAM. The state of the flipflop is controlled by CRU bits 3 and 4. When both
+ bits are set, the flipflop can be set or reset by address line 14 (2^1).
+*/
+void pgram_device::dsr_ram_write(offs_t offset, uint8_t data)
+{
+ // ..0. .... .... .... = DSR
+ // ..1. .... .... .... = RAM
+ bool dsr = ((offset & 0x2000)==0);
+
+ if ((dsr && m_crulatch->q0_r()) || (!dsr && m_crulatch->q1_r()))
+ {
+ // Get the current settings of the flipflop from the latch
+ m_bankff->clear_w(m_crulatch->q3_r());
+ m_bankff->preset_w(m_crulatch->q4_r());
+
+ int oldff = m_bankff->output_r();
+
+ // A14 is led to the flipflop D input
+ m_bankff->d_w((offset & 2)>>1); // A14
+ m_bankff->clock_w(0);
+
+ if (m_crulatch->q2_r()==0) // not write-protected
+ {
+ offs_t base = (offset & 0x2000)<<1;
+ offs_t address = base | (offset & 0x1fff) | (m_bankff->output_r()? 0x2000 : 0);
+
+ m_dsrram->write(address, data);
+ if (base==0)
+ LOGMASKED(LOG_DSR, "%04x (bank %d) <- %02x\n", offset|0x4000, m_bankff->output_r()? 1:0, data);
+ else
+ LOGMASKED(LOG_RAM, "%04x (bank %d) <- %02x\n", offset|0x4000, m_bankff->output_r()? 1:0, data);
+ }
+
+ m_bankff->clock_w(1);
+ if (m_bankff->output_r() != oldff)
+ LOGMASKED(LOG_BANK, "Switch to bank %d (%04x)\n", m_bankff->output_r(), offset|0x4000);
+ }
+}
+
+/*
+ Read access to the GRAM emulation. The GRAM space is split between
+ two memory circuits, one for G3 (8K) and one for the other four GRAMs (32K).
+ For PGRAM+, we habe 32K + 128K (four banks).
+ When the GROM address is outside the area for G3-G7, the access is ignored.
+ GRAM access requires setting CRU bit 1 before.
+*/
+void pgram_device::gram_read(offs_t offset, uint8_t *value)
+{
+ // Don't let the debugger mess with the GRAM emulation
+ if (machine().side_effects_disabled())
+ {
+ *value = 0;
+ return;
+ }
+
+ if (m_crulatch->q1_r())
+ {
+ // Reset the clock
+ m_bankff->clock_w(1);
+
+ clock_gram_counter(0);
+ uint16_t gaddress = get_gram_address();
+
+ // GROM3: 011. .... .... ....
+ // Checked by u9
+ if ((gaddress & 0xe000)==0x6000)
+ {
+ offs_t gfull = (gaddress & 0x1fff) | (m_pgramplus? (offset << 13) : 0);
+ *value = m_gram3->read(gfull);
+ LOGMASKED(LOG_GRAM, "gram(%04x,%04x) -> %02x\n", gaddress, gfull, *value);
+ }
+
+ // GROM4-7: 1... .... .... ....
+ // Checked by u9 + u8
+ if ((gaddress & 0x8000)!=0)
+ {
+ offs_t gfull = (gaddress & 0x7fff) | (m_pgramplus? (offset << 15) : 0);
+ *value = m_gram4567->read(gfull);
+ LOGMASKED(LOG_GRAM, "gram(%04x,%05x) -> %02x\n", gaddress, gfull, *value);
+ }
+ clock_gram_counter(1);
+ }
+}
+
+/*
+ Write access to the GRAM emulation. Same comments apply as for gram_read.
+*/
+void pgram_device::gram_write(offs_t offset, uint8_t data)
+{
+ // Don't let the debugger mess with the GRAM emulation
+ if (machine().side_effects_disabled())
+ {
+ return;
+ }
+
+ if (m_crulatch->q1_r())
+ {
+ clock_gram_counter(0);
+ uint16_t gaddress = get_gram_address();
+
+ // GROM3: 011. .... .... ....
+ if ((gaddress & 0xe000)==0x6000)
+ {
+ offs_t gfull = (gaddress & 0x1fff) | (m_pgramplus? (offset << 13) : 0);
+ m_gram3->write(gfull, data);
+ LOGMASKED(LOG_GRAM, "gram(%04x,%04x) <- %02x\n", gaddress, gfull, data);
+ }
+
+ // GROM4-7: 1... .... .... ....
+ if ((gaddress & 0x8000)!=0)
+ {
+ offs_t gfull = (gaddress & 0x7fff) | (m_pgramplus? (offset << 15) : 0);
+ m_gram4567->write(gfull, data);
+ LOGMASKED(LOG_GRAM, "gram(%04x,%05x) <- %02x\n", gaddress, gfull, data);
+ }
+ clock_gram_counter(1);
+ }
+}
+
+/*
+ Set the address digits in the counters. Address setting is done by two
+ consecutive byte writes, where the currently stored digits in u13 and u11
+ are transferred to u12 and u10, and u13 and u11 get their new values
+ from the data bus.
+
+ D0-D3 -> u11 -> u10
+ D4-D7 -> u13 -> u12
+*/
+void pgram_device::set_gram_address(uint8_t data)
+{
+ if (m_crulatch->q1_r())
+ {
+ set_load_gram_counter(0);
+ clock_gram_counter(0);
+ m_count0->p_w(data&0x0f);
+ m_count1->p_w((data>>4)&0x0f);
+ m_count2->p_w(m_count0->output_r());
+ m_count3->p_w(m_count1->output_r());
+ clock_gram_counter(1);
+ set_load_gram_counter(1);
+ m_lowbyte = !m_lowbyte;
+ }
+}
+
+/*
+ Set the clock signal for all four counter chips. Propagate carry bits.
+*/
+void pgram_device::clock_gram_counter(int state)
+{
+ if (m_crulatch->q1_r())
+ {
+ m_count1->cet_w(m_count0->tc_r());
+ m_count2->cet_w(m_count1->tc_r());
+ m_count3->cet_w(m_count2->tc_r());
+
+ m_count0->clock_w(state);
+ m_count1->clock_w(state);
+ m_count2->clock_w(state);
+ m_count3->clock_w(state);
+
+ // Debugging
+ if (state==1 && m_lowbyte)
+ {
+ uint16_t gaddr = get_gram_address();
+ if (gaddr >= 0x6000) LOGMASKED(LOG_GRAMADDR, "gaddr=%04x\n", gaddr);
+ }
+ }
+}
+
+/*
+ Convenience method to retrieve the current GRAM address.
+*/
+uint16_t pgram_device::get_gram_address()
+{
+ return (m_count3->output_r()<<12) | (m_count2->output_r()<<8) | (m_count1->output_r()<<4) | m_count0->output_r();
+}
+
+/*
+ Set/reset the PE* bit of all 74LS161 curcuits.
+*/
+void pgram_device::set_load_gram_counter(int state)
+{
+ m_count0->pe_w(state);
+ m_count1->pe_w(state);
+ m_count2->pe_w(state);
+ m_count3->pe_w(state);
+}
+
+/*
+ CRU write access to the LS259 latch.
+*/
+void pgram_device::cruwrite(offs_t offset, uint8_t data)
+{
+ // ...1 0xxx .... ...0
+ bool selected = ((offset & 0xff01)==m_crubase);
+ if (selected)
+ {
+ uint8_t bit = (offset & 0xfe)>>1;
+ LOGMASKED(LOG_CRU, "cru %04x (bit %d) <- %d\n", offset, bit , data);
+ if (bit==3 || bit==4) LOGMASKED(LOG_BANK, "cru bit %d <- %d\n", bit, data);
+ }
+
+ m_crulatch->enable_w(selected? 0 : 1);
+ m_crulatch->write_abcd((offset>>1)&0x07, data);
+}
+
+/*
+ Device construction.
+*/
+void pgram_device::device_add_mconfig(machine_config& config)
+{
+ // 4-bit counters
+ TTL74161(config, m_count0); // u13
+ TTL74161(config, m_count1); // u11
+ TTL74161(config, m_count2); // u12
+ TTL74161(config, m_count3); // u10
+
+ // Hardwired connections
+ m_count0->set_cet_pin_value(1);
+
+ m_count0->set_cep_pin_value(1);
+ m_count1->set_cep_pin_value(1);
+ m_count2->set_cep_pin_value(1);
+ m_count3->set_cep_pin_value(1);
+
+ // CRU latch
+ LS259(config, m_crulatch); // u14
+
+ // Bank switch
+ TTL7474(config, m_bankff, 0);
+
+ // We allocate the space for PGRAM+
+ BUFF_RAM(config, GRAM4567_TAG, 0).set_size(128*1024);
+ BUFF_RAM(config, GRAM3_TAG, 0).set_size(32*1024);
+ BUFF_RAM(config, DSRRAM_TAG, 0).set_size(32*1024);
+
+ // Real-time clock
+ MM58167(config, CLOCK_TAG, 32.768_kHz_XTAL);
+}
+
+void pgram_device::device_start()
+{
+}
+
+void pgram_device::device_reset()
+{
+ m_active = (ioport("SW2")->read()==1);
+ m_crubase = (ioport("SW1")->read()<<8) | 0x1000;
+ m_pgramplus = (ioport("SIZE")->read()==1);
+}
+
+INPUT_CHANGED_MEMBER( pgram_device::sw1_changed )
+{
+ // CRU base changed
+ m_crubase = (newval << 8) | 0x1000;
+}
+
+INPUT_CHANGED_MEMBER( pgram_device::sw2_changed )
+{
+ // Activation switch changed
+ m_active = (newval==1);
+}
+
+INPUT_PORTS_START( pgram_switches )
+ PORT_START( "SIZE" )
+ PORT_CONFNAME( 0x01, 0x00, "Memory size") // cannot be changed during runtime
+ PORT_CONFSETTING(0x00, "PGRAM 72K")
+ PORT_CONFSETTING(0x01, "PGRAM+ 192K")
+
+ PORT_START( "SW2" )
+ PORT_DIPNAME( 0x01, 0x01, "Activate switch" ) PORT_CHANGED_MEMBER(DEVICE_SELF, FUNC(pgram_device::sw2_changed), 0)
+ PORT_DIPSETTING(0x00, DEF_STR( Off ))
+ PORT_DIPSETTING(0x01, DEF_STR( On ))
+
+ PORT_START( "SW1" )
+ PORT_DIPNAME( 0x07, 0x00, "CRU base" ) PORT_CHANGED_MEMBER(DEVICE_SELF, FUNC(pgram_device::sw1_changed), 0)
+ PORT_DIPSETTING( 0x00, "1000")
+ PORT_DIPSETTING( 0x02, "1200")
+ PORT_DIPSETTING( 0x03, "1300")
+ PORT_DIPSETTING( 0x04, "1400")
+ PORT_DIPSETTING( 0x05, "1500")
+ PORT_DIPSETTING( 0x06, "1600")
+ PORT_DIPSETTING( 0x07, "1700")
+INPUT_PORTS_END
+
+ioport_constructor pgram_device::device_input_ports() const
+{
+ return INPUT_PORTS_NAME( pgram_switches );
+}
+
+} // end namespace bus::ti99::peb
diff --git a/src/devices/bus/ti99/peb/pgram.h b/src/devices/bus/ti99/peb/pgram.h
new file mode 100644
index 00000000000..27feb1768cc
--- /dev/null
+++ b/src/devices/bus/ti99/peb/pgram.h
@@ -0,0 +1,87 @@
+// license:LGPL-2.1+
+// copyright-holders:Michael Zapf
+/*******************************************************************************
+ PGRAM(+) Memory expansion and GROM simulator
+
+ The PGRAM card is a battery-buffered RAM card. It also contains a circuitry
+ to simulate GROMs (TMC0430).
+
+ Michael Zapf
+ March 2020
+
+*******************************************************************************/
+
+#ifndef MAME_BUS_TI99_PEB_PGRAM_H
+#define MAME_BUS_TI99_PEB_PGRAM_H
+
+#pragma once
+
+#include "peribox.h"
+#include "machine/ram.h"
+#include "machine/mm58167.h"
+#include "machine/74259.h"
+#include "machine/7474.h"
+#include "machine/74161.h"
+#include "bus/ti99/internal/buffram.h"
+
+namespace bus::ti99::peb {
+
+class pgram_device : public device_t, public device_ti99_peribox_card_interface
+{
+public:
+ pgram_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
+ void write(offs_t offset, uint8_t data) override;
+ void readz(offs_t offset, uint8_t *value) override;
+ void crureadz(offs_t offset, uint8_t *value) override { }
+ void cruwrite(offs_t offset, uint8_t data) override;
+ DECLARE_INPUT_CHANGED_MEMBER( sw1_changed );
+ DECLARE_INPUT_CHANGED_MEMBER( sw2_changed );
+
+private:
+ void device_start() override ATTR_COLD;
+ void device_reset() override ATTR_COLD;
+ void device_add_mconfig(machine_config &config) override;
+
+ // Settings
+ bool m_active;
+ uint16_t m_crubase;
+ bool m_pgramplus;
+
+ ioport_constructor device_input_ports() const override;
+
+ required_device<bus::ti99::internal::buffered_ram_device> m_gram3;
+ required_device<bus::ti99::internal::buffered_ram_device> m_gram4567;
+ required_device<bus::ti99::internal::buffered_ram_device> m_dsrram;
+ required_device<mm58167_device> m_clock;
+ required_device<ls259_device> m_crulatch;
+ required_device<ttl7474_device> m_bankff;
+
+ // GROM address counter
+ required_device<ttl74161_device> m_count0;
+ required_device<ttl74161_device> m_count1;
+ required_device<ttl74161_device> m_count2;
+ required_device<ttl74161_device> m_count3;
+
+ // Methods
+ void gram_read(offs_t offset, uint8_t *value);
+ void dsr_ram_read(offs_t offset, uint8_t *value);
+
+ void gram_write(offs_t offset, uint8_t data);
+ void dsr_ram_write(offs_t offset, uint8_t data);
+
+ void set_gram_address(uint8_t addrbyte);
+
+ // GRAM implementation
+ void clock_gram_counter(int state);
+ void set_load_gram_counter(int state);
+ uint16_t get_gram_address();
+
+ // For debugging
+ bool m_lowbyte;
+};
+
+} // end namespace bus::ti99::peb
+
+DECLARE_DEVICE_TYPE_NS(TI99_PGRAM, bus::ti99::peb, pgram_device)
+
+#endif // MAME_BUS_TI99_PEB_PGRAM_H
diff --git a/src/devices/bus/ti99/peb/samsmem.cpp b/src/devices/bus/ti99/peb/samsmem.cpp
index dff96b57198..dd509e8e3d2 100644
--- a/src/devices/bus/ti99/peb/samsmem.cpp
+++ b/src/devices/bus/ti99/peb/samsmem.cpp
@@ -19,6 +19,8 @@
called the Super AMS. Any documentation and software containing a reference
to the AEMS are applicable to either AMS or SAMS.
+ The SAMS does not decode AMA/AMB/AMC.
+
Michael Zapf
*****************************************************************************/
@@ -26,9 +28,9 @@
#include "emu.h"
#include "samsmem.h"
-DEFINE_DEVICE_TYPE_NS(TI99_SAMSMEM, bus::ti99::peb, sams_memory_expansion_device, "ti99_sams", "SuperAMS memory expansion card")
+DEFINE_DEVICE_TYPE(TI99_SAMSMEM, bus::ti99::peb::sams_memory_expansion_device, "ti99_sams", "SuperAMS memory expansion card")
-namespace bus { namespace ti99 { namespace peb {
+namespace bus::ti99::peb {
#define SAMS_CRU_BASE 0x1e00
@@ -46,11 +48,11 @@ sams_memory_expansion_device::sams_memory_expansion_device(const machine_config
0x2000-0x3fff and 0xa000-0xffff, and the mapper area is at 0x4000-0x401e
(only even addresses).
*/
-READ8Z_MEMBER(sams_memory_expansion_device::readz)
+void sams_memory_expansion_device::readz(offs_t offset, uint8_t *value)
{
int base;
- if (m_access_mapper && ((offset & 0xe000)==0x4000))
+ if (m_access_mapper && in_dsr_space(offset, false))
{
*value = m_mapper[(offset>>1)&0x000f];
}
@@ -74,7 +76,7 @@ void sams_memory_expansion_device::write(offs_t offset, uint8_t data)
{
int base;
- if (m_access_mapper && ((offset & 0xe000)==0x4000))
+ if (m_access_mapper && in_dsr_space(offset, false))
{
m_mapper[(offset>>1)&0x000f] = data;
}
@@ -97,7 +99,7 @@ void sams_memory_expansion_device::write(offs_t offset, uint8_t data)
/*
CRU read. None here.
*/
-READ8Z_MEMBER(sams_memory_expansion_device::crureadz)
+void sams_memory_expansion_device::crureadz(offs_t offset, uint8_t *value)
{
}
@@ -110,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;
}
@@ -142,4 +144,4 @@ void sams_memory_expansion_device::device_reset()
for (auto & elem : m_mapper) elem = 0;
}
-} } } // end namespace bus::ti99::peb
+} // end namespace bus::ti99::peb
diff --git a/src/devices/bus/ti99/peb/samsmem.h b/src/devices/bus/ti99/peb/samsmem.h
index da05b58438e..314664cb7b3 100644
--- a/src/devices/bus/ti99/peb/samsmem.h
+++ b/src/devices/bus/ti99/peb/samsmem.h
@@ -21,27 +21,27 @@
#include "machine/74259.h"
#include "machine/ram.h"
-namespace bus { namespace ti99 { namespace peb {
+namespace bus::ti99::peb {
class sams_memory_expansion_device : public device_t, public device_ti99_peribox_card_interface
{
public:
sams_memory_expansion_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
- DECLARE_READ8Z_MEMBER(readz) override;
+ void readz(offs_t offset, uint8_t *value) override;
void write(offs_t offset, uint8_t data) override;
- DECLARE_READ8Z_MEMBER(crureadz) override;
+ void crureadz(offs_t offset, uint8_t *value) override;
void cruwrite(offs_t offset, uint8_t data) override;
protected:
- void device_start() override;
- void device_reset() override;
+ void device_start() override ATTR_COLD;
+ void device_reset() override ATTR_COLD;
- virtual void device_add_mconfig(machine_config &config) override;
+ virtual void device_add_mconfig(machine_config &config) override ATTR_COLD;
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;
@@ -51,7 +51,7 @@ private:
bool m_access_mapper;
};
-} } } // end namespace bus::ti99::peb
+} // end namespace bus::ti99::peb
DECLARE_DEVICE_TYPE_NS(TI99_SAMSMEM, bus::ti99::peb, sams_memory_expansion_device)
diff --git a/src/devices/bus/ti99/peb/scsicard.cpp b/src/devices/bus/ti99/peb/scsicard.cpp
new file mode 100644
index 00000000000..4ffe141aeb7
--- /dev/null
+++ b/src/devices/bus/ti99/peb/scsicard.cpp
@@ -0,0 +1,699 @@
+// license:LGPL-2.1+
+// copyright-holders:Michael Zapf
+/****************************************************************************
+
+ SCSI adapter card
+ designed and realized by Western Horizon Technologies
+
+ Latest two revisions:
+ Rev F: using logic circuits and a PAL for decoding
+ Rev G: using a PLD custom chip
+
+ This is an emulation of the WHTech SCSI adapter. It has been modified over
+ the years in various ways, in particular to get it working with the Geneve
+ 9640, and to enable word transfers. This modification was only effective
+ on the Geneve because the TMS9995 uses an even/odd word transfer, while the
+ TI-99/4A console uses an odd/even word transfer (see datamux.cpp), hence
+ swapping the bytes from the controller. An additional SWPB operation would
+ have been required which would have slowed down the transfer, so there would
+ not have be a measurable performance gain. Accordingly, the DSR (firmware)
+ of the card does not activate word transfer.
+
+ Further modifications were done to enable block DMA transfer. This could
+ only be used with a new DSR (1.6) and a daughterboard to replace the
+ PLD circuit.
+
+ Note that the DSR is not used when the card is used with the Geneve, since
+ the Geneve operating system brings its own SCSI driver. Block mode can
+ be explicitly activated with PDMA ON, but for this version of the emulation,
+ this will lead to a lockup, so PDMA OFF must be ensured.
+
+ A clone card was designed by the System 99 user group (SNUG), called ASCSI,
+ which contained all modifications.
+
+
+ Components
+ ----------
+ ispLSI2064 PLD (Custom decoder chip) (Rev G)
+ 62256 RAM 32Kx8
+ 27512 EPROM 64Kx8
+ NEC 53C80 SCSI Controller
+ Dip switches
+
+
+ Memory map
+ ----------
+
+ CB5=0 (CRU bit 5)
+ 4000-4FDF: EPROM (1 of 8 banks @ 8K)
+ 4FE0-4FFF: Controller
+ 5000-5FFF: SRAM (if CB1=1) or EPROM (if CB1=0)
+
+ CB5=1:
+ 4000-4FFF: SRAM (if CB1=1) or EPROM (if CB1=0)
+ 5000-5FDF: EPROM (1 of 8 banks)
+ 5FE0-5FFF: Controller
+
+
+ DIP switches [1]
+ SW1: CRU base 0600 - 1f00
+ SW2: 0: Driver LOAD/Parity enable
+ 1: SCSI ID Bit 0 (6 or 7)
+ 2: Normally on
+ 3: Normally on
+ 4: Geneve mode
+
+ CRU mapping
+ -----------
+ Read Write
+ 0: SCSI IRQ 0: Card select
+ 1: SCSI DRQ 1: SRAM enable (hides EPROM)
+ 2: SCSI READY 2: SCSI DMA mode enable
+ 3-7: DIP SW2 3: SCSI EOP (End of process)
+ 4: Word transfer mode select
+ 5: Bank swap
+ 6: -
+ 7: -
+ 8-10: EPROM bank (10=MSB)
+ 11: -
+ 12-14: SRAM bank (14=MSB)
+ 15: -
+
+
+ I/O ports (4Fxx for CB5=0, 5Fxx for CB5=1)
+ ---------
+ Read Write
+ 4FE0 Current SCSI data 4FF0 Output data (PIO and DMA)
+ 4FE2 Initiator command 4FF2 Initiator command
+ 4FE4 Mode 4FF4 Mode
+ 4FE6 Target command 4FF6 Target command
+ 4FE8 Current SCSI bus status 4FF8 Select enable
+ 4FEA Bus and status 4FFA Start DMA send
+ 4FEC Input data (DMA) 4FFC Start DMA target receive
+ 4FEE Reset parity/interrupt 4FFE Start DMA initiator receive
+
+
+ Drive mappings:
+ SCS1 = SCSI ID 0
+ SCS2 = SCSI ID 1
+ ...
+ SCS8 = SCSI ID 7
+
+
+ Michael Zapf
+
+ References
+
+ [1] Western Horizon Technologies: SCSI Host Adapter Card / Hardware
+ Installation Manual
+
+ Acknowledgements
+
+ 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 VERBOSE (LOG_GENERAL | LOG_WARN)
+
+#include "logmacro.h"
+
+#define BUFFER "ram"
+#define PLD_TAG "pld"
+#define CONTR_TAG "scsibus:7:controller"
+#define SCSIBUS_TAG "scsibus"
+
+DEFINE_DEVICE_TYPE(TI99_WHTSCSI, bus::ti99::peb::whtech_scsi_card_device, "ti99_whtscsi", "Western Horizon Technologies SCSI host adapter")
+DEFINE_DEVICE_TYPE(WHTSCSI_PLD, bus::ti99::peb::whtscsi_pld_device, PLD_TAG, "WHTech SCSI PLD")
+
+namespace bus::ti99::peb {
+
+whtech_scsi_card_device::whtech_scsi_card_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) :
+ device_t(mconfig, TI99_WHTSCSI, tag, owner, clock),
+ device_ti99_peribox_card_interface(mconfig, *this),
+ m_buffer_ram(*this, BUFFER),
+ m_pld(*this, PLD_TAG),
+ m_controller(*this, CONTR_TAG),
+ m_scsibus(*this, SCSIBUS_TAG),
+ m_irq(false),
+ m_drq(false),
+ m_readyset(false)
+{
+}
+
+void whtech_scsi_card_device::setaddress_dbin(offs_t offset, int state)
+{
+ // Do not allow setaddress for debugger
+ if (machine().side_effects_disabled()) return;
+ m_address = offset;
+ if (in_dsr_space(offset, true) && m_pld->card_selected())
+ {
+ LOGMASKED(LOG_READY, "setadd %04x (%s)\n", offset & 0xffff, machine().describe_context());
+ operate_ready_line();
+ }
+}
+
+void whtech_scsi_card_device::operate_ready_line()
+{
+ m_pld->update_line_states(m_address, m_drq, m_irq);
+
+ // Clear or assert the outgoing READY line
+ bool newready = m_pld->ready();
+ if (newready != m_readyset)
+ {
+ LOGMASKED(LOG_READY, "READY line changed to %d\n", newready);
+ m_slot->set_ready(newready);
+ m_readyset = newready;
+ }
+}
+
+/*
+ Debugger access.
+*/
+void whtech_scsi_card_device::debug_read(offs_t offset, uint8_t* value)
+{
+ offs_t addrcopy = m_address;
+ m_address = offset;
+
+ if (m_pld->sram_cs())
+ {
+ *value = m_buffer_ram->pointer()[(m_address & 0x0fff) | (m_pld->sram_bank()<<12)];
+ }
+
+ if (m_pld->eprom_cs())
+ {
+ // EPROM selected
+ int base = (m_pld->eprom_bank()<<13);
+ *value = m_eprom[base | (m_address & 0x1fff)];
+ }
+ m_address = addrcopy;
+}
+
+/*
+ Debugger access.
+*/
+void whtech_scsi_card_device::debug_write(offs_t offset, uint8_t data)
+{
+ offs_t addrcopy = m_address;
+ m_address = offset;
+
+ if (m_pld->sram_cs())
+ {
+ m_buffer_ram->pointer()[(m_address & 0x0fff) | (m_pld->sram_bank()<<12)] = data;
+ }
+ m_address = addrcopy;
+}
+
+void whtech_scsi_card_device::readz(offs_t offset, uint8_t *value)
+{
+ if (machine().side_effects_disabled())
+ {
+ debug_read(offset, value);
+ return;
+ }
+
+ if (!m_pld->card_selected()) return;
+
+ if (in_dsr_space(offset, true)) LOGMASKED(LOG_READY, "rd %04x\n", offset & 0xffff);
+
+ if (m_pld->eprom_cs())
+ {
+ // Lines A0-A12 directly connected to the EPROM (chip pin order)
+ // Lines A13-A15 connected to PLD
+ int base = (m_pld->eprom_bank()<<13);
+ uint8_t* rom = &m_eprom[base | (m_address & 0x1fff)];
+ *value = *rom;
+
+ if (WORD_ALIGNED(m_address))
+ {
+ // Do logging by 16 bit words, as we typically have instructions in
+ // the eprom
+ uint16_t val = (*rom << 8) | (*(rom+1));
+ LOGMASKED(LOG_EPROM, "DSR: %04x (bank %d) -> %04x\n", m_address & 0xffff, m_pld->eprom_bank(), val);
+ }
+ }
+
+ if (m_pld->sram_cs())
+ {
+ // Lines A0-A11 directly connected to the SRAM (chip pin order)
+ // Lines A12-A14 connected to PLD
+ *value = m_buffer_ram->pointer()[(m_address & 0x0fff) | (m_pld->sram_bank()<<12)];
+ LOGMASKED(LOG_RAM, "RAM: %04x (bank %d) -> %02x\n", m_address & 0xffff, m_pld->sram_bank(), *value);
+ }
+
+ if (m_pld->scsi_cs())
+ {
+ // Only for addresses 4fe0-4fef
+ 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_drq && (reg == 6))
+ {
+ *value = m_controller->dma_r();
+ LOGMASKED(LOG_DMA, "CTR: DMA in [%d] -> %02x (%s)\n", m_dmacount++, *value, machine().describe_context());
+ }
+ else
+ {
+ *value = m_controller->read(reg);
+ LOGMASKED(LOG_CONTR, "CTR: Reg %d (%04x) -> %02x (%s)\n", reg, m_address & 0xffff, *value, machine().describe_context());
+ }
+ }
+ }
+}
+
+void whtech_scsi_card_device::write(offs_t offset, uint8_t data)
+{
+ if (machine().side_effects_disabled())
+ {
+ debug_write(offset, data);
+ return;
+ }
+
+ if (!m_pld->card_selected()) return;
+
+ if (in_dsr_space(offset, true)) LOGMASKED(LOG_READY, "wr %04x\n", offset & 0xffff);
+
+ if (m_pld->sram_cs())
+ {
+ // Lines A0-A11 directly connected to the SRAM (chip pin order)
+ // Lines A12-A14 connected to PLD
+ LOGMASKED(LOG_RAM, "RAM: %04x (bank %d) <- %02x\n", m_address & 0xffff, m_pld->sram_bank(), data);
+ m_buffer_ram->pointer()[(m_address & 0x0fff) | (m_pld->sram_bank()<<12)] = data;
+ }
+
+ if (m_pld->scsi_cs())
+ {
+ // Only for addresses 4ff0-4fff
+ if ((m_address & 0x0010)==0x0010)
+ {
+ int reg = (m_address >> 1)&0x07;
+
+ // If we are in DMA mode, writing to register 0 means DMA write
+ if (m_drq && (reg == 0))
+ {
+ LOGMASKED(LOG_DMA, "CTR: DMA out <- %02x [%d] (%s)\n", data, m_dmacount++, machine().describe_context());
+ m_controller->dma_w(data);
+ }
+ else
+ {
+ LOGMASKED(LOG_CONTR, "CTR: Reg %d (%04x) <- %02x (%s)\n", reg, m_address & 0xffff, data, machine().describe_context());
+ m_controller->write(reg, data);
+ }
+ }
+ }
+}
+
+/*
+ CRU read access
+*/
+void whtech_scsi_card_device::crureadz(offs_t offset, uint8_t *value)
+{
+ m_pld->crureadz(offset, value);
+}
+
+/*
+ CRU write access. The flags are kept in the PLD.
+*/
+void whtech_scsi_card_device::cruwrite(offs_t offset, uint8_t data)
+{
+ m_pld->cruwrite(offset, data);
+ operate_ready_line();
+}
+
+/*
+ Callbacks for the controller chip.
+*/
+void whtech_scsi_card_device::drq_w(int state)
+{
+ LOGMASKED(LOG_CB, "DRQ pin from controller = %d\n", state);
+ bool drq = (state==ASSERT_LINE);
+ if (drq != m_drq)
+ {
+ m_drq = drq;
+ m_slot->set_inta((m_drq || m_irq)? ASSERT_LINE : CLEAR_LINE);
+ }
+ operate_ready_line();
+}
+
+void whtech_scsi_card_device::irq_w(int state)
+{
+ LOGMASKED(LOG_CB, "IRQ pin from controller = %d\n", state);
+ bool irq = (state==ASSERT_LINE);
+ if (irq != m_irq)
+ {
+ m_irq = irq;
+ m_slot->set_inta((m_drq || m_irq)? ASSERT_LINE : CLEAR_LINE);
+ }
+ operate_ready_line();
+}
+
+void whtech_scsi_card_device::signal_scsi_eop(int state)
+{
+ m_controller->eop_w(state);
+}
+
+void whtech_scsi_card_device::device_add_mconfig(machine_config &config)
+{
+ // RAM circuit
+ RAM(config, BUFFER).set_default_size("32K").set_default_value(0);
+
+ // PLD circuit
+ WHTSCSI_PLD(config, m_pld, 0);
+ m_pld->set_board(this);
+
+ // SCSI bus
+ NSCSI_BUS(config, m_scsibus);
+ NSCSI_CONNECTOR(config, "scsibus:0", default_scsi_devices, nullptr, false);
+ NSCSI_CONNECTOR(config, "scsibus:1", default_scsi_devices, nullptr, false);
+ 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);
+ NSCSI_CONNECTOR(config, "scsibus:5", default_scsi_devices, nullptr, false);
+ NSCSI_CONNECTOR(config, "scsibus:6", default_scsi_devices, nullptr, false);
+ NSCSI_CONNECTOR(config, "scsibus:7").option_set("controller", NCR53C80).machine_config([this](device_t *device) {
+ ncr53c80_device &adapter = downcast<ncr53c80_device &>(*device);
+ adapter.drq_handler().set(*this, FUNC(whtech_scsi_card_device::drq_w));
+ adapter.irq_handler().set(*this, FUNC(whtech_scsi_card_device::irq_w));
+ });
+}
+
+void whtech_scsi_card_device::device_start()
+{
+ m_eprom = memregion(TI99_DSRROM)->base();
+ save_item(NAME(m_address));
+ save_item(NAME(m_irq));
+ save_item(NAME(m_drq));
+ save_item(NAME(m_readyset));
+}
+
+void whtech_scsi_card_device::device_reset()
+{
+ m_cru_base = (ioport("SW1")->read()) << 8;
+ m_sw2 = ioport("SW2")->read();
+ m_drq = false;
+ m_irq = false;
+}
+
+int whtech_scsi_card_device::get_sw1()
+{
+ return m_cru_base;
+}
+
+int whtech_scsi_card_device::get_sw2()
+{
+ return m_sw2;
+}
+
+/*
+ The CRU address base for the card. According to [1], settings below
+ 1000 only make sense with an installed AT keyboard and ROM upgrade.
+*/
+INPUT_PORTS_START( whtscsi )
+ PORT_START("SW1")
+ PORT_DIPNAME(0x1f, 0x12, "SCSI card CRU base")
+ PORT_DIPSETTING(0x06, "0600")
+ PORT_DIPSETTING(0x07, "0700")
+ PORT_DIPSETTING(0x08, "0800")
+ PORT_DIPSETTING(0x09, "0900")
+ PORT_DIPSETTING(0x0a, "0a00")
+ PORT_DIPSETTING(0x0b, "0b00")
+ PORT_DIPSETTING(0x0c, "0c00")
+ PORT_DIPSETTING(0x0d, "0d00")
+ PORT_DIPSETTING(0x0e, "0e00")
+ PORT_DIPSETTING(0x0f, "0f00")
+ PORT_DIPSETTING(0x10, "1000")
+ PORT_DIPSETTING(0x11, "1100")
+ PORT_DIPSETTING(0x12, "1200") // Default setting
+ PORT_DIPSETTING(0x13, "1300")
+ PORT_DIPSETTING(0x14, "1400")
+ PORT_DIPSETTING(0x15, "1500")
+ PORT_DIPSETTING(0x16, "1600")
+ PORT_DIPSETTING(0x17, "1700")
+ PORT_DIPSETTING(0x18, "1800")
+ PORT_DIPSETTING(0x19, "1900")
+ PORT_DIPSETTING(0x1a, "1a00")
+ PORT_DIPSETTING(0x1b, "1b00")
+ PORT_DIPSETTING(0x1c, "1c00")
+ PORT_DIPSETTING(0x1d, "1d00")
+ PORT_DIPSETTING(0x1e, "1e00")
+ PORT_DIPSETTING(0x1f, "1f00")
+
+ PORT_START("SW2")
+ PORT_DIPNAME(0x01, 0x00, "Driver LOAD/Parity enable")
+ PORT_DIPSETTING(0x00, DEF_STR(Off))
+ PORT_DIPSETTING(0x01, DEF_STR(On))
+
+ // Currently, the controller is fixed to ID 7, according to device_add_mconfig,
+ // and we cannot relocate the card on the bus
+ PORT_DIPNAME(0x0e, 0x0e, "SCSI card ID")
+ // PORT_DIPSETTING(0x0c, "6")
+ PORT_DIPSETTING(0x0e, "7")
+ PORT_DIPNAME(0x10, 0x00, "Geneve mode")
+ PORT_DIPSETTING(0x00, DEF_STR(Off))
+ PORT_DIPSETTING(0x10, DEF_STR(On))
+INPUT_PORTS_END
+
+ROM_START( whtscsi )
+ ROM_REGION(0x10000, TI99_DSRROM, 0)
+ ROM_LOAD("scsidsr150.u6", 0x0000, 0x10000, CRC(6e067c22) SHA1(f8d8861863e6a17042428e94967fd4ffc4b9d1de)) /* HFDC disk DSR ROM */
+ROM_END
+
+
+const tiny_rom_entry *whtech_scsi_card_device::device_rom_region() const
+{
+ return ROM_NAME( whtscsi );
+}
+
+ioport_constructor whtech_scsi_card_device::device_input_ports() const
+{
+ return INPUT_PORTS_NAME(whtscsi);
+}
+
+// ========================================================================
+// PLD circuit on the board
+// ========================================================================
+
+whtscsi_pld_device::whtscsi_pld_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
+ : device_t(mconfig, WHTSCSI_PLD, tag, owner, clock),
+ m_board(nullptr),
+ m_selected(false),
+ m_sram_shadow(false),
+ m_dma_lock(false),
+ m_word_transfer(false),
+ m_bank_swapped(false),
+ m_readyout(true),
+ m_eprom_bank(0),
+ m_sram_bank(0)
+{
+}
+
+void whtscsi_pld_device::device_start()
+{
+ save_item(NAME(m_selected));
+ save_item(NAME(m_sram_shadow));
+ save_item(NAME(m_dma_lock));
+ save_item(NAME(m_word_transfer));
+ save_item(NAME(m_bank_swapped));
+ save_item(NAME(m_readyout));
+ save_item(NAME(m_eprom_bank));
+ save_item(NAME(m_sram_bank));
+}
+
+void whtscsi_pld_device::device_reset()
+{
+ m_selected = false;
+ m_sram_shadow = false;
+ m_readyout = true;
+ m_dma_lock = false;
+ m_word_transfer = false;
+ m_bank_swapped = false;
+ m_eprom_bank = 0;
+ m_sram_bank = 0;
+}
+
+/*
+ SRAM is accessible at 5000-5fff for bank_swapped=false, else at 4000-4fff.
+ Needs to be turned on with the flag sram_shadow.
+*/
+line_state whtscsi_pld_device::sram_cs()
+{
+ if (!m_sram_shadow) return CLEAR_LINE;
+ return (busen()
+ && (((m_board->m_address & 0x1000)==0) == m_bank_swapped))? ASSERT_LINE : CLEAR_LINE;
+}
+
+/*
+ EPROM is selected when we are in the correct address space and neither
+ SRAM nor the controller are selected.
+*/
+line_state whtscsi_pld_device::eprom_cs()
+{
+ return (busen()
+ && (sram_cs()==CLEAR_LINE)
+ && (scsi_cs()==CLEAR_LINE))? ASSERT_LINE : CLEAR_LINE;
+}
+
+/*
+ The controller is selected in the 4fe0-4ffe space, or in 5fe0-5ffe, depending
+ on the bank_swapped flag (4xxx for bank_swapped=false).
+ Also, for byte mode, only the even addresses are mapped. In word mode, the
+ controller shall be active for both even and odd address accesses. This is
+ only needed for DMA.
+*/
+line_state whtscsi_pld_device::scsi_cs()
+{
+ return (busen()
+ && ((m_board->m_address & 0x0fe0)==0x0fe0)
+ && (((m_board->m_address & 0x1000)!=0) == m_bank_swapped)
+ && (((m_board->m_address & 1)==0) || m_word_transfer))? ASSERT_LINE : CLEAR_LINE;
+}
+
+/*
+ Are we accessing the memory area 4000-5FFF, and this card has been turned on?
+*/
+bool whtscsi_pld_device::busen()
+{
+ return (((m_board->m_address & 0x7e000)==0x74000) && m_selected);
+}
+
+/*
+ CRU read access
+*/
+void whtscsi_pld_device::crureadz(offs_t offset, uint8_t *value)
+{
+ int crubase = m_board->get_sw1();
+
+ if ((offset & 0xff00)==crubase)
+ {
+ int bit = (offset >> 1) & 0x1f;
+ switch (bit)
+ {
+ case 0:
+ *value = m_board->m_irq? 1 : 0;
+ break;
+ case 1:
+ *value = m_board->m_drq? 1 : 0;
+ break;
+ case 2:
+ // READY; not available in the current 53C80 emulation
+ break;
+ case 3:
+ case 4:
+ case 5:
+ case 6:
+ case 7:
+ *value = ((m_board->get_sw2() & (1<<(bit-3)))!=0)? 1 : 0;
+ break;
+ default:
+ break;
+ }
+ // LOGMASKED(LOG_CRU, "CRU %04x -> %d\n", offset & 0xffff, *value);
+ }
+}
+
+/*
+ CRU write access
+*/
+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());
+ int bit = (offset >> 1) & 0x1f;
+ switch (bit)
+ {
+ case 0: // card activation
+ 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 (%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 (%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 (%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 (%s)\n", (data!=0)? "on" : "off", machine().describe_context());
+ m_word_transfer = (data != 0);
+ break;
+ case 5:
+ 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) (%s)\n", (data!=0)? "on" : "off", machine().describe_context());
+ break;
+ case 8:
+ case 9:
+ case 10:
+ if (data != 0)
+ 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:
+ case 14:
+ if (data != 0)
+ 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;
+ }
+ }
+}
+
+bool whtscsi_pld_device::ready()
+{
+ return m_readyout;
+}
+
+bool whtscsi_pld_device::card_selected()
+{
+ return m_selected;
+}
+
+/*
+ Updates the state of the READY output of the PLD. In the real device, the
+ SCSIDACK line is also updated, but this line is not used with the current
+ implementation of the 53C80.
+
+ READY is always asserted when an IRQ is pending or when we do not use DMA
+ Otherwise, READY is asserted when a DRQ is pending
+ When the DMA lock is active, and there is no DRQ yet, let the CPU wait
+*/
+void whtscsi_pld_device::update_line_states(int address, bool drq, bool irq)
+{
+ m_readyout = (irq || !m_dma_lock)? true : drq;
+}
+
+} // end namespace bus::ti99::peb
diff --git a/src/devices/bus/ti99/peb/scsicard.h b/src/devices/bus/ti99/peb/scsicard.h
new file mode 100644
index 00000000000..af9adee4476
--- /dev/null
+++ b/src/devices/bus/ti99/peb/scsicard.h
@@ -0,0 +1,145 @@
+// license:LGPL-2.1+
+// copyright-holders:Michael Zapf
+/****************************************************************************
+
+ SCSI adapter card
+ See scsicard.cpp for documentation
+
+ Michael Zapf
+ November 2021
+
+*****************************************************************************/
+
+#ifndef MAME_BUS_TI99_PEB_SCSICARD_H
+#define MAME_BUS_TI99_PEB_SCSICARD_H
+
+#pragma once
+
+#include "peribox.h"
+#include "machine/ram.h"
+#include "machine/ncr5380.h"
+
+namespace bus::ti99::peb {
+class whtscsi_pld_device;
+
+class whtech_scsi_card_device : public device_t, public device_ti99_peribox_card_interface
+{
+ friend class whtscsi_pld_device;
+
+public:
+ whtech_scsi_card_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
+ void readz(offs_t offset, uint8_t *value) override;
+ void write(offs_t offset, uint8_t data) override;
+ void setaddress_dbin(offs_t offset, int state) override;
+
+ void crureadz(offs_t offset, uint8_t *value) override;
+ void cruwrite(offs_t offset, uint8_t data) override;
+
+ 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);
+
+protected:
+ 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;
+ virtual ioport_constructor device_input_ports() const override ATTR_COLD;
+ virtual const tiny_rom_entry *device_rom_region() const override ATTR_COLD;
+
+private:
+ // SCSI card on-board SRAM (32K)
+ required_device<ram_device> m_buffer_ram;
+
+ // Decoder PLD
+ required_device<whtscsi_pld_device> m_pld;
+
+ // SCSI controller chip
+ required_device<ncr53c80_device> m_controller;
+
+ // SCSI bus
+ required_device<nscsi_bus_device> m_scsibus;
+
+ // DSR ROM
+ uint8_t* m_eprom;
+
+ // Recent address
+ int m_address;
+
+ // 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;
+ bool m_drq;
+
+ // State of the READY line
+ bool m_readyset;
+
+ // Accessor functions for the PLD
+ int get_sw1();
+ int get_sw2();
+
+ // Determine the state of the READY line
+ void operate_ready_line();
+
+ // Send the EOP signal to the controller
+ void signal_scsi_eop(int state);
+};
+
+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);
+
+ void crureadz(offs_t offset, uint8_t *value);
+ void cruwrite(offs_t offset, uint8_t data);
+
+ bool card_selected();
+
+ // Selector output lines of the PLD
+ line_state sram_cs();
+ line_state eprom_cs();
+ line_state scsi_cs();
+
+ int eprom_bank() { return m_eprom_bank; }
+ int sram_bank() { return m_sram_bank; }
+
+ bool ready();
+
+ void update_line_states(int address, bool drq, bool irq);
+
+protected:
+ virtual void device_start() override ATTR_COLD;
+ virtual void device_reset() override ATTR_COLD;
+
+private:
+ whtech_scsi_card_device* m_board;
+
+ void set_board(whtech_scsi_card_device* board) { m_board = board; }
+ bool busen();
+
+ // Flags
+ bool m_selected;
+ bool m_sram_shadow;
+ bool m_dma_lock;
+ bool m_word_transfer;
+ bool m_bank_swapped;
+ bool m_readyout;
+ int m_eprom_bank;
+ int m_sram_bank;
+};
+
+} // end namespace bus::ti99::peb
+
+DECLARE_DEVICE_TYPE_NS(TI99_WHTSCSI, bus::ti99::peb, whtech_scsi_card_device)
+DECLARE_DEVICE_TYPE_NS(WHTSCSI_PLD, bus::ti99::peb, whtscsi_pld_device)
+
+#endif // MAME_BUS_TI99_PEB_SCSICARD_H
diff --git a/src/devices/bus/ti99/peb/sidmaster.cpp b/src/devices/bus/ti99/peb/sidmaster.cpp
new file mode 100644
index 00000000000..2fac13f654b
--- /dev/null
+++ b/src/devices/bus/ti99/peb/sidmaster.cpp
@@ -0,0 +1,98 @@
+// license:LGPL-2.1+
+// copyright-holders:Michael Zapf
+/****************************************************************************
+
+ SID Master 99
+ Original circuit copyright 2010 by Marc Hull
+ Board layout and board artwork copyright 2010 by Jim Fetzner
+
+ This expansion card adds a SID sound generator chip to the TI system.
+
+ The circuitry has an unconventional selection mechanism: It assumes to be
+ active at all times, unless a CRU address 1xxx and higher appears on the
+ bus. This requires that the 9901 addresses be visible on the bus. Also, it
+ has to be verified whether the real Geneve works with the SID Master.
+
+ The SID is mapped to addresses 5800-5836 (even addresses only), incompletely
+ decoded (5800-5FFF).
+
+ Michael Zapf
+ September 2020
+
+*****************************************************************************/
+
+#include "emu.h"
+#include "sidmaster.h"
+
+#define LOG_WARN (1U << 1)
+#define LOG_WRITE (1U << 2)
+
+#define VERBOSE (LOG_GENERAL | LOG_WARN)
+
+#include "logmacro.h"
+
+DEFINE_DEVICE_TYPE(TI99_SIDMASTER, bus::ti99::peb::sidmaster_device, "ti99_sidmaster", "SID Master 99")
+
+namespace bus::ti99::peb {
+
+sidmaster_device::sidmaster_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) :
+ device_t(mconfig, TI99_SIDMASTER, tag, owner, clock),
+ device_ti99_peribox_card_interface(mconfig, *this),
+ m_sid(*this, "sid")
+{
+}
+
+void sidmaster_device::write(offs_t offset, uint8_t data)
+{
+ if (m_selected && ((offset & 0xf800)==0x5800))
+ {
+ LOGMASKED(LOG_WRITE, "%04x <- %02x\n", offset, data);
+ m_sid->write((offset >> 1)& 0x1f, data);
+ }
+}
+
+/*
+ CRU read access
+ There is actually no CRU access; the card is deselected when CRU devices
+ 0x1000 and higher are accessed.
+*/
+void sidmaster_device::crureadz(offs_t offset, uint8_t *value)
+{
+ bool prevsel = m_selected;
+ m_selected = ((offset & 0xf000) == 0x0000);
+ if (prevsel && !m_selected)
+ m_sid->reset();
+}
+
+/*
+ CRU write access
+ There is actually no CRU access; the card is deselected when CRU devices
+ 0x1000 and higher are accessed.
+*/
+void sidmaster_device::cruwrite(offs_t offset, uint8_t data)
+{
+ bool prevsel = m_selected;
+ m_selected = ((offset & 0xf000) == 0x0000);
+ if (prevsel && !m_selected)
+ m_sid->reset();
+}
+
+void sidmaster_device::device_add_mconfig(machine_config &config)
+{
+ // sound hardware
+ SPEAKER(config, "mono").front_center();
+ MOS6581(config, m_sid, XTAL(17'734'472)/18);
+ m_sid->add_route(ALL_OUTPUTS, "mono", 1.00);
+}
+
+void sidmaster_device::device_start()
+{
+}
+
+void sidmaster_device::device_reset()
+{
+ m_sid->reset();
+}
+
+
+} // end namespace bus::ti99::peb
diff --git a/src/devices/bus/ti99/peb/sidmaster.h b/src/devices/bus/ti99/peb/sidmaster.h
new file mode 100644
index 00000000000..765d4a6d3ac
--- /dev/null
+++ b/src/devices/bus/ti99/peb/sidmaster.h
@@ -0,0 +1,47 @@
+// license:LGPL-2.1+
+// copyright-holders:Michael Zapf
+/****************************************************************************
+
+ SID Master 99
+ See sidmaster.cpp for documentation
+
+ Michael Zapf
+ September 2020
+
+*****************************************************************************/
+
+#ifndef MAME_BUS_TI99_PEB_SIDMASTER_H
+#define MAME_BUS_TI99_PEB_SIDMASTER_H
+
+#pragma once
+
+#include "peribox.h"
+#include "sound/mos6581.h"
+#include "speaker.h"
+
+namespace bus::ti99::peb {
+
+class sidmaster_device : public device_t, public device_ti99_peribox_card_interface
+{
+public:
+ sidmaster_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
+ void readz(offs_t offset, uint8_t *value) override { }; // No read
+ void write(offs_t offset, uint8_t data) override;
+
+ // Only for selection/deselection
+ void crureadz(offs_t offset, uint8_t *value) override;
+ void cruwrite(offs_t offset, uint8_t data) override;
+
+private:
+ void device_start() override ATTR_COLD;
+ void device_reset() override ATTR_COLD;
+ void device_add_mconfig(machine_config &config) override;
+
+ required_device<mos6581_device> m_sid;
+};
+
+} // end namespace bus::ti99::peb
+
+DECLARE_DEVICE_TYPE_NS(TI99_SIDMASTER, bus::ti99::peb, sidmaster_device)
+
+#endif // MAME_BUS_TI99_PEB_SIDMASTER_H
diff --git a/src/devices/bus/ti99/peb/spchsyn.cpp b/src/devices/bus/ti99/peb/spchsyn.cpp
deleted file mode 100644
index 73e6d37e682..00000000000
--- a/src/devices/bus/ti99/peb/spchsyn.cpp
+++ /dev/null
@@ -1,186 +0,0 @@
-// license:LGPL-2.1+
-// copyright-holders:Michael Zapf
-/****************************************************************************
-
- TI-99 Speech synthesizer
-
- We emulate the Speech Synthesizer plugged onto a P-Box adapter. The original
- Speech Synthesizer device was provided as a box to be plugged into the
- right side of the console. In order to be used with Geneve and SGCPU, the
- speech synthesizer must be moved into the Peripheral Box.
-
- The Speech Synthesizer used for the TI was the CD2501E, AKA TMS5200,
- (internal name TMC0285), a predecessor of the TMS5220 which was used in
- other commercial products.
-
- Note that this adapter also contains the speech roms.
-
- Michael Zapf
-
- February 2012: Rewritten as class
-
-*****************************************************************************/
-
-#include "emu.h"
-#include "spchsyn.h"
-
-#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 VERBOSE ( LOG_CONFIG | LOG_WARN )
-#include "logmacro.h"
-
-DEFINE_DEVICE_TYPE_NS(TI99_SPEECH, bus::ti99::peb, ti_speech_synthesizer_device, "ti99_speech", "TI-99 Speech synthesizer (on adapter card)")
-
-namespace bus { namespace ti99 { namespace peb {
-
-/****************************************************************************/
-
-ti_speech_synthesizer_device::ti_speech_synthesizer_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) :
- device_t(mconfig, TI99_SPEECH, tag, owner, clock),
- device_ti99_peribox_card_interface(mconfig, *this),
- m_vsp(*this, "vsp"),
- m_reading(false),
- m_sbe(false)
-{
-}
-
-/*
- Memory read
-*/
-
-READ8Z_MEMBER( ti_speech_synthesizer_device::readz )
-{
- if (machine().side_effects_disabled()) return;
-
- if (m_sbe)
- {
- *value = m_vsp->status_r() & 0xff;
- LOGMASKED(LOG_MEM, "read value = %02x\n", *value);
- // We should clear the lines at this point. The TI-99/4A clears the
- // lines by setting the address bus to a different value, but the
- // Geneve may behave differently. This may not 100% reflect the real
- // situation, but it ensures a safe processing.
- m_vsp->combined_rsq_wsq_w(~0);
- }
-}
-
-/*
- Memory write
-*/
-void ti_speech_synthesizer_device::write(offs_t offset, uint8_t data)
-{
- if (machine().side_effects_disabled()) return;
-
- if (m_sbe)
- {
- LOGMASKED(LOG_MEM, "write value = %02x\n", data);
- m_vsp->data_w(data);
- // Note that we must NOT clear the lines here. Find the lines in the
- // READY callback below.
- }
-}
-
-SETADDRESS_DBIN_MEMBER( ti_speech_synthesizer_device::setaddress_dbin )
-{
- // 1001 00xx xxxx xxx0 DBIN=1
- // 1001 01xx xxxx xxx0 DBIN=0
- // 1111 1000 0000 0001 mask
- m_reading = (state==ASSERT_LINE);
-
- bool valid = (((offset & 0x0400)==0) == m_reading);
- m_sbe = ((offset & m_select_mask)==m_select_value) && valid;
-
- if (m_sbe)
- {
- LOGMASKED(LOG_ADDR, "set address = %04x, dbin = %d\n", offset, state);
-
- // Caution: In the current tms5220 emulation, care must be taken
- // to clear one line before asserting the other line, or otherwise
- // both RS* and WS* are active, which is illegal.
- // Alternatively, we'll use the combined settings method
-
- m_vsp->combined_rsq_wsq_w(m_reading ? ~tms5220_device::RS : ~tms5220_device::WS);
- }
- else
- // If other address, turn off RS* and WS* (negative logic!)
- m_vsp->combined_rsq_wsq_w(~0);
-}
-
-/****************************************************************************/
-
-WRITE_LINE_MEMBER( ti_speech_synthesizer_device::speech_ready )
-{
- // The TMS5200 implementation uses true/false, not ASSERT/CLEAR semantics
- // and we have to adapt a /READY to a READY line.
- // The real synthesizer board uses a transistor for that purpose.
- m_slot->set_ready((state==0)? ASSERT_LINE : CLEAR_LINE);
- LOGMASKED(LOG_READY, "READY = %d\n", (state==0));
-
- if ((state==0) && !m_reading)
- // Clear the lines only when we are done with writing.
- m_vsp->combined_rsq_wsq_w(~0);
-}
-
-void ti_speech_synthesizer_device::device_start()
-{
- save_item(NAME(m_reading));
- save_item(NAME(m_sbe));
-}
-
-void ti_speech_synthesizer_device::device_reset()
-{
- if (m_genmod)
- {
- m_select_mask = 0x1ff801;
- m_select_value = 0x179000;
- }
- else
- {
- m_select_mask = 0x7f801;
- m_select_value = 0x79000;
- }
-
- m_reading = false;
- m_sbe = false;
-}
-
-ROM_START( ti99_speech )
- ROM_REGION(0x8000, "vsm", 0)
- ROM_LOAD("cd2325a.u2a", 0x0000, 0x4000, CRC(1f58b571) SHA1(0ef4f178716b575a1c0c970c56af8a8d97561ffe)) // at location u2, bottom of stack
- ROM_LOAD("cd2326a.u2b", 0x4000, 0x4000, CRC(65d00401) SHA1(a367242c2c96cebf0e2bf21862f3f6734b2b3020)) // at location u2, top of stack
-ROM_END
-
-void ti_speech_synthesizer_device::device_add_mconfig(machine_config& config)
-{
- SPEECHROM(config, "vsm", 0).set_reverse_bit_order(true);
- SPEAKER(config, "speech_out").front_center();
- CD2501E(config, m_vsp, 640000L);
- m_vsp->set_speechrom_tag("vsm");
- m_vsp->ready_cb().set(FUNC(ti_speech_synthesizer_device::speech_ready));
- m_vsp->add_route(ALL_OUTPUTS, "speech_out", 0.50);
-
-/*
- // FIXME: Make it work. Guess we need two VSM circuits @16K.
- TMS6100(config, "vsm", 640_kHz_XTAL/4);
- m_vsp->m0_cb().set("vsm", FUNC(tms6100_device::m0_w));
- m_vsp->m1_cb().set("vsm", FUNC(tms6100_device::m1_w));
- m_vsp->addr_cb().set("vsm", FUNC(tms6100_device::add_w));
- m_vsp->data_cb().set("vsm", FUNC(tms6100_device::data_line_r));
- m_vsp->romclk_cb().set("vsm", FUNC(tms6100_device::clk_w));
-*/
-}
-
-const tiny_rom_entry *ti_speech_synthesizer_device::device_rom_region() const
-{
- return ROM_NAME( ti99_speech );
-}
-
-} } } // end namespace bus::ti99::peb
-
diff --git a/src/devices/bus/ti99/peb/spchsyn.h b/src/devices/bus/ti99/peb/spchsyn.h
deleted file mode 100644
index 8efee71aed7..00000000000
--- a/src/devices/bus/ti99/peb/spchsyn.h
+++ /dev/null
@@ -1,53 +0,0 @@
-// license:LGPL-2.1+
-// copyright-holders:Michael Zapf
-/****************************************************************************
-
- TI-99 Speech Synthesizer
- See spchsyn.c for documentation
-
- Michael Zapf, October 2010
- February 2012: Rewritten as class
-
-*****************************************************************************/
-
-#ifndef MAME_BUS_TI99_PEB_SPCHSYN_H
-#define MAME_BUS_TI99_PEB_SPCHSYN_H
-
-#pragma once
-
-#include "peribox.h"
-#include "sound/tms5220.h"
-#include "machine/tms6100.h"
-
-namespace bus { namespace ti99 { namespace peb {
-
-class ti_speech_synthesizer_device : public device_t, public device_ti99_peribox_card_interface
-{
-public:
- ti_speech_synthesizer_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
- DECLARE_READ8Z_MEMBER(readz) override;
- void write(offs_t offset, uint8_t data) override;
- DECLARE_SETADDRESS_DBIN_MEMBER(setaddress_dbin) override;
-
- DECLARE_READ8Z_MEMBER(crureadz) override { }
- void cruwrite(offs_t offset, uint8_t data) override { }
-
-protected:
- 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;
-
-private:
- DECLARE_WRITE_LINE_MEMBER( speech_ready );
-
- required_device<cd2501e_device> m_vsp;
- bool m_reading;
- bool m_sbe; // Signal "Speech block enable"
-};
-
-} } } // end namespace bus::ti99::peb
-
-DECLARE_DEVICE_TYPE_NS(TI99_SPEECH, bus::ti99::peb, ti_speech_synthesizer_device)
-
-#endif // MAME_BUS_TI99_PEB_SPCHSYN_H
diff --git a/src/devices/bus/ti99/peb/speechadapter.cpp b/src/devices/bus/ti99/peb/speechadapter.cpp
new file mode 100644
index 00000000000..2bf237c2978
--- /dev/null
+++ b/src/devices/bus/ti99/peb/speechadapter.cpp
@@ -0,0 +1,158 @@
+// license:LGPL-2.1+
+// copyright-holders:Michael Zapf
+/****************************************************************************
+
+ TI-99 Speech synthesizer adapter device
+
+ This adapter card made the sidecar Speech Synthesizer unit available to
+ systems without a TI-99/4A console, like the SGCPU and the Geneve. The
+ board must be removed from the sidecar unit and plugged on this simple
+ adapter board, which is then put in a slot of the Peripheral Expansion Box.
+
+ +-------+
+ +-----|-------|---+
+ | Speech syn |
+ | board |
+ | _________ |
+ +-----+++++++++---+
+ +----------------------------+|||||||+------------+
+ | ------- |
+ | Adapter board |
+ | |
+ (((o LED PEB slot connector |
+ +--------------|||||||||||||||||||||||||----------+
+ |||||||||||||||||||||||||
+
+ Technical detail:
+
+ The SBE signal (Speech Block Enable), which is generated in the TI console,
+ is not forwarded to the PEB. One of the tasks of this board is thus to
+ decode the mapped addresses once more and to activate the synthesizer
+ accordingly.
+
+ A second issue for Geneve users is that the address extension bits (AMA,
+ AMB, AMC) need to be decoded as well to avoid the synthesizer interfering
+ with other memory access. This can be activated in the configuration. The
+ default is on.
+
+ Michael Zapf
+ March 2025
+
+*****************************************************************************/
+
+#include "emu.h"
+#include "speechadapter.h"
+
+#include "speaker.h"
+#include "bus/ti99/sidecar/speechsyn.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 VERBOSE (LOG_CONFIG | LOG_WARN)
+#include "logmacro.h"
+
+DEFINE_DEVICE_TYPE(TI99_SPEECHADAPTER, bus::ti99::peb::ti_speechsyn_adapter_device, "ti99_speechconn", "TI-99 Speech synthesizer adapter card")
+
+namespace bus::ti99::peb {
+
+#define PORT "conn"
+
+/****************************************************************************/
+
+ti_speechsyn_adapter_device::ti_speechsyn_adapter_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) :
+ device_t(mconfig, TI99_SPEECHADAPTER, tag, owner, clock),
+ device_ti99_peribox_card_interface(mconfig, *this),
+ m_port(*this, PORT),
+ m_dec_high(false)
+{
+}
+
+void ti_speechsyn_adapter_device::readz(offs_t offset, uint8_t *value)
+{
+ if (m_port != nullptr)
+ {
+ LOGMASKED(LOG_MEM, "read %06x\n", offset);
+ m_port->readz(offset, value);
+ }
+}
+
+void ti_speechsyn_adapter_device::write(offs_t offset, uint8_t data)
+{
+ if (m_port != nullptr)
+ {
+ LOGMASKED(LOG_MEM, "write %06x\n", offset);
+ m_port->write(offset, data);
+ }
+}
+
+void ti_speechsyn_adapter_device::setaddress_dbin(offs_t offset, int state)
+{
+ // Valid access = not(DBIN and A5)
+ bool reading = (state==ASSERT_LINE);
+
+ // An access is valid when reading from 9000 and writing to 9400.
+ bool valid = (((offset & 0x0400)==0) == reading);
+ bool sbe = false;
+
+ // Recreate the SBE signal that is only available at the I/O port of the console
+ if (m_dec_high)
+ // We need to decode the AMA/AMB/AMC address extension lines
+ sbe = ((offset & 0x7f801)==0x79000) && valid;
+ else
+ // No need to decode the extension lines
+ sbe = ((offset & 0x0f801)==0x09000) && valid;
+
+ if (sbe) LOGMASKED(LOG_ADDR, "set address = %04x, dbin = %d\n", offset, state);
+
+ if (m_port != nullptr)
+ {
+ m_port->sbe(sbe);
+ m_port->setaddress_dbin(offset, state);
+ }
+}
+
+void ti_speechsyn_adapter_device::ready(int state)
+{
+ LOGMASKED(LOG_READY, "Incoming READY=%d from synthesizer %d\n", state);
+ m_slot->set_ready(state);
+}
+
+void ti_speechsyn_adapter_device::device_start()
+{
+}
+
+void ti_speechsyn_adapter_device::device_reset()
+{
+ m_dec_high = (ioport("AMADECODE")->read()!=0);
+ LOGMASKED(LOG_CONFIG, "Speech adapter%s decoding the AMA/B/C lines.\n", m_dec_high? "" : " not");
+}
+
+void ti_speechsyn_adapter_options(device_slot_interface &device)
+{
+ device.option_add("speechsyn", TI99_SPEECHSYN);
+}
+
+void ti_speechsyn_adapter_device::device_add_mconfig(machine_config& config)
+{
+ TI99_IOPORT(config, m_port, 0, ti_speechsyn_adapter_options, "speechsyn");
+ m_port->ready_cb().set(FUNC(ti_speechsyn_adapter_device::ready));
+}
+
+INPUT_PORTS_START( ti99_speechadapter )
+ PORT_START( "AMADECODE" )
+ PORT_CONFNAME( 0x01, 0x01, "Decode AMA/AMB/AMC lines" )
+ PORT_CONFSETTING( 0x00, DEF_STR( Off ))
+ PORT_CONFSETTING( 0x01, DEF_STR( On ))
+INPUT_PORTS_END
+
+ioport_constructor ti_speechsyn_adapter_device::device_input_ports() const
+{
+ return INPUT_PORTS_NAME(ti99_speechadapter);
+}
+
+} // end namespace bus::ti99::peb
+
diff --git a/src/devices/bus/ti99/peb/speechadapter.h b/src/devices/bus/ti99/peb/speechadapter.h
new file mode 100644
index 00000000000..b77823811ca
--- /dev/null
+++ b/src/devices/bus/ti99/peb/speechadapter.h
@@ -0,0 +1,49 @@
+// license:LGPL-2.1+
+// copyright-holders:Michael Zapf
+/****************************************************************************
+
+ TI-99 Speech Synthesizer connector adapter
+ for the Peripheral Expansion Box
+
+ Michael Zapf, March 2025
+
+*****************************************************************************/
+
+#ifndef MAME_BUS_TI99_PEB_SPEECHADAPTER_H
+#define MAME_BUS_TI99_PEB_SPEECHADAPTER_H
+
+#pragma once
+
+#include "peribox.h"
+#include "bus/ti99/internal/ioport.h"
+
+namespace bus::ti99::peb {
+
+class ti_speechsyn_adapter_device : public device_t, public device_ti99_peribox_card_interface
+{
+public:
+ ti_speechsyn_adapter_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
+ void readz(offs_t offset, uint8_t *value) override;
+ void write(offs_t offset, uint8_t data) override;
+ void setaddress_dbin(offs_t offset, int state) override;
+ void crureadz(offs_t offset, uint8_t *value) override { }
+ void cruwrite(offs_t offset, uint8_t data) override { }
+
+protected:
+ virtual void device_start() override;
+ virtual void device_reset() override;
+ virtual void device_add_mconfig(machine_config &config) override ATTR_COLD;
+ virtual ioport_constructor device_input_ports() const override ATTR_COLD;
+
+private:
+ required_device<bus::ti99::internal::ioport_device> m_port;
+ bool m_dec_high;
+
+ void ready(int state);
+};
+
+} // end namespace bus::ti99::peb
+
+DECLARE_DEVICE_TYPE_NS(TI99_SPEECHADAPTER, bus::ti99::peb, ti_speechsyn_adapter_device)
+
+#endif // MAME_BUS_TI99_PEB_SPEECHADAPTER_H
diff --git a/src/devices/bus/ti99/peb/ti_32kmem.cpp b/src/devices/bus/ti99/peb/ti_32kmem.cpp
index b25c7d65784..1f9404bd1e1 100644
--- a/src/devices/bus/ti99/peb/ti_32kmem.cpp
+++ b/src/devices/bus/ti99/peb/ti_32kmem.cpp
@@ -31,9 +31,9 @@
#include "emu.h"
#include "ti_32kmem.h"
-DEFINE_DEVICE_TYPE_NS(TI99_32KMEM, bus::ti99::peb, ti_32k_expcard_device, "ti99_32kmem", "TI-99 32KiB memory expansion card")
+DEFINE_DEVICE_TYPE(TI99_32KMEM, bus::ti99::peb::ti_32k_expcard_device, "ti99_32kmem", "TI-99 32KiB memory expansion card")
-namespace bus { namespace ti99 { namespace peb {
+namespace bus::ti99::peb {
#define RAMREGION "ram32k"
@@ -44,7 +44,7 @@ ti_32k_expcard_device::ti_32k_expcard_device(const machine_config &mconfig, cons
{
}
-READ8Z_MEMBER(ti_32k_expcard_device::readz)
+void ti_32k_expcard_device::readz(offs_t offset, uint8_t *value)
{
uint8_t val = 0;
/*
@@ -107,4 +107,4 @@ void ti_32k_expcard_device::device_add_mconfig(machine_config &config)
m_ram->set_default_value(0);
}
-} } } // end namespace bus::ti99::peb
+} // end namespace bus::ti99::peb
diff --git a/src/devices/bus/ti99/peb/ti_32kmem.h b/src/devices/bus/ti99/peb/ti_32kmem.h
index 5ed0faac87c..fd341e0a8f8 100644
--- a/src/devices/bus/ti99/peb/ti_32kmem.h
+++ b/src/devices/bus/ti99/peb/ti_32kmem.h
@@ -19,27 +19,27 @@
#include "peribox.h"
#include "machine/ram.h"
-namespace bus { namespace ti99 { namespace peb {
+namespace bus::ti99::peb {
class ti_32k_expcard_device : public device_t, public device_ti99_peribox_card_interface
{
public:
ti_32k_expcard_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
- DECLARE_READ8Z_MEMBER(readz) override;
+ void readz(offs_t offset, uint8_t *value) override;
void write(offs_t offset, uint8_t data) override;
- DECLARE_READ8Z_MEMBER(crureadz) override { }
+ void crureadz(offs_t offset, uint8_t *value) override { }
void cruwrite(offs_t offset, uint8_t data) override { }
protected:
- void device_start() override;
- virtual void device_add_mconfig(machine_config &config) override;
+ void device_start() override ATTR_COLD;
+ virtual void device_add_mconfig(machine_config &config) override ATTR_COLD;
private:
required_device<ram_device> m_ram;
};
-} } } // end namespace bus::ti99::peb
+} // end namespace bus::ti99::peb
DECLARE_DEVICE_TYPE_NS(TI99_32KMEM, bus::ti99::peb, ti_32k_expcard_device)
diff --git a/src/devices/bus/ti99/peb/ti_fdc.cpp b/src/devices/bus/ti99/peb/ti_fdc.cpp
index 0e293c41401..3daeb24d41f 100644
--- a/src/devices/bus/ti99/peb/ti_fdc.cpp
+++ b/src/devices/bus/ti99/peb/ti_fdc.cpp
@@ -17,24 +17,24 @@
#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_NS(TI99_FDC, bus::ti99::peb, ti_fdc_device, "ti99_fdc", "TI-99 Standard DSSD Floppy Controller")
+DEFINE_DEVICE_TYPE(TI99_FDC, bus::ti99::peb::ti_fdc_device, "ti99_fdc", "TI-99 Standard DSSD Floppy Controller")
-namespace bus { namespace ti99 { namespace peb {
+namespace bus::ti99::peb {
// ----------------------------------
#define FDC_TAG "fd1771"
@@ -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,33 +80,33 @@ 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);
}
-SETADDRESS_DBIN_MEMBER( ti_fdc_device::setaddress_dbin )
+void ti_fdc_device::setaddress_dbin(offs_t offset, int state)
{
// Selection login in the PAL and some circuits on the board
// Is the card being selected?
m_address = offset;
- m_inDsrArea = ((m_address & m_select_mask)==m_select_value);
+ m_inDsrArea = in_dsr_space(offset, true);
if (!m_inDsrArea || !m_selected) return;
@@ -124,14 +125,14 @@ SETADDRESS_DBIN_MEMBER( ti_fdc_device::setaddress_dbin )
*/
void ti_fdc_device::debug_read(offs_t offset, uint8_t* value)
{
- if (((offset & m_select_mask)==m_select_value) && m_selected)
+ if (in_dsr_space(offset, true) && m_selected)
{
if ((offset & 0x1ff1)!=0x1ff0)
*value = m_dsrrom[offset & 0x1fff];
}
}
-READ8Z_MEMBER(ti_fdc_device::readz)
+void ti_fdc_device::readz(offs_t offset, uint8_t *value)
{
if (machine().side_effects_disabled())
{
@@ -201,7 +202,7 @@ void ti_fdc_device::write(offs_t offset, uint8_t data)
See schematics for the meaning of the bits.
*/
-READ8Z_MEMBER(ti_fdc_device::crureadz)
+void ti_fdc_device::crureadz(offs_t offset, uint8_t *value)
{
if ((offset & 0xff00)==m_cru_base)
{
@@ -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());
}
}
}
@@ -349,16 +352,6 @@ void ti_fdc_device::device_start()
void ti_fdc_device::device_reset()
{
- if (m_genmod)
- {
- m_select_mask = 0x1fe000;
- m_select_value = 0x174000;
- }
- else
- {
- m_select_mask = 0x7e000;
- m_select_value = 0x74000;
- }
m_DRQ = CLEAR_LINE;
m_IRQ = CLEAR_LINE;
m_DVENA = CLEAR_LINE;
@@ -368,32 +361,24 @@ 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()
+void ti_fdc_device::floppy_formats(format_registration &fr)
{
- // 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());
+ fr.add_mfm_containers();
+ fr.add(FLOPPY_TI99_SDF_FORMAT);
+ fr.add(FLOPPY_TI99_TDF_FORMAT);
}
-FLOPPY_FORMATS_MEMBER(ti_fdc_device::floppy_formats)
- FLOPPY_TI99_SDF_FORMAT,
- FLOPPY_TI99_TDF_FORMAT
-FLOPPY_FORMATS_END
-
static void tifdc_floppies(device_slot_interface &device)
{
device.option_add("525dd", FLOPPY_525_DD);
@@ -412,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));
@@ -439,4 +424,4 @@ const tiny_rom_entry *ti_fdc_device::device_rom_region() const
return ROM_NAME( ti_fdc );
}
-} } } // end namespace bus::ti99::peb
+} // end namespace bus::ti99::peb
diff --git a/src/devices/bus/ti99/peb/ti_fdc.h b/src/devices/bus/ti99/peb/ti_fdc.h
index 3a54e0e7c7e..b176dbb8e57 100644
--- a/src/devices/bus/ti99/peb/ti_fdc.h
+++ b/src/devices/bus/ti99/peb/ti_fdc.h
@@ -22,46 +22,45 @@
#include "imagedev/floppy.h"
#include "machine/74123.h"
-namespace bus { namespace ti99 { namespace peb {
+namespace bus::ti99::peb {
class ti_fdc_device : public device_t, public device_ti99_peribox_card_interface
{
public:
ti_fdc_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
- DECLARE_READ8Z_MEMBER(readz) override;
+ void readz(offs_t offset, uint8_t *value) override;
void write(offs_t offset, uint8_t data) override;
- DECLARE_SETADDRESS_DBIN_MEMBER(setaddress_dbin) override;
+ void setaddress_dbin(offs_t offset, int state) override;
- DECLARE_READ8Z_MEMBER(crureadz) override;
+ void crureadz(offs_t offset, uint8_t *value) override;
void cruwrite(offs_t offset, uint8_t data) override;
// bool dvena_r();
protected:
- void device_start() override;
- void device_reset() override;
- void device_config_complete() override;
+ virtual void device_start() override ATTR_COLD;
+ virtual void device_reset() override ATTR_COLD;
- const tiny_rom_entry *device_rom_region() const override;
- virtual void device_add_mconfig(machine_config &config) override;
+ virtual const tiny_rom_entry *device_rom_region() const override ATTR_COLD;
+ virtual void device_add_mconfig(machine_config &config) override ATTR_COLD;
private:
- DECLARE_FLOPPY_FORMATS( floppy_formats );
+ 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,13 +104,13 @@ 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;
};
-} } } // end namespace bus::ti99::peb
+} // end namespace bus::ti99::peb
DECLARE_DEVICE_TYPE_NS(TI99_FDC, bus::ti99::peb, ti_fdc_device)
diff --git a/src/devices/bus/ti99/peb/ti_rs232.cpp b/src/devices/bus/ti99/peb/ti_rs232.cpp
index 1ebae489d3a..1005029b23c 100644
--- a/src/devices/bus/ti99/peb/ti_rs232.cpp
+++ b/src/devices/bus/ti99/peb/ti_rs232.cpp
@@ -105,24 +105,24 @@
#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_NS(TI99_RS232, bus::ti99::peb, ti_rs232_pio_device, "ti99_rs232", "TI-99 RS232/PIO interface")
-DEFINE_DEVICE_TYPE_NS(TI99_RS232_DEV, bus::ti99::peb, ti_rs232_attached_device, "ti99_rs232_atttached", "TI-99 Serial attached device")
-DEFINE_DEVICE_TYPE_NS(TI99_PIO_DEV, bus::ti99::peb, ti_pio_attached_device, "ti99_pio_attached", "TI-99 Parallel attached device")
+DEFINE_DEVICE_TYPE(TI99_RS232, bus::ti99::peb::ti_rs232_pio_device, "ti99_rs232", "TI-99 RS232/PIO interface")
+DEFINE_DEVICE_TYPE(TI99_RS232_DEV, bus::ti99::peb::ti_rs232_attached_device, "ti99_rs232_atttached", "TI-99 Serial attached device")
+DEFINE_DEVICE_TYPE(TI99_PIO_DEV, bus::ti99::peb::ti_pio_attached_device, "ti99_pio_attached", "TI-99 Parallel attached device")
-namespace bus { namespace ti99 { namespace peb {
+namespace bus::ti99::peb {
#define SENILA_0_BIT 0x80
#define SENILA_1_BIT 0x40
@@ -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;
}
/****************************************************************************/
@@ -238,7 +234,7 @@ void ti_pio_attached_device::call_unload()
/*
CRU read
*/
-READ8Z_MEMBER(ti_rs232_pio_device::crureadz)
+void ti_rs232_pio_device::crureadz(offs_t offset, uint8_t *value)
{
if ((offset & 0xff00)==m_cru_base)
{
@@ -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;
}
@@ -374,7 +370,7 @@ WRITE_LINE_MEMBER(ti_rs232_pio_device::led_w)
/*
Memory read
*/
-READ8Z_MEMBER( ti_rs232_pio_device::readz )
+void ti_rs232_pio_device::readz(offs_t offset, uint8_t *value)
{
if (m_senila==ASSERT_LINE)
{
@@ -387,7 +383,7 @@ READ8Z_MEMBER( ti_rs232_pio_device::readz )
// use of it
m_ila = 0;
}
- if (((offset & m_select_mask)==m_select_value) && m_selected)
+ if (in_dsr_space(offset, true) && m_selected)
{
if ((offset & 0x1000)==0x0000)
{
@@ -405,7 +401,7 @@ READ8Z_MEMBER( ti_rs232_pio_device::readz )
*/
void ti_rs232_pio_device::write(offs_t offset, uint8_t data)
{
- if (((offset & m_select_mask)==m_select_value) && m_selected)
+ if (in_dsr_space(offset, true) && m_selected)
{
if ((offset & 0x1001)==0x1000)
{
@@ -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);
}
@@ -1061,17 +1057,6 @@ void ti_rs232_pio_device::device_reset()
m_bufpos[0] = m_bufpos[1] = m_buflen[0] = m_buflen[1] = 0;
- if (m_genmod)
- {
- m_select_mask = 0x1fe000;
- m_select_value = 0x174000;
- }
- else
- {
- m_select_mask = 0x7e000;
- m_select_value = 0x74000;
- }
-
m_selected = false;
m_cru_base = (ioport("CRURS232")->read()==0)? 0x1300 : 0x1500;
@@ -1119,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));
@@ -1141,4 +1127,4 @@ ioport_constructor ti_rs232_pio_device::device_input_ports() const
return INPUT_PORTS_NAME(ti_rs232);
}
-} } } // end namespace bus::ti99::peb
+} // end namespace bus::ti99::peb
diff --git a/src/devices/bus/ti99/peb/ti_rs232.h b/src/devices/bus/ti99/peb/ti_rs232.h
index 3c3b1e89d4b..f985a04973d 100644
--- a/src/devices/bus/ti99/peb/ti_rs232.h
+++ b/src/devices/bus/ti99/peb/ti_rs232.h
@@ -19,7 +19,7 @@
#include "machine/74259.h"
#include "machine/tms9902.h"
-namespace bus { namespace ti99 { namespace peb {
+namespace bus::ti99::peb {
class ti_pio_attached_device;
class ti_rs232_attached_device;
@@ -31,38 +31,38 @@ class ti_rs232_pio_device : public device_t, public device_ti99_peribox_card_int
public:
ti_rs232_pio_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
- DECLARE_READ8Z_MEMBER(readz) override;
+ void readz(offs_t offset, uint8_t *value) override;
void write(offs_t offset, uint8_t data) override;
- DECLARE_READ8Z_MEMBER(crureadz) override;
+ void crureadz(offs_t offset, uint8_t *value) override;
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 ATTR_COLD;
+ virtual void device_reset() override ATTR_COLD;
+ virtual void device_stop() override ATTR_COLD;
+ virtual const tiny_rom_entry *device_rom_region() const override ATTR_COLD;
+ virtual void device_add_mconfig(machine_config &config) override ATTR_COLD;
+ virtual ioport_constructor device_input_ports() const override ATTR_COLD;
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);
@@ -133,19 +133,20 @@ class ti_rs232_attached_device : public device_t, public device_image_interface
public:
ti_rs232_attached_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
- iodevice_t image_type() const override { return IO_SERIAL; }
- bool is_readable() const override { return true; }
- bool is_writeable() const override { return true; }
- bool is_creatable() const override { return true; }
- bool must_be_loaded() const override { return false; }
- bool is_reset_on_load() const override { return false; }
- const char *image_interface() const override { return ""; }
- const char *file_extensions() const override { return ""; }
+ bool is_readable() const noexcept override { return true; }
+ bool is_writeable() const noexcept override { return true; }
+ bool is_creatable() const noexcept override { return true; }
+ bool is_reset_on_load() const noexcept override { return false; }
+ bool support_command_line_image_creation() const noexcept override { return true; }
+ const char *image_type_name() const noexcept override { return "serial"; }
+ const char *image_brief_type_name() const noexcept override { return "serl"; }
+ const char *image_interface() const noexcept override { return ""; }
+ const char *file_extensions() const noexcept override { return ""; }
void connect(tms9902_device *dev) { m_uart = dev; }
protected:
- void device_start() override { };
- image_init_result call_load() override;
+ void device_start() override { }
+ std::pair<std::error_condition, std::string> call_load() override;
void call_unload() override;
private:
@@ -158,25 +159,31 @@ 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);
- iodevice_t image_type() const override { return IO_PARALLEL; }
- bool is_readable() const override { return true; }
- bool is_writeable() const override { return true; }
- bool is_creatable() const override { return true; }
- bool must_be_loaded() const override { return false; }
- bool is_reset_on_load() const override { return false; }
- const char *image_interface() const override { return ""; }
- const char *file_extensions() const override { return ""; }
+ bool is_readable() const noexcept override { return true; }
+ bool is_writeable() const noexcept override { return true; }
+ bool is_creatable() const noexcept override { return true; }
+ bool is_reset_on_load() const noexcept override { return false; }
+ bool support_command_line_image_creation() const noexcept override { return true; }
+ const char *image_type_name() const noexcept override { return "parallel"; }
+ const char *image_brief_type_name() const noexcept override { return "parl"; }
+ const char *image_interface() const noexcept override { return ""; }
+ const char *file_extensions() const noexcept override { return ""; }
protected:
- void device_start() override { };
- image_init_result call_load() override;
+ void device_start() 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
+} // end namespace bus::ti99::peb
DECLARE_DEVICE_TYPE_NS(TI99_RS232, bus::ti99::peb, ti_rs232_pio_device)
DECLARE_DEVICE_TYPE_NS(TI99_RS232_DEV, bus::ti99::peb, ti_rs232_attached_device)
diff --git a/src/devices/bus/ti99/peb/tipi.cpp b/src/devices/bus/ti99/peb/tipi.cpp
new file mode 100644
index 00000000000..a7eb3d31bd1
--- /dev/null
+++ b/src/devices/bus/ti99/peb/tipi.cpp
@@ -0,0 +1,739 @@
+// license:LGPL-2.1+
+// copyright-holders:Michael Zapf
+/****************************************************************************
+
+ TIPI adapter card
+ designed and realized by Matthew Splett (aka jedimatt42), Peter and others
+
+ The TIPI system (pronouced "tipee") is an expansion for the TI-99/4A and
+ other computers of this family. It consists of a Raspberry Pi computer
+ attached to an adapter card that fits into the PEB (Peripheral Expansion
+ Box) or to the console side connector.
+
+ The adapter card provides an interface between the TI system and the
+ Raspberry Pi, in particular for exchanging files. More than that, features
+ of the Raspberry like network connectivity, may be offered to the TI
+ system.
+
+ The general concept is that there is a set of memory-mapped ports between
+ the TI and the Raspberry Pi.
+
+ 0x5ff9 (RC): PI Control Signal (input from RPi)
+ 0x5ffb (RD): PI Data (input)
+ 0x5ffd (TC): TI Control Signal (output to RPi)
+ 0x5fff (TD): TI Data (output)
+
+ CRU map
+ -------
+ 1x00: Activate the card and its ROM (x=0...f)
+ 1x02: Send RESET to Raspberry Pi
+
+ TI-TIPI protocol [2]
+ --------------------
+
+ Byte layer protocol
+ ----------------
+ Reset-sync:
+ TI: rs -> TC rs = f1
+ PI: (TC==rs) rs -> RC
+ PIemu: (TC==rs) rs -> RC; (mode==sync) send("SYNC")
+
+ Write-byte(byte):
+ TI: byte -> TD
+ wb -> TC wb = 02 / 03 (alternating)
+ PI: (TC==wb) send (TD); (TC) -> RC
+ PIemu: (TC==wb) q.append(TD); (TC) -> RC
+
+
+ byte=Read-byte:
+ TI: rb -> TC rb = 06 / 07 (alternating)
+ (RC==rb) return (RD)
+ PI: (TC==rb) byte -> RD; (TC) -> RC
+ PIemu: (TC==rb) (q.length > 0) q.pop -> RD; (TC) -> RC
+
+ Message layer protocol
+ ----------------------
+ Send-message(c1,c2,...,cn), n = (n1<<8)+n2:
+ Write-byte(n1)
+ Write-byte(n2)
+ for i=1..n: Write-byte(c[i])
+
+ (c1,...cn) = Receive-message:
+ n1=Read-byte
+ n2=Read-byte
+ for i=1..(n1<<8)+n2: c[i] = Read-byte
+
+ Communication layer protocol
+ ----------------------------
+ Communication:
+ Reset-sync
+ Send-message(ms)
+ rm = Receive-message
+
+ Emulation adaptation
+ --------------------
+ Send-messageEmu(c1,c2,...,cn), n = (n1<<8)+n2:
+ Write-byte(n1)
+ Write-byte(n2)
+ for i=1..n: Write-byte(c[i])
+ send(q.content)
+
+
+ Raspberry connection
+ --------------------
+ The good thing in terms of emulation is that the Raspberry Pi is completely
+ outside of the emulation. It allows for connecting via a WebSocket, which
+ is especially provided for emulators. In the real machine, the Raspberry Pi
+ gets the data from the adapter card.
+
+ It is recommended to run a virtual Raspberry Pi as a QEMU image. An image
+ is available on the TIPI website.
+
+ The connection is specified by -conn rpi.<hostname>[:<port>],
+ like "-conn rpi.localhost" or "-conn rpi.some.host.net"
+
+ This will create a file in the current directory of that name, which is
+ a side effect of the MAME image handling. The port default is 9901.
+
+
+ Mouse support
+ -------------
+ The websocket server accepts messages for mouse movements and button actions
+ from the mouse input of the connected emulator. However, in MAME, mouse
+ input is only available if there is a proper mouse device, like the busmouse
+ or the Mechatronics mouse. Hence, we cannot send any mouse input to the
+ Raspberry without one of these mice connected.
+
+ However, if a mouse is connected to the real or virtual Raspberry Pi,
+ the mouse operations can be polled from the Raspberry in the
+ intended way.
+
+ Logging
+ -------
+ Since we use a background thread for the websocket client, and logging
+ is not thread-safe, log output may look broken at some times (in particular
+ when setting the LOG_PORTS flag).
+
+
+ Michael Zapf
+ March 20222
+
+ References
+
+ [1] TIPI description on Github: https://github.com/jedimatt42/tipi
+ [2] TIPI Protocol: https://github.com/jedimatt42/tipi/wiki/TIPI-Protocol
+
+*****************************************************************************/
+
+#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_RECV (1U << 6)
+#define LOG_SEND (1U << 7)
+#define LOG_PROT (1U << 8)
+
+#define VERBOSE (LOG_GENERAL | LOG_WARN)
+#define RASPI "rpi"
+
+#define PAUSEBASE 1000
+
+#include "logmacro.h"
+
+DEFINE_DEVICE_TYPE(TI99_TIPI, bus::ti99::peb::tipi_card_device, "ti99_tipi", "TIPI card")
+DEFINE_DEVICE_TYPE(TI99_TIPI_RPI, bus::ti99::peb::tipi_attached_device, "ti99_tipi_atttached", "Connection to external device")
+
+namespace bus::ti99::peb {
+
+tipi_card_device::tipi_card_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) :
+ device_t(mconfig, TI99_TIPI, tag, owner, clock),
+ device_ti99_peribox_card_interface(mconfig, *this),
+ m_rpi(*this, RASPI),
+ m_address(0),
+ m_dsr(false),
+ m_portaccess(false),
+ m_waitinit(false),
+ m_syncmode(true),
+ m_connected(false),
+ m_rpiconn(false),
+ m_pausetime(PAUSEBASE),
+ m_pending_read(false),
+ m_tc(0),
+ m_rd(0)
+{
+}
+
+void tipi_card_device::setaddress_dbin(offs_t offset, int state)
+{
+ if (machine().side_effects_disabled()) return;
+ m_address = offset;
+ m_dsr = false;
+ m_portaccess = false;
+
+ if (in_dsr_space(offset, true) && m_selected)
+ {
+ m_portaccess = ((offset & 0x1ff8)==0x1ff8);
+ m_dsr = !m_portaccess;
+ }
+}
+
+void tipi_card_device::readz(offs_t offset, uint8_t *value)
+{
+ if (machine().side_effects_disabled())
+ {
+ debug_read(offset, value);
+ return;
+ }
+
+ if (m_dsr)
+ {
+ // Lines A0-A12 directly connected to the EPROM (chip pin order)
+ // Lines A13-A15 connected to PLD (currently not used)
+ int base = 0;
+ uint8_t* rom = &m_eprom[base | (m_address & 0x1fff)];
+ *value = *rom;
+
+ if (WORD_ALIGNED(m_address))
+ {
+ // Do logging by 16 bit words, as we typically have instructions in
+ // the eprom
+ uint16_t val = (*rom << 8) | (*(rom+1));
+ LOGMASKED(LOG_EPROM, "DSR: %04x -> %04x\n", m_address & 0xffff, val);
+ }
+ }
+
+ if (m_portaccess)
+ {
+ if ((m_address & 5)==1)
+ {
+ int val = 0;
+ if (m_address & 2)
+ {
+ val = get_rd();
+ LOGMASKED(LOG_PORTS, "RD -> %02x\n", m_rd);
+ }
+ else
+ {
+ val = m_rc;
+ LOGMASKED(LOG_PORTS, "RC -> %02x\n", val);
+ }
+ *value = val;
+ }
+ }
+}
+
+void tipi_card_device::write(offs_t offset, uint8_t data)
+{
+ if (machine().side_effects_disabled())
+ {
+ debug_write(offset, data);
+ return;
+ }
+
+ if (m_dsr)
+ {
+ LOGMASKED(LOG_WARN, "Writing to DSR space: %04x <- %02x\n", m_address & 0xffff, data);
+ }
+
+ if (m_portaccess)
+ {
+ if (m_address & 1)
+ {
+ if (m_address & 2)
+ {
+ LOGMASKED(LOG_PORTS, "TD <- %02x\n", data);
+ m_td = data;
+ }
+ else
+ {
+ set_tc(data);
+ }
+ }
+ }
+}
+
+/*
+ Debugger access.
+*/
+void tipi_card_device::debug_read(offs_t offset, uint8_t* value)
+{
+ int base = 0;
+ if (in_dsr_space(offset, true) && m_selected)
+ {
+ if ((offset & 0x1ff8)!=0x1ff8) // not in mapping area
+ {
+ uint8_t* rom = &m_eprom[base | (offset & 0x1fff)];
+ *value = *rom;
+ }
+ }
+}
+
+/*
+ Debugger access.
+*/
+void tipi_card_device::debug_write(offs_t offset, uint8_t data)
+{
+ // No write allowed
+}
+
+/*
+ CRU read access
+*/
+void tipi_card_device::crureadz(offs_t offset, uint8_t *value)
+{
+ // No CRU read
+}
+
+/*
+ CRU write access.
+*/
+void tipi_card_device::cruwrite(offs_t offset, uint8_t data)
+{
+ if ((offset & 0xff00) == m_cru_base)
+ {
+ int bit = (offset >> 1) & 0x1f;
+ switch (bit)
+ {
+ case 0: // card activation
+ LOGMASKED(LOG_CRU, "DSR %s\n", (data!=0)? "on" : "off");
+ m_selected = (data != 0);
+ break;
+ case 1:
+ LOGMASKED(LOG_CRU, "CRU Bit 1 %s\n", (data!=0)? "on" : "off");
+ if (data != 0)
+ {
+ LOGMASKED(LOG_RPI, "Sending RESET\n");
+ send("RESET");
+ }
+ break;
+ default:
+ LOGMASKED(LOG_CRU, "Unknown CRU Bit %d\n", bit);
+ break;
+ }
+ }
+}
+
+u8 tipi_card_device::get_rd()
+{
+ // Prevent a read access to RD while RD and RC are being
+ // changed by the websocket client. It should suffice to guard RD.
+ const std::lock_guard<std::mutex> lock(m_mutex);
+ return m_rd;
+}
+
+void tipi_card_device::send(const char* message)
+{
+ if (m_rpiconn && m_connected)
+ {
+ *m_send_stream << message;
+ m_wsclient->send(m_send_stream);
+ }
+}
+
+void tipi_card_device::send(u8* message, int len)
+{
+ if (m_rpiconn && m_connected)
+ {
+ for (int i=0; i < len; i++)
+ {
+ LOGMASKED(LOG_SEND, "Sending byte %02x\n", message[i]);
+ *m_send_stream << message[i];
+ }
+ m_wsclient->send(m_send_stream, nullptr, 130); // binary (10000010)
+ }
+}
+
+enum
+{
+ TSWB = 0x02,
+ TSRB = 0x06,
+ TSRSET = 0xf1
+};
+
+/*
+ Process the command submitted to the TC register.
+ The TSRSET only sends a sync to the Pi in sync mode; the current TIPI
+ implementation normally uses the async mode.
+
+ Apart from that, TSRSET resets the pointers in preparation of getting a
+ received message or composing a message to be sent.
+
+ TSWB: Write a byte. Instead of sending single bytes, the message is composed
+ in an array and sent when it is complete.
+ TSRB: Read a byte. This requires a message to be available in the input
+ queue. If the queue is empty, the read operation is not acknowledged.
+ This is done in websocket_incoming.
+*/
+void tipi_card_device::set_tc(u8 command)
+{
+ // Synchronize between websocket client and main thread
+ const std::lock_guard<std::mutex> lock(m_mutex);
+
+ LOGMASKED(LOG_PORTS, "TC <- %02x\n", command);
+
+ // Only call once for the same value
+ if (m_tc == command) return;
+
+ m_tc = command;
+
+ switch (m_tc)
+ {
+ case TSRSET:
+ LOGMASKED(LOG_PROT, "TSRSET\n");
+ m_rpimessage = nullptr;
+ m_msgindex = -2;
+ m_rc = m_tc;
+ m_tc = 0;
+
+ if (m_syncmode)
+ {
+ LOGMASKED(LOG_PROT, "Sending SYNC\n");
+ send("SYNC"); // only for SYNC mode
+ }
+ break;
+
+ case TSWB:
+ case TSWB+1:
+ if (m_msgindex == -2)
+ m_msglength = m_td << 8;
+ else
+ {
+ if (m_msgindex == -1)
+ {
+ m_msglength |= m_td;
+ m_rpimessage = std::make_unique<u8[]>(m_msglength);
+ }
+ else
+ if (m_rpimessage != nullptr)
+ m_rpimessage[m_msgindex] = m_td;
+ }
+
+ m_msgindex++;
+
+ if (m_msgindex == m_msglength)
+ {
+ // Message is complete - transmit it
+ LOGMASKED(LOG_RPI, "Sending message, length %d\n", m_msglength);
+ send(m_rpimessage.get(), m_msglength);
+ }
+
+ m_rc = m_tc; // Auto-acknowledge
+ break;
+
+ case TSRB:
+ case TSRB+1:
+ if (!m_indqueue.empty())
+ {
+ m_rc = m_tc; // Auto-acknowledge
+ m_rd = m_indqueue.front();
+ m_indqueue.pop();
+ }
+ else
+ {
+ // We have to wait for the TIPI to send more data
+ LOGMASKED(LOG_PROT, "Pending read\n");
+ m_pending_read = true;
+ }
+ break;
+ }
+}
+
+/*
+ Syntax for connecting is
+ -conn rpi.<host>[:<port>]
+
+ Default for port is 9901.
+*/
+TIMER_CALLBACK_MEMBER(tipi_card_device::open_websocket)
+{
+ if (m_rpiconn)
+ {
+ // We are just interested in the file name
+ // Cannot call it "socket.xxx" because this will make sdlsocket open
+ // the connection
+ std::string sconn(m_rpi->filename());
+ int pos = sconn.find("rpi.");
+
+ if (pos != -1)
+ {
+ std::string shost(sconn.substr(pos + 4));
+ if (shost.find(":")==-1)
+ shost += ":9901";
+
+ shost += "/tipi";
+
+ LOG("Trying to connect to Raspberry Pi at %s\n", shost.c_str());
+
+ m_wsclient = std::make_unique<webpp::ws_client>(shost);
+ webpp::ws_client* wsc = m_wsclient.get();
+ wsc->on_open =
+ [this]()
+ { websocket_opened(); };
+
+ wsc->on_message =
+ [this](std::shared_ptr<webpp::ws_client::Message> message)
+ { websocket_incoming(message); };
+
+ wsc->on_close =
+ [this](int i, const std::string& msg)
+ { websocket_closed(i, msg); };
+
+ wsc->on_error =
+ [this](const std::error_code& code)
+ { websocket_error(code); };
+
+ m_send_stream = std::make_shared<webpp::ws_client::SendStream>();
+
+ asio::thread listener([this]()
+ { m_wsclient->start(); });
+ }
+ else
+ fatalerror("Invalid TIPI connection address. Syntax: -conn rpi.<host>[:<port>]\n");
+ }
+}
+
+void tipi_card_device::websocket_opened()
+{
+ LOG("Connection established\n");
+ m_connected = true;
+ m_rc = 0;
+ m_pausetime = PAUSEBASE;
+ if (m_waitinit) m_slot->set_ready(ASSERT_LINE);
+}
+
+void tipi_card_device::websocket_incoming(std::shared_ptr<webpp::ws_client::Message> message)
+{
+ // Synchronize between websocket client and main thread
+ const std::lock_guard<std::mutex> lock(m_mutex);
+
+ // Caution: Message is an istream, so the string method consumes the Message
+ // Size is not changed, nor is fin_rsv_opcode
+ std::string msg;
+
+ switch (message->fin_rsv_opcode & 0x0f)
+ {
+ case 1:
+ msg = message->string();
+ // Text message is "RD=xxx" or "RC=xxx" with xxx=decimal number
+
+ LOGMASKED(LOG_RPI, "Got text message: %s\n", msg);
+
+ if (msg.find("RD=")==0)
+ {
+ m_indqueue.push(std::stoi(message->string().substr(3)));
+ }
+ if (msg.find("RC=")==0)
+ {
+ m_rc = std::stoi(message->string().substr(3));
+ }
+ if (msg.find("ASYNC")==0)
+ {
+ LOGMASKED(LOG_PROT, "TIPI server offers ASYNC communication\n");
+ m_syncmode = false;
+ }
+ break;
+
+ case 2:
+ LOGMASKED(LOG_RPI, "Got binary message, length %d\n", message->size());
+ // Enqueue the incoming message
+ // as n1 n2 msg, where n1 and n2 are the length of the message,
+ // and msg is the byte sequence of the message.
+ {
+ u8 len1 = (message->size()>>8) & 0xff;
+ u8 len2 = message->size() & 0xff;
+ m_indqueue.push(len1);
+ LOGMASKED(LOG_RECV, "<- %02x (len1) [%d]\n", len1, m_indqueue.size());
+ m_indqueue.push(len2);
+ LOGMASKED(LOG_RECV, "<- %02x (len2) [%d]\n", len2, m_indqueue.size());
+ }
+
+ for (int i=0; i < message->size(); i++)
+ {
+ u8 msgbyte = (u8)message->get();
+ m_indqueue.push(msgbyte);
+ LOGMASKED(LOG_RECV, "<- %02x [%d]\n", msgbyte, m_indqueue.size());
+ }
+
+ LOGMASKED(LOG_PROT, "Queue length: %d\n", m_indqueue.size());
+
+ if (m_pending_read)
+ {
+ LOGMASKED(LOG_PROT, "Serving pending read\n");
+ m_rc = m_tc; // Auto-acknowledge
+ m_rd = m_indqueue.front();
+ m_indqueue.pop();
+ m_pending_read = false;
+ }
+
+ break;
+
+ default:
+ LOGMASKED(LOG_RPI, "Got unknown message\n");
+ break;
+ }
+}
+
+void tipi_card_device::websocket_error(const std::error_code& code)
+{
+ m_pausetime = m_pausetime*2;
+ m_attempts--;
+
+ if (m_attempts > 0)
+ {
+ if (code.value() == std::make_error_code(std::errc::connection_reset).value())
+ {
+ LOGMASKED(LOG_WARN, "Error, connection reset. Retrying after %d secs.\n", m_pausetime/1000);
+ }
+ else
+ {
+ // End-of-file (2) occurs when the Pi is rebooted
+ LOGMASKED(LOG_WARN, "Got error: %s (%d); retrying after %d secs\n", code.message().c_str(), code.value(), m_pausetime/1000);
+ // Reconnection is not implemented on the Pi side for emulations,
+ // so this may cause the config program to wait forever
+ // Needs to be documented
+ }
+ m_restart_timer->adjust(attotime::from_msec(m_pausetime));
+ }
+ else
+ {
+ LOGMASKED(LOG_WARN, "Unable to re-establish connection to TIPI; giving up\n");
+ m_connected = false;
+ }
+}
+
+void tipi_card_device::websocket_closed(int i, const std::string& msg)
+{
+ LOG("Closing connection; retrying after %d secs\n", m_pausetime/1000);
+ if (m_waitinit) m_slot->set_ready(CLEAR_LINE);
+ // Open it again
+ m_restart_timer->adjust(attotime::from_msec(m_pausetime));
+ m_attempts = 8;
+}
+
+void tipi_card_device::device_start()
+{
+ m_eprom = memregion(TI99_DSRROM)->base();
+ save_item(NAME(m_address));
+ save_item(NAME(m_dsr));
+ save_item(NAME(m_portaccess));
+ save_item(NAME(m_msgindex));
+ save_item(NAME(m_msglength));
+ save_item(NAME(m_attempts));
+ save_item(NAME(m_connected));
+ save_item(NAME(m_tc));
+ save_item(NAME(m_td));
+ save_item(NAME(m_rc));
+ save_item(NAME(m_lasttc));
+
+ m_restart_timer = timer_alloc(FUNC(tipi_card_device::open_websocket), this);
+ m_rpiconn = (m_rpi->exists());
+ m_connected = false;
+}
+
+void tipi_card_device::device_reset()
+{
+ m_cru_base = (ioport("SW1")->read()) << 8;
+ m_waitinit = (ioport("WAIT")->read()!=0);
+ m_syncmode = true;
+ m_address = 0;
+ m_dsr = false;
+ m_portaccess = false;
+ m_pausetime = PAUSEBASE;
+ if (!m_rpiconn) LOGMASKED(LOG_WARN, "No Raspberry Pi connected\n");
+
+ // READY=0 is ignored at this point because the CPU is being reset at this time
+ m_lasttc = 0;
+ m_attempts = 8;
+ if (!m_connected) m_restart_timer->adjust(attotime::from_msec(m_pausetime));
+}
+
+void tipi_card_device::device_stop()
+{
+ // MZ: Without this I'm getting segfaults/list corruption
+ // when leaving the emulation
+ m_wsclient->stop();
+ LOG("Stopping TIPI\n");
+}
+
+/*
+ The CRU address base for the card.
+ For the Geneve OS version 7.30, CRU base 1800 is mandatory.
+*/
+INPUT_PORTS_START( tipi )
+ PORT_START("SW1")
+ PORT_DIPNAME(0x1f, 0x18, "CRU base")
+ PORT_DIPSETTING(0x10, "1000")
+ PORT_DIPSETTING(0x11, "1100")
+ PORT_DIPSETTING(0x12, "1200")
+ PORT_DIPSETTING(0x13, "1300")
+ PORT_DIPSETTING(0x14, "1400")
+ PORT_DIPSETTING(0x15, "1500")
+ PORT_DIPSETTING(0x16, "1600")
+ PORT_DIPSETTING(0x17, "1700")
+ PORT_DIPSETTING(0x18, "1800") // Default setting
+ PORT_DIPSETTING(0x19, "1900")
+ PORT_DIPSETTING(0x1a, "1a00")
+ PORT_DIPSETTING(0x1b, "1b00")
+ PORT_DIPSETTING(0x1c, "1c00")
+ PORT_DIPSETTING(0x1d, "1d00")
+ PORT_DIPSETTING(0x1e, "1e00")
+ PORT_DIPSETTING(0x1f, "1f00")
+ PORT_START("WAIT")
+ PORT_CONFNAME(0x01, 0x00, "Wait for initialization")
+ PORT_CONFSETTING( 0x00, DEF_STR( Off ) )
+ PORT_CONFSETTING( 0x01, DEF_STR( On ) )
+INPUT_PORTS_END
+
+void tipi_card_device::device_add_mconfig(machine_config &config)
+{
+ TI99_TIPI_RPI(config, m_rpi, 0);
+}
+
+ROM_START( tipi )
+ ROM_REGION(0x8000, TI99_DSRROM, 0)
+ 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
+
+
+const tiny_rom_entry *tipi_card_device::device_rom_region() const
+{
+ return ROM_NAME( tipi );
+}
+
+ioport_constructor tipi_card_device::device_input_ports() const
+{
+ return INPUT_PORTS_NAME( tipi );
+}
+
+/****************************************************************************/
+
+/* Connection to the external device, a Raspberry PI */
+
+tipi_attached_device::tipi_attached_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
+ : device_t(mconfig, TI99_TIPI_RPI, tag, owner, clock),
+ device_image_interface(mconfig, *this)
+{
+}
+
+/*
+ Initialize connection
+*/
+std::pair<std::error_condition, std::string> tipi_attached_device::call_load()
+{
+ return std::make_pair(std::error_condition(), std::string()); // OK
+}
+
+void tipi_attached_device::call_unload()
+{
+}
+
+
+} // end namespace bus::ti99::peb
diff --git a/src/devices/bus/ti99/peb/tipi.h b/src/devices/bus/ti99/peb/tipi.h
new file mode 100644
index 00000000000..2e5446cdaeb
--- /dev/null
+++ b/src/devices/bus/ti99/peb/tipi.h
@@ -0,0 +1,131 @@
+// license:LGPL-2.1+
+// copyright-holders:Michael Zapf
+/****************************************************************************
+
+ TIPI adapter card for the Peripheral Expansion Box
+ See tipi.cpp for documentation
+
+ Michael Zapf
+ February 2022
+
+*****************************************************************************/
+
+#ifndef MAME_BUS_TI99_PEB_TIPI_H
+#define MAME_BUS_TI99_PEB_TIPI_H
+
+#pragma once
+
+#include "peribox.h"
+#include "client_ws.hpp"
+
+#include <queue>
+#include <mutex>
+
+namespace bus::ti99::peb {
+
+class tipi_attached_device;
+
+class tipi_card_device : public device_t, public device_ti99_peribox_card_interface
+{
+
+public:
+ tipi_card_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
+ void readz(offs_t offset, uint8_t *value) override;
+ void write(offs_t offset, uint8_t data) override;
+ void setaddress_dbin(offs_t offset, int state) override;
+
+ void crureadz(offs_t offset, uint8_t *value) override;
+ void cruwrite(offs_t offset, uint8_t data) override;
+
+private:
+ void device_start() override ATTR_COLD;
+ void device_reset() override ATTR_COLD;
+ void device_stop() override;
+ ioport_constructor device_input_ports() const override;
+ const tiny_rom_entry *device_rom_region() const override;
+ void device_add_mconfig(machine_config &config) override;
+
+ void debug_read(offs_t offset, uint8_t* value);
+ void debug_write(offs_t offset, uint8_t data);
+
+ void websocket_opened();
+ void websocket_incoming(std::shared_ptr<webpp::ws_client::Message> message);
+ void websocket_error(const std::error_code& code);
+ void websocket_closed(int i, const std::string& msg);
+ void websocket_debug(const char* msg, int i);
+
+ TIMER_CALLBACK_MEMBER(open_websocket);
+
+ void send(const char* message);
+ void send(u8* message, int len);
+ u8 get_rd();
+ void set_tc(u8 data);
+
+ required_device<tipi_attached_device> m_rpi;
+
+ int m_address;
+ bool m_dsr;
+ bool m_portaccess;
+ bool m_waitinit;
+ bool m_syncmode;
+
+ // DSR ROM
+ uint8_t* m_eprom;
+
+ // Websocket support
+ std::unique_ptr<webpp::ws_client> m_wsclient;
+ std::shared_ptr<webpp::ws_client::SendStream> m_send_stream;
+ std::unique_ptr<u8[]> m_rpimessage;
+ int m_msgindex;
+ int m_msglength;
+ emu_timer* m_restart_timer;
+ int m_attempts;
+ bool m_connected;
+ bool m_rpiconn;
+ int m_pausetime;
+
+ // Incoming queue
+ std::queue<u8> m_indqueue;
+ std::mutex m_mutex;
+ bool m_pending_read;
+
+ // Computer interface
+ u8 m_tc;
+ u8 m_td;
+ u8 m_rc;
+ u8 m_rd;
+
+ u8 m_lasttc;
+};
+
+/*
+ Defines the connection to the RPi.
+*/
+class tipi_attached_device : public device_t, public device_image_interface
+{
+public:
+ tipi_attached_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
+
+ bool is_readable() const noexcept override { return true; }
+ bool is_writeable() const noexcept override { return true; }
+ bool is_creatable() const noexcept override { return true; }
+ bool is_reset_on_load() const noexcept override { return false; }
+ bool support_command_line_image_creation() const noexcept override { return true; }
+ const char *image_type_name() const noexcept override { return "connect"; }
+ const char *image_brief_type_name() const noexcept override { return "conn"; }
+ const char *image_interface() const noexcept override { return ""; }
+ const char *file_extensions() const noexcept override { return ""; }
+
+protected:
+ void device_start() override { }
+ void call_unload() override;
+ std::pair<std::error_condition, std::string> call_load() override;
+};
+
+
+} // end namespace bus::ti99::peb
+
+DECLARE_DEVICE_TYPE_NS(TI99_TIPI_RPI, bus::ti99::peb, tipi_attached_device)
+DECLARE_DEVICE_TYPE_NS(TI99_TIPI, bus::ti99::peb, tipi_card_device)
+
+#endif // MAME_BUS_TI99_PEB_TIPI_H
diff --git a/src/devices/bus/ti99/peb/tn_ide.cpp b/src/devices/bus/ti99/peb/tn_ide.cpp
index 4654a926791..43e3107e6c8 100644
--- a/src/devices/bus/ti99/peb/tn_ide.cpp
+++ b/src/devices/bus/ti99/peb/tn_ide.cpp
@@ -2,386 +2,741 @@
// copyright-holders:Michael Zapf
/****************************************************************************
- Thierry Nouspikel's IDE card emulation
+ IDE adapter card
+ designed by Thierry Nouspikel in 2001, revised in 2004
+
+ The IDE card is quite simple, since it only implements PIO transfer. A DMA
+ support was also included, requiring a separate card, which did not become
+ available.
+
+ Detailed descriptions can be found on Thierry Nouspikel's website. [1]
+
+ The card includes a clock chip to timestamp files, and a SRAM for the DSR.
+
+ SRAM: 512 KiB (may be battery-backed)
+
+ Four variants of the clock chip (since the 2004 revision):
+ - RTC-65271 (external SRAM, unbuffered)
+ - BQ4847 (external SRAM, buffered)
+ - BQ4842 (internal SRAM, 128K)
+ - BQ4847 (internal SRAM, 512K)
- This card is just a prototype. It has been designed by Thierry Nouspikel,
- and its description was published in 2001. The card has been revised in
- 2004.
+ The card does not contain any ROM. The firmware must be loaded into the
+ card or saved on the IDE drive. It is part of the IDEAL software package [2]
+ ("IDE Access Layer").
- The specs have been published in <http://www.nouspikel.com/ti99/ide.html>.
+ DIP switches
+ - SW1: SP3T switch, located on card area outside of the box
+ selects 16 bit (TI) or 21 bit (Geneve) address decoding or disables
+ the card
- The IDE interface is quite simple, since it only implements PIO transfer.
- The card includes a clock chip to timestamp files, and an SRAM for the DSR.
- It should be possible to use a battery backed DSR SRAM, but since the clock
- chip includes 4kb of battery-backed RAM, a bootstrap loader can be saved in
- the clock SRAM in order to load the DSR from the HD when the computer
- starts.
+ - SW2: DPDT switch, located at center of the card
+ selects TI (LSB/MSB) vs. Geneve byte order (MSB/LSB)
- Raphael Nabet, 2002-2004.
+ - SW3: 4xDIP, located near front edge, lower edge
+ A resets the RTC65271 chip to clear interrupts that occured while
+ the power was off (clock continues running)
+ Not implemented since the clock does not run outside of MAME
+ B selects whether clock or SRAM is mapped into the 4000 address space
+ on powerup. SRAM should only be mapped when it is battery-backed.
+ (Switches A and B may have changed position between revisions, or the
+ existing PCBs do not match the specification.)
+ C, D not used
- Michael Zapf
- September 2010: Rewritten as device
- February 2012: Rewritten as class
+ - SW4: 16-position rotary switch, located near front edge
+ selects second digit for CRU base address (1x00, x=0..F)
- FIXME: Completely untested and likely to be broken
+ The card supports a battery-backed or normal SRAM of 512KiB size. The battery
+ power may be taken from the clock chip (which offers a battery holder).
+
+ Suggested configuration procedure:
+ (The IDELOAD program is part of the IDEAL package.)
+
+ 1) Clock chips BQ4847, BQ4842, BQ4852
+ The IDELOAD program must be used to load the firmware into the SRAM.
+ Bootstrap code cannot be stored in the RTC. In order to activate the DSR
+ on next system startup, set the DIP switch to boot from SRAM.
+
+ 2) Clock chip RTC65271
+ The IDELOAD program must be used to load the firmware into the SRAM and
+ to install the bootstrap code in the clock memory. The bootstrap code
+ must be inactive until the IDEAL files have been copied on the hard disk.
+ Once this is done, the bootstrap code must be activated; it will load the
+ IDEAL files into the SRAM on each power-up of the system.
+
+ Memory map
+ ----------
+
+ CRU bit 0 == 1:
+ CRU bit 1 == DIP switch setting: (bit 1==0 on power-up, switch==0 when closed)
+ RTC65271:
+ 4000-401F: XRAM (32 bytes of page given in 4080)
+ 402x: RTC data register (mirrored)
+ 403x: RTC indirect address register (mirrored)
+ 408x,409x: Page register for XRAM (mirrored)
+ 40Ax: mirror of 402x
+ 40Bx: mirror of 403x
+
+ BQ4842/4852: (switch should be open (1) on power-up)
+ 4000-403F: not mapped
+ 4080-40BF: not mapped
+
+ BQ4847:
+ 4020-403F: Registers (even addresses, mirrored on address+1)
+
+ 4040-404E: CS1Fx read (IDE register group 1), mirrored at 40C0-40CE
+ 4050-405E: CS1Fx write (IDE register group 1), mirrored at 40D0-40DE
+ 4060-406E: CS3Fx read (IDE register group 2), mirrored at 40E0-40FE
+ 4070-407E: CS3Fx write (IDE register group 2), mirrored at 40F0-40FE
+
+ 4000-40FF: SRAM (CRU bit 1 != DIP switch setting)
+ 4100-4FFF: SRAM
+
+ 6000-7FFF: SRAM (CRU bit 4 == 1) [RAMBO support]
+
+ BQ4842/52: Clock registers are located at upper end of SRAM
+ BQ4842: page 0F (mirrored 1F, 2F, 3F)
+ BQ4852: page 3F
+
+ Write SRAM:
+ CRU bit 2 == 0:
+ normal write
+ CRU bit 2 == 1:
+ Set SRAM page nn/2 (address 40nn, mirrored in 4000-5FFF, 6000-7FFF)
+ CRU bit 5 == 1:
+ SRAM write protect
+
+ Original version by Raphael Nabet
+ Rewritten by Michael Zapf
+
+ References
+
+ [1] Th. Nouspikel: IDE Interface card version 2
+ https://www.unige.ch/medecine/nouspikel/ti99/ide2.htm
+
+ [2] Th. Nouspikel: Description of the IDEAL software.
+ https://www.unige.ch/medecine/nouspikel/ti99/ideal.htm
*****************************************************************************/
#include "emu.h"
#include "tn_ide.h"
-DEFINE_DEVICE_TYPE_NS(TI99_IDE, bus::ti99::peb, nouspikel_ide_interface_device, "ti99_ide", "Nouspikel IDE interface card")
+#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)
-namespace bus { namespace ti99 { namespace peb {
+#include "logmacro.h"
-#define CRU_BASE 0x1000
+DEFINE_DEVICE_TYPE(TI99_IDE, bus::ti99::peb::nouspikel_ide_card_device, "ti99_ide", "Nouspikel IDE interface card")
-#define RAMREGION "ram"
+#define CLOCK65_TAG "rtc65271"
+#define CLOCK47_TAG "bq4847"
+#define CLOCK42_TAG "bq4842"
+#define CLOCK52_TAG "bq4852"
+#define ATA_TAG "ata"
+#define LATCH_TAG "crulatch"
+#define ATALATCHEV_TAG "atalatch_even"
+#define ATALATCHODD_TAG "atalatch_odd"
+#define RAM512_TAG "sram512"
-/* previously 0xff */
-#define PAGE_MASK 0x3f
+namespace bus::ti99::peb {
enum
{
- cru_reg_page_switching = 0x04,
- cru_reg_page_0 = 0x08,
- /*cru_reg_rambo = 0x10,*/ /* not emulated */
- cru_reg_wp = 0x20,
- cru_reg_int_en = 0x40,
- cru_reg_reset = 0x80
+ MODE_OFF = 0,
+ MODE_GENEVE,
+ MODE_TI
};
-nouspikel_ide_interface_device::nouspikel_ide_interface_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) :
+enum
+{
+ RTC65 = 0,
+ RTC47,
+ RTC42,
+ RTC52
+};
+
+nouspikel_ide_card_device::nouspikel_ide_card_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) :
device_t(mconfig, TI99_IDE, tag, owner, clock),
device_ti99_peribox_card_interface(mconfig, *this),
- m_cru_register(0),
- m_rtc(*this, "ide_rtc"),
- m_ata(*this, "ata"),
- m_clk_irq(false), m_sram_enable(false),
- m_sram_enable_dip(false), m_cur_page(0), m_tms9995_mode(false),
- m_input_latch(0), m_output_latch(0), m_ram(*this, RAMREGION)
+ m_rtc65(*this, CLOCK65_TAG),
+ m_rtc47(*this, CLOCK47_TAG),
+ m_rtc42(*this, CLOCK42_TAG),
+ m_rtc52(*this, CLOCK52_TAG),
+ m_ata(*this, ATA_TAG),
+ m_sram(*this, RAM512_TAG),
+ m_crulatch(*this, LATCH_TAG),
+ m_latch0_7(*this, ATALATCHEV_TAG),
+ m_latch8_15(*this, ATALATCHODD_TAG),
+ m_ideint(false),
+ m_mode(MODE_OFF),
+ m_page(0),
+ m_rtctype(0),
+ m_genmod(false)
{
}
-/*
- CRU read
-*/
-READ8Z_MEMBER(nouspikel_ide_interface_device::crureadz)
+void nouspikel_ide_card_device::readz(offs_t offset, uint8_t *value)
{
- uint8_t reply = 0;
- if ((offset & 0xff00)==m_cru_base)
+ bool mmap = false;
+ bool sramsel = false;
+ bool xramsel = false;
+ bool rtcsel = false;
+ bool cs1fx = false;
+ bool cs3fx = false;
+
+ decode(offset, mmap, sramsel, xramsel, rtcsel, cs1fx, cs3fx);
+
+ bool idesel = cs1fx || cs3fx;
+
+ if (xramsel || rtcsel)
{
- if ((offset & 0x0070) == 0)
+ // Swap the address bits (TI numbering vs. standard)
+ // A8->A5, A15->A4, A14->A3, A13->A2, A12->A1, A11->A0
+ // .... .... 5..0 1234
+ // .... .... ..54 3210
+
+ // int addr = ((offset & 0x80)>>2) | ((offset & 1)<<4) | ((offset & 2)<<2)
+ // | (offset & 4) | ((offset & 8)>>2) | ((offset & 16)>>4);
+ // *value = m_rtc->read(xramsel, addr);
+ // LOGMASKED(LOG_RTC, "rtc %04x (%02x, %s) -> %02x\n", offset&0xffff, addr, xramsel? "xram" : "rtc", *value);
+
+ // However, We take the simple way and keep the address as is.
+ // This makes debugging less tedious.
+
+ if (rtcsel) // 4020-403F
{
- reply = m_cru_register & 0x30;
- reply |= 8; /* IDE bus IORDY always set */
- if (!m_clk_irq)
- reply |= 4;
- if (m_sram_enable_dip)
- reply |= 2;
- if (!m_ata_irq)
- reply |= 1;
+ if (m_rtctype==RTC65)
+ {
+ if ((offset&0x0010)!=0)
+ {
+ *value = m_rtc65->read(0, 1);
+ LOGMASKED(LOG_RTC, "rtc65 read -> %02x\n", *value);
+ }
+ }
+ else
+ {
+ if (m_rtctype==RTC47)
+ {
+ *value = m_rtc47->read((offset & 0x1e)>>1);
+ LOGMASKED(LOG_RTC, "rtc reg %02d (%04x) -> %02x\n", (offset & 0x1e)>>1, offset & 0xffff, *value);
+ }
+ // No reaction for RTC42, RTC52
+ }
+ }
+ else
+ {
+ if (m_rtctype==RTC65) // xram, only for 65271, unmapped for others
+ {
+ int addr = (offset & 0x1f) | ((offset&0x80)>>2);
+ *value = m_rtc65->read(1, addr);
+ LOGMASKED(LOG_XRAM, "xram %02x -> %02x\n", addr, *value);
+ }
}
- *value = BIT(reply, (offset >> 1) & 7);
}
-}
-/*
- CRU write
-*/
-void nouspikel_ide_interface_device::cruwrite(offs_t offset, uint8_t data)
-{
- if ((offset & 0xff00)==m_cru_base)
+ if (sramsel)
{
- int bit = (offset >>1) & 7;
- switch (bit)
- {
- case 0:
- m_selected = (data!=0);
+ int page = m_page;
+ // When addressing in 4000-4fff, and bit 3 = 0, lock page to 0
+ if (((offset & 0x3000)==0x0000) && m_crulatch->q3_r()==0)
+ page = 0;
- case 1: // enable SRAM or registers in 0x4000-0x40ff
- m_sram_enable = (data!=0);
- break;
+ offs_t addr = (offset & 0x1fff) | (page<<13);
- case 2: // enable SRAM page switching
- case 3: // force SRAM page 0
- case 4: // enable SRAM in 0x6000-0x7000 ("RAMBO" mode)
- case 5: // write-protect RAM
- case 6: // irq and reset enable
- case 7: // reset drive
- if (data!=0)
- m_cru_register |= 1 << bit;
+ if (m_rtctype==RTC65 || m_rtctype==RTC47)
+ {
+ *value = m_sram->read(addr); // external SRAM
+ }
+ else
+ {
+ // The BQ4842/52 offer SRAM by themselves
+ if (m_rtctype==RTC42)
+ *value = m_rtc42->read(addr);
else
- m_cru_register &= ~(1 << bit);
+ *value = m_rtc52->read(addr);
+ }
+ if (m_mode==MODE_TI)
+ {
+ if ((offset & 1)==0)
+ LOGMASKED(LOG_SRAM, "sram %04x (%02x) -> %04x\n", offset&0xffff, page, (*value<<8) | m_sram->read(addr+1));
+ }
+ }
- if (bit == 6)
- m_slot->set_inta((m_cru_register & cru_reg_int_en) && m_ata_irq);
+ if (idesel)
+ {
+ // Don't let the debugger mess with the latches
+ if (machine().side_effects_disabled())
+ {
+ *value = 0;
+ return;
+ }
- if ((bit == 6) || (bit == 7))
- if ((m_cru_register & cru_reg_int_en) && !(m_cru_register & cru_reg_reset))
- m_ata->reset();
- break;
+ int reg = (offset >> 1)&7;
+ bool even = ((offset & 1)==0);
+
+ // Geneve writes even/odd, TI writes odd/even
+ bool first = (even != (m_mode==MODE_TI));
+
+ m_latch0_7->leba_w(first? 0:1);
+ m_latch8_15->leba_w(first? 0:1);
+
+ uint16_t atavalue = 0;
+
+ // On the first read, get the 16-bit value
+ // but only when addressing in the area 4040-404F / 4060-406F
+ // (check A11=0). That way, Read-before-Write does not interfere
+ if (first && ((offset & 0x0010)==0))
+ {
+ if (cs1fx)
+ atavalue = m_ata->cs0_r(reg);
+ else
+ atavalue = m_ata->cs1_r(reg);
+ LOGMASKED(LOG_ATA, "%s %02x -> %04x\n", cs1fx? "cs1" : "cs3", reg, atavalue);
}
+
+ // Load latches (no change during second access)
+ m_latch0_7->b_w(atavalue&0xff);
+ m_latch8_15->b_w((atavalue >> 8)&0xff);
+
+ // Activate the respective latch
+ m_latch0_7->oeba_w(even? 0:1);
+ m_latch8_15->oeba_w(even? 1:0);
+
+ // Only one of them delivers a value, the other is Z
+ m_latch0_7->outputa_rz(*value);
+ m_latch8_15->outputa_rz(*value);
+
+ // Reads in the upper half are RBW and should be ignored
+ if ((offset & 0x0010)==0)
+ LOGMASKED(LOG_ATA, "ata %04x -> %02x\n", offset&0xffff, *value);
}
}
-/*
- Memory read
-*/
-READ8Z_MEMBER(nouspikel_ide_interface_device::readz)
+void nouspikel_ide_card_device::write(offs_t offset, uint8_t data)
{
- uint8_t reply = 0;
- if (machine().side_effects_disabled()) return;
+ bool mmap = false;
+ bool sramsel = false;
+ bool xramsel = false;
+ bool rtcsel = false;
+ bool cs1fx = false;
+ bool cs3fx = false;
+
+ decode(offset, mmap, sramsel, xramsel, rtcsel, cs1fx, cs3fx);
+ bool idesel = cs1fx || cs3fx;
- if (((offset & m_select_mask)==m_select_value) && m_selected)
+ if (xramsel || rtcsel)
{
- int addr = offset & 0x1fff;
+ // Swap the address bits (TI numbering vs. standard)
+ // Actually, this is almost irrelevant for the RTC access, since only
+ // A0 determines the mode.
+ // A8->A5, A15->A4, A14->A3, A13->A2, A12->A1, A11->A0
+ // .... .... 5..0 1234
+ // .... .... ..54 3210
+
+ // int addr = ((offset & 0x80)>>2) | ((offset & 1)<<4) | ((offset & 2)<<2)
+ // | (offset & 4) | ((offset & 8)>>2) | ((offset & 16)>>4);
+
+ // LOGMASKED(LOG_RTC, "rtc %04x (%02x, %s) <- %02x\n", offset&0xffff, addr, xramsel? "xram" : "rtc", data);
+ // m_rtc->write(xramsel, addr, data);
+
+ // See above (read), don't swap the lines.
- if ((addr <= 0xff) && (m_sram_enable == m_sram_enable_dip))
- { /* registers */
- switch ((addr >> 5) & 0x3)
+ if (rtcsel)
+ {
+ if (m_rtctype == RTC65)
{
- case 0: /* RTC RAM */
- if (addr & 0x80)
- /* RTC RAM page register */
- reply = m_rtc->xram_r((addr & 0x1f) | 0x20);
- else
- /* RTC RAM read */
- reply = m_rtc->xram_r(addr);
- break;
- case 1: /* RTC registers */
- if (addr & 0x10)
- /* register data */
- reply = m_rtc->rtc_r(1);
+ if ((offset&0x0010)==0)
+ {
+ m_rtc65->write(0, 0, data);
+ LOGMASKED(LOG_RTC, "rtc set <- %02x\n", data);
+ }
else
- /* register select */
- reply = m_rtc->rtc_r(0);
- break;
- case 2: /* IDE registers set 1 (CS1Fx) */
- if (m_tms9995_mode ? (!(addr & 1)) : (addr & 1))
- { /* first read triggers 16-bit read cycle */
- m_input_latch = (! (addr & 0x10)) ? m_ata->read_cs0((addr >> 1) & 0x7) : 0;
+ {
+ m_rtc65->write(0, 1, data);
+ LOGMASKED(LOG_RTC, "rtc write <- %02x\n", data);
}
-
- /* return latched input */
- /*reply = (addr & 1) ? input_latch : (input_latch >> 8);*/
- /* return latched input - bytes are swapped in 2004 IDE card */
- reply = ((addr & 1) ? (m_input_latch >> 8) : m_input_latch) & 0xff;
- break;
- case 3: /* IDE registers set 2 (CS3Fx) */
- if (m_tms9995_mode ? (!(addr & 1)) : (addr & 1))
- { /* first read triggers 16-bit read cycle */
- m_input_latch = (! (addr & 0x10)) ? m_ata->read_cs1((addr >> 1) & 0x7) : 0;
+ }
+ else
+ {
+ if (m_rtctype == RTC47)
+ {
+ LOGMASKED(LOG_RTC, "rtc reg %02d (%04x) <- %02x\n", (offset & 0x1e)>>1, offset & 0xffff, data);
+ m_rtc47->write((offset & 0x1e)>>1, data);
}
-
- /* return latched input */
- /*reply = (addr & 1) ? input_latch : (input_latch >> 8);*/
- /* return latched input - bytes are swapped in 2004 IDE card */
- reply = ((addr & 1) ? (m_input_latch >> 8) : m_input_latch) & 0xff;
- break;
+ // No reaction for RTC42, RTC52
}
}
else
- { /* sram */
- if ((m_cru_register & cru_reg_page_0) || (addr >= 0x1000))
- reply = m_ram->pointer()[addr+0x2000 * m_cur_page];
- else
- reply = m_ram->pointer()[addr];
+ {
+ if (m_rtctype==RTC65)
+ {
+ int addr = (offset & 0x1f) | ((offset&0x80)>>2);
+ m_rtc65->write(1, addr, data);
+
+ if (addr & 0x20)
+ LOGMASKED(LOG_XRAM, "xram set page %02x\n", data);
+ else
+ LOGMASKED(LOG_XRAM, "xram %02x <- %02x\n", addr & 0x1f, data);
+ }
}
- *value = reply;
}
-}
-
-/*
- Memory write. The controller is 16 bit, so we need to demultiplex again.
-*/
-void nouspikel_ide_interface_device::write(offs_t offset, uint8_t data)
-{
- if (machine().side_effects_disabled()) return;
- if (((offset & m_select_mask)==m_select_value) && m_selected)
+ if (sramsel)
{
- if (m_cru_register & cru_reg_page_switching)
+ if (m_crulatch->q2_r()==1)
{
- m_cur_page = (offset >> 1) & PAGE_MASK;
+ m_page = (offset & 0x007e)>>1;
+ LOGMASKED(LOG_SRAM, "sram page set %02x (%04x)\n", m_page, offset&0xffff);
}
- int addr = offset & 0x1fff;
+ // Software must ensure that CRU bit 5 is 1 (SRAM write protect)
+ // when bit 2 is 1 (page select)
+ if (m_crulatch->q5_r()==0)
+ {
+ int page = m_page;
- if ((addr <= 0xff) && (m_sram_enable == m_sram_enable_dip))
- { /* registers */
- switch ((addr >> 5) & 0x3)
- {
- case 0: /* RTC RAM */
- if (addr & 0x80)
- /* RTC RAM page register */
- m_rtc->xram_w((addr & 0x1f) | 0x20, data);
- else
- /* RTC RAM write */
- m_rtc->xram_w(addr, data);
- break;
- case 1: /* RTC registers */
- if (addr & 0x10)
- /* register data */
- m_rtc->rtc_w(1, data);
- else
- /* register select */
- m_rtc->rtc_w(0, data);
- break;
- case 2: /* IDE registers set 1 (CS1Fx) */
-/*
- if (addr & 1)
- m_output_latch = (m_output_latch & 0xff00) | data;
- else
- m_output_latch = (m_output_latch & 0x00ff) | (data << 8);
-*/
- /* latch write - bytes are swapped in 2004 IDE card */
- if (addr & 1)
- m_output_latch = (m_output_latch & 0x00ff) | (data << 8);
- else
- m_output_latch = (m_output_latch & 0xff00) | data;
+ // When addressing in 4000-4fff, and bit 3 = 0, lock page to 0
+ if (((offset & 0x3000)==0x0000) && m_crulatch->q3_r()==0)
+ page = 0;
- if (m_tms9995_mode ? (addr & 1) : (!(addr & 1)))
- { /* second write triggers 16-bit write cycle */
- m_ata->write_cs0((addr >> 1) & 0x7, m_output_latch);
- }
- break;
- case 3: /* IDE registers set 2 (CS3Fx) */
-/*
- if (addr & 1)
- m_output_latch = (m_output_latch & 0xff00) | data;
- else
- m_output_latch = (m_output_latch & 0x00ff) | (data << 8);
-*/
- /* latch write - bytes are swapped in 2004 IDE card */
- if (addr & 1)
- m_output_latch = (m_output_latch & 0x00ff) | (data << 8);
- else
- m_output_latch = (m_output_latch & 0xff00) | data;
+ offs_t addr = (offset & 0x1fff) | (page<<13);
- if (m_tms9995_mode ? (addr & 1) : (!(addr & 1)))
- { /* second write triggers 16-bit write cycle */
- m_ata->write_cs1((addr >> 1) & 0x7, m_output_latch);
- }
- break;
+ if (m_rtctype==RTC65 || m_rtctype==RTC47)
+ {
+ m_sram->write(addr, data);
}
- }
- else
- { /* sram */
- if (! (m_cru_register & cru_reg_wp))
+ else
{
- if ((m_cru_register & cru_reg_page_0) || (addr >= 0x1000))
- m_ram->pointer()[addr+0x2000 * m_cur_page] = data;
+ if (m_rtctype==RTC42)
+ m_rtc42->write(addr, data);
else
- m_ram->pointer()[addr] = data;
+ m_rtc52->write(addr, data);
}
+
+ LOGMASKED(LOG_SRAM, "sram %04x (%02x) <- %02x\n", offset&0xffff, page, data);
+ if ((offset & 0xfff0)==0x5ff0)
+ LOGMASKED(LOG_SRAMH, "sram %04x (%02x) <- %02x\n", offset&0xffff, page, data);
+ }
+ }
+
+ if (idesel)
+ {
+ // Don't let the debugger mess with the latches
+ if (machine().side_effects_disabled())
+ {
+ return;
+ }
+ LOGMASKED(LOG_ATA, "ata %04x <- %02x\n", offset&0xffff, data);
+
+ bool even = ((offset & 1)==0);
+ m_latch0_7->leab_w(even? 0:1);
+ m_latch8_15->leab_w(even? 1:0);
+
+ // Load the value into the respective latch
+ m_latch0_7->a_w(data);
+ m_latch8_15->a_w(data);
+
+ // Geneve writes even/odd, TI writes odd/even
+ bool first = (even != (m_mode==MODE_TI));
+
+ // Output on second access
+ m_latch0_7->oeab_w(first? 1:0);
+ m_latch8_15->oeab_w(first? 1:0);
+
+ // No output during the first access
+ int reg = (offset >> 1)&7;
+ uint8_t out = 0;
+ m_latch8_15->outputb_rz(out);
+ uint16_t atavalue = (out << 8);
+ m_latch0_7->outputb_rz(out);
+ atavalue |= out;
+
+ if (!first)
+ {
+ LOGMASKED(LOG_ATA, "%s %02x <- %04x\n", cs1fx? "cs1" : "cs3", reg, atavalue);
+
+ if (cs1fx)
+ m_ata->cs0_w(reg, atavalue);
+ else
+ m_ata->cs1_w(reg, atavalue);
}
}
}
-void nouspikel_ide_interface_device::do_inta(int state)
+void nouspikel_ide_card_device::decode(offs_t offset, bool& mmap, bool& sramsel, bool& xramsel, bool& rtcsel, bool& cs1fx, bool& cs3fx)
{
- m_slot->set_inta(state);
+ bool inspace = false;
+
+ // In a normal Geneve, assume AME=1, AMD=0
+ if (!m_genmod) offset = ((offset & 0x07ffff) | 0x100000);
+
+ // A0=0
+ if (m_mode == MODE_TI) inspace = ((offset & 0x8000)==0);
+ else
+ {
+ // AME=1, AMD=0, AMC/AMB/AMA=111, A0=0
+ if (m_mode == MODE_GENEVE) inspace = ((offset & 0x1f8000)==0x170000);
+ // else mode=off
+ }
+
+ // mmap = 0x4000 - 0x40ff (if bit 1 == DIP setting)
+ // sramsel = 0x4100 - 0x4fff (if bit 0 = 1) or 0x6000 - 0x7fff (if bit 4 = 1)
+
+ // A0 is not checked again (subsumed in inspace)
+
+ mmap = ((offset & 0x7f00)==0x4000) && (m_crulatch->q0_r()==1)
+ && ((m_crulatch->q1_r()!=0) == m_srammap) && inspace;
+ sramsel = ((((offset & 0x6000)==0x4000) && !mmap && (m_crulatch->q0_r()==1))
+ || (((offset & 0x6000)==0x6000) && (m_crulatch->q4_r()==1))) && inspace;
+
+ xramsel = false;
+ rtcsel = false;
+ cs1fx = false;
+ cs3fx = false;
+
+ if (mmap)
+ {
+ xramsel = ((offset & 0x60)==0x00); // 4000-401F, 4080 (only 65271)
+ rtcsel = ((offset & 0x60)==0x20); // 4020-403F (65271 and 4847)
+ cs1fx = ((offset & 0x60)==0x40); // 4040-405F
+ cs3fx = ((offset & 0x60)==0x60); // 4060-407F
+ }
}
/*
- ti99_ide_interrupt()
- IDE interrupt callback
+ CRU read access to the LS251 multiplexer.
*/
-WRITE_LINE_MEMBER(nouspikel_ide_interface_device::ide_interrupt_callback)
+void nouspikel_ide_card_device::crureadz(offs_t offset, uint8_t *value)
{
- m_ata_irq = state;
- if (m_cru_register & cru_reg_int_en)
- do_inta(state);
+ uint8_t bit = 0;
+
+ if ((offset & 0xff00)==m_cru_base)
+ {
+ switch ((offset>>1) & 0x07)
+ {
+ case 0:
+ bit = m_ideint? 1:0;
+ break;
+ case 1:
+ bit = m_srammap? 1:0;
+ break;
+ case 2:
+ bit = BIT(m_rtc_int, m_rtctype);
+ break;
+ case 3:
+ bit = 1;
+ break;
+ case 4:
+ bit = m_crulatch->q4_r();
+ break;
+ case 5:
+ bit = m_crulatch->q5_r();
+ break;
+ case 6:
+ case 7:
+ break;
+ }
+ *value = bit;
+ LOGMASKED(LOG_CRU, "cru %04x (bit %d) -> %d\n", offset, (offset & 0xff)>>1, bit);
+ }
}
/*
- clk_interrupt_callback()
- clock interrupt callback
+ CRU write access to the latch.
*/
-WRITE_LINE_MEMBER(nouspikel_ide_interface_device::clock_interrupt_callback)
+void nouspikel_ide_card_device::cruwrite(offs_t offset, uint8_t data)
{
- m_clk_irq = (state!=0);
- m_slot->set_inta(state);
-}
+ if ((offset & 0xff00)==m_cru_base)
+ {
+ // LOGMASKED(LOG_CRU, "cru %04x (bit %d) <- %d\n", offset, (offset & 0xff)>>1, data);
+ int bitnumber = (offset >> 1) & 0x07;
+ m_crulatch->write_bit(bitnumber, data&1);
-void nouspikel_ide_interface_device::device_start()
-{
- m_sram_enable_dip = false; // TODO: what is this?
-
- save_item(NAME(m_ata_irq));
- save_item(NAME(m_cru_register));
- save_item(NAME(m_clk_irq));
- save_item(NAME(m_sram_enable));
- save_item(NAME(m_sram_enable_dip));
- save_item(NAME(m_cur_page));
- save_item(NAME(m_tms9995_mode));
- save_item(NAME(m_input_latch));
- save_item(NAME(m_output_latch));
+#if 0
+ // Just debugging
+ switch (bitnumber)
+ {
+ case 0:
+ LOGMASKED(LOG_CRU, "Turn card %s\n", (data&1)? "on" : "off");
+ break;
+ case 1:
+ LOGMASKED(LOG_CRU, "Map %s at 4000-40FF\n", ((data&1)==m_srammap)? "register" : "SRAM");
+ break;
+ case 2:
+ LOGMASKED(LOG_CRU, "%s SRAM page\n", (data&1)? "Enable switch" : "Fixed");
+ break;
+ case 3:
+ LOGMASKED(LOG_CRU, "%s\n", (data&1)? "Same page at 4000-5FFF" : "Fix page 0 at 4000-4FFF");
+ break;
+ case 4:
+ LOGMASKED(LOG_CRU, "%s RAMBO\n", (data&1)? "Enable" : "Disable");
+ break;
+ case 5:
+ LOGMASKED(LOG_CRU, "Write %s SRAM\n", (data&1)? "protect" : "enable");
+ break;
+ case 6:
+ LOGMASKED(LOG_CRU, "%s IDE interrupt\n", (data&1)? "Enable" : "Disable");
+ break;
+ case 7:
+ LOGMASKED(LOG_CRU, "%s\n", (data&1)? "Reset drives" : "Normal operation");
+ break;
+ }
+#endif
+ }
}
-void nouspikel_ide_interface_device::device_reset()
+template<int rtctype>
+void nouspikel_ide_card_device::rtc_int_callback(int state)
{
- m_cur_page = 0;
- m_sram_enable = false;
- m_cru_register = 0;
-
- if (m_genmod)
- {
- m_select_mask = 0x1fe000;
- m_select_value = 0x174000;
- }
+ if (state)
+ m_rtc_int |= 1 << rtctype;
else
- {
- m_select_mask = 0x7e000;
- m_select_value = 0x74000;
- }
- m_selected = false;
+ m_rtc_int &= ~(1 << rtctype);
- m_cru_base = ioport("CRUIDE")->read();
- m_clk_irq = false;
+ if (rtctype == m_rtctype)
+ m_slot->set_inta(state ? CLEAR_LINE : ASSERT_LINE);
+}
- m_tms9995_mode = false; // (device->type()==TMS9995);
+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);
}
-INPUT_PORTS_START( tn_ide )
- PORT_START( "CRUIDE" )
- PORT_DIPNAME( 0x1f00, 0x1000, "IDE CRU base" )
- PORT_DIPSETTING( 0x1000, "1000" )
- PORT_DIPSETTING( 0x1100, "1100" )
- PORT_DIPSETTING( 0x1200, "1200" )
- PORT_DIPSETTING( 0x1300, "1300" )
- PORT_DIPSETTING( 0x1400, "1400" )
- PORT_DIPSETTING( 0x1500, "1500" )
- PORT_DIPSETTING( 0x1600, "1600" )
- PORT_DIPSETTING( 0x1700, "1700" )
- PORT_DIPSETTING( 0x1800, "1800" )
- PORT_DIPSETTING( 0x1900, "1900" )
- PORT_DIPSETTING( 0x1a00, "1A00" )
- PORT_DIPSETTING( 0x1b00, "1B00" )
- PORT_DIPSETTING( 0x1c00, "1C00" )
- PORT_DIPSETTING( 0x1d00, "1D00" )
- PORT_DIPSETTING( 0x1e00, "1E00" )
- PORT_DIPSETTING( 0x1f00, "1F00" )
-INPUT_PORTS_END
+void nouspikel_ide_card_device::resetdr_callback(int state)
+{
+ if (m_crulatch->q6_r()==1 && (state==0))
+ // not implemented
+ LOGMASKED(LOG_ATA, "Drive reset\n");
+}
-void nouspikel_ide_interface_device::device_add_mconfig(machine_config &config)
+void nouspikel_ide_card_device::device_add_mconfig(machine_config &config)
{
- RTC65271(config, m_rtc, 0);
- m_rtc->interrupt_cb().set(FUNC(nouspikel_ide_interface_device::clock_interrupt_callback));
+ // Choice of RTC chips
+ RTC65271(config, m_rtc65, 0);
+ BQ4847(config, m_rtc47, 0);
+ BQ4842(config, m_rtc42, 0);
+ BQ4852(config, m_rtc52, 0);
+
+ m_rtc65->interrupt_cb().set(FUNC(nouspikel_ide_card_device::rtc_int_callback<RTC65>)).invert();
+ m_rtc47->int_handler().set(FUNC(nouspikel_ide_card_device::rtc_int_callback<RTC47>));
+ m_rtc42->interrupt_cb().set(FUNC(nouspikel_ide_card_device::rtc_int_callback<RTC42>)).invert();
+ m_rtc52->interrupt_cb().set(FUNC(nouspikel_ide_card_device::rtc_int_callback<RTC52>)).invert();
ATA_INTERFACE(config, m_ata).options(ata_devices, "hdd", nullptr, false);
- m_ata->irq_handler().set(FUNC(nouspikel_ide_interface_device::ide_interrupt_callback));
+ m_ata->irq_handler().set(FUNC(nouspikel_ide_card_device::ide_interrupt_callback));
+
+ TTL74543(config, m_latch0_7, 0);
+ m_latch0_7->set_ceab_pin_value(0);
+ m_latch0_7->set_ceba_pin_value(0);
+
+ TTL74543(config, m_latch8_15, 0);
+ m_latch8_15->set_ceab_pin_value(0);
+ m_latch8_15->set_ceba_pin_value(0);
- RAM(config, m_ram);
- m_ram->set_default_size("512K");
- m_ram->set_default_value(0);
+ LS259(config, m_crulatch);
+ m_crulatch->q_out_cb<7>().set(FUNC(nouspikel_ide_card_device::resetdr_callback));
+
+ BUFF_RAM(config, RAM512_TAG, 0).set_size(512*1024);
}
-ioport_constructor nouspikel_ide_interface_device::device_input_ports() const
+void nouspikel_ide_card_device::device_start()
{
- return INPUT_PORTS_NAME(tn_ide);
+ save_item(NAME(m_ideint));
+ save_item(NAME(m_page));
+ save_item(NAME(m_rtc_int));
+}
+
+void nouspikel_ide_card_device::device_reset()
+{
+ int rtype[] = { RTC65, RTC47, RTC42, RTC52 };
+
+ m_page = 0;
+ m_ideint = false;
+ m_cru_base = (ioport("CRUIDE")->read() << 8) | 0x1000;
+ m_mode = ioport("MODE")->read();
+ m_srammap = (ioport("MAPMODE")->read()!=0);
+ m_rtctype = rtype[ioport("RTC")->read()];
+ m_genmod = (ioport("GENMOD")->read() != 0);
+
+ // The 65271 option does not support buffered SRAM; only the BQ4847
+ // can drive a buffered external RAM; the other two chips have internal SRAM
+ m_sram->set_buffered(m_rtctype == RTC47);
+
+ // Only activate the selected RTC
+ m_rtc47->set_unscaled_clock((ioport("RTC")->read()==1) ? 32768 : 0);
+ m_rtc42->connect_osc(ioport("RTC")->read()==2);
+ m_rtc52->connect_osc(ioport("RTC")->read()==3);
}
-} } } // end namespace bus::ti99::peb
+INPUT_CHANGED_MEMBER( nouspikel_ide_card_device::mode_changed )
+{
+ // Card mode changed
+ if (param==0)
+ m_srammap = (newval != 0);
+ else
+ m_mode = newval;
+}
+
+INPUT_PORTS_START( tn_ide )
+
+ PORT_START("RTC")
+ PORT_CONFNAME(0x03, 1, "RTC chip")
+ PORT_CONFSETTING(0, "RTC-65271")
+ PORT_CONFSETTING(1, "BQ4847 (ext SRAM)")
+ PORT_CONFSETTING(2, "BQ4842 (128K)")
+ PORT_CONFSETTING(3, "BQ4852 (512K)")
+
+ // When used in a normal Geneve, AME/AMD lines are set to (1,0)
+ PORT_START("GENMOD")
+ PORT_CONFNAME(0x01, 0, "Genmod decoding")
+ PORT_CONFSETTING(0, DEF_STR( Off ))
+ PORT_CONFSETTING(1, DEF_STR( On ))
+
+ // The switch should be open (1) on powerup for BQ clock chips
+ PORT_START("MAPMODE")
+ PORT_DIPNAME(0x1, 1, "Map at boot time") PORT_CHANGED_MEMBER(DEVICE_SELF, FUNC(nouspikel_ide_card_device::mode_changed), 0)
+ PORT_DIPSETTING(0, "RTC")
+ PORT_DIPSETTING(1, "SRAM")
+
+ // Set to off as default, because random contents in SRAM may lead to lockup
+ PORT_START("MODE")
+ PORT_DIPNAME(0x3, MODE_OFF, "Card mode") PORT_CHANGED_MEMBER(DEVICE_SELF, FUNC(nouspikel_ide_card_device::mode_changed), 1)
+ PORT_DIPSETTING(MODE_OFF, "Off")
+ PORT_DIPSETTING(MODE_GENEVE, "Geneve")
+ PORT_DIPSETTING(MODE_TI, "TI")
+
+ PORT_START( "CRUIDE" )
+ PORT_DIPNAME( 0xf, 0x0, "IDE CRU base" )
+ PORT_DIPSETTING( 0x0, "1000" )
+ PORT_DIPSETTING( 0x1, "1100" )
+ PORT_DIPSETTING( 0x2, "1200" )
+ PORT_DIPSETTING( 0x3, "1300" )
+ PORT_DIPSETTING( 0x4, "1400" )
+ PORT_DIPSETTING( 0x5, "1500" )
+ PORT_DIPSETTING( 0x6, "1600" )
+ PORT_DIPSETTING( 0x7, "1700" )
+ PORT_DIPSETTING( 0x8, "1800" )
+ PORT_DIPSETTING( 0x9, "1900" )
+ PORT_DIPSETTING( 0xa, "1A00" )
+ PORT_DIPSETTING( 0xb, "1B00" )
+ PORT_DIPSETTING( 0xc, "1C00" )
+ PORT_DIPSETTING( 0xd, "1D00" )
+ PORT_DIPSETTING( 0xe, "1E00" )
+ PORT_DIPSETTING( 0xf, "1F00" )
+INPUT_PORTS_END
+
+ioport_constructor nouspikel_ide_card_device::device_input_ports() const
+{
+ return INPUT_PORTS_NAME(tn_ide);
+}
+} // end namespace bus::ti99::peb
diff --git a/src/devices/bus/ti99/peb/tn_ide.h b/src/devices/bus/ti99/peb/tn_ide.h
index 51d516d5af0..1ac042cde38 100644
--- a/src/devices/bus/ti99/peb/tn_ide.h
+++ b/src/devices/bus/ti99/peb/tn_ide.h
@@ -2,12 +2,11 @@
// copyright-holders:Michael Zapf
/****************************************************************************
- Nouspikel IDE controller card
- See tn_ide.c for documentation
+ IDE adapter card
+ See tn_ide.cpp for documentation
Michael Zapf
-
- February 2012: Rewritten as class
+ April 2020
*****************************************************************************/
@@ -17,54 +16,72 @@
#pragma once
#include "peribox.h"
-#include "machine/ataintf.h"
-#include "machine/ram.h"
+#include "bus/ata/ataintf.h"
+#include "bus/ti99/internal/buffram.h"
#include "machine/rtc65271.h"
+#include "machine/bq4847.h"
+#include "machine/bq48x2.h"
+#include "machine/74259.h"
+#include "machine/74543.h"
-namespace bus { namespace ti99 { namespace peb {
+namespace bus::ti99::peb {
-class nouspikel_ide_interface_device : public device_t, public device_ti99_peribox_card_interface
+class nouspikel_ide_card_device : public device_t, public device_ti99_peribox_card_interface
{
public:
- nouspikel_ide_interface_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
- DECLARE_READ8Z_MEMBER(readz) override;
+ nouspikel_ide_card_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
+ void readz(offs_t offset, uint8_t *value) override;
void write(offs_t offset, uint8_t data) override;
-
- DECLARE_READ8Z_MEMBER(crureadz) override;
+ void crureadz(offs_t offset, uint8_t *value) override;
void cruwrite(offs_t offset, uint8_t data) override;
-
- void do_inta(int state);
- bool m_ata_irq;
- int m_cru_register;
-
-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;
+ DECLARE_INPUT_CHANGED_MEMBER( mode_changed );
private:
- DECLARE_WRITE_LINE_MEMBER(clock_interrupt_callback);
- DECLARE_WRITE_LINE_MEMBER(ide_interrupt_callback);
+ void device_start() override ATTR_COLD;
+ void device_reset() override ATTR_COLD;
+ void device_add_mconfig(machine_config &config) override;
+ ioport_constructor device_input_ports() const override;
+
+ required_device<rtc65271_device> m_rtc65;
+ required_device<bq4847_device> m_rtc47;
+ required_device<bq4842_device> m_rtc42;
+ required_device<bq4852_device> m_rtc52;
- required_device<rtc65271_device> m_rtc;
required_device<ata_interface_device> m_ata;
+ required_device<bus::ti99::internal::buffered_ram_device> m_sram;
+ required_device<ls259_device> m_crulatch;
+ required_device<ttl74543_device> m_latch0_7;
+ required_device<ttl74543_device> m_latch8_15;
+
+ // Latches the IDE interrupt
+ bool m_ideint;
+
+ // TI mode or Geneve mode (or off)
+ int m_mode;
+
+ // Stores the currently selected page (74ALS373)
+ int m_page;
+
+ // Is the SRAM buffered?
+ bool m_srammap;
+
+ // RTC type
+ int m_rtctype;
- bool m_clk_irq;
- bool m_sram_enable;
- bool m_sram_enable_dip;
- int m_cur_page;
+ // Genmod decoding. If not used, the AME line is pulled up, and the AMD line is pulled down
+ bool m_genmod;
- bool m_tms9995_mode;
+ template<int rtctype> void rtc_int_callback(int state);
+ void ide_interrupt_callback(int state);
+ void resetdr_callback(int state);
- uint16_t m_input_latch;
- uint16_t m_output_latch;
+ void decode(offs_t offset, bool& mmap, bool& sramsel, bool& xramsel, bool& rtcsel, bool& cs1fx, bool& cs3fx);
- required_device<ram_device> m_ram;
+ int m_rtc_int;
};
-} } } // end namespace bus::ti99::peb
+} // end namespace bus::ti99::peb
-DECLARE_DEVICE_TYPE_NS(TI99_IDE, bus::ti99::peb, nouspikel_ide_interface_device)
+DECLARE_DEVICE_TYPE_NS(TI99_IDE, bus::ti99::peb, nouspikel_ide_card_device)
#endif // MAME_BUS_TI99_PEB_TN_IDE_H
diff --git a/src/devices/bus/ti99/peb/tn_usbsm.cpp b/src/devices/bus/ti99/peb/tn_usbsm.cpp
index 77f933667e9..a031613ca5a 100644
--- a/src/devices/bus/ti99/peb/tn_usbsm.cpp
+++ b/src/devices/bus/ti99/peb/tn_usbsm.cpp
@@ -42,15 +42,15 @@
#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"
-DEFINE_DEVICE_TYPE_NS(TI99_USBSM, bus::ti99::peb, nouspikel_usb_smartmedia_device, "ti99_usbsm", "Nouspikel USB/Smartmedia card")
+DEFINE_DEVICE_TYPE(TI99_USBSM, bus::ti99::peb::nouspikel_usb_smartmedia_device, "ti99_usbsm", "Nouspikel USB/Smartmedia card")
-namespace bus { namespace ti99 { namespace peb {
+namespace bus::ti99::peb {
#define STRATA_TAG "strata"
@@ -88,7 +88,7 @@ nouspikel_usb_smartmedia_device::nouspikel_usb_smartmedia_device(const machine_c
/*
CRU read
*/
-READ8Z_MEMBER(nouspikel_usb_smartmedia_device::crureadz)
+void nouspikel_usb_smartmedia_device::crureadz(offs_t offset, uint8_t *value)
{
if ((offset & 0xff00)==m_cru_base)
{
@@ -188,11 +188,11 @@ void nouspikel_usb_smartmedia_device::cruwrite(offs_t offset, uint8_t data)
Memory read
TODO: Check whether AMA/B/C is actually checked
*/
-READ8Z_MEMBER(nouspikel_usb_smartmedia_device::readz)
+void nouspikel_usb_smartmedia_device::readz(offs_t offset, uint8_t *value)
{
if (machine().side_effects_disabled()) return;
- if (((offset & m_select_mask)==m_select_value) && m_selected)
+ if (in_dsr_space(offset, true) && m_selected)
{
if (m_tms9995_mode ? (!(offset & 1)) : (offset & 1))
{
@@ -243,7 +243,7 @@ void nouspikel_usb_smartmedia_device::write(offs_t offset, uint8_t data)
{
if (machine().side_effects_disabled()) return;
- if (((offset & m_select_mask)==m_select_value) && m_selected)
+ if (in_dsr_space(offset, true) && m_selected)
{
/* latch write */
if (offset & 1)
@@ -325,16 +325,6 @@ void nouspikel_usb_smartmedia_device::device_reset()
m_enable_sm = false;
m_write_flash = false;
- if (m_genmod)
- {
- m_select_mask = 0x1fe000;
- m_select_value = 0x174000;
- }
- else
- {
- m_select_mask = 0x7e000;
- m_select_value = 0x74000;
- }
m_selected = false;
m_cru_base = ioport("CRUUSBSM")->read();
@@ -377,4 +367,5 @@ ioport_constructor nouspikel_usb_smartmedia_device::device_input_ports() const
{
return INPUT_PORTS_NAME(tn_usbsm);
}
-} } } // end namespace bus::ti99::peb
+
+} // end namespace bus::ti99::peb
diff --git a/src/devices/bus/ti99/peb/tn_usbsm.h b/src/devices/bus/ti99/peb/tn_usbsm.h
index 52c2690f3ed..a2414da480e 100644
--- a/src/devices/bus/ti99/peb/tn_usbsm.h
+++ b/src/devices/bus/ti99/peb/tn_usbsm.h
@@ -21,23 +21,23 @@
#include "machine/strata.h"
#include "machine/ram.h"
-namespace bus { namespace ti99 { namespace peb {
+namespace bus::ti99::peb {
class nouspikel_usb_smartmedia_device : public device_t, public device_ti99_peribox_card_interface
{
public:
nouspikel_usb_smartmedia_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
- DECLARE_READ8Z_MEMBER(readz) override;
+ void readz(offs_t offset, uint8_t *value) override;
void write(offs_t offset, uint8_t data) override;
- DECLARE_READ8Z_MEMBER(crureadz) override;
+ void crureadz(offs_t offset, uint8_t *value) override;
void cruwrite(offs_t offset, uint8_t data) 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 void device_start() override ATTR_COLD;
+ virtual void device_reset() override ATTR_COLD;
+ virtual void device_add_mconfig(machine_config &config) override ATTR_COLD;
+ virtual ioport_constructor device_input_ports() const override ATTR_COLD;
private:
@@ -59,7 +59,8 @@ private:
required_device<smartmedia_image_device> m_smartmedia;
required_device<strataflash_device> m_flash;
};
-} } } // end namespace bus::ti99::peb
+
+} // end namespace bus::ti99::peb
DECLARE_DEVICE_TYPE_NS(TI99_USBSM, bus::ti99::peb, nouspikel_usb_smartmedia_device)
diff --git a/src/devices/bus/ti99/sidecar/arcturus.cpp b/src/devices/bus/ti99/sidecar/arcturus.cpp
new file mode 100644
index 00000000000..26f32f395af
--- /dev/null
+++ b/src/devices/bus/ti99/sidecar/arcturus.cpp
@@ -0,0 +1,93 @@
+// license:LGPL-2.1+
+// copyright-holders:Michael Zapf
+/****************************************************************************
+
+ Arcturus sidecar cartridge
+ Michael Zapf
+
+*****************************************************************************/
+
+#include "emu.h"
+#include "arcturus.h"
+
+#define LOG_WARN (1U << 1) // Warnings
+
+// #define VERBOSE (LOG_GENERAL | LOG_WARN)
+
+#include "logmacro.h"
+
+#define TI99_CARTSC_4000 "mem4000"
+#define TI99_CARTSC_A000 "mema000"
+#define TI99_CARTSC_C000 "memc000"
+#define TI99_CARTSC_RAM "ram"
+
+DEFINE_DEVICE_TYPE(TI99_ARCTURUS, bus::ti99::sidecar::arcturus_device, "ti99_arcturus", "Arcturus sidecar cartridge")
+
+namespace bus::ti99::sidecar {
+
+/*
+ Constructor called from subclasses.
+*/
+arcturus_device::arcturus_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
+ : bus::ti99::internal::ioport_attached_device(mconfig, TI99_ARCTURUS, tag, owner, clock),
+ m_ram(*this, TI99_CARTSC_RAM)
+{
+}
+
+void arcturus_device::readz(offs_t offset, uint8_t *value)
+{
+ switch ((offset >> 13)&0x07)
+ {
+ case 0:
+ case 3:
+ case 4:
+ case 7:
+ break;
+ case 1:
+ *value = m_ram->pointer()[offset & 0x07ff];
+ break;
+ case 2:
+ *value = m_rom4[offset & 0x1fff];
+ break;
+ case 5:
+ *value = m_roma[offset & 0x1fff];
+ break;
+ case 6:
+ *value = m_romc[offset & 0x1fff];
+ break;
+ }
+}
+
+void arcturus_device::write(offs_t offset, uint8_t data)
+{
+ if (((offset >> 13)&0x07)==1)
+ m_ram->pointer()[offset & 0x07ff] = data;
+}
+
+void arcturus_device::device_start()
+{
+ m_rom4 = memregion(TI99_CARTSC_4000)->base();
+ m_roma = memregion(TI99_CARTSC_A000)->base();
+ m_romc = memregion(TI99_CARTSC_C000)->base();
+}
+
+ROM_START( ti99_arcturus )
+ ROM_REGION(0x2000, TI99_CARTSC_4000, 0)
+ ROM_LOAD("arcturus.u1", 0x0000, 0x2000, CRC(28ba65ec) SHA1(63329930c71ef776e8598a8d4c580c41bd52a339))
+ ROM_REGION(0x2000, TI99_CARTSC_A000, 0)
+ ROM_LOAD("arcturus.u2", 0x0000, 0x2000, CRC(91e6910a) SHA1(51c1f75d4e9d74af21c0b43188fc0ffc4a3ad4c0))
+ ROM_REGION(0x2000, TI99_CARTSC_C000, 0)
+ ROM_LOAD("arcturus.u3", 0x0000, 0x2000, CRC(e9ce9f4e) SHA1(65850c57e9480a5d8bdd852692f18d0162ca1406))
+ROM_END
+
+void arcturus_device::device_add_mconfig(machine_config& config)
+{
+ RAM(config, TI99_CARTSC_RAM).set_default_size("2K").set_default_value(0);
+}
+
+const tiny_rom_entry *arcturus_device::device_rom_region() const
+{
+ return ROM_NAME( ti99_arcturus );
+}
+
+} // end namespace bus::ti99::peb
diff --git a/src/devices/bus/ti99/sidecar/arcturus.h b/src/devices/bus/ti99/sidecar/arcturus.h
new file mode 100644
index 00000000000..940bd0e55f5
--- /dev/null
+++ b/src/devices/bus/ti99/sidecar/arcturus.h
@@ -0,0 +1,49 @@
+// license:LGPL-2.1+
+// copyright-holders:Michael Zapf
+/****************************************************************************
+
+ Arcturus sidecar cartridge
+ Michael Zapf
+
+*****************************************************************************/
+
+#ifndef MAME_BUS_TI99_SIDECAR_ARCTURUS_H
+#define MAME_BUS_TI99_SIDECAR_ARCTURUS_H
+
+#pragma once
+
+#include "bus/ti99/internal/ioport.h"
+#include "machine/ram.h"
+
+namespace bus::ti99::sidecar {
+
+/*****************************************************************************
+ Arcturus sidecar cartridge
+******************************************************************************/
+
+class arcturus_device : public bus::ti99::internal::ioport_attached_device
+{
+public:
+ arcturus_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
+ virtual void readz(offs_t offset, uint8_t *value) override;
+ virtual void write(offs_t offset, uint8_t data) override;
+
+protected:
+ virtual void device_start() override ATTR_COLD;
+ virtual const tiny_rom_entry *device_rom_region() const override ATTR_COLD;
+ virtual void device_add_mconfig(machine_config &config) override ATTR_COLD;
+
+private:
+ // ROMs
+ uint8_t* m_rom4;
+ uint8_t* m_roma;
+ uint8_t* m_romc;
+
+ required_device<ram_device> m_ram;
+};
+
+} // end namespace bus::ti99::internal
+
+DECLARE_DEVICE_TYPE_NS(TI99_ARCTURUS, bus::ti99::sidecar, arcturus_device)
+
+#endif // MAME_BUS_TI99_SIDECAR_ARCTURUS_H
diff --git a/src/devices/bus/ti99/sidecar/speechsyn.cpp b/src/devices/bus/ti99/sidecar/speechsyn.cpp
new file mode 100644
index 00000000000..65e4998da90
--- /dev/null
+++ b/src/devices/bus/ti99/sidecar/speechsyn.cpp
@@ -0,0 +1,273 @@
+// license:LGPL-2.1+
+// copyright-holders:Michael Zapf
+/****************************************************************************
+
+ TI-99 Speech synthesizer
+
+ This is the emulation Speech Synthesizer, which plugs into the I/O port of
+ the TI console. Even though the sidecar expansion concept was largely
+ abandoned by the introduction of the Peripheral Expansion Box with the 4A,
+ the Speech Synthesizer was sold as a sidecar expansion until the end.
+
+ Typical setup:
+ Speech Synthesizer
+ sidecar
+ v
+ +----------------+---+----------
+ | TI-99/4(A) | | PEB connection cable
+ +------------+---+ +----------
+ | oooooooooo | |---+
+ | oooooooooo | |
+ +-----------------
+
+ Also as a common modification, users removed the board inside the sidecar
+ and placed it on an adapter to go into the PEB and thus to become
+ available for the Geneve or SGCPU. See bus/ti99/peb/speechadapter.cpp.
+
+ The sidecar offers a flippable lid where vocabulary expansion modules were
+ supposed to be plugged in, but those have never seen daylight. In most of
+ the units, including mine, no connector can be found under the lid, so the
+ decision to drop this idea must have come early.
+
+ Technical details:
+
+ The Voice Synthesis Processor (VSP) used for the TI Speech Synthesizer
+ is the CD2501E, aka TMS5200 (internal name TMC0285), a predecessor of the
+ TMS5220 which was used in many other commercial products.
+ Two TMS6100 circuits hold the standard vocabulary, mainly used from Extended
+ Basic programs.
+
+ The interaction with the TMS5200 relies completely on the READY*
+ line; the INT* line is not connected.
+
+ The VSP delivers a READY* signal, which needs to be inverted for the rest
+ of the TI system. The board of the Speech Synthesizer uses a simple
+ transistor for this purpose.
+
+ Michael Zapf
+ March 2025
+
+*****************************************************************************/
+
+#include "emu.h"
+#include "speechsyn.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 VERBOSE (LOG_GENERAL | LOG_WARN)
+
+#include "logmacro.h"
+
+DEFINE_DEVICE_TYPE(TI99_SPEECHSYN, bus::ti99::sidecar::ti_speech_synthesizer_device, "ti99_speech", "TI-99 Speech Synthesizer")
+
+namespace bus::ti99::sidecar {
+
+#define VSP "tms5200"
+#define PORT "extport"
+
+/*
+ Constructor called from subclasses.
+*/
+ti_speech_synthesizer_device::ti_speech_synthesizer_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
+ : bus::ti99::internal::ioport_attached_device(mconfig, TI99_SPEECHSYN, tag, owner, clock),
+ m_vsp(*this, VSP),
+ m_port(*this, PORT),
+ m_reading(false),
+ m_sbe(CLEAR_LINE),
+ m_ext_ready(ASSERT_LINE),
+ m_ssyn_ready(ASSERT_LINE)
+{
+}
+
+/*
+ Memory read
+*/
+
+void ti_speech_synthesizer_device::readz(offs_t offset, uint8_t *value)
+{
+ if (m_sbe)
+ {
+ if (machine().side_effects_disabled()) return;
+
+ *value = m_vsp->status_r() & 0xff;
+ LOGMASKED(LOG_MEM, "read value = %02x\n", *value);
+ // We should clear the lines at this point. The TI-99/4A clears the
+ // lines by setting the address bus to a different value, but the
+ // Geneve may behave differently. This may not 100% reflect the real
+ // situation, but it ensures a safe processing.
+ m_vsp->combined_rsq_wsq_w(~0);
+ }
+
+ // Pass through to the external port
+ if (m_port != nullptr)
+ m_port->readz(offset, value);
+}
+/*
+ Memory write
+*/
+void ti_speech_synthesizer_device::write(offs_t offset, uint8_t data)
+{
+ if (m_sbe)
+ {
+ if (machine().side_effects_disabled()) return;
+ LOGMASKED(LOG_MEM, "write value = %02x\n", data);
+ m_vsp->data_w(data);
+ // Note that we must NOT clear the lines here. Find the lines in the
+ // READY callback below.
+ }
+
+ // Pass through to the external port
+ if (m_port != nullptr)
+ m_port->write(offset, data);
+}
+
+void ti_speech_synthesizer_device::setaddress_dbin(offs_t offset, int state)
+{
+ if (m_sbe)
+ {
+ m_reading = (state==ASSERT_LINE);
+ LOGMASKED(LOG_ADDR, "set address = %04x, dbin = %d\n", offset, state);
+
+ // Caution: In the current tms5220 emulation, care must be taken
+ // to clear one line before asserting the other line, or otherwise
+ // both RS* and WS* are active, which is illegal.
+ // Alternatively, we'll use the combined settings method
+
+ m_vsp->combined_rsq_wsq_w(m_reading ? ~tms5220_device::RS : ~tms5220_device::WS);
+ }
+ else
+ {
+ // If other address, turn off RS* and WS* (negative logic!)
+ m_vsp->combined_rsq_wsq_w(~0);
+
+ // Pass through to the external port
+ if (m_port != nullptr)
+ m_port->setaddress_dbin(offset, state);
+ }
+}
+
+void ti_speech_synthesizer_device::sbe(int state)
+{
+ m_sbe = (state==ASSERT_LINE);
+ // Not forwarded to the external port
+}
+
+void ti_speech_synthesizer_device::crureadz(offs_t offset, uint8_t *value)
+{
+ // Pass through to the external port
+ if (m_port != nullptr)
+ m_port->crureadz(offset, value);
+}
+
+void ti_speech_synthesizer_device::cruwrite(offs_t offset, uint8_t data)
+{
+ // Pass through to the external port
+ if (m_port != nullptr)
+ m_port->cruwrite(offset, data);
+}
+
+void ti_speech_synthesizer_device::memen_in(int state)
+{
+ // Pass through to the external port
+ if (m_port != nullptr)
+ m_port->memen_in(state);
+}
+
+void ti_speech_synthesizer_device::msast_in(int state)
+{
+ // Pass through to the external port
+ if (m_port != nullptr)
+ m_port->msast_in(state);
+}
+
+void ti_speech_synthesizer_device::clock_in(int state)
+{
+ // Pass through to the external port
+ if (m_port != nullptr)
+ m_port->clock_in(state);
+}
+
+void ti_speech_synthesizer_device::reset_in(int state)
+{
+ // Pass through to the external port
+ if (m_port != nullptr)
+ m_port->reset_in(state);
+}
+
+/*
+ Forward the incoming interrupt to the console
+*/
+void ti_speech_synthesizer_device::extint(int state)
+{
+ set_extint(state);
+}
+
+void ti_speech_synthesizer_device::extready(int state)
+{
+ LOGMASKED(LOG_READY, "Incoming READY=%d from external port\n", state);
+ m_ext_ready = (line_state)state;
+ set_ready(m_ext_ready & m_ssyn_ready);
+}
+
+void ti_speech_synthesizer_device::speech_ready(int state)
+{
+ // Invert the READY* signal
+ m_ssyn_ready = (state==0)? ASSERT_LINE : CLEAR_LINE;
+ LOGMASKED(LOG_READY, "SSyn READY = %d\n", (state==0));
+
+ if ((state==0) && !m_reading)
+ // Clear the lines only when we are done with writing.
+ m_vsp->combined_rsq_wsq_w(~0);
+
+ set_ready(m_ext_ready & m_ssyn_ready);
+}
+
+void ti_speech_synthesizer_device::device_start()
+{
+ save_item(NAME(m_reading));
+ save_item(NAME(m_sbe));
+}
+
+void ti_speech_synthesizer_device::device_reset()
+{
+ m_reading = false;
+ m_sbe = CLEAR_LINE;
+}
+
+ROM_START( ti99_speech )
+ ROM_REGION(0x8000, "vsm", 0)
+ ROM_LOAD("cd2325a.u2a", 0x0000, 0x4000, CRC(1f58b571) SHA1(0ef4f178716b575a1c0c970c56af8a8d97561ffe)) // at location u2, bottom of stack
+ ROM_LOAD("cd2326a.u2b", 0x4000, 0x4000, CRC(65d00401) SHA1(a367242c2c96cebf0e2bf21862f3f6734b2b3020)) // at location u2, top of stack
+ROM_END
+
+void ti_speech_synthesizer_device::device_add_mconfig(machine_config& config)
+{
+ SPEAKER(config, "speech_out").front_center();
+ CD2501E(config, m_vsp, 640000L);
+
+ m_vsp->ready_cb().set(FUNC(ti_speech_synthesizer_device::speech_ready));
+ m_vsp->add_route(ALL_OUTPUTS, "speech_out", 0.50);
+
+ TMS6100(config, "vsm", 0);
+ m_vsp->m0_cb().set("vsm", FUNC(tms6100_device::m0_w));
+ m_vsp->m1_cb().set("vsm", FUNC(tms6100_device::m1_w));
+ m_vsp->addr_cb().set("vsm", FUNC(tms6100_device::add_w));
+ m_vsp->data_cb().set("vsm", FUNC(tms6100_device::data_line_r));
+ m_vsp->romclk_cb().set("vsm", FUNC(tms6100_device::clk_w));
+
+ TI99_IOPORT(config, m_port, 0, ti99_ioport_options_evpc1, nullptr);
+ m_port->extint_cb().set(FUNC(ti_speech_synthesizer_device::extint));
+ m_port->ready_cb().set(FUNC(ti_speech_synthesizer_device::extready));
+}
+
+const tiny_rom_entry *ti_speech_synthesizer_device::device_rom_region() const
+{
+ return ROM_NAME( ti99_speech );
+}
+
+} // end namespace bus::ti99::sidecar
diff --git a/src/devices/bus/ti99/sidecar/speechsyn.h b/src/devices/bus/ti99/sidecar/speechsyn.h
new file mode 100644
index 00000000000..b0fc531832f
--- /dev/null
+++ b/src/devices/bus/ti99/sidecar/speechsyn.h
@@ -0,0 +1,65 @@
+// license:LGPL-2.1+
+// copyright-holders:Michael Zapf
+/****************************************************************************
+
+ Speech Synthesizer sidecar device
+ Michael Zapf
+
+*****************************************************************************/
+
+#ifndef MAME_BUS_TI99_SIDECAR_SPEECHSYN_H
+#define MAME_BUS_TI99_SIDECAR_SPEECHSYN_H
+
+#pragma once
+
+#include "bus/ti99/internal/ioport.h"
+#include "sound/tms5220.h"
+#include "machine/tms6100.h"
+
+namespace bus::ti99::sidecar {
+
+class ti_speech_synthesizer_device : public bus::ti99::internal::ioport_attached_device
+{
+public:
+ ti_speech_synthesizer_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
+ void readz(offs_t offset, uint8_t *value) override;
+ void write(offs_t offset, uint8_t data) override;
+ void setaddress_dbin(offs_t offset, int state) override;
+ void sbe(int state) override;
+
+ void crureadz(offs_t offset, uint8_t *value) override;
+ void cruwrite(offs_t offset, uint8_t data) override;
+
+ void memen_in(int state) override;
+ void msast_in(int state) override;
+
+ void clock_in(int state) override;
+ void reset_in(int state) override;
+
+protected:
+ virtual void device_start() override ATTR_COLD;
+ virtual void device_reset() override ATTR_COLD;
+ virtual const tiny_rom_entry *device_rom_region() const override ATTR_COLD;
+ virtual void device_add_mconfig(machine_config &config) override ATTR_COLD;
+
+ // Callbacks from the external port
+ void extint(int state);
+ void extready(int state);
+
+private:
+ required_device<cd2501e_device> m_vsp;
+ required_device<bus::ti99::internal::ioport_device> m_port;
+
+ void speech_ready(int state);
+
+ bool m_reading;
+ bool m_sbe;
+ line_state m_ext_ready;
+ line_state m_ssyn_ready;
+};
+
+} // end namespace bus::ti99::internal
+
+DECLARE_DEVICE_TYPE_NS(TI99_SPEECHSYN, bus::ti99::sidecar, ti_speech_synthesizer_device)
+
+#endif // MAME_BUS_TI99_SIDECAR_SPEECHSYN_H
diff --git a/src/devices/bus/ti99/ti99defs.h b/src/devices/bus/ti99/ti99defs.h
deleted file mode 100644
index 3a1ed9d00d5..00000000000
--- a/src/devices/bus/ti99/ti99defs.h
+++ /dev/null
@@ -1,67 +0,0 @@
-// license:LGPL-2.1+
-// copyright-holders:Michael Zapf
-/****************************************************************************
-
- Common definitions for TI family
- Should be included in each component.
-
- Michael Zapf
-
-*****************************************************************************/
-
-#ifndef MAME_BUS_TI99_TI99DEFS_H
-#define MAME_BUS_TI99_TI99DEFS_H
-
-#pragma once
-
-// TI-99/4(A)
-#define TI99_GROMPORT_TAG "gromport"
-#define TI99_GROM0_TAG "console_grom_0"
-#define TI99_GROM1_TAG "console_grom_1"
-#define TI99_GROM2_TAG "console_grom_2"
-#define TI99_IOPORT_TAG "ioport"
-#define TI99_EVPC_CONN_TAG "evpc_conn"
-#define TI99_DATAMUX_TAG "datamux_16_8"
-#define TI99_PADRAM_TAG "scratchpad"
-#define TI99_EXPRAM_TAG "internal_32k_mod"
-#define TI99_DSRROM "dsrrom"
-#define TI99_CONSOLEROM "console_rom"
-#define TI99_CONSOLEGROM "cons_grom"
-
-// Various systems (ti99, geneve)
-#define TI_SOUNDCHIP_TAG "soundchip"
-#define TI_TMS9901_TAG "tms9901"
-#define TI_PERIBOX_TAG "peb"
-#define TI_JOYPORT_TAG "joyport"
-#define TI_VDP_TAG "vdp"
-#define TI_SCREEN_TAG "screen"
-#define TI_HEXBUS_TAG "hexbus"
-#define TI_CASSETTE "cassette"
-#define TI992_VDC_TAG "vdc"
-
-#define TI_VDPFREQ XTAL(10'738'635)
-
-// v9938
-#define COLORBUS_TAG "colorbus"
-
-
-/*
- Macros for special read methods; these methods differs from the standard
- READ8 by allowing for a "high-impedance" state "Z" which means that the
- bus lines are not changed. That way, we can built busses with parallel
- devices as in the real machine, and only the active device changes the bus lines.
-*/
-
-#define READ8Z_MEMBER(name) void name(ATTR_UNUSED offs_t offset, ATTR_UNUSED uint8_t *value)
-#define DECLARE_READ8Z_MEMBER(name) void name(ATTR_UNUSED offs_t offset, ATTR_UNUSED uint8_t *value)
-
-/*
- For almost all applications of setaddress, we also need the data bus
- direction. This line is called DBIN on the TI CPUs, but as we do not assume
- that this is a general rule, we use new macros here which contain the
- DBIN setting.
-*/
-#define SETADDRESS_DBIN_MEMBER(name) void name(ATTR_UNUSED offs_t offset, ATTR_UNUSED int state)
-#define DECLARE_SETADDRESS_DBIN_MEMBER(name) void name(ATTR_UNUSED offs_t offset, ATTR_UNUSED int state)
-
-#endif // MAME_BUS_TI99_TI99DEFS_H
diff --git a/src/devices/bus/ti99x/990_dk.cpp b/src/devices/bus/ti99x/990_dk.cpp
index a634bba7a24..bc08be51f59 100644
--- a/src/devices/bus/ti99x/990_dk.cpp
+++ b/src/devices/bus/ti99x/990_dk.cpp
@@ -705,7 +705,7 @@ void fd800_legacy_device::do_cmd()
30: unit MSB
31: Interrupt (CBUSY???) (1 -> controller is ready)
*/
-READ8_MEMBER( fd800_legacy_device::cru_r )
+uint8_t fd800_legacy_device::cru_r(offs_t offset)
{
int reply = 0;
@@ -736,7 +736,7 @@ READ8_MEMBER( fd800_legacy_device::cru_r )
27: FD unit number MSB/extended command code
28-31: command code
*/
-WRITE8_MEMBER( fd800_legacy_device::cru_w )
+void fd800_legacy_device::cru_w(offs_t offset, uint8_t data)
{
switch (offset)
{
@@ -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_dk.h b/src/devices/bus/ti99x/990_dk.h
index d05278a187a..8d490fa703e 100644
--- a/src/devices/bus/ti99x/990_dk.h
+++ b/src/devices/bus/ti99x/990_dk.h
@@ -16,8 +16,8 @@ class fd800_legacy_device : public device_t
public:
fd800_legacy_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
- DECLARE_READ8_MEMBER( cru_r );
- DECLARE_WRITE8_MEMBER( cru_w );
+ uint8_t cru_r(offs_t offset);
+ void cru_w(offs_t offset, uint8_t data);
auto int_cb() { return m_int_line.bind(); }
private:
@@ -28,8 +28,8 @@ private:
static constexpr unsigned MAX_FLOPPIES = 4;
- void device_start() override;
- void device_reset() override;
+ void device_start() override ATTR_COLD;
+ void device_reset() override ATTR_COLD;
void set_interrupt_line();
int read_id(int unit, int head, int *cylinder_id, int *sector_id);
diff --git a/src/devices/bus/ti99x/990_hd.cpp b/src/devices/bus/ti99x/990_hd.cpp
index 8e9c08648a5..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,31 +152,25 @@ 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() )
{
- const hard_disk_info *standard_header;
-
d->format = format_mame;
- d->hd_handle = hd_file;
/* use standard hard disk image header. */
- standard_header = hard_disk_get_info(d->hd_handle);
+ const auto &standard_header = d->img->get_info();
- d->cylinders = standard_header->cylinders;
- d->heads = standard_header->heads;
- d->sectors_per_track = standard_header->sectors;
- d->bytes_per_sector = standard_header->sectorbytes;
+ d->cylinders = standard_header.cylinders;
+ d->heads = standard_header.heads;
+ d->sectors_per_track = standard_header.sectors;
+ d->bytes_per_sector = standard_header.sectorbytes;
}
else
{
@@ -196,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
@@ -208,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);
@@ -220,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 */
@@ -233,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;
@@ -247,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;
@@ -260,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();
}
/*
@@ -307,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)));
}
/*
@@ -365,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 * hard_disk_read(m_d[unit].hd_handle, 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;
@@ -395,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 * hard_disk_write(m_d[unit].hd_handle, 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;
@@ -924,7 +891,7 @@ void ti990_hdc_device::execute_command()
/*
Read one register in TPCS space
*/
-READ16_MEMBER(ti990_hdc_device::read)
+uint16_t ti990_hdc_device::read(offs_t offset)
{
if (offset < 8)
return m_w[offset];
@@ -935,7 +902,7 @@ READ16_MEMBER(ti990_hdc_device::read)
/*
Write one register in TPCS space. Execute command if w7_idle is cleared.
*/
-WRITE16_MEMBER(ti990_hdc_device::write)
+void ti990_hdc_device::write(offs_t offset, uint16_t data, uint16_t mem_mask)
{
if (offset < 8)
{
@@ -974,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;
}
@@ -989,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();
}
@@ -1007,18 +969,18 @@ void ti990_hdc_device::device_start()
void ti990_hdc_device::device_add_mconfig(machine_config &config)
{
harddisk_image_device &harddisk1(HARDDISK(config, "harddisk1"));
- harddisk1.set_device_load(FUNC(ti990_hdc_device::load_hd), this);
- harddisk1.set_device_unload(FUNC(ti990_hdc_device::unload_hd), this);
+ harddisk1.set_device_load(FUNC(ti990_hdc_device::load_hd));
+ harddisk1.set_device_unload(FUNC(ti990_hdc_device::unload_hd));
harddisk_image_device &harddisk2(HARDDISK(config, "harddisk2"));
- harddisk2.set_device_load(FUNC(ti990_hdc_device::load_hd), this);
- harddisk2.set_device_unload(FUNC(ti990_hdc_device::unload_hd), this);
+ harddisk2.set_device_load(FUNC(ti990_hdc_device::load_hd));
+ harddisk2.set_device_unload(FUNC(ti990_hdc_device::unload_hd));
harddisk_image_device &harddisk3(HARDDISK(config, "harddisk3"));
- harddisk3.set_device_load(FUNC(ti990_hdc_device::load_hd), this);
- harddisk3.set_device_unload(FUNC(ti990_hdc_device::unload_hd), this);
+ harddisk3.set_device_load(FUNC(ti990_hdc_device::load_hd));
+ harddisk3.set_device_unload(FUNC(ti990_hdc_device::unload_hd));
harddisk_image_device &harddisk4(HARDDISK(config, "harddisk4"));
- harddisk4.set_device_load(FUNC(ti990_hdc_device::load_hd), this);
- harddisk4.set_device_unload(FUNC(ti990_hdc_device::unload_hd), this);
+ harddisk4.set_device_load(FUNC(ti990_hdc_device::load_hd));
+ harddisk4.set_device_unload(FUNC(ti990_hdc_device::unload_hd));
}
diff --git a/src/devices/bus/ti99x/990_hd.h b/src/devices/bus/ti99x/990_hd.h
index 2f9be99a1e7..596e63c6056 100644
--- a/src/devices/bus/ti99x/990_hd.h
+++ b/src/devices/bus/ti99x/990_hd.h
@@ -15,19 +15,19 @@ class ti990_hdc_device : public device_t
public:
ti990_hdc_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
- DECLARE_READ16_MEMBER(read);
- DECLARE_WRITE16_MEMBER(write);
+ 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(); }
protected:
// device-level overrides
- virtual void device_start() override;
- virtual void device_add_mconfig(machine_config &config) override;
+ virtual void device_start() override ATTR_COLD;
+ virtual void device_add_mconfig(machine_config &config) override ATTR_COLD;
int get_id_from_device( device_t *device );
@@ -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 cafefbffda8..2a98a847823 100644
--- a/src/devices/bus/ti99x/990_tap.cpp
+++ b/src/devices/bus/ti99x/990_tap.cpp
@@ -33,6 +33,11 @@
#include "emu.h"
#include "990_tap.h"
+#include "imagedev/magtape.h"
+
+#include <algorithm>
+#include <iterator>
+
enum
{
w0_offline = 0x8000,
@@ -853,7 +858,7 @@ void tap_990_device::execute_command()
/*
Read one register in TPCS space
*/
-READ16_MEMBER( tap_990_device::read )
+uint16_t tap_990_device::read(offs_t offset)
{
if (offset < 8)
return m_w[offset];
@@ -864,7 +869,7 @@ READ16_MEMBER( tap_990_device::read )
/*
Write one register in TPCS space. Execute command if w7_idle is cleared.
*/
-WRITE16_MEMBER( tap_990_device::write )
+void tap_990_device::write(offs_t offset, uint16_t data, uint16_t mem_mask)
{
if (offset < 8)
{
@@ -887,28 +892,22 @@ WRITE16_MEMBER( tap_990_device::write )
}
}
-class ti990_tape_image_device : public device_t,
- public device_image_interface
+class ti990_tape_image_device : public magtape_image_device
{
public:
// construction/destruction
ti990_tape_image_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
- // image-level overrides
- virtual iodevice_t image_type() const override { return IO_MAGTAPE; }
-
- virtual bool is_readable() const override { return 1; }
- virtual bool is_writeable() const override { return 1; }
- virtual bool is_creatable() const override { return 1; }
- virtual bool must_be_loaded() const override { return 0; }
- virtual bool is_reset_on_load() const override { return 0; }
- virtual const char *file_extensions() const override { return "tap"; }
+ // 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
- virtual void device_start() override;
+ // device_t implementation
+ virtual void device_start() override ATTR_COLD;
+
private:
int tape_get_id();
};
@@ -916,7 +915,7 @@ private:
DEFINE_DEVICE_TYPE(TI990_TAPE, ti990_tape_image_device, "ti990_tape_image", "TI-990 Magnetic Tape")
ti990_tape_image_device::ti990_tape_image_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
- : device_t(mconfig, TI990_TAPE, tag, owner, clock), device_image_interface(mconfig, *this)
+ : magtape_image_device(mconfig, TI990_TAPE, tag, owner, clock)
{
}
@@ -939,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());
}
/*
@@ -972,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 3be370a9f5a..cc7a5076597 100644
--- a/src/devices/bus/ti99x/990_tap.h
+++ b/src/devices/bus/ti99x/990_tap.h
@@ -15,8 +15,8 @@ class tap_990_device : public device_t
public:
tap_990_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
- DECLARE_READ16_MEMBER( read );
- DECLARE_WRITE16_MEMBER( write );
+ uint16_t read(offs_t offset);
+ void write(offs_t offset, uint16_t data, uint16_t mem_mask = ~0);
void set_tape(int id, device_image_interface *img, bool bot, bool eot, bool wp)
{
@@ -30,9 +30,9 @@ public:
auto int_cb() { return m_int_line.bind(); }
protected:
- // device-level overrides
- virtual void device_start() override;
- virtual void device_add_mconfig(machine_config &config) override;
+ // device_t implementation
+ virtual void device_start() override ATTR_COLD;
+ virtual void device_add_mconfig(machine_config &config) override ATTR_COLD;
private:
static constexpr unsigned MAX_TAPE_UNIT = 4;
diff --git a/src/devices/bus/tiki100/8088.cpp b/src/devices/bus/tiki100/8088.cpp
index 0a940fcbc2c..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
@@ -52,7 +56,7 @@ const tiny_rom_entry *tiki100_8088_device::device_rom_region() const
void tiki100_8088_device::i8088_mem(address_map &map)
{
map(0x00000, 0xbffff).ram();
- map(0xc0000, 0xcffff).rw(":" TIKI100_BUS_TAG, FUNC(tiki100_bus_device::exin_mrq_r), FUNC(tiki100_bus_device::exin_mrq_w));
+ //map(0xc0000, 0xcffff).rw(m_bus, FUNC(tiki100_bus_device::exin_mrq_r), FUNC(tiki100_bus_device::exin_mrq_w)); don't have m_bus until start
map(0xff000, 0xfffff).rom().region(I8088_TAG, 0);
}
@@ -99,6 +103,10 @@ tiki100_8088_device::tiki100_8088_device(const machine_config &mconfig, const ch
void tiki100_8088_device::device_start()
{
+ m_maincpu->space(AS_PROGRAM).install_readwrite_handler(
+ 0xc0000, 0xcffff,
+ read8sm_delegate(*m_bus, FUNC(tiki100_bus_device::exin_mrq_r)),
+ write8sm_delegate(*m_bus, FUNC(tiki100_bus_device::exin_mrq_w)));
}
@@ -151,7 +159,7 @@ void tiki100_8088_device::iorq_w(offs_t offset, uint8_t data)
// read -
//-------------------------------------------------
-READ8_MEMBER( tiki100_8088_device::read )
+uint8_t tiki100_8088_device::read()
{
return m_busak << 4 | m_data;
}
@@ -161,7 +169,7 @@ READ8_MEMBER( tiki100_8088_device::read )
// write -
//-------------------------------------------------
-WRITE8_MEMBER( tiki100_8088_device::write )
+void tiki100_8088_device::write(uint8_t data)
{
m_data = data & 0x0f;
diff --git a/src/devices/bus/tiki100/8088.h b/src/devices/bus/tiki100/8088.h
index 2e4e6966172..d17358c2e13 100644
--- a/src/devices/bus/tiki100/8088.h
+++ b/src/devices/bus/tiki100/8088.h
@@ -31,10 +31,10 @@ public:
protected:
// device-level overrides
- 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;
+ virtual void device_start() override ATTR_COLD;
+ virtual void device_reset() override ATTR_COLD;
+ virtual const tiny_rom_entry *device_rom_region() const override ATTR_COLD;
+ virtual void device_add_mconfig(machine_config &config) override ATTR_COLD;
// device_tiki100bus_card_interface overrides
virtual uint8_t iorq_r(offs_t offset, uint8_t data) override;
@@ -45,11 +45,11 @@ private:
uint8_t m_data;
- DECLARE_READ8_MEMBER( read );
- DECLARE_WRITE8_MEMBER( write );
+ uint8_t read();
+ void write(uint8_t data);
- void i8088_io(address_map &map);
- void i8088_mem(address_map &map);
+ void i8088_io(address_map &map) ATTR_COLD;
+ void i8088_mem(address_map &map) ATTR_COLD;
};
diff --git a/src/devices/bus/tiki100/exp.cpp b/src/devices/bus/tiki100/exp.cpp
index 2d3dfc22031..a78b143146d 100644
--- a/src/devices/bus/tiki100/exp.cpp
+++ b/src/devices/bus/tiki100/exp.cpp
@@ -29,9 +29,9 @@ DEFINE_DEVICE_TYPE(TIKI100_BUS_SLOT, tiki100_bus_slot_device, "tiki100bus_slot",
tiki100_bus_slot_device::tiki100_bus_slot_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) :
device_t(mconfig, TIKI100_BUS_SLOT, tag, owner, clock),
- device_slot_interface(mconfig, *this),
+ device_single_card_slot_interface<device_tiki100bus_card_interface>(mconfig, *this),
device_z80daisy_interface(mconfig, *this),
- m_bus(nullptr),
+ m_bus(*this, finder_base::DUMMY_TAG),
m_card(nullptr)
{
}
@@ -43,13 +43,9 @@ tiki100_bus_slot_device::tiki100_bus_slot_device(const machine_config &mconfig,
void tiki100_bus_slot_device::device_start()
{
- m_bus = machine().device<tiki100_bus_device>(TIKI100_BUS_TAG);
- device_tiki100bus_card_interface *dev = dynamic_cast<device_tiki100bus_card_interface *>(get_card_device());
- if (dev)
- {
- m_bus->add_card(dev);
- m_card = dev;
- }
+ m_card = get_card_device();
+ if (m_card)
+ m_bus->add_card(*m_card);
}
@@ -62,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
@@ -74,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();
}
@@ -87,11 +81,11 @@ void tiki100_bus_device::device_start()
// add_card - add card
//-------------------------------------------------
-void tiki100_bus_device::add_card(device_tiki100bus_card_interface *card)
+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;
+ card.m_bus = this;
}
@@ -101,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;
}
@@ -119,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);
}
@@ -135,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;
}
@@ -153,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);
}
@@ -167,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);
}
@@ -189,13 +158,21 @@ WRITE_LINE_MEMBER( tiki100_bus_device::busak_w )
//-------------------------------------------------
device_tiki100bus_card_interface::device_tiki100bus_card_interface(const machine_config &mconfig, device_t &device) :
- device_slot_card_interface(mconfig, device), m_bus(nullptr),
- m_busak(CLEAR_LINE), m_next(nullptr)
+ device_interface(device, "tiki100bus"),
+ m_bus(nullptr),
+ m_busak(CLEAR_LINE)
{
m_slot = dynamic_cast<tiki100_bus_slot_device *>(device.owner());
}
+void device_tiki100bus_card_interface::interface_pre_start()
+{
+ if (!m_bus)
+ throw device_missing_dependencies();
+}
+
+
//-------------------------------------------------
// SLOT_INTERFACE( tiki100_cards )
//-------------------------------------------------
diff --git a/src/devices/bus/tiki100/exp.h b/src/devices/bus/tiki100/exp.h
index 9b0375daaa9..5d21a381c25 100644
--- a/src/devices/bus/tiki100/exp.h
+++ b/src/devices/bus/tiki100/exp.h
@@ -16,14 +16,10 @@
#include "machine/z80daisy.h"
+#include <functional>
+#include <vector>
-//**************************************************************************
-// CONSTANTS
-//**************************************************************************
-
-#define TIKI100_BUS_TAG "tiki100bus"
-
//**************************************************************************
// TYPE DEFINITIONS
@@ -37,14 +33,11 @@ class tiki100_bus_slot_device;
// ======================> device_tiki100bus_card_interface
-class device_tiki100bus_card_interface : public device_slot_card_interface
+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) { }
@@ -64,47 +57,49 @@ protected:
// construction/destruction
device_tiki100bus_card_interface(const machine_config &mconfig, device_t &device);
- tiki100_bus_device *m_bus;
+ virtual void interface_pre_start() override;
+
+ tiki100_bus_device *m_bus;
tiki100_bus_slot_device *m_slot;
int m_busak;
-
-private:
- device_tiki100bus_card_interface *m_next;
};
// ======================> tiki100_bus_slot_device
class tiki100_bus_slot_device : public device_t,
- public device_slot_interface,
+ public device_single_card_slot_interface<device_tiki100bus_card_interface>,
public device_z80daisy_interface
{
public:
// construction/destruction
- template <typename T>
- tiki100_bus_slot_device(const machine_config &mconfig, const char *tag, device_t *owner, T &&opts, const char *dflt)
+ template <typename T, typename U>
+ tiki100_bus_slot_device(const machine_config &mconfig, const char *tag, device_t *owner, T &&bus, U &&opts, const char *dflt)
: tiki100_bus_slot_device(mconfig, tag, owner, 0)
{
option_reset();
opts(*this);
set_default_option(dflt);
set_fixed(false);
+ set_bus(std::forward<T>(bus));
}
tiki100_bus_slot_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock = 0);
- // device-level overrides
- virtual void device_start() override;
+ template <typename T> void set_bus(T &&tag) { m_bus.set_tag(std::forward<T>(tag)); }
protected:
- // device_z80daisy_interface overrides
+ // device_t implementation
+ virtual void device_start() override ATTR_COLD;
+
+ // 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(); }
private:
// configuration
- tiki100_bus_device *m_bus;
+ required_device<tiki100_bus_device> m_bus;
device_tiki100bus_card_interface *m_card;
};
@@ -120,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(); }
@@ -128,7 +123,7 @@ public:
auto mrq_rd_callback() { return m_in_mrq_cb.bind(); }
auto mrq_wr_callback() { return m_out_mrq_cb.bind(); }
- void add_card(device_tiki100bus_card_interface *card);
+ void add_card(device_tiki100bus_card_interface &card);
// computer interface
uint8_t mrq_r(offs_t offset, uint8_t data, bool &mdis);
@@ -137,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
- virtual void device_start() override;
+ // device_t implementation
+ virtual void device_start() override ATTR_COLD;
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/tiki100/hdc.h b/src/devices/bus/tiki100/hdc.h
index d38927ff004..543039ead6a 100644
--- a/src/devices/bus/tiki100/hdc.h
+++ b/src/devices/bus/tiki100/hdc.h
@@ -31,9 +31,9 @@ public:
protected:
// device-level overrides
- virtual void device_start() override;
- virtual void device_reset() override;
- virtual void device_add_mconfig(machine_config &config) override;
+ 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_tiki100bus_card_interface overrides
virtual uint8_t iorq_r(offs_t offset, uint8_t data) override;
diff --git a/src/devices/bus/tim011/aycard.cpp b/src/devices/bus/tim011/aycard.cpp
new file mode 100644
index 00000000000..07dc362d46e
--- /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 ATTR_COLD;
+ virtual void device_reset() override ATTR_COLD;
+
+ // device-level overrides
+ virtual void device_add_mconfig(machine_config &config) override ATTR_COLD;
+ 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..d2138c9b038
--- /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 ATTR_COLD;
+
+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/tmc600/euro.cpp b/src/devices/bus/tmc600/euro.cpp
index aae96b0591a..9da4cf80227 100644
--- a/src/devices/bus/tmc600/euro.cpp
+++ b/src/devices/bus/tmc600/euro.cpp
@@ -2,7 +2,7 @@
// copyright-holders:Curt Coder
/**********************************************************************
- Telercas Telmac TMC-600 euro bus emulation
+ Telercas Telmac TMC-600 Eurobus emulation
**********************************************************************/
@@ -15,7 +15,7 @@
// GLOBAL VARIABLES
//**************************************************************************
-DEFINE_DEVICE_TYPE(TMC600_EURO_BUS_SLOT, tmc600_euro_bus_slot_t, "tmc600_euro_bus_slot", "TMC-600 euro bus slot")
+DEFINE_DEVICE_TYPE(TMC600_EUROBUS_SLOT, tmc600_eurobus_slot_device, "tmc600_eurobus_slot", "Telmac Eurobus slot")
@@ -24,23 +24,23 @@ DEFINE_DEVICE_TYPE(TMC600_EURO_BUS_SLOT, tmc600_euro_bus_slot_t, "tmc600_euro_bu
//**************************************************************************
//-------------------------------------------------
-// device_tmc600_euro_bus_card_interface - constructor
+// device_tmc600_eurobus_card_interface - constructor
//-------------------------------------------------
-device_tmc600_euro_bus_card_interface::device_tmc600_euro_bus_card_interface(const machine_config &mconfig, device_t &device)
- : device_slot_card_interface(mconfig, device)
+device_tmc600_eurobus_card_interface::device_tmc600_eurobus_card_interface(const machine_config &mconfig, device_t &device)
+ : device_interface(device, "telmaceurobus")
{
- m_slot = dynamic_cast<tmc600_euro_bus_slot_t *>(device.owner());
+ m_slot = dynamic_cast<tmc600_eurobus_slot_device *>(device.owner());
}
//-------------------------------------------------
-// tmc600_euro_bus_slot_t - constructor
+// tmc600_eurobus_slot_device - constructor
//-------------------------------------------------
-tmc600_euro_bus_slot_t::tmc600_euro_bus_slot_t(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) :
- device_t(mconfig, TMC600_EURO_BUS_SLOT, tag, owner, clock),
- device_slot_interface(mconfig, *this)
+tmc600_eurobus_slot_device::tmc600_eurobus_slot_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) :
+ device_t(mconfig, TMC600_EUROBUS_SLOT, tag, owner, clock),
+ device_single_card_slot_interface<device_tmc600_eurobus_card_interface>(mconfig, *this)
{
}
@@ -49,17 +49,17 @@ tmc600_euro_bus_slot_t::tmc600_euro_bus_slot_t(const machine_config &mconfig, co
// device_start - device-specific startup
//-------------------------------------------------
-void tmc600_euro_bus_slot_t::device_start()
+void tmc600_eurobus_slot_device::device_start()
{
- m_card = dynamic_cast<device_tmc600_euro_bus_card_interface *>(get_card_device());
+ m_card = get_card_device();
}
//-------------------------------------------------
-// SLOT_INTERFACE( tmc600_euro_bus_cards )
+// SLOT_INTERFACE( tmc600_eurobus_cards )
//-------------------------------------------------
-void tmc600_euro_bus_cards(device_slot_interface &device)
+void tmc600_eurobus_cards(device_slot_interface &device)
{
//device.option_add("tmc710", TMC710); // 5-way expander
//device.option_add("tmc720", TMC720); // 5-way expander (new model)
diff --git a/src/devices/bus/tmc600/euro.h b/src/devices/bus/tmc600/euro.h
index 51a4e435f2f..bf2e95ded78 100644
--- a/src/devices/bus/tmc600/euro.h
+++ b/src/devices/bus/tmc600/euro.h
@@ -2,7 +2,7 @@
// copyright-holders:Curt Coder
/**********************************************************************
- Telercas Telmac TMC-600 euro bus emulation
+ Telercas Telmac TMC-600 Eurobus emulation
**********************************************************************
@@ -42,52 +42,42 @@
**********************************************************************/
-#ifndef MAME_DEVICES_TMC600_EURO_H
-#define MAME_DEVICES_TMC600_EURO_H
+#ifndef MAME_BUS_TMC600_EURO_H
+#define MAME_BUS_TMC600_EURO_H
#pragma once
//**************************************************************************
-// CONSTANTS
-//**************************************************************************
-
-#define TMC600_EURO_BUS_TAG "bus"
-
-
-//**************************************************************************
// TYPE DEFINITIONS
//**************************************************************************
-// ======================> device_tmc600_euro_bus_card_interface
+// ======================> device_tmc600_eurobus_card_interface
-class tmc600_euro_bus_slot_t;
+class tmc600_eurobus_slot_device;
-class device_tmc600_euro_bus_card_interface : public device_slot_card_interface
+class device_tmc600_eurobus_card_interface : public device_interface
{
-public:
-
protected:
// construction/destruction
- device_tmc600_euro_bus_card_interface(const machine_config &mconfig, device_t &device);
+ device_tmc600_eurobus_card_interface(const machine_config &mconfig, device_t &device);
- tmc600_euro_bus_slot_t *m_slot;
+ tmc600_eurobus_slot_device *m_slot;
- friend class tmc600_euro_bus_slot_t;
+ friend class tmc600_eurobus_slot_device;
};
-// ======================> tmc600_euro_bus_slot_t
+// ======================> tmc600_eurobus_slot_device
-class tmc600_euro_bus_slot_t : public device_t,
- public device_slot_interface
+class tmc600_eurobus_slot_device : public device_t, public device_single_card_slot_interface<device_tmc600_eurobus_card_interface>
{
public:
// construction/destruction
template <typename T>
- tmc600_euro_bus_slot_t(const machine_config &mconfig, const char *tag, device_t *owner, T &&opts, const char *dflt)
- : tmc600_euro_bus_slot_t(mconfig, tag, owner, 0)
+ tmc600_eurobus_slot_device(const machine_config &mconfig, const char *tag, device_t *owner, T &&opts, const char *dflt)
+ : tmc600_eurobus_slot_device(mconfig, tag, owner, 0)
{
option_reset();
opts(*this);
@@ -95,25 +85,23 @@ public:
set_fixed(false);
}
- tmc600_euro_bus_slot_t(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock = 0);
+ tmc600_eurobus_slot_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock = 0);
protected:
// device-level overrides
- virtual void device_start() override;
- virtual void device_reset() override { if (m_card) get_card_device()->reset(); }
+ virtual void device_start() override ATTR_COLD;
- device_tmc600_euro_bus_card_interface *m_card;
+ device_tmc600_eurobus_card_interface *m_card;
};
// device type definition
-DECLARE_DEVICE_TYPE(TMC600_EURO_BUS_SLOT, tmc600_euro_bus_slot_t)
-
+DECLARE_DEVICE_TYPE(TMC600_EUROBUS_SLOT, tmc600_eurobus_slot_device)
-void tmc600_euro_bus_cards(device_slot_interface &device);
+void tmc600_eurobus_cards(device_slot_interface &device);
-typedef device_type_iterator<tmc600_euro_bus_slot_t> tmc600_euro_bus_slot_t_iterator;
+typedef device_type_enumerator<tmc600_eurobus_slot_device> tmc600_eurobus_slot_enumerator;
-#endif // MAME_DEVICES_TMC600_EURO_H
+#endif // MAME_BUS_TMC600_EURO_H
diff --git a/src/devices/bus/tvc/hbf.cpp b/src/devices/bus/tvc/hbf.cpp
index bb9dcae91db..43d95a753a3 100644
--- a/src/devices/bus/tvc/hbf.cpp
+++ b/src/devices/bus/tvc/hbf.cpp
@@ -9,14 +9,18 @@
#include "emu.h"
#include "hbf.h"
+#include "formats/tvc_dsk.h"
+
/***************************************************************************
IMPLEMENTATION
***************************************************************************/
-FLOPPY_FORMATS_MEMBER( tvc_hbf_device::floppy_formats )
- FLOPPY_TVC_FORMAT
-FLOPPY_FORMATS_END
+void tvc_hbf_device::floppy_formats(format_registration &fr)
+{
+ fr.add_mfm_containers();
+ fr.add(FLOPPY_TVC_FORMAT);
+}
static void tvc_hbf_floppies(device_slot_interface &device)
{
@@ -105,7 +109,7 @@ const tiny_rom_entry *tvc_hbf_device::device_rom_region() const
/*-------------------------------------------------
read
-------------------------------------------------*/
-READ8_MEMBER(tvc_hbf_device::read)
+uint8_t tvc_hbf_device::read(offs_t offset)
{
if (offset>=0x1000)
return m_ram[offset& 0x0fff];
@@ -117,7 +121,7 @@ READ8_MEMBER(tvc_hbf_device::read)
// write
//-------------------------------------------------
-WRITE8_MEMBER(tvc_hbf_device::write)
+void tvc_hbf_device::write(offs_t offset, uint8_t data)
{
if (offset>=0x1000)
m_ram[offset & 0x0fff] = data;
@@ -130,7 +134,7 @@ WRITE8_MEMBER(tvc_hbf_device::write)
// IO read
//-------------------------------------------------
-READ8_MEMBER(tvc_hbf_device::io_read)
+uint8_t tvc_hbf_device::io_read(offs_t offset)
{
switch((offset>>2) & 0x03)
{
@@ -147,7 +151,7 @@ READ8_MEMBER(tvc_hbf_device::io_read)
// IO write
//-------------------------------------------------
-WRITE8_MEMBER(tvc_hbf_device::io_write)
+void tvc_hbf_device::io_write(offs_t offset, uint8_t data)
{
switch((offset>>2) & 0x03)
{
diff --git a/src/devices/bus/tvc/hbf.h b/src/devices/bus/tvc/hbf.h
index cc154d71294..c344e2ed9e3 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"
//**************************************************************************
@@ -27,20 +26,20 @@ public:
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;
+ 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;
+ virtual const tiny_rom_entry *device_rom_region() const override ATTR_COLD;
// tvcexp_interface overrides
virtual uint8_t id_r() override { return 0x02; } // ID_A to GND, ID_B to VCC
- virtual DECLARE_READ8_MEMBER(read) override;
- virtual DECLARE_WRITE8_MEMBER(write) override;
- virtual DECLARE_READ8_MEMBER(io_read) override;
- virtual DECLARE_WRITE8_MEMBER(io_write) override;
+ virtual uint8_t read(offs_t offset) override;
+ virtual void write(offs_t offset, uint8_t data) override;
+ virtual uint8_t io_read(offs_t offset) override;
+ virtual void io_write(offs_t offset, uint8_t data) override;
private:
- DECLARE_FLOPPY_FORMATS( floppy_formats );
+ static void floppy_formats(format_registration &fr);
// internal state
required_device<fd1793_device> m_fdc;
diff --git a/src/devices/bus/tvc/tvc.cpp b/src/devices/bus/tvc/tvc.cpp
index 0f165e0395f..c1c8dc902e6 100644
--- a/src/devices/bus/tvc/tvc.cpp
+++ b/src/devices/bus/tvc/tvc.cpp
@@ -30,7 +30,7 @@ DEFINE_DEVICE_TYPE(TVCEXP_SLOT, tvcexp_slot_device, "tvcexp_slot", "TVC64 Expans
//-------------------------------------------------
device_tvcexp_interface::device_tvcexp_interface(const machine_config &mconfig, device_t &device)
- : device_slot_card_interface(mconfig, device)
+ : device_interface(device, "tvc64exp")
{
}
@@ -53,7 +53,7 @@ device_tvcexp_interface::~device_tvcexp_interface()
//-------------------------------------------------
tvcexp_slot_device::tvcexp_slot_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) :
device_t(mconfig, TVCEXP_SLOT, tag, owner, clock),
- device_slot_interface(mconfig, *this),
+ device_single_card_slot_interface<device_tvcexp_interface>(mconfig, *this),
m_out_irq_cb(*this),
m_out_nmi_cb(*this),
m_cart(nullptr)
@@ -74,11 +74,7 @@ tvcexp_slot_device::~tvcexp_slot_device()
void tvcexp_slot_device::device_start()
{
- m_cart = dynamic_cast<device_tvcexp_interface *>(get_card_device());
-
- // resolve callbacks
- m_out_irq_cb.resolve_safe();
- m_out_nmi_cb.resolve_safe();
+ m_cart = get_card_device();
}
/*-------------------------------------------------
@@ -124,10 +120,10 @@ uint8_t tvcexp_slot_device::int_r()
read
-------------------------------------------------*/
-READ8_MEMBER(tvcexp_slot_device::read)
+uint8_t tvcexp_slot_device::read(offs_t offset)
{
if (m_cart)
- return m_cart->read(space, offset);
+ return m_cart->read(offset);
else
return 0x00;
}
@@ -137,20 +133,20 @@ READ8_MEMBER(tvcexp_slot_device::read)
write
-------------------------------------------------*/
-WRITE8_MEMBER(tvcexp_slot_device::write)
+void tvcexp_slot_device::write(offs_t offset, uint8_t data)
{
if (m_cart)
- m_cart->write(space, offset, data);
+ m_cart->write(offset, data);
}
/*-------------------------------------------------
IO read
-------------------------------------------------*/
-READ8_MEMBER(tvcexp_slot_device::io_read)
+uint8_t tvcexp_slot_device::io_read(offs_t offset)
{
if (m_cart)
- return m_cart->io_read(space, offset);
+ return m_cart->io_read(offset);
else
return 0x00;
}
@@ -160,8 +156,8 @@ READ8_MEMBER(tvcexp_slot_device::io_read)
IO write
-------------------------------------------------*/
-WRITE8_MEMBER(tvcexp_slot_device::io_write)
+void tvcexp_slot_device::io_write(offs_t offset, uint8_t data)
{
if (m_cart)
- m_cart->io_write(space, offset, data);
+ m_cart->io_write(offset, data);
}
diff --git a/src/devices/bus/tvc/tvc.h b/src/devices/bus/tvc/tvc.h
index 09ba7b35ffd..840cb9ef717 100644
--- a/src/devices/bus/tvc/tvc.h
+++ b/src/devices/bus/tvc/tvc.h
@@ -65,7 +65,7 @@
// ======================> device_tvcexp_interface
-class device_tvcexp_interface : public device_slot_card_interface
+class device_tvcexp_interface : public device_interface
{
public:
// construction/destruction
@@ -75,10 +75,10 @@ public:
virtual uint8_t id_r() { return 0x00; } // ID_A and ID_B lines
virtual void int_ack() { }
virtual uint8_t int_r() { return 1; }
- virtual DECLARE_READ8_MEMBER(read) { return 0x00; }
- virtual DECLARE_WRITE8_MEMBER(write) { }
- virtual DECLARE_READ8_MEMBER(io_read) { return 0x00; }
- virtual DECLARE_WRITE8_MEMBER(io_write) { }
+ virtual uint8_t read(offs_t offset) { return 0x00; }
+ virtual void write(offs_t offset, uint8_t data) { }
+ virtual uint8_t io_read(offs_t offset) { return 0x00; }
+ virtual void io_write(offs_t offset, uint8_t data) { }
protected:
device_tvcexp_interface(const machine_config &mconfig, device_t &device);
@@ -86,8 +86,7 @@ protected:
// ======================> tvcexp_slot_device
-class tvcexp_slot_device : public device_t,
- public device_slot_interface
+class tvcexp_slot_device : public device_t, public device_single_card_slot_interface<device_tvcexp_interface>
{
public:
// construction/destruction
@@ -108,17 +107,17 @@ public:
auto out_nmi_callback() { return m_out_nmi_cb.bind(); }
// reading and writing
- virtual uint8_t id_r();
- virtual void int_ack();
- virtual uint8_t int_r();
- virtual DECLARE_READ8_MEMBER(read);
- virtual DECLARE_WRITE8_MEMBER(write);
- virtual DECLARE_READ8_MEMBER(io_read);
- virtual DECLARE_WRITE8_MEMBER(io_write);
+ uint8_t id_r();
+ void int_ack();
+ uint8_t int_r();
+ uint8_t read(offs_t offset);
+ void write(offs_t offset, uint8_t data);
+ uint8_t io_read(offs_t offset);
+ void io_write(offs_t offset, uint8_t data);
protected:
// device-level overrides
- virtual void device_start() override;
+ virtual void device_start() override ATTR_COLD;
devcb_write_line m_out_irq_cb;
devcb_write_line m_out_nmi_cb;
diff --git a/src/devices/bus/uts_kbd/400kbd.cpp b/src/devices/bus/uts_kbd/400kbd.cpp
index 38d35fda607..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;
@@ -112,7 +112,7 @@ static INPUT_PORTS_START(uts_400kbd)
PORT_BIT(0x03, IP_ACTIVE_LOW, IPT_UNUSED)
PORT_BIT(0x04, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CHAR(']') PORT_CHAR('}') PORT_CODE(KEYCODE_CLOSEBRACE)
PORT_BIT(0x08, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("Return") PORT_CHAR(0x0d) PORT_CODE(KEYCODE_ENTER)
- PORT_BIT(0x10, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CHAR('`') PORT_CHAR('@') PORT_CODE(KEYCODE_EQUALS)
+ 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_CHAR('[') PORT_CHAR('{') PORT_CODE(KEYCODE_OPENBRACE)
PORT_BIT(0x40, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CHAR('-') PORT_CHAR('=') PORT_CODE(KEYCODE_MINUS)
PORT_BIT(0x80, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CHAR('^') PORT_CHAR('~') PORT_CODE(KEYCODE_TILDE)
@@ -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..37b1ed5f1d3 100644
--- a/src/devices/bus/uts_kbd/400kbd.h
+++ b/src/devices/bus/uts_kbd/400kbd.h
@@ -14,21 +14,21 @@ 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;
- 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 ATTR_COLD;
+ virtual void device_start() override ATTR_COLD;
+ virtual void device_add_mconfig(machine_config &config) override ATTR_COLD;
+ virtual const tiny_rom_entry *device_rom_region() const override ATTR_COLD;
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);
+ void ext_map(address_map &map) ATTR_COLD;
required_ioport_array<16> m_keys;
output_finder<> m_shift_led;
diff --git a/src/devices/bus/uts_kbd/extw.cpp b/src/devices/bus/uts_kbd/extw.cpp
index 950d8b244f2..2502e0a5feb 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)
{
@@ -151,7 +151,7 @@ static INPUT_PORTS_START(uts_extw)
PORT_BIT(0x80, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("B") PORT_CHAR('b') PORT_CHAR('B') PORT_CODE(KEYCODE_B)
PORT_START("KEY4")
- PORT_BIT(0x01, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("SOE \xe2\x96\xb6 Tab Set") PORT_CODE(KEYCODE_LALT) // ▶
+ PORT_BIT(0x01, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME(u8"SOE \u25b6 Tab Set") PORT_CODE(KEYCODE_LALT) // ▶
PORT_BIT(0x02, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("Insert in Line Insert in Disp") PORT_CHAR(UCHAR_MAMEKEY(INSERT)) PORT_CODE(KEYCODE_INSERT)
PORT_BIT(0x04, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("Delete in Line Delete in Disp") PORT_CHAR(UCHAR_MAMEKEY(DEL)) PORT_CODE(KEYCODE_DEL)
PORT_BIT(0x08, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("Cursor to Home") PORT_CHAR(UCHAR_MAMEKEY(HOME)) PORT_CODE(KEYCODE_HOME) // ↖
diff --git a/src/devices/bus/uts_kbd/extw.h b/src/devices/bus/uts_kbd/extw.h
index 21599139ec1..e3fb4da9273 100644
--- a/src/devices/bus/uts_kbd/extw.h
+++ b/src/devices/bus/uts_kbd/extw.h
@@ -14,23 +14,23 @@ 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;
- 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 ATTR_COLD;
+ virtual void device_start() override ATTR_COLD;
+ virtual void device_add_mconfig(machine_config &config) override ATTR_COLD;
+ virtual const tiny_rom_entry *device_rom_region() const override ATTR_COLD;
private:
u8 p1_r();
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);
+ void prog_map(address_map &map) ATTR_COLD;
+ void ext_map(address_map &map) ATTR_COLD;
required_ioport_array<16> m_keys;
output_finder<> m_shift_led;
diff --git a/src/devices/bus/uts_kbd/uts_kbd.cpp b/src/devices/bus/uts_kbd/uts_kbd.cpp
index d652dbfca80..5f1cc77eab5 100644
--- a/src/devices/bus/uts_kbd/uts_kbd.cpp
+++ b/src/devices/bus/uts_kbd/uts_kbd.cpp
@@ -39,7 +39,7 @@ DEFINE_DEVICE_TYPE(UTS_KEYBOARD, uts_keyboard_port_device, "uts_kbd", "UTS Keybo
uts_keyboard_port_device::uts_keyboard_port_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock)
: device_t(mconfig, UTS_KEYBOARD, tag, owner, clock)
- , device_slot_interface(mconfig, *this)
+ , device_single_card_slot_interface<device_uts_keyboard_interface>(mconfig, *this)
, m_rxd_callback(*this)
, m_kbd(nullptr)
{
@@ -47,12 +47,7 @@ uts_keyboard_port_device::uts_keyboard_port_device(const machine_config &mconfig
void uts_keyboard_port_device::device_config_complete()
{
- m_kbd = dynamic_cast<device_uts_keyboard_interface *>(get_card_device());
-}
-
-void uts_keyboard_port_device::device_resolve_objects()
-{
- m_rxd_callback.resolve_safe();
+ m_kbd = get_card_device();
}
void uts_keyboard_port_device::device_start()
@@ -64,7 +59,7 @@ void uts_keyboard_port_device::device_start()
//**************************************************************************
device_uts_keyboard_interface::device_uts_keyboard_interface(const machine_config &mconfig, device_t &device)
- : device_slot_card_interface(mconfig, device)
+ : device_interface(device, "utskbd")
, m_port(device, DEVICE_SELF_OWNER)
{
}
diff --git a/src/devices/bus/uts_kbd/uts_kbd.h b/src/devices/bus/uts_kbd/uts_kbd.h
index 7cfff95c0fe..873de3ee9e7 100644
--- a/src/devices/bus/uts_kbd/uts_kbd.h
+++ b/src/devices/bus/uts_kbd/uts_kbd.h
@@ -21,7 +21,7 @@ class device_uts_keyboard_interface;
// ======================> uts_keyboard_port_device
-class uts_keyboard_port_device : public device_t, public device_slot_interface
+class uts_keyboard_port_device : public device_t, public device_single_card_slot_interface<device_uts_keyboard_interface>
{
friend class device_uts_keyboard_interface;
@@ -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;
+ virtual void device_start() override ATTR_COLD;
// 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
@@ -63,7 +62,7 @@ private:
// ======================> device_uts_keyboard_interface
-class device_uts_keyboard_interface : public device_slot_card_interface
+class device_uts_keyboard_interface : public device_interface
{
friend class uts_keyboard_port_device;
@@ -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 6c6117c8a9b..20ba18ff62a 100644
--- a/src/devices/bus/vboy/rom.cpp
+++ b/src/devices/bus/vboy/rom.cpp
@@ -1,59 +1,195 @@
// license:BSD-3-Clause
-// copyright-holders:Fabio Priuli
-/***********************************************************************************************************
+// copyright-holders:Vas Crabb
+/***************************************************************************
+ Virtual Boy cartridges
+ ***************************************************************************/
+#include "emu.h"
+#include "rom.h"
+#include "bus/generic/slot.h"
- Nintendo Virtual Boy cart emulation
+//#define VERBOSE 1
+//#define LOG_OUTPUT_FUNC osd_printf_info
+#include "logmacro.h"
- ***********************************************************************************************************/
+//**************************************************************************
+// GLOBAL VARIABLES
+//**************************************************************************
+DEFINE_DEVICE_TYPE(VBOY_FLAT_ROM, vboy_flat_rom_device, "vboy_flatrom", "Nintendo Virtual Boy Flat ROM Cartridge")
+DEFINE_DEVICE_TYPE(VBOY_FLAT_ROM_SRAM, vboy_flat_rom_sram_device, "vboy_flatrom_sram", "Nintendo Virtual Boy Flat ROM Cartridge with Backup SRAM")
-#include "emu.h"
-#include "rom.h"
-//-------------------------------------------------
-// vboy_rom_device - constructor
-//-------------------------------------------------
+//**************************************************************************
+// vboy_flat_rom_device
+//**************************************************************************
-DEFINE_DEVICE_TYPE(VBOY_ROM_STD, vboy_rom_device, "vboy_rom", "Nintendo Virtual Boy Carts")
-DEFINE_DEVICE_TYPE(VBOY_ROM_EEPROM, vboy_eeprom_device, "vboy_eeprom", "Nintendo Virtual Boy Carts + EEPROM")
+vboy_flat_rom_device::vboy_flat_rom_device(machine_config const &mconfig, char const *tag, device_t *owner, u32 clock) :
+ vboy_flat_rom_device(mconfig, VBOY_FLAT_ROM, tag, owner, clock)
+{
+}
-vboy_rom_device::vboy_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_vboy_cart_interface(mconfig, *this)
+vboy_flat_rom_device::vboy_flat_rom_device(machine_config const &mconfig, device_type type, char const *tag, device_t *owner, u32 clock) :
+ device_t(mconfig, type, tag, owner, clock),
+ device_vboy_cart_interface(mconfig, *this)
{
}
-vboy_rom_device::vboy_rom_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
- : vboy_rom_device(mconfig, VBOY_ROM_STD, tag, owner, clock)
+
+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"));
+ if (rom_space() && romregion)
+ {
+ // the slot should have verified that the ROM is a supported size
+ assert(!(romregion->bytes() & 0x0000'0003U));
+ assert(romregion->bytes() <= 0x0100'0000U);
+
+ // this should fail a validity check
+ assert(!(rom_base() & 0x00ff'ffff));
+
+ // This is a simplification that improves performance. In
+ // reality, cartridge ROM is 16 bits wide and 32-bit accesses
+ // are split up automatically. MAME doesn't really support
+ // dynamic bus sizing, and it's a lot faster to execute from a
+ // ROM handler than to go through the trampolines necessary to
+ // emulate 16-bit accesses.
+ device_generic_cart_interface::install_non_power_of_two<2>(
+ romregion->bytes() >> 2,
+ 0x00ff'ffff >> 2,
+ 0,
+ rom_base(),
+ [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",
+ src << 2,
+ (src << 2) + (end - begin),
+ begin,
+ end,
+ mirror);
+ rom_space()->install_rom(begin, end, mirror, &rom[src]);
+ });
+ }
+
+ return std::error_condition();
}
-vboy_eeprom_device::vboy_eeprom_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
- : vboy_rom_device(mconfig, VBOY_ROM_EEPROM, tag, owner, clock)
+
+void vboy_flat_rom_device::device_start()
{
}
-/*-------------------------------------------------
- mapper specific handlers
- -------------------------------------------------*/
-READ32_MEMBER(vboy_rom_device::read_cart)
+//**************************************************************************
+// vboy_flat_rom_sram_device
+//**************************************************************************
+
+vboy_flat_rom_sram_device::vboy_flat_rom_sram_device(machine_config const &mconfig, char const *tag, device_t *owner, u32 clock) :
+ vboy_flat_rom_device(mconfig, VBOY_FLAT_ROM_SRAM, tag, owner, clock)
{
- return m_rom[offset & m_rom_mask];
}
-READ32_MEMBER(vboy_eeprom_device::read_eeprom)
+std::error_condition vboy_flat_rom_sram_device::load()
{
- return m_eeprom[offset];
+ std::error_condition const result(vboy_flat_rom_device::load());
+ if (result)
+ return result;
+
+ memory_region *const sramregion(memregion("^sram"));
+ if (sramregion)
+ {
+ // this should fail a validity check
+ assert(!(chip_base() & 0x00ff'ffff));
+
+ switch (sramregion->bitwidth())
+ {
+ case 8:
+ if (chip_space())
+ {
+ device_generic_cart_interface::install_non_power_of_two<2>(
+ sramregion->bytes() >> 1,
+ 0x00ff'ffff >> 2,
+ 0,
+ chip_base(),
+ [this, sramregion] (offs_t begin, offs_t end, offs_t mirror, offs_t src)
+ {
+ LOG(
+ "Install SRAM 0x%08X-0x%08X at 0x%08X-0x%08X mirror %08X\n",
+ src << 1,
+ (src << 1) + ((end - begin) >> 1),
+ begin,
+ end,
+ mirror);
+ u8 *const base(&reinterpret_cast<u8 *>(sramregion->base())[src << 1]);
+ chip_space()->install_readwrite_handler(
+ begin,
+ end,
+ 0,
+ mirror,
+ 0,
+ read8sm_delegate(*this, NAME([base] (offs_t offset) { return base[offset]; })),
+ write8sm_delegate(*this, NAME([base] (offs_t offset, u8 data) { base[offset] = data; })),
+ 0x00ff'00ff);
+ });
+ }
+ save_pointer(NAME(&sramregion->as_u8()), sramregion->bytes());
+ break;
+
+ case 16:
+ if (chip_space())
+ {
+ device_generic_cart_interface::install_non_power_of_two<2>(
+ sramregion->bytes() >> 2,
+ 0x00ff'ffff >> 2,
+ 0,
+ chip_base(),
+ [this, sramregion] (offs_t begin, offs_t end, offs_t mirror, offs_t src)
+ {
+ LOG(
+ "Install SRAM 0x%08X-0x%08X at 0x%08X-0x%08X mirror %08X\n",
+ src << 2,
+ (src << 2) + (end - begin),
+ begin,
+ end,
+ mirror);
+ u16 *const base(&reinterpret_cast<u16 *>(sramregion->base())[src << 1]);
+ chip_space()->install_readwrite_handler(
+ begin,
+ end,
+ 0,
+ mirror,
+ 0,
+ read16s_delegate(*this, NAME([base] (offs_t offset, u16 mem_mask) { return base[offset]; })),
+ write16s_delegate(*this, NAME([base] (offs_t offset, u16 data, u16 mem_mask) { COMBINE_DATA(base + offset); })),
+ 0xffff'ffff);
+ });
+ }
+ save_pointer(NAME(&sramregion->as_u16()), sramregion->bytes() >> 1);
+ break;
+
+ default:
+ throw emu_fatalerror("Unsupported Virtual Boy cartridge backup RAM width\n");
+ }
+
+ battery_load(sramregion->base(), sramregion->bytes(), nullptr);
+ }
+
+ return std::error_condition();
}
-WRITE32_MEMBER(vboy_eeprom_device::write_eeprom)
+void vboy_flat_rom_sram_device::unload()
{
- COMBINE_DATA(&m_eeprom[offset]);
+ vboy_flat_rom_device::unload();
+
+ memory_region *const sramregion(memregion("^sram"));
+ if (sramregion)
+ battery_save(sramregion->base(), sramregion->bytes());
}
diff --git a/src/devices/bus/vboy/rom.h b/src/devices/bus/vboy/rom.h
index 6963a09fb9c..5e369783a10 100644
--- a/src/devices/bus/vboy/rom.h
+++ b/src/devices/bus/vboy/rom.h
@@ -1,5 +1,5 @@
// license:BSD-3-Clause
-// copyright-holders:Fabio Priuli
+// copyright-holders:Vas Crabb
#ifndef MAME_BUS_VBOY_ROM_H
#define MAME_BUS_VBOY_ROM_H
@@ -8,41 +8,43 @@
#include "slot.h"
-// ======================> vboy_rom_device
+//**************************************************************************
+// CLASS DECLARATIONS
+//**************************************************************************
-class vboy_rom_device : public device_t,
- public device_vboy_cart_interface
+class vboy_flat_rom_device : public device_t, public device_vboy_cart_interface
{
public:
- // construction/destruction
- vboy_rom_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
+ vboy_flat_rom_device(machine_config const &mconfig, char const *tag, device_t *owner, u32 clock);
- // reading and writing
- virtual DECLARE_READ32_MEMBER(read_cart) override;
+ // device_vboy_cart_interface implementation
+ virtual std::error_condition load() override ATTR_COLD;
protected:
- vboy_rom_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock);
+ vboy_flat_rom_device(machine_config const &mconfig, device_type type, char const *tag, device_t *owner, u32 clock);
- // device-level overrides
- virtual void device_start() override { }
+ // device_t implementation
+ virtual void device_start() override ATTR_COLD;
};
-// ======================> vboy_eeprom_device
-class vboy_eeprom_device : public vboy_rom_device
+class vboy_flat_rom_sram_device : public vboy_flat_rom_device
{
public:
- // construction/destruction
- vboy_eeprom_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
+ vboy_flat_rom_sram_device(machine_config const &mconfig, char const *tag, device_t *owner, u32 clock);
- // reading and writing
- virtual DECLARE_READ32_MEMBER(read_eeprom) override;
- virtual DECLARE_WRITE32_MEMBER(write_eeprom) override;
+ // device_vboy_cart_interface implementation
+ virtual std::error_condition load() override ATTR_COLD;
+ virtual void unload() override ATTR_COLD;
};
-// device type definition
-DECLARE_DEVICE_TYPE(VBOY_ROM_STD, vboy_rom_device)
-DECLARE_DEVICE_TYPE(VBOY_ROM_EEPROM, vboy_eeprom_device)
+
+//**************************************************************************
+// DEVICE TYPE DECLARATIONS
+//**************************************************************************
+
+DECLARE_DEVICE_TYPE(VBOY_FLAT_ROM, vboy_flat_rom_device)
+DECLARE_DEVICE_TYPE(VBOY_FLAT_ROM_SRAM, vboy_flat_rom_sram_device)
#endif // MAME_BUS_VBOY_ROM_H
diff --git a/src/devices/bus/vboy/slot.cpp b/src/devices/bus/vboy/slot.cpp
index 6ed81901d12..9b9cf4e88ea 100644
--- a/src/devices/bus/vboy/slot.cpp
+++ b/src/devices/bus/vboy/slot.cpp
@@ -1,250 +1,181 @@
// license:BSD-3-Clause
-// copyright-holders:Fabio Priuli
-/***********************************************************************************************************
-
- Nintendo Virtual Boy cart emulation
- (through slot devices)
-
- ***********************************************************************************************************/
+// copyright-holders:Vas Crabb
+/***************************************************************************
+ Virtual Boy cartridge slot
+ TODO:
+ - Sound capabilities
+ ***************************************************************************/
#include "emu.h"
#include "slot.h"
+#include "emuopts.h"
+#include "romload.h"
+#include "softlist.h"
+
+#include <cstring>
+
+//#define VERBOSE 1
+//#define LOG_OUTPUT_FUNC osd_printf_info
+#include "logmacro.h"
+
+
//**************************************************************************
// GLOBAL VARIABLES
//**************************************************************************
DEFINE_DEVICE_TYPE(VBOY_CART_SLOT, vboy_cart_slot_device, "vboy_cart_slot", "Nintendo Virtual Boy Cartridge Slot")
+
+
//**************************************************************************
-// vboy cartridges Interface
+// vboy_cart_slot_device
//**************************************************************************
-//-------------------------------------------------
-// device_vboy_cart_interface - constructor
-//-------------------------------------------------
-
-device_vboy_cart_interface::device_vboy_cart_interface(const machine_config &mconfig, device_t &device)
- : device_slot_card_interface(mconfig, device),
- m_rom(nullptr),
- m_rom_size(0),
- m_rom_mask(0)
+vboy_cart_slot_device::vboy_cart_slot_device(machine_config const &mconfig, char const *tag, device_t *owner, u32 clock) :
+ device_t(mconfig, VBOY_CART_SLOT, tag, owner, clock),
+ device_cartrom_image_interface(mconfig, *this),
+ device_single_card_slot_interface<device_vboy_cart_interface>(mconfig, *this),
+ m_intcro(*this),
+ m_exp_space(*this, finder_base::DUMMY_TAG, -1, 32),
+ m_chip_space(*this, finder_base::DUMMY_TAG, -1, 32),
+ m_rom_space(*this, finder_base::DUMMY_TAG, -1, 32),
+ m_exp_base(0U),
+ m_chip_base(0U),
+ m_rom_base(0U),
+ m_cart(nullptr)
{
}
-//-------------------------------------------------
-// ~device_vboy_cart_interface - destructor
-//-------------------------------------------------
-
-device_vboy_cart_interface::~device_vboy_cart_interface()
+std::pair<std::error_condition, std::string> vboy_cart_slot_device::call_load()
{
-}
+ if (!m_cart)
+ return std::make_pair(std::error_condition(), std::string());
-//-------------------------------------------------
-// rom_alloc - alloc the space for the 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");
-void device_vboy_cart_interface::rom_alloc(uint32_t size, const char *tag)
-{
- if (m_rom == nullptr)
+ u32 const len(loaded_through_softlist() ? romregion->bytes() : length());
+ if ((0x0000'0003 & len) || (0x0100'0000 < len))
+ 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())
{
- m_rom = (uint32_t *)device().machine().memory().region_alloc(std::string(tag).append(VBOYSLOT_ROM_REGION_TAG).c_str(), size, 4, ENDIANNESS_LITTLE)->base();
- m_rom_size = size/4;
- m_rom_mask = m_rom_size - 1;
+ LOG("Allocating %u byte cartridge ROM region\n", 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)
+ {
+ for (u32 i = 0; (len / 4) > i; ++i)
+ rombase[i] = swapendian_int32(rombase[i]);
+ }
}
-}
-
-//-------------------------------------------------
-// ram_alloc - alloc the space for the ram
-//-------------------------------------------------
-
-void device_vboy_cart_interface::eeprom_alloc(uint32_t size)
-{
- m_eeprom.resize(size/sizeof(uint32_t));
+ return std::make_pair(m_cart->load(), std::string());
}
-//**************************************************************************
-// LIVE DEVICE
-//**************************************************************************
-
-//-------------------------------------------------
-// vboy_cart_slot_device - constructor
-//-------------------------------------------------
-vboy_cart_slot_device::vboy_cart_slot_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) :
- device_t(mconfig, VBOY_CART_SLOT, tag, owner, clock),
- device_image_interface(mconfig, *this),
- device_slot_interface(mconfig, *this),
- m_type(VBOY_STD),
- m_cart(nullptr)
+void vboy_cart_slot_device::call_unload()
{
+ if (m_cart)
+ m_cart->unload();
}
-//-------------------------------------------------
-// vboy_cart_slot_device - destructor
-//-------------------------------------------------
-
-vboy_cart_slot_device::~vboy_cart_slot_device()
+void vboy_cart_slot_device::device_validity_check(validity_checker &valid) const
{
-}
+ if (m_exp_base & 0x00ff'ffff)
+ osd_printf_error("EXP base address 0x%X is not on a 24-bit boundary\n", m_exp_base);
-//-------------------------------------------------
-// device_start - device-specific startup
-//-------------------------------------------------
+ if (m_chip_base & 0x00ff'ffff)
+ osd_printf_error("CHIP base address 0x%X is not on a 24-bit boundary\n", m_chip_base);
-void vboy_cart_slot_device::device_start()
-{
- m_cart = dynamic_cast<device_vboy_cart_interface *>(get_card_device());
+ if (m_rom_base & 0x00ff'ffff)
+ osd_printf_error("ROM base address 0x%X is not on a 24-bit boundary\n", m_rom_base);
}
-//-------------------------------------------------
-// vboy PCB
-//-------------------------------------------------
-
-struct vboy_slot
+void vboy_cart_slot_device::device_start()
{
- int pcb_id;
- const char *slot_option;
-};
+ if (!m_exp_space && ((m_exp_space.finder_tag() != finder_base::DUMMY_TAG) || (m_exp_space.spacenum() >= 0)))
+ throw emu_fatalerror("%s: Address space %d of device %s not found (EXP)\n", tag(), m_exp_space.spacenum(), m_exp_space.finder_tag());
-// Here, we take the feature attribute from .xml (i.e. the PCB name) and we assign a unique ID to it
-static const vboy_slot slot_list[] =
-{
- { VBOY_STD, "vb_rom" },
- { VBOY_EEPROM, "vb_eeprom" }
-};
+ if (!m_chip_space && ((m_chip_space.finder_tag() != finder_base::DUMMY_TAG) || (m_chip_space.spacenum() >= 0)))
+ throw emu_fatalerror("%s: Address space %d of device %s not found (CHIP)\n", tag(), m_chip_space.spacenum(), m_chip_space.finder_tag());
-static int vboy_get_pcb_id(const char *slot)
-{
- for (auto & elem : slot_list)
- {
- if (!core_stricmp(elem.slot_option, slot))
- return elem.pcb_id;
- }
+ if (!m_rom_space && ((m_rom_space.finder_tag() != finder_base::DUMMY_TAG) || (m_rom_space.spacenum() >= 0)))
+ throw emu_fatalerror("%s: Address space %d of device %s not found (ROM)\n", tag(), m_rom_space.spacenum(), m_rom_space.finder_tag());
- return 0;
+ m_cart = get_card_device();
}
-#if 0
-static const char *vboy_get_slot(int type)
+
+std::string vboy_cart_slot_device::get_default_card_software(get_default_card_software_hook &hook) const
{
- for (int i = 0; i < ARRAY_LENGTH(slot_list); i++)
+ if (hook.image_file())
{
- if (slot_list[i].pcb_id == type)
- return slot_list[i].slot_option;
+ // 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";
}
-
- return "vb_rom";
-}
-#endif
-
-/*-------------------------------------------------
- call load
- -------------------------------------------------*/
-
-image_init_result vboy_cart_slot_device::call_load()
-{
- if (m_cart)
+ else
{
- uint8_t *ROM;
- uint32_t len = !loaded_through_softlist() ? length() : get_software_region_length("rom");
- bool has_eeprom = loaded_through_softlist() && get_software_region("eeprom");
-
- if (len > 0x200000)
+ 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)
{
- seterror(IMAGE_ERROR_UNSPECIFIED, "Unsupported cartridge size");
- return image_init_result::FAIL;
+ osd_printf_verbose("[%s] Found software part for image name '%s'\n", tag(), image_name);
+ for (rom_entry const &entry : part->romdata())
+ {
+ 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";
}
-
- // always alloc 0x200000 so to be able to directly map the region
- // to the address map (speeding up emulation a bit)
- m_cart->rom_alloc(0x200000, tag());
- if (has_eeprom)
- m_cart->eeprom_alloc(get_software_region_length("eeprom"));
-
- ROM = (uint8_t *)m_cart->get_rom_base();
-
- if (!loaded_through_softlist())
- fread(ROM, len);
- else
- memcpy(ROM, get_software_region("rom"), len);
-
- if (len < 0x080000) { memcpy(ROM + 0x040000, ROM, 0x040000); }
- if (len < 0x100000) { memcpy(ROM + 0x080000, ROM, 0x080000); }
- if (len < 0x200000) { memcpy(ROM + 0x100000, ROM, 0x100000); }
-
- if (!loaded_through_softlist())
- m_type = vboy_get_pcb_id("vb_rom");
else
{
- const char *pcb_name = get_feature("slot");
- if (pcb_name)
- m_type = vboy_get_pcb_id(pcb_name);
+ osd_printf_verbose("[%s] No software part found for image name '%s'\n", tag(), image_name);
}
-
- //printf("Type: %s\n", vboy_get_slot(m_type));
-
- return image_init_result::PASS;
}
- return image_init_result::PASS;
+ // leave the slot empty
+ return std::string();
}
-/*-------------------------------------------------
- call_unload
- -------------------------------------------------*/
-void vboy_cart_slot_device::call_unload()
-{
- if (m_cart && m_cart->get_eeprom_base() && m_cart->get_eeprom_size())
- battery_save(m_cart->get_eeprom_base(), m_cart->get_eeprom_size() * 4);
-}
-
-/*-------------------------------------------------
- get default card software
- -------------------------------------------------*/
+//**************************************************************************
+// device_vboy_cart_interface
+//**************************************************************************
-std::string vboy_cart_slot_device::get_default_card_software(get_default_card_software_hook &hook) const
+void device_vboy_cart_interface::unload()
{
- return software_get_default_slot("vb_rom");
}
-/*-------------------------------------------------
- read
- -------------------------------------------------*/
-READ32_MEMBER(vboy_cart_slot_device::read_cart)
+device_vboy_cart_interface::device_vboy_cart_interface(machine_config const &mconfig, device_t &device) :
+ device_interface(device, "vboycart"),
+ m_slot(dynamic_cast<vboy_cart_slot_device *>(device.owner()))
{
- if (m_cart)
- return m_cart->read_cart(space, offset, mem_mask);
- else
- return 0xffffffff;
}
-/*-------------------------------------------------
- read
- -------------------------------------------------*/
-READ32_MEMBER(vboy_cart_slot_device::read_eeprom)
-{
- if (m_cart)
- return m_cart->read_eeprom(space, offset, mem_mask);
- else
- return 0xffffffff;
-}
-/*-------------------------------------------------
- write
- -------------------------------------------------*/
+#include "rom.h"
-WRITE32_MEMBER(vboy_cart_slot_device::write_eeprom)
+void vboy_carts(device_slot_interface &device)
{
- if (m_cart)
- m_cart->write_eeprom(space, offset, data, mem_mask);
+ device.option_add_internal("flatrom", VBOY_FLAT_ROM);
+ device.option_add_internal("flatrom_sram", VBOY_FLAT_ROM_SRAM);
}
diff --git a/src/devices/bus/vboy/slot.h b/src/devices/bus/vboy/slot.h
index 547f09b8523..850841de194 100644
--- a/src/devices/bus/vboy/slot.h
+++ b/src/devices/bus/vboy/slot.h
@@ -1,122 +1,180 @@
// license:BSD-3-Clause
-// copyright-holders:Fabio Priuli
+// copyright-holders:Vas Crabb
+/***************************************************************************
+ Virtual Boy cartridge slot
+
+ 60-pin two-row connector (2.0 mm pin pitch, 1.6 mm row pitch)
+
+ GND 1 2 GND
+ /WE0 3 4 /ES
+ /WE1 5 6 /CS
+ /RESET 7 8 VCC
+ /INTCRO 9 10 A23
+ A19 11 12 A22
+ A18 13 14 A21
+ A8 15 16 A20
+ A7 17 18 A9
+ A6 19 20 A10
+ A5 21 22 A11
+ A4 23 24 A12
+ A3 25 26 A13
+ A2 27 28 A14
+ A1 29 30 A15
+ /RS 31 32 A16
+ GND 33 34 A17
+ /OE 35 36 VCC
+ D0 37 38 D15
+ D8 39 40 D7
+ D1 41 42 D14
+ D9 43 44 D6
+ D2 45 46 D13
+ D10 47 48 D5
+ D3 49 50 D12
+ D11 51 52 D4
+ VCC 53 54 VCC
+ ARO 55 56 ALO
+ ARI 57 58 ALI
+ GND 59 60 GND
+
+ The cartridge effectively has three 16 bit 8 megaword (16 megabyte) read/
+ write memory spaces. These are conventionally called EXP, CHIP and ROM.
+ Only 16 bit word accesses are possible (no lane select signals, and no
+ address bit A0). No commercial cartridges use the EXP space. The CHIP
+ space is used for cartridge SRAM (if present) and the ROM space is used
+ for program ROM.
+
+ Space Select Read Enable Write Enable Mapping on Virtual Boy
+ EXP /ES /OE /WE1 0x0400'0000-0x04ff'ffff
+ CHIP /CS /OE /WE0 0x0600'0000-0x06ff'ffff
+ ROM /RS /OE /WE1 0x0700'0000-0x07ff'ffff
+
+ Audio is passed through the cartridge, allowing cartridge hardware to
+ modify it. The output of the Virtual Boy's VSU sound chip is DC-coupled
+ to ARO (right) and ALO (left) via 4.7 kΩ resistors. ARI (right) and ALI
+ (left) are AC-coupled to the Virtual Boy's audio amplifier.
+
+ VCC is +5V
+ /INTCRO is an interrupt input from the cartridge to the host
+ /RESET is bidirectional - the system or cartridge can pull it low
+ ***************************************************************************/
#ifndef MAME_BUS_VBOY_SLOT_H
#define MAME_BUS_VBOY_SLOT_H
#pragma once
-#include "softlist_dev.h"
-
-
-/***************************************************************************
- TYPE DEFINITIONS
- ***************************************************************************/
-
-
-/* PCB */
-enum
-{
- VBOY_STD = 0,
- VBOY_EEPROM
-};
-
+#include "imagedev/cartrom.h"
-// ======================> device_vboy_cart_interface
+#include <cassert>
+#include <string>
+#include <utility>
-class device_vboy_cart_interface : public device_slot_card_interface
-{
-public:
- // construction/destruction
- virtual ~device_vboy_cart_interface();
- // reading and writing
- virtual DECLARE_READ32_MEMBER(read_cart) { return 0xffffffff; }
- virtual DECLARE_READ32_MEMBER(read_eeprom) { return 0xffffffff; }
- virtual DECLARE_WRITE32_MEMBER(write_eeprom) { }
+//**************************************************************************
+// FORWARD DECLARATIONS
+//**************************************************************************
- void rom_alloc(uint32_t size, const char *tag);
- void eeprom_alloc(uint32_t size);
- uint32_t* get_rom_base() { return m_rom; }
- uint32_t* get_eeprom_base() { return &m_eeprom[0]; }
- uint32_t get_rom_size() { return m_rom_size; }
- uint32_t get_eeprom_size() { return m_eeprom.size(); }
+class device_vboy_cart_interface;
- void save_eeprom() { device().save_item(NAME(m_eeprom)); }
-protected:
- device_vboy_cart_interface(const machine_config &mconfig, device_t &device);
-
- // internal state
- uint32_t *m_rom;
- uint32_t m_rom_size;
- uint32_t m_rom_mask;
- std::vector<uint32_t> m_eeprom;
-};
+//**************************************************************************
+// CLASS DECLARATIONS
+//**************************************************************************
-// ======================> vboy_cart_slot_device
-
-class vboy_cart_slot_device : public device_t,
- public device_image_interface,
- public device_slot_interface
+class vboy_cart_slot_device :
+ public device_t,
+ public device_cartrom_image_interface,
+ public device_single_card_slot_interface<device_vboy_cart_interface>
{
public:
- // construction/destruction
template <typename T>
- vboy_cart_slot_device(machine_config const &mconfig, char const *tag, device_t *owner, T &&opts, char const *dflt)
- : vboy_cart_slot_device(mconfig, tag, owner, 0)
+ vboy_cart_slot_device(machine_config const &mconfig, char const *tag, device_t *owner, T &&opts, char const *dflt) :
+ vboy_cart_slot_device(mconfig, tag, owner, 0U)
{
option_reset();
opts(*this);
set_default_option(dflt);
set_fixed(false);
}
- vboy_cart_slot_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock = 0);
- virtual ~vboy_cart_slot_device();
+ vboy_cart_slot_device(machine_config const &mconfig, char const *tag, device_t *owner, u32 clock = 0U);
- // image-level overrides
- virtual image_init_result call_load() override;
- virtual void call_unload() override;
- virtual const software_list_loader &get_software_list_loader() const override { return rom_software_list_loader::instance(); }
+ // configuration
+ auto intcro() { return m_intcro.bind(); }
+ template <typename T> void set_exp(T &&tag, int no, offs_t base) { m_exp_space.set_tag(std::forward<T>(tag), no); m_exp_base = base; }
+ template <typename T> void set_chip(T &&tag, int no, offs_t base) { m_chip_space.set_tag(std::forward<T>(tag), no); m_chip_base = base; }
+ 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; }
- int get_type() { return m_type; }
+ // 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 char const *image_interface() const noexcept override { return "vboy_cart"; }
+ virtual char const *file_extensions() const noexcept override { return "vb,bin"; }
- void save_eeprom() { if (m_cart && m_cart->get_eeprom_size()) m_cart->save_eeprom(); }
+ // device_slot_interface implementation
+ virtual std::string get_default_card_software(get_default_card_software_hook &hook) const override;
- virtual iodevice_t image_type() const override { return IO_CARTSLOT; }
- virtual bool is_readable() const override { return 1; }
- virtual bool is_writeable() const override { return 0; }
- virtual bool is_creatable() const override { return 0; }
- virtual bool must_be_loaded() const override { return 1; }
- virtual bool is_reset_on_load() const override { return 1; }
- virtual const char *image_interface() const override { return "vboy_cart"; }
- virtual const char *file_extensions() const override { return "vb,bin"; }
+protected:
+ // device_t implementation
+ virtual void device_validity_check(validity_checker &valid) const override ATTR_COLD;
+ virtual void device_start() override ATTR_COLD;
+
+private:
+ devcb_write_line m_intcro;
+ optional_address_space m_exp_space;
+ optional_address_space m_chip_space;
+ optional_address_space m_rom_space;
+ offs_t m_exp_base;
+ offs_t m_chip_base;
+ offs_t m_rom_base;
+
+ device_vboy_cart_interface *m_cart;
+
+ friend class device_vboy_cart_interface;
+};
- // slot interface overrides
- virtual std::string get_default_card_software(get_default_card_software_hook &hook) const override;
- // reading and writing
- virtual DECLARE_READ32_MEMBER(read_cart);
- virtual DECLARE_READ32_MEMBER(read_eeprom);
- virtual DECLARE_WRITE32_MEMBER(write_eeprom);
+class device_vboy_cart_interface : public device_interface
+{
+public:
+ virtual std::error_condition load() ATTR_COLD = 0;
+ virtual void unload() ATTR_COLD;
protected:
- // device-level overrides
- virtual void device_start() override;
+ device_vboy_cart_interface(machine_config const &mconfig, device_t &device);
+
+ 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); }
+ void battery_save(void const *buffer, int length) { assert(m_slot); m_slot->battery_save(buffer, length); }
- int m_type;
- device_vboy_cart_interface* m_cart;
+ void intcro(int state) { if (m_slot) m_slot->m_intcro(state); }
+
+private:
+ vboy_cart_slot_device *const m_slot;
};
-// device type definition
-DECLARE_DEVICE_TYPE(VBOY_CART_SLOT, vboy_cart_slot_device)
+//**************************************************************************
+// FUNCTION PROTOTYPES
+//**************************************************************************
-/***************************************************************************
- DEVICE CONFIGURATION MACROS
- ***************************************************************************/
+void vboy_carts(device_slot_interface &device);
-#define VBOYSLOT_ROM_REGION_TAG ":cart:rom"
+
+
+//**************************************************************************
+// DEVICE TYPE DECLARATIONS
+//**************************************************************************
+
+DECLARE_DEVICE_TYPE(VBOY_CART_SLOT, vboy_cart_slot_device)
#endif // MAME_BUS_VBOY_SLOT_H
diff --git a/src/devices/bus/vc4000/slot.cpp b/src/devices/bus/vc4000/slot.cpp
index 892213c5aef..ac0d7ce2de7 100644
--- a/src/devices/bus/vc4000/slot.cpp
+++ b/src/devices/bus/vc4000/slot.cpp
@@ -7,7 +7,6 @@
***********************************************************************************************************/
-
#include "emu.h"
#include "slot.h"
@@ -27,7 +26,7 @@ DEFINE_DEVICE_TYPE(H21_CART_SLOT, h21_cart_slot_device, "h21_cart_slot",
//-------------------------------------------------
device_vc4000_cart_interface::device_vc4000_cart_interface(const machine_config &mconfig, device_t &device)
- : device_slot_card_interface(mconfig, device)
+ : device_interface(device, "vc4000cart")
, m_rom(nullptr)
, m_rom_size(0)
{
@@ -46,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;
}
}
@@ -85,8 +84,8 @@ vc4000_cart_slot_device::vc4000_cart_slot_device(
device_t *owner,
uint32_t clock)
: device_t(mconfig, type, tag, owner, clock)
- , device_image_interface(mconfig, *this)
- , device_slot_interface(mconfig, *this)
+ , device_cartrom_image_interface(mconfig, *this)
+ , device_single_card_slot_interface<device_vc4000_cart_interface>(mconfig, *this)
, m_type(VC4000_STD)
, m_cart(nullptr)
{
@@ -107,7 +106,7 @@ vc4000_cart_slot_device::~vc4000_cart_slot_device()
void vc4000_cart_slot_device::device_start()
{
- m_cart = dynamic_cast<device_vc4000_cart_interface *>(get_card_device());
+ m_cart = get_card_device();
}
//-------------------------------------------------
@@ -146,7 +145,7 @@ static int vc4000_get_pcb_id(const char *slot)
{
for (auto & elem : slot_list)
{
- if (!core_stricmp(elem.slot_option, slot))
+ if (!strcmp(elem.slot_option, slot))
return elem.pcb_id;
}
@@ -169,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_UNSPECIFIED, "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);
@@ -211,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());
}
@@ -227,17 +221,17 @@ std::string vc4000_cart_slot_device::get_default_card_software(get_default_card_
{
if (hook.image_file())
{
- const char *slot_string;
- uint32_t size = hook.image_file()->size();
+ std::uint64_t size;
+ hook.image_file()->length(size); // FIXME: check error result
int type = VC4000_STD;
// attempt to identify the non-standard types
if (size > 0x1000) // 6k rom + 1k ram - Chess2 only
type = VC4000_CHESS2;
- else if (size > 0x0800) // some 4k roms have 1k of mirrored ram
+ else if (size > 0x0800) // some 4k roms have 1k of mirrored RAM
type = VC4000_RAM1K;
- slot_string = vc4000_get_slot(type);
+ char const *const slot_string = vc4000_get_slot(type);
//printf("type: %s\n", slot_string);
diff --git a/src/devices/bus/vc4000/slot.h b/src/devices/bus/vc4000/slot.h
index 2ad52b2c7e0..adb0711e497 100644
--- a/src/devices/bus/vc4000/slot.h
+++ b/src/devices/bus/vc4000/slot.h
@@ -3,11 +3,9 @@
#ifndef MAME_BUS_VC4000_SLOT_H
#define MAME_BUS_VC4000_SLOT_H
-#include "softlist_dev.h"
+#include "imagedev/cartrom.h"
-#define VC4000SLOT_ROM_REGION_TAG ":cart:rom"
-
/* PCB */
enum
{
@@ -20,7 +18,7 @@ enum
// ======================> device_vc4000_cart_interface
-class device_vc4000_cart_interface : public device_slot_card_interface
+class device_vc4000_cart_interface : public device_interface
{
public:
// construction/destruction
@@ -30,9 +28,9 @@ public:
virtual uint8_t read_rom(offs_t offset) { return 0xff; }
virtual uint8_t extra_rom(offs_t offset) { return 0xff; }
virtual uint8_t read_ram(offs_t offset) { return 0xff; }
- virtual void write_ram(offs_t offset, uint8_t data) {}
+ 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]; }
@@ -54,8 +52,8 @@ protected:
// ======================> vc4000_cart_slot_device
class vc4000_cart_slot_device : public device_t,
- public device_image_interface,
- public device_slot_interface
+ public device_cartrom_image_interface,
+ public device_single_card_slot_interface<device_vc4000_cart_interface>
{
public:
// construction/destruction
@@ -71,26 +69,20 @@ 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 const software_list_loader &get_software_list_loader() const override { return rom_software_list_loader::instance(); }
- int get_type() { return m_type; }
+ 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"; }
- void save_ram() { if (m_cart && m_cart->get_ram_size()) m_cart->save_ram(); }
+ // device_slot_interface implementation
+ virtual std::string get_default_card_software(get_default_card_software_hook &hook) const override;
- virtual iodevice_t image_type() const override { return IO_CARTSLOT; }
- virtual bool is_readable() const override { return 1; }
- virtual bool is_writeable() const override { return 0; }
- virtual bool is_creatable() const override { return 0; }
- virtual bool must_be_loaded() const override { return 0; }
- virtual bool is_reset_on_load() const override { return 1; }
- virtual const char *image_interface() const override { return "vc4000_cart"; }
- virtual const char *file_extensions() const override { return "bin,rom"; }
+ int get_type() { return m_type; }
- // slot interface overrides
- virtual std::string get_default_card_software(get_default_card_software_hook &hook) const override;
+ 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);
@@ -99,9 +91,6 @@ public:
virtual void write_ram(offs_t offset, uint8_t data);
protected:
- // device-level overrides
- virtual void device_start() override;
-
vc4000_cart_slot_device(
const machine_config &mconfig,
device_type type,
@@ -109,6 +98,9 @@ protected:
device_t *owner,
uint32_t clock);
+ // device_t implementation
+ virtual void device_start() override ATTR_COLD;
+
int m_type;
device_vc4000_cart_interface *m_cart;
};
@@ -129,7 +121,7 @@ public:
h21_cart_slot_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
virtual ~h21_cart_slot_device();
- virtual const char *image_interface() const override { return "h21_cart"; }
+ virtual const char *image_interface() const noexcept override { return "h21_cart"; }
};
// device type definition
diff --git a/src/devices/bus/vcs/compumat.cpp b/src/devices/bus/vcs/compumat.cpp
index 5b5c8ad9495..ff1beac7287 100644
--- a/src/devices/bus/vcs/compumat.cpp
+++ b/src/devices/bus/vcs/compumat.cpp
@@ -17,7 +17,8 @@ DEFINE_DEVICE_TYPE(A26_ROM_COMPUMATE, a26_rom_cm_device, "a2600_cm", "Atari 2600
a26_rom_cm_device::a26_rom_cm_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
- : a26_rom_f6_device(mconfig, A26_ROM_COMPUMATE, tag, owner, clock)
+ : a26_rom_base_device(mconfig, A26_ROM_COMPUMATE, tag, owner, clock)
+ , m_bank(*this, "bank")
{
}
@@ -25,14 +26,9 @@ a26_rom_cm_device::a26_rom_cm_device(const machine_config &mconfig, const char *
// mapper specific start/reset
//-------------------------------------------------
-void a26_rom_cm_device::device_start()
-{
- save_item(NAME(m_base_bank));
-}
-
void a26_rom_cm_device::device_reset()
{
- m_base_bank = 3;
+ m_bank->set_entry(3);
}
@@ -46,8 +42,10 @@ ioport_constructor a26_rom_cm_device::device_input_ports() const
}
-
-READ8_MEMBER(a26_rom_cm_device::read_rom)
+void a26_rom_cm_device::install_memory_handlers(address_space *space)
{
- return m_rom[offset + (m_base_bank * 0x1000)];
+ m_bank->configure_entries(0, 4, get_rom_base(), 0x1000);
+
+ space->install_read_bank(0x1000, 0x1fff, m_bank);
}
+
diff --git a/src/devices/bus/vcs/compumat.h b/src/devices/bus/vcs/compumat.h
index 0eed91e59e5..3cfe799a41d 100644
--- a/src/devices/bus/vcs/compumat.h
+++ b/src/devices/bus/vcs/compumat.h
@@ -13,19 +13,21 @@
// ======================> a26_rom_cm_device
-class a26_rom_cm_device : public a26_rom_f6_device
+class a26_rom_cm_device : public a26_rom_base_device
{
public:
// construction/destruction
a26_rom_cm_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
// device-level overrides
- virtual void device_start() override;
- virtual ioport_constructor device_input_ports() const override;
- virtual void device_reset() override;
+ virtual ioport_constructor device_input_ports() const override ATTR_COLD;
- // reading and writing
- virtual DECLARE_READ8_MEMBER(read_rom) override;
+ virtual void install_memory_handlers(address_space *space) override;
+
+protected:
+ virtual void device_reset() override ATTR_COLD;
+
+ memory_bank_creator m_bank;
};
diff --git a/src/devices/bus/vcs/dpc.cpp b/src/devices/bus/vcs/dpc.cpp
index 525f9e77085..deb5ba74748 100644
--- a/src/devices/bus/vcs/dpc.cpp
+++ b/src/devices/bus/vcs/dpc.cpp
@@ -2,7 +2,6 @@
// copyright-holders:Fabio Priuli
/***************************************************************************
-
Atari 2600 cart with DPC chip (Pitfall II)
***************************************************************************/
@@ -32,19 +31,16 @@ dpc_device::dpc_device(const machine_config& mconfig, const char* tag, device_t*
void dpc_device::device_start()
{
- m_oscillator = timer_alloc(TIMER_OSC);
+ m_oscillator = timer_alloc(FUNC(dpc_device::oscillator_tick), this);
m_oscillator->reset();
- for (int i = 0; i < 8; i++)
- {
- save_item(NAME(m_df[i].top), i);
- save_item(NAME(m_df[i].bottom), i);
- save_item(NAME(m_df[i].low), i);
- save_item(NAME(m_df[i].high), i);
- save_item(NAME(m_df[i].flag), i);
- save_item(NAME(m_df[i].music_mode), i);
- save_item(NAME(m_df[i].osc_clk), i);
- }
+ save_item(STRUCT_MEMBER(m_df, top));
+ save_item(STRUCT_MEMBER(m_df, bottom));
+ save_item(STRUCT_MEMBER(m_df, low));
+ save_item(STRUCT_MEMBER(m_df, high));
+ save_item(STRUCT_MEMBER(m_df, flag));
+ save_item(STRUCT_MEMBER(m_df, music_mode));
+ save_item(STRUCT_MEMBER(m_df, osc_clk));
save_item(NAME(m_movamt));
save_item(NAME(m_latch_62));
@@ -55,7 +51,7 @@ void dpc_device::device_start()
void dpc_device::device_reset()
{
- for (auto & elem : m_df)
+ for (df_t & elem : m_df)
{
elem.osc_clk = 0;
elem.flag = 0;
@@ -91,20 +87,16 @@ void dpc_device::decrement_counter(uint8_t data_fetcher)
//-------------------------------------------------
-// device_timer - handler timer events
+// oscillator_tick
//-------------------------------------------------
-void dpc_device::device_timer(emu_timer &timer, device_timer_id id, int param, void *ptr)
+TIMER_CALLBACK_MEMBER(dpc_device::oscillator_tick)
{
- if (id == TIMER_OSC)
+ for (int data_fetcher = 5; data_fetcher < 8; data_fetcher++)
{
- // callback
- for (int data_fetcher = 5; data_fetcher < 8; data_fetcher++)
+ if (m_df[data_fetcher].osc_clk)
{
- if (m_df[data_fetcher].osc_clk)
- {
- decrement_counter(data_fetcher);
- }
+ decrement_counter(data_fetcher);
}
}
}
@@ -114,13 +106,13 @@ void dpc_device::device_timer(emu_timer &timer, device_timer_id id, int param, v
// Read / Write accesses
//-------------------------------------------------
-READ8_MEMBER(dpc_device::read)
+uint8_t dpc_device::read(offs_t offset)
{
static const uint8_t dpc_amplitude[8] = { 0x00, 0x04, 0x05, 0x09, 0x06, 0x0a, 0x0b, 0x0f };
uint8_t data_fetcher = offset & 0x07;
uint8_t data = 0xff;
- //logerror("%04X: Read from DPC offset $%02X\n", machine().device<cpu_device>("maincpu")->pc(), offset);
+ //logerror("%s: Read from DPC offset $%02X\n", machine().describe_context(), offset);
if (offset < 0x08)
{
switch(offset & 0x06)
@@ -131,6 +123,7 @@ READ8_MEMBER(dpc_device::read)
return m_shift_reg;
case 0x04: // Sound value, MOVAMT value AND'd with Draw Line Carry; with Draw Line Add
m_latch_62 = m_latch_64;
+ [[fallthrough]];
case 0x06: // Sound value, MOVAMT value AND'd with Draw Line Carry; without Draw Line Add
m_latch_64 = m_latch_62 + m_df[4].top;
m_dlc = (m_latch_62 + m_df[4].top > 0xff) ? 1 : 0;
@@ -184,7 +177,7 @@ READ8_MEMBER(dpc_device::read)
return data;
}
-WRITE8_MEMBER(dpc_device::write)
+void dpc_device::write(offs_t offset, uint8_t data)
{
uint8_t data_fetcher = offset & 0x07;
@@ -223,13 +216,13 @@ WRITE8_MEMBER(dpc_device::write)
m_movamt = data;
break;
case 0x28: // Not used
- logerror("%04X: Write to unused DPC register $%02X, data $%02X\n", machine().device<cpu_device>("maincpu")->pc(), offset, data);
+ logerror("%s: Write to unused DPC register $%02X, data $%02X\n", machine().describe_context(), offset, data);
break;
case 0x30: // Random number generator reset
m_shift_reg = 0;
break;
case 0x38: // Not used
- logerror("%04X: Write to unused DPC register $%02X, data $%02X\n", machine().device<cpu_device>("maincpu")->pc(), offset, data);
+ logerror("%s: Write to unused DPC register $%02X, data $%02X\n", machine().describe_context(), offset, data);
break;
}
}
@@ -250,16 +243,6 @@ a26_rom_dpc_device::a26_rom_dpc_device(const machine_config &mconfig, const char
// mapper specific start/reset
//-------------------------------------------------
-void a26_rom_dpc_device::device_start()
-{
- save_item(NAME(m_base_bank));
-}
-
-void a26_rom_dpc_device::device_reset()
-{
- m_base_bank = 0;
-}
-
void a26_rom_dpc_device::setup_addon_ptr(uint8_t *ptr)
{
m_dpc->set_display_data(ptr);
@@ -271,18 +254,9 @@ void a26_rom_dpc_device::device_add_mconfig(machine_config &config)
ATARI_DPC(config, m_dpc, 0);
}
-READ8_MEMBER(a26_rom_dpc_device::read_rom)
-{
- if (offset < 0x40)
- return m_dpc->read(space, offset);
- else
- return a26_rom_f8_device::read_rom(space, offset);
-}
-
-WRITE8_MEMBER(a26_rom_dpc_device::write_bank)
+void a26_rom_dpc_device::install_memory_handlers(address_space *space)
{
- if (offset >= 0x40 && offset < 0x80)
- m_dpc->write(space, offset, data);
- else
- a26_rom_f8_device::write_bank(space, offset, data);
+ a26_rom_f8_device::install_memory_handlers(space);
+ space->install_read_handler(0x1000, 0x103f, read8sm_delegate(m_dpc, FUNC(dpc_device::read)));
+ space->install_write_handler(0x1040, 0x107f, write8sm_delegate(m_dpc, FUNC(dpc_device::write)));
}
diff --git a/src/devices/bus/vcs/dpc.h b/src/devices/bus/vcs/dpc.h
index 6cca68f9632..f76abf945ae 100644
--- a/src/devices/bus/vcs/dpc.h
+++ b/src/devices/bus/vcs/dpc.h
@@ -11,9 +11,7 @@
// TYPE DEFINITIONS
//**************************************************************************
-// TO DO: DPC should be made a separate device!
-
-// m_dpc.oscillator = machine().scheduler().timer_alloc(timer_expired_delegate(FUNC(a2600_state::modeDPC_timer_callback),this));
+// TODO: DPC should be made a separate device
class dpc_device : public device_t
{
@@ -23,11 +21,15 @@ public:
void set_display_data(uint8_t *data) { m_displaydata = data; }
- virtual DECLARE_READ8_MEMBER(read);
- virtual DECLARE_WRITE8_MEMBER(write);
+ virtual uint8_t read(offs_t offset);
+ virtual void write(offs_t offset, uint8_t data);
protected:
- static constexpr device_timer_id TIMER_OSC = 0;
+ // device-level overrides
+ virtual void device_start() override ATTR_COLD;
+ virtual void device_reset() override ATTR_COLD;
+
+ TIMER_CALLBACK_MEMBER(oscillator_tick);
struct df_t {
uint8_t top;
@@ -39,11 +41,6 @@ protected:
uint8_t osc_clk; /* Only used by data fetchers 5,6, and 7 */
};
- // device-level overrides
- virtual void device_start() override;
- virtual void device_reset() override;
- virtual void device_timer(emu_timer &timer, device_timer_id id, int param, void *ptr) override;
-
df_t m_df[8];
uint8_t m_movamt;
uint8_t m_latch_62;
@@ -70,22 +67,17 @@ DECLARE_DEVICE_TYPE(ATARI_DPC, dpc_device)
class a26_rom_dpc_device : public a26_rom_f8_device
{
public:
- // construction/destruction
a26_rom_dpc_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
required_device<dpc_device> m_dpc;
- // reading and writing
- virtual DECLARE_READ8_MEMBER(read_rom) override;
- virtual DECLARE_WRITE8_MEMBER(write_bank) override;
+ virtual void install_memory_handlers(address_space *space) override;
virtual void setup_addon_ptr(uint8_t *ptr) override;
protected:
- // device-level overrides
- virtual void device_start() override;
- virtual void device_add_mconfig(machine_config &config) override;
- virtual void device_reset() override;
+ virtual void device_add_mconfig(machine_config &config) override ATTR_COLD;
+ virtual uint8_t get_start_bank() override { return 0; }
};
diff --git a/src/devices/bus/vcs/harmony_melody.cpp b/src/devices/bus/vcs/harmony_melody.cpp
index a38d0c74fdc..3b3d5385e4a 100644
--- a/src/devices/bus/vcs/harmony_melody.cpp
+++ b/src/devices/bus/vcs/harmony_melody.cpp
@@ -65,7 +65,9 @@ DEFINE_DEVICE_TYPE(A26_ROM_HARMONY, a26_rom_harmony_device, "a2600_harmony", "At
a26_rom_harmony_device::a26_rom_harmony_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
- : a26_rom_f8_device(mconfig, A26_ROM_HARMONY, tag, owner, clock), m_cpu(*this, "arm")
+ : a26_rom_base_device(mconfig, A26_ROM_HARMONY, tag, owner, clock)
+ , m_cpu(*this, "arm")
+ , m_base_bank(0)
{
}
@@ -73,11 +75,6 @@ a26_rom_harmony_device::a26_rom_harmony_device(const machine_config &mconfig, co
// mapper specific start/reset
//-------------------------------------------------
-void a26_rom_harmony_device::device_start()
-{
- save_item(NAME(m_base_bank));
-}
-
void a26_rom_harmony_device::harmony_arm7_map(address_map &map)
{
}
@@ -88,6 +85,12 @@ void a26_rom_harmony_device::device_add_mconfig(machine_config &config)
m_cpu->set_addrmap(AS_PROGRAM, &a26_rom_harmony_device::harmony_arm7_map);
}
+
+void a26_rom_harmony_device::device_start()
+{
+ save_item(NAME(m_base_bank));
+}
+
// actually if the ARM code is doing this and providing every opcode to the main CPU based
// on bus activity then we shouldn't be doing and of this here (if the ROM is actually
// the internal Flash rom of the ARM CPU then the A2600 CPU won't be able to see it directly
@@ -104,7 +107,7 @@ void a26_rom_harmony_device::device_reset()
m_cpu->reset();
}
-READ8_MEMBER(a26_rom_harmony_device::read8_r)
+uint8_t a26_rom_harmony_device::read8_r(offs_t offset)
{
return m_rom[offset + (m_base_bank * 0x1000)];
}
@@ -114,27 +117,32 @@ void a26_rom_harmony_device::check_bankswitch(offs_t offset)
{
switch (offset)
{
- case 0x0FF6: m_base_bank = 0; break;
- case 0x0FF7: m_base_bank = 1; break;
- case 0x0FF8: m_base_bank = 2; break;
- case 0x0FF9: m_base_bank = 3; break;
- case 0x0FFa: m_base_bank = 4; break;
- case 0x0FFb: m_base_bank = 5; break;
+ case 0x0ff6: m_base_bank = 0; break;
+ case 0x0ff7: m_base_bank = 1; break;
+ case 0x0ff8: m_base_bank = 2; break;
+ case 0x0ff9: m_base_bank = 3; break;
+ case 0x0ffa: m_base_bank = 4; break;
+ case 0x0ffb: m_base_bank = 5; break;
default: break;
}
}
-READ8_MEMBER(a26_rom_harmony_device::read_rom)
+void a26_rom_harmony_device::install_memory_handlers(address_space *space)
+{
+ space->install_read_handler(0x1000, 0x1fff, read8sm_delegate(*this, FUNC(a26_rom_harmony_device::read)));
+ space->install_write_handler(0x1000, 0x1fff, write8sm_delegate(*this, FUNC(a26_rom_harmony_device::write)));
+}
+
+uint8_t a26_rom_harmony_device::read(offs_t offset)
{
- uint8_t retvalue = read8_r(space, offset + 0xc00); // banks start at 0xc00
+ uint8_t retvalue = read8_r(offset + 0xc00); // banks start at 0xc00
check_bankswitch(offset);
return retvalue;
}
-WRITE8_MEMBER(a26_rom_harmony_device::write_bank)
+void a26_rom_harmony_device::write(offs_t offset, uint8_t data)
{
check_bankswitch(offset);
-// a26_rom_f8_device::write_bank(space, offset, data);
}
diff --git a/src/devices/bus/vcs/harmony_melody.h b/src/devices/bus/vcs/harmony_melody.h
index d765b40d11b..63ad7a7ab69 100644
--- a/src/devices/bus/vcs/harmony_melody.h
+++ b/src/devices/bus/vcs/harmony_melody.h
@@ -11,31 +11,28 @@
// ======================> a26_rom_harmony_device
-class a26_rom_harmony_device : public a26_rom_f8_device
+class a26_rom_harmony_device : public a26_rom_base_device
{
public:
- // construction/destruction
a26_rom_harmony_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
-private:
- // device-level overrides
- virtual void device_start() override;
- virtual void device_reset() override;
+ virtual void install_memory_handlers(address_space *space) override;
- virtual void device_add_mconfig(machine_config &config) override;
+protected:
+ 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;
- // reading and writing
- virtual DECLARE_READ8_MEMBER(read_rom) override;
- virtual DECLARE_WRITE8_MEMBER(write_bank) override;
private:
void check_bankswitch(offs_t offset);
-
- DECLARE_READ8_MEMBER(read8_r);
-
- void harmony_arm7_map(address_map &map);
+ uint8_t read(offs_t offset);
+ void write(offs_t offset, uint8_t data);
+ uint8_t read8_r(offs_t offset);
+ void harmony_arm7_map(address_map &map) ATTR_COLD;
required_device<lpc210x_device> m_cpu;
+ uint8_t m_base_bank;
};
diff --git a/src/devices/bus/vcs/rom.cpp b/src/devices/bus/vcs/rom.cpp
index 9650bc29661..f40591e1173 100644
--- a/src/devices/bus/vcs/rom.cpp
+++ b/src/devices/bus/vcs/rom.cpp
@@ -21,8 +21,7 @@
// a26_rom_*k_device - constructor
//-------------------------------------------------
-DEFINE_DEVICE_TYPE(A26_ROM_2K, a26_rom_2k_device, "vcs_2k", "Atari VCS 2600 2K ROM Carts")
-DEFINE_DEVICE_TYPE(A26_ROM_4K, a26_rom_4k_device, "vcs_4k", "Atari VCS 2600 4K ROM Carts")
+DEFINE_DEVICE_TYPE(A26_ROM_2K_4K, a26_rom_2k_4k_device, "vcs_2k_4k", "Atari VCS 2600 2K/4K ROM Carts")
DEFINE_DEVICE_TYPE(A26_ROM_F4, a26_rom_f4_device, "vcs_f4", "Atari VCS 2600 ROM Carts w/F4 bankswitch")
DEFINE_DEVICE_TYPE(A26_ROM_F6, a26_rom_f6_device, "vcs_f6", "Atari VCS 2600 ROM Carts w/F6 bankswitch")
DEFINE_DEVICE_TYPE(A26_ROM_F8, a26_rom_f8_device, "vcs_f8", "Atari VCS 2600 ROM Carts w/F8 bankswitch")
@@ -44,301 +43,95 @@ DEFINE_DEVICE_TYPE(A26_ROM_32IN1, a26_rom_32in1_device, "vcs_32in1", "Atari VCS
DEFINE_DEVICE_TYPE(A26_ROM_X07, a26_rom_x07_device, "vcs_x07", "Atari VCS 2600 ROM Carts w/X07 bankswitch")
-a26_rom_2k_device::a26_rom_2k_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_vcs_cart_interface(mconfig, *this)
-{
-}
-
-a26_rom_2k_device::a26_rom_2k_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
- : a26_rom_2k_device(mconfig, A26_ROM_2K, tag, owner, clock)
-{
-}
-
-a26_rom_4k_device::a26_rom_4k_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
- : a26_rom_2k_device(mconfig, A26_ROM_4K, tag, owner, clock)
-{
-}
-
-
-a26_rom_f6_device::a26_rom_f6_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock)
- : a26_rom_2k_device(mconfig, type, tag, owner, clock)
- , m_base_bank(-1) // set to -1 to help the Xin1 multicart...
-{
-}
-
-a26_rom_f6_device::a26_rom_f6_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
- : a26_rom_f6_device(mconfig, A26_ROM_F6, tag, owner, clock)
+bool a26_rom_base_device::is_ram_present(size_t minimum_size)
{
+ return m_ram.size() >= minimum_size;
}
-
-a26_rom_f4_device::a26_rom_f4_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
- : a26_rom_f6_device(mconfig, A26_ROM_F4, tag, owner, clock)
+uint8_t a26_rom_base_device::read_ram(offs_t offset)
{
+ return m_ram[offset];
}
-
-a26_rom_f8_device::a26_rom_f8_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock)
- : a26_rom_f6_device(mconfig, type, tag, owner, clock)
+void a26_rom_base_device::write_ram(offs_t offset, uint8_t data)
{
+ m_ram[offset] = data;
}
-a26_rom_f8_device::a26_rom_f8_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
- : a26_rom_f8_device(mconfig, A26_ROM_F8, tag, owner, clock)
-{
-}
-a26_rom_f8_sw_device::a26_rom_f8_sw_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
- : a26_rom_f8_device(mconfig, A26_ROM_F8_SW, tag, owner, clock)
-{
-}
-
-a26_rom_fa_device::a26_rom_fa_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
- : a26_rom_f6_device(mconfig, A26_ROM_FA, tag, owner, clock)
-{
-}
-
-
-a26_rom_fe_device::a26_rom_fe_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
- : a26_rom_2k_device(mconfig, A26_ROM_FE, tag, owner, clock), m_base_bank(0), m_trigger_on_next_access(0)
-{
-}
-
-
-a26_rom_3e_device::a26_rom_3e_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
- : a26_rom_f6_device(mconfig, A26_ROM_3E, tag, owner, clock), m_num_bank(0), m_ram_bank(0), m_ram_enable(0)
-{
-}
-
-
-a26_rom_3f_device::a26_rom_3f_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
- : a26_rom_f6_device(mconfig, A26_ROM_3F, tag, owner, clock), m_num_bank(0)
-{
-}
-
-
-a26_rom_e0_device::a26_rom_e0_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
- : a26_rom_f6_device(mconfig, A26_ROM_E0, tag, owner, clock)
-{
-}
-
-
-a26_rom_e7_device::a26_rom_e7_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
- : a26_rom_f6_device(mconfig, A26_ROM_E7, tag, owner, clock), m_ram_bank(0)
-{
-}
-
-
-a26_rom_ua_device::a26_rom_ua_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
- : a26_rom_f6_device(mconfig, A26_ROM_UA, tag, owner, clock)
-{
-}
-
-
-a26_rom_cv_device::a26_rom_cv_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
- : a26_rom_2k_device(mconfig, A26_ROM_CV, tag, owner, clock)
-{
-}
-
-
-a26_rom_dc_device::a26_rom_dc_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
- : a26_rom_f6_device(mconfig, A26_ROM_DC, tag, owner, clock)
-{
-}
-
-
-a26_rom_fv_device::a26_rom_fv_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
- : a26_rom_f6_device(mconfig, A26_ROM_FV, tag, owner, clock), m_locked(0)
-{
-}
-
-
-a26_rom_jvp_device::a26_rom_jvp_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
- : a26_rom_f6_device(mconfig, A26_ROM_JVP, tag, owner, clock)
-{
-}
+/*-------------------------------------------------
+ BASE 2K & 4K Carts:
+ no bankswitch
+ GAMES: a large majority
+ -------------------------------------------------*/
-a26_rom_4in1_device::a26_rom_4in1_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
- : a26_rom_f6_device(mconfig, A26_ROM_4IN1, tag, owner, clock)
+a26_rom_2k_4k_device::a26_rom_2k_4k_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
+ : a26_rom_base_device(mconfig, A26_ROM_2K_4K, tag, owner, clock)
{
}
-
-a26_rom_8in1_device::a26_rom_8in1_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
- : a26_rom_f8_device(mconfig, A26_ROM_8IN1, tag, owner, clock), m_reset_bank(0)
+void a26_rom_2k_4k_device::install_memory_handlers(address_space *space)
{
+ if (m_rom_size < 0x1000)
+ space->install_rom(0x1000, 0x17ff, 0x800, get_rom_base());
+ else
+ space->install_rom(0x1000, 0x1fff, get_rom_base());
}
-a26_rom_32in1_device::a26_rom_32in1_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
- : a26_rom_f6_device(mconfig, A26_ROM_32IN1, tag, owner, clock)
-{
-}
-a26_rom_x07_device::a26_rom_x07_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
- : a26_rom_f6_device(mconfig, A26_ROM_X07, tag, owner, clock)
-{
-}
+/*-------------------------------------------------
+ "F6 Bankswitch" Carts:
+ read/write access to 0x1ff6-0x1ff9 determines the
+ 4K ROM bank to be read
+ GAMES: Atari 16K games, like Crossbow, Crystal
+ Castles and the 2-in-1 carts
-void a26_rom_2k_device::device_start()
-{
-}
+ -------------------------------------------------*/
-void a26_rom_2k_device::device_reset()
+a26_rom_f6_device::a26_rom_f6_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock)
+ : a26_rom_base_device(mconfig, type, tag, owner, clock)
+ , m_bank(*this, "bank")
{
}
-void a26_rom_f6_device::device_start()
+a26_rom_f6_device::a26_rom_f6_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
+ : a26_rom_f6_device(mconfig, A26_ROM_F6, tag, owner, clock)
{
- save_item(NAME(m_base_bank));
}
void a26_rom_f6_device::device_reset()
{
- m_base_bank = 0;
-}
-
-void a26_rom_f4_device::device_reset()
-{
- m_base_bank = 7;
-}
-
-void a26_rom_f8_sw_device::device_reset()
-{
- // Snow White proto starts from bank 1!!!
- m_base_bank = 1;
-}
-
-void a26_rom_fe_device::device_start()
-{
- save_item(NAME(m_base_bank));
- save_item(NAME(m_trigger_on_next_access));
-}
-
-void a26_rom_fe_device::device_reset()
-{
- m_base_bank = 0;
- m_trigger_on_next_access = 0;
-}
-
-void a26_rom_3e_device::device_start()
-{
- save_item(NAME(m_base_bank));
- save_item(NAME(m_ram_bank));
- save_item(NAME(m_ram_enable));
-}
-
-void a26_rom_3e_device::device_reset()
-{
- m_num_bank = m_rom_size / 0x800;
- m_base_bank = m_num_bank - 1;
- m_ram_bank = 0;
- m_ram_enable = 0;
-}
-
-void a26_rom_3f_device::device_reset()
-{
- m_num_bank = m_rom_size / 0x800;
- m_base_bank = m_num_bank - 1;
+ m_bank->set_entry(get_start_bank());
}
-void a26_rom_e0_device::device_start()
+void a26_rom_f6_device::install_super_chip_handlers(address_space *space)
{
- save_item(NAME(m_base_banks));
-}
-
-void a26_rom_e0_device::device_reset()
-{
- m_base_banks[0] = 4;
- m_base_banks[1] = 5;
- m_base_banks[2] = 6;
- m_base_banks[3] = 7;
-}
-
-void a26_rom_e7_device::device_start()
-{
- save_item(NAME(m_base_bank));
- save_item(NAME(m_ram_bank));
-}
-
-void a26_rom_e7_device::device_reset()
-{
- m_base_bank = 0;
- m_ram_bank = 0;
-}
-
-void a26_rom_ua_device::device_reset()
-{
- m_base_bank = 0;
-}
-
-void a26_rom_fv_device::device_start()
-{
- save_item(NAME(m_base_bank));
- save_item(NAME(m_locked));
-}
-
-void a26_rom_fv_device::device_reset()
-{
- m_base_bank = 0;
- m_locked = 0;
-}
-
-
-void a26_rom_4in1_device::device_reset()
-{
- m_base_bank++;
- m_base_bank &= 3;
-}
-
-
-void a26_rom_8in1_device::device_start()
-{
- save_item(NAME(m_base_bank));
- save_item(NAME(m_reset_bank));
+ if (is_ram_present(0x80)) {
+ space->install_read_handler(0x1080, 0x10ff, read8sm_delegate(*this, FUNC(a26_rom_f6_device::read_ram)));
+ space->install_write_handler(0x1000, 0x107f, write8sm_delegate(*this, FUNC(a26_rom_f6_device::write_ram)));
+ }
}
-void a26_rom_8in1_device::device_reset()
+void a26_rom_f6_device::install_memory_handlers(address_space *space)
{
- // we use here two different bank counter: the main one for the 8x8K chunks,
- // and the usual one (m_base_bank) for the 4K bank of the current game
- m_reset_bank++;
- m_reset_bank &= 7;
- m_base_bank = 0;
+ m_bank->configure_entries(0, 4, get_rom_base(), 0x1000);
+ space->install_read_bank(0x1000, 0x1fff, m_bank);
+ space->install_write_handler(0x1ff6, 0x1ff9, write8sm_delegate(*this, FUNC(a26_rom_f6_device::switch_bank)));
+ install_super_chip_handlers(space);
+ space->install_read_tap(0x1ff6, 0x1ff9, "bank",
+ [this] (offs_t address, u8 &, u8) { if (!machine().side_effects_disabled()) switch_bank(address - 0x1ff6, 0); });
}
-
-void a26_rom_32in1_device::device_reset()
+void a26_rom_f6_device::switch_bank(offs_t offset, uint8_t data)
{
- m_base_bank++;
- m_base_bank &= 0x1f;
+ m_bank->set_entry(offset);
}
-/*-------------------------------------------------
- mapper specific handlers
- -------------------------------------------------*/
-
-/*-------------------------------------------------
- BASE 2K & 4K Carts:
- no bankswitch
-
- GAMES: a large majority
- -------------------------------------------------*/
-
-READ8_MEMBER(a26_rom_2k_device::read_rom)
-{
- // Super Chip RAM reads are mapped in 0x1080-0x10ff
- if (!m_ram.empty() && offset >= 0x80 && offset < 0x100)
- {
- return m_ram[offset & (m_ram.size() - 1)];
- }
-
- return m_rom[offset & (m_rom_size - 1)];
-}
/*-------------------------------------------------
"F4 Bankswitch" Carts:
@@ -348,119 +141,21 @@ READ8_MEMBER(a26_rom_2k_device::read_rom)
GAMES: Fatal Run
-------------------------------------------------*/
-READ8_MEMBER(a26_rom_f4_device::read_rom)
-{
- // Super Chip RAM reads are mapped in 0x1080-0x10ff
- if (!m_ram.empty() && offset >= 0x80 && offset < 0x100)
- {
- return m_ram[offset & (m_ram.size() - 1)];
- }
-
- // update banks
- if (!machine().side_effects_disabled())
- {
- switch (offset)
- {
- case 0x0ff4:
- case 0x0ff5:
- case 0x0ff6:
- case 0x0ff7:
- case 0x0ff8:
- case 0x0ff9:
- case 0x0ffa:
- case 0x0ffb:
- m_base_bank = offset - 0x0ff4;
- break;
- }
- }
-
- return m_rom[offset + (m_base_bank * 0x1000)];
-}
-
-WRITE8_MEMBER(a26_rom_f4_device::write_bank)
+a26_rom_f4_device::a26_rom_f4_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
+ : a26_rom_f6_device(mconfig, A26_ROM_F4, tag, owner, clock)
{
- // Super Chip RAM writes are mapped in 0x1000-0x107f
- if (!m_ram.empty() && offset < 0x80)
- {
- m_ram[offset & (m_ram.size() - 1)] = data;
- return;
- }
-
- switch (offset)
- {
- case 0x0ff4:
- case 0x0ff5:
- case 0x0ff6:
- case 0x0ff7:
- case 0x0ff8:
- case 0x0ff9:
- case 0x0ffa:
- case 0x0ffb:
- m_base_bank = offset - 0x0ff4;
- break;
- default:
- logerror("Write Bank outside expected range (0x%X).\n", offset + 0x1000);
- break;
- }
}
-/*-------------------------------------------------
- "F6 Bankswitch" Carts:
- read/write access to 0x1ff6-0x1ff9 determines the
- 4K ROM bank to be read
-
- GAMES: Atari 16K games, like Crossbow, Crystal
- Castles and the 2-in-1 carts
-
- -------------------------------------------------*/
-
-READ8_MEMBER(a26_rom_f6_device::read_rom)
+void a26_rom_f4_device::install_memory_handlers(address_space *space)
{
- // Super Chip RAM reads are mapped in 0x1080-0x10ff
- if (!m_ram.empty() && offset >= 0x80 && offset < 0x100)
- {
- return m_ram[offset & (m_ram.size() - 1)];
- }
-
- // update banks
- if (!machine().side_effects_disabled())
- {
- switch (offset)
- {
- case 0x0ff6:
- case 0x0ff7:
- case 0x0ff8:
- case 0x0ff9:
- m_base_bank = offset - 0x0ff6;
- break;
- }
- }
-
- return m_rom[offset + (m_base_bank * 0x1000)];
+ m_bank->configure_entries(0, 8, get_rom_base(), 0x1000);
+ space->install_read_bank(0x1000, 0x1fff, m_bank);
+ space->install_write_handler(0x1ff4, 0x1ffb, write8sm_delegate(*this, FUNC(a26_rom_f4_device::switch_bank)));
+ install_super_chip_handlers(space);
+ space->install_read_tap(0x1ff4, 0x1ffb, "bank",
+ [this] (offs_t address, u8 &, u8) { if (!machine().side_effects_disabled()) switch_bank(address - 0x1ff4, 0); });
}
-WRITE8_MEMBER(a26_rom_f6_device::write_bank)
-{
- // Super Chip RAM writes are mapped in 0x1000-0x107f
- if (!m_ram.empty() && offset < 0x80)
- {
- m_ram[offset & (m_ram.size() - 1)] = data;
- return;
- }
-
- switch (offset)
- {
- case 0x0ff6:
- case 0x0ff7:
- case 0x0ff8:
- case 0x0ff9:
- m_base_bank = offset - 0x0ff6;
- break;
- default:
- logerror("Write Bank outside expected range (0x%X).\n", offset + 0x1000);
- break;
- }
-}
/*-------------------------------------------------
"F8 Bankswitch" Carts:
@@ -472,50 +167,33 @@ WRITE8_MEMBER(a26_rom_f6_device::write_bank)
-------------------------------------------------*/
-READ8_MEMBER(a26_rom_f8_device::read_rom)
+a26_rom_f8_device::a26_rom_f8_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock)
+ : a26_rom_f6_device(mconfig, type, tag, owner, clock)
{
- // Super Chip RAM reads are mapped in 0x1080-0x10ff
- if (!m_ram.empty() && offset >= 0x80 && offset < 0x100)
- {
- return m_ram[offset & (m_ram.size() - 1)];
- }
-
- // update banks
- if (!machine().side_effects_disabled())
- {
- switch (offset)
- {
- case 0x0ff8:
- case 0x0ff9:
- m_base_bank = offset - 0x0ff8;
- break;
- }
- }
+}
- return m_rom[offset + (m_base_bank * 0x1000)];
+a26_rom_f8_device::a26_rom_f8_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
+ : a26_rom_f8_device(mconfig, A26_ROM_F8, tag, owner, clock)
+{
}
-WRITE8_MEMBER(a26_rom_f8_device::write_bank)
+void a26_rom_f8_device::install_memory_handlers(address_space *space)
{
- // Super Chip RAM writes are mapped in 0x1000-0x107f
- if (!m_ram.empty() && offset < 0x80)
- {
- m_ram[offset & (m_ram.size() - 1)] = data;
- return;
- }
+ m_bank->configure_entries(0, 2, get_rom_base(), 0x1000);
+ space->install_read_bank(0x1000, 0x1fff, m_bank);
+ space->install_write_handler(0x1ff8, 0x1ff9, write8sm_delegate(*this, FUNC(a26_rom_f8_device::switch_bank)));
+ install_super_chip_handlers(space);
+ space->install_read_tap(0x1ff8, 0x1ff9, "bank",
+ [this] (offs_t address, u8 &, u8) { if (!machine().side_effects_disabled()) switch_bank(address - 0x1ff8, 0); });
+}
- switch (offset)
- {
- case 0x0ff8:
- case 0x0ff9:
- m_base_bank = offset - 0x0ff8;
- break;
- default:
- logerror("Write Bank outside expected range (0x%X).\n", offset + 0x1000);
- break;
- }
+
+a26_rom_f8_sw_device::a26_rom_f8_sw_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
+ : a26_rom_f8_device(mconfig, A26_ROM_F8_SW, tag, owner, clock)
+{
}
+
/*-------------------------------------------------
"FA Bankswitch" Carts:
read/write access to 0x1ff8-0x1ffa determines the
@@ -528,51 +206,24 @@ WRITE8_MEMBER(a26_rom_f8_device::write_bank)
-------------------------------------------------*/
-READ8_MEMBER(a26_rom_fa_device::read_rom)
+a26_rom_fa_device::a26_rom_fa_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
+ : a26_rom_f6_device(mconfig, A26_ROM_FA, tag, owner, clock)
{
- // CBS RAM+ reads are mapped in 0x1100-0x11ff
- if (!m_ram.empty() && offset >= 0x100 && offset < 0x200)
- {
- return m_ram[offset & (m_ram.size() - 1)];
- }
-
- // update banks
- if (!machine().side_effects_disabled())
- {
- switch (offset)
- {
- case 0x0ff8:
- case 0x0ff9:
- case 0x0ffa:
- m_base_bank = offset - 0x0ff8;
- break;
- }
- }
-
- return m_rom[offset + (m_base_bank * 0x1000)];
}
-WRITE8_MEMBER(a26_rom_fa_device::write_bank)
+void a26_rom_fa_device::install_memory_handlers(address_space *space)
{
- // CBS RAM+ writes are mapped in 0x1000-0x10ff
- if (!m_ram.empty() && offset < 0x100)
- {
- m_ram[offset & (m_ram.size() - 1)] = data;
- }
-
- switch (offset)
- {
- case 0x0ff8:
- case 0x0ff9:
- case 0x0ffa:
- m_base_bank = offset - 0x0ff8;
- break;
- default:
- logerror("Write Bank outside expected range (0x%X).\n", offset + 0x1000);
- break;
- }
+ m_bank->configure_entries(0, 3, get_rom_base(), 0x1000);
+ space->install_read_bank(0x1000, 0x1fff, m_bank);
+ space->install_write_handler(0x1ff8, 0x1ffa, write8sm_delegate(*this, FUNC(a26_rom_fa_device::switch_bank)));
+ space->install_read_tap(0x1ff8, 0x1ffa, "bank",
+ [this] (offs_t address, u8 &, u8) { if (!machine().side_effects_disabled()) switch_bank(address - 0x1ff8, 0); });
+ space->install_read_handler(0x1100, 0x11ff, read8sm_delegate(*this, FUNC(a26_rom_fa_device::read_ram)));
+ space->install_write_handler(0x1000, 0x10ff, write8sm_delegate(*this, FUNC(a26_rom_fa_device::write_ram)));
}
+
+
/*-------------------------------------------------
"FE Bankswitch" Carts:
read/write access to 0x01fe-0x1ff determines the
@@ -581,6 +232,43 @@ WRITE8_MEMBER(a26_rom_fa_device::write_bank)
GAMES: Activision 8K games like Decathlon
-------------------------------------------------*/
+
+a26_rom_fe_device::a26_rom_fe_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
+ : a26_rom_base_device(mconfig, A26_ROM_FE, tag, owner, clock)
+ , m_bank(*this, "bank")
+ , m_trigger_on_next_access(false)
+ , m_ignore_first_read(true)
+{
+}
+
+void a26_rom_fe_device::device_start()
+{
+ save_item(NAME(m_trigger_on_next_access));
+ save_item(NAME(m_ignore_first_read));
+}
+
+void a26_rom_fe_device::device_reset()
+{
+ m_bank->set_entry(0);
+ m_trigger_on_next_access = false;
+ // During cpu startup, before reading the boot vector a read from $01fe occurs
+ m_ignore_first_read = true;
+}
+
+void a26_rom_fe_device::install_memory_handlers(address_space *space)
+{
+ m_bank->configure_entries(0, 8, get_rom_base(), 0x1000);
+
+ space->install_read_bank(0x1000, 0x1fff, m_bank);
+ space->install_readwrite_tap(0x1fe, 0x1fe, "trigger_bank",
+ [this] (offs_t, u8 &, u8) { if (!machine().side_effects_disabled()) trigger_bank(); },
+ [this] (offs_t, u8 &, u8) { if (!machine().side_effects_disabled()) trigger_bank(); });
+ space->install_read_tap(0x1ff, 0x1ff, "switch_bank1",
+ [this] (offs_t, u8 &data, u8) { if (!machine().side_effects_disabled()) switch_bank(data); });
+ space->install_read_tap(0x1000, 0x1fff, "switch_bank2",
+ [this] (offs_t, u8 &data, u8) { if (!machine().side_effects_disabled()) switch_bank(data); });
+}
+
/*
There seems to be a kind of lag between the writing to address 0x1FE and the
@@ -593,73 +281,25 @@ WRITE8_MEMBER(a26_rom_fa_device::write_bank)
*/
-READ8_MEMBER(a26_rom_fe_device::read_rom)
+void a26_rom_fe_device::switch_bank(uint8_t data)
{
- uint8_t data;
-
- // Super Chip RAM reads are mapped in 0x1080-0x10ff
- if (!m_ram.empty() && offset >= 0x80 && offset < 0x100)
- {
- return m_ram[offset & (m_ram.size() - 1)];
- }
-
- data = m_rom[offset + (m_base_bank * 0x1000)];
-
- if (!machine().side_effects_disabled())
+ if (m_trigger_on_next_access)
{
- if (m_trigger_on_next_access)
- {
- m_base_bank = BIT(data, 5) ? 0 : 1;
- m_trigger_on_next_access = 0;
- }
+ m_bank->set_entry(BIT(data, 5) ? 0 : 1);
+ m_trigger_on_next_access = false;
}
-
- return data;
}
-WRITE8_MEMBER(a26_rom_fe_device::write_ram)
+void a26_rom_fe_device::trigger_bank()
{
- // Super Chip RAM writes are mapped in 0x1000-0x107f
- if (!m_ram.empty() && offset < 0x80)
- {
- m_ram[offset & (m_ram.size() - 1)] = data;
- }
+ if (m_ignore_first_read)
+ m_ignore_first_read = false;
+ else
+ // The next byte on the data bus determines which bank to switch to
+ m_trigger_on_next_access = true;
}
-READ8_MEMBER(a26_rom_fe_device::read_bank)
-{
- uint8_t data = space.read_byte(0xfe + offset);
- if (!machine().side_effects_disabled())
- {
- switch (offset & 1)
- {
- case 0:
- // The next byte on the data bus determines which bank to switch to
- m_trigger_on_next_access = 1;
- break;
-
- case 1:
- if (m_trigger_on_next_access)
- {
- m_base_bank = BIT(data, 5) ? 0 : 1;
- m_trigger_on_next_access = 0;
- }
- break;
- }
- }
- return data;
-}
-
-WRITE8_MEMBER(a26_rom_fe_device::write_bank)
-{
- space.write_byte(0xfe, data);
- if (!machine().side_effects_disabled())
- {
- // The next byte on the data bus determines which bank to switch to
- m_trigger_on_next_access = 1;
- }
-}
/*-------------------------------------------------
"3E Bankswitch" Carts:
@@ -671,38 +311,58 @@ WRITE8_MEMBER(a26_rom_fe_device::write_bank)
-------------------------------------------------*/
-READ8_MEMBER(a26_rom_3e_device::read_rom)
+a26_rom_3e_device::a26_rom_3e_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
+ : a26_rom_base_device(mconfig, A26_ROM_3E, tag, owner, clock)
+ , m_rom_bank(*this, "rom_bank")
+ , m_ram_bank(*this, "ram_bank")
+ , m_view(*this, "view")
+ , m_rom_bank_mask(0)
+ , m_ram_bank_mask(0)
{
- if (!m_ram.empty() && m_ram_enable && offset < 0x400)
- return m_ram[offset + (m_ram_bank * 0x400)];
+}
- if (offset >= 0x800)
- return m_rom[(offset & 0x7ff) + (m_num_bank - 1) * 0x800];
- else
- return m_rom[offset + m_base_bank * 0x800];
+void a26_rom_3e_device::device_reset()
+{
+ m_rom_bank->set_entry(m_rom_bank_mask);
+ m_view.select(0);
}
-WRITE8_MEMBER(a26_rom_3e_device::write_bank)
+void a26_rom_3e_device::install_memory_handlers(address_space *space)
{
- if (offset == 0x3f)
- {
- m_base_bank = data & (m_num_bank - 1);
- m_ram_enable = 0;
- }
- else if (offset == 0x3e)
- {
- m_ram_bank = data & 0x1f;
- m_ram_enable = 1;
- }
+ m_rom_bank_mask = (get_rom_size() / 0x800) - 1;
+ m_ram_bank_mask = (get_ram_size() / 0x400) - 1;
+ m_rom_bank->configure_entries(0, m_rom_bank_mask + 1, get_rom_base(), 0x800);
+ m_ram_bank->configure_entries(0, m_ram_bank_mask + 1, get_ram_base(), 0x400);
+
+ space->install_view(0x1000, 0x17ff, m_view);
+ // RAM disabled
+ m_view[0].install_read_bank(0x1000, 0x17ff, m_rom_bank);
+ // RAM enabled
+ m_view[1].install_read_bank(0x1000, 0x17ff, m_rom_bank);
+ m_view[1].install_read_bank(0x1000, 0x13ff, m_ram_bank);
+ m_view[1].install_write_bank(0x1400, 0x17ff, m_ram_bank);
+
+ space->install_rom(0x1800, 0x1fff, get_rom_base() + m_rom_bank_mask * 0x800);
+ space->install_write_tap(0x3e, 0x3e, "ram_bank",
+ [this] (offs_t address, u8 &data, u8) { if (!machine().side_effects_disabled()) select_ram_bank(address, data); });
+ space->install_write_tap(0x3f, 0x3f, "rom_bank",
+ [this] (offs_t address, u8 &data, u8) { if (!machine().side_effects_disabled()) select_rom_bank(address, data); });
+}
+
+void a26_rom_3e_device::select_ram_bank(offs_t address, uint8_t data)
+{
+ m_ram_bank->set_entry(data & m_ram_bank_mask);
+ m_view.select(1);
}
-WRITE8_MEMBER(a26_rom_3e_device::write_ram)
+void a26_rom_3e_device::select_rom_bank(offs_t address, uint8_t data)
{
- if (!m_ram.empty() && m_ram_enable && offset >= 0x400 && offset < 0x800)
- m_ram[(offset & 0x3ff) + (m_ram_bank * 0x400)] = data;
+ m_rom_bank->set_entry(data & m_rom_bank_mask);
+ m_view.select(0);
}
+
/*-------------------------------------------------
"3F Bankswitch" Carts:
write access to 0x00-0x3f determines the 2K ROM bank
@@ -714,22 +374,40 @@ WRITE8_MEMBER(a26_rom_3e_device::write_ram)
-------------------------------------------------*/
-READ8_MEMBER(a26_rom_3f_device::read_rom)
+a26_rom_3f_device::a26_rom_3f_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
+ : a26_rom_base_device(mconfig, A26_ROM_3F, tag, owner, clock)
+ , m_bank(*this, "bank")
+ , m_bank_mask(0)
{
- if (offset >= 0x800)
- return m_rom[(offset & 0x7ff) + (m_num_bank - 1) * 0x800];
- else
- return m_rom[offset + m_base_bank * 0x800];
}
-WRITE8_MEMBER(a26_rom_3f_device::write_bank)
+void a26_rom_3f_device::device_reset()
+{
+ m_bank->set_entry(m_bank_mask);
+}
+
+void a26_rom_3f_device::install_memory_handlers(address_space *space)
+{
+ m_bank_mask = (get_rom_size() / 0x800) - 1;
+ m_bank->configure_entries(0, get_rom_size() / 0x800, get_rom_base(), 0x800);
+
+ space->install_read_bank(0x1000, 0x17ff, m_bank);
+ // last bank
+ space->install_rom(0x1800, 0x1fff, get_rom_base() + m_bank_mask * 0x800);
+ space->install_write_tap(0x00, 0x3f, "bank",
+ [this] (offs_t offset, u8 &data, u8) { if (!machine().side_effects_disabled()) select_bank(offset, data); });
+}
+
+void a26_rom_3f_device::select_bank(offs_t offset, uint8_t data)
{
- m_base_bank = data & (m_num_bank - 1);
+ m_bank->set_entry(data & m_bank_mask);
}
+
+
/*-------------------------------------------------
"E0 Bankswitch" Carts:
- read/write access to 0x1fe0-0x1ff8 determines the
+ read/write access to 0x1fe0-0x1ff7 determines the
1K ROM bank to be read in each 1K chunk (0x1c00-0x1fff
always points to the last 1K of the ROM)
@@ -737,25 +415,48 @@ WRITE8_MEMBER(a26_rom_3f_device::write_bank)
-------------------------------------------------*/
-READ8_MEMBER(a26_rom_e0_device::read_rom)
+a26_rom_e0_device::a26_rom_e0_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
+ : a26_rom_base_device(mconfig, A26_ROM_E0, tag, owner, clock)
+ , m_bank(*this, "bank%u", 0U)
{
- // update banks
- if (!machine().side_effects_disabled())
- {
- if (offset >= 0xfe0 && offset <= 0xff8)
- m_base_banks[(offset >> 3) & 3] = offset & 7;
- }
+}
- return m_rom[(offset & 0x3ff) + (m_base_banks[(offset >> 10) & 3] * 0x400)];
+void a26_rom_e0_device::device_reset()
+{
+ m_bank[0]->set_entry(4);
+ m_bank[1]->set_entry(5);
+ m_bank[2]->set_entry(6);
}
-WRITE8_MEMBER(a26_rom_e0_device::write_bank)
+void a26_rom_e0_device::install_memory_handlers(address_space *space)
{
- if (offset >= 0xfe0 && offset <= 0xff8)
- m_base_banks[(offset >> 3) & 3] = offset & 7;
+ m_bank[0]->configure_entries(0, 8, get_rom_base(), 0x400);
+ m_bank[1]->configure_entries(0, 8, get_rom_base(), 0x400);
+ m_bank[2]->configure_entries(0, 8, get_rom_base(), 0x400);
+
+ space->install_read_bank(0x1000, 0x13ff, m_bank[0]);
+ space->install_read_bank(0x1400, 0x17ff, m_bank[1]);
+ space->install_read_bank(0x1800, 0x1bff, m_bank[2]);
+ space->install_rom(0x1c00, 0x1fff, get_rom_base() + 7 * 0x400);
+ space->install_write_handler(0x1fe0, 0x1fe7, write8sm_delegate(*this, FUNC(a26_rom_e0_device::switch_bank<0>)));
+ space->install_write_handler(0x1fe8, 0x1fef, write8sm_delegate(*this, FUNC(a26_rom_e0_device::switch_bank<1>)));
+ space->install_write_handler(0x1ff0, 0x1ff7, write8sm_delegate(*this, FUNC(a26_rom_e0_device::switch_bank<2>)));
+ space->install_read_tap(0x1fe0, 0x1fe7, "bank",
+ [this] (offs_t address, u8 &, u8) { if (!machine().side_effects_disabled()) switch_bank<0>(address, 0); });
+ space->install_read_tap(0x1fe8, 0x1fef, "bank",
+ [this] (offs_t address, u8 &, u8) { if (!machine().side_effects_disabled()) switch_bank<1>(address, 0); });
+ space->install_read_tap(0x1ff0, 0x1ff7, "bank",
+ [this] (offs_t address, u8 &, u8) { if (!machine().side_effects_disabled()) switch_bank<2>(address, 0); });
+}
+
+template <uint8_t Bank>
+void a26_rom_e0_device::switch_bank(offs_t offset, uint8_t data)
+{
+ m_bank[Bank]->set_entry(offset & 7);
}
+
/*-------------------------------------------------
"E7 Bankswitch" Carts:
this PCB can handle up to 16K of ROM and 2K of RAM,
@@ -776,57 +477,59 @@ WRITE8_MEMBER(a26_rom_e0_device::write_bank)
-------------------------------------------------*/
-READ8_MEMBER(a26_rom_e7_device::read_rom)
+a26_rom_e7_device::a26_rom_e7_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
+ : a26_rom_base_device(mconfig, A26_ROM_E7, tag, owner, clock)
+ , m_rom_bank(*this, "rom_bank")
+ , m_lo_ram_bank(*this, "low_ram")
+ , m_hi_ram_bank(*this, "high_ram")
+ , m_view(*this, "view")
{
- // update banks
- if (!machine().side_effects_disabled())
- {
- if (offset >= 0xfe0 && offset <= 0xfe7)
- m_base_bank = offset - 0xfe0;
- if (offset >= 0xfe8 && offset <= 0xfeb)
- m_ram_bank = offset - 0xfe8;
- }
+}
- if (!m_ram.empty())
- {
- // 1K of RAM
- if (m_base_bank == 0x07 && offset >= 0x400 && offset < 0x800)
- return m_ram[0x400 + (offset & 0x3ff)];
- // the other 1K of RAM
- if (offset >= 0x900 && offset < 0xa00)
- {
- offset -= 0x900;
- return m_ram[offset + (m_ram_bank * 0x100)];
- }
- }
+void a26_rom_e7_device::device_reset()
+{
+ m_rom_bank->set_entry(0);
+ m_hi_ram_bank->set_entry(0);
+}
- if (offset > 0x800)
- return m_rom[(offset & 0x7ff) + 0x3800];
- else
- return m_rom[(offset & 0x7ff) + (m_base_bank * 0x800)];
+void a26_rom_e7_device::install_memory_handlers(address_space *space)
+{
+ m_rom_bank->configure_entries(0, 8, get_rom_base(), 0x800);
+ m_lo_ram_bank->configure_entry(0, get_ram_base() + 0x400);
+ m_hi_ram_bank->configure_entries(0, 4, get_ram_base(), 0x100);
+
+ space->install_view(0x1000, 0x17ff, m_view);
+ // RAM disabled
+ m_view[0].install_read_bank(0x1000, 0x17ff, m_rom_bank);
+ // RAM enabled
+ m_view[1].install_read_bank(0x1000, 0x17ff, m_rom_bank);
+ m_view[1].install_write_bank(0x1000, 0x13ff, m_lo_ram_bank);
+ m_view[1].install_read_bank(0x1400, 0x17ff, m_lo_ram_bank);
+
+ space->install_rom(0x1800, 0x1fff, get_rom_base() + 7 * 0x800);
+ space->install_write_bank(0x1800, 0x18ff, m_hi_ram_bank);
+ space->install_read_bank(0x1900, 0x19ff, m_hi_ram_bank);
+ space->install_write_handler(0x1fe0, 0x1fe7, write8sm_delegate(*this, FUNC(a26_rom_e7_device::switch_rom_bank)));
+ space->install_read_tap(0x1fe0, 0x1fe7, "rom_bank",
+ [this] (offs_t address, u8 &, u8) { if (!machine().side_effects_disabled()) switch_rom_bank(address - 0x1fe0, 0); });
+ space->install_write_handler(0x1fe8, 0x1feb, write8sm_delegate(*this, FUNC(a26_rom_e7_device::switch_ram_bank)));
+ space->install_read_tap(0x1fe8, 0x1feb, "ram_bank",
+ [this] (offs_t address, u8 &, u8) { if (!machine().side_effects_disabled()) switch_ram_bank(address - 0x1fe8, 0); });
}
-WRITE8_MEMBER(a26_rom_e7_device::write_bank)
+void a26_rom_e7_device::switch_rom_bank(offs_t offset, uint8_t data)
{
- if (offset >= 0xfe0 && offset <= 0xfe7)
- m_base_bank = offset - 0xfe0;
- if (offset >= 0xfe8 && offset <= 0xfeb)
- m_ram_bank = offset - 0xfe8;
+ m_view.select(offset == 0x07 ? 1 : 0);
+ m_rom_bank->set_entry(offset);
+}
- if (!m_ram.empty())
- {
- // 1K of RAM
- if (m_base_bank == 0x07 && offset < 0x400)
- m_ram[0x400 + (offset & 0x3ff)] = data;
- // the other 1K of RAM
- if (offset >= 0x800 && offset < 0x900)
- {
- offset -= 0x800;
- m_ram[offset + (m_ram_bank * 0x100)] = data;
- }
- }
+void a26_rom_e7_device::switch_ram_bank(offs_t offset, uint8_t data)
+{
+ m_hi_ram_bank->set_entry(offset);
}
+
+
/*-------------------------------------------------
"UA Bankswitch" Carts:
read/write access to 0x200-0x27f determines the
@@ -838,25 +541,34 @@ WRITE8_MEMBER(a26_rom_e7_device::write_bank)
-------------------------------------------------*/
-READ8_MEMBER(a26_rom_ua_device::read_rom)
+a26_rom_ua_device::a26_rom_ua_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
+ : a26_rom_base_device(mconfig, A26_ROM_UA, tag, owner, clock)
+ , m_bank(*this, "bank")
{
- return m_rom[(offset + (m_base_bank * 0x1000)) & (m_rom_size - 1)];
}
-READ8_MEMBER(a26_rom_ua_device::read_bank)
+void a26_rom_ua_device::device_reset()
{
- if (!machine().side_effects_disabled())
- m_base_bank = offset >> 6;
+ m_bank->set_entry(0);
+}
- return 0;
+void a26_rom_ua_device::install_memory_handlers(address_space *space)
+{
+ m_bank->configure_entries(0, 2, get_rom_base(), 0x1000);
+
+ space->install_read_bank(0x1000, 0x1fff, m_bank);
+ space->install_readwrite_tap(0x200, 0x27f, "bank",
+ [this] (offs_t offset, u8 &data, u8) { if (!machine().side_effects_disabled()) change_bank(offset); },
+ [this] (offs_t offset, u8 &data, u8) { if (!machine().side_effects_disabled()) change_bank(offset); });
}
-WRITE8_MEMBER(a26_rom_ua_device::write_bank)
+void a26_rom_ua_device::change_bank(offs_t offset)
{
- m_base_bank = offset >> 6;
+ m_bank->set_entry((offset >> 6) & 1);
}
+
/*-------------------------------------------------
Commavid Carts:
It allows for both ROM and RAM on the cartridge,
@@ -867,27 +579,20 @@ WRITE8_MEMBER(a26_rom_ua_device::write_bank)
-------------------------------------------------*/
-READ8_MEMBER(a26_rom_cv_device::read_rom)
+a26_rom_cv_device::a26_rom_cv_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
+ : a26_rom_base_device(mconfig, A26_ROM_CV, tag, owner, clock)
{
- if (!m_ram.empty() && offset < 0x400)
- {
- return m_ram[offset & (m_ram.size() - 1)];
- }
-
- // games shall not read from 0x1400-0x17ff (RAM write)
- // but we fall back to ROM just in case...
- return m_rom[offset & 0x7ff];
}
-WRITE8_MEMBER(a26_rom_cv_device::write_bank)
+void a26_rom_cv_device::install_memory_handlers(address_space *space)
{
- if (!m_ram.empty() && offset >= 0x400 && offset < 0x800)
- {
- m_ram[offset & (m_ram.size() - 1)] = data;
- }
+ space->install_rom(0x1000, 0x17ff, 0x800, get_rom_base());
+ space->install_read_handler(0x1000, 0x13ff, read8sm_delegate(*this, FUNC(a26_rom_cv_device::read_ram)));
+ space->install_write_handler(0x1400, 0x17ff, write8sm_delegate(*this, FUNC(a26_rom_cv_device::write_ram)));
}
+
/*-------------------------------------------------
Dynacom Megaboy Carts (aka "F0 Banswitch"):
read/write access to 0x1ff0 determines the 4K ROM
@@ -898,96 +603,115 @@ WRITE8_MEMBER(a26_rom_cv_device::write_bank)
-------------------------------------------------*/
-READ8_MEMBER(a26_rom_dc_device::read_rom)
+a26_rom_dc_device::a26_rom_dc_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
+ : a26_rom_base_device(mconfig, A26_ROM_DC, tag, owner, clock)
+ , m_bank(*this, "bank")
+{
+}
+
+void a26_rom_dc_device::device_reset()
{
- if (!machine().side_effects_disabled())
- {
- if (offset == 0xff0)
- m_base_bank = (m_base_bank + 1) & 0x0f;
- }
+ m_bank->set_entry(0);
+}
+
+void a26_rom_dc_device::install_memory_handlers(address_space *space)
+{
+ m_bank->configure_entries(0, 16, get_rom_base(), 0x1000);
- if (offset == 0xfec)
- return m_base_bank;
+ space->install_read_bank(0x1000, 0x1fff, m_bank);
+ space->install_read_handler(0x1fec, 0x1fec, read8sm_delegate(*this, FUNC(a26_rom_dc_device::read_current_bank)));
+ space->install_write_handler(0x1ff0, 0x1ff0, write8sm_delegate(*this, FUNC(a26_rom_dc_device::switch_bank)));
+ space->install_read_tap(0x1ff0, 0x1ff0, "bank",
+ [this] (offs_t address, u8 &, u8) { if (!machine().side_effects_disabled()) switch_bank(0, 0); });
+}
- return m_rom[offset + (m_base_bank * 0x1000)];
+uint8_t a26_rom_dc_device::read_current_bank(offs_t offset)
+{
+ return m_bank->entry();
}
-WRITE8_MEMBER(a26_rom_dc_device::write_bank)
+void a26_rom_dc_device::switch_bank(offs_t offset, uint8_t data)
{
- if (offset == 0xff0)
- m_base_bank = (m_base_bank + 1) & 0x0f;
+ m_bank->set_entry((m_bank->entry() + 1) & 0x0f);
}
+
/*-------------------------------------------------
"FV Bankswitch" Carts:
- The first access to 0x1fd0 switch the bank, but
- only if pc() & 0x1f00 == 0x1f00!
+ The first access to 0x1fd0 switch the bank.
GAMES: Challenge by HES
-------------------------------------------------*/
-READ8_MEMBER(a26_rom_fv_device::read_rom)
+a26_rom_fv_device::a26_rom_fv_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
+ : a26_rom_base_device(mconfig, A26_ROM_FV, tag, owner, clock)
+ , m_bank(*this, "bank")
{
- if (!machine().side_effects_disabled())
- {
- if (offset == 0xfd0)
- {
- if (!m_locked && (machine().device<cpu_device>("maincpu")->pc() & 0x1f00) == 0x1f00)
- {
- m_locked = 1;
- m_base_bank = m_base_bank ^ 0x01;
- }
- }
- }
+}
- return m_rom[offset + (m_base_bank * 0x1000)];
+void a26_rom_fv_device::device_reset()
+{
+ m_bank->set_entry(0);
}
-WRITE8_MEMBER(a26_rom_fv_device::write_bank)
+void a26_rom_fv_device::install_memory_handlers(address_space *space)
{
- if (offset == 0xfd0)
- {
- if (!m_locked && (machine().device<cpu_device>("maincpu")->pc() & 0x1f00) == 0x1f00)
- {
- m_locked = 1;
- m_base_bank = m_base_bank ^ 0x01;
- }
- }
+ m_bank->configure_entries(0, 2, get_rom_base(), 0x1000);
+
+ space->install_read_bank(0x1000, 0x1fff, m_bank);
+ space->install_write_handler(0x1fd0, 0x1fd0, write8sm_delegate(*this, FUNC(a26_rom_fv_device::switch_bank)));
+ space->install_read_tap(0x1fd0, 0x1fd0, "bank",
+ [this] (offs_t, u8 &, u8) { if (!machine().side_effects_disabled()) switch_bank(0, 0); });
}
+void a26_rom_fv_device::switch_bank(offs_t offset, uint8_t data)
+{
+ m_bank->set_entry(1);
+}
+
+
/*-------------------------------------------------
"JVP Bankswitch" Carts:
read/write access to 0x0fa0-0x0fc0 determines the
- 4K ROM bank to be read (notice that this overlaps
- the RIOT, currently handled in the main driver until
- I can better investigate the behavior)
+ 4K ROM bank to be read.
GAMES: No test case!?!
-------------------------------------------------*/
-READ8_MEMBER(a26_rom_jvp_device::read_rom)
+a26_rom_jvp_device::a26_rom_jvp_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
+ : a26_rom_base_device(mconfig, A26_ROM_JVP, tag, owner, clock)
+ , m_bank(*this, "bank")
{
- return m_rom[offset + (m_base_bank * 0x1000)];
}
-WRITE8_MEMBER(a26_rom_jvp_device::write_bank)
+void a26_rom_jvp_device::device_reset()
{
- switch (offset)
- {
- case 0x00:
- case 0x20:
- m_base_bank ^= 1;
- break;
- default:
- //printf("%04X: write to unknown mapper address %02X\n", m_maincpu->pc(), 0xfa0 + offset);
- break;
- }
+ m_bank->set_entry(0);
+}
+
+void a26_rom_jvp_device::install_memory_handlers(address_space *space)
+{
+ m_bank->configure_entries(0, 2, get_rom_base(), 0x1000);
+
+ space->install_read_bank(0x1000, 0x1fff, m_bank);
+ space->install_readwrite_tap(0xfa0, 0xfa0, "bank_fa0",
+ [this] (offs_t, u8 &, u8) { if (!machine().side_effects_disabled()) change_bank(); },
+ [this] (offs_t, u8 &, u8) { if (!machine().side_effects_disabled()) change_bank(); });
+ space->install_readwrite_tap(0xfc0, 0xfc0, "bank_fc0",
+ [this] (offs_t, u8 &, u8) { if (!machine().side_effects_disabled()) change_bank(); },
+ [this] (offs_t, u8 &, u8) { if (!machine().side_effects_disabled()) change_bank(); });
}
+void a26_rom_jvp_device::change_bank()
+{
+ m_bank->set_entry(m_bank->entry() ^ 1);
+}
+
+
/*-------------------------------------------------
4 in 1 Carts (Reset based):
@@ -997,11 +721,33 @@ WRITE8_MEMBER(a26_rom_jvp_device::write_bank)
-------------------------------------------------*/
-READ8_MEMBER(a26_rom_4in1_device::read_rom)
+a26_rom_4in1_device::a26_rom_4in1_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
+ : a26_rom_base_device(mconfig, A26_ROM_4IN1, tag, owner, clock)
+ , m_bank(*this, "bank")
+ , m_current_game(0)
+{
+}
+
+void a26_rom_4in1_device::device_start()
+{
+ save_item(NAME(m_current_game));
+ m_current_game = 0;
+}
+
+void a26_rom_4in1_device::device_reset()
{
- return m_rom[offset + (m_base_bank * 0x1000)];
+ m_bank->set_entry(m_current_game);
+ m_current_game = (m_current_game + 1) & 3;
}
+void a26_rom_4in1_device::install_memory_handlers(address_space *space)
+{
+ m_bank->configure_entries(0, 4, get_rom_base(), 0x1000);
+
+ space->install_read_bank(0x1000, 0x1fff, m_bank);
+}
+
+
/*-------------------------------------------------
8 in 1 Carts (Reset based):
@@ -1012,23 +758,43 @@ READ8_MEMBER(a26_rom_4in1_device::read_rom)
-------------------------------------------------*/
-READ8_MEMBER(a26_rom_8in1_device::read_rom)
+a26_rom_8in1_device::a26_rom_8in1_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
+ : a26_rom_base_device(mconfig, A26_ROM_8IN1, tag, owner, clock)
+ , m_bank(*this, "bank")
{
- if (!machine().side_effects_disabled())
- {
- switch (offset)
- {
- case 0x0ff8:
- case 0x0ff9:
- m_base_bank = offset - 0x0ff8;
- break;
- }
- }
+}
+
+void a26_rom_8in1_device::device_start()
+{
+ save_item(NAME(m_game_bank));
+
+ // starting from last game so first reset will get us to game #0
+ m_game_bank = 14;
+}
+
+void a26_rom_8in1_device::device_reset()
+{
+ m_game_bank = (m_game_bank + 2) & 15;
+ m_bank->set_entry(m_game_bank);
+}
+
+void a26_rom_8in1_device::install_memory_handlers(address_space *space)
+{
+ m_bank->configure_entries(0, 16, get_rom_base(), 0x1000);
+
+ space->install_read_bank(0x1000, 0x1fff, m_bank);
+ space->install_write_handler(0x1ff8, 0x1ff9, write8sm_delegate(*this, FUNC(a26_rom_8in1_device::switch_bank)));
+ space->install_read_tap(0x1ff8, 0x1ff9, "bank",
+ [this] (offs_t address, u8 &, u8) { if (!machine().side_effects_disabled()) switch_bank(address - 0x1ff8, 0); });
+}
- return m_rom[offset + (m_base_bank * 0x1000) + (m_reset_bank * 0x2000)];
+void a26_rom_8in1_device::switch_bank(offs_t offset, uint8_t data)
+{
+ m_bank->set_entry(m_game_bank + offset);
}
+
/*-------------------------------------------------
32 in 1 Carts (Reset based):
the 2K banks change at each reset
@@ -1037,11 +803,33 @@ READ8_MEMBER(a26_rom_8in1_device::read_rom)
-------------------------------------------------*/
-READ8_MEMBER(a26_rom_32in1_device::read_rom)
+a26_rom_32in1_device::a26_rom_32in1_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
+ : a26_rom_base_device(mconfig, A26_ROM_32IN1, tag, owner, clock)
+ , m_bank(*this, "bank")
+ , m_current_game(0)
+{
+}
+
+void a26_rom_32in1_device::device_start()
{
- return m_rom[(offset & 0x7ff) + (m_base_bank * 0x800)];
+ save_item(NAME(m_current_game));
+ m_current_game = 0;
}
+void a26_rom_32in1_device::device_reset()
+{
+ m_bank->set_entry(m_current_game);
+ m_current_game = (m_current_game + 1) & 0x1f;
+}
+
+void a26_rom_32in1_device::install_memory_handlers(address_space *space)
+{
+ m_bank->configure_entries(0, 32, get_rom_base(), 0x800);
+
+ space->install_read_bank(0x1000, 0x17ff, 0x800, m_bank);
+}
+
+
/*-------------------------------------------------
"X07 Bankswitch" Carts:
@@ -1050,43 +838,48 @@ READ8_MEMBER(a26_rom_32in1_device::read_rom)
http://blog.kevtris.org/blogfiles/Atari%202600%20Mappers.txt
--------------------------------------------------*/
-READ8_MEMBER(a26_rom_x07_device::read_rom)
+a26_rom_x07_device::a26_rom_x07_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
+ : a26_rom_base_device(mconfig, A26_ROM_X07, tag, owner, clock)
+ , m_bank(*this, "bank")
{
- return m_rom[offset + (m_base_bank * 0x1000)];
}
-WRITE8_MEMBER(a26_rom_x07_device::write_bank)
+void a26_rom_x07_device::install_memory_handlers(address_space *space)
{
+ m_bank->configure_entries(0, 16, get_rom_base(), 0x1000);
+
+ space->install_read_bank(0x1000, 0x1fff, m_bank);
/*
A13 A0
----------------
- 0 1xxx nnnn 1101
+ 0 0xxx 0nxx xxxx
*/
-
- if ((offset & 0x180f) == 0x080d)
- {
- m_base_bank = (offset & 0x00f0) >> 4;
- }
+ space->install_readwrite_tap(0x0000, 0x0000, 0x077f, "bank1",
+ [this] (offs_t address, u8 &, u8) { if (!machine().side_effects_disabled()) change_bank1(address); },
+ [this] (offs_t address, u8 &, u8) { if (!machine().side_effects_disabled()) change_bank1(address); });
/*
A13 A0
----------------
- 0 0xxx 0nxx xxxx
+ 0 1xxx nnnn 1101
*/
+ space->install_readwrite_tap(0x080d, 0x080d, 0x07f0, "bank2",
+ [this] (offs_t address, u8 &, u8) { if (!machine().side_effects_disabled()) change_bank2(address); },
+ [this] (offs_t address, u8 &, u8) { if (!machine().side_effects_disabled()) change_bank2(address); });
+}
- if ((offset & 0x1880) == 0x0000)
+void a26_rom_x07_device::change_bank1(offs_t address)
+{
+ // only has an effect if bank is already 14 or 15
+ if (m_bank->entry() >= 14)
{
- // only has an effect if bank is already 14 or 15
- if (m_base_bank == 14 || m_base_bank == 15)
- {
- if (offset & 0x0040)
- {
- m_base_bank = 15;
- }
- else
- {
- m_base_bank = 14;
- }
-
- }
+ if (address & 0x0040)
+ m_bank->set_entry(15);
+ else
+ m_bank->set_entry(14);
}
}
+
+void a26_rom_x07_device::change_bank2(offs_t address)
+{
+ m_bank->set_entry((address >> 4) & 0x0f);
+}
diff --git a/src/devices/bus/vcs/rom.h b/src/devices/bus/vcs/rom.h
index 01e730c03a6..3bd20c68611 100644
--- a/src/devices/bus/vcs/rom.h
+++ b/src/devices/bus/vcs/rom.h
@@ -10,60 +10,50 @@
// ======================> a26_rom_2k_device
-class a26_rom_2k_device : public device_t,
- public device_vcs_cart_interface
+class a26_rom_base_device : public device_t,
+ public device_vcs_cart_interface
{
-public:
- // construction/destruction
- a26_rom_2k_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
-
- // reading and writing
- virtual DECLARE_READ8_MEMBER(read_rom) override;
-
protected:
- a26_rom_2k_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock);
+ a26_rom_base_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_vcs_cart_interface(mconfig, *this)
+ { }
- // device-level overrides
- virtual void device_start() override;
- virtual void device_reset() override;
-};
+ virtual void device_start() override { }
+ bool is_ram_present(size_t minimum_size);
+ uint8_t read_ram(offs_t offset);
+ void write_ram(offs_t offset, uint8_t data);
+};
-// ======================> a26_rom_4k_device
-class a26_rom_4k_device : public a26_rom_2k_device
+class a26_rom_2k_4k_device : public a26_rom_base_device
{
public:
- // construction/destruction
- a26_rom_4k_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
+ a26_rom_2k_4k_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
- // reading and writing
-
- // accesses just use the 2K ones, since it is just direct access to ROM/RAM
- // masked with its size!
+ virtual void install_memory_handlers(address_space *space) override;
};
// ======================> a26_rom_f6_device
-class a26_rom_f6_device : public a26_rom_2k_device
+class a26_rom_f6_device : public a26_rom_base_device
{
public:
- // construction/destruction
a26_rom_f6_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
- // reading and writing
- virtual DECLARE_READ8_MEMBER(read_rom) override;
- virtual DECLARE_WRITE8_MEMBER(write_bank) override;
+ virtual void install_memory_handlers(address_space *space) override;
protected:
a26_rom_f6_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock);
+ void install_super_chip_handlers(address_space *space);
- // device-level overrides
- virtual void device_start() override;
- virtual void device_reset() override;
+ virtual void device_reset() override ATTR_COLD;
+ virtual uint8_t get_start_bank() { return 0; }
+ void switch_bank(offs_t offset, uint8_t data);
- int m_base_bank;
+ memory_bank_creator m_bank;
};
@@ -72,16 +62,12 @@ protected:
class a26_rom_f4_device : public a26_rom_f6_device
{
public:
- // construction/destruction
a26_rom_f4_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
- // reading and writing
- virtual DECLARE_READ8_MEMBER(read_rom) override;
- virtual DECLARE_WRITE8_MEMBER(write_bank) override;
+ virtual void install_memory_handlers(address_space *space) override;
protected:
- // device-level overrides
- virtual void device_reset() override;
+ virtual uint8_t get_start_bank() override { return 7; }
};
@@ -90,12 +76,9 @@ protected:
class a26_rom_f8_device : public a26_rom_f6_device
{
public:
- // construction/destruction
a26_rom_f8_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
- // reading and writing
- virtual DECLARE_READ8_MEMBER(read_rom) override;
- virtual DECLARE_WRITE8_MEMBER(write_bank) override;
+ virtual void install_memory_handlers(address_space *space) override;
protected:
a26_rom_f8_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock);
@@ -107,12 +90,11 @@ protected:
class a26_rom_f8_sw_device : public a26_rom_f8_device
{
public:
- // construction/destruction
a26_rom_f8_sw_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
protected:
- // device-level overrides
- virtual void device_reset() override;
+ // Snow White proto starts from bank 1
+ virtual uint8_t get_start_bank() override { return 1; }
};
@@ -121,279 +103,266 @@ protected:
class a26_rom_fa_device : public a26_rom_f6_device
{
public:
- // construction/destruction
a26_rom_fa_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
- // reading and writing
- virtual DECLARE_READ8_MEMBER(read_rom) override;
- virtual DECLARE_WRITE8_MEMBER(write_bank) override;
+ virtual void install_memory_handlers(address_space *space) override;
};
// ======================> a26_rom_fe_device
-class a26_rom_fe_device : public a26_rom_2k_device
+class a26_rom_fe_device : public a26_rom_base_device
{
public:
- // construction/destruction
a26_rom_fe_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
- // reading and writing
- virtual DECLARE_READ8_MEMBER(read_rom) override;
- virtual DECLARE_READ8_MEMBER(read_bank) override;
- virtual DECLARE_WRITE8_MEMBER(write_ram) override;
- virtual DECLARE_WRITE8_MEMBER(write_bank) override;
+ virtual void install_memory_handlers(address_space *space) override;
protected:
- // device-level overrides
- virtual void device_start() override;
- virtual void device_reset() override;
-
- int m_base_bank;
- int m_trigger_on_next_access;
+ virtual void device_start() override ATTR_COLD;
+ virtual void device_reset() override ATTR_COLD;
+ void trigger_bank();
+ void switch_bank(uint8_t data);
+
+ memory_bank_creator m_bank;
+ bool m_trigger_on_next_access;
+ bool m_ignore_first_read;
};
// ======================> a26_rom_3e_device
-class a26_rom_3e_device : public a26_rom_f6_device
+class a26_rom_3e_device : public a26_rom_base_device
{
public:
- // construction/destruction
a26_rom_3e_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
- // reading and writing
- virtual DECLARE_READ8_MEMBER(read_rom) override;
- virtual DECLARE_WRITE8_MEMBER(write_bank) override;
- virtual DECLARE_WRITE8_MEMBER(write_ram) override;
+ virtual void install_memory_handlers(address_space *space) override;
protected:
- // device-level overrides
- virtual void device_start() override;
- virtual void device_reset() override;
-
- int m_num_bank;
- int m_ram_bank;
- int m_ram_enable;
+ virtual void device_reset() override ATTR_COLD;
+ void select_ram_bank(offs_t offset, uint8_t data);
+ void select_rom_bank(offs_t offset, uint8_t data);
+
+ memory_bank_creator m_rom_bank;
+ memory_bank_creator m_ram_bank;
+ memory_view m_view;
+ uint8_t m_rom_bank_mask;
+ uint8_t m_ram_bank_mask;
};
// ======================> a26_rom_3f_device
-class a26_rom_3f_device : public a26_rom_f6_device
+class a26_rom_3f_device : public a26_rom_base_device
{
public:
- // construction/destruction
a26_rom_3f_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
- // reading and writing
- virtual DECLARE_READ8_MEMBER(read_rom) override;
- virtual DECLARE_WRITE8_MEMBER(write_bank) override;
+ virtual void install_memory_handlers(address_space *space) override;
protected:
- // device-level overrides
- virtual void device_reset() override;
+ virtual void device_reset() override ATTR_COLD;
+ void select_bank(offs_t offset, uint8_t data);
- int m_num_bank;
+ memory_bank_creator m_bank;
+ uint8_t m_bank_mask;
};
// ======================> a26_rom_e0_device
-class a26_rom_e0_device : public a26_rom_f6_device
+class a26_rom_e0_device : public a26_rom_base_device
{
public:
- // construction/destruction
a26_rom_e0_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
- // reading and writing
- virtual DECLARE_READ8_MEMBER(read_rom) override;
- virtual DECLARE_WRITE8_MEMBER(write_bank) override;
+ virtual void install_memory_handlers(address_space *space) override;
protected:
- // device-level overrides
- virtual void device_start() override;
- virtual void device_reset() override;
+ virtual void device_reset() override ATTR_COLD;
+ template <uint8_t Bank> void switch_bank(offs_t offset, uint8_t data);
- int m_base_banks[4];
+ memory_bank_array_creator<3> m_bank;
};
// ======================> a26_rom_e7_device
-class a26_rom_e7_device : public a26_rom_f6_device
+class a26_rom_e7_device : public a26_rom_base_device
{
public:
- // construction/destruction
a26_rom_e7_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
- // reading and writing
- virtual DECLARE_READ8_MEMBER(read_rom) override;
- virtual DECLARE_WRITE8_MEMBER(write_bank) override;
+ virtual void install_memory_handlers(address_space *space) override;
protected:
- // device-level overrides
- virtual void device_start() override;
- virtual void device_reset() override;
-
- int m_ram_bank;
+ virtual void device_reset() override ATTR_COLD;
+ void switch_rom_bank(offs_t offset, uint8_t data);
+ void switch_ram_bank(offs_t offset, uint8_t data);
+
+ memory_bank_creator m_rom_bank;
+ memory_bank_creator m_lo_ram_bank;
+ memory_bank_creator m_hi_ram_bank;
+ memory_view m_view;
};
// ======================> a26_rom_ua_device
-class a26_rom_ua_device : public a26_rom_f6_device
+class a26_rom_ua_device : public a26_rom_base_device
{
public:
- // construction/destruction
a26_rom_ua_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
- // reading and writing
- virtual DECLARE_READ8_MEMBER(read_rom) override;
- virtual DECLARE_READ8_MEMBER(read_bank) override;
- virtual DECLARE_WRITE8_MEMBER(write_bank) override;
+ virtual void install_memory_handlers(address_space *space) override;
protected:
- // device-level overrides
- virtual void device_reset() override;
+ virtual void device_reset() override ATTR_COLD;
+ void change_bank(offs_t offset);
+
+ memory_bank_creator m_bank;
};
// ======================> a26_rom_cv_device
-class a26_rom_cv_device : public a26_rom_2k_device
+class a26_rom_cv_device : public a26_rom_base_device
{
public:
- // construction/destruction
a26_rom_cv_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
- // reading and writing
- virtual DECLARE_READ8_MEMBER(read_rom) override;
- virtual DECLARE_WRITE8_MEMBER(write_bank) override;
+ virtual void install_memory_handlers(address_space *space) override;
};
// ======================> a26_rom_dc_device
-class a26_rom_dc_device : public a26_rom_f6_device
+class a26_rom_dc_device : public a26_rom_base_device
{
public:
- // construction/destruction
a26_rom_dc_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
- // reading and writing
- virtual DECLARE_READ8_MEMBER(read_rom) override;
- virtual DECLARE_WRITE8_MEMBER(write_bank) override;
+ virtual void install_memory_handlers(address_space *space) override;
+
+protected:
+ virtual void device_reset() override ATTR_COLD;
+ uint8_t read_current_bank(offs_t offset);
+ void switch_bank(offs_t offset, uint8_t data);
+
+ memory_bank_creator m_bank;
};
// ======================> a26_rom_fv_device
-class a26_rom_fv_device : public a26_rom_f6_device
+class a26_rom_fv_device : public a26_rom_base_device
{
public:
- // construction/destruction
a26_rom_fv_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
- // reading and writing
- virtual DECLARE_READ8_MEMBER(read_rom) override;
- virtual DECLARE_WRITE8_MEMBER(write_bank) override;
+ virtual void install_memory_handlers(address_space *space) override;
protected:
- // device-level overrides
- virtual void device_start() override;
- virtual void device_reset() override;
+ virtual void device_reset() override ATTR_COLD;
+ void switch_bank(offs_t offset, uint8_t data);
- int m_locked;
+ memory_bank_creator m_bank;
};
// ======================> a26_rom_jvp_device
-class a26_rom_jvp_device : public a26_rom_f6_device
+class a26_rom_jvp_device : public a26_rom_base_device
{
public:
- // construction/destruction
a26_rom_jvp_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
- // reading and writing
- virtual DECLARE_READ8_MEMBER(read_rom) override;
- virtual DECLARE_WRITE8_MEMBER(write_bank) override;
+ virtual void install_memory_handlers(address_space *space) override;
+
+protected:
+ virtual void device_reset() override ATTR_COLD;
+ void change_bank();
+
+ memory_bank_creator m_bank;
};
// ======================> a26_rom_4in1_device
-class a26_rom_4in1_device : public a26_rom_f6_device
+class a26_rom_4in1_device : public a26_rom_base_device
{
public:
- // construction/destruction
a26_rom_4in1_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
- // reading and writing
- virtual DECLARE_READ8_MEMBER(read_rom) override;
+ virtual void install_memory_handlers(address_space *space) override;
protected:
- // device-level overrides
- virtual void device_reset() override;
+ virtual void device_start() override ATTR_COLD;
+ virtual void device_reset() override ATTR_COLD;
+
+ memory_bank_creator m_bank;
+ uint8_t m_current_game;
};
// ======================> a26_rom_8in1_device
-class a26_rom_8in1_device : public a26_rom_f8_device
+class a26_rom_8in1_device : public a26_rom_base_device
{
public:
- // construction/destruction
a26_rom_8in1_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
- // reading and writing
- virtual DECLARE_READ8_MEMBER(read_rom) override;
+ virtual void install_memory_handlers(address_space *space) override;
protected:
- // device-level overrides
- virtual void device_start() override;
- virtual void device_reset() override;
+ virtual void device_start() override ATTR_COLD;
+ virtual void device_reset() override ATTR_COLD;
+ void switch_bank(offs_t offset, uint8_t data);
- int m_reset_bank;
+ memory_bank_creator m_bank;
+ uint8_t m_game_bank;
};
// ======================> a26_rom_32in1_device
-class a26_rom_32in1_device : public a26_rom_f6_device
+class a26_rom_32in1_device : public a26_rom_base_device
{
public:
- // construction/destruction
a26_rom_32in1_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
- // reading and writing
- virtual DECLARE_READ8_MEMBER(read_rom) override;
+ virtual void install_memory_handlers(address_space *space) override;
protected:
- // device-level overrides
- virtual void device_reset() override;
+ virtual void device_start() override ATTR_COLD;
+ virtual void device_reset() override ATTR_COLD;
+
+ memory_bank_creator m_bank;
+ uint8_t m_current_game;
};
// ======================> a26_rom_x07_device
-class a26_rom_x07_device : public a26_rom_f6_device
+class a26_rom_x07_device : public a26_rom_base_device
{
public:
- // construction/destruction
a26_rom_x07_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
- // reading and writing
- virtual DECLARE_READ8_MEMBER(read_rom) override;
- virtual DECLARE_WRITE8_MEMBER(write_bank) override;
+ virtual void install_memory_handlers(address_space *space) override;
+
+private:
+ void change_bank1(offs_t offset);
+ void change_bank2(offs_t offset);
+
+ memory_bank_creator m_bank;
};
// device type definition
-DECLARE_DEVICE_TYPE(A26_ROM_2K, a26_rom_2k_device)
-DECLARE_DEVICE_TYPE(A26_ROM_4K, a26_rom_4k_device)
+DECLARE_DEVICE_TYPE(A26_ROM_2K_4K, a26_rom_2k_4k_device)
DECLARE_DEVICE_TYPE(A26_ROM_F4, a26_rom_f4_device)
DECLARE_DEVICE_TYPE(A26_ROM_F6, a26_rom_f6_device)
DECLARE_DEVICE_TYPE(A26_ROM_F8, a26_rom_f8_device)
diff --git a/src/devices/bus/vcs/scharger.cpp b/src/devices/bus/vcs/scharger.cpp
index 7c42fc9003c..1aa1b143328 100644
--- a/src/devices/bus/vcs/scharger.cpp
+++ b/src/devices/bus/vcs/scharger.cpp
@@ -37,20 +37,22 @@
#include "sound/wave.h"
#include "formats/a26_cas.h"
+//#define VERBOSE (LOG_GENERAL)
+#include "logmacro.h"
+
+
DEFINE_DEVICE_TYPE(A26_ROM_SUPERCHARGER, a26_rom_ss_device, "a2600_ss", "Atari 2600 ROM Cart Supercharger")
-a26_rom_ss_device::a26_rom_ss_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
- : a26_rom_f6_device(mconfig, A26_ROM_SUPERCHARGER, tag, owner, clock),
+a26_rom_ss_device::a26_rom_ss_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) :
+ a26_rom_base_device(mconfig, A26_ROM_SUPERCHARGER, tag, owner, clock),
m_cassette(*this, "cassette"),
- m_maincpu(nullptr),
- m_reg(0),
+ m_data(0),
m_write_delay(0),
m_ram_write_enabled(0),
m_rom_enabled(0),
- m_byte_started(0),
- m_last_address(0),
- m_diff_adjust(0)
+ m_last_address_bus(0),
+ m_address_bus_changes(0)
{
}
@@ -60,30 +62,26 @@ a26_rom_ss_device::a26_rom_ss_device(const machine_config &mconfig, const char *
void a26_rom_ss_device::device_start()
{
- m_maincpu = machine().device<cpu_device>("maincpu");
-
save_item(NAME(m_base_banks));
- save_item(NAME(m_reg));
+ save_item(NAME(m_data));
save_item(NAME(m_write_delay));
save_item(NAME(m_ram_write_enabled));
save_item(NAME(m_rom_enabled));
- save_item(NAME(m_byte_started));
- save_item(NAME(m_last_address));
- save_item(NAME(m_diff_adjust));
+ save_item(NAME(m_last_address_bus));
+ save_item(NAME(m_address_bus_changes));
}
void a26_rom_ss_device::device_reset()
{
- // banks = 0, 1, 2 are 2K chunk of RAM (of the available 6K), banks = 3 is ROM!
+ // banks = 0, 1, 2 are 2K chunk of RAM (of the available 6K), banks = 3 is ROM
m_base_banks[0] = 2;
m_base_banks[1] = 3;
- m_ram_write_enabled = 0;
- m_byte_started = 0;
- m_reg = 0;
+ m_ram_write_enabled = false;
+ m_data = 0;
m_write_delay = 0;
- m_rom_enabled = 1;
- m_last_address = 0;
- m_diff_adjust = 0;
+ m_rom_enabled = true;
+ m_last_address_bus = 0;
+ m_address_bus_changes = RAM_WRITE_TIME + 1;
}
@@ -97,36 +95,30 @@ void a26_rom_ss_device::device_add_mconfig(machine_config &config)
// WAVE(config, "wave", m_cassette).add_route(ALL_OUTPUTS, "mono", 0.25);
}
-inline uint8_t a26_rom_ss_device::read_byte(uint32_t offset)
+void a26_rom_ss_device::install_memory_handlers(address_space *space)
{
- if (offset < 0x800)
- return m_ram[(offset & 0x7ff) + (m_base_banks[0] * 0x800)];
- else if (m_base_banks[1] != 3)
- return m_ram[(offset & 0x7ff) + (m_base_banks[1] * 0x800)];
- else if (m_rom_enabled)
- return m_rom[offset & 0x7ff];
- else
- return 0xff;
+ space->install_read_handler(0x1000, 0x17ff, read8sm_delegate(*this, FUNC(a26_rom_ss_device::read_lo)));
+ space->install_read_handler(0x1800, 0x1fff, read8sm_delegate(*this, FUNC(a26_rom_ss_device::read_hi)));
+ space->install_read_handler(0x1ff9, 0x1ff9, read8sm_delegate(*this, FUNC(a26_rom_ss_device::read_cass)));
+ space->install_readwrite_tap(0x0000, 0x1fff, "watch",
+ [this] (offs_t address, u8 &, u8) { if (!machine().side_effects_disabled()) tap(address); },
+ [this] (offs_t address, u8 &, u8) { if (!machine().side_effects_disabled()) tap(address); });
}
-READ8_MEMBER(a26_rom_ss_device::read_rom)
+void a26_rom_ss_device::tap(offs_t address)
{
- if (machine().side_effects_disabled())
- return read_byte(offset);
-
- // Bankswitch
- if (offset == 0xff8)
+ if (address == 0x1ff8)
{
- //logerror("%04X: Access to control register data = %02X\n", m_maincpu->pc(), m_modeSS_byte);
- m_write_delay = m_reg >> 5;
- m_ram_write_enabled = BIT(m_reg, 1);
- m_rom_enabled = !BIT(m_reg, 0);
+ LOG("write control register %02X\n", m_data);
+ m_write_delay = m_data >> 5;
+ m_ram_write_enabled = BIT(m_data, 1);
+ m_rom_enabled = !BIT(m_data, 0);
- // compensate time spent in this access to avoid spurious RAM write
- m_byte_started -= 5;
+ // prevent spurious RAM write
+ m_address_bus_changes = RAM_WRITE_TIME + 1;
// handle bankswitch
- switch (m_reg & 0x1c)
+ switch (m_data & 0x1c)
{
case 0x00:
m_base_banks[0] = 2;
@@ -161,57 +153,69 @@ READ8_MEMBER(a26_rom_ss_device::read_rom)
m_base_banks[1] = 2;
break;
}
-
- return read_byte(offset);
}
- // Cassette port read
- else if (offset == 0xff9)
- {
- //logerror("%04X: Cassette port read, tap_val = %f\n", m_maincpu->pc(), tap_val);
- double tap_val = m_cassette->input();
-
- // compensate time spent in this access to avoid spurious RAM write
- m_byte_started -= 5;
+ if (m_address_bus_changes <= RAM_WRITE_TIME && m_last_address_bus != address)
+ m_address_bus_changes++;
+ m_last_address_bus = address;
+}
- if (tap_val < 0)
- return 0x00;
- else
- return 0x01;
- }
- // Possible RAM write
- else
+uint8_t a26_rom_ss_device::read_lo(offs_t offset)
+{
+ if (!machine().side_effects_disabled())
{
if (m_ram_write_enabled)
{
- /* Check for dummy read from same address */
- if (m_last_address == offset)
- m_diff_adjust++;
-
- int diff = m_maincpu->total_cycles() - m_byte_started;
- //logerror("%04X: offset = %04X, %d\n", m_maincpu->pc(), offset, diff);
-
- if (diff - m_diff_adjust == 5)
+ if (m_address_bus_changes == RAM_WRITE_TIME)
{
- //logerror("%04X: RAM write offset = %04X, data = %02X\n", m_maincpu->pc(), offset, m_modeSS_byte );
- if (offset < 0x800)
- m_ram[(offset & 0x7ff) + (m_base_banks[0] * 0x800)] = m_reg;
- else if (m_base_banks[1] != 3)
- m_ram[(offset & 0x7ff) + (m_base_banks[1] * 0x800)] = m_reg;
+ LOG("%s: RAM write offset %04X, data %02X\n", machine().describe_context(), offset + (m_base_banks[0] * 0x800), m_data);
+ m_ram[offset + (m_base_banks[0] * 0x800)] = m_data;
}
else if (offset < 0x0100)
{
- m_reg = offset;
- m_byte_started = m_maincpu->total_cycles();
- m_diff_adjust = 0;
+ m_data = offset;
+ m_address_bus_changes = 0;
}
}
else if (offset < 0x0100)
{
- m_reg = offset;
- m_byte_started = m_maincpu->total_cycles();
- m_diff_adjust = 0;
+ m_data = offset;
+ m_address_bus_changes = 0;
+ }
+ }
+ return m_ram[offset + (m_base_banks[0] * 0x800)];
+}
+
+uint8_t a26_rom_ss_device::read_hi(offs_t offset)
+{
+ if (!machine().side_effects_disabled())
+ {
+ if (m_ram_write_enabled)
+ {
+ if (m_address_bus_changes == RAM_WRITE_TIME)
+ {
+ if (m_base_banks[1] != 3)
+ {
+ LOG("%s: RAM write offset %04X, data %02X\n", machine().describe_context(), offset + (m_base_banks[1] * 0x800), m_data);
+ m_ram[offset + (m_base_banks[1] * 0x800)] = m_data;
+ }
+ }
}
- m_last_address = offset;
- return read_byte(offset);
}
+ if (m_base_banks[1] != 3)
+ return m_ram[offset + (m_base_banks[1] * 0x800)];
+ else if (m_rom_enabled)
+ return m_rom[offset];
+ else
+ return 0xff;
+}
+
+uint8_t a26_rom_ss_device::read_cass(offs_t offset)
+{
+ // prevent spurious RAM write
+ m_address_bus_changes = RAM_WRITE_TIME + 1;
+
+ if (m_cassette->input() < 0)
+ return 0x00;
+ else
+ return 0x01;
}
diff --git a/src/devices/bus/vcs/scharger.h b/src/devices/bus/vcs/scharger.h
index 2fa42e2ba4c..8f4801f4cca 100644
--- a/src/devices/bus/vcs/scharger.h
+++ b/src/devices/bus/vcs/scharger.h
@@ -14,33 +14,36 @@
// ======================> a26_rom_ss_device
-class a26_rom_ss_device : public a26_rom_f6_device
+class a26_rom_ss_device : public a26_rom_base_device
{
public:
- // construction/destruction
a26_rom_ss_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
- // reading and writing
- virtual DECLARE_READ8_MEMBER(read_rom) override;
+ virtual void install_memory_handlers(address_space *space) override;
+ uint8_t read_lo(offs_t offset);
+ uint8_t read_hi(offs_t offset);
+ uint8_t read_cass(offs_t offset);
private:
- // device-level overrides
- virtual void device_start() override;
- virtual void device_reset() override;
+ static constexpr uint32_t RAM_WRITE_TIME = 5;
- virtual void device_add_mconfig(machine_config &config) override;
+ 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;
+ void install_tap_handler();
required_device<cassette_image_device> m_cassette;
- cpu_device *m_maincpu;
- inline uint8_t read_byte(uint32_t offset);
+ void tap(offs_t offset);
int m_base_banks[2];
- uint8_t m_reg;
- uint8_t m_write_delay, m_ram_write_enabled, m_rom_enabled;
- uint32_t m_byte_started;
- uint16_t m_last_address;
- uint32_t m_diff_adjust;
+ uint8_t m_data;
+ uint8_t m_write_delay;
+ bool m_ram_write_enabled;
+ bool m_rom_enabled;
+ uint16_t m_last_address_bus;
+ uint32_t m_address_bus_changes;
};
diff --git a/src/devices/bus/vcs/vcs_slot.cpp b/src/devices/bus/vcs/vcs_slot.cpp
index ec1c653be2a..344071724e9 100644
--- a/src/devices/bus/vcs/vcs_slot.cpp
+++ b/src/devices/bus/vcs/vcs_slot.cpp
@@ -14,7 +14,6 @@
***********************************************************************************************************/
-
#include "emu.h"
#include "vcs_slot.h"
@@ -24,15 +23,43 @@
DEFINE_DEVICE_TYPE(VCS_CART_SLOT, vcs_cart_slot_device, "vcs_cart_slot", "Atari VCS 2600 Cartridge Slot")
+/* PCB */
+enum
+{
+ A26_2K_4K = 0,
+ A26_F4,
+ A26_F6,
+ A26_F8,
+ A26_F8SW,
+ A26_FA,
+ A26_FE,
+ A26_3E, // to test
+ A26_3F,
+ A26_E0,
+ A26_E7,
+ A26_UA,
+ A26_DC,
+ A26_CV,
+ A26_FV,
+ A26_JVP, // to test
+ A26_32IN1,
+ A26_8IN1,
+ A26_4IN1,
+ A26_DPC,
+ A26_SS,
+ A26_CM,
+ A26_X07,
+ A26_HARMONY,
+};
//-------------------------------------------------
// device_vcs_cart_interface - constructor
//-------------------------------------------------
-device_vcs_cart_interface::device_vcs_cart_interface(const machine_config &mconfig, device_t &device)
- : device_slot_card_interface(mconfig, device),
- m_rom(nullptr),
- m_rom_size(0)
+device_vcs_cart_interface::device_vcs_cart_interface(const machine_config &mconfig, device_t &device) :
+ device_interface(device, "vcscart"),
+ m_rom(nullptr),
+ m_rom_size(0)
{
}
@@ -53,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(A26SLOT_ROM_REGION_TAG).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;
}
}
@@ -79,8 +106,11 @@ void device_vcs_cart_interface::ram_alloc(uint32_t size)
//-------------------------------------------------
vcs_cart_slot_device::vcs_cart_slot_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) :
device_t(mconfig, VCS_CART_SLOT, tag, owner, clock),
- device_image_interface(mconfig, *this),
- device_slot_interface(mconfig, *this), m_cart(nullptr), m_type(0)
+ device_cartrom_image_interface(mconfig, *this),
+ device_single_card_slot_interface<device_vcs_cart_interface>(mconfig, *this),
+ m_cart(nullptr),
+ m_type(0),
+ m_address_space(*this, finder_base::DUMMY_TAG, -1, 8)
{
}
@@ -99,7 +129,7 @@ vcs_cart_slot_device::~vcs_cart_slot_device()
void vcs_cart_slot_device::device_start()
{
- m_cart = dynamic_cast<device_vcs_cart_interface *>(get_card_device());
+ m_cart = get_card_device();
}
@@ -121,8 +151,7 @@ struct vcs_slot
// Here, we take the feature attribute from .xml (i.e. the PCB name) and we assign a unique ID to it
static const vcs_slot slot_list[] =
{
- { A26_2K, "a26_2k" },
- { A26_4K, "a26_4k" },
+ { A26_2K_4K, "a26_2k_4k" },
{ A26_F4, "a26_f4" },
{ A26_F6, "a26_f6" },
{ A26_F8, "a26_f8" },
@@ -152,7 +181,7 @@ static int vcs_get_pcb_id(const char *slot)
{
for (auto & elem : slot_list)
{
- if (!core_stricmp(elem.slot_option, slot))
+ if (!strcmp(elem.slot_option, slot))
return elem.pcb_id;
}
@@ -167,22 +196,14 @@ static const char *vcs_get_slot(int type)
return elem.slot_option;
}
- return "a26_4k";
+ 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)
{
- uint8_t *ROM;
- uint32_t len;
-
- if (loaded_through_softlist())
- len = get_software_region_length("rom");
- else
- len = length();
-
- //printf("Size: 0x%X\n", len);
+ const uint32_t len = loaded_through_softlist() ? get_software_region_length("rom") : length();
// check that filesize is among the supported ones
switch (len)
@@ -200,20 +221,18 @@ image_init_result vcs_cart_slot_device::call_load()
break;
default:
- seterror(IMAGE_ERROR_UNSUPPORTED, "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());
- ROM = m_cart->get_rom_base();
+ uint8_t *const ROM = m_cart->get_rom_base();
if (loaded_through_softlist())
{
- const char *pcb_name;
- bool has_ram = get_software_region("ram") ? true : false;
memcpy(ROM, get_software_region("rom"), len);
+ const char *pcb_name = get_feature("slot");
- if ((pcb_name = get_feature("slot")) != nullptr)
+ if (pcb_name != nullptr)
m_type = vcs_get_pcb_id(pcb_name);
else
{
@@ -221,10 +240,8 @@ image_init_result vcs_cart_slot_device::call_load()
switch (len)
{
case 0x800:
- m_type = A26_2K;
- break;
case 0x1000:
- m_type = A26_4K;
+ m_type = A26_2K_4K;
break;
case 0x2000:
m_type = A26_F8;
@@ -249,13 +266,13 @@ image_init_result vcs_cart_slot_device::call_load()
m_type = A26_3F;
break;
default:
- m_type = A26_4K;
+ m_type = A26_2K_4K;
printf("Unrecognized cart type!\n");
break;
}
}
- if (has_ram)
+ if (get_software_region("ram"))
m_cart->ram_alloc(get_software_region_length("ram"));
}
else
@@ -263,17 +280,12 @@ image_init_result vcs_cart_slot_device::call_load()
fread(ROM, len);
m_type = identify_cart_type(ROM, len);
- // check for Special Chip (128bytes of RAM)
+ // check for Super Chip (128bytes of RAM)
if (len == 0x2000 || len == 0x4000 || len == 0x8000)
if (detect_super_chip(ROM, len))
{
m_cart->ram_alloc(0x80);
- //printf("Super Chip detected!\n");
}
- // Super chip games:
- // dig dig, crystal castles, millipede, stargate, defender ii, jr. Pac Man,
- // desert falcon, dark chambers, super football, sprintmaster, fatal run,
- // off the wall, shooting arcade, secret quest, radar lock, save mary, klax
// add CBS RAM+ (256bytes of RAM)
if (m_type == A26_FA)
@@ -292,16 +304,14 @@ image_init_result vcs_cart_slot_device::call_load()
m_cart->ram_alloc(0x8000);
}
- //printf("Type: %s\n", vcs_get_slot(m_type));
-
// pass a pointer to the now allocated ROM for the DPC chip
if (m_type == A26_DPC)
m_cart->setup_addon_ptr((uint8_t *)m_cart->get_rom_base() + 0x2000);
- return image_init_result::PASS;
+ m_cart->install_memory_handlers(m_address_space.target());
}
- return image_init_result::PASS;
+ return std::make_pair(std::error_condition(), std::string());
}
@@ -717,10 +727,8 @@ int vcs_cart_slot_device::identify_cart_type(const uint8_t *ROM, uint32_t len)
switch (len)
{
case 0x800:
- type = A26_2K;
- break;
case 0x1000:
- type = A26_4K;
+ type = A26_2K_4K;
break;
case 0x2000:
type = A26_F8;
@@ -745,7 +753,7 @@ int vcs_cart_slot_device::identify_cart_type(const uint8_t *ROM, uint32_t len)
type = A26_3F;
break;
default:
- type = A26_4K;
+ type = A26_2K_4K;
printf("Unrecognized cart type!\n");
break;
}
@@ -762,56 +770,17 @@ std::string vcs_cart_slot_device::get_default_card_software(get_default_card_sof
{
if (hook.image_file())
{
- const char *slot_string;
- uint32_t len = hook.image_file()->size();
+ uint64_t len;
+ hook.image_file()->length(len); // FIXME: check error return, guard against excessively large files
std::vector<uint8_t> rom(len);
- int type;
- hook.image_file()->read(&rom[0], len);
+ read(*hook.image_file(), &rom[0], len); // FIXME: check error return or read returning short
- type = identify_cart_type(&rom[0], len);
- slot_string = vcs_get_slot(type);
+ int const type = identify_cart_type(&rom[0], len);
+ char const *const slot_string = vcs_get_slot(type);
return std::string(slot_string);
}
else
- return software_get_default_slot("a26_4k");
-}
-
-
-/*-------------------------------------------------
- read
- -------------------------------------------------*/
-
-READ8_MEMBER(vcs_cart_slot_device::read_rom)
-{
- if (m_cart)
- return m_cart->read_rom(space, offset, mem_mask);
- else
- return 0xff;
-}
-
-READ8_MEMBER(vcs_cart_slot_device::read_bank)
-{
- if (m_cart)
- return m_cart->read_bank(space, offset, mem_mask);
- else
- return 0xff;
-}
-
-
-/*-------------------------------------------------
- write
- -------------------------------------------------*/
-
-WRITE8_MEMBER(vcs_cart_slot_device::write_bank)
-{
- if (m_cart)
- m_cart->write_bank(space, offset, data, mem_mask);
-}
-
-WRITE8_MEMBER(vcs_cart_slot_device::write_ram)
-{
- if (m_cart)
- m_cart->write_ram(space, offset, data, mem_mask);
+ return software_get_default_slot("a26_2k_4k");
}
diff --git a/src/devices/bus/vcs/vcs_slot.h b/src/devices/bus/vcs/vcs_slot.h
index 6e2cf9ce793..333784e3637 100644
--- a/src/devices/bus/vcs/vcs_slot.h
+++ b/src/devices/bus/vcs/vcs_slot.h
@@ -5,87 +5,15 @@
#pragma once
-#include "softlist_dev.h"
+#include "imagedev/cartrom.h"
-/***************************************************************************
- TYPE DEFINITIONS
- ***************************************************************************/
+class device_vcs_cart_interface;
-#define A26SLOT_ROM_REGION_TAG ":cart:rom"
-
-/* PCB */
-enum
-{
- A26_2K = 0,
- A26_4K,
- A26_F4,
- A26_F6,
- A26_F8,
- A26_F8SW,
- A26_FA,
- A26_FE,
- A26_3E, // to test
- A26_3F,
- A26_E0,
- A26_E7,
- A26_UA,
- A26_DC,
- A26_CV,
- A26_FV,
- A26_JVP, // to test
- A26_32IN1,
- A26_8IN1,
- A26_4IN1,
- A26_DPC,
- A26_SS,
- A26_CM,
- A26_X07,
- A26_HARMONY,
-};
-
-
-// ======================> device_vcs_cart_interface
-
-class device_vcs_cart_interface : public device_slot_card_interface
-{
-public:
- // construction/destruction
- virtual ~device_vcs_cart_interface();
-
- // reading from ROM
- virtual DECLARE_READ8_MEMBER(read_rom) { return 0xff; }
- // writing to RAM chips (sometimes it is in a different range than write_bank!)
- virtual DECLARE_WRITE8_MEMBER(write_ram) { }
-
- // read/write to bankswitch address
- virtual DECLARE_READ8_MEMBER(read_bank) { return 0xff; }
- virtual DECLARE_WRITE8_MEMBER(write_bank) { }
-
- virtual void setup_addon_ptr(uint8_t *ptr) { }
-
- 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(); }
-
-protected:
- device_vcs_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;
-};
-
-
-// ======================> vcs_cart_slot_device
class vcs_cart_slot_device : public device_t,
- public device_image_interface,
- public device_slot_interface
+ public device_cartrom_image_interface,
+ public device_single_card_slot_interface<device_vcs_cart_interface>
{
public:
// construction/destruction
@@ -101,38 +29,30 @@ public:
vcs_cart_slot_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock = 0);
virtual ~vcs_cart_slot_device();
- // image-level overrides
- virtual image_init_result call_load() override;
- virtual void call_unload() override;
- virtual const software_list_loader &get_software_list_loader() const override { return rom_software_list_loader::instance(); }
+ template <typename T> void set_address_space(T &&tag, int no) { m_address_space.set_tag(std::forward<T>(tag), no); }
- int get_cart_type() { return m_type; };
- static int identify_cart_type(const uint8_t *ROM, uint32_t len);
+ // device_image_interface implementation
+ virtual std::pair<std::error_condition, std::string> call_load() override;
+ virtual void call_unload() override;
- virtual iodevice_t image_type() const override { return IO_CARTSLOT; }
- virtual bool is_readable() const override { return 1; }
- virtual bool is_writeable() const override { return 0; }
- virtual bool is_creatable() const override { return 0; }
- virtual bool must_be_loaded() const override { return 1; }
- virtual bool is_reset_on_load() const override { return 1; }
- virtual const char *image_interface() const override { return "a2600_cart"; }
- virtual const char *file_extensions() const override { return "bin,a26"; }
+ 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;
- // reading and writing
- virtual DECLARE_READ8_MEMBER(read_rom);
- virtual DECLARE_READ8_MEMBER(read_bank);
- virtual DECLARE_WRITE8_MEMBER(write_bank);
- virtual DECLARE_WRITE8_MEMBER(write_ram);
+ int get_cart_type() { return m_type; }
+ static int identify_cart_type(const uint8_t *ROM, uint32_t len);
-private:
- // device-level overrides
- virtual void device_start() override;
+protected:
+ // device_t implementation
+ virtual void device_start() override ATTR_COLD;
- device_vcs_cart_interface* m_cart;
+private:
+ device_vcs_cart_interface *m_cart;
int m_type;
+ optional_address_space m_address_space;
static bool detect_snowhite(const uint8_t *cart, uint32_t len);
static bool detect_modeDC(const uint8_t *cart, uint32_t len);
@@ -149,6 +69,35 @@ private:
static bool detect_8K_mode3F(const uint8_t *cart, uint32_t len);
static bool detect_32K_mode3F(const uint8_t *cart, uint32_t len);
static bool detect_super_chip(const uint8_t *cart, uint32_t len);
+
+ friend class device_vcs_cart_interface;
+};
+
+
+class device_vcs_cart_interface : public device_interface
+{
+public:
+ // construction/destruction
+ virtual ~device_vcs_cart_interface();
+
+ virtual void install_memory_handlers(address_space *space) { }
+
+ virtual void setup_addon_ptr(uint8_t *ptr) { }
+
+ 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(); }
+
+protected:
+ device_vcs_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;
};
diff --git a/src/devices/bus/vcs_ctrl/ctrl.cpp b/src/devices/bus/vcs_ctrl/ctrl.cpp
index 57cdad8f4ba..8cf51645a55 100644
--- a/src/devices/bus/vcs_ctrl/ctrl.cpp
+++ b/src/devices/bus/vcs_ctrl/ctrl.cpp
@@ -28,7 +28,7 @@ DEFINE_DEVICE_TYPE(VCS_CONTROL_PORT, vcs_control_port_device, "vcs_control_port"
//-------------------------------------------------
device_vcs_control_port_interface::device_vcs_control_port_interface(const machine_config &mconfig, device_t &device) :
- device_slot_card_interface(mconfig, device)
+ device_interface(device, "vcsctrl")
{
m_port = dynamic_cast<vcs_control_port_device *>(device.owner());
}
@@ -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,12 +65,14 @@ 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"
#include "lightpen.h"
#include "mouse.h"
#include "paddles.h"
+#include "trakball.h"
#include "wheel.h"
void vcs_control_port_devices(device_slot_interface &device)
@@ -84,4 +84,12 @@ 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);
+ device.option_add("trakball", ATARI_TRAKBALL);
+}
+
+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 574a7dc3ae8..b1ca5fde075 100644
--- a/src/devices/bus/vcs_ctrl/ctrl.h
+++ b/src/devices/bus/vcs_ctrl/ctrl.h
@@ -9,8 +9,8 @@
**********************************************************************/
-#ifndef MAME_BUS_CVS_CTRL_CTRL_H
-#define MAME_BUS_CVS_CTRL_CTRL_H
+#ifndef MAME_BUS_VCS_CTRL_CTRL_H
+#define MAME_BUS_VCS_CTRL_CTRL_H
#pragma once
@@ -24,22 +24,25 @@ class vcs_control_port_device;
// ======================> device_vcs_control_port_interface
-class device_vcs_control_port_interface : public device_slot_card_interface
+class device_vcs_control_port_interface : public device_interface
{
public:
- // construction/destruction
- device_vcs_control_port_interface(const machine_config &mconfig, device_t &device);
virtual ~device_vcs_control_port_interface() { }
- virtual uint8_t vcs_joy_r() { return 0xff; };
- virtual uint8_t vcs_pot_x_r() { return 0xff; };
- virtual uint8_t vcs_pot_y_r() { return 0xff; };
- virtual void vcs_joy_w(uint8_t data) { };
+ virtual uint8_t vcs_joy_r() { return 0xff; }
+ virtual uint8_t vcs_pot_x_r() { return 0xff; }
+ virtual uint8_t vcs_pot_y_r() { return 0xff; }
+ virtual void vcs_joy_w(uint8_t data) { }
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);
+
vcs_control_port_device *m_port;
};
@@ -72,18 +75,15 @@ 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; }
- DECLARE_READ8_MEMBER( joy_r ) { return read_joy(); }
uint8_t read_pot_x() { return exists() ? m_device->vcs_pot_x_r() : 0xff; }
- DECLARE_READ8_MEMBER( pot_x_r ) { return read_pot_x(); }
uint8_t read_pot_y() { return exists() ? m_device->vcs_pot_y_r() : 0xff; }
- DECLARE_READ8_MEMBER( pot_y_r ) { return read_pot_y(); }
void joy_w(uint8_t data) { if (exists()) m_device->vcs_joy_w(data); }
@@ -95,7 +95,7 @@ public:
protected:
// device-level overrides
- virtual void device_start() override;
+ virtual void device_start() override ATTR_COLD;
device_vcs_control_port_interface *m_device;
@@ -103,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
+#endif // MAME_BUS_VCS_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..6fb0bf0a316
--- /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 ATTR_COLD;
+ virtual void device_add_mconfig(machine_config &config) override ATTR_COLD;
+
+ // optional information overrides
+ virtual ioport_constructor device_input_ports() const override ATTR_COLD;
+
+ // 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..b390a158e85 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(FUNC(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..4bb0695b47f 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 ATTR_COLD;
+
+ // optional information overrides
+ virtual ioport_constructor device_input_ports() const override ATTR_COLD;
+
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..a84e8ddfeaa 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(FUNC(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..af82bf5dd77 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;
+ virtual void device_start() override ATTR_COLD;
- // device_vcs_control_port_interface overrides
- virtual uint8_t vcs_joy_r() override;
+ // optional information overrides
+ virtual ioport_constructor device_input_ports() const override ATTR_COLD;
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..83a1f1a904f 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;
-
-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 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 ATTR_COLD;
+
+ // optional information overrides
+ virtual ioport_constructor device_input_ports() const override ATTR_COLD;
+
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.cpp b/src/devices/bus/vcs_ctrl/lightpen.cpp
index b79f447a809..f0145d50dda 100644
--- a/src/devices/bus/vcs_ctrl/lightpen.cpp
+++ b/src/devices/bus/vcs_ctrl/lightpen.cpp
@@ -27,7 +27,7 @@ INPUT_CHANGED_MEMBER( vcs_lightpen_device::trigger )
static INPUT_PORTS_START( vcs_lightpen )
PORT_START("JOY")
- PORT_BIT( 0x20, IP_ACTIVE_LOW, IPT_BUTTON1 ) PORT_CHANGED_MEMBER(DEVICE_SELF, vcs_lightpen_device, trigger, 0)
+ PORT_BIT( 0x20, IP_ACTIVE_LOW, IPT_BUTTON1 ) PORT_CHANGED_MEMBER(DEVICE_SELF, FUNC(vcs_lightpen_device::trigger), 0)
PORT_BIT( 0xdf, IP_ACTIVE_LOW, IPT_UNUSED )
PORT_START("LIGHTX")
diff --git a/src/devices/bus/vcs_ctrl/lightpen.h b/src/devices/bus/vcs_ctrl/lightpen.h
index f0b2805bdd6..bd375b07888 100644
--- a/src/devices/bus/vcs_ctrl/lightpen.h
+++ b/src/devices/bus/vcs_ctrl/lightpen.h
@@ -28,17 +28,17 @@ 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 );
protected:
// device-level overrides
- virtual void device_start() override;
+ virtual void device_start() override ATTR_COLD;
- // device_vcs_control_port_interface overrides
- virtual uint8_t vcs_joy_r() override;
+ // optional information overrides
+ virtual ioport_constructor device_input_ports() const override ATTR_COLD;
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..23dabc6c37d 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(FUNC(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..e31000e9180 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 ATTR_COLD;
+
+ // optional information overrides
+ virtual ioport_constructor device_input_ports() const override ATTR_COLD;
+
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 09e7a0d26a5..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(1)
- PORT_BIT( 0x08, IP_ACTIVE_LOW, IPT_BUTTON1 ) PORT_PLAYER(2)
+ 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..6e80b632a58 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 ATTR_COLD;
+
+ // optional information overrides
+ virtual ioport_constructor device_input_ports() const override ATTR_COLD;
+
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/trakball.cpp b/src/devices/bus/vcs_ctrl/trakball.cpp
new file mode 100644
index 00000000000..0da97221762
--- /dev/null
+++ b/src/devices/bus/vcs_ctrl/trakball.cpp
@@ -0,0 +1,150 @@
+// license:BSD-3-Clause
+/**********************************************************************
+
+ Atari CX22/CX80 Trak-Ball
+
+Note: this module only works in trackball mode and not in joystick emulation mode
+
+Reference: Atari, CX22 Trakball Field Service Manual, Rev. 01 (FD100660), November 1983
+
+**********************************************************************/
+
+#include "emu.h"
+#include "trakball.h"
+
+/***************************************************************************
+ CONSTANTS
+***************************************************************************/
+
+#define TRAKBALL_BUTTON_TAG "trackball_buttons"
+#define TRAKBALL_XAXIS_TAG "trackball_x"
+#define TRAKBALL_YAXIS_TAG "trackball_y"
+
+#define TRAKBALL_POS_UNINIT 0xffffffff /* default out-of-range position */
+
+//**************************************************************************
+// DEVICE TYPE DEFINITION
+//**************************************************************************
+
+DEFINE_DEVICE_TYPE(ATARI_TRAKBALL, atari_trakball_device, "atari_trakball", "Atari CX22/CX80 Trak-Ball")
+
+
+//**************************************************************************
+// INPUT PORTS
+//**************************************************************************
+
+static INPUT_PORTS_START(atari_trakball)
+ PORT_START(TRAKBALL_BUTTON_TAG) /* Trak-ball - button */
+ PORT_BIT( 0x0f, IP_ACTIVE_HIGH, IPT_UNUSED )
+ PORT_BIT( 0x20, IP_ACTIVE_LOW, IPT_BUTTON1) PORT_WRITE_LINE_MEMBER(FUNC(atari_trakball_device::trigger_w))
+ PORT_BIT( 0xd0, IP_ACTIVE_LOW, IPT_UNUSED )
+
+ PORT_START(TRAKBALL_XAXIS_TAG) /* Trak-ball - X AXIS */
+ PORT_BIT( 0xff, 0x00, IPT_TRACKBALL_X) PORT_SENSITIVITY(80) PORT_KEYDELTA(0) PORT_PLAYER(1) PORT_CHANGED_MEMBER(DEVICE_SELF, FUNC(atari_trakball_device::trakball_moved), 0)
+
+ PORT_START(TRAKBALL_YAXIS_TAG) /* Trak-ball - Y AXIS */
+ PORT_BIT( 0xff, 0x00, IPT_TRACKBALL_Y) PORT_SENSITIVITY(80) PORT_KEYDELTA(0) PORT_PLAYER(1) PORT_CHANGED_MEMBER(DEVICE_SELF, FUNC(atari_trakball_device::trakball_moved), 1)
+INPUT_PORTS_END
+
+
+//**************************************************************************
+// LIVE DEVICE
+//**************************************************************************
+
+//-------------------------------------------------
+// atari_trakball_device - constructor
+//-------------------------------------------------
+
+atari_trakball_device::atari_trakball_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock)
+ : device_t(mconfig, ATARI_TRAKBALL, tag, owner, clock)
+ , device_vcs_control_port_interface(mconfig, *this)
+ , m_trakballb(*this, TRAKBALL_BUTTON_TAG)
+ , m_trakballxy(*this, { TRAKBALL_XAXIS_TAG, TRAKBALL_YAXIS_TAG })
+ , m_last_pos{ TRAKBALL_POS_UNINIT, TRAKBALL_POS_UNINIT }
+ , m_last_direction{ 0, 0 }
+{
+}
+
+//-------------------------------------------------
+// device_input_ports - device-specific input ports
+//-------------------------------------------------
+
+ioport_constructor atari_trakball_device::device_input_ports() const
+{
+ return INPUT_PORTS_NAME(atari_trakball);
+}
+
+//-------------------------------------------------
+// device_start - device-specific startup
+//-------------------------------------------------
+
+void atari_trakball_device::device_start()
+{
+ save_item(NAME(m_last_pos));
+ save_item(NAME(m_last_direction));
+}
+
+#define QUADRATURE_ANGLE_RESOLUTION 0x02
+
+//-----------------------------------------------------------------
+// trakbal_pos_and_dir_upd - update tracked position and direction
+//-----------------------------------------------------------------
+
+void atari_trakball_device::trakball_pos_and_dir_upd(int axis)
+{
+ int diff_pos = 0;
+ int cur_pos = 0;
+
+ cur_pos = m_trakballxy[axis]->read();
+ if (m_last_pos[axis] == TRAKBALL_POS_UNINIT) {
+ if (!machine().side_effects_disabled()) {
+ m_last_pos[axis] = cur_pos;
+ }
+ }
+ diff_pos = cur_pos - m_last_pos[axis];
+ // wrap-around the position
+ if (diff_pos > 0x7f) {
+ diff_pos -= 0x100;
+ } else if (diff_pos < -0x80) {
+ diff_pos += 0x100;
+ }
+ if (!machine().side_effects_disabled()) {
+ m_last_pos[axis] = cur_pos;
+ if (diff_pos) {
+ m_last_direction[axis] = diff_pos > 0;
+ }
+ }
+}
+
+//---------------------------------------------------------
+// trakball_moved - called when moved outside of polling
+//---------------------------------------------------------
+
+INPUT_CHANGED_MEMBER( atari_trakball_device::trakball_moved )
+{
+ const int axis(param);
+
+ trakball_pos_and_dir_upd(axis);
+}
+
+//-------------------------------------------------
+// vcs_joy_r - read digital inputs
+//-------------------------------------------------
+
+u8 atari_trakball_device::vcs_joy_r()
+{
+ u8 vcs_joy_return = 0;
+
+ for (int axis = 0; axis < 2; axis++) {
+ trakball_pos_and_dir_upd(axis);
+ }
+
+ vcs_joy_return =
+ m_trakballb->read() |
+ (m_last_direction[0] ? 0x01 : 0x00) |
+ ((m_last_pos[0] & QUADRATURE_ANGLE_RESOLUTION) ? 0x02 : 0x00) |
+ (m_last_direction[1] ? 0x04 : 0x00) |
+ ((m_last_pos[1] & QUADRATURE_ANGLE_RESOLUTION) ? 0x08 : 0x00);
+
+ return vcs_joy_return;
+}
diff --git a/src/devices/bus/vcs_ctrl/trakball.h b/src/devices/bus/vcs_ctrl/trakball.h
new file mode 100644
index 00000000000..8bd357b0466
--- /dev/null
+++ b/src/devices/bus/vcs_ctrl/trakball.h
@@ -0,0 +1,53 @@
+// license:BSD-3-Clause
+/**********************************************************************
+
+ Atari CX22/CX80 Trak-Ball
+
+**********************************************************************/
+
+#ifndef MAME_BUS_VCS_CTRL_TRAKBALL_H
+#define MAME_BUS_VCS_CTRL_TRAKBALL_H
+
+#pragma once
+
+#include "ctrl.h"
+
+//**************************************************************************
+// TYPE DEFINITIONS
+//**************************************************************************
+
+// ======================> atari_trakball_device
+
+class atari_trakball_device : public device_t,
+ public device_vcs_control_port_interface
+{
+public:
+ // construction/destruction
+ atari_trakball_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock);
+ DECLARE_INPUT_CHANGED_MEMBER( trakball_moved );
+
+protected:
+ // device_t implementation
+ virtual void device_start() override;
+
+ // optional information overrides
+ virtual ioport_constructor device_input_ports() const override;
+
+ // device_vcs_control_port_interface overrides
+ virtual u8 vcs_joy_r() override;
+
+private:
+ void trakball_pos_and_dir_upd(int axis);
+
+ required_ioport m_trakballb;
+ required_ioport_array<2> m_trakballxy;
+
+ uint32_t m_last_pos[2];
+ uint8_t m_last_direction[2];
+};
+
+
+// device type declaration
+DECLARE_DEVICE_TYPE(ATARI_TRAKBALL, atari_trakball_device)
+
+#endif // MAME_BUS_VCS_CTRL_TRAKBALL_H
diff --git a/src/devices/bus/vcs_ctrl/wheel.cpp b/src/devices/bus/vcs_ctrl/wheel.cpp
index 76e86530cf8..c470f9117ec 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(FUNC(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..6981eaa6b63 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;
+ virtual void device_start() override ATTR_COLD;
- // device_vcs_control_port_interface overrides
- virtual uint8_t vcs_joy_r() override;
+ // optional information overrides
+ virtual ioport_constructor device_input_ports() const override ATTR_COLD;
private:
required_ioport m_joy;
diff --git a/src/devices/bus/vectrex/rom.cpp b/src/devices/bus/vectrex/rom.cpp
index 8f93c87f6fd..04410dd5623 100644
--- a/src/devices/bus/vectrex/rom.cpp
+++ b/src/devices/bus/vectrex/rom.cpp
@@ -64,7 +64,7 @@ void vectrex_rom64k_device::device_reset()
mapper specific handlers
-------------------------------------------------*/
-READ8_MEMBER(vectrex_rom_device::read_rom)
+uint8_t vectrex_rom_device::read_rom(offs_t offset)
{
if (offset < m_rom_size)
return m_rom[offset];
@@ -73,17 +73,17 @@ READ8_MEMBER(vectrex_rom_device::read_rom)
}
-READ8_MEMBER(vectrex_rom64k_device::read_rom)
+uint8_t vectrex_rom64k_device::read_rom(offs_t offset)
{
return m_rom[(offset + m_bank * 0x8000) & (m_rom_size - 1)];
}
-WRITE8_MEMBER(vectrex_rom64k_device::write_bank)
+void vectrex_rom64k_device::write_bank(uint8_t data)
{
m_bank = data >> 6;
}
-WRITE8_MEMBER(vectrex_sram_device::write_ram)
+void vectrex_sram_device::write_ram(offs_t offset, uint8_t data)
{
m_rom[offset & (m_rom_size - 1)] = data;
}
diff --git a/src/devices/bus/vectrex/rom.h b/src/devices/bus/vectrex/rom.h
index 375db83315c..eb5eb0fa2ec 100644
--- a/src/devices/bus/vectrex/rom.h
+++ b/src/devices/bus/vectrex/rom.h
@@ -18,7 +18,7 @@ public:
vectrex_rom_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
// reading and writing
- virtual DECLARE_READ8_MEMBER(read_rom) override;
+ virtual uint8_t read_rom(offs_t offset) override;
protected:
vectrex_rom_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock);
@@ -37,13 +37,13 @@ public:
vectrex_rom64k_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
// reading and writing
- virtual DECLARE_READ8_MEMBER(read_rom) override;
- virtual DECLARE_WRITE8_MEMBER(write_bank) override;
+ virtual uint8_t read_rom(offs_t offset) override;
+ virtual void write_bank(uint8_t data) override;
protected:
// device-level overrides
- virtual void device_start() override;
- virtual void device_reset() override;
+ virtual void device_start() override ATTR_COLD;
+ virtual void device_reset() override ATTR_COLD;
private:
int m_bank;
@@ -58,7 +58,7 @@ public:
vectrex_sram_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
// reading and writing
- virtual DECLARE_WRITE8_MEMBER(write_ram) override;
+ virtual void write_ram(offs_t offset, uint8_t data) override;
};
diff --git a/src/devices/bus/vectrex/slot.cpp b/src/devices/bus/vectrex/slot.cpp
index 43f39178a49..2b5ebd481a1 100644
--- a/src/devices/bus/vectrex/slot.cpp
+++ b/src/devices/bus/vectrex/slot.cpp
@@ -7,7 +7,6 @@
***********************************************************************************************************/
-
#include "emu.h"
#include "slot.h"
@@ -25,10 +24,10 @@ DEFINE_DEVICE_TYPE(VECTREX_CART_SLOT, vectrex_cart_slot_device, "vectrex_cart_sl
// device_vectrex_cart_interface - constructor
//-------------------------------------------------
-device_vectrex_cart_interface::device_vectrex_cart_interface(const machine_config &mconfig, device_t &device)
- : device_slot_card_interface(mconfig, device),
- m_rom(nullptr),
- m_rom_size(0)
+device_vectrex_cart_interface::device_vectrex_cart_interface(const machine_config &mconfig, device_t &device) :
+ device_interface(device, "vectrexcart"),
+ m_rom(nullptr),
+ m_rom_size(0)
{
}
@@ -45,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;
}
}
@@ -64,8 +63,8 @@ void device_vectrex_cart_interface::rom_alloc(uint32_t size, const char *tag)
//-------------------------------------------------
vectrex_cart_slot_device::vectrex_cart_slot_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) :
device_t(mconfig, VECTREX_CART_SLOT, tag, owner, clock),
- device_image_interface(mconfig, *this),
- device_slot_interface(mconfig, *this),
+ device_cartrom_image_interface(mconfig, *this),
+ device_single_card_slot_interface<device_vectrex_cart_interface>(mconfig, *this),
m_type(VECTREX_STD),
m_vec3d(VEC3D_NONE),
m_cart(nullptr)
@@ -87,7 +86,7 @@ vectrex_cart_slot_device::~vectrex_cart_slot_device()
void vectrex_cart_slot_device::device_start()
{
- m_cart = dynamic_cast<device_vectrex_cart_interface *>(get_card_device());
+ m_cart = get_card_device();
}
@@ -112,9 +111,9 @@ static const vectrex_slot slot_list[] =
#if 0
static int vectrex_get_pcb_id(const char *slot)
{
- for (int i = 0; i < ARRAY_LENGTH(slot_list); i++)
+ for (int i = 0; i < std::size(slot_list); i++)
{
- if (!core_stricmp(slot_list[i].slot_option, slot))
+ if (!strcmp(slot_list[i].slot_option, slot))
return slot_list[i].pcb_id;
}
@@ -124,7 +123,7 @@ static int vectrex_get_pcb_id(const char *slot)
static const char *vectrex_get_slot(int type)
{
- for (auto & elem : slot_list)
+ for (auto &elem : slot_list)
{
if (elem.pcb_id == type)
return elem.slot_option;
@@ -137,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_UNSPECIFIED, "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);
@@ -160,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_UNSPECIFIED, "Invalid image");
- return image_init_result::FAIL;
- }
+ return std::make_pair(image_error::INVALIDIMAGE, "Invalid Vectrex ROM");
// determine type
m_type = VECTREX_STD;
@@ -183,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());
}
@@ -199,19 +189,20 @@ std::string vectrex_cart_slot_device::get_default_card_software(get_default_card
{
if (hook.image_file())
{
- const char *slot_string;
- uint32_t size = hook.image_file()->size();
+ // FIXME: consider oversize files, check for errors, and check for read returning early
+ // it's also really wasteful to read the whole file here when only a small part of it is used for identification
+ std::uint64_t size;
+ hook.image_file()->length(size);
std::vector<uint8_t> rom(size);
- int type = VECTREX_STD;
+ read(*hook.image_file(), &rom[0], size);
- hook.image_file()->read(&rom[0], size);
-
- if (!memcmp(&rom[0x06], "SRAM", 4))
+ int type = VECTREX_STD;
+ if (!memcmp(&rom[0x06], "SRAM", 4)) // FIXME: bounds check!
type = VECTREX_SRAM;
if (size > 0x8000)
type = VECTREX_64K;
- slot_string = vectrex_get_slot(type);
+ char const *const slot_string = vectrex_get_slot(type);
//printf("type: %s\n", slot_string);
@@ -225,10 +216,10 @@ std::string vectrex_cart_slot_device::get_default_card_software(get_default_card
read_rom
-------------------------------------------------*/
-READ8_MEMBER(vectrex_cart_slot_device::read_rom)
+uint8_t vectrex_cart_slot_device::read_rom(offs_t offset)
{
if (m_cart)
- return m_cart->read_rom(space, offset);
+ return m_cart->read_rom(offset);
else
return 0xff;
}
@@ -237,18 +228,18 @@ READ8_MEMBER(vectrex_cart_slot_device::read_rom)
write_ram
-------------------------------------------------*/
-WRITE8_MEMBER(vectrex_cart_slot_device::write_ram)
+void vectrex_cart_slot_device::write_ram(offs_t offset, uint8_t data)
{
if (m_cart)
- m_cart->write_ram(space, offset, data);
+ m_cart->write_ram(offset, data);
}
/*-------------------------------------------------
write_bank
-------------------------------------------------*/
-WRITE8_MEMBER(vectrex_cart_slot_device::write_bank)
+void vectrex_cart_slot_device::write_bank(uint8_t data)
{
if (m_cart)
- m_cart->write_bank(space, offset, data);
+ m_cart->write_bank(data);
}
diff --git a/src/devices/bus/vectrex/slot.h b/src/devices/bus/vectrex/slot.h
index f779bf5d514..5276a1062fa 100644
--- a/src/devices/bus/vectrex/slot.h
+++ b/src/devices/bus/vectrex/slot.h
@@ -5,7 +5,7 @@
#pragma once
-#include "softlist_dev.h"
+#include "imagedev/cartrom.h"
/***************************************************************************
@@ -32,18 +32,18 @@ enum
// ======================> device_vectrex_cart_interface
-class device_vectrex_cart_interface : public device_slot_card_interface
+class device_vectrex_cart_interface : public device_interface
{
public:
// construction/destruction
virtual ~device_vectrex_cart_interface();
// reading and writing
- virtual DECLARE_READ8_MEMBER(read_rom) { return 0xff; }
- virtual DECLARE_WRITE8_MEMBER(write_ram) { }
- virtual DECLARE_WRITE8_MEMBER(write_bank) { }
+ virtual uint8_t read_rom(offs_t offset) { return 0xff; }
+ 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; }
@@ -59,45 +59,39 @@ protected:
// ======================> vectrex_cart_slot_device
class vectrex_cart_slot_device : public device_t,
- public device_image_interface,
- public device_slot_interface
+ public device_cartrom_image_interface,
+ public device_single_card_slot_interface<device_vectrex_cart_interface>
{
public:
// construction/destruction
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 const software_list_loader &get_software_list_loader() const override { return rom_software_list_loader::instance(); }
- int get_type() { return m_type; }
- int get_vec3d() { return m_vec3d; }
-
- virtual iodevice_t image_type() const override { return IO_CARTSLOT; }
- virtual bool is_readable() const override { return 1; }
- virtual bool is_writeable() const override { return 0; }
- virtual bool is_creatable() const override { return 0; }
- virtual bool must_be_loaded() const override { return 0; }
- virtual bool is_reset_on_load() const override { return 1; }
- virtual const char *image_interface() const override { return "vectrex_cart"; }
- virtual const char *file_extensions() const override { return "bin,gam,vec"; }
+ 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; }
+ int get_vec3d() { return m_vec3d; }
+
// reading and writing
- virtual DECLARE_READ8_MEMBER(read_rom);
- virtual DECLARE_WRITE8_MEMBER(write_ram);
- virtual DECLARE_WRITE8_MEMBER(write_bank);
+ uint8_t read_rom(offs_t offset);
+ void write_ram(offs_t offset, uint8_t data);
+ void write_bank(uint8_t data);
protected:
- // device-level overrides
- virtual void device_start() override;
+ // device_t implementation
+ virtual void device_start() override ATTR_COLD;
int m_type, m_vec3d;
- device_vectrex_cart_interface* m_cart;
+ device_vectrex_cart_interface *m_cart;
};
@@ -105,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 26ad1980448..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>
//**************************************************************************
@@ -28,11 +30,8 @@ DEFINE_DEVICE_TYPE(VIC10_EXPANSION_SLOT, vic10_expansion_slot_device, "vic10_exp
// device_vic10_expansion_card_interface - constructor
//-------------------------------------------------
-device_vic10_expansion_card_interface::device_vic10_expansion_card_interface(const machine_config &mconfig, device_t &device)
- : device_slot_card_interface(mconfig,device),
- m_lorom(*this, "lorom"),
- m_exram(*this, "exram"),
- m_uprom(*this, "uprom")
+device_vic10_expansion_card_interface::device_vic10_expansion_card_interface(const machine_config &mconfig, device_t &device) :
+ device_interface(device, "vic10exp")
{
m_slot = dynamic_cast<vic10_expansion_slot_device *>(device.owner());
}
@@ -58,8 +57,8 @@ device_vic10_expansion_card_interface::~device_vic10_expansion_card_interface()
vic10_expansion_slot_device::vic10_expansion_slot_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) :
device_t(mconfig, VIC10_EXPANSION_SLOT, tag, owner, clock),
- device_slot_interface(mconfig, *this),
- device_image_interface(mconfig, *this),
+ device_single_card_slot_interface<device_vic10_expansion_card_interface>(mconfig, *this),
+ device_cartrom_image_interface(mconfig, *this),
m_write_irq(*this),
m_write_res(*this),
m_write_cnt(*this),
@@ -70,50 +69,12 @@ vic10_expansion_slot_device::vic10_expansion_slot_device(const machine_config &m
//-------------------------------------------------
-// device_validity_check -
-//-------------------------------------------------
-
-void vic10_expansion_slot_device::device_validity_check(validity_checker &valid) const
-{
- device_t *const carddev = get_card_device();
- if (carddev && !dynamic_cast<device_vic10_expansion_card_interface *>(carddev))
- osd_printf_error("Card device %s (%s) does not implement device_vic10_expansion_card_interface\n", carddev->tag(), carddev->name());
-}
-
-
-//-------------------------------------------------
// device_start - device-specific startup
//-------------------------------------------------
void vic10_expansion_slot_device::device_start()
{
- device_t *const carddev = get_card_device();
- m_card = dynamic_cast<device_vic10_expansion_card_interface *>(carddev);
- if (carddev && !m_card)
- fatalerror("Card device %s (%s) does not implement device_vic10_expansion_card_interface\n", carddev->tag(), carddev->name());
-
- // resolve callbacks
- m_write_irq.resolve_safe();
- m_write_res.resolve_safe();
- m_write_cnt.resolve_safe();
- m_write_sp.resolve_safe();
-
- // inherit bus clock
- if (clock() == 0)
- {
- vic10_expansion_slot_device *root = machine().device<vic10_expansion_slot_device>(VIC10_EXPANSION_SLOT_TAG);
- assert(root);
- set_unscaled_clock(root->clock());
- }
-}
-
-
-//-------------------------------------------------
-// device_reset - device-specific reset
-//-------------------------------------------------
-
-void vic10_expansion_slot_device::device_reset()
-{
+ m_card = get_card_device();
}
@@ -121,28 +82,37 @@ void vic10_expansion_slot_device::device_reset()
// 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"))
{
@@ -151,20 +121,24 @@ 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;
- m_card->m_lorom.allocate(roml_size);
- m_card->m_uprom.allocate(romh_size);
+ m_card->m_lorom = std::make_unique<uint8_t[]>(roml_size);
+ m_card->m_uprom = std::make_unique<uint8_t[]>(romh_size);
- if (roml_size) roml = m_card->m_lorom;
- if (romh_size) romh = m_card->m_lorom;
+ 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
{
@@ -174,7 +148,7 @@ image_init_result vic10_expansion_slot_device::call_load()
}
}
- return image_init_result::PASS;
+ return std::make_pair(err, std::string());
}
@@ -221,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 710b25bbd49..fdfb96408d1 100644
--- a/src/devices/bus/vic10/exp.h
+++ b/src/devices/bus/vic10/exp.h
@@ -36,16 +36,7 @@
#pragma once
-#include "softlist_dev.h"
-#include "formats/cbm_crt.h"
-
-
-//**************************************************************************
-// CONSTANTS
-//**************************************************************************
-
-#define VIC10_EXPANSION_SLOT_TAG "exp"
-
+#include "imagedev/cartrom.h"
//**************************************************************************
@@ -57,8 +48,8 @@
class device_vic10_expansion_card_interface;
class vic10_expansion_slot_device : public device_t,
- public device_slot_interface,
- public device_image_interface
+ public device_single_card_slot_interface<device_vic10_expansion_card_interface>,
+ public device_cartrom_image_interface
{
public:
// construction/destruction
@@ -81,36 +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
- virtual void device_validity_check(validity_checker &valid) const override;
- virtual void device_start() override;
- virtual void device_reset() override;
-
- // image-level overrides
- virtual image_init_result call_load() override;
- virtual const software_list_loader &get_software_list_loader() const override { return rom_software_list_loader::instance(); }
-
- virtual iodevice_t image_type() const override { return IO_CARTSLOT; }
-
- virtual bool is_readable() const override { return 1; }
- virtual bool is_writeable() const override { return 0; }
- virtual bool is_creatable() const override { return 0; }
- virtual bool must_be_loaded() const override { return 1; }
- virtual bool is_reset_on_load() const override { return 1; }
- virtual const char *image_interface() const override { return "vic10_cart"; }
- virtual const char *file_extensions() const override { return "80,e0"; }
-
- // slot interface overrides
+ // device_t implementation
+ virtual void device_start() override ATTR_COLD;
+
+ // 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"; }
+
+ // 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;
@@ -125,7 +107,7 @@ protected:
// ======================> device_vic10_expansion_card_interface
// class representing interface-specific live vic10_expansion card
-class device_vic10_expansion_card_interface : public device_slot_card_interface
+class device_vic10_expansion_card_interface : public device_interface
{
friend class vic10_expansion_slot_device;
@@ -143,9 +125,9 @@ public:
protected:
device_vic10_expansion_card_interface(const machine_config &mconfig, device_t &device);
- optional_shared_ptr<uint8_t> m_lorom;
- optional_shared_ptr<uint8_t> m_exram;
- optional_shared_ptr<uint8_t> m_uprom;
+ std::unique_ptr<uint8_t[]> m_lorom;
+ std::unique_ptr<uint8_t[]> m_exram;
+ std::unique_ptr<uint8_t[]> m_uprom;
vic10_expansion_slot_device *m_slot;
};
diff --git a/src/devices/bus/vic10/multimax.h b/src/devices/bus/vic10/multimax.h
index 51175fc7bd8..9e732f9de48 100644
--- a/src/devices/bus/vic10/multimax.h
+++ b/src/devices/bus/vic10/multimax.h
@@ -29,8 +29,8 @@ public:
protected:
// device-level overrides
- virtual void device_start() override;
- virtual void device_reset() override;
+ virtual void device_start() override ATTR_COLD;
+ virtual void device_reset() override ATTR_COLD;
// device_vic10_expansion_card_interface overrides
virtual uint8_t vic10_cd_r(offs_t offset, uint8_t data, int lorom, int uprom, int exram) override;
diff --git a/src/devices/bus/vic10/std.cpp b/src/devices/bus/vic10/std.cpp
index de4ba6ff8b6..a4eff1853ac 100644
--- a/src/devices/bus/vic10/std.cpp
+++ b/src/devices/bus/vic10/std.cpp
@@ -48,17 +48,17 @@ void vic10_standard_cartridge_device::device_start()
uint8_t vic10_standard_cartridge_device::vic10_cd_r(offs_t offset, uint8_t data, int lorom, int uprom, int exram)
{
- if (!lorom && m_lorom.bytes())
+ if (!lorom && m_lorom)
{
- data = m_lorom[offset & m_lorom.mask()];
+ data = m_lorom[offset & 0x1fff];
}
- else if (!exram && m_exram.bytes())
+ else if (!exram && m_exram)
{
- data = m_exram[offset & m_exram.mask()];
+ data = m_exram[offset & 0x7ff];
}
- else if (!uprom && m_uprom.bytes())
+ else if (!uprom && m_uprom)
{
- data = m_uprom[offset & m_uprom.mask()];
+ data = m_uprom[offset & 0x1fff];
}
return data;
@@ -71,8 +71,8 @@ uint8_t vic10_standard_cartridge_device::vic10_cd_r(offs_t offset, uint8_t data,
void vic10_standard_cartridge_device::vic10_cd_w(offs_t offset, uint8_t data, int lorom, int uprom, int exram)
{
- if (!exram && m_exram.bytes())
+ if (!exram && m_exram)
{
- m_exram[offset & m_exram.mask()] = data;
+ m_exram[offset & 0x7ff] = data;
}
}
diff --git a/src/devices/bus/vic10/std.h b/src/devices/bus/vic10/std.h
index 3279a58333c..72e21dc58a0 100644
--- a/src/devices/bus/vic10/std.h
+++ b/src/devices/bus/vic10/std.h
@@ -30,7 +30,7 @@ public:
protected:
// device-level overrides
- virtual void device_start() override;
+ virtual void device_start() override ATTR_COLD;
// device_vic10_expansion_card_interface overrides
virtual uint8_t vic10_cd_r(offs_t offset, uint8_t data, int lorom, int uprom, int exram) override;
diff --git a/src/devices/bus/vic20/4cga.cpp b/src/devices/bus/vic20/4cga.cpp
index f806598433a..974f7cf2fd6 100644
--- a/src/devices/bus/vic20/4cga.cpp
+++ b/src/devices/bus/vic20/4cga.cpp
@@ -23,19 +23,19 @@ DEFINE_DEVICE_TYPE(C64_4CGA, c64_4cga_device, "c64_4cga", "C64 Protovision 4 Pla
static INPUT_PORTS_START( c64_4player )
PORT_START("JOY3")
- PORT_BIT( 0x01, IP_ACTIVE_LOW, IPT_JOYSTICK_UP ) PORT_8WAY PORT_PLAYER(1) PORT_WRITE_LINE_DEVICE_MEMBER(DEVICE_SELF, c64_4cga_device, write_joy3_0)
- PORT_BIT( 0x02, IP_ACTIVE_LOW, IPT_JOYSTICK_DOWN ) PORT_8WAY PORT_PLAYER(1) PORT_WRITE_LINE_DEVICE_MEMBER(DEVICE_SELF, c64_4cga_device, write_joy3_1)
- PORT_BIT( 0x04, IP_ACTIVE_LOW, IPT_JOYSTICK_LEFT ) PORT_8WAY PORT_PLAYER(1) PORT_WRITE_LINE_DEVICE_MEMBER(DEVICE_SELF, c64_4cga_device, write_joy3_2)
- PORT_BIT( 0x08, IP_ACTIVE_LOW, IPT_JOYSTICK_RIGHT ) PORT_8WAY PORT_PLAYER(1) PORT_WRITE_LINE_DEVICE_MEMBER(DEVICE_SELF, c64_4cga_device, write_joy3_3)
- PORT_BIT( 0x10, IP_ACTIVE_LOW, IPT_BUTTON1 ) PORT_PLAYER(1) PORT_WRITE_LINE_DEVICE_MEMBER(DEVICE_SELF, device_pet_user_port_interface, output_h)
+ PORT_BIT( 0x01, IP_ACTIVE_LOW, IPT_JOYSTICK_UP ) PORT_8WAY PORT_PLAYER(1) PORT_WRITE_LINE_DEVICE_MEMBER(DEVICE_SELF, FUNC(c64_4cga_device::write_joy3_0))
+ PORT_BIT( 0x02, IP_ACTIVE_LOW, IPT_JOYSTICK_DOWN ) PORT_8WAY PORT_PLAYER(1) PORT_WRITE_LINE_DEVICE_MEMBER(DEVICE_SELF, FUNC(c64_4cga_device::write_joy3_1))
+ PORT_BIT( 0x04, IP_ACTIVE_LOW, IPT_JOYSTICK_LEFT ) PORT_8WAY PORT_PLAYER(1) PORT_WRITE_LINE_DEVICE_MEMBER(DEVICE_SELF, FUNC(c64_4cga_device::write_joy3_2))
+ PORT_BIT( 0x08, IP_ACTIVE_LOW, IPT_JOYSTICK_RIGHT ) PORT_8WAY PORT_PLAYER(1) PORT_WRITE_LINE_DEVICE_MEMBER(DEVICE_SELF, FUNC(c64_4cga_device::write_joy3_3))
+ PORT_BIT( 0x10, IP_ACTIVE_LOW, IPT_BUTTON1 ) PORT_PLAYER(1) PORT_WRITE_LINE_DEVICE_MEMBER(DEVICE_SELF, FUNC(device_pet_user_port_interface::output_h))
PORT_BIT( 0xe0, IP_ACTIVE_LOW, IPT_UNUSED )
PORT_START("JOY4")
- PORT_BIT( 0x01, IP_ACTIVE_LOW, IPT_JOYSTICK_UP ) PORT_8WAY PORT_PLAYER(2) PORT_WRITE_LINE_DEVICE_MEMBER(DEVICE_SELF, c64_4cga_device, write_joy4_0)
- PORT_BIT( 0x02, IP_ACTIVE_LOW, IPT_JOYSTICK_DOWN ) PORT_8WAY PORT_PLAYER(2) PORT_WRITE_LINE_DEVICE_MEMBER(DEVICE_SELF, c64_4cga_device, write_joy4_1)
- PORT_BIT( 0x04, IP_ACTIVE_LOW, IPT_JOYSTICK_LEFT ) PORT_8WAY PORT_PLAYER(2) PORT_WRITE_LINE_DEVICE_MEMBER(DEVICE_SELF, c64_4cga_device, write_joy4_2)
- PORT_BIT( 0x08, IP_ACTIVE_LOW, IPT_JOYSTICK_RIGHT ) PORT_8WAY PORT_PLAYER(2) PORT_WRITE_LINE_DEVICE_MEMBER(DEVICE_SELF, c64_4cga_device, write_joy4_3)
- PORT_BIT( 0x10, IP_ACTIVE_LOW, IPT_BUTTON1 ) PORT_PLAYER(2) PORT_WRITE_LINE_DEVICE_MEMBER(DEVICE_SELF, device_pet_user_port_interface, output_j)
+ PORT_BIT( 0x01, IP_ACTIVE_LOW, IPT_JOYSTICK_UP ) PORT_8WAY PORT_PLAYER(2) PORT_WRITE_LINE_DEVICE_MEMBER(DEVICE_SELF, FUNC(c64_4cga_device::write_joy4_0))
+ PORT_BIT( 0x02, IP_ACTIVE_LOW, IPT_JOYSTICK_DOWN ) PORT_8WAY PORT_PLAYER(2) PORT_WRITE_LINE_DEVICE_MEMBER(DEVICE_SELF, FUNC(c64_4cga_device::write_joy4_1))
+ PORT_BIT( 0x04, IP_ACTIVE_LOW, IPT_JOYSTICK_LEFT ) PORT_8WAY PORT_PLAYER(2) PORT_WRITE_LINE_DEVICE_MEMBER(DEVICE_SELF, FUNC(c64_4cga_device::write_joy4_2))
+ PORT_BIT( 0x08, IP_ACTIVE_LOW, IPT_JOYSTICK_RIGHT ) PORT_8WAY PORT_PLAYER(2) PORT_WRITE_LINE_DEVICE_MEMBER(DEVICE_SELF, FUNC(c64_4cga_device::write_joy4_3))
+ PORT_BIT( 0x10, IP_ACTIVE_LOW, IPT_BUTTON1 ) PORT_PLAYER(2) PORT_WRITE_LINE_DEVICE_MEMBER(DEVICE_SELF, FUNC(device_pet_user_port_interface::output_j))
PORT_BIT( 0xe0, IP_ACTIVE_LOW, IPT_UNUSED )
INPUT_PORTS_END
@@ -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..48c7391dfac 100644
--- a/src/devices/bus/vic20/4cga.h
+++ b/src/devices/bus/vic20/4cga.h
@@ -30,24 +30,24 @@ public:
c64_4cga_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;
+ virtual ioport_constructor device_input_ports() const override ATTR_COLD;
- 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;
+ virtual void device_start() override ATTR_COLD;
// 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 1b634cd0321..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>
+
//**************************************************************************
@@ -28,14 +32,9 @@ 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_slot_card_interface(mconfig, device),
- m_blk1(*this, "blk1"),
- m_blk2(*this, "blk2"),
- m_blk3(*this, "blk3"),
- m_blk5(*this, "blk5"),
- m_nvram(*this, "nvram")
+ : device_interface(device, "vic20exp")
+ , m_slot(dynamic_cast<vic20_expansion_slot_device *>(device.owner()))
{
- m_slot = dynamic_cast<vic20_expansion_slot_device *>(device.owner());
}
@@ -59,8 +58,8 @@ device_vic20_expansion_card_interface::~device_vic20_expansion_card_interface()
vic20_expansion_slot_device::vic20_expansion_slot_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) :
device_t(mconfig, VIC20_EXPANSION_SLOT, tag, owner, clock),
- device_slot_interface(mconfig, *this),
- device_image_interface(mconfig, *this),
+ device_single_card_slot_interface<device_vic20_expansion_card_interface>(mconfig, *this),
+ device_cartrom_image_interface(mconfig, *this),
m_write_irq(*this),
m_write_nmi(*this),
m_write_res(*this),
@@ -70,32 +69,12 @@ vic20_expansion_slot_device::vic20_expansion_slot_device(const machine_config &m
//-------------------------------------------------
-// device_validity_check -
-//-------------------------------------------------
-
-void vic20_expansion_slot_device::device_validity_check(validity_checker &valid) const
-{
- device_t *const carddev = get_card_device();
- if (carddev && !dynamic_cast<device_vic20_expansion_card_interface *>(carddev))
- osd_printf_error("Card device %s (%s) does not implement device_vic20_expansion_card_interface\n", carddev->tag(), carddev->name());
-}
-
-
-//-------------------------------------------------
// device_start - device-specific startup
//-------------------------------------------------
void vic20_expansion_slot_device::device_start()
{
- device_t *const carddev = get_card_device();
- m_card = dynamic_cast<device_vic20_expansion_card_interface *>(carddev);
- if (carddev && !m_card)
- fatalerror("Card device %s (%s) does not implement device_vic20_expansion_card_interface\n", carddev->tag(), carddev->name());
-
- // resolve callbacks
- m_write_irq.resolve_safe();
- m_write_nmi.resolve_safe();
- m_write_res.resolve_safe();
+ m_card = get_card_device();
}
@@ -112,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
{
@@ -152,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 f7e51b0ee57..02ae3e73dde 100644
--- a/src/devices/bus/vic20/exp.h
+++ b/src/devices/bus/vic20/exp.h
@@ -36,15 +36,7 @@
#pragma once
-#include "softlist_dev.h"
-
-
-//**************************************************************************
-// CONSTANTS
-//**************************************************************************
-
-#define VIC20_EXPANSION_SLOT_TAG "exp"
-
+#include "imagedev/cartrom.h"
//**************************************************************************
@@ -56,8 +48,8 @@
class device_vic20_expansion_card_interface;
class vic20_expansion_slot_device : public device_t,
- public device_slot_interface,
- public device_image_interface
+ public device_single_card_slot_interface<device_vic20_expansion_card_interface>,
+ public device_cartrom_image_interface
{
public:
// construction/destruction
@@ -83,31 +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
- virtual void device_validity_check(validity_checker &valid) const override;
- virtual void device_start() override;
- virtual void device_reset() override;
-
- // image-level overrides
- virtual image_init_result call_load() override;
- virtual const software_list_loader &get_software_list_loader() const override { return rom_software_list_loader::instance(); }
-
- virtual iodevice_t image_type() const override { return IO_CARTSLOT; }
-
- virtual bool is_readable() const override { return 1; }
- virtual bool is_writeable() const override { return 0; }
- virtual bool is_creatable() const override { return 0; }
- virtual bool must_be_loaded() const override { return 0; }
- virtual bool is_reset_on_load() const override { return 1; }
- virtual const char *image_interface() const override { return "vic1001_cart"; }
- virtual const char *file_extensions() const override { return "20,40,60,70,a0,b0,crt"; }
-
- // slot interface overrides
+ // device_t implementation
+ virtual void device_start() override ATTR_COLD;
+ virtual void device_reset() override ATTR_COLD;
+
+ // 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"; }
+
+ // 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;
@@ -121,7 +105,7 @@ protected:
// ======================> device_vic20_expansion_card_interface
// class representing interface-specific live vic20_expansion card
-class device_vic20_expansion_card_interface : public device_slot_card_interface
+class device_vic20_expansion_card_interface : public device_interface
{
friend class vic20_expansion_slot_device;
@@ -129,19 +113,18 @@ public:
// construction/destruction
virtual ~device_vic20_expansion_card_interface();
- 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) { return data; };
- 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) { };
+ 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) { return data; }
+ 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) { }
protected:
device_vic20_expansion_card_interface(const machine_config &mconfig, device_t &device);
- optional_shared_ptr<uint8_t> m_blk1;
- optional_shared_ptr<uint8_t> m_blk2;
- optional_shared_ptr<uint8_t> m_blk3;
- optional_shared_ptr<uint8_t> m_blk5;
- optional_shared_ptr<uint8_t> m_nvram;
+ std::unique_ptr<uint8_t[]> m_blk1;
+ std::unique_ptr<uint8_t[]> m_blk2;
+ 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/fe3.cpp b/src/devices/bus/vic20/fe3.cpp
index f008bec3cb8..230dc076bb4 100644
--- a/src/devices/bus/vic20/fe3.cpp
+++ b/src/devices/bus/vic20/fe3.cpp
@@ -105,7 +105,7 @@ vic20_final_expansion_3_device::vic20_final_expansion_3_device(const machine_con
device_t(mconfig, VIC20_FE3, tag, owner, clock),
device_vic20_expansion_card_interface(mconfig, *this),
m_flash_rom(*this, AM29F040_TAG),
- m_ram(*this, "sram"), m_reg1(0), m_reg2(0), m_lockbit(0)
+ m_ram(*this, "sram", 0x80000, ENDIANNESS_LITTLE), m_reg1(0), m_reg2(0), m_lockbit(0)
{
}
@@ -116,8 +116,6 @@ vic20_final_expansion_3_device::vic20_final_expansion_3_device(const machine_con
void vic20_final_expansion_3_device::device_start()
{
- m_ram.allocate(0x80000);
-
// state saving
save_item(NAME(m_reg1));
save_item(NAME(m_reg2));
diff --git a/src/devices/bus/vic20/fe3.h b/src/devices/bus/vic20/fe3.h
index 018ef2617b6..02871283ddb 100644
--- a/src/devices/bus/vic20/fe3.h
+++ b/src/devices/bus/vic20/fe3.h
@@ -31,12 +31,12 @@ public:
protected:
// device-level overrides
- virtual void device_start() override;
- virtual void device_reset() override;
+ virtual void device_start() override ATTR_COLD;
+ virtual void device_reset() override ATTR_COLD;
// optional information overrides
- virtual const tiny_rom_entry *device_rom_region() const override;
- virtual void device_add_mconfig(machine_config &config) override;
+ virtual const tiny_rom_entry *device_rom_region() const override ATTR_COLD;
+ virtual void device_add_mconfig(machine_config &config) override ATTR_COLD;
// device_vic20_expansion_card_interface overrides
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;
@@ -77,7 +77,7 @@ private:
void write_register(offs_t offset, uint8_t data);
required_device<amd_29f040_device> m_flash_rom;
- optional_shared_ptr<uint8_t> m_ram;
+ memory_share_creator<uint8_t> m_ram;
uint8_t m_reg1;
uint8_t m_reg2;
diff --git a/src/devices/bus/vic20/megacart.cpp b/src/devices/bus/vic20/megacart.cpp
index 8094adfba2b..74da56d5395 100644
--- a/src/devices/bus/vic20/megacart.cpp
+++ b/src/devices/bus/vic20/megacart.cpp
@@ -39,6 +39,7 @@ vic20_megacart_device::vic20_megacart_device(const machine_config &mconfig, cons
: device_t(mconfig, VIC20_MEGACART, tag, owner, clock)
, device_vic20_expansion_card_interface(mconfig, *this)
, device_nvram_interface(mconfig, *this)
+ , m_nvram(*this, "nvram", 0x2000, ENDIANNESS_LITTLE)
, m_nvram_en(0)
{
}
@@ -50,8 +51,6 @@ vic20_megacart_device::vic20_megacart_device(const machine_config &mconfig, cons
void vic20_megacart_device::device_start()
{
- m_nvram.allocate(0x2000);
-
// state saving
save_item(NAME(m_nvram_en));
}
@@ -66,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 52f5182fc3c..7e99646fe6a 100644
--- a/src/devices/bus/vic20/megacart.h
+++ b/src/devices/bus/vic20/megacart.h
@@ -30,23 +30,22 @@ public:
vic20_megacart_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_t implementation
+ 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;
- // optional information overrides
- virtual void device_add_mconfig(machine_config &config) override;
+ // 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_nvram_interface overrides
- virtual void nvram_default() override { }
- virtual void nvram_read(emu_file &file) override { file.read(m_nvram, m_nvram.bytes()); }
- virtual void nvram_write(emu_file &file) override { file.write(m_nvram, m_nvram.bytes()); }
-
- // 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;
private:
+ memory_share_creator<uint8_t> m_nvram;
int m_nvram_en;
};
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/speakeasy.h b/src/devices/bus/vic20/speakeasy.h
index 6df3880d2df..1fd60ef0732 100644
--- a/src/devices/bus/vic20/speakeasy.h
+++ b/src/devices/bus/vic20/speakeasy.h
@@ -32,10 +32,10 @@ public:
protected:
// device-level overrides
- virtual void device_start() override;
+ virtual void device_start() override ATTR_COLD;
// optional information overrides
- virtual void device_add_mconfig(machine_config &config) override;
+ virtual void device_add_mconfig(machine_config &config) override ATTR_COLD;
// device_vic20_expansion_card_interface overrides
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;
diff --git a/src/devices/bus/vic20/std.h b/src/devices/bus/vic20/std.h
index 0318f80aa54..cf2b5837a14 100644
--- a/src/devices/bus/vic20/std.h
+++ b/src/devices/bus/vic20/std.h
@@ -30,7 +30,7 @@ public:
protected:
// device-level overrides
- virtual void device_start() override;
+ virtual void device_start() override ATTR_COLD;
// device_vic20_expansion_card_interface overrides
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;
diff --git a/src/devices/bus/vic20/vic1010.h b/src/devices/bus/vic20/vic1010.h
index af85f4bfc3c..c7bb7b93b16 100644
--- a/src/devices/bus/vic20/vic1010.h
+++ b/src/devices/bus/vic20/vic1010.h
@@ -30,11 +30,11 @@ public:
protected:
// device-level overrides
- virtual void device_start() override;
- virtual void device_reset() override;
+ virtual void device_start() override ATTR_COLD;
+ virtual void device_reset() override ATTR_COLD;
// optional information overrides
- virtual void device_add_mconfig(machine_config &config) override;
+ virtual void device_add_mconfig(machine_config &config) override ATTR_COLD;
// device_vic20_expansion_card_interface overrides
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;
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..5ba68aab310 100644
--- a/src/devices/bus/vic20/vic1011.h
+++ b/src/devices/bus/vic20/vic1011.h
@@ -29,20 +29,20 @@ 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
- virtual void device_start() override;
+ virtual void device_start() override ATTR_COLD;
// optional information overrides
- virtual void device_add_mconfig(machine_config &config) override;
+ virtual void device_add_mconfig(machine_config &config) override ATTR_COLD;
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/vic1110.cpp b/src/devices/bus/vic20/vic1110.cpp
index 9b2d0c192d9..f9ee69fd8b1 100644
--- a/src/devices/bus/vic20/vic1110.cpp
+++ b/src/devices/bus/vic20/vic1110.cpp
@@ -69,7 +69,7 @@ ioport_constructor vic1110_device::device_input_ports() const
vic1110_device::vic1110_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
: device_t(mconfig, VIC1110, tag, owner, clock)
, device_vic20_expansion_card_interface(mconfig, *this)
- , m_ram(*this, "ram")
+ , m_ram(*this, "ram", 0x2000, ENDIANNESS_LITTLE)
, m_sw(*this, "SW")
{
}
@@ -81,8 +81,6 @@ vic1110_device::vic1110_device(const machine_config &mconfig, const char *tag, d
void vic1110_device::device_start()
{
- // allocate memory
- m_ram.allocate(0x2000);
}
diff --git a/src/devices/bus/vic20/vic1110.h b/src/devices/bus/vic20/vic1110.h
index 9ec1ea2791a..07546c913fb 100644
--- a/src/devices/bus/vic20/vic1110.h
+++ b/src/devices/bus/vic20/vic1110.h
@@ -29,18 +29,18 @@ public:
vic1110_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;
+ virtual ioport_constructor device_input_ports() const override ATTR_COLD;
protected:
// device-level overrides
- virtual void device_start() override;
+ virtual void device_start() override ATTR_COLD;
// device_vic20_expansion_card_interface overrides
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;
private:
- optional_shared_ptr<uint8_t> m_ram;
+ memory_share_creator<uint8_t> m_ram;
required_ioport m_sw;
};
diff --git a/src/devices/bus/vic20/vic1111.cpp b/src/devices/bus/vic20/vic1111.cpp
index 1f8fa215078..4bb3a492ef2 100644
--- a/src/devices/bus/vic20/vic1111.cpp
+++ b/src/devices/bus/vic20/vic1111.cpp
@@ -30,7 +30,7 @@ DEFINE_DEVICE_TYPE(VIC1111, vic1111_device, "vic1111", "VIC-1111 16K RAM Expansi
vic1111_device::vic1111_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
: device_t(mconfig, VIC1111, tag, owner, clock)
, device_vic20_expansion_card_interface(mconfig, *this)
- , m_ram(*this, "ram")
+ , m_ram(*this, "ram", 0x4000, ENDIANNESS_LITTLE)
{
}
@@ -41,8 +41,6 @@ vic1111_device::vic1111_device(const machine_config &mconfig, const char *tag, d
void vic1111_device::device_start()
{
- // allocate memory
- m_ram.allocate(0x4000);
}
diff --git a/src/devices/bus/vic20/vic1111.h b/src/devices/bus/vic20/vic1111.h
index eb42db2f149..a1d47a5e6d7 100644
--- a/src/devices/bus/vic20/vic1111.h
+++ b/src/devices/bus/vic20/vic1111.h
@@ -30,14 +30,14 @@ public:
protected:
// device-level overrides
- virtual void device_start() override;
+ virtual void device_start() override ATTR_COLD;
// device_vic20_expansion_card_interface overrides
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;
private:
- optional_shared_ptr<uint8_t> m_ram;
+ memory_share_creator<uint8_t> m_ram;
};
diff --git a/src/devices/bus/vic20/vic1112.cpp b/src/devices/bus/vic20/vic1112.cpp
index 77b421f51d8..c7043110992 100644
--- a/src/devices/bus/vic20/vic1112.cpp
+++ b/src/devices/bus/vic20/vic1112.cpp
@@ -27,14 +27,14 @@
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;
m_slot->irq_w(m_via0_irq | m_via1_irq);
}
-READ8_MEMBER( vic1112_device::via0_pb_r )
+uint8_t vic1112_device::via0_pb_r()
{
/*
@@ -62,7 +62,7 @@ READ8_MEMBER( vic1112_device::via0_pb_r )
return data;
}
-WRITE8_MEMBER( vic1112_device::via0_pb_w )
+void vic1112_device::via0_pb_w(uint8_t data)
{
/*
@@ -85,7 +85,7 @@ WRITE8_MEMBER( vic1112_device::via0_pb_w )
}
-WRITE_LINE_MEMBER( vic1112_device::via1_irq_w )
+void vic1112_device::via1_irq_w(int state)
{
m_via1_irq = state;
@@ -99,12 +99,12 @@ WRITE_LINE_MEMBER( vic1112_device::via1_irq_w )
void vic1112_device::device_add_mconfig(machine_config &config)
{
- VIA6522(config, m_via0, DERIVED_CLOCK(1, 1));
+ MOS6522(config, m_via0, DERIVED_CLOCK(1, 1));
m_via0->readpb_handler().set(FUNC(vic1112_device::via0_pb_r));
m_via0->writepb_handler().set(FUNC(vic1112_device::via0_pb_w));
m_via0->irq_handler().set(FUNC(vic1112_device::via0_irq_w));
- VIA6522(config, m_via1, DERIVED_CLOCK(1, 1));
+ MOS6522(config, m_via1, DERIVED_CLOCK(1, 1));
m_via1->readpb_handler().set(IEEE488_TAG, FUNC(ieee488_device::dio_r));
m_via1->writepa_handler().set(IEEE488_TAG, FUNC(ieee488_device::host_dio_w));
m_via1->ca2_handler().set(IEEE488_TAG, FUNC(ieee488_device::host_atn_w));
diff --git a/src/devices/bus/vic20/vic1112.h b/src/devices/bus/vic20/vic1112.h
index 5c4e05446a0..67080793640 100644
--- a/src/devices/bus/vic20/vic1112.h
+++ b/src/devices/bus/vic20/vic1112.h
@@ -35,21 +35,21 @@ public:
protected:
// device-level overrides
- virtual void device_start() override;
- virtual void device_reset() override;
+ virtual void device_start() override ATTR_COLD;
+ virtual void device_reset() override ATTR_COLD;
// optional information overrides
- virtual void device_add_mconfig(machine_config &config) override;
+ virtual void device_add_mconfig(machine_config &config) override ATTR_COLD;
// device_vic20_expansion_card_interface overrides
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;
private:
- DECLARE_WRITE_LINE_MEMBER( via0_irq_w );
- DECLARE_READ8_MEMBER( via0_pb_r );
- DECLARE_WRITE8_MEMBER( via0_pb_w );
- DECLARE_WRITE_LINE_MEMBER( via1_irq_w );
+ void via0_irq_w(int state);
+ uint8_t via0_pb_r();
+ void via0_pb_w(uint8_t data);
+ void via1_irq_w(int state);
required_device<via6522_device> m_via0;
required_device<via6522_device> m_via1;
diff --git a/src/devices/bus/vic20/vic1210.cpp b/src/devices/bus/vic20/vic1210.cpp
index 6fa2a917254..88c94e8fbbd 100644
--- a/src/devices/bus/vic20/vic1210.cpp
+++ b/src/devices/bus/vic20/vic1210.cpp
@@ -31,7 +31,7 @@ DEFINE_DEVICE_TYPE(VIC1210, vic1210_device, "vic1210", "VIC-1210 3K RAM Expansio
vic1210_device::vic1210_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
: device_t(mconfig, VIC1210, tag, owner, clock)
, device_vic20_expansion_card_interface(mconfig, *this)
- , m_ram(*this, "ram")
+ , m_ram(*this, "ram", 0xc00, ENDIANNESS_LITTLE)
{
}
@@ -42,8 +42,6 @@ vic1210_device::vic1210_device(const machine_config &mconfig, const char *tag, d
void vic1210_device::device_start()
{
- // allocate memory
- m_ram.allocate(0xc00);
}
diff --git a/src/devices/bus/vic20/vic1210.h b/src/devices/bus/vic20/vic1210.h
index f890d5ad61e..82eb40fd651 100644
--- a/src/devices/bus/vic20/vic1210.h
+++ b/src/devices/bus/vic20/vic1210.h
@@ -31,14 +31,14 @@ public:
protected:
// device-level overrides
- virtual void device_start() override;
+ virtual void device_start() override ATTR_COLD;
// device_vic20_expansion_card_interface overrides
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;
private:
- optional_shared_ptr<uint8_t> m_ram;
+ memory_share_creator<uint8_t> m_ram;
};
diff --git a/src/devices/bus/vic20/videopak.cpp b/src/devices/bus/vic20/videopak.cpp
index 98a6c054d22..542c2fb8320 100644
--- a/src/devices/bus/vic20/videopak.cpp
+++ b/src/devices/bus/vic20/videopak.cpp
@@ -77,7 +77,7 @@ MC6845_UPDATE_ROW( vic20_video_pak_device::crtc_update_row )
int x = (column * 8) + bit;
int color = BIT(data, 7) && de;
- bitmap.pix32(vbp + y, hbp + x) = pen[color];
+ bitmap.pix(vbp + y, hbp + x) = pen[color];
data <<= 1;
}
@@ -112,7 +112,7 @@ void vic20_video_pak_device::device_add_mconfig(machine_config &config)
m_crtc->set_screen(MC6845_SCREEN_TAG);
m_crtc->set_show_border_area(true);
m_crtc->set_char_width(8);
- m_crtc->set_update_row_callback(FUNC(vic20_video_pak_device::crtc_update_row), this);
+ m_crtc->set_update_row_callback(FUNC(vic20_video_pak_device::crtc_update_row));
}
@@ -131,8 +131,8 @@ vic20_video_pak_device::vic20_video_pak_device(const machine_config &mconfig, co
m_crtc(*this, MC6845_TAG),
m_palette(*this, "palette"),
m_char_rom(*this, MC6845_TAG),
- m_videoram(*this, "videoram"),
- m_ram(*this, "ram")
+ m_videoram(*this, "videoram", VIDEORAM_SIZE, ENDIANNESS_LITTLE),
+ m_ram(*this, "ram", RAM_SIZE, ENDIANNESS_LITTLE)
{
}
@@ -143,9 +143,6 @@ vic20_video_pak_device::vic20_video_pak_device(const machine_config &mconfig, co
void vic20_video_pak_device::device_start()
{
- // allocate memory
- m_videoram.allocate(VIDEORAM_SIZE);
- m_ram.allocate(RAM_SIZE);
}
diff --git a/src/devices/bus/vic20/videopak.h b/src/devices/bus/vic20/videopak.h
index 9e3176e5365..8819ef7e7d1 100644
--- a/src/devices/bus/vic20/videopak.h
+++ b/src/devices/bus/vic20/videopak.h
@@ -34,12 +34,12 @@ public:
protected:
// device-level overrides
- virtual void device_start() override;
- virtual void device_reset() override;
+ virtual void device_start() override ATTR_COLD;
+ virtual void device_reset() override ATTR_COLD;
// optional information overrides
- virtual const tiny_rom_entry *device_rom_region() const override;
- virtual void device_add_mconfig(machine_config &config) override;
+ virtual const tiny_rom_entry *device_rom_region() const override ATTR_COLD;
+ virtual void device_add_mconfig(machine_config &config) override ATTR_COLD;
// device_vic20_expansion_card_interface overrides
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;
@@ -51,8 +51,8 @@ private:
required_device<mc6845_device> m_crtc;
required_device<palette_device> m_palette;
required_memory_region m_char_rom;
- optional_shared_ptr<uint8_t> m_videoram;
- optional_shared_ptr<uint8_t> m_ram;
+ memory_share_creator<uint8_t> m_videoram;
+ memory_share_creator<uint8_t> m_ram;
bool m_case;
bool m_bank_size;
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..32ae4e10ce0
--- /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 ATTR_COLD;
+
+ // 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 808907678cc..4423ae3a385 100644
--- a/src/devices/bus/vidbrain/exp.cpp
+++ b/src/devices/bus/vidbrain/exp.cpp
@@ -12,14 +12,6 @@
//**************************************************************************
-// MACROS/CONSTANTS
-//**************************************************************************
-
-#define LOG 0
-
-
-
-//**************************************************************************
// DEVICE DEFINITIONS
//**************************************************************************
@@ -36,7 +28,7 @@ DEFINE_DEVICE_TYPE(VIDEOBRAIN_EXPANSION_SLOT, videobrain_expansion_slot_device,
//-------------------------------------------------
device_videobrain_expansion_card_interface::device_videobrain_expansion_card_interface(const machine_config &mconfig, device_t &device) :
- device_slot_card_interface(mconfig, device),
+ device_interface(device, "vidbrainexp"),
m_rom_mask(0),
m_ram_mask(0)
{
@@ -45,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)
@@ -53,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;
}
@@ -70,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;
}
@@ -89,8 +79,8 @@ uint8_t* device_videobrain_expansion_card_interface::videobrain_ram_pointer(runn
videobrain_expansion_slot_device::videobrain_expansion_slot_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) :
device_t(mconfig, VIDEOBRAIN_EXPANSION_SLOT, tag, owner, clock),
- device_slot_interface(mconfig, *this),
- device_image_interface(mconfig, *this),
+ device_single_card_slot_interface<device_videobrain_expansion_card_interface>(mconfig, *this),
+ device_cartrom_image_interface(mconfig, *this),
m_write_extres(*this), m_cart(nullptr)
{
}
@@ -102,10 +92,7 @@ videobrain_expansion_slot_device::videobrain_expansion_slot_device(const machine
void videobrain_expansion_slot_device::device_start()
{
- m_cart = dynamic_cast<device_videobrain_expansion_card_interface *>(get_card_device());
-
- // resolve callbacks
- m_write_extres.resolve_safe();
+ m_cart = get_card_device();
}
@@ -113,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());
}
@@ -150,47 +137,21 @@ std::string videobrain_expansion_slot_device::get_default_card_software(get_defa
//-------------------------------------------------
-// bo_r - cartridge data read
-//-------------------------------------------------
-
-uint8_t videobrain_expansion_slot_device::bo_r(offs_t offset, int cs1, int cs2)
-{
- uint8_t data = 0;
-
- if (m_cart != nullptr)
- {
- data = m_cart->videobrain_bo_r(offset, cs1, cs2);
- }
-
- return data;
-}
-
-
-//-------------------------------------------------
-// bo_w - cartridge data write
-//-------------------------------------------------
-
-void videobrain_expansion_slot_device::bo_w(offs_t offset, uint8_t data, int cs1, int cs2)
-{
- if (m_cart != nullptr)
- {
- m_cart->videobrain_bo_w(offset, data, cs1, cs2);
- }
-}
-
-
-//-------------------------------------------------
// SLOT_INTERFACE_START( vidbrain_expansion_cards )
//-------------------------------------------------
// 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 e841df6c32c..de7737eb8f0 100644
--- a/src/devices/bus/vidbrain/exp.h
+++ b/src/devices/bus/vidbrain/exp.h
@@ -39,14 +39,7 @@
#pragma once
-#include "softlist_dev.h"
-
-
-//**************************************************************************
-// CONSTANTS
-//**************************************************************************
-
-#define VIDEOBRAIN_EXPANSION_SLOT_TAG "exp"
+#include "imagedev/cartrom.h"
//**************************************************************************
@@ -57,7 +50,7 @@ class videobrain_expansion_slot_device;
// ======================> device_videobrain_expansion_card_interface
-class device_videobrain_expansion_card_interface : public device_slot_card_interface
+class device_videobrain_expansion_card_interface : public device_interface
{
friend class videobrain_expansion_slot_device;
@@ -90,14 +83,14 @@ protected:
// ======================> videobrain_expansion_slot_device
class videobrain_expansion_slot_device : public device_t,
- public device_slot_interface,
- public device_image_interface
+ public device_single_card_slot_interface<device_videobrain_expansion_card_interface>,
+ public device_cartrom_image_interface
{
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,41 +102,34 @@ public:
auto extres_wr_callback() { return m_write_extres.bind(); }
// computer interface
- uint8_t bo_r(offs_t offset, int cs1, int cs2);
- void bo_w(offs_t offset, uint8_t data, int cs1, int cs2);
+ uint8_t bo_r(offs_t offset, int cs1, int cs2) { return m_cart ? m_cart->videobrain_bo_r(offset, cs1, cs2) : 0; }
+ void bo_w(offs_t offset, uint8_t data, int cs1, int cs2) { if (m_cart) m_cart->videobrain_bo_w(offset, data, cs1, cs2); }
uint8_t cs1_r(offs_t offset) { return bo_r(offset + 0x1000, 0, 1); }
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
- virtual void device_start() override;
-
- // image-level overrides
- virtual image_init_result call_load() override;
- virtual const software_list_loader &get_software_list_loader() const override { return rom_software_list_loader::instance(); }
+ // device_t implementation
+ virtual void device_start() override ATTR_COLD;
- virtual iodevice_t image_type() const override { return IO_CARTSLOT; }
+ // device_image_interface implementation
+ virtual std::pair<std::error_condition, std::string> call_load() override;
- virtual bool is_readable() const override { return 1; }
- virtual bool is_writeable() const override { return 0; }
- virtual bool is_creatable() const override { return 0; }
- virtual bool must_be_loaded() const override { return 0; }
- virtual bool is_reset_on_load() const override { return 1; }
- virtual const char *image_interface() const override { return "vidbrain_cart"; }
- virtual const char *file_extensions() const override { return "bin"; }
+ 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 7b908dad442..0826cab70ac 100644
--- a/src/devices/bus/vip/byteio.cpp
+++ b/src/devices/bus/vip/byteio.cpp
@@ -27,8 +27,8 @@ DEFINE_DEVICE_TYPE(VIP_BYTEIO_PORT, vip_byteio_port_device, "vip_byteio_port", "
// device_vip_byteio_port_interface - constructor
//-------------------------------------------------
-device_vip_byteio_port_interface::device_vip_byteio_port_interface(const machine_config &mconfig, device_t &device)
- : device_slot_card_interface(mconfig,device)
+device_vip_byteio_port_interface::device_vip_byteio_port_interface(const machine_config &mconfig, device_t &device) :
+ device_interface(device, "vipbyteio")
{
m_slot = dynamic_cast<vip_byteio_port_device *>(device.owner());
}
@@ -45,7 +45,7 @@ device_vip_byteio_port_interface::device_vip_byteio_port_interface(const machine
vip_byteio_port_device::vip_byteio_port_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) :
device_t(mconfig, VIP_BYTEIO_PORT, tag, owner, clock),
- device_slot_interface(mconfig, *this),
+ device_single_card_slot_interface<device_vip_byteio_port_interface>(mconfig, *this),
m_write_inst(*this),
m_cart(nullptr)
{
@@ -57,10 +57,7 @@ vip_byteio_port_device::vip_byteio_port_device(const machine_config &mconfig, co
void vip_byteio_port_device::device_start()
{
- m_cart = dynamic_cast<device_vip_byteio_port_interface *>(get_card_device());
-
- // resolve callbacks
- m_write_inst.resolve_safe();
+ m_cart = get_card_device();
}
@@ -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 f2b12ca49f2..851e66e8174 100644
--- a/src/devices/bus/vip/byteio.h
+++ b/src/devices/bus/vip/byteio.h
@@ -53,8 +53,7 @@
class device_vip_byteio_port_interface;
-class vip_byteio_port_device : public device_t,
- public device_slot_interface
+class vip_byteio_port_device : public device_t, public device_single_card_slot_interface<device_vip_byteio_port_interface>
{
public:
// construction/destruction
@@ -75,17 +74,17 @@ 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
- virtual void device_start() override;
- virtual void device_reset() override;
+ virtual void device_start() override ATTR_COLD;
+ virtual void device_reset() override ATTR_COLD;
devcb_write_line m_write_inst;
@@ -96,7 +95,7 @@ protected:
// ======================> device_vip_byteio_port_interface
// class representing interface-specific live c64_expansion card
-class device_vip_byteio_port_interface : public device_slot_card_interface
+class device_vip_byteio_port_interface : public device_interface
{
public:
virtual uint8_t vip_in_r() { return 0xff; }
diff --git a/src/devices/bus/vip/exp.cpp b/src/devices/bus/vip/exp.cpp
index 132a4d753ef..16374ed7941 100644
--- a/src/devices/bus/vip/exp.cpp
+++ b/src/devices/bus/vip/exp.cpp
@@ -36,7 +36,7 @@ DEFINE_DEVICE_TYPE(VIP_EXPANSION_SLOT, vip_expansion_slot_device, "vip_expansion
//-------------------------------------------------
device_vip_expansion_card_interface::device_vip_expansion_card_interface(const machine_config &mconfig, device_t &device)
- : device_slot_card_interface(mconfig, device)
+ : device_interface(device, "vipexp")
{
m_slot = dynamic_cast<vip_expansion_slot_device *>(device.owner());
}
@@ -53,7 +53,7 @@ device_vip_expansion_card_interface::device_vip_expansion_card_interface(const m
vip_expansion_slot_device::vip_expansion_slot_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) :
device_t(mconfig, VIP_EXPANSION_SLOT, tag, owner, clock),
- device_slot_interface(mconfig, *this),
+ device_single_card_slot_interface<device_vip_expansion_card_interface>(mconfig, *this),
m_write_int(*this),
m_write_dma_out(*this),
m_write_dma_in(*this), m_card(nullptr)
@@ -67,12 +67,7 @@ vip_expansion_slot_device::vip_expansion_slot_device(const machine_config &mconf
void vip_expansion_slot_device::device_start()
{
- m_card = dynamic_cast<device_vip_expansion_card_interface *>(get_card_device());
-
- // resolve callbacks
- m_write_int.resolve_safe();
- m_write_dma_out.resolve_safe();
- m_write_dma_in.resolve_safe();
+ m_card = get_card_device();
}
@@ -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 9073dafee0d..4f1c7cc4264 100644
--- a/src/devices/bus/vip/exp.h
+++ b/src/devices/bus/vip/exp.h
@@ -40,13 +40,6 @@
//**************************************************************************
-// CONSTANTS
-//**************************************************************************
-
-#define VIP_EXPANSION_SLOT_TAG "exp"
-
-
-//**************************************************************************
// TYPE DEFINITIONS
//**************************************************************************
@@ -54,8 +47,7 @@
class device_vip_expansion_card_interface;
-class vip_expansion_slot_device : public device_t,
- public device_slot_interface
+class vip_expansion_slot_device : public device_t, public device_single_card_slot_interface<device_vip_expansion_card_interface>
{
public:
// construction/destruction
@@ -82,22 +74,22 @@ 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
- virtual void device_start() override;
+ virtual void device_start() override ATTR_COLD;
devcb_write_line m_write_int;
devcb_write_line m_write_dma_out;
@@ -109,7 +101,7 @@ protected:
// ======================> device_vip_expansion_card_interface
-class device_vip_expansion_card_interface : public device_slot_card_interface
+class device_vip_expansion_card_interface : public device_interface
{
friend class vip_expansion_slot_device;
diff --git a/src/devices/bus/vip/vp550.cpp b/src/devices/bus/vip/vp550.cpp
index 6d1e36f57d7..4fc501154da 100644
--- a/src/devices/bus/vip/vp550.cpp
+++ b/src/devices/bus/vip/vp550.cpp
@@ -4,40 +4,18 @@
RCA VIP Super Sound System VP550 emulation
-**********************************************************************/
-
-/*
-
- TODO:
+ TODO: Implement VP551 variant
- - VP551
-
-*/
+**********************************************************************/
#include "emu.h"
#include "vp550.h"
-
#include "speaker.h"
+#define VERBOSE (0)
+#include "logmacro.h"
-//**************************************************************************
-// MACROS / CONSTANTS
-//**************************************************************************
-
-#define LOG 0
-
-
-#define CDP1863_A_TAG "u1"
-#define CDP1863_B_TAG "u2"
-
-
-enum
-{
- CHANNEL_A = 0,
- CHANNEL_B
-};
-
//**************************************************************************
// DEVICE DEFINITIONS
@@ -47,20 +25,20 @@ DEFINE_DEVICE_TYPE(VP550, vp550_device, "vp550", "VP-550 Super Sound")
//-------------------------------------------------
-// machine_config( vp550 )
+// device_add_mconfig
//-------------------------------------------------
void vp550_device::device_add_mconfig(machine_config &config)
{
SPEAKER(config, "mono").front_center();
- CDP1863(config, m_pfg_a, 0);
- m_pfg_a->set_clock2(0);
- m_pfg_a->add_route(ALL_OUTPUTS, "mono", 1.0);
+ CDP1863(config, m_pfg[0], 0);
+ m_pfg[0]->set_clock2(0);
+ m_pfg[0]->add_route(ALL_OUTPUTS, "mono", 1.0);
- CDP1863(config, m_pfg_b, 0);
- m_pfg_b->set_clock2(0);
- m_pfg_b->add_route(ALL_OUTPUTS, "mono", 1.0);
+ CDP1863(config, m_pfg[1], 0);
+ m_pfg[1]->set_clock2(0);
+ m_pfg[1]->add_route(ALL_OUTPUTS, "mono", 1.0);
}
@@ -76,8 +54,7 @@ void vp550_device::device_add_mconfig(machine_config &config)
vp550_device::vp550_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) :
device_t(mconfig, VP550, tag, owner, clock),
device_vip_expansion_card_interface(mconfig, *this),
- m_pfg_a(*this, CDP1863_A_TAG),
- m_pfg_b(*this, CDP1863_B_TAG),
+ m_pfg(*this, "u%u", 1U),
m_sync_timer(nullptr)
{
}
@@ -90,19 +67,19 @@ vp550_device::vp550_device(const machine_config &mconfig, const char *tag, devic
void vp550_device::device_start()
{
// allocate timers
- m_sync_timer = timer_alloc();
+ m_sync_timer = timer_alloc(FUNC(vp550_device::sync_tick), this);
m_sync_timer->adjust(attotime::from_hz(50), 0, attotime::from_hz(50));
m_sync_timer->enable(0);
}
//-------------------------------------------------
-// device_timer - handler timer events
+// sync_timer - fire an interrupt on host
//-------------------------------------------------
-void vp550_device::device_timer(emu_timer &timer, device_timer_id id, int param, void *ptr)
+TIMER_CALLBACK_MEMBER(vp550_device::sync_tick)
{
- if (LOG) logerror("VP550 '%s' Interrupt\n", tag());
+ LOG("VP550 '%s' Interrupt\n", tag());
m_slot->interrupt_w(ASSERT_LINE);
}
@@ -120,8 +97,8 @@ void vp550_device::vip_program_w(offs_t offset, uint8_t data, int cdef, int *min
switch (offset & 0x03)
{
- case 1: m_pfg_a->write_str(data); break;
- case 2: m_pfg_b->write_str(data); break;
+ case 1: m_pfg[0]->str_w(data); break;
+ case 2: m_pfg[1]->str_w(data); break;
case 3: octave_w(data); break;
}
@@ -143,7 +120,7 @@ void vp550_device::vip_sc_w(int n, int sc)
{
if (BIT(sc, 1))
{
- if (LOG) logerror("VP550 '%s' Clear Interrupt\n", tag());
+ LOG("VP550 '%s' Clear Interrupt\n", tag());
m_slot->interrupt_w(CLEAR_LINE);
}
@@ -156,8 +133,8 @@ void vp550_device::vip_sc_w(int n, int sc)
void vp550_device::vip_q_w(int state)
{
- m_pfg_a->oe_w(state);
- m_pfg_b->oe_w(state);
+ m_pfg[0]->oe_w(state);
+ m_pfg[1]->oe_w(state);
}
@@ -169,8 +146,8 @@ void vp550_device::vip_run_w(int state)
{
if (!state)
{
- m_pfg_a->reset();
- m_pfg_b->reset();
+ m_pfg[0]->reset();
+ m_pfg[1]->reset();
}
}
@@ -184,24 +161,14 @@ void vp550_device::octave_w(uint8_t data)
int channel = (data >> 2) & 0x03;
int clock2 = 0;
- if (data & 0x10)
+ if (BIT(data, 4))
{
- switch (data & 0x03)
- {
- case 0: clock2 = m_slot->clock() / 8; break;
- case 1: clock2 = m_slot->clock() / 4; break;
- case 2: clock2 = m_slot->clock() / 2; break;
- case 3: clock2 = m_slot->clock(); break;
- }
+ clock2 = m_slot->clock() >> (3 - (data & 0x03));
}
- switch (channel)
- {
- case CHANNEL_A: m_pfg_a->set_clk2(clock2); break;
- case CHANNEL_B: m_pfg_b->set_clk2(clock2); break;
- }
+ m_pfg[BIT(data, 2)]->set_clk2(clock2);
- if (LOG) logerror("VP550 '%s' Clock %c: %u Hz\n", tag(), 'A' + channel, clock2);
+ LOG("VP550 '%s' Clock %c: %u Hz\n", tag(), 'A' + channel, clock2);
}
@@ -211,11 +178,10 @@ void vp550_device::octave_w(uint8_t data)
void vp550_device::vlmna_w(uint8_t data)
{
- if (LOG) logerror("VP550 '%s' A Volume: %u\n", tag(), data & 0x0f);
+ LOG("VP550 '%s' A Volume: %u\n", tag(), data & 0x0f);
- float gain = (data & 0x0f) * 0.0666;
-
- m_pfg_a->set_output_gain(0, gain);
+ float gain = (data & 0x0f) / 15.0f;
+ m_pfg[0]->set_output_gain(0, gain);
}
@@ -225,11 +191,10 @@ void vp550_device::vlmna_w(uint8_t data)
void vp550_device::vlmnb_w(uint8_t data)
{
- if (LOG) logerror("VP550 '%s' B Volume: %u\n", tag(), data & 0x0f);
-
- float gain = (data & 0x0f) * 0.0666;
+ LOG("VP550 '%s' B Volume: %u\n", tag(), data & 0x0f);
- m_pfg_b->set_output_gain(0, gain);
+ float gain = (data & 0x0f) / 15.0f;
+ m_pfg[1]->set_output_gain(0, gain);
}
@@ -239,7 +204,7 @@ void vp550_device::vlmnb_w(uint8_t data)
void vp550_device::sync_w(uint8_t data)
{
- if (LOG) logerror("VP550 '%s' Interrupt Enable: %u\n", tag(), BIT(data, 0));
+ LOG("VP550 '%s' Interrupt Enable: %u\n", tag(), BIT(data, 0));
m_sync_timer->enable(BIT(data, 0));
}
diff --git a/src/devices/bus/vip/vp550.h b/src/devices/bus/vip/vp550.h
index d881063ba2c..85575490c7a 100644
--- a/src/devices/bus/vip/vp550.h
+++ b/src/devices/bus/vip/vp550.h
@@ -31,9 +31,8 @@ public:
protected:
// device-level overrides
- virtual void device_start() override;
- virtual void device_timer(emu_timer &timer, device_timer_id id, int param, void *ptr) override;
- virtual void device_add_mconfig(machine_config &config) override;
+ virtual void device_start() override ATTR_COLD;
+ virtual void device_add_mconfig(machine_config &config) override ATTR_COLD;
// device_vip_expansion_card_interface overrides
virtual void vip_program_w(offs_t offset, uint8_t data, int cdef, int *minh) override;
@@ -41,14 +40,15 @@ protected:
virtual void vip_q_w(int state) override;
virtual void vip_run_w(int state) override;
+ TIMER_CALLBACK_MEMBER(sync_tick);
+
private:
void octave_w(uint8_t data);
void vlmna_w(uint8_t data);
void vlmnb_w(uint8_t data);
void sync_w(uint8_t data);
- required_device<cdp1863_device> m_pfg_a;
- required_device<cdp1863_device> m_pfg_b;
+ required_device_array<cdp1863_device, 2> m_pfg;
// timers
emu_timer *m_sync_timer;
diff --git a/src/devices/bus/vip/vp570.cpp b/src/devices/bus/vip/vp570.cpp
index f9473bd2f87..f2e32dffd35 100644
--- a/src/devices/bus/vip/vp570.cpp
+++ b/src/devices/bus/vip/vp570.cpp
@@ -63,7 +63,7 @@ ioport_constructor vp570_device::device_input_ports() const
vp570_device::vp570_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) :
device_t(mconfig, VP570, tag, owner, clock),
device_vip_expansion_card_interface(mconfig, *this),
- m_ram(*this, "ram"),
+ m_ram(*this, "ram", 0x1000, ENDIANNESS_LITTLE),
m_base(*this, "BASE"),
m_sw1(*this, "SW1")
{
@@ -76,7 +76,6 @@ vp570_device::vp570_device(const machine_config &mconfig, const char *tag, devic
void vp570_device::device_start()
{
- m_ram.allocate(0x1000);
}
diff --git a/src/devices/bus/vip/vp570.h b/src/devices/bus/vip/vp570.h
index 04ad752d804..58575193d6a 100644
--- a/src/devices/bus/vip/vp570.h
+++ b/src/devices/bus/vip/vp570.h
@@ -29,18 +29,18 @@ public:
vp570_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;
+ virtual ioport_constructor device_input_ports() const override ATTR_COLD;
protected:
// device-level overrides
- virtual void device_start() override;
+ virtual void device_start() override ATTR_COLD;
// device_vip_expansion_card_interface overrides
virtual uint8_t vip_program_r(offs_t offset, int cs, int cdef, int *minh) override;
virtual void vip_program_w(offs_t offset, uint8_t data, int cdef, int *minh) override;
private:
- optional_shared_ptr<uint8_t> m_ram;
+ memory_share_creator<uint8_t> m_ram;
required_ioport m_base;
required_ioport m_sw1;
};
diff --git a/src/devices/bus/vip/vp575.h b/src/devices/bus/vip/vp575.h
index fb5c22f5628..8ab057db789 100644
--- a/src/devices/bus/vip/vp575.h
+++ b/src/devices/bus/vip/vp575.h
@@ -30,8 +30,8 @@ public:
protected:
// device-level overrides
- virtual void device_start() override;
- virtual void device_add_mconfig(machine_config &config) override;
+ virtual void device_start() override ATTR_COLD;
+ virtual void device_add_mconfig(machine_config &config) override ATTR_COLD;
// device_vip_expansion_card_interface overrides
virtual uint8_t vip_program_r(offs_t offset, int cs, int cdef, int *minh) override;
@@ -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/vp585.h b/src/devices/bus/vip/vp585.h
index f32bf055e91..bbfd52ae69d 100644
--- a/src/devices/bus/vip/vp585.h
+++ b/src/devices/bus/vip/vp585.h
@@ -29,11 +29,11 @@ public:
vp585_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;
+ virtual ioport_constructor device_input_ports() const override ATTR_COLD;
protected:
// device-level overrides
- virtual void device_start() override;
+ virtual void device_start() override ATTR_COLD;
// device_vip_expansion_card_interface overrides
virtual void vip_io_w(offs_t offset, uint8_t data) override;
diff --git a/src/devices/bus/vip/vp590.cpp b/src/devices/bus/vip/vp590.cpp
index 3fd9185c5d1..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);
}
@@ -131,7 +131,7 @@ vp590_device::vp590_device(const machine_config &mconfig, const char *tag, devic
device_t(mconfig, VP590, tag, owner, clock),
device_vip_expansion_card_interface(mconfig, *this),
m_cgc(*this, CDP1862_TAG),
- m_color_ram(*this, "color_ram"),
+ m_color_ram(*this, "color_ram", COLOR_RAM_SIZE, ENDIANNESS_LITTLE),
m_j1(*this, "J1"),
m_j2(*this, "J2"),
m_a12(0), m_color(0), m_keylatch(0)
@@ -145,9 +145,6 @@ vp590_device::vp590_device(const machine_config &mconfig, const char *tag, devic
void vp590_device::device_start()
{
- // allocate memory
- m_color_ram.allocate(COLOR_RAM_SIZE);
-
// state saving
save_item(NAME(m_a12));
save_item(NAME(m_color));
diff --git a/src/devices/bus/vip/vp590.h b/src/devices/bus/vip/vp590.h
index 230b7d8d02d..a272d190c42 100644
--- a/src/devices/bus/vip/vp590.h
+++ b/src/devices/bus/vip/vp590.h
@@ -32,9 +32,9 @@ public:
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 void device_start() override ATTR_COLD;
+ virtual void device_add_mconfig(machine_config &config) override ATTR_COLD;
+ virtual ioport_constructor device_input_ports() const override ATTR_COLD;
// device_vip_expansion_card_interface overrides
virtual void vip_program_w(offs_t offset, uint8_t data, int cdef, int *minh) override;
@@ -45,12 +45,12 @@ 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;
- optional_shared_ptr<uint8_t> m_color_ram;
+ memory_share_creator<uint8_t> m_color_ram;
required_ioport m_j1;
required_ioport m_j2;
diff --git a/src/devices/bus/vip/vp595.cpp b/src/devices/bus/vip/vp595.cpp
index 1dab7f4a49f..670b0926f90 100644
--- a/src/devices/bus/vip/vp595.cpp
+++ b/src/devices/bus/vip/vp595.cpp
@@ -79,7 +79,7 @@ void vp595_device::vip_io_w(offs_t offset, uint8_t data)
{
if (!data) data = 0x80;
- m_pfg->write_str(data);
+ m_pfg->str_w(data);
}
}
diff --git a/src/devices/bus/vip/vp595.h b/src/devices/bus/vip/vp595.h
index 5c98b33fe7c..7b7d3890816 100644
--- a/src/devices/bus/vip/vp595.h
+++ b/src/devices/bus/vip/vp595.h
@@ -31,8 +31,8 @@ public:
protected:
// device-level overrides
- virtual void device_start() override;
- virtual void device_add_mconfig(machine_config &config) override;
+ virtual void device_start() override ATTR_COLD;
+ virtual void device_add_mconfig(machine_config &config) override ATTR_COLD;
// device_vip_expansion_card_interface overrides
virtual void vip_io_w(offs_t offset, uint8_t data) override;
diff --git a/src/devices/bus/vip/vp620.h b/src/devices/bus/vip/vp620.h
index 3541db5d8e5..10389bd0bba 100644
--- a/src/devices/bus/vip/vp620.h
+++ b/src/devices/bus/vip/vp620.h
@@ -31,8 +31,8 @@ public:
protected:
// device-level overrides
- virtual void device_start() override;
- virtual void device_add_mconfig(machine_config &config) override;
+ virtual void device_start() override ATTR_COLD;
+ virtual void device_add_mconfig(machine_config &config) override ATTR_COLD;
// device_vip_byteio_port_interface overrides
virtual uint8_t vip_in_r() override;
diff --git a/src/devices/bus/vip/vp700.h b/src/devices/bus/vip/vp700.h
index 4927005742e..9bb34a20f74 100644
--- a/src/devices/bus/vip/vp700.h
+++ b/src/devices/bus/vip/vp700.h
@@ -30,11 +30,11 @@ public:
vp700_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 const tiny_rom_entry *device_rom_region() const override ATTR_COLD;
protected:
// device-level overrides
- virtual void device_start() override;
+ virtual void device_start() override ATTR_COLD;
// device_vip_expansion_card_interface overrides
virtual uint8_t vip_program_r(offs_t offset, int cs, int cdef, int *minh) override;
diff --git a/src/devices/bus/vme/cp31.cpp b/src/devices/bus/vme/cp31.cpp
new file mode 100644
index 00000000000..14b739713fe
--- /dev/null
+++ b/src/devices/bus/vme/cp31.cpp
@@ -0,0 +1,315 @@
+// license:BSD-3-Clause
+// copyright-holders:Sergey Svishchev
+
+/*
+ * Besta CP31 board, possibly a customized version of Force CPU30.
+ *
+ * Supported by SysV R3 "Bestix" port and also by Linux port,
+ * see https://github.com/shattered/linux-m68k
+ *
+ * Chips:
+ *
+ * 68030 @ 25 MHz - CPU
+ * 68882 @ 25 MHz - FPU
+ * 68561 - MPCC (serial port)
+ * 68230 - PI/T (parallel interface and timer)
+ * 68153 - BIM (interrupt router)
+ * 62421 - RTC
+ *
+ * To do:
+ *
+ * - pass functional test
+ * - boot to multiuser (SysV and Linux) (requires ISCSI-1)
+ *
+ */
+
+#include "emu.h"
+
+#include "cp31.h"
+
+
+#define LOG_INT (1U << 1)
+
+#define VERBOSE (0) // (LOG_GENERAL | LOG_INT)
+//#define LOG_OUTPUT_FUNC printf
+#include "logmacro.h"
+
+#define LOGINT(...) LOGMASKED(LOG_INT, __VA_ARGS__)
+
+
+#ifdef _MSC_VER
+#define FUNCNAME __func__
+#else
+#define FUNCNAME __PRETTY_FUNCTION__
+#endif
+
+
+#define CLOCK50 XTAL(50'000'000) /* HCJ */
+#define CLOCK40 XTAL(40'000'000) /* HCJ */
+#define CLOCK32 XTAL(32'000'000) /* HCJ */
+
+#define RS232P1_TAG "rs232p1"
+
+
+//**************************************************************************
+// GLOBAL VARIABLES
+//**************************************************************************
+
+DEFINE_DEVICE_TYPE(VME_CP31, vme_cp31_card_device, "cp31", "Besta CP31 CPU board")
+
+void vme_cp31_card_device::cp31_mem(address_map &map)
+{
+ map.unmap_value_high();
+ map(0x00000000, 0x001fffff).ram().share("dram"); // local bus DRAM, 4 MB
+// map(0x08010000, 0x08011fff).ram(); // unknown -- accessed by cp31dssp
+// map(0xfca03500, 0xfca0350f).unmaprw(); // ISCSI-1 board on VME bus
+ map(0xff000000, 0xff03ffff).rom().region("user1", 0);
+ map(0xff040000, 0xff07ffff).ram(); // onboard SRAM
+ map(0xff800000, 0xff80001f).rw(m_mpcc, FUNC(mpcc68561_device::read), FUNC(mpcc68561_device::write));
+ map(0xff800200, 0xff8003ff).rw(m_pit2, FUNC(pit68230_device::read), FUNC(pit68230_device::write));
+ map(0xff800800, 0xff80080f).rw(m_bim, FUNC(bim68153_device::read), FUNC(bim68153_device::write)).umask32(0xff00ff00);
+ map(0xff800a00, 0xff800a1f).rw(m_rtc, FUNC(rtc62421_device::read), FUNC(rtc62421_device::write));
+ map(0xff800c00, 0xff800dff).rw(m_pit1, FUNC(pit68230_device::read), FUNC(pit68230_device::write));
+// map(0xff800400, 0xff800xxx) // TIC? -- shows up in cp31dssp log
+// map(0xff800e00, 0xff800xxx) // PIT3?
+}
+
+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
+
+// FIXME unverified
+static INPUT_PORTS_START(cp31)
+ PORT_START("SA1")
+ PORT_DIPNAME(0x01, 0x00, "Clear macros on reset")
+ PORT_DIPSETTING(0x00, "On")
+ PORT_DIPSETTING(0x01, "Off")
+ PORT_DIPNAME(0x02, 0x00, "VME bus width")
+ PORT_DIPSETTING(0x00, "16 bits")
+ PORT_DIPSETTING(0x02, "32 bits")
+ PORT_DIPNAME(0x0c, 0x0c, "Boot into...")
+ PORT_DIPSETTING(0x00, "UNIX")
+ PORT_DIPSETTING(0x0c, "Monitor")
+ PORT_DIPNAME(0x10, 0x10, "Console port setup")
+ PORT_DIPSETTING(0x00, "Custom")
+ PORT_DIPSETTING(0x10, "Standard")
+ PORT_DIPNAME(0x20, 0x20, "Console port bits")
+ PORT_DIPSETTING(0x00, "7N1")
+ PORT_DIPSETTING(0x20, "8N2")
+ PORT_DIPNAME(0xc0, 0xc0, "Console port speed")
+ PORT_DIPSETTING(0xc0, "9600")
+ PORT_DIPSETTING(0x80, "4800")
+ PORT_DIPSETTING(0x40, "2400")
+ PORT_DIPSETTING(0x00, "1200")
+INPUT_PORTS_END
+
+ROM_START(cp31)
+ ROM_REGION32_BE(0x40000, "user1", ROMREGION_ERASEFF)
+
+ ROM_DEFAULT_BIOS("cp31dssp")
+ ROM_SYSTEM_BIOS(0, "cp31dbg", "CP31 Debug")
+ ROMX_LOAD( "cp31dbgboot.27c512", 0x0000, 0x10000, CRC(9bf057de) SHA1(b13cb16042e4c6ca63ae26058a78259c0849d0b6), ROM_BIOS(0))
+ ROM_SYSTEM_BIOS(1, "cp31dssp", "CP31 DSSP")
+ ROMX_LOAD( "cp31dsspboot.27c512", 0x0000, 0x10000, CRC(607a0a55) SHA1(c257a88672ab39d2f3fad681d22e062182b0236d), ROM_BIOS(1))
+ ROM_SYSTEM_BIOS(2, "cp31os9", "CP31 OS9")
+ ROMX_LOAD( "cp31os9.27c512", 0x0000, 0x10000, CRC(607a0a55) SHA1(c257a88672ab39d2f3fad681d22e062182b0236d), ROM_BIOS(2))
+ROM_END
+
+//-------------------------------------------------
+// rom_region - device-specific ROM region
+//-------------------------------------------------
+
+const tiny_rom_entry *vme_cp31_card_device::device_rom_region() const
+{
+ return ROM_NAME(cp31);
+}
+
+//-------------------------------------------------
+// input_ports - device-specific input ports
+//-------------------------------------------------
+
+ioport_constructor vme_cp31_card_device::device_input_ports() const
+{
+ return INPUT_PORTS_NAME(cp31);
+}
+
+
+void vme_cp31_card_device::cpu_space_map(address_map &map)
+{
+ map(0xfffffff2, 0xffffffff).lr16(NAME([this](offs_t offset) -> u16 { return m_bim->iack(offset+1); }));
+}
+
+
+//-------------------------------------------------
+// device_add_mconfig - add device configuration
+//-------------------------------------------------
+
+void vme_cp31_card_device::device_add_mconfig(machine_config &config)
+{
+ M68030(config, m_maincpu, CLOCK50 / 2);
+ m_maincpu->set_addrmap(AS_PROGRAM, &vme_cp31_card_device::cp31_mem);
+ m_maincpu->set_addrmap(m68000_base_device::AS_CPU_SPACE, &vme_cp31_card_device::cpu_space_map);
+
+ MC68153(config, m_bim, CLOCK32 / 8);
+ m_bim->out_int_callback().set(FUNC(vme_cp31_card_device::bim_irq_callback));
+
+ MPCC68561(config, m_mpcc, 1392000, 0, 0); // FIXME: XTAL unknown
+ m_mpcc->out_txd_cb().set(RS232P1_TAG, FUNC(rs232_port_device::write_txd));
+ m_mpcc->out_dtr_cb().set(RS232P1_TAG, FUNC(rs232_port_device::write_dtr));
+ m_mpcc->out_rts_cb().set(RS232P1_TAG, FUNC(rs232_port_device::write_rts));
+ m_mpcc->out_int_cb().set(m_bim, FUNC(bim68153_device::int1_w));
+
+ rs232_port_device &rs232p1(RS232_PORT(config, RS232P1_TAG, default_rs232_devices, "terminal"));
+ rs232p1.rxd_handler().set(m_mpcc, FUNC(mpcc68561_device::write_rx));
+ rs232p1.cts_handler().set(m_mpcc, FUNC(mpcc68561_device::cts_w));
+ rs232p1.set_option_device_input_defaults("terminal", DEVICE_INPUT_DEFAULTS_NAME(terminal));
+
+ RTC62421(config, m_rtc, 32.768_kHz_XTAL);
+ m_rtc->out_int_handler().set(m_pit1, FUNC(pit68230_device::h2_w));
+
+ // H1 is SYSFAIL and H3 is ACFAIL
+ PIT68230(config, m_pit1, 8064000); // via c33_txt
+ m_pit1->pa_in_callback().set_ioport("SA1");
+ m_pit1->pb_out_callback().set(*this, FUNC(vme_cp31_card_device::pit1_pb_w));
+ m_pit1->pc_in_callback().set(*this, FUNC(vme_cp31_card_device::pit1_pc_r));
+// m_pit1->pc_out_callback().set(*this, FUNC(vme_cp31_card_device::pit1_pc_w));
+ m_pit1->timer_irq_callback().set(m_bim, FUNC(bim68153_device::int2_w));
+ m_pit1->port_irq_callback().set(m_bim, FUNC(bim68153_device::int3_w));
+
+ PIT68230(config, m_pit2, 8064000); // via c33_txt
+ m_pit2->port_irq_callback().set(m_pit1, FUNC(pit68230_device::h4_w));
+}
+
+uint32_t vme_cp31_card_device::trap_r(offs_t offset, uint32_t mem_mask)
+{
+ if (!machine().side_effects_disabled()) set_bus_error((offset << 2), true, mem_mask);
+
+ return 0xffffffff;
+}
+
+void vme_cp31_card_device::bim_irq_callback(int state)
+{
+ LOGINT("%s(%02x)\n", FUNCNAME, state);
+
+ bim_irq_state = state;
+ bim_irq_level = m_bim->get_irq_level();
+ LOGINT(" - BIM irq level %s\n", bim_irq_level == CLEAR_LINE ? "Cleared" : "Asserted");
+ update_irq_to_maincpu();
+}
+
+// TODO: IRQ masking
+void vme_cp31_card_device::update_irq_to_maincpu()
+{
+ LOGINT("%s()\n", FUNCNAME);
+ LOGINT(" - bim_irq_level: %02x\n", bim_irq_level);
+ LOGINT(" - bim_irq_state: %02x\n", bim_irq_state);
+ switch (bim_irq_level & 0x07)
+ {
+ case 1: m_maincpu->set_input_line(M68K_IRQ_1, bim_irq_state); break;
+ case 2: m_maincpu->set_input_line(M68K_IRQ_2, bim_irq_state); break;
+ case 3: m_maincpu->set_input_line(M68K_IRQ_3, bim_irq_state); break;
+ case 4: m_maincpu->set_input_line(M68K_IRQ_4, bim_irq_state); break;
+ case 5: m_maincpu->set_input_line(M68K_IRQ_5, bim_irq_state); break;
+ case 6: m_maincpu->set_input_line(M68K_IRQ_6, bim_irq_state); break;
+ case 7: m_maincpu->set_input_line(M68K_IRQ_7, bim_irq_state); break;
+ default: logerror("Programmatic error in %s, please report\n", FUNCNAME);
+ }
+}
+
+
+void vme_cp31_card_device::trap_w(offs_t offset, uint32_t data, uint32_t mem_mask)
+{
+ LOG("%s(%08x,%08X)\n", FUNCNAME, offset << 2, data);
+ if (!machine().side_effects_disabled()) set_bus_error((offset << 2), false, mem_mask);
+}
+
+// PC4 - IRQ7 state, PC6 - FPCP SENSE (0 = FPCP installed)
+uint8_t vme_cp31_card_device::pit1_pc_r()
+{
+ uint8_t data = 0;
+
+ LOG("%s(%02X)\n", FUNCNAME, data);
+
+ return data;
+}
+
+// IRQ masking
+void vme_cp31_card_device::pit1_pb_w(uint8_t data)
+{
+ LOG("%s(%02X)\n", FUNCNAME, data);
+}
+
+void vme_cp31_card_device::set_bus_error(uint32_t address, bool rw, uint32_t mem_mask)
+{
+ if (m_bus_error)
+ {
+ return;
+ }
+ LOG("bus error at %08x & %08x (%s)\n", address, mem_mask, rw ? "read" : "write");
+ if (!ACCESSING_BITS_16_31)
+ {
+ address++;
+ }
+ m_bus_error = true;
+ m_maincpu->set_buserror_details(address, rw, m_maincpu->get_fc());
+ m_maincpu->set_input_line(M68K_LINE_BUSERROR, ASSERT_LINE);
+ m_bus_error_timer->adjust(m_maincpu->cycles_to_attotime(16)); // let rmw cycles complete
+}
+
+vme_cp31_card_device::vme_cp31_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_bim(*this, "bim")
+ , m_mpcc(*this, "mpcc")
+ , m_rtc(*this, "rtc")
+ , m_pit1(*this, "pit1")
+ , m_pit2(*this, "pit2")
+ , m_p_ram(*this, "dram")
+ , m_sysrom(*this, "user1")
+{
+}
+
+//
+
+vme_cp31_card_device::vme_cp31_card_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
+ : vme_cp31_card_device(mconfig, VME_CP31, tag, owner, clock)
+{
+}
+
+void vme_cp31_card_device::device_start()
+{
+ m_bus_error_timer = timer_alloc(FUNC(vme_cp31_card_device::bus_error_off), this);
+}
+
+void vme_cp31_card_device::device_reset()
+{
+ address_space &program = m_maincpu->space(AS_PROGRAM);
+
+ program.install_rom(0x00000000, 0x00000007, m_sysrom); // do it here for F3
+ m_rom_shadow_tap.remove();
+ m_rom_shadow_tap = program.install_read_tap(
+ 0xff000000, 0xff007fff,
+ "rom_shadow_r",
+ [this] (offs_t offset, u32 &data, u32 mem_mask)
+ {
+ if (!machine().side_effects_disabled())
+ {
+ // delete this tap
+ m_rom_shadow_tap.remove();
+
+ // reinstall RAM over the ROM shadow
+ m_maincpu->space(AS_PROGRAM).install_ram(0x00000000, 0x00000007, m_p_ram);
+ }
+ },
+ &m_rom_shadow_tap);
+}
+
+TIMER_CALLBACK_MEMBER(vme_cp31_card_device::bus_error_off)
+{
+ m_bus_error = false;
+}
diff --git a/src/devices/bus/vme/cp31.h b/src/devices/bus/vme/cp31.h
new file mode 100644
index 00000000000..8344b24a166
--- /dev/null
+++ b/src/devices/bus/vme/cp31.h
@@ -0,0 +1,72 @@
+// license:BSD-3-Clause
+// copyright-holders:Sergey Svishchev
+#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/m68030.h"
+#include "machine/68153bim.h"
+#include "machine/68230pit.h"
+#include "machine/68561mpcc.h"
+#include "machine/clock.h"
+#include "machine/msm6242.h"
+
+DECLARE_DEVICE_TYPE(VME_CP31, vme_cp31_card_device)
+
+class vme_cp31_card_device : public device_t, public device_vme_card_interface
+{
+public:
+ vme_cp31_card_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
+
+protected:
+ vme_cp31_card_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock);
+
+ virtual void device_start() override ATTR_COLD;
+ virtual void device_reset() override ATTR_COLD;
+
+ // optional information overrides
+ virtual void device_add_mconfig(machine_config &config) override ATTR_COLD;
+ virtual const tiny_rom_entry *device_rom_region() const override ATTR_COLD;
+ virtual ioport_constructor device_input_ports() const override ATTR_COLD;
+
+ TIMER_CALLBACK_MEMBER(bus_error_off);
+
+private:
+ 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;
+ required_device<pit68230_device> m_pit1;
+ required_device<pit68230_device> m_pit2;
+ required_shared_ptr<uint32_t> m_p_ram;
+ required_region_ptr<uint32_t> m_sysrom;
+
+ // Pointer to System ROMs needed by bootvect_r and masking RAM buffer for post reset accesses
+ memory_passthrough_handler m_rom_shadow_tap;
+ bool m_bus_error;
+ emu_timer *m_bus_error_timer;
+
+ uint8_t bim_irq_state;
+ int bim_irq_level;
+
+ void bim_irq_callback(int state);
+ void update_irq_to_maincpu();
+
+ void pit1_pb_w(uint8_t data);
+ uint8_t pit1_pc_r();
+ void pit1_pc_w(uint8_t data);
+
+ uint32_t trap_r(offs_t offset, uint32_t mem_mask);
+ void trap_w(offs_t offset, uint32_t data, uint32_t mem_mask = ~0);
+
+ void set_bus_error(uint32_t address, bool write, uint32_t mem_mask);
+
+ void cp31_mem(address_map &map) ATTR_COLD;
+ void cpu_space_map(address_map &map) ATTR_COLD;
+};
+
+#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..42a32a60654
--- /dev/null
+++ b/src/devices/bus/vme/enp10.cpp
@@ -0,0 +1,416 @@
+// license:BSD-3-Clause
+// copyright-holders:Patrick Mackinlay
+
+/*
+ * Communication Machinery Corporation Ethernet Node Processor (ENP-10)
+ *
+ * Rebadged/resold by Motorola as the MVME330 Ethernet Controller, and also
+ * by Silicon Graphics as part 013-0204-00[123].
+ *
+ * Firmware expects to find a UART at address 0xef'8010-0xef'802f, which was
+ * apparently provided by a Mizar VME8300 card.
+ *
+ * Sources:
+ * - Ethernet Node Processor ENP-30 Reference Guide (6213000-05B), Communication Machinery Corporation, November 15, 1988
+ * - MVME330 Ethernet Controller User's Manual (MVME330/D2), Motorola, Second Edition, 1988
+ *
+ * TODO:
+ * - remaining control register flags
+ * - configurable interrupts
+ * - MVME330 -1 and -2 variants
+ */
+
+#include "emu.h"
+#include "enp10.h"
+
+//#define VERBOSE (LOG_GENERAL)
+#include "logmacro.h"
+
+DEFINE_DEVICE_TYPE(VME_ENP10, vme_enp10_card_device, "enp10", "CMC ENP-10")
+
+enum csr_mask : u8
+{
+ CSR_SUSPEND = 0x08, // set by lance dma
+ CSR_TIMER = 0x10, // set by 2ms timer
+ CSR_RESET = 0x20, // assert vme reset
+ CSR_FAIL = 0x40,
+ CSR_VIRQ = 0x80,
+};
+enum obr_mask : u8
+{
+ OBR_IE = 0x01, // interrupt enable
+ OBR_TI = 0x02, // transmit interrupt
+ OBR_RI = 0x04, // receive interrupt
+ OBR_UI = 0x08, // utility interrupt
+ OBR_RE = 0x80, // RAM enable
+};
+enum exr_mask : u8
+{
+ EXR_RTO = 0x01, // resource time-out
+ EXR_PER = 0x02, // parity error
+ EXR_ABO = 0x04, // abort
+ EXR_ACLO = 0x08, // AC line voltage low
+};
+
+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(0x10000, "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_FILL(0x4000, 0xc000, 0xff)
+
+ 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))
+ ROM_FILL(0x4000, 0xc000, 0xff)
+
+ ROM_SYSTEM_BIOS(2, "mvme330", "MVME330")
+ ROMX_LOAD("knlrom10__v4.1-h.u4", 0x0000, 0x2000, CRC(b5f0a49b) SHA1(70e0d54c25a152503796fae8d7c5ffab6d625583), ROM_SKIP(1) | ROM_BIOS(2))
+ ROMX_LOAD("knlrom10__v4.1-l.u3", 0x0001, 0x2000, CRC(78d8ae1b) SHA1(c69a8fa2edec7d6faadb48591ce252ac45b55cad), ROM_SKIP(1) | ROM_BIOS(2))
+ ROM_FILL(0x4000, 0xc000, 0xff)
+
+ // this firmware requires 512KiB RAM
+ ROM_SYSTEM_BIOS(3, "mvme330_1", "MVME330-1")
+ ROMX_LOAD("u_rev-99592-616335-2.u4", 0x0000, 0x8000, CRC(88527c5e) SHA1(b953d99d5eb3462c41202f64f560fae592e269fa), ROM_SKIP(1) | ROM_BIOS(3))
+ ROM_CONTINUE(0x0000, 0x8000) // first 32K is 0xff
+ ROMX_LOAD("u_rev-99592-616335-1.u3", 0x0001, 0x8000, CRC(0d8e5aa4) SHA1(f4b165581c5840e0607bd979c297d3e5ee77cb0f), ROM_SKIP(1) | ROM_BIOS(3))
+ ROM_CONTINUE(0x0001, 0x8000) // first 32K is 0xff
+
+ // 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_obr));
+ save_item(NAME(m_exr));
+
+ save_item(NAME(m_bint));
+ save_item(NAME(m_lint));
+ save_item(NAME(m_int_state));
+
+ m_bint = false;
+ m_lint = false;
+ m_int_state = 0;
+}
+
+void vme_enp10_card_device::device_reset()
+{
+ m_boot.select(0);
+
+ m_ivr = 0;
+ m_csr = CSR_FAIL | CSR_RESET;
+ m_obr = 0;
+ m_exr = 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);
+
+ interrupt();
+}
+
+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);
+ m_cpu->set_addrmap(m68000_base_device::AS_CPU_SPACE, &vme_enp10_card_device::cpu_ack);
+
+ AM7990(config, m_net, 20_MHz_XTAL / 2);
+ m_net->intr_out().set(
+ [this](int state)
+ {
+ m_lint = !state;
+
+ interrupt();
+ });
+ 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); });
+
+ TIMER(config, "timer").configure_periodic(FUNC(vme_enp10_card_device::timer), attotime::from_msec(2));
+
+ vme_iack().set(FUNC(vme_enp10_card_device::iack_r));
+ vme_berr().set(
+ [this](int state)
+ {
+ m_exr |= EXR_RTO;
+
+ m_cpu->trigger_bus_error();
+ });
+}
+
+void vme_enp10_card_device::cpu_map(address_map &map)
+{
+ map(0x00'1000, 0xee'ffff).rw(FUNC(vme_enp10_card_device::vme_a24_r), FUNC(vme_enp10_card_device::vme_a24_w));
+ map(0xef'0000, 0xef'ffff).rw(FUNC(vme_enp10_card_device::vme_a16_r), FUNC(vme_enp10_card_device::vme_a16_w));
+
+ map(0xf0'0000, 0xf1'ffff).ram().share("ram");
+ map(0xf8'0000, 0xf8'ffff).rom().region("eprom", 0).mirror(0x02'0000);
+
+ map(0x00'0000, 0xf1'ffff).view(m_boot);
+ // map first 4k of eprom at 0x00'0000
+ m_boot[0](0x00'0000, 0x00'0fff).rom().region("eprom", 0);
+
+ // map first 4k 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();
+
+ map(0xfe'0080, 0xfe'0081).mirror(0x1e).umask16(0x00ff).rw(FUNC(vme_enp10_card_device::vect_r), FUNC(vme_enp10_card_device::vect_w));
+
+ map(0xfe'00a0, 0xfe'00a1).mirror(0x1e).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, 6); // run
+
+ // TODO: CSR_RESET
+ // TODO: CSR_SUSPEND
+ m_csr = (m_csr & (CSR_VIRQ | CSR_TIMER)) | (data & (CSR_FAIL | CSR_RESET));
+ }, "csr_w");
+
+ map(0xfe'00c0, 0xfe'00cf).mirror(0x10).umask16(0x00ff).rw(FUNC(vme_enp10_card_device::obr_r), FUNC(vme_enp10_card_device::obr_w));
+
+ map(0xfe'00e0, 0xfe'00ef).mirror(0x10).umask16(0x00ff).lrw8(
+ NAME([this]() { return m_exr; }),
+ NAME([this](u8 data)
+ {
+ if (m_exr)
+ LOG("exr_w 0x%02x (%s)\n", data, machine().describe_context());
+
+ m_exr = 0;
+ m_csr &= ~CSR_TIMER;
+
+ interrupt();
+ }));
+
+ map(0xfe'0200, 0xfe'0203).mirror(0x1fc).rw(m_net, FUNC(am7990_device::regs_r), FUNC(am7990_device::regs_w));
+ map(0xfe'0400, 0xfe'041f).mirror(0x3e0).rom().region("mac", 0);
+}
+
+void vme_enp10_card_device::vme_map(address_map &map)
+{
+ map(0x0'0000, 0x1'fdff).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'fe00, 0x1'feff).lw16(
+ [this](u16 data)
+ {
+ LOG("host interrupt (%s)\n", machine().describe_context());
+
+ m_bint = true;
+ interrupt();
+ }, "bint_w");
+
+ map(0x1'ff00, 0x1'ffff).lw16(
+ [this](u16 data)
+ {
+ LOG("host reset (%s)\n", machine().describe_context());
+ reset();
+ }, "reset_w");
+}
+
+u8 vme_enp10_card_device::vect_r()
+{
+ LOG("vect_r (%s)\n", machine().describe_context());
+
+ return m_base->read();
+}
+
+void vme_enp10_card_device::vect_w(u8 data)
+{
+ LOG("vect_w 0x%02x (%s)\n", data, machine().describe_context());
+
+ if (!(m_csr & CSR_VIRQ))
+ {
+ m_ivr = data;
+ m_csr |= CSR_VIRQ;
+
+ vme_irq_w<4>(0);
+ }
+}
+
+u8 vme_enp10_card_device::iack_r()
+{
+ if (m_csr & CSR_VIRQ)
+ {
+ vme_irq_w<4>(1);
+ m_csr &= ~CSR_VIRQ;
+ }
+
+ return m_ivr;
+}
+
+u8 vme_enp10_card_device::obr_r(offs_t offset)
+{
+ return (m_obr & (1U << offset)) ? 0x80 : 0;
+}
+
+void vme_enp10_card_device::obr_w(offs_t offset, u8 data)
+{
+ unsigned const state = BIT(data, 7);
+
+ if (BIT(m_obr, offset) != state)
+ {
+ //static char const *const reg[] = { "ier", "tir", "rir", "uir", "bit4", "bit5", "bit6", "mapr" };
+ //LOG("obr_w %s %u (%s)\n", reg[offset], state, machine().describe_context());
+
+ if (state)
+ m_obr |= 1U << offset;
+ else
+ m_obr &= ~(1U << offset);
+
+ if (offset < 4)
+ interrupt();
+ else if (offset == 7)
+ m_boot.select(state);
+ }
+}
+
+void vme_enp10_card_device::timer(timer_device &timer, s32 param)
+{
+ m_csr |= CSR_TIMER;
+
+ interrupt();
+}
+
+void vme_enp10_card_device::interrupt()
+{
+ u8 int_state = 0;
+
+ if (m_obr & OBR_IE)
+ {
+ // find highest priority asserted interrupt source
+ if ((m_csr & CSR_TIMER) || (m_exr & (EXR_ACLO | EXR_ABO | EXR_PER)))
+ int_state = 7;
+ else if (m_lint)
+ int_state = 6;
+ else if (m_obr & OBR_RI)
+ int_state = 5;
+ else if (m_obr & OBR_TI)
+ int_state = 4;
+ else if (m_bint)
+ int_state = 3;
+ else if (m_obr & OBR_UI)
+ int_state = 2;
+ }
+
+ if (int_state != m_int_state)
+ {
+ // deassert old interrupt
+ if (m_int_state)
+ m_cpu->set_input_line(m_int_state, CLEAR_LINE);
+
+ // assert new interrupt
+ if (int_state)
+ m_cpu->set_input_line(int_state, int_state == 3 ? HOLD_LINE : ASSERT_LINE);
+
+ m_int_state = int_state;
+ }
+}
+
+void vme_enp10_card_device::cpu_ack(address_map &map)
+{
+ map(0xff'fff3, 0xff'fff3).lr8(NAME([]() { return m68000_base_device::autovector(1); }));
+ map(0xff'fff5, 0xff'fff5).lr8(NAME([]() { return m68000_base_device::autovector(2); }));
+ map(0xff'fff7, 0xff'fff7).lr8(NAME([this]() { m_bint = false; return m68000_base_device::autovector(3); }));
+ map(0xff'fff9, 0xff'fff9).lr8(NAME([]() { return m68000_base_device::autovector(4); }));
+ map(0xff'fffb, 0xff'fffb).lr8(NAME([]() { return m68000_base_device::autovector(5); }));
+ map(0xff'fffd, 0xff'fffd).lr8(NAME([]() { return m68000_base_device::autovector(6); }));
+ map(0xff'ffff, 0xff'ffff).lr8(NAME([]() { return m68000_base_device::autovector(7); }));
+}
+
+u16 vme_enp10_card_device::vme_a16_r(offs_t offset, u16 mem_mask)
+{
+ if (!machine().side_effects_disabled())
+ {
+ if (m_cpu->supervisor_mode())
+ return device_vme_card_interface::vme_read16<vme::AM_2d>(offset, mem_mask);
+ else
+ return device_vme_card_interface::vme_read16<vme::AM_29>(offset, mem_mask);
+ }
+ else
+ return 0;
+}
+
+void vme_enp10_card_device::vme_a16_w(offs_t offset, u16 data, u16 mem_mask)
+{
+ if (m_cpu->supervisor_mode())
+ device_vme_card_interface::vme_write16<vme::AM_2d>(offset, data, mem_mask);
+ else
+ device_vme_card_interface::vme_write16<vme::AM_29>(offset, data, mem_mask);
+}
+
+u16 vme_enp10_card_device::vme_a24_r(offs_t offset, u16 mem_mask)
+{
+ if (!machine().side_effects_disabled())
+ {
+ switch (m_cpu->get_fc())
+ {
+ case 1: return device_vme_card_interface::vme_read16<vme::AM_39>(offset, mem_mask);
+ case 2: return device_vme_card_interface::vme_read16<vme::AM_3a>(offset, mem_mask);
+ case 5: return device_vme_card_interface::vme_read16<vme::AM_3d>(offset, mem_mask);
+ case 6: return device_vme_card_interface::vme_read16<vme::AM_3e>(offset, mem_mask);
+ default:
+ fatalerror("enp10: unknown vme a24 space read (%s)\n", machine().describe_context());
+ }
+ }
+ else
+ return 0;
+}
+
+void vme_enp10_card_device::vme_a24_w(offs_t offset, u16 data, u16 mem_mask)
+{
+ switch (m_cpu->get_fc())
+ {
+ case 1: device_vme_card_interface::vme_write16<vme::AM_39>(offset, data, mem_mask); break;
+ case 2: device_vme_card_interface::vme_write16<vme::AM_3a>(offset, data, mem_mask); break;
+ case 5: device_vme_card_interface::vme_write16<vme::AM_3d>(offset, data, mem_mask); break;
+ case 6: device_vme_card_interface::vme_write16<vme::AM_3e>(offset, data, mem_mask); break;
+ default:
+ fatalerror("enp10: unknown vme a24 space write (%s)\n", machine().describe_context());
+ }
+}
diff --git a/src/devices/bus/vme/enp10.h b/src/devices/bus/vme/enp10.h
new file mode 100644
index 00000000000..0414a1325d5
--- /dev/null
+++ b/src/devices/bus/vme/enp10.h
@@ -0,0 +1,71 @@
+// 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 "machine/timer.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 ATTR_COLD;
+ virtual void device_add_mconfig(machine_config &config) override ATTR_COLD;
+ virtual ioport_constructor device_input_ports() const override ATTR_COLD;
+ virtual void device_start() override ATTR_COLD;
+ virtual void device_reset() override ATTR_COLD;
+
+private:
+ void cpu_map(address_map &map) ATTR_COLD;
+ void cpu_ack(address_map &map) ATTR_COLD;
+ void vme_map(address_map &map) ATTR_COLD;
+
+ // vme bus outgoing interrupt
+ u8 vect_r();
+ void vect_w(u8 data);
+ u8 iack_r();
+
+ // one-bit register handlers
+ u8 obr_r(offs_t offset);
+ void obr_w(offs_t offset, u8 data);
+
+ void timer(timer_device &timer, s32 param);
+ void interrupt();
+
+ // vme bus access handlers
+ u16 vme_a16_r(offs_t offset, u16 mem_mask);
+ void vme_a16_w(offs_t offset, u16 data, u16 mem_mask);
+ u16 vme_a24_r(offs_t offset, u16 mem_mask);
+ void vme_a24_w(offs_t offset, u16 data, u16 mem_mask);
+
+ 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_obr; // one-bit registers
+ u8 m_exr; // exception register
+
+ bool m_bint; // host to card interrupt
+ bool m_lint; // lance interrupt
+ u8 m_int_state; // current interrupt state
+
+ 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/hcpu30.cpp b/src/devices/bus/vme/hcpu30.cpp
new file mode 100644
index 00000000000..2165a8c2c6d
--- /dev/null
+++ b/src/devices/bus/vme/hcpu30.cpp
@@ -0,0 +1,594 @@
+// license:BSD-3-Clause
+// copyright-holders:Sergey Svishchev
+
+/*
+ * Besta HCPU30 board.
+ *
+ * Supported by SysV R3 "Bestix" port and also by Linux port,
+ * see https://github.com/shattered/linux-m68k
+ *
+ * 68030 @ 33 MHz - primary CPU
+ * 68882 @ 33 Mhz - FPU
+ * 68020 @ 16 MHz - I/O CPU (using shared memory region)
+ *
+ * 4 or 16 MB of DRAM
+ * 8 or 32 KB of NVRAM
+ *
+ * 33C93A - SCSI
+ * DP8473 - Floppy
+ * i82590 - Ethernet
+ * 62421A - Real-time clock
+ *
+ * To do:
+ *
+ * - pass functional test
+ * - boot to multiuser (SysV and Linux)
+ * - add LAN and Centronics
+ * - floppy: how is TC signal generated? (m_fdcdrq_hack); ready signal routing; dp8493 hacks
+ * - dump PALs (should help with irq routing)
+ *
+ */
+
+#include "emu.h"
+#include "hcpu30.h"
+
+#define LOG_INT (1U << 1)
+
+#define VERBOSE (0) // (LOG_GENERAL | LOG_INT)
+//#define LOG_OUTPUT_FUNC printf
+#include "logmacro.h"
+
+#define LOGINT(...) LOGMASKED(LOG_INT, __VA_ARGS__)
+
+
+#define DUSCC_CLOCK XTAL(14'745'600) /* XXX Unverified */
+#define RS232P1_TAG "rs232p1"
+#define RS232P2_TAG "rs232p2"
+
+
+//**************************************************************************
+// GLOBAL VARIABLES
+//**************************************************************************
+
+DEFINE_DEVICE_TYPE(VME_HCPU30, vme_hcpu30_card_device, "hcpu30", "Besta HCPU30 CPU board")
+
+void vme_hcpu30_card_device::hcpu30_mem(address_map &map)
+{
+ map.unmap_value_high();
+ map(0x00000000, 0x003fffff).ram().share("dram"); // local bus DRAM, 4 MB
+ map(0x00400000, 0x00ffffff).ram().share("hldram"); // optional HLDRAM
+ map(0xff000000, 0xff007fff).rom().region("user1", 0).mirror(0x8000);
+ map(0xfff1f400, 0xfff1f4ff).unmaprw(); // LAN DMA
+ map(0xff020000, 0xff021fff).ram().share("mailbox").mirror(0x8000); // SRAM 32KB -- shared with iocpu
+ map(0xff022000, 0xff027fff).ram().mirror(0x8000);
+ map(0xffff8000, 0xffff9fff).ram().share("mailbox");
+ map(0xfffff000, 0xfffff0ff).rw(FUNC(vme_hcpu30_card_device::dma_r), FUNC(vme_hcpu30_card_device::dma_w));
+ map(0xfffff100, 0xfffff11f).rw(FUNC(vme_hcpu30_card_device::irq_state_r), FUNC(vme_hcpu30_card_device::irq_mask_w));
+ map(0xfffff120, 0xfffff13f).rw(FUNC(vme_hcpu30_card_device::rtc_r), FUNC(vme_hcpu30_card_device::rtc_w));
+ map(0xfffff200, 0xfffff2ff).rw("scsi:7:wd33c93", FUNC(wd33c93_device::indir_r), FUNC(wd33c93_device::indir_w)).umask32(0xffff0000);
+ map(0xfffff300, 0xfffff3ff).rw("duscc", FUNC(duscc68562_device::read), FUNC(duscc68562_device::write));
+ map(0xfffff580, 0xfffff583).rw("scsi:7:wd33c93", FUNC(wd33c93_device::dma_r), FUNC(wd33c93_device::dma_w)).umask32(0xff000000);
+ map(0xfffff600, 0xfffff6ff).unmaprw(); // LAN
+ map(0xfffff700, 0xfffff7ff).m("floppy", FUNC(dp8473_device::map));
+}
+
+void vme_hcpu30_card_device::hcpu30_os_mem(address_map &map)
+{
+// bus error handler
+ map(0x00000000, 0xffffffff).rw(FUNC(vme_hcpu30_card_device::trap_r), FUNC(vme_hcpu30_card_device::trap_w));
+// shared memory with iocpu
+ map(0x00000000, 0x003fffff).ram().share("dram");
+ map(0x00400000, 0x00ffffff).ram().share("hldram");
+ map(0xffff8000, 0xffff9fff).ram().share("mailbox");
+}
+
+void vme_hcpu30_card_device::cpu_space_map(address_map &map)
+{
+ map(0xfffffff0, 0xffffffff).lr16(NAME([](offs_t offset) -> u16 { return 0x18 + offset; }));
+}
+
+void vme_hcpu30_card_device::oscpu_space_map(address_map &map)
+{
+ map(0xfffffff0, 0xffffffff).lr16(NAME([this](offs_t offset) -> u16 {
+ u16 vec = (offset & 1) ? (m_mailbox[offset >> 1] >> 8) : (m_mailbox[offset >> 1] >> 24);
+ logerror("68030 iack %d = %02x\n", offset, vec);
+ if (1 || BIT(m_irq_state, 6)) // FIXME: irq routing is not fully understood
+ {
+ m_irq_state &= ~(1 << 6); // raise IRQ30*
+ update_030_irq(offset, CLEAR_LINE);
+ return vec;
+ }
+ else
+ {
+ return 0;
+ }
+ }));
+}
+
+static INPUT_PORTS_START(hcpu30)
+ PORT_START("SA1")
+ PORT_DIPNAME(0x03, 0x00, "Console Port Speed")
+ PORT_DIPSETTING(0x00, "9600")
+ PORT_DIPSETTING(0x01, "19200")
+ PORT_DIPSETTING(0x02, "38400")
+ PORT_DIPSETTING(0x03, "4800")
+ PORT_DIPNAME(0x04, 0x04, "Boot Mode")
+ PORT_DIPSETTING(0x00, "UNIX")
+ PORT_DIPSETTING(0x04, "Monitor")
+ PORT_DIPNAME(0x08, 0x00, "Undefined 1")
+ PORT_DIPSETTING(0x00, "Off")
+ PORT_DIPSETTING(0x08, "On")
+ PORT_DIPNAME(0x10, 0x00, "VME Bus Width")
+ PORT_DIPSETTING(0x00, "32 bits")
+ PORT_DIPSETTING(0x10, "16 bits")
+ PORT_DIPNAME(0x20, 0x00, "VME Bus Free")
+ PORT_DIPSETTING(0x00, "ROR")
+ PORT_DIPSETTING(0x20, "REC")
+ PORT_DIPNAME(0x40, 0x00, "Cache Burst Mode")
+ PORT_DIPSETTING(0x00, "Off")
+ PORT_DIPSETTING(0x40, "On")
+ PORT_DIPNAME(0x80, 0x00, "Undefined 2")
+ PORT_DIPSETTING(0x00, "Off")
+ PORT_DIPSETTING(0x80, "On")
+INPUT_PORTS_END
+
+ROM_START(hcpu30)
+ ROM_REGION32_BE(0x8000, "user1", ROMREGION_ERASEFF)
+ // Rev 1.E of 09-NOV-1993
+ ROM_LOAD("hcpu30.27c256.dat", 0x0000, 0x8000, CRC(d24da66e) SHA1(5431b0559b168a995e725b35e1465a0b8ee8aa72))
+ROM_END
+
+//-------------------------------------------------
+// rom_region - device-specific ROM region
+//-------------------------------------------------
+
+const tiny_rom_entry *vme_hcpu30_card_device::device_rom_region() const
+{
+ return ROM_NAME(hcpu30);
+}
+
+//-------------------------------------------------
+// input_ports - device-specific input ports
+//-------------------------------------------------
+
+ioport_constructor vme_hcpu30_card_device::device_input_ports() const
+{
+ return INPUT_PORTS_NAME(hcpu30);
+}
+
+static void hcpu_floppies(device_slot_interface &device)
+{
+ device.option_add("525qd", FLOPPY_525_QD);
+}
+
+//-------------------------------------------------
+// device_add_mconfig - add device configuration
+//-------------------------------------------------
+
+void vme_hcpu30_card_device::device_add_mconfig(machine_config &config)
+{
+ // I/O CPU
+ 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->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);
+ m_dusccterm->configure_channels(0, 0, 0, 0);
+ m_dusccterm->out_txda_callback().set(RS232P1_TAG, FUNC(rs232_port_device::write_txd));
+ m_dusccterm->out_dtra_callback().set(RS232P1_TAG, FUNC(rs232_port_device::write_dtr));
+ m_dusccterm->out_rtsa_callback().set(RS232P1_TAG, FUNC(rs232_port_device::write_rts));
+// m_dusccterm->out_dtra_callback().set(m_dusccterm, FUNC(duscc68562_device::dcda_w));
+// m_dusccterm->out_rtsa_callback().set(m_dusccterm, FUNC(duscc68562_device::ctsa_w));
+ m_dusccterm->out_txdb_callback().set(RS232P2_TAG, FUNC(rs232_port_device::write_txd));
+ m_dusccterm->out_dtrb_callback().set(RS232P2_TAG, FUNC(rs232_port_device::write_dtr));
+ m_dusccterm->out_rtsb_callback().set(RS232P2_TAG, FUNC(rs232_port_device::write_rts));
+// m_dusccterm->out_txdb_callback().set(m_dusccterm, FUNC(duscc68562_device::rxb_w));
+// m_dusccterm->out_dtrb_callback().set(m_dusccterm, FUNC(duscc68562_device::dcdb_w));
+// m_dusccterm->out_rtsb_callback().set(m_dusccterm, FUNC(duscc68562_device::ctsb_w));
+ m_dusccterm->out_int_callback().set(FUNC(vme_hcpu30_card_device::dusirq_callback));
+
+ rs232_port_device &rs232p1(RS232_PORT(config, RS232P1_TAG, default_rs232_devices, "terminal"));
+ rs232p1.rxd_handler().set(m_dusccterm, FUNC(duscc68562_device::rxa_w));
+ rs232p1.cts_handler().set(m_dusccterm, FUNC(duscc68562_device::ctsa_w));
+
+ rs232_port_device &rs232p2(RS232_PORT(config, RS232P2_TAG, default_rs232_devices, nullptr));
+ rs232p2.rxd_handler().set(m_dusccterm, FUNC(duscc68562_device::rxb_w));
+ rs232p2.cts_handler().set(m_dusccterm, FUNC(duscc68562_device::ctsb_w));
+
+ NSCSI_BUS(config, "scsi");
+ NSCSI_CONNECTOR(config, "scsi:0").option_set("hd", NSCSI_HARDDISK);
+ NSCSI_CONNECTOR(config, "scsi:1").option_set("hd", NSCSI_HARDDISK);
+ NSCSI_CONNECTOR(config, "scsi:2").option_set("hd", NSCSI_HARDDISK);
+ NSCSI_CONNECTOR(config, "scsi:7").option_set("wd33c93", WD33C93A).machine_config(
+ [this](device_t *device)
+ {
+ wd33c9x_base_device &wd33c93(downcast<wd33c9x_base_device &>(*device));
+
+ wd33c93.set_clock(16670000/4); // default internal divisor is 2
+ wd33c93.irq_cb().set(*this, FUNC(vme_hcpu30_card_device::scsiirq_callback)).invert();
+ wd33c93.drq_cb().set(*this, FUNC(vme_hcpu30_card_device::scsidrq_callback));
+ });
+
+ // schematics connect INT to IPL1, not DRQ; could be outdated
+ DP8473(config, m_fdc, 24_MHz_XTAL);
+ m_fdc->drq_wr_callback().set_inputline(m_maincpu, M68K_IRQ_IPL1);
+ m_fdc->intrq_wr_callback().set(*this, FUNC(vme_hcpu30_card_device::fdcirq_callback)).invert();
+
+ // FIXME: drive select signals are swapped, handle this
+ FLOPPY_CONNECTOR(config, "floppy:0", hcpu_floppies, "525qd", floppy_image_device::default_pc_floppy_formats);
+ FLOPPY_CONNECTOR(config, "floppy:1", hcpu_floppies, "525qd", floppy_image_device::default_pc_floppy_formats);
+
+ RTC62421(config, m_rtc, 32.768_kHz_XTAL);
+
+ // FIXME: functional test expects A26-C24 A27-C28 A28-C26 A29-C30 A30-C32
+ // i.e. ACKNOWL-CENTDS BUSY-CENTD3 PE-CENTD1 SLCT-CENTD5 ERROR-CENTD7
+ CENTRONICS(config, m_centronics, centronics_devices, "printer");
+
+ INPUT_BUFFER(config, m_cent_status_in);
+
+ OUTPUT_LATCH(config, m_cent_data_out);
+
+ // OS CPU
+ M68030(config, m_oscpu, 2*16670000);
+ m_oscpu->set_addrmap(AS_PROGRAM, &vme_hcpu30_card_device::hcpu30_os_mem);
+ m_oscpu->set_addrmap(m68000_base_device::AS_CPU_SPACE, &vme_hcpu30_card_device::oscpu_space_map);
+ m_oscpu->set_disable();
+}
+
+uint32_t vme_hcpu30_card_device::rtc_r(offs_t offset)
+{
+ uint32_t data;
+
+ if (m_rtc_hack)
+ {
+ data = (m_rtc_reg[offset << 1] << 28) | (m_rtc_reg[(offset << 1) + 1] << 12);
+ data |= (m_rtc_reg[offset << 1] << 20) | (m_rtc_reg[(offset << 1) + 1] << 4);
+ }
+ else
+ {
+ data = (m_rtc->read(offset << 1) << 28) | (m_rtc->read((offset << 1) + 1) << 12);
+ data |= (m_rtc->read(offset << 1) << 20) | (m_rtc->read((offset << 1) + 1) << 4);
+ }
+
+ if (offset == 0)
+ {
+ data &= 0xffffff;
+ data |= m_dips->read() << 24;
+ }
+ if (offset == 7)
+ {
+ data &= 0xff00ffff;
+ data |= (m_cent_status_in->read() ^ 0xff) << 16;
+ }
+ LOG("vme_hcpu30_card_device::rtc_r(%02x) == %08x %s\n", offset, data, m_rtc_hack ? "(hacked)" : "");
+ return data;
+}
+
+void vme_hcpu30_card_device::rtc_w(offs_t offset, uint32_t data, uint32_t mem_mask)
+{
+ LOG("vme_hcpu30_card_device::rtc_w(%02x, %08x)<-%08x\n", offset, mem_mask, data);
+ if (mem_mask == 0xffff0000)
+ {
+ m_rtc->write(offset << 1, (data >> 4) & 15);
+ m_rtc_reg[offset << 1] = (data >> 4) & 15;
+ if (offset == 7)
+ {
+ m_cent_data_out->write(data >> 8);
+ }
+ }
+ else
+ {
+ m_rtc->write((offset << 1) + 1, (data >> 20) & 15);
+ m_rtc_reg[(offset << 1) + 1] = (data >> 20) & 15;
+ }
+ m_rtc_hack = (offset < 6 || (offset == 6 && mem_mask == 0xffff0000));
+}
+
+uint32_t vme_hcpu30_card_device::dma_r(offs_t offset)
+{
+ if (m_fdcdrq_hack++ == 1023)
+ {
+ m_fdc->tc_w(1);
+ m_fdcdrq_hack = 0;
+ }
+ else
+ {
+ m_fdc->tc_w(0);
+ }
+ return m_fdc->dma_r() << 24;
+}
+
+void vme_hcpu30_card_device::dma_w(offs_t offset, uint32_t data, uint32_t mem_mask)
+{
+ if (m_fdcdrq_hack++ == 1023)
+ {
+ m_fdc->tc_w(1);
+ m_fdcdrq_hack = 0;
+ }
+ else
+ {
+ m_fdc->tc_w(0);
+ }
+ m_fdc->dma_w(data);
+}
+
+uint32_t vme_hcpu30_card_device::trap_r(offs_t offset, uint32_t mem_mask)
+{
+ if (!machine().side_effects_disabled()) set_bus_error((offset << 2), true, mem_mask);
+
+ return 0xffffffff;
+}
+
+void vme_hcpu30_card_device::trap_w(offs_t offset, uint32_t data, uint32_t mem_mask)
+{
+ LOG("vme_hcpu30_card_device::trap_w(%08x, %08X)\n", offset << 2, data);
+ if (!machine().side_effects_disabled()) set_bus_error((offset << 2), false, mem_mask);
+}
+
+// Active High?
+void vme_hcpu30_card_device::dusirq_callback(int state)
+{
+ LOGINT("vme_hcpu30_card_device::dusirq_callback(%02x)\n", state);
+ m_irq_state &= ~(1 << 12);
+ m_irq_state |= (state << 12);
+}
+
+// Active Low?
+void vme_hcpu30_card_device::scsiirq_callback(int state)
+{
+ LOGINT("vme_hcpu30_card_device::scsiirq_callback(%02x)\n", state);
+ m_irq_state &= ~(1 << 8);
+ m_irq_state |= (state << 8);
+}
+
+// Active Low?
+void vme_hcpu30_card_device::scsidrq_callback(int state)
+{
+ LOGINT("vme_hcpu30_card_device::scsidrq_callback(%02x)\n", state);
+ m_irq_state &= ~(1 << 7);
+ m_irq_state |= (state << 7);
+}
+
+// Active Low?
+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));
+ m_irq_state |= (state << (8+2));
+}
+
+// Active Low?
+void vme_hcpu30_card_device::fdcdrq_callback(int state)
+{
+ LOGINT("vme_hcpu30_card_device::fdcdrq_callback(%02x)\n", state);
+#if 0
+ if (state)
+ {
+ if (m_fdcdrq_hack++ == 1022)
+ {
+ m_fdc->tc_w(1);
+ m_fdcdrq_hack = 0;
+ }
+ else
+ {
+ m_fdc->tc_w(0);
+ }
+ }
+#endif
+}
+
+// FF0003F2: move.w #$1d40, D7
+// i.e. DUSIRQ, ABORT, FDCIRQ, SCSIIRQ, IRQ30
+// FF00074C: eori.w #$2540, D0
+// i.e. bits 6, 8, 10, 13 are active low
+// D70 translates to DL16-23
+// D69 translates to DI0-7, D67 to DL24-31
+//
+// == f101.w ==
+// 0 - SYSFAIL*
+// 1 - ACFAIL*
+// 2 - TERMRES*
+// 3 - nc
+// 4 - FPSENSE*
+// 5 - RST*
+// 6 - IRQ30* D119 PLM output (CLRINT* and VECT20 inputs)
+// 7 - SDMRQ*
+// == f100.w ==
+// 8 - SCSIIRQ
+// 9 - CENTIRQ*
+// 10 - FDCIRQ*
+// 11 - ABORT*
+// 12 - DUSIRQ*
+// 13 - LANIRQ
+// 14 - IPEND* from 030
+// 15 - LDMARQ*
+uint32_t vme_hcpu30_card_device::irq_state_r(offs_t offset)
+{
+ return m_irq_state << 16;
+}
+
+void vme_hcpu30_card_device::update_030_irq(int irq, line_state state)
+{
+ if (irq != 0)
+ {
+ if (state == ASSERT_LINE)
+ {
+ LOG("triggering 68030 irq %d\n", irq);
+ m_oscpu->set_input_line(M68K_IRQ_NONE + irq, ASSERT_LINE);
+ }
+ else
+ {
+ LOG("clearing 68030 irq %d\n", irq);
+ m_oscpu->set_input_line(M68K_IRQ_NONE + irq, CLEAR_LINE);
+ }
+ }
+}
+
+// D60 translates from DI0-7 (DL24-31)
+// D61 translates from DL16-21
+// 0 - INTL0
+// 1 - INTL1
+// 2 - INTL2
+// 3 - VME16
+// 4 - CLRINT* D119 PLM input
+// 5 - LPBK* (loopback?)
+// 6-7 - nc
+// 8 - SCSIRES*
+// 9 - ROR
+// 10 - CENTDS (strobe)
+// 11 - RESET*
+// 12 - HALT*
+// 13 - SRLOCL*
+// 14 - PWRDOWN
+// 15 - INTENA* "enable input" pin of LS148 priority encoder
+void vme_hcpu30_card_device::irq_mask_w(offs_t offset, uint32_t data, uint32_t mem_mask)
+{
+ data >>= 16;
+ uint16_t diff = data ^ m_irq_mask;
+
+ LOG("vme_hcpu30_card_device::irq_mask_w(%04x,%04x)\n", data, diff);
+
+ if (BIT(diff, 15))
+ {
+ update_030_irq((BIT(data, 15) ? m_irq_mask : data) & 7, BIT(data, 15) ? CLEAR_LINE : ASSERT_LINE);
+ }
+ // CLRINT* affects IRQ30*
+ if (BIT(diff, 4))
+ {
+ m_irq_state &= ~(1 << 6);
+ m_irq_state |= (BIT(data, 4) << 6);
+ }
+ if (BIT(diff, 8))
+ {
+ m_scsi->reset_w(BIT(data, 8));
+ m_irq_state &= ~(1 << 5);
+ m_irq_state |= (!BIT(data, 8) << 5);
+ }
+ if (BIT(diff, 10))
+ {
+ m_centronics->write_strobe(BIT(data, 10));
+ }
+ if (BIT(diff, 11))
+ {
+ if (BIT(m_irq_mask, 11))
+ {
+ m_oscpu->set_input_line(INPUT_LINE_RESET, ASSERT_LINE);
+ LOG("68030 halted by reset\n");
+ }
+ else
+ {
+ if (m_oscpu->suspended(SUSPEND_REASON_RESET))
+ {
+ m_oscpu->set_input_line(INPUT_LINE_RESET, CLEAR_LINE);
+ LOG("68030 started after reset\n");
+ }
+ }
+ }
+ if (BIT(diff, 12))
+ {
+ if (BIT(m_irq_mask, 12))
+ {
+ m_oscpu->suspend(SUSPEND_REASON_DISABLE, 1);
+ LOG("68030 halted\n");
+ }
+ else
+ {
+ if (m_oscpu->suspended(SUSPEND_REASON_DISABLE))
+ {
+ m_oscpu->resume(SUSPEND_REASON_DISABLE);
+ LOG("68030 started\n");
+ }
+ }
+ }
+ m_irq_mask = data;
+}
+
+void vme_hcpu30_card_device::set_bus_error(uint32_t address, bool rw, uint32_t mem_mask)
+{
+ if (m_bus_error)
+ {
+ return;
+ }
+ LOG("bus error at %08x & %08x (%s)\n", address, mem_mask, rw ? "read" : "write");
+ if (!ACCESSING_BITS_16_31)
+ {
+ address++;
+ }
+ m_bus_error = true;
+ m_oscpu->set_buserror_details(address, rw, m_oscpu->get_fc());
+ m_oscpu->set_input_line(M68K_LINE_BUSERROR, ASSERT_LINE);
+ m_bus_error_timer->adjust(m_oscpu->cycles_to_attotime(16)); // let rmw cycles complete
+}
+
+vme_hcpu30_card_device::vme_hcpu30_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_dusccterm(*this, "duscc")
+ , m_scsi(*this, "scsi:7:wd33c93")
+ , m_fdc(*this, "floppy")
+ , m_floppy0(*this, "floppy:0")
+ , m_floppy1(*this, "floppy:1")
+ , m_rtc(*this, "rtc")
+ , m_centronics(*this, "centronics")
+ , m_cent_data_out(*this, "cent_data_out")
+ , m_cent_status_in(*this, "cent_status_in")
+ , m_oscpu(*this, "oscpu")
+ , m_mailbox(*this, "mailbox")
+ , m_p_ram(*this, "dram")
+ , m_sysrom(*this, "user1")
+ , m_dips(*this, "SA1")
+{
+ LOG("vme_hcpu30_card_device::vme_hcpu30_card_device ctor: %s\n", tag);
+}
+
+//
+
+vme_hcpu30_card_device::vme_hcpu30_card_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
+ : vme_hcpu30_card_device(mconfig, VME_HCPU30, tag, owner, clock)
+{
+}
+
+void vme_hcpu30_card_device::device_start()
+{
+ LOG("vme_hcpu30_card_device::device_start %s\n", tag());
+
+ m_bus_error_timer = timer_alloc(FUNC(vme_hcpu30_card_device::bus_error_off), this);
+}
+
+void vme_hcpu30_card_device::device_reset()
+{
+ address_space &program = m_maincpu->space(AS_PROGRAM);
+
+ LOG("vme_hcpu30_card_device::device_reset %s\n", tag());
+ m_irq_state = (1 << 10) | (1 << 6); // fdcirq | irq30*
+ m_irq_mask = 0;
+ m_rtc_hack = false;
+ m_fdcdrq_hack = 0;
+ m_fdc->ready_w(false);
+
+ program.install_rom(0x00000000, 0x00000007, m_sysrom); // do it here for F3
+ m_rom_shadow_tap.remove();
+ m_rom_shadow_tap = program.install_read_tap(
+ 0xff000000, 0xff007fff,
+ "rom_shadow_r",
+ [this] (offs_t offset, u32 &data, u32 mem_mask)
+ {
+ if (!machine().side_effects_disabled())
+ {
+ // delete this tap
+ m_rom_shadow_tap.remove();
+
+ // reinstall RAM over the ROM shadow
+ m_maincpu->space(AS_PROGRAM).install_ram(0x00000000, 0x00000007, m_p_ram);
+ }
+ },
+ &m_rom_shadow_tap);
+}
+
+TIMER_CALLBACK_MEMBER(vme_hcpu30_card_device::bus_error_off)
+{
+ m_bus_error = false;
+}
diff --git a/src/devices/bus/vme/hcpu30.h b/src/devices/bus/vme/hcpu30.h
new file mode 100644
index 00000000000..28697b782fe
--- /dev/null
+++ b/src/devices/bus/vme/hcpu30.h
@@ -0,0 +1,94 @@
+// license:BSD-3-Clause
+// copyright-holders:Sergey Svishchev
+#ifndef MAME_BUS_VME_HCPU30_H
+#define MAME_BUS_VME_HCPU30_H
+
+#pragma once
+
+#include "vme.h"
+
+#include "bus/centronics/ctronics.h"
+#include "bus/nscsi/hd.h"
+#include "bus/rs232/rs232.h"
+#include "cpu/m68000/m68020.h"
+#include "cpu/m68000/m68030.h"
+#include "imagedev/floppy.h"
+#include "machine/clock.h"
+#include "machine/msm6242.h"
+#include "machine/scnxx562.h"
+#include "machine/terminal.h"
+#include "machine/upd765.h"
+#include "machine/wd33c9x.h"
+
+DECLARE_DEVICE_TYPE(VME_HCPU30, vme_hcpu30_card_device)
+
+class vme_hcpu30_card_device : public device_t, public device_vme_card_interface
+{
+public:
+ vme_hcpu30_card_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
+
+protected:
+ vme_hcpu30_card_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock);
+
+ virtual void device_start() override ATTR_COLD;
+ virtual void device_reset() override ATTR_COLD;
+
+ // optional information overrides
+ virtual void device_add_mconfig(machine_config &config) override ATTR_COLD;
+ virtual const tiny_rom_entry *device_rom_region() const override ATTR_COLD;
+ virtual ioport_constructor device_input_ports() const override ATTR_COLD;
+
+ TIMER_CALLBACK_MEMBER(bus_error_off);
+
+private:
+ 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;
+ required_device<floppy_connector> m_floppy0;
+ required_device<floppy_connector> m_floppy1;
+ required_device<rtc62421_device> m_rtc;
+ 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_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;
+
+ 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;
+ uint16_t m_irq_state;
+ uint16_t m_irq_mask;
+ uint8_t m_rtc_reg[16];
+ bool m_rtc_hack;
+ int m_fdcdrq_hack;
+ bool m_bus_error;
+ emu_timer *m_bus_error_timer;
+
+ uint32_t irq_state_r(offs_t offset);
+ void irq_mask_w(offs_t offset, uint32_t data, uint32_t mem_mask = ~0);
+ uint32_t rtc_r(offs_t offset);
+ void rtc_w(offs_t offset, uint32_t data, uint32_t mem_mask = ~0);
+ uint32_t dma_r(offs_t offset);
+ void dma_w(offs_t offset, uint32_t data, uint32_t mem_mask = ~0);
+ uint32_t trap_r(offs_t offset, uint32_t mem_mask);
+ void trap_w(offs_t offset, uint32_t data, uint32_t mem_mask = ~0);
+
+ void set_bus_error(uint32_t address, bool write, uint32_t mem_mask);
+ void update_030_irq(int irq, line_state state);
+
+ void hcpu30_mem(address_map &map) ATTR_COLD;
+ void hcpu30_os_mem(address_map &map) ATTR_COLD;
+ void cpu_space_map(address_map &map) ATTR_COLD;
+ void oscpu_space_map(address_map &map) ATTR_COLD;
+};
+
+#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..c821a421305
--- /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 */
+ SCC8530(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..ae805c054d5
--- /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 ATTR_COLD;
+ virtual void device_add_mconfig(machine_config &config) override ATTR_COLD;
+ virtual ioport_constructor device_input_ports() const override ATTR_COLD;
+ virtual void device_start() override ATTR_COLD;
+ virtual void device_reset() override ATTR_COLD;
+
+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) ATTR_COLD;
+
+ 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/mvme120.cpp b/src/devices/bus/vme/mvme120.cpp
new file mode 100644
index 00000000000..32036b1875f
--- /dev/null
+++ b/src/devices/bus/vme/mvme120.cpp
@@ -0,0 +1,469 @@
+// license:BSD-3-Clause
+// copyright-holders:Katherine Rohl
+/*
+ * Motorola MVME120 CPU board.
+ * This is an early MVME system from 1984, using standard Motorola parts
+ * instead of the many ASICs of later boards.
+ *
+ * The following configurations were available:
+ * MVME120 - 10MHz 68010, 128KB RAM, 4KB SRAM cache, 68451 MMU
+ * MVME121 - 10MHz 68010, 512KB RAM, 4KB SRAM cache, 68451 MMU
+ * MVME122 - 12.5MHz 68010, 128KB RAM, no cache, no MMU
+ * MVME123 - 12.5MHz 68010, 512KB RAM, 4KB SRAM cache, no MMU
+ *
+ * Current state, it crashes at $F058D8 while testing CPU exception handling.
+ * If you skip over that address (pc=F058E2 in the debugger) it continues
+ * through the self-test.
+ *
+ * Looks like you also have to reboot the system once before the terminal
+ * works properly? Still working on that.
+ */
+
+#include "emu.h"
+#include "mvme120.h"
+
+#ifdef _MSC_VER
+#define FUNCNAME __func__
+#else
+#define FUNCNAME __PRETTY_FUNCTION__
+#endif
+
+#define VERBOSE (LOG_GENERAL)
+#include "logmacro.h"
+
+// Clocks
+#define MVME120_MASTER_CLOCK 20_MHz_XTAL
+#define MVME120_CPU_CLOCK ( MVME120_MASTER_CLOCK / 2 )
+#define MVME120_MFP_CLOCK ( MVME120_CPU_CLOCK / 4 )
+
+#define MVME122_MASTER_CLOCK 25_MHz_XTAL
+#define MVME122_CPU_CLOCK ( MVME122_MASTER_CLOCK / 2 )
+#define MVME122_MFP_CLOCK ( MVME122_CPU_CLOCK / 4 )
+
+// The four MVME12x card variants.
+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")
+ // described as "autoboot" and "cache disable" in the manual
+ PORT_DIPNAME(0x01, 0x00, DEF_STR( Unknown ) ) PORT_DIPLOCATION("S3:1") PORT_CHANGED_MEMBER(DEVICE_SELF, FUNC(vme_mvme120_device::s3_autoboot), 0)
+ PORT_DIPSETTING( 0x01, DEF_STR( On ) )
+ PORT_DIPSETTING( 0x00, DEF_STR( Off ) )
+
+ PORT_DIPNAME(0x02, 0x00, "Baud Rate Select") PORT_DIPLOCATION("S3:2") PORT_CHANGED_MEMBER(DEVICE_SELF, FUNC(vme_mvme120_device::s3_baudrate), 0)
+ PORT_DIPSETTING( 0x02, "10.0MHz CPU")
+ PORT_DIPSETTING( 0x00, "12.5MHz CPU")
+
+ PORT_DIPNAME(0x0C, 0x08, "Reset Vector Source") PORT_DIPLOCATION("S3:3,4")
+ PORT_DIPSETTING( 0x08, "Onboard ROM")
+ PORT_DIPSETTING( 0x04, "VMEbus")
+
+ // Select whether MSR bit 7 monitors ACFAIL* or SYSFAIL* on the VME bus.
+ PORT_START("J2")
+ PORT_DIPNAME(0x01, 0x01, "ACFAIL*/SYSFAIL* Select")
+ PORT_DIPSETTING( 0x00, "ACFAIL*")
+ PORT_DIPSETTING( 0x01, "SYSFAIL*")
+
+ PORT_START("J3-J4") // Different configurations of jumpers in J3 and J4.
+ PORT_DIPNAME(0x03, 0x03, "VMEbus Request Level")
+ PORT_DIPSETTING( 0x00, "Level 0")
+ PORT_DIPSETTING( 0x01, "Level 1")
+ PORT_DIPSETTING( 0x02, "Level 2")
+ PORT_DIPSETTING( 0x03, "Level 3")
+
+ PORT_START("J5")
+ PORT_DIPNAME(0x01, 0x01, "Abort Switch Enable")
+ PORT_DIPSETTING( 0x00, DEF_STR( Off ))
+ PORT_DIPSETTING( 0x01, DEF_STR( On ))
+
+ PORT_START("J6")
+ PORT_DIPNAME(0x01, 0x01, "Reset Switch Enable")
+ PORT_DIPSETTING( 0x00, DEF_STR( Off ))
+ PORT_DIPSETTING( 0x01, DEF_STR( On ))
+
+ PORT_START("J7") // Enable/disable VME IRQs reaching the MFP.
+ PORT_DIPNAME(0x01, 0x01, "VME IRQ1") PORT_DIPLOCATION("J7:1")
+ PORT_DIPSETTING( 0x00, DEF_STR( Off ))
+ PORT_DIPSETTING( 0x01, DEF_STR( On ))
+ PORT_DIPNAME(0x02, 0x02, "VME IRQ2") PORT_DIPLOCATION("J7:2")
+ PORT_DIPSETTING( 0x00, DEF_STR( Off ))
+ PORT_DIPSETTING( 0x02, DEF_STR( On ))
+ PORT_DIPNAME(0x04, 0x04, "VME IRQ3") PORT_DIPLOCATION("J7:3")
+ PORT_DIPSETTING( 0x00, DEF_STR( Off ))
+ PORT_DIPSETTING( 0x04, DEF_STR( On ))
+ PORT_DIPNAME(0x08, 0x08, "VME IRQ4") PORT_DIPLOCATION("J7:4")
+ PORT_DIPSETTING( 0x00, DEF_STR( Off ))
+ PORT_DIPSETTING( 0x08, DEF_STR( On ))
+ PORT_DIPNAME(0x10, 0x10, "VME IRQ5") PORT_DIPLOCATION("J7:5")
+ PORT_DIPSETTING( 0x00, DEF_STR( Off ))
+ PORT_DIPSETTING( 0x10, DEF_STR( On ))
+ PORT_DIPNAME(0x20, 0x20, "VME IRQ6") PORT_DIPLOCATION("J7:6")
+ PORT_DIPSETTING( 0x00, DEF_STR( Off ))
+ PORT_DIPSETTING( 0x20, DEF_STR( On ))
+ PORT_DIPNAME(0x40, 0x40, "VME IRQ7") PORT_DIPLOCATION("J7:7")
+ PORT_DIPSETTING( 0x00, DEF_STR( Off ))
+ PORT_DIPSETTING( 0x40, DEF_STR( On ))
+
+ // EPROM configuration is J8
+ // Cache configuration is J9/J17
+INPUT_PORTS_END
+
+ioport_constructor vme_mvme120_device::device_input_ports() const
+{
+ return INPUT_PORTS_NAME(mvme120);
+}
+
+vme_mvme120_device::vme_mvme120_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock, mvme12x_variant board_id) :
+ device_t(mconfig, type, tag, owner, clock)
+ , device_vme_card_interface(mconfig, *this)
+ , m_maincpu(*this, "maincpu")
+ , m_mfp(*this, "mfp")
+ , m_rs232(*this, "rs232")
+ , m_input_s3(*this, "S3")
+ , m_sysrom(*this, "maincpu")
+ , m_localram(*this, "localram")
+ , m_board_id(board_id)
+{
+
+}
+
+vme_mvme120_card_device::vme_mvme120_card_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
+ : vme_mvme120_card_device(mconfig, VME_MVME120, tag, owner, clock)
+{
+
+}
+
+vme_mvme121_card_device::vme_mvme121_card_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
+ : vme_mvme121_card_device(mconfig, VME_MVME121, tag, owner, clock)
+{
+
+}
+
+vme_mvme122_card_device::vme_mvme122_card_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
+ : vme_mvme122_card_device(mconfig, VME_MVME122, tag, owner, clock)
+{
+}
+
+vme_mvme123_card_device::vme_mvme123_card_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
+ : vme_mvme123_card_device(mconfig, VME_MVME123, tag, owner, clock)
+{
+
+}
+
+void vme_mvme120_device::mvme12x_base_mem(address_map &map)
+{
+ map(0xf00000, 0xf0ffff).rom().region("maincpu", 0x00000); // ROM/EEPROM bank 1 - 120bug
+ map(0xf10000, 0xf1ffff).rom().region("maincpu", 0x10000); // ROM/EEPROM bank 2 - unpopulated
+ map(0xf20000, 0xf2003f).mirror(0x1ffc0).umask16(0x00ff).rw(m_mfp, FUNC(mc68901_device::read), FUNC(mc68901_device::write));
+ map(0xf40000, 0xf40000).mirror(0x1fffc).rw(FUNC(vme_mvme120_card_device::ctrlreg_r), FUNC(vme_mvme120_card_device::ctrlreg_w));
+ // $F60000-F6003F 68451 MMU, mirrored to $F7FFFF
+ map(0xfa0000, 0xfeffff).rw(FUNC(vme_mvme120_card_device::vme_a24_r), FUNC(vme_mvme120_card_device::vme_a24_w)); // VMEbus 24-bit addresses
+ map(0xff0000, 0xffffff).rw(FUNC(vme_mvme120_card_device::vme_a16_r), FUNC(vme_mvme120_card_device::vme_a16_w)); // VMEbus 16-bit addresses
+
+ // $F80002-F80003 clear cache bank 2
+ // $F80004-F80005 clear cache bank 1
+ // $F80006-F80007 clear cache bank 1+2
+ // (above mirrored to $F9FFFF)
+}
+
+void vme_mvme120_device::mvme120_mem(address_map &map)
+{
+ mvme12x_base_mem(map);
+ map(0x000000, 0x01ffff).ram().share(m_localram);
+ map(0x020000, 0xefffff).rw(FUNC(vme_mvme120_card_device::vme_a24_r), FUNC(vme_mvme120_card_device::vme_a24_w)); // VMEbus 24-bit addresses
+ // $F60000-F6003F 68451 MMU, mirrored to $F7FFFF
+ // $F80002-F80003 clear cache bank 2
+ // $F80004-F80005 clear cache bank 1
+ // $F80006-F80007 clear cache bank 1+2
+ // (above mirrored to $F9FFFF)
+}
+
+void vme_mvme120_device::mvme121_mem(address_map &map)
+{
+ mvme12x_base_mem(map);
+ map(0x000000, 0x07ffff).ram().share(m_localram);
+ map(0x080000, 0xefffff).rw(FUNC(vme_mvme120_card_device::vme_a24_r), FUNC(vme_mvme120_card_device::vme_a24_w)); // VMEbus 24-bit addresses
+ // $F60000-F6003F 68451 MMU, mirrored to $F7FFFF
+ // $F80002-F80003 clear cache bank 2
+ // $F80004-F80005 clear cache bank 1
+ // $F80006-F80007 clear cache bank 1+2
+ // (above mirrored to $F9FFFF)
+}
+
+void vme_mvme120_device::mvme122_mem(address_map &map)
+{
+ mvme12x_base_mem(map);
+ map(0x000000, 0x01ffff).ram().share(m_localram);
+ map(0x020000, 0xefffff).rw(FUNC(vme_mvme120_card_device::vme_a24_r), FUNC(vme_mvme120_card_device::vme_a24_w)); // VMEbus 24-bit addresses
+ // No MMU, no cache
+}
+
+void vme_mvme120_device::mvme123_mem(address_map &map)
+{
+ mvme12x_base_mem(map);
+ map(0x000000, 0x07ffff).ram().share(m_localram);
+ map(0x020000, 0xefffff).rw(FUNC(vme_mvme120_card_device::vme_a24_r), FUNC(vme_mvme120_card_device::vme_a24_w)); // VMEbus 24-bit addresses
+ // $F80002-F80003 clear cache bank 2
+ // $F80004-F80005 clear cache bank 1
+ // $F80006-F80007 clear cache bank 1+2
+ // (above mirrored to $F9FFFF)
+}
+
+void vme_mvme120_device::device_start()
+{
+ LOG("%s\n", FUNCNAME);
+}
+
+void vme_mvme120_device::device_reset()
+{
+ LOG("%s\n", FUNCNAME);
+
+ // First 4 machine cycles, ROM is mapped to the reset vector.
+ address_space &program = m_maincpu->space(AS_PROGRAM);
+ program.install_rom(0x000000, 0x000007, m_sysrom);
+ m_memory_read_count = 0;
+
+ m_rom_shadow_tap.remove();
+ m_rom_shadow_tap = program.install_read_tap(
+ 0x000000, 0x000007,
+ "rom_shadow_r",
+ [this] (offs_t offset, u16 &data, u16 mem_mask)
+ {
+ rom_shadow_tap(offset, data, mem_mask);
+ },
+ &m_rom_shadow_tap);
+
+ ctrlreg_w(0, 0xFF); // /RESET flips the latch bits to $FF
+}
+
+void vme_mvme120_device::rom_shadow_tap(offs_t address, u16 data, u16 mem_mask)
+{
+ if(!machine().side_effects_disabled())
+ {
+ if(m_memory_read_count >= 3)
+ {
+ // delete this tap
+ m_rom_shadow_tap.remove();
+
+ // reinstall RAM over the ROM shadow
+ m_maincpu->space(AS_PROGRAM).install_ram(0x000000, 0x000007, m_localram);
+ }
+ m_memory_read_count++;
+ }
+}
+
+void vme_mvme120_device::watchdog_reset(int state)
+{
+ if(state)
+ {
+ LOG("%s: MFP watchdog reset\n", FUNCNAME);
+ machine().schedule_soft_reset();
+ }
+}
+
+void vme_mvme120_device::mfp_interrupt(int state)
+{
+ LOG("%s: MFP asserting interrupt\n", FUNCNAME);
+
+ // MFP interrupts are gated by bit 2 of the control register.
+ if(state && !BIT(m_ctrlreg, 2))
+ {
+ LOG("%s: MFP interrupt triggered 68K IRQ6\n", FUNCNAME);
+ m_maincpu->set_input_line(M68K_IRQ_6, ASSERT_LINE);
+ }
+ if(!state)
+ {
+ m_maincpu->set_input_line(M68K_IRQ_6, CLEAR_LINE);
+ }
+}
+
+void vme_mvme120_device::vme_bus_timeout()
+{
+ m_mfp->i2_w(ASSERT_LINE);
+ m_mfp->i2_w(CLEAR_LINE);
+
+ m_maincpu->set_input_line(M68K_LINE_BUSERROR, ASSERT_LINE);
+ m_maincpu->set_input_line(M68K_LINE_BUSERROR, CLEAR_LINE);
+}
+
+// Dummy VMEbus access
+uint16_t vme_mvme120_device::vme_a24_r()
+{
+ if(!machine().side_effects_disabled())
+ {
+ vme_bus_timeout();
+ }
+ return 0;
+}
+
+void vme_mvme120_device::vme_a24_w(uint16_t data)
+{
+ vme_bus_timeout();
+}
+
+uint16_t vme_mvme120_device::vme_a16_r()
+{
+ if(!machine().side_effects_disabled())
+ {
+ vme_bus_timeout();
+ }
+ return 0;
+}
+
+void vme_mvme120_device::vme_a16_w(uint16_t data)
+{
+ vme_bus_timeout();
+}
+
+uint8_t vme_mvme120_device::ctrlreg_r(offs_t offset)
+{
+ // Control Register
+ // b0 - BRDFAIL - Controls FAIL LED
+ // b1 - /CTS - Asserts RTS on serial port 1
+ // b2 - /IE - When asserted, MFP interrupts reach the CPU
+ // b3 - /PAREN - When asserted, parity errors do not cause /BERR.
+ // b4 - CACHEN - Enable SRAM cache
+ // b5 - FREEZE - Cache cannot be updated (but can be invalidated)
+ // b6 - /ALTCLR - "Allows bus error to start alternate interrupt mode" (?)
+ // b7 - /WWP - When asserted, bad parity is written to RAM.
+
+ return m_ctrlreg;
+}
+
+void vme_mvme120_device::ctrlreg_w(offs_t offset, uint8_t data)
+{
+ LOG("%s: vme120 control register set to $%02X\n", FUNCNAME, data);
+ m_ctrlreg = data;
+
+ // Set lines according to the new ctrlreg status.
+ m_rs232->write_rts(!BIT(m_ctrlreg, 1));
+}
+
+static const input_device_default terminal_defaults[] =
+{
+ 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 )
+ { nullptr, 0, 0 }
+};
+
+/*
+ * Machine configuration
+ */
+void vme_mvme120_device::device_add_mconfig(machine_config &config)
+{
+ // basic machine hardware
+ M68010(config, m_maincpu, MVME120_CPU_CLOCK);
+ m_maincpu->set_addrmap(AS_PROGRAM, &vme_mvme120_card_device::mvme120_mem);
+ m_maincpu->set_addrmap(m68000_base_device::AS_CPU_SPACE, &vme_mvme120_card_device::mvme120_mem);
+
+ MC68901(config, m_mfp, MVME120_MFP_CLOCK);
+ m_mfp->set_timer_clock(MVME120_MFP_CLOCK);
+ m_mfp->out_so_cb().set("rs232", FUNC(rs232_port_device::write_txd));
+ m_mfp->out_tao_cb().set("mfp", FUNC(mc68901_device::tbi_w));
+ m_mfp->out_tbo_cb().set(FUNC(vme_mvme120_card_device::watchdog_reset));
+ m_mfp->out_tco_cb().set("mfp", FUNC(mc68901_device::rc_w));
+ m_mfp->out_tco_cb().append("mfp", FUNC(mc68901_device::tc_w));
+ m_mfp->out_irq_cb().set(FUNC(vme_mvme120_card_device::mfp_interrupt));
+
+ RS232_PORT(config, m_rs232, default_rs232_devices, "terminal");
+ m_rs232->rxd_handler().set("mfp", FUNC(mc68901_device::si_w));
+ m_rs232->set_option_device_input_defaults("terminal", terminal_defaults);
+
+ // Missing: MMU, VMEbus
+
+ VME(config, "vme", 0);
+
+ /*
+ // Onboard RAM is always visible to VMEbus. (Decoding controlled by U28.)
+ m_vme->install_device(vme_device::A24_SC, 0, 0x1FFFF,
+ read16_delegate(*this, FUNC(vme_mvme120_device::vme_to_ram_r)),
+ write16_delegate(*this, FUNC(vme_mvme120_device::vme_to_ram_w)),
+ 0xFFFF);
+ */
+}
+
+uint16_t vme_mvme120_device::vme_to_ram_r(address_space &space, offs_t address, uint16_t mem_mask)
+{
+ return m_localram[address];
+}
+
+void vme_mvme120_device::vme_to_ram_w(address_space &space, offs_t address, uint16_t data, uint16_t mem_mask)
+{
+ m_localram[address] = data;
+}
+
+void vme_mvme120_card_device::device_add_mconfig(machine_config &config)
+{
+ vme_mvme120_device::device_add_mconfig(config);
+ m_maincpu->set_addrmap(AS_PROGRAM, &vme_mvme120_card_device::mvme120_mem);
+ m_maincpu->set_addrmap(m68000_base_device::AS_CPU_SPACE, &vme_mvme120_card_device::mvme120_mem);
+}
+
+void vme_mvme121_card_device::device_add_mconfig(machine_config &config)
+{
+ vme_mvme120_device::device_add_mconfig(config);
+ m_maincpu->set_addrmap(AS_PROGRAM, &vme_mvme121_card_device::mvme121_mem);
+ m_maincpu->set_addrmap(m68000_base_device::AS_CPU_SPACE, &vme_mvme121_card_device::mvme121_mem);
+}
+
+void vme_mvme122_card_device::device_add_mconfig(machine_config &config)
+{
+ vme_mvme120_device::device_add_mconfig(config);
+
+ m_maincpu->set_addrmap(AS_PROGRAM, &vme_mvme122_card_device::mvme122_mem);
+ m_maincpu->set_addrmap(m68000_base_device::AS_CPU_SPACE, &vme_mvme122_card_device::mvme122_mem);
+ m_maincpu->set_clock(MVME122_CPU_CLOCK);
+
+ m_mfp->set_clock(MVME122_MFP_CLOCK);
+ m_mfp->set_timer_clock(MVME122_MFP_CLOCK);
+}
+
+void vme_mvme123_card_device::device_add_mconfig(machine_config &config)
+{
+ vme_mvme120_device::device_add_mconfig(config);
+ m_maincpu->set_addrmap(AS_PROGRAM, &vme_mvme123_card_device::mvme123_mem);
+ m_maincpu->set_addrmap(m68000_base_device::AS_CPU_SPACE, &vme_mvme123_card_device::mvme123_mem);
+
+ m_maincpu->set_clock(MVME122_CPU_CLOCK);
+
+ m_mfp->set_clock(MVME122_MFP_CLOCK);
+ m_mfp->set_timer_clock(MVME122_MFP_CLOCK);
+}
+
+// DIP switch and jumpers
+INPUT_CHANGED_MEMBER(vme_mvme120_device::s3_autoboot)
+{
+ // TODO: verify
+ //m_mfp->i0_w(BIT(m_input_s3->read(), 0));
+}
+
+INPUT_CHANGED_MEMBER(vme_mvme120_device::s3_baudrate)
+{
+ // TODO: verify
+ //m_mfp->i1_w(BIT(m_input_s3->read(), 1));
+}
+
+// ROM definitions
+ROM_START(mvme120)
+ ROM_REGION16_BE(0x20000, "maincpu", 0)
+ ROM_DEFAULT_BIOS("12xbug-v2.0")
+
+ ROM_SYSTEM_BIOS(0, "12xbug-v2.0", "MVME120 12xbug v2.0")
+ ROMX_LOAD("12xbug-2.0-u44.bin", 0x0000, 0x4000, CRC(87d62dac) SHA1(c57eb9f8aefe29794b8fc5f0afbaff9b59d38c73), ROM_SKIP(1) | ROM_BIOS(0))
+ ROMX_LOAD("12xbug-2.0-u52.bin", 0x0001, 0x4000, CRC(5651b61d) SHA1(0d0004dff3c88b2f0b18951b4f2acd7f65f701b1), ROM_SKIP(1) | ROM_BIOS(0))
+
+ ROM_SYSTEM_BIOS(1, "12xbug-v1.1", "MVME120 12xbug v1.1")
+ ROMX_LOAD("12xbug-1.1-u44.bin", 0x0000, 0x4000, CRC(bf4d6cf1) SHA1(371bb55611eddeb6231a92af7c1e34d4ec0321b5), ROM_SKIP(1) | ROM_BIOS(1))
+ ROMX_LOAD("12xbug-1.1-u52.bin", 0x0001, 0x4000, CRC(76fabe32) SHA1(2f933d0eb46d00db0051ce23c3e53ccef75a2c69), ROM_SKIP(1) | ROM_BIOS(1))
+ROM_END
+
+const tiny_rom_entry *vme_mvme120_device::device_rom_region() const
+{
+ return ROM_NAME(mvme120);
+}
diff --git a/src/devices/bus/vme/mvme120.h b/src/devices/bus/vme/mvme120.h
new file mode 100644
index 00000000000..4738dbf8a2a
--- /dev/null
+++ b/src/devices/bus/vme/mvme120.h
@@ -0,0 +1,153 @@
+// license:BSD-3-Clause
+// copyright-holders:Katherine Rohl
+#ifndef MAME_BUS_VME_MVME120_H
+#define MAME_BUS_VME_MVME120_H
+
+#pragma once
+
+#include "cpu/m68000/m68010.h"
+#include "bus/vme/vme.h"
+#include "bus/rs232/rs232.h"
+#include "machine/clock.h"
+#include "machine/mc68901.h"
+
+DECLARE_DEVICE_TYPE(VME_MVME120, vme_mvme120_card_device)
+DECLARE_DEVICE_TYPE(VME_MVME121, vme_mvme121_card_device)
+DECLARE_DEVICE_TYPE(VME_MVME122, vme_mvme122_card_device)
+DECLARE_DEVICE_TYPE(VME_MVME123, vme_mvme123_card_device)
+
+//**************************************************************************
+// Base Device declaration
+//**************************************************************************
+class vme_mvme120_device : public device_t, public device_vme_card_interface
+{
+public:
+ /* Board types */
+ enum mvme12x_variant
+ {
+ mvme120_board,
+ mvme121_board,
+ mvme122_board,
+ mvme123_board
+ };
+
+ vme_mvme120_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock, mvme12x_variant board_id);
+
+ // Switch and jumper handlers
+ DECLARE_INPUT_CHANGED_MEMBER(s3_autoboot);
+ DECLARE_INPUT_CHANGED_MEMBER(s3_baudrate);
+
+ uint16_t vme_to_ram_r(address_space &space, offs_t offset, uint16_t mem_mask);
+ void vme_to_ram_w(address_space &space, offs_t address, uint16_t data, uint16_t mem_mask);
+
+protected:
+ void device_add_mconfig(machine_config &config) override;
+ virtual const tiny_rom_entry *device_rom_region() const override ATTR_COLD;
+ virtual ioport_constructor device_input_ports() const override ATTR_COLD;
+
+ virtual void device_start() override ATTR_COLD;
+ virtual void device_reset() override ATTR_COLD;
+
+ void mvme12x_base_mem(address_map &map) ATTR_COLD;
+ void mvme120_mem(address_map &map) ATTR_COLD;
+ void mvme121_mem(address_map &map) ATTR_COLD;
+ void mvme122_mem(address_map &map) ATTR_COLD;
+ void mvme123_mem(address_map &map) ATTR_COLD;
+
+ required_device<cpu_device> m_maincpu;
+
+ required_device<mc68901_device> m_mfp;
+ required_device<rs232_port_device> m_rs232;
+
+ required_ioport m_input_s3;
+
+ memory_passthrough_handler m_rom_shadow_tap;
+
+ required_region_ptr<uint16_t> m_sysrom;
+ required_shared_ptr<uint16_t> m_localram;
+
+ uint8_t m_ctrlreg; // "VME120 Control Register"
+ uint8_t m_memory_read_count; // For boot ROM shadowing $000000
+
+ uint8_t ctrlreg_r(offs_t offset);
+ void ctrlreg_w(offs_t offset, uint8_t data);
+
+ // VMEbus dummy lines
+ void vme_bus_timeout();
+ 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 rom_shadow_tap(offs_t address, u16 data, u16 mem_mask);
+
+ void watchdog_reset(int state);
+ void mfp_interrupt(int state);
+
+ const mvme12x_variant m_board_id;
+};
+
+
+//**************************************************************************
+// Board Device declarations
+//**************************************************************************
+
+class vme_mvme120_card_device : public vme_mvme120_device
+{
+public:
+ vme_mvme120_card_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
+
+protected:
+ vme_mvme120_card_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock)
+ : vme_mvme120_device(mconfig, type, tag, owner, clock, mvme120_board)
+ { }
+
+ // optional information overrides
+ virtual void device_add_mconfig(machine_config &config) override ATTR_COLD;
+};
+
+class vme_mvme121_card_device : public vme_mvme120_device
+{
+public:
+ vme_mvme121_card_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
+
+protected:
+ vme_mvme121_card_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock)
+ : vme_mvme120_device(mconfig, type, tag, owner, clock, mvme121_board)
+ { }
+
+ // optional information overrides
+ virtual void device_add_mconfig(machine_config &config) override ATTR_COLD;
+};
+
+
+class vme_mvme122_card_device : public vme_mvme120_device
+{
+public:
+ vme_mvme122_card_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
+
+protected:
+ vme_mvme122_card_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock)
+ : vme_mvme120_device(mconfig, type, tag, owner, clock, mvme122_board)
+ { }
+
+ // optional information overrides
+ virtual void device_add_mconfig(machine_config &config) override ATTR_COLD;
+};
+
+
+class vme_mvme123_card_device : public vme_mvme120_device
+{
+public:
+ vme_mvme123_card_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
+
+protected:
+ vme_mvme123_card_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock)
+ : vme_mvme120_device(mconfig, type, tag, owner, clock, mvme123_board)
+ { }
+
+ // optional information overrides
+ virtual void device_add_mconfig(machine_config &config) override ATTR_COLD;
+};
+
+#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..0318b95feb7
--- /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 ATTR_COLD;
+ virtual void device_add_mconfig(machine_config &config) override ATTR_COLD;
+ virtual ioport_constructor device_input_ports() const override ATTR_COLD;
+ virtual void device_start() override ATTR_COLD;
+ virtual void device_reset() override ATTR_COLD;
+
+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) ATTR_COLD;
+
+ 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..087780f86cd
--- /dev/null
+++ b/src/devices/bus/vme/mvme180.cpp
@@ -0,0 +1,129 @@
+// 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);
+ m_cpu->set_cmmu_code([this](u32 const address) -> mc88200_device & { return *m_mmu[0]; });
+ m_cpu->set_cmmu_data([this](u32 const address) -> mc88200_device & { return *m_mmu[1]; });
+
+ MC88200(config, m_mmu[0], 40_MHz_XTAL / 2, 0x7e).set_mbus(m_cpu, AS_PROGRAM);
+ MC88200(config, m_mmu[1], 40_MHz_XTAL / 2, 0x7f).set_mbus(m_cpu, AS_PROGRAM);
+
+ 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..6e035fe18cd
--- /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 ATTR_COLD;
+ virtual void device_add_mconfig(machine_config &config) override ATTR_COLD;
+ virtual ioport_constructor device_input_ports() const override ATTR_COLD;
+ virtual void device_start() override ATTR_COLD;
+ virtual void device_reset() override ATTR_COLD;
+
+private:
+ void cpu_mem(address_map &map) ATTR_COLD;
+
+ 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..ef098c64d46
--- /dev/null
+++ b/src/devices/bus/vme/mvme181.cpp
@@ -0,0 +1,155 @@
+// 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 (ACCESSING_BITS_24_31)
+ {
+ if (m_rtc->ceo_r())
+ data = (data & 0x00ffffffU) | u32(m_rtc->read(offset >> 2)) << 24;
+ else
+ m_rtc->read(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);
+ m_cpu->set_cmmu_code([this](u32 const address) -> mc88200_device & { return *m_mmu[0]; });
+ m_cpu->set_cmmu_data([this](u32 const address) -> mc88200_device & { return *m_mmu[1]; });
+
+ MC88200(config, m_mmu[0], 40_MHz_XTAL / 2, 0x7e).set_mbus(m_cpu, AS_PROGRAM);
+ MC88200(config, m_mmu[1], 40_MHz_XTAL / 2, 0x7f).set_mbus(m_cpu, AS_PROGRAM);
+
+ DS1216E(config, m_rtc);
+
+ 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..ccdf1cc4ede
--- /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/ds1215.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 ATTR_COLD;
+ virtual void device_add_mconfig(machine_config &config) override ATTR_COLD;
+ virtual ioport_constructor device_input_ports() const override ATTR_COLD;
+ virtual void device_start() override ATTR_COLD;
+ virtual void device_reset() override ATTR_COLD;
+
+private:
+ void cpu_mem(address_map &map) ATTR_COLD;
+
+ 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<ds1216e_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..7fd1633838f
--- /dev/null
+++ b/src/devices/bus/vme/mvme187.cpp
@@ -0,0 +1,135 @@
+// 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);
+ m_cpu->set_cmmu_code([this](u32 const address) -> mc88200_device & { return *m_mmu[0]; });
+ m_cpu->set_cmmu_data([this](u32 const address) -> mc88200_device & { return *m_mmu[1]; });
+
+ MC88200(config, m_mmu[0], 50_MHz_XTAL / 2, 0x77).set_mbus(m_cpu, AS_PROGRAM);
+ MC88200(config, m_mmu[1], 50_MHz_XTAL / 2, 0x7f).set_mbus(m_cpu, AS_PROGRAM);
+
+ 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..fc2249a3fca
--- /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 ATTR_COLD;
+ virtual void device_add_mconfig(machine_config &config) override ATTR_COLD;
+ virtual ioport_constructor device_input_ports() const override ATTR_COLD;
+ virtual void device_start() override ATTR_COLD;
+ virtual void device_reset() override ATTR_COLD;
+
+private:
+ void cpu_mem(address_map &map) ATTR_COLD;
+
+ 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..b84b863c770
--- /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 ATTR_COLD;
+ virtual void device_add_mconfig(machine_config &config) override ATTR_COLD;
+ virtual ioport_constructor device_input_ports() const override ATTR_COLD;
+ virtual void device_start() override ATTR_COLD;
+ virtual void device_reset() override ATTR_COLD;
+
+private:
+ void cpu_mem(address_map &map) ATTR_COLD;
+ void cpu_int(address_map &map) ATTR_COLD;
+
+ 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/mvme328.cpp b/src/devices/bus/vme/mvme328.cpp
new file mode 100644
index 00000000000..837031804d4
--- /dev/null
+++ b/src/devices/bus/vme/mvme328.cpp
@@ -0,0 +1,291 @@
+// license:BSD-3-Clause
+// copyright-holders:Patrick Mackinlay
+
+/*
+ * Interphase V/SCSI 4210 Jaguar High-Performance VMEbus Dual SCSI Host Adapter (aka Motorola MVME328 VMEbus Dual SCSI Host Adapter)
+ *
+ * Sources:
+ * - V/SCSI 4210 Jaguar High-Performance VMEbus Dual SCSI Host Adapter System Integration Guide, Interphase Corporation, March 13, 1991 (UG04210-000 REVD)
+ * - MVME328 VMEbus VMEbus Dual SCSI Host Adapter User's Manual (MVME328/D1)
+ *
+ * TODO:
+ * - scsi data transfer and dma
+ * - vme interrupts
+ * - leds
+ * - timer
+ * - smt variant
+ */
+/*
+ * WIP notes
+ * --
+ * configuration block (+0x788 at 0x61ff88 = base 0x61f800)
+ * - product code = "077"
+ * - variation = "0"
+ * - firmware version = "01T"
+ * - firmware date "11 51992"
+ *
+ * LED1 - red/green, board OK (bit 1 in MSR, red indicates reset or failure)
+ * LED2.0 - VMEbus busy (system)
+ * LED2.1 - VMEbus busy (bus master)
+ * LED2.2 - SCSI busy (port 0)
+ * LED2.3 - not used
+ */
+#include "emu.h"
+#include "mvme328.h"
+
+#include "bus/nscsi/hd.h"
+#include "bus/nscsi/tape.h"
+
+//#define VERBOSE (LOG_GENERAL)
+#include "logmacro.h"
+
+DEFINE_DEVICE_TYPE(VME_MVME328, vme_mvme328_device, "mvme328", "Motorola MVME328")
+
+vme_mvme328_device::vme_mvme328_device(machine_config const &mconfig, char const *tag, device_t *owner, u32 clock)
+ : device_t(mconfig, VME_MVME328, tag, owner, clock)
+ , device_vme_card_interface(mconfig, *this)
+ , m_cpu(*this, "cpu")
+ , m_scsi(*this, "scsi%u:7:mb87030", 0U)
+ , m_bram(*this, "buffer_ram")
+ , m_sw1(*this, "SW1")
+ , m_led1(*this, "led1")
+ , m_led2(*this, "led2.%u", 0U)
+ , m_boot(*this, "boot")
+{
+}
+
+ROM_START(mvme328)
+ ROM_REGION16_BE(0x10000, "eprom", 0)
+ ROM_SYSTEM_BIOS(0, "077001t", "Interphase Jaguar 0770 firmware version 01T, 11 51992")
+ ROMX_LOAD("0770k0801t.uk8", 0x0001, 0x8000, CRC(22f0440e) SHA1(37d8039778ec7ef0cb24940eabd45992920975a1), ROM_SKIP(1) | ROM_BIOS(0))
+ ROMX_LOAD("0770k1001t.uk10", 0x0000, 0x8000, CRC(d7d0d4c3) SHA1(5756719bf005e3e26be7bbc8cb1c2f771d260a02), ROM_SKIP(1) | ROM_BIOS(0))
+
+ ROM_SYSTEM_BIOS(1, "077401s", "Interphase Jaguar 0774 firmware version 01S, 07311992")
+ ROMX_LOAD("0774e1501s__9348.ue15", 0x0000, 0x8000, CRC(e614ef1f) SHA1(8bc56ad49989e78682a6d69351e8cf0f2557b311), ROM_SKIP(1) | ROM_BIOS(1))
+ ROMX_LOAD("0774f1501s__9348.uf15", 0x0001, 0x8000, CRC(3c6e8016) SHA1(0a39873b5a17f71db86afcd361141e5b9f6786e9), ROM_SKIP(1) | ROM_BIOS(1))
+ROM_END
+
+static INPUT_PORTS_START(mvme328)
+ PORT_START("SW1")
+ PORT_DIPNAME(0x100, 0x000, "Permit User Access") PORT_DIPLOCATION("SW1:9")
+ PORT_DIPSETTING(0x000, DEF_STR(No))
+ PORT_DIPSETTING(0x100, DEF_STR(Yes))
+ PORT_DIPNAME(0x0f8, 0x000, "Base Address") PORT_DIPLOCATION("SW1:4,5,6,7,8")
+ PORT_DIPSETTING(0x000, "0x0000")
+ PORT_DIPSETTING(0x008, "0x0800")
+ PORT_DIPSETTING(0x010, "0x1000")
+ PORT_DIPSETTING(0x018, "0x1800")
+ PORT_DIPSETTING(0x020, "0x2000")
+ PORT_DIPSETTING(0x028, "0x2800")
+ PORT_DIPSETTING(0x030, "0x3000")
+ PORT_DIPSETTING(0x038, "0x3800")
+ PORT_DIPSETTING(0x040, "0x4000")
+ PORT_DIPSETTING(0x048, "0x4800")
+ PORT_DIPSETTING(0x050, "0x5000")
+ PORT_DIPSETTING(0x058, "0x5800")
+ PORT_DIPSETTING(0x060, "0x6000")
+ PORT_DIPSETTING(0x068, "0x6800")
+ PORT_DIPSETTING(0x070, "0x7000")
+ PORT_DIPSETTING(0x078, "0x7800")
+ PORT_DIPSETTING(0x080, "0x8000")
+ PORT_DIPSETTING(0x088, "0x8800")
+ PORT_DIPSETTING(0x090, "0x9000")
+ PORT_DIPSETTING(0x098, "0x9800")
+ PORT_DIPSETTING(0x0a0, "0xa000")
+ PORT_DIPSETTING(0x0a8, "0xa800")
+ PORT_DIPSETTING(0x0b0, "0xb000")
+ PORT_DIPSETTING(0x0b8, "0xb800")
+ PORT_DIPSETTING(0x0c0, "0xc000")
+ PORT_DIPSETTING(0x0c8, "0xc800")
+ PORT_DIPSETTING(0x0d0, "0xd000")
+ PORT_DIPSETTING(0x0d8, "0xd800")
+ PORT_DIPSETTING(0x0e0, "0xe000")
+ PORT_DIPSETTING(0x0e8, "0xe800")
+ PORT_DIPSETTING(0x0f0, "0xf000")
+ PORT_DIPSETTING(0x0f8, "0xf800")
+ PORT_DIPNAME(0x007, 0x007, "SCSI Port 0 ID") PORT_DIPLOCATION("SW1:1,2,3")
+ PORT_DIPSETTING(0x000, "0")
+ PORT_DIPSETTING(0x001, "1")
+ PORT_DIPSETTING(0x002, "2")
+ PORT_DIPSETTING(0x003, "3")
+ PORT_DIPSETTING(0x004, "4")
+ PORT_DIPSETTING(0x005, "5")
+ PORT_DIPSETTING(0x006, "6")
+ PORT_DIPSETTING(0x007, "7")
+
+ PORT_START("Priority")
+ PORT_CONFNAME(0x03, 0x03, "VMEbus Request Priority")
+ PORT_CONFSETTING(0x00, "0")
+ PORT_CONFSETTING(0x01, "1")
+ PORT_CONFSETTING(0x02, "2")
+ PORT_CONFSETTING(0x03, "3")
+INPUT_PORTS_END
+
+const tiny_rom_entry *vme_mvme328_device::device_rom_region() const
+{
+ return ROM_NAME(mvme328);
+}
+
+ioport_constructor vme_mvme328_device::device_input_ports() const
+{
+ return INPUT_PORTS_NAME(mvme328);
+}
+
+void vme_mvme328_device::device_start()
+{
+ m_led1.resolve();
+ m_led2.resolve();
+
+ m_timer = timer_alloc(FUNC(vme_mvme328_device::timer), this);
+
+ save_item(NAME(m_ctl));
+ save_item(NAME(m_sts));
+
+ m_ctl = 0;
+}
+
+void vme_mvme328_device::device_reset()
+{
+ m_timer->adjust(attotime::never);
+
+ m_boot.select(0);
+
+ // HACK: 0x0700 indicates an original board type?
+ m_sts = (BIT(m_sw1->read(), 0, 3) << 12) | 0x0700;
+}
+
+static void scsi_devices(device_slot_interface &device)
+{
+ device.option_add("harddisk", NSCSI_HARDDISK);
+ device.option_add("tape", NSCSI_TAPE);
+}
+
+void vme_mvme328_device::device_add_mconfig(machine_config &config)
+{
+ M68000(config, m_cpu, 24_MHz_XTAL / 2); // HD68HC000P12
+ m_cpu->set_addrmap(AS_PROGRAM, &vme_mvme328_device::cpu_mem);
+
+ NSCSI_BUS(config, "scsi0");
+ 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("mb87030", MB87030).machine_config(
+ [this](device_t *device)
+ {
+ mb87030_device &mb87030(downcast<mb87030_device &>(*device));
+
+ mb87030.set_clock(8'000'000);
+ mb87030.out_irq_callback().set(
+ [this](int state)
+ {
+ if (state)
+ m_sts |= 1U << 6;
+ else
+ m_sts &= ~(1U << 6);
+
+ m_cpu->set_input_line(INPUT_LINE_IRQ6, state);
+ });
+ });
+
+ NSCSI_BUS(config, "scsi1");
+ 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("mb87030", MB87030).machine_config(
+ [this](device_t *device)
+ {
+ mb87030_device &mb87030(downcast<mb87030_device &>(*device));
+
+ mb87030.set_clock(8'000'000);
+ mb87030.out_irq_callback().set(
+ [this](int state)
+ {
+ if (state)
+ m_sts |= 1U << 5;
+ else
+ m_sts &= ~(1U << 5);
+
+ m_cpu->set_input_line(INPUT_LINE_IRQ5, state);
+ });
+ });
+
+ // TODO: VLSI VGC7224-0420 II-DMA-50M
+}
+
+void vme_mvme328_device::cpu_mem(address_map &map)
+{
+ map(0x00'0000, 0x00'ffff).view(m_boot);
+ m_boot[0](0x00'0000, 0x00'ffff).rom().region("eprom", 0);
+ m_boot[1](0x00'0000, 0x00'3fff).ram();
+
+ map(0x20'0000, 0x20'ffff).rom().region("eprom", 0);
+ map(0x60'0000, 0x61'ffff).ram().share("buffer_ram");
+ map(0x68'0000, 0x69'ffff).noprw(); // event ram?
+
+ map(0x80'0000, 0x80'0001).r(FUNC(vme_mvme328_device::sts_r));
+ map(0xa0'0000, 0xa0'0001).rw(FUNC(vme_mvme328_device::ctl_r), FUNC(vme_mvme328_device::ctl_w));
+
+ map(0xc0'0000, 0xc0'001f).m(m_scsi[0], FUNC(mb87030_device::map)).umask16(0x00ff);
+ map(0xc0'8000, 0xc0'801f).m(m_scsi[1], FUNC(mb87030_device::map)).umask16(0x00ff);
+
+ // 0xc0'c000 = smt version switches?
+
+ map(0xc1'0000, 0xc1'0001).lw16([this](u16 data) { m_timer->adjust(attotime::from_msec(10)); }, "timer");
+}
+
+void vme_mvme328_device::timer(int param)
+{
+ m_cpu->set_input_line(INPUT_LINE_IRQ1, HOLD_LINE);
+}
+
+u16 vme_mvme328_device::sts_r()
+{
+ LOG("sts_r 0x%04x (%s)\n", m_sts, machine().describe_context());
+
+ // .sss .??? iiii iiii
+ // sss scsi id
+ // ??? xor with same bits from 90'0000?, board type?
+ // iii irq state?
+
+ return m_sts;
+}
+
+u16 vme_mvme328_device::ctl_r()
+{
+ return m_ctl;
+}
+
+void vme_mvme328_device::ctl_w(u16 data)
+{
+ LOG("ctl_w 0x%04x (%s)\n", data, machine().describe_context());
+
+ // bit 10: enable scratchpad ram?
+ if (BIT(data, 10))
+ m_boot.select(1);
+
+ // bit 14: enable VME access?
+ if (BIT(data, 14) && !BIT(m_ctl, 14))
+ {
+ unsigned const sw1 = m_sw1->read();
+
+ // share last 2k of buffer RAM in VME supervisor short space (a16, privileged)
+ offs_t const base = BIT(sw1, 3, 5) * 0x800U;
+ vme_space(vme::AM_2d).install_ram(base, base + 0x7ffU, &m_bram[0xfc00]);
+
+ // optionally share in user short space (a16, non-privileged)
+ if (BIT(sw1, 8))
+ vme_space(vme::AM_29).install_ram(base, base + 0x7ffU, &m_bram[0xfc00]);
+ }
+
+ // bit 15: led?
+
+ m_ctl = data;
+}
diff --git a/src/devices/bus/vme/mvme328.h b/src/devices/bus/vme/mvme328.h
new file mode 100644
index 00000000000..6b82809fc45
--- /dev/null
+++ b/src/devices/bus/vme/mvme328.h
@@ -0,0 +1,56 @@
+// license:BSD-3-Clause
+// copyright-holders:Patrick Mackinlay
+
+#ifndef MAME_BUS_VME_MVME328_H
+#define MAME_BUS_VME_MVME328_H
+
+#pragma once
+
+#include "cpu/m68000/m68000.h"
+#include "machine/mb87030.h"
+
+#include "bus/vme/vme.h"
+
+class vme_mvme328_device
+ : public device_t
+ , public device_vme_card_interface
+{
+public:
+ vme_mvme328_device(machine_config const &mconfig, char const *tag, device_t *owner, u32 clock);
+
+protected:
+ virtual const tiny_rom_entry *device_rom_region() const override ATTR_COLD;
+ virtual void device_add_mconfig(machine_config &config) override ATTR_COLD;
+ virtual ioport_constructor device_input_ports() const override ATTR_COLD;
+ virtual void device_start() override ATTR_COLD;
+ virtual void device_reset() override ATTR_COLD;
+
+private:
+ void cpu_mem(address_map &map) ATTR_COLD;
+ void cpu_int(address_map &map) ATTR_COLD;
+
+ void timer(int param);
+
+ u16 sts_r();
+ u16 ctl_r();
+ void ctl_w(u16 data);
+
+ required_device<m68000_device> m_cpu;
+ required_device_array<mb87030_device, 2> m_scsi;
+
+ required_shared_ptr<u16> m_bram;
+
+ required_ioport m_sw1;
+ output_finder<> m_led1;
+ output_finder<4> m_led2;
+
+ emu_timer *m_timer;
+ memory_view m_boot;
+
+ u16 m_sts;
+ u16 m_ctl;
+};
+
+DECLARE_DEVICE_TYPE(VME_MVME328, vme_mvme328_device)
+
+#endif // MAME_BUS_VME_MVME328_H
diff --git a/src/devices/bus/vme/vme_mvme350.cpp b/src/devices/bus/vme/mvme350.cpp
index b433620b6fe..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"
@@ -175,14 +165,14 @@ void vme_mvme350_card_device::mvme350_mem(address_map &map)
map(0x060000, 0x06001f).ram(); /* Area is cleared on start */
map(0x080000, 0x080035).rw("pit", FUNC(pit68230_device::read), FUNC(pit68230_device::write)).umask16(0x00ff); /* PIT ?*/
#endif
-//AM_RANGE(0x100000, 0xfeffff) AM_READWRITE(vme_a24_r, vme_a24_w) /* VMEbus Rev B addresses (24 bits) - not verified */
-//AM_RANGE(0xff0000, 0xffffff) AM_READWRITE(vme_a16_r, vme_a16_w) /* VMEbus Rev B addresses (16 bits) - not verified */
+//map(0x100000, 0xfeffff).rw(FUNC(vme_mvme350_card_device::vme_a24_r), FUNC(vme_mvme350_card_device::vme_a24_w)); /* VMEbus Rev B addresses (24 bits) - not verified */
+//map(0xff0000, 0xffffff).rw(FUNC(vme_mvme350_card_device::vme_a16_r), FUNC(vme_mvme350_card_device::vme_a16_w)); /* VMEbus Rev B addresses (16 bits) - not verified */
}
ROM_START( mvme350 )
- ROM_REGION (0x20000, MVME350_ROM, 0)
- ROM_LOAD16_BYTE ("mvme350u40v2.3.bin", 0x0001, 0x4000, CRC (bcef82ef) SHA1 (e6fdf26e4714cbaeb3e97d7b5acf02d64d8ad744))
- ROM_LOAD16_BYTE ("mvme350u47v2.3.bin", 0x0000, 0x4000, CRC (582ce095) SHA1 (d0929dbfeb0cfda63df6b5bc29ee27fbf665def7))
+ ROM_REGION16_BE(0x20000, MVME350_ROM, 0)
+ ROM_LOAD16_BYTE("mvme350u40v2.3.bin", 0x0000, 0x4000, CRC (bcef82ef) SHA1 (e6fdf26e4714cbaeb3e97d7b5acf02d64d8ad744))
+ ROM_LOAD16_BYTE("mvme350u47v2.3.bin", 0x0001, 0x4000, CRC (582ce095) SHA1 (d0929dbfeb0cfda63df6b5bc29ee27fbf665def7))
ROM_END
//-------------------------------------------------
@@ -224,7 +214,6 @@ vme_mvme350_card_device::vme_mvme350_card_device(const machine_config &mconfig,
void vme_mvme350_card_device::device_start()
{
LOG("%s %s\n", tag(), FUNCNAME);
- set_vme_device();
/* Setup r/w handlers for shared memory area */
#if 0
@@ -252,12 +241,12 @@ void vme_mvme350_card_device::device_reset()
}
#if 0
-READ16_MEMBER (vme_mvme350_card_device::read16){
+uint16_t vme_mvme350_card_device::read16(){
LOG("%s()\n", FUNCNAME);
return (uint8_t) 0;
}
-WRITE16_MEMBER (vme_mvme350_card_device::write16){
+void vme_mvme350_card_device::write16(uint16_t data){
LOG("%s()\n", FUNCNAME);
}
#endif
diff --git a/src/devices/bus/vme/vme_mvme350.h b/src/devices/bus/vme/mvme350.h
index c140a5b9fc3..2cd391ef437 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
@@ -15,21 +15,21 @@ public:
vme_mvme350_card_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
// Shared memory methods to be exported to the VME bus
-// virtual DECLARE_READ16_MEMBER (read16) override;
-// virtual DECLARE_WRITE16_MEMBER (write16) override;
+// virtual uint16_t read16() override;
+// virtual void write16(uint16_t data) override;
protected:
vme_mvme350_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;
+ virtual void device_start() override ATTR_COLD;
+ virtual void device_reset() override ATTR_COLD;
// optional information overrides
- virtual void device_add_mconfig(machine_config &config) override;
- virtual const tiny_rom_entry *device_rom_region() const override;
+ virtual void device_add_mconfig(machine_config &config) override ATTR_COLD;
+ virtual const tiny_rom_entry *device_rom_region() const override ATTR_COLD;
private:
- void mvme350_mem(address_map &map);
+ void mvme350_mem(address_map &map) ATTR_COLD;
};
-#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..086111f30a7
--- /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 ATTR_COLD;
+ virtual void device_add_mconfig(machine_config &config) override ATTR_COLD;
+ virtual ioport_constructor device_input_ports() const override ATTR_COLD;
+ virtual void device_start() override ATTR_COLD;
+ virtual void device_reset() override ATTR_COLD;
+
+private:
+ void mzr8105_mem(address_map &map) ATTR_COLD;
+ 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 133c17e9f49..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_new_device& sio0(UPD7201_NEW(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_NEW(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_new_device::rxb_w));
- rs232p1.cts_handler().set("sio0", FUNC(upd7201_new_device::ctsb_w));
-
- am9513_device &stc(AM9513(config, "stc", 4_MHz_XTAL));
- stc.out1_cb().set("sio0", FUNC(upd7201_new_device::rxca_w));
- stc.out1_cb().append("sio0", FUNC(upd7201_new_device::txca_w));
- stc.out2_cb().set("sio0", FUNC(upd7201_new_device::rxcb_w));
- stc.out2_cb().append("sio0", FUNC(upd7201_new_device::txcb_w));
- stc.out3_cb().set("sio1", FUNC(upd7201_new_device::rxca_w));
- stc.out3_cb().append("sio1", FUNC(upd7201_new_device::txca_w));
- stc.out4_cb().set("sio1", FUNC(upd7201_new_device::rxcb_w));
- stc.out4_cb().append("sio1", FUNC(upd7201_new_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);
}
@@ -168,27 +158,23 @@ vme_mzr8300_card_device::vme_mzr8300_card_device(const machine_config &mconfig,
void vme_mzr8300_card_device::device_start()
{
LOG("%s %s\n", tag(), FUNCNAME);
- set_vme_device();
/* 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(FUNC(z80sio_device::db_r), subdevice<z80sio_device>("sio0")),
- write8smo_delegate(FUNC(z80sio_device::db_w), subdevice<z80sio_device>("sio0")), 0x00ff);
- m_vme->install_device(vme_device::A16_SC, base + 2, base + 3, // Channel B - Control
- read8smo_delegate(FUNC(z80sio_device::cb_r), subdevice<z80sio_device>("sio0")),
- write8smo_delegate(FUNC(z80sio_device::cb_w), subdevice<z80sio_device>("sio0")), 0x00ff);
- m_vme->install_device(vme_device::A16_SC, base + 4, base + 5, // Channel A - Data
- read8smo_delegate(FUNC(z80sio_device::da_r), subdevice<z80sio_device>("sio0")),
- write8smo_delegate(FUNC(z80sio_device::da_w), subdevice<z80sio_device>("sio0")), 0x00ff);
- m_vme->install_device(vme_device::A16_SC, base + 6, base + 7, // Channel A - Control
- read8smo_delegate(FUNC(z80sio_device::ca_r), subdevice<z80sio_device>("sio0")),
- write8smo_delegate(FUNC(z80sio_device::ca_w), subdevice<z80sio_device>("sio0")), 0x00ff);
- m_vme->install_device(vme_device::A16_SC, base + 0x10, base + 0x13, // Am9513
- read8sm_delegate(FUNC(am9513_device::read8), subdevice<am9513_device>("stc")),
- write8sm_delegate(FUNC(am9513_device::write8), subdevice<am9513_device>("stc")), 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()
@@ -197,12 +183,12 @@ void vme_mzr8300_card_device::device_reset()
}
#if 0
-READ8_MEMBER (vme_mzr8300_card_device::read8){
+uint8_t vme_mzr8300_card_device::read8(offs_t offset){
LOG("%s()\n", FUNCNAME);
return (uint8_t) 0;
}
-WRITE8_MEMBER (vme_mzr8300_card_device::write8){
+void vme_mzr8300_card_device::write8(offs_t offset, uint8_t data){
LOG("%s()\n", FUNCNAME);
}
#endif
diff --git a/src/devices/bus/vme/vme_mzr8300.h b/src/devices/bus/vme/mzr8300.h
index 6d105335276..e619b9f719b 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)
@@ -14,17 +16,21 @@ class vme_mzr8300_card_device : public device_t, public device_vme_card_interfac
public:
vme_mzr8300_card_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
-// virtual DECLARE_READ8_MEMBER (read8) override;
-// virtual DECLARE_WRITE8_MEMBER (write8) override;
+// virtual uint8_t read8(offs_t offset) override;
+// virtual void write8(offs_t offset, uint8_t data) override;
protected:
vme_mzr8300_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;
+ virtual void device_start() override ATTR_COLD;
+ virtual void device_reset() override ATTR_COLD;
// optional information overrides
- virtual void device_add_mconfig(machine_config &config) override;
+ virtual void device_add_mconfig(machine_config &config) override ATTR_COLD;
+
+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/smvme2000.cpp b/src/devices/bus/vme/smvme2000.cpp
new file mode 100644
index 00000000000..76948574f74
--- /dev/null
+++ b/src/devices/bus/vme/smvme2000.cpp
@@ -0,0 +1,138 @@
+// license:BSD-3-Clause
+// copyright-holders:Patrick Mackinlay
+
+/*
+ * Signetics SMVME2000 VMEbus CPU Module
+ *
+ * Probably also sold as the Motorola MVME115M with different firmware, 68010 and MMU.
+ *
+ * Sources:
+ * - http://bitsavers.org/components/signetics/_dataBooks/1986_Signetics_Microprocessor.pdf
+ *
+ * TODO:
+ * - interrupts and configuration
+ * - VME interface
+ * - MMU
+ */
+
+#include "emu.h"
+#include "smvme2000.h"
+
+#define VERBOSE 0
+#include "logmacro.h"
+
+DEFINE_DEVICE_TYPE(VME_SMVME2000, vme_smvme2000_card_device, "smvme2000", "Signetics SMVME2000")
+
+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")
+ //, m_mmu(*this, "mmu")
+ , m_duart(*this, "duart")
+ , m_pit(*this, "pit")
+ , m_serial(*this, "serial%u", 0U)
+ , m_fail(*this, "fail")
+ , m_eprom(*this, "eprom")
+ , m_ram(*this, "ram")
+{
+}
+
+ROM_START(smvme2000)
+ ROM_REGION16_BE(0x10000, "eprom", 0)
+ ROM_SYSTEM_BIOS(0, "v11", "SIGbug Version 1.1 Copyright 1983 Signetics")
+ ROMX_LOAD("sigbug__1.bin", 0x0000, 0x4000, CRC(ae23c2c3) SHA1(da422ca03ac77d9aed2067f1099ec0fb96939fc8), ROM_SKIP(1) | ROM_BIOS(0))
+ ROMX_LOAD("sigbug__2.bin", 0x0001, 0x4000, CRC(e39bd1db) SHA1(2f610170f118c74477f4586e19aee0fc63803e17), ROM_SKIP(1) | ROM_BIOS(0))
+ ROMX_LOAD("sigbug__3.bin", 0x8000, 0x4000, CRC(182998ef) SHA1(ecf980b7dd8bd0286f002b31cd726798f84a2267), ROM_SKIP(1) | ROM_BIOS(0))
+ ROMX_LOAD("sigbug__4.bin", 0x8001, 0x4000, CRC(f0e25380) SHA1(78427f7b9a6f676945c2cdb90632a16a619c83f9), ROM_SKIP(1) | ROM_BIOS(0))
+ROM_END
+
+static INPUT_PORTS_START(smvme2000)
+INPUT_PORTS_END
+
+const tiny_rom_entry *vme_smvme2000_card_device::device_rom_region() const
+{
+ return ROM_NAME(smvme2000);
+}
+
+ioport_constructor vme_smvme2000_card_device::device_input_ports() const
+{
+ return INPUT_PORTS_NAME(smvme2000);
+}
+
+void vme_smvme2000_card_device::device_start()
+{
+ m_fail.resolve();
+}
+
+void vme_smvme2000_card_device::device_reset()
+{
+ /*
+ * FIXME: EPROM is mapped at the start of memory during reset to allow the
+ * CPU to fetch the stack pointer and initial PC. The exact mechanism used
+ * is unknown; current emulation unmaps the EPROM and maps RAM when the last
+ * two bytes of the reset vector are fetched.
+ */
+ m_cpu->space(AS_PROGRAM).install_rom(0, m_eprom.bytes() - 1, m_eprom.target());
+
+ m_boot = m_cpu->space(AS_PROGRAM).install_read_tap(0x000006, 0x000007, "boot",
+ [this](offs_t offset, u16 &data, u16 mem_mask)
+ {
+ if (!machine().side_effects_disabled())
+ {
+ m_cpu->space(AS_PROGRAM).unmap_readwrite(0, m_eprom.bytes() - 1);
+ m_cpu->space(AS_PROGRAM).install_ram(0, m_ram.bytes() - 1, m_ram.target());
+
+ m_boot.remove();
+ }
+ });
+}
+
+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_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
+
+ PIT68230(config, m_pit, 0);
+ m_pit->pc_out_callback().set(
+ [this](u8 data)
+ {
+ m_fail = BIT(data, 4);
+ });
+ m_pit->port_irq_callback().set_inputline(m_cpu, M68K_IRQ_5); // TODO: verify destination
+
+ RS232_PORT(config, m_serial[0], default_rs232_devices, nullptr);
+ 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_smvme2000_card_device::cpu_mem(address_map &map)
+{
+ map(0x000000, 0x000fff).ram().share("ram");
+
+ //map(0x010000, 0xf6ffff); // VMEbus memory address space
+ map(0xf70000, 0xf7ffff).rom().region("eprom", 0);
+ //map(0xf80000, 0xf8003f); // MMU
+ map(0xf81000, 0xf8103f).rw(m_pit, FUNC(pit68230_device::read), FUNC(pit68230_device::write)).umask16(0x00ff);
+ map(0xf82000, 0xf8201f).rw(m_duart, FUNC(scn2681_device::read), FUNC(scn2681_device::write)).umask16(0x00ff);
+ //map(0xf90000, 0xf9ffff).mirror(0x060000); // VMEbus short I/O space
+}
+
+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); }));
+ 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); })); // TODO: m_pit->irq_piack()?
+ 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/smvme2000.h b/src/devices/bus/vme/smvme2000.h
new file mode 100644
index 00000000000..745dd9eb17c
--- /dev/null
+++ b/src/devices/bus/vme/smvme2000.h
@@ -0,0 +1,54 @@
+// license:BSD-3-Clause
+// copyright-holders:Patrick Mackinlay
+
+#ifndef MAME_BUS_VME_SMVME2000_H
+#define MAME_BUS_VME_SMVME2000_H
+
+#pragma once
+
+#include "bus/vme/vme.h"
+
+#include "cpu/m68000/m68000.h"
+//#include "machine/m68451.h"
+#include "machine/mc68681.h"
+#include "machine/68230pit.h"
+
+#include "bus/rs232/rs232.h"
+
+class vme_smvme2000_card_device
+ : public device_t
+ , public device_vme_card_interface
+{
+public:
+ vme_smvme2000_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 ATTR_COLD;
+ virtual void device_add_mconfig(machine_config &config) override ATTR_COLD;
+ virtual ioport_constructor device_input_ports() const override ATTR_COLD;
+ virtual void device_start() override ATTR_COLD;
+ virtual void device_reset() override ATTR_COLD;
+
+private:
+ void cpu_mem(address_map &map) ATTR_COLD;
+ void cpu_int(address_map &map) ATTR_COLD;
+
+ required_device<m68000_device> m_cpu;
+ //optional_device<m68451_device> m_mmu;
+ required_device<scn2681_device> m_duart;
+ required_device<pit68230_device> m_pit;
+
+ required_device_array<rs232_port_device, 2> m_serial;
+
+ output_finder<> m_fail;
+
+ required_region_ptr<u16> m_eprom;
+ required_shared_ptr<u16> m_ram;
+
+ memory_passthrough_handler m_boot;
+};
+
+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..160a14ad3e8
--- /dev/null
+++ b/src/devices/bus/vme/sys68k_cpu1.cpp
@@ -0,0 +1,671 @@
+// 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_NO_SOUND | MACHINE_NOT_WORKING )
+//COMP( 1989, fccpu6a, 0, 0, fccpu6a, force68k, vme_sys68k_cpu1_card_device, empty_init, "Force Computers GmbH", "SYS68K/CPU-6a", MACHINE_NO_SOUND | MACHINE_NOT_WORKING )
+//COMP( 1989, fccpu6v, 0, 0, fccpu6v, force68k, vme_sys68k_cpu1_card_device, empty_init, "Force Computers GmbH", "SYS68K/CPU-6v", MACHINE_NO_SOUND | MACHINE_NOT_WORKING )
+//COMP( 1989, fccpu6va, 0, 0, fccpu6va, force68k, vme_sys68k_cpu1_card_device, empty_init, "Force Computers GmbH", "SYS68K/CPU-6va", MACHINE_NO_SOUND | MACHINE_NOT_WORKING )
+//COMP( 1989, fccpu6vb, 0, 0, fccpu6vb, force68k, vme_sys68k_cpu1_card_device, empty_init, "Force Computers GmbH", "SYS68K/CPU-6vb", MACHINE_NO_SOUND | MACHINE_NOT_WORKING )
diff --git a/src/devices/bus/vme/sys68k_cpu1.h b/src/devices/bus/vme/sys68k_cpu1.h
new file mode 100644
index 00000000000..4843f29b81f
--- /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 ATTR_COLD;
+ virtual void device_add_mconfig(machine_config &config) override ATTR_COLD;
+ virtual ioport_constructor device_input_ports() const override ATTR_COLD;
+ virtual void device_start() override ATTR_COLD;
+ virtual void device_reset() override ATTR_COLD;
+
+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) ATTR_COLD;
+
+ 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 d9096ca13e2..2273a57920d 100644
--- a/src/devices/bus/vme/vme_fccpu20.cpp
+++ b/src/devices/bus/vme/sys68k_cpu20.cpp
@@ -183,58 +183,48 @@
* - 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__)
-#ifdef _MSC_VER
-#define FUNCNAME __func__
-#else
-#define FUNCNAME __PRETTY_FUNCTION__
-#endif
+
//**************************************************************************
// 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));
@@ -246,34 +236,33 @@ void vme_fccpu20_device::cpu20_mem(address_map &map)
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_STARTBITS", 0xff, RS232_STARTBITS_1 )
DEVICE_INPUT_DEFAULTS( "RS232_DATABITS", 0xff, RS232_DATABITS_7 )
DEVICE_INPUT_DEFAULTS( "RS232_PARITY", 0xff, RS232_PARITY_NONE )
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("bim irq", [this](offs_t offset) -> u16 { return m_bim->iack(offset+1); });
+ 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 */
@@ -320,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);
}
@@ -377,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")
@@ -386,155 +375,134 @@ 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("%s\n", FUNCNAME);
+ 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("%s %s\n", tag, FUNCNAME);
+ 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("%s %s\n", tag, FUNCNAME);
+ 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("%s %s\n", tag, FUNCNAME);
+ 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("%s %s\n", tag, FUNCNAME);
+ 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("%s %s\n", tag, FUNCNAME);
+ 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("%s %s\n", tag, FUNCNAME);
+ 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("%s %s\n", tag, FUNCNAME);
+ LOG("vme_sys68k_cpu21yb_card_device ctor: %s\n", tag);
}
-/* Start it up */
-void vme_fccpu20_device::device_start()
+void vme_sys68k_cpu20_card_device_base::device_start()
{
- LOG("%s\n", FUNCNAME);
+ LOG("vme_sys68k_cpu20_card_device::device_start\n");
- set_vme_device();
-
- 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
- read8_delegate(FUNC(z80sio_device::db_r), subdevice<z80sio_device>("pit")), write8_delegate(FUNC(z80sio_device::db_w), subdevice<z80sio_device>("pit")), 0x00ff);
+ read8_delegate(*subdevice<z80sio_device>("pit"), FUNC(z80sio_device::db_r)), write8_delegate(*subdevice<z80sio_device>("pit"), FUNC(z80sio_device::db_w)), 0x00ff);
m_vme->install_device(base + 2, base + 3, // Channel B - Control
- read8_delegate(FUNC(z80sio_device::cb_r), subdevice<z80sio_device>("pit")), write8_delegate(FUNC(z80sio_device::cb_w), subdevice<z80sio_device>("pit")), 0x00ff);
+ 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_sys68k_cpu20_card_device_base::grant_bus), this);
}
-enum
+void vme_sys68k_cpu20_card_device_base::device_reset()
{
- TIMER_ID_BUS_GRANT
-};
-
-void vme_fccpu20_device::device_reset()
-{
- LOG("%s\n", FUNCNAME);
+ 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 = timer_alloc(TIMER_ID_BUS_GRANT);
- m_arbiter_start->adjust(attotime::from_msec(10), TIMER_ID_BUS_GRANT, attotime::never);
+ 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();
+ }
+ });
}
//-------------------------------------------------
-// device_timer - handler timer events
+// grant_bus
//-------------------------------------------------
-void vme_fccpu20_device::device_timer (emu_timer &timer, device_timer_id id, int32_t param, void *ptr)
-{
- switch(id)
- {
- case TIMER_ID_BUS_GRANT:
- m_pit->h1_w(ASSERT_LINE); // Grant bus always
- break;
- default:
- LOG("Unhandled Timer ID %d\n", id);
- break;
- }
-}
-
-/* Boot vector handler, the PCB hardwires the first 8 bytes from 0xff800000 to 0x0 at reset*/
-READ32_MEMBER (vme_fccpu20_device::bootvect_r)
-{
- LOG("%s\n", FUNCNAME);
- return m_sysrom[offset];
-}
-WRITE32_MEMBER (vme_fccpu20_device::bootvect_w)
+TIMER_CALLBACK_MEMBER(vme_sys68k_cpu20_card_device_base::grant_bus)
{
- LOG("%s\n", FUNCNAME);
- m_sysram[offset % ARRAY_LENGTH(m_sysram)] &= ~mem_mask;
- m_sysram[offset % ARRAY_LENGTH(m_sysram)] |= (data & mem_mask);
- m_sysrom = &m_sysram[0]; // redirect all upcoming accesses to masking RAM until reset.
+ m_pit->h1_w(ASSERT_LINE); // Grant bus always
}
-WRITE_LINE_MEMBER(vme_fccpu20_device::bim_irq_callback)
+void vme_sys68k_cpu20_card_device_base::bim_irq_callback(int state)
{
- LOGINT("%s(%02x)\n", FUNCNAME, state);
+ LOGINT("vme_sys68k_cpu20_card_device_base::bim_irq_callback(%02x)\n", state);
- bim_irq_state = state;
- bim_irq_level = m_bim->get_irq_level();
- LOGINT(" - BIM irq level %s\n", bim_irq_level == CLEAR_LINE ? "Cleared" : "Asserted");
+ m_bim_irq_state = state;
+ m_bim_irq_level = m_bim->get_irq_level();
+ LOGINT(" - BIM irq level %s\n", m_bim_irq_level == CLEAR_LINE ? "Cleared" : "Asserted");
update_irq_to_maincpu();
}
-void vme_fccpu20_device::update_irq_to_maincpu()
+void vme_sys68k_cpu20_card_device_base::update_irq_to_maincpu()
{
- LOGINT("%s()\n", FUNCNAME);
- LOGINT(" - bim_irq_level: %02x\n", bim_irq_level);
- LOGINT(" - bim_irq_state: %02x\n", bim_irq_state);
- switch (bim_irq_level & 0x07)
+ 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)
{
- case 1: m_maincpu->set_input_line(M68K_IRQ_1, bim_irq_state); break;
- case 2: m_maincpu->set_input_line(M68K_IRQ_2, bim_irq_state); break;
- case 3: m_maincpu->set_input_line(M68K_IRQ_3, bim_irq_state); break;
- case 4: m_maincpu->set_input_line(M68K_IRQ_4, bim_irq_state); break;
- case 5: m_maincpu->set_input_line(M68K_IRQ_5, bim_irq_state); break;
- case 6: m_maincpu->set_input_line(M68K_IRQ_6, bim_irq_state); break;
- case 7: m_maincpu->set_input_line(M68K_IRQ_7, bim_irq_state); break;
- default: logerror("Programmatic error in %s, please report\n", FUNCNAME);
+ case 1: m_maincpu->set_input_line(M68K_IRQ_1, m_bim_irq_state); break;
+ case 2: m_maincpu->set_input_line(M68K_IRQ_2, m_bim_irq_state); break;
+ case 3: m_maincpu->set_input_line(M68K_IRQ_3, m_bim_irq_state); break;
+ case 4: m_maincpu->set_input_line(M68K_IRQ_4, m_bim_irq_state); break;
+ 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_sys68k_cpu20_card_device_base::update_irq_to_maincpu, please report\n");
}
}
@@ -558,26 +526,26 @@ void vme_fccpu20_device::update_irq_to_maincpu()
#define BR8N38400 0x08
#define FORCEBUG 0x30
-READ8_MEMBER (vme_fccpu20_device::pita_r)
+uint8_t vme_sys68k_cpu20_card_device_base::pita_r()
{
- LOG("%s\n", FUNCNAME);
+ LOG("vme_sys68k_cpu20_card_device::pita_r\n");
return FORCEBUG | BR7N9600;
}
/* Enabling/Disabling of VME IRQ 1-7 */
-READ8_MEMBER (vme_fccpu20_device::pitb_r)
+uint8_t vme_sys68k_cpu20_card_device_base::pitb_r()
{
- LOG("%s\n", FUNCNAME);
+ 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 */
-READ8_MEMBER (vme_fccpu20_device::pitc_r)
+uint8_t vme_sys68k_cpu20_card_device_base::pitc_r()
{
uint8_t board_id = 0;
- LOG("%s Board id:%02x\n", FUNCNAME, m_board_id);
+ LOG("vme_sys68k_cpu20_card_device_base::pitc_r Board id:%02x\n", m_board_id);
switch (m_board_id)
{
@@ -592,46 +560,26 @@ READ8_MEMBER (vme_fccpu20_device::pitc_r)
case cpu21:
board_id = CPU21;
break;
- default: logerror("Attempt to set unknown board type %02x, defaulting to CPU20\n", board_id);
+ default: logerror("Attempted to set unknown board type %02x, defaulting to CPU20\n", board_id);
board_id = CPU20;
+ break;
}
return board_id | 0xbf;
}
/* 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("%s\n", FUNCNAME);
-
- 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("Attempt 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..25f04980c29
--- /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 ATTR_COLD;
+ virtual void device_reset() override ATTR_COLD;
+
+ // optional information overrides
+ virtual void device_add_mconfig(machine_config &config) override ATTR_COLD;
+ virtual const tiny_rom_entry *device_rom_region() const override ATTR_COLD;
+
+ 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) ATTR_COLD;
+ void cpu_space_map(address_map &map) ATTR_COLD;
+
+ 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 ATTR_COLD;
+};
+
+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 ATTR_COLD;
+};
+
+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 ATTR_COLD;
+};
+
+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 ATTR_COLD;
+};
+
+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 ATTR_COLD;
+};
+
+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 ATTR_COLD;
+};
+
+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 ATTR_COLD;
+};
+
+
+#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..711181153d0
--- /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 ATTR_COLD;
+ virtual void device_start() override ATTR_COLD;
+ virtual void device_reset() override ATTR_COLD;
+
+ 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) ATTR_COLD;
+ 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) ATTR_COLD;
+
+ 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 ATTR_COLD;
+ virtual void device_add_mconfig(machine_config &config) override ATTR_COLD;
+};
+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 ATTR_COLD;
+ virtual void device_add_mconfig(machine_config &config) override ATTR_COLD;
+};
+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 ATTR_COLD;
+ virtual void device_add_mconfig(machine_config &config) override ATTR_COLD;
+};
+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 ATTR_COLD;
+ virtual void device_add_mconfig(machine_config &config) override ATTR_COLD;
+};
+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 ATTR_COLD;
+ virtual void device_add_mconfig(machine_config &config) override ATTR_COLD;
+};
+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 ATTR_COLD;
+ virtual void device_add_mconfig(machine_config &config) override ATTR_COLD;
+};
+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 ATTR_COLD;
+ virtual void device_add_mconfig(machine_config &config) override ATTR_COLD;
+};
+
+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 7c76080caea..184cc5d0643 100644
--- a/src/devices/bus/vme/vme_fcscsi.cpp
+++ b/src/devices/bus/vme/sys68k_iscsi.cpp
@@ -91,7 +91,7 @@
* ----------------------------------------------------------
* 000000 - 000007 Initialisation vectors from system EPROM
* 000008 - 001FFF Local SRAM
- * 002000 - 01FFFF Dynamic Dual Port RAM VME bus accessable
+ * 002000 - 01FFFF Dynamic Dual Port RAM VME bus accessible
* C40000 - C4001F SCSIbus controller
* C80000 - C800FF DMAC
* CC0000 - CC0007 FDC
@@ -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);
-// AM_RANGE (0xc40000, 0xc4001f) AM_DEVREADWRITE8("scsi", ncr5386_device, read, write, 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("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_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,16 +226,12 @@ 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));
}
-FLOPPY_FORMATS_MEMBER( vme_fcscsi1_card_device::floppy_formats )
- FLOPPY_PC_FORMAT
-FLOPPY_FORMATS_END
-
static void fcscsi_floppies(device_slot_interface &device)
{
device.option_add("525qd", FLOPPY_525_QD);
@@ -256,87 +239,85 @@ 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", vme_fcscsi1_card_device::floppy_formats);
- FLOPPY_CONNECTOR(config, "fdc:1", fcscsi_floppies, "525qd", vme_fcscsi1_card_device::floppy_formats);
- FLOPPY_CONNECTOR(config, "fdc:2", fcscsi_floppies, "525qd", vme_fcscsi1_card_device::floppy_formats);
- FLOPPY_CONNECTOR(config, "fdc:3", fcscsi_floppies, "525qd", vme_fcscsi1_card_device::floppy_formats);
+ 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);
+ FLOPPY_CONNECTOR(config, "fdc:2", fcscsi_floppies, "525qd", floppy_image_device::default_pc_floppy_formats);
+ FLOPPY_CONNECTOR(config, "fdc:3", fcscsi_floppies, "525qd", floppy_image_device::default_pc_floppy_formats);
/* 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);
- set_vme_device();
-
- /* 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;
@@ -348,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 */
-READ16_MEMBER (vme_fcscsi1_card_device::bootvect_r){
- 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
@@ -370,12 +358,12 @@ Bit #: 7 6 5 4 3 2 1 0
\ ISCSI-l 1.D. Bit #2
*/
-READ8_MEMBER (vme_fcscsi1_card_device::tcr_r){
+uint8_t vme_sys68k_iscsi1_card_device::tcr_r(){
LOG("%s\n", FUNCNAME);
return (uint8_t) m_tcr;
}
-WRITE8_MEMBER (vme_fcscsi1_card_device::tcr_w){
+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();
@@ -406,7 +394,7 @@ WRITE8_MEMBER (vme_fcscsi1_card_device::tcr_w){
return;
}
-WRITE8_MEMBER (vme_fcscsi1_card_device::led_w){
+void vme_sys68k_iscsi1_card_device::led_w(uint8_t data) {
LOG("%s [%02x]\n", FUNCNAME, data);
m_fdc->dden_w(BIT(data, 7));
@@ -414,7 +402,7 @@ WRITE8_MEMBER (vme_fcscsi1_card_device::led_w){
return;
}
-WRITE_LINE_MEMBER(vme_fcscsi1_card_device::dma_irq)
+void vme_sys68k_iscsi1_card_device::dma_irq(int state)
{
if(state != CLEAR_LINE)
{
@@ -429,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();
@@ -437,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)
{
@@ -450,17 +438,17 @@ WRITE_LINE_MEMBER(vme_fcscsi1_card_device::fdc_irq)
update_irq_to_maincpu();
}
-READ8_MEMBER(vme_fcscsi1_card_device::fdc_read_byte)
+uint8_t vme_sys68k_iscsi1_card_device::fdc_read_byte()
{
return m_fdc->data_r();
}
-WRITE8_MEMBER(vme_fcscsi1_card_device::fdc_write_byte)
+void vme_sys68k_iscsi1_card_device::fdc_write_byte(uint8_t data)
{
m_fdc->data_w(data & 0xff);
}
-READ8_MEMBER(vme_fcscsi1_card_device::scsi_r)
+uint8_t vme_sys68k_iscsi1_card_device::scsi_r(offs_t offset)
{
uint8_t data = 0;
@@ -473,12 +461,12 @@ READ8_MEMBER(vme_fcscsi1_card_device::scsi_r)
return data;
}
-WRITE8_MEMBER(vme_fcscsi1_card_device::scsi_w)
+void vme_sys68k_iscsi1_card_device::scsi_w(offs_t offset, uint8_t data)
{
LOG("scsi W %02x <- %02x\n", offset, data);
}
-READ8_MEMBER (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);
@@ -487,7 +475,7 @@ READ8_MEMBER (vme_fcscsi1_card_device::not_implemented_r){
return (uint8_t) 0;
}
-WRITE8_MEMBER (vme_fcscsi1_card_device::not_implemented_w){
+void vme_sys68k_iscsi1_card_device::not_implemented_w(uint8_t data){
static int been_here = 0;
if (!been_here++){
logerror(TODO);
@@ -498,4 +486,4 @@ WRITE8_MEMBER (vme_fcscsi1_card_device::not_implemented_w){
// 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, fcscsi1, 0, 0, fcscsi1, fcscsi1, driver_device, 0, "Force Computers Gmbh", "SYS68K/SCSI-1", MACHINE_IS_SKELETON )
+//COMP( 1986, fcscsi1, 0, 0, fcscsi1, fcscsi1, driver_device, 0, "Force Computers Gmbh", "SYS68K/SCSI-1", MACHINE_NO_SOUND | MACHINE_NOT_WORKING )
diff --git a/src/devices/bus/vme/sys68k_iscsi.h b/src/devices/bus/vme/sys68k_iscsi.h
new file mode 100644
index 00000000000..b3d6ff1f20b
--- /dev/null
+++ b/src/devices/bus/vme/sys68k_iscsi.h
@@ -0,0 +1,72 @@
+// license:BSD-3-Clause
+// copyright-holders:Joakim Larsson Edstrom
+#ifndef MAME_BUS_VME_SYS68K_ISCSI_H
+#define MAME_BUS_VME_SYS68K_ISCSI_H
+
+#pragma once
+
+#include "imagedev/floppy.h"
+#include "machine/68230pit.h"
+#include "machine/wd_fdc.h"
+#include "machine/hd63450.h" // compatible with MC68450
+#include "bus/vme/vme.h"
+
+DECLARE_DEVICE_TYPE(VME_SYS68K_ISCSI1, vme_sys68k_iscsi1_card_device)
+
+class vme_sys68k_iscsi1_card_device : public device_t, public device_vme_card_interface
+{
+public:
+ vme_sys68k_iscsi1_card_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
+
+protected:
+ 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 ATTR_COLD;
+ virtual void device_reset() override ATTR_COLD;
+
+ // optional information overrides
+ virtual void device_add_mconfig(machine_config &config) override ATTR_COLD;
+ virtual const tiny_rom_entry *device_rom_region() const override ATTR_COLD;
+
+ void update_irq_to_maincpu();
+
+ uint8_t fdc_irq_state;
+ uint8_t dmac_irq_state;
+
+private:
+ //dmac
+ void dma_irq(int state);
+ uint8_t dma_iack();
+
+ //fdc
+ void fdc_irq(int state);
+ uint8_t fdc_read_byte();
+ void fdc_write_byte(uint8_t data);
+
+ uint8_t tcr_r();
+ void tcr_w(uint8_t data);
+ void led_w(uint8_t data);
+
+ /* Dummy driver routines */
+ uint8_t not_implemented_r();
+ void not_implemented_w(uint8_t data);
+
+ uint8_t scsi_r(offs_t offset);
+ void scsi_w(offs_t offset, uint8_t data);
+
+ void fcscsi1_mem(address_map &map) ATTR_COLD;
+ void cpu_space_map(address_map &map) ATTR_COLD;
+
+ required_device<cpu_device> m_maincpu;
+ required_device<wd1772_device> m_fdc;
+ required_device<pit68230_device> m_pit;
+ required_device<hd63450_device> m_dmac;
+
+ required_memory_region m_eprom;
+ required_shared_ptr<uint16_t> m_ram;
+ memory_passthrough_handler m_boot_mph;
+
+ uint8_t m_tcr;
+};
+
+#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 711231b7901..36369dc45c5 100644
--- a/src/devices/bus/vme/vme_fcisio.cpp
+++ b/src/devices/bus/vme/sys68k_isio.cpp
@@ -117,7 +117,7 @@
* - add PIT and DUSCC interrupts
* - add port mapping to self test jumper
* - add VME bus driver
- * - write and map a 68153 device (accessable from VME side)
+ * - write and map a 68153 device (accessible from VME side)
*
* Status: passes Self test and get stuck on no ticks for the scheduler.
* Schematics of the IRQ routing needed or a good trace of how the
@@ -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 */
-// AM_RANGE (0xc40000, 0xc800ff) AM_READWRITE8 (not_implemented_r, not_implemented_w, 0xffff) /* 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,21 @@ 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);
- set_vme_device();
-
- /* 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;
@@ -420,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 */
-READ16_MEMBER (vme_fcisio1_card_device::bootvect_r){
- 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();
+ }
+ });
}
-READ8_MEMBER (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);
@@ -439,7 +437,7 @@ READ8_MEMBER (vme_fcisio1_card_device::not_implemented_r){
return (uint8_t) 0;
}
-WRITE8_MEMBER (vme_fcisio1_card_device::not_implemented_w){
+void vme_sys68k_isio1_card_device::not_implemented_w(uint8_t data){
static int been_here = 0;
if (!been_here++){
logerror(TODO);
@@ -449,7 +447,7 @@ WRITE8_MEMBER (vme_fcisio1_card_device::not_implemented_w){
}
// TODO: Get a manual to understand the config options for real
-READ8_MEMBER (vme_fcisio1_card_device::config_rd){
+uint8_t vme_sys68k_isio1_card_device::config_rd(){
uint8_t ret = 0;
LOG("%s\n", FUNCNAME);
@@ -462,4 +460,4 @@ READ8_MEMBER (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/sys68k_isio.h b/src/devices/bus/vme/sys68k_isio.h
new file mode 100644
index 00000000000..f3d9012397c
--- /dev/null
+++ b/src/devices/bus/vme/sys68k_isio.h
@@ -0,0 +1,53 @@
+// license:BSD-3-Clause
+// copyright-holders:Joakim Larsson Edstrom
+#ifndef MAME_BUS_VME_SYS68K_ISIO_H
+#define MAME_BUS_VME_SYS68K_ISIO_H
+
+#pragma once
+
+#include "machine/scnxx562.h"
+#include "machine/68230pit.h"
+#include "machine/68153bim.h"
+#include "bus/vme/vme.h"
+
+DECLARE_DEVICE_TYPE(VME_SYS68K_ISIO1, vme_sys68k_isio1_card_device)
+
+class vme_sys68k_isio1_card_device : public device_t, public device_vme_card_interface
+{
+public:
+ vme_sys68k_isio1_card_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
+
+protected:
+ 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 ATTR_COLD;
+ virtual void device_reset() override ATTR_COLD;
+
+ // optional information overrides
+ virtual void device_add_mconfig(machine_config &config) override ATTR_COLD;
+ virtual const tiny_rom_entry *device_rom_region() const override ATTR_COLD;
+
+private:
+ uint8_t config_rd();
+
+ /* Dummy driver routines */
+ uint8_t not_implemented_r();
+ void not_implemented_w(uint8_t data);
+
+ void fcisio1_mem(address_map &map) ATTR_COLD;
+
+ required_device<cpu_device> m_maincpu;
+ required_device<duscc68562_device> m_duscc0;
+ required_device<duscc68562_device> m_duscc1;
+ required_device<duscc68562_device> m_duscc2;
+ required_device<duscc68562_device> m_duscc3;
+
+ required_device<pit68230_device> m_pit;
+ required_device<bim68153_device> m_bim;
+
+ required_memory_region m_eprom;
+ required_shared_ptr<uint16_t> m_ram;
+ memory_passthrough_handler m_boot_mph;
+};
+
+#endif // MAME_BUS_VME_SYS68K_ISIO_H
diff --git a/src/devices/bus/vme/tp880v.cpp b/src/devices/bus/vme/tp880v.cpp
new file mode 100644
index 00000000000..a3a2e12b0f6
--- /dev/null
+++ b/src/devices/bus/vme/tp880v.cpp
@@ -0,0 +1,168 @@
+// license:BSD-3-Clause
+// copyright-holders:Patrick Mackinlay
+
+/*
+ * Tadpole Technology TP880V
+ *
+ * Sources:
+ * - TPROM/88K User Manual, Monitor/Debugger For 88000 Boards, Issue: 1.3, 26 June 1990, Part No. DS-1003
+ *
+ * TODO:
+ * - cio hookup is incomplete, inter-processor interrupts are not working
+ * - dmac
+ * - vme
+ * - leds and switches
+ */
+
+#include "emu.h"
+#include "tp880v.h"
+
+#include "bus/nscsi/hd.h"
+#include "bus/nscsi/tape.h"
+
+#define VERBOSE 0
+#include "logmacro.h"
+
+DEFINE_DEVICE_TYPE(VME_TP880V, vme_tp880v_card_device, "tp880v", "Tadpole Technology TP880V")
+
+vme_tp880v_card_device::vme_tp880v_card_device(machine_config const &mconfig, char const *tag, device_t *owner, u32 clock)
+ : device_t(mconfig, VME_TP880V, tag, owner, clock)
+ , device_vme_card_interface(mconfig, *this)
+ , m_cpu(*this, "cpu")
+ , m_mmu(*this, "mmu%u", 0U)
+ , m_ios(*this, "ios")
+ , m_cio(*this, "cio%u", 0U)
+ , m_dma(*this, "dma")
+ , m_rtc(*this, "rtc")
+ , m_scsi(*this, "scsi:7:ncr53c90")
+ , m_duart(*this, "duart")
+ , m_serial(*this, "serial%u", 0U)
+ , m_ram(*this, "ram")
+ , m_ram_68k(nullptr)
+{
+}
+
+ROM_START(tp880v)
+ ROM_REGION16_BE(0x20000, "eprom", 0)
+ ROM_SYSTEM_BIOS(0, "v421", "TP880V Monitor - Revision R4.21")
+ ROMX_LOAD("880-v__v4.2.1.bin", 0x00000, 0x20000, CRC(c5e64026) SHA1(724f54573b1b0c79f20250fdb6434bb2248c5e04), ROM_GROUPWORD | ROM_REVERSE | ROM_BIOS(0)) // D27C1024D-15
+ROM_END
+
+static INPUT_PORTS_START(tp880v)
+INPUT_PORTS_END
+
+const tiny_rom_entry *vme_tp880v_card_device::device_rom_region() const
+{
+ return ROM_NAME(tp880v);
+}
+
+ioport_constructor vme_tp880v_card_device::device_input_ports() const
+{
+ return INPUT_PORTS_NAME(tp880v);
+}
+
+void vme_tp880v_card_device::device_start()
+{
+ m_ram_68k = util::big_endian_cast<u16>(m_ram.target());
+}
+
+void vme_tp880v_card_device::device_reset()
+{
+}
+
+static void scsi_devices(device_slot_interface &device)
+{
+ device.option_add("harddisk", NSCSI_HARDDISK);
+ device.option_add("tape", NSCSI_TAPE);
+ device.option_add("ncr53c90", NCR53C90);
+}
+
+void vme_tp880v_card_device::device_add_mconfig(machine_config &config)
+{
+ MC88100(config, m_cpu, 40_MHz_XTAL / 2);
+ m_cpu->set_addrmap(AS_PROGRAM, &vme_tp880v_card_device::cpu_mem);
+ m_cpu->set_cmmu_code([this](u32 const address) -> mc88200_device & { return *m_mmu[0]; });
+ m_cpu->set_cmmu_data([this](u32 const address) -> mc88200_device & { return *m_mmu[1]; });
+
+ MC88200(config, m_mmu[0], 40_MHz_XTAL / 2, 0x7e).set_mbus(m_cpu, AS_PROGRAM);
+ MC88200(config, m_mmu[1], 40_MHz_XTAL / 2, 0x7f).set_mbus(m_cpu, AS_PROGRAM);
+
+ M68000(config, m_ios, 10'000'000);
+ m_ios->set_addrmap(AS_PROGRAM, &vme_tp880v_card_device::ios_mem);
+
+ Z8036(config, m_cio[0], 4'000'000); // Z0803606VSC
+ m_cio[0]->irq_wr_cb().set_inputline(m_ios, INPUT_LINE_IRQ4); // ?
+ Z8036(config, m_cio[1], 4'000'000); // Z0803606VSC
+ m_cio[0]->irq_wr_cb().set_inputline(m_ios, INPUT_LINE_IRQ1); // ?
+
+ // TODO: MC68440 is function and pin compatible with MC68450/HD63450, but
+ // has only two DMA channels instead of four.
+ HD63450(config, m_dma, 10'000'000); // MC68440FN10
+ m_dma->set_cpu_tag(m_ios);
+ m_dma->irq_callback().set_inputline(m_ios, INPUT_LINE_IRQ3);
+ m_dma->dma_read<0>().set(m_scsi, FUNC(ncr53c90_device::dma_r));
+ m_dma->dma_write<0>().set(m_scsi, FUNC(ncr53c90_device::dma_w));
+
+ M48T02(config, m_rtc, 0); // MK40T02B-25
+
+ NSCSI_BUS(config, "scsi", 0);
+ NSCSI_CONNECTOR(config, "scsi:0", scsi_devices, "harddisk", false);
+ NSCSI_CONNECTOR(config, "scsi:1", scsi_devices, nullptr, false);
+ NSCSI_CONNECTOR(config, "scsi:2", scsi_devices, "tape", 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("ncr53c90", NCR53C90).machine_config(
+ [this](device_t *device)
+ {
+ ncr53c90_device &ncr53c90(downcast<ncr53c90_device &>(*device));
+
+ ncr53c90.set_clock(10'000'000);
+ ncr53c90.irq_handler_cb().set_inputline(m_ios, INPUT_LINE_IRQ2);
+ ncr53c90.drq_handler_cb().set(m_dma, FUNC(hd63450_device::drq0_w));
+ });
+
+ SCN2681(config, m_duart, 3.6864_MHz_XTAL);
+ m_duart->irq_cb().set_inputline(m_ios, INPUT_LINE_IRQ6);
+ m_duart->outport_cb().set([this](int state) { m_cpu->set_input_line(INPUT_LINE_RESET, state); }).bit(5);
+
+ RS232_PORT(config, m_serial[0], default_rs232_devices, "terminal");
+ RS232_PORT(config, m_serial[1], default_rs232_devices, nullptr);
+
+ 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_tp880v_card_device::cpu_mem(address_map &map)
+{
+ map(0x0000'0000, 0x003f'ffff).ram().share("ram");
+
+ map(0xfff0'0002, 0xfff0'0002).select(0x3f00).lrw8(
+ [this](offs_t offset) { return m_cio[0]->read(offset >> 8); }, "cio0_r",
+ [this](offs_t offset, u8 data) { m_cio[0]->write(offset >> 8, data); }, "cio0_w");
+ map(0xfff0'8002, 0xfff0'8002).select(0x3f00).lrw8(
+ [this](offs_t offset) { return m_cio[1]->read(offset >> 8); }, "cio1_r",
+ [this](offs_t offset, u8 data) { m_cio[1]->write(offset >> 8, data); }, "cio1_w");
+
+ //map(0xfff1'0000, 0xfff1'0000); // vme iack vector?
+}
+
+void vme_tp880v_card_device::ios_mem(address_map &map)
+{
+ map(0x00'0000, 0x01'ffff).rom().region("eprom", 0);
+
+ map(0x10'0000, 0x10'3fff).ram(); // SRAM
+
+ map(0x20'0000, 0x20'001f).rw(m_duart, FUNC(scn2681_device::read), FUNC(scn2681_device::write)).umask16(0x00ff);
+ map(0x24'0000, 0x2f'001f).m(m_scsi, FUNC(ncr53c90_device::map)).umask16(0x00ff);
+ map(0x28'0000, 0x28'00ff).rw(m_dma, FUNC(hd63450_device::read), FUNC(hd63450_device::write));
+ map(0x2c'0000, 0x2c'0fff).rw(m_rtc, FUNC(m48t02_device::read), FUNC(m48t02_device::write)).umask16(0x00ff);
+
+ map(0x80'0000, 0xbf'ffff).lrw16(
+ [this](offs_t offset, u16 mem_mask) { return m_ram_68k[offset]; }, "ram_68k_r",
+ [this](offs_t offset, u16 data, u16 mem_mask) { COMBINE_DATA(&m_ram_68k[offset]); }, "ram_68k_w");
+}
diff --git a/src/devices/bus/vme/tp880v.h b/src/devices/bus/vme/tp880v.h
new file mode 100644
index 00000000000..d2f60273550
--- /dev/null
+++ b/src/devices/bus/vme/tp880v.h
@@ -0,0 +1,57 @@
+// license:BSD-3-Clause
+// copyright-holders:Patrick Mackinlay
+
+#ifndef MAME_BUS_VME_TP880V_H
+#define MAME_BUS_VME_TP880V_H
+
+#pragma once
+
+#include "cpu/m68000/m68000.h"
+#include "cpu/m88000/m88000.h"
+#include "machine/hd63450.h"
+#include "machine/mc68681.h"
+#include "machine/mc88200.h"
+#include "machine/ncr53c90.h"
+#include "machine/timekpr.h"
+#include "machine/z8536.h"
+
+#include "bus/vme/vme.h"
+#include "bus/rs232/rs232.h"
+
+class vme_tp880v_card_device
+ : public device_t
+ , public device_vme_card_interface
+{
+public:
+ vme_tp880v_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 ATTR_COLD;
+ virtual void device_add_mconfig(machine_config &config) override ATTR_COLD;
+ virtual ioport_constructor device_input_ports() const override ATTR_COLD;
+ virtual void device_start() override ATTR_COLD;
+ virtual void device_reset() override ATTR_COLD;
+
+private:
+ void cpu_mem(address_map &map) ATTR_COLD;
+ void ios_mem(address_map &map) ATTR_COLD;
+
+ required_device<mc88100_device> m_cpu;
+ required_device_array<mc88200_device, 2> m_mmu;
+ required_device<m68000_device> m_ios;
+
+ required_device_array<z8036_device, 2> m_cio;
+ required_device<hd63450_device> m_dma;
+ required_device<m48t02_device> m_rtc;
+ required_device<ncr53c90_device> m_scsi;
+ required_device<scn2681_device> m_duart;
+
+ required_device_array<rs232_port_device, 2> m_serial;
+
+ required_shared_ptr<u32> m_ram;
+ util::endian_cast<u32, u16, util::endianness::big> m_ram_68k;
+};
+
+DECLARE_DEVICE_TYPE(VME_TP880V, vme_tp880v_card_device)
+
+#endif // MAME_BUS_VME_TP880V_H
diff --git a/src/devices/bus/vme/tp881v.cpp b/src/devices/bus/vme/tp881v.cpp
new file mode 100644
index 00000000000..30cd01a568b
--- /dev/null
+++ b/src/devices/bus/vme/tp881v.cpp
@@ -0,0 +1,346 @@
+// 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);
+ m_cpu->set_cmmu_code([this](u32 const address) -> mc88200_device & { return *m_mmu[0]; });
+ m_cpu->set_cmmu_data([this](u32 const address) -> mc88200_device & { return *m_mmu[1]; });
+
+ MC88200(config, m_mmu[0], 40_MHz_XTAL / 2, 0x00).set_mbus(m_cpu, AS_PROGRAM);
+ MC88200(config, m_mmu[1], 40_MHz_XTAL / 2, 0x01).set_mbus(m_cpu, AS_PROGRAM);
+
+ // 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..817e65ab3b3
--- /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 ATTR_COLD;
+ virtual void device_add_mconfig(machine_config &config) override ATTR_COLD;
+ virtual ioport_constructor device_input_ports() const override ATTR_COLD;
+ virtual void device_start() override ATTR_COLD;
+ virtual void device_reset() override ATTR_COLD;
+
+private:
+ void cpu_mem(address_map &map) ATTR_COLD;
+ void net_mem(address_map &map) ATTR_COLD;
+
+ 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 61ca35c2199..c1ad72e17a4 100644
--- a/src/devices/bus/vme/vme.cpp
+++ b/src/devices/bus/vme/vme.cpp
@@ -66,439 +66,299 @@
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_tag(nullptr)
- , m_vme_slottag(nullptr)
- , m_vme_j1_callback(*this)
-{
- LOG("%s %s\n", tag, FUNCNAME);
-}
-
-//-------------------------------------------------
-// update_vme_chains
-//-------------------------------------------------
-void vme_slot_device::update_vme_chains(uint32_t slot_nbr)
-{
- LOG("%s %s - %d\n", FUNCNAME, tag(), slot_nbr);
-}
-
-//-------------------------------------------------
-// set_vme_slot
-//-------------------------------------------------
-void vme_slot_device::set_vme_slot(const char *tag, const char *slottag)
-{
- LOG("%s %s - %s\n", FUNCNAME, tag, slottag);
- m_vme_tag = tag;
- m_vme_slottag = slottag;
-}
-
-//-------------------------------------------------
-// device_start - device-specific startup
-//-------------------------------------------------
-void vme_slot_device::device_start()
-{
- device_vme_card_interface *dev = dynamic_cast<device_vme_card_interface *>(get_card_device());
- LOG("%s %s - %s:%s\n", tag(), FUNCNAME, m_vme_tag, m_vme_slottag);
- 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_tag(m_vme_tag, m_vme_slottag);
+ { "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) },
}
-
- // m_card = dynamic_cast<device_vme_card_interface *>(get_card_device());
-}
-
-//-------------------------------------------------
-// device_config_complete - perform any
-// operations now that the configuration is
-// complete
-//-------------------------------------------------
-void vme_slot_device::device_config_complete()
-{
- LOG("%s %s\n", tag(), FUNCNAME);
-}
-
-//-------------------------------------------------
-// P1 D8 read
-//-------------------------------------------------
-READ8_MEMBER(vme_slot_device::read8)
+ , 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(space, offset);
- return result;
}
-//-------------------------------------------------
-// P1 D8 write
-//-------------------------------------------------
-WRITE8_MEMBER(vme_slot_device::write8)
+void vme_bus_device::device_start()
{
- LOG("%s %s\n", tag(), FUNCNAME);
- // printf("%s %s\n", tag(), FUNCNAME);
- // if (m_card) m_card->write8(space, 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);
+ 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]),
+ };
}
-#endif
-// All boards that can be non-controller boards, eg not driving the VME CLK etc
-void vme_slots(device_slot_interface &device)
+u32 vme_bus_device::read_iack(address_space &space, offs_t offset, u32 mem_mask)
{
- device.option_add("mzr8300", VME_MZR8300);
- device.option_add("mvme350", VME_MVME350);
- device.option_add("fcisio1", VME_FCISIO1);
- device.option_add("fcscsi1", VME_FCSCSI1);
-}
+ if (!device().machine().side_effects_disabled())
+ {
+ // decode the interrupt number from address lines A03-A01
+ unsigned const irq = BIT(offset, 1, 3);
-//
-// VME device P1
-//
+ LOG("read_iack 0x%08x mem_mask 0x%08x /IRQ%u /IACKIN asserted (%s)\n", offset, mem_mask, irq, machine().describe_context());
-DEFINE_DEVICE_TYPE(VME, vme_device, "vme", "VME bus")
+ // enable interrupt acknowledge daisy chain
+ m_iack = true;
+ }
-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.unmap();
}
-// 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()
+// 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);
+ u32 const data = space.unmap();
- m_allocspaces = false;
-}
-
-vme_device::vme_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
- : vme_device(mconfig, VME, tag, owner, clock)
-{
-}
+ if (!device().machine().side_effects_disabled())
+ {
+ LOG("read_berr %s 0x%08x data 0x%08x mem_mask 0x%08x /BERR asserted (%s)\n", space.name(), offset << 2, data, mem_mask, machine().describe_context());
-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("VME A32", ENDIANNESS_BIG, 32, 32, 0, address_map_constructor())
- , m_allocspaces(true)
- , m_cputag("maincpu")
-{
- LOG("%s %s\n", tag, FUNCNAME);
-}
+ m_berr(0);
+ }
-vme_device::~vme_device()
-{
- LOG("%s %s\n", tag(), FUNCNAME);
- m_device_list.detach_all();
+ return data;
}
-void vme_device::device_start()
+// generate bus errors on unmapped write cycles
+void vme_bus_device::write_berr(address_space &space, offs_t offset, u32 data, u32 mem_mask)
{
- LOG("%s %s %s\n", owner()->tag(), tag(), FUNCNAME);
- if (m_allocspaces)
- {
- 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
+ if (!device().machine().side_effects_disabled())
{
- 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 %s 0x%08x data 0x%08x mem_mask 0x%08x /BERR asserted (%s)\n", space.name(), 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);
-
- LOG(" - width:%d\n", m_prgwidth);
+ bool const irq_active = m_irq_count[I - 1];
- // 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);
- }
+ // count assertions
+ if (!state)
+ m_irq_count[I - 1]++;
+ else if (irq_active)
+ m_irq_count[I - 1]--;
- switch(m_prgwidth)
+ // update line state
+ if (irq_active ^ bool(m_irq_count[I - 1]))
{
- 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("bus /IRQ%u %s\n", I, state ? "cleared" : "asserted");
+ 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);
+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);
- // 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);
- }
-}
-
-// 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)
{
- 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_config_complete()
{
- 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);
- }
+ device_vme_card_interface *const card(dynamic_cast<device_vme_card_interface *>(get_card_device()));
+ if (card && owner())
+ card->set_bus(*dynamic_cast<vme_bus_device *>(owner()));
}
-//
-// Card interface
-//
-device_vme_card_interface::device_vme_card_interface(const machine_config &mconfig, device_t &device)
- : device_slot_card_interface(mconfig, device)
- ,m_vme(nullptr)
- ,m_vme_tag(nullptr)
- ,m_vme_slottag(nullptr)
- ,m_slot(0)
- ,m_next(nullptr)
+void vme_slot_device::device_start()
{
- m_device = &device;
- LOG("%s %s\n", m_device->tag(), FUNCNAME);
}
-device_vme_card_interface::~device_vme_card_interface()
+#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_bus(nullptr)
+ , m_berr(*this)
+ , m_irq(*this)
+ , m_iack(*this, 0)
+ , m_irq_active(0)
+ , m_master(false)
{
- LOG("%s %s\n", m_device->tag(), FUNCNAME);
}
-void device_vme_card_interface::set_vme_tag(const char *tag, const char *slottag)
+void device_vme_card_interface::interface_post_start()
{
- LOG("%s %s\n", tag, FUNCNAME);
- m_vme_tag = tag;
- m_vme_slottag = slottag;
+ 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_bus->iackin_r() && BIT(m_irq_active, irq))
+ {
+ // deassert interrupt acknowledge daisy chain output
+ m_bus->iackout_w(1);
+
+ // read and return the interrupting device status/ID
+ data = m_iack(irq);
+
+ LOG("vme iack irq %u status 0x%08x /IACKOUT deasserted (%s)\n", irq, data, device().machine().describe_context());
+ }
+ });
}
-void device_vme_card_interface::set_vme_device()
+void device_vme_card_interface::set_bus(vme_bus_device &bus)
{
- LOG("%s %s\n", m_device->tag(), FUNCNAME);
- m_vme = dynamic_cast<vme_device *>(device().machine().device(m_vme_tag));
- // printf("*** %s %sfound\n", m_vme_tag, m_vme ? "" : "not ");
- if (m_vme) m_vme->add_vme_card(this);
+ m_bus = &bus;
+
+ // route incoming bus errors to a card only when it is the bus master
+ m_bus->berr().append(
+ [this](int state)
+ {
+ if (m_master)
+ {
+ LOG("vme incoming /BERR %s\n", state ? "cleared" : "asserted");
+ m_berr(state);
+ }
+ });
+
+ // route incoming interrupt requests to all cards
+ m_bus->irq<1>().append([this](int state) { LOG("vme incoming /IRQ1 %s\n", state ? "cleared" : "asserted"); m_irq[0](state); });
+ m_bus->irq<2>().append([this](int state) { LOG("vme incoming /IRQ2 %s\n", state ? "cleared" : "asserted"); m_irq[1](state); });
+ m_bus->irq<3>().append([this](int state) { LOG("vme incoming /IRQ3 %s\n", state ? "cleared" : "asserted"); m_irq[2](state); });
+ m_bus->irq<4>().append([this](int state) { LOG("vme incoming /IRQ4 %s\n", state ? "cleared" : "asserted"); m_irq[3](state); });
+ m_bus->irq<5>().append([this](int state) { LOG("vme incoming /IRQ5 %s\n", state ? "cleared" : "asserted"); m_irq[4](state); });
+ m_bus->irq<6>().append([this](int state) { LOG("vme incoming /IRQ6 %s\n", state ? "cleared" : "asserted"); m_irq[5](state); });
+ m_bus->irq<7>().append([this](int state) { LOG("vme incoming /IRQ7 %s\n", state ? "cleared" : "asserted"); m_irq[6](state); });
}
-/* VME D8 accesses */
-READ8_MEMBER(device_vme_card_interface::read8)
+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_w outgoing /IRQ%u %s\n", I, state ? "cleared" : "asserted");
-WRITE8_MEMBER(device_vme_card_interface::write8)
-{
- 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_bus->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 2849b07f8b3..c70a4b1ab73 100644
--- a/src/devices/bus/vme/vme.h
+++ b/src/devices/bus/vme/vme.h
@@ -50,194 +50,166 @@
#pragma once
-
-//**************************************************************************
-// CONSTANTS
-//**************************************************************************
-
-#define VME_BUS_TAG "vme"
-
-//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_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
+ enum address_modifier : u8
{
- AS,
- DS0,
- DS1,
- BERR,
- DTACK,
- WRITE
+ 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
};
+}
- enum class address
- {
- DS0,
- DS1,
- LWORD
- };
-
- // construction/destruction
- template <typename T>
- vme_slot_device(machine_config const &mconfig, char const *tag, device_t *owner, T &&opts, char const *dflt, uint32_t slot_nbr, char const *bus_tag)
- : vme_slot_device(mconfig, tag, owner, 0)
- {
- option_reset();
- opts(*this);
- set_default_option(dflt);
- set_fixed(false);
- set_vme_slot(bus_tag, tag);
- update_vme_chains(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);
- void set_vme_slot(const char *tag, const char *slottag);
- void update_vme_chains(uint32_t slot_nbr);
+ // configuration
+ auto berr() { return m_berr.bind(); }
+ template <unsigned I> auto irq() { return m_irq[I - 1].bind(); }
- virtual DECLARE_READ8_MEMBER(read8);
- virtual DECLARE_WRITE8_MEMBER(write8);
+ // 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_t implementation
+ virtual void device_start() override ATTR_COLD;
- // device-level overrides
- virtual void device_start() override;
- virtual void device_config_complete() override;
+ // device_memory_interface implementation
+ virtual space_config_vector memory_space_config() const override;
- // configuration
- const char *m_vme_tag, *m_vme_slottag;
+private:
+ void iack(address_map &map) ATTR_COLD;
+ void a16(address_map &map) ATTR_COLD;
+ void a24(address_map &map) ATTR_COLD;
+ void a32(address_map &map) ATTR_COLD;
- // callbacks
- devcb_write_line m_vme_j1_callback;
- device_vme_card_interface *m_card;
-};
+ 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(address_space &space, offs_t offset, u32 data, u32 mem_mask);
-DECLARE_DEVICE_TYPE(VME, vme_device)
+ address_space_config const m_asc[64];
+ devcb_write_line::array<7> m_irq;
+ devcb_write_line m_berr;
-class vme_card_interface;
+ u8 m_irq_count[7];
+ bool m_iack;
+};
-class vme_device : public device_t,
- public device_memory_interface
+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();
-
- virtual space_config_vector memory_space_config() const override;
+ vme_slot_device(machine_config const &mconfig, char const *tag, device_t *owner, u32 clock = DERIVED_CLOCK(1, 1));
- 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);
+ 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);
+ }
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;
-
- // internal state
- cpu_device *m_maincpu;
-
- // address spaces
- address_space *m_prgspace;
- int m_prgwidth;
- bool m_allocspaces;
-
- const char *m_cputag;
+ // device_t implementation
+ virtual void device_config_complete() override ATTR_COLD;
+ virtual void device_start() override ATTR_COLD;
+private:
};
-
-
-// device type definition
-DECLARE_DEVICE_TYPE(VME_SLOT, vme_slot_device)
-
-class device_vme_card_interface : public device_slot_card_interface
+class device_vme_card_interface : public device_interface
{
- template <class ElementType> friend class simple_list;
public:
- // inline configuration
- void set_vme_tag(const char *tag, const char *slottag);
+ 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_bus->space(AM).read_dword(base + (offset << 2), mem_mask);
+ m_master = false;
- // construction/destruction
- virtual ~device_vme_card_interface();
- void set_vme_device();
+ 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_bus->space(AM).read_word(base + (offset << 1), mem_mask);
+ m_master = false;
- virtual DECLARE_READ8_MEMBER(read8);
- virtual DECLARE_WRITE8_MEMBER(write8);
+ 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_bus->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_bus->space(AM).write_word(base + (offset << 1), data, mem_mask);
+ m_master = false;
+ }
+ u32 vme_iack_r(offs_t offset)
+ {
+ return m_bus->space(vme::IACK).read_dword(offset);
+ }
- device_vme_card_interface(const machine_config &mconfig, device_t &device);
+ void set_bus(vme_bus_device &bus);
protected:
- device_t *m_device;
+ device_vme_card_interface(machine_config const &mconfig, device_t &device);
+
+ // device_interface implementation
+ virtual void interface_post_start() override;
- vme_device *m_vme;
- const char *m_vme_tag, *m_vme_slottag;
- int m_slot;
+ // configuration
+ auto vme_berr() { return m_berr.bind(); } // receive a bus error
+ template <unsigned I> auto vme_irq() { return m_irq[I - 1].bind(); } // receive a bus interrupt
+ auto vme_iack() { return m_iack.bind(); } // provide an interrupt acknowledge vector
+
+ // runtime
+ void vme_berr_w(int state) { m_bus->berr_w(state); } // generate a bus error
+ template <unsigned I> void vme_irq_w(int state); // generate a bus interrupt
+
+ address_space &vme_space(vme::address_modifier am) const { return m_bus->space(am); }
private:
- device_vme_card_interface *m_next;
+ vme_bus_device *m_bus;
+
+ devcb_write_line m_berr;
+ devcb_write_line::array<7> m_irq;
+ 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..d2d0245e7a0
--- /dev/null
+++ b/src/devices/bus/vme/vme_cards.cpp
@@ -0,0 +1,69 @@
+// 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 "mvme328.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 "tp880v.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("mvme328", VME_MVME328);
+ 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("tp880v", VME_TP880V);
+ 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..25ac3e3d109
--- /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_VME_CARDS_H
+#define MAME_BUS_VME_VME_CARDS_H
+
+#pragma once
+
+void vme_cards(device_slot_interface &device);
+
+#endif // MAME_BUS_VME_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 23ebf0338d6..00000000000
--- a/src/devices/bus/vme/vme_fccpu20.h
+++ /dev/null
@@ -1,190 +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;
- virtual void device_timer(emu_timer &timer, device_timer_id id, int param, void *ptr) 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 bim_irq_state;
- int 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 */
- DECLARE_READ8_MEMBER (pita_r);
- DECLARE_READ8_MEMBER (pitb_r);
- DECLARE_READ8_MEMBER (pitc_r);
-
- // Below are duplicated declarations from src/mame/drivers/fccpu20.cpp
- DECLARE_READ32_MEMBER (bootvect_r);
- DECLARE_WRITE32_MEMBER (bootvect_w);
-
- 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_fcisio.h b/src/devices/bus/vme/vme_fcisio.h
deleted file mode 100644
index 9a0c8056617..00000000000
--- a/src/devices/bus/vme/vme_fcisio.h
+++ /dev/null
@@ -1,54 +0,0 @@
-// license:BSD-3-Clause
-// copyright-holders:Joakim Larsson Edstrom
-#ifndef MAME_BUS_VME_VME_FCISIO_H
-#define MAME_BUS_VME_VME_FCISIO_H
-
-#pragma once
-
-#include "machine/scnxx562.h"
-#include "machine/68230pit.h"
-#include "machine/68153bim.h"
-#include "bus/vme/vme.h"
-
-DECLARE_DEVICE_TYPE(VME_FCISIO1, vme_fcisio1_card_device)
-
-class vme_fcisio1_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);
-
-protected:
- vme_fcisio1_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;
- virtual const tiny_rom_entry *device_rom_region() const override;
-
-private:
- DECLARE_READ8_MEMBER (config_rd);
-
- DECLARE_READ16_MEMBER (bootvect_r);
-
- /* Dummy driver routines */
- DECLARE_READ8_MEMBER (not_implemented_r);
- DECLARE_WRITE8_MEMBER (not_implemented_w);
-
- void fcisio1_mem(address_map &map);
-
- required_device<cpu_device> m_maincpu;
- required_device<duscc68562_device> m_duscc0;
- required_device<duscc68562_device> m_duscc1;
- required_device<duscc68562_device> m_duscc2;
- required_device<duscc68562_device> m_duscc3;
-
- required_device<pit68230_device> m_pit;
- required_device<bim68153_device> m_bim;
-
- // Pointer to System ROMs needed by bootvect_r
- uint16_t *m_sysrom;
-};
-
-#endif // MAME_BUS_VME_VME_FCISIO_H
diff --git a/src/devices/bus/vme/vme_fcscsi.h b/src/devices/bus/vme/vme_fcscsi.h
deleted file mode 100644
index d36320d6183..00000000000
--- a/src/devices/bus/vme/vme_fcscsi.h
+++ /dev/null
@@ -1,73 +0,0 @@
-// license:BSD-3-Clause
-// copyright-holders:Joakim Larsson Edstrom
-#ifndef MAME_BUS_VME_VME_FCSCSI_H
-#define MAME_BUS_VME_VME_FCSCSI_H
-
-#pragma once
-
-#include "imagedev/floppy.h"
-#include "machine/68230pit.h"
-#include "machine/wd_fdc.h"
-#include "machine/hd63450.h" // compatible with MC68450
-#include "bus/vme/vme.h"
-
-DECLARE_DEVICE_TYPE(VME_FCSCSI1, vme_fcscsi1_card_device)
-
-class vme_fcscsi1_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);
-
-protected:
- vme_fcscsi1_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;
- virtual const tiny_rom_entry *device_rom_region() const override;
-
- void update_irq_to_maincpu();
-
- uint8_t fdc_irq_state;
- uint8_t dmac_irq_state;
-
-private:
- //dmac
- DECLARE_WRITE_LINE_MEMBER(dma_irq);
- uint8_t dma_iack();
-
- //fdc
- DECLARE_WRITE_LINE_MEMBER(fdc_irq);
- DECLARE_READ8_MEMBER(fdc_read_byte);
- DECLARE_WRITE8_MEMBER(fdc_write_byte);
- DECLARE_FLOPPY_FORMATS(floppy_formats);
-
- DECLARE_READ16_MEMBER (bootvect_r);
- DECLARE_READ8_MEMBER (tcr_r);
- DECLARE_WRITE8_MEMBER (tcr_w);
- DECLARE_WRITE8_MEMBER (led_w);
-
- /* Dummy driver routines */
- DECLARE_READ8_MEMBER(not_implemented_r);
- DECLARE_WRITE8_MEMBER(not_implemented_w);
-
- DECLARE_READ8_MEMBER(scsi_r);
- DECLARE_WRITE8_MEMBER(scsi_w);
-
- void fcscsi1_mem(address_map &map);
- void cpu_space_map(address_map &map);
-
- required_device<cpu_device> m_maincpu;
- required_device<wd1772_device> m_fdc;
- required_device<pit68230_device> m_pit;
- required_device<hd63450_device> m_dmac;
-
- uint8_t m_tcr;
-
- // Pointer to System ROMs needed by bootvect_r
- uint16_t *m_sysrom;
-};
-
-#endif // MAME_BUS_VME_VME_FCSCSI_H
diff --git a/src/devices/bus/vme/vme_hcpu30.cpp b/src/devices/bus/vme/vme_hcpu30.cpp
deleted file mode 100644
index 57994820f7c..00000000000
--- a/src/devices/bus/vme/vme_hcpu30.cpp
+++ /dev/null
@@ -1,195 +0,0 @@
-// license:BSD-3-Clause
-// copyright-holders:Sergey Svishchev
-
-/*
- * Besta HCPU30 board, skeleton driver.
- *
- * Supported by SysV R3 "Bestix" port and also by Linux port,
- * see https://github.com/shattered/linux-m68k
- *
- * 68030 @ 33 MHz - primary CPU
- * 68882 @ ?? Mhz - FPU
- * 68020 @ ?? MHz - I/O CPU (using shared memory region)
- *
- * 4 or 16 MB of DRAM
- * 8 or 32 KB of NVRAM
- *
- * WD33C93 - SCSI
- * DP8473 - Floppy
- * i82586? - Ethernet
- * 62421 - Real-time clock
- */
-
-#include "emu.h"
-#include "vme_hcpu30.h"
-
-//#define LOG_GENERAL (1U << 0)
-#define LOG_SETUP (1U << 1)
-#define LOG_INT (1U << 2)
-
-//#define VERBOSE (LOG_GENERAL | LOG_SETUP | LOG_INT)
-//#define LOG_OUTPUT_FUNC printf
-
-#include "logmacro.h"
-
-#define LOGSETUP(...) LOGMASKED(LOG_SETUP, __VA_ARGS__)
-#define LOGINT(...) LOGMASKED(LOG_INT, __VA_ARGS__)
-
-#ifdef _MSC_VER
-#define FUNCNAME __func__
-#else
-#define FUNCNAME __PRETTY_FUNCTION__
-#endif
-
-
-#define DUSCC_CLOCK XTAL(14'745'600) /* XXX Unverified */
-#define RS232P1_TAG "rs232p1"
-#define RS232P2_TAG "rs232p2"
-
-
-//**************************************************************************
-// GLOBAL VARIABLES
-//**************************************************************************
-
-DEFINE_DEVICE_TYPE(VME_HCPU30, vme_hcpu30_card_device, "hcpu30", "Besta HCPU30 CPU board")
-
-void vme_hcpu30_card_device::hcpu30_mem(address_map &map)
-{
- map(0x00000000, 0x00000007).ram().w(FUNC(vme_hcpu30_card_device::bootvect_w)); /* After first write we act as RAM */
- map(0x00000000, 0x00000007).rom().r(FUNC(vme_hcpu30_card_device::bootvect_r)); /* ROM mirror just during reset */
- map(0x00000008, 0x001fffff).ram(); // local bus DRAM, 4MB
- map(0x00200000, 0x00201fff).ram(); // AM_SHARE("iocpu")
- map(0xff000000, 0xff007fff).rom().mirror(0x8000).region("user1", 0);
- map(0xff020000, 0xff027fff).ram().mirror(0x8000); // SRAM 32KB
- map(0xffff8000, 0xffff8fff).unmaprw(); // shared memory with iocpu
- map(0xffff9000, 0xffff9fff).ram(); // SRAM, optional: battery-backed
- map(0xfffff100, 0xfffff11f).unmaprw(); // VME bus configuration (accessed after DIP switch read)
- map(0xfffff120, 0xfffff123).portr("SA1");
- map(0xfffff200, 0xfffff2ff).unmaprw();
- map(0xfffff300, 0xfffff3ff).rw("duscc", FUNC(duscc68562_device::read), FUNC(duscc68562_device::write));
- map(0xfffff600, 0xfffff6ff).unmaprw();
- map(0xfffff700, 0xfffff7ff).unmaprw();
-}
-
-static INPUT_PORTS_START(hcpu30)
- PORT_START("SA1")
- PORT_DIPNAME(0x03000000, 0x00000000, "Console port speed")
- PORT_DIPSETTING(0x00000000, "9600")
- PORT_DIPSETTING(0x01000000, "19200")
- PORT_DIPSETTING(0x02000000, "38400")
- PORT_DIPSETTING(0x03000000, "4800")
- PORT_DIPNAME(0x04000000, 0x04000000, "Boot into...")
- PORT_DIPSETTING(0x00000000, "UNIX")
- PORT_DIPSETTING(0x04000000, "Monitor")
- PORT_DIPNAME(0x10000000, 0x00000000, "VME bus width")
- PORT_DIPSETTING(0x00000000, "32 bits")
- PORT_DIPSETTING(0x10000000, "16 bits")
- PORT_DIPNAME(0x20000000, 0x00000000, "VME bus free")
- PORT_DIPSETTING(0x00000000, "ROR")
- PORT_DIPSETTING(0x20000000, "not ROR")
- PORT_DIPNAME(0x40000000, 0x00000000, "Cache burst mode")
- PORT_DIPSETTING(0x00000000, "Off")
- PORT_DIPSETTING(0x40000000, "On")
- PORT_DIPNAME(0x80000000, 0x00000000, "Undefined")
- PORT_DIPSETTING(0x00000000, "Off")
- PORT_DIPSETTING(0x80000000, "On")
-INPUT_PORTS_END
-
-ROM_START(hcpu30)
- ROM_REGION32_BE(0x8000, "user1", ROMREGION_ERASEFF)
- ROM_LOAD("hcpu30.27c256.dat", 0x0000, 0x8000, CRC(d24da66e) SHA1(5431b0559b168a995e725b35e1465a0b8ee8aa72))
-ROM_END
-
-//-------------------------------------------------
-// rom_region - device-specific ROM region
-//-------------------------------------------------
-
-const tiny_rom_entry *vme_hcpu30_card_device::device_rom_region() const
-{
- return ROM_NAME(hcpu30);
-}
-
-//-------------------------------------------------
-// input_ports - device-specific input ports
-//-------------------------------------------------
-
-ioport_constructor vme_hcpu30_card_device::device_input_ports() const
-{
- return INPUT_PORTS_NAME(hcpu30);
-}
-
-//-------------------------------------------------
-// device_add_mconfig - add device configuration
-//-------------------------------------------------
-
-void vme_hcpu30_card_device::device_add_mconfig(machine_config &config)
-{
- M68030(config, m_maincpu, 2*16670000);
- m_maincpu->set_addrmap(AS_PROGRAM, &vme_hcpu30_card_device::hcpu30_mem);
-
- DUSCC68562(config, m_dusccterm, DUSCC_CLOCK);
- m_dusccterm->configure_channels(0, 0, 0, 0);
- m_dusccterm->out_txda_callback().set(RS232P1_TAG, FUNC(rs232_port_device::write_txd));
- m_dusccterm->out_dtra_callback().set(RS232P1_TAG, FUNC(rs232_port_device::write_dtr));
- m_dusccterm->out_rtsa_callback().set(RS232P1_TAG, FUNC(rs232_port_device::write_rts));
- m_dusccterm->out_txdb_callback().set(RS232P2_TAG, FUNC(rs232_port_device::write_txd));
- m_dusccterm->out_dtrb_callback().set(RS232P2_TAG, FUNC(rs232_port_device::write_dtr));
- m_dusccterm->out_rtsb_callback().set(RS232P2_TAG, FUNC(rs232_port_device::write_rts));
-// m_dusccterm->out_int_callback(),set(FUNC());
-
- rs232_port_device &rs232p1(RS232_PORT(config, RS232P1_TAG, default_rs232_devices, "terminal"));
- rs232p1.rxd_handler().set(m_dusccterm, FUNC(duscc68562_device::rxa_w));
- rs232p1.cts_handler().set(m_dusccterm, FUNC(duscc68562_device::ctsa_w));
-
- rs232_port_device &rs232p2(RS232_PORT(config, RS232P2_TAG, default_rs232_devices, nullptr));
- rs232p2.rxd_handler().set(m_dusccterm, FUNC(duscc68562_device::rxb_w));
- rs232p2.cts_handler().set(m_dusccterm, FUNC(duscc68562_device::ctsb_w));
-}
-
-/* Boot vector handler, the PCB hardwires the first 8 bytes from 0xff800000 to 0x0 at reset */
-READ32_MEMBER(vme_hcpu30_card_device::bootvect_r)
-{
- LOG("%s\n", FUNCNAME);
- return m_sysrom[offset];
-}
-
-WRITE32_MEMBER(vme_hcpu30_card_device::bootvect_w)
-{
- LOG("%s\n", FUNCNAME);
- m_sysram[offset % ARRAY_LENGTH(m_sysram)] &= ~mem_mask;
- m_sysram[offset % ARRAY_LENGTH(m_sysram)] |= (data & mem_mask);
- m_sysrom = &m_sysram[0]; // redirect all upcoming accesses to masking RAM until reset.
-}
-
-vme_hcpu30_card_device::vme_hcpu30_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_dusccterm(*this, "duscc")
-{
- LOG("%s %s\n", tag, FUNCNAME);
- m_slot = 1;
-}
-
-vme_hcpu30_card_device::vme_hcpu30_card_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
- : vme_hcpu30_card_device(mconfig, VME_HCPU30, tag, owner, clock)
-{
-}
-
-void vme_hcpu30_card_device::device_start()
-{
- LOG("%s %s\n", tag(), FUNCNAME);
-
- set_vme_device();
-
- save_pointer (NAME (m_sysrom), sizeof(m_sysrom));
- save_pointer (NAME (m_sysram), sizeof(m_sysram));
-
- /* Setup pointer to bootvector in ROM for bootvector handler bootvect_r */
- m_sysrom = (uint32_t*)(memregion ("user1")->base());
-}
-
-void vme_hcpu30_card_device::device_reset()
-{
- LOG("%s %s\n", tag(), FUNCNAME);
-}
diff --git a/src/devices/bus/vme/vme_hcpu30.h b/src/devices/bus/vme/vme_hcpu30.h
deleted file mode 100644
index b4e387ace22..00000000000
--- a/src/devices/bus/vme/vme_hcpu30.h
+++ /dev/null
@@ -1,48 +0,0 @@
-// license:BSD-3-Clause
-// copyright-holders:Sergey Svishchev
-#ifndef MAME_BUS_VME_VME_HCPU30_H
-#define MAME_BUS_VME_VME_HCPU30_H
-
-#pragma once
-
-#include "bus/vme/vme.h"
-#include "bus/rs232/rs232.h"
-#include "cpu/m68000/m68000.h"
-#include "machine/68230pit.h"
-#include "machine/scnxx562.h"
-#include "machine/terminal.h"
-#include "machine/wd33c9x.h"
-
-DECLARE_DEVICE_TYPE(VME_HCPU30, vme_hcpu30_card_device)
-
-class vme_hcpu30_card_device : public device_t, public device_vme_card_interface
-{
-public:
- vme_hcpu30_card_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
-
-protected:
- vme_hcpu30_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;
- virtual const tiny_rom_entry *device_rom_region() const override;
- virtual ioport_constructor device_input_ports() const override;
-
-private:
- required_device<cpu_device> m_maincpu;
- required_device<duscc68562_device> m_dusccterm;
-
- // 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];
-
- DECLARE_READ32_MEMBER(bootvect_r);
- DECLARE_WRITE32_MEMBER(bootvect_w);
-
- void hcpu30_mem(address_map &map);
-};
-
-#endif // MAME_BUS_VME_VME_HCPU30_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/keyboard.cpp b/src/devices/bus/vsmile/keyboard.cpp
new file mode 100644
index 00000000000..cdd2f13c914
--- /dev/null
+++ b/src/devices/bus/vsmile/keyboard.cpp
@@ -0,0 +1,566 @@
+// license:BSD-3-Clause
+// copyright-holders:Ryan Holtz, Vas Crabb
+
+#include "emu.h"
+#include "keyboard.h"
+
+#include "machine/keyboard.ipp"
+
+#include <algorithm>
+
+//#define VERBOSE 1
+#include "logmacro.h"
+
+
+//**************************************************************************
+// GLOBAL VARIABLES
+//**************************************************************************
+
+DEFINE_DEVICE_TYPE(VSMILE_KEYBOARD_US, vsmile_keyboard_us_device, "vsmile_keyboard_us", "V.Smile Keyboard (US)")
+DEFINE_DEVICE_TYPE(VSMILE_KEYBOARD_FR, vsmile_keyboard_fr_device, "vsmile_keyboard_fr", "V.Smile Keyboard (FR)")
+DEFINE_DEVICE_TYPE(VSMILE_KEYBOARD_GE, vsmile_keyboard_ge_device, "vsmile_keyboard_ge", "V.Smile Keyboard (GE)")
+
+
+//**************************************************************************
+// V.Smile Keyboard
+//**************************************************************************
+
+vsmile_keyboard_us_device::vsmile_keyboard_us_device(machine_config const &mconfig, char const *tag, device_t *owner, uint32_t clock)
+ : vsmile_keyboard_device(mconfig, VSMILE_KEYBOARD_US, tag, owner, clock, 0x40)
+{
+}
+
+vsmile_keyboard_fr_device::vsmile_keyboard_fr_device(machine_config const &mconfig, char const *tag, device_t *owner, uint32_t clock)
+ : vsmile_keyboard_device(mconfig, VSMILE_KEYBOARD_FR, tag, owner, clock, 0x42)
+{
+}
+
+vsmile_keyboard_ge_device::vsmile_keyboard_ge_device(machine_config const &mconfig, char const *tag, device_t *owner, uint32_t clock)
+ : vsmile_keyboard_device(mconfig, VSMILE_KEYBOARD_GE, tag, owner, clock, 0x44)
+{
+}
+
+vsmile_keyboard_device::vsmile_keyboard_device(machine_config const &mconfig, device_type type, char const *tag, device_t *owner, uint32_t clock, uint8_t layout_type)
+ : vsmile_ctrl_device_base(mconfig, type, tag, owner, clock)
+ , device_matrix_keyboard_interface(mconfig, *this, "ROW0", "ROW1", "ROW2", "ROW3", "ROW4")
+ , m_io_joy(*this, "JOY")
+ , m_io_keys(*this, "ROW%u", 0U)
+ , m_io_buttons(*this, "BUTTONS")
+ , m_layout_type(layout_type)
+ , m_state(STATE_HELLO_MESSAGE)
+ , m_sent_joy(0x0000U)
+ , m_sent_buttons(0x0000U)
+ , m_active(false)
+ , m_idle_timer(nullptr)
+ , m_hello_timer(nullptr)
+ , m_hello_timeout_timer(nullptr)
+{
+ std::fill(std::begin(m_ctrl_probe_history), std::end(m_ctrl_probe_history), 0U);
+ m_stale = stale_all();
+}
+
+vsmile_keyboard_device::~vsmile_keyboard_device()
+{
+}
+
+void vsmile_keyboard_device::device_start()
+{
+ vsmile_ctrl_device_base::device_start();
+
+ m_idle_timer = timer_alloc(FUNC(vsmile_keyboard_device::handle_idle), this);
+ m_hello_timer = timer_alloc(FUNC(vsmile_keyboard_device::handle_hello), this);
+ m_hello_timeout_timer = timer_alloc(FUNC(vsmile_keyboard_device::handle_hello_timeout), this);
+
+ save_item(NAME(m_state));
+ save_item(NAME(m_sent_joy));
+ save_item(NAME(m_sent_buttons));
+ save_item(NAME(m_stale));
+ save_item(NAME(m_active));
+ save_item(NAME(m_ctrl_probe_history));
+}
+
+void vsmile_keyboard_device::device_reset()
+{
+ m_state = STATE_HELLO_MESSAGE;
+ m_sent_joy = 0x0000U;
+ m_sent_buttons = 0x0000U;
+ m_stale = stale_all();
+ m_active = false;
+
+ m_idle_timer->adjust(attotime::never);
+ m_hello_timer->adjust(attotime::from_msec(300));
+ m_hello_timeout_timer->adjust(attotime::never);
+
+ reset_key_state();
+ typematic_stop();
+}
+
+bool vsmile_keyboard_device::translate(uint8_t code, uint8_t &translated) const
+{
+ const uint8_t row((code >> 4) & 0x0fU);
+ const uint8_t col((code >> 0) & 0x0fU);
+
+ static const uint8_t s_mapping[5][16] = {
+ { 0x33, 0x34, 0x35, 0x37, 0x36, 0x30, 0x31, 0x3e, 0x3f, 0x38, 0x29, 0x39, 0x00, 0x00, 0x00, 0x00 },
+ { 0x22, 0x23, 0x24, 0x25, 0x27, 0x26, 0x20, 0x21, 0x3a, 0x3b, 0x3c, 0x2a, 0x3d, 0x00, 0x00, 0x00 },
+ { 0x1a, 0x1b, 0x1c, 0x1d, 0x1f, 0x1e, 0x18, 0x19, 0x0a, 0x0b, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00 },
+ { 0xa9, 0x13, 0x14, 0x15, 0x17, 0x16, 0x08, 0x11, 0x0c, 0x2f, 0x12, 0x00, 0x00, 0x00, 0x00, 0x00 },
+ { 0x04, 0x2c, 0x05, 0x0e, 0x06, 0x0f, 0x0d, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }
+ };
+
+ translated = s_mapping[row][col];
+ return translated != 0;
+}
+
+void vsmile_keyboard_device::key_make(uint8_t row, uint8_t column)
+{
+ uint8_t translated = 0;
+ if (translate((row << 4) | column, translated))
+ uart_tx_fifo_push(translated);
+}
+
+void vsmile_keyboard_device::key_break(uint8_t row, uint8_t column)
+{
+ uint8_t translated = 0;
+ if (translate((row << 4) | column, translated))
+ {
+ // Shift has a different break code than usual
+ if (translated == 0xa9)
+ uart_tx_fifo_push(0xaa);
+ else
+ uart_tx_fifo_push(translated | 0xc0);
+ }
+}
+
+void vsmile_keyboard_device::tx_complete()
+{
+ if (m_state != STATE_RUNNING)
+ {
+ return;
+ }
+
+ enter_active_state();
+}
+
+void vsmile_keyboard_device::enter_active_state()
+{
+ if (!m_active)
+ LOG("entered active state\n");
+ m_idle_timer->adjust(attotime::from_seconds(1));
+ m_active = true;
+ m_stale = STALE_NONE;
+}
+
+void vsmile_keyboard_device::tx_timeout()
+{
+ if (m_active)
+ {
+ m_idle_timer->reset();
+ m_active = false;
+ m_stale = stale_all();
+ std::fill(std::begin(m_ctrl_probe_history), std::end(m_ctrl_probe_history), 0U);
+ LOG("left active state\n");
+ }
+ uart_tx_fifo_push(0x55);
+}
+
+void vsmile_keyboard_device::rx_complete(uint8_t data, bool select)
+{
+ if (m_state != STATE_RUNNING)
+ {
+ switch (m_state)
+ {
+ case STATE_HELLO_RECEIVE_BYTE1:
+ case STATE_HELLO_RECEIVE_BYTE2:
+ if (data != 0x02)
+ LOG("unknown power-up message response byte: %02x\n", data);
+ else
+ LOG("received power-up message response byte: %02x\n", data);
+ m_state++;
+ break;
+ case STATE_HELLO_REPLY_BYTE1:
+ if (data != 0xe6)
+ LOG("unknown power-up message reply byte 1: %02x\n", data);
+ m_state++;
+ break;
+ case STATE_HELLO_REPLY_BYTE2:
+ if (data != 0xd6)
+ LOG("unknown power-up message reply byte 2: %02x\n", data);
+ m_state++;
+ break;
+ case STATE_HELLO_REPLY_BYTE3:
+ if (data != 0x60)
+ LOG("unknown power-up message reply byte 3: %02x\n", data);
+ uart_tx_fifo_push(m_layout_type);
+ m_state = STATE_RUNNING;
+ m_idle_timer->adjust(attotime::from_seconds(1));
+ start_processing(attotime::from_hz(2'400));
+ m_active = true;
+ break;
+ }
+ return;
+ }
+
+ if (select)
+ {
+ if (((data & 0xf0) == 0x70) || ((data & 0xf0) == 0xb0))
+ {
+ m_ctrl_probe_history[0] = ((data & 0xf0) == 0x70) ? 0 : m_ctrl_probe_history[1];
+ m_ctrl_probe_history[1] = data;
+ uint8_t const response = ((m_ctrl_probe_history[0] + m_ctrl_probe_history[1] + 0x0f) & 0x0f) ^ 0x05;
+ LOG(
+ "%s: received probe %02X, %02X, sending response %02X\n",
+ machine().describe_context(),
+ m_ctrl_probe_history[0],
+ m_ctrl_probe_history[1],
+ 0xb0 | response);
+ uart_tx_fifo_push(0xb0 | response);
+ }
+ }
+}
+
+void vsmile_keyboard_device::uart_tx_fifo_push(uint8_t data)
+{
+ m_idle_timer->reset();
+ queue_tx(data);
+}
+
+TIMER_CALLBACK_MEMBER(vsmile_keyboard_device::handle_idle)
+{
+ LOG("idle timer expired, sending keep-alive 55\n");
+ queue_tx(0x55);
+}
+
+TIMER_CALLBACK_MEMBER(vsmile_keyboard_device::handle_hello)
+{
+ LOG("hello timer expired, raising RTS\n");
+ rts_out(1);
+ m_hello_timeout_timer->adjust(attotime::from_usec(12200));
+}
+
+TIMER_CALLBACK_MEMBER(vsmile_keyboard_device::handle_hello_timeout)
+{
+ rts_out(0);
+ if (!is_selected())
+ {
+ LOG("hello timed out without selection, restarting hello timer\n");
+ m_hello_timer->adjust(attotime::from_msec(300));
+ }
+ else
+ {
+ LOG("hello timed out and we're selected, sending hello bytes\n");
+ uart_tx_fifo_push(0x52);
+ uart_tx_fifo_push(0x52);
+ uart_tx_fifo_push(0x52);
+ m_state++;
+ }
+}
+
+INPUT_CHANGED_MEMBER(vsmile_keyboard_device::joy_changed)
+{
+ if (m_active && m_state == STATE_RUNNING)
+ {
+ if (!is_tx_empty())
+ {
+ LOG("joy changed while transmission in progress, marking stale\n");
+ m_stale |= stale_non_key_inputs(param);
+ }
+ else
+ {
+ uint8_t const joy = m_io_joy->read();
+ if ((joy ^ m_sent_joy) & 0x03)
+ {
+ if (BIT(joy, 0))
+ uart_tx_fifo_push(0x87); // up
+ else if (BIT(joy, 1))
+ uart_tx_fifo_push(0x8f); // down
+ else
+ uart_tx_fifo_push(0x80);
+ }
+ if ((joy ^ m_sent_joy) & 0x0c)
+ {
+ if (BIT(joy, 2))
+ uart_tx_fifo_push(0x7f); // left
+ else if (BIT(joy, 3))
+ uart_tx_fifo_push(0x77); // right
+ else
+ uart_tx_fifo_push(0x70);
+ }
+ m_sent_joy = joy;
+ }
+ }
+}
+
+INPUT_CHANGED_MEMBER(vsmile_keyboard_device::button_changed)
+{
+ if (m_active && m_state == STATE_RUNNING)
+ {
+ if (!is_tx_empty())
+ {
+ LOG("buttons changed while transmission in progress, marking stale\n");
+ m_stale |= stale_non_key_inputs(param);
+ }
+ else
+ {
+ uint8_t const buttons = m_io_buttons->read();
+ if (BIT((m_sent_buttons ^ buttons) & buttons, 0))
+ uart_tx_fifo_push(0xa1);
+ if (BIT((m_sent_buttons ^ buttons) & buttons, 1))
+ uart_tx_fifo_push(0xa2);
+ if (BIT((m_sent_buttons ^ buttons) & buttons, 2))
+ uart_tx_fifo_push(0xa3);
+ if (!buttons)
+ uart_tx_fifo_push(0xa0);
+ m_sent_buttons = buttons;
+ }
+ }
+}
+
+static INPUT_PORTS_START( vsmile_keyboard_common )
+ PORT_START("JOY")
+ PORT_BIT( 0x01, IP_ACTIVE_HIGH, IPT_JOYSTICK_UP ) PORT_CHANGED_MEMBER(DEVICE_SELF, FUNC(vsmile_keyboard_device::joy_changed), vsmile_keyboard_device::STALE_UP_DOWN) PORT_NAME("Joypad Up")
+ PORT_BIT( 0x02, IP_ACTIVE_HIGH, IPT_JOYSTICK_DOWN ) PORT_CHANGED_MEMBER(DEVICE_SELF, FUNC(vsmile_keyboard_device::joy_changed), vsmile_keyboard_device::STALE_UP_DOWN) PORT_NAME("Joypad Down")
+ PORT_BIT( 0x04, IP_ACTIVE_HIGH, IPT_JOYSTICK_LEFT ) PORT_CHANGED_MEMBER(DEVICE_SELF, FUNC(vsmile_keyboard_device::joy_changed), vsmile_keyboard_device::STALE_LEFT_RIGHT) PORT_NAME("Joypad Left")
+ PORT_BIT( 0x08, IP_ACTIVE_HIGH, IPT_JOYSTICK_RIGHT ) PORT_CHANGED_MEMBER(DEVICE_SELF, FUNC(vsmile_keyboard_device::joy_changed), vsmile_keyboard_device::STALE_LEFT_RIGHT) PORT_NAME("Joypad Right")
+ PORT_BIT( 0xf0, IP_ACTIVE_HIGH, IPT_UNUSED )
+
+ PORT_START("BUTTONS")
+ PORT_BIT( 0x01, IP_ACTIVE_HIGH, IPT_BUTTON1 ) PORT_CHANGED_MEMBER(DEVICE_SELF, FUNC(vsmile_keyboard_device::button_changed), vsmile_keyboard_device::STALE_OK) PORT_NAME("OK") PORT_CODE(KEYCODE_ENTER)
+ PORT_BIT( 0x02, IP_ACTIVE_HIGH, IPT_BUTTON2 ) PORT_CHANGED_MEMBER(DEVICE_SELF, FUNC(vsmile_keyboard_device::button_changed), vsmile_keyboard_device::STALE_QUIT) PORT_NAME("Quit/Escape")
+ PORT_BIT( 0x04, IP_ACTIVE_HIGH, IPT_BUTTON3 ) PORT_CHANGED_MEMBER(DEVICE_SELF, FUNC(vsmile_keyboard_device::button_changed), vsmile_keyboard_device::STALE_HELP) PORT_NAME("Help")
+ PORT_BIT( 0xf8, IP_ACTIVE_HIGH, IPT_UNUSED )
+INPUT_PORTS_END
+
+static INPUT_PORTS_START( vsmile_keyboard_us )
+ PORT_INCLUDE( vsmile_keyboard_common )
+
+ PORT_START("ROW0")
+ PORT_BIT( 0x0001, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CODE(KEYCODE_1) PORT_CHAR('1') PORT_CHAR('!')
+ PORT_BIT( 0x0002, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CODE(KEYCODE_2) PORT_CHAR('2') PORT_CHAR('@')
+ PORT_BIT( 0x0004, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CODE(KEYCODE_3) PORT_CHAR('3') PORT_CHAR('#')
+ PORT_BIT( 0x0008, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CODE(KEYCODE_4) PORT_CHAR('4') PORT_CHAR('$')
+ PORT_BIT( 0x0010, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CODE(KEYCODE_5) PORT_CHAR('5') PORT_CHAR('%')
+ PORT_BIT( 0x0020, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CODE(KEYCODE_6) PORT_CHAR('6') PORT_CHAR('^')
+ PORT_BIT( 0x0040, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CODE(KEYCODE_7) PORT_CHAR('7') PORT_CHAR('&')
+ PORT_BIT( 0x0080, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CODE(KEYCODE_8) PORT_CHAR('8') PORT_CHAR('*')
+ PORT_BIT( 0x0100, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CODE(KEYCODE_9) PORT_CHAR('9') PORT_CHAR('(')
+ PORT_BIT( 0x0200, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CODE(KEYCODE_0) PORT_CHAR('0') PORT_CHAR(')')
+ PORT_BIT( 0x0400, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CODE(KEYCODE_MINUS) PORT_CHAR('-') PORT_CHAR('+')
+ PORT_BIT( 0x0800, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CODE(KEYCODE_BACKSPACE) PORT_CHAR(8)
+ PORT_BIT( 0xf000, IP_ACTIVE_HIGH, IPT_UNUSED )
+
+ PORT_START("ROW1")
+ PORT_BIT( 0x0001, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CODE(KEYCODE_TAB) PORT_NAME("Typing Time")
+ PORT_BIT( 0x0002, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CODE(KEYCODE_Q) PORT_CHAR('q') PORT_CHAR('Q')
+ PORT_BIT( 0x0004, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CODE(KEYCODE_W) PORT_CHAR('w') PORT_CHAR('W')
+ PORT_BIT( 0x0008, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CODE(KEYCODE_E) PORT_CHAR('e') PORT_CHAR('E')
+ PORT_BIT( 0x0010, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CODE(KEYCODE_R) PORT_CHAR('r') PORT_CHAR('R')
+ PORT_BIT( 0x0020, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CODE(KEYCODE_T) PORT_CHAR('t') PORT_CHAR('T')
+ PORT_BIT( 0x0040, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CODE(KEYCODE_Y) PORT_CHAR('y') PORT_CHAR('Y')
+ PORT_BIT( 0x0080, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CODE(KEYCODE_U) PORT_CHAR('u') PORT_CHAR('U')
+ PORT_BIT( 0x0100, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CODE(KEYCODE_I) PORT_CHAR('i') PORT_CHAR('I')
+ PORT_BIT( 0x0200, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CODE(KEYCODE_O) PORT_CHAR('o') PORT_CHAR('O')
+ PORT_BIT( 0x0400, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CODE(KEYCODE_P) PORT_CHAR('p') PORT_CHAR('P')
+ PORT_BIT( 0x0800, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CODE(KEYCODE_OPENBRACE) PORT_CHAR('\'') PORT_CHAR('"')
+ PORT_BIT( 0x1000, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CODE(KEYCODE_CLOSEBRACE) PORT_NAME("Erase")
+ PORT_BIT( 0xe000, IP_ACTIVE_HIGH, IPT_UNUSED )
+
+ PORT_START("ROW2")
+ PORT_BIT( 0x0001, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CODE(KEYCODE_CAPSLOCK) PORT_NAME("Caps")
+ PORT_BIT( 0x0002, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CODE(KEYCODE_A) PORT_CHAR('a') PORT_CHAR('A')
+ PORT_BIT( 0x0004, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CODE(KEYCODE_S) PORT_CHAR('s') PORT_CHAR('S')
+ PORT_BIT( 0x0008, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CODE(KEYCODE_D) PORT_CHAR('d') PORT_CHAR('D')
+ PORT_BIT( 0x0010, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CODE(KEYCODE_F) PORT_CHAR('f') PORT_CHAR('F')
+ PORT_BIT( 0x0020, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CODE(KEYCODE_G) PORT_CHAR('g') PORT_CHAR('G')
+ PORT_BIT( 0x0040, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CODE(KEYCODE_H) PORT_CHAR('h') PORT_CHAR('H')
+ PORT_BIT( 0x0080, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CODE(KEYCODE_J) PORT_CHAR('j') PORT_CHAR('J')
+ PORT_BIT( 0x0100, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CODE(KEYCODE_K) PORT_CHAR('k') PORT_CHAR('K')
+ 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( 0xf800, IP_ACTIVE_HIGH, IPT_UNUSED )
+
+ PORT_START("ROW3")
+ PORT_BIT( 0x0001, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CODE(KEYCODE_LSHIFT) PORT_CHAR(UCHAR_SHIFT_1)
+ PORT_BIT( 0x0002, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CODE(KEYCODE_Z) PORT_CHAR('z') PORT_CHAR('Z')
+ PORT_BIT( 0x0004, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CODE(KEYCODE_X) PORT_CHAR('x') PORT_CHAR('X')
+ PORT_BIT( 0x0008, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CODE(KEYCODE_C) PORT_CHAR('c') PORT_CHAR('C')
+ PORT_BIT( 0x0010, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CODE(KEYCODE_V) PORT_CHAR('v') PORT_CHAR('V')
+ PORT_BIT( 0x0020, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CODE(KEYCODE_B) PORT_CHAR('b') PORT_CHAR('B')
+ PORT_BIT( 0x0040, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CODE(KEYCODE_N) PORT_CHAR('n') PORT_CHAR('N')
+ PORT_BIT( 0x0080, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CODE(KEYCODE_M) PORT_CHAR('m') PORT_CHAR('M')
+ PORT_BIT( 0x0100, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CODE(KEYCODE_COMMA) PORT_CHAR(',') PORT_CHAR('<')
+ PORT_BIT( 0x0200, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CODE(KEYCODE_STOP) PORT_CHAR('.') PORT_CHAR('>')
+ PORT_BIT( 0x0400, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CODE(KEYCODE_UP) PORT_NAME("Up")
+ PORT_BIT( 0xf800, IP_ACTIVE_HIGH, IPT_UNUSED )
+
+ PORT_START("ROW4")
+ PORT_BIT( 0x0001, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CODE(KEYCODE_1_PAD) PORT_NAME("Player 1")
+ PORT_BIT( 0x0002, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CODE(KEYCODE_PLUS_PAD) PORT_NAME("Symbol")
+ PORT_BIT( 0x0004, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CODE(KEYCODE_SPACE) PORT_CHAR(' ')
+ PORT_BIT( 0x0008, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CODE(KEYCODE_2_PAD) PORT_NAME("Player 2")
+ PORT_BIT( 0x0010, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CODE(KEYCODE_LEFT) PORT_NAME("Left")
+ PORT_BIT( 0x0020, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CODE(KEYCODE_DOWN) PORT_NAME("Down")
+ PORT_BIT( 0x0040, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CODE(KEYCODE_RIGHT) PORT_NAME("Right")
+ PORT_BIT( 0xff80, IP_ACTIVE_HIGH, IPT_UNUSED )
+INPUT_PORTS_END
+
+static INPUT_PORTS_START( vsmile_keyboard_fr )
+ PORT_INCLUDE( vsmile_keyboard_common )
+
+ PORT_START("ROW0")
+ PORT_BIT( 0x0001, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CODE(KEYCODE_1) PORT_CHAR('&') PORT_CHAR('1')
+ PORT_BIT( 0x0002, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CODE(KEYCODE_2) PORT_CHAR(0x00e9) PORT_CHAR('2')
+ PORT_BIT( 0x0004, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CODE(KEYCODE_3) PORT_CHAR('"') PORT_CHAR('3')
+ PORT_BIT( 0x0008, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CODE(KEYCODE_4) PORT_CHAR('\'') PORT_CHAR('4')
+ PORT_BIT( 0x0010, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CODE(KEYCODE_5) PORT_CHAR('(') PORT_CHAR('5')
+ PORT_BIT( 0x0020, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CODE(KEYCODE_6) PORT_CHAR('-') PORT_CHAR('6')
+ PORT_BIT( 0x0040, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CODE(KEYCODE_7) PORT_CHAR(0x00e8) PORT_CHAR('7')
+ PORT_BIT( 0x0080, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CODE(KEYCODE_8) PORT_CHAR('_') PORT_CHAR('8')
+ PORT_BIT( 0x0100, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CODE(KEYCODE_9) PORT_CHAR(0x00e7) PORT_CHAR('9')
+ PORT_BIT( 0x0200, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CODE(KEYCODE_0) PORT_CHAR(0x00e0) PORT_CHAR('0')
+ PORT_BIT( 0x0400, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CODE(KEYCODE_MINUS) PORT_CHAR(')') PORT_CHAR(0x00ba)
+ PORT_BIT( 0x0800, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CODE(KEYCODE_BACKSPACE) PORT_CHAR(8)
+ PORT_BIT( 0xf000, IP_ACTIVE_HIGH, IPT_UNUSED )
+
+ PORT_START("ROW1")
+ PORT_BIT( 0x0001, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CODE(KEYCODE_TAB) PORT_NAME("Mode Dactylo")
+ PORT_BIT( 0x0002, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CODE(KEYCODE_A) PORT_CHAR('a') PORT_CHAR('A')
+ PORT_BIT( 0x0004, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CODE(KEYCODE_Z) PORT_CHAR('z') PORT_CHAR('Z')
+ PORT_BIT( 0x0008, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CODE(KEYCODE_E) PORT_CHAR('e') PORT_CHAR('E')
+ PORT_BIT( 0x0010, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CODE(KEYCODE_R) PORT_CHAR('r') PORT_CHAR('R')
+ PORT_BIT( 0x0020, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CODE(KEYCODE_T) PORT_CHAR('t') PORT_CHAR('T')
+ PORT_BIT( 0x0040, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CODE(KEYCODE_Y) PORT_CHAR('y') PORT_CHAR('Y')
+ PORT_BIT( 0x0080, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CODE(KEYCODE_U) PORT_CHAR('u') PORT_CHAR('U')
+ PORT_BIT( 0x0100, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CODE(KEYCODE_I) PORT_CHAR('i') PORT_CHAR('I')
+ PORT_BIT( 0x0200, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CODE(KEYCODE_O) PORT_CHAR('o') PORT_CHAR('O')
+ PORT_BIT( 0x0400, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CODE(KEYCODE_P) PORT_CHAR('p') PORT_CHAR('P')
+ PORT_BIT( 0x0800, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CODE(KEYCODE_OPENBRACE) PORT_CHAR('^') PORT_CHAR(0x00a8)
+ PORT_BIT( 0x1000, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CODE(KEYCODE_CLOSEBRACE) PORT_NAME("Erase")
+ PORT_BIT( 0xe000, IP_ACTIVE_HIGH, IPT_UNUSED )
+
+ PORT_START("ROW2")
+ PORT_BIT( 0x0001, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CODE(KEYCODE_CAPSLOCK) PORT_NAME("Verr. Maj.")
+ PORT_BIT( 0x0002, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CODE(KEYCODE_Q) PORT_CHAR('q') PORT_CHAR('Q')
+ PORT_BIT( 0x0004, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CODE(KEYCODE_S) PORT_CHAR('s') PORT_CHAR('S')
+ PORT_BIT( 0x0008, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CODE(KEYCODE_D) PORT_CHAR('d') PORT_CHAR('D')
+ PORT_BIT( 0x0010, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CODE(KEYCODE_F) PORT_CHAR('f') PORT_CHAR('F')
+ PORT_BIT( 0x0020, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CODE(KEYCODE_G) PORT_CHAR('g') PORT_CHAR('G')
+ PORT_BIT( 0x0040, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CODE(KEYCODE_H) PORT_CHAR('h') PORT_CHAR('H')
+ PORT_BIT( 0x0080, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CODE(KEYCODE_J) PORT_CHAR('j') PORT_CHAR('J')
+ PORT_BIT( 0x0100, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CODE(KEYCODE_K) PORT_CHAR('k') PORT_CHAR('K')
+ 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_M) PORT_CHAR('m') PORT_CHAR('M')
+ PORT_BIT( 0xf800, IP_ACTIVE_HIGH, IPT_UNUSED )
+
+ PORT_START("ROW3")
+ PORT_BIT( 0x0001, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CODE(KEYCODE_LSHIFT) PORT_CHAR(UCHAR_SHIFT_1)
+ PORT_BIT( 0x0002, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CODE(KEYCODE_W) PORT_CHAR('w') PORT_CHAR('W')
+ PORT_BIT( 0x0004, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CODE(KEYCODE_X) PORT_CHAR('x') PORT_CHAR('X')
+ PORT_BIT( 0x0008, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CODE(KEYCODE_C) PORT_CHAR('c') PORT_CHAR('C')
+ PORT_BIT( 0x0010, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CODE(KEYCODE_V) PORT_CHAR('v') PORT_CHAR('V')
+ PORT_BIT( 0x0020, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CODE(KEYCODE_B) PORT_CHAR('b') PORT_CHAR('B')
+ PORT_BIT( 0x0040, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CODE(KEYCODE_N) PORT_CHAR('n') PORT_CHAR('N')
+ PORT_BIT( 0x0080, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CODE(KEYCODE_COMMA) PORT_CHAR(',') PORT_CHAR('?')
+ PORT_BIT( 0x0100, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CODE(KEYCODE_STOP) PORT_CHAR(';') PORT_CHAR('.')
+ PORT_BIT( 0x0200, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CODE(KEYCODE_SLASH) PORT_CHAR(':') PORT_CHAR('/')
+ PORT_BIT( 0x0400, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CODE(KEYCODE_UP) PORT_NAME("Up")
+ PORT_BIT( 0xf800, IP_ACTIVE_HIGH, IPT_UNUSED )
+
+ PORT_START("ROW4")
+ PORT_BIT( 0x0001, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CODE(KEYCODE_1_PAD) PORT_NAME("Player 1")
+ PORT_BIT( 0x0002, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CODE(KEYCODE_PLUS_PAD) PORT_NAME("Symbol")
+ PORT_BIT( 0x0004, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CODE(KEYCODE_SPACE) PORT_CHAR(' ')
+ PORT_BIT( 0x0008, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CODE(KEYCODE_2_PAD) PORT_NAME("Player 2")
+ PORT_BIT( 0x0010, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CODE(KEYCODE_LEFT) PORT_NAME("Left")
+ PORT_BIT( 0x0020, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CODE(KEYCODE_DOWN) PORT_NAME("Down")
+ PORT_BIT( 0x0040, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CODE(KEYCODE_RIGHT) PORT_NAME("Right")
+ PORT_BIT( 0xff80, IP_ACTIVE_HIGH, IPT_UNUSED )
+INPUT_PORTS_END
+
+static INPUT_PORTS_START( vsmile_keyboard_ge )
+ PORT_INCLUDE( vsmile_keyboard_common )
+
+ PORT_START("ROW0")
+ PORT_BIT( 0x0001, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CODE(KEYCODE_1) PORT_CHAR('1') PORT_CHAR('!')
+ PORT_BIT( 0x0002, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CODE(KEYCODE_2) PORT_CHAR('2') PORT_CHAR('\"')
+ PORT_BIT( 0x0004, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CODE(KEYCODE_3) PORT_CHAR('3') PORT_CHAR('#')
+ PORT_BIT( 0x0008, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CODE(KEYCODE_4) PORT_CHAR('4') PORT_CHAR(0x20ac)
+ PORT_BIT( 0x0010, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CODE(KEYCODE_5) PORT_CHAR('5') PORT_CHAR('%')
+ PORT_BIT( 0x0020, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CODE(KEYCODE_6) PORT_CHAR('6') PORT_CHAR('&')
+ PORT_BIT( 0x0040, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CODE(KEYCODE_7) PORT_CHAR('7') PORT_CHAR('/')
+ PORT_BIT( 0x0080, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CODE(KEYCODE_8) PORT_CHAR('8') PORT_CHAR('(')
+ PORT_BIT( 0x0100, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CODE(KEYCODE_9) PORT_CHAR('9') PORT_CHAR(')')
+ PORT_BIT( 0x0200, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CODE(KEYCODE_0) PORT_CHAR('0') PORT_CHAR('=')
+ PORT_BIT( 0x0400, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CODE(KEYCODE_MINUS) PORT_CHAR(0x00df) PORT_CHAR('?')
+ PORT_BIT( 0x0800, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CODE(KEYCODE_BACKSPACE) PORT_CHAR(8)
+ PORT_BIT( 0xf000, IP_ACTIVE_HIGH, IPT_UNUSED )
+
+ PORT_START("ROW1")
+ PORT_BIT( 0x0001, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CODE(KEYCODE_TAB) PORT_NAME("Tipp-Trainer")
+ PORT_BIT( 0x0002, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CODE(KEYCODE_Q) PORT_CHAR('q') PORT_CHAR('Q')
+ PORT_BIT( 0x0004, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CODE(KEYCODE_W) PORT_CHAR('w') PORT_CHAR('W')
+ PORT_BIT( 0x0008, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CODE(KEYCODE_E) PORT_CHAR('e') PORT_CHAR('E')
+ PORT_BIT( 0x0010, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CODE(KEYCODE_R) PORT_CHAR('r') PORT_CHAR('R')
+ PORT_BIT( 0x0020, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CODE(KEYCODE_T) PORT_CHAR('t') PORT_CHAR('T')
+ PORT_BIT( 0x0040, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CODE(KEYCODE_Z) PORT_CHAR('z') PORT_CHAR('Z')
+ PORT_BIT( 0x0080, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CODE(KEYCODE_U) PORT_CHAR('u') PORT_CHAR('U')
+ PORT_BIT( 0x0100, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CODE(KEYCODE_I) PORT_CHAR('i') PORT_CHAR('I')
+ PORT_BIT( 0x0200, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CODE(KEYCODE_O) PORT_CHAR('o') PORT_CHAR('O')
+ PORT_BIT( 0x0400, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CODE(KEYCODE_P) PORT_CHAR('p') PORT_CHAR('P')
+ PORT_BIT( 0x0800, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CODE(KEYCODE_OPENBRACE) PORT_CHAR(0x00fc) PORT_CHAR(0x00dc)
+ PORT_BIT( 0x1000, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CODE(KEYCODE_CLOSEBRACE) PORT_NAME("Erase")
+ PORT_BIT( 0xe000, IP_ACTIVE_HIGH, IPT_UNUSED )
+
+ PORT_START("ROW2")
+ PORT_BIT( 0x0001, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CODE(KEYCODE_CAPSLOCK) PORT_NAME("Feststelltaste")
+ PORT_BIT( 0x0002, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CODE(KEYCODE_A) PORT_CHAR('a') PORT_CHAR('A')
+ PORT_BIT( 0x0004, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CODE(KEYCODE_S) PORT_CHAR('s') PORT_CHAR('S')
+ PORT_BIT( 0x0008, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CODE(KEYCODE_D) PORT_CHAR('d') PORT_CHAR('D')
+ PORT_BIT( 0x0010, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CODE(KEYCODE_F) PORT_CHAR('f') PORT_CHAR('F')
+ PORT_BIT( 0x0020, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CODE(KEYCODE_G) PORT_CHAR('g') PORT_CHAR('G')
+ PORT_BIT( 0x0040, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CODE(KEYCODE_H) PORT_CHAR('h') PORT_CHAR('H')
+ PORT_BIT( 0x0080, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CODE(KEYCODE_J) PORT_CHAR('j') PORT_CHAR('J')
+ PORT_BIT( 0x0100, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CODE(KEYCODE_K) PORT_CHAR('k') PORT_CHAR('K')
+ 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(0x00f6) PORT_CHAR(0x00d6)
+ PORT_BIT( 0xf800, IP_ACTIVE_HIGH, IPT_UNUSED )
+
+ PORT_START("ROW3")
+ PORT_BIT( 0x0001, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CODE(KEYCODE_LSHIFT) PORT_CHAR(UCHAR_SHIFT_1)
+ PORT_BIT( 0x0002, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CODE(KEYCODE_Y) PORT_CHAR('y') PORT_CHAR('Y')
+ PORT_BIT( 0x0004, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CODE(KEYCODE_X) PORT_CHAR('x') PORT_CHAR('X')
+ PORT_BIT( 0x0008, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CODE(KEYCODE_C) PORT_CHAR('c') PORT_CHAR('C')
+ PORT_BIT( 0x0010, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CODE(KEYCODE_V) PORT_CHAR('v') PORT_CHAR('V')
+ PORT_BIT( 0x0020, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CODE(KEYCODE_B) PORT_CHAR('b') PORT_CHAR('B')
+ PORT_BIT( 0x0040, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CODE(KEYCODE_N) PORT_CHAR('n') PORT_CHAR('N')
+ PORT_BIT( 0x0080, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CODE(KEYCODE_M) PORT_CHAR('m') PORT_CHAR('M')
+ PORT_BIT( 0x0100, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CODE(KEYCODE_COMMA) PORT_CHAR('.')
+ PORT_BIT( 0x0200, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CODE(KEYCODE_STOP) PORT_CHAR(0x00e4) PORT_CHAR(0x00c4)
+ PORT_BIT( 0x0400, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CODE(KEYCODE_UP) PORT_NAME("Up")
+ PORT_BIT( 0xf800, IP_ACTIVE_HIGH, IPT_UNUSED )
+
+ PORT_START("ROW4")
+ PORT_BIT( 0x0001, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CODE(KEYCODE_1_PAD) PORT_NAME("Player 1")
+ PORT_BIT( 0x0002, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CODE(KEYCODE_PLUS_PAD) PORT_NAME("Symbol")
+ PORT_BIT( 0x0004, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CODE(KEYCODE_SPACE) PORT_CHAR(' ')
+ PORT_BIT( 0x0008, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CODE(KEYCODE_2_PAD) PORT_NAME("Player 2")
+ PORT_BIT( 0x0010, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CODE(KEYCODE_LEFT) PORT_NAME("Left")
+ PORT_BIT( 0x0020, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CODE(KEYCODE_DOWN) PORT_NAME("Down")
+ PORT_BIT( 0x0040, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CODE(KEYCODE_RIGHT) PORT_NAME("Right")
+ PORT_BIT( 0xff80, IP_ACTIVE_HIGH, IPT_UNUSED )
+INPUT_PORTS_END
+
+ioport_constructor vsmile_keyboard_us_device::device_input_ports() const
+{
+ return INPUT_PORTS_NAME( vsmile_keyboard_us );
+}
+
+ioport_constructor vsmile_keyboard_fr_device::device_input_ports() const
+{
+ return INPUT_PORTS_NAME( vsmile_keyboard_fr );
+}
+
+ioport_constructor vsmile_keyboard_ge_device::device_input_ports() const
+{
+ return INPUT_PORTS_NAME( vsmile_keyboard_ge );
+}
diff --git a/src/devices/bus/vsmile/keyboard.h b/src/devices/bus/vsmile/keyboard.h
new file mode 100644
index 00000000000..b908e611caa
--- /dev/null
+++ b/src/devices/bus/vsmile/keyboard.h
@@ -0,0 +1,143 @@
+// license:BSD-3-Clause
+// copyright-holders:Ryan Holtz, Vas Crabb
+#ifndef MAME_BUS_VSMILE_KEYBOARD_H
+#define MAME_BUS_VSMILE_KEYBOARD_H
+
+#pragma once
+
+#include "vsmile_ctrl.h"
+
+#include "machine/keyboard.h"
+
+/***************************************************************************
+ TYPE DEFINITIONS
+ ***************************************************************************/
+
+// ======================> vsmile_keyboard_device
+
+class vsmile_keyboard_device : public vsmile_ctrl_device_base, protected device_matrix_keyboard_interface<5U>
+{
+public:
+ // construction/destruction
+ virtual ~vsmile_keyboard_device();
+
+ // input handlers
+ DECLARE_INPUT_CHANGED_MEMBER(joy_changed);
+ DECLARE_INPUT_CHANGED_MEMBER(key_changed);
+ DECLARE_INPUT_CHANGED_MEMBER(button_changed);
+
+ enum stale_non_key_inputs : uint16_t
+ {
+ STALE_NONE = 0U,
+ STALE_LEFT_RIGHT = 1U << 0,
+ STALE_UP_DOWN = 1U << 1,
+ STALE_OK = 1U << 3,
+ STALE_QUIT = 1U << 4,
+ STALE_HELP = 1U << 5,
+
+ STALE_JOY = STALE_LEFT_RIGHT | STALE_UP_DOWN,
+ STALE_BUTTONS = STALE_OK | STALE_QUIT | STALE_HELP,
+ STALE_ALL = STALE_JOY | STALE_BUTTONS
+ };
+
+ enum comms_state : uint8_t
+ {
+ STATE_POWERUP = 0U,
+ STATE_HELLO_MESSAGE,
+ STATE_HELLO_RECEIVE_BYTE1,
+ STATE_HELLO_RECEIVE_BYTE2,
+ STATE_HELLO_REPLY_BYTE1,
+ STATE_HELLO_REPLY_BYTE2,
+ STATE_HELLO_REPLY_BYTE3,
+ STATE_RUNNING
+ };
+
+protected:
+ vsmile_keyboard_device(machine_config const &mconfig, device_type type, char const *tag, device_t *owner, uint32_t clock, uint8_t layout_type);
+
+ // device_t implementation
+ virtual void device_start() override ATTR_COLD;
+ virtual void device_reset() override ATTR_COLD;
+
+ // vsmile_ctrl_device_base implementation
+ virtual void tx_complete() override;
+ virtual void tx_timeout() override;
+ virtual void rx_complete(uint8_t data, bool cts) override;
+
+ // device_matrix_keyboard_interface implementation
+ virtual void key_make(uint8_t row, uint8_t column) override;
+ virtual void key_break(uint8_t row, uint8_t column) override;
+
+ uint16_t stale_all() { return STALE_ALL; }
+ bool translate(uint8_t code, uint8_t &translated) const;
+
+ void enter_active_state();
+
+ void uart_tx_fifo_push(uint8_t data);
+
+ required_ioport m_io_joy;
+ required_ioport_array<5> m_io_keys;
+ required_ioport m_io_buttons;
+
+ const uint8_t m_layout_type;
+
+ uint8_t m_state;
+
+ uint16_t m_sent_joy, m_sent_buttons;
+
+ uint16_t m_stale;
+ bool m_active;
+ emu_timer *m_idle_timer;
+ emu_timer *m_hello_timer;
+ emu_timer *m_hello_timeout_timer;
+
+private:
+ TIMER_CALLBACK_MEMBER(handle_idle);
+ TIMER_CALLBACK_MEMBER(handle_hello);
+ TIMER_CALLBACK_MEMBER(handle_hello_timeout);
+
+ uint8_t m_ctrl_probe_history[2];
+};
+
+class vsmile_keyboard_us_device : public vsmile_keyboard_device
+{
+public:
+ // construction/destruction
+ vsmile_keyboard_us_device(machine_config const &mconfig, char const *tag, device_t *owner, uint32_t clock = 0U);
+
+protected:
+ // device_t implementation
+ virtual ioport_constructor device_input_ports() const override ATTR_COLD;
+};
+
+class vsmile_keyboard_fr_device : public vsmile_keyboard_device
+{
+public:
+ // construction/destruction
+ vsmile_keyboard_fr_device(machine_config const &mconfig, char const *tag, device_t *owner, uint32_t clock = 0U);
+
+protected:
+ // device_t implementation
+ virtual ioport_constructor device_input_ports() const override ATTR_COLD;
+};
+
+class vsmile_keyboard_ge_device : public vsmile_keyboard_device
+{
+public:
+ // construction/destruction
+ vsmile_keyboard_ge_device(machine_config const &mconfig, char const *tag, device_t *owner, uint32_t clock = 0U);
+
+protected:
+ // device_t implementation
+ virtual ioport_constructor device_input_ports() const override ATTR_COLD;
+};
+
+/***************************************************************************
+ DEVICE TYPES
+ ***************************************************************************/
+
+DECLARE_DEVICE_TYPE(VSMILE_KEYBOARD_US, vsmile_keyboard_us_device)
+DECLARE_DEVICE_TYPE(VSMILE_KEYBOARD_FR, vsmile_keyboard_fr_device)
+DECLARE_DEVICE_TYPE(VSMILE_KEYBOARD_GE, vsmile_keyboard_ge_device)
+
+#endif // MAME_BUS_VSMILE_KEYBOARD_H
diff --git a/src/devices/bus/vsmile/mat.cpp b/src/devices/bus/vsmile/mat.cpp
new file mode 100644
index 00000000000..20a634d0a03
--- /dev/null
+++ b/src/devices/bus/vsmile/mat.cpp
@@ -0,0 +1,198 @@
+// license:BSD-3-Clause
+// copyright-holders:Ryan Holtz, Vas Crabb
+
+#include "emu.h"
+#include "mat.h"
+
+#include <algorithm>
+
+//#define VERBOSE 1
+#include "logmacro.h"
+
+
+//**************************************************************************
+// GLOBAL VARIABLES
+//**************************************************************************
+
+DEFINE_DEVICE_TYPE(VSMILE_MAT, vsmile_mat_device, "vsmile_mat", "V.Smile Gym Mat")
+
+
+//**************************************************************************
+// V.Smile gym mat
+//**************************************************************************
+
+vsmile_mat_device::vsmile_mat_device(machine_config const &mconfig, char const *tag, device_t *owner, uint32_t clock)
+ : vsmile_pad_device(mconfig, VSMILE_MAT, tag, owner, clock)
+ , m_io_joy(*this, "JOY")
+ , m_io_colors(*this, "COLORS")
+ , m_io_buttons(*this, "BUTTONS")
+{
+}
+
+vsmile_mat_device::~vsmile_mat_device()
+{
+}
+
+void vsmile_mat_device::tx_complete()
+{
+ // update "joystick"-mapped mat pads
+ if ((m_stale & STALE_JOY) != STALE_NONE)
+ {
+ m_sent_joy = m_io_joy->read();
+ if ((m_stale & STALE_YELLOW_RIGHT) != STALE_NONE)
+ {
+ if (BIT(m_sent_joy, 0))
+ uart_tx_fifo_push(0xcb); // yellow
+ else if (BIT(m_sent_joy, 1))
+ uart_tx_fifo_push(0xcd); // right
+ else
+ uart_tx_fifo_push(0xc0);
+ }
+ if ((m_stale & STALE_RED_LEFT) != STALE_NONE)
+ {
+ if (BIT(m_sent_joy, 2))
+ uart_tx_fifo_push(0x8b); // red
+ else if (BIT(m_sent_joy, 3))
+ uart_tx_fifo_push(0x8d); // left
+ else
+ uart_tx_fifo_push(0x80);
+ }
+ }
+
+ // update "color"-mapped mat pads
+ if ((m_stale & STALE_COLORS) != STALE_NONE)
+ {
+ m_sent_colors = m_io_colors->read();
+ uart_tx_fifo_push(0x90 | m_sent_colors);
+ }
+
+ // update "button"-mapped mat pads
+ if ((m_stale & STALE_BUTTONS) != STALE_NONE)
+ {
+ m_sent_buttons = m_io_buttons->read();
+ if (((m_stale & STALE_OK) != STALE_NONE) && BIT(m_sent_buttons, 0))
+ uart_tx_fifo_push(0xa1);
+ if (((m_stale & STALE_QUIT) != STALE_NONE) && BIT(m_sent_buttons, 1))
+ uart_tx_fifo_push(0xa2);
+ if (((m_stale & STALE_HELP) != STALE_NONE) && BIT(m_sent_buttons, 2))
+ uart_tx_fifo_push(0xa3);
+ if (((m_stale & STALE_BLUE) != STALE_NONE) && BIT(m_sent_buttons, 3))
+ uart_tx_fifo_push(0xa4);
+ if (!m_sent_buttons)
+ uart_tx_fifo_push(0xa0);
+ }
+
+ // if nothing happens in the next second we'll queue a keep-alive
+ if (!m_active)
+ LOG("entered active state\n");
+ m_idle_timer->adjust(attotime::from_seconds(1));
+ m_active = true;
+ m_stale = STALE_NONE;
+}
+
+INPUT_CHANGED_MEMBER(vsmile_mat_device::mat_joy_changed)
+{
+ if (m_active)
+ {
+ if (!is_tx_empty())
+ {
+ LOG("joy changed while transmission in progress, marking stale\n");
+ m_stale |= stale_mat_inputs(param);
+ }
+ else
+ {
+ uint8_t const joy = m_io_joy->read();
+ if ((joy ^ m_sent_joy) & 0x03)
+ {
+ if (BIT(joy, 0))
+ uart_tx_fifo_push(0xcb); // yellow
+ else if (BIT(joy, 1))
+ uart_tx_fifo_push(0xcd); // right
+ else
+ uart_tx_fifo_push(0xc0);
+ }
+ if ((joy ^ m_sent_joy) & 0x0c)
+ {
+ if (BIT(joy, 2))
+ uart_tx_fifo_push(0x8b); // red
+ else if (BIT(joy, 3))
+ uart_tx_fifo_push(0x8d); // left
+ else
+ uart_tx_fifo_push(0x80);
+ }
+ m_sent_joy = joy;
+ }
+ }
+}
+
+INPUT_CHANGED_MEMBER(vsmile_mat_device::mat_color_changed)
+{
+ if (m_active)
+ {
+ if (!is_tx_empty())
+ {
+ LOG("colors changed while transmission in progress, marking stale\n");
+ m_stale |= STALE_COLORS;
+ }
+ else
+ {
+ m_sent_colors = m_io_colors->read();
+ uart_tx_fifo_push(0x90 | m_sent_colors);
+ }
+ }
+}
+
+INPUT_CHANGED_MEMBER(vsmile_mat_device::mat_button_changed)
+{
+ if (m_active)
+ {
+ if (!is_tx_empty())
+ {
+ LOG("buttons changed while transmission in progress, marking stale\n");
+ m_stale |= stale_mat_inputs(param);
+ }
+ else
+ {
+ uint8_t const buttons = m_io_buttons->read();
+ if (BIT((m_sent_buttons ^ buttons) & buttons, 0))
+ uart_tx_fifo_push(0xa1);
+ if (BIT((m_sent_buttons ^ buttons) & buttons, 1))
+ uart_tx_fifo_push(0xa2);
+ if (BIT((m_sent_buttons ^ buttons) & buttons, 2))
+ uart_tx_fifo_push(0xa3);
+ if (BIT((m_sent_buttons ^ buttons) & buttons, 3))
+ uart_tx_fifo_push(0xa4);
+ if (!buttons)
+ uart_tx_fifo_push(0xa0);
+ m_sent_buttons = buttons;
+ }
+ }
+}
+
+static INPUT_PORTS_START( vsmile_mat )
+ PORT_START("JOY")
+ PORT_BIT( 0x01, IP_ACTIVE_HIGH, IPT_BUTTON1 ) PORT_CODE(KEYCODE_9_PAD) PORT_CODE(JOYCODE_BUTTON1) PORT_CHANGED_MEMBER(DEVICE_SELF, FUNC(vsmile_mat_device::mat_joy_changed), vsmile_mat_device::STALE_YELLOW_RIGHT) PORT_NAME("Yellow")
+ PORT_BIT( 0x02, IP_ACTIVE_HIGH, IPT_BUTTON2 ) PORT_CODE(KEYCODE_6_PAD) PORT_CODE(JOYCODE_BUTTON2) PORT_CHANGED_MEMBER(DEVICE_SELF, FUNC(vsmile_mat_device::mat_joy_changed), vsmile_mat_device::STALE_YELLOW_RIGHT) PORT_NAME("Right")
+ PORT_BIT( 0x04, IP_ACTIVE_HIGH, IPT_BUTTON3 ) PORT_CODE(KEYCODE_7_PAD) PORT_CODE(JOYCODE_BUTTON3) PORT_CHANGED_MEMBER(DEVICE_SELF, FUNC(vsmile_mat_device::mat_joy_changed), vsmile_mat_device::STALE_RED_LEFT) PORT_NAME("Red")
+ PORT_BIT( 0x08, IP_ACTIVE_HIGH, IPT_BUTTON4 ) PORT_CODE(KEYCODE_4_PAD) PORT_CODE(JOYCODE_BUTTON4) PORT_CHANGED_MEMBER(DEVICE_SELF, FUNC(vsmile_mat_device::mat_joy_changed), vsmile_mat_device::STALE_RED_LEFT) PORT_NAME("Left")
+ PORT_BIT( 0xf0, IP_ACTIVE_HIGH, IPT_UNUSED )
+
+ PORT_START("COLORS")
+ PORT_BIT( 0x01, IP_ACTIVE_HIGH, IPT_BUTTON5 ) PORT_CODE(KEYCODE_5_PAD) PORT_CODE(JOYCODE_BUTTON5) PORT_CHANGED_MEMBER(DEVICE_SELF, FUNC(vsmile_mat_device::mat_color_changed), vsmile_mat_device::STALE_COLORS) PORT_NAME("Center")
+ PORT_BIT( 0x02, IP_ACTIVE_HIGH, IPT_BUTTON6 ) PORT_CODE(KEYCODE_8_PAD) PORT_CODE(JOYCODE_BUTTON6) PORT_CHANGED_MEMBER(DEVICE_SELF, FUNC(vsmile_mat_device::mat_color_changed), vsmile_mat_device::STALE_COLORS) PORT_NAME("Up")
+ PORT_BIT( 0x04, IP_ACTIVE_HIGH, IPT_BUTTON7 ) PORT_CODE(KEYCODE_2_PAD) PORT_CODE(JOYCODE_BUTTON7) PORT_CHANGED_MEMBER(DEVICE_SELF, FUNC(vsmile_mat_device::mat_color_changed), vsmile_mat_device::STALE_COLORS) PORT_NAME("Down")
+ PORT_BIT( 0x08, IP_ACTIVE_HIGH, IPT_BUTTON8 ) PORT_CODE(KEYCODE_3_PAD) PORT_CODE(JOYCODE_BUTTON8) PORT_CHANGED_MEMBER(DEVICE_SELF, FUNC(vsmile_mat_device::mat_color_changed), vsmile_mat_device::STALE_COLORS) PORT_NAME("Green")
+ PORT_BIT( 0xf0, IP_ACTIVE_HIGH, IPT_UNUSED )
+
+ PORT_START("BUTTONS")
+ PORT_BIT( 0x01, IP_ACTIVE_HIGH, IPT_BUTTON9 ) PORT_CODE(KEYCODE_ENTER_PAD) PORT_CODE(JOYCODE_BUTTON9) PORT_CHANGED_MEMBER(DEVICE_SELF, FUNC(vsmile_mat_device::mat_button_changed), vsmile_mat_device::STALE_OK) PORT_NAME("OK")
+ PORT_BIT( 0x02, IP_ACTIVE_HIGH, IPT_BUTTON10 ) PORT_CODE(KEYCODE_0_PAD) PORT_CODE(JOYCODE_BUTTON10) PORT_CHANGED_MEMBER(DEVICE_SELF, FUNC(vsmile_mat_device::mat_button_changed), vsmile_mat_device::STALE_QUIT) PORT_NAME("Quit")
+ PORT_BIT( 0x04, IP_ACTIVE_HIGH, IPT_BUTTON11 ) PORT_CODE(KEYCODE_MINUS_PAD) PORT_CODE(JOYCODE_BUTTON11) PORT_CHANGED_MEMBER(DEVICE_SELF, FUNC(vsmile_mat_device::mat_button_changed), vsmile_mat_device::STALE_HELP) PORT_NAME("Help")
+ PORT_BIT( 0x08, IP_ACTIVE_HIGH, IPT_BUTTON12 ) PORT_CODE(KEYCODE_1_PAD) PORT_CODE(JOYCODE_BUTTON12) PORT_CHANGED_MEMBER(DEVICE_SELF, FUNC(vsmile_mat_device::mat_button_changed), vsmile_mat_device::STALE_BLUE) PORT_NAME("Blue")
+ PORT_BIT( 0xf0, IP_ACTIVE_HIGH, IPT_UNUSED )
+INPUT_PORTS_END
+
+ioport_constructor vsmile_mat_device::device_input_ports() const
+{
+ return INPUT_PORTS_NAME( vsmile_mat );
+}
diff --git a/src/devices/bus/vsmile/mat.h b/src/devices/bus/vsmile/mat.h
new file mode 100644
index 00000000000..fbebf762e57
--- /dev/null
+++ b/src/devices/bus/vsmile/mat.h
@@ -0,0 +1,70 @@
+// license:BSD-3-Clause
+// copyright-holders:Ryan Holtz, Vas Crabb
+#ifndef MAME_BUS_VSMILE_MAT_H
+#define MAME_BUS_VSMILE_MAT_H
+
+#pragma once
+
+#include "pad.h"
+
+/***************************************************************************
+ TYPE DEFINITIONS
+ ***************************************************************************/
+
+// ======================> vsmile_mat_device
+
+class vsmile_mat_device : public vsmile_pad_device
+{
+public:
+ // construction/destruction
+ vsmile_mat_device(machine_config const &mconfig, char const *tag, device_t *owner, uint32_t clock = 0U);
+ virtual ~vsmile_mat_device();
+
+ // input handlers
+ DECLARE_INPUT_CHANGED_MEMBER(mat_joy_changed);
+ DECLARE_INPUT_CHANGED_MEMBER(mat_color_changed);
+ DECLARE_INPUT_CHANGED_MEMBER(mat_button_changed);
+
+ enum stale_mat_inputs : uint16_t
+ {
+ STALE_NONE = 0U,
+ STALE_YELLOW_RIGHT = 1U << 0,
+ STALE_RED_LEFT = 1U << 1,
+ STALE_CENTER = 1U << 2,
+ STALE_UP = 1U << 3,
+ STALE_DOWN = 1U << 4,
+ STALE_GREEN = 1U << 5,
+ STALE_OK = 1U << 6,
+ STALE_QUIT = 1U << 7,
+ STALE_HELP = 1U << 8,
+ STALE_BLUE = 1U << 9,
+
+ STALE_JOY = STALE_YELLOW_RIGHT | STALE_RED_LEFT,
+ STALE_COLORS = STALE_CENTER | STALE_UP | STALE_DOWN | STALE_GREEN,
+ STALE_BUTTONS = STALE_OK | STALE_QUIT | STALE_HELP | STALE_BLUE,
+ STALE_ALL = STALE_JOY | STALE_COLORS | STALE_BUTTONS
+ };
+
+protected:
+ // device_t implementation
+ virtual ioport_constructor device_input_ports() const override ATTR_COLD;
+
+ // vsmile_pad_device implementation
+ virtual void tx_complete() override;
+
+ uint16_t stale_all() { return STALE_ALL; }
+
+private:
+ required_ioport m_io_joy;
+ required_ioport m_io_colors;
+ required_ioport m_io_buttons;
+};
+
+
+/***************************************************************************
+ DEVICE TYPES
+ ***************************************************************************/
+
+DECLARE_DEVICE_TYPE(VSMILE_MAT, vsmile_mat_device)
+
+#endif // MAME_BUS_VSMILE_MAT_H
diff --git a/src/devices/bus/vsmile/pad.cpp b/src/devices/bus/vsmile/pad.cpp
index 94c7decdaa9..1dae1a74511 100644
--- a/src/devices/bus/vsmile/pad.cpp
+++ b/src/devices/bus/vsmile/pad.cpp
@@ -21,22 +21,24 @@ DEFINE_DEVICE_TYPE(VSMILE_PAD, vsmile_pad_device, "vsmile_pad", "V.Smile Joystic
// V.Smile control pad
//**************************************************************************
-DECLARE_ENUM_BITWISE_OPERATORS(vsmile_pad_device::stale_inputs)
-ALLOW_SAVE_TYPE(vsmile_pad_device::stale_inputs);
-
vsmile_pad_device::vsmile_pad_device(machine_config const &mconfig, char const *tag, device_t *owner, uint32_t clock)
- : vsmile_ctrl_device_base(mconfig, VSMILE_PAD, tag, owner, clock)
+ : vsmile_pad_device(mconfig, VSMILE_PAD, tag, owner, clock)
+{
+}
+
+vsmile_pad_device::vsmile_pad_device(machine_config const &mconfig, device_type type, char const *tag, device_t *owner, uint32_t clock)
+ : vsmile_ctrl_device_base(mconfig, type, tag, owner, clock)
, m_io_joy(*this, "JOY")
, m_io_colors(*this, "COLORS")
, m_io_buttons(*this, "BUTTONS")
- , m_idle_timer(nullptr)
- , m_sent_joy(0x00U)
- , m_sent_colors(0x00U)
- , m_sent_buttons(0x00U)
- , m_stale(STALE_ALL)
+ , m_sent_joy(0x0000U)
+ , m_sent_colors(0x0000U)
+ , m_sent_buttons(0x0000U)
, m_active(false)
+ , m_idle_timer(nullptr)
{
std::fill(std::begin(m_ctrl_probe_history), std::end(m_ctrl_probe_history), 0U);
+ m_stale = stale_all();
}
vsmile_pad_device::~vsmile_pad_device()
@@ -47,14 +49,13 @@ void vsmile_pad_device::device_start()
{
vsmile_ctrl_device_base::device_start();
- m_idle_timer = machine().scheduler().timer_alloc(
- timer_expired_delegate(FUNC(vsmile_pad_device::handle_idle), this));
+ m_idle_timer = timer_alloc(FUNC(vsmile_pad_device::handle_idle), this);
m_idle_timer->adjust(attotime::from_seconds(1));
- m_sent_joy = 0x00U;
- m_sent_colors = 0x00U;
- m_sent_buttons = 0x00U;
- m_stale = STALE_ALL;
+ m_sent_joy = 0x0000U;
+ m_sent_colors = 0x0000U;
+ m_sent_buttons = 0x0000U;
+ m_stale = stale_all();
m_active = false;
save_item(NAME(m_sent_joy));
@@ -128,7 +129,7 @@ void vsmile_pad_device::tx_timeout()
{
m_idle_timer->reset();
m_active = false;
- m_stale = STALE_ALL;
+ m_stale = stale_all();
std::fill(std::begin(m_ctrl_probe_history), std::end(m_ctrl_probe_history), 0U);
LOG("left active state\n");
}
@@ -174,7 +175,7 @@ INPUT_CHANGED_MEMBER(vsmile_pad_device::pad_joy_changed)
if (!is_tx_empty())
{
LOG("joy changed while transmission in progress, marking stale\n");
- m_stale |= stale_inputs(param);
+ m_stale |= stale_pad_inputs(param);
}
else
{
@@ -226,7 +227,7 @@ INPUT_CHANGED_MEMBER(vsmile_pad_device::pad_button_changed)
if (!is_tx_empty())
{
LOG("buttons changed while transmission in progress, marking stale\n");
- m_stale |= stale_inputs(param);
+ m_stale |= stale_pad_inputs(param);
}
else
{
@@ -248,24 +249,24 @@ INPUT_CHANGED_MEMBER(vsmile_pad_device::pad_button_changed)
static INPUT_PORTS_START( vsmile_pad )
PORT_START("JOY")
- PORT_BIT( 0x01, IP_ACTIVE_HIGH, IPT_JOYSTICK_UP ) PORT_CHANGED_MEMBER(DEVICE_SELF, vsmile_pad_device, pad_joy_changed, vsmile_pad_device::STALE_UP_DOWN) PORT_NAME("Joypad Up")
- PORT_BIT( 0x02, IP_ACTIVE_HIGH, IPT_JOYSTICK_DOWN ) PORT_CHANGED_MEMBER(DEVICE_SELF, vsmile_pad_device, pad_joy_changed, vsmile_pad_device::STALE_UP_DOWN) PORT_NAME("Joypad Down")
- PORT_BIT( 0x04, IP_ACTIVE_HIGH, IPT_JOYSTICK_LEFT ) PORT_CHANGED_MEMBER(DEVICE_SELF, vsmile_pad_device, pad_joy_changed, vsmile_pad_device::STALE_LEFT_RIGHT) PORT_NAME("Joypad Left")
- PORT_BIT( 0x08, IP_ACTIVE_HIGH, IPT_JOYSTICK_RIGHT ) PORT_CHANGED_MEMBER(DEVICE_SELF, vsmile_pad_device, pad_joy_changed, vsmile_pad_device::STALE_LEFT_RIGHT) PORT_NAME("Joypad Right")
+ PORT_BIT( 0x01, IP_ACTIVE_HIGH, IPT_JOYSTICK_UP ) PORT_CHANGED_MEMBER(DEVICE_SELF, FUNC(vsmile_pad_device::pad_joy_changed), vsmile_pad_device::STALE_UP_DOWN) PORT_NAME("Joypad Up")
+ PORT_BIT( 0x02, IP_ACTIVE_HIGH, IPT_JOYSTICK_DOWN ) PORT_CHANGED_MEMBER(DEVICE_SELF, FUNC(vsmile_pad_device::pad_joy_changed), vsmile_pad_device::STALE_UP_DOWN) PORT_NAME("Joypad Down")
+ PORT_BIT( 0x04, IP_ACTIVE_HIGH, IPT_JOYSTICK_LEFT ) PORT_CHANGED_MEMBER(DEVICE_SELF, FUNC(vsmile_pad_device::pad_joy_changed), vsmile_pad_device::STALE_LEFT_RIGHT) PORT_NAME("Joypad Left")
+ PORT_BIT( 0x08, IP_ACTIVE_HIGH, IPT_JOYSTICK_RIGHT ) PORT_CHANGED_MEMBER(DEVICE_SELF, FUNC(vsmile_pad_device::pad_joy_changed), vsmile_pad_device::STALE_LEFT_RIGHT) PORT_NAME("Joypad Right")
PORT_BIT( 0xf0, IP_ACTIVE_HIGH, IPT_UNUSED )
PORT_START("COLORS")
- PORT_BIT( 0x01, IP_ACTIVE_HIGH, IPT_BUTTON1 ) PORT_CHANGED_MEMBER(DEVICE_SELF, vsmile_pad_device, pad_color_changed, vsmile_pad_device::STALE_COLORS) PORT_NAME("Green")
- PORT_BIT( 0x02, IP_ACTIVE_HIGH, IPT_BUTTON2 ) PORT_CHANGED_MEMBER(DEVICE_SELF, vsmile_pad_device, pad_color_changed, vsmile_pad_device::STALE_COLORS) PORT_NAME("Blue")
- PORT_BIT( 0x04, IP_ACTIVE_HIGH, IPT_BUTTON3 ) PORT_CHANGED_MEMBER(DEVICE_SELF, vsmile_pad_device, pad_color_changed, vsmile_pad_device::STALE_COLORS) PORT_NAME("Yellow")
- PORT_BIT( 0x08, IP_ACTIVE_HIGH, IPT_BUTTON4 ) PORT_CHANGED_MEMBER(DEVICE_SELF, vsmile_pad_device, pad_color_changed, vsmile_pad_device::STALE_COLORS) PORT_NAME("Red")
+ PORT_BIT( 0x01, IP_ACTIVE_HIGH, IPT_BUTTON1 ) PORT_CHANGED_MEMBER(DEVICE_SELF, FUNC(vsmile_pad_device::pad_color_changed), vsmile_pad_device::STALE_COLORS) PORT_NAME("Green")
+ PORT_BIT( 0x02, IP_ACTIVE_HIGH, IPT_BUTTON2 ) PORT_CHANGED_MEMBER(DEVICE_SELF, FUNC(vsmile_pad_device::pad_color_changed), vsmile_pad_device::STALE_COLORS) PORT_NAME("Blue")
+ PORT_BIT( 0x04, IP_ACTIVE_HIGH, IPT_BUTTON3 ) PORT_CHANGED_MEMBER(DEVICE_SELF, FUNC(vsmile_pad_device::pad_color_changed), vsmile_pad_device::STALE_COLORS) PORT_NAME("Yellow")
+ PORT_BIT( 0x08, IP_ACTIVE_HIGH, IPT_BUTTON4 ) PORT_CHANGED_MEMBER(DEVICE_SELF, FUNC(vsmile_pad_device::pad_color_changed), vsmile_pad_device::STALE_COLORS) PORT_NAME("Red")
PORT_BIT( 0xf0, IP_ACTIVE_HIGH, IPT_UNUSED )
PORT_START("BUTTONS")
- PORT_BIT( 0x01, IP_ACTIVE_HIGH, IPT_BUTTON5 ) PORT_CHANGED_MEMBER(DEVICE_SELF, vsmile_pad_device, pad_button_changed, vsmile_pad_device::STALE_OK) PORT_NAME("OK")
- PORT_BIT( 0x02, IP_ACTIVE_HIGH, IPT_BUTTON6 ) PORT_CHANGED_MEMBER(DEVICE_SELF, vsmile_pad_device, pad_button_changed, vsmile_pad_device::STALE_QUIT) PORT_NAME("Quit")
- PORT_BIT( 0x04, IP_ACTIVE_HIGH, IPT_BUTTON7 ) PORT_CHANGED_MEMBER(DEVICE_SELF, vsmile_pad_device, pad_button_changed, vsmile_pad_device::STALE_HELP) PORT_NAME("Help")
- PORT_BIT( 0x08, IP_ACTIVE_HIGH, IPT_BUTTON8 ) PORT_CHANGED_MEMBER(DEVICE_SELF, vsmile_pad_device, pad_button_changed, vsmile_pad_device::STALE_ABC) PORT_NAME("ABC")
+ PORT_BIT( 0x01, IP_ACTIVE_HIGH, IPT_BUTTON5 ) PORT_CHANGED_MEMBER(DEVICE_SELF, FUNC(vsmile_pad_device::pad_button_changed), vsmile_pad_device::STALE_OK) PORT_NAME("OK")
+ PORT_BIT( 0x02, IP_ACTIVE_HIGH, IPT_BUTTON6 ) PORT_CHANGED_MEMBER(DEVICE_SELF, FUNC(vsmile_pad_device::pad_button_changed), vsmile_pad_device::STALE_QUIT) PORT_NAME("Quit")
+ PORT_BIT( 0x04, IP_ACTIVE_HIGH, IPT_BUTTON7 ) PORT_CHANGED_MEMBER(DEVICE_SELF, FUNC(vsmile_pad_device::pad_button_changed), vsmile_pad_device::STALE_HELP) PORT_NAME("Help")
+ PORT_BIT( 0x08, IP_ACTIVE_HIGH, IPT_BUTTON8 ) PORT_CHANGED_MEMBER(DEVICE_SELF, FUNC(vsmile_pad_device::pad_button_changed), vsmile_pad_device::STALE_ABC) PORT_NAME("ABC")
PORT_BIT( 0xf0, IP_ACTIVE_HIGH, IPT_UNUSED )
INPUT_PORTS_END
diff --git a/src/devices/bus/vsmile/pad.h b/src/devices/bus/vsmile/pad.h
index 5e2515c2b58..857e41a7920 100644
--- a/src/devices/bus/vsmile/pad.h
+++ b/src/devices/bus/vsmile/pad.h
@@ -16,7 +16,16 @@
class vsmile_pad_device : public vsmile_ctrl_device_base
{
public:
- enum stale_inputs : uint8_t
+ // construction/destruction
+ vsmile_pad_device(machine_config const &mconfig, char const *tag, device_t *owner, uint32_t clock = 0U);
+ virtual ~vsmile_pad_device();
+
+ // input handlers
+ DECLARE_INPUT_CHANGED_MEMBER(pad_joy_changed);
+ DECLARE_INPUT_CHANGED_MEMBER(pad_color_changed);
+ DECLARE_INPUT_CHANGED_MEMBER(pad_button_changed);
+
+ enum stale_pad_inputs : uint16_t
{
STALE_NONE = 0U,
STALE_LEFT_RIGHT = 1U << 0,
@@ -32,39 +41,35 @@ public:
STALE_ALL = STALE_JOY | STALE_COLORS | STALE_BUTTONS
};
- // construction/destruction
- vsmile_pad_device(machine_config const &mconfig, char const *tag, device_t *owner, uint32_t clock = 0U);
- virtual ~vsmile_pad_device();
-
- // input handlers
- DECLARE_INPUT_CHANGED_MEMBER(pad_joy_changed);
- DECLARE_INPUT_CHANGED_MEMBER(pad_color_changed);
- DECLARE_INPUT_CHANGED_MEMBER(pad_button_changed);
-
protected:
+ vsmile_pad_device(machine_config const &mconfig, device_type type, char const *tag, device_t *owner, uint32_t clock = 0U);
+
// device_t implementation
- virtual ioport_constructor device_input_ports() const override;
- virtual void device_start() override;
+ virtual ioport_constructor device_input_ports() const override ATTR_COLD;
+ virtual void device_start() override ATTR_COLD;
// vsmile_ctrl_device_base implementation
virtual void tx_complete() override;
virtual void tx_timeout() override;
virtual void rx_complete(uint8_t data, bool cts) override;
-private:
- void uart_tx_fifo_push(uint8_t data);
+ uint16_t stale_all() { return STALE_ALL; }
- TIMER_CALLBACK_MEMBER(handle_idle);
+ void uart_tx_fifo_push(uint8_t data);
required_ioport m_io_joy;
required_ioport m_io_colors;
required_ioport m_io_buttons;
- emu_timer *m_idle_timer;
+ uint16_t m_sent_joy, m_sent_colors, m_sent_buttons;
- uint8_t m_sent_joy, m_sent_colors, m_sent_buttons;
- stale_inputs m_stale;
+ uint16_t m_stale;
bool m_active;
+ emu_timer *m_idle_timer;
+
+private:
+ TIMER_CALLBACK_MEMBER(handle_idle);
+
uint8_t m_ctrl_probe_history[2];
};
diff --git a/src/devices/bus/vsmile/rom.cpp b/src/devices/bus/vsmile/rom.cpp
index 584a8cfe058..bc69099d698 100644
--- a/src/devices/bus/vsmile/rom.cpp
+++ b/src/devices/bus/vsmile/rom.cpp
@@ -52,7 +52,7 @@ void vsmile_rom_device::device_start()
save_item(NAME(m_bank_offset));
}
-void vsmile_rom_device::device_reset()
+void vsmile_rom_device::device_resolve_objects()
{
m_bank_offset = 0;
}
@@ -62,7 +62,7 @@ void vsmile_rom_device::device_reset()
Cart with NVRAM
-------------------------------------------------*/
-READ16_MEMBER(vsmile_rom_nvram_device::bank2_r)
+uint16_t vsmile_rom_nvram_device::bank2_r(offs_t offset)
{
if (!m_nvram.empty() && offset < m_nvram.size())
return m_nvram[offset];
@@ -70,10 +70,10 @@ READ16_MEMBER(vsmile_rom_nvram_device::bank2_r)
return 0;
}
-WRITE16_MEMBER(vsmile_rom_nvram_device::bank2_w)
+void vsmile_rom_nvram_device::bank2_w(offs_t offset, uint16_t data)
{
if (!m_nvram.empty() && offset < m_nvram.size())
- COMBINE_DATA(&m_nvram[offset]);
+ m_nvram[offset] = data;
}
/*-------------------------------------------------
diff --git a/src/devices/bus/vsmile/rom.h b/src/devices/bus/vsmile/rom.h
index ec39f1f743e..52f7b420d68 100644
--- a/src/devices/bus/vsmile/rom.h
+++ b/src/devices/bus/vsmile/rom.h
@@ -16,10 +16,10 @@ public:
vsmile_rom_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
// reading and writing
- virtual DECLARE_READ16_MEMBER(bank0_r) override { return m_rom[m_bank_offset + 0x000000 + offset]; }
- virtual DECLARE_READ16_MEMBER(bank1_r) override { return m_rom[m_bank_offset + 0x100000 + offset]; }
- virtual DECLARE_READ16_MEMBER(bank2_r) override { return m_rom[m_bank_offset + 0x200000 + offset]; }
- virtual DECLARE_READ16_MEMBER(bank3_r) override { return m_rom[m_bank_offset + 0x300000 + offset]; }
+ virtual uint16_t bank0_r(offs_t offset) override { return m_rom[m_bank_offset + 0x000000 + offset]; }
+ virtual uint16_t bank1_r(offs_t offset) override { return m_rom[m_bank_offset + 0x100000 + offset]; }
+ virtual uint16_t bank2_r(offs_t offset) override { return m_rom[m_bank_offset + 0x200000 + offset]; }
+ virtual uint16_t bank3_r(offs_t offset) override { return m_rom[m_bank_offset + 0x300000 + offset]; }
// banking
virtual void set_cs2(bool cs2) override;
@@ -28,8 +28,8 @@ protected:
vsmile_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 void device_start() override ATTR_COLD;
+ virtual void device_resolve_objects() override ATTR_COLD;
uint32_t m_bank_offset;
};
@@ -43,8 +43,8 @@ public:
// construction/destruction
vsmile_rom_nvram_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
- virtual DECLARE_READ16_MEMBER(bank2_r) override;
- virtual DECLARE_WRITE16_MEMBER(bank2_w) override;
+ virtual uint16_t bank2_r(offs_t offset) override;
+ virtual void bank2_w(offs_t offset, uint16_t data) override;
protected:
vsmile_rom_nvram_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock);
diff --git a/src/devices/bus/vsmile/vsmile_ctrl.cpp b/src/devices/bus/vsmile/vsmile_ctrl.cpp
index a8cbf25278b..8fc8e0e678b 100644
--- a/src/devices/bus/vsmile/vsmile_ctrl.cpp
+++ b/src/devices/bus/vsmile/vsmile_ctrl.cpp
@@ -23,7 +23,7 @@ DEFINE_DEVICE_TYPE(VSMILE_CTRL_PORT, vsmile_ctrl_port_device, "vsmile_ctrl_port"
//**************************************************************************
device_vsmile_ctrl_interface::device_vsmile_ctrl_interface(const machine_config &mconfig, device_t &device)
- : device_slot_card_interface(mconfig, device)
+ : device_interface(device, "vsmilectrl")
, m_port(dynamic_cast<vsmile_ctrl_port_device *>(device.owner()))
{
}
@@ -34,8 +34,6 @@ device_vsmile_ctrl_interface::~device_vsmile_ctrl_interface()
void device_vsmile_ctrl_interface::interface_validity_check(validity_checker &valid) const
{
- device_slot_card_interface::interface_validity_check(valid);
-
if (device().owner() && !m_port)
{
osd_printf_error(
@@ -47,8 +45,6 @@ void device_vsmile_ctrl_interface::interface_validity_check(validity_checker &va
void device_vsmile_ctrl_interface::interface_pre_start()
{
- device_slot_card_interface::interface_pre_start();
-
if (m_port && !m_port->started())
throw device_missing_dependencies();
}
@@ -64,7 +60,7 @@ vsmile_ctrl_port_device::vsmile_ctrl_port_device(
device_t *owner,
uint32_t clock)
: device_t(mconfig, VSMILE_CTRL_PORT, tag, owner, clock)
- , device_slot_interface(mconfig, *this)
+ , device_single_card_slot_interface<device_vsmile_ctrl_interface>(mconfig, *this)
, m_rts_cb(*this)
, m_data_cb(*this)
{
@@ -74,45 +70,15 @@ vsmile_ctrl_port_device::~vsmile_ctrl_port_device()
{
}
-void vsmile_ctrl_port_device::device_validity_check(validity_checker &valid) const
-{
- device_t *const card(get_card_device());
- if (card && !dynamic_cast<device_vsmile_ctrl_interface *>(card))
- {
- osd_printf_error(
- "Card device %s (%s) does not implement device_vsmile_ctrl_interface\n",
- card->tag(),
- card->name());
- }
-}
-
void vsmile_ctrl_port_device::device_resolve_objects()
{
- device_vsmile_ctrl_interface *const card(dynamic_cast<device_vsmile_ctrl_interface *>(get_card_device()));
- if (card)
- m_device = card;
-
- m_rts_cb.resolve_safe();
- m_data_cb.resolve_safe();
+ m_device = get_card_device();
}
void vsmile_ctrl_port_device::device_start()
{
- device_t *const card(get_card_device());
- if (card)
- {
- if (!m_device)
- {
- throw emu_fatalerror(
- "vsmile_ctrl_port_device: card device %s (%s) does not implement device_vsmile_ctrl_interface\n",
- card->tag(),
- card->name());
- }
- else
- {
- m_device->select_w(0);
- }
- }
+ if (m_device)
+ m_device->select_w(0);
}
@@ -146,12 +112,10 @@ vsmile_ctrl_device_base::~vsmile_ctrl_device_base()
void vsmile_ctrl_device_base::device_start()
{
// allocate a timer to limit transmit rate to something realistic
- m_tx_timer = machine().scheduler().timer_alloc(
- timer_expired_delegate(FUNC(vsmile_ctrl_device_base::tx_timer_expired), this));
+ m_tx_timer = timer_alloc(FUNC(vsmile_ctrl_device_base::tx_timer_expired), this);
// allocate a timer for RTS timeouts
- m_rts_timer = machine().scheduler().timer_alloc(
- timer_expired_delegate(FUNC(vsmile_ctrl_device_base::rts_timer_expired), this));
+ m_rts_timer = timer_alloc(FUNC(vsmile_ctrl_device_base::rts_timer_expired), this);
// start with transmit queue empty
m_tx_fifo_head = m_tx_fifo_tail = 0U;
@@ -176,14 +140,14 @@ bool vsmile_ctrl_device_base::queue_tx(uint8_t data)
"%s: discarding byte %02X because FIFO is full (length %u, Tx %sactive)\n",
machine().describe_context(),
data,
- ARRAY_LENGTH(m_tx_fifo),
+ std::size(m_tx_fifo),
m_tx_active ? "" : "in");
return false;
}
// queue the byte
m_tx_fifo[m_tx_fifo_tail] = data;
- m_tx_fifo_tail = (m_tx_fifo_tail + 1) % ARRAY_LENGTH(m_tx_fifo);
+ m_tx_fifo_tail = (m_tx_fifo_tail + 1) % std::size(m_tx_fifo);
m_tx_fifo_empty = false;
// assert RTS and start transmitting if necessary
@@ -204,7 +168,7 @@ bool vsmile_ctrl_device_base::queue_tx(uint8_t data)
}
else
{
- unsigned const fifo_used((m_tx_fifo_tail + ARRAY_LENGTH(m_tx_fifo) - m_tx_fifo_head) % ARRAY_LENGTH(m_tx_fifo));
+ unsigned const fifo_used((m_tx_fifo_tail + std::size(m_tx_fifo) - m_tx_fifo_head) % std::size(m_tx_fifo));
LOG("%s: queued byte %02X (%u bytes queued, Tx %sactive)\n", machine().describe_context(), data, fifo_used, m_tx_active ? "" : "in");
}
@@ -219,7 +183,7 @@ void vsmile_ctrl_device_base::select_w(int state)
if (state && !m_tx_fifo_empty && !m_tx_active)
{
m_rts_timer->reset();
- unsigned const fifo_used((m_tx_fifo_tail + ARRAY_LENGTH(m_tx_fifo) - m_tx_fifo_head) % ARRAY_LENGTH(m_tx_fifo));
+ unsigned const fifo_used((m_tx_fifo_tail + std::size(m_tx_fifo) - m_tx_fifo_head) % std::size(m_tx_fifo));
LOG("%s: select asserted, starting transmission (%u bytes queued)\n", machine().describe_context(), fifo_used);
m_tx_active = true;
m_tx_timer->adjust(attotime::from_hz(9600 / 10));
@@ -250,7 +214,7 @@ TIMER_CALLBACK_MEMBER(vsmile_ctrl_device_base::tx_timer_expired)
// deliver the byte to the host (bits have shifted out now)
uint8_t const data(m_tx_fifo[m_tx_fifo_head]);
- m_tx_fifo_head = (m_tx_fifo_head + 1) % ARRAY_LENGTH(m_tx_fifo);
+ m_tx_fifo_head = (m_tx_fifo_head + 1) % std::size(m_tx_fifo);
if (m_tx_fifo_head == m_tx_fifo_tail)
m_tx_fifo_empty = true;
data_out(data);
@@ -263,7 +227,7 @@ TIMER_CALLBACK_MEMBER(vsmile_ctrl_device_base::tx_timer_expired)
}
else
{
- unsigned const fifo_used((m_tx_fifo_tail + ARRAY_LENGTH(m_tx_fifo) - m_tx_fifo_head) % ARRAY_LENGTH(m_tx_fifo));
+ unsigned const fifo_used((m_tx_fifo_tail + std::size(m_tx_fifo) - m_tx_fifo_head) % std::size(m_tx_fifo));
LOG("transmitted byte %02X (%u bytes queued, select %sasserted)\n", data, fifo_used, m_select ? "" : "de");
}
@@ -283,7 +247,7 @@ TIMER_CALLBACK_MEMBER(vsmile_ctrl_device_base::tx_timer_expired)
{
LOG("select deasserted, waiting to transmit\n");
m_tx_active = false;
- m_rts_timer->adjust(attotime::from_msec(500));
+ //m_rts_timer->adjust(attotime::from_msec(2000));
}
}
@@ -296,7 +260,7 @@ TIMER_CALLBACK_MEMBER(vsmile_ctrl_device_base::rts_timer_expired)
// clear out anything queued and let the implementation deal with it
if (!m_tx_fifo_empty)
{
- unsigned const fifo_used((m_tx_fifo_tail + ARRAY_LENGTH(m_tx_fifo) - m_tx_fifo_head) % ARRAY_LENGTH(m_tx_fifo));
+ unsigned const fifo_used((m_tx_fifo_tail + std::size(m_tx_fifo) - m_tx_fifo_head) % std::size(m_tx_fifo));
LOG("timeout waiting for select after asserting RTS (%u bytes queued)\n", fifo_used);
m_tx_fifo_head = m_tx_fifo_tail = 0U;
m_tx_fifo_empty = true;
@@ -308,8 +272,14 @@ TIMER_CALLBACK_MEMBER(vsmile_ctrl_device_base::rts_timer_expired)
#include "pad.h"
+#include "mat.h"
+#include "keyboard.h"
void vsmile_controllers(device_slot_interface &device)
{
device.option_add("joy", VSMILE_PAD);
+ device.option_add("mat", VSMILE_MAT);
+ device.option_add("smartkb_us", VSMILE_KEYBOARD_US);
+ device.option_add("smartkb_fr", VSMILE_KEYBOARD_FR);
+ device.option_add("smartkb_ge", VSMILE_KEYBOARD_GE);
}
diff --git a/src/devices/bus/vsmile/vsmile_ctrl.h b/src/devices/bus/vsmile/vsmile_ctrl.h
index 66921ce817a..0a9cdcc37d2 100644
--- a/src/devices/bus/vsmile/vsmile_ctrl.h
+++ b/src/devices/bus/vsmile/vsmile_ctrl.h
@@ -19,7 +19,7 @@ class vsmile_ctrl_port_device;
// ======================> device_vsmile_ctrl_interface
-class device_vsmile_ctrl_interface : public device_slot_card_interface
+class device_vsmile_ctrl_interface : public device_interface
{
public:
virtual ~device_vsmile_ctrl_interface();
@@ -48,7 +48,7 @@ private:
// ======================> vsmile_ctrl_port_device
-class vsmile_ctrl_port_device : public device_t, public device_slot_interface
+class vsmile_ctrl_port_device : public device_t, public device_single_card_slot_interface<device_vsmile_ctrl_interface>
{
public:
// configuration
@@ -74,9 +74,8 @@ public:
protected:
// device_t implementation
- virtual void device_validity_check(validity_checker &valid) const override ATTR_COLD;
- virtual void device_resolve_objects() override;
- virtual void device_start() override;
+ virtual void device_resolve_objects() override ATTR_COLD;
+ virtual void device_start() override ATTR_COLD;
private:
device_vsmile_ctrl_interface *m_device;
@@ -100,11 +99,12 @@ protected:
vsmile_ctrl_device_base(machine_config const &mconfig, device_type type, char const *tag, device_t *owner, uint32_t clock);
// device_t implementation
- virtual void device_start() override;
+ virtual void device_start() override ATTR_COLD;
// UART simulation helpers
bool is_tx_empty() const { return m_tx_fifo_empty; }
bool queue_tx(uint8_t data);
+ bool is_selected() { return m_select; }
private:
// device_vsmile_ctrl_interfaceA implementation
diff --git a/src/devices/bus/vsmile/vsmile_slot.cpp b/src/devices/bus/vsmile/vsmile_slot.cpp
index 61d7873b63f..1e743c5f393 100644
--- a/src/devices/bus/vsmile/vsmile_slot.cpp
+++ b/src/devices/bus/vsmile/vsmile_slot.cpp
@@ -7,7 +7,6 @@
***********************************************************************************************************/
-
#include "emu.h"
#include "vsmile_slot.h"
@@ -26,7 +25,7 @@ DEFINE_DEVICE_TYPE(VSMILE_CART_SLOT, vsmile_cart_slot_device, "vsmile_cart_slot"
//-------------------------------------------------
device_vsmile_cart_interface::device_vsmile_cart_interface(const machine_config &mconfig, device_t &device)
- : device_slot_card_interface(mconfig, device)
+ : device_interface(device, "vsmilecart")
, m_rom(nullptr)
, m_rom_size(0)
{
@@ -45,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;
}
}
@@ -75,8 +74,8 @@ void device_vsmile_cart_interface::nvram_alloc(uint32_t size)
//-------------------------------------------------
vsmile_cart_slot_device::vsmile_cart_slot_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) :
device_t(mconfig, VSMILE_CART_SLOT, tag, owner, clock),
- device_image_interface(mconfig, *this),
- device_slot_interface(mconfig, *this),
+ device_cartrom_image_interface(mconfig, *this),
+ device_single_card_slot_interface<device_vsmile_cart_interface>(mconfig, *this),
m_type(VSMILE_STD),
m_cart(nullptr)
{
@@ -97,7 +96,7 @@ vsmile_cart_slot_device::~vsmile_cart_slot_device()
void vsmile_cart_slot_device::device_start()
{
- m_cart = dynamic_cast<device_vsmile_cart_interface *>(get_card_device());
+ m_cart = get_card_device();
}
@@ -122,7 +121,7 @@ static int vsmile_get_pcb_id(const char *slot)
{
for (auto & elem : slot_list)
{
- if (!core_stricmp(elem.slot_option, slot))
+ if (!strcmp(elem.slot_option, slot))
return elem.pcb_id;
}
@@ -133,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_UNSPECIFIED, "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())
{
@@ -161,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());
}
@@ -208,44 +198,44 @@ std::string vsmile_cart_slot_device::get_default_card_software(get_default_card_
cart accessors
-------------------------------------------------*/
-READ16_MEMBER(vsmile_cart_slot_device::bank0_r)
+uint16_t vsmile_cart_slot_device::bank0_r(offs_t offset)
{
- return m_cart->bank0_r(space, offset, mem_mask);
+ return m_cart->bank0_r(offset);
}
-READ16_MEMBER(vsmile_cart_slot_device::bank1_r)
+uint16_t vsmile_cart_slot_device::bank1_r(offs_t offset)
{
- return m_cart->bank1_r(space, offset, mem_mask);
+ return m_cart->bank1_r(offset);
}
-READ16_MEMBER(vsmile_cart_slot_device::bank2_r)
+uint16_t vsmile_cart_slot_device::bank2_r(offs_t offset)
{
- return m_cart->bank2_r(space, offset, mem_mask);
+ return m_cart->bank2_r(offset);
}
-READ16_MEMBER(vsmile_cart_slot_device::bank3_r)
+uint16_t vsmile_cart_slot_device::bank3_r(offs_t offset)
{
- return m_cart->bank3_r(space, offset, mem_mask);
+ return m_cart->bank3_r(offset);
}
-WRITE16_MEMBER(vsmile_cart_slot_device::bank0_w)
+void vsmile_cart_slot_device::bank0_w(offs_t offset, uint16_t data)
{
- m_cart->bank0_w(space, offset, data, mem_mask);
+ m_cart->bank0_w(offset, data);
}
-WRITE16_MEMBER(vsmile_cart_slot_device::bank1_w)
+void vsmile_cart_slot_device::bank1_w(offs_t offset, uint16_t data)
{
- m_cart->bank1_w(space, offset, data, mem_mask);
+ m_cart->bank1_w(offset, data);
}
-WRITE16_MEMBER(vsmile_cart_slot_device::bank2_w)
+void vsmile_cart_slot_device::bank2_w(offs_t offset, uint16_t data)
{
- m_cart->bank2_w(space, offset, data, mem_mask);
+ m_cart->bank2_w(offset, data);
}
-WRITE16_MEMBER(vsmile_cart_slot_device::bank3_w)
+void vsmile_cart_slot_device::bank3_w(offs_t offset, uint16_t data)
{
- m_cart->bank3_w(space, offset, data, mem_mask);
+ m_cart->bank3_w(offset, data);
}
void vsmile_cart_slot_device::set_cs2(bool cs2)
diff --git a/src/devices/bus/vsmile/vsmile_slot.h b/src/devices/bus/vsmile/vsmile_slot.h
index 7d800677214..d35c2ade4c3 100644
--- a/src/devices/bus/vsmile/vsmile_slot.h
+++ b/src/devices/bus/vsmile/vsmile_slot.h
@@ -5,15 +5,13 @@
#pragma once
-#include "softlist_dev.h"
+#include "imagedev/cartrom.h"
/***************************************************************************
TYPE DEFINITIONS
***************************************************************************/
-#define VSMILE_SLOT_ROM_REGION_TAG ":cart:rom"
-
enum
{
VSMILE_STD = 0,
@@ -22,26 +20,26 @@ enum
// ======================> device_vsmile_cart_interface
-class device_vsmile_cart_interface : public device_slot_card_interface
+class device_vsmile_cart_interface : public device_interface
{
public:
// construction/destruction
virtual ~device_vsmile_cart_interface();
// reading and writing
- virtual DECLARE_READ16_MEMBER(bank0_r) { return 0; }
- virtual DECLARE_READ16_MEMBER(bank1_r) { return 0; }
- virtual DECLARE_READ16_MEMBER(bank2_r) { return 0; }
- virtual DECLARE_READ16_MEMBER(bank3_r) { return 0; }
- virtual DECLARE_WRITE16_MEMBER(bank0_w) { }
- virtual DECLARE_WRITE16_MEMBER(bank1_w) { }
- virtual DECLARE_WRITE16_MEMBER(bank2_w) { }
- virtual DECLARE_WRITE16_MEMBER(bank3_w) { }
+ virtual uint16_t bank0_r(offs_t offset) { return 0; }
+ virtual uint16_t bank1_r(offs_t offset) { return 0; }
+ virtual uint16_t bank2_r(offs_t offset) { return 0; }
+ virtual uint16_t bank3_r(offs_t offset) { return 0; }
+ virtual void bank0_w(offs_t offset, uint16_t data) { }
+ virtual void bank1_w(offs_t offset, uint16_t data) { }
+ virtual void bank2_w(offs_t offset, uint16_t data) { }
+ virtual void bank3_w(offs_t offset, uint16_t data) { }
// 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]; }
@@ -64,8 +62,8 @@ protected:
// ======================> vsmile_cart_slot_device
class vsmile_cart_slot_device : public device_t,
- public device_image_interface,
- public device_slot_interface
+ public device_cartrom_image_interface,
+ public device_single_card_slot_interface<device_vsmile_cart_interface>
{
public:
// construction/destruction
@@ -81,45 +79,39 @@ public:
vsmile_cart_slot_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
virtual ~vsmile_cart_slot_device();
- // 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 void call_unload() override;
- virtual const software_list_loader &get_software_list_loader() const override { return rom_software_list_loader::instance(); }
- void save_nvram() { if (m_cart && m_cart->get_nvram_size()) m_cart->save_nvram(); }
- uint32_t get_rom_size() { if (m_cart) return m_cart->get_rom_size(); return 0; }
-
- virtual iodevice_t image_type() const override { return IO_CARTSLOT; }
- virtual bool is_readable() const override { return 1; }
- virtual bool is_writeable() const override { return 0; }
- virtual bool is_creatable() const override { return 0; }
- virtual bool must_be_loaded() const override { return 0; }
- virtual bool is_reset_on_load() const override { return 1; }
- virtual const char *image_interface() const override { return "vsmile_cart"; }
- virtual const char *file_extensions() const override { return "u1,u3,bin"; }
-
- // slot interface overrides
+ 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"; }
+
+ // 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(); }
+ uint32_t get_rom_size() { return m_cart ? m_cart->get_rom_size() : 0; }
+
// reading and writing
- virtual DECLARE_READ16_MEMBER(bank0_r);
- virtual DECLARE_READ16_MEMBER(bank1_r);
- virtual DECLARE_READ16_MEMBER(bank2_r);
- virtual DECLARE_READ16_MEMBER(bank3_r);
- virtual DECLARE_WRITE16_MEMBER(bank0_w);
- virtual DECLARE_WRITE16_MEMBER(bank1_w);
- virtual DECLARE_WRITE16_MEMBER(bank2_w);
- virtual DECLARE_WRITE16_MEMBER(bank3_w);
+ uint16_t bank0_r(offs_t offset);
+ uint16_t bank1_r(offs_t offset);
+ uint16_t bank2_r(offs_t offset);
+ uint16_t bank3_r(offs_t offset);
+ void bank0_w(offs_t offset, uint16_t data);
+ void bank1_w(offs_t offset, uint16_t data);
+ void bank2_w(offs_t offset, uint16_t data);
+ void bank3_w(offs_t offset, uint16_t data);
// banking
void set_cs2(bool cs2);
protected:
+ // device_t implementation
+ virtual void device_start() override ATTR_COLD;
+
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/ioexp.cpp b/src/devices/bus/vtech/ioexp/ioexp.cpp
index 897b0dba95b..475f287201e 100644
--- a/src/devices/bus/vtech/ioexp/ioexp.cpp
+++ b/src/devices/bus/vtech/ioexp/ioexp.cpp
@@ -1,5 +1,5 @@
-// license:GPL-2.0+
-// copyright-holders:Dirk Best
+// license: GPL-2.0+
+// copyright-holders: Dirk Best
/***************************************************************************
VTech Laser/VZ I/O Expansion Slot
@@ -29,9 +29,8 @@ DEFINE_DEVICE_TYPE(VTECH_IOEXP_SLOT, vtech_ioexp_slot_device, "vtech_ioexp_slot"
vtech_ioexp_slot_device::vtech_ioexp_slot_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) :
device_t(mconfig, VTECH_IOEXP_SLOT, tag, owner, clock),
- device_slot_interface(mconfig, *this),
- m_io(*this, finder_base::DUMMY_TAG, -1),
- m_cart(nullptr)
+ device_single_card_slot_interface<device_vtech_ioexp_interface>(mconfig, *this),
+ m_iospace(*this, finder_base::DUMMY_TAG, -1)
{
}
@@ -49,14 +48,24 @@ vtech_ioexp_slot_device::~vtech_ioexp_slot_device()
void vtech_ioexp_slot_device::device_start()
{
-}
-
-//-------------------------------------------------
-// device_reset - device-specific reset
-//-------------------------------------------------
-
-void vtech_ioexp_slot_device::device_reset()
-{
+ // get inserted module
+ m_module = get_card_device();
+
+ // install io access taps
+ m_iospace->install_readwrite_tap
+ (
+ 0x00, 0xff, "io_tap",
+ [this](offs_t offset, uint8_t &data, uint8_t mem_mask)
+ {
+ if (m_module)
+ data &= m_module->iorq_r(offset);
+ },
+ [this](offs_t offset, uint8_t &data, uint8_t mem_mask)
+ {
+ if (m_module)
+ m_module->iorq_w(offset, data);
+ }
+ );
}
@@ -69,7 +78,7 @@ void vtech_ioexp_slot_device::device_reset()
//-------------------------------------------------
device_vtech_ioexp_interface::device_vtech_ioexp_interface(const machine_config &mconfig, device_t &device) :
- device_slot_card_interface(mconfig, device)
+ device_interface(device, "vtechioexp")
{
m_slot = dynamic_cast<vtech_ioexp_slot_device *>(device.owner());
}
@@ -81,3 +90,52 @@ device_vtech_ioexp_interface::device_vtech_ioexp_interface(const machine_config
device_vtech_ioexp_interface::~device_vtech_ioexp_interface()
{
}
+
+
+//**************************************************************************
+// BASE DEVICE
+//**************************************************************************
+
+//-------------------------------------------------
+// vtech_ioexp_device - constructor
+//-------------------------------------------------
+
+vtech_ioexp_device::vtech_ioexp_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_vtech_ioexp_interface(mconfig, *this),
+ m_io(*this, "iospace")
+{
+}
+
+//-------------------------------------------------
+// device_add_mconfig - add device configuration
+//-------------------------------------------------
+
+void vtech_ioexp_device::device_add_mconfig(machine_config &config)
+{
+ ADDRESS_MAP_BANK(config, m_io);
+ m_io->set_addrmap(AS_PROGRAM, &vtech_ioexp_device::io_map);
+ m_io->set_data_width(8);
+ m_io->set_addr_width(16);
+}
+
+//-------------------------------------------------
+// device_start - device-specific startup
+//-------------------------------------------------
+
+void vtech_ioexp_device::device_start()
+{
+ // silence unmapped warnings, or we'll get them for everything the
+ // expansion device doesn't handle
+ m_io->set_log_unmap(false);
+}
+
+uint8_t vtech_ioexp_device::iorq_r(offs_t offset)
+{
+ return m_io->read8(offset);
+}
+
+void vtech_ioexp_device::iorq_w(offs_t offset, uint8_t data)
+{
+ m_io->write8(offset, data);
+}
diff --git a/src/devices/bus/vtech/ioexp/ioexp.h b/src/devices/bus/vtech/ioexp/ioexp.h
index 9a78f861478..1df488770cd 100644
--- a/src/devices/bus/vtech/ioexp/ioexp.h
+++ b/src/devices/bus/vtech/ioexp/ioexp.h
@@ -1,5 +1,5 @@
-// license:GPL-2.0+
-// copyright-holders:Dirk Best
+// license: GPL-2.0+
+// copyright-holders: Dirk Best
/***************************************************************************
VTech Laser/VZ I/O Expansion Slot
@@ -29,16 +29,19 @@
#pragma once
+#include "machine/bankdev.h"
+
// include here so drivers don't need to
#include "carts.h"
+
//**************************************************************************
// TYPE DEFINITIONS
//**************************************************************************
class device_vtech_ioexp_interface;
-class vtech_ioexp_slot_device : public device_t, public device_slot_interface
+class vtech_ioexp_slot_device : public device_t, public device_single_card_slot_interface<device_vtech_ioexp_interface>
{
friend class device_vtech_ioexp_interface;
public:
@@ -54,33 +57,54 @@ public:
vtech_ioexp_slot_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
virtual ~vtech_ioexp_slot_device();
- template <typename T> void set_io_space(T &&tag, int spacenum) { m_io.set_tag(std::forward<T>(tag), spacenum); }
+ template <typename T> void set_iospace(T &&tag, int spacenum) { m_iospace.set_tag(std::forward<T>(tag), spacenum); }
protected:
// device-level overrides
- virtual void device_start() override;
- virtual void device_reset() override;
+ virtual void device_start() override ATTR_COLD;
- required_address_space m_io;
+private:
+ required_address_space m_iospace;
- device_vtech_ioexp_interface *m_cart;
+ device_vtech_ioexp_interface *m_module;
};
// class representing interface-specific live ioexp device
-class device_vtech_ioexp_interface : public device_slot_card_interface
+class device_vtech_ioexp_interface : public device_interface
{
public:
// construction/destruction
virtual ~device_vtech_ioexp_interface();
+ virtual uint8_t iorq_r(offs_t offset) { return 0xff; }
+ virtual void iorq_w(offs_t offset, uint8_t data) { }
+
protected:
device_vtech_ioexp_interface(const machine_config &mconfig, device_t &device);
- address_space &io_space() { return *m_slot->m_io; }
-
vtech_ioexp_slot_device *m_slot;
};
+// base io expansion device
+class vtech_ioexp_device : public device_t, public device_vtech_ioexp_interface
+{
+public:
+ // construction/destruction
+ vtech_ioexp_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock);
+
+ // from host
+ virtual uint8_t iorq_r(offs_t offset) override;
+ virtual void iorq_w(offs_t offset, uint8_t data) override;
+
+protected:
+ virtual void device_add_mconfig(machine_config &config) override ATTR_COLD;
+ virtual void device_start() override ATTR_COLD;
+
+ virtual void io_map(address_map &map) { }
+
+ required_device<address_map_bank_device> m_io;
+};
+
// device type definition
DECLARE_DEVICE_TYPE(VTECH_IOEXP_SLOT, vtech_ioexp_slot_device)
diff --git a/src/devices/bus/vtech/ioexp/joystick.cpp b/src/devices/bus/vtech/ioexp/joystick.cpp
index 7570deca3b5..f54125c64ae 100644
--- a/src/devices/bus/vtech/ioexp/joystick.cpp
+++ b/src/devices/bus/vtech/ioexp/joystick.cpp
@@ -20,6 +20,16 @@
DEFINE_DEVICE_TYPE(VTECH_JOYSTICK_INTERFACE, vtech_joystick_interface_device, "vtech_joystick", "Laser/VZ Joystick Interface")
//-------------------------------------------------
+// io_map - memory space address map
+//-------------------------------------------------
+
+void vtech_joystick_interface_device::io_map(address_map &map)
+{
+ map.unmap_value_high();
+ map(0x20, 0x2f).r(FUNC(vtech_joystick_interface_device::joystick_r));
+}
+
+//-------------------------------------------------
// input_ports - device-specific input ports
//-------------------------------------------------
@@ -66,8 +76,7 @@ ioport_constructor vtech_joystick_interface_device::device_input_ports() const
//-------------------------------------------------
vtech_joystick_interface_device::vtech_joystick_interface_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) :
- device_t(mconfig, VTECH_JOYSTICK_INTERFACE, tag, owner, clock),
- device_vtech_ioexp_interface(mconfig, *this),
+ vtech_ioexp_device(mconfig, VTECH_JOYSTICK_INTERFACE, tag, owner, clock),
m_joy0(*this, "joystick_0"),
m_joy0_arm(*this, "joystick_0_arm"),
m_joy1(*this, "joystick_1"),
@@ -81,15 +90,7 @@ vtech_joystick_interface_device::vtech_joystick_interface_device(const machine_c
void vtech_joystick_interface_device::device_start()
{
-}
-
-//-------------------------------------------------
-// device_reset - device-specific reset
-//-------------------------------------------------
-
-void vtech_joystick_interface_device::device_reset()
-{
- io_space().install_read_handler(0x20, 0x2f, read8_delegate(FUNC(vtech_joystick_interface_device::joystick_r), this));
+ vtech_ioexp_device::device_start();
}
@@ -97,7 +98,7 @@ void vtech_joystick_interface_device::device_reset()
// IMPLEMENTATION
//**************************************************************************
-READ8_MEMBER( vtech_joystick_interface_device::joystick_r )
+uint8_t vtech_joystick_interface_device::joystick_r(offs_t offset)
{
uint8_t data = 0xff;
diff --git a/src/devices/bus/vtech/ioexp/joystick.h b/src/devices/bus/vtech/ioexp/joystick.h
index 0c05403ad2b..12af4c39d11 100644
--- a/src/devices/bus/vtech/ioexp/joystick.h
+++ b/src/devices/bus/vtech/ioexp/joystick.h
@@ -21,20 +21,21 @@
// TYPE DEFINITIONS
//**************************************************************************
-// ======================> joystick_interface_device
+// ======================> vtech_joystick_interface_device
-class vtech_joystick_interface_device : public device_t, public device_vtech_ioexp_interface
+class vtech_joystick_interface_device : public vtech_ioexp_device
{
public:
// construction/destruction
vtech_joystick_interface_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
- DECLARE_READ8_MEMBER( joystick_r );
+ uint8_t joystick_r(offs_t offset);
protected:
- virtual ioport_constructor device_input_ports() const override;
- virtual void device_start() override;
- virtual void device_reset() override;
+ virtual ioport_constructor device_input_ports() const override ATTR_COLD;
+ virtual void device_start() override ATTR_COLD;
+
+ virtual void io_map(address_map &map) override ATTR_COLD;
private:
required_ioport m_joy0;
diff --git a/src/devices/bus/vtech/ioexp/lpen.cpp b/src/devices/bus/vtech/ioexp/lpen.cpp
new file mode 100644
index 00000000000..732340218e1
--- /dev/null
+++ b/src/devices/bus/vtech/ioexp/lpen.cpp
@@ -0,0 +1,63 @@
+// license: GPL-2.0+
+// copyright-holders: Dirk Best
+/***************************************************************************
+
+ VTech Laser Lightpen Interface
+
+ Skeleton just to document the I/O ports used
+
+***************************************************************************/
+
+#include "emu.h"
+#include "lpen.h"
+
+
+//**************************************************************************
+// DEVICE DEFINITIONS
+//**************************************************************************
+
+DEFINE_DEVICE_TYPE(VTECH_LPEN_INTERFACE, vtech_lpen_interface_device, "vtech_lpen", "Laser/VZ Lightpen Interface")
+
+//-------------------------------------------------
+// io_map - memory space address map
+//-------------------------------------------------
+
+void vtech_lpen_interface_device::io_map(address_map &map)
+{
+ map.unmap_value_high();
+ map(0x40, 0x4f).r(FUNC(vtech_lpen_interface_device::lpen_r));
+}
+
+
+//**************************************************************************
+// LIVE DEVICE
+//**************************************************************************
+
+//-------------------------------------------------
+// vtech_lpen_interface_device - constructor
+//-------------------------------------------------
+
+vtech_lpen_interface_device::vtech_lpen_interface_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) :
+ vtech_ioexp_device(mconfig, VTECH_LPEN_INTERFACE, tag, owner, clock)
+{
+}
+
+//-------------------------------------------------
+// device_start - device-specific startup
+//-------------------------------------------------
+
+void vtech_lpen_interface_device::device_start()
+{
+ vtech_ioexp_device::device_start();
+}
+
+
+//**************************************************************************
+// IMPLEMENTATION
+//**************************************************************************
+
+uint8_t vtech_lpen_interface_device::lpen_r(offs_t offset)
+{
+ logerror("lpen_r %02x\n", offset);
+ return 0xff;
+}
diff --git a/src/devices/bus/vtech/ioexp/lpen.h b/src/devices/bus/vtech/ioexp/lpen.h
new file mode 100644
index 00000000000..53676e3d0d6
--- /dev/null
+++ b/src/devices/bus/vtech/ioexp/lpen.h
@@ -0,0 +1,43 @@
+// license: GPL-2.0+
+// copyright-holders: Dirk Best
+/***************************************************************************
+
+ VTech Laser Lightpen Interface
+
+***************************************************************************/
+
+#ifndef MAME_BUS_VTECH_IOEXP_LPEN_H
+#define MAME_BUS_VTECH_IOEXP_LPEN_H
+
+#pragma once
+
+#include "ioexp.h"
+
+
+//**************************************************************************
+// TYPE DEFINITIONS
+//**************************************************************************
+
+// ======================> vtech_lpen_interface_device
+
+class vtech_lpen_interface_device : public vtech_ioexp_device
+{
+public:
+ // construction/destruction
+ vtech_lpen_interface_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
+
+ static constexpr feature_type unemulated_features() { return feature::CONTROLS; }
+
+protected:
+ virtual void device_start() override ATTR_COLD;
+
+ virtual void io_map(address_map &map) override ATTR_COLD;
+
+private:
+ uint8_t lpen_r(offs_t offset);
+};
+
+// device type definition
+DECLARE_DEVICE_TYPE(VTECH_LPEN_INTERFACE, vtech_lpen_interface_device)
+
+#endif // MAME_BUS_VTECH_IOEXP_LPEN_H
diff --git a/src/devices/bus/vtech/ioexp/printer.cpp b/src/devices/bus/vtech/ioexp/printer.cpp
index b927f41d3c4..ba549b22a5e 100644
--- a/src/devices/bus/vtech/ioexp/printer.cpp
+++ b/src/devices/bus/vtech/ioexp/printer.cpp
@@ -20,11 +20,25 @@
DEFINE_DEVICE_TYPE(VTECH_PRINTER_INTERFACE, vtech_printer_interface_device, "vtech_printer", "Laser/VZ Printer Interface")
//-------------------------------------------------
+// io_map - memory space address map
+//-------------------------------------------------
+
+void vtech_printer_interface_device::io_map(address_map &map)
+{
+ map.unmap_value_high();
+ map(0x00, 0x00).r(FUNC(vtech_printer_interface_device::busy_r));
+ map(0x0d, 0x0d).w(FUNC(vtech_printer_interface_device::strobe_w));
+ map(0x0e, 0x0e).w(m_latch, FUNC(output_latch_device::write));
+}
+
+//-------------------------------------------------
// device_add_mconfig - add device configuration
//-------------------------------------------------
void vtech_printer_interface_device::device_add_mconfig(machine_config &config)
{
+ vtech_ioexp_device::device_add_mconfig(config);
+
CENTRONICS(config, m_centronics, centronics_devices, "printer");
m_centronics->busy_handler().set(FUNC(vtech_printer_interface_device::busy_w));
@@ -42,8 +56,7 @@ void vtech_printer_interface_device::device_add_mconfig(machine_config &config)
//-------------------------------------------------
vtech_printer_interface_device::vtech_printer_interface_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) :
- device_t(mconfig, VTECH_PRINTER_INTERFACE, tag, owner, clock),
- device_vtech_ioexp_interface(mconfig, *this),
+ vtech_ioexp_device(mconfig, VTECH_PRINTER_INTERFACE, tag, owner, clock),
m_centronics(*this, "centronics"),
m_latch(*this, "latch"),
m_centronics_busy(0)
@@ -56,17 +69,10 @@ vtech_printer_interface_device::vtech_printer_interface_device(const machine_con
void vtech_printer_interface_device::device_start()
{
-}
-
-//-------------------------------------------------
-// device_reset - device-specific reset
-//-------------------------------------------------
+ vtech_ioexp_device::device_start();
-void vtech_printer_interface_device::device_reset()
-{
- io_space().install_read_handler(0x00, 0x00, read8_delegate(FUNC(vtech_printer_interface_device::busy_r), this));
- io_space().install_write_handler(0x0d, 0x0d, write8_delegate(FUNC(vtech_printer_interface_device::strobe_w), this));
- io_space().install_write_handler(0x0e, 0x0e, write8_delegate(FUNC(output_latch_device::bus_w), m_latch.target()));
+ // register for save states
+ save_item(NAME(m_centronics_busy));
}
@@ -74,17 +80,17 @@ void vtech_printer_interface_device::device_reset()
// IMPLEMENTATION
//**************************************************************************
-WRITE_LINE_MEMBER( vtech_printer_interface_device::busy_w )
+void vtech_printer_interface_device::busy_w(int state)
{
m_centronics_busy = state;
}
-READ8_MEMBER( vtech_printer_interface_device::busy_r )
+uint8_t vtech_printer_interface_device::busy_r()
{
return 0xfe | m_centronics_busy;
}
-WRITE8_MEMBER( vtech_printer_interface_device::strobe_w )
+void vtech_printer_interface_device::strobe_w(uint8_t data)
{
m_centronics->write_strobe(1);
m_centronics->write_strobe(0);
diff --git a/src/devices/bus/vtech/ioexp/printer.h b/src/devices/bus/vtech/ioexp/printer.h
index 013d2366528..c5c772e1f7b 100644
--- a/src/devices/bus/vtech/ioexp/printer.h
+++ b/src/devices/bus/vtech/ioexp/printer.h
@@ -21,27 +21,28 @@
// TYPE DEFINITIONS
//**************************************************************************
-// ======================> printer_interface_device
+// ======================> vtech_printer_interface_device
-class vtech_printer_interface_device : public device_t, public device_vtech_ioexp_interface
+class vtech_printer_interface_device : public vtech_ioexp_device
{
public:
// construction/destruction
vtech_printer_interface_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;
+ virtual void device_add_mconfig(machine_config &config) override ATTR_COLD;
+ virtual void device_start() override ATTR_COLD;
-private:
- DECLARE_WRITE_LINE_MEMBER( busy_w );
- DECLARE_READ8_MEMBER( busy_r );
- DECLARE_WRITE8_MEMBER( strobe_w );
+ virtual void io_map(address_map &map) override ATTR_COLD;
+private:
required_device<centronics_device> m_centronics;
required_device<output_latch_device> m_latch;
+ void busy_w(int state);
+ uint8_t busy_r();
+ void strobe_w(uint8_t data);
+
int m_centronics_busy;
};
diff --git a/src/devices/bus/vtech/memexp/carts.cpp b/src/devices/bus/vtech/memexp/carts.cpp
index 41bd9d42c0f..73a59b9fcdb 100644
--- a/src/devices/bus/vtech/memexp/carts.cpp
+++ b/src/devices/bus/vtech/memexp/carts.cpp
@@ -13,6 +13,7 @@
#include "memory.h"
#include "rs232.h"
#include "rtty.h"
+#include "sdloader.h"
#include "wordpro.h"
@@ -25,5 +26,6 @@ void vtech_memexp_carts(device_slot_interface &device)
device.option_add("laser_64k", VTECH_LASER_64K);
device.option_add("rs232", VTECH_RS232_INTERFACE);
device.option_add("rtty", VTECH_RTTY_INTERFACE);
+ device.option_add("sdloader", VTECH_SDLOADER);
device.option_add("wordpro", VTECH_WORDPRO);
}
diff --git a/src/devices/bus/vtech/memexp/floppy.cpp b/src/devices/bus/vtech/memexp/floppy.cpp
index 5807588ec27..7fdfd30a65a 100644
--- a/src/devices/bus/vtech/memexp/floppy.cpp
+++ b/src/devices/bus/vtech/memexp/floppy.cpp
@@ -12,6 +12,11 @@
#include "emu.h"
#include "floppy.h"
+#include "formats/fs_vtech.h"
+#include "formats/vt_dsk.h"
+
+#include <algorithm>
+
//**************************************************************************
// DEVICE DEFINITIONS
@@ -19,12 +24,27 @@
DEFINE_DEVICE_TYPE(VTECH_FLOPPY_CONTROLLER, vtech_floppy_controller_device, "vtech_fdc", "Laser/VZ Floppy Disk Controller")
-void vtech_floppy_controller_device::map(address_map &map)
+//-------------------------------------------------
+// mem_map - memory space address map
+//-------------------------------------------------
+
+void vtech_floppy_controller_device::mem_map(address_map &map)
{
- map(0, 0).w(FUNC(vtech_floppy_controller_device::latch_w));
- map(1, 1).r(FUNC(vtech_floppy_controller_device::shifter_r));
- map(2, 2).r(FUNC(vtech_floppy_controller_device::rd_r));
- map(3, 3).r(FUNC(vtech_floppy_controller_device::wpt_r));
+ map.unmap_value_high();
+ map(0x4000, 0x5fff).rom().region("software", 0);
+}
+
+//-------------------------------------------------
+// io_map - io space address map
+//-------------------------------------------------
+
+void vtech_floppy_controller_device::io_map(address_map &map)
+{
+ map.unmap_value_high();
+ map(0x10, 0x10).w(FUNC(vtech_floppy_controller_device::latch_w));
+ map(0x11, 0x11).r(FUNC(vtech_floppy_controller_device::shifter_r));
+ map(0x12, 0x12).r(FUNC(vtech_floppy_controller_device::rd_r));
+ map(0x13, 0x13).r(FUNC(vtech_floppy_controller_device::wpt_r));
}
//-------------------------------------------------
@@ -32,7 +52,7 @@ void vtech_floppy_controller_device::map(address_map &map)
//-------------------------------------------------
ROM_START( floppy )
- ROM_REGION(0x3000, "software", 0)
+ ROM_REGION(0x2000, "software", 0)
ROM_LOAD("vzdos.rom", 0x0000, 0x2000, CRC(b6ed6084) SHA1(59d1cbcfa6c5e1906a32704fbf0d9670f0d1fd8b))
ROM_END
@@ -47,14 +67,26 @@ const tiny_rom_entry *vtech_floppy_controller_device::device_rom_region() const
static void laser_floppies(device_slot_interface &device)
{
- device.option_add("525", FLOPPY_525_SSSD);
+ device.option_add("525", FLOPPY_525_VTECH);
+}
+
+void vtech_floppy_controller_device::floppy_formats(format_registration &fr)
+{
+ fr.add(FLOPPY_VTECH_BIN_FORMAT);
+ fr.add(FLOPPY_VTECH_DSK_FORMAT);
+ fr.add(fs::VTECH);
}
void vtech_floppy_controller_device::device_add_mconfig(machine_config &config)
{
+ vtech_memexp_device::device_add_mconfig(config);
+
VTECH_MEMEXP_SLOT(config, m_memexp);
- FLOPPY_CONNECTOR(config, m_floppy0, laser_floppies, "525", floppy_image_device::default_floppy_formats);
- FLOPPY_CONNECTOR(config, m_floppy1, laser_floppies, "525", floppy_image_device::default_floppy_formats);
+ m_memexp->set_memspace(m_mem, AS_PROGRAM);
+ m_memexp->set_iospace(m_io, AS_PROGRAM);
+
+ for (auto &floppy : m_floppy)
+ FLOPPY_CONNECTOR(config, floppy, laser_floppies, "525", floppy_formats);
}
@@ -67,12 +99,10 @@ 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) :
- device_t(mconfig, VTECH_FLOPPY_CONTROLLER, tag, owner, clock),
- device_vtech_memexp_interface(mconfig, *this),
+ 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)
{
}
@@ -82,6 +112,9 @@ vtech_floppy_controller_device::vtech_floppy_controller_device(const machine_con
void vtech_floppy_controller_device::device_start()
{
+ vtech_memexp_device::device_start();
+
+ // register for save states
save_item(NAME(m_latch));
save_item(NAME(m_shifter));
save_item(NAME(m_latching_inverter));
@@ -90,15 +123,13 @@ 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
-
- uint8_t *bios = memregion("software")->base();
+ // 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.
-
- bios[0x1678] = 0x75;
- bios[0x1688] = 0x85;
+ uint8_t *rom = memregion("software")->base();
+ rom[0x1678] = 0x75;
+ rom[0x1688] = 0x85;
}
//-------------------------------------------------
@@ -107,19 +138,15 @@ void vtech_floppy_controller_device::device_start()
void vtech_floppy_controller_device::device_reset()
{
- program_space().install_rom(0x4000, 0x5fff, memregion("software")->base());
-
- io_space().install_device(0x10, 0x1f, *this, &vtech_floppy_controller_device::map);
-
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);
}
@@ -133,34 +160,33 @@ void vtech_floppy_controller_device::device_reset()
// bit 6: !write request
// bits 4,7: floppy select
-WRITE8_MEMBER(vtech_floppy_controller_device::latch_w)
+void vtech_floppy_controller_device::latch_w(uint8_t data)
{
uint8_t diff = m_latch ^ data;
m_latch = 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->set_rpm(85);
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))) {
@@ -169,10 +195,10 @@ WRITE8_MEMBER(vtech_floppy_controller_device::latch_w)
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);
}
}
}
@@ -181,8 +207,8 @@ WRITE8_MEMBER(vtech_floppy_controller_device::latch_w)
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();
@@ -191,7 +217,7 @@ WRITE8_MEMBER(vtech_floppy_controller_device::latch_w)
}
}
if(!(m_latch & 0x40) && (diff & 0x20)) {
- if(m_write_position == ARRAY_LENGTH(m_write_buffer)) {
+ if(m_write_position == std::size(m_write_buffer)) {
update_latching_inverter();
flush_writes(true);
}
@@ -209,17 +235,20 @@ WRITE8_MEMBER(vtech_floppy_controller_device::latch_w)
// - the inverted inverter output is shifted through the lsb of the shift register
// - the inverter is cleared
-READ8_MEMBER(vtech_floppy_controller_device::shifter_r)
+uint8_t vtech_floppy_controller_device::shifter_r()
{
- update_latching_inverter();
- m_shifter = (m_shifter << 1) | !m_latching_inverter;
- m_latching_inverter = false;
+ if (!machine().side_effects_disabled())
+ {
+ update_latching_inverter();
+ m_shifter = (m_shifter << 1) | !m_latching_inverter;
+ m_latching_inverter = false;
+ }
return m_shifter;
}
// Linked to the latching inverter on bit 7, rest is floating
-READ8_MEMBER(vtech_floppy_controller_device::rd_r)
+uint8_t vtech_floppy_controller_device::rd_r()
{
update_latching_inverter();
return m_latching_inverter ? 0x80 : 0x00;
@@ -227,22 +256,22 @@ READ8_MEMBER(vtech_floppy_controller_device::rd_r)
// Linked to wp signal on bit 7, rest is floating
-READ8_MEMBER(vtech_floppy_controller_device::wpt_r)
+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;
@@ -258,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)
@@ -283,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 a81ea420395..236abc84d72 100644
--- a/src/devices/bus/vtech/memexp/floppy.h
+++ b/src/devices/bus/vtech/memexp/floppy.h
@@ -24,34 +24,37 @@
// ======================> vtech_floppy_controller_device
-class vtech_floppy_controller_device : public device_t, public device_vtech_memexp_interface
+class vtech_floppy_controller_device : public vtech_memexp_device
{
public:
// construction/destruction
vtech_floppy_controller_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;
- 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 ATTR_COLD;
+ 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;
+
+ virtual void mem_map(address_map &map) override ATTR_COLD;
+ virtual void io_map(address_map &map) override ATTR_COLD;
private:
- void map(address_map &map);
+ required_device<vtech_memexp_slot_device> m_memexp;
+ required_device_array<floppy_connector, 2> m_floppy;
+ floppy_image_device *m_selected_floppy;
+
+ static void floppy_formats(format_registration &fr);
- DECLARE_WRITE8_MEMBER(latch_w);
- DECLARE_READ8_MEMBER(shifter_r);
- DECLARE_READ8_MEMBER(rd_r);
- DECLARE_READ8_MEMBER(wpt_r);
+ void latch_w(uint8_t data);
+ uint8_t shifter_r();
+ uint8_t rd_r();
+ uint8_t wpt_r();
void index_callback(floppy_image_device *floppy, int state);
void update_latching_inverter();
void flush_writes(bool keep_margin = false);
- required_device<vtech_memexp_slot_device> m_memexp;
- required_device<floppy_connector> m_floppy0, m_floppy1;
- floppy_image_device *m_floppy;
-
uint8_t m_latch, m_shifter;
bool m_latching_inverter;
int m_current_cyl;
diff --git a/src/devices/bus/vtech/memexp/memexp.cpp b/src/devices/bus/vtech/memexp/memexp.cpp
index 90f51da7345..984849fe9ab 100644
--- a/src/devices/bus/vtech/memexp/memexp.cpp
+++ b/src/devices/bus/vtech/memexp/memexp.cpp
@@ -1,5 +1,5 @@
-// license:GPL-2.0+
-// copyright-holders:Dirk Best
+// license: GPL-2.0+
+// copyright-holders: Dirk Best
/***************************************************************************
VTech Laser/VZ Memory Expansion Slot
@@ -29,10 +29,9 @@ DEFINE_DEVICE_TYPE(VTECH_MEMEXP_SLOT, vtech_memexp_slot_device, "vtech_memexp_sl
vtech_memexp_slot_device::vtech_memexp_slot_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) :
device_t(mconfig, VTECH_MEMEXP_SLOT, tag, owner, clock),
- device_slot_interface(mconfig, *this),
- m_program(*this, finder_base::DUMMY_TAG, -1),
- m_io(*this, finder_base::DUMMY_TAG, -1),
- m_cart(nullptr),
+ device_single_card_slot_interface<device_vtech_memexp_interface>(mconfig, *this),
+ m_memspace(*this, finder_base::DUMMY_TAG, -1),
+ m_iospace(*this, finder_base::DUMMY_TAG, -1),
m_int_handler(*this),
m_nmi_handler(*this),
m_reset_handler(*this)
@@ -48,66 +47,132 @@ vtech_memexp_slot_device::~vtech_memexp_slot_device()
}
//-------------------------------------------------
-// device_config_complete - perform any
-// operations now that the configuration is
-// complete
+// device_start - device-specific startup
//-------------------------------------------------
-void vtech_memexp_slot_device::device_config_complete()
+void vtech_memexp_slot_device::device_start()
{
- // for passthrough connectors, use the parent slot's spaces
- if (dynamic_cast<device_vtech_memexp_interface *>(owner()) != nullptr)
- {
- auto parent = dynamic_cast<vtech_memexp_slot_device *>(owner()->owner());
- if (parent != nullptr)
+ // get inserted module
+ m_module = get_card_device();
+
+ // install memory access taps
+ m_memspace->install_readwrite_tap
+ (
+ 0x0000, 0xffff, "mem_tap",
+ [this](offs_t offset, uint8_t &data, uint8_t mem_mask)
+ {
+ if (m_module)
+ data &= m_module->mreq_r(offset);
+ },
+ [this](offs_t offset, uint8_t &data, uint8_t mem_mask)
{
- if (m_program.finder_tag() == finder_base::DUMMY_TAG)
- m_program.set_tag(parent->m_program, parent->m_program.spacenum());
- if (m_io.finder_tag() == finder_base::DUMMY_TAG)
- m_io.set_tag(parent->m_io, parent->m_io.spacenum());
+ if (m_module)
+ m_module->mreq_w(offset, data);
}
- }
+ );
+
+ // install io access taps
+ m_iospace->install_readwrite_tap
+ (
+ 0x00, 0xff, "io_tap",
+ [this](offs_t offset, uint8_t &data, uint8_t mem_mask)
+ {
+ if (m_module)
+ data &= m_module->iorq_r(offset);
+ },
+ [this](offs_t offset, uint8_t &data, uint8_t mem_mask)
+ {
+ if (m_module)
+ m_module->iorq_w(offset, data);
+ }
+ );
}
+
+//**************************************************************************
+// CARTRIDGE INTERFACE
+//**************************************************************************
+
//-------------------------------------------------
-// device_start - device-specific startup
+// device_vtech_memexp_interface - constructor
//-------------------------------------------------
-void vtech_memexp_slot_device::device_start()
+device_vtech_memexp_interface::device_vtech_memexp_interface(const machine_config &mconfig, device_t &device) :
+ device_interface(device, "vtechmemexp")
{
- // resolve callbacks
- m_int_handler.resolve_safe();
- m_nmi_handler.resolve_safe();
- m_reset_handler.resolve_safe();
+ m_slot = dynamic_cast<vtech_memexp_slot_device *>(device.owner());
}
//-------------------------------------------------
-// device_reset - device-specific reset
+// ~device_vtech_memexp_interface - destructor
//-------------------------------------------------
-void vtech_memexp_slot_device::device_reset()
+device_vtech_memexp_interface::~device_vtech_memexp_interface()
{
}
//**************************************************************************
-// CARTRIDGE INTERFACE
+// BASE DEVICE
//**************************************************************************
//-------------------------------------------------
-// device_vtech_memexp_interface - constructor
+// vtech_memexp_device - constructor
//-------------------------------------------------
-device_vtech_memexp_interface::device_vtech_memexp_interface(const machine_config &mconfig, device_t &device) :
- device_slot_card_interface(mconfig, device)
+vtech_memexp_device::vtech_memexp_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_vtech_memexp_interface(mconfig, *this),
+ m_mem(*this, "memspace"),
+ m_io(*this, "iospace")
{
- m_slot = dynamic_cast<vtech_memexp_slot_device *>(device.owner());
}
//-------------------------------------------------
-// ~device_vtech_memexp_interface - destructor
+// device_add_mconfig - add device configuration
//-------------------------------------------------
-device_vtech_memexp_interface::~device_vtech_memexp_interface()
+void vtech_memexp_device::device_add_mconfig(machine_config &config)
+{
+ ADDRESS_MAP_BANK(config, m_mem);
+ m_mem->set_addrmap(AS_PROGRAM, &vtech_memexp_device::mem_map);
+ m_mem->set_data_width(8);
+ m_mem->set_addr_width(16);
+
+ ADDRESS_MAP_BANK(config, m_io);
+ m_io->set_addrmap(AS_PROGRAM, &vtech_memexp_device::io_map);
+ m_io->set_data_width(8);
+ m_io->set_addr_width(16);
+}
+
+//-------------------------------------------------
+// device_start - device-specific startup
+//-------------------------------------------------
+
+void vtech_memexp_device::device_start()
+{
+ // silence unmapped warnings, or we'll get them for everything the
+ // expansion device doesn't handle
+ m_mem->set_log_unmap(false);
+ m_io->set_log_unmap(false);
+}
+
+uint8_t vtech_memexp_device::mreq_r(offs_t offset)
+{
+ return m_mem->read8(offset);
+}
+
+void vtech_memexp_device::mreq_w(offs_t offset, uint8_t data)
+{
+ m_mem->write8(offset, data);
+}
+
+uint8_t vtech_memexp_device::iorq_r(offs_t offset)
+{
+ return m_io->read8(offset);
+}
+
+void vtech_memexp_device::iorq_w(offs_t offset, uint8_t data)
{
+ m_io->write8(offset, data);
}
diff --git a/src/devices/bus/vtech/memexp/memexp.h b/src/devices/bus/vtech/memexp/memexp.h
index ca096075e90..6521fd5bdc6 100644
--- a/src/devices/bus/vtech/memexp/memexp.h
+++ b/src/devices/bus/vtech/memexp/memexp.h
@@ -1,5 +1,5 @@
-// license:GPL-2.0+
-// copyright-holders:Dirk Best
+// license: GPL-2.0+
+// copyright-holders: Dirk Best
/***************************************************************************
VTech Laser/VZ Memory Expansion Slot
@@ -36,16 +36,19 @@
#pragma once
+#include "machine/bankdev.h"
+
// include here so drivers don't need to
#include "carts.h"
+
//**************************************************************************
// TYPE DEFINITIONS
//**************************************************************************
class device_vtech_memexp_interface;
-class vtech_memexp_slot_device : public device_t, public device_slot_interface
+class vtech_memexp_slot_device : public device_t, public device_single_card_slot_interface<device_vtech_memexp_interface>
{
friend class device_vtech_memexp_interface;
public:
@@ -61,8 +64,8 @@ public:
vtech_memexp_slot_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
virtual ~vtech_memexp_slot_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); }
+ template <typename T> void set_memspace(T &&tag, int spacenum) { m_memspace.set_tag(std::forward<T>(tag), spacenum); }
+ template <typename T> void set_iospace(T &&tag, int spacenum) { m_iospace.set_tag(std::forward<T>(tag), spacenum); }
// callbacks
auto int_handler() { return m_int_handler.bind(); }
@@ -70,42 +73,66 @@ 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
- virtual void device_config_complete() override;
- virtual void device_start() override;
- virtual void device_reset() override;
-
- required_address_space m_program;
- required_address_space m_io;
-
- device_vtech_memexp_interface *m_cart;
+ virtual void device_start() override ATTR_COLD;
private:
+ required_address_space m_memspace;
+ required_address_space m_iospace;
+
devcb_write_line m_int_handler;
devcb_write_line m_nmi_handler;
devcb_write_line m_reset_handler;
+
+ device_vtech_memexp_interface *m_module;
};
// class representing interface-specific live memexp device
-class device_vtech_memexp_interface : public device_slot_card_interface
+class device_vtech_memexp_interface : public device_interface
{
public:
// construction/destruction
device_vtech_memexp_interface(const machine_config &mconfig, device_t &device);
virtual ~device_vtech_memexp_interface();
-protected:
- address_space &program_space() { return *m_slot->m_program; }
- address_space &io_space() { return *m_slot->m_io; }
+ 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) { }
+protected:
vtech_memexp_slot_device *m_slot;
};
+// base memory expansion device
+class vtech_memexp_device : public device_t, public device_vtech_memexp_interface
+{
+public:
+ // construction/destruction
+ vtech_memexp_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock);
+
+ // from host
+ 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 void iorq_w(offs_t offset, uint8_t data) override;
+
+protected:
+ virtual void device_add_mconfig(machine_config &config) override ATTR_COLD;
+ virtual void device_start() override ATTR_COLD;
+
+ virtual void mem_map(address_map &map) { }
+ virtual void io_map(address_map &map) { }
+
+ required_device<address_map_bank_device> m_mem;
+ required_device<address_map_bank_device> m_io;
+};
+
// device type definition
DECLARE_DEVICE_TYPE(VTECH_MEMEXP_SLOT, vtech_memexp_slot_device)
diff --git a/src/devices/bus/vtech/memexp/memory.cpp b/src/devices/bus/vtech/memexp/memory.cpp
index 15ccbeb949e..bfac5f06b4c 100644
--- a/src/devices/bus/vtech/memexp/memory.cpp
+++ b/src/devices/bus/vtech/memexp/memory.cpp
@@ -25,31 +25,31 @@ DEFINE_DEVICE_TYPE(VTECH_LASER_64K, vtech_laser_64k_device, "vtech_laser_6
//**************************************************************************
//-------------------------------------------------
-// laser110_16k_device - constructor
+// mem_map - memory space address map
//-------------------------------------------------
-vtech_laser110_16k_device::vtech_laser110_16k_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) :
- device_t(mconfig, VTECH_LASER110_16K, tag, owner, clock),
- device_vtech_memexp_interface(mconfig, *this)
+void vtech_laser110_16k_device::mem_map(address_map &map)
{
+ map.unmap_value_high();
+ map(0x8000, 0xbfff).ram();
}
//-------------------------------------------------
-// device_start - device-specific startup
+// laser110_16k_device - constructor
//-------------------------------------------------
-void vtech_laser110_16k_device::device_start()
+vtech_laser110_16k_device::vtech_laser110_16k_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) :
+ vtech_memexp_device(mconfig, VTECH_LASER110_16K, tag, owner, clock)
{
- m_ram.resize(16 * 1024);
}
//-------------------------------------------------
-// device_reset - device-specific reset
+// device_start - device-specific startup
//-------------------------------------------------
-void vtech_laser110_16k_device::device_reset()
+void vtech_laser110_16k_device::device_start()
{
- program_space().install_ram(0x8000, 0xbfff, &m_ram[0]);
+ vtech_memexp_device::device_start();
}
@@ -58,31 +58,31 @@ void vtech_laser110_16k_device::device_reset()
//**************************************************************************
//-------------------------------------------------
-// vtech_laser210_16k_device - constructor
+// mem_map - memory space address map
//-------------------------------------------------
-vtech_laser210_16k_device::vtech_laser210_16k_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) :
- device_t(mconfig, VTECH_LASER210_16K, tag, owner, clock),
- device_vtech_memexp_interface(mconfig, *this)
+void vtech_laser210_16k_device::mem_map(address_map &map)
{
+ map.unmap_value_high();
+ map(0x9000, 0xcfff).ram();
}
//-------------------------------------------------
-// device_start - device-specific startup
+// vtech_laser210_16k_device - constructor
//-------------------------------------------------
-void vtech_laser210_16k_device::device_start()
+vtech_laser210_16k_device::vtech_laser210_16k_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) :
+ vtech_memexp_device(mconfig, VTECH_LASER210_16K, tag, owner, clock)
{
- m_ram.resize(16 * 1024);
}
//-------------------------------------------------
-// device_reset - device-specific reset
+// device_start - device-specific startup
//-------------------------------------------------
-void vtech_laser210_16k_device::device_reset()
+void vtech_laser210_16k_device::device_start()
{
- program_space().install_ram(0x9000, 0xcfff, &m_ram[0]);
+ vtech_memexp_device::device_start();
}
@@ -91,31 +91,31 @@ void vtech_laser210_16k_device::device_reset()
//**************************************************************************
//-------------------------------------------------
-// vtech_laser310_16k_device - constructor
+// mem_map - memory space address map
//-------------------------------------------------
-vtech_laser310_16k_device::vtech_laser310_16k_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) :
- device_t(mconfig, VTECH_LASER310_16K, tag, owner, clock),
- device_vtech_memexp_interface(mconfig, *this)
+void vtech_laser310_16k_device::mem_map(address_map &map)
{
+ map.unmap_value_high();
+ map(0xb800, 0xf7ff).ram();
}
//-------------------------------------------------
-// device_start - device-specific startup
+// vtech_laser310_16k_device - constructor
//-------------------------------------------------
-void vtech_laser310_16k_device::device_start()
+vtech_laser310_16k_device::vtech_laser310_16k_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) :
+ vtech_memexp_device(mconfig, VTECH_LASER310_16K, tag, owner, clock)
{
- m_ram.resize(16 * 1024);
}
//-------------------------------------------------
-// device_reset - device-specific reset
+// device_start - device-specific startup
//-------------------------------------------------
-void vtech_laser310_16k_device::device_reset()
+void vtech_laser310_16k_device::device_start()
{
- program_space().install_ram(0xb800, 0xf7ff, &m_ram[0]);
+ vtech_memexp_device::device_start();
}
@@ -124,44 +124,54 @@ void vtech_laser310_16k_device::device_reset()
//**************************************************************************
//-------------------------------------------------
-// vtech_laser_64k_device - constructor
+// mem_map - memory space address map
//-------------------------------------------------
-vtech_laser_64k_device::vtech_laser_64k_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) :
- device_t(mconfig, VTECH_LASER_64K, tag, owner, clock),
- device_vtech_memexp_interface(mconfig, *this)
+void vtech_laser_64k_device::mem_map(address_map &map)
{
+ map.unmap_value_high();
+ map(0x8000, 0xbfff).bankrw(m_fixed_bank);
+ map(0xc000, 0xffff).bankrw(m_bank);
}
//-------------------------------------------------
-// device_start - device-specific startup
+// io_map - memory space address map
//-------------------------------------------------
-void vtech_laser_64k_device::device_start()
+void vtech_laser_64k_device::io_map(address_map &map)
+{
+ map.unmap_value_high();
+ map(0x70, 0x70).mirror(0x0f).lw8(NAME([this] (uint8_t data) { m_bank->set_entry(data & 0x03); }));
+}
+
+//-------------------------------------------------
+// vtech_laser_64k_device - constructor
+//-------------------------------------------------
+
+vtech_laser_64k_device::vtech_laser_64k_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) :
+ vtech_memexp_device(mconfig, VTECH_LASER_64K, tag, owner, clock),
+ m_fixed_bank(*this, "fixed_bank"),
+ m_bank(*this, "bank")
{
- m_ram.resize(64 * 1024);
}
//-------------------------------------------------
-// device_reset - device-specific reset
+// device_start - device-specific startup
//-------------------------------------------------
-void vtech_laser_64k_device::device_reset()
+void vtech_laser_64k_device::device_start()
{
- // fixed first bank
- program_space().install_ram(0x8000, 0xbfff, &m_ram[0]);
+ vtech_memexp_device::device_start();
- // other banks
- program_space().install_readwrite_bank(0xc000, 0xffff, tag());
+ // init ram
+ m_ram = std::make_unique<uint8_t[]>(0x10000);
- membank(tag())->configure_entries(0, 4, &m_ram[0], 0x4000);
- membank(tag())->set_entry(1);
+ // configure banking
+ m_fixed_bank->set_base(m_ram.get());
- // bank switch
- io_space().install_write_handler(0x70, 0x7f, write8_delegate(FUNC(vtech_laser_64k_device::bankswitch_w), this));
-}
+ m_bank->configure_entries(0, 4, m_ram.get(), 0x4000);
+ m_bank->set_entry(1);
-WRITE8_MEMBER( vtech_laser_64k_device::bankswitch_w )
-{
- membank(tag())->set_entry(data & 0x03);
+ // register for savestates
+ save_pointer(NAME(m_ram), 0x10000);
}
diff --git a/src/devices/bus/vtech/memexp/memory.h b/src/devices/bus/vtech/memexp/memory.h
index f8a0fe78e7d..2f467c73fdd 100644
--- a/src/devices/bus/vtech/memexp/memory.h
+++ b/src/devices/bus/vtech/memexp/memory.h
@@ -20,68 +20,65 @@
// ======================> vtech_laser110_16k_device
-class vtech_laser110_16k_device : public device_t, public device_vtech_memexp_interface
+class vtech_laser110_16k_device : public vtech_memexp_device
{
public:
// construction/destruction
vtech_laser110_16k_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_start() override ATTR_COLD;
-private:
- std::vector<uint8_t> m_ram;
+ virtual void mem_map(address_map &map) override ATTR_COLD;
};
// ======================> vtech_laser210_16k_device
-class vtech_laser210_16k_device : public device_t, public device_vtech_memexp_interface
+class vtech_laser210_16k_device : public vtech_memexp_device
{
public:
// construction/destruction
vtech_laser210_16k_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_start() override ATTR_COLD;
-private:
- std::vector<uint8_t> m_ram;
+ virtual void mem_map(address_map &map) override ATTR_COLD;
};
// ======================> vtech_laser310_16k_device
-class vtech_laser310_16k_device : public device_t, public device_vtech_memexp_interface
+class vtech_laser310_16k_device : public vtech_memexp_device
{
public:
// construction/destruction
vtech_laser310_16k_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_start() override ATTR_COLD;
-private:
- std::vector<uint8_t> m_ram;
+ virtual void mem_map(address_map &map) override ATTR_COLD;
};
// ======================> vtech_laser_64k_device
-class vtech_laser_64k_device : public device_t, public device_vtech_memexp_interface
+class vtech_laser_64k_device : public vtech_memexp_device
{
public:
// construction/destruction
vtech_laser_64k_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
- DECLARE_WRITE8_MEMBER( bankswitch_w );
-
protected:
- virtual void device_start() override;
- virtual void device_reset() override;
+ virtual void device_start() override ATTR_COLD;
+
+ virtual void mem_map(address_map &map) override ATTR_COLD;
+ virtual void io_map(address_map &map) override ATTR_COLD;
private:
- std::vector<uint8_t> m_ram;
+ required_memory_bank m_fixed_bank;
+ required_memory_bank m_bank;
+
+ std::unique_ptr<uint8_t[]> m_ram;
};
// device type definition
diff --git a/src/devices/bus/vtech/memexp/rs232.cpp b/src/devices/bus/vtech/memexp/rs232.cpp
index cf21b7ee006..cf07b2055d6 100644
--- a/src/devices/bus/vtech/memexp/rs232.cpp
+++ b/src/devices/bus/vtech/memexp/rs232.cpp
@@ -17,12 +17,28 @@
DEFINE_DEVICE_TYPE(VTECH_RS232_INTERFACE, vtech_rs232_interface_device, "vtech_rs232", "DSE VZ-200/300 RS-232 Interface")
//-------------------------------------------------
+// mem_map - memory space address map
+//-------------------------------------------------
+
+void vtech_rs232_interface_device::mem_map(address_map &map)
+{
+ map.unmap_value_high();
+ map(0x4000, 0x47ff).rom().region("software", 0);
+ map(0x5000, 0x5000).mirror(0x7ff).r(FUNC(vtech_rs232_interface_device::receive_data_r));
+ map(0x5800, 0x5800).mirror(0x7ff).w(FUNC(vtech_rs232_interface_device::transmit_data_w));
+}
+
+//-------------------------------------------------
// rom_region - device-specific ROM region
//-------------------------------------------------
ROM_START( rs232 )
ROM_REGION(0x800, "software", 0)
- ROM_LOAD("rs232_v15.ic2", 0x000, 0x800, CRC(6545260d) SHA1(4042f6f1e09e383f3c92f628c6187dc5f072fdb2))
+ ROM_DEFAULT_BIOS("16")
+ ROM_SYSTEM_BIOS(0, "15", "Version 1.5") // 1985
+ ROMX_LOAD("rs232_v15.ic2", 0x000, 0x800, CRC(6545260d) SHA1(4042f6f1e09e383f3c92f628c6187dc5f072fdb2), ROM_BIOS(0))
+ ROM_SYSTEM_BIOS(1, "16", "Version 1.6") // 1987
+ ROMX_LOAD("rs232_v16.ic2", 0x000, 0x800, CRC(d761fc79) SHA1(28e00c7ff33143a948308330859bee54b474e114), ROM_BIOS(1))
ROM_END
const tiny_rom_entry *vtech_rs232_interface_device::device_rom_region() const
@@ -36,8 +52,10 @@ const tiny_rom_entry *vtech_rs232_interface_device::device_rom_region() const
void vtech_rs232_interface_device::device_add_mconfig(machine_config &config)
{
+ vtech_memexp_device::device_add_mconfig(config);
+
RS232_PORT(config, m_rs232, default_rs232_devices, nullptr);
- m_rs232->rxd_handler().set(FUNC(vtech_rs232_interface_device::rs232_rx_w));
+ m_rs232->rxd_handler().set([this](int state) { m_rx = state; });
}
@@ -50,8 +68,7 @@ void vtech_rs232_interface_device::device_add_mconfig(machine_config &config)
//-------------------------------------------------
vtech_rs232_interface_device::vtech_rs232_interface_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) :
- device_t(mconfig, VTECH_RS232_INTERFACE, tag, owner, clock),
- device_vtech_memexp_interface(mconfig, *this),
+ vtech_memexp_device(mconfig, VTECH_RS232_INTERFACE, tag, owner, clock),
m_rs232(*this, "rs232"),
m_rx(1)
{
@@ -63,20 +80,10 @@ vtech_rs232_interface_device::vtech_rs232_interface_device(const machine_config
void vtech_rs232_interface_device::device_start()
{
-}
-
-//-------------------------------------------------
-// device_reset - device-specific reset
-//-------------------------------------------------
-
-void vtech_rs232_interface_device::device_reset()
-{
- // program
- program_space().install_rom(0x4000, 0x47ff, 0x800, memregion("software")->base());
+ vtech_memexp_device::device_start();
- // data
- program_space().install_read_handler(0x5000, 0x57ff, read8_delegate(FUNC(vtech_rs232_interface_device::receive_data_r), this));
- program_space().install_write_handler(0x5800, 0x5fff, write8_delegate(FUNC(vtech_rs232_interface_device::transmit_data_w), this));
+ // register for save states
+ save_item(NAME(m_rx));
}
@@ -84,17 +91,12 @@ void vtech_rs232_interface_device::device_reset()
// IMPLEMENTATION
//**************************************************************************
-WRITE_LINE_MEMBER( vtech_rs232_interface_device::rs232_rx_w )
-{
- m_rx = state;
-}
-
-READ8_MEMBER( vtech_rs232_interface_device::receive_data_r )
+uint8_t vtech_rs232_interface_device::receive_data_r()
{
return 0x7f | (m_rx << 7);
}
-WRITE8_MEMBER( vtech_rs232_interface_device::transmit_data_w )
+void vtech_rs232_interface_device::transmit_data_w(uint8_t data)
{
m_rs232->write_txd(!BIT(data, 7));
}
diff --git a/src/devices/bus/vtech/memexp/rs232.h b/src/devices/bus/vtech/memexp/rs232.h
index 272ef41e2d6..6640be2d2d5 100644
--- a/src/devices/bus/vtech/memexp/rs232.h
+++ b/src/devices/bus/vtech/memexp/rs232.h
@@ -21,25 +21,25 @@
// ======================> vtech_rs232_interface_device
-class vtech_rs232_interface_device : public device_t, public device_vtech_memexp_interface
+class vtech_rs232_interface_device : public vtech_memexp_device
{
public:
// construction/destruction
vtech_rs232_interface_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;
- 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 ATTR_COLD;
+ virtual void device_add_mconfig(machine_config &config) override ATTR_COLD;
+ virtual void device_start() override ATTR_COLD;
-private:
- DECLARE_WRITE_LINE_MEMBER( rs232_rx_w );
- DECLARE_READ8_MEMBER( receive_data_r );
- DECLARE_WRITE8_MEMBER( transmit_data_w );
+ virtual void mem_map(address_map &map) override ATTR_COLD;
+private:
required_device<rs232_port_device> m_rs232;
+ uint8_t receive_data_r();
+ void transmit_data_w(uint8_t data);
+
int m_rx;
};
diff --git a/src/devices/bus/vtech/memexp/rtty.cpp b/src/devices/bus/vtech/memexp/rtty.cpp
index 96e394bfb4d..6a0f96c58a8 100644
--- a/src/devices/bus/vtech/memexp/rtty.cpp
+++ b/src/devices/bus/vtech/memexp/rtty.cpp
@@ -17,6 +17,19 @@
DEFINE_DEVICE_TYPE(VTECH_RTTY_INTERFACE, vtech_rtty_interface_device, "vtech_rtty", "DSE VZ-200/300 RTTY Interface")
//-------------------------------------------------
+// mem_map - memory space address map
+//-------------------------------------------------
+
+void vtech_rtty_interface_device::mem_map(address_map &map)
+{
+ map.unmap_value_high();
+ map(0x4000, 0x4fff).rom().region("software", 0);
+ map(0x5000, 0x5000).mirror(0x7ff).r(FUNC(vtech_rtty_interface_device::receive_data_r));
+ map(0x5800, 0x5800).mirror(0x7ff).w(FUNC(vtech_rtty_interface_device::transmit_data_w));
+ map(0x6000, 0x6000).mirror(0x7ff).w(FUNC(vtech_rtty_interface_device::relay_w));
+}
+
+//-------------------------------------------------
// rom_region - device-specific ROM region
//-------------------------------------------------
@@ -40,8 +53,7 @@ const tiny_rom_entry *vtech_rtty_interface_device::device_rom_region() const
//-------------------------------------------------
vtech_rtty_interface_device::vtech_rtty_interface_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) :
- device_t(mconfig, VTECH_RTTY_INTERFACE, tag, owner, clock),
- device_vtech_memexp_interface(mconfig, *this)
+ vtech_memexp_device(mconfig, VTECH_RTTY_INTERFACE, tag, owner, clock)
{
}
@@ -51,21 +63,7 @@ vtech_rtty_interface_device::vtech_rtty_interface_device(const machine_config &m
void vtech_rtty_interface_device::device_start()
{
-}
-
-//-------------------------------------------------
-// device_reset - device-specific reset
-//-------------------------------------------------
-
-void vtech_rtty_interface_device::device_reset()
-{
- // program
- program_space().install_rom(0x4000, 0x4fff, 0x1000, memregion("software")->base());
-
- // data
- program_space().install_read_handler(0x5000, 0x57ff, read8_delegate(FUNC(vtech_rtty_interface_device::receive_data_r), this));
- program_space().install_write_handler(0x5800, 0x5fff, write8_delegate(FUNC(vtech_rtty_interface_device::transmit_data_w), this));
- program_space().install_write_handler(0x6000, 0x67ff, write8_delegate(FUNC(vtech_rtty_interface_device::relay_w), this));
+ vtech_memexp_device::device_start();
}
@@ -73,17 +71,17 @@ void vtech_rtty_interface_device::device_reset()
// IMPLEMENTATION
//**************************************************************************
-READ8_MEMBER( vtech_rtty_interface_device::receive_data_r )
+uint8_t vtech_rtty_interface_device::receive_data_r()
{
return 0xff;
}
-WRITE8_MEMBER( vtech_rtty_interface_device::transmit_data_w )
+void vtech_rtty_interface_device::transmit_data_w(uint8_t data)
{
logerror("transmit_w: %d\n", BIT(data, 7));
}
-WRITE8_MEMBER( vtech_rtty_interface_device::relay_w )
+void vtech_rtty_interface_device::relay_w(uint8_t data)
{
logerror("relay_w: %d\n", BIT(data, 7));
}
diff --git a/src/devices/bus/vtech/memexp/rtty.h b/src/devices/bus/vtech/memexp/rtty.h
index 82c3b150f34..6313001ba04 100644
--- a/src/devices/bus/vtech/memexp/rtty.h
+++ b/src/devices/bus/vtech/memexp/rtty.h
@@ -20,20 +20,22 @@
// ======================> vtech_rtty_interface_device
-class vtech_rtty_interface_device : public device_t, public device_vtech_memexp_interface
+class vtech_rtty_interface_device : public vtech_memexp_device
{
public:
// construction/destruction
vtech_rtty_interface_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
- DECLARE_READ8_MEMBER( receive_data_r );
- DECLARE_WRITE8_MEMBER( transmit_data_w );
- DECLARE_WRITE8_MEMBER( relay_w );
-
protected:
- virtual const tiny_rom_entry *device_rom_region() const override;
- virtual void device_start() override;
- virtual void device_reset() override;
+ virtual const tiny_rom_entry *device_rom_region() const override ATTR_COLD;
+ virtual void device_start() override ATTR_COLD;
+
+ virtual void mem_map(address_map &map) override ATTR_COLD;
+
+private:
+ uint8_t receive_data_r();
+ void transmit_data_w(uint8_t data);
+ void relay_w(uint8_t data);
};
// device type definition
diff --git a/src/devices/bus/vtech/memexp/sdloader.cpp b/src/devices/bus/vtech/memexp/sdloader.cpp
new file mode 100644
index 00000000000..18420ca459b
--- /dev/null
+++ b/src/devices/bus/vtech/memexp/sdloader.cpp
@@ -0,0 +1,343 @@
+// license: GPL-2.0+
+// copyright-holders: Dirk Best
+/***************************************************************************
+
+ BennVenn SD Loader for VZ300
+
+ Notes:
+ - Also works for VZ200
+ - The loader can't format the SD card, so you need to do that yourself
+ Instructions for Linux:
+ * dd if=/dev/zero of=vz300.img count=2048 bs=1M
+ * mkfs.vfat vz300.img
+ * mount image and copy .vz files to it
+ * chdman createhd -o vz300.chd -i vz300.img -c none
+
+ TODO:
+ - SPI clock needed too fast
+
+***************************************************************************/
+
+#include "emu.h"
+#include "sdloader.h"
+
+#include "machine/spi_sdcard.h"
+
+#define LOG_SPI (1U << 1)
+#define VERBOSE (LOG_GENERAL)
+#include "logmacro.h"
+
+
+namespace {
+
+//**************************************************************************
+// TYPE DEFINITIONS
+//**************************************************************************
+
+// ======================> vtech_sdloader_device
+
+class vtech_sdloader_device : public vtech_memexp_device
+{
+public:
+ // construction/destruction
+ vtech_sdloader_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
+
+ static constexpr feature_type unemulated_features() { return feature::DISK; }
+
+protected:
+ virtual const tiny_rom_entry *device_rom_region() const override ATTR_COLD;
+ 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;
+
+ virtual void mem_map(address_map &map) override ATTR_COLD;
+ virtual void io_map(address_map &map) override ATTR_COLD;
+
+private:
+ required_device<spi_sdcard_device> m_sdcard;
+ required_memory_bank m_dosbank;
+ memory_view m_dosview;
+ memory_bank_creator m_expbank;
+
+ TIMER_CALLBACK_MEMBER(spi_clock);
+ void spi_miso_w(int state);
+
+ void mapper_w(uint8_t data);
+ void sdcfg_w(uint8_t data);
+ uint8_t sdio_r();
+ void sdio_w(uint8_t data);
+ void mode_w(uint8_t data);
+
+ uint8_t exp_ram_r(offs_t offset);
+ void exp_ram_w(offs_t offset, uint8_t data);
+
+ emu_timer *m_spi_clock;
+ bool m_spi_clock_state;
+ bool m_spi_clock_sysclk;
+ int m_spi_clock_cycles;
+ int m_in_bit;
+ uint8_t m_in_latch;
+ uint8_t m_out_latch;
+
+ std::unique_ptr<uint8_t[]> m_ram;
+ bool m_vz300_mode;
+};
+
+
+//-------------------------------------------------
+// mem_map - memory space address map
+//-------------------------------------------------
+
+void vtech_sdloader_device::mem_map(address_map &map)
+{
+ map.unmap_value_high();
+ map(0x4000, 0x67ff).view(m_dosview);
+ m_dosview[0](0x4000, 0x67ff).rom().region("software", 0).bankw(m_dosbank);
+ m_dosview[1](0x4000, 0x67ff).bankrw(m_dosbank);
+ map(0x9000, 0xffff).rw(FUNC(vtech_sdloader_device::exp_ram_r), FUNC(vtech_sdloader_device::exp_ram_w));
+}
+
+//-------------------------------------------------
+// io_map - io space address map
+//-------------------------------------------------
+
+void vtech_sdloader_device::io_map(address_map &map)
+{
+ map.unmap_value_high();
+ map(0x37, 0x37).w(FUNC(vtech_sdloader_device::mapper_w));
+ map(0x38, 0x38).w(FUNC(vtech_sdloader_device::sdcfg_w));
+ map(0x39, 0x39).rw(FUNC(vtech_sdloader_device::sdio_r), FUNC(vtech_sdloader_device::sdio_w));
+ map(0x3a, 0x3a).w(FUNC(vtech_sdloader_device::mode_w));
+}
+
+//-------------------------------------------------
+// rom_region - device-specific ROM region
+//-------------------------------------------------
+
+ROM_START( sdloader )
+ ROM_REGION(0x2800, "software", 0)
+ ROM_DEFAULT_BIOS("18")
+ ROM_SYSTEM_BIOS(0, "15", "Version 1.5")
+ ROMX_LOAD("vzdos15.bin", 0x0000, 0x16c2, CRC(828f7703) SHA1(150c6e5a8f20416c0dab1fa96f68726f415a8b7e), ROM_BIOS(0))
+ ROM_SYSTEM_BIOS(1, "17", "Version 1.7")
+ ROMX_LOAD("vzdos17.bin", 0x0000, 0x1783, CRC(7ef7fb1e) SHA1(6278ac675d6c08dca39a5a7f4c72988a178eff8a), ROM_BIOS(1))
+ ROM_SYSTEM_BIOS(2, "18", "Version 1.8")
+ ROMX_LOAD("vzdos18.bin", 0x0000, 0x1795, CRC(2b1cec28) SHA1(d4f8fa0c7a70984334be3e5c831017cfc53683b2), ROM_BIOS(2))
+ROM_END
+
+const tiny_rom_entry *vtech_sdloader_device::device_rom_region() const
+{
+ return ROM_NAME( sdloader );
+}
+
+//-------------------------------------------------
+// device_add_mconfig - add device configuration
+//-------------------------------------------------
+
+void vtech_sdloader_device::device_add_mconfig(machine_config &config)
+{
+ vtech_memexp_device::device_add_mconfig(config);
+
+ SPI_SDCARD(config, m_sdcard, 0);
+ m_sdcard->set_prefer_sdhc();
+ m_sdcard->spi_miso_callback().set(FUNC(vtech_sdloader_device::spi_miso_w));
+}
+
+
+//**************************************************************************
+// LIVE DEVICE
+//**************************************************************************
+
+//-------------------------------------------------
+// vtech_sdloader_device - constructor
+//-------------------------------------------------
+
+vtech_sdloader_device::vtech_sdloader_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) :
+ vtech_memexp_device(mconfig, VTECH_SDLOADER, tag, owner, clock),
+ m_sdcard(*this, "sdcard"),
+ m_dosbank(*this, "dosbank"),
+ m_dosview(*this, "dosview"),
+ m_expbank(*this, "expbank"),
+ m_spi_clock_state(false),
+ m_spi_clock_cycles(0),
+ m_vz300_mode(false)
+{
+}
+
+//-------------------------------------------------
+// device_start - device-specific startup
+//-------------------------------------------------
+
+void vtech_sdloader_device::device_start()
+{
+ vtech_memexp_device::device_start();
+
+ // init ram
+ m_ram = std::make_unique<uint8_t[]>(0x20000);
+
+ // configure banks
+ m_dosbank->configure_entry(0, m_ram.get() + 0x00000);
+ m_dosbank->configure_entry(1, m_ram.get() + 0x08000);
+ m_expbank->configure_entry(0, m_ram.get() + 0x10000);
+ m_expbank->configure_entry(1, m_ram.get() + 0x18000);
+
+ // allocate timer for sdcard
+ m_spi_clock = timer_alloc(FUNC(vtech_sdloader_device::spi_clock), this);
+
+ // register for savestates
+ save_item(NAME(m_spi_clock_state));
+ save_item(NAME(m_spi_clock_sysclk));
+ save_item(NAME(m_spi_clock_cycles));
+ save_item(NAME(m_in_bit));
+ save_item(NAME(m_in_latch));
+ save_item(NAME(m_out_latch));
+ save_item(NAME(m_vz300_mode));
+ save_pointer(NAME(m_ram), 0x20000);
+}
+
+//-------------------------------------------------
+// device_reset - device-specific startup
+//-------------------------------------------------
+
+void vtech_sdloader_device::device_reset()
+{
+ // startup in vz200 mode
+ m_vz300_mode = false;
+
+ // rom enabled
+ m_dosview.select(0);
+
+ m_spi_clock->adjust(attotime::never);
+ m_spi_clock_cycles = 0;
+ m_spi_clock_state = false;
+}
+
+
+//**************************************************************************
+// IMPLEMENTATION
+//**************************************************************************
+
+TIMER_CALLBACK_MEMBER(vtech_sdloader_device::spi_clock)
+{
+ if (m_spi_clock_cycles > 0)
+ {
+ if (m_spi_clock_state)
+ {
+ m_in_latch <<= 1;
+ m_in_latch &= ~0x01;
+ m_in_latch |= m_in_bit;
+
+ m_sdcard->spi_clock_w(1);
+
+ m_spi_clock_cycles--;
+ }
+ else
+ {
+ if (m_spi_clock_cycles == 8)
+ LOGMASKED(LOG_SPI, "SPI transfer start\n");
+
+ m_sdcard->spi_mosi_w(BIT(m_out_latch, 7));
+ m_sdcard->spi_clock_w(0);
+
+ m_out_latch <<= 1;
+ }
+
+ m_spi_clock_state = !m_spi_clock_state;
+ }
+ else
+ {
+ LOGMASKED(LOG_SPI, "SPI transfer done\n");
+ m_spi_clock_state = false;
+ m_spi_clock->adjust(attotime::never);
+ }
+}
+
+void vtech_sdloader_device::spi_miso_w(int state)
+{
+ LOGMASKED(LOG_SPI, "spi_miso_w: %d\n", state);
+
+ m_in_bit = state;
+}
+
+void vtech_sdloader_device::mapper_w(uint8_t data)
+{
+ // 7654---- not used
+ // ----3--- led
+ // -----2-- expansion ram bank
+ // ------1- dos ram bank
+ // -------0 dos rom/ram switch
+
+ m_dosview.select(BIT(data, 0));
+ m_dosbank->set_entry(BIT(data, 1));
+ m_expbank->set_entry(BIT(data, 2));
+}
+
+void vtech_sdloader_device::sdcfg_w(uint8_t data)
+{
+ // 765432-- not used
+ // ------1- sd card cs
+ // -------0 clock speed
+
+ LOGMASKED(LOG_SPI, "sdcfg_w: %02x\n", data);
+
+ m_sdcard->spi_ss_w(BIT(data, 1));
+ m_spi_clock_sysclk = bool(BIT(data, 0));
+
+ m_spi_clock_state = false;
+ m_spi_clock->adjust(attotime::never);
+}
+
+uint8_t vtech_sdloader_device::sdio_r()
+{
+ LOGMASKED(LOG_SPI, "sdio_r: %02x\n", m_in_latch);
+
+ return m_in_latch;
+}
+
+void vtech_sdloader_device::sdio_w(uint8_t data)
+{
+ LOGMASKED(LOG_SPI, "sdio_w: %02x\n", data);
+
+ m_out_latch = data;
+ m_spi_clock_cycles = 8;
+
+ // TODO: too fast, also slightly different on vz200
+ // code only waits for a single NOP before sending the next byte
+ if (m_spi_clock_sysclk)
+ m_spi_clock->adjust(attotime::from_hz(17.734470_MHz_XTAL / 1.5), 0, attotime::from_hz(17.734470_MHz_XTAL / 1.5));
+ else
+ m_spi_clock->adjust(attotime::from_hz(100_kHz_XTAL), 0, attotime::from_hz(100_kHz_XTAL));
+}
+
+void vtech_sdloader_device::mode_w(uint8_t data)
+{
+ LOG("Switching to %s mode\n", BIT(data, 0) ? "VZ-300" : "VZ-200");
+ m_vz300_mode = bool(BIT(data, 0));
+}
+
+uint8_t vtech_sdloader_device::exp_ram_r(offs_t offset)
+{
+ offset += 0x9000;
+
+ if (!m_vz300_mode || (m_vz300_mode && offset >= 0xb800))
+ return reinterpret_cast<uint8_t *>(m_expbank->base())[offset & 0x7fff];
+
+ return 0xff;
+}
+
+void vtech_sdloader_device::exp_ram_w(offs_t offset, uint8_t data)
+{
+ offset += 0x9000;
+
+ if (!m_vz300_mode || (m_vz300_mode && offset >= 0xb800))
+ reinterpret_cast<uint8_t *>(m_expbank->base())[offset & 0x7fff] = data;
+}
+
+} // anonymous namespace
+
+
+//**************************************************************************
+// DEVICE DEFINITIONS
+//**************************************************************************
+
+DEFINE_DEVICE_TYPE_PRIVATE(VTECH_SDLOADER, vtech_memexp_device, vtech_sdloader_device, "vtech_sdloader", "BennVenn SD Loader")
diff --git a/src/devices/bus/vtech/memexp/sdloader.h b/src/devices/bus/vtech/memexp/sdloader.h
new file mode 100644
index 00000000000..dd16368d568
--- /dev/null
+++ b/src/devices/bus/vtech/memexp/sdloader.h
@@ -0,0 +1,19 @@
+// license: GPL-2.0+
+// copyright-holders: Dirk Best
+/***************************************************************************
+
+ BennVenn SD Loader for VZ300
+
+***************************************************************************/
+
+#ifndef MAME_BUS_VTECH_MEMEXP_SDLOADER_H
+#define MAME_BUS_VTECH_MEMEXP_SDLOADER_H
+
+#pragma once
+
+#include "memexp.h"
+
+
+DECLARE_DEVICE_TYPE(VTECH_SDLOADER, vtech_memexp_device)
+
+#endif // MAME_BUS_VTECH_MEMEXP_SDLOADER_H
diff --git a/src/devices/bus/vtech/memexp/wordpro.cpp b/src/devices/bus/vtech/memexp/wordpro.cpp
index 099702ef844..811cb953a83 100644
--- a/src/devices/bus/vtech/memexp/wordpro.cpp
+++ b/src/devices/bus/vtech/memexp/wordpro.cpp
@@ -17,6 +17,17 @@
DEFINE_DEVICE_TYPE(VTECH_WORDPRO, vtech_wordpro_device, "vtech_wordpro", "DSE VZ-300 WordPro")
//-------------------------------------------------
+// mem_map - memory space address map
+//-------------------------------------------------
+
+void vtech_wordpro_device::mem_map(address_map &map)
+{
+ map.unmap_value_high();
+ map(0x6000, 0x67ff).rom().region("software", 0);
+ map(0xd000, 0xffff).rom().region("software", 0);
+}
+
+//-------------------------------------------------
// rom_region - device-specific ROM region
//-------------------------------------------------
@@ -42,8 +53,7 @@ const tiny_rom_entry *vtech_wordpro_device::device_rom_region() const
//-------------------------------------------------
vtech_wordpro_device::vtech_wordpro_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) :
- device_t(mconfig, VTECH_WORDPRO, tag, owner, clock),
- device_vtech_memexp_interface(mconfig, *this)
+ vtech_memexp_device(mconfig, VTECH_WORDPRO, tag, owner, clock)
{
}
@@ -53,14 +63,5 @@ vtech_wordpro_device::vtech_wordpro_device(const machine_config &mconfig, const
void vtech_wordpro_device::device_start()
{
-}
-
-//-------------------------------------------------
-// device_reset - device-specific reset
-//-------------------------------------------------
-
-void vtech_wordpro_device::device_reset()
-{
- program_space().install_rom(0x6000, 0x67ff, memregion("software")->base());
- program_space().install_rom(0xd000, 0xffff, memregion("software")->base());
+ vtech_memexp_device::device_start();
}
diff --git a/src/devices/bus/vtech/memexp/wordpro.h b/src/devices/bus/vtech/memexp/wordpro.h
index f7b6422a319..11cd0b53917 100644
--- a/src/devices/bus/vtech/memexp/wordpro.h
+++ b/src/devices/bus/vtech/memexp/wordpro.h
@@ -20,16 +20,17 @@
// ======================> vtech_wordpro_device
-class vtech_wordpro_device : public device_t, public device_vtech_memexp_interface
+class vtech_wordpro_device : public vtech_memexp_device
{
public:
// construction/destruction
vtech_wordpro_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;
- virtual void device_start() override;
- virtual void device_reset() override;
+ virtual const tiny_rom_entry *device_rom_region() const override ATTR_COLD;
+ virtual void device_start() override ATTR_COLD;
+
+ virtual void mem_map(address_map &map) override ATTR_COLD;
};
// device type definition
diff --git a/src/devices/bus/wangpc/emb.cpp b/src/devices/bus/wangpc/emb.cpp
index 8a1817d1666..6a69c1a0fee 100644
--- a/src/devices/bus/wangpc/emb.cpp
+++ b/src/devices/bus/wangpc/emb.cpp
@@ -47,7 +47,7 @@ DEFINE_DEVICE_TYPE(WANGPC_EMB, wangpc_emb_device, "wangpc_emb", "Wang PC-PM031-B
wangpc_emb_device::wangpc_emb_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) :
device_t(mconfig, WANGPC_EMB, tag, owner, clock),
device_wangpcbus_card_interface(mconfig, *this),
- m_ram(*this, "ram"),
+ m_ram(*this, "ram", RAM_SIZE, ENDIANNESS_LITTLE),
m_option(0), m_parity_error(0), m_parity_odd(0)
{
}
@@ -59,9 +59,6 @@ wangpc_emb_device::wangpc_emb_device(const machine_config &mconfig, const char *
void wangpc_emb_device::device_start()
{
- // allocate memory
- m_ram.allocate(RAM_SIZE);
-
// state saving
save_item(NAME(m_option));
save_item(NAME(m_parity_error));
diff --git a/src/devices/bus/wangpc/emb.h b/src/devices/bus/wangpc/emb.h
index 1e175ae6867..de137305f44 100644
--- a/src/devices/bus/wangpc/emb.h
+++ b/src/devices/bus/wangpc/emb.h
@@ -30,8 +30,8 @@ public:
protected:
// device-level overrides
- virtual void device_start() override;
- virtual void device_reset() override;
+ virtual void device_start() override ATTR_COLD;
+ virtual void device_reset() override ATTR_COLD;
// device_wangpcbus_card_interface overrides
virtual uint16_t wangpcbus_mrdc_r(offs_t offset, uint16_t mem_mask) override;
@@ -40,7 +40,7 @@ protected:
virtual void wangpcbus_aiowc_w(offs_t offset, uint16_t mem_mask, uint16_t data) override;
private:
- optional_shared_ptr<uint16_t> m_ram;
+ memory_share_creator<uint16_t> m_ram;
uint16_t m_option;
int m_parity_error;
int m_parity_odd;
diff --git a/src/devices/bus/wangpc/lic.h b/src/devices/bus/wangpc/lic.h
index 8ead2c65f0a..a93cfe308fb 100644
--- a/src/devices/bus/wangpc/lic.h
+++ b/src/devices/bus/wangpc/lic.h
@@ -30,10 +30,10 @@ public:
protected:
// device-level overrides
- 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;
+ virtual void device_start() override ATTR_COLD;
+ virtual void device_reset() override ATTR_COLD;
+ virtual const tiny_rom_entry *device_rom_region() const override ATTR_COLD;
+ virtual void device_add_mconfig(machine_config &config) override ATTR_COLD;
// device_wangpcbus_card_interface overrides
virtual uint16_t wangpcbus_mrdc_r(offs_t offset, uint16_t mem_mask) override;
diff --git a/src/devices/bus/wangpc/lvc.cpp b/src/devices/bus/wangpc/lvc.cpp
index 9f6a8d59626..66b86493051 100644
--- a/src/devices/bus/wangpc/lvc.cpp
+++ b/src/devices/bus/wangpc/lvc.cpp
@@ -62,17 +62,17 @@ MC6845_UPDATE_ROW( wangpc_lvc_device::crtc_update_row )
{
for (int column = 0; column < x_count; column++)
{
- offs_t addr = scroll_y + (m_scroll & 0x3f) + ((ma / 80) * 0x480) + (((ra & 0x0f) << 7) | (column & 0x7f));
+ offs_t const addr = scroll_y + (m_scroll & 0x3f) + ((ma / 80) * 0x480) + (((ra & 0x0f) << 7) | (column & 0x7f));
uint16_t data = m_video_ram[addr & 0x7fff];
for (int bit = 0; bit < 8; bit++)
{
- int x = (column * 8) + bit;
+ int const x = (column * 8) + bit;
int color = (BIT(data, 15) << 1) | BIT(data, 7);
if (column == cursor_x) color = 0x03;
- bitmap.pix32(vbp + y, hbp + x) = de ? m_palette[color] : rgb_t::black();
+ bitmap.pix(vbp + y, hbp + x) = de ? m_palette[color] : rgb_t::black();
data <<= 1;
}
@@ -89,12 +89,12 @@ MC6845_UPDATE_ROW( wangpc_lvc_device::crtc_update_row )
for (int bit = 0; bit < 8; bit++)
{
- int x = (column * 8) + bit;
+ int const x = (column * 8) + bit;
int color = (BIT(data, 31) << 3) | (BIT(data, 23) << 2) | (BIT(data, 15) << 1) | BIT(data, 7);
if (column == cursor_x) color = 0x03;
- bitmap.pix32(vbp + y, hbp + x) = de ? m_palette[color] : rgb_t::black();
+ bitmap.pix(vbp + y, hbp + x) = de ? m_palette[color] : rgb_t::black();
data <<= 1;
}
@@ -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)
{
@@ -129,7 +129,7 @@ void wangpc_lvc_device::device_add_mconfig(machine_config &config)
m_crtc->set_screen(SCREEN_TAG);
m_crtc->set_show_border_area(true);
m_crtc->set_char_width(8);
- m_crtc->set_update_row_callback(FUNC(wangpc_lvc_device::crtc_update_row), this);
+ m_crtc->set_update_row_callback(FUNC(wangpc_lvc_device::crtc_update_row));
m_crtc->out_vsync_callback().set(FUNC(wangpc_lvc_device::vsync_w));
}
@@ -164,7 +164,7 @@ wangpc_lvc_device::wangpc_lvc_device(const machine_config &mconfig, const char *
device_t(mconfig, WANGPC_LVC, tag, owner, clock),
device_wangpcbus_card_interface(mconfig, *this),
m_crtc(*this, MC6845_TAG),
- m_video_ram(*this, "video_ram"),
+ m_video_ram(*this, "video_ram", RAM_SIZE, ENDIANNESS_LITTLE),
m_option(0), m_scroll(0),
m_irq(CLEAR_LINE)
{
@@ -177,9 +177,6 @@ wangpc_lvc_device::wangpc_lvc_device(const machine_config &mconfig, const char *
void wangpc_lvc_device::device_start()
{
- // allocate memory
- m_video_ram.allocate(RAM_SIZE);
-
// state saving
save_item(NAME(m_option));
save_item(NAME(m_scroll));
diff --git a/src/devices/bus/wangpc/lvc.h b/src/devices/bus/wangpc/lvc.h
index 3fa858adf1c..9e954497bab 100644
--- a/src/devices/bus/wangpc/lvc.h
+++ b/src/devices/bus/wangpc/lvc.h
@@ -31,9 +31,9 @@ public:
protected:
// device-level overrides
- virtual void device_start() override;
- virtual void device_reset() override;
- virtual void device_add_mconfig(machine_config &config) override;
+ 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_wangpcbus_card_interface overrides
virtual uint16_t wangpcbus_mrdc_r(offs_t offset, uint16_t mem_mask) override;
@@ -43,12 +43,12 @@ 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);
required_device<mc6845_device> m_crtc;
- optional_shared_ptr<uint16_t> m_video_ram;
+ memory_share_creator<uint16_t> m_video_ram;
rgb_t m_palette[16];
uint8_t m_option;
diff --git a/src/devices/bus/wangpc/mcc.cpp b/src/devices/bus/wangpc/mcc.cpp
index a3419f7c373..7eb56eb479e 100644
--- a/src/devices/bus/wangpc/mcc.cpp
+++ b/src/devices/bus/wangpc/mcc.cpp
@@ -57,7 +57,7 @@ DEFINE_DEVICE_TYPE(WANGPC_MCC, wangpc_mcc_device, "wangpc_mcc", "Wang PC-PM043 M
void wangpc_mcc_device::device_add_mconfig(machine_config &config)
{
- Z80SIO2(config, m_sio, 4000000);
+ Z80SIO(config, m_sio, 4000000); // SIO/2?
Z80DART(config, m_dart, 4000000);
}
diff --git a/src/devices/bus/wangpc/mcc.h b/src/devices/bus/wangpc/mcc.h
index 58b8931f5fa..848969f584f 100644
--- a/src/devices/bus/wangpc/mcc.h
+++ b/src/devices/bus/wangpc/mcc.h
@@ -12,7 +12,7 @@
#pragma once
#include "wangpc.h"
-#include "machine/z80dart.h"
+#include "machine/z80sio.h"
@@ -31,9 +31,9 @@ public:
protected:
// device-level overrides
- virtual void device_start() override;
- virtual void device_reset() override;
- virtual void device_add_mconfig(machine_config &config) override;
+ 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_wangpcbus_card_interface overrides
virtual uint16_t wangpcbus_iorc_r(offs_t offset, uint16_t mem_mask) override;
@@ -42,7 +42,7 @@ protected:
private:
inline void set_irq(int state);
- required_device<z80dart_device> m_sio;
+ required_device<z80sio_device> m_sio;
required_device<z80dart_device> m_dart;
uint8_t m_option;
diff --git a/src/devices/bus/wangpc/mvc.cpp b/src/devices/bus/wangpc/mvc.cpp
index af78d16cc29..65985890f82 100644
--- a/src/devices/bus/wangpc/mvc.cpp
+++ b/src/devices/bus/wangpc/mvc.cpp
@@ -73,15 +73,15 @@ MC6845_UPDATE_ROW( wangpc_mvc_device::crtc_update_row )
{
for (int sx = 0; sx < 50; sx++)
{
- offs_t addr = (y * 50) + sx;
+ offs_t const addr = (y * 50) + sx;
uint16_t data = m_bitmap_ram[addr];
for (int bit = 0; bit < 16; bit++)
{
- int x = (sx * 16) + bit;
- int color = BIT(data, 15) && de;
+ int const x = (sx * 16) + bit;
+ int const color = BIT(data, 15) && de;
- bitmap.pix32(vbp + y, hbp + x) = PALETTE_MVC[color];
+ bitmap.pix(vbp + y, hbp + x) = PALETTE_MVC[color];
data <<= 1;
}
@@ -89,8 +89,8 @@ MC6845_UPDATE_ROW( wangpc_mvc_device::crtc_update_row )
for (int column = 0; column < x_count; column++)
{
- uint16_t code = m_video_ram[((ma + column) & 0x7ff)];
- uint8_t attr = code & 0xff;
+ uint16_t const code = m_video_ram[((ma + column) & 0x7ff)];
+ uint8_t const attr = code & 0xff;
uint8_t new_ra = ra + 1;
@@ -103,7 +103,7 @@ MC6845_UPDATE_ROW( wangpc_mvc_device::crtc_update_row )
new_ra = ra;
}
- offs_t addr = ((code >> 8) << 4) | (new_ra & 0x0f);
+ offs_t const addr = ((code >> 8) << 4) | (new_ra & 0x0f);
uint16_t data = m_char_ram[addr & 0xfff];
if ((column == cursor_x) || (!ra && ATTR_OVERSCORE) || ((ra == 9) && ATTR_UNDERSCORE))
@@ -113,18 +113,20 @@ MC6845_UPDATE_ROW( wangpc_mvc_device::crtc_update_row )
for (int bit = 0; bit < 10; bit++)
{
- int x = (column * 10) + bit;
+ int const x = (column * 10) + bit;
int color = ((BIT(data, 9) & ~ATTR_BLANK) ^ ATTR_REVERSE);
- if ((color | bitmap.pix32(vbp + y, hbp + x)) & ATTR_BOLD) color = 2;
- if (color) bitmap.pix32(vbp + y, hbp + x) = de ? PALETTE_MVC[color] : rgb_t::black();
+ if ((color | bitmap.pix(vbp + y, hbp + x)) & ATTR_BOLD)
+ color = 2;
+ if (color)
+ bitmap.pix(vbp + y, hbp + x) = de ? PALETTE_MVC[color] : rgb_t::black();
data <<= 1;
}
}
}
-WRITE_LINE_MEMBER( wangpc_mvc_device::vsync_w )
+void wangpc_mvc_device::vsync_w(int state)
{
if (OPTION_VSYNC && state)
{
@@ -149,7 +151,7 @@ void wangpc_mvc_device::device_add_mconfig(machine_config &config)
m_crtc->set_screen(SCREEN_TAG);
m_crtc->set_show_border_area(true);
m_crtc->set_char_width(10);
- m_crtc->set_update_row_callback(FUNC(wangpc_mvc_device::crtc_update_row), this);
+ m_crtc->set_update_row_callback(FUNC(wangpc_mvc_device::crtc_update_row));
m_crtc->out_vsync_callback().set(FUNC(wangpc_mvc_device::vsync_w));
}
@@ -184,9 +186,9 @@ wangpc_mvc_device::wangpc_mvc_device(const machine_config &mconfig, const char *
device_t(mconfig, WANGPC_MVC, tag, owner, clock),
device_wangpcbus_card_interface(mconfig, *this),
m_crtc(*this, MC6845_TAG),
- m_video_ram(*this, "video_ram"),
- m_char_ram(*this, "char_ram"),
- m_bitmap_ram(*this, "bitmap_ram"),
+ m_video_ram(*this, "video_ram", VIDEO_RAM_SIZE*2, ENDIANNESS_LITTLE),
+ m_char_ram(*this, "char_ram", CHAR_RAM_SIZE*2, ENDIANNESS_LITTLE),
+ m_bitmap_ram(*this, "bitmap_ram", BITMAP_RAM_SIZE*2, ENDIANNESS_LITTLE),
m_option(0),
m_irq(CLEAR_LINE)
{
@@ -199,11 +201,6 @@ wangpc_mvc_device::wangpc_mvc_device(const machine_config &mconfig, const char *
void wangpc_mvc_device::device_start()
{
- // allocate memory
- m_video_ram.allocate(VIDEO_RAM_SIZE);
- m_char_ram.allocate(CHAR_RAM_SIZE);
- m_bitmap_ram.allocate(BITMAP_RAM_SIZE);
-
// state saving
save_item(NAME(m_option));
save_item(NAME(m_irq));
diff --git a/src/devices/bus/wangpc/mvc.h b/src/devices/bus/wangpc/mvc.h
index aee0cdf51b2..30fa9e38454 100644
--- a/src/devices/bus/wangpc/mvc.h
+++ b/src/devices/bus/wangpc/mvc.h
@@ -31,9 +31,9 @@ public:
protected:
// device-level overrides
- virtual void device_start() override;
- virtual void device_reset() override;
- virtual void device_add_mconfig(machine_config &config) override;
+ 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_wangpcbus_card_interface overrides
virtual uint16_t wangpcbus_mrdc_r(offs_t offset, uint16_t mem_mask) override;
@@ -43,14 +43,14 @@ 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);
required_device<mc6845_device> m_crtc;
- optional_shared_ptr<uint16_t> m_video_ram;
- optional_shared_ptr<uint16_t> m_char_ram;
- optional_shared_ptr<uint16_t> m_bitmap_ram;
+ memory_share_creator<uint16_t> m_video_ram;
+ memory_share_creator<uint16_t> m_char_ram;
+ memory_share_creator<uint16_t> m_bitmap_ram;
uint8_t m_option;
int m_irq;
diff --git a/src/devices/bus/wangpc/rtc.cpp b/src/devices/bus/wangpc/rtc.cpp
index 4512939003f..708c15ecc67 100644
--- a/src/devices/bus/wangpc/rtc.cpp
+++ b/src/devices/bus/wangpc/rtc.cpp
@@ -70,22 +70,22 @@ void wangpc_rtc_device::wangpc_rtc_mem(address_map &map)
void wangpc_rtc_device::wangpc_rtc_io(address_map &map)
{
map.global_mask(0xff);
- map(0x00, 0x03).rw(m_sio, FUNC(z80sio0_device::cd_ba_r), FUNC(z80sio0_device::cd_ba_w));
+ map(0x00, 0x03).rw(m_sio, FUNC(z80sio_device::cd_ba_r), FUNC(z80sio_device::cd_ba_w));
map(0x10, 0x1f).rw(AM9517A_TAG, FUNC(am9517a_device::read), FUNC(am9517a_device::write));
map(0x20, 0x23).rw(m_ctc0, FUNC(z80ctc_device::read), FUNC(z80ctc_device::write));
- map(0x30, 0x30); //AM_WRITE(clear_char_w)
- map(0x31, 0x31); //AM_WRITE(set_char_w)
- map(0x40, 0x40).portr("SW1"); //AM_WRITE(control_w)
- map(0x44, 0x44); //AM_READ(i8086_status_r) AM_WRITE(reset_w)
- map(0x48, 0x48); //AM_WRITE(dte_ready_w)
- map(0x4c, 0x4c); //AM_READWRITE(8232_acu_r, 8232_acu_w)
- map(0x50, 0x50); //AM_READ(outbound_data_r)
- map(0x51, 0x52); //AM_WRITE(status_w)
- map(0x54, 0x54); //AM_WRITE(enable_inbound_data_w)
- map(0x51, 0x52); //AM_WRITE(inbound_data_w)
+ map(0x30, 0x30); //.w(FUNC(wangpc_rtc_device::clear_char_w));
+ map(0x31, 0x31); //.w(FUNC(wangpc_rtc_device::set_char_w));
+ map(0x40, 0x40).portr(m_sw1); //.w(FUNC(wangpc_rtc_device::control_w));
+ map(0x44, 0x44); //.rw(FUNC(wangpc_rtc_device::i8086_status_r), FUNC(wangpc_rtc_device::reset_w));
+ map(0x48, 0x48); //.w(FUNC(wangpc_rtc_device::dte_ready_w));
+ map(0x4c, 0x4c); //.rw(FUNC(wangpc_rtc_device::8232_acu_r), FUNC(wangpc_rtc_device::8232_acu_w));
+ map(0x50, 0x50); //.r(FUNC(wangpc_rtc_device::outbound_data_r));
+ map(0x51, 0x52); //.w(FUNC(wangpc_rtc_device::status_w));
+ map(0x54, 0x54); //.w(FUNC(wangpc_rtc_device::enable_inbound_data_w));
+ map(0x51, 0x52); //.w(FUNC(wangpc_rtc_device::inbound_data_w));
map(0x60, 0x63).rw(m_ctc1, FUNC(z80ctc_device::read), FUNC(z80ctc_device::write));
- map(0x70, 0x70); //AM_READWRITE(led_toggle_r, odd_parity_w)
- map(0x71, 0x71); //AM_WRITE(even_parity_w)
+ map(0x70, 0x70); //.rw(FUNC(wangpc_rtc_device::led_toggle_r), FUNC(wangpc_rtc_device::odd_parity_w));
+ map(0x71, 0x71); //.w(FUNC(wangpc_rtc_device::even_parity_w));
}
@@ -120,7 +120,7 @@ void wangpc_rtc_device::device_add_mconfig(machine_config &config)
Z80CTC(config, m_ctc1, 2000000);
m_ctc1->intr_callback().set_inputline(m_maincpu, INPUT_LINE_IRQ0);
- Z80SIO0(config, m_sio, 2000000);
+ Z80SIO(config, m_sio, 2000000); // SIO/0?
m_sio->out_int_callback().set_inputline(m_maincpu, INPUT_LINE_IRQ0);
}
@@ -186,7 +186,8 @@ wangpc_rtc_device::wangpc_rtc_device(const machine_config &mconfig, const char *
m_ctc0(*this, Z80CTC_0_TAG),
m_ctc1(*this, Z80CTC_1_TAG),
m_sio(*this, Z80SIO_TAG),
- m_char_ram(*this, "char_ram")
+ m_char_ram(*this, "char_ram", 0x100, ENDIANNESS_LITTLE),
+ m_sw1(*this, "SW1")
{
}
@@ -197,7 +198,6 @@ wangpc_rtc_device::wangpc_rtc_device(const machine_config &mconfig, const char *
void wangpc_rtc_device::device_start()
{
- m_char_ram.allocate(0x100);
}
diff --git a/src/devices/bus/wangpc/rtc.h b/src/devices/bus/wangpc/rtc.h
index 9233222a4f9..42d7179d24e 100644
--- a/src/devices/bus/wangpc/rtc.h
+++ b/src/devices/bus/wangpc/rtc.h
@@ -15,7 +15,7 @@
#include "cpu/z80/z80.h"
#include "machine/am9517a.h"
#include "machine/z80ctc.h"
-#include "machine/z80dart.h"
+#include "machine/z80sio.h"
@@ -34,11 +34,11 @@ public:
protected:
// device-level overrides
- 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;
- virtual ioport_constructor device_input_ports() const override;
+ virtual void device_start() override ATTR_COLD;
+ virtual void device_reset() override ATTR_COLD;
+ virtual const tiny_rom_entry *device_rom_region() const override ATTR_COLD;
+ virtual void device_add_mconfig(machine_config &config) override ATTR_COLD;
+ virtual ioport_constructor device_input_ports() const override ATTR_COLD;
// device_wangpcbus_card_interface overrides
virtual uint16_t wangpcbus_mrdc_r(offs_t offset, uint16_t mem_mask) override;
@@ -51,11 +51,12 @@ private:
required_device<am9517a_device> m_dmac;
required_device<z80ctc_device> m_ctc0;
required_device<z80ctc_device> m_ctc1;
- required_device<z80dart_device> m_sio;
- optional_shared_ptr<uint8_t> m_char_ram;
+ required_device<z80sio_device> m_sio;
+ memory_share_creator<uint8_t> m_char_ram;
+ required_ioport m_sw1;
- void wangpc_rtc_io(address_map &map);
- void wangpc_rtc_mem(address_map &map);
+ void wangpc_rtc_io(address_map &map) ATTR_COLD;
+ void wangpc_rtc_mem(address_map &map) ATTR_COLD;
};
diff --git a/src/devices/bus/wangpc/tig.h b/src/devices/bus/wangpc/tig.h
index 0e95eb42676..70b1a4e83de 100644
--- a/src/devices/bus/wangpc/tig.h
+++ b/src/devices/bus/wangpc/tig.h
@@ -32,10 +32,10 @@ public:
protected:
// device-level overrides
- 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;
+ virtual void device_start() override ATTR_COLD;
+ virtual void device_reset() override ATTR_COLD;
+ virtual const tiny_rom_entry *device_rom_region() const override ATTR_COLD;
+ virtual void device_add_mconfig(machine_config &config) override ATTR_COLD;
// device_wangpcbus_card_interface overrides
virtual uint16_t wangpcbus_iorc_r(offs_t offset, uint16_t mem_mask) override;
@@ -50,8 +50,8 @@ private:
UPD7220_DRAW_TEXT_LINE_MEMBER( hgdc_draw_text );
UPD7220_DISPLAY_PIXELS_MEMBER( hgdc_display_pixels );
- void upd7220_0_map(address_map &map);
- void upd7220_1_map(address_map &map);
+ void upd7220_0_map(address_map &map) ATTR_COLD;
+ void upd7220_1_map(address_map &map) ATTR_COLD;
// internal state
required_device<upd7220_device> m_hgdc0;
diff --git a/src/devices/bus/wangpc/wangpc.cpp b/src/devices/bus/wangpc/wangpc.cpp
index 540ed94c1b3..c03f84d9372 100644
--- a/src/devices/bus/wangpc/wangpc.cpp
+++ b/src/devices/bus/wangpc/wangpc.cpp
@@ -29,8 +29,8 @@ DEFINE_DEVICE_TYPE(WANGPC_BUS_SLOT, wangpcbus_slot_device, "wangpcbus_slot", "Wa
wangpcbus_slot_device::wangpcbus_slot_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) :
device_t(mconfig, WANGPC_BUS_SLOT, tag, owner, clock),
- device_slot_interface(mconfig, *this),
- m_bus(nullptr),
+ device_single_card_slot_interface<device_wangpcbus_card_interface>(mconfig, *this),
+ m_bus(*this, finder_base::DUMMY_TAG),
m_sid(0)
{
}
@@ -41,9 +41,9 @@ wangpcbus_slot_device::wangpcbus_slot_device(const machine_config &mconfig, cons
void wangpcbus_slot_device::device_start()
{
- m_bus = machine().device<wangpcbus_device>(WANGPC_BUS_TAG);
- device_wangpcbus_card_interface *dev = dynamic_cast<device_wangpcbus_card_interface *>(get_card_device());
- if (dev) m_bus->add_card(dev, m_sid);
+ 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();
}
@@ -91,12 +84,12 @@ void wangpcbus_device::device_start()
// add_card - add card
//-------------------------------------------------
-void wangpcbus_device::add_card(device_wangpcbus_card_interface *card, int sid)
+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;
+ 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,18 @@ WRITE_LINE_MEMBER( wangpcbus_device::tc_w )
//-------------------------------------------------
device_wangpcbus_card_interface::device_wangpcbus_card_interface(const machine_config &mconfig, device_t &device) :
- device_slot_card_interface(mconfig, device), 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)
+{
+}
+
+
+void device_wangpcbus_card_interface::interface_pre_start()
{
- m_slot = dynamic_cast<wangpcbus_slot_device *>(device.owner());
+ if (!m_bus)
+ throw device_missing_dependencies();
}
diff --git a/src/devices/bus/wangpc/wangpc.h b/src/devices/bus/wangpc/wangpc.h
index bb8c7a3c4ac..4c9e4cc69a8 100644
--- a/src/devices/bus/wangpc/wangpc.h
+++ b/src/devices/bus/wangpc/wangpc.h
@@ -14,50 +14,49 @@
#pragma once
+#include <functional>
+#include <vector>
//**************************************************************************
-// CONSTANTS
+// TYPE DEFINITIONS
//**************************************************************************
-#define WANGPC_BUS_TAG "wangpcbus"
+class device_wangpcbus_card_interface;
+class wangpcbus_device;
-//**************************************************************************
-// TYPE DEFINITIONS
-//**************************************************************************
-
// ======================> wangpcbus_slot_device
-class wangpcbus_device;
-
-class wangpcbus_slot_device : public device_t, public device_slot_interface
+class wangpcbus_slot_device : public device_t, public device_single_card_slot_interface<device_wangpcbus_card_interface>
{
public:
// construction/destruction
- template <typename T>
- wangpcbus_slot_device(machine_config const &mconfig, char const *tag, device_t *owner, T &&opts, char const *dflt, int sid)
+ template <typename T, typename U>
+ wangpcbus_slot_device(machine_config const &mconfig, char const *tag, device_t *owner, T &&bus, U &&opts, char const *dflt, int sid)
: wangpcbus_slot_device(mconfig, tag, owner, 0)
{
option_reset();
opts(*this);
set_default_option(dflt);
set_fixed(false);
- set_wangpcbus_slot(sid);
+ set_bus(std::forward<T>(bus));
+ set_bus_slot(sid);
}
wangpcbus_slot_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock = 0);
// inline configuration
- void set_wangpcbus_slot(int sid) { m_sid = sid; }
+ template <typename T> void set_bus(T &&tag) { m_bus.set_tag(std::forward<T>(tag)); }
+ void set_bus_slot(int sid) { m_sid = sid; }
protected:
- // device-level overrides
- virtual void device_start() override;
+ // device_t implementation
+ virtual void device_start() override ATTR_COLD;
private:
// configuration
- wangpcbus_device *m_bus;
+ required_device<wangpcbus_device> m_bus;
int m_sid;
};
@@ -66,9 +65,6 @@ private:
DECLARE_DEVICE_TYPE(WANGPC_BUS_SLOT, wangpcbus_slot_device)
-class device_wangpcbus_card_interface;
-
-
// ======================> wangpcbus_device
class wangpcbus_device : public device_t
@@ -76,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(); }
@@ -89,7 +85,7 @@ public:
auto drq3_wr_callback() { return m_write_drq3.bind(); }
auto ioerror_wr_callback() { return m_write_ioerror.bind(); }
- void add_card(device_wangpcbus_card_interface *card, int sid);
+ void add_card(device_wangpcbus_card_interface &card, int sid);
// computer interface
uint16_t mrdc_r(offs_t offset, uint16_t mem_mask = 0xffff);
@@ -110,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
- virtual void device_start() override;
+ // devicedevice_t implementation
+ virtual void device_start() override ATTR_COLD;
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;
@@ -140,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;
};
@@ -151,14 +149,11 @@ DECLARE_DEVICE_TYPE(WANGPC_BUS, wangpcbus_device)
// ======================> device_wangpcbus_card_interface
// class representing interface-specific live wangpcbus card
-class device_wangpcbus_card_interface : public device_slot_card_interface
+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) { }
@@ -178,13 +173,12 @@ protected:
// construction/destruction
device_wangpcbus_card_interface(const machine_config &mconfig, device_t &device);
+ 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/wangpc/wdc.cpp b/src/devices/bus/wangpc/wdc.cpp
index 8b816a50ece..ddb6d07163b 100644
--- a/src/devices/bus/wangpc/wdc.cpp
+++ b/src/devices/bus/wangpc/wdc.cpp
@@ -292,7 +292,7 @@ bool wangpc_wdc_device::wangpcbus_have_dack(int line)
// port_r -
//-------------------------------------------------
-READ8_MEMBER( wangpc_wdc_device::port_r )
+uint8_t wangpc_wdc_device::port_r()
{
/*
@@ -317,7 +317,7 @@ READ8_MEMBER( wangpc_wdc_device::port_r )
// status_w - status register write
//-------------------------------------------------
-WRITE8_MEMBER( wangpc_wdc_device::status_w )
+void wangpc_wdc_device::status_w(uint8_t data)
{
logerror("WDC status %02x\n", data);
@@ -325,11 +325,11 @@ WRITE8_MEMBER( wangpc_wdc_device::status_w )
}
-READ8_MEMBER( wangpc_wdc_device::ctc_ch0_r ) { return m_ctc->read(0); }
-WRITE8_MEMBER( wangpc_wdc_device::ctc_ch0_w ) { m_ctc->write(0, data); }
-READ8_MEMBER( wangpc_wdc_device::ctc_ch1_r ) { return m_ctc->read(1); }
-WRITE8_MEMBER( wangpc_wdc_device::ctc_ch1_w ) { m_ctc->write(1, data); }
-READ8_MEMBER( wangpc_wdc_device::ctc_ch2_r ) { return m_ctc->read(2); }
-WRITE8_MEMBER( wangpc_wdc_device::ctc_ch2_w ) { m_ctc->write(2, data); }
-READ8_MEMBER( wangpc_wdc_device::ctc_ch3_r ) { return m_ctc->read(3); }
-WRITE8_MEMBER( wangpc_wdc_device::ctc_ch3_w ) { m_ctc->write(3, data); }
+uint8_t wangpc_wdc_device::ctc_ch0_r() { return m_ctc->read(0); }
+void wangpc_wdc_device::ctc_ch0_w(uint8_t data) { m_ctc->write(0, data); }
+uint8_t wangpc_wdc_device::ctc_ch1_r() { return m_ctc->read(1); }
+void wangpc_wdc_device::ctc_ch1_w(uint8_t data) { m_ctc->write(1, data); }
+uint8_t wangpc_wdc_device::ctc_ch2_r() { return m_ctc->read(2); }
+void wangpc_wdc_device::ctc_ch2_w(uint8_t data) { m_ctc->write(2, data); }
+uint8_t wangpc_wdc_device::ctc_ch3_r() { return m_ctc->read(3); }
+void wangpc_wdc_device::ctc_ch3_w(uint8_t data) { m_ctc->write(3, data); }
diff --git a/src/devices/bus/wangpc/wdc.h b/src/devices/bus/wangpc/wdc.h
index c945ba6707d..e654cc444b1 100644
--- a/src/devices/bus/wangpc/wdc.h
+++ b/src/devices/bus/wangpc/wdc.h
@@ -33,10 +33,10 @@ public:
protected:
// device-level overrides
- 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;
+ virtual void device_start() override ATTR_COLD;
+ virtual void device_reset() override ATTR_COLD;
+ virtual const tiny_rom_entry *device_rom_region() const override ATTR_COLD;
+ virtual void device_add_mconfig(machine_config &config) override ATTR_COLD;
// device_wangpcbus_card_interface overrides
virtual uint16_t wangpcbus_mrdc_r(offs_t offset, uint16_t mem_mask) override;
@@ -50,19 +50,19 @@ protected:
private:
inline void set_irq(int state);
- DECLARE_READ8_MEMBER( port_r );
- DECLARE_WRITE8_MEMBER( status_w );
- DECLARE_READ8_MEMBER( ctc_ch0_r );
- DECLARE_WRITE8_MEMBER( ctc_ch0_w );
- DECLARE_READ8_MEMBER( ctc_ch1_r );
- DECLARE_WRITE8_MEMBER( ctc_ch1_w );
- DECLARE_READ8_MEMBER( ctc_ch2_r );
- DECLARE_WRITE8_MEMBER( ctc_ch2_w );
- DECLARE_READ8_MEMBER( ctc_ch3_r );
- DECLARE_WRITE8_MEMBER( ctc_ch3_w );
-
- void wangpc_wdc_io(address_map &map);
- void wangpc_wdc_mem(address_map &map);
+ uint8_t port_r();
+ void status_w(uint8_t data);
+ uint8_t ctc_ch0_r();
+ void ctc_ch0_w(uint8_t data);
+ uint8_t ctc_ch1_r();
+ void ctc_ch1_w(uint8_t data);
+ uint8_t ctc_ch2_r();
+ void ctc_ch2_w(uint8_t data);
+ uint8_t ctc_ch3_r();
+ void ctc_ch3_w(uint8_t data);
+
+ void wangpc_wdc_io(address_map &map) ATTR_COLD;
+ void wangpc_wdc_mem(address_map &map) ATTR_COLD;
required_device<z80_device> m_maincpu;
required_device<z80ctc_device> m_ctc;
diff --git a/src/devices/bus/waveblaster/db50xg.cpp b/src/devices/bus/waveblaster/db50xg.cpp
new file mode 100644
index 00000000000..c105227dce5
--- /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 ATTR_COLD;
+ virtual void device_reset() override ATTR_COLD;
+ const tiny_rom_entry *device_rom_region() const override;
+ virtual void device_add_mconfig(machine_config &config) override ATTR_COLD;
+
+private:
+ required_device<h83002_device> m_cpu;
+ required_device<swp00_device> m_swp00;
+
+ void map(address_map &map) ATTR_COLD;
+};
+
+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, 0);
+ m_swp00->add_route(1, DEVICE_SELF_OWNER, 1.0, 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..c194d5d0e6e
--- /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 ATTR_COLD;
+ virtual void device_reset() override ATTR_COLD;
+ const tiny_rom_entry *device_rom_region() const override;
+ virtual void device_add_mconfig(machine_config &config) override ATTR_COLD;
+
+private:
+ required_device<h83002_device> m_cpu;
+ required_device<swp00_device> m_swp00;
+
+ void map(address_map &map) ATTR_COLD;
+};
+
+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, 0);
+ m_swp00->add_route(1, DEVICE_SELF_OWNER, 1.0, 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..a83399c28f9
--- /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 ATTR_COLD;
+ const tiny_rom_entry *device_rom_region() const override;
+ virtual void device_add_mconfig(machine_config &config) override ATTR_COLD;
+
+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, 0);
+ m_ks0164->add_route(1, DEVICE_SELF_OWNER, 1.0, 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..d947a265e63
--- /dev/null
+++ b/src/devices/bus/waveblaster/waveblaster.cpp
@@ -0,0 +1,55 @@
+// 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),
+ m_midi_tx(*this)
+{
+}
+
+void waveblaster_connector::device_start()
+{
+}
+
+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..bfc58e7b98a
--- /dev/null
+++ b/src/devices/bus/waveblaster/waveblaster.h
@@ -0,0 +1,59 @@
+// 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:
+ devcb_write_line m_midi_tx;
+
+ virtual void device_start() override ATTR_COLD;
+};
+
+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..8c44347c2b7
--- /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 ATTR_COLD;
+ const tiny_rom_entry *device_rom_region() const override;
+ virtual ioport_constructor device_input_ports() const override ATTR_COLD;
+ virtual void device_add_mconfig(machine_config &config) override ATTR_COLD;
+
+private:
+ required_device<gt913_device> m_gt913;
+
+ void map(address_map &map) ATTR_COLD;
+};
+
+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, 0);
+ m_gt913->add_route(1, DEVICE_SELF_OWNER, 1.0, 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/rom.cpp b/src/devices/bus/wswan/rom.cpp
index c4c991212b6..2d089989989 100644
--- a/src/devices/bus/wswan/rom.cpp
+++ b/src/devices/bus/wswan/rom.cpp
@@ -24,9 +24,10 @@ enum
DEFINE_DEVICE_TYPE(WS_ROM_STD, ws_rom_device, "ws_rom", "Wonderswan Standard Carts")
DEFINE_DEVICE_TYPE(WS_ROM_SRAM, ws_rom_sram_device, "ws_sram", "Wonderswan Carts w/SRAM")
DEFINE_DEVICE_TYPE(WS_ROM_EEPROM, ws_rom_eeprom_device, "ws_eeprom", "Wonderswan Carts w/EEPROM")
+DEFINE_DEVICE_TYPE(WS_ROM_WWITCH, ws_wwitch_device, "ws_wwitch", "WonderWitch")
-ws_rom_device::ws_rom_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock) :
+ws_rom_device::ws_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_ws_cart_interface(mconfig, *this),
m_base20(0),
@@ -45,25 +46,35 @@ ws_rom_device::ws_rom_device(const machine_config &mconfig, device_type type, co
{
}
-ws_rom_device::ws_rom_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) :
+ws_rom_device::ws_rom_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock) :
ws_rom_device(mconfig, WS_ROM_STD, tag, owner, clock)
{
}
-ws_rom_sram_device::ws_rom_sram_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) :
+ws_rom_sram_device::ws_rom_sram_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock) :
ws_rom_device(mconfig, WS_ROM_SRAM, tag, owner, clock),
m_nvram_base(0)
{
}
+ws_rom_sram_device::ws_rom_sram_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, u32 clock) :
+ ws_rom_device(mconfig, type, tag, owner, clock),
+ m_nvram_base(0)
+{
+}
-ws_rom_eeprom_device::ws_rom_eeprom_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) :
+ws_rom_eeprom_device::ws_rom_eeprom_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock) :
ws_rom_device(mconfig, WS_ROM_EEPROM, tag, owner, clock),
m_eeprom_mode(0), m_eeprom_address(0), m_eeprom_command(0), m_eeprom_start(0), m_eeprom_write_enabled(0)
{
}
+ws_wwitch_device::ws_wwitch_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock) :
+ ws_rom_sram_device(mconfig, WS_ROM_WWITCH, tag, owner, clock)
+{
+}
+
//-------------------------------------------------
// device_start - device-specific startup
//-------------------------------------------------
@@ -78,7 +89,7 @@ void ws_rom_device::device_start()
// Set up RTC timer
if (m_has_rtc)
{
- rtc_timer = timer_alloc(TIMER_RTC);
+ rtc_timer = timer_alloc(FUNC(ws_rom_device::rtc_tick), this);
rtc_timer->adjust(attotime::zero, 0, attotime::from_seconds(1));
}
@@ -91,15 +102,17 @@ void ws_rom_device::device_start()
save_item(NAME(m_rtc_minute));
save_item(NAME(m_rtc_second));
save_item(NAME(m_rtc_index));
+ save_item(NAME(m_rom_mask));
}
void ws_rom_device::device_reset()
{
- m_base20 = ((0xff & m_bank_mask) << 16) & (m_rom_size - 1);
- m_base30 = ((0xff & m_bank_mask) << 16) & (m_rom_size - 1);
- m_base40 = (((0xf0 & m_bank_mask) | 4) << 16) & (m_rom_size - 1);
+ m_rom_mask = (m_rom_size >> 1) - 1;
+ m_base20 = ((0xff & m_bank_mask) << 15) & m_rom_mask;
+ m_base30 = ((0xff & m_bank_mask) << 15) & m_rom_mask;
+ m_base40 = (((0xf0 & m_bank_mask) | 4) << 15) & m_rom_mask;
- memset(m_io_regs, 0, sizeof(m_io_regs));
+ memset(m_io_regs, 0xff, sizeof(m_io_regs));
// Initialize RTC
m_rtc_index = 0;
@@ -135,6 +148,30 @@ void ws_rom_eeprom_device::device_start()
save_item(NAME(m_eeprom_write_enabled));
}
+void ws_wwitch_device::device_start()
+{
+ save_item(NAME(m_flash_seq));
+ save_item(NAME(m_flash_command));
+ save_item(NAME(m_write_flash));
+ save_item(NAME(m_writing_flash));
+ save_item(NAME(m_write_resetting));
+ save_item(NAME(m_flash_mode));
+ save_item(NAME(m_flash_status));
+ ws_rom_sram_device::device_start();
+}
+
+void ws_wwitch_device::device_reset()
+{
+ m_flash_seq = 0;
+ m_flash_command = 0;
+ m_write_flash = false;
+ m_writing_flash = false;
+ m_write_resetting = false;
+ m_flash_mode = READ_MODE;
+ m_flash_status = 0;
+ ws_rom_sram_device::device_reset();
+}
+
void ws_rom_eeprom_device::device_reset()
{
m_eeprom_address = 0;
@@ -159,44 +196,41 @@ void ws_rom_eeprom_device::device_reset()
//-------------------------------------------------
-// device_timer - handler timer events
+// rtc_tick
//-------------------------------------------------
-void ws_rom_device::device_timer(emu_timer &timer, device_timer_id id, int param, void *ptr)
+TIMER_CALLBACK_MEMBER(ws_rom_device::rtc_tick)
{
- if (id == TIMER_RTC)
- {
- // a second passed
- m_rtc_second++;
- if ((m_rtc_second & 0x0f) > 9)
- m_rtc_second = (m_rtc_second & 0xf0) + 0x10;
+ // a second passed
+ m_rtc_second++;
+ if ((m_rtc_second & 0x0f) > 9)
+ m_rtc_second = (m_rtc_second & 0xf0) + 0x10;
- // check for minute passed
- if (m_rtc_second >= 0x60)
- {
- m_rtc_second = 0;
- m_rtc_minute++;
- if ((m_rtc_minute & 0x0f) > 9)
- m_rtc_minute = (m_rtc_minute & 0xf0) + 0x10;
- }
+ // check for minute passed
+ if (m_rtc_second >= 0x60)
+ {
+ m_rtc_second = 0;
+ m_rtc_minute++;
+ if ((m_rtc_minute & 0x0f) > 9)
+ m_rtc_minute = (m_rtc_minute & 0xf0) + 0x10;
+ }
- // check for hour passed
- if (m_rtc_minute >= 0x60)
- {
- m_rtc_minute = 0;
- m_rtc_hour++;
- if ((m_rtc_hour & 0x0f) > 9)
- m_rtc_hour = (m_rtc_hour & 0xf0) + 0x10;
- if (m_rtc_hour == 0x12)
- m_rtc_hour |= 0x80;
- }
+ // check for hour passed
+ if (m_rtc_minute >= 0x60)
+ {
+ m_rtc_minute = 0;
+ m_rtc_hour++;
+ if ((m_rtc_hour & 0x0f) > 9)
+ m_rtc_hour = (m_rtc_hour & 0xf0) + 0x10;
+ if (m_rtc_hour == 0x12)
+ m_rtc_hour |= 0x80;
+ }
- // check for day passed
- if (m_rtc_hour >= 0x24)
- {
- m_rtc_hour = 0;
- m_rtc_day++;
- }
+ // check for day passed
+ if (m_rtc_hour >= 0x24)
+ {
+ m_rtc_hour = 0;
+ m_rtc_day++;
}
}
@@ -205,48 +239,52 @@ void ws_rom_device::device_timer(emu_timer &timer, device_timer_id id, int param
mapper specific handlers
-------------------------------------------------*/
-uint8_t ws_rom_device::read_rom20(offs_t offset)
+u16 ws_rom_device::read_rom20(offs_t offset, u16 mem_mask)
{
return m_rom[offset + m_base20];
}
-uint8_t ws_rom_device::read_rom30(offs_t offset)
+u16 ws_rom_device::read_rom30(offs_t offset, u16 mem_mask)
{
return m_rom[offset + m_base30];
}
-uint8_t ws_rom_device::read_rom40(offs_t offset)
+u16 ws_rom_device::read_rom40(offs_t offset, u16 mem_mask)
{
// we still need to mask in some cases, e.g. when game is 512K
- return m_rom[(offset + m_base40) & (m_rom_size - 1)];
+ return m_rom[(offset + m_base40) & m_rom_mask];
}
-uint8_t ws_rom_device::read_io(offs_t offset)
+u16 ws_rom_device::read_io(offs_t offset, u16 mem_mask)
{
- uint8_t value = m_io_regs[offset];
+ u16 value = m_io_regs[offset];
switch (offset)
{
- case 0x0b: // RTC data
+ case 0x0a / 2:
if (!m_has_rtc)
break;
- if (m_io_regs[0x0a] == 0x95 && (m_rtc_index < 7))
+ // RTC data
+ if (ACCESSING_BITS_8_15)
{
- switch (m_rtc_index)
+ if ((m_io_regs[0x0a / 2] & 0xff) == 0x95 && (m_rtc_index < 7))
{
- case 0: value = m_rtc_year; break;
- case 1: value = m_rtc_month; break;
- case 2: value = m_rtc_day; break;
- case 3: value = m_rtc_day_of_week; break;
- case 4: value = m_rtc_hour; break;
- case 5: value = m_rtc_minute; break;
- case 6: value = m_rtc_second; break;
+ switch (m_rtc_index)
+ {
+ case 0: value = (value & 0xff) | (m_rtc_year << 8); break;
+ case 1: value = (value & 0xff) | (m_rtc_month << 8); break;
+ case 2: value = (value & 0xff) | (m_rtc_day << 8); break;
+ case 3: value = (value & 0xff) | (m_rtc_day_of_week << 8); break;
+ case 4: value = (value & 0xff) | (m_rtc_hour << 8); break;
+ case 5: value = (value & 0xff) | (m_rtc_minute << 8); break;
+ case 6: value = (value & 0xff) | (m_rtc_second << 8); break;
+ }
+ m_rtc_index++;
}
- m_rtc_index++;
}
break;
}
@@ -254,285 +292,452 @@ uint8_t ws_rom_device::read_io(offs_t offset)
return value;
}
-void ws_rom_device::write_io(offs_t offset, uint8_t data)
+void ws_rom_device::write_io(offs_t offset, u16 data, u16 mem_mask)
{
switch (offset)
{
- case 0x00:
- // Bit 0-3 - ROM bank base register for segments 3-15
+ case 0x00 / 2:
+ // Bit 0-3 - ROM bank base register for segments 4-15
// Bit 4-7 - Unknown
- data = ((data & 0x0f) << 4) | 4;
- m_base40 = ((data & m_bank_mask) << 16) & (m_rom_size - 1);
- break;
- case 0x02: // ROM bank for segment 2 (0x20000 - 0x2ffff)
- m_base20 = ((data & m_bank_mask) << 16) & (m_rom_size - 1);
- break;
- case 0x03: // ROM bank for segment 3 (0x30000 - 0x3ffff)
- m_base30 = ((data & m_bank_mask) << 16) & (m_rom_size - 1);
+ if (ACCESSING_BITS_0_7)
+ {
+ m_base40 = (((((data & 0x0f) << 4) | 4) & m_bank_mask) << 15) & m_rom_mask;
+ }
break;
- case 0x0a: // RTC Command
- // Bit 0-4 - RTC command
- // 10000 - Reset
- // 10010 - Write timer settings (alarm)
- // 10011 - Read timer settings (alarm)
- // 10100 - Set time/date
- // 10101 - Get time/date
- // Bit 5-6 - Unknown
- // Bit 7 - Command done (read only)
- if (!m_has_rtc)
- break;
-
- switch (data)
+ case 0x02 / 2:
+ // ROM bank for segment 2 (0x20000 - 0x2ffff)
+ if (ACCESSING_BITS_0_7)
{
- case 0x10: // Reset
- m_rtc_index = 8;
- m_rtc_year = 0;
- m_rtc_month = 1;
- m_rtc_day = 1;
- m_rtc_day_of_week = 0;
- m_rtc_hour = 0;
- m_rtc_minute = 0;
- m_rtc_second = 0;
- m_rtc_setting = 0xff;
- data |= 0x80;
- break;
- case 0x12: // Write Timer Settings (Alarm)
- m_rtc_index = 8;
- m_rtc_setting = m_io_regs[0x0b];
- data |= 0x80;
- break;
- case 0x13: // Read Timer Settings (Alarm)
- m_rtc_index = 8;
- m_io_regs[0x0b] = m_rtc_setting;
- data |= 0x80;
- break;
- case 0x14: // Set Time/Date
- m_rtc_year = m_io_regs[0x0b];
- m_rtc_index = 1;
- data |= 0x80;
- break;
- case 0x15: // Get Time/Date
- m_rtc_index = 0;
- data |= 0x80;
- m_io_regs[0x0b] = m_rtc_year;
- break;
- default:
- logerror( "Unknown RTC command (%X) requested\n", data);
+ m_base20 = (((data & 0xff) & m_bank_mask) << 15) & m_rom_mask;
+ }
+ // ROM bank for segment 3 (0x30000 - 0x3ffff)
+ if (ACCESSING_BITS_8_15)
+ {
+ m_base30 = (((data >> 8) & m_bank_mask) << 15) & m_rom_mask;
}
break;
- case 0x0b: // RTC Data
+ case 0x0a / 2:
if (!m_has_rtc)
break;
-
- if (m_io_regs[0x0a] == 0x94 && m_rtc_index < 7)
+ // RTC Command
+ // Bit 0-4 - RTC command
+ // 10000 - Reset
+ // 10010 - Write timer settings (alarm)
+ // 10011 - Read timer settings (alarm)
+ // 10100 - Set time/date
+ // 10101 - Get time/date
+ // Bit 5-6 - Unknown
+ // Bit 7 - Command done (read only)
+ if (ACCESSING_BITS_0_7)
+ {
+ switch (data & 0xff)
+ {
+ case 0x10: // Reset
+ m_rtc_index = 8;
+ m_rtc_year = 0;
+ m_rtc_month = 1;
+ m_rtc_day = 1;
+ m_rtc_day_of_week = 0;
+ m_rtc_hour = 0;
+ m_rtc_minute = 0;
+ m_rtc_second = 0;
+ m_rtc_setting = 0xff;
+ data |= 0x80;
+ break;
+ case 0x12: // Write Timer Settings (Alarm)
+ m_rtc_index = 8;
+ m_rtc_setting = m_io_regs[0x0a / 2] >> 8;
+ data |= 0x80;
+ break;
+ case 0x13: // Read Timer Settings (Alarm)
+ m_rtc_index = 8;
+ m_io_regs[0x0a / 2] = (m_io_regs[0x0a / 2] & 0x00ff) | (m_rtc_setting << 8);
+ data |= 0x80;
+ break;
+ case 0x14: // Set Time/Date
+ m_rtc_year = m_io_regs[0x0a / 2] >> 8;
+ m_rtc_index = 1;
+ data |= 0x80;
+ break;
+ case 0x15: // Get Time/Date
+ m_rtc_index = 0;
+ data |= 0x80;
+ m_io_regs[0x0a / 2] = (m_io_regs[0x0a / 2] & 0x00ff) | (m_rtc_year << 8);
+ break;
+ default:
+ logerror( "Unknown RTC command (%X) requested\n", data & 0xff);
+ }
+ }
+ // RTC Data
+ if (ACCESSING_BITS_8_15)
{
- switch (m_rtc_index)
+ if ((m_io_regs[0x0a / 2] & 0xff) == 0x94 && m_rtc_index < 7)
{
- case 0: m_rtc_year = data; break;
- case 1: m_rtc_month = data; break;
- case 2: m_rtc_day = data; break;
- case 3: m_rtc_day_of_week = data; break;
- case 4: m_rtc_hour = data; break;
- case 5: m_rtc_minute = data; break;
- case 6: m_rtc_second = data; break;
+ switch (m_rtc_index)
+ {
+ case 0: m_rtc_year = data >> 8; break;
+ case 1: m_rtc_month = data >> 8; break;
+ case 2: m_rtc_day = data >> 8; break;
+ case 3: m_rtc_day_of_week = data >> 8; break;
+ case 4: m_rtc_hour = data >> 8; break;
+ case 5: m_rtc_minute = data >> 8; break;
+ case 6: m_rtc_second = data >> 8; break;
+ }
+ m_rtc_index++;
}
- m_rtc_index++;
}
break;
}
- m_io_regs[offset] = data;
+ COMBINE_DATA(&m_io_regs[offset]);
}
-uint8_t ws_rom_sram_device::read_ram(offs_t offset)
+u16 ws_rom_sram_device::read_ram(offs_t offset, u16 mem_mask)
{
- return m_nvram[m_nvram_base + offset];
+ u32 nvram_address = (m_nvram_base + (offset << 1)) & (m_nvram_size - 1);
+ return m_nvram[nvram_address] | (m_nvram[nvram_address + 1] << 8);
}
-void ws_rom_sram_device::write_ram(offs_t offset, uint8_t data)
+void ws_rom_sram_device::write_ram(offs_t offset, u16 data, u16 mem_mask)
{
- m_nvram[m_nvram_base + offset] = data;
+ u32 nvram_address = (m_nvram_base + (offset << 1)) & (m_nvram_size - 1);
+ if (ACCESSING_BITS_0_7)
+ m_nvram[nvram_address] = data & 0xff;
+ if (ACCESSING_BITS_8_15)
+ m_nvram[nvram_address + 1] = data >> 8;
}
-void ws_rom_sram_device::write_io(offs_t offset, uint8_t data)
+void ws_rom_sram_device::write_io(offs_t offset, u16 data, u16 mem_mask)
{
switch (offset)
{
- case 0x01: // SRAM bank to select
- m_nvram_base = (data * 0x10000) & (m_nvram.size() - 1);
+ case 0x00 / 2:
+ // SRAM bank to select
+ if (ACCESSING_BITS_8_15)
+ {
+ m_nvram_base = ((data >> 8) * 0x10000) & (m_nvram.size() - 1);
+ }
+ [[fallthrough]];
default:
- ws_rom_device::write_io(offset, data);
+ ws_rom_device::write_io(offset, data, mem_mask);
break;
}
}
-uint8_t ws_rom_eeprom_device::read_io(offs_t offset)
+u16 ws_rom_eeprom_device::read_io(offs_t offset, u16 mem_mask)
{
- uint8_t value = m_io_regs[offset];
+ u16 value = m_io_regs[offset];
switch (offset)
{
- case 0x04:
- case 0x05:
- case 0x06:
- case 0x07:
- case 0x08:
+ case 0x04 / 2:
+ case 0x06 / 2:
+ case 0x08 / 2:
// EEPROM reads, taken from regs
break;
default:
- value = ws_rom_device::read_io(offset);
+ value = ws_rom_device::read_io(offset, mem_mask);
break;
}
return value;
}
-void ws_rom_eeprom_device::write_io(offs_t offset, uint8_t data)
+void ws_rom_eeprom_device::write_io(offs_t offset, u16 data, u16 mem_mask)
{
switch (offset)
{
- case 0x06: /* EEPROM address lower bits port/EEPROM address and command port
- 1KBit EEPROM:
- Bit 0-5 - EEPROM address bit 1-6
- Bit 6-7 - Command
- 00 - Extended command address bit 4-5:
- 00 - Write disable
- 01 - Write all
- 10 - Erase all
- 11 - Write enable
- 01 - Write
- 10 - Read
- 11 - Erase
- 16KBit EEPROM:
- Bit 0-7 - EEPROM address bit 1-8
- */
- switch (m_eeprom_mode)
+ case 0x06 / 2:
+ /* EEPROM address lower bits port/EEPROM address and command port
+ 1KBit EEPROM:
+ Bit 0-5 - EEPROM address bit 1-6
+ Bit 6-7 - Command
+ 00 - Extended command address bit 4-5:
+ 00 - Write disable
+ 01 - Write all
+ 10 - Erase all
+ 11 - Write enable
+ 01 - Write
+ 10 - Read
+ 11 - Erase
+ 16KBit EEPROM:
+ Bit 0-7 - EEPROM address bit 1-8
+ */
+ if (ACCESSING_BITS_0_7)
{
- case EEPROM_1K:
+ switch (m_eeprom_mode)
+ {
+ case EEPROM_1K:
m_eeprom_address = data & 0x3f;
- m_eeprom_command = data >> 4;
- if ((m_eeprom_command & 0x0c) != 0x00)
- m_eeprom_command = m_eeprom_command & 0x0c;
- break;
-
- case EEPROM_8K:
- case EEPROM_16K:
- m_eeprom_address = (m_eeprom_address & 0xff00) | data;
- break;
-
- default:
- logerror( "Write EEPROM address/register register C6 for unsupported EEPROM type\n" );
- break;
- }
- break;
-
- case 0x07: /* EEPROM higher bits/command bits port
- 1KBit EEPROM:
- Bit 0 - Start
- Bit 1-7 - Unknown
- 16KBit EEPROM:
- Bit 0-1 - EEPROM address bit 9-10
- Bit 2-3 - Command
- 00 - Extended command address bit 0-1:
- 00 - Write disable
- 01 - Write all
- 10 - Erase all
- 11 - Write enable
- 01 - Write
- 10 - Read
- 11 - Erase
- Bit 4 - Start
- Bit 5-7 - Unknown
- */
- switch (m_eeprom_mode)
- {
- case EEPROM_1K:
- m_eeprom_start = data & 0x01;
- break;
-
- case EEPROM_8K:
- m_eeprom_address = ((data & 0x01) << 8) | (m_eeprom_address & 0xff);
- m_eeprom_command = data & 0x0f;
- if ((m_eeprom_command & 0x0c) != 0x00)
- m_eeprom_command = m_eeprom_command & 0x0c;
- m_eeprom_start = (data >> 4) & 0x01;
- break;
+ m_eeprom_command = (data >> 4) & 0x0f;
+ if ((m_eeprom_command & 0x0c) != 0x00)
+ m_eeprom_command = m_eeprom_command & 0x0c;
+ break;
- case EEPROM_16K:
- m_eeprom_address = ((data & 0x03) << 8) | (m_eeprom_address & 0xff);
- m_eeprom_command = data & 0x0f;
- if ((m_eeprom_command & 0x0c) != 0x00)
- m_eeprom_command = m_eeprom_command & 0x0c;
- m_eeprom_start = (data >> 4) & 0x01;
- break;
+ case EEPROM_8K:
+ case EEPROM_16K:
+ m_eeprom_address = (m_eeprom_address & 0xff00) | (data & 0xff);
+ break;
- default:
- logerror( "Write EEPROM address/command register C7 for unsupported EEPROM type\n" );
- break;
+ default:
+ logerror( "Write EEPROM address/register register C6 for unsupported EEPROM type\n" );
+ break;
+ }
}
- break;
-
- case 0x08: /* EEPROM command
- Bit 0 - Read complete (read only)
- Bit 1 - Write complete (read only)
- Bit 2-3 - Unknown
- Bit 4 - Read
- Bit 5 - Write
- Bit 6 - Protect
- Bit 7 - Initialize
- */
- if (data & 0x80) // Initialize
- logerror("Unsupported EEPROM command 'Initialize'\n");
-
- if (data & 0x40) // Protect
+ /* EEPROM higher bits/command bits port
+ 1KBit EEPROM:
+ Bit 0 - Start
+ Bit 1-7 - Unknown
+ 16KBit EEPROM:
+ Bit 0-1 - EEPROM address bit 9-10
+ Bit 2-3 - Command
+ 00 - Extended command address bit 0-1:
+ 00 - Write disable
+ 01 - Write all
+ 10 - Erase all
+ 11 - Write enable
+ 01 - Write
+ 10 - Read
+ 11 - Erase
+ Bit 4 - Start
+ Bit 5-7 - Unknown
+ */
+ if (ACCESSING_BITS_8_15)
{
- switch (m_eeprom_command)
+ switch (m_eeprom_mode)
{
- case 0x00:
- m_eeprom_write_enabled = 0;
- data |= 0x02;
+ case EEPROM_1K:
+ m_eeprom_start = (data >> 8) & 0x01;
+ break;
+
+ case EEPROM_8K:
+ m_eeprom_address = (data & 0x0100) | (m_eeprom_address & 0xff);
+ m_eeprom_command = (data >> 8) & 0x0f;
+ if ((m_eeprom_command & 0x0c) != 0x00)
+ m_eeprom_command = m_eeprom_command & 0x0c;
+ m_eeprom_start = (data >> 12) & 0x01;
break;
- case 0x03:
- m_eeprom_write_enabled = 1;
- data |= 0x02;
+
+ case EEPROM_16K:
+ m_eeprom_address = (data & 0x0300) | (m_eeprom_address & 0xff);
+ m_eeprom_command = (data >> 8) & 0x0f;
+ if ((m_eeprom_command & 0x0c) != 0x00)
+ m_eeprom_command = m_eeprom_command & 0x0c;
+ m_eeprom_start = (data >> 12) & 0x01;
break;
+
default:
- logerror("Unsupported 'Protect' command %X\n", m_eeprom_command);
- break;
+ logerror( "Write EEPROM address/command register C7 for unsupported EEPROM type\n" );
+ break;
}
}
+ break;
- if (data & 0x20) // Write
+ case 0x08 / 2:
+ /* EEPROM command
+ Bit 0 - Read complete (read only)
+ Bit 1 - Write complete (read only)
+ Bit 2-3 - Unknown
+ Bit 4 - Read
+ Bit 5 - Write
+ Bit 6 - Protect
+ Bit 7 - Initialize
+ */
+ if (ACCESSING_BITS_0_7)
{
- if (m_eeprom_write_enabled)
+ if (data & 0x80) // Initialize
+ logerror("Unsupported EEPROM command 'Initialize'\n");
+
+ if (data & 0x40) // Protect
{
switch (m_eeprom_command)
{
- case 0x04:
- m_nvram[(m_eeprom_address << 1) + 1] = m_io_regs[0x04];
- m_nvram[m_eeprom_address << 1] = m_io_regs[0x05];
+ case 0x00:
+ m_eeprom_write_enabled = 0;
+ data |= 0x02;
+ break;
+ case 0x03:
+ m_eeprom_write_enabled = 1;
data |= 0x02;
break;
default:
- logerror("Unsupported 'Write' command %X\n", m_eeprom_command);
+ logerror("Unsupported 'Protect' command %X\n", m_eeprom_command);
break;
}
}
- }
- if (data & 0x10) // Read
- {
- m_io_regs[0x04] = m_nvram[(m_eeprom_address << 1) + 1];
- m_io_regs[0x05] = m_nvram[m_eeprom_address << 1];
- data |= 0x01;
+ if (data & 0x20) // Write
+ {
+ if (m_eeprom_write_enabled)
+ {
+ switch (m_eeprom_command)
+ {
+ case 0x04:
+ m_nvram[(m_eeprom_address << 1) + 1] = m_io_regs[0x04 / 2] & 0xff;
+ m_nvram[m_eeprom_address << 1] = m_io_regs[0x04 / 2] >> 8;
+ data |= 0x02;
+ break;
+ default:
+ logerror("Unsupported 'Write' command %X\n", m_eeprom_command);
+ break;
+ }
+ }
+ }
+
+ if (data & 0x10) // Read
+ {
+ m_io_regs[0x04] = m_nvram[(m_eeprom_address << 1) + 1];
+ m_io_regs[0x05] = m_nvram[m_eeprom_address << 1];
+ data |= 0x01;
+ }
}
break;
default:
- ws_rom_device::write_io(offset, data);
+ ws_rom_device::write_io(offset, data, mem_mask);
break;
}
- m_io_regs[offset] = data;
+ COMBINE_DATA(&m_io_regs[offset]);
+}
+
+
+u16 ws_wwitch_device::read_ram(offs_t offset, u16 mem_mask)
+{
+ if (m_flash_mode == COMMAND_MODE)
+ {
+ if (!machine().side_effects_disabled())
+ {
+ if (m_writing_flash)
+ {
+ m_flash_status ^= 0x40;
+ m_flash_count++;
+ if (m_flash_count > 4) {
+ m_writing_flash = false;
+ m_flash_mode = READ_MODE;
+ }
+ }
+ // After initiating an erase block command the wwitch expects to see bit 7 set
+ if (m_flash_command == 0x30)
+ {
+ m_flash_status |= 0x80;
+ m_flash_mode = READ_MODE;
+ }
+ }
+ return m_flash_status;
+ }
+ if (m_io_regs[0x01] >= 8 && m_io_regs[0x01] < 16)
+ {
+ return m_rom[((m_io_regs[0x01] * 0x8000) | offset) & m_rom_mask];
+ }
+ if (m_io_regs[0x01] < 8)
+ {
+ return ws_rom_sram_device::read_ram(offset, mem_mask);
+ }
+ else
+ {
+ return 0xffff;
+ }
+}
+
+
+void ws_wwitch_device::write_ram(offs_t offset, u16 data, u16 mem_mask)
+{
+ if (m_flash_seq == 0 && offset == (0xaaa >> 1) && ACCESSING_BITS_0_7 && data == 0xaa)
+ {
+ m_flash_seq = 1;
+ }
+ else if (m_flash_seq == 1 && offset == (0x555 >> 1) && ACCESSING_BITS_8_15 && data == 0x55)
+ {
+ m_flash_seq = 2;
+ }
+ else if (m_flash_seq == 2 && offset == (0xaaa >> 1) && ACCESSING_BITS_0_7)
+ {
+ switch (data)
+ {
+ case 0x10: // Chip erase
+ if (m_flash_command == 0x80)
+ {
+ // TODO
+ }
+ break;
+ case 0x20: // Set to fast mode
+ m_flash_command = data;
+ m_flash_mode = COMMAND_MODE;
+ break;
+ case 0x30: // (Erase) block
+ // TODO: Any write to a block address triggers the block erase
+ if (m_flash_command == 0x80)
+ {
+ if ((m_io_regs[0x01] & 0x07) < 7)
+ {
+ u32 block_base = (m_io_regs[0x01] & 0x07) << 15;
+ for (u32 address = 0; address < 0x8000; address++)
+ {
+ m_rom[(block_base | address) & m_rom_mask] = 0xffff;
+ }
+ }
+
+ m_flash_command = data;
+ m_flash_mode = COMMAND_MODE;
+ }
+ break;
+ case 0x80: // Erase (chip or block)
+ m_flash_command = data;
+ break;
+ default: // Unknown command
+ m_flash_command = 0;
+ }
+ m_flash_seq = 0;
+ }
+ else if (m_io_regs[0x01] >= 8 && m_io_regs[0x01] < 15)
+ {
+ if (m_write_flash)
+ {
+ // perform write
+ if (!ACCESSING_BITS_0_7)
+ data |= 0xff;
+ if (!ACCESSING_BITS_8_15)
+ data |= 0xff00;
+ m_rom[((m_io_regs[0x01] * 0x8000) | offset) & m_rom_mask] &= data;
+ m_flash_status = (m_flash_status & 0x7f) | ((data ^ 0x80) & 0x80);
+ m_writing_flash = true;
+ m_flash_count = 0;
+ m_write_flash = false;
+ }
+ else if (m_flash_command == 0x20)
+ {
+ switch (data)
+ {
+ case 0x00:
+ if (m_write_resetting)
+ {
+ m_write_flash = false;
+ m_write_resetting = false;
+ m_flash_mode = READ_MODE;
+ }
+ break;
+ case 0xF0: // Reset from fast mode #2
+ m_write_flash = false;
+ m_write_resetting = false;
+ m_flash_mode = READ_MODE;
+ break;
+ case 0x90: // Reset from fast mode #1
+ m_write_resetting = true;
+ break;
+ case 0xA0: // Fast program
+ if (m_flash_command == 0x20)
+ {
+ m_write_flash = true;
+ m_flash_mode = COMMAND_MODE;
+ }
+ break;
+ }
+ }
+ }
+ else if (m_io_regs[0x01] < 8)
+ {
+ ws_rom_sram_device::write_ram(offset, data, mem_mask);
+ }
}
diff --git a/src/devices/bus/wswan/rom.h b/src/devices/bus/wswan/rom.h
index 916562ab6e2..a4ab1082503 100644
--- a/src/devices/bus/wswan/rom.h
+++ b/src/devices/bus/wswan/rom.h
@@ -13,38 +13,38 @@ class ws_rom_device : public device_t,
{
public:
// construction/destruction
- ws_rom_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
+ ws_rom_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock);
// reading and writing
- virtual uint8_t read_rom20(offs_t offset) override;
- virtual uint8_t read_rom30(offs_t offset) override;
- virtual uint8_t read_rom40(offs_t offset) override;
- virtual uint8_t read_io(offs_t offset) override;
- virtual void write_io(offs_t offset, uint8_t data) override;
+ virtual u16 read_rom20(offs_t offset, u16 mem_mask) override;
+ virtual u16 read_rom30(offs_t offset, u16 mem_mask) override;
+ virtual u16 read_rom40(offs_t offset, u16 mem_mask) override;
+ virtual u16 read_io(offs_t offset, u16 mem_mask) override;
+ virtual void write_io(offs_t offset, u16 data, u16 mem_mask) override;
protected:
- static constexpr device_timer_id TIMER_RTC = 0;
-
- ws_rom_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock);
+ ws_rom_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;
- virtual void device_timer(emu_timer &timer, device_timer_id id, int param, void *ptr) override;
+ virtual void device_start() override ATTR_COLD;
+ virtual void device_reset() override ATTR_COLD;
+
+ TIMER_CALLBACK_MEMBER(rtc_tick);
- uint8_t m_io_regs[0x10];
- uint32_t m_base20, m_base30, m_base40;
+ u16 m_io_regs[8];
+ u32 m_base20, m_base30, m_base40;
+ u32 m_rom_mask;
// RTC
- uint8_t m_rtc_setting; /* Timer setting byte */
- uint8_t m_rtc_year; /* Year */
- uint8_t m_rtc_month; /* Month */
- uint8_t m_rtc_day; /* Day */
- uint8_t m_rtc_day_of_week; /* Day of the week */
- uint8_t m_rtc_hour; /* Hour, high bit = 0 => AM, high bit = 1 => PM */
- uint8_t m_rtc_minute; /* Minute */
- uint8_t m_rtc_second; /* Second */
- uint8_t m_rtc_index; /* index for reading/writing of current of alarm time */
+ u8 m_rtc_setting; /* Timer setting byte */
+ u8 m_rtc_year; /* Year */
+ u8 m_rtc_month; /* Month */
+ u8 m_rtc_day; /* Day */
+ u8 m_rtc_day_of_week; /* Day of the week */
+ u8 m_rtc_hour; /* Hour, high bit = 0 => AM, high bit = 1 => PM */
+ u8 m_rtc_minute; /* Minute */
+ u8 m_rtc_second; /* Second */
+ u8 m_rtc_index; /* index for reading/writing of current of alarm time */
emu_timer *rtc_timer;
};
@@ -56,20 +56,22 @@ class ws_rom_sram_device : public ws_rom_device
{
public:
// construction/destruction
- ws_rom_sram_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
+ ws_rom_sram_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock);
// reading and writing
- virtual uint8_t read_ram(offs_t offset) override;
- virtual void write_ram(offs_t offset, uint8_t data) override;
- virtual void write_io(offs_t offset, uint8_t data) override;
+ virtual u16 read_ram(offs_t offset, u16 mem_mask) override;
+ virtual void write_ram(offs_t offset, u16 data, u16 mem_mask) override;
+ virtual void write_io(offs_t offset, u16 data, u16 mem_mask) override;
protected:
+ ws_rom_sram_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;
+ virtual void device_start() override ATTR_COLD;
+ virtual void device_reset() override ATTR_COLD;
private:
- uint32_t m_nvram_base;
+ u32 m_nvram_base;
};
@@ -79,30 +81,61 @@ class ws_rom_eeprom_device : public ws_rom_device
{
public:
// construction/destruction
- ws_rom_eeprom_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
+ ws_rom_eeprom_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock);
// reading and writing
- virtual uint8_t read_io(offs_t offset) override;
- virtual void write_io(offs_t offset, uint8_t data) override;
+ virtual u16 read_io(offs_t offset, u16 mem_mask) override;
+ virtual void write_io(offs_t offset, u16 data, u16 mem_mask) override;
protected:
// device-level overrides
- virtual void device_start() override;
- virtual void device_reset() override;
+ virtual void device_start() override ATTR_COLD;
+ virtual void device_reset() override ATTR_COLD;
private:
- uint8_t m_eeprom_mode; /* eeprom mode */
- uint16_t m_eeprom_address; /* Read/write address */
- uint8_t m_eeprom_command; /* Commands: 00, 01, 02, 03, 04, 08, 0C */
- uint8_t m_eeprom_start; /* start bit */
- uint8_t m_eeprom_write_enabled; /* write enabled yes/no */
+ u8 m_eeprom_mode; /* eeprom mode */
+ u16 m_eeprom_address; /* Read/write address */
+ u8 m_eeprom_command; /* Commands: 00, 01, 02, 03, 04, 08, 0C */
+ u8 m_eeprom_start; /* start bit */
+ u8 m_eeprom_write_enabled; /* write enabled yes/no */
};
+class ws_wwitch_device : public ws_rom_sram_device
+{
+public:
+ // construction/destruction
+ ws_wwitch_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock);
+
+ // reading and writing
+ virtual u16 read_ram(offs_t offset, u16 mem_mask) override;
+ virtual void write_ram(offs_t offset, u16 data, u16 mem_mask) override;
+
+protected:
+ // device-level overrides
+ virtual void device_start() override ATTR_COLD;
+ virtual void device_reset() override ATTR_COLD;
+
+private:
+ enum {
+ READ_MODE = 0,
+ COMMAND_MODE
+ };
+ u8 m_flash_seq;
+ u8 m_flash_command;
+ bool m_write_flash;
+ bool m_writing_flash;
+ bool m_write_resetting;
+ u8 m_flash_mode;
+ u8 m_flash_status;
+ u8 m_flash_count;
+};
+
// device type definition
DECLARE_DEVICE_TYPE(WS_ROM_STD, ws_rom_device)
DECLARE_DEVICE_TYPE(WS_ROM_SRAM, ws_rom_sram_device)
DECLARE_DEVICE_TYPE(WS_ROM_EEPROM, ws_rom_eeprom_device)
+DECLARE_DEVICE_TYPE(WS_ROM_WWITCH, ws_wwitch_device)
#endif // MAME_BUS_WSWAN_ROM_H
diff --git a/src/devices/bus/wswan/slot.cpp b/src/devices/bus/wswan/slot.cpp
index 731c0967e1e..31edbc6d971 100644
--- a/src/devices/bus/wswan/slot.cpp
+++ b/src/devices/bus/wswan/slot.cpp
@@ -7,7 +7,6 @@
***********************************************************************************************************/
-
#include "emu.h"
#include "slot.h"
@@ -25,13 +24,13 @@ DEFINE_DEVICE_TYPE(WS_CART_SLOT, ws_cart_slot_device, "ws_cart_slot", "Wonderswa
// device_ws_cart_interface - constructor
//-------------------------------------------------
-device_ws_cart_interface::device_ws_cart_interface(const machine_config &mconfig, device_t &device)
- : device_slot_card_interface(mconfig, device),
- m_rom(nullptr),
- m_rom_size(0),
- m_bank_mask(0),
- m_has_rtc(false),
- m_is_rotated(false)
+device_ws_cart_interface::device_ws_cart_interface(const machine_config &mconfig, device_t &device) :
+ device_interface(device, "wswancart"),
+ m_rom(nullptr),
+ m_rom_size(0),
+ m_nvram_size(0),
+ m_bank_mask(0),
+ m_has_rtc(false)
{
}
@@ -48,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(uint32_t size, const char *tag)
+void device_ws_cart_interface::rom_alloc(u32 size)
{
if (m_rom == nullptr)
{
- m_rom = device().machine().memory().region_alloc(std::string(tag).append(WSSLOT_ROM_REGION_TAG).c_str(), size, 1, 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);
}
@@ -63,8 +62,9 @@ void device_ws_cart_interface::rom_alloc(uint32_t size, const char *tag)
// nvram_alloc - alloc the space for the ram
//-------------------------------------------------
-void device_ws_cart_interface::nvram_alloc(uint32_t size)
+void device_ws_cart_interface::nvram_alloc(u32 size)
{
+ m_nvram_size = size;
m_nvram.resize(size);
}
@@ -76,10 +76,10 @@ void device_ws_cart_interface::nvram_alloc(uint32_t size)
//-------------------------------------------------
// ws_cart_slot_device - constructor
//-------------------------------------------------
-ws_cart_slot_device::ws_cart_slot_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) :
+ws_cart_slot_device::ws_cart_slot_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock) :
device_t(mconfig, WS_CART_SLOT, tag, owner, clock),
- device_image_interface(mconfig, *this),
- device_slot_interface(mconfig, *this),
+ device_cartrom_image_interface(mconfig, *this),
+ device_single_card_slot_interface<device_ws_cart_interface>(mconfig, *this),
m_type(WS_STD),
m_cart(nullptr)
{
@@ -100,7 +100,7 @@ ws_cart_slot_device::~ws_cart_slot_device()
void ws_cart_slot_device::device_start()
{
- m_cart = dynamic_cast<device_ws_cart_interface *>(get_card_device());
+ m_cart = get_card_device();
}
@@ -119,14 +119,15 @@ static const ws_slot slot_list[] =
{
{ WS_STD, "ws_rom" },
{ WS_SRAM, "ws_sram" },
- { WS_EEPROM, "ws_eeprom" }
+ { WS_EEPROM, "ws_eeprom" },
+ { WWITCH, "wwitch"}
};
static int ws_get_pcb_id(const char *slot)
{
for (auto & elem : slot_list)
{
- if (!core_stricmp(elem.slot_option, slot))
+ if (!strcmp(elem.slot_option, slot))
return elem.pcb_id;
}
@@ -149,32 +150,28 @@ 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)
{
- uint8_t *ROM;
- uint32_t size = !loaded_through_softlist() ? length() : get_software_region_length("rom");
- uint32_t 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())
{
- int chunks = size / 0x10000;
// get cart type and nvram length
m_type = get_cart_type(ROM, size, nvram_size);
- if (ROM[(chunks - 1) * 0x10000 + 0xfffd])
+ if (ROM[(size >> 1) - 2] & 0xff00)
m_cart->set_has_rtc(true);
- if (ROM[(chunks - 1) * 0x10000 + 0xfffc] & 0x01)
- m_cart->set_is_rotated(true);
}
else
{
@@ -182,25 +179,18 @@ image_init_result ws_cart_slot_device::call_load()
if (pcb_name)
m_type = ws_get_pcb_id(pcb_name);
- if (m_type == WS_SRAM)
+ if (m_type == WS_SRAM || m_type == WWITCH)
nvram_size = get_software_region_length("sram");
if (m_type == WS_EEPROM)
nvram_size = get_software_region_length("eeprom");
if (get_feature("rtc"))
{
- if (!core_stricmp(get_feature("rtc"), "yes"))
+ if (!strcmp(get_feature("rtc"), "yes"))
m_cart->set_has_rtc(true);
}
- if (get_feature("rotated"))
- {
- if (!core_stricmp(get_feature("rotated"), "yes"))
- m_cart->set_is_rotated(true);
- }
}
- //printf("Type: %s\n", ws_get_slot(m_type));
-
if (nvram_size)
{
// allocate NVRAM
@@ -212,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());
}
/*-------------------------------------------------
@@ -230,12 +220,11 @@ void ws_cart_slot_device::call_unload()
get cart type from cart file
-------------------------------------------------*/
-int ws_cart_slot_device::get_cart_type(const uint8_t *ROM, uint32_t len, uint32_t &nvram_len) const
+int ws_cart_slot_device::get_cart_type(const u16 *ROM, u32 len, u32 &nvram_len) const
{
- int chunks = len / 0x10000;
int type = WS_STD;
- switch (ROM[(chunks - 1) * 0x10000 + 0xfffb])
+ switch (ROM[(len >> 1) - 3] >> 8)
{
case 0x00:
break;
@@ -272,8 +261,7 @@ int ws_cart_slot_device::get_cart_type(const uint8_t *ROM, uint32_t len, uint32_
nvram_len = 0x800;
break;
default:
- printf("Unknown RAM size [0x%X]\n", ROM[(chunks - 1) * 0x10000 + 0xfffb]);
- logerror("Unknown RAM size [0x%X]\n", ROM[(chunks - 1) * 0x10000 + 0xfffb]);
+ logerror("Unknown RAM size [0x%X]\n", ROM[(len >> 1) - 3] >> 8);
break;
}
@@ -288,20 +276,26 @@ std::string ws_cart_slot_device::get_default_card_software(get_default_card_soft
{
if (hook.image_file())
{
+ // FIXME: multiple issues in this function
+ // * Check for error from getting file length
+ // * Check for file length too large for size_t
+ // * File length is bytes but vector is sized in words
+ // * Catch out-of-memory when resizing vector
+ // * Check for error reading
+ // * Consider big-endian hosts - word data needs swapping
const char *slot_string;
- uint32_t size = hook.image_file()->size();
- std::vector<uint8_t> rom(size);
+ std::uint64_t size = 0;
+ hook.image_file()->length(size);
+ std::vector<u16> rom(size);
int type;
- uint32_t nvram;
+ u32 nvram;
- hook.image_file()->read(&rom[0], size);
+ /*[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);
slot_string = ws_get_slot(type);
- //printf("type: %s\n", slot_string);
-
return std::string(slot_string);
}
@@ -312,80 +306,80 @@ std::string ws_cart_slot_device::get_default_card_software(get_default_card_soft
read_rom20
-------------------------------------------------*/
-uint8_t ws_cart_slot_device::read_rom20(offs_t offset)
+u16 ws_cart_slot_device::read_rom20(offs_t offset, u16 mem_mask)
{
if (m_cart)
- return m_cart->read_rom20(offset);
+ return m_cart->read_rom20(offset, mem_mask);
else
- return 0xff;
+ return 0xffff;
}
/*-------------------------------------------------
read_rom30
-------------------------------------------------*/
-uint8_t ws_cart_slot_device::read_rom30(offs_t offset)
+u16 ws_cart_slot_device::read_rom30(offs_t offset, u16 mem_mask)
{
if (m_cart)
- return m_cart->read_rom30(offset);
+ return m_cart->read_rom30(offset, mem_mask);
else
- return 0xff;
+ return 0xffff;
}
/*-------------------------------------------------
read_rom40
-------------------------------------------------*/
-uint8_t ws_cart_slot_device::read_rom40(offs_t offset)
+u16 ws_cart_slot_device::read_rom40(offs_t offset, u16 mem_mask)
{
if (m_cart)
- return m_cart->read_rom40(offset);
+ return m_cart->read_rom40(offset, mem_mask);
else
- return 0xff;
+ return 0xffff;
}
/*-------------------------------------------------
read_ram
-------------------------------------------------*/
-uint8_t ws_cart_slot_device::read_ram(offs_t offset)
+u16 ws_cart_slot_device::read_ram(offs_t offset, u16 mem_mask)
{
if (m_cart)
- return m_cart->read_ram(offset);
+ return m_cart->read_ram(offset, mem_mask);
else
- return 0xff;
+ return 0xffff;
}
/*-------------------------------------------------
write_ram
-------------------------------------------------*/
-void ws_cart_slot_device::write_ram(offs_t offset, uint8_t data)
+void ws_cart_slot_device::write_ram(offs_t offset, u16 data, u16 mem_mask)
{
if (m_cart)
- m_cart->write_ram(offset, data);
+ m_cart->write_ram(offset, data, mem_mask);
}
/*-------------------------------------------------
read_io
-------------------------------------------------*/
-uint8_t ws_cart_slot_device::read_io(offs_t offset)
+u16 ws_cart_slot_device::read_io(offs_t offset, u16 mem_mask)
{
if (m_cart)
- return m_cart->read_io(offset);
+ return m_cart->read_io(offset & 0x07, mem_mask);
else
- return 0xff;
+ return 0xffff;
}
/*-------------------------------------------------
write_io
-------------------------------------------------*/
-void ws_cart_slot_device::write_io(offs_t offset, uint8_t data)
+void ws_cart_slot_device::write_io(offs_t offset, u16 data, u16 mem_mask)
{
if (m_cart)
- m_cart->write_io(offset, data);
+ m_cart->write_io(offset & 0x07, data, mem_mask);
}
@@ -398,36 +392,37 @@ static const char *const sram_str[] = { "none", "64Kbit SRAM", "256Kbit SRAM", "
static const char *const eeprom_str[] = { "none", "1Kbit EEPROM", "16Kbit EEPROM", "Unknown", "Unknown", "8Kbit EEPROM" };
static const char *const romsize_str[] = { "Unknown", "Unknown", "4Mbit", "8Mbit", "16Mbit", "Unknown", "32Mbit", "Unknown", "64Mbit", "128Mbit" };
-void ws_cart_slot_device::internal_header_logging(uint8_t *ROM, uint32_t offs, uint32_t len)
+void ws_cart_slot_device::internal_header_logging(const u16 *ROM, u32 offs, u32 len)
{
- int sum = 0, banks = len / 0x10000;
- uint8_t romsize, ramtype, ramsize;
- romsize = ROM[offs + 0xfffa];
- ramtype = (ROM[offs + 0xfffb] & 0xf0) ? 1 : 0; // 1 = EEPROM, 0 = SRAM
- ramsize = ramtype ? ((ROM[offs + 0xfffb] & 0xf0) >> 4) : (ROM[offs + 0xfffb] & 0x0f);
-
+ const int banks = len / 0x10000;
+ const int words = len >> 1;
+ const u8 romsize = ROM[words - 3] & 0xff;
+ const u8 ramtype = (ROM[words - 3] & 0xf000) ? 1 : 0; // 1 = EEPROM, 0 = SRAM
+ const u8 ramsize = ramtype ? (((ROM[words - 3] >> 8) & 0xf0) >> 4) : ((ROM[words - 3] >> 8) & 0x0f);
+ u16 sum = 0;
logerror( "ROM DETAILS\n" );
logerror( "===========\n\n" );
- logerror("\tDeveloper ID: %X\n", ROM[offs + 0xfff6]);
- logerror("\tMinimum system: %s\n", ROM[offs + 0xfff7] ? "WonderSwan Color" : "WonderSwan");
- logerror("\tCart ID: %X\n", ROM[offs + 0xfff8]);
+ logerror("\tDeveloper ID: %X\n", ROM[words - 5] & 0xff);
+ logerror("\tMinimum system: %s\n", ROM[words - 5] & 0xff00 ? "WonderSwan Color" : "WonderSwan");
+ logerror("\tCart ID: %X\n", ROM[words - 4] & 0xff);
logerror("\tROM size: %s\n", romsize_str[romsize]);
if (ramtype)
logerror("\tEEPROM size: %s\n", (ramsize < 6) ? eeprom_str[ramsize] : "Unknown");
else
logerror("\tSRAM size: %s\n", (ramsize < 6) ? sram_str[ramsize] : "Unknown");
- logerror("\tFeatures: %X\n", ROM[offs + 0xfffc]);
- logerror("\tRTC: %s\n", ROM[offs + 0xfffd] ? "yes" : "no");
+ logerror("\tFeatures: %X\n", ROM[words - 2] & 0xff);
+ logerror("\tRTC: %s\n", (ROM[words - 2] & 0xff00) ? "yes" : "no");
for (int i = 0; i < banks; i++)
{
- for (int count = 0; count < 0x10000; count++)
+ for (int count = 0; count < 0x8000; count++)
{
- sum += ROM[(i * 0x10000) + count];
+ sum += ROM[i * 0x8000 + count] & 0xff;
+ sum += ROM[i * 0x8000 + count] >> 8;
}
}
- sum -= ROM[offs + 0xffff];
- sum -= ROM[offs + 0xfffe];
+ sum -= ROM[words - 1] & 0xff;
+ sum -= ROM[words - 1] >> 8;
sum &= 0xffff;
- logerror("\tChecksum: %.2X%.2X (calculated: %04X)\n", ROM[offs + 0xffff], ROM[offs + 0xfffe], sum);
+ logerror("\tChecksum: %04X (calculated: %04X)\n", ROM[words - 1], sum);
}
diff --git a/src/devices/bus/wswan/slot.h b/src/devices/bus/wswan/slot.h
index 219a4bb3fe8..308fedf97a3 100644
--- a/src/devices/bus/wswan/slot.h
+++ b/src/devices/bus/wswan/slot.h
@@ -1,11 +1,72 @@
// license:BSD-3-Clause
// copyright-holders:Wilbert Pol
+/***************************************************************************
+ Bandai WonderSwan cartridge slot
+
+ 48-pin single-sided PCB edge connector
+
+ The SoC maps the following ranges to the cartridge slot:
+ * Memory 0x10000-0x1ffff 8-bit read/write (typically used for cartridge SRAM)
+ 3-cycle access on WonderSwan, 1-cycle access on WonderSwan Color
+ * Memory 0x20000-0xfffff 16-bit read-only (writes not emitted)
+ * I/O 0xc0-0xff
+
+ Pin Name Notes
+ 1 GND
+ 2 A15
+ 3 A10
+ 4 A11
+ 5 A9
+ 6 A8
+ 7 A13
+ 8 A14
+ 9 A12
+ 10 A7
+ 11 A6
+ 12 A5
+ 13 A4
+ 14 D15
+ 15 D14
+ 16 D7
+ 17 D6
+ 18 D5
+ 19 D4
+ 20 D3
+ 21 D2
+ 22 D1
+ 23 D0
+ 24 +3.3V
+ 25 +3.3V
+ 26 A0
+ 27 A1
+ 28 A2
+ 29 A3
+ 30 A19
+ 31 A18
+ 32 A17
+ 33 A16
+ 34 D8
+ 35 D9
+ 36 D10
+ 37 D11
+ 38 D12
+ 39 D13
+ 40 /RESET
+ 41 ? input used while authenticating cartridge
+ 42 IO/M low when accessing I/O ports
+ 43 /RD
+ 44 /WR
+ 45 /CART low when accessing cartridge
+ 46 INT usually used for RTC alarm interrupt
+ 47 CLK 384 kHz on WonderSwan
+ 48 GND
+ ***************************************************************************/
#ifndef MAME_BUS_WSWAN_SLOT_H
#define MAME_BUS_WSWAN_SLOT_H
#pragma once
-#include "softlist_dev.h"
+#include "imagedev/cartrom.h"
/***************************************************************************
@@ -18,62 +79,62 @@ enum
{
WS_STD = 0,
WS_SRAM,
- WS_EEPROM
+ WS_EEPROM,
+ WWITCH
};
// ======================> device_ws_cart_interface
-class device_ws_cart_interface : public device_slot_card_interface
+class device_ws_cart_interface : public device_interface
{
public:
// construction/destruction
virtual ~device_ws_cart_interface();
// reading and writing
- virtual uint8_t read_rom20(offs_t offset) { return 0xff; }
- virtual uint8_t read_rom30(offs_t offset) { return 0xff; }
- virtual uint8_t read_rom40(offs_t offset) { return 0xff; }
- virtual uint8_t read_ram(offs_t offset) { return 0xff; }
- virtual void write_ram(offs_t offset, uint8_t data) {}
- 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 nvram_alloc(uint32_t size);
- uint8_t* get_rom_base() { return m_rom; }
+ virtual u16 read_rom20(offs_t offset, u16 mem_mask) { return 0xffff; }
+ virtual u16 read_rom30(offs_t offset, u16 mem_mask) { return 0xffff; }
+ virtual u16 read_rom40(offs_t offset, u16 mem_mask) { return 0xffff; }
+ virtual u16 read_ram(offs_t offset, u16 mem_mask) { return 0xffff; }
+ virtual void write_ram(offs_t offset, u16 data, u16 mem_mask) {}
+ 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);
+ void nvram_alloc(u32 size);
+ u16* get_rom_base() { return m_rom; }
uint8_t* get_nvram_base() { return &m_nvram[0]; }
uint32_t get_rom_size() { return m_rom_size; }
uint32_t get_nvram_size() { return m_nvram.size(); }
void save_nvram() { device().save_item(NAME(m_nvram)); }
void set_has_rtc(bool val) { m_has_rtc = val; }
- void set_is_rotated(bool val) { m_is_rotated = val; }
- int get_is_rotated() { return m_is_rotated ? 1 : 0; }
protected:
device_ws_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_nvram;
+ u16 *m_rom;
+ u32 m_rom_size;
+ std::vector<u8> m_nvram;
+ u32 m_nvram_size;
int m_bank_mask;
- bool m_has_rtc, m_is_rotated;
+ bool m_has_rtc;
};
// ======================> ws_cart_slot_device
class ws_cart_slot_device : public device_t,
- public device_image_interface,
- public device_slot_interface
+ public device_cartrom_image_interface,
+ public device_single_card_slot_interface<device_ws_cart_interface>
{
public:
// construction/destruction
template <typename T>
- ws_cart_slot_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock, T &&opts, const char *dflt)
+ ws_cart_slot_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock, T &&opts, const char *dflt)
: ws_cart_slot_device(mconfig, tag, owner, clock)
{
option_reset();
@@ -81,48 +142,41 @@ public:
set_default_option(dflt);
set_fixed(false);
}
- ws_cart_slot_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
+ 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 const software_list_loader &get_software_list_loader() const override { return rom_software_list_loader::instance(); }
- int get_type() { return m_type; }
- int get_is_rotated() { return m_cart->get_is_rotated(); }
- int get_cart_type(const uint8_t *ROM, uint32_t len, uint32_t &nvram_len) const;
- void internal_header_logging(uint8_t *ROM, uint32_t offs, uint32_t len);
+ 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"; }
- void save_nvram() { if (m_cart && m_cart->get_nvram_size()) m_cart->save_nvram(); }
+ // device_slot_interface implementation
+ virtual std::string get_default_card_software(get_default_card_software_hook &hook) const override;
- virtual iodevice_t image_type() const override { return IO_CARTSLOT; }
- virtual bool is_readable() const override { return 1; }
- virtual bool is_writeable() const override { return 0; }
- virtual bool is_creatable() const override { return 0; }
- virtual bool must_be_loaded() const override { return 1; }
- virtual bool is_reset_on_load() const override { return 1; }
- virtual const char *image_interface() const override { return "wswan_cart"; }
- virtual const char *file_extensions() const override { return "ws,wsc,bin"; }
+ int get_type() { return m_type; }
+ int get_cart_type(const u16 *ROM, u32 len, u32 &nvram_len) const;
+ void internal_header_logging(const u16 *ROM, u32 offs, u32 len);
- // slot interface overrides
- 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(); }
// reading and writing
- virtual uint8_t read_rom20(offs_t offset);
- virtual uint8_t read_rom30(offs_t offset);
- virtual uint8_t read_rom40(offs_t offset);
- virtual uint8_t read_ram(offs_t offset);
- virtual void write_ram(offs_t offset, uint8_t data);
- virtual uint8_t read_io(offs_t offset);
- virtual void write_io(offs_t offset, uint8_t data);
+ virtual u16 read_rom20(offs_t offset, u16 mem_mask);
+ virtual u16 read_rom30(offs_t offset, u16 mem_mask);
+ virtual u16 read_rom40(offs_t offset, u16 mem_mask);
+ virtual u16 read_ram(offs_t offset, u16 mem_mask);
+ virtual void write_ram(offs_t offset, u16 data, u16 mem_mask);
+ virtual u16 read_io(offs_t offset, u16 mem_mask);
+ virtual void write_io(offs_t offset, u16 data, u16 mem_mask);
protected:
- // device-level overrides
- virtual void device_start() override;
+ // device_t implementation
+ virtual void device_start() override ATTR_COLD;
int m_type;
- device_ws_cart_interface* m_cart;
+ device_ws_cart_interface *m_cart;
};
@@ -130,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..22fd035f148
--- /dev/null
+++ b/src/devices/bus/wysekbd/wysegakb.cpp
@@ -0,0 +1,1020 @@
+// license:BSD-3-Clause
+// copyright-holders:AJR
+/***************************************************************************
+
+ Wyse gate array-based terminal keyboards
+
+ The original WY-85 keyboard (#840105-01) did not have a gate array but
+ used LSTTL counters and decoders, an analog multiplexer, LM339
+ comparators and various discrete components. The later WY-85 gate array
+ keyboard (#840336-01) is likely functionally identical to it.
+
+***************************************************************************/
+
+#include "emu.h"
+#include "wysegakb.h"
+
+
+//**************************************************************************
+// DEVICE TYPE DEFINITIONS
+//**************************************************************************
+
+// device type definitions
+DEFINE_DEVICE_TYPE(WY85_KEYBOARD, wy85_keyboard_device, "wy85_kbd", "WY-85 Keyboard")
+DEFINE_DEVICE_TYPE(WY30_KEYBOARD, wy30_keyboard_device, "wy30_kbd", "WY-30 Keyboard")
+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
+//**************************************************************************
+
+wy85_keyboard_device::wy85_keyboard_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock)
+ : wyse_gate_array_keyboard_device(mconfig, WY85_KEYBOARD, tag, owner, clock)
+{
+}
+
+static INPUT_PORTS_START(wy85_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_CHAR(UCHAR_MAMEKEY(4_PAD)) PORT_CODE(KEYCODE_4_PAD)
+ PORT_BIT(0x04, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("PF1") PORT_CODE(KEYCODE_NUMLOCK)
+ PORT_BIT(0x08, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CHAR('<') PORT_CHAR('>') PORT_CODE(KEYCODE_BACKSLASH2)
+ 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("Tab") 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("F1 (Hold Screen)") PORT_CHAR(UCHAR_MAMEKEY(F1)) PORT_CODE(KEYCODE_F1)
+
+ 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("PF2") PORT_CODE(KEYCODE_EQUALS_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_NAME("F2 (Print Screen)") PORT_CHAR(UCHAR_MAMEKEY(F2)) PORT_CODE(KEYCODE_F2)
+
+ 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("PF3") PORT_CODE(KEYCODE_SLASH_PAD)
+ 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_CHAR('\\') PORT_CHAR('|') PORT_CODE(KEYCODE_BACKSLASH)
+ PORT_BIT(0x80, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("F3 (Reset/Set Up)") PORT_CHAR(UCHAR_MAMEKEY(F3)) PORT_CODE(KEYCODE_F3)
+
+ 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_CHAR(UCHAR_MAMEKEY(1_PAD)) PORT_CODE(KEYCODE_1_PAD)
+ PORT_BIT(0x04, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("PF4") PORT_CODE(KEYCODE_ASTERISK)
+ 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_NAME("F4 (Send Block)") PORT_CHAR(UCHAR_MAMEKEY(F4)) PORT_CODE(KEYCODE_F4)
+
+ 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_CHAR(UCHAR_MAMEKEY(2_PAD)) PORT_CODE(KEYCODE_2_PAD)
+ PORT_BIT(0x04, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CHAR(UCHAR_MAMEKEY(7_PAD)) PORT_CODE(KEYCODE_7_PAD)
+ 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_NAME("Space Bar") PORT_CHAR(' ') PORT_CODE(KEYCODE_SPACE)
+ PORT_BIT(0x80, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("F5 (Break)") PORT_CHAR(UCHAR_MAMEKEY(F5)) PORT_CODE(KEYCODE_F5)
+
+ PORT_START("R5")
+ PORT_BIT(0x01, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CHAR(UCHAR_MAMEKEY(F19)) PORT_CODE(KEYCODE_F19)
+ PORT_BIT(0x02, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CHAR(UCHAR_MAMEKEY(F18)) PORT_CODE(KEYCODE_F18)
+ PORT_BIT(0x04, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CHAR(UCHAR_MAMEKEY(F17)) PORT_CODE(KEYCODE_F17)
+ PORT_BIT(0x08, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("Do") PORT_CHAR(UCHAR_MAMEKEY(F16)) PORT_CODE(KEYCODE_F16)
+ PORT_BIT(0x10, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("Help") PORT_CHAR(UCHAR_MAMEKEY(F15)) PORT_CODE(KEYCODE_F15)
+ PORT_BIT(0x20, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("F14 (Home)") PORT_CHAR(UCHAR_MAMEKEY(F14), UCHAR_MAMEKEY(HOME)) PORT_CODE(KEYCODE_F14)
+ PORT_BIT(0x40, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("F13 (LF)") PORT_CHAR(UCHAR_MAMEKEY(F13), 0x0a) PORT_CODE(KEYCODE_F13)
+ PORT_BIT(0x80, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("Compose Character") PORT_CHAR(UCHAR_MAMEKEY(LALT)) PORT_CODE(KEYCODE_LALT)
+
+ 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") PORT_CHAR(UCHAR_SHIFT_1) PORT_CODE(KEYCODE_LSHIFT) PORT_CODE(KEYCODE_RSHIFT)
+ 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_CHAR(UCHAR_MAMEKEY(F20)) PORT_CODE(KEYCODE_F20)
+ PORT_BIT(0x80, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CHAR(UCHAR_MAMEKEY(F6)) PORT_CODE(KEYCODE_F6)
+
+ 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(u8"\u232B (Delete)") PORT_CODE(KEYCODE_BACKSPACE) // ⌫
+ 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("Insert Here") PORT_CHAR(UCHAR_MAMEKEY(INSERT)) PORT_CODE(KEYCODE_HOME)
+ PORT_BIT(0x40, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("Ctrl") PORT_CHAR(UCHAR_MAMEKEY(LCONTROL)) PORT_CODE(KEYCODE_LCONTROL)
+ PORT_BIT(0x80, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CHAR(UCHAR_MAMEKEY(F7)) PORT_CODE(KEYCODE_F7)
+
+ 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("Remove") PORT_CHAR(UCHAR_MAMEKEY(DEL)) 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_NAME("Lock") PORT_CHAR(UCHAR_MAMEKEY(CAPSLOCK)) PORT_CODE(KEYCODE_CAPSLOCK)
+ PORT_BIT(0x80, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CHAR(UCHAR_MAMEKEY(F8)) PORT_CODE(KEYCODE_F8)
+
+ 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_CODE(KEYCODE_STOP)
+ PORT_BIT(0x04, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CHAR(',') PORT_CODE(KEYCODE_COMMA)
+ PORT_BIT(0x08, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("Select") 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(F9)) PORT_CODE(KEYCODE_F9)
+
+ PORT_START("R10")
+ 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_CHAR(UCHAR_MAMEKEY(MINUS_PAD)) PORT_CODE(KEYCODE_MINUS_PAD)
+ PORT_BIT(0x04, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("Prev Screen") PORT_CHAR(UCHAR_MAMEKEY(PGUP)) 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(F10)) PORT_CODE(KEYCODE_F10)
+
+ 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_NAME("Next Screen") PORT_CHAR(UCHAR_MAMEKEY(PGDN)) PORT_CODE(KEYCODE_PGDN)
+ PORT_BIT(0x04, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CHAR(UCHAR_MAMEKEY(8_PAD)) PORT_CODE(KEYCODE_8_PAD)
+ 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_NAME("F11 (Esc)") PORT_CHAR(UCHAR_MAMEKEY(F11), 0x1b) PORT_CODE(KEYCODE_F11)
+
+ PORT_START("R12")
+ PORT_BIT(0x01, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("Find") PORT_CODE(KEYCODE_INSERT)
+ PORT_BIT(0x02, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CHAR(UCHAR_MAMEKEY(3_PAD)) PORT_CODE(KEYCODE_3_PAD)
+ PORT_BIT(0x04, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CHAR(UCHAR_MAMEKEY(9_PAD)) PORT_CODE(KEYCODE_9_PAD)
+ 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_NAME("F12 (BS)") PORT_CHAR(UCHAR_MAMEKEY(F12), 0x08) PORT_CODE(KEYCODE_F12)
+INPUT_PORTS_END
+
+ioport_constructor wy85_keyboard_device::device_input_ports() const
+{
+ return INPUT_PORTS_NAME(wy85_keyboard);
+}
+
+u8 wy85_keyboard_device::wysekbd_get_id()
+{
+ // Original LSTTL version definitely lacks an ID; gate array version has this ID according to https://geekhack.org/index.php?topic=51079.0
+ return 0x60 ^ 0xff;
+}
+
+
+wy30_keyboard_device::wy30_keyboard_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock)
+ : wyse_gate_array_keyboard_device(mconfig, WY30_KEYBOARD, tag, owner, clock)
+{
+}
+
+static INPUT_PORTS_START(wy30_keyboard)
+ PORT_START("R0")
+ PORT_BIT(0x01, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("Keypad 1 Send") PORT_CHAR(UCHAR_MAMEKEY(1_PAD)) PORT_CODE(KEYCODE_1_PAD)
+ PORT_BIT(0x02, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("Keypad - Replace") PORT_CHAR(UCHAR_MAMEKEY(MINUS_PAD)) PORT_CODE(KEYCODE_MINUS_PAD)
+ PORT_BIT(0x04, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CHAR(UCHAR_MAMEKEY(F1)) PORT_CHAR(UCHAR_MAMEKEY(F5)) PORT_CODE(KEYCODE_NUMLOCK)
+ PORT_BIT(0x08, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("CapsLock") PORT_CHAR(UCHAR_MAMEKEY(CAPSLOCK)) PORT_CODE(KEYCODE_LCONTROL)
+ 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_NAME("Funct") PORT_CODE(KEYCODE_LALT)
+ PORT_BIT(0x80, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("Esc") PORT_CHAR(0x1b) PORT_CODE(KEYCODE_TILDE)
+
+ PORT_START("R1")
+ PORT_BIT(0x01, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("Keypad 2 Copy Prt") PORT_CHAR(UCHAR_MAMEKEY(2_PAD)) PORT_CODE(KEYCODE_2_PAD)
+ PORT_BIT(0x02, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("Keypad 4 Ins Line") PORT_CHAR(UCHAR_MAMEKEY(4_PAD)) PORT_CODE(KEYCODE_4_PAD)
+ PORT_BIT(0x04, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CHAR(UCHAR_MAMEKEY(F2)) PORT_CHAR(UCHAR_MAMEKEY(F6)) PORT_CODE(KEYCODE_EQUALS_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("Return") 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(u8"Keypad 3 \u25B2 Page") PORT_CHAR(UCHAR_MAMEKEY(3_PAD)) PORT_CODE(KEYCODE_3_PAD) // ▲ Page
+ PORT_BIT(0x02, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("Keypad 5 Del Line") PORT_CHAR(UCHAR_MAMEKEY(5_PAD)) PORT_CODE(KEYCODE_5_PAD)
+ PORT_BIT(0x04, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CHAR(UCHAR_MAMEKEY(F3)) PORT_CHAR(UCHAR_MAMEKEY(F7)) PORT_CODE(KEYCODE_SLASH_PAD)
+ 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("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_NAME("Setup") PORT_CODE(KEYCODE_INSERT)
+ PORT_BIT(0x02, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("BackSpace") PORT_CHAR(0x08) PORT_CODE(KEYCODE_BACKSPACE)
+ 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_CHAR('-') PORT_CHAR('_') PORT_CODE(KEYCODE_MINUS)
+ 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('`') PORT_CHAR('~') PORT_CODE(KEYCODE_BACKSLASH)
+ PORT_BIT(0x40, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CHAR('9') PORT_CHAR('(') PORT_CODE(KEYCODE_9)
+ 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(HOME)) PORT_CODE(KEYCODE_HOME)
+ PORT_BIT(0x02, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CHAR(UCHAR_MAMEKEY(UP)) PORT_CODE(KEYCODE_UP) // (possibly DOWN instead)
+ 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_CHAR('.') PORT_CHAR('>') PORT_CODE(KEYCODE_STOP)
+ PORT_BIT(0x10, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("Ctrl") PORT_CHAR(UCHAR_MAMEKEY(LCONTROL)) PORT_CODE(KEYCODE_CAPSLOCK)
+ 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_NAME("Line Feed") PORT_CHAR(0x0a) PORT_CODE(KEYCODE_END)
+
+ 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(0x08, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("J") PORT_CHAR('j') PORT_CHAR('J') PORT_CODE(KEYCODE_J)
+ PORT_BIT(0x10, 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("Shift") PORT_CHAR(UCHAR_SHIFT_1) PORT_CODE(KEYCODE_LSHIFT) PORT_CODE(KEYCODE_RSHIFT)
+ PORT_BIT(0x80, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CHAR('4') PORT_CHAR('$') PORT_CODE(KEYCODE_4)
+
+ PORT_START("R7")
+ 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_NAME(u8"Keypad . \u25BC Page") PORT_CHAR(UCHAR_MAMEKEY(DEL_PAD)) PORT_CODE(KEYCODE_DEL_PAD) // ▼ Page
+ PORT_BIT(0x04, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("Keypad 0 Print Page") PORT_CHAR(UCHAR_MAMEKEY(0_PAD)) 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 Clr Line") PORT_CHAR(UCHAR_MAMEKEY(9_PAD)) PORT_CODE(KEYCODE_9_PAD)
+ PORT_BIT(0x02, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("Keypad , Insert") PORT_CHAR(UCHAR_MAMEKEY(COMMA_PAD)) PORT_CODE(KEYCODE_PLUS_PAD)
+ PORT_BIT(0x04, IP_ACTIVE_LOW, IPT_UNUSED)
+ 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("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("Keypad 8 Del Char") PORT_CHAR(UCHAR_MAMEKEY(8_PAD)) PORT_CODE(KEYCODE_8_PAD)
+ PORT_BIT(0x02, IP_ACTIVE_LOW, IPT_UNUSED)
+ PORT_BIT(0x04, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CHAR(UCHAR_MAMEKEY(F4)) PORT_CHAR(UCHAR_MAMEKEY(F8)) PORT_CODE(KEYCODE_ASTERISK)
+ PORT_BIT(0x08, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CHAR(UCHAR_MAMEKEY(DOWN)) PORT_CODE(KEYCODE_DOWN) // (possibly UP instead)
+ 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_NAME("Del Break") PORT_CHAR(UCHAR_MAMEKEY(DEL)) PORT_CODE(KEYCODE_DEL)
+ PORT_BIT(0x02, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("Keypad 6 Clr Page") PORT_CHAR(UCHAR_MAMEKEY(6_PAD)) PORT_CODE(KEYCODE_6_PAD)
+ PORT_BIT(0x04, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("Keypad 7 Ins Char") PORT_CHAR(UCHAR_MAMEKEY(7_PAD)) PORT_CODE(KEYCODE_7_PAD)
+ 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("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(0xff, IP_ACTIVE_LOW, IPT_UNUSED)
+
+ PORT_START("R12")
+ PORT_BIT(0xff, IP_ACTIVE_LOW, IPT_UNUSED)
+INPUT_PORTS_END
+
+ioport_constructor wy30_keyboard_device::device_input_ports() const
+{
+ return INPUT_PORTS_NAME(wy30_keyboard);
+}
+
+u8 wy30_keyboard_device::wysekbd_get_id()
+{
+ return 0x01 ^ 0xff;
+}
+
+
+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..d4c581a0cdb
--- /dev/null
+++ b/src/devices/bus/wysekbd/wysegakb.h
@@ -0,0 +1,163 @@
+// 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 ATTR_COLD;
+
+ // 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;
+};
+
+// ======================> wy85_keyboard_device
+
+class wy85_keyboard_device : public wyse_gate_array_keyboard_device
+{
+public:
+ // device type constructor
+ wy85_keyboard_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock = 0U);
+
+protected:
+ virtual ioport_constructor device_input_ports() const override ATTR_COLD;
+ virtual u8 wysekbd_get_id() override;
+};
+
+// ======================> wy30_keyboard_device
+
+class wy30_keyboard_device : public wyse_gate_array_keyboard_device
+{
+public:
+ // device type constructor
+ wy30_keyboard_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock = 0U);
+
+protected:
+ virtual ioport_constructor device_input_ports() const override ATTR_COLD;
+ virtual u8 wysekbd_get_id() override;
+};
+
+// ======================> 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 ATTR_COLD;
+ 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 ATTR_COLD;
+
+ virtual ioport_constructor device_input_ports() const override ATTR_COLD;
+ 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 ATTR_COLD;
+ 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 ATTR_COLD;
+ 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 ATTR_COLD;
+ virtual u8 wysekbd_get_id() override;
+};
+
+// device type declarations
+DECLARE_DEVICE_TYPE(WY85_KEYBOARD, wy85_keyboard_device)
+DECLARE_DEVICE_TYPE(WY30_KEYBOARD, wy30_keyboard_device)
+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..6e7f6c66c6d
--- /dev/null
+++ b/src/devices/bus/wysekbd/wysekbd.cpp
@@ -0,0 +1,89 @@
+// 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 (though this is absent on
+ the earliest keyboards). 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 wy85_keyboards(device_slot_interface &slot)
+{
+ slot.option_add("wy85", WY85_KEYBOARD);
+}
+
+void wy30_keyboards(device_slot_interface &slot)
+{
+ slot.option_add("wy30", WY30_KEYBOARD);
+}
+
+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..f9372419a07
--- /dev/null
+++ b/src/devices/bus/wysekbd/wysekbd.h
@@ -0,0 +1,94 @@
+// license:BSD-3-Clause
+// copyright-holders:AJR
+/***************************************************************************
+
+ Wyse Keyboard Port interface
+
+***************************************************************************/
+
+#ifndef MAME_BUS_WYSEKBD_WYSEKBD_H
+#define MAME_BUS_WYSEKBD_WYSEKBD_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 ATTR_COLD;
+
+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 wy85_keyboards(device_slot_interface &slot);
+extern void wy30_keyboards(device_slot_interface &slot);
+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_WYSEKBD_H
diff --git a/src/devices/bus/x68k/x68k_midi.cpp b/src/devices/bus/x68k/x68k_midi.cpp
index 011fe5f734f..2f55ce3781f 100644
--- a/src/devices/bus/x68k/x68k_midi.cpp
+++ b/src/devices/bus/x68k/x68k_midi.cpp
@@ -40,21 +40,21 @@ x68k_midi_device::x68k_midi_device(const machine_config &mconfig, const char *ta
void x68k_midi_device::device_start()
{
m_slot = dynamic_cast<x68k_expansion_slot_device *>(owner());
- m_slot->space().install_readwrite_handler(0xeafa00,0xeafa0f,read8_delegate(FUNC(x68k_midi_device::x68k_midi_reg_r),this),write8_delegate(FUNC(x68k_midi_device::x68k_midi_reg_w),this),0x00ff00ff);
+ m_slot->space().install_readwrite_handler(0xeafa00,0xeafa0f, read8sm_delegate(*this, FUNC(x68k_midi_device::x68k_midi_reg_r)), write8sm_delegate(*this, FUNC(x68k_midi_device::x68k_midi_reg_w)), 0x00ff00ff);
}
void x68k_midi_device::device_reset()
{
}
-READ8_MEMBER(x68k_midi_device::x68k_midi_reg_r)
+uint8_t x68k_midi_device::x68k_midi_reg_r(offs_t offset)
{
- return m_midi->read(space, offset);
+ return m_midi->read(offset);
}
-WRITE8_MEMBER(x68k_midi_device::x68k_midi_reg_w)
+void x68k_midi_device::x68k_midi_reg_w(offs_t offset, uint8_t data)
{
- m_midi->write(space, offset, data);
+ m_midi->write(offset, data);
}
void x68k_midi_device::irq_w(int state)
diff --git a/src/devices/bus/x68k/x68k_midi.h b/src/devices/bus/x68k/x68k_midi.h
index 405ab433bd9..8e17b24df82 100644
--- a/src/devices/bus/x68k/x68k_midi.h
+++ b/src/devices/bus/x68k/x68k_midi.h
@@ -25,15 +25,15 @@ public:
x68k_midi_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 void device_add_mconfig(machine_config &config) override ATTR_COLD;
- DECLARE_READ8_MEMBER(x68k_midi_reg_r);
- DECLARE_WRITE8_MEMBER(x68k_midi_reg_w);
+ uint8_t x68k_midi_reg_r(offs_t offset);
+ void x68k_midi_reg_w(offs_t offset, uint8_t data);
protected:
// device-level overrides
- virtual void device_start() override;
- virtual void device_reset() override;
+ virtual void device_start() override ATTR_COLD;
+ virtual void device_reset() override ATTR_COLD;
// device_x68k_expansion_card_interface overrides
virtual uint8_t iack4() override;
diff --git a/src/devices/bus/x68k/x68k_neptunex.cpp b/src/devices/bus/x68k/x68k_neptunex.cpp
index 2bf97fa474d..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,22 +41,24 @@ 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,read16_delegate(FUNC(x68k_neptune_device::x68k_neptune_port_r),this),write16_delegate(FUNC(x68k_neptune_device::x68k_neptune_port_w),this),0xffffffff);
+ 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);
}
-READ16_MEMBER(x68k_neptune_device::x68k_neptune_port_r)
+uint16_t x68k_neptune_device::x68k_neptune_port_r(offs_t offset, uint16_t mem_mask)
{
uint16_t data;
@@ -62,17 +66,15 @@ READ16_MEMBER(x68k_neptune_device::x68k_neptune_port_r)
return 0xffff;
if(offset < 0x100+16)
{
- m_dp8390->dp8390_cs(CLEAR_LINE);
- return (m_dp8390->dp8390_r(space, offset, 0xff) << 8)|
- m_dp8390->dp8390_r(space, offset+1, 0xff);
+ return (m_dp8390->cs_read(offset) << 8)|
+ m_dp8390->cs_read(offset+1);
}
//if(mem_mask == 0x00ff) offset++;
switch(offset)
{
case 0x100+16:
- m_dp8390->dp8390_cs(ASSERT_LINE);
- data = m_dp8390->dp8390_r(space, offset, mem_mask);
- data = ((data & 0x00ff) << 8) | ((data & 0xff00) >> 8);
+ data = m_dp8390->remote_read();
+ data = swapendian_int16(data);
return data;
case 0x100+31:
m_dp8390->dp8390_reset(CLEAR_LINE);
@@ -83,29 +85,26 @@ READ16_MEMBER(x68k_neptune_device::x68k_neptune_port_r)
return 0;
}
-WRITE16_MEMBER(x68k_neptune_device::x68k_neptune_port_w)
+void x68k_neptune_device::x68k_neptune_port_w(offs_t offset, uint16_t data, uint16_t mem_mask)
{
if(offset >= 0x100+32 || offset < 0x100)
return;
if(offset < 0x100+16)
{
- m_dp8390->dp8390_cs(CLEAR_LINE);
if(mem_mask == 0x00ff)
{
data <<= 8;
offset++;
}
- m_dp8390->dp8390_w(space, offset, data>>8, 0xff);
- if(mem_mask == 0xffff) m_dp8390->dp8390_w(space, offset+1, data & 0xff, 0xff);
+ m_dp8390->cs_write(offset, data>>8);
+ if(mem_mask == 0xffff) m_dp8390->cs_write(offset+1, data & 0xff);
return;
}
//if(mem_mask == 0x00ff) offset++;
switch(offset)
{
case 0x100+16:
- m_dp8390->dp8390_cs(ASSERT_LINE);
- data = ((data & 0x00ff) << 8) | ((data & 0xff00) >> 8);
- m_dp8390->dp8390_w(space, offset, data, mem_mask);
+ m_dp8390->remote_write(swapendian_int16(data));
return;
case 0x100+31:
m_dp8390->dp8390_reset(ASSERT_LINE);
@@ -116,7 +115,7 @@ WRITE16_MEMBER(x68k_neptune_device::x68k_neptune_port_w)
return;
}
-READ8_MEMBER(x68k_neptune_device::x68k_neptune_mem_read)
+uint8_t x68k_neptune_device::x68k_neptune_mem_read(offs_t offset)
{
if(offset < 32) return m_prom[offset>>1];
if((offset < (16*1024)) || (offset >= (32*1024)))
@@ -127,7 +126,7 @@ READ8_MEMBER(x68k_neptune_device::x68k_neptune_mem_read)
return m_board_ram[offset - (16*1024)];
}
-WRITE8_MEMBER(x68k_neptune_device::x68k_neptune_mem_write)
+void x68k_neptune_device::x68k_neptune_mem_write(offs_t offset, uint8_t data)
{
if((offset < (16*1024)) || (offset >= (32*1024)))
{
@@ -137,7 +136,7 @@ WRITE8_MEMBER(x68k_neptune_device::x68k_neptune_mem_write)
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_neptunex.h b/src/devices/bus/x68k/x68k_neptunex.h
index 0684193e2ac..926dee3e76b 100644
--- a/src/devices/bus/x68k/x68k_neptunex.h
+++ b/src/devices/bus/x68k/x68k_neptunex.h
@@ -27,21 +27,21 @@ public:
// construction/destruction
x68k_neptune_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
- DECLARE_READ16_MEMBER(x68k_neptune_port_r);
- DECLARE_WRITE16_MEMBER(x68k_neptune_port_w);
+ uint16_t x68k_neptune_port_r(offs_t offset, uint16_t mem_mask = ~0);
+ void x68k_neptune_port_w(offs_t offset, uint16_t data, uint16_t mem_mask = ~0);
protected:
// device-level overrides
- virtual void device_add_mconfig(machine_config &config) override;
- virtual void device_start() override;
- virtual void device_reset() override;
+ 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;
// device_x68k_expansion_card_interface overrides
virtual uint8_t iack2() override;
private:
- DECLARE_READ8_MEMBER(x68k_neptune_mem_read);
- DECLARE_WRITE8_MEMBER(x68k_neptune_mem_write);
+ uint8_t x68k_neptune_mem_read(offs_t offset);
+ void x68k_neptune_mem_write(offs_t offset, uint8_t data);
void x68k_neptune_irq_w(int state);
x68k_expansion_slot_device *m_slot;
diff --git a/src/devices/bus/x68k/x68k_scsiext.cpp b/src/devices/bus/x68k/x68k_scsiext.cpp
index b4233875f1e..dbf1e9a04cd 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,43 +35,57 @@ 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(10'000'000 / 2); // 10MHz clock from bus
+ 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")
+ , m_drq(false)
{
}
void x68k_scsiext_device::device_start()
{
+ save_item(NAME(m_drq));
+
m_slot = dynamic_cast<x68k_expansion_slot_device *>(owner());
- m_slot->space().install_read_bank(0xea0020,0xea1fff,"scsi_ext");
- m_slot->space().unmap_write(0xea0020,0xea1fff);
- uint8_t *ROM = machine().root_device().memregion(subtag("scsiexrom").c_str())->base();
- machine().root_device().membank("scsi_ext")->set_base(ROM);
+ m_slot->space().install_rom(0xea0020,0xea1fff, m_rom.target());
+ m_slot->space().unmap_write(0xea0020,0xea1fff);
+ m_slot->space().install_device(0xea0000, 0xea001f, *m_spc, &mb89352_device::map, 0x00ff00ff);
-m_slot->space().install_readwrite_handler(0xea0000,0xea001f,read8_delegate(FUNC(x68k_scsiext_device::register_r),this),write8_delegate(FUNC(x68k_scsiext_device::register_w),this),0x00ff00ff);
+ // replace data register handlers with DMA-aware glue
+ m_slot->space().install_readwrite_handler(0xea0015, 0xea0015,
+ emu::rw_delegate(*this, FUNC(x68k_scsiext_device::data_r)),
+ emu::rw_delegate(*this, FUNC(x68k_scsiext_device::data_w)));
}
void x68k_scsiext_device::device_reset()
@@ -81,7 +94,8 @@ void x68k_scsiext_device::device_reset()
void x68k_scsiext_device::irq_w(int state)
{
- m_slot->irq2_w(state); // correct? Or perhaps selectable?
+ // TODO: jumper-configurable IRQ2/IRQ4
+ m_slot->irq2_w(state);
}
uint8_t x68k_scsiext_device::iack2()
@@ -91,15 +105,36 @@ uint8_t x68k_scsiext_device::iack2()
void x68k_scsiext_device::drq_w(int state)
{
- // TODO
+ m_drq = bool(state);
}
-READ8_MEMBER(x68k_scsiext_device::register_r)
+u8 x68k_scsiext_device::data_r()
{
- return m_spc->mb89352_r(space,offset);
+ // check for DMA cycle
+ if (m_slot->exown() && !machine().side_effects_disabled())
+ {
+ // negate #DTACK if not requesting a DMA transfer
+ if (!m_drq)
+ m_slot->dtack_w(1);
+
+ return m_spc->dma_r();
+ }
+ else
+ return m_spc->dreg_r();
+
}
-WRITE8_MEMBER(x68k_scsiext_device::register_w)
+void x68k_scsiext_device::data_w(u8 data)
{
- m_spc->mb89352_w(space,offset,data);
+ // check for DMA cycle
+ if (m_slot->exown())
+ {
+ // negate #DTACK if not requesting a DMA transfer
+ if (!m_drq)
+ m_slot->dtack_w(1);
+ else
+ m_spc->dma_w(data);
+ }
+ else
+ m_spc->dreg_w(data);
}
diff --git a/src/devices/bus/x68k/x68k_scsiext.h b/src/devices/bus/x68k/x68k_scsiext.h
index 19dd534d88b..8bd66a52a70 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,27 +21,29 @@ public:
// construction/destruction
x68k_scsiext_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
- DECLARE_READ8_MEMBER(register_r);
- DECLARE_WRITE8_MEMBER(register_w);
-
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;
+ // 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;
+ virtual const tiny_rom_entry *device_rom_region() const override ATTR_COLD;
- // device_x68k_expansion_card_interface overrides
+ // device_x68k_expansion_card_interface implementation
virtual uint8_t iack2() override;
private:
void irq_w(int state);
void drq_w(int state);
+ u8 data_r();
+ void data_w(u8 data);
+
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;
+
+ bool m_drq;
};
// device type definition
diff --git a/src/devices/bus/x68k/x68kexp.cpp b/src/devices/bus/x68k/x68kexp.cpp
index 05fa90e9a0d..cd83867017e 100644
--- a/src/devices/bus/x68k/x68kexp.cpp
+++ b/src/devices/bus/x68k/x68kexp.cpp
@@ -19,8 +19,8 @@ DEFINE_DEVICE_TYPE(X68K_EXPANSION_SLOT, x68k_expansion_slot_device, "x68k_expans
//**************************************************************************
-device_x68k_expansion_card_interface::device_x68k_expansion_card_interface(const machine_config &mconfig, device_t &device)
- : device_slot_card_interface(mconfig, device)
+device_x68k_expansion_card_interface::device_x68k_expansion_card_interface(const machine_config &mconfig, device_t &device) :
+ device_interface(device, "x68kexp")
{
}
@@ -47,12 +47,13 @@ uint8_t device_x68k_expansion_card_interface::iack4()
x68k_expansion_slot_device::x68k_expansion_slot_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) :
device_t(mconfig, X68K_EXPANSION_SLOT, tag, owner, clock),
- device_slot_interface(mconfig, *this),
+ device_single_card_slot_interface<device_x68k_expansion_card_interface>(mconfig, *this),
m_space(*this, finder_base::DUMMY_TAG, -1),
m_out_irq2_cb(*this),
m_out_irq4_cb(*this),
m_out_nmi_cb(*this),
m_out_reset_cb(*this),
+ m_out_dtack_cb(*this),
m_card(nullptr)
{
}
@@ -67,26 +68,14 @@ x68k_expansion_slot_device::~x68k_expansion_slot_device()
void x68k_expansion_slot_device::device_start()
{
- m_card = dynamic_cast<device_x68k_expansion_card_interface *>(get_card_device());
+ save_item(NAME(m_exown));
- // 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();
+ m_card = get_card_device();
}
-//-------------------------------------------------
-// device_reset - device-specific reset
-//-------------------------------------------------
-
-void x68k_expansion_slot_device::device_reset()
-{
-}
-
-
-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); }
+void x68k_expansion_slot_device::dtack_w(int state) { m_out_dtack_cb(state); }
diff --git a/src/devices/bus/x68k/x68kexp.h b/src/devices/bus/x68k/x68kexp.h
index a42aa3e2fd3..a4638de1157 100644
--- a/src/devices/bus/x68k/x68kexp.h
+++ b/src/devices/bus/x68k/x68kexp.h
@@ -68,20 +68,13 @@
//**************************************************************************
-// CONSTANTS
-//**************************************************************************
-
-#define X68K_EXP_SLOT_TAG "x68kexp"
-
-
-//**************************************************************************
// TYPE DEFINITIONS
//**************************************************************************
// ======================> device_x68k_expansion_card_interface
// class representing interface-specific live x68k_expansion card
-class device_x68k_expansion_card_interface : public device_slot_card_interface
+class device_x68k_expansion_card_interface : public device_interface
{
public:
// construction/destruction
@@ -100,7 +93,7 @@ protected:
// ======================> x68k_expansion_slot_device
-class x68k_expansion_slot_device : public device_t, public device_slot_interface
+class x68k_expansion_slot_device : public device_t, public device_single_card_slot_interface<device_x68k_expansion_card_interface>
{
public:
// construction/destruction
@@ -122,30 +115,37 @@ public:
auto out_irq4_callback() { return m_out_irq4_cb.bind(); }
auto out_nmi_callback() { return m_out_nmi_cb.bind(); }
auto out_reset_callback() { return m_out_reset_cb.bind(); }
+ auto out_dtack_callback() { return m_out_dtack_cb.bind(); }
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);
+ void dtack_w(int state);
+ bool exown() const { return m_exown; }
uint8_t iack2() { return (m_card != nullptr) ? m_card->iack2() : 0x18; }
uint8_t iack4() { return (m_card != nullptr) ? m_card->iack4() : 0x18; }
+ void exown_w(int state) { m_exown = !state; }
protected:
- // device-level overrides
- virtual void device_start() override;
- virtual void device_reset() override;
+ // device_t implementation
+ virtual void device_start() override ATTR_COLD;
required_address_space m_space;
+private:
devcb_write_line m_out_irq2_cb;
devcb_write_line m_out_irq4_cb;
devcb_write_line m_out_nmi_cb;
devcb_write_line m_out_reset_cb;
+ devcb_write_line m_out_dtack_cb;
device_x68k_expansion_card_interface *m_card;
+
+ bool m_exown;
};
diff --git a/src/devices/bus/z29_kbd/he191_3425.cpp b/src/devices/bus/z29_kbd/he191_3425.cpp
new file mode 100644
index 00000000000..bf44f34610d
--- /dev/null
+++ b/src/devices/bus/z29_kbd/he191_3425.cpp
@@ -0,0 +1,239 @@
+// license:BSD-3-Clause
+// copyright-holders:AJR
+/***************************************************************************
+
+ Heath HE 191-3425 keyboard
+
+ This 91-key detached keyboard is standard issue for the H-29 (Z-29)
+ terminal. Its schematics are also included in the MDT 60 Service
+ Manual.
+
+***************************************************************************/
+
+#include "emu.h"
+#include "he191_3425.h"
+
+#include "cpu/mcs48/mcs48.h"
+#include "machine/rescap.h"
+#include "speaker.h"
+
+
+DEFINE_DEVICE_TYPE(HE191_3425, he191_3425_device, "he191_3425", "Heath HE 191-3425 Keyboard")
+
+he191_3425_device::he191_3425_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock)
+ : device_t(mconfig, HE191_3425, tag, owner, clock)
+ , device_z29_keyboard_interface(mconfig, *this)
+ , m_mcu(*this, "mcu")
+ , m_buzzer(*this, "buzzer")
+ , m_matrix(*this, {"B1", "B2", "B3", "B4", "B5", "B6", "B7", "B8", "B9", "B11", "B13", "B14"})
+ , m_modifiers(*this, "MODIFIERS")
+ , m_leds(*this, "led%u", 1U)
+ , m_select(0)
+ , m_recv_data(true)
+{
+}
+
+void he191_3425_device::device_resolve_objects()
+{
+ m_leds.resolve();
+}
+
+void he191_3425_device::device_start()
+{
+ m_leds[0] = 1; // L1: Power
+
+ save_item(NAME(m_select));
+ save_item(NAME(m_recv_data));
+}
+
+void he191_3425_device::receive_data(bool state)
+{
+ machine().scheduler().synchronize(timer_expired_delegate(FUNC(he191_3425_device::receive_data_synced), this), state);
+}
+
+TIMER_CALLBACK_MEMBER(he191_3425_device::receive_data_synced)
+{
+ m_recv_data = param;
+}
+
+u8 he191_3425_device::mcu_pa_r()
+{
+ return m_select < 12 ? m_matrix[m_select]->read() : 0xff;
+}
+
+void he191_3425_device::mcu_pb_w(u8 data)
+{
+ transmit_data(!BIT(data, 3));
+ m_leds[1] = !BIT(data, 4); // L2: Keyboard Lock
+ m_leds[2] = !BIT(data, 5); // L3: Off/Line
+ m_leds[3] = !BIT(data, 6); // L4: Caps Lock
+ m_buzzer->set_state(BIT(data, 7));
+}
+
+void he191_3425_device::mcu_pc_w(u8 data)
+{
+ m_select = data & 0xf;
+}
+
+int he191_3425_device::mcu_t1_r()
+{
+ return m_recv_data;
+}
+
+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);
+}
+
+
+static INPUT_PORTS_START(he191_3425)
+ PORT_START("B1")
+ 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(DEL_PAD)) PORT_CODE(KEYCODE_DEL_PAD)
+ PORT_BIT(0x04, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CHAR(UCHAR_MAMEKEY(0_PAD)) PORT_CODE(KEYCODE_0_PAD)
+ 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_CHAR('0') PORT_CHAR(')') PORT_CODE(KEYCODE_0)
+ PORT_BIT(0x20, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CHAR('o') PORT_CHAR('O') PORT_CODE(KEYCODE_O)
+ 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('/') PORT_CHAR('?') PORT_CODE(KEYCODE_SLASH)
+
+ PORT_START("B2")
+ PORT_BIT(0x01, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("Keypad 3 DL") PORT_CHAR(UCHAR_MAMEKEY(3_PAD)) PORT_CODE(KEYCODE_3_PAD)
+ PORT_BIT(0x02, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CHAR(UCHAR_MAMEKEY(2_PAD)) PORT_CODE(KEYCODE_2_PAD)
+ PORT_BIT(0x04, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("Keypad 1 IL") PORT_CHAR(UCHAR_MAMEKEY(1_PAD)) PORT_CODE(KEYCODE_1_PAD)
+ PORT_BIT(0x08, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CHAR(UCHAR_MAMEKEY(F9)) PORT_CODE(KEYCODE_F9)
+ 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('i') PORT_CHAR('I') PORT_CODE(KEYCODE_I)
+ PORT_BIT(0x40, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CHAR('l') PORT_CHAR('L') PORT_CODE(KEYCODE_L)
+ PORT_BIT(0x80, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CHAR('.') PORT_CHAR('>') PORT_CODE(KEYCODE_STOP)
+
+ PORT_START("B3")
+ PORT_BIT(0x01, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CHAR(UCHAR_MAMEKEY(6_PAD)) PORT_CODE(KEYCODE_6_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_CHAR(UCHAR_MAMEKEY(4_PAD)) PORT_CODE(KEYCODE_4_PAD)
+ 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('8') PORT_CHAR('*') PORT_CODE(KEYCODE_8)
+ PORT_BIT(0x20, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CHAR('u') PORT_CHAR('U') PORT_CODE(KEYCODE_U)
+ PORT_BIT(0x40, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CHAR('k') PORT_CHAR('K') PORT_CODE(KEYCODE_K)
+ PORT_BIT(0x80, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CHAR(',') PORT_CHAR('<') PORT_CODE(KEYCODE_COMMA)
+
+ PORT_START("B4")
+ PORT_BIT(0x01, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("Keypad 9 DC") PORT_CHAR(UCHAR_MAMEKEY(9_PAD)) PORT_CODE(KEYCODE_9_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_NAME("Keypad 7 IC") PORT_CHAR(UCHAR_MAMEKEY(7_PAD)) PORT_CODE(KEYCODE_7_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_CHAR('7') PORT_CHAR('&') PORT_CODE(KEYCODE_7)
+ PORT_BIT(0x20, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CHAR('y') PORT_CHAR('Y') PORT_CODE(KEYCODE_Y)
+ PORT_BIT(0x40, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CHAR('j') PORT_CHAR('J') PORT_CODE(KEYCODE_J)
+ PORT_BIT(0x80, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CHAR('m') PORT_CHAR('M') PORT_CODE(KEYCODE_M)
+
+ PORT_START("B5")
+ PORT_BIT(0x01, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("Line Feed") PORT_CHAR(0x0a) PORT_CODE(KEYCODE_RALT)
+ PORT_BIT(0x02, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("Help") PORT_CODE(KEYCODE_F10)
+ PORT_BIT(0x04, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("Space Bar") PORT_CHAR(' ') PORT_CODE(KEYCODE_SPACE)
+ 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_CHAR('6') PORT_CHAR('^') PORT_CODE(KEYCODE_6)
+ PORT_BIT(0x20, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CHAR('t') PORT_CHAR('T') PORT_CODE(KEYCODE_T)
+ PORT_BIT(0x40, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CHAR('h') PORT_CHAR('H') PORT_CODE(KEYCODE_H)
+ PORT_BIT(0x80, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CHAR('n') PORT_CHAR('N') PORT_CODE(KEYCODE_N)
+
+ PORT_START("B6")
+ PORT_BIT(0x01, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CHAR('\\') PORT_CHAR('|') PORT_CODE(KEYCODE_RCONTROL) // to right of Return key
+ PORT_BIT(0x02, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("Return") PORT_CHAR(0x0d) PORT_CODE(KEYCODE_ENTER)
+ PORT_BIT(0x04, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CHAR('\'') PORT_CHAR('"') PORT_CODE(KEYCODE_QUOTE)
+ PORT_BIT(0x08, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CHAR(UCHAR_MAMEKEY(F5)) PORT_CODE(KEYCODE_F5)
+ 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('r') PORT_CHAR('R') PORT_CODE(KEYCODE_R)
+ PORT_BIT(0x40, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CHAR('g') PORT_CHAR('G') PORT_CODE(KEYCODE_G)
+ PORT_BIT(0x80, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CHAR('b') PORT_CHAR('B') PORT_CODE(KEYCODE_B)
+
+ PORT_START("B7")
+ PORT_BIT(0x01, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CHAR(']') PORT_CHAR('}') PORT_CODE(KEYCODE_CLOSEBRACE)
+ PORT_BIT(0x02, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CHAR('[') PORT_CHAR('{') PORT_CODE(KEYCODE_OPENBRACE)
+ PORT_BIT(0x04, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CHAR('p') PORT_CHAR('P') PORT_CODE(KEYCODE_P)
+ PORT_BIT(0x08, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CHAR(UCHAR_MAMEKEY(F4)) PORT_CODE(KEYCODE_F4)
+ 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('e') PORT_CHAR('E') PORT_CODE(KEYCODE_E)
+ PORT_BIT(0x40, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CHAR('f') PORT_CHAR('F') PORT_CODE(KEYCODE_F)
+ PORT_BIT(0x80, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CHAR('v') PORT_CHAR('V') PORT_CODE(KEYCODE_V)
+
+ PORT_START("B8")
+ PORT_BIT(0x01, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("Delete") PORT_CHAR(UCHAR_MAMEKEY(DEL)) PORT_CODE(KEYCODE_DEL) // to right of `/~ key
+ PORT_BIT(0x02, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CHAR(UCHAR_MAMEKEY(HOME)) PORT_CODE(KEYCODE_F11)
+ PORT_BIT(0x04, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CHAR(UCHAR_MAMEKEY(DOWN)) PORT_CODE(KEYCODE_DOWN) // between +/= and Back Space keys
+ PORT_BIT(0x08, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CHAR(UCHAR_MAMEKEY(F3)) PORT_CODE(KEYCODE_F3)
+ 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('w') PORT_CHAR('W') PORT_CODE(KEYCODE_W)
+ PORT_BIT(0x40, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CHAR('d') PORT_CHAR('D') PORT_CODE(KEYCODE_D)
+ PORT_BIT(0x80, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CHAR('c') PORT_CHAR('C') PORT_CODE(KEYCODE_C)
+
+ PORT_START("B9")
+ PORT_BIT(0x01, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("Back Space") PORT_CHAR(0x08) PORT_CODE(KEYCODE_BACKSPACE)
+ 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('-') PORT_CHAR('_') PORT_CODE(KEYCODE_MINUS)
+ PORT_BIT(0x08, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CHAR(UCHAR_MAMEKEY(F2)) PORT_CODE(KEYCODE_F2)
+ 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_CHAR('q') PORT_CHAR('Q') PORT_CODE(KEYCODE_Q)
+ PORT_BIT(0x40, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CHAR('s') PORT_CHAR('S') PORT_CODE(KEYCODE_S)
+ PORT_BIT(0x80, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CHAR('x') PORT_CHAR('X') PORT_CODE(KEYCODE_X)
+
+ PORT_START("B11")
+ 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(UCHAR_MAMEKEY(UP)) PORT_CODE(KEYCODE_UP)
+ PORT_BIT(0x04, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CHAR(UCHAR_MAMEKEY(LEFT)) PORT_CODE(KEYCODE_LEFT) // to right of Home key
+ PORT_BIT(0x08, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CHAR(UCHAR_MAMEKEY(F1)) PORT_CODE(KEYCODE_F1)
+ 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("Tab") PORT_CHAR('\t') PORT_CODE(KEYCODE_TAB)
+ PORT_BIT(0x40, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CHAR('a') PORT_CHAR('A') PORT_CODE(KEYCODE_A)
+ PORT_BIT(0x80, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CHAR('z') PORT_CHAR('Z') PORT_CODE(KEYCODE_Z)
+
+ PORT_START("B13")
+ 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_CHAR(UCHAR_MAMEKEY(MINUS_PAD)) PORT_CODE(KEYCODE_MINUS_PAD)
+ PORT_BIT(0x04, IP_ACTIVE_LOW, IPT_UNUSED)
+ PORT_BIT(0x08, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("No Scroll") PORT_CODE(KEYCODE_LALT)
+ PORT_BIT(0x10, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("Set Up") PORT_CODE(KEYCODE_ESC)
+ PORT_BIT(0x20, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("Esc") PORT_CHAR(0x1b) PORT_CODE(KEYCODE_TILDE)
+ PORT_BIT(0x40, IP_ACTIVE_LOW, IPT_UNUSED)
+ PORT_BIT(0x80, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("Erase") PORT_CODE(KEYCODE_F12)
+
+ PORT_START("B14")
+ PORT_BIT(0x01, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CHAR(UCHAR_MAMEKEY(CAPSLOCK)) PORT_CODE(KEYCODE_CAPSLOCK)
+ PORT_BIT(0xfe, IP_ACTIVE_LOW, IPT_UNUSED)
+
+ PORT_START("MODIFIERS")
+ PORT_BIT(0x01, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("Ctrl") PORT_CHAR(UCHAR_SHIFT_2) PORT_CODE(KEYCODE_LCONTROL)
+ PORT_BIT(0x02, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("Shift") PORT_CHAR(UCHAR_SHIFT_1) PORT_CODE(KEYCODE_LSHIFT) PORT_CODE(KEYCODE_RSHIFT) PORT_WRITE_LINE_MEMBER(FUNC(he191_3425_device::shift_reset))
+ PORT_BIT(0x04, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("Break Reset") PORT_CODE(KEYCODE_PAUSE) PORT_WRITE_LINE_MEMBER(FUNC(he191_3425_device::shift_reset)) // to right of Back Space key
+ PORT_BIT(0xf8, IP_ACTIVE_LOW, IPT_UNUSED)
+INPUT_PORTS_END
+
+ioport_constructor he191_3425_device::device_input_ports() const
+{
+ return INPUT_PORTS_NAME(he191_3425);
+}
+
+void he191_3425_device::device_add_mconfig(machine_config &config)
+{
+ i8021_device &mcu(I8021(config, m_mcu, 3.579545_MHz_XTAL));
+ mcu.bus_in_cb().set(FUNC(he191_3425_device::mcu_pa_r));
+ mcu.p1_in_cb().set_ioport("MODIFIERS");
+ mcu.p1_out_cb().set(FUNC(he191_3425_device::mcu_pb_w));
+ mcu.p2_out_cb().set(FUNC(he191_3425_device::mcu_pc_w));
+ mcu.t1_in_cb().set(FUNC(he191_3425_device::mcu_t1_r));
+
+ SPEAKER(config, "speaker").front_center();
+ BEEP(config, m_buzzer, 1'000'000'000 / PERIOD_OF_555_ASTABLE_NSEC(RES_R(510), RES_R(510), CAP_U(1)));
+ m_buzzer->add_route(ALL_OUTPUTS, "speaker", 1.0);
+}
+
+ROM_START(he191_3425)
+ ROM_REGION(0x400, "mcu", 0)
+ ROM_LOAD("p8021h-2155_444-100.z1", 0x000, 0x400, CRC(41e62f11) SHA1(4369de412cef907a3734ba511abe902d2d1b6cbf))
+ROM_END
+
+const tiny_rom_entry *he191_3425_device::device_rom_region() const
+{
+ return ROM_NAME(he191_3425);
+}
diff --git a/src/devices/bus/z29_kbd/he191_3425.h b/src/devices/bus/z29_kbd/he191_3425.h
new file mode 100644
index 00000000000..3969bbddcbb
--- /dev/null
+++ b/src/devices/bus/z29_kbd/he191_3425.h
@@ -0,0 +1,58 @@
+// license:BSD-3-Clause
+// copyright-holders:AJR
+
+#ifndef MAME_BUS_Z29_KBD_HE191_3425_H
+#define MAME_BUS_Z29_KBD_HE191_3425_H
+
+#pragma once
+
+#include "bus/z29_kbd/keyboard.h"
+#include "sound/beep.h"
+
+
+class he191_3425_device : public device_t, public device_z29_keyboard_interface
+{
+public:
+ // device type constructor
+ he191_3425_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock);
+
+ // miscellanous handlers
+ void shift_reset(int state);
+
+protected:
+ // device-level overrides
+ virtual void device_resolve_objects() override ATTR_COLD;
+ virtual void device_start() override ATTR_COLD;
+ virtual ioport_constructor device_input_ports() const override ATTR_COLD;
+ virtual void device_add_mconfig(machine_config &config) override ATTR_COLD;
+ virtual const tiny_rom_entry *device_rom_region() const override ATTR_COLD;
+
+ // device_z29_keyboard_interface overrides
+ virtual void receive_data(bool state) override;
+
+private:
+ // MCU port handlers
+ u8 mcu_pa_r();
+ void mcu_pb_w(u8 data);
+ void mcu_pc_w(u8 data);
+ int mcu_t1_r();
+
+ // misc. helpers
+ TIMER_CALLBACK_MEMBER(receive_data_synced);
+
+ // object finders
+ required_device<cpu_device> m_mcu;
+ required_device<beep_device> m_buzzer;
+ required_ioport_array<12> m_matrix;
+ required_ioport m_modifiers;
+ output_finder<4> m_leds;
+
+ // internal state
+ u8 m_select;
+ bool m_recv_data;
+};
+
+// device type declaration
+DECLARE_DEVICE_TYPE(HE191_3425, he191_3425_device)
+
+#endif // MAME_BUS_Z29_KBD_HE191_3425_H
diff --git a/src/devices/bus/z29_kbd/keyboard.cpp b/src/devices/bus/z29_kbd/keyboard.cpp
new file mode 100644
index 00000000000..670ab5804a8
--- /dev/null
+++ b/src/devices/bus/z29_kbd/keyboard.cpp
@@ -0,0 +1,111 @@
+// license:BSD-3-Clause
+// copyright-holders:AJR
+/***************************************************************************
+
+ Zenith Z-29 keyboard port
+
+ This supports the custom serial interface for the H-29/Z-29 and other
+ early Heath/Zenith terminals with detachable keyboards. (Keyboards for
+ later Zenith terminals such as the Z-49 use a standard asynchronous
+ serial protocol.)
+
+ All printable characters outside of the numeric keypad use standard
+ ASCII codes, as do Back Space, Line Feed, Return, Esc and Del. The
+ following codes are assigned to other keys:
+
+ 80 Up
+ 81 Down
+ 82 Left
+ 83 Right
+ 84 Home
+ 85 Erase
+ 86 Help
+ 87 No Scroll
+ 88 Set Up
+ 89 Break
+ 8A Caps Lock
+ 8B Tab
+ 8C Space Bar
+ 8F (Power On)
+ 90 0 (Keypad)
+ 91 1 (Keypad)
+ 92 2 (Keypad)
+ 93 3 (Keypad)
+ 94 4 (Keypad)
+ 95 5 (Keypad)
+ 96 6 (Keypad)
+ 97 7 (Keypad)
+ 98 8 (Keypad)
+ 99 9 (Keypad)
+ 9A . (Keypad)
+ 9B Enter (Keypad)
+ 9C - (Keypad)
+ 9D , (Keypad)
+ 9F 80 F1
+ 9F 81 F2
+ 9F 82 F3
+ 9F 83 F4
+ 9F 84 F5
+ 9F 85 F6
+ 9F 86 F7
+ 9F 87 F8
+ 9F 88 F9
+
+ Bit 6 is set in these codes when pressed with Shift, and bit 5 when
+ pressed with Ctrl.
+
+***************************************************************************/
+
+#include "emu.h"
+#include "keyboard.h"
+
+#include "he191_3425.h"
+#include "md_kbd.h"
+
+//**************************************************************************
+// Z-29 KEYBOARD PORT DEVICE
+//**************************************************************************
+
+DEFINE_DEVICE_TYPE(Z29_KEYBOARD, z29_keyboard_port_device, "z29_kbd", "Z-29 Keyboard Port")
+
+z29_keyboard_port_device::z29_keyboard_port_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock)
+ : device_t(mconfig, Z29_KEYBOARD, tag, owner, clock)
+ , device_single_card_slot_interface<device_z29_keyboard_interface>(mconfig, *this)
+ , m_keyin_callback(*this)
+ , m_reset_callback(*this)
+ , m_kbd(nullptr)
+{
+}
+
+void z29_keyboard_port_device::device_config_complete()
+{
+ m_kbd = get_card_device();
+}
+
+void z29_keyboard_port_device::device_start()
+{
+}
+
+//**************************************************************************
+// Z-29 KEYBOARD INTERFACE
+//**************************************************************************
+
+device_z29_keyboard_interface::device_z29_keyboard_interface(const machine_config &mconfig, device_t &device)
+ : device_interface(device, "z29kbd")
+ , m_port(device, DEVICE_SELF_OWNER)
+{
+}
+
+device_z29_keyboard_interface::~device_z29_keyboard_interface()
+{
+}
+
+//**************************************************************************
+// KEYBOARD OPTIONS
+//**************************************************************************
+
+void z29_keyboards(device_slot_interface &slot)
+{
+ slot.option_add("heath", HE191_3425);
+ slot.option_add("md", MD_KEYBOARD);
+}
diff --git a/src/devices/bus/z29_kbd/keyboard.h b/src/devices/bus/z29_kbd/keyboard.h
new file mode 100644
index 00000000000..42a102a4221
--- /dev/null
+++ b/src/devices/bus/z29_kbd/keyboard.h
@@ -0,0 +1,103 @@
+// license:BSD-3-Clause
+// copyright-holders:AJR
+/***************************************************************************
+
+ Zenith Z-29 keyboard port
+
+***************************************************************************/
+
+#ifndef MAME_BUS_Z29_KBD_KEYBOARD_H
+#define MAME_BUS_Z29_KBD_KEYBOARD_H
+
+#pragma once
+
+
+//**************************************************************************
+// TYPE DEFINITIONS
+//**************************************************************************
+
+// forward declaration
+class device_z29_keyboard_interface;
+
+// ======================> z29_keyboard_port_device
+
+class z29_keyboard_port_device : public device_t, public device_single_card_slot_interface<device_z29_keyboard_interface>
+{
+ friend class device_z29_keyboard_interface;
+
+public:
+ // construction/destruction
+ z29_keyboard_port_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock);
+ template <typename T>
+ z29_keyboard_port_device(const machine_config &mconfig, const char *tag, device_t *owner, T &&opts, const char *dflt)
+ : z29_keyboard_port_device(mconfig, tag, owner, 0U)
+ {
+ option_reset();
+ opts(*this);
+ set_default_option(dflt);
+ set_fixed(false);
+ }
+
+ // callback configuration
+ auto keyin_callback() { return m_keyin_callback.bind(); }
+ auto reset_callback() { return m_reset_callback.bind(); }
+
+ // line handler
+ void keyout_w(int state);
+
+protected:
+ // device_t implementation
+ virtual void device_config_complete() override;
+ virtual void device_start() override ATTR_COLD;
+
+ // called from keyboard
+ void transmit_data(bool state) { m_keyin_callback(state); }
+ void reset_from_keyboard(bool state) { m_reset_callback(state); }
+
+private:
+ // line callbacks
+ devcb_write_line m_keyin_callback;
+ devcb_write_line m_reset_callback;
+
+ // selected keyboard
+ device_z29_keyboard_interface *m_kbd;
+};
+
+// ======================> device_z29_keyboard_interface
+
+class device_z29_keyboard_interface : public device_interface
+{
+ friend class z29_keyboard_port_device;
+
+protected:
+ // construction/destruction
+ device_z29_keyboard_interface(const machine_config &mconfig, device_t &device);
+ virtual ~device_z29_keyboard_interface();
+
+ void transmit_data(bool state) { m_port->transmit_data(state); }
+ void reset_from_keyboard(bool state) { m_port->reset_from_keyboard(state); }
+
+ virtual void receive_data(bool state) = 0;
+
+private:
+ // parent port
+ required_device<z29_keyboard_port_device> m_port;
+};
+
+// device type definition
+DECLARE_DEVICE_TYPE(Z29_KEYBOARD, z29_keyboard_port_device)
+
+// standard options
+extern void z29_keyboards(device_slot_interface &slot);
+
+//**************************************************************************
+// INLINE FUNCTIONS
+//**************************************************************************
+
+inline void z29_keyboard_port_device::keyout_w(int state)
+{
+ if (m_kbd != nullptr)
+ m_kbd->receive_data(state);
+}
+
+#endif // MAME_BUS_Z29_KBD_KEYBOARD_H
diff --git a/src/devices/bus/z29_kbd/md_kbd.cpp b/src/devices/bus/z29_kbd/md_kbd.cpp
new file mode 100644
index 00000000000..dbe9c81f46f
--- /dev/null
+++ b/src/devices/bus/z29_kbd/md_kbd.cpp
@@ -0,0 +1,277 @@
+// license:BSD-3-Clause
+// copyright-holders:AJR
+/***************************************************************************
+
+ Micro-Decision keyboard
+
+ This 93-key keyboard was obtained with a Morrow MD3-P. The unit part
+ number is unknown, but "DEKU-0224-PHM-B" and "I/F PCB FOR 14515B" are
+ silkscreened on the component board.
+
+ Like the original Z-29 keyboard, it may also have been designed by
+ Heath/Zenith. It is missing the Erase, Set Up and Break keys (though
+ the first two are still recognized by the program), but has five
+ additional function keys instead.
+
+ Some clumsy coding suggests that the program was originally designed
+ for an 8048 operating in single-chip mode, with the 14515B and LS175
+ having being added to latch outputs also sent to the upper half of
+ Port 2.
+
+***************************************************************************/
+
+#include "emu.h"
+#include "md_kbd.h"
+
+#include "machine/rescap.h"
+#include "speaker.h"
+
+
+DEFINE_DEVICE_TYPE(MD_KEYBOARD, md_keyboard_device, "md_kbd", "Micro-Decision Keyboard")
+
+md_keyboard_device::md_keyboard_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock)
+ : device_t(mconfig, MD_KEYBOARD, tag, owner, clock)
+ , device_z29_keyboard_interface(mconfig, *this)
+ , m_mcu(*this, "mcu")
+ , m_buzzer(*this, "buzzer")
+ , m_matrix(*this, "S%u", 0U)
+ , m_leds(*this, "led%u", 1U)
+ , m_14515b_select(0)
+ , m_ls175_clock(true)
+ , m_recv_data(true)
+{
+}
+
+void md_keyboard_device::device_resolve_objects()
+{
+ m_leds.resolve();
+}
+
+void md_keyboard_device::device_start()
+{
+ save_item(NAME(m_14515b_select));
+ save_item(NAME(m_ls175_clock));
+ save_item(NAME(m_recv_data));
+}
+
+void md_keyboard_device::device_reset()
+{
+ ls175_w(0);
+}
+
+void md_keyboard_device::receive_data(bool state)
+{
+ machine().scheduler().synchronize(timer_expired_delegate(FUNC(md_keyboard_device::receive_data_synced), this), state);
+}
+
+TIMER_CALLBACK_MEMBER(md_keyboard_device::receive_data_synced)
+{
+ m_recv_data = param;
+}
+
+void md_keyboard_device::ls175_w(u8 data)
+{
+ m_leds[0] = !BIT(data, 7); // Caps Lock
+ m_leds[1] = !BIT(data, 5); // Keyboard lock?
+ m_buzzer->set_state(BIT(data, 6));
+}
+
+u8 md_keyboard_device::mcu_p1_r()
+{
+ return 0xc0 | m_matrix[m_14515b_select]->read();
+}
+
+void md_keyboard_device::mcu_p1_w(u8 data)
+{
+ transmit_data(!BIT(data, 7));
+ if (!m_ls175_clock && BIT(data, 6))
+ ls175_w(m_mcu->p2_r());
+ m_ls175_clock = BIT(data, 6);
+}
+
+int md_keyboard_device::mcu_t1_r()
+{
+ return m_recv_data;
+}
+
+void md_keyboard_device::mcu_movx_w(u8 data)
+{
+ m_14515b_select = (data >> 4) & 0x0f;
+}
+
+void md_keyboard_device::prog_map(address_map &map)
+{
+ map(0x000, 0xfff).rom().region("program", 0);
+}
+
+void md_keyboard_device::ext_map(address_map &map)
+{
+ map(0x00, 0x00).mirror(0xff).w(FUNC(md_keyboard_device::mcu_movx_w));
+}
+
+
+static INPUT_PORTS_START(md_kbd)
+
+ PORT_START("S0")
+ PORT_BIT(0x01, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CHAR('q') PORT_CHAR('Q') PORT_CODE(KEYCODE_Q)
+ PORT_BIT(0x02, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CHAR('g') PORT_CHAR('G') PORT_CODE(KEYCODE_G)
+ PORT_BIT(0x04, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CHAR(';') PORT_CHAR(':') PORT_CODE(KEYCODE_COLON)
+ PORT_BIT(0x08, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CHAR(UCHAR_MAMEKEY(0_PAD)) PORT_CODE(KEYCODE_0_PAD)
+ 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("Erase") // not actually on keyboard?
+
+ PORT_START("S1")
+ PORT_BIT(0x01, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CHAR('w') PORT_CHAR('W') PORT_CODE(KEYCODE_W)
+ PORT_BIT(0x02, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CHAR('b') PORT_CHAR('B') PORT_CODE(KEYCODE_B)
+ PORT_BIT(0x04, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CHAR(']') PORT_CHAR('}') PORT_CODE(KEYCODE_CLOSEBRACE)
+ PORT_BIT(0x08, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CHAR(UCHAR_MAMEKEY(9_PAD)) PORT_CODE(KEYCODE_9_PAD)
+ 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("Help") PORT_CODE(KEYCODE_F12)
+
+ PORT_START("S2")
+ PORT_BIT(0x01, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CHAR('e') PORT_CHAR('E') PORT_CODE(KEYCODE_E)
+ PORT_BIT(0x02, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CHAR('n') PORT_CHAR('N') PORT_CODE(KEYCODE_N)
+ 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_CHAR(UCHAR_MAMEKEY(8_PAD)) PORT_CODE(KEYCODE_8_PAD)
+ 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("Home Clear") PORT_CHAR(UCHAR_MAMEKEY(HOME)) PORT_CODE(KEYCODE_F11)
+
+ PORT_START("S3")
+ PORT_BIT(0x01, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CHAR('r') PORT_CHAR('R') PORT_CODE(KEYCODE_R)
+ PORT_BIT(0x02, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CHAR('m') PORT_CHAR('M') PORT_CODE(KEYCODE_M)
+ PORT_BIT(0x04, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CHAR('-') PORT_CHAR('_') PORT_CODE(KEYCODE_MINUS)
+ PORT_BIT(0x08, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CHAR(UCHAR_MAMEKEY(7_PAD)) PORT_CODE(KEYCODE_7_PAD)
+ PORT_BIT(0x10, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CHAR('7') PORT_CHAR('&') PORT_CODE(KEYCODE_7)
+ PORT_BIT(0x20, IP_ACTIVE_LOW, IPT_UNUSED)
+
+ PORT_START("S4")
+ PORT_BIT(0x01, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CHAR('f') PORT_CHAR('F') PORT_CODE(KEYCODE_F)
+ PORT_BIT(0x02, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CHAR('l') PORT_CHAR('L') PORT_CODE(KEYCODE_L)
+ 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_CHAR(UCHAR_MAMEKEY(6_PAD)) PORT_CODE(KEYCODE_6_PAD)
+ 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_NAME("No Scroll") PORT_CODE(KEYCODE_ESC)
+
+ PORT_START("S5")
+ PORT_BIT(0x01, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CHAR('d') PORT_CHAR('D') PORT_CODE(KEYCODE_D)
+ PORT_BIT(0x02, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CHAR('k') PORT_CHAR('K') PORT_CODE(KEYCODE_K)
+ PORT_BIT(0x04, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CHAR('`') PORT_CHAR('~') PORT_CODE(KEYCODE_BACKSLASH) // to right of +/=
+ PORT_BIT(0x08, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CHAR(UCHAR_MAMEKEY(5_PAD)) PORT_CODE(KEYCODE_5_PAD)
+ 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_NAME("Caps Lock") PORT_CHAR(UCHAR_MAMEKEY(CAPSLOCK)) PORT_CODE(KEYCODE_CAPSLOCK)
+
+ PORT_START("S6")
+ PORT_BIT(0x01, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CHAR('s') PORT_CHAR('S') PORT_CODE(KEYCODE_S)
+ PORT_BIT(0x02, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CHAR('j') PORT_CHAR('J') PORT_CODE(KEYCODE_J)
+ PORT_BIT(0x04, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CHAR('\'') PORT_CHAR('"') PORT_CODE(KEYCODE_QUOTE)
+ PORT_BIT(0x08, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CHAR(UCHAR_MAMEKEY(4_PAD)) PORT_CODE(KEYCODE_4_PAD)
+ 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_NAME("Del") PORT_CHAR(UCHAR_MAMEKEY(DEL)) PORT_CODE(KEYCODE_DEL)
+
+ PORT_START("S7")
+ PORT_BIT(0x01, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CHAR('a') PORT_CHAR('A') PORT_CODE(KEYCODE_A)
+ PORT_BIT(0x02, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CHAR('h') PORT_CHAR('H') PORT_CODE(KEYCODE_H)
+ PORT_BIT(0x04, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CHAR('p') PORT_CHAR('P') PORT_CODE(KEYCODE_P)
+ PORT_BIT(0x08, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CHAR(UCHAR_MAMEKEY(3_PAD)) PORT_CODE(KEYCODE_3_PAD)
+ 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(UP)) PORT_CODE(KEYCODE_UP)
+
+ PORT_START("S8")
+ PORT_BIT(0x01, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CHAR('z') PORT_CHAR('Z') PORT_CODE(KEYCODE_Z)
+ PORT_BIT(0x02, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CHAR('t') PORT_CHAR('T') PORT_CODE(KEYCODE_T)
+ PORT_BIT(0x04, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CHAR('o') PORT_CHAR('O') PORT_CODE(KEYCODE_O)
+ PORT_BIT(0x08, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CHAR(UCHAR_MAMEKEY(2_PAD)) PORT_CODE(KEYCODE_2_PAD)
+ 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_CHAR(UCHAR_MAMEKEY(DOWN)) PORT_CODE(KEYCODE_DOWN)
+
+ PORT_START("S9")
+ PORT_BIT(0x01, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CHAR('x') PORT_CHAR('X') PORT_CODE(KEYCODE_X)
+ PORT_BIT(0x02, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CHAR('y') PORT_CHAR('Y') PORT_CODE(KEYCODE_Y)
+ PORT_BIT(0x04, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CHAR('\\') PORT_CHAR('|') PORT_CODE(KEYCODE_RCONTROL)
+ PORT_BIT(0x08, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CHAR(UCHAR_MAMEKEY(1_PAD)) PORT_CODE(KEYCODE_1_PAD)
+ 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_CHAR(UCHAR_MAMEKEY(RIGHT)) PORT_CODE(KEYCODE_RIGHT)
+
+ PORT_START("S10")
+ PORT_BIT(0x01, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CHAR('c') PORT_CHAR('C') PORT_CODE(KEYCODE_C)
+ PORT_BIT(0x02, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CHAR('u') PORT_CHAR('U') PORT_CODE(KEYCODE_U)
+ 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_CHAR(UCHAR_MAMEKEY(COMMA_PAD)) PORT_CODE(KEYCODE_PLUS_PAD)
+ PORT_BIT(0x10, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("Esc") PORT_CHAR(0x1b) PORT_CODE(KEYCODE_TILDE)
+ PORT_BIT(0x20, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CHAR(UCHAR_MAMEKEY(LEFT)) PORT_CODE(KEYCODE_LEFT)
+
+ PORT_START("S11")
+ PORT_BIT(0x01, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CHAR('v') PORT_CHAR('V') PORT_CODE(KEYCODE_V)
+ PORT_BIT(0x02, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CHAR('i') PORT_CHAR('I') PORT_CODE(KEYCODE_I)
+ PORT_BIT(0x04, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CHAR('.') PORT_CHAR('>') PORT_CODE(KEYCODE_STOP)
+ 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_NAME("Tab") PORT_CHAR('\t') PORT_CODE(KEYCODE_TAB)
+ PORT_BIT(0x20, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CHAR('/') PORT_CHAR('?') PORT_CODE(KEYCODE_SLASH)
+
+ PORT_START("S12")
+ PORT_BIT(0x01, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CHAR(' ') PORT_CODE(KEYCODE_SPACE)
+ PORT_BIT(0x02, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("Return") PORT_CHAR(0x0d) PORT_CODE(KEYCODE_ENTER)
+ PORT_BIT(0x04, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("Keypad Enter +") PORT_CHAR(UCHAR_MAMEKEY(ENTER_PAD)) PORT_CODE(KEYCODE_ENTER_PAD)
+ PORT_BIT(0x08, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CHAR(UCHAR_MAMEKEY(MINUS_PAD)) PORT_CODE(KEYCODE_MINUS_PAD)
+ PORT_BIT(0x10, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("Line Feed") PORT_CHAR(0x0a) PORT_CODE(KEYCODE_RALT)
+ PORT_BIT(0x20, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("Back Space") PORT_CHAR(0x08) PORT_CODE(KEYCODE_BACKSPACE)
+
+ PORT_START("S13")
+ 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(F2)) PORT_CODE(KEYCODE_F2)
+ PORT_BIT(0x04, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CHAR(UCHAR_MAMEKEY(F3)) PORT_CODE(KEYCODE_F3)
+ PORT_BIT(0x08, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CHAR(UCHAR_MAMEKEY(F4)) PORT_CODE(KEYCODE_F4)
+ PORT_BIT(0x10, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CHAR(UCHAR_MAMEKEY(F5)) PORT_CODE(KEYCODE_F5)
+ PORT_BIT(0x20, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CHAR(UCHAR_MAMEKEY(F6)) PORT_CODE(KEYCODE_F6)
+
+ PORT_START("S14")
+ 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(F8)) PORT_CODE(KEYCODE_F8)
+ PORT_BIT(0x04, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CHAR(UCHAR_MAMEKEY(F9)) PORT_CODE(KEYCODE_F9)
+ PORT_BIT(0x08, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CHAR(UCHAR_MAMEKEY(F10)) PORT_CODE(KEYCODE_F10)
+ PORT_BIT(0x10, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("FA") PORT_CHAR(UCHAR_MAMEKEY(F11))
+ PORT_BIT(0x20, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("FB") PORT_CHAR(UCHAR_MAMEKEY(F12))
+
+ PORT_START("S15")
+ PORT_BIT(0x01, IP_ACTIVE_LOW, IPT_UNUSED)
+ PORT_BIT(0x02, IP_ACTIVE_LOW, IPT_UNUSED)
+ PORT_BIT(0x04, IP_ACTIVE_LOW, IPT_UNUSED)
+ PORT_BIT(0x08, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("Setup") // not actually on keyboard?
+ PORT_BIT(0x10, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("FD") PORT_CHAR(UCHAR_MAMEKEY(F14))
+ PORT_BIT(0x20, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("FC") PORT_CHAR(UCHAR_MAMEKEY(F13))
+
+ PORT_START("MODIFIERS")
+ PORT_BIT(0x04, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("Ctrl") PORT_CHAR(UCHAR_SHIFT_2) PORT_CODE(KEYCODE_LCONTROL)
+ PORT_BIT(0x08, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("Shift") PORT_CHAR(UCHAR_SHIFT_1) PORT_CODE(KEYCODE_LSHIFT) PORT_CODE(KEYCODE_RSHIFT)
+INPUT_PORTS_END
+
+ioport_constructor md_keyboard_device::device_input_ports() const
+{
+ return INPUT_PORTS_NAME(md_kbd);
+}
+
+void md_keyboard_device::device_add_mconfig(machine_config &config)
+{
+ // U4 is M5L8048-052P (internal ROM likely unused), but location is silkscreened "8035"
+ I8035(config, m_mcu, 3.579545_MHz_XTAL); // "CSA 3 58MT" resonator
+ m_mcu->set_addrmap(AS_PROGRAM, &md_keyboard_device::prog_map);
+ m_mcu->set_addrmap(AS_IO, &md_keyboard_device::ext_map);
+ m_mcu->p1_in_cb().set(FUNC(md_keyboard_device::mcu_p1_r));
+ m_mcu->p1_out_cb().set(FUNC(md_keyboard_device::mcu_p1_w));
+ m_mcu->p2_in_cb().set_ioport("MODIFIERS");
+ m_mcu->t1_in_cb().set(FUNC(md_keyboard_device::mcu_t1_r));
+
+ SPEAKER(config, "speaker").front_center();
+ BEEP(config, m_buzzer, 1'000'000'000 / PERIOD_OF_555_ASTABLE_NSEC(RES_R(510), RES_R(510), CAP_U(1)));
+ m_buzzer->add_route(ALL_OUTPUTS, "speaker", 1.0);
+}
+
+ROM_START(md_kbd)
+ ROM_REGION(0x1000, "program", 0)
+ ROM_LOAD("kb-rom_rev_3.4_27d4.u5", 0x0000, 0x1000, CRC(c34b606b) SHA1(20cf62fc31257b6c3e767152086f2604fead97bd)) // location marked "2716/2732"
+ROM_END
+
+const tiny_rom_entry *md_keyboard_device::device_rom_region() const
+{
+ return ROM_NAME(md_kbd);
+}
diff --git a/src/devices/bus/z29_kbd/md_kbd.h b/src/devices/bus/z29_kbd/md_kbd.h
new file mode 100644
index 00000000000..0822118aecd
--- /dev/null
+++ b/src/devices/bus/z29_kbd/md_kbd.h
@@ -0,0 +1,61 @@
+// license:BSD-3-Clause
+// copyright-holders:AJR
+
+#ifndef MAME_BUS_Z29_KBD_MD_KBD_H
+#define MAME_BUS_Z29_KBD_MD_KBD_H
+
+#pragma once
+
+#include "keyboard.h"
+#include "cpu/mcs48/mcs48.h"
+#include "sound/beep.h"
+
+class md_keyboard_device : public device_t, public device_z29_keyboard_interface
+{
+public:
+ // device type constructor
+ md_keyboard_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock);
+
+protected:
+ // device-level overrides
+ virtual void device_resolve_objects() override ATTR_COLD;
+ virtual void device_start() override ATTR_COLD;
+ virtual void device_reset() override ATTR_COLD;
+ virtual ioport_constructor device_input_ports() const override ATTR_COLD;
+ virtual void device_add_mconfig(machine_config &config) override ATTR_COLD;
+ virtual const tiny_rom_entry *device_rom_region() const override ATTR_COLD;
+
+ // device_z29_keyboard_interface overrides
+ virtual void receive_data(bool state) override;
+
+private:
+ // MCU handlers
+ u8 mcu_p1_r();
+ void mcu_p1_w(u8 data);
+ int mcu_t1_r();
+ void mcu_movx_w(u8 data);
+
+ // misc. helpers
+ TIMER_CALLBACK_MEMBER(receive_data_synced);
+ void ls175_w(u8 data);
+
+ // address maps
+ void prog_map(address_map &map) ATTR_COLD;
+ void ext_map(address_map &map) ATTR_COLD;
+
+ // object finders
+ required_device<mcs48_cpu_device> m_mcu;
+ required_device<beep_device> m_buzzer;
+ required_ioport_array<16> m_matrix;
+ output_finder<2> m_leds;
+
+ // internal state
+ u8 m_14515b_select;
+ bool m_ls175_clock;
+ bool m_recv_data;
+};
+
+// device type declaration
+DECLARE_DEVICE_TYPE(MD_KEYBOARD, md_keyboard_device)
+
+#endif // MAME_BUS_Z29_KBD_MD_KBD_H
diff --git a/src/devices/bus/z88/flash.cpp b/src/devices/bus/z88/flash.cpp
index ee92f351ec7..bda80f4cff6 100644
--- a/src/devices/bus/z88/flash.cpp
+++ b/src/devices/bus/z88/flash.cpp
@@ -37,10 +37,27 @@ z88_1024k_flash_device::z88_1024k_flash_device(const machine_config &mconfig, co
: device_t(mconfig, Z88_1024K_FLASH, tag, owner, clock)
, device_z88cart_interface(mconfig, *this)
, m_flash(*this, FLASH_TAG)
+ , m_region(*this, FLASH_TAG)
{
}
//-------------------------------------------------
+// rom_region - device-specific ROM region
+//-------------------------------------------------
+
+ROM_START( z88_1024k_flash )
+ ROM_REGION( 0x100000, FLASH_TAG, ROMREGION_ERASEFF )
+ // this region is required to initialize the flash device with the data loaded from the cartridge interface
+ROM_END
+
+
+const tiny_rom_entry *z88_1024k_flash_device::device_rom_region() const
+{
+ return ROM_NAME( z88_1024k_flash );
+}
+
+
+//-------------------------------------------------
// device_start - device-specific startup
//-------------------------------------------------
@@ -64,14 +81,14 @@ void z88_1024k_flash_device::device_add_mconfig(machine_config &config)
uint8_t* z88_1024k_flash_device::get_cart_base()
{
- return m_flash->base();
+ return m_region->base();
}
/*-------------------------------------------------
read
-------------------------------------------------*/
-READ8_MEMBER(z88_1024k_flash_device::read)
+uint8_t z88_1024k_flash_device::read(offs_t offset)
{
return m_flash->read(offset & (get_cart_size() - 1));
}
@@ -80,7 +97,7 @@ READ8_MEMBER(z88_1024k_flash_device::read)
write
-------------------------------------------------*/
-WRITE8_MEMBER(z88_1024k_flash_device::write)
+void z88_1024k_flash_device::write(offs_t offset, uint8_t data)
{
m_flash->write(offset & (get_cart_size() - 1), data);
}
diff --git a/src/devices/bus/z88/flash.h b/src/devices/bus/z88/flash.h
index b26be3b515d..97851421542 100644
--- a/src/devices/bus/z88/flash.h
+++ b/src/devices/bus/z88/flash.h
@@ -23,17 +23,21 @@ public:
protected:
// device-level overrides
- virtual void device_add_mconfig(machine_config &config) override;
- virtual void device_start() override;
+ virtual void device_add_mconfig(machine_config &config) override ATTR_COLD;
+ virtual void device_start() override ATTR_COLD;
+
+ // optional information overrides
+ virtual const tiny_rom_entry *device_rom_region() const override ATTR_COLD;
// z88cart_interface overrides
- virtual DECLARE_READ8_MEMBER(read) override;
- virtual DECLARE_WRITE8_MEMBER(write) override;
+ 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 0x100000; }
private:
required_device<intelfsh8_device> m_flash;
+ required_memory_region m_region;
};
// device type definition
diff --git a/src/devices/bus/z88/ram.cpp b/src/devices/bus/z88/ram.cpp
index 69ddd3125a6..c697e40c7b0 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 ATTR_COLD;
+
+ // 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
@@ -38,7 +117,10 @@ z88_32k_ram_device::z88_32k_ram_device(const machine_config &mconfig, const char
}
z88_32k_ram_device::z88_32k_ram_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_z88cart_interface(mconfig, *this), m_ram(nullptr)
+ : device_t(mconfig, type, tag, owner, clock)
+ , device_nvram_interface(mconfig, *this)
+ , device_z88cart_interface(mconfig, *this)
+ , m_ram(nullptr)
{
}
@@ -93,7 +175,7 @@ uint8_t* z88_32k_ram_device::get_cart_base()
read
-------------------------------------------------*/
-READ8_MEMBER(z88_32k_ram_device::read)
+uint8_t z88_32k_ram_device::read(offs_t offset)
{
return m_ram[offset & (get_cart_size() - 1)];
}
@@ -102,7 +184,19 @@ READ8_MEMBER(z88_32k_ram_device::read)
write
-------------------------------------------------*/
-WRITE8_MEMBER(z88_32k_ram_device::write)
+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 357959064a8..c99ab03676f 100644
--- a/src/devices/bus/z88/ram.h
+++ b/src/devices/bus/z88/ram.h
@@ -7,79 +7,10 @@
#include "z88.h"
-//**************************************************************************
-// TYPE DEFINITIONS
-//**************************************************************************
-
-// ======================> z88_32k_ram_device
-
-class z88_32k_ram_device : public device_t,
- 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;
-
- // z88cart_interface overrides
- virtual DECLARE_READ8_MEMBER(read) override;
- virtual DECLARE_WRITE8_MEMBER(write) 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 ea1feb603f4..b62f380f0c9 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 ATTR_COLD;
+
+ // 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
@@ -37,7 +111,12 @@ z88_32k_rom_device::z88_32k_rom_device(const machine_config &mconfig, const char
}
z88_32k_rom_device::z88_32k_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_z88cart_interface(mconfig, *this), m_rom(nullptr)
+ : device_t(mconfig, type, tag, owner, clock)
+ , device_nvram_interface(mconfig, *this)
+ , device_z88cart_interface(mconfig, *this)
+ , m_rom(nullptr)
+ , m_vpp_state(0)
+ , m_modified(false)
{
}
@@ -66,6 +145,10 @@ z88_256k_rom_device::z88_256k_rom_device(const machine_config &mconfig, const ch
void z88_32k_rom_device::device_start()
{
m_rom = machine().memory().region_alloc(tag(), get_cart_size(), 1, ENDIANNESS_LITTLE)->base();
+ std::fill_n(m_rom, get_cart_size(), 0xff);
+
+ save_item(NAME(m_vpp_state));
+ save_item(NAME(m_modified));
}
/*-------------------------------------------------
@@ -81,7 +164,34 @@ uint8_t* z88_32k_rom_device::get_cart_base()
read
-------------------------------------------------*/
-READ8_MEMBER(z88_32k_rom_device::read)
+uint8_t z88_32k_rom_device::read(offs_t offset)
{
return m_rom[offset & (get_cart_size() - 1)];
}
+
+/*-------------------------------------------------
+ write
+-------------------------------------------------*/
+
+void z88_32k_rom_device::write(offs_t offset, uint8_t data)
+{
+ if (m_vpp_state)
+ {
+ const uint32_t offset_mask = get_cart_size() - 1;
+ if (m_rom[offset & offset_mask] & ~data)
+ m_modified = true;
+
+ m_rom[offset & offset_mask] &= 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 9508efbef14..05c33fd814d 100644
--- a/src/devices/bus/z88/rom.h
+++ b/src/devices/bus/z88/rom.h
@@ -7,64 +7,9 @@
#include "z88.h"
-//**************************************************************************
-// TYPE DEFINITIONS
-//**************************************************************************
-
-// ======================> z88_32k_rom_device
-
-class z88_32k_rom_device : public device_t,
- 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;
-
- // z88cart_interface overrides
- virtual DECLARE_READ8_MEMBER(read) override;
- virtual uint8_t* get_cart_base() override;
- virtual uint32_t get_cart_size() override { return 0x8000; }
-
-protected:
- // internal state
- uint8_t * m_rom;
-};
-
-// ======================> 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 0x200000; }
-};
-
-// 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 bed0141b012..fe77274a8ed 100644
--- a/src/devices/bus/z88/z88.cpp
+++ b/src/devices/bus/z88/z88.cpp
@@ -26,7 +26,7 @@ DEFINE_DEVICE_TYPE(Z88CART_SLOT, z88cart_slot_device, "z88cart_slot", "Z88 Cartr
//**************************************************************************
-// Z88 cartridges Interface
+// Z88 Cartridge Interface
//**************************************************************************
//-------------------------------------------------
@@ -34,7 +34,7 @@ DEFINE_DEVICE_TYPE(Z88CART_SLOT, z88cart_slot_device, "z88cart_slot", "Z88 Cartr
//-------------------------------------------------
device_z88cart_interface::device_z88cart_interface(const machine_config &mconfig, device_t &device)
- : device_slot_card_interface(mconfig, device)
+ : device_interface(device, "z88cart")
{
}
@@ -57,8 +57,8 @@ device_z88cart_interface::~device_z88cart_interface()
//-------------------------------------------------
z88cart_slot_device::z88cart_slot_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
: device_t(mconfig, Z88CART_SLOT, tag, owner, clock)
- , device_image_interface(mconfig, *this)
- , device_slot_interface(mconfig, *this)
+ , device_cartrom_image_interface(mconfig, *this)
+ , device_single_card_slot_interface<device_z88cart_interface>(mconfig, *this)
, m_out_flp_cb(*this)
, m_cart(nullptr)
, m_flp_timer(nullptr)
@@ -71,65 +71,54 @@ z88cart_slot_device::z88cart_slot_device(const machine_config &mconfig, const ch
void z88cart_slot_device::device_start()
{
- m_cart = dynamic_cast<device_z88cart_interface *>(get_card_device());
+ m_cart = get_card_device();
- // resolve callbacks
- m_out_flp_cb.resolve_safe();
-
- m_flp_timer = timer_alloc(TIMER_FLP_CLEAR);
+ m_flp_timer = timer_alloc(FUNC(z88cart_slot_device::close_flap), this);
m_flp_timer->reset();
}
//-------------------------------------------------
-// device_timer - handler timer events
+// close_flap
//-------------------------------------------------
-void z88cart_slot_device::device_timer(emu_timer &timer, device_timer_id id, int param, void *ptr)
+TIMER_CALLBACK_MEMBER(z88cart_slot_device::close_flap)
{
- if (id == TIMER_FLP_CLEAR)
- {
- // close the flap
- m_out_flp_cb(CLEAR_LINE);
- }
+ // close the flap
+ m_out_flp_cb(CLEAR_LINE);
}
/*-------------------------------------------------
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);
}
}
// open the flap
m_out_flp_cb(ASSERT_LINE);
- // setup the timer for close the flap
+ // 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());
}
@@ -151,7 +140,7 @@ void z88cart_slot_device::call_unload()
// open the flap
m_out_flp_cb(ASSERT_LINE);
- // setup the timer for close the flap
+ // setup the timer to close the flap
m_flp_timer->adjust(CLOSE_FLAP_TIME);
}
@@ -162,6 +151,24 @@ void z88cart_slot_device::call_unload()
std::string z88cart_slot_device::get_default_card_software(get_default_card_software_hook &hook) const
{
+ // select the correct slot device for the ROM size
+ if (hook.image_file())
+ {
+ uint64_t size;
+ std::error_condition err = hook.image_file()->length(size);
+
+ if (!err)
+ {
+ if (size <= 0x8000) return std::string("32krom");
+ if (size <= 0x20000) return std::string("128krom");
+ if (size <= 0x40000) return std::string("256krom");
+ if (size <= 0x100000) return std::string("1024kflash");
+ fatalerror("%s: unsupported ROM size 0x%06x", tag(), size);
+ }
+ else
+ fatalerror("%s: %s:%d %s\n", tag(), err.category().name(), err.value(), err.message());
+ }
+
return software_get_default_slot("128krom");
}
@@ -170,10 +177,10 @@ std::string z88cart_slot_device::get_default_card_software(get_default_card_soft
read
-------------------------------------------------*/
-READ8_MEMBER(z88cart_slot_device::read)
+uint8_t z88cart_slot_device::read(offs_t offset)
{
if (m_cart)
- return m_cart->read(space, offset);
+ return m_cart->read(offset);
else
return 0xff;
}
@@ -183,10 +190,20 @@ READ8_MEMBER(z88cart_slot_device::read)
write
-------------------------------------------------*/
-WRITE8_MEMBER(z88cart_slot_device::write)
+void z88cart_slot_device::write(offs_t offset, uint8_t data)
+{
+ if (m_cart)
+ m_cart->write(offset, data);
+}
+
+/*-------------------------------------------------
+ set EPROM programming voltage to slot 3
+-------------------------------------------------*/
+
+void z88cart_slot_device::vpp_w(int state)
{
if (m_cart)
- m_cart->write(space, offset, data);
+ m_cart->vpp_w(state);
}
diff --git a/src/devices/bus/z88/z88.h b/src/devices/bus/z88/z88.h
index 444eeb3c111..072d41a58fc 100644
--- a/src/devices/bus/z88/z88.h
+++ b/src/devices/bus/z88/z88.h
@@ -56,7 +56,7 @@
#pragma once
-#include "softlist_dev.h"
+#include "imagedev/cartrom.h"
/***************************************************************************
@@ -65,15 +65,16 @@
// ======================> device_z88cart_interface
-class device_z88cart_interface : public device_slot_card_interface
+class device_z88cart_interface : public device_interface
{
public:
// construction/destruction
virtual ~device_z88cart_interface();
// reading and writing
- virtual DECLARE_READ8_MEMBER(read) { return 0xff; }
- virtual DECLARE_WRITE8_MEMBER(write) { }
+ virtual uint8_t read(offs_t offset) { return 0xff; }
+ virtual void write(offs_t offset, uint8_t data) { }
+ virtual void vpp_w(int state) { }
virtual uint8_t* get_cart_base() { return nullptr; }
virtual uint32_t get_cart_size() { return 0; }
@@ -85,8 +86,8 @@ protected:
// ======================> z88cart_slot_device
class z88cart_slot_device : public device_t,
- public device_image_interface,
- public device_slot_interface
+ public device_cartrom_image_interface,
+ public device_single_card_slot_interface<device_z88cart_interface>
{
public:
// construction/destruction
@@ -103,36 +104,30 @@ 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 const software_list_loader &get_software_list_loader() const override { return rom_software_list_loader::instance(); }
-
- virtual iodevice_t image_type() const override { return IO_CARTSLOT; }
- virtual bool is_readable() const override { return 1; }
- virtual bool is_writeable() const override { return 1; }
- virtual bool is_creatable() const override { return 1; }
- virtual bool must_be_loaded() const override { return 0; }
- virtual bool is_reset_on_load() const override { return 0; }
- virtual const char *image_interface() const override { return "z88_cart"; }
- virtual const char *file_extensions() const override { return "epr,bin"; }
-
- // slot interface overrides
+
+ 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"; }
+
+ // device_slot_interface implementation
virtual std::string get_default_card_software(get_default_card_software_hook &hook) const override;
// reading and writing
- virtual DECLARE_READ8_MEMBER(read);
- virtual DECLARE_WRITE8_MEMBER(write);
- virtual uint8_t* get_cart_base();
+ uint8_t read(offs_t offset);
+ void write(offs_t offset, uint8_t data);
+ void vpp_w(int state);
+ uint8_t* get_cart_base();
protected:
- // device-level overrides
- virtual void device_start() override;
- virtual void device_timer(emu_timer &timer, device_timer_id id, int param, void *ptr) override;
+ // device_t implementation
+ virtual void device_start() override ATTR_COLD;
-private:
- static constexpr device_timer_id TIMER_FLP_CLEAR = 0;
+ TIMER_CALLBACK_MEMBER(close_flap);
+private:
devcb_write_line m_out_flp_cb;
device_z88cart_interface* m_cart;
emu_timer * m_flp_timer;
diff --git a/src/devices/cpu/8x300/8x300.cpp b/src/devices/cpu/8x300/8x300.cpp
index a8a9b9dcdad..dbc7614748a 100644
--- a/src/devices/cpu/8x300/8x300.cpp
+++ b/src/devices/cpu/8x300/8x300.cpp
@@ -12,12 +12,11 @@
#include "emu.h"
#include "8x300.h"
#include "8x300dasm.h"
-#include "debugger.h"
-#define FETCHOP(a) (m_cache->read_word(a))
+#define FETCHOP(a) (m_cache.read_word(a))
#define CYCLES(x) do { m_icount -= (x); } while (0)
-#define READPORT(a) (m_io->read_byte(a))
-#define WRITEPORT(a,v) (m_io->write_byte((a), (v)))
+#define READPORT(a) (m_io.read_byte(a))
+#define WRITEPORT(a,v) (m_io.write_byte((a), (v)))
#define SRC ((opcode & 0x1f00) >> 8)
#define DST (opcode & 0x001f)
@@ -47,6 +46,11 @@ n8x300_cpu_device::n8x300_cpu_device(const machine_config &mconfig, device_type
, m_program_config("program", ENDIANNESS_BIG, 16, 13, -1)
, m_io_config("io", ENDIANNESS_BIG, 8, 9, 0)
, m_sc_callback(*this)
+ , m_wc_callback(*this)
+ , m_lb_callback(*this)
+ , m_rb_callback(*this)
+ , m_mclk_callback(*this)
+ , m_iv_callback(*this)
{
}
@@ -68,15 +72,49 @@ device_memory_interface::space_config_vector n8x300_cpu_device::memory_space_con
};
}
-void n8x300_cpu_device::xmit_lb(uint8_t dst, uint8_t mask)
+void n8x300_cpu_device::xmit_lb(uint8_t dst, uint8_t mask, bool with_sc, bool with_wc)
{
m_IV_latch = (m_IV_latch & ~mask) | (dst & mask);
+
+ if(with_sc)
+ {
+ m_sc_callback(1);
+ m_wc_callback(0);
+ m_lb_callback(1);
+ m_iv_callback(m_IVL);
+ }
+
+ if(with_wc)
+ {
+ m_sc_callback(0);
+ m_wc_callback(1);
+ m_lb_callback(1);
+ m_iv_callback(m_IV_latch);
+ }
+
WRITEPORT(m_IVL, m_IV_latch);
}
-void n8x300_cpu_device::xmit_rb(uint8_t dst, uint8_t mask)
+void n8x300_cpu_device::xmit_rb(uint8_t dst, uint8_t mask, bool with_sc, bool with_wc)
{
m_IV_latch = (m_IV_latch & ~mask) | (dst & mask);
+
+ if(with_sc)
+ {
+ m_sc_callback(1);
+ m_wc_callback(0);
+ m_rb_callback(1);
+ m_iv_callback(m_IVL);
+ }
+
+ if(with_wc)
+ {
+ m_sc_callback(0);
+ m_wc_callback(1);
+ m_rb_callback(1);
+ m_iv_callback(m_IV_latch);
+ }
+
WRITEPORT(m_IVR + 0x100, m_IV_latch);
}
@@ -91,11 +129,11 @@ void n8x300_cpu_device::set_reg(uint8_t reg, uint8_t val, bool xmit)
case 0x04: m_R4 = val; break;
case 0x05: m_R5 = val; break;
case 0x06: m_R6 = val; break;
- case 0x07: m_IVL = val; m_sc_callback(0, val); break;
+ case 0x07: m_IVL = val; xmit_lb(val, 0xFF, true, false); break;
// OVF is read-only
case 0x09: m_R11 = val; break;
- case 0x0f: m_IVR = val; m_sc_callback(1, val); break;
- default: logerror("8X300: Invalid register %02x written to.\n",reg); break;
+ case 0x0f: m_IVR = val; xmit_rb(val, 0xFF, true, false); break;
+ default: logerror("8X300: Tried to write to invalid register %02x.\n",reg); break;
}
}
@@ -103,8 +141,8 @@ void n8x305_cpu_device::set_reg(uint8_t reg, uint8_t val, bool xmit)
{
switch (reg)
{
- case 0x0a: if (xmit) xmit_lb(val, 0xff); else m_R12 = val; break;
- case 0x0b: if (xmit) xmit_rb(val, 0xff); else m_R13 = val; break;
+ case 0x0a: if (xmit) xmit_lb(val, 0xff, true, true); else m_R12 = val; break;
+ case 0x0b: if (xmit) xmit_rb(val, 0xff, true, true); else m_R13 = val; break;
case 0x0c: m_R14 = val; break;
case 0x0d: m_R15 = val; break;
case 0x0e: m_R16 = val; break;
@@ -146,16 +184,11 @@ uint8_t n8x305_cpu_device::get_reg(uint8_t reg)
}
}
-void n8x300_cpu_device::device_resolve_objects()
-{
- m_sc_callback.resolve_safe();
-}
-
void n8x300_cpu_device::device_start()
{
- m_program = &space(AS_PROGRAM);
- m_cache = m_program->cache<1, -1, ENDIANNESS_BIG>();
- m_io = &space(AS_IO);
+ space(AS_PROGRAM).cache(m_cache);
+ space(AS_PROGRAM).specific(m_program);
+ space(AS_IO).specific(m_io);
save_item(NAME(m_PC));
save_item(NAME(m_AR));
@@ -271,6 +304,10 @@ void n8x300_cpu_device::device_reset()
m_AR = 0;
m_genPC = 0;
m_increment_pc = true;
+
+ m_lb_callback(0);
+ m_rb_callback(0);
+ m_mclk_callback(0);
}
void n8x300_cpu_device::execute_run()
@@ -282,12 +319,21 @@ void n8x300_cpu_device::execute_run()
uint8_t dst;
uint8_t rotlen; // rotate amount or I/O field length
uint8_t mask;
+ bool with_sc;
+ bool with_wc;
/* fetch the opcode */
m_genPC = m_AR;
debugger_instruction_hook(m_genPC);
opcode = FETCHOP(m_genPC);
+ /* reset I/O lines for this instruction */
+ m_lb_callback(0);
+ m_rb_callback(0);
+ m_sc_callback(0);
+ m_wc_callback(0);
+ m_mclk_callback(0);
+
if (m_increment_pc)
{
m_PC++;
@@ -322,9 +368,9 @@ void n8x300_cpu_device::execute_run()
src = (get_reg(SRC)) << (7-DST_LSB);
mask <<= (7-DST_LSB);
if(DST_IS_RIGHT_BANK)
- xmit_rb(src, mask);
+ xmit_rb(src, mask, false, true);
else
- xmit_lb(src, mask);
+ xmit_lb(src, mask, false, true);
}
else if(!(is_src_reg(opcode)) && is_dst_reg(opcode))
{ // MOVE IV,reg
@@ -343,9 +389,9 @@ void n8x300_cpu_device::execute_run()
dst <<= (7-DST_LSB);
mask <<= (7-DST_LSB);
if(DST_IS_RIGHT_BANK) // untouched source IV bits are preserved and sent to destination IV
- xmit_rb(dst, mask);
+ xmit_rb(dst, mask, false, true);
else
- xmit_lb(dst, mask);
+ xmit_lb(dst, mask, false, true);
}
}
break;
@@ -373,9 +419,9 @@ void n8x300_cpu_device::execute_run()
mask <<= DST_LSB;
SET_OVF;
if(DST_IS_RIGHT_BANK)
- xmit_rb(dst, mask);
+ xmit_rb(dst, mask, false, true);
else
- xmit_lb(dst, mask);
+ xmit_lb(dst, mask, false, true);
}
else if(!(is_src_reg(opcode)) && is_dst_reg(opcode))
{ // ADD IV,reg
@@ -396,9 +442,9 @@ void n8x300_cpu_device::execute_run()
dst = (result << (7-DST_LSB)) & 0xff;
mask <<= (7-DST_LSB);
if(DST_IS_RIGHT_BANK) // unused destination IV data is not preserved, is merged with input IV data
- xmit_rb(dst, mask);
+ xmit_rb(dst, mask, false, true);
else
- xmit_lb(dst, mask);
+ xmit_lb(dst, mask, false, true);
}
}
break;
@@ -424,9 +470,9 @@ void n8x300_cpu_device::execute_run()
dst <<= (7-DST_LSB);
mask <<= (7-DST_LSB);
if(DST_IS_RIGHT_BANK)
- xmit_rb(dst, mask);
+ xmit_rb(dst, mask, false, true);
else
- xmit_lb(dst, mask);
+ xmit_lb(dst, mask, false, true);
}
else if(!(is_src_reg(opcode)) && is_dst_reg(opcode))
{ // AND IV,reg
@@ -445,9 +491,9 @@ void n8x300_cpu_device::execute_run()
dst <<= (7-DST_LSB);
mask <<= (7-DST_LSB);
if(DST_IS_RIGHT_BANK)
- xmit_rb(dst, mask);
+ xmit_rb(dst, mask, false, true);
else
- xmit_lb(dst, mask);
+ xmit_lb(dst, mask, false, true);
}
}
break;
@@ -472,9 +518,9 @@ void n8x300_cpu_device::execute_run()
dst <<= (7-DST_LSB);
mask <<= (7-DST_LSB);
if(DST_IS_RIGHT_BANK)
- xmit_rb(dst, mask);
+ xmit_rb(dst, mask, false, true);
else
- xmit_lb(dst, mask);
+ xmit_lb(dst, mask, false, true);
}
else if(!(is_src_reg(opcode)) && is_dst_reg(opcode))
{ // XOR IV,reg
@@ -493,9 +539,9 @@ void n8x300_cpu_device::execute_run()
dst <<= (7-DST_LSB);
mask <<= (7-DST_LSB);
if(DST_IS_RIGHT_BANK)
- xmit_rb(dst, mask);
+ xmit_rb(dst, mask, false, true);
else
- xmit_lb(dst, mask);
+ xmit_lb(dst, mask, false, true);
}
}
break;
@@ -553,16 +599,36 @@ void n8x300_cpu_device::execute_run()
dst = IMM5;
mask <<= (7-SRC_LSB);
dst <<= (7-SRC_LSB);
+
+ if(opcode & 0xA00 || opcode & 0xB00)
+ {
+ // Imm -> IV Data
+ with_sc = false;
+ with_wc = true;
+ }
+ else
+ {
+ // Imm -> IV Address
+ with_sc = false;
+ with_wc = true;
+ }
+
if(SRC_IS_RIGHT_BANK)
- xmit_rb(dst, mask);
+ {
+ xmit_rb(dst, mask, with_sc, with_wc);
+ }
else
- xmit_lb(dst, mask);
+ {
+ xmit_lb(dst, mask, with_sc, with_wc);
+ }
+
}
break;
case 0x07: // JMP
SET_PC(ADDR);
break;
}
+ m_mclk_callback(1);
CYCLES(1); // all instructions take 1 cycle (250ns)
} while (m_icount > 0);
}
diff --git a/src/devices/cpu/8x300/8x300.h b/src/devices/cpu/8x300/8x300.h
index 155079d225a..82e82a89f92 100644
--- a/src/devices/cpu/8x300/8x300.h
+++ b/src/devices/cpu/8x300/8x300.h
@@ -46,35 +46,37 @@ public:
n8x300_cpu_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
auto sc_callback() { return m_sc_callback.bind(); }
-
+ auto wc_callback() { return m_wc_callback.bind(); }
+ auto mclk_callback() { return m_mclk_callback.bind(); }
+ auto lb_callback() { return m_lb_callback.bind(); }
+ auto rb_callback() { return m_rb_callback.bind(); }
+ auto iv_callback() { return m_iv_callback.bind(); }
protected:
n8x300_cpu_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;
- virtual void device_reset() override;
+ // device_t implementation
+ virtual void device_start() override ATTR_COLD;
+ virtual void device_reset() override ATTR_COLD;
- // device_state_interface overrides
+ // device_state_interface implementation
virtual void state_import(const device_state_entry &entry) override;
- // device_execute_interface overrides
- virtual uint32_t execute_min_cycles() const override { return 1; }
- virtual uint32_t execute_max_cycles() const override { return 1; }
- virtual uint32_t execute_input_lines() const override { return 0; }
+ // device_execute_interface implementation
+ virtual uint32_t execute_min_cycles() const noexcept override { return 1; }
+ virtual uint32_t execute_max_cycles() const noexcept override { return 1; }
virtual void execute_run() override;
- // device_memory_interface overrides
+ // device_memory_interface implementation
virtual space_config_vector memory_space_config() const override;
- // device_disasm_interface overrides
+ // device_disasm_interface implementation
virtual std::unique_ptr<util::disasm_interface> create_disassembler() override;
virtual void set_reg(uint8_t reg, uint8_t val, bool xmit);
virtual uint8_t get_reg(uint8_t reg);
- void xmit_lb(uint8_t dst, uint8_t mask);
- void xmit_rb(uint8_t dst, uint8_t mask);
+ void xmit_lb(uint8_t dst, uint8_t mask, bool with_sc, bool with_wc);
+ void xmit_rb(uint8_t dst, uint8_t mask, bool with_sc, bool with_wc);
address_space_config m_program_config;
address_space_config m_io_config;
@@ -82,11 +84,16 @@ protected:
int m_icount;
bool m_increment_pc;
- address_space *m_program;
- memory_access_cache<1, -1, ENDIANNESS_BIG> *m_cache;
- address_space *m_io;
+ memory_access<13, 1, -1, ENDIANNESS_BIG>::cache m_cache;
+ memory_access<13, 1, -1, ENDIANNESS_BIG>::specific m_program;
+ memory_access< 9, 0, 0, ENDIANNESS_BIG>::specific m_io;
- devcb_write8 m_sc_callback; // Select Command (address latch)
+ devcb_write_line m_sc_callback; // address latch
+ devcb_write_line m_wc_callback; // data latch
+ devcb_write_line m_lb_callback;
+ devcb_write_line m_rb_callback;
+ devcb_write_line m_mclk_callback;
+ devcb_write8 m_iv_callback;
uint16_t m_PC; // Program Counter
uint16_t m_AR; // Address Register
diff --git a/src/devices/cpu/8x300/8x300dasm.cpp b/src/devices/cpu/8x300/8x300dasm.cpp
index 3f03ed19cfd..be7623761f8 100644
--- a/src/devices/cpu/8x300/8x300dasm.cpp
+++ b/src/devices/cpu/8x300/8x300dasm.cpp
@@ -49,6 +49,7 @@ u32 n8x300_disassembler::opcode_alignment() const
offs_t n8x300_disassembler::disassemble(std::ostream &stream, offs_t pc, const data_buffer &opcodes, const data_buffer &params)
{
unsigned startpc = pc;
+ offs_t flags = 0;
uint16_t opcode = opcodes.r16(pc);
uint8_t inst = opcode >> 13;
pc+=1;
@@ -111,6 +112,7 @@ offs_t n8x300_disassembler::disassemble(std::ostream &stream, offs_t pc, const d
util::stream_format(stream, ",%i", ROTLEN);
util::stream_format(stream, ",%02XH", IMM5);
}
+ flags = STEP_COND;
break;
case 0x06:
stream << "XMIT ";
@@ -132,5 +134,5 @@ offs_t n8x300_disassembler::disassemble(std::ostream &stream, offs_t pc, const d
}
- return (pc - startpc);
+ return (pc - startpc) | flags | SUPPORTED;
}
diff --git a/src/devices/cpu/adsp2100/2100dasm.cpp b/src/devices/cpu/adsp2100/2100dasm.cpp
index b3efa6ac6ec..1c5ceaa0c6d 100644
--- a/src/devices/cpu/adsp2100/2100dasm.cpp
+++ b/src/devices/cpu/adsp2100/2100dasm.cpp
@@ -180,24 +180,24 @@ const char *const adsp21xx_disassembler::constants[] =
};
-void adsp21xx_disassembler::alumac(std::ostream &stream, int dest, int op)
+void adsp21xx_disassembler::alumac(std::ostream &stream, int dest, uint32_t op)
{
- int opindex = (op >> 13) & 31;
+ int opindex = BIT(op, 13, 5);
const char *xop, *yop, *dst, *opstring;
- if (opindex & 16)
+ if (BIT(opindex, 4))
{
- xop = alu_xop[(op >> 8) & 7];
- yop = alu_yop[(op >> 11) & 3];
+ xop = alu_xop[BIT(op, 8, 3)];
+ yop = alu_yop[BIT(op, 11, 2)];
dst = alu_dst[dest];
}
else
{
- xop = mac_xop[(op >> 8) & 7];
- yop = mac_yop[(op >> 11) & 3];
+ xop = mac_xop[BIT(op, 8, 3)];
+ yop = mac_yop[BIT(op, 11, 2)];
dst = mac_dst[dest];
}
- opstring = alumac_op[opindex][((op >> 11) & 3) == 3];
+ opstring = alumac_op[opindex][BIT(op, 11, 2) == 3];
if (opstring[0] == '!')
util::stream_format(stream, opstring + 1, dst, yop, xop);
else
@@ -205,24 +205,24 @@ void adsp21xx_disassembler::alumac(std::ostream &stream, int dest, int op)
}
-void adsp21xx_disassembler::aluconst(std::ostream &stream, int dest, int op)
+void adsp21xx_disassembler::aluconst(std::ostream &stream, int dest, uint32_t op)
{
- int opindex = (op >> 13) & 31;
+ int opindex = BIT(op, 13, 5);
const char *xop, *dst, *cval, *opstring;
- if (opindex & 16)
+ if (BIT(opindex, 4))
{
- xop = alu_xop[(op >> 8) & 7];
- cval = constants[((op >> 5) & 0x07) | ((op >> 8) & 0x18)];
+ xop = alu_xop[BIT(op, 8, 3)];
+ cval = constants[BIT(op, 5, 3) | BIT(op, 11, 2) << 3];
dst = alu_dst[dest];
}
else
{
- xop = mac_xop[(op >> 8) & 7];
+ xop = mac_xop[BIT(op, 8, 3)];
cval = xop;
dst = mac_dst[dest];
}
- opstring = alumac_op[opindex][((op >> 11) & 3) == 3];
+ opstring = alumac_op[opindex][BIT(op, 11, 2) == 3];
if (opstring[0] == '!')
util::stream_format(stream, opstring + 1, dst, cval, xop);
else
@@ -232,300 +232,309 @@ void adsp21xx_disassembler::aluconst(std::ostream &stream, int dest, int op)
offs_t adsp21xx_disassembler::disassemble(std::ostream &stream, offs_t pc, const data_buffer &opcodes, const data_buffer &params)
{
- unsigned int op = opcodes.r32(pc);
+ uint32_t op = opcodes.r32(pc);
unsigned dasmflags = 0;
int temp;
- switch ((op >> 16) & 0xff)
+ switch (BIT(op, 16, 8))
{
case 0x00:
- /* 00000000 00000000 00000000 NOP */
+ // 00000000 00000000 00000000 NOP
stream << "NOP";
break;
case 0x01:
- /* 00000000 0xxxxxxx xxxxxxxx dst = IO(x) */
- /* 00000000 1xxxxxxx xxxxxxxx IO(x) = dst */
- /* ADSP-218x only */
- if ((op & 0x008000) == 0x000000)
- util::stream_format(stream, "%s = IO($%X)", reg_grp[0][op & 15], (op >> 4) & 0x7ff);
+ // 00000001 0xxxxxxx xxxxxxxx dst = IO(x)
+ // 00000001 1xxxxxxx xxxxxxxx IO(x) = dst
+ // ADSP-218x only
+ if (!BIT(op, 15))
+ util::stream_format(stream, "%s = IO($%X)", reg_grp[0][BIT(op, 0, 4)], BIT(op, 4, 11));
else
- util::stream_format(stream, "IO($%X) = %s", (op >> 4) & 0x7ff, reg_grp[0][op & 15]);
+ util::stream_format(stream, "IO($%X) = %s", BIT(op, 4, 11), reg_grp[0][BIT(op, 0, 4)]);
break;
case 0x02:
- /* 00000010 0000xxxx xxxxxxxx modify flag out */
- if ((op & 0x00f000) == 0x000000)
+ // 00000010 0000xxxx xxxxxxxx modify flag out
+ if (BIT(op, 12, 4) == 0)
{
- util::stream_format(stream, "%s", condition[op & 15]);
- util::stream_format(stream, flag_change[(op >> 4) & 3], "FLAG_OUT");
- util::stream_format(stream, flag_change[(op >> 6) & 3], "FL0");
- util::stream_format(stream, flag_change[(op >> 8) & 3], "FL1");
- util::stream_format(stream, flag_change[(op >> 10) & 3], "FL2");
+ util::stream_format(stream, "%s", condition[BIT(op, 0, 4)]);
+ util::stream_format(stream, flag_change[BIT(op, 4, 2)], "FLAG_OUT");
+ util::stream_format(stream, flag_change[BIT(op, 6, 2)], "FL0");
+ util::stream_format(stream, flag_change[BIT(op, 8, 2)], "FL1");
+ util::stream_format(stream, flag_change[BIT(op, 10, 2)], "FL2");
}
- /* 00000010 10000000 00000000 idle */
- /* 00000010 10000000 0000xxxx idle (n) */
- else if ((op & 0x00fff0) == 0x008000)
+ // 00000010 10000000 00000000 idle
+ // 00000010 10000000 0000xxxx idle (n)
+ else if (BIT(op, 4, 12) == 0x800)
{
}
else
util::stream_format(stream, "??? (%06X)", op);
break;
case 0x03:
- /* 00000011 xxxxxxxx xxxxxxxx call or jump on flag in */
- if (op & 2)
+ // 00000011 xxxxxxxx xxxxxxxx call or jump on flag in
+ if (BIT(op, 1))
util::stream_format(stream, "%s", "IF FLAG_IN ");
else
util::stream_format(stream, "%s", "IF NOT FLAG_IN ");
- if (op & 1)
+ if (BIT(op, 0))
{
util::stream_format(stream, "%s", "CALL ");
- dasmflags = STEP_OVER;
+ dasmflags = STEP_OVER | STEP_COND;
}
else
+ {
util::stream_format(stream, "%s", "JUMP ");
- temp = ((op >> 4) & 0x0fff) | ((op << 10) & 0x3000);
+ dasmflags = STEP_COND;
+ }
+ temp = BIT(op, 4, 12) | BIT(op, 2, 2) << 12;
util::stream_format(stream, "$%04X", temp);
break;
case 0x04:
- /* 00000100 00000000 000xxxxx stack control */
- if ((op & 0x00ffe0) == 0x000000)
+ // 00000100 00000000 000xxxxx stack control
+ if (BIT(op, 5, 11) == 0)
{
- if (op & 0x000010)
+ if (BIT(op, 4))
{
util::stream_format(stream, "%s", "POP PC ");
dasmflags = STEP_OUT;
}
- if (op & 0x000008) util::stream_format(stream, "%s", "POP LOOP ");
- if (op & 0x000004) util::stream_format(stream, "%s", "POP CNTR ");
- if ((op & 0x000003) == 0x000002) util::stream_format(stream, "%s", "PUSH STAT ");
- else if ((op & 0x000003) == 0x000003) util::stream_format(stream, "%s", "POP STAT ");
+ if (BIT(op, 3)) util::stream_format(stream, "%s", "POP LOOP ");
+ if (BIT(op, 2)) util::stream_format(stream, "%s", "POP CNTR ");
+ if (BIT(op, 0, 2) == 2) util::stream_format(stream, "%s", "PUSH STAT ");
+ else if (BIT(op, 0, 2) == 3) util::stream_format(stream, "%s", "POP STAT ");
}
else
util::stream_format(stream, "??? (%06X)", op);
break;
case 0x05:
- /* 00000101 00000000 00000000 saturate MR */
- if ((op & 0x00ffff) == 0x000000)
+ // 00000101 00000000 00000000 saturate MR
+ if (BIT(op, 0, 16) == 0)
util::stream_format(stream, "%s", "IF MV SAT MR");
else
util::stream_format(stream, "??? (%06X)", op);
break;
case 0x06:
- /* 00000110 000xxxxx 00000000 DIVS */
+ // 00000110 000xxxxx 00000000 DIVS
if ((op & 0x00e0ff) == 0x000000)
- util::stream_format(stream, "DIVS %s,%s", alu_yop[(op >> 11) & 3], alu_xop[(op >> 8) & 7]);
+ util::stream_format(stream, "DIVS %s,%s", alu_yop[BIT(op, 11, 2)], alu_xop[BIT(op, 8, 3)]);
else
util::stream_format(stream, "??? (%06X)", op);
break;
case 0x07:
- /* 00000111 00010xxx 00000000 DIVQ */
+ // 00000111 00010xxx 00000000 DIVQ
if ((op & 0x00f8ff) == 0x001000)
- util::stream_format(stream, "DIVQ %s", alu_xop[(op >> 8) & 7]);
+ util::stream_format(stream, "DIVQ %s", alu_xop[BIT(op, 8, 3)]);
else
util::stream_format(stream, "??? (%06X)", op);
break;
case 0x08:
- /* 00001000 00000000 0000xxxx reserved */
+ // 00001000 00000000 0000xxxx reserved
util::stream_format(stream, "??? (%06X)", op);
break;
case 0x09:
- /* 00001001 00000000 000xxxxx modify address register */
- if ((op & 0x00ffe0) == 0x000000)
+ // 00001001 00000000 000xxxxx modify address register
+ if (BIT(op, 5, 11) == 0)
{
- temp = (op >> 2) & 4;
- util::stream_format(stream, "MODIFY (I%d,M%d)", temp + ((op >> 2) & 3), temp + (op & 3));
+ temp = BIT(op, 2, 3);
+ util::stream_format(stream, "MODIFY (I%d,M%d)", temp, (temp & 4) + BIT(op, 0, 2));
}
else
util::stream_format(stream, "??? (%06X)", op);
break;
case 0x0a:
- /* 00001010 00000000 0000xxxx conditional return */
- if ((op & 0x00ffe0) == 0x000000)
+ // 00001010 00000000 000xxxxx conditional return
+ if (BIT(op, 5, 11) == 0)
{
- util::stream_format(stream, "%s", condition[op & 15]);
- if (op & 0x000010)
+ util::stream_format(stream, "%s", condition[BIT(op, 0, 4)]);
+ if (BIT(op, 4))
util::stream_format(stream, "%s", "RTI");
else
util::stream_format(stream, "%s", "RTS");
dasmflags = STEP_OUT;
+ if (BIT(op, 0, 4) != 15)
+ dasmflags |= STEP_COND;
}
else
util::stream_format(stream, "??? (%06X)", op);
break;
case 0x0b:
- /* 00001011 00000000 xx00xxxx conditional jump (indirect address) */
- if ((op & 0x00ff00) == 0x000000)
+ // 00001011 00000000 xx00xxxx conditional jump (indirect address)
+ if (BIT(op, 8, 8) == 0)
{
- util::stream_format(stream, "%s", condition[op & 15]);
- if (op & 0x000010)
+ util::stream_format(stream, "%s", condition[BIT(op, 0, 4)]);
+ if (BIT(op, 4))
{
- util::stream_format(stream, "CALL (I%d)", 4 + ((op >> 6) & 3));
+ util::stream_format(stream, "CALL (I%d)", 4 + BIT(op, 6, 2));
dasmflags = STEP_OVER;
}
else
- util::stream_format(stream, "JUMP (I%d)", 4 + ((op >> 6) & 3));
+ util::stream_format(stream, "JUMP (I%d)", 4 + BIT(op, 6, 2));
+ if (BIT(op, 0, 4) != 15)
+ dasmflags |= STEP_COND;
}
else
util::stream_format(stream, "??? (%06X)", op);
break;
case 0x0c:
- /* 00001100 xxxxxxxx xxxxxxxx mode control */
- util::stream_format(stream, mode_change[(op >> 4) & 3], "SEC_REG");
- util::stream_format(stream, mode_change[(op >> 6) & 3], "BIT_REV");
- util::stream_format(stream, mode_change[(op >> 8) & 3], "AV_LATCH");
- util::stream_format(stream, mode_change[(op >> 10) & 3], "AR_SAT");
- util::stream_format(stream, mode_change[(op >> 12) & 3], "M_MODE");
- util::stream_format(stream, mode_change[(op >> 14) & 3], "TIMER");
- util::stream_format(stream, mode_change[(op >> 2) & 3], "G_MODE");
+ // 00001100 xxxxxxxx xxxxxxxx mode control
+ util::stream_format(stream, mode_change[BIT(op, 4, 2)], "SEC_REG");
+ util::stream_format(stream, mode_change[BIT(op, 6, 2)], "BIT_REV");
+ util::stream_format(stream, mode_change[BIT(op, 8, 2)], "AV_LATCH");
+ util::stream_format(stream, mode_change[BIT(op, 10, 2)], "AR_SAT");
+ util::stream_format(stream, mode_change[BIT(op, 12, 2)], "M_MODE");
+ util::stream_format(stream, mode_change[BIT(op, 14, 2)], "TIMER");
+ util::stream_format(stream, mode_change[BIT(op, 2, 2)], "G_MODE");
break;
case 0x0d:
- /* 00001101 0000xxxx xxxxxxxx internal data move */
- if ((op & 0x00f000) == 0x000000)
- util::stream_format(stream, "%s = %s", reg_grp[(op >> 10) & 3][(op >> 4) & 15], reg_grp[(op >> 8) & 3][op & 15]);
+ // 00001101 0000xxxx xxxxxxxx internal data move
+ if (BIT(op, 12, 4) == 0)
+ util::stream_format(stream, "%s = %s", reg_grp[BIT(op, 10, 2)][BIT(op, 4, 4)], reg_grp[BIT(op, 8, 2)][BIT(op, 0, 4)]);
else
util::stream_format(stream, "??? (%06X)", op);
break;
case 0x0e:
- /* 00001110 0xxxxxxx xxxxxxxx conditional shift */
+ // 00001110 0xxxxxxx xxxxxxxx conditional shift
if ((op & 0x0080f0) == 0x000000)
{
- util::stream_format(stream, "%s", condition[op & 15]);
- util::stream_format(stream, shift_op[(op >> 11) & 15], shift_xop[(op >> 8) & 7]);
+ util::stream_format(stream, "%s", condition[BIT(op, 0, 4)]);
+ util::stream_format(stream, shift_op[BIT(op, 11, 4)], shift_xop[BIT(op, 8, 3)]);
}
else
util::stream_format(stream, "??? (%06X)", op);
break;
case 0x0f:
- /* 00001111 0xxxxxxx xxxxxxxx shift immediate */
- if ((op & 0x008000) == 0x000000)
- util::stream_format(stream, shift_by_op[(op >> 11) & 15], shift_xop[(op >> 8) & 7], (signed char)op);
+ // 00001111 0xxxxxxx xxxxxxxx shift immediate
+ if (!BIT(op, 15))
+ util::stream_format(stream, shift_by_op[BIT(op, 11, 4)], shift_xop[BIT(op, 8, 3)], (signed char)op);
else
util::stream_format(stream, "??? (%06X)", op);
break;
case 0x10:
- /* 00010000 0xxxxxxx xxxxxxxx shift with internal data register move */
- if ((op & 0x008000) == 0x000000)
+ // 00010000 0xxxxxxx xxxxxxxx shift with internal data register move
+ if (!BIT(op, 15))
{
- util::stream_format(stream, shift_op[(op >> 11) & 15], shift_xop[(op >> 8) & 7]);
- util::stream_format(stream, ", %s = %s", reg_grp[0][(op >> 4) & 15], reg_grp[0][op & 15]);
+ util::stream_format(stream, shift_op[BIT(op, 11, 4)], shift_xop[BIT(op, 8, 3)]);
+ util::stream_format(stream, ", %s = %s", reg_grp[0][BIT(op, 4, 4)], reg_grp[0][BIT(op, 0, 4)]);
}
else
util::stream_format(stream, "??? (%06X)", op);
break;
case 0x11:
- /* 00010001 0xxxxxxx xxxxxxxx shift with pgm memory read/write */
- util::stream_format(stream, shift_op[(op >> 11) & 15], shift_xop[(op >> 8) & 7]);
- if (op & 0x008000)
- util::stream_format(stream, ", PM(I%d,M%d) = %s", 4 + ((op >> 2) & 3), 4 + (op & 3), reg_grp[0][(op >> 4) & 15]);
+ // 00010001 0xxxxxxx xxxxxxxx shift with pgm memory read/write
+ util::stream_format(stream, shift_op[BIT(op, 11, 4)], shift_xop[BIT(op, 8, 3)]);
+ if (BIT(op, 15))
+ util::stream_format(stream, ", PM(I%d,M%d) = %s", 4 + BIT(op, 2, 2), 4 + BIT(op, 0, 2), reg_grp[0][BIT(op, 4, 4)]);
else
- util::stream_format(stream, ", %s = PM(I%d,M%d)", reg_grp[0][(op >> 4) & 15], 4 + ((op >> 2) & 3), 4 + (op & 3));
+ util::stream_format(stream, ", %s = PM(I%d,M%d)", reg_grp[0][BIT(op, 4, 4)], 4 + BIT(op, 2, 2), 4 + BIT(op, 0, 2));
break;
case 0x12: case 0x13:
- /* 0001001x 0xxxxxxx xxxxxxxx shift with data memory read/write */
- util::stream_format(stream, shift_op[(op >> 11) & 15], shift_xop[(op >> 8) & 7]);
- temp = (op >> 14) & 4;
- if (op & 0x008000)
- util::stream_format(stream, ", DM(I%d,M%d) = %s", temp + ((op >> 2) & 3), temp + (op & 3), reg_grp[0][(op >> 4) & 15]);
+ // 0001001x 0xxxxxxx xxxxxxxx shift with data memory read/write
+ util::stream_format(stream, shift_op[BIT(op, 11, 4)], shift_xop[BIT(op, 8, 3)]);
+ temp = BIT(op, 16) ? 4 : 0;
+ if (BIT(op, 15))
+ util::stream_format(stream, ", DM(I%d,M%d) = %s", temp + BIT(op, 2, 2), temp + BIT(op, 0, 2), reg_grp[0][BIT(op, 4, 4)]);
else
- util::stream_format(stream, ", %s = DM(I%d,M%d)", reg_grp[0][(op >> 4) & 15], temp + ((op >> 2) & 3), temp + (op & 3));
+ util::stream_format(stream, ", %s = DM(I%d,M%d)", reg_grp[0][BIT(op, 4, 4)], temp + BIT(op, 2, 2), temp + BIT(op, 0, 2));
break;
case 0x14: case 0x15: case 0x16: case 0x17:
- /* 000101xx xxxxxxxx xxxxxxxx do until */
- util::stream_format(stream, "DO $%04X UNTIL %s", (op >> 4) & 0x3fff, do_condition[op & 15]);
+ // 000101xx xxxxxxxx xxxxxxxx do until
+ util::stream_format(stream, "DO $%04X UNTIL %s", BIT(op, 4, 14), do_condition[BIT(op, 0, 4)]);
break;
case 0x18: case 0x19: case 0x1a: case 0x1b: case 0x1c: case 0x1d: case 0x1e: case 0x1f:
- /* 00011xxx xxxxxxxx xxxxxxxx conditional jump (immediate addr) */
- if (op & 0x040000)
+ // 00011xxx xxxxxxxx xxxxxxxx conditional jump (immediate addr)
+ if (BIT(op, 18))
{
- util::stream_format(stream, "%sCALL $%04X", condition[op & 15], (op >> 4) & 0x3fff);
+ util::stream_format(stream, "%sCALL $%04X", condition[BIT(op, 0, 4)], BIT(op, 4, 14));
dasmflags = STEP_OVER;
}
else
- util::stream_format(stream, "%sJUMP $%04X", condition[op & 15], (op >> 4) & 0x3fff);
+ util::stream_format(stream, "%sJUMP $%04X", condition[BIT(op, 0, 4)], BIT(op, 4, 14));
+ if (BIT(op, 0, 4) != 15)
+ dasmflags |= STEP_COND;
break;
case 0x20: case 0x21: case 0x22: case 0x23: case 0x24: case 0x25: case 0x26: case 0x27:
- /* 00100xxx xxxxxxxx xxxxxxxx conditional ALU/MAC */
- util::stream_format(stream, "%s", condition[op & 15]);
- if (!(op & 0x10))
- alumac(stream, (op >> 18) & 1, op);
+ // 00100xxx xxxxxxxx xxxxxxxx conditional ALU/MAC
+ util::stream_format(stream, "%s", condition[BIT(op, 0, 4)]);
+ if (!BIT(op, 4))
+ alumac(stream, BIT(op, 18), op);
else
{
- /* ADSP-218x only */
- aluconst(stream, (op >> 18) & 1, op);
+ // ADSP-218x only
+ aluconst(stream, BIT(op, 18), op);
}
break;
case 0x28: case 0x29: case 0x2a: case 0x2b: case 0x2c: case 0x2d: case 0x2e: case 0x2f:
- /* 00101xxx xxxxxxxx xxxxxxxx ALU/MAC with internal data register move */
+ // 00101xxx xxxxxxxx xxxxxxxx ALU/MAC with internal data register move
if ((op & 0x0600ff) == 0x0200aa)
{
- /* ADSP-218x only */
+ // ADSP-218x only
alumac(stream, 2, op);
}
else
{
- if ((op & 0x03e000) != 0)
+ if (BIT(op, 13, 5) != 0)
{
- alumac(stream, (op >> 18) & 1, op);
+ alumac(stream, BIT(op, 18), op);
util::stream_format(stream, ", ");
}
- util::stream_format(stream, "%s = %s", reg_grp[0][(op >> 4) & 15], reg_grp[0][op & 15]);
+ util::stream_format(stream, "%s = %s", reg_grp[0][BIT(op, 4, 4)], reg_grp[0][BIT(op, 0, 4)]);
}
break;
case 0x30: case 0x31: case 0x32: case 0x33: case 0x34: case 0x35: case 0x36: case 0x37:
case 0x38: case 0x39: case 0x3a: case 0x3b: case 0x3c: case 0x3d: case 0x3e: case 0x3f:
- /* 0011xxxx xxxxxxxx xxxxxxxx load non-data register immediate */
- util::stream_format(stream, "%s = $%04X", reg_grp[(op >> 18) & 3][op & 15], (op >> 4) & 0x3fff);
+ // 0011xxxx xxxxxxxx xxxxxxxx load non-data register immediate
+ util::stream_format(stream, "%s = $%04X", reg_grp[BIT(op, 18, 2)][BIT(op, 0, 4)], BIT(op, 4, 14));
break;
case 0x40: case 0x41: case 0x42: case 0x43: case 0x44: case 0x45: case 0x46: case 0x47:
case 0x48: case 0x49: case 0x4a: case 0x4b: case 0x4c: case 0x4d: case 0x4e: case 0x4f:
- /* 0100xxxx xxxxxxxx xxxxxxxx load data register immediate */
- util::stream_format(stream, "%s = $%04X", reg_grp[0][op & 15], (op >> 4) & 0xffff);
+ // 0100xxxx xxxxxxxx xxxxxxxx load data register immediate
+ util::stream_format(stream, "%s = $%04X", reg_grp[0][BIT(op, 0, 4)], BIT(op, 4, 16));
break;
case 0x50: case 0x51: case 0x52: case 0x53: case 0x54: case 0x55: case 0x56: case 0x57:
case 0x58: case 0x59: case 0x5a: case 0x5b: case 0x5c: case 0x5d: case 0x5e: case 0x5f:
- /* 0101xxxx xxxxxxxx xxxxxxxx ALU/MAC with pgm memory read/write */
- if ((op & 0x03e000) != 0)
+ // 0101xxxx xxxxxxxx xxxxxxxx ALU/MAC with pgm memory read/write
+ if (BIT(op, 13, 5) != 0)
{
- alumac(stream, (op >> 18) & 1, op);
+ alumac(stream, BIT(op, 18), op);
util::stream_format(stream, ", ");
}
- if (op & 0x080000)
- util::stream_format(stream, "PM(I%d,M%d) = %s", 4 + ((op >> 2) & 3), 4 + (op & 3), reg_grp[0][(op >> 4) & 15]);
+ if (BIT(op, 19))
+ util::stream_format(stream, "PM(I%d,M%d) = %s", 4 + BIT(op, 2, 2), 4 + BIT(op, 0, 2), reg_grp[0][BIT(op, 4, 4)]);
else
- util::stream_format(stream, "%s = PM(I%d,M%d)", reg_grp[0][(op >> 4) & 15], 4 + ((op >> 2) & 3), 4 + (op & 3));
+ util::stream_format(stream, "%s = PM(I%d,M%d)", reg_grp[0][BIT(op, 4, 4)], 4 + BIT(op, 2, 2), 4 + BIT(op, 0, 2));
break;
case 0x60: case 0x61: case 0x62: case 0x63: case 0x64: case 0x65: case 0x66: case 0x67:
case 0x68: case 0x69: case 0x6a: case 0x6b: case 0x6c: case 0x6d: case 0x6e: case 0x6f:
case 0x70: case 0x71: case 0x72: case 0x73: case 0x74: case 0x75: case 0x76: case 0x77:
case 0x78: case 0x79: case 0x7a: case 0x7b: case 0x7c: case 0x7d: case 0x7e: case 0x7f:
- /* 011xxxxx xxxxxxxx xxxxxxxx ALU/MAC with data memory read/write */
- if ((op & 0x03e000) != 0)
+ // 011xxxxx xxxxxxxx xxxxxxxx ALU/MAC with data memory read/write
+ if (BIT(op, 13, 5) != 0)
{
- alumac(stream, (op >> 18) & 1, op);
+ alumac(stream, BIT(op, 18), op);
util::stream_format(stream, ", ");
}
- temp = (op >> 18) & 4;
- if (op & 0x080000)
- util::stream_format(stream, "DM(I%d,M%d) = %s", temp + ((op >> 2) & 3), temp + (op & 3), reg_grp[0][(op >> 4) & 15]);
+ temp = BIT(op, 20) ? 4 : 0;
+ if (BIT(op, 19))
+ util::stream_format(stream, "DM(I%d,M%d) = %s", temp + BIT(op, 2, 2), temp + BIT(op, 0, 2), reg_grp[0][BIT(op, 4, 4)]);
else
- util::stream_format(stream, "%s = DM(I%d,M%d)", reg_grp[0][(op >> 4) & 15], temp + ((op >> 2) & 3), temp + (op & 3));
+ util::stream_format(stream, "%s = DM(I%d,M%d)", reg_grp[0][BIT(op, 4, 4)], temp + BIT(op, 2, 2), temp + BIT(op, 0, 2));
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:
case 0x90: case 0x91: case 0x92: case 0x93: case 0x94: case 0x95: case 0x96: case 0x97:
case 0x98: case 0x99: case 0x9a: case 0x9b: case 0x9c: case 0x9d: case 0x9e: case 0x9f:
- /* 100xxxxx xxxxxxxx xxxxxxxx read/write data memory (immediate addr) */
- if (op & 0x100000)
- util::stream_format(stream, "DM($%04X) = %s", (op >> 4) & 0x3fff, reg_grp[(op >> 18) & 3][op & 15]);
+ // 100xxxxx xxxxxxxx xxxxxxxx read/write data memory (immediate addr)
+ if (BIT(op, 20))
+ util::stream_format(stream, "DM($%04X) = %s", BIT(op, 4, 14), reg_grp[BIT(op, 18, 2)][BIT(op, 0, 4)]);
else
- util::stream_format(stream, "%s = DM($%04X)", reg_grp[(op >> 18) & 3][op & 15], (op >> 4) & 0x3fff);
+ util::stream_format(stream, "%s = DM($%04X)", reg_grp[BIT(op, 18, 2)][BIT(op, 0, 4)], BIT(op, 4, 14));
break;
case 0xa0: case 0xa1: case 0xa2: case 0xa3: case 0xa4: case 0xa5: case 0xa6: case 0xa7:
case 0xa8: case 0xa9: case 0xaa: case 0xab: case 0xac: case 0xad: case 0xae: case 0xaf:
case 0xb0: case 0xb1: case 0xb2: case 0xb3: case 0xb4: case 0xb5: case 0xb6: case 0xb7:
case 0xb8: case 0xb9: case 0xba: case 0xbb: case 0xbc: case 0xbd: case 0xbe: case 0xbf:
- /* 101xxxxx xxxxxxxx xxxxxxxx data memory write (immediate) */
- temp = (op >> 18) & 4;
- util::stream_format(stream, "DM(I%d,M%d) = $%04X", temp + ((op >> 2) & 3), temp + (op & 3), (op >> 4) & 0xffff);
+ // 101xxxxx xxxxxxxx xxxxxxxx data memory write (immediate)
+ temp = BIT(op, 20) ? 4 : 0;
+ util::stream_format(stream, "DM(I%d,M%d) = $%04X", temp + BIT(op, 2, 2), temp + BIT(op, 0, 2), BIT(op, 4, 16));
break;
case 0xc0: case 0xc1: case 0xc2: case 0xc3: case 0xc4: case 0xc5: case 0xc6: case 0xc7:
case 0xc8: case 0xc9: case 0xca: case 0xcb: case 0xcc: case 0xcd: case 0xce: case 0xcf:
@@ -535,14 +544,14 @@ offs_t adsp21xx_disassembler::disassemble(std::ostream &stream, offs_t pc, const
case 0xe8: case 0xe9: case 0xea: case 0xeb: case 0xec: case 0xed: case 0xee: case 0xef:
case 0xf0: case 0xf1: case 0xf2: case 0xf3: case 0xf4: case 0xf5: case 0xf6: case 0xf7:
case 0xf8: case 0xf9: case 0xfa: case 0xfb: case 0xfc: case 0xfd: case 0xfe: case 0xff:
- /* 11xxxxxx xxxxxxxx xxxxxxxx ALU/MAC with data & pgm memory read */
- if ((op & 0x03e000) != 0)
+ // 11xxxxxx xxxxxxxx xxxxxxxx ALU/MAC with data & pgm memory read
+ if (BIT(op, 13, 5) != 0)
{
alumac(stream, 0, op);
util::stream_format(stream, ", ");
}
- util::stream_format(stream, "%s = DM(I%d,M%d), %s = PM(I%d,M%d)", dual_xreg[(op >> 18) & 3], (op >> 2) & 3, op & 3,
- dual_yreg[(op >> 20) & 3], 4 + ((op >> 6) & 3), 4 + ((op >> 4) & 3));
+ util::stream_format(stream, "%s = DM(I%d,M%d), %s = PM(I%d,M%d)", dual_xreg[BIT(op, 18, 2)], BIT(op, 2, 2), BIT(op, 0, 2),
+ dual_yreg[BIT(op, 20, 2)], 4 + BIT(op, 6, 2), 4 + BIT(op, 4, 2));
break;
}
diff --git a/src/devices/cpu/adsp2100/2100dasm.h b/src/devices/cpu/adsp2100/2100dasm.h
index 1c80c47a554..cbfacc89e53 100644
--- a/src/devices/cpu/adsp2100/2100dasm.h
+++ b/src/devices/cpu/adsp2100/2100dasm.h
@@ -24,7 +24,7 @@ private:
static const char *const mac_xop[];
static const char *const mac_yop[];
static const char *const mac_dst[];
- static const char *const shift_xop[];;
+ static const char *const shift_xop[];
static const char *const reg_grp[][16];
static const char *const dual_xreg[];
static const char *const dual_yreg[];
@@ -35,8 +35,8 @@ private:
static const char *const shift_by_op[];
static const char *const constants[];
- void alumac(std::ostream &stream, int dest, int op);
- void aluconst(std::ostream &stream, int dest, int op);
+ void alumac(std::ostream &stream, int dest, uint32_t op);
+ void aluconst(std::ostream &stream, int dest, uint32_t op);
};
diff --git a/src/devices/cpu/adsp2100/2100ops.hxx b/src/devices/cpu/adsp2100/2100ops.hxx
index 0b9aded2a22..be8f4524a7a 100644
--- a/src/devices/cpu/adsp2100/2100ops.hxx
+++ b/src/devices/cpu/adsp2100/2100ops.hxx
@@ -4,7 +4,7 @@
ASTAT -- ALU/MAC status register
===========================================================================*/
-/* extracts flags */
+// extracts flags
#define GET_SS (m_astat & SSFLAG)
#define GET_MV (m_astat & MVFLAG)
#define GET_Q (m_astat & QFLAG)
@@ -14,7 +14,7 @@
#define GET_N (m_astat & NFLAG)
#define GET_Z (m_astat & ZFLAG)
-/* clears flags */
+// clears flags
#define CLR_SS (m_astat &= ~SSFLAG)
#define CLR_MV (m_astat &= ~MVFLAG)
#define CLR_Q (m_astat &= ~QFLAG)
@@ -24,7 +24,7 @@
#define CLR_N (m_astat &= ~NFLAG)
#define CLR_Z (m_astat &= ~ZFLAG)
-/* sets flags */
+// sets flags
#define SET_SS (m_astat |= SSFLAG)
#define SET_MV (m_astat |= MVFLAG)
#define SET_Q (m_astat |= QFLAG)
@@ -34,10 +34,10 @@
#define SET_Z (m_astat |= ZFLAG)
#define SET_N (m_astat |= NFLAG)
-/* flag clearing; must be done before setting */
+// flag clearing; must be done before setting
#define CLR_FLAGS (m_astat &= m_astat_clear)
-/* compute flags */
+// compute flags
#define CALC_Z(r) (m_astat |= ((r & 0xffff) == 0))
#define CALC_N(r) (m_astat |= (r >> 14) & 0x02)
#define CALC_V(s,d,r) (m_astat |= ((s ^ d ^ r ^ (r >> 1)) >> 13) & 0x04)
@@ -48,7 +48,7 @@
#define CALC_NZVC(s,d,r) CLR_FLAGS; CALC_N(r); CALC_Z(r); CALC_V(s,d,r); CALC_C(r)
#define CALC_NZVC_SUB(s,d,r) CLR_FLAGS; CALC_N(r); CALC_Z(r); CALC_V(s,d,r); CALC_C_SUB(r)
-/* ADSP-218x constants */
+// ADSP-218x constants
static const int32_t constants[] =
{
0x0001, 0xfffe, 0x0002, 0xfffd, 0x0004, 0xfffb, 0x0008, 0xfff7,
@@ -63,16 +63,19 @@ static const int32_t constants[] =
MSTAT -- ALU/MAC control register
===========================================================================*/
-/* flag definitions */
-#define MSTAT_BANK 0x01 /* register bank select */
-#define MSTAT_REVERSE 0x02 /* bit-reverse addressing enable (DAG1) */
-#define MSTAT_STICKYV 0x04 /* sticky ALU overflow enable */
-#define MSTAT_SATURATE 0x08 /* AR saturation mode enable */
-#define MSTAT_INTEGER 0x10 /* MAC result placement; 0=fractional, 1=integer */
-#define MSTAT_TIMER 0x20 /* timer enable */
-#define MSTAT_GOMODE 0x40 /* go mode enable */
+// flag definitions
+enum : uint32_t
+{
+ MSTAT_BANK = 0x01, // register bank select
+ MSTAT_REVERSE = 0x02, // bit-reverse addressing enable (DAG1)
+ MSTAT_STICKYV = 0x04, // sticky ALU overflow enable
+ MSTAT_SATURATE = 0x08, // AR saturation mode enable
+ MSTAT_INTEGER = 0x10, // MAC result placement; 0=fractional, 1=integer
+ MSTAT_TIMER = 0x20, // timer enable
+ MSTAT_GOMODE = 0x40 // go mode enable
+};
-/* you must call this in order to change MSTAT */
+// you must call this in order to change MSTAT
inline void adsp21xx_device::update_mstat()
{
if ((m_mstat ^ m_mstat_prev) & MSTAT_BANK)
@@ -82,8 +85,7 @@ inline void adsp21xx_device::update_mstat()
m_alt = temp;
}
if ((m_mstat ^ m_mstat_prev) & MSTAT_TIMER)
- if (!m_timer_fired_cb.isnull())
- m_timer_fired_cb((m_mstat & MSTAT_TIMER) != 0);
+ m_timer_fired_cb((m_mstat & MSTAT_TIMER) != 0);
if (m_mstat & MSTAT_STICKYV)
m_astat_clear = ~(CFLAG | NFLAG | ZFLAG);
else
@@ -96,16 +98,18 @@ inline void adsp21xx_device::update_mstat()
SSTAT -- stack status register
===========================================================================*/
-/* flag definitions */
-#define PC_EMPTY 0x01 /* PC stack empty */
-#define PC_OVER 0x02 /* PC stack overflow */
-#define COUNT_EMPTY 0x04 /* count stack empty */
-#define COUNT_OVER 0x08 /* count stack overflow */
-#define STATUS_EMPTY 0x10 /* status stack empty */
-#define STATUS_OVER 0x20 /* status stack overflow */
-#define LOOP_EMPTY 0x40 /* loop stack empty */
-#define LOOP_OVER 0x80 /* loop stack overflow */
-
+// flag definitions
+enum : uint32_t
+{
+ PC_EMPTY = 0x01, // PC stack empty
+ PC_OVER = 0x02, // PC stack overflow
+ COUNT_EMPTY = 0x04, // count stack empty
+ COUNT_OVER = 0x08, // count stack overflow
+ STATUS_EMPTY = 0x10, // status stack empty
+ STATUS_OVER = 0x20, // status stack overflow
+ LOOP_EMPTY = 0x40, // loop stack empty
+ LOOP_OVER = 0x80 // loop stack overflow
+};
/*===========================================================================
@@ -305,7 +309,7 @@ inline int adsp21xx_device::condition(int c)
if (c != 14)
return m_condition_table[((c) << 8) | m_astat];
else
- return slow_condition(c);
+ return slow_condition();
}
*/
@@ -337,6 +341,11 @@ inline void adsp21xx_device::update_l(int which)
m_base[which] = m_i[which] & m_lmask[which];
}
+inline void adsp21xx_device::update_dmovlay()
+{
+ m_dmovlay_cb(m_dmovlay);
+}
+
void adsp21xx_device::write_reg0(int regnum, int32_t val)
{
switch (regnum)
@@ -371,7 +380,7 @@ void adsp21xx_device::write_reg1(int regnum, int32_t val)
break;
case 1:
- m_m[index] = (int32_t)(val << 18) >> 18;
+ m_m[index] = util::sext(val, 14);
break;
case 2:
@@ -380,9 +389,23 @@ void adsp21xx_device::write_reg1(int regnum, int32_t val)
break;
case 3:
- // Check for DMOVLAY instruction callback
- if (regnum == 0xf && !m_dmovlay_cb.isnull())
- m_dmovlay_cb(val & 0x3fff);
+ if (m_chip_type == CHIP_TYPE_ADSP2181) // ADSP2181 Overlay register
+ {
+ switch (index)
+ {
+ case 2:
+ m_pmovlay = val & 0x3fff;
+ //update_pmovlay();
+ break;
+ case 3:
+ m_dmovlay = val & 0x3fff;
+ update_dmovlay();
+ break;
+ default:
+ logerror("ADSP %04x: Writing to an invalid register! RGP=01 RegCode=%1X Val=%04X\n", m_ppc, regnum, val);
+ break;
+ }
+ }
else
logerror("ADSP %04x: Writing to an invalid register! RGP=01 RegCode=%1X Val=%04X\n", m_ppc, regnum, val);
break;
@@ -400,7 +423,7 @@ void adsp21xx_device::write_reg2(int regnum, int32_t val)
break;
case 1:
- m_m[index] = (int32_t)(val << 18) >> 18;
+ m_m[index] = util::sext(val, 14);
break;
case 2:
@@ -423,45 +446,45 @@ void adsp21xx_device::write_reg3(int regnum, int32_t val)
case 0x03: m_imask = val & m_imask_mask; check_irqs(); break;
case 0x04: m_icntl = val & 0x001f; check_irqs(); break;
case 0x05: cntr_stack_push(); m_cntr = val & 0x3fff; break;
- case 0x06: m_core.sb.s = (int32_t)(val << 27) >> 27; break;
+ case 0x06: m_core.sb.s = util::sext(val, 5); break;
case 0x07: m_px = val; break;
- case 0x09: if (!m_sport_tx_cb.isnull()) m_sport_tx_cb(0, val, 0xffff); break;
- case 0x0b: if (!m_sport_tx_cb.isnull()) m_sport_tx_cb(1, val, 0xffff); break;
+ case 0x09: m_sport_tx_cb(0, val, 0xffff); break;
+ case 0x0b: m_sport_tx_cb(1, val, 0xffff); break;
case 0x0c:
m_ifc = val;
if (m_chip_type >= CHIP_TYPE_ADSP2181)
{
- /* clear timer */
- if (val & 0x0002) m_irq_latch[ADSP2181_IRQ0] = 0;
- if (val & 0x0004) m_irq_latch[ADSP2181_IRQ1] = 0;
- if (val & 0x0008) m_irq_latch[ADSP2181_BDMA] = 0;
- if (val & 0x0010) m_irq_latch[ADSP2181_IRQE] = 0;
- if (val & 0x0020) m_irq_latch[ADSP2181_SPORT0_RX] = 0;
- if (val & 0x0040) m_irq_latch[ADSP2181_SPORT0_TX] = 0;
- if (val & 0x0080) m_irq_latch[ADSP2181_IRQ2] = 0;
- /* force timer */
- if (val & 0x0200) m_irq_latch[ADSP2181_IRQ0] = 1;
- if (val & 0x0400) m_irq_latch[ADSP2181_IRQ1] = 1;
- if (val & 0x0800) m_irq_latch[ADSP2181_BDMA] = 1;
- if (val & 0x1000) m_irq_latch[ADSP2181_IRQE] = 1;
- if (val & 0x2000) m_irq_latch[ADSP2181_SPORT0_RX] = 1;
- if (val & 0x4000) m_irq_latch[ADSP2181_SPORT0_TX] = 1;
- if (val & 0x8000) m_irq_latch[ADSP2181_IRQ2] = 1;
+ // clear timer
+ if (BIT(val, 1)) m_irq_latch[ADSP2181_IRQ0] = 0;
+ if (BIT(val, 2)) m_irq_latch[ADSP2181_IRQ1] = 0;
+ if (BIT(val, 3)) m_irq_latch[ADSP2181_BDMA] = 0;
+ if (BIT(val, 4)) m_irq_latch[ADSP2181_IRQE] = 0;
+ if (BIT(val, 5)) m_irq_latch[ADSP2181_SPORT0_RX] = 0;
+ if (BIT(val, 6)) m_irq_latch[ADSP2181_SPORT0_TX] = 0;
+ if (BIT(val, 7)) m_irq_latch[ADSP2181_IRQ2] = 0;
+ // force timer
+ if (BIT(val, 9)) m_irq_latch[ADSP2181_IRQ0] = 1;
+ if (BIT(val, 10)) m_irq_latch[ADSP2181_IRQ1] = 1;
+ if (BIT(val, 11)) m_irq_latch[ADSP2181_BDMA] = 1;
+ if (BIT(val, 12)) m_irq_latch[ADSP2181_IRQE] = 1;
+ if (BIT(val, 13)) m_irq_latch[ADSP2181_SPORT0_RX] = 1;
+ if (BIT(val, 14)) m_irq_latch[ADSP2181_SPORT0_TX] = 1;
+ if (BIT(val, 15)) m_irq_latch[ADSP2181_IRQ2] = 1;
}
else
{
- /* clear timer */
- if (val & 0x002) m_irq_latch[ADSP2101_IRQ0] = 0;
- if (val & 0x004) m_irq_latch[ADSP2101_IRQ1] = 0;
- if (val & 0x008) m_irq_latch[ADSP2101_SPORT0_RX] = 0;
- if (val & 0x010) m_irq_latch[ADSP2101_SPORT0_TX] = 0;
- if (val & 0x020) m_irq_latch[ADSP2101_IRQ2] = 0;
- /* set timer */
- if (val & 0x080) m_irq_latch[ADSP2101_IRQ0] = 1;
- if (val & 0x100) m_irq_latch[ADSP2101_IRQ1] = 1;
- if (val & 0x200) m_irq_latch[ADSP2101_SPORT0_RX] = 1;
- if (val & 0x400) m_irq_latch[ADSP2101_SPORT0_TX] = 1;
- if (val & 0x800) m_irq_latch[ADSP2101_IRQ2] = 1;
+ // clear timer
+ if (BIT(val, 1)) m_irq_latch[ADSP2101_IRQ0] = 0;
+ if (BIT(val, 2)) m_irq_latch[ADSP2101_IRQ1] = 0;
+ if (BIT(val, 3)) m_irq_latch[ADSP2101_SPORT0_RX] = 0;
+ if (BIT(val, 4)) m_irq_latch[ADSP2101_SPORT0_TX] = 0;
+ if (BIT(val, 5)) m_irq_latch[ADSP2101_IRQ2] = 0;
+ // set timer
+ if (BIT(val, 7)) m_irq_latch[ADSP2101_IRQ0] = 1;
+ if (BIT(val, 8)) m_irq_latch[ADSP2101_IRQ1] = 1;
+ if (BIT(val, 9)) m_irq_latch[ADSP2101_SPORT0_RX] = 1;
+ if (BIT(val, 10)) m_irq_latch[ADSP2101_SPORT0_TX] = 1;
+ if (BIT(val, 11)) m_irq_latch[ADSP2101_IRQ2] = 1;
}
check_irqs();
break;
@@ -486,7 +509,19 @@ int32_t adsp21xx_device::read_reg0(int regnum)
int32_t adsp21xx_device::read_reg1(int regnum)
{
- return *m_read1_ptr[regnum];
+ int32_t ret = *m_read1_ptr[regnum];
+ // ADSP2181 Overlay register
+ if ((m_chip_type == CHIP_TYPE_ADSP2181) && (regnum >= 0xe))
+ {
+ switch (regnum)
+ {
+ case 0xe: ret = m_pmovlay; break;
+ case 0xf: ret = m_dmovlay; break;
+ default: break;
+ }
+ }
+
+ return ret;
}
int32_t adsp21xx_device::read_reg2(int regnum)
@@ -506,8 +541,8 @@ int32_t adsp21xx_device::read_reg3(int regnum)
case 0x05: return m_cntr;
case 0x06: return m_core.sb.s;
case 0x07: return m_px;
- case 0x08: if (!m_sport_rx_cb.isnull()) return m_sport_rx_cb(0); else return 0;
- case 0x0a: if (!m_sport_rx_cb.isnull()) return m_sport_rx_cb(1); else return 0;
+ case 0x08: return m_sport_rx_cb(0);
+ case 0x0a: return m_sport_rx_cb(1);
case 0x0f: return pc_stack_pop_val();
default: logerror("ADSP %04x: Reading from an invalid register! RGP=b11 RegCode=%1X\n", m_ppc, regnum); return 0;
}
@@ -539,8 +574,8 @@ inline void adsp21xx_device::modify_address(uint32_t ireg, uint32_t mreg)
inline void adsp21xx_device::data_write_dag1(uint32_t op, int32_t val)
{
- uint32_t ireg = (op >> 2) & 3;
- uint32_t mreg = op & 3;
+ uint32_t ireg = BIT(op, 2, 2);
+ uint32_t mreg = BIT(op, 0, 2);
uint32_t base = m_base[ireg];
uint32_t i = m_i[ireg];
uint32_t l = m_l[ireg];
@@ -563,8 +598,8 @@ inline void adsp21xx_device::data_write_dag1(uint32_t op, int32_t val)
inline uint32_t adsp21xx_device::data_read_dag1(uint32_t op)
{
- uint32_t ireg = (op >> 2) & 3;
- uint32_t mreg = op & 3;
+ uint32_t ireg = BIT(op, 2, 2);
+ uint32_t mreg = BIT(op, 0, 2);
uint32_t base = m_base[ireg];
uint32_t i = m_i[ireg];
uint32_t l = m_l[ireg];
@@ -588,8 +623,8 @@ inline uint32_t adsp21xx_device::data_read_dag1(uint32_t op)
inline void adsp21xx_device::data_write_dag2(uint32_t op, int32_t val)
{
- uint32_t ireg = 4 + ((op >> 2) & 3);
- uint32_t mreg = 4 + (op & 3);
+ uint32_t ireg = 4 + BIT(op, 2, 2);
+ uint32_t mreg = 4 + BIT(op, 0, 2);
uint32_t base = m_base[ireg];
uint32_t i = m_i[ireg];
uint32_t l = m_l[ireg];
@@ -605,8 +640,8 @@ inline void adsp21xx_device::data_write_dag2(uint32_t op, int32_t val)
inline uint32_t adsp21xx_device::data_read_dag2(uint32_t op)
{
- uint32_t ireg = 4 + ((op >> 2) & 3);
- uint32_t mreg = 4 + (op & 3);
+ uint32_t ireg = 4 + BIT(op, 2, 2);
+ uint32_t mreg = 4 + BIT(op, 0, 2);
uint32_t base = m_base[ireg];
uint32_t i = m_i[ireg];
uint32_t l = m_l[ireg];
@@ -627,8 +662,8 @@ inline uint32_t adsp21xx_device::data_read_dag2(uint32_t op)
inline void adsp21xx_device::pgm_write_dag2(uint32_t op, int32_t val)
{
- uint32_t ireg = 4 + ((op >> 2) & 3);
- uint32_t mreg = 4 + (op & 3);
+ uint32_t ireg = 4 + BIT(op, 2, 2);
+ uint32_t mreg = 4 + BIT(op, 0, 2);
uint32_t base = m_base[ireg];
uint32_t i = m_i[ireg];
uint32_t l = m_l[ireg];
@@ -644,8 +679,8 @@ inline void adsp21xx_device::pgm_write_dag2(uint32_t op, int32_t val)
inline uint32_t adsp21xx_device::pgm_read_dag2(uint32_t op)
{
- uint32_t ireg = 4 + ((op >> 2) & 3);
- uint32_t mreg = 4 + (op & 3);
+ uint32_t ireg = 4 + BIT(op, 2, 2);
+ uint32_t mreg = 4 + BIT(op, 0, 2);
uint32_t base = m_base[ireg];
uint32_t i = m_i[ireg];
uint32_t l = m_l[ireg];
@@ -686,135 +721,136 @@ inline uint32_t adsp21xx_device::pgm_read_dag2(uint32_t op)
ALU operations (result in AR)
===========================================================================*/
-void adsp21xx_device::alu_op_ar(int op)
+void adsp21xx_device::alu_op_ar(uint32_t op)
{
- int32_t xop = (op >> 8) & 7;
- int32_t yop = (op >> 11) & 3;
+ int32_t xop = BIT(op, 8, 3);
+ int32_t yop = BIT(op, 11, 2);
int32_t res;
- switch (op & (15<<13)) /*JB*/
+ switch (BIT(op, 13, 4)) //JB
{
- case 0x00<<13:
- /* Y Clear when y = 0 */
+ case 0x00:
+ // Y Clear when y = 0
res = ALU_GETYREG_UNSIGNED(yop);
CALC_NZ(res);
break;
- case 0x01<<13:
- /* Y + 1 PASS 1 when y = 0 */
+ case 0x01:
+ // Y + 1 PASS 1 when y = 0
yop = ALU_GETYREG_UNSIGNED(yop);
res = yop + 1;
CALC_NZ(res);
if (yop == 0x7fff) SET_V;
else if (yop == 0xffff) SET_C;
break;
- case 0x02<<13:
- /* X + Y + C */
+ case 0x02:
+ // X + Y + C
xop = ALU_GETXREG_UNSIGNED(xop);
yop = ALU_GETYREG_UNSIGNED(yop);
yop += GET_C >> 3;
res = xop + yop;
CALC_NZVC(xop, yop, res);
break;
- case 0x03<<13:
- /* X + Y X when y = 0 */
+ case 0x03:
+ // X + Y X when y = 0
xop = ALU_GETXREG_UNSIGNED(xop);
yop = ALU_GETYREG_UNSIGNED(yop);
res = xop + yop;
CALC_NZVC(xop, yop, res);
break;
- case 0x04<<13:
- /* NOT Y */
+ case 0x04:
+ // NOT Y
res = ALU_GETYREG_UNSIGNED(yop) ^ 0xffff;
CALC_NZ(res);
break;
- case 0x05<<13:
- /* -Y */
+ case 0x05:
+ // -Y
yop = ALU_GETYREG_UNSIGNED(yop);
res = -yop;
CALC_NZ(res);
if (yop == 0x8000) SET_V;
if (yop == 0x0000) SET_C;
break;
- case 0x06<<13:
- /* X - Y + C - 1 X + C - 1 when y = 0 */
+ case 0x06:
+ // X - Y + C - 1 X + C - 1 when y = 0
xop = ALU_GETXREG_UNSIGNED(xop);
yop = ALU_GETYREG_UNSIGNED(yop);
res = xop - yop + (GET_C >> 3) - 1;
CALC_NZVC_SUB(xop, yop, res);
break;
- case 0x07<<13:
- /* X - Y */
+ case 0x07:
+ // X - Y
xop = ALU_GETXREG_UNSIGNED(xop);
yop = ALU_GETYREG_UNSIGNED(yop);
res = xop - yop;
CALC_NZVC_SUB(xop, yop, res);
break;
- case 0x08<<13:
- /* Y - 1 PASS -1 when y = 0 */
+ case 0x08:
+ // Y - 1 PASS -1 when y = 0
yop = ALU_GETYREG_UNSIGNED(yop);
res = yop - 1;
CALC_NZ(res);
if (yop == 0x8000) SET_V;
else if (yop == 0x0000) SET_C;
break;
- case 0x09<<13:
- /* Y - X -X when y = 0 */
+ case 0x09:
+ // Y - X -X when y = 0
xop = ALU_GETXREG_UNSIGNED(xop);
yop = ALU_GETYREG_UNSIGNED(yop);
res = yop - xop;
CALC_NZVC_SUB(yop, xop, res);
break;
- case 0x0a<<13:
- /* Y - X + C - 1 -X + C - 1 when y = 0 */
+ case 0x0a:
+ // Y - X + C - 1 -X + C - 1 when y = 0
xop = ALU_GETXREG_UNSIGNED(xop);
yop = ALU_GETYREG_UNSIGNED(yop);
res = yop - xop + (GET_C >> 3) - 1;
CALC_NZVC_SUB(yop, xop, res);
break;
- case 0x0b<<13:
- /* NOT X */
+ case 0x0b:
+ // NOT X
res = ALU_GETXREG_UNSIGNED(xop) ^ 0xffff;
CALC_NZ(res);
break;
- case 0x0c<<13:
- /* X AND Y */
+ case 0x0c:
+ // X AND Y
xop = ALU_GETXREG_UNSIGNED(xop);
yop = ALU_GETYREG_UNSIGNED(yop);
res = xop & yop;
CALC_NZ(res);
break;
- case 0x0d<<13:
- /* X OR Y */
+ case 0x0d:
+ // X OR Y
xop = ALU_GETXREG_UNSIGNED(xop);
yop = ALU_GETYREG_UNSIGNED(yop);
res = xop | yop;
CALC_NZ(res);
break;
- case 0x0e<<13:
- /* X XOR Y */
+ case 0x0e:
+ // X XOR Y
xop = ALU_GETXREG_UNSIGNED(xop);
yop = ALU_GETYREG_UNSIGNED(yop);
res = xop ^ yop;
CALC_NZ(res);
break;
- case 0x0f<<13:
- /* ABS X */
+ case 0x0f:
+ // ABS X
xop = ALU_GETXREG_UNSIGNED(xop);
res = (xop & 0x8000) ? -xop : xop;
CLR_FLAGS;
+ CLR_S;
if (xop == 0) SET_Z;
if (xop == 0x8000) SET_N, SET_V;
if (xop & 0x8000) SET_S;
break;
default:
- res = 0; /* just to keep the compiler happy */
+ res = 0; // just to keep the compiler happy
break;
}
- /* saturate */
+ // saturate
if ((m_mstat & MSTAT_SATURATE) && GET_V) res = GET_C ? -32768 : 32767;
- /* set the final value */
+ // set the final value
m_core.ar.u = res;
}
@@ -824,123 +860,124 @@ void adsp21xx_device::alu_op_ar(int op)
ALU operations (result in AR, constant yop)
===========================================================================*/
-void adsp21xx_device::alu_op_ar_const(int op)
+void adsp21xx_device::alu_op_ar_const(uint32_t op)
{
- int32_t xop = (op >> 8) & 7;
- int32_t yop = constants[((op >> 5) & 0x07) | ((op >> 8) & 0x18)];
+ int32_t xop = BIT(op, 8, 3);
+ int32_t yop = constants[BIT(op, 5, 3) | BIT(op, 11, 2) << 3];
int32_t res;
- switch (op & (15<<13)) /*JB*/
+ switch (BIT(op, 13, 4)) //JB
{
- case 0x00<<13:
- /* Y Clear when y = 0 */
+ case 0x00:
+ // Y Clear when y = 0
res = yop;
CALC_NZ(res);
break;
- case 0x01<<13:
- /* Y + 1 PASS 1 when y = 0 */
+ case 0x01:
+ // Y + 1 PASS 1 when y = 0
res = yop + 1;
CALC_NZ(res);
if (yop == 0x7fff) SET_V;
else if (yop == 0xffff) SET_C;
break;
- case 0x02<<13:
- /* X + Y + C */
+ case 0x02:
+ // X + Y + C
xop = ALU_GETXREG_UNSIGNED(xop);
yop += GET_C >> 3;
res = xop + yop;
CALC_NZVC(xop, yop, res);
break;
- case 0x03<<13:
- /* X + Y X when y = 0 */
+ case 0x03:
+ // X + Y X when y = 0
xop = ALU_GETXREG_UNSIGNED(xop);
res = xop + yop;
CALC_NZVC(xop, yop, res);
break;
- case 0x04<<13:
- /* NOT Y */
+ case 0x04:
+ // NOT Y
res = yop ^ 0xffff;
CALC_NZ(res);
break;
- case 0x05<<13:
- /* -Y */
+ case 0x05:
+ // -Y
res = -yop;
CALC_NZ(res);
if (yop == 0x8000) SET_V;
if (yop == 0x0000) SET_C;
break;
- case 0x06<<13:
- /* X - Y + C - 1 X + C - 1 when y = 0 */
+ case 0x06:
+ // X - Y + C - 1 X + C - 1 when y = 0
xop = ALU_GETXREG_UNSIGNED(xop);
res = xop - yop + (GET_C >> 3) - 1;
CALC_NZVC_SUB(xop, yop, res);
break;
- case 0x07<<13:
- /* X - Y */
+ case 0x07:
+ // X - Y
xop = ALU_GETXREG_UNSIGNED(xop);
res = xop - yop;
CALC_NZVC_SUB(xop, yop, res);
break;
- case 0x08<<13:
- /* Y - 1 PASS -1 when y = 0 */
+ case 0x08:
+ // Y - 1 PASS -1 when y = 0
res = yop - 1;
CALC_NZ(res);
if (yop == 0x8000) SET_V;
else if (yop == 0x0000) SET_C;
break;
- case 0x09<<13:
- /* Y - X -X when y = 0 */
+ case 0x09:
+ // Y - X -X when y = 0
xop = ALU_GETXREG_UNSIGNED(xop);
res = yop - xop;
CALC_NZVC_SUB(yop, xop, res);
break;
- case 0x0a<<13:
- /* Y - X + C - 1 -X + C - 1 when y = 0 */
+ case 0x0a:
+ // Y - X + C - 1 -X + C - 1 when y = 0
xop = ALU_GETXREG_UNSIGNED(xop);
res = yop - xop + (GET_C >> 3) - 1;
CALC_NZVC_SUB(yop, xop, res);
break;
- case 0x0b<<13:
- /* NOT X */
+ case 0x0b:
+ // NOT X
res = ALU_GETXREG_UNSIGNED(xop) ^ 0xffff;
CALC_NZ(res);
break;
- case 0x0c<<13:
- /* X AND Y */
+ case 0x0c:
+ // X AND Y
xop = ALU_GETXREG_UNSIGNED(xop);
res = xop & yop;
CALC_NZ(res);
break;
- case 0x0d<<13:
- /* X OR Y */
+ case 0x0d:
+ // X OR Y
xop = ALU_GETXREG_UNSIGNED(xop);
res = xop | yop;
CALC_NZ(res);
break;
- case 0x0e<<13:
- /* X XOR Y */
+ case 0x0e:
+ // X XOR Y
xop = ALU_GETXREG_UNSIGNED(xop);
res = xop ^ yop;
CALC_NZ(res);
break;
- case 0x0f<<13:
- /* ABS X */
+ case 0x0f:
+ // ABS X
xop = ALU_GETXREG_UNSIGNED(xop);
res = (xop & 0x8000) ? -xop : xop;
CLR_FLAGS;
+ CLR_S;
if (xop == 0) SET_Z;
if (xop == 0x8000) SET_N, SET_V;
if (xop & 0x8000) SET_S;
break;
default:
- res = 0; /* just to keep the compiler happy */
+ res = 0; // just to keep the compiler happy
break;
}
- /* saturate */
+ // saturate
if ((m_mstat & MSTAT_SATURATE) && GET_V) res = GET_C ? -32768 : 32767;
- /* set the final value */
+ // set the final value
m_core.ar.u = res;
}
@@ -950,132 +987,133 @@ void adsp21xx_device::alu_op_ar_const(int op)
ALU operations (result in AF)
===========================================================================*/
-void adsp21xx_device::alu_op_af(int op)
+void adsp21xx_device::alu_op_af(uint32_t op)
{
- int32_t xop = (op >> 8) & 7;
- int32_t yop = (op >> 11) & 3;
+ int32_t xop = BIT(op, 8, 3);
+ int32_t yop = BIT(op, 11, 2);
int32_t res;
- switch (op & (15<<13)) /*JB*/
+ switch (BIT(op, 13, 4)) //JB
{
- case 0x00<<13:
- /* Y Clear when y = 0 */
+ case 0x00:
+ // Y Clear when y = 0
res = ALU_GETYREG_UNSIGNED(yop);
CALC_NZ(res);
break;
- case 0x01<<13:
- /* Y + 1 PASS 1 when y = 0 */
+ case 0x01:
+ // Y + 1 PASS 1 when y = 0
yop = ALU_GETYREG_UNSIGNED(yop);
res = yop + 1;
CALC_NZ(res);
if (yop == 0x7fff) SET_V;
else if (yop == 0xffff) SET_C;
break;
- case 0x02<<13:
- /* X + Y + C */
+ case 0x02:
+ // X + Y + C
xop = ALU_GETXREG_UNSIGNED(xop);
yop = ALU_GETYREG_UNSIGNED(yop);
yop += GET_C >> 3;
res = xop + yop;
CALC_NZVC(xop, yop, res);
break;
- case 0x03<<13:
- /* X + Y X when y = 0 */
+ case 0x03:
+ // X + Y X when y = 0
xop = ALU_GETXREG_UNSIGNED(xop);
yop = ALU_GETYREG_UNSIGNED(yop);
res = xop + yop;
CALC_NZVC(xop, yop, res);
break;
- case 0x04<<13:
- /* NOT Y */
+ case 0x04:
+ // NOT Y
res = ALU_GETYREG_UNSIGNED(yop) ^ 0xffff;
CALC_NZ(res);
break;
- case 0x05<<13:
- /* -Y */
+ case 0x05:
+ // -Y
yop = ALU_GETYREG_UNSIGNED(yop);
res = -yop;
CALC_NZ(res);
if (yop == 0x8000) SET_V;
if (yop == 0x0000) SET_C;
break;
- case 0x06<<13:
- /* X - Y + C - 1 X + C - 1 when y = 0 */
+ case 0x06:
+ // X - Y + C - 1 X + C - 1 when y = 0
xop = ALU_GETXREG_UNSIGNED(xop);
yop = ALU_GETYREG_UNSIGNED(yop);
res = xop - yop + (GET_C >> 3) - 1;
CALC_NZVC_SUB(xop, yop, res);
break;
- case 0x07<<13:
- /* X - Y */
+ case 0x07:
+ // X - Y
xop = ALU_GETXREG_UNSIGNED(xop);
yop = ALU_GETYREG_UNSIGNED(yop);
res = xop - yop;
CALC_NZVC_SUB(xop, yop, res);
break;
- case 0x08<<13:
- /* Y - 1 PASS -1 when y = 0 */
+ case 0x08:
+ // Y - 1 PASS -1 when y = 0
yop = ALU_GETYREG_UNSIGNED(yop);
res = yop - 1;
CALC_NZ(res);
if (yop == 0x8000) SET_V;
else if (yop == 0x0000) SET_C;
break;
- case 0x09<<13:
- /* Y - X -X when y = 0 */
+ case 0x09:
+ // Y - X -X when y = 0
xop = ALU_GETXREG_UNSIGNED(xop);
yop = ALU_GETYREG_UNSIGNED(yop);
res = yop - xop;
CALC_NZVC_SUB(yop, xop, res);
break;
- case 0x0a<<13:
- /* Y - X + C - 1 -X + C - 1 when y = 0 */
+ case 0x0a:
+ // Y - X + C - 1 -X + C - 1 when y = 0
xop = ALU_GETXREG_UNSIGNED(xop);
yop = ALU_GETYREG_UNSIGNED(yop);
res = yop - xop + (GET_C >> 3) - 1;
CALC_NZVC_SUB(yop, xop, res);
break;
- case 0x0b<<13:
- /* NOT X */
+ case 0x0b:
+ // NOT X
res = ALU_GETXREG_UNSIGNED(xop) ^ 0xffff;
CALC_NZ(res);
break;
- case 0x0c<<13:
- /* X AND Y */
+ case 0x0c:
+ // X AND Y
xop = ALU_GETXREG_UNSIGNED(xop);
yop = ALU_GETYREG_UNSIGNED(yop);
res = xop & yop;
CALC_NZ(res);
break;
- case 0x0d<<13:
- /* X OR Y */
+ case 0x0d:
+ // X OR Y
xop = ALU_GETXREG_UNSIGNED(xop);
yop = ALU_GETYREG_UNSIGNED(yop);
res = xop | yop;
CALC_NZ(res);
break;
- case 0x0e<<13:
- /* X XOR Y */
+ case 0x0e:
+ // X XOR Y
xop = ALU_GETXREG_UNSIGNED(xop);
yop = ALU_GETYREG_UNSIGNED(yop);
res = xop ^ yop;
CALC_NZ(res);
break;
- case 0x0f<<13:
- /* ABS X */
+ case 0x0f:
+ // ABS X
xop = ALU_GETXREG_UNSIGNED(xop);
res = (xop & 0x8000) ? -xop : xop;
CLR_FLAGS;
+ CLR_S;
if (xop == 0) SET_Z;
if (xop == 0x8000) SET_N, SET_V;
if (xop & 0x8000) SET_S;
break;
default:
- res = 0; /* just to keep the compiler happy */
+ res = 0; // just to keep the compiler happy
break;
}
- /* set the final value */
+ // set the final value
m_core.af.u = res;
}
@@ -1085,120 +1123,121 @@ void adsp21xx_device::alu_op_af(int op)
ALU operations (result in AF, constant yop)
===========================================================================*/
-void adsp21xx_device::alu_op_af_const(int op)
+void adsp21xx_device::alu_op_af_const(uint32_t op)
{
- int32_t xop = (op >> 8) & 7;
- int32_t yop = constants[((op >> 5) & 0x07) | ((op >> 8) & 0x18)];
+ int32_t xop = BIT(op, 8, 3);
+ int32_t yop = constants[BIT(op, 5, 3) | BIT(op, 11, 2) << 3];
int32_t res;
- switch (op & (15<<13)) /*JB*/
+ switch (BIT(op, 13, 4)) //JB
{
- case 0x00<<13:
- /* Y Clear when y = 0 */
+ case 0x00:
+ // Y Clear when y = 0
res = yop;
CALC_NZ(res);
break;
- case 0x01<<13:
- /* Y + 1 PASS 1 when y = 0 */
+ case 0x01:
+ // Y + 1 PASS 1 when y = 0
res = yop + 1;
CALC_NZ(res);
if (yop == 0x7fff) SET_V;
else if (yop == 0xffff) SET_C;
break;
- case 0x02<<13:
- /* X + Y + C */
+ case 0x02:
+ // X + Y + C
xop = ALU_GETXREG_UNSIGNED(xop);
yop += GET_C >> 3;
res = xop + yop;
CALC_NZVC(xop, yop, res);
break;
- case 0x03<<13:
- /* X + Y X when y = 0 */
+ case 0x03:
+ // X + Y X when y = 0
xop = ALU_GETXREG_UNSIGNED(xop);
res = xop + yop;
CALC_NZVC(xop, yop, res);
break;
- case 0x04<<13:
- /* NOT Y */
+ case 0x04:
+ // NOT Y
res = yop ^ 0xffff;
CALC_NZ(res);
break;
- case 0x05<<13:
- /* -Y */
+ case 0x05:
+ // -Y
res = -yop;
CALC_NZ(res);
if (yop == 0x8000) SET_V;
if (yop == 0x0000) SET_C;
break;
- case 0x06<<13:
- /* X - Y + C - 1 X + C - 1 when y = 0 */
+ case 0x06:
+ // X - Y + C - 1 X + C - 1 when y = 0
xop = ALU_GETXREG_UNSIGNED(xop);
res = xop - yop + (GET_C >> 3) - 1;
CALC_NZVC_SUB(xop, yop, res);
break;
- case 0x07<<13:
- /* X - Y */
+ case 0x07:
+ // X - Y
xop = ALU_GETXREG_UNSIGNED(xop);
res = xop - yop;
CALC_NZVC_SUB(xop, yop, res);
break;
- case 0x08<<13:
- /* Y - 1 PASS -1 when y = 0 */
+ case 0x08:
+ // Y - 1 PASS -1 when y = 0
res = yop - 1;
CALC_NZ(res);
if (yop == 0x8000) SET_V;
else if (yop == 0x0000) SET_C;
break;
- case 0x09<<13:
- /* Y - X -X when y = 0 */
+ case 0x09:
+ // Y - X -X when y = 0
xop = ALU_GETXREG_UNSIGNED(xop);
res = yop - xop;
CALC_NZVC_SUB(yop, xop, res);
break;
- case 0x0a<<13:
- /* Y - X + C - 1 -X + C - 1 when y = 0 */
+ case 0x0a:
+ // Y - X + C - 1 -X + C - 1 when y = 0
xop = ALU_GETXREG_UNSIGNED(xop);
res = yop - xop + (GET_C >> 3) - 1;
CALC_NZVC_SUB(yop, xop, res);
break;
- case 0x0b<<13:
- /* NOT X */
+ case 0x0b:
+ // NOT X
res = ALU_GETXREG_UNSIGNED(xop) ^ 0xffff;
CALC_NZ(res);
break;
- case 0x0c<<13:
- /* X AND Y */
+ case 0x0c:
+ // X AND Y
xop = ALU_GETXREG_UNSIGNED(xop);
res = xop & yop;
CALC_NZ(res);
break;
- case 0x0d<<13:
- /* X OR Y */
+ case 0x0d:
+ // X OR Y
xop = ALU_GETXREG_UNSIGNED(xop);
res = xop | yop;
CALC_NZ(res);
break;
- case 0x0e<<13:
- /* X XOR Y */
+ case 0x0e:
+ // X XOR Y
xop = ALU_GETXREG_UNSIGNED(xop);
res = xop ^ yop;
CALC_NZ(res);
break;
- case 0x0f<<13:
- /* ABS X */
+ case 0x0f:
+ // ABS X
xop = ALU_GETXREG_UNSIGNED(xop);
res = (xop & 0x8000) ? -xop : xop;
CLR_FLAGS;
+ CLR_S;
if (xop == 0) SET_Z;
if (xop == 0x8000) SET_N, SET_V;
if (xop & 0x8000) SET_S;
break;
default:
- res = 0; /* just to keep the compiler happy */
+ res = 0; // just to keep the compiler happy
break;
}
- /* set the final value */
+ // set the final value
m_core.af.u = res;
}
@@ -1208,122 +1247,123 @@ void adsp21xx_device::alu_op_af_const(int op)
ALU operations (no result)
===========================================================================*/
-void adsp21xx_device::alu_op_none(int op)
+void adsp21xx_device::alu_op_none(uint32_t op)
{
- int32_t xop = (op >> 8) & 7;
- int32_t yop = (op >> 11) & 3;
+ int32_t xop = BIT(op, 8, 3);
+ int32_t yop = BIT(op, 11, 2);
int32_t res;
- switch (op & (15<<13)) /*JB*/
+ switch (BIT(op, 13, 4)) //JB
{
- case 0x00<<13:
- /* Y Clear when y = 0 */
+ case 0x00:
+ // Y Clear when y = 0
res = ALU_GETYREG_UNSIGNED(yop);
CALC_NZ(res);
break;
- case 0x01<<13:
- /* Y + 1 PASS 1 when y = 0 */
+ case 0x01:
+ // Y + 1 PASS 1 when y = 0
yop = ALU_GETYREG_UNSIGNED(yop);
res = yop + 1;
CALC_NZ(res);
if (yop == 0x7fff) SET_V;
else if (yop == 0xffff) SET_C;
break;
- case 0x02<<13:
- /* X + Y + C */
+ case 0x02:
+ // X + Y + C
xop = ALU_GETXREG_UNSIGNED(xop);
yop = ALU_GETYREG_UNSIGNED(yop);
yop += GET_C >> 3;
res = xop + yop;
CALC_NZVC(xop, yop, res);
break;
- case 0x03<<13:
- /* X + Y X when y = 0 */
+ case 0x03:
+ // X + Y X when y = 0
xop = ALU_GETXREG_UNSIGNED(xop);
yop = ALU_GETYREG_UNSIGNED(yop);
res = xop + yop;
CALC_NZVC(xop, yop, res);
break;
- case 0x04<<13:
- /* NOT Y */
+ case 0x04:
+ // NOT Y
res = ALU_GETYREG_UNSIGNED(yop) ^ 0xffff;
CALC_NZ(res);
break;
- case 0x05<<13:
- /* -Y */
+ case 0x05:
+ // -Y
yop = ALU_GETYREG_UNSIGNED(yop);
res = -yop;
CALC_NZ(res);
if (yop == 0x8000) SET_V;
if (yop == 0x0000) SET_C;
break;
- case 0x06<<13:
- /* X - Y + C - 1 X + C - 1 when y = 0 */
+ case 0x06:
+ // X - Y + C - 1 X + C - 1 when y = 0
xop = ALU_GETXREG_UNSIGNED(xop);
yop = ALU_GETYREG_UNSIGNED(yop);
res = xop - yop + (GET_C >> 3) - 1;
CALC_NZVC_SUB(xop, yop, res);
break;
- case 0x07<<13:
- /* X - Y */
+ case 0x07:
+ // X - Y
xop = ALU_GETXREG_UNSIGNED(xop);
yop = ALU_GETYREG_UNSIGNED(yop);
res = xop - yop;
CALC_NZVC_SUB(xop, yop, res);
break;
- case 0x08<<13:
- /* Y - 1 PASS -1 when y = 0 */
+ case 0x08:
+ // Y - 1 PASS -1 when y = 0
yop = ALU_GETYREG_UNSIGNED(yop);
res = yop - 1;
CALC_NZ(res);
if (yop == 0x8000) SET_V;
else if (yop == 0x0000) SET_C;
break;
- case 0x09<<13:
- /* Y - X -X when y = 0 */
+ case 0x09:
+ // Y - X -X when y = 0
xop = ALU_GETXREG_UNSIGNED(xop);
yop = ALU_GETYREG_UNSIGNED(yop);
res = yop - xop;
CALC_NZVC_SUB(yop, xop, res);
break;
- case 0x0a<<13:
- /* Y - X + C - 1 -X + C - 1 when y = 0 */
+ case 0x0a:
+ // Y - X + C - 1 -X + C - 1 when y = 0
xop = ALU_GETXREG_UNSIGNED(xop);
yop = ALU_GETYREG_UNSIGNED(yop);
res = yop - xop + (GET_C >> 3) - 1;
CALC_NZVC_SUB(yop, xop, res);
break;
- case 0x0b<<13:
- /* NOT X */
+ case 0x0b:
+ // NOT X
res = ALU_GETXREG_UNSIGNED(xop) ^ 0xffff;
CALC_NZ(res);
break;
- case 0x0c<<13:
- /* X AND Y */
+ case 0x0c:
+ // X AND Y
xop = ALU_GETXREG_UNSIGNED(xop);
yop = ALU_GETYREG_UNSIGNED(yop);
res = xop & yop;
CALC_NZ(res);
break;
- case 0x0d<<13:
- /* X OR Y */
+ case 0x0d:
+ // X OR Y
xop = ALU_GETXREG_UNSIGNED(xop);
yop = ALU_GETYREG_UNSIGNED(yop);
res = xop | yop;
CALC_NZ(res);
break;
- case 0x0e<<13:
- /* X XOR Y */
+ case 0x0e:
+ // X XOR Y
xop = ALU_GETXREG_UNSIGNED(xop);
yop = ALU_GETYREG_UNSIGNED(yop);
res = xop ^ yop;
CALC_NZ(res);
break;
- case 0x0f<<13:
- /* ABS X */
+ case 0x0f:
+ // ABS X
xop = ALU_GETXREG_UNSIGNED(xop);
res = (xop & 0x8000) ? -xop : xop;
CLR_FLAGS;
+ CLR_S;
if (xop == 0) SET_Z;
if (xop == 0x8000) SET_N, SET_V;
if (xop & 0x8000) SET_S;
@@ -1337,21 +1377,21 @@ void adsp21xx_device::alu_op_none(int op)
MAC operations (result in MR)
===========================================================================*/
-void adsp21xx_device::mac_op_mr(int op)
+void adsp21xx_device::mac_op_mr(uint32_t op)
{
- int8_t shift = ((m_mstat & MSTAT_INTEGER) >> 4) ^ 1;
- int32_t xop = (op >> 8) & 7;
- int32_t yop = (op >> 11) & 3;
+ int8_t shift = (m_mstat & MSTAT_INTEGER) ? 0 : 1;
+ int32_t xop = BIT(op, 8, 3);
+ int32_t yop = BIT(op, 11, 2);
int32_t temp;
int64_t res;
- switch (op & (15<<13)) /*JB*/
+ switch (BIT(op, 13, 4)) //JB
{
- case 0x00<<13:
- /* no-op */
+ case 0x00:
+ // no-op
return;
- case 0x01<<13:
- /* X * Y (RND) */
+ case 0x01:
+ // X * Y (RND)
xop = MAC_GETXREG_SIGNED(xop);
yop = MAC_GETYREG_SIGNED(yop);
temp = (xop * yop) << shift;
@@ -1366,8 +1406,8 @@ void adsp21xx_device::mac_op_mr(int op)
res &= ~((uint64_t)0x10000);
#endif
break;
- case 0x02<<13:
- /* MR + X * Y (RND) */
+ case 0x02:
+ // MR + X * Y (RND)
xop = MAC_GETXREG_SIGNED(xop);
yop = MAC_GETYREG_SIGNED(yop);
temp = (xop * yop) << shift;
@@ -1382,8 +1422,8 @@ void adsp21xx_device::mac_op_mr(int op)
res &= ~((uint64_t)0x10000);
#endif
break;
- case 0x03<<13:
- /* MR - X * Y (RND) */
+ case 0x03:
+ // MR - X * Y (RND)
xop = MAC_GETXREG_SIGNED(xop);
yop = MAC_GETYREG_SIGNED(yop);
temp = (xop * yop) << shift;
@@ -1398,97 +1438,97 @@ void adsp21xx_device::mac_op_mr(int op)
res &= ~((uint64_t)0x10000);
#endif
break;
- case 0x04<<13:
- /* X * Y (SS) Clear when y = 0 */
+ case 0x04:
+ // X * Y (SS) Clear when y = 0
xop = MAC_GETXREG_SIGNED(xop);
yop = MAC_GETYREG_SIGNED(yop);
temp = (xop * yop) << shift;
res = (int64_t)temp;
break;
- case 0x05<<13:
- /* X * Y (SU) */
+ case 0x05:
+ // X * Y (SU)
xop = MAC_GETXREG_SIGNED(xop);
yop = MAC_GETYREG_UNSIGNED(yop);
temp = (xop * yop) << shift;
res = (int64_t)temp;
break;
- case 0x06<<13:
- /* X * Y (US) */
+ case 0x06:
+ // X * Y (US)
xop = MAC_GETXREG_UNSIGNED(xop);
yop = MAC_GETYREG_SIGNED(yop);
temp = (xop * yop) << shift;
res = (int64_t)temp;
break;
- case 0x07<<13:
- /* X * Y (UU) */
+ case 0x07:
+ // X * Y (UU)
xop = MAC_GETXREG_UNSIGNED(xop);
yop = MAC_GETYREG_UNSIGNED(yop);
temp = (xop * yop) << shift;
res = (int64_t)temp;
break;
- case 0x08<<13:
- /* MR + X * Y (SS) */
+ case 0x08:
+ // MR + X * Y (SS)
xop = MAC_GETXREG_SIGNED(xop);
yop = MAC_GETYREG_SIGNED(yop);
temp = (xop * yop) << shift;
res = m_core.mr.mr + (int64_t)temp;
break;
- case 0x09<<13:
- /* MR + X * Y (SU) */
+ case 0x09:
+ // MR + X * Y (SU)
xop = MAC_GETXREG_SIGNED(xop);
yop = MAC_GETYREG_UNSIGNED(yop);
temp = (xop * yop) << shift;
res = m_core.mr.mr + (int64_t)temp;
break;
- case 0x0a<<13:
- /* MR + X * Y (US) */
+ case 0x0a:
+ // MR + X * Y (US)
xop = MAC_GETXREG_UNSIGNED(xop);
yop = MAC_GETYREG_SIGNED(yop);
temp = (xop * yop) << shift;
res = m_core.mr.mr + (int64_t)temp;
break;
- case 0x0b<<13:
- /* MR + X * Y (UU) */
+ case 0x0b:
+ // MR + X * Y (UU)
xop = MAC_GETXREG_UNSIGNED(xop);
yop = MAC_GETYREG_UNSIGNED(yop);
temp = (xop * yop) << shift;
res = m_core.mr.mr + (int64_t)temp;
break;
- case 0x0c<<13:
- /* MR - X * Y (SS) */
+ case 0x0c:
+ // MR - X * Y (SS)
xop = MAC_GETXREG_SIGNED(xop);
yop = MAC_GETYREG_SIGNED(yop);
temp = (xop * yop) << shift;
res = m_core.mr.mr - (int64_t)temp;
break;
- case 0x0d<<13:
- /* MR - X * Y (SU) */
+ case 0x0d:
+ // MR - X * Y (SU)
xop = MAC_GETXREG_SIGNED(xop);
yop = MAC_GETYREG_UNSIGNED(yop);
temp = (xop * yop) << shift;
res = m_core.mr.mr - (int64_t)temp;
break;
- case 0x0e<<13:
- /* MR - X * Y (US) */
+ case 0x0e:
+ // MR - X * Y (US)
xop = MAC_GETXREG_UNSIGNED(xop);
yop = MAC_GETYREG_SIGNED(yop);
temp = (xop * yop) << shift;
res = m_core.mr.mr - (int64_t)temp;
break;
- case 0x0f<<13:
- /* MR - X * Y (UU) */
+ case 0x0f:
+ // MR - X * Y (UU)
xop = MAC_GETXREG_UNSIGNED(xop);
yop = MAC_GETYREG_UNSIGNED(yop);
temp = (xop * yop) << shift;
res = m_core.mr.mr - (int64_t)temp;
break;
default:
- res = 0; /* just to keep the compiler happy */
+ res = 0; // just to keep the compiler happy
break;
}
- /* set the final value */
- temp = (res >> 31) & 0x1ff;
+ // set the final value
+ temp = BIT(res, 31, 9);
CLR_MV;
if (temp != 0x000 && temp != 0x1ff) SET_MV;
m_core.mr.mr = res;
@@ -1500,20 +1540,20 @@ void adsp21xx_device::mac_op_mr(int op)
MAC operations (result in MR, yop == xop)
===========================================================================*/
-void adsp21xx_device::mac_op_mr_xop(int op)
+void adsp21xx_device::mac_op_mr_xop(uint32_t op)
{
- int8_t shift = ((m_mstat & MSTAT_INTEGER) >> 4) ^ 1;
- int32_t xop = (op >> 8) & 7;
+ int8_t shift = (m_mstat & MSTAT_INTEGER) ? 0 : 1;
+ int32_t xop = BIT(op, 8, 3);
int32_t temp;
int64_t res;
- switch (op & (15<<13)) /*JB*/
+ switch (BIT(op, 13, 4)) //JB
{
- case 0x00<<13:
- /* no-op */
+ case 0x00:
+ // no-op
return;
- case 0x01<<13:
- /* X * Y (RND) */
+ case 0x01:
+ // X * Y (RND)
xop = MAC_GETXREG_SIGNED(xop);
temp = (xop * xop) << shift;
res = (int64_t)temp;
@@ -1527,8 +1567,8 @@ void adsp21xx_device::mac_op_mr_xop(int op)
res &= ~((uint64_t)0x10000);
#endif
break;
- case 0x02<<13:
- /* MR + X * Y (RND) */
+ case 0x02:
+ // MR + X * Y (RND)
xop = MAC_GETXREG_SIGNED(xop);
temp = (xop * xop) << shift;
res = m_core.mr.mr + (int64_t)temp;
@@ -1542,8 +1582,8 @@ void adsp21xx_device::mac_op_mr_xop(int op)
res &= ~((uint64_t)0x10000);
#endif
break;
- case 0x03<<13:
- /* MR - X * Y (RND) */
+ case 0x03:
+ // MR - X * Y (RND)
xop = MAC_GETXREG_SIGNED(xop);
temp = (xop * xop) << shift;
res = m_core.mr.mr - (int64_t)temp;
@@ -1557,85 +1597,85 @@ void adsp21xx_device::mac_op_mr_xop(int op)
res &= ~((uint64_t)0x10000);
#endif
break;
- case 0x04<<13:
- /* X * Y (SS) Clear when y = 0 */
+ case 0x04:
+ // X * Y (SS) Clear when y = 0
xop = MAC_GETXREG_SIGNED(xop);
temp = (xop * xop) << shift;
res = (int64_t)temp;
break;
- case 0x05<<13:
- /* X * Y (SU) */
+ case 0x05:
+ // X * Y (SU)
xop = MAC_GETXREG_SIGNED(xop);
temp = (xop * xop) << shift;
res = (int64_t)temp;
break;
- case 0x06<<13:
- /* X * Y (US) */
+ case 0x06:
+ // X * Y (US)
xop = MAC_GETXREG_UNSIGNED(xop);
temp = (xop * xop) << shift;
res = (int64_t)temp;
break;
- case 0x07<<13:
- /* X * Y (UU) */
+ case 0x07:
+ // X * Y (UU)
xop = MAC_GETXREG_UNSIGNED(xop);
temp = (xop * xop) << shift;
res = (int64_t)temp;
break;
- case 0x08<<13:
- /* MR + X * Y (SS) */
+ case 0x08:
+ // MR + X * Y (SS)
xop = MAC_GETXREG_SIGNED(xop);
temp = (xop * xop) << shift;
res = m_core.mr.mr + (int64_t)temp;
break;
- case 0x09<<13:
- /* MR + X * Y (SU) */
+ case 0x09:
+ // MR + X * Y (SU)
xop = MAC_GETXREG_SIGNED(xop);
temp = (xop * xop) << shift;
res = m_core.mr.mr + (int64_t)temp;
break;
- case 0x0a<<13:
- /* MR + X * Y (US) */
+ case 0x0a:
+ // MR + X * Y (US)
xop = MAC_GETXREG_UNSIGNED(xop);
temp = (xop * xop) << shift;
res = m_core.mr.mr + (int64_t)temp;
break;
- case 0x0b<<13:
- /* MR + X * Y (UU) */
+ case 0x0b:
+ // MR + X * Y (UU)
xop = MAC_GETXREG_UNSIGNED(xop);
temp = (xop * xop) << shift;
res = m_core.mr.mr + (int64_t)temp;
break;
- case 0x0c<<13:
- /* MR - X * Y (SS) */
+ case 0x0c:
+ // MR - X * Y (SS)
xop = MAC_GETXREG_SIGNED(xop);
temp = (xop * xop) << shift;
res = m_core.mr.mr - (int64_t)temp;
break;
- case 0x0d<<13:
- /* MR - X * Y (SU) */
+ case 0x0d:
+ // MR - X * Y (SU)
xop = MAC_GETXREG_SIGNED(xop);
temp = (xop * xop) << shift;
res = m_core.mr.mr - (int64_t)temp;
break;
- case 0x0e<<13:
- /* MR - X * Y (US) */
+ case 0x0e:
+ // MR - X * Y (US)
xop = MAC_GETXREG_UNSIGNED(xop);
temp = (xop * xop) << shift;
res = m_core.mr.mr - (int64_t)temp;
break;
- case 0x0f<<13:
- /* MR - X * Y (UU) */
+ case 0x0f:
+ // MR - X * Y (UU)
xop = MAC_GETXREG_UNSIGNED(xop);
temp = (xop * xop) << shift;
res = m_core.mr.mr - (int64_t)temp;
break;
default:
- res = 0; /* just to keep the compiler happy */
+ res = 0; // just to keep the compiler happy
break;
}
- /* set the final value */
- temp = (res >> 31) & 0x1ff;
+ // set the final value
+ temp = BIT(res, 31, 9);
CLR_MV;
if (temp != 0x000 && temp != 0x1ff) SET_MV;
m_core.mr.mr = res;
@@ -1647,21 +1687,21 @@ void adsp21xx_device::mac_op_mr_xop(int op)
MAC operations (result in MF)
===========================================================================*/
-void adsp21xx_device::mac_op_mf(int op)
+void adsp21xx_device::mac_op_mf(uint32_t op)
{
- int8_t shift = ((m_mstat & MSTAT_INTEGER) >> 4) ^ 1;
- int32_t xop = (op >> 8) & 7;
- int32_t yop = (op >> 11) & 3;
+ int8_t shift = (m_mstat & MSTAT_INTEGER) ? 0 : 1;
+ int32_t xop = BIT(op, 8, 3);
+ int32_t yop = BIT(op, 11, 2);
int32_t temp;
int64_t res;
- switch (op & (15<<13)) /*JB*/
+ switch (BIT(op, 13, 4)) //JB
{
- case 0x00<<13:
- /* no-op */
+ case 0x00:
+ // no-op
return;
- case 0x01<<13:
- /* X * Y (RND) */
+ case 0x01:
+ // X * Y (RND)
xop = MAC_GETXREG_SIGNED(xop);
yop = MAC_GETYREG_SIGNED(yop);
temp = (xop * yop) << shift;
@@ -1676,8 +1716,8 @@ void adsp21xx_device::mac_op_mf(int op)
res &= ~((uint64_t)0x10000);
#endif
break;
- case 0x02<<13:
- /* MR + X * Y (RND) */
+ case 0x02:
+ // MR + X * Y (RND)
xop = MAC_GETXREG_SIGNED(xop);
yop = MAC_GETYREG_SIGNED(yop);
temp = (xop * yop) << shift;
@@ -1692,8 +1732,8 @@ void adsp21xx_device::mac_op_mf(int op)
res &= ~((uint64_t)0x10000);
#endif
break;
- case 0x03<<13:
- /* MR - X * Y (RND) */
+ case 0x03:
+ // MR - X * Y (RND)
xop = MAC_GETXREG_SIGNED(xop);
yop = MAC_GETYREG_SIGNED(yop);
temp = (xop * yop) << shift;
@@ -1708,96 +1748,96 @@ void adsp21xx_device::mac_op_mf(int op)
res &= ~((uint64_t)0x10000);
#endif
break;
- case 0x04<<13:
- /* X * Y (SS) Clear when y = 0 */
+ case 0x04:
+ // X * Y (SS) Clear when y = 0
xop = MAC_GETXREG_SIGNED(xop);
yop = MAC_GETYREG_SIGNED(yop);
temp = (xop * yop) << shift;
res = (int64_t)temp;
break;
- case 0x05<<13:
- /* X * Y (SU) */
+ case 0x05:
+ // X * Y (SU)
xop = MAC_GETXREG_SIGNED(xop);
yop = MAC_GETYREG_UNSIGNED(yop);
temp = (xop * yop) << shift;
res = (int64_t)temp;
break;
- case 0x06<<13:
- /* X * Y (US) */
+ case 0x06:
+ // X * Y (US)
xop = MAC_GETXREG_UNSIGNED(xop);
yop = MAC_GETYREG_SIGNED(yop);
temp = (xop * yop) << shift;
res = (int64_t)temp;
break;
- case 0x07<<13:
- /* X * Y (UU) */
+ case 0x07:
+ // X * Y (UU)
xop = MAC_GETXREG_UNSIGNED(xop);
yop = MAC_GETYREG_UNSIGNED(yop);
temp = (xop * yop) << shift;
res = (int64_t)temp;
break;
- case 0x08<<13:
- /* MR + X * Y (SS) */
+ case 0x08:
+ // MR + X * Y (SS)
xop = MAC_GETXREG_SIGNED(xop);
yop = MAC_GETYREG_SIGNED(yop);
temp = (xop * yop) << shift;
res = m_core.mr.mr + (int64_t)temp;
break;
- case 0x09<<13:
- /* MR + X * Y (SU) */
+ case 0x09:
+ // MR + X * Y (SU)
xop = MAC_GETXREG_SIGNED(xop);
yop = MAC_GETYREG_UNSIGNED(yop);
temp = (xop * yop) << shift;
res = m_core.mr.mr + (int64_t)temp;
break;
- case 0x0a<<13:
- /* MR + X * Y (US) */
+ case 0x0a:
+ // MR + X * Y (US)
xop = MAC_GETXREG_UNSIGNED(xop);
yop = MAC_GETYREG_SIGNED(yop);
temp = (xop * yop) << shift;
res = m_core.mr.mr + (int64_t)temp;
break;
- case 0x0b<<13:
- /* MR + X * Y (UU) */
+ case 0x0b:
+ // MR + X * Y (UU)
xop = MAC_GETXREG_UNSIGNED(xop);
yop = MAC_GETYREG_UNSIGNED(yop);
temp = (xop * yop) << shift;
res = m_core.mr.mr + (int64_t)temp;
break;
- case 0x0c<<13:
- /* MR - X * Y (SS) */
+ case 0x0c:
+ // MR - X * Y (SS)
xop = MAC_GETXREG_SIGNED(xop);
yop = MAC_GETYREG_SIGNED(yop);
temp = (xop * yop) << shift;
res = m_core.mr.mr - (int64_t)temp;
break;
- case 0x0d<<13:
- /* MR - X * Y (SU) */
+ case 0x0d:
+ // MR - X * Y (SU)
xop = MAC_GETXREG_SIGNED(xop);
yop = MAC_GETYREG_UNSIGNED(yop);
temp = (xop * yop) << shift;
res = m_core.mr.mr - (int64_t)temp;
break;
- case 0x0e<<13:
- /* MR - X * Y (US) */
+ case 0x0e:
+ // MR - X * Y (US)
xop = MAC_GETXREG_UNSIGNED(xop);
yop = MAC_GETYREG_SIGNED(yop);
temp = (xop * yop) << shift;
res = m_core.mr.mr - (int64_t)temp;
break;
- case 0x0f<<13:
- /* MR - X * Y (UU) */
+ case 0x0f:
+ // MR - X * Y (UU)
xop = MAC_GETXREG_UNSIGNED(xop);
yop = MAC_GETYREG_UNSIGNED(yop);
temp = (xop * yop) << shift;
res = m_core.mr.mr - (int64_t)temp;
break;
default:
- res = 0; /* just to keep the compiler happy */
+ res = 0; // just to keep the compiler happy
break;
}
- /* set the final value */
+ // set the final value
m_core.mf.u = (uint32_t)res >> 16;
}
@@ -1807,20 +1847,20 @@ void adsp21xx_device::mac_op_mf(int op)
MAC operations (result in MF, yop == xop)
===========================================================================*/
-void adsp21xx_device::mac_op_mf_xop(int op)
+void adsp21xx_device::mac_op_mf_xop(uint32_t op)
{
- int8_t shift = ((m_mstat & MSTAT_INTEGER) >> 4) ^ 1;
- int32_t xop = (op >> 8) & 7;
+ int8_t shift = (m_mstat & MSTAT_INTEGER) ? 0 : 1;
+ int32_t xop = BIT(op, 8, 3);
int32_t temp;
int64_t res;
- switch (op & (15<<13)) /*JB*/
+ switch (BIT(op, 13, 4)) //JB
{
- case 0x00<<13:
- /* no-op */
+ case 0x00:
+ // no-op
return;
- case 0x01<<13:
- /* X * Y (RND) */
+ case 0x01:
+ // X * Y (RND)
xop = MAC_GETXREG_SIGNED(xop);
temp = (xop * xop) << shift;
res = (int64_t)temp;
@@ -1834,8 +1874,8 @@ void adsp21xx_device::mac_op_mf_xop(int op)
res &= ~((uint64_t)0x10000);
#endif
break;
- case 0x02<<13:
- /* MR + X * Y (RND) */
+ case 0x02:
+ // MR + X * Y (RND)
xop = MAC_GETXREG_SIGNED(xop);
temp = (xop * xop) << shift;
res = m_core.mr.mr + (int64_t)temp;
@@ -1849,8 +1889,8 @@ void adsp21xx_device::mac_op_mf_xop(int op)
res &= ~((uint64_t)0x10000);
#endif
break;
- case 0x03<<13:
- /* MR - X * Y (RND) */
+ case 0x03:
+ // MR - X * Y (RND)
xop = MAC_GETXREG_SIGNED(xop);
temp = (xop * xop) << shift;
res = m_core.mr.mr - (int64_t)temp;
@@ -1864,84 +1904,84 @@ void adsp21xx_device::mac_op_mf_xop(int op)
res &= ~((uint64_t)0x10000);
#endif
break;
- case 0x04<<13:
- /* X * Y (SS) Clear when y = 0 */
+ case 0x04:
+ // X * Y (SS) Clear when y = 0
xop = MAC_GETXREG_SIGNED(xop);
temp = (xop * xop) << shift;
res = (int64_t)temp;
break;
- case 0x05<<13:
- /* X * Y (SU) */
+ case 0x05:
+ // X * Y (SU)
xop = MAC_GETXREG_SIGNED(xop);
temp = (xop * xop) << shift;
res = (int64_t)temp;
break;
- case 0x06<<13:
- /* X * Y (US) */
+ case 0x06:
+ // X * Y (US)
xop = MAC_GETXREG_UNSIGNED(xop);
temp = (xop * xop) << shift;
res = (int64_t)temp;
break;
- case 0x07<<13:
- /* X * Y (UU) */
+ case 0x07:
+ // X * Y (UU)
xop = MAC_GETXREG_UNSIGNED(xop);
temp = (xop * xop) << shift;
res = (int64_t)temp;
break;
- case 0x08<<13:
- /* MR + X * Y (SS) */
+ case 0x08:
+ // MR + X * Y (SS)
xop = MAC_GETXREG_SIGNED(xop);
temp = (xop * xop) << shift;
res = m_core.mr.mr + (int64_t)temp;
break;
- case 0x09<<13:
- /* MR + X * Y (SU) */
+ case 0x09:
+ // MR + X * Y (SU)
xop = MAC_GETXREG_SIGNED(xop);
temp = (xop * xop) << shift;
res = m_core.mr.mr + (int64_t)temp;
break;
- case 0x0a<<13:
- /* MR + X * Y (US) */
+ case 0x0a:
+ // MR + X * Y (US)
xop = MAC_GETXREG_UNSIGNED(xop);
temp = (xop * xop) << shift;
res = m_core.mr.mr + (int64_t)temp;
break;
- case 0x0b<<13:
- /* MR + X * Y (UU) */
+ case 0x0b:
+ // MR + X * Y (UU)
xop = MAC_GETXREG_UNSIGNED(xop);
temp = (xop * xop) << shift;
res = m_core.mr.mr + (int64_t)temp;
break;
- case 0x0c<<13:
- /* MR - X * Y (SS) */
+ case 0x0c:
+ // MR - X * Y (SS)
xop = MAC_GETXREG_SIGNED(xop);
temp = (xop * xop) << shift;
res = m_core.mr.mr - (int64_t)temp;
break;
- case 0x0d<<13:
- /* MR - X * Y (SU) */
+ case 0x0d:
+ // MR - X * Y (SU)
xop = MAC_GETXREG_SIGNED(xop);
temp = (xop * xop) << shift;
res = m_core.mr.mr - (int64_t)temp;
break;
- case 0x0e<<13:
- /* MR - X * Y (US) */
+ case 0x0e:
+ // MR - X * Y (US)
xop = MAC_GETXREG_UNSIGNED(xop);
temp = (xop * xop) << shift;
res = m_core.mr.mr - (int64_t)temp;
break;
- case 0x0f<<13:
- /* MR - X * Y (UU) */
+ case 0x0f:
+ // MR - X * Y (UU)
xop = MAC_GETXREG_UNSIGNED(xop);
temp = (xop * xop) << shift;
res = m_core.mr.mr - (int64_t)temp;
break;
default:
- res = 0; /* just to keep the compiler happy */
+ res = 0; // just to keep the compiler happy
break;
}
- /* set the final value */
+ // set the final value
m_core.mf.u = (uint32_t)res >> 16;
}
@@ -1951,72 +1991,72 @@ void adsp21xx_device::mac_op_mf_xop(int op)
SHIFT operations (result in SR/SE/SB)
===========================================================================*/
-void adsp21xx_device::shift_op(int op)
+void adsp21xx_device::shift_op(uint32_t op)
{
int8_t sc = m_core.se.s;
- int32_t xop = (op >> 8) & 7;
+ int32_t xop = BIT(op, 8, 3);
uint32_t res;
- switch (op & (15<<11)) /*JB*/
+ switch (BIT(op, 11, 4)) //JB
{
- case 0x00<<11:
- /* LSHIFT (HI) */
+ case 0x00:
+ // LSHIFT (HI)
xop = SHIFT_GETXREG_UNSIGNED(xop) << 16;
if (sc > 0) res = (sc < 32) ? (xop << sc) : 0;
else res = (sc > -32) ? ((uint32_t)xop >> -sc) : 0;
m_core.sr.sr = res;
break;
- case 0x01<<11:
- /* LSHIFT (HI, OR) */
+ case 0x01:
+ // LSHIFT (HI, OR)
xop = SHIFT_GETXREG_UNSIGNED(xop) << 16;
if (sc > 0) res = (sc < 32) ? (xop << sc) : 0;
else res = (sc > -32) ? ((uint32_t)xop >> -sc) : 0;
m_core.sr.sr |= res;
break;
- case 0x02<<11:
- /* LSHIFT (LO) */
+ case 0x02:
+ // LSHIFT (LO)
xop = SHIFT_GETXREG_UNSIGNED(xop);
if (sc > 0) res = (sc < 32) ? (xop << sc) : 0;
else res = (sc > -32) ? (xop >> -sc) : 0;
m_core.sr.sr = res;
break;
- case 0x03<<11:
- /* LSHIFT (LO, OR) */
+ case 0x03:
+ // LSHIFT (LO, OR)
xop = SHIFT_GETXREG_UNSIGNED(xop);
if (sc > 0) res = (sc < 32) ? (xop << sc) : 0;
else res = (sc > -32) ? (xop >> -sc) : 0;
m_core.sr.sr |= res;
break;
- case 0x04<<11:
- /* ASHIFT (HI) */
+ case 0x04:
+ // ASHIFT (HI)
xop = SHIFT_GETXREG_SIGNED(xop) << 16;
if (sc > 0) res = (sc < 32) ? (xop << sc) : 0;
else res = (sc > -32) ? (xop >> -sc) : (xop >> 31);
m_core.sr.sr = res;
break;
- case 0x05<<11:
- /* ASHIFT (HI, OR) */
+ case 0x05:
+ // ASHIFT (HI, OR)
xop = SHIFT_GETXREG_SIGNED(xop) << 16;
if (sc > 0) res = (sc < 32) ? (xop << sc) : 0;
else res = (sc > -32) ? (xop >> -sc) : (xop >> 31);
m_core.sr.sr |= res;
break;
- case 0x06<<11:
- /* ASHIFT (LO) */
+ case 0x06:
+ // ASHIFT (LO)
xop = SHIFT_GETXREG_SIGNED(xop);
if (sc > 0) res = (sc < 32) ? (xop << sc) : 0;
else res = (sc > -32) ? (xop >> -sc) : (xop >> 31);
m_core.sr.sr = res;
break;
- case 0x07<<11:
- /* ASHIFT (LO, OR) */
+ case 0x07:
+ // ASHIFT (LO, OR)
xop = SHIFT_GETXREG_SIGNED(xop);
if (sc > 0) res = (sc < 32) ? (xop << sc) : 0;
else res = (sc > -32) ? (xop >> -sc) : (xop >> 31);
m_core.sr.sr |= res;
break;
- case 0x08<<11:
- /* NORM (HI) */
+ case 0x08:
+ // NORM (HI)
xop = SHIFT_GETXREG_SIGNED(xop) << 16;
if (sc > 0)
{
@@ -2026,8 +2066,8 @@ void adsp21xx_device::shift_op(int op)
else res = (sc > -32) ? (xop << -sc) : 0;
m_core.sr.sr = res;
break;
- case 0x09<<11:
- /* NORM (HI, OR) */
+ case 0x09:
+ // NORM (HI, OR)
xop = SHIFT_GETXREG_SIGNED(xop) << 16;
if (sc > 0)
{
@@ -2037,40 +2077,38 @@ void adsp21xx_device::shift_op(int op)
else res = (sc > -32) ? (xop << -sc) : 0;
m_core.sr.sr |= res;
break;
- case 0x0a<<11:
- /* NORM (LO) */
+ case 0x0a:
+ // NORM (LO)
xop = SHIFT_GETXREG_UNSIGNED(xop);
if (sc > 0) res = (sc < 32) ? (xop >> sc) : 0;
else res = (sc > -32) ? (xop << -sc) : 0;
m_core.sr.sr = res;
break;
- case 0x0b<<11:
- /* NORM (LO, OR) */
+ case 0x0b:
+ // NORM (LO, OR)
xop = SHIFT_GETXREG_UNSIGNED(xop);
if (sc > 0) res = (sc < 32) ? (xop >> sc) : 0;
else res = (sc > -32) ? (xop << -sc) : 0;
m_core.sr.sr |= res;
break;
- case 0x0c<<11:
- /* EXP (HI) */
- xop = SHIFT_GETXREG_SIGNED(xop) << 16;
- res = 0;
+ case 0x0c:
+ // EXP (HI)
+ xop = SHIFT_GETXREG_SIGNED(xop);
if (xop < 0)
{
SET_SS;
- while ((xop & 0x40000000) != 0) res++, xop <<= 1;
+ res = count_leading_ones_32(xop) - 16 - 1;
}
else
{
CLR_SS;
- xop |= 0x8000;
- while ((xop & 0x40000000) == 0) res++, xop <<= 1;
+ res = count_leading_zeros_32(xop) - 16 - 1;
}
m_core.se.s = -res;
break;
- case 0x0d<<11:
- /* EXP (HIX) */
- xop = SHIFT_GETXREG_SIGNED(xop) << 16;
+ case 0x0d:
+ // EXP (HIX)
+ xop = SHIFT_GETXREG_SIGNED(xop);
if (GET_V)
{
m_core.se.s = 1;
@@ -2079,48 +2117,32 @@ void adsp21xx_device::shift_op(int op)
}
else
{
- res = 0;
if (xop < 0)
{
SET_SS;
- while ((xop & 0x40000000) != 0) res++, xop <<= 1;
+ res = count_leading_ones_32(xop) - 16 - 1;
}
else
{
CLR_SS;
- xop |= 0x8000;
- while ((xop & 0x40000000) == 0) res++, xop <<= 1;
+ res = count_leading_zeros_32(xop) - 16 - 1;
}
m_core.se.s = -res;
}
break;
- case 0x0e<<11:
- /* EXP (LO) */
+ case 0x0e:
+ // EXP (LO)
if (m_core.se.s == -15)
{
xop = SHIFT_GETXREG_SIGNED(xop);
- res = 15;
- if (GET_SS)
- while ((xop & 0x8000) != 0) res++, xop <<= 1;
- else
- {
- xop = (xop << 1) | 1;
- while ((xop & 0x10000) == 0) res++, xop <<= 1;
- }
+ res = count_leading_zeros_32((GET_SS ? ~xop : xop) & 0xffff) - 1;
m_core.se.s = -res;
}
break;
- case 0x0f<<11:
- /* EXPADJ */
- xop = SHIFT_GETXREG_SIGNED(xop) << 16;
- res = 0;
- if (xop < 0)
- while ((xop & 0x40000000) != 0) res++, xop <<= 1;
- else
- {
- xop |= 0x8000;
- while ((xop & 0x40000000) == 0) res++, xop <<= 1;
- }
+ case 0x0f:
+ // EXPADJ
+ xop = SHIFT_GETXREG_SIGNED(xop);
+ res = count_leading_zeros_32((xop < 0) ? ~xop : xop) - 16 - 1;
if (res < -m_core.sb.s)
m_core.sb.s = -res;
break;
@@ -2133,72 +2155,72 @@ void adsp21xx_device::shift_op(int op)
Immediate SHIFT operations (result in SR/SE/SB)
===========================================================================*/
-void adsp21xx_device::shift_op_imm(int op)
+void adsp21xx_device::shift_op_imm(uint32_t op)
{
int8_t sc = (int8_t)op;
- int32_t xop = (op >> 8) & 7;
+ int32_t xop = BIT(op, 8, 3);
uint32_t res;
- switch (op & (15<<11)) /*JB*/
+ switch (BIT(op, 11, 4)) //JB
{
- case 0x00<<11:
- /* LSHIFT (HI) */
+ case 0x00:
+ // LSHIFT (HI)
xop = SHIFT_GETXREG_UNSIGNED(xop) << 16;
if (sc > 0) res = (sc < 32) ? (xop << sc) : 0;
else res = (sc > -32) ? ((uint32_t)xop >> -sc) : 0;
m_core.sr.sr = res;
break;
- case 0x01<<11:
- /* LSHIFT (HI, OR) */
+ case 0x01:
+ // LSHIFT (HI, OR)
xop = SHIFT_GETXREG_UNSIGNED(xop) << 16;
if (sc > 0) res = (sc < 32) ? (xop << sc) : 0;
else res = (sc > -32) ? ((uint32_t)xop >> -sc) : 0;
m_core.sr.sr |= res;
break;
- case 0x02<<11:
- /* LSHIFT (LO) */
+ case 0x02:
+ // LSHIFT (LO)
xop = SHIFT_GETXREG_UNSIGNED(xop);
if (sc > 0) res = (sc < 32) ? (xop << sc) : 0;
else res = (sc > -32) ? (xop >> -sc) : 0;
m_core.sr.sr = res;
break;
- case 0x03<<11:
- /* LSHIFT (LO, OR) */
+ case 0x03:
+ // LSHIFT (LO, OR)
xop = SHIFT_GETXREG_UNSIGNED(xop);
if (sc > 0) res = (sc < 32) ? (xop << sc) : 0;
else res = (sc > -32) ? (xop >> -sc) : 0;
m_core.sr.sr |= res;
break;
- case 0x04<<11:
- /* ASHIFT (HI) */
+ case 0x04:
+ // ASHIFT (HI)
xop = SHIFT_GETXREG_SIGNED(xop) << 16;
if (sc > 0) res = (sc < 32) ? (xop << sc) : 0;
else res = (sc > -32) ? (xop >> -sc) : (xop >> 31);
m_core.sr.sr = res;
break;
- case 0x05<<11:
- /* ASHIFT (HI, OR) */
+ case 0x05:
+ // ASHIFT (HI, OR)
xop = SHIFT_GETXREG_SIGNED(xop) << 16;
if (sc > 0) res = (sc < 32) ? (xop << sc) : 0;
else res = (sc > -32) ? (xop >> -sc) : (xop >> 31);
m_core.sr.sr |= res;
break;
- case 0x06<<11:
- /* ASHIFT (LO) */
+ case 0x06:
+ // ASHIFT (LO)
xop = SHIFT_GETXREG_SIGNED(xop);
if (sc > 0) res = (sc < 32) ? (xop << sc) : 0;
else res = (sc > -32) ? (xop >> -sc) : (xop >> 31);
m_core.sr.sr = res;
break;
- case 0x07<<11:
- /* ASHIFT (LO, OR) */
+ case 0x07:
+ // ASHIFT (LO, OR)
xop = SHIFT_GETXREG_SIGNED(xop);
if (sc > 0) res = (sc < 32) ? (xop << sc) : 0;
else res = (sc > -32) ? (xop >> -sc) : (xop >> 31);
m_core.sr.sr |= res;
break;
- case 0x08<<11:
- /* NORM (HI) */
+ case 0x08:
+ // NORM (HI)
xop = SHIFT_GETXREG_SIGNED(xop) << 16;
if (sc > 0)
{
@@ -2208,8 +2230,8 @@ void adsp21xx_device::shift_op_imm(int op)
else res = (sc > -32) ? (xop << -sc) : 0;
m_core.sr.sr = res;
break;
- case 0x09<<11:
- /* NORM (HI, OR) */
+ case 0x09:
+ // NORM (HI, OR)
xop = SHIFT_GETXREG_SIGNED(xop) << 16;
if (sc > 0)
{
@@ -2219,15 +2241,15 @@ void adsp21xx_device::shift_op_imm(int op)
else res = (sc > -32) ? (xop << -sc) : 0;
m_core.sr.sr |= res;
break;
- case 0x0a<<11:
- /* NORM (LO) */
+ case 0x0a:
+ // NORM (LO)
xop = SHIFT_GETXREG_UNSIGNED(xop);
if (sc > 0) res = (sc < 32) ? (xop >> sc) : 0;
else res = (sc > -32) ? (xop << -sc) : 0;
m_core.sr.sr = res;
break;
- case 0x0b<<11:
- /* NORM (LO, OR) */
+ case 0x0b:
+ // NORM (LO, OR)
xop = SHIFT_GETXREG_UNSIGNED(xop);
if (sc > 0) res = (sc < 32) ? (xop >> sc) : 0;
else res = (sc > -32) ? (xop << -sc) : 0;
diff --git a/src/devices/cpu/adsp2100/adsp2100.cpp b/src/devices/cpu/adsp2100/adsp2100.cpp
index ff08e96b72b..817cd2c6bea 100644
--- a/src/devices/cpu/adsp2100/adsp2100.cpp
+++ b/src/devices/cpu/adsp2100/adsp2100.cpp
@@ -2,7 +2,7 @@
// copyright-holders:Aaron Giles
/***************************************************************************
- ADSP2100.c
+ adsp2100.cpp
ADSP-21xx series emulator.
@@ -61,8 +61,8 @@
Program Space: Program Space:
0000-01ff = 512 Internal RAM (booted) 0000-37ff = 14k External access
- 0400-07ff = 1k Reserved 3800-3bff = 1k Internal RAM
- 0800-3fff = 14k External access 3c00-3fff = 1k Reserved
+ 0200-07ff = 1.5k Reserved 3800-39ff = 512 Internal RAM
+ 0800-3fff = 14k External access 3a00-3fff = 1.5k Reserved
Data Space: Data Space:
0000-03ff = 1k External DWAIT0 0000-03ff = 1k External DWAIT0
@@ -71,7 +71,7 @@
3000-33ff = 1k External DWAIT3 3000-33ff = 1k External DWAIT3
3400-37ff = 1k External DWAIT4 3400-37ff = 1k External DWAIT4
3800-38ff = 256 Internal RAM 3800-38ff = 256 Internal RAM
- 3a00-3bff = 512 Reserved 3a00-3bff = 512 Reserved
+ 3900-3bff = 768 Reserved 3900-3bff = 768 Reserved
3c00-3fff = 1k Internal Control regs 3c00-3fff = 1k Internal Control regs
@@ -80,12 +80,16 @@
MMAP = 0 MMAP = 1
+ Auto boot loading via BDMA or IDMA No auto boot loading
+
Program Space: Program Space:
0000-1fff = 8k Internal RAM 0000-1fff = 8k External access
- 2000-3fff = 8k Internal RAM or Overlay 2000-3fff = 8k Internal
+ 2000-3fff = 8k Internal RAM (PMOVLAY = 0) 2000-3fff = 8k Internal (PMOVLAY = 0)
+ 2000-3fff = 8k External (PMOVLAY = 1,2)
Data Space: Data Space:
- 0000-1fff = 8k Internal RAM or Overlay 0000-1fff = 8k Internal RAM or Overlay
+ 0000-1fff = 8k Internal RAM (DMOVLAY = 0) 0000-1fff = 8k Internal RAM (DMOVLAY = 0)
+ 0000-1fff = 8k External (DMOVLAY = 1,2) 0000-1fff = 8k External (DMOVLAY = 1,2)
2000-3fdf = 8k-32 Internal RAM 2000-3fdf = 8k-32 Internal RAM
3fe0-3fff = 32 Internal Control regs 3fe0-3fff = 32 Internal Control regs
@@ -95,10 +99,13 @@
0400-05ff = 512 External IOWAIT2 0400-05ff = 512 External IOWAIT2
0600-07ff = 512 External IOWAIT3 0600-07ff = 512 External IOWAIT3
+ TODO:
+ - Move internal stuffs into CPU core file (on-chip RAM, control registers, etc)
+ - Support variable internal memory mappings
+
***************************************************************************/
#include "emu.h"
-#include "debugger.h"
#include "adsp2100.h"
#include "2100dasm.h"
@@ -137,6 +144,8 @@ adsp21xx_device::adsp21xx_device(const machine_config &mconfig, device_type type
m_astat_clear(0),
m_idle(0),
m_px(0),
+ m_pmovlay(0),
+ m_dmovlay(0),
m_pc_sp(0),
m_cntr_sp(0),
m_stat_sp(0),
@@ -156,7 +165,7 @@ adsp21xx_device::adsp21xx_device(const machine_config &mconfig, device_type type
m_mstat_mask((m_chip_type >= CHIP_TYPE_ADSP2101) ? 0x7f : 0x0f),
m_imask_mask((m_chip_type >= CHIP_TYPE_ADSP2181) ? 0x3ff :
(m_chip_type >= CHIP_TYPE_ADSP2101) ? 0x3f : 0x0f),
- m_sport_rx_cb(*this),
+ m_sport_rx_cb(*this, 0),
m_sport_tx_cb(*this),
m_timer_fired_cb(*this),
m_dmovlay_cb(*this)
@@ -275,7 +284,7 @@ adsp2115_device::adsp2115_device(const machine_config &mconfig, const char *tag,
adsp2181_device::adsp2181_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
: adsp21xx_device(mconfig, ADSP2181, tag, owner, clock, CHIP_TYPE_ADSP2181)
- , m_io_config("I/O", ENDIANNESS_LITTLE, 16, 11, -1)
+ , m_io_config("io", ENDIANNESS_LITTLE, 16, 11, -1)
{ }
@@ -411,16 +420,12 @@ uint16_t adsp2181_device::idma_data_r()
void adsp21xx_device::device_start()
{
- m_sport_rx_cb.resolve();
- m_sport_tx_cb.resolve();
- m_timer_fired_cb.resolve();
- m_dmovlay_cb.resolve();
-
// get our address spaces
- m_program = &space(AS_PROGRAM);
- m_cache = m_program->cache<2, -2, ENDIANNESS_LITTLE>();
- m_data = &space(AS_DATA);
- m_io = has_space(AS_IO) ? &space(AS_IO) : nullptr;
+ space(AS_PROGRAM).cache(m_cache);
+ space(AS_PROGRAM).specific(m_program);
+ space(AS_DATA).specific(m_data);
+ if(has_space(AS_IO))
+ space(AS_IO).specific(m_io);
// "core"
save_item(NAME(m_core.ax0.u));
@@ -466,6 +471,8 @@ void adsp21xx_device::device_start()
save_item(NAME(m_lmask));
save_item(NAME(m_base));
save_item(NAME(m_px));
+ save_item(NAME(m_pmovlay));
+ save_item(NAME(m_dmovlay));
save_item(NAME(m_pc));
save_item(NAME(m_ppc));
@@ -569,7 +576,6 @@ void adsp21xx_device::device_start()
state_add(ADSP2100_MSTAT, "MSTAT", m_mstat).mask((m_chip_type == CHIP_TYPE_ADSP2100) ? 0x0f : 0x7f).callimport();
state_add(ADSP2100_PCSP, "PCSP", m_pc_sp).mask(0xff);
- state_add(STATE_GENSP, "CURSP", m_pc_sp).mask(0xff).noshow();
state_add(ADSP2100_CNTRSP, "CNTRSP", m_cntr_sp).mask(0xf);
state_add(ADSP2100_STATSP, "STATSP", m_stat_sp).mask(0xf);
state_add(ADSP2100_LOOPSP, "LOOPSP", m_loop_sp).mask(0xf);
@@ -587,6 +593,12 @@ void adsp21xx_device::device_start()
state_add(ADSP2100_FL1, "FL1", m_fl1).mask(1);
state_add(ADSP2100_FL2, "FL2", m_fl2).mask(1);
+ if (m_chip_type == CHIP_TYPE_ADSP2181)
+ {
+ state_add(ADSP2100_PMOVLAY, "PMOVLAY", m_pmovlay);
+ state_add(ADSP2100_DMOVLAY, "DMOVLAY", m_dmovlay);
+ }
+
// set our instruction counter
set_icountptr(m_icount);
}
@@ -611,6 +623,14 @@ void adsp21xx_device::device_reset()
write_reg2(0x0a, m_l[6]); write_reg2(0x02, m_i[6]);
write_reg2(0x0b, m_l[7]); write_reg2(0x03, m_i[7]);
+ // reset overlays
+ if (m_chip_type == CHIP_TYPE_ADSP2181)
+ {
+ m_pmovlay = m_dmovlay = 0;
+ // PMOVLAY
+ update_dmovlay();
+ }
+
// reset PC and loops
m_pc = (m_chip_type >= CHIP_TYPE_ADSP2101) ? 0 : 4;
m_ppc = m_pc;
@@ -645,6 +665,21 @@ void adsp21xx_device::device_reset()
//-------------------------------------------------
+// device_post_load - called after loading a saved state
+//-------------------------------------------------
+
+void adsp21xx_device::device_post_load()
+{
+ // update overlays
+ if (m_chip_type == CHIP_TYPE_ADSP2181)
+ {
+ // PMOVLAY
+ update_dmovlay();
+ }
+}
+
+
+//-------------------------------------------------
// memory_space_config - return the configuration
// of the specified address space, or nullptr if
// the space doesn't exist
@@ -728,6 +763,11 @@ void adsp21xx_device::state_import(const device_state_entry &entry)
update_l(entry.index() - ADSP2100_L0);
break;
+ // PMOVLAY
+ case ADSP2100_DMOVLAY:
+ update_dmovlay();
+ break;
+
default:
fatalerror("CPU_IMPORT_STATE(adsp21xx) called for unexpected value\n");
}
@@ -776,37 +816,37 @@ std::unique_ptr<util::disasm_interface> adsp21xx_device::create_disassembler()
inline uint16_t adsp21xx_device::data_read(uint32_t addr)
{
- return m_data->read_word(addr);
+ return m_data.read_word(addr);
}
inline void adsp21xx_device::data_write(uint32_t addr, uint16_t data)
{
- m_data->write_word(addr, data);
+ m_data.write_word(addr, data);
}
inline uint16_t adsp21xx_device::io_read(uint32_t addr)
{
- return m_io->read_word(addr);
+ return m_io.read_word(addr);
}
inline void adsp21xx_device::io_write(uint32_t addr, uint16_t data)
{
- m_io->write_word(addr, data);
+ m_io.write_word(addr, data);
}
inline uint32_t adsp21xx_device::program_read(uint32_t addr)
{
- return m_program->read_dword(addr);
+ return m_program.read_dword(addr);
}
inline void adsp21xx_device::program_write(uint32_t addr, uint32_t data)
{
- m_program->write_dword(addr, data & 0xffffff);
+ m_program.write_dword(addr, data & 0xffffff);
}
inline uint32_t adsp21xx_device::opcode_read()
{
- return m_cache->read_dword(m_pc);
+ return m_cache.read_dword(m_pc);
}
@@ -1048,7 +1088,7 @@ void adsp21xx_device::create_tables()
// initialize the mask table
for (int i = 0; i < 0x4000; i++)
{
- if (i > 0x2000) m_mask_table[i] = 0x0000;
+ if (i > 0x2000) m_mask_table[i] = 0x0000;
else if (i > 0x1000) m_mask_table[i] = 0x2000;
else if (i > 0x0800) m_mask_table[i] = 0x3000;
else if (i > 0x0400) m_mask_table[i] = 0x3800;
@@ -1104,7 +1144,7 @@ void adsp21xx_device::create_tables()
// cycles it takes for one instruction to execute
//-------------------------------------------------
-uint32_t adsp21xx_device::execute_min_cycles() const
+uint32_t adsp21xx_device::execute_min_cycles() const noexcept
{
return 1;
}
@@ -1115,33 +1155,12 @@ uint32_t adsp21xx_device::execute_min_cycles() const
// cycles it takes for one instruction to execute
//-------------------------------------------------
-uint32_t adsp21xx_device::execute_max_cycles() const
+uint32_t adsp21xx_device::execute_max_cycles() const noexcept
{
return 1;
}
-//-------------------------------------------------
-// execute_input_lines - return the number of
-// input/interrupt lines
-//-------------------------------------------------
-
-uint32_t adsp2100_device::execute_input_lines() const
-{
- return 4;
-}
-
-uint32_t adsp2101_device::execute_input_lines() const
-{
- return 5;
-}
-
-uint32_t adsp2181_device::execute_input_lines() const
-{
- return 9;
-}
-
-
void adsp21xx_device::execute_set_input(int inputnum, int state)
{
// update the latched state
@@ -1156,12 +1175,13 @@ void adsp21xx_device::execute_set_input(int inputnum, int state)
void adsp21xx_device::execute_run()
{
// Return if CPU is halted
- if (current_input_state(INPUT_LINE_HALT)) {
+ if (input_line_state(INPUT_LINE_HALT)) {
+ debugger_wait_hook();
m_icount = 0;
return;
}
- bool check_debugger = ((device_t::machine().debug_flags & DEBUG_FLAG_ENABLED) != 0);
+ const bool check_debugger = debugger_enabled();
check_irqs();
@@ -1201,7 +1221,7 @@ void adsp21xx_device::execute_run()
// parse the instruction
uint32_t temp;
- switch ((op >> 16) & 0xff)
+ switch (BIT(op, 16, 8))
{
case 0x00:
// 00000000 00000000 00000000 NOP
@@ -1212,68 +1232,56 @@ void adsp21xx_device::execute_run()
// ADSP-218x only
if (m_chip_type >= CHIP_TYPE_ADSP2181)
{
- if ((op & 0x008000) == 0x000000)
- write_reg0(op & 15, io_read((op >> 4) & 0x7ff));
+ if (!BIT(op, 15))
+ write_reg0(BIT(op, 0, 4), io_read(BIT(op, 4, 11)));
else
- io_write((op >> 4) & 0x7ff, read_reg0(op & 15));
+ io_write(BIT(op, 4, 11), read_reg0(BIT(op, 0, 4)));
}
break;
case 0x02:
// 00000010 0000xxxx xxxxxxxx modify flag out
// 00000010 10000000 00000000 idle
// 00000010 10000000 0000xxxx idle (n)
- if (op & 0x008000)
+ if (BIT(op, 15))
{
m_idle = 1;
m_icount = 0;
}
else
{
- if (condition(op & 15))
+ if (condition(BIT(op, 0, 4)))
{
- if (op & 0x020) m_flagout = 0;
- if (op & 0x010) m_flagout ^= 1;
+ if (BIT(op, 5)) m_flagout = 0;
+ if (BIT(op, 4)) m_flagout ^= 1;
if (m_chip_type >= CHIP_TYPE_ADSP2101)
{
- if (op & 0x080) m_fl0 = 0;
- if (op & 0x040) m_fl0 ^= 1;
- if (op & 0x200) m_fl1 = 0;
- if (op & 0x100) m_fl1 ^= 1;
- if (op & 0x800) m_fl2 = 0;
- if (op & 0x400) m_fl2 ^= 1;
+ if (BIT(op, 7)) m_fl0 = 0;
+ if (BIT(op, 6)) m_fl0 ^= 1;
+ if (BIT(op, 9)) m_fl1 = 0;
+ if (BIT(op, 8)) m_fl1 ^= 1;
+ if (BIT(op, 11)) m_fl2 = 0;
+ if (BIT(op, 10)) m_fl2 ^= 1;
}
}
}
break;
case 0x03:
// 00000011 xxxxxxxx xxxxxxxx call or jump on flag in
- if (op & 0x000002)
+ if (BIT(op, 1) ? m_flagin : !m_flagin)
{
- if (m_flagin)
- {
- if (op & 0x000001)
- pc_stack_push();
- m_pc = ((op >> 4) & 0x0fff) | ((op << 10) & 0x3000);
- }
- }
- else
- {
- if (!m_flagin)
- {
- if (op & 0x000001)
- pc_stack_push();
- m_pc = ((op >> 4) & 0x0fff) | ((op << 10) & 0x3000);
- }
+ if (BIT(op, 0))
+ pc_stack_push();
+ m_pc = BIT(op, 4, 12) | BIT(op, 2, 2) << 12;
}
break;
case 0x04:
// 00000100 00000000 000xxxxx stack control
- if (op & 0x000010) pc_stack_pop_val();
- if (op & 0x000008) loop_stack_pop();
- if (op & 0x000004) cntr_stack_pop();
- if (op & 0x000002)
+ if (BIT(op, 4)) pc_stack_pop_val();
+ if (BIT(op, 3)) loop_stack_pop();
+ if (BIT(op, 2)) cntr_stack_pop();
+ if (BIT(op, 1))
{
- if (op & 0x000001) stat_stack_pop();
+ if (BIT(op, 0)) stat_stack_pop();
else stat_stack_push();
}
break;
@@ -1290,8 +1298,8 @@ void adsp21xx_device::execute_run()
case 0x06:
// 00000110 000xxxxx 00000000 DIVS
{
- int xop = (op >> 8) & 7;
- int yop = (op >> 11) & 3;
+ int xop = BIT(op, 8, 3);
+ int yop = BIT(op, 11, 2);
xop = ALU_GETXREG_UNSIGNED(xop);
yop = ALU_GETYREG_UNSIGNED(yop);
@@ -1305,7 +1313,7 @@ void adsp21xx_device::execute_run()
case 0x07:
// 00000111 00010xxx 00000000 DIVQ
{
- int xop = (op >> 8) & 7;
+ int xop = BIT(op, 8, 3);
int res;
xop = ALU_GETXREG_UNSIGNED(xop);
@@ -1326,68 +1334,68 @@ void adsp21xx_device::execute_run()
break;
case 0x09:
// 00001001 00000000 000xxxxx modify address register
- temp = (op >> 2) & 4;
- modify_address(temp + ((op >> 2) & 3), temp + (op & 3));
+ temp = BIT(op, 2, 3);
+ modify_address(temp, (temp & 4) | (op & 3));
break;
case 0x0a:
// 00001010 00000000 000xxxxx conditional return
- if (condition(op & 15))
+ if (condition(BIT(op, 0, 4)))
{
pc_stack_pop();
// RTI case
- if (op & 0x000010)
+ if (BIT(op, 4))
stat_stack_pop();
}
break;
case 0x0b:
// 00001011 00000000 xxxxxxxx conditional jump (indirect address)
- if (condition(op & 15))
+ if (condition(BIT(op, 0, 4)))
{
- if (op & 0x000010)
+ if (BIT(op, 4))
pc_stack_push();
- m_pc = m_i[4 + ((op >> 6) & 3)] & 0x3fff;
+ m_pc = m_i[4 + BIT(op, 6, 2)] & 0x3fff;
}
break;
case 0x0c:
// 00001100 xxxxxxxx xxxxxxxx mode control
if (m_chip_type >= CHIP_TYPE_ADSP2101)
{
- if (op & 0x000008) m_mstat = (m_mstat & ~MSTAT_GOMODE) | ((op << 5) & MSTAT_GOMODE);
- if (op & 0x002000) m_mstat = (m_mstat & ~MSTAT_INTEGER) | ((op >> 8) & MSTAT_INTEGER);
- if (op & 0x008000) m_mstat = (m_mstat & ~MSTAT_TIMER) | ((op >> 9) & MSTAT_TIMER);
+ if (BIT(op, 3)) m_mstat = BIT(op, 2) ? (m_mstat | MSTAT_GOMODE) : (m_mstat & ~MSTAT_GOMODE);
+ if (BIT(op, 13)) m_mstat = BIT(op, 12) ? (m_mstat | MSTAT_INTEGER) : (m_mstat & ~MSTAT_INTEGER);
+ if (BIT(op, 15)) m_mstat = BIT(op, 14) ? (m_mstat | MSTAT_TIMER) : (m_mstat & ~MSTAT_TIMER);
}
- if (op & 0x000020) m_mstat = (m_mstat & ~MSTAT_BANK) | ((op >> 4) & MSTAT_BANK);
- if (op & 0x000080) m_mstat = (m_mstat & ~MSTAT_REVERSE) | ((op >> 5) & MSTAT_REVERSE);
- if (op & 0x000200) m_mstat = (m_mstat & ~MSTAT_STICKYV) | ((op >> 6) & MSTAT_STICKYV);
- if (op & 0x000800) m_mstat = (m_mstat & ~MSTAT_SATURATE) | ((op >> 7) & MSTAT_SATURATE);
+ if (BIT(op, 5)) m_mstat = BIT(op, 4) ? (m_mstat | MSTAT_BANK) : (m_mstat & ~MSTAT_BANK);
+ if (BIT(op, 7)) m_mstat = BIT(op, 6) ? (m_mstat | MSTAT_REVERSE) : (m_mstat & ~MSTAT_REVERSE);
+ if (BIT(op, 9)) m_mstat = BIT(op, 8) ? (m_mstat | MSTAT_STICKYV) : (m_mstat & ~MSTAT_STICKYV);
+ if (BIT(op, 11)) m_mstat = BIT(op, 10) ? (m_mstat | MSTAT_SATURATE) : (m_mstat & ~MSTAT_SATURATE);
update_mstat();
break;
case 0x0d:
// 00001101 0000xxxx xxxxxxxx internal data move
- switch ((op >> 8) & 15)
+ switch (BIT(op, 8, 4))
{
- case 0x00: write_reg0((op >> 4) & 15, read_reg0(op & 15)); break;
- case 0x01: write_reg0((op >> 4) & 15, read_reg1(op & 15)); break;
- case 0x02: write_reg0((op >> 4) & 15, read_reg2(op & 15)); break;
- case 0x03: write_reg0((op >> 4) & 15, read_reg3(op & 15)); break;
- case 0x04: write_reg1((op >> 4) & 15, read_reg0(op & 15)); break;
- case 0x05: write_reg1((op >> 4) & 15, read_reg1(op & 15)); break;
- case 0x06: write_reg1((op >> 4) & 15, read_reg2(op & 15)); break;
- case 0x07: write_reg1((op >> 4) & 15, read_reg3(op & 15)); break;
- case 0x08: write_reg2((op >> 4) & 15, read_reg0(op & 15)); break;
- case 0x09: write_reg2((op >> 4) & 15, read_reg1(op & 15)); break;
- case 0x0a: write_reg2((op >> 4) & 15, read_reg2(op & 15)); break;
- case 0x0b: write_reg2((op >> 4) & 15, read_reg3(op & 15)); break;
- case 0x0c: write_reg3((op >> 4) & 15, read_reg0(op & 15)); break;
- case 0x0d: write_reg3((op >> 4) & 15, read_reg1(op & 15)); break;
- case 0x0e: write_reg3((op >> 4) & 15, read_reg2(op & 15)); break;
- case 0x0f: write_reg3((op >> 4) & 15, read_reg3(op & 15)); break;
+ case 0x00: write_reg0(BIT(op, 4, 4), read_reg0(BIT(op, 0, 4))); break;
+ case 0x01: write_reg0(BIT(op, 4, 4), read_reg1(BIT(op, 0, 4))); break;
+ case 0x02: write_reg0(BIT(op, 4, 4), read_reg2(BIT(op, 0, 4))); break;
+ case 0x03: write_reg0(BIT(op, 4, 4), read_reg3(BIT(op, 0, 4))); break;
+ case 0x04: write_reg1(BIT(op, 4, 4), read_reg0(BIT(op, 0, 4))); break;
+ case 0x05: write_reg1(BIT(op, 4, 4), read_reg1(BIT(op, 0, 4))); break;
+ case 0x06: write_reg1(BIT(op, 4, 4), read_reg2(BIT(op, 0, 4))); break;
+ case 0x07: write_reg1(BIT(op, 4, 4), read_reg3(BIT(op, 0, 4))); break;
+ case 0x08: write_reg2(BIT(op, 4, 4), read_reg0(BIT(op, 0, 4))); break;
+ case 0x09: write_reg2(BIT(op, 4, 4), read_reg1(BIT(op, 0, 4))); break;
+ case 0x0a: write_reg2(BIT(op, 4, 4), read_reg2(BIT(op, 0, 4))); break;
+ case 0x0b: write_reg2(BIT(op, 4, 4), read_reg3(BIT(op, 0, 4))); break;
+ case 0x0c: write_reg3(BIT(op, 4, 4), read_reg0(BIT(op, 0, 4))); break;
+ case 0x0d: write_reg3(BIT(op, 4, 4), read_reg1(BIT(op, 0, 4))); break;
+ case 0x0e: write_reg3(BIT(op, 4, 4), read_reg2(BIT(op, 0, 4))); break;
+ case 0x0f: write_reg3(BIT(op, 4, 4), read_reg3(BIT(op, 0, 4))); break;
}
break;
case 0x0e:
// 00001110 0xxxxxxx xxxxxxxx conditional shift
- if (condition(op & 15)) shift_op(op);
+ if (condition(BIT(op, 0, 4))) shift_op(op);
break;
case 0x0f:
// 00001111 0xxxxxxx xxxxxxxx shift immediate
@@ -1396,46 +1404,46 @@ void adsp21xx_device::execute_run()
case 0x10:
// 00010000 0xxxxxxx xxxxxxxx shift with internal data register move
shift_op(op);
- temp = read_reg0(op & 15);
- write_reg0((op >> 4) & 15, temp);
+ temp = read_reg0(BIT(op, 0, 4));
+ write_reg0(BIT(op, 4, 4), temp);
break;
case 0x11:
// 00010001 xxxxxxxx xxxxxxxx shift with pgm memory read/write
- if (op & 0x8000)
+ if (BIT(op, 15))
{
- pgm_write_dag2(op, read_reg0((op >> 4) & 15));
+ pgm_write_dag2(op, read_reg0(BIT(op, 4, 4)));
shift_op(op);
}
else
{
shift_op(op);
- write_reg0((op >> 4) & 15, pgm_read_dag2(op));
+ write_reg0(BIT(op, 4, 4), pgm_read_dag2(op));
}
break;
case 0x12:
// 00010010 xxxxxxxx xxxxxxxx shift with data memory read/write DAG1
- if (op & 0x8000)
+ if (BIT(op, 15))
{
- data_write_dag1(op, read_reg0((op >> 4) & 15));
+ data_write_dag1(op, read_reg0(BIT(op, 4, 4)));
shift_op(op);
}
else
{
shift_op(op);
- write_reg0((op >> 4) & 15, data_read_dag1(op));
+ write_reg0(BIT(op, 4, 4), data_read_dag1(op));
}
break;
case 0x13:
// 00010011 xxxxxxxx xxxxxxxx shift with data memory read/write DAG2
- if (op & 0x8000)
+ if (BIT(op, 15))
{
- data_write_dag2(op, read_reg0((op >> 4) & 15));
+ data_write_dag2(op, read_reg0(BIT(op, 4, 4)));
shift_op(op);
}
else
{
shift_op(op);
- write_reg0((op >> 4) & 15, data_read_dag2(op));
+ write_reg0(BIT(op, 4, 4), data_read_dag2(op));
}
break;
case 0x14: case 0x15: case 0x16: case 0x17:
@@ -1445,9 +1453,9 @@ void adsp21xx_device::execute_run()
break;
case 0x18: case 0x19: case 0x1a: case 0x1b:
// 000110xx xxxxxxxx xxxxxxxx conditional jump (immediate addr)
- if (condition(op & 15))
+ if (condition(BIT(op, 0, 4)))
{
- m_pc = (op >> 4) & 0x3fff;
+ m_pc = BIT(op, 4, 14);
// check for a busy loop
if (m_pc == m_ppc)
m_icount = 0;
@@ -1455,15 +1463,15 @@ void adsp21xx_device::execute_run()
break;
case 0x1c: case 0x1d: case 0x1e: case 0x1f:
// 000111xx xxxxxxxx xxxxxxxx conditional call (immediate addr)
- if (condition(op & 15))
+ if (condition(BIT(op, 0, 4)))
{
pc_stack_push();
- m_pc = (op >> 4) & 0x3fff;
+ m_pc = BIT(op, 4, 14);
}
break;
case 0x20: case 0x21:
// 0010000x xxxxxxxx xxxxxxxx conditional MAC to MR
- if (condition(op & 15))
+ if (condition(BIT(op, 0, 4)))
{
if (m_chip_type >= CHIP_TYPE_ADSP2181 && (op & 0x0018f0) == 0x000010)
mac_op_mr_xop(op);
@@ -1473,9 +1481,9 @@ void adsp21xx_device::execute_run()
break;
case 0x22: case 0x23:
// 0010001x xxxxxxxx xxxxxxxx conditional ALU to AR
- if (condition(op & 15))
+ if (condition(BIT(op, 0, 4)))
{
- if (m_chip_type >= CHIP_TYPE_ADSP2181 && (op & 0x000010) == 0x000010)
+ if (m_chip_type >= CHIP_TYPE_ADSP2181 && BIT(op, 4))
alu_op_ar_const(op);
else
alu_op_ar(op);
@@ -1483,7 +1491,7 @@ void adsp21xx_device::execute_run()
break;
case 0x24: case 0x25:
// 0010010x xxxxxxxx xxxxxxxx conditional MAC to MF
- if (condition(op & 15))
+ if (condition(BIT(op, 0, 4)))
{
if (m_chip_type >= CHIP_TYPE_ADSP2181 && (op & 0x0018f0) == 0x000010)
mac_op_mf_xop(op);
@@ -1493,9 +1501,9 @@ void adsp21xx_device::execute_run()
break;
case 0x26: case 0x27:
// 0010011x xxxxxxxx xxxxxxxx conditional ALU to AF
- if (condition(op & 15))
+ if (condition(BIT(op, 0, 4)))
{
- if (m_chip_type >= CHIP_TYPE_ADSP2181 && (op & 0x000010) == 0x000010)
+ if (m_chip_type >= CHIP_TYPE_ADSP2181 && BIT(op, 4))
alu_op_af_const(op);
else
alu_op_af(op);
@@ -1503,215 +1511,215 @@ void adsp21xx_device::execute_run()
break;
case 0x28: case 0x29:
// 0010100x xxxxxxxx xxxxxxxx MAC to MR with internal data register move
- temp = read_reg0(op & 15);
+ temp = read_reg0(BIT(op, 0, 4));
mac_op_mr(op);
- write_reg0((op >> 4) & 15, temp);
+ write_reg0(BIT(op, 4, 4), temp);
break;
case 0x2a: case 0x2b:
// 0010101x xxxxxxxx xxxxxxxx ALU to AR with internal data register move
- if (m_chip_type >= CHIP_TYPE_ADSP2181 && (op & 0x0000ff) == 0x0000aa)
+ if (m_chip_type >= CHIP_TYPE_ADSP2181 && BIT(op, 0, 8) == 0xaa)
alu_op_none(op);
else
{
- temp = read_reg0(op & 15);
+ temp = read_reg0(BIT(op, 0, 4));
alu_op_ar(op);
- write_reg0((op >> 4) & 15, temp);
+ write_reg0(BIT(op, 4, 4), temp);
}
break;
case 0x2c: case 0x2d:
// 0010110x xxxxxxxx xxxxxxxx MAC to MF with internal data register move
- temp = read_reg0(op & 15);
+ temp = read_reg0(BIT(op, 0, 4));
mac_op_mf(op);
- write_reg0((op >> 4) & 15, temp);
+ write_reg0(BIT(op, 4, 4), temp);
break;
case 0x2e: case 0x2f:
// 0010111x xxxxxxxx xxxxxxxx ALU to AF with internal data register move
- temp = read_reg0(op & 15);
+ temp = read_reg0(BIT(op, 0, 4));
alu_op_af(op);
- write_reg0((op >> 4) & 15, temp);
+ write_reg0(BIT(op, 4, 4), temp);
break;
case 0x30: case 0x31: case 0x32: case 0x33:
// 001100xx xxxxxxxx xxxxxxxx load non-data register immediate (group 0)
- write_reg0(op & 15, (int32_t)(op << 14) >> 18);
+ write_reg0(BIT(op, 0, 4), util::sext(op >> 4, 14));
break;
case 0x34: case 0x35: case 0x36: case 0x37:
// 001101xx xxxxxxxx xxxxxxxx load non-data register immediate (group 1)
- write_reg1(op & 15, (int32_t)(op << 14) >> 18);
+ write_reg1(BIT(op, 0, 4), util::sext(op >> 4, 14));
break;
case 0x38: case 0x39: case 0x3a: case 0x3b:
// 001110xx xxxxxxxx xxxxxxxx load non-data register immediate (group 2)
- write_reg2(op & 15, (int32_t)(op << 14) >> 18);
+ write_reg2(BIT(op, 0, 4), util::sext(op >> 4, 14));
break;
case 0x3c: case 0x3d: case 0x3e: case 0x3f:
// 001111xx xxxxxxxx xxxxxxxx load non-data register immediate (group 3)
- write_reg3(op & 15, (int32_t)(op << 14) >> 18);
+ write_reg3(BIT(op, 0, 4), util::sext(op >> 4, 14));
break;
case 0x40: case 0x41: case 0x42: case 0x43: case 0x44: case 0x45: case 0x46: case 0x47:
case 0x48: case 0x49: case 0x4a: case 0x4b: case 0x4c: case 0x4d: case 0x4e: case 0x4f:
// 0100xxxx xxxxxxxx xxxxxxxx load data register immediate
- write_reg0(op & 15, (op >> 4) & 0xffff);
+ write_reg0(BIT(op, 0, 4), BIT(op, 4, 16));
break;
case 0x50: case 0x51:
// 0101000x xxxxxxxx xxxxxxxx MAC to MR with pgm memory read
mac_op_mr(op);
- write_reg0((op >> 4) & 15, pgm_read_dag2(op));
+ write_reg0(BIT(op, 4, 4), pgm_read_dag2(op));
break;
case 0x52: case 0x53:
// 0101001x xxxxxxxx xxxxxxxx ALU to AR with pgm memory read
alu_op_ar(op);
- write_reg0((op >> 4) & 15, pgm_read_dag2(op));
+ write_reg0(BIT(op, 4, 4), pgm_read_dag2(op));
break;
case 0x54: case 0x55:
// 0101010x xxxxxxxx xxxxxxxx MAC to MF with pgm memory read
mac_op_mf(op);
- write_reg0((op >> 4) & 15, pgm_read_dag2(op));
+ write_reg0(BIT(op, 4, 4), pgm_read_dag2(op));
break;
case 0x56: case 0x57:
// 0101011x xxxxxxxx xxxxxxxx ALU to AF with pgm memory read
alu_op_af(op);
- write_reg0((op >> 4) & 15, pgm_read_dag2(op));
+ write_reg0(BIT(op, 4, 4), pgm_read_dag2(op));
break;
case 0x58: case 0x59:
// 0101100x xxxxxxxx xxxxxxxx MAC to MR with pgm memory write
- pgm_write_dag2(op, read_reg0((op >> 4) & 15));
+ pgm_write_dag2(op, read_reg0(BIT(op, 4, 4)));
mac_op_mr(op);
break;
case 0x5a: case 0x5b:
// 0101101x xxxxxxxx xxxxxxxx ALU to AR with pgm memory write
- pgm_write_dag2(op, read_reg0((op >> 4) & 15));
+ pgm_write_dag2(op, read_reg0(BIT(op, 4, 4)));
alu_op_ar(op);
break;
case 0x5c: case 0x5d:
// 0101110x xxxxxxxx xxxxxxxx ALU to MR with pgm memory write
- pgm_write_dag2(op, read_reg0((op >> 4) & 15));
+ pgm_write_dag2(op, read_reg0(BIT(op, 4, 4)));
mac_op_mf(op);
break;
case 0x5e: case 0x5f:
// 0101111x xxxxxxxx xxxxxxxx ALU to MF with pgm memory write
- pgm_write_dag2(op, read_reg0((op >> 4) & 15));
+ pgm_write_dag2(op, read_reg0(BIT(op, 4, 4)));
alu_op_af(op);
break;
case 0x60: case 0x61:
// 0110000x xxxxxxxx xxxxxxxx MAC to MR with data memory read DAG1
mac_op_mr(op);
- write_reg0((op >> 4) & 15, data_read_dag1(op));
+ write_reg0(BIT(op, 4, 4), data_read_dag1(op));
break;
case 0x62: case 0x63:
// 0110001x xxxxxxxx xxxxxxxx ALU to AR with data memory read DAG1
alu_op_ar(op);
- write_reg0((op >> 4) & 15, data_read_dag1(op));
+ write_reg0(BIT(op, 4, 4), data_read_dag1(op));
break;
case 0x64: case 0x65:
// 0110010x xxxxxxxx xxxxxxxx MAC to MF with data memory read DAG1
mac_op_mf(op);
- write_reg0((op >> 4) & 15, data_read_dag1(op));
+ write_reg0(BIT(op, 4, 4), data_read_dag1(op));
break;
case 0x66: case 0x67:
// 0110011x xxxxxxxx xxxxxxxx ALU to AF with data memory read DAG1
alu_op_af(op);
- write_reg0((op >> 4) & 15, data_read_dag1(op));
+ write_reg0(BIT(op, 4, 4), data_read_dag1(op));
break;
case 0x68: case 0x69:
// 0110100x xxxxxxxx xxxxxxxx MAC to MR with data memory write DAG1
- data_write_dag1(op, read_reg0((op >> 4) & 15));
+ data_write_dag1(op, read_reg0(BIT(op, 4, 4)));
mac_op_mr(op);
break;
case 0x6a: case 0x6b:
// 0110101x xxxxxxxx xxxxxxxx ALU to AR with data memory write DAG1
- data_write_dag1(op, read_reg0((op >> 4) & 15));
+ data_write_dag1(op, read_reg0(BIT(op, 4, 4)));
alu_op_ar(op);
break;
case 0x6c: case 0x6d:
// 0111110x xxxxxxxx xxxxxxxx MAC to MF with data memory write DAG1
- data_write_dag1(op, read_reg0((op >> 4) & 15));
+ data_write_dag1(op, read_reg0(BIT(op, 4, 4)));
mac_op_mf(op);
break;
case 0x6e: case 0x6f:
// 0111111x xxxxxxxx xxxxxxxx ALU to AF with data memory write DAG1
- data_write_dag1(op, read_reg0((op >> 4) & 15));
+ data_write_dag1(op, read_reg0(BIT(op, 4, 4)));
alu_op_af(op);
break;
case 0x70: case 0x71:
// 0111000x xxxxxxxx xxxxxxxx MAC to MR with data memory read DAG2
mac_op_mr(op);
- write_reg0((op >> 4) & 15, data_read_dag2(op));
+ write_reg0(BIT(op, 4, 4), data_read_dag2(op));
break;
case 0x72: case 0x73:
// 0111001x xxxxxxxx xxxxxxxx ALU to AR with data memory read DAG2
alu_op_ar(op);
- write_reg0((op >> 4) & 15, data_read_dag2(op));
+ write_reg0(BIT(op, 4, 4), data_read_dag2(op));
break;
case 0x74: case 0x75:
// 0111010x xxxxxxxx xxxxxxxx MAC to MF with data memory read DAG2
mac_op_mf(op);
- write_reg0((op >> 4) & 15, data_read_dag2(op));
+ write_reg0(BIT(op, 4, 4), data_read_dag2(op));
break;
case 0x76: case 0x77:
// 0111011x xxxxxxxx xxxxxxxx ALU to AF with data memory read DAG2
alu_op_af(op);
- write_reg0((op >> 4) & 15, data_read_dag2(op));
+ write_reg0(BIT(op, 4, 4), data_read_dag2(op));
break;
case 0x78: case 0x79:
// 0111100x xxxxxxxx xxxxxxxx MAC to MR with data memory write DAG2
- data_write_dag2(op, read_reg0((op >> 4) & 15));
+ data_write_dag2(op, read_reg0(BIT(op, 4, 4)));
mac_op_mr(op);
break;
case 0x7a: case 0x7b:
// 0111101x xxxxxxxx xxxxxxxx ALU to AR with data memory write DAG2
- data_write_dag2(op, read_reg0((op >> 4) & 15));
+ data_write_dag2(op, read_reg0(BIT(op, 4, 4)));
alu_op_ar(op);
break;
case 0x7c: case 0x7d:
// 0111110x xxxxxxxx xxxxxxxx MAC to MF with data memory write DAG2
- data_write_dag2(op, read_reg0((op >> 4) & 15));
+ data_write_dag2(op, read_reg0(BIT(op, 4, 4)));
mac_op_mf(op);
break;
case 0x7e: case 0x7f:
// 0111111x xxxxxxxx xxxxxxxx ALU to AF with data memory write DAG2
- data_write_dag2(op, read_reg0((op >> 4) & 15));
+ data_write_dag2(op, read_reg0(BIT(op, 4, 4)));
alu_op_af(op);
break;
case 0x80: case 0x81: case 0x82: case 0x83:
// 100000xx xxxxxxxx xxxxxxxx read data memory (immediate addr) to reg group 0
- write_reg0(op & 15, data_read((op >> 4) & 0x3fff));
+ write_reg0(BIT(op, 0, 4), data_read(BIT(op, 4, 14)));
break;
case 0x84: case 0x85: case 0x86: case 0x87:
// 100001xx xxxxxxxx xxxxxxxx read data memory (immediate addr) to reg group 1
- write_reg1(op & 15, data_read((op >> 4) & 0x3fff));
+ write_reg1(BIT(op, 0, 4), data_read(BIT(op, 4, 14)));
break;
case 0x88: case 0x89: case 0x8a: case 0x8b:
// 100010xx xxxxxxxx xxxxxxxx read data memory (immediate addr) to reg group 2
- write_reg2(op & 15, data_read((op >> 4) & 0x3fff));
+ write_reg2(BIT(op, 0, 4), data_read(BIT(op, 4, 14)));
break;
case 0x8c: case 0x8d: case 0x8e: case 0x8f:
// 100011xx xxxxxxxx xxxxxxxx read data memory (immediate addr) to reg group 3
- write_reg3(op & 15, data_read((op >> 4) & 0x3fff));
+ write_reg3(BIT(op, 0, 4), data_read(BIT(op, 4, 14)));
break;
case 0x90: case 0x91: case 0x92: case 0x93:
// 1001xxxx xxxxxxxx xxxxxxxx write data memory (immediate addr) from reg group 0
- data_write((op >> 4) & 0x3fff, read_reg0(op & 15));
+ data_write(BIT(op, 4, 14), read_reg0(BIT(op, 0, 4)));
break;
case 0x94: case 0x95: case 0x96: case 0x97:
// 1001xxxx xxxxxxxx xxxxxxxx write data memory (immediate addr) from reg group 1
- data_write((op >> 4) & 0x3fff, read_reg1(op & 15));
+ data_write(BIT(op, 4, 14), read_reg1(BIT(op, 0, 4)));
break;
case 0x98: case 0x99: case 0x9a: case 0x9b:
// 1001xxxx xxxxxxxx xxxxxxxx write data memory (immediate addr) from reg group 2
- data_write((op >> 4) & 0x3fff, read_reg2(op & 15));
+ data_write(BIT(op, 4, 14), read_reg2(BIT(op, 0, 4)));
break;
case 0x9c: case 0x9d: case 0x9e: case 0x9f:
// 1001xxxx xxxxxxxx xxxxxxxx write data memory (immediate addr) from reg group 3
- data_write((op >> 4) & 0x3fff, read_reg3(op & 15));
+ data_write(BIT(op, 4, 14), read_reg3(BIT(op, 0, 4)));
break;
case 0xa0: case 0xa1: case 0xa2: case 0xa3: case 0xa4: case 0xa5: case 0xa6: case 0xa7:
case 0xa8: case 0xa9: case 0xaa: case 0xab: case 0xac: case 0xad: case 0xae: case 0xaf:
// 1010xxxx xxxxxxxx xxxxxxxx data memory write (immediate) DAG1
- data_write_dag1(op, (op >> 4) & 0xffff);
+ data_write_dag1(op, BIT(op, 4, 16));
break;
case 0xb0: case 0xb1: case 0xb2: case 0xb3: case 0xb4: case 0xb5: case 0xb6: case 0xb7:
case 0xb8: case 0xb9: case 0xba: case 0xbb: case 0xbc: case 0xbd: case 0xbe: case 0xbf:
// 1011xxxx xxxxxxxx xxxxxxxx data memory write (immediate) DAG2
- data_write_dag2(op, (op >> 4) & 0xffff);
+ data_write_dag2(op, BIT(op, 4, 16));
break;
case 0xc0: case 0xc1:
// 1100000x xxxxxxxx xxxxxxxx MAC to MR with data read to AX0 & pgm read to AY0
diff --git a/src/devices/cpu/adsp2100/adsp2100.h b/src/devices/cpu/adsp2100/adsp2100.h
index 29e61f277a7..bf50fbca7a3 100644
--- a/src/devices/cpu/adsp2100/adsp2100.h
+++ b/src/devices/cpu/adsp2100/adsp2100.h
@@ -153,6 +153,8 @@ enum
ADSP2100_FL0,
ADSP2100_FL1,
ADSP2100_FL2,
+ ADSP2100_PMOVLAY,
+ ADSP2100_DMOVLAY,
ADSP2100_AX0_SEC,
ADSP2100_AX1_SEC,
ADSP2100_AY0_SEC,
@@ -194,7 +196,7 @@ public:
// public interfaces
void load_boot_data(uint8_t *srcdata, uint32_t *dstdata);
// Returns base address for circular dag
- uint32_t get_ibase(int index) { return m_base[index]; };
+ uint32_t get_ibase(int index) { return m_base[index]; }
protected:
enum
@@ -211,12 +213,13 @@ protected:
adsp21xx_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock, uint32_t chiptype);
// device-level overrides
- virtual void device_start() override;
- virtual void device_reset() override;
+ virtual void device_start() override ATTR_COLD;
+ virtual void device_reset() override ATTR_COLD;
+ virtual void device_post_load() override;
// device_execute_interface overrides
- virtual uint32_t execute_min_cycles() const override;
- virtual uint32_t execute_max_cycles() const override;
+ virtual uint32_t execute_min_cycles() const noexcept override;
+ virtual uint32_t execute_max_cycles() const noexcept override;
virtual void execute_run() override;
virtual void execute_set_input(int inputnum, int state) override;
@@ -253,17 +256,17 @@ protected:
inline uint32_t data_read_dag2(uint32_t op);
inline void pgm_write_dag2(uint32_t op, int32_t val);
inline uint32_t pgm_read_dag2(uint32_t op);
- void alu_op_ar(int op);
- void alu_op_ar_const(int op);
- void alu_op_af(int op);
- void alu_op_af_const(int op);
- void alu_op_none(int op);
- void mac_op_mr(int op);
- void mac_op_mr_xop(int op);
- void mac_op_mf(int op);
- void mac_op_mf_xop(int op);
- void shift_op(int op);
- void shift_op_imm(int op);
+ void alu_op_ar(uint32_t op);
+ void alu_op_ar_const(uint32_t op);
+ void alu_op_af(uint32_t op);
+ void alu_op_af_const(uint32_t op);
+ void alu_op_none(uint32_t op);
+ void mac_op_mr(uint32_t op);
+ void mac_op_mr_xop(uint32_t op);
+ void mac_op_mf(uint32_t op);
+ void mac_op_mf_xop(uint32_t op);
+ void shift_op(uint32_t op);
+ void shift_op_imm(uint32_t op);
// memory access
inline uint16_t data_read(uint32_t addr);
@@ -277,6 +280,7 @@ protected:
// register read/write
inline void update_i(int which);
inline void update_l(int which);
+ inline void update_dmovlay();
inline void write_reg0(int regnum, int32_t val);
inline void write_reg1(int regnum, int32_t val);
inline void write_reg2(int regnum, int32_t val);
@@ -382,6 +386,8 @@ protected:
uint32_t m_lmask[8];
uint32_t m_base[8];
uint8_t m_px;
+ uint32_t m_pmovlay; // External Program Space overlay
+ uint32_t m_dmovlay; // External Data Space overlay
// stacks
uint32_t m_loop_stack[LOOP_STACK_DEPTH];
@@ -429,10 +435,10 @@ protected:
adsp_core m_alt;
// address spaces
- address_space * m_program;
- address_space * m_data;
- address_space * m_io;
- memory_access_cache<2, -2, ENDIANNESS_LITTLE> *m_cache;
+ memory_access<14, 2, -2, ENDIANNESS_LITTLE>::cache m_cache;
+ memory_access<14, 2, -2, ENDIANNESS_LITTLE>::specific m_program;
+ memory_access<14, 1, -1, ENDIANNESS_LITTLE>::specific m_data;
+ memory_access<11, 1, -1, ENDIANNESS_LITTLE>::specific m_io;
// tables
uint8_t m_condition_table[0x1000];
@@ -441,8 +447,8 @@ protected:
devcb_read32 m_sport_rx_cb; // callback for serial receive
devcb_write32 m_sport_tx_cb; // callback for serial transmit
- devcb_write_line m_timer_fired_cb; // callback for timer fired
- devcb_write_line m_dmovlay_cb; // callback for DMOVLAY instruction
+ devcb_write_line m_timer_fired_cb; // callback for timer fired
+ devcb_write32 m_dmovlay_cb; // callback for DMOVLAY instruction
// debugging
#if ADSP_TRACK_HOTSPOTS
@@ -470,9 +476,6 @@ public:
adsp2100_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
protected:
- // device_execute_interface overrides
- virtual uint32_t execute_input_lines() const override;
-
// device_memory_interface overrides
virtual space_config_vector memory_space_config() const override;
@@ -493,9 +496,6 @@ public:
protected:
adsp2101_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock, uint32_t chiptype);
- // device_execute_interface overrides
- virtual uint32_t execute_input_lines() const override;
-
// device_memory_interface overrides
virtual space_config_vector memory_space_config() const override;
@@ -514,9 +514,6 @@ public:
adsp2181_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
protected:
- // device_execute_interface overrides
- virtual uint32_t execute_input_lines() const override;
-
// device_memory_interface overrides
virtual space_config_vector memory_space_config() const override;
diff --git a/src/devices/cpu/alph8201/8201dasm.cpp b/src/devices/cpu/alph8201/8201dasm.cpp
deleted file mode 100644
index 76a1d0d98a8..00000000000
--- a/src/devices/cpu/alph8201/8201dasm.cpp
+++ /dev/null
@@ -1,404 +0,0 @@
-// license:BSD-3-Clause
-// copyright-holders:Tatsuyuki Satoh
-/*
-
-Notice: The alpha 8201 is now emulated using mame/alpha8201.*
-
-cpu/alph8201/ will be removed when the alpha 8304 has been dumped.
-
-
-
-
-*/
-
-/****************************************************************************
- Alpha 8201/8301 Disassembler
-
- Copyright Tatsuyuki Satoh
- Originally written for the MAME project.
-
-****************************************************************************/
-
-#include "emu.h"
-#include "8201dasm.h"
-
-#include <ctype.h>
-#include <stdexcept>
-
-
-#define FMT(a,b) a, b
-#define PTRS_PER_FORMAT 2
-
-/****************************************************
-
-8201 CONFIRMED OPCODES:
-
-opcode mnemonic function flags
--------- ------------ ------------- -----
-00000000 NOP - --
-00000001 RORA ror A -C
-00000010 ROLA rol A -C
-00000011 INC RXB RXB+=2 ZC
-00000100 DEC RXB RXB-=2 ZC (C=1 means No Borrow: RXB>=2)
-00000101 INC A A++ ZC
-00000110 DEC A A-- ZC (C=1 means No Borrow: A>=1)
-00000110 CPL A A^=$FF --
-00001aaa LD A,(IX0+i) A=[IX0+i] --
-00010aaa LD A,(IX1+i) A=[IX1+i] --
-00011aaa LD (IX2+i),A [IX2+i]=A --
-00111aaa BIT R0.n ZF=R0 bit n Z-
-0100aaa0 LD A,Rn A=Rn Z- [1]
-0100aaa1 LD Rn,A Rn=A --
-0101aaa0 ADD A,Rn A+=Rn ZC
-0101aaa1 SUB A,Rn A-=Rn ZC (C=1 means No Borrow: A>=Rn)
-0110aaa0 AND A,Rn A&=Rn Z-
-0110aaa1 OR A,Rn A|=Rn Z-
-0111aaaa ADD IX0,i IX0+=i --
-1000aaaa ADD IX1,i IX1+=i --
-1001aaaa ADD IX2,i IX2+=i --
-1010aaaa LD RB,i RB=i -- Note: no bounds checking. Can set bank up to F.
-1011-0aa LD MB,i set after-jump page
-1011-1-- STOP
-11000000 imm LD IX0,imm IX0=imm --
-11000001 imm LD IX1,imm IX1=imm --
-11000010 imm LD IX2,imm IX2=imm --
-11000011 imm LD A,imm A=imm --
-11000100 imm LD LP0,imm LP0=imm --
-11000101 imm LD LP1,imm LP1=imm --
-11000110 imm LD LP2,imm LP2=imm --
-11000111 imm LD RXB,imm RXB=imm --
-11001000 imm ADD A,imm A+=imm ZC
-11001001 imm SUB A,imm A-=imm ZC (C=1 means No Borrow: A>=imm)
-11001010 imm AND A,imm A&=imm Z-
-11001011 imm OR A,imm A|=imm Z-
-11001100 imm DJNZ LP0,imm LP0--,branch --
-11001101 imm DJNZ LP1,imm LP1--,branch --
-11001110 imm DJNZ LP2,imm LP2--,branch --
-11001111 imm JNZ imm branch if !Z --
-1101--00 imm JNC imm branch if !C --
-1101--01 imm JZ imm branch if Z --
-1101--1- imm J imm branch --
-1110--xx mirror for the above
-1111--xx mirror for the above
-
-Notes:
-[1] bug: the Z flag is not updated correctly after a LD A,Rn instruction. Fixed in 8302 (possibly 8301).
-
-
-8302 CONFIRMED OPCODES:
-----------------------
-all of the 8201 ones, with stricter decoding for the following:
-
-11010-00 imm JNC imm branch if !C --
-11010-01 imm JZ imm branch if Z --
-11010-1- imm J imm branch --
-
-and these new opcodes:
-
-opcode mnemonic function flags
--------- ------------ --------------- -----
-11011000 imm LD A,(imm) A=MB:[imm] --
-11011001 imm LD (imm),A MB:[imm]=A --
-11011010 imm CMP A,imm temp=A-imm ZC
-11011011 imm XOR A,imm A^=imm Z0
-11011100 imm LD A,R(imm) A=reg(imm) --
-11011101 imm LD R(imm),A reg(imm)=A --
-11011110 imm JC imm branch if C --
-11011111 imm CALL $xx save PC, branch --
-
-11100000 EXG A,IX0 A<->IX0 --
-11100001 EXG A,IX1 A<->IX1 --
-11100010 EXG A,IX2 A<->IX2 --
-11100011 EXG A,LP1 A<->LP1 --
-11100100 EXG A,LP2 A<->LP2 --
-11100101 EXG A,RXB A<->RXB --
-11100110 EXG A,LP0 A<->LP0 --
-11100111 EXG A,RB A<->RB --
-11101000 LD IX0,A IX0=A --
-11101001 LD IX1,A IX1=A --
-11101010 LD IX2,A IX2=A --
-11101011 LD LP1,A LP1=A --
-11101100 LD LP2,A LP2=A --
-11101101 LD RXB,A RXB=A --
-11101110 LD LP0,A LP0=A --
-11101111 LD RB,A RB=A --
-11110000 EXG IX0,IX1 IX0<->IX1 --
-11110001 EXG IX0,IX2 IX0<->IX2 --
-11110010 REP LD (IX2),(RXB) equivalent to LD (IX2),(RXB); INC RXB; DJNZ LP0
-11110011 REP LD (RXB),(IX0) equivalent to LD (RXB),(IX0); INC RXB; DJNZ LP0
-11110100 SAVE ZC save ZC --
-11110101 REST ZC restore ZC ZC
-11110110 LD (RXB),A reg(RXB)=A --
-11110111 LD A,(RXB) A=reg(RXB) --
-11111000 CMP A,(RXB) temp=A-reg(RXB) ZC
-11111001 XOR A,(RXB) A^=reg(RXB) Z0
-11111010 ADD A,CF if (C) A++ ZC
-11111011 SUB A,!CF if (!C) A-- ZC
-11111100 TST A A==0? Z-
-11111101 CLR A A=0 --
-11111110 LD A,(IX0+A) A=[IX0+A] --
-11111111 RET restore PC --
-
-
-8303 CONFIRMED OPCODES:
-----------------------
-all of the 8302 ones, with stricter decoding for the following:
-
-11010000 imm JNC imm branch if !C --
-11010001 imm JZ imm branch if Z --
-1101001- imm J imm branch --
-
-additionally, this opcode is modified to support 11-bit instead of 10-bit
-external addressing, this wasn't used in games however.
-
-1011-0aa LD MB,i modified so that bit 3 is shifted to bit 2 before loading MB.
-
-and these new opcodes are added:
-
-110101--
-11010100 imm LD A,(R77:$%02X)
-11010101 imm LD (R77:$%02X),A
-11010110 imm LD PC,(R77:$%02X) [1]
-11010111 imm LD (R77:$%02X),PC [2]
-
-Notes:
-[1] appears to be LD PC,x in the disassembly, however it's LD LP0,x for kouyakyu
- which uses a 8304, so the opcode was probably changed again.
-[2] appears to be LD x,PC in the disassembly, however it's LD x,LP0 for hvoltage
- which uses a 8304 (or 8404?), so the opcode was probably changed again.
-
-****************************************************/
-
-
-/****************************************************/
-
-const char *const alpha8201_disassembler::Formats[] = {
- FMT("0000_0000", "NOP"), // 00
- FMT("0000_0001", "RRCA"), // 01
- FMT("0000_0010", "RLCA"), // 02
- FMT("0000_0011", "INC RXB"), // 03 : shougi $360 to $377; splndrbt
- FMT("0000_0100", "DEC RXB"), // 04 : not found
- FMT("0000_0101", "INC A"), // 05
- FMT("0000_0110", "DEC A"), // 06
- FMT("0000_0111", "CPL A"), // 07
- FMT("0000_1aaa", "LD A,(IX0+%X)"), // 08-0F
- FMT("0001_0aaa", "LD A,(IX1+%X)"), // 10-17
- FMT("0001_1aaa", "LD (IX2+%X),A"), // 18-1F
- FMT("0010_0aaa", "LD (RXB),(IX0+%X)"),// 20-27 : shougi $360 to $377
- FMT("0010_1aaa", "LD (RXB),(IX1+%X)"),// 28-2f : not found
- FMT("0011_0aaa", "LD (IX2+%X),(RXB)"),// 30-37 : not found
- FMT("0011_1aaa", "BIT R0.%d"), // 38-3F ZF = R0.a (bit test)
- FMT("0100_aaa0", "LD A,R%X"), // 40-4E
- FMT("0100_aaa1", "LD R%X,A"), // 41-4F
- FMT("0101_aaa0", "ADD A,R%X"), // 50-5E
- FMT("0101_aaa1", "SUB A,R%X"), // 51-5F
- FMT("0110_aaa0", "AND A,R%X"), // 60-6E
- FMT("0110_aaa1", "OR A,R%X"), // 61-6F
- FMT("0111_aaaa", "ADD IX0,$%X"), // 70-7f
- FMT("1000_aaaa", "ADD IX1,$%X"), // 80-8f
- FMT("1001_aaaa", "ADD IX2,$%X"), // 90-9f
- FMT("1010_aaaa", "LD RB,%X"), // A0-AF
- FMT("1011_x0aa", "LD MB,%X"), // B0-B3 (+ mirrors)
- FMT("1011_x1xx", "STOP"), // B4 (+ mirrors)
-
- FMT("1100_0000 I", "LD IX0,$%02X"), // C0
- FMT("1100_0001 I", "LD IX1,$%02X"), // C1
- FMT("1100_0010 I", "LD IX2,$%02X"), // C2
- FMT("1100_0011 I", "LD A,$%02X"), // C3
- FMT("1100_0100 I", "LD LP0,$%02X"), // C4
- FMT("1100_0101 I", "LD LP1,$%02X"), // C5
- FMT("1100_0110 I", "LD LP2,$%02X"), // C6
- FMT("1100_0111 I", "LD RXB,$%02X"), // C7 : shougi, splndrbt, equites
- FMT("1100_1000 I", "ADD A,$%02X"), // C8
- FMT("1100_1001 I", "SUB A,$%02X"), // C9
- FMT("1100_1010 I", "AND A,$%02X"), // CA
- FMT("1100_1011 I", "OR A,$%02X"), // CB
- FMT("1100_1100 I", "DJNZ LP0,$%02X"), // CC
- FMT("1100_1101 I", "DJNZ LP1,$%02X"), // CD
- FMT("1100_1110 I", "DJNZ LP2,$%02X"), // CE
- FMT("1100_1111 I", "JNZ $%02X"), // CF
- FMT("1101_0000 I", "JNC $%02X"), // D0
- FMT("1101_0001 I", "JZ $%02X"), // D1
- FMT("1101_001x I", "J $%02X"), // D2 (+ mirror)
-
- /* -------------- 830x only ------------- */
-
- FMT("1101_0100 I", "LD A,(R77:$%02X)"), // D4 : 8303+ only. exctscc2, bullfgtr
- FMT("1101_0101 I", "LD (R77:$%02X),A"), // D5 : 8303+ only. exctscc2, bullfgtr, kouyakyu
- FMT("1101_0110 I", "LD LP0,(R77:$%02X)"), // D6 : 8303+ only. kouyakyu
- FMT("1101_0111 I", "LD (R77:$%02X),LP0"), // D7 : 8303+ only. hvoltage
- FMT("1101_1000 I", "LD A,($%02X)"), // D8 : equites
- FMT("1101_1001 I", "LD ($%02X),A"), // D9 : equites
- FMT("1101_1010 I", "CMP A,$%02X"), // DA :
- FMT("1101_1011 I", "XOR A,$%02X"), // DB : equites splndrbt
- FMT("1101_1100 I", "LD A,R($%02X)"), // DC : not found
- FMT("1101_1101 I", "LD R($%02X),A"), // DD : equites, splndrbt
- FMT("1101_1110 I", "JC $%02X"), // DE : not found
- FMT("1101_1111 I", "CALL $%02X"), // DF :
-
- FMT("1110_0000", "EXG A,IX0"), // E0 : exctsccr
- FMT("1110_0001", "EXG A,IX1"), // E1 : not found
- FMT("1110_0010", "EXG A,IX2"), // E2 : not found
- FMT("1110_0011", "EXG A,LP1"), // E3 : exctsccr in pair with EB
- FMT("1110_0100", "EXG A,LP2"), // E4 : not found
- FMT("1110_0101", "EXG A,RXB"), // E5 : splndrbt
- FMT("1110_0110", "EXG A,LP0"), // E6 : splndrbt, bullfgtr, kouyakyu. EXG, not LD: see splndrbt $3ba to $3d3
- FMT("1110_0111", "EXG A,RB"), // E7 : not found
- FMT("1110_1000", "LD IX0,A"), // E8 :
- FMT("1110_1001", "LD IX1,A"), // E9 : not found
- FMT("1110_1010", "LD IX2,A"), // EA :
- FMT("1110_1011", "LD LP1,A"), // EB : exctsccr in pair with E3
- FMT("1110_1100", "LP LP2,A"), // EC : not found
- FMT("1110_1101", "LD RXB,A"), // ED : splndrbt
- FMT("1110_1110", "LD LP0,A"), // EE : splndrbt, bullfgtr
- FMT("1110_1111", "LD RB,A"), // EF : not found
- FMT("1111_0000", "EXG IX0,IX1"), // F0 : not found
- FMT("1111_0001", "EXG IX0,IX2"), // F1 : splndrbt $2e to $38, equites $40 to $4a
- FMT("1111_0010", "REP LD (IX2),(RXB)"),// F2 : splndrbt LD (IX2),(RXB); INC RXB; DJNZ LP0
- FMT("1111_0011", "REP LD (RXB),(IX0)"),// F3 : not found LD (RXB),(IX0); INC RXB; DJNZ LP0
- FMT("1111_0100", "SAVE ZC"), // F4 : not found
- FMT("1111_0101", "REST ZC"), // F5 : not found
- FMT("1111_0110", "LD (RXB),A"), // F6 : exctsccr
- FMT("1111_0111", "LD A,(RXB)"), // F7 : not found
- FMT("1111_1000", "CMP A,(RXB)"), // F8 : exctsccr
- FMT("1111_1001", "XOR A,(RXB)"), // F9 : exctsccr
- FMT("1111_1010", "ADD A,CF"), // FA :
- FMT("1111_1011", "SUB A,!CF"), // FB : not found
- FMT("1111_1100", "TST A"), // FC :
- FMT("1111_1101", "CLR A"), // FD :
- FMT("1111_1110", "LD A,(IX0+A)"), // FE :
- FMT("1111_1111", "RET"), // FF :
- nullptr
-};
-
-alpha8201_disassembler::alpha8201_disassembler()
-{
- const char *p;
- u8 mask, bits;
- int bit;
- int i;
- char chr , type;
- int pmask , pdown;
-
- for(i=0;(p=Formats[i*2])!=nullptr;i++)
- {
- mask = 0;
- bits = 0;
- pmask = 0;
- pdown = 0;
- type = 0;
- bit = 7;
- while (*p && bit >= 0) {
- chr = *p++;
- switch (chr) {
- case '1': bits |= 1<<bit;
- case '0': mask |= 1<<bit; bit--; break;
-#if 0
- case 'b':
- type |= 0x80;
-#endif
- case 'a':
- pmask |= 1<<bit;
- pdown = bit;
- case 'x':
- bit--;
- break;
- case '_':
- continue;
- default:
- throw std::logic_error(util::string_format("Invalid instruction encoding '%s %s'\n", Formats[i*2],Formats[i*2+1]));
- }
- }
- if (bit != -1) {
- throw std::logic_error(util::string_format("not enough bits in encoding '%s %s' %d\n", Formats[i*2],Formats[i*2+1],bit));
- }
-
- Op[i].mask = mask;
- Op[i].bits = bits;
- Op[i].pmask = pmask;
- Op[i].pdown = pdown;
- Op[i].fmt = Formats[i*2+1];
- Op[i].type = type;
-
- /* 2 byte code ? */
- while (isspace(u8(*p))) p++;
- if( (*p) )
- Op[i].type |= 0x10;
- /* number of param */
- if( (p=strchr(Op[i].fmt,'%'))!=nullptr )
- {
- Op[i].type |= 0x01; /* single param */
- if(strchr(p+1,'%') )
- Op[i].type |= 0x02; /* double param */
- }
- }
- op_count = i;
-}
-
-offs_t alpha8201_disassembler::disassemble(std::ostream &stream, offs_t pc, const data_buffer &opcodes, const data_buffer &params)
-{
- offs_t dasmflags = 0;
- int i;
- int op;
- int cnt = 1;
- int code , disp;
-
- code = opcodes.r8(pc);
- op = -1; /* no matching opcode */
- for ( i = 0; i < op_count; i++)
- {
- if( (code & Op[i].mask) == Op[i].bits )
- {
- if (op != -1)
- {
- fprintf(stderr, "Error: opcode %02X matches %d (%s) and %d (%s)\n",
- code,i,Op[i].fmt,op,Op[op].fmt);
- }
- op = i;
- }
- }
-
- if (op == -1)
- {
- util::stream_format(stream, "db %2.2x",code);
- return cnt;
- }
-
- if (Op[op].type & 0x10)
- {
- disp = params.r8(pc+1);
- cnt++;
- }
- else
- {
- disp = (code & Op[op].pmask) >> Op[op].pdown;
- }
-
- if (Op[op].type & 0x02)
- util::stream_format(stream, Op[op].fmt,disp,disp);
- else if (Op[op].type & 0x01)
- util::stream_format(stream, Op[op].fmt,disp);
- else
- util::stream_format(stream, "%s",Op[op].fmt);
-
- switch (code)
- {
- case 0xcc:
- case 0xcd:
- case 0xce:
- case 0xdf:
- dasmflags = STEP_OVER;
- break;
-
- case 0xff:
- dasmflags = STEP_OUT;
- break;
- }
-
- return cnt | dasmflags | SUPPORTED;
-}
-
-u32 alpha8201_disassembler::opcode_alignment() const
-{
- return 1;
-}
diff --git a/src/devices/cpu/alph8201/8201dasm.h b/src/devices/cpu/alph8201/8201dasm.h
deleted file mode 100644
index 85676c5de10..00000000000
--- a/src/devices/cpu/alph8201/8201dasm.h
+++ /dev/null
@@ -1,51 +0,0 @@
-// license:BSD-3-Clause
-// copyright-holders:Tatsuyuki Satoh
-/*
-
-Notice: The alpha 8201 is now emulated using mame/alpha8201.*
-
-cpu/alph8201/ will be removed when the alpha 8304 has been dumped.
-
-
-
-
-*/
-
-/****************************************************************************
- Alpha 8201/8301 Disassembler
-
- Copyright Tatsuyuki Satoh
- Originally written for the MAME project.
-
-****************************************************************************/
-
-#ifndef MAME_CPU_ALPH8201_8201DASM_H
-#define MAME_CPU_ALPH8201_8201DASM_H
-
-#pragma once
-
-class alpha8201_disassembler : public util::disasm_interface
-{
-public:
- alpha8201_disassembler();
- virtual ~alpha8201_disassembler() = default;
-
- virtual u32 opcode_alignment() const override;
- virtual offs_t disassemble(std::ostream &stream, offs_t pc, const data_buffer &opcodes, const data_buffer &params) override;
-
-private:
- struct AD8201Opcode {
- u8 mask;
- u8 bits;
- u8 type;
- u8 pmask;
- u8 pdown;
- const char *fmt;
- };
-
- static const char *const Formats[];
- AD8201Opcode Op[256];
- int op_count;
-};
-
-#endif
diff --git a/src/devices/cpu/alph8201/alph8201.cpp b/src/devices/cpu/alph8201/alph8201.cpp
deleted file mode 100644
index 111b833c9bb..00000000000
--- a/src/devices/cpu/alph8201/alph8201.cpp
+++ /dev/null
@@ -1,698 +0,0 @@
-// license:BSD-3-Clause
-// copyright-holders:Tatsuyuki Satoh
-/*
-
-Notice: The alpha 8201 is now emulated using mame/alpha8201.*
-
-cpu/alph8201/ will be removed when the alpha 8304 has been dumped.
-
-
-
-
-*/
-
-/****************************************************************************
- Alpha8201 Emulator
-
- Copyright Tatsuyuki Satoh
- Originally written for the MAME project.
-
-
-The Alpha8201/830x isn't a real CPU. It is a Hitachi HD44801 4-bit MCU,
-programmed to interpret an external program using a custom instruction set.
-Alpha8301 has an expanded instruction set, backwards compatible with Alpha8201
-
-The internal ROM hasn't been read (yet), so here we provide a simulation of
-the behaviour.
-
-
-Game Year MCU
------------------------- ---- ----
-Shougi 1982? 8201 (pcb)
-Shougi 2 1982? 8201 (pcb)
-Talbot 1982 8201?
-Champion Base Ball 1983 8201 (schematics)
-Exciting Soccer 1983 8302 (pcb)
-Champion Base Ball II 1983 8302 (pcb, unofficial schematics)
-Exciting Soccer II 1984 8303 (uses 8303+ opcodes)
-Equites 1984 8303 (post)
-Bull Fighter 1984 8303 (post)
-Splendor Blast 1985 8303 (post)
-Gekisou 1985 8304 (post)
-The Koukou Yakyuu 1985 8304 (post)
-High Voltage 1985 8304?(post says 8404, but readme says 8304)
-unknown CLS bingo game 1986 8505
-
-ALPHA-8201: "44801A75" -> HD44801, ROM code = A75
-ALPHA-8302: "44801B35" -> HD44801, ROM code = B35
-ALPHA-8303: "44801B42" -> HD44801, ROM code = B42
-ALPHA-8304: ?
-ALPHA-8505: "44801C57" -> HD44801, ROM code = C57
-
-
- Notes :
- some unknown instruction are not emulated.
-
- Because there was no information, opcode-syntax was created.
-
- TODO:
- verify with real chip or analyze more.
- -A lot of 8301 opcode.
- -memory address 000 specification
- -memory address 001 bit 7-5 specification
- -write value after HALT operation to ODD of vector memory.
- -operation cycle(execution speed).
-
-****************************************************************************/
-
-/****************************************************************************
-
------------------------
-package / pin assign
------------------------
-ALPHA 8201 DIP 42
-
-pin HD44801 Alpha
---- ------- -----
-1 : D3 WR
-2-4 : D4-D6 n.c.
-5-7 : D7-D9 GND in shougi , n.c. in champbas
-8-13 : D10-D15 n.c.
-14 : n.c. n.c.
-15 : RESET RESET
-16 : GND GND
-17 : OSC1 (champbas=384KHz)
-18 : OSC2 n.c.
-19 : !HLT Vcc
-20 : !TEST Vcc
-21 : Vcc Vcc
-22-25: R00-R03 DB4-DB7
-26-29: R10-R13 DB0-DB3
-30 : INT0 GO (input)
-31 : INT1 n.c.
-32-35: R20-R23 A4-A7
-36-39: R30-R33 A0-A3
-40-41: D0-D1 A8-A9
-42 : D2 /RD
-
-
------------------------
-Register Set
------------------------
-
-PC : 10bit Program Pointer
- A lower 8bits are loaded from the immidate.
- A higher 2bits are loaded from the MB register.
-
-MB : 2bit memory bank register, load PC[9:8] after branch
- load high to higher 2bit of PC after branch.
-
-RB : 3bit register bank select register
-
-R0-R7 : internal? RAM register 8bitx8 (x8 bank)
-
-A : 8bit
-
-cpustate->IX0/1 : memory indirect 'read' access pointer
-
-cpustate->IX2 : memory indirect 'write' access pointer
-
-RXB : unknown , looks index register
-
-cpustate->LP0/1/2 : loop count register used by DJNZ operation
-
-cpustate->cf : carry flag
-cpustate->zf : zero flag
-
------------------------
-Memoy Space
------------------------
-
-000 : unknown ...
-001 : bit4..0 = pointer of current entry , bit7..6 = unknown
-002-003 : entrypoint1 vector
-004-005 : entrypoint2 vector
-006-007 : entrypoint3 vector
-008-009 : entrypoint4 vector
-00A-00B : entrypoint5 vector
-00C-00D : entrypoint6 vector
-00E-00F : entrypoint7 vector
-010-011 : entrypoint8 vector
-012-013 : entrypoint9 vector
-014-015 : entrypoint10 vector
-016-017 : entrypoint11 vector
-018-019 : entrypoint12 vector
-01A-01B : entrypoint13 vector
-01C-01D : entrypoint14 vector
-01E-01F : entrypoint15 vector
-020-0FF : bank 0, program / data memory
-100-1FF : bank 1, program / data memory
-200-2FF : bank 2, program / data memory
-300-3FF : bank 3, program / data memory
-
-The even address is the lower byte of the entry address.
-The odd-address of entry point is a MB and status.
- Bit 0 and 1 are a memory bank.
- Bit 2 is HALT.At the time of set, it doesn't execute entry address.
- After EXIT operation, Bit2 is set.
-
------------------------
-Timming
------------------------
-
-****************************************************************************/
-
-#include "emu.h"
-#include "alph8201.h"
-#include "debugger.h"
-#include "8201dasm.h"
-
-DEFINE_DEVICE_TYPE(ALPHA8201L, alpha8201_cpu_device, "alpha8201l", "ALPHA-8201L")
-DEFINE_DEVICE_TYPE(ALPHA8301L, alpha8301_cpu_device, "alpha8301l", "ALPHA-8301L")
-
-
-/* instruction cycle count */
-#define C1 16
-#define C2 32
-
-/* debug option */
-#define TRACE_PC 0
-#define SHOW_ENTRY_POINT 0
-#define SHOW_MESSAGE_CONSOLE 0
-#define BREAK_ON_UNKNOWN_OPCODE 0
-#define BREAK_ON_UNCERTAIN_OPCODE 0
-
-
-#define FN(x) &alpha8201_cpu_device::x
-
-
-alpha8201_cpu_device::alpha8201_cpu_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock)
- : alpha8201_cpu_device(mconfig, ALPHA8201L, tag, owner, clock, opcode_8201)
-{
-}
-
-
-alpha8201_cpu_device::alpha8201_cpu_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, u32 clock, const s_opcode *opmap)
- : cpu_device(mconfig, type, tag, owner, clock)
- , m_program_config("program", ENDIANNESS_LITTLE, 8, 10, 0)
- , m_io_config("io", ENDIANNESS_LITTLE, 8, 6, 0)
- , m_opmap(opmap)
-{
-}
-
-alpha8301_cpu_device::alpha8301_cpu_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock)
- : alpha8201_cpu_device(mconfig, ALPHA8301L, tag, owner, clock, opcode_8301)
-{
-}
-
-device_memory_interface::space_config_vector alpha8201_cpu_device::memory_space_config() const
-{
- return space_config_vector {
- std::make_pair(AS_PROGRAM, &m_program_config),
- std::make_pair(AS_IO, &m_io_config)
- };
-}
-
-/* Get next opcode argument and increment program counter */
-unsigned alpha8201_cpu_device::M_RDMEM_OPCODE()
-{
- unsigned retval;
- retval=M_RDOP_ARG(m_pc.w.l);
- m_pc.b.l++;
- return retval;
-}
-
-void alpha8201_cpu_device::M_ADD(u8 dat)
-{
- u16 temp = m_A + dat;
- m_A = temp & 0xff;
- m_zf = (m_A==0);
- m_cf = temp>>8;
-}
-
-void alpha8201_cpu_device::M_ADDB(u8 dat)
-{
- u16 temp = m_B + dat;
- m_B = temp & 0xff;
- m_zf = (m_B==0);
- m_cf = temp>>8;
-}
-
-void alpha8201_cpu_device::M_SUB(u8 dat)
-{
- m_cf = (m_A>=dat); // m_cf is No Borrow
- m_A -= dat;
- m_zf = (m_A==0);
-}
-
-void alpha8201_cpu_device::M_AND(u8 dat)
-{
- m_A &= dat;
- m_zf = (m_A==0);
-}
-
-void alpha8201_cpu_device::M_OR(u8 dat)
-{
- m_A |= dat;
- m_zf = (m_A==0);
-}
-
-void alpha8201_cpu_device::M_XOR(u8 dat)
-{
- m_A ^= dat;
- m_zf = (m_A==0);
- m_cf = 0;
-}
-
-void alpha8201_cpu_device::M_JMP(u8 dat)
-{
- m_pc.b.l = dat;
- /* update pc page */
- m_pc.b.h = m_ix0.b.h = m_ix1.b.h = m_ix2.b.h = m_mb & 3;
-}
-
-void alpha8201_cpu_device::M_UNDEFINED()
-{
- logerror("alpha8201: PC = %03x, Unimplemented opcode = %02x\n", m_pc.w.l-1, M_RDMEM(m_pc.w.l-1));
-#if SHOW_MESSAGE_CONSOLE
- osd_printf_debug("alpha8201: PC = %03x, Unimplemented opcode = %02x\n", m_pc.w.l-1, M_RDMEM(m_pc.w.l-1));
-#endif
-#if BREAK_ON_UNKNOWN_OPCODE
- machine().debug_break();
-#endif
-}
-
-void alpha8201_cpu_device::M_UNDEFINED2()
-{
- u8 op = M_RDOP(m_pc.w.l-1);
- u8 imm = M_RDMEM_OPCODE();
- logerror("alpha8201: PC = %03x, Unimplemented opcode = %02x,%02x\n", m_pc.w.l-2, op,imm);
-#if SHOW_MESSAGE_CONSOLE
- osd_printf_debug("alpha8201: PC = %03x, Unimplemented opcode = %02x,%02x\n", m_pc.w.l-2, op,imm);
-#endif
-#if BREAK_ON_UNKNOWN_OPCODE
- machine().debug_break();
-#endif
-}
-
-
-void alpha8201_cpu_device::stop()
-{
- u8 pcptr = M_RDMEM(0x001) & 0x1f;
- M_WRMEM(pcptr,(M_RDMEM(pcptr)&0xf)+0x08); /* mark entry point ODD to HALT */
- m_mb |= 0x08; /* mark internal HALT state */
-}
-
-
-const alpha8201_cpu_device::s_opcode alpha8201_cpu_device::opcode_8201[256]=
-{
- {C1, FN(nop) },{C1,FN(rora) },{C1, FN(rola) },{C1,FN(inc_b) },{C1,FN(dec_b) },{C1, FN(inc_a) },{C1, FN(dec_a) },{C1, FN(cpl) },
- {C2,FN(ld_a_ix0_0) },{C2,FN(ld_a_ix0_1)},{C2, FN(ld_a_ix0_2)},{C2,FN(ld_a_ix0_3)},{C2,FN(ld_a_ix0_4)},{C2,FN(ld_a_ix0_5)},{C2,FN(ld_a_ix0_6)},{C2,FN(ld_a_ix0_7)},
- {C2,FN(ld_a_ix1_0) },{C2,FN(ld_a_ix1_1)},{C2, FN(ld_a_ix1_2)},{C2,FN(ld_a_ix1_3)},{C2,FN(ld_a_ix1_4)},{C2,FN(ld_a_ix1_5)},{C2,FN(ld_a_ix1_6)},{C2,FN(ld_a_ix1_7)},
- {C2,FN(ld_ix2_0_a) },{C2,FN(ld_ix2_1_a)},{C2, FN(ld_ix2_2_a)},{C2,FN(ld_ix2_3_a)},{C2,FN(ld_ix2_4_a)},{C2,FN(ld_ix2_5_a)},{C2,FN(ld_ix2_6_a)},{C2,FN(ld_ix2_7_a)},
-/* 20 */
- {C2,FN(ld_ix0_0_b) },{C2,FN(ld_ix0_1_b)},{C2, FN(ld_ix0_2_b)},{C2,FN(ld_ix0_3_b)},{C2,FN(ld_ix0_4_b)},{C2,FN(ld_ix0_5_b)},{C2,FN(ld_ix0_6_b)},{C2,FN(ld_ix0_7_b)},
- {C2,FN(undefined) },{C2,FN(undefined) },{C2, FN(undefined) },{C2,FN(undefined) },{C2,FN(undefined) },{C2,FN(undefined) },{C2,FN(undefined) },{C2,FN(undefined) },
- {C2,FN(undefined) },{C2,FN(undefined) },{C2, FN(undefined) },{C2,FN(undefined) },{C2,FN(undefined) },{C2,FN(undefined) },{C2,FN(undefined) },{C2,FN(undefined) },
- {C2,FN(bit_r0_0) },{C2,FN(bit_r0_1) },{C2, FN(bit_r0_2) },{C2, FN(bit_r0_3) },{C2, FN(bit_r0_4) },{C2, FN(bit_r0_5) },{C2, FN(bit_r0_6) },{C2, FN(bit_r0_7) },
-/* 40 : 8201 */
- {C2, FN(ld_a_r0) },{C2, FN(ld_r0_a) },{C2, FN(ld_a_r1) },{C2, FN(ld_r1_a) },{C2, FN(ld_a_r2) },{C2, FN(ld_r2_a) },{C2, FN(ld_a_r3) },{C2, FN(ld_r3_a) },
- {C2, FN(ld_a_r4) },{C2, FN(ld_r4_a) },{C2, FN(ld_a_r5) },{C2, FN(ld_r5_a) },{C2, FN(ld_a_r6) },{C2, FN(ld_r6_a) },{C2, FN(ld_a_r7) },{C2, FN(ld_r7_a) },
- {C1, FN(add_a_r0) },{C1, FN(sub_a_r0) },{C1, FN(add_a_r1) },{C1, FN(sub_a_r1) },{C1, FN(add_a_r2) },{C1, FN(sub_a_r2) },{C1, FN(add_a_r3) },{C1, FN(sub_a_r3) },
- {C1, FN(add_a_r4) },{C1, FN(sub_a_r4) },{C1, FN(add_a_r5) },{C1, FN(sub_a_r5) },{C1, FN(add_a_r6) },{C1, FN(sub_a_r6) },{C1, FN(add_a_r7) },{C1, FN(sub_a_r7) },
- {C1, FN(and_a_r0) },{C1, FN(or_a_r0) },{C1, FN(and_a_r1) },{C1, FN(or_a_r1) },{C1, FN(and_a_r2) },{C1, FN(or_a_r2) },{C1, FN(and_a_r3) },{C1, FN(or_a_r3) },
- {C1, FN(and_a_r4) },{C1, FN(or_a_r4) },{C1, FN(and_a_r5) },{C1, FN(or_a_r5) },{C1, FN(and_a_r6) },{C1, FN(or_a_r6) },{C1, FN(and_a_r7) },{C1, FN(or_a_r7) },
- {C1, FN(add_ix0_0) },{C1, FN(add_ix0_1)},{C1, FN(add_ix0_2)},{C1, FN(add_ix0_3)},{C1, FN(add_ix0_4)},{C1, FN(add_ix0_5)},{C1, FN(add_ix0_6)},{C1, FN(add_ix0_7)},
- {C1, FN(add_ix0_8) },{C1, FN(add_ix0_9)},{C1, FN(add_ix0_a)},{C1, FN(add_ix0_b)},{C1, FN(add_ix0_c)},{C1, FN(add_ix0_d)},{C1, FN(add_ix0_e)},{C1, FN(add_ix0_f)},
-/* 80 : 8201 */
- {C1, FN(add_ix1_0) },{C1, FN(add_ix1_1)},{C1, FN(add_ix1_2)},{C1, FN(add_ix1_3)},{C1, FN(add_ix1_4)},{C1, FN(add_ix1_5)},{C1, FN(add_ix1_6)},{C1, FN(add_ix1_7)},
- {C1, FN(add_ix1_8) },{C1, FN(add_ix1_9)},{C1, FN(add_ix1_a)},{C1, FN(add_ix1_b)},{C1, FN(add_ix1_c)},{C1, FN(add_ix1_d)},{C1, FN(add_ix1_e)},{C1, FN(add_ix1_f)},
- {C1, FN(add_ix2_0) },{C1, FN(add_ix2_1)},{C1, FN(add_ix2_2)},{C1, FN(add_ix2_3)},{C1, FN(add_ix2_4)},{C1, FN(add_ix2_5)},{C1, FN(add_ix2_6)},{C1, FN(add_ix2_7)},
- {C1, FN(add_ix2_8) },{C1, FN(add_ix2_9)},{C1, FN(add_ix2_a)},{C1, FN(add_ix2_b)},{C1, FN(add_ix2_c)},{C1, FN(add_ix2_d)},{C1, FN(add_ix2_e)},{C1, FN(add_ix2_f)},
- {C1, FN(ld_base_0) },{C1, FN(ld_base_1)},{C1, FN(ld_base_2)},{C1, FN(ld_base_3)},{C1, FN(ld_base_4)},{C1, FN(ld_base_5)},{C1, FN(ld_base_6)},{C1, FN(ld_base_7)},
- {C1, FN(undefined) },{C1, FN(undefined)},{C1, FN(undefined)},{C1, FN(undefined)},{C1, FN(undefined)},{C1, FN(undefined)},{C1, FN(undefined)},{C1, FN(undefined)},
- {C1, FN(ld_bank_0) },{C1, FN(ld_bank_1)},{C1, FN(ld_bank_2)},{C1, FN(ld_bank_3)},{C2, FN(stop) },{C1, FN(undefined)},{C1, FN(undefined)},{C1, FN(undefined)},
- {C1, FN(undefined) },{C1, FN(undefined)},{C1, FN(undefined)},{C1, FN(undefined)},{C1, FN(undefined)},{C1, FN(undefined)},{C1, FN(undefined)},{C1, FN(undefined)},
-/* c0 : 8201 */
- {C2, FN(ld_ix0_n) },{C2, FN(ld_ix1_n) },{C2, FN(ld_ix2_n) },{C2, FN(ld_a_n) },{C2, FN(ld_lp0_n) },{C2, FN(ld_lp1_n) },{C2, FN(ld_lp2_n) },{C2, FN(ld_b_n) },
- {C2, FN(add_a_n) },{C2, FN(sub_a_n) },{C2, FN(and_a_n) },{C2, FN(or_a_n) },{C2, FN(djnz_lp0) },{C2, FN(djnz_lp1) },{C2, FN(djnz_lp2) },{C2, FN(jnz) },
- {C2, FN(jnc) },{C2, FN(jz) },{C2, FN(jmp) },{C2,FN(undefined2)},{C2,FN(undefined2)},{C2,FN(undefined2)},{C2,FN(undefined2)},{C2, FN(undefined2)},
- {C2, FN(undefined2) },{C2,FN(undefined2)},{C2,FN(undefined2)},{C2,FN(undefined2)},{C2,FN(undefined2)},{C2,FN(undefined2)},{C2,FN(undefined2)},{C2, FN(undefined2)},
-/* E0 : 8201*/
- {C1, FN(undefined) },{C1, FN(undefined)},{C1, FN(undefined)},{C1, FN(undefined)},{C1, FN(undefined)},{C1, FN(undefined)},{C1, FN(undefined)},{C1, FN(undefined)},
- {C1, FN(undefined) },{C1, FN(undefined)},{C1, FN(undefined)},{C1, FN(undefined)},{C1, FN(undefined)},{C1, FN(undefined)},{C1, FN(undefined)},{C1, FN(undefined)},
- {C1, FN(undefined) },{C1, FN(undefined)},{C1, FN(undefined)},{C1, FN(undefined)},{C1, FN(undefined)},{C1, FN(undefined)},{C1, FN(undefined)},{C1, FN(undefined)},
- {C1, FN(undefined) },{C1, FN(undefined)},{C1, FN(undefined)},{C1, FN(undefined)},{C1, FN(undefined)},{C1, FN(undefined)},{C1, FN(undefined)},{C1, FN(undefined) }
-};
-
-
-const alpha8201_cpu_device::s_opcode alpha8201_cpu_device::opcode_8301[256]=
-{
- {C1, FN(nop) },{C1,FN(rora) },{C1, FN(rola) },{C1,FN(inc_b) },{C1,FN(dec_b) },{C1, FN(inc_a) },{C1, FN(dec_a) },{C1, FN(cpl) },
- {C2,FN(ld_a_ix0_0) },{C2,FN(ld_a_ix0_1)},{C2, FN(ld_a_ix0_2)},{C2,FN(ld_a_ix0_3)},{C2,FN(ld_a_ix0_4)},{C2,FN(ld_a_ix0_5)},{C2,FN(ld_a_ix0_6)},{C2,FN(ld_a_ix0_7)},
- {C2,FN(ld_a_ix1_0) },{C2,FN(ld_a_ix1_1)},{C2, FN(ld_a_ix1_2)},{C2,FN(ld_a_ix1_3)},{C2,FN(ld_a_ix1_4)},{C2,FN(ld_a_ix1_5)},{C2,FN(ld_a_ix1_6)},{C2,FN(ld_a_ix1_7)},
- {C2,FN(ld_ix2_0_a) },{C2,FN(ld_ix2_1_a)},{C2, FN(ld_ix2_2_a)},{C2,FN(ld_ix2_3_a)},{C2,FN(ld_ix2_4_a)},{C2,FN(ld_ix2_5_a)},{C2,FN(ld_ix2_6_a)},{C2,FN(ld_ix2_7_a)},
-/* 20 : 8301 */
- {C2,FN(ld_ix0_0_b) },{C2,FN(ld_ix0_1_b)},{C2, FN(ld_ix0_2_b)},{C2,FN(ld_ix0_3_b)},{C2,FN(ld_ix0_4_b)},{C2,FN(ld_ix0_5_b)},{C2,FN(ld_ix0_6_b)},{C2,FN(ld_ix0_7_b)},
- {C2,FN(undefined) },{C2,FN(undefined) },{C2, FN(undefined) },{C2,FN(undefined) },{C2,FN(undefined) },{C2,FN(undefined) },{C2,FN(undefined) },{C2,FN(undefined) },
- {C2,FN(undefined) },{C2,FN(undefined) },{C2, FN(undefined) },{C2,FN(undefined) },{C2,FN(undefined) },{C2,FN(undefined) },{C2,FN(undefined) },{C2,FN(undefined) },
- {C2,FN(bit_r0_0) },{C2,FN(bit_r0_1) },{C2, FN(bit_r0_2) },{C2, FN(bit_r0_3) },{C2, FN(bit_r0_4) },{C2, FN(bit_r0_5) },{C2, FN(bit_r0_6) },{C2, FN(bit_r0_7) },
-/* 40 : 8301 */
- {C2, FN(ld_a_r0) },{C2, FN(ld_r0_a) },{C2, FN(ld_a_r1) },{C2, FN(ld_r1_a) },{C2, FN(ld_a_r2) },{C2, FN(ld_r2_a) },{C2, FN(ld_a_r3) },{C2, FN(ld_r3_a) },
- {C2, FN(ld_a_r4) },{C2, FN(ld_r4_a) },{C2, FN(ld_a_r5) },{C2, FN(ld_r5_a) },{C2, FN(ld_a_r6) },{C2, FN(ld_r6_a) },{C2, FN(ld_a_r7) },{C2, FN(ld_r7_a) },
- {C1, FN(add_a_r0) },{C1, FN(sub_a_r0) },{C1, FN(add_a_r1) },{C1, FN(sub_a_r1) },{C1, FN(add_a_r2) },{C1, FN(sub_a_r2) },{C1, FN(add_a_r3) },{C1, FN(sub_a_r3) },
- {C1, FN(add_a_r4) },{C1, FN(sub_a_r4) },{C1, FN(add_a_r5) },{C1, FN(sub_a_r5) },{C1, FN(add_a_r6) },{C1, FN(sub_a_r6) },{C1, FN(add_a_r7) },{C1, FN(sub_a_r7) },
-/* 60 : 8301 */
- {C1, FN(and_a_r0) },{C1, FN(or_a_r0) },{C1, FN(and_a_r1) },{C1, FN(or_a_r1) },{C1, FN(and_a_r2) },{C1, FN(or_a_r2) },{C1, FN(and_a_r3) },{C1, FN(or_a_r3) },
- {C1, FN(and_a_r4) },{C1, FN(or_a_r4) },{C1, FN(and_a_r5) },{C1, FN(or_a_r5) },{C1, FN(and_a_r6) },{C1, FN(or_a_r6) },{C1, FN(and_a_r7) },{C1, FN(or_a_r7) },
- {C1, FN(add_ix0_0) },{C1, FN(add_ix0_1)},{C1, FN(add_ix0_2)},{C1, FN(add_ix0_3)},{C1, FN(add_ix0_4)},{C1, FN(add_ix0_5)},{C1, FN(add_ix0_6)},{C1, FN(add_ix0_7)},
- {C1, FN(add_ix0_8) },{C1, FN(add_ix0_9)},{C1, FN(add_ix0_a)},{C1, FN(add_ix0_b)},{C1, FN(add_ix0_c)},{C1, FN(add_ix0_d)},{C1, FN(add_ix0_e)},{C1, FN(add_ix0_f)},
-/* 80 : 8301 */
- {C1, FN(add_ix1_0) },{C1, FN(add_ix1_1)},{C1, FN(add_ix1_2)},{C1, FN(add_ix1_3)},{C1, FN(add_ix1_4)},{C1, FN(add_ix1_5)},{C1, FN(add_ix1_6)},{C1, FN(add_ix1_7)},
- {C1, FN(add_ix1_8) },{C1, FN(add_ix1_9)},{C1, FN(add_ix1_a)},{C1, FN(add_ix1_b)},{C1, FN(add_ix1_c)},{C1, FN(add_ix1_d)},{C1, FN(add_ix1_e)},{C1, FN(add_ix1_f)},
- {C1, FN(add_ix2_0) },{C1, FN(add_ix2_1)},{C1, FN(add_ix2_2)},{C1, FN(add_ix2_3)},{C1, FN(add_ix2_4)},{C1, FN(add_ix2_5)},{C1, FN(add_ix2_6)},{C1, FN(add_ix2_7)},
- {C1, FN(add_ix2_8) },{C1, FN(add_ix2_9)},{C1, FN(add_ix2_a)},{C1, FN(add_ix2_b)},{C1, FN(add_ix2_c)},{C1, FN(add_ix2_d)},{C1, FN(add_ix2_e)},{C1, FN(add_ix2_f)},
-/* A0 : 8301 */
- {C1, FN(ld_base_0) },{C1, FN(ld_base_1)},{C1, FN(ld_base_2)},{C1, FN(ld_base_3)},{C1, FN(ld_base_4)},{C1, FN(ld_base_5)},{C1, FN(ld_base_6)},{C1, FN(ld_base_7)},
- {C1, FN(undefined) },{C1, FN(undefined)},{C1, FN(undefined)},{C1, FN(undefined)},{C1, FN(undefined)},{C1, FN(undefined)},{C1, FN(undefined)},{C1, FN(undefined)},
- {C1, FN(ld_bank_0) },{C1, FN(ld_bank_1)},{C1, FN(ld_bank_2)},{C1, FN(ld_bank_3)},{C2, FN(stop) },{C1, FN(undefined)},{C1, FN(undefined)},{C1, FN(undefined)},
- {C1, FN(undefined) },{C1, FN(undefined)},{C1, FN(undefined)},{C1, FN(undefined)},{C1, FN(undefined)},{C1, FN(undefined)},{C1, FN(undefined)},{C1, FN(undefined)},
-/* c0 : 8301 */
- {C2, FN(ld_ix0_n) },{C2, FN(ld_ix1_n)},{C2, FN(ld_ix2_n) },{C2, FN(ld_a_n) },{C2, FN(ld_lp0_n) },{C2, FN(ld_lp1_n) },{C2, FN(ld_lp2_n) },{C2, FN(ld_b_n) },
- {C2, FN(add_a_n) },{C2, FN(sub_a_n) },{C2, FN(and_a_n) },{C2, FN(or_a_n) },{C2, FN(djnz_lp0) },{C2, FN(djnz_lp1) },{C2, FN(djnz_lp2) },{C2, FN(jnz) },
- {C2, FN(jnc) },{C2, FN(jz) },{C2, FN(jmp) },{C2,FN(undefined2)},{C2, FN(op_d4) },{C2, FN(op_d5) },{C2, FN(op_d6) },{C2, FN(op_d7) },
- {C2, FN(ld_a_abs) },{C2, FN(ld_abs_a)},{C2,FN(cmp_a_n) },{C2,FN(xor_a_n) },{C2, FN(ld_a_r) },{C2, FN(ld_r_a) },{C2, FN(jc) },{C2, FN(call)},
-/* E0 : 8301 */
- {C1, FN(exg_a_ix0) },{C1, FN(exg_a_ix1)},{C1, FN(exg_a_ix2)},{C1, FN(exg_a_lp1)},{C1, FN(exg_a_lp2)},{C1, FN(exg_a_b) },{C1, FN(exg_a_lp0)},{C1, FN(exg_a_rb) },
- {C1, FN(ld_ix0_a) },{C1, FN(ld_ix1_a) },{C1, FN(ld_ix2_a) },{C1, FN(ld_lp1_a) },{C1, FN(ld_lp2_a) },{C1, FN(ld_b_a) },{C1, FN(ld_lp0_a) },{C1, FN(ld_rb_a) },
- {C1,FN(exg_ix0_ix1)},{C1,FN(exg_ix0_ix2)},{C1,FN(op_rep_ld_ix2_b)},{C1, FN(op_rep_ld_b_ix0)},{C1, FN(save_zc)},{C1, FN(rest_zc)},{C1, FN(ld_rxb_a) },{C1, FN(ld_a_rxb) },
- {C1, FN(cmp_a_rxb) },{C1, FN(xor_a_rxb)},{C1, FN(add_a_cf) },{C1, FN(sub_a_cf) },{C1, FN(tst_a) },{C1, FN(clr_a) },{C1, FN(ld_a_ix0_a)},{C1, FN(ret) }
-};
-
-
-/****************************************************************************
- * Initialize emulation
- ****************************************************************************/
-void alpha8201_cpu_device::device_start()
-{
- m_program = &space(AS_PROGRAM);
- m_cache = m_program->cache<0, 0, ENDIANNESS_LITTLE>();
-
- state_add( ALPHA8201_PC, "PC", m_pc.w.l ).callimport().mask(0x3ff).formatstr("%03X");
- state_add( ALPHA8201_SP, "SP", m_sp ).callimport().callexport().formatstr("%02X");
- state_add( ALPHA8201_RB, "RB", m_regPtr ).mask(0x7);
- state_add( ALPHA8201_MB, "MB", m_mb ).mask(0x3);
- state_add( ALPHA8201_IX0, "IX0", m_ix0.b.l );
- state_add( ALPHA8201_IX1, "IX1", m_ix1.b.l );
- state_add( ALPHA8201_IX2, "IX2", m_ix2.b.l );
- state_add( ALPHA8201_LP0, "LP0", m_lp0 );
- state_add( ALPHA8201_LP1, "LP1", m_lp1 );
- state_add( ALPHA8201_LP2, "LP2", m_lp2 );
- state_add( ALPHA8201_A, "A", m_A );
- state_add( ALPHA8201_B, "B", m_B );
- state_add( ALPHA8201_R0, "R0", m_R[0] ).callimport().callexport().formatstr("%02X");
- state_add( ALPHA8201_R1, "R1", m_R[1] ).callimport().callexport().formatstr("%02X");
- state_add( ALPHA8201_R2, "R2", m_R[2] ).callimport().callexport().formatstr("%02X");
- state_add( ALPHA8201_R3, "R3", m_R[3] ).callimport().callexport().formatstr("%02X");
- state_add( ALPHA8201_R4, "R4", m_R[4] ).callimport().callexport().formatstr("%02X");
- state_add( ALPHA8201_R5, "R5", m_R[5] ).callimport().callexport().formatstr("%02X");
- state_add( ALPHA8201_R6, "R6", m_R[6] ).callimport().callexport().formatstr("%02X");
- state_add( ALPHA8201_R7, "R7", m_R[7] ).callimport().callexport().formatstr("%02X");
- state_add( STATE_GENPCBASE, "CURPC", m_PREVPC ).callimport().noshow();
- state_add( STATE_GENFLAGS, "CURFLAGS", m_flags ).callimport().callexport().formatstr("%2s").noshow();
- state_add( STATE_GENSP, "CURSP", m_sp ).callimport().callexport();
-
- save_item(NAME(m_RAM));
- save_item(NAME(m_PREVPC));
- save_item(NAME(m_pc.w.l));
- save_item(NAME(m_regPtr));
- save_item(NAME(m_zf));
- save_item(NAME(m_cf));
- save_item(NAME(m_mb));
- save_item(NAME(m_halt));
- save_item(NAME(m_ix0.b.l));
- save_item(NAME(m_ix1.b.l));
- save_item(NAME(m_ix2.b.l));
- save_item(NAME(m_lp0));
- save_item(NAME(m_lp1));
- save_item(NAME(m_lp2));
- save_item(NAME(m_A));
- save_item(NAME(m_B));
- save_item(NAME(m_retptr));
- save_item(NAME(m_savec));
- save_item(NAME(m_savez));
-
- set_icountptr(m_icount);
-}
-
-
-//-------------------------------------------------
-// state_import - import state into the device,
-// after it has been set
-//-------------------------------------------------
-
-void alpha8201_cpu_device::state_import(const device_state_entry &entry)
-{
- switch (entry.index())
- {
- case ALPHA8201_PC:
- m_PREVPC = m_pc.w.l;
- break;
-
- case STATE_GENPCBASE:
- m_pc.w.l = m_PREVPC;
- break;
-
- case STATE_GENFLAGS:
- m_cf = BIT(m_flags, 1);
- m_zf = BIT(m_flags, 0);
- break;
-
- case ALPHA8201_SP:
- case STATE_GENSP:
- M_WRMEM(0x001, m_sp);
- break;
-
- case ALPHA8201_R0:
- WR_REG(0, m_R[0]);
- break;
-
- case ALPHA8201_R1:
- WR_REG(1, m_R[1]);
- break;
-
- case ALPHA8201_R2:
- WR_REG(2, m_R[2]);
- break;
-
- case ALPHA8201_R3:
- WR_REG(3, m_R[3]);
- break;
-
- case ALPHA8201_R4:
- WR_REG(4, m_R[4]);
- break;
-
- case ALPHA8201_R5:
- WR_REG(5, m_R[5]);
- break;
-
- case ALPHA8201_R6:
- WR_REG(6, m_R[6]);
- break;
-
- case ALPHA8201_R7:
- WR_REG(7, m_R[7]);
- break;
- }
-}
-
-
-//-------------------------------------------------
-// state_export - export state from the device,
-// to a known location where it can be read
-//-------------------------------------------------
-
-void alpha8201_cpu_device::state_export(const device_state_entry &entry)
-{
- switch (entry.index())
- {
- case STATE_GENFLAGS:
- m_flags = (m_cf << 1) | m_zf;
- break;
-
- case ALPHA8201_SP:
- case STATE_GENSP:
- m_sp = M_RDMEM(0x001);
- break;
-
- case ALPHA8201_R0:
- m_R[0] = RD_REG(0);
- break;
-
- case ALPHA8201_R1:
- m_R[1] = RD_REG(1);
- break;
-
- case ALPHA8201_R2:
- m_R[2] = RD_REG(2);
- break;
-
- case ALPHA8201_R3:
- m_R[3] = RD_REG(3);
- break;
-
- case ALPHA8201_R4:
- m_R[4] = RD_REG(4);
- break;
-
- case ALPHA8201_R5:
- m_R[5] = RD_REG(5);
- break;
-
- case ALPHA8201_R6:
- m_R[6] = RD_REG(6);
- break;
-
- case ALPHA8201_R7:
- m_R[7] = RD_REG(7);
- break;
- }
-}
-
-
-//-------------------------------------------------
-// state_string_export - export state as a string
-// for the debugger
-//-------------------------------------------------
-
-void alpha8201_cpu_device::state_string_export(const device_state_entry &entry, std::string &str) const
-{
- switch (entry.index())
- {
- case STATE_GENFLAGS:
- str = string_format("%c%c", m_cf ? 'C' : '.', m_zf ? 'Z' : '.');
- break;
- }
-}
-
-/****************************************************************************
- * Reset registers to their initial values
- ****************************************************************************/
-void alpha8201_cpu_device::device_reset()
-{
- m_pc.w.l = 0;
- m_regPtr = 0;
- m_zf = 0;
- m_cf = 0;
- m_mb = 0;
- m_ix0.w.l = 0;
- m_ix1.w.l = 0;
- m_ix2.w.l = 0;
- m_lp0 = 0;
- m_lp1 = 0;
- m_lp2 = 0;
- m_A = 0;
- m_B = 0;
- m_halt = 0;
-}
-
-
-/****************************************************************************
- * Execute cycles CPU cycles. Return number of cycles really executed
- ****************************************************************************/
-
-void alpha8201_cpu_device::execute_run()
-{
- unsigned opcode;
- u8 pcptr;
-
- if(m_halt)
- {
- m_icount = 0;
- return;
- }
-
- /* setup address bank & fall safe */
- m_ix0.b.h =
- m_ix1.b.h =
- m_ix2.b.h = (m_pc.b.h &= 3);
-
- /* reset start hack */
- if(m_pc.w.l<0x20)
- m_mb |= 0x08;
-
- do
- {
- if(m_mb & 0x08)
- {
- pcptr = M_RDMEM(0x001) & 0x1f; /* pointer of entry point */
- m_icount -= C1;
-
- /* entry point scan phase */
- if( (pcptr&1) == 0)
- {
- /* EVEN , get PC low */
- m_pc.b.l = M_RDMEM(pcptr);
-//osd_printf_debug("alpha8201 load PCL ENTRY=%02X PCL=%02X\n",pcptr, m_pc.b.l);
- m_icount -= C1;
- M_WRMEM(0x001,pcptr+1);
- continue;
- }
-
- /* ODD , check HALT flag */
- m_mb = M_RDMEM(pcptr) & (0x08|0x03);
- m_icount -= C1;
-
- /* not entryaddress 000,001 */
- if(pcptr<2) m_mb |= 0x08;
-
- if(m_mb & 0x08)
- {
- /* HALTED current entry point . next one */
- pcptr = (pcptr+1)&0x1f;
- M_WRMEM(0x001,pcptr);
- m_icount -= C1;
- continue;
- }
-
- /* goto run phase */
- M_JMP(m_pc.b.l);
-
-#if SHOW_ENTRY_POINT
-logerror("alpha8201 START ENTRY=%02X PC=%03X\n",pcptr,m_pc.w.l);
-osd_printf_debug("alpha8201 START ENTRY=%02X PC=%03X\n",pcptr,m_pc.w.l);
-#endif
- }
-
- /* run */
- m_PREVPC = m_pc.w.l;
- debugger_instruction_hook(m_pc.w.l);
- opcode =M_RDOP(m_pc.w.l);
-#if TRACE_PC
-osd_printf_debug("alpha8201: PC = %03x, opcode = %02x\n", m_pc.w.l, opcode);
-#endif
- m_pc.b.l++;
- m_inst_cycles = m_opmap[opcode].cycles;
- (this->*m_opmap[opcode].opcode_func)();
- m_icount -= m_inst_cycles;
- } while (m_icount>0);
-}
-
-
-/****************************************************************************
- * Set IRQ line state
- ****************************************************************************/
-void alpha8201_cpu_device::execute_set_input(int inputnum, int state)
-{
- if(inputnum == INPUT_LINE_HALT)
- {
- m_halt = (state==ASSERT_LINE) ? 1 : 0;
-/* osd_printf_debug("alpha8201 HALT %d\n",m_halt); */
- }
-}
-
-std::unique_ptr<util::disasm_interface> alpha8201_cpu_device::create_disassembler()
-{
- return std::make_unique<alpha8201_disassembler>();
-}
diff --git a/src/devices/cpu/alph8201/alph8201.h b/src/devices/cpu/alph8201/alph8201.h
deleted file mode 100644
index 46c00143f6b..00000000000
--- a/src/devices/cpu/alph8201/alph8201.h
+++ /dev/null
@@ -1,415 +0,0 @@
-// license:BSD-3-Clause
-// copyright-holders:Tatsuyuki Satoh
-/*
-
-Notice: The alpha 8201 is now emulated using mame/alpha8201.*
-
-cpu/alph8201/ will be removed when the alpha 8304 has been dumped.
-
-
-
-
-*/
-
- /**************************************************************************\
- * Alpha8201 Emulator *
- * *
- * Copyright Tatsuyuki Satoh *
- * Originally written for the MAME project. *
- * *
- * *
- \**************************************************************************/
-
-#ifndef MAME_CPU_ALPH8201_ALPH8201_H
-#define MAME_CPU_ALPH8201_ALPH8201_H
-
-#pragma once
-
-enum
-{
- ALPHA8201_PC = STATE_GENPC,
- ALPHA8201_SP = 0,
- ALPHA8201_RB,
- ALPHA8201_MB,
-//
- ALPHA8201_IX0,
- ALPHA8201_IX1,
- ALPHA8201_IX2,
- ALPHA8201_LP0,
- ALPHA8201_LP1,
- ALPHA8201_LP2,
- ALPHA8201_A,
- ALPHA8201_B,
-//
- ALPHA8201_R0,ALPHA8201_R1,ALPHA8201_R2,ALPHA8201_R3,
- ALPHA8201_R4,ALPHA8201_R5,ALPHA8201_R6,ALPHA8201_R7
-};
-
-
-class alpha8201_cpu_device : public cpu_device
-{
-public:
- // construction/destruction
- alpha8201_cpu_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock);
-
-protected:
- typedef void ( alpha8201_cpu_device::*opcode_fun ) ();
-
- /* The opcode table now is a combination of cycle counts and function pointers */
- struct s_opcode {
- unsigned cycles;
- opcode_fun opcode_func;
- };
-
- alpha8201_cpu_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, u32 clock, const s_opcode *opmap);
-
- // device-level overrides
- virtual void device_start() override;
- virtual void device_reset() override;
-
- // device_execute_interface overrides
- virtual u32 execute_min_cycles() const override { return 1; }
- virtual u32 execute_max_cycles() const override { return 16; }
- virtual u32 execute_input_lines() const override { return 1; }
- virtual void execute_run() override;
- virtual void execute_set_input(int inputnum, int state) override;
-
- // device_memory_interface overrides
- virtual space_config_vector memory_space_config() const override;
-
- // device_state_interface overrides
- virtual void state_import(const device_state_entry &entry) override;
- virtual void state_export(const device_state_entry &entry) override;
- virtual void state_string_export(const device_state_entry &entry, std::string &str) const override;
-
- // device_disasm_interface overrides
- virtual std::unique_ptr<util::disasm_interface> create_disassembler() override;
-
- u8 M_RDMEM(u16 A) { return m_program->read_byte(A); }
- void M_WRMEM(u16 A, u8 V) { m_program->write_byte(A, V); }
- u8 M_RDOP(u16 A) { return m_cache->read_byte(A); }
- u8 M_RDOP_ARG(u16 A) { return m_cache->read_byte(A); }
- u8 RD_REG(u8 x) { return m_RAM[(m_regPtr<<3)+(x)]; }
- void WR_REG(u8 x, u8 d) { m_RAM[(m_regPtr<<3)+(x)]=(d); }
-
- unsigned M_RDMEM_OPCODE();
- void M_ADD(u8 dat);
- void M_ADDB(u8 dat);
- void M_SUB(u8 dat);
- void M_AND(u8 dat);
- void M_OR(u8 dat);
- void M_XOR(u8 dat);
- void M_JMP(u8 dat);
- void M_UNDEFINED();
- void M_UNDEFINED2();
-
- void undefined() { M_UNDEFINED(); }
- void undefined2() { M_UNDEFINED2(); }
-
- void nop() { }
- void rora() { m_cf = m_A &1; m_A = (m_A>>1) | (m_A<<7); }
- void rola() { m_cf = (m_A>>7)&1; m_A = (m_A<<1) | (m_A>>7); }
- void inc_b() { M_ADDB(0x02); }
- void dec_b() { M_ADDB(0xfe); }
- void inc_a() { M_ADD(0x01); }
- void dec_a() { M_ADD(0xff); }
- void cpl() { m_A ^= 0xff; };
-
- void ld_a_ix0_0() { m_A = M_RDMEM(m_ix0.w.l+0); }
- void ld_a_ix0_1() { m_A = M_RDMEM(m_ix0.w.l+1); }
- void ld_a_ix0_2() { m_A = M_RDMEM(m_ix0.w.l+2); }
- void ld_a_ix0_3() { m_A = M_RDMEM(m_ix0.w.l+3); }
- void ld_a_ix0_4() { m_A = M_RDMEM(m_ix0.w.l+4); }
- void ld_a_ix0_5() { m_A = M_RDMEM(m_ix0.w.l+5); }
- void ld_a_ix0_6() { m_A = M_RDMEM(m_ix0.w.l+6); }
- void ld_a_ix0_7() { m_A = M_RDMEM(m_ix0.w.l+7); }
-
- void ld_a_ix1_0() { m_A = M_RDMEM(m_ix1.w.l+0); }
- void ld_a_ix1_1() { m_A = M_RDMEM(m_ix1.w.l+1); }
- void ld_a_ix1_2() { m_A = M_RDMEM(m_ix1.w.l+2); }
- void ld_a_ix1_3() { m_A = M_RDMEM(m_ix1.w.l+3); }
- void ld_a_ix1_4() { m_A = M_RDMEM(m_ix1.w.l+4); }
- void ld_a_ix1_5() { m_A = M_RDMEM(m_ix1.w.l+5); }
- void ld_a_ix1_6() { m_A = M_RDMEM(m_ix1.w.l+6); }
- void ld_a_ix1_7() { m_A = M_RDMEM(m_ix1.w.l+7); }
-
- void ld_ix2_0_a() { M_WRMEM(m_ix2.w.l+0,m_A); }
- void ld_ix2_1_a() { M_WRMEM(m_ix2.w.l+1,m_A); }
- void ld_ix2_2_a() { M_WRMEM(m_ix2.w.l+2,m_A); }
- void ld_ix2_3_a() { M_WRMEM(m_ix2.w.l+3,m_A); }
- void ld_ix2_4_a() { M_WRMEM(m_ix2.w.l+4,m_A); }
- void ld_ix2_5_a() { M_WRMEM(m_ix2.w.l+5,m_A); }
- void ld_ix2_6_a() { M_WRMEM(m_ix2.w.l+6,m_A); }
- void ld_ix2_7_a() { M_WRMEM(m_ix2.w.l+7,m_A); }
-
- void ld_ix0_0_b() { m_RAM[(m_B>>1)&0x3f] = M_RDMEM(m_ix0.w.l+0); }
- void ld_ix0_1_b() { m_RAM[(m_B>>1)&0x3f] = M_RDMEM(m_ix0.w.l+1); }
- void ld_ix0_2_b() { m_RAM[(m_B>>1)&0x3f] = M_RDMEM(m_ix0.w.l+2); }
- void ld_ix0_3_b() { m_RAM[(m_B>>1)&0x3f] = M_RDMEM(m_ix0.w.l+3); }
- void ld_ix0_4_b() { m_RAM[(m_B>>1)&0x3f] = M_RDMEM(m_ix0.w.l+4); }
- void ld_ix0_5_b() { m_RAM[(m_B>>1)&0x3f] = M_RDMEM(m_ix0.w.l+5); }
- void ld_ix0_6_b() { m_RAM[(m_B>>1)&0x3f] = M_RDMEM(m_ix0.w.l+6); }
- void ld_ix0_7_b() { m_RAM[(m_B>>1)&0x3f] = M_RDMEM(m_ix0.w.l+7); }
-
- void bit_r0_0() { m_zf = RD_REG(0)&(1<<0)?0:1; }
- void bit_r0_1() { m_zf = RD_REG(0)&(1<<1)?0:1; }
- void bit_r0_2() { m_zf = RD_REG(0)&(1<<2)?0:1; }
- void bit_r0_3() { m_zf = RD_REG(0)&(1<<3)?0:1; }
- void bit_r0_4() { m_zf = RD_REG(0)&(1<<4)?0:1; }
- void bit_r0_5() { m_zf = RD_REG(0)&(1<<5)?0:1; }
- void bit_r0_6() { m_zf = RD_REG(0)&(1<<6)?0:1; }
- void bit_r0_7() { m_zf = RD_REG(0)&(1<<7)?0:1; }
-
- void ld_a_n() { m_A = M_RDMEM_OPCODE(); }
-
- void ld_a_r0() { m_A = RD_REG(0); m_zf = (m_A==0); }
- void ld_a_r1() { m_A = RD_REG(1); m_zf = (m_A==0); }
- void ld_a_r2() { m_A = RD_REG(2); m_zf = (m_A==0); }
- void ld_a_r3() { m_A = RD_REG(3); m_zf = (m_A==0); }
- void ld_a_r4() { m_A = RD_REG(4); m_zf = (m_A==0); }
- void ld_a_r5() { m_A = RD_REG(5); m_zf = (m_A==0); }
- void ld_a_r6() { m_A = RD_REG(6); m_zf = (m_A==0); }
- void ld_a_r7() { m_A = RD_REG(7); m_zf = (m_A==0); }
-
- void ld_r0_a() { WR_REG(0,m_A); }
- void ld_r1_a() { WR_REG(1,m_A); }
- void ld_r2_a() { WR_REG(2,m_A); }
- void ld_r3_a() { WR_REG(3,m_A); }
- void ld_r4_a() { WR_REG(4,m_A); }
- void ld_r5_a() { WR_REG(5,m_A); }
- void ld_r6_a() { WR_REG(6,m_A); }
- void ld_r7_a() { WR_REG(7,m_A); }
-
- void add_a_n() { M_ADD(M_RDMEM_OPCODE()); }
-
- void add_a_r0() { M_ADD(RD_REG(0)); }
- void add_a_r1() { M_ADD(RD_REG(1)); }
- void add_a_r2() { M_ADD(RD_REG(2)); }
- void add_a_r3() { M_ADD(RD_REG(3)); }
- void add_a_r4() { M_ADD(RD_REG(4)); }
- void add_a_r5() { M_ADD(RD_REG(5)); }
- void add_a_r6() { M_ADD(RD_REG(6)); }
- void add_a_r7() { M_ADD(RD_REG(7)); }
-
- void sub_a_n() { M_SUB(M_RDMEM_OPCODE()); }
-
- void sub_a_r0() { M_SUB(RD_REG(0)); }
- void sub_a_r1() { M_SUB(RD_REG(1)); }
- void sub_a_r2() { M_SUB(RD_REG(2)); }
- void sub_a_r3() { M_SUB(RD_REG(3)); }
- void sub_a_r4() { M_SUB(RD_REG(4)); }
- void sub_a_r5() { M_SUB(RD_REG(5)); }
- void sub_a_r6() { M_SUB(RD_REG(6)); }
- void sub_a_r7() { M_SUB(RD_REG(7)); }
-
- void and_a_n() { M_AND(M_RDMEM_OPCODE()); }
-
- void and_a_r0() { M_AND(RD_REG(0)); }
- void and_a_r1() { M_AND(RD_REG(1)); }
- void and_a_r2() { M_AND(RD_REG(2)); }
- void and_a_r3() { M_AND(RD_REG(3)); }
- void and_a_r4() { M_AND(RD_REG(4)); }
- void and_a_r5() { M_AND(RD_REG(5)); }
- void and_a_r6() { M_AND(RD_REG(6)); }
- void and_a_r7() { M_AND(RD_REG(7)); }
-
- void or_a_n() { M_OR(M_RDMEM_OPCODE()); }
-
- void or_a_r0() { M_OR(RD_REG(0)); }
- void or_a_r1() { M_OR(RD_REG(1)); }
- void or_a_r2() { M_OR(RD_REG(2)); }
- void or_a_r3() { M_OR(RD_REG(3)); }
- void or_a_r4() { M_OR(RD_REG(4)); }
- void or_a_r5() { M_OR(RD_REG(5)); }
- void or_a_r6() { M_OR(RD_REG(6)); }
- void or_a_r7() { M_OR(RD_REG(7)); }
-
- void add_ix0_0() { }
- void add_ix0_1() { m_ix0.b.l += 1; }
- void add_ix0_2() { m_ix0.b.l += 2; }
- void add_ix0_3() { m_ix0.b.l += 3; }
- void add_ix0_4() { m_ix0.b.l += 4; }
- void add_ix0_5() { m_ix0.b.l += 5; }
- void add_ix0_6() { m_ix0.b.l += 6; }
- void add_ix0_7() { m_ix0.b.l += 7; }
- void add_ix0_8() { m_ix0.b.l += 8; }
- void add_ix0_9() { m_ix0.b.l += 9; }
- void add_ix0_a() { m_ix0.b.l += 10; }
- void add_ix0_b() { m_ix0.b.l += 11; }
- void add_ix0_c() { m_ix0.b.l += 12; }
- void add_ix0_d() { m_ix0.b.l += 13; }
- void add_ix0_e() { m_ix0.b.l += 14; }
- void add_ix0_f() { m_ix0.b.l += 15; }
-
- void add_ix1_0() { }
- void add_ix1_1() { m_ix1.b.l += 1; }
- void add_ix1_2() { m_ix1.b.l += 2; }
- void add_ix1_3() { m_ix1.b.l += 3; }
- void add_ix1_4() { m_ix1.b.l += 4; }
- void add_ix1_5() { m_ix1.b.l += 5; }
- void add_ix1_6() { m_ix1.b.l += 6; }
- void add_ix1_7() { m_ix1.b.l += 7; }
- void add_ix1_8() { m_ix1.b.l += 8; }
- void add_ix1_9() { m_ix1.b.l += 9; }
- void add_ix1_a() { m_ix1.b.l += 10; }
- void add_ix1_b() { m_ix1.b.l += 11; }
- void add_ix1_c() { m_ix1.b.l += 12; }
- void add_ix1_d() { m_ix1.b.l += 13; }
- void add_ix1_e() { m_ix1.b.l += 14; }
- void add_ix1_f() { m_ix1.b.l += 15; }
-
- void add_ix2_0() { }
- void add_ix2_1() { m_ix2.b.l += 1; }
- void add_ix2_2() { m_ix2.b.l += 2; }
- void add_ix2_3() { m_ix2.b.l += 3; }
- void add_ix2_4() { m_ix2.b.l += 4; }
- void add_ix2_5() { m_ix2.b.l += 5; }
- void add_ix2_6() { m_ix2.b.l += 6; }
- void add_ix2_7() { m_ix2.b.l += 7; }
- void add_ix2_8() { m_ix2.b.l += 8; }
- void add_ix2_9() { m_ix2.b.l += 9; }
- void add_ix2_a() { m_ix2.b.l += 10; }
- void add_ix2_b() { m_ix2.b.l += 11; }
- void add_ix2_c() { m_ix2.b.l += 12; }
- void add_ix2_d() { m_ix2.b.l += 13; }
- void add_ix2_e() { m_ix2.b.l += 14; }
- void add_ix2_f() { m_ix2.b.l += 15; }
-
- void ld_base_0() { m_regPtr = 0; }
- void ld_base_1() { m_regPtr = 1; }
- void ld_base_2() { m_regPtr = 2; }
- void ld_base_3() { m_regPtr = 3; }
- void ld_base_4() { m_regPtr = 4; }
- void ld_base_5() { m_regPtr = 5; }
- void ld_base_6() { m_regPtr = 6; }
- void ld_base_7() { m_regPtr = 7; }
-
- void ld_bank_0() { m_mb = 0; }
- void ld_bank_1() { m_mb = 1; }
- void ld_bank_2() { m_mb = 2; }
- void ld_bank_3() { m_mb = 3; }
-
- void ld_ix0_n() { m_ix0.b.l = M_RDMEM_OPCODE(); }
- void ld_ix1_n() { m_ix1.b.l = M_RDMEM_OPCODE(); }
- void ld_ix2_n() { m_ix2.b.l = M_RDMEM_OPCODE(); }
- void ld_lp0_n() { m_lp0 = M_RDMEM_OPCODE(); }
- void ld_lp1_n() { m_lp1 = M_RDMEM_OPCODE(); }
- void ld_lp2_n() { m_lp2 = M_RDMEM_OPCODE(); }
- void ld_b_n() { m_B = M_RDMEM_OPCODE(); }
-
- void djnz_lp0() { u8 i=M_RDMEM_OPCODE(); m_lp0--; if (m_lp0 != 0) M_JMP(i); }
- void djnz_lp1() { u8 i=M_RDMEM_OPCODE(); m_lp1--; if (m_lp1 != 0) M_JMP(i); }
- void djnz_lp2() { u8 i=M_RDMEM_OPCODE(); m_lp2--; if (m_lp2 != 0) M_JMP(i); }
- void jnz() { u8 i=M_RDMEM_OPCODE(); if (!m_zf) M_JMP(i); }
- void jnc() { u8 i=M_RDMEM_OPCODE(); if (!m_cf) M_JMP(i);}
- void jz() { u8 i=M_RDMEM_OPCODE(); if ( m_zf) M_JMP(i); }
- void jc() { u8 i=M_RDMEM_OPCODE(); if ( m_cf) M_JMP(i);}
- void jmp() { M_JMP(M_RDMEM_OPCODE() ); }
-
- void stop();
-
- /* ALPHA 8301 : added instruction */
- void exg_a_ix0() { u8 t=m_A; m_A = m_ix0.b.l; m_ix0.b.l = t; }
- void exg_a_ix1() { u8 t=m_A; m_A = m_ix1.b.l; m_ix1.b.l = t; }
- void exg_a_ix2() { u8 t=m_A; m_A = m_ix2.b.l; m_ix2.b.l = t; }
- void exg_a_lp0() { u8 t=m_A; m_A = m_lp0; m_lp0 = t; }
- void exg_a_lp1() { u8 t=m_A; m_A = m_lp1; m_lp1 = t; }
- void exg_a_lp2() { u8 t=m_A; m_A = m_lp2; m_lp2 = t; }
- void exg_a_b() { u8 t=m_A; m_A = m_B; m_B = t; }
- void exg_a_rb() { u8 t=m_A; m_A = m_regPtr; m_regPtr = t; }
-
- void ld_ix0_a() { m_ix0.b.l = m_A; }
- void ld_ix1_a() { m_ix1.b.l = m_A; }
- void ld_ix2_a() { m_ix2.b.l = m_A; }
- void ld_lp0_a() { m_lp0 = m_A; }
- void ld_lp1_a() { m_lp1 = m_A; }
- void ld_lp2_a() { m_lp2 = m_A; }
- void ld_b_a() { m_B = m_A; }
- void ld_rb_a() { m_regPtr = m_A; }
-
- void exg_ix0_ix1() { u8 t=m_ix1.b.l; m_ix1.b.l = m_ix0.b.l; m_ix0.b.l = t; }
- void exg_ix0_ix2() { u8 t=m_ix2.b.l; m_ix2.b.l = m_ix0.b.l; m_ix0.b.l = t; }
-
- void op_d4() { m_A = M_RDMEM( ((m_RAM[(7<<3)+7] & 3) << 8) | M_RDMEM_OPCODE() ); }
- void op_d5() { M_WRMEM( ((m_RAM[(7<<3)+7] & 3) << 8) | M_RDMEM_OPCODE(), m_A ); }
- void op_d6() { m_lp0 = M_RDMEM( ((m_RAM[(7<<3)+7] & 3) << 8) | M_RDMEM_OPCODE() ); }
- void op_d7() { M_WRMEM( ((m_RAM[(7<<3)+7] & 3) << 8) | M_RDMEM_OPCODE(), m_lp0 ); }
-
- void ld_a_abs() { m_A = M_RDMEM( ((m_mb & 3) << 8) | M_RDMEM_OPCODE() ); }
- void ld_abs_a() { M_WRMEM( ((m_mb & 3) << 8) | M_RDMEM_OPCODE(), m_A ); }
-
- void ld_a_r() { m_A = m_RAM[(M_RDMEM_OPCODE()>>1)&0x3f]; }
- void ld_r_a() { m_RAM[(M_RDMEM_OPCODE()>>1)&0x3f] = m_A; }
- void op_rep_ld_ix2_b() { do { M_WRMEM(m_ix2.w.l, m_RAM[(m_B>>1)&0x3f]); m_ix2.b.l++; m_B+=2; m_lp0--; } while (m_lp0 != 0); }
- void op_rep_ld_b_ix0() { do { m_RAM[(m_B>>1)&0x3f] = M_RDMEM(m_ix0.w.l); m_ix0.b.l++; m_B+=2; m_lp0--; } while (m_lp0 != 0); }
- void ld_rxb_a() { m_RAM[(m_B>>1)&0x3f] = m_A; }
- void ld_a_rxb() { m_A = m_RAM[(m_B>>1)&0x3f]; }
- void cmp_a_rxb() { u8 i=m_RAM[(m_B>>1)&0x3f]; m_zf = (m_A==i); m_cf = (m_A>=i); }
- void xor_a_rxb() { M_XOR(m_RAM[(m_B>>1)&0x3f] ); }
-
- void add_a_cf() { if (m_cf) inc_a(); }
- void sub_a_cf() { if (m_cf) dec_a(); }
- void tst_a() { m_zf = (m_A==0); }
- void clr_a() { m_A = 0; m_zf = (m_A==0); }
- void cmp_a_n() { u8 i=M_RDMEM_OPCODE(); m_zf = (m_A==i); m_cf = (m_A>=i); }
- void xor_a_n() { M_XOR(M_RDMEM_OPCODE() ); }
- void call() { u8 i=M_RDMEM_OPCODE(); m_retptr.w.l = m_pc.w.l; M_JMP(i); };
- void ld_a_ix0_a() { m_A = M_RDMEM(m_ix0.w.l+m_A); }
- void ret() { m_mb = m_retptr.b.h; M_JMP( m_retptr.b.l ); };
- void save_zc() { m_savez = m_zf; m_savec = m_cf; };
- void rest_zc() { m_zf = m_savez; m_cf = m_savec; };
-
- static const s_opcode opcode_8201[256];
- static const s_opcode opcode_8301[256];
-
- address_space_config m_program_config;
- address_space_config m_io_config;
-
- u8 m_RAM[8*8]; /* internal GP register 8 * 8bank */
- unsigned m_PREVPC;
- PAIR m_retptr; /* for 8301, return address of CALL */
- PAIR m_pc; /* 2bit+8bit program counter */
- u8 m_regPtr; /* RB register base */
- u8 m_mb; /* MB memory bank reg. latch after Branch */
- u8 m_cf; /* C flag */
- u8 m_zf; /* Z flag */
- u8 m_savec; /* for 8301, save flags */
- u8 m_savez; /* for 8301, save flags */
-
- PAIR m_ix0; /* 8bit memory read index reg. */
- PAIR m_ix1; /* 8bitmemory read index reg. */
- PAIR m_ix2; /* 8bitmemory write index reg. */
- u8 m_lp0; /* 8bit loop reg. */
- u8 m_lp1; /* 8bit loop reg. */
- u8 m_lp2; /* 8bit loop reg. */
- u8 m_A; /* 8bit accumulator */
- u8 m_B; /* 8bit register */
-
- u8 m_halt; /* halt input line */
-
- address_space *m_program;
- memory_access_cache<0, 0, ENDIANNESS_LITTLE> *m_cache;
- int m_icount;
- int m_inst_cycles;
-
- const s_opcode *const m_opmap;
-
- // Used for import/export only
- u8 m_sp;
- u8 m_R[8];
- u8 m_flags;
-};
-
-
-class alpha8301_cpu_device : public alpha8201_cpu_device
-{
-public:
- // construction/destruction
- alpha8301_cpu_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock);
-};
-
-
-DECLARE_DEVICE_TYPE(ALPHA8201L, alpha8201_cpu_device)
-DECLARE_DEVICE_TYPE(ALPHA8301L, alpha8301_cpu_device)
-
-#endif // MAME_CPU_ALPH8201_ALPH8201_H
diff --git a/src/devices/cpu/alpha/alpha.cpp b/src/devices/cpu/alpha/alpha.cpp
index 9ebfc6dd09e..62752d5f590 100644
--- a/src/devices/cpu/alpha/alpha.cpp
+++ b/src/devices/cpu/alpha/alpha.cpp
@@ -26,11 +26,8 @@
#include "alpha.h"
#include "common.h"
-#include "debugger.h"
-
#include "softfloat3/source/include/softfloat.h"
-#define LOG_GENERAL (1U << 0)
#define LOG_EXCEPTION (1U << 1)
#define LOG_SYSCALLS (1U << 2)
@@ -61,7 +58,7 @@ alpha_device::alpha_device(const machine_config &mconfig, device_type type, cons
address_space_config("3", ENDIANNESS_LITTLE, 64, 32, 0)
}
, m_srom_oe_cb(*this)
- , m_srom_data_cb(*this)
+ , m_srom_data_cb(*this, 0)
, m_icount(0)
{
}
@@ -88,9 +85,6 @@ void alpha_device::device_start()
// floating point registers
for (unsigned i = 0; i < 32; i++)
state_add(i + 32, util::string_format("F%d", i).c_str(), m_f[i]);
-
- m_srom_oe_cb.resolve_safe();
- m_srom_data_cb.resolve_safe(0);
}
void alpha_device::device_reset()
@@ -147,8 +141,9 @@ device_memory_interface::space_config_vector alpha_device::memory_space_config()
};
}
-bool alpha_device::memory_translate(int spacenum, int intention, offs_t &address)
+bool alpha_device::memory_translate(int spacenum, int intention, offs_t &address, address_space *&target_space)
{
+ target_space = &space(spacenum);
u64 placeholder = s64(s32(address));
if (cpu_translate(placeholder, intention))
@@ -398,14 +393,14 @@ void alpha_device::cpu_execute(u32 const op)
// register variants
case 0x00: m_r[Rc(op)] = s64(s32(u32(m_r[Ra(op)]) * u32(m_r[Rb(op)]))); break; // mull
case 0x20: m_r[Rc(op)] = m_r[Ra(op)] * m_r[Rb(op)]; break; // mulq
- case 0x30: mulu_64x64(m_r[Ra(op)], m_r[Rb(op)], &m_r[Rc(op)]); break; // umulh
+ case 0x30: mulu_64x64(m_r[Ra(op)], m_r[Rb(op)], m_r[Rc(op)]); break; // umulh
case 0x40: m_r[Rc(op)] = s64(s32(u32(m_r[Ra(op)]) * u32(m_r[Rb(op)]))); break; // mull/v
case 0x60: m_r[Rc(op)] = m_r[Ra(op)] * m_r[Rb(op)]; break; // mulq/v
// immediate variants
case 0x80: m_r[Rc(op)] = s64(s32(u32(m_r[Ra(op)]) * u32(Im(op)))); break; // mull
case 0xa0: m_r[Rc(op)] = m_r[Ra(op)] * Im(op); break; // mulq
- case 0xb0: mulu_64x64(m_r[Ra(op)], Im(op), &m_r[Rc(op)]); break; // umulh
+ case 0xb0: mulu_64x64(m_r[Ra(op)], Im(op), m_r[Rc(op)]); break; // umulh
case 0xc0: m_r[Rc(op)] = s64(s32(u32(m_r[Ra(op)]) * u32(Im(op)))); break; // mull/v
case 0xe0: m_r[Rc(op)] = m_r[Ra(op)] * Im(op); break; // mulq/v
}
@@ -628,7 +623,7 @@ bool alpha_ev4_device::cpu_translate(u64 &address, int intention)
// trim virtual address to 43 bits
address &= 0x7ff'ffffffff;
- if (intention & TRANSLATE_FETCH)
+ if (intention == device_memory_interface::TR_FETCH)
{
// instruction superpage mapping
if ((m_ibx[IBX_ICCSR] & IBX_ICCSR_R_MAP) && !(m_ibx[IBX_PS] & IBX_PS_R_CM) && (address >> 41) == 2)
@@ -662,7 +657,7 @@ bool alpha_ev4_device::cpu_translate(u64 &address, int intention)
template <typename T, typename U> std::enable_if_t<std::is_convertible<U, std::function<void(T)>>::value, void> alpha_device::load(u64 address, U &&apply)
{
- cpu_translate(address, TRANSLATE_READ);
+ cpu_translate(address, device_memory_interface::TR_READ);
unsigned const s = (address >> 31) & 6;
@@ -677,7 +672,7 @@ template <typename T, typename U> std::enable_if_t<std::is_convertible<U, std::f
template <typename T, typename U> std::enable_if_t<std::is_convertible<U, std::function<void(address_space &, u64, T)>>::value, void> alpha_device::load_l(u64 address, U &&apply)
{
- cpu_translate(address, TRANSLATE_READ);
+ cpu_translate(address, device_memory_interface::TR_READ);
unsigned const s = (address >> 31) & 6;
@@ -690,7 +685,7 @@ template <typename T, typename U> std::enable_if_t<std::is_convertible<U, std::f
template <typename T, typename U> std::enable_if_t<std::is_convertible<U, T>::value, void> alpha_device::store(u64 address, U data, T mem_mask)
{
- cpu_translate(address, TRANSLATE_WRITE);
+ cpu_translate(address, device_memory_interface::TR_WRITE);
unsigned const s = (address >> 31) & 6;
@@ -705,7 +700,7 @@ template <typename T, typename U> std::enable_if_t<std::is_convertible<U, T>::va
void alpha_device::fetch(u64 address, std::function<void(u32)> &&apply)
{
- cpu_translate(address, TRANSLATE_FETCH);
+ cpu_translate(address, device_memory_interface::TR_FETCH);
apply(icache_fetch(address));
}
diff --git a/src/devices/cpu/alpha/alpha.h b/src/devices/cpu/alpha/alpha.h
index ac1f5e60e2f..60d0a83ca73 100644
--- a/src/devices/cpu/alpha/alpha.h
+++ b/src/devices/cpu/alpha/alpha.h
@@ -21,18 +21,18 @@ protected:
alpha_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;
+ virtual void device_start() override ATTR_COLD;
+ virtual void device_reset() override ATTR_COLD;
// device_execute_interface overrides
- virtual u32 execute_min_cycles() const override { return 1; }
- virtual u32 execute_max_cycles() const override { return 1; }
+ virtual u32 execute_min_cycles() const noexcept override { return 1; }
+ virtual u32 execute_max_cycles() const noexcept override { return 1; }
virtual void execute_run() override;
virtual void execute_set_input(int inputnum, int state) override;
// device_memory_interface overrides
virtual space_config_vector memory_space_config() const override;
- virtual bool memory_translate(int spacenum, int intention, offs_t &address) override;
+ virtual bool memory_translate(int spacenum, int intention, offs_t &address, address_space *&target_space) override;
// device_disasm_interface overrides
virtual std::unique_ptr<util::disasm_interface> create_disassembler() override;
@@ -80,11 +80,8 @@ public:
protected:
// device-level overrides
- virtual void device_start() override;
- virtual void device_reset() override;
-
- // device_execute_interface overrides
- virtual u32 execute_input_lines() const override { return 6; }
+ virtual void device_start() override ATTR_COLD;
+ virtual void device_reset() override ATTR_COLD;
virtual void cpu_execute(u32 const op) override;
virtual bool cpu_translate(u64 &address, int intention) override;
@@ -256,7 +253,7 @@ public:
dec_21064_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock);
protected:
- virtual void device_reset() override;
+ virtual void device_reset() override ATTR_COLD;
virtual u32 icache_fetch(u64 const address) override;
diff --git a/src/devices/cpu/alpha/alphad.cpp b/src/devices/cpu/alpha/alphad.cpp
index 4bd759e53c3..1608811cbd2 100644
--- a/src/devices/cpu/alpha/alphad.cpp
+++ b/src/devices/cpu/alpha/alphad.cpp
@@ -594,6 +594,7 @@ offs_t alpha_disassembler::disassemble(std::ostream &stream, offs_t pc, const da
default: UNKNOWN("intm*"); break;
}
+ break;
case 0x14: // ITFP* (integer to floating)
switch ((instruction >> 5) & 0x7ff)
{
@@ -1224,21 +1225,21 @@ offs_t alpha_disassembler::disassemble(std::ostream &stream, offs_t pc, const da
else
BRANCH_R("br", Ra(instruction), Disp_B(instruction)); // BR
break;
- case 0x31: BRANCH_F("fbeq", Ra(instruction), Disp_B(instruction)); break; // FBEQ
- case 0x32: BRANCH_F("fblt", Ra(instruction), Disp_B(instruction)); break; // FBLT
- case 0x33: BRANCH_F("fble", Ra(instruction), Disp_B(instruction)); break; // FBLE
- case 0x34: BRANCH_R("bsr", Ra(instruction), Disp_B(instruction)); break; // BSR
- case 0x35: BRANCH_F("fbne", Ra(instruction), Disp_B(instruction)); break; // FBNE
- case 0x36: BRANCH_F("fbge", Ra(instruction), Disp_B(instruction)); break; // FBGE
- case 0x37: BRANCH_F("fbgt", Ra(instruction), Disp_B(instruction)); break; // FBGT
- case 0x38: BRANCH_R("blbc", Ra(instruction), Disp_B(instruction)); break; // BLBC
- case 0x39: BRANCH_R("beq", Ra(instruction), Disp_B(instruction)); break; // BEQ
- case 0x3a: BRANCH_R("blt", Ra(instruction), Disp_B(instruction)); break; // BLT
- case 0x3b: BRANCH_R("ble", Ra(instruction), Disp_B(instruction)); break; // BLE
- case 0x3c: BRANCH_R("blbs", Ra(instruction), Disp_B(instruction)); break; // BLBS
- case 0x3d: BRANCH_R("bne", Ra(instruction), Disp_B(instruction)); break; // BNE
- case 0x3e: BRANCH_R("bge", Ra(instruction), Disp_B(instruction)); break; // BGE
- case 0x3f: BRANCH_R("bgt", Ra(instruction), Disp_B(instruction)); break; // BGT
+ case 0x31: BRANCH_F("fbeq", Ra(instruction), Disp_B(instruction)); flags |= STEP_COND; break; // FBEQ
+ case 0x32: BRANCH_F("fblt", Ra(instruction), Disp_B(instruction)); flags |= STEP_COND; break; // FBLT
+ case 0x33: BRANCH_F("fble", Ra(instruction), Disp_B(instruction)); flags |= STEP_COND; break; // FBLE
+ case 0x34: BRANCH_R("bsr", Ra(instruction), Disp_B(instruction)); flags |= STEP_OVER; break; // BSR
+ case 0x35: BRANCH_F("fbne", Ra(instruction), Disp_B(instruction)); flags |= STEP_COND; break; // FBNE
+ case 0x36: BRANCH_F("fbge", Ra(instruction), Disp_B(instruction)); flags |= STEP_COND; break; // FBGE
+ case 0x37: BRANCH_F("fbgt", Ra(instruction), Disp_B(instruction)); flags |= STEP_COND; break; // FBGT
+ case 0x38: BRANCH_R("blbc", Ra(instruction), Disp_B(instruction)); flags |= STEP_COND; break; // BLBC
+ case 0x39: BRANCH_R("beq", Ra(instruction), Disp_B(instruction)); flags |= STEP_COND; break; // BEQ
+ case 0x3a: BRANCH_R("blt", Ra(instruction), Disp_B(instruction)); flags |= STEP_COND; break; // BLT
+ case 0x3b: BRANCH_R("ble", Ra(instruction), Disp_B(instruction)); flags |= STEP_COND; break; // BLE
+ case 0x3c: BRANCH_R("blbs", Ra(instruction), Disp_B(instruction)); flags |= STEP_COND; break; // BLBS
+ case 0x3d: BRANCH_R("bne", Ra(instruction), Disp_B(instruction)); flags |= STEP_COND; break; // BNE
+ case 0x3e: BRANCH_R("bge", Ra(instruction), Disp_B(instruction)); flags |= STEP_COND; break; // BGE
+ case 0x3f: BRANCH_R("bgt", Ra(instruction), Disp_B(instruction)); flags |= STEP_COND; break; // BGT
}
return bytes | flags;
diff --git a/src/devices/cpu/alpha/alphad.h b/src/devices/cpu/alpha/alphad.h
index 3c3475e5730..6ee5404a382 100644
--- a/src/devices/cpu/alpha/alphad.h
+++ b/src/devices/cpu/alpha/alphad.h
@@ -20,10 +20,10 @@ public:
alpha_disassembler(alpha_disassembler::dasm_type type = TYPE_UNKNOWN)
: m_dasm_type(type)
{
- };
+ }
virtual ~alpha_disassembler() = default;
- virtual u32 opcode_alignment() const override { return 4; };
+ virtual u32 opcode_alignment() const override { return 4; }
virtual offs_t disassemble(std::ostream &stream, offs_t pc, const data_buffer &opcodes, const data_buffer &params) override;
private:
diff --git a/src/devices/cpu/alpha/common.h b/src/devices/cpu/alpha/common.h
index 0c9668f304a..61daeccdcbc 100644
--- a/src/devices/cpu/alpha/common.h
+++ b/src/devices/cpu/alpha/common.h
@@ -13,7 +13,7 @@
#define Im(x) (u64(u8(x >> 13))) // literal immediate field
#define Disp_M(x) (s64(s16(x))) // memory instruction 16-bit signed offset
-#define Disp_P(x) (s64(s16(x << 4)) >> 4) // hardware load/store 12-bit signed offset
-#define Disp_B(x) (s64(s32(x << 11)) >> 9) // branch instruction offset
+#define Disp_P(x) (s64(util::sext(x, 12))) // hardware load/store 12-bit signed offset
+#define Disp_B(x) (s64(util::sext(x << 2, 23))) // branch instruction offset
#endif // MAME_CPU_ALPHA_COMMON_H
diff --git a/src/devices/cpu/alto2/a2curt.h b/src/devices/cpu/alto2/a2curt.h
index cdfc6a22973..a09c790dbb2 100644
--- a/src/devices/cpu/alto2/a2curt.h
+++ b/src/devices/cpu/alto2/a2curt.h
@@ -8,8 +8,8 @@
#ifdef ALTO2_DEFINE_CONSTANTS
#else // ALTO2_DEFINE_CONSTANTS
-#ifndef _A2CURT_H_
-#define _A2CURT_H_
+#ifndef MAME_CPU_ALTO2_A2CURT_H
+#define MAME_CPU_ALTO2_A2CURT_H
//! F2 functions for cursor task
enum {
@@ -24,5 +24,5 @@ void activate_curt(); //!< curt_activate: called by th
void init_curt(int task = task_curt); //!< initialize cursor task
void exit_curt(); //!< deinitialize cursor task
void reset_curt(); //!< reset cursor task
-#endif // _A2CURT_H_
+#endif // MAME_CPU_A2CURT_H
#endif // ALTO2_DEFINE_CONSTANTS
diff --git a/src/devices/cpu/alto2/a2dht.h b/src/devices/cpu/alto2/a2dht.h
index 9ff7acc17f4..3d3bb305f76 100644
--- a/src/devices/cpu/alto2/a2dht.h
+++ b/src/devices/cpu/alto2/a2dht.h
@@ -8,8 +8,8 @@
#ifdef ALTO2_DEFINE_CONSTANTS
#else // ALTO2_DEFINE_CONSTANTS
-#ifndef _A2DHT_H_
-#define _A2DHT_H_
+#ifndef MAME_CPU_ALTO2_A2DHT_H
+#define MAME_CPU_ALTO2_A2DHT_H
//! F2 functions for display horizontal task
enum {
@@ -23,5 +23,5 @@ void activate_dht(); //!< called by the CPU when the
void init_dht(int task = task_dht); //!< initialize display horizontal task
void exit_dht(); //!< deinitialize display horizontal task
void reset_dht(); //!< reset the display horizontal task
-#endif // _A2DHT_H_
+#endif // MAME_CPU_ALTO2_A2DHT_H
#endif // ALTO2_DEFINE_CONSTANTS
diff --git a/src/devices/cpu/alto2/a2disk.cpp b/src/devices/cpu/alto2/a2disk.cpp
index fa9392695dc..0e031a0cd85 100644
--- a/src/devices/cpu/alto2/a2disk.cpp
+++ b/src/devices/cpu/alto2/a2disk.cpp
@@ -792,12 +792,10 @@ void alto2_cpu_device::kwd_timing(int bitclk, int datin, int block)
/**
* @brief timer callback to take away the SECLATE pulse (monoflop)
- * @param ptr some unused pointer
* @param arg contains the seclate value
*/
-void alto2_cpu_device::disk_seclate(void* ptr, int32_t arg)
+void alto2_cpu_device::disk_seclate(int32_t arg)
{
- (void)ptr;
LOG((this,LOG_DISK,2," SECLATE -> %d\n", arg));
m_dsk.seclate = arg;
m_dsk.seclate_timer->enable(false);
@@ -805,12 +803,10 @@ void alto2_cpu_device::disk_seclate(void* ptr, int32_t arg)
/**
* @brief timer callback to take away the OK TO RUN pulse (reset)
- * @param ptr some unused pointer
* @param arg contains the ok_to_run value
*/
-void alto2_cpu_device::disk_ok_to_run(void* ptr, int32_t arg)
+void alto2_cpu_device::disk_ok_to_run(int32_t arg)
{
- (void)ptr;
LOG((this,LOG_DISK,2," OK TO RUN -> %d\n", arg));
m_dsk.ok_to_run = arg;
m_dsk.ok_to_run_timer->enable(false);
@@ -833,12 +829,10 @@ void alto2_cpu_device::disk_ok_to_run(void* ptr, int32_t arg)
* flag 0 (SKINC, active low). If the seek would go beyond the last cylinder,
* the drive deasserts seek_incomplete, but does not assert the addx_acknowledge.
*
- * @param ptr some unused pointer
* @param arg contains the drive, cylinder, and restore flag
*/
-void alto2_cpu_device::disk_strobon(void* ptr, int32_t arg)
+void alto2_cpu_device::disk_strobon(int32_t arg)
{
- (void)ptr;
int unit = arg % 2;
int restore = (arg / 2) % 2;
int cylinder = arg / 4;
@@ -904,7 +898,7 @@ void alto2_cpu_device::disk_strobon(void* ptr, int32_t arg)
}
/** @brief timer callback to change the READY monoflop 31a */
-void alto2_cpu_device::disk_ready_mf31a(void* ptr, int32_t arg)
+void alto2_cpu_device::disk_ready_mf31a(int32_t arg)
{
diablo_hd_device* dhd = m_drive[m_dsk.drive];
m_dsk.ready_mf31a = arg & dhd->get_ready_0();
@@ -1005,7 +999,7 @@ void alto2_cpu_device::f1_late_strobe()
LOG((this,LOG_DISK,1," STROBE (SENDADR:1)\n"));
/* Set the STROBON flag and start the STROBON monoflop */
m_dsk.strobe = 1;
- disk_strobon(nullptr,
+ disk_strobon(
4 * GET_KADDR_CYLINDER(m_dsk.kaddr) +
2 * GET_KADDR_RESTORE(m_dsk.kaddr) +
m_dsk.drive);
@@ -1570,12 +1564,10 @@ void alto2_cpu_device::f2_late_strobon()
/**
* @brief update the disk controller with a new bitclk
*
- * @param id timer id
* @param arg bit number
*/
-void alto2_cpu_device::disk_bitclk(void* ptr, int32_t arg)
+void alto2_cpu_device::disk_bitclk(int32_t arg)
{
- (void)ptr;
diablo_hd_device* dhd = m_drive[m_dsk.drive];
int clk = arg & 1;
int bit;
@@ -1749,16 +1741,16 @@ void alto2_cpu_device::init_disk()
m_dsk.kcom = 066000;
- m_dsk.strobon_timer = machine().scheduler().timer_alloc(timer_expired_delegate(FUNC(alto2_cpu_device::disk_strobon),this));
+ m_dsk.strobon_timer = timer_alloc(FUNC(alto2_cpu_device::disk_strobon), this);
m_dsk.strobon_timer->reset();
- m_dsk.seclate_timer = machine().scheduler().timer_alloc(timer_expired_delegate(FUNC(alto2_cpu_device::disk_seclate),this));
+ m_dsk.seclate_timer = timer_alloc(FUNC(alto2_cpu_device::disk_seclate), this);
m_dsk.seclate_timer->reset();
- m_dsk.ok_to_run_timer = machine().scheduler().timer_alloc(timer_expired_delegate(FUNC(alto2_cpu_device::disk_ok_to_run),this));
+ m_dsk.ok_to_run_timer = timer_alloc(FUNC(alto2_cpu_device::disk_ok_to_run), this);
m_dsk.ok_to_run_timer->adjust(attotime::from_nsec(35 * ALTO2_UCYCLE / 1000), 1);
- m_dsk.ready_timer = machine().scheduler().timer_alloc(timer_expired_delegate(FUNC(alto2_cpu_device::disk_ready_mf31a),this));
+ m_dsk.ready_timer = timer_alloc(FUNC(alto2_cpu_device::disk_ready_mf31a), this);
m_dsk.ready_timer->reset();
m_dsk.bitclk_time[0] = static_cast<int>(attotime::from_nsec(300).as_attoseconds() / 1000000);
diff --git a/src/devices/cpu/alto2/a2disk.h b/src/devices/cpu/alto2/a2disk.h
index 19efa66d66f..167e336d4af 100644
--- a/src/devices/cpu/alto2/a2disk.h
+++ b/src/devices/cpu/alto2/a2disk.h
@@ -8,8 +8,8 @@
#ifdef ALTO2_DEFINE_CONSTANTS
#else // ALTO2_DEFINE_CONSTANTS
-#ifndef _A2DISK_H_
-#define _A2DISK_H_
+#ifndef MAME_CPU_ALTO2_A2DISK_H
+#define MAME_CPU_ALTO2_A2DISK_H
required_device_array<diablo_hd_device, 2> m_drive; //!< two diablo_hd_device drives
@@ -74,7 +74,7 @@ TIMER_CALLBACK_MEMBER( disk_seclate ); //!< timer callback to take away
TIMER_CALLBACK_MEMBER( disk_ok_to_run ); //!< timer callback to take away the OK TO RUN pulse (reset)
TIMER_CALLBACK_MEMBER( disk_strobon ); //!< timer callback to pulse the STROBE' signal to the drive
TIMER_CALLBACK_MEMBER( disk_ready_mf31a ); //!< timer callback to change the READY monoflop 31a
-void disk_bitclk(void *ptr, int arg); //!< function to update the disk controller with a new bitclk
+void disk_bitclk(int arg); //!< function to update the disk controller with a new bitclk
void disk_block(int task); //!< called if one of the disk tasks (task_kwd or task_ksec) blocks
void bs_early_read_kstat(); //!< bus source: bus driven by disk status register KSTAT
void bs_early_read_kdata(); //!< bus source: bus driven by disk data register KDATA input
@@ -95,5 +95,5 @@ void f2_late_strobon(); //!< f2_strobon late: branch on
void init_disk(); //!< initialize the disk controller
void exit_disk(); //!< deinitialize the disk controller
void reset_disk(); //!< reset the disk controller
-#endif // _A2DISK_H_
+#endif // MAME_CPU_ALTO2_A2DISK_H
#endif // ALTO2_DEFINE_CONSTANTS
diff --git a/src/devices/cpu/alto2/a2disp.cpp b/src/devices/cpu/alto2/a2disp.cpp
index ea850e6a82d..5cc9e5cc300 100644
--- a/src/devices/cpu/alto2/a2disp.cpp
+++ b/src/devices/cpu/alto2/a2disp.cpp
@@ -258,7 +258,7 @@ void alto2_cpu_device::update_framebuf_word(uint16_t* framebuf, int x, int y, ui
if (word == framebuf[x])
return;
framebuf[x] = word;
- draw_scanline8(*m_dsp.bitmap, x * 16, y, 16, m_dsp.patterns + 16 * word, nullptr);
+ draw_scanline8(*m_dsp.bitmap, x * 16, y, 16, &m_dsp.patterns[16 * word], nullptr);
}
/**
@@ -499,7 +499,7 @@ void alto2_cpu_device::f2_late_evenfield()
*/
void alto2_cpu_device::init_disp()
{
- memset(&m_dsp, 0, sizeof(m_dsp));
+ m_dsp = decltype(m_dsp)();
save_item(NAME(m_dsp.state));
save_item(NAME(m_dsp.hlc));
save_item(NAME(m_dsp.setmode));
@@ -517,16 +517,16 @@ void alto2_cpu_device::init_disp()
save_item(NAME(m_dsp.xpreg));
save_item(NAME(m_dsp.csr));
- m_disp_a38 = prom_load(machine(), &pl_displ_a38, memregion("displ_a38")->base());
- m_disp_a63 = prom_load(machine(), &pl_displ_a63, memregion("displ_a63")->base());
- m_disp_a66 = prom_load(machine(), &pl_displ_a66, memregion("displ_a66")->base());
+ m_disp_a38 = prom_load<uint8_t>(machine(), &pl_displ_a38, memregion("displ_a38")->base());
+ m_disp_a63 = prom_load<uint8_t>(machine(), &pl_displ_a63, memregion("displ_a63")->base());
+ m_disp_a66 = prom_load<uint8_t>(machine(), &pl_displ_a66, memregion("displ_a66")->base());
m_dsp.hlc = A2_DISP_HLC_START;
m_dsp.framebuf = std::make_unique<uint16_t[]>(A2_DISP_TOTAL_HEIGHT * A2_DISP_SCANLINE_WORDS);
- m_dsp.patterns = auto_alloc_array(machine(), uint8_t, 65536 * 16);
+ m_dsp.patterns = std::make_unique<uint8_t[]>(65536 * 16);
for (int y = 0; y < 65536; y++) {
- uint8_t* dst = m_dsp.patterns + y * 16;
+ uint8_t* dst = &m_dsp.patterns[y * 16];
for (int x = 0; x < 16; x++)
*dst++ = (~y >> (15 - x)) & 1;
}
diff --git a/src/devices/cpu/alto2/a2disp.h b/src/devices/cpu/alto2/a2disp.h
index c4d47047519..02c51435d5a 100644
--- a/src/devices/cpu/alto2/a2disp.h
+++ b/src/devices/cpu/alto2/a2disp.h
@@ -190,29 +190,29 @@
* </PRE>
*/
-#ifndef _A2DISP_H_
-#define _A2DISP_H_
+#ifndef MAME_CPU_ALTO2_A2DISP_H
+#define MAME_CPU_ALTO2_A2DISP_H
struct {
- uint32_t state; //!< current state of the display_state_machine()
- uint32_t hlc; //!< horizontal line counter
- uint32_t setmode; //!< value written by last SETMODE<-
- uint32_t inverse; //!< set to 0xffff if line is inverse, 0x0000 otherwise
- uint32_t scanline; //!< current scanline
- bool halfclock; //!< false for normal pixel clock, true for half pixel clock
- bool vblank; //!< true during vblank, false otherwise
- uint16_t fifo[A2_DISP_FIFO]; //!< display word fifo
- uint32_t wa; //!< fifo input pointer (write address; 4-bit)
- uint32_t ra; //!< fifo output pointer (read address; 4-bit)
- uint32_t a63; //!< most recent value read from the PROM a63
- uint32_t a66; //!< most recent value read from the PROM a66
- bool dht_blocks; //!< set true, if the DHT executed BLOCK
- bool dwt_blocks; //!< set true, if the DWT executed BLOCK
- bool curt_blocks; //!< set true, if the CURT executed BLOCK
- bool curt_wakeup; //!< set true, if CURT wakeups are generated
- uint32_t xpreg; //!< cursor cursor x position register (10-bit)
- uint32_t csr; //!< cursor shift register (16-bit)
- std::unique_ptr<uint16_t[]> framebuf; //!< array of words of the raw bitmap that is displayed
- uint8_t *patterns; //!< array of 65536 patterns (16 bytes) with 1 byte per pixel
+ uint32_t state = 0; //!< current state of the display_state_machine()
+ uint32_t hlc = 0; //!< horizontal line counter
+ uint32_t setmode = 0; //!< value written by last SETMODE<-
+ uint32_t inverse = 0; //!< set to 0xffff if line is inverse, 0x0000 otherwise
+ uint32_t scanline = 0; //!< current scanline
+ bool halfclock = false; //!< false for normal pixel clock, true for half pixel clock
+ bool vblank = false; //!< true during vblank, false otherwise
+ uint16_t fifo[A2_DISP_FIFO] = { }; //!< display word fifo
+ uint32_t wa = 0; //!< fifo input pointer (write address; 4-bit)
+ uint32_t ra = 0; //!< fifo output pointer (read address; 4-bit)
+ uint32_t a63 = 0; //!< most recent value read from the PROM a63
+ uint32_t a66 = 0; //!< most recent value read from the PROM a66
+ bool dht_blocks = false; //!< set true, if the DHT executed BLOCK
+ bool dwt_blocks = false; //!< set true, if the DWT executed BLOCK
+ bool curt_blocks = false; //!< set true, if the CURT executed BLOCK
+ bool curt_wakeup = false; //!< set true, if CURT wakeups are generated
+ uint32_t xpreg = 0; //!< cursor cursor x position register (10-bit)
+ uint32_t csr = 0; //!< cursor shift register (16-bit)
+ std::unique_ptr<uint16_t[]> framebuf; //!< array of words of the raw bitmap that is displayed
+ std::unique_ptr<uint8_t[]> patterns; //!< array of 65536 patterns (16 bytes) with 1 byte per pixel
std::unique_ptr<bitmap_ind16> bitmap; //!< MAME bitmap with 16 bit indices
} m_dsp;
@@ -238,7 +238,7 @@ struct {
* O3 (010) = MBEMPTY'
* </PRE>
*/
-uint8_t* m_disp_a38;
+std::unique_ptr<uint8_t[]> m_disp_a38;
//! output bits of PROM A38
enum {
@@ -273,7 +273,7 @@ enum {
* which happens to be very close to every 7th CPU microcycle.
* </PRE>
*/
-uint8_t* m_disp_a63;
+std::unique_ptr<uint8_t[]> m_disp_a63;
enum {
disp_a63_HBLANK = (1 << 0), //!< PROM a63 B0 is latched as HBLANK signal
@@ -293,7 +293,7 @@ enum {
* Address lines are driven by H[1] to H[128] of the horz. line counters.
* The PROM is enabled whenever H[256] and H[512] are both 0.
*/
-uint8_t* m_disp_a66;
+std::unique_ptr<uint8_t[]> m_disp_a66;
enum {
disp_a66_VSYNC_ODD = (1 << 0), //!< Q1 (001) is VSYNC for the odd field (with H1024=1)
@@ -312,5 +312,5 @@ void init_disp(); //!< initialize the display context
void exit_disp(); //!< deinitialize the display context
void reset_disp(); //!< reset the display context
-#endif // _A2DISP_H_
+#endif // MAME_CPU_ALTO2_A2DISP_H
#endif // ALTO2_DEFINE_CONSTANTS
diff --git a/src/devices/cpu/alto2/a2dvt.h b/src/devices/cpu/alto2/a2dvt.h
index 0d9430b1731..8b3cbbb587b 100644
--- a/src/devices/cpu/alto2/a2dvt.h
+++ b/src/devices/cpu/alto2/a2dvt.h
@@ -8,8 +8,8 @@
#ifdef ALTO2_DEFINE_CONSTANTS
#else // ALTO2_DEFINE_CONSTANTS
-#ifndef _A2DVT_H_
-#define _A2DVT_H_
+#ifndef MAME_CPU_ALTO2_A2DVT_H
+#define MAME_CPU_ALTO2_A2DVT_H
//! F2 functions for display vertical task
enum {
@@ -30,5 +30,5 @@ void exit_dvt();
//! Reset the display vertical task.
void reset_dvt();
-#endif // _A2DVT_H_
+#endif // MAME_CPU_ALTO2_A2DVT_H
#endif // ALTO2_DEFINE_CONSTANTS
diff --git a/src/devices/cpu/alto2/a2dwt.h b/src/devices/cpu/alto2/a2dwt.h
index 788af460369..896f627f3e3 100644
--- a/src/devices/cpu/alto2/a2dwt.h
+++ b/src/devices/cpu/alto2/a2dwt.h
@@ -8,8 +8,8 @@
#ifdef ALTO2_DEFINE_CONSTANTS
#else // ALTO2_DEFINE_CONSTANTS
-#ifndef _A2DWT_H_
-#define _A2DWT_H_
+#ifndef MAME_CPU_ALTO2_A2DWT_H
+#define MAME_CPU_ALTO2_A2DWT_H
//! F2 functions for display word task
enum {
@@ -21,5 +21,5 @@ void f2_late_load_ddr(); //!< F2 func: load the display d
void init_dwt(int task = task_dwt); //!< initialize the display word task
void exit_dwt(); //!< deinitialize the display word task
void reset_dwt(); //!< reset the display word task
-#endif // _A2DWT_H_
+#endif // MAME_CPU_ALTO2_A2DWT_H
#endif // ALTO2_DEFINE_CONSTANTS
diff --git a/src/devices/cpu/alto2/a2emu.cpp b/src/devices/cpu/alto2/a2emu.cpp
index a7ea40a6aca..7b815f44e56 100644
--- a/src/devices/cpu/alto2/a2emu.cpp
+++ b/src/devices/cpu/alto2/a2emu.cpp
@@ -267,13 +267,13 @@ void alto2_cpu_device::f1_early_emu_block()
CPU_CLR_TASK_WAKEUP(m_task);
LOG((this,LOG_EMU,2, " BLOCK %02o:%s\n", m_task, task_name(m_task)));
#elif 0
- fatal(1, "Emulator task want's to BLOCK.\n" \
- "%s-%04o: r:%02o af:%02o bs:%02o f1:%02o f2:%02o" \
- " t:%o l:%o next:%05o next2:%05o cycle:%lld\n",
- task_name(m_task), m_mpc,
- m_rsel, m_daluf, m_dbs, m_df1, mdf2,
- m_dloadt, m_dloatl, m_next, m_next2,
- ntime() / CPU_MICROCYCLE_TIME);
+ throw emu_fatalerror(1, "Emulator task want's to BLOCK.\n"
+ "%s-%04o: r:%02o af:%02o bs:%02o f1:%02o f2:%02o"
+ " t:%o l:%o next:%05o next2:%05o cycle:%lld\n",
+ task_name(m_task), m_mpc,
+ m_rsel, m_daluf, m_dbs, m_df1, mdf2,
+ m_dloadt, m_dloatl, m_next, m_next2,
+ ntime() / CPU_MICROCYCLE_TIME);
#else
/* just ignore (?) */
#endif
diff --git a/src/devices/cpu/alto2/a2emu.h b/src/devices/cpu/alto2/a2emu.h
index 5fd012b6196..03e681b5039 100644
--- a/src/devices/cpu/alto2/a2emu.h
+++ b/src/devices/cpu/alto2/a2emu.h
@@ -8,8 +8,8 @@
#ifdef ALTO2_DEFINE_CONSTANTS
#else // ALTO2_DEFINE_CONSTANTS
-#ifndef _A2EMU_H_
-#define _A2EMU_H_
+#ifndef MAME_CPU_ALTO2_A2EMU_H
+#define MAME_CPU_ALTO2_A2EMU_H
//! BUS source for emulator task
enum {
@@ -65,5 +65,5 @@ void f2_late_acsource(); //!< F2 func: branch on arithmet
void init_emu(int task = task_emu); //!< initialize the emulator task
void exit_emu(); //!< deinitialize the emulator task
void reset_emu(); //!< reset the emulator task
-#endif // _A2EMU_H_
+#endif // MAME_CPU_ALTO2_A2EMU_H
#endif // ALTO2_DEFINE_CONSTANTS
diff --git a/src/devices/cpu/alto2/a2ether.cpp b/src/devices/cpu/alto2/a2ether.cpp
index 2c1a3d56a89..4bdd9b649a5 100644
--- a/src/devices/cpu/alto2/a2ether.cpp
+++ b/src/devices/cpu/alto2/a2ether.cpp
@@ -483,7 +483,7 @@ uint32_t f9401_7(uint32_t crc, uint32_t data)
* This is probably lacking the updates to one or more of
* the status flip flops.
*/
-void alto2_cpu_device::rx_breath_of_life(void* ptr, int32_t arg)
+void alto2_cpu_device::rx_breath_of_life(int32_t arg)
{
uint32_t data;
@@ -533,7 +533,7 @@ void alto2_cpu_device::rx_breath_of_life(void* ptr, int32_t arg)
* @param ptr unused pointer
* @param arg word count if >= 0, -1 if CRC is to be transmitted (last word)
*/
-void alto2_cpu_device::tx_packet(void* ptr, int32_t arg)
+void alto2_cpu_device::tx_packet(int32_t arg)
{
uint32_t data;
@@ -1307,7 +1307,7 @@ void alto2_cpu_device::update_tclk(int tclk)
void alto2_cpu_device::init_ether(int task)
{
// intialize all ethernet variables
- memset(&m_eth, 0, sizeof(m_eth));
+ m_eth = decltype(m_eth)();
save_item(NAME(m_eth.fifo));
save_item(NAME(m_eth.fifo_rd));
save_item(NAME(m_eth.fifo_wr));
@@ -1318,17 +1318,17 @@ void alto2_cpu_device::init_ether(int task)
save_item(NAME(m_eth.tx_count));
save_item(NAME(m_eth.breath_of_life));
- m_ether_a41 = prom_load(machine(), &pl_enet_a41, memregion("ether_a41")->base());
- m_ether_a42 = prom_load(machine(), &pl_enet_a42, memregion("ether_a42")->base());
- m_ether_a49 = prom_load(machine(), &pl_enet_a49, memregion("ether_a49")->base());
+ m_ether_a41 = prom_load<uint8_t>(machine(), &pl_enet_a41, memregion("ether_a41")->base());
+ m_ether_a42 = prom_load<uint8_t>(machine(), &pl_enet_a42, memregion("ether_a42")->base());
+ m_ether_a49 = prom_load<uint8_t>(machine(), &pl_enet_a49, memregion("ether_a49")->base());
m_eth.rx_packet = std::make_unique<uint16_t[]>(sizeof(uint16_t)*ALTO2_ETHER_PACKET_SIZE);
m_eth.tx_packet = std::make_unique<uint16_t[]>(sizeof(uint16_t)*ALTO2_ETHER_PACKET_SIZE);
- m_eth.tx_timer = machine().scheduler().timer_alloc(timer_expired_delegate(FUNC(alto2_cpu_device::tx_packet),this));
+ m_eth.tx_timer = timer_alloc(FUNC(alto2_cpu_device::tx_packet), this);
m_eth.tx_timer->reset();
- m_eth.rx_timer = machine().scheduler().timer_alloc(timer_expired_delegate(FUNC(alto2_cpu_device::rx_breath_of_life),this));
+ m_eth.rx_timer = timer_alloc(FUNC(alto2_cpu_device::rx_breath_of_life), this);
m_eth.rx_timer->reset();
}
diff --git a/src/devices/cpu/alto2/a2ether.h b/src/devices/cpu/alto2/a2ether.h
index fe302fd0eef..7ec4320c226 100644
--- a/src/devices/cpu/alto2/a2ether.h
+++ b/src/devices/cpu/alto2/a2ether.h
@@ -11,8 +11,8 @@
#define ALTO2_ETHER_PACKET_SIZE 0400 //!< size of a packet in words
#else // ALTO2_DEFINE_CONSTANTS
-#ifndef _A2ETHER_H_
-#define _A2ETHER_H_
+#ifndef MAME_CPU_ALTO2_A2ETHER_H
+#define MAME_CPU_ALTO2_A2ETHER_H
//! BUS source for ethernet task
enum {
bs_ether_eidfct = bs_task_3 //!< ethernet task: Ethernet input data function
@@ -37,9 +37,9 @@ enum {
//!< f2 (1111): undefined
};
-uint8_t* m_ether_a41; //!< BPROM; P3601-1; 256x4; enet.a41 "PE1"
-uint8_t* m_ether_a42; //!< BPROM; P3601-1; 256x4; enet.a42 "PE2"
-uint8_t* m_ether_a49; //!< BPROM; P3601-1; 265x4 enet.a49 "AFIFO"
+std::unique_ptr<uint8_t[]> m_ether_a41; //!< BPROM; P3601-1; 256x4; enet.a41 "PE1"
+std::unique_ptr<uint8_t[]> m_ether_a42; //!< BPROM; P3601-1; 256x4; enet.a42 "PE2"
+std::unique_ptr<uint8_t[]> m_ether_a49; //!< BPROM; P3601-1; 265x4 enet.a49 "AFIFO"
enum {
ether_a49_BE = (1 << 0), //!< buffer empty
ether_a49_BNE = (1 << 1), //!< buffer next empty
@@ -48,45 +48,45 @@ enum {
};
struct {
- uint32_t serin; //!< serial input shift registers 74164 #37 and #33
- uint16_t fifo[ALTO2_ETHER_FIFO_SIZE]; //!< FIFO buffer
- uint16_t fifo_rd; //!< FIFO input pointer
- uint16_t fifo_wr; //!< FIFO output pointer
- uint16_t status; //!< status word
- uint16_t rx_crc; //!< receiver CRC
- uint16_t tx_crc; //!< transmitter CRC
- uint32_t rx_count; //!< received words count
- uint32_t tx_count; //!< transmitted words count
- std::unique_ptr<uint16_t[]> rx_packet; //!< buffer to collect received words
- std::unique_ptr<uint16_t[]> tx_packet; //!< buffer to collect transmitted words
- emu_timer* rx_timer; //!< receiver timer
- emu_timer* tx_timer; //!< transmitter timer
- jkff_t ff_10a; //!< JK flip-flop 10a IBUSY (Sheet 13)
- jkff_t ff_10b; //!< JK flip-flop 10b OBUSY (Sheet 13)
- jkff_t ff_21a; //!< JK flip-flop 21a OUTON (Sheet 19)
- jkff_t ff_21b; //!< JK flip-flop 21b COLL (Sheet 19)
- jkff_t ff_31a; //!< JK flip-flop 31a OUTGONE (Sheet 19)
- jkff_t ff_31b; //!< JK flip-flop 31b OEOT (Sheet 19)
- jkff_t ff_35a; //!< JK flip-flop 35a OCMD (Sheet 7)
- jkff_t ff_35b; //!< JK flip-flop 35b ICMD (Sheet 7)
- jkff_t ff_47a; //!< JK flip-flop 47a ISR14 (Sheet 15)
- jkff_t ff_47b; //!< JK flip-flop 47b ISR15 (Sheet 15)
- jkff_t ff_51a; //!< JK flip-flop 51a EWFCT latch (Sheet 19)
- jkff_t ff_51b; //!< JK flip-flop 51b OCDW (Sheet 19)
- jkff_t ff_52b; //!< JK flip-flop 52b OSLOAD (Sheet 17)
- jkff_t ff_61a; //!< JK flip-flop 61a CRCGO (Sheet 21)
- jkff_t ff_61b; //!< JK flip-flop 61b OUTRGO (Sheet 21)
- jkff_t ff_62a; //!< JK flip-flop 62a OUTON (Sheet 21)
- jkff_t ff_62b; //!< JK flip-flop 62b OUTGO (Sheet 21)
- jkff_t ff_65a; //!< JK flip-flop 65a IDL (Sheet 10)
- jkff_t ff_65b; //!< JK flip-flop 65b IO (Sheet 10)
- jkff_t ff_69a; //!< JK flip-flop 69a IT (Sheet 14)
- jkff_t ff_69b; //!< JK flip-flop 69b INON (Sheet 14)
- jkff_t ff_70a; //!< JK flip-flop 70a IMID (Sheet 14)
- jkff_t ff_70b; //!< JK flip-flop 70b ILOC (Sheet 14)
- jkff_t ff_77a; //!< JK flip-flop 77a WR (Sheet 10)
- jkff_t ff_77b; //!< JK flip-flop 77b WLF (Sheet 10)
- int breath_of_life; //!< if non-zero, interval in seconds at which to broadcast the breath-of-life
+ uint32_t serin = 0; //!< serial input shift registers 74164 #37 and #33
+ uint16_t fifo[ALTO2_ETHER_FIFO_SIZE] = { }; //!< FIFO buffer
+ uint16_t fifo_rd = 0; //!< FIFO input pointer
+ uint16_t fifo_wr = 0; //!< FIFO output pointer
+ uint16_t status = 0; //!< status word
+ uint16_t rx_crc = 0; //!< receiver CRC
+ uint16_t tx_crc = 0; //!< transmitter CRC
+ uint32_t rx_count = 0; //!< received words count
+ uint32_t tx_count = 0; //!< transmitted words count
+ std::unique_ptr<uint16_t []> rx_packet; //!< buffer to collect received words
+ std::unique_ptr<uint16_t []> tx_packet; //!< buffer to collect transmitted words
+ emu_timer *rx_timer = nullptr; //!< receiver timer
+ emu_timer *tx_timer = nullptr; //!< transmitter timer
+ jkff_t ff_10a = JKFF_0; //!< JK flip-flop 10a IBUSY (Sheet 13)
+ jkff_t ff_10b = JKFF_0; //!< JK flip-flop 10b OBUSY (Sheet 13)
+ jkff_t ff_21a = JKFF_0; //!< JK flip-flop 21a OUTON (Sheet 19)
+ jkff_t ff_21b = JKFF_0; //!< JK flip-flop 21b COLL (Sheet 19)
+ jkff_t ff_31a = JKFF_0; //!< JK flip-flop 31a OUTGONE (Sheet 19)
+ jkff_t ff_31b = JKFF_0; //!< JK flip-flop 31b OEOT (Sheet 19)
+ jkff_t ff_35a = JKFF_0; //!< JK flip-flop 35a OCMD (Sheet 7)
+ jkff_t ff_35b = JKFF_0; //!< JK flip-flop 35b ICMD (Sheet 7)
+ jkff_t ff_47a = JKFF_0; //!< JK flip-flop 47a ISR14 (Sheet 15)
+ jkff_t ff_47b = JKFF_0; //!< JK flip-flop 47b ISR15 (Sheet 15)
+ jkff_t ff_51a = JKFF_0; //!< JK flip-flop 51a EWFCT latch (Sheet 19)
+ jkff_t ff_51b = JKFF_0; //!< JK flip-flop 51b OCDW (Sheet 19)
+ jkff_t ff_52b = JKFF_0; //!< JK flip-flop 52b OSLOAD (Sheet 17)
+ jkff_t ff_61a = JKFF_0; //!< JK flip-flop 61a CRCGO (Sheet 21)
+ jkff_t ff_61b = JKFF_0; //!< JK flip-flop 61b OUTRGO (Sheet 21)
+ jkff_t ff_62a = JKFF_0; //!< JK flip-flop 62a OUTON (Sheet 21)
+ jkff_t ff_62b = JKFF_0; //!< JK flip-flop 62b OUTGO (Sheet 21)
+ jkff_t ff_65a = JKFF_0; //!< JK flip-flop 65a IDL (Sheet 10)
+ jkff_t ff_65b = JKFF_0; //!< JK flip-flop 65b IO (Sheet 10)
+ jkff_t ff_69a = JKFF_0; //!< JK flip-flop 69a IT (Sheet 14)
+ jkff_t ff_69b = JKFF_0; //!< JK flip-flop 69b INON (Sheet 14)
+ jkff_t ff_70a = JKFF_0; //!< JK flip-flop 70a IMID (Sheet 14)
+ jkff_t ff_70b = JKFF_0; //!< JK flip-flop 70b ILOC (Sheet 14)
+ jkff_t ff_77a = JKFF_0; //!< JK flip-flop 77a WR (Sheet 10)
+ jkff_t ff_77b = JKFF_0; //!< JK flip-flop 77b WLF (Sheet 10)
+ int breath_of_life = 0; //!< if non-zero, interval in seconds at which to broadcast the breath-of-life
} m_eth;
TIMER_CALLBACK_MEMBER( rx_breath_of_life ); //!< HACK: pull the next word from the breath-of-life in the fifo
@@ -112,5 +112,5 @@ void update_tclk(int tclk); //!< update all JK flip-flops fo
void init_ether(int task = task_ether); //!< initialize the ethernet task
void exit_ether(); //!< deinitialize the ethernet task
void reset_ether(); //!< reset the ethernet task
-#endif // _A2ETHER_H_
+#endif // MAME_CPU_ALTO2_A2ETHER_H
#endif // ALTO2_DEFINE_CONSTANTS
diff --git a/src/devices/cpu/alto2/a2hw.cpp b/src/devices/cpu/alto2/a2hw.cpp
index bdb8897d1d7..561267fe63c 100644
--- a/src/devices/cpu/alto2/a2hw.cpp
+++ b/src/devices/cpu/alto2/a2hw.cpp
@@ -13,173 +13,173 @@
* @brief read printer paper ready bit
* Paper ready bit. 0 when the printer is ready for a paper scrolling operation.
*/
-READ16_MEMBER ( alto2_cpu_device::pprdy_r ) { return X_RDBITS(m_hw.utilin,16,0,0); }
+uint16_t alto2_cpu_device::pprdy_r() { return X_RDBITS(m_hw.utilin,16,0,0); }
/**
* @brief read printer check bit
* Printer check bit bit.
* Should the printer find itself in an abnormal state, it sets this bit to 0
*/
-READ16_MEMBER ( alto2_cpu_device::pcheck_r ) { return X_RDBITS(m_hw.utilin,16,1,1); }
+uint16_t alto2_cpu_device::pcheck_r() { return X_RDBITS(m_hw.utilin,16,1,1); }
/**
* @brief read unused bit 2
*/
-READ16_MEMBER ( alto2_cpu_device::unused2_r ) { return X_RDBITS(m_hw.utilin,16,2,2); }
+uint16_t alto2_cpu_device::unused2_r() { return X_RDBITS(m_hw.utilin,16,2,2); }
/**
* @brief read printer daisy ready bit
* Daisy ready bit. 0 when the printer is ready to print a character.
*/
-READ16_MEMBER ( alto2_cpu_device::pchrdy_r ) { return X_RDBITS(m_hw.utilin,16,3,3); }
+uint16_t alto2_cpu_device::pchrdy_r() { return X_RDBITS(m_hw.utilin,16,3,3); }
/**
* @brief read printer carriage ready bit
* Carriage ready bit. 0 when the printer is ready for horizontal positioning.
*/
-READ16_MEMBER ( alto2_cpu_device::parrdy_r ) { return X_RDBITS(m_hw.utilin,16,4,4); }
+uint16_t alto2_cpu_device::parrdy_r() { return X_RDBITS(m_hw.utilin,16,4,4); }
/**
* @brief read printer ready bit
* Ready bit. Both this bit and the appropriate other ready bit (carriage,
* daisy, etc.) must be 0 before attempting any output operation.
*/
-READ16_MEMBER ( alto2_cpu_device::pready_r ) { return X_RDBITS(m_hw.utilin,16,5,5); }
+uint16_t alto2_cpu_device::pready_r() { return X_RDBITS(m_hw.utilin,16,5,5); }
/**
* @brief memory configuration switch
*/
-READ16_MEMBER ( alto2_cpu_device::memconfig_r ) { return X_RDBITS(m_hw.utilin,16,6,6); }
+uint16_t alto2_cpu_device::memconfig_r() { return X_RDBITS(m_hw.utilin,16,6,6); }
/**
* @brief get unused bit 7
*/
-READ16_MEMBER ( alto2_cpu_device::unused7_r ) { return X_RDBITS(m_hw.utilin,16,7,7); }
+uint16_t alto2_cpu_device::unused7_r() { return X_RDBITS(m_hw.utilin,16,7,7); }
/**
* @brief get key set key 0
*/
-READ16_MEMBER ( alto2_cpu_device::keyset_key0_r ) { return X_RDBITS(m_hw.utilin,16,8,8); }
+uint16_t alto2_cpu_device::keyset_key0_r() { return X_RDBITS(m_hw.utilin,16,8,8); }
/**
* @brief get key set key 1
*/
-READ16_MEMBER ( alto2_cpu_device::keyset_key1_r ) { return X_RDBITS(m_hw.utilin,16,9,9); }
+uint16_t alto2_cpu_device::keyset_key1_r() { return X_RDBITS(m_hw.utilin,16,9,9); }
/**
* @brief get key set key 2
*/
-READ16_MEMBER ( alto2_cpu_device::keyset_key2_r ) { return X_RDBITS(m_hw.utilin,16,10,10); }
+uint16_t alto2_cpu_device::keyset_key2_r() { return X_RDBITS(m_hw.utilin,16,10,10); }
/**
* @brief get key set key 3
*/
-READ16_MEMBER ( alto2_cpu_device::keyset_key3_r ) { return X_RDBITS(m_hw.utilin,16,11,11); }
+uint16_t alto2_cpu_device::keyset_key3_r() { return X_RDBITS(m_hw.utilin,16,11,11); }
/**
* @brief get key set key 4
*/
-READ16_MEMBER ( alto2_cpu_device::keyset_key4_r ) { return X_RDBITS(m_hw.utilin,16,12,12); }
+uint16_t alto2_cpu_device::keyset_key4_r() { return X_RDBITS(m_hw.utilin,16,12,12); }
/**
* @brief get mouse red button bit
*/
-READ16_MEMBER ( alto2_cpu_device::mouse_red_r ) { return X_RDBITS(m_hw.utilin,16,13,13); }
+uint16_t alto2_cpu_device::mouse_red_r() { return X_RDBITS(m_hw.utilin,16,13,13); }
/**
* @brief get mouse blue button bit
*/
-READ16_MEMBER ( alto2_cpu_device::mouse_blue_r ) { return X_RDBITS(m_hw.utilin,16,14,14); }
+uint16_t alto2_cpu_device::mouse_blue_r() { return X_RDBITS(m_hw.utilin,16,14,14); }
/**
* @brief get mouse yellow button bit
*/
-READ16_MEMBER ( alto2_cpu_device::mouse_yellow_r ) { return X_RDBITS(m_hw.utilin,16,15,15); }
+uint16_t alto2_cpu_device::mouse_yellow_r() { return X_RDBITS(m_hw.utilin,16,15,15); }
/**
* @brief write printer paper ready bit
*/
-WRITE16_MEMBER( alto2_cpu_device::pprdy_w ) { X_WRBITS(m_hw.utilin,16,0,0,data); }
+void alto2_cpu_device::pprdy_w(uint16_t data) { X_WRBITS(m_hw.utilin,16,0,0,data); }
/**
* @brief write printer check bit
*/
-WRITE16_MEMBER( alto2_cpu_device::pcheck_w ) { X_WRBITS(m_hw.utilin,16,1,1,data); }
+void alto2_cpu_device::pcheck_w(uint16_t data) { X_WRBITS(m_hw.utilin,16,1,1,data); }
/**
* @brief read unused bit 2
*/
-WRITE16_MEMBER( alto2_cpu_device::unused2_w ) { X_WRBITS(m_hw.utilin,16,2,2,data); }
+void alto2_cpu_device::unused2_w(uint16_t data) { X_WRBITS(m_hw.utilin,16,2,2,data); }
/**
* @brief write printer daisy ready bit
*/
-WRITE16_MEMBER( alto2_cpu_device::pchrdy_w ) { X_WRBITS(m_hw.utilin,16,3,3,data); }
+void alto2_cpu_device::pchrdy_w(uint16_t data) { X_WRBITS(m_hw.utilin,16,3,3,data); }
/**
* @brief write printer carriage ready bit
*/
-WRITE16_MEMBER( alto2_cpu_device::parrdy_w ) { X_WRBITS(m_hw.utilin,16,4,4,data); }
+void alto2_cpu_device::parrdy_w(uint16_t data) { X_WRBITS(m_hw.utilin,16,4,4,data); }
/**
* @brief write printer ready bit
*/
-WRITE16_MEMBER( alto2_cpu_device::pready_w ) { X_WRBITS(m_hw.utilin,16,5,5,data); }
+void alto2_cpu_device::pready_w(uint16_t data) { X_WRBITS(m_hw.utilin,16,5,5,data); }
/**
* @brief write memory configuration switch
*/
-WRITE16_MEMBER( alto2_cpu_device::memconfig_w ) { X_WRBITS(m_hw.utilin,16,6,6,data); }
+void alto2_cpu_device::memconfig_w(uint16_t data) { X_WRBITS(m_hw.utilin,16,6,6,data); }
/**
* @brief write unused bit 7
*/
-WRITE16_MEMBER( alto2_cpu_device::unused7_w ) { X_WRBITS(m_hw.utilin,16,7,7,data); }
+void alto2_cpu_device::unused7_w(uint16_t data) { X_WRBITS(m_hw.utilin,16,7,7,data); }
/**
* @brief write key set key 0
*/
-WRITE16_MEMBER( alto2_cpu_device::keyset_key0_w ) { X_WRBITS(m_hw.utilin,16,8,8,data); }
+void alto2_cpu_device::keyset_key0_w(uint16_t data) { X_WRBITS(m_hw.utilin,16,8,8,data); }
/**
* @brief write key set key 1
*/
-WRITE16_MEMBER( alto2_cpu_device::keyset_key1_w ) { X_WRBITS(m_hw.utilin,16,9,9,data); }
+void alto2_cpu_device::keyset_key1_w(uint16_t data) { X_WRBITS(m_hw.utilin,16,9,9,data); }
/**
* @brief write key set key 2
*/
-WRITE16_MEMBER( alto2_cpu_device::keyset_key2_w ) { X_WRBITS(m_hw.utilin,16,10,10,data); }
+void alto2_cpu_device::keyset_key2_w(uint16_t data) { X_WRBITS(m_hw.utilin,16,10,10,data); }
/**
* @brief write key set key 3
*/
-WRITE16_MEMBER( alto2_cpu_device::keyset_key3_w ) { X_WRBITS(m_hw.utilin,16,11,11,data); }
+void alto2_cpu_device::keyset_key3_w(uint16_t data) { X_WRBITS(m_hw.utilin,16,11,11,data); }
/**
* @brief write key set key 4
*/
-WRITE16_MEMBER( alto2_cpu_device::keyset_key4_w ) { X_WRBITS(m_hw.utilin,16,12,12,data); }
+void alto2_cpu_device::keyset_key4_w(uint16_t data) { X_WRBITS(m_hw.utilin,16,12,12,data); }
/**
* @brief write mouse red button bit
*/
-WRITE16_MEMBER( alto2_cpu_device::mouse_red_w ) { X_WRBITS(m_hw.utilin,16,13,13,data); }
+void alto2_cpu_device::mouse_red_w(uint16_t data) { X_WRBITS(m_hw.utilin,16,13,13,data); }
/**
* @brief write mouse blue button bit
*/
-WRITE16_MEMBER( alto2_cpu_device::mouse_blue_w ) { X_WRBITS(m_hw.utilin,16,14,14,data); }
+void alto2_cpu_device::mouse_blue_w(uint16_t data) { X_WRBITS(m_hw.utilin,16,14,14,data); }
/**
* @brief write mouse yellow button bit
*/
-WRITE16_MEMBER( alto2_cpu_device::mouse_yellow_w ) { X_WRBITS(m_hw.utilin,16,15,15,data); }
+void alto2_cpu_device::mouse_yellow_w(uint16_t data) { X_WRBITS(m_hw.utilin,16,15,15,data); }
/**
* @brief write mouse buttons bits
*/
-WRITE16_MEMBER( alto2_cpu_device::mouse_buttons_w ) { X_WRBITS(m_hw.utilin,16,13,15,data); }
+void alto2_cpu_device::mouse_buttons_w(uint16_t data) { X_WRBITS(m_hw.utilin,16,13,15,data); }
/**
* @brief printer paper strobe bit
@@ -234,7 +234,7 @@ WRITE16_MEMBER( alto2_cpu_device::mouse_buttons_w ) { X_WRBITS(m_hw.utilin,16,13
* @param offset memory mapped I/O address to be read
* @return current value on the UTILIN port
*/
-READ16_MEMBER( alto2_cpu_device::utilin_r )
+uint16_t alto2_cpu_device::utilin_r(offs_t offset)
{
uint16_t data;
// FIXME: update the printer status
@@ -254,7 +254,7 @@ READ16_MEMBER( alto2_cpu_device::utilin_r )
* @param offset memory mapped I/O address to be read
* @return current value on the XBUS port latch
*/
-READ16_MEMBER( alto2_cpu_device::xbus_r )
+uint16_t alto2_cpu_device::xbus_r(offs_t offset)
{
uint16_t data = m_hw.xbus[offset & 3];
@@ -272,7 +272,7 @@ READ16_MEMBER( alto2_cpu_device::xbus_r )
* @param addr memory mapped I/O address to be read
* @param data value to write to the XBUS port latch
*/
-WRITE16_MEMBER( alto2_cpu_device::xbus_w )
+void alto2_cpu_device::xbus_w(offs_t offset, uint16_t data)
{
if (!machine().side_effects_disabled()) {
LOG((this,LOG_HW,2," XBUS[%d] wr %#o (%#o)\n", offset & 3, offset, data));
@@ -286,7 +286,7 @@ WRITE16_MEMBER( alto2_cpu_device::xbus_w )
* @param addr memory mapped I/O address to be read
* @return current value on the UTILOUT port latch
*/
-READ16_MEMBER( alto2_cpu_device::utilout_r )
+uint16_t alto2_cpu_device::utilout_r(offs_t offset)
{
uint16_t data = m_hw.utilout ^ 0177777;
if (!machine().side_effects_disabled()) {
@@ -303,7 +303,7 @@ READ16_MEMBER( alto2_cpu_device::utilout_r )
* @param addr memory mapped I/O address to be read
* @param data value to write to the UTILOUT port latch
*/
-WRITE16_MEMBER( alto2_cpu_device::utilout_w )
+void alto2_cpu_device::utilout_w(offs_t offset, uint16_t data)
{
if (!machine().side_effects_disabled()) {
LOG((this,LOG_HW,2," UTILOUT wr %#o (%#o)\n", offset, data));
@@ -398,8 +398,8 @@ static const prom_load_t pl_madr_a65 =
void alto2_cpu_device::init_hw()
{
memset(&m_hw, 0, sizeof(m_hw));
- m_madr_a64 = prom_load(machine(), &pl_madr_a64, memregion("madr_a64")->base());
- m_madr_a65 = prom_load(machine(), &pl_madr_a65, memregion("madr_a65")->base());
+ m_madr_a64 = prom_load<uint8_t>(machine(), &pl_madr_a64, memregion("madr_a64")->base());
+ m_madr_a65 = prom_load<uint8_t>(machine(), &pl_madr_a65, memregion("madr_a65")->base());
}
void alto2_cpu_device::exit_hw()
diff --git a/src/devices/cpu/alto2/a2hw.h b/src/devices/cpu/alto2/a2hw.h
index 18accb36c23..d2c2a16e3ba 100644
--- a/src/devices/cpu/alto2/a2hw.h
+++ b/src/devices/cpu/alto2/a2hw.h
@@ -8,8 +8,8 @@
#ifdef ALTO2_DEFINE_CONSTANTS
#else // ALTO2_DEFINE_CONSTANTS
-#ifndef _A2HW_H_
-#define _A2HW_H_
+#ifndef MAME_CPU_ALTO2_A2HW_H
+#define MAME_CPU_ALTO2_A2HW_H
//! miscellaneous hardware registers in the memory mapped I/O range
struct {
uint16_t eia; //!< the EIA port at 0177001
@@ -18,49 +18,49 @@ struct {
uint16_t utilin; //!< the UTILIN port at 0177030 to 0177033 (same value on all addresses)
} m_hw;
-DECLARE_READ16_MEMBER ( pprdy_r ); //!< read UTILIN[0] printer paper ready bit
-DECLARE_READ16_MEMBER ( pcheck_r ); //!< read UTILIN[1] printer check bit
-DECLARE_READ16_MEMBER ( unused2_r ); //!< read UTILIN[2] unused bit
-DECLARE_READ16_MEMBER ( pchrdy_r ); //!< read UTILIN[3] printer daisy ready bit
-DECLARE_READ16_MEMBER ( parrdy_r ); //!< read UTILIN[4] printer carriage ready bit
-DECLARE_READ16_MEMBER ( pready_r ); //!< read UTILIN[5] printer ready bit
-DECLARE_READ16_MEMBER ( memconfig_r ); //!< read UTILIN[6] memory config switch
-DECLARE_READ16_MEMBER ( unused7_r ); //!< read UTILIN[7] unused bit
-DECLARE_READ16_MEMBER ( keyset_key0_r ); //!< read UTILIN[8] keyset key #0
-DECLARE_READ16_MEMBER ( keyset_key1_r ); //!< read UTILIN[9] keyset key #1
-DECLARE_READ16_MEMBER ( keyset_key2_r ); //!< read UTILIN[10] keyset key #2
-DECLARE_READ16_MEMBER ( keyset_key3_r ); //!< read UTILIN[11] keyset key #3
-DECLARE_READ16_MEMBER ( keyset_key4_r ); //!< read UTILIN[12] keyset key #4
-DECLARE_READ16_MEMBER ( mouse_red_r ); //!< read UTILIN[13] mouse red button bit
-DECLARE_READ16_MEMBER ( mouse_blue_r ); //!< read UTILIN[14] mouse blue button bit
-DECLARE_READ16_MEMBER ( mouse_yellow_r ); //!< read UTILIN[15] mouse yellow button bit
+uint16_t pprdy_r(); //!< read UTILIN[0] printer paper ready bit
+uint16_t pcheck_r(); //!< read UTILIN[1] printer check bit
+uint16_t unused2_r(); //!< read UTILIN[2] unused bit
+uint16_t pchrdy_r(); //!< read UTILIN[3] printer daisy ready bit
+uint16_t parrdy_r(); //!< read UTILIN[4] printer carriage ready bit
+uint16_t pready_r(); //!< read UTILIN[5] printer ready bit
+uint16_t memconfig_r(); //!< read UTILIN[6] memory config switch
+uint16_t unused7_r(); //!< read UTILIN[7] unused bit
+uint16_t keyset_key0_r(); //!< read UTILIN[8] keyset key #0
+uint16_t keyset_key1_r(); //!< read UTILIN[9] keyset key #1
+uint16_t keyset_key2_r(); //!< read UTILIN[10] keyset key #2
+uint16_t keyset_key3_r(); //!< read UTILIN[11] keyset key #3
+uint16_t keyset_key4_r(); //!< read UTILIN[12] keyset key #4
+uint16_t mouse_red_r(); //!< read UTILIN[13] mouse red button bit
+uint16_t mouse_blue_r(); //!< read UTILIN[14] mouse blue button bit
+uint16_t mouse_yellow_r(); //!< read UTILIN[15] mouse yellow button bit
-DECLARE_WRITE16_MEMBER( pprdy_w ); //!< write UTILIN[0] printer paper ready bit
-DECLARE_WRITE16_MEMBER( pcheck_w ); //!< write UTILIN[1] printer check bit
-DECLARE_WRITE16_MEMBER( unused2_w ); //!< write UTILIN[2] unused bit
-DECLARE_WRITE16_MEMBER( pchrdy_w ); //!< write UTILIN[3] printer daisy ready bit
-DECLARE_WRITE16_MEMBER( parrdy_w ); //!< write UTILIN[4] carriage ready bit
-DECLARE_WRITE16_MEMBER( pready_w ); //!< write UTILIN[5] printer ready bit
-DECLARE_WRITE16_MEMBER( memconfig_w ); //!< write UTILIN[6] memory config switch
-DECLARE_WRITE16_MEMBER( unused7_w ); //!< write UTILIN[7] unused bit
-DECLARE_WRITE16_MEMBER( keyset_key0_w ); //!< write UTILIN[8] keyset key #0
-DECLARE_WRITE16_MEMBER( keyset_key1_w ); //!< write UTILIN[9] keyset key #1
-DECLARE_WRITE16_MEMBER( keyset_key2_w ); //!< write UTILIN[10] keyset key #2
-DECLARE_WRITE16_MEMBER( keyset_key3_w ); //!< write UTILIN[11] keyset key #3
-DECLARE_WRITE16_MEMBER( keyset_key4_w ); //!< write UTILIN[12] keyset key #4
-DECLARE_WRITE16_MEMBER( mouse_red_w ); //!< write UTILIN[13] mouse red button bit
-DECLARE_WRITE16_MEMBER( mouse_blue_w ); //!< write UTILIN[14] mouse blue button bit
-DECLARE_WRITE16_MEMBER( mouse_yellow_w ); //!< write UTILIN[15] mouse yellow button bit
-DECLARE_WRITE16_MEMBER( mouse_buttons_w ); //!< write UTILIN[13-15] mouse buttons bits
+void pprdy_w(uint16_t data); //!< write UTILIN[0] printer paper ready bit
+void pcheck_w(uint16_t data); //!< write UTILIN[1] printer check bit
+void unused2_w(uint16_t data); //!< write UTILIN[2] unused bit
+void pchrdy_w(uint16_t data); //!< write UTILIN[3] printer daisy ready bit
+void parrdy_w(uint16_t data); //!< write UTILIN[4] carriage ready bit
+void pready_w(uint16_t data); //!< write UTILIN[5] printer ready bit
+void memconfig_w(uint16_t data); //!< write UTILIN[6] memory config switch
+void unused7_w(uint16_t data); //!< write UTILIN[7] unused bit
+void keyset_key0_w(uint16_t data); //!< write UTILIN[8] keyset key #0
+void keyset_key1_w(uint16_t data); //!< write UTILIN[9] keyset key #1
+void keyset_key2_w(uint16_t data); //!< write UTILIN[10] keyset key #2
+void keyset_key3_w(uint16_t data); //!< write UTILIN[11] keyset key #3
+void keyset_key4_w(uint16_t data); //!< write UTILIN[12] keyset key #4
+void mouse_red_w(uint16_t data); //!< write UTILIN[13] mouse red button bit
+void mouse_blue_w(uint16_t data); //!< write UTILIN[14] mouse blue button bit
+void mouse_yellow_w(uint16_t data); //!< write UTILIN[15] mouse yellow button bit
+void mouse_buttons_w(uint16_t data); //!< write UTILIN[13-15] mouse buttons bits
-DECLARE_READ16_MEMBER ( utilin_r ); //!< read an UTILIN address
-DECLARE_READ16_MEMBER ( utilout_r ); //!< read the UTILOUT address
-DECLARE_WRITE16_MEMBER( utilout_w ); //!< write the UTILOUT address
-DECLARE_READ16_MEMBER ( xbus_r ); //!< read an XBUS address
-DECLARE_WRITE16_MEMBER( xbus_w ); //!< write an XBUS address (?)
+uint16_t utilin_r(offs_t offset); //!< read an UTILIN address
+uint16_t utilout_r(offs_t offset); //!< read the UTILOUT address
+void utilout_w(offs_t offset, uint16_t data); //!< write the UTILOUT address
+uint16_t xbus_r(offs_t offset); //!< read an XBUS address
+void xbus_w(offs_t offset, uint16_t data); //!< write an XBUS address (?)
-void init_hw(); //!< initialize miscellaneous hardware
-void exit_hw(); //!< deinitialize miscellaneous hardware
-void reset_hw(); //!< reset miscellaneous hardware
-#endif // _A2HW_H_
+void init_hw(); //!< initialize miscellaneous hardware
+void exit_hw(); //!< deinitialize miscellaneous hardware
+void reset_hw(); //!< reset miscellaneous hardware
+#endif // MAME_CPU_ALTO2_A2HW_H
#endif // ALTO2_DEFINE_CONSTANTS
diff --git a/src/devices/cpu/alto2/a2jkff.h b/src/devices/cpu/alto2/a2jkff.h
index 49929474c19..8f5e853f72b 100644
--- a/src/devices/cpu/alto2/a2jkff.h
+++ b/src/devices/cpu/alto2/a2jkff.h
@@ -44,8 +44,8 @@ typedef enum {
#else // ALTO2_DEFINE_CONSTANTS
-#ifndef _A2JKFF_H_
-#define _A2JKFF_H_
+#ifndef MAME_CPU_ALTO2_A2JKFF_H
+#define MAME_CPU_ALTO2_A2JKFF_H
#if JKFF_DEBUG
/**
@@ -188,5 +188,5 @@ static inline jkff_t update_jkff(uint8_t s0, uint8_t s1, const char*)
}
#endif // JKFF_DEBUG
-#endif // _A2JKFF_H_
+#endif // MAME_CPU_ALTO2_A2JKFF_H
#endif // ALTO2_DEFINE_CONSTANTS
diff --git a/src/devices/cpu/alto2/a2kbd.cpp b/src/devices/cpu/alto2/a2kbd.cpp
index 4f7831beffb..ad94be209b4 100644
--- a/src/devices/cpu/alto2/a2kbd.cpp
+++ b/src/devices/cpu/alto2/a2kbd.cpp
@@ -14,7 +14,7 @@
* @param addr memory mapped I/O address to be read
* @return keyboard matrix value for address modulo 4
*/
-READ16_MEMBER( alto2_cpu_device::kbd_ad_r )
+uint16_t alto2_cpu_device::kbd_ad_r(offs_t offset)
{
uint16_t data = m_kb_read_callback(offset & 3);
m_kbd.matrix[offset & 03] = data;
diff --git a/src/devices/cpu/alto2/a2kbd.h b/src/devices/cpu/alto2/a2kbd.h
index 8f5c9dd2538..e48eeb65a9c 100644
--- a/src/devices/cpu/alto2/a2kbd.h
+++ b/src/devices/cpu/alto2/a2kbd.h
@@ -93,17 +93,17 @@
#define A2_KEY_FR5 MAKE_KEY(3,000) //!< ADL right function key 5
#else // ALTO2_DEFINE_CONSTANTS
-#ifndef _A2KBD_H_
-#define _A2KBD_H_
+#ifndef MAME_CPU_ALTO2_A2KBD_H
+#define MAME_CPU_ALTO2_A2KBD_H
struct {
uint16_t bootkey; //!< boot key - key code pressed before power on
uint16_t matrix[4]; //!< a bit map of the keys pressed (ioports ROW0 ... ROW3)
} m_kbd;
-DECLARE_READ16_MEMBER( kbd_ad_r ); //!< read the keyboard matrix
+uint16_t kbd_ad_r(offs_t offset); //!< read the keyboard matrix
void init_kbd(uint16_t bootkey = 0177777); //!< initialize the keyboard hardware, optionally set the boot key
void exit_kbd(); //!< deinitialize the keyboard hardware
void reset_kbd(); //!< reset the keyboard hardware
-#endif // _A2KBD_H_
+#endif // MAME_CPU_ALTO2_A2KBD_H
#endif // ALTO2_DEFINE_CONSTANTS
diff --git a/src/devices/cpu/alto2/a2ksec.h b/src/devices/cpu/alto2/a2ksec.h
index 96c2530a2a5..2a908cbafd2 100644
--- a/src/devices/cpu/alto2/a2ksec.h
+++ b/src/devices/cpu/alto2/a2ksec.h
@@ -8,8 +8,8 @@
#ifdef ALTO2_DEFINE_CONSTANTS
#else // ALTO2_DEFINE_CONSTANTS
-#ifndef _A2KSEC_H_
-#define _A2KSEC_H_
+#ifndef MAME_CPU_ALTO2_A2KSEC_H
+#define MAME_CPU_ALTO2_A2KSEC_H
//! BUS source for disk sector task
enum {
bs_ksec_read_kstat = bs_task_3, //!< bus source: read disk status register
@@ -44,5 +44,5 @@ void f1_early_ksec_block(void); //!< block ksec task
void init_ksec(int task = task_ksec); //!< initialize the disk sector task
void exit_ksec(); //!< deinitialize the disk sector task
void reset_ksec(); //!< reset the disk sector task
-#endif // _A2KSEC_H_
+#endif // MAME_CPU_ALTO2_A2KSEC_H
#endif // ALTO2_DEFINE_CONSTANTS
diff --git a/src/devices/cpu/alto2/a2kwd.h b/src/devices/cpu/alto2/a2kwd.h
index 678408501d2..18405379dd6 100644
--- a/src/devices/cpu/alto2/a2kwd.h
+++ b/src/devices/cpu/alto2/a2kwd.h
@@ -8,8 +8,8 @@
#ifdef ALTO2_DEFINE_CONSTANTS
#else // ALTO2_DEFINE_CONSTANTS
-#ifndef _A2KWD_H_
-#define _A2KWD_H_
+#ifndef MAME_CPU_ALTO2_A2KWD_H
+#define MAME_CPU_ALTO2_A2KWD_H
//! BUS source for disk word task
enum {
@@ -45,5 +45,5 @@ void f1_early_kwd_block(); //!< F1 func: disable the disk w
void init_kwd(int task = task_kwd); //!< initialize the disk word task
void exit_kwd(); //!< deinitialize the disk word task
void reset_kwd(); //!< reset the disk word task
-#endif // _A2KWD_H_
+#endif // MAME_CPU_ALTO2_A2KWD_H
#endif // ALTO2_DEFINE_CONSTANTS
diff --git a/src/devices/cpu/alto2/a2mem.cpp b/src/devices/cpu/alto2/a2mem.cpp
index 036ac05e23e..e1887913318 100644
--- a/src/devices/cpu/alto2/a2mem.cpp
+++ b/src/devices/cpu/alto2/a2mem.cpp
@@ -482,7 +482,7 @@ uint32_t alto2_cpu_device::hamming_code(bool write, uint32_t dw_addr, uint32_t d
* memory access. Note that MEAR is set whenever an error of
* _any kind_ (single-bit or double-bit) is detected.
*/
-READ16_MEMBER( alto2_cpu_device::mear_r )
+uint16_t alto2_cpu_device::mear_r()
{
int data = m_mem.error ? m_mem.mear : m_mem.mar;
if (!machine().side_effects_disabled()) {
@@ -507,7 +507,7 @@ READ16_MEMBER( alto2_cpu_device::mear_r )
* MESR[14-15] Bank number in which error occurred
* </PRE>
*/
-READ16_MEMBER( alto2_cpu_device::mesr_r )
+uint16_t alto2_cpu_device::mesr_r()
{
uint16_t data = m_mem.mesr ^ 0177777;
if (!machine().side_effects_disabled()) {
@@ -521,7 +521,7 @@ READ16_MEMBER( alto2_cpu_device::mesr_r )
return data;
}
-WRITE16_MEMBER( alto2_cpu_device::mesr_w )
+void alto2_cpu_device::mesr_w(uint16_t data)
{
if (!machine().side_effects_disabled()) {
LOG((this,LOG_MEM,2," MESR write %07o (clear MESR; was %07o)\n", data, m_mem.mesr));
@@ -552,7 +552,7 @@ WRITE16_MEMBER( alto2_cpu_device::mesr_w )
* MECR[15] Spare
* </PRE>
*/
-WRITE16_MEMBER( alto2_cpu_device::mecr_w )
+void alto2_cpu_device::mecr_w(uint16_t data)
{
m_mem.mecr = data ^ 0177777;
// clear spare bits
@@ -571,7 +571,7 @@ WRITE16_MEMBER( alto2_cpu_device::mecr_w )
/**
* @brief memory error control register read
*/
-READ16_MEMBER( alto2_cpu_device::mecr_r )
+uint16_t alto2_cpu_device::mecr_r()
{
uint16_t data = m_mem.mecr ^ 0177777;
// all spare bits are set
@@ -591,7 +591,7 @@ READ16_MEMBER( alto2_cpu_device::mecr_r )
* Note: This is for debugger access. Regular memory access is
* only through load_mar, read_mem and write_mem.
*/
-READ16_MEMBER ( alto2_cpu_device::ioram_r )
+uint16_t alto2_cpu_device::ioram_r(offs_t offset)
{
offs_t dw_addr = offset / 2;
return static_cast<uint16_t>(offset & 1 ? GET_ODD(m_mem.ram[dw_addr]) : GET_EVEN(m_mem.ram[dw_addr]));
@@ -602,7 +602,7 @@ READ16_MEMBER ( alto2_cpu_device::ioram_r )
* Note: This is for debugger access. Regular memory access is
* only through load_mar, read_mem and write_mem.
*/
-WRITE16_MEMBER( alto2_cpu_device::ioram_w )
+void alto2_cpu_device::ioram_w(offs_t offset, uint16_t data)
{
offs_t dw_addr = offset / 2;
if (offset & 1)
@@ -807,7 +807,7 @@ void alto2_cpu_device::debug_write_mem(uint32_t addr, uint16_t data)
*/
void alto2_cpu_device::init_memory()
{
- memset(&m_mem, 0, sizeof(m_mem));
+ m_mem = decltype(m_mem)();
save_item(NAME(m_mem.mar));
save_item(NAME(m_mem.rmdd));
save_item(NAME(m_mem.wmdd));
@@ -826,23 +826,19 @@ void alto2_cpu_device::exit_memory()
void alto2_cpu_device::reset_memory()
{
- if (m_mem.ram) {
- m_mem.ram = nullptr;
- }
- if (m_mem.hpb) {
- m_mem.hpb = nullptr;
- }
+ m_mem.ram.reset();
+ m_mem.hpb.reset();
// allocate 64K or 128K words of main memory
- ioport_port* config = ioport(":CONFIG");
+ ioport_port *const config = ioport(":CONFIG");
m_mem.size = ALTO2_RAM_SIZE;
// config should be valid, unless the driver doesn't define it
if (config && 0 == config->read())
m_mem.size *= 2;
- logerror("Main memory %u KiB\n", static_cast<uint32_t>(sizeof(uint16_t) * m_mem.size / 1024));
+ logerror("Main memory %u KiB\n", sizeof(uint16_t) * m_mem.size / 1024);
- m_mem.ram = make_unique_clear<uint32_t[]>(sizeof(uint16_t) * m_mem.size);
- m_mem.hpb = make_unique_clear<uint8_t[]> (sizeof(uint16_t) * m_mem.size);
+ m_mem.ram = make_unique_clear<uint32_t []>(sizeof(uint16_t) * m_mem.size);
+ m_mem.hpb = make_unique_clear<uint8_t []> (sizeof(uint16_t) * m_mem.size);
// Initialize the hamming codes and parity bits
for (uint32_t addr = 0; addr < m_mem.size; addr++)
diff --git a/src/devices/cpu/alto2/a2mem.h b/src/devices/cpu/alto2/a2mem.h
index 8c79c439a6c..f58d6aed5ae 100644
--- a/src/devices/cpu/alto2/a2mem.h
+++ b/src/devices/cpu/alto2/a2mem.h
@@ -12,8 +12,8 @@
#define ALTO2_IO_PAGE_SIZE 0001000 //!< size of the memory mapped io range
#else // ALTO2_DEFINE_CONSTANTS
-#ifndef _A2MEM_H_
-#define _A2MEM_H_
+#ifndef MAME_CPU_ALTO2_A2MEM_H
+#define MAME_CPU_ALTO2_A2MEM_H
//! memory access mode
enum {
ALTO2_MEM_NONE,
@@ -25,14 +25,14 @@ enum {
};
struct {
- uint32_t size; //!< main memory size (64K or 128K)
- std::unique_ptr<uint32_t[]> ram; //!< main memory organized as double-words
- std::unique_ptr<uint8_t[]> hpb; //!< Hamming Code bits (6) and Parity bits (1) per double word
- uint32_t mar; //!< memory address register
- uint32_t rmdd; //!< read memory data double-word
- uint32_t wmdd; //!< write memory data double-word
- uint32_t md; //!< memory data register
- uint64_t cycle; //!< cycle when the memory address register was loaded
+ uint32_t size = 0; //!< main memory size (64K or 128K)
+ std::unique_ptr<uint32_t []> ram; //!< main memory organized as double-words
+ std::unique_ptr<uint8_t []> hpb; //!< Hamming Code bits (6) and Parity bits (1) per double word
+ uint32_t mar = 0; //!< memory address register
+ uint32_t rmdd = 0; //!< read memory data double-word
+ uint32_t wmdd = 0; //!< write memory data double-word
+ uint32_t md = 0; //!< memory data register
+ uint64_t cycle = 0; //!< cycle when the memory address register was loaded
/**
* @brief memory access under the way if non-zero
@@ -41,11 +41,11 @@ struct {
* 2: memory access even word (MEM_RAM)
* 3: memory access odd word (MEM_RAM | MEM_ODD)
*/
- int access;
- bool error; //!< non-zero after a memory error was detected
- uint32_t mear; //!< memory error address register
- uint32_t mesr; //!< memory error status register
- uint32_t mecr; //!< memory error control register
+ int access = 0;
+ bool error = false; //!< non-zero after a memory error was detected
+ uint32_t mear = 0; //!< memory error address register
+ uint32_t mesr = 0; //!< memory error status register
+ uint32_t mecr = 0; //!< memory error control register
} m_mem;
/**
@@ -103,11 +103,11 @@ inline bool check_mem_write_stall() {
}
-DECLARE_READ16_MEMBER ( mear_r ); //!< memory error address register read
-DECLARE_READ16_MEMBER ( mesr_r ); //!< memory error status register read
-DECLARE_WRITE16_MEMBER( mesr_w ); //!< memory error status register write (clear)
-DECLARE_READ16_MEMBER ( mecr_r ); //!< memory error control register read
-DECLARE_WRITE16_MEMBER( mecr_w ); //!< memory error control register write
+uint16_t mear_r(); //!< memory error address register read
+uint16_t mesr_r(); //!< memory error status register read
+void mesr_w(uint16_t data); //!< memory error status register write (clear)
+uint16_t mecr_r(); //!< memory error control register read
+void mecr_w(uint16_t data); //!< memory error control register write
//! Read or write a memory double-word and calculate or compare its Hamming code.
uint32_t hamming_code(bool write, uint32_t dw_addr, uint32_t dw_data);
@@ -135,5 +135,5 @@ void watch_read(uint32_t addr, uint32_t data);
void init_memory(); //!< initialize the memory system
void exit_memory(); //!< deinitialize the memory system
void reset_memory(); //!< reset the memory system
-#endif // _A2MEM_H_
+#endif // MAME_CPU_ALTO2_A2MEM_H
#endif // ALTO2_DEFINE_CONSTANTS
diff --git a/src/devices/cpu/alto2/a2mouse.cpp b/src/devices/cpu/alto2/a2mouse.cpp
index 4ee209e6c1d..3747abb71ea 100644
--- a/src/devices/cpu/alto2/a2mouse.cpp
+++ b/src/devices/cpu/alto2/a2mouse.cpp
@@ -148,7 +148,7 @@ INPUT_CHANGED_MEMBER( alto2_cpu_device::mouse_motion_x )
{
int16_t ox = static_cast<int16_t>(oldval);
int16_t nx = static_cast<int16_t>(newval);
- m_mouse.dx = std::min(std::max(0, m_mouse.dx + (nx - ox)), 639);
+ m_mouse.dx = std::clamp(m_mouse.dx + (nx - ox), 0, 639);
}
/**
@@ -162,7 +162,7 @@ INPUT_CHANGED_MEMBER( alto2_cpu_device::mouse_motion_y )
{
int16_t oy = static_cast<int16_t>(oldval);
int16_t ny = static_cast<int16_t>(newval);
- m_mouse.dy = std::min(std::max(0, m_mouse.dy + (ny - oy)), 824);
+ m_mouse.dy = std::clamp(m_mouse.dy + (ny - oy), 0, 824);
}
/**
@@ -233,7 +233,7 @@ static const prom_load_t pl_madr_a32 =
void alto2_cpu_device::init_mouse()
{
memset(&m_mouse, 0, sizeof(m_mouse));
- m_madr_a32 = prom_load(machine(), &pl_madr_a32, memregion("madr_a32")->base());
+ m_madr_a32 = prom_load<uint8_t>(machine(), &pl_madr_a32, memregion("madr_a32")->base());
}
void alto2_cpu_device::exit_mouse()
diff --git a/src/devices/cpu/alto2/a2mouse.h b/src/devices/cpu/alto2/a2mouse.h
index 375a37397a2..628b73f671e 100644
--- a/src/devices/cpu/alto2/a2mouse.h
+++ b/src/devices/cpu/alto2/a2mouse.h
@@ -8,8 +8,8 @@
#ifdef ALTO2_DEFINE_CONSTANTS
#else // ALTO2_DEFINE_CONSTANTS
-#ifndef _A2MOUSE_H_
-#define _A2MOUSE_H_
+#ifndef MAME_CPU_ALTO2_A2MOUSE_H
+#define MAME_CPU_ALTO2_A2MOUSE_H
/**
* @brief PROM madr.a32 contains a lookup table to translate mouse motions
*
@@ -51,7 +51,7 @@
* sequence: 10 -> 70 -> e0 -> 80
* </PRE>
*/
-uint8_t* m_madr_a32;
+std::unique_ptr<uint8_t[]> m_madr_a32;
//! mouse context
struct {
@@ -67,5 +67,5 @@ uint16_t mouse_read(); //!< return the mouse motion f
void init_mouse(); //!< initialize the mouse context
void exit_mouse(); //!< deinitialize the mouse context
void reset_mouse(); //!< reset the mouse context
-#endif // _A2MOUSE_H_
+#endif // MAME_CPU_ALTO2_A2MOUSE_H
#endif // ALTO2_DEFINE_CONSTANTS
diff --git a/src/devices/cpu/alto2/a2mrt.h b/src/devices/cpu/alto2/a2mrt.h
index 20b00724fc9..abaa4e92c24 100644
--- a/src/devices/cpu/alto2/a2mrt.h
+++ b/src/devices/cpu/alto2/a2mrt.h
@@ -8,12 +8,12 @@
#ifdef ALTO2_DEFINE_CONSTANTS
#else // ALTO2_DEFINE_CONSTANTS
-#ifndef _A2MRT_H_
-#define _A2MRT_H_
+#ifndef MAME_CPU_ALTO2_A2MRT_H
+#define MAME_CPU_ALTO2_A2MRT_H
void f1_early_mrt_block(); //!< F1 func: block the display word task
void activate_mrt(); //!< called by the CPU when MRT becomes active
void init_mrt(int task = task_mrt); //!< initialize the memory refresh task
void exit_mrt(); //!< deinitialize the memory refresh task
void reset_mrt(); //!< reset the memory refresh task
-#endif // _A2MRT_H_
+#endif // MAME_CPU_ALTO2_A2MRT_H
#endif // ALTO2_DEFINE_CONSTANTS
diff --git a/src/devices/cpu/alto2/a2part.h b/src/devices/cpu/alto2/a2part.h
index 0bc8583bbbc..b9946a83f0c 100644
--- a/src/devices/cpu/alto2/a2part.h
+++ b/src/devices/cpu/alto2/a2part.h
@@ -8,11 +8,11 @@
#ifdef ALTO2_DEFINE_CONSTANTS
#else // ALTO2_DEFINE_CONSTANTS
-#ifndef _A2PART_H_
-#define _A2PART_H_
+#ifndef MAME_CPU_ALTO2_A2PART_H
+#define MAME_CPU_ALTO2_A2PART_H
void activate_part();
void init_part(int task = task_part); //!< initialize the parity task
void exit_part(); //!< deinitialize the parity task
void reset_part(); //!< reset the parity task
-#endif // _A2PART_H_
+#endif // MAME_CPU_ALTO2_A2PART_H
#endif // ALTO2_DEFINE_CONSTANTS
diff --git a/src/devices/cpu/alto2/a2ram.cpp b/src/devices/cpu/alto2/a2ram.cpp
index 3aab054871d..a9babb97900 100644
--- a/src/devices/cpu/alto2/a2ram.cpp
+++ b/src/devices/cpu/alto2/a2ram.cpp
@@ -246,7 +246,7 @@ void alto2_cpu_device::f1_late_swmode()
branch_ROM("RAM0", 0);
break;
default:
- fatal(1, "Impossible current mpc %u\n", page);
+ throw emu_fatalerror(1, "Impossible current mpc %u\n", page);
}
break;
@@ -262,7 +262,7 @@ void alto2_cpu_device::f1_late_swmode()
branch_ROM("ROM0", 1);
break;
default:
- fatal(1, "Impossible next %u\n", next);
+ throw emu_fatalerror(1, "Impossible next %u\n", next);
}
break;
case 1: /* ROM1 to ROM0 or RAM0 */
@@ -274,7 +274,7 @@ void alto2_cpu_device::f1_late_swmode()
branch_RAM("ROM1", 0);
break;
default:
- fatal(1, "Impossible next %u\n", next);
+ throw emu_fatalerror(1, "Impossible next %u\n", next);
}
break;
case 2: /* RAM0 to ROM0 or ROM1 */
@@ -286,11 +286,11 @@ void alto2_cpu_device::f1_late_swmode()
branch_ROM("RAM0", 1);
break;
default:
- fatal(1, "Impossible next %u\n", next);
+ throw emu_fatalerror(1, "Impossible next %u\n", next);
}
break;
default:
- fatal(1, "Impossible current mpc %u\n", page);
+ throw emu_fatalerror(1, "Impossible current mpc %u\n", page);
}
break;
@@ -313,7 +313,7 @@ void alto2_cpu_device::f1_late_swmode()
branch_RAM("ROM0", 0);
break;
default:
- fatal(1, "Impossible next %u\n", next);
+ throw emu_fatalerror(1, "Impossible next %u\n", next);
}
break;
case 1: /* RAM0 to ROM0, RAM2, RAM1, RAM1 */
@@ -331,7 +331,7 @@ void alto2_cpu_device::f1_late_swmode()
branch_RAM("RAM0", 1);
break;
default:
- fatal(1, "Impossible next %u\n", next);
+ throw emu_fatalerror(1, "Impossible next %u\n", next);
}
break;
case 2: /* RAM1 to ROM0, RAM2, RAM0, RAM0 */
@@ -349,7 +349,7 @@ void alto2_cpu_device::f1_late_swmode()
branch_RAM("RAM1", 0);
break;
default:
- fatal(1, "Impossible next %u\n", next);
+ throw emu_fatalerror(1, "Impossible next %u\n", next);
}
break;
case 3: /* RAM2 to ROM0, RAM1, RAM0, RAM0 */
@@ -367,15 +367,15 @@ void alto2_cpu_device::f1_late_swmode()
branch_RAM("RAM2", 0);
break;
default:
- fatal(1, "Impossible next %u\n", next);
+ throw emu_fatalerror(1, "Impossible next %u\n", next);
}
break;
default:
- fatal(1, "Impossible current mpc %u\n", page);
+ throw emu_fatalerror(1, "Impossible current mpc %u\n", page);
}
break;
default:
- fatal(1, "Impossible control ROM/RAM config %u (%u CROM pages, %u CRAM pages)\n",
+ throw emu_fatalerror(1, "Impossible control ROM/RAM config %u (%u CROM pages, %u CRAM pages)\n",
m_cram_config, m_ucode_rom_pages, m_ucode_ram_pages);
}
}
diff --git a/src/devices/cpu/alto2/a2ram.h b/src/devices/cpu/alto2/a2ram.h
index 62745bdc5bd..adaafd63d05 100644
--- a/src/devices/cpu/alto2/a2ram.h
+++ b/src/devices/cpu/alto2/a2ram.h
@@ -11,8 +11,8 @@
#define ALTO2_UCODE_PAGE_MASK (ALTO2_UCODE_PAGE_SIZE-1) //!< mask for microcode ROM/RAM address
#else // ALTO2_DEFINE_CONSTANTS
-#ifndef _A2RAM_H_
-#define _A2RAM_H_
+#ifndef MAME_CPU_ALTO2_A2RAM_H
+#define MAME_CPU_ALTO2_A2RAM_H
//! BUS source for RAM related tasks
enum {
bs_ram_read_slocation= bs_task_3, //!< ram related: read S register
@@ -41,5 +41,5 @@ void f1_late_load_srb(); //!< F1 func: load the S registe
void init_ram(int task); //!< called by RAM related tasks
void exit_ram(); //!< deinitialize the RAM related tasks
void reset_ram(); //!< reset the RAM related tasks
-#endif // A2RAM_H
+#endif // MAME_CPU_ALTO2_A2RAM_H
#endif // ALTO2_DEFINE_CONSTANTS
diff --git a/src/devices/cpu/alto2/a2roms.cpp b/src/devices/cpu/alto2/a2roms.cpp
index 7eab1e34212..fe55ef21f8b 100644
--- a/src/devices/cpu/alto2/a2roms.cpp
+++ b/src/devices/cpu/alto2/a2roms.cpp
@@ -104,28 +104,20 @@ static void write_type_and_xor(void *base, int type, uint32_t addr, uint32_t dan
* @param segments number of segments in one page of the result
* @return pointer to the newly allocated memory filled with source bits
*/
-uint8_t* prom_load(running_machine& machine, const prom_load_t* prom, const uint8_t* src, int pages, int segments)
+template <typename T>
+std::unique_ptr<T []> prom_load(running_machine& machine, const prom_load_t* prom, const uint8_t* src, int pages, int segments)
{
- void* array = nullptr;
- size_t type = prom->type;
- size_t size = prom->size;
+ assert(sizeof(T) == prom->type);
+
+ size_t const size = prom->size;
#if DEBUG_PROM_LOAD
- uint8_t width = prom->width;
+ size_t const type = prom->type;
+ uint8_t const width = prom->width;
#endif
- switch (type) {
- case sizeof(uint8_t):
- array = auto_alloc_array(machine, uint8_t, pages * size);
- break;
- case sizeof(uint16_t):
- array = auto_alloc_array(machine, uint16_t, pages * size);
- break;
- case sizeof(uint32_t):
- array = auto_alloc_array(machine, uint32_t, pages * size);
- break;
- }
+ std::unique_ptr<T []> array = std::make_unique<T []>(pages * size);
- uint8_t* base = reinterpret_cast<uint8_t*>(array);
+ uint8_t* base = reinterpret_cast<uint8_t *>(array.get());
for (int page = 0; page < pages; page++)
{
uint8_t* dst = base + (prom->type * prom->size * page);
@@ -151,47 +143,38 @@ uint8_t* prom_load(running_machine& machine, const prom_load_t* prom, const uint
}
#if DEBUG_PROM_LOAD
- switch (type) {
- case sizeof(uint8_t):
- {
- uint8_t* data = reinterpret_cast<uint8_t*>(array);
- for (int addr = 0; addr < pages*size; addr++) {
- if (0 == (addr % 16))
- printf("%04x:", addr);
- if (width <= 4)
- printf(" %x", data[addr]);
- else
- printf(" %02x", data[addr]);
- if (15 == (addr % 16))
- printf("\n");
- }
+ for (int addr = 0; addr < pages*size; addr++) {
+ switch (type) {
+ case sizeof(uint8_t):
+ if (0 == (addr % 16))
+ printf("%04x:", addr);
+ if (width <= 4)
+ printf(" %x", array[addr]);
+ else
+ printf(" %02x", array[addr]);
+ if (15 == (addr % 16))
+ printf("\n");
+ break;
+ case sizeof(uint16_t):
+ if (0 == (addr % 8))
+ printf("%04x:", addr);
+ printf(" %04x", array[addr]);
+ if (7 == (addr % 8))
+ printf("\n");
+ break;
+ case sizeof(uint32_t):
+ if (0 == (addr % 4))
+ printf("%04x:", addr);
+ printf(" %08x", array[addr]);
+ if (3 == (addr % 4))
+ printf("\n");
+ break;
}
- break;
- case sizeof(uint16_t):
- {
- uint16_t* data = reinterpret_cast<uint16_t*>(array);
- for (int addr = 0; addr < pages*size; addr++) {
- if (0 == (addr % 8))
- printf("%04x:", addr);
- printf(" %04x", data[addr]);
- if (7 == (addr % 8))
- printf("\n");
- }
- }
- break;
- case sizeof(uint32_t):
- {
- uint32_t* data = reinterpret_cast<uint32_t*>(array);
- for (int addr = 0; addr < pages*size; addr++) {
- if (0 == (addr % 4))
- printf("%04x:", addr);
- printf(" %08x", data[addr]);
- if (3 == (addr % 4))
- printf("\n");
- }
- }
- break;
}
#endif
- return reinterpret_cast<uint8_t *>(array);
+ return array;
}
+
+template std::unique_ptr<uint8_t []> prom_load<uint8_t>(running_machine& machine, const prom_load_t* prom, const uint8_t* src, int pages, int segments);
+template std::unique_ptr<uint16_t []> prom_load<uint16_t>(running_machine& machine, const prom_load_t* prom, const uint8_t* src, int pages, int segments);
+template std::unique_ptr<uint32_t []> prom_load<uint32_t>(running_machine& machine, const prom_load_t* prom, const uint8_t* src, int pages, int segments);
diff --git a/src/devices/cpu/alto2/a2roms.h b/src/devices/cpu/alto2/a2roms.h
index 1d1cc149660..930732a497f 100644
--- a/src/devices/cpu/alto2/a2roms.h
+++ b/src/devices/cpu/alto2/a2roms.h
@@ -5,9 +5,10 @@
* Xerox AltoII RAM PROM loading and decoding
*
*****************************************************************************/
-#ifndef _CPU_A2ROMS_H_
-#define _CPU_A2ROMS_H_
+#ifndef MAME_CPU_ALTO2_A2ROMS_H
+#define MAME_CPU_ALTO2_A2ROMS_H
+#pragma once
/**
* @brief structure to define a ROM's or PROM's loading options
@@ -38,5 +39,6 @@ typedef struct {
#define DMAP_DEFAULT {0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15}
#define DMAP_REVERSE_0_3 {3,2,1,0,}
-extern uint8_t* prom_load(running_machine& machine, const prom_load_t* prom, const uint8_t* src, int pages = 1, int segments = 1);
-#endif // _CPU_A2ROMS_H_
+template <typename T> std::unique_ptr<T []> prom_load(running_machine& machine, const prom_load_t* prom, const uint8_t* src, int pages = 1, int segments = 1);
+
+#endif // MAME_CPU_ALTO2_A2ROMS_H
diff --git a/src/devices/cpu/alto2/alto2cpu.cpp b/src/devices/cpu/alto2/alto2cpu.cpp
index 5b7f58e0aca..0ae70dc623b 100644
--- a/src/devices/cpu/alto2/alto2cpu.cpp
+++ b/src/devices/cpu/alto2/alto2cpu.cpp
@@ -95,10 +95,10 @@ void alto2_cpu_device::iomem_map(address_map &map)
map(0177205, 0177233).rw(FUNC(alto2_cpu_device::noop_r), FUNC(alto2_cpu_device::noop_w)); // UNUSED RANGE
map(0177234, 0177237).rw(FUNC(alto2_cpu_device::noop_r), FUNC(alto2_cpu_device::noop_w)); // { Experimental cursor control }
map(0177240, 0177257).rw(FUNC(alto2_cpu_device::noop_r), FUNC(alto2_cpu_device::noop_w)); // { Alto-II debugger }
-// AM_RANGE(0177244, 0177247) AM_READWRITE( noop_r, noop_w ) // { Graphics keyboard }
+// map(0177244, 0177247).rw(FUNC(alto2_cpu_device::noop_r), FUNC(alto2_cpu_device::noop_w)); // { Graphics keyboard }
map(0177260, 0177377).rw(FUNC(alto2_cpu_device::noop_r), FUNC(alto2_cpu_device::noop_w)); // UNUSED RANGE
// page 0377
-// AM_RANGE(0177400, 0177405) AM_READWRITE( noop_r, noop_w ) // { Maxc2 maintenance interface }
+// map(0177400, 0177405).rw(FUNC(alto2_cpu_device::noop_r), FUNC(alto2_cpu_device::noop_w)); // { Maxc2 maintenance interface }
map(0177400, 0177400).rw(FUNC(alto2_cpu_device::noop_r), FUNC(alto2_cpu_device::noop_w)); // { Alto DLS input }
map(0177401, 0177417).rw(FUNC(alto2_cpu_device::noop_r), FUNC(alto2_cpu_device::noop_w)); // UNUSED RANGE
map(0177420, 0177420).rw(FUNC(alto2_cpu_device::noop_r), FUNC(alto2_cpu_device::noop_w)); // { "" }
@@ -127,7 +127,7 @@ void alto2_cpu_device::iomem_map(address_map &map)
alto2_cpu_device::alto2_cpu_device(const machine_config& mconfig, const char* tag, device_t* owner, uint32_t clock) :
cpu_device(mconfig, ALTO2, tag, owner, clock),
- m_kb_read_callback(*this),
+ m_kb_read_callback(*this, 0177777),
m_utilout_callback(*this),
m_ucode_config("ucode", ENDIANNESS_BIG, 32, 12, -2, address_map_constructor(FUNC(alto2_cpu_device::ucode_map), this)),
m_const_config("const", ENDIANNESS_BIG, 16, 8, -1, address_map_constructor(FUNC(alto2_cpu_device::const_map), this)),
@@ -138,8 +138,6 @@ alto2_cpu_device::alto2_cpu_device(const machine_config& mconfig, const char* ta
m_ucode_ram_base(ALTO2_UCODE_PAGE_SIZE),
m_ucode_size(3*ALTO2_UCODE_PAGE_SIZE),
m_sreg_banks(1),
- m_ucode_crom(nullptr),
- m_const_data(nullptr),
m_icount(0),
m_task(0),
m_next_task(0),
@@ -794,32 +792,28 @@ device_memory_interface::space_config_vector alto2_cpu_device::memory_space_conf
void alto2_cpu_device::device_start()
{
- m_kb_read_callback.resolve_safe(0177777);
- m_utilout_callback.resolve_safe();
-
// get a pointer to the IO address space
m_iomem = &space(2);
// Decode 2 pages of micro code PROMs to CROM
// If m_cram_config == 1 or 3, only the first page will be used
- m_ucode_crom = prom_load(machine(), pl_ucode, memregion("ucode_proms")->base(), 2, 8);
+ m_ucode_crom = prom_load<uint32_t>(machine(), pl_ucode, memregion("ucode_proms")->base(), 2, 8);
// allocate micro code CRAM for max 3 pages
- m_ucode_cram = std::make_unique<uint8_t[]>(sizeof(uint32_t) * 3 * ALTO2_UCODE_PAGE_SIZE);
+ m_ucode_cram = std::make_unique<uint32_t []>(3 * ALTO2_UCODE_PAGE_SIZE);
// fill with the micro code inverted bits value
- for (offs_t offset = 0; offset < 3 * ALTO2_UCODE_PAGE_SIZE; offset++)
- *reinterpret_cast<uint32_t *>(m_ucode_cram.get() + offset * 4) = ALTO2_UCODE_INVERTED;
+ std::fill_n(m_ucode_cram.get(), 3 * ALTO2_UCODE_PAGE_SIZE, ALTO2_UCODE_INVERTED);
// decode constant PROMs to m_const_data
- m_const_data = prom_load(machine(), pl_const, memregion("const_proms")->base(), 1, 4);
+ m_const_data = prom_load<uint16_t>(machine(), pl_const, memregion("const_proms")->base(), 1, 4);
- m_ctl2k_u3 = prom_load(machine(), &pl_2kctl_u3, memregion("2kctl_u3")->base());
- m_ctl2k_u38 = prom_load(machine(), &pl_2kctl_u38, memregion("2kctl_u38")->base());
- m_ctl2k_u76 = prom_load(machine(), &pl_2kctl_u76, memregion("2kctl_u76")->base());
- m_alu_a10 = prom_load(machine(), &pl_alu_a10, memregion("alu_a10")->base());
- m_cram3k_a37 = prom_load(machine(), &pl_3kcram_a37, memregion("3kcram_a37")->base());
- m_madr_a90 = prom_load(machine(), &pl_madr_a90, memregion("madr_a90")->base());
- m_madr_a91 = prom_load(machine(), &pl_madr_a91, memregion("madr_a91")->base());
+ m_ctl2k_u3 = prom_load<uint8_t>(machine(), &pl_2kctl_u3, memregion("2kctl_u3")->base());
+ m_ctl2k_u38 = prom_load<uint8_t>(machine(), &pl_2kctl_u38, memregion("2kctl_u38")->base());
+ m_ctl2k_u76 = prom_load<uint8_t>(machine(), &pl_2kctl_u76, memregion("2kctl_u76")->base());
+ m_alu_a10 = prom_load<uint8_t>(machine(), &pl_alu_a10, memregion("alu_a10")->base());
+ m_cram3k_a37 = prom_load<uint8_t>(machine(), &pl_3kcram_a37, memregion("3kcram_a37")->base());
+ m_madr_a90 = prom_load<uint8_t>(machine(), &pl_madr_a90, memregion("madr_a90")->base());
+ m_madr_a91 = prom_load<uint8_t>(machine(), &pl_madr_a91, memregion("madr_a91")->base());
#if DEBUG_ALU_A10_PROM
// dump ALU a10 PROM after loading
@@ -1006,31 +1000,31 @@ void alto2_cpu_device::state_string_export(const device_state_entry &entry, std:
}
//! read microcode CROM or CRAM
-READ32_MEMBER ( alto2_cpu_device::crom_cram_r )
+uint32_t alto2_cpu_device::crom_cram_r(offs_t offset)
{
if (offset < m_ucode_ram_base)
- return *reinterpret_cast<uint32_t *>(m_ucode_crom + offset * 4);
- return *reinterpret_cast<uint32_t *>(m_ucode_cram.get() + (offset - m_ucode_ram_base) * 4);
+ return m_ucode_crom[offset];
+ else
+ return m_ucode_cram[offset - m_ucode_ram_base];
}
//! write microcode CROM or CRAM (CROM of course can't be written)
-WRITE32_MEMBER( alto2_cpu_device::crom_cram_w )
+void alto2_cpu_device::crom_cram_w(offs_t offset, uint32_t data)
{
- if (offset < m_ucode_ram_base)
- return;
- *reinterpret_cast<uint32_t *>(m_ucode_cram.get() + (offset - m_ucode_ram_base) * 4) = data;
+ if (offset >= m_ucode_ram_base)
+ m_ucode_cram[offset - m_ucode_ram_base] = data;
}
//! read constants PROM
-READ16_MEMBER ( alto2_cpu_device::const_r )
+uint16_t alto2_cpu_device::const_r(offs_t offset)
{
- return *reinterpret_cast<uint16_t *>(m_const_data + offset * 2);
+ return m_const_data[offset];
}
//! direct read access to the microcode CROM or CRAM
-#define RD_UCODE(addr) (addr < m_ucode_ram_base ? \
- *reinterpret_cast<uint32_t *>(m_ucode_crom + addr * 4) : \
- *reinterpret_cast<uint32_t *>(m_ucode_cram.get() + (addr - m_ucode_ram_base) * 4))
+#define RD_UCODE(addr) (((addr) < m_ucode_ram_base) ? \
+ m_ucode_crom[addr] : \
+ m_ucode_cram[(addr) - m_ucode_ram_base])
//-------------------------------------------------
// device_reset - device-specific reset
@@ -1093,14 +1087,6 @@ void alto2_cpu_device::execute_set_input(int inputnum, int state)
{
}
-void alto2_cpu_device::fatal(int exitcode, const char *format, ...)
-{
- va_list ap;
- va_start(ap, format);
- emu_fatalerror error(exitcode, format, ap);
- va_end(ap);
-}
-
/** @brief task names */
const char* alto2_cpu_device::task_name(int task)
{
@@ -1265,45 +1251,45 @@ void alto2_cpu_device::watch_write(uint32_t addr, uint32_t data)
}
#endif
-/** @brief fatal exit on unitialized dynamic phase BUS source */
+/** @brief fatal exit on uninitialized dynamic phase BUS source */
void alto2_cpu_device::bs_early_bad()
{
- fatal(9,"fatal: bad early bus source pointer for task %s, mpc:%05o bs:%s\n",
- task_name(m_task), m_mpc, bs_name(bs()));
+ throw emu_fatalerror(9,"fatal: bad early bus source pointer for task %s, mpc:%05o bs:%s\n",
+ task_name(m_task), m_mpc, bs_name(bs()));
}
-/** @brief fatal exit on unitialized latching phase BUS source */
+/** @brief fatal exit on uninitialized latching phase BUS source */
void alto2_cpu_device::bs_late_bad()
{
- fatal(9,"fatal: bad late bus source pointer for task %s, mpc:%05o bs: %s\n",
- task_name(m_task), m_mpc, bs_name(bs()));
+ throw emu_fatalerror(9,"fatal: bad late bus source pointer for task %s, mpc:%05o bs: %s\n",
+ task_name(m_task), m_mpc, bs_name(bs()));
}
-/** @brief fatal exit on unitialized dynamic phase F1 function */
+/** @brief fatal exit on uninitialized dynamic phase F1 function */
void alto2_cpu_device::f1_early_bad()
{
- fatal(9,"fatal: bad early f1 function pointer for task %s, mpc:%05o f1: %s\n",
- task_name(m_task), m_mpc, f1_name(f1()));
+ throw emu_fatalerror(9,"fatal: bad early f1 function pointer for task %s, mpc:%05o f1: %s\n",
+ task_name(m_task), m_mpc, f1_name(f1()));
}
-/** @brief fatal exit on unitialized latching phase F1 function */
+/** @brief fatal exit on uninitialized latching phase F1 function */
void alto2_cpu_device::f1_late_bad()
{
- fatal(9,"fatal: bad late f1 function pointer for task %s, mpc:%05o f1: %s\n",
- task_name(m_task), m_mpc, f1_name(f1()));
+ throw emu_fatalerror(9,"fatal: bad late f1 function pointer for task %s, mpc:%05o f1: %s\n",
+ task_name(m_task), m_mpc, f1_name(f1()));
}
-/** @brief fatal exit on unitialized dynamic phase F2 function */
+/** @brief fatal exit on uninitialized dynamic phase F2 function */
void alto2_cpu_device::f2_early_bad()
{
- fatal(9,"fatal: bad early f2 function pointer for task %s, mpc:%05o f2: %s\n",
- task_name(m_task), m_mpc, f2_name(f2()));
+ throw emu_fatalerror(9,"fatal: bad early f2 function pointer for task %s, mpc:%05o f2: %s\n",
+ task_name(m_task), m_mpc, f2_name(f2()));
}
-/** @brief fatal exit on unitialized latching phase F2 function */
+/** @brief fatal exit on uninitialized latching phase F2 function */
void alto2_cpu_device::f2_late_bad()
{
- fatal(9,"fatal: bad late f2 function pointer for task %s, mpc:%05o f2: %s\n",
+ throw emu_fatalerror(9,"fatal: bad late f2 function pointer for task %s, mpc:%05o f2: %s\n",
task_name(m_task), m_mpc, f2_name(f2()));
}
@@ -1372,7 +1358,7 @@ static const char* memory_range_name(offs_t offset)
/**
* @brief read the open bus for unused MMIO range
*/
-READ16_MEMBER( alto2_cpu_device::noop_r )
+uint16_t alto2_cpu_device::noop_r(offs_t offset)
{
LOG((this,LOG_CPU,0," MMIO rd %s\n", memory_range_name(offset)));
return 0177777;
@@ -1381,7 +1367,7 @@ READ16_MEMBER( alto2_cpu_device::noop_r )
/**
* @brief write nowhere for unused MMIO range
*/
-WRITE16_MEMBER( alto2_cpu_device::noop_w )
+void alto2_cpu_device::noop_w(offs_t offset, uint16_t data)
{
LOG((this,LOG_CPU,0," MMIO wr %s\n", memory_range_name(offset)));
}
@@ -1391,7 +1377,7 @@ WRITE16_MEMBER( alto2_cpu_device::noop_w )
*
* The bank registers are stored in a 16x4-bit RAM 74S189.
*/
-READ16_MEMBER( alto2_cpu_device::bank_reg_r )
+uint16_t alto2_cpu_device::bank_reg_r(offs_t offset)
{
int task = offset & 017;
int bank = m_bank_reg[task] | 0177760;
@@ -1403,7 +1389,7 @@ READ16_MEMBER( alto2_cpu_device::bank_reg_r )
*
* The bank registers are stored in a 16x4-bit RAM 74S189.
*/
-WRITE16_MEMBER( alto2_cpu_device::bank_reg_w )
+void alto2_cpu_device::bank_reg_w(offs_t offset, uint16_t data)
{
int task = offset & 017;
m_bank_reg[task] = data & 017;
@@ -1768,7 +1754,7 @@ void alto2_cpu_device::f1_early_task()
return;
}
}
- fatal(3, "no tasks requesting service\n");
+ throw emu_fatalerror(3, "no tasks requesting service\n");
#endif /* !USE_PRIO_F9318 */
}
@@ -2297,7 +2283,7 @@ void alto2_cpu_device::execute_run()
* the bitclk sequence by leaving m_bitclk_time at -1.
*/
m_bitclk_time -= ucycle;
- disk_bitclk(nullptr, m_bitclk_index);
+ disk_bitclk(m_bitclk_index);
}
m_mpc = m_next; // next instruction's micro program counter
@@ -2346,7 +2332,7 @@ void alto2_cpu_device::execute_run()
// The constant memory is gated to the bus by F1 == f1_const, F2 == f2_const, or BS >= 4
if (!do_bs || bs() >= bs_task_4) {
const uint32_t addr = 8 * m_rsel + bs();
- const uint16_t data = m_const_data[2*addr] | (m_const_data[2*addr+1] << 8);
+ const uint16_t data = m_const_data[addr];
m_bus &= data;
LOG((this,LOG_CPU,2," %#o; BUS &= %#o CONST[%03o]\n", m_bus, data, addr));
}
diff --git a/src/devices/cpu/alto2/alto2cpu.h b/src/devices/cpu/alto2/alto2cpu.h
index e0fbc075895..d8817978ba8 100644
--- a/src/devices/cpu/alto2/alto2cpu.h
+++ b/src/devices/cpu/alto2/alto2cpu.h
@@ -5,15 +5,13 @@
* Xerox AltoII CPU core interface
*
*****************************************************************************/
-#ifndef MAME_DEVICES_CPU_ALTO2_H
-#define MAME_DEVICES_CPU_ALTO2_H
+#ifndef MAME_CPU_ALTO2_ALTO2CPU_H
+#define MAME_CPU_ALTO2_ALTO2CPU_H
#pragma once
#include "machine/diablo_hd.h"
-#include "debugger.h"
-
#define ALTO2_TAG "alto2"
/**
@@ -209,17 +207,16 @@ public:
protected:
//! device-level override for start
- virtual void device_start() override;
+ virtual void device_start() override ATTR_COLD;
//! device-level override for reset
- virtual void device_reset() override;
+ virtual void device_reset() override ATTR_COLD;
//! device-level override for post reset
void interface_post_reset() override;
//! device_execute_interface overrides
- virtual uint32_t execute_min_cycles() const override { return 1; }
- virtual uint32_t execute_max_cycles() const override { return 1; }
- virtual uint32_t execute_input_lines() const override { return 1; }
+ virtual uint32_t execute_min_cycles() const noexcept override { return 1; }
+ virtual uint32_t execute_max_cycles() const noexcept override { return 1; }
virtual void execute_run() override;
virtual void execute_set_input(int inputnum, int state) override;
@@ -227,7 +224,7 @@ protected:
virtual space_config_vector memory_space_config() const override;
//! device (P)ROMs
- virtual const tiny_rom_entry *device_rom_region() const override;
+ virtual const tiny_rom_entry *device_rom_region() const override ATTR_COLD;
//! device_state_interface overrides
virtual void state_string_export(const device_state_entry &entry, std::string &str) const override;
@@ -235,8 +232,6 @@ protected:
virtual std::unique_ptr<util::disasm_interface> create_disassembler() override;
private:
- void fatal(int level, const char *format, ...);
-
devcb_read16 m_kb_read_callback;
devcb_write16 m_utilout_callback;
@@ -253,28 +248,28 @@ private:
uint32_t m_ucode_size; //!< Size of both, CROM and CRAM together
uint32_t m_sreg_banks; //!< Number of S register banks; derived from m_cram_config
- uint8_t* m_ucode_crom;
- std::unique_ptr<uint8_t[]> m_ucode_cram;
- uint8_t* m_const_data;
+ std::unique_ptr<uint32_t[]> m_ucode_crom;
+ std::unique_ptr<uint32_t[]> m_ucode_cram;
+ std::unique_ptr<uint16_t[]> m_const_data;
- void ucode_map(address_map &map);
- void const_map(address_map &map);
- void iomem_map(address_map &map);
+ void ucode_map(address_map &map) ATTR_COLD;
+ void const_map(address_map &map) ATTR_COLD;
+ void iomem_map(address_map &map) ATTR_COLD;
//! read microcode CROM or CRAM, depending on m_ucode_ram_base
- DECLARE_READ32_MEMBER ( crom_cram_r );
+ uint32_t crom_cram_r(offs_t offset);
//! write microcode CRAM, depending on m_ucode_ram_base (ignore writes to CROM)
- DECLARE_WRITE32_MEMBER( crom_cram_w );
+ void crom_cram_w(offs_t offset, uint32_t data);
//! read constants PROM
- DECLARE_READ16_MEMBER ( const_r );
+ uint16_t const_r(offs_t offset);
//! read i/o space RAM
- DECLARE_READ16_MEMBER ( ioram_r );
+ uint16_t ioram_r(offs_t offset);
//!< write i/o space RAM
- DECLARE_WRITE16_MEMBER( ioram_w );
+ void ioram_w(offs_t offset, uint16_t data);
int m_icount;
@@ -657,7 +652,7 @@ private:
* access it. Also both, address and data lines, are inverted.
* </PRE>
*/
- uint8_t* m_ctl2k_u3;
+ std::unique_ptr<uint8_t[]> m_ctl2k_u3;
/**
* @brief 2KCTL PROM u38; 82S23; 32x8 bit
@@ -706,7 +701,7 @@ private:
* B7 9 NEXT[06]'
* </PRE>
*/
- uint8_t* m_ctl2k_u38;
+ std::unique_ptr<uint8_t[]> m_ctl2k_u38;
//! output lines of the 2KCTL U38 PROM
enum {
@@ -778,22 +773,22 @@ private:
* depending on the current NEXT[01]' level.
* </PRE>
*/
- uint8_t* m_ctl2k_u76;
+ std::unique_ptr<uint8_t[]> m_ctl2k_u76;
/**
* @brief 3k CRAM PROM a37
*/
- uint8_t* m_cram3k_a37;
+ std::unique_ptr<uint8_t[]> m_cram3k_a37;
/**
* @brief memory addressing PROM a64
*/
- uint8_t* m_madr_a64;
+ std::unique_ptr<uint8_t[]> m_madr_a64;
/**
* @brief memory addressing PROM a65
*/
- uint8_t* m_madr_a65;
+ std::unique_ptr<uint8_t[]> m_madr_a65;
/**
* @brief unused PROM a90
@@ -808,7 +803,7 @@ private:
*
* I haven't found yet where KP3-KP5 are used
*/
- uint8_t* m_madr_a90;
+ std::unique_ptr<uint8_t[]> m_madr_a90;
/**
* @brief unused PROM a91
@@ -835,12 +830,12 @@ private:
* KE(6) KB(^L) KB(RTN) KB(") KB(/) KB(S3) KB(<-) KB(]) KB(\)
* KE(7) KB(S1) KB(DEL) KB(S2) KB(LF) KB(S4) KB(S5) KB(BW) KB(BS)
*/
- uint8_t* m_madr_a91;
+ std::unique_ptr<uint8_t[]> m_madr_a91;
/**
* @brief ALU function to 74181 operation lookup PROM
*/
- uint8_t* m_alu_a10;
+ std::unique_ptr<uint8_t[]> m_alu_a10;
//! output lines of the ALU a10 PROM
enum {
@@ -868,20 +863,20 @@ private:
void hard_reset(); //!< reset the various registers
void soft_reset(); //!< soft reset
- void bs_early_bad(); //! bs dummy early function
- void bs_late_bad(); //! bs dummy late function
+ [[noreturn]] void bs_early_bad(); //! bs dummy early function
+ [[noreturn]] void bs_late_bad(); //! bs dummy late function
- void f1_early_bad(); //! f1 dummy early function
- void f1_late_bad(); //! f1 dummy late function
+ [[noreturn]] void f1_early_bad(); //! f1 dummy early function
+ [[noreturn]] void f1_late_bad(); //! f1 dummy late function
- void f2_early_bad(); //! f2 dummy early function
- void f2_late_bad(); //! f2 dummy late function
+ [[noreturn]] void f2_early_bad(); //! f2 dummy early function
+ [[noreturn]] void f2_late_bad(); //! f2 dummy late function
- DECLARE_READ16_MEMBER( noop_r ); //!< read open bus (0177777)
- DECLARE_WRITE16_MEMBER( noop_w ); //!< write open bus
+ uint16_t noop_r (offs_t offset); //!< read open bus (0177777)
+ void noop_w(offs_t offset, uint16_t data); //!< write open bus
- DECLARE_READ16_MEMBER( bank_reg_r ); //!< read bank register in memory mapped I/O range
- DECLARE_WRITE16_MEMBER( bank_reg_w ); //!< write bank register in memory mapped I/O range
+ uint16_t bank_reg_r(offs_t offset); //!< read bank register in memory mapped I/O range
+ void bank_reg_w(offs_t offset, uint16_t data); //!< write bank register in memory mapped I/O range
void bs_early_read_r(); //!< bus source: drive bus by R register
void bs_early_load_r(); //!< bus source: load R places 0 on the BUS
@@ -937,4 +932,4 @@ private:
DECLARE_DEVICE_TYPE(ALTO2, alto2_cpu_device)
-#endif // MAME_DEVICES_CPU_ALTO2_H
+#endif // MAME_CPU_ALTO2_ALTO2CPU_H
diff --git a/src/devices/cpu/am29000/am29000.cpp b/src/devices/cpu/am29000/am29000.cpp
index a3f0c4ca91c..d4039c18916 100644
--- a/src/devices/cpu/am29000/am29000.cpp
+++ b/src/devices/cpu/am29000/am29000.cpp
@@ -15,7 +15,6 @@
***************************************************************************/
#include "emu.h"
-#include "debugger.h"
#include "am29000.h"
#include "am29dasm.h"
@@ -108,7 +107,7 @@ am29000_cpu_device::am29000_cpu_device(const machine_config &mconfig, const char
m_fpe = 0;
m_inte = 0;
m_fps = 0;
- memset( m_exception_queue, 0, sizeof( m_exception_queue) );;
+ memset( m_exception_queue, 0, sizeof( m_exception_queue) );
m_irq_active = 0;
m_irq_lines = 0;
m_exec_ir = 0;
@@ -130,11 +129,12 @@ device_memory_interface::space_config_vector am29000_cpu_device::memory_space_co
void am29000_cpu_device::device_start()
{
- m_program = &space(AS_PROGRAM);
- m_cache = m_program->cache<2, 0, ENDIANNESS_BIG>();
- m_data = &space(AS_DATA);
- m_datacache = m_data->cache<2, 0, ENDIANNESS_BIG>();
- m_io = &space(AS_IO);
+ space(AS_PROGRAM).cache(m_cache);
+ space(AS_PROGRAM).specific(m_program);
+ space(AS_DATA).cache(m_datacache);
+ space(AS_DATA).specific(m_data);
+ space(AS_IO).specific(m_io);
+
m_cfg = (PRL_AM29000 | PRL_REV_D) << CFG_PRL_SHIFT;
/* Register state for saving */
@@ -511,7 +511,7 @@ uint32_t am29000_cpu_device::read_program_word(uint32_t address)
{
/* TODO: ROM enable? */
if (m_cps & CPS_PI || m_cps & CPS_RE)
- return m_cache->read_dword(address);
+ return m_cache.read_dword(address);
else
{
fatalerror("Am29000 instruction MMU translation enabled!\n");
@@ -628,7 +628,7 @@ void am29000_cpu_device::fetch_decode()
void am29000_cpu_device::execute_run()
{
- uint32_t call_debugger = (machine().debug_flags & DEBUG_FLAG_ENABLED) != 0;
+ const bool call_debugger = debugger_enabled();
external_irq_check();
@@ -658,7 +658,7 @@ void am29000_cpu_device::execute_run()
if (m_cfg & CFG_VF)
{
uint32_t vaddr = m_vab | m_exception_queue[0] * 4;
- uint32_t vect = m_datacache->read_dword(vaddr);
+ uint32_t vect = m_datacache.read_dword(vaddr);
m_pc = vect & ~3;
m_next_pc = m_pc;
diff --git a/src/devices/cpu/am29000/am29000.h b/src/devices/cpu/am29000/am29000.h
index 4061fadbe64..d95efc1f587 100644
--- a/src/devices/cpu/am29000/am29000.h
+++ b/src/devices/cpu/am29000/am29000.h
@@ -440,13 +440,12 @@ public:
protected:
// device-level overrides
- virtual void device_start() override;
- virtual void device_reset() override;
+ virtual void device_start() override ATTR_COLD;
+ virtual void device_reset() override ATTR_COLD;
// device_execute_interface overrides
- virtual uint32_t execute_min_cycles() const override { return 1; }
- virtual uint32_t execute_max_cycles() const override { return 2; }
- virtual uint32_t execute_input_lines() const override { return 1; }
+ virtual uint32_t execute_min_cycles() const noexcept override { return 1; }
+ virtual uint32_t execute_max_cycles() const noexcept override { return 2; }
virtual void execute_run() override;
virtual void execute_set_input(int inputnum, int state) override;
@@ -629,12 +628,11 @@ protected:
uint32_t m_exec_pc;
uint32_t m_next_pc;
- address_space *m_program;
- memory_access_cache<2, 0, ENDIANNESS_BIG> *m_cache;
- address_space *m_data;
-
- memory_access_cache<2, 0, ENDIANNESS_BIG> *m_datacache;
- address_space *m_io;
+ memory_access<32, 2, 0, ENDIANNESS_BIG>::cache m_cache;
+ memory_access<32, 2, 0, ENDIANNESS_BIG>::specific m_program;
+ memory_access<32, 2, 0, ENDIANNESS_BIG>::cache m_datacache;
+ memory_access<32, 2, 0, ENDIANNESS_BIG>::specific m_data;
+ memory_access<32, 2, 0, ENDIANNESS_BIG>::specific m_io;
typedef void ( am29000_cpu_device::*opcode_func ) ();
struct op_info {
diff --git a/src/devices/cpu/am29000/am29dasm.cpp b/src/devices/cpu/am29000/am29dasm.cpp
index 7e69544ab2c..1751b3779c8 100644
--- a/src/devices/cpu/am29000/am29dasm.cpp
+++ b/src/devices/cpu/am29000/am29dasm.cpp
@@ -212,17 +212,17 @@ offs_t am29000_disassembler::disassemble(std::ostream &stream, offs_t pc, const
case 0x9f: util::stream_format(stream, "inv"); break;
case 0xa0: util::stream_format(stream, "jmp $%04x", pc + OP_SJMP); break;
case 0xa1: util::stream_format(stream, "jmp $%04x", OP_IJMP); break;
- case 0xa4: case 0xa5: util::stream_format(stream, "jmpf %s", TYPE_4); break;
- case 0xa8: case 0xa9: util::stream_format(stream, "call %s", TYPE_4); break;
- case 0xac: case 0xad: util::stream_format(stream, "jmpt %s", TYPE_4); break;
- case 0xb4: case 0xb5: util::stream_format(stream, "jmpfdec %s", TYPE_4); break;
+ case 0xa4: case 0xa5: util::stream_format(stream, "jmpf %s", TYPE_4); flags = STEP_COND | step_over_extra(1); break;
+ case 0xa8: case 0xa9: util::stream_format(stream, "call %s", TYPE_4); flags = STEP_OVER | step_over_extra(1); break;
+ case 0xac: case 0xad: util::stream_format(stream, "jmpt %s", TYPE_4); flags = STEP_COND | step_over_extra(1); break;
+ case 0xb4: case 0xb5: util::stream_format(stream, "jmpfdec %s", TYPE_4); flags = STEP_COND | step_over_extra(1); break;
case 0xb6: util::stream_format(stream, "mftlb r%d, r%d", OP_RC, OP_RA); break;
case 0xbe: util::stream_format(stream, "mttlb r%d, r%d", OP_RA, OP_RB); break;
case 0xc0: util::stream_format(stream, "jmpi r%d", OP_RB); break;
- case 0xc4: util::stream_format(stream, "jmpfi r%d, r%d", OP_RA, OP_RB); break;
+ case 0xc4: util::stream_format(stream, "jmpfi r%d, r%d", OP_RA, OP_RB); flags = STEP_COND | step_over_extra(1); break;
case 0xc6: util::stream_format(stream, "mfsr r%d, %s", OP_RC, get_spr(OP_SA)); break;
- case 0xc8: util::stream_format(stream, "calli r%d, r%d", OP_RA, OP_RB); break;
- case 0xcc: util::stream_format(stream, "jmpti r%d, r%d", OP_RA, OP_RB); break;
+ case 0xc8: util::stream_format(stream, "calli r%d, r%d", OP_RA, OP_RB); flags = STEP_OVER | step_over_extra(1); break;
+ case 0xcc: util::stream_format(stream, "jmpti r%d, r%d", OP_RA, OP_RB); flags = STEP_COND | step_over_extra(1); break;
case 0xce: util::stream_format(stream, "mtsr %s, r%d", get_spr(OP_SA), OP_RB); break;
case 0xd7: util::stream_format(stream, "emulate %s", TYPE_5); break;
case 0xde: util::stream_format(stream, "multm %s", TYPE_2); break;
diff --git a/src/devices/cpu/am29000/am29ops.h b/src/devices/cpu/am29000/am29ops.h
index 3c44c506077..d594a7485ab 100644
--- a/src/devices/cpu/am29000/am29ops.h
+++ b/src/devices/cpu/am29000/am29ops.h
@@ -390,7 +390,6 @@ void am29000_cpu_device::MUL()
uint32_t a = GET_RA_VAL;
uint32_t b = INST_M_BIT ? I8 : GET_RB_VAL;
uint32_t r;
- uint64_t v;
uint32_t sign;
if (m_q & 1)
@@ -404,10 +403,9 @@ void am29000_cpu_device::MUL()
sign = b >> 31;
}
- v = ((((uint64_t)r << 32) | m_q) >> 1) | ((uint64_t)sign << 63);
- m_q = v & 0xffffffff;
-
- m_r[RC] = v >> 32;
+ // Shift combined value right one bit position, entering sign into bit 31 of destination
+ m_r[RC] = (r >> 1) | (sign << 31);
+ m_q = (m_q >> 1) | (r << 31);
}
void am29000_cpu_device::MULL()
@@ -416,7 +414,6 @@ void am29000_cpu_device::MULL()
uint32_t a = GET_RA_VAL;
uint32_t b = INST_M_BIT ? I8 : GET_RB_VAL;
uint32_t r;
- uint64_t v;
uint32_t sign;
if (m_q & 1)
@@ -430,10 +427,9 @@ void am29000_cpu_device::MULL()
sign = b >> 31;
}
- v = ((((uint64_t)r << 32) | m_q) >> 1) | ((uint64_t)sign << 63);
- m_q = v & 0xffffffff;
-
- m_r[RC] = v >> 32;
+ // Shift combined value right one bit position, entering sign into bit 31 of destination
+ m_r[RC] = (r >> 1) | (sign << 31);
+ m_q = (m_q >> 1) | (r << 31);
}
void am29000_cpu_device::MULU()
@@ -442,7 +438,6 @@ void am29000_cpu_device::MULU()
uint32_t a = GET_RA_VAL;
uint32_t b = INST_M_BIT ? I8 : GET_RB_VAL;
uint32_t r;
- uint64_t v;
uint32_t c;
if (m_q & 1)
@@ -456,10 +451,9 @@ void am29000_cpu_device::MULU()
c = 0;
}
- v = ((((uint64_t)r << 32) | m_q) >> 1) | ((uint64_t)c << 63);
- m_q = v & 0xffffffff;
-
- m_r[RC] = v >> 32;
+ // Shift combined value right one bit position, entering carry into bit 31 of destination
+ m_r[RC] = (r >> 1) | (c << 31);
+ m_q = (m_q >> 1) | (r << 31);
}
void am29000_cpu_device::DIVIDE()
@@ -479,7 +473,6 @@ void am29000_cpu_device::DIVIDU()
void am29000_cpu_device::DIV0()
{
uint32_t b = INST_M_BIT ? I8: GET_RB_VAL;
- uint64_t v;
if (!FREEZE_MODE)
{
@@ -487,11 +480,9 @@ void am29000_cpu_device::DIV0()
SET_ALU_N(b);
}
- v = (((uint64_t)b << 32) | m_q) << 1;
-
- m_q = v & 0xffffffff;
-
- m_r[RC] = v >> 32;
+ // Shift combined value left one bit position, zeroing bit 0 of Q
+ m_r[RC] = (b << 1) | (m_q >> 31);
+ m_q <<= 1;
}
void am29000_cpu_device::DIV()
@@ -500,7 +491,6 @@ void am29000_cpu_device::DIV()
uint32_t b = INST_M_BIT ? I8: GET_RB_VAL;
uint32_t c;
uint32_t r;
- uint64_t r64;
uint32_t df;
if (m_alu & ALU_DF)
@@ -524,10 +514,9 @@ void am29000_cpu_device::DIV()
SET_ALU_N(r);
}
- r64 = ((((uint64_t)r << 32) | m_q) << 1) | df;
- m_q = r64 & 0xffffffff;
-
- m_r[RC] = r64 >> 32;
+ // Shift combined value left one bit position, entering DF into bit 0 of Q
+ m_r[RC] = (r << 1) | (m_q >> 31);
+ m_q = (m_q << 1) | df;
}
void am29000_cpu_device::DIVL()
@@ -947,7 +936,7 @@ void am29000_cpu_device::LOAD()
return;
}
- r = m_data->read_dword(addr);
+ r = m_data.read_dword(addr);
}
}
@@ -1013,7 +1002,7 @@ void am29000_cpu_device::LOADM()
return;
}
- r = m_data->read_dword(addr);
+ r = m_data.read_dword(addr);
}
}
@@ -1035,7 +1024,7 @@ void am29000_cpu_device::LOADM()
for (int32_t cnt = 0; cnt <= GET_CHC_CR; ++cnt)
{
- m_r[r] = m_data->read_dword(addr);
+ m_r[r] = m_data.read_dword(addr);
// SET_CHC_CR(cnt - 1);
addr += 4;
@@ -1076,7 +1065,7 @@ void am29000_cpu_device::STORE()
}
}
- m_data->write_dword(addr, m_r[RA]);
+ m_data.write_dword(addr, m_r[RA]);
if (!FREEZE_MODE)
{
@@ -1148,7 +1137,7 @@ void am29000_cpu_device::STOREM()
for (int32_t cnt = 0; cnt <= GET_CHC_CR; ++cnt)
{
- m_data->write_dword(addr, m_r[r]);
+ m_data.write_dword(addr, m_r[r]);
addr += 4;
@@ -1396,7 +1385,7 @@ void am29000_cpu_device::CLZ()
{
uint32_t b = INST_M_BIT ? I8: GET_RB_VAL;
- m_r[RC] = count_leading_zeros(b);
+ m_r[RC] = count_leading_zeros_32(b);
}
void am29000_cpu_device::SETIP()
diff --git a/src/devices/cpu/amis2000/amis2000.cpp b/src/devices/cpu/amis2000/amis2000.cpp
index 70df8370ae4..5911cb2543b 100644
--- a/src/devices/cpu/amis2000/amis2000.cpp
+++ b/src/devices/cpu/amis2000/amis2000.cpp
@@ -3,7 +3,6 @@
/*
American Microsystems, Inc.(AMI) S2000-family 4-bit MCU cores, introduced late 1970s
- Overall functionality is similar to (and probably derived from) NEC uCOM-4.
References:
- AMI MOS Products Catalog 1979/1980
@@ -21,7 +20,6 @@
#include "emu.h"
#include "amis2000.h"
#include "amis2000d.h"
-#include "debugger.h"
// S2000 is the most basic one, 64 nibbles internal RAM and 1KB internal ROM
@@ -61,16 +59,32 @@ void amis2000_base_device::data_80x4(address_map &map)
// device definitions
-amis2000_cpu_device::amis2000_cpu_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock)
- : amis2000_base_device(mconfig, AMI_S2000, tag, owner, clock, 2, 10, 3, 13, address_map_constructor(FUNC(amis2000_cpu_device::program_1k), this), 6, address_map_constructor(FUNC(amis2000_cpu_device::data_64x4), this))
+amis2000_base_device::amis2000_base_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, u32 clock, u8 bu_bits, u8 callstack_bits, u8 callstack_depth, int prgwidth, address_map_constructor program, int datawidth, address_map_constructor data) :
+ cpu_device(mconfig, type, tag, owner, clock),
+ m_program_config("program", ENDIANNESS_BIG, 8, prgwidth, 0, program),
+ m_data_config("data", ENDIANNESS_BIG, 8, datawidth, 0, data),
+ m_bu_bits(bu_bits),
+ m_callstack_bits(callstack_bits),
+ m_callstack_depth(callstack_depth),
+ m_7seg_table(nullptr),
+ m_read_k(*this, 0xf),
+ m_read_i(*this, 0xf),
+ m_read_d(*this, 0),
+ m_write_d(*this),
+ m_write_a(*this),
+ m_write_f(*this)
{ }
-amis2150_cpu_device::amis2150_cpu_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock)
- : amis2000_base_device(mconfig, AMI_S2150, tag, owner, clock, 3, 11, 3, 13, address_map_constructor(FUNC(amis2150_cpu_device::program_1_5k), this), 7, address_map_constructor(FUNC(amis2150_cpu_device::data_80x4), this))
+amis2000_cpu_device::amis2000_cpu_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock) :
+ amis2000_base_device(mconfig, AMI_S2000, tag, owner, clock, 2, 10, 3, 13, address_map_constructor(FUNC(amis2000_cpu_device::program_1k), this), 6, address_map_constructor(FUNC(amis2000_cpu_device::data_64x4), this))
{ }
-amis2152_cpu_device::amis2152_cpu_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock)
- : amis2000_base_device(mconfig, AMI_S2152, tag, owner, clock, 3, 11, 3, 13, address_map_constructor(FUNC(amis2152_cpu_device::program_1_5k), this), 7, address_map_constructor(FUNC(amis2152_cpu_device::data_80x4), this))
+amis2150_cpu_device::amis2150_cpu_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock) :
+ amis2000_base_device(mconfig, AMI_S2150, tag, owner, clock, 3, 11, 3, 13, address_map_constructor(FUNC(amis2150_cpu_device::program_1_5k), this), 7, address_map_constructor(FUNC(amis2150_cpu_device::data_80x4), this))
+{ }
+
+amis2152_cpu_device::amis2152_cpu_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock) :
+ amis2000_base_device(mconfig, AMI_S2152, tag, owner, clock, 3, 11, 3, 13, address_map_constructor(FUNC(amis2152_cpu_device::program_1_5k), this), 7, address_map_constructor(FUNC(amis2152_cpu_device::data_80x4), this))
{ }
device_memory_interface::space_config_vector amis2000_base_device::memory_space_config() const
@@ -114,24 +128,11 @@ std::unique_ptr<util::disasm_interface> amis2000_base_device::create_disassemble
// device_start - device-specific startup
//-------------------------------------------------
-enum
-{
- S2000_PC = STATE_GENPC, S2000_BL = 0, S2000_BU,
- S2000_ACC, S2000_E, S2000_CY
-};
-
void amis2000_base_device::device_start()
{
m_program = &space(AS_PROGRAM);
m_data = &space(AS_DATA);
- m_read_k.resolve_safe(0xf);
- m_read_i.resolve_safe(0xf);
- m_read_d.resolve_safe(0);
- m_write_d.resolve_safe();
- m_write_a.resolve_safe();
- m_write_f.resolve_safe();
-
m_bu_mask = (1 << m_bu_bits) - 1;
m_callstack_mask = (1 << m_callstack_bits) - 1;
@@ -176,16 +177,18 @@ void amis2000_base_device::device_start()
save_item(NAME(m_a));
// register state for debugger
- state_add(S2000_PC, "PC", m_pc ).formatstr("%04X");
- state_add(S2000_BL, "BL", m_bl ).formatstr("%01X");
- state_add(S2000_BU, "BU", m_bu ).formatstr("%01X");
- state_add(S2000_ACC, "ACC", m_acc ).formatstr("%01X");
- state_add(S2000_E, "E", m_e ).formatstr("%01X");
- state_add(S2000_CY, "CY", m_carry ).formatstr("%01X");
-
- state_add(STATE_GENPCBASE, "CURPC", m_pc).noshow();
+ state_add(STATE_GENPC, "GENPC", m_pc).formatstr("%04X").noshow();
+ state_add(STATE_GENPCBASE, "CURPC", m_pc).formatstr("%04X").noshow();
state_add(STATE_GENFLAGS, "CURFLAGS", m_f).formatstr("%6s").noshow();
+ m_state_count = 0;
+ state_add(++m_state_count, "PC", m_pc).formatstr("%04X"); // 1
+ state_add(++m_state_count, "BL", m_bl).formatstr("%01X"); // 2
+ state_add(++m_state_count, "BU", m_bu).formatstr("%01X"); // 3
+ state_add(++m_state_count, "ACC", m_acc).formatstr("%01X"); // 4
+ state_add(++m_state_count, "E", m_e).formatstr("%01X"); // 5
+ state_add(++m_state_count, "CY", m_carry).formatstr("%01X"); // 6
+
set_icountptr(m_icount);
}
@@ -194,7 +197,7 @@ void amis2152_cpu_device::device_start()
{
amis2000_base_device::device_start();
- m_d2f_timer = machine().scheduler().timer_alloc(timer_expired_delegate(FUNC(amis2152_cpu_device::d2f_timer_cb), this));
+ m_d2f_timer = timer_alloc(FUNC(amis2152_cpu_device::d2f_timer_cb), this);
// zerofill
m_d2f_latch = 0;
@@ -250,7 +253,9 @@ void amis2000_base_device::execute_run()
// remember previous opcode
m_prev_op = m_op;
- debugger_instruction_hook(m_pc);
+ // fetch next opcode
+ if (!m_skip)
+ debugger_instruction_hook(m_pc);
m_op = m_program->read_byte(m_pc);
m_pc = (m_pc + 1) & 0x1fff;
@@ -332,6 +337,6 @@ void amis2000_base_device::execute_run()
}
break; // 0xff
- } // big switch
+ } // 0xf0
}
}
diff --git a/src/devices/cpu/amis2000/amis2000.h b/src/devices/cpu/amis2000/amis2000.h
index 58665c7f6bc..18f6a8baf70 100644
--- a/src/devices/cpu/amis2000/amis2000.h
+++ b/src/devices/cpu/amis2000/amis2000.h
@@ -32,40 +32,24 @@ public:
// uncustomizable, but wildfire proves to be an exception to that rule.
void set_7seg_table(const u8 *ptr) { m_7seg_table = ptr; } // d0=A, d1=B, etc.
- void data_64x4(address_map &map);
- void data_80x4(address_map &map);
- void program_1_5k(address_map &map);
- void program_1k(address_map &map);
+ void data_64x4(address_map &map) ATTR_COLD;
+ void data_80x4(address_map &map) ATTR_COLD;
+ void program_1_5k(address_map &map) ATTR_COLD;
+ void program_1k(address_map &map) ATTR_COLD;
protected:
// construction/destruction
- amis2000_base_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, u32 clock, u8 bu_bits, u8 callstack_bits, u8 callstack_depth, int prgwidth, address_map_constructor program, int datawidth, address_map_constructor data)
- : cpu_device(mconfig, type, tag, owner, clock)
- , m_program_config("program", ENDIANNESS_BIG, 8, prgwidth, 0, program)
- , m_data_config("data", ENDIANNESS_BIG, 8, datawidth, 0, data)
- , m_bu_bits(bu_bits)
- , m_callstack_bits(callstack_bits)
- , m_callstack_depth(callstack_depth)
- , m_7seg_table(nullptr)
- , m_read_k(*this)
- , m_read_i(*this)
- , m_read_d(*this)
- , m_write_d(*this)
- , m_write_a(*this)
- , m_write_f(*this)
- {
- }
+ amis2000_base_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, u32 clock, u8 bu_bits, u8 callstack_bits, u8 callstack_depth, int prgwidth, address_map_constructor program, int datawidth, address_map_constructor data);
// device-level overrides
- virtual void device_start() override;
- virtual void device_reset() override;
+ virtual void device_start() override ATTR_COLD;
+ virtual void device_reset() override ATTR_COLD;
// device_execute_interface overrides
- virtual u64 execute_clocks_to_cycles(u64 clocks) const override { return (clocks + 4 - 1) / 4; } // 4 cycles per machine cycle
- virtual u64 execute_cycles_to_clocks(u64 cycles) const override { return (cycles * 4); } // "
- virtual u32 execute_min_cycles() const override { return 1; }
- virtual u32 execute_max_cycles() const override { return 2; }
- virtual u32 execute_input_lines() const override { return 1; }
+ virtual u64 execute_clocks_to_cycles(u64 clocks) const noexcept override { return (clocks + 4 - 1) / 4; } // 4 cycles per machine cycle
+ virtual u64 execute_cycles_to_clocks(u64 cycles) const noexcept override { return (cycles * 4); } // "
+ virtual u32 execute_min_cycles() const noexcept override { return 1; }
+ virtual u32 execute_max_cycles() const noexcept override { return 2; }
virtual void execute_run() override;
// device_memory_interface overrides
@@ -82,13 +66,15 @@ protected:
address_space *m_program;
address_space *m_data;
+ int m_icount;
+ int m_state_count;
+
u8 m_bu_bits;
u16 m_bu_mask;
u8 m_callstack_bits; // number of program counter bits held in callstack
u16 m_callstack_mask;
u8 m_callstack_depth; // callstack levels: 3 on 2000/2150, 5 on 2200/2400
u16 m_callstack[5]; // max 5
- int m_icount;
u16 m_pc; // 13-bit program counter
u8 m_ppr; // prepared page register (PP 1)
u8 m_pbr; // prepared bank register (PP 2)
@@ -205,8 +191,8 @@ public:
protected:
// device-level overrides
- virtual void device_start() override;
- virtual void device_reset() override;
+ virtual void device_start() override ATTR_COLD;
+ virtual void device_reset() override ATTR_COLD;
// digital-to-frequency converter
u8 m_d2f_latch;
diff --git a/src/devices/cpu/amis2000/amis2000d.cpp b/src/devices/cpu/amis2000/amis2000d.cpp
index cff6155fa0a..6f9d95d2a70 100644
--- a/src/devices/cpu/amis2000/amis2000d.cpp
+++ b/src/devices/cpu/amis2000/amis2000d.cpp
@@ -9,6 +9,19 @@
#include "emu.h"
#include "amis2000d.h"
+
+// common lookup tables
+
+enum amis2000_disassembler::e_mnemonics : unsigned
+{
+ mLAB = 0, mLAE, mLAI, mLBE, mLBEP, mLBF, mLBZ, mXAB, mXABU, mXAE,
+ mLAM, mXC, mXCI, mXCD, mSTM, mRSM,
+ mADD, mADCS, mADIS, mAND, mXOR, mCMA, mSTC, mRSC, mSF1, mRF1, mSF2, mRF2,
+ mSAM, mSZM, mSBE, mSZC, mSOS, mSZK, mSZI, mTF1, mTF2,
+ mPP, mJMP, mJMS, mRT, mRTS, mNOP, mHALT,
+ mINP, mOUT, mDISB, mDISN, mMVS, mPSH, mPSL, mEUR
+};
+
const char *const amis2000_disassembler::s_mnemonics[] =
{
"LAB", "LAE", "LAI", "LBE", "LBEP", "LBF", "LBZ", "XAB", "XABU", "XAE",
@@ -33,9 +46,9 @@ const s8 amis2000_disassembler::s_bits[] =
const u32 amis2000_disassembler::s_flags[] =
{
0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, STEP_COND, STEP_COND, 0, 0,
+ 0, STEP_COND, STEP_COND, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ STEP_COND, STEP_COND, STEP_COND, STEP_COND, STEP_COND, STEP_COND, STEP_COND, STEP_COND, STEP_COND,
0, 0, STEP_OVER, STEP_OUT, STEP_OUT, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0
};
@@ -83,12 +96,15 @@ const u8 amis2000_disassembler::s2000_mnemonic[0x100] =
mJMP, mJMP, mJMP, mJMP, mJMP, mJMP, mJMP, mJMP
};
+
+// disasm
+
offs_t amis2000_disassembler::disassemble(std::ostream &stream, offs_t pc, const data_buffer &opcodes, const data_buffer &params)
{
u8 op = opcodes.r8(pc);
u8 instr = s2000_mnemonic[op];
- util::stream_format(stream, "%-5s ", s_mnemonics[instr]);
+ util::stream_format(stream, "%-6s", s_mnemonics[instr]);
// opcode parameter
int mask = s_bits[instr];
@@ -112,8 +128,3 @@ offs_t amis2000_disassembler::disassemble(std::ostream &stream, offs_t pc, const
return 1 | s_flags[instr] | SUPPORTED;
}
-
-u32 amis2000_disassembler::opcode_alignment() const
-{
- return 1;
-}
diff --git a/src/devices/cpu/amis2000/amis2000d.h b/src/devices/cpu/amis2000/amis2000d.h
index 0de1a455fa8..abc9a6dd6a6 100644
--- a/src/devices/cpu/amis2000/amis2000d.h
+++ b/src/devices/cpu/amis2000/amis2000d.h
@@ -17,20 +17,11 @@ public:
amis2000_disassembler() = default;
virtual ~amis2000_disassembler() = default;
- virtual u32 opcode_alignment() const override;
+ virtual u32 opcode_alignment() const override { return 1; }
virtual offs_t disassemble(std::ostream &stream, offs_t pc, const data_buffer &opcodes, const data_buffer &params) override;
private:
- enum e_mnemonics
- {
- mLAB = 0, mLAE, mLAI, mLBE, mLBEP, mLBF, mLBZ, mXAB, mXABU, mXAE,
- mLAM, mXC, mXCI, mXCD, mSTM, mRSM,
- mADD, mADCS, mADIS, mAND, mXOR, mCMA, mSTC, mRSC, mSF1, mRF1, mSF2, mRF2,
- mSAM, mSZM, mSBE, mSZC, mSOS, mSZK, mSZI, mTF1, mTF2,
- mPP, mJMP, mJMS, mRT, mRTS, mNOP, mHALT,
- mINP, mOUT, mDISB, mDISN, mMVS, mPSH, mPSL, mEUR
- };
-
+ enum e_mnemonics : unsigned;
static const char *const s_mnemonics[];
static const s8 s_bits[];
static const u32 s_flags[];
diff --git a/src/devices/cpu/amis2000/amis2000op.cpp b/src/devices/cpu/amis2000/amis2000op.cpp
index 92c2eaae3dc..53c17f4bb4c 100644
--- a/src/devices/cpu/amis2000/amis2000op.cpp
+++ b/src/devices/cpu/amis2000/amis2000op.cpp
@@ -205,7 +205,7 @@ void amis2000_base_device::op_inp()
void amis2000_base_device::op_out()
{
// OUT: pulse output ACC and RAM to D-pins
- logerror("%s unknown opcode $%02X at $%04X\n", tag(), m_op, m_pc);
+ logerror("unknown opcode $%02X at $%04X\n", m_op, m_pc);
}
void amis2000_base_device::op_disb()
@@ -359,7 +359,7 @@ void amis2000_base_device::op_nop()
void amis2000_base_device::op_halt()
{
// HALT: debugger breakpoint for devkit-use
- logerror("%s unknown opcode $%02X at $%04X\n", tag(), m_op, m_pc);
+ logerror("unknown opcode $%02X at $%04X\n", m_op, m_pc);
}
@@ -405,7 +405,7 @@ void amis2000_base_device::op_sam()
void amis2000_base_device::op_sos()
{
// SOS: skip next on SF(timer output), clear SF
- logerror("%s unknown opcode $%02X at $%04X\n", tag(), m_op, m_pc);
+ logerror("unknown opcode $%02X at $%04X\n", m_op, m_pc);
}
void amis2000_base_device::op_tf1()
diff --git a/src/devices/cpu/apexc/apexc.cpp b/src/devices/cpu/apexc/apexc.cpp
index c759cb7b988..b5a908c2c4b 100644
--- a/src/devices/cpu/apexc/apexc.cpp
+++ b/src/devices/cpu/apexc/apexc.cpp
@@ -328,7 +328,6 @@ field: X address D Function Y address D (part 2)
#include "emu.h"
#include "apexc.h"
#include "apexcdsm.h"
-#include "debugger.h"
DEFINE_DEVICE_TYPE(APEXC, apexc_cpu_device, "apexc_cpu", "APE(X)C")
@@ -341,7 +340,7 @@ DEFINE_DEVICE_TYPE(APEXC, apexc_cpu_device, "apexc_cpu", "APE(X)C")
apexc_cpu_device::apexc_cpu_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
: cpu_device(mconfig, APEXC, tag, owner, clock)
, m_program_config("program", ENDIANNESS_BIG, 32, 15, 0)
- , m_tape_read_cb(*this)
+ , m_tape_read_cb(*this, 0)
, m_tape_punch_cb(*this)
, m_a(0)
, m_r(0)
@@ -764,9 +763,6 @@ special_fetch:
void apexc_cpu_device::device_start()
{
- m_tape_read_cb.resolve_safe(0);
- m_tape_punch_cb.resolve_safe();
-
m_program = &space(AS_PROGRAM);
save_item(NAME(m_a));
@@ -846,12 +842,14 @@ void apexc_cpu_device::execute_run()
{
do
{
- debugger_instruction_hook(m_pc);
-
if (m_running)
+ {
+ debugger_instruction_hook(m_pc);
execute();
+ }
else
{
+ debugger_wait_hook();
DELAY(m_icount); /* burn cycles once for all */
}
} while (m_icount > 0);
diff --git a/src/devices/cpu/apexc/apexc.h b/src/devices/cpu/apexc/apexc.h
index fc579824388..6998a62dad4 100644
--- a/src/devices/cpu/apexc/apexc.h
+++ b/src/devices/cpu/apexc/apexc.h
@@ -28,13 +28,12 @@ public:
protected:
// device-level overrides
- virtual void device_start() override;
- virtual void device_reset() override;
+ virtual void device_start() override ATTR_COLD;
+ virtual void device_reset() override ATTR_COLD;
// device_execute_interface overrides
- virtual uint32_t execute_min_cycles() const override { return 2; }
- virtual uint32_t execute_max_cycles() const override { return 75; }
- virtual uint32_t execute_input_lines() const override { return 0; }
+ virtual uint32_t execute_min_cycles() const noexcept override { return 2; }
+ virtual uint32_t execute_max_cycles() const noexcept override { return 75; }
virtual void execute_run() override;
// device_memory_interface overrides
diff --git a/src/devices/cpu/apexc/apexcdsm.cpp b/src/devices/cpu/apexc/apexcdsm.cpp
index bb581dd2850..c0b07e894cf 100644
--- a/src/devices/cpu/apexc/apexcdsm.cpp
+++ b/src/devices/cpu/apexc/apexcdsm.cpp
@@ -101,7 +101,7 @@ offs_t apexc_disassembler::disassemble(std::ostream &stream, offs_t pc, const da
the_desc = & instructions[function >> 1];
/* generate mnemonic : append a 'v' to the basic mnemonic if it is a vector instruction */
- sprintf(mnemonic, "%.*s%c", (int)sizeof(mnemonic)-2, the_desc->mnemonic, vector ? 'v' : ' ');
+ snprintf(mnemonic, 9, "%.*s%c", (int)sizeof(mnemonic)-2, the_desc->mnemonic, vector ? 'v' : ' ');
/* print mnemonic and n immediate */
switch (the_desc->format)
diff --git a/src/devices/cpu/arc/arc.cpp b/src/devices/cpu/arc/arc.cpp
index 70a2b274b57..5b1b61bf6e1 100644
--- a/src/devices/cpu/arc/arc.cpp
+++ b/src/devices/cpu/arc/arc.cpp
@@ -10,7 +10,6 @@
\*********************************/
#include "emu.h"
-#include "debugger.h"
#include "arc.h"
#include "arcdasm.h"
@@ -34,6 +33,13 @@ std::unique_ptr<util::disasm_interface> arc_cpu_device::create_disassembler()
/*****************************************************************************/
+device_memory_interface::space_config_vector arc_cpu_device::memory_space_config() const
+{
+ return space_config_vector {
+ std::make_pair(AS_PROGRAM, &m_program_config)
+ };
+}
+
/*****************************************************************************/
void arc_cpu_device::unimplemented_opcode(uint16_t op)
diff --git a/src/devices/cpu/arc/arc.h b/src/devices/cpu/arc/arc.h
index ba9bfe02fe4..dc00869bb44 100644
--- a/src/devices/cpu/arc/arc.h
+++ b/src/devices/cpu/arc/arc.h
@@ -25,13 +25,12 @@ public:
protected:
// device-level overrides
- virtual void device_start() override;
- virtual void device_reset() override;
+ virtual void device_start() override ATTR_COLD;
+ virtual void device_reset() override ATTR_COLD;
// device_execute_interface overrides
- virtual uint32_t execute_min_cycles() const override { return 5; }
- virtual uint32_t execute_max_cycles() const override { return 5; }
- virtual uint32_t execute_input_lines() const override { return 0; }
+ virtual uint32_t execute_min_cycles() const noexcept override { return 5; }
+ virtual uint32_t execute_max_cycles() const noexcept override { return 5; }
virtual void execute_run() override;
virtual void execute_set_input(int inputnum, int state) override;
diff --git a/src/devices/cpu/arcompact/arcompact.cpp b/src/devices/cpu/arcompact/arcompact.cpp
index c35798e5b94..7b13e7eafe2 100644
--- a/src/devices/cpu/arcompact/arcompact.cpp
+++ b/src/devices/cpu/arcompact/arcompact.cpp
@@ -1,10 +1,9 @@
// license:BSD-3-Clause
// copyright-holders:David Haywood
/*********************************\
-
ARCompact Core
- The following procesors use the ARCompact instruction set
+ The following processors use the ARCompact instruction set
- ARCtangent-A5
- ARC 600
@@ -13,53 +12,222 @@
(this is a skeleton core)
ARCompact is a 32-bit CPU that freely mixes 32-bit and 16-bit instructions
- various user customizations could be made as with the ARC A4 based processors
+
+ Various user customizations could be made as with the ARC A4 based processors
these include custom instructions and registers.
\*********************************/
#include "emu.h"
-#include "debugger.h"
-#include "arcompact.h"
+#include "arcompact_helper.ipp"
+
#include "arcompactdasm.h"
DEFINE_DEVICE_TYPE(ARCA5, arcompact_device, "arc_a5", "Argonaut ARCtangent A5")
+uint32_t arcompact_device::arcompact_auxreg002_LPSTART_r() { return m_LP_START & 0xfffffffe; }
+void arcompact_device::arcompact_auxreg002_LPSTART_w(uint32_t data) { m_LP_START = data & 0xfffffffe; }
+uint32_t arcompact_device::arcompact_auxreg003_LPEND_r() { return m_LP_END & 0xfffffffe; }
+void arcompact_device::arcompact_auxreg003_LPEND_w(uint32_t data) { m_LP_END = data & 0xfffffffe; }
-READ32_MEMBER( arcompact_device::arcompact_auxreg002_LPSTART_r) { return m_LP_START&0xfffffffe; }
-WRITE32_MEMBER(arcompact_device::arcompact_auxreg002_LPSTART_w) { m_LP_START = data&0xfffffffe; }
-READ32_MEMBER( arcompact_device::arcompact_auxreg003_LPEND_r) { return m_LP_END&0xfffffffe; }
-WRITE32_MEMBER(arcompact_device::arcompact_auxreg003_LPEND_w) { m_LP_END = data&0xfffffffe; }
+uint32_t arcompact_device::arcompact_auxreg00a_STATUS32_r() { return m_status32; }
-READ32_MEMBER( arcompact_device::arcompact_auxreg00a_STATUS32_r) { return 0xffffdead; /*m_status32;*/ }
+uint32_t arcompact_device::arcompact_auxreg00b_STATUS32_L1_r() { return m_status32_l1; }
+uint32_t arcompact_device::arcompact_auxreg00c_STATUS32_L2_r() { return m_status32_l2; }
+void arcompact_device::arcompact_auxreg00b_STATUS32_L1_w(uint32_t data) { m_status32_l1 = data; }
+void arcompact_device::arcompact_auxreg00c_STATUS32_L2_w(uint32_t data) { m_status32_l2 = data; }
+
+void arcompact_device::arcompact_auxreg012_MULHI_w(uint32_t data)
+{
+ // The regular multiply result registers (r56 - MLO, r57 - MMID and r58 - MHI) are read-only
+ // this optional extension allows the program to directly set the value of MHI
+ // so that it's state can be restored
+ //
+ // (although the Leapster BIOS tries to write MMID directly when doing such a restoration
+ // despite otherwise going through the recommended procedure of multiplying the lower result
+ // by 1 to restore MLO and writing to this AUX address to restore MHI)
+ m_regs[REG_MHI] = data;
+}
-READ32_MEMBER( arcompact_device::arcompact_auxreg025_INTVECTORBASE_r) { return m_INTVECTORBASE&0xfffffc00; }
-WRITE32_MEMBER(arcompact_device::arcompact_auxreg025_INTVECTORBASE_w) { m_INTVECTORBASE = data&0xfffffc00; }
+uint32_t arcompact_device::arcompact_auxreg043_AUX_IRQ_LV12_r()
+{
+ logerror("%s: arcompact_auxreg043_AUX_IRQ_LV12_r\n", machine().describe_context());
+ return m_AUX_IRQ_LV12;
+}
+void arcompact_device::arcompact_auxreg043_AUX_IRQ_LV12_w(uint32_t data)
+{
+ logerror("%s: arcompact_auxreg043_AUX_IRQ_LV12_w %08x\n", machine().describe_context(), data);
+ if (data & 0x00000001) m_AUX_IRQ_LV12 &= ~0x00000001;
+ if (data & 0x00000002) m_AUX_IRQ_LV12 &= ~0x00000002;
+}
+uint32_t arcompact_device::arcompact_auxreg025_INTVECTORBASE_r() { return m_INTVECTORBASE & 0xfffffc00; }
-void arcompact_device::arcompact_auxreg_map(address_map &map)
+void arcompact_device::arcompact_auxreg025_INTVECTORBASE_w(uint32_t data)
{
+ logerror("%s: m_INTVECTORBASE write %08x\n", machine().describe_context(), data);
+ m_INTVECTORBASE = data & 0xfffffc00;
+}
+
+uint32_t arcompact_device::arcompact_auxreg012_TIMER0_r(offs_t offset)
+{
+ switch (offset)
+ {
+ case 0x00:
+ logerror("%s: TIMER0 COUNT read\n", machine().describe_context());
+ return m_timer[0][0];
+ case 0x01:
+ logerror("%s: TIMER0 CONTROL read\n", machine().describe_context());
+ return m_timer[0][1];
+ case 0x02:
+ logerror("%s: TIMER0 LIMIT read\n", machine().describe_context());
+ return m_timer[0][2];
+ }
+ return 0x00;
+}
+
+uint32_t arcompact_device::arcompact_auxreg100_TIMER1_r(offs_t offset)
+{
+ switch (offset)
+ {
+ case 0x00:
+ logerror("%s: TIMER1 COUNT read\n", machine().describe_context());
+ return m_timer[1][0];
+ case 0x01:
+ logerror("%s: TIMER1 CONTROL read\n", machine().describe_context());
+ return m_timer[1][1];
+ case 0x02:
+ logerror("%s: TIMER1 LIMIT read\n", machine().describe_context());
+ return m_timer[1][2];
+ }
+ return 0x00;
+}
+
+void arcompact_device::arcompact_auxreg012_TIMER0_w(offs_t offset, uint32_t data)
+{
+ switch (offset)
+ {
+ case 0x00:
+ m_timer[0][0] = data;
+ logerror("%s: TIMER0 COUNT write %08x\n", machine().describe_context(), data);
+ break;
+ case 0x01:
+ m_timer[0][1] = data;
+ logerror("%s: TIMER0 CONTROL write %08x\n", machine().describe_context(), data);
+ break;
+ case 0x02:
+ m_timer[0][2] = data;
+ logerror("%s: TIMER0 LIMIT write %08x\n", machine().describe_context(), data);
+ break;
+ }
+}
+
+void arcompact_device::arcompact_auxreg100_TIMER1_w(offs_t offset, uint32_t data)
+{
+ switch (offset)
+ {
+ case 0x00:
+ m_timer[1][0] = data;
+ logerror("%s: TIMER1 COUNT write %08x\n", machine().describe_context(), data);
+ break;
+ case 0x01:
+ m_timer[1][1] = data;
+ logerror("%s: TIMER1 CONTROL write %08x\n", machine().describe_context(), data);
+ break;
+ case 0x02:
+ m_timer[1][2] = data;
+ logerror("%s: TIMER1 LIMIT write %08x\n", machine().describe_context(), data);
+ break;
+ }
+}
+
+uint32_t arcompact_device::arcompact_auxreg200_AUX_IRQ_LVL_r()
+{
+ logerror("%s: arcompact_auxreg200_AUX_IRQ_LVL_r\n", machine().describe_context());
+ return 0;
+}
+
+void arcompact_device::arcompact_auxreg200_AUX_IRQ_LVL_w(uint32_t data)
+{
+ logerror("%s: arcompact_auxreg200_AUX_IRQ_LVL_w %08x\n", machine().describe_context(), data);
+ m_AUX_IRQ_LEV = data;
+}
+
+
+
+void arcompact_device::arcompact_auxreg_map(address_map& map)
+{
+ //map(0x000000000, 0x000000000) // STATUS register in ARCtangent-A4 format (legacy)
+ //map(0x000000001, 0x000000001) // SEMAPHORE (for multi-cpu comms)
map(0x000000002, 0x000000002).rw(FUNC(arcompact_device::arcompact_auxreg002_LPSTART_r), FUNC(arcompact_device::arcompact_auxreg002_LPSTART_w));
map(0x000000003, 0x000000003).rw(FUNC(arcompact_device::arcompact_auxreg003_LPEND_r), FUNC(arcompact_device::arcompact_auxreg003_LPEND_w));
- map(0x000000009, 0x000000009).r(FUNC(arcompact_device::arcompact_auxreg00a_STATUS32_r)); // r/o
+ //map(0x000000004, 0x000000004) // IDENTITY (processor ID register)
+ //map(0x000000005, 0x000000005) // DEBUG (various flags, including SLEEP)
+ //map(0x000000006, 0x000000006) // PC (alt way of reading current PC)
+ map(0x00000000a, 0x00000000a).r(FUNC(arcompact_device::arcompact_auxreg00a_STATUS32_r)); // r/o
+ map(0x00000000b, 0x00000000b).rw(FUNC(arcompact_device::arcompact_auxreg00b_STATUS32_L1_r), FUNC(arcompact_device::arcompact_auxreg00b_STATUS32_L1_w));
+ map(0x00000000c, 0x00000000c).rw(FUNC(arcompact_device::arcompact_auxreg00c_STATUS32_L2_r), FUNC(arcompact_device::arcompact_auxreg00c_STATUS32_L2_w));
+
+ map(0x000000012, 0x000000012).w(FUNC(arcompact_device::arcompact_auxreg012_MULHI_w));
+
+ map(0x000000021, 0x000000023).rw(FUNC(arcompact_device::arcompact_auxreg012_TIMER0_r), FUNC(arcompact_device::arcompact_auxreg012_TIMER0_w));
+
map(0x000000025, 0x000000025).rw(FUNC(arcompact_device::arcompact_auxreg025_INTVECTORBASE_r), FUNC(arcompact_device::arcompact_auxreg025_INTVECTORBASE_w));
-}
-#define AUX_SPACE_ADDRESS_WIDTH 32 // IO space is 32 bits of dwords
+ //map(0x000000041, 0x000000041) // AUX_MACMODE (used by optional maths extensions)
+
+ map(0x000000043, 0x000000043).rw(FUNC(arcompact_device::arcompact_auxreg043_AUX_IRQ_LV12_r), FUNC(arcompact_device::arcompact_auxreg043_AUX_IRQ_LV12_w));
-arcompact_device::arcompact_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
+ // these registers can be used to check which optional capabilities any given CPU was built with
+ //map(0x000000060, 0x000000060) // BCR_VER - Build Configuration Registers Version
+ //map(0x000000063, 0x000000063) // BTA_LINK_BUILD - Build configuration for BTA Registers
+ //map(0x000000065, 0x000000065) // EA_BUILD - Build configuration for Extended Arithmetic
+ //map(0x000000068, 0x000000068) // VECBASE_AC_BUILD - Build configuration for Interrupts
+ //map(0x00000006e, 0x00000006e) // RF_BUILD - Build configuration for Core Registers
+ //map(0x000000075, 0x000000075) // TIMER_BUILD - Build configuration for Processor Timers
+ //map(0x00000007b, 0x00000007b) // MULTIPLY_BUILD - Build configuration for Multiply
+ //map(0x00000007c, 0x00000007c) // SWAP_BUILD - Build configuration for Swap
+ //map(0x00000007d, 0x00000007d) // NORM_BUILD - Build configuration for Normalize
+ //map(0x00000007e, 0x00000007e) // MINMAX_BUILD - Build configuration for Min/Max
+ //map(0x00000007f, 0x00000007f) // BARREL_BUILD - Build configuration for Barrel Shift
+
+ map(0x000000100, 0x000000102).rw(FUNC(arcompact_device::arcompact_auxreg100_TIMER1_r), FUNC(arcompact_device::arcompact_auxreg100_TIMER1_w));
+
+ map(0x000000200, 0x000000200).rw(FUNC(arcompact_device::arcompact_auxreg200_AUX_IRQ_LVL_r), FUNC(arcompact_device::arcompact_auxreg200_AUX_IRQ_LVL_w));
+ //map(0x000000201, 0x000000201) // AUX_IRQ_HINT
+
+ // below are ARC700 registers
+ //map(0x000000400, 0x000000400) // ERET
+ //map(0x000000401, 0x000000401) // ERBTA
+ //map(0x000000402, 0x000000402) // ERSTATUS
+ //map(0x000000403, 0x000000403) // ECR
+ //map(0x000000404, 0x000000404) // EFA
+ //map(0x00000040a, 0x00000040a) // ICAUSE1
+ //map(0x00000040b, 0x00000040b) // ICAUSE2
+ //map(0x00000040c, 0x00000040c) // AUX_IENABLE
+ //map(0x00000040d, 0x00000040d) // AUX_ITRIGGER
+ //map(0x000000410, 0x000000410) // XPU
+ //map(0x000000412, 0x000000412) // BTA
+ //map(0x000000413, 0x000000413) // BTA_L1
+ //map(0x000000414, 0x000000414) // BTA_L2
+ //map(0x000000415, 0x000000415) // AUX_IRQ_PULSE_CANCEL
+ //map(0x000000416, 0x000000416) // AUX_IRQ_PENDING
+}
+
+arcompact_device::arcompact_device(const machine_config& mconfig, const char* tag, device_t* owner, uint32_t clock)
: cpu_device(mconfig, ARCA5, tag, owner, clock)
- , m_program_config("program", ENDIANNESS_LITTLE, 32, 32, 0) // some docs describe these as 'middle endian'?!
- , m_io_config( "io", ENDIANNESS_LITTLE, 32, AUX_SPACE_ADDRESS_WIDTH, -2, address_map_constructor(FUNC(arcompact_device::arcompact_auxreg_map), this))
+ , m_program_config("program", ENDIANNESS_LITTLE, 32, 32, 0) // some docs describe these as 'middle endian'
+ , m_io_config("io", ENDIANNESS_LITTLE, 32, 32, -2, address_map_constructor(FUNC(arcompact_device::arcompact_auxreg_map), this))
+ , m_default_vector_base(0)
{
}
device_memory_interface::space_config_vector arcompact_device::memory_space_config() const
{
- return space_config_vector {
+ return space_config_vector{
std::make_pair(AS_PROGRAM, &m_program_config),
std::make_pair(AS_IO, &m_io_config)
};
@@ -94,21 +262,40 @@ void arcompact_device::device_start()
m_program = &space(AS_PROGRAM);
m_io = &space(AS_IO);
- state_add( ARCOMPACT_PC, "PC", m_debugger_temp).callimport().callexport().formatstr("%08X");
+ state_add(ARCOMPACT_PC, "PC", m_debugger_temp).callimport().callexport().formatstr("%08X");
- state_add( ARCOMPACT_STATUS32, "STATUS32", m_debugger_temp).callimport().callexport().formatstr("%08X");
- state_add( ARCOMPACT_LP_START, "LP_START", m_debugger_temp).callimport().callexport().formatstr("%08X");
- state_add( ARCOMPACT_LP_END, "LP_END", m_debugger_temp).callimport().callexport().formatstr("%08X");
+ state_add(ARCOMPACT_STATUS32, "STATUS32", m_debugger_temp).callimport().callexport().formatstr("%08X");
+ state_add(ARCOMPACT_LP_START, "LP_START", m_debugger_temp).callimport().callexport().formatstr("%08X");
+ state_add(ARCOMPACT_LP_END, "LP_END", m_debugger_temp).callimport().callexport().formatstr("%08X");
state_add(STATE_GENPCBASE, "CURPC", m_debugger_temp).callimport().callexport().noshow();
for (int i = 0x100; i < 0x140; i++)
{
- state_add(i, arcompact_disassembler::regnames[i-0x100], m_debugger_temp).callimport().callexport().formatstr("%08X");
+ state_add(i, arcompact_disassembler::regnames[i - 0x100], m_debugger_temp).callimport().callexport().formatstr("%08X");
}
+ m_irq_pending = false;
set_icountptr(m_icount);
+
+ save_item(NAME(m_pc));
+ save_item(NAME(m_regs));
+ save_item(NAME(m_delayactive));
+ save_item(NAME(m_delaylinks));
+ save_item(NAME(m_delayjump));
+ save_item(NAME(m_allow_loop_check));
+ save_item(NAME(m_irq_pending));
+ save_item(NAME(m_status32));
+ save_item(NAME(m_status32_l1));
+ save_item(NAME(m_status32_l2));
+ save_item(NAME(m_debug));
+ save_item(NAME(m_timer));
+ save_item(NAME(m_LP_START));
+ save_item(NAME(m_LP_END));
+ save_item(NAME(m_INTVECTORBASE));
+ save_item(NAME(m_AUX_IRQ_LV12));
+ save_item(NAME(m_AUX_IRQ_LEV));
}
@@ -117,34 +304,33 @@ void arcompact_device::device_start()
// to a known location where it can be read
//-------------------------------------------------
-void arcompact_device::state_export(const device_state_entry &entry)
+void arcompact_device::state_export(const device_state_entry& entry)
{
int index = entry.index();
switch (index)
{
- case ARCOMPACT_PC:
- case STATE_GENPCBASE:
- m_debugger_temp = m_pc;
- break;
-
- case ARCOMPACT_STATUS32:
- m_debugger_temp = m_status32;
- break;
- case ARCOMPACT_LP_START:
- m_debugger_temp = m_LP_START;
- break;
- case ARCOMPACT_LP_END:
- m_debugger_temp = m_LP_END;
- break;
+ case ARCOMPACT_PC:
+ case STATE_GENPCBASE:
+ m_debugger_temp = m_pc;
+ break;
- default:
- if ((index >= 0x100) && (index < 0x140))
- {
- m_debugger_temp = m_regs[index - 0x100];
- }
- break;
+ case ARCOMPACT_STATUS32:
+ m_debugger_temp = m_status32;
+ break;
+ case ARCOMPACT_LP_START:
+ m_debugger_temp = m_LP_START;
+ break;
+ case ARCOMPACT_LP_END:
+ m_debugger_temp = m_LP_END;
+ break;
+ default:
+ if ((index >= 0x100) && (index < 0x140))
+ {
+ m_debugger_temp = m_regs[index - 0x100];
+ }
+ break;
}
}
@@ -154,57 +340,2610 @@ void arcompact_device::state_export(const device_state_entry &entry)
// after it has been set
//-------------------------------------------------
-void arcompact_device::state_import(const device_state_entry &entry)
+void arcompact_device::state_import(const device_state_entry& entry)
{
int index = entry.index();
switch (index)
{
- case ARCOMPACT_PC:
- case STATE_GENPCBASE:
- m_pc = (m_debugger_temp & 0xfffffffe);
- break;
-
- case ARCOMPACT_STATUS32:
- m_status32 = m_debugger_temp;
- break;
- case ARCOMPACT_LP_START:
- m_LP_START = m_debugger_temp;
- break;
- case ARCOMPACT_LP_END:
- m_LP_END = m_debugger_temp;
- break;
-
- default:
- if ((index >= 0x100) && (index < 0x140))
- {
- m_regs[index - 0x100] = m_debugger_temp;
- }
- break;
+ case ARCOMPACT_PC:
+ case STATE_GENPCBASE:
+ m_pc = (m_debugger_temp & 0xfffffffe);
+ break;
+
+ case ARCOMPACT_STATUS32:
+ m_status32 = m_debugger_temp;
+ break;
+ case ARCOMPACT_LP_START:
+ m_LP_START = m_debugger_temp;
+ break;
+ case ARCOMPACT_LP_END:
+ m_LP_END = m_debugger_temp;
+ break;
+
+ default:
+ if ((index >= 0x100) && (index < 0x140))
+ {
+ m_regs[index - 0x100] = m_debugger_temp;
+ }
+ break;
}
}
void arcompact_device::device_reset()
{
- m_pc = 0x00000000;
+ m_pc = m_INTVECTORBASE = m_default_vector_base;
- m_delayactive = 0;
+ m_delayactive = false;
m_delayjump = 0x00000000;
+ m_irq_pending = false;
- for (auto & elem : m_regs)
+ for (auto& elem : m_regs)
elem = 0;
m_status32 = 0;
+ m_status32_l1 = 0;
+ m_status32_l2 = 0;
+ m_debug = 0;
+
m_LP_START = 0;
m_LP_END = 0;
- m_INTVECTORBASE = 0;
+ m_AUX_IRQ_LV12 = 0;
+ m_AUX_IRQ_LEV = 0x000000c0; // only 2 interrupts are set to 'medium' priority (level 2) by default.
+ m_allow_loop_check = true;
+
+ for (int t = 0; t < 2; t++)
+ for (int r = 0; r < 3; r++)
+ m_timer[t][r] = 0x00;
}
/*****************************************************************************/
-
void arcompact_device::execute_set_input(int irqline, int state)
{
+ if (state == ASSERT_LINE)
+ m_irq_pending = true;
+ else
+ m_irq_pending = false;
+}
+
+/*****************************************************************************/
+
+uint32_t arcompact_device::get_instruction(uint32_t op)
+{
+ uint8_t instruction = ((op & 0xf800) >> 11);
+
+ if (instruction < 0x0c)
+ {
+ op <<= 16;
+ op |= READ16((m_pc + 2));
+
+ switch (instruction & 0x3f) // 32-bit instructions (with optional extra dword for immediate data)
+ {
+ default: return -1;
+ case 0x00: // Bcc
+ {
+ uint8_t subinstr = (op & 0x00010000) >> 16;
+
+ switch (subinstr & 0x01)
+ {
+ default: return -1;
+ case 0x00:
+ {
+// +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+// B<cc><.d> s21 0000 0sss ssss sss0 SSSS SSSS SSNQ QQQQ
+// +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+ return handleop32_B_cc_D_s21(op); // Branch Conditionally
+ }
+ case 0x01:
+ {
+// +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+// B<.d> s25 0000 0sss ssss sss1 SSSS SSSS SSNR tttt
+// +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+ return handleop32_B_D_s25(op); // Branch Unconditionally Far
+ }
+ }
+ }
+ case 0x01: // BLcc/BRcc
+ {
+ uint8_t subinstr = (op & 0x00010000) >> 16;
+ switch (subinstr & 0x01)
+ {
+ default: return -1;
+ case 0x00: // Branch & Link
+ {
+ uint8_t subinstr2 = (op & 0x00020000) >> 17;
+ switch (subinstr2)
+ {
+ default: return -1;
+ case 0x00:
+ {
+// +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+// BL<.cc><.d> s21 0000 1sss ssss ss00 SSSS SSSS SSNQ QQQQ
+// +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+ return handleop32_BL_cc_d_s21(op); // Branch and Link Conditionally
+ }
+ case 0x01:
+ {
+// +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+// BL<.d> s25 0000 1sss ssss ss10 SSSS SSSS SSNR tttt
+// +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+ return handleop32_BL_d_s25(op); // Branch and Link Unconditional Far
+ }
+ }
+ }
+ case 0x01: // Branch on Compare
+ {
+ uint8_t subinstr2 = (op & 0x00000010) >> 4;
+
+ switch (subinstr2)
+ {
+ default: return -1;
+ case 0x00: // Branch on Compare Register-Register
+ {
+ uint8_t subinstr3 = op & 0x0000000f;
+ switch (subinstr3)
+ {
+ case 0x00:
+ {
+// +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+// BREQ<.d> b,c,s9 0000 1bbb ssss sss1 SBBB CCCC CCN0 0000
+// BREQ b,limm,s9 0000 1bbb ssss sss1 SBBB 1111 1000 0000 (+ Limm)
+// BREQ limm,c,s9 0000 1110 ssss sss1 S111 CCCC CC00 0000 (+ Limm)
+// +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+ return handleop32_BRxx_reg_reg(op, 0); // BREQ (reg-reg)
+ }
+ case 0x01:
+ {
+// +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+// BRNE<.d> b,c,s9 0000 1bbb ssss sss1 SBBB CCCC CCN0 0001
+// BRNE b,limm,s9 0000 1bbb ssss sss1 SBBB 1111 1000 0001 (+ Limm)
+// BRNE limm,c,s9 0000 1110 ssss sss1 S111 CCCC CC00 0001 (+ Limm)
+// +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+ return handleop32_BRxx_reg_reg(op, 1); // BRNE (reg-reg)
+ }
+ case 0x02:
+ {
+// +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+// BRLT<.d> b,c,s9 0000 1bbb ssss sss1 SBBB CCCC CCN0 0010
+// BRLT b,limm,s9 0000 1bbb ssss sss1 SBBB 1111 1000 0010 (+ Limm)
+// BRLT limm,c,s9 0000 1110 ssss sss1 S111 CCCC CC00 0010 (+ Limm)
+// +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+ return handleop32_BRxx_reg_reg(op, 2); // BRLT (reg-reg)
+ }
+ case 0x03:
+ {
+// +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+// BRGE<.d> b,c,s9 0000 1bbb ssss sss1 SBBB CCCC CCN0 0011
+// BRGE b,limm,s9 0000 1bbb ssss sss1 SBBB 1111 1000 0011 (+ Limm)
+// BRGE limm,c,s9 0000 1110 ssss sss1 S111 CCCC CC00 0011 (+ Limm)
+// +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+ return handleop32_BRxx_reg_reg(op, 3); // BRGE (reg-reg)
+ }
+ case 0x04:
+ {
+// +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+// BRLO<.d> b,c,s9 0000 1bbb ssss sss1 SBBB CCCC CCN0 0100
+// BRLO b,limm,s9 0000 1bbb ssss sss1 SBBB 1111 1000 0100 (+ Limm)
+// BRLO limm,c,s9 0000 1110 ssss sss1 S111 CCCC CC00 0100 (+ Limm)
+// +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+ return handleop32_BRxx_reg_reg(op, 4); // BRLO (reg-reg)
+ }
+ case 0x05:
+ {
+// +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+// BRHS b,limm,s9 0000 1bbb ssss sss1 SBBB 1111 1000 0101 (+ Limm)
+// BRHS limm,c,s9 0000 1110 ssss sss1 S111 CCCC CC00 0101 (+ Limm)
+// BRHS<.d> b,c,s9 0000 1bbb ssss sss1 SBBB CCCC CCN0 0101
+// +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+ return handleop32_BRxx_reg_reg(op, 5); // BRHS (reg-reg)
+ }
+ case 0x0e:
+ {
+// +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+// BBIT0<.d> b,c,s9 0000 1bbb ssss sss1 SBBB CCCC CCN0 1110
+// +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+ return handleop32_BRxx_reg_reg(op, 6); // BBIT0 (reg-reg)
+ }
+ case 0x0f:
+ {
+// +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+// BBIT1<.d> b,c,s9 0000 1bbb ssss sss1 SBBB CCCC CCN0 1111
+// +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+ return handleop32_BRxx_reg_reg(op, 7); // BBIT1 (reg-reg)
+ }
+ default:
+ {
+ // 0x06 - 0x0d
+ return arcompact_handle_reserved(instruction, subinstr, subinstr2, subinstr3, op); // illegal
+ }
+ }
+ }
+ case 0x01: // Branch on Compare/Bit Test Register-Immediate
+ {
+ uint8_t subinstr3 = op & 0x0000000f;
+ switch (subinstr3)
+ {
+ case 0x00:
+ {
+// +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+// BREQ<.d> b,u6,s9 0000 1bbb ssss sss1 SBBB UUUU UUN1 0000
+// +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+ return handleop32_BRxx_reg_imm(op, 0); // BREQ (reg-imm)
+ }
+ case 0x01:
+ {
+// +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+// BRNE<.d> b,u6,s9 0000 1bbb ssss sss1 SBBB UUUU UUN1 0001
+// +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+ return handleop32_BRxx_reg_imm(op, 1); // BRNE (reg-imm)
+ }
+ case 0x02:
+ {
+// +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+// BRLT<.d> b,u6,s9 0000 1bbb ssss sss1 SBBB UUUU UUN1 0010
+// +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+ return handleop32_BRxx_reg_imm(op, 2); // BRLT (reg-imm)
+ }
+ case 0x03:
+ {
+// +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+// BRGE<.d> b,u6,s9 0000 1bbb ssss sss1 SBBB UUUU UUN1 0011
+// +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+ return handleop32_BRxx_reg_imm(op, 3); // BRGE (reg-imm)
+ }
+ case 0x04:
+ {
+// +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+// BRLO<.d> b,u6,s9 0000 1bbb ssss sss1 SBBB UUUU UUN1 0100
+// +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+ return handleop32_BRxx_reg_imm(op, 4); // BRLO (reg-imm)
+ }
+ case 0x05:
+ {
+// +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+// BRHS<.d> b,u6,s9 0000 1bbb ssss sss1 SBBB UUUU UUN1 0101
+// +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+ return handleop32_BRxx_reg_imm(op, 5); // BRHS (reg-imm)
+ }
+ case 0x0e:
+ {
+// +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+// BBIT0<.d> b,u6,s9 0000 1bbb ssss sss1 SBBB uuuu uuN1 1110
+// +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+ return handleop32_BRxx_reg_imm(op, 6); // BBIT0 (reg-imm)
+ }
+ case 0x0f:
+ {
+// +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+// BBIT1<.d> b,u6,s9 0000 1bbb ssss sss1 SBBB uuuu uuN1 1111
+// +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+ return handleop32_BRxx_reg_imm(op, 7); // BBIT1 (reg-imm)
+ }
+ default:
+ {
+ // 0x06 - 0x0d
+ return arcompact_handle_reserved(instruction, subinstr, subinstr2, subinstr3, op); // illegal
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ case 0x02:
+ {
+// +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+// IIII I
+// LD<zz><.x><.aa><.di> a,[b,s9] 0001 0bbb ssss ssss SBBB DaaZ ZXAA AAAA
+// LD<zz><.x><.di> a,[limm] 0001 0110 0000 0000 0111 DRRZ ZXAA AAAA (+ Limm)
+// LD<zz><.x><.aa><.di> 0,[b,s9] 0001 0bbb ssss ssss SBBB DaaZ ZX11 1110
+// LD<zz><.x><.di> 0,[limm] 0001 0110 0000 0000 0111 DRRZ ZX11 1110 (+ Limm)
+//
+// PREFETCH<.aa> [b,s9] 0001 0bbb ssss ssss SBBB 0aa0 0011 1110
+// PREFETCH [limm] 0001 0110 0000 0000 0111 0RR0 0011 1110 (+ Limm)
+// +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+ return handleop32_LD_r_o(op); // LD r+o
+ }
+ case 0x03:
+ {
+// +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+// IIII I
+// ST<zz><.aa><.di> c,[b,s9] 0001 1bbb ssss ssss SBBB CCCC CCDa aZZR
+// ST<zz><.di> c,[limm] 0001 1110 0000 0000 0111 CCCC CCDR RZZR (+ Limm)
+// ST<zz><.aa><.di> limm,[b,s9] 0001 1bbb ssss ssss SBBB 1111 10Da aZZR (+ Limm)
+// +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+ return handleop32_ST_r_o(op); // ST r+o
+ }
+ case 0x04: // op a,b,c (basecase)
+ {
+ uint8_t subinstr = (op & 0x003f0000) >> 16;
+
+ switch (subinstr & 0x3f)
+ {
+ case 0x00:
+ {
+// +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+// ADD<.f> a,b,c 0010 0bbb 0000 0000 FBBB CCCC CCAA AAAA
+// ADD<.f> a,b,u6 0010 0bbb 0100 0000 FBBB uuuu uuAA AAAA
+// ADD<.f> b,b,s12 0010 0bbb 1000 0000 FBBB ssss ssSS SSSS
+// ADD<.cc><.f> b,b,c 0010 0bbb 1100 0000 FBBB CCCC CC0Q QQQQ
+// ADD<.cc><.f> b,b,u6 0010 0bbb 1100 0000 FBBB uuuu uu1Q QQQQ
+// ADD<.f> a,limm,c 0010 0110 0000 0000 F111 CCCC CCAA AAAA (+ Limm)
+// ADD<.f> a,b,limm 0010 0bbb 0000 0000 FBBB 1111 10AA AAAA (+ Limm)
+// ADD<.cc><.f> b,b,limm 0010 0bbb 1100 0000 FBBB 1111 100Q QQQQ (+ Limm)
+//
+// ADD<.f> 0,b,c 0010 0bbb 0000 0000 FBBB CCCC CC11 1110
+// ADD<.f> 0,b,u6 0010 0bbb 0100 0000 FBBB uuuu uu11 1110
+// ADD<.f> 0,b,limm 0010 0bbb 0000 0000 FBBB 1111 1011 1110 (+ Limm)
+// ADD<.cc><.f> 0,limm,c 0010 0110 1100 0000 F111 CCCC CC0Q QQQQ (+ Limm)
+// +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+ return handleop32_general(op, handleop32_ADD_do_op); // ADD
+ }
+ case 0x01:
+ {
+// +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+// ADC<.f> a,b,c 0010 0bbb 0000 0001 FBBB CCCC CCAA AAAA
+// ADC<.f> a,b,u6 0010 0bbb 0100 0001 FBBB uuuu uuAA AAAA
+// ADC<.f> b,b,s12 0010 0bbb 1000 0001 FBBB ssss ssSS SSSS
+// ADC<.cc><.f> b,b,c 0010 0bbb 1100 0001 FBBB CCCC CC0Q QQQQ
+// ADC<.cc><.f> b,b,u6 0010 0bbb 1100 0001 FBBB uuuu uu1Q QQQQ
+// ADC<.f> a,limm,c 0010 0110 0000 0001 F111 CCCC CCAA AAAA (+ Limm)
+// ADC<.f> a,b,limm 0010 0bbb 0000 0001 FBBB 1111 10AA AAAA (+ Limm)
+// ADC<.cc><.f> b,b,limm 0010 0bbb 1100 0001 FBBB 1111 100Q QQQQ (+ Limm)
+//
+// ADC<.f> 0,b,c 0010 0bbb 0000 0001 FBBB CCCC CC11 1110
+// ADC<.f> 0,b,u6 0010 0bbb 0100 0001 FBBB uuuu uu11 1110
+// ADC<.f> 0,b,limm 0010 0bbb 0000 0001 FBBB 1111 1011 1110 (+ Limm)
+// ADC<.cc><.f> 0,limm,c 0010 0110 1100 0001 F111 CCCC CC0Q QQQQ (+ Limm)
+// +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+ return handleop32_general(op, handleop32_ADC_do_op); // ADC
+ }
+ case 0x02:
+ {
+// +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+// SUB<.f> a,b,c 0010 0bbb 0000 0010 FBBB CCCC CCAA AAAA
+// SUB<.f> a,b,u6 0010 0bbb 0100 0010 FBBB uuuu uuAA AAAA
+// SUB<.f> b,b,s12 0010 0bbb 1000 0010 FBBB ssss ssSS SSSS
+// SUB<.cc><.f> b,b, c 0010 0bbb 1100 0010 FBBB CCCC CC0Q QQQQ
+// SUB<.cc><.f> b,b,u6 0010 0bbb 1100 0010 FBBB uuuu uu1Q QQQQ
+// SUB<.f> a,limm,c 0010 0110 0000 0010 F111 CCCC CCAA AAAA (+ Limm)
+// SUB<.f> a,b,limm 0010 0bbb 0000 0010 FBBB 1111 10AA AAAA (+ Limm)
+// SUB<.cc><.f> b,b,limm 0010 0bbb 1100 0010 FBBB 1111 100Q QQQQ (+ Limm)
+//
+// SUB <.f> 0,b,c 0010 0bbb 0000 0010 FBBB CCCC CC11 1110
+// SUB <.f> 0,b,u6 0010 0bbb 0100 0010 FBBB uuuu uu11 1110
+// SUB <.f> 0,b,limm 0010 0bbb 0000 0010 FBBB 1111 1011 1110 (+ Limm)
+// SUB <.cc><.f> 0,limm,c 0010 0110 1100 0010 F111 CCCC CC0Q QQQQ (+ Limm)
+// +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+ return handleop32_general(op, handleop32_SUB_do_op); // SUB
+ }
+ case 0x03:
+ {
+// +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+// SBC<.f> a,b,c 0010 0bbb 0000 0011 FBBB CCCC CCAA AAAA
+// SBC<.f> a,b,u6 0010 0bbb 0100 0011 FBBB uuuu uuAA AAAA
+// SBC<.f> b,b,s12 0010 0bbb 1000 0011 FBBB ssss ssSS SSSS
+// SBC<.cc><.f> b,b,c 0010 0bbb 1100 0011 FBBB CCCC CC0Q QQQQ
+// SBC<.cc><.f> b,b,u6 0010 0bbb 1100 0011 FBBB uuuu uu1Q QQQQ
+// SBC<.f> a,limm,c 0010 0110 0000 0011 F111 CCCC CCAA AAAA (+ Limm)
+// SBC<.f> a,b,limm 0010 0bbb 0000 0011 FBBB 1111 10AA AAAA (+ Limm)
+// SBC<.cc><.f> b,b,limm 0010 0bbb 1100 0011 FBBB 1111 100Q QQQQ (+ Limm)
+//
+// SBC<.f> 0,b,c 0010 0bbb 0000 0011 FBBB CCCC CC11 1110
+// SBC<.f> 0,b,u6 0010 0bbb 0100 0011 FBBB uuuu uu11 1110
+// SBC<.f> 0,b,limm 0010 0bbb 0000 0011 FBBB 1111 1011 1110 (+ Limm)
+// SBC<.cc><.f> 0,limm,c 0010 0110 1100 0011 F111 CCCC CC0Q QQQQ (+ Limm)
+// +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+ return handleop32_general(op, handleop32_SBC_do_op); // SBC
+ }
+ case 0x04:
+ {
+// +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+// AND<.f> a,b,c 0010 0bbb 0000 0100 FBBB CCCC CCAA AAAA
+// AND<.f> a,b,u6 0010 0bbb 0100 0100 FBBB uuuu uuAA AAAA
+// AND<.f> b,b,s12 0010 0bbb 1000 0100 FBBB ssss ssSS SSSS
+// AND<.cc><.f> b,b,c 0010 0bbb 1100 0100 FBBB CCCC CC0Q QQQQ
+// AND<.cc><.f> b,b,u6 0010 0bbb 1100 0100 FBBB uuuu uu1Q QQQQ
+// AND<.f> a,limm,c 0010 0110 0000 0100 F111 CCCC CCAA AAAA (+ Limm)
+// AND<.f> a,b,limm 0010 0bbb 0000 0100 FBBB 1111 10AA AAAA (+ Limm)
+// AND<.cc><.f> b,b,limm 0010 0bbb 1100 0100 FBBB 1111 100Q QQQQ (+ Limm)
+//
+// AND<.f> 0,b,c 0010 0bbb 0000 0100 FBBB CCCC CC11 1110
+// AND<.f> 0,b,u6 0010 0bbb 0100 0100 FBBB uuuu uu11 1110
+// AND<.f> 0,b,limm 0010 0bbb 0000 0100 FBBB 1111 1011 1110 (+ Limm)
+// AND<.cc><.f> 0,limm,c 0010 0110 1100 0100 F111 CCCC CC0Q QQQQ (+ Limm)
+// +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+ return handleop32_general(op, handleop32_AND_do_op); // AND
+ }
+ case 0x05:
+ {
+// +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+// OR<.f> a,b,c 0010 0bbb 0000 0101 FBBB CCCC CCAA AAAA
+// OR<.f> a,b,u6 0010 0bbb 0100 0101 FBBB uuuu uuAA AAAA
+// OR<.f> b,b,s12 0010 0bbb 1000 0101 FBBB ssss ssSS SSSS
+// OR<.cc><.f> b,b,c 0010 0bbb 1100 0101 FBBB CCCC CC0Q QQQQ
+// OR<.cc><.f> b,b,u6 0010 0bbb 1100 0101 FBBB uuuu uu1Q QQQQ
+// OR<.f> a,limm,c 0010 0110 0000 0101 F111 CCCC CCAA AAAA (+ Limm)
+// OR<.f> a,b,limm 0010 0bbb 0000 0101 FBBB 1111 10AA AAAA (+ Limm)
+// OR<.cc><.f> b,b,limm 0010 0bbb 1100 0101 FBBB 1111 100Q QQQQ (+ Limm)
+//
+// OR<.f> 0,b,c 0010 0bbb 0000 0101 FBBB CCCC CC11 1110
+// OR<.f> 0,b,u6 0010 0bbb 0100 0101 FBBB uuuu uu11 1110
+// OR<.f> 0,b,limm 0010 0bbb 0000 0101 FBBB 1111 1011 1110 (+ Limm)
+// OR<.cc><.f> 0,limm,c 0010 0110 1100 010 1 F111 CCCC CC0Q QQQQ (+ Limm)
+// +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+ return handleop32_general(op, handleop32_OR_do_op); // OR
+ }
+ case 0x06:
+ {
+// +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+// IIII I SS SSSS
+// BIC<.f> a,b,c 0010 0bbb 0000 0110 FBBB CCCC CCAA AAAA
+// BIC<.f> a,b,u6 0010 0bbb 0100 0110 FBBB uuuu uuAA AAAA
+// BIC<.f> b,b,s12 0010 0bbb 1000 0110 FBBB ssss ssSS SSSS
+// BIC<.cc><.f> b,b,c 0010 0bbb 1100 0110 FBBB CCCC CC0Q QQQQ
+// BIC<.cc><.f> b,b,u6 0010 0bbb 1100 0110 FBBB uuuu uu1Q QQQQ
+// BIC<.f> a,limm,c 0010 0110 0000 0110 F111 CCCC CCAA AAAA (+ Limm)
+// BIC<.f> a,b,limm 0010 0bbb 0000 0110 FBBB 1111 10AA AAAA (+ Limm)
+// BIC<.cc><.f> b,b,limm 0010 0bbb 1100 0110 FBBB 1111 100Q QQQQ (+ Limm)
+//
+// BIC<.f> 0,b,c 0010 0bbb 0000 0110 FBBB CCCC CC11 1110
+// BIC<.f> 0,b,u6 0010 0bbb 0100 0110 FBBB uuuu uu11 1110
+// BIC<.f> 0,b,limm 0010 0bbb 0000 0110 FBBB 1111 1011 1110 (+ Limm)
+// BIC<.cc><.f> 0,limm,c 0010 0110 1100 0110 F111 CCCC CC0Q QQQQ (+ Limm)
+// +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+ return handleop32_general(op, handleop32_BIC_do_op); // BIC
+ }
+ case 0x07:
+ {
+// +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+// IIII I SS SSSS
+// XOR<.f> a,b,c 0010 0bbb 0000 0111 FBBB CCCC CCAA AAAA
+// XOR<.f> a,b,u6 0010 0bbb 0100 0111 FBBB uuuu uuAA AAAA
+// XOR<.f> b,b,s12 0010 0bbb 1000 0111 FBBB ssss ssSS SSSS
+// XOR<.cc><.f> b,b,c 0010 0bbb 1100 0111 FBBB CCCC CC0Q QQQQ
+// XOR<.cc><.f> b,b,u6 0010 0bbb 1100 0111 FBBB uuuu uu1Q QQQQ
+// XOR<.f> a,limm,c 0010 0110 0000 0111 F111 CCCC CCAA AAAA (+ Limm)
+// XOR<.f> a,b,limm 0010 0bbb 0000 0111 FBBB 1111 10AA AAAA (+ Limm)
+// XOR<.cc><.f> b,b,limm 0010 0bbb 1100 0111 FBBB 1111 100Q QQQQ (+ Limm)
+//
+// XOR<.f> 0,b,c 0010 0bbb 0000 0111 FBBB CCCC CC11 1110
+// XOR<.f> 0,b,u6 0010 0bbb 0100 0111 FBBB uuuu uu11 1110
+// XOR<.f> 0,b,limm 0010 0bbb 0000 0111 FBBB 1111 1011 1110 (+ Limm)
+// XOR<.cc><.f> 0,limm,c 0010 0110 1100 0111 F111 CCCC CC0Q QQQQ (+ Limm)
+// +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+ return handleop32_general(op, handleop32_XOR_do_op); // XOR
+ }
+ case 0x08:
+ {
+// +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+// IIII I SS SSSS
+// MAX<.f> a,b,c 0010 0bbb 0000 1000 FBBB CCCC CCAA AAAA
+// MAX<.f> a,b,u6 0010 0bbb 0100 1000 FBBB uuuu uuAA AAAA
+// MAX<.f> b,b,s12 0010 0bbb 1000 1000 FBBB ssss ssSS SSSS
+// MAX<.cc><.f> b,b,c 0010 0bbb 1100 1000 FBBB CCCC CC0Q QQQQ
+// MAX<.cc><.f> b,b,u6 0010 0bbb 1100 1000 FBBB uuuu uu1Q QQQQ
+// MAX<.f> a,limm,c 0010 0110 0000 1000 F111 CCCC CCAA AAAA (+ Limm)
+// MAX<.f> a,b,limm 0010 0bbb 0000 1000 FBBB 1111 10AA AAAA (+ Limm)
+// MAX<.cc><.f> b,b,limm 0010 0bbb 1100 1000 FBBB 1111 100Q QQQQ (+ Limm)
+//
+// MAX<.f> 0,b,c 0010 0bbb 0000 1000 FBBB CCCC CC11 1110
+// MAX<.f> 0,b,u6 0010 0bbb 0100 1000 FBBB uuuu uu11 1110
+// MAX<.f> 0,b,limm 0010 0bbb 0000 1000 FBBB 1111 1011 1110 (+ Limm)
+// MAX<.cc><.f> 0,limm,c 0010 0110 1100 1000 F111 CCCC CC0Q QQQQ (+ Limm)
+// +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+ return handleop32_general(op, handleop32_MAX_do_op); // MAX
+ }
+ case 0x09:
+ {
+// +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+// IIII I SS SSSS
+// MIN<.f> a,b,c 0010 0bbb 0000 1001 FBBB CCCC CCAA AAAA
+// MIN<.f> a,b,u6 0010 0bbb 0100 1001 FBBB uuuu uuAA AAAA
+// MIN<.f> b,b,s12 0010 0bbb 1000 1001 FBBB ssss ssSS SSSS
+// MIN<.cc><.f> b,b,c 0010 0bbb 1100 1001 FBBB CCCC CC0Q QQQQ
+// MIN<.cc><.f> b,b,u6 0010 0bbb 1100 1001 FBBB uuuu uu1Q QQQQ
+// MIN<.f> a,limm,c 0010 0110 0000 1001 F111 CCCC CCAA AAAA (+ Limm)
+// MIN<.f> a,b,limm 0010 0bbb 0000 1001 FBBB 1111 10AA AAAA (+ Limm)
+// MIN<.cc><.f> b,b,limm 0010 0bbb 1100 1001 FBBB 1111 100Q QQQQ (+ Limm)
+//
+// MIN<.f> 0,b,c 0010 0bbb 0000 1001 FBBB CCCC CC11 1110
+// MIN<.f> 0,b,u6 0010 0bbb 0100 1001 FBBB uuuu uu11 1110
+// MIN<.f> 0,b,limm 0010 0bbb 0000 1001 FBBB 1111 1011 1110 (+ Limm)
+// MIN<.cc><.f> 0,limm,c 0010 0110 1100 1001 F111 CCCC CC0Q QQQQ (+ Limm)
+// +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+ return handleop32_general(op, handleop32_MIN_do_op); // MIN
+ }
+ case 0x0a:
+ {
+// +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+// IIII I SS SSSS
+// MOV<.f> b,s12 0010 0bbb 1000 1010 FBBB ssss ssSS SSSS
+// MOV<.cc><.f> b,c 0010 0bbb 1100 1010 FBBB CCCC CC0Q QQQQ
+// MOV<.cc><.f> b,u6 0010 0bbb 1100 1010 FBBB uuuu uu1Q QQQQ
+// MOV<.cc><.f> b,limm 0010 0bbb 1100 1010 FBBB 1111 100Q QQQQ (+ Limm)
+//
+// MOV<.f> 0,s12 0010 0110 1000 1010 F111 ssss ssSS SSSS
+// MOV<.cc><.f> 0,c 0010 0110 1100 1010 F111 CCCC CC0Q QQQQ
+// MOV<.cc><.f> 0,u6 0010 0110 1100 1010 F111 uuuu uu1Q QQQQ
+// MOV<.cc><.f> 0,limm 0010 0110 1100 1010 F111 1111 100Q QQQQ (+ Limm)
+//
+// NOP 0010 0110 0100 1010 0111 0000 0000 0000 (NOP is a custom encoded MOV?)
+// +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+ return handleop32_MOV(op); // MOV
+ }
+ case 0x0b:
+ {
+// +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+// IIII I SS SSSS
+// TST b,s12 0010 0bbb 1000 1011 1BBB ssss ssSS SSSS
+// TST<.cc> b,c 0010 0bbb 1100 1011 1BBB CCCC CC0Q QQQQ
+// TST<.cc> b,u6 0010 0bbb 1100 1011 1BBB uuuu uu1Q QQQQ
+// TST<.cc> b,limm 0010 0bbb 1100 1011 1BBB 1111 100Q QQQQ (+ Limm)
+// TST<.cc> limm,c 0010 0110 1100 1011 1111 CCCC CC0Q QQQQ (+ Limm)
+// +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+ return handleop32_general_nowriteback_forced_flag(op, handleop32_TST_do_op); // TST
+ }
+ case 0x0c:
+ {
+// +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+// IIII I SS SSSS
+// CMP b,s12 0010 0bbb 1000 1100 1BBB ssss ssSS SSSS
+// CMP<.cc> b,c 0010 0bbb 1100 1100 1BBB CCCC CC0Q QQQQ
+// CMP<.cc> b,u6 0010 0bbb 1100 1100 1BBB uuuu uu1Q QQQQ
+// CMP<.cc> b,limm 0010 0bbb 1100 1100 1BBB 1111 100Q QQQQ (+ Limm)
+// CMP<.cc> limm,c 0010 0110 1100 1100 1111 CCCC CC0Q QQQQ (+ Limm)
+// +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+ return handleop32_general_nowriteback_forced_flag(op, handleop32_CMP_do_op); // CMP
+ }
+ case 0x0d:
+ {
+// +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+// RCMP b,s12 0010 0bbb 1000 1101 1BBB ssss ssSS SSSS
+// RCMP<.cc> b,c 0010 0bbb 1100 1101 1BBB CCCC CC0Q QQQQ
+// RCMP<.cc> b,u6 0010 0bbb 1100 1101 1BBB uuuu uu1Q QQQQ
+// RCMP<.cc> b,limm 0010 0bbb 1100 1101 1BBB 1111 100Q QQQQ (+ Limm)
+// RCMP<.cc> limm,c 0010 0110 1100 1101 1111 CCCC CC0Q QQQQ (+ Limm)
+// +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+ return handleop32_general_nowriteback_forced_flag(op, handleop32_RCMP_do_op); // RCMP
+ }
+ case 0x0e:
+ {
+// +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+// RSUB<.f> a,b,c 0010 0bbb 0000 1110 FBBB CCCC CCAA AAAA
+// RSUB<.f> a,b,u6 0010 0bbb 0100 1110 FBBB uuuu uuAA AAAA
+// NEG<.f> a,b 0010 0bbb 0100 1110 FBBB 0000 00AA AAAA (NEG is an alias)
+//
+// RSUB<.f> b,b,s12 0010 0bbb 1000 1110 FBBB ssss ssSS SSSS
+// RSUB<.cc><.f> b,b,c 0010 0bbb 1100 1110 FBBB CCCC CC0Q QQQQ
+// RSUB<.cc><.f> b,b,u6 0010 0bbb 1100 1110 FBBB uuuu uu1Q QQQQ
+// NEG<.cc><.f> b,b 0010 0bbb 1100 1110 FBBB 0000 001Q QQQQ (NEG is an alias)
+//
+// RSUB<.f> a,limm,c 0010 0110 0000 1110 F111 CCCC CCAA AAAA (+ Limm)
+// RSUB<.f> a,b,limm 0010 0bbb 0000 1110 FBBB 1111 10AA AAAA (+ Limm)
+// RSUB<.cc><.f> b,b,limm 0010 0bbb 1100 1110 FBBB 1111 100Q QQQQ (+ Limm)
+//
+// RSUB<.f> 0,b,c 0010 0bbb 0000 1110 FBBB CCCC CC11 1110
+// RSUB<.f> 0,b,u6 0010 0bbb 0100 1110 FBBB uuuu uu11 1110
+// RSUB<.f> 0,b,limm 0010 0bbb 0000 1110 FBBB 1111 1011 1110 (+ Limm)
+// RSUB<.cc><.f> 0,limm,c 0010 0110 1100 1110 F111 CCCC CC0Q QQQQ (+ Limm)
+//
+// IIII I SS SSSS
+// +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+ return handleop32_general(op, handleop32_RSUB_do_op); // RSUB
+ }
+ case 0x0f:
+ {
+// +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+// BSET<.f> a,b,c 0010 0bbb 0000 1111 FBBB CCCC CCAA AAAA
+// BSET<.f> a,b,u6 0010 0bbb 0100 1111 FBBB uuuu uuAA AAAA
+// BSET<.cc><.f> b,b,c 0010 0bbb 1100 1111 FBBB CCCC CC0Q QQQQ
+// BSET<.cc><.f> b,b,u6 0010 0bbb 1100 1111 FBBB uuuu uu1Q QQQQ
+// BSET<.f> a,limm,c 0010 0110 0000 1111 F111 CCCC CCAA AAAA (+ Limm)
+//
+// BSET<.f> 0,b,c 0010 0bbb 0000 1111 FBBB CCCC CC11 1110
+// BSET<.f> 0,b,u6 0010 0bbb 0100 1111 FBBB uuuu uu11 1110
+// BSET<.cc><.f> 0,limm,c 0010 0110 1100 1111 F110 CCCC CC0Q QQQQ (+ Limm)
+// +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+ return handleop32_general(op, handleop32_BSET_do_op); // BSET
+ }
+ case 0x10:
+ {
+// +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+// BCLR<.f> a,b,c 0010 0bbb 0001 0000 FBBB CCCC CCAA AAAA
+// BCLR<.f> a,b,u6 0010 0bbb 0101 0000 FBBB uuuu uuAA AAAA
+// BCLR<.cc><.f> b,b,c 0010 0bbb 1101 0000 FBBB CCCC CC0Q QQQQ
+// BCLR<.cc><.f> b,b,u6 0010 0bbb 1101 0000 FBBB uuuu uu1Q QQQQ
+// BCLR<.f> a,limm,c 0010 0110 0001 0000 F111 CCCC CCAA AAAA (+ Limm)
+//
+// BCLR<.f> 0,b,c 0010 0bbb 0001 0000 FBBB CCCC CC11 1110
+// BCLR<.f> 0,b,u6 0010 0bbb 0101 0000 FBBB uuuu uu11 1110
+// BCLR<.cc><.f> 0,limm,c 0010 0110 1101 0000 F111 CCCC CC0Q QQQQ (+ Limm)
+// +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+ return handleop32_general(op, handleop32_BCLR_do_op); // BCLR
+ }
+ case 0x11:
+ {
+// +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+// BTST<.cc> b,c 0010 0bbb 1101 0001 1BBB CCCC CC0Q QQQQ
+// BTST<.cc> b,u6 0010 0bbb 1101 0001 1BBB uuuu uu1Q QQQQ
+// BTST<.cc> limm,c 0010 0110 1101 0001 1111 CCCC CC0Q QQQQ (+ Limm)
+// +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+ return handleop32_general_nowriteback_forced_flag(op, handleop32_BTST_do_op); // BTST
+ }
+ case 0x12:
+ {
+// +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+// BXOR<.f> a,b,c 0010 0bbb 0001 0010 FBBB CCCC CCAA AAAA
+// BXOR<.f> a,b,u6 0010 0bbb 0101 0010 FBBB uuuu uuAA AAAA
+// BXOR<.cc><.f> b,b,c 0010 0bbb 1101 0010 FBBB CCCC CC0Q QQQQ
+// BXOR<.cc><.f> b,b,u6 0010 0bbb 1101 0010 FBBB uuuu uu1Q QQQQ
+// BXOR<.f> a,limm,c 0010 0110 0001 0010 F111 CCCC CCAA AAAA (+ Limm)
+//
+// BXOR<.f> 0,b,c 0010 0bbb 0001 0010 FBBB CCCC CC11 1110
+// BXOR<.f> 0,b,u6 0010 0bbb 0101 0010 FBBB uuuu uu11 1110
+// BXOR<.cc><.f> 0,limm,c 0010 0110 1101 0010 F111 CCCC CC0Q QQQQ (+ Limm)
+// +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+ return handleop32_general(op, handleop32_BXOR_do_op); // BXOR
+ }
+ case 0x13:
+ {
+// +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+// BMSK<.f> a,b,c 0010 0bbb 0001 0011 FBBB CCCC CCAA AAAA
+// BMSK<.f> a,b,u6 0010 0bbb 0101 0011 FBBB uuuu uuAA AAAA
+// BMSK<.cc><.f> b,b,c 0010 0bbb 1101 0011 FBBB CCCC CC0Q QQQQ
+// BMSK<.cc><.f> b,b,u6 0010 0bbb 1101 0011 FBBB uuuu uu1Q QQQQ
+// BMSK<.f> a,limm,c 0010 0110 0001 0011 F111 CCCC CCAA AAAA (+ Limm)
+//
+// BMSK<.f> 0,b,c 0010 0bbb 0001 0011 FBBB CCCC CC11 1110
+// BMSK<.f> 0,b,u6 0010 0bbb 0101 0011 FBBB uuuu uu11 1110
+// BMSK<.cc><.f> 0,limm,c 0010 0110 1101 0011 F111 CCCC CC0Q QQQQ (+ Limm)
+// +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+ return handleop32_general(op, handleop32_BMSK_do_op); // BMSK
+ }
+ case 0x14:
+ {
+// +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+// IIII I SS SSSS
+// ADD1<.f> a,b,c 0010 0bbb 0001 0100 FBBB CCCC CCAA AAAA
+// ADD1<.f> a,b,u6 0010 0bbb 0101 0100 FBBB uuuu uuAA AAAA
+// ADD1<.f> b,b,s12 0010 0bbb 1001 0100 FBBB ssss ssSS SSSS
+// ADD1<.cc><.f> b,b,c 0010 0bbb 1101 0100 FBBB CCCC CC0Q QQQQ
+// ADD1<.cc><.f> b,b,u6 0010 0bbb 1101 0100 FBBB uuuu uu1Q QQQQ
+// ADD1<.f> a,limm,c 0010 0110 0001 0100 F111 CCCC CCAA AAAA (+ Limm)
+// ADD1<.f> a,b,limm 0010 0bbb 0001 0100 FBBB 1111 10AA AAAA (+ Limm)
+// ADD1<.cc><.f> b,b,limm 0010 0bbb 1101 0100 FBBB 1111 100Q QQQQ (+ Limm)
+//
+// ADD1<.f> 0,b,c 0010 0bbb 0001 0100 FBBB CCCC CC11 1110
+// ADD1<.f> 0,b,u6 0010 0bbb 0101 0100 FBBB uuuu uu11 1110
+// ADD1<.f> 0,b,limm 0010 0bbb 0001 0100 FBBB 1111 1011 1110 (+ Limm)
+// ADD1<.cc><.f> 0,limm,c 0010 0110 1101 0100 F111 CCCC CC0Q QQQQ (+ Limm)
+// +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+ return handleop32_general(op, handleop32_ADD1_do_op); // ADD1
+ }
+ case 0x15:
+ {
+// +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+// IIII I SS SSSS
+// ADD2<.f> a,b,c 0010 0bbb 0001 0101 FBBB CCCC CCAA AAAA
+// ADD2<.f> a,b,u6 0010 0bbb 0101 0101 FBBB uuuu uuAA AAAA
+// ADD2<.f> b,b,s12 0010 0bbb 1001 0101 FBBB ssss ssSS SSSS
+// ADD2<.cc><.f> b,b,c 0010 0bbb 1101 0101 FBBB CCCC CC0Q QQQQ
+// ADD2<.cc><.f> b,b,u6 0010 0bbb 1101 0101 FBBB uuuu uu1Q QQQQ
+// ADD2<.f> a,limm,c 0010 0110 0001 0101 F111 CCCC CCAA AAAA (+ Limm)
+// ADD2<.f> a,b,limm 0010 0bbb 0001 0101 FBBB 1111 10AA AAAA (+ Limm)
+// ADD2<.cc><.f> b,b,limm 0010 0bbb 1101 0101 FBBB 1111 100Q QQQQ (+ Limm)
+//
+// ADD2<.f> 0,b,c 0010 0bbb 0001 0101 FBBB CCCC CC11 1110
+// ADD2<.f> 0,b,u6 0010 0bbb 0101 0101 FBBB uuuu uu11 1110
+// ADD2<.f> 0,b,limm 0010 0bbb 0001 0101 FBBB 1111 1011 1110 (+ Limm)
+// ADD2<.cc><.f> 0,limm,c 0010 0110 1101 0101 F111 CCCC CC0Q QQQQ (+ Limm)
+// +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+ return handleop32_general(op, handleop32_ADD2_do_op); // ADD2
+ }
+ case 0x16:
+ {
+// +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+// IIII I SS SSSS
+// ADD3<.f> a,b,c 0010 0bbb 0001 0110 FBBB CCCC CCAA AAAA
+// ADD3<.f> a,b,u6 0010 0bbb 0101 0110 FBBB uuuu uuAA AAAA
+// ADD3<.f> b,b,s12 0010 0bbb 1001 0110 FBBB ssss ssSS SSSS
+// ADD3<.cc><.f> b,b,c 0010 0bbb 1101 0110 FBBB CCCC CC0Q QQQQ
+// ADD3<.cc><.f> b,b,u6 0010 0bbb 1101 0110 FBBB uuuu uu1Q QQQQ
+// ADD3<.f> a,limm,c 0010 0110 0001 0110 F111 CCCC CCAA AAAA (+ Limm)
+// ADD3<.f> a,b,limm 0010 0bbb 0001 0110 FBBB 1111 10AA AAAA (+ Limm)
+// ADD3<.cc><.f> b,b,limm 0010 0bbb 1101 0110 FBBB 1111 100Q QQQQ (+ Limm)
+//
+// ADD3<.f> 0,b,c 0010 0bbb 0001 0110 FBBB CCCC CC11 1110
+// ADD3<.f> 0,b,u6 0010 0bbb 0101 0110 FBBB uuuu uu11 1110
+// ADD3<.f> 0,b,limm 0010 0bbb 0001 0110 FBBB 1111 1011 1110 (+ Limm)
+// ADD3<.cc><.f> 0,limm,c 0010 0110 1101 0110 F111 CCCC CC0Q QQQQ (+ Limm)
+// +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+ return handleop32_general(op, handleop32_ADD3_do_op); // ADD3
+ }
+ case 0x17:
+ {
+// +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+// IIII I SS SSSS
+// SUB1<.f> a,b,c 0010 0bbb 0001 0111 FBBB CCCC CCAA AAAA
+// SUB1<.f> a,b,u6 0010 0bbb 0101 0111 FBBB uuuu uuAA AAAA
+// SUB1<.f> b,b,s12 0010 0bbb 1001 0111 FBBB ssss ssSS SSSS
+// SUB1<.cc><.f> b,b,c 0010 0bbb 1101 0111 FBBB CCCC CC0Q QQQQ
+// SUB1<.cc><.f> b,b,u6 0010 0bbb 1101 0111 FBBB uuuu uu1Q QQQQ
+// SUB1<.f> a,limm,c 0010 0110 0001 0111 F111 CCCC CCAA AAAA (+ Limm)
+// SUB1<.f> a,b,limm 0010 0bbb 0001 0111 FBBB 1111 10AA AAAA (+ Limm)
+// SUB1<.cc><.f> b,b,limm 0010 0bbb 1101 0111 FBBB 1111 100Q QQQQ (+ Limm)
+//
+// SUB1<.f> 0,b,c 0010 0bbb 0001 0111 FBBB CCCC CC11 1110
+// SUB1<.f> 0,b,u6 0010 0bbb 0101 0111 FBBB uuuu uu11 1110
+// SUB1<.f> 0,b,limm 0010 0bbb 0001 0111 FBBB 1111 1011 1110 (+ Limm)
+// SUB1<.cc><.f> 0,limm,c 0010 0110 1101 0111 F111 CCCC CC0Q QQQQ (+ Limm)
+// +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+ return handleop32_general(op, handleop32_SUB1_do_op); // SUB1
+ }
+ case 0x18:
+ {
+// +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+// IIII I SS SSSS
+// SUB2<.f> a,b,c 0010 0bbb 0001 1000 FBBB CCCC CCAA AAAA
+// SUB2<.f> a,b,u6 0010 0bbb 0101 1000 FBBB uuuu uuAA AAAA
+// SUB2<.f> b,b,s12 0010 0bbb 1001 1000 FBBB ssss ssSS SSSS
+// SUB2<.cc><.f> b,b,c 0010 0bbb 1101 1000 FBBB CCCC CC0Q QQQQ
+// SUB2<.cc><.f> b,b,u6 0010 0bbb 1101 1000 FBBB uuuu uu1Q QQQQ
+// SUB2<.f> a,limm,c 0010 0110 0001 1000 F111 CCCC CCAA AAAA (+ Limm)
+// SUB2<.f> a,b,limm 0010 0bbb 0001 1000 FBBB 1111 10AA AAAA (+ Limm)
+// SUB2<.cc><.f> b,b,limm 0010 0bbb 1101 1000 FBBB 1111 100Q QQQQ (+ Limm)
+//
+// SUB2<.f> 0,b,c 0010 0bbb 0001 1000 FBBB CCCC CC11 1110
+// SUB2<.f> 0,b,u6 0010 0bbb 0101 1000 FBBB uuuu uu11 1110
+// SUB2<.f> 0,b,limm 0010 0bbb 0001 1000 FBBB 1111 1011 1110 (+ Limm)
+// SUB2<.cc><.f> 0,limm,c 0010 0110 1101 1000 F111 CCCC CC0Q QQQQ (+ Limm)
+// +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+ return handleop32_general(op, handleop32_SUB2_do_op); // SUB2
+ }
+ case 0x19:
+ {
+// +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+// IIII I SS SSSS
+// SUB3<.f> a,b,c 0010 0bbb 0001 1001 FBBB CCCC CCAA AAAA
+// SUB3<.f> a,b,u6 0010 0bbb 0101 1001 FBBB uuuu uuAA AAAA
+// SUB3<.f> b,b,s12 0010 0bbb 1001 1001 FBBB ssss ssSS SSSS
+// SUB3<.cc><.f> b,b,c 0010 0bbb 1101 1001 FBBB CCCC CC0Q QQQQ
+// SUB3<.cc><.f> b,b,u6 0010 0bbb 1101 1001 FBBB uuuu uu1Q QQQQ
+// SUB3<.f> a,limm,c 0010 0110 0001 1001 F111 CCCC CCAA AAAA (+ Limm)
+// SUB3<.f> a,b,limm 0010 0bbb 0001 1001 FBBB 1111 10AA AAAA (+ Limm)
+// SUB3<.cc><.f> b,b,limm 0010 0bbb 1101 1001 FBBB 1111 100Q QQQQ (+ Limm)
+//
+// SUB3<.f> 0,b,c 0010 0bbb 0001 1001 FBBB CCCC CC11 1110
+// SUB3<.f> 0,b,u6 0010 0bbb 0101 1001 FBBB uuuu uu11 1110
+// SUB3<.f> 0,limm,c 0010 0110 0001 1001 F111 CCCC CC11 1110 (+ Limm)
+// SUB3<.cc><.f> 0,limm,c 0010 0110 1101 1001 F111 CCCC CC0Q QQQQ (+ Limm)
+// +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+ return handleop32_general(op, handleop32_SUB3_do_op); // SUB3
+ }
+ case 0x1a:
+ {
+// +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+// IIII I SS SSSS
+// MPY<.f> a,b,c 0010 0bbb 0001 1010 FBBB CCCC CCAA AAAA
+// MPY<.f> a,b,u6 0010 0bbb 0101 1010 FBBB uuuu uuAA AAAA
+// MPY<.f> b,b,s12 0010 0bbb 1001 1010 FBBB ssss ssSS SSSS
+// MPY<.cc><.f> b,b,c 0010 0bbb 1101 1010 FBBB CCCC CC0Q QQQQ
+// MPY<.cc><.f> b,b,u6 0010 0bbb 1101 1010 FBBB uuuu uu1Q QQQQ
+// MPY<.f> a,limm,c 0010 0110 0001 1010 F111 CCCC CCAA AAAA (+ Limm)
+// MPY<.f> a,b,limm 0010 0bbb 0001 1010 FBBB 1111 10AA AAAA (+ Limm)
+// MPY<.cc><.f> b,b,limm 0010 0bbb 1101 1010 FBBB 1111 100Q QQQQ (+ Limm)
+//
+// MPY<.f> 0,b,c 0010 0bbb 0001 1010 FBBB CCCC CC11 1110
+// MPY<.f> 0,b,u6 0010 0bbb 0101 1010 FBBB uuuu uu11 1110
+// MPY<.cc><.f> 0,limm,c 0010 0110 1101 1010 F111 CCCC CC0Q QQQQ (+ Limm)
+// +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+ return handleop32_general(op, handleop32_MPY_do_op); // MPY *
+ }
+ case 0x1b:
+ {
+// +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+// IIII I SS SSSS
+// MPYH<.f> a,b,c 0010 0bbb 0001 1011 FBBB CCCC CCAA AAAA
+// MPYH<.f> a,b,u6 0010 0bbb 0101 1011 FBBB uuuu uuAA AAAA
+// MPYH<.f> b,b,s12 0010 0bbb 1001 1011 FBBB ssss ssSS SSSS
+// MPYH<.cc><.f> b,b,c 0010 0bbb 1101 1011 FBBB CCCC CC0Q QQQQ
+// MPYH<.cc><.f> b,b,u6 0010 0bbb 1101 1011 FBBB uuuu uu1Q QQQQ
+// MPYH<.f> a,limm,c 0010 0110 0001 1011 F111 CCCC CCAA AAAA (+ Limm)
+// MPYH<.f> a,b,limm 0010 0bbb 0001 1010 FBBB 1111 10AA AAAA (+ Limm)
+// MPYH<.cc><.f> b,b,limm 0010 0bbb 1101 1011 FBBB 1111 100Q QQQQ (+ Limm)
+//
+// MPYH<.f> 0,b,c 0010 0bbb 0001 1011 FBBB CCCC CC11 1110
+// MPYH<.f> 0,b,u6 0010 0bbb 0101 1011 FBBB uuuu uu11 1110
+// MPYH<.cc><.f> 0,limm,c 0010 0110 1101 1011 F111 CCCC CC0Q QQQQ (+ Limm)
+// +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+ return handleop32_general(op, handleop32_MPYH_do_op); // MPYH *
+ }
+ case 0x1c:
+ {
+// +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+// IIII I SS SSSS
+// MPYHU<.f> a,b,c 0010 0bbb 0001 1100 FBBB CCCC CCAA AAAA
+// MPYHU<.f> a,b,u6 0010 0bbb 0101 1100 FBBB uuuu uuAA AAAA
+// MPYHU<.f> b,b,s12 0010 0bbb 1001 1100 FBBB ssss ssSS SSSS
+// MPYHU<.cc><.f> b,b,c 0010 0bbb 1101 1100 FBBB CCCC CC0Q QQQQ
+// MPYHU<.cc><.f> b,b,u6 0010 0bbb 1101 1100 FBBB uuuu uu1Q QQQQ
+// MPYHU<.f> a,limm,c 0010 0110 0001 1100 F111 CCCC CCAA AAAA (+ Limm)
+// MPYHU<.f> a,b,limm 0010 0bbb 0001 1100 FBBB 1111 10AA AAAA (+ Limm)
+// MPYHU<.cc><.f> b,b,limm 0010 0bbb 1101 1100 FBBB 1111 100Q QQQQ (+ Limm)
+//
+// MPYHU<.f> 0,b,c 0010 0bbb 0001 1100 FBBB CCCC CC11 1110
+// MPYHU<.f> 0,b,u6 0010 0bbb 0101 1100 FBBB uuuu uu11 1110
+// MPYHU<.cc><.f> 0,limm,c 0010 0110 1101 1100 F111 CCCC CC0Q QQQQ (+ Limm)
+// +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+ return handleop32_general(op, handleop32_MPYHU_do_op); // MPYHU *
+ }
+ case 0x1d:
+ {
+// +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+// MPYU<.f> a,b,c 0010 0bbb 0001 1101 FBBB CCCC CCAA AAAA
+// MPYU<.f> a,b,u6 0010 0bbb 0101 1101 FBBB uuuu uuAA AAAA
+// MPYU<.f> b,b,s12 0010 0bbb 1001 1101 FBBB ssss ssSS SSSS
+// MPYU<.cc><.f> b,b,c 0010 0bbb 1101 1101 FBBB CCCC CC0Q QQQQ
+// MPYU<.cc><.f> b,b,u6 0010 0bbb 1101 1101 FBBB uuuu uu1Q QQQQ
+// MPYU<.f> a,limm,c 0010 0110 0001 1101 F111 CCCC CCAA AAAA (+ Limm)
+// MPYU<.f> a,b,limm 0010 0bbb 0001 1101 FBBB 1111 10AA AAAA (+ Limm)
+// MPYU<.cc><.f> b,b,limm 0010 0bbb 1101 1101 FBBB 1111 100Q QQQQ (+ Limm)
+//
+// MPYU<.f> 0,b,c 0010 0bbb 0001 1101 FBBB CCCC CC11 1110
+// MPYU<.f> 0,b,u6 0010 0bbb 0101 1101 FBBB uuuu uu11 1110
+// MPYU<.cc><.f> 0,limm,c 0010 0110 1101 1101 F111 CCCC CC0Q QQQQ (+ Limm)
+// +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+ return handleop32_general(op, handleop32_MPYU_do_op); // MPYU *
+ }
+ case 0x20:
+ {
+// +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+// IIII I SS SSSS
+// Jcc [c] 0010 0RRR 1110 0000 0RRR CCCC CC0Q QQQQ
+// Jcc limm 0010 0RRR 1110 0000 0RRR 1111 100Q QQQQ (+ Limm)
+// Jcc u6 0010 0RRR 1110 0000 0RRR uuuu uu1Q QQQQ
+// Jcc.F [ilink1] 0010 0RRR 1110 0000 1RRR 0111 010Q QQQQ
+// Jcc.F [ilink2] 0010 0RRR 1110 0000 1RRR 0111 100Q QQQQ
+// IIII I SS SSSS
+// J [c] 0010 0RRR 0010 0000 0RRR CCCC CCRR RRRR
+// J.F [ilink1] 0010 0RRR 0010 0000 1RRR 0111 01RR RRRR
+// J.F [ilink2] 0010 0RRR 0010 0000 1RRR 0111 10RR RRRR
+// J limm 0010 0RRR 0010 0000 0RRR 1111 10RR RRRR (+ Limm)
+// J u6 0010 0RRR 0110 0000 0RRR uuuu uuRR RRRR
+// J s12 0010 0RRR 1010 0000 0RRR ssss ssSS SSSS
+// +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+ return handleop32_J(op, false, false); // Jcc
+ }
+ case 0x21:
+ {
+// +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+// IIII I SS SSSS
+// Jcc.D u6 0010 0RRR 1110 0001 0RRR uuuu uu1Q QQQQ
+// Jcc.D [c] 0010 0RRR 1110 0001 0RRR CCCC CC0Q QQQQ
+// +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+// +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+// J.D [c] 0010 0RRR 0010 0001 0RRR CCCC CCRR RRRR
+// J.D u6 0010 0RRR 0110 0001 0RRR uuuu uuRR RRRR
+// J.D s12 0010 0RRR 1010 0001 0RRR ssss ssSS SSSS
+// +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+
+ return handleop32_J(op, true, false); // Jcc.D
+ }
+ case 0x22:
+ {
+// +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+// IIII I SS SSSS
+// JLcc [c] 0010 0RRR 1110 0010 0RRR CCCC CC0Q QQQQ
+// JLcc limm 0010 0RRR 1110 0010 0RRR 1111 100Q QQQQ (+ Limm)
+// JLcc u6 0010 0RRR 1110 0010 0RRR uuuu uu1Q QQQQ
+// JL [c] 0010 0RRR 0010 0010 0RRR CCCC CCRR RRRR
+// JL limm 0010 0RRR 0010 0010 0RRR 1111 10RR RRRR (+ Limm)
+// JL u6 0010 0RRR 0110 0010 0RRR uuuu uuRR RRRR
+// JL s12 0010 0RRR 1010 0010 0RRR ssss ssSS SSSS
+// +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+ return handleop32_J(op, false, true); // JLcc
+ }
+ case 0x23:
+ {
+// +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+// IIII I SS SSSS
+// JLcc.D u6 0010 0RRR 1110 0011 0RRR uuuu uu1Q QQQQ
+// JLcc.D [c] 0010 0RRR 1110 0011 0RRR CCCC CC0Q QQQQ
+// JL.D [c] 0010 0RRR 0010 0011 0RRR CCCC CCRR RRRR
+// JL.D u6 0010 0RRR 0110 0011 0RRR uuuu uuRR RRRR
+// JL.D s12 0010 0RRR 1010 0011 0RRR ssss ssSS SSSS
+// +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+ return handleop32_J(op, true, true); // JLcc.D
+ }
+ case 0x28:
+ {
+// +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+// IIII I SS SSSS
+// LP<cc> u7 0010 0RRR 1110 1000 0RRR uuuu uu1Q QQQQ
+// LP s13 0010 0RRR 1010 1000 0RRR ssss ssSS SSSS
+// +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+ return handleop32_LP(op); // LPcc
+ }
+ case 0x29:
+ {
+// +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+// IIII I SS SSSS
+// FLAG<.cc> c 0010 0rrr 1110 1001 0RRR CCCC CC0Q QQQQ
+// FLAG<.cc> u6 0010 0rrr 1110 1001 0RRR uuuu uu1Q QQQQ
+// FLAG<.cc> limm 0010 0rrr 1110 1001 0RRR 1111 100Q QQQQ (+ Limm)
+// FLAG s12 0010 0rrr 1010 1001 0RRR ssss ssSS SSSS
+// FLAG c (unknown format) 0010 0000 0010 1001 0000 0000 0100 0000 (Leapster BIOS encodes like this? unless it's customized and isn't FLAG?)
+// +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+ return handleop32_FLAG(op); // FLAG
+ }
+ case 0x2a:
+ {
+// +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+// IIII I SS SSSS
+// LR b,[c] 0010 0bbb 0010 1010 0BBB CCCC CCRR RRRR
+// LR b,[limm] 0010 0bbb 0010 1010 0BBB 1111 10RR RRRR (+ Limm)
+// LR b,[u6] 0010 0bbb 0110 1010 0BBB uuuu uu00 0000
+// LR b,[s12] 0010 0bbb 1010 1010 0BBB ssss ssSS SSSS
+// +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+ return handleop32_LR(op); // LR
+ }
+ case 0x2b:
+ {
+// +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+// IIII I SS SSSS
+// SR b,[c] 0010 0bbb 0010 1011 0BBB CCCC CCRR RRRR
+// SR b,[limm] 0010 0bbb 0010 1011 0BBB 1111 10RR RRRR (+ Limm)
+// SR b,[u6] 0010 0bbb 0110 1011 0BBB uuuu uu00 0000
+// SR b,[s12] 0010 0bbb 1010 1011 0BBB ssss ssSS SSSS
+// SR limm,[c] 0010 0110 0010 1011 0111 CCCC CCRR RRRR (+ Limm)
+// SR limm,[u6] 0010 0110 0110 1011 0111 uuuu uu00 0000
+// SR limm,[s12] 0010 0110 1010 1011 0111 ssss ssSS SSSS (+ Limm)
+// +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+ return handleop32_SR(op); // SR
+ }
+ case 0x2f: // Sub Opcode
+ {
+ uint8_t subinstr2 = op & 0x0000003f;
+ switch (subinstr2 & 0x3f)
+ {
+ case 0x00:
+ {
+// +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+// IIII I SS SSSS ss ssss
+// ASL<.f> b,c 0010 0bbb 0010 1111 FBBB CCCC CC00 0000
+// ASL<.f> b,u6 0010 0bbb 0110 1111 FBBB uuuu uu00 0000
+// ASL<.f> b,limm 0010 0bbb 0010 1111 FBBB 1111 1000 0000 (+ Limm)
+//
+// ASL<.f> 0,c 0010 0110 0010 1111 F111 CCCC CC00 0000
+// ASL<.f> 0,u6 0010 0110 0110 1111 F111 uuuu uu00 0000
+// ASL<.f> 0,limm 0010 0110 0010 1111 F111 1111 1000 0000 (+ Limm)
+// +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+ return handleop32_general_SOP_group(op, handleop32_ASL_single_do_op); // ASL
+ }
+ case 0x01:
+ {
+// +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+// IIII I SS SSSS ss ssss
+// ASR<.f> b,c 0010 0bbb 0010 1111 FBBB CCCC CC00 0001
+// ASR<.f> b,u6 0010 0bbb 0110 1111 FBBB uuuu uu00 0001
+// ASR<.f> b,limm 0010 0bbb 0010 1111 FBBB 1111 1000 0001 (+ Limm)
+//
+// ASR<.f> 0,c 0010 0110 0010 1111 F111 CCCC CC00 0001
+// ASR<.f> 0,u6 0010 0110 0110 1111 F111 uuuu uu00 0001
+// ASR<.f> 0,limm 0010 0110 0010 1111 F111 1111 1000 0001 (+ Limm)
+// +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+ return handleop32_general_SOP_group(op, handleop32_ASR_single_do_op); // ASR
+ }
+ case 0x02:
+ {
+// +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+// IIII I SS SSSS ss ssss
+// LSR<.f> b,c 0010 0bbb 0010 1111 FBBB CCCC CC00 0010
+// LSR<.f> b,u6 0010 0bbb 0110 1111 FBBB uuuu uu00 0010
+// LSR<.f> b,limm 0010 0bbb 0010 1111 FBBB 1111 1000 0010 (+ Limm)
+//
+// LSR<.f> 0,c 0010 0110 0010 1111 F111 CCCC CC00 0010
+// LSR<.f> 0,u6 0010 0110 0110 1111 F111 uuuu uu00 0010
+// LSR<.f> 0,limm 0010 0110 0010 1111 F111 1111 1000 0010 (+ Limm)
+// +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+ return handleop32_general_SOP_group(op, handleop32_LSR_single_do_op); // LSR
+ }
+ case 0x03:
+ {
+// +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+// IIII I SS SSSS ss ssss
+// ROR<.f> b,c 0010 0bbb 0010 1111 FBBB CCCC CC00 0011
+// ROR<.f> b,u6 0010 0bbb 0110 1111 FBBB uuuu uu00 0011
+// ROR<.f> b,limm 0010 0bbb 0010 1111 FBBB 1111 1000 0011 (+ Limm)
+//
+// ROR<.f> 0,c 0010 0110 0010 1111 F111 CCCC CC00 0011
+// ROR<.f> 0,u6 0010 0110 0110 1111 F111 uuuu uu00 0011
+// ROR<.f> 0,limm 0010 0110 0010 1111 F111 1111 1000 0011 (+ Limm)
+// +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+ return handleop32_general_SOP_group(op, handleop32_ROR_do_op); // ROR
+ }
+ case 0x04:
+ {
+// +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+// IIII I SS SSSS ss ssss
+// RRC<.f> b,c 0010 0bbb 0010 1111 FBBB CCCC CC00 0100
+// RRC<.f> b,u6 0010 0bbb 0110 1111 FBBB uuuu uu00 0100
+// RRC<.f> b,limm 0010 0bbb 0010 1111 FBBB 1111 1000 0100 (+ Limm)
+//
+// RRC<.f> 0,c 0010 0110 0010 1111 F111 CCCC CC00 0100
+// RRC<.f> 0,u6 0010 0110 0110 1111 F111 uuuu uu00 0100
+// RRC<.f> 0,limm 0010 0110 0010 1111 F111 1111 1000 0100 (+ Limm)
+// +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+ return handleop32_general_SOP_group(op, handleop32_RRC_do_op); // RRC
+ }
+ case 0x05:
+ {
+// +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+// IIII I SS SSSS ss ssss
+// SEXB<.f> b,c 0010 0bbb 0010 1111 FBBB CCCC CC00 0101
+// SEXB<.f> b,u6 0010 0bbb 0110 1111 FBBB uuuu uu00 0101
+// SEXB<.f> b,limm 0010 0bbb 0010 1111 FBBB 1111 1000 0101 (+ Limm)
+//
+// SEXB<.f> 0,c 0010 0110 0010 1111 F111 CCCC CC00 0101
+// SEXB<.f> 0,u6 0010 0110 0110 1111 F111 uuuu uu00 0101
+// SEXB<.f> 0,limm 0010 0110 0010 1111 F111 1111 1000 0101 (+ Limm)
+// +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+ return handleop32_general_SOP_group(op, handleop32_SEXB_do_op); // SEXB
+ }
+ case 0x06:
+ {
+// +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+// IIII I SS SSSS ss ssss
+// SEXW<.f> b,c 0010 0bbb 0010 1111 FBBB CCCC CC00 0110
+// SEXW<.f> b,u6 0010 0bbb 0110 1111 FBBB uuuu uu00 0110
+// SEXW<.f> b,limm 0010 0bbb 0010 1111 FBBB 1111 1000 0110 (+ Limm)
+//
+// SEXW<.f> 0,c 0010 0110 0010 1111 F111 CCCC CC00 0110
+// SEXW<.f> 0,u6 0010 0110 0110 1111 F111 uuuu uu00 0110
+// SEXW<.f> 0,limm 0010 0110 0010 1111 F111 1111 1000 0110 (+ Limm)
+// +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+ return handleop32_general_SOP_group(op, handleop32_SEXW_do_op); // SEXW
+ }
+ case 0x07:
+ {
+// +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+// IIII I SS SSSS ss ssss
+// EXTB<.f> b,c 0010 0bbb 0010 1111 FBBB CCCC CC00 0111
+// EXTB<.f> b,u6 0010 0bbb 0110 1111 FBBB uuuu uu00 0111
+// EXTB<.f> b,limm 0010 0bbb 0010 1111 FBBB 1111 1000 0111 (+ Limm)
+//
+// EXTB<.f> 0,c 0010 0110 0010 1111 F111 CCCC CC00 0111
+// EXTB<.f> 0,u6 0010 0110 0110 1111 F111 uuuu uu00 0111
+// EXTB<.f> 0,limm 0010 0110 0010 1111 F111 1111 1000 0111 (+ Limm)
+// +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+ return handleop32_general_SOP_group(op, handleop32_EXTB_do_op); // EXTB
+ }
+ case 0x08:
+ {
+// +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+// IIII I SS SSSS ss ssss
+// EXTW<.f> b,c 0010 0bbb 0010 1111 FBBB CCCC CC00 1000
+// EXTW<.f> b,u6 0010 0bbb 0110 1111 FBBB uuuu uu00 1000
+// EXTW<.f> b,limm 0010 0bbb 0010 1111 FBBB 1111 1000 1000 (+ Limm)
+//
+// EXTW<.f> 0,c 0010 0110 0010 1111 F111 CCCC CC00 1000
+// EXTW<.f> 0,u6 0010 0110 0110 1111 F111 uuuu uu00 1000
+// EXTW<.f> 0,limm 0010 0110 0010 1111 F111 1111 1000 1000 (+ Limm)
+// +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+ return handleop32_general_SOP_group(op, handleop32_EXTW_do_op); // EXTW
+ }
+ case 0x09:
+ {
+// +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+// IIII I SS SSSS ss ssss
+// ABS<.f> b,c 0010 0bbb 0010 1111 FBBB CCCC CC00 1001
+// ABS<.f> b,u6 0010 0bbb 0110 1111 FBBB uuuu uu00 1001
+// ABS<.f> b,limm 0010 0bbb 0010 1111 FBBB 1111 1000 1001 (+ Limm)
+//
+// ABS<.f> 0,c 0010 0110 0010 1111 F111 CCCC CC00 1001
+// ABS<.f> 0,u6 0010 0110 0110 1111 F111 uuuu uu00 1001
+// ABS<.f> 0,limm 0010 0110 0010 1111 F111 1111 1000 1001 (+ Limm)
+// +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+ return handleop32_general_SOP_group(op, handleop32_ABS_do_op); // ABS
+ }
+ case 0x0a:
+ {
+// +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+// IIII I SS SSSS ss ssss
+// NOT<.f> b,c 0010 0bbb 0010 1111 FBBB CCCC CC00 1010
+// NOT<.f> b,u6 0010 0bbb 0110 1111 FBBB uuuu uu00 1010
+// NOT<.f> b,limm 0010 0bbb 0010 1111 FBBB 1111 1000 1010 (+ Limm)
+//
+// NOT<.f> 0,c 0010 0110 0010 1111 F111 CCCC CC00 1010
+// NOT<.f> 0,u6 0010 0110 0110 1111 F111 uuuu uu00 1010
+// NOT<.f> 0,limm 0010 0110 0010 1111 F111 1111 1000 1010 (+ Limm)
+//
+// +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+ return handleop32_general_SOP_group(op, handleop32_NOT_do_op); // NOT
+ }
+ case 0x0b:
+ {
+// +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+// IIII I SS SSSS ss ssss
+// RLC<.f> b,c 0010 0bbb 0010 1111 FBBB CCCC CC00 1011
+// RLC<.f> b,u6 0010 0bbb 0110 1111 FBBB uuuu uu00 1011
+// RLC<.f> b,limm 0010 0bbb 0010 1111 FBBB 1111 1000 1011 (+ Limm)
+//
+// RLC<.f> 0,c 0010 0110 0010 1111 F111 CCCC CC00 1011
+// RLC<.f> 0,u6 0010 0110 0110 1111 F111 uuuu uu00 1011
+// RLC<.f> 0,limm 0010 0110 0010 1111 F111 1111 1000 1011 (+ Limm)
+// +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+ return handleop32_general_SOP_group(op, handleop32_RLC_do_op); // RLC
+ }
+ case 0x0c:
+ {
+// +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+// IIII I SS SSSS ss ssss
+// EX<.di> b,[c] 0010 0bbb 0010 1111 DBBB CCCC CC00 1100
+// EX<.di> b,[u6] 0010 0bbb 0110 1111 DBBB uuuu uu00 1100
+// EX<.di> b,[limm] 0010 0bbb 0010 1111 DBBB 1111 1000 1100 (+ Limm)
+// +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+ return handleop32_EX(op); // EX
+ }
+ case 0x3f: // ZOPs (Zero Operand Opcodes)
+ {
+ uint8_t subinstr3 = (op & 0x07000000) >> 24;
+ subinstr3 |= ((op & 0x00007000) >> 12) << 3;
+
+ switch (subinstr3 & 0x3f)
+ {
+ case 0x01:
+ {
+// +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+// IIII I$$$ SS SSSS $$$ ss ssss
+// SLEEP <u6> 0010 0001 0110 1111 0000 uuuu uu11 1111
+// SLEEP c 0010 0001 0010 1111 0000 CCCC CC11 1111
+// +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+ return handleop32_SLEEP(op); // SLEEP
+ }
+ case 0x02:
+ {
+// +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+// IIII I$$$ SS SSSS $$$ ss ssss
+// SWI/TRAP0 0010 0010 0110 1111 0000 0000 0011 1111
+// +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+ return handleop32_SWI(op); // SWI / TRAP0
+ }
+ case 0x03:
+ {
+// +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+// IIII I$$$ SS SSSS $$$ ss ssss
+// SYNC 0010 0011 0110 1111 0000 0000 0011 1111
+// +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+ return handleop32_SYNC(op); // SYNC
+ }
+ case 0x04:
+ {
+// +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+// IIII I$$$ SS SSSS $$$ ss ssss
+// RTIE 0010 0100 0110 1111 0000 0000 0011 1111
+// +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+ return handleop32_RTIE(op); // RTIE
+ }
+ case 0x05:
+ {
+// +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+// IIII I$$$ SS SSSS $$$ ss ssss
+// BRK 0010 0101 0110 1111 0000 0000 0011 1111
+// +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+ return handleop32_BRK(op); // BRK
+ }
+
+ default:
+ {
+ // 0x00, 0x06-0x3f
+ return arcompact_handle_illegal(instruction, subinstr, subinstr2, subinstr3, op); // illegal
+ }
+ }
+ }
+ default:
+ {
+ // 0x0d - 0x3e
+ return arcompact_handle_illegal(instruction, subinstr, subinstr2, op); // illegal
+ }
+ }
+ }
+
+// +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+// IIII I SS SSSS
+// LD<zz><.x><.aa><.di> a,[b,c] 0010 0bbb aa11 0ZZX DBBB CCCC CCAA AAAA
+// LD<zz><.x><.aa><.di> 0,[b,c] 0010 0bbb aa11 0ZZX DBBB CCCC CC11 1110
+// PREFETCH<.aa> [b,c] 0010 0bbb aa11 0000 0BBB CCCC CC11 1110 (prefetch is an alias)
+//
+// LD<zz><.x><.aa><.di> a,[b,limm] 0010 0bbb aa11 0ZZX DBBB 1111 10AA AAAA (+ Limm)
+// LD<zz><.x><.aa><.di> 0,[b,limm] 0010 0bbb aa11 0ZZX DBBB 1111 1011 1110 (+ Limm)
+// PREFETCH<.aa> [b,limm] 0010 0bbb aa11 0000 0BBB 1111 1011 1110 (+ Limm) (prefetch is an alias)
+//
+// LD<zz><.x><.di> a,[limm,c] 0010 0110 RR11 0ZZX D111 CCCC CCAA AAAA (+ Limm)
+// LD<zz><.x><.di> 0,[limm,c] 0010 0110 RR11 0ZZX D111 CCCC CC11 1110 (+ Limm)
+// PREFETCH [limm,c] 0010 0110 RR11 0000 0111 CCCC CC11 1110 (+ Limm) (prefetch is an alias)
+// +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+ case 0x30: case 0x31: case 0x32: case 0x33: case 0x34: case 0x35: case 0x36: case 0x37:
+ {
+ return handleop32_LDrr(op, (op >> 17) & 3, (op >> 16) & 1); // LD r-r
+ }
+ default:
+ {
+ return arcompact_handle_illegal(instruction, subinstr, op); // illegal
+ }
+ }
+ }
+ case 0x05: // op a,b,c (05 ARC ext)
+ {
+ uint8_t subinstr = (op & 0x003f0000) >> 16;
+
+ switch (subinstr)
+ {
+ case 0x00:
+ {
+// +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+// IIII I SS SSSS
+// ASL<.f> a,b,c 0010 1bbb 0000 0000 FBBB CCCC CCAA AAAA
+// ASL<.f> a,b,u6 0010 1bbb 0100 0000 FBBB uuuu uuAA AAAA
+// ASL<.f> b,b,s12 0010 1bbb 1000 0000 FBBB ssss ssSS SSSS
+// ASL<.cc><.f> b,b,c 0010 1bbb 1100 0000 FBBB CCCC CC0Q QQQQ
+// ASL<.cc><.f> b,b,u6 0010 1bbb 1100 0000 FBBB uuuu uu1Q QQQQ
+// ASL<.f> a,limm,c 0010 1110 0000 0000 F111 CCCC CCAA AAAA (+ Limm)
+// ASL<.f> a,b,limm 0010 1bbb 0000 0000 FBBB 1111 10AA AAAA (+ Limm)
+// ASL<.cc><.f> b,b,limm 0010 1bbb 1100 0000 FBBB 1111 100Q QQQQ (+ Limm)
+//
+// ASL<.f> 0,b,c 0010 1bbb 0000 0000 FBBB CCCC CC11 1110
+// ASL<.f> 0,b,u6 0010 1bbb 0100 0000 FBBB uuuu uu11 1110
+// ASL<.cc><.f> 0,limm,c 0010 1110 1100 0000 F111 CCCC CC0Q QQQQ (+ Limm)
+// +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+ return handleop32_general(op, handleop32_ASL_multiple_do_op); // ASL
+ }
+ case 0x01:
+ {
+// +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+// LSR<.f> a,b,c 0010 1bbb 0000 0001 FBBB CCCC CCAA AAAA
+// LSR<.f> a,b,u6 0010 1bbb 0100 0001 FBBB uuuu uuAA AAAA
+// LSR<.f> b,b,s12 0010 1bbb 1000 0001 FBBB ssss ssSS SSSS
+// LSR<.cc><.f> b,b,c 0010 1bbb 1100 0001 FBBB CCCC CC0Q QQQQ
+// LSR<.cc><.f> b,b,u6 0010 1bbb 1100 0001 FBBB uuuu uu1Q QQQQ
+// LSR<.f> a,limm,c 0010 1110 0000 0001 F111 CCCC CCAA AAAA (+ Limm)
+// LSR<.f> a,b,limm 0010 1bbb 0000 0001 FBBB 1111 10AA AAAA (+ Limm)
+// LSR<.cc><.f> b,b,limm 0010 1bbb 1100 0001 FBBB 1111 100Q QQQQ (+ Limm)
+//
+// LSR<.f> 0,b,c 0010 1bbb 0000 0001 FBBB CCCC CC11 1110
+// LSR<.f> 0,b,u6 0010 1bbb 0100 0001 FBBB uuuu uu11 1110
+// LSR<.cc><.f> 0,limm,c 0010 1110 1100 0001 F111 CCCC CC0Q QQQQ (+ Limm)
+// +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+ return handleop32_general(op, handleop32_LSR_multiple_do_op); // LSR
+ }
+ case 0x02:
+ {
+// +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+// ASR<.f> a,b,c 0010 1bbb 0000 0010 FBBB CCCC CCAA AAAA
+// ASR<.f> a,b,u6 0010 1bbb 0100 0010 FBBB uuuu uuAA AAAA
+// ASR<.f> b,b,s12 0010 1bbb 1000 0010 FBBB ssss ssSS SSSS
+// ASR<.cc><.f> b,b,c 0010 1bbb 1100 0010 FBBB CCCC CC0Q QQQQ
+// ASR<.cc><.f> b,b,u6 0010 1bbb 1100 0010 FBBB uuuu uu1Q QQQQ
+// ASR<.f> a,limm,c 0010 1110 0000 0010 F111 CCCC CCAA AAAA (+ Limm)
+// ASR<.f> a,b,limm 0010 1bbb 0000 0010 FBBB 1111 10AA AAAA (+ Limm)
+// ASR<.cc><.f> b,b,limm 0010 1bbb 1100 0010 FBBB 1111 100Q QQQQ (+ Limm)
+//
+// ASR<.f> 0,b,c 0010 1bbb 0000 0010 FBBB CCCC CC11 1110
+// ASR<.f> 0,b,u6 0010 1bbb 0100 0010 FBBB uuuu uu11 1110
+// ASR<.cc><.f> 0,limm,c 0010 1110 1100 0010 F111 CCCC CC0Q QQQQ (+ Limm)
+// +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+ return handleop32_general(op, handleop32_ASR_multiple_do_op); // ASR
+ }
+ case 0x03:
+ {
+// +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+// ROR<.f> a,b,c 0010 1bbb 0000 0011 FBBB CCCC CCAA AAAA
+// ROR<.f> a,b,u6 0010 1bbb 0100 0011 FBBB uuuu uuAA AAAA
+// ROR<.f> b,b,s12 0010 1bbb 1000 0011 FBBB ssss ssSS SSSS
+// ROR<.cc><.f> b,b,c 0010 1bbb 1100 0011 FBBB CCCC CC0Q QQQQ
+// ROR<.cc><.f> b,b,u6 0010 1bbb 1100 0011 FBBB uuuu uu1Q QQQQ
+// ROR<.f> a,limm,c 0010 1110 0000 0011 F111 CCCC CCAA AAAA (+ Limm)
+// ROR<.f> a,b,limm 0010 1bbb 0000 0011 FBBB 1111 10AA AAAA (+ Limm)
+// ROR<.cc><.f> b,b,limm 0010 1bbb 1100 0011 FBBB 1111 100Q QQQQ (+ Limm)
+//
+// ROR<.f> 0,b,c 0010 1bbb 0000 0011 FBBB CCCC CC11 1110
+// ROR<.f> 0,b,u6 0010 1bbb 0100 0011 FBBB uuuu uu11 1110
+// ROR<.cc><.f> 0,limm,c 0010 1110 1100 0011 F111 CCCC CC0Q QQQQ (+ Limm)
+// +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+ return handleop32_general(op, handleop32_ROR_multiple_do_op); // ROR
+ }
+ case 0x04:
+ {
+// +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+// MUL64 <0,>b,c 0010 1bbb 0000 0100 0BBB CCCC CC11 1110
+// MUL64 <0,>b,u6 0010 1bbb 0100 0100 0BBB uuuu uu11 1110
+// MUL64 <0,>b,s12 0010 1bbb 1000 0100 0BBB ssss ssSS SSSS
+// MUL64 <0,>limm,c 0010 1110 0000 0100 0111 CCCC CC11 1110 (+ Limm)
+//
+// MUL64<.cc> <0,>b,c 0010 1bbb 1100 0100 0BBB CCCC CC0Q QQQQ
+// MUL64<.cc> <0,>b,u6 0010 1bbb 1100 0100 0BBB uuuu uu1Q QQQQ
+// MUL64<.cc> <0,>limm,c 0010 1110 1100 0100 0111 CCCC CC0Q QQQQ (+ Limm)
+// MUL64<.cc> <0,>b,limm 0010 1bbb 1100 0100 0BBB 1111 100Q QQQQ (+ Limm)
+// +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+ return handleop32_general_MULx64(op, handleop32_MUL64_do_op); // MUL64
+ }
+ case 0x05:
+ {
+// +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+// MULU64 <0,>b,c 0010 1bbb 0000 0101 0BBB CCCC CC11 1110
+// MULU64 <0,>b,u6 0010 1bbb 0100 0101 0BBB uuuu uu11 1110
+// MULU64 <0,>b,s12 0010 1bbb 1000 0101 0BBB ssss ssSS SSSS
+// MULU64 <0,>limm,c 0010 1110 0000 0101 0111 CCCC CC11 1110 (+ Limm)
+//
+// MULU64<.cc> <0,>b,c 0010 1bbb 1100 0101 0BBB CCCC CC0Q QQQQ
+// MULU64<.cc> <0,>b,u6 0010 1bbb 1100 0101 0BBB uuuu uu1Q QQQQ
+// MULU64<.cc> <0,>limm,c 0010 1110 1100 0101 0111 CCCC CC0Q QQQQ (+ Limm)
+// MULU64<.cc> <0,>b,limm 0010 1bbb 1100 0101 0BBB 1111 100Q QQQQ (+ Limm)
+// +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+ return handleop32_general_MULx64(op, handleop32_MULU64_do_op); // MULU64
+ }
+ case 0x06:
+ {
+// +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+// Extended Arithmetic (optional on ARCtangent-A5, ARC600, built in on ARC700)
+// ADDS - Add and Saturate
+//
+// ADDS<.f> a,b,c 0010 1bbb 0000 0110 FBBB CCCC CCAA AAAA
+// ADDS<.f> a,b,u6 0010 1bbb 0100 0110 FBBB uuuu uuAA AAAA
+// ADDS<.f> b,b,s12 0010 1bbb 1000 0110 FBBB ssss ssSS SSSS
+// ADDS<.cc><.f> b,b,c 0010 1bbb 1100 0110 FBBB CCCC CC0Q QQQQ
+// ADDS<.cc><.f> b,b,u6 0010 1bbb 1100 0110 FBBB uuuu uu1Q QQQQ
+// ADDS<.f> a,limm,c 0010 1110 0000 0110 F111 CCCC CCAA AAAA (+ Limm)
+// ADDS<.f> a,b,limm 0010 1bbb 0000 0110 FBBB 1111 10AA AAAA (+ Limm)
+// ADDS<.cc><.f> b,b,limm 0010 1bbb 1100 0110 FBBB 1111 10QQ QQQQ (+ Limm)
+//
+// ADDS<.f> 0,b,c 0010 1bbb 0000 0110 FBBB CCCC CC11 1110
+// ADDS<.f> 0,b,u6 0010 1bbb 0100 0110 FBBB uuuu uu11 1110
+// ADDS<.f> 0,b,limm 0010 1bbb 0000 0110 FBBB 1111 1011 1110 (+ Limm)
+// ADDS<.cc><.f> 0,limm,c 0010 1110 1100 0110 F111 CCCC CC0Q QQQQ (+ Limm)
+// +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+ return handleop32_general(op, handleop32_ADDS_do_op); // ADDS
+ }
+ case 0x07:
+ {
+// +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+// Extended Arithmetic (optional on ARCtangent-A5, ARC600, built in on ARC700)
+// SUBS - Subtract and Saturate
+//
+// SUBS<.f> a,b,c 0010 1bbb 0000 0111 FBBB CCCC CCAA AAAA
+// SUBS<.f> a,b,u6 0010 1bbb 0100 0111 FBBB uuuu uuAA AAAA
+// SUBS<.f> b,b,s12 0010 1bbb 1000 0111 FBBB ssss ssSS SSSS
+// SUBS<.cc><.f> b,b,c 0010 1bbb 1100 0111 FBBB CCCC CC0Q QQQQ
+// SUBS<.cc><.f> b,b,u6 0010 1bbb 1100 0111 FBBB uuuu uu1Q QQQQ
+// SUBS<.f> a,limm,c 0010 1110 0000 0111 F111 CCCC CCAA AAAA (+ Limm)
+// SUBS<.f> a,b,limm 0010 1bbb 0000 0111 FBBB 1111 10AA AAAA (+ Limm)
+// SUBS<.cc><.f> b,b,limm 0010 1bbb 1100 0111 FBBB 1111 10QQ QQQQ (+ Limm)
+//
+// SUBS<.f> 0,b,c 0010 1bbb 0000 0111 FBBB CCCC CC11 1110
+// SUBS<.f> 0,b,u6 0010 1bbb 0100 0111 FBBB uuuu uu11 1110
+// SUBS<.f> 0,b,limm 0010 1bbb 0000 0111 FBBB 1111 1011 1110 (+ Limm)
+// SUBS<.cc><.f> 0,limm,c 0010 1110 1100 0111 F111 CCCC CC0Q QQQQ (+ Limm)
+// +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+ return handleop32_general(op, handleop32_SUBS_do_op); // SUBS
+ }
+ case 0x08:
+ {
+// +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+// Extended Arithmetic (optional on ARCtangent-A5, ARC600, built in on ARC700)
+// DIVAW - Division Assist
+//
+// DIVAW a,b,c 0010 1bbb 0000 1000 0BBB CCCC CCAA AAAA
+// DIVAW a,b,u6 0010 1bbb 0100 1000 0BBB uuuu uuAA AAAA
+// DIVAW b,b,s12 0010 1bbb 1000 1000 0BBB ssss ssSS SSSS
+// DIVAW<.cc> b,b,c 0010 1bbb 1100 1000 0BBB CCCC CC0Q QQQQ
+// DIVAW<.cc> b,b,u6 0010 1bbb 1100 1000 0BBB uuuu uu1Q QQQQ
+// DIVAW a,limm,c 0010 1110 0000 1000 0111 CCCC CCAA AAAA (+ Limm)
+// DIVAW a,b,limm 0010 1bbb 0000 1000 0BBB 1111 10AA AAAA (+ Limm)
+// DIVAW<.cc> b,b,limm 0010 1bbb 1100 1000 0BBB 1111 10QQ QQQQ (+ Limm)
+//
+// DIVAW 0,b,c 0010 1bbb 0000 1000 0BBB CCCC CC11 1110
+// DIVAW 0,b,u6 0010 1bbb 0100 1000 0BBB uuuu uu11 1110
+// DIVAW<.cc> 0,limm,c 0010 1110 1100 1000 0111 CCCC CC0Q QQQQ (+ Limm)
+// +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+ return handleop32_general(op, handleop32_DIVAW_do_op); // DIVAW
+ }
+ case 0x0a:
+ {
+// +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+// Extended Arithmetic (optional ARCtangent-A5, ARC600, built in on ARC700)
+// ASLS - Arithmetic Shift Left and Saturate (with negative shift value support)
+//
+// IIII I SS SSSS
+// ASLS<.f> a,b,c 0010 1bbb 0000 1010 FBBB CCCC CCAA AAAA
+// ASLS<.f> a,b,u6 0010 1bbb 0100 1010 FBBB uuuu uuAA AAAA
+// ASLS<.f> b,b,s12 0010 1bbb 1000 1010 FBBB ssss ssSS SSSS
+// ASLS<.cc><.f> b,b,c 0010 1bbb 1100 1010 FBBB CCCC CC0Q QQQQ
+// ASLS<.cc><.f> b,b,u6 0010 1bbb 1100 1010 FBBB uuuu uu1Q QQQQ
+// ASLS<.f> a,limm,c 0010 1110 0000 1010 F111 CCCC CCAA AAAA (+ Limm)
+// ASLS<.f> a,b,limm 0010 1bbb 0000 1010 FBBB 1111 10AA AAAA (+ Limm)
+// ASLS<.cc><.f> b,b,limm 0010 1bbb 1100 1010 FBBB 1111 10QQ QQQQ (+ Limm)
+// ASLS<.f> 0,b,c 0010 1bbb 0000 1010 FBBB CCCC CC11 1110
+// ASLS<.f> 0,b,u6 0010 1bbb 0100 1010 FBBB uuuu uu11 1110
+// ASLS<.cc><.f> 0,limm,c 0010 1110 1100 1010 F111 CCCC CC0Q QQQQ (+ Limm)
+// +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+ return handleop32_general(op, handleop32_ASLS_do_op); // ASLS
+ }
+ case 0x0b:
+ {
+// +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+// Extended Arithmetic (optional ARCtangent-A5, ARC600, built in on ARC700)
+// ASRS - Arithmetic Shift Right and Saturate (with negative shift value support)
+//
+// ASRS<.f> a,b,c 0010 1bbb 0000 1011 FBBB CCCC CCAA AAAA
+// ASRS<.f> a,b,u6 0010 1bbb 0100 1011 FBBB uuuu uuAA AAAA
+// ASRS<.f> b,b,s12 0010 1bbb 1000 1011 FBBB ssss ssSS SSSS
+// ASRS<.cc><.f> b,b,c 0010 1bbb 1100 1011 FBBB CCCC CC0Q QQQQ
+// ASRS<.cc><.f> b,b,u6 0010 1bbb 1100 1011 FBBB uuuu uu1Q QQQQ
+// ASRS<.f> a,limm,c 0010 1110 0000 1011 F111 CCCC CCAA AAAA (+ Limm)
+// ASRS<.f> a,b,limm 0010 1bbb 0000 1011 FBBB 1111 10AA AAAA (+ Limm)
+// ASRS<.cc><.f> b,b,limm 0010 1bbb 1100 1011 FBBB 1111 10QQ QQQQ (+ Limm)
+//
+// ASRS<.f> 0,b,c 0010 1bbb 0000 1011 FBBB CCCC CC11 1110
+// ASRS<.f> 0,b,u6 0010 1bbb 0100 1011 FBBB uuuu uu11 1110
+// ASRS<.cc><.f> 0,limm,c 0010 1110 1100 1011 F111 CCCC CC0Q QQQQ (+ Limm)
+// +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+ return handleop32_general(op, handleop32_ASRS_do_op); // ASRS
+ }
+ case 0x0c:
+ {
+// +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+// Unknown Extension Op
+// +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+ return handleop32_general(op, handleop32_UNKNOWN_05_0c_do_op);
+ }
+ case 0x10:
+ {
+// +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+// Unknown Extension Op
+// +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+ return handleop32_general(op, handleop32_UNKNOWN_05_10_do_op);
+ }
+ case 0x14:
+ {
+// +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+// Unknown Extension Op
+// +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+ return handleop32_general(op, handleop32_UNKNOWN_05_14_do_op);
+ }
+ case 0x28:
+ {
+// +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+// Extended Arithmetic (optional ARCtangent-A5, ARC600, built in on ARC700)
+// ADDSDW - Dual 16-bit Add and Saturate
+//
+// ADDSDW<.f> a,b,c 0010 1bbb 0010 1000 FBBB CCCC CCAA AAAA
+// ADDSDW<.f> a,b,u6 0010 1bbb 0110 1000 FBBB uuuu uuAA AAAA
+// ADDSDW<.f> b,b,s12 0010 1bbb 1010 1000 FBBB ssss ssSS SSSS
+// ADDSDW<.cc><.f> b,b,c 0010 1bbb 1110 1000 FBBB CCCC CC0Q QQQQ
+// ADDSDW<.cc><.f> b,b,u6 0010 1bbb 1110 1000 FBBB uuuu uu1Q QQQQ
+// ADDSDW<.f> a,limm,c 0010 1110 0010 1000 F111 CCCC CCAA AAAA (+ Limm)
+// ADDSDW<.f> a,b,limm 0010 1bbb 0010 1000 FBBB 1111 10AA AAAA (+ Limm)
+// ADDSDW<.cc><.f> b,b,limm 0010 1bbb 1110 1000 FBBB 1111 10QQ QQQQ (+ Limm)
+//
+// ADDSDW<.f> 0,b,c 0010 1bbb 0010 1000 FBBB CCCC CC11 1110
+// ADDSDW<.f> 0,b,u6 0010 1bbb 0110 1000 FBBB uuuu uu11 1110
+// ADDSDW<.cc><.f> 0,limm,c 0010 1110 1110 1000 F111 CCCC CC0Q QQQQ (+ Limm)
+// +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+ return handleop32_general(op, handleop32_ADDSDW_do_op); // ADDSDW
+ }
+ case 0x29:
+ {
+// +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+// Extended Arithmetic (optional ARCtangent-A5, ARC600, built in on ARC700)
+// SUBSDW - Dual 16-bit Subtract and Saturate
+//
+// SUBSDW<.f> a,b,c 0010 1bbb 0010 1001 FBBB CCCC CCAA AAAA
+// SUBSDW<.f> a,b,u6 0010 1bbb 0110 1001 FBBB uuuu uuAA AAAA
+// SUBSDW<.f> b,b,s12 0010 1bbb 1010 1001 FBBB ssss ssSS SSSS
+// SUBSDW<.cc><.f> b,b,c 0010 1bbb 1110 1001 FBBB CCCC CC0Q QQQQ
+// SUBSDW<.cc><.f> b,b,u6 0010 1bbb 1110 1001 FBBB uuuu uu1Q QQQQ
+// SUBSDW<.f> a,limm,c 0010 1110 0010 1001 F111 CCCC CCAA AAAA (+ Limm)
+// SUBSDW<.f> a,b,limm 0010 1bbb 0010 1001 FBBB 1111 10AA AAAA (+ Limm)
+// SUBSDW<.cc><.f> b,b,limm 0010 1bbb 1110 1001 FBBB 1111 10QQ QQQQ (+ Limm)
+//
+// SUBSDW<.f> 0,b,c 0010 1bbb 0010 1001 FBBB CCCC CC11 1110
+// SUBSDW<.f> 0,b,u6 0010 1bbb 0110 1001 FBBB uuuu uu11 1110
+// SUBSDW<.cc><.f> 0,limm,c 0010 1110 1110 1001 F111 CCCC CC0Q QQQQ (+ Limm)
+// +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+ return handleop32_general(op, handleop32_SUBSDW_do_op); // SUBSDW
+ }
+ case 0x2f: // SOPs
+ {
+ uint8_t subinstr2 = op & 0x0000003f;
+ switch (subinstr2)
+ {
+ case 0x00:
+ {
+// +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+// SWAP<.f> b,c 0010 1bbb 0010 1111 FBBB CCCC CC00 0000
+// SWAP<.f> b,u6 0010 1bbb 0110 1111 FBBB uuuu uu00 0000
+// SWAP<.f> b,limm 0010 1bbb 0010 1111 FBBB 1111 1000 0000 (+ Limm)
+//
+// SWAP<.f> 0,c 0010 1110 0010 1111 F111 CCCC CC00 0000
+// SWAP<.f> 0,u6 0010 1110 0110 1111 F111 uuuu uu00 0000
+// SWAP<.f> 0,limm 0010 1110 0010 1111 F111 1111 1000 0000 (+ Limm)
+// +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+ return handleop32_general_SOP_group(op, handleop32_SWAP_do_op); // SWAP
+ }
+ case 0x01:
+ {
+// +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+// NORM<.f> b,c 0010 1bbb 0010 1111 FBBB CCCC CC00 0001
+// NORM<.f> b,u6 0010 1bbb 0110 1111 FBBB uuuu uu00 0001
+// NORM<.f> b,limm 0010 1bbb 0010 1111 FBBB 1111 1000 0001 (+ Limm)
+//
+// NORM<.f> 0,c 0010 1110 0010 1111 F111 CCCC CC00 0001
+// NORM<.f> 0,u6 0010 1110 0110 1111 F111 uuuu uu00 0001
+// NORM<.f> 0,limm 0010 1110 0010 1111 F111 1111 1000 0001 (+ Limm)
+// +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+ return handleop32_general_SOP_group(op, handleop32_NORM_do_op); // NORM
+ }
+ case 0x02:
+ {
+// +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+// SAT16<.f> b,c 0010 1bbb 0010 1111 FBBB CCCC CC00 0010
+// SAT16<.f> b,u6 0010 1bbb 0110 1111 FBBB uuuu uu00 0010
+// SAT16<.f> b,limm 0010 1bbb 0010 1111 FBBB 1111 1000 0010 (+ Limm)
+//
+// SAT16<.f> 0,c 0010 1110 0010 1111 F111 CCCC CC00 0010
+// SAT16<.f> 0,u6 0010 1110 0110 1111 F111 uuuu uu00 0010
+// SAT16<.f> 0,limm 0010 1110 0010 1111 F111 1111 1000 0010 (+ Limm)
+// +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+ return handleop32_general_SOP_group(op, handleop32_SAT16_do_op); // SAT16
+ }
+ case 0x03:
+ {
+// +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+// RND16<.f> b,c 0010 1bbb 0010 1111 FBBB CCCC CC00 0011
+// RND16<.f> b,u6 0010 1bbb 0110 1111 FBBB uuuu uu00 0011
+// RND16<.f> b,limm 0010 1bbb 0010 1111 FBBB 1111 1000 0011 (+ Limm)
+//
+// RND16<.f> 0,c 0010 1110 0010 1111 F111 CCCC CC00 0011
+// RND16<.f> 0,u6 0010 1110 0110 1111 F111 uuuu uu00 0011
+// RND16<.f> 0,limm 0010 1110 0010 1111 F111 1111 1000 0011 (+ Limm)
+// +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+ return handleop32_general_SOP_group(op, handleop32_RND16_do_op); // RND16
+ }
+ case 0x04:
+ {
+// +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+// ABSSW<.f> b,c 0010 1bbb 0010 1111 FBBB CCCC CC00 0100
+// ABSSW<.f> b,u6 0010 1bbb 0110 1111 FBBB uuuu uu00 0100
+// ABSSW<.f> b,limm 0010 1bbb 0010 1111 FBBB 1111 1000 0100 (+ Limm)
+//
+// ABSSW<.f> 0,c 0010 1110 0010 1111 F111 CCCC CC00 0100
+// ABSSW<.f> 0,u6 0010 1110 0110 1111 F111 uuuu uu00 0100
+// ABSSW<.f> 0,limm 0010 1110 0010 1111 F111 1111 1000 0100 (+ Limm)
+// +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+ return handleop32_general_SOP_group(op, handleop32_ABSSW_do_op); // ABSSW
+ }
+ case 0x05:
+ {
+// +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+// ABSS<.f> b,c 0010 1bbb 0010 1111 FBBB CCCC CC00 0101
+// ABSS<.f> b,u6 0010 1bbb 0110 1111 FBBB uuuu uu00 0101
+// ABSS<.f> b,limm 0010 1bbb 0010 1111 FBBB 1111 1000 0101 (+ Limm)
+//
+// ABSS<.f> 0,c 0010 1110 0010 1111 F111 CCCC CC00 0101
+// ABSS<.f> 0,u6 0010 1110 0110 1111 F111 uuuu uu00 0101
+// ABSS<.f> 0,limm 0010 1110 0010 1111 F111 1111 1000 0101 (+ Limm)
+// +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+ return handleop32_general_SOP_group(op, handleop32_ABSS_do_op); // ABSS
+ }
+ case 0x06:
+ {
+// +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+// NEGSW<.f> b,c 0010 1bbb 0010 1111 FBBB CCCC CC00 0110
+// NEGSW<.f> b,u6 0010 1bbb 0110 1111 FBBB uuuu uu00 0110
+// NEGSW<.f> b,limm 0010 1bbb 0010 1111 FBBB 1111 1000 0110 (+ Limm)
+//
+// NEGSW<.f> 0,c 0010 1110 0010 1111 F111 CCCC CC00 0110
+// NEGSW<.f> 0,u6 0010 1110 0110 1111 F111 uuuu uu00 0110
+// NEGSW<.f> 0,limm 0010 1110 0010 1111 F111 1111 1000 0110 (+ Limm)
+// +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+ return handleop32_general_SOP_group(op, handleop32_NEGSW_do_op); // NEGSW
+ }
+ case 0x07:
+ {
+// +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+// NEGS<.f> b,c 0010 1bbb 0010 1111 FBBB CCCC CC00 0111
+// NEGS<.f> b,u6 0010 1bbb 0110 1111 FBBB uuuu uu00 0111
+// NEGS<.f> b,limm 0010 1bbb 0010 1111 FBBB 1111 1000 0111 (+ Limm)
+//
+// NEGS<.f> 0,c 0010 1110 0010 1111 F111 CCCC CC00 0111
+// NEGS<.f> 0,u6 0010 1110 0110 1111 F111 uuuu uu00 0111
+// NEGS<.f> 0,limm 0010 1110 0010 1111 F111 1111 1000 0111 (+ Limm)
+// +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+ return handleop32_general_SOP_group(op, handleop32_NEGS_do_op); // NEGS
+ }
+ case 0x08:
+ {
+// +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+// NORMW<.f> b,c 0010 1bbb 0010 1111 FBBB CCCC CC00 1000
+// NORMW<.f> b,u6 0010 1bbb 0110 1111 FBBB uuuu uu00 1000
+// NORMW<.f> b,limm 0010 1bbb 0010 1111 FBBB 1111 1000 1000 (+ Limm)
+//
+// NORMW<.f> 0,c 0010 1110 0010 1111 F111 CCCC CC00 1000
+// NORMW<.f> 0,u6 0010 1110 0110 1111 F111 uuuu uu00 1000
+// NORMW<.f> 0,limm 0010 1110 0010 1111 F111 1111 1000 1000 (+ Limm)
+// +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+ return handleop32_general_SOP_group(op, handleop32_NORMW_do_op); // NORMW
+ }
+ case 0x3f: // ZOPs (Zero Operand Opcodes)
+ {
+ uint8_t subinstr3 = (op & 0x07000000) >> 24;
+ subinstr3 |= ((op & 0x00007000) >> 12) << 3;
+
+ switch (subinstr3)
+ {
+ default:
+ {
+ return arcompact_handle_illegal(instruction, subinstr, subinstr2, subinstr3, op); // illegal
+ }
+ }
+ }
+ default:
+ {
+ return arcompact_handle_illegal(instruction, subinstr, subinstr2, op); // illegal
+ }
+ }
+ }
+ default:
+ {
+ return arcompact_handle_illegal(instruction, subinstr, op); // illegal
+ }
+
+ }
+ }
+ case 0x06: return handleop32_ARC_EXT06(op); // op a,b,c (06 ARC ext)
+ case 0x07: return handleop32_USER_EXT07(op); // op a,b,c (07 User ext)
+ case 0x08: return handleop32_USER_EXT08(op); // op a,b,c (08 User ext)
+ case 0x09: return handleop32_MARKET_EXT09(op); // op a,b,c (09 Market ext)
+ case 0x0a: return handleop32_MARKET_EXT0a(op); // op a,b,c (0a Market ext)
+ case 0x0b: return handleop32_MARKET_EXT0b(op); // op a,b,c (0b Market ext)
+ }
+ }
+ else
+ {
+ switch (instruction) // 16-bit instructions
+ {
+ default: return -1;
+ case 0x0c: // Load/Add reg-reg
+ {
+ uint8_t subinstr = (op & 0x0018) >> 3;
+ switch (subinstr)
+ {
+ default: return -1;
+ case 0x00:
+ {
+// #######################################################################################################################
+// IIII I S S
+// LD_S a,[b,c] 0110 0bbb ccc0 0aaa
+// #######################################################################################################################
+ return handleop_LD_S_a_b_c(op); // LD_S a,[b,c]
+ }
+ case 0x01:
+ {
+// #######################################################################################################################
+// IIII I S S
+// LDB_S a,[b,c] 0110 0bbb ccc0 1aaa
+// #######################################################################################################################
+ return handleop_LDB_S_a_b_c(op); // LDB_S a,[b,c]
+ }
+ case 0x02:
+ {
+// #######################################################################################################################
+// IIII I S S
+// LDW_S a,[b,c] 0110 0bbb ccc1 0aaa
+// #######################################################################################################################
+ return handleop_LDW_S_a_b_c(op); // LDW_S a,[b,c]
+ }
+ case 0x03:
+ {
+// #######################################################################################################################
+// IIII I S S
+// ADD_S a,b,c 0110 0bbb ccc1 1aaa
+// #######################################################################################################################
+ return handleop_ADD_S_a_b_c(op); // ADD_S a,b,c
+ }
+ }
+ }
+ case 0x0d: // Add/Sub/Shft imm
+ {
+ uint8_t subinstr = (op & 0x0018) >> 3;
+ switch (subinstr)
+ {
+ default: return -1;
+ case 0x00:
+ {
+// #######################################################################################################################
+// ADD_S c,b,u3 0110 1bbb ccc0 0uuu
+// #######################################################################################################################
+ return handleop_ADD_S_c_b_u3(op); // ADD_S c,b,u3
+ }
+ case 0x01:
+ {
+// #######################################################################################################################
+// SUB_S c,b,u3 0110 1bbb ccc0 1uuu
+// #######################################################################################################################
+ return handleop_SUB_S_c_b_u3(op); // SUB_S c,b,u3
+ }
+ case 0x02:
+ {
+// #######################################################################################################################
+// IIII I S S
+// ASL_S c,b,u3 0110 1bbb ccc1 0uuu
+// #######################################################################################################################
+ return handleop_ASL_S_c_b_u3(op); // ASL_S c,b,u3
+ }
+ case 0x03:
+ {
+// #######################################################################################################################
+// IIII I S S
+// ASR_S c,b,u3 0110 1bbb ccc1 1uuu
+// #######################################################################################################################
+ return handleop_ASR_S_c_b_u3(op); // ASR_S c,b,u3
+ }
+ }
+ }
+ case 0x0e: // Mov/Cmp/Add
+ {
+ uint8_t subinstr = (op & 0x0018) >> 3;
+
+ switch (subinstr)
+ {
+ default: return -1;
+ case 0x00:
+ {
+// #######################################################################################################################
+// IIII I S S
+// ADD_S b,b,h 0111 0bbb hhh0 0HHH
+// ADD_S b,b,limm 0111 0bbb 1100 0111 (+ Limm)
+// #######################################################################################################################
+ return handleop_ADD_S_b_b_h_or_limm(op); // ADD_S b,b,h or ADD_S b,b,limm
+ }
+ case 0x01:
+ {
+// #######################################################################################################################
+// IIII I S S
+// MOV_S b,h 0111 0bbb hhh0 1HHH
+// MOV_S b,limm 0111 0bbb 1100 1111 (+ Limm)
+// #######################################################################################################################
+ return handleop_MOV_S_b_h_or_limm(op); // MOV_S b,h or MOV_S b,limm
+ }
+ case 0x02:
+ {
+// #######################################################################################################################
+// IIII I S S
+// CMP_S b,h 0111 0bbb hhh1 0HHH
+// CMP_S b,limm 0111 0bbb 1101 0111 (+ Limm)
+// #######################################################################################################################
+ return handleop_CMP_S_b_h_or_limm(op); // CMP_S b,h or CMP_S b,limm
+ }
+ case 0x03:
+ {
+// #######################################################################################################################
+// IIII I S S
+// MOV_S h,b 0111 0bbb hhh1 1HHH
+// #######################################################################################################################
+ return handleop_MOV_S_h_b(op); // MOV_S h,b
+ }
+ }
+ }
+ case 0x0f: // op_S b,b,c (single 16-bit ops)
+ {
+ uint8_t subinstr = op & 0x01f;
+
+ switch (subinstr)
+ {
+ case 0x00: // SOPs
+ {
+ uint8_t subinstr2 = (op & 0x00e0) >> 5;
+
+ switch (subinstr2)
+ {
+ case 0x00:
+ {
+// #######################################################################################################################
+// IIII I sssS SSSS
+// J_S [b] 0111 1bbb 0000 0000
+// #######################################################################################################################
+ return handleop_J_S_b(op); // J_S [b]
+ }
+ case 0x01:
+ {
+// #######################################################################################################################
+// IIII I sssS SSSS
+// J_S.D [b] 0111 1bbb 0010 0000
+// #######################################################################################################################
+ return handleop_J_S_D_b(op); // J_S.D [b]
+ }
+ case 0x02:
+ {
+// #######################################################################################################################
+// IIII I sssS SSSS
+// JL_S [b] 0111 1bbb 0100 0000
+// #######################################################################################################################
+ return handleop_JL_S_b(op); // JL_S [b]
+ }
+ case 0x03:
+ {
+// #######################################################################################################################
+// IIII I sssS SSSS
+// JL_S.D [b] 0111 1bbb 0110 0000
+// #######################################################################################################################
+ return handleop_JL_S_D_b(op); // JL_S.D [b]
+ }
+ case 0x06:
+ {
+// #######################################################################################################################
+// SUB_S.NE b,b,b 0111 1bbb 1100 0000
+// IIII I sssS SSSS
+// #######################################################################################################################
+ return handleop_SUB_S_NE_b_b_b(op); // SUB_S.NE b,b,b
+ }
+ case 0x07: // ZOPs
+ {
+ uint8_t subinstr3 = (op & 0x0700) >> 8;
+
+ switch (subinstr3)
+ {
+ case 0x00:
+ {
+// #######################################################################################################################
+// IIII I$$$ sssS SSSS
+// NOP_S 0111 1000 1110 0000
+// #######################################################################################################################
+ return handleop_NOP_S(op); // NOP_S
+ }
+ case 0x01:
+ {
+// #######################################################################################################################
+// IIII I$$$ sssS SSSS
+// UNIMP_S 0111 1001 1110 0000
+// #######################################################################################################################
+ return handleop_UNIMP_S(op); // UNIMP_S
+ }
+ case 0x04:
+ {
+// #######################################################################################################################
+// IIII I$$$ sssS SSSS
+// JEQ_S [blink] 0111 1100 1110 0000
+// #######################################################################################################################
+ return handleop_JEQ_S_blink(op); // JEQ_S [BLINK]
+ }
+ case 0x05:
+ {
+// #######################################################################################################################
+// IIII I$$$ sssS SSSS
+// JNE_S [blink] 0111 1101 1110 0000
+// #######################################################################################################################
+ return handleop_JNE_S_blink(op); // JNE_S [BLINK]
+ }
+ case 0x06:
+ {
+// #######################################################################################################################
+// IIII I$$$ sssS SSSS
+// J_S [blink] 0111 1110 1110 0000
+// #######################################################################################################################
+ return handleop_J_S_blink(op); // J_S [BLINK]
+ }
+ case 0x07:
+ {
+// #######################################################################################################################
+// IIII I$$$ sssS SSSS
+// J_S.D [blink] 0111 1111 1110 0000
+// #######################################################################################################################
+ return handleop_J_S_D_blink(op); // J_S.D [BLINK]
+ }
+
+ default: // 0x02, 0x03
+ {
+ return arcompact_handle_illegal(instruction,subinstr, subinstr2, subinstr3, op);
+ }
+ }
+ }
+ default: // 0x04, 0x05
+ {
+ return arcompact_handle_illegal(instruction,subinstr, subinstr2, op);
+ }
+ }
+ }
+ case 0x02:
+ {
+// #######################################################################################################################
+// IIII I S SSSS
+// SUB_S b,b,c 0111 1bbb ccc0 0010
+// #######################################################################################################################
+ return handleop_SUB_S_b_b_c(op); // SUB_S b,b,c
+ }
+ case 0x04:
+ {
+// #######################################################################################################################
+// IIII I S SSSS
+// AND_S b,b,c 0111 1bbb ccc0 0100
+// #######################################################################################################################
+ return handleop_AND_S_b_b_c(op); // AND_S b,b,c
+ }
+ case 0x05:
+ {
+// #######################################################################################################################
+// IIII I S SSSS
+// OR_S b,b,c 0111 1bbb ccc0 0101
+// #######################################################################################################################
+ return handleop_OR_S_b_b_c(op); // OR_S b,b,c
+ }
+ case 0x06:
+ {
+// #######################################################################################################################
+// IIII I S SSSS
+// BIC_S b,b,c 0111 1bbb ccc0 0110
+// #######################################################################################################################
+ return handleop_BIC_S_b_b_c(op); // BIC_S b,b,c
+ }
+ case 0x07:
+ {
+// #######################################################################################################################
+// IIII I S SSSS
+// XOR_S b,b,c 0111 1bbb ccc0 0111
+// #######################################################################################################################
+ return handleop_XOR_S_b_b_c(op); // XOR_S b,b,c
+ }
+ case 0x0b:
+ {
+// #######################################################################################################################
+// IIII I S SSSS
+// TST_S b,c 0111 1bbb ccc0 1011
+// #######################################################################################################################
+ return handleop_TST_S_b_c(op); // TST_S b,c
+ }
+ case 0x0c:
+ {
+// #######################################################################################################################
+// IIII I S SSSS
+// MUL64_S <0,>b,c 0111 1bbb ccc0 1100
+// #######################################################################################################################
+ return handleop_MUL64_S_0_b_c(op); // MUL64_S <0,>b,c
+ }
+ case 0x0d:
+ {
+
+// #######################################################################################################################
+// IIII I S SSSS
+// SEXB_S b,c 0111 1bbb ccc0 1101
+// #######################################################################################################################
+ return handleop_SEXB_S_b_c(op); // SEXB_S b,c
+ }
+ case 0x0e:
+ {
+// #######################################################################################################################
+// IIII I S SSSS
+// SEXW_S b,c 0111 1bbb ccc0 1110
+// #######################################################################################################################
+ return handleop_SEXW_S_b_c(op); // SEXW_S b,c
+ }
+ case 0x0f:
+ {
+// #######################################################################################################################
+// IIII I S SSSS
+// EXTB_S b,c 0111 1bbb ccc0 1111
+// #######################################################################################################################
+ return handleop_EXTB_S_b_c(op); // EXTB_S b,c
+ }
+ case 0x10:
+ {
+// #######################################################################################################################
+// IIII I S SSSS
+// EXTW_S b,c 0111 1bbb ccc1 0000
+// #######################################################################################################################
+ return handleop_EXTW_S_b_c(op); // EXTW_S b,c
+ }
+ case 0x11:
+ {
+// #######################################################################################################################
+// IIII I S SSSS
+// ABS_S b,c 0111 1bbb ccc1 0001
+// #######################################################################################################################
+ return handleop_ABS_S_b_c(op); // ABS_S b,c
+ }
+ case 0x12:
+ {
+// #######################################################################################################################
+// IIII I S SSSS
+// NOT_S b,c 0111 1bbb ccc1 0010
+// #######################################################################################################################
+ return handleop_NOT_S_b_c(op); // NOT_S b,c
+ }
+ case 0x13:
+ {
+// #######################################################################################################################
+// IIII I S SSSS
+// NEG_S b,c 0111 1bbb ccc1 0011
+// #######################################################################################################################
+ return handleop_NEG_S_b_c(op); // NEG_S b,c
+ }
+ case 0x14:
+ {
+// #######################################################################################################################
+// IIII I S SSSS
+// ADD1_S b,b,c 0111 1bbb ccc1 0100
+// #######################################################################################################################
+ return handleop_ADD1_S_b_b_c(op); // ADD1_S b,b,c
+ }
+ case 0x15:
+ {
+// #######################################################################################################################
+// IIII I S SSSS
+// ADD2_S b,b,c 0111 1bbb ccc1 0101
+// #######################################################################################################################
+ return handleop_ADD2_S_b_b_c(op); // ADD2_S b,b,c
+ }
+ case 0x16:
+ {
+// #######################################################################################################################
+// IIII I S SSSS
+// ADD3_S b,b,c 0111 1bbb ccc1 0110
+// #######################################################################################################################
+ return handleop_ADD3_S_b_b_c(op); // ADD3_S b,b,c
+ }
+ case 0x18:
+ {
+// #######################################################################################################################
+// IIII I S SSSS
+// ASL_S b,b,c 0111 1bbb ccc1 1000
+// #######################################################################################################################
+ return handleop_ASL_S_b_b_c_multiple(op); // ASL_S b,b,c (multiple)
+ }
+ case 0x19:
+ {
+// #######################################################################################################################
+// IIII I S SSSS
+// LSR_S b,b,c 0111 1bbb ccc1 1001
+// #######################################################################################################################
+ return handleop_LSR_S_b_b_c_multiple(op); // LSR_S b,b,c (multiple)
+ }
+ case 0x1a:
+ {
+// #######################################################################################################################
+// IIII I S SSSS
+// ASR_S b,b,c 0111 1bbb ccc1 1010
+// #######################################################################################################################
+ return handleop_ASR_S_b_b_c_multiple(op); // ASR_S b,b,c (multiple)
+ }
+ case 0x1b:
+ {
+// #######################################################################################################################
+// IIII I S SSSS
+// ASL_S b,c 0111 1bbb ccc1 1011
+// #######################################################################################################################
+ return handleop_ASL_S_b_c_single(op); // ASL_S b,c (single)
+ }
+ case 0x1c:
+ {
+// #######################################################################################################################
+// IIII I S SSSS
+// ASR_S b,c 0111 1bbb ccc1 1100
+// #######################################################################################################################
+ return handleop_ASR_S_b_c_single(op); // ASR_S b,c (single)
+ }
+ case 0x1d:
+ {
+// #######################################################################################################################
+// IIII I S SSSS
+// LSR_S b,c 0111 1bbb ccc1 1101
+// #######################################################################################################################
+ return handleop_LSR_S_b_c_single(op); // LSR_S b,c (single)
+ }
+ case 0x1e:
+ {
+// #######################################################################################################################
+// IIII I S SSSS
+// TRAP_S u6 0111 1uuu uuu1 1110
+// #######################################################################################################################
+ return handleop_TRAP_S_u6(op); // TRAP_S u6 (not a5?)
+ }
+ case 0x1f:
+ {
+ uint8_t subinstr2 = (op & 0x07e0) >> 5;
+ if (subinstr2 == 0x3f)
+ {
+// #######################################################################################################################
+// IIII Isss sssS SSSS
+// BRK_S 0111 1111 1111 1111
+// #######################################################################################################################
+ return handleop_BRK_S(op); // BRK_S ( 0x7fff only? )
+ }
+ else
+ {
+ return arcompact_handle_illegal(instruction,subinstr,subinstr2, op);
+ }
+ }
+ default: // 0x01, 0x03, 0x08, 0x09, 0x0a, 0x17
+ {
+ return arcompact_handle_illegal(instruction, subinstr, op);
+ }
+ }
+ }
+ case 0x10:
+ {
+// #######################################################################################################################
+// IIII I
+// LD_S c,[b,u7] 1000 0bbb cccu uuuu
+// #######################################################################################################################
+ return handleop_LD_S_c_b_u7(op); // LD_S c,[b,u7]
+ }
+ case 0x11:
+ {
+// #######################################################################################################################
+// IIII I
+// LDB_S c,[b,u5] 1000 1bbb cccu uuuu
+// #######################################################################################################################
+ return handleop_LDB_S_c_b_u5(op); // LDB_S c,[b,u5]
+ }
+ case 0x12:
+ {
+// #######################################################################################################################
+// IIII I
+// LDW_S c,[b,u6] 1001 0bbb cccu uuuu
+// #######################################################################################################################
+ return handleop_LDW_S_c_b_u6(op); // LDW_S c,[b,u6]
+ }
+ case 0x13:
+ {
+// #######################################################################################################################
+// IIII I
+// LDW_S.X c,[b,u6] 1001 1bbb cccu uuuu
+// #######################################################################################################################
+ return handleop_LDW_S_X_c_b_u6(op); // LDW_S.X c,[b,u6]
+ }
+ case 0x14:
+ {
+// #######################################################################################################################
+// IIII I
+// ST_S c,[b,u7] 1010 0bbb cccu uuuu
+// #######################################################################################################################
+ return handleop_ST_S_c_b_u7(op); // ST_S c,[b,u7]
+ }
+ case 0x15:
+ {
+// #######################################################################################################################
+// IIII I
+// STB_S c,[b,u5] 1010 1bbb cccu uuuu
+// #######################################################################################################################
+ return handleop_STB_S_c_b_u5(op); // STB_S
+ }
+ case 0x16:
+ {
+// #######################################################################################################################
+// IIII I
+// STW_S c,[b,u6] 1011 0bbb cccu uuuu
+// #######################################################################################################################
+ return handleop_STW_S_c_b_u6(op); // STW_S
+ }
+ case 0x17: // Shift/Sub/Bit
+ {
+ uint8_t subinstr = (op & 0x00e0) >> 5;
+ switch (subinstr)
+ {
+ default: return -1;
+ case 0x00:
+ {
+// #######################################################################################################################
+// IIII I SSS
+// ASL_S b,b,u5 1011 1bbb 000u uuuu
+// #######################################################################################################################
+ return handleop_ASL_S_b_b_u5(op); // ASL_S b,b,u5
+ }
+ case 0x01:
+ {
+// #######################################################################################################################
+// IIII I SSS
+// LSR_S b,b,u5 1011 1bbb 001u uuuu
+// #######################################################################################################################
+ return handleop_LSR_S_b_b_u5(op); // LSR_S b,b,u5
+ }
+ case 0x02:
+ {
+// #######################################################################################################################
+// IIII I SSS
+// ASR_S b,b,u5 1011 1bbb 010u uuuu
+// #######################################################################################################################
+ return handleop_ASR_S_b_b_u5(op); // ASR_S b,b,u5
+ }
+ case 0x03:
+ {
+// #######################################################################################################################
+// IIII I SSS
+// SUB_S b,b,u5 1011 1bbb 011u uuuu
+// #######################################################################################################################
+ return handleop_SUB_S_b_b_u5(op); // SUB_S b,b,u5
+ }
+ case 0x04:
+ {
+// #######################################################################################################################
+// IIII I SSS
+// BSET_S b,b,u5 1011 1bbb 100u uuuu
+// #######################################################################################################################
+ return handleop_BSET_S_b_b_u5(op); // BSET_S b,b,u5
+ }
+ case 0x05:
+ {
+// #######################################################################################################################
+// IIII I SSS
+// BCLR_S b,b,u5 1011 1bbb 101u uuuu
+// #######################################################################################################################
+ return handleop_BCLR_S_b_b_u5(op); // BCLR_S b,b,u5
+ }
+ case 0x06:
+ {
+// #######################################################################################################################
+// IIII I SSS
+// BMSK_S b,b,u5 1011 1bbb 110u uuuu
+// #######################################################################################################################
+ return handleop_BMSK_S_b_b_u5(op); // BMSK_S b,b,u5
+ }
+ case 0x07:
+ {
+// #######################################################################################################################
+// IIII I SSS
+// BTST_S b,u5 1011 1bbb 111u uuuu
+// #######################################################################################################################
+ return handleop_BTST_S_b_u5(op); // BTST_S b,u5
+ }
+ }
+ }
+ case 0x18: // Stack Instr
+ {
+ uint8_t subinstr = (op & 0x00e0) >> 5;
+ switch (subinstr)
+ {
+ default: return -1;
+ case 0x00:
+ {
+// #######################################################################################################################
+// IIII I SSS
+// LD_S b,[sp,u7] 1100 0bbb 000u uuuu
+// #######################################################################################################################
+ return handleop_LD_S_b_sp_u7(op); // LD_S b,[sp,u7]
+ }
+ case 0x01:
+ {
+// #######################################################################################################################
+// IIII I SSS
+// LDB_S b,[sp,u7] 1100 0bbb 001u uuuu
+// #######################################################################################################################
+ return handleop_LDB_S_b_sp_u7(op); // LDB_S b,[sp,u7]
+ }
+ case 0x02:
+ {
+// #######################################################################################################################
+// IIII I SSS
+// ST_S b,[sp,u7] 1100 0bbb 010u uuuu
+// #######################################################################################################################
+ return handleop_ST_S_b_sp_u7(op); // ST_S b,[sp,u7]
+ }
+ case 0x03:
+ {
+// #######################################################################################################################
+// IIII I SSS
+// STB_S b,[sp,u7] 1100 0bbb 011u uuuu
+// #######################################################################################################################
+ return handleop_STB_S_b_sp_u7(op); // STB_S b,[sp,u7]
+ }
+ case 0x04:
+ {
+// #######################################################################################################################
+// IIII I SSS
+// ADD_S b,sp,u7 1100 0bbb 100u uuuu
+// #######################################################################################################################
+ return handleop_ADD_S_b_sp_u7(op); // ADD_S b,sp,u7
+ }
+
+ case 0x05: // subtable 18_05
+ {
+ uint8_t subinstr2 = (op & 0x0700) >> 8;
+ switch (subinstr2)
+ {
+ case 0x00:
+ {
+// #######################################################################################################################
+// IIII Isss SSS
+// ADD_S sp,sp,u7 1100 0000 101u uuuu
+// #######################################################################################################################
+ return handleop_ADD_S_sp_sp_u7(op); // ADD_S sp,sp,u7
+ }
+ case 0x01:
+ {
+// #######################################################################################################################
+// IIII Isss SSS
+// SUB_S sp,sp,u7 1100 0001 101u uuuu
+// #######################################################################################################################
+ return handleop_SUB_S_sp_sp_u7(op); // SUB_S sp,sp,u7
+ }
+ default: return arcompact_handle_illegal(instruction,subinstr,subinstr2, op);
+ }
+ }
+ case 0x06: // subtable 18_06
+ {
+ uint8_t subinstr2 = op & 0x001f;
+ switch (subinstr2)
+ {
+ case 0x01:
+ {
+// #######################################################################################################################
+// IIII I SSSs ssss
+// POP_S b 1100 0bbb 1100 0001
+// #######################################################################################################################
+ return handleop_POP_S_b(op); // POP_S b
+ }
+ case 0x11:
+ {
+// #######################################################################################################################
+// IIII I SSSs ssss
+// POP_S blink 1100 0RRR 1101 0001
+// #######################################################################################################################
+ return handleop_POP_S_blink(op); // POP_S blink
+ }
+ default: return arcompact_handle_illegal(instruction,subinstr,subinstr2, op);
+ }
+ }
+ case 0x07: // subtable 18_07
+ {
+ uint8_t subinstr2 = op & 0x001f;
+
+ switch (subinstr2)
+ {
+ case 0x01:
+ {
+// #######################################################################################################################
+// IIII I SSSs ssss
+// PUSH_S b 1100 0bbb 1110 0001
+// #######################################################################################################################
+ return handleop_PUSH_S_b(op); // PUSH_S b
+ }
+ case 0x11:
+ {
+// #######################################################################################################################
+// IIII I SSSs ssss
+// PUSH_S blink 1100 0RRR 1111 0001
+// #######################################################################################################################
+ return handleop_PUSH_S_blink(op); // PUSH_S blink
+ }
+ default: return arcompact_handle_illegal(instruction,subinstr,subinstr2, op);
+ }
+ }
+ }
+ }
+ case 0x19: // GP Instr
+ {
+ uint8_t subinstr = (op & 0x0600) >> 9;
+
+ switch (subinstr)
+ {
+ default: return -1;
+ case 0x00:
+ {
+// #######################################################################################################################
+// IIII ISS
+// LD_S r0,[gp,s11] 1100 100s ssss ssss
+// #######################################################################################################################
+ return handleop_LD_S_r0_gp_s11(op); // LD_S r0,[gp,s11]
+ }
+ case 0x01:
+ {
+// #######################################################################################################################
+// IIII ISS
+// LDB_S r0,[gp,s9] 1100 101s ssss ssss
+// #######################################################################################################################
+ return handleop_LDB_S_r0_gp_s9(op); // LDB_S r0,[gp,s9]
+ }
+ case 0x02:
+ {
+// #######################################################################################################################
+// IIII ISS
+// LDW_S r0,[gp,s10] 1100 110s ssss ssss
+// #######################################################################################################################
+ return handleop_LDW_S_r0_gp_s10(op); // LDW_S r0,[gp,s10]
+ }
+ case 0x03:
+ {
+// #######################################################################################################################
+// IIII ISS
+// ADD_S r0,gp,s11 1100 111s ssss ssss
+// #######################################################################################################################
+ return handleop_ADD_S_r0_gp_s11(op); // ADD_S r0,gp,s11
+ }
+ }
+ }
+ case 0x1a:
+ {
+// #######################################################################################################################
+// IIII I
+// LD_S b,[pcl,u10] 1101 0bbb uuuu uuuu
+// #######################################################################################################################
+ return handleop_LD_S_b_pcl_u10(op); // LD_S b,[pcl,u10]
+ }
+
+ case 0x1b:
+ {
+// #######################################################################################################################
+// IIII I
+// MOV_S b,u8 1101 1bbb uuuu uuuu
+// #######################################################################################################################
+ return handleop_MOV_S_b_u8(op); // MOV_S b, u8
+ }
+
+ case 0x1c: // ADD_S/CMP_S
+ {
+ uint8_t subinstr = (op & 0x0080) >> 7;
+ switch (subinstr)
+ {
+ default: return -1;
+ case 0x00:
+ {
+// #######################################################################################################################
+// IIII I s
+// ADD_S b,b,u7 1110 0bbb 0uuu uuuu
+// #######################################################################################################################
+ return handleop_ADD_S_b_b_u7(op); // ADD_S b, b, u7
+ }
+ case 0x01:
+ {
+// #######################################################################################################################
+// IIII I s
+// CMP_S b,u7 1110 0bbb 1uuu uuuu
+// #######################################################################################################################
+ return handleop_CMP_S_b_u7(op); // CMP_S b, u7
+ }
+ }
+ }
+ case 0x1d: // BRcc_S
+ {
+ uint8_t subinstr = (op & 0x0080) >> 7;
+ switch (subinstr)
+ {
+ default: return -1;
+ case 0x00:
+ {
+// #######################################################################################################################
+// IIII I s
+// BREQ_S b,0,s8 1110 1bbb 0sss ssss
+// #######################################################################################################################
+ return handleop_BREQ_S_b_0_s8(op); // BREQ_S b,0,s8
+ }
+ case 0x01:
+ {
+// #######################################################################################################################
+// IIII I s
+// BRNE_S b,0,s8 1110 1bbb 1sss ssss
+// #######################################################################################################################
+ return handleop_BRNE_S_b_0_s8(op); // BRNE_S b,0,s8
+ }
+ }
+ }
+ case 0x1e: // Bcc_S
+ {
+ uint8_t subinstr = (op & 0x0600) >> 9;
+ switch (subinstr)
+ {
+ default: return -1;
+ case 0x00:
+ {
+// #######################################################################################################################
+// IIII ISS
+// B_S s10 1111 000s ssss ssss
+// #######################################################################################################################
+ return handleop_B_S_s10(op); // B_S s10
+ }
+ case 0x01:
+ {
+// #######################################################################################################################
+// IIII ISS
+// BEQ_S s10 1111 001s ssss ssss
+// #######################################################################################################################
+ return handleop_BEQ_S_s10(op); // BEQ_S s10
+ }
+ case 0x02:
+ {
+// #######################################################################################################################
+// IIII ISS
+// BNE_S s10 1111 010s ssss ssss
+// #######################################################################################################################
+ return handleop_BNE_S_s10(op); // BNE_S s10
+ }
+ case 0x03: // Bcc_S
+ {
+ uint8_t subinstr2 = (op & 0x01c0) >> 6;
+ switch (subinstr2)
+ {
+ default: return -1;
+ case 0x00:
+ {
+// #######################################################################################################################
+// IIII ISSs ss
+// BGT_S s7 1111 0110 00ss ssss
+// #######################################################################################################################
+ return handleop_BGT_S_s7(op); // BGT_S s7
+ }
+ case 0x01:
+ {
+// #######################################################################################################################
+// IIII ISSs ss
+// BGE_S s7 1111 0110 01ss ssss
+// #######################################################################################################################
+ return handleop_BGE_S_s7(op); // BGE_S s7
+ }
+ case 0x02:
+ {
+// #######################################################################################################################
+// IIII ISSs ss
+// BLT_S s7 1111 0110 10ss ssss
+// #######################################################################################################################
+ return handleop_BLT_S_s7(op); // BLT_S s7
+ }
+ case 0x03:
+ {
+// #######################################################################################################################
+// IIII ISSs ss
+// BLE_S s7 1111 0110 11ss ssss
+// #######################################################################################################################
+ return handleop_BLE_S_s7(op); // BLE_S s7
+ }
+ case 0x04:
+ {
+// #######################################################################################################################
+// IIII ISSs ss
+// BHI_S s7 1111 0111 00ss ssss
+// #######################################################################################################################
+ return handleop_BHI_S_s7(op); // BHI_S s7
+ }
+ case 0x05:
+ {
+// #######################################################################################################################
+// IIII ISSs ss
+// BHS_S s7 1111 0111 01ss ssss
+// #######################################################################################################################
+ return handleop_BHS_S_s7(op); // BHS_S s7
+ }
+ case 0x06:
+ {
+// #######################################################################################################################
+// IIII ISSs ss
+// BLO_S s7 1111 0111 10ss ssss
+// #######################################################################################################################
+ return handleop_BLO_S_s7(op); // BLO_S s7
+ }
+
+ case 0x07:
+ {
+// #######################################################################################################################
+// IIII ISSs ss
+// BLS_S s7 1111 0111 11ss ssss
+// #######################################################################################################################
+ return handleop_BLS_S_s7(op); // BLS_S s7
+ }
+ }
+ }
+ }
+ }
+ case 0x1f:
+ {
+// #######################################################################################################################
+// IIII I
+// BL_S s13 1111 1sss ssss ssss
+// #######################################################################################################################
+ return handleop_BL_S_s13(op); // BL_S s13
+ }
+ }
+ }
+ return 0;
}
diff --git a/src/devices/cpu/arcompact/arcompact.h b/src/devices/cpu/arcompact/arcompact.h
index 8025510a203..714e0f1ebeb 100644
--- a/src/devices/cpu/arcompact/arcompact.h
+++ b/src/devices/cpu/arcompact/arcompact.h
@@ -1,9 +1,7 @@
// license:BSD-3-Clause
// copyright-holders:David Haywood
/*********************************\
-
ARCompact Core
-
\*********************************/
#ifndef MAME_CPU_ARCOMPACT_ARCOMPACT_H
@@ -11,87 +9,25 @@
#pragma once
-enum
-{
- ARCOMPACT_PC = STATE_GENPC,
- ARCOMPACT_STATUS32 = 0x10,
- ARCOMPACT_LP_START,
- ARCOMPACT_LP_END
+#include "arcompact_common.h"
-};
-#define ARCOMPACT_RETTYPE uint32_t
-#define OPS_32 uint32_t op
-#define OPS_16 uint16_t op
-#define PARAMS op
-#define LIMM_REG 62
-#define ARCOMPACT_OPERATION ((op & 0xf800) >> 11)
-
-
-#define ARCOMPACT_HANDLER04_P11_TYPE(name) \
-ARCOMPACT_RETTYPE arcompact_handle##name##_p11(OPS_32) \
-{ \
- int M = (op & 0x00000020) >> 5; \
- \
- switch (M) \
- { \
- case 0x00: return arcompact_handle##name##_p11_m0(PARAMS); \
- case 0x01: return arcompact_handle##name##_p11_m1(PARAMS); \
- } \
- \
- return 0; \
-}
-#define ARCOMPACT_HANDLER04_TYPE(name) \
-ARCOMPACT_RETTYPE arcompact_handle##name(OPS_32) \
-{ \
- int p = (op & 0x00c00000) >> 22; \
- \
- switch (p) \
- { \
- case 0x00: return arcompact_handle##name##_p00(PARAMS); \
- case 0x01: return arcompact_handle##name##_p01(PARAMS); \
- case 0x02: return arcompact_handle##name##_p10(PARAMS); \
- case 0x03: return arcompact_handle##name##_p11(PARAMS); \
- } \
- \
- return 0; \
-}
-
-#define ARCOMPACT_HANDLER04_TYPE_PM(name) \
- ARCOMPACT_RETTYPE arcompact_handle##name##_p00(OPS_32); \
- ARCOMPACT_RETTYPE arcompact_handle##name##_p01(OPS_32); \
- ARCOMPACT_RETTYPE arcompact_handle##name##_p10(OPS_32); \
- ARCOMPACT_RETTYPE arcompact_handle##name##_p11_m0(OPS_32); \
- ARCOMPACT_RETTYPE arcompact_handle##name##_p11_m1(OPS_32); \
- ARCOMPACT_HANDLER04_P11_TYPE(name); \
- ARCOMPACT_HANDLER04_TYPE(name);
-
-class arcompact_device : public cpu_device
+class arcompact_device : public cpu_device, protected arcompact_common
{
public:
// construction/destruction
arcompact_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
- DECLARE_READ32_MEMBER( arcompact_auxreg002_LPSTART_r);
- DECLARE_WRITE32_MEMBER(arcompact_auxreg002_LPSTART_w);
- DECLARE_READ32_MEMBER( arcompact_auxreg003_LPEND_r);
- DECLARE_WRITE32_MEMBER(arcompact_auxreg003_LPEND_w);
-
- DECLARE_READ32_MEMBER( arcompact_auxreg00a_STATUS32_r);
- DECLARE_READ32_MEMBER( arcompact_auxreg025_INTVECTORBASE_r);
- DECLARE_WRITE32_MEMBER( arcompact_auxreg025_INTVECTORBASE_w);
+ void set_default_vector_base(uint32_t address) { m_default_vector_base = address & 0xfffffc00; }
-
- void arcompact_auxreg_map(address_map &map);
protected:
// device-level overrides
- virtual void device_start() override;
- virtual void device_reset() override;
+ virtual void device_start() override ATTR_COLD;
+ virtual void device_reset() override ATTR_COLD;
// device_execute_interface overrides
- virtual uint32_t execute_min_cycles() const override { return 5; }
- virtual uint32_t execute_max_cycles() const override { return 5; }
- virtual uint32_t execute_input_lines() const override { return 0; }
+ virtual uint32_t execute_min_cycles() const noexcept override { return 5; }
+ virtual uint32_t execute_max_cycles() const noexcept override { return 5; }
virtual void execute_run() override;
virtual void execute_set_input(int inputnum, int state) override;
@@ -105,726 +41,455 @@ protected:
// device_disasm_interface overrides
virtual std::unique_ptr<util::disasm_interface> create_disassembler() override;
+private:
+ void arcompact_auxreg_map(address_map &map) ATTR_COLD;
+
+
+ uint32_t arcompact_auxreg002_LPSTART_r();
+ void arcompact_auxreg002_LPSTART_w(uint32_t data);
+ uint32_t arcompact_auxreg003_LPEND_r();
+ void arcompact_auxreg003_LPEND_w(uint32_t data);
+
+ uint32_t arcompact_auxreg00a_STATUS32_r();
+
+ uint32_t arcompact_auxreg00b_STATUS32_L1_r();
+ uint32_t arcompact_auxreg00c_STATUS32_L2_r();
+ void arcompact_auxreg00b_STATUS32_L1_w(uint32_t data);
+ void arcompact_auxreg00c_STATUS32_L2_w(uint32_t data);
+
+ void arcompact_auxreg012_MULHI_w(uint32_t data);
+
+ uint32_t arcompact_auxreg012_TIMER0_r(offs_t offset);
+ uint32_t arcompact_auxreg100_TIMER1_r(offs_t offset);
+ void arcompact_auxreg012_TIMER0_w(offs_t offset, uint32_t data);
+ void arcompact_auxreg100_TIMER1_w(offs_t offset, uint32_t data);
+
+ uint32_t arcompact_auxreg025_INTVECTORBASE_r();
+ void arcompact_auxreg025_INTVECTORBASE_w(uint32_t data);
+
+ uint32_t arcompact_auxreg043_AUX_IRQ_LV12_r();
+ void arcompact_auxreg043_AUX_IRQ_LV12_w(uint32_t data);
+
+ uint32_t arcompact_auxreg200_AUX_IRQ_LVL_r();
+ void arcompact_auxreg200_AUX_IRQ_LVL_w(uint32_t data);
+
+
+ const static int REG_BLINK = 0x1f; // r31
+ const static int REG_GP = 0x1a; // r26
+ const static int REG_FP = 0x1b; // r27
+ const static int REG_SP = 0x1c; // r28
+ const static int REG_ILINK1 = 0x1d; // r29
+ const static int REG_ILINK2 = 0x1e; // r30
+ const static int REG_MLO = 0x39; // r57 - multiply low 32-bits (of 64-bit result)
+ const static int REG_MMID = 0x3a; // r58 - multiply mid 32-bits (of 64-bit result - overlaps)
+ const static int REG_MHI = 0x3b; // r59 - multiply high 32-bits (of 64-bit result)
+ const static int REG_LP_COUNT = 0x3c; // r60
+ const static int REG_LIMM = 0x3e; // r62 - used to indicate long immedaite
+ const static int REG_PCL = 0x3f; // r63
+
+ const static uint32_t E1_FLAG = 0x00000002;
+ const static uint32_t E2_FLAG = 0x00000004;
+
+ const static uint32_t V_OVERFLOW_FLAG = 0x00000100;
+ const static uint32_t C_CARRY_FLAG = 0x00000200;
+ const static uint32_t N_NEGATIVE_FLAG = 0x00000400;
+ const static uint32_t Z_ZERO_FLAG = 0x00000800;
+
+ enum
+ {
+ ARCOMPACT_PC = STATE_GENPC,
+ ARCOMPACT_STATUS32 = 0x10,
+ ARCOMPACT_LP_START,
+ ARCOMPACT_LP_END
+ };
+
+ void get_limm_32bit_opcode()
+ {
+ m_regs[REG_LIMM] = (READ16((m_pc + 4)) << 16);
+ m_regs[REG_LIMM] |= READ16((m_pc + 6));
+ }
+
+ void get_limm_16bit_opcode()
+ {
+ m_regs[REG_LIMM] = (READ16((m_pc + 2)) << 16);
+ m_regs[REG_LIMM] |= READ16((m_pc + 4));
+ }
+
+ int check_limm16(uint8_t hreg)
+ {
+ if (hreg == REG_LIMM)
+ {
+ get_limm_16bit_opcode();
+ return 6;
+ }
+ return 2;
+ }
+
+ int check_limm(uint8_t reg)
+ {
+ if (reg == REG_LIMM)
+ {
+ get_limm_32bit_opcode();
+ return 8;
+ }
+ return 4;
+ }
+
+ int check_limm(uint8_t breg, uint8_t creg)
+ {
+ if ((breg == REG_LIMM) || (creg == REG_LIMM))
+ {
+ get_limm_32bit_opcode();
+ return 8;
+ }
+ return 4;
+ }
+
+ static uint8_t group_0e_get_h(uint16_t op)
+ {
+ uint8_t h = ((op & 0x0007) << 3);
+ h |= ((op & 0x00e0) >> 5);
+ return h;
+ }
+
+ void status32_set_e1() { m_status32 |= E1_FLAG; }
+ void status32_clear_e1() { m_status32 &= ~E1_FLAG; }
+ bool status32_check_e1() { return (m_status32 & E1_FLAG ? true : false); }
+
+ void status32_set_e2() { m_status32 |= E2_FLAG; }
+ void status32_clear_e2() { m_status32 &= ~E2_FLAG; }
+ bool status32_check_e2() { return (m_status32 & E2_FLAG ? true : false); }
+
+ // V = overflow (set if signed operation would overflow)
+ void status32_set_v() { m_status32 |= V_OVERFLOW_FLAG; }
+ void status32_clear_v() { m_status32 &= ~V_OVERFLOW_FLAG; }
+ bool status32_check_v() { return (m_status32 & V_OVERFLOW_FLAG ? true : false); }
+
+ // C = carry (unsigned op, carry set is same condition as LO Lower Than, carry clear is same condition as HS Higher Same)
+ void status32_set_c() { m_status32 |= C_CARRY_FLAG; }
+ void status32_clear_c() { m_status32 &= ~C_CARRY_FLAG; }
+ bool status32_check_c() { return (m_status32 & C_CARRY_FLAG ? true : false); }
+
+ // N = negative (set if most significant bit of result is set)
+ void status32_set_n() { m_status32 |= N_NEGATIVE_FLAG; }
+ void status32_clear_n() { m_status32 &= ~N_NEGATIVE_FLAG; }
+ bool status32_check_n() { return (m_status32 & N_NEGATIVE_FLAG ? true : false); }
+
+ // Z = zero (set if result is zero, ie both values the same for CMP)
+ void status32_set_z() { m_status32 |= Z_ZERO_FLAG; }
+ void status32_clear_z() { m_status32 &= ~Z_ZERO_FLAG; }
+ bool status32_check_z() { return (m_status32 & Z_ZERO_FLAG ? true : false); }
+
+ // debug is the name of the register, this is not a debug function
+ void debugreg_set_ZZ() { m_debug |= (1<<23); }
+ void debugreg_clear_ZZ() { m_debug &= ~(1<<23); }
+ bool debugreg_check_ZZ() { return (m_debug & (1<<23)) ? true : false; }
+
+ // 0x00 - AL / RA - Always
+ static bool condition_AL() { return (true); }
+ // 0x01 - EQ / Z - Zero
+ bool condition_EQ() { return (status32_check_z()); }
+ // 0x02 - NE / NZ - Non-Zero
+ bool condition_NE() { return (!status32_check_z()); }
+ // 0x03 - PL / P - Positive
+ bool condition_PL() { return (!status32_check_n()); }
+ // 0x04 - MI / N - Negative
+ bool condition_MI() { return (status32_check_n()); }
+ // 0x05 - CS / C / LO - Carry Set
+ bool condition_CS() { return (status32_check_c()); }
+ // 0x06 - CC / NC / HS - Carry Clear
+ bool condition_HS() { return (!status32_check_c()); }
+ // 0x07 - VS / V - Overflow set
+ bool condition_VS() { return (status32_check_v()); }
+ // 0x08 - VC / NV - Overflow clear
+ bool condition_VC() { return (!status32_check_v()); }
+ // 0x09 GT - Greater than (signed)
+ bool condition_GT() { return ((status32_check_n() && status32_check_v() && !status32_check_z()) || (!status32_check_n() && !status32_check_v() && !status32_check_z())); }
+ // 0x0a - GE - Greater than or equal to (signed)
+ bool condition_GE() { return ((status32_check_n() && status32_check_v()) || (!status32_check_n() && !status32_check_v())); }
+ // 0x0b - LT - Less than (signed)
+ bool condition_LT() { return ((status32_check_n() && !status32_check_v()) || (!status32_check_n() && status32_check_v())); };
+ // 0x0c - LE - Less than or equal (signed)
+ bool condition_LE() { return ((status32_check_z()) || (status32_check_n() && !status32_check_v()) || (!status32_check_n() && status32_check_v())) ; }
+ // 0x0d - HI - Higher than (unsigned)
+ bool condition_HI() { return ((!status32_check_c()) && (!status32_check_z())); }
+ // 0x0e - LS - Lower than or same (unsigned)
+ bool condition_LS() { return (status32_check_c() || status32_check_z()); }
+ // 0x0f - PNZ - Positive Non Zero
+ bool condition_PNZ() { return ((!status32_check_n()) && (!status32_check_z())); }
+
+ void check_interrupts();
+ /************************************************************************************************************************************
+ * *
+ * 32-bit opcode handlers *
+ * *
+ ************************************************************************************************************************************/
- // Dispatch
- ARCOMPACT_RETTYPE arcompact_handle00(OPS_32);
- ARCOMPACT_RETTYPE arcompact_handle01(OPS_32);
- ARCOMPACT_RETTYPE arcompact_handle01_00(OPS_32);
- ARCOMPACT_RETTYPE arcompact_handle01_01(OPS_32);
- ARCOMPACT_RETTYPE arcompact_handle01_01_00(OPS_32);
- ARCOMPACT_RETTYPE arcompact_handle01_01_01(OPS_32);
- ARCOMPACT_RETTYPE arcompact_handle04(OPS_32);
- ARCOMPACT_RETTYPE arcompact_handle04_2f(OPS_32);
- ARCOMPACT_RETTYPE arcompact_handle04_2f_3f(OPS_32);
- ARCOMPACT_RETTYPE arcompact_handle05(OPS_32);
-
- ARCOMPACT_RETTYPE arcompact_handle05_2f(OPS_32);
- ARCOMPACT_RETTYPE arcompact_handle05_2f_3f(OPS_32);
-
- ARCOMPACT_RETTYPE arcompact_handle0c(OPS_16);
- ARCOMPACT_RETTYPE arcompact_handle0d(OPS_16);
- ARCOMPACT_RETTYPE arcompact_handle0e(OPS_16);
- ARCOMPACT_RETTYPE arcompact_handle0f(OPS_16);
- ARCOMPACT_RETTYPE arcompact_handle0f_00(OPS_16);
- ARCOMPACT_RETTYPE arcompact_handle0f_00_07(OPS_16);
- ARCOMPACT_RETTYPE arcompact_handle17(OPS_16);
- ARCOMPACT_RETTYPE arcompact_handle18(OPS_16);
- ARCOMPACT_RETTYPE arcompact_handle18_05(OPS_16);
- ARCOMPACT_RETTYPE arcompact_handle18_06(OPS_16);
- ARCOMPACT_RETTYPE arcompact_handle18_07(OPS_16);
- ARCOMPACT_RETTYPE arcompact_handle19(OPS_16);
- ARCOMPACT_RETTYPE arcompact_handle1c(OPS_16);
- ARCOMPACT_RETTYPE arcompact_handle1d(OPS_16);
- ARCOMPACT_RETTYPE arcompact_handle1e(OPS_16);
- ARCOMPACT_RETTYPE arcompact_handle1e_03(OPS_16);
-
- // Handler
-
- ARCOMPACT_RETTYPE arcompact_handle00_00(OPS_32);
- ARCOMPACT_RETTYPE arcompact_handle00_01(OPS_32);
- ARCOMPACT_RETTYPE arcompact_handle01_00_00dasm(OPS_32);
- ARCOMPACT_RETTYPE arcompact_handle01_00_01dasm(OPS_32);
- ARCOMPACT_RETTYPE arcompact_handle01_01_00_00(OPS_32);
- ARCOMPACT_RETTYPE arcompact_handle01_01_00_01(OPS_32);
- ARCOMPACT_RETTYPE arcompact_handle01_01_00_02(OPS_32);
- ARCOMPACT_RETTYPE arcompact_handle01_01_00_03(OPS_32);
- ARCOMPACT_RETTYPE arcompact_handle01_01_00_04(OPS_32);
- ARCOMPACT_RETTYPE arcompact_handle01_01_00_05(OPS_32);
- ARCOMPACT_RETTYPE arcompact_handle01_01_00_0e(OPS_32);
- ARCOMPACT_RETTYPE arcompact_handle01_01_00_0f(OPS_32);
- ARCOMPACT_RETTYPE arcompact_handle01_01_01_00(OPS_32);
- ARCOMPACT_RETTYPE arcompact_handle01_01_01_01(OPS_32);
- ARCOMPACT_RETTYPE arcompact_handle01_01_01_02(OPS_32);
- ARCOMPACT_RETTYPE arcompact_handle01_01_01_03(OPS_32);
- ARCOMPACT_RETTYPE arcompact_handle01_01_01_04(OPS_32);
- ARCOMPACT_RETTYPE arcompact_handle01_01_01_05(OPS_32);
- ARCOMPACT_RETTYPE arcompact_handle01_01_01_0e(OPS_32);
- ARCOMPACT_RETTYPE arcompact_handle01_01_01_0f(OPS_32);
- ARCOMPACT_RETTYPE arcompact_handle02(OPS_32);
- ARCOMPACT_RETTYPE arcompact_handle03(OPS_32);
-// ARCOMPACT_RETTYPE arcompact_handle04_00(OPS_32);
- ARCOMPACT_RETTYPE arcompact_handle04_01(OPS_32);
-// ARCOMPACT_RETTYPE arcompact_handle04_02(OPS_32);
- ARCOMPACT_RETTYPE arcompact_handle04_03(OPS_32);
-// ARCOMPACT_RETTYPE arcompact_handle04_04(OPS_32);
-// ARCOMPACT_RETTYPE arcompact_handle04_05(OPS_32);
-// ARCOMPACT_RETTYPE arcompact_handle04_06(OPS_32);
-// ARCOMPACT_RETTYPE arcompact_handle04_07(OPS_32);
- ARCOMPACT_RETTYPE arcompact_handle04_08(OPS_32);
- ARCOMPACT_RETTYPE arcompact_handle04_09(OPS_32);
-// ARCOMPACT_RETTYPE arcompact_handle04_0a(OPS_32);
- ARCOMPACT_RETTYPE arcompact_handle04_0b(OPS_32);
- ARCOMPACT_RETTYPE arcompact_handle04_0c(OPS_32);
- ARCOMPACT_RETTYPE arcompact_handle04_0d(OPS_32);
-// ARCOMPACT_RETTYPE arcompact_handle04_0e(OPS_32);
-// ARCOMPACT_RETTYPE arcompact_handle04_0f(OPS_32);
- ARCOMPACT_RETTYPE arcompact_handle04_10(OPS_32);
- ARCOMPACT_RETTYPE arcompact_handle04_11(OPS_32);
- ARCOMPACT_RETTYPE arcompact_handle04_12(OPS_32);
-// ARCOMPACT_RETTYPE arcompact_handle04_13(OPS_32);
-// ARCOMPACT_RETTYPE arcompact_handle04_14(OPS_32);
-// ARCOMPACT_RETTYPE arcompact_handle04_15(OPS_32);
-// ARCOMPACT_RETTYPE arcompact_handle04_16(OPS_32);
-// ARCOMPACT_RETTYPE arcompact_handle04_17(OPS_32);
-// ARCOMPACT_RETTYPE arcompact_handle04_18(OPS_32);
-// ARCOMPACT_RETTYPE arcompact_handle04_19(OPS_32);
- ARCOMPACT_RETTYPE arcompact_handle04_1a(OPS_32);
- ARCOMPACT_RETTYPE arcompact_handle04_1b(OPS_32);
- ARCOMPACT_RETTYPE arcompact_handle04_1c(OPS_32);
- ARCOMPACT_RETTYPE arcompact_handle04_1d(OPS_32);
-// ARCOMPACT_RETTYPE arcompact_handle04_20(OPS_32);
-// ARCOMPACT_RETTYPE arcompact_handle04_21(OPS_32);
- ARCOMPACT_RETTYPE arcompact_handle04_22(OPS_32);
- ARCOMPACT_RETTYPE arcompact_handle04_23(OPS_32);
- ARCOMPACT_RETTYPE arcompact_handle04_28(OPS_32);
- ARCOMPACT_RETTYPE arcompact_handle04_29(OPS_32);
-// ARCOMPACT_RETTYPE arcompact_handle04_2a(OPS_32);
-// ARCOMPACT_RETTYPE arcompact_handle04_2b(OPS_32);
- ARCOMPACT_RETTYPE arcompact_handle04_2f_00(OPS_32);
- ARCOMPACT_RETTYPE arcompact_handle04_2f_01(OPS_32);
-// ARCOMPACT_RETTYPE arcompact_handle04_2f_02(OPS_32);
-// ARCOMPACT_RETTYPE arcompact_handle04_2f_03(OPS_32);
- ARCOMPACT_RETTYPE arcompact_handle04_2f_04(OPS_32);
- ARCOMPACT_RETTYPE arcompact_handle04_2f_05(OPS_32);
- ARCOMPACT_RETTYPE arcompact_handle04_2f_06(OPS_32);
-// ARCOMPACT_RETTYPE arcompact_handle04_2f_07(OPS_32);
-// ARCOMPACT_RETTYPE arcompact_handle04_2f_08(OPS_32);
- ARCOMPACT_RETTYPE arcompact_handle04_2f_09(OPS_32);
- ARCOMPACT_RETTYPE arcompact_handle04_2f_0a(OPS_32);
- ARCOMPACT_RETTYPE arcompact_handle04_2f_0b(OPS_32);
- ARCOMPACT_RETTYPE arcompact_handle04_2f_0c(OPS_32);
- ARCOMPACT_RETTYPE arcompact_handle04_2f_3f_01(OPS_32);
- ARCOMPACT_RETTYPE arcompact_handle04_2f_3f_02(OPS_32);
- ARCOMPACT_RETTYPE arcompact_handle04_2f_3f_03(OPS_32);
- ARCOMPACT_RETTYPE arcompact_handle04_2f_3f_04(OPS_32);
- ARCOMPACT_RETTYPE arcompact_handle04_2f_3f_05(OPS_32);
- ARCOMPACT_RETTYPE arcompact_handle04_30(OPS_32);
- ARCOMPACT_RETTYPE arcompact_handle04_31(OPS_32);
- ARCOMPACT_RETTYPE arcompact_handle04_32(OPS_32);
- ARCOMPACT_RETTYPE arcompact_handle04_33(OPS_32);
- ARCOMPACT_RETTYPE arcompact_handle04_34(OPS_32);
- ARCOMPACT_RETTYPE arcompact_handle04_35(OPS_32);
- ARCOMPACT_RETTYPE arcompact_handle04_36(OPS_32);
- ARCOMPACT_RETTYPE arcompact_handle04_37(OPS_32);
- //ARCOMPACT_RETTYPE arcompact_handle05_00(OPS_32);
- //ARCOMPACT_RETTYPE arcompact_handle05_01(OPS_32);
- ARCOMPACT_RETTYPE arcompact_handle05_02(OPS_32);
- ARCOMPACT_RETTYPE arcompact_handle05_03(OPS_32);
- ARCOMPACT_RETTYPE arcompact_handle05_04(OPS_32);
- ARCOMPACT_RETTYPE arcompact_handle05_05(OPS_32);
- ARCOMPACT_RETTYPE arcompact_handle05_06(OPS_32);
- ARCOMPACT_RETTYPE arcompact_handle05_07(OPS_32);
- ARCOMPACT_RETTYPE arcompact_handle05_08(OPS_32);
- ARCOMPACT_RETTYPE arcompact_handle05_0a(OPS_32);
- ARCOMPACT_RETTYPE arcompact_handle05_0b(OPS_32);
- ARCOMPACT_RETTYPE arcompact_handle05_28(OPS_32);
- ARCOMPACT_RETTYPE arcompact_handle05_29(OPS_32);
-
- ARCOMPACT_RETTYPE arcompact_handle06(OPS_32);
- ARCOMPACT_RETTYPE arcompact_handle07(OPS_32);
- ARCOMPACT_RETTYPE arcompact_handle08(OPS_32);
- ARCOMPACT_RETTYPE arcompact_handle09(OPS_32);
- ARCOMPACT_RETTYPE arcompact_handle0a(OPS_32);
- ARCOMPACT_RETTYPE arcompact_handle0b(OPS_32);
-
- ARCOMPACT_RETTYPE arcompact_handle0c_00(OPS_16);
- ARCOMPACT_RETTYPE arcompact_handle0c_01(OPS_16);
- ARCOMPACT_RETTYPE arcompact_handle0c_02(OPS_16);
- ARCOMPACT_RETTYPE arcompact_handle0c_03(OPS_16);
- ARCOMPACT_RETTYPE arcompact_handle0d_00(OPS_16);
- ARCOMPACT_RETTYPE arcompact_handle0d_01(OPS_16);
- ARCOMPACT_RETTYPE arcompact_handle0d_02(OPS_16);
- ARCOMPACT_RETTYPE arcompact_handle0d_03(OPS_16);
- ARCOMPACT_RETTYPE arcompact_handle0e_00(OPS_16);
- ARCOMPACT_RETTYPE arcompact_handle0e_01(OPS_16);
- ARCOMPACT_RETTYPE arcompact_handle0e_02(OPS_16);
- ARCOMPACT_RETTYPE arcompact_handle0e_03(OPS_16);
- ARCOMPACT_RETTYPE arcompact_handle0f_00_00(OPS_16);
- ARCOMPACT_RETTYPE arcompact_handle0f_00_01(OPS_16);
- ARCOMPACT_RETTYPE arcompact_handle0f_00_02(OPS_16);
- ARCOMPACT_RETTYPE arcompact_handle0f_00_03(OPS_16);
- ARCOMPACT_RETTYPE arcompact_handle0f_00_06(OPS_16);
- ARCOMPACT_RETTYPE arcompact_handle0f_00_07_00(OPS_16);
- ARCOMPACT_RETTYPE arcompact_handle0f_00_07_01(OPS_16);
- ARCOMPACT_RETTYPE arcompact_handle0f_00_07_04(OPS_16);
- ARCOMPACT_RETTYPE arcompact_handle0f_00_07_05(OPS_16);
- ARCOMPACT_RETTYPE arcompact_handle0f_00_07_06(OPS_16);
- ARCOMPACT_RETTYPE arcompact_handle0f_00_07_07(OPS_16);
- ARCOMPACT_RETTYPE arcompact_handle0f_02(OPS_16);
- ARCOMPACT_RETTYPE arcompact_handle0f_04(OPS_16);
- ARCOMPACT_RETTYPE arcompact_handle0f_05(OPS_16);
- ARCOMPACT_RETTYPE arcompact_handle0f_06(OPS_16);
- ARCOMPACT_RETTYPE arcompact_handle0f_07(OPS_16);
- ARCOMPACT_RETTYPE arcompact_handle0f_0b(OPS_16);
- ARCOMPACT_RETTYPE arcompact_handle0f_0c(OPS_16);
- ARCOMPACT_RETTYPE arcompact_handle0f_0d(OPS_16);
- ARCOMPACT_RETTYPE arcompact_handle0f_0e(OPS_16);
- ARCOMPACT_RETTYPE arcompact_handle0f_0f(OPS_16);
- ARCOMPACT_RETTYPE arcompact_handle0f_10(OPS_16);
- ARCOMPACT_RETTYPE arcompact_handle0f_11(OPS_16);
- ARCOMPACT_RETTYPE arcompact_handle0f_12(OPS_16);
- ARCOMPACT_RETTYPE arcompact_handle0f_13(OPS_16);
- ARCOMPACT_RETTYPE arcompact_handle0f_14(OPS_16);
- ARCOMPACT_RETTYPE arcompact_handle0f_15(OPS_16);
- ARCOMPACT_RETTYPE arcompact_handle0f_16(OPS_16);
- ARCOMPACT_RETTYPE arcompact_handle0f_18(OPS_16);
- ARCOMPACT_RETTYPE arcompact_handle0f_19(OPS_16);
- ARCOMPACT_RETTYPE arcompact_handle0f_1a(OPS_16);
- ARCOMPACT_RETTYPE arcompact_handle0f_1b(OPS_16);
- ARCOMPACT_RETTYPE arcompact_handle0f_1c(OPS_16);
- ARCOMPACT_RETTYPE arcompact_handle0f_1d(OPS_16);
- ARCOMPACT_RETTYPE arcompact_handle0f_1e(OPS_16);
- ARCOMPACT_RETTYPE arcompact_handle0f_1f(OPS_16);
- ARCOMPACT_RETTYPE arcompact_handle10(OPS_16);
- ARCOMPACT_RETTYPE arcompact_handle11(OPS_16);
- ARCOMPACT_RETTYPE arcompact_handle12(OPS_16);
- ARCOMPACT_RETTYPE arcompact_handle13(OPS_16);
- ARCOMPACT_RETTYPE arcompact_handle14(OPS_16);
- ARCOMPACT_RETTYPE arcompact_handle15(OPS_16);
- ARCOMPACT_RETTYPE arcompact_handle16(OPS_16);
- ARCOMPACT_RETTYPE arcompact_handle17_00(OPS_16);
- ARCOMPACT_RETTYPE arcompact_handle17_01(OPS_16);
- ARCOMPACT_RETTYPE arcompact_handle17_02(OPS_16);
- ARCOMPACT_RETTYPE arcompact_handle17_03(OPS_16);
- ARCOMPACT_RETTYPE arcompact_handle17_04(OPS_16);
- ARCOMPACT_RETTYPE arcompact_handle17_05(OPS_16);
- ARCOMPACT_RETTYPE arcompact_handle17_06(OPS_16);
- ARCOMPACT_RETTYPE arcompact_handle17_07(OPS_16);
- ARCOMPACT_RETTYPE arcompact_handle18_00(OPS_16);
- ARCOMPACT_RETTYPE arcompact_handle18_01(OPS_16);
- ARCOMPACT_RETTYPE arcompact_handle18_02(OPS_16);
- ARCOMPACT_RETTYPE arcompact_handle18_03(OPS_16);
- ARCOMPACT_RETTYPE arcompact_handle18_04(OPS_16);
- ARCOMPACT_RETTYPE arcompact_handle18_05_00(OPS_16);
- ARCOMPACT_RETTYPE arcompact_handle18_05_01(OPS_16);
- ARCOMPACT_RETTYPE arcompact_handle18_06_01(OPS_16);
- ARCOMPACT_RETTYPE arcompact_handle18_06_11(OPS_16);
- ARCOMPACT_RETTYPE arcompact_handle18_07_01(OPS_16);
- ARCOMPACT_RETTYPE arcompact_handle18_07_11(OPS_16);
- ARCOMPACT_RETTYPE arcompact_handle19_00(OPS_16);
- ARCOMPACT_RETTYPE arcompact_handle19_01(OPS_16);
- ARCOMPACT_RETTYPE arcompact_handle19_02(OPS_16);
- ARCOMPACT_RETTYPE arcompact_handle19_03(OPS_16);
- ARCOMPACT_RETTYPE arcompact_handle1a(OPS_16);
- ARCOMPACT_RETTYPE arcompact_handle1b(OPS_16);
- ARCOMPACT_RETTYPE arcompact_handle1c_00(OPS_16);
- ARCOMPACT_RETTYPE arcompact_handle1c_01(OPS_16);
- ARCOMPACT_RETTYPE arcompact_handle1d_00(OPS_16);
- ARCOMPACT_RETTYPE arcompact_handle1d_01(OPS_16);
- ARCOMPACT_RETTYPE arcompact_handle1e_00(OPS_16);
- ARCOMPACT_RETTYPE arcompact_handle1e_01(OPS_16);
- ARCOMPACT_RETTYPE arcompact_handle1e_02(OPS_16);
- ARCOMPACT_RETTYPE arcompact_handle1e_03_00(OPS_16);
- ARCOMPACT_RETTYPE arcompact_handle1e_03_01(OPS_16);
- ARCOMPACT_RETTYPE arcompact_handle1e_03_02(OPS_16);
- ARCOMPACT_RETTYPE arcompact_handle1e_03_03(OPS_16);
- ARCOMPACT_RETTYPE arcompact_handle1e_03_04(OPS_16);
- ARCOMPACT_RETTYPE arcompact_handle1e_03_05(OPS_16);
- ARCOMPACT_RETTYPE arcompact_handle1e_03_06(OPS_16);
- ARCOMPACT_RETTYPE arcompact_handle1e_03_07(OPS_16);
- ARCOMPACT_RETTYPE arcompact_handle1f(OPS_16);
+ // arcompact_execute_ops_00to01.cpp
+ uint32_t handleop32_B_cc_D_s21(uint32_t op);
+ uint32_t handleop32_B_D_s25(uint32_t op);
+ uint32_t handleop32_BL_cc_d_s21(uint32_t op);
+ uint32_t handleop32_BL_d_s25(uint32_t op);
+ uint32_t get_01_01_01_address_offset(uint32_t op);
+ uint32_t BRxx_takejump(uint32_t address, uint8_t n, int size, bool link);
+ static bool BRxx_condition(uint8_t condition, uint32_t b, uint32_t c);
+ uint32_t handleop32_BRxx_reg_reg(uint32_t op, uint8_t condition);
+ uint32_t handleop32_BRxx_reg_imm(uint32_t op, uint8_t condition);
+
+ // arcompact_execute_ops_02to03.cpp
+ uint32_t handleop32_LD_r_o(uint32_t op);
+ uint32_t handleop32_ST_r_o(uint32_t op);
+
+ // arcompact_execute_ops_04.cpp
+ static uint32_t handleop32_ADD_do_op(arcompact_device &o, uint32_t src1, uint32_t src2, bool set_flags);
+ static uint32_t handleop32_ADC_do_op(arcompact_device &o, uint32_t src1, uint32_t src2, bool set_flags);
+ static uint32_t handleop32_SUB_do_op(arcompact_device &o, uint32_t src1, uint32_t src2, bool set_flags);
+ static uint32_t handleop32_AND_do_op(arcompact_device &o, uint32_t src1, uint32_t src2, bool set_flags);
+ static uint32_t handleop32_OR_do_op(arcompact_device &o, uint32_t src1, uint32_t src2, bool set_flags);
+ static uint32_t handleop32_BIC_do_op(arcompact_device &o, uint32_t src1, uint32_t src2, bool set_flags);
+ static uint32_t handleop32_XOR_do_op(arcompact_device &o, uint32_t src1, uint32_t src2, bool set_flags);
+
+ void handleop32_MOV_do_op(uint32_t breg, uint32_t src2, bool set_flags);
+ uint32_t handleop32_MOV(uint32_t op);
+
+ static uint32_t handleop32_RSUB_do_op(arcompact_device &o, uint32_t src1, uint32_t src2, bool set_flags);
+ static uint32_t handleop32_BSET_do_op(arcompact_device &o, uint32_t src1, uint32_t src2, bool set_flags);
+ static uint32_t handleop32_BCLR_do_op(arcompact_device &o, uint32_t src1, uint32_t src2, bool set_flags);
+ static uint32_t handleop32_BMSK_do_op(arcompact_device &o, uint32_t src1, uint32_t src2, bool set_flags);
+ static uint32_t handleop32_ADD1_do_op(arcompact_device &o, uint32_t src1, uint32_t src2, bool set_flags);
+ static uint32_t handleop32_ADD2_do_op(arcompact_device &o, uint32_t src1, uint32_t src2, bool set_flags);
+ static uint32_t handleop32_ADD3_do_op(arcompact_device &o, uint32_t src1, uint32_t src2, bool set_flags);
+ static uint32_t handleop32_SUB1_do_op(arcompact_device &o, uint32_t src1, uint32_t src2, bool set_flags);
+ static uint32_t handleop32_SUB2_do_op(arcompact_device &o, uint32_t src1, uint32_t src2, bool set_flags);
+ static uint32_t handleop32_SUB3_do_op(arcompact_device &o, uint32_t src1, uint32_t src2, bool set_flags);
+ static uint32_t handleop32_SBC_do_op(arcompact_device &o, uint32_t src1, uint32_t src2, bool set_flags);
+ static uint32_t handleop32_MAX_do_op(arcompact_device &o, uint32_t src1, uint32_t src2, bool set_flags);
+ static uint32_t handleop32_MIN_do_op(arcompact_device &o, uint32_t src1, uint32_t src2, bool set_flags);
+ static uint32_t handleop32_BXOR_do_op(arcompact_device &o, uint32_t src1, uint32_t src2, bool set_flags);
+ static uint32_t handleop32_MPY_do_op(arcompact_device &o, uint32_t src1, uint32_t src2, bool set_flags);
+ static uint32_t handleop32_MPYH_do_op(arcompact_device &o, uint32_t src1, uint32_t src2, bool set_flags);
+ static uint32_t handleop32_MPYHU_do_op(arcompact_device &o, uint32_t src1, uint32_t src2, bool set_flags);
+ static uint32_t handleop32_MPYU_do_op(arcompact_device &o, uint32_t src1, uint32_t src2, bool set_flags);
+
+ static void handleop32_TST_do_op(arcompact_device &o, uint32_t src1, uint32_t src2);
+ static void handleop32_CMP_do_op(arcompact_device &o, uint32_t src1, uint32_t src2);
+ static void handleop32_RCMP_do_op(arcompact_device &o, uint32_t src1, uint32_t src2);
+ static void handleop32_BTST_do_op(arcompact_device &o, uint32_t src1, uint32_t src2);
+
+ void handleop32_FLAG_do_op(uint32_t source);
+ uint32_t handleop32_FLAG(uint32_t op);
+
+ // arcompact_execute_ops_04_jumps.cpp
+ uint32_t handle_jump_to_addr(bool delay, bool link, uint32_t address, uint32_t next_addr);
+ uint32_t handle_jump_to_register(bool delay, bool link, uint32_t reg, uint32_t next_addr, int flag);
+ uint32_t handleop32_Jcc_f_a_b_c_helper(uint32_t op, bool delay, bool link);
+ uint32_t handleop32_Jcc_cc_f_b_b_c_helper(uint32_t op, bool delay, bool link);
+ uint32_t handleop32_J(uint32_t op, bool delay, bool link);
+
+ // arcompact_execute_ops_04_aux.cpp
+ uint32_t handleop32_LR(uint32_t op);
+ uint32_t handleop32_SR(uint32_t op);
+
+ // arcompact_execute_ops_04_loop.cpp
+ uint32_t handleop32_LP(uint32_t op);
+
+ // arcompact_execute_ops_04_2f_sop.cpp
+ static uint32_t handleop32_ASR_single_do_op(arcompact_device &o, uint32_t src, bool set_flags);
+ static uint32_t handleop32_ASL_single_do_op(arcompact_device &o, uint32_t src, bool set_flags);
+ static uint32_t handleop32_LSR_single_do_op(arcompact_device &o, uint32_t src, bool set_flags);
+ static uint32_t handleop32_ROR_do_op(arcompact_device &o, uint32_t src, bool set_flags);
+ static uint32_t handleop32_EXTB_do_op(arcompact_device &o, uint32_t src, bool set_flags);
+ static uint32_t handleop32_EXTW_do_op(arcompact_device &o, uint32_t src, bool set_flags);
+ static uint32_t handleop32_RLC_do_op(arcompact_device &o, uint32_t src, bool set_flags);
+
+ static uint32_t handleop32_RRC_do_op(arcompact_device &o, uint32_t src, bool set_flags);
+ static uint32_t handleop32_SEXB_do_op(arcompact_device &o, uint32_t src, bool set_flags);
+ static uint32_t handleop32_SEXW_do_op(arcompact_device &o, uint32_t src, bool set_flags);
+ static uint32_t handleop32_ABS_do_op(arcompact_device &o, uint32_t src, bool set_flags);
+ static uint32_t handleop32_NOT_do_op(arcompact_device &o, uint32_t src, bool set_flags);
+ uint32_t handleop32_EX(uint32_t op);
+
+ // arcompact_execute_ops_04_2f_3f_zop.cpp
+ uint32_t handleop32_SLEEP(uint32_t op);
+ uint32_t handleop32_SWI(uint32_t op);
+ uint32_t handleop32_SYNC(uint32_t op);
+ uint32_t handleop32_RTIE(uint32_t op);
+ uint32_t handleop32_BRK(uint32_t op);
+
+ // arcompact_execute_ops_04_3x.cpp
+ uint32_t handleop32_LDrr(uint32_t op, int dsize, int extend);
+
+ // arcompact_execute_ops_05.cpp
+ static uint32_t handleop32_ASL_multiple_do_op(arcompact_device &o, uint32_t src1, uint32_t src2, bool set_flags);
+ static uint32_t handleop32_LSR_multiple_do_op(arcompact_device &o, uint32_t src1, uint32_t src2, bool set_flags);
+ static uint32_t handleop32_ASR_multiple_do_op(arcompact_device &o, uint32_t src1, uint32_t src2, bool set_flags);
+ static uint32_t handleop32_ROR_multiple_do_op(arcompact_device &o, uint32_t src1, uint32_t src2, bool set_flags);
+ static void handleop32_MUL64_do_op(arcompact_device &o, uint32_t src1, uint32_t src2);
+ static void handleop32_MULU64_do_op(arcompact_device &o, uint32_t src1, uint32_t src2);
+ static uint32_t handleop32_ADDS_do_op(arcompact_device &o, uint32_t src1, uint32_t src2, bool set_flags);
+ static uint32_t handleop32_SUBS_do_op(arcompact_device &o, uint32_t src1, uint32_t src2, bool set_flags);
+ static uint32_t handleop32_DIVAW_do_op(arcompact_device &o, uint32_t src1, uint32_t src2, bool set_flags);
+ static uint32_t handleop32_ASLS_do_op(arcompact_device &o, uint32_t src1, uint32_t src2, bool set_flags);
+ static uint32_t handleop32_ASRS_do_op(arcompact_device &o, uint32_t src1, uint32_t src2, bool set_flags);
+ static uint32_t handleop32_ADDSDW_do_op(arcompact_device &o, uint32_t src1, uint32_t src2, bool set_flags);
+ static uint32_t handleop32_SUBSDW_do_op(arcompact_device &o, uint32_t src1, uint32_t src2, bool set_flags);
+ static uint32_t handleop32_UNKNOWN_05_0c_do_op(arcompact_device &o, uint32_t src1, uint32_t src2, bool set_flags);
+ static uint32_t handleop32_UNKNOWN_05_10_do_op(arcompact_device &o, uint32_t src1, uint32_t src2, bool set_flags);
+ static uint32_t handleop32_UNKNOWN_05_14_do_op(arcompact_device &o, uint32_t src1, uint32_t src2, bool set_flags);
+
+ // arcompact_execute_ops_05_2f_sop.cpp
+ static uint32_t handleop32_NORM_do_op(arcompact_device &o, uint32_t src, bool set_flags);
+ static uint32_t handleop32_SWAP_do_op(arcompact_device &o, uint32_t src, bool set_flags);
+ static uint32_t handleop32_SAT16_do_op(arcompact_device &o, uint32_t src, bool set_flags);
+ static uint32_t handleop32_RND16_do_op(arcompact_device &o, uint32_t src, bool set_flags);
+ static uint32_t handleop32_ABSSW_do_op(arcompact_device &o, uint32_t src, bool set_flags);
+ static uint32_t handleop32_ABSS_do_op(arcompact_device &o, uint32_t src, bool set_flags);
+ static uint32_t handleop32_NEGSW_do_op(arcompact_device &o, uint32_t src, bool set_flags);
+ static uint32_t handleop32_NEGS_do_op(arcompact_device &o, uint32_t src, bool set_flags);
+ static uint32_t handleop32_NORMW_do_op(arcompact_device &o, uint32_t src, bool set_flags);
+
+ // arcompact_execute_ops_06to0b.cpp
+ uint32_t handleop32_ARC_EXT06(uint32_t op);
+ uint32_t handleop32_USER_EXT07(uint32_t op);
+ uint32_t handleop32_USER_EXT08(uint32_t op);
+ uint32_t handleop32_MARKET_EXT09(uint32_t op);
+ uint32_t handleop32_MARKET_EXT0a(uint32_t op);
+ uint32_t handleop32_MARKET_EXT0b(uint32_t op);
/************************************************************************************************************************************
* *
- * illegal opcode handlers (disassembly) *
+ * 16-bit opcode handlers *
* *
************************************************************************************************************************************/
- ARCOMPACT_RETTYPE arcompact_handle01_01_00_06(OPS_32);
- ARCOMPACT_RETTYPE arcompact_handle01_01_00_07(OPS_32);
- ARCOMPACT_RETTYPE arcompact_handle01_01_00_08(OPS_32);
- ARCOMPACT_RETTYPE arcompact_handle01_01_00_09(OPS_32);
- ARCOMPACT_RETTYPE arcompact_handle01_01_00_0a(OPS_32);
- ARCOMPACT_RETTYPE arcompact_handle01_01_00_0b(OPS_32);
- ARCOMPACT_RETTYPE arcompact_handle01_01_00_0c(OPS_32);
- ARCOMPACT_RETTYPE arcompact_handle01_01_00_0d(OPS_32);
-
- ARCOMPACT_RETTYPE arcompact_handle01_01_01_06(OPS_32);
- ARCOMPACT_RETTYPE arcompact_handle01_01_01_07(OPS_32);
- ARCOMPACT_RETTYPE arcompact_handle01_01_01_08(OPS_32);
- ARCOMPACT_RETTYPE arcompact_handle01_01_01_09(OPS_32);
- ARCOMPACT_RETTYPE arcompact_handle01_01_01_0a(OPS_32);
- ARCOMPACT_RETTYPE arcompact_handle01_01_01_0b(OPS_32);
- ARCOMPACT_RETTYPE arcompact_handle01_01_01_0c(OPS_32);
- ARCOMPACT_RETTYPE arcompact_handle01_01_01_0d(OPS_32);
-
-
- ARCOMPACT_RETTYPE arcompact_handle04_1e(OPS_32);
- ARCOMPACT_RETTYPE arcompact_handle04_1f(OPS_32);
-
- ARCOMPACT_RETTYPE arcompact_handle04_24(OPS_32);
- ARCOMPACT_RETTYPE arcompact_handle04_25(OPS_32);
- ARCOMPACT_RETTYPE arcompact_handle04_26(OPS_32);
- ARCOMPACT_RETTYPE arcompact_handle04_27(OPS_32);
-
- ARCOMPACT_RETTYPE arcompact_handle04_2c(OPS_32);
- ARCOMPACT_RETTYPE arcompact_handle04_2d(OPS_32);
- ARCOMPACT_RETTYPE arcompact_handle04_2e(OPS_32);
-
- ARCOMPACT_RETTYPE arcompact_handle04_2f_0d(OPS_32);
- ARCOMPACT_RETTYPE arcompact_handle04_2f_0e(OPS_32);
- ARCOMPACT_RETTYPE arcompact_handle04_2f_0f(OPS_32);
- ARCOMPACT_RETTYPE arcompact_handle04_2f_10(OPS_32);
- ARCOMPACT_RETTYPE arcompact_handle04_2f_11(OPS_32);
- ARCOMPACT_RETTYPE arcompact_handle04_2f_12(OPS_32);
- ARCOMPACT_RETTYPE arcompact_handle04_2f_13(OPS_32);
- ARCOMPACT_RETTYPE arcompact_handle04_2f_14(OPS_32);
- ARCOMPACT_RETTYPE arcompact_handle04_2f_15(OPS_32);
- ARCOMPACT_RETTYPE arcompact_handle04_2f_16(OPS_32);
- ARCOMPACT_RETTYPE arcompact_handle04_2f_17(OPS_32);
- ARCOMPACT_RETTYPE arcompact_handle04_2f_18(OPS_32);
- ARCOMPACT_RETTYPE arcompact_handle04_2f_19(OPS_32);
- ARCOMPACT_RETTYPE arcompact_handle04_2f_1a(OPS_32);
- ARCOMPACT_RETTYPE arcompact_handle04_2f_1b(OPS_32);
- ARCOMPACT_RETTYPE arcompact_handle04_2f_1c(OPS_32);
- ARCOMPACT_RETTYPE arcompact_handle04_2f_1d(OPS_32);
- ARCOMPACT_RETTYPE arcompact_handle04_2f_1e(OPS_32);
- ARCOMPACT_RETTYPE arcompact_handle04_2f_1f(OPS_32);
- ARCOMPACT_RETTYPE arcompact_handle04_2f_20(OPS_32);
- ARCOMPACT_RETTYPE arcompact_handle04_2f_21(OPS_32);
- ARCOMPACT_RETTYPE arcompact_handle04_2f_22(OPS_32);
- ARCOMPACT_RETTYPE arcompact_handle04_2f_23(OPS_32);
- ARCOMPACT_RETTYPE arcompact_handle04_2f_24(OPS_32);
- ARCOMPACT_RETTYPE arcompact_handle04_2f_25(OPS_32);
- ARCOMPACT_RETTYPE arcompact_handle04_2f_26(OPS_32);
- ARCOMPACT_RETTYPE arcompact_handle04_2f_27(OPS_32);
- ARCOMPACT_RETTYPE arcompact_handle04_2f_28(OPS_32);
- ARCOMPACT_RETTYPE arcompact_handle04_2f_29(OPS_32);
- ARCOMPACT_RETTYPE arcompact_handle04_2f_2a(OPS_32);
- ARCOMPACT_RETTYPE arcompact_handle04_2f_2b(OPS_32);
- ARCOMPACT_RETTYPE arcompact_handle04_2f_2c(OPS_32);
- ARCOMPACT_RETTYPE arcompact_handle04_2f_2d(OPS_32);
- ARCOMPACT_RETTYPE arcompact_handle04_2f_2e(OPS_32);
- ARCOMPACT_RETTYPE arcompact_handle04_2f_2f(OPS_32);
- ARCOMPACT_RETTYPE arcompact_handle04_2f_30(OPS_32);
- ARCOMPACT_RETTYPE arcompact_handle04_2f_31(OPS_32);
- ARCOMPACT_RETTYPE arcompact_handle04_2f_32(OPS_32);
- ARCOMPACT_RETTYPE arcompact_handle04_2f_33(OPS_32);
- ARCOMPACT_RETTYPE arcompact_handle04_2f_34(OPS_32);
- ARCOMPACT_RETTYPE arcompact_handle04_2f_35(OPS_32);
- ARCOMPACT_RETTYPE arcompact_handle04_2f_36(OPS_32);
- ARCOMPACT_RETTYPE arcompact_handle04_2f_37(OPS_32);
- ARCOMPACT_RETTYPE arcompact_handle04_2f_38(OPS_32);
- ARCOMPACT_RETTYPE arcompact_handle04_2f_39(OPS_32);
- ARCOMPACT_RETTYPE arcompact_handle04_2f_3a(OPS_32);
- ARCOMPACT_RETTYPE arcompact_handle04_2f_3b(OPS_32);
- ARCOMPACT_RETTYPE arcompact_handle04_2f_3c(OPS_32);
- ARCOMPACT_RETTYPE arcompact_handle04_2f_3d(OPS_32);
- ARCOMPACT_RETTYPE arcompact_handle04_2f_3e(OPS_32);
-
- ARCOMPACT_RETTYPE arcompact_handle04_2f_3f_00(OPS_32);
- ARCOMPACT_RETTYPE arcompact_handle04_2f_3f_06(OPS_32);
- ARCOMPACT_RETTYPE arcompact_handle04_2f_3f_07(OPS_32);
- ARCOMPACT_RETTYPE arcompact_handle04_2f_3f_08(OPS_32);
- ARCOMPACT_RETTYPE arcompact_handle04_2f_3f_09(OPS_32);
- ARCOMPACT_RETTYPE arcompact_handle04_2f_3f_0a(OPS_32);
- ARCOMPACT_RETTYPE arcompact_handle04_2f_3f_0b(OPS_32);
- ARCOMPACT_RETTYPE arcompact_handle04_2f_3f_0c(OPS_32);
- ARCOMPACT_RETTYPE arcompact_handle04_2f_3f_0d(OPS_32);
- ARCOMPACT_RETTYPE arcompact_handle04_2f_3f_0e(OPS_32);
- ARCOMPACT_RETTYPE arcompact_handle04_2f_3f_0f(OPS_32);
- ARCOMPACT_RETTYPE arcompact_handle04_2f_3f_10(OPS_32);
- ARCOMPACT_RETTYPE arcompact_handle04_2f_3f_11(OPS_32);
- ARCOMPACT_RETTYPE arcompact_handle04_2f_3f_12(OPS_32);
- ARCOMPACT_RETTYPE arcompact_handle04_2f_3f_13(OPS_32);
- ARCOMPACT_RETTYPE arcompact_handle04_2f_3f_14(OPS_32);
- ARCOMPACT_RETTYPE arcompact_handle04_2f_3f_15(OPS_32);
- ARCOMPACT_RETTYPE arcompact_handle04_2f_3f_16(OPS_32);
- ARCOMPACT_RETTYPE arcompact_handle04_2f_3f_17(OPS_32);
- ARCOMPACT_RETTYPE arcompact_handle04_2f_3f_18(OPS_32);
- ARCOMPACT_RETTYPE arcompact_handle04_2f_3f_19(OPS_32);
- ARCOMPACT_RETTYPE arcompact_handle04_2f_3f_1a(OPS_32);
- ARCOMPACT_RETTYPE arcompact_handle04_2f_3f_1b(OPS_32);
- ARCOMPACT_RETTYPE arcompact_handle04_2f_3f_1c(OPS_32);
- ARCOMPACT_RETTYPE arcompact_handle04_2f_3f_1d(OPS_32);
- ARCOMPACT_RETTYPE arcompact_handle04_2f_3f_1e(OPS_32);
- ARCOMPACT_RETTYPE arcompact_handle04_2f_3f_1f(OPS_32);
- ARCOMPACT_RETTYPE arcompact_handle04_2f_3f_20(OPS_32);
- ARCOMPACT_RETTYPE arcompact_handle04_2f_3f_21(OPS_32);
- ARCOMPACT_RETTYPE arcompact_handle04_2f_3f_22(OPS_32);
- ARCOMPACT_RETTYPE arcompact_handle04_2f_3f_23(OPS_32);
- ARCOMPACT_RETTYPE arcompact_handle04_2f_3f_24(OPS_32);
- ARCOMPACT_RETTYPE arcompact_handle04_2f_3f_25(OPS_32);
- ARCOMPACT_RETTYPE arcompact_handle04_2f_3f_26(OPS_32);
- ARCOMPACT_RETTYPE arcompact_handle04_2f_3f_27(OPS_32);
- ARCOMPACT_RETTYPE arcompact_handle04_2f_3f_28(OPS_32);
- ARCOMPACT_RETTYPE arcompact_handle04_2f_3f_29(OPS_32);
- ARCOMPACT_RETTYPE arcompact_handle04_2f_3f_2a(OPS_32);
- ARCOMPACT_RETTYPE arcompact_handle04_2f_3f_2b(OPS_32);
- ARCOMPACT_RETTYPE arcompact_handle04_2f_3f_2c(OPS_32);
- ARCOMPACT_RETTYPE arcompact_handle04_2f_3f_2d(OPS_32);
- ARCOMPACT_RETTYPE arcompact_handle04_2f_3f_2e(OPS_32);
- ARCOMPACT_RETTYPE arcompact_handle04_2f_3f_2f(OPS_32);
- ARCOMPACT_RETTYPE arcompact_handle04_2f_3f_30(OPS_32);
- ARCOMPACT_RETTYPE arcompact_handle04_2f_3f_31(OPS_32);
- ARCOMPACT_RETTYPE arcompact_handle04_2f_3f_32(OPS_32);
- ARCOMPACT_RETTYPE arcompact_handle04_2f_3f_33(OPS_32);
- ARCOMPACT_RETTYPE arcompact_handle04_2f_3f_34(OPS_32);
- ARCOMPACT_RETTYPE arcompact_handle04_2f_3f_35(OPS_32);
- ARCOMPACT_RETTYPE arcompact_handle04_2f_3f_36(OPS_32);
- ARCOMPACT_RETTYPE arcompact_handle04_2f_3f_37(OPS_32);
- ARCOMPACT_RETTYPE arcompact_handle04_2f_3f_38(OPS_32);
- ARCOMPACT_RETTYPE arcompact_handle04_2f_3f_39(OPS_32);
- ARCOMPACT_RETTYPE arcompact_handle04_2f_3f_3a(OPS_32);
- ARCOMPACT_RETTYPE arcompact_handle04_2f_3f_3b(OPS_32);
- ARCOMPACT_RETTYPE arcompact_handle04_2f_3f_3c(OPS_32);
- ARCOMPACT_RETTYPE arcompact_handle04_2f_3f_3d(OPS_32);
- ARCOMPACT_RETTYPE arcompact_handle04_2f_3f_3e(OPS_32);
- ARCOMPACT_RETTYPE arcompact_handle04_2f_3f_3f(OPS_32);
-
- ARCOMPACT_RETTYPE arcompact_handle05_2f_00(OPS_32);
- ARCOMPACT_RETTYPE arcompact_handle05_2f_01(OPS_32);
- ARCOMPACT_RETTYPE arcompact_handle05_2f_02(OPS_32);
- ARCOMPACT_RETTYPE arcompact_handle05_2f_03(OPS_32);
- ARCOMPACT_RETTYPE arcompact_handle05_2f_04(OPS_32);
- ARCOMPACT_RETTYPE arcompact_handle05_2f_05(OPS_32);
- ARCOMPACT_RETTYPE arcompact_handle05_2f_06(OPS_32);
- ARCOMPACT_RETTYPE arcompact_handle05_2f_07(OPS_32);
- ARCOMPACT_RETTYPE arcompact_handle05_2f_08(OPS_32);
- ARCOMPACT_RETTYPE arcompact_handle05_2f_09(OPS_32);
- ARCOMPACT_RETTYPE arcompact_handle05_2f_0a(OPS_32);
- ARCOMPACT_RETTYPE arcompact_handle05_2f_0b(OPS_32);
- ARCOMPACT_RETTYPE arcompact_handle05_2f_0c(OPS_32);
- ARCOMPACT_RETTYPE arcompact_handle05_2f_0d(OPS_32);
- ARCOMPACT_RETTYPE arcompact_handle05_2f_0e(OPS_32);
- ARCOMPACT_RETTYPE arcompact_handle05_2f_0f(OPS_32);
- ARCOMPACT_RETTYPE arcompact_handle05_2f_10(OPS_32);
- ARCOMPACT_RETTYPE arcompact_handle05_2f_11(OPS_32);
- ARCOMPACT_RETTYPE arcompact_handle05_2f_12(OPS_32);
- ARCOMPACT_RETTYPE arcompact_handle05_2f_13(OPS_32);
- ARCOMPACT_RETTYPE arcompact_handle05_2f_14(OPS_32);
- ARCOMPACT_RETTYPE arcompact_handle05_2f_15(OPS_32);
- ARCOMPACT_RETTYPE arcompact_handle05_2f_16(OPS_32);
- ARCOMPACT_RETTYPE arcompact_handle05_2f_17(OPS_32);
- ARCOMPACT_RETTYPE arcompact_handle05_2f_18(OPS_32);
- ARCOMPACT_RETTYPE arcompact_handle05_2f_19(OPS_32);
- ARCOMPACT_RETTYPE arcompact_handle05_2f_1a(OPS_32);
- ARCOMPACT_RETTYPE arcompact_handle05_2f_1b(OPS_32);
- ARCOMPACT_RETTYPE arcompact_handle05_2f_1c(OPS_32);
- ARCOMPACT_RETTYPE arcompact_handle05_2f_1d(OPS_32);
- ARCOMPACT_RETTYPE arcompact_handle05_2f_1e(OPS_32);
- ARCOMPACT_RETTYPE arcompact_handle05_2f_1f(OPS_32);
- ARCOMPACT_RETTYPE arcompact_handle05_2f_20(OPS_32);
- ARCOMPACT_RETTYPE arcompact_handle05_2f_21(OPS_32);
- ARCOMPACT_RETTYPE arcompact_handle05_2f_22(OPS_32);
- ARCOMPACT_RETTYPE arcompact_handle05_2f_23(OPS_32);
- ARCOMPACT_RETTYPE arcompact_handle05_2f_24(OPS_32);
- ARCOMPACT_RETTYPE arcompact_handle05_2f_25(OPS_32);
- ARCOMPACT_RETTYPE arcompact_handle05_2f_26(OPS_32);
- ARCOMPACT_RETTYPE arcompact_handle05_2f_27(OPS_32);
- ARCOMPACT_RETTYPE arcompact_handle05_2f_28(OPS_32);
- ARCOMPACT_RETTYPE arcompact_handle05_2f_29(OPS_32);
- ARCOMPACT_RETTYPE arcompact_handle05_2f_2a(OPS_32);
- ARCOMPACT_RETTYPE arcompact_handle05_2f_2b(OPS_32);
- ARCOMPACT_RETTYPE arcompact_handle05_2f_2c(OPS_32);
- ARCOMPACT_RETTYPE arcompact_handle05_2f_2d(OPS_32);
- ARCOMPACT_RETTYPE arcompact_handle05_2f_2e(OPS_32);
- ARCOMPACT_RETTYPE arcompact_handle05_2f_2f(OPS_32);
- ARCOMPACT_RETTYPE arcompact_handle05_2f_30(OPS_32);
- ARCOMPACT_RETTYPE arcompact_handle05_2f_31(OPS_32);
- ARCOMPACT_RETTYPE arcompact_handle05_2f_32(OPS_32);
- ARCOMPACT_RETTYPE arcompact_handle05_2f_33(OPS_32);
- ARCOMPACT_RETTYPE arcompact_handle05_2f_34(OPS_32);
- ARCOMPACT_RETTYPE arcompact_handle05_2f_35(OPS_32);
- ARCOMPACT_RETTYPE arcompact_handle05_2f_36(OPS_32);
- ARCOMPACT_RETTYPE arcompact_handle05_2f_37(OPS_32);
- ARCOMPACT_RETTYPE arcompact_handle05_2f_38(OPS_32);
- ARCOMPACT_RETTYPE arcompact_handle05_2f_39(OPS_32);
- ARCOMPACT_RETTYPE arcompact_handle05_2f_3a(OPS_32);
- ARCOMPACT_RETTYPE arcompact_handle05_2f_3b(OPS_32);
- ARCOMPACT_RETTYPE arcompact_handle05_2f_3c(OPS_32);
- ARCOMPACT_RETTYPE arcompact_handle05_2f_3d(OPS_32);
- ARCOMPACT_RETTYPE arcompact_handle05_2f_3e(OPS_32);
-
- ARCOMPACT_RETTYPE arcompact_handle05_2f_3f_00(OPS_32);
- ARCOMPACT_RETTYPE arcompact_handle05_2f_3f_01(OPS_32);
- ARCOMPACT_RETTYPE arcompact_handle05_2f_3f_02(OPS_32);
- ARCOMPACT_RETTYPE arcompact_handle05_2f_3f_03(OPS_32);
- ARCOMPACT_RETTYPE arcompact_handle05_2f_3f_04(OPS_32);
- ARCOMPACT_RETTYPE arcompact_handle05_2f_3f_05(OPS_32);
- ARCOMPACT_RETTYPE arcompact_handle05_2f_3f_06(OPS_32);
- ARCOMPACT_RETTYPE arcompact_handle05_2f_3f_07(OPS_32);
- ARCOMPACT_RETTYPE arcompact_handle05_2f_3f_08(OPS_32);
- ARCOMPACT_RETTYPE arcompact_handle05_2f_3f_09(OPS_32);
- ARCOMPACT_RETTYPE arcompact_handle05_2f_3f_0a(OPS_32);
- ARCOMPACT_RETTYPE arcompact_handle05_2f_3f_0b(OPS_32);
- ARCOMPACT_RETTYPE arcompact_handle05_2f_3f_0c(OPS_32);
- ARCOMPACT_RETTYPE arcompact_handle05_2f_3f_0d(OPS_32);
- ARCOMPACT_RETTYPE arcompact_handle05_2f_3f_0e(OPS_32);
- ARCOMPACT_RETTYPE arcompact_handle05_2f_3f_0f(OPS_32);
- ARCOMPACT_RETTYPE arcompact_handle05_2f_3f_10(OPS_32);
- ARCOMPACT_RETTYPE arcompact_handle05_2f_3f_11(OPS_32);
- ARCOMPACT_RETTYPE arcompact_handle05_2f_3f_12(OPS_32);
- ARCOMPACT_RETTYPE arcompact_handle05_2f_3f_13(OPS_32);
- ARCOMPACT_RETTYPE arcompact_handle05_2f_3f_14(OPS_32);
- ARCOMPACT_RETTYPE arcompact_handle05_2f_3f_15(OPS_32);
- ARCOMPACT_RETTYPE arcompact_handle05_2f_3f_16(OPS_32);
- ARCOMPACT_RETTYPE arcompact_handle05_2f_3f_17(OPS_32);
- ARCOMPACT_RETTYPE arcompact_handle05_2f_3f_18(OPS_32);
- ARCOMPACT_RETTYPE arcompact_handle05_2f_3f_19(OPS_32);
- ARCOMPACT_RETTYPE arcompact_handle05_2f_3f_1a(OPS_32);
- ARCOMPACT_RETTYPE arcompact_handle05_2f_3f_1b(OPS_32);
- ARCOMPACT_RETTYPE arcompact_handle05_2f_3f_1c(OPS_32);
- ARCOMPACT_RETTYPE arcompact_handle05_2f_3f_1d(OPS_32);
- ARCOMPACT_RETTYPE arcompact_handle05_2f_3f_1e(OPS_32);
- ARCOMPACT_RETTYPE arcompact_handle05_2f_3f_1f(OPS_32);
- ARCOMPACT_RETTYPE arcompact_handle05_2f_3f_20(OPS_32);
- ARCOMPACT_RETTYPE arcompact_handle05_2f_3f_21(OPS_32);
- ARCOMPACT_RETTYPE arcompact_handle05_2f_3f_22(OPS_32);
- ARCOMPACT_RETTYPE arcompact_handle05_2f_3f_23(OPS_32);
- ARCOMPACT_RETTYPE arcompact_handle05_2f_3f_24(OPS_32);
- ARCOMPACT_RETTYPE arcompact_handle05_2f_3f_25(OPS_32);
- ARCOMPACT_RETTYPE arcompact_handle05_2f_3f_26(OPS_32);
- ARCOMPACT_RETTYPE arcompact_handle05_2f_3f_27(OPS_32);
- ARCOMPACT_RETTYPE arcompact_handle05_2f_3f_28(OPS_32);
- ARCOMPACT_RETTYPE arcompact_handle05_2f_3f_29(OPS_32);
- ARCOMPACT_RETTYPE arcompact_handle05_2f_3f_2a(OPS_32);
- ARCOMPACT_RETTYPE arcompact_handle05_2f_3f_2b(OPS_32);
- ARCOMPACT_RETTYPE arcompact_handle05_2f_3f_2c(OPS_32);
- ARCOMPACT_RETTYPE arcompact_handle05_2f_3f_2d(OPS_32);
- ARCOMPACT_RETTYPE arcompact_handle05_2f_3f_2e(OPS_32);
- ARCOMPACT_RETTYPE arcompact_handle05_2f_3f_2f(OPS_32);
- ARCOMPACT_RETTYPE arcompact_handle05_2f_3f_30(OPS_32);
- ARCOMPACT_RETTYPE arcompact_handle05_2f_3f_31(OPS_32);
- ARCOMPACT_RETTYPE arcompact_handle05_2f_3f_32(OPS_32);
- ARCOMPACT_RETTYPE arcompact_handle05_2f_3f_33(OPS_32);
- ARCOMPACT_RETTYPE arcompact_handle05_2f_3f_34(OPS_32);
- ARCOMPACT_RETTYPE arcompact_handle05_2f_3f_35(OPS_32);
- ARCOMPACT_RETTYPE arcompact_handle05_2f_3f_36(OPS_32);
- ARCOMPACT_RETTYPE arcompact_handle05_2f_3f_37(OPS_32);
- ARCOMPACT_RETTYPE arcompact_handle05_2f_3f_38(OPS_32);
- ARCOMPACT_RETTYPE arcompact_handle05_2f_3f_39(OPS_32);
- ARCOMPACT_RETTYPE arcompact_handle05_2f_3f_3a(OPS_32);
- ARCOMPACT_RETTYPE arcompact_handle05_2f_3f_3b(OPS_32);
- ARCOMPACT_RETTYPE arcompact_handle05_2f_3f_3c(OPS_32);
- ARCOMPACT_RETTYPE arcompact_handle05_2f_3f_3d(OPS_32);
- ARCOMPACT_RETTYPE arcompact_handle05_2f_3f_3e(OPS_32);
- ARCOMPACT_RETTYPE arcompact_handle05_2f_3f_3f(OPS_32);
-
-
- ARCOMPACT_RETTYPE arcompact_handle04_38(OPS_32);
- ARCOMPACT_RETTYPE arcompact_handle04_39(OPS_32);
- ARCOMPACT_RETTYPE arcompact_handle04_3a(OPS_32);
- ARCOMPACT_RETTYPE arcompact_handle04_3b(OPS_32);
- ARCOMPACT_RETTYPE arcompact_handle04_3c(OPS_32);
- ARCOMPACT_RETTYPE arcompact_handle04_3d(OPS_32);
- ARCOMPACT_RETTYPE arcompact_handle04_3e(OPS_32);
- ARCOMPACT_RETTYPE arcompact_handle04_3f(OPS_32);
-
- ARCOMPACT_RETTYPE arcompact_handle05_09(OPS_32);
- ARCOMPACT_RETTYPE arcompact_handle05_0c(OPS_32);
- ARCOMPACT_RETTYPE arcompact_handle05_0d(OPS_32);
- ARCOMPACT_RETTYPE arcompact_handle05_0e(OPS_32);
- ARCOMPACT_RETTYPE arcompact_handle05_0f(OPS_32);
- ARCOMPACT_RETTYPE arcompact_handle05_10(OPS_32);
- ARCOMPACT_RETTYPE arcompact_handle05_11(OPS_32);
- ARCOMPACT_RETTYPE arcompact_handle05_12(OPS_32);
- ARCOMPACT_RETTYPE arcompact_handle05_13(OPS_32);
- ARCOMPACT_RETTYPE arcompact_handle05_14(OPS_32);
- ARCOMPACT_RETTYPE arcompact_handle05_15(OPS_32);
- ARCOMPACT_RETTYPE arcompact_handle05_16(OPS_32);
- ARCOMPACT_RETTYPE arcompact_handle05_17(OPS_32);
- ARCOMPACT_RETTYPE arcompact_handle05_18(OPS_32);
- ARCOMPACT_RETTYPE arcompact_handle05_19(OPS_32);
- ARCOMPACT_RETTYPE arcompact_handle05_1a(OPS_32);
- ARCOMPACT_RETTYPE arcompact_handle05_1b(OPS_32);
- ARCOMPACT_RETTYPE arcompact_handle05_1c(OPS_32);
- ARCOMPACT_RETTYPE arcompact_handle05_1d(OPS_32);
- ARCOMPACT_RETTYPE arcompact_handle05_1e(OPS_32);
- ARCOMPACT_RETTYPE arcompact_handle05_1f(OPS_32);
- ARCOMPACT_RETTYPE arcompact_handle05_20(OPS_32);
- ARCOMPACT_RETTYPE arcompact_handle05_21(OPS_32);
- ARCOMPACT_RETTYPE arcompact_handle05_22(OPS_32);
- ARCOMPACT_RETTYPE arcompact_handle05_23(OPS_32);
- ARCOMPACT_RETTYPE arcompact_handle05_24(OPS_32);
- ARCOMPACT_RETTYPE arcompact_handle05_25(OPS_32);
- ARCOMPACT_RETTYPE arcompact_handle05_26(OPS_32);
- ARCOMPACT_RETTYPE arcompact_handle05_27(OPS_32);
-
- ARCOMPACT_RETTYPE arcompact_handle05_2a(OPS_32);
- ARCOMPACT_RETTYPE arcompact_handle05_2b(OPS_32);
- ARCOMPACT_RETTYPE arcompact_handle05_2c(OPS_32);
- ARCOMPACT_RETTYPE arcompact_handle05_2d(OPS_32);
- ARCOMPACT_RETTYPE arcompact_handle05_2e(OPS_32);
-
- ARCOMPACT_RETTYPE arcompact_handle05_30(OPS_32);
- ARCOMPACT_RETTYPE arcompact_handle05_31(OPS_32);
- ARCOMPACT_RETTYPE arcompact_handle05_32(OPS_32);
- ARCOMPACT_RETTYPE arcompact_handle05_33(OPS_32);
- ARCOMPACT_RETTYPE arcompact_handle05_34(OPS_32);
- ARCOMPACT_RETTYPE arcompact_handle05_35(OPS_32);
- ARCOMPACT_RETTYPE arcompact_handle05_36(OPS_32);
- ARCOMPACT_RETTYPE arcompact_handle05_37(OPS_32);
- ARCOMPACT_RETTYPE arcompact_handle05_38(OPS_32);
- ARCOMPACT_RETTYPE arcompact_handle05_39(OPS_32);
- ARCOMPACT_RETTYPE arcompact_handle05_3a(OPS_32);
- ARCOMPACT_RETTYPE arcompact_handle05_3b(OPS_32);
- ARCOMPACT_RETTYPE arcompact_handle05_3c(OPS_32);
- ARCOMPACT_RETTYPE arcompact_handle05_3d(OPS_32);
- ARCOMPACT_RETTYPE arcompact_handle05_3e(OPS_32);
- ARCOMPACT_RETTYPE arcompact_handle05_3f(OPS_32);
-
- ARCOMPACT_RETTYPE arcompact_handle0f_00_04(OPS_16);
- ARCOMPACT_RETTYPE arcompact_handle0f_00_05(OPS_16);
- ARCOMPACT_RETTYPE arcompact_handle0f_00_07_02(OPS_16);
- ARCOMPACT_RETTYPE arcompact_handle0f_00_07_03(OPS_16);
- ARCOMPACT_RETTYPE arcompact_handle0f_01(OPS_16);
- ARCOMPACT_RETTYPE arcompact_handle0f_03(OPS_16);
- ARCOMPACT_RETTYPE arcompact_handle0f_08(OPS_16);
- ARCOMPACT_RETTYPE arcompact_handle0f_09(OPS_16);
- ARCOMPACT_RETTYPE arcompact_handle0f_0a(OPS_16);
- ARCOMPACT_RETTYPE arcompact_handle0f_17(OPS_16);
-
- ARCOMPACT_RETTYPE arcompact_handle18_05_02(OPS_16);
- ARCOMPACT_RETTYPE arcompact_handle18_05_03(OPS_16);
- ARCOMPACT_RETTYPE arcompact_handle18_05_04(OPS_16);
- ARCOMPACT_RETTYPE arcompact_handle18_05_05(OPS_16);
- ARCOMPACT_RETTYPE arcompact_handle18_05_06(OPS_16);
- ARCOMPACT_RETTYPE arcompact_handle18_05_07(OPS_16);
- ARCOMPACT_RETTYPE arcompact_handle18_06_00(OPS_16);
- ARCOMPACT_RETTYPE arcompact_handle18_06_02(OPS_16);
- ARCOMPACT_RETTYPE arcompact_handle18_06_03(OPS_16);
- ARCOMPACT_RETTYPE arcompact_handle18_06_04(OPS_16);
- ARCOMPACT_RETTYPE arcompact_handle18_06_05(OPS_16);
- ARCOMPACT_RETTYPE arcompact_handle18_06_06(OPS_16);
- ARCOMPACT_RETTYPE arcompact_handle18_06_07(OPS_16);
- ARCOMPACT_RETTYPE arcompact_handle18_06_08(OPS_16);
- ARCOMPACT_RETTYPE arcompact_handle18_06_09(OPS_16);
- ARCOMPACT_RETTYPE arcompact_handle18_06_0a(OPS_16);
- ARCOMPACT_RETTYPE arcompact_handle18_06_0b(OPS_16);
- ARCOMPACT_RETTYPE arcompact_handle18_06_0c(OPS_16);
- ARCOMPACT_RETTYPE arcompact_handle18_06_0d(OPS_16);
- ARCOMPACT_RETTYPE arcompact_handle18_06_0e(OPS_16);
- ARCOMPACT_RETTYPE arcompact_handle18_06_0f(OPS_16);
- ARCOMPACT_RETTYPE arcompact_handle18_06_10(OPS_16);
- ARCOMPACT_RETTYPE arcompact_handle18_06_12(OPS_16);
- ARCOMPACT_RETTYPE arcompact_handle18_06_13(OPS_16);
- ARCOMPACT_RETTYPE arcompact_handle18_06_14(OPS_16);
- ARCOMPACT_RETTYPE arcompact_handle18_06_15(OPS_16);
- ARCOMPACT_RETTYPE arcompact_handle18_06_16(OPS_16);
- ARCOMPACT_RETTYPE arcompact_handle18_06_17(OPS_16);
- ARCOMPACT_RETTYPE arcompact_handle18_06_18(OPS_16);
- ARCOMPACT_RETTYPE arcompact_handle18_06_19(OPS_16);
- ARCOMPACT_RETTYPE arcompact_handle18_06_1a(OPS_16);
- ARCOMPACT_RETTYPE arcompact_handle18_06_1b(OPS_16);
- ARCOMPACT_RETTYPE arcompact_handle18_06_1c(OPS_16);
- ARCOMPACT_RETTYPE arcompact_handle18_06_1d(OPS_16);
- ARCOMPACT_RETTYPE arcompact_handle18_06_1e(OPS_16);
- ARCOMPACT_RETTYPE arcompact_handle18_06_1f(OPS_16);
- ARCOMPACT_RETTYPE arcompact_handle18_07_00(OPS_16);
- ARCOMPACT_RETTYPE arcompact_handle18_07_02(OPS_16);
- ARCOMPACT_RETTYPE arcompact_handle18_07_03(OPS_16);
- ARCOMPACT_RETTYPE arcompact_handle18_07_04(OPS_16);
- ARCOMPACT_RETTYPE arcompact_handle18_07_05(OPS_16);
- ARCOMPACT_RETTYPE arcompact_handle18_07_06(OPS_16);
- ARCOMPACT_RETTYPE arcompact_handle18_07_07(OPS_16);
- ARCOMPACT_RETTYPE arcompact_handle18_07_08(OPS_16);
- ARCOMPACT_RETTYPE arcompact_handle18_07_09(OPS_16);
- ARCOMPACT_RETTYPE arcompact_handle18_07_0a(OPS_16);
- ARCOMPACT_RETTYPE arcompact_handle18_07_0b(OPS_16);
- ARCOMPACT_RETTYPE arcompact_handle18_07_0c(OPS_16);
- ARCOMPACT_RETTYPE arcompact_handle18_07_0d(OPS_16);
- ARCOMPACT_RETTYPE arcompact_handle18_07_0e(OPS_16);
- ARCOMPACT_RETTYPE arcompact_handle18_07_0f(OPS_16);
- ARCOMPACT_RETTYPE arcompact_handle18_07_10(OPS_16);
- ARCOMPACT_RETTYPE arcompact_handle18_07_12(OPS_16);
- ARCOMPACT_RETTYPE arcompact_handle18_07_13(OPS_16);
- ARCOMPACT_RETTYPE arcompact_handle18_07_14(OPS_16);
- ARCOMPACT_RETTYPE arcompact_handle18_07_15(OPS_16);
- ARCOMPACT_RETTYPE arcompact_handle18_07_16(OPS_16);
- ARCOMPACT_RETTYPE arcompact_handle18_07_17(OPS_16);
- ARCOMPACT_RETTYPE arcompact_handle18_07_18(OPS_16);
- ARCOMPACT_RETTYPE arcompact_handle18_07_19(OPS_16);
- ARCOMPACT_RETTYPE arcompact_handle18_07_1a(OPS_16);
- ARCOMPACT_RETTYPE arcompact_handle18_07_1b(OPS_16);
- ARCOMPACT_RETTYPE arcompact_handle18_07_1c(OPS_16);
- ARCOMPACT_RETTYPE arcompact_handle18_07_1d(OPS_16);
- ARCOMPACT_RETTYPE arcompact_handle18_07_1e(OPS_16);
- ARCOMPACT_RETTYPE arcompact_handle18_07_1f(OPS_16);
-
- ARCOMPACT_RETTYPE arcompact_01_01_00_helper(OPS_32, const char* optext);
- ARCOMPACT_RETTYPE arcompact_01_01_01_helper(OPS_32, const char* optext);
- ARCOMPACT_RETTYPE arcompact_handle04_helper(OPS_32, const char* optext, int ignore_dst, int b_reserved);
- ARCOMPACT_RETTYPE arcompact_handle04_2f_helper(OPS_32, const char* optext);
- ARCOMPACT_RETTYPE arcompact_handle04_3x_helper(OPS_32, int dsize, int extend);
- ARCOMPACT_RETTYPE arcompact_handle05_2f_0x_helper(OPS_32, const char* optext);
- ARCOMPACT_RETTYPE arcompact_handle0c_helper(OPS_16, const char* optext);
- ARCOMPACT_RETTYPE arcompact_handle0d_helper(OPS_16, const char* optext);
- ARCOMPACT_RETTYPE arcompact_handle0e_0x_helper(OPS_16, const char* optext, int revop);
- ARCOMPACT_RETTYPE arcompact_handle0f_00_0x_helper(OPS_16, const char* optext);
- ARCOMPACT_RETTYPE arcompact_handle0f_0x_helper(OPS_16, const char* optext, int nodst);
- ARCOMPACT_RETTYPE arcompact_handle_ld_helper(OPS_16, const char* optext, int shift, int swap);
- ARCOMPACT_RETTYPE arcompact_handle_l7_0x_helper(OPS_16, const char* optext);
- ARCOMPACT_RETTYPE arcompact_handle18_0x_helper(OPS_16, const char* optext, int st);
- ARCOMPACT_RETTYPE arcompact_handle19_0x_helper(OPS_16, const char* optext, int shift, int format);
- ARCOMPACT_RETTYPE arcompact_handle1e_0x_helper(OPS_16, const char* optext);
- ARCOMPACT_RETTYPE arcompact_handle1e_03_0x_helper(OPS_16, const char* optext);
-
-
- uint32_t handle_jump_to_addr(int delay, int link, uint32_t address, uint32_t next_addr);
- uint32_t handle_jump_to_register(int delay, int link, uint32_t reg, uint32_t next_addr, int flag);
-
- ARCOMPACT_RETTYPE get_insruction(OPS_32);
-
- ARCOMPACT_HANDLER04_TYPE_PM(04_00)
- ARCOMPACT_HANDLER04_TYPE_PM(04_02)
- ARCOMPACT_HANDLER04_TYPE_PM(04_04)
- ARCOMPACT_HANDLER04_TYPE_PM(04_05)
- ARCOMPACT_HANDLER04_TYPE_PM(04_06)
- ARCOMPACT_HANDLER04_TYPE_PM(04_07)
- ARCOMPACT_HANDLER04_TYPE_PM(04_0a)
- ARCOMPACT_HANDLER04_TYPE_PM(04_0e)
- ARCOMPACT_HANDLER04_TYPE_PM(04_0f)
- ARCOMPACT_HANDLER04_TYPE_PM(04_13)
- ARCOMPACT_HANDLER04_TYPE_PM(04_14)
- ARCOMPACT_HANDLER04_TYPE_PM(04_15)
- ARCOMPACT_HANDLER04_TYPE_PM(04_16)
- ARCOMPACT_HANDLER04_TYPE_PM(04_17)
- ARCOMPACT_HANDLER04_TYPE_PM(04_18)
- ARCOMPACT_HANDLER04_TYPE_PM(04_19)
- ARCOMPACT_HANDLER04_TYPE_PM(04_20)
- ARCOMPACT_HANDLER04_TYPE_PM(04_21)
- ARCOMPACT_HANDLER04_TYPE_PM(04_2a)
- ARCOMPACT_HANDLER04_TYPE_PM(04_2b)
-
- ARCOMPACT_HANDLER04_TYPE_PM(04_2f_02)
- ARCOMPACT_HANDLER04_TYPE_PM(04_2f_03)
- ARCOMPACT_HANDLER04_TYPE_PM(04_2f_07)
- ARCOMPACT_HANDLER04_TYPE_PM(04_2f_08)
-
- ARCOMPACT_HANDLER04_TYPE_PM(05_00)
- ARCOMPACT_HANDLER04_TYPE_PM(05_01)
+ uint32_t handleop_LD_S_a_b_c(uint16_t op);
+ uint32_t handleop_LDB_S_a_b_c(uint16_t op);
+ uint32_t handleop_LDW_S_a_b_c(uint16_t op);
+ uint32_t handleop_ADD_S_a_b_c(uint16_t op);
+ uint32_t handleop_ADD_S_c_b_u3(uint16_t op);
+ uint32_t handleop_SUB_S_c_b_u3(uint16_t op);
+ uint32_t handleop_ASL_S_c_b_u3(uint16_t op);
+ uint32_t handleop_ASR_S_c_b_u3(uint16_t op);
+ uint32_t handleop_ADD_S_b_b_h_or_limm(uint16_t op);
+ uint32_t handleop_MOV_S_b_h_or_limm(uint16_t op);
+ uint32_t handleop_CMP_S_b_h_or_limm(uint16_t op);
+ uint32_t handleop_MOV_S_h_b(uint16_t op);
+ uint32_t handleop_J_S_b(uint16_t op);
+ uint32_t handleop_J_S_D_b(uint16_t op);
+ uint32_t handleop_JL_S_b(uint16_t op);
+ uint32_t handleop_JL_S_D_b(uint16_t op);
+ uint32_t handleop_SUB_S_NE_b_b_b(uint16_t op);
+ uint32_t handleop_NOP_S(uint16_t op);
+ uint32_t handleop_UNIMP_S(uint16_t op);
+ uint32_t handleop_JEQ_S_blink(uint16_t op);
+ uint32_t handleop_JNE_S_blink(uint16_t op);
+ uint32_t handleop_J_S_blink(uint16_t op);
+ uint32_t handleop_J_S_D_blink(uint16_t op);
+ uint32_t handleop_SUB_S_b_b_c(uint16_t op);
+ uint32_t handleop_AND_S_b_b_c(uint16_t op);
+ uint32_t handleop_OR_S_b_b_c(uint16_t op);
+ uint32_t handleop_BIC_S_b_b_c(uint16_t op);
+ uint32_t handleop_XOR_S_b_b_c(uint16_t op);
+ uint32_t handleop_TST_S_b_c(uint16_t op);
+ uint32_t handleop_MUL64_S_0_b_c(uint16_t op);
+ uint32_t handleop_SEXB_S_b_c(uint16_t op);
+ uint32_t handleop_SEXW_S_b_c(uint16_t op);
+ uint32_t handleop_EXTB_S_b_c(uint16_t op);
+ uint32_t handleop_EXTW_S_b_c(uint16_t op);
+ uint32_t handleop_ABS_S_b_c(uint16_t op);
+ uint32_t handleop_NOT_S_b_c(uint16_t op);
+ uint32_t handleop_NEG_S_b_c(uint16_t op);
+ uint32_t handleop_ADD1_S_b_b_c(uint16_t op);
+ uint32_t handleop_ADD2_S_b_b_c(uint16_t op);
+ uint32_t handleop_ADD3_S_b_b_c(uint16_t op);
+ uint32_t handleop_ASL_S_b_b_c_multiple(uint16_t op);
+ uint32_t handleop_LSR_S_b_b_c_multiple(uint16_t op);
+ uint32_t handleop_ASR_S_b_b_c_multiple(uint16_t op);
+ uint32_t handleop_ASL_S_b_c_single(uint16_t op);
+ uint32_t handleop_ASR_S_b_c_single(uint16_t op);
+ uint32_t handleop_LSR_S_b_c_single(uint16_t op);
+ uint32_t handleop_TRAP_S_u6(uint16_t op);
+ uint32_t handleop_BRK_S(uint16_t op);
+ uint32_t handleop_LD_S_c_b_u7(uint16_t op);
+ uint32_t handleop_LDB_S_c_b_u5(uint16_t op);
+ uint32_t handleop_LDW_S_c_b_u6(uint16_t op);
+ uint32_t handleop_LDW_S_X_c_b_u6(uint16_t op);
+ uint32_t handleop_ST_S_c_b_u7(uint16_t op);
+ uint32_t handleop_STB_S_c_b_u5(uint16_t op);
+ uint32_t handleop_STW_S_c_b_u6(uint16_t op);
+ uint32_t handleop_ASL_S_b_b_u5(uint16_t op);
+ uint32_t handleop_LSR_S_b_b_u5(uint16_t op);
+ uint32_t handleop_ASR_S_b_b_u5(uint16_t op);
+ uint32_t handleop_SUB_S_b_b_u5(uint16_t op);
+ uint32_t handleop_BSET_S_b_b_u5(uint16_t op);
+ uint32_t handleop_BCLR_S_b_b_u5(uint16_t op);
+ uint32_t handleop_BMSK_S_b_b_u5(uint16_t op);
+ uint32_t handleop_BTST_S_b_u5(uint16_t op);
+ uint32_t handleop_LD_S_b_sp_u7(uint16_t op);
+ uint32_t handleop_LDB_S_b_sp_u7(uint16_t op);
+ uint32_t handleop_ST_S_b_sp_u7(uint16_t op);
+ uint32_t handleop_STB_S_b_sp_u7(uint16_t op);
+ uint32_t handleop_ADD_S_b_sp_u7(uint16_t op);
+ uint32_t handleop_ADD_S_sp_sp_u7(uint16_t op);
+ uint32_t handleop_SUB_S_sp_sp_u7(uint16_t op);
+ uint32_t handleop_POP_S_b(uint16_t op);
+ uint32_t handleop_POP_S_blink(uint16_t op);
+ uint32_t handleop_PUSH_S_b(uint16_t op);
+ uint32_t handleop_PUSH_S_blink(uint16_t op);
+ uint32_t handleop_LD_S_r0_gp_s11(uint16_t op);
+ uint32_t handleop_LDB_S_r0_gp_s9(uint16_t op);
+ uint32_t handleop_LDW_S_r0_gp_s10(uint16_t op);
+ uint32_t handleop_ADD_S_r0_gp_s11(uint16_t op);
+ uint32_t handleop_LD_S_b_pcl_u10(uint16_t op);
+ uint32_t handleop_MOV_S_b_u8(uint16_t op);
+ uint32_t handleop_ADD_S_b_b_u7(uint16_t op);
+ uint32_t handleop_CMP_S_b_u7(uint16_t op);
+ uint32_t branch_common(uint16_t op, bool cond, unsigned width);
+ uint32_t handleop_BREQ_S_b_0_s8(uint16_t op);
+ uint32_t handleop_BRNE_S_b_0_s8(uint16_t op);
+ uint32_t handleop_B_S_s10(uint16_t op);
+ uint32_t handleop_BEQ_S_s10(uint16_t op);
+ uint32_t handleop_BNE_S_s10(uint16_t op);
+ uint32_t handleop_BGT_S_s7(uint16_t op);
+ uint32_t handleop_BGE_S_s7(uint16_t op);
+ uint32_t handleop_BLT_S_s7(uint16_t op);
+ uint32_t handleop_BLE_S_s7(uint16_t op);
+ uint32_t handleop_BHI_S_s7(uint16_t op);
+ uint32_t handleop_BHS_S_s7(uint16_t op);
+ uint32_t handleop_BLO_S_s7(uint16_t op);
+ uint32_t handleop_BLS_S_s7(uint16_t op);
+ uint32_t handleop_BL_S_s13(uint16_t op);
+ /************************************************************************************************************************************
+ * *
+ * illegal opcode handlers *
+ * *
+ ************************************************************************************************************************************/
+
+ uint32_t arcompact_handle_illegal(uint8_t param1, uint8_t param2, uint16_t op);
+ uint32_t arcompact_handle_illegal(uint8_t param1, uint8_t param2, uint8_t param3, uint16_t op);
+ uint32_t arcompact_handle_illegal(uint8_t param1, uint8_t param2, uint8_t param3, uint8_t param4, uint16_t op);
+
+ uint32_t arcompact_handle_illegal(uint8_t param1, uint8_t param2, uint32_t op);
+ uint32_t arcompact_handle_illegal(uint8_t param1, uint8_t param2, uint8_t param3, uint32_t op);
+ uint32_t arcompact_handle_illegal(uint8_t param1, uint8_t param2, uint8_t param3, uint8_t param4, uint32_t op);
+
+ uint32_t arcompact_handle_reserved(uint8_t param1, uint8_t param2, uint8_t param3, uint8_t param4, uint32_t op);
+
+ /************************************************************************************************************************************
+ * *
+ * helpers *
+ * *
+ ************************************************************************************************************************************/
+
+ uint32_t get_instruction(uint32_t op);
-private:
const address_space_config m_program_config;
const address_space_config m_io_config;
- uint32_t m_pc;
-
address_space *m_program;
- address_space *m_io;
+ address_space *m_io;
int m_icount;
@@ -832,68 +497,101 @@ private:
void unimplemented_opcode(uint16_t op);
- inline uint32_t READ32(uint32_t address) { return m_program->read_dword(address << 2); }
- inline void WRITE32(uint32_t address, uint32_t data) { m_program->write_dword(address << 2, data); }
- inline uint16_t READ16(uint32_t address) { return m_program->read_word(address << 1); }
- inline void WRITE16(uint32_t address, uint16_t data){ m_program->write_word(address << 1, data); }
- inline uint8_t READ8(uint32_t address) { return m_program->read_byte(address << 0); }
- inline void WRITE8(uint32_t address, uint8_t data){ m_program->write_byte(address << 0, data); }
-
- inline uint64_t READAUX(uint64_t address) { return m_io->read_dword(address); }
- inline void WRITEAUX(uint64_t address, uint32_t data) { m_io->write_dword(address, data); }
-
-
- int check_condition(uint8_t condition);
-
+ void set_pc(uint32_t pc)
+ {
+ m_pc = pc; // can be 16-bit aligned
+ m_regs[REG_PCL] = m_pc & 0xfffffffc; // always 32-bit aligned
+ }
+
+ uint32_t READ32(uint32_t address)
+ {
+ if (address & 0x3)
+ fatalerror("%08x: attempted unaligned READ32 on address %08x", m_pc, address);
+
+ return m_program->read_dword(address);
+ }
+
+ void WRITE32(uint32_t address, uint32_t data)
+ {
+ if (address & 0x3)
+ fatalerror("%08x: attempted unaligned WRITE32 on address %08x", m_pc, address);
+
+ m_program->write_dword(address, data);
+ }
+ uint16_t READ16(uint32_t address)
+ {
+ if (address & 0x1)
+ fatalerror("%08x: attempted unaligned READ16 on address %08x", m_pc, address);
+
+ return m_program->read_word(address);
+ }
+ void WRITE16(uint32_t address, uint16_t data)
+ {
+ if (address & 0x1)
+ fatalerror("%08x: attempted unaligned WRITE16 on address %08x", m_pc, address);
+
+ m_program->write_word(address, data);
+ }
+ uint8_t READ8(uint32_t address)
+ {
+ return m_program->read_byte(address);
+ }
+ void WRITE8(uint32_t address, uint8_t data)
+ {
+ m_program->write_byte(address, data);
+ }
+
+ uint64_t READAUX(uint64_t address) { return m_io->read_dword(address); }
+ void WRITEAUX(uint64_t address, uint32_t data) { m_io->write_dword(address, data); }
+
+ // arcompact_helper.ipp
+ bool check_condition(uint8_t condition);
+ void do_flags_overflow(uint32_t result, uint32_t b, uint32_t c);
+ void do_flags_add(uint32_t result, uint32_t b, uint32_t c);
+ void do_flags_sub(uint32_t result, uint32_t b, uint32_t c);
+ void do_flags_nz(uint32_t result);
+ using ophandler32 = uint32_t (*)(arcompact_device &obj, uint32_t src1, uint32_t src2, bool set_flags);
+ using ophandler32_ff = void (*)(arcompact_device &obj, uint32_t src1, uint32_t src2);
+ using ophandler32_mul = void (*)(arcompact_device &obj, uint32_t src1, uint32_t src2);
+ using ophandler32_sop = uint32_t (*)(arcompact_device &obj, uint32_t src1, bool set_flags);
+ uint32_t handleop32_general(uint32_t op, ophandler32 ophandler);
+ uint32_t handleop32_general_MULx64(uint32_t op, ophandler32_mul ophandler);
+ uint32_t handleop32_general_nowriteback_forced_flag(uint32_t op, ophandler32_ff ophandler);
+ uint32_t handleop32_general_SOP_group(uint32_t op, ophandler32_sop ophandler);
+ void arcompact_handle_ld_helper(uint32_t op, uint8_t areg, uint8_t breg, uint32_t s, uint8_t X, uint8_t Z, uint8_t a);
+
+ // config
+ uint32_t m_default_vector_base;
+
+ // internal state
+ uint32_t m_pc;
uint32_t m_regs[0x40];
- int m_delayactive;
- int m_delaylinks;
+ bool m_delayactive;
+ bool m_delaylinks;
uint32_t m_delayjump;
+ bool m_allow_loop_check;
+ bool m_irq_pending;
// f e d c| b a 9 8| 7 6 5 4| 3 2 1 0
// - - - L| Z N C V| U DE AE A2|A1 E2 E1 H
uint32_t m_status32;
+ uint32_t m_status32_l1;
+ uint32_t m_status32_l2;
+
+// 31 30 29 28 27 26 25 24 23 22 21 20 19 18 17 16 15 14 13 12 11 10 09 08 07 06 05 04 03 02 01 00
+// LD | SH | BH | UB | xx | xx | xx | xx | ZZ | RA | xx | xx | xx | xx | xx | xx | xx | xx | xx | xx | IS | xx | xx | xx | xx | xx | xx | xx | xx | xx | FH | SS
+ uint32_t m_debug;
+
+ uint32_t m_timer[2][3];
uint32_t m_LP_START;
uint32_t m_LP_END;
uint32_t m_INTVECTORBASE;
-
+ uint32_t m_AUX_IRQ_LV12;
+ uint32_t m_AUX_IRQ_LEV;
};
-#define V_OVERFLOW_FLAG (0x00000100)
-#define C_CARRY_FLAG (0x00000200)
-#define N_NEGATIVE_FLAG (0x00000400)
-#define Z_ZERO_FLAG (0x00000800)
-
-// V = overflow (set if signed operation would overflow)
-#define STATUS32_SET_V (m_status32 |= V_OVERFLOW_FLAG)
-#define STATUS32_CLEAR_V (m_status32 &= ~V_OVERFLOW_FLAG)
-#define STATUS32_CHECK_V (m_status32 & V_OVERFLOW_FLAG)
-
-// C = carry (unsigned op, carry set is same condition as LO Lower Than, carry clear is same condition as HS Higher Same)
-#define STATUS32_SET_C (m_status32 |= C_CARRY_FLAG)
-#define STATUS32_CLEAR_C (m_status32 &= ~C_CARRY_FLAG)
-#define STATUS32_CHECK_C (m_status32 & C_CARRY_FLAG)
-
-// N = negative (set if most significant bit of result is set)
-#define STATUS32_SET_N (m_status32 |= N_NEGATIVE_FLAG)
-#define STATUS32_CLEAR_N (m_status32 &= ~N_NEGATIVE_FLAG)
-#define STATUS32_CHECK_N (m_status32 & N_NEGATIVE_FLAG)
-
-// Z = zero (set if result is zero, ie both values the same for CMP)
-#define STATUS32_SET_Z (m_status32 |= Z_ZERO_FLAG)
-#define STATUS32_CLEAR_Z (m_status32 &= ~Z_ZERO_FLAG)
-#define STATUS32_CHECK_Z (m_status32 & Z_ZERO_FLAG)
-
-// Condition 0x0c (LE)
-#define CONDITION_LE ((STATUS32_CHECK_Z) || (STATUS32_CHECK_N && !STATUS32_CHECK_V) || (!STATUS32_CHECK_N && STATUS32_CHECK_V)) // Z or (N and /V) or (/N and V)
-#define CONDITION_EQ (STATUS32_CHECK_Z)
-#define CONDITION_CS (STATUS32_CHECK_C)
-#define CONDITION_LT ((STATUS32_CHECK_N && !STATUS32_CHECK_V) || (!STATUS32_CHECK_N && STATUS32_CHECK_V))
-#define CONDITION_MI (STATUS32_CHECK_N)
-
-
DECLARE_DEVICE_TYPE(ARCA5, arcompact_device)
#endif // MAME_CPU_ARCOMPACT_ARCOMPACT_H
diff --git a/src/devices/cpu/arcompact/arcompact_common.h b/src/devices/cpu/arcompact/arcompact_common.h
new file mode 100644
index 00000000000..bf658f5cdf3
--- /dev/null
+++ b/src/devices/cpu/arcompact/arcompact_common.h
@@ -0,0 +1,109 @@
+// license:BSD-3-Clause
+// copyright-holders:David Haywood
+/*********************************\
+ ARCompact Core
+\*********************************/
+
+#ifndef MAME_CPU_ARCOMPACT_ARCOMPACT_COMMON_H
+#define MAME_CPU_ARCOMPACT_ARCOMPACT_COMMON_H
+
+#pragma once
+
+
+class arcompact_common
+{
+protected:
+ // registers used in 16-bit opcodes have a limited range
+ // and can only address registers r0-r3 and r12-r15
+ static constexpr uint8_t common_expand_reg(uint8_t reg)
+ {
+ return (reg > 3) ? (reg + 8) : reg;
+ }
+
+ static constexpr uint8_t common16_get_and_expand_breg(uint16_t op)
+ {
+ return common_expand_reg((op & 0x0700) >> 8);
+ }
+
+ static constexpr uint8_t common16_get_and_expand_creg(uint16_t op)
+ {
+ return common_expand_reg((op & 0x00e0) >> 5);
+ }
+
+ static constexpr uint8_t common16_get_and_expand_areg(uint16_t op)
+ {
+ return common_expand_reg(op & 0x0007);
+ }
+
+ static constexpr uint32_t common16_get_u3(uint16_t op)
+ {
+ return op & 0x0007;
+ }
+
+ static constexpr uint32_t common16_get_u5(uint16_t op)
+ {
+ return op & 0x001f;
+ }
+
+ static constexpr uint32_t common16_get_u7(uint16_t op)
+ {
+ return op & 0x007f;
+ }
+
+ static constexpr uint32_t common16_get_u8(uint16_t op)
+ {
+ return op & 0x00ff;
+ }
+
+ static constexpr uint32_t common16_get_s9(uint16_t op)
+ {
+ return util::sext(op, 9);
+ }
+
+ static constexpr uint8_t common32_get_areg(uint32_t op)
+ {
+ return op & 0x0000003f;
+ }
+
+ static constexpr uint8_t common32_get_areg_reserved(uint32_t op)
+ {
+ return op & 0x0000003f;
+ }
+
+ static constexpr uint8_t common32_get_breg(uint32_t op)
+ {
+ return ((op & 0x07000000) >> 24) | (((op & 0x00007000) >> 12) << 3);
+ }
+
+ static constexpr uint8_t common32_get_creg(uint32_t op)
+ {
+ return (op & 0x00000fc0) >> 6;
+ }
+
+ static constexpr uint8_t common32_get_condition(uint32_t op)
+ {
+ return op & 0x0000001f;
+ }
+
+ static constexpr bool common32_get_F(uint32_t op)
+ {
+ return (op & 0x00008000) ? true : false;
+ }
+
+ static constexpr uint8_t common32_get_p(uint32_t op)
+ {
+ return (op & 0x00c00000) >> 22;
+ }
+
+ static constexpr uint32_t common32_get_u6(uint32_t op)
+ {
+ return (op & 0x00000fc0) >> 6;
+ }
+
+ static constexpr uint32_t common32_get_s12(uint32_t op)
+ {
+ return util::sext(((op & 0x00000fc0) >> 6) | ((op & 0x0000003f) << 6), 12);
+ }
+};
+
+#endif // MAME_CPU_ARCOMPACT_ARCOMPACT_COMMON_H
diff --git a/src/devices/cpu/arcompact/arcompact_execute.cpp b/src/devices/cpu/arcompact/arcompact_execute.cpp
index 7d5d9383708..875c12d6543 100644
--- a/src/devices/cpu/arcompact/arcompact_execute.cpp
+++ b/src/devices/cpu/arcompact/arcompact_execute.cpp
@@ -2,8134 +2,172 @@
// copyright-holders:David Haywood
#include "emu.h"
-#include "debugger.h"
-#include "arcompact.h"
-#include "arcompactdasm.h"
+#include "arcompact_helper.ipp"
-#define REG_BLINK (0x1f) // r31
-#define REG_SP (0x1c) // r28
-#define REG_ILINK1 (0x1d) // r29
-#define REG_ILINK2 (0x1e) // r30
-#define REG_LP_COUNT (0x3c) // r60
+/*
-#define ARCOMPACT_LOGGING 1
+NOTES:
-#define arcompact_fatal if (ARCOMPACT_LOGGING) fatalerror
-#define arcompact_log if (ARCOMPACT_LOGGING) fatalerror
+LIMM use
+--------
+If "destination register = LIMM" then there is no result stored, only flag updates, however there's no way to read LIMM anyway
+as specifying LIMM as a source register just causes the CPU to read the long immediate data instead. For emulation purposes we
+therefore just store the result as normal, to the reigster that can't be read.
+Likewise, when LIMM is used as a source register, we load the LIMM register with the long immediate when the opcode is decoded
+so don't require special logic further in the opcode handler.
-void arcompact_device::execute_run()
-{
- //uint32_t lres;
- //lres = 0;
-
- while (m_icount > 0)
- {
- debugger_instruction_hook(m_pc);
-
-// printf("new pc %04x\n", m_pc);
-
- if (m_delayactive)
- {
- uint16_t op = READ16((m_pc + 0) >> 1);
- m_pc = get_insruction(op);
- if (m_delaylinks) m_regs[REG_BLINK] = m_pc;
-
- m_pc = m_delayjump;
- m_delayactive = 0; m_delaylinks = 0;
- }
- else
- {
- uint16_t op = READ16((m_pc + 0) >> 1);
- m_pc = get_insruction(op);
- }
-
- // hardware loops
- if (m_pc == m_LP_END)
- {
- if (m_regs[REG_LP_COUNT] != 1)
- {
- m_pc = m_LP_START;
- }
- m_regs[REG_LP_COUNT]--;
-
- }
-
- m_icount--;
- }
-
-}
-
-
-#define GET_01_01_01_BRANCH_ADDR \
- int32_t address = (op & 0x00fe0000) >> 17; \
- address |= ((op & 0x00008000) >> 15) << 7; \
- if (address & 0x80) address = -0x80 + (address & 0x7f);
-
-#define GROUP_0e_GET_h \
- h = ((op & 0x0007) << 3); \
- h |= ((op & 0x00e0) >> 5);
-#define COMMON32_GET_breg \
- int b_temp = (op & 0x07000000) >> 24; \
- int B_temp = (op & 0x00007000) >> 12; \
- int breg = b_temp | (B_temp << 3);
-#define COMMON32_GET_creg \
- int creg = (op & 0x00000fc0) >> 6;
-#define COMMON32_GET_u6 \
- int u = (op & 0x00000fc0) >> 6;
-#define COMMON32_GET_areg \
- int areg = (op & 0x0000003f) >> 0;
-#define COMMON32_GET_areg_reserved \
- int ares = (op & 0x0000003f) >> 0;
-#define COMMON32_GET_F \
- int F = (op & 0x00008000) >> 15;
-#define COMMON32_GET_p \
- int p = (op & 0x00c00000) >> 22;
-
-#define COMMON32_GET_s12 \
- int S_temp = (op & 0x0000003f) >> 0; \
- int s_temp = (op & 0x00000fc0) >> 6; \
- int32_t S = s_temp | (S_temp<<6); \
- if (S & 0x800) S = -0x800 + (S&0x7ff); /* sign extend */
-#define COMMON32_GET_CONDITION \
- uint8_t condition = op & 0x0000001f;
-
-
-#define COMMON16_GET_breg \
- breg = ((op & 0x0700) >>8);
-#define COMMON16_GET_creg \
- creg = ((op & 0x00e0) >>5);
-#define COMMON16_GET_areg \
- areg = ((op & 0x0007) >>0);
-#define COMMON16_GET_u3 \
- u = ((op & 0x0007) >>0);
-#define COMMON16_GET_u5 \
- u = ((op & 0x001f) >>0);
-#define COMMON16_GET_u8 \
- u = ((op & 0x00ff) >>0);
-#define COMMON16_GET_u7 \
- u = ((op & 0x007f) >>0);
-#define COMMON16_GET_s9 \
- s = ((op & 0x01ff) >>0);
-// registers used in 16-bit opcodes hae a limited range
-// and can only address registers r0-r3 and r12-r15
-
-#define REG_16BIT_RANGE(_reg_) \
- if (_reg_>3) _reg_+= 8;
-
-#define GET_LIMM_32 \
- limm = (READ16((m_pc + 4) >> 1) << 16); \
- limm |= READ16((m_pc + 6) >> 1);
-#define GET_LIMM_16 \
- limm = (READ16((m_pc + 2) >> 1) << 16); \
- limm |= READ16((m_pc + 4) >> 1);
-
-#define PC_ALIGNED32 \
- (m_pc&0xfffffffc)
-
-int arcompact_device::check_condition(uint8_t condition)
-{
- switch (condition & 0x1f)
- {
- case 0x00: return 1; // AL
- case 0x01: return CONDITION_EQ;
- case 0x02: return !CONDITION_EQ; // NE
- case 0x03: fatalerror("unhandled condition check %s", arcompact_disassembler::conditions[condition]); return -1;
- case 0x04: return CONDITION_MI; // MI (N)
- case 0x05: return CONDITION_CS; // CS (Carry Set / Lower than)
- case 0x06: fatalerror("unhandled condition check %s", arcompact_disassembler::conditions[condition]); return -1;
- case 0x07: fatalerror("unhandled condition check %s", arcompact_disassembler::conditions[condition]); return -1;
- case 0x08: fatalerror("unhandled condition check %s", arcompact_disassembler::conditions[condition]); return -1;
- case 0x09: fatalerror("unhandled condition check %s", arcompact_disassembler::conditions[condition]); return -1;
- case 0x0a: fatalerror("unhandled condition check %s", arcompact_disassembler::conditions[condition]); return -1;
- case 0x0b: fatalerror("unhandled condition check %s", arcompact_disassembler::conditions[condition]); return -1;
- case 0x0c: fatalerror("unhandled condition check %s", arcompact_disassembler::conditions[condition]); return -1;
- case 0x0d: fatalerror("unhandled condition check %s", arcompact_disassembler::conditions[condition]); return -1;
- case 0x0e: fatalerror("unhandled condition check %s", arcompact_disassembler::conditions[condition]); return -1;
- case 0x0f: fatalerror("unhandled condition check %s", arcompact_disassembler::conditions[condition]); return -1;
- case 0x10: fatalerror("unhandled condition check %s", arcompact_disassembler::conditions[condition]); return -1;
- case 0x11: fatalerror("unhandled condition check %s", arcompact_disassembler::conditions[condition]); return -1;
- case 0x12: fatalerror("unhandled condition check %s", arcompact_disassembler::conditions[condition]); return -1;
- case 0x13: fatalerror("unhandled condition check %s", arcompact_disassembler::conditions[condition]); return -1;
- case 0x14: fatalerror("unhandled condition check %s", arcompact_disassembler::conditions[condition]); return -1;
- case 0x15: fatalerror("unhandled condition check %s", arcompact_disassembler::conditions[condition]); return -1;
- case 0x16: fatalerror("unhandled condition check %s", arcompact_disassembler::conditions[condition]); return -1;
- case 0x17: fatalerror("unhandled condition check %s", arcompact_disassembler::conditions[condition]); return -1;
- case 0x18: fatalerror("unhandled condition check %s", arcompact_disassembler::conditions[condition]); return -1;
- case 0x19: fatalerror("unhandled condition check %s", arcompact_disassembler::conditions[condition]); return -1;
- case 0x1a: fatalerror("unhandled condition check %s", arcompact_disassembler::conditions[condition]); return -1;
- case 0x1b: fatalerror("unhandled condition check %s", arcompact_disassembler::conditions[condition]); return -1;
- case 0x1c: fatalerror("unhandled condition check %s", arcompact_disassembler::conditions[condition]); return -1;
- case 0x1d: fatalerror("unhandled condition check %s", arcompact_disassembler::conditions[condition]); return -1;
- case 0x1e: fatalerror("unhandled condition check %s", arcompact_disassembler::conditions[condition]); return -1;
- case 0x1f: fatalerror("unhandled condition check %s", arcompact_disassembler::conditions[condition]); return -1;
- }
-
- return -1;
-
-}
-
-
-ARCOMPACT_RETTYPE arcompact_device::get_insruction(OPS_32)
-{
- uint8_t instruction = ARCOMPACT_OPERATION;
-
- if (instruction < 0x0c)
- {
- op <<= 16;
- op |= READ16((m_pc + 2) >> 1);
-
- switch (instruction) // 32-bit instructions (with optional extra dword for immediate data)
- {
- case 0x00: return arcompact_handle00(PARAMS); // Bcc
- case 0x01: return arcompact_handle01(PARAMS); // BLcc/BRcc
- case 0x02: return arcompact_handle02(PARAMS); // LD r+o
- case 0x03: return arcompact_handle03(PARAMS); // ST r+o
- case 0x04: return arcompact_handle04(PARAMS); // op a,b,c (basecase)
- case 0x05: return arcompact_handle05(PARAMS); // op a,b,c (05 ARC ext)
- case 0x06: return arcompact_handle06(PARAMS); // op a,b,c (06 ARC ext)
- case 0x07: return arcompact_handle07(PARAMS); // op a,b,c (07 User ext)
- case 0x08: return arcompact_handle08(PARAMS); // op a,b,c (08 User ext)
- case 0x09: return arcompact_handle09(PARAMS); // op a,b,c (09 Market ext)
- case 0x0a: return arcompact_handle0a(PARAMS); // op a,b,c (0a Market ext)
- case 0x0b: return arcompact_handle0b(PARAMS); // op a,b,c (0b Market ext)
- }
- }
- else
- {
- switch (instruction) // 16-bit instructions
- {
- case 0x0c: return arcompact_handle0c(PARAMS); // Load/Add reg-reg
- case 0x0d: return arcompact_handle0d(PARAMS); // Add/Sub/Shft imm
- case 0x0e: return arcompact_handle0e(PARAMS); // Mov/Cmp/Add
- case 0x0f: return arcompact_handle0f(PARAMS); // op_S b,b,c (single 16-bit ops)
- case 0x10: return arcompact_handle10(PARAMS); // LD_S
- case 0x11: return arcompact_handle11(PARAMS); // LDB_S
- case 0x12: return arcompact_handle12(PARAMS); // LDW_S
- case 0x13: return arcompact_handle13(PARAMS); // LSW_S.X
- case 0x14: return arcompact_handle14(PARAMS); // ST_S
- case 0x15: return arcompact_handle15(PARAMS); // STB_S
- case 0x16: return arcompact_handle16(PARAMS); // STW_S
- case 0x17: return arcompact_handle17(PARAMS); // Shift/Sub/Bit
- case 0x18: return arcompact_handle18(PARAMS); // Stack Instr
- case 0x19: return arcompact_handle19(PARAMS); // GP Instr
- case 0x1a: return arcompact_handle1a(PARAMS); // PCL Instr
- case 0x1b: return arcompact_handle1b(PARAMS); // MOV_S
- case 0x1c: return arcompact_handle1c(PARAMS); // ADD_S/CMP_S
- case 0x1d: return arcompact_handle1d(PARAMS); // BRcc_S
- case 0x1e: return arcompact_handle1e(PARAMS); // Bcc_S
- case 0x1f: return arcompact_handle1f(PARAMS); // BL_S
- }
- }
-
- return 0;
-}
-
-ARCOMPACT_RETTYPE arcompact_device::arcompact_handle00(OPS_32)
-{
- uint8_t subinstr = (op & 0x00010000) >> 16;
-
- switch (subinstr)
- {
- case 0x00: return arcompact_handle00_00(PARAMS); // Branch Conditionally
- case 0x01: return arcompact_handle00_01(PARAMS); // Branch Unconditionally Far
- }
-
- return 0;
-}
-
-ARCOMPACT_RETTYPE arcompact_device::arcompact_handle01(OPS_32)
-{
- uint8_t subinstr = (op & 0x00010000) >> 16;
-
- switch (subinstr)
- {
- case 0x00: return arcompact_handle01_00(PARAMS); // Branh & Link
- case 0x01: return arcompact_handle01_01(PARAMS); // Branch on Compare
- }
-
- return 0;
-}
-
-ARCOMPACT_RETTYPE arcompact_device::arcompact_handle01_00(OPS_32)
-{
- uint8_t subinstr2 = (op & 0x00020000) >> 17;
-
- switch (subinstr2)
- {
- case 0x00: return arcompact_handle01_00_00dasm(PARAMS); // Branch and Link Conditionally
- case 0x01: return arcompact_handle01_00_01dasm(PARAMS); // Branch and Link Unconditional Far
- }
-
- return 0;
-}
-
-ARCOMPACT_RETTYPE arcompact_device::arcompact_handle01_01(OPS_32)
-{
- uint8_t subinstr2 = (op & 0x00000010) >> 4;
-
- switch (subinstr2)
- {
- case 0x00: return arcompact_handle01_01_00(PARAMS); // Branch on Compare Register-Register
- case 0x01: return arcompact_handle01_01_01(PARAMS); // Branch on Compare/Bit Test Register-Immediate
- }
-
- return 0;
-}
-
-ARCOMPACT_RETTYPE arcompact_device::arcompact_handle01_01_00(OPS_32)
-{
- uint8_t subinstr3 = (op & 0x0000000f) >> 0;
-
- switch (subinstr3)
- {
- case 0x00: return arcompact_handle01_01_00_00(PARAMS); // BREQ (reg-reg)
- case 0x01: return arcompact_handle01_01_00_01(PARAMS); // BRNE (reg-reg)
- case 0x02: return arcompact_handle01_01_00_02(PARAMS); // BRLT (reg-reg)
- case 0x03: return arcompact_handle01_01_00_03(PARAMS); // BRGE (reg-reg)
- case 0x04: return arcompact_handle01_01_00_04(PARAMS); // BRLO (reg-reg)
- case 0x05: return arcompact_handle01_01_00_05(PARAMS); // BRHS (reg-reg)
- case 0x06: return arcompact_handle01_01_00_06(PARAMS); // reserved
- case 0x07: return arcompact_handle01_01_00_07(PARAMS); // reserved
- case 0x08: return arcompact_handle01_01_00_08(PARAMS); // reserved
- case 0x09: return arcompact_handle01_01_00_09(PARAMS); // reserved
- case 0x0a: return arcompact_handle01_01_00_0a(PARAMS); // reserved
- case 0x0b: return arcompact_handle01_01_00_0b(PARAMS); // reserved
- case 0x0c: return arcompact_handle01_01_00_0c(PARAMS); // reserved
- case 0x0d: return arcompact_handle01_01_00_0d(PARAMS); // reserved
- case 0x0e: return arcompact_handle01_01_00_0e(PARAMS); // BBIT0 (reg-reg)
- case 0x0f: return arcompact_handle01_01_00_0f(PARAMS); // BBIT1 (reg-reg)
- }
-
- return 0;
-}
-
-ARCOMPACT_RETTYPE arcompact_device::arcompact_handle01_01_01(OPS_32) // Branch on Compare/Bit Test Register-Immediate
-{
- uint8_t subinstr3 = (op & 0x0000000f) >> 0;
-
- switch (subinstr3)
- {
- case 0x00: return arcompact_handle01_01_01_00(PARAMS); // BREQ (reg-imm)
- case 0x01: return arcompact_handle01_01_01_01(PARAMS); // BRNE (reg-imm)
- case 0x02: return arcompact_handle01_01_01_02(PARAMS); // BRLT (reg-imm)
- case 0x03: return arcompact_handle01_01_01_03(PARAMS); // BRGE (reg-imm)
- case 0x04: return arcompact_handle01_01_01_04(PARAMS); // BRLO (reg-imm)
- case 0x05: return arcompact_handle01_01_01_05(PARAMS); // BRHS (reg-imm)
- case 0x06: return arcompact_handle01_01_01_06(PARAMS); // reserved
- case 0x07: return arcompact_handle01_01_01_07(PARAMS); // reserved
- case 0x08: return arcompact_handle01_01_01_08(PARAMS); // reserved
- case 0x09: return arcompact_handle01_01_01_09(PARAMS); // reserved
- case 0x0a: return arcompact_handle01_01_01_0a(PARAMS); // reserved
- case 0x0b: return arcompact_handle01_01_01_0b(PARAMS); // reserved
- case 0x0c: return arcompact_handle01_01_01_0c(PARAMS); // reserved
- case 0x0d: return arcompact_handle01_01_01_0d(PARAMS); // reserved
- case 0x0e: return arcompact_handle01_01_01_0e(PARAMS); // BBIT0 (reg-imm)
- case 0x0f: return arcompact_handle01_01_01_0f(PARAMS); // BBIT1 (reg-imm)
- }
-
- return 0;
-}
-
-ARCOMPACT_RETTYPE arcompact_device::arcompact_handle04(OPS_32)
-{
- uint8_t subinstr = (op & 0x003f0000) >> 16;
-
- switch (subinstr)
- {
- case 0x00: return arcompact_handle04_00(PARAMS); // ADD
- case 0x01: return arcompact_handle04_01(PARAMS); // ADC
- case 0x02: return arcompact_handle04_02(PARAMS); // SUB
- case 0x03: return arcompact_handle04_03(PARAMS); // SBC
- case 0x04: return arcompact_handle04_04(PARAMS); // AND
- case 0x05: return arcompact_handle04_05(PARAMS); // OR
- case 0x06: return arcompact_handle04_06(PARAMS); // BIC
- case 0x07: return arcompact_handle04_07(PARAMS); // XOR
- case 0x08: return arcompact_handle04_08(PARAMS); // MAX
- case 0x09: return arcompact_handle04_09(PARAMS); // MIN
- case 0x0a: return arcompact_handle04_0a(PARAMS); // MOV
- case 0x0b: return arcompact_handle04_0b(PARAMS); // TST
- case 0x0c: return arcompact_handle04_0c(PARAMS); // CMP
- case 0x0d: return arcompact_handle04_0d(PARAMS); // RCMP
- case 0x0e: return arcompact_handle04_0e(PARAMS); // RSUB
- case 0x0f: return arcompact_handle04_0f(PARAMS); // BSET
- case 0x10: return arcompact_handle04_10(PARAMS); // BCLR
- case 0x11: return arcompact_handle04_11(PARAMS); // BTST
- case 0x12: return arcompact_handle04_12(PARAMS); // BXOR
- case 0x13: return arcompact_handle04_13(PARAMS); // BMSK
- case 0x14: return arcompact_handle04_14(PARAMS); // ADD1
- case 0x15: return arcompact_handle04_15(PARAMS); // ADD2
- case 0x16: return arcompact_handle04_16(PARAMS); // ADD3
- case 0x17: return arcompact_handle04_17(PARAMS); // SUB1
- case 0x18: return arcompact_handle04_18(PARAMS); // SUB2
- case 0x19: return arcompact_handle04_19(PARAMS); // SUB3
- case 0x1a: return arcompact_handle04_1a(PARAMS); // MPY *
- case 0x1b: return arcompact_handle04_1b(PARAMS); // MPYH *
- case 0x1c: return arcompact_handle04_1c(PARAMS); // MPYHU *
- case 0x1d: return arcompact_handle04_1d(PARAMS); // MPYU *
- case 0x1e: return arcompact_handle04_1e(PARAMS); // illegal
- case 0x1f: return arcompact_handle04_1f(PARAMS); // illegal
- case 0x20: return arcompact_handle04_20(PARAMS); // Jcc
- case 0x21: return arcompact_handle04_21(PARAMS); // Jcc.D
- case 0x22: return arcompact_handle04_22(PARAMS); // JLcc
- case 0x23: return arcompact_handle04_23(PARAMS); // JLcc.D
- case 0x24: return arcompact_handle04_24(PARAMS); // illegal
- case 0x25: return arcompact_handle04_25(PARAMS); // illegal
- case 0x26: return arcompact_handle04_26(PARAMS); // illegal
- case 0x27: return arcompact_handle04_27(PARAMS); // illegal
- case 0x28: return arcompact_handle04_28(PARAMS); // LPcc
- case 0x29: return arcompact_handle04_29(PARAMS); // FLAG
- case 0x2a: return arcompact_handle04_2a(PARAMS); // LR
- case 0x2b: return arcompact_handle04_2b(PARAMS); // SR
- case 0x2c: return arcompact_handle04_2c(PARAMS); // illegal
- case 0x2d: return arcompact_handle04_2d(PARAMS); // illegal
- case 0x2e: return arcompact_handle04_2e(PARAMS); // illegal
- case 0x2f: return arcompact_handle04_2f(PARAMS); // Sub Opcode
- case 0x30: return arcompact_handle04_30(PARAMS); // LD r-r
- case 0x31: return arcompact_handle04_31(PARAMS); // LD r-r
- case 0x32: return arcompact_handle04_32(PARAMS); // LD r-r
- case 0x33: return arcompact_handle04_33(PARAMS); // LD r-r
- case 0x34: return arcompact_handle04_34(PARAMS); // LD r-r
- case 0x35: return arcompact_handle04_35(PARAMS); // LD r-r
- case 0x36: return arcompact_handle04_36(PARAMS); // LD r-r
- case 0x37: return arcompact_handle04_37(PARAMS); // LD r-r
- case 0x38: return arcompact_handle04_38(PARAMS); // illegal
- case 0x39: return arcompact_handle04_39(PARAMS); // illegal
- case 0x3a: return arcompact_handle04_3a(PARAMS); // illegal
- case 0x3b: return arcompact_handle04_3b(PARAMS); // illegal
- case 0x3c: return arcompact_handle04_3c(PARAMS); // illegal
- case 0x3d: return arcompact_handle04_3d(PARAMS); // illegal
- case 0x3e: return arcompact_handle04_3e(PARAMS); // illegal
- case 0x3f: return arcompact_handle04_3f(PARAMS); // illegal
- }
-
- return 0;
-}
-
-ARCOMPACT_RETTYPE arcompact_device::arcompact_handle04_2f(OPS_32)
-{
- uint8_t subinstr2 = (op & 0x0000003f) >> 0;
-
- switch (subinstr2)
- {
- case 0x00: return arcompact_handle04_2f_00(PARAMS); // ASL
- case 0x01: return arcompact_handle04_2f_01(PARAMS); // ASR
- case 0x02: return arcompact_handle04_2f_02(PARAMS); // LSR
- case 0x03: return arcompact_handle04_2f_03(PARAMS); // ROR
- case 0x04: return arcompact_handle04_2f_04(PARAMS); // RCC
- case 0x05: return arcompact_handle04_2f_05(PARAMS); // SEXB
- case 0x06: return arcompact_handle04_2f_06(PARAMS); // SEXW
- case 0x07: return arcompact_handle04_2f_07(PARAMS); // EXTB
- case 0x08: return arcompact_handle04_2f_08(PARAMS); // EXTW
- case 0x09: return arcompact_handle04_2f_09(PARAMS); // ABS
- case 0x0a: return arcompact_handle04_2f_0a(PARAMS); // NOT
- case 0x0b: return arcompact_handle04_2f_0b(PARAMS); // RLC
- case 0x0c: return arcompact_handle04_2f_0c(PARAMS); // EX
- case 0x0d: return arcompact_handle04_2f_0d(PARAMS); // illegal
- case 0x0e: return arcompact_handle04_2f_0e(PARAMS); // illegal
- case 0x0f: return arcompact_handle04_2f_0f(PARAMS); // illegal
- case 0x10: return arcompact_handle04_2f_10(PARAMS); // illegal
- case 0x11: return arcompact_handle04_2f_11(PARAMS); // illegal
- case 0x12: return arcompact_handle04_2f_12(PARAMS); // illegal
- case 0x13: return arcompact_handle04_2f_13(PARAMS); // illegal
- case 0x14: return arcompact_handle04_2f_14(PARAMS); // illegal
- case 0x15: return arcompact_handle04_2f_15(PARAMS); // illegal
- case 0x16: return arcompact_handle04_2f_16(PARAMS); // illegal
- case 0x17: return arcompact_handle04_2f_17(PARAMS); // illegal
- case 0x18: return arcompact_handle04_2f_18(PARAMS); // illegal
- case 0x19: return arcompact_handle04_2f_19(PARAMS); // illegal
- case 0x1a: return arcompact_handle04_2f_1a(PARAMS); // illegal
- case 0x1b: return arcompact_handle04_2f_1b(PARAMS); // illegal
- case 0x1c: return arcompact_handle04_2f_1c(PARAMS); // illegal
- case 0x1d: return arcompact_handle04_2f_1d(PARAMS); // illegal
- case 0x1e: return arcompact_handle04_2f_1e(PARAMS); // illegal
- case 0x1f: return arcompact_handle04_2f_1f(PARAMS); // illegal
- case 0x20: return arcompact_handle04_2f_20(PARAMS); // illegal
- case 0x21: return arcompact_handle04_2f_21(PARAMS); // illegal
- case 0x22: return arcompact_handle04_2f_22(PARAMS); // illegal
- case 0x23: return arcompact_handle04_2f_23(PARAMS); // illegal
- case 0x24: return arcompact_handle04_2f_24(PARAMS); // illegal
- case 0x25: return arcompact_handle04_2f_25(PARAMS); // illegal
- case 0x26: return arcompact_handle04_2f_26(PARAMS); // illegal
- case 0x27: return arcompact_handle04_2f_27(PARAMS); // illegal
- case 0x28: return arcompact_handle04_2f_28(PARAMS); // illegal
- case 0x29: return arcompact_handle04_2f_29(PARAMS); // illegal
- case 0x2a: return arcompact_handle04_2f_2a(PARAMS); // illegal
- case 0x2b: return arcompact_handle04_2f_2b(PARAMS); // illegal
- case 0x2c: return arcompact_handle04_2f_2c(PARAMS); // illegal
- case 0x2d: return arcompact_handle04_2f_2d(PARAMS); // illegal
- case 0x2e: return arcompact_handle04_2f_2e(PARAMS); // illegal
- case 0x2f: return arcompact_handle04_2f_2f(PARAMS); // illegal
- case 0x30: return arcompact_handle04_2f_30(PARAMS); // illegal
- case 0x31: return arcompact_handle04_2f_31(PARAMS); // illegal
- case 0x32: return arcompact_handle04_2f_32(PARAMS); // illegal
- case 0x33: return arcompact_handle04_2f_33(PARAMS); // illegal
- case 0x34: return arcompact_handle04_2f_34(PARAMS); // illegal
- case 0x35: return arcompact_handle04_2f_35(PARAMS); // illegal
- case 0x36: return arcompact_handle04_2f_36(PARAMS); // illegal
- case 0x37: return arcompact_handle04_2f_37(PARAMS); // illegal
- case 0x38: return arcompact_handle04_2f_38(PARAMS); // illegal
- case 0x39: return arcompact_handle04_2f_39(PARAMS); // illegal
- case 0x3a: return arcompact_handle04_2f_3a(PARAMS); // illegal
- case 0x3b: return arcompact_handle04_2f_3b(PARAMS); // illegal
- case 0x3c: return arcompact_handle04_2f_3c(PARAMS); // illegal
- case 0x3d: return arcompact_handle04_2f_3d(PARAMS); // illegal
- case 0x3e: return arcompact_handle04_2f_3e(PARAMS); // illegal
- case 0x3f: return arcompact_handle04_2f_3f(PARAMS); // ZOPs (Zero Operand Opcodes)
- }
-
- return 0;
-}
-
-
-ARCOMPACT_RETTYPE arcompact_device::arcompact_handle05_2f(OPS_32)
-{
- uint8_t subinstr2 = (op & 0x0000003f) >> 0;
-
- switch (subinstr2)
- {
- case 0x00: return arcompact_handle05_2f_00(PARAMS); // SWAP
- case 0x01: return arcompact_handle05_2f_01(PARAMS); // NORM
- case 0x02: return arcompact_handle05_2f_02(PARAMS); // SAT16
- case 0x03: return arcompact_handle05_2f_03(PARAMS); // RND16
- case 0x04: return arcompact_handle05_2f_04(PARAMS); // ABSSW
- case 0x05: return arcompact_handle05_2f_05(PARAMS); // ABSS
- case 0x06: return arcompact_handle05_2f_06(PARAMS); // NEGSW
- case 0x07: return arcompact_handle05_2f_07(PARAMS); // NEGS
- case 0x08: return arcompact_handle05_2f_08(PARAMS); // NORMW
- case 0x09: return arcompact_handle05_2f_09(PARAMS); // illegal
- case 0x0a: return arcompact_handle05_2f_0a(PARAMS); // illegal
- case 0x0b: return arcompact_handle05_2f_0b(PARAMS); // illegal
- case 0x0c: return arcompact_handle05_2f_0c(PARAMS); // illegal
- case 0x0d: return arcompact_handle05_2f_0d(PARAMS); // illegal
- case 0x0e: return arcompact_handle05_2f_0e(PARAMS); // illegal
- case 0x0f: return arcompact_handle05_2f_0f(PARAMS); // illegal
- case 0x10: return arcompact_handle05_2f_10(PARAMS); // illegal
- case 0x11: return arcompact_handle05_2f_11(PARAMS); // illegal
- case 0x12: return arcompact_handle05_2f_12(PARAMS); // illegal
- case 0x13: return arcompact_handle05_2f_13(PARAMS); // illegal
- case 0x14: return arcompact_handle05_2f_14(PARAMS); // illegal
- case 0x15: return arcompact_handle05_2f_15(PARAMS); // illegal
- case 0x16: return arcompact_handle05_2f_16(PARAMS); // illegal
- case 0x17: return arcompact_handle05_2f_17(PARAMS); // illegal
- case 0x18: return arcompact_handle05_2f_18(PARAMS); // illegal
- case 0x19: return arcompact_handle05_2f_19(PARAMS); // illegal
- case 0x1a: return arcompact_handle05_2f_1a(PARAMS); // illegal
- case 0x1b: return arcompact_handle05_2f_1b(PARAMS); // illegal
- case 0x1c: return arcompact_handle05_2f_1c(PARAMS); // illegal
- case 0x1d: return arcompact_handle05_2f_1d(PARAMS); // illegal
- case 0x1e: return arcompact_handle05_2f_1e(PARAMS); // illegal
- case 0x1f: return arcompact_handle05_2f_1f(PARAMS); // illegal
- case 0x20: return arcompact_handle05_2f_20(PARAMS); // illegal
- case 0x21: return arcompact_handle05_2f_21(PARAMS); // illegal
- case 0x22: return arcompact_handle05_2f_22(PARAMS); // illegal
- case 0x23: return arcompact_handle05_2f_23(PARAMS); // illegal
- case 0x24: return arcompact_handle05_2f_24(PARAMS); // illegal
- case 0x25: return arcompact_handle05_2f_25(PARAMS); // illegal
- case 0x26: return arcompact_handle05_2f_26(PARAMS); // illegal
- case 0x27: return arcompact_handle05_2f_27(PARAMS); // illegal
- case 0x28: return arcompact_handle05_2f_28(PARAMS); // illegal
- case 0x29: return arcompact_handle05_2f_29(PARAMS); // illegal
- case 0x2a: return arcompact_handle05_2f_2a(PARAMS); // illegal
- case 0x2b: return arcompact_handle05_2f_2b(PARAMS); // illegal
- case 0x2c: return arcompact_handle05_2f_2c(PARAMS); // illegal
- case 0x2d: return arcompact_handle05_2f_2d(PARAMS); // illegal
- case 0x2e: return arcompact_handle05_2f_2e(PARAMS); // illegal
- case 0x2f: return arcompact_handle05_2f_2f(PARAMS); // illegal
- case 0x30: return arcompact_handle05_2f_30(PARAMS); // illegal
- case 0x31: return arcompact_handle05_2f_31(PARAMS); // illegal
- case 0x32: return arcompact_handle05_2f_32(PARAMS); // illegal
- case 0x33: return arcompact_handle05_2f_33(PARAMS); // illegal
- case 0x34: return arcompact_handle05_2f_34(PARAMS); // illegal
- case 0x35: return arcompact_handle05_2f_35(PARAMS); // illegal
- case 0x36: return arcompact_handle05_2f_36(PARAMS); // illegal
- case 0x37: return arcompact_handle05_2f_37(PARAMS); // illegal
- case 0x38: return arcompact_handle05_2f_38(PARAMS); // illegal
- case 0x39: return arcompact_handle05_2f_39(PARAMS); // illegal
- case 0x3a: return arcompact_handle05_2f_3a(PARAMS); // illegal
- case 0x3b: return arcompact_handle05_2f_3b(PARAMS); // illegal
- case 0x3c: return arcompact_handle05_2f_3c(PARAMS); // illegal
- case 0x3d: return arcompact_handle05_2f_3d(PARAMS); // illegal
- case 0x3e: return arcompact_handle05_2f_3e(PARAMS); // illegal
- case 0x3f: return arcompact_handle05_2f_3f(PARAMS); // ZOPs (Zero Operand Opcodes)
- }
-
- return 0;
-}
-
-ARCOMPACT_RETTYPE arcompact_device::arcompact_handle04_2f_3f(OPS_32)
-{
- uint8_t subinstr3 = (op & 0x07000000) >> 24;
- subinstr3 |= ((op & 0x00007000) >> 12) << 3;
-
- switch (subinstr3)
- {
- case 0x00: return arcompact_handle04_2f_3f_00(PARAMS); // illegal
- case 0x01: return arcompact_handle04_2f_3f_01(PARAMS); // SLEEP
- case 0x02: return arcompact_handle04_2f_3f_02(PARAMS); // SWI / TRAP9
- case 0x03: return arcompact_handle04_2f_3f_03(PARAMS); // SYNC
- case 0x04: return arcompact_handle04_2f_3f_04(PARAMS); // RTIE
- case 0x05: return arcompact_handle04_2f_3f_05(PARAMS); // BRK
- case 0x06: return arcompact_handle04_2f_3f_06(PARAMS); // illegal
- case 0x07: return arcompact_handle04_2f_3f_07(PARAMS); // illegal
- case 0x08: return arcompact_handle04_2f_3f_08(PARAMS); // illegal
- case 0x09: return arcompact_handle04_2f_3f_09(PARAMS); // illegal
- case 0x0a: return arcompact_handle04_2f_3f_0a(PARAMS); // illegal
- case 0x0b: return arcompact_handle04_2f_3f_0b(PARAMS); // illegal
- case 0x0c: return arcompact_handle04_2f_3f_0c(PARAMS); // illegal
- case 0x0d: return arcompact_handle04_2f_3f_0d(PARAMS); // illegal
- case 0x0e: return arcompact_handle04_2f_3f_0e(PARAMS); // illegal
- case 0x0f: return arcompact_handle04_2f_3f_0f(PARAMS); // illegal
- case 0x10: return arcompact_handle04_2f_3f_10(PARAMS); // illegal
- case 0x11: return arcompact_handle04_2f_3f_11(PARAMS); // illegal
- case 0x12: return arcompact_handle04_2f_3f_12(PARAMS); // illegal
- case 0x13: return arcompact_handle04_2f_3f_13(PARAMS); // illegal
- case 0x14: return arcompact_handle04_2f_3f_14(PARAMS); // illegal
- case 0x15: return arcompact_handle04_2f_3f_15(PARAMS); // illegal
- case 0x16: return arcompact_handle04_2f_3f_16(PARAMS); // illegal
- case 0x17: return arcompact_handle04_2f_3f_17(PARAMS); // illegal
- case 0x18: return arcompact_handle04_2f_3f_18(PARAMS); // illegal
- case 0x19: return arcompact_handle04_2f_3f_19(PARAMS); // illegal
- case 0x1a: return arcompact_handle04_2f_3f_1a(PARAMS); // illegal
- case 0x1b: return arcompact_handle04_2f_3f_1b(PARAMS); // illegal
- case 0x1c: return arcompact_handle04_2f_3f_1c(PARAMS); // illegal
- case 0x1d: return arcompact_handle04_2f_3f_1d(PARAMS); // illegal
- case 0x1e: return arcompact_handle04_2f_3f_1e(PARAMS); // illegal
- case 0x1f: return arcompact_handle04_2f_3f_1f(PARAMS); // illegal
- case 0x20: return arcompact_handle04_2f_3f_20(PARAMS); // illegal
- case 0x21: return arcompact_handle04_2f_3f_21(PARAMS); // illegal
- case 0x22: return arcompact_handle04_2f_3f_22(PARAMS); // illegal
- case 0x23: return arcompact_handle04_2f_3f_23(PARAMS); // illegal
- case 0x24: return arcompact_handle04_2f_3f_24(PARAMS); // illegal
- case 0x25: return arcompact_handle04_2f_3f_25(PARAMS); // illegal
- case 0x26: return arcompact_handle04_2f_3f_26(PARAMS); // illegal
- case 0x27: return arcompact_handle04_2f_3f_27(PARAMS); // illegal
- case 0x28: return arcompact_handle04_2f_3f_28(PARAMS); // illegal
- case 0x29: return arcompact_handle04_2f_3f_29(PARAMS); // illegal
- case 0x2a: return arcompact_handle04_2f_3f_2a(PARAMS); // illegal
- case 0x2b: return arcompact_handle04_2f_3f_2b(PARAMS); // illegal
- case 0x2c: return arcompact_handle04_2f_3f_2c(PARAMS); // illegal
- case 0x2d: return arcompact_handle04_2f_3f_2d(PARAMS); // illegal
- case 0x2e: return arcompact_handle04_2f_3f_2e(PARAMS); // illegal
- case 0x2f: return arcompact_handle04_2f_3f_2f(PARAMS); // illegal
- case 0x30: return arcompact_handle04_2f_3f_30(PARAMS); // illegal
- case 0x31: return arcompact_handle04_2f_3f_31(PARAMS); // illegal
- case 0x32: return arcompact_handle04_2f_3f_32(PARAMS); // illegal
- case 0x33: return arcompact_handle04_2f_3f_33(PARAMS); // illegal
- case 0x34: return arcompact_handle04_2f_3f_34(PARAMS); // illegal
- case 0x35: return arcompact_handle04_2f_3f_35(PARAMS); // illegal
- case 0x36: return arcompact_handle04_2f_3f_36(PARAMS); // illegal
- case 0x37: return arcompact_handle04_2f_3f_37(PARAMS); // illegal
- case 0x38: return arcompact_handle04_2f_3f_38(PARAMS); // illegal
- case 0x39: return arcompact_handle04_2f_3f_39(PARAMS); // illegal
- case 0x3a: return arcompact_handle04_2f_3f_3a(PARAMS); // illegal
- case 0x3b: return arcompact_handle04_2f_3f_3b(PARAMS); // illegal
- case 0x3c: return arcompact_handle04_2f_3f_3c(PARAMS); // illegal
- case 0x3d: return arcompact_handle04_2f_3f_3d(PARAMS); // illegal
- case 0x3e: return arcompact_handle04_2f_3f_3e(PARAMS); // illegal
- case 0x3f: return arcompact_handle04_2f_3f_3f(PARAMS); // illegal
- }
-
- return 0;
-}
-
-
-ARCOMPACT_RETTYPE arcompact_device::arcompact_handle05_2f_3f(OPS_32) // useless ZOP group, no actual opcodes
-{
- uint8_t subinstr3 = (op & 0x07000000) >> 24;
- subinstr3 |= ((op & 0x00007000) >> 12) << 3;
-
- switch (subinstr3)
- {
- case 0x00: return arcompact_handle05_2f_3f_00(PARAMS); // illegal
- case 0x01: return arcompact_handle05_2f_3f_01(PARAMS); // illegal
- case 0x02: return arcompact_handle05_2f_3f_02(PARAMS); // illegal
- case 0x03: return arcompact_handle05_2f_3f_03(PARAMS); // illegal
- case 0x04: return arcompact_handle05_2f_3f_04(PARAMS); // illegal
- case 0x05: return arcompact_handle05_2f_3f_05(PARAMS); // illegal
- case 0x06: return arcompact_handle05_2f_3f_06(PARAMS); // illegal
- case 0x07: return arcompact_handle05_2f_3f_07(PARAMS); // illegal
- case 0x08: return arcompact_handle05_2f_3f_08(PARAMS); // illegal
- case 0x09: return arcompact_handle05_2f_3f_09(PARAMS); // illegal
- case 0x0a: return arcompact_handle05_2f_3f_0a(PARAMS); // illegal
- case 0x0b: return arcompact_handle05_2f_3f_0b(PARAMS); // illegal
- case 0x0c: return arcompact_handle05_2f_3f_0c(PARAMS); // illegal
- case 0x0d: return arcompact_handle05_2f_3f_0d(PARAMS); // illegal
- case 0x0e: return arcompact_handle05_2f_3f_0e(PARAMS); // illegal
- case 0x0f: return arcompact_handle05_2f_3f_0f(PARAMS); // illegal
- case 0x10: return arcompact_handle05_2f_3f_10(PARAMS); // illegal
- case 0x11: return arcompact_handle05_2f_3f_11(PARAMS); // illegal
- case 0x12: return arcompact_handle05_2f_3f_12(PARAMS); // illegal
- case 0x13: return arcompact_handle05_2f_3f_13(PARAMS); // illegal
- case 0x14: return arcompact_handle05_2f_3f_14(PARAMS); // illegal
- case 0x15: return arcompact_handle05_2f_3f_15(PARAMS); // illegal
- case 0x16: return arcompact_handle05_2f_3f_16(PARAMS); // illegal
- case 0x17: return arcompact_handle05_2f_3f_17(PARAMS); // illegal
- case 0x18: return arcompact_handle05_2f_3f_18(PARAMS); // illegal
- case 0x19: return arcompact_handle05_2f_3f_19(PARAMS); // illegal
- case 0x1a: return arcompact_handle05_2f_3f_1a(PARAMS); // illegal
- case 0x1b: return arcompact_handle05_2f_3f_1b(PARAMS); // illegal
- case 0x1c: return arcompact_handle05_2f_3f_1c(PARAMS); // illegal
- case 0x1d: return arcompact_handle05_2f_3f_1d(PARAMS); // illegal
- case 0x1e: return arcompact_handle05_2f_3f_1e(PARAMS); // illegal
- case 0x1f: return arcompact_handle05_2f_3f_1f(PARAMS); // illegal
- case 0x20: return arcompact_handle05_2f_3f_20(PARAMS); // illegal
- case 0x21: return arcompact_handle05_2f_3f_21(PARAMS); // illegal
- case 0x22: return arcompact_handle05_2f_3f_22(PARAMS); // illegal
- case 0x23: return arcompact_handle05_2f_3f_23(PARAMS); // illegal
- case 0x24: return arcompact_handle05_2f_3f_24(PARAMS); // illegal
- case 0x25: return arcompact_handle05_2f_3f_25(PARAMS); // illegal
- case 0x26: return arcompact_handle05_2f_3f_26(PARAMS); // illegal
- case 0x27: return arcompact_handle05_2f_3f_27(PARAMS); // illegal
- case 0x28: return arcompact_handle05_2f_3f_28(PARAMS); // illegal
- case 0x29: return arcompact_handle05_2f_3f_29(PARAMS); // illegal
- case 0x2a: return arcompact_handle05_2f_3f_2a(PARAMS); // illegal
- case 0x2b: return arcompact_handle05_2f_3f_2b(PARAMS); // illegal
- case 0x2c: return arcompact_handle05_2f_3f_2c(PARAMS); // illegal
- case 0x2d: return arcompact_handle05_2f_3f_2d(PARAMS); // illegal
- case 0x2e: return arcompact_handle05_2f_3f_2e(PARAMS); // illegal
- case 0x2f: return arcompact_handle05_2f_3f_2f(PARAMS); // illegal
- case 0x30: return arcompact_handle05_2f_3f_30(PARAMS); // illegal
- case 0x31: return arcompact_handle05_2f_3f_31(PARAMS); // illegal
- case 0x32: return arcompact_handle05_2f_3f_32(PARAMS); // illegal
- case 0x33: return arcompact_handle05_2f_3f_33(PARAMS); // illegal
- case 0x34: return arcompact_handle05_2f_3f_34(PARAMS); // illegal
- case 0x35: return arcompact_handle05_2f_3f_35(PARAMS); // illegal
- case 0x36: return arcompact_handle05_2f_3f_36(PARAMS); // illegal
- case 0x37: return arcompact_handle05_2f_3f_37(PARAMS); // illegal
- case 0x38: return arcompact_handle05_2f_3f_38(PARAMS); // illegal
- case 0x39: return arcompact_handle05_2f_3f_39(PARAMS); // illegal
- case 0x3a: return arcompact_handle05_2f_3f_3a(PARAMS); // illegal
- case 0x3b: return arcompact_handle05_2f_3f_3b(PARAMS); // illegal
- case 0x3c: return arcompact_handle05_2f_3f_3c(PARAMS); // illegal
- case 0x3d: return arcompact_handle05_2f_3f_3d(PARAMS); // illegal
- case 0x3e: return arcompact_handle05_2f_3f_3e(PARAMS); // illegal
- case 0x3f: return arcompact_handle05_2f_3f_3f(PARAMS); // illegal
- }
-
- return 0;
-}
-
-
-// this is an Extension ALU group, maybe optional on some CPUs?
-ARCOMPACT_RETTYPE arcompact_device::arcompact_handle05(OPS_32)
-{
- uint8_t subinstr = (op & 0x003f0000) >> 16;
-
- switch (subinstr)
- {
- case 0x00: return arcompact_handle05_00(PARAMS); // ASL
- case 0x01: return arcompact_handle05_01(PARAMS); // LSR
- case 0x02: return arcompact_handle05_02(PARAMS); // ASR
- case 0x03: return arcompact_handle05_03(PARAMS); // ROR
- case 0x04: return arcompact_handle05_04(PARAMS); // MUL64
- case 0x05: return arcompact_handle05_05(PARAMS); // MULU64
- case 0x06: return arcompact_handle05_06(PARAMS); // ADDS
- case 0x07: return arcompact_handle05_07(PARAMS); // SUBS
- case 0x08: return arcompact_handle05_08(PARAMS); // DIVAW
- case 0x09: return arcompact_handle05_09(PARAMS); // illegal
- case 0x0a: return arcompact_handle05_0a(PARAMS); // ASLS
- case 0x0b: return arcompact_handle05_0b(PARAMS); // ASRS
- case 0x0c: return arcompact_handle05_0c(PARAMS); // illegal
- case 0x0d: return arcompact_handle05_0d(PARAMS); // illegal
- case 0x0e: return arcompact_handle05_0e(PARAMS); // illegal
- case 0x0f: return arcompact_handle05_0f(PARAMS); // illegal
- case 0x10: return arcompact_handle05_10(PARAMS); // illegal
- case 0x11: return arcompact_handle05_11(PARAMS); // illegal
- case 0x12: return arcompact_handle05_12(PARAMS); // illegal
- case 0x13: return arcompact_handle05_13(PARAMS); // illegal
- case 0x14: return arcompact_handle05_14(PARAMS); // illegal
- case 0x15: return arcompact_handle05_15(PARAMS); // illegal
- case 0x16: return arcompact_handle05_16(PARAMS); // illegal
- case 0x17: return arcompact_handle05_17(PARAMS); // illegal
- case 0x18: return arcompact_handle05_18(PARAMS); // illegal
- case 0x19: return arcompact_handle05_19(PARAMS); // illegal
- case 0x1a: return arcompact_handle05_1a(PARAMS); // illegal
- case 0x1b: return arcompact_handle05_1b(PARAMS); // illegal
- case 0x1c: return arcompact_handle05_1c(PARAMS); // illegal
- case 0x1d: return arcompact_handle05_1d(PARAMS); // illegal
- case 0x1e: return arcompact_handle05_1e(PARAMS); // illegal
- case 0x1f: return arcompact_handle05_1f(PARAMS); // illegal
- case 0x20: return arcompact_handle05_20(PARAMS); // illegal
- case 0x21: return arcompact_handle05_21(PARAMS); // illegal
- case 0x22: return arcompact_handle05_22(PARAMS); // illegal
- case 0x23: return arcompact_handle05_23(PARAMS); // illegal
- case 0x24: return arcompact_handle05_24(PARAMS); // illegal
- case 0x25: return arcompact_handle05_25(PARAMS); // illegal
- case 0x26: return arcompact_handle05_26(PARAMS); // illegal
- case 0x27: return arcompact_handle05_27(PARAMS); // illegal
- case 0x28: return arcompact_handle05_28(PARAMS); // ADDSDW
- case 0x29: return arcompact_handle05_29(PARAMS); // SUBSDW
- case 0x2a: return arcompact_handle05_2a(PARAMS); // illegal
- case 0x2b: return arcompact_handle05_2b(PARAMS); // illegal
- case 0x2c: return arcompact_handle05_2c(PARAMS); // illegal
- case 0x2d: return arcompact_handle05_2d(PARAMS); // illegal
- case 0x2e: return arcompact_handle05_2e(PARAMS); // illegal
- case 0x2f: return arcompact_handle05_2f(PARAMS); // SOPs
- case 0x30: return arcompact_handle05_30(PARAMS); // illegal
- case 0x31: return arcompact_handle05_31(PARAMS); // illegal
- case 0x32: return arcompact_handle05_32(PARAMS); // illegal
- case 0x33: return arcompact_handle05_33(PARAMS); // illegal
- case 0x34: return arcompact_handle05_34(PARAMS); // illegal
- case 0x35: return arcompact_handle05_35(PARAMS); // illegal
- case 0x36: return arcompact_handle05_36(PARAMS); // illegal
- case 0x37: return arcompact_handle05_37(PARAMS); // illegal
- case 0x38: return arcompact_handle05_38(PARAMS); // illegal
- case 0x39: return arcompact_handle05_39(PARAMS); // illegal
- case 0x3a: return arcompact_handle05_3a(PARAMS); // illegal
- case 0x3b: return arcompact_handle05_3b(PARAMS); // illegal
- case 0x3c: return arcompact_handle05_3c(PARAMS); // illegal
- case 0x3d: return arcompact_handle05_3d(PARAMS); // illegal
- case 0x3e: return arcompact_handle05_3e(PARAMS); // illegal
- case 0x3f: return arcompact_handle05_3f(PARAMS); // illegal
- }
-
- return 0;
-}
-
-ARCOMPACT_RETTYPE arcompact_device::arcompact_handle0c(OPS_16)
-{
- uint8_t subinstr = (op & 0x0018) >> 3;
-
- switch (subinstr)
- {
- case 0x00: return arcompact_handle0c_00(PARAMS); // LD_S
- case 0x01: return arcompact_handle0c_01(PARAMS); // LDB_S
- case 0x02: return arcompact_handle0c_02(PARAMS); // LDW_S
- case 0x03: return arcompact_handle0c_03(PARAMS); // ADD_S
- }
-
- return 0;
-}
-
-ARCOMPACT_RETTYPE arcompact_device::arcompact_handle0d(OPS_16)
-{
- uint8_t subinstr = (op & 0x0018) >> 3;
-
- switch (subinstr)
- {
- case 0x00: return arcompact_handle0d_00(PARAMS); // ADD_S
- case 0x01: return arcompact_handle0d_01(PARAMS); // SUB_S
- case 0x02: return arcompact_handle0d_02(PARAMS); // ASL_S
- case 0x03: return arcompact_handle0d_03(PARAMS); // ASR_S
- }
-
- return 0;
-}
-
-ARCOMPACT_RETTYPE arcompact_device::arcompact_handle0e(OPS_16)
-{
- uint8_t subinstr = (op & 0x0018) >> 3;
-
- switch (subinstr)
- {
- case 0x00: return arcompact_handle0e_00(PARAMS); // ADD_S
- case 0x01: return arcompact_handle0e_01(PARAMS); // MOV_S
- case 0x02: return arcompact_handle0e_02(PARAMS); // CMP_S
- case 0x03: return arcompact_handle0e_03(PARAMS); // MOV_S
- }
-
- return 0;
-}
-
-ARCOMPACT_RETTYPE arcompact_device::arcompact_handle0f(OPS_16)
-{
- uint8_t subinstr = (op & 0x01f) >> 0;
-
- switch (subinstr)
- {
- case 0x00: return arcompact_handle0f_00(PARAMS); // SOPs
- case 0x01: return arcompact_handle0f_01(PARAMS); // 0x01 <illegal>
- case 0x02: return arcompact_handle0f_02(PARAMS); // SUB_S
- case 0x03: return arcompact_handle0f_03(PARAMS); // 0x03 <illegal>
- case 0x04: return arcompact_handle0f_04(PARAMS); // AND_S
- case 0x05: return arcompact_handle0f_05(PARAMS); // OR_S
- case 0x06: return arcompact_handle0f_06(PARAMS); // BIC_S
- case 0x07: return arcompact_handle0f_07(PARAMS); // XOR_S
- case 0x08: return arcompact_handle0f_08(PARAMS); // 0x08 <illegal>
- case 0x09: return arcompact_handle0f_09(PARAMS); // 0x09 <illegal>
- case 0x0a: return arcompact_handle0f_0a(PARAMS); // 0x0a <illegal>
- case 0x0b: return arcompact_handle0f_0b(PARAMS); // TST_S
- case 0x0c: return arcompact_handle0f_0c(PARAMS); // MUL64_S
- case 0x0d: return arcompact_handle0f_0d(PARAMS); // SEXB_S
- case 0x0e: return arcompact_handle0f_0e(PARAMS); // SEXW_S
- case 0x0f: return arcompact_handle0f_0f(PARAMS); // EXTB_S
- case 0x10: return arcompact_handle0f_10(PARAMS); // EXTW_S
- case 0x11: return arcompact_handle0f_11(PARAMS); // ABS_S
- case 0x12: return arcompact_handle0f_12(PARAMS); // NOT_S
- case 0x13: return arcompact_handle0f_13(PARAMS); // NEG_S
- case 0x14: return arcompact_handle0f_14(PARAMS); // ADD1_S
- case 0x15: return arcompact_handle0f_15(PARAMS); // ADD2_S
- case 0x16: return arcompact_handle0f_16(PARAMS); // ADD3_S
- case 0x17: return arcompact_handle0f_17(PARAMS); // 0x17 <illegal>
- case 0x18: return arcompact_handle0f_18(PARAMS); // ASL_S (multiple)
- case 0x19: return arcompact_handle0f_19(PARAMS); // LSR_S (multiple)
- case 0x1a: return arcompact_handle0f_1a(PARAMS); // ASR_S (multiple)
- case 0x1b: return arcompact_handle0f_1b(PARAMS); // ASL_S (single)
- case 0x1c: return arcompact_handle0f_1c(PARAMS); // LSR_S (single)
- case 0x1d: return arcompact_handle0f_1d(PARAMS); // ASR_S (single)
- case 0x1e: return arcompact_handle0f_1e(PARAMS); // TRAP (not a5?)
- case 0x1f: return arcompact_handle0f_1f(PARAMS); // BRK_S ( 0x7fff only? )
-
- }
-
- return 0;
-}
-
-ARCOMPACT_RETTYPE arcompact_device::arcompact_handle0f_00(OPS_16)
-{
- uint8_t subinstr = (op & 0x00e0) >> 5;
-
- switch (subinstr)
- {
- case 0x00: return arcompact_handle0f_00_00(PARAMS); // J_S
- case 0x01: return arcompact_handle0f_00_01(PARAMS); // J_S.D
- case 0x02: return arcompact_handle0f_00_02(PARAMS); // JL_S
- case 0x03: return arcompact_handle0f_00_03(PARAMS); // JL_S.D
- case 0x04: return arcompact_handle0f_00_04(PARAMS); // 0x04 <illegal>
- case 0x05: return arcompact_handle0f_00_05(PARAMS); // 0x05 <illegal>
- case 0x06: return arcompact_handle0f_00_06(PARAMS); // SUB_S.NE
- case 0x07: return arcompact_handle0f_00_07(PARAMS); // ZOPs
-
- }
-
- return 0;
-}
-
-ARCOMPACT_RETTYPE arcompact_device::arcompact_handle0f_00_07(OPS_16)
-{
- uint8_t subinstr3 = (op & 0x0700) >> 8;
-
- switch (subinstr3)
- {
- case 0x00: return arcompact_handle0f_00_07_00(PARAMS); // NOP_S
- case 0x01: return arcompact_handle0f_00_07_01(PARAMS); // UNIMP_S
- case 0x02: return arcompact_handle0f_00_07_02(PARAMS); // 0x02 <illegal>
- case 0x03: return arcompact_handle0f_00_07_03(PARAMS); // 0x03 <illegal>
- case 0x04: return arcompact_handle0f_00_07_04(PARAMS); // JEQ_S [BLINK]
- case 0x05: return arcompact_handle0f_00_07_05(PARAMS); // JNE_S [BLINK]
- case 0x06: return arcompact_handle0f_00_07_06(PARAMS); // J_S [BLINK]
- case 0x07: return arcompact_handle0f_00_07_07(PARAMS); // J_S.D [BLINK]
-
- }
-
- return 0;
-}
-
-ARCOMPACT_RETTYPE arcompact_device::arcompact_handle17(OPS_16)
-{
- uint8_t subinstr = (op & 0x00e0) >> 5;
-
- switch (subinstr)
- {
- case 0x00: return arcompact_handle17_00(PARAMS); // ASL_S
- case 0x01: return arcompact_handle17_01(PARAMS); // LSR_S
- case 0x02: return arcompact_handle17_02(PARAMS); // ASR_S
- case 0x03: return arcompact_handle17_03(PARAMS); // SUB_S
- case 0x04: return arcompact_handle17_04(PARAMS); // BSET_S
- case 0x05: return arcompact_handle17_05(PARAMS); // BCLR_S
- case 0x06: return arcompact_handle17_06(PARAMS); // BMSK_S
- case 0x07: return arcompact_handle17_07(PARAMS); // BTST_S
- }
-
- return 0;
-}
-
-ARCOMPACT_RETTYPE arcompact_device::arcompact_handle18(OPS_16)
-{
- uint8_t subinstr = (op & 0x00e0) >> 5;
-
- switch (subinstr)
- {
- case 0x00: return arcompact_handle18_00(PARAMS); // LD_S (SP)
- case 0x01: return arcompact_handle18_01(PARAMS); // LDB_S (SP)
- case 0x02: return arcompact_handle18_02(PARAMS); // ST_S (SP)
- case 0x03: return arcompact_handle18_03(PARAMS); // STB_S (SP)
- case 0x04: return arcompact_handle18_04(PARAMS); // ADD_S (SP)
- case 0x05: return arcompact_handle18_05(PARAMS); // subtable 18_05
- case 0x06: return arcompact_handle18_06(PARAMS); // subtable 18_06
- case 0x07: return arcompact_handle18_07(PARAMS); // subtable 18_07
- }
-
- return 0;
-}
-
-ARCOMPACT_RETTYPE arcompact_device::arcompact_handle18_05(OPS_16)
-{
- uint8_t subinstr2 = (op & 0x0700) >> 8;
-
- switch (subinstr2)
- {
- case 0x00: return arcompact_handle18_05_00(PARAMS); // ADD_S (SP)
- case 0x01: return arcompact_handle18_05_01(PARAMS); // SUB_S (SP)
- case 0x02: return arcompact_handle18_05_02(PARAMS); // <illegal 0x18_05_02>
- case 0x03: return arcompact_handle18_05_03(PARAMS); // <illegal 0x18_05_03>
- case 0x04: return arcompact_handle18_05_04(PARAMS); // <illegal 0x18_05_04>
- case 0x05: return arcompact_handle18_05_05(PARAMS); // <illegal 0x18_05_05>
- case 0x06: return arcompact_handle18_05_06(PARAMS); // <illegal 0x18_05_06>
- case 0x07: return arcompact_handle18_05_07(PARAMS); // <illegal 0x18_05_07>
- }
-
- return 0;
-}
-
-ARCOMPACT_RETTYPE arcompact_device::arcompact_handle18_06(OPS_16)
-{
- uint8_t subinstr2 = (op & 0x001f) >> 0;
-
- switch (subinstr2)
- {
- case 0x00: return arcompact_handle18_06_00(PARAMS); // <illegal 0x18_06_00>
- case 0x01: return arcompact_handle18_06_01(PARAMS); // POP_S b
- case 0x02: return arcompact_handle18_06_02(PARAMS); // <illegal 0x18_06_02>
- case 0x03: return arcompact_handle18_06_03(PARAMS); // <illegal 0x18_06_03>
- case 0x04: return arcompact_handle18_06_04(PARAMS); // <illegal 0x18_06_04>
- case 0x05: return arcompact_handle18_06_05(PARAMS); // <illegal 0x18_06_05>
- case 0x06: return arcompact_handle18_06_06(PARAMS); // <illegal 0x18_06_06>
- case 0x07: return arcompact_handle18_06_07(PARAMS); // <illegal 0x18_06_07>
- case 0x08: return arcompact_handle18_06_08(PARAMS); // <illegal 0x18_06_08>
- case 0x09: return arcompact_handle18_06_09(PARAMS); // <illegal 0x18_06_09>
- case 0x0a: return arcompact_handle18_06_0a(PARAMS); // <illegal 0x18_06_0a>
- case 0x0b: return arcompact_handle18_06_0b(PARAMS); // <illegal 0x18_06_0b>
- case 0x0c: return arcompact_handle18_06_0c(PARAMS); // <illegal 0x18_06_0c>
- case 0x0d: return arcompact_handle18_06_0d(PARAMS); // <illegal 0x18_06_0d>
- case 0x0e: return arcompact_handle18_06_0e(PARAMS); // <illegal 0x18_06_0e>
- case 0x0f: return arcompact_handle18_06_0f(PARAMS); // <illegal 0x18_06_0f>
- case 0x10: return arcompact_handle18_06_10(PARAMS); // <illegal 0x18_06_10>
- case 0x11: return arcompact_handle18_06_11(PARAMS); // POP_S blink
- case 0x12: return arcompact_handle18_06_12(PARAMS); // <illegal 0x18_06_12>
- case 0x13: return arcompact_handle18_06_13(PARAMS); // <illegal 0x18_06_13>
- case 0x14: return arcompact_handle18_06_14(PARAMS); // <illegal 0x18_06_14>
- case 0x15: return arcompact_handle18_06_15(PARAMS); // <illegal 0x18_06_15>
- case 0x16: return arcompact_handle18_06_16(PARAMS); // <illegal 0x18_06_16>
- case 0x17: return arcompact_handle18_06_17(PARAMS); // <illegal 0x18_06_17>
- case 0x18: return arcompact_handle18_06_18(PARAMS); // <illegal 0x18_06_18>
- case 0x19: return arcompact_handle18_06_19(PARAMS); // <illegal 0x18_06_19>
- case 0x1a: return arcompact_handle18_06_1a(PARAMS); // <illegal 0x18_06_1a>
- case 0x1b: return arcompact_handle18_06_1b(PARAMS); // <illegal 0x18_06_1b>
- case 0x1c: return arcompact_handle18_06_1c(PARAMS); // <illegal 0x18_06_1c>
- case 0x1d: return arcompact_handle18_06_1d(PARAMS); // <illegal 0x18_06_1d>
- case 0x1e: return arcompact_handle18_06_1e(PARAMS); // <illegal 0x18_06_1e>
- case 0x1f: return arcompact_handle18_06_1f(PARAMS); // <illegal 0x18_06_1f>
- }
-
- return 0;
-}
-
-ARCOMPACT_RETTYPE arcompact_device::arcompact_handle18_07(OPS_16)
-{
- uint8_t subinstr2 = (op & 0x001f) >> 0;
-
- switch (subinstr2)
- {
- case 0x00: return arcompact_handle18_07_00(PARAMS); // <illegal 0x18_07_00>
- case 0x01: return arcompact_handle18_07_01(PARAMS); // PUSH_S b
- case 0x02: return arcompact_handle18_07_02(PARAMS); // <illegal 0x18_07_02>
- case 0x03: return arcompact_handle18_07_03(PARAMS); // <illegal 0x18_07_03>
- case 0x04: return arcompact_handle18_07_04(PARAMS); // <illegal 0x18_07_04>
- case 0x05: return arcompact_handle18_07_05(PARAMS); // <illegal 0x18_07_05>
- case 0x06: return arcompact_handle18_07_06(PARAMS); // <illegal 0x18_07_06>
- case 0x07: return arcompact_handle18_07_07(PARAMS); // <illegal 0x18_07_07>
- case 0x08: return arcompact_handle18_07_08(PARAMS); // <illegal 0x18_07_08>
- case 0x09: return arcompact_handle18_07_09(PARAMS); // <illegal 0x18_07_09>
- case 0x0a: return arcompact_handle18_07_0a(PARAMS); // <illegal 0x18_07_0a>
- case 0x0b: return arcompact_handle18_07_0b(PARAMS); // <illegal 0x18_07_0b>
- case 0x0c: return arcompact_handle18_07_0c(PARAMS); // <illegal 0x18_07_0c>
- case 0x0d: return arcompact_handle18_07_0d(PARAMS); // <illegal 0x18_07_0d>
- case 0x0e: return arcompact_handle18_07_0e(PARAMS); // <illegal 0x18_07_0e>
- case 0x0f: return arcompact_handle18_07_0f(PARAMS); // <illegal 0x18_07_0f>
- case 0x10: return arcompact_handle18_07_10(PARAMS); // <illegal 0x18_07_10>
- case 0x11: return arcompact_handle18_07_11(PARAMS); // PUSH_S blink
- case 0x12: return arcompact_handle18_07_12(PARAMS); // <illegal 0x18_07_12>
- case 0x13: return arcompact_handle18_07_13(PARAMS); // <illegal 0x18_07_13>
- case 0x14: return arcompact_handle18_07_14(PARAMS); // <illegal 0x18_07_14>
- case 0x15: return arcompact_handle18_07_15(PARAMS); // <illegal 0x18_07_15>
- case 0x16: return arcompact_handle18_07_16(PARAMS); // <illegal 0x18_07_16>
- case 0x17: return arcompact_handle18_07_17(PARAMS); // <illegal 0x18_07_17>
- case 0x18: return arcompact_handle18_07_18(PARAMS); // <illegal 0x18_07_18>
- case 0x19: return arcompact_handle18_07_19(PARAMS); // <illegal 0x18_07_19>
- case 0x1a: return arcompact_handle18_07_1a(PARAMS); // <illegal 0x18_07_1a>
- case 0x1b: return arcompact_handle18_07_1b(PARAMS); // <illegal 0x18_07_1b>
- case 0x1c: return arcompact_handle18_07_1c(PARAMS); // <illegal 0x18_07_1c>
- case 0x1d: return arcompact_handle18_07_1d(PARAMS); // <illegal 0x18_07_1d>
- case 0x1e: return arcompact_handle18_07_1e(PARAMS); // <illegal 0x18_07_1e>
- case 0x1f: return arcompact_handle18_07_1f(PARAMS); // <illegal 0x18_07_1f>
- }
-
- return 0;
-}
-
-ARCOMPACT_RETTYPE arcompact_device::arcompact_handle19(OPS_16)
-{
- uint8_t subinstr = (op & 0x0600) >> 9;
-
- switch (subinstr)
- {
- case 0x00: return arcompact_handle19_00(PARAMS); // LD_S (GP)
- case 0x01: return arcompact_handle19_01(PARAMS); // LDB_S (GP)
- case 0x02: return arcompact_handle19_02(PARAMS); // LDW_S (GP)
- case 0x03: return arcompact_handle19_03(PARAMS); // ADD_S (GP)
- }
-
- return 0;
-}
-
-ARCOMPACT_RETTYPE arcompact_device::arcompact_handle1c(OPS_16)
-{
- uint8_t subinstr = (op & 0x0080) >> 7;
-
- switch (subinstr)
- {
- case 0x00: return arcompact_handle1c_00(PARAMS); // ADD_S
- case 0x01: return arcompact_handle1c_01(PARAMS); // CMP_S
- }
-
- return 0;
-}
-
-ARCOMPACT_RETTYPE arcompact_device::arcompact_handle1d(OPS_16)
-{
- uint8_t subinstr = (op & 0x0080) >> 7;
-
- switch (subinstr)
- {
- case 0x00: return arcompact_handle1d_00(PARAMS); // BREQ_S
- case 0x01: return arcompact_handle1d_01(PARAMS); // BRNE_S
- }
-
- return 0;
-}
-
-ARCOMPACT_RETTYPE arcompact_device::arcompact_handle1e(OPS_16)
-{
- uint8_t subinstr = (op & 0x0600) >> 9;
-
- switch (subinstr)
- {
- case 0x00: return arcompact_handle1e_00(PARAMS); // B_S
- case 0x01: return arcompact_handle1e_01(PARAMS); // BEQ_S
- case 0x02: return arcompact_handle1e_02(PARAMS); // BNE_S
- case 0x03: return arcompact_handle1e_03(PARAMS); // Bcc_S
- }
-
- return 0;
-}
-
-ARCOMPACT_RETTYPE arcompact_device::arcompact_handle1e_03(OPS_16)
-{
- uint8_t subinstr2 = (op & 0x01c0) >> 6;
-
- switch (subinstr2)
- {
- case 0x00: return arcompact_handle1e_03_00(PARAMS); // BGT_S
- case 0x01: return arcompact_handle1e_03_01(PARAMS); // BGE_S
- case 0x02: return arcompact_handle1e_03_02(PARAMS); // BLT_S
- case 0x03: return arcompact_handle1e_03_03(PARAMS); // BLE_S
- case 0x04: return arcompact_handle1e_03_04(PARAMS); // BHI_S
- case 0x05: return arcompact_handle1e_03_05(PARAMS); // BHS_S
- case 0x06: return arcompact_handle1e_03_06(PARAMS); // BLO_S
- case 0x07: return arcompact_handle1e_03_07(PARAMS); // BLS_S
- }
-
- return 0;
-}
-
-// handlers
-
-uint32_t arcompact_device::handle_jump_to_addr(int delay, int link, uint32_t address, uint32_t next_addr)
-{
- if (delay)
- {
- m_delayactive = 1;
- m_delayjump = address;
- if (link) m_delaylinks = 1;
- else m_delaylinks = 0;
- return next_addr;
- }
- else
- {
- if (link) m_regs[REG_BLINK] = next_addr;
- return address;
- }
-
-}
-
-uint32_t arcompact_device::handle_jump_to_register(int delay, int link, uint32_t reg, uint32_t next_addr, int flag)
-{
- if (reg == LIMM_REG)
- arcompact_fatal("handle_jump_to_register called with LIMM register, call handle_jump_to_addr instead");
-
- if ((reg == REG_ILINK1) || (reg == REG_ILINK2))
- {
- if (flag)
- {
- arcompact_fatal("jump to ILINK1/ILINK2 not supported");
- return next_addr;
- }
- else
- {
- arcompact_fatal("illegal jump to ILINK1/ILINK2 not supported"); // FLAG bit must be set
- return next_addr;
- }
- }
- else
- {
- if (flag)
- {
- arcompact_fatal("illegal jump (flag bit set)"); // FLAG bit must NOT be set
- return next_addr;
- }
- else
- {
- //arcompact_fatal("jump not supported");
- uint32_t target = m_regs[reg];
- return handle_jump_to_addr(delay, link, target, next_addr);
- }
- }
-
- return 0;
-}
-
-ARCOMPACT_RETTYPE arcompact_device::arcompact_handle00_00(OPS_32)
-{
- int size = 4;
-
- COMMON32_GET_CONDITION
-
- if (!check_condition(condition))
- return m_pc + (size>>0);
-
- // Branch Conditionally
- // 0000 0sss ssss sss0 SSSS SSSS SSNQ QQQQ
- int32_t address = (op & 0x07fe0000) >> 17;
- address |= ((op & 0x0000ffc0) >> 6) << 10;
- if (address & 0x80000) address = -0x80000 + (address & 0x7ffff);
- int n = (op & 0x00000020) >> 5; op &= ~0x00000020;
-
- uint32_t realaddress = PC_ALIGNED32 + (address * 2);
-
- if (n)
- {
- m_delayactive = 1;
- m_delayjump = realaddress;
- m_delaylinks = 0; // don't link
- }
- else
- {
- // m_regs[REG_BLINK] = m_pc + (size >> 0); // don't link
- return realaddress;
- }
-
-
- return m_pc + (size>>0);
-}
-
-ARCOMPACT_RETTYPE arcompact_device::arcompact_handle00_01(OPS_32)
-{
- int size = 4;
- // Branch Unconditionally Far
- int32_t address = (op & 0x07fe0000) >> 17;
- address |= ((op & 0x0000ffc0) >> 6) << 10;
- address |= ((op & 0x0000000f) >> 0) << 20;
- if (address & 0x800000) address = -0x800000 + (address & 0x7fffff);
- int n = (op & 0x00000020) >> 5; op &= ~0x00000020;
-// int res = (op & 0x00000010) >> 4; op &= ~0x00000010; // should be set to 0
-
- uint32_t realaddress = PC_ALIGNED32 + (address * 2);
-
- if (n)
- {
- m_delayactive = 1;
- m_delayjump = realaddress;
- m_delaylinks = 0; // don't link
- }
- else
- {
- // m_regs[REG_BLINK] = m_pc + (size >> 0); // don't link
- return realaddress;
- }
-
-
- return m_pc + (size>>0);
-
-}
-
-ARCOMPACT_RETTYPE arcompact_device::arcompact_handle01_00_00dasm(OPS_32)
-{
- int size = 4;
-
- // Branch and Link Conditionally
- arcompact_log("unimplemented BLcc %08x", op);
- return m_pc + (size>>0);
-}
-
-
-
-ARCOMPACT_RETTYPE arcompact_device::arcompact_handle01_00_01dasm(OPS_32)
-{
- int size = 4;
- // Branch and Link Unconditionally Far
- // 00001 sssssssss 10 SSSSSSSSSS N R TTTT
- int32_t address = (op & 0x07fc0000) >> 17;
- address |= ((op & 0x0000ffc0) >> 6) << 10;
- address |= ((op & 0x0000000f) >> 0) << 20;
- if (address & 0x800000) address = -0x800000 + (address&0x7fffff);
- int n = (op & 0x00000020) >> 5; op &= ~0x00000020;
-// int res = (op & 0x00000010) >> 4; op &= ~0x00000010;
-
- uint32_t realaddress = PC_ALIGNED32 + (address * 2);
-
- if (n)
- {
- m_delayactive = 1;
- m_delayjump = realaddress;
- m_delaylinks = 1;
- }
- else
- {
- m_regs[REG_BLINK] = m_pc + (size >> 0);
- return realaddress;
- }
-
-
- return m_pc + (size>>0);
-}
-
-
-
-ARCOMPACT_RETTYPE arcompact_device::arcompact_01_01_00_helper(OPS_32, const char* optext)
-{
- int size;
-
- // Branch on Compare / Bit Test - Register-Register
-
- COMMON32_GET_creg
- COMMON32_GET_breg;
- //int n = (op & 0x00000020) >> 5;
-
-
- if ((breg != LIMM_REG) && (creg != LIMM_REG))
- {
- }
- else
- {
- //uint32_t limm;
- //GET_LIMM_32;
- size = 8;
- }
-
- arcompact_log("unimplemented %s %08x (reg-reg)", optext, op);
- return m_pc + (size>>0);
-}
-
-
-// register - register cases
-
-#define BR_REGREG_SETUP \
- /* Branch on Compare / Bit Test - Register-Register */ \
- int size = 4; \
- GET_01_01_01_BRANCH_ADDR; \
- COMMON32_GET_creg; \
- COMMON32_GET_breg; \
- int n = (op & 0x00000020) >> 5; \
- uint32_t b,c; \
- if ((breg != LIMM_REG) && (creg != LIMM_REG)) \
- { \
- b = m_regs[breg]; \
- c = m_regs[creg]; \
- } \
- else \
- { \
- uint32_t limm; \
- GET_LIMM_32; \
- size = 8; \
- \
- if (breg == LIMM_REG) \
- b = limm; \
- else \
- b = m_regs[breg]; \
- \
- if (creg == LIMM_REG) \
- c = limm; \
- else \
- c = m_regs[creg]; \
- }
-#define BR_TAKEJUMP \
- /* take jump */ \
- uint32_t realaddress = PC_ALIGNED32 + (address * 2); \
- \
- if (n) \
- { \
- m_delayactive = 1; \
- m_delayjump = realaddress; \
- m_delaylinks = 0; \
- } \
- else \
- { \
- return realaddress; \
- }
-
-
-ARCOMPACT_RETTYPE arcompact_device::arcompact_handle01_01_00_00(OPS_32) // register - register BREQ
-{
- BR_REGREG_SETUP
-
- // BREQ
- if (b == c)
- {
- BR_TAKEJUMP
- }
-
- return m_pc + (size>>0);
-}
-
-ARCOMPACT_RETTYPE arcompact_device::arcompact_handle01_01_00_01(OPS_32) // register - register BRNE
-{
- BR_REGREG_SETUP
-
- // BRNE
- if (b != c)
- {
- BR_TAKEJUMP
- }
-
- return m_pc + (size>>0);
-}
-
-ARCOMPACT_RETTYPE arcompact_device::arcompact_handle01_01_00_02(OPS_32) // regiter - register BRLT
-{
- BR_REGREG_SETUP
-
- // BRLT (signed operation)
- if ((int32_t)b < (int32_t)c)
- {
- BR_TAKEJUMP
- }
-
- return m_pc + (size>>0);
-
-}
-ARCOMPACT_RETTYPE arcompact_device::arcompact_handle01_01_00_03(OPS_32) // register - register BRGE
-{
- BR_REGREG_SETUP
-
- // BRGE (signed operation)
- if ((int32_t)b >= (int32_t)c)
- {
- BR_TAKEJUMP
- }
-
- return m_pc + (size>>0);
-}
-
-ARCOMPACT_RETTYPE arcompact_device::arcompact_handle01_01_00_04(OPS_32) // register - register BRLO
-{
- BR_REGREG_SETUP
-
- // BRLO (unsigned operation)
- if (b < c)
- {
- BR_TAKEJUMP
- }
-
- return m_pc + (size>>0);
-}
-
-
-ARCOMPACT_RETTYPE arcompact_device::arcompact_handle01_01_00_05(OPS_32) // register - register BRHS
-{
- BR_REGREG_SETUP
+It is possible this is how the CPU works internally.
- // BRHS (unsigned operation)
- if (b >= c)
- {
- BR_TAKEJUMP
- }
+*/
- return m_pc + (size>>0);
-}
+/*
+Vector | Offset | Default Source | Link Reg | Default Pri | Relative Priority
+--------------------------------------------------------------------------------------------------------
+ 0 | 0x00 | Reset (Special) | (none) | high (always) | H1
+ 1 | 0x08 | Memory Error (Special) | ILINK2 (always) | high (always) | H2
+ 2 | 0x10 | Instruction Error (Special) | ILINK2 (always) | high (always) | H3
+--------------------------------------------------------------------------------------------------------
+ 3 | 0x18 | Timer 0 IRQ | ILINK1 | lv. 1 (low) | L27
+ 4 | 0x20 | XY Memory IRQ | ILINK1 | lv. 1 (low) | L26
+ 5 | 0x28 | UART IRQ | ILINK1 | lv. 1 (low) | L25
+ 6 | 0x30 | EMAC IRQ | ILINK2 | lv. 2 (med) | M2
+ 7 | 0x38 | Timer 1 IRQ | ILINK2 | lv. 2 (med) | M1
+--------------------------------------------------------------------------------------------------------
+ 8 | 0x40 | IRQ8 | ILINK1 | lv. 1 (low) | L24
+ 9 | 0x48 | IRQ9 | ILINK1 | lv. 1 (low) | L23
+....
+ 14 | 0x70 | IRQ14 | ILINK1 | lv. 1 (low) | L18
+ 15 | 0x78 | IRQ15 | ILINK1 | lv. 1 (low) | L17
+--------------------------------------------------------------------------------------------------------
+ 16 | 0x80 | IRQ16 (extended) | ILINK1 | lv. 1 (low) | L16
+ 17 | 0x87 | IRQ17 (extended) | ILINK1 | lv. 1 (low) | L15
+....
+ 16 | 0xf0 | IRQ30 (extended) | ILINK1 | lv. 1 (low) | L2
+ 17 | 0xf8 | IRQ31 (extended) | ILINK1 | lv. 1 (low) | L1
+--------------------------------------------------------------------------------------------------------
-ARCOMPACT_RETTYPE arcompact_device::arcompact_handle01_01_00_0e(OPS_32) { return arcompact_01_01_00_helper( PARAMS, "BBIT0");}
-ARCOMPACT_RETTYPE arcompact_device::arcompact_handle01_01_00_0f(OPS_32) { return arcompact_01_01_00_helper( PARAMS, "BBIT1");}
+*/
-ARCOMPACT_RETTYPE arcompact_device::arcompact_01_01_01_helper(OPS_32, const char* optext)
+// currently causes the Leapster to put an unhandled interrupt exception string in RAM
+// at 0x03000800
+void arcompact_device::check_interrupts()
{
- int size = 4;
- arcompact_log("unimplemented %s %08x (reg-imm)", optext, op);
- return m_pc + (size>>0);
-}
+ int vector = 8;
-#define BR_REGIMM_SETUP \
- int size = 4; \
- GET_01_01_01_BRANCH_ADDR \
- COMMON32_GET_u6; \
- COMMON32_GET_breg; \
- int n = (op & 0x00000020) >> 5; \
- uint32_t b,c; \
- c = u; \
- /* comparing a LIMM to an immediate is pointless, is it a valid encoding? */ \
- if ((breg != LIMM_REG)) \
- { \
- b = m_regs[breg]; \
- } \
- else \
- { \
- uint32_t limm; \
- GET_LIMM_32; \
- size = 8; \
- b = limm; \
- }
-
-// register -immediate cases
-ARCOMPACT_RETTYPE arcompact_device::arcompact_handle01_01_01_00(OPS_32) // BREQ reg-imm
-{
- BR_REGIMM_SETUP
-
- // BREQ
- if (b == c)
+ if (vector < 3)
{
- BR_TAKEJUMP
+ fatalerror("check_interrupts called for vector < 3 (these are special exceptions)");
}
- return m_pc + (size>>0);
-}
-
-ARCOMPACT_RETTYPE arcompact_device::arcompact_handle01_01_01_01(OPS_32) // BRNE reg-imm
-{
- BR_REGIMM_SETUP
-
- // BRNE
- if (b != c)
+ if (m_irq_pending)
{
- BR_TAKEJUMP
- }
-
- return m_pc + (size>>0);
-}
-
-
-
-ARCOMPACT_RETTYPE arcompact_device::arcompact_handle01_01_01_02(OPS_32) // BRLT reg-imm
-{
- BR_REGIMM_SETUP
-
- // BRLT (signed operation)
- if ((int32_t)b < (int32_t)c)
- {
- BR_TAKEJUMP
- }
-
- return m_pc + (size>>0);
-
-}
-ARCOMPACT_RETTYPE arcompact_device::arcompact_handle01_01_01_03(OPS_32)
-{
- BR_REGIMM_SETUP
-
- // BRGE (signed operation)
- if ((int32_t)b >= (int32_t)c)
- {
- BR_TAKEJUMP
- }
-
- return m_pc + (size>>0);
-}
-
-ARCOMPACT_RETTYPE arcompact_device::arcompact_handle01_01_01_04(OPS_32) // register - immediate BRLO
-{
- BR_REGIMM_SETUP
-
- // BRLO (unsigned operation)
- if (b < c)
- {
- BR_TAKEJUMP
- }
-
- return m_pc + (size>>0);
-
-}
-
-ARCOMPACT_RETTYPE arcompact_device::arcompact_handle01_01_01_05(OPS_32) // register - immediate BRHS
-{
- BR_REGIMM_SETUP
-
- // BRHS (unsigned operation)
- if (b >= c)
- {
- BR_TAKEJUMP
- }
-
- return m_pc + (size>>0);
-}
-
-ARCOMPACT_RETTYPE arcompact_device::arcompact_handle01_01_01_0e(OPS_32) { return arcompact_01_01_01_helper(PARAMS, "BBIT0"); }
-ARCOMPACT_RETTYPE arcompact_device::arcompact_handle01_01_01_0f(OPS_32) { return arcompact_01_01_01_helper(PARAMS, "BBIT1"); }
-
-
-ARCOMPACT_RETTYPE arcompact_device::arcompact_handle02(OPS_32)
-{
- int size = 4;
- uint32_t limm;
-
- int S = (op & 0x00008000) >> 15;// op &= ~0x00008000;
- int s = (op & 0x00ff0000) >> 16;// op &= ~0x00ff0000;
- if (S) s = -0x100 + s;
-
- COMMON32_GET_breg;
- COMMON32_GET_areg
-
- int X = (op & 0x00000040) >> 6; //op &= ~0x00000040;
- int Z = (op & 0x00000180) >> 7; //op &= ~0x00000180;
- int a = (op & 0x00000600) >> 9; //op &= ~0x00000600;
-// int D = (op & 0x00000800) >> 11;// op &= ~0x00000800; // we don't use the data cache currently
-
- uint32_t address = m_regs[breg];
-
- if (breg == LIMM_REG)
- {
- GET_LIMM_32;
- size = 8;
-
- address = limm;
- }
-
- // address manipulation
- if ((a == 0) || (a == 1))
- {
- address = address + s;
- }
- else if (a == 2)
- {
- //address = address;
- }
- else if (a == 3)
- {
- if (Z == 0)
- {
- address = address + (s << 2);
- }
- else if (Z == 2)
- {
- address = address + (s << 1);
- }
- else // Z == 1 and Z == 3 are invalid here
+ if (m_status32 & 0x00000002) // & 0x04 = level2, & 0x02 = level1
{
- arcompact_fatal("zz_ illegal LD %08x (data size %d mode %d)", op, Z, a);
- }
- }
-
- uint32_t readdata = 0;
-
- // read data
- if (Z == 0)
- {
- readdata = READ32(address >> 2);
-
- if (X) // sign extend is not supported for long reads
- arcompact_fatal("illegal LD %08x (data size %d mode %d with X)", op, Z, a);
-
- }
- else if (Z == 1)
- {
- readdata = READ8(address >> 0);
-
- if (X) // todo
- arcompact_fatal("illegal LD %08x (data size %d mode %d with X)", op, Z, a);
-
- }
- else if (Z == 2)
- {
- readdata = READ16(address >> 1);
-
- if (X) // todo
- arcompact_fatal("illegal LD %08x (data size %d mode %d with X)", op, Z, a);
-
- }
- else if (Z == 3)
- { // Z == 3 is always illegal
- arcompact_fatal("xx_ illegal LD %08x (data size %d mode %d)", op, Z, a);
- }
-
- m_regs[areg] = readdata;
-
- // writeback / increment
- if ((a == 1) || (a == 2))
- {
- if (breg==LIMM_REG)
- arcompact_fatal("yy_ illegal LD %08x (data size %d mode %d)", op, Z, a); // using the LIMM as the base register and an increment mode is illegal
-
- m_regs[breg] = m_regs[breg] + s;
- }
-
- return m_pc + (size>>0);
-
-}
-
-ARCOMPACT_RETTYPE arcompact_device::arcompact_handle03(OPS_32)
-{
- int size = 4;
- uint32_t limm = 0;
- int got_limm = 0;
- int S = (op & 0x00008000) >> 15;
- int s = (op & 0x00ff0000) >> 16;
- if (S) s = -0x100 + s;
-
- COMMON32_GET_breg;
- COMMON32_GET_creg;
-
-// int R = (op & 0x00000001) >> 0; // bit 0 is reserved
- int Z = (op & 0x00000006) >> 1;
- int a = (op & 0x00000018) >> 3;
-// int D = (op & 0x00000020) >> 5; // we don't use the data cache currently
+ int level = ((m_AUX_IRQ_LEV >> vector) & 1) + 1;
+ logerror("HACK/TEST IRQ\n");
- uint32_t address = m_regs[breg];
-
- if (breg == LIMM_REG)
- {
- GET_LIMM_32;
- size = 8;
- got_limm = 1;
-
- address = limm;
- }
-
- uint32_t writedata = m_regs[creg];
-
- if (creg == LIMM_REG)
- {
- if (!got_limm)
- {
- GET_LIMM_32;
- size = 8;
- }
-
- writedata = limm;
- }
-
- // are LIMM addresses with 's' offset non-0 ('a' mode 0 / 3) legal?
- // not mentioned in docs..
-
- // address manipulation
- if ((a == 0) || (a == 1))
- {
- address = address + s;
- }
- else if (a == 2)
- {
- //address = address;
- }
- else if (a == 3)
- {
- if (Z == 0)
- address = address + (s << 2);
- else if (Z==2)
- address = address + (s << 1);
- else // Z == 1 and Z == 3 are invalid here
- arcompact_fatal("illegal ST %08x (data size %d mode %d)", op, Z, a);
- }
-
- // write data
- if (Z == 0)
- {
- WRITE32(address >> 2, writedata);
- }
- else if (Z == 1)
- {
- WRITE8(address >> 0, writedata);
- }
- else if (Z == 2)
- {
- WRITE16(address >> 1, writedata);
- }
- else if (Z == 3)
- { // Z == 3 is always illegal
- arcompact_fatal("illegal ST %08x (data size %d mode %d)", op, Z, a);
- }
-
- // writeback / increment
- if ((a == 1) || (a == 2))
- {
- if (breg==LIMM_REG)
- arcompact_fatal("illegal ST %08x (data size %d mode %d)", op, Z, a); // using the LIMM as the base register and an increment mode is illegal
-
- m_regs[breg] = m_regs[breg] + s;
- }
-
- return m_pc + (size>>0);
-
-}
-
-
-
-
-
-ARCOMPACT_RETTYPE arcompact_device::arcompact_handle04_helper(OPS_32, const char* optext, int ignore_dst, int b_reserved)
-{
- int size;
- //uint32_t limm = 0;
- int got_limm = 0;
-
- COMMON32_GET_p;
- COMMON32_GET_breg;
-
- if (!b_reserved)
- {
- if (breg == LIMM_REG)
- {
- //GET_LIMM_32;
- size = 8;
- got_limm = 1;
- }
- else
- {
- }
- }
- else
- {
- }
-
-
- if (p == 0)
- {
- COMMON32_GET_creg
-
- if (creg == LIMM_REG)
- {
- if (!got_limm)
+ standard_irq_callback(level, m_pc);
+ if (level == 1)
{
- //GET_LIMM_32;
- size = 8;
+ m_regs[REG_ILINK1] = m_pc;
+ m_status32_l1 = m_status32;
+ m_AUX_IRQ_LV12 |= 0x00000001;
}
- }
- else
- {
- }
- }
- else if (p == 1)
- {
- }
- else if (p == 2)
- {
- }
- else if (p == 3)
- {
- int M = (op & 0x00000020) >> 5;
-
- if (M == 0)
- {
- COMMON32_GET_creg
-
- if (creg == LIMM_REG)
+ else if (level == 2)
{
- if (!got_limm)
- {
- //GET_LIMM_32;
- size = 8;
- }
+ m_regs[REG_ILINK2] = m_pc;
+ m_status32_l2 = m_status32;
+ m_AUX_IRQ_LV12 |= 0x00000002;
}
else
{
+ fatalerror("illegal IRQ level\n");
}
+ set_pc(m_INTVECTORBASE + vector * 8);
+ m_irq_pending = 0;
+ debugreg_clear_ZZ();
}
- else if (M == 1)
- {
- }
-
}
-
- arcompact_log("unimplemented %s %08x (04 type helper)", optext, op);
-
- return m_pc + (size>>0);
}
-
-ARCOMPACT_RETTYPE arcompact_device::arcompact_handle04_00_p00(OPS_32)
+void arcompact_device::execute_run()
{
- int size = 4;
- uint32_t limm = 0;
- int got_limm = 0;
-
- COMMON32_GET_breg;
- COMMON32_GET_F;
- COMMON32_GET_creg;
- COMMON32_GET_areg;
-
- uint32_t c;
- uint32_t b;
-
- if (breg == LIMM_REG)
- {
- GET_LIMM_32;
- size = 8;
- got_limm = 1;
- b = limm;
- }
- else
- {
- b = m_regs[breg];
- }
-
- if (creg == LIMM_REG)
- {
- if (!got_limm)
- {
- GET_LIMM_32;
- size = 8;
- }
- c = limm;
- }
- else
- {
- c = m_regs[creg];
- }
- /* todo: is the limm, limm syntax valid? (it's pointless.) */
- /* todo: if areg = LIMM then there is no result (but since that register can never be read, I guess it doesn't matter if we store it there anyway?) */
- uint32_t result = b + c;
- m_regs[areg] = result;
-
- if (F)
+ while (m_icount > 0)
{
- if (result & 0x80000000) { STATUS32_SET_N; }
- else { STATUS32_CLEAR_N; }
- if (result == 0x00000000) { STATUS32_SET_Z; }
- else { STATUS32_CLEAR_Z; }
- if ((b & 0x80000000) == (c & 0x80000000))
- {
- if ((result & 0x80000000) != (b & 0x80000000))
- {
- STATUS32_SET_V;
- }
- else
- {
- STATUS32_CLEAR_V;
- }
- }
- if (b < c)
+ if (!m_delayactive)
{
- STATUS32_SET_C;
+ check_interrupts();
}
- else
- {
- STATUS32_CLEAR_C;
- }
- }
- return m_pc + (size >> 0);
-}
-
-
-ARCOMPACT_RETTYPE arcompact_device::arcompact_handle04_00_p01(OPS_32)
-{
- int size = 4;
- uint32_t limm = 0;
-/* int got_limm = 0; */
- COMMON32_GET_breg;
- COMMON32_GET_F;
- COMMON32_GET_u6;
- COMMON32_GET_areg;
-
- uint32_t c;
- uint32_t b;
-
- /* is having b as LIMM valid here? LIMM vs. fixed u6 value makes no sense */
- if (breg == LIMM_REG)
- {
- GET_LIMM_32;
- size = 8;
-/* got_limm = 1; */
- b = limm;
- }
- else
- {
- b = m_regs[breg];
- }
-
- c = u;
-
- /* todo: if areg = LIMM then there is no result (but since that register can never be read, I guess it doesn't matter if we store it there anyway?) */
- uint32_t result = b + c;
- m_regs[areg] = result;
-
- if (F)
- {
- if (result & 0x80000000) { STATUS32_SET_N; }
- else { STATUS32_CLEAR_N; }
- if (result == 0x00000000) { STATUS32_SET_Z; }
- else { STATUS32_CLEAR_Z; }
- if ((b & 0x80000000) == (c & 0x80000000))
- {
- if ((result & 0x80000000) != (b & 0x80000000))
- {
- STATUS32_SET_V;
- }
- else
- {
- STATUS32_CLEAR_V;
- }
- }
- if (b < c)
- {
- STATUS32_SET_C;
- }
+ // make sure CPU isn't in 'SLEEP' mode
+ if (debugreg_check_ZZ())
+ debugger_wait_hook();
else
{
- STATUS32_CLEAR_C;
- }
- }
- return m_pc + (size >> 0);
-}
-
-
-ARCOMPACT_RETTYPE arcompact_device::arcompact_handle04_00_p10(OPS_32)
-{
- int size = 4;
- uint32_t limm = 0;
-/* int got_limm = 0; */
-
- COMMON32_GET_breg;
- COMMON32_GET_F;
- COMMON32_GET_s12;
-
- uint32_t c;
- uint32_t b;
-
- /* is having b as LIMM valid here? LIMM vs. fixed u6 value makes no sense */
- if (breg == LIMM_REG)
- {
- GET_LIMM_32;
- size = 8;
-/* got_limm = 1; */
- b = limm;
- }
- else
- {
- b = m_regs[breg];
- }
-
- c = (uint32_t)S;
+ debugger_instruction_hook(m_pc);
- /* todo: if areg = LIMM then there is no result (but since that register can never be read, I guess it doesn't matter if we store it there anyway?) */
- uint32_t result = b + c;
- m_regs[breg] = result;
-
- if (F)
- {
- if (result & 0x80000000) { STATUS32_SET_N; }
- else { STATUS32_CLEAR_N; }
- if (result == 0x00000000) { STATUS32_SET_Z; }
- else { STATUS32_CLEAR_Z; }
- if ((b & 0x80000000) == (c & 0x80000000))
- {
- if ((result & 0x80000000) != (b & 0x80000000))
+ if (m_delayactive)
{
- STATUS32_SET_V;
- }
- else
- {
- STATUS32_CLEAR_V;
- }
- }
- if (b < c)
- {
- STATUS32_SET_C;
- }
- else
- {
- STATUS32_CLEAR_C;
- }
- }
- return m_pc + (size >> 0);
-}
-
-
-ARCOMPACT_RETTYPE arcompact_device::arcompact_handle04_00_p11_m0(OPS_32)
-{
- int size = 4;
- arcompact_fatal("arcompact_handle04_00_p11_m0 (ADD)\n");
- return m_pc + (size >> 0);
-}
-
-
-ARCOMPACT_RETTYPE arcompact_device::arcompact_handle04_00_p11_m1(OPS_32)
-{
- int size = 4;
- uint32_t limm = 0;
-/* int got_limm = 0; */
-
- COMMON32_GET_breg;
- COMMON32_GET_F;
- COMMON32_GET_u6;
- //COMMON32_GET_areg; // areg bits already used as condition code select
-
- uint32_t c;
- uint32_t b;
-
- /* is having b as LIMM valid here? LIMM vs. fixed u6 value makes no sense */
- if (breg == LIMM_REG)
- {
- GET_LIMM_32;
- size = 8;
-/* got_limm = 1; */
- b = limm;
- }
- else
- {
- b = m_regs[breg];
- }
-
- c = u;
+ uint16_t op = READ16((m_pc + 0));
+ set_pc(get_instruction(op));
+ if (m_delaylinks) m_regs[REG_BLINK] = m_pc;
- /* todo: if areg = LIMM then there is no result (but since that register can never be read, I guess it doesn't matter if we store it there anyway?) */
- COMMON32_GET_CONDITION;
- if (!check_condition(condition))
- return m_pc + (size>>0);
+ set_pc(m_delayjump);
- uint32_t result = b + c;
- m_regs[breg] = result;
-
- if (F)
- {
- if (result & 0x80000000) { STATUS32_SET_N; }
- else { STATUS32_CLEAR_N; }
- if (result == 0x00000000) { STATUS32_SET_Z; }
- else { STATUS32_CLEAR_Z; }
- if ((b & 0x80000000) == (c & 0x80000000))
- {
- if ((result & 0x80000000) != (b & 0x80000000))
- {
- STATUS32_SET_V;
+ m_delayactive = false;
+ m_delaylinks = false;
}
else
{
- STATUS32_CLEAR_V;
+ uint16_t op = READ16((m_pc + 0));
+ set_pc(get_instruction(op));
}
- }
- if (b < c)
- {
- STATUS32_SET_C;
- }
- else
- {
- STATUS32_CLEAR_C;
- }
- }
- return m_pc + (size >> 0);
-}
-
-
-ARCOMPACT_RETTYPE arcompact_device::arcompact_handle04_02_p00(OPS_32)
-{
- int size = 4;
- uint32_t limm = 0;
- int got_limm = 0;
-
- COMMON32_GET_breg;
- COMMON32_GET_F;
- COMMON32_GET_creg;
- COMMON32_GET_areg;
-
- uint32_t c;
- uint32_t b;
-
- if (breg == LIMM_REG)
- {
- GET_LIMM_32;
- size = 8;
- got_limm = 1;
- b = limm;
- }
- else
- {
- b = m_regs[breg];
- }
-
- if (creg == LIMM_REG)
- {
- if (!got_limm)
- {
- GET_LIMM_32;
- size = 8;
- }
- c = limm;
- }
- else
- {
- c = m_regs[creg];
- }
- /* todo: is the limm, limm syntax valid? (it's pointless.) */
- /* todo: if areg = LIMM then there is no result (but since that register can never be read, I guess it doesn't matter if we store it there anyway?) */
- uint32_t result = b - c;
- m_regs[areg] = result;
-
- if (F)
- {
- arcompact_fatal("arcompact_handle04_02 (SUB) (F set)\n"); // not yet supported
- }
- return m_pc + (size >> 0);
-}
-
-
-ARCOMPACT_RETTYPE arcompact_device::arcompact_handle04_02_p01(OPS_32)
-{
- int size = 4;
- uint32_t limm = 0;
-/* int got_limm = 0; */
-
- COMMON32_GET_breg;
- COMMON32_GET_F;
- COMMON32_GET_u6;
- COMMON32_GET_areg;
-
- uint32_t c;
- uint32_t b;
-
- /* is having b as LIMM valid here? LIMM vs. fixed u6 value makes no sense */
- if (breg == LIMM_REG)
- {
- GET_LIMM_32;
- size = 8;
-/* got_limm = 1; */
- b = limm;
- }
- else
- {
- b = m_regs[breg];
- }
-
- c = u;
-
- /* todo: if areg = LIMM then there is no result (but since that register can never be read, I guess it doesn't matter if we store it there anyway?) */
- uint32_t result = b - c;
- m_regs[areg] = result;
-
- if (F)
- {
- arcompact_fatal("arcompact_handle04_02 (SUB) (F set)\n"); // not yet supported
- }
- return m_pc + (size >> 0);
-}
-
-
-ARCOMPACT_RETTYPE arcompact_device::arcompact_handle04_02_p10(OPS_32)
-{
- int size = 4;
- uint32_t limm = 0;
-/* int got_limm = 0; */
-
- COMMON32_GET_breg;
- COMMON32_GET_F;
- COMMON32_GET_s12;
-
- uint32_t c;
- uint32_t b;
-
- /* is having b as LIMM valid here? LIMM vs. fixed u6 value makes no sense */
- if (breg == LIMM_REG)
- {
- GET_LIMM_32;
- size = 8;
-/* got_limm = 1; */
- b = limm;
- }
- else
- {
- b = m_regs[breg];
- }
-
- c = (uint32_t)S;
-
- /* todo: if areg = LIMM then there is no result (but since that register can never be read, I guess it doesn't matter if we store it there anyway?) */
- uint32_t result = b - c;
- m_regs[breg] = result;
-
- if (F)
- {
- arcompact_fatal("arcompact_handle04_02 (SUB) (F set)\n"); // not yet supported
- }
- return m_pc + (size >> 0);
-}
-
-
-ARCOMPACT_RETTYPE arcompact_device::arcompact_handle04_02_p11_m0(OPS_32)
-{
- int size = 4;
- arcompact_fatal("arcompact_handle04_02_p11_m0 (SUB)\n");
- return m_pc + (size >> 0);
-}
-
-
-ARCOMPACT_RETTYPE arcompact_device::arcompact_handle04_02_p11_m1(OPS_32)
-{
- int size = 4;
- uint32_t limm = 0;
-/* int got_limm = 0; */
-
- COMMON32_GET_breg;
- COMMON32_GET_F;
- COMMON32_GET_u6;
- //COMMON32_GET_areg; // areg bits already used as condition code select
-
- uint32_t c;
- uint32_t b;
-
- /* is having b as LIMM valid here? LIMM vs. fixed u6 value makes no sense */
- if (breg == LIMM_REG)
- {
- GET_LIMM_32;
- size = 8;
-/* got_limm = 1; */
- b = limm;
- }
- else
- {
- b = m_regs[breg];
- }
-
- c = u;
-
- /* todo: if areg = LIMM then there is no result (but since that register can never be read, I guess it doesn't matter if we store it there anyway?) */
- COMMON32_GET_CONDITION;
- if (!check_condition(condition))
- return m_pc + (size>>0);
-
- uint32_t result = b - c;
- m_regs[breg] = result;
-
- if (F)
- {
- arcompact_fatal("arcompact_handle04_02 (SUB) (F set)\n"); // not yet supported
- }
- return m_pc + (size >> 0);
-}
-
-
-ARCOMPACT_RETTYPE arcompact_device::arcompact_handle04_04_p00(OPS_32)
-{
- int size = 4;
- uint32_t limm = 0;
- int got_limm = 0;
-
- COMMON32_GET_breg;
- COMMON32_GET_F;
- COMMON32_GET_creg;
- COMMON32_GET_areg;
-
- uint32_t c;
- uint32_t b;
-
- if (breg == LIMM_REG)
- {
- GET_LIMM_32;
- size = 8;
- got_limm = 1;
- b = limm;
- }
- else
- {
- b = m_regs[breg];
- }
-
- if (creg == LIMM_REG)
- {
- if (!got_limm)
- {
- GET_LIMM_32;
- size = 8;
- }
- c = limm;
- }
- else
- {
- c = m_regs[creg];
- }
- /* todo: is the limm, limm syntax valid? (it's pointless.) */
- /* todo: if areg = LIMM then there is no result (but since that register can never be read, I guess it doesn't matter if we store it there anyway?) */
- uint32_t result = b & c;
- if (areg != LIMM_REG) { m_regs[areg] = result; }
-
- if (F)
- {
- if (result & 0x80000000) { STATUS32_SET_N; }
- else { STATUS32_CLEAR_N; }
- if (result == 0x00000000) { STATUS32_SET_Z; }
- else { STATUS32_CLEAR_Z; }
- }
- return m_pc + (size >> 0);
-}
-
-
-ARCOMPACT_RETTYPE arcompact_device::arcompact_handle04_04_p01(OPS_32)
-{
- int size = 4;
- uint32_t limm = 0;
-/* int got_limm = 0; */
-
- COMMON32_GET_breg;
- COMMON32_GET_F;
- COMMON32_GET_u6;
- COMMON32_GET_areg;
-
- uint32_t c;
- uint32_t b;
-
- /* is having b as LIMM valid here? LIMM vs. fixed u6 value makes no sense */
- if (breg == LIMM_REG)
- {
- GET_LIMM_32;
- size = 8;
-/* got_limm = 1; */
- b = limm;
- }
- else
- {
- b = m_regs[breg];
- }
-
- c = u;
-
- /* todo: if areg = LIMM then there is no result (but since that register can never be read, I guess it doesn't matter if we store it there anyway?) */
- uint32_t result = b & c;
- if (areg != LIMM_REG) { m_regs[areg] = result; }
-
- if (F)
- {
- if (result & 0x80000000) { STATUS32_SET_N; }
- else { STATUS32_CLEAR_N; }
- if (result == 0x00000000) { STATUS32_SET_Z; }
- else { STATUS32_CLEAR_Z; }
- }
- return m_pc + (size >> 0);
-}
-
-
-ARCOMPACT_RETTYPE arcompact_device::arcompact_handle04_04_p10(OPS_32)
-{
- int size = 4;
- uint32_t limm = 0;
-/* int got_limm = 0; */
-
- COMMON32_GET_breg;
- COMMON32_GET_F;
- COMMON32_GET_s12;
-
- uint32_t c;
- uint32_t b;
-
- /* is having b as LIMM valid here? LIMM vs. fixed u6 value makes no sense */
- if (breg == LIMM_REG)
- {
- GET_LIMM_32;
- size = 8;
-/* got_limm = 1; */
- b = limm;
- }
- else
- {
- b = m_regs[breg];
- }
-
- c = (uint32_t)S;
-
- /* todo: if areg = LIMM then there is no result (but since that register can never be read, I guess it doesn't matter if we store it there anyway?) */
- uint32_t result = b & c;
- if (breg != LIMM_REG) { m_regs[breg] = result; }
-
- if (F)
- {
- if (result & 0x80000000) { STATUS32_SET_N; }
- else { STATUS32_CLEAR_N; }
- if (result == 0x00000000) { STATUS32_SET_Z; }
- else { STATUS32_CLEAR_Z; }
- }
- return m_pc + (size >> 0);
-}
-
-
-ARCOMPACT_RETTYPE arcompact_device::arcompact_handle04_04_p11_m0(OPS_32)
-{
- int size = 4;
- arcompact_fatal("arcompact_handle04_04_p11_m0 (AND)\n");
- return m_pc + (size >> 0);
-}
-
-
-ARCOMPACT_RETTYPE arcompact_device::arcompact_handle04_04_p11_m1(OPS_32)
-{
- int size = 4;
- uint32_t limm = 0;
-/* int got_limm = 0; */
-
- COMMON32_GET_breg;
- COMMON32_GET_F;
- COMMON32_GET_u6;
- //COMMON32_GET_areg; // areg bits already used as condition code select
-
- uint32_t c;
- uint32_t b;
-
- /* is having b as LIMM valid here? LIMM vs. fixed u6 value makes no sense */
- if (breg == LIMM_REG)
- {
- GET_LIMM_32;
- size = 8;
-/* got_limm = 1; */
- b = limm;
- }
- else
- {
- b = m_regs[breg];
- }
-
- c = u;
-
- /* todo: if areg = LIMM then there is no result (but since that register can never be read, I guess it doesn't matter if we store it there anyway?) */
- COMMON32_GET_CONDITION;
- if (!check_condition(condition))
- return m_pc + (size>>0);
-
- uint32_t result = b & c;
- if (breg != LIMM_REG) { m_regs[breg] = result; }
-
- if (F)
- {
- if (result & 0x80000000) { STATUS32_SET_N; }
- else { STATUS32_CLEAR_N; }
- if (result == 0x00000000) { STATUS32_SET_Z; }
- else { STATUS32_CLEAR_Z; }
- }
- return m_pc + (size >> 0);
-}
-
-
-ARCOMPACT_RETTYPE arcompact_device::arcompact_handle04_05_p00(OPS_32)
-{
- int size = 4;
- uint32_t limm = 0;
- int got_limm = 0;
-
- COMMON32_GET_breg;
- COMMON32_GET_F;
- COMMON32_GET_creg;
- COMMON32_GET_areg;
-
- uint32_t c;
- uint32_t b;
-
- if (breg == LIMM_REG)
- {
- GET_LIMM_32;
- size = 8;
- got_limm = 1;
- b = limm;
- }
- else
- {
- b = m_regs[breg];
- }
-
- if (creg == LIMM_REG)
- {
- if (!got_limm)
- {
- GET_LIMM_32;
- size = 8;
- }
- c = limm;
- }
- else
- {
- c = m_regs[creg];
- }
- /* todo: is the limm, limm syntax valid? (it's pointless.) */
- /* todo: if areg = LIMM then there is no result (but since that register can never be read, I guess it doesn't matter if we store it there anyway?) */
- uint32_t result = b | c;
- m_regs[areg] = result;
-
- if (F)
- {
- arcompact_fatal("arcompact_handle04_05 (OR) (F set)\n"); // not yet supported
- }
- return m_pc + (size >> 0);
-}
-
-
-ARCOMPACT_RETTYPE arcompact_device::arcompact_handle04_05_p01(OPS_32)
-{
- int size = 4;
- uint32_t limm = 0;
-/* int got_limm = 0; */
-
- COMMON32_GET_breg;
- COMMON32_GET_F;
- COMMON32_GET_u6;
- COMMON32_GET_areg;
-
- uint32_t c;
- uint32_t b;
-
- /* is having b as LIMM valid here? LIMM vs. fixed u6 value makes no sense */
- if (breg == LIMM_REG)
- {
- GET_LIMM_32;
- size = 8;
-/* got_limm = 1; */
- b = limm;
- }
- else
- {
- b = m_regs[breg];
- }
-
- c = u;
-
- /* todo: if areg = LIMM then there is no result (but since that register can never be read, I guess it doesn't matter if we store it there anyway?) */
- uint32_t result = b | c;
- m_regs[areg] = result;
-
- if (F)
- {
- arcompact_fatal("arcompact_handle04_05 (OR) (F set)\n"); // not yet supported
- }
- return m_pc + (size >> 0);
-}
-
-
-ARCOMPACT_RETTYPE arcompact_device::arcompact_handle04_05_p10(OPS_32)
-{
- int size = 4;
- uint32_t limm = 0;
-/* int got_limm = 0; */
-
- COMMON32_GET_breg;
- COMMON32_GET_F;
- COMMON32_GET_s12;
-
- uint32_t c;
- uint32_t b;
-
- /* is having b as LIMM valid here? LIMM vs. fixed u6 value makes no sense */
- if (breg == LIMM_REG)
- {
- GET_LIMM_32;
- size = 8;
-/* got_limm = 1; */
- b = limm;
- }
- else
- {
- b = m_regs[breg];
- }
-
- c = (uint32_t)S;
-
- /* todo: if areg = LIMM then there is no result (but since that register can never be read, I guess it doesn't matter if we store it there anyway?) */
- uint32_t result = b | c;
- m_regs[breg] = result;
-
- if (F)
- {
- arcompact_fatal("arcompact_handle04_05 (OR) (F set)\n"); // not yet supported
- }
- return m_pc + (size >> 0);
-}
-
-
-ARCOMPACT_RETTYPE arcompact_device::arcompact_handle04_05_p11_m0(OPS_32)
-{
- int size = 4;
- arcompact_fatal("arcompact_handle04_05_p11_m0 (OR)\n");
- return m_pc + (size >> 0);
-}
-
-
-ARCOMPACT_RETTYPE arcompact_device::arcompact_handle04_05_p11_m1(OPS_32)
-{
- int size = 4;
- uint32_t limm = 0;
-/* int got_limm = 0; */
-
- COMMON32_GET_breg;
- COMMON32_GET_F;
- COMMON32_GET_u6;
- //COMMON32_GET_areg; // areg bits already used as condition code select
-
- uint32_t c;
- uint32_t b;
-
- /* is having b as LIMM valid here? LIMM vs. fixed u6 value makes no sense */
- if (breg == LIMM_REG)
- {
- GET_LIMM_32;
- size = 8;
-/* got_limm = 1; */
- b = limm;
- }
- else
- {
- b = m_regs[breg];
- }
-
- c = u;
-
- /* todo: if areg = LIMM then there is no result (but since that register can never be read, I guess it doesn't matter if we store it there anyway?) */
- COMMON32_GET_CONDITION;
- if (!check_condition(condition))
- return m_pc + (size>>0);
-
- uint32_t result = b | c;
- m_regs[breg] = result;
-
- if (F)
- {
- arcompact_fatal("arcompact_handle04_05 (OR) (F set)\n"); // not yet supported
- }
- return m_pc + (size >> 0);
-}
-
-
-ARCOMPACT_RETTYPE arcompact_device::arcompact_handle04_06_p00(OPS_32)
-{
- int size = 4;
- uint32_t limm = 0;
- int got_limm = 0;
-
- COMMON32_GET_breg;
- COMMON32_GET_F;
- COMMON32_GET_creg;
- COMMON32_GET_areg;
-
- uint32_t c;
- uint32_t b;
-
- if (breg == LIMM_REG)
- {
- GET_LIMM_32;
- size = 8;
- got_limm = 1;
- b = limm;
- }
- else
- {
- b = m_regs[breg];
- }
-
- if (creg == LIMM_REG)
- {
- if (!got_limm)
- {
- GET_LIMM_32;
- size = 8;
- }
- c = limm;
- }
- else
- {
- c = m_regs[creg];
- }
- /* todo: is the limm, limm syntax valid? (it's pointless.) */
- /* todo: if areg = LIMM then there is no result (but since that register can never be read, I guess it doesn't matter if we store it there anyway?) */
- uint32_t result = b & (~c);
- m_regs[areg] = result;
-
- if (F)
- {
- arcompact_fatal("arcompact_handle04_06 (BIC) (F set)\n"); // not yet supported
- }
- return m_pc + (size >> 0);
-}
-
-
-ARCOMPACT_RETTYPE arcompact_device::arcompact_handle04_06_p01(OPS_32)
-{
- int size = 4;
- uint32_t limm = 0;
-/* int got_limm = 0; */
-
- COMMON32_GET_breg;
- COMMON32_GET_F;
- COMMON32_GET_u6;
- COMMON32_GET_areg;
-
- uint32_t c;
- uint32_t b;
-
- /* is having b as LIMM valid here? LIMM vs. fixed u6 value makes no sense */
- if (breg == LIMM_REG)
- {
- GET_LIMM_32;
- size = 8;
-/* got_limm = 1; */
- b = limm;
- }
- else
- {
- b = m_regs[breg];
- }
-
- c = u;
-
- /* todo: if areg = LIMM then there is no result (but since that register can never be read, I guess it doesn't matter if we store it there anyway?) */
- uint32_t result = b & (~c);
- m_regs[areg] = result;
-
- if (F)
- {
- arcompact_fatal("arcompact_handle04_06 (BIC) (F set)\n"); // not yet supported
- }
- return m_pc + (size >> 0);
-}
-
-
-ARCOMPACT_RETTYPE arcompact_device::arcompact_handle04_06_p10(OPS_32)
-{
- int size = 4;
- uint32_t limm = 0;
-/* int got_limm = 0; */
-
- COMMON32_GET_breg;
- COMMON32_GET_F;
- COMMON32_GET_s12;
-
- uint32_t c;
- uint32_t b;
-
- /* is having b as LIMM valid here? LIMM vs. fixed u6 value makes no sense */
- if (breg == LIMM_REG)
- {
- GET_LIMM_32;
- size = 8;
-/* got_limm = 1; */
- b = limm;
- }
- else
- {
- b = m_regs[breg];
- }
-
- c = (uint32_t)S;
-
- /* todo: if areg = LIMM then there is no result (but since that register can never be read, I guess it doesn't matter if we store it there anyway?) */
- uint32_t result = b & (~c);
- m_regs[breg] = result;
-
- if (F)
- {
- arcompact_fatal("arcompact_handle04_06 (BIC) (F set)\n"); // not yet supported
- }
- return m_pc + (size >> 0);
-}
-
-
-ARCOMPACT_RETTYPE arcompact_device::arcompact_handle04_06_p11_m0(OPS_32)
-{
- int size = 4;
- arcompact_fatal("arcompact_handle04_06_p11_m0 (BIC)\n");
- return m_pc + (size >> 0);
-}
-
-
-ARCOMPACT_RETTYPE arcompact_device::arcompact_handle04_06_p11_m1(OPS_32)
-{
- int size = 4;
- uint32_t limm = 0;
-/* int got_limm = 0; */
-
- COMMON32_GET_breg;
- COMMON32_GET_F;
- COMMON32_GET_u6;
- //COMMON32_GET_areg; // areg bits already used as condition code select
-
- uint32_t c;
- uint32_t b;
-
- /* is having b as LIMM valid here? LIMM vs. fixed u6 value makes no sense */
- if (breg == LIMM_REG)
- {
- GET_LIMM_32;
- size = 8;
-/* got_limm = 1; */
- b = limm;
- }
- else
- {
- b = m_regs[breg];
- }
-
- c = u;
-
- /* todo: if areg = LIMM then there is no result (but since that register can never be read, I guess it doesn't matter if we store it there anyway?) */
- COMMON32_GET_CONDITION;
- if (!check_condition(condition))
- return m_pc + (size>>0);
-
- uint32_t result = b & (~c);
- m_regs[breg] = result;
-
- if (F)
- {
- arcompact_fatal("arcompact_handle04_06 (BIC) (F set)\n"); // not yet supported
- }
- return m_pc + (size >> 0);
-}
-
-
-ARCOMPACT_RETTYPE arcompact_device::arcompact_handle04_07_p00(OPS_32)
-{
- int size = 4;
- uint32_t limm = 0;
- int got_limm = 0;
-
- COMMON32_GET_breg;
- COMMON32_GET_F;
- COMMON32_GET_creg;
- COMMON32_GET_areg;
-
- uint32_t c;
- uint32_t b;
-
- if (breg == LIMM_REG)
- {
- GET_LIMM_32;
- size = 8;
- got_limm = 1;
- b = limm;
- }
- else
- {
- b = m_regs[breg];
- }
-
- if (creg == LIMM_REG)
- {
- if (!got_limm)
- {
- GET_LIMM_32;
- size = 8;
- }
- c = limm;
- }
- else
- {
- c = m_regs[creg];
- }
- /* todo: is the limm, limm syntax valid? (it's pointless.) */
- /* todo: if areg = LIMM then there is no result (but since that register can never be read, I guess it doesn't matter if we store it there anyway?) */
- uint32_t result = b ^ c;
- m_regs[areg] = result;
-
- if (F)
- {
- arcompact_fatal("arcompact_handle04_07 (XOR) (F set)\n"); // not yet supported
- }
- return m_pc + (size >> 0);
-}
-
-
-ARCOMPACT_RETTYPE arcompact_device::arcompact_handle04_07_p01(OPS_32)
-{
- int size = 4;
- uint32_t limm = 0;
-/* int got_limm = 0; */
-
- COMMON32_GET_breg;
- COMMON32_GET_F;
- COMMON32_GET_u6;
- COMMON32_GET_areg;
-
- uint32_t c;
- uint32_t b;
-
- /* is having b as LIMM valid here? LIMM vs. fixed u6 value makes no sense */
- if (breg == LIMM_REG)
- {
- GET_LIMM_32;
- size = 8;
-/* got_limm = 1; */
- b = limm;
- }
- else
- {
- b = m_regs[breg];
- }
-
- c = u;
-
- /* todo: if areg = LIMM then there is no result (but since that register can never be read, I guess it doesn't matter if we store it there anyway?) */
- uint32_t result = b ^ c;
- m_regs[areg] = result;
-
- if (F)
- {
- arcompact_fatal("arcompact_handle04_07 (XOR) (F set)\n"); // not yet supported
- }
- return m_pc + (size >> 0);
-}
-
-
-ARCOMPACT_RETTYPE arcompact_device::arcompact_handle04_07_p10(OPS_32)
-{
- int size = 4;
- uint32_t limm = 0;
-/* int got_limm = 0; */
-
- COMMON32_GET_breg;
- COMMON32_GET_F;
- COMMON32_GET_s12;
-
- uint32_t c;
- uint32_t b;
-
- /* is having b as LIMM valid here? LIMM vs. fixed u6 value makes no sense */
- if (breg == LIMM_REG)
- {
- GET_LIMM_32;
- size = 8;
-/* got_limm = 1; */
- b = limm;
- }
- else
- {
- b = m_regs[breg];
- }
-
- c = (uint32_t)S;
-
- /* todo: if areg = LIMM then there is no result (but since that register can never be read, I guess it doesn't matter if we store it there anyway?) */
- uint32_t result = b ^ c;
- m_regs[breg] = result;
-
- if (F)
- {
- arcompact_fatal("arcompact_handle04_07 (XOR) (F set)\n"); // not yet supported
- }
- return m_pc + (size >> 0);
-}
-
-
-ARCOMPACT_RETTYPE arcompact_device::arcompact_handle04_07_p11_m0(OPS_32)
-{
- int size = 4;
- arcompact_fatal("arcompact_handle04_07_p11_m0 (XOR)\n");
- return m_pc + (size >> 0);
-}
-
-
-ARCOMPACT_RETTYPE arcompact_device::arcompact_handle04_07_p11_m1(OPS_32)
-{
- int size = 4;
- uint32_t limm = 0;
-/* int got_limm = 0; */
-
- COMMON32_GET_breg;
- COMMON32_GET_F;
- COMMON32_GET_u6;
- //COMMON32_GET_areg; // areg bits already used as condition code select
-
- uint32_t c;
- uint32_t b;
-
- /* is having b as LIMM valid here? LIMM vs. fixed u6 value makes no sense */
- if (breg == LIMM_REG)
- {
- GET_LIMM_32;
- size = 8;
-/* got_limm = 1; */
- b = limm;
- }
- else
- {
- b = m_regs[breg];
- }
-
- c = u;
-
- /* todo: if areg = LIMM then there is no result (but since that register can never be read, I guess it doesn't matter if we store it there anyway?) */
- COMMON32_GET_CONDITION;
- if (!check_condition(condition))
- return m_pc + (size>>0);
-
- uint32_t result = b ^ c;
- m_regs[breg] = result;
-
- if (F)
- {
- arcompact_fatal("arcompact_handle04_07 (XOR) (F set)\n"); // not yet supported
- }
- return m_pc + (size >> 0);
-}
-
-
-ARCOMPACT_RETTYPE arcompact_device::arcompact_handle04_0a_p00(OPS_32)
-{
- int size = 4;
- uint32_t limm = 0;
- int got_limm = 0;
-
- COMMON32_GET_breg;
- COMMON32_GET_F;
- COMMON32_GET_creg;
- //COMMON32_GET_areg; // areg is reserved / not used
-
- uint32_t c;
-
- if (creg == LIMM_REG)
- {
- if (!got_limm)
- {
- GET_LIMM_32;
- size = 8;
- }
- c = limm;
- }
- else
- {
- c = m_regs[creg];
- }
- /* todo: is the limm, limm syntax valid? (it's pointless.) */
- /* todo: if areg = LIMM then there is no result (but since that register can never be read, I guess it doesn't matter if we store it there anyway?) */
- uint32_t result = c;
- m_regs[breg] = result;
-
- if (F)
- {
- if (result & 0x80000000) { STATUS32_SET_N; }
- else { STATUS32_CLEAR_N; }
- if (result == 0x00000000) { STATUS32_SET_Z; }
- else { STATUS32_CLEAR_Z; }
- }
- return m_pc + (size >> 0);
-}
-
-
-ARCOMPACT_RETTYPE arcompact_device::arcompact_handle04_0a_p01(OPS_32)
-{
- int size = 4;
-/* int got_limm = 0; */
-
- COMMON32_GET_breg;
- COMMON32_GET_F;
- COMMON32_GET_u6;
- //COMMON32_GET_areg; // areg is reserved / not used
-
- uint32_t c;
-
- c = u;
-
- /* todo: if areg = LIMM then there is no result (but since that register can never be read, I guess it doesn't matter if we store it there anyway?) */
- uint32_t result = c;
- m_regs[breg] = result;
-
- if (F)
- {
- if (result & 0x80000000) { STATUS32_SET_N; }
- else { STATUS32_CLEAR_N; }
- if (result == 0x00000000) { STATUS32_SET_Z; }
- else { STATUS32_CLEAR_Z; }
- }
- return m_pc + (size >> 0);
-}
-
-
-ARCOMPACT_RETTYPE arcompact_device::arcompact_handle04_0a_p10(OPS_32)
-{
- int size = 4;
-/* int got_limm = 0; */
-
- COMMON32_GET_breg;
- COMMON32_GET_F;
- COMMON32_GET_s12;
-
- uint32_t c;
-
- c = (uint32_t)S;
-
- /* todo: if areg = LIMM then there is no result (but since that register can never be read, I guess it doesn't matter if we store it there anyway?) */
- uint32_t result = c;
- m_regs[breg] = result;
-
- if (F)
- {
- if (result & 0x80000000) { STATUS32_SET_N; }
- else { STATUS32_CLEAR_N; }
- if (result == 0x00000000) { STATUS32_SET_Z; }
- else { STATUS32_CLEAR_Z; }
- }
- return m_pc + (size >> 0);
-}
-
-
-ARCOMPACT_RETTYPE arcompact_device::arcompact_handle04_0a_p11_m0(OPS_32)
-{
- int size = 4;
- arcompact_fatal("arcompact_handle04_0a_p11_m0 (MOV)\n");
- return m_pc + (size >> 0);
-}
-
-
-ARCOMPACT_RETTYPE arcompact_device::arcompact_handle04_0a_p11_m1(OPS_32)
-{
- int size = 4;
-/* int got_limm = 0; */
-
- COMMON32_GET_breg;
- COMMON32_GET_F;
- COMMON32_GET_u6;
- //COMMON32_GET_areg; // areg bits already used as condition code select
-
- uint32_t c;
-
- c = u;
-
- /* todo: if areg = LIMM then there is no result (but since that register can never be read, I guess it doesn't matter if we store it there anyway?) */
- COMMON32_GET_CONDITION;
- if (!check_condition(condition))
- return m_pc + (size>>0);
-
- uint32_t result = c;
- m_regs[breg] = result;
-
- if (F)
- {
- if (result & 0x80000000) { STATUS32_SET_N; }
- else { STATUS32_CLEAR_N; }
- if (result == 0x00000000) { STATUS32_SET_Z; }
- else { STATUS32_CLEAR_Z; }
- }
- return m_pc + (size >> 0);
-}
-
-
-ARCOMPACT_RETTYPE arcompact_device::arcompact_handle04_0e_p00(OPS_32)
-{
- int size = 4;
- uint32_t limm = 0;
- int got_limm = 0;
-
- COMMON32_GET_breg;
- COMMON32_GET_F;
- COMMON32_GET_creg;
- COMMON32_GET_areg;
-
- uint32_t c;
- uint32_t b;
-
- if (breg == LIMM_REG)
- {
- GET_LIMM_32;
- size = 8;
- got_limm = 1;
- b = limm;
- }
- else
- {
- b = m_regs[breg];
- }
-
- if (creg == LIMM_REG)
- {
- if (!got_limm)
- {
- GET_LIMM_32;
- size = 8;
- }
- c = limm;
- }
- else
- {
- c = m_regs[creg];
- }
- /* todo: is the limm, limm syntax valid? (it's pointless.) */
- /* todo: if areg = LIMM then there is no result (but since that register can never be read, I guess it doesn't matter if we store it there anyway?) */
- uint32_t result = c - b;
- m_regs[areg] = result;
-
- if (F)
- {
- arcompact_fatal("arcompact_handle04_0e (RSUB) (F set)\n"); // not yet supported
- }
- return m_pc + (size >> 0);
-}
-
-
-ARCOMPACT_RETTYPE arcompact_device::arcompact_handle04_0e_p01(OPS_32)
-{
- int size = 4;
- uint32_t limm = 0;
-/* int got_limm = 0; */
-
- COMMON32_GET_breg;
- COMMON32_GET_F;
- COMMON32_GET_u6;
- COMMON32_GET_areg;
-
- uint32_t c;
- uint32_t b;
-
- /* is having b as LIMM valid here? LIMM vs. fixed u6 value makes no sense */
- if (breg == LIMM_REG)
- {
- GET_LIMM_32;
- size = 8;
-/* got_limm = 1; */
- b = limm;
- }
- else
- {
- b = m_regs[breg];
- }
-
- c = u;
-
- /* todo: if areg = LIMM then there is no result (but since that register can never be read, I guess it doesn't matter if we store it there anyway?) */
- uint32_t result = c - b;
- m_regs[areg] = result;
-
- if (F)
- {
- arcompact_fatal("arcompact_handle04_0e (RSUB) (F set)\n"); // not yet supported
- }
- return m_pc + (size >> 0);
-}
-
-
-ARCOMPACT_RETTYPE arcompact_device::arcompact_handle04_0e_p10(OPS_32)
-{
- int size = 4;
- uint32_t limm = 0;
-/* int got_limm = 0; */
-
- COMMON32_GET_breg;
- COMMON32_GET_F;
- COMMON32_GET_s12;
-
- uint32_t c;
- uint32_t b;
-
- /* is having b as LIMM valid here? LIMM vs. fixed u6 value makes no sense */
- if (breg == LIMM_REG)
- {
- GET_LIMM_32;
- size = 8;
-/* got_limm = 1; */
- b = limm;
- }
- else
- {
- b = m_regs[breg];
- }
-
- c = (uint32_t)S;
-
- /* todo: if areg = LIMM then there is no result (but since that register can never be read, I guess it doesn't matter if we store it there anyway?) */
- uint32_t result = c - b;
- m_regs[breg] = result;
-
- if (F)
- {
- arcompact_fatal("arcompact_handle04_0e (RSUB) (F set)\n"); // not yet supported
- }
- return m_pc + (size >> 0);
-}
-
-
-ARCOMPACT_RETTYPE arcompact_device::arcompact_handle04_0e_p11_m0(OPS_32)
-{
- int size = 4;
- arcompact_fatal("arcompact_handle04_0e_p11_m0 (RSUB)\n");
- return m_pc + (size >> 0);
-}
-
-
-ARCOMPACT_RETTYPE arcompact_device::arcompact_handle04_0e_p11_m1(OPS_32)
-{
- int size = 4;
- uint32_t limm = 0;
-/* int got_limm = 0; */
-
- COMMON32_GET_breg;
- COMMON32_GET_F;
- COMMON32_GET_u6;
- //COMMON32_GET_areg; // areg bits already used as condition code select
-
- uint32_t c;
- uint32_t b;
-
- /* is having b as LIMM valid here? LIMM vs. fixed u6 value makes no sense */
- if (breg == LIMM_REG)
- {
- GET_LIMM_32;
- size = 8;
-/* got_limm = 1; */
- b = limm;
- }
- else
- {
- b = m_regs[breg];
- }
-
- c = u;
-
- /* todo: if areg = LIMM then there is no result (but since that register can never be read, I guess it doesn't matter if we store it there anyway?) */
- COMMON32_GET_CONDITION;
- if (!check_condition(condition))
- return m_pc + (size>>0);
-
- uint32_t result = c - b;
- m_regs[breg] = result;
-
- if (F)
- {
- arcompact_fatal("arcompact_handle04_0e (RSUB) (F set)\n"); // not yet supported
- }
- return m_pc + (size >> 0);
-}
-
-
-ARCOMPACT_RETTYPE arcompact_device::arcompact_handle04_0f_p00(OPS_32)
-{
- int size = 4;
- uint32_t limm = 0;
- int got_limm = 0;
-
- COMMON32_GET_breg;
- COMMON32_GET_F;
- COMMON32_GET_creg;
- COMMON32_GET_areg;
-
- uint32_t c;
- uint32_t b;
-
- if (breg == LIMM_REG)
- {
- GET_LIMM_32;
- size = 8;
- got_limm = 1;
- b = limm;
- }
- else
- {
- b = m_regs[breg];
- }
-
- if (creg == LIMM_REG)
- {
- if (!got_limm)
- {
- GET_LIMM_32;
- size = 8;
- }
- c = limm;
- }
- else
- {
- c = m_regs[creg];
- }
- /* todo: is the limm, limm syntax valid? (it's pointless.) */
- /* todo: if areg = LIMM then there is no result (but since that register can never be read, I guess it doesn't matter if we store it there anyway?) */
- uint32_t result = b | (1 << (c & 0x1f));
- m_regs[areg] = result;
-
- if (F)
- {
- arcompact_fatal("arcompact_handle04_0f (BSET) (F set)\n"); // not yet supported
- }
- return m_pc + (size >> 0);
-}
-
-
-ARCOMPACT_RETTYPE arcompact_device::arcompact_handle04_0f_p01(OPS_32)
-{
- int size = 4;
- uint32_t limm = 0;
-/* int got_limm = 0; */
-
- COMMON32_GET_breg;
- COMMON32_GET_F;
- COMMON32_GET_u6;
- COMMON32_GET_areg;
-
- uint32_t c;
- uint32_t b;
-
- /* is having b as LIMM valid here? LIMM vs. fixed u6 value makes no sense */
- if (breg == LIMM_REG)
- {
- GET_LIMM_32;
- size = 8;
-/* got_limm = 1; */
- b = limm;
- }
- else
- {
- b = m_regs[breg];
- }
-
- c = u;
-
- /* todo: if areg = LIMM then there is no result (but since that register can never be read, I guess it doesn't matter if we store it there anyway?) */
- uint32_t result = b | (1 << (c & 0x1f));
- m_regs[areg] = result;
-
- if (F)
- {
- arcompact_fatal("arcompact_handle04_0f (BSET) (F set)\n"); // not yet supported
- }
- return m_pc + (size >> 0);
-}
-
-
-ARCOMPACT_RETTYPE arcompact_device::arcompact_handle04_0f_p10(OPS_32)
-{
- int size = 4;
- uint32_t limm = 0;
-/* int got_limm = 0; */
-
- COMMON32_GET_breg;
- COMMON32_GET_F;
- COMMON32_GET_s12;
-
- uint32_t c;
- uint32_t b;
-
- /* is having b as LIMM valid here? LIMM vs. fixed u6 value makes no sense */
- if (breg == LIMM_REG)
- {
- GET_LIMM_32;
- size = 8;
-/* got_limm = 1; */
- b = limm;
- }
- else
- {
- b = m_regs[breg];
- }
-
- c = (uint32_t)S;
-
- /* todo: if areg = LIMM then there is no result (but since that register can never be read, I guess it doesn't matter if we store it there anyway?) */
- uint32_t result = b | (1 << (c & 0x1f));
- m_regs[breg] = result;
-
- if (F)
- {
- arcompact_fatal("arcompact_handle04_0f (BSET) (F set)\n"); // not yet supported
- }
- return m_pc + (size >> 0);
-}
-
-
-ARCOMPACT_RETTYPE arcompact_device::arcompact_handle04_0f_p11_m0(OPS_32)
-{
- int size = 4;
- arcompact_fatal("arcompact_handle04_0f_p11_m0 (BSET)\n");
- return m_pc + (size >> 0);
-}
-
-
-ARCOMPACT_RETTYPE arcompact_device::arcompact_handle04_0f_p11_m1(OPS_32)
-{
- int size = 4;
- uint32_t limm = 0;
-/* int got_limm = 0; */
-
- COMMON32_GET_breg;
- COMMON32_GET_F;
- COMMON32_GET_u6;
- //COMMON32_GET_areg; // areg bits already used as condition code select
-
- uint32_t c;
- uint32_t b;
-
- /* is having b as LIMM valid here? LIMM vs. fixed u6 value makes no sense */
- if (breg == LIMM_REG)
- {
- GET_LIMM_32;
- size = 8;
-/* got_limm = 1; */
- b = limm;
- }
- else
- {
- b = m_regs[breg];
- }
-
- c = u;
-
- /* todo: if areg = LIMM then there is no result (but since that register can never be read, I guess it doesn't matter if we store it there anyway?) */
- COMMON32_GET_CONDITION;
- if (!check_condition(condition))
- return m_pc + (size>>0);
-
- uint32_t result = b | (1 << (c & 0x1f));
- m_regs[breg] = result;
-
- if (F)
- {
- arcompact_fatal("arcompact_handle04_0f (BSET) (F set)\n"); // not yet supported
- }
- return m_pc + (size >> 0);
-}
-
-
-ARCOMPACT_RETTYPE arcompact_device::arcompact_handle04_13_p00(OPS_32)
-{
- int size = 4;
- uint32_t limm = 0;
- int got_limm = 0;
-
- COMMON32_GET_breg;
- COMMON32_GET_F;
- COMMON32_GET_creg;
- COMMON32_GET_areg;
-
- uint32_t c;
- uint32_t b;
-
- if (breg == LIMM_REG)
- {
- GET_LIMM_32;
- size = 8;
- got_limm = 1;
- b = limm;
- }
- else
- {
- b = m_regs[breg];
- }
-
- if (creg == LIMM_REG)
- {
- if (!got_limm)
- {
- GET_LIMM_32;
- size = 8;
- }
- c = limm;
- }
- else
- {
- c = m_regs[creg];
- }
- /* todo: is the limm, limm syntax valid? (it's pointless.) */
- /* todo: if areg = LIMM then there is no result (but since that register can never be read, I guess it doesn't matter if we store it there anyway?) */
- uint32_t result = b & ((1<<(c+1))-1);
- m_regs[areg] = result;
-
- if (F)
- {
- arcompact_fatal("arcompact_handle04_13 (BMSK) (F set)\n"); // not yet supported
- }
- return m_pc + (size >> 0);
-}
-
-
-ARCOMPACT_RETTYPE arcompact_device::arcompact_handle04_13_p01(OPS_32)
-{
- int size = 4;
- uint32_t limm = 0;
-/* int got_limm = 0; */
-
- COMMON32_GET_breg;
- COMMON32_GET_F;
- COMMON32_GET_u6;
- COMMON32_GET_areg;
-
- uint32_t c;
- uint32_t b;
-
- /* is having b as LIMM valid here? LIMM vs. fixed u6 value makes no sense */
- if (breg == LIMM_REG)
- {
- GET_LIMM_32;
- size = 8;
-/* got_limm = 1; */
- b = limm;
- }
- else
- {
- b = m_regs[breg];
- }
-
- c = u;
-
- /* todo: if areg = LIMM then there is no result (but since that register can never be read, I guess it doesn't matter if we store it there anyway?) */
- uint32_t result = b & ((1<<(c+1))-1);
- m_regs[areg] = result;
-
- if (F)
- {
- arcompact_fatal("arcompact_handle04_13 (BMSK) (F set)\n"); // not yet supported
- }
- return m_pc + (size >> 0);
-}
-
-
-ARCOMPACT_RETTYPE arcompact_device::arcompact_handle04_13_p10(OPS_32)
-{
- int size = 4;
- uint32_t limm = 0;
-/* int got_limm = 0; */
-
- COMMON32_GET_breg;
- COMMON32_GET_F;
- COMMON32_GET_s12;
-
- uint32_t c;
- uint32_t b;
-
- /* is having b as LIMM valid here? LIMM vs. fixed u6 value makes no sense */
- if (breg == LIMM_REG)
- {
- GET_LIMM_32;
- size = 8;
-/* got_limm = 1; */
- b = limm;
- }
- else
- {
- b = m_regs[breg];
- }
-
- c = (uint32_t)S;
-
- /* todo: if areg = LIMM then there is no result (but since that register can never be read, I guess it doesn't matter if we store it there anyway?) */
- uint32_t result = b & ((1<<(c+1))-1);
- m_regs[breg] = result;
-
- if (F)
- {
- arcompact_fatal("arcompact_handle04_13 (BMSK) (F set)\n"); // not yet supported
- }
- return m_pc + (size >> 0);
-}
-
-
-ARCOMPACT_RETTYPE arcompact_device::arcompact_handle04_13_p11_m0(OPS_32)
-{
- int size = 4;
- arcompact_fatal("arcompact_handle04_13_p11_m0 (BMSK)\n");
- return m_pc + (size >> 0);
-}
-
-
-ARCOMPACT_RETTYPE arcompact_device::arcompact_handle04_13_p11_m1(OPS_32)
-{
- int size = 4;
- uint32_t limm = 0;
-/* int got_limm = 0; */
-
- COMMON32_GET_breg;
- COMMON32_GET_F;
- COMMON32_GET_u6;
- //COMMON32_GET_areg; // areg bits already used as condition code select
-
- uint32_t c;
- uint32_t b;
-
- /* is having b as LIMM valid here? LIMM vs. fixed u6 value makes no sense */
- if (breg == LIMM_REG)
- {
- GET_LIMM_32;
- size = 8;
-/* got_limm = 1; */
- b = limm;
- }
- else
- {
- b = m_regs[breg];
- }
-
- c = u;
-
- /* todo: if areg = LIMM then there is no result (but since that register can never be read, I guess it doesn't matter if we store it there anyway?) */
- COMMON32_GET_CONDITION;
- if (!check_condition(condition))
- return m_pc + (size>>0);
-
- uint32_t result = b & ((1<<(c+1))-1);
- m_regs[breg] = result;
-
- if (F)
- {
- arcompact_fatal("arcompact_handle04_13 (BMSK) (F set)\n"); // not yet supported
- }
- return m_pc + (size >> 0);
-}
-
-
-ARCOMPACT_RETTYPE arcompact_device::arcompact_handle04_14_p00(OPS_32)
-{
- int size = 4;
- uint32_t limm = 0;
- int got_limm = 0;
-
- COMMON32_GET_breg;
- COMMON32_GET_F;
- COMMON32_GET_creg;
- COMMON32_GET_areg;
-
- uint32_t c;
- uint32_t b;
-
- if (breg == LIMM_REG)
- {
- GET_LIMM_32;
- size = 8;
- got_limm = 1;
- b = limm;
- }
- else
- {
- b = m_regs[breg];
- }
-
- if (creg == LIMM_REG)
- {
- if (!got_limm)
- {
- GET_LIMM_32;
- size = 8;
- }
- c = limm;
- }
- else
- {
- c = m_regs[creg];
- }
- /* todo: is the limm, limm syntax valid? (it's pointless.) */
- /* todo: if areg = LIMM then there is no result (but since that register can never be read, I guess it doesn't matter if we store it there anyway?) */
- uint32_t result = b + (c << 1);
- m_regs[areg] = result;
-
- if (F)
- {
- arcompact_fatal("arcompact_handle04_14 (ADD1) (F set)\n"); // not yet supported
- }
- return m_pc + (size >> 0);
-}
-
-
-ARCOMPACT_RETTYPE arcompact_device::arcompact_handle04_14_p01(OPS_32)
-{
- int size = 4;
- uint32_t limm = 0;
-/* int got_limm = 0; */
-
- COMMON32_GET_breg;
- COMMON32_GET_F;
- COMMON32_GET_u6;
- COMMON32_GET_areg;
-
- uint32_t c;
- uint32_t b;
-
- /* is having b as LIMM valid here? LIMM vs. fixed u6 value makes no sense */
- if (breg == LIMM_REG)
- {
- GET_LIMM_32;
- size = 8;
-/* got_limm = 1; */
- b = limm;
- }
- else
- {
- b = m_regs[breg];
- }
-
- c = u;
-
- /* todo: if areg = LIMM then there is no result (but since that register can never be read, I guess it doesn't matter if we store it there anyway?) */
- uint32_t result = b + (c << 1);
- m_regs[areg] = result;
-
- if (F)
- {
- arcompact_fatal("arcompact_handle04_14 (ADD1) (F set)\n"); // not yet supported
- }
- return m_pc + (size >> 0);
-}
-
-
-ARCOMPACT_RETTYPE arcompact_device::arcompact_handle04_14_p10(OPS_32)
-{
- int size = 4;
- uint32_t limm = 0;
-/* int got_limm = 0; */
-
- COMMON32_GET_breg;
- COMMON32_GET_F;
- COMMON32_GET_s12;
-
- uint32_t c;
- uint32_t b;
-
- /* is having b as LIMM valid here? LIMM vs. fixed u6 value makes no sense */
- if (breg == LIMM_REG)
- {
- GET_LIMM_32;
- size = 8;
-/* got_limm = 1; */
- b = limm;
- }
- else
- {
- b = m_regs[breg];
- }
-
- c = (uint32_t)S;
-
- /* todo: if areg = LIMM then there is no result (but since that register can never be read, I guess it doesn't matter if we store it there anyway?) */
- uint32_t result = b + (c << 1);
- m_regs[breg] = result;
-
- if (F)
- {
- arcompact_fatal("arcompact_handle04_14 (ADD1) (F set)\n"); // not yet supported
- }
- return m_pc + (size >> 0);
-}
-
-
-ARCOMPACT_RETTYPE arcompact_device::arcompact_handle04_14_p11_m0(OPS_32)
-{
- int size = 4;
- arcompact_fatal("arcompact_handle04_14_p11_m0 (ADD1)\n");
- return m_pc + (size >> 0);
-}
-
-
-ARCOMPACT_RETTYPE arcompact_device::arcompact_handle04_14_p11_m1(OPS_32)
-{
- int size = 4;
- uint32_t limm = 0;
-/* int got_limm = 0; */
-
- COMMON32_GET_breg;
- COMMON32_GET_F;
- COMMON32_GET_u6;
- //COMMON32_GET_areg; // areg bits already used as condition code select
-
- uint32_t c;
- uint32_t b;
-
- /* is having b as LIMM valid here? LIMM vs. fixed u6 value makes no sense */
- if (breg == LIMM_REG)
- {
- GET_LIMM_32;
- size = 8;
-/* got_limm = 1; */
- b = limm;
- }
- else
- {
- b = m_regs[breg];
- }
-
- c = u;
-
- /* todo: if areg = LIMM then there is no result (but since that register can never be read, I guess it doesn't matter if we store it there anyway?) */
- COMMON32_GET_CONDITION;
- if (!check_condition(condition))
- return m_pc + (size>>0);
-
- uint32_t result = b + (c << 1);
- m_regs[breg] = result;
-
- if (F)
- {
- arcompact_fatal("arcompact_handle04_14 (ADD1) (F set)\n"); // not yet supported
- }
- return m_pc + (size >> 0);
-}
-
-
-ARCOMPACT_RETTYPE arcompact_device::arcompact_handle04_15_p00(OPS_32)
-{
- int size = 4;
- uint32_t limm = 0;
- int got_limm = 0;
-
- COMMON32_GET_breg;
- COMMON32_GET_F;
- COMMON32_GET_creg;
- COMMON32_GET_areg;
-
- uint32_t c;
- uint32_t b;
-
- if (breg == LIMM_REG)
- {
- GET_LIMM_32;
- size = 8;
- got_limm = 1;
- b = limm;
- }
- else
- {
- b = m_regs[breg];
- }
-
- if (creg == LIMM_REG)
- {
- if (!got_limm)
- {
- GET_LIMM_32;
- size = 8;
- }
- c = limm;
- }
- else
- {
- c = m_regs[creg];
- }
- /* todo: is the limm, limm syntax valid? (it's pointless.) */
- /* todo: if areg = LIMM then there is no result (but since that register can never be read, I guess it doesn't matter if we store it there anyway?) */
- uint32_t result = b + (c << 2);
- m_regs[areg] = result;
-
- if (F)
- {
- arcompact_fatal("arcompact_handle04_15 (ADD2) (F set)\n"); // not yet supported
- }
- return m_pc + (size >> 0);
-}
-
-
-ARCOMPACT_RETTYPE arcompact_device::arcompact_handle04_15_p01(OPS_32)
-{
- int size = 4;
- uint32_t limm = 0;
-/* int got_limm = 0; */
-
- COMMON32_GET_breg;
- COMMON32_GET_F;
- COMMON32_GET_u6;
- COMMON32_GET_areg;
-
- uint32_t c;
- uint32_t b;
-
- /* is having b as LIMM valid here? LIMM vs. fixed u6 value makes no sense */
- if (breg == LIMM_REG)
- {
- GET_LIMM_32;
- size = 8;
-/* got_limm = 1; */
- b = limm;
- }
- else
- {
- b = m_regs[breg];
- }
-
- c = u;
-
- /* todo: if areg = LIMM then there is no result (but since that register can never be read, I guess it doesn't matter if we store it there anyway?) */
- uint32_t result = b + (c << 2);
- m_regs[areg] = result;
-
- if (F)
- {
- arcompact_fatal("arcompact_handle04_15 (ADD2) (F set)\n"); // not yet supported
- }
- return m_pc + (size >> 0);
-}
-
-
-ARCOMPACT_RETTYPE arcompact_device::arcompact_handle04_15_p10(OPS_32)
-{
- int size = 4;
- uint32_t limm = 0;
-/* int got_limm = 0; */
-
- COMMON32_GET_breg;
- COMMON32_GET_F;
- COMMON32_GET_s12;
-
- uint32_t c;
- uint32_t b;
-
- /* is having b as LIMM valid here? LIMM vs. fixed u6 value makes no sense */
- if (breg == LIMM_REG)
- {
- GET_LIMM_32;
- size = 8;
-/* got_limm = 1; */
- b = limm;
- }
- else
- {
- b = m_regs[breg];
- }
-
- c = (uint32_t)S;
-
- /* todo: if areg = LIMM then there is no result (but since that register can never be read, I guess it doesn't matter if we store it there anyway?) */
- uint32_t result = b + (c << 2);
- m_regs[breg] = result;
-
- if (F)
- {
- arcompact_fatal("arcompact_handle04_15 (ADD2) (F set)\n"); // not yet supported
- }
- return m_pc + (size >> 0);
-}
-
-
-ARCOMPACT_RETTYPE arcompact_device::arcompact_handle04_15_p11_m0(OPS_32)
-{
- int size = 4;
- arcompact_fatal("arcompact_handle04_15_p11_m0 (ADD2)\n");
- return m_pc + (size >> 0);
-}
-
-
-ARCOMPACT_RETTYPE arcompact_device::arcompact_handle04_15_p11_m1(OPS_32)
-{
- int size = 4;
- uint32_t limm = 0;
-/* int got_limm = 0; */
-
- COMMON32_GET_breg;
- COMMON32_GET_F;
- COMMON32_GET_u6;
- //COMMON32_GET_areg; // areg bits already used as condition code select
-
- uint32_t c;
- uint32_t b;
-
- /* is having b as LIMM valid here? LIMM vs. fixed u6 value makes no sense */
- if (breg == LIMM_REG)
- {
- GET_LIMM_32;
- size = 8;
-/* got_limm = 1; */
- b = limm;
- }
- else
- {
- b = m_regs[breg];
- }
-
- c = u;
-
- /* todo: if areg = LIMM then there is no result (but since that register can never be read, I guess it doesn't matter if we store it there anyway?) */
- COMMON32_GET_CONDITION;
- if (!check_condition(condition))
- return m_pc + (size>>0);
-
- uint32_t result = b + (c << 2);
- m_regs[breg] = result;
-
- if (F)
- {
- arcompact_fatal("arcompact_handle04_15 (ADD2) (F set)\n"); // not yet supported
- }
- return m_pc + (size >> 0);
-}
-
-
-ARCOMPACT_RETTYPE arcompact_device::arcompact_handle04_16_p00(OPS_32)
-{
- int size = 4;
- uint32_t limm = 0;
- int got_limm = 0;
-
- COMMON32_GET_breg;
- COMMON32_GET_F;
- COMMON32_GET_creg;
- COMMON32_GET_areg;
-
- uint32_t c;
- uint32_t b;
-
- if (breg == LIMM_REG)
- {
- GET_LIMM_32;
- size = 8;
- got_limm = 1;
- b = limm;
- }
- else
- {
- b = m_regs[breg];
- }
-
- if (creg == LIMM_REG)
- {
- if (!got_limm)
- {
- GET_LIMM_32;
- size = 8;
- }
- c = limm;
- }
- else
- {
- c = m_regs[creg];
- }
- /* todo: is the limm, limm syntax valid? (it's pointless.) */
- /* todo: if areg = LIMM then there is no result (but since that register can never be read, I guess it doesn't matter if we store it there anyway?) */
- uint32_t result = b + (c << 3);
- m_regs[areg] = result;
-
- if (F)
- {
- arcompact_fatal("arcompact_handle04_16 (ADD3) (F set)\n"); // not yet supported
- }
- return m_pc + (size >> 0);
-}
-
-
-ARCOMPACT_RETTYPE arcompact_device::arcompact_handle04_16_p01(OPS_32)
-{
- int size = 4;
- uint32_t limm = 0;
-/* int got_limm = 0; */
-
- COMMON32_GET_breg;
- COMMON32_GET_F;
- COMMON32_GET_u6;
- COMMON32_GET_areg;
-
- uint32_t c;
- uint32_t b;
-
- /* is having b as LIMM valid here? LIMM vs. fixed u6 value makes no sense */
- if (breg == LIMM_REG)
- {
- GET_LIMM_32;
- size = 8;
-/* got_limm = 1; */
- b = limm;
- }
- else
- {
- b = m_regs[breg];
- }
-
- c = u;
-
- /* todo: if areg = LIMM then there is no result (but since that register can never be read, I guess it doesn't matter if we store it there anyway?) */
- uint32_t result = b + (c << 3);
- m_regs[areg] = result;
-
- if (F)
- {
- arcompact_fatal("arcompact_handle04_16 (ADD3) (F set)\n"); // not yet supported
- }
- return m_pc + (size >> 0);
-}
-
-
-ARCOMPACT_RETTYPE arcompact_device::arcompact_handle04_16_p10(OPS_32)
-{
- int size = 4;
- uint32_t limm = 0;
-/* int got_limm = 0; */
-
- COMMON32_GET_breg;
- COMMON32_GET_F;
- COMMON32_GET_s12;
-
- uint32_t c;
- uint32_t b;
-
- /* is having b as LIMM valid here? LIMM vs. fixed u6 value makes no sense */
- if (breg == LIMM_REG)
- {
- GET_LIMM_32;
- size = 8;
-/* got_limm = 1; */
- b = limm;
- }
- else
- {
- b = m_regs[breg];
- }
-
- c = (uint32_t)S;
-
- /* todo: if areg = LIMM then there is no result (but since that register can never be read, I guess it doesn't matter if we store it there anyway?) */
- uint32_t result = b + (c << 3);
- m_regs[breg] = result;
-
- if (F)
- {
- arcompact_fatal("arcompact_handle04_16 (ADD3) (F set)\n"); // not yet supported
- }
- return m_pc + (size >> 0);
-}
-
-
-ARCOMPACT_RETTYPE arcompact_device::arcompact_handle04_16_p11_m0(OPS_32)
-{
- int size = 4;
- arcompact_fatal("arcompact_handle04_16_p11_m0 (ADD3)\n");
- return m_pc + (size >> 0);
-}
-
-
-ARCOMPACT_RETTYPE arcompact_device::arcompact_handle04_16_p11_m1(OPS_32)
-{
- int size = 4;
- uint32_t limm = 0;
-/* int got_limm = 0; */
-
- COMMON32_GET_breg;
- COMMON32_GET_F;
- COMMON32_GET_u6;
- //COMMON32_GET_areg; // areg bits already used as condition code select
-
- uint32_t c;
- uint32_t b;
-
- /* is having b as LIMM valid here? LIMM vs. fixed u6 value makes no sense */
- if (breg == LIMM_REG)
- {
- GET_LIMM_32;
- size = 8;
-/* got_limm = 1; */
- b = limm;
- }
- else
- {
- b = m_regs[breg];
- }
-
- c = u;
-
- /* todo: if areg = LIMM then there is no result (but since that register can never be read, I guess it doesn't matter if we store it there anyway?) */
- COMMON32_GET_CONDITION;
- if (!check_condition(condition))
- return m_pc + (size>>0);
-
- uint32_t result = b + (c << 3);
- m_regs[breg] = result;
-
- if (F)
- {
- arcompact_fatal("arcompact_handle04_16 (ADD3) (F set)\n"); // not yet supported
- }
- return m_pc + (size >> 0);
-}
-
-
-ARCOMPACT_RETTYPE arcompact_device::arcompact_handle04_17_p00(OPS_32)
-{
- int size = 4;
- uint32_t limm = 0;
- int got_limm = 0;
-
- COMMON32_GET_breg;
- COMMON32_GET_F;
- COMMON32_GET_creg;
- COMMON32_GET_areg;
-
- uint32_t c;
- uint32_t b;
-
- if (breg == LIMM_REG)
- {
- GET_LIMM_32;
- size = 8;
- got_limm = 1;
- b = limm;
- }
- else
- {
- b = m_regs[breg];
- }
-
- if (creg == LIMM_REG)
- {
- if (!got_limm)
- {
- GET_LIMM_32;
- size = 8;
- }
- c = limm;
- }
- else
- {
- c = m_regs[creg];
- }
- /* todo: is the limm, limm syntax valid? (it's pointless.) */
- /* todo: if areg = LIMM then there is no result (but since that register can never be read, I guess it doesn't matter if we store it there anyway?) */
- uint32_t result = b - (c << 1);
- m_regs[areg] = result;
-
- if (F)
- {
- arcompact_fatal("arcompact_handle04_17 (SUB1) (F set)\n"); // not yet supported
- }
- return m_pc + (size >> 0);
-}
-
-
-ARCOMPACT_RETTYPE arcompact_device::arcompact_handle04_17_p01(OPS_32)
-{
- int size = 4;
- uint32_t limm = 0;
-/* int got_limm = 0; */
-
- COMMON32_GET_breg;
- COMMON32_GET_F;
- COMMON32_GET_u6;
- COMMON32_GET_areg;
-
- uint32_t c;
- uint32_t b;
-
- /* is having b as LIMM valid here? LIMM vs. fixed u6 value makes no sense */
- if (breg == LIMM_REG)
- {
- GET_LIMM_32;
- size = 8;
-/* got_limm = 1; */
- b = limm;
- }
- else
- {
- b = m_regs[breg];
- }
-
- c = u;
-
- /* todo: if areg = LIMM then there is no result (but since that register can never be read, I guess it doesn't matter if we store it there anyway?) */
- uint32_t result = b - (c << 1);
- m_regs[areg] = result;
-
- if (F)
- {
- arcompact_fatal("arcompact_handle04_17 (SUB1) (F set)\n"); // not yet supported
- }
- return m_pc + (size >> 0);
-}
-
-
-ARCOMPACT_RETTYPE arcompact_device::arcompact_handle04_17_p10(OPS_32)
-{
- int size = 4;
- uint32_t limm = 0;
-/* int got_limm = 0; */
-
- COMMON32_GET_breg;
- COMMON32_GET_F;
- COMMON32_GET_s12;
-
- uint32_t c;
- uint32_t b;
-
- /* is having b as LIMM valid here? LIMM vs. fixed u6 value makes no sense */
- if (breg == LIMM_REG)
- {
- GET_LIMM_32;
- size = 8;
-/* got_limm = 1; */
- b = limm;
- }
- else
- {
- b = m_regs[breg];
- }
-
- c = (uint32_t)S;
-
- /* todo: if areg = LIMM then there is no result (but since that register can never be read, I guess it doesn't matter if we store it there anyway?) */
- uint32_t result = b - (c << 1);
- m_regs[breg] = result;
-
- if (F)
- {
- arcompact_fatal("arcompact_handle04_17 (SUB1) (F set)\n"); // not yet supported
- }
- return m_pc + (size >> 0);
-}
-
-
-ARCOMPACT_RETTYPE arcompact_device::arcompact_handle04_17_p11_m0(OPS_32)
-{
- int size = 4;
- arcompact_fatal("arcompact_handle04_17_p11_m0 (SUB1)\n");
- return m_pc + (size >> 0);
-}
-
-
-ARCOMPACT_RETTYPE arcompact_device::arcompact_handle04_17_p11_m1(OPS_32)
-{
- int size = 4;
- uint32_t limm = 0;
-/* int got_limm = 0; */
-
- COMMON32_GET_breg;
- COMMON32_GET_F;
- COMMON32_GET_u6;
- //COMMON32_GET_areg; // areg bits already used as condition code select
-
- uint32_t c;
- uint32_t b;
-
- /* is having b as LIMM valid here? LIMM vs. fixed u6 value makes no sense */
- if (breg == LIMM_REG)
- {
- GET_LIMM_32;
- size = 8;
-/* got_limm = 1; */
- b = limm;
- }
- else
- {
- b = m_regs[breg];
- }
-
- c = u;
-
- /* todo: if areg = LIMM then there is no result (but since that register can never be read, I guess it doesn't matter if we store it there anyway?) */
- COMMON32_GET_CONDITION;
- if (!check_condition(condition))
- return m_pc + (size>>0);
-
- uint32_t result = b - (c << 1);
- m_regs[breg] = result;
-
- if (F)
- {
- arcompact_fatal("arcompact_handle04_17 (SUB1) (F set)\n"); // not yet supported
- }
- return m_pc + (size >> 0);
-}
-
-
-ARCOMPACT_RETTYPE arcompact_device::arcompact_handle04_18_p00(OPS_32)
-{
- int size = 4;
- uint32_t limm = 0;
- int got_limm = 0;
-
- COMMON32_GET_breg;
- COMMON32_GET_F;
- COMMON32_GET_creg;
- COMMON32_GET_areg;
-
- uint32_t c;
- uint32_t b;
-
- if (breg == LIMM_REG)
- {
- GET_LIMM_32;
- size = 8;
- got_limm = 1;
- b = limm;
- }
- else
- {
- b = m_regs[breg];
- }
-
- if (creg == LIMM_REG)
- {
- if (!got_limm)
- {
- GET_LIMM_32;
- size = 8;
- }
- c = limm;
- }
- else
- {
- c = m_regs[creg];
- }
- /* todo: is the limm, limm syntax valid? (it's pointless.) */
- /* todo: if areg = LIMM then there is no result (but since that register can never be read, I guess it doesn't matter if we store it there anyway?) */
- uint32_t result = b - (c << 2);
- m_regs[areg] = result;
-
- if (F)
- {
- arcompact_fatal("arcompact_handle04_18 (SUB2) (F set)\n"); // not yet supported
- }
- return m_pc + (size >> 0);
-}
-
-
-ARCOMPACT_RETTYPE arcompact_device::arcompact_handle04_18_p01(OPS_32)
-{
- int size = 4;
- uint32_t limm = 0;
-/* int got_limm = 0; */
-
- COMMON32_GET_breg;
- COMMON32_GET_F;
- COMMON32_GET_u6;
- COMMON32_GET_areg;
-
- uint32_t c;
- uint32_t b;
-
- /* is having b as LIMM valid here? LIMM vs. fixed u6 value makes no sense */
- if (breg == LIMM_REG)
- {
- GET_LIMM_32;
- size = 8;
-/* got_limm = 1; */
- b = limm;
- }
- else
- {
- b = m_regs[breg];
- }
-
- c = u;
-
- /* todo: if areg = LIMM then there is no result (but since that register can never be read, I guess it doesn't matter if we store it there anyway?) */
- uint32_t result = b - (c << 2);
- m_regs[areg] = result;
-
- if (F)
- {
- arcompact_fatal("arcompact_handle04_18 (SUB2) (F set)\n"); // not yet supported
- }
- return m_pc + (size >> 0);
-}
-
-
-ARCOMPACT_RETTYPE arcompact_device::arcompact_handle04_18_p10(OPS_32)
-{
- int size = 4;
- uint32_t limm = 0;
-/* int got_limm = 0; */
-
- COMMON32_GET_breg;
- COMMON32_GET_F;
- COMMON32_GET_s12;
-
- uint32_t c;
- uint32_t b;
-
- /* is having b as LIMM valid here? LIMM vs. fixed u6 value makes no sense */
- if (breg == LIMM_REG)
- {
- GET_LIMM_32;
- size = 8;
-/* got_limm = 1; */
- b = limm;
- }
- else
- {
- b = m_regs[breg];
- }
-
- c = (uint32_t)S;
-
- /* todo: if areg = LIMM then there is no result (but since that register can never be read, I guess it doesn't matter if we store it there anyway?) */
- uint32_t result = b - (c << 2);
- m_regs[breg] = result;
-
- if (F)
- {
- arcompact_fatal("arcompact_handle04_18 (SUB2) (F set)\n"); // not yet supported
- }
- return m_pc + (size >> 0);
-}
-
-
-ARCOMPACT_RETTYPE arcompact_device::arcompact_handle04_18_p11_m0(OPS_32)
-{
- int size = 4;
- arcompact_fatal("arcompact_handle04_18_p11_m0 (SUB2)\n");
- return m_pc + (size >> 0);
-}
-
-
-ARCOMPACT_RETTYPE arcompact_device::arcompact_handle04_18_p11_m1(OPS_32)
-{
- int size = 4;
- uint32_t limm = 0;
-/* int got_limm = 0; */
-
- COMMON32_GET_breg;
- COMMON32_GET_F;
- COMMON32_GET_u6;
- //COMMON32_GET_areg; // areg bits already used as condition code select
-
- uint32_t c;
- uint32_t b;
-
- /* is having b as LIMM valid here? LIMM vs. fixed u6 value makes no sense */
- if (breg == LIMM_REG)
- {
- GET_LIMM_32;
- size = 8;
-/* got_limm = 1; */
- b = limm;
- }
- else
- {
- b = m_regs[breg];
- }
-
- c = u;
-
- /* todo: if areg = LIMM then there is no result (but since that register can never be read, I guess it doesn't matter if we store it there anyway?) */
- COMMON32_GET_CONDITION;
- if (!check_condition(condition))
- return m_pc + (size>>0);
-
- uint32_t result = b - (c << 2);
- m_regs[breg] = result;
-
- if (F)
- {
- arcompact_fatal("arcompact_handle04_18 (SUB2) (F set)\n"); // not yet supported
- }
- return m_pc + (size >> 0);
-}
-
-
-ARCOMPACT_RETTYPE arcompact_device::arcompact_handle04_19_p00(OPS_32)
-{
- int size = 4;
- uint32_t limm = 0;
- int got_limm = 0;
-
- COMMON32_GET_breg;
- COMMON32_GET_F;
- COMMON32_GET_creg;
- COMMON32_GET_areg;
-
- uint32_t c;
- uint32_t b;
-
- if (breg == LIMM_REG)
- {
- GET_LIMM_32;
- size = 8;
- got_limm = 1;
- b = limm;
- }
- else
- {
- b = m_regs[breg];
- }
-
- if (creg == LIMM_REG)
- {
- if (!got_limm)
- {
- GET_LIMM_32;
- size = 8;
- }
- c = limm;
- }
- else
- {
- c = m_regs[creg];
- }
- /* todo: is the limm, limm syntax valid? (it's pointless.) */
- /* todo: if areg = LIMM then there is no result (but since that register can never be read, I guess it doesn't matter if we store it there anyway?) */
- uint32_t result = b - (c << 3);
- m_regs[areg] = result;
-
- if (F)
- {
- arcompact_fatal("arcompact_handle04_19 (SUB3) (F set)\n"); // not yet supported
- }
- return m_pc + (size >> 0);
-}
-
-
-ARCOMPACT_RETTYPE arcompact_device::arcompact_handle04_19_p01(OPS_32)
-{
- int size = 4;
- uint32_t limm = 0;
-/* int got_limm = 0; */
-
- COMMON32_GET_breg;
- COMMON32_GET_F;
- COMMON32_GET_u6;
- COMMON32_GET_areg;
-
- uint32_t c;
- uint32_t b;
-
- /* is having b as LIMM valid here? LIMM vs. fixed u6 value makes no sense */
- if (breg == LIMM_REG)
- {
- GET_LIMM_32;
- size = 8;
-/* got_limm = 1; */
- b = limm;
- }
- else
- {
- b = m_regs[breg];
- }
-
- c = u;
-
- /* todo: if areg = LIMM then there is no result (but since that register can never be read, I guess it doesn't matter if we store it there anyway?) */
- uint32_t result = b - (c << 3);
- m_regs[areg] = result;
-
- if (F)
- {
- arcompact_fatal("arcompact_handle04_19 (SUB3) (F set)\n"); // not yet supported
- }
- return m_pc + (size >> 0);
-}
-
-
-ARCOMPACT_RETTYPE arcompact_device::arcompact_handle04_19_p10(OPS_32)
-{
- int size = 4;
- uint32_t limm = 0;
-/* int got_limm = 0; */
-
- COMMON32_GET_breg;
- COMMON32_GET_F;
- COMMON32_GET_s12;
-
- uint32_t c;
- uint32_t b;
-
- /* is having b as LIMM valid here? LIMM vs. fixed u6 value makes no sense */
- if (breg == LIMM_REG)
- {
- GET_LIMM_32;
- size = 8;
-/* got_limm = 1; */
- b = limm;
- }
- else
- {
- b = m_regs[breg];
- }
-
- c = (uint32_t)S;
-
- /* todo: if areg = LIMM then there is no result (but since that register can never be read, I guess it doesn't matter if we store it there anyway?) */
- uint32_t result = b - (c << 3);
- m_regs[breg] = result;
-
- if (F)
- {
- arcompact_fatal("arcompact_handle04_19 (SUB3) (F set)\n"); // not yet supported
- }
- return m_pc + (size >> 0);
-}
-
-
-ARCOMPACT_RETTYPE arcompact_device::arcompact_handle04_19_p11_m0(OPS_32)
-{
- int size = 4;
- arcompact_fatal("arcompact_handle04_19_p11_m0 (SUB3)\n");
- return m_pc + (size >> 0);
-}
-
-
-ARCOMPACT_RETTYPE arcompact_device::arcompact_handle04_19_p11_m1(OPS_32)
-{
- int size = 4;
- uint32_t limm = 0;
-/* int got_limm = 0; */
-
- COMMON32_GET_breg;
- COMMON32_GET_F;
- COMMON32_GET_u6;
- //COMMON32_GET_areg; // areg bits already used as condition code select
-
- uint32_t c;
- uint32_t b;
-
- /* is having b as LIMM valid here? LIMM vs. fixed u6 value makes no sense */
- if (breg == LIMM_REG)
- {
- GET_LIMM_32;
- size = 8;
-/* got_limm = 1; */
- b = limm;
- }
- else
- {
- b = m_regs[breg];
- }
-
- c = u;
-
- /* todo: if areg = LIMM then there is no result (but since that register can never be read, I guess it doesn't matter if we store it there anyway?) */
- COMMON32_GET_CONDITION;
- if (!check_condition(condition))
- return m_pc + (size>>0);
-
- uint32_t result = b - (c << 3);
- m_regs[breg] = result;
-
- if (F)
- {
- arcompact_fatal("arcompact_handle04_19 (SUB3) (F set)\n"); // not yet supported
- }
- return m_pc + (size >> 0);
-}
-
-
-ARCOMPACT_RETTYPE arcompact_device::arcompact_handle04_2a_p00(OPS_32)
-{
- int size = 4;
- uint32_t limm = 0;
- int got_limm = 0;
-
- COMMON32_GET_breg;
- COMMON32_GET_F;
- COMMON32_GET_creg;
- //COMMON32_GET_areg; // areg is reserved / not used
-
- uint32_t c;
-
- if (creg == LIMM_REG)
- {
- if (!got_limm)
- {
- GET_LIMM_32;
- size = 8;
- }
- c = limm;
- }
- else
- {
- c = m_regs[creg];
- }
- /* todo: is the limm, limm syntax valid? (it's pointless.) */
- /* todo: if areg = LIMM then there is no result (but since that register can never be read, I guess it doesn't matter if we store it there anyway?) */
- m_regs[breg] = READAUX(c);
-
-
- if (F)
- {
- // no flag changes
- }
- return m_pc + (size >> 0);
-}
-
-
-ARCOMPACT_RETTYPE arcompact_device::arcompact_handle04_2a_p01(OPS_32)
-{
- int size = 4;
-/* int got_limm = 0; */
-
- COMMON32_GET_breg;
- COMMON32_GET_F;
- COMMON32_GET_u6;
- //COMMON32_GET_areg; // areg is reserved / not used
-
- uint32_t c;
-
- c = u;
-
- /* todo: if areg = LIMM then there is no result (but since that register can never be read, I guess it doesn't matter if we store it there anyway?) */
- m_regs[breg] = READAUX(c);
-
-
- if (F)
- {
- // no flag changes
- }
- return m_pc + (size >> 0);
-}
-
-
-ARCOMPACT_RETTYPE arcompact_device::arcompact_handle04_2a_p10(OPS_32)
-{
- int size = 4;
-/* int got_limm = 0; */
-
- COMMON32_GET_breg;
- COMMON32_GET_F;
- COMMON32_GET_s12;
-
- uint32_t c;
-
- c = (uint32_t)S;
-
- /* todo: if areg = LIMM then there is no result (but since that register can never be read, I guess it doesn't matter if we store it there anyway?) */
- m_regs[breg] = READAUX(c);
-
-
- if (F)
- {
- // no flag changes
- }
- return m_pc + (size >> 0);
-}
-
-
-ARCOMPACT_RETTYPE arcompact_device::arcompact_handle04_2a_p11_m0(OPS_32)
-{
- int size = 4;
- arcompact_fatal("arcompact_handle04_2a_p11_m0 (LR)\n");
- return m_pc + (size >> 0);
-}
-
-
-ARCOMPACT_RETTYPE arcompact_device::arcompact_handle04_2a_p11_m1(OPS_32)
-{
- int size = 4;
-/* int got_limm = 0; */
-
- COMMON32_GET_breg;
- COMMON32_GET_F;
- COMMON32_GET_u6;
- //COMMON32_GET_areg; // areg bits already used as condition code select
-
- uint32_t c;
-
- c = u;
-
- /* todo: if areg = LIMM then there is no result (but since that register can never be read, I guess it doesn't matter if we store it there anyway?) */
- COMMON32_GET_CONDITION;
- if (!check_condition(condition))
- return m_pc + (size>>0);
-
- m_regs[breg] = READAUX(c);
-
-
- if (F)
- {
- // no flag changes
- }
- return m_pc + (size >> 0);
-}
-
-
-ARCOMPACT_RETTYPE arcompact_device::arcompact_handle04_2b_p00(OPS_32)
-{
- int size = 4;
- uint32_t limm = 0;
- int got_limm = 0;
-
- COMMON32_GET_breg;
- COMMON32_GET_F;
- COMMON32_GET_creg;
- //COMMON32_GET_areg; // areg is reserved / not used
-
- uint32_t c;
- uint32_t b;
-
- if (breg == LIMM_REG)
- {
- GET_LIMM_32;
- size = 8;
- got_limm = 1;
- b = limm;
- }
- else
- {
- b = m_regs[breg];
- }
-
- if (creg == LIMM_REG)
- {
- if (!got_limm)
- {
- GET_LIMM_32;
- size = 8;
- }
- c = limm;
- }
- else
- {
- c = m_regs[creg];
- }
- /* todo: is the limm, limm syntax valid? (it's pointless.) */
- /* todo: if areg = LIMM then there is no result (but since that register can never be read, I guess it doesn't matter if we store it there anyway?) */
- WRITEAUX(c,b);
-
-
- if (F)
- {
- // no flag changes
- }
- return m_pc + (size >> 0);
-}
-
-
-ARCOMPACT_RETTYPE arcompact_device::arcompact_handle04_2b_p01(OPS_32)
-{
- int size = 4;
- uint32_t limm = 0;
-/* int got_limm = 0; */
-
- COMMON32_GET_breg;
- COMMON32_GET_F;
- COMMON32_GET_u6;
- //COMMON32_GET_areg; // areg is reserved / not used
-
- uint32_t c;
- uint32_t b;
-
- /* is having b as LIMM valid here? LIMM vs. fixed u6 value makes no sense */
- if (breg == LIMM_REG)
- {
- GET_LIMM_32;
- size = 8;
-/* got_limm = 1; */
- b = limm;
- }
- else
- {
- b = m_regs[breg];
- }
-
- c = u;
-
- /* todo: if areg = LIMM then there is no result (but since that register can never be read, I guess it doesn't matter if we store it there anyway?) */
- WRITEAUX(c,b);
-
-
- if (F)
- {
- // no flag changes
- }
- return m_pc + (size >> 0);
-}
-
-
-ARCOMPACT_RETTYPE arcompact_device::arcompact_handle04_2b_p10(OPS_32)
-{
- int size = 4;
- uint32_t limm = 0;
-/* int got_limm = 0; */
-
- COMMON32_GET_breg;
- COMMON32_GET_F;
- COMMON32_GET_s12;
-
- uint32_t c;
- uint32_t b;
-
- /* is having b as LIMM valid here? LIMM vs. fixed u6 value makes no sense */
- if (breg == LIMM_REG)
- {
- GET_LIMM_32;
- size = 8;
-/* got_limm = 1; */
- b = limm;
- }
- else
- {
- b = m_regs[breg];
- }
-
- c = (uint32_t)S;
-
- /* todo: if areg = LIMM then there is no result (but since that register can never be read, I guess it doesn't matter if we store it there anyway?) */
- WRITEAUX(c,b);
-
-
- if (F)
- {
- // no flag changes
- }
- return m_pc + (size >> 0);
-}
-
-
-ARCOMPACT_RETTYPE arcompact_device::arcompact_handle04_2b_p11_m0(OPS_32)
-{
- int size = 4;
- arcompact_fatal("arcompact_handle04_2b_p11_m0 (SR)\n");
- return m_pc + (size >> 0);
-}
-
-
-ARCOMPACT_RETTYPE arcompact_device::arcompact_handle04_2b_p11_m1(OPS_32)
-{
- int size = 4;
- uint32_t limm = 0;
-/* int got_limm = 0; */
-
- COMMON32_GET_breg;
- COMMON32_GET_F;
- COMMON32_GET_u6;
- //COMMON32_GET_areg; // areg bits already used as condition code select
-
- uint32_t c;
- uint32_t b;
-
- /* is having b as LIMM valid here? LIMM vs. fixed u6 value makes no sense */
- if (breg == LIMM_REG)
- {
- GET_LIMM_32;
- size = 8;
-/* got_limm = 1; */
- b = limm;
- }
- else
- {
- b = m_regs[breg];
- }
-
- c = u;
-
- /* todo: if areg = LIMM then there is no result (but since that register can never be read, I guess it doesn't matter if we store it there anyway?) */
- COMMON32_GET_CONDITION;
- if (!check_condition(condition))
- return m_pc + (size>>0);
-
- WRITEAUX(c,b);
-
-
- if (F)
- {
- // no flag changes
- }
- return m_pc + (size >> 0);
-}
-
-
-ARCOMPACT_RETTYPE arcompact_device::arcompact_handle05_00_p00(OPS_32)
-{
- int size = 4;
- uint32_t limm = 0;
- int got_limm = 0;
-
- COMMON32_GET_breg;
- COMMON32_GET_F;
- COMMON32_GET_creg;
- COMMON32_GET_areg;
-
- uint32_t c;
- uint32_t b;
-
- if (breg == LIMM_REG)
- {
- GET_LIMM_32;
- size = 8;
- got_limm = 1;
- b = limm;
- }
- else
- {
- b = m_regs[breg];
- }
-
- if (creg == LIMM_REG)
- {
- if (!got_limm)
- {
- GET_LIMM_32;
- size = 8;
- }
- c = limm;
- }
- else
- {
- c = m_regs[creg];
- }
- /* todo: is the limm, limm syntax valid? (it's pointless.) */
- /* todo: if areg = LIMM then there is no result (but since that register can never be read, I guess it doesn't matter if we store it there anyway?) */
- uint32_t result = b << (c&0x1f);
- m_regs[areg] = result;
-
- if (F)
- {
- arcompact_fatal("arcompact_handle05_00 (ASL) (F set)\n"); // not yet supported
- }
- return m_pc + (size >> 0);
-}
-
-
-ARCOMPACT_RETTYPE arcompact_device::arcompact_handle05_00_p01(OPS_32)
-{
- int size = 4;
- uint32_t limm = 0;
-/* int got_limm = 0; */
-
- COMMON32_GET_breg;
- COMMON32_GET_F;
- COMMON32_GET_u6;
- COMMON32_GET_areg;
-
- uint32_t c;
- uint32_t b;
-
- /* is having b as LIMM valid here? LIMM vs. fixed u6 value makes no sense */
- if (breg == LIMM_REG)
- {
- GET_LIMM_32;
- size = 8;
-/* got_limm = 1; */
- b = limm;
- }
- else
- {
- b = m_regs[breg];
- }
-
- c = u;
-
- /* todo: if areg = LIMM then there is no result (but since that register can never be read, I guess it doesn't matter if we store it there anyway?) */
- uint32_t result = b << (c&0x1f);
- m_regs[areg] = result;
-
- if (F)
- {
- arcompact_fatal("arcompact_handle05_00 (ASL) (F set)\n"); // not yet supported
- }
- return m_pc + (size >> 0);
-}
-
-
-ARCOMPACT_RETTYPE arcompact_device::arcompact_handle05_00_p10(OPS_32)
-{
- int size = 4;
- uint32_t limm = 0;
-/* int got_limm = 0; */
-
- COMMON32_GET_breg;
- COMMON32_GET_F;
- COMMON32_GET_s12;
-
- uint32_t c;
- uint32_t b;
-
- /* is having b as LIMM valid here? LIMM vs. fixed u6 value makes no sense */
- if (breg == LIMM_REG)
- {
- GET_LIMM_32;
- size = 8;
-/* got_limm = 1; */
- b = limm;
- }
- else
- {
- b = m_regs[breg];
- }
-
- c = (uint32_t)S;
-
- /* todo: if areg = LIMM then there is no result (but since that register can never be read, I guess it doesn't matter if we store it there anyway?) */
- uint32_t result = b << (c&0x1f);
- m_regs[breg] = result;
-
- if (F)
- {
- arcompact_fatal("arcompact_handle05_00 (ASL) (F set)\n"); // not yet supported
- }
- return m_pc + (size >> 0);
-}
-
-
-ARCOMPACT_RETTYPE arcompact_device::arcompact_handle05_00_p11_m0(OPS_32)
-{
- int size = 4;
- arcompact_fatal("arcompact_handle05_00_p11_m0 (ASL)\n");
- return m_pc + (size >> 0);
-}
-
-
-ARCOMPACT_RETTYPE arcompact_device::arcompact_handle05_00_p11_m1(OPS_32)
-{
- int size = 4;
- uint32_t limm = 0;
-/* int got_limm = 0; */
-
- COMMON32_GET_breg;
- COMMON32_GET_F;
- COMMON32_GET_u6;
- //COMMON32_GET_areg; // areg bits already used as condition code select
-
- uint32_t c;
- uint32_t b;
-
- /* is having b as LIMM valid here? LIMM vs. fixed u6 value makes no sense */
- if (breg == LIMM_REG)
- {
- GET_LIMM_32;
- size = 8;
-/* got_limm = 1; */
- b = limm;
- }
- else
- {
- b = m_regs[breg];
- }
-
- c = u;
-
- /* todo: if areg = LIMM then there is no result (but since that register can never be read, I guess it doesn't matter if we store it there anyway?) */
- COMMON32_GET_CONDITION;
- if (!check_condition(condition))
- return m_pc + (size>>0);
-
- uint32_t result = b << (c&0x1f);
- m_regs[breg] = result;
-
- if (F)
- {
- arcompact_fatal("arcompact_handle05_00 (ASL) (F set)\n"); // not yet supported
- }
- return m_pc + (size >> 0);
-}
-
-
-ARCOMPACT_RETTYPE arcompact_device::arcompact_handle05_01_p00(OPS_32)
-{
- int size = 4;
- uint32_t limm = 0;
- int got_limm = 0;
-
- COMMON32_GET_breg;
- COMMON32_GET_F;
- COMMON32_GET_creg;
- COMMON32_GET_areg;
-
- uint32_t c;
- uint32_t b;
-
- if (breg == LIMM_REG)
- {
- GET_LIMM_32;
- size = 8;
- got_limm = 1;
- b = limm;
- }
- else
- {
- b = m_regs[breg];
- }
-
- if (creg == LIMM_REG)
- {
- if (!got_limm)
- {
- GET_LIMM_32;
- size = 8;
- }
- c = limm;
- }
- else
- {
- c = m_regs[creg];
- }
- /* todo: is the limm, limm syntax valid? (it's pointless.) */
- /* todo: if areg = LIMM then there is no result (but since that register can never be read, I guess it doesn't matter if we store it there anyway?) */
- uint32_t result = b >> (c&0x1f);
- m_regs[areg] = result;
-
- if (F)
- {
- arcompact_fatal("arcompact_handle05_01 (LSR) (F set)\n"); // not yet supported
- }
- return m_pc + (size >> 0);
-}
-
-
-ARCOMPACT_RETTYPE arcompact_device::arcompact_handle05_01_p01(OPS_32)
-{
- int size = 4;
- uint32_t limm = 0;
-/* int got_limm = 0; */
-
- COMMON32_GET_breg;
- COMMON32_GET_F;
- COMMON32_GET_u6;
- COMMON32_GET_areg;
-
- uint32_t c;
- uint32_t b;
-
- /* is having b as LIMM valid here? LIMM vs. fixed u6 value makes no sense */
- if (breg == LIMM_REG)
- {
- GET_LIMM_32;
- size = 8;
-/* got_limm = 1; */
- b = limm;
- }
- else
- {
- b = m_regs[breg];
- }
-
- c = u;
-
- /* todo: if areg = LIMM then there is no result (but since that register can never be read, I guess it doesn't matter if we store it there anyway?) */
- uint32_t result = b >> (c&0x1f);
- m_regs[areg] = result;
-
- if (F)
- {
- arcompact_fatal("arcompact_handle05_01 (LSR) (F set)\n"); // not yet supported
- }
- return m_pc + (size >> 0);
-}
-
-
-ARCOMPACT_RETTYPE arcompact_device::arcompact_handle05_01_p10(OPS_32)
-{
- int size = 4;
- uint32_t limm = 0;
-/* int got_limm = 0; */
-
- COMMON32_GET_breg;
- COMMON32_GET_F;
- COMMON32_GET_s12;
-
- uint32_t c;
- uint32_t b;
-
- /* is having b as LIMM valid here? LIMM vs. fixed u6 value makes no sense */
- if (breg == LIMM_REG)
- {
- GET_LIMM_32;
- size = 8;
-/* got_limm = 1; */
- b = limm;
- }
- else
- {
- b = m_regs[breg];
- }
-
- c = (uint32_t)S;
-
- /* todo: if areg = LIMM then there is no result (but since that register can never be read, I guess it doesn't matter if we store it there anyway?) */
- uint32_t result = b >> (c&0x1f);
- m_regs[breg] = result;
-
- if (F)
- {
- arcompact_fatal("arcompact_handle05_01 (LSR) (F set)\n"); // not yet supported
- }
- return m_pc + (size >> 0);
-}
-
-
-ARCOMPACT_RETTYPE arcompact_device::arcompact_handle05_01_p11_m0(OPS_32)
-{
- int size = 4;
- arcompact_fatal("arcompact_handle05_01_p11_m0 (LSR)\n");
- return m_pc + (size >> 0);
-}
-
-
-ARCOMPACT_RETTYPE arcompact_device::arcompact_handle05_01_p11_m1(OPS_32)
-{
- int size = 4;
- uint32_t limm = 0;
-/* int got_limm = 0; */
-
- COMMON32_GET_breg;
- COMMON32_GET_F;
- COMMON32_GET_u6;
- //COMMON32_GET_areg; // areg bits already used as condition code select
-
- uint32_t c;
- uint32_t b;
-
- /* is having b as LIMM valid here? LIMM vs. fixed u6 value makes no sense */
- if (breg == LIMM_REG)
- {
- GET_LIMM_32;
- size = 8;
-/* got_limm = 1; */
- b = limm;
- }
- else
- {
- b = m_regs[breg];
- }
-
- c = u;
-
- /* todo: if areg = LIMM then there is no result (but since that register can never be read, I guess it doesn't matter if we store it there anyway?) */
- COMMON32_GET_CONDITION;
- if (!check_condition(condition))
- return m_pc + (size>>0);
-
- uint32_t result = b >> (c&0x1f);
- m_regs[breg] = result;
-
- if (F)
- {
- arcompact_fatal("arcompact_handle05_01 (LSR) (F set)\n"); // not yet supported
- }
- return m_pc + (size >> 0);
-}
-
-
-ARCOMPACT_RETTYPE arcompact_device::arcompact_handle04_2f_02_p00(OPS_32)
-{
- int size = 4;
- uint32_t limm = 0;
- int got_limm = 0;
-
- COMMON32_GET_breg;
- COMMON32_GET_F;
- COMMON32_GET_creg;
- //COMMON32_GET_areg; // areg bits already used as opcode select
-
- uint32_t c;
-
- if (creg == LIMM_REG)
- {
- if (!got_limm)
- {
- GET_LIMM_32;
- size = 8;
- }
- c = limm;
- }
- else
- {
- c = m_regs[creg];
- }
- /* todo: is the limm, limm syntax valid? (it's pointless.) */
- /* todo: if areg = LIMM then there is no result (but since that register can never be read, I guess it doesn't matter if we store it there anyway?) */
- uint32_t result = c >> 1;
- m_regs[breg] = result;
-
- if (F)
- {
- if (result & 0x80000000) { STATUS32_SET_N; }
- else { STATUS32_CLEAR_N; }
- if (result == 0x00000000) { STATUS32_SET_Z; }
- else { STATUS32_CLEAR_Z; }
- if (c == 0x00000001) { STATUS32_SET_C; }
- else { STATUS32_CLEAR_C; }
- }
- return m_pc + (size >> 0);
-}
-
-
-ARCOMPACT_RETTYPE arcompact_device::arcompact_handle04_2f_02_p01(OPS_32)
-{
- int size = 4;
-/* int got_limm = 0; */
-
- COMMON32_GET_breg;
- COMMON32_GET_F;
- COMMON32_GET_u6;
- //COMMON32_GET_areg; // areg bits already used as opcode select
-
- uint32_t c;
-
- c = u;
-
- /* todo: if areg = LIMM then there is no result (but since that register can never be read, I guess it doesn't matter if we store it there anyway?) */
- uint32_t result = c >> 1;
- m_regs[breg] = result;
-
- if (F)
- {
- if (result & 0x80000000) { STATUS32_SET_N; }
- else { STATUS32_CLEAR_N; }
- if (result == 0x00000000) { STATUS32_SET_Z; }
- else { STATUS32_CLEAR_Z; }
- if (c == 0x00000001) { STATUS32_SET_C; }
- else { STATUS32_CLEAR_C; }
- }
- return m_pc + (size >> 0);
-}
-
-
-ARCOMPACT_RETTYPE arcompact_device::arcompact_handle04_2f_02_p10(OPS_32)
-{
- int size = 4;
- arcompact_fatal("illegal arcompact_handle04_2f_02_p10 (ares bits already used as opcode select, can't be used as s12) (LSR1)\n");
- return m_pc + (size >> 0);
-}
-
-
-ARCOMPACT_RETTYPE arcompact_device::arcompact_handle04_2f_02_p11_m0(OPS_32)
-{
- int size = 4;
- arcompact_fatal("illegal arcompact_handle04_2f_02_p11_m0 (ares bits already used as opcode select, can't be used as Q condition) (LSR1)\n");
- return m_pc + (size >> 0);
-}
-ARCOMPACT_RETTYPE arcompact_device::arcompact_handle04_2f_02_p11_m1(OPS_32)
-{
- int size = 4;
- arcompact_fatal("illegal arcompact_handle04_2f_02_p11_m1 (ares bits already used as opcode select, can't be used as Q condition) (LSR1)\n");
- return m_pc + (size >> 0);
-}
-
-
-ARCOMPACT_RETTYPE arcompact_device::arcompact_handle04_2f_03_p00(OPS_32)
-{
- int size = 4;
- uint32_t limm = 0;
- int got_limm = 0;
-
- COMMON32_GET_breg;
- COMMON32_GET_F;
- COMMON32_GET_creg;
- //COMMON32_GET_areg; // areg bits already used as opcode select
-
- uint32_t c;
-
- if (creg == LIMM_REG)
- {
- if (!got_limm)
- {
- GET_LIMM_32;
- size = 8;
- }
- c = limm;
- }
- else
- {
- c = m_regs[creg];
- }
- /* todo: is the limm, limm syntax valid? (it's pointless.) */
- /* todo: if areg = LIMM then there is no result (but since that register can never be read, I guess it doesn't matter if we store it there anyway?) */
- int shift = 1; uint32_t mask = (1 << (shift)) - 1; mask <<= (32-shift); uint32_t result = ((c >> shift) & ~mask) | ((c << (32-shift)) & mask);
- m_regs[breg] = result;
-
- if (F)
- {
- if (result & 0x80000000) { STATUS32_SET_N; }
- else { STATUS32_CLEAR_N; }
- if (result == 0x00000000) { STATUS32_SET_Z; }
- else { STATUS32_CLEAR_Z; }
- if (c == 0x00000001) { STATUS32_SET_C; }
- else { STATUS32_CLEAR_C; }
- }
- return m_pc + (size >> 0);
-}
-
-
-ARCOMPACT_RETTYPE arcompact_device::arcompact_handle04_2f_03_p01(OPS_32)
-{
- int size = 4;
-/* int got_limm = 0; */
-
- COMMON32_GET_breg;
- COMMON32_GET_F;
- COMMON32_GET_u6;
- //COMMON32_GET_areg; // areg bits already used as opcode select
-
- uint32_t c;
-
- c = u;
-
- /* todo: if areg = LIMM then there is no result (but since that register can never be read, I guess it doesn't matter if we store it there anyway?) */
- int shift = 1; uint32_t mask = (1 << (shift)) - 1; mask <<= (32-shift); uint32_t result = ((c >> shift) & ~mask) | ((c << (32-shift)) & mask);
- m_regs[breg] = result;
-
- if (F)
- {
- if (result & 0x80000000) { STATUS32_SET_N; }
- else { STATUS32_CLEAR_N; }
- if (result == 0x00000000) { STATUS32_SET_Z; }
- else { STATUS32_CLEAR_Z; }
- if (c == 0x00000001) { STATUS32_SET_C; }
- else { STATUS32_CLEAR_C; }
- }
- return m_pc + (size >> 0);
-}
-
-
-ARCOMPACT_RETTYPE arcompact_device::arcompact_handle04_2f_03_p10(OPS_32)
-{
- int size = 4;
- arcompact_fatal("illegal arcompact_handle04_2f_03_p10 (ares bits already used as opcode select, can't be used as s12) (ROR)\n");
- return m_pc + (size >> 0);
-}
-
-
-ARCOMPACT_RETTYPE arcompact_device::arcompact_handle04_2f_03_p11_m0(OPS_32)
-{
- int size = 4;
- arcompact_fatal("illegal arcompact_handle04_2f_03_p11_m0 (ares bits already used as opcode select, can't be used as Q condition) (ROR)\n");
- return m_pc + (size >> 0);
-}
-ARCOMPACT_RETTYPE arcompact_device::arcompact_handle04_2f_03_p11_m1(OPS_32)
-{
- int size = 4;
- arcompact_fatal("illegal arcompact_handle04_2f_03_p11_m1 (ares bits already used as opcode select, can't be used as Q condition) (ROR)\n");
- return m_pc + (size >> 0);
-}
-
-
-ARCOMPACT_RETTYPE arcompact_device::arcompact_handle04_2f_07_p00(OPS_32)
-{
- int size = 4;
- uint32_t limm = 0;
- int got_limm = 0;
-
- COMMON32_GET_breg;
- COMMON32_GET_F;
- COMMON32_GET_creg;
- //COMMON32_GET_areg; // areg bits already used as opcode select
-
- uint32_t c;
-
- if (creg == LIMM_REG)
- {
- if (!got_limm)
- {
- GET_LIMM_32;
- size = 8;
- }
- c = limm;
- }
- else
- {
- c = m_regs[creg];
- }
- /* todo: is the limm, limm syntax valid? (it's pointless.) */
- /* todo: if areg = LIMM then there is no result (but since that register can never be read, I guess it doesn't matter if we store it there anyway?) */
- uint32_t result = c & 0x000000ff;
- m_regs[breg] = result;
-
- if (F)
- {
- arcompact_fatal("arcompact_handle04_2f_07 (EXTB) (F set)\n"); // not yet supported
- }
- return m_pc + (size >> 0);
-}
-
-
-ARCOMPACT_RETTYPE arcompact_device::arcompact_handle04_2f_07_p01(OPS_32)
-{
- int size = 4;
-/* int got_limm = 0; */
-
- COMMON32_GET_breg;
- COMMON32_GET_F;
- COMMON32_GET_u6;
- //COMMON32_GET_areg; // areg bits already used as opcode select
-
- uint32_t c;
-
- c = u;
-
- /* todo: if areg = LIMM then there is no result (but since that register can never be read, I guess it doesn't matter if we store it there anyway?) */
- uint32_t result = c & 0x000000ff;
- m_regs[breg] = result;
-
- if (F)
- {
- arcompact_fatal("arcompact_handle04_2f_07 (EXTB) (F set)\n"); // not yet supported
- }
- return m_pc + (size >> 0);
-}
-
-
-ARCOMPACT_RETTYPE arcompact_device::arcompact_handle04_2f_07_p10(OPS_32)
-{
- int size = 4;
- arcompact_fatal("illegal arcompact_handle04_2f_07_p10 (ares bits already used as opcode select, can't be used as s12) (EXTB)\n");
- return m_pc + (size >> 0);
-}
-
-
-ARCOMPACT_RETTYPE arcompact_device::arcompact_handle04_2f_07_p11_m0(OPS_32)
-{
- int size = 4;
- arcompact_fatal("illegal arcompact_handle04_2f_07_p11_m0 (ares bits already used as opcode select, can't be used as Q condition) (EXTB)\n");
- return m_pc + (size >> 0);
-}
-ARCOMPACT_RETTYPE arcompact_device::arcompact_handle04_2f_07_p11_m1(OPS_32)
-{
- int size = 4;
- arcompact_fatal("illegal arcompact_handle04_2f_07_p11_m1 (ares bits already used as opcode select, can't be used as Q condition) (EXTB)\n");
- return m_pc + (size >> 0);
-}
-
-
-ARCOMPACT_RETTYPE arcompact_device::arcompact_handle04_2f_08_p00(OPS_32)
-{
- int size = 4;
- uint32_t limm = 0;
- int got_limm = 0;
-
- COMMON32_GET_breg;
- COMMON32_GET_F;
- COMMON32_GET_creg;
- //COMMON32_GET_areg; // areg bits already used as opcode select
-
- uint32_t c;
-
- if (creg == LIMM_REG)
- {
- if (!got_limm)
- {
- GET_LIMM_32;
- size = 8;
- }
- c = limm;
- }
- else
- {
- c = m_regs[creg];
- }
- /* todo: is the limm, limm syntax valid? (it's pointless.) */
- /* todo: if areg = LIMM then there is no result (but since that register can never be read, I guess it doesn't matter if we store it there anyway?) */
- uint32_t result = c & 0x0000ffff;
- m_regs[breg] = result;
-
- if (F)
- {
- arcompact_fatal("arcompact_handle04_2f_08 (EXTW) (F set)\n"); // not yet supported
- }
- return m_pc + (size >> 0);
-}
-
-
-ARCOMPACT_RETTYPE arcompact_device::arcompact_handle04_2f_08_p01(OPS_32)
-{
- int size = 4;
-/* int got_limm = 0; */
-
- COMMON32_GET_breg;
- COMMON32_GET_F;
- COMMON32_GET_u6;
- //COMMON32_GET_areg; // areg bits already used as opcode select
-
- uint32_t c;
-
- c = u;
-
- /* todo: if areg = LIMM then there is no result (but since that register can never be read, I guess it doesn't matter if we store it there anyway?) */
- uint32_t result = c & 0x0000ffff;
- m_regs[breg] = result;
-
- if (F)
- {
- arcompact_fatal("arcompact_handle04_2f_08 (EXTW) (F set)\n"); // not yet supported
- }
- return m_pc + (size >> 0);
-}
-
-
-ARCOMPACT_RETTYPE arcompact_device::arcompact_handle04_2f_08_p10(OPS_32)
-{
- int size = 4;
- arcompact_fatal("illegal arcompact_handle04_2f_08_p10 (ares bits already used as opcode select, can't be used as s12) (EXTW)\n");
- return m_pc + (size >> 0);
-}
-
-
-ARCOMPACT_RETTYPE arcompact_device::arcompact_handle04_2f_08_p11_m0(OPS_32)
-{
- int size = 4;
- arcompact_fatal("illegal arcompact_handle04_2f_08_p11_m0 (ares bits already used as opcode select, can't be used as Q condition) (EXTW)\n");
- return m_pc + (size >> 0);
-}
-ARCOMPACT_RETTYPE arcompact_device::arcompact_handle04_2f_08_p11_m1(OPS_32)
-{
- int size = 4;
- arcompact_fatal("illegal arcompact_handle04_2f_08_p11_m1 (ares bits already used as opcode select, can't be used as Q condition) (EXTW)\n");
- return m_pc + (size >> 0);
-}
-
-
-ARCOMPACT_RETTYPE arcompact_device::arcompact_handle0d_00(OPS_16)
-{
- int u, breg, creg;
-
- COMMON16_GET_u3;
- COMMON16_GET_breg;
- COMMON16_GET_creg;
-
- REG_16BIT_RANGE(breg);
- REG_16BIT_RANGE(creg);
-
- uint32_t result = m_regs[breg] + u;
- m_regs[creg] = result;
-
- return m_pc + (2 >> 0);
-}
-
-
-ARCOMPACT_RETTYPE arcompact_device::arcompact_handle0d_01(OPS_16)
-{
- int u, breg, creg;
-
- COMMON16_GET_u3;
- COMMON16_GET_breg;
- COMMON16_GET_creg;
-
- REG_16BIT_RANGE(breg);
- REG_16BIT_RANGE(creg);
-
- uint32_t result = m_regs[breg] - u;
- m_regs[creg] = result;
-
- return m_pc + (2 >> 0);
-}
-
-
-ARCOMPACT_RETTYPE arcompact_device::arcompact_handle0d_02(OPS_16)
-{
- int u, breg, creg;
-
- COMMON16_GET_u3;
- COMMON16_GET_breg;
- COMMON16_GET_creg;
-
- REG_16BIT_RANGE(breg);
- REG_16BIT_RANGE(creg);
-
- uint32_t result = m_regs[breg] << u;
- m_regs[creg] = result;
-
- return m_pc + (2 >> 0);
-}
-
-
-ARCOMPACT_RETTYPE arcompact_device::arcompact_handle0f_02(OPS_16)
-{
- int breg, creg;
-
- COMMON16_GET_breg;
- COMMON16_GET_creg;
-
- REG_16BIT_RANGE(breg);
- REG_16BIT_RANGE(creg);
-
- uint32_t result = m_regs[breg] - m_regs[creg];
- m_regs[breg] = result;
-
- return m_pc + (2 >> 0);
-}
-
-
-ARCOMPACT_RETTYPE arcompact_device::arcompact_handle0f_04(OPS_16)
-{
- int breg, creg;
-
- COMMON16_GET_breg;
- COMMON16_GET_creg;
-
- REG_16BIT_RANGE(breg);
- REG_16BIT_RANGE(creg);
-
- uint32_t result = m_regs[breg] & m_regs[creg];
- m_regs[breg] = result;
-
- return m_pc + (2 >> 0);
-}
-
-
-ARCOMPACT_RETTYPE arcompact_device::arcompact_handle0f_05(OPS_16)
-{
- int breg, creg;
-
- COMMON16_GET_breg;
- COMMON16_GET_creg;
-
- REG_16BIT_RANGE(breg);
- REG_16BIT_RANGE(creg);
-
- uint32_t result = m_regs[breg] | m_regs[creg];
- m_regs[breg] = result;
-
- return m_pc + (2 >> 0);
-}
-
-
-ARCOMPACT_RETTYPE arcompact_device::arcompact_handle0f_07(OPS_16)
-{
- int breg, creg;
-
- COMMON16_GET_breg;
- COMMON16_GET_creg;
-
- REG_16BIT_RANGE(breg);
- REG_16BIT_RANGE(creg);
-
- uint32_t result = m_regs[breg] ^ m_regs[creg];
- m_regs[breg] = result;
-
- return m_pc + (2 >> 0);
-}
-
-
-ARCOMPACT_RETTYPE arcompact_device::arcompact_handle0f_0f(OPS_16)
-{
- int breg, creg;
-
- COMMON16_GET_breg;
- COMMON16_GET_creg;
-
- REG_16BIT_RANGE(breg);
- REG_16BIT_RANGE(creg);
-
- uint32_t result = m_regs[creg] & 0x000000ff;
- m_regs[breg] = result;
-
- return m_pc + (2 >> 0);
-}
-
-
-ARCOMPACT_RETTYPE arcompact_device::arcompact_handle0f_10(OPS_16)
-{
- int breg, creg;
-
- COMMON16_GET_breg;
- COMMON16_GET_creg;
-
- REG_16BIT_RANGE(breg);
- REG_16BIT_RANGE(creg);
-
- uint32_t result = m_regs[creg] & 0x0000ffff;
- m_regs[breg] = result;
-
- return m_pc + (2 >> 0);
-}
-
-
-ARCOMPACT_RETTYPE arcompact_device::arcompact_handle0f_13(OPS_16)
-{
- int breg, creg;
-
- COMMON16_GET_breg;
- COMMON16_GET_creg;
-
- REG_16BIT_RANGE(breg);
- REG_16BIT_RANGE(creg);
-
- uint32_t result = 0 - m_regs[creg];
- m_regs[breg] = result;
-
- return m_pc + (2 >> 0);
-}
-
-
-ARCOMPACT_RETTYPE arcompact_device::arcompact_handle0f_14(OPS_16)
-{
- int breg, creg;
-
- COMMON16_GET_breg;
- COMMON16_GET_creg;
-
- REG_16BIT_RANGE(breg);
- REG_16BIT_RANGE(creg);
-
- uint32_t result = m_regs[breg] + (m_regs[creg] <<1);
- m_regs[breg] = result;
-
- return m_pc + (2 >> 0);
-}
-
-
-ARCOMPACT_RETTYPE arcompact_device::arcompact_handle0f_15(OPS_16)
-{
- int breg, creg;
-
- COMMON16_GET_breg;
- COMMON16_GET_creg;
-
- REG_16BIT_RANGE(breg);
- REG_16BIT_RANGE(creg);
-
- uint32_t result = m_regs[breg] + (m_regs[creg] <<2);
- m_regs[breg] = result;
-
- return m_pc + (2 >> 0);
-}
-
-
-ARCOMPACT_RETTYPE arcompact_device::arcompact_handle0f_16(OPS_16)
-{
- int breg, creg;
-
- COMMON16_GET_breg;
- COMMON16_GET_creg;
-
- REG_16BIT_RANGE(breg);
- REG_16BIT_RANGE(creg);
-
- uint32_t result = m_regs[breg] + (m_regs[creg] <<3);
- m_regs[breg] = result;
-
- return m_pc + (2 >> 0);
-}
-
-
-ARCOMPACT_RETTYPE arcompact_device::arcompact_handle0f_19(OPS_16)
-{
- int breg, creg;
-
- COMMON16_GET_breg;
- COMMON16_GET_creg;
-
- REG_16BIT_RANGE(breg);
- REG_16BIT_RANGE(creg);
-
- uint32_t result = m_regs[breg] >> (m_regs[creg]&0x1f);
- m_regs[breg] = result;
-
- return m_pc + (2 >> 0);
-}
-
-
-ARCOMPACT_RETTYPE arcompact_device::arcompact_handle0f_1b(OPS_16)
-{
- int breg, creg;
-
- COMMON16_GET_breg;
- COMMON16_GET_creg;
-
- REG_16BIT_RANGE(breg);
- REG_16BIT_RANGE(creg);
-
- uint32_t result = m_regs[creg] << 1;
- m_regs[breg] = result;
-
- return m_pc + (2 >> 0);
-}
-
-
-ARCOMPACT_RETTYPE arcompact_device::arcompact_handle17_00(OPS_16)
-{
- int breg, u;
-
- COMMON16_GET_breg;
- COMMON16_GET_u5;
-
- REG_16BIT_RANGE(breg);
-
- m_regs[breg] = m_regs[breg] << (u&0x1f);
-
- return m_pc + (2 >> 0);
-}
-
-
-ARCOMPACT_RETTYPE arcompact_device::arcompact_handle17_01(OPS_16)
-{
- int breg, u;
-
- COMMON16_GET_breg;
- COMMON16_GET_u5;
-
- REG_16BIT_RANGE(breg);
-
- m_regs[breg] = m_regs[breg] >> (u&0x1f);
-
- return m_pc + (2 >> 0);
-}
-
-
-ARCOMPACT_RETTYPE arcompact_device::arcompact_handle17_02(OPS_16)
-{
- int breg, u;
-
- COMMON16_GET_breg;
- COMMON16_GET_u5;
-
- REG_16BIT_RANGE(breg);
-
- int32_t temp = (int32_t)m_regs[breg]; m_regs[breg] = temp >> (u&0x1f); // treat it as a signed value, so sign extension occurs during shift
-
- return m_pc + (2 >> 0);
-}
-
-
-ARCOMPACT_RETTYPE arcompact_device::arcompact_handle17_03(OPS_16)
-{
- int breg, u;
-
- COMMON16_GET_breg;
- COMMON16_GET_u5;
-
- REG_16BIT_RANGE(breg);
-
- m_regs[breg] = m_regs[breg] - u;
-
- return m_pc + (2 >> 0);
-}
+ // hardware loops
-ARCOMPACT_RETTYPE arcompact_device::arcompact_handle17_04(OPS_16)
-{
- int breg, u;
-
- COMMON16_GET_breg;
- COMMON16_GET_u5;
-
- REG_16BIT_RANGE(breg);
-
- m_regs[breg] = m_regs[breg] | (1 << (u & 0x1f));
-
- return m_pc + (2 >> 0);
-}
-
-
-ARCOMPACT_RETTYPE arcompact_device::arcompact_handle17_06(OPS_16)
-{
- int breg, u;
-
- COMMON16_GET_breg;
- COMMON16_GET_u5;
-
- REG_16BIT_RANGE(breg);
-
- m_regs[breg] = m_regs[breg] | ((1 << (u + 1)) - 1);
-
- return m_pc + (2 >> 0);
-}
-
-
-
-ARCOMPACT_RETTYPE arcompact_device::arcompact_handle04_01(OPS_32)
-{
- return arcompact_handle04_helper(PARAMS, arcompact_disassembler::opcodes_04[0x01], /*"ADC"*/ 0,0);
-}
-
-
-
-ARCOMPACT_RETTYPE arcompact_device::arcompact_handle04_03(OPS_32)
-{
- return arcompact_handle04_helper(PARAMS, arcompact_disassembler::opcodes_04[0x03], /*"SBC"*/ 0,0);
-}
-
-ARCOMPACT_RETTYPE arcompact_device::arcompact_handle04_08(OPS_32)
-{
- return arcompact_handle04_helper(PARAMS, arcompact_disassembler::opcodes_04[0x08], /*"MAX"*/ 0,0);
-}
-
-ARCOMPACT_RETTYPE arcompact_device::arcompact_handle04_09(OPS_32)
-{
- return arcompact_handle04_helper(PARAMS, arcompact_disassembler::opcodes_04[0x09], /*"MIN"*/ 0,0);
-}
-
-
-
-ARCOMPACT_RETTYPE arcompact_device::arcompact_handle04_0b(OPS_32)
-{
- return arcompact_handle04_helper(PARAMS, arcompact_disassembler::opcodes_04[0x0b], /*"TST"*/ 1,0);
-}
-
-ARCOMPACT_RETTYPE arcompact_device::arcompact_handle04_0c(OPS_32)
-{
- return arcompact_handle04_helper(PARAMS, arcompact_disassembler::opcodes_04[0x0c], /*"CMP"*/ 1,0);
-}
-
-ARCOMPACT_RETTYPE arcompact_device::arcompact_handle04_0d(OPS_32)
-{
- return arcompact_handle04_helper(PARAMS, arcompact_disassembler::opcodes_04[0x0d], /*"RCMP"*/ 1,0);
-}
-
-
-
-ARCOMPACT_RETTYPE arcompact_device::arcompact_handle04_10(OPS_32)
-{
- return arcompact_handle04_helper(PARAMS, arcompact_disassembler::opcodes_04[0x10], /*"BCLR"*/ 0,0);
-}
-
-ARCOMPACT_RETTYPE arcompact_device::arcompact_handle04_11(OPS_32)
-{
- return arcompact_handle04_helper(PARAMS, arcompact_disassembler::opcodes_04[0x11], /*"BTST"*/ 0,0);
-}
-
-ARCOMPACT_RETTYPE arcompact_device::arcompact_handle04_12(OPS_32)
-{
- return arcompact_handle04_helper(PARAMS, arcompact_disassembler::opcodes_04[0x12], /*"BXOR"*/ 0,0);
-}
-
-
-
-
-
-
-ARCOMPACT_RETTYPE arcompact_device::arcompact_handle04_1a(OPS_32)
-{
- return arcompact_handle04_helper(PARAMS, arcompact_disassembler::opcodes_04[0x1a], /*"MPY"*/ 0,0);
-} // *
-
-ARCOMPACT_RETTYPE arcompact_device::arcompact_handle04_1b(OPS_32)
-{
- return arcompact_handle04_helper(PARAMS, arcompact_disassembler::opcodes_04[0x1b], /*"MPYH"*/ 0,0);
-} // *
-
-ARCOMPACT_RETTYPE arcompact_device::arcompact_handle04_1c(OPS_32)
-{
- return arcompact_handle04_helper(PARAMS, arcompact_disassembler::opcodes_04[0x1c], /*"MPYHU"*/ 0,0);
-} // *
-
-ARCOMPACT_RETTYPE arcompact_device::arcompact_handle04_1d(OPS_32)
-{
- return arcompact_handle04_helper(PARAMS, arcompact_disassembler::opcodes_04[0x1d], /*"MPYU"*/ 0,0);
-} // *
-
-ARCOMPACT_RETTYPE arcompact_device::arcompact_handle04_20_p00(OPS_32)
-{
- int size;
- uint32_t limm = 0;
- int got_limm = 0;
-
- COMMON32_GET_creg
- COMMON32_GET_F
-
- if (creg == LIMM_REG)
- {
- // opcode iiii i--- ppII IIII F--- CCCC CC-- ----
- // J limm 0010 0RRR 0010 0000 0RRR 1111 10RR RRRR [LIMM] (creg = LIMM)
-
- if (!got_limm)
- {
- GET_LIMM_32;
- size = 8;
- }
-
- return limm;
- }
- else
- {
- // opcode iiii i--- ppII IIII F--- CCCC CC-- ----
- // J [c] 0010 0RRR 0010 0000 0RRR CCCC CCRR RRRR
- // J.F [ilink1] 0010 0RRR 0010 0000 1RRR 0111 01RR RRRR (creg = ILINK1, FLAG must be set)
- // J.F [ilink2] 0010 0RRR 0010 0000 1RRR 0111 10RR RRRR (creg = ILINE2, FLAG must be set)
-
- if (F)
- {
- if ((creg == REG_ILINK1) || (creg == REG_ILINK2))
- {
- arcompact_log("1 unimplemented J.F %08x", op);
- }
- else
- {
- // should not use .F unless jumping to ILINK1/2
- arcompact_fatal ("illegal 1 unimplemented J.F (F should not be set) %08x", op);
- }
-
- }
- else
- {
- if ((creg == REG_ILINK1) || (creg == REG_ILINK2))
+ // NOTE: if LPcc condition code fails, the m_PC returned will be m_LP_END
+ // which will then cause this check to happen and potentially jump back to
+ // the start of the loop if LP_COUNT is anything other than 1, this should
+ // not happen. It could be our PC handling needs to be better? Either way
+ // guard against it!
+ if (m_allow_loop_check)
{
- // should only jumping to ILINK1/2 if .F is set
- arcompact_fatal("illegal 1 unimplemented J (F not set) %08x", op);
+ if (m_pc == m_LP_END)
+ {
+ // NOTE: this behavior should differ between ARC models
+ if ((m_regs[REG_LP_COUNT] != 1))
+ {
+ set_pc(m_LP_START);
+ }
+ m_regs[REG_LP_COUNT]--;
+ }
}
else
{
- return m_regs[creg];
+ m_allow_loop_check = true;
}
}
+ m_icount--;
}
-
- return m_pc + (size>>0);
-}
-
-ARCOMPACT_RETTYPE arcompact_device::arcompact_handle04_20_p01(OPS_32)
-{
- // opcode iiii i--- ppII IIII F--- uuuu uu-- ----
- // J u6 0010 0RRR 0110 0000 0RRR uuuu uuRR RRRR
- int size = 4;
- arcompact_log("2 unimplemented J %08x", op);
- return m_pc + (size>>0);
-}
-
-ARCOMPACT_RETTYPE arcompact_device::arcompact_handle04_20_p10(OPS_32)
-{
- // opcode iiii i--- ppII IIII F--- ssss ssSS SSSS
- // J s12 0010 0RRR 1010 0000 0RRR ssss ssSS SSSS
- int size = 4;
- arcompact_log("3 unimplemented J %08x", op);
- return m_pc + (size>>0);
-}
-
-
-ARCOMPACT_RETTYPE arcompact_device::arcompact_handle04_20_p11_m0(OPS_32) // Jcc (no link, no delay)
-{
- int size = 4;
- uint32_t limm = 0;
- int got_limm = 0;
-
- COMMON32_GET_creg
- COMMON32_GET_CONDITION;
- COMMON32_GET_F
-
- uint32_t c;
-
- if (creg == LIMM_REG)
- {
- // opcode iiii i--- ppII IIII F--- cccc ccmq qqqq
- // Jcc limm 0010 0RRR 1110 0000 0RRR 1111 100Q QQQQ [LIUMM]
- if (!got_limm)
- {
- GET_LIMM_32;
- size = 8;
- }
-
- c = limm;
-
- }
- else
- {
- // opcode iiii i--- ppII IIII F--- cccc ccmq qqqq
- // Jcc [c] 0010 0RRR 1110 0000 0RRR CCCC CC0Q QQQQ
- // no conditional links to ILINK1, ILINK2?
-
- c = m_regs[creg];
- }
-
- if (!check_condition(condition))
- return m_pc + (size>>0);
-
- if (!F)
- {
- // if F isn't set then the destination can't be ILINK1 or ILINK2
-
- if ((creg == REG_ILINK1) || (creg == REG_ILINK2))
- {
- arcompact_fatal ("fatal arcompact_handle04_20_p11_m0 J %08x (F not set but ILINK1 or ILINK2 used as dst)", op);
- }
- else
- {
- uint32_t realaddress = c;
- return realaddress;
- }
- }
-
- if (F)
- {
- // if F is set then the destination MUST be ILINK1 or ILINK2
-
- if ((creg == REG_ILINK1) || (creg == REG_ILINK2))
- {
- arcompact_log("unimplemented arcompact_handle04_20_p11_m0 J %08x (F set)", op);
- }
- else
- {
- arcompact_fatal ("fatal arcompact_handle04_20_p11_m0 J %08x (F set but not ILINK1 or ILINK2 used as dst)", op);
-
- }
- }
-
-
- return m_pc + (size>>0);
-}
-
-ARCOMPACT_RETTYPE arcompact_device::arcompact_handle04_20_p11_m1(OPS_32)
-{
- // opcode iiii i--- ppII IIII F--- uuuu uumq qqqq
- // Jcc u6 0010 0RRR 1110 0000 0RRR uuuu uu1Q QQQQ
- int size = 4;
- arcompact_log("unimplemented arcompact_handle04_20_p11_m1 J %08x (u6)", op);
- return m_pc + (size>>0);
-}
-
-
-ARCOMPACT_RETTYPE arcompact_device::arcompact_handle04_21_p00(OPS_32)
-{
- int size = 4;
- uint32_t limm = 0;
- int got_limm = 0;
-
- COMMON32_GET_creg
- COMMON32_GET_F
-
- if (creg == LIMM_REG)
- {
- if (!got_limm)
- {
- GET_LIMM_32;
- size = 8;
- }
-
- handle_jump_to_addr(1,0,limm, m_pc + (size>>0));
- }
- else
- {
- return handle_jump_to_register(1,0,creg, m_pc + (size>>0), F); // delay, no link
- }
-
- return m_pc + (size>>0);
-}
-
-ARCOMPACT_RETTYPE arcompact_device::arcompact_handle04_21_p01(OPS_32)
-{
- int size = 4;
- arcompact_log("unimplemented J.D (u6 type) %08x", op);
- return m_pc + (size>>0);
-}
-
-ARCOMPACT_RETTYPE arcompact_device::arcompact_handle04_21_p10(OPS_32)
-{
- int size = 4;
- arcompact_log("unimplemented J.D (s12 type) %08x", op);
- return m_pc + (size>>0);
-}
-
-
-ARCOMPACT_RETTYPE arcompact_device::arcompact_handle04_21_p11_m0(OPS_32) // Jcc.D (no link, delay)
-{
- int size = 4;
- uint32_t limm;
- int got_limm = 0;
-
- COMMON32_GET_creg
- COMMON32_GET_CONDITION;
- COMMON32_GET_F
-
- //uint32_t c = 0;
-
- if (creg == LIMM_REG)
- {
- if (!got_limm)
- {
- GET_LIMM_32;
- size = 8;
- }
-
- // c = limm;
-
- }
- else
- {
- // opcode iiii i--- ppII IIII F--- cccc ccmq qqqq
- // Jcc [c] 0010 0RRR 1110 0000 0RRR CCCC CC0Q QQQQ
- // no conditional links to ILINK1, ILINK2?
-
- // c = m_regs[creg];
- }
-
- if (!check_condition(condition))
- return m_pc + (size>>0);
-
- if (!F)
- {
- // if F isn't set then the destination can't be ILINK1 or ILINK2
-
- if ((creg == REG_ILINK1) || (creg == REG_ILINK2))
- {
- arcompact_log("unimplemented Jcc.D (p11_m0 type, illegal) %08x", op);
- }
- else
- {
- arcompact_log("unimplemented Jcc.D (p11_m0 type, unimplemented) %08x", op);
- }
- }
-
- if (F)
- {
- // if F is set then the destination MUST be ILINK1 or ILINK2
-
- if ((creg == REG_ILINK1) || (creg == REG_ILINK2))
- {
- arcompact_log("unimplemented Jcc.D.F (p11_m0 type, unimplemented) %08x", op);
- }
- else
- {
- arcompact_log("unimplemented Jcc.D.F (p11_m0 type, illegal) %08x", op);
- }
- }
-
-
- return m_pc + (size>>0);
-}
-
-ARCOMPACT_RETTYPE arcompact_device::arcompact_handle04_21_p11_m1(OPS_32)
-{
- int size = 4;
- arcompact_log("unimplemented arcompact_handle04_21_p11_m1 J.D %08x (u6)", op);
- return m_pc + (size>>0);
-}
-
-
-
-ARCOMPACT_RETTYPE arcompact_device::arcompact_handle04_22(OPS_32)
-{
- return arcompact_handle04_helper(PARAMS, arcompact_disassembler::opcodes_04[0x22], /*"JL"*/ 1,1);
-}
-
-ARCOMPACT_RETTYPE arcompact_device::arcompact_handle04_23(OPS_32)
-{
- return arcompact_handle04_helper(PARAMS, arcompact_disassembler::opcodes_04[0x23], /*"JL.D"*/ 1,1);
-}
-
-
-
-
-ARCOMPACT_RETTYPE arcompact_device::arcompact_handle04_28(OPS_32) // LPcc (loop setup)
-{
- int size = 4;
-// COMMON32_GET_breg; // breg is reserved
- COMMON32_GET_p;
-
- if (p == 0x00)
- {
- arcompact_fatal("<illegal LPcc, p = 0x00)");
- }
- else if (p == 0x01)
- {
- arcompact_fatal("<illegal LPcc, p = 0x01)");
- }
- else if (p == 0x02) // Loop unconditional
- { // 0010 0RRR 1010 1000 0RRR ssss ssSS SSSS
- COMMON32_GET_s12
- if (S & 0x800) S = -0x800 + (S&0x7ff);
-
- arcompact_fatal("Lp unconditional not supported %d", S);
- }
- else if (p == 0x03) // Loop conditional
- { // 0010 0RRR 1110 1000 0RRR uuuu uu1Q QQQQ
- COMMON32_GET_u6
- COMMON32_GET_CONDITION
- //arcompact_fatal("Lp conditional %s not supported %d", arcompact_disassembler::conditions[condition], u);
-
- // if the loop condition fails then just jump to after the end of the loop, don't set any registers
- if (!check_condition(condition))
- {
- uint32_t realoffset = PC_ALIGNED32 + (u * 2);
- return realoffset;
- }
- else
- {
- // otherwise set up the loop positions
- m_LP_START = m_pc + (size >> 0);
- m_LP_END = PC_ALIGNED32 + (u * 2);
- return m_pc + (size>>0);
- }
-
- }
-
- return m_pc + (size>>0);
-
-}
-
-
-ARCOMPACT_RETTYPE arcompact_device::arcompact_handle04_29(OPS_32)
-{
- // leapster bios uses formats for FLAG that are not defined, bug I guess work anyway (P modes 0 / 1)
- return arcompact_handle04_helper(PARAMS, arcompact_disassembler::opcodes_04[0x29], /*"FLAG"*/ 1,1);
-}
-
-
-ARCOMPACT_RETTYPE arcompact_device::arcompact_handle04_2f_helper(OPS_32, const char* optext)
-{
- int size;
-
- COMMON32_GET_p;
- //COMMON32_GET_breg;
-
- if (p == 0)
- {
- COMMON32_GET_creg
-
- if (creg == LIMM_REG)
- {
- //uint32_t limm;
- //GET_LIMM_32;
- size = 8;
- }
- else
- {
- }
- }
- else if (p == 1)
- {
- }
- else if (p == 2)
- {
- }
- else if (p == 3)
- {
- }
-
- arcompact_log("unimplemented %s %08x (type 04_2f)", optext, op);
- return m_pc + (size>>0);
-}
-
-
-
-ARCOMPACT_RETTYPE arcompact_device::arcompact_handle04_2f_00(OPS_32) { return arcompact_handle04_2f_helper(PARAMS, "ASL"); } // ASL
-ARCOMPACT_RETTYPE arcompact_device::arcompact_handle04_2f_01(OPS_32) { return arcompact_handle04_2f_helper(PARAMS, "ASR"); } // ASR
-
-ARCOMPACT_RETTYPE arcompact_device::arcompact_handle04_2f_04(OPS_32) { return arcompact_handle04_2f_helper(PARAMS, "RCC"); } // RCC
-ARCOMPACT_RETTYPE arcompact_device::arcompact_handle04_2f_05(OPS_32) { return arcompact_handle04_2f_helper(PARAMS, "SEXB"); } // SEXB
-ARCOMPACT_RETTYPE arcompact_device::arcompact_handle04_2f_06(OPS_32) { return arcompact_handle04_2f_helper(PARAMS, "SEXW"); } // SEXW
-
-
-ARCOMPACT_RETTYPE arcompact_device::arcompact_handle04_2f_09(OPS_32) { return arcompact_handle04_2f_helper(PARAMS, "ABS"); } // ABS
-ARCOMPACT_RETTYPE arcompact_device::arcompact_handle04_2f_0a(OPS_32) { return arcompact_handle04_2f_helper(PARAMS, "NOT"); } // NOT
-ARCOMPACT_RETTYPE arcompact_device::arcompact_handle04_2f_0b(OPS_32) { return arcompact_handle04_2f_helper(PARAMS, "RCL"); } // RLC
-ARCOMPACT_RETTYPE arcompact_device::arcompact_handle04_2f_0c(OPS_32) { return arcompact_handle04_2f_helper(PARAMS, "EX"); } // EX
-
-
-ARCOMPACT_RETTYPE arcompact_device::arcompact_handle04_2f_3f_01(OPS_32) { arcompact_log("SLEEP (%08x)", op); return m_pc + (4 >> 0);}
-ARCOMPACT_RETTYPE arcompact_device::arcompact_handle04_2f_3f_02(OPS_32) { arcompact_log("SWI / TRAP0 (%08x)", op); return m_pc + (4 >> 0);}
-ARCOMPACT_RETTYPE arcompact_device::arcompact_handle04_2f_3f_03(OPS_32) { arcompact_log("SYNC (%08x)", op); return m_pc + (4 >> 0);}
-ARCOMPACT_RETTYPE arcompact_device::arcompact_handle04_2f_3f_04(OPS_32) { arcompact_log("RTIE (%08x)", op); return m_pc + (4 >> 0);}
-ARCOMPACT_RETTYPE arcompact_device::arcompact_handle04_2f_3f_05(OPS_32) { arcompact_log("BRK (%08x)", op); return m_pc + (4 >> 0);}
-
-
-
-
-ARCOMPACT_RETTYPE arcompact_device::arcompact_handle04_3x_helper(OPS_32, int dsize, int extend)
-{
- int size;
- //uint32_t limm=0;
- int got_limm = 0;
-
-
- COMMON32_GET_breg;
- COMMON32_GET_creg
-
-
-
- if (breg == LIMM_REG)
- {
- //GET_LIMM_32;
- size = 8;
- got_limm = 1;
-
- }
- else
- {
- }
-
- if (creg == LIMM_REG)
- {
- if (!got_limm)
- {
- //GET_LIMM_32;
- size = 8;
- }
-
- }
- else
- {
- }
-
- arcompact_log("unimplemented LD %08x (type 04_3x)", op);
- return m_pc + (size>>0);
-}
-
-ARCOMPACT_RETTYPE arcompact_device::arcompact_handle04_30(OPS_32) { return arcompact_handle04_3x_helper(PARAMS,0,0); }
-// ZZ value of 0x0 with X of 1 is illegal
-ARCOMPACT_RETTYPE arcompact_device::arcompact_handle04_31(OPS_32) { return arcompact_handle04_3x_helper(PARAMS,0,1); }
-ARCOMPACT_RETTYPE arcompact_device::arcompact_handle04_32(OPS_32) { return arcompact_handle04_3x_helper(PARAMS,1,0); }
-ARCOMPACT_RETTYPE arcompact_device::arcompact_handle04_33(OPS_32) { return arcompact_handle04_3x_helper(PARAMS,1,1); }
-ARCOMPACT_RETTYPE arcompact_device::arcompact_handle04_34(OPS_32) { return arcompact_handle04_3x_helper(PARAMS,2,0); }
-ARCOMPACT_RETTYPE arcompact_device::arcompact_handle04_35(OPS_32) { return arcompact_handle04_3x_helper(PARAMS,2,1); }
-// ZZ value of 0x3 is illegal
-ARCOMPACT_RETTYPE arcompact_device::arcompact_handle04_36(OPS_32) { return arcompact_handle04_3x_helper(PARAMS,3,0); }
-ARCOMPACT_RETTYPE arcompact_device::arcompact_handle04_37(OPS_32) { return arcompact_handle04_3x_helper(PARAMS,3,1); }
-
-
-
-
-
-
-
-
-ARCOMPACT_RETTYPE arcompact_device::arcompact_handle05_02(OPS_32) { return arcompact_handle04_helper(PARAMS, "ASR", 0,0); }
-ARCOMPACT_RETTYPE arcompact_device::arcompact_handle05_03(OPS_32) { return arcompact_handle04_helper(PARAMS, "ROR", 0,0); }
-ARCOMPACT_RETTYPE arcompact_device::arcompact_handle05_04(OPS_32) { return arcompact_handle04_helper(PARAMS, "MUL64", 2,0); } // special
-ARCOMPACT_RETTYPE arcompact_device::arcompact_handle05_05(OPS_32) { return arcompact_handle04_helper(PARAMS, "MULU64", 2,0);} // special
-ARCOMPACT_RETTYPE arcompact_device::arcompact_handle05_06(OPS_32) { return arcompact_handle04_helper(PARAMS, "ADDS", 0,0); }
-ARCOMPACT_RETTYPE arcompact_device::arcompact_handle05_07(OPS_32) { return arcompact_handle04_helper(PARAMS, "SUBS", 0,0); }
-ARCOMPACT_RETTYPE arcompact_device::arcompact_handle05_08(OPS_32) { return arcompact_handle04_helper(PARAMS, "DIVAW", 0,0); }
-
-
-
-ARCOMPACT_RETTYPE arcompact_device::arcompact_handle05_0a(OPS_32) { return arcompact_handle04_helper(PARAMS, "ASLS", 0,0); }
-ARCOMPACT_RETTYPE arcompact_device::arcompact_handle05_0b(OPS_32) { return arcompact_handle04_helper(PARAMS, "ASRS", 0,0); }
-
-ARCOMPACT_RETTYPE arcompact_device::arcompact_handle05_28(OPS_32) { return arcompact_handle04_helper(PARAMS, "ADDSDW", 0,0); }
-ARCOMPACT_RETTYPE arcompact_device::arcompact_handle05_29(OPS_32) { return arcompact_handle04_helper(PARAMS, "SUBSDW", 0,0); }
-
-
-
-ARCOMPACT_RETTYPE arcompact_device::arcompact_handle05_2f_0x_helper(OPS_32, const char* optext)
-{
- int size;
-
- COMMON32_GET_p;
- //COMMON32_GET_breg;
-
- if (p == 0)
- {
- COMMON32_GET_creg
-
- if (creg == LIMM_REG)
- {
- //uint32_t limm;
- //GET_LIMM_32;
- size = 8;
-
- }
- else
- {
- }
- }
- else if (p == 1)
- {
- }
- else if (p == 2)
- {
- }
- else if (p == 3)
- {
- }
-
- arcompact_log("unimplemented %s %08x", optext, op);
- return m_pc + (size>>0);
-}
-
-
-ARCOMPACT_RETTYPE arcompact_device::arcompact_handle05_2f_00(OPS_32) { return arcompact_handle05_2f_0x_helper(PARAMS, "SWAP"); }
-ARCOMPACT_RETTYPE arcompact_device::arcompact_handle05_2f_01(OPS_32) { return arcompact_handle05_2f_0x_helper(PARAMS, "NORM"); }
-ARCOMPACT_RETTYPE arcompact_device::arcompact_handle05_2f_02(OPS_32) { return arcompact_handle05_2f_0x_helper(PARAMS, "SAT16"); }
-ARCOMPACT_RETTYPE arcompact_device::arcompact_handle05_2f_03(OPS_32) { return arcompact_handle05_2f_0x_helper(PARAMS, "RND16"); }
-ARCOMPACT_RETTYPE arcompact_device::arcompact_handle05_2f_04(OPS_32) { return arcompact_handle05_2f_0x_helper(PARAMS, "ABSSW"); }
-ARCOMPACT_RETTYPE arcompact_device::arcompact_handle05_2f_05(OPS_32) { return arcompact_handle05_2f_0x_helper(PARAMS, "ABSS"); }
-ARCOMPACT_RETTYPE arcompact_device::arcompact_handle05_2f_06(OPS_32) { return arcompact_handle05_2f_0x_helper(PARAMS, "NEGSW"); }
-ARCOMPACT_RETTYPE arcompact_device::arcompact_handle05_2f_07(OPS_32) { return arcompact_handle05_2f_0x_helper(PARAMS, "NEGS"); }
-ARCOMPACT_RETTYPE arcompact_device::arcompact_handle05_2f_08(OPS_32) { return arcompact_handle05_2f_0x_helper(PARAMS, "NORMW"); }
-
-
-ARCOMPACT_RETTYPE arcompact_device::arcompact_handle06(OPS_32)
-{
- arcompact_log("op a,b,c (06 ARC ext) (%08x)", op );
- return m_pc + (4 >> 0);
-}
-
-ARCOMPACT_RETTYPE arcompact_device::arcompact_handle07(OPS_32)
-{
- arcompact_log("op a,b,c (07 User ext) (%08x)", op );
- return m_pc + (4 >> 0);
-}
-
-ARCOMPACT_RETTYPE arcompact_device::arcompact_handle08(OPS_32)
-{
- arcompact_log("op a,b,c (08 User ext) (%08x)", op );
- return m_pc + (4 >> 0);
-}
-
-ARCOMPACT_RETTYPE arcompact_device::arcompact_handle09(OPS_32)
-{
- arcompact_log("op a,b,c (09 Market ext) (%08x)", op );
- return m_pc + (4 >> 0);
-}
-
-ARCOMPACT_RETTYPE arcompact_device::arcompact_handle0a(OPS_32)
-{
- arcompact_log("op a,b,c (0a Market ext) (%08x)", op );
- return m_pc + (4 >> 0);
-}
-
-ARCOMPACT_RETTYPE arcompact_device::arcompact_handle0b(OPS_32)
-{
- arcompact_log("op a,b,c (0b Market ext) (%08x)", op );
- return m_pc + (4 >> 0);
-}
-
-
-
-ARCOMPACT_RETTYPE arcompact_device::arcompact_handle0c_helper(OPS_16, const char* optext)
-{
- arcompact_log("unimplemented %s %04x (0x0c group)", optext, op);
- return m_pc + (2 >> 0);
-}
-
-
-ARCOMPACT_RETTYPE arcompact_device::arcompact_handle0c_00(OPS_16)
-{
- return arcompact_handle0c_helper(PARAMS, "LD_S");
-}
-
-ARCOMPACT_RETTYPE arcompact_device::arcompact_handle0c_01(OPS_16)
-{
- return arcompact_handle0c_helper(PARAMS, "LDB_S");
-}
-
-ARCOMPACT_RETTYPE arcompact_device::arcompact_handle0c_02(OPS_16)
-{
- return arcompact_handle0c_helper(PARAMS, "LDW_S");
-}
-
-ARCOMPACT_RETTYPE arcompact_device::arcompact_handle0c_03(OPS_16) // ADD_S a <- b + c
-{
- int areg, breg, creg;
-
- COMMON16_GET_areg;
- COMMON16_GET_breg;
- COMMON16_GET_creg;
-
- REG_16BIT_RANGE(areg);
- REG_16BIT_RANGE(breg);
- REG_16BIT_RANGE(creg);
-
- m_regs[areg] = m_regs[breg] + m_regs[creg];
-
- return m_pc + (2 >> 0);
-}
-
-
-ARCOMPACT_RETTYPE arcompact_device::arcompact_handle0d_helper(OPS_16, const char* optext)
-{
- arcompact_log("unimplemented %s %04x (0x0d group)", optext, op);
- return m_pc + (2 >> 0);
-}
-
-
-
-ARCOMPACT_RETTYPE arcompact_device::arcompact_handle0d_03(OPS_16)
-{
- return arcompact_handle0d_helper(PARAMS, "ASR_S");
-}
-
-
-
-ARCOMPACT_RETTYPE arcompact_device::arcompact_handle0e_0x_helper(OPS_16, const char* optext, int revop)
-{
- int h;// , breg;
- int size;
-
- GROUP_0e_GET_h;
-
- if (h == LIMM_REG)
- {
- //uint32_t limm;
- //GET_LIMM;
- size = 6;
- }
- else
- {
- }
-
- arcompact_log("unimplemented %s %04x (0x0e_0x group)", optext, op);
-
- return m_pc+ (size>>0);
-
-}
-
-ARCOMPACT_RETTYPE arcompact_device::arcompact_handle0e_00(OPS_16) // ADD_s b, b, h
-{
- int h,breg;
- int size = 2;
-
- GROUP_0e_GET_h;
- COMMON16_GET_breg;
- REG_16BIT_RANGE(breg);
-
- if (h == LIMM_REG)
- {
- uint32_t limm;
- GET_LIMM_16;
- size = 6;
-
- m_regs[breg] = m_regs[breg] + limm;
-
- }
- else
- {
- m_regs[breg] = m_regs[breg] + m_regs[h];
- }
-
- return m_pc+ (size>>0);
-}
-
-// 16-bit MOV with extended register range
-ARCOMPACT_RETTYPE arcompact_device::arcompact_handle0e_01(OPS_16) // MOV_S b <- h
-{
- int h,breg;
- int size = 2;
-
- GROUP_0e_GET_h;
- COMMON16_GET_breg;
- REG_16BIT_RANGE(breg);
-
- if (h == LIMM_REG)
- {
- // opcode iiii ibbb hhhI Ihhh
- // MOV_S b, limm 0111 0bbb 1100 1111 [LIMM] (h == LIMM)
-
- uint32_t limm;
- GET_LIMM_16;
- size = 6;
-
- m_regs[breg] = limm;
-
- }
- else
- {
- // opcode iiii ibbb hhhI Ihhh
- // MOV_S b,h 0111 0bbb hhh0 1HHH
- m_regs[breg] = m_regs[h];
- }
-
- return m_pc+ (size>>0);
-}
-
-ARCOMPACT_RETTYPE arcompact_device::arcompact_handle0e_02(OPS_16)
-{
- return arcompact_handle0e_0x_helper(PARAMS, "CMP_S", 0);
-}
-
-ARCOMPACT_RETTYPE arcompact_device::arcompact_handle0e_03(OPS_16) // MOV_S h <- b
-{
- int h,breg;
- int size = 2;
-
- GROUP_0e_GET_h;
- COMMON16_GET_breg;
- REG_16BIT_RANGE(breg);
-
- if (h == LIMM_REG) // no result..
- {
- }
-
- m_regs[h] = m_regs[breg];
-
- return m_pc+ (size>>0);
-}
-
-
-
-ARCOMPACT_RETTYPE arcompact_device::arcompact_handle0f_00_0x_helper(OPS_16, const char* optext)
-{
- arcompact_log("unimplemented %s %04x", optext, op);
- return m_pc + (2 >> 0);
-}
-
-
-
-ARCOMPACT_RETTYPE arcompact_device::arcompact_handle0f_00_00(OPS_16) { return arcompact_handle0f_00_0x_helper(PARAMS, "J_S"); }
-ARCOMPACT_RETTYPE arcompact_device::arcompact_handle0f_00_01(OPS_16) { return arcompact_handle0f_00_0x_helper(PARAMS, "J_S.D"); }
-
-ARCOMPACT_RETTYPE arcompact_device::arcompact_handle0f_00_02(OPS_16) // JL_S
-{
- int breg;
-
- COMMON16_GET_breg;
- REG_16BIT_RANGE(breg);
-
- m_regs[REG_BLINK] = m_pc + (2 >> 0);
-
- return m_regs[breg];
-}
-
-
-ARCOMPACT_RETTYPE arcompact_device::arcompact_handle0f_00_03(OPS_16) // JL_S.D
-{
- int breg;
-
- COMMON16_GET_breg;
- REG_16BIT_RANGE(breg);
-
- m_delayactive = 1;
- m_delayjump = m_regs[breg];
- m_delaylinks = 1;
-
- return m_pc + (2 >> 0);
-}
-
-ARCOMPACT_RETTYPE arcompact_device::arcompact_handle0f_00_06(OPS_16) { return arcompact_handle0f_00_0x_helper(PARAMS, "SUB_S.NE"); }
-
-
-
-
-// Zero parameters (ZOP)
-ARCOMPACT_RETTYPE arcompact_device::arcompact_handle0f_00_07_00(OPS_16) { /*arcompact_log("NOP_S");*/ return m_pc + (2 >> 0);}
-ARCOMPACT_RETTYPE arcompact_device::arcompact_handle0f_00_07_01(OPS_16) { arcompact_log("UNIMP_S"); return m_pc + (2 >> 0);} // Unimplemented Instruction, same as illegal, but recommended to fill blank space
-ARCOMPACT_RETTYPE arcompact_device::arcompact_handle0f_00_07_04(OPS_16) { arcompact_log("JEQ_S [blink]"); return m_pc + (2 >> 0);}
-ARCOMPACT_RETTYPE arcompact_device::arcompact_handle0f_00_07_05(OPS_16) { arcompact_log("JNE_S [blink]"); return m_pc + (2 >> 0);}
-
-ARCOMPACT_RETTYPE arcompact_device::arcompact_handle0f_00_07_06(OPS_16) // J_S [blink]
-{
- return m_regs[REG_BLINK];
-}
-
-
-ARCOMPACT_RETTYPE arcompact_device::arcompact_handle0f_00_07_07(OPS_16) // J_S.D [blink]
-{
- m_delayactive = 1;
- m_delayjump = m_regs[REG_BLINK];
- m_delaylinks = 0;
-
- return m_pc + (2 >> 0);
-}
-
-
-
-
-
-ARCOMPACT_RETTYPE arcompact_device::arcompact_handle0f_0x_helper(OPS_16, const char* optext, int nodst)
-{
- arcompact_log("unimplemented %s %04x (0xf_0x group)", optext, op);
- return m_pc + (2 >> 0);
-}
-
-
-
-
-
-
-ARCOMPACT_RETTYPE arcompact_device::arcompact_handle0f_06(OPS_16) { return arcompact_handle0f_0x_helper(PARAMS, "BIC_S",0); }
-
-ARCOMPACT_RETTYPE arcompact_device::arcompact_handle0f_0b(OPS_16) { return arcompact_handle0f_0x_helper(PARAMS, "TST_S",1); }
-ARCOMPACT_RETTYPE arcompact_device::arcompact_handle0f_0c(OPS_16) { return arcompact_handle0f_0x_helper(PARAMS, "MUL64_S",2); } // actual destination is special multiply registers
-ARCOMPACT_RETTYPE arcompact_device::arcompact_handle0f_0d(OPS_16) { return arcompact_handle0f_0x_helper(PARAMS, "SEXB_S",0); }
-ARCOMPACT_RETTYPE arcompact_device::arcompact_handle0f_0e(OPS_16) { return arcompact_handle0f_0x_helper(PARAMS, "SEXW_S",0); }
-
-
-
-
-ARCOMPACT_RETTYPE arcompact_device::arcompact_handle0f_11(OPS_16) { return arcompact_handle0f_0x_helper(PARAMS, "ABS_S",0); }
-ARCOMPACT_RETTYPE arcompact_device::arcompact_handle0f_12(OPS_16) { return arcompact_handle0f_0x_helper(PARAMS, "NOT_S",0); }
-
-
-ARCOMPACT_RETTYPE arcompact_device::arcompact_handle0f_18(OPS_16) { return arcompact_handle0f_0x_helper(PARAMS, "ASL_S",0); }